#using scripts\codescripts\struct;

#using scripts\shared\callbacks_shared;
#using scripts\shared\challenges_shared;
#using scripts\shared\clientfield_shared;
#using scripts\shared\hostmigration_shared;
#using scripts\shared\killstreaks_shared;
#using scripts\shared\popups_shared;
#using scripts\shared\util_shared;
#using scripts\shared\vehicle_shared;
#using scripts\shared\vehicle_death_shared;
#using scripts\shared\weapons\_hacker_tool;
#using scripts\shared\scoreevents_shared;
#using scripts\shared\math_shared;
#using scripts\shared\weapons\_heatseekingmissile;
#using scripts\mp\killstreaks\_qrdrone;
#using scripts\mp\killstreaks\_airsupport;
#using scripts\shared\vehicle_ai_shared;

#using scripts\mp\_util;
#using scripts\mp\gametypes\_shellshock;
#using scripts\mp\killstreaks\_killstreak_bundles;
#using scripts\mp\killstreaks\_killstreak_detect;
#using scripts\mp\killstreaks\_killstreak_hacking;
#using scripts\mp\killstreaks\_killstreakrules;
#using scripts\mp\killstreaks\_killstreaks;
#using scripts\mp\killstreaks\_remote_weapons;

  
                                                                                                   	  	                                                                    	                     	                 	                                                                         	                       	                                                      	                                                      	                                                       	                                                                                                  	                                                                                                                 	                                                   	                	                                          	                                      	       	  	             	                                                     	                                                                             	                         	                                                                	                                                             	                                                             	                                                                                      	                                                         	                                                         	                                                               	                                                               	                                                   	                                                                	                                                     	                                                	                                                	                                                        	                                                                                                  	                                                                             	                                            	                                                                                    	                                          	                     	                                              	                                        	                 	   
                                             
    	   	                                                                                                                                         	                                	                                                                                                                                                                                                                                                                                                                                                                    	        	     	              	    	   	               	                                              	                                                           	                               	                     	                                                                                                           	                                                                 	                                                              	                                                                                                                                             	                            	                                     	                                       	                                                                                                              	   	                  	       	                                                    	                   	                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                            	                                                                                                 	                                    	                                                                                        	           	                        	                                            	                                             	                                                   	                                                             	                                                         	                                                                    	                                                                                                                                                                                                                                	                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                  	    	         	                                                              	                                                          	                                   	                                   	                                                    	                                       	                                           	     	                                                                                                                                                                                                                                                      	                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                         	                                                               	        	                                                                                                                              	                                                                                                                     	                               	                                                      	                          
                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                         	   	                                                                                                                                                                                                                                  	                                                                                                                                                                                                                                                                                                                                                                                                                                                   
#using scripts\shared\visionset_mgr_shared;

#namespace dart;



	
#precache( "string", "KILLSTREAK_DART_HACKED" );
#precache( "string", "KILLSTREAK_DART_EARNED" );
#precache( "string", "KILLSTREAK_DART_NOT_AVAILABLE" );
#precache( "string", "KILLSTREAK_DART_INBOUND" );
#precache( "string", "KILLSTREAK_DART_HACKED" );
#precache( "string", "KILLSTREAK_DESTROYED_DART" );
#precache( "string", "mpl_killstreak_dart_strt" );
	
function init()
{
	killstreaks::register( "dart", "dart", "killstreak_dart", "dart_used", &ActivateDart, true) ;
	killstreaks::register_strings( "dart", &"KILLSTREAK_DART_EARNED", &"KILLSTREAK_DART_NOT_AVAILABLE", &"KILLSTREAK_DART_INBOUND", undefined, &"KILLSTREAK_DART_HACKED" );
	killstreaks::register_dialog( "dart", "mpl_killstreak_dart_strt", "dartDialogBundle", "dartPilotDialogBundle", "friendlyDart", "enemyDart",  "enemyDartMultiple", "friendlyDartHacked", "enemyDartHacked", "requestDart", "threatDart" );
	killstreaks::override_entity_camera_in_demo( "dart", true );

	killstreaks::register_alt_weapon( "dart", "killstreak_remote" );
	killstreaks::register_alt_weapon( "dart", "dart_blade" );
	killstreaks::register_alt_weapon( "dart", "dart_turret" );
	
	clientfield::register( "toplayer", "dart_update_ammo", 1, 2, "int" );
	clientfield::register( "toplayer", "fog_bank_3", 1, 1, "int" );	

	remote_weapons::RegisterRemoteWeapon( "dart", &"", &StartDartRemoteControl, &EndDartRemoteControl, true );
	
	visionset_mgr::register_info( "visionset", "dart_visionset", 1, 90, 16, true, &visionset_mgr::ramp_in_out_thread_per_player_death_shutdown, false  );
}

function wait_dart_timed_out( time )
{
	self endon( "disconnect" );
	self endon( "death" );
	self endon( "dart_throw_failed" );
	self endon( "dart_entered" );

	wait( time );
	
	self notify( "dart_throw_timed_out" );
}

function wait_for_throw_status()
{
	thread dart::wait_dart_timed_out( 5 );
	
	notifyString = self util::waittill_any_return( "death", "disconnect", "dart_entered", "dart_throw_timed_out","dart_throw_failed" );

	if ( notifyString == "dart_entered" || notifyString == "death" )
		return true;
	
	return false;
}

function ActivateDart( killstreakType )
{
	player = self;
	
	assert( IsPlayer( player ) );
	
	if( !player killstreakrules::isKillstreakAllowed( "dart", player.team ) )
		return false;
	
	player DisableOffhandWeapons();
	
	missileWeapon = player GetCurrentWeapon();
	if( !( isdefined( missileWeapon ) && ( ( missileWeapon.name == "dart" ) || ( missileWeapon.name == "inventory_dart" ) ) ) )
		return false;
	
	player thread WatchThrow( missileWeapon );

	notifyString = player util::waittill_any_return( "weapon_change", "grenade_fire", "death", "disconnect", "joined_team", "emp_jammed", "emp_grenaded" );

	if( notifyString == "death" || notifyString == "emp_jammed" || notifyString == "emp_grenaded" )
	{
		///#iprintln( "death" );#/
		if( player.waitingOnDartThrow ) 
			player notify( "dart_putaway" );
		
		player EnableOffhandWeapons();
		return false; 
	}
	
	if( notifyString == "grenade_fire" )
	{
		// wait for the killStreakStart results
		return player wait_for_throw_status();
	}

	if( notifyString == "weapon_change" )
	{
		if( player.waitingOnDartThrow ) 
			player notify( "dart_putaway" );
		
		player EnableOffhandWeapons();
		return false; 
	}
	
	return true;
}

function cleanup_grenade()
{
	self thread waitThenDelete( 0.05 );
	self.origin = self.origin + ( 0, 0, 1000 );	
}

function WatchThrow( missileWeapon )
{
	assert( IsPlayer( self ) );
	player = self;
	playerEntNum = player.entNum;
	
	player endon( "disconnect" );
	player endon( "joined_team" );
	// player endon( "death" ); // once the dart is thrown, even after death, the player should control it
	player endon( "dart_putaway" );
	
	level endon( "game_ended" );

	player.waitingOnDartThrow = 1;
	player waittill( "grenade_fire", grenade, weapon );
	player.waitingOnDartThrow = 0;
	
	if( weapon != missileWeapon )
	{
		self notify("dart_throw_failed");
		return;
	}
	
	trace = player check_launch_space(grenade.origin);
	
	if ( trace["fraction"] < 1.0 )
	{
		self iprintlnbold( &"KILLSTREAK_DART_NOT_AVAILABLE" );
		grenade cleanup_grenade();
		self notify("dart_throw_failed");
		return;
	}
	
	killstreak_id = player killstreakrules::killstreakStart( "dart", player.team, undefined, false );
	if( killstreak_id == (-1) )
	{
		grenade cleanup_grenade();
		self notify("dart_throw_failed");
		return;
	}
	
	player.dart_thrown_time = GetTime();
	
	player TakeWeapon( missileWeapon );
	
	player killstreaks::set_killstreak_delay_killcam( "dart" ); // special case: death while watching does not prevent riding dart, and thus no killcam
	player.resurrect_not_allowed_by = "dart";

	player AddWeaponStat( GetWeapon( "dart" ), "used", 1 );
	level thread popups::DisplayKillstreakTeamMessageToAll( "dart", player );
	
	dart = player SpawnDart( grenade, killstreak_id, trace["position"] );
	if( isdefined( dart ) )
	{
		player killstreaks::play_killstreak_start_dialog( "dart", player.team, killstreak_id );
	}
}

function HackedPreFunction( hacker )
{
	dart = self;
	dart.owner util::freeze_player_controls( false );
	visionset_mgr::deactivate( "visionset", "dart_visionset", dart.owner );
	dart.owner clientfield::set_to_player( "fog_bank_3", 0 );
	dart.owner unlink();
	dart clientfield::set( "vehicletransition", 0 );
	dart.owner killstreaks::clear_using_remote();
	dart.owner killstreaks::unhide_compass();
	dart.owner vehicle::stop_monitor_missiles_locked_on_to_me();
	dart.owner vehicle::stop_monitor_damage_as_occupant();
	dart DisableDartMissileLocking();
}

function HackedPostFunction( hacker )
{
	dart = self;
	hacker StartDartRemoteControl( dart );
	
	hacker killstreak_hacking::set_vehicle_drivable_time_starting_now( dart );
	hacker remote_weapons::UseRemoteWeapon( dart, "dart", false );
	hacker killstreaks::set_killstreak_delay_killcam( "dart" );
}

function dart_hacked_health_update( hacker )
{
	dart = self;
	if ( dart.health > dart.hackedhealth )
	{
		dart.health = dart.hackedhealth;	
	}
}

function check_launch_space(origin)
{
	player_angles = self getPlayerAngles();
	forward = AnglesToForward( player_angles );
	spawn_origin = origin + VectorScale( forward, 50 );
	
	radius = 10;
	return physicstrace( origin, spawn_origin, ( -radius, -radius, 0 ), ( radius, radius, 2 * radius ), self, (1 << 0) );
}

function SpawnDart( grenade, killstreak_id, spawn_origin )
{
	///#iprintln( "Spawn Dart" );#/
	player = self;
	assert( IsPlayer( player ) );
	playerEntNum = player.entNum;
	player_angles = player getPlayerAngles();
	
	grenade cleanup_grenade();
	
	params = level.killstreakBundle["dart"];

	if(!isdefined(params.ksDartVehicle))params.ksDartVehicle="veh_dart_mp";
	if(!isdefined(params.ksDartInitialSpeed))params.ksDartInitialSpeed=35;
	if(!isdefined(params.ksDartAcceleration))params.ksDartAcceleration=35;
		
	dart = SpawnVehicle( params.ksDartVehicle, spawn_origin, player_angles, "dynamic_spawn_ai" );
	
	//dart thread debug_origin();
	
	dart.is_shutting_down = 0;
	dart.team = player.team;
	dart SetSpeedImmediate( params.ksDartInitialSpeed, params.ksDartAcceleration );
	dart.maxhealth = killstreak_bundles::get_max_health( "dart" );
	dart.health = dart.maxhealth;
	dart.hackedhealth = killstreak_bundles::get_hacked_health( "dart" );
	dart.hackedHealthUpdateCallback = &dart_hacked_health_update;
	
	dart killstreaks::configure_team( "dart", killstreak_id, player, "small_vehicle" );
	dart killstreak_hacking::enable_hacking( "dart", &HackedPreFunction, &HackedPostFunction );

	dart clientfield::set( "enemyvehicle", 1 );
	dart.killstreak_id = killstreak_id;
	dart.hardpointType = "dart";
	dart thread killstreaks::WaitForTimeout( "dart", ( 30 * 1000 ), &stop_remote_weapon, "remote_weapon_end", "death" );
	dart hacker_tool::registerWithhackerTool( ( 50 ), ( 2000 ) );
	dart.overrideVehicleDamage = &dartDamageOverride;	
	dart.DetonateViaEMP = &emp_damage_cb;
	dart.do_scripted_crash = false;
	dart.delete_on_death = true;
	dart.one_remote_use = true;
	dart.vehcheckforpredictedcrash = true;
	dart.predictedCollisionTime = 0.2;
	dart.glasscollision_alt = true;
	dart.damageTaken = 0;
	dart.death_enter_cb = &waitRemoteControl;
	
	Target_Set( dart );
	
	dart vehicle::init_target_group();
	dart vehicle::add_to_target_group( dart );
	
	dart thread WatchCollision();
	
	dart thread WatchDeath();
	
	dart thread WatchOwnerNonDeathEvents();
	
	dart.forceWaitRemoteControl = true;
	
	player util::waittill_any( "weapon_change", "death" ); // wait for the killstreak weapon to go away, or the player dies (special case for Dart)

	player remote_weapons::UseRemoteWeapon( dart, "dart", true, true, true );
	
	player notify( "dart_entered" );
	
	return dart;
}

function debug_origin()
{
	self endon( "death" );
	while( 1 )
	{
		/#sphere( self.origin, 5, ( 1.0, 0, 0 ), 1.0, true, 2, 120 );#/
		{wait(.05);};
	}
}

function waitRemoteControl()
{
	dart = self;
	
	remote_controlled = ( isdefined( dart.control_initiated ) && dart.control_initiated ) || ( isdefined( dart.controlled ) && dart.controlled );
	
	if( remote_controlled )
	{
		notifyString = dart util::waittill_any_return( "remote_weapon_end", "dart_left" );
		if ( isdefined( notifyString ) )
		{
			if( notifyString == "remote_weapon_end" )
				dart waittill( "dart_left" );
			else
				dart waittill( "remote_weapon_end" );
		}
	}
	else
		dart waittill( "dart_left" );
}

function StartDartRemoteControl( dart )
{
	///#iprintln( "StartDartRemoteControl" );#/
	player = self;
	assert( IsPlayer( player ) );

	if( !dart.is_shutting_down )
	{
		player.dart_thrown_time = undefined;
	
		///#iprintln( "UseVehicle" );#/
		dart UseVehicle( player, 0 );/// 
		player.resurrect_not_allowed_by = undefined;
		dart clientfield::set( "vehicletransition", 1 );
		dart thread WatchAmmo();
		dart thread vehicle::monitor_missiles_locked_on_to_me( player );
		dart thread vehicle::monitor_damage_as_occupant( player );
		
		player vehicle::set_vehicle_drivable_time_starting_now( ( 30 * 1000 ) );
		player.no_fade2black = true;
		
		dart.inHeliProximity = false;
		
		minHeightOverride = undefined;
		minz_struct = struct::get( "vehicle_oob_minz", "targetname");
		if( isdefined( minz_struct ) )
			minHeightOverride = minz_struct.origin[2];			
		
		dart thread qrdrone::QRDrone_watch_distance( ( 2000 ), minHeightOverride );
		dart.distance_shutdown_override = &DartDistanceFailure;
		
		dart EnableDartMissileLocking();
		visionset_mgr::activate( "visionset", "dart_visionset", self, 1, 90000, 1 );		
		player clientfield::set_to_player( "fog_bank_3", 1 );
	}
}

function EndDartRemoteControl( dart, exitRequestedByOwner )
{
	dart thread leave_dart();
}

function DartDistanceFailure()
{
	thread stop_remote_weapon();
}
 
function stop_remote_weapon( attacker, weapon )
{
	dart = self;

	dart.DetonateViaEMP = undefined; 
	
	attacker = self [[ level.figure_out_attacker ]]( attacker );
	if ( isdefined( attacker ) && ( !isdefined( dart.owner ) ||  dart.owner util::IsEnemyPlayer( attacker ) ) )
	{
		challenges::destroyedAircraft( attacker, weapon, true );
		attacker challenges::addFlySwatterStat( weapon, self );
		scoreevents::processScoreEvent( "destroyed_dart", attacker, dart.owner, weapon );
		LUINotifyEvent( &"player_callout", 2, &"KILLSTREAK_DESTROYED_DART", attacker.entnum );		
	}
	
	if( isdefined( attacker ) && attacker != dart.owner )
	{
		dart killstreaks::play_destroyed_dialog_on_owner( "dart", dart.killstreak_id );
	}		

	dart thread remote_weapons::EndRemoteControlWeaponUse( false );		
}

function dartDamageOverride( eInflictor, eAttacker, iDamage, iDFlags, sMeansOfDeath, weapon, vPoint, vDir, sHitLoc, vDamageOrigin, psOffsetTime, damageFromUnderneath, modelIndex, partName, vSurfaceNormal )
{
	dart = self;
	
	if( ( sMeansOfDeath == "MOD_TRIGGER_HURT" ) || ( isdefined( dart.is_shutting_down ) && dart.is_shutting_down ) )
		return 0;
	
	player = dart.owner;

	iDamage = killstreaks::OnDamagePerWeapon( "dart", eAttacker, iDamage, iDFlags, sMeansOfDeath, weapon, self.maxhealth, &stop_remote_weapon, self.maxhealth*0.4, undefined, 
	                                         0, &emp_damage_cb, true, 1.0 );

	return iDamage;
}

function emp_damage_cb( attacker, weapon )
{
	dart = self;
	dart stop_remote_weapon( attacker, weapon );
}

function DarPredictedCollision()
{
	self endon( "death" );
	
	while( 1 )
	{
		self waittill( "veh_predictedcollision", velocity, normal, ent, stype );
		self notify( "veh_collision", velocity, normal, ent, stype );
		
		if( stype == "glass" )
			continue;
		else
			break;
	}
}

function WatchCollision()
{
	dart = self;
	dart endon( "death" );
	dart.owner endon( "disconnect" );
	
	dart thread DarPredictedCollision();
	
	
	while( 1 )
	{
		dart waittill( "veh_collision", velocity, normal, ent, stype );
		
		///#sphere( dart.origin, 5, ( 1.0, 0, 0 ), 1.0, true, 100, 120 );#/
		if( stype === "glass" )
			continue;
		
		dart SetSpeedImmediate( 0 );
		dart vehicle_death::death_fx();
		
		dart thread stop_remote_weapon();
		break;
	}
}

function WatchDeath()
{
	dart = self;
	player = dart.owner;
	
	player endon( "dart_entered" ); // the remote weapon script should handle it from here on
	dart endon( "delete" );

	dart waittill( "death" );
	//dart waittill( "death", attacker, damageFromUnderneath, weapon, point, dir, modType );
	
	dart thread leave_dart();
}

function WatchOwnerNonDeathEvents( endCondition1, endCondition2 )
{
	dart = self;
	player = dart.owner;
	
	player endon( "dart_entered" ); // the remote weapon script should handle it from here on
	dart endon( "death" );
	
	dart thread WatchForGameEnd();
	
	player util::waittill_any( "joined_team", "disconnect", "joined_spectators", "emp_jammed" );
	
	dart thread leave_dart();
}

function WatchForGameEnd()
{
	dart = self;
	dart endon( "death" );	

	level waittill( "game_ended" );

	dart thread leave_dart();
}
	
function WatchAmmo()
{
	dart = self;
	dart endon( "death" );
	
	player = dart.owner;
	
	player endon( "disconnect" );
	
	shotCount = 0;
	
	params = level.killstreakBundle["dart"];

	if(!isdefined(params.ksDartShotCount))params.ksDartShotCount=3;
	if(!isdefined(params.ksDartBladeCount))params.ksDartBladeCount=6;
	if(!isdefined(params.ksDartWaitTimeAfterLastShot))params.ksDartWaitTimeAfterLastShot=1;
	
	if(!isdefined(params.ksBladeStartDistance))params.ksBladeStartDistance=0;
	if(!isdefined(params.ksBladeEndDistance))params.ksBladeEndDistance=10000;
	if(!isdefined(params.ksBladeStartSpreadRadius))params.ksBladeStartSpreadRadius=50;
	if(!isdefined(params.ksBladeEndSpreadRadius))params.ksBladeEndSpreadRadius=1;
	
	player clientfield::set_to_player( "dart_update_ammo", params.ksDartShotCount );

	while( true )
	{
		dart waittill( "weapon_fired" );
		shotCount++;
		
		player clientfield::set_to_player( "dart_update_ammo", params.ksDartShotCount - shotCount );
		
		if( shotCount >= params.ksDartShotCount )
		{
			dart DisableDriverFiring( true );
			wait( params.ksDartWaitTimeAfterLastShot );
			dart stop_remote_weapon();
		}
	}
}

function leave_dart()
{
	dart = self;
	owner = dart.owner;
	
	if( isdefined( owner ) )
	{
		visionset_mgr::deactivate( "visionset", "dart_visionset", owner );
		owner clientfield::set_to_player( "fog_bank_3", 0 );
		owner qrdrone::destroyHud();	
	}
	
	if( isdefined( dart ) && ( dart.is_shutting_down == 1 ) )
		return;
	
	dart.is_shutting_down = 1;
	
	dart clientfield::set( "timeout_beep", 0 );
	dart vehicle::lights_off();
	dart vehicle_death::death_fx();
	dart Hide();
	
	dart_original_team = dart.originalteam;
	dart_killstreak_id = dart.killstreak_id;
	
	if( Target_IsTarget( dart ) )
		Target_Remove( dart );
	
	iF( isalive( dart ) )
		dart notify( "death" );	
	
	params = level.killstreakBundle["dart"];
	
	if(!isdefined(params.ksDartExplosionOuterRadius))params.ksDartExplosionOuterRadius=200; 
	if(!isdefined(params.ksDartExplosionInnerRadius))params.ksDartExplosionInnerRadius=1;
	if(!isdefined(params.ksDartExplosionOuterDamage))params.ksDartExplosionOuterDamage=25;
	if(!isdefined(params.ksDartExplosionInnerDamage))params.ksDartExplosionInnerDamage=350;
	if(!isdefined(params.ksDartExplosionMagnitude))params.ksDartExplosionMagnitude=1;
	
	PhysicsExplosionSphere( dart.origin, 
	                       params.ksDartExplosionOuterRadius, 
	                       params.ksDartExplosionInnerRadius, 
	                       params.ksDartExplosionMagnitude,
	                       params.ksDartExplosionOuterDamage,
	                       params.ksDartExplosionInnerDamage );
	
	if( isdefined( owner ) )
	{
		owner killstreaks::set_killstreak_delay_killcam( "dart" ); // hold the respawn till we finish here
		
		dart RadiusDamage( dart.origin, 
		             params.ksDartExplosionOuterRadius,
		             params.ksDartExplosionInnerDamage,
		             params.ksDartExplosionOuterDamage,
		             owner, 
		             "MOD_EXPLOSIVE",
		             GetWeapon( "dart" ) );
		
		owner thread play_bda_dialog( self.pilotIndex );		
		
		if( ( isdefined( dart.controlled ) && dart.controlled ) || ( isdefined( dart.control_initiated ) && dart.control_initiated ) )
		{
			owner SetClientUIVisibilityFlag( "hud_visible", 0 );
			owner unlink();
			dart clientfield::set( "vehicletransition", 0 );
			
			if( isdefined( params.ksExplosionRumble ) )
				owner PlayRumbleOnEntity( params.ksExplosionRumble );

			owner vehicle::stop_monitor_missiles_locked_on_to_me();
			owner vehicle::stop_monitor_damage_as_occupant();
			
			dart DisableDartMissileLocking();
			
			owner util::freeze_player_controls( true );
		
			forward = AnglesToForward( dart.angles );
			if(!isdefined(params.ksDartCameraWatchDistance))params.ksDartCameraWatchDistance=350;
			moveAmount = VectorScale( forward, -( params.ksDartCameraWatchDistance ) );
			
			size = 4;
			trace = physicstrace( dart.origin, dart.origin + moveAmount, ( -size, -size, -size ), ( size, size, size ), undefined, (1 << 0) );
			
			cam = spawn( "script_model", trace["position"] );
			cam SetModel( "tag_origin" );
			cam LinkTo( dart );
			dart SetSpeedImmediate( 0 );
			
			owner CameraSetPosition( cam.origin );
			owner CameraSetLookAt( dart.origin );
			owner CameraActivate( true );	
		
			if(!isdefined(params.ksDartCameraWatchDuration))params.ksDartCameraWatchDuration=2;
			wait( params.ksDartCameraWatchDuration );
			
			if ( isdefined( owner ) )
			{
				owner CameraActivate( false );
			}
			
			cam delete();
			
			if( isdefined( owner ) )
			{
				if( !level.gameEnded )
					owner util::freeze_player_controls( false );
				
				owner SetClientUIVisibilityFlag( "hud_visible", 1 );
			}
		}
		
		if ( isdefined( owner ) )
		{
			owner killstreaks::reset_killstreak_delay_killcam();
		}
	}

	killstreakrules::killstreakStop( "dart", dart_original_team, dart_killstreak_id );
	
	if ( isdefined( dart ) )
	{
		dart notify( "dart_left" );
	}
}

function DeleteOnConditions( condition )
{
	dart = self;
	dart endon( "delete" );
	
	if( isdefined( condition ) )
		dart waittill( condition );
	
	dart notify( "delete" );
	dart delete();
}

function waitThenDelete( waitTime )
{
	self endon( "delete" );
	self endon( "death" );
	wait( waitTime );
	self delete();
}

function play_bda_dialog( pilotIndex )
{
	self endon( "game_ended" );

	wait( 0.5 );
	
	if ( !isdefined( self.dartBda ) || self.dartBda == 0 )
	{
		bdaDialog = "killNone";
	}
	else if ( self.dartBda == 1 )
	{
		bdaDialog = "kill1";
	}
	else if ( self.dartBda == 2 )
	{
		bdaDialog = "kill2";
	}
	else if ( self.dartBda == 3 )
	{
		bdaDialog = "kill3";
	}
	else if ( self.dartBda > 3 )
	{
		bdaDialog = "killMultiple";
	}

	self killstreaks::play_pilot_dialog( bdaDialog, "dart", undefined, pilotIndex );
	
	self.dartBda = undefined;
}

function EnableDartMissileLocking() // self == dart
{	
	dart = self;
	player = dart.owner;
	weapon = dart SeatGetWeapon( 0 );
	
	player.get_stinger_target_override = &GetDartMissileTargets;
	player.is_still_valid_target_for_stinger_override = &IsStillValidDartMissileTarget;
	player.is_valid_target_for_stinger_override = &IsValidDartMissileTarget;
	player.dart_killstreak_weapon = weapon;

	player thread heatseekingmissile::StingerIRTLoop( weapon );
}

function DisableDartMissileLocking() // self == dart
{
	player = self.owner;
	
	player.get_stinger_target_override = undefined;
	player.is_still_valid_target_for_stinger_override = undefined;
	player.is_valid_target_for_stinger_override = undefined;
	player.dart_killstreak_weapon = undefined;
	
	player notify( "stinger_IRT_off" );
	player heatseekingmissile::ClearIRTarget();
}

function GetDartMissileTargets()
{
	targets = ArrayCombine( target_getArray(), level.MissileEntities, false, false );
	targets = ArrayCombine( targets, level.players, false, false );
	
	return targets;
}

function IsValidDartMissileTarget( ent ) // self == player
{
	player = self;
	
	if ( !isdefined( ent ) )
		return false;
	
	entIsPlayer = IsPlayer( ent );

	if ( entIsPlayer && !IsAlive( ent ) )
		return false;

	if ( ent.ignoreme === true )
		return false;

	dart = player GetVehicleOccupied();
	if ( !isdefined( dart ) )
		return false;

	if ( DistanceSquared( dart.origin, ent.origin ) > ( (player.dart_killstreak_weapon.lockOnMaxRange) * (player.dart_killstreak_weapon.lockOnMaxRange) ) )
		return false;

	if ( entIsPlayer && ent HasPerk( "specialty_nokillstreakreticle" ) )
		return false;

	return true;	
}

function IsStillValidDartMissileTarget( ent, weapon ) // self == player
{
	player = self;
	
	if ( !( target_isTarget( ent ) || IsPlayer( ent ) ) && !( isdefined( ent.allowContinuedLockonAfterInvis ) && ent.allowContinuedLockonAfterInvis ) )
		return false;
	
	dart = player GetVehicleOccupied();
	if ( !isdefined( dart ) )
		return false;
	
	entIsPlayer = IsPlayer( ent );
	
	if ( entIsPlayer && !IsAlive( ent ) )
		return false;
	
	if ( ent.ignoreme === true )
		return false;

	if ( DistanceSquared( dart.origin, ent.origin ) > ( (player.dart_killstreak_weapon.lockOnMaxRange) * (player.dart_killstreak_weapon.lockOnMaxRange) ) )
		return false;
	
	if ( entIsPlayer && ent HasPerk( "specialty_nokillstreakreticle" ) )
		return false;
		
	if ( !heatseekingmissile::InsideStingerReticleLocked( ent, weapon ) )
		return false;

	return true;
}
