/*
	Individual Hold the Flag - WW2X mod compatible version
	Author : La Truffe
	
	Based on HTF (Hold the Flag)

	Credits : Bell (HTF), Ravir (cvardef function), Wizard220, Marc, Astoroth (WW2X mod)

	Version : 1.2

	Objective: 	Score points by holding the flag
	Map ends:	When one player reaches the score limit, or time limit is reached
	Respawning:	After a configurable delay
*/
#include ww2x\_drm;

main()
{
	// Trick : pretend we're on HQ gametype to benefit from the level.radio definitions in the map script
	setcvar ("g_gametype", "hq");

	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();

	level.autoassign = ww2x\_wwx_clientcontrol::menuAutoAssignDM;
	level.allies = ww2x\_wwx_clientcontrol::menuAllies;
	level.axis = ww2x\_wwx_clientcontrol::menuAxis;
	level.spectator = ww2x\_wwx_clientcontrol::menuSpectator;
	level.weapon = ww2x\_wwx_clientcontrol::menuWeapon;
	level.spawnplayer = ::spawnplayer;
	level.endgameconfirmed = ::endMap;
	
	// Over-override Callback_StartGameType
	
	level.ihtf_callbackStartGameType = level.callbackStartGameType;
	level.callbackStartGameType = ::IHTF_Callback_StartGameType;

	ww2x\_wwx_varcache::main();
}

IHTF_Callback_StartGameType()
{
	// Trick : restore IHTF gametype
	setcvar ("g_gametype", "ihtf");

	level.wwx_currentgt = "ihtf";
	level.wwx_teamplay = false;
	level.wwx_radiobased = false;
	level.wwx_tweapons = 0;
	
	[[level.ihtf_callbackStartGameType]]();
}

Callback_StartGameType()
{
	level.compassflag_allies = "compass_flag_" + game["allies"];
	level.compassflag_axis = "compass_flag_" + game["axis"];
	level.compassflag_none	= "objective";
	level.objpointflag_allies = "objpoint_flag_" + game["allies"];
	level.objpointflag_axis = "objpoint_flag_" + game["axis"];
	level.objpointflag_none = "objpoint_star";
	level.hudflag_allies = "compass_flag_" + game["allies"];
	level.hudflag_axis = "compass_flag_" + game["axis"];
	
	if (!isDefined (game["precachedone"]))
	{
	precacheShader("white");

      if(!level.wwx_ranksystem)
		{
			precacheStatusIcon("hud_status_connecting");
	            precacheStatusIcon("hud_status_dead");
                  precacheStatusIcon(level.hudflag_allies);
                  precacheStatusIcon(level.hudflag_axis);
		}
	precacheRumble("damage_heavy");
	precacheShader(level.compassflag_allies);
	precacheShader(level.compassflag_axis);
	precacheShader(level.compassflag_none);
	precacheShader(level.objpointflag_allies);
	precacheShader(level.objpointflag_axis);
	precacheShader(level.objpointflag_none);
	precacheShader(level.hudflag_allies);
	precacheShader(level.hudflag_axis);
	precacheModel("xmodel/prop_flag_" + game["allies"]);
	precacheModel("xmodel/prop_flag_" + game["axis"]);
	precacheModel("xmodel/prop_flag_" + game["allies"] + "_carry");
	precacheModel("xmodel/prop_flag_" + game["axis"] + "_carry");
	precacheString(&"MP_TIME_TILL_SPAWN");
	precacheString(&"PLATFORM_PRESS_TO_SPAWN");
	precacheString (&"MP_IHTF_OBJ_TEXT");
	precacheString (&"MP_IHTF_OBJ_TEXT_NOSCORE");
	precacheString (&"MP_IHTF_MAX_HOLD_TIME");
	precacheString (&"MP_IHTF_HOLD_TIME_TO_SCORE");
	precacheString (&"MP_IHTF_TIMEOUT");
	precacheString (&"MP_IHTF_RESPAWN_DELAY");
	precacheString (&"MP_IHTF_FLAG_SPAWN_DELAY");
	precacheString (&"MP_IHTF_POINTS_STEALING");
	precacheString (&"MP_IHTF_POINTS_HOLDING");
	precacheString (&"MP_IHTF_POINTS_KILLING_FLAG_CARRIER");
	precacheString (&"MP_IHTF_POINTS_KILLING_PLAYERS");
	precacheString (&"MP_IHTF_FLAG_TIMEOUT");
	precacheString (&"MP_IHTF_FLAG_MAXTIME");
	precacheString (&"MP_IHTF_STOLE_FLAG");
	precacheString (&"MP_IHTF_YOU_STOLE_FLAG");
	precacheString (&"MP_IHTF_KILLED_FLAG_CARRIER");
	precacheString (&"MP_IHTF_YOU_KILLED_FLAG_CARRIER");
	precacheString (&"MP_IHTF_FLAG_CARRIER_SCORES");
	precacheString (&"MP_IHTF_YOU_SCORE");

		game["precachedone"] = true;
   }

	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_playerscore::init();
	thread maps\mp\gametypes\_deathicons::init();
	thread maps\mp\gametypes\_damagefeedback::init();
	thread maps\mp\gametypes\_healthoverlay::init();
	thread maps\mp\gametypes\_spectating::init();
	thread maps\mp\gametypes\_grenadeindicators::init();
	thread maps\mp\gametypes\_landmines::init();
	thread ww2x\_wwx_tempvote::init();

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

	setClientNameMode("auto_change");

	// Time limit per map
	level.timelimit = [[level.drm_cvardef]]("scr_ihtf_timelimit",30,0,1440,"float");
	setCvar("ui_ihtf_timelimit", level.timelimit);
	makeCvarServerInfo("ui_ihtf_timelimit", "30");

	// Score limit per map
	level.scorelimit = [[level.drm_cvardef]]("scr_ihtf_scorelimit",30,0,9999,"int");
	setCvar("ui_ihtf_scorelimit", level.scorelimit);
	makeCvarServerInfo("ui_ihtf_scorelimit", "30");

	// Max hold time
	level.MaxHoldTime = [[level.drm_cvardef]] ("scr_ihtf_maxholdtime", 120, 1, 99999, "int");

	// Time to score
	level.HoldTimeToScore = [[level.drm_cvardef]]("scr_ihtf_holdtimetoscore", 10, 1, 99999, "int");

	level.holdtime = 0;
	level.totalholdtime = 0;
	level.holdtime_old = level.holdtime;
	level.totalholdtime_old = level.totalholdtime;

	// Flag spawn delay
	level.flagspawndelay = [[level.drm_cvardef]]("scr_ihtf_flagspawndelay", 15, 0, 9999, "int");

	// Random spawnpoints for the flag
	level.randomflagspawns = [[level.drm_cvardef]]("scr_ihtf_randomflagspawns", 1, 0, 1, "int");

	// Respawn delay
	level.respawndelay = [[level.drm_cvardef]]("scr_ihtf_respawndelay", 10, 0, 600, "int");;

	// Force respawning
	level.forcerespawn = [[level.drm_cvardef]]("scr_forcerespawn",0,0,60,"int");
	level.PointsForKillingPlayers		= [[level.drm_cvardef]]("scr_ihtf_pointsforkillingplayers", 0, -100, 100, "int");
	level.PointsForKillingFlagCarrier	= [[level.drm_cvardef]]("scr_ihtf_pointsforkillingflagcarrier", 1, 0, 100, "int");
	level.PointsForStealingFlag		= [[level.drm_cvardef]]("scr_ihtf_pointsforstealingflag", 1, 0, 100, "int");
	level.PointsForHoldingFlag		= [[level.drm_cvardef]]("scr_ihtf_pointsforholdingflag", 2, 0, 100, "int");

	// Time out for stealing flag
	level.flagtimeout = [[level.drm_cvardef]]("scr_ihtf_flagtimeout", 180, 1, 9999, "int");
	level.startflagtime = 0;
	
	// Minimum distance a player can spawn from the flag
	level.spawndistance = [[level.drm_cvardef]]("scr_ithf_spawndistance", 1000, 1, 99999, "int");

	// Player spawn points creation mode
	level.playerspawnpointsmode = [[level.drm_cvardef]]("scr_ihtf_playerspawnpointsmode", "dm tdm", "", "", "string");
	
	// Flag spawn points creation mode
	level.flagspawnpointsmode = [[level.drm_cvardef]]("scr_ihtf_flagspawnpointsmode", "dm ctff sdb hq", "", "", "string");

	SaveSDBombzonesPos();
	SaveCTFFlagsPos();

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

	level.playerspawnpoints = SpawnPointsArray (level.playerspawnpointsmode, "ihtf_player_spawn");
	level.flagspawnpoints = SpawnPointsArray (level.flagspawnpointsmode, "ihtf_flag_spawn");

	if (! level.playerspawnpoints.size)
	{
		maps\mp\_utility::error ("NO PLAYER SPAWNPOINTS IN MAP");
		maps\mp\gametypes\_callbacksetup::AbortLevel();
		return;
	}

	if (! level.flagspawnpoints.size)
	{
		maps\mp\_utility::error ("NO FLAG SPAWNPOINTS IN MAP");
		maps\mp\gametypes\_callbacksetup::AbortLevel();
		return;
	}

	logprint (level.playerspawnpoints.size + " player spawn points\n");
	logprint (level.flagspawnpoints.size + " flag positions\n");

	RemoveHQRadioPoints();

      thread ww2x\_wwx_varcache::postmapload();

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

	level.QuickMessageToAll = true;
	level.mapended = false; 
	level.hasspawned["flag"] = false;

	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 InitFlag();
	thread startGame();
	thread updateGametypeCvars();
	thread maps\mp\gametypes\_teams::addTestClients();
	thread maps\mp\gametypes\_redirect::redirect_init();

	ww2x\_wwx_main::main();
}

dummy()
{
	waittillframeend;

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

Callback_PlayerConnect()
{
	thread dummy();
	thread ww2x\_wwx_clientcontrol::wwxplayerconnect();
      self ww2x\_wwx_tempvote::voteMenuChk();

	if( !level.wwx_ranksystem) self.statusicon = "hud_status_connecting";
	self waittill("begin");
	self.statusicon = "";

	level notify("connected", self);

	thread ww2x\_wwx_clientcontrol::wwxplayerjoinedserver();

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

	if(game["state"] == "intermission")
	{
		ww2x\_wwx_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");
		self.sessionteam = "none";
		
		if(isDefined(self.pers["weapon"]))
			spawnPlayer();
		else
		{
			ww2x\_wwx_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";

		ww2x\_wwx_spawn::spawnspectator();
	}

	self setClientCvar("g_scriptMainMenu", scriptMainMenu);
}

Callback_PlayerDisconnect()
{
	self dropFlag();
	self ww2x\_wwx_clientcontrol::wwxplayerdisconnect();

	if (level.xenon)
		if(isdefined(self.clientid))
			setplayerteamrank(self, self.clientid, 0);
			setplayerteamrank(self, self.clientid, 0);

	lpselfnum = self getEntityNumber();
	lpselfGuid = self getGuid();
	logPrint("Q;" + lpselfGuid + ";" + lpselfnum + ";" + self.name + "\n");
}

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

	if(isDefined(sWeapon) && sWeapon == "smoke_grenade_american_fire_mp" || sWeapon == "smoke_grenade_russian_fire_mp" || sWeapon == "smoke_grenade_british_fire_mp" || sWeapon == "smoke_grenade_german_fire_mp" || sWeapon == "smoke_grenade_american_gas_mp" || sWeapon == "smoke_grenade_russian_gas_mp" || sWeapon == "smoke_grenade_british_gas_mp" || sWeapon == "smoke_grenade_german_gas_mp" || sWeapon == "fire_mp" || sWeapon == "gas_mp")
	{
	 if((sWeapon == "smoke_grenade_american_fire_mp" || sWeapon == "smoke_grenade_russian_fire_mp" || sWeapon == "smoke_grenade_british_fire_mp" || sWeapon == "smoke_grenade_german_fire_mp" || sWeapon == "fire_mp") && sMeansOfDeath != "MOD_MELEE")
		{
			if (!isDefined(vPoint))
				vPoint = self.origin + (0,0,11);

			if(isDefined(level.cocktail) && level.cocktail == vPoint)
				return;
			level.cocktail = vPoint;
			level thread ww2x\_wwx_firenades::MonitorCocktail(eInflictor, eAttacker, iDamage, iDFlags, sMeansOfDeath, sWeapon, level.cocktail, vDir, sHitLoc, psOffsetTime);
			return;

		}
		else if((sWeapon == "smoke_grenade_american_gas_mp" || sWeapon == "smoke_grenade_russian_gas_mp" || sWeapon == "smoke_grenade_british_gas_mp" || sWeapon == "smoke_grenade_german_gas_mp" || sWeapon == "gas_mp") && sMeansOfDeath != "MOD_MELEE")
		{
			if (!isDefined(vPoint))
				vPoint = self.origin + (0,0,11);
			if(isDefined(level.mustardgas) && level.mustardgas == vPoint)
				return;
			level.mustardgas = vPoint;
			level thread ww2x\_wwx_firenades::MonitorMustardGas(eInflictor, eAttacker, iDamage, iDFlags, sMeansOfDeath, sWeapon, level.mustardgas, vDir, sHitLoc, psOffsetTime);
			return;
		}
	}

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

	// check for completely getting out of the damage
	if(!(iDFlags & level.iDFLAGS_NO_PROTECTION))
	{
		// 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";
		}

		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(isdefined(self.flag))
		flagcarrier = true;
	else
		flagcarrier = undefined;

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

	self thread ww2x\_wwx_main::wwxplayerkilled (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 ww2x\_wwx_obituary::main (eInflictor, attacker, iDamage, sMeansOfDeath, sWeapon, vDir, sHitLoc);

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

	self dropFlag();

	self.sessionstate = "dead";
	if(!level.wwx_ranksystem) self.statusicon = "hud_status_dead";

	if(!isdefined(self.switching_teams))
		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;
		else
		{
			attackerNum = attacker getEntityNumber();
			doKillcam = true;

			// Was the flagcarrier killed?
			if(isdefined(flagcarrier))
			{
                        if(level.wwx_linux_server >= 1)
                        {
				attacker AnnounceSelf (&"MP_IHTF_YOU_KILLED_FLAG_CARRIER", undefined);
				attacker AnnounceOthers (&"MP_IHTF_KILLED_FLAG_CARRIER", attacker.name);
				attacker.score += level.PointsForKillingFlagCarrier;
                        }
                        else
                        {
				attacker AnnounceSelf (&"MP_IHTF_YOU_KILLED_FLAG_CARRIER", undefined);
				attacker AnnounceOthers (&"MP_IHTF_KILLED_FLAG_CARRIER", attacker);
				attacker.score += level.PointsForKillingFlagCarrier;
                        }
			}
			else
				attacker.score += level.PointsForKillingPlayers;
			
			attacker checkScoreLimit();
		}

		lpattacknum = attacker getEntityNumber();
		lpattackguid = attacker getGuid();
		lpattackname = attacker.name;
		lpattackerteam = attacker.pers["team"];
		
		attacker notify("update_playerhud_score");
	}
	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";
		
		self notify("update_playerhud_score");
	}

	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))
		self.wwx_team_changed = true;

	self.joining_team = undefined;
	self.leaving_team = undefined;
	self.switching_teams = 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, true);

	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 = "none";
	self.sessionstate = "playing";
	self.spectatorclient = -1;
	self.archivetime = 0;
	self.psoffsettime = 0;
	self.statusicon = "";
	self.maxhealth = 100;
	self.health = self.maxhealth;
	self.dead_origin = undefined;
	self.dead_angles = undefined;

	self ww2x\_wwx_main::wwxprespawn();

	spawnpoints = level.playerspawnpoints;
	
	// Find a spawn point away from the flag
	spawnpoint = undefined;
	for (i = 0; i < 50; i ++)
	{
		spawnpoint = maps\mp\gametypes\_spawnlogic::getSpawnpoint_Random (spawnpoints);
		if (spawnpoint isAwayFromFlag())
			break;
	}

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

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

	ww2x\_wwx_weapons::loadout();

	if (! level.splitscreen)
	{
		if (level.scorelimit > 0)
			self setClientCvar ("cg_objectiveText", &"MP_IHTF_OBJ_TEXT", level.scorelimit);
		else
			self setClientCvar ("cg_objectiveText", &"MP_IHTF_OBJ_TEXT_NOSCORE");
	}
	else
		self setClientCvar ("cg_objectiveText", &"MP_IHTF_OBJ_TEXT_NOSCORE");

	self thread updateTimer();

	waittillframeend;

	self ww2x\_wwx_main::wwxpostspawn();

	self notify("spawned_player");

	thread CheckForFlag();
}

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

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

	self.sessionteam = "none";
	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 allowSpectateTeam ("freelook", cvardef("scr_freelook", 0, 0, 1, "int"));
      self allowSpectateTeam ("none", cvardef("scr_spectateenemy", 0, 0, 1, "int"));

	self spawn(origin, angles);

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

	if(level.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();

	if(level.timelimit > 0)
	{
		ww2x\_wwx_gtcommon::createClock();

		level.clock setTimer(level.timelimit * 60);
	}

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

endMap()
{
	ww2x\_wwx_main::wwxendmap();

	game["state"] = "intermission";
	level notify("intermission");

	players = getentarray("player", "classname");
	highscore = undefined;
	tied = undefined;
	playername = undefined;
	playerteam = undefined;
	name = undefined;
	guid = undefined;

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

		if(isdefined(player.pers["team"]) && player.pers["team"] == "spectator")
			continue;

		if(!isdefined(highscore))
		{
			highscore = player.score;
			playername = player;
			name = player.name;
			guid = player getGuid();
			continue;
		}

		if(player.score == highscore)
			tied = true;
		else if(player.score > highscore)
		{
			tied = false;
			highscore = player.score;
			playername = player;
			playerteam = player.pers["team"];
			name = player.name;
			guid = player getGuid();
		}
	}

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

		player closeMenu();
		player closeInGameMenu();

		if(isdefined(tied) && tied == true)
			player setClientCvar("cg_objectiveText", &"MP_THE_GAME_IS_A_TIE");
		else if(isdefined(playername))
			player setClientCvar("cg_objectiveText", &"MP_WINS", playername);

		player ww2x\_wwx_spawn::spawnIntermission();

		if(level.wwx_ranksystem)
		{
			statusicon = player thread ww2x\_wwx_ranksystem::get_Current_Rank();
			if(isdefined(player.statusicon))					
			player.statusicon = statusicon;
		}
	}

	if(isdefined(name))
		logPrint("W;;" + guid + ";" + name + "\n");

	// set everyone's rank on xenon
	if(level.xenon)
	{
		for(i = 0; i < players.size; i++)
		{
			player = players[i];

			if(isdefined(player.pers["team"]) && player.pers["team"] == "spectator")
				continue;

			if(highscore <= 0)
				rank = 0;
			else
			{
				rank = int(player.score * 10 / highscore);
				if(rank < 0)
					rank = 0;
			}

			// since this is a free-for-all game type, give every player their own team number
			setplayerteamrank(player, player.clientid, rank);
		}
		sendranks();
	}

	if (isdefined (level.wwx_endmusic) && level.wwx_endmusic)
		level waittill ("end_music_over");
	else
	wait 15;

	exitLevel(false);
}

checkTimeLimit()
{
	flagtimepassed = (getTime() - level.startflagtime) / 1000;
	if ((level.flag.atbase || (! level.flag.stolen)) && (flagtimepassed >= level.flagtimeout))
	{
		iprintln (&"MP_IHTF_FLAG_TIMEOUT", level.flagtimeout);

		// Hide the flag
		level.flag.basemodel hide();
		level.flag.flagmodel hide();
		level.flag.compassflag = level.compassflag_none;
		level.flag.objpointflag = level.objpointflag_none;

		// Prevent players from stealing it until it respawns
		level.flag.stolen = true;

		// Respawn the flag		
		level.flag returnFlag();
	}

	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()
{
	waittillframeend;

	if(level.scorelimit <= 0)
		return;

	if(self.score < level.scorelimit)
		return;

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

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

	level thread endMap();
}

updateGametypeCvars()
{
	for(;;)
	{
		timelimit = [[level.drm_cvardef]]("scr_ihtf_timelimit",30,0,1440,"float");
		if(level.timelimit != timelimit)
		{
			level.timelimit = timelimit;
			setCvar("ui_ihtf_timelimit", level.timelimit);
			level.starttime = getTime();

			if(level.timelimit > 0)
			{
				if(!isDefined(level.clock))

				ww2x\_wwx_gtcommon::createClock();

				level.clock setTimer(level.timelimit * 60);
			}
			else
			{
				if(isDefined(level.clock))
					level.clock destroy();
			}

			checkTimeLimit();
		}

		scorelimit = [[level.drm_cvardef]]("scr_ihtf_scorelimit",30,0,9999,"int");
		if(level.scorelimit != scorelimit)
		{
			level.scorelimit = scorelimit;
			setCvar("ui_ihtf_scorelimit", level.scorelimit);

			level notify ("update_teamscore_hud");

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

		wait 1;
	}
}

pickupFlag(flag)
{
	// What is my team?
	myteam = self.pers["team"];
	if(myteam == "allies")
		otherteam = "axis";
	else
		otherteam = "allies";

	flag.origin = flag.origin + (0, 0, -10000);
	flag.flagmodel hide();
	flag.flagmodel setmodel("xmodel/prop_flag_" + game[myteam]);
	self.flag = flag;


	flag.team = myteam;
	flag.atbase = false;

	if(myteam == "allies")
	{
		flag.compassflag = level.compassflag_allies;
		flag.objpointflag = level.objpointflag_allies;
	}
	else
	{
		flag.compassflag = level.compassflag_axis;
		flag.objpointflag = level.objpointflag_axis;
	}

	flag deleteFlagWaypoint();

	objective_icon(self.flag.objective, flag.compassflag);
	objective_team(self.flag.objective, "none");

	self playsound("ctf_touchenemy");
	self attachFlag();
}

dropFlag()
{
	if(isdefined(self.flag))
	{
		level.holdtime = 0;
		level.totalholdtime = 0;

		UpdateHud();

		start = self.origin + (0, 0, 10);
		end = start + (0, 0, -2000);
		trace = bulletTrace(start, end, false, undefined);

		self.flag.origin = trace["position"];
		self.flag.flagmodel.origin = self.flag.origin;
		self.flag.flagmodel show();
		self.flag.atbase = false;
		self.flag.stolen = false;

		// set compass flag position on player
		objective_position(self.flag.objective, self.flag.origin);
		objective_state(self.flag.objective, "current");

		self.flag createFlagWaypoint();

		self detachFlag(self.flag);

		// check if it's in a flag_returner
		for(i = 0; i < level.flag_returners.size; i++)
		{
			if(self.flag.flagmodel istouching(level.flag_returners[i]))
			{
				self.flag.compassflag = level.compassflag_none;
				self.flag.objpointflag = level.objpointflag_none;
				self.flag thread returnFlag();
				break;
			}
		}

		self.flag = undefined;
		
		level.startflagtime = getTime();
	}
}

returnFlag()
{
	self deleteFlagWaypoint();
	objective_delete(self.objective);

	if(!level.hasspawned["flag"])
	{
		self.origin = self.home_origin;
 		self.flagmodel.origin = self.home_origin;
	 	self.flagmodel.angles = self.home_angles;
		if(level.randomflagspawns)	level.hasspawned["flag"] = true;
	}
	else
	{
		spawnpoints = level.flagspawnpoints;

		// Find a new spawn point for the flag
		spawnpoint = undefined;
		for (i = 0; i < 50; i ++)
		{
			spawnpoint = maps\mp\gametypes\_spawnlogic::getSpawnpoint_Random (spawnpoints);
			if (spawnpoint.origin != self.origin)
				break;
		}

		self.origin = spawnpoint.origin;
 		self.flagmodel.origin = spawnpoint.origin;
	 	self.flagmodel.angles = spawnpoint.angles;
		self.basemodel.origin = spawnpoint.origin;
	 	self.basemodel.angles = spawnpoint.angles;
	}

	// Wait delay before spawning flag
	wait level.flagspawndelay + 0.05;

	self.flagmodel show();
	self.basemodel show();
	self.atbase = true;
	self.stolen = false;

	// set compass flag position on player
	objective_add(self.objective, "current", self.origin, self.compassflag);
	objective_position(self.objective, self.origin);
	objective_state(self.objective, "current");

	self createFlagWaypoint();
	
	level.holdtime = 0;
	level.totalholdtime = 0;

	UpdateHud();

	level.startflagtime = getTime();
}

attachFlag()
{
	if (isdefined(self.flagAttached))
		return;

	//put icon on screen
	self.flagAttached = newClientHudElem(self);
	self.flagAttached.x = 30;
	self.flagAttached.y = 95;
	self.flagAttached.alignX = "center";
	self.flagAttached.alignY = "middle";
	self.flagAttached.horzAlign = "left";
	self.flagAttached.vertAlign = "top";

	iconSize = 40;

	if(self.pers["team"] == "allies")
	{
		flagModel = "xmodel/prop_flag_" + game["allies"] + "_carry";
		self.flagAttached setShader(level.hudflag_allies, iconSize, iconSize);
		if(!level.wwx_ranksystem) self.statusicon = level.hudflag_allies;
	}
	else
	{
		flagModel = "xmodel/prop_flag_" + game["axis"] + "_carry";
		self.flagAttached setShader(level.hudflag_axis, iconSize, iconSize);
	      if(!level.wwx_ranksystem) self.statusicon = level.hudflag_axis;
	}
	self attach(flagModel, "J_Spine4", true);
}

detachFlag(flag)
{
	if (!isdefined(self.flagAttached))
		return;

	if (flag.team == "allies")
		flagModel = "xmodel/prop_flag_" + game["allies"] + "_carry";
	else
		flagModel = "xmodel/prop_flag_" + game["axis"] + "_carry";
	self detach(flagModel, "J_Spine4");

	self.statusicon = "";

	self.flagAttached destroy();
}

createFlagWaypoint()
{
	if (! level.wwx_objindicator)
		return;

	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
		waypoint setShader(self.objpointflag, 7, 7);

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

deleteFlagWaypoint()
{
	if (! level.wwx_objindicator)
		return;

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

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

AnnounceSelf (locstring, var)
{
	if (isdefined (var))
		self iprintlnbold (locstring, var);
	else
		self iprintlnbold (locstring);
}

AnnounceOthers (locstring, var)
{
	players = getentarray ("player", "classname");
	for (i = 0; i < players.size; i++)
	{
		if (players[i] == self)
			continue;

		if (isdefined (var))
			players[i] iprintln (locstring, var);
		else
			players[i] iprintln (locstring);
	}
}

AnnounceAll (locstring, var)
{
	players = getentarray ("player", "classname");
	for (i = 0; i < players.size; i++)
	{
		if (isdefined (var))
			players[i] iprintln (locstring, var);
		else
			players[i] iprintln (locstring);
	}
}

InitFlag()
{
	// Get map name
	mapname = drm_getcvar("mapname");

	// Look for cvars
	x = drm_getcvar("scr_ihtf_home_x_" + mapname);
	y = drm_getcvar("scr_ihtf_home_y_" + mapname);
	z = drm_getcvar("scr_ihtf_home_z_" + mapname);
	a = drm_getcvar("scr_ihtf_home_a_" + mapname);

	if(x != "" && y != "" && z != "" && a != "")
	{
		position = (x,y,z);
		angles = (0,a,0);
	}
	else
	{
		// No cvars...
		flagpoint = GetFlagPoint();
		position = flagpoint.origin;
		angles = flagpoint.angles;
	}
	origin = position;

	// Spawn a script origin
	level.flag = spawn("script_origin",origin);
	level.flag.targetname = "ihtf_flaghome";
	level.flag.origin = origin;
	level.flag.angles = angles;
	level.flag.home_origin = origin;
	level.flag.home_angles = angles;

	// Spawn the flag base model
	level.flag.basemodel = spawn("script_model", level.flag.home_origin);
	level.flag.basemodel.angles = level.flag.home_angles;
	level.flag.basemodel setmodel("xmodel/prop_flag_base");
	
	// Spawn the flag
	level.flag.flagmodel = spawn("script_model", level.flag.home_origin);
	level.flag.flagmodel.angles = level.flag.home_angles;
	level.flag.flagmodel setmodel("xmodel/prop_flag_german");
	level.flag.flagmodel hide();

	// Set flag properties
	level.flag.team = "none";
	level.flag.atbase = false;
	level.flag.stolen = false;
	level.flag.objective = 0;
	level.flag.compassflag = level.compassflag_none;
	level.flag.objpointflag = level.objpointflag_none;

	wait 0.05;

	SetupHud();

	level.flag returnFlag();
}

GetFlagPoint()
{
	// Get nearest spawn

	spawnpoints = level.flagspawnpoints;
	flagpoint = maps\mp\gametypes\_spawnlogic::getSpawnpoint_Random(spawnpoints);

	return flagpoint;
}

CheckForFlag()
{
	level endon("intermission");

	self.flag = undefined;
	count=0;

	// What is my team?
	myteam = self.pers["team"];
	if(myteam == "allies")
		otherteam = "axis";
	else
		otherteam = "allies";
	
	while (isAlive(self) && self.sessionstate=="playing" && myteam == self.pers["team"]) 
	{
		// Does the flag exist and is not currently being stolen?
		if(!level.flag.stolen)
		{
			// Am I touching it and it is not currently being stolen?
			if(self isTouchingFlag() && !level.flag.stolen)
			{
				level.flag.stolen = true;
		
				// Steal flag
				self pickupFlag(level.flag);
				
				self AnnounceSelf (&"MP_IHTF_YOU_STOLE_FLAG", undefined);
                        if(level.wwx_linux_server >= 1)
                        {
				self AnnounceOthers (&"MP_IHTF_STOLE_FLAG", self.name);
                        }
                        else
                        {
				self AnnounceOthers (&"MP_IHTF_STOLE_FLAG", self);
                        }                        

				// Get personal score
				self.score += level.PointsForStealingFlag;

				lpselfnum = self getEntityNumber();
				lpselfguid = self getGuid();
				logPrint("A;" + lpselfguid + ";" + lpselfnum + ";" + self.name + ";" + "ihtf_stole" + "\n");

				self notify("update_playerscore_hud");

				self checkScoreLimit();
				
				count = 0;
			}
		}

		// Update objective on compass
		if(isdefined(self.flag))
		{
			// Update the objective
			objective_position(self.flag.objective, self.origin);

			wait 0.05;

			// Make sure flag still exist
			if(isdefined(self.flag))
			{
				// Check hold time every second
				count++;
				if(count>=20)
				{
					count = 0;
				
					level.holdtime ++;
					level.totalholdtime ++;
					
					if (level.totalholdtime >= level.MaxHoldTime)
					{
						AnnounceAll (&"MP_IHTF_FLAG_MAXTIME", level.MaxHoldTime);

						level.holdtime = 0;
						level.totalholdtime = 0;

						lpselfnum = self getEntityNumber();
						lpselfguid = self getGuid();
						logPrint("A;" + lpselfguid + ";" + lpselfnum + ";" + self.name + ";" + "ihtf_maxheld" + "\n");
						
						self detachFlag(self.flag);
						self.flag.compassflag = level.compassflag_none;
						self.flag.objpointflag = level.objpointflag_none;

						self.flag thread ReturnFlag();
						self.flag = undefined;	
					}

					if (level.holdtime >= level.HoldTimeToScore)
					{
						iprintln (&"MP_IHTF_FLAG_CARRIER_SCORES", level.PointsForHoldingFlag);
						self.score += level.PointsForHoldingFlag;

						level.holdtime = 0;

						lpselfnum = self getEntityNumber();
						lpselfguid = self getGuid();
						logPrint("A;" + lpselfguid + ";" + lpselfnum + ";" + self.name + ";" + "ihtf_scored" + "\n");

						self notify("update_playerscore_hud");

						self checkScoreLimit();
					}

					UpdateHud();
				}
			}
		}
		else
			wait 0.2;		
	}

	//player died or went spectator
	self dropFlag();
}

isTouchingFlag()
{
	if(distance(self.origin, level.flag.origin) < 50)
		return true;
	else
		return false;
}

isAwayFromFlag()
{
	if (distance (self.origin, level.flag.origin) >= level.spawndistance)
		return true;
	else
		return false;
}

SetupHud()
{
	y = 10;

	level.cursorleft = newHudElem();
	level.cursorleft.x = 320;
	level.cursorleft.y = y;
	level.cursorleft.alignX = "right";
	level.cursorleft.alignY = "middle";
	level.cursorleft.color = (1,0,0);
	level.cursorleft.alpha = 0.4;
	level.cursorleft setShader("white", 1, 10);

	level.cursorright = newHudElem();
	level.cursorright.x = 320;
	level.cursorright.y = y;
	level.cursorright.alignX = "left";
	level.cursorright.alignY = "middle";
	level.cursorright.color = (0,0,1);
	level.cursorright.alpha = 0.4;
	level.cursorright setShader("white", 1, 10);
}

UpdateHud()
{
	y = 10;
	barsize = 200;

	left = int (level.holdtime * barsize / (level.HoldTimeToScore - 1) + 1);
	right = int (level.totalholdtime * barsize / (level.MaxHoldTime - 1) + 1);

	if (level.holdtime != level.holdtime_old)
		level.cursorleft scaleOverTime (1, left, 10);
	if (level.totalholdtime != level.totalholdtime_old)
		level.cursorright scaleOverTime (1, right, 10);
		
	level.holdtime_old = level.holdtime;
	level.totalholdtime_old = level.totalholdtime;
}

AddToSpawnArray (array, spawntype, customclassname)
{
	spawnpoints = getentarray (spawntype, "classname");
	for (i = 0; i < spawnpoints.size; i ++)
	{
		s = array.size;
		origin = FixSpawnPoint (spawnpoints[i].origin);
		array[s] = spawn ("script_origin", origin);
		array[s].origin = origin;
		array[s].angles = spawnpoints[i].angles;
		array[s].targetname = customclassname;
		array[s] placeSpawnpoint();
	}
	
	return (array);
}

AddToSpawnArrayCTFFlags (array, customclassname)
{
	if ((! isdefined (level.ctfflagspos[0])) || (! isdefined (level.ctfflagspos[1])))
		return (array);
		
	s = array.size;
	origin = FixSpawnPoint (level.ctfflagspos[0].origin);
	array[s] = spawn ("script_origin", origin);
	array[s].origin = origin;
	array[s].angles = level.ctfflagspos[0].angles;
	array[s].targetname = customclassname;
	array[s] placeSpawnpoint();
	
	origin = FixSpawnPoint (level.ctfflagspos[1].origin);
	array[s + 1] = spawn ("script_origin", origin);
	array[s + 1].origin = origin;
	array[s + 1].angles = level.ctfflagspos[1].angles;
	array[s + 1].targetname = customclassname;
	array[s + 1] placeSpawnpoint();

	return (array);
}

SaveCTFFlagsPos()
{
	allied_flags = getentarray ("allied_flag", "targetname");
	axis_flags = getentarray ("axis_flag", "targetname");
	
	if ((allied_flags.size != 1) || (axis_flags.size != 1))
		return;

	allied_flag = getent ("allied_flag", "targetname");
	axis_flag = getent ("axis_flag", "targetname");
	
	level.ctfflagspos[0] = spawnstruct();
	level.ctfflagspos[0].origin = allied_flag.origin;
	level.ctfflagspos[0].angles = allied_flag.angles;
	level.ctfflagspos[1] = spawnstruct();
	level.ctfflagspos[1].origin = axis_flag.origin;
	level.ctfflagspos[1].angles = axis_flag.angles;
}

AddToSpawnArraySDbombzones (array, customclassname)
{
	if ((! isdefined (level.sdbombzonepos[0])) || (! isdefined (level.sdbombzonepos[1])))
		return (array);

	s = array.size;
	for (i = 0; i <= 1; i ++)
	{
		origin = FixSpawnPoint (level.sdbombzonepos[i].origin);
		array[s + i] = spawn ("script_origin", origin);
		array[s + i].origin = origin;
		array[s + i].angles = level.sdbombzonepos[i].angles;
		array[s + i].targetname = customclassname;
		array[s + i] placeSpawnpoint();
	}

	return (array);
}

SaveSDBombzonesPos()
{
	bombzones = getentarray ("bombzone", "targetname");
	if (isdefined (bombzones[0]))
	{
		level.sdbombzonepos[0] = spawnstruct();
		level.sdbombzonepos[0].origin = bombzones[0].origin;
		level.sdbombzonepos[0].angles = bombzones[0].angles;
	}
	if (isdefined (bombzones[1]))
	{
		level.sdbombzonepos[1] = spawnstruct();
		level.sdbombzonepos[1].origin = bombzones[1].origin;
		level.sdbombzonepos[1].angles = bombzones[1].angles;
	}
}

AddToSpawnArrayHQRadios (array, customclassname)
{
	if (! isdefined (level.radio))
		return (array);

	for (i = 0; i < level.radio.size; i ++)
	{
		s = array.size;
		origin = FixSpawnPoint (level.radio[i].origin);
		array[s] = spawn ("script_origin", origin);
		array[s].origin = origin;
		array[s].angles = level.radio[i].angles;
		array[s].targetname = customclassname;
		array[s] placeSpawnpoint();
	}
	
	return (array);
}

RemoveHQRadioPoints()
{
	if (! isdefined (level.radio))
		return;

	for (i = 0; i < level.radio.size; i ++)
		level.radio[i] delete();

	level.radio = undefined;
}

SpawnPointsArray (modestring, customclassname)
{
	modearray = strtok (modestring, " ");
	activespawntype = [];
	for (i = 0; i < modearray.size; i ++)
	{
		switch (modearray[i])
		{
			case "dm" :
			case "tdm" :
			case "ctfp" :
			case "ctff" :
			case "sdp" :
			case "sdb" :
			case "hq" :
				activespawntype[modearray[i]] = true;
				break;
			default :
				break;
		}
	}

	array = [];

	if (isdefined (activespawntype["dm"]))
		array = AddToSpawnArray (array, "mp_dm_spawn", customclassname);

	if (isdefined (activespawntype["tdm"]))
		array = AddToSpawnArray (array, "mp_tdm_spawn", customclassname);
	
	if (isdefined (activespawntype["ctfp"]))
	{
		array = AddToSpawnArray (array, "mp_ctf_spawn_allied", customclassname);
		array = AddToSpawnArray (array, "mp_ctf_spawn_axis", customclassname);
	}
	
	if (isdefined (activespawntype["sdp"]))
	{
		array = AddToSpawnArray (array, "mp_sd_spawn_attacker", customclassname);
		array = AddToSpawnArray (array, "mp_sd_spawn_defender", customclassname);
	}
	
	if (isdefined (activespawntype["ctff"]))
		array = AddToSpawnArrayCTFFlags (array, customclassname);
	
	if (isdefined (activespawntype["sdb"]))
		array = AddToSpawnArraySDBombzones (array, customclassname);
	
	if (isdefined (activespawntype["hq"]))
		array = AddToSpawnArrayHQRadios (array, customclassname);

	return (array);
}

FixSpawnPoint (position)
{
	return (physicstrace (position + (0, 0, 20), position + (0, 0, -20)));
}
