/*
	_harrier modded
	Author: INeedGames
	Date: 09/26/2020
	Uses the harrier duration, and fixes harrier leaving on custom maps.
*/

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

/******************************************************************* 
//						_harrier.gsc  
//	
//	Holds all the harrier specific functions
//	
//	Jordan Hirsh	Dec. 18th 	2008
********************************************************************/

beginHarrier( lifeId, startPoint, pos )
{
	heightEnt = GetEnt( "airstrikeheight", "targetname" );
	
	if ( isDefined( heightEnt ) )
		trueHeight = heightEnt.origin[2];
	else if( isDefined( level.airstrikeHeightScale ) )
		trueHeight = 850 * level.airstrikeHeightScale;
	else
		trueHeight = 850;
	
	pos *= (1,1,0);
	pathGoal = pos + (0,0, trueHeight );
	
	harrier = self spawnDefensiveHarrier( lifeId, self, startPoint, pathGoal );
	harrier.pathGoal = pathGoal;

	return harrier;
}

getCorrectHeight( x, y, rand )
{
	offGroundHeight = 1200;
	groundHeight = self traceGroundPoint(x,y);
	trueHeight = groundHeight + offGroundHeight;
	
	if( isDefined( level.airstrikeHeightScale ) && trueHeight < ( 850 * level.airstrikeHeightScale ) )
		trueHeight = ( 950 * level.airstrikeHeightScale );
	
	trueHeight += RandomInt( rand );
	
	return trueHeight;
}

spawnDefensiveHarrier( lifeId, owner, pathStart, pathGoal )
{
	forward = vectorToAngles( pathGoal - pathStart );

	if ( owner.team == "allies" )
		harrier = spawnHelicopter( owner, pathStart, forward, "harrier_mp" , "vehicle_av8b_harrier_jet_mp" );
	else
		harrier = spawnHelicopter( owner, pathStart, forward, "harrier_mp" , "vehicle_av8b_harrier_jet_opfor_mp" );
		
	if ( !isDefined( harrier ) )
		return;

	harrier addToHeliList();
	harrier thread removeFromHeliListOnDeath();

	harrier.speed = 250;
	harrier.accel = 175;
	harrier.health = 3000; 
	harrier.maxhealth = harrier.health;
	harrier.team = owner.team;
	harrier.owner = owner;
	harrier setCanDamage( true );
	harrier.owner = owner;
	harrier thread harrierDestroyed();
	harrier SetMaxPitchRoll( 0, 90 );		
	harrier Vehicle_SetSpeed( harrier.speed, harrier.accel );
	harrier thread playHarrierFx();
	harrier setdamagestage( 3 );
	harrier.missiles = 6;
	harrier.pers["team"] = harrier.team;
	harrier SetHoverParams( 50, 100, 50 );
	harrier setTurningAbility( 0.05 );
	harrier setYawSpeed(45,25,25,.5);
	harrier.defendLoc = pathGoal;
	harrier.lifeId = lifeId;
	
	harrier.damageCallback = ::Callback_VehicleDamage;
	
	level.harriers = remove_undefined_from_array( level.harriers );
	
	level.harriers[level.harriers.size] = harrier;
	
	return harrier;
}

defendLocation( harrier )
{
	harrier endon( "death" );
	assert ( isDefined( harrier ) );
	
	harrier thread harrierTimer();
	
	harrier setVehGoalPos( harrier.pathGoal, 1 );
	harrier thread closeToGoalCheck( harrier.pathGoal );
	
	harrier waittill ( "goal" );
	harrier stopHarrierWingFx();
	harrier engageGround();
}

closeToGoalCheck( pathGoal )
{
	self endon( "goal" );
	self endon( "death" );
	
	for( ;; )
	{
		if ( distance2d( self.origin, pathGoal  ) < 768 )
		{
			self SetMaxPitchRoll( 45, 25 );	
			break;
		}
		
		wait .05;
	}
}

engageGround()
{ 
	self notify( "engageGround" ); 
	self endon("engageGround");
	self endon("death");

	self thread harrierGetTargets();
	self thread randomHarrierMovement();
	
	pathGoal = self.defendLoc;

	self Vehicle_SetSpeed( 15, 5 );
	self setVehGoalPos( pathGoal, 1 );
	self waittill ( "goal" );
}

forceLeaveAfterTime(time)
{
	self endon( "death" );

	wait time;

	self.force_harrier_leave = true;
}

harrierLeave()
{
	self endon( "death" );
	
	self SetMaxPitchRoll( 0, 0 );
	self notify( "leaving" );
	self breakTarget( true );
	self notify("stopRand");

	self thread forceLeaveAfterTime(5);
	
	for ( ;; )
	{
		self Vehicle_SetSpeed( 35, 25 );
		pathGoal = self.origin + ( vector_multiply( anglestoforward( (0,RandomInt(360),0) ), 500 ) );
		pathGoal += ( 0,0,900);
		
		leaveTrace = BulletTrace(self.origin, self.origin+(0,0,900), false, self );
		if( leaveTrace["surfacetype"] == "none" || isDefined(self.force_harrier_leave) )
			break;
		
		wait( 0.10 );
	}
	
	self setVehGoalPos( pathGoal, 1 );
	self thread startHarrierWingFx();
	self waittill ( "goal" );
	self playSound( "harrier_fly_away" );
	pathEnd = self getPathEnd(); 
	self Vehicle_SetSpeed( 250, 75 );
	self setVehGoalPos( pathEnd, 1 );
	self waittill ( "goal" );
	
	level.airPlane[level.airPlane.size - 1] = undefined; 

	self notify ( "harrier_gone" );
	self thread harrierDelete();
}


harrierDelete()
{
	self delete();
}

harrierTimer()
{
	self endon( "death" );
	
	maps\mp\gametypes\_hostmigration::waitLongDurationWithHostMigrationPause( level.harrierDuration );
	self harrierLeave();
}

randomHarrierMovement()
{
	self notify( "randomHarrierMovement" ); 
	self endon("randomHarrierMovement");
	
	self endon("stopRand");
	self endon("death");
	self endon( "acquiringTarget" );
	self endon( "leaving" );
	
	pos = self.defendloc;
	
	for ( ;; )
	{
		newpos =  self GetNewPoint(self.origin); //crazy blocking call
		self setVehGoalPos( newpos, 1 );
		self waittill ("goal");	
		wait( randomIntRange( 3, 6) );
		self notify( "randMove" );
	}
}

getNewPoint( pos, targ )
{
	self endon("stopRand");
	self endon("death");
	self endon( "acquiringTarget" );
	self endon( "leaving" );
	
	if ( !isDefined( targ ) )
	{
		enemyPoints = [];
		
		foreach( player in level.players )
		{
			if ( player == self )
				continue;
			
			if ( !level.teambased || player.team != self.team )
				enemyPoints[enemyPoints.size] = player.origin;
		}
		
		if ( enemyPoints.size > 0 )
		{
			gotoPoint = AveragePoint( enemyPoints );
			
			pointX = gotoPoint[0];
			pointY = gotoPoint[1];
		}	
		else
		{
			center = level.mapCenter;
			movementDist = ( level.mapSize / 6 ) - 200; 
		
			pointX = RandomFloatRange( center[0]-movementDist, center[0]+movementDist );
			pointY = RandomFloatRange( center[1]-movementDist, center[1]+movementDist );
		}
		
		newHeight = self getCorrectHeight( pointX, PointY, 20 );
	}
	else
	{
		if( coinToss() )
		{
			directVector = self.origin - self.bestTarget.origin;
			pointX = directVector[0];
			pointY = directVector[1] * -1;
			newHeight = self getCorrectHeight( pointX, PointY, 20 );
			perpendicularVector = ( pointY,pointX,newHeight );
		
			if ( distance2D( self.origin, perpendicularVector ) > 1200 )
			{
				pointY *= .5;
				pointX *= .5;	
				perpendicularVector = ( pointY,pointX,newHeight );
			}
		}
		else
		{	
			if ( distance2D( self.origin, self.bestTarget.origin ) < 200 )
				return;
			
			yaw = self.angles[1];	
			direction = (0,yaw,0);
			moveToPoint = self.origin + vector_multiply( anglestoforward( direction ), randomIntRange( 200, 400 ) );
			newHeight = self getCorrectHeight( moveToPoint[0], moveToPoint[1], 20 );
			
			pointX = moveToPoint[0];
			pointY = moveToPoint[1];
		}
	}
	for ( ;; )
	{
		point =  traceNewPoint( pointX, PointY, newHeight );
		
		if ( point != 0 )
			return point;
			
		pointX = RandomFloatRange( pos[0]-1200, pos[0]+1200 );
		pointY = RandomFloatRange( pos[1]-1200, pos[1]+1200 );
		newHeight = self getCorrectHeight( pointX, PointY, 20 );
	}
}	

traceNewPoint(x,y,z)
{
	self endon("stopRand");
	self endon("death");
	self endon( "acquiringTarget" );
	self endon( "leaving" );
	self endon( "randMove" );
	
	for( i = 1 ; i <= 10 ; i++ )
	{
		
		switch( i )
		{
			case 1:
				trc = BulletTrace( self.origin, (x,y,z), false, self );
				break;
			case 2:
				trc = BulletTrace( (self getTagOrigin( "tag_left_wingtip" )), (x,y,z), false, self );
				//self thread drawLine( (self getTagOrigin( "tag_left_wingtip" )), (x,y,z), 4 );
				break;
			case 3:
				trc = BulletTrace( (self getTagOrigin( "tag_right_wingtip" )), (x,y,z), false, self );
				//self thread drawLine( (self getTagOrigin( "tag_right_wingtip" )), (x,y,z), 4 );
				break;
			case 4:
				trc = BulletTrace( (self getTagOrigin( "tag_engine_left2" )), (x,y,z), false, self );
				//self thread drawLine( (self getTagOrigin( "tag_engine_left2" )), (x,y,z), 4 );
				break;
			case 5:
				trc = BulletTrace( (self getTagOrigin( "tag_engine_right2" )), (x,y,z), false, self );
				//self thread drawLine( (self getTagOrigin( "tag_engine_right2" )), (x,y,z), 4 );
				break;
			case 6:
				trc = BulletTrace( (self getTagOrigin( "tag_right_alamo_missile" )), (x,y,z), false, self );
				//self thread drawLine( (self getTagOrigin( "tag_right_alamo_missile" )), (x,y,z), 4 );
				break;
			case 7:
				trc = BulletTrace( (self getTagOrigin( "tag_left_alamo_missile" )), (x,y,z), false, self );
				//self thread drawLine( (self getTagOrigin( "tag_left_alamo_missile" )), (x,y,z), 4 );
				break;
			case 8:
				trc = BulletTrace( (self getTagOrigin( "tag_right_archer_missile" )), (x,y,z), false, self );
				//self thread drawLine( (self getTagOrigin( "tag_right_archer_missile" )), (x,y,z), 4 );
				break;
			case 9:
				trc = BulletTrace( (self getTagOrigin( "tag_left_archer_missile" )), (x,y,z), false, self );
				//self thread drawLine( (self getTagOrigin( "tag_left_archer_missile" )), (x,y,z), 4 );
				break;
			case 10:
				trc = BulletTrace( (self getTagOrigin( "tag_light_tail" )), (x,y,z), false, self );
				//self thread drawLine( (self getTagOrigin( "tag_light_tail" )), (x,y,z), 4 );
				break;
			default:
				trc = BulletTrace( self.origin, (x,y,z), false, self );
		}
		
		if ( trc["surfacetype"] != "none" )
		{	
			return 0;
		}
		
		wait(0.05);		
	}
	
	pathGoal = ( x, y, z );
	return pathGoal;
}


traceGroundPoint(x,y)
{
	self endon("death");
	self endon( "acquiringTarget" );
	self endon( "leaving" );
	
	highTrace = -9999999;
	lowTrace = 9999999;
	z = -9999999;
	highz = self.origin[2];
	trace = undefined;
	lTrace = undefined;
	
	for( i = 1 ; i <= 5 ; i++ )
	{
		
		switch( i )
		{
			case 1:
				trc = BulletTrace( (x,y,highz), (x,y,z), false, self );
				//self thread drawLine( ( x,y,highz ), (x,y,z), 4 );
				break;
			case 2:
				trc = BulletTrace( (x+20,y+20,highz), (x+20,y+20,z), false, self );
				//self thread drawLine( ( x+20,y+20,highz ), (x+20,y+20,z), 4 );
				break;
			case 3:
				trc = BulletTrace( (x-20,y-20,highz), (x-20,y-20,z), false, self );
				//self thread drawLine( ( x-20,y-20,highz ), (x-20,y-20,z), 4 );
				break;
			case 4:
				trc = BulletTrace( (x+20,y-20,highz), (x+20,y-20,z), false, self );
				//self thread drawLine( ( x+20,y-20,highz ), (x+20,y-20,z), 4 );
				break;
			case 5:
				trc = BulletTrace( (x-20,y+20,highz), (x-20,y+20,z), false, self );
				//self thread drawLine( ( x-20,y+20,highz ), (x-20,y+20,z), 4 );
				break;	
			default:
				trc = BulletTrace( self.origin, (x,y,z), false, self );
		}
		
		if ( trc["position"][2] > highTrace )
		{
			highTrace = trc["position"][2];
			trace = trc;
		}
		else if ( trc["position"][2] < lowTrace )
		{
			lowTrace = trc["position"][2];
			lTrace = trc;
		}
		
		wait(0.05);		
	}
	
	//thread drawLine( self.origin, lTrace["position"], 5, (0,1,0) );
	//thread drawLine( self.origin, trace["position"], 5, (1,0,0) );
	
	return highTrace;
}


playHarrierFx()
{
	self endon ( "death" );

	wait( 0.2 );
	playfxontag( level.fx_airstrike_contrail, self, "tag_right_wingtip" );	
	playfxontag( level.fx_airstrike_contrail, self, "tag_left_wingtip" );
	wait( 0.2 );
	playfxontag( level.harrier_afterburnerfx, self, "tag_engine_right" );
	playfxontag( level.harrier_afterburnerfx, self, "tag_engine_left" );
	wait( 0.2 );
	playfxontag( level.harrier_afterburnerfx, self, "tag_engine_right2" );
	playfxontag( level.harrier_afterburnerfx, self, "tag_engine_left2" );
	wait( 0.2 );
	playFXOnTag( level.chopper_fx["light"]["left"], self, "tag_light_L_wing" );
	wait ( 0.2 );
	playFXOnTag( level.chopper_fx["light"]["right"], self, "tag_light_R_wing" );
	wait ( 0.2 );
	playFXOnTag( level.chopper_fx["light"]["belly"], self, "tag_light_belly" );
	wait ( 0.2 );
	playFXOnTag( level.chopper_fx["light"]["tail"], self, "tag_light_tail" );
	
}

stopHarrierWingFx()
{
	stopfxontag( level.fx_airstrike_contrail, self, "tag_right_wingtip" );
	stopfxontag( level.fx_airstrike_contrail, self, "tag_left_wingtip" );
}

startHarrierWingFx()
{
	wait ( 3.0);
	
	if ( !isDefined( self ) )
		return;
		
	playfxontag( level.fx_airstrike_contrail, self, "tag_right_wingtip" );
	playfxontag( level.fx_airstrike_contrail, self, "tag_left_wingtip" );
}

getPathStart( coord )
{
	pathRandomness = 100;
	harrierHalfDistance = 15000;
	harrierFlyHeight = 850;

	yaw = randomFloat( 360 );	
	direction = (0,yaw,0);

	startPoint = coord + vector_multiply( anglestoforward( direction ), -1 * harrierHalfDistance );
	startPoint += ( (randomfloat(2) - 1)*pathRandomness, (randomfloat(2) - 1)*pathRandomness, 0 );
	
	return startPoint;
}

getPathEnd()
{
	pathRandomness = 150;
	harrierHalfDistance = 15000;
	harrierFlyHeight = 850;

	yaw = self.angles[1];	
	direction = (0,yaw,0);

	endPoint = self.origin + vector_multiply( anglestoforward( direction ), harrierHalfDistance );
	return endPoint;
}

fireOnTarget( facingTolerance, zOffset )
{
	self endon("leaving");
	self endon("stopfiring");
	self endon("explode");
	self endon("death");
	self.bestTarget endon( "death" );
	
	acquiredTime = getTime();
	missileTime = getTime();
	missileReady = false;
	
	self setVehWeapon( "harrier_20mm_mp" );
	
	if ( !isDefined( zOffset ) )
		zOffset = 50;

	for ( ;; )
	{
		if ( self isReadyToFire( facingTolerance ) )
			break;
		else
			wait ( .25 );
	} 
	self SetTurretTargetEnt( self.bestTarget, ( 0,0,50 ) );
	
	numShots = 25;
	
	for ( ;; )
	{
		if ( numShots == 25 )
			self playLoopSound( "weap_cobra_20mm_fire_npc" );
				
		numShots--;
		self FireWeapon( "tag_flash", self.bestTarget, (0,0,0), .05 );
		wait ( .10);
		
		if ( numShots <= 0 )
		{
			self stopLoopSound();
			wait (1);
			numShots = 25;
		}
	}
}

isReadyToFire( tolerance )
{
	self endon( "death" );
	self endon( "leaving" );
	
	if (! isdefined(tolerance) )
		tolerance = 10;
	
	harrierForwardVector = anglesToForward( self.angles );
	harrierToTarget = self.bestTarget.origin - self.origin;
	harrierForwardVector *= (1,1,0);
	harrierToTarget *= (1,1,0 );
	
	harrierToTarget = VectorNormalize( harrierToTarget );
	harrierForwardVector = VectorNormalize( harrierForwardVector );
	
	targetCosine = VectorDot( harrierToTarget, harrierForwardVector );
	facingCosine = Cos( tolerance );

	if ( targetCosine >= facingCosine )
		return true;
	else
		return false;
}

acquireGroundTarget( targets )
{
	self endon( "death" );
	self endon( "leaving" );

	if ( targets.size == 1 )
		self.bestTarget = targets[0];
	else
		self.bestTarget = self getBestTarget( targets );
	
	self backToDefendLocation( false );
	
	self notify( "acquiringTarget" );
	
	self SetTurretTargetEnt( self.bestTarget );
	self SetLookAtEnt( self.bestTarget );
	
	newpos =  self GetNewPoint(self.origin, true);
	self setVehGoalPos( newpos, 1 );
		
	self thread watchTargetDeath();
	self thread watchTargetLOS();
	
	self setVehWeapon( "harrier_20mm_mp" );
	self thread fireOnTarget(); // fires on current target.
}

backToDefendLocation( forced )
{
	self setVehGoalPos( self.defendloc, 1 );
	
	if ( isDefined( forced ) && forced )
		self waittill ( "goal" );
}


wouldCollide( destination )
{
	trace = BulletTrace( self.origin, destination, true, self );
	
	if ( trace["position"] == destination )
		return false;
	else
		return true;
}

watchTargetDeath()
{
	self notify( "watchTargetDeath" );
	self endon( "watchTargetDeath" );
	self endon( "newTarget" );
	
	self endon( "death" );
	self endon( "leaving" );

	self.bestTarget waittill( "death" );
	self thread breakTarget();
}

watchTargetLOS( tolerance )
{	
	self endon( "death" );
	self.bestTarget endon( "death" );
	self.bestTarget endon( "disconnect" );
	self endon( "leaving" );
	self endon( "newTarget" );
	lostTime = undefined;
	
	if ( !isDefined( tolerance ) )
		tolerance = 1000;
	
	for ( ;; )
	{
		if ( !isTarget( self.bestTarget ) )
		{
			self thread breakTarget();
			return;	
		}	
		
		if ( !isDefined( self.bestTarget ) )//hack to cover host migration vehicle targets
		{
			self thread breakTarget();
			return;	
		}
		
		if ( self.bestTarget sightConeTrace( self.origin, self ) < 1 )
		{		
			if ( !isDefined(lostTime) )
				lostTime = getTime();
			
			if ( getTime() - lostTime > tolerance )
			{
				self thread breakTarget();
				return;
			}
		}	
		else
		{
			lostTime = undefined;
		}
		
		wait( .25 );
	}
}

breakTarget( noNewTarget )
{
	self endon( "death" );
	
	self ClearLookAtEnt();
	self stopLoopSound();
	self notify("stopfiring");
	
	if ( isDefined(noNewTarget) && noNewTarget )
 		return;
 	
 	self thread randomHarrierMovement();
 	self notify( "newTarget" );
 	self thread harrierGetTargets();
	
}

harrierGetTargets()
{
	self notify( "harrierGetTargets" ); 
	self endon("harrierGetTargets");
	
	self endon( "death" );
	self endon( "leaving" );
	targets = [];
	
	for ( ;; )
	{
		targets = [];
		players = level.players;
		
		if ( isDefined( level.chopper ) && level.chopper.team != self.team && isAlive( level.chopper ) )
		{	
			if ( !isDefined( level.chopper.nonTarget ) || ( isDefined( level.chopper.nonTarget ) && !level.chopper.nonTarget )  )
			{
					self thread engageVehicle( level.chopper );
					return;
			}
			else
			{
				backToDefendLocation( true );		
			}
		}
			
		for (i = 0; i < players.size; i++)
		{
			potentialTarget = players[i];
			if ( isTarget( potentialTarget ) )
			{
				if( isdefined( players[i] ) )
					targets[targets.size] = players[i];
			}
			else
				continue;
			
			wait( .05 );
		}
		if ( targets.size > 0 )
		{
			self acquireGroundTarget( targets );
			return;
		}
		wait( 1 );
	}
}

isTarget( potentialTarget )
{
	self endon( "death" );
	
	if ( !isalive( potentialTarget ) || potentialTarget.sessionstate != "playing" )
		return false;
		
	if ( isDefined( self.owner ) && potentialTarget == self.owner )
		return false;
	
	if ( distance( potentialTarget.origin, self.origin ) > 8192 )
		return false;
	
	if ( Distance2D( potentialTarget.origin , self.origin ) < 768 )
		return false;
	
	if ( !isdefined( potentialTarget.pers["team"] ) )
		return false;
	
	if ( level.teamBased && potentialTarget.pers["team"] == self.team )
		return false;
	
	if ( potentialTarget.pers["team"] == "spectator" )
		return false;
	
	if ( isdefined( potentialTarget.spawntime ) && ( gettime() - potentialTarget.spawntime )/1000 <= 5 )
		return false;

	if ( potentialTarget _hasPerk( "specialty_coldblooded" ) )
		return false;
	
	harrier_centroid = self.origin + ( 0, 0, -160 );
	harrier_forward_norm = anglestoforward( self.angles );
	harrier_turret_point = harrier_centroid + 144 * harrier_forward_norm;
	harrier_canSeeTarget = potentialTarget sightConeTrace( self.origin, self );
	
	if ( harrier_canSeeTarget < 1 )
		return false;	
	
	return true;
}

getBestTarget( targets )
{
	self endon( "death" );
	mainGunPointOrigin = self getTagOrigin( "tag_flash" );
	harrierOrigin = self.origin;
	harrier_forward_norm = anglestoforward( self.angles );
	
	bestYaw = undefined;
	bestTarget = undefined;
	targetHasRocket = false;
	
	foreach ( targ in targets )
	{
		angle = abs ( vectorToAngles ( ( targ.origin - self.origin ) )[1] );
		noseAngle = abs( self getTagAngles( "tag_flash" )[1] );
		angle = abs ( angle - noseAngle );			
		
		// in this calculation having a rocket removes 40d of rotation cost from best target calculation
		// to prioritize targeting dangerous targets.
		weaponsArray = targ GetWeaponsListItems();
		foreach ( weapon in weaponsArray )
		{
			if ( isSubStr( weapon, "at4" ) || isSubStr( weapon, "stinger" ) || isSubStr( weapon, "jav" ) )
				angle -= 40;
		}
		
		if ( Distance( self.origin, targ.origin ) > 2000 )
			angle += 40;
				
		if ( !isDefined( bestYaw ) )
		{				
			bestYaw = angle;
			bestTarget = targ;
		} 
		else if ( bestYaw > angle )
		{
			bestYaw = angle;
			bestTarget = targ;			
		}
	}
	
	return ( bestTarget );
}

fireMissile( missileTarget )
{
	self endon( "death" );
	self endon( "leaving" );
	
	assert( self.health > 0 );
	
	if ( self.missiles <= 0 )
		return;
	
	friendlyInRadius = self checkForFriendlies( missileTarget, 256 );
	
	if ( !isdefined( missileTarget ) )
		return;
		
	if ( Distance2D(self.origin, missileTarget.origin ) < 512 )
		return;
	
	if ( isDefined ( friendlyInRadius ) && friendlyInRadius )
		return;

	self.missiles--;
	self setVehWeapon( "harrier_FFAR_mp" );
	
	if ( isDefined( missileTarget.targetEnt ) )
		missile = self fireWeapon( "tag_flash", missileTarget.targetEnt, (0,0,-250) );
	else
		missile = self fireWeapon( "tag_flash", missileTarget, (0,0,-250) );
		
	missile Missile_SetFlightmodeDirect();
	missile Missile_SetTargetEnt( missileTarget );
}

checkForFriendlies( missileTarget, radiusSize )
{
	self endon( "death" );
	self endon( "leaving" );
	
	targets = [];
	players = level.players;
	strikePosition = missileTarget.origin;
	
	for (i = 0; i < players.size; i++)
	{
		potentialCollateral = players[i];
	
		if ( potentialCollateral.team != self.team )
			continue;
		
		potentialPosition = potentialCollateral.origin;
		
		if ( distance2D( potentialPosition, strikePosition ) < 512 )
			return true;
	}
	return false;
}

///-------------------------------------------------------
//
//		Health Functions
//
///------------------------------------------------------


Callback_VehicleDamage( inflictor, attacker, damage, dFlags, meansOfDeath, weapon, point, dir, hitLoc, timeOffset, modelIndex, partName )
{
	if ( ( attacker == self || ( isDefined( attacker.pers ) && attacker.pers["team"] == self.team ) && level.teamBased ) && ( attacker != self.owner ) )
		return;
	
	if ( self.health <= 0 )
		return;
	
	switch ( weapon )
	{
		case "ac130_105mm_mp":
		case "ac130_40mm_mp":
		case "stinger_mp":
		case "javelin_mp":
		case "remotemissile_projectile_mp":
			self.largeProjectileDamage = true;
			damage = self.maxhealth + 1;
			break;
		case "rpg_mp":
		case "at4_mp":
			self.largeProjectileDamage = true;
			damage = self.maxhealth - 900;
			break;
		default:
			if ( weapon != "none" )
				damage = Int(damage/2);
			self.largeProjectileDamage = false;
			break;
	}
	
	attacker maps\mp\gametypes\_damagefeedback::updateDamageFeedback( "" );
	
	if ( isPlayer( attacker ) && attacker _hasPerk( "specialty_armorpiercing" ) )
	{
		damageAdd = int( damage*level.armorPiercingMod );
		damage += damageAdd;
	}
	
	if ( self.health <= damage )
	{
		if ( isPlayer( attacker ) && (!isDefined(self.owner) || attacker != self.owner) )
		{
			thread teamPlayerCardSplash( "callout_destroyed_harrier", attacker );
			attacker thread maps\mp\gametypes\_rank::giveRankXP( "kill", 300 );
			thread maps\mp\gametypes\_missions::vehicleKilled( self.owner, self, undefined, attacker, damage, meansOfDeath );
			attacker notify( "destroyed_killstreak" );
		}
	
		self notify("death"); 
	}
	
	if ( self.health - damage <= 900 && ( !isDefined( self.smoking ) || !self.smoking ) )
	{
		self thread playDamageEfx();
		self.smoking = true;		
	}
	
	self Vehicle_FinishDamage( inflictor, attacker, damage, dFlags, meansOfDeath, weapon, point, dir, hitLoc, timeOffset, modelIndex, partName );
}

playDamageEfx()
{
	self endon( "death" );
	
	stopFxOnTag( level.harrier_afterburnerfx, self, "tag_engine_left" );
	playFxOnTag( level.harrier_smoke, self, "tag_engine_left" );
	
	stopFxOnTag( level.harrier_afterburnerfx, self, "tag_engine_right" );
	playFxOnTag( level.harrier_smoke, self, "tag_engine_right" );
	wait( 0.15 );
	
	stopFxOnTag( level.harrier_afterburnerfx, self, "tag_engine_left2" );
	playFxontag( level.harrier_smoke, self, "tag_engine_left2" );
		
	stopFxOnTag( level.harrier_afterburnerfx, self, "tag_engine_right2" );
	playFxontag( level.harrier_smoke, self, "tag_engine_right2" );
	playFxOnTag( level.chopper_fx["damage"]["heavy_smoke"], self, "tag_engine_left" );
}

harrierDestroyed()
{
	self endon( "harrier_gone" );
	
	self waittill( "death" );
	
	if (! isDefined(self) )
		return;

	if ( !isDefined( self.largeProjectileDamage ) )
	{
		self Vehicle_SetSpeed( 25, 5 );
		self thread harrierSpin( RandomIntRange(180, 220) );
		
		wait( RandomFloatRange( .5, 1.5 ) );
	}

	harrierExplode();
}

// crash explosion
harrierExplode()
{
	self playSound( "harrier_jet_crash" );
	level.airPlane[level.airPlane.size - 1] = undefined; 

	deathAngles = self getTagAngles( "tag_deathfx" );		
	playFx( level.harrier_deathfx, self getTagOrigin( "tag_deathfx" ), anglesToForward( deathAngles ), anglesToUp( deathAngles ) );

	self notify ( "explode" );

	wait ( 0.05 );

	self thread harrierDelete();
}


harrierSpin( speed )
{
	self endon( "explode" );
	
	playfxontag( level.chopper_fx["explode"]["medium"], self, "tag_origin" );
	
	self setyawspeed( speed, speed, speed );
	while ( isdefined( self ) )
	{
		self settargetyaw( self.angles[1]+(speed*0.9) );
		wait ( 1 );
	}
}

engageVehicle( vehTarget )
{
	vehTarget endon("death");
	vehTarget endon("leaving");
	vehTarget endon("crashing");
	self endon("death");
	
		self acquireVehicleTarget( vehTarget );

		self thread fireOnVehicleTarget();
}

fireOnVehicleTarget()
{
	self endon("leaving");
	self endon("stopfiring");
	self endon("explode");
	self.bestTarget endon ("crashing");
	self.bestTarget endon ("leaving");
	self.bestTarget endon ("death");
	
	acquiredTime = getTime();
	
	if ( isDefined( self.bestTarget ) && self.bestTarget.classname == "script_vehicle" )
	{
		self SetTurretTargetEnt( self.bestTarget );
	
		for ( ;; )
		{
			curDist = distance2D( self.origin, self.bestTarget.origin );
			
			if ( getTime() - acquiredTime >  2500 && curDist > 1000 )
			{
				self fireMissile( self.bestTarget );
				acquiredTime = getTime();
			}
			
			wait ( .10);
		}
	}
}

acquireVehicleTarget( vehTarget )
{
	self endon( "death" );
	self endon( "leaving" );
		
	self notify( "newTarget" );
	self.bestTarget = vehTarget;
	self notify( "acquiringVehTarget" );
	self SetLookAtEnt( self.bestTarget );
	self thread watchVehTargetDeath();
	self thread watchVehTargetCrash();
	
	self SetTurretTargetEnt( self.bestTarget );
}

watchVehTargetCrash()
{
	self endon( "death" );
	self endon( "leaving" );
	self.bestTarget endon ( "death" );
	self.bestTarget endon ( "drop_crate" );
	
	self.bestTarget waittill( "crashing" );
		self breakVehTarget();
}

watchVehTargetDeath()
{
	self endon( "death" );
	self endon( "leaving" );
	self.bestTarget endon ( "crashing" );
	self.bestTarget endon ( "drop_crate" );
	
	self.bestTarget waittill( "death" );
		breakVehTarget();
}

breakVehTarget()
{
	self ClearLookAtEnt();
	
	if ( isDefined( self.bestTarget ) && !isDefined( self.bestTarget.nonTarget ) )
		self.bestTarget.nonTarget = true;
	
	self notify("stopfiring");
 	self notify( "newTarget" );
 	self thread stopHarrierWingFx();
 	self thread engageGround();
}

evasiveManuverOne()
{
	self SetMaxPitchRoll( 15, 80);		
	self Vehicle_SetSpeed( 50, 100 );
	self setYawSpeed(90,30,30,.5);
	
	curOrg = self.origin;
		
	yaw = self.angles[1];	
	if( cointoss() )
		direction = (0,yaw+90,0);
	else
		direction = (0,yaw-90,0);
		
	moveToPoint = self.origin + vector_multiply( anglestoforward( direction ), 500 );
	
	self setVehGoalPos( moveToPoint, 1 );
	//println( "evasive manuver one" );
	self waittill ("goal");
}

drawLine( start, end, timeSlice, color )
{
	if( !isdefined( color ) )
		color = ( 1,1,1 );
	
	drawTime = int(timeSlice * 20);
	for( time = 0; time < drawTime; time++ )
	{
		line( start, end, color,false, 1 );
		wait ( 0.05 );
	}
}

addToHeliList()
{
	level.helis[self getEntityNumber()] = self;	
}

removeFromHeliListOnDeath()
{
	entityNumber = self getEntityNumber();

	self waittill ( "death" );

	level.helis[entityNumber] = undefined;
}