#include extreme\_ex_drm;

// * AdmiralMOD by Matthias Lorenz, http://www.cod2mod.com *


/*
	Domination
	Objective: 	Score points for your team by capturing the enemy's flag and returning it to your base
	Map ends:	When one team reaches the score limit, or time limit is reached
	Respawning:	Instant / At base

	Level requirements
	------------------
		Spawnpoints:
			classname		mp_dm_spawn
			Allied players spawn from these.
			classname		mp_dm_spawn
			Axis players spawn from these.

		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["allies"] = "american";
			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

/*--------------------------------------------------------------------------------------
	Updates, Additions and Standalone Version:
		
	La Tuffe (nedgerblansky), Tally, & Oddball
	
	credits:
	
	Some script in here was originally coded by Pointy - www.planetpointy.co.uk
----------------------------------------------------------------------------------------*/
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;
	
	if(!isDefined(game["roundsplayed"])) game["roundsplayed"] = 0;	
	
	thread maps\mp\gametypes\_mapsetup::init();
	// set eXtreme+ variables and precache
	extreme\_ex_varcache::main();
}

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

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

	// 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");
	
	
	if(!isDefined(game["alliedscore"]))	game["alliedscore"] = 0;
	if(!isDefined(game["axisscore"]))	game["axisscore"] = 0;

	level.compassflag_allies 	= "compass_flag_" + game["allies"];
	level.compassflag_axis 		= "compass_flag_" + game["axis"];
	level.compassflag_empty 	= "gfx/custom/objective_empty.tga";
	
	level.objpointflag_allies 	= "objpoint_flagpatch1_" + game["allies"];
	level.objpointflag_axis 	= "objpoint_flagpatch1_" + game["axis"];	
	level.objpointflag_empty 	= "gfx/custom/objpoint_empty.tga";

	level.hudicon_empty 		= "gfx/custom/headicon_empty.tga";

	if(!level.ex_ranksystem) precacheStatusIcon("hud_status_dead");
	precacheRumble("damage_heavy");
	precacheShader(level.compassflag_allies);
	precacheShader(level.compassflag_axis);
	precacheShader(level.objpointflag_allies);
	precacheShader(level.objpointflag_axis);
	
	precacheShader(level.compassflag_empty);
	precacheShader(level.objpointflag_empty);
	precacheShader(level.hudicon_empty);
	
	precacheShader("gfx/custom/flagge_german.tga");
	precacheShader("gfx/custom/flagge_" + game["allies"] + ".tga");

	//Setup the hud icons and team specific stuff
	if(isDefined(game["allies"]))
	{
		switch(game["allies"])
		{
			case "american":
				game["allies_area_secured"] = "US_area_secured";
				game["allies_ground_taken"] = "US_ground_taken";
				game["allies_losing_ground"] = "US_losing_ground";
				break;
			case "british":
				game["allies_area_secured"] = "UK_area_secured";
				game["allies_ground_taken"] = "UK_ground_taken";
				game["allies_losing_ground"] = "UK_losing_ground";
				break;
			case "russian":
				game["allies_area_secured"] = "RU_area_secured";
				game["allies_ground_taken"] = "RU_ground_taken";
				game["allies_losing_ground"] = "RU_losing_ground";
				break;
		}
	}

	if(isDefined(game["axis"]))
	{
		switch(game["axis"])
		{
			case "german":
				game["german_area_secured"] = "GE_area_secured";
				game["german_ground_taken"] = "GE_ground_taken";
				game["german_losing_ground"] = "GE_losing_ground";
				break;
		}
	}

	precacheModel("xmodel/prop_flag_" + game["allies"]);
	precacheModel("xmodel/prop_flag_" + game["axis"]);
	precacheString(&"MP_TIME_TILL_SPAWN");
	precacheString(&"PLATFORM_PRESS_TO_SPAWN");

	precacheModel("xmodel/fahne");
	precacheModel ("xmodel/prop_flag_base");

//	precacheString(&"MP_DOM_WAITING_FOR_PLAYERS");
	precacheString(&"MP_DOM_MATCH_STARTING");
	
	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\_objpoints::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();

	level.xenon = (getcvar("xenonGame") == "true");
	if(level.xenon) // Xenon only
		thread maps\mp\gametypes\_richpresence::init();
	else // PC only
		thread maps\mp\gametypes\_quickmessages::init();

	thread extreme\_ex_varcache::postmapload();

	setClientNameMode("auto_change");
	
	//Modified by 0ddball.
	
	//if Spawn Type defined
  if (!isdefined(level.spawntype)||!(isSpawnTypeCorrect(level.spawntype)))
  {
  	level.spawntype = "dm";
  }
    level.spawn_allies = getSpawnTypeAllies(level.spawntype);
    level.spawn_axis = getSpawnTypeAxis(level.spawntype);  
    
  //Assert that the spawntype is compliant with the current map
  
  assert(isSpawnTypeCompliant(level.spawn_allies, level.spawn_axis));
  	
	setSpawnPoints(level.spawn_allies);
  if (level.spawn_allies != level.spawn_axis) //For "sd" or "ctf"
      setSpawnPoints(level.spawn_axis);
  //End of modifications.
  
	allowed[0] = "ctf"; // KEEP IT THIS WAY
	maps\mp\gametypes\_gameobjects::main(allowed);

  //NO score limit for DOM
	level.scorelimit = 0;
	// Time limit per map
	if(drm_getCvar("scr_dom_timelimit") == "")
		setCvar("scr_dom_timelimit", "30");
	else if(drm_getCvarFloat("scr_dom_timelimit") > 1440)
		setCvar("scr_dom_timelimit", "1440");
	level.timelimit = drm_getCvarFloat("scr_dom_timelimit");
	setCvar("ui_dom_timelimit", level.timelimit);
	storeServerInfoDvar("ui_dom_timelimit");

	// Round limit per map
	if(drm_getCvar("scr_dom_roundlimit") == "")
		setCvar("scr_dom_roundlimit", "0");
	level.roundlimit = drm_getCvarInt("scr_dom_roundlimit");
	setCvar("ui_dom_roundlimit", level.roundlimit);
	storeServerInfoDvar("ui_dom_roundlimit");

	if(drm_getCvar("scr_dom_graceperiod") == "")
		setCvar("scr_dom_graceperiod", "15");
	else if(drm_getCvarFloat("scr_dom_graceperiod") > 60)
		setCvar("scr_dom_graceperiod", "60");
	else if(drm_getCvarFloat("scr_dom_graceperiod") < 0)
		setCvar("scr_dom_graceperiod", "0");
	level.graceperiod = drm_getCvarFloat("scr_dom_graceperiod");

	// Time length of each round
	if(drm_getCvar("scr_dom_roundlength") == "")
		setCvar("scr_dom_roundlength", "4");
	else if(drm_getCvarFloat("scr_dom_roundlength") > 10)
		setCvar("scr_dom_roundlength", "10");
	else if(drm_getCvarFloat("scr_dom_roundlength") < (level.graceperiod / 60))
		setCvar("scr_dom_roundlength", (level.graceperiod / 60));
	level.roundlength = drm_getCvarFloat("scr_dom_roundlength");

	if(drm_getCvar("scr_dom_allow_flagtimeout") == "")
		setCvar("scr_dom_allow_flagtimeout", "0");
	level.allow_flagtimeout = drm_getCvarInt("scr_dom_allow_flagtimeout");

//#######################################
	if(!isDefined(game["state"]))
		game["state"] = "waiting";

	level.mapended = false;
//#######################################
//#######################################
	level.roundstarted = false;
	level.roundended = false;
//#######################################

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

	level.respawndelay = [[level.ex_drm]]("scr_dom_respawndelay", 10, 1, 60, "int");
	level.pointscaptureflag = [[level.ex_drm]]("scr_dom_pointscaptureflag", 5, 1, 50, "int");
	level.flagcapturetime = [[level.ex_drm]]("scr_dom_flagcapturetime", 20, 1, 45, "int");
	level.spawndistance = [[level.ex_drm]]("scr_dom_spawndistance", 250, 1, 99999, "int");
	level.flagsnumber = [[level.ex_drm]]("scr_dom_flagsnumber", 5, 0, 99, "int");
	level.flagtimeout = [[level.ex_drm]]("scr_dom_flagtimeout", 120, 1, 9999, "int");
	
	if(drm_getCvar("scr_show_flagpoints") == "")
		setCvar("scr_show_flagpoints", "1");
  
	minefields = [];
	minefields = getentarray("minefield", "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];

	thread initFlags();
	thread startGame();
	thread updateGametypeCvars();
	thread maps\mp\gametypes\_teams::addTestClients();
	thread maps\mp\gametypes\_redirect::redirect_init();

	level.winning_team = "none";

	// launch eXtreme+
	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.statusicon = "";
	self waittill("begin");
	self.statusicon = "";
//############################################
	//stops connected messages upon map start after warmup
	if(!isDefined(self.pers["team"]))
		iprintln(&"MP_CONNECTED", self);
//#############################################

	self thread setServerInfoDvars();

	thread extreme\_ex_clientcontrol::explayerjoinedserver();

	if(!level.splitscreen)
	{
		if (IsLinuxServer ())
			iprintln(&"MP_CONNECTED", self.name);
		else
			iprintln(&"MP_CONNECTED", self);
	}
	
	lpselfnum = self getEntityNumber();
	lpGuid = self getGuid();
	logPrint("J;" + lpGuid + ";" + lpselfnum + ";" + self.name + "\n");

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

	level endon("intermission");

	if(level.splitscreen)
		scriptMainMenu = game["menu_ingame_spectator"];
	else
		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";

// Fix for spectate problem ->
      self maps\mp\gametypes\_spectating::setSpectatePermissions ();
// Fix for spectate problem <- 

		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(!level.xenon)
		{
			if(!isdefined(self.pers["skipserverinfo"]))
				self openMenu(game["menu_serverinfo"]);
		}
		else
			self openMenu(game["menu_team"]);

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

		extreme\_ex_spawn::spawnspectator();
	}

	self setClientCvar("g_scriptMainMenu", scriptMainMenu);
}

Callback_PlayerDisconnect()
{
	self extreme\_ex_clientcontrol::explayerdisconnect();
	
	if(!level.splitscreen)
	{
		if (IsLinuxServer ())
			iprintln(&"MP_DISCONNECTED", self.name);
		else
			iprintln(&"MP_DISCONNECTED", self);
	}
	
	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");
//############################################################
	if(level.roundstarted || game["state"] == "warmup")
		level thread CheckTeams();
//############################################################
}

Callback_PlayerDamage(eInflictor, eAttacker, iDamage, iDFlags, sMeansOfDeath, sWeapon, vPoint, vDir, sHitLoc, psOffsetTime)
{
	if(self.sessionteam == "spectator" || 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 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";
	if(!level.ex_ranksystem) self.statusicon = "hud_status_dead";
	self.dead_origin = self.origin;
	self.dead_angles = self.angles;

//#########################################################################################
	if(!isdefined(self.switching_teams) && !level.roundended && level.roundstarted)
		self.deaths++;
//#########################################################################################

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

	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.score--;
				}
			}

			if(isdefined(attacker.friendlydamage))
				attacker iprintln(&"MP_FRIENDLY_FIRE_WILL_NOT");
		}
		else
		{
			attackerNum = attacker getEntityNumber();
			doKillcam = true;
			
			// Only handle points if game has started and has not ended
			if(!level.roundended && level.roundstarted)
			{
				// 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.score -= points;
						else attacker.score--;
				}
				else
				{
					attacker.score += points;
					attacker.pers["bonus"] += reward_points;
				}
			}
		}

		// 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.score--;

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

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

//##############################
	if(level.roundended)
		return;
//##############################

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

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

	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 extreme\_ex_main::exprespawn();

	//Modified by 0ddball.
	  if(self.pers["team"] == "allies")
		  spawnpointname = level.spawn_allies;
	  else
		  spawnpointname = level.spawn_axis;
	//End of Modifications
		
		spawnpoints = getentarray(spawnpointname, "classname");
    
		
	 // Find a spawn point away from the flags
	
	 spawnpoint = undefined;
	 for (i = 0; i < 50; i ++)
	 {
		 spawnpoint = maps\mp\gametypes\_spawnlogic::getSpawnpoint_NearTeam (spawnpoints);
		 if (spawnpoint IsAwayFromFlags (level.spawndistance))
			 break;
	 }
	
	//End of modifications.

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

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

	extreme\_ex_weapons::loadout();

	if(!level.splitscreen)
	{
		self setClientCvar("cg_objectiveText", &"MP_DOM_OBJ_TEXT_NOSCORE");
	}
	else
		self setClientCvar("cg_objectiveText", &"MP_DOM_OBJ_TEXT");

	self thread updateTimer();

	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 = "";

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

	self setClientCvar("cg_objectiveText", "");

}

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()
{
	setTeamScore("allies", game["alliedscore"]);
	setTeamScore("axis", game["axisscore"]);

	level.starttime = getTime();
//##############################
	thread startRound();
	thread maps\mp\gametypes\_spectating::init();
	showWaiting();
//##############################
  
	for(;;)
	{
		checkTimeLimit();
		wait 1;
	}
}

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

	level notify("end_map");
	
	if(isDefined(level.clock))		
		level.clock destroy();			

	winningteam = "tie";
	losingteam = "tie";
	text = &"MP_THE_GAME_IS_A_TIE";
		
	if(level.winning_team == "allies")
	{
			game["alliedscore"]++;
			setTeamScore("allies", game["alliedscore"]);
					
			winningteam = "allies";
			losingteam = "axis";
			text = &"MP_ALLIES_WIN";
					
			level createLevelHudElement("flag_winner", 320,110, "center","middle","fullscreen","fullscreen",false,"gfx/custom/flagge_" + game["allies"] + ".tga",128,128,1,0.9,1,1,1);
	}
				
	if(level.winning_team == "axis")
	{
			game["axisscore"]++;
			setTeamScore("axis", game["axisscore"]);
					
			winningteam = "axis";
			losingteam = "allies";
			text = &"MP_AXIS_WIN";
					
			level createLevelHudElement("flag_winner", 320,110, "center","middle","fullscreen","fullscreen",false,"gfx/custom/flagge_german.tga",128,128,1,0.9,1,1,1);
	}
		
		level notify("update_teamscore_hud");
	
		iprintlnbold(text);
	
		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");
	
	//############################################################
		//do endround delay
		if(drm_getCvar("scr_dom_cooldowntime") == "")
			setCvar("scr_dom_cooldowntime", "10");
		time= drm_getCvarInt("scr_dom_cooldowntime");
			
		if ( time < 1 )
			time = 1;
				
		wait(time);
	//############################################################
	
		level deleteLevelHudElementByName("flag_winner");
		wait(time);
	
		// * Rounds Check * 
		game["roundsplayed"]++;
				
	if(game["roundsplayed"] < level.roundlimit) 
	{
		iprintlnbold(&"MP_DOM_START_NEXT_ROUND");
		time= drm_getCvarInt("scr_dom_cooldowntime");
				
		if ( time < 1 )
			time = 1;
						
		wait(time);
			
		players = getentarray("player", "classname");
		for(i = 0; i < players.size; i++) 
		{
			players[i].pers["rank"] = 1;
		}
			
		level.mapended = false;
				
		game["state"] = "playing";
		level notify("restarting");
		
		map_restart(true);		
	}
	else 
	{
		if(game["alliedscore"] == game["axisscore"]) 
		{
			text = &"MP_THE_GAME_IS_A_TIE";
		}
		else if(game["alliedscore"] > game["axisscore"]) 
		{
			text = &"MP_ALLIES_WIN";
			winningteam = "axis";
			losingteam = "allies";
		}
		else 
		{
			text = &"MP_AXIS_WIN";
			winningteam = "allies";
			winningteam = "axis";
		}

		extreme\_ex_main::exendmap();
		
		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 extreme\_ex_spawn::spawnIntermission();

			if(level.ex_ranksystem)
			{
				statusicon = player thread extreme\_ex_ranksystem::get_Current_Rank();
				
				player.statusicon = statusicon;
			}
		}
		
		if((winningteam == "allies") || (winningteam == "axis"))
		{
			logPrint("W;" + winningteam + winners + "\n");
			logPrint("L;" + losingteam + losers + "\n");
		}
		
		// wait for end music to finish
		if(isdefined(level.ex_endmusic) && level.ex_endmusic == 1)
			level waittill("end_music_over");
		else
			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.roundended)
		return;
	level.roundended = true;
//##############################

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

	level thread endMap();
}

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

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

			checkTimeLimit();
		}

		roundlimit = drm_getCvarInt("scr_dom_roundlimit");
		if(level.roundlimit != roundlimit)
		{
			level.roundlimit = roundlimit;
			setCvar("ui_dom_roundlimit", level.roundlimit);			
		} 

		wait 1;
	}
}

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

initFlags()
{
	level.hud_dom_pos_y = 20;
	level.flag_radius 	= 80;
	
	if (isdefined(level.flags))
	{
		flags = level.flags ;
	}
	else
	{
		flags = [];
		
		spawnpoints = getentarray("mp_dm_spawn", "classname");
		
		j = randomInt(spawnpoints.size);
		
		flags[0] = spawnpoints[j];	
		//logprint("Flag "+flags.size+ " : " + spawnpoints[j].origin + "\n");
		
		if (level.flagsnumber > 0)
			// Fixed number of flags
			flagsnumber = level.flagsnumber;
		else
		{
			// Variable number of flags, depending on the number of players
			// We have to wait until teams are populated
			
			while (! check_teams_exist ())
			{
				iprintlnbold (&"MP_DOM_WAITING_FOR_PLAYERS");
				wait 20;
			}
			
			players = getentarray ("player", "classname");
			flagsnumber = players.size / 2 + 1;
			if (flagsnumber < 2)
				flagsnumber = 2;
			if (flagsnumber > 7)
				flagsnumber = 7;
		}
	
		trys = 0;
		
		while(flags.size < flagsnumber) 
		{
			trys++;
			if(trys > 100) break;
		
			j = randomInt(spawnpoints.size);
			
			near = false;
			
			for(i=0;i<flags.size;i++) 
			{
				if(distance(spawnpoints[j].origin,flags[i].origin) < 1000) 
				{
					near = true;
					break;
				}
			}
		
			if(near == true) 
				continue;
			
			flags[flags.size] = spawnpoints[j];					
		}
			
		level.flags = flags;
	}

	for(i=0;i<flags.size;i++) 
	{
		team = "none";

		flags[i].flagmodel 	= spawn("script_model", flags[i].origin);
		flags[i].flagmodel.angles 		= flags[i].angles;
		flags[i].flagmodel setmodel("xmodel/fahne");
	
		flags[i].basemodel 	= spawn("script_model", flags[i].origin);
		flags[i].basemodel.angles = flags[i].angles;
		flags[i].basemodel setmodel("xmodel/prop_flag_base");

		flags[i].team 					= team;
		flags[i].objective 				= i;
		flags[i].compassflag 			= level.compassflag_empty;
		flags[i].objpointflag 			= level.objpointflag_empty;
		
		flags[i] thread flag();		

		level createLevelHudElement ("flag_" + flags[i].objective, 325 + 36 * i - 18 * (flags.size - 1), level.hud_dom_pos_y, "center", "middle", "fullscreen", "fullscreen", false, level.hudicon_empty, 32, 32, 1, 0.8, 1, 1, 1);
	}	
	
	level.flagscaptured["allies"] = 0;
	level.flagscaptured["axis"] = 0;
	//level.flags = flags;
	
	level thread checkWin(level.flags);
}

FlagTimeOut()
{
	if(!level.allow_flagtimeout)
		return;

	if(!level.roundstarted)
		return;	
	
	while (isdefined (level.FlagTimeOut_running) && level.FlagTimeOut_running)
		// No multiple occurrences allowed otherwise new flag point selection will yield unpredictable results
		wait (randomint (10) / 10);

	iprintln (&"MP_DOM_CAPTURE_TIMEOUT", level.flagtimeout);
	iprintln (&"MP_DOM_NEW_FLAG", 5);
	
	level.FlagTimeOut_running = true;
	self.flagmodel hide ();
	self.basemodel hide ();
	self deleteFlagWaypoint ();
	objective_state (self.objective, "invisible");
	level changeLevelHudElementByName ("flag_" + self.objective, 0);

	spawnpoints = getentarray ("mp_dm_spawn", "classname");
	
	new_point = undefined;
	for (i = 0; i < 100 ; i ++)
	{
		new_point = spawnpoints[randomint (spawnpoints.size)];
		if (new_point IsAwayFromFlags (1000))
			break;
	}

	wait 5;

	self.origin = new_point.origin;
	self.flagmodel.origin = self.origin;
	self.flagmodel.angles = self.angles;
	self.basemodel.origin = self.origin;
	self.basemodel.angles = self.angles;
	level changeLevelHudElementByName ("flag_" + self.objective, 0.8);
	objective_position (self.objective, self.origin);
	objective_state (self.objective, "current");
	self createFlagWaypoint ();
	self.flagmodel show ();
	self.basemodel show ();

	level.FlagTimeOut_running = false;
}

flag()
{
	level endon("end_map");

	objective_add(self.objective, "current", self.origin, self.compassflag);
	self createFlagWaypoint();

	for(;;)
	{				
		other = WaitForRadius(self.origin, level.flag_radius, 50);

		if (! isdefined (other))
			// no return value for WaitForRadius : time out for the flag
			self FlagTimeOut ();
							
		else if(isPlayer(other) && isAlive(other) && (other.pers["team"] != "spectator") && level.roundstarted && !level.roundended) 
		{
			if(check_teams_exist()) 
			{
				// Touched by enemy
				if(other.pers["team"] != self.team) 
				{
					self startCaptureProgress(other.clientid, other.pers["team"]);
					
					//thread capmsg();
				}
			}
			else 
			{
				other iprintlnbold(&"MP_DOM_WAIT_FOR_TEAM");				
				wait 7;
			}
			
			// Flag is reachable
			self.reachable = true;
		}
		
		wait 0.5;
	}
}

startCaptureProgress(clientid, team) 
{
	helper = spawn("script_model",self.origin);			
	helper playloopsound("dom_start_flag_capture");
	
	origin 	= self.origin;
	time 	= 0;
	swatch 	= 0;
	
	// * Flagge Neutralizieren *	
	if(self.team != "none") 
	{
		time_neutral = int(level.flagcapturetime/2);
	
		self.blink = true;
	
		while(isDefined(self) && time < time_neutral) 
		{
			// * abfragen ob sich der Player noch im Radius der Flag befindet *
			origin = getPlayerOrigin(clientid);

			// * Abbruch *
			if(!isDefined(origin) || (isDefined(origin) && distance(origin, self.origin) > level.flag_radius) || checkOtherPlayerInRange(clientid, origin, EnemyTeam (team), level.flag_radius) > -1) 
			{
				
				level changeLevelHudElementByName("flag_" + self.objective,0.8);

				if(isDefined(helper)) 
				{
					helper stoploopsound();
					helper delete();
				}

				self.blink = undefined;

				return;
			}

			alpha = 0.8 - ((0.8/time_neutral) * time);

			if(swatch == 0) level changeLevelHudElementByName("flag_" + self.objective,0);
			if(swatch == 1) level changeLevelHudElementByName("flag_" + self.objective,alpha);

			swatch++;
			if(swatch > 1) swatch = 0;

			time++;
			wait 0.5;			
		}
		
		level.flagscaptured[EnemyTeam (team)] --;
	}

	// * Neutral anzeigen *
	self.flagmodel setmodel("xmodel/fahne");
	self.team 					= "none";
	self.compassflag 			= level.compassflag_empty;
	self.objpointflag 			= level.objpointflag_empty;
	objective_icon(self.objective, self.compassflag);  

	level deleteLevelHudElementByName("flag_" + self.objective);
	level createLevelHudElement ("flag_" + self.objective, 325 + 36 * self.objective - 18 * (level.flags.size - 1), level.hud_dom_pos_y, "center", "middle", "fullscreen", "fullscreen", false, level.hudicon_empty, 32, 32, 1, 0.8, 1, 1, 1);

	self createFlagWaypoint();	

	// * Dem anderen Team mitteilen das Ihre Flagge neutralisiert wurde, und im Begriff ist übernommen zu werden *
	if(self.team == "allies")
		level thread playSoundOnPlayers(game["allies_losing_ground"], "allies");
	else
		level thread playSoundOnPlayers(game["german_losing_ground"], "axis");
	
	self.blink = true;

	// * Flagge Capturen *	
	while(isDefined(self) && time < level.flagcapturetime) 
	{
		// * abfragen ob sich der Player noch im Radius der Flag befindet *
		origin = getPlayerOrigin(clientid);
	
		// * Abbruch *
		if(!isDefined(origin) || (isDefined(origin) && distance(origin, self.origin) > level.flag_radius) || checkOtherPlayerInRange(clientid, origin, EnemyTeam (team), level.flag_radius) > -1) 
		{
			level changeLevelHudElementByName("flag_" + self.objective,0.8);
			
			if(isDefined(helper)) 
			{
				helper stoploopsound();
				helper delete();
			}
			
			self.blink = undefined;
			
			return;
		}
		
		alpha = 0.8 - ((0.8/level.flagcapturetime) * time);
	
		if(swatch == 0) level changeLevelHudElementByName("flag_" + self.objective,0);
		if(swatch == 1) level changeLevelHudElementByName("flag_" + self.objective,alpha);
		
		swatch++;
		if(swatch > 1) swatch = 0;
		
		time++;
		wait 0.5;
	}
	
	if(isDefined(helper)) helper delete();

	other = getPlayerPlaying(clientid,team);
	if(isDefined(other)) other GetFlag(self); // Getting flag
	
	self.blink = undefined;
}


GetFlag(flag) 
{
	self endon("disconnect");

	// Give points
	if(level.pointscaptureflag > 0)
	{
		self.score += level.pointscaptureflag;

		if(level.ex_ranksystem) self.pers["special"] += level.pointscaptureflag;
		// added for arcade style HUD points
		self notify("update_playerscore_hud");
	}

	level.flagscaptured[self.pers["team"]] ++;
	
	if(self.pers["team"] == "allies") 
	{
		flag.team = "allies";	// Muß hier oben stehen		
		
		// * nur wenn nicht letzte Flag *
		if(!checkAllFlagsCaptured()) 
		{
			if(flag.team != "axis")
				level thread playSoundOnPlayers(game["allies_area_secured"], "allies");
			else
				level thread playSoundOnPlayers(game["allies_ground_taken"], "allies");

			level thread playSoundOnPlayers(game["german_losing_ground"], "axis");
		}
	
		flagModel = "xmodel/prop_flag_" + game["allies"];
		flag.flagmodel setmodel(flagModel);	
		
		flag.compassflag = level.compassflag_allies;
		objective_icon(flag.objective, flag.compassflag);
		
		
		if(drm_getCvar("scr_show_flagpoints") == "1")
		{  
			flag.objpointflag = level.objpointflag_allies;
		}
		
		level deleteLevelHudElementByName("flag_" + flag.objective);
		level createLevelHudElement ("flag_" + flag.objective, 325 + 36 * flag.objective - 18 * (level.flags.size - 1), level.hud_dom_pos_y, "center", "middle", "fullscreen", "fullscreen", false, game["hudicon_allies"], 32, 32, 1, 0.8, 1, 1, 1);
		
	}
	else 
	{
		flag.team = "axis";	  // Muß hier oben stehen	

		// * nur wenn nicht letzte Flag *
		if(!checkAllFlagsCaptured()) 
		{
			if(flag.team != "allies")	
				level thread playSoundOnPlayers(game["german_area_secured"], "axis");
			else						
				level thread playSoundOnPlayers(game["german_ground_taken"], "axis");

			level thread playSoundOnPlayers(game["allies_losing_ground"], "allies");
		}

		flagModel = "xmodel/prop_flag_" + game["axis"];
		flag.flagmodel setmodel(flagModel);	
		
		flag.compassflag = level.compassflag_axis;
		objective_icon(flag.objective, flag.compassflag);
		if(drm_getCvar("scr_show_flagpoints") == "1")
		{
			flag.objpointflag = level.objpointflag_axis;
		}

		level deleteLevelHudElementByName("flag_" + flag.objective);
		level createLevelHudElement ("flag_" + flag.objective, 325 + 36 * flag.objective - 18 * (level.flags.size - 1), level.hud_dom_pos_y, "center", "middle", "fullscreen", "fullscreen", false, game["hudicon_axis"], 32, 32, 1, 0.8, 1, 1, 1);
	}

	self.dont_auto_balance = true;
	flag createFlagWaypoint();
}

createFlagWaypoint()
{
	self deleteFlagWaypoint();

	waypoint = newHudElem();
	waypoint.x = self.origin[0];
	waypoint.y = self.origin[1];
	waypoint.z = self.origin[2] + 100;
	waypoint.alpha = .61;
	waypoint.archived = true;

	if(level.splitscreen)
		waypoint setShader(self.objpointflag, 14, 14);
	else
	{
		if(drm_getCvar("scr_show_flagpoints") == "1")
			waypoint setShader(self.objpointflag, 7, 7);
	}

	waypoint setwaypoint(true);
	self.waypoint_flag = waypoint;
}

deleteFlagWaypoint()
{
	if(isdefined(self.waypoint_flag))
		self.waypoint_flag destroy();
}

checkWin(flags) 
{
	level notify("checkWin");
	level endon("checkWin");
	
	while(isDefined(flags)) 
	{
		if(checkAllFlagsCaptured()) 
		{
			if(flags[0].team == "allies")	
				level.winning_team = "allies";
			else							
				level.winning_team = "axis";
	
			level.mapended = true;
			
			level thread endMap();
		
			break;
		}		
		
		wait 0.5;
	}
}

checkAllFlagsCaptured() 
{
	flags = level.flags;
	
	team = flags[0].team;

	if(!isDefined(team)) return false;
	if(team != "axis" && team != "allies") return false;

	if (level.flagscaptured[team] == flags.size)
		return true;
	
	return false;
}

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, playername)
{
	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,playername);
	}
}

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

createLevelHudElement(hud_element_name, x,y,xAlign,yAlign,horzAlign,vertAlign,foreground,shader,shader_width,shader_height,sort,alpha,color_r,color_g,color_b) 
{
	if(!isDefined(level.hud)) level.hud = [];
	
	count = level.hud.size;

	level.hud[count] = newHudElem();
	level.hud[count].x = x;
	level.hud[count].y = y;
	level.hud[count].alignX = xAlign;
	level.hud[count].alignY = yAlign;
	level.hud[count].horzAlign = horzAlign;
	level.hud[count].vertAlign = vertAlign;
	level.hud[count].foreground = foreground;
	level.hud[count] setShader(shader, shader_width, shader_height);	
	level.hud[count].sort = sort;
	level.hud[count].alpha = alpha;
	level.hud[count].color = (color_r,color_g,color_b);
	
	level.hud[count].name 			= hud_element_name;
	level.hud[count].shader_name 	= shader;
	level.hud[count].shader_width 	= shader_width;
	level.hud[count].shader_height 	= shader_height;
}

changeLevelHudElementByName(hud_element_name,alpha) 
{
	if(isDefined(level.hud) && level.hud.size > 0) 
	{
	
		for(i=0;i<level.hud.size;i++) 
		{
			if(isDefined(level.hud[i].name) && level.hud[i].name == hud_element_name) 
			{
 				if(isDefined(level.hud[i])) level.hud[i].alpha = alpha;
				
				break;
			}
		}	
	}
}

deleteLevelHudElementByName(hud_element_name) 
{
	// * HUD-Elemente entfernen *
	if(isDefined(level.hud) && level.hud.size > 0) 
	{
	
		for(i=0;i<level.hud.size;i++) 
		{
			if(isDefined(level.hud[i].name) && level.hud[i].name == hud_element_name) 
			{
				level.hud[i] destroy();
				level.hud[i].name = undefined;
			}
		}
		
		new_ar = [];
		
		for(i=0;i<level.hud.size;i++) 
		{
			if(isDefined(level.hud[i].name)) new_ar[new_ar.size] = level.hud[i];			
		}
		
		level.hud = new_ar;
	}
}

WaitFlagTimeOut (timeout)
{
	if (isdefined (self.reachable))
		// No more time out for this flag
		return;
		
	wait (timeout);
	
	// If still not reachable, time out !
	if (! isdefined (self.reachable))
		self notify ("flag_timeout");
}

WaitForRadius(origin, radius, height) 
{
	self endon ("flag_timeout");
	
	self thread WaitFlagTimeOut (level.flagtimeout);

	if(!isDefined(origin) || !isDefined(radius) || !isDefined(height)) return;

	trigger = spawn("trigger_radius", origin, 0, radius, height);	

	while(1) 
	{
		trigger waittill("trigger", other);	
	
		if(isPlayer(other) && other.sessionstate == "playing") 
		{
			if(isDefined(trigger)) trigger delete();
			return other;
		}	
		
		wait 0.1;
	}
	
	if(isDefined(trigger)) trigger delete();
}

getPlayerPlaying(client_id,team) 
{
 	self endon("disconnect");

	players = getentarray("player", "classname");

	for(i=0;i<players.size;i++) 
	{
		if(players[i].sessionstate == "playing" && players[i].clientid == client_id && isDefined(players[i].pers["team"]) && players[i].pers["team"] == team) 
		{
			return players[i];
		}
	}
		
	return undefined;
}

getPlayerOrigin(client_id) 
{

 	self endon("disconnect");

	players = getentarray("player", "classname");

	for(i=0;i<players.size;i++) 
	{
		if(players[i].sessionstate == "playing" && players[i].clientid == client_id) 
		{
			return players[i].origin;
		}
	}
		
	return undefined;
}

givePlayerPoints(clientid,clientteam,points) 
{	
	if(!isDefined(clientid) || !isDefined(clientteam)) 
		return;
	
	if(clientteam != "allies" && clientteam != "axis")
		return;
	
	players = getentarray("player", "classname");

	for(i=0;i<players.size;i++) 
	{
		if(players[i].clientid == clientid && players[i].sessionstate == "playing") 
		{	
			players[i] doPlayerPoints(clientteam,points);
			break;
		}
	}	
}

checkOtherPlayerInRange(client_id, origin, team, radius) 
{
	wait 0.05;
	
	players = getentarray("player", "classname");

	for(i = 0; i < players.size; i++) 
	{             
		if(players[i].sessionstate == "playing" && isDefined(players[i].pers["team"]) && (players[i].pers["team"] == team || team == "all") && distance(players[i].origin,origin) < radius && players[i].clientid != client_id) 
		{
			return players[i].clientid;			
		}
	}		
	
	return -1;
}

doPlayerPoints(clientteam,points) 
{
	self endon("disconnect");

	if(isDefined(self.pers["score"])) 	
	{
		self.pers["score"] = self.pers["score"] + points;		
		
		if(isDefined(self.score)) self.score = self.pers["score"];
	}
	else 
	{
		self.score 	= self.score + points;
	}

	Points = drm_getCvarInt("scr_dom_pointscaptureflag");
	level.ex_dom_points = Points;
	if(level.ex_ranksystem && !level.ex_score) self.pers["special"]+= level.ex_dom_points;

	level notify("update_teamscore_hud");
}

IsLinuxServer ()
{
	if (! isdefined (level.IsLinuxServer))
	{
		version = getcvar ("version");
		endstr = "";
		for (i = 0; i < 7; i ++)
			endstr += version[i + version.size - 7];
		level.IsLinuxServer = (endstr != "win-x86");
	}
	
	return (level.IsLinuxServer);
}

IsAwayFromFlags (mindist)
{
	if (! isdefined (level.flags))
		return true;

	for (i = 0; i < level.flags.size; i ++)
		if (distance (self.origin, level.flags[i].origin) < mindist)
			return false;
	
	return true;
}

EnemyTeam (team)
{
	if (team == "allies")
		return ("axis");
	return ("allies");
}

check_teams_exist() 
{
	players = getentarray("player", "classname");
	
	alliesexist = false;
	axisexist = false;
	
	for(i = 0; i < players.size; i++) 
	{
		if(!isdefined(players[i].pers["team"]) || players[i].pers["team"] == "spectator") 
			continue;
		
		if(players[i].pers["team"] == "allies")		
			alliesexist = true;
		else if(players[i].pers["team"] == "axis")	
			axisexist = true;

		if(alliesexist && axisexist) return true;
	}
	
	return false;
}

showWaiting()
{
	if   (!level.roundstarted)
	{
		if(!isdefined(level.waitmsg))
		{
			level.waitmsg = newHudElem();
			level.waitmsg.archived = false;
			level.waitmsg.x = 320;
			level.waitmsg.y = 80;
			level.waitmsg.alignX = "center";
			level.waitmsg.alignY = "middle";
			level.waitmsg.fontScale = 2;
			level.waitmsg setText(&"MP_DOM_WAITING_FOR_PLAYERS");
		}
		else
		{
			level.waitmsg setText(&"^4Waiting for players");
		}

		if (isDefined(level.clock))
			level.clock destroy();

		if(isdefined(level.warmupcountdown))
			level.warmupcountdown destroy();
	}
}

CheckTeams()
{
	// Kill dupes
	self notify("checkforteams");
	self endon("checkforteams");

	wait 0;	// Required for Callback_PlayerDisconnect to complete before updateCheckTeams execute

	debug = drm_getCvarint("scr_debug_ctf");

	players_on_allies = 0;
	players_on_axis = 0;

	players = getentarray("player", "classname");
	for(i = 0; i < players.size; i++)
	{
		
		player = players[i];
		
		if(isDefined(player.pers["team"]))
			switch(player.pers["team"])
			{
				case "allies":
				{
					players_on_allies++;
					break;
				}
				case "axis":
				{
					players_on_axis++;
					break;
				}
			}
				
		// if we are in debug mode and we have found one person on a team then we are good
		if ( debug && (players_on_allies || players_on_axis) )
		{
			players_on_allies = 1;
			players_on_axis = 1;
			break;
		}			
		
		// if there is at least one player on each team then we are good.
		if (players_on_allies && players_on_axis )
		{
			break;
		}
	}
		
	// if one of these is zero then we only have one team
	if ( !players_on_allies || !players_on_axis )
	{
		if(level.roundstarted)
		{
			//abort round
			level.roundstarted=false;
			announcement(&"MP_THE_GAME_IS_A_TIE");
			level thread playSoundOnPlayers("MP_announcer_round_draw");
			setTeamScore("axis", 0);
			setTeamScore("allies", 0);
			level notify("update_teamscore_hud");
			thread showWaiting();
		}
		else if(game["state"] == "warmup")
		{
			//abort start
			level notify("abort_startround");
			game["state"] = "waiting";
			thread showWaiting();
		}
	}
	else
	//teams are good to play
	{
		//start the round if not started or starting
		if(!level.roundstarted && game["state"] != "warmup")
			thread dowarmup();
	}
}

doWarmup()
{
	level endon("abort_startround");

	level.roundstarted=false;
	game["state"] = "warmup";


	if(isdefined(level.waitmsg))
		level.waitmsg setText(&"MP_DOM_MATCH_STARTING");

	time = drm_getCvarInt("scr_dom_warmuptime");
	
	if ( time < 1 )
		time = 1;

	level.warmupcountdown = newHudElem();
	level.warmupcountdown.archived = false;
	level.warmupcountdown.x = 320;
	level.warmupcountdown.y = 100;
	level.warmupcountdown.alignX = "center";
	level.warmupcountdown.alignY = "middle";
	level.warmupcountdown.fontScale = 2;

	while (time)
	{	
		level.warmupcountdown setTimer(time );
		wait 1;
		time--;
	}	
	
	game["state"] = "playing";

	if(isdefined(level.waitmsg))
		level.waitmsg destroy();

	if(isdefined(level.warmupcountdown))
		level.warmupcountdown destroy();

	level notify("cleanup match starting");

	map_restart(true);
}

startRound()
{
	//don't start unless the match has started
	if(game["state"] != "playing")
		return;

	level.roundstarted=true;

	extreme\_ex_gtcommon::createClock();
	level.clock setTimer(level.roundlength * 60);

	if(isdefined(level.roundstarted))
	{
		level.clock.color = (1, 1, 0);

		wait(level.roundlength * 60);
	}

	if(level.roundended)
		return;

	iprintln(&"MP_TIMEHASEXPIRED");
	level thread endMap();
}

//Added by 0ddball.

getSpawnTypeAllies(spawntype)
{
	switch(spawntype)
	{
		case "dm" :
		  spawntype_allies = "mp_dm_spawn";
			break;
		case "tdm" : 
			spawntype_allies = "mp_tdm_spawn";
			break;
		case "sd" :
			spawntype_allies = "mp_sd_spawn_attacker";
			break;
		case "ctf":
			spawntype_allies = "mp_ctf_spawn_allied";
			break;
		default:
			spawntype_allies = "mp_dm_spawn";
		break;
	}
	return spawntype_allies;
}

getSpawnTypeAxis(spawntype)
{
	switch(spawntype)
	{
		case "dm" :
		  spawntype_axis = "mp_dm_spawn";
			break;
		case "tdm" : 
			spawntype_axis = "mp_tdm_spawn";
			break;
		case "sd" :
			spawntype_axis = "mp_sd_spawn_defender";
			break;
		case "ctf":
			spawntype_axis = "mp_ctf_spawn_axis";
			break;
		default:
			spawntype_axis = "mp_dm_spawn";
		break;
	}
	return spawntype_axis;
}

isSpawnTypeCorrect(spawntype)
{
	switch(spawntype)
	{
		case "dm" :
		case "tdm" : 
		case "sd" :
		case "ctf":
			res = true;
			break;
		default:
			res=false;;
		break;
	}
	return res;
}

setSpawnPoints(spawntype)
{
	spawnpoints = getentarray(spawntype, "classname");
	if(!spawnpoints.size)
	{
		maps\mp\gametypes\_callbacksetup::AbortLevel();
		return;
	}

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

