-- Sometimes persistent ones don't get created.

local dummy = CreateClientConVar("_zs_dummyconvar", 1, false, false)

local oldCreateClientConVar = CreateClientConVar

function CreateClientConVar(...)

	return oldCreateClientConVar(...) or dummy

end



include("shared.lua")

include("cl_draw.lua")

include("cl_util.lua")

include("cl_options.lua")

include("obj_player_extend_cl.lua")

include("cl_scoreboard.lua")

include("cl_targetid.lua")

include("cl_postprocess.lua")



include("vgui/dgamestate.lua")

include("vgui/dteamcounter.lua")

include("vgui/dmodelpanelex.lua")

include("vgui/dammocounter.lua")

include("vgui/dteamheading.lua")



include("vgui/dexroundedpanel.lua")

include("vgui/dexroundedframe.lua")

include("vgui/dexrotatedimage.lua")

include("vgui/dexnotificationslist.lua")

include("vgui/dexchanginglabel.lua")



include("vgui/pmainmenu.lua")

include("vgui/poptions.lua")

include("vgui/phelp.lua")

include("vgui/pclassselect.lua")

include("vgui/pweapons.lua")

include("vgui/pendboard.lua")

include("vgui/pworth.lua")

include("vgui/ppointshop.lua")

include("vgui/dpingmeter.lua")

include("vgui/dsidemenu.lua")

include("vgui/zshealtharea.lua")



include("cl_dermaskin.lua")

include("cl_deathnotice.lua")

include("cl_floatingscore.lua")

include("cl_hint.lua")



include("cl_zombieescape.lua")



w, h = ScrW(), ScrH()



MySelf = MySelf or NULL

hook.Add("InitPostEntity", "GetLocal", function()

	MySelf = LocalPlayer()



	GAMEMODE.HookGetLocal = GAMEMODE.HookGetLocal or (function(g) end)

	gamemode.Call("HookGetLocal", MySelf)

	RunConsoleCommand("initpostentity")

end)



-- Remove when model decal crash is fixed.

function util.Decal()

end



-- Save on global lookup time.

local render = render

local surface = surface

local draw = draw

local cam = cam

local player = player

local ents = ents

local util = util

local math = math

local string = string

local bit = bit

local gamemode = gamemode

local hook = hook

local Vector = Vector

local VectorRand = VectorRand

local Angle = Angle

local AngleRand = AngleRand

local Entity = Entity

local Color = Color

local FrameTime = FrameTime

local RealTime = RealTime

local CurTime = CurTime

local SysTime = SysTime

local EyePos = EyePos

local EyeAngles = EyeAngles

local pairs = pairs

local ipairs = ipairs

local tostring = tostring

local tonumber = tonumber

local type = type

local ScrW = ScrW

local ScrH = ScrH

local TEXT_ALIGN_CENTER = TEXT_ALIGN_CENTER

local TEXT_ALIGN_LEFT = TEXT_ALIGN_LEFT

local TEXT_ALIGN_RIGHT = TEXT_ALIGN_RIGHT

local TEXT_ALIGN_TOP = TEXT_ALIGN_TOP

local TEXT_ALIGN_BOTTOM = TEXT_ALIGN_BOTTOM



local TEAM_HUMAN = TEAM_HUMAN

local TEAM_UNDEAD = TEAM_UNDEAD

local translate = translate



local COLOR_PURPLE = COLOR_PURPLE

local COLOR_GRAY = COLOR_GRAY

local COLOR_RED = COLOR_RED

local COLOR_DARKRED = COLOR_DARKRED

local COLOR_DARKGREEN = COLOR_DARKGREEN

local COLOR_GREEN = COLOR_GREEN

local COLOR_WHITE = COLOR_WHITE



local surface_SetFont = surface.SetFont

local surface_SetTexture = surface.SetTexture

local surface_SetMaterial = surface.SetMaterial

local surface_SetDrawColor = surface.SetDrawColor

local surface_DrawRect = surface.DrawRect

local surface_DrawOutlinedRect = surface.DrawOutlinedRect

local surface_DrawTexturedRect = surface.DrawTexturedRect

local surface_DrawTexturedRectRotated = surface.DrawTexturedRectRotated

local surface_DrawTexturedRectUV = surface.DrawTexturedRectUV

local surface_PlaySound = surface.PlaySound



local draw_SimpleText = draw.SimpleText

local draw_SimpleTextBlurry = draw.SimpleTextBlurry

local draw_SimpleTextBlur = draw.SimpleTextBlur

local draw_GetFontHeight = draw.GetFontHeight



local MedicalAuraDistance = 400



function GM:ClickedPlayerButton(pl, button)

end



function GM:ClickedEndBoardPlayerButton(pl, button)

end



function GM:CenterNotify(...)

	if self.CenterNotificationHUD and self.CenterNotificationHUD:Valid() then

		return self.CenterNotificationHUD:AddNotification(...)

	end

end



function GM:TopNotify(...)

	if self.TopNotificationHUD and self.TopNotificationHUD:Valid() then

		return self.TopNotificationHUD:AddNotification(...)

	end

end



GM.InputMouseX = 0

GM.InputMouseY = 0

function GM:_InputMouseApply(cmd, x, y, ang)

	self.InputMouseX = x

	self.InputMouseY = y



	if MySelf:KeyDown(IN_WALK) and MySelf:IsHolding() then

		RunConsoleCommand("_zs_rotateang", self.InputMouseX, self.InputMouseY)

		return true

	end

end



function GM:_GUIMousePressed(mc)

	if self.HumanMenuPanel and self.HumanMenuPanel:Valid() and self.HumanMenuPanel:IsVisible() and MySelf:KeyDown(self.MenuKey) then

		local dir = gui.ScreenToVector(gui.MousePos())

		local ent = util.TraceLine({start = MySelf:EyePos(), endpos = MySelf:EyePos() + dir * self.CraftingRange, filter = MySelf, mask = MASK_SOLID}).Entity

		if ent:IsValid() and not ent:IsPlayer() and (ent:GetMoveType() == MOVETYPE_NONE or ent:GetMoveType() == MOVETYPE_VPHYSICS) and ent:GetSolid() == SOLID_VPHYSICS then

			if mc == MOUSE_LEFT then

				if ent == self.CraftingEntity then

					self.CraftingEntity = nil

				else

					self.CraftingEntity = ent

				end

			elseif mc == MOUSE_RIGHT and self.CraftingEntity and self.CraftingEntity:IsValid() then

				RunConsoleCommand("_zs_craftcombine", self.CraftingEntity:EntIndex(), ent:EntIndex())

				self.CraftingEntity = nil

			end

		end

	end

end



function GM:TryHumanPickup(pl, entity)

end



function GM:AddExtraOptions(list, window)

end



function GM:SpawnMenuEnabled()

	return false

end



function GM:SpawnMenuOpen()

	return false

end



function GM:ContextMenuOpen()

	return false

end



function GM:HUDWeaponPickedUp(wep)

end



function GM:_HUDWeaponPickedUp(wep)

	if MySelf:Team() == TEAM_HUMAN and not wep.NoPickupNotification then

		self:Rewarded(wep:GetClass())

	end

end



function GM:HUDItemPickedUp(itemname)

end



function GM:HUDAmmoPickedUp(itemname, amount)

end



function GM:InitPostEntity()

	if not self.HealthHUD then

		self.HealthHUD = vgui.Create("ZSHealthArea")

	end



	self:LocalPlayerFound()



	self:EvaluateFilmMode()



	timer.Simple(2, function() GAMEMODE:GetFogData() end)

end



function GM:SetupWorldFog()

	if self.DeathFog == 0 then return end



	local power = self.DeathFog

	local rpower = 1 - self.DeathFog



	local fogstart = self.FogStart * rpower

	local fogend = self.FogEnd * rpower + 150 * power

	local fogr = self.FogRed * rpower

	local fogg = self.FogGreen * rpower + 40 * power

	local fogb = self.FogBlue * rpower



	render.FogMode(1)



	render.FogStart(fogstart)

	render.FogEnd(fogend)

	render.FogColor(fogr, fogg, fogb)

	render.FogMaxDensity(1)



	return true

end



function GM:SetupSkyboxFog(skyboxscale)

	if self.DeathFog == 0 then return end



	local power = self.DeathFog

	local rpower = 1 - self.DeathFog



	local fogstart = self.FogStart * rpower

	local fogend = self.FogEnd * rpower + 150 * power

	local fogr = self.FogRed * rpower

	local fogg = self.FogGreen * rpower + 40 * power

	local fogb = self.FogBlue * rpower

	local fogdensity = 1 - power * 0.1



	render.FogMode(1)



	render.FogStart(fogstart * skyboxscale)

	render.FogEnd(fogend * skyboxscale)

	render.FogColor(fogr, fogg, fogb)

	render.FogMaxDensity(1)



	return true

end



function GM:PreDrawSkyBox()

	self.DrawingInSky = true

end



local matSky = CreateMaterial("SkyOverride", "UnlitGeneric", {["$basetexture"] = "color/white", ["$vertexcolor"] = 1, ["$vertexalpha"] = 1, ["$model"] = 1})

local colSky = Color(0, 30, 0)

function GM:PostDrawSkyBox()

	self.DrawingInSky = false



	if self.DeathFog == 0 then return end



	colSky.a = self.DeathFog * 230



	cam.Start3D(EyePos(), EyeAngles())

		render.SuppressEngineLighting(true)



		render.SetMaterial(matSky)



		render.DrawQuadEasy(Vector(0, 0, 10240), Vector(0, 0, -1), 20480, 20480, colSky, 0)

		render.DrawQuadEasy(Vector(0, 10240, 0), Vector(0, -1, 0), 20480, 20480, colSky, 0)

		render.DrawQuadEasy(Vector(0, -10240, 0), Vector(0, 1, 0), 20480, 20480, colSky, 0)

		render.DrawQuadEasy(Vector(10240, 0, 0), Vector(-1, 0, 0), 20480, 20480, colSky, 0)

		render.DrawQuadEasy(Vector(-10240, 0, 0), Vector(1, 0, 0), 20480, 20480, colSky, 0)



		render.SuppressEngineLighting(false)

	cam.End3D()

end



GM.DeathFog = 0

GM.FogStart = 0

GM.FogEnd = 8000

GM.FogRed = 30

GM.FogGreen = 30

GM.FogBlue = 30

function GM:GetFogData()

	local fogstart, fogend = render.GetFogDistances()

	local fogr, fogg, fogb = render.GetFogColor()



	self.FogStart = fogstart

	self.FogEnd = fogend

	self.FogRed = fogr

	self.FogGreen = fogg

	self.FogBlue = fogb

end



local matAura = Material("models/debug/debugwhite")

local skip = false

function GM.PostPlayerDrawMedical(pl)

	if not skip and pl:Team() == TEAM_HUMAN and pl ~= LocalPlayer() then

		local eyepos = EyePos()

		local dist = pl:NearestPoint(eyepos):Distance(eyepos)

		if dist < MedicalAuraDistance then

			local green = pl:Health() / pl:GetMaxHealth()



			pl.SkipDrawHooks = true

			skip = true



			render.SuppressEngineLighting(true)

			render.ModelMaterialOverride(matAura)

			render.SetBlend((1 - (dist / MedicalAuraDistance)) * 0.1 * (1 + math.abs(math.sin((CurTime() + pl:EntIndex()) * 4)) * 0.05))

			render.SetColorModulation(1 - green, green, 0)

				pl:DrawModel()

			render.SetColorModulation(1, 1, 1)

			render.SetBlend(1)

			render.ModelMaterialOverride()

			render.SuppressEngineLighting(false)



			skip = false

			pl.SkipDrawHooks = false

		end

	end

end



function GM:OnReloaded()

	self.BaseClass.OnReloaded(self)



	self:LocalPlayerFound()

end



-- The whole point of this is so we don't need to check if the local player is valid 1000 times a second.

function GM:LocalPlayerFound()

	self.Think = self._Think

	self.HUDShouldDraw = self._HUDShouldDraw

	self.CachedFearPower = self._CachedFearPower

	self.CalcView = self._CalcView

	self.ShouldDrawLocalPlayer = self._ShouldDrawLocalPlayer

	self.PostDrawOpaqueRenderables = self._PostDrawOpaqueRenderables

	self.PostDrawTranslucentRenderables = self._PostDrawTranslucentRenderables

	self.HUDPaint = self._HUDPaint

	self.HUDPaintBackground = self._HUDPaintBackground

	self.CreateMove = self._CreateMove

	self.PrePlayerDraw = self._PrePlayerDraw

	self.PostPlayerDraw = self._PostPlayerDraw

	self.InputMouseApply = self._InputMouseApply

	self.GUIMousePressed = self._GUIMousePressed

	self.HUDWeaponPickedUp = self._HUDWeaponPickedUp



	if render.GetDXLevel() >= 80 then

		self.RenderScreenspaceEffects = self._RenderScreenspaceEffects

	end

end



local currentpower = 0

local spawngreen = 0

local matFearMeter = Material("zombiesurvival/fearometer")

local matNeedle = Material("zombiesurvival/fearometerneedle")

local matEyeGlow = Material("Sprites/light_glow02_add_noz")

function GM:DrawFearMeter(power, screenscale)

	if currentpower < power then

		currentpower = math.min(power, currentpower + FrameTime() * (math.tan(currentpower) * 2 + 0.05))

	elseif power < currentpower then

		currentpower = math.max(power, currentpower - FrameTime() * (math.tan(currentpower) * 2 + 0.05))

	end



	local w, h = ScrW(), ScrH()

	local wid, hei = 192 * screenscale, 192 * screenscale

	local mx, my = w * 0.5 - wid * 0.5, h - hei



	surface_SetMaterial(matFearMeter)

	surface_SetDrawColor(140, 140, 140, 240)

	surface_DrawTexturedRect(mx, my, wid, hei)

	if currentpower >= 0.75 then

		local pulse = CurTime() % 3 - 1

		if pulse > 0 then

			pulse = pulse ^ 2

			local pulsesize = pulse * screenscale * 28

			surface_SetDrawColor(140, 140, 140, 120 - pulse * 120)

			surface_DrawTexturedRect(mx - pulsesize, my - pulsesize, wid + pulsesize * 2, hei + pulsesize * 2)

		end

	end



	surface_SetMaterial(matNeedle)

	surface_SetDrawColor(160, 160, 160, 225)

	local rot = math.Clamp((0.5 - currentpower) + math.sin(RealTime() * 10) * 0.01, -0.5, 0.5) * 300

	surface_DrawTexturedRectRotated(w * 0.5 - math.max(0, rot * wid * -0.0001), h - hei * 0.5 - math.abs(rot) * hei * 0.00015, wid, hei, rot)



	if MySelf:Team() == TEAM_UNDEAD then

		if self:GetDynamicSpawning() and self:ShouldUseAlternateDynamicSpawn() then

			local obs = MySelf:GetObserverTarget()

			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)



			local sy = my + hei * 0.6953

			local size = wid * 0.085



			surface_SetMaterial(matEyeGlow)

			surface_SetDrawColor(220 * (1 - spawngreen), 220 * spawngreen, 0, 240)

			surface_DrawTexturedRectRotated(mx + wid * 0.459, sy, size, size, 0)

			surface_DrawTexturedRectRotated(mx + wid * 0.525, sy, size, size, 0)

		end



		if currentpower > 0 and not self.ZombieEscape then

			draw_SimpleTextBlurry(translate.Format("resist_x", math.ceil(self:GetDamageResistance(currentpower) * 100)), "ZSDamageResistance", w * 0.5, my + hei * 0.75, Color(currentpower * 200, 200 - currentpower * 200, 0, 255), TEXT_ALIGN_CENTER)

		end

	end

end



function GM:GetDynamicSpawning()

	return not GetGlobalBool("DynamicSpawningDisabled", false)

end



GM.LastTimeDead = 0

GM.LastTimeAlive = 0



function GM:TrackLastDeath()

	if MySelf:Alive() then

		self.LastTimeAlive = CurTime()

	else

		self.LastTimeDead = CurTime()

	end

end



function GM:IsClassicMode()

	return GetGlobalBool("classicmode", false)

end



function GM:IsBabyMode()

	return GetGlobalBool("babymode", false)

end



function GM:PostRender()

	if self.m_ZombieVision and MySelf:IsValid() and MySelf:Team() == TEAM_UNDEAD then

		local eyepos = EyePos()

		local eyedir = EyeAngles():Forward()

		local tr = util.TraceLine({start = eyepos, endpos = eyepos + eyedir * 128, mask = MASK_SOLID_BRUSHONLY})



		local dlight = DynamicLight(MySelf:EntIndex())

		if dlight then

			dlight.Pos = tr.HitPos + tr.HitNormal * 2

			dlight.r = 10

			dlight.g = 255

			dlight.b = 80

			dlight.Brightness = 3

			dlight.Size = 300

			dlight.Decay = 900

			dlight.DieTime = CurTime() + 1

		end

	end

end



local lastwarntim = -1

GM.HeartBeatTime = 0

GM.FOVLerp = 1

GM.HurtEffect = 0

GM.PrevHealth = 0

local NextGas = 0

function GM:_Think()

	if self:GetEscapeStage() == ESCAPESTAGE_DEATH then

		self.DeathFog = math.min(self.DeathFog + FrameTime() / 5, 1)



		if CurTime() >= NextGas then

			NextGas = CurTime() + 0.01



			local eyepos = EyePos()



			local emitter = ParticleEmitter(eyepos)



			for i=1, 3 do

				local randdir = VectorRand()

				randdir.z = math.abs(randdir.z)

				randdir:Normalize()

				local emitpos = eyepos + randdir * math.Rand(0, 1200)



				local particle = emitter:Add("particles/smokey", emitpos)

				particle:SetVelocity(randdir * math.Rand(8, 256))

				particle:SetAirResistance(16)

				particle:SetDieTime(math.Rand(2.2, 3.5))

				particle:SetStartAlpha(math.Rand(70, 90))

				particle:SetEndAlpha(0)

				particle:SetStartSize(1)

				particle:SetEndSize(math.Rand(150, 325))

				particle:SetRoll(math.Rand(0, 360))

				particle:SetRollDelta(math.Rand(-1, 1))

				particle:SetColor(0, math.Rand(20, 45), 0)

			end



			emitter:Finish()

		end

	elseif self.DeathFog > 0 then

		self.DeathFog = math.max(self.DeathFog - FrameTime() / 5, 0)

	end



	local health = MySelf:Health()

	if self.PrevHealth and health < self.PrevHealth then

		self.HurtEffect = math.min(self.HurtEffect + (self.PrevHealth - health) * 0.02, 1.5)

	elseif self.HurtEffect > 0 then

		self.HurtEffect = math.max(0, self.HurtEffect - FrameTime() * 0.65)

	end

	self.PrevHealth = health



	self:TrackLastDeath()



	local endtime = self:GetWaveActive() and self:GetWaveEnd() or self:GetWaveStart()

	if endtime ~= -1 then

		local timleft = math.max(0, endtime - CurTime())

		if timleft <= 10 and lastwarntim ~= math.ceil(timleft) then

			lastwarntim = math.ceil(timleft)

			if 0 < lastwarntim then

				surface_PlaySound("buttons/lightswitch2.wav")

			end

		end

	end



	local myteam = MySelf:Team()



	self:PlayBeats(myteam, self:CachedFearPower())



	if myteam == TEAM_HUMAN then

		local wep = MySelf:GetActiveWeapon()

		if wep:IsValid() and wep.GetIronsights and wep:GetIronsights() then

			self.FOVLerp = math.Approach(self.FOVLerp, wep.IronsightsMultiplier or 0.6, FrameTime() * 4)

		elseif self.FOVLerp ~= 1 then

			self.FOVLerp = math.Approach(self.FOVLerp, 1, FrameTime() * 5)

		end



		if MySelf:GetBarricadeGhosting() then

			MySelf:BarricadeGhostingThink()

		end

	else

		self.HeartBeatTime = self.HeartBeatTime + (6 + self:CachedFearPower() * 5) * FrameTime()



		if not MySelf:Alive() then

			self:ToggleZombieVision(false)

		end

	end



	for _, pl in pairs(player.GetAll()) do

		if pl:Team() == TEAM_UNDEAD then

			local tab = pl:GetZombieClassTable()

			if tab.BuildBonePositions then

				pl.WasBuildingBonePositions = true

				pl:ResetBones()

				tab.BuildBonePositions(tab, pl)

			elseif pl.WasBuildingBonePositions then

				pl.WasBuildingBonePositions = nil

				pl:ResetBones()

			end

		elseif pl.WasBuildingBonePositions then

			pl.WasBuildingBonePositions = nil

			pl:ResetBones()

		end

	end

end



function GM:ShouldPlayBeats(teamid, fear)

	return not self.RoundEnded and not self.ZombieEscape and not GetGlobalBool("beatsdisabled", false)

end



local cv_ShouldPlayMusic = CreateClientConVar("zs_playmusic", 1, true, false)

local NextBeat = 0

local LastBeatLevel = 0

function GM:PlayBeats(teamid, fear)

	if RealTime() <= NextBeat or not gamemode.Call("ShouldPlayBeats", teamid, fear) then return end



	if LASTHUMAN and cv_ShouldPlayMusic:GetBool() then

		MySelf:EmitSound(self.LastHumanSound, 0, 100, self.BeatsVolume)

		NextBeat = RealTime() + (self.SoundDuration[snd] or SoundDuration(self.LastHumanSound)) - 0.025

		return

	end



	if fear <= 0 or not self.BeatsEnabled then return end



	local beats = self.Beats[teamid == TEAM_HUMAN and self.BeatSetHuman or self.BeatSetZombie]

	if not beats then return end



	LastBeatLevel = math.Approach(LastBeatLevel, math.ceil(fear * 10), 3)



	local snd = beats[LastBeatLevel]

	if snd then

		MySelf:EmitSound(snd, 0, 100, self.BeatsVolume)

		NextBeat = RealTime() + (self.SoundDuration[snd] or SoundDuration(snd)) - 0.025

	end

end



local colPackUp = Color(20, 255, 20, 220)

local colPackUpNotOwner = Color(255, 240, 10, 220)

function GM:DrawPackUpBar(x, y, fraction, notowner, screenscale)

	local col = notowner and colPackUpNotOwner or colPackUp



	local maxbarwidth = 270 * screenscale

	local barheight = 11 * screenscale

	local barwidth = maxbarwidth * math.Clamp(fraction, 0, 1)

	local startx = x - maxbarwidth * 0.5



	surface_SetDrawColor(0, 0, 0, 220)

	surface_DrawRect(startx, y, maxbarwidth, barheight)

	surface_SetDrawColor(col)

	surface_DrawRect(startx + 3, y + 3, barwidth - 6, barheight - 6)

	surface_DrawOutlinedRect(startx, y, maxbarwidth, barheight)



	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)

end



function GM:HumanHUD(screenscale)

	local curtime = CurTime()

	local w, h = ScrW(), ScrH()



	local packup = MySelf.PackUp

	if packup and packup:IsValid() then

		self:DrawPackUpBar(w * 0.5, h * 0.55, 1 - packup:GetTimeRemaining() / packup:GetMaxTime(), packup:GetNotOwner(), screenscale)

	end



	if not self.RoundEnded then

		if self:GetWave() == 0 and not self:GetWaveActive() then

			local txth = draw_GetFontHeight("ZSHUDFontSmall")

			draw_SimpleTextBlurry(translate.Get("waiting_for_players").." "..util.ToMinutesSeconds(math.max(0, self:GetWaveStart() - curtime)), "ZSHUDFontSmall", w * 0.5, h * 0.25, COLOR_GRAY, TEXT_ALIGN_CENTER)

			draw_SimpleTextBlurry(translate.Get("humans_closest_to_spawns_are_zombies"), "ZSHUDFontSmall", w * 0.5, h * 0.25 + txth, COLOR_GRAY, TEXT_ALIGN_CENTER)



			local desiredzombies = self:GetDesiredStartingZombies()



			draw_SimpleTextBlurry(translate.Format("number_of_initial_zombies_this_game", self.WaveOneZombies * 100, desiredzombies), "ZSHUDFontSmall", w * 0.5, h * 0.75, COLOR_GRAY, TEXT_ALIGN_CENTER)



			draw_SimpleTextBlurry(translate.Get("zombie_volunteers"), "ZSHUDFontSmall", w * 0.5, h * 0.75 + txth, COLOR_GRAY, TEXT_ALIGN_CENTER)

			local y = h * 0.75 + txth * 2



			txth = draw_GetFontHeight("ZSHUDFontTiny")

			for i, pl in ipairs(self.ZombieVolunteers) do

				if pl:IsValid() then

					draw_SimpleTextBlurry(pl:Name(), "ZSHUDFontTiny", w * 0.5, y, pl == MySelf and COLOR_RED or COLOR_GRAY, TEXT_ALIGN_CENTER)

					y = y + txth

				end

			end

		end



		local drown = MySelf.status_drown

		if drown and drown:IsValid() then

			surface_SetDrawColor(0, 0, 0, 60)

			surface_DrawRect(w * 0.4, h * 0.35, w * 0.2, 12)

			surface_SetDrawColor(30, 30, 230, 180)

			surface_DrawOutlinedRect(w * 0.4, h * 0.35, w * 0.2, 12)

			surface_DrawRect(w * 0.4, h * 0.35, w * 0.2 * (1 - drown:GetDrown()), 12)

			draw_SimpleTextBlurry(translate.Get("breath").." ", "ZSHUDFontSmall", w * 0.4, h * 0.35 + 6, COLOR_BLUE, TEXT_ALIGN_RIGHT, TEXT_ALIGN_CENTER)

		end

	end



	if gamemode.Call("PlayerCanPurchase", MySelf) then

		if self:GetWaveActive() then

			draw_SimpleTextBlurry(translate.Get("press_f2_for_the_points_shop"), "ZSHUDFontSmall", w * 0.5, 8, COLOR_GRAY, TEXT_ALIGN_CENTER)

		else

			local th = draw_GetFontHeight("ZSHUDFontSmall")

			draw_SimpleTextBlurry(translate.Get("press_f2_for_the_points_shop"), "ZSHUDFontSmall", w * 0.5, 8, COLOR_GRAY, TEXT_ALIGN_CENTER)

			draw_SimpleTextBlurry(translate.Format("x_discount_for_buying_between_waves", self.ArsenalCrateDiscountPercentage), "ZSHUDFontSmall", w * 0.5, 9 + th, COLOR_GRAY, TEXT_ALIGN_CENTER)

		end

	end

end



function GM:HUDPaint()

end



function GM:_HUDPaint()

	if self.FilmMode then return end



	local screenscale = BetterScreenScale()



	local myteam = MySelf:Team()



	self:HUDDrawTargetID(myteam, screenscale)



	if self:GetWave() > 0 then

		self:DrawFearMeter(self:CachedFearPower(), screenscale)

	end



	if myteam == TEAM_UNDEAD then

		self:ZombieHUD()

	else

		self:HumanHUD(screenscale)

	end



	if GetGlobalBool("classicmode") then

		draw_SimpleTextBlurry(translate.Get("classic_mode"), "ZSHUDFontSmaller", 4, ScrH() - 4, COLOR_GRAY, TEXT_ALIGN_LEFT, TEXT_ALIGN_TOP)

	end

end



function GM:ZombieObserverHUD(obsmode)

	local w, h = ScrW(), ScrH()

	local texh = draw_GetFontHeight("ZSHUDFontSmall")



	local dyn



	if obsmode == OBS_MODE_CHASE then

		local target = MySelf:GetObserverTarget()

		if target and target:IsValid() then

			if target:IsPlayer() and target:Team() == TEAM_UNDEAD then

				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)

			end



			dyn = self:GetDynamicSpawning() and self:DynamicSpawnIsValid(target)

		end

	end



	if self:GetWaveActive() then

		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)

	end



	local space = texh + 8

	draw_SimpleTextBlur(translate.Get("press_rmb_to_cycle_targets"), "ZSHUDFontSmall", w * 0.5, h * 0.75 + space, COLOR_DARKRED, TEXT_ALIGN_CENTER)

	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)

	draw_SimpleTextBlur(translate.Get("press_jump_to_free_roam"), "ZSHUDFontSmall", w * 0.5, h * 0.75 + space * 3, COLOR_DARKRED, TEXT_ALIGN_CENTER)



	for _, ent in pairs(ents.FindByClass("prop_thrownbaby")) do

		if ent:GetSettled() then

			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)

			break

		end

	end

end



local matHumanHeadID = Material("zombiesurvival/humanhead")

local matZombieHeadID = Material("zombiesurvival/zombiehead")

local colLifeStats = Color(255, 0, 0, 255)

function GM:ZombieHUD()

	if self.LifeStatsEndTime and CurTime() < self.LifeStatsEndTime and (self.LifeStatsBarricadeDamage > 0 or self.LifeStatsHumanDamage > 0 or self.LifeStatsBrainsEaten > 0) then

		colLifeStats.a = math.Clamp((self.LifeStatsEndTime - CurTime()) / (self.LifeStatsLifeTime * 0.33), 0, 1) * 255



		local th = draw_GetFontHeight("ZSHUDFontSmall")

		local x = ScrW() * 0.75

		local y = ScrH() * 0.75



		draw_SimpleTextBlur(translate.Get("that_life"), "ZSHUDFontSmall", x, y, colLifeStats, TEXT_ALIGN_LEFT)

		y = y + th



		if self.LifeStatsBarricadeDamage > 0 then

			draw_SimpleTextBlur(translate.Format("x_damage_to_barricades", self.LifeStatsBarricadeDamage), "ZSHUDFontSmall", x, y, colLifeStats, TEXT_ALIGN_LEFT)

			y = y + th

		end

		if self.LifeStatsHumanDamage > 0 then

			draw_SimpleTextBlur(translate.Format("x_damage_to_humans", self.LifeStatsHumanDamage), "ZSHUDFontSmall", x, y, colLifeStats, TEXT_ALIGN_LEFT)

			y = y + th

		end

		if self.LifeStatsBrainsEaten > 0 then

			draw_SimpleTextBlur(translate.Format("x_brains_eaten", self.LifeStatsBrainsEaten), "ZSHUDFontSmall", x, y, colLifeStats, TEXT_ALIGN_LEFT)

			y = y + th

		end

	end



	local obsmode = MySelf:GetObserverMode()

	if obsmode ~= OBS_MODE_NONE then

		self:ZombieObserverHUD(obsmode)

	elseif not self:GetWaveActive() and not MySelf:Alive() then

		draw_SimpleTextBlur(translate.Get("waiting_for_next_wave"), "ZSHUDFont", ScrW() * 0.5, ScrH() * 0.3, COLOR_DARKRED, TEXT_ALIGN_CENTER)



		if MySelf:GetZombieClassTable().NeverAlive then

			for _, ent in pairs(ents.FindByClass("prop_thrownbaby")) do

				if ent:GetSettled() then

					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)

					break

				end

			end

		end

	end

end



function GM:RequestedDefaultCart()

	local defaultcart = GetConVarString("zs_defaultcart")

	if #defaultcart > 0 then

		defaultcart = string.lower(defaultcart)



		for i, carttab in ipairs(self.SavedCarts) do

			if carttab[1] and string.lower(carttab[1]) == defaultcart then

				gamemode.Call("SuppressArsenalUpgrades", 1)

				RunConsoleCommand("worthcheckout", unpack(carttab[2]))



				return

			end

		end



		RunConsoleCommand("worthrandom")

	end

end



function GM:_PostDrawTranslucentRenderables()

	if not self.DrawingInSky then

		self:DrawPointWorldHints()

		self:DrawWorldHints()

	end

end



function GM:RestartRound()

	self.TheLastHuman = nil

	self.RoundEnded = nil

	LASTHUMAN = nil



	if pEndBoard and pEndBoard:Valid() then

		pEndBoard:Remove()

		pEndBoard = nil

	end



	self:InitPostEntity()



	self:RevertZombieClasses()

end



function GM:_HUDShouldDraw(name)

	if self.FilmMode and name ~= "CHudWeaponSelection" then return false end



	return name ~= "CHudHealth" and name ~= "CHudBattery"

	and name ~= "CHudAmmo" and name ~= "CHudSecondaryAmmo"

	and name ~= "CHudDamageIndicator"

end



local Current = 0

local NextCalculate = 0

function GM:_CachedFearPower()

	if CurTime() >= NextCalculate then

		NextCalculate = CurTime() + 0.15

		Current = self:GetFearMeterPower(EyePos(), TEAM_UNDEAD, MySelf)

	end



	return Current

end



function surface.CreateLegacyFont(font, size, weight, antialias, additive, name, shadow, outline, blursize)

	surface.CreateFont(name, {font = font, size = size, weight = weight, antialias = antialias, additive = additive, shadow = shadow, outline = outline, blursize = blursize})

end



function GM:CreateFonts()

	local fontfamily = "Typenoksidi"

	local fontfamily3d = "hidden"

	local fontweight = 0

	local fontweight3D = 0

	local fontaa = true

	local fontshadow = false

	local fontoutline = true



	surface.CreateLegacyFont("csd", 42, 500, true, false, "healthsign", false, true)

	surface.CreateLegacyFont("tahoma", 96, 1000, true, false, "zshintfont", false, true)



	surface.CreateLegacyFont(fontfamily3d, 48, fontweight3D, false, false,  "ZS3D2DFontSmall", false, true)

	surface.CreateLegacyFont(fontfamily3d, 72, fontweight3D, false, false, "ZS3D2DFont", false, true)

	surface.CreateLegacyFont(fontfamily3d, 128, fontweight3D, false, false, "ZS3D2DFontBig", false, true)

	surface.CreateLegacyFont(fontfamily3d, 48, fontweight3D, false, false,  "ZS3D2DFontSmallBlur", false, false, 16)

	surface.CreateLegacyFont(fontfamily3d, 72, fontweight3D, false, false, "ZS3D2DFontBlur", false, false, 16)

	surface.CreateLegacyFont(fontfamily3d, 128, fontweight3D, false, false, "ZS3D2DFontBigBlur", false, false, 16)

	surface.CreateLegacyFont(fontfamily, 40, fontweight3D, false, false,  "ZS3D2DFont2Smaller", false, true)

	surface.CreateLegacyFont(fontfamily, 48, fontweight3D, false, false,  "ZS3D2DFont2Small", false, true)

	surface.CreateLegacyFont(fontfamily, 72, fontweight3D, false, false, "ZS3D2DFont2", false, true)

	surface.CreateLegacyFont(fontfamily, 128, fontweight3D, false, false, "ZS3D2DFont2Big", false, true)

	surface.CreateLegacyFont(fontfamily, 40, fontweight3D, false, false,  "ZS3D2DFont2SmallerBlur", false, false, 16)

	surface.CreateLegacyFont(fontfamily, 48, fontweight3D, false, false,  "ZS3D2DFont2SmallBlur", false, false, 16)

	surface.CreateLegacyFont(fontfamily, 72, fontweight3D, false, false, "ZS3D2DFont2Blur", false, false, 16)

	surface.CreateLegacyFont(fontfamily, 128, fontweight3D, false, false, "ZS3D2DFont2BigBlur", false, false, 16)



	local screenscale = BetterScreenScale()



	surface.CreateLegacyFont("csd", screenscale * 36, 100, true, false, "zsdeathnoticecs", false, true)

	surface.CreateLegacyFont("HL2MP", screenscale * 36, 100, true, false, "zsdeathnotice", false, true)



	surface.CreateLegacyFont(fontfamily, screenscale * 16, fontweight, fontaa, false, "ZSHUDFontTiny", fontshadow, fontoutline)

	surface.CreateLegacyFont(fontfamily, screenscale * 20, fontweight, fontaa, false, "ZSHUDFontSmallest", fontshadow, fontoutline)

	surface.CreateLegacyFont(fontfamily, screenscale * 22, fontweight, fontaa, false, "ZSHUDFontSmaller", fontshadow, fontoutline)

	surface.CreateLegacyFont(fontfamily, screenscale * 28, fontweight, fontaa, false, "ZSHUDFontSmall", fontshadow, fontoutline)

	surface.CreateLegacyFont(fontfamily, screenscale * 42, fontweight, fontaa, false, "ZSHUDFont", fontshadow, fontoutline)

	surface.CreateLegacyFont(fontfamily, screenscale * 72, fontweight, fontaa, false, "ZSHUDFontBig", fontshadow, fontoutline)

	surface.CreateLegacyFont(fontfamily, screenscale * 16, fontweight, fontaa, false, "ZSHUDFontTinyBlur", false, false, 8)

	surface.CreateLegacyFont(fontfamily, screenscale * 22, fontweight, fontaa, false, "ZSHUDFontSmallerBlur", false, false, 8)

	surface.CreateLegacyFont(fontfamily, screenscale * 28, fontweight, fontaa, false, "ZSHUDFontSmallBlur", false, false, 8)

	surface.CreateLegacyFont(fontfamily, screenscale * 42, fontweight, fontaa, false, "ZSHUDFontBlur", false, false, 8)

	surface.CreateLegacyFont(fontfamily, screenscale * 72, fontweight, fontaa, false, "ZSHUDFontBigBlur", false, false, 8)



	surface.CreateLegacyFont(fontfamily, screenscale * 16, 0, fontaa, false, "ZSAmmoName", false, false)

	surface.CreateLegacyFont(fontfamily, screenscale * 16, fontweight, fontaa, false, "ZSHUDFontTinyNS", false, false)

	surface.CreateLegacyFont(fontfamily, screenscale * 20, fontweight, fontaa, false, "ZSHUDFontSmallestNS", false, false)

	surface.CreateLegacyFont(fontfamily, screenscale * 22, fontweight, fontaa, false, "ZSHUDFontSmallerNS", false, false)

	surface.CreateLegacyFont(fontfamily, screenscale * 28, fontweight, fontaa, false, "ZSHUDFontSmallNS", false, false)

	surface.CreateLegacyFont(fontfamily, screenscale * 42, fontweight, fontaa, false, "ZSHUDFontNS", false, false)

	surface.CreateLegacyFont(fontfamily, screenscale * 72, fontweight, fontaa, false, "ZSHUDFontBigNS", false, false)



	surface.CreateLegacyFont(fontfamily, screenscale * 16, 0, true, false, "ZSDamageResistance", false, true)

	surface.CreateLegacyFont(fontfamily, screenscale * 16, 0, true, false, "ZSDamageResistanceBlur", false, true)



	surface.CreateLegacyFont(fontfamily, 32, fontweight, true, false, "ZSScoreBoardTitle", false, true)

	surface.CreateLegacyFont(fontfamily, 22, fontweight, true, false, "ZSScoreBoardSubTitle", false, true)

	surface.CreateLegacyFont(fontfamily, 16, fontweight, true, false, "ZSScoreBoardPlayer", false, true)

	surface.CreateLegacyFont(fontfamily, 24, fontweight, true, false, "ZSScoreBoardHeading", false, false)

	surface.CreateLegacyFont("arial", 20, 0, true, false, "ZSScoreBoardPlayerSmall", false, true)



	-- Default, DefaultBold, DefaultSmall, etc. were changed when gmod13 hit. These are renamed fonts that have the old values.

	surface.CreateFont("DefaultFontVerySmall", {font = "tahoma", size = 10, weight = 0, antialias = false})

	surface.CreateFont("DefaultFontSmall", {font = "tahoma", size = 11, weight = 0, antialias = false})

	surface.CreateFont("DefaultFontSmallDropShadow", {font = "tahoma", size = 11, weight = 0, shadow = true, antialias = false})

	surface.CreateFont("DefaultFont", {font = "tahoma", size = 13, weight = 500, antialias = false})

	surface.CreateFont("DefaultFontBold", {font = "tahoma", size = 13, weight = 1000, antialias = false})

	surface.CreateFont("DefaultFontLarge", {font = "tahoma", size = 16, weight = 0, antialias = false})

end



function GM:EvaluateFilmMode()

	local visible = not self.FilmMode



	if self.GameStatePanel and self.GameStatePanel:Valid() then

		self.GameStatePanel:SetVisible(visible)

	end



	if self.TopNotificationHUD and self.TopNotificationHUD:Valid() then

		self.TopNotificationHUD:SetVisible(visible)

	end



	if self.CenterNotificationHUD and self.CenterNotificationHUD:Valid() then

		self.CenterNotificationHUD:SetVisible(visible)

	end



	if self.HealthHUD and self.HealthHUD:Valid() then

		self.HealthHUD:SetVisible(visible)

	end

end



function GM:CreateVGUI()

	local screenscale = BetterScreenScale()

	self.GameStatePanel = vgui.Create("DGameState")

	self.GameStatePanel:SetTextFont("ZSHUDFontSmaller")

	self.GameStatePanel:SetAlpha(220)

	self.GameStatePanel:SetSize(screenscale * 420, screenscale * 80)

	self.GameStatePanel:ParentToHUD()



	self.TopNotificationHUD = vgui.Create("DEXNotificationsList")

	self.TopNotificationHUD:SetAlign(RIGHT)

	self.TopNotificationHUD.PerformLayout = function(pan)

		local screenscale = BetterScreenScale()

		pan:SetSize(ScrW() * 0.4, ScrH() * 0.6)

		pan:AlignTop(16 * screenscale)

		pan:AlignRight()

	end

	self.TopNotificationHUD:InvalidateLayout()

	self.TopNotificationHUD:ParentToHUD()



	self.CenterNotificationHUD = vgui.Create("DEXNotificationsList")

	self.CenterNotificationHUD:SetAlign(CENTER)

	self.CenterNotificationHUD:SetMessageHeight(36)

	self.CenterNotificationHUD.PerformLayout = function(pan)

		local screenscale = BetterScreenScale()

		pan:SetSize(ScrW() * 0.5, ScrH() * 0.35)

		pan:CenterHorizontal()

		pan:AlignBottom(16 * screenscale)

	end

	self.CenterNotificationHUD:InvalidateLayout()

	self.CenterNotificationHUD:ParentToHUD()

end



function GM:Initialize()

	self:CreateFonts()

	self:PrecacheResources()

	self:CreateVGUI()

	self:InitializeBeats()

	self:AddCustomAmmo()

end



local function FirstOfGoodType(a)

	for _, v in pairs(a) do

		local ext = string.sub(v, -4)

		if ext == ".ogg" or ext == ".wav" or ext == ".mp3" then

			return v

		end

	end

end



GM.Beats = {}

function GM:InitializeBeats()

	local _, dirs = file.Find("sound/zombiesurvival/beats/*", "GAME")

	for _, dirname in pairs(dirs) do

		if dirname == "none" or dirname == "default" then continue end



		self.Beats[dirname] = {}

		local highestexist

		for i=1, 10 do

			local a, __ = file.Find("sound/zombiesurvival/beats/"..dirname.."/"..i..".*", "GAME")

			local a1 = FirstOfGoodType(a)

			if a1 then

				local filename = "zombiesurvival/beats/"..dirname.."/"..a1

				if file.Exists("sound/"..filename, "GAME") then

					self.Beats[dirname][i] = Sound(filename)

					highestexist = filename



					continue

				end

			end



			if highestexist then

				self.Beats[dirname][i] = highestexist

			end

		end

	end

end



function GM:PlayerDeath(pl, attacker)

end



function GM:OnPlayerHitGround(pl, inwater, hitfloater, speed)

	if inwater then return true end



	if pl:Team() == TEAM_UNDEAD then

		if pl:GetZombieClassTable().NoFallDamage then return true end



		speed = math.max(0, speed - 200)

	end



	if pl:Team() ~= TEAM_UNDEAD or not pl:GetZombieClassTable().NoFallSlowdown then

		pl:RawCapLegDamage(CurTime() + math.min(2, speed * 0.0035))

	end



	return true

end



function GM:LastHuman(pl)

	if not IsValid(pl) then pl = nil end



	self.TheLastHuman = pl



	if not LASTHUMAN then

		LASTHUMAN = true

		timer.Simple(0.5, function() GAMEMODE:LastHumanMessage() end)

	end

end



function GM:LastHumanMessage()

	if self.RoundEnded or not MySelf:IsValid() then return end



	local icon = self.PantsMode and "weapon_zs_legs" or "default"

	if MySelf:Team() == TEAM_UNDEAD or not MySelf:Alive() then

		self:CenterNotify({killicon = icon}, {font = "ZSHUDFont"}, " ", COLOR_RED, translate.Get(self.PantsMode and "kick_the_last_human" or "kill_the_last_human"), {killicon = icon})

	else

		self:CenterNotify({font = "ZSHUDFont"}, " ", COLOR_RED, translate.Get("you_are_the_last_human"))

		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})

	end

end



function GM:PlayerShouldTakeDamage(pl, attacker)

	return pl == attacker or not attacker:IsPlayer() or pl:Team() ~= attacker:Team() or pl.AllowTeamDamage or attacker.AllowTeamDamage

end



function GM:SetWave(wave)

	SetGlobalInt("wave", wave)

end



--[[local texGradientUp = surface.GetTextureID("vgui/gradient_up")

local texGradientDown = surface.GetTextureID("vgui/gradient_down")

local texGradientRight = surface.GetTextureID("vgui/gradient-r")]]

local matFilmGrain = Material("zombiesurvival/filmgrain/filmgrain")

--local color_black = color_black

function GM:_HUDPaintBackground()

	--[[local w, h = ScrW(), ScrH()

	local bordersize = BetterScreenScale() * 32



	surface_SetDrawColor(color_black)



	surface_SetTexture(texGradientDown)

	surface_DrawTexturedRect(0, 0, w, bordersize)

	surface_SetTexture(texGradientUp)

	surface_DrawTexturedRect(0, h - bordersize, w, bordersize)

	surface_SetTexture(texGradientRight)

	surface_DrawTexturedRectRotated(bordersize / 2, h / 2, bordersize, h, 180)

	surface_DrawTexturedRect(w - bordersize, 0, bordersize, h)]]



	if self.FilmGrainEnabled and MySelf:Team() == TEAM_HUMAN then

		surface_SetMaterial(matFilmGrain)

		surface_SetDrawColor(0, 0, 0, (0.25 + 0.75 * self:CachedFearPower()) * self.FilmGrainOpacity)

		surface_DrawTexturedRectUV(0, 0, ScrW(), ScrH(), 2, 2, 0, 0)

	end



	local wep = MySelf:GetActiveWeapon()

	if wep:IsValid() and wep.DrawHUDBackground then

		wep:DrawHUDBackground()

	end

end



local function GiveWeapon()

	RunConsoleCommand("zsgiveweapon")

end

local function GiveWeaponClip()

	RunConsoleCommand("zsgiveweaponclip")

end

local function DropWeapon()

	RunConsoleCommand("zsdropweapon")

end

local function EmptyClip()

	RunConsoleCommand("zsemptyclip")

end

function GM:HumanMenu()

	if self.ZombieEscape then return end



	local ent = MySelf:MeleeTrace(48, 2).Entity

	if self:ValidMenuLockOnTarget(MySelf, ent) then

		self.HumanMenuLockOn = ent

	else

		self.HumanMenuLockOn = nil

	end



	if self.HumanMenuPanel and self.HumanMenuPanel:Valid() then

		self.HumanMenuPanel:SetVisible(true)

		self.HumanMenuPanel:OpenMenu()

		return

	end



	local panel = vgui.Create("DSideMenu")

	self.HumanMenuPanel = panel



	local screenscale = BetterScreenScale()

	for k, v in pairs(self.AmmoNames) do

		local b = vgui.Create("DAmmoCounter", panel)

		b:SetAmmoType(k)

		b:SetTall(screenscale * 36)

		panel:AddItem(b)

	end



	local b = EasyButton(panel, "Give Weapon", 8, 4)

	b.DoClick = GiveWeapon

	panel:AddItem(b)

	b = EasyButton(panel, "Give Weapon and 5 clips", 8, 4)

	b.DoClick = GiveWeaponClip

	panel:AddItem(b)

	b = EasyButton(panel, "Drop weapon", 8, 4)

	b.DoClick = DropWeapon

	panel:AddItem(b)

	b = EasyButton(panel, "Empty clip", 8, 4)

	b.DoClick = EmptyClip

	panel:AddItem(b)



	panel:OpenMenu()

end



GM.ZombieThirdPerson = false

function GM:PlayerBindPress(pl, bind, wasin)

	if bind == "gmod_undo" or bind == "undo" then

		RunConsoleCommand("+zoom")

		timer.CreateEx("ReleaseZoom", 1, 1, RunConsoleCommand, "-zoom")

	elseif bind == "+menu_context" then

		self.ZombieThirdPerson = not self.ZombieThirdPerson

	end

end



function GM:_ShouldDrawLocalPlayer(pl)

	return pl:Team() == TEAM_UNDEAD and (self.ZombieThirdPerson or pl:CallZombieFunction("ShouldDrawLocalPlayer")) or pl:IsPlayingTaunt()

end



local roll = 0

function GM:_CalcView(pl, origin, angles, fov, znear, zfar)

	if pl.Confusion and pl.Confusion:IsValid() then

		pl.Confusion:CalcView(pl, origin, angles, fov, znear, zfar)

	end



	if pl.Revive and pl.Revive:IsValid() and pl.Revive.GetRagdollEyes then

		local rpos, rang = pl.Revive:GetRagdollEyes(pl)

		if rpos then

			origin = rpos

			angles = rang

		end

	elseif pl.KnockedDown and pl.KnockedDown:IsValid() then

		local rpos, rang = self:GetRagdollEyes(pl)

		if rpos then

			origin = rpos

			angles = rang

		end

	elseif pl:ShouldDrawLocalPlayer() and pl:OldAlive() then

		origin = pl:GetThirdPersonCameraPos(origin, angles)

	end



	local targetroll = 0

	if self.MovementViewRoll then

		local dir = pl:GetVelocity()

		local speed = dir:Length()

		dir:Normalize()



		targetroll = targetroll + dir:Dot(angles:Right()) * math.min(30, speed / 100)

	end



	if pl:WaterLevel() >= 3 then

		targetroll = targetroll + math.sin(CurTime()) * 7

	end



	roll = math.Approach(roll, targetroll, math.max(0.25, math.sqrt(math.abs(roll))) * 30 * FrameTime())

	angles.roll = angles.roll + roll



	if pl:IsPlayingTaunt() then

		self:CalcViewTaunt(pl, origin, angles, fov, zclose, zfar)

	end



	local target = pl:GetObserverTarget()

	if target and target:IsValid() then

		local lasttarget = self.LastObserverTarget

		if lasttarget and lasttarget:IsValid() and target ~= lasttarget then

			if self.LastObserverTargetLerp then

				if CurTime() >= self.LastObserverTargetLerp then

					self.LastObserverTarget = nil

					self.LastObserverTargetLerp = nil

				else

					local delta = math.Clamp((self.LastObserverTargetLerp - CurTime()) / 0.3333, 0, 1) ^ 0.5

					origin:Set(self.LastObserverTargetPos * delta + origin * (1 - delta))

				end

			else

				self.LastObserverTargetLerp = CurTime() + 0.3333

			end

		else

			self.LastObserverTarget = target

			self.LastObserverTargetPos = origin

		end

	end



	pl:CallZombieFunction("CalcView", origin, angles)



	return self.BaseClass.CalcView(self, pl, origin, angles, fov, znear, zfar)

end



function GM:CalcViewTaunt(pl, origin, angles, fov, zclose, zfar)

	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})

	origin:Set(tr.HitPos + tr.HitNormal * 2)

end



local staggerdir = VectorRand():GetNormalized()

function GM:_CreateMove(cmd)

	if MySelf:IsPlayingTaunt() and MySelf:Alive() then

		self:CreateMoveTaunt(cmd)

		return

	end



	if MySelf:GetLegDamage() >= 0.5 then

		local buttons = cmd:GetButtons()

		if bit.band(buttons, IN_JUMP) ~= 0 then

			cmd:SetButtons(buttons - IN_JUMP)

		end

	end



	if MySelf:Team() == TEAM_HUMAN then

		if MySelf:Alive() then

			local lockon = self.HumanMenuLockOn

			if lockon then

				if self:ValidMenuLockOnTarget(MySelf, lockon) and self.HumanMenuPanel and self.HumanMenuPanel:Valid() and self.HumanMenuPanel:IsVisible() and MySelf:KeyDown(self.MenuKey) then

					local oldang = cmd:GetViewAngles()

					local newang = (lockon:EyePos() - EyePos()):Angle()

					--oldang.pitch = math.ApproachAngle(oldang.pitch, newang.pitch, FrameTime() * math.max(45, math.abs(math.AngleDifference(oldang.pitch, newang.pitch)) ^ 1.3))

					oldang.yaw = math.ApproachAngle(oldang.yaw, newang.yaw, FrameTime() * math.max(45, math.abs(math.AngleDifference(oldang.yaw, newang.yaw)) ^ 1.3))

					cmd:SetViewAngles(oldang)

				else

					self.HumanMenuLockOn = nil

				end

			else

				local maxhealth = MySelf:GetMaxHealth()

				local threshold = MySelf:GetPalsy() and maxhealth - 1 or maxhealth * 0.25

				local health = MySelf:Health()

				if health <= threshold then

					local ft = FrameTime()



					staggerdir = (staggerdir + ft * 8 * VectorRand()):GetNormalized()



					local ang = cmd:GetViewAngles()

					local rate = ft * ((threshold - health) / threshold) * 7

					ang.pitch = math.NormalizeAngle(ang.pitch + staggerdir.z * rate)

					ang.yaw = math.NormalizeAngle(ang.yaw + staggerdir.x * rate)

					cmd:SetViewAngles(ang)

				end

			end

		end

	else

		MySelf:CallZombieFunction("CreateMove", cmd)

	end

end



function GM:CreateMoveTaunt(cmd)

	cmd:ClearButtons(0)

	cmd:ClearMovement()

end



function GM:PostProcessPermitted(str)

	return false

end



function GM:HUDPaintEndRound()

end



function GM:PreDrawViewModel(vm, pl, wep)

	if pl and pl:IsValid() and pl:IsHolding() then return true end



	if wep and wep:IsValid() and wep.PreDrawViewModel then

		return wep:PreDrawViewModel(vm)

	end

end



function GM:PostDrawViewModel(vm, pl, wep)

	if wep and wep:IsValid() then

		if wep.UseHands or not wep:IsScripted() then

			local hands = pl:GetHands()

			if hands and hands:IsValid() then

				hands:DrawModel()

			end

		end



		if wep.PostDrawViewModel then

			wep:PostDrawViewModel(vm)

		end

	end

end



local undomodelblend = false

local undozombievision = false

local matWhite = Material("models/debug/debugwhite")

function GM:_PrePlayerDraw(pl)

	if pl:CallZombieFunction("PrePlayerDraw") then return true end



	local shadowman = false



	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.

		undomodelblend = true

		render.SetBlend(0)

	elseif MySelf:Team() == TEAM_HUMAN and pl ~= MySelf and pl:Team() == TEAM_HUMAN then

		local radius = self.TransparencyRadius

		if radius > 0 then

			local eyepos = EyePos()

			local dist = pl:NearestPoint(eyepos):Distance(eyepos)

			if dist < radius then

				local blend = math.max((dist / radius) ^ 1.4, 0.04)

				render.SetBlend(blend)

				if blend < 0.4 then

					render.ModelMaterialOverride(matWhite)

					render.SetColorModulation(0.2, 0.2, 0.2)

					shadowman = true

				end

				undomodelblend = true

			end

		end

	end



	pl.ShadowMan = shadowman



	if self.m_ZombieVision and MySelf:Team() == TEAM_UNDEAD and pl:Team() == TEAM_HUMAN and pl:GetPos():Distance(EyePos()) <= pl:GetAuraRange() then

		undozombievision = true



		local green = math.Clamp(pl:Health() / pl:GetMaxHealth(), 0, 1)

		render.ModelMaterialOverride(matWhite)

		render.SetColorModulation(1 - green, green, 0)

		render.SuppressEngineLighting(true)

		cam.IgnoreZ(true)

	end

end



local colFriend = Color(10, 255, 10, 60)

local matFriendRing = Material("SGM/playercircle")

function GM:_PostPlayerDraw(pl)

	pl:CallZombieFunction("PostPlayerDraw")



	if undomodelblend then

		render.SetBlend(1)

		render.ModelMaterialOverride()

		render.SetColorModulation(1, 1, 1)



		undomodelblend = false

	end

	if undozombievision then

		render.ModelMaterialOverride()

		render.SetColorModulation(1, 1, 1)

		render.SuppressEngineLighting(false)

		cam.IgnoreZ(false)



		undozombievision = false

	end



	if pl ~= MySelf and MySelf:Team() == pl:Team() and pl:IsFriend() then

		local pos = pl:GetPos() + Vector(0, 0, 2)

		render.SetMaterial(matFriendRing)

		render.DrawQuadEasy(pos, Vector(0, 0, 1), 32, 32, colFriend)

		render.DrawQuadEasy(pos, Vector(0, 0, -1), 32, 32, colFriend)

	end

end



function GM:DrawCraftingEntity()

	local craftingentity = self.CraftingEntity

	if craftingentity and craftingentity:IsValid() then

		if self.HumanMenuPanel and self.HumanMenuPanel:Valid() and self.HumanMenuPanel:IsVisible() and MySelf:KeyDown(self.MenuKey) then

			local scale = craftingentity:GetModelScale()

			if not scale then return end



			render.ModelMaterialOverride(matWhite)

			render.SuppressEngineLighting(true)

			render.SetBlend(0.025)

			local extrascale = 1.05 + math.abs(math.sin(RealTime() * 7)) * 0.1

			craftingentity:SetModelScale(scale * extrascale, 0)



			local oldpos = craftingentity:GetPos()

			craftingentity:SetPos(oldpos - craftingentity:LocalToWorld(oldpos))

			craftingentity:DrawModel()

			craftingentity:SetPos(oldpos)



			craftingentity:SetModelScale(scale, 0)

			render.SetBlend(1)

			render.SuppressEngineLighting(false)

			render.ModelMaterialOverride(0)

		else

			self.CraftingEntity = nil

		end

	end

end



function GM:HUDPaintBackgroundEndRound()

	local w, h = ScrW(), ScrH()

	local timleft = math.max(0, self.EndTime + self.EndGameTime - CurTime())



	if timleft <= 0 then

		draw_SimpleTextBlur(translate.Get("loading"), "ZSHUDFont", w * 0.5, h * 0.8, COLOR_WHITE, TEXT_ALIGN_CENTER)

	else

		draw_SimpleTextBlur(translate.Format("next_round_in_x", util.ToMinutesSeconds(timleft)), "ZSHUDFontSmall", w * 0.5, h * 0.8, COLOR_WHITE, TEXT_ALIGN_CENTER)

	end

end



local function EndRoundCalcView(pl, origin, angles, fov, znear, zfar)

	if GAMEMODE.EndTime and CurTime() < GAMEMODE.EndTime + 5 then

		local endposition = GAMEMODE.LastHumanPosition

		local override = GetGlobalVector("endcamerapos", 1)

		if type(override) ~= "number" then

			endposition = override

		end

		if endposition then

			local delta = math.Clamp((CurTime() - GAMEMODE.EndTime) * 2, 0, 1)

 

			local start = endposition * delta + origin * (1 - delta)

			local tr = util.TraceHull({start = start, endpos = start + delta * 64 * Angle(0, CurTime() * 30, 0):Forward(), mins = Vector(-2, -2, -2), maxs = Vector(2, 2, 2), filter = player.GetAll(), mask = MASK_SOLID})

			return {origin = tr.HitPos + tr.HitNormal, angles = (start - tr.HitPos):Angle()}

		end



		return

	end



	hook.Remove("CalcView", "EndRoundCalcView")

end



local function EndRoundShouldDrawLocalPlayer(pl)

	if GAMEMODE.EndTime and CurTime() < GAMEMODE.EndTime + 5 then

		return true

	end



	hook.Remove("ShouldDrawLocalPlayer", "EndRoundShouldDrawLocalPlayer")

end



local function EndRoundGetMeleeFilter(self) return {self} end

function GM:EndRound(winner, nextmap)

	if self.RoundEnded then return end

	self.RoundEnded = true



	ROUNDWINNER = winner



	self.EndTime = CurTime()



	RunConsoleCommand("stopsound")



	FindMetaTable("Player").GetMeleeFilter = EndRoundGetMeleeFilter



	self.HUDPaint = self.HUDPaintEndRound

	self.HUDPaintBackground = self.HUDPaintBackgroundEndRound



	if winner == TEAM_UNDEAD and GetGlobalBool("endcamera", true) then

		hook.Add("CalcView", "EndRoundCalcView", EndRoundCalcView)

		hook.Add("ShouldDrawLocalPlayer", "EndRoundShouldDrawLocalPlayer", EndRoundShouldDrawLocalPlayer)

	end



	local dvar = winner == TEAM_UNDEAD and self.AllLoseSound or self.HumanWinSound

	local snd = GetGlobalString(winner == TEAM_UNDEAD and "losemusic" or "winmusic", dvar)

	if snd == "default" then

		snd = dvar

	elseif snd == "none" then

		snd = nil

	end

	if snd then

		timer.Simple(0.5, function() surface_PlaySound(snd) end)

	end



	timer.Simple(5, function()

		if not (pEndBoard and pEndBoard:IsValid()) then

			MakepEndBoard(winner)

		end

	end)

end



function GM:WeaponDeployed(pl, wep)

end



function GM:LocalPlayerDied(attackername)

	LASTDEATH = RealTime()



	surface_PlaySound(self.DeathSound)

	if attackername then

		self:CenterNotify(COLOR_RED, {font = "ZSHUDFont"}, translate.Get("you_have_died"))

		self:CenterNotify(COLOR_RED, translate.Format(self.PantsMode and "you_were_kicked_by_x" or "you_were_killed_by_x", tostring(attackername)))

	else

		self:CenterNotify(COLOR_RED, {font = "ZSHUDFont"}, translate.Get("you_have_died"))

	end

end



function GM:KeyPress(pl, key)

	if key == self.MenuKey then

		if pl:Team() == TEAM_HUMAN and pl:Alive() and not pl:IsHolding() then

			gamemode.Call("HumanMenu")

		end

	elseif key == IN_SPEED then

		if pl:Alive() then

			if pl:Team() == TEAM_HUMAN then

				pl:DispatchAltUse()

			elseif pl:Team() == TEAM_UNDEAD then

				pl:CallZombieFunction("AltUse")

			end

		end

	end

end



function GM:PlayerStepSoundTime(pl, iType, bWalking)

	local time = pl:CallZombieFunction("PlayerStepSoundTime", iType, bWalking)

	if time then

		return time

	end



	if iType == STEPSOUNDTIME_NORMAL or iType == STEPSOUNDTIME_WATER_FOOT then

		return 520 - pl:GetVelocity():Length()

	end



	if iType == STEPSOUNDTIME_ON_LADDER then

		return 500

	end



	if iType == STEPSOUNDTIME_WATER_KNEE then

		return 650

	end



	return 350

end



function GM:PlayerFootstep(pl, vFootPos, iFoot, strSoundName, fVolume)

	return pl:CallZombieFunction("PlayerFootstep", vFootPos, iFoot, strSoundName, fVolume)

end



function GM:PlayerCanCheckout(pl)

	return pl:IsValid() and pl:Team() == TEAM_HUMAN and pl:Alive() and self:GetWave() <= 0

end



function GM:OpenWorth()

	if gamemode.Call("PlayerCanCheckout", MySelf) then

		MakepWorth()

	end

end



function GM:CloseWorth()

	if pWorth and pWorth:Valid() then

		pWorth:Remove()

		pWorth = nil

	end

end



GM.SuppressArsenalTime = 0

function GM:SuppressArsenalUpgrades(suppresstime)

	self.SuppressArsenalTime = math.max(CurTime() + suppresstime, self.SuppressArsenalTime)

end



function GM:Rewarded(class, amount)

	if CurTime() < self.SuppressArsenalTime then return end



	class = class or "0"



	local toptext = translate.Get("arsenal_upgraded")



	local wep = weapons.GetStored(class)

	if wep and wep.PrintName then

		if killicon.Get(class) == killicon.Get("default") then

			self:CenterNotify(COLOR_PURPLE, toptext..": ", color_white, wep.PrintName)

		else

			self:CenterNotify({killicon = class}, " ", COLOR_PURPLE, toptext..": ", color_white, wep.PrintName)

		end

	elseif amount then

		self:CenterNotify(COLOR_PURPLE, toptext..": ", color_white, amount.." "..class)

	else

		self:CenterNotify(COLOR_PURPLE, toptext)

	end

end



function PlayMenuOpenSound()

	LocalPlayer():EmitSound("buttons/lightswitch2.wav", 100, 30)

end



function PlayMenuCloseSound()

	LocalPlayer():EmitSound("buttons/lightswitch2.wav", 100, 20)

end



local DamageFloaters = CreateClientConVar("zs_damagefloaters", "1", true, false):GetBool()

cvars.AddChangeCallback("zs_damagefloaters", function(cvar, oldvalue, newvalue)

	DamageFloaters = newvalue ~= "0"

end)



net.Receive("zs_legdamage", function(length)

	LocalPlayer().LegDamage = net.ReadFloat()

end)



net.Receive("zs_zvols", function(length)

	local volunteers = {}

	local count = net.ReadUInt(8)

	for i=1, count do

		volunteers[i] = net.ReadEntity()

	end



	GAMEMODE.ZombieVolunteers = volunteers

end)



net.Receive("zs_dmg", function(length)

	local damage = net.ReadUInt(16)

	local pos = net.ReadVector()



	if DamageFloaters then

		local effectdata = EffectData()

			effectdata:SetOrigin(pos)

			effectdata:SetMagnitude(damage)

			effectdata:SetScale(0)

		util.Effect("damagenumber", effectdata)

	end

end)



net.Receive("zs_dmg_prop", function(length)

	local damage = net.ReadUInt(16)

	local pos = net.ReadVector()



	if DamageFloaters then

		local effectdata = EffectData()

			effectdata:SetOrigin(pos)

			effectdata:SetMagnitude(damage)

			effectdata:SetScale(1)

		util.Effect("damagenumber", effectdata)

	end

end)



net.Receive("zs_lifestats", function(length)

	local barricadedamage = net.ReadUInt(24)

	local humandamage = net.ReadUInt(24)

	local brainseaten = net.ReadUInt(16)



	GAMEMODE.LifeStatsEndTime = CurTime() + GAMEMODE.LifeStatsLifeTime

	GAMEMODE.LifeStatsBarricadeDamage = barricadedamage

	GAMEMODE.LifeStatsHumanDamage = humandamage

	GAMEMODE.LifeStatsBrainsEaten = brainseaten

end)



net.Receive("zs_lifestatsbd", function(length)

	local barricadedamage = net.ReadUInt(24)



	GAMEMODE.LifeStatsEndTime = CurTime() + GAMEMODE.LifeStatsLifeTime

	GAMEMODE.LifeStatsBarricadeDamage = barricadedamage

end)



net.Receive("zs_lifestatshd", function(length)

	local humandamage = net.ReadUInt(24)



	GAMEMODE.LifeStatsEndTime = CurTime() + GAMEMODE.LifeStatsLifeTime

	GAMEMODE.LifeStatsHumanDamage = humandamage

end)



net.Receive("zs_lifestatsbe", function(length)

	local brainseaten = net.ReadUInt(16)



	GAMEMODE.LifeStatsEndTime = CurTime() + GAMEMODE.LifeStatsLifeTime

	GAMEMODE.LifeStatsBrainsEaten = brainseaten

end)



net.Receive("zs_honmention", function(length)

	local pl = net.ReadEntity()

	local mentionid = net.ReadUInt(8)

	local etc = net.ReadInt(32)



	if pl:IsValid() then

		gamemode.Call("AddHonorableMention", pl, mentionid, etc)

	end

end)



net.Receive("zs_wavestart", function(length)

	local wave = net.ReadInt(16)

	local time = net.ReadFloat()



	gamemode.Call("SetWave", wave)

	gamemode.Call("SetWaveEnd", time)



	if GAMEMODE.ZombieEscape then

		GAMEMODE:CenterNotify(COLOR_RED, {font = "ZSHUDFont"}, translate.Get("escape_from_the_zombies"))

	elseif wave == GAMEMODE:GetNumberOfWaves() then

		GAMEMODE:CenterNotify({killicon = "default"}, {font = "ZSHUDFont"}, " ", COLOR_RED, translate.Get("final_wave"), {killicon = "default"})

		GAMEMODE:CenterNotify(translate.Get("final_wave_sub"))

	else

		local UnlockedClasses = {}

		for i, tab in ipairs(GAMEMODE.ZombieClasses) do

			if tab.Wave <= wave and not tab.Unlocked then

				tab.Unlocked = true

				UnlockedClasses[#UnlockedClasses + 1] = translate.Get(tab.TranslationName)

			end

		end



		GAMEMODE:CenterNotify({killicon = "default"}, {font = "ZSHUDFont"}, " ", COLOR_RED, translate.Format("wave_x_has_begun", wave), {killicon = "default"})

		if #UnlockedClasses > 0 then

			GAMEMODE:CenterNotify(COLOR_GREEN, translate.Format("x_unlocked", string.AndSeparate(UnlockedClasses)))

		end

	end



	surface_PlaySound("ambient/creatures/town_zombie_call1.wav")

end)



net.Receive("zs_waveend", function(length)

	local wave = net.ReadInt(16)

	local time = net.ReadFloat()



	gamemode.Call("SetWaveStart", time)



	if wave < GAMEMODE:GetNumberOfWaves() and wave > 0 then

		GAMEMODE:CenterNotify(COLOR_RED, {font = "ZSHUDFont"}, translate.Format("wave_x_is_over", wave))

		GAMEMODE:CenterNotify(translate.Format("wave_x_is_over_sub", GAMEMODE.ArsenalCrateDiscountPercentage))



		surface_PlaySound("ambient/atmosphere/cave_hit"..math.random(6)..".wav")

	end

end)



net.Receive("zs_gamestate", function(length)

	local wave = net.ReadInt(16)

	local wavestart = net.ReadFloat()

	local waveend = net.ReadFloat()



	gamemode.Call("SetWave", wave)

	gamemode.Call("SetWaveStart", wavestart)

	gamemode.Call("SetWaveEnd", waveend)

end)



local matSkull = Material("zombiesurvival/horderally")

local bossspawnedend

local function BossSpawnedPaint()

	if CurTime() > bossspawnedend then

		hook.Remove("HUDPaint", "BossSpawnedPaint")

		return

	end



	local delta = math.Clamp(bossspawnedend - CurTime(), 0, 1)

	local size = (1 - delta) * math.max(ScrW(), ScrH())



	surface_SetMaterial(matSkull)

	surface_SetDrawColor(160, 0, 0, math.min(delta * 400, 180))

	surface_DrawTexturedRectRotated(ScrW() / 2, ScrH() / 2, size, size, delta * 25)

end

net.Receive("zs_boss_spawned", function(length)

	local ent = net.ReadEntity()

	local classindex = net.ReadUInt(8)



	if ent == MySelf and ent:IsValid() then

		GAMEMODE:CenterNotify({killicon = "default"}, " ", COLOR_RED, translate.Format("you_are_x", translate.Get(GAMEMODE.ZombieClasses[classindex].TranslationName)), {killicon = "default"})

	elseif ent:IsValid() then

		GAMEMODE:CenterNotify({killicon = "default"}, " ", COLOR_RED, (translate.Format("x_has_risen_as_y", ent:Name(), translate.Get(GAMEMODE.ZombieClasses[classindex].TranslationName))), {killicon = "default"})

	else

		GAMEMODE:CenterNotify({killicon = "default"}, " ", COLOR_RED, translate.Format("x_has_risen", translate.Get(GAMEMODE.ZombieClasses[classindex].TranslationName)), {killicon = "default"})

	end



	if MySelf:IsValid() then

		MySelf:EmitSound("npc/zombie_poison/pz_alert1.wav", 0)

	end



	bossspawnedend = CurTime() + 1

	hook.Add("HUDPaint", "BossSpawnedPaint", BossSpawnedPaint)

end)



net.Receive("zs_centernotify", function(length)

	local tab = net.ReadTable()



	GAMEMODE:CenterNotify(unpack(tab))

end)



net.Receive("zs_topnotify", function(length)

	local tab = net.ReadTable()



	GAMEMODE:TopNotify(unpack(tab))

end)



net.Receive("zs_lasthuman", function(length)

	local pl = net.ReadEntity()



	gamemode.Call("LastHuman", pl)

end)



net.Receive("zs_gamemodecall", function(length)

	gamemode.Call(net.ReadString())

end)



net.Receive("zs_lasthumanpos", function(length)

	GAMEMODE.LastHumanPosition = net.ReadVector()

end)



net.Receive("zs_endround", function(length)

	local winner = net.ReadUInt(8)

	local nextmap = net.ReadString()



	gamemode.Call("EndRound", winner, nextmap)

end)



-- Temporary fix

function render.DrawQuadEasy(pos, dir, xsize, ysize, color, rotation)

	xsize = xsize / 2

	ysize = ysize / 2



	local ang = dir:Angle()



	if rotation then

		ang:RotateAroundAxis(ang:Forward(), rotation)

	end



	local upoffset = ang:Up() * ysize

	local rightoffset = ang:Right() * xsize



	render.DrawQuad(pos - upoffset - rightoffset, pos - upoffset + rightoffset, pos + upoffset + rightoffset, pos + upoffset - rightoffset, color)

end

