zombiesurvival-evolved/gamemodes/zombiesurvival/gamemode/obj_player_extend.lua
2014-12-23 18:24:31 -05:00

872 lines
22 KiB
Lua

local meta = FindMetaTable("Player")
if not meta then return end
function meta:GetMaxHealthEx()
if self:Team() == TEAM_UNDEAD then
return self:GetMaxZombieHealth()
end
return self:GetMaxHealth()
end
function meta:Dismember(dismembermenttype)
local effectdata = EffectData()
effectdata:SetOrigin(self:EyePos())
effectdata:SetEntity(self)
effectdata:SetScale(dismembermenttype)
util.Effect("dismemberment", effectdata, true, true)
end
function meta:HasWon()
if self:Team() == TEAM_HUMAN and self:GetObserverMode() == OBS_MODE_ROAMING then
if SERVER then
local target = self:GetObserverTarget()
return target and target:IsValid() and target:GetClass() == "prop_obj_exit"
end
return true
end
return false
end
function meta:GetBossZombieIndex()
local bossclasses = {}
for _, classtable in pairs(GAMEMODE.ZombieClasses) do
if classtable.Boss then
table.insert(bossclasses, classtable.Index)
end
end
if #bossclasses == 0 then return -1 end
local desired = self:GetInfo("zs_bossclass") or ""
if GAMEMODE:IsBabyMode() then
desired = "Giga Gore Child"
elseif desired == "[RANDOM]" or desired == "" then
desired = "Nightmare"
end
local bossindex
for _, classindex in pairs(bossclasses) do
local classtable = GAMEMODE.ZombieClasses[classindex]
if string.lower(classtable.Name) == string.lower(desired) then
bossindex = classindex
break
end
end
return bossindex or bossclasses[math.random(#bossclasses)]
end
function meta:GetAuraRange()
local wep = self:GetActiveWeapon()
return wep:IsValid() and wep.GetAuraRange and wep:GetAuraRange() or 2048
end
function meta:GetCoupledHeadcrab()
local status = self.m_Couple
return status and status:IsValid() and status:GetPartner() or NULL
end
function meta:GetPoisonDamage()
return self.PoisonRecovery and self.PoisonRecovery:IsValid() and self.PoisonRecovery:GetDamage() or 0
end
function meta:GetBleedDamage()
return self.Bleed and self.Bleed:IsValid() and self.Bleed:GetDamage() or 0
end
function meta:CallWeaponFunction(funcname, ...)
local wep = self:GetActiveWeapon()
if wep:IsValid() and wep[funcname] then
return wep[funcname](wep, self, ...)
end
end
function meta:ClippedName()
local name = self:Name()
if #name > 16 then
name = string.sub(name, 1, 14)..".."
end
return name
end
function meta:DispatchAltUse()
local tr = self:TraceLine(64, MASK_SOLID, self:GetMeleeFilter())
local ent = tr.Entity
if ent and ent:IsValid() then
if ent.AltUse then
return ent:AltUse(self, tr)
end
end
end
function meta:MeleeViewPunch(damage)
local maxpunch = (damage + 25) * 0.5
local minpunch = -maxpunch
self:ViewPunch(Angle(math.Rand(minpunch, maxpunch), math.Rand(minpunch, maxpunch), math.Rand(minpunch, maxpunch)))
end
function meta:NearArsenalCrate()
local pos = self:EyePos()
for _, ent in pairs(ents.FindByClass("prop_arsenalcrate")) do
local nearest = ent:NearestPoint(pos)
if pos:Distance(nearest) <= 80 and (WorldVisible(pos, nearest) or self:TraceLine(80).Entity == ent) then
return true
end
end
return false
end
meta.IsNearArsenalCrate = meta.NearArsenalCrate
function meta:NearestArsenalCrateOwnedByOther()
local pos = self:EyePos()
for _, ent in pairs(ents.FindByClass("prop_arsenalcrate")) do
local nearest = ent:NearestPoint(pos)
local owner = ent:GetObjectOwner()
if owner ~= self and owner:IsValid() and owner:IsPlayer() and owner:Team() == TEAM_HUMAN and pos:Distance(nearest) <= 80 and (WorldVisible(pos, nearest) or self:TraceLine(80).Entity == ent) then
return ent
end
end
end
function meta:SetZombieClassName(classname)
if GAMEMODE.ZombieClasses[classname] then
self:SetZombieClass(GAMEMODE.ZombieClasses[classname].Index)
end
end
function meta:SetPoints(points)
self:SetDTInt(1, points)
end
function meta:GetPoints()
return self:GetDTInt(1)
end
function meta:SetPalsy(onoff, nosend)
self.m_Palsy = onoff
if SERVER and not nosend then
self:SendLua("LocalPlayer():SetPalsy("..tostring(onoff)..")")
end
end
function meta:GetPalsy()
return self.m_Palsy
end
function meta:SetHemophilia(onoff, nosend)
self.m_Hemophilia = onoff
if SERVER and not nosend then
self:SendLua("LocalPlayer():SetHemophilia("..tostring(onoff)..")")
end
end
function meta:GetHemophilia()
return self.m_Hemophilia
end
function meta:SetUnlucky(onoff)
self.m_Unlucky = onoff
end
function meta:GetUnlucky()
return self.m_Unlucky
end
function meta:AddLegDamage(damage)
self:SetLegDamage(self:GetLegDamage() + damage)
end
function meta:SetLegDamage(damage)
self.LegDamage = CurTime() + math.min(GAMEMODE.MaxLegDamage, damage * 0.125)
if SERVER then
self:UpdateLegDamage()
end
end
function meta:RawSetLegDamage(time)
self.LegDamage = math.min(CurTime() + GAMEMODE.MaxLegDamage, time)
if SERVER then
self:UpdateLegDamage()
end
end
function meta:RawCapLegDamage(time)
self:RawSetLegDamage(math.max(self.LegDamage or 0, time))
end
function meta:GetLegDamage()
return math.max(0, (self.LegDamage or 0) - CurTime())
end
function meta:WouldDieFrom(damage, hitpos)
return self:Health() <= damage * GAMEMODE:GetZombieDamageScale(hitpos, self)
end
function meta:ProcessDamage(dmginfo)
local attacker, inflictor = dmginfo:GetAttacker(), dmginfo:GetInflictor()
if self.DamageVulnerability then
dmginfo:SetDamage(dmginfo:GetDamage() * self.DamageVulnerability)
end
if self:Team() == TEAM_UNDEAD then
if self ~= attacker then
dmginfo:SetDamage(dmginfo:GetDamage() * GAMEMODE:GetZombieDamageScale(dmginfo:GetDamagePosition(), self))
end
return self:CallZombieFunction("ProcessDamage", dmginfo)
elseif attacker:IsValid() and attacker:IsPlayer() and attacker:Team() == TEAM_UNDEAD and inflictor:IsValid() and inflictor == attacker:GetActiveWeapon() then
local damage = dmginfo:GetDamage()
local scale = inflictor.SlowDownScale or 1
if damage >= 40 or scale > 1 then
local dolegdamage = true
if inflictor.SlowDownImmunityTime then
if CurTime() < (self.SlowDownImmunityTime or 0) then
dolegdamage = false
else
self.SlowDownImmunityTime = CurTime() + inflictor.SlowDownImmunityTime
end
end
if dolegdamage then
self:RawCapLegDamage(self:GetLegDamage() + CurTime() + damage * 0.04 * (inflictor.SlowDownScale or 1))
end
end
if self:GetHemophilia() and damage >= 5 then
local dmgtype = dmginfo:GetDamageType()
if dmgtype == 0
or bit.band(dmgtype, DMG_SLASH) ~= 0
or bit.band(dmgtype, DMG_CLUB) ~= 0
or bit.band(dmgtype, DMG_BULLET) ~= 0
or bit.band(dmgtype, DMG_BUCKSHOT) ~= 0
or bit.band(dmgtype, DMG_CRUSH) ~= 0 then
local bleed = self:GiveStatus("bleed")
if bleed and bleed:IsValid() then
bleed:AddDamage(damage * 0.2)
if attacker:IsValid() and attacker:IsPlayer() then
bleed.Damager = attacker
end
end
end
end
end
end
function meta:KnockDown(time)
if self:Team() ~= TEAM_UNDEAD then
self:GiveStatus("knockdown", time or 3)
end
end
function meta:GetZombieClass()
return self.Class or GAMEMODE.DefaultZombieClass
end
local ZombieClasses = GM.ZombieClasses
function meta:GetZombieClassTable()
return ZombieClasses[self:GetZombieClass()]
end
function meta:CallZombieFunction(funcname, ...)
if self:Team() == TEAM_UNDEAD then
local tab = self:GetZombieClassTable()
if tab[funcname] then
return tab[funcname](tab, self, ...)
end
end
end
function meta:TraceLine(distance, mask, filter, start)
start = start or self:GetShootPos()
return util.TraceLine({start = start, endpos = start + self:GetAimVector() * distance, filter = filter or self, mask = mask})
end
function meta:TraceHull(distance, mask, size, filter, start)
start = start or self:GetShootPos()
return util.TraceHull({start = start, endpos = start + self:GetAimVector() * distance, filter = filter or self, mask = mask, mins = Vector(-size, -size, -size), maxs = Vector(size, size, size)})
end
function meta:DoubleTrace(distance, mask, size, mask2, filter)
local tr1 = self:TraceLine(distance, mask, filter)
if tr1.Hit then return tr1 end
if mask2 then
local tr2 = self:TraceLine(distance, mask2, filter)
if tr2.Hit then return tr2 end
end
local tr3 = self:TraceHull(distance, mask, size, filter)
if tr3.Hit then return tr3 end
if mask2 then
local tr4 = self:TraceHull(distance, mask2, size, filter)
if tr4.Hit then return tr4 end
end
return tr1
end
function meta:SetSpeed(speed)
if not speed then speed = 200 end
self:SetWalkSpeed(speed)
self:SetRunSpeed(speed)
self:SetMaxSpeed(speed)
end
function meta:SetHumanSpeed(speed)
if self:Team() == TEAM_HUMAN then self:SetSpeed(speed) end
end
function meta:ResetSpeed(noset, health)
if not self:IsValid() then return end
if self:Team() == TEAM_UNDEAD then
local speed = self:GetZombieClassTable().Speed * GAMEMODE.ZombieSpeedMultiplier
self:SetSpeed(speed)
return speed
end
local wep = self:GetActiveWeapon()
local speed
if wep:IsValid() and wep.GetWalkSpeed then
speed = wep:GetWalkSpeed()
end
if not speed then
speed = wep.WalkSpeed or SPEED_NORMAL
end
if self.HumanSpeedAdder and self:Team() == TEAM_HUMAN and 32 < speed then
speed = speed + self.HumanSpeedAdder
end
--[[if self:IsHolding() then
local status = self.status_human_holding
if status and status:IsValid() and status:GetObject():IsValid() and status:GetObject():GetPhysicsObject():IsValid() then
speed = math.min(speed, math.max(CARRY_SPEEDLOSS_MINSPEED, speed - status:GetObject():GetPhysicsObject():GetMass() * CARRY_SPEEDLOSS_PERKG))
end
end]]
if 32 < speed and not GAMEMODE.ZombieEscape then
if not health then health = self:Health() end
if health < 60 then
speed = math.max(88, speed - speed * 0.4 * (1 - health / 60))
end
end
if not noset then
self:SetSpeed(speed)
end
return speed
end
function meta:ResetJumpPower(noset)
local power = DEFAULT_JUMP_POWER
if self:Team() == TEAM_UNDEAD then
power = self:CallZombieFunction("GetJumpPower") or power
local classtab = self:GetZombieClassTable()
if classtab and classtab.JumpPower then
power = classtab.JumpPower
end
else
if self:GetBarricadeGhosting() then
power = power * 0.25
if not noset then
self:SetJumpPower(power)
end
return power
end
end
local wep = self:GetActiveWeapon()
if wep and wep.ResetJumpPower then
power = wep:ResetJumpPower(power) or power
end
if not noset then
self:SetJumpPower(power)
end
return power
end
function meta:SetBarricadeGhosting(b)
if b and self.NoGhosting then return end
self:SetDTBool(0, b)
self:CollisionRulesChanged()
self:ResetJumpPower()
end
function meta:GetBarricadeGhosting()
return self:GetDTBool(0)
end
meta.IsBarricadeGhosting = meta.GetBarricadeGhosting
function meta:ShouldBarricadeGhostWith(ent)
return ent:IsBarricadeProp()
end
function meta:BarricadeGhostingThink()
if self:KeyDown(IN_ZOOM) or self:ActiveBarricadeGhosting() then return end
self:SetBarricadeGhosting(false)
end
function meta:ShouldNotCollide(ent)
if ent:IsValid() then
if ent:IsPlayer() then
return self:Team() == ent:Team() or self.NoCollideAll or ent.NoCollideAll
end
return self:GetBarricadeGhosting() and ent:IsBarricadeProp() or self:Team() == TEAM_HUMAN and ent:GetPhysicsObject():IsValid() and ent:GetPhysicsObject():HasGameFlag(FVPHYSICS_PLAYER_HELD)
end
return false
end
local function nocollidetimer(self, timername)
if self:IsValid() then
for _, e in pairs(ents.FindInBox(self:WorldSpaceAABB())) do
if e and e:IsValid() and e:IsPlayer() and e ~= self and GAMEMODE:ShouldCollide(self, e) then
return
end
end
self:SetCollisionGroup(COLLISION_GROUP_PLAYER)
end
timer.Destroy(timername)
end
function meta:TemporaryNoCollide(force)
if self:GetCollisionGroup() ~= COLLISION_GROUP_PLAYER and not force then return end
for _, e in pairs(ents.FindInBox(self:WorldSpaceAABB())) do
if e and e:IsValid() and e:IsPlayer() and e ~= self and GAMEMODE:ShouldCollide(self, e) then
self:SetCollisionGroup(COLLISION_GROUP_DEBRIS_TRIGGER)
local timername = "TemporaryNoCollide"..self:UniqueID()
timer.CreateEx(timername, 0, 0, nocollidetimer, self, timername)
return
end
end
self:SetCollisionGroup(COLLISION_GROUP_PLAYER)
end
meta.OldSetHealth = FindMetaTable("Entity").SetHealth
function meta:SetHealth(health)
self:OldSetHealth(health)
if self:Team() == TEAM_HUMAN and 1 <= health then
self:ResetSpeed(nil, health)
end
end
function meta:IsHeadcrab()
return self:Team() == TEAM_UNDEAD and GAMEMODE.ZombieClasses[self:GetZombieClass()].IsHeadcrab
end
function meta:AirBrake()
local vel = self:GetVelocity()
vel.x = vel.x * 0.15
vel.y = vel.y * 0.15
if vel.z > 0 then
vel.z = vel.z * 0.15
end
self:SetLocalVelocity(vel)
end
function meta:GetMeleeFilter()
return GAMEMODE.RoundEnded and {self} or team.GetPlayers(self:Team())
end
meta.GetTraceFilter = meta.GetMeleeFilter
function meta:MeleeTrace(distance, size, filter, start)
return self:TraceHull(distance, MASK_SOLID, size, filter, start)
end
function meta:PenetratingMeleeTrace(distance, size, prehit, start, dir)
start = start or self:GetShootPos()
dir = dir or self:GetAimVector()
local t = {}
local trace = {start = start, endpos = start + dir * distance, filter = self:GetMeleeFilter(), mask = MASK_SOLID, mins = Vector(-size, -size, -size), maxs = Vector(size, size, size)}
local onlyhitworld
for i=1, 50 do
local tr = util.TraceHull(trace)
if not tr.Hit then break end
if tr.HitWorld then
table.insert(t, tr)
break
end
if onlyhitworld then break end
local ent = tr.Entity
if ent and ent:IsValid() then
if not ent:IsPlayer() then
trace.mask = MASK_SOLID_BRUSHONLY
onlyhitworld = true
end
table.insert(t, tr)
table.insert(trace.filter, ent)
end
end
if prehit and (#t == 1 and not t[1].HitNonWorld and prehit.HitNonWorld or #t == 0 and prehit.HitNonWorld) then
t[1] = prehit
end
return t
end
function meta:ActiveBarricadeGhosting(override)
if self:Team() ~= TEAM_HUMAN and not override or not self:GetBarricadeGhosting() then return false end
for _, ent in pairs(ents.FindInBox(self:WorldSpaceAABB())) do
if ent and ent:IsValid() and self:ShouldBarricadeGhostWith(ent) then return true end
end
return false
end
function meta:IsHolding()
return self:GetHolding():IsValid()
end
meta.IsCarrying = meta.IsHolding
function meta:GetHolding()
local status = self.status_human_holding
if status and status:IsValid() then
local obj = status:GetObject()
if obj:IsValid() then return obj end
end
return NULL
end
function meta:GetMaxZombieHealth()
return self:GetZombieClassTable().Health
end
local oldmaxhealth = FindMetaTable("Entity").GetMaxHealth
function meta:GetMaxHealth()
if self:Team() == TEAM_UNDEAD then
return self:GetMaxZombieHealth()
end
return oldmaxhealth(self)
end
if not meta.OldAlive then
meta.OldAlive = meta.Alive
function meta:Alive()
return self:GetObserverMode() == OBS_MODE_NONE and not self.NeverAlive and self:OldAlive()
end
end
local VoiceSets = {}
VoiceSets["male"] = {
["GiveAmmoSounds"] = {
Sound("vo/npc/male01/ammo03.wav"),
Sound("vo/npc/male01/ammo04.wav"),
Sound("vo/npc/male01/ammo05.wav")
},
["PainSoundsLight"] = {
Sound("vo/npc/male01/ow01.wav"),
Sound("vo/npc/male01/ow02.wav"),
Sound("vo/npc/male01/pain01.wav"),
Sound("vo/npc/male01/pain02.wav"),
Sound("vo/npc/male01/pain03.wav")
},
["PainSoundsMed"] = {
Sound("vo/npc/male01/pain04.wav"),
Sound("vo/npc/male01/pain05.wav"),
Sound("vo/npc/male01/pain06.wav")
},
["PainSoundsHeavy"] = {
Sound("vo/npc/male01/pain07.wav"),
Sound("vo/npc/male01/pain08.wav"),
Sound("vo/npc/male01/pain09.wav")
},
["DeathSounds"] = {
Sound("vo/npc/male01/no02.wav"),
Sound("ambient/voices/citizen_beaten1.wav"),
Sound("ambient/voices/citizen_beaten3.wav"),
Sound("ambient/voices/citizen_beaten4.wav"),
Sound("ambient/voices/citizen_beaten5.wav"),
Sound("vo/npc/male01/pain07.wav"),
Sound("vo/npc/male01/pain08.wav")
},
["EyePoisonedSounds"] = {
Sound("ambient/voices/m_scream1.wav")
}
}
VoiceSets["barney"] = {
["GiveAmmoSounds"] = {
Sound("items/ammo_pickup.wav")
},
["PainSoundsLight"] = {
Sound("vo/npc/Barney/ba_pain02.wav"),
Sound("vo/npc/Barney/ba_pain07.wav"),
Sound("vo/npc/Barney/ba_pain04.wav")
},
["PainSoundsMed"] = {
Sound("vo/npc/Barney/ba_pain01.wav"),
Sound("vo/npc/Barney/ba_pain08.wav"),
Sound("vo/npc/Barney/ba_pain10.wav")
},
["PainSoundsHeavy"] = {
Sound("vo/npc/Barney/ba_pain05.wav"),
Sound("vo/npc/Barney/ba_pain06.wav"),
Sound("vo/npc/Barney/ba_pain09.wav")
},
["DeathSounds"] = {
Sound("vo/npc/Barney/ba_ohshit03.wav"),
Sound("vo/npc/Barney/ba_no01.wav"),
Sound("vo/npc/Barney/ba_no02.wav"),
Sound("vo/npc/Barney/ba_pain03.wav")
},
["EyePoisonedSounds"] = {
Sound("vo/k_lab/ba_thingaway02.wav")
}
}
VoiceSets["female"] = {
["GiveAmmoSounds"] = {
Sound("vo/npc/female01/ammo03.wav"),
Sound("vo/npc/female01/ammo04.wav"),
Sound("vo/npc/female01/ammo05.wav")
},
["PainSoundsLight"] = {
Sound("vo/npc/female01/pain01.wav"),
Sound("vo/npc/female01/pain02.wav"),
Sound("vo/npc/female01/pain03.wav")
},
["PainSoundsMed"] = {
Sound("vo/npc/female01/pain04.wav"),
Sound("vo/npc/female01/pain05.wav"),
Sound("vo/npc/female01/pain06.wav")
},
["PainSoundsHeavy"] = {
Sound("vo/npc/female01/pain07.wav"),
Sound("vo/npc/female01/pain08.wav"),
Sound("vo/npc/female01/pain09.wav")
},
["DeathSounds"] = {
Sound("vo/npc/female01/no01.wav"),
Sound("vo/npc/female01/ow01.wav"),
Sound("vo/npc/female01/ow02.wav"),
Sound("vo/npc/female01/goodgod.wav"),
Sound("ambient/voices/citizen_beaten2.wav")
},
["EyePoisonedSounds"] = {
Sound("ambient/voices/f_scream1.wav")
}
}
VoiceSets["alyx"] = {
["GiveAmmoSounds"] = {
Sound("vo/npc/female01/ammo03.wav"),
Sound("vo/npc/female01/ammo04.wav"),
Sound("vo/npc/female01/ammo05.wav")
},
["PainSoundsLight"] = {
Sound("vo/npc/Alyx/gasp03.wav"),
Sound("vo/npc/Alyx/hurt08.wav")
},
["PainSoundsMed"] = {
Sound("vo/npc/Alyx/hurt04.wav"),
Sound("vo/npc/Alyx/hurt06.wav"),
Sound("vo/Citadel/al_struggle07.wav"),
Sound("vo/Citadel/al_struggle08.wav")
},
["PainSoundsHeavy"] = {
Sound("vo/npc/Alyx/hurt05.wav"),
Sound("vo/npc/Alyx/hurt06.wav")
},
["DeathSounds"] = {
Sound("vo/npc/Alyx/no01.wav"),
Sound("vo/npc/Alyx/no02.wav"),
Sound("vo/npc/Alyx/no03.wav"),
Sound("vo/Citadel/al_dadgordonno_c.wav"),
Sound("vo/Streetwar/Alyx_gate/al_no.wav")
},
["EyePoisonedSounds"] = {
Sound("vo/npc/Alyx/uggh01.wav"),
Sound("vo/npc/Alyx/uggh02.wav")
}
}
VoiceSets["combine"] = {
["GiveAmmoSounds"] = {
Sound("npc/combine_soldier/vo/hardenthatposition.wav"),
Sound("npc/combine_soldier/vo/readyweapons.wav"),
Sound("npc/combine_soldier/vo/weareinaninfestationzone.wav"),
Sound("npc/metropolice/vo/dismountinghardpoint.wav")
},
["PainSoundsLight"] = {
Sound("npc/combine_soldier/pain1.wav"),
Sound("npc/combine_soldier/pain2.wav"),
Sound("npc/combine_soldier/pain3.wav")
},
["PainSoundsMed"] = {
Sound("npc/metropolice/pain1.wav"),
Sound("npc/metropolice/pain2.wav")
},
["PainSoundsHeavy"] = {
Sound("npc/metropolice/pain3.wav"),
Sound("npc/metropolice/pain4.wav")
},
["DeathSounds"] = {
Sound("npc/combine_soldier/die1.wav"),
Sound("npc/combine_soldier/die2.wav"),
Sound("npc/combine_soldier/die3.wav")
},
["EyePoisonSounds"] = {
Sound("npc/combine_soldier/die1.wav"),
Sound("npc/combine_soldier/die2.wav"),
Sound("npc/metropolice/vo/shit.wav")
}
}
VoiceSets["monk"] = {
["GiveAmmoSounds"] = {
Sound("vo/ravenholm/monk_giveammo01.wav")
},
["PainSoundsLight"] = {
Sound("vo/ravenholm/monk_pain01.wav"),
Sound("vo/ravenholm/monk_pain02.wav"),
Sound("vo/ravenholm/monk_pain03.wav"),
Sound("vo/ravenholm/monk_pain05.wav")
},
["PainSoundsMed"] = {
Sound("vo/ravenholm/monk_pain04.wav"),
Sound("vo/ravenholm/monk_pain06.wav"),
Sound("vo/ravenholm/monk_pain07.wav"),
Sound("vo/ravenholm/monk_pain08.wav")
},
["PainSoundsHeavy"] = {
Sound("vo/ravenholm/monk_pain09.wav"),
Sound("vo/ravenholm/monk_pain10.wav"),
Sound("vo/ravenholm/monk_pain12.wav")
},
["DeathSounds"] = {
Sound("vo/ravenholm/monk_death07.wav")
},
["EyePoisonSounds"] = {
Sound("vo/ravenholm/monk_death07.wav")
}
}
function meta:PlayEyePoisonedSound()
local snds = VoiceSets[self.VoiceSet].EyePoisonSounds
if snds then
self:EmitSound(snds[math.random(1, #snds)])
end
end
function meta:PlayGiveAmmoSound()
local snds = VoiceSets[self.VoiceSet].GiveAmmoSounds
if snds then
self:EmitSound(snds[math.random(1, #snds)])
end
end
function meta:PlayDeathSound()
local snds = VoiceSets[self.VoiceSet].DeathSounds
if snds then
self:EmitSound(snds[math.random(1, #snds)])
end
end
function meta:PlayZombieDeathSound()
if not self:CallZombieFunction("PlayDeathSound") then
local snds = self:GetZombieClassTable().DeathSounds
if snds then
self:EmitSound(snds[math.random(#snds)])
end
end
end
function meta:PlayPainSound()
if CurTime() < self.NextPainSound then return end
local snds
if self:Team() == TEAM_UNDEAD then
if self:CallZombieFunction("PlayPainSound") then return end
snds = self:GetZombieClassTable().PainSounds
else
local set = VoiceSets[self.VoiceSet]
if set then
local health = self:Health()
if 70 <= health then
snds = set.PainSoundsLight
elseif 35 <= health then
snds = set.PainSoundsMed
else
snds = set.PainSoundsHeavy
end
end
end
if snds then
local snd = snds[math.random(#snds)]
if snd then
self:EmitSound(snd)
self.NextPainSound = CurTime() + SoundDuration(snd) - 0.1
end
end
end
local ViewHullMins = Vector(-8, -8, -8)
local ViewHullMaxs = Vector(8, 8, 8)
function meta:GetThirdPersonCameraPos(origin, angles)
local allplayers = player.GetAll()
local tr = util.TraceHull({start = origin, endpos = origin + angles:Forward() * -math.max(36, self:Team() == TEAM_UNDEAD and self:GetZombieClassTable().CameraDistance or self:BoundingRadius()), mask = MASK_SHOT, filter = allplayers, mins = ViewHullMins, maxs = ViewHullMaxs})
return tr.HitPos + tr.HitNormal * 3
end
-- Override these because they're different in 1st person and on the server.
function meta:SyncAngles()
local ang = self:EyeAngles()
ang.pitch = 0
ang.roll = 0
return ang
end
meta.GetAngles = meta.SyncAngles
function meta:GetForward()
return self:SyncAngles():Forward()
end
function meta:GetUp()
return self:SyncAngles():Up()
end
function meta:GetRight()
return self:SyncAngles():Right()
end