Complete disaster-recovery snapshot: engine/game source, game data assets, VC6 toolchain + DX SDKs, build outputs, deployed game, and _UNUSED archive. Large binaries in Git LFS; text preserved byte-for-byte (core.autocrlf=false, no eol attributes). See RECOVERY.md for the one-clone rebuild procedure.
336 lines
9.0 KiB
C++
336 lines
9.0 KiB
C++
//===========================================================================//
|
|
// 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 "mech_ai.hpp"
|
|
#include "Adept\Interface.hpp"
|
|
#include "Adept\Application.hpp"
|
|
#include "Vehicle.hpp"
|
|
#include "lancemate.hpp"
|
|
#include "gameinfo.hpp"
|
|
#include "field_base.hpp"
|
|
#include "vehicleinterface.hpp"
|
|
|
|
using namespace MechWarrior4;
|
|
using namespace MW4AI;
|
|
|
|
std::list<MechAI*>* MechAI::m_gShutdownMechAIs = 0;
|
|
int MechAI::m_gShutdownMechAIs_RefCount = 0;
|
|
|
|
//#############################################################################
|
|
//############################### AI ##################################
|
|
//#############################################################################
|
|
|
|
MechAI::ClassData* MechAI::DefaultData = NULL;
|
|
|
|
const Receiver::MessageEntry MechAI::MessageEntries[]=
|
|
{
|
|
MESSAGE_ENTRY(MechAI, DebugText),
|
|
};
|
|
//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
|
|
//
|
|
void MechAI::InitializeClass()
|
|
{
|
|
Verify(!DefaultData);
|
|
DefaultData =
|
|
new ClassData(
|
|
MechAIClassID,
|
|
"MechWarrior4::MechAI",
|
|
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 MechAI::TerminateClass()
|
|
{
|
|
Unregister_Object(DefaultData);
|
|
delete DefaultData;
|
|
DefaultData = NULL;
|
|
}
|
|
|
|
//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
|
|
//
|
|
MechAI* MechAI::Make(CreateMessage *message,ReplicatorID *base_id)
|
|
{
|
|
AutoHeap local_heap (g_AIHeap);
|
|
Check_Object(message);
|
|
MechAI *new_entity = new MechAI(DefaultData, message, base_id, NULL);
|
|
Check_Object(new_entity);
|
|
new_entity->SyncMatrices(true);
|
|
return new_entity;
|
|
}
|
|
|
|
//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
|
|
//
|
|
MechAI::MechAI(ClassData *class_data,CreateMessage *message,ReplicatorID *base_id,ElementRenderer::Element *element)
|
|
: CombatAI(class_data, message, base_id, element)
|
|
{
|
|
Check_Pointer(this);
|
|
Check_Object(message);
|
|
|
|
m_Mech = NULL;
|
|
|
|
if (Network::GetInstance()->AmIServer())
|
|
{
|
|
|
|
Check_Object(vehicle);
|
|
m_Mech = Cast_Object(Mech *, getEntity ());
|
|
Check_Object (m_Mech);
|
|
}
|
|
|
|
if (m_gShutdownMechAIs_RefCount == 0)
|
|
{
|
|
Verify(m_gShutdownMechAIs == 0);
|
|
m_gShutdownMechAIs = new std::list<MechAI*>;
|
|
}
|
|
|
|
++m_gShutdownMechAIs_RefCount;
|
|
}
|
|
|
|
//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
|
|
//
|
|
MechAI::~MechAI()
|
|
{
|
|
Verify(m_gShutdownMechAIs_RefCount > 0);
|
|
Verify(m_gShutdownMechAIs != 0);
|
|
|
|
std::list<MechAI*>::iterator found = std::find(m_gShutdownMechAIs->begin(),m_gShutdownMechAIs->end(),this);
|
|
if (found != m_gShutdownMechAIs->end())
|
|
{
|
|
m_gShutdownMechAIs->erase(found);
|
|
}
|
|
|
|
--m_gShutdownMechAIs_RefCount;
|
|
if (m_gShutdownMechAIs_RefCount == 0)
|
|
{
|
|
delete m_gShutdownMechAIs;
|
|
m_gShutdownMechAIs = 0;
|
|
}
|
|
}
|
|
|
|
//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
|
|
//
|
|
void MechAI::PreCollisionExecute(Time till)
|
|
{
|
|
extern int g_nMR;
|
|
if (g_nMR == 2)
|
|
return;
|
|
AI_LOGIC("Pre-Collision::MechAI");
|
|
Check_Object(this);
|
|
#if defined(LAB_ONLY)
|
|
if (!instanceName)
|
|
MWGameInfo::g_LastMWObject[0] = '\0';
|
|
else
|
|
{
|
|
strncpy(MWGameInfo::g_LastMWObject, instanceName, sizeof(MWGameInfo::g_LastMWObject)-1);
|
|
MWGameInfo::g_LastMWObject[sizeof(MWGameInfo::g_LastMWObject)-1] = '\0';
|
|
}
|
|
MWGameInfo::g_LastMWObjectPos = GetLocalToWorld();
|
|
#endif
|
|
|
|
//
|
|
//---------------------------------
|
|
// Verify that this always executes
|
|
//---------------------------------
|
|
//
|
|
|
|
|
|
Check_Object(executionState);
|
|
Verify(executionState->GetState() != ExecutionStateEngine::NeverExecuteState);
|
|
if (m_StartupRequest)
|
|
Startup ();
|
|
if (m_ShutdownRequest)
|
|
Shutdown ();
|
|
|
|
inherited::PreCollisionExecute(till);
|
|
}
|
|
|
|
|
|
//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
|
|
//
|
|
void MechAI::DebugTextMessageHandler(Adept::ReceiverDataMessageOf<int> *message)
|
|
{
|
|
Check_Object(this);
|
|
Check_Object(message);
|
|
Verify(message->messageID == DebugTextMessageID);
|
|
}
|
|
|
|
//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
|
|
//
|
|
bool MechAI::ReactToCollision(Stuff::DynamicArrayOf<CollisionData> *collisions,bool& shoulddamage)
|
|
{
|
|
int i;
|
|
|
|
if (m_EnteringFieldBase != FIELDBASE_NOT_ACTIVE)
|
|
{
|
|
return inherited::ReactToCollision (collisions,shoulddamage);
|
|
}
|
|
|
|
for (i=0; i<collisions->GetLength(); ++i)
|
|
{
|
|
CollisionData *data = &(*collisions)[i];
|
|
|
|
Check_Object(data);
|
|
Check_Object(data->m_otherEntity);
|
|
Verify(this != data->m_otherEntity);
|
|
Verify(GetInterestLevel() != DormantInterestLevel);
|
|
Check_Object(m_Vehicle);
|
|
|
|
Vector3D vector_to_target;
|
|
Point3D local_to_world(m_Vehicle->GetLocalToWorld());
|
|
Point3D target_local_to_world(data->m_otherEntity->GetLocalToWorld());
|
|
if (data->m_otherEntity->IsDerivedFrom (FieldBase::DefaultData))
|
|
{
|
|
if (!CreateFieldBasePoints (Cast_Object (FieldBase *,data->m_otherEntity)))
|
|
{
|
|
if (!m_Vehicle->vehicleInterface)
|
|
{
|
|
ClearMoveOrder ();
|
|
}
|
|
shoulddamage = false;
|
|
return inherited::ReactToCollision (collisions,shoulddamage);
|
|
}
|
|
if (m_Vehicle->vehicleInterface)
|
|
{
|
|
m_Vehicle->vehicleInterface->PlayerAIFieldBase (true);
|
|
}
|
|
PrepareEnterFieldBase ();
|
|
shoulddamage = false;
|
|
}
|
|
}
|
|
return inherited::ReactToCollision (collisions,shoulddamage);
|
|
}
|
|
//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
|
|
//
|
|
void MechAI::TestInstance() const
|
|
{
|
|
Verify(IsDerivedFrom(DefaultData));
|
|
}
|
|
|
|
void MechAI::SetOrderSpeed (Stuff::Scalar newvalue)
|
|
{
|
|
if (newvalue < 0)
|
|
{
|
|
Mech *mech;
|
|
mech = Cast_Object (Mech *,m_Vehicle);
|
|
if (mech->gimpState != Mech::NotGimpedMode)
|
|
newvalue = -newvalue;
|
|
}
|
|
m_OrderSpeed = newvalue;
|
|
}
|
|
|
|
void MechAI::Shutdown (void)
|
|
{
|
|
Check_Object (m_Mech);
|
|
m_StartupRequest = false;
|
|
if (!m_Mech->ShutDownRequest (true))
|
|
m_ShutdownRequest = true;
|
|
else
|
|
m_ShutdownRequest = false;
|
|
inherited::Shutdown ();
|
|
|
|
if (m_gShutdownMechAIs != 0)
|
|
{
|
|
std::list<MechAI*>::iterator found = std::find(m_gShutdownMechAIs->begin(),m_gShutdownMechAIs->end(),this);
|
|
|
|
if (found == m_gShutdownMechAIs->end())
|
|
{
|
|
m_gShutdownMechAIs->push_back(this);
|
|
}
|
|
}
|
|
}
|
|
|
|
void MechAI::Startup (void)
|
|
{
|
|
Check_Object (m_Mech);
|
|
m_ShutdownRequest = false;
|
|
if (!m_Mech->ShutDownRequest (false))
|
|
m_StartupRequest = true;
|
|
else
|
|
m_StartupRequest = false;
|
|
inherited::Startup ();
|
|
|
|
if (m_gShutdownMechAIs != 0)
|
|
{
|
|
std::list<MechAI*>::iterator found = std::find(m_gShutdownMechAIs->begin(),m_gShutdownMechAIs->end(),this);
|
|
if (found != m_gShutdownMechAIs->end())
|
|
{
|
|
m_gShutdownMechAIs->erase(found);
|
|
}
|
|
}
|
|
}
|
|
|
|
void MechAI::Save (MemoryStream *stream)
|
|
{
|
|
*stream << m_StartupRequest;
|
|
*stream << m_ShutdownRequest;
|
|
CombatAI::Save (stream);
|
|
}
|
|
|
|
void MechAI::Load (MemoryStream *stream)
|
|
{
|
|
*stream >> m_StartupRequest;
|
|
*stream >> m_ShutdownRequest;
|
|
CombatAI::Load (stream);
|
|
}
|
|
|
|
//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
|
|
//
|
|
void MechAI::NotifyShutDownMechsShotFired(const Adept::Entity::CollisionQuery& query, MWObject& shooter)
|
|
{
|
|
if (m_gShutdownMechAIs == 0)
|
|
{
|
|
return;
|
|
}
|
|
|
|
{for (std::list<MechAI*>::iterator i = m_gShutdownMechAIs->begin();
|
|
i != m_gShutdownMechAIs->end();
|
|
++i)
|
|
{
|
|
(*i)->NotifyShotFired(query,shooter);
|
|
}}
|
|
}
|
|
|
|
bool MechAI::ShouldRunScript()
|
|
{
|
|
if (m_SquadOrders.GetPointer() != 0)
|
|
{
|
|
return (m_SquadOrders->ShouldRunScript());
|
|
}
|
|
|
|
return (inherited::ShouldRunScript());
|
|
}
|
|
|
|
bool MechAI::GetLeaderAlignment(int& alignment)
|
|
{
|
|
if (m_SquadOrders.GetPointer() != 0)
|
|
{
|
|
return (m_SquadOrders->GetLeaderAlignment(alignment));
|
|
}
|
|
|
|
return (inherited::GetLeaderAlignment(alignment));
|
|
}
|