//===========================================================================//
// File:	PlayerAI.cpp														 //
//---------------------------------------------------------------------------//
//   Date    Who  Modification                                               //
// --------  ---  ---------------------------------------------------------- //
// 01/14/2000  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 "playerai.hpp"
#include "Adept\Interface.hpp"
#include "Adept\Application.hpp"
#include "Vehicle.hpp"
#include "NavPoint.hpp"
#include "mwguimanager.hpp"
#include "hudmap.hpp"
#include "guiradarmanager.hpp"
#include "field_base.hpp"
#include "vehicleinterface.hpp"

using namespace MechWarrior4;
using namespace MW4AI;

//#############################################################################
//##################	Airplane::ExecutionStateEngine    #####################
//#############################################################################

const StateEngine::StateEntry
	PlayerAI::ExecutionStateEngine::StateEntries[]=
{
	STATE_ENTRY(PlayerAI__ExecutionStateEngine, AutoPilot),
	STATE_ENTRY(PlayerAI__ExecutionStateEngine, Cinema),
	STATE_ENTRY(PlayerAI__ExecutionStateEngine, FieldBase)
};


PlayerAI::ExecutionStateEngine::ClassData*
	PlayerAI::ExecutionStateEngine::DefaultData = NULL;

//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
//
void PlayerAI::ExecutionStateEngine::InitializeClass()
{
	Check_Object(StateEngine::DefaultData);
	Verify(!DefaultData);

	DefaultData =
		new ClassData(
			PlayerAI__ExecutionStateEngineClassID,
			"PlayerAI::ExecutionStateEngine",
			BaseClass::DefaultData,
			ELEMENTS(StateEntries), StateEntries,
			(Entity::ExecutionStateEngine::Factory)Make,
			(Entity::ExecutionStateEngine::FactoryRequest::Factory)
				&FactoryRequest::ConstructFactoryRequest
		);
	Register_Object(DefaultData);
}

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

//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
//
PlayerAI::ExecutionStateEngine* PlayerAI::ExecutionStateEngine::Make(PlayerAI *mover,FactoryRequest *request)
{
	Check_Object(mover);
	Check_Object(request);
	gos_PushCurrentHeap(Heap);
	PlayerAI::ExecutionStateEngine *engine = new PlayerAI::ExecutionStateEngine(DefaultData, mover, request);
	gos_PopCurrentHeap();
	return engine;
		
}

//
void PlayerAI::ExecutionStateEngine::TestInstance() const
{
	Verify(IsDerivedFrom(DefaultData));
}

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

PlayerAI::ClassData* PlayerAI::DefaultData = NULL;

const Receiver::MessageEntry PlayerAI::MessageEntries[]=
{
	MESSAGE_ENTRY(PlayerAI, DebugText),
};
//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
//
void PlayerAI::InitializeClass()
{
	Verify(!DefaultData);
	DefaultData =
	new ClassData(
		 PlayerAIClassID,
		 "MechWarrior4::PlayerAI",
		 MechAI::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 PlayerAI::TerminateClass()
{
	Unregister_Object(DefaultData);
	delete DefaultData;
	DefaultData = NULL;
}

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

//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
//
PlayerAI::PlayerAI(ClassData *class_data,CreateMessage *message,ReplicatorID *base_id,ElementRenderer::Element *element)
	: MechAI(class_data, message, base_id, element)
{
	Check_Pointer(this);
	Check_Object(message);
	m_AutoPilot = false;
	m_GunnerySkill = 75;
	m_PilotSkill = 75;
	m_EliteSkill = 75;
}

//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
//
PlayerAI::~PlayerAI()
{
}

bool PlayerAI::ShouldRunScript()
{
	switch (executionState->GetState ())
	{
	case ExecutionStateEngine::FieldBaseState:
		return false;
		break;
	}
	return true;
}
//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
//
void PlayerAI::PreCollisionExecute(Time till)
{
  extern int g_nMR;
  if (g_nMR == 2)
       return;

	Check_Object(this);
	PRECOLLISION_LOGIC("Player AI");

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

	switch (executionState->GetState ())
	{
	case ExecutionStateEngine::AutoPilotState:
		m_ExecutionNumber = MW4AI::g_AIExecutionNumber;
		MoverAI::PreCollisionExecute(till);
		break;
	case ExecutionStateEngine::CinemaState:
			m_ExecutionNumber = MW4AI::g_AIExecutionNumber;
			inherited::PreCollisionExecute(till);
		break;
	case ExecutionStateEngine::FieldBaseState:
			m_ExecutionNumber = MW4AI::g_AIExecutionNumber;
			inherited::PreCollisionExecute(till);
		break;
	}
}

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

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

void PlayerAI::StartCinema (void)
{
	executionState->RequestState(ExecutionStateEngine::CinemaState);
}

void PlayerAI::StartFieldBase (void)
{
	executionState->RequestState(ExecutionStateEngine::FieldBaseState);
}

void PlayerAI::StopExecuting (void)
{
	ClearMoveOrder ();
	OrderStopAttacking ();
	executionState->RequestState(ExecutionStateEngine::NeverExecuteState);
}

void PlayerAI::TurnOn (void)
{
}

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

bool PlayerAI::RequestHeatShutdown() const
{
	return (true);
}

void PlayerAI::NotifyHeatShutdownImminent()
{
	// this space intentionally left blank
}

void PlayerAI::FinishFieldBase (void)
{
	Verify (m_Vehicle->vehicleInterface);
	m_Vehicle->vehicleInterface->PlayerAIFieldBase (false);
	inherited::FinishFieldBase ();
}

void PlayerAI::AutoPilot (bool value)
{
	if (value == m_AutoPilot)
	{
		return;
	}
	m_AutoPilot = value;
	if ((m_AutoPilot) && (m_AutoPilotDest))
	{
		Check_Object (m_AutoPilotDest);
		Point3D loc (m_AutoPilotDest->GetLocalToWorld ());

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

		m_AutoPilotSpeed = m_Vehicle->speedDemand;

		orderMoveToLocPoint (loc,(int) (m_AutoPilotSpeed * model->maxSpeed),true,true);
		executionState->RequestState(ExecutionStateEngine::AutoPilotState);
	}
	else
	{
		ClearMoveOrder ();
		executionState->RequestState(ExecutionStateEngine::NeverExecuteState);
	}
}

void PlayerAI::NavPoint (MechWarrior4::NavPoint *point)
{
	Check_Object (point);
	if (m_AutoPilotDest == point)
	{
		return;
	}
	m_AutoPilotDest = point;
	if ((m_AutoPilot) && (m_AutoPilotDest))
	{
		Check_Object (m_AutoPilotDest);
		Point3D loc (m_AutoPilotDest->GetLocalToWorld ());

		orderMoveToLocPoint (loc,(int) m_AutoPilotSpeed,true,true);
	}
	else if ((m_AutoPilot) && (!m_AutoPilotDest))
	{
		AutoPilot (false);
	}
}

void PlayerAI::ChangeAutoPilotSpeed (Stuff::Scalar newspeed)
{
	Verify (m_AutoPilot);
	Verify (m_CurMove);

	m_AutoPilotSpeed = newspeed;

	if (m_CurMove)
	{
		m_CurMove->Speed (newspeed);
	}
}


