#include maps\mp\_utility;

InitStingerUsage()
{
	self.stingerStage = undefined;
	self.stingerTarget = undefined;
	self.stingerLockStartTime = undefined;
	self.stingerLostSightlineTime = undefined;
	
	self thread ResetStingerLockingOnDeath();
}


ResetStingerLocking()
{
	if ( !IsDefined( self.stingerUseEntered ) )
		return;
	self.stingerUseEntered = undefined;

	self notify( "stop_javelin_locking_feedback" );
	self notify( "stop_javelin_locked_feedback" );

	self WeaponLockFree();
	InitStingerUsage();
}


ResetStingerLockingOnDeath()
{
	self endon( "disconnect" );

	self notify ( "ResetStingerLockingOnDeath" );
	self endon ( "ResetStingerLockingOnDeath" );

	for ( ;; )
	{
		self waittill( "death" );
		self ResetStingerLocking();
	}
}


StillValidStingerLock( ent )
{
	assert( IsDefined( self ) );

	if ( !IsDefined( ent ) )
		return false;
	if ( !(self WorldPointInReticle_Circle( ent.origin, 65, 85 )) )
		return false;

	if ( IsDefined( level.ac130 ) && self.stingerTarget == level.ac130.planeModel && !isDefined( level.ac130player ) )
		return false;
	
	if ( IsDefined( level.orbitalsupport_planeModel ) && self.stingerTarget == level.orbitalsupport_planeModel && !IsDefined( level.orbitalsupport_player ) )
		return false;

	return true;
}


LoopStingerLockingFeedback()
{
	self endon( "faux_spawn" );
	self endon( "stop_javelin_locking_feedback" );

	for ( ;; )
	{
		if ( isDefined( level.chopper ) && isDefined( level.chopper.gunner ) && isDefined( self.stingerTarget ) && self.stingerTarget == level.chopper.gunner )
			level.chopper.gunner playLocalSound( "missile_locking" );

		if ( isDefined( level.ac130player ) && isDefined( self.stingerTarget ) && self.stingerTarget == level.ac130.planeModel )
			level.ac130player playLocalSound( "missile_locking" );
		
		self playLocalSound( "stinger_locking" );
		self PlayRumbleOnEntity( "ac130_25mm_fire" );

		wait 0.6;
	}
}


LoopStingerLockedFeedback()
{
	self endon( "faux_spawn" );
	self endon( "stop_javelin_locked_feedback" );

	for ( ;; )
	{
		if ( isDefined( level.chopper ) && isDefined( level.chopper.gunner ) && isDefined( self.stingerTarget ) && self.stingerTarget == level.chopper.gunner )
			level.chopper.gunner playLocalSound( "missile_locking" );

		if ( isDefined( level.ac130player ) && isDefined( self.stingerTarget ) && self.stingerTarget == level.ac130.planeModel )
			level.ac130player playLocalSound( "missile_locking" );

		self playLocalSound( "stinger_locked" );
		self PlayRumbleOnEntity( "ac130_25mm_fire" );

		wait 0.25;
	}
}


/#
DrawStar( point )
{
	Line( point + (10,0,0), point - (10,0,0) );
	Line( point + (0,10,0), point - (0,10,0) );
	Line( point + (0,0,10), point - (0,0,10) );
}
#/


LockSightTest( target )
{
	eyePos = self GetEye();
	
	if ( !isDefined( target ) ) //targets can disapear during targeting.
		return false;
	
	passed = SightTracePassed( eyePos, target.origin, false, target );
	if ( passed )
		return true;

	front = target GetPointInBounds( 1, 0, 0 );
	passed = SightTracePassed( eyePos, front, false, target );
	if ( passed )
		return true;

	back = target GetPointInBounds( -1, 0, 0 );
	passed = SightTracePassed( eyePos, back, false, target );
	if ( passed )
		return true;

	return false;
}


StingerDebugDraw( target )
{
/#
	if ( GetDVar( "missileDebugDraw" ) != "1" )
		return;
	if ( !IsDefined( target ) )
		return;

	org = target.origin;
	DrawStar( org );
	org = target GetPointInBounds( 1, 0, 0 );
	DrawStar( org );
	org = target GetPointInBounds( -1, 0, 0 );
	DrawStar( org );
#/
}


SoftSightTest()
{
	LOST_SIGHT_LIMIT = 500;

	if ( self LockSightTest( self.stingerTarget ) )
	{
		self.stingerLostSightlineTime = 0;
		return true;
	}

	if ( self.stingerLostSightlineTime == 0 )
		self.stingerLostSightlineTime = getTime();

	timePassed = GetTime() - self.stingerLostSightlineTime;
	//PrintLn( "Losing sight of target [", timePassed, "]..." );

	if ( timePassed >= LOST_SIGHT_LIMIT )
	{
		//PrintLn( "Lost sight of target." );
		ResetStingerLocking();
		return false;
	}
	
	return true;
}

GetTargetList()
{
	targets = [];
	
	if ( inVirtualLobby() )
		return targets;

	if ( level.teamBased )
	{
		if ( IsDefined( level.chopper ) && ( level.chopper.team != self.team || ( IsDefined( level.chopper.owner ) && level.chopper.owner == self ) ) )
			targets[targets.size] = level.chopper;

		if ( IsDefined( level.ac130player ) && level.ac130player.team != self.team )
			targets[targets.size] = level.ac130.planemodel;
		
		if ( IsDefined( level.orbitalsupport_player ) && level.orbitalsupport_player.team != self.team )
			targets[targets.size] = level.orbitalsupport_planemodel;
		
		if( IsDefined(level.SpawnedWarbirds) )
		{
			foreach(warbird in level.SpawnedWarbirds)
			{
				if( IsDefined( warbird ) && warbird.team != self.team)
					targets[targets.size] = warbird;
			}
		}
		/*
		if(IsDefined(level._orbital_care_pod))
		{
			foreach(pod in level._orbital_care_pod)
			{
				if(IsDefined(pod.podrocket) && pod.owner.team != self.team)
				{
					targets[targets.size] = pod.podrocket;
				}
			}
		}
		*/
		if ( IsDefined( level.harriers) )
		{
			foreach( harrier in level.harriers )
			{
				if ( IsDefined( harrier ) && ( harrier.team != self.team || ( IsDefined( harrier.owner ) && harrier.owner == self ) ) )
					targets[targets.size] = harrier;
			}
		}
	
		if( level.multiTeamBased )
		{
			//for all teams
			for( i = 0; i < level.teamNameList.size; i++ )
			{
				//that are not our team
				if( self.team != level.teamNameList[i] )
				{
					//does that team have any uav's
					if( level.UAVModels[level.teamNameList[i]].size )
					{
						//add each uav to the target list
						foreach ( UAV in level.UAVModels[level.teamNameList[i]] )
						{
							targets[targets.size] = UAV;
						}
					}
				}
			}
		}
		else if ( level.UAVModels[level.otherTeam[self.team]].size )
		{
			foreach ( UAV in level.UAVModels[level.otherTeam[self.team]] )
				targets[targets.size] = UAV;
		}

		if ( IsDefined( level.littleBirds ) )
		{
			foreach ( lb in level.littleBirds )
			{
				if ( IsDefined( lb ) && ( lb.team != self.team || ( isDefined( lb.owner ) && lb.owner == self ) ) )
					targets[targets.size] = lb;
			}
		}
		
		if ( IsDefined( level.ugvs ) )
		{
			foreach ( ugv in level.ugvs )
			{
				if ( IsDefined( ugv ) && ( ugv.team != self.team || ( isDefined( ugv.owner ) && ugv.owner == self ) ) )
					targets[targets.size] = ugv;
			}
		}

		//This exposes missile tracking issues - CUT IW5 Jordan
		/*
		foreach ( player in level.players )
		{
			if ( !isAlive( player ) )
				continue;

			if ( level.teamBased && player.team == self.team )
				continue;
				
			if ( player == self )
				continue;
	
			if ( player isJuggernaut() )
				targets[targets.size] = player;
		}
		*/
	}
	else
	{
		if ( IsDefined( level.chopper ) ) //check for teams IW5: ( level.chopper.owner != self )
			targets[targets.size] = level.chopper;

		if ( isDefined( level.ac130player ) )
			targets[targets.size] = level.ac130.planemodel;
		
		if ( isDefined( level.harriers) )
		{
			foreach( harrier in level.harriers )
			{
				if ( isDefined( harrier ) )
					targets[targets.size] = harrier;
			}
		}
		/*
		if(IsDefined(level._orbital_care_pod))
		{
			foreach(pod in level._orbital_care_pod)
			{
				if(IsDefined(pod.podrocket))
				{
					targets[targets.size] = pod.podrocket;
				}
			}
		}
		*/
		if ( level.UAVModels.size )
		{
			foreach ( ownerGuid, UAV in level.UAVModels )
			{
				if ( isDefined( UAV.owner ) && UAV.owner == self )
					continue;
					
				targets[targets.size] = UAV;
			}
		}
		
		if ( isDefined( level.littleBirds ) )
		{
			foreach ( lb in level.littleBirds )
			{
				if ( !isDefined( lb ) )
					continue;

				targets[targets.size] = lb;
			}
		}

		if ( IsDefined( level.ugvs ) )
		{
			foreach ( ugv in level.ugvs )
			{
				if ( !IsDefined( ugv ) )
					continue;

				targets[targets.size] = ugv;
			}
		}
		
//		foreach ( player in level.players )
//		{
//			if ( !isAlive( player ) )
//				continue;
//			
//			if ( level.teamBased && player.team == self.team )
//				continue;
//				
//			if ( player == self )
//				continue;
//			
//			targets[targets.size] = player;
//		}
	}
	
	return targets;
}

StingerUsageLoop()
{
	if ( !IsPlayer(self) )
		return;
	
	self endon("death");
	self endon("disconnect");
	self endon("faux_spawn");
	
	LOCK_LENGTH = 1000;
	
	InitStingerUsage();
	
	for( ;; )
	{
		wait 0.05;
		
		if ( self PlayerADS() < 0.95 )
		{
			ResetStingerLocking();
			continue;
		}

		weapon = self getCurrentWeapon();
		
		// Do not run any stinger logic if stingerM7 - stingerM7 has its own script in _stingerm7.gsc.
		if ( IsSubStr( weapon, "stingerm7" ) )
			continue;
		
		if ( weapon != "stinger_mp" && weapon != "iw5_maaws_mp" )
		{
			ResetStingerLocking();
			continue;
		}
		
		self.stingerUseEntered = true;
		
		if ( !IsDefined( self.stingerStage ) )
			self.stingerStage = 0;
		
		StingerDebugDraw( self.stingerTarget );
		
		if ( self.stingerStage == 0 )  // searching for target
		{
			targets = GetTargetList();
			if ( targets.size == 0 )
				continue;

			targetsInReticle = [];
			foreach ( target in targets )
			{
				if ( !isDefined( target ) )
					continue;
				
				insideReticle = self WorldPointInReticle_Circle( target.origin, 65, 75 );
				
				if ( insideReticle )
					targetsInReticle[targetsInReticle.size] = target;
			}
			if ( targetsInReticle.size == 0 )
				continue;

			sortedTargets = SortByDistance( targetsInReticle, self.origin );
			if ( !( self LockSightTest( sortedTargets[0] ) ) )
				continue;

			//PrintLn( "Found a target to lock to..." );
			thread LoopStingerLockingFeedback();
			self.stingerTarget = sortedTargets[0];
			self.stingerLockStartTime = GetTime();
			self.stingerStage = 1;
			self.stingerLostSightlineTime = 0;
		}

		if ( self.stingerStage == 1 )  // locking on to a target
		{
			if ( !(self StillValidStingerLock( self.stingerTarget )) )
			{
				//PrintLn( "Failed to get lock." );
				ResetStingerLocking();
				continue;
			}

			passed = SoftSightTest();
			if ( !passed )
				continue;

			timePassed = getTime() - self.stingerLockStartTime;
			//PrintLn( "Locking [", timePassed, "]..." );
			if( self _hasPerk( "specialty_fasterlockon" ) )
			{
				if( timePassed < ( LOCK_LENGTH * 0.5 ) )
					continue;
			}
			else
			{
				if ( timePassed < LOCK_LENGTH )
					continue;
			}

			self notify( "stop_javelin_locking_feedback" );
			thread LoopStingerLockedFeedback();
			
			//PrintLn( "Locked!");
			self WeaponLockFinalize( self.stingerTarget );
			
			self.stingerStage = 2;
		}
		
		if ( self.stingerStage == 2 )  // target locked
		{
			passed = SoftSightTest();
			if ( !passed )
				continue;

			if ( !(self StillValidStingerLock( self.stingerTarget )) )
			{
				//PrintLn( "Gave up lock." );
				ResetStingerLocking();
				continue;
			}
		}
	}
}
