Advertisement
Guest User

Untitled

a guest
Jun 28th, 2016
162
0
Never
Not a member of Pastebin yet? Sign Up, it unlocks many cool features!
text 20.95 KB | None | 0 0
  1. GM.Name = "Zombie Survival"
  2. GM.Author = "William \"JetBoom\" Moodhe"
  3. GM.Email = "williammoodhe@gmail.com"
  4. GM.Website = "http://www.noxiousnet.com"
  5.  
  6. -- No, adding a gun doesn't make your name worth being here.
  7. GM.Credits = {
  8. {"William \"JetBoom\" Moodhe", "williammoodhe@gmail.com (www.noxiousnet.com)", "Creator / Programmer"},
  9. {"11k", "tjd113@gmail.com", "Zombie view models"},
  10. {"Eisiger", "k2deseve@gmail.com", "Zombie kill icons"},
  11. {"Austin \"Little Nemo\" Killey", "austin_odyssey@yahoo.com", "Ambient music"},
  12. {"Zombie Panic: Source", "http://www.zombiepanic.org/", "Melee weapon sounds"},
  13. {"Samuel", "samuel_games@hotmail.com", "Board Kit model"},
  14. {"Typhon", "lukas-tinel@hotmail.com", "HUD textures"},
  15.  
  16. {"Mr. Darkness", "", "Russian translation"},
  17. {"honsal", "", "Korean translation"},
  18. {"rui_troia", "", "Portuguese translation"},
  19. {"Shinyshark", "", "Dutch translation"},
  20. {"Kradar", "", "Italian translation"},
  21. {"Raptor", "", "German translation"},
  22. {"The Special Duckling", "", "Danish translation"},
  23. {"Box, ptown, Dr. Broly", "", "Spanish translation"}
  24. }
  25.  
  26. include("nixthelag.lua")
  27. include("buffthefps.lua")
  28.  
  29. function GM:GetNumberOfWaves()
  30. local default = GetGlobalBool("classicmode") and 10 or self.NumberOfWaves
  31. local num = GetGlobalInt("numwaves", default) -- This is controlled by logic_waves.
  32. return num == -2 and default or num
  33. end
  34.  
  35. function GM:GetWaveOneLength()
  36. return GetGlobalBool("classicmode") and self.WaveOneLengthClassic or self.WaveOneLength
  37. end
  38.  
  39. include("sh_translate.lua")
  40. include("sh_colors.lua")
  41. include("sh_serialization.lua")
  42.  
  43. include("sh_globals.lua")
  44. include("sh_crafts.lua")
  45. include("sh_util.lua")
  46. include("sh_options.lua")
  47. include("sh_zombieclasses.lua")
  48. include("sh_animations.lua")
  49. include("sh_sigils.lua")
  50.  
  51. include("noxapi/noxapi.lua")
  52.  
  53. include("obj_vector_extend.lua")
  54. include("obj_entity_extend.lua")
  55. include("obj_player_extend.lua")
  56. include("obj_weapon_extend.lua")
  57.  
  58. include("workshopfix.lua")
  59.  
  60. ----------------------
  61.  
  62. GM.EndRound = false
  63. GM.StartingWorth = 180
  64. GM.ZombieVolunteers = {}
  65.  
  66. team.SetUp(TEAM_ZOMBIE, "The Undead", Color(0, 255, 0, 255))
  67. team.SetUp(TEAM_SURVIVORS, "Survivors", Color(0, 160, 255, 255))
  68.  
  69. local validmodels = player_manager.AllValidModels()
  70. validmodels["tf01"] = nil
  71. validmodels["tf02"] = nil
  72.  
  73. vector_tiny = Vector(0.001, 0.001, 0.001)
  74.  
  75. -- ogg/mp3 still doesn't work with SoundDuration() function
  76. GM.SoundDuration = {
  77. ["zombiesurvival/music_win.ogg"] = 33.149,
  78. ["zombiesurvival/music_lose.ogg"] = 45.714,
  79. ["zombiesurvival/lasthuman.ogg"] = 120.503,
  80.  
  81. ["zombiesurvival/beats/defaulthuman/1.ogg"] = 7.111,
  82. ["zombiesurvival/beats/defaulthuman/2.ogg"] = 7.111,
  83. ["zombiesurvival/beats/defaulthuman/3.ogg"] = 7.111,
  84. ["zombiesurvival/beats/defaulthuman/4.ogg"] = 7.111,
  85. ["zombiesurvival/beats/defaulthuman/5.ogg"] = 7.111,
  86. ["zombiesurvival/beats/defaulthuman/6.ogg"] = 14.222,
  87. ["zombiesurvival/beats/defaulthuman/7.ogg"] = 14.222,
  88. ["zombiesurvival/beats/defaulthuman/8.ogg"] = 7.111,
  89. ["zombiesurvival/beats/defaulthuman/9.ogg"] = 14.222,
  90.  
  91. ["zombiesurvival/beats/defaultzombiev2/1.ogg"] = 8,
  92. ["zombiesurvival/beats/defaultzombiev2/2.ogg"] = 8,
  93. ["zombiesurvival/beats/defaultzombiev2/3.ogg"] = 8,
  94. ["zombiesurvival/beats/defaultzombiev2/4.ogg"] = 8,
  95. ["zombiesurvival/beats/defaultzombiev2/5.ogg"] = 8,
  96. ["zombiesurvival/beats/defaultzombiev2/6.ogg"] = 6.038,
  97. ["zombiesurvival/beats/defaultzombiev2/7.ogg"] = 6.038,
  98. ["zombiesurvival/beats/defaultzombiev2/8.ogg"] = 6.038,
  99. ["zombiesurvival/beats/defaultzombiev2/9.ogg"] = 6.038,
  100. ["zombiesurvival/beats/defaultzombiev2/10.ogg"] = 6.038
  101. }
  102.  
  103. function GM:AddCustomAmmo()
  104. game.AddAmmoType({name = "pulse"})
  105. game.AddAmmoType({name = "stone"})
  106.  
  107. game.AddAmmoType({name = "spotlamp"})
  108. game.AddAmmoType({name = "manhack"})
  109. game.AddAmmoType({name = "manhack_saw"})
  110. game.AddAmmoType({name = "drone"})
  111. end
  112.  
  113. function GM:CanRemoveOthersNail(pl, nailowner, ent)
  114. local plpoints = pl:Frags()
  115. local ownerpoints = nailowner:Frags()
  116. if plpoints >= 75 or ownerpoints < 75 then return true end
  117.  
  118. pl:PrintTranslatedMessage(HUD_PRINTCENTER, "cant_remove_nails_of_superior_player")
  119.  
  120. return false
  121. end
  122.  
  123. function GM:SetRedeemBrains(amount)
  124. SetGlobalInt("redeembrains", amount)
  125. end
  126.  
  127. function GM:GetRedeemBrains()
  128. return GetGlobalInt("redeembrains", self.DefaultRedeem)
  129. end
  130.  
  131. function GM:PlayerIsAdmin(pl)
  132. return pl:IsAdmin()
  133. end
  134.  
  135. function GM:GetFallDamage(pl, fallspeed)
  136. return 0
  137. end
  138.  
  139. function GM:ShouldRestartRound()
  140. if self.TimeLimit == -1 or self.RoundLimit == -1 then return true end
  141.  
  142. local roundlimit = self.RoundLimit
  143. if self.ZombieEscape and roundlimit > 0 then
  144. roundlimit = math.ceil(roundlimit * 1.5)
  145. end
  146.  
  147. local timelimit = self.TimeLimit
  148. if self.ZombieEscape and timelimit > 0 then
  149. timelimit = timelimit * 1.5
  150. end
  151.  
  152. if timelimit > 0 and CurTime() >= timelimit or roundlimit > 0 and self.CurrentRound >= roundlimit then return false end
  153.  
  154. return true
  155. end
  156.  
  157. function GM:ZombieSpawnDistanceSort(other)
  158. return self._ZombieSpawnDistance < other._ZombieSpawnDistance
  159. end
  160.  
  161. function GM:SortZombieSpawnDistances(allplayers)
  162. local curtime = CurTime()
  163.  
  164. local zspawns = ents.FindByClass("zombiegasses")
  165. if #zspawns == 0 then
  166. zspawns = team.GetValidSpawnPoint(TEAM_UNDEAD)
  167. end
  168.  
  169. for _, pl in pairs(allplayers) do
  170. if pl:Team() == TEAM_UNDEAD or pl:GetInfo("zs_alwaysvolunteer") == "1" then
  171. pl._ZombieSpawnDistance = -1
  172. elseif CLIENT or pl.LastNotAFK and CurTime() <= pl.LastNotAFK + 60 then
  173. local plpos = pl:GetPos()
  174. local closest = 9999999
  175. for _, ent in pairs(zspawns) do
  176. local dist = ent:GetPos():Distance(plpos)
  177. if dist < closest then
  178. closest = dist
  179. end
  180. end
  181. pl._ZombieSpawnDistance = closest
  182. else
  183. pl._ZombieSpawnDistance = 9999999
  184. end
  185. end
  186.  
  187. table.sort(allplayers, self.ZombieSpawnDistanceSort)
  188. end
  189.  
  190. function GM:SetDynamicSpawning(onoff)
  191. SetGlobalBool("DynamicSpawningDisabled", not onoff)
  192. self.DynamicSpawning = onoff
  193. end
  194.  
  195. function GM:ValidMenuLockOnTarget(pl, ent)
  196. if ent and ent:IsValid() and ent:IsPlayer() and ent:Team() == TEAM_HUMAN and ent:Alive() then
  197. local startpos = pl:EyePos()
  198. local endpos = ent:NearestPoint(startpos)
  199. if startpos:Distance(endpos) <= 48 and TrueVisible(startpos, endpos) then
  200. return true
  201. end
  202. end
  203.  
  204. return false
  205. end
  206.  
  207. function GM:GetHandsModel(pl)
  208. return player_manager.TranslatePlayerHands(pl:GetInfo("cl_playermodel"))
  209. end
  210.  
  211. local playerheight = Vector(0, 0, 72)
  212. local playermins = Vector(-17, -17, 0)
  213. local playermaxs = Vector(17, 17, 4)
  214. local SkewedDistance = util.SkewedDistance
  215.  
  216. GM.DynamicSpawnDistVisOld = 2048
  217. GM.DynamicSpawnDistOld = 640
  218. function GM:DynamicSpawnIsValidOld(zombie, humans, allplayers)
  219. -- I didn't make this check where trigger_hurt entities are. Rather I made it check the time since the last time you were hit with a trigger_hurt.
  220. -- I'm not sure if it's possible to check if a trigger_hurt is enabled or disabled through the Lua bindings.
  221. if SERVER and zombie.LastHitWithTriggerHurt and CurTime() < zombie.LastHitWithTriggerHurt + 2 then
  222. return false
  223. end
  224.  
  225. -- Optional caching for these.
  226. if not humans then humans = team.GetPlayers(TEAM_HUMAN) end
  227. if not allplayers then allplayers = player.GetAll() end
  228.  
  229. local pos = zombie:GetPos() + Vector(0, 0, 1)
  230. if zombie:Alive() and zombie:GetMoveType() == MOVETYPE_WALK and zombie:OnGround()
  231. and not util.TraceHull({start = pos, endpos = pos + playerheight, mins = playermins, maxs = playermaxs, mask = MASK_SOLID, filter = allplayers}).Hit then
  232. local vtr = util.TraceHull({start = pos, endpos = pos - playerheight, mins = playermins, maxs = playermaxs, mask = MASK_SOLID_BRUSHONLY})
  233. if not vtr.HitSky and not vtr.HitNoDraw then
  234. local valid = true
  235.  
  236. for _, human in pairs(humans) do
  237. local hpos = human:GetPos()
  238. local nearest = zombie:NearestPoint(hpos)
  239. local dist = SkewedDistance(hpos, nearest, 2.75) -- We make it so that the Z distance between a human and a zombie is skewed if the zombie is below the human.
  240. if dist <= self.DynamicSpawnDistOld or dist <= self.DynamicSpawnDistVisOld and WorldVisible(hpos, nearest) then -- Zombies can't be in radius of any humans. Zombies can't be clearly visible by any humans.
  241. valid = false
  242. break
  243. end
  244. end
  245.  
  246. return valid
  247. end
  248. end
  249.  
  250. return false
  251. end
  252.  
  253. function GM:GetBestDynamicSpawnOld(pl, pos)
  254. local spawns = self:GetDynamicSpawnsOld(pl)
  255. if #spawns == 0 then return end
  256.  
  257. return self:GetClosestSpawnPoint(spawns, pos or self:GetTeamEpicentre(TEAM_HUMAN)) or table.Random(spawns)
  258. end
  259.  
  260. function GM:GetDynamicSpawnsOld(pl)
  261. local tab = {}
  262.  
  263. local allplayers = player.GetAll()
  264. local humans = team.GetPlayers(TEAM_HUMAN)
  265. for _, zombie in pairs(team.GetPlayers(TEAM_UNDEAD)) do
  266. if zombie ~= pl and self:DynamicSpawnIsValidOld(zombie, humans, allplayers) then
  267. table.insert(tab, zombie)
  268. end
  269. end
  270.  
  271. return tab
  272. end
  273.  
  274. GM.DynamicSpawnDist = 400
  275. GM.DynamicSpawnDistBuild = 650
  276. function GM:DynamicSpawnIsValid(nest, humans, allplayers)
  277. if self:ShouldUseAlternateDynamicSpawn() then
  278. return self:DynamicSpawnIsValidOld(nest, humans, allplayers)
  279. end
  280.  
  281. -- Optional caching for these.
  282. if not humans then humans = team.GetPlayers(TEAM_HUMAN) end
  283. --if not allplayers then allplayers = player.GetAll() end
  284.  
  285. local pos = nest:GetPos() + Vector(0, 0, 1)
  286. if nest.GetNestBuilt and nest:GetNestBuilt() and not util.TraceHull({start = pos, endpos = pos + playerheight, mins = playermins, maxs = playermaxs, mask = MASK_SOLID_BRUSHONLY}).Hit then
  287. local vtr = util.TraceHull({start = pos, endpos = pos - playerheight, mins = playermins, maxs = playermaxs, mask = MASK_SOLID_BRUSHONLY})
  288. if not vtr.HitSky and not vtr.HitNoDraw then
  289. local valid = true
  290. local nearest = nest:GetPos()
  291.  
  292. for _, human in pairs(humans) do
  293. local hpos = human:GetPos()
  294. local dist = SkewedDistance(hpos, nearest, 2.75) -- We make it so that the Z distance between a human and a nest is skewed if the nest is below the human.
  295. if dist <= self.DynamicSpawnDist then
  296. valid = false
  297. break
  298. end
  299. end
  300.  
  301. return valid
  302. end
  303. end
  304.  
  305. return false
  306. end
  307.  
  308. function GM:GetBestDynamicSpawn(pl, pos)
  309. if self:ShouldUseAlternateDynamicSpawn() then
  310. return self:GetBestDynamicSpawnOld(pl, pos)
  311. end
  312.  
  313. local spawns = self:GetDynamicSpawns(pl)
  314. if #spawns == 0 then return end
  315.  
  316. return self:GetClosestSpawnPoint(spawns, pos or self:GetTeamEpicentre(TEAM_HUMAN)) or table.Random(spawns)
  317. end
  318.  
  319. function GM:GetDynamicSpawns(pl)
  320. if self:ShouldUseAlternateDynamicSpawn() then
  321. return self:GetDynamicSpawnsOld(pl)
  322. end
  323.  
  324. local tab = {}
  325.  
  326. --local allplayers = player.GetAll()
  327. local humans = team.GetPlayers(TEAM_HUMAN)
  328. for _, nest in pairs(ents.FindByClass("prop_creepernest")) do
  329. if self:DynamicSpawnIsValid(nest, humans--[[, allplayers]]) then
  330. table.insert(tab, nest)
  331. end
  332. end
  333.  
  334. return tab
  335. end
  336.  
  337. function GM:GetDesiredStartingZombies()
  338. local numplayers = #player.GetAll()
  339. return math.min(math.max(1, math.ceil(numplayers * self.WaveOneZombies)), numplayers - 1)
  340. end
  341.  
  342. function GM:GetEndRound()
  343. return self.RoundEnded
  344. end
  345.  
  346. function GM:PrecacheResources()
  347. util.PrecacheSound("physics/body/body_medium_break2.wav")
  348. util.PrecacheSound("physics/body/body_medium_break3.wav")
  349. util.PrecacheSound("physics/body/body_medium_break4.wav")
  350. for name, mdl in pairs(player_manager.AllValidModels()) do
  351. util.PrecacheModel(mdl)
  352. end
  353. end
  354.  
  355. function GM:ShouldCollide(enta, entb)
  356. if enta.ShouldNotCollide and enta:ShouldNotCollide(entb) or entb.ShouldNotCollide and entb:ShouldNotCollide(enta) then
  357. return false
  358. end
  359.  
  360. return true
  361. end
  362.  
  363. function GM:Move(pl, move)
  364. if pl:Team() == TEAM_HUMAN then
  365. if pl:GetBarricadeGhosting() then
  366. move:SetMaxSpeed(36)
  367. move:SetMaxClientSpeed(36)
  368. elseif move:GetForwardSpeed() < 0 then
  369. move:SetMaxSpeed(move:GetMaxSpeed() * 0.5)
  370. move:SetMaxClientSpeed(move:GetMaxClientSpeed() * 0.5)
  371. elseif move:GetForwardSpeed() == 0 then
  372. move:SetMaxSpeed(move:GetMaxSpeed() * 0.85)
  373. move:SetMaxClientSpeed(move:GetMaxClientSpeed() * 0.85)
  374. end
  375. elseif pl:CallZombieFunction("Move", move) then
  376. return
  377. end
  378.  
  379. local legdamage = pl:GetLegDamage()
  380. if legdamage > 0 then
  381. local scale = 1 - math.min(1, legdamage * 0.33)
  382. move:SetMaxSpeed(move:GetMaxSpeed() * scale)
  383. move:SetMaxClientSpeed(move:GetMaxClientSpeed() * scale)
  384. end
  385. end
  386.  
  387. function GM:OnPlayerHitGround(pl, inwater, hitfloater, speed)
  388. if inwater then return true end
  389.  
  390. local isundead = pl:Team() == TEAM_UNDEAD
  391.  
  392. if isundead then
  393. if pl:GetZombieClassTable().NoFallDamage then return true end
  394. else
  395. pl:PreventSkyCade()
  396. end
  397.  
  398. if not isundead or not pl:GetZombieClassTable().NoFallSlowdown then
  399. pl:RawCapLegDamage(CurTime() + math.min(2, speed * 0.0035))
  400. end
  401.  
  402. if SERVER then
  403. if isundead then
  404. speed = math.max(0, speed - 200)
  405. end
  406.  
  407. local damage = (0.1 * (speed - 525)) ^ 1.45
  408. if hitfloater then damage = damage / 2 end
  409.  
  410. if math.floor(damage) > 0 then
  411. if 20 <= damage and damage < pl:Health() then
  412. pl:KnockDown(damage * 0.05)
  413. end
  414. pl:TakeSpecialDamage(damage, DMG_FALL, game.GetWorld(), game.GetWorld(), pl:GetPos())
  415. pl:EmitSound("player/pl_fallpain"..(math.random(2) == 1 and 3 or 1)..".wav")
  416. end
  417. end
  418.  
  419. return true
  420. end
  421.  
  422. function GM:PlayerCanBeHealed(pl)
  423. return true
  424. end
  425.  
  426. function GM:PlayerCanPurchase(pl)
  427. return pl:Team() == TEAM_HUMAN and self:GetWave() > 0 and pl:Alive() and pl:NearArsenalCrate()
  428. end
  429.  
  430. function GM:PlayerCanHearPlayersVoice(listener, talker)
  431. return listener:Team() == talker:Team()
  432. --[[if self:GetEndRound() then return true, false end
  433.  
  434. if listener:Team() == talker:Team() then
  435. return true, listener:GetPos():DistanceZSkew(talker:GetPos(), 2) <= 128
  436. end
  437.  
  438. return false]]
  439. end
  440.  
  441. function GM:PlayerTraceAttack(pl, dmginfo, dir, trace)
  442. end
  443.  
  444. function GM:ScalePlayerDamage(pl, hitgroup, dmginfo)
  445. if hitgroup == HITGROUP_HEAD and dmginfo:IsBulletDamage() then
  446. pl.m_LastHeadShot = CurTime()
  447. end
  448.  
  449. if not pl:CallZombieFunction("ScalePlayerDamage", hitgroup, dmginfo) then
  450. if hitgroup == HITGROUP_HEAD then
  451. dmginfo:SetDamage(dmginfo:GetDamage() * 2)
  452. elseif hitgroup == HITGROUP_LEFTLEG or hitgroup == HITGROUP_RIGHTLEG or hitgroup == HITGROUP_GEAR then
  453. dmginfo:SetDamage(dmginfo:GetDamage() * 0.25)
  454. elseif hitgroup == HITGROUP_STOMACH or hitgroup == HITGROUP_LEFTARM or hitgroup == HITGROUP_RIGHTARM then
  455. dmginfo:SetDamage(dmginfo:GetDamage() * 0.75)
  456. end
  457. end
  458.  
  459. if (hitgroup == HITGROUP_LEFTLEG or hitgroup == HITGROUP_RIGHTLEG) and self:PlayerShouldTakeDamage(pl, dmginfo:GetAttacker()) then
  460. pl:AddLegDamage(dmginfo:GetDamage())
  461. end
  462. end
  463.  
  464. function GM:CanDamageNail(ent, attacker, inflictor, damage, dmginfo)
  465. return not attacker:IsPlayer() or attacker:Team() ~= TEAM_HUMAN
  466. end
  467.  
  468. function GM:CanPlaceNail(pl, tr)
  469. return true
  470. end
  471.  
  472. function GM:CanRemoveNail(pl, nail)
  473. return true
  474. end
  475.  
  476. function GM:GetDamageResistance(fearpower)
  477. return fearpower * 0.35
  478. end
  479.  
  480. function GM:FindUseEntity(pl, ent)
  481. if not ent:IsValid() then
  482. local e = pl:TraceLine(90, MASK_SOLID, pl:GetMeleeFilter()).Entity
  483. if e:IsValid() then return e end
  484. end
  485.  
  486. return ent
  487. end
  488.  
  489. function GM:ShouldUseAlternateDynamicSpawn()
  490. return self.ZombieEscape or self:IsClassicMode() or self.PantsMode or self:IsBabyMode()
  491. end
  492.  
  493. function GM:GetZombieDamageScale(pos, ignore)
  494. if LASTHUMAN then return self.ZombieDamageMultiplier end
  495.  
  496. return self.ZombieDamageMultiplier * (1 - self:GetDamageResistance(self:GetFearMeterPower(pos, TEAM_UNDEAD, ignore)))
  497. end
  498.  
  499. local temppos
  500. local function SortByDistance(a, b)
  501. return a:GetPos():Distance(temppos) < b:GetPos():Distance(temppos)
  502. end
  503.  
  504. function GM:GetClosestSpawnPoint(teamid, pos)
  505. temppos = pos
  506. local spawnpoints
  507. if type(teamid) == "table" then
  508. spawnpoints = teamid
  509. else
  510. spawnpoints = team.GetValidSpawnPoint(teamid)
  511. end
  512. table.sort(spawnpoints, SortByDistance)
  513. return spawnpoints[1]
  514. end
  515.  
  516. local FEAR_RANGE = 768
  517. local FEAR_PERINSTANCE = 0.075
  518. local RALLYPOINT_THRESHOLD = 0.3
  519.  
  520. local function GetEpicenter(tab)
  521. local vec = Vector(0, 0, 0)
  522. if #tab == 0 then return vec end
  523.  
  524. for k, v in pairs(tab) do
  525. vec = vec + v:GetPos()
  526. end
  527.  
  528. return vec / #tab
  529. end
  530.  
  531. function GM:GetTeamRallyGroups(teamid)
  532. local groups = {}
  533. local ingroup = {}
  534.  
  535. local plys = team.GetPlayers(teamid)
  536.  
  537. for _, pl in pairs(plys) do
  538. if not ingroup[pl] and pl:Alive() then
  539. local plpos = pl:GetPos()
  540. local group = {pl}
  541.  
  542. for __, otherpl in pairs(plys) do
  543. if otherpl ~= pl and not ingroup[otherpl] and otherpl:Alive() and otherpl:GetPos():Distance(plpos) <= FEAR_RANGE then
  544. group[#group + 1] = otherpl
  545. end
  546. end
  547.  
  548. if #group * FEAR_PERINSTANCE >= RALLYPOINT_THRESHOLD then
  549. for k, v in pairs(group) do
  550. ingroup[v] = true
  551. end
  552. groups[#groups + 1] = group
  553. end
  554. end
  555. end
  556.  
  557. return groups
  558. end
  559.  
  560. function GM:GetTeamRallyPoints(teamid)
  561. local points = {}
  562.  
  563. for _, group in pairs(self:GetTeamRallyGroups(teamid)) do
  564. points[#points + 1] = {GetEpicenter(group), math.min(1, (#group * FEAR_PERINSTANCE - RALLYPOINT_THRESHOLD) / (1 - RALLYPOINT_THRESHOLD))}
  565. end
  566.  
  567. return points
  568. end
  569.  
  570. local CachedEpicentreTimes = {}
  571. local CachedEpicentres = {}
  572. function GM:GetTeamEpicentre(teamid, nocache)
  573. if not nocache and CachedEpicentres[teamid] and CurTime() < CachedEpicentreTimes[teamid] then
  574. return CachedEpicentres[teamid]
  575. end
  576.  
  577. local plys = team.GetPlayers(teamid)
  578. local vVec = Vector(0, 0, 0)
  579. for _, pl in pairs(plys) do
  580. if pl:Alive() then
  581. vVec = vVec + pl:GetPos()
  582. end
  583. end
  584.  
  585. local epicentre = vVec / #plys
  586. if not nocache then
  587. CachedEpicentreTimes[teamid] = CurTime() + 0.5
  588. CachedEpicentres[teamid] = epicentre
  589. end
  590.  
  591. return epicentre
  592. end
  593. GM.GetTeamEpicenter = GM.GetTeamEpicentre
  594.  
  595. function GM:GetCurrentEquipmentCount(id)
  596. local count = 0
  597.  
  598. local item = self.Items[id]
  599. if item then
  600. if item.Countables then
  601. if type(item.Countables) == "table" then
  602. for k, v in pairs(item.Countables) do
  603. count = count + #ents.FindByClass(v)
  604. end
  605. else
  606. count = count + #ents.FindByClass(item.Countables)
  607. end
  608. end
  609.  
  610. if item.SWEP then
  611. count = count + #ents.FindByClass(item.SWEP)
  612. end
  613. end
  614.  
  615. return count
  616. end
  617.  
  618. function GM:GetFearMeterPower(pos, teamid, ignore)
  619. if LASTHUMAN then return 1 end
  620.  
  621. local power = 0
  622.  
  623. for _, pl in pairs(player.GetAll()) do
  624. if pl ~= ignore and pl:Team() == teamid and not pl:CallZombieFunction("DoesntGiveFear") and pl:Alive() then
  625. local dist = pl:NearestPoint(pos):Distance(pos)
  626. if dist <= FEAR_RANGE then
  627. power = power + ((FEAR_RANGE - dist) / FEAR_RANGE) * (pl:GetZombieClassTable().FearPerInstance or FEAR_PERINSTANCE)
  628. end
  629. end
  630. end
  631.  
  632. return math.min(1, power)
  633. end
  634.  
  635. function GM:GetRagdollEyes(pl)
  636. local Ragdoll = pl:GetRagdollEntity()
  637. if not Ragdoll then return end
  638.  
  639. local att = Ragdoll:GetAttachment(Ragdoll:LookupAttachment("eyes"))
  640. if att then
  641. att.Pos = att.Pos + att.Ang:Forward() * -2
  642. att.Ang = att.Ang
  643.  
  644. return att.Pos, att.Ang
  645. end
  646. end
  647.  
  648. function GM:PlayerNoClip(pl, on)
  649. if pl:IsAdmin() then
  650. if SERVER then
  651. PrintMessage(HUD_PRINTCONSOLE, translate.Format(on and "x_turned_on_noclip" or "x_turned_off_noclip", pl:Name()))
  652. end
  653.  
  654. if SERVER then
  655. pl:MarkAsBadProfile()
  656. end
  657.  
  658. return true
  659. end
  660.  
  661. return false
  662. end
  663.  
  664. function GM:IsSpecialPerson(pl, image)
  665. local img, tooltip
  666.  
  667. if pl:SteamID() == "STEAM_0:1:3307510" then
  668. img = "VGUI/steam/games/icon_sourcesdk"
  669. tooltip = "JetBoom\nCreator of Zombie Survival!"
  670. elseif pl:IsAdmin() then
  671. img = "VGUI/servers/icon_robotron"
  672. tooltip = "Admin"
  673. elseif pl:IsNoxSupporter() then
  674. img = "noxiousnet/noxicon.png"
  675. tooltip = "Nox Supporter"
  676. end
  677.  
  678. if img then
  679. if CLIENT then
  680. image:SetImage(img)
  681. image:SetTooltip(tooltip)
  682. end
  683.  
  684. return true
  685. end
  686.  
  687. return false
  688. end
  689.  
  690. function GM:GetWaveEnd()
  691. return GetGlobalFloat("waveend", 0)
  692. end
  693.  
  694. function GM:SetWaveEnd(wave)
  695. SetGlobalFloat("waveend", wave)
  696. end
  697.  
  698. function GM:GetWaveStart()
  699. return GetGlobalFloat("wavestart", self.WaveZeroLength)
  700. end
  701.  
  702. function GM:SetWaveStart(wave)
  703. SetGlobalFloat("wavestart", wave)
  704. end
  705.  
  706. function GM:GetWave()
  707. return GetGlobalInt("wave", 0)
  708. end
  709.  
  710. if GM:GetWave() == 0 then
  711. GM:SetWaveStart(GM.WaveZeroLength)
  712. GM:SetWaveEnd(GM.WaveZeroLength + GM:GetWaveOneLength())
  713. end
  714.  
  715. function GM:GetWaveActive()
  716. return GetGlobalBool("waveactive", false)
  717. end
  718.  
  719. function GM:SetWaveActive(active)
  720. if self.RoundEnded then return end
  721.  
  722. if self:GetWaveActive() ~= active then
  723. SetGlobalBool("waveactive", active)
  724.  
  725. if SERVER then
  726. gamemode.Call("WaveStateChanged", active)
  727. end
  728. end
  729. end
  730.  
  731. if not FixedSoundDuration then
  732. FixedSoundDuration = true
  733. local OldSoundDuration = SoundDuration
  734. function SoundDuration(snd)
  735. if snd then
  736. local ft = string.sub(snd, -4)
  737. if ft == ".mp3" then
  738. return OldSoundDuration(snd) * 2.25
  739. end
  740. if ft == ".ogg" then
  741. return OldSoundDuration(snd) * 3
  742. end
  743. end
  744.  
  745. return OldSoundDuration(snd)
  746. end
  747. end
Advertisement
Add Comment
Please, Sign In to add comment
Advertisement