-- Zombie Survival Final Version for GM 9.0.4 (v4) --
--                             By JetBoom                              --

-- V Options V


-- Set this lower or higher depending on how hard you want the mod.
-- 3.0 = ZS V2 difficulty. 4.0 = ZS V3 Extreme Difficulty
-- 3.5 or more - Reviving
DIFFICULTY = 4.1
-- Time in seconds after the round ends before the map is reset
INTERMISSIONTIME = 30
-- Music/sound used when zombies win
ZOMBIEWINSOUND = "npc/stalker/go_alert2a.wav"
-- Music/sound used when humans survive
HUMANWINSOUND = "zombiesurvival/humanvictory.mp3"
-- Music/sound used when 1 human is left. ONLY works when atleast 4 players in server
LASTHUMANSOUND = "zombiesurvival/lasthuman.mp3"
-- Music/sound played when "Half-Life" has been reached.
HALFLIFESOUND = "zombiesurvival/halflife.mp3"
-- Music/sound played to a person when they turn to The Undead
DEATHSOUND = "music/stingers/HL1_stinger_song8.mp3"
-- Last tier before can join as a human.
HUMANDEADLINE = 2
-- If true, a person is killed when the round starts.
RANDOMFIRSTZOMBIE = true
-- Starting weapon.
STARTWEAPON = "weapons/zombiesurvival/weapon_battleaxe.lua"
-- Number of survival Tiers.
MAXTIERS = 7
-- Amount of time each tier is, in minutes.
TIERTIME = 2.5

REWARDS = {} -- Leave this
REWARDS[1] = {[1]="weapons/zombiesurvival/weapon_deagle.lua", [2]="weapons/zombiesurvival/weapon_glock3.lua"}
REWARDS[2] = {[1]="weapons/zombiesurvival/weapon_uzi.lua", [2]="weapons/zombiesurvival/weapon_smg.lua"}
REWARDS[3] = {[1]="weapons/zombiesurvival/weapon_sweepershotgunmk2.lua"}
REWARDS[4] = {[1]="weapons/zombiesurvival/weapon_rifle.lua", [2]="weapons/zombiesurvival/weapon_crossbowgiver.lua"}
REWARDS[5] = {[1]="weapons/zombiesurvival/weapon_boomstick.lua", [2]="weapons/zombiesurvival/weapon_slamgiver.lua"}
REWARDS[6] = {[1]="weapons/zombiesurvival/weapon_ak47.lua"}
REWARDS[7] = {[1]="weapon_physcannon", [2]="weapons/zombiesurvival/weapon_rocketlauncher.lua"}
THRESHOLDS = {}
THRESHOLDS[1] = 7
THRESHOLDS[2] = 16
THRESHOLDS[3] = 29
THRESHOLDS[4] = 45
THRESHOLDS[5] = 60
THRESHOLDS[6] = 75
THRESHOLDS[7] = 90


function PlayerSetMaxSpeed(userid, speed)
	AddTimer(0.1, 1, _PlayerSetMaxSpeed, userid, speed)
end

-- Name = Display name.
-- Health = Starting health.
-- Threshold = Infliction required.
-- SWEP = Scripted weapon given.
-- Model = Model used.
-- Speed = Max walking speed.
ZombieClasses = {} -- Leave this
ZombieClasses[1] = {Name = "Zombie", Revives = true, Health = 150, Threshold = 0.0, SWEP = "weapons/zombiesurvival/weapon_zombieknife.lua", Model = "models/player/classic.mdl", Speed = 130}
ZombieClasses[2] = {Name = "Fast Zombie", Health = 75, Threshold = 0.5, SWEP = "weapons/zombiesurvival/weapon_fastzombieknife.lua", Model = "models/player/corpse1.mdl", Speed = 220}
ZombieClasses[3] = {Name = "Poison Zombie", Health = 225, Threshold = 0.75, SWEP = "weapons/zombiesurvival/weapon_poisonzombieknife.lua", Model = "models/player/charple01.mdl", Speed = 110}
ZombieClasses[4] = {Name = "Headcrab", Health = 25, Threshold = 0.0, SWEP = "weapons/zombiesurvival/weapon_headcrabknife.lua", Model = "models/headcrabclassic.mdl", Speed = 170}
ZombieClasses[5] = {Name = "Fast Headcrab", Health = 25, Threshold = 0.5, SWEP = "weapons/zombiesurvival/weapon_headcrabknife.lua", Model = "models/headcrab.mdl", Speed = 250}
ZombieClasses[6] = {Name = "Fire Zombie", Health = 35, Threshold = 0.75, SWEP = "weapons/zombiesurvival/weapon_firezombie.lua", Model = "models/player/classic.mdl", Speed = 190}

-- V Developers V

ENDROUND = false
LASTHUMAN = false
HALFLIFE = false
QUARTERLIFE = false
FIRSTDIED = false
ARCADEMODE = false
INFLICTION = 0.01
ROUNDEND = 0
STARTZOMBIE = ""
KILLEDPEOPLE = ""
CURRENTTIER = 1

PlayerInfo = {}
for i=1, _MaxPlayers() do
	PlayerInfo[i] = {}
	PlayerInfo[i].Class = 1
	PlayerInfo[i].LastChange = -30
end

function math.clamp(num, mi, ma)
	if num > ma then num = ma elseif
	num < mi then num = mi end
	return num
end

DIFFICULTY = math.clamp(DIFFICULTY, 0.75, 100.0)

function canPlayerHaveItem(playerid, itemname)
	if isUndead(playerid) then
		return string.find(ZombieClasses[PlayerInfo[playerid].Class].SWEP, itemname) ~= nil
	end
	return true
end

function GiveDefaultItems(userid)
	_player.ShouldDropWeapon(userid, false)
	if isUndead(userid) then
		_PlayerGiveSWEP(userid, ZombieClasses[PlayerInfo[userid].Class].SWEP or "none")
	else
		_PlayerGiveSWEP(userid, "weapons/zombiesurvival/weapon_swissarmyknife.lua")
		_PlayerGiveSWEP(userid, STARTWEAPON)
	end
end

function PlayerSpawnChooseModel(userid)
	if isUndead(userid) then
		_PlayerSetModel(userid, ZombieClasses[PlayerInfo[userid].Class].Model or "models/player/classic.mdl")
	else
		if _PlayerPreferredModel(userid) == "" then
			if _EntGetModel(userid) == DEFAULT_PLAYER_MODEL then
				_PlayerSetModel(userid, "models/player/male_02.mdl")
			end
		else
			_PlayerSetModel(userid, _PlayerPreferredModel(userid))
		end
	end
end

function onShowHelp(userid)
	_GModRect_Start( "gmod/white" )
	 _GModRect_SetPos( 0.2, 0.3, 0.0, 0.0 )
	 _GModRect_SetColor( 0, 0, 0, 100 )
	 _GModRect_SetTime( 15, 0, 1 )
	_GModRect_Send( userid, 50 )

	_GModRect_Start( "gmod/white" )
	 _GModRect_SetPos( 0.198, 0.298, 0.604, 0.154 )
	 _GModRect_SetColor( 0, 0, 0, 150 )
	 _GModRect_SetTime( 15, 0, 1 )
	_GModRect_SendAnimate( userid, 50, 1, 0.2 )

	_GModRect_Start( "gmod/white" )
	 _GModRect_SetPos( 0.2, 0.3, 0.0, 0.0 )
	 _GModRect_SetColor( 0, 0, 0, 10 )
	 _GModRect_SetTime( 15, 0, 1 )
	_GModRect_Send( userid, 51 )

	_GModRect_Start( "gmod/white" )
	 _GModRect_SetPos( 0.2, 0.3, 0.6, 0.15 )
	 _GModRect_SetColor( 0, 0, 0, 50 )
	 _GModRect_SetTime( 15, 0, 1 )
	_GModRect_SendAnimate( userid, 51, 1, 0.2 )

	if isUndead(userid) then
	_GModText_Start( "Default" )
	 _GModText_SetPos( 0.21, 0.36 )
	 _GModText_SetColor( 255, 255, 255, 0 )
	 _GModText_SetTime( 15, 1, 1 )
	 _GModText_SetText( "You are part of The Undead. Kill all of the remaining humans to win the round.\nYou may die as many times as it takes, but do it before the time limit! \n F4=Class Change")
	_GModText_Send( userid, 50 )
	else
	_GModText_Start( "Default" )
	 _GModText_SetPos( 0.21, 0.36 )
	 _GModText_SetColor( 255, 255, 255, 0 )
	 _GModText_SetTime( 15, 1, 1 )
	 _GModText_SetText( "Kill the undead to increase your score. You get weapons at certain score levels.\nDie and you will become an Undead! Humans must survive for the time set to win!" )
	_GModText_Send( userid, 50 )
	end
	
	_GModText_Start( "Default" )
	 _GModText_SetPos( 0.21, 0.36 )
	 _GModText_SetColor( 255, 255, 255, 255 )
	 _GModText_SetTime( 15, 1, 1 )
	_GModText_SendAnimate( userid, 50, 2, 0.2 )

	_GModText_Start( "ImpactMassive" )
	 _GModText_SetPos( 0.41, 0.295 )
	 _GModText_SetColor( 255, 255, 255, 0 )
	 _GModText_SetTime( 15, 1, 1 )
	 _GModText_SetText( "[HELP]" )
	_GModText_Send( userid, 51 )

	_GModText_Start( "ImpactMassive" )
	 _GModText_SetPos( 0.41, 0.295 )
	 _GModText_SetColor( 255, 255, 255, 255 )
	 _GModText_SetTime( 15, 1, 1 )
	_GModText_SendAnimate( userid, 51, 2, 0.2 )
end

function eventPlayerDisconnect(name, userid, address, steamid, reason)
	if IsPlayerOnline(userid) then
		PlayerInfo[userid].Class = 1
		PlayerInfo[userid].LastChange = -30
		--CalculateInfliction()
	end
end

function onShowSpare2(userid)
	if not isUndead(userid) then
		BottomPrintMessage(userid, "This button is for Undead only.", 255, 255, 255, 200)
		return
	elseif _CurTime() < PlayerInfo[userid].LastChange+30.0 then
		BottomPrintMessage(userid, "You must wait a moment\nbefore switching classes!", 255, 255, 255, 200)
		return
	end
	DisplayClassMenu(userid)
end

function ChooseClass(userid, num, seconds)
	_GModRect_Hide(userid, 750, 0.25)
	_GModText_Hide(userid, 751, 0.25)
	local tab = {}
	local x = 1
	for i=1, table.getn(ZombieClasses) do
		if INFLICTION >= ZombieClasses[i].Threshold then
			tab[x] = i
			x = x + 1
		end
	end
	if num > table.getn(tab) then
		return
	end
	PlayerInfo[userid].Class = tab[num]
	CenterPrintMessage(userid, "You are now a "..ZombieClasses[PlayerInfo[userid].Class].Name, 255, 255, 255, 200)
	_PlayerSilentKill(userid, 2, true)
	PlayerInfo[userid].LastChange = _CurTime()
end

function DisplayClassMenu(userid)
	_PlayerOption(userid, "ChooseClass", 99999)	
	 _GModRect_Start( "gmod/white" )
	 _GModRect_SetPos( 0.77, 0.37, 0.325, 0.25 )
	 _GModRect_SetColor( 0, 0, 0, 100 )
	 _GModRect_SetTime( 7.5, 1, 1 )
	_GModRect_Send( userid, 750 )

	_GModText_Start( "Default" )
	 _GModText_SetPos( 0.79, 0.4 )
	 _GModText_SetColor( 255, 255, 255, 255 )
	 _GModText_SetTime( 7.5, 1, 1 )
	 local str = "Choose a Class:\n"
	 local x = 1
	 for i=1, table.getn(ZombieClasses) do
		if INFLICTION >= ZombieClasses[i].Threshold then
			str = str..x..". "..ZombieClasses[i].Name.."\n"
			x = x + 1
		end
	 end
	 str = str.."\n"..x..". Cancel"
	 _GModText_SetText( str )
	_GModText_Send( userid, 751 )
end

function onGravGunPunt(userid, entity)
	if _EntGetModel(entity) == "models/props_lab/monitor01b.mdl" then
		_EntRemove(entity)
		return false
	end
	return true
end

function onGravGunPickup(userid, entity)
	if _EntGetModel(entity) == "models/props_lab/monitor01b.mdl" then
		_EntRemove(entity)
		return false
	end
	return true
end

function onShowTeam(userid)
	if isUndead(userid) then
		BottomPrintMessage(userid, "You'll have to wait untill next round...", 255, 255, 255, 200)
	else
		BottomPrintMessage(userid, "Killing yourself might just work...", 255, 255, 255, 200)
	end
end

function GetPlayerDamageScale(hitgroup)
	if hitgroup == HITGROUP_HEAD then
		return 4.1
	end
	return 0.85
end

function isUndead(userid)
	return _PlayerInfo(userid,"team") == TEAM_GREEN
end

function eventKeyPressed(userid, in_key)
	if in_key == IN_WALK then
		if isUndead(userid) then
			_PlayerKill(userid)
			CenterPrintMessage(userid, "Walk = g4y", 255, 0, 0)
		end
	end
end

lastTick = 0
function gamerulesThink()
	if _CurTime() >= lastTick+3 then
		gamerulesTick()
		lastTick = _CurTime()
	end
	for i=1, _MaxPlayers() do
		if _player.GetFlashlight(i) then
			if isUndead(i) then
				_PlayerSetFlashlight(i, false)
			end
		end
	end
end

function gamerulesTick()
	if (CURRENTTIER*TIERTIME*60) < _CurTime() then
		for i=1, _MaxPlayers() do
			if _PlayerInfo(i, "team") == TEAM_BLUE then
				CheckGiveWeapon(i)
			end
		end
		CURRENTTIER = CURRENTTIER + 1
		if CURRENTTIER > MAXTIERS then
			if not ENDROUND then
				EndRound(1)
				return
			end
		end
		DrawTier(0)
	end
	_GModText_Start( "Default" )
	local msg = ""
	if CURRENTTIER == MAXTIERS then
		msg = "ENDING ROUND"
		 _GModText_SetColor( 255, 0, 0, 255 )
	else
		msg = "Next Tier"
		 _GModText_SetColor( 0, 255, 0, 255 )
	end
	local timetonext = (CURRENTTIER*TIERTIME*60)-_CurTime()
	 _GModText_SetPos( 0.025, 0.01 )
	 _GModText_SetTime( 9999, 0, 0 )
	if not ENDROUND then
		 _GModText_SetText( msg..": "..ToMinutesSeconds(timetonext))
	else
		 _GModText_SetText( "Next Round: "..ToMinutesSeconds(ROUNDEND+INTERMISSIONTIME-_CurTime()))
	end
	_GModText_Send( 0, 666 )
	if not FIRSTDIED then
		if RANDOMFIRSTZOMBIE then
			if _TeamNumPlayers(TEAM_BLUE) > 3 then
				while not FIRSTDIED do
					local i = math.random(1, _MaxPlayers())
					if IsPlayerOnline(i) then
						if _PlayerInfo(i, "team") == TEAM_BLUE then
							JoinUndeadFirst(i)
						end
					end
				end
			end
		end
	end
end

function PickDefaultSpawnTeam(userid)
	if CURRENTTIER > HUMANDEADLINE or LASTHUMAN or string.find(KILLEDPEOPLE, _PlayerInfo(userid, "networkid")) then
		_PlayerChangeTeam(userid, TEAM_GREEN)
		if STARTZOMBIE == "" then
			STARTZOMBIE = _PlayerInfo(userid, "networkid")
		end
		KILLEDPEOPLE = KILLEDPEOPLE.._PlayerInfo(userid, "networkid")
		FIRSTDIED = true
		CalculateInfliction()
	else
		_PlayerChangeTeam(userid, TEAM_BLUE)
	end
	return true
end

function eventPlayerActive(name, userid, steamid)
	Splash(userid)
	drawInfliction(userid)
	DrawTier(userid)
end

function DrawTier(userid)
	_GModText_Start( "Default" )
	 _GModText_SetPos( 0.025, 0.05 )
	 _GModText_SetColor( 255, 0, 0, 255 )
	 _GModText_SetTime( 99999, 0, 0 )
	 _GModText_SetText( "Tier: "..CURRENTTIER.."/"..MAXTIERS)
	_GModText_Send( userid, 751 )
end

function drawInfliction(userid)
	_GModRect_Start("gmod/white")
	 _GModRect_SetPos(0.41, 0.96, (INFLICTION)*0.18, 0.05)
	 _GModRect_SetColor( math.floor(INFLICTION*255), math.floor(255-(INFLICTION*255)), 0, 255 )
	 _GModRect_SetTime(9999, 1, 1)
	_GModRect_Send(userid, 901)
end

function JoinUndead(userid, silent)
	if STARTZOMBIE == "" then
		STARTZOMBIE = _PlayerInfo(userid, "networkid")
	end
	_PlayerChangeTeam(userid, TEAM_GREEN)
	DrawUndeadOverlay(userid)
	CalculateInfliction()
	if not silent then
		_PlaySoundPlayer(userid, DEATHSOUND)
		CenterPrintMessage(userid, "You are dead.", 255, 0, 0, 200)
	end
	KILLEDPEOPLE = KILLEDPEOPLE.._PlayerInfo(userid, "networkid")
end

function JoinUndeadFirst(userid)
	STARTZOMBIE = _PlayerInfo(userid, "networkid")
	_PlayerChangeTeam(userid, TEAM_GREEN)
	DrawUndeadOverlay(userid)
	CalculateInfliction()
	BottomPrintMessage(userid, "You have been chosen to\nstart the Undead army!", 255, 0, 0, 200)
	KILLEDPEOPLE = KILLEDPEOPLE.._PlayerInfo(userid, "networkid")
	FIRSTDIED = true
	_PlayerRespawn(userid)
end

function DrawUndeadOverlay( userid )
	_GModRect_Start( "gmod/white" )
 	 _GModRect_SetPos( 0, 0, 1, 1 )
	 _GModRect_SetColor( 255, 200, 90, 90 )
	 _GModRect_SetTime( 9999, 0, 0 )
	_GModRect_Send( userid, 22 )
end

function gamerulesStartMap()
	PlayerFreezeAll( false )
	_TeamSetName( TEAM_SPECTATOR, "SURVIVED" )
	_TeamSetName( TEAM_BLUE, "Survivers" )
	_TeamSetName( TEAM_GREEN, "The Undead" )
	_TeamSetName( TEAM_YELLOW, "Error in script" )
	_TeamSetName( TEAM_RED, "Error in script" )
	_GameSetTargetIDRules(3)
	_EntPrecacheModel("models/headcrabclassic.mdl")
	_EntPrecacheModel("models/headcrabblack.mdl")
	_EntPrecacheModel("models/headcrab.mdl")
	if not RANDOMFIRSTZOMBIE then
		FIRSTDIED = true
	end
	CreateResFile()
	AddTimer(1, 1, SpawnDisp)
	_Msg("-  Zombie Survival  -\n-     By JetBoom    -\n")

	-- ZS doesn't work because of npc_makers not being Linux friendly or something like that.

	if _IsLinux() then
		for i=1, 4000 do
			if string.find(_EntGetType(i), "maker") ~= nil then
				_EntFire(i, "kill", "", 0.1)
			end
		end
		_Msg("Linux anti-crash.\n")		
	else
		_ServerCommand("sk_zombie_health "..math.clamp(DIFFICULTY*25, 25, 500).."\n")
		_ServerCommand("sk_zombie_dmg_both_slash "..math.clamp(DIFFICULTY*9, 9, 500).."\n")
		_ServerCommand("sk_zombie_dmg_one_slash "..math.clamp(DIFFICULTY*5, 5, 300).."\n")
	end
end

function drawScore(userid)
	if isUndead(userid) then
		_GModText_Hide( userid, 101 )
		return
	end
	_GModText_Start("ImpactMassive")
	 _GModText_SetPos(0.025, 0.80)
	 _GModText_SetColor(255, 0, 0, 255)
	 _GModText_SetTime(99999, 0, 0)
	 _GModText_SetText(_PlayerInfo(userid,"kills").." / "..THRESHOLDS[CURRENTTIER])
	_GModText_Send(userid, 101)
end

function eventNPCKilled(killerid, killed)
	if IsPlayer(killerid) then
		if _PlayerInfo(killerid, "alive") and not isUndead(killerid) then
			_PlayerAddScore(killerid, 1)
			drawScore(killerid)
		end
	end
end

function SecondWind(userid)
	AddTimer(1.75, 1, Revive, userid)
end

function Revive(userid)
	if Gibbed[userid] then return end
	local deadpos = _EntGetPos(userid)
	_PlayerRespawn(userid)
	_EntSetPos(userid, deadpos)
	_EntEmitSound(userid, "npc/zombie/zombie_voice_idle"..math.random( 1, 14 )..".wav")
	_PlayerSetHealth(userid, ZombieClasses[PlayerInfo[userid].Class].Health*0.2 or 30)
end

function eventPlayerKilled(killed, attacker, weapon)
	_PlayerAddDeath(killed, 1)
	if isUndead(killed) then
		if DIFFICULTY >= 3.5 then
			if ZombieClasses[PlayerInfo[killed].Class].Revives then
				if _player.LastHitGroup(killed) > HITGROUP_HEAD and IsPlayer(attacker) and attacker ~= killed then
					if weapon ~= "sweepershotgunmk2" and string.find(weapon, "env") == nil then
						SecondWind(killed)
						return
					end
				end
			end
		end
		if IsPlayer(attacker) then
			_PlayerAddScore(attacker, 1)
			drawScore(attacker)
		end
	else
		_PlaySound("npc/stalker/go_alert2a.wav")
		JoinUndead(killed, false)
		_PlayerSetScore(killed, 0)
		FIRSTDIED = true
		if IsPlayer(attacker) and attacker ~= killed then
			_PlayerAddScore(attacker, 1)
			SecondWind(killed)
		end
	end
end

function onTakeDamage(ent, inflictor, attacker, damage)
	if IsPlayer(ent) then
		if damage > _PlayerInfo(ent, "health")+39 then
			if IsPlayer(attacker) then
				if _PlayerInfo(attacker, "team") ~= _PlayerInfo(ent, "team") then
					Gib(ent)
				end
			else
				Gib(ent)
			end
		end
	end
end

-- NoXious gibbing system

GibModels = {}
GibModels[1]="models/Gibs/Antlion_gib_medium_1.mdl"
GibModels[2]="models/Gibs/Antlion_gib_small_1.mdl"
GibModels[3]="models/Gibs/Antlion_gib_medium_2.mdl"
GibModels[4]="models/Gibs/Antlion_gib_medium_3.mdl"
GibModels[5]="models/Gibs/Antlion_gib_small_1.mdl"
GibModels[6]="models/Gibs/Antlion_gib_small_2.mdl"

Gibbed = {}
for i=1, _MaxPlayers() do
	Gibbed[i] = false
end

function IsInRadius(a, b, dist)
	return math.abs(vecLength(vecSub(_EntGetPos(a),_EntGetPos(b)))) <= dist
end

-- Finally, corpse eating.
function CheckCorpseExplode(x, y, z)
	local ents = _EntitiesFindInSphere(vector3(x, y, z), 125)
	for i=1, table.getn(ents) do
		if IsPlayer(ents[i]) then
			if not Gibbed[ents[i]] then
				if IsPlayerOnline(ents[i]) and not _PlayerInfo(ents[i], "alive") then
					Gib(ents[i])
				end
			end
		end
	end
end

function IsInRadius(a, b, dist)
	return math.abs(vecLength(vecSub(_EntGetPos(a),_EntGetPos(b)))) <= dist
end

function eventPlayerUseEntity(userid, entity)
	if isUndead(userid) then
		if _EntGetName(entity) == "gibs" then
			if not IsInRadius(userid, entity, 120) then return true end
			local maxhealth = ZombieClasses[PlayerInfo[userid].Class].Health
			local health = _PlayerInfo(userid, "health")
			if health < maxhealth then
				_PlayerSetHealth(userid, health+(math.ceil(maxhealth*0.1)))
				if _PlayerInfo(userid, "health") > maxhealth then
					_PlayerSetHealth(userid, maxhealth)
				end
				_EntEmitSound(entity, "physics/body/body_medium_break"..math.random(2, 4)..".wav")
				_EntFire(entity, "kill", "", 0.01)
				return true
			end
		end
	end
	return false
end

function Gib(killed)
	if Gibbed[killed] then return end
	Gibbed[killed] = true
	_TraceLine(_EntGetPos(killed), vector3(0,0,-1), 100, killed)
	if _TraceHit() then
		_MakeDecal(math.random(46,51))
	end

	local gibstospawn = {}
	gibstospawn[1] = "models/gibs/HGIBS.mdl"
	gibstospawn[2] = "models/gibs/HGIBS_rib.mdl"
	gibstospawn[3] = "models/gibs/HGIBS_scapula.mdl"
	gibstospawn[4] = "models/gibs/HGIBS_spine.mdl"
	gibstospawn[5] = GibModels[math.random(1, table.getn(GibModels))]
	gibstospawn[6] = GibModels[math.random(1, table.getn(GibModels))]
	for i in gibstospawn do
		local gib = _EntCreate("prop_physics_multiplayer")
		if gib > 0 then
			_EntPrecacheModel(gibstospawn[i])
			_EntSetModel(gib, gibstospawn[i])
			_EntSetKeyValue(gib, "spawnflags", "4")
			_EntSetPos(gib, vecAdd(_EntGetPos(killed), vector3(math.random(-10,10),math.random(-10,10),math.random(10,30))))
			_EntSetAngAngle(gib, vector3(math.random(0,359), math.random(0,359), math.random(0,359)))
			_EntSetName(gib, "gibs")
			_EntSpawn(gib)
			_phys.ApplyForceCenter(gib, vector3(math.random(-2500, 2500), math.random(-2500, 2500), math.random(0, 5000)))
			_phys.ApplyForceCenter(gib, vecMul(_EntGetVelocity(killed), vector3(8,8,8)))
			_phys.ApplyTorqueCenter(gib, vector3(math.random(-8000, 8000), math.random(-8000, 8000), math.random(-8000, 8000)))
			_EntFire(gib, "kill", "", 15)
		end
	end
	_EntEmitSoundEx(killed, "physics/flesh/flesh_bloody_break.wav", 1.0, 0.75)
	AddTimer(0.11, 1, _PlayerSilentKill, killed, 1.5, true)
end

function CheckGiveWeapon(userid)
	local score = _PlayerInfo(userid, "kills")
	local needed = THRESHOLDS[CURRENTTIER]
	if score >= needed then
		local weap = _EntGetType(_PlayerGetActiveWeapon(userid))
		local newwep = REWARDS[CURRENTTIER] newwep = newwep[math.random(1, table.getn(newwep))]
		_PlayerGiveSWEP(userid, newwep)
		_PlayerSelectWeapon(userid, weap)
		BottomPrintMessage(userid, " Your arsenal has been upgraded...", 20, 255, 20)
		_PlaySoundPlayer(userid, "weapons/physcannon/physcannon_charge.wav")
		drawScore(userid)
	else
		BottomPrintMessage(userid, "You did not meet the requirements...", 255, 20, 20)
		_PlaySoundPlayer(userid, "buttons/button2.wav")
		drawScore(userid)
	end
end

function Splash(userid)
	_GModRect_Start("gmod/white")
	 _GModRect_SetPos(0.4, 0.95, 0.2, 0.1)
	 _GModRect_SetColor(0, 0, 0, 200)
	 _GModRect_SetTime(99999, 0, 0)
	_GModRect_Send(userid, 899)

	_GModRect_Start( "models/props_lab/tank_glass001" )
	 _GModRect_SetPos(0.0, 0.0, 0.1, 0.1)
	 _GModRect_SetColor(255, 255, 255, 15)
	 _GModRect_SetTime(1.0, 0, 0)
	 _GModRect_SetDelay(3)
	_GModRect_Send(userid, 9111)
	
	_GModText_Start("Default")
	 _GModText_SetPos(-1, 0.93)
	 _GModText_SetColor(255, 0, 0, 255)
	 _GModText_SetTime(99999, 0, 0)
	 _GModText_SetText("Infliction")
	_GModText_Send( userid, 900)

	_GModRect_Start( "gmod/white" )
	 _GModRect_SetPos( 0.0, 0.0, 0.15, 0.08 )
	 _GModRect_SetColor( 0, 0, 0, 150 )
	 _GModRect_SetTime( 99999, 0, 0 )
	_GModRect_Send( userid, 665 )

	_GModText_Start( "BudgetLabel" )
	 _GModText_SetPos( 0.8, 0.01 )
	 _GModText_SetColor( 255, 30, 5, 230 )
	 _GModText_SetTime( 9999, 0, 0 )
	 _GModText_SetText("Zombie Survival v4.2\nBy JetBoom")
	_GModText_Send( userid, 955 )

	_GModRect_Start( "zombiesurvival/zssplash_v4" )
	 _GModRect_SetPos( 0.21, 0.095, 0.6, 0.6 )
	 _GModRect_SetColor( 255, 255, 255, 255 )
	 _GModRect_SetTime( 10, 1, 1 )
	_GModRect_Send( userid, 245 )

	_GModText_Start( "Default" )
	 _GModText_SetPos( -1.0, 0.51 )
	 _GModText_SetColor( 100, 100, 255, 255 )
	 _GModText_SetTime( 10, 1, 1 )
	 _GModText_SetText("Difficulty: "..DIFFICULTY.."x")
	_GModText_Send( userid, 246 )
end

function CreateResFile()
	local str = [["resources"
	{
	"sound/zombiesurvival/minutes.mp3" "file"
	"sound/zombiesurvival/remaining.mp3" "file"
	"materials/zombiesurvival/zssplash_v4.vmt" "file"
	"materials/zombiesurvival/zssplash_v4.vtf" "file"
	"materials/deathnotify/d_brains.vmt" "file"
	"materials/deathnotify/d_brains.vtf" "file"
	}]]
	_file.Write("maps/".._GetCurrentMap()..".res", str)
end

function CalculateInfliction()
	local PlayerCount=_TeamNumPlayers(TEAM_BLUE) + _TeamNumPlayers(TEAM_GREEN)
	local ZombieCount=_TeamNumPlayers(TEAM_GREEN)
	INFLICTION = ZombieCount/PlayerCount
	if INFLICTION >=1.0 and not ENDROUND then
		EndRound(2)
	elseif INFLICTION >= 0.5 and not HALFLIFE then
		HalfLife()
	elseif PlayerCount-ZombieCount <= 1 and PlayerCount > 3 and not LASTHUMAN then
		LastHuman()
	end
	drawInfliction(0)
end

function HalfLife()
	_PlaySound(HALFLIFESOUND)
	HALFLIFE = true
	BottomPrintMessage(0, "'Half-Life' has been reached!", 255, 255, 255, 200)
end

function LastHuman()
	_PlaySound(LASTHUMANSOUND)
	LASTHUMAN = true
	for i=1, _MaxPlayers() do
		if _PlayerInfo(i, "connected") then
			if isUndead(i) then
				BottomPrintMessage(i, "Kill the last human!", 255, 255, 255, 255)
			else
				BottomPrintMessage(i, "You are the last human alive!", 255, 255, 255, 255)
			end
		end
	end
end

function EndRound(winner)
	if ENDROUND then return end
	ENDROUND = true
	ROUNDEND = _CurTime()
	AddTimer(INTERMISSIONTIME, 1, _StartNextLevel)
	if winner == 1 then
		if LASTHUMAN then
			for i=1, _MaxPlayers() do
				if IsPlayerOnline(i) then
					if not isUndead(i) then
						CenterPrintMessage(0, _PlayerInfo(i, "name").." has survived...\nNext round in "..INTERMISSIONTIME.." seconds.", 20, 20, 255, 255)
						break
					end
				end
			end	
		else
			CenterPrintMessage(0, "The remaining humans have survived...\nNext round in "..INTERMISSIONTIME.." seconds.", 20, 20, 255, 255)
		end
		_PlaySound(HUMANWINSOUND)
		for i=1, _MaxPlayers() do
			if IsPlayerOnline(i) then
				if isUndead(i) then
					BottomPrintMessage(i, "You have lost the match.", 255, 20, 20, 255)
				else
					_PlayerGod(i, true)
					BottomPrintMessage(i, "You have won the match.", 20, 20, 255, 255)
					_PlayerChangeTeam(i, TEAM_SPECTATOR)
					_PlayerRespawn(i)
				end
			end
		end
	elseif winner == 2 then
		local TheWinner = 0
		for i=1, _MaxPlayers() do
			if _PlayerInfo(i, "networkid") == STARTZOMBIE then
				TheWinner = i
			end
		end
		if TheWinner <= 0 then
			CenterPrintMessage(0, "The Undead have conquered...\n   Next round in "..INTERMISSIONTIME.." seconds.", 255, 0, 0, 255)
		else
			CenterPrintMessage(0, "  The Undead have conquered.\n".._PlayerInfo(TheWinner, "name").." has spread their evil...\n  Next round in "..INTERMISSIONTIME.." seconds.", 255, 0, 0, 255)
			for i=1, _MaxPlayers() do
				if STARTZOMBIE ~= _PlayerInfo(i, "networkid") then
					BottomPrintMessage(i, "You have lost the match.", 255, 20, 20, 255)
				else
					BottomPrintMessage(i, "You have won the match.", 20, 20, 255, 255)
				end
			end
		end
		_PlaySound(ZOMBIEWINSOUND)
	end
end

function FiveMinuteWarning()
	if ENDROUND then return end
	BottomPrintMessage(0, "- 5 Minute Warning -", 255, 20, 50, 200)
	_PlaySound("HL1/fvox/five.wav")
	AddTimer(0.8, 1, _PlaySound, "zombiesurvival/minutes.mp3")
	AddTimer(1.53, 1, _PlaySound, "zombiesurvival/remaining.mp3")
end

function CenterPrintMessage(userid, msg, r, g, b)
	_GModRect_Start( "gmod/white" )
	 _GModRect_SetPos( 0.37, 0.37, 0.325, 0.1 )
	 _GModRect_SetColor( 0, 0, 0, 100 )
	 _GModRect_SetTime( 7.5, 1, 1 )
	_GModRect_Send( userid, 500 )

	_GModText_Start( "DefaultShadow" )
	 _GModText_SetPos( -1, 0.4 )
	 _GModText_SetColor( r, g, b, 240 )
	 _GModText_SetTime( 7.5, 1, 1 )
	 _GModText_SetText( msg )
	_GModText_Send( userid, 501 )
end

function BottomPrintMessage(userid, msg, r, g, b)
	_GModRect_Start( "gmod/white" )
	 _GModRect_SetPos( 0.37, 0.77, 0.325, 0.1 )
	 _GModRect_SetColor( 0, 0, 0, 100 )
	 _GModRect_SetTime( 7.5, 1, 1 )
	_GModRect_Send( userid, 520 )

	_GModText_Start( "DefaultShadow" )
	 _GModText_SetPos( -1, 0.8 )
	 _GModText_SetColor( r, g, b, 240 )
	 _GModText_SetTime( 7.5, 1, 1 )
	 _GModText_SetText( msg )
	_GModText_Send( userid, 521 )
end
	
function SidePrintMessage(userid, msg, r, g, b)
	_GModRect_Start( "gmod/white" )
	 _GModRect_SetPos( 0.77, 0.37, 0.325, 0.1 )
	 _GModRect_SetColor( 0, 0, 0, 100 )
	 _GModRect_SetTime( 7.5, 1, 1 )
	_GModRect_Send( userid, 520 )

	_GModText_Start( "DefaultShadow" )
	 _GModText_SetPos( 0.79, 0.4 )
	 _GModText_SetColor( r, g, b, 240 )
	 _GModText_SetTime( 7.5, 1, 1 )
	 _GModText_SetText( msg )
	_GModText_Send( userid, 521 )
end

disp1 = 0
disp2 = 0
disp3 = 0
disp4 = 0
disp5 = 0
disp6 = 0
disp7 = 0
disp8 = 0

function SpawnDisp()
	disp1 = _EntCreate( "ai_relationship" )
	if disp1 > 0 then
		_EntSetKeyValue( disp1, "subject", "npc_headcrab")
		_EntSetKeyValue( disp1, "target", "zombieplayer")
		_EntSetKeyValue( disp1, "disposition", 3)
		_EntSetKeyValue( disp1, "Radius for subject", 99999)
		_EntSetKeyValue( disp1, "rank", 99)
		_EntSetKeyValue( disp1, "Reciprocal", 1)
		_EntSetPos(disp1, vector3(0, 0, 0))
		_EntSpawn(disp1)
	end
	disp2 = _EntCreate( "ai_relationship" )
	if disp2 > 0 then
		_EntSetKeyValue( disp2, "subject", "npc_headcrab_fast")
		_EntSetKeyValue( disp2, "target", "zombieplayer")
		_EntSetKeyValue( disp2, "disposition", 3)
		_EntSetKeyValue( disp2, "Radius for subject", 99999)
		_EntSetKeyValue( disp2, "rank", 99)
		_EntSetKeyValue( disp2, "Reciprocal", 1)
		_EntSetPos(disp2, vector3(0, 0, 0))
		_EntSpawn(disp2)
	end
	disp3 = _EntCreate( "ai_relationship" )
	if disp3 > 0 then
		_EntSetKeyValue( disp3, "subject", "npc_headcrab_black")
		_EntSetKeyValue( disp3, "target", "zombieplayer")
		_EntSetKeyValue( disp3, "disposition", 3)
		_EntSetKeyValue( disp3, "Radius for subject", 99999)
		_EntSetKeyValue( disp3, "rank", 99)
		_EntSetKeyValue( disp3, "Reciprocal", 1)
		_EntSetPos(disp3, vector3(0, 0, 0))
		_EntSpawn(disp3)
	end
	disp4 = _EntCreate( "ai_relationship" )
	if disp4 > 0 then
		_EntSetKeyValue( disp4, "subject", "npc_fastzombie")
		_EntSetKeyValue( disp4, "target", "zombieplayer")
		_EntSetKeyValue( disp4, "disposition", 3)
		_EntSetKeyValue( disp4, "Radius for subject", 99999)
		_EntSetKeyValue( disp4, "rank", 99)
		_EntSetKeyValue( disp4, "Reciprocal", 1)
		_EntSetPos(disp4, vector3(0, 0, 0))
		_EntSpawn(disp4)
	end
	disp5 = _EntCreate( "ai_relationship" )
	if disp5 > 0 then
		_EntSetKeyValue( disp5, "subject", "npc_zombie")
		_EntSetKeyValue( disp5, "target", "zombieplayer")
		_EntSetKeyValue( disp5, "disposition", 3)
		_EntSetKeyValue( disp5, "Radius for subject", 99999)
		_EntSetKeyValue( disp5, "rank", 99)
		_EntSetKeyValue( disp5, "Reciprocal", 1)
		_EntSetPos(disp5, vector3(0, 0, 0))
		_EntSpawn(disp5)
	end
	disp6 = _EntCreate( "ai_relationship" )
	if disp6 > 0 then
		_EntSetKeyValue( disp6, "subject", "npc_poisonzombie")
		_EntSetKeyValue( disp6, "target", "zombieplayer")
		_EntSetKeyValue( disp6, "disposition", 3)
		_EntSetKeyValue( disp6, "Radius for subject", 99999)
		_EntSetKeyValue( disp6, "rank", 99)
		_EntSetKeyValue( disp6, "Reciprocal", 1)
		_EntSetPos(disp6, vector3(0, 0, 0))
		_EntSpawn(disp6)
	end
	disp7 = _EntCreate( "ai_relationship" )
	if disp7 > 0 then
		_EntSetKeyValue( disp7, "subject", "npc_poisonzombie")
		_EntSetKeyValue( disp7, "target", "zombieplayer")
		_EntSetKeyValue( disp7, "disposition", 3)
		_EntSetKeyValue( disp7, "Radius for subject", 99999)
		_EntSetKeyValue( disp7, "rank", 99)
		_EntSetKeyValue( disp7, "Reciprocal", 1)
		_EntSetPos(disp7, vector3(0, 0, 0))
		_EntSpawn(disp7)
	end
	disp8 = _EntCreate( "ai_relationship" )
	if disp8 > 0 then
		_EntSetKeyValue(disp8, "subject", "npc_zombie_torso")
		_EntSetKeyValue(disp8, "target", "zombieplayer")
		_EntSetKeyValue(disp8, "disposition", 3)
		_EntSetKeyValue(disp8, "Radius for subject", 99999)
		_EntSetKeyValue(disp8, "rank", 99)
		_EntSetKeyValue(disp8, "Reciprocal", 1)
		_EntSetPos(disp8, vector3(0, 0, 0))
		_EntSpawn(disp8)
	end
end

function ApplyDisp()
	_EntFire(disp1, "ApplyRelationship", "", 0)
	_EntFire(disp2, "ApplyRelationship", "", 0.2)
	_EntFire(disp3, "ApplyRelationship", "", 0.4)
	_EntFire(disp4, "ApplyRelationship", "", 0.6)
	_EntFire(disp5, "ApplyRelationship", "", 0.8)
	_EntFire(disp6, "ApplyRelationship", "", 1.0)
	_EntFire(disp7, "ApplyRelationship", "", 1.2)
	_EntFire(disp8, "ApplyRelationship", "", 1.4)
end

function eventPlayerSpawn(userid)
	AddTimer(0.1, 1, _PlayerEnableSprint, userid, false)
	Gibbed[userid] = false
	if isUndead(userid) then
		_EntSetName(userid, "zombieplayer")
		ApplyDisp()
		_PlayerSetDrawViewModel(userid, false)
		_PlayerSetHealth(userid, ZombieClasses[PlayerInfo[userid].Class].Health or 100)
		PlayerSetMaxSpeed(userid, ZombieClasses[PlayerInfo[userid].Class].Speed or 170)
		_EntSetMaxHealth(userid, 1)
	else
		_PlayerSetDrawViewModel(userid, true)
	end
	drawScore(userid)
end

function ThrowHeadCrab(userid)
	AddTimer(2.0, 1, DoThrowHeadCrab, userid)
end

function DoThrowHeadCrab(userid)
	if not isUndead(userid) or not _PlayerInfo(userid, "alive") then return end
	_EntEmitSound(userid, "npc/headcrab_poison/ph_jump"..math.random(1,3)..".wav")

	local headcrab = _EntCreate( "npc_headcrab_black")
	if headcrab > 0 then
		local angle = _PlayerGetShootAng(userid)
		angle.z = 0
		local pos = _PlayerGetShootPos(userid)
		pos.z = pos.z+5
		_EntSetPos(headcrab, vecAdd(pos, vecMul(angle, vector3(55,55,55))))
		_EntSetAng(headcrab, _EntGetAng(userid))
		local fireforce = vecMul(_PlayerGetShootAng(userid), vector3(600, 600, 600*1.25))
		_EntSpawn(headcrab)
		_EntSetVelocity(headcrab, fireforce)
		ApplyDisp()
	end
end

function PlayerUnlock(userid)
	AddTimer(2.5, 1, _PlayerLockInPlace, userid, false)
end
