Advertisement
Guest User

Untitled

a guest
Jan 17th, 2020
106
0
Never
Not a member of Pastebin yet? Sign Up, it unlocks many cool features!
Lua 77.65 KB | None | 0 0
  1. -- Sometimes persistent ones don't get created.
  2. local dummy = CreateClientConVar("_zs_dummyconvar", 1, false, false)
  3. local oldCreateClientConVar = CreateClientConVar
  4. function CreateClientConVar(...)
  5.     return oldCreateClientConVar(...) or dummy
  6. end
  7.  
  8. include("shared.lua")
  9. include("client/cl_draw.lua")
  10. include("client/cl_util.lua")
  11. include("client/cl_options.lua")
  12. include("client/cl_scoreboard.lua")
  13. include("client/cl_targetid.lua")
  14. include("client/cl_postprocess.lua")
  15.  
  16.  
  17. include("meta/obj_entity_extend_cl.lua")
  18. include("meta/obj_player_extend_cl.lua")
  19. include("meta/obj_weapon_extend_cl.lua")
  20.  
  21. include("client/vgui/dgamestate.lua")
  22. include("client/vgui/dteamcounter.lua")
  23. include("client/vgui/dmodelpanelex.lua")
  24. include("client/vgui/dammocounter.lua")
  25. include("client/vgui/dteamheading.lua")
  26. include("client/vgui/dmodelkillicon.lua")
  27. include("client/vgui/dexroundedpanel.lua")
  28. include("client/vgui/dexroundedframe.lua")
  29. include("client/vgui/dexrotatedimage.lua")
  30. include("client/vgui/dexnotificationslist.lua")
  31. include("client/vgui/dexchanginglabel.lua")
  32. include("client/vgui/mainmenu.lua")
  33. include("client/vgui/pmainmenu.lua")
  34. include("client/vgui/poptions.lua")
  35. include("client/vgui/phelp.lua")
  36. include("client/vgui/pclassselect.lua")
  37. include("client/vgui/pweapons.lua")
  38. include("client/vgui/pendboard.lua")
  39. include("client/vgui/pworth.lua")
  40. include("client/vgui/ppointshop.lua")
  41. include("client/vgui/pmutationshop.lua")
  42. include("client/vgui/dpingmeter.lua")
  43. include("client/vgui/dsidemenu.lua")
  44. include("client/vgui/changeteam.lua")
  45. include("client/vgui/zshealtharea.lua")
  46.  
  47. include("client/cl_dermaskin.lua")
  48. include("client/cl_deathnotice.lua")
  49. include("client/cl_floatingscore.lua")
  50. include("client/cl_hint.lua")
  51. include("client/cl_extras.lua")
  52.  
  53. include("zombieescape/cl_zombieescape.lua")
  54.  
  55. w, h = ScrW(), ScrH()
  56.  
  57. UsedMutations = {}
  58.  
  59. MySelf = MySelf or NULL
  60. hook.Add("InitPostEntity", "GetLocal", function()
  61.     MySelf = LocalPlayer()
  62.  
  63.     GAMEMODE.HookGetLocal = GAMEMODE.HookGetLocal or (function(g) end)
  64.     gamemode.Call("HookGetLocal", MySelf)
  65.     RunConsoleCommand("initpostentity")
  66. end)
  67.  
  68. -- Remove when model decal crash is fixed.
  69. function util.Decal()
  70. end
  71.  
  72. -- Save on global lookup time.
  73. local render = render
  74. local surface = surface
  75. local draw = draw
  76. local cam = cam
  77. local player = player
  78. local ents = ents
  79. local util = util
  80. local math = math
  81. local string = string
  82. local bit = bit
  83. local gamemode = gamemode
  84. local hook = hook
  85. local Vector = Vector
  86. local VectorRand = VectorRand
  87. local Angle = Angle
  88. local AngleRand = AngleRand
  89. local Entity = Entity
  90. local Color = Color
  91. local FrameTime = FrameTime
  92. local RealTime = RealTime
  93. local CurTime = CurTime
  94. local SysTime = SysTime
  95. local EyePos = EyePos
  96. local EyeAngles = EyeAngles
  97. local pairs = pairs
  98. local ipairs = ipairs
  99. local tostring = tostring
  100. local tonumber = tonumber
  101. local type = type
  102. local ScrW = ScrW
  103. local ScrH = ScrH
  104. local TEXT_ALIGN_CENTER = TEXT_ALIGN_CENTER
  105. local TEXT_ALIGN_LEFT = TEXT_ALIGN_LEFT
  106. local TEXT_ALIGN_RIGHT = TEXT_ALIGN_RIGHT
  107. local TEXT_ALIGN_TOP = TEXT_ALIGN_TOP
  108. local TEXT_ALIGN_BOTTOM = TEXT_ALIGN_BOTTOM
  109.  
  110. local TEAM_HUMAN = TEAM_HUMAN
  111. local TEAM_REDEEMER = TEAM_REDEEMER
  112. local TEAM_UNDEAD = TEAM_UNDEAD
  113. local translate = translate
  114.  
  115. local COLOR_PURPLE = COLOR_PURPLE
  116. local COLOR_GRAY = COLOR_GRAY
  117. local COLOR_RED = COLOR_RED
  118. local COLOR_DARKRED = COLOR_DARKRED
  119. local COLOR_DARKGREEN = COLOR_DARKGREEN
  120. local COLOR_GREEN = COLOR_GREEN
  121. local COLOR_WHITE = COLOR_WHITE
  122.  
  123. local surface_SetFont = surface.SetFont
  124. local surface_SetTexture = surface.SetTexture
  125. local surface_SetMaterial = surface.SetMaterial
  126. local surface_SetDrawColor = surface.SetDrawColor
  127. local surface_DrawRect = surface.DrawRect
  128. local surface_DrawOutlinedRect = surface.DrawOutlinedRect
  129. local surface_DrawTexturedRect = surface.DrawTexturedRect
  130. local surface_DrawTexturedRectRotated = surface.DrawTexturedRectRotated
  131. local surface_DrawTexturedRectUV = surface.DrawTexturedRectUV
  132. local surface_PlaySound = surface.PlaySound
  133.  
  134. local draw_SimpleText = draw.SimpleText
  135. local draw_SimpleTextBlurry = draw.SimpleTextBlurry
  136. local draw_SimpleTextBlur = draw.SimpleTextBlur
  137. local draw_GetFontHeight = draw.GetFontHeight
  138.  
  139. -- Flashlight sound
  140. local flashsound = Sound('items/flashlight1.wav')
  141. local flashlight
  142. local flashlight_Active = false
  143.  
  144. local MedicalAuraDistance = 800 ^ 2
  145.  
  146. local M_Player = FindMetaTable("Player")
  147. local P_Team = M_Player.Team
  148. local E_meta = FindMetaTable("Entity")
  149. local E_IsValid = E_meta.IsValid
  150.  
  151. GM.LifeStatsBrainsEaten = 0
  152. GM.LifeStatsHumanDamage = 0
  153. GM.LifeStatsBarricadeDamage = 0
  154. GM.InputMouseX = 0
  155. GM.InputMouseY = 0
  156. GM.LastTimeDead = 0
  157. GM.LastTimeAlive = 0
  158. GM.HeartBeatTime = 0
  159. GM.FOVLerp = 1
  160. GM.HurtEffect = 0
  161. GM.PrevHealth = 0
  162. GM.SuppressArsenalTime = 0
  163. GM.ZombieThirdPerson = false
  164. GM.Beats = {}
  165.  
  166. GM.DeathFog = 0
  167. GM.FogStart = 0
  168. GM.FogEnd = 8000
  169. GM.FogRed = 30
  170. GM.FogGreen = 30
  171. GM.FogBlue = 30
  172.  
  173. function GM:ClickedPlayerButton(pl, button)
  174. end
  175.  
  176. function GM:ClickedEndBoardPlayerButton(pl, button)
  177. end
  178.  
  179. function GM:CenterNotify(...)
  180.     if self.CenterNotificationHUD and self.CenterNotificationHUD:Valid() then
  181.         return self.CenterNotificationHUD:AddNotification(...)
  182.     end
  183. end
  184.  
  185. function GM:TopNotify(...)
  186.     if self.TopNotificationHUD and self.TopNotificationHUD:Valid() then
  187.         return self.TopNotificationHUD:AddNotification(...)
  188.     end
  189. end
  190.  
  191. function GM:_InputMouseApply(cmd, x, y, ang)
  192.     if MySelf:KeyDown(IN_WALK) and MySelf:IsHolding() then
  193.         self.InputMouseX = math.NormalizeAngle(self.InputMouseX - x * 0.02 * GAMEMODE.PropRotationSensitivity)
  194.         self.InputMouseY = math.NormalizeAngle(self.InputMouseY - y * 0.02 * GAMEMODE.PropRotationSensitivity)
  195.  
  196.         local snap = GAMEMODE.PropRotationSnap
  197.         local snapanglex, snapangley = self.InputMouseX, self.InputMouseY
  198.         if snap > 0 then
  199.             snapanglex = Angle(self.InputMouseX, 0, 0):SnapTo("p", snap).p
  200.             snapangley = Angle(self.InputMouseY, 0, 0):SnapTo("p", snap).p
  201.         end
  202.  
  203.         RunConsoleCommand("_zs_rotateang", snapanglex, snapangley)
  204.         return true
  205.     end
  206. end
  207.  
  208. function GM:_GUIMousePressed(mc)
  209.     if self.HumanMenuPanel and self.HumanMenuPanel:Valid() and self.HumanMenuPanel:IsVisible() and MySelf:KeyDown(self.MenuKey) then
  210.         local dir = gui.ScreenToVector(gui.MousePos())
  211.         local ent = util.TraceLine({start = MySelf:EyePos(), endpos = MySelf:EyePos() + dir * self.CraftingRange, filter = MySelf, mask = MASK_SOLID}).Entity
  212.         if ent:IsValid() and not ent:IsPlayer() and (ent:GetMoveType() == MOVETYPE_NONE or ent:GetMoveType() == MOVETYPE_VPHYSICS) and ent:GetSolid() == SOLID_VPHYSICS then
  213.             if mc == MOUSE_LEFT then
  214.                 if ent == self.CraftingEntity then
  215.                     self.CraftingEntity = nil
  216.                 else
  217.                     self.CraftingEntity = ent
  218.                 end
  219.             elseif mc == MOUSE_RIGHT and self.CraftingEntity and self.CraftingEntity:IsValid() then
  220.                 RunConsoleCommand("_zs_craftcombine", self.CraftingEntity:EntIndex(), ent:EntIndex())
  221.                 self.CraftingEntity = nil
  222.             end
  223.         end
  224.     end
  225. end
  226.  
  227. function GM:TryHumanPickup(pl, entity)
  228. end
  229.  
  230. function GM:AddExtraOptions(list, window)
  231. end
  232.  
  233. function GM:SpawnMenuEnabled()
  234.     return false
  235. end
  236.  
  237. function GM:SpawnMenuOpen()
  238.     return false
  239. end
  240.  
  241. function GM:ContextMenuOpen()
  242.     return false
  243. end
  244.  
  245. function GM:HUDWeaponPickedUp(wep)
  246. end
  247.  
  248. function GM:_HUDWeaponPickedUp(wep)
  249.     if MySelf:Team() ~= TEAM_UNDEAD and not wep.NoPickupNotification then
  250.         self:Rewarded(wep:GetClass())
  251.     end
  252. end
  253.  
  254. function GM:HUDItemPickedUp(itemname)
  255. end
  256.  
  257. function GM:HUDAmmoPickedUp(itemname, amount)
  258. end
  259.  
  260. function GM:InitPostEntity()
  261.     if not self.HealthHUD and not GetConVar("zs_classichud"):GetBool() then
  262.         self.HealthHUD = vgui.Create("ZSHealthArea")
  263.     end
  264.  
  265.     self:LocalPlayerFound()
  266.  
  267.     self:EvaluateFilmMode()
  268.  
  269.     timer.Simple(2, function() GAMEMODE:GetFogData() end)
  270. end
  271.  
  272. function GM:SetupWorldFog()
  273.     if self.DeathFog == 0 then return end
  274.  
  275.     local power = self.DeathFog
  276.     local rpower = 1 - self.DeathFog
  277.  
  278.     local fogstart = self.FogStart * rpower
  279.     local fogend = self.FogEnd * rpower + 150 * power
  280.     local fogr = self.FogRed * rpower
  281.     local fogg = self.FogGreen * rpower + 40 * power
  282.     local fogb = self.FogBlue * rpower
  283.  
  284.     render.FogMode(1)
  285.  
  286.     render.FogStart(fogstart)
  287.     render.FogEnd(fogend)
  288.     render.FogColor(fogr, fogg, fogb)
  289.     render.FogMaxDensity(1)
  290.  
  291.     return true
  292. end
  293.  
  294. function GM:SetupSkyboxFog(skyboxscale)
  295.     if self.DeathFog == 0 then return end
  296.  
  297.     local power = self.DeathFog
  298.     local rpower = 1 - self.DeathFog
  299.  
  300.     local fogstart = self.FogStart * rpower
  301.     local fogend = self.FogEnd * rpower + 150 * power
  302.     local fogr = self.FogRed * rpower
  303.     local fogg = self.FogGreen * rpower + 40 * power
  304.     local fogb = self.FogBlue * rpower
  305.     local fogdensity = 1 - power * 0.1
  306.  
  307.     render.FogMode(1)
  308.  
  309.     render.FogStart(fogstart * skyboxscale)
  310.     render.FogEnd(fogend * skyboxscale)
  311.     render.FogColor(fogr, fogg, fogb)
  312.     render.FogMaxDensity(1)
  313.  
  314.     return true
  315. end
  316.  
  317. function GM:PreDrawSkyBox()
  318.     self.DrawingInSky = true
  319. end
  320.  
  321. local matSky = CreateMaterial("SkyOverride", "UnlitGeneric", {["$basetexture"] = "color/white", ["$vertexcolor"] = 1, ["$vertexalpha"] = 1, ["$model"] = 1})
  322. local colSky = Color(0, 30, 0)
  323. function GM:PostDrawSkyBox()
  324.     self.DrawingInSky = false
  325.  
  326.     if self.DeathFog == 0 then return end
  327.  
  328.     colSky.a = self.DeathFog * 230
  329.  
  330.     cam.Start3D(EyePos(), EyeAngles())
  331.         render.SuppressEngineLighting(true)
  332.  
  333.         render.SetMaterial(matSky)
  334.  
  335.         render.DrawQuadEasy(Vector(0, 0, 10240), Vector(0, 0, -1), 20480, 20480, colSky, 0)
  336.         render.DrawQuadEasy(Vector(0, 10240, 0), Vector(0, -1, 0), 20480, 20480, colSky, 0)
  337.         render.DrawQuadEasy(Vector(0, -10240, 0), Vector(0, 1, 0), 20480, 20480, colSky, 0)
  338.         render.DrawQuadEasy(Vector(10240, 0, 0), Vector(-1, 0, 0), 20480, 20480, colSky, 0)
  339.         render.DrawQuadEasy(Vector(-10240, 0, 0), Vector(1, 0, 0), 20480, 20480, colSky, 0)
  340.  
  341.         render.SuppressEngineLighting(false)
  342.     cam.End3D()
  343. end
  344.  
  345. function GM:GetFogData()
  346.     local fogstart, fogend = render.GetFogDistances()
  347.     local fogr, fogg, fogb = render.GetFogColor()
  348.  
  349.     self.FogStart = fogstart
  350.     self.FogEnd = fogend
  351.     self.FogRed = fogr
  352.     self.FogGreen = fogg
  353.     self.FogBlue = fogb
  354. end
  355.  
  356. local matAura = Material("models/debug/debugwhite")
  357. local skip = false
  358. function GM.PostPlayerDrawMedical(pl)
  359.     if not skip and pl:Team() ~= TEAM_UNDEAD and pl ~= LocalPlayer() then
  360.         local eyepos = EyePos()
  361.         local dist = pl:NearestPoint(eyepos):Distance(eyepos)
  362.         if dist < MedicalAuraDistance then
  363.             local green = pl:Health() / pl:GetMaxHealth()
  364.  
  365.             pl.SkipDrawHooks = true
  366.             skip = true
  367.  
  368.             render.SuppressEngineLighting(true)
  369.             render.ModelMaterialOverride(matAura)
  370.             render.SetBlend((1 - (dist / MedicalAuraDistance)) * 0.1 * (1 + math.abs(math.sin((CurTime() + pl:EntIndex()) * 4)) * 0.05))
  371.             render.SetColorModulation(1 - green, green, 0)
  372.                 pl:DrawModel()
  373.             render.SetColorModulation(1, 1, 1)
  374.             render.SetBlend(1)
  375.             render.ModelMaterialOverride()
  376.             render.SuppressEngineLighting(false)
  377.  
  378.             skip = false
  379.             pl.SkipDrawHooks = false
  380.         end
  381.     end
  382. end
  383.  
  384. function GM:OnReloaded()
  385.     self.BaseClass.OnReloaded(self)
  386.  
  387.     self:LocalPlayerFound()
  388. end
  389.  
  390. -- The whole point of this is so we don't need to check if the local player is valid 1000 times a second.
  391. function GM:LocalPlayerFound()
  392.     self.Think = self._Think
  393.     self.HUDShouldDraw = self._HUDShouldDraw
  394.     self.CachedFearPower = self._CachedFearPower
  395.     self.CalcView = self._CalcView
  396.     self.ShouldDrawLocalPlayer = self._ShouldDrawLocalPlayer
  397.     self.PostDrawOpaqueRenderables = self._PostDrawOpaqueRenderables
  398.     self.PostDrawTranslucentRenderables = self._PostDrawTranslucentRenderables
  399.     self.HUDPaint = self._HUDPaint
  400.     self.HUDPaintBackground = self._HUDPaintBackground
  401.     self.CreateMove = self._CreateMove
  402.     self.PrePlayerDraw = self._PrePlayerDraw
  403.     self.PostPlayerDraw = self._PostPlayerDraw
  404.     self.InputMouseApply = self._InputMouseApply
  405.     self.GUIMousePressed = self._GUIMousePressed
  406.     self.HUDWeaponPickedUp = self._HUDWeaponPickedUp
  407.  
  408.     LocalPlayer().LegDamage = 0
  409.  
  410.     if render.GetDXLevel() >= 80 then
  411.         self.RenderScreenspaceEffects = self._RenderScreenspaceEffects
  412.     end
  413. end
  414.  
  415. local currentpower = 0
  416. local spawngreen = 0
  417. local matFearMeter = Material("zombiesurvival/fearometer")
  418. local matNeedle = Material("zombiesurvival/fearometerneedle")
  419. local matEyeGlow = Material("Sprites/light_glow02_add_noz")
  420. local matSigil = Material("zombiesurvival/sigil.png")
  421. function GM:DrawFearMeter(power, screenscale)
  422.     if GAMEMODE.ZombieEscape then return end
  423.     if currentpower < power then
  424.         currentpower = math.min(power, currentpower + FrameTime() * (math.tan(currentpower) * 2 + 0.05))
  425.     elseif power < currentpower then
  426.         currentpower = math.max(power, currentpower - FrameTime() * (math.tan(currentpower) * 2 + 0.05))
  427.     end
  428.    
  429.     local sigilSizeMult = 1.25
  430.     local sigilWidth, sigilHeight = screenscale * (18 * sigilSizeMult), screenscale * (36 * sigilSizeMult)
  431.     local sigilFearSpacing = 32 * screenscale
  432.     local sigilOffsetX = sigilWidth + screenscale * 18
  433.     local sigilOffsetY = -52 * screenscale
  434.     if not self:GetUseSigils() or not (self.MaxSigils > 0) or not (#self:GetSigils() > 0) then
  435.         sigilHeight, sigilFearSpacing = 0, 0
  436.     end
  437.    
  438.     local size = 192 * screenscale
  439.     local half_size = size / 2
  440.     local mx, my = w / 2 - half_size, h - size - sigilHeight - sigilFearSpacing
  441.    
  442.     surface_SetMaterial(matFearMeter)
  443.     surface_SetDrawColor(140, 140, 140, 240)
  444.     surface_DrawTexturedRect(mx, my, size, size)
  445.     if currentpower >= 0.75 then
  446.         local pulse = CurTime() % 3 - 1
  447.         if pulse > 0 then
  448.             pulse = pulse ^ 2
  449.             local pulsesize = pulse * screenscale * 28
  450.             surface_SetDrawColor(140, 140, 140, 120 - pulse * 120)
  451.             surface_DrawTexturedRect(mx - pulsesize, my - pulsesize, size + pulsesize * 2, size + pulsesize * 2)
  452.         end
  453.     end
  454.    
  455.     surface_SetMaterial(matNeedle)
  456.     surface_SetDrawColor(160, 160, 160, 225)
  457.     local rot = math.Clamp((0.5 - currentpower) + math.sin(RealTime() * 10) * 0.01, -0.5, 0.5) * 300
  458.     surface_DrawTexturedRectRotated(w * 0.5 - math.max(0, rot * size * -0.0001), h - half_size - math.abs(rot) * size * 0.00015 - sigilHeight - sigilFearSpacing, size, size, rot)
  459.    
  460.     if MySelf:Team() == TEAM_UNDEAD then
  461.         if self:GetDynamicSpawning() and self:ShouldUseAlternateDynamicSpawn() then
  462.             local obs = MySelf:GetObserverTarget()
  463.             spawngreen = math.Approach(spawngreen, self:DynamicSpawnIsValid(obs and obs:IsValid() and obs:IsPlayer() and obs:Team() == TEAM_UNDEAD and obs or MySelf) and 1 or 0, FrameTime() * 4)
  464.            
  465.             local sy = my + size * 0.6953
  466.             local gsize = size * 0.085
  467.            
  468.             surface_SetMaterial(matEyeGlow)
  469.             surface_SetDrawColor(220 * (1 - spawngreen), 220 * spawngreen, 0, 240)
  470.             surface_DrawTexturedRectRotated(mx + size * 0.459, sy, gsize, gsize, 0)
  471.             surface_DrawTexturedRectRotated(mx + size * 0.525, sy, gsize, gsize, 0)
  472.         end
  473.        
  474.         if currentpower > 0 and not self.ZombieEscape then
  475.             draw_SimpleTextBlurry(translate.Format("resist_x", math.ceil(self:GetDamageResistance(currentpower) * 100)), "ZSDamageResistance", w * 0.5, my + size * 0.75, Color(currentpower * 200, 200 - currentpower * 200, 0, 255), TEXT_ALIGN_CENTER)
  476.         end
  477.     end
  478.    
  479.     if self:GetUseSigils() and self.MaxSigils > 0 then
  480.         local health, maxhealth, corrupt, damageflash, sigilX, sigilY, healthfrac, sigilLetter
  481.         local sigils = GAMEMODE.CachedSigils
  482.         local numSigils = #sigils
  483.         for k, sigil in ipairs(sigils) do
  484.             health = 0
  485.             maxhealth = 0
  486.             sigilLetter = ""
  487.             if sigil and sigil:IsValid() then
  488.                 health = sigil:GetSigilHealth()
  489.                 maxhealth = sigil:GetSigilMaxHealth()
  490.                 sigilLetter = sigil:GetSigilLetter()
  491.             end
  492.            
  493.             if health >= 0 then
  494.                
  495.                 sigilX = w/2 - (sigilWidth + sigilOffsetX * (numSigils - 1)) / 2 + (k-1) * sigilOffsetX
  496.                 sigilY = h - sigilHeight + sigilOffsetY
  497.                
  498.                 if sigil and sigil:IsValid() then
  499.                     damageflash = math.min((CurTime() - sigil:GetSigilLastDamaged()) * 2, 1) * 255
  500.                 else
  501.                     damageflash = 255
  502.                 end
  503.                 healthfrac = health / maxhealth
  504.                 if corrupt then
  505.                     surface_SetDrawColor((255 - damageflash) * healthfrac, damageflash * healthfrac, 0, 220)
  506.                 else
  507.                     surface_SetDrawColor((255 - damageflash) * healthfrac, damageflash * healthfrac, 220, 220)
  508.                 end
  509.                
  510.                 surface_SetMaterial(matSigil)
  511.                 surface_DrawTexturedRect(sigilX, sigilY, sigilWidth, sigilHeight)
  512.                 draw.SimpleText(sigilLetter, "ZS3D2DFontSmallest", sigilX + sigilWidth/2, sigilY + sigilHeight, Vector(255, 255, 255, 255), TEXT_ALIGN_CENTER)
  513.             end
  514.         end
  515.     end
  516. end
  517.  
  518. function GM:GetDynamicSpawning()
  519.     return not GetGlobalBool("DynamicSpawningDisabled", false)
  520. end
  521.  
  522. function GM:TrackLastDeath()
  523.     if MySelf:Alive() then
  524.         self.LastTimeAlive = CurTime()
  525.     else
  526.         self.LastTimeDead = CurTime()
  527.     end
  528. end
  529.  
  530. function GM:IsClassicMode()
  531.     return GetGlobalBool("classicmode", false)
  532. end
  533.  
  534. function GM:IsRedeemMode()
  535.     return GetGlobalBool("redeemmode", false)
  536. end
  537.  
  538. function GM:IsBabyMode()
  539.     return GetGlobalBool("babymode", false)
  540. end
  541.  
  542. function GM:PostRender()
  543.     if self.m_ZombieVision and MySelf:IsValid() and MySelf:Team() ~= TEAM_HUMAN then
  544.         local eyepos = EyePos()
  545.         local eyedir = EyeAngles():Forward()
  546.         --local tr = util.TraceLine({start = eyepos, endpos = eyepos + eyedir * 128, mask = MASK_SOLID_BRUSHONLY})
  547.  
  548.         local dlight = DynamicLight(MySelf:EntIndex())
  549.         if dlight then
  550.             dlight.Pos = MySelf:GetShootPos()
  551.             dlight.r = 255
  552.             dlight.g = 218
  553.             dlight.b = 74
  554.             dlight.Brightness = 0
  555.             dlight.Size = 2048
  556.             dlight.Decay = 900
  557.             dlight.DieTime = CurTime() + 2
  558.         end
  559.     end
  560. end
  561.  
  562. -- Create the flashlight
  563. local function CreateFlashlight()
  564.     local flash = ProjectedTexture()
  565.     flash:SetTexture('effects/flashlight001')
  566.     flash:SetBrightness(1)
  567.     flash:SetFarZ(650)
  568.     flash:SetFOV(70)
  569.     flash:SetColor(color_white)
  570.     flash:SetEnableShadows(false)
  571.  
  572.     return flash
  573. end
  574.  
  575. function GM:CreateFlashlightCheck()
  576.     -- Only turn on flashlight for Human
  577.     if MySelf:IsValid() and P_Team(MySelf) == TEAM_HUMAN then
  578.         flashlight_Active = !flashlight_Active
  579.         surface.PlaySound(flashsound)
  580.     end
  581. end
  582.  
  583. local lastwarntim = -1
  584. local NextGas = 0
  585. function GM:_Think()
  586.     if self:GetEscapeStage() == ESCAPESTAGE_DEATH then
  587.         self.DeathFog = math.min(self.DeathFog + FrameTime() / 5, 1)
  588.  
  589.         if CurTime() >= NextGas then
  590.             NextGas = CurTime() + 0.01
  591.  
  592.             local eyepos = EyePos()
  593.  
  594.             local emitter = ParticleEmitter(eyepos)
  595.  
  596.             for i=1, 3 do
  597.                 local randdir = VectorRand()
  598.                 randdir.z = math.abs(randdir.z)
  599.                 randdir:Normalize()
  600.                 local emitpos = eyepos + randdir * math.Rand(0, 1200)
  601.  
  602.                 local particle = emitter:Add("particles/smokey", emitpos)
  603.                 particle:SetVelocity(randdir * math.Rand(8, 256))
  604.                 particle:SetAirResistance(16)
  605.                 particle:SetDieTime(math.Rand(2.2, 3.5))
  606.                 particle:SetStartAlpha(math.Rand(70, 90))
  607.                 particle:SetEndAlpha(0)
  608.                 particle:SetStartSize(1)
  609.                 particle:SetEndSize(math.Rand(150, 325))
  610.                 particle:SetRoll(math.Rand(0, 360))
  611.                 particle:SetRollDelta(math.Rand(-1, 1))
  612.                 particle:SetColor(0, math.Rand(20, 45), 0)
  613.             end
  614.  
  615.             emitter:Finish()
  616.         end
  617.     elseif self.DeathFog > 0 then
  618.         self.DeathFog = math.max(self.DeathFog - FrameTime() / 5, 0)
  619.     end
  620.  
  621.     local health = MySelf:Health()
  622.     if self.PrevHealth and health < self.PrevHealth then
  623.         self.HurtEffect = math.min(self.HurtEffect + (self.PrevHealth - health) * 0.02, 1.5)
  624.     elseif self.HurtEffect > 0 then
  625.         self.HurtEffect = math.max(0, self.HurtEffect - FrameTime() * 0.65)
  626.     end
  627.     self.PrevHealth = health
  628.  
  629.     self:TrackLastDeath()
  630.  
  631.     local endtime = self:GetWaveActive() and self:GetWaveEnd() or self:GetWaveStart()
  632.     if endtime ~= -1 then
  633.         local timleft = math.max(0, endtime - CurTime())
  634.         if timleft <= 10 and lastwarntim ~= math.ceil(timleft) then
  635.             lastwarntim = math.ceil(timleft)
  636.             if 0 < lastwarntim then
  637.                 surface_PlaySound("buttons/lightswitch2.wav")
  638.             end
  639.         end
  640.     end
  641.  
  642.     local myteam = MySelf:Team()
  643.  
  644.     self:PlayBeats(myteam, self:CachedFearPower())
  645.  
  646.     if myteam ~= TEAM_UNDEAD then
  647.         local wep = MySelf:GetActiveWeapon()
  648.         if wep:IsValid() and wep.GetIronsights and wep:GetIronsights() then
  649.             self.FOVLerp = math.Approach(self.FOVLerp, wep.IronsightsMultiplier or 0.6, FrameTime() * 4)
  650.         elseif self.FOVLerp ~= 1 then
  651.             self.FOVLerp = math.Approach(self.FOVLerp, 1, FrameTime() * 5)
  652.         end
  653.  
  654.         if MySelf:GetBarricadeGhosting() then
  655.             MySelf:BarricadeGhostingThink()
  656.         end
  657.     else
  658.         self.HeartBeatTime = self.HeartBeatTime + (6 + self:CachedFearPower() * 5) * FrameTime()
  659.  
  660.         if not MySelf:Alive() then
  661.             self:ToggleZombieVision(false)
  662.         end
  663.     end
  664.  
  665.     for _, pl in pairs(player.GetAll()) do
  666.         if pl:Team() == TEAM_UNDEAD then
  667.             local tab = pl:GetZombieClassTable()
  668.             if tab.BuildBonePositions then
  669.                 pl.WasBuildingBonePositions = true
  670.                 pl:ResetBones()
  671.                 tab.BuildBonePositions(tab, pl)
  672.             elseif pl.WasBuildingBonePositions then
  673.                 pl.WasBuildingBonePositions = nil
  674.                 pl:ResetBones()
  675.             end
  676.         elseif pl.WasBuildingBonePositions then
  677.             pl.WasBuildingBonePositions = nil
  678.             pl:ResetBones()
  679.         end
  680.     end
  681. end
  682.  
  683. function GM:ShouldPlayBeats(teamid, fear)
  684.     return not self.RoundEnded and not self.ZombieEscape and not GetGlobalBool("beatsdisabled", false)
  685. end
  686.  
  687. local cv_ShouldPlayMusic = CreateClientConVar("zs_playmusic", 1, true, false)
  688. local NextBeat = 0
  689. local LastBeatLevel = 0
  690. function GM:PlayBeats(teamid, fear)
  691.     if RealTime() <= NextBeat or not gamemode.Call("ShouldPlayBeats", teamid, fear) then return end
  692.  
  693.     if LASTHUMAN and cv_ShouldPlayMusic:GetBool() then
  694.         MySelf:EmitSound(self.LastHumanSound, 0, 100, self.BeatsVolume)
  695.         NextBeat = RealTime() + (self.SoundDuration[snd] or SoundDuration(self.LastHumanSound)) - 0.025
  696.         return
  697.     end
  698.  
  699.     if fear <= 0 or not self.BeatsEnabled then return end
  700.  
  701.     local beats = self.Beats[teamid == TEAM_HUMAN and self.BeatSetHuman or self.BeatSetZombie]
  702.     if not beats then return end
  703.  
  704.     LastBeatLevel = math.Approach(LastBeatLevel, math.ceil(fear * 10), 3)
  705.  
  706.     local snd = beats[LastBeatLevel]
  707.     if snd then
  708.         MySelf:EmitSound(snd, 0, 100, self.BeatsVolume)
  709.         NextBeat = RealTime() + (self.SoundDuration[snd] or SoundDuration(snd)) - 0.025
  710.     end
  711. end
  712.  
  713. local OSTintro = 0
  714. local colHealth = Color(0, 130, 0, 240)
  715. local colPoison = Color(220, 220, 0, 240)
  716. function GM:DrawHealthBar(x, y, health, maxhealth, bartexture, screenscale, poisondamage)
  717.     health = math.max(0, health)
  718.  
  719.     local screenscale = BetterScreenScale() -- used for screenscaling
  720.     local wid, hei = 512 * screenscale, 256 * screenscale -- size of HUD element in bottom left
  721.     if health > 0 then
  722.         local healthfrac = math.min(1, health / maxhealth)
  723.         local barx = x + screenscale * 72
  724.         local bary = y + screenscale * 99
  725.         local maxbarwidth = screenscale * 405
  726.         local barwidth = maxbarwidth * healthfrac
  727.         colHealth.g = 130 * healthfrac
  728.         colHealth.r = 130 - colHealth.g
  729.         surface.SetDrawColor(colHealth)
  730.         surface.DrawRect(barx, bary, barwidth, screenscale * 26)
  731.         if poisondamage then
  732.             surface.SetDrawColor(colPoison)
  733.             local poisonbarwidth = maxbarwidth * (poisondamage / maxhealth)
  734.             surface.DrawRect(barx + barwidth, bary, math.min(poisonbarwidth, maxbarwidth - barwidth), screenscale * 16)
  735.         end
  736.     end
  737.  
  738.     surface.SetTexture(bartexture)
  739.     surface.SetDrawColor(150, 150, 150, 240)
  740.     surface.DrawTexturedRect(x, y, wid, hei)
  741.  
  742.     draw.SimpleText(translate.Get("health"), "ZSHUDFontSmall", x + screenscale * 70, y + screenscale * 55, COLOR_GRAY, TEXT_ALIGN_LEFT)
  743.     draw.SimpleText(health, "ZSHUDFont", x + screenscale * 180, y + screenscale * 48, colHealth, TEXT_ALIGN_LEFT)
  744.  
  745.     local w, h = ScrW(), ScrH() -- Get Screen Size of local player
  746.  
  747.     --Points
  748.     if MySelf:Team() ~= TEAM_UNDEAD then
  749.         draw_SimpleText(translate.Format("points_x", MySelf:GetPoints().." / "..MySelf:Frags().." / "..MySelf:GetPoints().." + "), "ZSHUDFontSmallNS",  x + screenscale * 70, y + screenscale * 133, COLOR_GRAY, TEXT_ALIGN_LEFT)
  750.         elseif MySelf:Team() == TEAM_UNDEAD then
  751.         draw_SimpleText(translate.Format("brains_eaten_x", MySelf:Frags()), "ZSHUDFontSmallNS",  x + screenscale * 70, y + screenscale * 133, COLOR_GRAY, TEXT_ALIGN_LEFT)
  752.         else
  753.     end
  754.  
  755.     local wavenumber = GAMEMODE:GetWave()
  756.  
  757.     if wavenumber > 0 and wavenumber < 7 then --show wave count when wave 1 starts hide the wave count after 6 rounds
  758.         draw_SimpleText(wavenumber, "ZSHUDFontSmallNS", x + screenscale * 475, y + screenscale * 133, COLOR_GRAY, TEXT_ALIGN_CENTER)
  759.         draw_SimpleText(translate.Get("wave"), "ZSHUDFontSmallNS", x + screenscale * 430, y + screenscale * 133, COLOR_GRAY, TEXT_ALIGN_CENTER)
  760.     end
  761.  
  762.     --Intermission Checker Because people are thick yolo
  763.     if wavenumber > 0 and wavenumber < 7 and not GAMEMODE:GetWaveActive() then
  764.  
  765.     local col
  766.     local timeleft = math.max(0, GAMEMODE:GetWaveStart() - CurTime())
  767.     if timeleft < 10 then
  768.         local glow = math.sin(RealTime() * 8) * 200 + 255
  769.             col = Color(255, glow, glow)
  770.         else
  771.             col = COLOR_GRAY
  772.     end
  773.  
  774.     local wavestart = GAMEMODE:GetWaveStart()
  775.     if wavestart ~= -1 then
  776.         local timeleft = math.max(0, wavestart - CurTime())
  777.     end
  778.  
  779.     draw_SimpleText(translate.Get("wave_intermission"), "ZSHUDFontSmallNS", x + screenscale * 70, y + screenscale * 23, COLOR_YELLOW, TEXT_ALIGN_LEFT)
  780.     draw_SimpleText(util.ToMinutesSeconds(timeleft), "ZSHUDFontSmallNS", x + screenscale * 320, y + screenscale * 25, 10 < timeleft and COLOR_YELLOW or Color(255, 0, 0, math.abs(math.sin(RealTime() * 8)) * 180 + 40), TEXT_ALIGN_LEFT)
  781.  
  782.     end
  783.  
  784.     --Wave Timer
  785.     if wavenumber > 0 and wavenumber < 7 and GAMEMODE:GetWave() <= 0 then
  786.         local col
  787.         local timeleft = math.max(0, GAMEMODE:GetWaveStart() - CurTime())
  788.         if timeleft < 10 then
  789.             local glow = math.sin(RealTime() * 8) * 200 + 255
  790.             col = Color(255, glow, glow)
  791.         else
  792.             col = COLOR_GRAY
  793.         end
  794.  
  795.     draw_SimpleText(util.ToMinutesSeconds(timeleft), "ZSHUDFontSmallNS", x + screenscale * 483, y + screenscale * 60, col, TEXT_ALIGN_RIGHT)
  796.  
  797.     elseif GAMEMODE:GetWaveActive() then
  798.         local waveend = GAMEMODE:GetWaveEnd()
  799.         if waveend ~= -1 then
  800.             local timeleft = math.max(0, waveend - CurTime())
  801.             draw_SimpleText(util.ToMinutesSeconds(timeleft), "ZSHUDFontSmallNS", x + screenscale * 483, y + screenscale * 60, 10 < timeleft and COLOR_GRAY or Color(255, 0, 0, math.abs(math.sin(RealTime() * 8)) * 180 + 40), TEXT_ALIGN_RIGHT)
  802.         end
  803.     else
  804.         local wavestart = GAMEMODE:GetWaveStart()
  805.         if wavestart ~= -1 then
  806.             local timeleft = math.max(0, wavestart - CurTime())
  807.                 end
  808.             end
  809.  
  810.             --Intro Song
  811.             if wavenumber >= 1 and OSTintro == 0 and MySelf:GetInfo("zs_intro") == "1" and not self.ZombieEscape then
  812.             if OSTintro == 0 then
  813.             MySelf:EmitSound("zombiesurvival/zsrintrov2.mp3", 50, 100, 0.5)
  814.             OSTintro = 1 -- So it doesn't repeat the track again.
  815.         end
  816.     end
  817. end
  818.  
  819.  
  820. --TODO: Put this packup bar inside status_packup!
  821. --local colPackUp = Color(20, 255, 20, 220)
  822. --local colPackUpNotOwner = Color(255, 240, 10, 220)
  823. --function GM:DrawPackUpBar(x, y, fraction, notowner, screenscale)
  824. --  local col = notowner and colPackUpNotOwner or colPackUp
  825. --
  826. --  local maxbarwidth = 270 * screenscale
  827. --  local barheight = 11 * screenscale
  828. --  local barwidth = maxbarwidth * math.Clamp(fraction, 0, 1)
  829. --  local startx = x - maxbarwidth * 0.5
  830. --
  831. --  surface_SetDrawColor(0, 0, 0, 220)
  832. --  surface_DrawRect(startx, y, maxbarwidth, barheight)
  833. --  surface_SetDrawColor(col)
  834. --  surface_DrawRect(startx + 3, y + 3, barwidth - 6, barheight - 6)
  835. --  surface_DrawOutlinedRect(startx, y, maxbarwidth, barheight)
  836. --
  837. --  draw_SimpleText(notowner and CurTime() % 2 < 1 and translate.Format("requires_x_people", 4) or notowner and translate.Get("packing_others_object") or translate.Get("packing"), "ZSHUDFontSmall", x, y - draw_GetFontHeight("ZSHUDFontSmall") - 2, col, TEXT_ALIGN_CENTER)
  838. --end
  839.  
  840. local texHumanHealthBar = surface.GetTextureID("zombiesurvival/healthbar__human")
  841. function GM:HumanHUD(screenscale)
  842.     local curtime = CurTime()
  843.     local w, h = ScrW(), ScrH()
  844.  
  845.     if GetConVar("zs_classichud"):GetBool() then
  846.     self:DrawHealthBar(screenscale * 24, h - 272 * screenscale, MySelf:Health(), MySelf:GetMaxHealth(), texHumanHealthBar, screenscale, MySelf:GetPoisonDamage())
  847.     end
  848.  
  849.  
  850.     if not self.RoundEnded then
  851.         if self:GetWave() == 0 and not self:GetWaveActive() then
  852.             local txth = draw_GetFontHeight("ZS3D2DFontSmall")
  853.             draw_SimpleTextBlurry(translate.Get("invasion_in"), "ZS3D2DFontSmall", w * 0.5, h * 0.25, COLOR_GRAY, TEXT_ALIGN_CENTER)
  854.             draw_SimpleTextBlurry(util.ToMinutesSeconds(math.max(0, self:GetWaveStart() - curtime)), "ZS3D2DFontSmall", w * 0.5, h * 0.25 + txth, COLOR_DARKRED, TEXT_ALIGN_CENTER)
  855.  
  856.             local desiredzombies = self:GetDesiredStartingZombies()
  857.  
  858.             local txth2 = draw_GetFontHeight("ZSHUDFontSmall")
  859.             draw_SimpleTextBlurry(translate.Get("stay_from_zombie_spawns"), "ZSHUDFontSmall", w * 0.5, h * 0.75, COLOR_GRAY, TEXT_ALIGN_CENTER)
  860.             draw_SimpleTextBlurry(translate.Get("zombie_volunteers"), "ZSHUDFontSmall", w * 0.5, h * 0.75 + txth2, COLOR_GRAY, TEXT_ALIGN_CENTER)
  861.  
  862.             local txth3 = draw_GetFontHeight("ZSHUDFontTiny")
  863.  
  864.             local y = h * 0.78 + txth3 * 2
  865.             for i, pl in ipairs(self.ZombieVolunteers) do
  866.                 if pl:IsValid() then
  867.                     draw_SimpleTextBlurry(pl:Name(), "ZSHUDFontTiny", w * 0.5, y, pl == MySelf and COLOR_RED or pl:IsFriend() and COLOR_LIMEGREEN or COLOR_GRAY, TEXT_ALIGN_CENTER)
  868.                     y = y + txth3
  869.                 end
  870.             end
  871.         end
  872.     end
  873.  
  874.     if gamemode.Call("PlayerCanPurchase", MySelf) then
  875.         if self:GetWaveActive() then
  876.             draw_SimpleTextBlurry(translate.Get("press_f2_for_the_points_shop"), "ZSHUDFontSmall", w * 0.5, 8, COLOR_GRAY, TEXT_ALIGN_CENTER)
  877.         else
  878.             local th = draw_GetFontHeight("ZSHUDFontSmall")
  879.             draw_SimpleTextBlurry(translate.Get("press_f2_for_the_points_shop"), "ZSHUDFontSmall", w * 0.5, 8, COLOR_GRAY, TEXT_ALIGN_CENTER)
  880.             draw_SimpleTextBlurry(translate.Format("x_discount_for_buying_between_waves", self.ArsenalCrateDiscountPercentage), "ZSHUDFontSmall", w * 0.5, 9 + th, COLOR_GRAY, TEXT_ALIGN_CENTER)
  881.         end
  882.     end
  883. end
  884.  
  885. function GM:HUDPaint()
  886. end
  887.  
  888. function GM:_HUDPaint()
  889.     if self.FilmMode then return end
  890.  
  891.     local screenscale = BetterScreenScale()
  892.  
  893.     local myteam = MySelf:Team()
  894.  
  895.     if GetConVar("zs_classichud"):GetBool() then
  896.         if self.HealthHUD and self.HealthHUD:Valid() and self.HealthHUD:IsVisible() then
  897.             self.HealthHUD:SetVisible(false)
  898.         end
  899.     end
  900.    
  901.     self:HUDDrawTargetID(myteam, screenscale)
  902.     if self:GetWave() > 0 and myteam ~= TEAM_SPECTATOR then
  903.         self:DrawFearMeter(self:CachedFearPower(), screenscale * 1)
  904.     end
  905.     if myteam == TEAM_SPECTATOR then return end
  906.     if myteam == TEAM_UNDEAD then
  907.         self:ZombieHUD(screenscale * 0.75)
  908.     else
  909.         self:HumanHUD(screenscale * 0.75)
  910.     end
  911.     if GetGlobalBool("classicmode") then
  912.         draw_SimpleTextBlurry(translate.Get("classic_mode"), "ZSHUDFontSmaller", 4, ScrH() - 4, COLOR_GRAY, TEXT_ALIGN_LEFT, TEXT_ALIGN_TOP)
  913.     end
  914.  
  915. end
  916.  
  917. function GM:ZombieObserverHUD(obsmode)
  918.     local w, h = ScrW(), ScrH()
  919.     local texh = draw_GetFontHeight("ZSHUDFontSmall")
  920.  
  921.     local dyn
  922.  
  923.     if obsmode == OBS_MODE_CHASE then
  924.         local target = MySelf:GetObserverTarget()
  925.         if target and target:IsValid() then
  926.             if target:IsPlayer() and target:Team() == TEAM_UNDEAD then
  927.                 draw_SimpleTextBlur(translate.Format("observing_x", target:Name(), math.max(0, target:Health())), "ZSHUDFontSmall", w * 0.5, h * 0.75 - texh - 32, COLOR_DARKRED, TEXT_ALIGN_CENTER)
  928.             end
  929.  
  930.             dyn = self:GetDynamicSpawning() and self:DynamicSpawnIsValid(target)
  931.         end
  932.     end
  933.  
  934.     if self:GetWaveActive() then
  935.         draw_SimpleTextBlur(dyn and translate.Get("press_lmb_to_spawn_on_them") or translate.Get("press_lmb_to_spawn"), "ZSHUDFontSmall", w * 0.5, h * 0.75, dyn and COLOR_DARKGREEN or COLOR_DARKRED, TEXT_ALIGN_CENTER)
  936.     end
  937.  
  938.     local space = texh + 8
  939.     draw_SimpleTextBlur(translate.Get("press_rmb_to_cycle_targets"), "ZSHUDFontSmall", w * 0.5, h * 0.75 + space, COLOR_DARKRED, TEXT_ALIGN_CENTER)
  940.     draw_SimpleTextBlur(translate.Get("press_reload_to_spawn_at_normal_point"), "ZSHUDFontSmall", w * 0.5, h * 0.75 + space * 2, COLOR_DARKRED, TEXT_ALIGN_CENTER)
  941.     draw_SimpleTextBlur(translate.Get("press_jump_to_free_roam"), "ZSHUDFontSmall", w * 0.5, h * 0.75 + space * 3, COLOR_DARKRED, TEXT_ALIGN_CENTER)
  942.  
  943.     for _, ent in pairs(ents.FindByClass("prop_thrownbaby")) do
  944.         if ent:GetSettled() then
  945.             draw_SimpleTextBlur(translate.Format("press_walk_to_spawn_as_x", self.ZombieClasses["Gore Child"].Name), "ZSHUDFontSmall", w * 0.5, h * 0.75 + space * 3, COLOR_DARKRED, TEXT_ALIGN_CENTER)
  946.             break
  947.         end
  948.     end
  949. end
  950.  
  951. local colLifeStats = Color(255, 0, 0, 255)
  952. function GM:ZombieHUD(screenscale)
  953.     local classtab = self.ZombieClasses[MySelf:GetZombieClass()]
  954.     local curtime = CurTime()
  955.  
  956.     if GetConVar("zs_classichud"):GetBool() then
  957.     self:DrawHealthBar(screenscale * 24, h - 272 * screenscale, MySelf:Health(), classtab.Health, texHumanHealthBar, screenscale)
  958.     end
  959.    
  960.     if not self.RoundEnded then
  961.         if self:GetWave() == 0 and not self:GetWaveActive() then
  962.  
  963.             local txth = draw_GetFontHeight("ZS3D2DFont")
  964.             draw_SimpleTextBlurry(util.ToMinutesSeconds(math.max(0, self:GetWaveStart() - curtime)), "ZS3D2DFont", w * 0.5, h * 0.25 + txth, COLOR_DARKRED, TEXT_ALIGN_CENTER)
  965.  
  966.             local desiredzombies = self:GetDesiredStartingZombies()
  967.  
  968.             local txth2 = draw_GetFontHeight("ZSHUDFontSmall")
  969.             draw_SimpleTextBlurry(translate.Get("stay_from_zombie_spawns"), "ZSHUDFontSmall", w * 0.5, h * 0.75, COLOR_GRAY, TEXT_ALIGN_CENTER)
  970.             draw_SimpleTextBlurry(translate.Get("zombie_volunteers"), "ZSHUDFontSmall", w * 0.5, h * 0.75 + txth2, COLOR_GRAY, TEXT_ALIGN_CENTER)
  971.  
  972.             local txth3 = draw_GetFontHeight("ZSHUDFontTiny")
  973.  
  974.             local y = h * 0.78 + txth3 * 2
  975.             for i, pl in ipairs(self.ZombieVolunteers) do
  976.                 if pl:IsValid() then
  977.                     draw_SimpleTextBlurry(pl:Name(), "ZSHUDFontTiny", w * 0.5, y, pl == MySelf and COLOR_RED or pl:IsFriend() and COLOR_LIMEGREEN or COLOR_GRAY, TEXT_ALIGN_CENTER)
  978.                     y = y + txth3
  979.                 end
  980.             end
  981.         end
  982.     end
  983.  
  984.     if self.LifeStatsEndTime and CurTime() < self.LifeStatsEndTime and (self.LifeStatsBarricadeDamage > 0 or self.LifeStatsHumanDamage > 0 or self.LifeStatsBrainsEaten > 0) then
  985.         colLifeStats.a = math.Clamp((self.LifeStatsEndTime - CurTime()) / (self.LifeStatsLifeTime * 0.33), 0, 1) * 255
  986.  
  987.         local th = draw_GetFontHeight("ZSHUDFontSmall")
  988.         local x = ScrW() * 0.75
  989.         local y = ScrH() * 0.75
  990.  
  991.         draw_SimpleTextBlur(translate.Get("that_life"), "ZSHUDFontSmall", x, y, colLifeStats, TEXT_ALIGN_LEFT)
  992.         y = y + th
  993.  
  994.         if self.LifeStatsBarricadeDamage > 0 then
  995.             draw_SimpleTextBlur(translate.Format("x_damage_to_barricades", self.LifeStatsBarricadeDamage), "ZSHUDFontSmall", x, y, colLifeStats, TEXT_ALIGN_LEFT)
  996.             y = y + th
  997.         end
  998.         if self.LifeStatsHumanDamage > 0 then
  999.             draw_SimpleTextBlur(translate.Format("x_damage_to_humans", self.LifeStatsHumanDamage), "ZSHUDFontSmall", x, y, colLifeStats, TEXT_ALIGN_LEFT)
  1000.             y = y + th
  1001.         end
  1002.         if self.LifeStatsBrainsEaten > 0 then
  1003.             draw_SimpleTextBlur(translate.Format("x_brains_eaten", self.LifeStatsBrainsEaten), "ZSHUDFontSmall", x, y, colLifeStats, TEXT_ALIGN_LEFT)
  1004.             y = y + th
  1005.         end
  1006.     end
  1007.  
  1008.     local obsmode = MySelf:GetObserverMode()
  1009.     if obsmode ~= OBS_MODE_NONE then
  1010.         self:ZombieObserverHUD(obsmode)
  1011.     elseif not self:GetWaveActive() and not MySelf:Alive() then
  1012.         local th = draw_GetFontHeight("ZSHUDFont")
  1013.         local x = ScrW() * 0.5
  1014.         local y = ScrH() * 0.3
  1015.         draw_SimpleTextBlur(translate.Get("waiting_for_next_wave"), "ZSHUDFont", x, y, COLOR_DARKRED, TEXT_ALIGN_CENTER)
  1016.         local pl = GAMEMODE.NextBossZombie
  1017.         local bossname = GAMEMODE.NextBossZombieClass
  1018.         if pl and pl:IsValid() then
  1019.             if pl == MySelf then
  1020.                 draw_SimpleTextBlur(translate.Format("you_will_be_x_soon", "'"..bossname.."'"), "ZSHUDFont", x, y+th, COLOR_RED, TEXT_ALIGN_CENTER)
  1021.             else
  1022.                 draw_SimpleTextBlur(translate.Format("x_will_be_y_soon", pl:Name(), "'"..bossname.."'"), "ZSHUDFont", x, y+th, COLOR_GRAY, TEXT_ALIGN_CENTER)
  1023.             end
  1024.         end
  1025.         if MySelf:GetZombieClassTable().NeverAlive then
  1026.             for _, ent in pairs(ents.FindByClass("prop_thrownbaby")) do
  1027.                 if ent:GetSettled() then
  1028.                     draw_SimpleTextBlur(translate.Format("press_walk_to_spawn_as_x", self.ZombieClasses["Gore Child"].Name), "ZSHUDFontSmall", w * 0.5, h * 0.75, COLOR_DARKRED, TEXT_ALIGN_CENTER)
  1029.                     break
  1030.                 end
  1031.             end
  1032.         end
  1033.     end
  1034.  
  1035.     if GetGlobalBool("waveactive") == false then
  1036.     local pl = GAMEMODE.NextBossZombie
  1037.     if pl and MySelf:Alive() and pl:IsValid() then
  1038.         local bossname = GAMEMODE.NextBossZombieClass
  1039.         local th = draw_GetFontHeight("ZSHUDFont")
  1040.         local x = ScrW() * 0.5
  1041.         local y = ScrH() * 0
  1042.         if pl == MySelf then
  1043.             draw_SimpleTextBlur(translate.Format("you_will_be_x_soon", "'"..bossname.."'"), "ZSHUDFont", x, y+th, COLOR_RED, TEXT_ALIGN_CENTER)
  1044.         else
  1045.             draw_SimpleTextBlur(translate.Format("x_will_be_y_soon", pl:Name(), "'"..bossname.."'"), "ZSHUDFont", x, y+th, COLOR_GRAY, TEXT_ALIGN_CENTER)
  1046.             end
  1047.         end
  1048.     end
  1049. end
  1050.  
  1051. function GM:RequestedDefaultCart()
  1052.     local defaultcart = GetConVar("zs_defaultcart"):GetString()
  1053.     if #defaultcart > 0 then
  1054.         defaultcart = string.lower(defaultcart)
  1055.  
  1056.         for i, carttab in ipairs(self.SavedCarts) do
  1057.             if carttab[1] and string.lower(carttab[1]) == defaultcart then
  1058.                 gamemode.Call("SuppressArsenalUpgrades", 1)
  1059.                 RunConsoleCommand("worthcheckout", unpack(carttab[2]))
  1060.  
  1061.                 return
  1062.             end
  1063.         end
  1064.  
  1065.         RunConsoleCommand("worthrandom")
  1066.     end
  1067. end
  1068.  
  1069. function GM:_PostDrawTranslucentRenderables()
  1070.     if not self.DrawingInSky then
  1071.         self:DrawPointWorldHints()
  1072.         self:DrawWorldHints()
  1073.     end
  1074. end
  1075.  
  1076. function GM:RestartRound()
  1077.     self.TheLastHuman = nil
  1078.     self.RoundEnded = nil
  1079.     LASTHUMAN = nil
  1080.  
  1081.     if pEndBoard and pEndBoard:Valid() then
  1082.         pEndBoard:Remove()
  1083.         pEndBoard = nil
  1084.     end
  1085.  
  1086.     self:InitPostEntity()
  1087.  
  1088.     self:RevertZombieClasses()
  1089.     timer.Create("RestartOSTintro", 10, 1, function() OSTintro = 0 end)
  1090. end
  1091.  
  1092. function GM:_HUDShouldDraw(name)
  1093.     if self.FilmMode and name ~= "CHudWeaponSelection" then return false end
  1094.  
  1095.     return name ~= "CHudHealth" and name ~= "CHudBattery"
  1096.     and name ~= "CHudAmmo" and name ~= "CHudSecondaryAmmo"
  1097.     and name ~= "CHudDamageIndicator"
  1098. end
  1099.  
  1100. local Current = 0
  1101. local NextCalculate = 0
  1102. function GM:_CachedFearPower()
  1103.     if CurTime() >= NextCalculate then
  1104.         NextCalculate = CurTime() + 0.15
  1105.         Current = self:GetFearMeterPower(EyePos(), TEAM_UNDEAD, MySelf)
  1106.     end
  1107.  
  1108.     return Current
  1109. end
  1110.  
  1111. function surface.CreateLegacyFont(font, size, weight, antialias, additive, name, shadow, outline, blursize)
  1112.     surface.CreateFont(name, {font = font, size = size, weight = weight, antialias = antialias, additive = additive, shadow = shadow, outline = outline, blursize = blursize})
  1113. end
  1114.  
  1115. function GM:CreateFonts()
  1116.     local fontfamily = "Typenoksidi"
  1117.     local fontfamily3d = "hidden"
  1118.     local fontweight = 0
  1119.     local fontweight3D = 0
  1120.     local fontaa = true
  1121.     local fontshadow = false
  1122.     local fontoutline = true
  1123.  
  1124.     surface.CreateLegacyFont("csd", 42, 500, true, false, "healthsign", false, true)
  1125.     surface.CreateLegacyFont("tahoma", 96, 1000, true, false, "zshintfont", false, true)
  1126.  
  1127.     surface.CreateLegacyFont(fontfamily3d, 12, fontweight3D, false, false,  "ZS3D2DFontSuperTiny2", false, true)
  1128.     surface.CreateLegacyFont(fontfamily3d, 15, fontweight3D, false, false,  "ZS3D2DFontSuperTiny", false, true)
  1129.     surface.CreateLegacyFont(fontfamily3d, 20, fontweight3D, false, false,  "ZS3D2DFontTiny", false, true)
  1130.     surface.CreateLegacyFont(fontfamily3d, 32, fontweight3D, false, false,  "ZS3D2DFontSmallest", false, true)
  1131.     surface.CreateLegacyFont(fontfamily3d, 40, fontweight3D, false, false,  "ZS3D2DFontSmaller", false, true)
  1132.     surface.CreateLegacyFont(fontfamily3d, 48, fontweight3D, false, false,  "ZS3D2DFontSmall", false, true)
  1133.     surface.CreateLegacyFont(fontfamily3d, 72, fontweight3D, false, false, "ZS3D2DFont", false, true)
  1134.     surface.CreateLegacyFont(fontfamily3d, 128, fontweight3D, false, false, "ZS3D2DFontBig", false, true)
  1135.     surface.CreateLegacyFont(fontfamily3d, 48, fontweight3D, false, false,  "ZS3D2DFontSmallBlur", false, false, 16)
  1136.     surface.CreateLegacyFont(fontfamily3d, 72, fontweight3D, false, false, "ZS3D2DFontBlur", false, false, 16)
  1137.     surface.CreateLegacyFont(fontfamily3d, 128, fontweight3D, false, false, "ZS3D2DFontBigBlur", false, false, 16)
  1138.     surface.CreateLegacyFont(fontfamily, 40, fontweight3D, false, false,  "ZS3D2DFont2Smaller", false, true)
  1139.     surface.CreateLegacyFont(fontfamily, 48, fontweight3D, false, false,  "ZS3D2DFont2Small", false, true)
  1140.     surface.CreateLegacyFont(fontfamily, 72, fontweight3D, false, false, "ZS3D2DFont2", false, true)
  1141.     surface.CreateLegacyFont(fontfamily, 128, fontweight3D, false, false, "ZS3D2DFont2Big", false, true)
  1142.     surface.CreateLegacyFont(fontfamily, 40, fontweight3D, false, false,  "ZS3D2DFont2SmallerBlur", false, false, 16)
  1143.     surface.CreateLegacyFont(fontfamily, 48, fontweight3D, false, false,  "ZS3D2DFont2SmallBlur", false, false, 16)
  1144.     surface.CreateLegacyFont(fontfamily, 72, fontweight3D, false, false, "ZS3D2DFont2Blur", false, false, 16)
  1145.     surface.CreateLegacyFont(fontfamily, 128, fontweight3D, false, false, "ZS3D2DFont2BigBlur", false, false, 16)
  1146.  
  1147.     local screenscale = BetterScreenScale()
  1148.  
  1149.     surface.CreateLegacyFont("csd", screenscale * 36, 100, true, false, "zsdeathnoticecs", false, true)
  1150.     surface.CreateLegacyFont("HL2MP", screenscale * 36, 100, true, false, "zsdeathnotice", false, true)
  1151.  
  1152.     surface.CreateLegacyFont(fontfamily, screenscale * 16, fontweight, fontaa, false, "ZSHUDFontTiny", fontshadow, fontoutline)
  1153.     surface.CreateLegacyFont(fontfamily, screenscale * 20, fontweight, fontaa, false, "ZSHUDFontSmallest", fontshadow, fontoutline)
  1154.     surface.CreateLegacyFont(fontfamily, screenscale * 22, fontweight, fontaa, false, "ZSHUDFontSmaller", fontshadow, fontoutline)
  1155.     surface.CreateLegacyFont(fontfamily, screenscale * 28, fontweight, fontaa, false, "ZSHUDFontSmall", fontshadow, fontoutline)
  1156.     surface.CreateLegacyFont(fontfamily, screenscale * 42, fontweight, fontaa, false, "ZSHUDFont", fontshadow, fontoutline)
  1157.     surface.CreateLegacyFont(fontfamily, screenscale * 72, fontweight, fontaa, false, "ZSHUDFontBig", fontshadow, fontoutline)
  1158.     surface.CreateLegacyFont(fontfamily, screenscale * 16, fontweight, fontaa, false, "ZSHUDFontTinyBlur", false, false, 8)
  1159.     surface.CreateLegacyFont(fontfamily, screenscale * 22, fontweight, fontaa, false, "ZSHUDFontSmallerBlur", false, false, 8)
  1160.     surface.CreateLegacyFont(fontfamily, screenscale * 22, fontweight, fontaa, false, "ZSHUDFontSmallNSBlur", false, false, 8)
  1161.     surface.CreateLegacyFont(fontfamily, screenscale * 28, fontweight, fontaa, false, "ZSHUDFontSmallBlur", false, false, 8)
  1162.     surface.CreateLegacyFont(fontfamily, screenscale * 42, fontweight, fontaa, false, "ZSHUDFontBlur", false, false, 8)
  1163.     surface.CreateLegacyFont(fontfamily, screenscale * 72, fontweight, fontaa, false, "ZSHUDFontBigBlur", false, false, 8)
  1164.  
  1165.     surface.CreateLegacyFont(fontfamily, screenscale * 16, 0, fontaa, false, "ZSAmmoName", false, false)
  1166.     surface.CreateLegacyFont(fontfamily, screenscale * 16, fontweight, fontaa, false, "ZSHUDFontTinyNS", false, false)
  1167.     surface.CreateLegacyFont(fontfamily, screenscale * 20, fontweight, fontaa, false, "ZSHUDFontSmallestNS", false, false)
  1168.     surface.CreateLegacyFont(fontfamily, screenscale * 22, fontweight, fontaa, false, "ZSHUDFontSmallerNS", false, false)
  1169.     surface.CreateLegacyFont(fontfamily, screenscale * 28, fontweight, fontaa, false, "ZSHUDFontSmallNS", false, false)
  1170.     surface.CreateLegacyFont(fontfamily, screenscale * 42, fontweight, fontaa, false, "ZSHUDFontNS", false, false)
  1171.     surface.CreateLegacyFont(fontfamily, screenscale * 72, fontweight, fontaa, false, "ZSHUDFontBigNS", false, false)
  1172.  
  1173.     surface.CreateLegacyFont(fontfamily, screenscale * 16, 0, true, false, "ZSDamageResistance", false, true)
  1174.     surface.CreateLegacyFont(fontfamily, screenscale * 16, 0, true, false, "ZSDamageResistanceBlur", false, true)
  1175.     surface.CreateLegacyFont("HL2MP", screenscale * 96, 100, true, false, "zsdeathnoticews", false, false)
  1176.     surface.CreateLegacyFont("csd", screenscale * 96, 100, true, false, "zsdeathnoticecsws", false, false)
  1177.  
  1178.     surface.CreateLegacyFont(fontfamily, 32, fontweight, true, false, "ZSScoreBoardTitle", false, true)
  1179.     surface.CreateLegacyFont(fontfamily, 22, fontweight, true, false, "ZSScoreBoardSubTitle", false, true)
  1180.     surface.CreateLegacyFont(fontfamily, 16, fontweight, true, false, "ZSScoreBoardPlayer", false, true)
  1181.     surface.CreateLegacyFont(fontfamily, 24, fontweight, true, false, "ZSScoreBoardHeading", false, false)
  1182.     surface.CreateLegacyFont("arial", 20, 0, true, false, "ZSScoreBoardPlayerSmall", false, true)
  1183.  
  1184.     -- Default, DefaultBold, DefaultSmall, etc. were changed when gmod13 hit. These are renamed fonts that have the old values.
  1185.     surface.CreateFont("DefaultFontVerySmall", {font = "tahoma", size = 10, weight = 0, antialias = false})
  1186.     surface.CreateFont("DefaultFontSmall", {font = "tahoma", size = 11, weight = 0, antialias = false})
  1187.     surface.CreateFont("DefaultFontSmallDropShadow", {font = "tahoma", size = 11, weight = 0, shadow = true, antialias = false})
  1188.     surface.CreateFont("DefaultFont", {font = "tahoma", size = 13, weight = 500, antialias = false})
  1189.     surface.CreateFont("DefaultFontBold", {font = "tahoma", size = 13, weight = 1000, antialias = false})
  1190.     surface.CreateFont("DefaultFontLarge", {font = "tahoma", size = 16, weight = 0, antialias = false})
  1191. end
  1192.  
  1193. function GM:EvaluateFilmMode()
  1194.     local visible = not self.FilmMode
  1195.  
  1196.     if self.GameStatePanel and self.GameStatePanel:Valid() then
  1197.         self.GameStatePanel:SetVisible(visible)
  1198.     end
  1199.  
  1200.     if self.TopNotificationHUD and self.TopNotificationHUD:Valid() then
  1201.         self.TopNotificationHUD:SetVisible(visible)
  1202.     end
  1203.  
  1204.     if self.CenterNotificationHUD and self.CenterNotificationHUD:Valid() then
  1205.         self.CenterNotificationHUD:SetVisible(visible)
  1206.     end
  1207.  
  1208.     if self.HealthHUD and self.HealthHUD:Valid() then
  1209.         self.HealthHUD:SetVisible(visible)
  1210.     end
  1211. end
  1212.  
  1213. function GM:CreateVGUI()
  1214.     local screenscale = BetterScreenScale()
  1215.     self.GameStatePanel = vgui.Create("DGameState")
  1216.     self.GameStatePanel:SetTextFont("ZSHUDFontSmaller")
  1217.     self.GameStatePanel:SetAlpha(220)
  1218.     self.GameStatePanel:SetSize(screenscale * 420, screenscale * 80)
  1219.     self.GameStatePanel:ParentToHUD()
  1220.  
  1221.     self.TopNotificationHUD = vgui.Create("DEXNotificationsList")
  1222.     self.TopNotificationHUD:SetAlign(RIGHT)
  1223.     self.TopNotificationHUD.PerformLayout = function(pan)
  1224.         local screenscale = BetterScreenScale()
  1225.         pan:SetSize(ScrW() * 0.4, ScrH() * 0.6)
  1226.         pan:AlignTop(16 * screenscale)
  1227.         pan:AlignRight()
  1228.     end
  1229.     self.TopNotificationHUD:InvalidateLayout()
  1230.     self.TopNotificationHUD:ParentToHUD()
  1231.  
  1232.     self.CenterNotificationHUD = vgui.Create("DEXNotificationsList")
  1233.     self.CenterNotificationHUD:SetAlign(CENTER)
  1234.     self.CenterNotificationHUD:SetMessageHeight(36)
  1235.     self.CenterNotificationHUD.PerformLayout = function(pan)
  1236.         local screenscale = BetterScreenScale()
  1237.         pan:SetSize(ScrW() * 0.5, ScrH() * 0.35)
  1238.         pan:CenterHorizontal()
  1239.         pan:AlignBottom(16 * screenscale)
  1240.     end
  1241.     self.CenterNotificationHUD:InvalidateLayout()
  1242.     self.CenterNotificationHUD:ParentToHUD()
  1243. end
  1244.  
  1245. function GM:Initialize()
  1246.     self:CreateFonts()
  1247.     self:PrecacheResources()
  1248.     self:CreateVGUI()
  1249.     self:InitializeBeats()
  1250.     self:AddCustomAmmo()
  1251.    
  1252.     RunConsoleCommand("r_drawmodeldecals", "0")
  1253.     RunConsoleCommand("r_3dsky", "0")
  1254.     RunConsoleCommand("mat_shadowstate", "0")
  1255.     RunConsoleCommand("r_shadowmaxrendered", "0")
  1256.     RunConsoleCommand("r_shadowrendertotexture", "0")
  1257. end
  1258.  
  1259. function GM:ShutDown()
  1260.     RunConsoleCommand("r_drawmodeldecals", "1")
  1261.     RunConsoleCommand("r_3dsky", "1")
  1262.     RunConsoleCommand("mat_shadowstate", "1")
  1263.     RunConsoleCommand("r_shadowmaxrendered", "1")
  1264.     RunConsoleCommand("r_shadowrendertotexture", "1")
  1265. end
  1266.  
  1267. local function FirstOfGoodType(a)
  1268.     for _, v in pairs(a) do
  1269.         local ext = string.sub(v, -4)
  1270.         if ext == ".ogg" or ext == ".wav" or ext == ".mp3" then
  1271.             return v
  1272.         end
  1273.     end
  1274. end
  1275.  
  1276. function GM:InitializeBeats()
  1277.     local _, dirs = file.Find("sound/zombiesurvival/beats/*", "GAME")
  1278.     for _, dirname in pairs(dirs) do
  1279.         if dirname == "none" or dirname == "default" then continue end
  1280.  
  1281.         self.Beats[dirname] = {}
  1282.         local highestexist
  1283.         for i=1, 10 do
  1284.             local a, __ = file.Find("sound/zombiesurvival/beats/"..dirname.."/"..i..".*", "GAME")
  1285.             local a1 = FirstOfGoodType(a)
  1286.             if a1 then
  1287.                 local filename = "zombiesurvival/beats/"..dirname.."/"..a1
  1288.                 if file.Exists("sound/"..filename, "GAME") then
  1289.                     self.Beats[dirname][i] = Sound(filename)
  1290.                     highestexist = filename
  1291.  
  1292.                     continue
  1293.                 end
  1294.             end
  1295.  
  1296.             if highestexist then
  1297.                 self.Beats[dirname][i] = highestexist
  1298.             end
  1299.         end
  1300.     end
  1301. end
  1302.  
  1303. function GM:PlayerDeath(pl, attacker)
  1304. end
  1305.  
  1306. function GM:LastHuman(pl)
  1307.     if not IsValid(pl) then pl = nil end
  1308.     self.TheLastHuman = pl
  1309.  
  1310.     if not LASTHUMAN then
  1311.  
  1312.     hook.Add( "PreDrawHalos", "ZS.PreDrawHalos.AddHalos", function()
  1313.     if self.TheLastHuman then
  1314.         if not IsValid(self.TheLastHuman) or LocalPlayer() == self.TheLastHuman or self.TheLastHuman:Team() == TEAM_UNDEAD then return end
  1315.  
  1316.         halo.Add({self.TheLastHuman},team.GetColor(self.TheLastHuman:Team()),1,1,2,true,true);
  1317.  
  1318.         end
  1319.     end )
  1320.  
  1321.     LASTHUMAN = true
  1322.         timer.Simple(0.5, function() GAMEMODE:LastHumanMessage() end)
  1323.     end
  1324. end
  1325.  
  1326. function GM:LastHumanMessage()
  1327.     if self.RoundEnded or not MySelf:IsValid() then return end
  1328.  
  1329.     local icon = self.PantsMode and "weapon_zs_legs" or "default"
  1330.     if MySelf:Team() == TEAM_UNDEAD or not MySelf:Alive() then
  1331.         self:CenterNotify({killicon = icon}, {font = "ZSHUDFont"}, " ", COLOR_RED, translate.Get(self.PantsMode and "kick_the_last_human" or "kill_the_last_human"), {killicon = icon})
  1332.     else
  1333.         self:CenterNotify({font = "ZSHUDFont"}, " ", COLOR_RED, translate.Get("you_are_the_last_human"))
  1334.         self:CenterNotify({killicon = icon}, " ", COLOR_RED, translate.Format(self.PantsMode and "x_pants_out_to_get_you" or "x_zombies_out_to_get_you", team.NumPlayers(TEAM_UNDEAD)), {killicon = icon})
  1335.     end
  1336. end
  1337.  
  1338. function GM:PlayerShouldTakeDamage(pl, attacker)
  1339.     return pl == attacker or not attacker:IsPlayer() or pl:Team() ~= attacker:Team() or pl.AllowTeamDamage or attacker.AllowTeamDamage
  1340. end
  1341.  
  1342. function GM:SetWave(wave)
  1343.     SetGlobalInt("wave", wave)
  1344. end
  1345.  
  1346. --[[local texGradientUp = surface.GetTextureID("vgui/gradient_up")
  1347. local texGradientDown = surface.GetTextureID("vgui/gradient_down")
  1348. local texGradientRight = surface.GetTextureID("vgui/gradient-r")]]
  1349. local matFilmGrain = Material("zombiesurvival/filmgrain/filmgrain")
  1350. --local color_black = color_black
  1351. function GM:_HUDPaintBackground()
  1352.     --[[local w, h = ScrW(), ScrH()
  1353.     local bordersize = BetterScreenScale() * 32
  1354.  
  1355.     surface_SetDrawColor(color_black)
  1356.  
  1357.     surface_SetTexture(texGradientDown)
  1358.     surface_DrawTexturedRect(0, 0, w, bordersize)
  1359.     surface_SetTexture(texGradientUp)
  1360.     surface_DrawTexturedRect(0, h - bordersize, w, bordersize)
  1361.     surface_SetTexture(texGradientRight)
  1362.     surface_DrawTexturedRectRotated(bordersize / 2, h / 2, bordersize, h, 180)
  1363.     surface_DrawTexturedRect(w - bordersize, 0, bordersize, h)]]
  1364.  
  1365.     if self.FilmGrainEnabled and MySelf:Team() ~= TEAM_UNDEAD then
  1366.         surface_SetMaterial(matFilmGrain)
  1367.         surface_SetDrawColor(0, 0, 0, (0.25 + 0.75 * self:CachedFearPower()) * self.FilmGrainOpacity)
  1368.         surface_DrawTexturedRectUV(0, 0, ScrW(), ScrH(), 2, 2, 0, 0)
  1369.     end
  1370.  
  1371.     local wep = MySelf:GetActiveWeapon()
  1372.     if wep:IsValid() and wep.DrawHUDBackground then
  1373.         wep:DrawHUDBackground()
  1374.     end
  1375. end
  1376.  
  1377. local function GiveWeapon()
  1378.     RunConsoleCommand("zsgiveweapon")
  1379. end
  1380. local function GiveWeaponClip()
  1381.     RunConsoleCommand("zsgiveweaponclip")
  1382. end
  1383. local function DropWeapon()
  1384.     RunConsoleCommand("zsdropweapon")
  1385. end
  1386. local function EmptyClip()
  1387.     RunConsoleCommand("zsemptyclip")
  1388. end
  1389. function GM:HumanMenu()
  1390.     if self.ZombieEscape then return end
  1391.  
  1392.     local ent = MySelf:MeleeTrace(48, 2).Entity
  1393.     if self:ValidMenuLockOnTarget(MySelf, ent) then
  1394.         self.HumanMenuLockOn = ent
  1395.     else
  1396.         self.HumanMenuLockOn = nil
  1397.     end
  1398.  
  1399.     if self.HumanMenuPanel and self.HumanMenuPanel:Valid() then
  1400.         self.HumanMenuPanel:SetVisible(true)
  1401.         self.HumanMenuPanel:OpenMenu()
  1402.         return
  1403.     end
  1404.  
  1405.     local panel = vgui.Create("DSideMenu")
  1406.     self.HumanMenuPanel = panel
  1407.  
  1408.     local screenscale = BetterScreenScale()
  1409.     for k, v in pairs(self.AmmoNames) do
  1410.         local b = vgui.Create("DAmmoCounter", panel)
  1411.         b:SetAmmoType(k)
  1412.         b:SetTall(screenscale * 36)
  1413.         panel:AddItem(b)
  1414.     end
  1415.  
  1416.     local b = EasyButton(panel, ""..translate.Get("alt_gw"), 8, 4)
  1417.     b.DoClick = GiveWeapon
  1418.     panel:AddItem(b)
  1419.     b = EasyButton(panel, ""..translate.Get("alt_gw5"), 8, 4)
  1420.     b.DoClick = GiveWeaponClip
  1421.     panel:AddItem(b)
  1422.     b = EasyButton(panel, ""..translate.Get("alt_dw"), 8, 4)
  1423.     b.DoClick = DropWeapon
  1424.     panel:AddItem(b)
  1425.     b = EasyButton(panel, ""..translate.Get("alt_ec"), 8, 4)
  1426.     b.DoClick = EmptyClip
  1427.     panel:AddItem(b)
  1428.  
  1429.     panel:OpenMenu()
  1430. end
  1431.  
  1432. function GM:PlayerBindPress(pl, bind, wasin)
  1433.     if bind == "gmod_undo" or bind == "undo" then
  1434.         RunConsoleCommand("+zoom")
  1435.         timer.Create("ReleaseZoom", 1, 1, function() RunConsoleCommand("-zoom") end)
  1436.     elseif bind == "+menu_context" then
  1437.         if P_Team(pl) ~= TEAM_SPECTATOR then
  1438.             self.ZombieThirdPerson = not self.ZombieThirdPerson
  1439.         end
  1440.     elseif bind == "impulse 100" then
  1441.         if P_Team(pl) == TEAM_UNDEAD and pl:Alive() then
  1442.             self:ToggleZombieVision()
  1443.     else
  1444.             self:CreateFlashlightCheck()
  1445.         end
  1446.     end
  1447. end
  1448. function GM:_ShouldDrawLocalPlayer(pl)
  1449.     return pl:Team() ~= TEAM_SPECTATOR and (self.ZombieThirdPerson or pl:CallZombieFunction("ShouldDrawLocalPlayer")) or pl:IsPlayingTaunt()
  1450. end
  1451.  
  1452. local roll = 0
  1453. function GM:_CalcView(pl, origin, angles, fov, znear, zfar)
  1454.     if flashlight_Active and (MySelf:Team() ~= TEAM_HUMAN or not MySelf:Alive()) then
  1455.         flashlight_Active = false
  1456.     end
  1457.     if flashlight_Active then
  1458.         if not IsValid(flashlight) then
  1459.             flashlight = CreateFlashlight()
  1460.         end
  1461.        
  1462.         if GAMEMODE.ZombieThirdPerson then
  1463.            local bonenum = MySelf:LookupBone("ValveBiped.Bip01_Head1")
  1464.            local b_pos = bonenum and MySelf:GetBonePosition(bonenum) or MySelf:GetShootPos()
  1465.             flashlight:SetPos(b_pos + (angles:Forward() * 10))
  1466.         else
  1467.             flashlight:SetPos(MySelf:GetShootPos())
  1468.         end
  1469.        
  1470.         flashlight:SetAngles(MySelf:EyeAngles())
  1471.        
  1472.         flashlight:Update()
  1473.     else
  1474.         if IsValid(flashlight) then
  1475.             flashlight:Remove()
  1476.         end
  1477.     end
  1478.  
  1479.     if pl.Confusion and pl.Confusion:IsValid() then
  1480.         pl.Confusion:CalcView(pl, origin, angles, fov, znear, zfar)
  1481.     end
  1482.  
  1483.     if pl.Revive and pl.Revive:IsValid() and pl.Revive.GetRagdollEyes then
  1484.         local rpos, rang = pl.Revive:GetRagdollEyes(pl)
  1485.         if rpos then
  1486.             origin = rpos
  1487.             angles = rang
  1488.         end
  1489.     elseif pl.KnockedDown and pl.KnockedDown:IsValid() then
  1490.         local rpos, rang = self:GetRagdollEyes(pl)
  1491.         if rpos then
  1492.             origin = rpos
  1493.             angles = rang
  1494.         end
  1495.     elseif pl:ShouldDrawLocalPlayer() and pl:OldAlive() then
  1496.         origin = pl:GetThirdPersonCameraPos(origin, angles)
  1497.     end
  1498.  
  1499.     local targetroll = 0
  1500.     if self.MovementViewRoll then
  1501.         local dir = pl:GetVelocity()
  1502.         local speed = dir:Length()
  1503.         dir:Normalize()
  1504.  
  1505.         targetroll = targetroll + dir:Dot(angles:Right()) * math.min(30, speed / 100)
  1506.     end
  1507.  
  1508.     if pl:WaterLevel() >= 3 then
  1509.         targetroll = targetroll + math.sin(CurTime()) * 7
  1510.     end
  1511.  
  1512.     roll = math.Approach(roll, targetroll, math.max(0.25, math.sqrt(math.abs(roll))) * 30 * FrameTime())
  1513.     angles.roll = angles.roll + roll
  1514.  
  1515.     if pl:IsPlayingTaunt() then
  1516.         self:CalcViewTaunt(pl, origin, angles, fov, zclose, zfar)
  1517.     end
  1518.  
  1519.     local target = pl:GetObserverTarget()
  1520.     if target and target:IsValid() then
  1521.         local lasttarget = self.LastObserverTarget
  1522.         if lasttarget and lasttarget:IsValid() and target ~= lasttarget then
  1523.             if self.LastObserverTargetLerp then
  1524.                 if CurTime() >= self.LastObserverTargetLerp then
  1525.                     self.LastObserverTarget = nil
  1526.                     self.LastObserverTargetLerp = nil
  1527.                 else
  1528.                     local delta = math.Clamp((self.LastObserverTargetLerp - CurTime()) / 0.3333, 0, 1) ^ 0.5
  1529.                     origin:Set(self.LastObserverTargetPos * delta + origin * (1 - delta))
  1530.                 end
  1531.             else
  1532.                 self.LastObserverTargetLerp = CurTime() + 0.3333
  1533.             end
  1534.         else
  1535.             self.LastObserverTarget = target
  1536.             self.LastObserverTargetPos = origin
  1537.         end
  1538.     end
  1539.  
  1540.     pl:CallZombieFunction("CalcView", origin, angles)
  1541.  
  1542.     return self.BaseClass.CalcView(self, pl, origin, angles, fov, znear, zfar)
  1543. end
  1544.  
  1545. function GM:CalcViewTaunt(pl, origin, angles, fov, zclose, zfar)
  1546.     local tr = util.TraceHull({start = origin, endpos = origin - angles:Forward() * 72, mins = Vector(-2, -2, -2), maxs = Vector(2, 2, 2), mask = MASK_OPAQUE, filter = pl})
  1547.     origin:Set(tr.HitPos + tr.HitNormal * 2)
  1548. end
  1549.  
  1550. local staggerdir = VectorRand():GetNormalized()
  1551. local BHopTime = 0
  1552. local WasPressingJump = false
  1553.  
  1554. local function PressingJump(cmd)
  1555.     return bit.band(cmd:GetButtons(), IN_JUMP) ~= 0
  1556. end
  1557.  
  1558. local function DontPressJump(cmd)
  1559.     cmd:SetButtons(cmd:GetButtons() - IN_JUMP)
  1560. end
  1561.  
  1562. function GM:_CreateMove(cmd)
  1563.     if MySelf:IsPlayingTaunt() and MySelf:Alive() then
  1564.         self:CreateMoveTaunt(cmd)
  1565.         return
  1566.     end
  1567.  
  1568.     -- Disables bunny hopping to an extent.
  1569.     if MySelf:GetLegDamage() >= 0.5 then
  1570.         if PressingJump(cmd) then
  1571.             DontPressJump(cmd)
  1572.         end
  1573.     elseif MySelf:OnGround() then
  1574.         if CurTime() < BHopTime then
  1575.             if PressingJump(cmd) then
  1576.                 DontPressJump(cmd)
  1577.                 WasPressingJump = true
  1578.             end
  1579.         elseif WasPressingJump then
  1580.             if PressingJump(cmd) then
  1581.                 DontPressJump(cmd)
  1582.             else
  1583.                 WasPressingJump = false
  1584.             end
  1585.         end
  1586.     else
  1587.         BHopTime = CurTime() + 0.065
  1588.     end
  1589.  
  1590.     local myteam = MySelf:Team()
  1591.     if myteam ~= TEAM_UNDEAD then
  1592.         if MySelf:Alive() then
  1593.             local lockon = self.HumanMenuLockOn
  1594.             if lockon then
  1595.                 if self:ValidMenuLockOnTarget(MySelf, lockon) and self.HumanMenuPanel and self.HumanMenuPanel:Valid() and self.HumanMenuPanel:IsVisible() and MySelf:KeyDown(self.MenuKey) then
  1596.                     local oldang = cmd:GetViewAngles()
  1597.                     local newang = (lockon:EyePos() - EyePos()):Angle()
  1598.                     --oldang.pitch = math.ApproachAngle(oldang.pitch, newang.pitch, FrameTime() * math.max(45, math.abs(math.AngleDifference(oldang.pitch, newang.pitch)) ^ 1.3))
  1599.                     oldang.yaw = math.ApproachAngle(oldang.yaw, newang.yaw, FrameTime() * math.max(45, math.abs(math.AngleDifference(oldang.yaw, newang.yaw)) ^ 1.3))
  1600.                     cmd:SetViewAngles(oldang)
  1601.                 else
  1602.                     self.HumanMenuLockOn = nil
  1603.                 end
  1604.             else
  1605.                 local maxhealth = MySelf:GetMaxHealth()
  1606.                 local threshold = MySelf:GetPalsy() and maxhealth - 1 or maxhealth * 0.25
  1607.                 local health = MySelf:Health()
  1608.                 if health <= threshold then
  1609.                     local ft = FrameTime()
  1610.  
  1611.                     staggerdir = (staggerdir + ft * 8 * VectorRand()):GetNormalized()
  1612.  
  1613.                     local ang = cmd:GetViewAngles()
  1614.                     local rate = ft * ((threshold - health) / threshold) * 7
  1615.                     ang.pitch = math.NormalizeAngle(ang.pitch + staggerdir.z * rate)
  1616.                     ang.yaw = math.NormalizeAngle(ang.yaw + staggerdir.x * rate)
  1617.                     cmd:SetViewAngles(ang)
  1618.                 end
  1619.             end
  1620.         end
  1621.     elseif myteam == TEAM_UNDEAD then
  1622.         local buttons = cmd:GetButtons()
  1623.         if bit.band(buttons, IN_ZOOM) ~= 0 then
  1624.             cmd:SetButtons(buttons - IN_ZOOM)
  1625.         end
  1626.  
  1627.         MySelf:CallZombieFunction("CreateMove", cmd)
  1628.     end
  1629. end
  1630.  
  1631. function GM:CreateMoveTaunt(cmd)
  1632.     cmd:ClearButtons(0)
  1633.     cmd:ClearMovement()
  1634. end
  1635.  
  1636. function GM:PostProcessPermitted(str)
  1637.     return false
  1638. end
  1639.  
  1640. function GM:HUDPaintEndRound()
  1641. end
  1642.  
  1643. function GM:PreDrawViewModel(vm, pl, wep)
  1644.     if pl and pl:IsValid() and pl:IsHolding() then return true end
  1645.  
  1646.     if wep and wep:IsValid() and wep.PreDrawViewModel then
  1647.         return wep:PreDrawViewModel(vm)
  1648.     end
  1649. end
  1650.  
  1651. function GM:PostDrawViewModel(vm, pl, wep)
  1652.     if wep and wep:IsValid() then
  1653.         if wep.UseHands or not wep:IsScripted() then
  1654.             local hands = pl:GetHands()
  1655.             if hands and hands:IsValid() then
  1656.                 hands:DrawModel()
  1657.             end
  1658.         end
  1659.  
  1660.         if wep.PostDrawViewModel then
  1661.             wep:PostDrawViewModel(vm)
  1662.         end
  1663.     end
  1664. end
  1665.  
  1666. local undomodelblend = false
  1667. local undozombievision = false
  1668. local matWhite = Material("models/debug/debugwhite")
  1669. function GM:_PrePlayerDraw(pl)
  1670.     if pl:CallZombieFunction("PrePlayerDraw") then return true end
  1671.  
  1672.     local shadowman = false
  1673.  
  1674.     if pl.status_overridemodel and pl.status_overridemodel:IsValid() and self:ShouldDrawLocalPlayer(MySelf) then -- We need to do this otherwise the player's real model shows up for some reason.
  1675.         undomodelblend = true
  1676.         render.SetBlend(0)
  1677.     else
  1678.         local myteam = MySelf:Team()
  1679.         if myteam == pl:Team() and pl ~= MySelf and not self.MedicalAura then
  1680.             local radius = self.TransparencyRadius
  1681.             if radius > 0 then
  1682.                 local eyepos = EyePos()
  1683.                 local dist = pl:NearestPoint(eyepos):Distance(eyepos)
  1684.                 if dist < radius then
  1685.                     local blend = math.max((dist / radius) ^ 1.4, myteam ~= TEAM_UNDEAD and 0.04 or 0.1)
  1686.                     render.SetBlend(blend)
  1687.                     if myteam ~= TEAM_UNDEAD and blend < 0.4 then
  1688.                         render.ModelMaterialOverride(matWhite)
  1689.                         render.SetColorModulation(0.2, 0.2, 0.2)
  1690.                         shadowman = true
  1691.                     end
  1692.                     undomodelblend = true
  1693.                 end
  1694.             end
  1695.         end
  1696.     end
  1697.  
  1698.     pl.ShadowMan = shadowman
  1699.  
  1700.     if (MySelf:KeyDown(IN_SPEED) and MySelf:Team() ~= TEAM_UNDEAD and MySelf:Alive() and pl:Team() ~= TEAM_UNDEAD and pl ~= MySelf) or self.m_ZombieVision and MySelf:Team() ~= TEAM_HUMAN and pl:Team() ~= TEAM_UNDEAD and pl:GetPos():Distance(EyePos()) <= pl:GetAuraRange() then
  1701.         undozombievision = true
  1702.         local color = Color(255, 255, 255, 255)
  1703.         local healthfrac = math.max(pl:Health(), 0) / pl:GetMaxHealth()
  1704.         local lowhealthcolor = GAMEMODE.AuraColorEmpty
  1705.         local fullhealthcolor = GAMEMODE.AuraColorFull
  1706.  
  1707.         color.r = math.Approach(lowhealthcolor.r, fullhealthcolor.r, math.abs(lowhealthcolor.r - fullhealthcolor.r) * healthfrac)
  1708.         color.g = math.Approach(lowhealthcolor.g, fullhealthcolor.g, math.abs(lowhealthcolor.g - fullhealthcolor.g) * healthfrac)
  1709.         color.b = math.Approach(lowhealthcolor.b, fullhealthcolor.b, math.abs(lowhealthcolor.b - fullhealthcolor.b) * healthfrac)
  1710.  
  1711.         render.ModelMaterialOverride(matWhite)
  1712.         render.SetColorModulation(color.r/255, color.g/255, color.b/255)
  1713.         render.SuppressEngineLighting(true)
  1714.         cam.IgnoreZ(true)
  1715.     end
  1716. end
  1717.  
  1718. local colFriend = Color(10, 255, 10, 60)
  1719. local matFriendRing = Material("SGM/playercircle")
  1720. function GM:_PostPlayerDraw(pl)
  1721.     pl:CallZombieFunction("PostPlayerDraw")
  1722.  
  1723.     if undomodelblend then
  1724.         render.SetBlend(1)
  1725.         render.ModelMaterialOverride()
  1726.         render.SetColorModulation(1, 1, 1)
  1727.  
  1728.         undomodelblend = false
  1729.     end
  1730.     if undozombievision then
  1731.         render.ModelMaterialOverride()
  1732.         render.SetColorModulation(1, 1, 1)
  1733.         render.SuppressEngineLighting(false)
  1734.         cam.IgnoreZ(false)
  1735.  
  1736.         undozombievision = false
  1737.     end
  1738.  
  1739.     if pl ~= MySelf and MySelf:Team() == pl:Team() and pl:IsFriend() then
  1740.         local pos = pl:GetPos() + Vector(0, 0, 2)
  1741.         render.SetMaterial(matFriendRing)
  1742.         render.DrawQuadEasy(pos, Vector(0, 0, 1), 32, 32, colFriend)
  1743.         render.DrawQuadEasy(pos, Vector(0, 0, -1), 32, 32, colFriend)
  1744.     end
  1745. end
  1746.  
  1747. function GM:DrawCraftingEntity()
  1748.     local craftingentity = self.CraftingEntity
  1749.     if craftingentity and craftingentity:IsValid() then
  1750.         if self.HumanMenuPanel and self.HumanMenuPanel:Valid() and self.HumanMenuPanel:IsVisible() and MySelf:KeyDown(self.MenuKey) then
  1751.             local scale = craftingentity:GetModelScale()
  1752.             if not scale then return end
  1753.  
  1754.             render.ModelMaterialOverride(matWhite)
  1755.             render.SuppressEngineLighting(true)
  1756.             render.SetBlend(0.025)
  1757.             local extrascale = 1.05 + math.abs(math.sin(RealTime() * 7)) * 0.1
  1758.             craftingentity:SetModelScale(scale * extrascale, 0)
  1759.  
  1760.             local oldpos = craftingentity:GetPos()
  1761.             craftingentity:SetPos(oldpos - craftingentity:LocalToWorld(oldpos))
  1762.             craftingentity:DrawModel()
  1763.             craftingentity:SetPos(oldpos)
  1764.  
  1765.             craftingentity:SetModelScale(scale, 0)
  1766.             render.SetBlend(1)
  1767.             render.SuppressEngineLighting(false)
  1768.             render.ModelMaterialOverride(0)
  1769.         else
  1770.             self.CraftingEntity = nil
  1771.         end
  1772.     end
  1773. end
  1774.  
  1775. function GM:HUDPaintBackgroundEndRound()
  1776.     local w, h = ScrW(), ScrH()
  1777.     local timleft = math.max(0, self.EndTime + self.EndGameTime - CurTime())
  1778.  
  1779.     if timleft <= 0 then
  1780.         draw_SimpleTextBlur(translate.Get("loading"), "ZSHUDFont", w * 0.5, h * 0.8, COLOR_WHITE, TEXT_ALIGN_CENTER)
  1781.     else
  1782.         draw_SimpleTextBlur(translate.Format("next_round_in_x", util.ToMinutesSeconds(timleft)), "ZSHUDFontSmall", w * 0.5, h * 0.8, COLOR_WHITE, TEXT_ALIGN_CENTER)
  1783.     end
  1784. end
  1785.  
  1786. local endRoundViewPosStart = nil
  1787. local endRoundViewAngleStart = nil
  1788. local function EndRoundCalcView(pl, origin, angles, fov, znear, zfar)
  1789.     if GAMEMODE.EndTime and CurTime() < GAMEMODE.EndTime + 5 then
  1790.         endRoundViewPosStart = endRoundViewPosStart or origin
  1791.         endRoundViewAngleStart = endRoundViewAngleStart or angles
  1792.         local endRoundViewPosEnd = GAMEMODE.LastHumanPosition
  1793.         local override = GetGlobalVector("endcamerapos", 1)
  1794.         if type(override) ~= "number" then
  1795.             endRoundViewPosEnd = override
  1796.         end
  1797.         if endRoundViewPosEnd then
  1798.             local delta = math.Clamp((CurTime() - GAMEMODE.EndTime) * 2, 0, 1)
  1799.  
  1800.             local camPos = endRoundViewPosEnd * delta + endRoundViewPosStart * (1 - delta)
  1801.             local camVec = Angle(0, CurTime() * 30, 0):Forward() * delta - endRoundViewAngleStart:Forward() * (1 - delta)
  1802.             camVec:Normalize()
  1803.             local tr = util.TraceHull({start = camPos, endpos = camPos + delta * 128 * camVec, mins = Vector(-2, -2, -2), maxs = Vector(2, 2, 2), filter = player.GetAll(), mask = MASK_SOLID})
  1804.             return {origin = tr.HitPos + tr.HitNormal, angles = (camPos - tr.HitPos):Angle()}
  1805.         end
  1806.  
  1807.         return
  1808.     end
  1809.  
  1810.     endRoundViewPosStart = nil
  1811.     endRoundViewAngleStart = nil
  1812.  
  1813.     hook.Remove("CalcView", "EndRoundCalcView")
  1814. end
  1815.  
  1816. local function EndRoundShouldDrawLocalPlayer(pl)
  1817.     if GAMEMODE.EndTime and CurTime() < GAMEMODE.EndTime + 5 then
  1818.         return true
  1819.     end
  1820.  
  1821.     hook.Remove("ShouldDrawLocalPlayer", "EndRoundShouldDrawLocalPlayer")
  1822. end
  1823.  
  1824. local function EndRoundGetMeleeFilter(self) return {self} end
  1825. function GM:EndRound(winner, nextmap)
  1826.     if self.RoundEnded then return end
  1827.     self.RoundEnded = true
  1828.  
  1829.     ROUNDWINNER = winner
  1830.  
  1831.     self.EndTime = CurTime()
  1832.  
  1833.     RunConsoleCommand("stopsound")
  1834.  
  1835.     FindMetaTable("Player").GetMeleeFilter = EndRoundGetMeleeFilter
  1836.  
  1837.     self.HUDPaint = self.HUDPaintEndRound
  1838.     self.HUDPaintBackground = self.HUDPaintBackgroundEndRound
  1839.  
  1840.     if winner == TEAM_UNDEAD and GetGlobalBool("endcamera", true) then
  1841.         hook.Add("CalcView", "EndRoundCalcView", EndRoundCalcView)
  1842.         hook.Add("ShouldDrawLocalPlayer", "EndRoundShouldDrawLocalPlayer", EndRoundShouldDrawLocalPlayer)
  1843.     end
  1844.  
  1845.     local dvar = winner == TEAM_UNDEAD and self.AllLoseSound or self.HumanWinSound
  1846.     local snd = GetGlobalString(winner == TEAM_UNDEAD and "losemusic" or "winmusic", dvar)
  1847.     if snd == "default" then
  1848.         snd = dvar
  1849.     elseif snd == "none" then
  1850.         snd = nil
  1851.     end
  1852.     if snd then
  1853.         timer.Simple(0.5, function() surface_PlaySound(snd) end)
  1854.     end
  1855.  
  1856.     timer.Simple(5, function()
  1857.         if not (pEndBoard and pEndBoard:IsValid()) then
  1858.             MakepEndBoard(winner)
  1859.         end
  1860.     end)
  1861. end
  1862.  
  1863. function GM:WeaponDeployed(pl, wep)
  1864. end
  1865.  
  1866. function GM:LocalPlayerDied(attackername)
  1867.     LASTDEATH = RealTime()
  1868.  
  1869.     surface_PlaySound(self.DeathSound)
  1870.     if attackername then
  1871.         self:CenterNotify(COLOR_RED, {font = "ZSHUDFont"}, translate.Get("you_have_died"))
  1872.         self:CenterNotify(COLOR_RED, translate.Format(self.PantsMode and "you_were_kicked_by_x" or "you_were_killed_by_x", tostring(attackername)))
  1873.     else
  1874.         self:CenterNotify(COLOR_RED, {font = "ZSHUDFont"}, translate.Get("you_have_died"))
  1875.     end
  1876. end
  1877.  
  1878. function GM:KeyPress(pl, key)
  1879.     if key == self.MenuKey then
  1880.         if pl:Team() ~= TEAM_UNDEAD and pl:Alive() and not pl:IsHolding() then
  1881.             gamemode.Call("HumanMenu")
  1882.         end
  1883.     elseif key == IN_SPEED then
  1884.         if pl:Alive() then
  1885.             if pl:Team() ~= TEAM_UNDEAD then
  1886.                 pl:DispatchAltUse()
  1887.             elseif pl:Team() == TEAM_UNDEAD then
  1888.                 pl:CallZombieFunction("AltUse")
  1889.             end
  1890.         end
  1891.     end
  1892. end
  1893.  
  1894. function GM:PlayerStepSoundTime(pl, iType, bWalking)
  1895.     local time = pl:CallZombieFunction("PlayerStepSoundTime", iType, bWalking)
  1896.     if time then
  1897.         return time
  1898.     end
  1899.  
  1900.     if iType == STEPSOUNDTIME_NORMAL or iType == STEPSOUNDTIME_WATER_FOOT then
  1901.         return 520 - pl:GetVelocity():Length()
  1902.     end
  1903.  
  1904.     if iType == STEPSOUNDTIME_ON_LADDER then
  1905.         return 500
  1906.     end
  1907.  
  1908.     if iType == STEPSOUNDTIME_WATER_KNEE then
  1909.         return 650
  1910.     end
  1911.  
  1912.     return 350
  1913. end
  1914.  
  1915. function GM:PlayerFootstep(pl, vFootPos, iFoot, strSoundName, fVolume)
  1916.     return pl:CallZombieFunction("PlayerFootstep", vFootPos, iFoot, strSoundName, fVolume)
  1917. end
  1918.  
  1919. function GM:PlayerCanCheckout(pl)
  1920.     return pl:IsValid() and pl:Team() == TEAM_HUMAN and pl:Alive() and self:GetWave() <= 0
  1921. end
  1922.  
  1923. function GM:OpenWorth()
  1924.     if gamemode.Call("PlayerCanCheckout", MySelf) then
  1925.         MakepWorth()
  1926.     end
  1927. end
  1928.  
  1929. function GM:CloseWorth()
  1930.     if pWorth and pWorth:IsValid() then
  1931.         pWorth:Remove()
  1932.         pWorth = nil
  1933.     end
  1934. end
  1935.  
  1936. function GM:SuppressArsenalUpgrades(suppresstime)
  1937.     self.SuppressArsenalTime = math.max(CurTime() + suppresstime, self.SuppressArsenalTime)
  1938. end
  1939.  
  1940. function GM:Rewarded(class, amount)
  1941.     if CurTime() < self.SuppressArsenalTime then return end
  1942.  
  1943.     class = class or "0"
  1944.  
  1945.     local toptext = translate.Get("arsenal_upgraded")
  1946.  
  1947.     local wep = weapons.GetStored(class)
  1948.     if wep and wep.PrintName then
  1949.         if killicon.Get(class) == killicon.Get("default") then
  1950.             self:CenterNotify(COLOR_PURPLE, toptext..": ", color_white, wep.PrintName)
  1951.         else
  1952.             self:CenterNotify({killicon = class}, " ", COLOR_PURPLE, toptext..": ", color_white, wep.PrintName)
  1953.         end
  1954.     elseif amount then
  1955.         self:CenterNotify(COLOR_PURPLE, toptext..": ", color_white, amount.." "..class)
  1956.     else
  1957.         self:CenterNotify(COLOR_PURPLE, toptext)
  1958.     end
  1959. end
  1960.  
  1961. function PlayMenuOpenSound()
  1962.     LocalPlayer():EmitSound("buttons/lightswitch2.wav", 100, 30)
  1963. end
  1964.  
  1965. function PlayMenuCloseSound()
  1966.     LocalPlayer():EmitSound("buttons/lightswitch2.wav", 100, 20)
  1967. end
  1968.  
  1969. local DamageFloaters = CreateClientConVar("zs_damagefloaters", "1", true, false):GetBool()
  1970. cvars.AddChangeCallback("zs_damagefloaters", function(cvar, oldvalue, newvalue)
  1971.     DamageFloaters = newvalue ~= "0"
  1972. end)
  1973.  
  1974. concommand.Add("spectate", function()
  1975.     net.Start("zs_spectate")
  1976.     net.SendToServer()
  1977. end)
  1978.  
  1979. net.Receive("zs_legdamage", function(length)
  1980.     LocalPlayer().LegDamage = net.ReadFloat()
  1981. end)
  1982.  
  1983. net.Receive("zs_nextboss", function(length)
  1984.     GAMEMODE.NextBossZombie = net.ReadEntity()
  1985.     GAMEMODE.NextBossZombieClass = net.ReadString()
  1986. end)
  1987.  
  1988. net.Receive("zs_zvols", function(length)
  1989.     local volunteers = {}
  1990.     local count = net.ReadUInt(8)
  1991.     for i=1, count do
  1992.         volunteers[i] = net.ReadEntity()
  1993.     end
  1994.  
  1995.     GAMEMODE.ZombieVolunteers = volunteers
  1996. end)
  1997.  
  1998. net.Receive("zs_dmg", function(length)
  1999.     local damage = net.ReadUInt(16)
  2000.     local pos = net.ReadVector()
  2001.  
  2002.     if DamageFloaters then
  2003.         local effectdata = EffectData()
  2004.             effectdata:SetOrigin(pos)
  2005.             effectdata:SetMagnitude(damage)
  2006.             effectdata:SetScale(0)
  2007.         util.Effect("damagenumber", effectdata)
  2008.     end
  2009. end)
  2010.  
  2011. net.Receive("zs_dmg_prop", function(length)
  2012.     local damage = net.ReadUInt(16)
  2013.     local pos = net.ReadVector()
  2014.  
  2015.     if DamageFloaters then
  2016.         local effectdata = EffectData()
  2017.             effectdata:SetOrigin(pos)
  2018.             effectdata:SetMagnitude(damage)
  2019.             effectdata:SetScale(1)
  2020.         util.Effect("damagenumber", effectdata)
  2021.     end
  2022. end)
  2023.  
  2024. net.Receive("zs_lifestats", function(length)
  2025.     local barricadedamage = net.ReadUInt(24)
  2026.     local humandamage = net.ReadUInt(24)
  2027.     local brainseaten = net.ReadUInt(16)
  2028.  
  2029.     GAMEMODE.LifeStatsEndTime = CurTime() + GAMEMODE.LifeStatsLifeTime
  2030.     GAMEMODE.LifeStatsBarricadeDamage = barricadedamage
  2031.     GAMEMODE.LifeStatsHumanDamage = humandamage
  2032.     GAMEMODE.LifeStatsBrainsEaten = brainseaten
  2033. end)
  2034.  
  2035. net.Receive("zs_lifestatsbd", function(length)
  2036.     local barricadedamage = net.ReadUInt(24)
  2037.  
  2038.     GAMEMODE.LifeStatsEndTime = CurTime() + GAMEMODE.LifeStatsLifeTime
  2039.     GAMEMODE.LifeStatsBarricadeDamage = barricadedamage
  2040. end)
  2041.  
  2042. net.Receive("zs_lifestatshd", function(length)
  2043.     local humandamage = net.ReadUInt(24)
  2044.  
  2045.     GAMEMODE.LifeStatsEndTime = CurTime() + GAMEMODE.LifeStatsLifeTime
  2046.     GAMEMODE.LifeStatsHumanDamage = humandamage
  2047. end)
  2048.  
  2049. net.Receive("zs_lifestatsbe", function(length)
  2050.     local brainseaten = net.ReadUInt(16)
  2051.  
  2052.     GAMEMODE.LifeStatsEndTime = CurTime() + GAMEMODE.LifeStatsLifeTime
  2053.     GAMEMODE.LifeStatsBrainsEaten = brainseaten
  2054. end)
  2055.  
  2056. net.Receive("zs_honmention", function(length)
  2057.     local pl = net.ReadEntity()
  2058.     local mentionid = net.ReadUInt(8)
  2059.     local etc = net.ReadInt(32)
  2060.  
  2061.     if pl:IsValid() then
  2062.         gamemode.Call("AddHonorableMention", pl, mentionid, etc)
  2063.     end
  2064. end)
  2065.  
  2066. net.Receive("zs_wavestart", function(length)
  2067.     local wave = net.ReadInt(16)
  2068.     local time = net.ReadFloat()
  2069.  
  2070.     gamemode.Call("SetWave", wave)
  2071.     gamemode.Call("SetWaveEnd", time)
  2072.  
  2073.     if GAMEMODE.ZombieEscape then
  2074.         GAMEMODE:CenterNotify(COLOR_RED, {font = "ZSHUDFont"}, translate.Get("escape_from_the_zombies"))
  2075.     elseif wave == GAMEMODE:GetNumberOfWaves() then
  2076.         GAMEMODE:CenterNotify({killicon = "default"}, {font = "ZSHUDFont"}, " ", COLOR_RED, translate.Get("final_wave"), {killicon = "default"})
  2077.         GAMEMODE:CenterNotify(translate.Get("final_wave_sub"))
  2078.     else
  2079.         GAMEMODE:CenterNotify({killicon = "default"}, {font = "ZSHUDFont"}, " ", COLOR_RED, translate.Format("wave_x_has_begun", wave), {killicon = "default"})
  2080.     end
  2081.  
  2082.     if not GAMEMODE.ObjectiveMap then
  2083.     if LocalPlayer():IsValid() and LocalPlayer():Team() ~= TEAM_UNDEAD then
  2084.             GAMEMODE:CenterNotify(COLOR_GREEN, translate.Format("weapon_tier_x", wave))
  2085.         end
  2086.     end
  2087.    
  2088.     surface_PlaySound("zombiesurvival/round_start.mp3")
  2089. end)
  2090.  
  2091. net.Receive("zs_classunlock", function(length)
  2092.     GAMEMODE:CenterNotify(COLOR_GREEN, translate.Format("x_unlocked", net.ReadString()))
  2093. end)
  2094.  
  2095. net.Receive("zs_waveend", function(length)
  2096.     local wave = net.ReadInt(16)
  2097.     local time = net.ReadFloat()
  2098.  
  2099.     gamemode.Call("SetWaveStart", time)
  2100.  
  2101.     if wave < GAMEMODE:GetNumberOfWaves() and wave > 0 then
  2102.         GAMEMODE:CenterNotify(COLOR_RED, {font = "ZSHUDFont"}, translate.Format("wave_x_is_over", wave))
  2103.         GAMEMODE:CenterNotify(translate.Format("wave_x_is_over_sub", GAMEMODE.ArsenalCrateDiscountPercentage))
  2104.  
  2105.         surface_PlaySound("zombiesurvival/round_end.mp3")
  2106.     end
  2107. end)
  2108.  
  2109. net.Receive("zs_gamestate", function(length)
  2110.     local wave = net.ReadInt(16)
  2111.     local wavestart = net.ReadFloat()
  2112.     local waveend = net.ReadFloat()
  2113.  
  2114.     gamemode.Call("SetWave", wave)
  2115.     gamemode.Call("SetWaveStart", wavestart)
  2116.     gamemode.Call("SetWaveEnd", waveend)
  2117. end)
  2118.  
  2119. local matSkull = Material("zombiesurvival/horderally")
  2120. local bossspawnedend
  2121. local function BossSpawnedPaint()
  2122.     if CurTime() > bossspawnedend then
  2123.         hook.Remove("HUDPaint", "BossSpawnedPaint")
  2124.         return
  2125.     end
  2126.  
  2127.     local delta = math.Clamp(bossspawnedend - CurTime(), 0, 1)
  2128.     local size = (1 - delta) * math.max(ScrW(), ScrH())
  2129.  
  2130.     surface_SetMaterial(matSkull)
  2131.     surface_SetDrawColor(160, 0, 0, math.min(delta * 400, 180))
  2132.     surface_DrawTexturedRectRotated(ScrW() / 2, ScrH() / 2, size, size, delta * 25)
  2133. end
  2134. net.Receive("zs_boss_spawned", function(length)
  2135.     local ent = net.ReadEntity()
  2136.     local classindex = net.ReadUInt(8)
  2137.  
  2138.     if ent == MySelf and ent:IsValid() then
  2139.         GAMEMODE:CenterNotify({killicon = "default"}, " ", COLOR_RED, translate.Format("you_are_x", translate.Get(GAMEMODE.ZombieClasses[classindex].TranslationName)), {killicon = "default"})
  2140.     elseif ent:IsValid() then
  2141.         GAMEMODE:CenterNotify({killicon = "default"}, " ", COLOR_RED, (translate.Format("x_has_risen_as_y", ent:Name(), translate.Get(GAMEMODE.ZombieClasses[classindex].TranslationName))), {killicon = "default"})
  2142.     else
  2143.         GAMEMODE:CenterNotify({killicon = "default"}, " ", COLOR_RED, translate.Format("x_has_risen", translate.Get(GAMEMODE.ZombieClasses[classindex].TranslationName)), {killicon = "default"})
  2144.     end
  2145.  
  2146.     if MySelf:IsValid() then
  2147.         MySelf:EmitSound("npc/zombie_poison/pz_alert1.wav", 0)
  2148.     end
  2149.  
  2150.     bossspawnedend = CurTime() + 1
  2151.     hook.Add("HUDPaint", "BossSpawnedPaint", BossSpawnedPaint)
  2152. end)
  2153.  
  2154. net.Receive("zs_centernotify", function(length)
  2155.     local tab = net.ReadTable()
  2156.  
  2157.     GAMEMODE:CenterNotify(unpack(tab))
  2158. end)
  2159.  
  2160. net.Receive("zs_topnotify", function(length)
  2161.     local tab = net.ReadTable()
  2162.  
  2163.     GAMEMODE:TopNotify(unpack(tab))
  2164. end)
  2165.  
  2166. net.Receive("zs_lasthuman", function(length)
  2167.     local pl = net.ReadEntity()
  2168.  
  2169.     gamemode.Call("LastHuman", pl)
  2170. end)
  2171.  
  2172. net.Receive("zs_weapontiers", function(length)
  2173.     local tab = GAMEMODE.Items[net.ReadUInt(8)]
  2174.     tab.Unlocked = net.ReadBit()==1
  2175. end)
  2176.  
  2177. net.Receive("zs_gamemodecall", function(length)
  2178.     gamemode.Call(net.ReadString())
  2179. end)
  2180.  
  2181. net.Receive("zs_lasthumanpos", function(length)
  2182.     GAMEMODE.LastHumanPosition = net.ReadVector()
  2183. end)
  2184.  
  2185. net.Receive("zs_endround", function(length)
  2186.     local winner = net.ReadUInt(8)
  2187.     local nextmap = net.ReadString()
  2188.  
  2189.     gamemode.Call("EndRound", winner, nextmap)
  2190. end)
  2191.  
  2192. net.Receive("zs_ammogive", function(length)
  2193.     local amount = net.ReadUInt(16)
  2194.     local ammotype = net.ReadString()
  2195.     local ent = net.ReadEntity()
  2196.  
  2197.     if not ent:IsValidPlayer() then return end
  2198.     local ico = GAMEMODE.AmmoIcons[ammotype] or "weapon_zs_resupplybox"
  2199.  
  2200.     ammotype = GAMEMODE.AmmoNames[ammotype] or ammotype
  2201.  
  2202.     GAMEMODE:CenterNotify({killicon = ico}, " ", COLOR_GREEN, translate.Format("gave_x_y_ammo_to_z", amount, ammotype, ent:Name()))
  2203. end)
  2204.  
  2205. net.Receive("zs_ammogiven", function(length)
  2206.     local amount = net.ReadUInt(16)
  2207.     local ammotype = net.ReadString()
  2208.     local ent = net.ReadEntity()
  2209.  
  2210.     if not ent:IsValidPlayer() then return end
  2211.     local ico = GAMEMODE.AmmoIcons[ammotype] or "weapon_zs_resupplybox"
  2212.  
  2213.     ammotype = GAMEMODE.AmmoNames[ammotype] or ammotype
  2214.  
  2215.     GAMEMODE:CenterNotify({killicon = ico}, " ", COLOR_GREEN, translate.Format("obtained_x_y_ammo_from_z", amount, ammotype, ent:Name()))
  2216. end)
  2217.  
  2218. net.Receive("zs_updatealtselwep", function(length)
  2219. end)
  2220.  
  2221. local function AltSelItemUpd()
  2222.     local activeweapon = MySelf:GetActiveWeapon()
  2223.     if not activeweapon or not activeweapon:IsValid() then return end
  2224.  
  2225.     local actwclass = activeweapon:GetClass()
  2226.     GAMEMODE.HumanMenuPanel.SelectedItemLabel:SetText(weapons.Get(actwclass).PrintName)
  2227. end
  2228.  
  2229. local function AltSelItemUpd()
  2230.     local activeweapon = MySelf:GetActiveWeapon()
  2231.     if not activeweapon or not activeweapon:IsValid() then return end
  2232.  
  2233.     local actwclass = activeweapon:GetClass()
  2234.     GAMEMODE.HumanMenuPanel.SelectedItemLabel:SetText(weapons.Get(actwclass).PrintName)
  2235. end
  2236.  
  2237. -- Mutations Net
  2238. net.Receive("zs_mutations_table", function(len)
  2239.     local mutationstable = net.ReadTable()
  2240.     if mutationstable then
  2241.         UsedMutations = mutationstable
  2242.     end
  2243. end)
  2244.  
  2245. -- Temporary fix
  2246. function render.DrawQuadEasy(pos, dir, xsize, ysize, color, rotation)
  2247.     xsize = xsize / 2
  2248.     ysize = ysize / 2
  2249.  
  2250.     local ang = dir:Angle()
  2251.  
  2252.     if rotation then
  2253.         ang:RotateAroundAxis(ang:Forward(), rotation)
  2254.     end
  2255.  
  2256.     local upoffset = ang:Up() * ysize
  2257.     local rightoffset = ang:Right() * xsize
  2258.  
  2259.     render.DrawQuad(pos - upoffset - rightoffset, pos - upoffset + rightoffset, pos + upoffset + rightoffset, pos + upoffset - rightoffset, color)
  2260. end
Advertisement
Add Comment
Please, Sign In to add comment
Advertisement