Advertisement
Guest User

Untitled

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