#include maps\mp\_utility;
#include maps\mp\gametypes\_hud_util;
#include common_scripts\utility;
/*
	Confirmed Kill
	Objective: 	Score points for your team by eliminating players on the opposing team.
				Score bonus points for picking up dogtags from downed enemies.
	Map ends:	When one team reaches the score limit, or time limit is reached
	Respawning:	No wait / Near teammates

	Level requirementss
	------------------
		Spawnpoints:
			classname		mp_tdm_spawn
			All players spawn from these. The spawnpoint chosen is dependent on the current locations of teammates and enemies
			at the time of spawn. Players generally spawn behind their teammates relative to the direction of enemies.

		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.
*/


main()
{
	if(getdvar("mapname") == "mp_background")
		return;
	
	maps\mp\gametypes\_globallogic::init();
	maps\mp\gametypes\_callbacksetup::SetupCallbacks();
	maps\mp\gametypes\_globallogic::SetupCallbacks();

	if ( isUsingMatchRulesData() )
	{
		level.initializeMatchRules = ::initializeMatchRules;
		[[level.initializeMatchRules]]();
		level thread reInitializeMatchRulesOnMigration();			
	}
	else
	{
		registerRoundSwitchDvar( level.gameType, 0, 0, 9 );
		registerTimeLimitDvar( level.gameType, 10 );
		registerScoreLimitDvar( level.gameType, 65 );
		registerRoundLimitDvar( level.gameType, 1 );
		registerWinLimitDvar( level.gameType, 1 );
		registerNumLivesDvar( level.gameType, 0 );
		registerHalfTimeDvar( level.gameType, 0 );
		
		level.matchRules_damageMultiplier = 0;
		level.matchRules_vampirism = 0;	
	}

	level.teamBased = true;
	level.onStartGameType = ::onStartGameType;
	level.getSpawnPoint = ::getSpawnPoint;
	level.onNormalDeath = ::onNormalDeath;
	
	if ( level.matchRules_damageMultiplier || level.matchRules_vampirism )
		level.modifyPlayerDamage = maps\mp\gametypes\_damage::gamemodeModifyPlayerDamage;

	game["dialog"]["gametype"] = "kc_intro";
	
	if ( getDvarInt( "g_hardcore" ) )
		game["dialog"]["gametype"] = "hc_" + game["dialog"]["gametype"];
	
	game["dialog"]["kill_confirmed"] = "kc_killconfirmed";
	game["dialog"]["kill_denied"] = "kc_killdenied";
	game["dialog"]["kill_lost"] = "kc_killlost";
	
	game["dialog"]["defense_obj"] = "kc_start";
	game["dialog"]["offense_obj"] = "kc_start";
	
	level.conf_fx["vanish"] = loadFx( "vfx/unique/dogtag_vanish" );
}


initializeMatchRules()
{
	//	set common values
	setCommonRulesFromMatchRulesData();
	
	//	set everything else (private match options, default .cfg file values, and what normally is registered in the 'else' below)
	SetDynamicDvar( "scr_conf_roundswitch", 0 );
	registerRoundSwitchDvar( "conf", 0, 0, 9 );
	SetDynamicDvar( "scr_conf_roundlimit", 1 );
	registerRoundLimitDvar( "conf", 1 );		
	SetDynamicDvar( "scr_conf_winlimit", 1 );
	registerWinLimitDvar( "conf", 1 );			
	SetDynamicDvar( "scr_conf_halftime", 0 );
	registerHalfTimeDvar( "conf", 0 );	
}


onStartGameType()
{
	setClientNameMode("auto_change");

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

	if ( game["switchedsides"] )
	{
		oldAttackers = game["attackers"];
		oldDefenders = game["defenders"];
		game["attackers"] = oldDefenders;
		game["defenders"] = oldAttackers;
	}

	setObjectiveText( "allies", &"OBJECTIVES_CONF" );
	setObjectiveText( "axis", &"OBJECTIVES_CONF" );
	
	if ( level.splitscreen )
	{
		setObjectiveScoreText( "allies", &"OBJECTIVES_CONF" );
		setObjectiveScoreText( "axis", &"OBJECTIVES_CONF" );
	}
	else
	{
		setObjectiveScoreText( "allies", &"OBJECTIVES_CONF_SCORE" );
		setObjectiveScoreText( "axis", &"OBJECTIVES_CONF_SCORE" );
	}
	setObjectiveHintText( "allies", &"OBJECTIVES_CONF_HINT" );
	setObjectiveHintText( "axis", &"OBJECTIVES_CONF_HINT" );

	initSpawns();
	
	level.dogtags = [];
	
	allowed[0] = level.gameType;
	
	maps\mp\gametypes\_gameobjects::main(allowed);	
}

initSpawns()
{
	level.spawnMins = ( 0, 0, 0 );
	level.spawnMaxs = ( 0, 0, 0 );	
	maps\mp\gametypes\_spawnlogic::addStartSpawnPoints( "mp_tdm_spawn_allies_start" );
	maps\mp\gametypes\_spawnlogic::addStartSpawnPoints( "mp_tdm_spawn_axis_start" );
	maps\mp\gametypes\_spawnlogic::addSpawnPoints( "allies", "mp_tdm_spawn" );
	maps\mp\gametypes\_spawnlogic::addSpawnPoints( "axis", "mp_tdm_spawn" );
	
	level.mapCenter = maps\mp\gametypes\_spawnlogic::findBoxCenter( level.spawnMins, level.spawnMaxs );
	setMapCenter( level.mapCenter );	
}


getSpawnPoint()
{
	spawnteam = self.pers["team"];
	if ( game["switchedsides"] )
		spawnteam = getOtherTeam( spawnteam );

	if ( level.useStartSpawns && level.inGracePeriod )
	{
		spawnPoints = maps\mp\gametypes\_spawnlogic::getSpawnpointArray( "mp_tdm_spawn_" + spawnteam + "_start" );
		spawnPoint = maps\mp\gametypes\_spawnlogic::getSpawnpoint_startSpawn( spawnPoints );
	}
	else
	{
		spawnPoints = maps\mp\gametypes\_spawnlogic::getTeamSpawnPoints( spawnteam );
		spawnPoint = maps\mp\gametypes\_spawnscoring::getSpawnpoint_awayFromEnemies( spawnPoints );
	}
	
	self maps\mp\gametypes\_spawnlogic::recon_set_spawnpoint( spawnpoint );
	
	return spawnPoint;
}


onNormalDeath( victim, attacker, lifeId )
{
	level thread spawnDogTags( victim, attacker );
	
	if ( game["state"] == "postgame" && game["teamScores"][attacker.team] > game["teamScores"][level.otherTeam[attacker.team]] )
		attacker.finalKill = true;
}


spawnDogTags( victim, attacker )
{
	
	victim_pers_team = victim.pers["team"];
	if ( isDefined( level.dogtags[victim.guid] ) )
	{
		PlayFx( level.conf_fx["vanish"], level.dogtags[victim.guid].curOrigin );
		level.dogtags[victim.guid] notify( "reset" );		
	}
	else
	{
		visuals[0] = spawn( "script_model", (0,0,0) );
		visuals[0] setModel( "prop_dogtags_future_enemy_animated" );
		visuals[1] = spawn( "script_model", (0,0,0) );
		visuals[1] setModel( "prop_dogtags_future_friend_animated" );
		
		trigger = spawn( "trigger_radius", (0,0,0), 0, 32, 32 );
		
		level.dogtags[victim.guid] = maps\mp\gametypes\_gameobjects::createUseObject( "any", trigger, visuals, (0,0,16) );
		
		// remove team based compass icons
		_objective_delete( level.dogtags[victim.guid].objIDAllies );
		_objective_delete( level.dogtags[victim.guid].objIDAxis );
		_objective_delete( level.dogtags[victim.guid].objIDMLGSpectator );

		// remove team based head icons, tags do not have head icons 		
		maps\mp\gametypes\_objpoints::deleteObjPoint( level.dogtags[victim.guid].objPoints["allies"] );
		maps\mp\gametypes\_objpoints::deleteObjPoint( level.dogtags[victim.guid].objPoints["axis"] );
		maps\mp\gametypes\_objpoints::deleteObjPoint( level.dogtags[victim.guid].objPoints["mlg"] );		
		
		level.dogtags[victim.guid] maps\mp\gametypes\_gameobjects::setUseTime( 0 );
		level.dogtags[victim.guid].onUse = ::onUse;
		level.dogtags[victim.guid].victim = victim;
		level.dogtags[victim.guid].victimTeam = victim_pers_team;
		
		level.dogtags[victim.guid].objId = maps\mp\gametypes\_gameobjects::getNextObjID();	
		objective_add( level.dogtags[victim.guid].objId, "invisible", (0,0,0) );
		objective_icon( level.dogtags[victim.guid].objId, "waypoint_dogtags" );	
		
		level thread clearOnVictimDisconnect( victim );
		victim thread tagTeamUpdater( level.dogtags[victim.guid] );
	}	
	
	pos = victim.origin + (0,0,14);
	level.dogtags[victim.guid].curOrigin = pos;
	level.dogtags[victim.guid].trigger.origin = pos;
	level.dogtags[victim.guid].visuals[0].origin = pos;
	level.dogtags[victim.guid].visuals[1].origin = pos;
	level.dogtags[victim.guid] maps\mp\gametypes\_gameobjects::initializeTagPathVariables();
	
	level.dogtags[victim.guid] maps\mp\gametypes\_gameobjects::allowUse( "any" );	
	
	level.dogtags[victim.guid].visuals[0] thread showToTeam( level.dogtags[victim.guid], getOtherTeam( victim_pers_team ) );
	level.dogtags[victim.guid].visuals[1] thread showToTeam( level.dogtags[victim.guid], victim_pers_team );
	
	level.dogtags[victim.guid].attacker = attacker;
	
	objective_position( level.dogtags[victim.guid].objId, pos );
	objective_state( level.dogtags[victim.guid].objId, "active" );
	Objective_PlayerEnemyTeam( level.dogtags[victim.guid].objId, victim getEntityNumber() );
	
	playSoundAtPos( pos, "mp_killconfirm_tags_drop" );
	
	level.dogtags[victim.guid].visuals[0] ScriptModelPlayAnim( "mp_dogtag_spin" );
	level.dogtags[victim.guid].visuals[1] ScriptModelPlayAnim( "mp_dogtag_spin" );
}


showToTeam( gameObject, team )
{
	gameObject endon( "death" );
	gameObject endon( "reset" );

	self hide();

	foreach ( player in level.players )
	{
		if( player.team == team )
			self ShowToPlayer( player );
		
		if( player.team == "spectator" && team == "allies" )
			self ShowToPlayer( player );
	}

	for ( ;; )
	{
		level waittill ( "joined_team" );
		
		self hide();
		foreach ( player in level.players )
		{
			if ( player.team == team )
				self ShowToPlayer( player );
			
			if( player.team == "spectator" && team == "allies" )
				self ShowToPlayer( player );
				
			if ( gameObject.victimTeam == player.team && player == gameObject.attacker )
				objective_state( gameObject.objId, "invisible" );
		}
	}	
}


onUse( player )
{
	// If this is a squadmate, give credit to the agent's owner player
	if ( IsDefined(player.owner) )
	{
		player = player.owner;
	}
	
	player_pers_team = player.pers["team"];
	
	//	friendly pickup
	if( player_pers_team == self.victimTeam )
	{
		self.trigger playSound( "mp_kc_tag_denied" );
		
		if( IsPlayer(player) )
			player leaderDialogOnPlayer( "kill_denied" );
	
		if( IsDefined(self.attacker) && IsPlayer(self.attacker) )
			self.attacker leaderDialogOnPlayer( "kc_killlost" );
			
		isTagOwner = (self.victim == player);
		player maps\mp\_events::killDeniedEvent( isTagOwner );
	}
	else //	enemy pickup
	{
		self.trigger playSound( "mp_kc_tag_collected" );
		
		if( IsPlayer(self.attacker) && (self.attacker != player) )
			level thread maps\mp\gametypes\_rank::awardGameEvent( "team_confirmed", self.attacker );
		
		player maps\mp\_events::killConfirmedEvent();
		
		if ( IsPlayer(player) )
			player leaderDialogOnPlayer( "kill_confirmed" );
		
		player maps\mp\gametypes\_gamescore::giveTeamScoreForObjective( player_pers_team, 1 );
	}	
	
	level thread maps\mp\_events::monitorTagCollector( player );
	
	//	do all this at the end now so the location doesn't change before playing the sound on the entity
	self resetTags();		
}

resetTags()
{
	self.attacker = undefined;
	self notify( "reset" );
	self.visuals[0] hide();
	self.visuals[1] hide();
	self.curOrigin = (0,0,1000);
	self.trigger.origin = (0,0,1000);
	self.visuals[0].origin = (0,0,1000);
	self.visuals[1].origin = (0,0,1000);
	self maps\mp\gametypes\_gameobjects::allowUse( "none" );	
	objective_state( self.objId, "invisible" );	
}


tagTeamUpdater( tags )
{
	level endon( "game_ended" );
	self endon( "disconnect" );
	
	while( true )
	{
		self waittill( "joined_team" );
		
		tags.victimTeam = self.pers["team"];
		tags resetTags();
	}
}


clearOnVictimDisconnect( victim )
{
	level endon( "game_ended" );	
	
	guid = victim.guid;
	victim waittill( "disconnect" );
	
	if ( isDefined( level.dogtags[guid] ) )
	{
		//	block further use
		level.dogtags[guid] maps\mp\gametypes\_gameobjects::allowUse( "none" );		
		
		//	play vanish effect, reset, and wait for reset to process
		PlayFx( level.conf_fx["vanish"], level.dogtags[guid].curOrigin );
		level.dogtags[guid] notify( "reset" );		
		wait( 0.05 );
		
		//	sanity check before removal
		if ( isDefined( level.dogtags[guid] ) )
		{
			//	delete objective and visuals
			objective_delete( level.dogtags[guid].objId );
			level.dogtags[guid].trigger delete();
			for ( i=0; i<level.dogtags[guid].visuals.size; i++ )
				level.dogtags[guid].visuals[i] delete();
			level.dogtags[guid] notify ( "deleted" );
			
			//	remove from list
			level.dogtags[guid] = undefined;		
		}	
	}	
}
