#include maps\mp\_utility;
#include common_scripts\utility;

FACTION_REF_COL 					= 0;
FACTION_NAME_COL 					= 1;
FACTION_SHORT_NAME_COL 				= 2;
FACTION_ELIMINATED_COL 				= 3;
FACTION_FORFEITED_COL 				= 4;
FACTION_ICON_COL 					= 5;
FACTION_HUD_ICON_COL 				= 6;
FACTION_VOICE_PREFIX_COL 			= 7;
FACTION_SPAWN_MUSIC_COL 			= 8;
FACTION_WIN_MUSIC_COL 				= 9;
FACTION_FLAG_MODEL_COL 				= 10;
FACTION_FLAG_CARRY_MODEL_COL 		= 11;
FACTION_FLAG_ICON_COL 				= 12;
FACTION_FLAG_FX_COL 				= 13;
FACTION_COLOR_R_COL 				= 14;
FACTION_COLOR_G_COL 				= 15;
FACTION_COLOR_B_COL 				= 16;
FACTION_HEAD_ICON_COL 				= 17;
FACTION_CRATE_MODEL_COL 			= 18;
FACTION_DEPLOY_MODEL_COL 			= 19;

MT_REF_COL							= 0;
MT_NAME_COL							= 1;
MT_ICON_COL							= 2;
MT_HEAD_ICON_COL					= 3;

init()
{
	initScoreBoard();

	level.teamBalance = getDvarInt("scr_teambalance");
	level.maxClients = getDvarInt( "sv_maxclients" );

	setPlayerModels();

	level.freeplayers = [];

	if( level.teamBased )
	{
		level thread onPlayerConnect();
		level thread updateTeamBalance();

		wait .15;
		level thread updatePlayerTimes();
	}
	else
	{
		level thread onFreePlayerConnect();

		wait .15;
		level thread updateFreePlayerTimes();
	}
}


initScoreBoard()
{
	//NOTE: multi team teams do not need to set these dvars, the team names used on the scoreboard are taken from MTTable.csv
	//currently there are no team icons used for the MT scoreboard, and enemy teams will use g_teamTitleColor_EnemyTeam when needed.
	
	setDvar("g_TeamName_Allies", getTeamShortName( "allies" ));
	setDvar("g_TeamIcon_Allies", getTeamIcon( "allies" ));
	setDvar("g_TeamIcon_MyAllies", getTeamIcon( "allies" ));
	setDvar("g_TeamIcon_EnemyAllies", getTeamIcon( "allies" ));
	scoreColor = getTeamColor( "allies" );	
	setDvar("g_ScoresColor_Allies", scoreColor[0] + " " + scoreColor[1] + " " + scoreColor[2] );

	setDvar("g_TeamName_Axis", getTeamShortName( "axis" ));
	setDvar("g_TeamIcon_Axis", getTeamIcon( "axis" ));
	setDvar("g_TeamIcon_MyAxis", getTeamIcon( "axis" ));
	setDvar("g_TeamIcon_EnemyAxis", getTeamIcon( "axis" ));
	scoreColor = getTeamColor( "axis" );	
	setDvar("g_ScoresColor_Axis", scoreColor[0] + " " + scoreColor[1] + " " + scoreColor[2] );

	setdvar("g_ScoresColor_Spectator", ".25 .25 .25");
	setdvar("g_ScoresColor_Free", ".76 .78 .10");
	setdvar("g_teamTitleColor_MyTeam", ".6 .8 .6" );
	setdvar("g_teamTitleColor_EnemyTeam", "1 .45 .5" );	
}

onPlayerConnect()
{
	for(;;)
	{
		level waittill( "connected", player );

		player thread onJoinedTeam();
		player thread onJoinedSpectators();
		player thread onPlayerSpawned();

		player thread trackPlayedTime();
	}
}


onFreePlayerConnect()
{
	for(;;)
	{
		level waittill( "connected", player );

		player thread trackFreePlayedTime();
	}
}


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

	for(;;)
	{
		self waittill( "joined_team" );
		//self logString( "joined team: " + self.pers["team"] );
		self updateTeamTime();
	}
}


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

	for(;;)
	{
		self waittill("joined_spectators");
		self.pers["teamTime"] = undefined;
	}
}


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

	lootservicestarttrackingplaytime( self.xuid );

	self.timePlayed["allies"] = 0;
	self.timePlayed["axis"] = 0;
	self.timePlayed["other"] = 0;

	gameFlagWait( "prematch_done" );

	for ( ;; )
	{
		if ( game["state"] == "playing" )
		{
			if ( self.sessionteam == "allies" )
			{
				self.timePlayed["allies"]++;
				self.timePlayed["total"]++;
			}
			else if ( self.sessionteam == "axis" )
			{
				self.timePlayed["axis"]++;
				self.timePlayed["total"]++;
			}
			else if ( self.sessionteam == "spectator" )
			{
				self.timePlayed["other"]++;
			}

		}

		wait ( 1.0 );
	}
}


updatePlayerTimes()
{
	if ( !level.rankedmatch )
		return;
	
	level endon( "game_ended" );
	
	for ( ;; )
	{
		maps\mp\gametypes\_hostmigration::waitTillHostMigrationDone();
		
		foreach ( player in level.players )
			player updatePlayedTime();

		wait( 1.0 );
	}
}


updatePlayedTime()
{
	// bots dont need this logic running and its one of the lowest hanging script performance costs
	if ( IsAI( self ) )
		return;
	
	if ( !self rankingEnabled() )
		return;

	if ( self.timePlayed["allies"] )
	{
		self maps\mp\gametypes\_persistence::statAddBuffered( "timePlayedAllies", self.timePlayed["allies"] );
		self maps\mp\gametypes\_persistence::statAddBuffered( "timePlayedTotal", self.timePlayed["allies"] );
		self maps\mp\gametypes\_persistence::statAddChildBuffered( "round", "timePlayed", self.timePlayed["allies"] );
	}

	if ( self.timePlayed["axis"] )
	{
		self maps\mp\gametypes\_persistence::statAddBuffered( "timePlayedOpfor", self.timePlayed["axis"] );
		self maps\mp\gametypes\_persistence::statAddBuffered( "timePlayedTotal", self.timePlayed["axis"] );
		self maps\mp\gametypes\_persistence::statAddChildBuffered( "round", "timePlayed", self.timePlayed["axis"] );
	}

	if ( self.timePlayed["other"] )
	{
		self maps\mp\gametypes\_persistence::statAddBuffered( "timePlayedOther", self.timePlayed["other"] );
		self maps\mp\gametypes\_persistence::statAddBuffered( "timePlayedTotal", self.timePlayed["other"] );
		self maps\mp\gametypes\_persistence::statAddChildBuffered( "round", "timePlayed", self.timePlayed["other"] );
	}

	if ( game["state"] == "postgame" )
		return;

	self.timePlayed["allies"] = 0;
	self.timePlayed["axis"] = 0;
	self.timePlayed["other"] = 0;
}


updateTeamTime()
{
	if ( game["state"] != "playing" )
		return;

	self.pers["teamTime"] = getTime();
}


updateTeamBalanceDvar()
{
	for(;;)
	{
		teambalance = getdvarInt("scr_teambalance");
		if(level.teambalance != teambalance)
			level.teambalance = getdvarInt("scr_teambalance");

		wait 1;
	}
}


updateTeamBalance()
{
	level.teamLimit = level.maxclients / 2;

	level thread updateTeamBalanceDvar();

	wait .15;

	if ( level.teamBalance && isRoundBased() )
	{
    	if( isDefined( game["BalanceTeamsNextRound"] ) )
    		iPrintLnbold( &"MP_AUTOBALANCE_NEXT_ROUND" );

		// TODO: add or change
		level waittill( "restarting" );

		if( isDefined( game["BalanceTeamsNextRound"] ) )
		{
			level balanceTeams();
			game["BalanceTeamsNextRound"] = undefined;
		}
		else if( !getTeamBalance() )
		{
			game["BalanceTeamsNextRound"] = true;
		}
	}
	else
	{
		level endon ( "game_ended" );
		for( ;; )
		{
			if( level.teamBalance )
			{
				if( !getTeamBalance() )
				{
					iPrintLnBold( &"MP_AUTOBALANCE_SECONDS", 15 );
				    wait 15.0;

					if( !getTeamBalance() )
						level balanceTeams();
				}

				wait 59.0;
			}

			wait 1.0;
		}
	}

}


getTeamBalance()
{
	level.team["allies"] = 0;
	level.team["axis"] = 0;

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

	if((level.team["allies"] > (level.team["axis"] + level.teamBalance)) || (level.team["axis"] > (level.team["allies"] + level.teamBalance)))
		return false;
	else
		return true;
}


balanceTeams()
{
	iPrintLnBold( game["strings"]["autobalance"] );
	//Create/Clear the team arrays
	AlliedPlayers = [];
	AxisPlayers = [];

	// Populate the team arrays
	players = level.players;
	for(i = 0; i < players.size; i++)
	{
		if(!isdefined(players[i].pers["teamTime"]))
			continue;

		if((isdefined(players[i].pers["team"])) && (players[i].pers["team"] == "allies"))
			AlliedPlayers[AlliedPlayers.size] = players[i];
		else if((isdefined(players[i].pers["team"])) && (players[i].pers["team"] == "axis"))
			AxisPlayers[AxisPlayers.size] = players[i];
	}

	MostRecent = undefined;

	while((AlliedPlayers.size > (AxisPlayers.size + 1)) || (AxisPlayers.size > (AlliedPlayers.size + 1)))
	{
		if(AlliedPlayers.size > (AxisPlayers.size + 1))
		{
			// Move the player that's been on the team the shortest ammount of time (highest teamTime value)
			for(j = 0; j < AlliedPlayers.size; j++)
			{
				if(isdefined(AlliedPlayers[j].dont_auto_balance))
					continue;

				if(!isdefined(MostRecent))
					MostRecent = AlliedPlayers[j];
				else if(AlliedPlayers[j].pers["teamTime"] > MostRecent.pers["teamTime"])
					MostRecent = AlliedPlayers[j];
			}

			MostRecent [[level.onTeamSelection]]("axis");
		}
		else if(AxisPlayers.size > (AlliedPlayers.size + 1))
		{
			// Move the player that's been on the team the shortest ammount of time (highest teamTime value)
			for(j = 0; j < AxisPlayers.size; j++)
			{
				if(isdefined(AxisPlayers[j].dont_auto_balance))
					continue;

				if(!isdefined(MostRecent))
					MostRecent = AxisPlayers[j];
				else if(AxisPlayers[j].pers["teamTime"] > MostRecent.pers["teamTime"])
					MostRecent = AxisPlayers[j];
			}

			MostRecent [[level.onTeamSelection]]("allies");
		}

		MostRecent = undefined;
		AlliedPlayers = [];
		AxisPlayers = [];

		players = level.players;
		for(i = 0; i < players.size; i++)
		{
			if((isdefined(players[i].pers["team"])) && (players[i].pers["team"] == "allies"))
				AlliedPlayers[AlliedPlayers.size] = players[i];
			else if((isdefined(players[i].pers["team"])) &&(players[i].pers["team"] == "axis"))
				AxisPlayers[AxisPlayers.size] = players[i];
		}
	}
}


setGhillieModels( env )
{
	/*
	level.environment = env;
	switch ( env )
	{
		case "desert":
			//mptype\mptype_ally_ghillie_desert::precache();
			if( level.multiTeamBased )
			{
				
				for( i = 0; i < level.teamNameList.size; i++ )
				{
					string_ref = level.teamNameList[i] + "_model";
					game[string_ref]["GHILLIE"] = mptype\mptype_ally_ghillie_desert::main;
				}
			}
			else
			{
				//mptype\mptype_opforce_ghillie_desert::precache();
				game["allies_model"]["GHILLIE"] = mptype\mptype_ally_ghillie_desert::main;
				game["axis_model"]["GHILLIE"] = mptype\mptype_opforce_ghillie_desert::main;
			}
			break;
		case "arctic":
			//mptype\mptype_ally_ghillie_arctic::precache();
			if( level.multiTeamBased )
			{
				for( i = 0; i < level.teamNameList.size; i++ )
				{
					string_ref = level.teamNameList[i] + "_model";
					game[string_ref]["GHILLIE"] = mptype\mptype_ally_ghillie_arctic::main;
				}
			}
			else
			{
				//mptype\mptype_opforce_ghillie_arctic::precache();
				game["allies_model"]["GHILLIE"] = mptype\mptype_ally_ghillie_arctic::main;
				game["axis_model"]["GHILLIE"] = mptype\mptype_opforce_ghillie_arctic::main;
			}
			break;
		case "urban":
			//mptype\mptype_ally_ghillie_urban::precache();
			if( level.multiTeamBased )
			{
				for( i = 0; i < level.teamNameList.size; i++ )
				{
					string_ref = level.teamNameList[i] + "_model";
					game[string_ref]["GHILLIE"] = mptype\mptype_ally_ghillie_urban::main;
				}
			}
			else
			{
				//mptype\mptype_opforce_ghillie_urban::precache();
				game["allies_model"]["GHILLIE"] = mptype\mptype_ally_ghillie_urban::main;
				game["axis_model"]["GHILLIE"] = mptype\mptype_opforce_ghillie_urban::main;
			}
			break;
		case "forest":
			//mptype\mptype_ally_ghillie_forest::precache();
			if( level.multiTeamBased )
			{
				for( i = 0; i < level.teamNameList.size; i++ )
				{
					string_ref = level.teamNameList[i] + "_model";
					game[string_ref]["GHILLIE"] = mptype\mptype_ally_ghillie_forest::main;
				}
			}
			else
			{
				//mptype\mptype_opforce_ghillie_forest::precache();
				game["allies_model"]["GHILLIE"] = mptype\mptype_ally_ghillie_forest::main;
				game["axis_model"]["GHILLIE"] = mptype\mptype_opforce_ghillie_forest::main;
			}
			break;
		case "forest_militia":
			//mptype\mptype_ally_ghillie_forest::precache();
			if( level.multiTeamBased )
			{
				for( i = 0; i < level.teamNameList.size; i++ )
				{
					string_ref = level.teamNameList[i] + "_model";
					game[string_ref]["GHILLIE"] = mptype\mptype_ally_ghillie_forest::main;
				}
			}
			else
			{
				//mptype\mptype_opforce_ghillie_militia::precache();
				game["allies_model"]["GHILLIE"] = mptype\mptype_ally_ghillie_forest::main;
				game["axis_model"]["GHILLIE"] = mptype\mptype_opforce_ghillie_militia::main;
			}
			break;
		case "desert_militia":
			//mptype\mptype_ally_ghillie_desert::precache();
			if( level.multiTeamBased )
			{
				for( i = 0; i < level.teamNameList.size; i++ )
				{
					string_ref = level.teamNameList[i] + "_model";
					game[string_ref]["GHILLIE"] = mptype\mptype_ally_ghillie_desert::main;
				}
			}
			else
			{
				//mptype\mptype_opforce_ghillie_militia::precache();
				game["allies_model"]["GHILLIE"] = mptype\mptype_ally_ghillie_desert::main;
				game["axis_model"]["GHILLIE"] = mptype\mptype_opforce_ghillie_militia::main;
			}
			break;	
		case "arctic_militia":
			//mptype\mptype_ally_ghillie_arctic::precache();
			if( level.multiTeamBased )
			{
				for( i = 0; i < level.teamNameList.size; i++ )
				{
					string_ref = level.teamNameList[i] + "_model";
					game[string_ref]["GHILLIE"] = mptype\mptype_ally_ghillie_arctic::main;
				}
			}
			else
			{
				//mptype\mptype_opforce_ghillie_militia::precache();
				game["allies_model"]["GHILLIE"] = mptype\mptype_ally_ghillie_arctic::main;
				game["axis_model"]["GHILLIE"] = mptype\mptype_opforce_ghillie_militia::main;
			}
			break;
		case "urban_militia":
			//mptype\mptype_ally_ghillie_urban::precache();
			if( level.multiTeamBased )
			{
				for( i = 0; i < level.teamNameList.size; i++ )
				{
					string_ref = level.teamNameList[i] + "_model";
					game[string_ref]["GHILLIE"] = mptype\mptype_ally_ghillie_urban::main;
				}
			}
			else
			{
				//mptype\mptype_opforce_ghillie_militia::precache();
				game["allies_model"]["GHILLIE"] = mptype\mptype_ally_ghillie_urban::main;
				game["axis_model"]["GHILLIE"] = mptype\mptype_opforce_ghillie_militia::main;
			}
			break;
		default:
			break;			
	}
	*/
}

setTeamModels( team, charSet )
{
	/*
	switch ( charSet )
	{
		//MW3 Type
		case "delta_multicam":
			//mptype\mptype_delta_multicam_assault::precache();
			//mptype\mptype_delta_multicam_lmg::precache();
			//mptype\mptype_delta_multicam_smg::precache();
			//mptype\mptype_delta_multicam_shotgun::precache();
			//mptype\mptype_delta_multicam_sniper::precache();
			//mptype\mptype_delta_multicam_riot::precache();
			//mptype\mptype_ally_juggernaut::precache();

			game[team + "_model"]["SNIPER"] = mptype\mptype_delta_multicam_sniper::main;
			game[team + "_model"]["LMG"] = mptype\mptype_delta_multicam_lmg::main;
			game[team + "_model"]["ASSAULT"] = mptype\mptype_delta_multicam_assault::main;
			game[team + "_model"]["SHOTGUN"] = mptype\mptype_delta_multicam_shotgun::main;
			game[team + "_model"]["SMG"] = mptype\mptype_delta_multicam_smg::main;
			game[team + "_model"]["RIOT"] = mptype\mptype_delta_multicam_riot::main;
			game[team + "_model"]["JUGGERNAUT"] = mptype\mptype_ally_juggernaut::main;
			
			break;
		//MW3 Type	
		case "sas_urban":
			//mptype\mptype_sas_urban_assault::precache();
			//mptype\mptype_sas_urban_lmg::precache();
			//mptype\mptype_sas_urban_shotgun::precache();
			//mptype\mptype_sas_urban_smg::precache();
			//mptype\mptype_sas_urban_sniper::precache();
			//mptype\mptype_ally_juggernaut::precache();
			
			game[team + "_model"]["SNIPER"] = mptype\mptype_sas_urban_sniper::main;
			game[team + "_model"]["LMG"] = mptype\mptype_sas_urban_lmg::main;
			game[team + "_model"]["ASSAULT"] = mptype\mptype_sas_urban_assault::main;
			game[team + "_model"]["SHOTGUN"] = mptype\mptype_sas_urban_shotgun::main;
			game[team + "_model"]["SMG"] = mptype\mptype_sas_urban_smg::main;
			game[team + "_model"]["RIOT"] = mptype\mptype_sas_urban_smg::main;
			game[team + "_model"]["JUGGERNAUT"] = mptype\mptype_ally_juggernaut::main;

			break;
		//MW3 Type
		case "gign_paris":
			//mptype\mptype_gign_paris_assault::precache();
			//mptype\mptype_gign_paris_lmg::precache();
			//mptype\mptype_gign_paris_shotgun::precache();
			//mptype\mptype_gign_paris_smg::precache();
			//mptype\mptype_gign_paris_sniper::precache();
			//mptype\mptype_gign_paris_riot::precache();
			//mptype\mptype_ally_juggernaut::precache();

			game[team + "_model"]["SNIPER"] = mptype\mptype_gign_paris_sniper::main;
			game[team + "_model"]["LMG"] = mptype\mptype_gign_paris_lmg::main;
			game[team + "_model"]["ASSAULT"] = mptype\mptype_gign_paris_assault::main;
			game[team + "_model"]["SHOTGUN"] = mptype\mptype_gign_paris_shotgun::main;
			game[team + "_model"]["SMG"] = mptype\mptype_gign_paris_smg::main;
			game[team + "_model"]["RIOT"] = mptype\mptype_gign_paris_riot::main;//temp
			game[team + "_model"]["JUGGERNAUT"] = mptype\mptype_ally_juggernaut::main;

			break;	
		//MW3 Type
		case "pmc_africa":
			//mptype\mptype_pmc_africa_assault::precache();
			//mptype\mptype_pmc_africa_lmg::precache();
			//mptype\mptype_pmc_africa_smg::precache();
			//mptype\mptype_pmc_africa_shotgun::precache();
			//mptype\mptype_pmc_africa_sniper::precache();
			//mptype\mptype_pmc_africa_riot::precache();
			//mptype\mptype_ally_juggernaut::precache();

			game[team + "_model"]["SNIPER"] = mptype\mptype_pmc_africa_sniper::main;
			game[team + "_model"]["LMG"] = mptype\mptype_pmc_africa_lmg::main;
			game[team + "_model"]["ASSAULT"] = mptype\mptype_pmc_africa_assault::main;
			game[team + "_model"]["SHOTGUN"] = mptype\mptype_pmc_africa_shotgun::main;
			game[team + "_model"]["SMG"] = mptype\mptype_pmc_africa_smg::main;
			game[team + "_model"]["RIOT"] = mptype\mptype_pmc_africa_riot::main;
			game[team + "_model"]["JUGGERNAUT"] = mptype\mptype_ally_juggernaut::main;
			
			break;	
			
		case "opforce_air"://MW3 Type
			//mptype\mptype_opforce_air_assault::precache();
			//mptype\mptype_opforce_air_lmg::precache();
			//mptype\mptype_opforce_air_shotgun::precache();
			//mptype\mptype_opforce_air_smg::precache();
			//mptype\mptype_opforce_air_sniper::precache();
			//mptype\mptype_opforce_air_riot::precache();
			//mptype\mptype_opforce_juggernaut::precache();

			game[team + "_model"]["SNIPER"] = mptype\mptype_opforce_air_sniper::main;//old type
			game[team + "_model"]["LMG"] = mptype\mptype_opforce_air_lmg::main;
			game[team + "_model"]["ASSAULT"] = mptype\mptype_opforce_air_assault::main;
			game[team + "_model"]["SHOTGUN"] = mptype\mptype_opforce_air_shotgun::main;
			game[team + "_model"]["SMG"] = mptype\mptype_opforce_air_smg::main;
			game[team + "_model"]["RIOT"] = mptype\mptype_opforce_air_riot::main;//temp
			game[team + "_model"]["JUGGERNAUT"] = mptype\mptype_opforce_juggernaut::main;

			break;
		
		case "opforce_snow"://MW3 Type
			//mptype\mptype_opforce_snow_assault::precache();
			//mptype\mptype_opforce_snow_lmg::precache();
			//mptype\mptype_opforce_snow_shotgun::precache();
			//mptype\mptype_opforce_snow_smg::precache();
			//mptype\mptype_opforce_snow_sniper::precache();
			//mptype\mptype_opforce_snow_riot::precache();
			//mptype\mptype_opforce_juggernaut::precache();
			
			game[team + "_model"]["SNIPER"] = mptype\mptype_opforce_snow_sniper::main;
			game[team + "_model"]["LMG"] = mptype\mptype_opforce_snow_lmg::main;
			game[team + "_model"]["ASSAULT"] = mptype\mptype_opforce_snow_assault::main;
			game[team + "_model"]["SHOTGUN"] = mptype\mptype_opforce_snow_shotgun::main;
			game[team + "_model"]["SMG"] = mptype\mptype_opforce_snow_smg::main;
			game[team + "_model"]["RIOT"] = mptype\mptype_opforce_snow_riot::main;//temp
			game[team + "_model"]["JUGGERNAUT"] = mptype\mptype_opforce_juggernaut::main;

			break;
				
		case "opforce_urban"://MW3 Type
			//mptype\mptype_opforce_urban_assault::precache();
			//mptype\mptype_opforce_urban_lmg::precache();
			//mptype\mptype_opforce_urban_shotgun::precache();
			//mptype\mptype_opforce_urban_smg::precache();
			//mptype\mptype_opforce_urban_sniper::precache();
			//mptype\mptype_opforce_urban_riot::precache();
			//mptype\mptype_opforce_juggernaut::precache();

			game[team + "_model"]["SNIPER"] = mptype\mptype_opforce_urban_sniper::main;
			game[team + "_model"]["LMG"] = mptype\mptype_opforce_urban_lmg::main;
			game[team + "_model"]["ASSAULT"] = mptype\mptype_opforce_urban_assault::main;
			game[team + "_model"]["SHOTGUN"] = mptype\mptype_opforce_urban_shotgun::main;
			game[team + "_model"]["SMG"] = mptype\mptype_opforce_urban_smg::main;
			game[team + "_model"]["RIOT"] = mptype\mptype_opforce_urban_riot::main;//temp
			game[team + "_model"]["JUGGERNAUT"] = mptype\mptype_opforce_juggernaut::main;

			break;
			
		case "opforce_woodland"://MW3 Type
			//mptype\mptype_opforce_woodland_assault::precache();
			//mptype\mptype_opforce_woodland_lmg::precache();
			//mptype\mptype_opforce_woodland_shotgun::precache();
			//mptype\mptype_opforce_woodland_smg::precache();
			//mptype\mptype_opforce_woodland_sniper::precache();
			//mptype\mptype_opforce_woodland_riot::precache();
			//mptype\mptype_opforce_juggernaut::precache();

			game[team + "_model"]["SNIPER"] = mptype\mptype_opforce_woodland_sniper::main;
			game[team + "_model"]["LMG"] = mptype\mptype_opforce_woodland_lmg::main;
			game[team + "_model"]["ASSAULT"] = mptype\mptype_opforce_woodland_assault::main;
			game[team + "_model"]["SHOTGUN"] = mptype\mptype_opforce_woodland_shotgun::main;
			game[team + "_model"]["SMG"] = mptype\mptype_opforce_woodland_smg::main;
			game[team + "_model"]["RIOT"] = mptype\mptype_opforce_woodland_riot::main;//temp
			game[team + "_model"]["JUGGERNAUT"] = mptype\mptype_opforce_juggernaut::main;

			break;
			
		case "opforce_africa"://MW3 Type
			//mptype\mptype_opforce_africa_assault::precache();
			//mptype\mptype_opforce_africa_lmg::precache();
			//mptype\mptype_opforce_africa_shotgun::precache();
			//mptype\mptype_opforce_africa_smg::precache();
			//mptype\mptype_opforce_africa_sniper::precache();
			//mptype\mptype_opforce_africa_riot::precache();
			//mptype\mptype_opforce_juggernaut::precache();

			//game[team + "_model"]["SNIPER"] = mptype\mptype_opforce_africa_sniper::main;
			game[team + "_model"]["SNIPER"] = mptype\mptype_opforce_africa_lmg::main;
			game[team + "_model"]["LMG"] = mptype\mptype_opforce_africa_lmg::main;
			game[team + "_model"]["ASSAULT"] = mptype\mptype_opforce_africa_assault::main;
			game[team + "_model"]["SHOTGUN"] = mptype\mptype_opforce_africa_shotgun::main;
			game[team + "_model"]["SMG"] = mptype\mptype_opforce_africa_smg::main;
			game[team + "_model"]["RIOT"] = mptype\mptype_opforce_africa_riot::main;//temp
			game[team + "_model"]["JUGGERNAUT"] = mptype\mptype_opforce_juggernaut::main;

			break;
			
		case "opforce_henchmen":
			//mptype\mptype_opforce_henchmen_assault::precache();
			//mptype\mptype_opforce_henchmen_lmg::precache();
			//mptype\mptype_opforce_henchmen_shotgun::precache();
			//mptype\mptype_opforce_henchmen_smg::precache();
			//mptype\mptype_opforce_henchmen_sniper::precache();
			//mptype\mptype_opforce_henchmen_riot::precache();
			//mptype\mptype_opforce_juggernaut::precache();

			game[team + "_model"]["SNIPER"] = mptype\mptype_opforce_henchmen_sniper::main;
			game[team + "_model"]["LMG"] = mptype\mptype_opforce_henchmen_lmg::main;
			game[team + "_model"]["ASSAULT"] = mptype\mptype_opforce_henchmen_assault::main;
			game[team + "_model"]["SHOTGUN"] = mptype\mptype_opforce_henchmen_shotgun::main;
			game[team + "_model"]["SMG"] = mptype\mptype_opforce_henchmen_smg::main;
			game[team + "_model"]["RIOT"] = mptype\mptype_opforce_henchmen_riot::main;//temp
			game[team + "_model"]["JUGGERNAUT"] = mptype\mptype_opforce_juggernaut::main;

			break;

		case "sentinel":
			game[team + "_model"]["SNIPER"] = mptype\mptype_sentinel_sniper::main;
			game[team + "_model"]["LMG"] = mptype\mptype_sentinel_sniper::main;
			game[team + "_model"]["ASSAULT"] = mptype\mptype_sentinel_sniper::main;
			game[team + "_model"]["SHOTGUN"] = mptype\mptype_sentinel_sniper::main;
			game[team + "_model"]["SMG"] = mptype\mptype_sentinel_sniper::main;
			game[team + "_model"]["RIOT"] = mptype\mptype_sentinel_sniper::main;//temp
			game[team + "_model"]["JUGGERNAUT"] = mptype\mptype_sentinel_sniper::main;

			break;

		case "sentinel_vl":
			game[team + "_model"]["SNIPER"] = mptype\mptype_sentinel::main;
			game[team + "_model"]["LMG"] = mptype\mptype_sentinel::main;
			game[team + "_model"]["ASSAULT"] = mptype\mptype_sentinel::main;
			game[team + "_model"]["SHOTGUN"] = mptype\mptype_sentinel::main;
			game[team + "_model"]["SMG"] = mptype\mptype_sentinel::main;
			game[team + "_model"]["RIOT"] = mptype\mptype_sentinel::main;//temp
			game[team + "_model"]["JUGGERNAUT"] = mptype\mptype_sentinel::main;

			break;

		case "atlas":
			game[team + "_model"]["SNIPER"] = mptype\mptype_atlas_smg::main;
			game[team + "_model"]["LMG"] = mptype\mptype_atlas_smg::main;
			game[team + "_model"]["ASSAULT"] = mptype\mptype_atlas_smg::main;
			game[team + "_model"]["SHOTGUN"] = mptype\mptype_atlas_smg::main;
			game[team + "_model"]["SMG"] = mptype\mptype_atlas_smg::main;
			game[team + "_model"]["RIOT"] = mptype\mptype_atlas_smg::main;//temp
			game[team + "_model"]["JUGGERNAUT"] = mptype\mptype_atlas_smg::main;

			break;
	}
	*/
}

setPlayerModels()
{
	//mptype\mptype_us_army_riot::precache();
	//game["allies_model"]["riotshield"] = mptype\mptype_us_army_riot::main;
	//game["axis_model"]["riotshield"] = mptype\mptype_us_army_riot::main;

	if( level.multiTeamBased )
	{
		for( i = 0; i < level.teamNameList.size; i++ )
		{
			assert( isDefined( game[level.teamNameList[i]] ));	
			setTeamModels( level.teamNameList[i], game[level.teamNameList[i]] );
		}
	}
	else
	{
		setTeamModels( "allies", game["allies"] );
		setTeamModels( "axis", game["axis"] );
	}
	
	setGhillieModels( getMapCustom( "environment" ) );
	//mptype\mptype_cloak_test::precache();
}


playerCostume()
{
	// Don't set agent costumes like this (use the agent costume table instead)
	if ( IsAgent( self ) && !GetDvarInt( "virtualLobbyActive", 0 ) )
		return true;
	
	prof_begin( "playerCostume" );
	self SetCostumeModels( self.costume );
	prof_end( "playerCostume" );
	
	if ( IsDefined( self.perks ) && !GetDvarInt( "virtualLobbyActive", 0 ) )
	{
		if ( self _hasPerk( "specialty_exo_shoulderlauncher" ) )
		{
			if ( !self _hasPerk( "specialty_wildcard_dualtacticals" ) )
				self attach( "npc_exo_launcher_base_L", "", true );
			if ( self _hasPerk( "specialty_wildcard_duallethals" ) )
				self attach( "npc_exo_launcher_base_R", "", true );
		}
		else
		{
			if ( !self _hasPerk( "specialty_wildcard_dualtacticals" ) )
				self attach( "npc_exo_arm_launcher_L", "J_Elbow_LE", true );
			if ( self _hasPerk( "specialty_wildcard_duallethals" ) )
				self attach( "npc_exo_arm_launcher_R", "J_Elbow_RI", true );
		}
	}

	prof_begin( "attachCostume" );
	self.voice = "american";
	self SetClothType("vestlight");
	prof_end( "attachCostume" );
	return true;
}

validCostume( costume )
{
	if ( !IsDefined( costume ) )
		return false;
	
	valid = ValidateCostume( costume );

	for ( i = 0; i < costume.size; i++ )
	{
		if ( costume[i] != valid[i] )
		{
			return false;
		}
	}

	return true;
}

getDefaultCostume()
{	
	costume = RandomCostume();  
	return costume;
}

getPracticeRoundCostume()
{
	if ( !IsDefined( level.practice_round_costume ) )
	{
		level.practice_round_max_costumes = TableGetColumnCount( level.practiceRoundCostumeTableName ) - 1;
		level.practice_round_costume = RandomInt( level.practice_round_max_costumes );
	}
	
	player_index = 0;
	for( i = 0; i < level.players.size; i++ )
	{
		if ( level.players[i] == self )
		{
			player_index = i;
			break;
		}
	}
	
	player_costume = ( level.practice_round_costume + player_index ) % level.practice_round_max_costumes;

	costume = GetCostumeFromTable( level.practiceRoundCostumeTableName, player_costume + 1 );
	return costume;
}

getHardcoreCostume()
{
	col_index = 2;
	if ( self.pers["team"] == "axis" )
		col_index = 1;
	
	costume = GetCostumeFromTable( level.hardcoreCostumeTableName, col_index );
	return costume;
}

playerModelForWeapon( weapon, secondary )
{
	team = self.team;

	costumeFound = self playerCostume();
	assert( costumeFound );
	
	self notify( "player_model_set" );
}


CountPlayers()
{
	player_counts = [];

	for( i = 0; i < level.teamNameList.size; i++ )
	{
		player_counts[level.teamNameList[i]] = 0;
	}
	
	for( i = 0; i < level.players.size; i++ )
	{
		if( level.players[i] == self )
			continue;

		if( level.players[i].pers["team"] == "spectator" )
			continue;

		if( isdefined( level.players[i].pers["team"] ))
		{
			assert( isdefined( player_counts[level.players[i].pers["team"]] ));
			player_counts[level.players[i].pers["team"]]++;
		}
	}

	return player_counts;
}


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

	lootservicestarttrackingplaytime( self.xuid );

	self.timePlayed["allies"] = 0;
	self.timePlayed["axis"] = 0;
	self.timePlayed["other"] = 0;

	for ( ;; )
	{
		if ( game["state"] == "playing" )
		{
			if ( isDefined( self.pers["team"] ) && self.pers["team"] == "allies" && self.sessionteam != "spectator" )
			{
				self.timePlayed["allies"]++;
				self.timePlayed["total"]++;
			}
			else if ( isDefined( self.pers["team"] ) && self.pers["team"] == "axis" && self.sessionteam != "spectator" )
			{
				self.timePlayed["axis"]++;
				self.timePlayed["total"]++;
			}
			else
			{
				self.timePlayed["other"]++;
			}
		}

		wait ( 1.0 );
	}
}


/#
playerConnectedTest()
{
	if ( getdvarint( "scr_runlevelandquit" ) == 1 )
		return;
	
	level endon( "exitLevel_called" );
	
	// every frame, do a getPlayerData on each player in level.players.
	// this will force a script error if a player in level.players isn't connected.
	for ( ;; )
	{
		foreach ( player in level.players )
		{
			player getPlayerData( "experience" );
		}
		wait .05;
	}
}
#/


updateFreePlayerTimes()
{
	if ( !level.rankedmatch )
		return;
	
	/#
	thread playerConnectedTest();
	#/
	
	nextToUpdate = 0;
	for ( ;; )
	{
		nextToUpdate++;
		if ( nextToUpdate >= level.players.size )
			nextToUpdate = 0;

		if ( isDefined( level.players[nextToUpdate] ) )
			level.players[nextToUpdate] updateFreePlayedTime();

		wait ( 1.0 );
	}
}


updateFreePlayedTime()
{
	if ( !self rankingEnabled() )
		return;

	// bots dont need this logic running and its one of the lowest hanging script performance costs
	if ( IsAI( self ) )
		return;

	if ( self.timePlayed["allies"] )
	{
		self maps\mp\gametypes\_persistence::statAddBuffered( "timePlayedAllies", self.timePlayed["allies"] );
		self maps\mp\gametypes\_persistence::statAddBuffered( "timePlayedTotal", self.timePlayed["allies"] );
		self maps\mp\gametypes\_persistence::statAddChildBuffered( "round", "timePlayed", self.timePlayed["allies"] );
	}

	if ( self.timePlayed["axis"] )
	{
		self maps\mp\gametypes\_persistence::statAddBuffered( "timePlayedOpfor", self.timePlayed["axis"] );
		self maps\mp\gametypes\_persistence::statAddBuffered( "timePlayedTotal", self.timePlayed["axis"] );
		self maps\mp\gametypes\_persistence::statAddChildBuffered( "round", "timePlayed", self.timePlayed["axis"] );
	}

	if ( self.timePlayed["other"] )
	{
		self maps\mp\gametypes\_persistence::statAddBuffered( "timePlayedOther", self.timePlayed["other"] );
		self maps\mp\gametypes\_persistence::statAddBuffered( "timePlayedTotal", self.timePlayed["other"] );
		self maps\mp\gametypes\_persistence::statAddChildBuffered( "round", "timePlayed", self.timePlayed["other"] );
	}

	if ( game["state"] == "postgame" )
		return;

	self.timePlayed["allies"] = 0;
	self.timePlayed["axis"] = 0;
	self.timePlayed["other"] = 0;
}


getJoinTeamPermissions( team )
{
	if ( isCOOP() )
		return true;
	
	teamcount = 0;
	botcount = 0;

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

		if((isdefined(player.pers["team"])) && (player.pers["team"] == team))
		{
			teamcount++;
			
			if( IsBot( player ) )
				botcount++;
		}
	}

	if( teamCount < level.teamLimit )
		return true;
	else if ( botcount > 0 ) 	// If team is full but has bots, still allow human player on
		return true;
	else if ( level.gameType == "infect" )		// In infect we put all the players on the survivors team at the start so we ignore team limit
		return true;
	else
		return false;
}


onPlayerSpawned()
{
	level endon ( "game_ended" );

	for ( ;; )
	{
		self waittill ( "spawned_player" );
	}
}

MT_getTeamName( teamRef )
{
	return ( tableLookupIString( "mp/MTTable.csv", MT_REF_COL, teamRef, MT_NAME_COL ));
}

MT_getTeamIcon( teamRef )
{
	return ( tableLookup( "mp/MTTable.csv", MT_REF_COL, teamRef, MT_ICON_COL ));
}

MT_getTeamHeadIcon( teamRef )
{
	return ( tableLookup( "mp/MTTable.csv", MT_REF_COL, teamRef, MT_HEAD_ICON_COL ));	
}

getTeamName( teamRef )
{
	return ( tableLookupIString( "mp/factionTable.csv", FACTION_REF_COL, game[teamRef], FACTION_NAME_COL ) );
}

getTeamShortName( teamRef )
{
	return ( tableLookupIString( "mp/factionTable.csv", FACTION_REF_COL, game[teamRef], FACTION_SHORT_NAME_COL ) );
}

getTeamForfeitedString( teamRef )
{
	return ( tableLookupIString( "mp/factionTable.csv", FACTION_REF_COL, game[teamRef], FACTION_FORFEITED_COL ) );
}

getTeamEliminatedString( teamRef )
{
	return ( tableLookupIString( "mp/factionTable.csv", FACTION_REF_COL, game[teamRef], FACTION_ELIMINATED_COL ) );
}

getTeamIcon( teamRef )
{
	return ( tableLookup( "mp/factionTable.csv", FACTION_REF_COL, game[teamRef], FACTION_ICON_COL ) );
}

getTeamHudIcon( teamRef )
{
	return ( tableLookup( "mp/factionTable.csv", FACTION_REF_COL, game[teamRef], FACTION_HUD_ICON_COL ) );
}

getTeamHeadIcon( teamRef )
{
	return ( tableLookup( "mp/factionTable.csv", FACTION_REF_COL, game[teamRef], FACTION_HEAD_ICON_COL ) );
}

getTeamVoicePrefix( teamRef )
{
	return ( tableLookup( "mp/factionTable.csv", FACTION_REF_COL, game[teamRef], FACTION_VOICE_PREFIX_COL ) );
}

getTeamSpawnMusic( teamRef )
{
	return ( tableLookup( "mp/factionTable.csv", FACTION_REF_COL, game[teamRef], FACTION_SPAWN_MUSIC_COL ) );
}

getTeamWinMusic( teamRef )
{
	return ( tableLookup( "mp/factionTable.csv", FACTION_REF_COL, game[teamRef], FACTION_WIN_MUSIC_COL ) );
}

getTeamFlagModel( teamRef )
{
	return ( tableLookup( "mp/factionTable.csv", FACTION_REF_COL, game[teamRef], FACTION_FLAG_MODEL_COL ) );
}

getTeamFlagCarryModel( teamRef )
{
	return ( tableLookup( "mp/factionTable.csv", FACTION_REF_COL, game[teamRef], FACTION_FLAG_CARRY_MODEL_COL ) );
}

getTeamFlagIcon( teamRef )
{
	return ( tableLookup( "mp/factionTable.csv", FACTION_REF_COL, game[teamRef], FACTION_FLAG_ICON_COL ) );
}

getTeamFlagFX( teamRef )
{
	return ( tableLookup( "mp/factionTable.csv", FACTION_REF_COL, game[teamRef], FACTION_FLAG_FX_COL ) );
}

getTeamColor( teamRef )
{
	return ( (stringToFloat( tableLookup( "mp/factionTable.csv", FACTION_REF_COL, game[teamRef], FACTION_COLOR_R_COL ) ),
				stringToFloat( tableLookup( "mp/factionTable.csv", FACTION_REF_COL, game[teamRef], FACTION_COLOR_G_COL ) ),
				stringToFloat( tableLookup( "mp/factionTable.csv", FACTION_REF_COL, game[teamRef], FACTION_COLOR_B_COL ) ))
			);
}

getTeamCrateModel( teamRef )
{
	return ( tableLookup( "mp/factionTable.csv", FACTION_REF_COL, game[teamRef], FACTION_CRATE_MODEL_COL ) );	
}

getTeamDeployModel( teamRef )
{
	return ( tableLookup( "mp/factionTable.csv", FACTION_REF_COL, game[teamRef], FACTION_DEPLOY_MODEL_COL ) );	
}
