zombiesurvival-evolved/gamemodes/zombiesurvival/entities/weapons/weapon_zs_fastzombie.lua

597 lines
14 KiB
Lua
Raw Normal View History

2014-10-02 08:49:54 +08:00
AddCSLuaFile()
DEFINE_BASECLASS("weapon_zs_zombie")
SWEP.PrintName = "Fast Zombie"
2014-10-02 08:49:54 +08:00
SWEP.ViewModel = Model("models/weapons/v_fza.mdl")
SWEP.WorldModel = ""
2014-10-02 08:49:54 +08:00
if CLIENT then
SWEP.ViewModelFOV = 70
end
SWEP.MeleeDelay = 0
SWEP.MeleeReach = 42
SWEP.MeleeDamage = 7 --8
2014-10-02 08:49:54 +08:00
SWEP.MeleeForceScale = 0.1
SWEP.MeleeSize = 4.5 --1.5
2014-10-02 08:49:54 +08:00
SWEP.MeleeDamageType = DMG_SLASH
SWEP.Primary.Delay = 0.32
SWEP.SlowMeleeDelay = 0.8
SWEP.SlowMeleeDamage = 18
SWEP.PounceDamage = 20
SWEP.PounceDamageVsPlayerMul = 0.2
2014-10-02 08:49:54 +08:00
SWEP.PounceDamageType = DMG_IMPACT
2014-11-16 18:23:27 +08:00
SWEP.PounceReach = 26
SWEP.PounceSize = 12
2014-10-02 08:49:54 +08:00
SWEP.PounceStartDelay = 0.5
SWEP.PounceDelay = 1.25
SWEP.PounceVelocity = 700
SWEP.RoarTime = 1.6
SWEP.Secondary.Automatic = false
SWEP.NextClimbSound = 0
SWEP.NextAllowPounce = 0
function SWEP:Think()
BaseClass.Think(self)
2014-10-02 08:49:54 +08:00
local curtime = CurTime()
local owner = self:GetOwner()
2014-10-02 08:49:54 +08:00
if self.NextAllowJump and self.NextAllowJump <= curtime then
self.NextAllowJump = nil
owner:ResetJumpPower()
end
if self:GetClimbing() then
if self:GetClimbSurface() and owner:KeyDown(IN_ATTACK2) then
if curtime >= self.NextClimbSound and IsFirstTimePredicted() then
local speed = owner:GetVelocity():LengthSqr()
if speed >= 2500 then
if speed >= 10000 then
2014-10-02 08:49:54 +08:00
self.NextClimbSound = curtime + 0.25
else
self.NextClimbSound = curtime + 0.8
end
self:PlayClimbSound()
2014-10-02 08:49:54 +08:00
end
end
else
self:StopClimbing()
end
end
if self:IsSlowSwinging() then
if curtime >= self:GetSlowSwingEnd() then
self:SetSlowSwingEnd(0)
if IsFirstTimePredicted() then
self.MeleeAnimationMul = 1 / owner:GetMeleeSpeedMul()
self:SendAttackAnim()
local hit = false
local traces = owner:CompensatedZombieMeleeTrace(self.MeleeReach, self.MeleeSize)
local prehit = self.PreHit
if prehit then
local ins = true
for _, tr in pairs(traces) do
if tr.Entity == prehit.Entity then
ins = false
break
end
end
if ins then
local eyepos = owner:EyePos()
if prehit.Entity:IsValid() and prehit.Entity:NearestPoint(eyepos):DistToSqr(eyepos) <= self.MeleeReach * self.MeleeReach then
table.insert(traces, prehit)
end
end
self.PreHit = nil
end
local damage = self:GetSlowSwingDamage(self:GetTracesNumPlayers(traces))
for _, trace in ipairs(traces) do
if not trace.Hit then continue end
hit = true
if trace.HitWorld then
self:MeleeHitWorld(trace)
else
local ent = trace.Entity
if ent and ent:IsValid() then
self:MeleeHit(ent, trace, damage)
if ent:IsPlayer() then
self:MeleeHitPlayer(ent, trace, damage)
end
end
end
end
if hit then
self:PlayHitSound()
else
self:PlayMissSound()
end
end
end
elseif self:GetSwinging() then
2014-10-02 08:49:54 +08:00
if not owner:KeyDown(IN_ATTACK) and self.SwingStop and self.SwingStop <= curtime then
self:SetSwinging(false)
self.SwingStop = nil
self.RoarCheck = curtime + 0.1
self:StopSwingingSound()
end
elseif self.RoarCheck then
if self.RoarCheck <= curtime then
self.RoarCheck = nil
if owner:GetVelocity():Length2DSqr() <= 1 and owner:IsOnGround() then
2014-10-02 08:49:54 +08:00
self:SetRoarEndTime(curtime + self.RoarTime)
if IsFirstTimePredicted() then
self:PlaySwingEndSound()
2014-10-02 08:49:54 +08:00
end
end
end
elseif self:GetPouncing() then
if owner:IsOnGround() or owner:WaterLevel() >= 2 then
self:StopPounce()
else
local dir = owner:GetAimVector()
dir.z = math.Clamp(dir.z, -0.5, 0.9)
dir:Normalize()
local traces = owner:CompensatedZombieMeleeTrace(self.PounceReach, self.PounceSize, owner:WorldSpaceCenter(), dir)
2014-10-02 08:49:54 +08:00
local damage = self:GetDamage(self:GetTracesNumPlayers(traces), self.PounceDamage)
local hit = false
2014-10-02 08:49:54 +08:00
for _, trace in ipairs(traces) do
if not trace.Hit then continue end
if trace.HitWorld then
if trace.HitNormal.z < 0.8 then
hit = true
self:MeleeHitWorld(trace)
end
2014-10-02 08:49:54 +08:00
else
local ent = trace.Entity
if ent and ent:IsValid() then
hit = true
self:MeleeHit(ent, trace, damage * (ent:IsPlayer() and self.PounceDamageVsPlayerMul or ent.PounceWeakness or 1), ent:IsPlayer() and 1 or 10)
2014-10-02 08:49:54 +08:00
end
end
end
if hit then
if IsFirstTimePredicted() then
self:PlayPounceHitSound()
end
2014-10-02 08:49:54 +08:00
self:StopPounce()
end
end
elseif self:GetPounceTime() > 0 and curtime >= self:GetPounceTime() then
self:StartPounce()
end
self:NextThink(curtime)
return true
end
function SWEP:PlayClimbSound()
self:EmitSound("player/footsteps/metalgrate"..math.random(4)..".wav")
end
function SWEP:PlayPounceHitSound()
self:EmitSound("physics/flesh/flesh_strider_impact_bullet1.wav")
self:EmitSound("npc/fast_zombie/wake1.wav", nil, nil, nil, CHAN_AUTO)
end
function SWEP:PlaySwingEndSound()
self:EmitSound("NPC_FastZombie.Frenzy")
end
function SWEP:MeleeHitPlayer(ent, trace, damage)
ent:MeleeViewPunch(damage)
local nearest = ent:NearestPoint(trace.StartPos)
util.Blood(nearest, math.Rand(damage * 0.5, damage * 0.75), (nearest - trace.StartPos):GetNormalized(), math.Rand(damage * 5, damage * 10), true)
end
function SWEP:GetSlowSwingDamage(numplayers, basedamage)
basedamage = basedamage or self.SlowMeleeDamage
if numplayers then
return basedamage * math.Clamp(1.2 - numplayers * 0.2, 0.5, 1)
end
return basedamage
end
function SWEP:Move(mv)
if self:IsPouncing() or self:GetPounceTime() > 0 then
mv:SetMaxSpeed(0)
mv:SetMaxClientSpeed(0)
elseif self:GetClimbing() then
mv:SetMaxSpeed(0)
mv:SetMaxClientSpeed(0)
local owner = self:GetOwner()
local tr = self:GetClimbSurface()
local angs = owner:SyncAngles()
local dir = tr and tr.Hit and (tr.HitNormal.z <= -0.5 and (angs:Forward() * -1) or math.abs(tr.HitNormal.z) < 0.75 and tr.HitNormal:Angle():Up()) or Vector(0, 0, 1)
local vel = Vector(0, 0, 4)
if owner:KeyDown(IN_FORWARD) then
owner:SetGroundEntity(nil)
vel = vel + dir * 250 --160
end
if owner:KeyDown(IN_BACK) then
vel = vel + dir * -250 ---160
end
if vel.z == 4 then
if owner:KeyDown(IN_MOVERIGHT) then
vel = vel + angs:Right() * 100 --60
end
if owner:KeyDown(IN_MOVELEFT) then
vel = vel + angs:Right() * -100 ---60
end
end
mv:SetVelocity(vel)
return true
elseif self:GetSwinging() then
mv:SetMaxSpeed(mv:GetMaxSpeed() * 0.6666)
mv:SetMaxClientSpeed(mv:GetMaxClientSpeed() * 0.6666)
elseif self:IsSlowSwinging() then
mv:SetMaxSpeed(mv:GetMaxSpeed() * 0.85)
mv:SetMaxClientSpeed(mv:GetMaxClientSpeed() * 0.85)
end
end
2014-10-02 08:49:54 +08:00
function SWEP:MeleeHitEntity(ent, trace, damage, forcescale)
BaseClass.MeleeHitEntity(self, ent, trace, damage, forcescale ~= nil and forcescale * 0.25)
2014-10-02 08:49:54 +08:00
end
local climblerp = 0
function SWEP:GetViewModelPosition(pos, ang)
climblerp = math.Approach(climblerp, self:IsClimbing() and not self:IsSwinging() and 1 or 0, FrameTime() * ((climblerp + 1) ^ 3))
ang:RotateAroundAxis(ang:Right(), 64 * climblerp)
if climblerp > 0 then
pos = pos + -8 * climblerp * ang:Up() + -12 * climblerp * ang:Forward()
end
return pos, ang
end
function SWEP:Swung()
self.SwingStop = CurTime() + 0.5
if not self:GetSwinging() then
self:SetSwinging(true)
self:StartSwingingSound()
end
BaseClass.Swung(self)
2014-10-02 08:49:54 +08:00
end
function SWEP:PrimaryAttack()
if self:IsSlowSwinging() or self:IsPouncing() or self:GetPounceTime() > 0 then return end
local owner = self:GetOwner()
if self:IsClimbing() or owner:WaterLevel() >= 2 or owner:GetVelocity():LengthSqr() < 64 then
BaseClass.PrimaryAttack(self)
elseif CurTime() >= self:GetNextPrimaryFire() then
local armdelay = owner:GetMeleeSpeedMul()
self:SetNextPrimaryFire(CurTime() + (self.SlowMeleeDelay + 0.25) * armdelay)
self:SetNextSecondaryFire(self:GetNextPrimaryFire() + 0.5)
self:SetSlowSwingEnd(CurTime() + self.SlowMeleeDelay * armdelay)
owner:DoAttackEvent()
if IsFirstTimePredicted() then
self:PlaySlowSwingSound()
end
self:StopSwingingSound()
self:SetSwinging(false)
local trace = self:GetOwner():CompensatedMeleeTrace(self.MeleeReach, self.MeleeSize)
if trace.HitNonWorld then
trace.IsPreHit = true
self.PreHit = trace
end
2014-10-02 08:49:54 +08:00
self.IdleAnimation = CurTime() + self:SequenceDuration() * armdelay
end
end
function SWEP:PlaySlowSwingSound()
self:EmitSound("npc/fast_zombie/leap1.wav")
2014-10-02 08:49:54 +08:00
end
local climbtrace = {mask = MASK_SOLID_BRUSHONLY, mins = Vector(-5, -5, -5), maxs = Vector(5, 5, 5)}
2014-10-02 08:49:54 +08:00
function SWEP:GetClimbSurface()
local owner = self:GetOwner()
local fwd = owner:SyncAngles():Forward()
local up = owner:GetUp()
local pos = owner:GetPos()
local height = owner:OBBMaxs().z
local tr
local ha
for i=5, height, 5 do
if not tr or not tr.Hit then
climbtrace.start = pos + up * i
climbtrace.endpos = climbtrace.start + fwd * 36
tr = util.TraceHull(climbtrace)
ha = i
if tr.Hit and not tr.HitSky then break end
end
end
2014-10-02 08:49:54 +08:00
if tr.Hit and not tr.HitSky then
climbtrace.start = pos + up * ha --tr.HitPos + tr.HitNormal
climbtrace.endpos = climbtrace.start + owner:SyncAngles():Up() * (height - ha)
local tr2 = util.TraceHull(climbtrace)
if tr2.Hit and not tr2.HitSky then
return tr2
end
2014-10-02 08:49:54 +08:00
return tr
end
end
function SWEP:SecondaryAttack()
if self:IsPouncing() or self:IsClimbing() or self:GetPounceTime() > 0 then return end
if self:GetOwner():IsOnGround() then
2014-10-02 08:49:54 +08:00
if CurTime() < self:GetNextPrimaryFire() or CurTime() < self:GetNextSecondaryFire() or CurTime() < self.NextAllowPounce then return end
self:SetNextPrimaryFire(math.huge)
self:SetPounceTime(CurTime() + self.PounceStartDelay)
self:GetOwner():ResetJumpPower()
if IsFirstTimePredicted() then
self:PlayPounceStartSound()
2014-10-02 08:49:54 +08:00
end
elseif self:GetClimbSurface() then
self:StartClimbing()
end
end
function SWEP:StartClimbing()
if self:GetClimbing() then return end
self:SetClimbing(true)
self:SetNextSecondaryFire(CurTime() + 0.5)
end
function SWEP:StopClimbing()
if not self:GetClimbing() then return end
self:SetClimbing(false)
self:SetNextSecondaryFire(CurTime())
end
function SWEP:StartPounce()
if self:IsPouncing() then return end
self:SetPounceTime(0)
local owner = self:GetOwner()
2014-10-02 08:49:54 +08:00
if owner:IsOnGround() then
self:SetPouncing(true)
self.m_ViewAngles = owner:EyeAngles()
if IsFirstTimePredicted() then
self:PlayPounceSound()
2014-10-02 08:49:54 +08:00
end
local ang = owner:EyeAngles()
ang.pitch = math.min(-20, ang.pitch)
2014-10-02 08:49:54 +08:00
owner:SetGroundEntity(NULL)
owner:SetVelocity((1 - 0.5 * (owner:GetLegDamage() / GAMEMODE.MaxLegDamage)) * self.PounceVelocity * ang:Forward())
2014-10-02 08:49:54 +08:00
owner:SetAnimation(PLAYER_JUMP)
else
self:SetNextSecondaryFire(CurTime())
self.m_ViewAngles = nil
self.NextAllowJump = CurTime()
self.NextAllowPounce = CurTime() + self.PounceDelay
self:SetNextPrimaryFire(CurTime() + 0.1)
self:GetOwner():ResetJumpPower()
2014-10-02 08:49:54 +08:00
end
end
function SWEP:PlayPounceStartSound()
self:EmitSound("npc/fast_zombie/leap1.wav", nil, nil, nil, CHAN_AUTO)
end
function SWEP:PlayPounceSound()
self:EmitSound("NPC_FastZombie.Scream", nil, nil, nil, CHAN_AUTO)
end
2014-10-02 08:49:54 +08:00
function SWEP:StopPounce()
if not self:IsPouncing() then return end
self:SetPouncing(false)
self:SetNextSecondaryFire(CurTime())
self.m_ViewAngles = nil
self.NextAllowJump = CurTime() + 0.25
self.NextAllowPounce = CurTime() + self.PounceDelay
self:SetNextPrimaryFire(CurTime() + 0.1)
self:GetOwner():ResetJumpPower()
2014-10-02 08:49:54 +08:00
end
function SWEP:Reload()
BaseClass.SecondaryAttack(self)
2014-10-02 08:49:54 +08:00
end
function SWEP:OnRemove()
self.Removing = true
local owner = self:GetOwner()
2014-10-02 08:49:54 +08:00
if owner and owner:IsValid() then
self:StopSwingingSound()
owner:ResetJumpPower()
end
BaseClass.OnRemove(self)
2014-10-02 08:49:54 +08:00
end
function SWEP:Holster()
local owner = self:GetOwner()
2014-10-02 08:49:54 +08:00
if owner and owner:IsValid() then
self:StopSwingingSound()
owner:ResetJumpPower()
end
BaseClass.Holster(self)
2014-10-02 08:49:54 +08:00
end
function SWEP:ResetJumpPower(power)
if self.Removing then return end
if self.NextAllowJump and CurTime() < self.NextAllowJump or self:IsPouncing() or self:GetPounceTime() > 0 then
return 1
end
end
--[[function SWEP:CheckIdleAnimation()
2014-10-02 08:49:54 +08:00
end
SWEP.CheckAttackAnimation = SWEP.CheckIdleAnimation]]
2014-10-02 08:49:54 +08:00
function SWEP:CheckMoaning()
2014-10-02 08:49:54 +08:00
end
SWEP.StartMoaning = SWEP.CheckMoaning
SWEP.StopMoaning = SWEP.CheckMoaning
SWEP.StartMoaningSound = SWEP.CheckMoaning
SWEP.DoSwingEvent = SWEP.CheckMoaning
2014-10-02 08:49:54 +08:00
function SWEP:PlayHitSound()
self:EmitSound("NPC_FastZombie.AttackHit", nil, nil, nil, CHAN_AUTO)
2014-10-02 08:49:54 +08:00
end
function SWEP:PlayMissSound()
self:EmitSound("NPC_FastZombie.AttackMiss", nil, nil, nil, CHAN_AUTO)
2014-10-02 08:49:54 +08:00
end
function SWEP:PlayAttackSound()
end
function SWEP:PlayIdleSound()
self:GetOwner():EmitSound("NPC_FastZombie.AlertFar")
2014-10-02 08:49:54 +08:00
self:SetRoarEndTime(CurTime() + self.RoarTime)
end
function SWEP:PlayAlertSound()
self:GetOwner():EmitSound("NPC_FastZombie.Frenzy")
2014-10-02 08:49:54 +08:00
self:SetRoarEndTime(CurTime() + self.RoarTime)
end
function SWEP:StartSwingingSound()
self:EmitSound("NPC_FastZombie.Gurgle")
2014-10-02 08:49:54 +08:00
end
function SWEP:StopSwingingSound()
self:StopSound("NPC_FastZombie.Gurgle")
2014-10-02 08:49:54 +08:00
end
function SWEP:IsMoaning()
return false
end
function SWEP:SetRoarEndTime(time)
self:SetDTFloat(1, time)
end
function SWEP:GetRoarEndTime()
return self:GetDTFloat(1)
end
function SWEP:IsRoaring()
return CurTime() < self:GetRoarEndTime()
end
function SWEP:SetPounceTime(time)
self:SetDTFloat(2, time)
end
function SWEP:GetPounceTime()
return self:GetDTFloat(2)
end
function SWEP:SetPounceTime(time)
self:SetDTFloat(2, time)
end
function SWEP:GetPounceTime()
return self:GetDTFloat(2)
end
function SWEP:SetClimbing(climbing)
self:SetDTBool(1, climbing)
end
function SWEP:GetClimbing()
return self:GetDTBool(1)
end
SWEP.IsClimbing = SWEP.GetClimbing
function SWEP:SetSwinging(swinging)
self:SetDTBool(2, swinging)
end
function SWEP:GetSwinging()
return self:GetDTBool(2)
end
function SWEP:SetPouncing(leaping)
self:SetDTBool(3, leaping)
end
function SWEP:SetSlowSwingEnd(time)
self:SetDTFloat(3, time)
end
function SWEP:GetSlowSwingEnd()
return self:GetDTFloat(3)
end
function SWEP:IsSlowSwinging()
return self:GetSlowSwingEnd() > 0
end
2014-10-02 08:49:54 +08:00
function SWEP:GetPouncing()
return self:GetDTBool(3)
end
SWEP.IsPouncing = SWEP.GetPouncing
if CLIENT then return end
function SWEP:Deploy()
self:GetOwner():CreateAmbience("fastzombieambience")
2014-10-02 08:49:54 +08:00
return BaseClass.Deploy(self)
2014-10-02 08:49:54 +08:00
end