//===========================================================================//
// File:	MechAI.cpp																	     //
//---------------------------------------------------------------------------//
//   Date    Who  Modification                                               //
// --------  ---  ---------------------------------------------------------- //
// 07/13/99  AHF  Created file                          //
//---------------------------------------------------------------------------//
// Copyright (C) 1999, Microsoft										 //
// All Rights reserved worldwide                                             //
// This unpublished sourcecode is PROPRIETARY and CONFIDENTIAL               //
//===========================================================================//

#include "MW4Headers.hpp"
#include "Adept\AdeptHeaders.hpp"

#include "mw4.hpp"
#include "planeai.hpp"
#include "Adept\Interface.hpp"
#include "Adept\Application.hpp"
#include "Adept\player.hpp"
#include "Adept\map.hpp"
#include "torso.hpp"
#include "Airplane.hpp"
#include "helicopter.hpp"
#include "dropship.hpp"
#include <Adept\CollisionGrid.hpp>
#include <adept\collisionvolume.hpp>
#include "cheap_move.hpp"
#include "aiutils.hpp"
#include "dropship.hpp"

#pragma warning (push)
#include <algorithm>
#pragma warning (pop)

const int OBSTACLELOOKAHEAD = 50;
const Stuff::Time FLYBY_TIME = 1.0;			// 1 second fly by
const Stuff::Scalar flyby_distance = 200.0f;

using namespace MechWarrior4;
using namespace MW4AI;

extern __int64 tMoverAITime,tDynamicObstacleTime;

//#############################################################################
//###############################    AI      ##############################
//#############################################################################

PlaneAI::ClassData* PlaneAI::DefaultData = NULL;


const Receiver::MessageEntry
PlaneAI::MessageEntries[]=
{
	MESSAGE_ENTRY(PlaneAI, DebugText),
};


//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
//
void PlaneAI::InitializeClass()
{
	Verify(!DefaultData);
	DefaultData =
	new ClassData(
							 PlaneAIClassID,
							 "MechWarrior4::PlaneAI",
							 CombatAI::DefaultData,
							 ELEMENTS(MessageEntries), MessageEntries,
							 (Entity::Factory)Make,
							 (Entity::CreateMessage::Factory)CreateMessage::ConstructCreateMessage,
							 ExecutionStateEngine::DefaultData,
							 (Entity::GameModel::Factory)GameModel::ConstructGameModel,
							 NULL,
							 (Entity::GameModel::ReadAndVerifier)GameModel::ReadAndVerify,
							 (Entity::GameModel::ModelWrite)GameModel::WriteToText,
							 (Entity::GameModel::ModelSave)GameModel::SaveGameModel
							 );
	Register_Object(DefaultData);
}

//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
//
void PlaneAI::TerminateClass()
{
	Unregister_Object(DefaultData);
	delete DefaultData;
	DefaultData = NULL;
}

//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
//
PlaneAI* PlaneAI::Make(CreateMessage *message,ReplicatorID *base_id)
{
	Check_Object(message);
	AutoHeap local_heap (g_AIHeap);
	PlaneAI *new_entity = new PlaneAI(DefaultData, message, base_id, NULL);
	Check_Object(new_entity);
	new_entity->SyncMatrices(true);
	return new_entity;
}

//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
//
PlaneAI::PlaneAI(ClassData *class_data,CreateMessage *message,ReplicatorID *base_id,ElementRenderer::Element *element)
: CombatAI(class_data, message, base_id, element),
m_ContinuousFlybySwingPoint(-1,-1,-1)
{
	AutoHeap local_heap (g_AIHeap);
	Check_Pointer(this);
	Check_Object(message);
	m_InMove = 0;
	m_InMoveDir = 1;

	m_AirLockedRects.reserve (20);
	m_ObstacleAvoidPoint = Point3D (-1,-1,-1);
	m_AttackRun = false;
	m_Aborting = false;
	m_FinishedFlyBy = false;

	if (Network::GetInstance()->AmIServer())
	{
		Entity *ent = getEntity ();
		Check_Object(ent);
		Verify (ent->IsDerivedFrom (Airplane::DefaultData));
		m_Airplane = Cast_Object (Airplane *,ent);
//		if (!m_Airplane->IsDerivedFrom (Dropship::DefaultData))
			m_Airplane->TurnOn ();
	}
}

//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
//
PlaneAI::~PlaneAI()
{
}

bool PlaneAI::PointIsOK(const Stuff::Point3D& point) const
{
	Check_Object (this);
	Check_Object (MW4AI::g_MissionGraph);
	Check_Object (m_Vehicle);

	return true;
}

void PlaneAI::ClearPathLock (bool quitting,bool fromram)
{
	Check_Object (this);
	__int64 TempTime=GetCycles();

	stlport::vector<Rect4D *>::iterator iter2;
	Verify (m_AirLockedRects.size () == 0);
	for (iter2 = m_AirLockedRects.begin ();iter2 != m_AirLockedRects.end ();iter2++)
	{
		g_AirRect4DHash->RemoveRect (*iter2);
		g_AirRect4DHash->VerifyRectGone (*iter2);
		delete *iter2;
	}
	m_AirLockedRects.clear ();


	MoverAI::ClearPathLock (quitting,fromram);
	tDynamicObstacleTime+=GetCycles()-TempTime;
}

bool PlaneAI::PathLock (bool secondrun,bool fromram)
{
	Check_Object (this);
	if (!m_Vehicle)
		return false;
	__int64 TempTime=GetCycles();

	Check_Object (m_Vehicle);
	Check_Object (m_Vehicle->GetGameModel ());

	Airplane *airplane;
	airplane = Cast_Object (Airplane *,m_Vehicle);
	if (airplane->OnGround ())
	{
		MoverAI::PathLock (secondrun,fromram);
	}

	tDynamicObstacleTime+=GetCycles()-TempTime;
	return false;
}

void PlaneAI::NotifyNoPath(void)
{
	inherited::NotifyNoPath ();
}

void PlaneAI::NotifyReachedDestination(void)
{
	inherited::NotifyReachedDestination ();
}

void PlaneAI::NotifyCollided(Entity *who)
{
	inherited::NotifyCollided (who);
}

bool PlaneAI::AddLockRect (Rect4D *newrect,bool carecollide,Stuff::Time till)
{
	delete newrect;
	return false;
#if 0
	Check_Object (this);
	Rect4D *crect;
	Point3D loc;


	Check_Pointer (g_AirRect4DHash);
	Check_Pointer (newrect);

	if ((!carecollide) || (!m_AttackRun))
	{
		g_AirRect4DHash->AddRect (newrect);
		m_AirLockedRects.push_back (newrect);
		return false;
	}
	crect = g_AirRect4DHash->Collide (*newrect);
	if (crect)
	{
		Verify (m_Vehicle);
		loc = (Point3D) m_Vehicle->GetLocalToWorld ();
		UnitVector3D p1(m_Vehicle->worldSpaceVelocity.linearMotion),p2;
		Point3D extra,otherloc;
		Scalar dot = 5.0f;
		if ((crect->who) && (crect->who->IsDerivedFrom (AI::DefaultData)))
		{
			AI* tempai;
			tempai = (AI*) crect->who;
			if (tempai->getEntity ())
			{
				otherloc = (Point3D) tempai->getEntity ()->GetLocalToWorld ();
				extra.Subtract (otherloc,loc);
				if (Small_Enough (extra.GetLength ()))
					dot = 0.0f;
				else
				{
					p2 = extra;
					dot = (p1.x*p2.x) + (p1.z*p2.z);
				}
			}
		}
		if (dot > 0)
		{
			HandleObstacle (crect);
			delete newrect;	
			return true;
		}
		else
		{
			g_AirRect4DHash->AddRect (newrect);
			m_AirLockedRects.push_back (newrect);
		}
	}
	else
	{
		g_AirRect4DHash->AddRect (newrect);
		m_AirLockedRects.push_back (newrect);
	}
	return false;
#endif
}

bool PlaneAI::Avoiding (PlaneAI *who)
{
	stlport::vector<AvoidData>::iterator iter;
	
	for (iter = m_AvoidList.begin ();iter != m_AvoidList.end ();iter++)
		if (iter->who == who)
			return true;
	return false;
}

void PlaneAI::AddAvoid (PlaneAI *who)
{
	AutoHeap local_heap (g_AIHeap);
	stlport::vector<AvoidData>::iterator iter;
	for (iter = m_AvoidList.begin ();iter != m_AvoidList.end ();iter++)
		if (iter->who == who)
			break;
	if (iter == m_AvoidList.end ())
	{
		m_AvoidList.push_back (AvoidData (who,gos_GetElapsedTime ()));
	}
	else
	{
		iter->active = gos_GetElapsedTime ();
	}
}

void PlaneAI::CleanAvoidList (void)
{
	Stuff::Time current;
	stlport::vector<AvoidData>::iterator iter;
	
	AutoHeap local_heap (g_AIHeap);
	current = gos_GetElapsedTime ();
	iter = m_AvoidList.begin ();
	while (iter != m_AvoidList.end ())
	{
		if ((iter->active - current) >= 2.0)
			iter = m_AvoidList.erase (iter);
		else
			iter++;
	}
}

void PlaneAI::RemoveAvoid (PlaneAI *who)
{
	stlport::vector<AvoidData>::iterator iter;
	AutoHeap local_heap (g_AIHeap);
	
	for (iter = m_AvoidList.begin ();iter != m_AvoidList.end ();iter++)
		if (iter->who == who)
			break;
	if (iter != m_AvoidList.end ())
	{
		m_AvoidList.erase (iter);
	}
}

void PlaneAI::KillAvoidList (void)
{
	AutoHeap local_heap (g_AIHeap);
	m_AvoidList.clear ();
}

Point3D PlaneAI::FindAvoidPoint (Rect4D *rect)
{
	Point3D head;

	Check_Object (rect->who);
	Verify (rect->who->IsDerivedFrom (PlaneAI::DefaultData));
	Check_Object (m_Vehicle);
	PlaneAI *plane = Cast_Object (PlaneAI *,rect->who);
	Check_Object (plane->m_Vehicle);

	head.x = ((rect->right - rect->left) / 2.0f) + rect->left;
	head.z = ((rect->bottom - rect->top) / 2.0f) + rect->top;
	head.y = 0;

	Scalar rad1aa,rad2aa;
	CollisionVolume *col1,*col2;
	col1 = m_Vehicle->GetHierarchicalVolume ();
	if (!col1)
		col1 = m_Vehicle->GetSolidVolume ();
	if (!col1)
		rad1aa = 15.0f;
	else
		rad1aa = col1->m_localSpaceBounds.sphereRadius;
	col2 = plane->m_Vehicle->GetHierarchicalVolume ();
	if (!col2)
		col2 = plane->m_Vehicle->GetSolidVolume ();
	if (!col2)
		rad2aa = 15.0f;
	else
		rad2aa = col2->m_localSpaceBounds.sphereRadius;

	rad1aa *= 1.2f;
	rad2aa *= 1.2f;

	Vector3D dir;
	if (Small_Enough (rect->velocity.linearMotion.GetLengthSquared ()))
	{
		dir.x = 1;
		dir.y = 0;
		dir.z = 0;
	}
	else
		dir.Normalize (rect->velocity.linearMotion);
	dir *= (rad1aa+rad2aa);
	head -= dir;

	return head;
}

void PlaneAI::AttackRunDone (void)
{
	m_AttackRun = false;
	m_Aborting = false;
	m_FinishedFlyBy = true;
}

void PlaneAI::EndAttackRun (void)
{
	if (m_Aborting)
		return;
	m_EndStart = gos_GetElapsedTime ();
	m_Aborting = true;
}

void PlaneAI::AbortAttackRun (void)
{
	Check_Object (m_Airplane);
	m_EndStart = gos_GetElapsedTime ()-FLYBY_TIME;
	m_Aborting = true;
	m_Airplane->m_Attacking = false;
}

bool PlaneAI::ValidAttackPoint (const Point3D& point)
{
	Check_Object (m_Vehicle);

	Point3D endpt,extra;

	Point3D loc (m_Vehicle->GetLocalToWorld ());

	endpt.Subtract (point,loc);
	endpt.y = 0;
	extra.Normalize (endpt);
	Check_Object (m_Vehicle->GetGameModel ());
	const Vehicle__GameModel *model = static_cast<const Vehicle__GameModel *> (m_Vehicle->GetGameModel ()) ;

	extra *= ((float) (FLYBY_TIME * (double) model->maxSpeed));	
	extra += point;
	return g_MissionGraph->AirQuickCheck ((int) loc.x,(int) loc.z,(int) extra.x,(int) extra.z);
}

bool PlaneAI::FlyBy (const Point3D& point)
{
	if (m_FinishedFlyBy)
		return true;
	
	if ((m_Aborting) || (m_AttackRun))
		return false;

	return (!StartAttackRun (point));
}

void PlaneAI::ContinuousFlyBy(const Point3D& point)
{
	if (m_ContinuousFlybySwingPoint != Point3D(-1,-1,-1))
	{
		FlyBy(point);
	}

	if ((m_FinishedFlyBy == true) ||
		((m_CurMove == 0) && (m_OrderSpeed == 0)))
	{
		if ((m_ContinuousFlybySwingPoint == Point3D(-1,-1,-1)) ||
			(m_CurMove == 0))
		{
			Stuff::Point3D& p = m_ContinuousFlybySwingPoint;
			p = point;

			switch (gos_rand() & 0x03)
			{
				case 0:
				{
					p.x += flyby_distance;
					p.z += flyby_distance;
					break;
				}
				case 1:
				{
					p.x -= flyby_distance;
					p.z += flyby_distance;
					break;
				}
				case 2:
				{
					p.x += flyby_distance;
					p.z -= flyby_distance;
					break;
				}
				case 3:
				{
					p.x -= flyby_distance;
					p.z -= flyby_distance;
					break;
				}
			}

			Clamp(p.x,MW4AI::MinX,MW4AI::MaxX);
			Clamp(p.z,MW4AI::MinZ,MW4AI::MaxZ);

			ClearMoveOrder();
			orderMoveToLocPoint(p,1000,true,false);

			return;
		}

		Point3D my_pos(vehicle->GetLocalToWorld());
		m_ContinuousFlybySwingPoint.y = my_pos.y;

		if ((m_CurMove == 0) ||
			(m_CurMove->Done() == true) ||
			(GetApproximateLength(m_ContinuousFlybySwingPoint,my_pos) < 50))
		{
			ClearMoveOrder();
			m_ContinuousFlybySwingPoint = Point3D(-1,-1,-1);
			m_FinishedFlyBy = false;
		}
	}
}

bool PlaneAI::StartAttackRun (const Point3D& attackpoint)
{
	Verify (m_Vehicle);
	m_FinishedFlyBy = false;
	if ((m_Aborting) || (m_AttackRun))
	{
		return false;
	}

	if (!ValidAttackPoint (attackpoint))
	{
		return false;
	}

	ClearMoveOrder ();
	Scalar height;

	BYTE material;
	Point3D loc (m_Vehicle->GetLocalToWorld ());
	height = GetMapY (attackpoint.x,attackpoint.z,m_Vehicle,material,loc.y);
	m_AttackPoint = attackpoint;
	if (attackpoint.y < (height+g_MaxAirHeight))
	{
		m_AttackPoint.y = height + g_MaxAirHeight;
	}

	m_AttackRun = true;
	m_Aborting = false;
	m_OrderSpeed = 1.0f;
	m_Airplane->m_Attacking = true;
	m_Airplane->m_AttackAltitude = g_MaxAirHeight;
	return true;
}

void PlaneAI::HandleObstacle (MW4AI::Rect4D *p1,Adept::Entity *p2)
{
	if (p1)							// potential collision
	{
		Verify (m_AttackRun);

		Verify (p1->who);
		Verify (p1->who->IsDerivedFrom (PlaneAI::DefaultData));
		PlaneAI *plane = Cast_Object (PlaneAI *,p1->who);

		Point3D loc(m_Airplane->GetLocalToWorld ()),otherloc (plane->m_Airplane->GetLocalToWorld ());

		if (otherloc.y < loc.y)		// only avoid plane lower than us since we are decending
		{
			AbortAttackRun ();
		}

#if 0
		Point3D head;

		if (!plane->Avoiding (this))
		{
			head = FindAvoidPoint (p1);
	
			CommandEntry *com;
			com = CreateTurnToCommand (head,false);
			Check_Pointer (com);
			ExecuteCommand (com);
			AddAvoid (plane);
		}
#endif

	}
	else if (p2)
	{
		STOP (("plane ran into another object"));
	}
	else
	{
		STOP (("somehow a plane went up a slope that was too steep"));
	}
}



void PlaneAI::PathDone (Stuff::Time till,bool failed)
{
	Verify (m_Vehicle);

	NotifyReachedDestination ();
	if ((m_CurMove->MoveType () == MOVE_PATROL) || (m_CurMove->MoveType () == MOVE_SEMIPATROL))
	{
		CPatrolData *tempmove;
		tempmove = (CPatrolData *) m_CurMove;
		switch (tempmove->PatrolType ())
		{
			case PATROL_SINGLE:
				m_CurMove->Done (true);
				break;
			case PATROL_LOOP:
				m_InMove = 0;
				m_InMoveDir = 1;
				break;
			case PATROL_SEESAW:
				m_InMoveDir *= -1;
				m_InMove += m_InMoveDir;
				break;
		}
	}
	else
		m_CurMove->Done (true);
	if (m_Vehicle->IsDerivedFrom (Helicopter::DefaultData))
	{
		CommandEntry *com;
		com = CreateSetSpeedCommand (0);
		Check_Pointer (com);
		ExecuteCommand (com);
	}
}

void PlaneAI::ExecuteMoveHead (Stuff::Time till)
{
	if (m_NewMoveHead != m_MoveHead)
	{
		m_MoveHead = m_NewMoveHead;
    m_NeedHeadingAdjust = true;
	}
	if (m_NewOutVec != m_OutVec)
	{
		m_OutVec = m_NewOutVec;
	}
	if (m_NewSpeedRequest != m_SpeedRequest)
	{
		m_SpeedRequest = m_NewSpeedRequest;
	}

}

void PlaneAI::ExecutePath (Stuff::Time till)
{
	Verify (m_Vehicle);
	if ((!m_CurMove) && (!(((m_Aborting) || (m_AttackRun)))))
		return;
	Stuff::Scalar dist,move,yvalue;
	CommandEntry *com;
	Point3D head(0,0,0),destloc,extra;

	Point3D loc (m_Vehicle->GetLocalToWorld ());

	const Vehicle__GameModel *model = static_cast<const Vehicle__GameModel *> (m_Vehicle->GetGameModel ()) ;

	Stuff::Scalar speed;

	speed = m_Vehicle->speedDemand;
	yvalue = loc.y;
	loc.y = 0;

	if (m_AttackRun)
	{
		if (!ValidAttackPoint (m_AttackPoint))
		{
			AbortAttackRun ();
		}

		destloc = m_AttackPoint;
	}
	else
	{
		destloc = m_CurMove->Location (m_InMove);
	}
	destloc.y = 0;
	extra.Subtract (destloc,loc);
	dist = extra.GetLengthSquared ();
	move = (float) (speed * model->maxSpeed);		// use one second buffer
	move *= move;

	if ((dist<25.0) || (dist < move))
	{
		if (m_AttackRun)
		{
			EndAttackRun ();
		}
		else if ((m_InMoveDir > 0) && (m_CurMove->LocationSize () > (m_InMove+m_InMoveDir)))
		{
			m_InMove+=m_InMoveDir;
		}
		else if ((m_InMoveDir < 0) && ((m_InMove+m_InMoveDir) > 0))
		{
			m_InMove+= m_InMoveDir;
		}
		else
		{
			PathDone (till);
		}
	}

	if (m_AttackRun)
	{
		head = m_AttackPoint;
	}
	else
	{
		head = m_CurMove->Location (m_InMove);
	}
	if (m_Aborting)
	{
		BYTE material;
		Scalar height;

		if ((m_EndStart+FLYBY_TIME) <= gos_GetElapsedTime ())
		{
			Check_Object (m_Airplane);
			m_Airplane->m_Attacking = false;
		}
		height = GetMapY (loc.x,loc.z,m_Vehicle,material,yvalue);
		if (yvalue >= (height + m_Airplane->flyingAltitude))
		{
			AttackRunDone ();
		}
		else
		{
			m_NewMoveHead = Point3D (-1,-1,-1);

			com = CreateKillTurnToCommand ();
			Check_Pointer (com);
			ExecuteCommand (com);
			return;
		}
	}
	else
	{
		m_NewMoveHead = Point3D (-1,-1,-1);
		com = CreateTurnToCommand (head,false);
		Check_Pointer (com);
		ExecuteCommand (com);
	}
	m_NewSpeedRequest = m_OrderSpeed;
	com = CreateSetSpeedCommand (m_OrderSpeed);
	Check_Pointer (com);
	ExecuteCommand (com);
}

void PlaneAI::ExecuteMoveCommand (Stuff::Time till)
{
	Verify (m_Vehicle);

	if (!m_CurMove)
		return;

	if (m_CurMove->Done ())
		return;

	if (!m_CurMove->Executing ())	
	{
			m_CurMove->Executing (true);
			m_OrderSpeed = m_CurMove->Speed ();
	}
	else
	{
			m_OrderSpeed = m_CurMove->Speed ();
	}
}

//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
//
void PlaneAI::PreCollisionExecute(Time till)
{
	Check_Object(this);
	AI_LOGIC("Pre-Collision::Plane AI");

	//
	//---------------------------------
	// Verify that this always executes
	//---------------------------------
	//
	Check_Object(executionState);
	Verify(executionState->GetState() != ExecutionStateEngine::NeverExecuteState);
	m_Deactive = false;

	CleanAvoidList ();
	CombatAI::PreCollisionExecute(till);
}


//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
//
void PlaneAI::DebugTextMessageHandler(Adept::ReceiverDataMessageOf<int> *message)
{
	Check_Object(this);
	Check_Object(message);
	Verify(message->messageID == DebugTextMessageID);
}

//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
//
void PlaneAI::TestInstance() const
{
	Verify(IsDerivedFrom(DefaultData));
}

void PlaneAI::TurnOn (void)
{
}

void PlaneAI::TurnOff (void)
{
	m_Deactive = false;
}

void PlaneAI::ExecuteMoveCommand (MW4AI::CommandEntry *command)
{
	Verify (m_Vehicle);
	Check_Pointer (command);

	ClearMoveOrder ();

	m_CurMove = (CMoveData *) command->DataPtr ();

	Stuff::Point3D temp;
	temp = (Stuff::Point3D) m_Vehicle->GetLocalToWorld ();
	m_CurMove->CreatePlaneRequests (temp);
	m_OrderSpeed = m_CurMove->Speed ();
	m_InMove = 0;
	m_InMoveDir = 1;

	Check_Pointer (m_CurMove);
}

void PlaneAI::hellteleport (void)
{
	Check_Object(m_Vehicle);
	Verify(m_Vehicle->IsDerivedFrom(Airplane::DefaultData));
	Airplane *flyer = Cast_Object(Airplane *, m_Vehicle);
	flyer->executionState->RequestState(Airplane::ExecutionStateEngine::NeverExecuteState);
}

bool  PlaneAI::orderTakeOff (int distance)
{
	Check_Object(m_Vehicle);
	Verify(m_Vehicle->IsDerivedFrom(Airplane::DefaultData));
	Airplane *flyer = Cast_Object(Airplane *, m_Vehicle);
	if(flyer->executionState->GetState() == Airplane::ExecutionStateEngine::NeverExecuteState)
		flyer->TakeOff((Scalar)distance);
	else if(flyer->executionState->GetState() == Airplane::ExecutionStateEngine::AlwaysExecuteState)
		flyer->TakeOff((Scalar)distance);
	else if(flyer->executionState->GetState() == Airplane::ExecutionStateEngine::TaxiState)
		flyer->TakeOff((Scalar)distance);
	else if(flyer->executionState->GetState() == Airplane::ExecutionStateEngine::FlyingMotionState)
		return true;

	return false;
}

bool  PlaneAI::orderLand (void)
{
	Check_Object(m_Vehicle);
	Verify(m_Vehicle->IsDerivedFrom(Helicopter::DefaultData));
	ClearMoveOrder ();
	Helicopter *flyer = Cast_Object(Helicopter *, m_Vehicle);
	if(flyer->executionState->GetState() == Airplane::ExecutionStateEngine::NeverExecuteState)
		return true;
	else if(flyer->executionState->GetState() == Airplane::ExecutionStateEngine::AlwaysExecuteState)
		return true;
	else if(flyer->executionState->GetState() == Airplane::ExecutionStateEngine::TaxiState)
		return true;
	else if(flyer->executionState->GetState() == Airplane::ExecutionStateEngine::FlyingMotionState)
		flyer->Land();

	return false;
}
bool PlaneAI::orderDoorOpen(void)
{
	Check_Object(m_Vehicle);
	Verify(m_Vehicle->IsDerivedFrom(Dropship::DefaultData));
	ClearMoveOrder ();
	Dropship *drop = Cast_Object(Dropship *, m_Vehicle);
	return drop->orderDoorOpen();

}

bool PlaneAI::orderDoorClose(void)
{
	Check_Object(m_Vehicle);
	Verify(m_Vehicle->IsDerivedFrom(Dropship::DefaultData));
	ClearMoveOrder ();
	Dropship *drop = Cast_Object(Dropship *, m_Vehicle);
	return drop->orderDoorClose();
}
		
void  PlaneAI::orderMoveLookOut (void)
{
	if (!m_Active)
		return;
	gosREPORT (false,"Cannot give a lookout order to a plane");
}

void  PlaneAI::orderMoveSit (bool shutdown)
{
	if (!m_Active)
		return;
	gosREPORT (false,"Cannot give a sit order to a plane");
}
