#include extreme\_ex_drm;

/*
	Liberation
	Objective: 	Capture the enemy team in Jail, free your teamates from enemy jail
	Map ends:	When one team jails the entire enemy team
	Respawning:	Into jail after starting round at base

	Level requirements
	------------------


		Spectator Spawnpoints:
			classname		mp_global_intermission
			Spectators spawn from these and intermission is viewed from these positions.
			Atleast one is required, any more and they are randomly chosen between.

	Level script requirements
	-------------------------
		Team Definitions:

			game["axis"] = "german";
			This sets the nationalities of the teams. Allies can be american, british, or russian. Axis can be german.

		If using minefields or exploders:
			maps\mp\_load::main();

	Optional level script settings
	------------------------------
		Soldier Type and Variation:
			game["american_soldiertype"] = "normandy";
			game["german_soldiertype"] = "normandy";
			This sets what character models are used for each nationality on a particular map.

			Valid settings:
				american_soldiertype	normandy
				british_soldiertype		normandy, africa
				russian_soldiertype		coats, padded
				german_soldiertype		normandy, africa, winterlight, winterdark
*/

/*QUAKED mp_ctf_spawn_allied (0.0 1.0 0.0) (-16 -16 0) (16 16 72)
Players spawn away from enemies and near their team at one of these positions.
*/

/*QUAKED mp_ctf_spawn_axis (1.0 0.0 0.0) (-16 -16 0) (16 16 72)
Players spawn away from enemies and near their team at one of these positions.
*/

main()
{
	level.callbackStartGameType = ::Callback_StartGameType;
	level.callbackPlayerConnect = ::Callback_PlayerConnect;
	level.callbackPlayerDisconnect = ::Callback_PlayerDisconnect;
	level.callbackPlayerDamage = ::Callback_PlayerDamage;
	level.callbackPlayerKilled = ::Callback_PlayerKilled;
	maps\mp\gametypes\_callbacksetup::SetupCallbacks();
//////////////////////////////////////////////////////////////////////////
//DaMole EndMapVote
	thread maps\mp\gametypes\_mapvote::Init();
//DaMole
//////////////////////////////////////////////////////////////////////////
	level.autoassign = extreme\_ex_clientcontrol::menuAutoAssign;
	level.allies = extreme\_ex_clientcontrol::menuAllies;
	level.axis = extreme\_ex_clientcontrol::menuAxis;
	level.spectator = extreme\_ex_clientcontrol::menuSpectator;
	level.weapon = extreme\_ex_clientcontrol::menuWeapon;
	level.spawnplayer = ::spawnplayer;
	level.endgameconfirmed = ::endMap;

	// set eXtreme+ variables and precache
	extreme\_ex_varcache::main();
	
}

Callback_StartGameType()
{
	level.splitscreen = isSplitScreen();

	if(!isdefined(game["gamestarted"]))
	{
		// defaults if not defined in level script
		if(!isDefined(game["allies"]))
			game["allies"] = "american";
		if(!isDefined(game["axis"]))
			game["axis"] = "german";


		// just to get sound working at start round?
		if(!isdefined(game["attackers"]))
			game["attackers"] = "allies";
		if(!isdefined(game["defenders"]))
			game["defenders"] = "axis";


		// server cvar overrides
		if(drm_getCvar("scr_allies") != "")
			game["allies"] = drm_getCvar("scr_allies");
		if(drm_getCvar("scr_axis") != "")
			game["axis"] = drm_getCvar("scr_axis");

		
		//precacheStatusIcon("hud_status_dead");
		//precacheStatusIcon("hud_status_connecting");
		precacheRumble("damage_heavy");

		precacheShader("objective");
		precacheString(&"MP_SLASH");
		precacheString(&"MP_TIME_TILL_SPAWN");
		precacheString(&"PLATFORM_PRESS_TO_SPAWN");
		precacheString(&"MP_MATCHSTARTING");
		precacheString(&"MP_MATCHRESUMING");
		precacheString(&"MP_ROUNDDRAW");
		precacheString(&"MP_ALLIEDMISSIONACCOMPLISHED");
		precacheString(&"MP_AXISMISSIONACCOMPLISHED");
		precacheString(&"LIB_WAITING_FOR");
		precacheString(&"LIB_AXIS_WIN");
		precacheString(&"LIB_ALLIES_WIN");
		precacheString(&"LIB_AXISFREED");
		precacheString(&"LIB_ALLIESFREED");
		switch(game["allies"])
		{
		case "american":
			game["hudicon_allies"] = "hudicon_american";
			break;
	
		case "british":
			game["hudicon_allies"] = "hudicon_british";
			break;
	
		case "russian":
			game["hudicon_allies"] = "hudicon_russian";
			break;
		}
	
		assert(game["axis"] == "german");
		game["hudicon_axis"] = "hudicon_german";

		//precacheShader(game["hudicon_allies"]);
		//precacheShader(game["hudicon_axis"]);
	}

	thread maps\mp\gametypes\_menus::init();
	thread maps\mp\gametypes\_serversettings::init();
	thread maps\mp\gametypes\_clientids::init();
	thread maps\mp\gametypes\_teams::init();
	thread maps\mp\gametypes\_weapons::init();
	thread maps\mp\gametypes\_scoreboard::init();
	thread maps\mp\gametypes\_killcam::init();
	thread maps\mp\gametypes\_shellshock::init();
	thread maps\mp\gametypes\_hud_teamscore::init();
	thread maps\mp\gametypes\_deathicons::init();
	thread maps\mp\gametypes\_damagefeedback::init();
	thread maps\mp\gametypes\_healthoverlay::init();
	thread maps\mp\gametypes\_friendicons::init();
	thread maps\mp\gametypes\_spectating::init();
	thread maps\mp\gametypes\_grenadeindicators::init();
	thread maps\mp\gametypes\_landmines::Init();
	thread extreme\_ex_varcache::postmapload();

	level.xenon = (getcvar("xenonGame") == "true");
	thread maps\mp\gametypes\_quickmessages::init();

	setClientNameMode("auto_change");

	spawnpointname = "mp_lib_spawn_alliesnonjail";
	spawnpoints = getentarray(spawnpointname, "classname");

	if(!spawnpoints.size)
	{
		maps\mp\gametypes\_callbacksetup::AbortLevel();
		return;
	}

	for(i = 0; i < spawnpoints.size; i++)
		spawnpoints[i] placeSpawnpoint();

	spawnpointname = "mp_lib_spawn_axisnonjail";
	spawnpoints = getentarray(spawnpointname, "classname");

	if(!spawnpoints.size)
	{
		maps\mp\gametypes\_callbacksetup::AbortLevel();
		return;
	}

	for(i = 0; i < spawnpoints.size; i++)
		spawnpoints[i] PlaceSpawnpoint();

	spawnpointname = "mp_lib_spawn_alliesinjail";
	spawnpoints = getentarray(spawnpointname, "classname");

	if(!spawnpoints.size)
	{
		maps\mp\gametypes\_callbacksetup::AbortLevel();
		return;
	}

	for(i = 0; i < spawnpoints.size; i++)
		spawnpoints[i] placeSpawnpoint();

	spawnpointname = "mp_lib_spawn_axisinjail";
	spawnpoints = getentarray(spawnpointname, "classname");

	if(!spawnpoints.size)
	{
		maps\mp\gametypes\_callbacksetup::AbortLevel();
		return;
	}

	for(i = 0; i < spawnpoints.size; i++)
		spawnpoints[i] PlaceSpawnpoint();

	allowed[0] = "lib";
	maps\mp\gametypes\_gameobjects::main(allowed);

	// Time limit per map
	if(drm_getCvar("scr_lib_timelimit") == "")
		setCvar("scr_lib_timelimit", "30");
	else if(drm_getCvarFloat("scr_lib_timelimit") > 1440)
		setCvar("scr_lib_timelimit", "1440");
	level.timelimit = drm_getCvarFloat("scr_lib_timelimit");
	setCvar("ui_lib_timelimit", level.timelimit);
	storeServerInfoDvar("ui_lib_timelimit");

	// Score limit per map
	if(drm_getCvar("scr_lib_scorelimit") == "")
		setCvar("scr_lib_scorelimit", "10");
	level.scorelimit = drm_getCvarInt("scr_lib_scorelimit");
	setCvar("ui_lib_scorelimit", level.scorelimit);
	storeServerInfoDvar("ui_lib_scorelimit");

	// Round Time limit
	if(drm_getCvar("scr_lib_roundlength") == "")
		setCvar("scr_lib_roundlength", "30");
	else if(drm_getCvarFloat("scr_lib_roundlength") > 1440)
		setCvar("scr_lib_roundlength", "1440");
	level.roundlength = drm_getCvarFloat("scr_lib_roundlength");
	setCvar("ui_lib_roundlength", level.roundlength);
	storeServerInfoDvar("ui_lib_roundlength");

	// Time at round start where spawning and weapon choosing is still allowed
	if(drm_getCvar("scr_lib_graceperiod") == "")
		setCvar("scr_lib_graceperiod", "10");
	else if(drm_getCvarFloat("scr_lib_graceperiod") > level.roundlength * 60)
		setCvar("scr_lib_graceperiod", "10");
	else if(drm_getCvarFloat("scr_lib_graceperiod") < 10)
		setCvar("scr_lib_graceperiod", "10");
	level.graceperiod = drm_getCvarFloat("scr_lib_graceperiod");

	if(!isDefined(game["state"]))
		game["state"] = "playing";

	level.mapended = false;

	level.team["allies"] = 0;
	level.team["axis"] = 0;

	level.respawndelay = 1;

	level.spawn_in_jail = false;
	level.roundended = false;
	level.kills["allies"] = 0;
	level.kills["axis"] = 0;
	if(!isdefined(game["alliedscore"]))
		game["alliedscore"] = 0;
	setTeamScore("allies", game["alliedscore"]);

	if(!isdefined(game["axisscore"]))
		game["axisscore"] = 0;
	setTeamScore("axis", game["axisscore"]);


	minefields = [];
	minefields = getentarray("minefield", "targetname");
	doordamageaxis = [];
	doordamageaxis = getentarray("doordamageaxis", "targetname");
	trigger_hurts = [];
	trigger_hurts = getentarray("trigger_hurt", "classname");

	level.flag_returners = minefields;
	for(i = 0; i < trigger_hurts.size; i++)
		level.flag_returners[level.flag_returners.size] = trigger_hurts[i];

	game["gamestarted"] = true;

	thread lib_jails();
	thread Jail_Init();
	thread startGame();
	thread updateGametypeCvars();


	if (!isDefined(game["test_client_limit"]))
	thread maps\mp\gametypes\_teams::addTestClients();
	thread maps\mp\gametypes\_redirect::redirect_init();
		
	game["test_client_limit"] = 0;

	extreme\_ex_main::main();
}

storeServerInfoDvar(dvar)
{
	if (!isdefined (game["serverinfodvar"]))
		game["serverinfodvar"] = [];

	game["serverinfodvar"][game["serverinfodvar"].size] = dvar;
}

setServerInfoDvars()
{
	self endon ("disconnect");

	for (i= 0; i < game["serverinfodvar"].size; i ++)
	{
		dvar = game["serverinfodvar"][i];
		val = getCvar (dvar);
		self setClientCvar (dvar, val);
		wait 0.05;
	}
}

dummy()
{
	waittillframeend;

	if(isdefined(self))
		level notify("connecting", self);
}

Callback_PlayerConnect()
{
	thread dummy();
	thread extreme\_ex_clientcontrol::explayerconnect();


	self waittill("begin");
	self.statusicon = "";
	self.killed_once = false;

	level notify("connected", self);

	thread extreme\_ex_clientcontrol::explayerjoinedserver();

	lpselfnum = self getEntityNumber();
	lpGuid = self getGuid();
	logPrint("J;" + lpGuid + ";" + lpselfnum + ";" + self.name + "\n");

	self thread setServerInfoDvars();

	if(game["state"] == "intermission")
	{
		extreme\_ex_spawn::spawnIntermission();
		return;
	}

	level endon("intermission");

	scriptMainMenu = game["menu_ingame"];

	if(isDefined(self.pers["team"]) && self.pers["team"] != "spectator")
	{
		self setClientCvar("ui_allow_weaponchange", "1");

		if(self.pers["team"] == "allies")
			self.sessionteam = "allies";
		else
			self.sessionteam = "axis";

		if(isDefined(self.pers["weapon"]))
		{
			spawnPlayer();
		}
		else
		{
			extreme\_ex_spawn::spawnspectator();

			if(self.pers["team"] == "allies")
			{
				self openMenu(game["menu_weapon_allies"]);
				scriptMainMenu = game["menu_weapon_allies"];
			}
			else
			{
				self openMenu(game["menu_weapon_axis"]);
				scriptMainMenu = game["menu_weapon_axis"];
			}
		}
	}
	else
	{
		self setClientCvar("ui_allow_weaponchange", "0");

		if(!isDefined(self.pers["skipserverinfo"]))
		{
			self openMenu(game["menu_serverinfo"]);
			self.pers["skipserverinfo"] = true;
		}

		self.pers["team"] = "spectator";
		self.sessionteam = "spectator";

		extreme\_ex_spawn::spawnspectator();
	}

	self setClientCvar("g_scriptMainMenu", scriptMainMenu);
}


Callback_PlayerDisconnect()
{
	self extreme\_ex_clientcontrol::explayerdisconnect();
	
	if(isdefined(self.pers["team"]))
	{
		if(self.pers["team"] == "allies") setplayerteamrank(self, 0, 0);
		else if(self.pers["team"] == "axis") setplayerteamrank(self, 1, 0);
		else if(self.pers["team"] == "spectator") setplayerteamrank(self, 2, 0);
	}
	
	lpselfnum = self getEntityNumber();
	lpGuid = self getGuid();
	logPrint("Q;" + lpGuid + ";" + lpselfnum + ";" + self.name + "\n");
}

Callback_PlayerDamage(eInflictor, eAttacker, iDamage, iDFlags, sMeansOfDeath, sWeapon, vPoint, vDir, sHitLoc, psOffsetTime)
{
	if(self.sessionteam == "spectator" || self.in_jail || self.ex_invulnerable)
		return;

	// Don't do knockback if the damage direction was not specified
	if(!isDefined(vDir))
		iDFlags |= level.iDFLAGS_NO_KNOCKBACK;

	friendly = undefined;

	// check for completely getting out of the damage
	if(!(iDFlags & level.iDFLAGS_NO_PROTECTION))
	{
		if(isPlayer(eAttacker) && (self != eAttacker) && (self.pers["team"] == eAttacker.pers["team"]))
		{
			if(level.friendlyfire == "0")
			{
				return;
			}
			else if(level.friendlyfire == "1")
			{
				// Make sure at least one point of damage is done
				if(iDamage < 1)
					iDamage = 1;

				self finishPlayerDamage(eInflictor, eAttacker, iDamage, iDFlags, sMeansOfDeath, sWeapon, vPoint, vDir, sHitLoc, psOffsetTime);

				// Shellshock/Rumble
				self thread maps\mp\gametypes\_shellshock::shellshockOnDamage(sMeansOfDeath, iDamage);
				self playrumble("damage_heavy");
			}
			else if(level.friendlyfire == "2")
			{
				eAttacker.friendlydamage = true;

				iDamage = int(iDamage * .5);

				// Make sure at least one point of damage is done
				if(iDamage < 1)
					iDamage = 1;

				eAttacker finishPlayerDamage(eInflictor, eAttacker, iDamage, iDFlags, sMeansOfDeath, sWeapon, vPoint, vDir, sHitLoc, psOffsetTime);
				eAttacker.friendlydamage = undefined;

				friendly = true;
			}
			else if(level.friendlyfire == "3")
			{
				eAttacker.friendlydamage = true;

				iDamage = int(iDamage * .5);

				// Make sure at least one point of damage is done
				if(iDamage < 1)
					iDamage = 1;

				self finishPlayerDamage(eInflictor, eAttacker, iDamage, iDFlags, sMeansOfDeath, sWeapon, vPoint, vDir, sHitLoc, psOffsetTime);
				eAttacker finishPlayerDamage(eInflictor, eAttacker, iDamage, iDFlags, sMeansOfDeath, sWeapon, vPoint, vDir, sHitLoc, psOffsetTime);
				eAttacker.friendlydamage = undefined;

				friendly = true;

				// Shellshock/Rumble
				self thread maps\mp\gametypes\_shellshock::shellshockOnDamage(sMeansOfDeath, iDamage);
				self playrumble("damage_heavy");
			}
		}
		else
		{
			// Make sure at least one point of damage is done
			if(iDamage < 1)
				iDamage = 1;

			self finishPlayerDamage(eInflictor, eAttacker, iDamage, iDFlags, sMeansOfDeath, sWeapon, vPoint, vDir, sHitLoc, psOffsetTime);

			// Shellshock/Rumble
			self thread maps\mp\gametypes\_shellshock::shellshockOnDamage(sMeansOfDeath, iDamage);
			self playrumble("damage_heavy");
		}

		if(isdefined(eAttacker) && eAttacker != self)
			eAttacker thread maps\mp\gametypes\_damagefeedback::updateDamageFeedback();
	}

	// Do debug print if it's enabled
	if(drm_getCvarInt("g_debugDamage"))
	{
		println("client:" + self getEntityNumber() + " health:" + self.health +
			" damage:" + iDamage + " hitLoc:" + sHitLoc);
	}

	if(self.sessionstate != "dead")
	{
		lpselfnum = self getEntityNumber();
		lpselfname = self.name;
		lpselfteam = self.pers["team"];
		lpselfGuid = self getGuid();
		lpattackerteam = "";

		if(isPlayer(eAttacker))
		{
			lpattacknum = eAttacker getEntityNumber();
			lpattackGuid = eAttacker getGuid();
			lpattackname = eAttacker.name;
			lpattackerteam = eAttacker.pers["team"];
		}
		else
		{
			lpattacknum = -1;
			lpattackGuid = "";
			lpattackname = "";
			lpattackerteam = "world";
		}

		if(isDefined(friendly))
		{
			lpattacknum = lpselfnum;
			lpattackname = lpselfname;
			lpattackGuid = lpselfGuid;
		}

		logPrint("D;" + lpselfGuid + ";" + lpselfnum + ";" + lpselfteam + ";" + lpselfname + ";" + lpattackGuid + ";" + lpattacknum + ";" + lpattackerteam + ";" + lpattackname + ";" + sWeapon + ";" + iDamage + ";" + sMeansOfDeath + ";" + sHitLoc + "\n");
	}
}

Callback_PlayerKilled(eInflictor, attacker, iDamage, sMeansOfDeath, sWeapon, vDir, sHitLoc, psOffsetTime, deathAnimDuration)
{
	self endon("spawned");
	self notify("killed_player");

	if(self.sessionteam == "spectator")
		return;

	self.in_jail = true;	
	self.killed_once = true;

	self thread extreme\_ex_main::explayerkilled(eInflictor, attacker, iDamage, sMeansOfDeath, sWeapon, vDir, sHitLoc);

	// If the player was killed by a head shot, let players know it was a head shot kill
	if(sHitLoc == "head" && sMeansOfDeath != "MOD_MELEE")
		sMeansOfDeath = "MOD_HEAD_SHOT";

	// send out an obituary message to all clients about the kill
	self thread extreme\_ex_obituary::main(eInflictor, attacker, iDamage, sMeansOfDeath, sWeapon, vDir, sHitLoc);

	self maps\mp\gametypes\_weapons::dropWeapon();
	self maps\mp\gametypes\_weapons::dropOffhand();

	self.sessionstate = "dead";

	self.status = "injail";
	self.dead_origin = self.origin;
	self.dead_angles = self.angles;

	if(!isdefined(self.switching_teams))
	{
		self.pers["deaths"]++;
		self.deaths = self.pers["deaths"];
	}

	lpselfnum = self getEntityNumber();
	lpselfname = self.name;
	lpselfguid = self getGuid();
	lpselfteam = self.pers["team"];
	lpattackerteam = "";

	//if (attacker != self || !isDefined(self.switching_teams))
	//	self.killed_once = true;

	attackerNum = -1;
	if(isPlayer(attacker))
	{
		if(attacker == self) // killed himself
		{
			doKillcam = false;

			// switching teams
			if(isdefined(self.switching_teams))
			{
				if((self.leaving_team == "allies" && self.joining_team == "axis") || (self.leaving_team == "axis" && self.joining_team == "allies"))
				{
					players = maps\mp\gametypes\_teams::CountPlayers();
					players[self.leaving_team]--;
					players[self.joining_team]++;

					if((players[self.joining_team] - players[self.leaving_team]) > 1)
					{
						attacker.pers["score"]--;
						attacker.score = attacker.pers["score"];
					}
				}
			}

			if(isdefined(attacker.friendlydamage))
				attacker iprintln(&"MP_FRIENDLY_FIRE_WILL_NOT");
		}
		else
		{
			attackerNum = attacker getEntityNumber();
			doKillcam = true;

			// Check if extra points should be given for bash or headshot
			reward_points = 0;
			if(isDefined(sMeansOfDeath))
			{
				if(sMeansOfDeath == "MOD_MELEE") reward_points = level.ex_reward_melee;
					else if(sMeansOfDeath == "MOD_HEAD_SHOT") reward_points = level.ex_reward_headshot;
			}

			points = 1 + reward_points;

			if(self.pers["team"] == attacker.pers["team"]) // killed by a friendly
			{
				if(level.ex_reward_teamkill)
				{
					attacker.pers["score"] -= points;
					attacker.score = attacker.pers["score"];
				}
				else
				{
					attacker.pers["score"]--;
					attacker.score = attacker.pers["score"];
				}
			}
			else
			{
				attacker.pers["score"] += points;
				attacker.pers["bonus"] += reward_points;
				attacker.score = attacker.pers["score"];
			}
		}

		// added for arcade style HUD points
		attacker notify("update_playerscore_hud");

		lpattacknum = attacker getEntityNumber();
		lpattackguid = attacker getGuid();
		lpattackname = attacker.name;
		lpattackerteam = attacker.pers["team"];
	}
	else // If you weren't killed by a player, you were in the wrong place at the wrong time
	{
		doKillcam = false;

		self.pers["score"]--;
		self.score = self.pers["score"];

		lpattacknum = -1;
		lpattackname = "";
		lpattackguid = "";
		lpattackerteam = "world";
	}

	logPrint("K;" + lpselfguid + ";" + lpselfnum + ";" + lpselfteam + ";" + lpselfname + ";" + lpattackguid + ";" + lpattacknum + ";" + lpattackerteam + ";" + lpattackname + ";" + sWeapon + ";" + iDamage + ";" + sMeansOfDeath + ";" + sHitLoc + "\n");

	// Stop thread if map ended on this death
	if(level.mapended)
		return;

	if(!isdefined(self.switching_teams))
	{
		body = self cloneplayer(deathAnimDuration);
		thread maps\mp\gametypes\_deathicons::addDeathicon(body, self.clientid, self.pers["team"], 5);
	}

	self.switching_teams = undefined;
	self.joining_team = undefined;
	self.leaving_team = undefined;

	team_dead = self getTeamStatus();

	if(team_dead) // If the last player on a team was just killed, don't do killcam
	{
		self.skip_setspectatepermissions = true;
		wait 2;
		self thread spawnPlayer();
		return;
	}

	delay = 2;	// Delay the player becoming a spectator till after he's done dying
	self thread respawn_timer(delay);

	wait delay;	// ?? Also required for Callback_PlayerKilled to complete before respawn/killcam can execute

	if(doKillcam && level.killcam)
		self maps\mp\gametypes\_killcam::killcam(attackerNum, delay, psOffsetTime);
	

	self thread respawn();
}

spawnPlayer()
{
	self endon("disconnect");
	self notify("spawned");
	self notify("end_respawn");

	resettimeout();

	// Stop shellshock and rumble
	self stopShellshock();
	self stoprumble("damage_heavy");

	self.sessionteam = self.pers["team"];
	self.sessionstate = "playing";
	self.spectatorclient = -1;
	self.archivetime = 0;
	self.psoffsettime = 0;
	self.friendlydamage = undefined;
	self.statusicon = "";
	self.maxhealth = 100;
	self.health = self.maxhealth;
	self.dead_origin = undefined;
	self.dead_angles = undefined;
	self.in_jail = false;
	self.status = "free";

	self extreme\_ex_main::exprespawn();
	
	if(level.spawn_in_jail || self.killed_once)
	{
		//self.in_jail = true;
		if(self.pers["team"] == "allies")
			spawnpointname = "mp_lib_spawn_alliesinjail";
		else
			spawnpointname = "mp_lib_spawn_axisinjail";

	}
	else
	{
		if(self.pers["team"] == "allies")
			spawnpointname = "mp_lib_spawn_alliesnonjail";
		else
			spawnpointname = "mp_lib_spawn_axisnonjail";
	}

	spawnpoints = getentarray(spawnpointname, "classname");
	spawnpoint = maps\mp\gametypes\_spawnlogic::getSpawnpoint_NearTeam(spawnpoints);

	if(isDefined(spawnpoint))
		self spawn(spawnpoint.origin, spawnpoint.angles);
	else
		maps\mp\_utility::error("NO " + spawnpointname + " SPAWNPOINTS IN MAP");

	if(!isdefined(self.pers["score"]))
		self.pers["score"] = 0;
	self.score = self.pers["score"];

	if(!isdefined(self.pers["deaths"]))
		self.pers["deaths"] = 0;
	self.deaths = self.pers["deaths"];

	if(!isDefined(self.pers["savedmodel"]))
		maps\mp\gametypes\_teams::model();
	else
		maps\mp\_utility::loadModel(self.pers["savedmodel"]);

	extreme\_ex_weapons::loadout();

	if (level.roundlength <= 0)
		self setClientCvar("cg_objectiveText", "Capture all enemies in your jail.  Capture the enemy's jail control switch (marked on your compass) to release any of your teammates in jail.");
	else
		self setClientCvar("cg_objectiveText", "Capture all enemies in your jail before the round ends.  Capture the enemy's jail control switch (marked on your compass) to release any of your teammates in jail. If the round ends due to roundlength, the team with the most kills wins the round.");

	self thread updateTimer();

	self maps\mp\gametypes\_spectating::setSpectatePermissions();

	waittillframeend;

	self extreme\_ex_main::expostspawn();
	self notify("spawned_player");
	


}

spawnSpectator(origin, angles)
{
	self notify("spawned");
	self notify("end_respawn");

	resettimeout();

	// Stop shellshock and rumble
	self stopShellshock();
	self stoprumble("damage_heavy");

	self.sessionstate = "spectator";
	
	self.spectatorclient = -1;
	self.archivetime = 0;
	self.psoffsettime = 0;
	self.friendlydamage = undefined;

	if(self.pers["team"] == "spectator")
		self.statusicon = "";

	self maps\mp\gametypes\_spectating::setSpectatePermissions();

	if(isDefined(origin) && isDefined(angles))
		self spawn(origin, angles);
	else
	{
		spawnpointname = "mp_global_intermission";
		spawnpoints = getentarray(spawnpointname, "classname");
		spawnpoint = maps\mp\gametypes\_spawnlogic::getSpawnpoint_Random(spawnpoints);

		if(isDefined(spawnpoint))
			self spawn(spawnpoint.origin, spawnpoint.angles);
		else
			maps\mp\_utility::error("NO " + spawnpointname + " SPAWNPOINTS IN MAP");
	}

	if (level.roundlength <= 0)
		self setClientCvar("cg_objectiveText", "Capture all enemies in your jail.  Capture the enemy's jail control switch (marked on your compass) to release any of your teammates in jail.  You can gain one point each time you open your team's jail");
	else
		self setClientCvar("cg_objectiveText", "Capture all enemies in your jail before the round ends.  Capture the enemy's jail control switch (marked on your compass) to release any of your teammates in jail. jails will be locked down during last minute of round, team with most free players will win the round if time runs out.");
}

spawnIntermission()
{
	self notify("spawned");
	self notify("end_respawn");

	resettimeout();

	// Stop shellshock and rumble
	self stopShellshock();
	self stoprumble("damage_heavy");

	self.sessionstate = "intermission";
	self.spectatorclient = -1;
	self.archivetime = 0;
	self.psoffsettime = 0;
	self.friendlydamage = undefined;

	spawnpointname = "mp_global_intermission";
	spawnpoints = getentarray(spawnpointname, "classname");
	spawnpoint = maps\mp\gametypes\_spawnlogic::getSpawnpoint_Random(spawnpoints);

	if(isDefined(spawnpoint))
		self spawn(spawnpoint.origin, spawnpoint.angles);
	else
		maps\mp\_utility::error("NO " + spawnpointname + " SPAWNPOINTS IN MAP");

	self thread updateTimer();
}

respawn()
{
	self endon("disconnect");
	self endon("end_respawn");

	if(!isDefined(self.pers["weapon"]))
		return;

	self.sessionteam = self.pers["team"];
	self.sessionstate = "spectator";

	if(isdefined(self.dead_origin) && isdefined(self.dead_angles))
	{
		origin = self.dead_origin + (0, 0, 16);
		angles = self.dead_angles;
	}
	else
	{
		origin = self.origin + (0, 0, 16);
		angles = self.angles;
	}

	self spawn(origin, angles);

	while(isdefined(self.WaitingToSpawn))
		wait .05;

	if(drm_getCvarInt("scr_forcerespawn") <= 0)
	{
		self thread waitRespawnButton();
		self waittill("respawn");
	}

	self thread spawnPlayer();
}

waitRespawnButton()
{
	self endon("disconnect");
	self endon("end_respawn");
	self endon("respawn");

	wait 0; // Required or the "respawn" notify could happen before it's waittill has begun

	if(!isdefined(self.respawntext))
	{
		self.respawntext = newClientHudElem(self);
		self.respawntext.horzAlign = "center_safearea";
		self.respawntext.vertAlign = "center_safearea";
		self.respawntext.alignX = "center";
		self.respawntext.alignY = "middle";
		self.respawntext.x = 0;
		self.respawntext.y = -50;
		self.respawntext.archived = false;
		self.respawntext.font = "default";
		self.respawntext.fontscale = 2;
		self.respawntext setText(&"PLATFORM_PRESS_TO_SPAWN");
	}

	thread removeRespawnText();
	thread waitRemoveRespawnText("end_respawn");
	thread waitRemoveRespawnText("respawn");

	while(self useButtonPressed() != true)
		wait .05;

	self notify("remove_respawntext");

	self notify("respawn");
}

removeRespawnText()
{
	self waittill("remove_respawntext");

	if(isDefined(self.respawntext))
		self.respawntext destroy();
}

waitRemoveRespawnText(message)
{
	self endon("remove_respawntext");

	self waittill(message);
	self notify("remove_respawntext");
}

startGame()
{
	level.starttime = getTime();
	Monitor_Match_Start();
	thread startRound();

	/*
	// Timelimit is a "To Do" item if you want it.
	if(level.timelimit > 0)
	{
		level.clock = newHudElem();
		level.clock.horzAlign = "left";
		level.clock.vertAlign = "top";
		level.clock.x = 8;
		level.clock.y = 2;
		level.clock.font = "default";
		level.clock.fontscale = 2;
		level.clock setTimer(level.timelimit * 60);
	}

	for(;;)
	{
		checkTimeLimit();
		wait 1;
	}
	*/
}

startRound()
{
	level endon("round_ended");
	thread Monitor_Teams();
	wait .2;
	thread Players_Free_Hud();

	thread sayObjective();

	level.clock = newHudElem();
	level.clock.horzAlign = "left";
	level.clock.vertAlign = "top";
	level.clock.x = 8;
	level.clock.y = 2;
	level.clock.font = "default";
	level.clock.fontscale = 2;
	level.clock setTimer(level.roundlength * 60);

	//if (drm_getCvar("scr_lib_lockdown") == "" || drm_getCvarint("scr_lib_lockdown") > 0)
	//{
	//	timer = (level.roundlength * 60) - 60;
	//	if (timer > 60)
	//		thread lockdown_timer(timer);
	//}

	level.clock.color = (.98, .827, .58);
	level notify("round_started");

	if((level.roundlength * 60) > level.graceperiod)
		level.graceperiod = level.roundlength*6;

	wait level.graceperiod;

	level.spawn_in_jail = true;
	level.clock.color = (1, 1, 1);

	/*
	// Players on a team but without a weapon show as dead since they can not get in this round
	players = getentarray("player", "classname");
	for(i = 0; i < players.size; i++)
	{
		player = players[i];

		if(player.sessionteam != "spectator" && !isdefined(player.pers["weapon"]))
			player.status = "injail";

		if(player.pers["team"] == "spectator")
			player notify("joined_spectators");
	}*/

	wait((level.roundlength * 60) - level.graceperiod);

	if(level.roundended)
		return;

	// Check for Win Via Teams
	thread Check_Win_by_Teams();

	/*
	if(!level.exist[game["attackers"]] || !level.exist[game["defenders"]])
	{
		iprintln(&"MP_TIMEHASEXPIRED");
		level thread endRound("draw");
		return;
	}

	iprintln(&"MP_TIMEHASEXPIRED");
	level thread endRound(game["defenders"]);
	*/
}

endRound(roundwinner)
{
	level endon("intermission");
	level endon("kill_endround");

	if(level.roundended)
		return;
	level.roundended = true;

	level notify("update_allhud_score");

	level thread announceWinner(roundwinner, 0.6);

	winners = "";
	losers = "";

	if(roundwinner == "allies")
	{
		game["alliedscore"]++;
		setTeamScore("allies", game["alliedscore"]);
		iprintlnbold(&"LIB_ALLIES_WIN");
		players = getentarray("player", "classname");
		for(i = 0; i < players.size; i++)
		{
			lpGuid = players[i] getGuid();
			if((isdefined(players[i].pers["team"])) && (players[i].pers["team"] == "allies"))
				winners = (winners + ";" + lpGuid + ";" + players[i].name);
			else if((isdefined(players[i].pers["team"])) && (players[i].pers["team"] == "axis"))
				losers = (losers + ";" + lpGuid + ";" + players[i].name);
		}
		logPrint("W;allies" + winners + "\n");
		logPrint("L;axis" + losers + "\n");
	}
	else if(roundwinner == "axis")
	{
		game["axisscore"]++;
		setTeamScore("axis", game["axisscore"]);
		iprintlnbold(&"LIB_AXIS_WIN");
		players = getentarray("player", "classname");
		for(i = 0; i < players.size; i++)
		{
			lpGuid = players[i] getGuid();
			if((isdefined(players[i].pers["team"])) && (players[i].pers["team"] == "axis"))
				winners = (winners + ";" + lpGuid + ";" + players[i].name);
			else if((isdefined(players[i].pers["team"])) && (players[i].pers["team"] == "allies"))
				losers = (losers + ";" + lpGuid + ";" + players[i].name);
		}
		logPrint("W;axis" + winners + "\n");
		logPrint("L;allies" + losers + "\n");
	}

	wait 7;

	if(game["matchstarted"])
	{
		checkScoreLimit();
		//game["roundsplayed"]++;
		//checkRoundLimit();
	}

	if(!game["matchstarted"] && roundwinner == "reset")
	{
		game["matchstarted"] = true;
		thread resetScores();
		//game["roundsplayed"] = 0;
	}

	//game["timepassed"] = game["timepassed"] + ((getTime() - level.starttime) / 1000) / 60.0;
	//checkTimeLimit();

	if(level.mapended)
		return;
	level.mapended = true;

	/*
	// for all living players store their weapons
	players = getentarray("player", "classname");
	for(i = 0; i < players.size; i++)
	{
		player = players[i];

		if(isdefined(player.pers["team"]) && player.pers["team"] != "spectator" && player.sessionstate == "playing")
		{
			weapon1 = player getWeaponSlotWeapon("primary");
			weapon2 = player getWeaponSlotWeapon("primaryb");
			current = player getCurrentWeapon();

			// A new weapon has been selected
			if(isdefined(player.oldweapon))
			{
				player.pers["weapon1"] = player.pers["weapon"];
				player.pers["weapon2"] = "none";
				player.pers["spawnweapon"] = player.pers["weapon1"];
			} // No new weapons selected
			else
			{
				if(!maps\mp\gametypes\_weapons::isMainWeapon(weapon1) && !maps\mp\gametypes\_weapons::isMainWeapon(weapon2))
				{
					player.pers["weapon1"] = player.pers["weapon"];
					player.pers["weapon2"] = "none";
				}
				else if(maps\mp\gametypes\_weapons::isMainWeapon(weapon1) && !maps\mp\gametypes\_weapons::isMainWeapon(weapon2))
				{
					player.pers["weapon1"] = weapon1;
					player.pers["weapon2"] = "none";
				}
				else if(!maps\mp\gametypes\_weapons::isMainWeapon(weapon1) && maps\mp\gametypes\_weapons::isMainWeapon(weapon2))
				{
					player.pers["weapon1"] = weapon2;
					player.pers["weapon2"] = "none";
				}
				else
				{
					assert(maps\mp\gametypes\_weapons::isMainWeapon(weapon1) && maps\mp\gametypes\_weapons::isMainWeapon(weapon2));

					if(current == weapon2)
					{
						player.pers["weapon1"] = weapon2;
						player.pers["weapon2"] = weapon1;
					}
					else
					{
						player.pers["weapon1"] = weapon1;
						player.pers["weapon2"] = weapon2;
					}
				}

				player.pers["spawnweapon"] = player.pers["weapon1"];
			}
		}
	}*/

	level notify("restarting");

	map_restart(true);
}

endMap()
{
//////////////////////////////////////////////////////////////////////////
//Damole EndMapVote
	maps\mp\gametypes\_mapvote::Initialize();
//DaMole
//////////////////////////////////////////////////////////////////////////
	game["state"] = "intermission";
	level notify("intermission");

	alliedscore = getTeamScore("allies");
	axisscore = getTeamScore("axis");

	if(alliedscore == axisscore)
	{
		winningteam = "tie";
		losingteam = "tie";
		text = "MP_THE_GAME_IS_A_TIE";
	}
	else if(alliedscore > axisscore)
	{
		winningteam = "allies";
		losingteam = "axis";
		text = &"MP_ALLIES_WIN";
		
	}
	else
	{
		winningteam = "axis";
		losingteam = "allies";
		text = &"MP_AXIS_WIN";
		
	}

	winners = "";
	losers = "";

	if(winningteam == "allies")
		level thread playSoundOnPlayers("MP_announcer_allies_win");
	else if(winningteam == "axis")
		level thread playSoundOnPlayers("MP_announcer_axis_win");
	else
		level thread playSoundOnPlayers("MP_announcer_round_draw");

	players = getentarray("player", "classname");
	for(i = 0; i < players.size; i++)
	{
		player = players[i];

		if((winningteam == "allies") || (winningteam == "axis"))
		{
			lpGuid = player getGuid();
			if((isDefined(player.pers["team"])) && (player.pers["team"] == winningteam))
				winners = (winners + ";" + lpGuid + ";" + player.name);
			else if((isDefined(player.pers["team"])) && (player.pers["team"] == losingteam))
				losers = (losers + ";" + lpGuid + ";" + player.name);
		}

		player closeMenu();
		player closeInGameMenu();
		player setClientCvar("cg_objectiveText", text);

		player spawnIntermission();
	}

	if((winningteam == "allies") || (winningteam == "axis"))
	{
		logPrint("W;" + winningteam + winners + "\n");
		logPrint("L;" + losingteam + losers + "\n");
	}

	wait 10;
	exitLevel(false);
}

checkTimeLimit()
{
	if(level.timelimit <= 0)
		return;

	timepassed = (getTime() - level.starttime) / 1000;
	timepassed = timepassed / 60.0;

	if(timepassed < level.timelimit)
		return;

	if(level.mapended)
		return;
	level.mapended = true;

	if(!level.splitscreen)
		iprintln(&"MP_TIME_LIMIT_REACHED");

	level thread endMap();
}

checkScoreLimit()
{
	//iprintln("Got Here");
	if(level.scorelimit <= 0)
		return;

	iprintln(level.scorelimit + " " + game["alliedscore"] + " " + game["axisscore"]);

	if(game["alliedscore"] < level.scorelimit && game["axisscore"] < level.scorelimit)
		return;

	if(level.mapended)
		return;
	level.mapended = true;

	if(!level.splitscreen)
		iprintln(&"MP_SCORE_LIMIT_REACHED");

	level thread endMap();
}

updateGametypeCvars()
{
	for(;;)
	{
		timelimit = drm_getCvarFloat("scr_lib_timelimit");
		if(level.timelimit != timelimit)
		{
			if(timelimit > 1440)
			{
				timelimit = 1440;
				setCvar("scr_lib_timelimit", "1440");
			}

			level.timelimit = timelimit;
			setCvar("ui_lib_timelimit", level.timelimit);
			level.starttime = getTime();

			if(level.timelimit > 0)
			{
				if(!isDefined(level.clock))
				{
					level.clock = newHudElem();
					level.clock.horzAlign = "left";
					level.clock.vertAlign = "top";
					level.clock.x = 8;
					level.clock.y = 2;
					level.clock.font = "default";
					level.clock.fontscale = 2;
				}
				level.clock setTimer(level.timelimit * 60);
			}
			else
			{
				if(isDefined(level.clock))
					level.clock destroy();
			}

			checkTimeLimit();
		}

		scorelimit = drm_getCvarInt("scr_lib_scorelimit");
		if(level.scorelimit != scorelimit)
		{
			level.scorelimit = scorelimit;
			setCvar("ui_lib_scorelimit", level.scorelimit);
			checkScoreLimit();
		}

		wait 1;
	}
}

printJoinedTeam(team)
{
	if(!level.splitscreen)
	{
	    if(team == "allies")
		    iprintln(&"MP_JOINED_ALLIES", self);
	    else if(team == "axis")
		    iprintln(&"MP_JOINED_AXIS", self);
	}
}

playSoundOnPlayers(sound, team)
{
	players = getentarray("player", "classname");

	if(level.splitscreen)
	{
		if(isdefined(players[0]))
			players[0] playLocalSound(sound);
	}
	else
	{
		if(isdefined(team))
		{
			for(i = 0; i < players.size; i++)
			{
				if((isdefined(players[i].pers["team"])) && (players[i].pers["team"] == team))
					players[i] playLocalSound(sound);
			}
		}
		else
		{
			for(i = 0; i < players.size; i++)
				players[i] playLocalSound(sound);
		}
	}
}

printOnTeam(text, team)
{
	players = getentarray("player", "classname");
	for(i = 0; i < players.size; i++)
	{
		if((isdefined(players[i].pers["team"])) && (players[i].pers["team"] == team))
			players[i] iprintln(text);
	}
}

menuAutoAssign()
{
	numonteam["allies"] = 0;
	numonteam["axis"] = 0;

	players = getentarray("player", "classname");
	for(i = 0; i < players.size; i++)
	{
		player = players[i];

		if(!isDefined(player.pers["team"]) || player.pers["team"] == "spectator" || player == self)
			continue;

		numonteam[player.pers["team"]]++;
	}

	// if teams are equal return the team with the lowest score
	if(numonteam["allies"] == numonteam["axis"])
	{
		if(getTeamScore("allies") == getTeamScore("axis"))
		{
			teams[0] = "allies";
			teams[1] = "axis";
			assignment = teams[randomInt(2)];
		}
		else if(getTeamScore("allies") < getTeamScore("axis"))
			assignment = "allies";
		else
			assignment = "axis";
	}
	else if(numonteam["allies"] < numonteam["axis"])
		assignment = "allies";
	else
		assignment = "axis";

	if(assignment == self.pers["team"] && (self.sessionstate == "playing" || self.sessionstate == "dead"))
	{
	    if(!isdefined(self.pers["weapon"]))
	    {
		    if(self.pers["team"] == "allies")
			    self openMenu(game["menu_weapon_allies"]);
		    else
			    self openMenu(game["menu_weapon_axis"]);
	    }

		return;
	}

	if(assignment != self.pers["team"] && (self.sessionstate == "playing" || self.sessionstate == "dead"))
	{
		self.switching_teams = true;
		self.joining_team = assignment;
		self.leaving_team = self.pers["team"];
		self suicide();
	}

	self.pers["team"] = assignment;
	self.pers["weapon"] = undefined;
	self.pers["savedmodel"] = undefined;

	self setClientCvar("ui_allow_weaponchange", "1");

	if(self.pers["team"] == "allies")
	{
		self openMenu(game["menu_weapon_allies"]);
		self setClientCvar("g_scriptMainMenu", game["menu_weapon_allies"]);
	}
	else
	{
		self openMenu(game["menu_weapon_axis"]);
		self setClientCvar("g_scriptMainMenu", game["menu_weapon_axis"]);
	}

	self notify("joined_team");
	self notify("end_respawn");
}

menuAllies()
{
	if(self.pers["team"] != "allies")
	{
		if(self.sessionstate == "playing")
		{
			self.switching_teams = true;
			self.joining_team = "allies";
			self.leaving_team = self.pers["team"];
			self suicide();
		}

		self.pers["team"] = "allies";
		self.pers["weapon"] = undefined;
		self.pers["savedmodel"] = undefined;

		self setClientCvar("ui_allow_weaponchange", "1");
		self setClientCvar("g_scriptMainMenu", game["menu_weapon_allies"]);

		self notify("joined_team");
		self notify("end_respawn");
	}

	if(!isdefined(self.pers["weapon"]))
		self openMenu(game["menu_weapon_allies"]);
}

menuAxis()
{
	if(self.pers["team"] != "axis")
	{
		if(self.sessionstate == "playing")
		{
			self.switching_teams = true;
			self.joining_team = "axis";
			self.leaving_team = self.pers["team"];
			self suicide();
		}

		self.pers["team"] = "axis";
		self.pers["weapon"] = undefined;
		self.pers["savedmodel"] = undefined;

		self setClientCvar("ui_allow_weaponchange", "1");
		self setClientCvar("g_scriptMainMenu", game["menu_weapon_axis"]);

		self notify("joined_team");
		self notify("end_respawn");
	}

	if(!isdefined(self.pers["weapon"]))
		self openMenu(game["menu_weapon_axis"]);
}

menuSpectator()
{
	if(self.pers["team"] != "spectator")
	{
		if(isAlive(self))
		{
			self.switching_teams = true;
			self.joining_team = "spectator";
			self.leaving_team = self.pers["team"];
			self suicide();
		}

		self.pers["team"] = "spectator";
		self.pers["weapon"] = undefined;
		self.pers["savedmodel"] = undefined;

		self.sessionteam = "spectator";
		self setClientCvar("ui_allow_weaponchange", "0");

		self thread updateTimer();

		spawnSpectator();

		if(level.splitscreen)
			self setClientCvar("g_scriptMainMenu", game["menu_ingame_spectator"]);
		else
			self setClientCvar("g_scriptMainMenu", game["menu_ingame"]);

		self notify("joined_spectators");
		self notify("end_respawn");
	}
}

menuWeapon(response)
{
	if(!isDefined(self.pers["team"]) || (self.pers["team"] != "allies" && self.pers["team"] != "axis"))
		return;

	weapon = self maps\mp\gametypes\_weapons::restrictWeaponByServerCvars(response);

	if(weapon == "restricted")
	{
		if(self.pers["team"] == "allies")
			self openMenu(game["menu_weapon_allies"]);
		else if(self.pers["team"] == "axis")
			self openMenu(game["menu_weapon_axis"]);

		return;
	}

	if(level.splitscreen)
		self setClientCvar("g_scriptMainMenu", game["menu_ingame_onteam"]);
	else
		self setClientCvar("g_scriptMainMenu", game["menu_ingame"]);

	if(isDefined(self.pers["weapon"]) && self.pers["weapon"] == weapon)
		return;

	if(!isDefined(self.pers["weapon"]))
	{
		self.pers["weapon"] = weapon;

		if(isdefined(self.WaitingToSpawn))
		{
			self thread respawn();
			self thread updateTimer();
		}
		else
			spawnPlayer();

		self thread printJoinedTeam(self.pers["team"]);
	}
	else
	{
		self.pers["weapon"] = weapon;

		weaponname = maps\mp\gametypes\_weapons::getWeaponName(self.pers["weapon"]);

		if(maps\mp\gametypes\_weapons::useAn(self.pers["weapon"]))
			self iprintln(&"MP_YOU_WILL_RESPAWN_WITH_AN", weaponname);
		else
			self iprintln(&"MP_YOU_WILL_RESPAWN_WITH_A", weaponname);
	}

	self thread maps\mp\gametypes\_spectating::setSpectatePermissions();
}

respawn_timer(delay)
{
	self endon("disconnect");

	self.WaitingToSpawn = true;

	if(level.respawndelay > 0)
	{
		if(!isdefined(self.respawntimer))
		{
			self.respawntimer = newClientHudElem(self);
			self.respawntimer.x = 0;
			self.respawntimer.y = -50;
			self.respawntimer.alignX = "center";
			self.respawntimer.alignY = "middle";
			self.respawntimer.horzAlign = "center_safearea";
			self.respawntimer.vertAlign = "center_safearea";
			self.respawntimer.alpha = 0;
			self.respawntimer.archived = false;
			self.respawntimer.font = "default";
			self.respawntimer.fontscale = 2;
			self.respawntimer.label = (&"MP_TIME_TILL_SPAWN");
			self.respawntimer setTimer (level.respawndelay + delay);
		}

		wait delay;
		self thread updateTimer();

		wait level.respawndelay;

		if(isdefined(self.respawntimer))
			self.respawntimer destroy();
	}

	self.WaitingToSpawn = undefined;
}

updateTimer()
{
	if(isdefined(self.respawntimer))
	{
		if(isdefined(self.pers["team"]) && (self.pers["team"] == "allies" || self.pers["team"] == "axis") && isdefined(self.pers["weapon"]))
			self.respawntimer.alpha = 1;
		else
			self.respawntimer.alpha = 0;
	}
}

Jail_Init()
{
	// Set up Objective Icons
	door_switches = getentarray("door_switch","targetname");
	for(i = 0; i < door_switches.size; i++)
	{
		door_switch = door_switches[i];

		if(door_switch.script_noteworthy == "alliesdoor")
		{
			door_switch.objective = i;
			door_switch.team = "allies";
			objective_add(i, "current", door_switch.origin, "objective");
			objective_team(i, "allies");
		}

		if(door_switch.script_noteworthy == "axisdoor")
		{
			door_switch.objective = i;
			door_switch.team = "axis";
			objective_add(i, "current", door_switch.origin, "objective");
			objective_team(i, "axis");
		}
	}

	// Setup Jailcell Zones
	axisjailfields = getentarray("axisinjail", "targetname");
	for(i = 0; i < axisjailfields.size; i++)
		axisjailfields[i] thread jail_think("axis");

	alliesjailfields = getentarray("alliesinjail", "targetname");
	for(i = 0; i < alliesjailfields.size; i++)
		alliesjailfields[i] thread jail_think("allies");

	// SETUP DOOR DAMAGE TRIGGERS

	axisjaildoordamage = getentarray("doordamageaxis", "targetname");
	for(i = 0; i < axisjaildoordamage.size; i++)
		axisjaildoordamage[i] thread jail_damagethink("axis");

	alliesjaildoordamage = getentarray("doordamageallies", "targetname");
	for(i = 0; i < alliesjaildoordamage.size; i++)
		alliesjaildoordamage[i] thread jail_damagethink("allies");


}

jail_think(team)
{
	//objective_add(self.objective, "current", self.origin, "objective");
	//objective_team(self.objective, team);

	while (1)
	{
		self waittill ("trigger",other);
		
		if( level.door_closed[team] && isPlayer(other) && other.pers["team"] == team && isDefined(other.in_jail) && !other.in_jail && isAlive(other) )
			other thread goto_jail(self,team);
	}
}

goto_jail(jail,team)
{
	self endon("disconnect");
	self.in_jail = true;
	self.status = "injail";
	//self.ex_haswmdbinocs = false;


	while(self istouching(jail) && level.door_closed[team])
	{

		//self.ex_haswmdbinocs = false;
		weapon1 = self getWeaponSlotWeapon("primary");
		self disableWeapon(weapon1);
		weapon2 = self getWeaponSlotWeapon("primaryb");
		self disableWeapon(weapon2);
		//self takeallWeapons();
	
		wait .1;	

	}
	//self.ex_haswmdbinocs = true;
	//extreme\_ex_weapons::loadout();	
	self.in_jail = false;
	self.statusicon = "";
	self.status = "free";
	weapon1 = self getWeaponSlotWeapon("primary");	
	self enableWeapon(weapon1);
	weapon2 = self getWeaponSlotWeapon("primaryb");
	self enableWeapon(weapon2);



}

jail_damagethink(team)
{
	while (1)
	{
		self waittill ("trigger",other);
		
		if( isPlayer(other) && isAlive(other) )
			other thread goto_jaildamage(self,team);
	}
}


goto_jaildamage(hurt,team)
{
	self endon("disconnect");
		
	if(self istouching(hurt) && level.door_damage[team])
	{
		self.ex_forcedsuicide = true;
		self suicide();
		wait .5;
		//iprintln("the trigger should now ^1KILL when door shuts");
	}
	//iprintln("You are in the trigger to get killed");
}

Monitor_Teams()
{
	level.old_allies = 0;
	level.old_axis = 0;
	old_allies_free = 0;
	old_axis_free = 0;
	teams_free = true;

	while (teams_free)
	{
		wait 0.5;

		allies = 0;
		axis = 0;
		level.exist["allies"] = 0;
		level.exist["axis"] = 0;
		level.free["allies"] = 0;
		level.free["axis"] = 0;

		players = getentarray("player", "classname");
		for(i = 0; i < players.size; i++)
		{
			player = players[i];

			if(isdefined(player.pers["team"]) && player.pers["team"] != "spectator")
			{
				level.exist[player.pers["team"]]++;

				if (player.pers["team"] == "axis")
					axis++;
				else
					allies++;

				if (player.sessionstate != "playing")
					continue;

				if (!player.in_jail)
					level.free[player.pers["team"]]++;
			}
		}

		//HUD stuff
		if (old_axis_free != level.free["axis"] || old_allies_free != level.free["allies"] || level.old_allies != allies || level.old_axis != axis)
		{
			old_axis_free = level.free["axis"];
			old_allies_free = level.free["allies"];
			level.old_allies = allies;
			level.old_axis = axis;
			
			level.free_hud["axis"] = level.free["axis"];
			level.free_hud["allies"] = level.free["allies"];
			level notify("Update_Free_HUD");
		}

		// If one entire team leaves
		if (!level.exist["allies"] || !level.exist["axis"])
		{
			thread endRound("draw");
			return;
		}

		if ( (!level.free["allies"] && level.door_closed["allies"]) || (!level.free["axis"] && level.door_closed["axis"]) )
			teams_free = false;					
	}

	// At least one team is not free - End the Round
	allies_down = false;
	axis_down = false;

	if (!level.free["allies"] && level.door_closed["allies"])
		allies_down = true;

	if (!level.free["axis"] && level.door_closed["axis"])
		axis_down = true;

	if (allies_down && axis_down)
		thread endRound("draw");
	else if (allies_down && !axis_down)
		thread endRound("axis");
	else if (!allies_down && axis_down)
		thread endRound("allies");
}

Monitor_Match_Start()
{
	if (!isDefined(game["matchstarted"]))
		game["matchstarted"] = false;

	teams_exist = false;
	did_exist_allies = false;
	did_exist_axis = false;
	level.waiting_for_players = false;
	count = 0;

	while (!teams_exist)
	{
		wait 0.5;

		level.exist["allies"] = 0;
		level.exist["axis"] = 0;
		count++;
		if (count > 100)
			count = 100;

		players = getentarray("player", "classname");
		for(i = 0; i < players.size; i++)
		{
			player = players[i];

			if(isdefined(player.pers["team"]) && player.pers["team"] != "spectator" && player.sessionstate == "playing")
				level.exist[player.pers["team"]]++;
		}

		if (level.exist["allies"] && level.exist["axis"])
			teams_exist = true;
		else if (!level.waiting_for_players && count > 10)
			thread Waiting_For_More_Players();
	}

	if (game["matchstarted"] && count < 11)
		return;

	if (!game["matchstarted"])
	{
		iprintlnbold(&"MP_MATCHSTARTING");
		level.waiting_for_players = false;

		wait 4;
		endRound("reset");
	}
	else
	{
		iprintlnbold(&"MP_MATCHRESUMING");

		level notify("kill_endround");
		level.roundended = false;
		endRound("draw");
	}
}

getTeamStatus()
{
	//Checks to see if this was the last person on the team to die
	//With ALL other teammates either dead or in jail
	players = getentarray("player", "classname");
	for(i = 0; i < players.size; i++)
	{
		player = players[i];

		if (player.pers["team"] != self.pers["team"])
			continue;
		
		if (player.sessionstate == "dead" || player.in_jail)
			continue;

		if (player.sessionstate == "playing")
			return false;
	}

	return true;
}

Check_Win_by_Teams()
{
	iprintln(&"MP_TIMEHASEXPIRED");

	if (level.free_hud["axis"] > level.free_hud["allies"])
		thread endRound("axis");
	else if (level.free_hud["axis"] < level.free_hud["allies"])
		thread endRound("allies");
	else
		thread endRound("draw");
}

announceWinner(winner, delay)
{
	wait delay;

	// Announce winner
	if(winner == "allies")
		level thread playSoundOnPlayers("MP_announcer_allies_win");
	else if(winner == "axis")
		level thread playSoundOnPlayers("MP_announcer_axis_win");
	else if(winner == "draw")
		level thread playSoundOnPlayers("MP_announcer_round_draw");
}

resetScores()
{
	players = getentarray("player", "classname");
	for(i = 0; i < players.size; i++)
	{
		player = players[i];
		player.pers["score"] = 0;
		player.pers["deaths"] = 0;
	}

	game["alliedscore"] = 0;
	setTeamScore("allies", game["alliedscore"]);
	game["axisscore"] = 0;
	setTeamScore("axis", game["axisscore"]);
}

Waiting_For_More_Players()
{
	level.waiting_for_players = true;

	while (level.waiting_for_players)
	{
		iprintln(&"LIB_WAITING_FOR");
		wait 8;
	}
}


sayObjective()
{
	wait 2;

	attacksounds["american"] = "US_mp_cmd_movein";
	attacksounds["british"] = "UK_mp_cmd_movein";
	attacksounds["russian"] = "RU_mp_cmd_movein";
	attacksounds["german"] = "GE_mp_cmd_movein";
	defendsounds["american"] = "US_mp_cmd_movein";
	defendsounds["british"] = "UK_mp_cmd_movein";
	defendsounds["russian"] = "RU_mp_cmd_movein";
	defendsounds["german"] = "GE_mp_cmd_movein";

	level playSoundOnPlayers(attacksounds[game[game["attackers"]]], game["attackers"]);
	level playSoundOnPlayers(defendsounds[game[game["defenders"]]], game["defenders"]);
}
	


Players_Free_Hud()
{

	level.old_axis = 0;
	level.old_allies = 0;
	level.free_hud["axis"] = 0;
	level.free_hud["allies"] = 0;

	level.libhud_axisicon = newHudElem();
	level.libhud_axisicon.horzAlign = "right";
	level.libhud_axisicon.vertAlign = "top";
	level.libhud_axisicon.x = -20;
	level.libhud_axisicon.y = 28;
	level.libhud_axisicon.archived = false;
	level.libhud_axisicon setShader(game["hudicon_allies"], 16, 16);

	level.libhud_alliesicon = newHudElem();
	level.libhud_alliesicon.horzAlign = "right";
	level.libhud_alliesicon.vertAlign = "top";
	level.libhud_alliesicon.x = -20;
	level.libhud_alliesicon.y = 50;
	level.libhud_alliesicon.archived = false;
	level.libhud_alliesicon setShader(game["hudicon_axis"], 16, 16);

	level.libhud_axisfree = newHudElem();
	level.libhud_axisfree.horzAlign = "right";
	level.libhud_axisfree.vertAlign = "top";
	level.libhud_axisfree.alignX = "right";
	level.libhud_axisfree.x = -40;
	level.libhud_axisfree.y = 52;
	level.libhud_axisfree.font = "default";
	level.libhud_axisfree.fontscale = 1;
	level.libhud_axisfree.archived = false;
	level.libhud_axisfree setValue(level.free_hud["axis"]);

	level.libhud_alliesfree = newHudElem();
	level.libhud_alliesfree.horzAlign = "right";
	level.libhud_alliesfree.vertAlign = "top";
	level.libhud_alliesfree.alignX = "right";
	level.libhud_alliesfree.x = -40;
	level.libhud_alliesfree.y = 30;
	level.libhud_alliesfree.font = "default";
	level.libhud_alliesfree.fontscale = 1;
	level.libhud_alliesfree.archived = false;
	level.libhud_alliesfree setValue(level.free_hud["allies"]);

	level.libhud_axis = newHudElem();
	level.libhud_axis.horzAlign = "right";
	level.libhud_axis.vertAlign = "top";
	level.libhud_axis.alignX = "right";
	level.libhud_axis.x = -20;
	level.libhud_axis.y = 52;
	level.libhud_axis.font = "default";
	level.libhud_axis.fontscale = 1;
	level.libhud_axis.archived = false;
	level.libhud_axis.label = (&"MP_SLASH");
	level.libhud_axis setValue(level.old_axis);

	level.libhud_allies = newHudElem();
	level.libhud_allies.horzAlign = "right";
	level.libhud_allies.vertAlign = "top";
	level.libhud_allies.alignX = "right";
	level.libhud_allies.x = -20;
	level.libhud_allies.y = 30;
	level.libhud_allies.font = "default";
	level.libhud_allies.fontscale = 1;
	level.libhud_allies.archived = false;
	level.libhud_allies.label = (&"MP_SLASH");
	level.libhud_allies setValue(level.old_allies);

	level thread Maintain_Free_HUD();
}

Maintain_Free_HUD()
{
	while (1)
	{
		level waittill("Update_Free_HUD");
		wait .05;

		thread Update_Free_HUD();
	}
}

Update_Free_HUD()
{
	level.libhud_axis.x = getPosition(level.free_hud["axis"]);
	level.libhud_axis setValue(level.old_axis);

	level.libhud_allies.x = getPosition(level.free_hud["allies"]);
	level.libhud_allies setValue(level.old_allies);

	level.libhud_axisfree setValue(level.free_hud["axis"]);
	level.libhud_alliesfree setValue(level.free_hud["allies"]);
}

getPosition(free)
{
	offset = 0;
	if(free >= 10)
		offset += 11;

	return -20 + offset;
}

lockdown_timer(timer)
{
	wait timer;

	iprintln("^3Lockdown now in effect");
	level.lockdown = true;
	level.clock.color = (1, 1, 0);
}

///door crap


lib_jails()
{
	//thread test();
	level.door_closed["axis"] = true;
	level.door_closed["allies"] = true;
	level.door_damage["axis"] = false;
	level.door_damage["allies"] = false;
	

	door_trigs = getentarray("door_trig","targetname");

	for(i = 0; i < door_trigs.size; i++)
	{
		if(! isdefined (door_trigs[i].script_noteworthy))

			door_trigs[i].script_noteworthy = "rot";

		switch (door_trigs[i].script_noteworthy)
		{
			
			case "alliesdoor":
				 
				 door_trigs[i] thread allies_door_think();break;
				
			case "axisdoor":
			
				 door_trigs[i] thread axis_door_think();break;

		}
	}
}

//--------------------------------------------------------------------------------------------------------------


addalliedplayerscore(trigger)
{
	if(level.door_closed["allies"])
		{					
			self.pers["score"]++;
			self.score = self.pers["score"];
			iprintln(self.name, &"LIB_ALLIESFREED");
		}
}

addaxisplayerscore(trigger)
{
	if(level.door_closed["axis"])
		{					
			self.pers["score"]++;
			self.score = self.pers["score"];
			iprintln(self.name, &"LIB_AXISFREED");
		}
}
//--------------------------------------------------------------------------------------------------------------

allies_door_think()
{
	self.team = "allies";
	self setteamfortrigger("allies");

	while(1)
	{
		self waittill ("trigger",other);

		if(level.door_closed["allies"])
		{					
			if(isPlayer(other))
				other thread addalliedplayerscore(self);
		}		

		door = getentarray(self.target,"targetname");

		for(i=0;i<door.size;i++)
		{
			if(! isdefined(door[i].script_start) || door[i].script_start == false)
			{
				if(self.script_noteworthy == "slide_nouse")

					self thread open_slide_door(door[i], "allies");
				else
				{
					if(other useButtonPressed())
						self thread open_slide_door(door[i], "allies");
				}
			}

				
		}

	}
}

axis_door_think()
{
	self.team = "axis";
	self setteamfortrigger("axis");

	while(1)
	{
		self waittill ("trigger",other);

		if(level.door_closed["axis"])
		{					
				if(isPlayer(other))
					other thread addaxisplayerscore(self);
		}		

		door = getentarray(self.target,"targetname");

		for(i=0;i<door.size;i++)
		{
			if(! isdefined(door[i].script_start) || door[i].script_start == false)
			{
				if(self.script_noteworthy == "slide_nouse")

					self thread open_slide_door(door[i], "axis");
				else
				{
					if(other useButtonPressed())

						self thread open_slide_doors(door[i], "axis");
						
				}
			}

				
		}

	}
}


test()
{
	while (1)
	{
		wait .5;
		if (drm_getCvar("test_open") != "")
		{
			door_switches = getentarray("door_switch","targetname");
			n=0;
			for(i = 0; i < door_switches.size; i++)
			{
				door_switch = door_switches[i];
				n++;

				if(door_switch.script_noteworthy == "alliesdoor")
					iprintln("Allies Switch Found");
				else if(door_switch.script_noteworthy == "axisdoor")
					iprintln("Axis Switch Found");
			}

			if (n==0)
				iprintln("No Door Switches");

			door_trigs = getentarray("door_trig","targetname");
			for(i = 0; i < door_trigs.size; i++)
			{
				if(door_trigs[i].script_noteworthy == "alliesdoor")
					door_trigs[i] thread test_door("allies");
				else if(door_trigs[i].script_noteworthy == "axisdoor")
					door_trigs[i] thread test_door("axis");
			}
			iprintln("^3Test script: Doors Opening");
			setcvar("test_open", "");
		}
	}
}

test_door(team)
{
	door = getentarray(self.target,"targetname");

	for(i=0;i<door.size;i++)
	{
		if(! isdefined(door[i].script_start) || door[i].script_start == false)
			self thread open_slide_door(door[i], team);

		//self thread detect_slide_touch(door[i],other);
	}
}

//--------------------------------------------------------------------------------------------------------------

open_slide_door(door, team)
{

	door.script_start = true;
	open_sound1 = undefined;
	stop_sound = undefined;
	close_sound = undefined;
	alarm_sound = undefined;

	if(isdefined (door.script_noteworthy2) && (door.script_noteworthy2 == "locked"))
	{
		
		if(! isdefined (door.script_noteworthy))
			door.script_noteworthy = "wood";

		if(door.script_noteworthy == "wood")
			door playsound ("wood_door_locked");
		else
			door playsound ("metal_door_locked");

		door.script_start = false;
	}
	else
	{


		if(! isdefined (door.script_noteworthy))

			door.script_noteworthy = "wood";

			switch(door.script_noteworthy)
			{
				case "wood":
						open_sound1 = "wood_sliding_door";
						stop_sound = "wood_door_open_stop";
						close_sound = "wood_door_close_stop";
						break;
				case "metal":
						open_sound1 = "metal_door_sliding_openlib";
						stop_sound = "metal_door_sliding_close";
						close_sound = "metal_door_sliding_closelib";
						alarm_sound = "jail_alarmlib";
						break;
			}

		if(! isdefined(door.script_delay))
			door.script_delay = 10;

		open_move_timer = door.script_delay;

		script_org1 = getent(door.target,"targetname");

		script_org2 = getent(script_org1.target,"targetname");

		vec = (script_org1.origin - script_org2.origin);

		pos1 = door.origin;

		pos2 = (door.origin + vec);

		move_timer = 1.4;

		while(1)
		{
			start_time =  gettime();

			if(move_timer < .01)
				move_timer = .01;

			level.door_closed[team] = false;

			if(door.script_noteworthy == "metal")
			{	
				door playsound (open_sound1);
				door playsound (alarm_sound);
				
			}

			door moveto(pos2, move_timer, 0, 0);

			door waittill ("movedone");

			door moveto(door.origin,.01,0,0);

			end_time = gettime();

			time =  ((end_time - start_time)/ 1000);

			move_timer -= time;

			if(move_timer < .01)
				move_timer = .01;

			if(door.origin == pos2)
				break;
			else
				door waittill("notouch"); // rotatedone sent by touch thread so wait

		}

		//door playsound (stop_sound);

		wait open_move_timer;

		thread alliesdead();

		move_timer = 1.4;

		while(1)
		{
			start_time =  gettime();

			if(move_timer < .01)
				move_timer = .01;

			if(move_timer < .2)
				level.door_damage["team"] = true;			
				

			if(door.script_noteworthy == "metal")
				door playsound (close_sound);

			door moveto(pos1, move_timer, 0, 0);

			door waittill ("movedone");

			door moveto(door.origin,.01,0,0);

			end_time = gettime();

			time =  ((end_time - start_time)/ 1000);

			move_timer -= time;

			if(move_timer < .01)
				move_timer = .01;

			if(door.origin == pos1)
				break;
			else
				door waittill("notouch"); // rotatedone sent by touch thread so wait

		}

		door notify("closed");

		level.door_closed[team] = true;
		level.door_damage["team"] = false;
		door.script_start = false;
	}
		
}


open_slide_doors(door, team)
{

	door.script_start = true;
	open_sound1 = undefined;
	stop_sound = undefined;
	close_sound = undefined;
	alarm_sound = undefined;

	if(isdefined (door.script_noteworthy2) && (door.script_noteworthy2 == "locked"))
	{
		
		if(! isdefined (door.script_noteworthy))
			door.script_noteworthy = "wood";

		if(door.script_noteworthy == "wood")
			door playsound ("wood_door_locked");
		else
			door playsound ("metal_door_locked");

		door.script_start = false;
	}
	else
	{


		if(! isdefined (door.script_noteworthy))

			door.script_noteworthy = "wood";

			switch(door.script_noteworthy)
			{
				case "wood":
						open_sound1 = "wood_sliding_door";
						stop_sound = "wood_door_open_stop";
						close_sound = "wood_door_close_stop";
						break;
				case "metal":
						open_sound1 = "metal_door_sliding_openlib";
						stop_sound = "metal_door_sliding_close";
						close_sound = "metal_door_sliding_closelib";
						alarm_sound = "jail_alarmlib";
						break;
			}

		if(! isdefined(door.script_delay))
			door.script_delay = 10;

		open_move_timer = door.script_delay;

		script_org1 = getent(door.target,"targetname");

		script_org2 = getent(script_org1.target,"targetname");

		vec = (script_org1.origin - script_org2.origin);

		pos1 = door.origin;

		pos2 = (door.origin + vec);

		move_timer = 1.4;

		while(1)
		{
			start_time =  gettime();

			if(move_timer < .01)
				move_timer = .01;

			level.door_closed[team] = false;

			if(door.script_noteworthy == "metal")
			{	
				door playsound (open_sound1);
				door playsound (alarm_sound);
				
			}

			door moveto(pos2, move_timer, 0, 0);

			door waittill ("movedone");

			door moveto(door.origin,.01,0,0);

			end_time = gettime();

			time =  ((end_time - start_time)/ 1000);

			move_timer -= time;

			if(move_timer < .01)
				move_timer = .01;

			if(door.origin == pos2)
				break;
			else
				door waittill("notouch"); // rotatedone sent by touch thread so wait

		}

		//door playsound (stop_sound);

		wait open_move_timer;
		
		//level.door_damage["axis"] = true;
		thread axisdead();
		move_timer = 1.4;

		while(1)
		{
			start_time =  gettime();

			if(move_timer < .01)
				move_timer = .01;
		
			if(door.script_noteworthy == "metal")
				door playsound (close_sound);

			door moveto(pos1, move_timer, 0, 0);

			door waittill ("movedone");

			//thread doaxisdamage(other);

			door moveto(door.origin,.01,0,0);

			end_time = gettime();

			time =  ((end_time - start_time)/ 1000);

			move_timer -= time;

			if(move_timer < .01)
				move_timer = .01;
					
			if(door.origin == pos1)
				break;
			else
				door waittill("notouch"); // rotatedone sent by touch thread so wait

		}

		door notify("closed");

		level.door_closed[team] = true;
		//level.door_damage["axis"] = false;

		door.script_start = false;
	}
		
}

axisdead()

{

		wait 1.2;
		level.door_damage["axis"] = true;
		wait .5;
		level.door_damage["axis"] = false;
}

alliesdead()

{

		wait 1.2;
		level.door_damage["allies"] = true;
		wait .5;
		level.door_damage["allies"] = false;
}
