/*
*	general.cpp
*	----------------------------------------
*	A part of "Intelligent AI"
*	© 2001 SCC Team 064
*	----------------------------------------
*
*	This file:
*		€ Contains functions which control basic, general actions performed
*		   within the simulation. These include:
*			- void Move();
*				~ Takes an azimuth and moves the unit at its set speed to the specified  
*				azimuth, and calls void Notify(flag event, int unitNumber, int player);  
*				when a unit reaches its destination and movement is complete.
*			~ void UnitRange();
*				~ Checks to see if the player can attack any other planes by calculating  
*				the distance between the planes and comparing this to the planes horizon.  
*				If any planes can be attacked then they are entered into the CanSee list 
*				and flaged as attackable.
*			- void Attack(player_class &enemy);
*				~ Takes a unit and simulates it attacking a specific enemy unit.  Limited by the  
*				unit's attack rate.  Deducts hitpoints from the enemy based on the attacking unit's  
*				damage potential. If a unit is destroyed (hitpoints fall to or below 0), the player  
*				elimination function will eliminate it from the simulation.
*/


#include <math.h>
#include <time.h>
#include <stdlib.h>

#include "Project.h"



/*------------------------------------------------------------------------------------------*/
/*										GENERAL FUNCTIONS									*/
/*------------------------------------------------------------------------------------------*/



/*										Notify										*/
/*----------------------------------------------------------------------------------*/
void player_class::Notify(int event, int player, int data)
{
}


/*										Move										*/
/*----------------------------------------------------------------------------------*/
void player_class::Move()
{
	long double diffYaw, diffPitch, diffRoll;

	// Keeps the targetYaw within 2¼ and -2¼.
	if (targetYaw > 2. * M_PI)
		targetYaw -= 2. * M_PI;
	if (targetYaw <= 0)
		targetYaw += 2. * M_PI;
	if (targetPitch > 2. * M_PI)
		targetPitch -= 2. * M_PI;
	if (targetPitch <= 0)
		targetPitch += 2. * M_PI;

	// Calculated the difference between the players yaw and the desired yaw.
	diffYaw = targetYaw - yaw;
	diffPitch = targetPitch - pitch;
	diffRoll = targetRoll - roll;


	// Ensures the plane will pitch in the most logical direction to its destination.
	if (diffPitch >= M_PI)
		diffPitch -= 2 * M_PI;
	if (diffPitch <= - M_PI)
		diffPitch += 2 * M_PI;

	// Ensures the plane will turn in the most logical direction to its destination.
	if (diffYaw >= M_PI)
		diffYaw -= 2 * M_PI;
	if (diffYaw <= - M_PI)
		diffYaw += 2 * M_PI;


	// Keeps the diffYaw within 2¼ and -2¼.
	if (diffYaw >= 2. * M_PI)
		diffYaw -= 2. * M_PI;
	if (diffYaw < 0)
		diffYaw += 2. * M_PI;

	// Keeps the diffPitch within 2¼ and -2¼.
	if (diffPitch >= 2. * M_PI)
		diffPitch -= 2. * M_PI;
	if (diffPitch < 0)
		diffPitch += 2. * M_PI;

	// Ensures that the plane's turning increments are constant 
	if (oldTargetYaw != targetYaw)
	{
		if (diffYaw >= M_PI)
			turnRate2 = ((M_PI - diffYaw) / M_PI) * turnRate;
		else
			turnRate2 = (diffYaw / M_PI) * turnRate;
	}


	// Alters the planes pitch by the desired amount.
	pitch 	+= diffPitch/turnRate;
	yaw 	+= diffYaw/turnRate2;
	roll 	+= diffRoll/turnRate;

	oldTargetYaw = targetYaw;
}


/*										Unit Range									*/
/*----------------------------------------------------------------------------------*/
void player_class::UnitRange()
{
	double			xDist, yDist, zDist;
	long double 	pSeperation;

	for (int i = 0; i < getCurrentNumPlayers(); i++)
	{
		yDist = player[i].yPos - yPos;
		xDist = player[i].xPos - xPos;
		zDist = player[i].zPos - zPos;

		// This calculates the distance between two units, to see if one unit can attack the other.
		pSeperation = sqrt( (xDist * xDist) + (yDist * yDist) + (zDist * zDist) );

		if (range >= pSeperation && whichPlayer != i)
			canSee[i] = true;	// The enemy is put into the players attackable array.
	}
}


/*										Attack										*/
/*----------------------------------------------------------------------------------*/
void player_class::Attack(player_class &enemy)
{
	double 	slopeX, slopeZ;

	slopeX = tan(yaw);	// Calculates on which slope the plane is flying.
	slopeZ = tan(pitch);

	// Range is calculated from the UnitRange function.
	// Calculates the the planes trajectory and determins if the enemy is intersected by it, 
	// within a given value, in which case, hit points are deducted.
	if ( ((slopeX - ( (enemy.yPos - yPos)/(enemy.xPos - xPos) ) < .1339) &&
			(slopeX - ( (enemy.yPos - yPos)/(enemy.xPos - xPos) ) > - .1339))
		  && ((slopeZ - ( (enemy.zPos - zPos)/(enemy.xPos - xPos) ) < .1339) &&
			(slopeZ - ( (enemy.zPos - zPos)/(enemy.xPos - xPos) ) > - .1339)) )
	{
		lockOn++;	// The enemy must aquire a lock for five cycles before it can fire, 
					// this is to prevent random strafing.
		if (lockOn == 5 || firing)
		{
			enemy.underFire = true;

			enemy.hitPoints -= damage;
			firing = true;

			enemy.flashColor = true;	// This flashes the plane yellow so as to indicate a hit.
			cout << "hit" << endl;
		}
	}
	else
	{
		lockOn = 0;
		firing = false;
		enemy.flashColor = false;
	}

}