#using scripts\shared\challenges_shared;
#using scripts\shared\clientfield_shared;
#using scripts\shared\demo_shared;
#using scripts\shared\gameobjects_shared;
#using scripts\shared\hud_message_shared;
#using scripts\shared\hud_util_shared;
#using scripts\shared\math_shared;
#using scripts\shared\popups_shared;
#using scripts\shared\rank_shared;
#using scripts\shared\scoreevents_shared;
#using scripts\shared\sound_shared;
#using scripts\shared\system_shared;
#using scripts\shared\util_shared;

    	   	                                                                                                                                         	                                	                                                                                                                                                                                                                                                                                                                                                                    	        	     	              	    	   	               	                                              	                                                           	                               	                     	                                                                                                           	                                                                 	                                                              	                                                                                                                                             	                            	                                     	                                       	                                                                                                              	   	                  	       	                                                    	                   	                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                            	                                                                                                 	                                    	                                                                                        	           	                        	                                            	                                             	                                                   	                                                             	                                                         	                                                                    	                                                                                                                                                                                                                                	                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                  	    	         	                                                              	                                                          	                                   	                                   	                                                    	                                       	                                           	     	                                                                                                                                                                                                                                                      	                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                         	                                                               	        	                                                                                                                              	                                                                                                                     	                               	                                                      	                          
                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                         	   	                                                                                                                                                                                                                                  	                                                                                                                                                                                                                                                                                                                                                                                                                                                   

#using scripts\mp\gametypes\_globallogic;
#using scripts\mp\gametypes\_globallogic_audio;
#using scripts\mp\gametypes\_globallogic_defaults;
#using scripts\mp\gametypes\_globallogic_score;
#using scripts\mp\gametypes\_globallogic_utils;
#using scripts\mp\gametypes\_hud_message;
#using scripts\mp\gametypes\_spawning;
#using scripts\mp\gametypes\_spawnlogic;

#using scripts\mp\_challenges;
#using scripts\mp\_util;
#using scripts\mp\teams\_teams;

                                             




/*
	CTF
	
	Level requirements
	------------------
		Allied Spawnpoints:
			classname		mp_sd_spawn_attacker
			Allied players spawn from these. Place at least 16 of these relatively close together.

		Axis Spawnpoints:
			classname		mp_sd_spawn_defender
			Axis players spawn from these. Place at least 16 of these relatively close together.

		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.

		Flag:
			classname				trigger_multiple
			targetname				flagtrigger
			script_gameobjectname	ctf
			script_label				Set to name of flag. This sets the letter shown on the compass in original mode.
			script_team					Set to allies or axis. This is used to set which team a flag is used by.
			This should be a 16x16 unit trigger with an origin brush placed so that it's center lies on the bottom plane of the trigger.
			Must be in the level somewhere. This is the trigger that is used to represent a flag.
			It gets moved to the position of the planted bomb model.
*/

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

/*QUAKED mp_ctf_spawn_allies (0.0 0.75 0.5) (-16 -16 0) (16 16 72)
Allied players spawn away from enemies and near their team at one of these positions.*/

/*QUAKED mp_ctf_spawn_axis_start (1.0 0.0 0.5) (-16 -16 0) (16 16 72)
Axis players spawn away from enemies and near their team at one of these positions at the start of a round.*/

/*QUAKED mp_ctf_spawn_allies_start (0.0 1.0 0.5) (-16 -16 0) (16 16 72)
Allied players spawn away from enemies and near their team at one of these positions at the start of a round.*/




	
#precache( "string", "OBJECTIVES_CTF" );
#precache( "string", "OBJECTIVES_CTF_SCORE" );
#precache( "string", "OBJECTIVES_CTF_HINT" );
#precache( "string", "MP_CTF_OVERTIME_ROUND_1" );
#precache( "string", "MP_CTF_OVERTIME_ROUND_1" );
#precache( "string", "MP_CTF_OVERTIME_ROUND_2_WINNER" );
#precache( "string", "MP_CTF_OVERTIME_ROUND_2_LOSER" );
#precache( "string", "MP_CTF_OVERTIME_ROUND_2_TIE" );
#precache( "string", "MP_CTF_OVERTIME_ROUND_2_TIE" );
#precache( "string", "MP_FLAG_TAKEN_BY");
#precache( "string", "MP_ENEMY_FLAG_TAKEN");
#precache( "string", "MP_FRIENDLY_FLAG_TAKEN");
#precache( "string", "MP_FLAG_CAPTURED_BY");
#precache( "string", "MP_ENEMY_FLAG_CAPTURED_BY");
#precache( "string", "MP_FLAG_RETURNED_BY");
#precache( "string", "MP_FLAG_RETURNED");
#precache( "string", "MP_ENEMY_FLAG_RETURNED");
#precache( "string", "MP_FRIENDLY_FLAG_RETURNED");
#precache( "string", "MP_YOUR_FLAG_RETURNING_IN");
#precache( "string", "MP_ENEMY_FLAG_RETURNING_IN");
#precache( "string", "MP_FRIENDLY_FLAG_DROPPED_BY");
#precache( "string", "MP_FRIENDLY_FLAG_DROPPED");
#precache( "string", "MP_ENEMY_FLAG_DROPPED");
#precache( "string", "MP_SUDDEN_DEATH");
#precache( "string", "MP_CAP_LIMIT_REACHED");
#precache( "string", "MP_CTF_CANT_CAPTURE_FLAG" );
#precache( "triggerstring", "MP_CTF_CANT_CAPTURE_FLAG" );
#precache( "string", "MP_CTF_OVERTIME_WIN" );
#precache( "string", "MP_CTF_OVERTIME_ROUND_1" );
#precache( "string", "MP_CTF_OVERTIME_ROUND_2_WINNER" );
#precache( "string", "MP_CTF_OVERTIME_ROUND_2_LOSER" );
#precache( "string", "MP_CTF_OVERTIME_ROUND_2_TIE" );
#precache( "string", "MPUI_CTF_OVERTIME_FASTEST_CAP_TIME" );
#precache( "string", "MPUI_CTF_OVERTIME_DEFEAT_TIMELIMIT" );
#precache( "string", "MPUI_CTF_OVERTIME_DEFEAT_DID_NOT_DEFEND" );
#precache( "objective", "allies_base" );
#precache( "objective", "axis_base" );
#precache( "objective", "allies_flag" );
#precache( "objective", "axis_flag" );
#precache( "fx", "ui/fx_ctf_flag_base_team" );

function autoexec __init__sytem__() {     system::register("ctf",&__init__,undefined,undefined);    }
	
function __init__()
{
	clientfield::register( "scriptmover", "ctf_flag_away", 1, 1, "int" );	
}

function main()
{
	globallogic::init();
	
	util::registerTimeLimit( 0, 1440 );
	util::registerRoundLimit( 0, 10 );
	util::registerRoundWinLimit( 0, 10 );
	util::registerRoundSwitch( 0, 9 );
	util::registerNumLives( 0, 100 );
	util::registerScoreLimit( 0, 5000 );

	level.scoreRoundWinBased = ( GetGametypeSetting( "cumulativeRoundScores" ) == false );
	level.flagCaptureCondition = GetGametypeSetting( "flagCaptureCondition" );
	level.doubleOvertime = true;
	
	globallogic::registerFriendlyFireDelay( level.gameType, 15, 0, 1440 );

	if ( GetDvarString( "scr_ctf_spawnPointFacingAngle") == "" )
		SetDvar("scr_ctf_spawnPointFacingAngle", "0");

	level.teamBased = true;
	level.overrideTeamScore = true;
	level.onStartGameType =&onStartGameType;
	level.onSpawnPlayer =&onSpawnPlayer;
	level.onPrecacheGameType =&onPrecacheGameType;
	level.onPlayerKilled =&onPlayerKilled;
	level.onRoundSwitch =&onRoundSwitch;
	level.onEndGame =&onEndGame;
	level.onRoundEndGame =&onRoundEndGame;
	level.getTeamKillPenalty =&ctf_getTeamKillPenalty;
	level.getTeamKillScore =&ctf_getTeamKillScore;
	level.setMatchScoreHUDElemForTeam =&setMatchScoreHUDElemForTeam;
	level.shouldPlayOvertimeRound =&shouldPlayOvertimeRound;

	gameobjects::register_allowed_gameobject( level.gameType );
	
	if ( !isdefined( game["ctf_teamscore_cache"] ) )
	{
		game["ctf_teamscore_cache"]["allies"] = 0; // ctf team score cacge is the total flags earned before the score is reset for OT, used by cumulative-round win rule
		game["ctf_teamscore_cache"]["axis"] = 0;
	}
	
	globallogic_audio::set_leader_gametype_dialog ( "startCtf", "hcStartCtf", "objCapture", "objCapture" );

	level.lastDialogTime = getTime();	

	level thread ctf_icon_hide();

	// Sets the scoreboard columns and determines with data is sent across the network
	if ( !SessionModeIsSystemlink() && !SessionModeIsOnlineGame() && IsSplitScreen() )
		// local matches only show the first three columns
		globallogic::setvisiblescoreboardcolumns( "score", "kills", "captures", "returns", "deaths" );
	else
		globallogic::setvisiblescoreboardcolumns( "score", "kills", "deaths", "captures", "returns" );
}

function onPrecacheGameType()
{
	game["flag_dropped_sound"] = "mp_war_objective_lost";
	game["flag_recovered_sound"] = "mp_war_objective_taken";

	game["strings"]["score_limit_reached"] = &"MP_CAP_LIMIT_REACHED";

}

function onStartGameType()
{
	if ( !isdefined( game["switchedsides"] ) )
		game["switchedsides"] = false;

	/#
	setdebugsideswitch(game["switchedsides"]);
	#/
	
	setClientNameMode("auto_change");

	globallogic_score::resetTeamScores();

	util::setObjectiveText( "allies", &"OBJECTIVES_CTF" );
	util::setObjectiveText( "axis", &"OBJECTIVES_CTF" );
	
	if ( level.splitscreen )
	{
		util::setObjectiveScoreText( "allies", &"OBJECTIVES_CTF" );
		util::setObjectiveScoreText( "axis", &"OBJECTIVES_CTF" );
	}
	else
	{
		util::setObjectiveScoreText( "allies", &"OBJECTIVES_CTF_SCORE" );
		util::setObjectiveScoreText( "axis", &"OBJECTIVES_CTF_SCORE" );
	}
	util::setObjectiveHintText( "allies", &"OBJECTIVES_CTF_HINT" );
	util::setObjectiveHintText( "axis", &"OBJECTIVES_CTF_HINT" );
	
	if ( isdefined( game["overtime_round"] ) )
	{
		// This is only necessary when cumulativeRoundScores is on so that the game doesn't immediately end due to scorelimit being set to 1 in OT
		game["ctf_teamscore_cache"]["allies"] += [[level._getTeamScore]]( "allies" );
		game["ctf_teamscore_cache"]["axis"] += [[level._getTeamScore]]( "axis" );

		[[level._setTeamScore]]( "allies", 0 );
		[[level._setTeamScore]]( "axis", 0 );
		
		// One flag wins the round
		util::registerScoreLimit( 1, 1 );
		if ( isdefined( game["ctf_overtime_time_to_beat"] ) )
		{
			util::registerTimeLimit( game["ctf_overtime_time_to_beat"] / 60000, game["ctf_overtime_time_to_beat"] / 60000 );
		}
		
		if ( game["overtime_round"] == 1 )
		{
			util::setObjectiveHintText( "allies", &"MP_CTF_OVERTIME_ROUND_1" );
			util::setObjectiveHintText( "axis", &"MP_CTF_OVERTIME_ROUND_1" );
		}
		else if ( isdefined( game["ctf_overtime_first_winner"] ) )
		{
			util::setObjectiveHintText( game["ctf_overtime_first_winner"], &"MP_CTF_OVERTIME_ROUND_2_WINNER" );
			util::setObjectiveHintText( util::getOtherTeam( game["ctf_overtime_first_winner"] ), &"MP_CTF_OVERTIME_ROUND_2_LOSER" );
		}
		else
		{
			util::setObjectiveHintText( "allies", &"MP_CTF_OVERTIME_ROUND_2_TIE" );
			util::setObjectiveHintText( "axis", &"MP_CTF_OVERTIME_ROUND_2_TIE" );
		}
	}
			
	
	// now that the game objects have been deleted place the influencers
	spawning::create_map_placed_influencers();
	
	level.spawnMins = ( 0, 0, 0 );
	level.spawnMaxs = ( 0, 0, 0 );	
	spawnlogic::place_spawn_points( "mp_ctf_spawn_allies_start" );
	spawnlogic::place_spawn_points( "mp_ctf_spawn_axis_start" );
	spawnlogic::add_spawn_points( "allies", "mp_ctf_spawn_allies" );
	spawnlogic::add_spawn_points( "axis", "mp_ctf_spawn_axis" );

	spawning::add_fallback_spawnpoints( "allies", "mp_tdm_spawn" );
	spawning::add_fallback_spawnpoints( "axis", "mp_tdm_spawn" );

	spawning::updateAllSpawnPoints();
	spawning::update_fallback_spawnpoints();

	level.mapCenter = math::find_box_center( level.spawnMins, level.spawnMaxs );
	setMapCenter( level.mapCenter );

	spawnpoint = spawnlogic::get_random_intermission_point();
	setDemoIntermissionPoint( spawnpoint.origin, spawnpoint.angles );
	
	level.spawn_axis = spawnlogic::get_spawnpoint_array( "mp_ctf_spawn_axis" );
	level.spawn_allies = spawnlogic::get_spawnpoint_array( "mp_ctf_spawn_allies" );

	level.spawn_start = [];
	
	foreach( team in level.teams )
	{
		level.spawn_start[ team ] =  spawnlogic::get_spawnpoint_array("mp_ctf_spawn_" + team + "_start");
	}

		thread updateGametypeDvars();
	
	thread ctf();
}

function shouldPlayOvertimeRound()
{
	// Play 2 rounds of overtime
	if ( isdefined( game["overtime_round"] ) )
	{
		if ( game["overtime_round"] == 1 || !level.gameEnded ) // If we've only played 1 round or we're in the middle of the 2nd keep going
		{
			return true;
		}
		
		return false;
	}
	
	if ( !level.scoreRoundWinBased )
	{
		// Only go to overtime if both teams are tied and it's either the last round or both teams are one away from winning
		if ( ( game["teamScores"]["allies"] == game["teamScores"]["axis"] ) &&
		    ( util::hitRoundLimit() || ( game["teamScores"]["allies"] == level.scoreLimit-1 ) ) )
		{
			return true;
		}
	}
	else
	{
		// Only go to overtime if both teams are one round away from winning
		alliesRoundsWon = util::getRoundsWon( "allies" );
		axisRoundsWon = util::getRoundsWon( "axis" );
		if ( ( level.roundWinLimit > 0 ) && ( axisRoundsWon == level.roundWinLimit-1 ) && ( alliesRoundsWon == level.roundWinLimit-1 ) )
		{
			return true;
		}
		if ( util::hitRoundLimit() && ( alliesRoundsWon == axisRoundsWon ) )
		{
			return true;
		}
	}
	
	return false;
}

function minutesAndSecondsString( milliseconds )
{
	minutes = floor( milliseconds / 60000 );
	milliseconds -= minutes * 60000;
	seconds = floor( milliseconds / 1000 );
	if ( seconds < 10 )
	{
		return minutes+":0"+seconds;
	}
	else
	{
		return minutes+":"+seconds;
	}
}

function setMatchScoreHUDElemForTeam( team )
{
	if ( !isdefined( game["overtime_round"] ) )
	{
		self hud_message::setMatchScoreHUDElemForTeam( team );
	}
	else if ( isdefined( game["ctf_overtime_second_winner"] ) && ( game["ctf_overtime_second_winner"] == team ) )
	{
		self setText( minutesAndSecondsString( game["ctf_overtime_best_time"] ) );
	}
	else if ( isdefined( game["ctf_overtime_first_winner"] ) && ( game["ctf_overtime_first_winner"] == team ) )
	{
		self setText( minutesAndSecondsString( game["ctf_overtime_time_to_beat"] ) );
	}
	else
	{
		self setText( &"" );
	}
}

function onRoundSwitch()
{
	if ( !isdefined( game["switchedsides"] ) )
		game["switchedsides"] = false;
	
	level.halftimeType = "halftime";
	game["switchedsides"] = !game["switchedsides"];
}

function onEndGame( winningTeam )
{
	if ( isdefined( game["overtime_round"] ) )
	{
		if ( game["overtime_round"] == 1 )
		{
			if ( isdefined( winningTeam ) && ( winningTeam != "tie" ) )
			{
				game["ctf_overtime_first_winner"] = winningTeam;
				game["ctf_overtime_time_to_beat"] = globallogic_utils::getTimePassed();
			}
		}
		else
		{
			game["ctf_overtime_second_winner"] = winningTeam;
			game["ctf_overtime_best_time"] = globallogic_utils::getTimePassed();
		}
	}
}

function updateTeamScoreByRoundsWon()
{
	if ( level.scoreRoundWinBased ) 
	{
		foreach( team in level.teams )
		{
			[[level._setTeamScore]]( team, game["roundswon"][team] );
		}
	}
}

function updateTeamScoreByFlagsCaptured()
{
	if ( level.scoreRoundWinBased )
		return;

	foreach( team in level.teams )
	{
		[[level._setTeamScore]]( team, [[level._getTeamScore]]( team ) + game["ctf_teamscore_cache"][team] );
	}
}

function onRoundEndGame( winningTeam )
{
	if ( isdefined( game["overtime_round"] ) )
	{
		if ( isdefined( game["ctf_overtime_first_winner"] ) )
		{
			if ( !isdefined( winningTeam ) || ( winningTeam == "tie" ) )
			{
				winningTeam = game["ctf_overtime_first_winner"];
			}
			
			if ( game["ctf_overtime_first_winner"] == winningTeam )
			{
				level.endVictoryReasonText = &"MPUI_CTF_OVERTIME_FASTEST_CAP_TIME";
				level.endDefeatReasonText = &"MPUI_CTF_OVERTIME_DEFEAT_TIMELIMIT";
			}
			else
			{
				level.endVictoryReasonText = &"MPUI_CTF_OVERTIME_FASTEST_CAP_TIME";
				level.endDefeatReasonText = &"MPUI_CTF_OVERTIME_DEFEAT_DID_NOT_DEFEND";
			}			
		}
		else if ( !isdefined( winningTeam ) || ( winningTeam == "tie" ) )
		{
			if ( level.scoreRoundWinBased )
			{
				updateTeamScoreByRoundsWon();
			}
			else
			{
				updateTeamScoreByFlagsCaptured();
			}
			
			return "tie";
		}
		
		if ( level.scoreRoundWinBased ) 
		{
			foreach( team in level.teams )
			{
				score = game["roundswon"][team];
				if ( team === winningTeam )
				{
					score++;
				}
				[[level._setTeamScore]]( team, score );
			}			
		}
		else
		{
			updateTeamScoreByFlagsCaptured();
		}
		return winningTeam;
	}
	
	if ( level.scoreRoundWinBased ) 
	{
		updateTeamScoreByRoundsWon();
	
		winner = globallogic::determineTeamWinnerByGameStat( "roundswon" );
	}
	else
	{
		winner = globallogic::determineTeamWinnerByTeamScore();
	}
	
	return winner;
}

function onSpawnPlayer(predictedSpawn)
{
	self.isFlagCarrier = false;
	self.flagCarried = undefined;
	self clientfield::set( "ctf_flag_carrier", 0 );	
	
	spawning::onSpawnPlayer(predictedSpawn);
}

function updateGametypeDvars()
{
	level.flagCaptureTime = GetGametypeSetting( "captureTime" );
	level.flagTouchReturnTime = GetGametypeSetting( "defuseTime" );  // using defuseTime for touch return
	level.idleFlagReturnTime = GetGametypeSetting( "idleFlagResetTime" );
	level.flagRespawnTime = GetGametypeSetting( "flagRespawnTime" );
	level.enemyCarrierVisible = GetGametypeSetting( "enemyCarrierVisible" );
	level.roundLimit = GetGametypeSetting( "roundLimit" );
	level.cumulativeRoundScores = GetGametypeSetting( "cumulativeRoundScores" );
	
	level.teamKillPenaltyMultiplier = GetGametypeSetting( "teamKillPenalty" );
	level.teamKillScoreMultiplier = GetGametypeSetting( "teamKillScore" );

	if ( level.flagTouchReturnTime >= 0 && level.flagTouchReturnTime != 63)
	{
		level.touchReturn = true;
	}
	else
	{
		level.touchReturn = false;
	}
}

function createFlag( trigger )
{		
	if ( isdefined( trigger.target ) )
	{
		visuals[0] = getEnt( trigger.target, "targetname" );
	}
	else
	{
		visuals[0] = spawn( "script_model", trigger.origin );
		visuals[0].angles = trigger.angles;
	}

	entityTeam = trigger.script_team;
	// TODO MTEAM - switched sides
	if ( game["switchedsides"] )
		entityTeam = util::getOtherTeam( entityTeam );

	visuals[0] setModel( teams::get_flag_model( entityTeam ) );
	visuals[0] SetTeam( entityTeam );

	flag = gameobjects::create_carry_object( entityTeam, trigger, visuals, (0,0,100), istring(entityTeam+"_flag") );
	flag gameobjects::set_team_use_time( "friendly", level.flagTouchReturnTime );
	flag gameobjects::set_team_use_time( "enemy", level.flagCaptureTime );
	flag gameobjects::allow_carry( "enemy" );
	flag gameobjects::set_visible_team( "any" );
	flag gameobjects::set_visible_carrier_model( teams::get_flag_carry_model( entityTeam ) );
	flag gameobjects::set_2d_icon( "friendly", level.iconDefend2D );
	flag gameobjects::set_3d_icon( "friendly", level.iconDefend3D );
	flag gameobjects::set_2d_icon( "enemy", level.iconCapture2D );
	flag gameobjects::set_3d_icon( "enemy", level.iconCapture3D );

	if ( level.enemyCarrierVisible == 2 )
	{
		flag.objIDPingFriendly = true;
	}
	flag.allowWeapons = true;
	flag.onPickup =&onPickup;
	flag.onPickupFailed =&onPickup;
	flag.onDrop =&onDrop;
	flag.onReset =&onReset;
			
	if ( level.idleFlagReturnTime > 0 )
	{
		flag.autoResetTime = level.idleFlagReturnTime;
	}
	else
	{
		flag.autoResetTime = undefined;
	}		
	
	return flag;
}

function createFlagZone( trigger )
{
	visuals = [];
	
	entityTeam = trigger.script_team;
	// TODO MTEAM - switched sides
	if ( game["switchedsides"] )
		entityTeam = util::getOtherTeam( entityTeam );

	flagZone = gameobjects::create_use_object( entityTeam, trigger, visuals, (0,0,0), istring(entityTeam+"_base") );
	flagZone gameobjects::allow_use( "friendly" );
	flagZone gameobjects::set_use_time( 0 );
	flagZone gameobjects::set_use_text( &"MP_CAPTURING_FLAG" );
	flagZone gameobjects::set_visible_team( "friendly" );

	enemyTeam = util::getOtherTeam( entityTeam );
	flagZone gameobjects::set_key_object( level.teamFlags[enemyTeam] );
	flagZone.onUse =&onCapture;
	
	flag = level.teamFlags[entityTeam];
	flag.flagBase = flagZone;
	flagZone.flag = flag;

	flagZone createFlagSpawnInfluencer( entityTeam );
	
	return flagZone;
}

function createFlagHint( team, origin )
{
	radius = 128;
	height = 64;
	
	trigger = spawn("trigger_radius", origin, 0, radius, height);
	trigger setHintString( &"MP_CTF_CANT_CAPTURE_FLAG" );
	trigger setcursorhint("HINT_NOICON");
	trigger.original_origin = origin;
	
	trigger turn_off();
	
	return trigger;
}

function ctf()
{
	level.flags = [];
	level.teamFlags = [];
	level.flagZones = [];
	level.teamFlagZones = [];
	
	flag_triggers = getEntArray( "ctf_flag_pickup_trig", "targetname" );
	if ( !isdefined( flag_triggers ) || flag_triggers.size != 2)
	{
		/#util::error("Not enough ctf_flag_pickup_trig triggers found in map.  Need two.");#/
		return;
	}

	for ( index = 0; index < flag_triggers.size; index++ )
	{
		trigger = flag_triggers[index];
		
		flag = createFlag( trigger );
		
		team = flag gameobjects::get_owner_team();
		level.flags[level.flags.size] = flag;
		level.teamFlags[team] = flag;
		
	}

	flag_zones = getEntArray( "ctf_flag_zone_trig", "targetname" );
	if ( !isdefined( flag_zones ) || flag_zones.size != 2)
	{
		/#util::error("Not enough ctf_flag_zone_trig triggers found in map.  Need two.");#/
		return;
	}

	for ( index = 0; index < flag_zones.size; index++ )
	{
		trigger = flag_zones[index];
		
		flagZone = createFlagZone( trigger );

		team = flagZone gameobjects::get_owner_team();
		level.flagZones[level.flagZones.size] = flagZone;		
		level.teamFlagZones[team] = flagZone;		

		level.flagHints[team] = createFlagHint( team, trigger.origin );		

		facing_angle = GetDvarint( "scr_ctf_spawnPointFacingAngle");
		
		// the opposite team will want to face this point
		setspawnpointsbaseweight( util::getOtherTeamsMask(team), trigger.origin, facing_angle, level.spawnsystem.objective_facing_bonus);
	}
	
	// once all the flags have been registered with the game,
	// give each spawn point a baseline score for each objective flag,
	// based on whether or not player will be looking in the direction of that flag upon spawning
	//generate_baseline_spawn_point_scores();

	createReturnMessageElems();
}

//Runs each round, as function as restarted at the start of every round.
//Hides the flag status icons and the 2D and 3D icons from the player's view
function ctf_icon_hide()
{
	level waittill ( "game_ended" );

	level.teamFlags["allies"] gameobjects::set_visible_team( "none" );
	level.teamFlags["axis"] gameobjects::set_visible_team( "none" );
}

function removeInfluencers()
{
	if ( isdefined( self.spawn_influencer_enemy_carrier ) )
	{
		// self == player
		self spawning::remove_influencer( self.spawn_influencer_enemy_carrier );
		self.spawn_influencer_enemy_carrier = undefined;
	}
	if ( isdefined( self.spawn_influencer_friendly_carrier ) )
	{
		// self == player
		self spawning::remove_influencer( self.spawn_influencer_friendly_carrier );
		self.spawn_influencer_friendly_carrier = undefined;
	}
	if ( isdefined( self.spawn_influencer_dropped ) )
	{
		// self == flag
		self.trigger spawning::remove_influencer( self.spawn_influencer_dropped );
		self.spawn_influencer_dropped = undefined;
	}
}

function onDrop( player )
{
	origin = (0,0,0);
	if ( isdefined( player ) )
	{
		player clientfield::set( "ctf_flag_carrier", 0 );	
		origin = player.origin;
	}

	team = self gameobjects::get_owner_team();
	otherTeam = util::getOtherTeam( team );
	
	bbPrint( "mpobjective", "gametime %d objtype %s team %s playerx %d playery %d playerz %d", gettime(), "ctf_flagdropped", team, origin );

	self.visuals[0] clientfield::set( "ctf_flag_away", 1 );
	
	if ( level.touchReturn )
	{
		self gameobjects::allow_carry( "any" );
		level.flagHints[otherTeam] turn_off();
	}
		
	if ( isdefined( player ) )
	{
		util::printAndSoundOnEveryone( team, undefined, &"", undefined, "mp_war_objective_lost" );	

		level thread popups::DisplayTeamMessageToTeam( &"MP_FRIENDLY_FLAG_DROPPED", player, team );
		level thread popups::DisplayTeamMessageToTeam( &"MP_ENEMY_FLAG_DROPPED", player, otherTeam );
	}
	else
	{
		util::printAndSoundOnEveryone( team, undefined, &"", undefined, "mp_war_objective_lost" );		
	}
	
	globallogic_audio::leader_dialog( "ctfFriendlyFlagDropped", team, undefined, "ctf_flag" );
	globallogic_audio::leader_dialog( "ctfEnemyFlagDropped", otherTeam, undefined, "ctf_flag_enemy" );
	/#
	if ( isdefined( player ) )
	 	print( team + " flag dropped" );
	else
	 	print( team + " flag dropped" );
	#/

	if ( isdefined( player ) )
	{
		player playLocalSound("mpl_flag_drop_plr");
	}


	globallogic_audio::play_2d_on_team( "mpl_flagdrop_sting_friend", otherTeam );
	globallogic_audio::play_2d_on_team( "mpl_flagdrop_sting_enemy", team );

	if ( level.touchReturn )
	{
		self gameobjects::set_3d_icon( "friendly", level.iconReturn3D );
		self gameobjects::set_2d_icon( "friendly", level.iconReturn2D );
	}
	else
	{
		self gameobjects::set_3d_icon( "friendly", level.iconDropped3D );
		self gameobjects::set_2d_icon( "friendly", level.iconDropped2D );
	}	
	self gameobjects::set_visible_team( "any" );
	self gameobjects::set_3d_icon( "enemy", level.iconCapture3D );
	self gameobjects::set_2d_icon( "enemy", level.iconCapture2D );

	thread sound::play_on_players( game["flag_dropped_sound"], game["attackers"] );

	self thread returnFlagAfterTimeMsg( level.idleFlagReturnTime );	
	
	// remove carrier influencers
	if ( isdefined( player ) )
	{
		player removeInfluencers();
	}
		
	// create new influencers on the flag
	ss = level.spawnsystem;
	player_team_mask = util::getTeamMask( otherTeam );	// this is the player that has the flag's team
	enemy_team_mask = util::getTeamMask( team );	// and his enemies

	if ( isdefined( player ) )
		flag_origin = player.origin;
	else
		flag_origin = self.curorigin;
	
	self.spawn_influencer_dropped = self.trigger spawning::create_entity_influencer( "ctf_flag_dropped", player_team_mask|enemy_team_mask );
	SetInfluencerTimeOut( self.spawn_influencer_dropped, level.idleFlagReturnTime );

}


function onPickup( player )
{
	carrierKilledBy = self.carrierKilledBy;
	self.carrierKilledBy = undefined;
	if ( isdefined( self.spawn_influencer_dropped ) )
	{
		self.trigger spawning::remove_influencer( self.spawn_influencer_dropped );
		self.spawn_influencer_dropped = undefined;
	}

	player AddPlayerStatWithGameType( "PICKUPS", 1 );
	
	//scoreevents::processScoreEvent( "flag_grab", player );
	
	if ( level.touchReturn )
	{
		self gameobjects::allow_carry( "enemy" );
	}

	// always clear influencers. we'll create new ones if it's been picked up by an enemy.
	self removeInfluencers();

	team = self gameobjects::get_owner_team();
	otherTeam = util::getOtherTeam( team );

	self clearReturnFlagHudElems();		

	if ( isdefined( player ) && player.pers["team"] == team )
	{	
		self notify("picked_up");

		util::printAndSoundOnEveryone( team, undefined, &"", undefined, "mp_obj_returned" );
	
		if( isdefined(player.pers["returns"]) )
		{
			player.pers["returns"]++;
			player.returns = player.pers["returns"];
		}
		if ( isdefined(carrierKilledBy) && carrierKilledBy == player ) 
		{
			scoreevents::processScoreEvent( "flag_carrier_kill_return_close", player );
		}
		else if (distancesquared(self.trigger.baseOrigin, player.origin) > 300*300) 
		{
			scoreevents::processScoreEvent( "flag_return", player );
		}
		demo::bookmark( "event", gettime(), player );

		player AddPlayerStatWithGameType( "RETURNS", 1 );

		level thread popups::DisplayTeamMessageToTeam( &"MP_FRIENDLY_FLAG_RETURNED", player, team );
		level thread popups::DisplayTeamMessageToTeam( &"MP_ENEMY_FLAG_RETURNED", player, otherTeam );

		self.visuals[0] clientfield::set( "ctf_flag_away", 0 );
		self gameobjects::set_flags( 0 );
		
		bbPrint( "mpobjective", "gametime %d objtype %s team %s playerx %d playery %d playerz %d", gettime(), "ctf_flagreturn", team, player.origin );
		player RecordGameEvent("return");	
		
		// want to return the flag here
		self returnFlag();
		/#
		if ( isdefined( player ) )
		 	print( team + " flag returned" );
		 else
		 	print( team + " flag returned" );
		#/
		 
		return;
	}
	else
	{
		bbPrint( "mpobjective", "gametime %d objtype %s team %s playerx %d playery %d playerz %d", gettime(), "ctf_flagpickup", team, player.origin );
		player RecordGameEvent("pickup");

		scoreevents::processScoreEvent( "flag_grab", player );
		demo::bookmark( "event", gettime(), player );
	
		util::printAndSoundOnEveryone( otherteam, undefined, &"", undefined, "mp_obj_taken", "mp_enemy_obj_taken" );

		level thread popups::DisplayTeamMessageToTeam( &"MP_FRIENDLY_FLAG_TAKEN", player, team );
		level thread popups::DisplayTeamMessageToTeam( &"MP_ENEMY_FLAG_TAKEN", player, otherTeam );

		globallogic_audio::leader_dialog( "ctfFriendlyFlagTaken", team, undefined, "ctf_flag" );
		globallogic_audio::leader_dialog( "ctfEnemyFlagTaken", otherTeam, undefined, "ctf_flag_enemy" );
	
		player.isFlagCarrier = true;
		player.flagCarried = self;
		player playLocalSound("mpl_flag_pickup_plr");
		player clientfield::set( "ctf_flag_carrier", 1 );	
		self gameobjects::set_flags( 1 );
	
		globallogic_audio::play_2d_on_team( "mpl_flagget_sting_friend", otherTeam );
		globallogic_audio::play_2d_on_team( "mpl_flagget_sting_enemy", team );
		
		if ( level.enemyCarrierVisible )
		{
			self gameobjects::set_visible_team( "any" );
		}
		else
		{
			self gameobjects::set_visible_team( "enemy" );
		}

		self gameobjects::set_2d_icon( "friendly", level.iconKill2D );
		self gameobjects::set_3d_icon( "friendly", level.iconKill3D );
		self gameobjects::set_2d_icon( "enemy", level.iconEscort2D );
		self gameobjects::set_3d_icon( "enemy", level.iconEscort3D );

		player thread claim_trigger( level.flagHints[otherTeam] );
		
		update_hints();
		
		
		//Reset flashback here
		player resetflashback();

		/#print( team + " flag taken" );#/
		
		ss = level.spawnsystem;
		player_team_mask = util::getTeamMask( otherTeam );	// this is the player that has the flag's team
		enemy_team_mask = util::getTeamMask( team );	// and his enemies
		
		player.spawn_influencer_friendly_carrier = player spawning::create_entity_masked_friendly_influencer( "ctf_carrier_friendly", player_team_mask );
		player.spawn_influencer_enemy_carrier = player spawning::create_entity_masked_enemy_influencer( "ctf_carrier_enemy", enemy_team_mask );
	}
	
}
function OnPickupMusicState ( player )
{
	self endon( "disconnect" );
	self endon( "death" );
	
	// wait 6 seconds and see if the player still has the flag.
	wait (6);
	if (player.isFlagCarrier)
	{
		//Was the SUSPENSE state changes to ACTION - removed state CDC - 6/19/12
	}
}	
function isHome()
{
	if ( isdefined( self.carrier ) )
		return false;

	if ( self.curOrigin != self.trigger.baseOrigin )
		return false;
		
	return true;
}

function returnFlag()
{
	team = self gameobjects::get_owner_team();
	otherTeam = util::getOtherTeam(team);
	
	globallogic_audio::play_2d_on_team( "mpl_flagreturn_sting", team );
	globallogic_audio::play_2d_on_team( "mpl_flagreturn_sting", otherTeam );
	
	level.teamFlagZones[otherTeam] gameobjects::allow_use( "friendly" );
	level.teamFlagZones[otherTeam] gameobjects::set_visible_team( "friendly" );

	update_hints();
	
	if ( level.touchReturn )
	{
		self gameobjects::allow_carry( "enemy" );
	}
	self gameobjects::return_home();
	self gameobjects::set_visible_team( "any" );
	//TODO: Add 2D Icons
	self gameobjects::set_3d_icon( "friendly", level.iconDefend3D );
	self gameobjects::set_2d_icon( "friendly", level.iconDefend2D );
	self gameobjects::set_3d_icon( "enemy", level.iconCapture3D );	
	self gameobjects::set_2d_icon( "enemy", level.iconCapture2D );
	
	globallogic_audio::leader_dialog( "ctfFriendlyFlagReturned", team, undefined, "ctf_flag" );
	globallogic_audio::leader_dialog( "ctfEnemyFlagReturned", otherTeam, undefined, "ctf_flag_enemy" );
}


function onCapture( player )
{
	team = player.pers["team"];
	enemyTeam = util::getOtherTeam( team );
	time = gettime();
	
	playerTeamsFlag = level.teamFlags[team];
	
	if ( (level.flagCaptureCondition == 1) && playerTeamsFlag gameobjects::is_object_away_from_home() )
	{
		return;
	}
	
	if ( !isdefined( player.carryObject ) )
	{
		return; // the carryObject can be undefined if the player dies a frame before (and possibly other edges cases)
	}

	util::printAndSoundOnEveryone( team, undefined, &"", undefined, "mp_obj_captured", "mp_enemy_obj_captured" );
	bbPrint( "mpobjective", "gametime %d objtype %s team %s playerx %d playery %d playerz %d", time, "ctf_flagcapture", enemyTeam, player.origin ); // flag BELONGS to enemyTeam

	game["challenge"][team]["capturedFlag"] = true;
	
	if( isdefined(player.pers["captures"]) )
	{
		player.pers["captures"]++;
		player.captures = player.pers["captures"];
	}

	demo::bookmark( "event", gettime(), player );
	player AddPlayerStatWithGameType( "CAPTURES", 1 );

	level thread popups::DisplayTeamMessageToTeam( &"MP_ENEMY_FLAG_CAPTURED", player, team );
	level thread popups::DisplayTeamMessageToTeam( &"MP_FRIENDLY_FLAG_CAPTURED", player, enemyTeam );

	globallogic_audio::play_2d_on_team( "mpl_flagcapture_sting_enemy", enemyTeam );
	globallogic_audio::play_2d_on_team( "mpl_flagcapture_sting_friend", team );
	
	player giveFlagCaptureXP( player );

	/#print( enemyTeam + " flag captured" );#/

	flag = player.carryObject;

	player challenges::capturedObjective( time, flag.trigger );
	
	flag.dontAnnounceReturn = true;
	flag gameobjects::return_home();
	flag.dontAnnounceReturn = undefined;
	
	otherTeam = util::getOtherTeam(team);
		level.teamFlags[otherTeam] gameobjects::allow_carry( "enemy" );
		level.teamFlags[otherTeam] gameobjects::set_visible_team( "any" );
		level.teamFlags[otherTeam] gameobjects::return_home();
		level.teamFlagZones[otherTeam] gameobjects::allow_use( "friendly" );
	
	player.isFlagCarrier = false;
	player.flagCarried = undefined;
	player clientfield::set( "ctf_flag_carrier", 0 );	

	// execution will stop on this line on last flag cap of a level
	globallogic_score::giveTeamScoreForObjective( team, 1 );
	
	// NOTE: team is the team of the capturing player, unlike in other flag events
	globallogic_audio::leader_dialog( "ctfEnemyFlagCaptured", team, undefined, "ctf_flag_enemy" );
	globallogic_audio::leader_dialog( "ctfFriendlyFlagCaptured", enemyTeam, undefined, "ctf_flag" );

	flag removeInfluencers();
	player removeInfluencers();
}

function giveFlagCaptureXP( player )
{
	scoreevents::processScoreEvent( "flag_capture", player );
	player RecordGameEvent("capture");
}

function onReset()
{	
	update_hints();

	team = self gameobjects::get_owner_team();
	
	self gameobjects::set_3d_icon( "friendly", level.iconDefend3D );
	self gameobjects::set_2d_icon( "friendly", level.iconDefend2D );
	self gameobjects::set_3d_icon( "enemy", level.iconCapture3D );
	self gameobjects::set_2d_icon( "enemy", level.iconCapture2D );
	
	if ( level.touchReturn )
	{
		self gameobjects::allow_carry( "enemy" );
	}

	level.teamFlagZones[team] gameobjects::set_visible_team( "friendly" );
	level.teamFlagZones[team] gameobjects::allow_use( "friendly" );
	
	self.visuals[0] clientfield::set( "ctf_flag_away", 0 );
	self gameobjects::set_flags( 0 );
	self clearReturnFlagHudElems();
	self removeInfluencers();
}

function getOtherFlag( flag )
{
	if ( flag == level.flags[0] )
	 	return level.flags[1];
	 	
	return level.flags[0];
}

function onPlayerKilled( eInflictor, attacker, iDamage, sMeansOfDeath, weapon, vDir, sHitLoc, psOffsetTime, deathAnimDuration )
{
	if (  isdefined( attacker ) && isplayer( attacker ) )
	{
		for ( index = 0; index < level.flags.size; index++ )
		{
			flagTeam = "invalidTeam";
			inFlagRadius = false;
			defendedFlag = false;
			offendedFlag = false;

			flagCarrier = level.flags[index].carrier;
			if ( isdefined( flagCarrier ) )
			{
				flagOrigin = level.flags[index].carrier.origin;
				isCarried = true;

				if ( isPlayer( attacker ) && ( attacker.pers["team"] != self.pers["team"] ) ) 
				{
					if ( isdefined( level.flags[index].carrier.attackerData ) ) 
					{	
						if ( level.flags[index].carrier != attacker ) 
						{
							if ( isdefined( level.flags[index].carrier.attackerData[self.clientid] ) ) 
							{
								scoreevents::processScoreEvent( "rescue_flag_carrier", attacker, undefined, weapon );
							}
						}
					}
				}
			}
			else 
			{
				flagOrigin = level.flags[index].curorigin;
				isCarried = false;
			}
				
			dist = Distance2dSquared(self.origin, flagOrigin);
			if ( dist < level.defaultOffenseRadiusSQ )
			{
				inFlagRadius = true;
				if ( level.flags[index].ownerteam == attacker.pers["team"] )
					defendedFlag = true;
				else
					offendedFlag = true;					
			}
			dist = Distance2dSquared(attacker.origin, flagOrigin);
			if ( dist < level.defaultOffenseRadiusSQ )
			{
				inFlagRadius = true;
				if ( level.flags[index].ownerteam == attacker.pers["team"] )
					defendedFlag = true;
				else
					offendedFlag = true;					
			}
			
			
			if ( inFlagRadius && isPlayer( attacker ) && attacker.pers["team"] != self.pers["team"] )
			{	
				if ( defendedFlag )
				{
					if ( isdefined( self.isFlagCarrier ) && self.isFlagCarrier )
					{
						scoreevents::processScoreEvent( "kill_flag_carrier", attacker, undefined, weapon );
						attacker AddPlayerStat( "kill_carrier", 1 );
					}
					else
					{
						scoreevents::processScoreEvent( "killed_attacker", attacker, undefined, weapon );
					}
	
					self RecordKillModifier("assaulting");
				}
				if ( offendedFlag )
				{
					if ( isCarried == true ) 
					{
						if ( isdefined ( flagCarrier ) && attacker == flagCarrier ) 
						{
							scoreevents::processScoreEvent( "killed_enemy_while_carrying_flag", attacker, undefined, weapon );
						}
						else
						{
							scoreevents::processScoreEvent( "defend_flag_carrier", attacker, undefined, weapon );
							attacker addplayerstat( "defend_carrier", 1 );
						}
					}
					else
					{
						scoreevents::processScoreEvent( "killed_defender", attacker, undefined, weapon );
					}
					self RecordKillModifier("defending");
				}
			}
		}
		
		victim = self;
		
		foreach( flag_zone in level.flagZones )
		{
			if ( isdefined( attacker.team ) && ( attacker != victim ) && isdefined( victim.team ) )
			{
				dist_to_zone_origin = Distance2dSquared( attacker.origin, flag_zone.origin );
				victim_dist_to_zone_origin = Distance2dSquared( victim.origin, flag_zone.origin );
				if ( victim_dist_to_zone_origin < level.defaultOffenseRadiusSQ || dist_to_zone_origin < level.defaultOffenseRadiusSQ )
				{
					if ( victim.team == flag_zone.team )
					{
						attacker thread challenges::killedBaseDefender( flag_zone.trigger );
					}
					else				
					{
						attacker thread challenges::killedBaseOffender( flag_zone.trigger, weapon );
					}
				}
			}			
		}
	}

	if ( !isdefined( self.isFlagCarrier ) || !self.isFlagCarrier )
		return;

	if ( isdefined( attacker ) && isPlayer( attacker ) && attacker.pers["team"] != self.pers["team"] )
	{
		if ( isdefined ( self.flagCarried ) ) 
		{
			for ( index = 0; index < level.flags.size; index++ )
			{
				currentFlag = level.flags[index];
				if ( currentFlag.ownerteam == self.team ) 
				{
					if ( currentFlag.curOrigin == currentFlag.trigger.baseOrigin )
					{
						dist = Distance2dSquared(self.origin, currentFlag.curOrigin );
						if ( dist < level.defaultOffenseRadiusSQ )
						{	
							self.flagCarried.carrierKilledBy = attacker;
							break;
						}
					}
				}
			}
		}
		
		attacker RecordGameEvent("kill_carrier");	
		self RecordKillModifier("carrying");
	}
}

function createReturnMessageElems()
{
	level.ReturnMessageElems = [];

	level.ReturnMessageElems["allies"]["axis"] = hud::createServerTimer( "objective", 1.4, "allies" );
	level.ReturnMessageElems["allies"]["axis"] hud::setPoint( "TOPRIGHT", "TOPRIGHT", 0, 0 );
	level.ReturnMessageElems["allies"]["axis"].label = &"MP_ENEMY_FLAG_RETURNING_IN";
	level.ReturnMessageElems["allies"]["axis"].alpha = 0;
	level.ReturnMessageElems["allies"]["axis"].archived = false;
	level.ReturnMessageElems["allies"]["allies"] = hud::createServerTimer( "objective", 1.4, "allies" );
	level.ReturnMessageElems["allies"]["allies"] hud::setPoint( "TOPRIGHT", "TOPRIGHT", 0, 20 );
	level.ReturnMessageElems["allies"]["allies"].label = &"MP_YOUR_FLAG_RETURNING_IN";
	level.ReturnMessageElems["allies"]["allies"].alpha = 0;
	level.ReturnMessageElems["allies"]["allies"].archived = false;

	level.ReturnMessageElems["axis"]["allies"] = hud::createServerTimer( "objective", 1.4, "axis" );
	level.ReturnMessageElems["axis"]["allies"] hud::setPoint( "TOPRIGHT", "TOPRIGHT", 0, 0 );
	level.ReturnMessageElems["axis"]["allies"].label = &"MP_ENEMY_FLAG_RETURNING_IN";
	level.ReturnMessageElems["axis"]["allies"].alpha = 0;
	level.ReturnMessageElems["axis"]["allies"].archived = false;
	level.ReturnMessageElems["axis"]["axis"] = hud::createServerTimer( "objective", 1.4, "axis" );
	level.ReturnMessageElems["axis"]["axis"] hud::setPoint( "TOPRIGHT", "TOPRIGHT", 0, 20 );
	level.ReturnMessageElems["axis"]["axis"].label = &"MP_YOUR_FLAG_RETURNING_IN";
	level.ReturnMessageElems["axis"]["axis"].alpha = 0;
	level.ReturnMessageElems["axis"]["axis"].archived = false;
}

function returnFlagAfterTimeMsg( time )
{
	if ( level.touchReturn || level.idleFlagReturnTime == 0 )
		return;

	self notify("returnFlagAfterTimeMsg");
	self endon("returnFlagAfterTimeMsg");
	
	result = returnFlagHudElems( time );
	
	self removeInfluencers();
	self clearReturnFlagHudElems();
	
	if ( !isdefined( result ) ) // returnFlagHudElems hit an endon
		return;
		
//	self returnFlag();
}

function returnFlagHudElems( time )
{
	self endon("picked_up");
	level endon("game_ended");
	
	ownerteam = self gameobjects::get_owner_team();
	
	assert( !level.ReturnMessageElems["axis"][ownerteam].alpha );
	level.ReturnMessageElems["axis"][ownerteam].alpha = 1;
	level.ReturnMessageElems["axis"][ownerteam] setTimer( time );
	
	assert( !level.ReturnMessageElems["allies"][ownerteam].alpha );
	level.ReturnMessageElems["allies"][ownerteam].alpha = 1;
	level.ReturnMessageElems["allies"][ownerteam] setTimer( time );
	
	if( time <= 0 )
		return false;
	else
		wait time;
	
	return true;
}

function clearReturnFlagHudElems()
{
	ownerteam = self gameobjects::get_owner_team();
	
	level.ReturnMessageElems["allies"][ownerteam].alpha = 0;
	level.ReturnMessageElems["axis"][ownerteam].alpha = 0;
}

function turn_on()
{
	if ( level.hardcoreMode )
		return;
		
	self.origin = self.original_origin;
}

function turn_off()
{
	self.origin = ( self.original_origin[0], self.original_origin[1], self.original_origin[2] - 10000);
}

function update_hints()
{
	allied_flag = level.teamFlags["allies"];
	axis_flag = level.teamFlags["axis"];
			
	if ( !level.touchReturn )
		return;

	if ( isdefined(allied_flag.carrier) && axis_flag gameobjects::is_object_away_from_home() )
	{
		level.flagHints["axis"] turn_on();		
	}
	else
	{
		level.flagHints["axis"] turn_off();
	}		
	
	if ( isdefined(axis_flag.carrier) && allied_flag gameobjects::is_object_away_from_home() )
	{
		level.flagHints["allies"] turn_on();		
	}
	else
	{
		level.flagHints["allies"] turn_off();
	}		
}

function claim_trigger( trigger )
{
	self endon("disconnect");
	self ClientClaimTrigger( trigger );
	
	self waittill("drop_object");
	self ClientReleaseTrigger( trigger );
}

function createFlagSpawnInfluencer( entityTeam )
{
	otherteam = util::getOtherTeam(entityTeam);
	team_mask = util::getTeamMask( entityTeam );
	other_team_mask = util::getTeamMask( otherteam );
	
	self.spawn_influencer_friendly = self spawning::create_influencer( "ctf_base_friendly", self.trigger.origin, team_mask );
	self.spawn_influencer_enemy = self spawning::create_influencer( "ctf_base_friendly", self.trigger.origin, other_team_mask );
}

function ctf_getTeamKillPenalty( eInflictor, attacker, sMeansOfDeath, weapon )
{
	teamkill_penalty = globallogic_defaults::default_getTeamKillPenalty( eInflictor, attacker, sMeansOfDeath, weapon );

	if ( ( isdefined( self.isFlagCarrier ) && self.isFlagCarrier ) )
	{
		teamkill_penalty = teamkill_penalty * level.teamKillPenaltyMultiplier;
	}
	
	return teamkill_penalty;
}

function ctf_getTeamKillScore( eInflictor, attacker, sMeansOfDeath, weapon )
{
	teamkill_score = rank::getScoreInfoValue( "kill" );
	
	if ( ( isdefined( self.isFlagCarrier ) && self.isFlagCarrier ) )
	{
		teamkill_score = teamkill_score * level.teamKillScoreMultiplier;
	}
	
	return int(teamkill_score);
}