dobrograd-13-06-2022/garrysmod/addons/gmod-sweps/lua/weapons/dbg_hands/init.lua
Jonny_Bro (Nikita) e4d5311906 first commit
2023-11-16 15:01:19 +05:00

424 lines
11 KiB
Lua

AddCSLuaFile('shared.lua')
AddCSLuaFile('cl_init.lua')
include('shared.lua')
local SwingSound = Sound('WeaponFrag.Throw')
local HitSound = Sound('Flesh.ImpactHard')
SWEP.HitDistance = 48
SWEP.KnockDistSqr = 65 * 65
SWEP.isDragging = false
SWEP.pickedEnt = nil
SWEP.pickedEntOffset = Vector(0,0,0)
-------------------------------------------------
-- MAIN
-------------------------------------------------
local function isCarOwner(ent, ply)
local owner = ent:CPPIGetOwner()
return IsValid(owner) and
(owner == ply or owner.Buddies and owner.Buddies[ply] and table.HasValue(owner.Buddies[ply], true)) and
not ply:InVehicle() -- to prevent mouse clicks lock/unlock the car
end
function SWEP:lookingAtLockable(ply, ent)
local eyepos = ply:EyePos()
if not IsValid(ent) then return false end
if ent:IsDoor() and not ent:IsBlocked() and eyepos:DistToSqr(ent:GetPos()) < self.KnockDistSqr then
return true
end
if ent.isFadingDoor and ent:GetPos():DistToSqr(eyepos) < self.KnockDistSqr then return true end
if ent.IsSimfphyscar then return true end
end
function SWEP:lockUnlockAnimation(ply, snd)
ply:EmitSound('doors/door_latch1.wav')
ply:DoAnimation(ACT_GMOD_GESTURE_ITEM_PLACE)
end
function SWEP:doKnock(ply, sound)
ply:EmitSound(sound, 100, math.random(90, 110))
ply:DoAnimation(ACT_HL2MP_GESTURE_RANGE_ATTACK_FIST)
end
SWEP.UseDel = CurTime()
function SWEP:DoTrace()
local trace = {}
trace.start = self.Owner:GetShootPos()
trace.endpos = trace.start + (self.Owner:GetAimVector() * 10000)
trace.filter = { self.Owner, self.Weapon }
local tr = util.TraceLine(trace)
return tr
end
function SWEP:DealDamage()
if not self.anim then return end
local owner = self:GetOwner()
owner:LagCompensation(true)
local aim = owner:EyeAngles():Forward()
local tr = util.TraceLine({
start = owner:GetShootPos(),
endpos = owner:GetShootPos() + aim * self.HitDistance,
filter = owner,
mask = MASK_SHOT_HULL
})
if not IsValid(tr.Entity) then
tr = util.TraceHull({
start = owner:GetShootPos(),
endpos = owner:GetShootPos() + aim * self.HitDistance,
filter = owner,
mins = Vector(-10, -10, -8),
maxs = Vector(10, 10, 8),
mask = MASK_SHOT_HULL
})
end
if tr.Hit then
owner:EmitSound(HitSound)
end
if (SERVER and IsValid(tr.Entity) and (tr.Entity:IsNPC() or tr.Entity:IsPlayer() or tr.Entity:Health() > 0)) then
local dmginfo = DamageInfo()
local attacker = owner
if not IsValid(attacker) then attacker = self end
dmginfo:SetAttacker(attacker)
dmginfo:SetInflictor(self)
local dmgAmount = math.random(8, 12)
if tr.Entity:IsPlayer() then dmgAmount = math.Clamp(tr.Entity:Health() - (attacker:HasBuff('Meth') and 0 or 20), 0, dmgAmount) end
dmginfo:SetDamage(dmgAmount)
dmginfo:SetDamageType(DMG_CLUB)
if (self.anim == 'fists_left') then
dmginfo:SetDamageForce(owner:GetRight() * 4912 + owner:GetForward() * 9998)
elseif (self.anim == 'fists_right') then
dmginfo:SetDamageForce(owner:GetRight() * -4912 + owner:GetForward() * 9989)
end
tr.Entity:TakeDamageInfo(dmginfo)
-- if tr.Entity:GetClass() == 'func_breakable_surf' then
-- tr.Entity:Fire('Shatter', Vector(0,0,0))
-- owner:TakeDamage(math.random(10, 15), Entity(0), tr.Entity)
-- end
end
if SERVER and IsValid(tr.Entity) then
local phys = tr.Entity:GetPhysicsObject()
if (IsValid(phys)) then
phys:ApplyForceOffset(owner:GetAimVector() * 80 * phys:GetMass(), tr.HitPos)
end
local ent = tr.Entity
local carOwner = ent:CPPIGetOwner()
if IsValid(carOwner) and ent.IsSimfphyscar and carOwner ~= owner
and not (carOwner.Buddies and carOwner.Buddies[owner] and table.HasValue(carOwner.Buddies[owner], true))
and CurTime() - (owner.karmaLast.cardamage or -180) > 180 then
owner:AddKarma(-1, L.cardamage)
print('[KARMA] ' .. tostring(owner) .. ' -1 karma for car fists damage')
owner.karmaLast.cardamage = CurTime()
end
end
owner:LagCompensation(false)
end
function SWEP:PrimaryAttack()
local owner = self:GetOwner()
if owner:IsGhost() or owner:IsHandcuffed() then return end
if self.isFists and self:GetHoldType() == 'fist' then
local can, why = hook.Run('dbg-hands.canPunch', owner, owner:GetEyeTrace())
if can == false then
if why then owner:Notify('warning', why) end
return
end
owner:SetAnimation(PLAYER_ATTACK1)
self.anim = self.punchRight and 'fists_right' or 'fists_left'
owner:EmitSound(SwingSound)
self:SetNextMeleeAttack(CurTime() + 0.2)
self:SetNextPrimaryFire(CurTime() + 0.9)
self:SetNextSecondaryFire(CurTime() + 0.9)
self.punchRight = not self.punchRight
else
local ent = owner:GetEyeTrace().Entity
if not self:lookingAtLockable(owner, ent) or owner:GetNetVar('Ghost') then return end
self:SetNextPrimaryFire(CurTime() + 0.3)
if ent:CanBeLockedBy(owner) and CurTime() > (ent.nextLock or 0) then
owner:DoAnimation(ACT_GMOD_GESTURE_ITEM_PLACE)
owner:DelayedAction('door_lock', 'Закрытие замка', {
time = 1.5,
check = function() return octolib.use.check(owner, ent) end,
succ = function()
ent:EmitSound('doors/door_latch1.wav')
ent:DoLock()
end,
})
elseif ent.IsSimfphyscar then
if isCarOwner(ent, owner) and CurTime() > (ent.nextLock or 0) then
ent:Lock()
end
else
self:doKnock(owner, 'physics/wood/wood_crate_impact_hard2.wav')
end
end
end
function SWEP:SecondaryAttack()
local owner = self.Owner
if owner:IsGhost() or owner:IsHandcuffed() then return end
local ent = owner:GetEyeTrace().Entity
if not self:lookingAtLockable(owner, ent) then return end
self:SetNextSecondaryFire(CurTime() + 0.3)
if ent:CanBeUnlockedBy(owner) then
ent:DoUnlock()
ent:EmitSound('doors/door_latch1.wav')
owner:DoAnimation(ACT_GMOD_GESTURE_ITEM_PLACE)
elseif ent.IsSimfphyscar then
if isCarOwner(ent, owner) then
ent:UnLock()
end
else
self:doKnock(owner, 'physics/wood/wood_crate_impact_hard3.wav')
end
end
function SWEP:Reload()
-- do nothing
end
function SWEP:PrimaryAttackPressed()
if self.isFists then return end
if self.isDragging then
self:StopDragging()
return
end
local owner = self:GetOwner()
local veh = owner:GetVehicle()
if IsValid(veh) and IsValid(veh:GetParent()) then return end
local tr = util.TraceLine({
start = owner:EyePos(),
endpos = owner:EyePos() + owner:GetAimVector() * 100,
filter = owner
})
local ent = tr.Entity
if not IsValid(ent) then
self:SetHoldType('pistol')
self.isPointing = true
return
end
local can, why = hook.Run('dbg-hands.canDrag', owner, ent, tr)
if can == false then
if why then owner:Notify('warning', why) end
return
end
local class = ent:GetClass()
local ph = class and not self.doNotDrag[class] and ent:GetPhysicsObjectNum(tr.PhysicsBone)
local should = not ent:IsPlayer() or (not ent:IsGhost() and ent:Crouching() and ent:KeyDown(IN_ATTACK))
if should and IsValid(ph) and not ent:IsDoor() then
self.pickedEnt = ent
if ent.OnHandsPickup then
ent:OnHandsPickup(owner, self)
end
self.pickedEntBone = tr.PhysicsBone
self.pickedEntOffset = ph:WorldToLocal(tr.HitPos)
self.isDragging = true
self.pickedEnt.lastCarrier = owner -- to register killer
self:SetHoldType(IsValid(veh) and 'pistol' or 'magic')
if class == 'prop_ragdoll' then
local name = owner:Name()
if owner:isCP() then name = name .. L.analyzer_cop end
ent.criminals = ent.criminals or {}
if not table.HasValue(ent.criminals, name) then table.insert(ent.criminals, name) end
end
else
self:SetHoldType('pistol')
self.isPointing = true
end
end
function SWEP:PrimaryAttackReleased()
if not self.isPointing then return end
self:SetHoldType('normal')
self.isPointing = nil
end
function SWEP:SecondaryAttackPressed()
self.isFists = true
self.isPointing = nil
self:SetHoldType('fist')
octolib.stopAnimations(self:GetOwner())
end
function SWEP:SecondaryAttackReleased()
self.isFists = nil
self:SetHoldType('normal')
self.anim = nil
end
function SWEP:StopDragging()
if self.isDragging then
self.isDragging = false
self.pickedEnt = nil
self:SetHoldType('normal')
netstream.Start(self:GetOwner(), 'dbg_hands.StopDragging')
end
end
function SWEP:Think()
local owner = self:GetOwner()
if owner:IsGhost() then return end
if self.isDragging then
local ent = self.pickedEnt
if not IsValid(ent) then
self:StopDragging()
return
end
local should = owner:KeyDown(IN_ATTACK) and not owner:KeyDown(IN_ATTACK2) and owner:GetGroundEntity() ~= ent and not ent.APG_Picked
if ent:IsPlayer() and not (ent:KeyDown(IN_ATTACK) and ent:Crouching() and not ent:IsGhost()) then should = false end
if ent.IsSimfphyscar and ent:EngineActive() and ent:GetThrottle() > 0.5 then should = false end
if not should then return self:StopDragging() end
local ph = ent:GetPhysicsObjectNum(self.pickedEntBone)
local ph2 = ent:GetPhysicsObject()
local pos = owner:EyePos() + owner:GetAimVector()*80
local pos2 = ph:LocalToWorld(self.pickedEntOffset)
if (pos - pos2):LengthSqr() > 10000 then
self:StopDragging()
return
end
local force = math.min(100, math.pow(ph2:GetMass(), 0.7) * 4)
if ent:GetPhysicsObjectCount() > 1 then force = force * 1.5 end
local vel = (pos - pos2) * force
if vel.z > 0 and ph:GetVelocity().z < 0 then vel.z = vel.z * 2.5 end
ph:ApplyForceOffset(vel, pos2)
ph:ApplyForceCenter(-ph:GetVelocity() * 0.3)
ph:AddAngleVelocity(-ph:GetAngleVelocity() * 0.3)
vel.z = vel.z * 0.4
owner:SetVelocity(-vel * 0.02)
elseif self.isFists then
local meleetime = self:GetNextMeleeAttack()
if meleetime > 0 and CurTime() > meleetime and owner:KeyDown(IN_ATTACK2) then
if not owner:InVehicle() then
self:DealDamage()
end
self:SetNextMeleeAttack(0)
end
end
self:NextThink(CurTime() + 0.03)
return true
end
-------------------------------------------------
-- JOB-SPECIFIC
-------------------------------------------------
util.AddNetworkString 'dbg-revive'
net.Receive('dbg-revive', function(len, ply)
local target = net.ReadEntity()
if not IsValid(target) or not target:IsPlayer() or not target:IsGhost()
or ply:IsGhost() or ply:Team() ~= TEAM_PRIEST or target:GetPos():DistToSqr(ply:GetPos()) > 6000 then
return
end
local ghostBuffs = target:GetDBVar('ghostBuffs', 0)
if ghostBuffs >= 10 then
ply:Notify('error', 'Священник может помочь грешникам, но всему есть предел!')
return
end
target:SetDBVar('ghostBuffs', ghostBuffs + 1)
target:SetNetVar('_SpawnTime', math.max((math.min(CurTime() + 5, target:GetNetVar('_SpawnTime', 0))), target:GetNetVar('_SpawnTime', 0) - 30))
target:EmitSound('dbg/revive.ogg', 70, 100, 0.8)
local effectdata = EffectData()
effectdata:SetOrigin(target:GetPos() + Vector(0,0,45))
effectdata:SetMagnitude(2.5)
effectdata:SetScale(2)
effectdata:SetRadius(3)
util.Effect('GlassImpact', effectdata, true, true)
end)
-------------------------------------------------
-- HOOKS
-------------------------------------------------
function SWEP:CanUseAnimation()
if self:GetHoldType() ~= 'normal' then
return false
end
end
hook.Add('AllowPlayerPickup', 'dbg_hands', function()
return false
end)