zombiesurvival-evolved/gamemodes/zombiesurvival/gamemode/obj_player_extend.lua

873 lines
22 KiB
Lua
Raw Normal View History

2014-10-02 08:49:54 +08:00
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
2014-10-02 08:49:54 +08:00
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
2014-10-02 08:49:54 +08:00
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
Merge with current nox changes. Random starting loadouts now include things that aren't weapons (ammo, traits, etc.). Added an option to disable the automatic suicide when changing zombie classes. Zombies will no longer receive damage resistance when only one human remains. Players can no longer claim the arsenal crate that gets spawned in the human spawn when nobody has one. Any player can pack it up though. The Ghoul's ghoul touch special ability has been changed. It will no longer slow targets but will debuff them for the next 10 seconds. They will take 40% more damage (the extra damage is attributed to the person who ghoul touched them last) for the next 10 seconds as well as slightly disorienting them. The Ghoul movement speed has been reduced from 185 to 170. Added crafting recipe: 'Waraxe' Handgun. Combine two 'Battleaxe' Handguns to craft this. Slightly better version of the Owens. The Flesh Creeper model has been changed to one that doesn't have severely awkward hitboxes. The Flesh Creeper can no longer jump and attack at the same time. The Lead Pipe special trait has been changed from a disorientation to a severe view punch/snap on a global cooldown of 1.5 seconds. The Regenerative trait is now 1 health every 6 seconds under 50% health instead of 1 health every 5 seconds under 50% health. Fast Zombie Legs have been changed to be a slightly faster but slightly weaker version of Zombie Legs. Zombies that have just spawned or enter zombie gas will now have a temporary buff which gives 25% extra speed and 40% damage resistance. This buff lasts for 3 seconds and is refreshed by entering the gas. Gas will no longer heal. Zombies with this buff on will strobe dark green. Added crafting recipe: Bladehack. Combine a saw blade with a manhack to get this. Slower but has more health, does more damage, and has less of a knockback when hitting something. Resupply Boxes now award the owner a point for every 2 people who use their box instead of every single person (so half as many points). Fixed Fast Zombie Legs spawning much more abundantly than intended. Fixed Flesh Creepers not being able to jump over obstacles due to their insanely low jump height. Fixed zombies taking themselves in to account when calculating horde damage resistance (bosses always had full resistance because of this). Fixed allowing people to use worth menu after redeeming.
2014-11-07 13:03:40 +08:00
dmginfo:SetDamage(dmginfo:GetDamage() * GAMEMODE:GetZombieDamageScale(dmginfo:GetDamagePosition(), self))
2014-10-02 08:49:54 +08:00
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)
2014-10-02 08:49:54 +08:00
end
return false
2014-10-02 08:49:54 +08:00
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
2014-10-02 08:49:54 +08:00
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
2014-10-02 08:49:54 +08:00
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)
2014-10-02 08:49:54 +08:00
start = start or self:GetShootPos()
dir = dir or self:GetAimVector()
2014-10-02 08:49:54 +08:00
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)}
2014-10-02 08:49:54 +08:00
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
2014-10-02 08:49:54 +08:00
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