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.
847 lines
20 KiB
C++
847 lines
20 KiB
C++
//===========================================================================//
|
|
// File: MWPlayer.cpp //
|
|
//---------------------------------------------------------------------------//
|
|
// Date Who Modification //
|
|
// -------- --- ---------------------------------------------------------- //
|
|
// 09/09/98 JSE Inital base class based off of Shadowrun/Adept //
|
|
//---------------------------------------------------------------------------//
|
|
// Copyright (C) 1998, Fasa Interactive //
|
|
// All Rights reserved worldwide //
|
|
// This unpublished sourcecode is PROPRIETARY and CONFIDENTIAL //
|
|
//===========================================================================//
|
|
|
|
#include "MW4Headers.hpp"
|
|
|
|
#include "MWPlayer.hpp"
|
|
#include "MWMover.hpp"
|
|
#include "Vehicle.hpp"
|
|
#include "VehicleInterface.hpp"
|
|
#include "MWMission.hpp"
|
|
#include "MWApplication.hpp"
|
|
#include "playerai.hpp"
|
|
#include "AI_Groups.hpp"
|
|
#include "Team.hpp"
|
|
|
|
#include <Adept\EntityClassData.hpp>
|
|
#include <Adept\EntityManager.hpp>
|
|
#include <Adept\Interface.hpp>
|
|
#include <Adept\Application.hpp>
|
|
#include <Adept\Map.hpp>
|
|
#include <adept\collisionvolume.hpp>
|
|
#include <Adept\CollisionGrid.hpp>
|
|
#include <Adept\DamageObject.hpp>
|
|
|
|
using namespace MW4AI;
|
|
|
|
//#############################################################################
|
|
//############################### MWPlayer ##############################
|
|
//#############################################################################
|
|
|
|
MWPlayer::ClassData*
|
|
MWPlayer::DefaultData = NULL;
|
|
|
|
|
|
//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
|
|
//
|
|
void
|
|
MWPlayer::InitializeClass()
|
|
{
|
|
Verify(!DefaultData);
|
|
DefaultData =
|
|
new ClassData(
|
|
MWPlayerClassID,
|
|
"MechWarrior4::MWPlayer",
|
|
Player::DefaultData,
|
|
0, NULL,
|
|
(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
|
|
MWPlayer::TerminateClass()
|
|
{
|
|
Unregister_Object(DefaultData);
|
|
delete DefaultData;
|
|
DefaultData = NULL;
|
|
}
|
|
|
|
//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
|
|
//
|
|
MWPlayer*
|
|
MWPlayer::Make(
|
|
CreateMessage *message,
|
|
ReplicatorID *base_id
|
|
)
|
|
{
|
|
Check_Object(message);
|
|
gos_PushCurrentHeap(Heap);
|
|
MWPlayer *new_entity =
|
|
new MWPlayer(DefaultData, message, base_id, NULL);
|
|
gos_PopCurrentHeap();
|
|
Check_Object(new_entity);
|
|
return new_entity;
|
|
}
|
|
|
|
//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
|
|
//
|
|
ObjectID MWPlayer::FindDropZone(int team)
|
|
{
|
|
if (team != MWApplication::No_Team)
|
|
{
|
|
NameTable *table = NameTable::GetInstance();
|
|
|
|
int size(table->nameTableArray[NameTable::DropZoneArray].GetLength());
|
|
|
|
{for (int i = 0;
|
|
i < size;
|
|
++i)
|
|
{
|
|
NameTableEntry *data;
|
|
|
|
data = &table->nameTableArray [NameTable::DropZoneArray][i];
|
|
Adept::Entity* ent = data->dataPointer->GetCurrent ();
|
|
|
|
if (ent != 0)
|
|
{
|
|
int team_number = MWApplication::NameToTeamNumber(ent->instanceName);
|
|
|
|
if (team_number == team)
|
|
{
|
|
return (ent->objectID);
|
|
}
|
|
}
|
|
}}
|
|
}
|
|
|
|
ObjectID obj_id = (NameTable::GetInstance()->FindID("PlayerStart"));
|
|
|
|
if (obj_id == NameTable::NullObjectID)
|
|
{
|
|
STOP(("No valid dropzone"));
|
|
}
|
|
|
|
return obj_id;
|
|
|
|
}
|
|
|
|
//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
|
|
//
|
|
MWPlayer::MWPlayer(
|
|
ClassData *class_data,
|
|
CreateMessage *message,
|
|
ReplicatorID *base_id,
|
|
ElementRenderer::Element *element
|
|
):
|
|
Player(class_data, message, base_id, element),
|
|
m_Team(MWApplication::No_Team)
|
|
{
|
|
Check_Pointer(this);
|
|
Check_Object(message);
|
|
|
|
isDropped = false;
|
|
|
|
|
|
Mission::GetInstance()->AddChild(this);
|
|
|
|
//
|
|
//----------------------
|
|
// Create the interface
|
|
//----------------------
|
|
//
|
|
playerInterface = NULL;
|
|
interfaceResourceID = ResourceID::Null;
|
|
if (GetReplicatorMode() == Replicator::ClientMasterMode || GetReplicatorMode() == Replicator::MasterMode)
|
|
{
|
|
Resource stream(message->interfaceResourceID);
|
|
Verify(stream.DoesResourceExist());
|
|
//ReplicatorID id = owningConnection->GetNextReplicatorID();
|
|
ReplicatorID interface_id = Connection::Hermit->GetNextReplicatorID();
|
|
playerInterface = Cast_Object(Interface *, CreateEntity(&stream, &interface_id));
|
|
Check_Object(playerInterface);
|
|
interfaceResourceID = message->interfaceResourceID;
|
|
}
|
|
|
|
|
|
|
|
|
|
//
|
|
//-------------------
|
|
// Create the vehicle
|
|
//-------------------
|
|
//
|
|
|
|
Resource mech_instance(message->vehicleResourceID);
|
|
mech_instance.LoadData();
|
|
Verify(mech_instance.DoesResourceExist());
|
|
|
|
void *new_data = new BYTE[mech_instance.GetSize()];
|
|
Mem_Copy(new_data, mech_instance.GetPointer(), mech_instance.GetSize(), mech_instance.GetSize());
|
|
|
|
MWObject::CreateMessage *create_message =
|
|
Cast_Pointer(MWObject::CreateMessage*, new_data);
|
|
Check_Object(create_message);
|
|
|
|
create_message->pilotDecal = message->pilotDecal;
|
|
create_message->teamDecal = message->teamDecal;
|
|
|
|
|
|
Team* team = 0;
|
|
if (message->teamNumber != MWApplication::No_Team)
|
|
{
|
|
team = MWApplication::GetInstance()->teams[message->teamNumber]->GetCurrent();
|
|
if (team)
|
|
{
|
|
create_message->skinPrefix = team->GetTeamPrefix();
|
|
}
|
|
}
|
|
else if (MWApplication::GetInstance()->networkingFlag)
|
|
{
|
|
create_message->skinPrefix = message->skinPrefix;
|
|
}
|
|
// for campaign skin - jcem
|
|
else {
|
|
extern bool g_bCOOP;
|
|
if (g_bCOOP) { // m_isCampaign == (serverFlag && !networkingFlag)
|
|
create_message->skinPrefix = message->skinPrefix;
|
|
}
|
|
}
|
|
// for campaign skin - jcem
|
|
|
|
|
|
|
|
|
|
MemoryStream mech_stream(create_message, create_message->messageLength);
|
|
|
|
//Insure that we start with a bad id and don't get our stuff set since we are going to do it later
|
|
Mech::CreateMessage *mech_message = Cast_Pointer(Mech::CreateMessage *, mech_stream.GetPointer());
|
|
mech_message->nameID = NameTableEntry::BuildObjectID(NameTable::TableSize, 0);
|
|
if(mech_message->initialAge == 0.0f)
|
|
{
|
|
Stuff::LinearMatrix4D drop_location = Stuff::LinearMatrix4D::Identity;
|
|
drop_location.BuildTranslation(Point3D::HellPoint);
|
|
|
|
mech_message->localToParent = drop_location;
|
|
}
|
|
vehicle = CreateEntity(&mech_stream, base_id);
|
|
Check_Object(vehicle);
|
|
|
|
|
|
//SPEW(("jerryeds","CREATE MECH %d:%d", vehicle->GetReplicatorID().connectionID, vehicle->GetReplicatorID().localID));
|
|
|
|
|
|
delete new_data;
|
|
|
|
|
|
|
|
|
|
if (team)
|
|
{
|
|
((Vehicle*)vehicle)->SetTeam(message->teamNumber);
|
|
team->AddMemberToTeam((Vehicle*)vehicle);
|
|
m_Team = message->teamNumber;
|
|
}
|
|
|
|
vehicle->SetPropType(PlayerPropType);
|
|
Check_Object(Map::GetInstance());
|
|
Map::GetInstance()->AddChild(vehicle);
|
|
|
|
|
|
EntityManager::GetInstance()->RemoveMover((Mover*)vehicle);
|
|
|
|
ReplicatorID mech_id = vehicle->GetReplicatorID();
|
|
vehicle->instanceName =
|
|
Network::GetInstance()->GetConnection(mech_id.connectionID)->GetConnectionName();
|
|
|
|
if(!vehicle->instanceName || !vehicle->instanceName.GetLength())
|
|
{
|
|
char buffer[10];
|
|
sprintf(buffer, "%d::", owningConnection->GetID());
|
|
MString new_name;
|
|
new_name = buffer + vehicle->instanceName;
|
|
vehicle->instanceName = new_name;
|
|
}
|
|
|
|
Check_Object(NameTable::GetInstance());
|
|
vehicle->objectID = NameTable::GetInstance()->FindID(vehicle->instanceName);
|
|
|
|
if(vehicle->objectID == NameTable::NullObjectID)
|
|
NameTable::GetInstance()->AddEntry(vehicle, NameTable::VehicleArray);
|
|
else
|
|
NameTable::GetInstance()->SetData(vehicle);
|
|
if (owningConnection != Connection::Local)
|
|
{
|
|
vehicle->SetAlignment(Entity::Enemy);
|
|
}
|
|
|
|
Check_Object(EntityManager::GetInstance());
|
|
EntityManager::GetInstance()->AddMover((Mover*)vehicle);
|
|
|
|
|
|
// connect to the drop zone
|
|
|
|
if (message->initialAge != 0.0f)
|
|
{
|
|
|
|
ElementRenderer::Element *element = vehicle->GetElement();
|
|
Check_Object(element);
|
|
ReceiveDropZone(element->GetNewLocalToParent());
|
|
|
|
|
|
}
|
|
else
|
|
{
|
|
dropZone = FindDropZone(m_Team);
|
|
|
|
Stuff::LinearMatrix4D drop_location = Stuff::LinearMatrix4D::Identity;
|
|
drop_location.BuildTranslation(Point3D::HellPoint);
|
|
|
|
vehicle->SetNewLocalToParent(drop_location);
|
|
vehicle->SyncMatrices(true);
|
|
Map::GetInstance()->UpdateZone(vehicle);
|
|
}
|
|
|
|
|
|
//
|
|
//----------------------------
|
|
//Store the Vehicle ResourceID
|
|
//----------------------------
|
|
//
|
|
vehicleResourceID = message->vehicleResourceID;
|
|
|
|
m_LockedRects.reserve (50);
|
|
}
|
|
|
|
//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
|
|
//
|
|
|
|
void
|
|
MWPlayer::Respawn(CreateMessage *message)
|
|
{
|
|
|
|
Check_Pointer(this);
|
|
Check_Object(message);
|
|
|
|
isDropped = false;
|
|
|
|
|
|
//
|
|
//----------------------
|
|
// Respawn the interface
|
|
//----------------------
|
|
//
|
|
|
|
Entity::CreateMessage *interface_respawn_message = NULL;
|
|
|
|
|
|
interfaceResourceID = ResourceID::Null;
|
|
if (GetReplicatorMode() == Replicator::ClientMasterMode || GetReplicatorMode() == Replicator::MasterMode)
|
|
{
|
|
Resource stream(message->interfaceResourceID);
|
|
Verify(stream.DoesResourceExist());
|
|
//ReplicatorID id = owningConnection->GetNextReplicatorID();
|
|
//ReplicatorID interface_id = Connection::Hermit->GetNextReplicatorID();
|
|
|
|
interface_respawn_message =
|
|
Cast_Pointer(Entity::CreateMessage*, stream.GetPointer());
|
|
|
|
//playerInterface->Respawn(new_message);
|
|
//Check_Object(playerInterface);
|
|
|
|
}
|
|
|
|
//
|
|
//-------------------
|
|
// Create the vehicle
|
|
//-------------------
|
|
//
|
|
|
|
Resource mech_instance(message->vehicleResourceID);
|
|
Verify(mech_instance.DoesResourceExist());
|
|
|
|
void *new_data = new BYTE[mech_instance.GetSize()];
|
|
Mem_Copy(new_data, mech_instance.GetPointer(), mech_instance.GetSize(), mech_instance.GetSize());
|
|
|
|
MWObject::CreateMessage *create_message =
|
|
Cast_Pointer(MWObject::CreateMessage*, new_data);
|
|
Check_Object(create_message);
|
|
|
|
create_message->pilotDecal = message->pilotDecal;
|
|
create_message->teamDecal = message->teamDecal;
|
|
//create_message->skinPrefix = message->skinPrefix;
|
|
|
|
MemoryStream mech_stream(create_message, create_message->messageLength);
|
|
|
|
|
|
vehicle->Respawn(create_message);
|
|
Check_Object(vehicle);
|
|
|
|
delete[] new_data;
|
|
|
|
// we do this after the vehicle for a respawn since farther down
|
|
// the stream there is no reconnect
|
|
if (interface_respawn_message != NULL)
|
|
{
|
|
|
|
playerInterface->Respawn(interface_respawn_message);
|
|
Check_Object(playerInterface);
|
|
}
|
|
|
|
|
|
// connect to the drop zone
|
|
if (message->initialAge != 0.0f)
|
|
{
|
|
ElementRenderer::Element *element = vehicle->GetElement();
|
|
Check_Object(element);
|
|
ReceiveDropZone(element->GetNewLocalToParent());
|
|
|
|
}
|
|
else
|
|
{
|
|
dropZone = FindDropZone(m_Team);
|
|
|
|
// Stuff::LinearMatrix4D drop_location = Stuff::LinearMatrix4D::Identity;
|
|
// drop_location.BuildTranslation(Point3D::HellPoint);
|
|
|
|
// vehicle->SetNewLocalToParent(drop_location);
|
|
// vehicle->SyncMatrices(true);
|
|
// Map::GetInstance()->UpdateZone(vehicle);
|
|
}
|
|
if (owningConnection != Connection::Local)
|
|
{
|
|
vehicle->SetAlignment(Entity::Enemy);
|
|
}
|
|
|
|
|
|
//
|
|
//----------------------------
|
|
//Store the Vehicle ResourceID
|
|
//----------------------------
|
|
//
|
|
vehicleResourceID = message->vehicleResourceID;
|
|
|
|
|
|
}
|
|
//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
|
|
//
|
|
MWPlayer::~MWPlayer()
|
|
{
|
|
ClearPathLock (true);
|
|
|
|
#if 0
|
|
|
|
// happens automaticly with plugs.
|
|
|
|
if ((vehicle != 0) &&
|
|
(m_Team != MWApplication::No_Team))
|
|
{
|
|
Team* team = MWApplication::GetInstance()->teams[m_Team]->GetCurrent();
|
|
|
|
if (team != 0)
|
|
{
|
|
team->RemoveMemberFromTeam((Vehicle*)vehicle);
|
|
}
|
|
}
|
|
#endif
|
|
|
|
}
|
|
|
|
//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
|
|
//
|
|
|
|
void
|
|
MWPlayer::ConnectToVehicle(void)
|
|
{
|
|
Check_Object(vehicle);
|
|
Check_Object(playerInterface);
|
|
|
|
Player::ConnectToVehicle();
|
|
|
|
GetInterface()->ConnectVehicleToInterface(GetVehicle(),this);
|
|
}
|
|
|
|
//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
|
|
//
|
|
void
|
|
MWPlayer::PreCollisionExecute(Time till)
|
|
{
|
|
Check_Object(this);
|
|
PRECOLLISION_LOGIC("MWPlayer");
|
|
|
|
Player::PreCollisionExecute(till);
|
|
|
|
|
|
ClearPathLock (false);
|
|
PathLock ();
|
|
}
|
|
|
|
|
|
|
|
//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
|
|
//
|
|
MWPlayer::LancemateCommandProxy::LancemateCommandProxy()
|
|
: m_Mode(INVALID)
|
|
{
|
|
}
|
|
|
|
bool
|
|
MWPlayer::LancemateCommandProxy::SetMode(Mode mode)
|
|
{
|
|
Verify(mode != INVALID);
|
|
|
|
stlport::vector<MWObject *> lance;
|
|
MW4AI::Groups::GetLancemates (lance);
|
|
m_Mode = INVALID;
|
|
switch (mode)
|
|
{
|
|
case LANCEMATE_1:
|
|
if (lance.size () < 1)
|
|
return false;
|
|
break;
|
|
case LANCEMATE_2:
|
|
if (lance.size () < 2)
|
|
return false;
|
|
break;
|
|
case LANCEMATE_3:
|
|
if (lance.size () < 3)
|
|
return false;
|
|
break;
|
|
case LANCEMATE_ALL:
|
|
if (lance.size ()== 0)
|
|
return false;
|
|
break;
|
|
}
|
|
|
|
m_Mode = mode;
|
|
return (true);
|
|
}
|
|
|
|
bool
|
|
MWPlayer::LancemateCommandProxy::IssueCommand(Vehicle* v, MW4AI::LancemateCommands::ID command)
|
|
{
|
|
if ((v == 0) ||
|
|
(v->GetGroups().size() == 0))
|
|
{
|
|
return (false);
|
|
}
|
|
|
|
Check_Object(v);
|
|
|
|
Group::identifier group_id;
|
|
|
|
if (MW4AI::Groups::GetLancemateGroup(v->GetGroups(),group_id) == false)
|
|
{
|
|
return (false);
|
|
}
|
|
|
|
std::vector<unsigned int> indices_to_add;
|
|
|
|
switch (m_Mode)
|
|
{
|
|
case LANCEMATE_1: { indices_to_add.push_back(1); break; }
|
|
case LANCEMATE_2: { indices_to_add.push_back(2); break; }
|
|
case LANCEMATE_3: { indices_to_add.push_back(3); break; }
|
|
case LANCEMATE_ALL:
|
|
{
|
|
indices_to_add.push_back(1);
|
|
indices_to_add.push_back(2);
|
|
indices_to_add.push_back(3);
|
|
break;
|
|
}
|
|
default:
|
|
{
|
|
return (false);
|
|
}
|
|
}
|
|
|
|
MW4AI::LancemateCommands::lancemate_list lancemates;
|
|
|
|
{for (std::vector<unsigned int>::const_iterator i = indices_to_add.begin();
|
|
i != indices_to_add.end();
|
|
++i)
|
|
{
|
|
Adept::ObjectID id;
|
|
if (MW4AI::Groups::GetMember(group_id,*i,id) == true)
|
|
{
|
|
lancemates.push_back(id);
|
|
}
|
|
}}
|
|
|
|
MW4AI::LancemateCommands::Execute(command,lancemates);
|
|
|
|
m_Mode = INVALID;
|
|
|
|
return (true);
|
|
}
|
|
|
|
//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
|
|
//
|
|
//void
|
|
// MWPlayer::PostCollisionExecute(Time till)
|
|
//{
|
|
// Check_Object(this);
|
|
|
|
// Player::PostCollisionExecute(till);
|
|
|
|
|
|
//}
|
|
|
|
//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
|
|
//
|
|
void
|
|
MWPlayer::PostCollisionExecute(Time till)
|
|
{
|
|
Check_Object(this);
|
|
POSTCOLLISION_LOGIC("MWPlayer");
|
|
|
|
|
|
if (playerInterface)
|
|
{
|
|
|
|
VehicleInterface *veh_inf = Cast_Object(VehicleInterface *, playerInterface);
|
|
if (veh_inf->IsObserving(true) && (veh_inf->observingEntity.GetCurrent() != NULL))
|
|
{
|
|
SetNewLocalToParent(veh_inf->observingEntity.GetCurrent()->GetLocalToWorld());
|
|
}
|
|
else
|
|
{
|
|
SetNewLocalToParent(vehicle->GetLocalToWorld());
|
|
}
|
|
|
|
}
|
|
else
|
|
{
|
|
SetNewLocalToParent(vehicle->GetLocalToWorld());
|
|
}
|
|
|
|
if (m_ObjectsToDestroy.size() > 0)
|
|
{
|
|
{for (stlport::vector<ObjectID>::iterator i = m_ObjectsToDestroy.begin();
|
|
i != m_ObjectsToDestroy.end();
|
|
++i)
|
|
{
|
|
Entity* ent = NameTable::GetInstance()->FindData(*i);
|
|
|
|
if (ent != 0)
|
|
{
|
|
Entity::TakeDamageMessage damage_message(
|
|
ent->GetReplicatorID(),
|
|
ent->GetReplicatorID(),
|
|
// 100000,
|
|
0.0f,
|
|
// MSL 5.05 Armor Mode
|
|
0,
|
|
Adept::RammingDamageFromAboveType,
|
|
Stuff::UnitVector3D(1,0,0),
|
|
(Stuff::Point3D)ent->GetLocalToWorld(),
|
|
0,
|
|
false,
|
|
Entity::TakeDamageMessage::DefaultWeaponType
|
|
);
|
|
|
|
ent->Receive(&damage_message);
|
|
}
|
|
}}
|
|
|
|
m_ObjectsToDestroy.clear();
|
|
}
|
|
|
|
SyncMatrices(true);
|
|
|
|
//skip player & driver
|
|
Entity::PostCollisionExecute(till);
|
|
}
|
|
|
|
|
|
|
|
//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
|
|
//
|
|
void MWPlayer::TestInstance() const
|
|
{
|
|
Verify(IsDerivedFrom(DefaultData));
|
|
}
|
|
|
|
void MWPlayer::ClearPathLock (bool quitting)
|
|
{
|
|
stlport::vector<LockData *>::iterator iter;
|
|
|
|
for (iter = m_PathLock.begin ();iter != m_PathLock.end ();iter++)
|
|
{
|
|
if (!quitting)
|
|
{
|
|
MW4AI::g_MissionGraph->PassableLocalOverride ((*iter)->locx,(*iter)->locz,(*iter)->olddata);
|
|
MW4AI::RemoveBlockLocal ((*iter)->locx,(*iter)->locz,(MWObject *) this);
|
|
}
|
|
delete (*iter);
|
|
}
|
|
m_PathLock.clear ();
|
|
|
|
Verify (m_LockedRects.size () == 0);
|
|
stlport::vector<Rect4D *>::iterator iter2;
|
|
for (iter2 = m_LockedRects.begin ();iter2 != m_LockedRects.end ();iter2++)
|
|
{
|
|
g_Rect4DHash->RemoveRect (*iter2);
|
|
g_Rect4DHash->VerifyRectGone (*iter2);
|
|
delete (*iter2);
|
|
}
|
|
m_LockedRects.clear ();
|
|
}
|
|
|
|
bool MWPlayer::AddLockCell (const Stuff::Point3D& loc)
|
|
{
|
|
unsigned short value;
|
|
int locx,locz;
|
|
Point3D pt;
|
|
|
|
if (loc.x < MW4AI::MinX)
|
|
return true;
|
|
if (loc.z < MW4AI::MinX)
|
|
return true;
|
|
if (loc.x >= MW4AI::MaxX)
|
|
return true;
|
|
if (loc.z >= MW4AI::MaxZ)
|
|
return true;
|
|
|
|
locx = (int) (loc.x / BLOCK_GRID_RES);
|
|
locz = (int) (loc.z / BLOCK_GRID_RES);
|
|
|
|
MWObject *who;
|
|
|
|
who = MW4AI::BlockerLocal (locx,locz);
|
|
if (who == (MWObject *) this)
|
|
return true;
|
|
if (who)
|
|
return false;
|
|
|
|
value = MW4AI::g_MissionGraph->PassableLocal (locx,locz);
|
|
if (value & (MOVEPASSNOW_FLAG))
|
|
return false;
|
|
|
|
MW4AI::g_MissionGraph->PassableLocalOverride (locx,locz,(unsigned short)(value|MOVEPASSNOW_FLAG));
|
|
m_PathLock.push_back (new LockData (locx,locz,value));
|
|
MW4AI::AddBlockLocal (locx,locz,(MWObject *) this);
|
|
|
|
return true;
|
|
}
|
|
|
|
bool MWPlayer::LockSquare (const Point3D& loc,Stuff::Scalar rad)
|
|
{
|
|
int sqrindex[8][2] = {
|
|
{-1,-1},
|
|
{0,-1},
|
|
{1,-1},
|
|
{-1,0},
|
|
{1,0},
|
|
{-1,1},
|
|
{0,1},
|
|
{1,1}
|
|
};
|
|
int i;
|
|
Point3D pt (0,0,0);
|
|
|
|
if (rad < 10.0f)
|
|
rad = 10.0f;
|
|
for (i=0;i<8;i++)
|
|
{
|
|
pt.x = loc.x+(sqrindex[i][0]*rad);
|
|
pt.z = loc.z+(sqrindex[i][1]*rad);
|
|
|
|
if (LockedByMe (pt))
|
|
continue;
|
|
|
|
AddLockCell (pt);
|
|
}
|
|
return false;
|
|
}
|
|
bool MWPlayer::PathLock (bool secondpass)
|
|
{
|
|
Check_Object (GetVehicle ());
|
|
Check_Object (GetVehicle ()->GetGameModel ());
|
|
|
|
if (!GetVehicle())
|
|
return false;
|
|
|
|
|
|
if (playerInterface)
|
|
{
|
|
Check_Object (playerInterface);
|
|
|
|
if (playerInterface->executionState->GetState () == VehicleInterface::ExecutionStateEngine::AIRunningState)
|
|
return false;
|
|
}
|
|
|
|
OBB *obb;
|
|
CollisionVolume *col;
|
|
col = vehicle->GetSolidVolume ();
|
|
if (!col)
|
|
return false;
|
|
obb = &(col->m_localSpaceBounds);
|
|
if (!obb)
|
|
return false;
|
|
Stuff::Scalar rad = obb->sphereRadius;
|
|
rad *= 1.5f;
|
|
|
|
|
|
Stuff::Scalar speed,movemps,slowtime;
|
|
UnitVector3D forward;
|
|
Point3D step,loc;
|
|
int i,timelen;
|
|
|
|
const Vehicle__GameModel *model = static_cast<const Vehicle__GameModel *> (vehicle->GetGameModel ()) ;
|
|
|
|
loc = (Point3D) vehicle->GetLocalToWorld ();
|
|
vehicle->GetLocalToWorld ().GetLocalForwardInWorld (&forward);
|
|
step = forward;
|
|
|
|
speed = GetVehicle ()->currentSpeedMPS;
|
|
LockSquare (loc,rad);
|
|
AddLockCell (loc);
|
|
if (speed == 0)
|
|
{
|
|
return false;
|
|
}
|
|
movemps = speed;
|
|
Max_Clamp(movemps, model->maxSpeed);
|
|
Min_Clamp(movemps, model->minSpeed);
|
|
slowtime = movemps / model->decceleration;
|
|
|
|
Min_Clamp (movemps,1);
|
|
step *= movemps;
|
|
|
|
slowtime += 1.0f; //extra second of buffer
|
|
timelen = (int) (slowtime);
|
|
|
|
int maxi;
|
|
Scalar delta;
|
|
delta = 10.0f/movemps;
|
|
step *= delta;
|
|
|
|
maxi = (int) (timelen / delta);
|
|
|
|
Min_Clamp (maxi,1);
|
|
loc += step;
|
|
for (i=0;i<maxi;i++)
|
|
{
|
|
LockSquare (loc,rad);
|
|
AddLockCell (loc);
|
|
loc += step;
|
|
}
|
|
|
|
return false;
|
|
}
|
|
|
|
void
|
|
MWPlayer::AddObjectToDestroy(ObjectID who)
|
|
{
|
|
m_ObjectsToDestroy.push_back(who);
|
|
}
|