8cbfdaf59f
Players no longer get leg damage unless they take damage from the fall. Anti bunny hopping script remade and now applies to all players regardless of leg damage, team, or zombie class.
872 lines
22 KiB
Lua
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 - 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
|