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

globalThink()
{
	if ( !isdefined( self.vehicletype ) )
		return;

	isHelicopter = false;
	if ( self.vehicletype == "hind" )
	{
		isHelicopter = true;
	}
	if ( ( self.vehicletype == "cobra" ) || ( self.vehicletype == "cobra_player" ) )
	{
		self thread attachMissiles( "cobra_Hellfire", "cobra_Sidewinder" );
		isHelicopter = true;
	}

	if ( !isHelicopter )
		return;

	level thread flares_think( self );
	level thread maps\_helicopter_ai::evasive_think( self );

	if ( getdvar( "cobrapilot_wingman_enabled" ) == "1" )
	{
		if ( isdefined( self.script_wingman ) )
		{
			level._wingman = self;
			level thread maps\_helicopter_ai::wingman_think( self );
		}
	}
}

flares_think( vehicle )
{
	vehicle endon( "death" );
	while ( vehicle.health > 0 )
	{
		if ( isdefined( vehicle.playercontrolled ) )
		{
			if ( ( !vehicle.pilot buttonPressed( level._flareButton1 ) ) && ( !vehicle.pilot buttonPressed( level._flareButton2 ) ) )
			{
				wait 0.05;
				continue;
			}
		}
		else
		{
			vehicle waittill( "incomming_missile", eMissile );
			if ( !isdefined( eMissile ) )
				continue;

			//sometimes dont drop flares
			if ( randomint( 3 ) == 0 )
				continue;

			wait randomfloatrange( 0.5, 1.0 );
		}

		flares_fire( vehicle );

		wait 0.05;
		if ( !isdefined( vehicle.playercontrolled ) )
			wait 3.0;
	}
}

flares_fire_burst( vehicle, fxCount, flareCount, flareTime )
{
	assert( isdefined( level._flare_fx[ vehicle.vehicletype ] ) );

	assert( fxCount >= flareCount );

	for ( i = 0 ; i < fxCount ; i++ )
	{
		playfx( level._flare_fx[ vehicle.vehicletype ], vehicle getTagOrigin( "tag_flare" ) );

		if ( isdefined( vehicle.playercontrolled ) )
		{
			level._stats[ "flares_used" ]++ ;
			if ( getdvar( "cobrapilot_sounds_enabled" ) == "1" )
				vehicle.pilot playLocalSound( "weap_flares_fire" );
		}

		if ( i <= flareCount - 1 )
			thread flares_redirect_missiles( vehicle, flareTime );

		wait 0.1;
	}
}

flares_fire( vehicle )
{
	vehicle endon( "death" );

	if ( isdefined( vehicle.playercontrolled ) )
	{
		flareTime = 1.0;
		while ( ( vehicle.pilot buttonPressed( level._flareButton1 ) ) || ( vehicle.pilot buttonPressed( level._flareButton2 ) ) )
		{
			flares_fire_burst( vehicle, 1, 1, flareTime );
			flareTime = flareTime + 1.0;
			if ( flareTime > 5.0 )
				flareTime = 5.0;
		}
	}
	else
	{
		flares_fire_burst( vehicle, 8, 1, 5.0 );
	}

}

flares_redirect_missiles( vehicle, flareTime )
{
	vehicle notify( "flares_out" );
	vehicle endon( "death" );
	vehicle endon( "flares_out" );

	if ( !isdefined( flareTime ) )
		flareTime = 5.0;

	// create a script_origin at the flares location and move it down with gravity
	vec = flares_get_vehicle_velocity( vehicle );
	flare = spawn( "script_origin", vehicle getTagOrigin( "tag_flare" ) );
	flare movegravity( vec, flareTime );

	if ( !isdefined( vehicle.incomming_Missiles ) )
		return;

	// redirect all incomming missiles to the new flares
	for ( i = 0 ; i < vehicle.incomming_Missiles.size ; i++ )
		vehicle.incomming_Missiles[ i ] Missile_SetTargetEnt( flare );

	// wait for flares to burn out	
	wait flareTime;

	if ( !isdefined( vehicle.script_targetoffset_z ) )
		vehicle.script_targetoffset_z = 0;
	offset = ( 0, 0, vehicle.script_targetoffset_z );

	// when the flares burn out redirect missiles to the main target again ( if missile is still alive )
	if ( !isdefined( vehicle.incomming_Missiles ) )
		return;
	for ( i = 0 ; i < vehicle.incomming_Missiles.size ; i++ )
		vehicle.incomming_Missiles[ i ] Missile_SetTargetEnt( vehicle, offset );
}

flares_get_vehicle_velocity( vehicle )
{
	org1 = vehicle.origin;
	wait 0.05;
	vec = ( vehicle.origin - org1 );
	return vector_multiply( vec, 20 );
}

missile_deathWait( eMissile, eMissile_Target )
{
	eMissile_Target endon( "death" );

	eMissile waittill( "death" );

	if ( !isdefined( eMissile_Target.incomming_Missiles ) )
		return;

	eMissile_Target.incomming_Missiles = array_remove( eMissile_Target.incomming_Missiles, eMissile );
}

//*******************************************************************
//																	*
//																	*
//*******************************************************************
get_potential_enemy_targets( fRadius, iFOVcos, getAITargets, doSightTrace, getVehicleTargets, randomizeTargetArray, aExcluders )
{
	if ( !isdefined( getAITargets ) )
		getAITargets = false;

	if ( !isdefined( doSightTrace ) )
		doSightTrace = false;

	if ( !isdefined( getVehicleTargets ) )
		getVehicleTargets = true;

	if ( !isdefined( randomizeTargetArray ) )
		randomizeTargetArray = false;

	eTargets = [];

	enemyTeam = common_scripts\utility::get_enemy_team( self.script_team );
	possibleTargets = [];
	//prof_begin( "cobrapilot_ai" );

	if ( getVehicleTargets )
	{
		assert( isdefined( level._vehicles[ enemyTeam ] ) );
		for ( i = 0 ; i < level._vehicles[ enemyTeam ].size ; i++ )
		{
			if ( IsDefined( level._vehicles[enemyTeam][i].ignoreme ) && level._vehicles[enemyTeam][i].ignoreme )
			{
				continue;
			}

			possibleTargets[ possibleTargets.size ] = level._vehicles[ enemyTeam ][ i ];
		}
	}

	if ( getAITargets )
	{
		enemyAI = getaiarray( enemyTeam );
		for ( i = 0 ; i < enemyAI.size ; i++ )
		{
			if ( !IsAlive( enemyAI[i] ) )
			{
				continue;
			}

			if( isdefined( enemyAI[ i ].ignored_by_attack_heli ) )
			{
				continue;
			}

			if ( IsDefined( enemyAI[i].ignoreme ) && enemyAI[i].ignoreme )
			{
				continue;
			}

			possibleTargets[ possibleTargets.size ] = enemyAI[ i ];
		}

		if ( enemyTeam == "allies" )
		{
			for ( i = 0; i < level._players.size; i++ )
			{
				if ( IsDefined( level._players[i].ignoreme ) && level._players[i].ignoreme )
				{
					continue;
				}

				possibleTargets[ possibleTargets.size ] = level._players[ i ];
			}
		}
	}

	if ( isdefined( aExcluders ) )
		possibleTargets = array_exclude( possibleTargets, aExcluders );

	if ( randomizeTargetArray )
		possibleTargets = array_randomize( possibleTargets );

	forwardvec = anglestoforward( self.angles );
	for ( i = 0 ; i < possibleTargets.size ; i++ )
	{
		// threatbias - if this is an ignored group then dont consider this target
		if ( ( isSentient( possibleTargets[ i ] ) ) && ( isSentient( self ) ) && ( self getThreatBiasGroup() != "" ) )
		{
			bias = getThreatBias( possibleTargets[ i ] getThreatBiasGroup(), self getThreatBiasGroup() );
			if ( bias <= -1000000 )
				continue;
		}

		// check if the target is within range
		if ( isdefined( fRadius ) && ( fRadius > 0 ) )
		{
			if ( distance( self.origin, possibleTargets[ i ].origin ) > fRadius )
				continue;
		}

		// check if the target is within fov
		if ( isdefined( iFOVcos ) )
		{
			normalvec = vectorNormalize( possibleTargets[ i ].origin - ( self.origin ) );
			vecdot = vectordot( forwardvec, normalvec );
			if ( vecdot <= iFOVcos )
				continue;
		}

		// check if a sight trace passes
		if ( doSightTrace )
		{
			sightTracePassed = false;
			if ( isAi( possibleTargets[ i ] ) )
				TraceZoffset = 48;
			else
				TraceZoffset = 150;
			sightTracePassed = sighttracepassed( self.origin, possibleTargets[ i ].origin + ( 0, 0, TraceZoffset ), false, self );
			if ( !sightTracePassed )
				continue;
		}

		eTargets[ eTargets.size ] = possibleTargets[ i ];
	}

	return eTargets;
}

getEnemyTarget( fRadius, iFOVcos, getAITargets, doSightTrace, getVehicleTargets, randomizeTargetArray, aExcluders )
{
	eTargets = self get_potential_enemy_targets( fRadius, iFOVcos, getAITargets, doSightTrace, getVehicleTargets, randomizeTargetArray, aExcluders );
	//prof_end( "cobrapilot_ai" );

	self notify( "gunner_new_target" );

	// return if no targets were found
	if ( eTargets.size == 0 )
		return undefined;

	// if only one target was found return it
	if ( eTargets.size == 1 )
		return eTargets[ 0 ];

	// return the closest of the targets
	//prof_begin( "cobrapilot_ai" );
	theTarget = getClosest( self.origin, eTargets );
	//prof_end( "cobrapilot_ai" );

	return theTarget;
}

shootEnemyTarget_Bullets( eTarget )
{
	self endon( "death" );
	self endon( "mg_off" );
	eTarget endon( "death" );
	self endon( "gunner_new_target" );
	if ( isdefined( self.playercontrolled ) )
		self endon( "gunner_stop_firing" );

	eTargetOffset = ( 0, 0, 0 );
	if ( isdefined( eTarget.script_targetoffset_z ) )
		eTargetOffset += ( 0, 0, eTarget.script_targetoffset_z );
	else if ( isSentient( eTarget ) )
		eTargetOffset = ( 0, 0, 32 );

	self setTurretTargetEnt( eTarget, eTargetOffset );

	while ( self.health > 0 )
	{
		randomShots = randomintrange( 1, 25 );
		if ( getdvar( "cobrapilot_debug" ) == "1" )
			iprintln( "randomShots = " + randomShots );

		for ( i = 0 ; i < randomShots ; i++ )
		{
			// if the vehicle firing the bullets is the players vehicle we have to switch to the 20mm gun
			if ( isdefined( self.playercontrolled ) )
			{
				if ( ( isdefined( level._cobraWeapon ) ) && ( level._cobraWeapon.size > 0 ) )
					self setVehWeapon( level._GunnerWeapon );
			}

			self thread shootEnemyTarget_Bullets_DebugLine( self, "tag_turret", eTarget, eTargetOffset, ( 1, 1, 0 ), 0.05 );
			self fireWeapon( "tag_flash" );

			// then switch it back to the players selection after the shots are fired
			if ( isdefined( self.playercontrolled ) )
				self setVehWeapon( level._cobraWeapon[ self.pilot.currentWeapon ].v[ "weapon" ] );

			wait 0.05;
		}

		wait randomFloatRange( 0.25, 2.5 );
	}
}

shootEnemyTarget_Bullets_DebugLine( eStartEnt, eStartEntTag, eTarget, eTargetOffset, color, timer )
{
	if ( getdvar( "cobrapilot_debug" ) != "1" )
		return;

	if ( !isdefined( color ) )
		color = ( 0, 0, 0 );

	eTarget endon( "death" );
	self endon( "gunner_new_target" );

	assert( isdefined( eStartEntTag ) );

	if ( !isdefined( eTargetOffset ) )
		eTargetOffset = ( 0, 0, 0 );

	if ( isdefined( timer ) )
	{
		timer = gettime() + ( timer * 1000 );
		while ( gettime() < timer )
		{
			line( eStartEnt getTagOrigin( eStartEntTag ), eTarget.origin + eTargetOffset, color );
			wait 0.05;
		}
	}
	else
	{
		for ( ;; )
		{
			line( eStartEnt getTagOrigin( eStartEntTag ), eTarget.origin + eTargetOffset, color );
			wait 0.05;
		}
	}
}

attachMissiles( weapon1, weapon2, weapon3, weapon4 )
{
	self.hasAttachedWeapons = true;
	assert( isdefined( weapon1 ) );
	weapon = [];
	weapon[ 0 ] = weapon1;
	if ( isdefined( weapon2 ) )
		weapon[ 1 ] = weapon2;
	if ( isdefined( weapon3 ) )
		weapon[ 2 ] = weapon3;
	if ( isdefined( weapon4 ) )
		weapon[ 3 ] = weapon4;

	/*
	for( i = 0 ; i < weapon.size ; i++ )
	{
		for( k = 0 ; k < level.cobra_weapon_tags[weapon[i]].size ; k++ )
		{
			self attach( level.cobra_missile_models[weapon[i]], level.cobra_weapon_tags[weapon[i]][k] );
		}
	}
	*/

	for ( i = 0 ; i < weapon.size ; i++ )
	{
		for ( k = 0 ; k < level._cobra_weapon_tags[ weapon[ i ] ].size ; k++ )
		{
			self attach( level._cobra_missile_models[ weapon[ i ] ], level._cobra_weapon_tags[ weapon[ i ] ][ k ] );
		}
	}
}

fire_missile( sMissileType, iShots, eTarget, fDelay )
{
	self endon( "death" );
	self endon( "delete" );

	if ( !isdefined( iShots ) )
		iShots = 1;
	assert( self.health > 0 );

	weaponName = undefined;
	weaponShootTime = undefined;
	defaultWeapon = "cobra_20mm";
	tags = [];
	switch( sMissileType )
	{
		case "f15_missile":
			weaponName = "cobra_Sidewinder";
			tags[ 0 ] = "le_side_wing_jnt";
			tags[ 1 ] = "ri_side_wing_jnt";
			break;
		case "mi28_seeker":
			weaponName = "cobra_seeker";
			tags[ 0 ] = "tag_store_L_1_a";
			tags[ 1 ] = "tag_store_R_1_a";
			tags[ 2 ] = "tag_store_L_2_a";
			tags[ 3 ] = "tag_store_R_2_a";
			break;
		case "ffar":
			weaponName = "cobra_FFAR";
			tags[ 0 ] = "tag_store_r_2";
			break;
		case "seeker":
			weaponName = "cobra_seeker";
			tags[ 0 ] = "tag_store_r_2";
			break;
		case "ffar_bog_a_lite":
			weaponName = "cobra_FFAR_bog_a_lite";
			tags[ 0 ] = "tag_store_r_2";
			break;
		case "ffar_airlift":
			weaponName = "cobra_FFAR_airlift";
			tags[ 0 ] = "tag_store_L_wing";
			tags[ 1 ] = "tag_store_R_wing";
			break;
		case "ffar_airlift_nofx":
			weaponName = "cobra_FFAR_airlift_nofx";
			tags[ 0 ] = "tag_store_L_wing";
			tags[ 1 ] = "tag_store_R_wing";
			break;
		case "cobra_zippy":
			weaponName = "zippy_rockets";
			tags[ 0 ] = "tag_store_L_wing";
			tags[ 1 ] = "tag_store_R_wing";
			break;
		case "cobra_turret":
			weaponName = "hind_turret_penetration";
			tags[ 0 ] = "tag_store_L_wing";
			tags[ 1 ] = "tag_store_R_wing";
			break;
		case "ffar_hind":
			defaultWeapon = "hind_turret";
			weaponName = "hind_FFAR";
			tags[ 0 ] = "tag_missile_left";
			tags[ 1 ] = "tag_missile_right";
			break;
		case "hind_zippy":
			defaultWeapon = "hind_turret";
			weaponName = "zippy_rockets";
			tags[ 0 ] = "tag_missile_left";
			tags[ 1 ] = "tag_missile_right";
			break;
		case "ffar_hind_nodamage":
			defaultWeapon = "hind_turret";
			weaponName = "hind_FFAR_nodamage";
			tags[ 0 ] = "tag_missile_left";
			tags[ 1 ] = "tag_missile_right";
			break;
		case "ffar_mi28_village_assault":
			defaultWeapon = "hind_turret";
			weaponName = "mi28_ffar_village_assault";
			tags[ 0 ] = "tag_store_L_2_a";
			tags[ 1 ] = "tag_store_R_2_a";
			tags[ 2 ] = "tag_store_L_2_b";
			tags[ 3 ] = "tag_store_R_2_b";
			tags[ 4 ] = "tag_store_L_2_c";
			tags[ 5 ] = "tag_store_R_2_c";
			tags[ 6 ] = "tag_store_L_2_d";
			tags[ 7 ] = "tag_store_R_2_d";
			break;
		case "ffar_co_rescue":
			weaponName = "cobra_FFAR_bog_a_lite";
			tags[ 0 ] = "tag_store_R_2_a";
			tags[ 1 ] = "tag_store_L_2_a";
			break;
		default:
			assertMsg( "Invalid missile type specified." );
			break;
	}
	assert( isdefined( weaponName ) );
	assert( tags.size > 0 );

	weaponShootTime = weaponfiretime( weaponName );
	assert( isdefined( weaponShootTime ) );

	nextMissileTag = -1;
	for ( i = 0 ; i < iShots ; i++ )
	{
		nextMissileTag++ ;
		if ( nextMissileTag >= tags.size )
			nextMissileTag = 0;

		if ( sMissileType == "ffar_mi28_village_assault" )
		{
			if ( isdefined( eTarget ) && isdefined( eTarget.origin ) )
			{
				magicBullet( weaponName, self getTagOrigin( tags[ nextMissileTag ] ), eTarget.origin );
				if ( isdefined( level._effect[ "ffar_mi28_muzzleflash" ] ) )
					playfxontag( getfx( "ffar_mi28_muzzleflash" ), self, tags[ nextMissileTag ] );
				thread delayed_earthquake( 0.1, 0.5, 0.2, eTarget.origin, 1600 );
			}
		}
		else
		{
			self setVehWeapon( weaponName );
			if ( isdefined( eTarget ) )
			{
				eMissile = self fireWeapon( tags[ nextMissileTag ], eTarget );
				if ( sMissileType == "ffar" )
					eMissile thread missileLoseTarget( 0.1 );
				if ( sMissileType == "ffar_bog_a_lite" )
					eMissile thread missileLoseTarget( 0.1 );
				if ( sMissileType == "ffar_airlift" )
					eMissile thread missileLoseTarget( 0.1 );
			}
			else
				eMissile = self fireWeapon( tags[ nextMissileTag ] );
		}

		if ( i < iShots - 1 )
			wait weaponShootTime;

		if ( isdefined( fDelay ) )
			wait( fDelay );
	}

	self setVehWeapon( defaultWeapon );
}

delayed_earthquake( fDelay, scale, duration, source, fRadius )
{
	wait fDelay;
	earthquake( scale, duration, source, fRadius );
}

missileLoseTarget( fDelay )
{
	self endon( "death" );
	wait fDelay;
	if ( isdefined( self ) )
		self Missile_ClearTarget();
}
