Files
Cyd 2b8ca921cb Initial full mirror of c:\VWE (source + assets + toolchain + outputs) via Git LFS
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.
2026-06-24 21:28:16 -05:00

2586 lines
66 KiB
C++

//===========================================================================//
// File: Entity.cpp //
//---------------------------------------------------------------------------//
// Date Who Modification //
// -------- --- ---------------------------------------------------------- //
// 11/29/94 JMA Initial coding. //
// 08/25/97 JMA Infrastructure changes //
// 08/25/97 ECH Infrastructure changes //
//---------------------------------------------------------------------------//
// Copyright (C) 1994-97, Virtual World Entertainment, Inc. //
// All Rights reserved worldwide //
// This unpublished sourcecode is PROPRIETARY and CONFIDENTIAL //
//===========================================================================//
#include "AdeptHeaders.hpp"
#include "EntityManager.hpp"
#include "EntityAttribute.hpp"
#include "RendererManager.hpp"
#include "VideoComponentWeb.hpp"
#include "EntityClassData.hpp"
#include "Map.hpp"
#include "Application.hpp"
#include <ElementRenderer\GroupElement.hpp>
#include <ElementRenderer\StateChange.hpp>
#include "DamageObject.hpp"
#include "GameModelAttribute.hpp"
#include "NameTable.hpp"
#include "CollisionVolume.hpp"
#include "CollisionGrid.hpp"
#include "Zone.hpp"
#include "Tile.hpp"
#include <MLR\MLRTexturePool.hpp>
#include <MLR\MLRTexture.hpp>
//#define HUNT_BUG "jmalbert"
//#define TIME_BUG "your_loginname_here"
extern int g_nMR;
char g_LastEntity[255] = "";
//#############################################################################
//############################# Entity ##################################
//#############################################################################
HGOSHEAP
Entity::s_Heap = NULL,
Entity::s_CollisionHeap = NULL;
Entity::ClassData*
Entity::DefaultData = NULL;
const Receiver::MessageEntry
Entity::MessageEntries[]=
{
MESSAGE_ENTRY(Entity, Destroy),
MESSAGE_ENTRY(Entity, Update),
MESSAGE_ENTRY(Entity, TakeDamage),
MESSAGE_ENTRY(Entity, BecomeInteresting)
};
int Entity::s_EntitiesSynced;
DWORD Entity_Count;
DECLARE_TIMER(static, Renderer_Loading);
//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
//
void
Entity::InitializeClass()
{
Verify(!s_Heap);
s_Heap = gos_CreateMemoryHeap("Entities", 0, g_LibraryHeap);
Check_Pointer(s_Heap);
Verify(!s_CollisionHeap);
s_CollisionHeap = gos_CreateMemoryHeap("Collision", 0, g_LibraryHeap);
Check_Pointer(s_CollisionHeap);
Check_Object(ExecutionStateEngine::DefaultData);
Verify(!DefaultData);
DefaultData =
new ClassData(
EntityClassID,
"Adept::Entity",
BaseClass::DefaultData,
ELEMENTS(MessageEntries), MessageEntries,
Entity::Make,
Entity::CreateMessage::ConstructCreateMessage,
ExecutionStateEngine::DefaultData,
Entity::GameModel::ConstructGameModel,
(Entity::GameModel::Factory)GameModel::ConstructOBBStream,
Entity::GameModel::ReadAndVerify,
Entity::GameModel::WriteToText,
Entity::GameModel::SaveGameModel
);
Check_Object(DefaultData);
INDIRECT_STATE_ATTRIBUTE(
Entity,
ExecutionState,
executionState,
Entity__ExecutionStateEngine
);
CUSTOM_DIRECT_ATTRIBUTE(
Entity,
IsDestroyed,
isDestroyed,
int,
IntClassID
);
CUSTOM_DIRECT_ATTRIBUTE(
Entity,
VisualRepresentation,
visualRepresentation,
int,
IntClassID
);
DIRECT_ATTRIBUTE(
Entity,
LightIntensity,
lightIntensity,
Scalar
);
CUSTOM_DIRECT_GAME_MODEL_ATTRIBUTE(
Entity__GameModel,
Collider,
collider,
bool,
BoolClassID
);
CUSTOM_DIRECT_GAME_MODEL_ATTRIBUTE(
Entity__GameModel,
CanBeWalkedOn,
canBeWalkedOn,
bool,
BoolClassID
);
CUSTOM_DIRECT_GAME_MODEL_ATTRIBUTE(
Entity__GameModel,
CanBeShot,
canBeShot,
bool,
BoolClassID
);
CUSTOM_DIRECT_GAME_MODEL_ATTRIBUTE(
Entity__GameModel,
WaterSurface,
waterSurface,
bool,
BoolClassID
);
CUSTOM_DIRECT_GAME_MODEL_ATTRIBUTE(
Entity__GameModel,
OBBCollides,
OBBCollides,
bool,
BoolClassID
);
{
AttributeEntry *attribute_entry =
new LocalToWorldAttributeEntry(
LocalToWorldAttributeID,
"LocalToWorld"
);
Check_Object(attribute_entry);
Check_Object(DefaultData);
DefaultData->attributeTable.AddAttributeEntry(attribute_entry);
}
#if !defined(NO_STATS)
AddStatistic("Entities", "entities", gos_DWORD, &Entity_Count, 0);
AddStatistic("Entities Sync'd", "entities", gos_DWORD, &s_EntitiesSynced, Stat_AutoReset);
#endif
Initialize_Timer(Renderer_Loading, "Renderer Loading");
}
//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
//
void
Entity::TerminateClass()
{
Check_Object(DefaultData);
delete DefaultData;
DefaultData = NULL;
Check_Pointer(s_CollisionHeap);
gos_DestroyMemoryHeap(s_CollisionHeap);
s_CollisionHeap = NULL;
Check_Pointer(s_Heap);
gos_DestroyMemoryHeap(s_Heap);
s_Heap = NULL;
}
//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
//
Entity::ClassData*
Entity::GetClassData()
{
return Cast_Pointer(ClassData*, classData);
}
//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
//
Entity*
Entity::Make(
const CreateMessage *message,
ReplicatorID *base_id
)
{
gos_PushCurrentHeap(s_Heap);
Entity *new_entity = new Entity(DefaultData, message, base_id, NULL);
Check_Object(new_entity);
gos_PopCurrentHeap();
return new_entity;
}
//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
//
Replicator::CreateMessage*
Entity::SaveMakeMessage(MemoryStream *stream, ResourceFile *res_file)
{
Check_Object(this);
Check_Object(stream);
//
//-----------------------------------
// Make sure that the stuff is synced
//-----------------------------------
//
#if 0
SyncMatrices(true);
#endif
//
//---------------------------------------------------------------------
// Make sure there is enough room for the factory request on the stream
//---------------------------------------------------------------------
//
stream->AllocateBytes(sizeof(CreateMessage));
BaseClass::SaveMakeMessage(stream, res_file);
CreateMessage *message =
Cast_Pointer(CreateMessage*, stream->GetPointer());
message->messageLength = sizeof(*message);
//
//----------------------
// Save the data list ID
//----------------------
//
Verify(dataListResource.DoesResourceExist());
message->dataListID = dataListResource.GetResourceID();
//
//-------------------------------------
// Save the initial state of the entity
//-------------------------------------
//
message->localToParent = initialLocalToParent;
message->initialAge =
static_cast<Scalar>(lastExecuted - lastParameterization);
Check_Object(executionState);
executionState->Save(&message->executionState);
//
//--------------------------------
// Save the Save the instance Name
//--------------------------------
//
if(NameTable::GetInstance())
{
Check_Object(NameTable::GetInstance());
message->nameID = NameTable::GetInstance()->FindID(instanceName);
}
else
{
message->nameID = NameTable::NullObjectID;
}
//
//----------------------
//Save out the Alignment
//----------------------
//
message->alignment = alignment;
return message;
}
//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
//
void
Entity::Reuse(
const CreateMessage *message,
ReplicatorID *base_id
)
{
Check_Object(this);
Check_Object(message);
//
//-----------------------------------------
// Verify that an entity can be created now
//-----------------------------------------
//
BaseClass::Reuse(message, base_id);
#ifdef _ARMOR
Application *app = Application::GetInstance();
Check_Object(app);
Verify(!app->InPreCollisionPhase());
#endif
#if defined(HUNT_BUG)
SPEW((HUNT_BUG, "Reusing %s(+", GetClassString()));
Spew(HUNT_BUG, GetReplicatorID());
if (owningConnection==Connection::Local)
SPEW((HUNT_BUG, "*+"));
switch (GetReplicatorMode())
{
case MasterMode:
SPEW((HUNT_BUG, ") as master"));
break;
case IndependentMode:
SPEW((HUNT_BUG, ") as independent"));
break;
case HermitMode:
SPEW((HUNT_BUG, ") as hermit"));
break;
case ReplicantMode:
SPEW((HUNT_BUG, ") as replicant"));
break;
case ClientMasterMode:
SPEW((HUNT_BUG, ") as ClientMasterMode"));
break;
case ServerMasterMode:
SPEW((HUNT_BUG, ") as ServerMasterMode"));
break;
}
#endif
//
//----------------------
// Set up the data list and
//----------------------
//
lastExecuted = gos_GetElapsedTime();
lastParameterization = lastExecuted - message->initialAge;
SetInterestMask(DormantInterestLevel);
updateFlags = 0;
#if defined(TIME_BUG)
SPEW((TIME_BUG, "Reusing %s(+", GetClassString()));
Spew(TIME_BUG, GetReplicatorID());
SPEW((TIME_BUG, ") at time %f", lastExecuted.GetSeconds()));
#endif
lightIntensity = 0.0f;
//
//----------------------------------------------------------------------
// Set up the game model and set the flags that come from the game model
//----------------------------------------------------------------------
//
Verify(dataListResource.DoesResourceExist());
Verify(gameModelResource.DoesResourceExist());
const GameModel *model = GetGameModel();
Check_Object(model);
replicatorFlags &= ~GameModelMask;
replicatorFlags |= model->defaultFlags;
if (IsACollider() && IsTileBound())
replicatorFlags &= ~ColliderFlag;
//
//--------------------------
// Create the locator object
//--------------------------
//
Check_Object(VideoRenderer::Instance);
Resource element_stream(model->elementResourceID);
Verify(element_stream.DoesResourceExist());
//
//-------------------------
// Read in the entity state
//-------------------------
//
gos_PushCurrentHeap(ElementRenderer::g_Heap);
Check_Object(entityElement);
#ifdef _DEBUG
{static void* s_p = (void*)0x08f40500;
if (s_p == (void*)this) {
int n = 0;
n++;
n--;
}}
#endif // _DEBUG
entityElement->SetClientData(this);
unsigned state;
element_stream >> state;
entityElement->SetElementState(state);
element_stream >> entityElement->m_localOBB;
Verify(!solidVolume);
Verify(!hierarchicalVolume);
//
//-------------------------------------------------------------------
// Read a state change from stream, but if it has no changes, kill it
//-------------------------------------------------------------------
//
ElementRenderer::StateChange *states =
new ElementRenderer::StateChange(
&element_stream,
ElementRenderer::CurrentERFVersion
);
Check_Object(states);
if (states->IsRealStateChange())
entityElement->AdoptStateChange(states);
else
{
Check_Object(states);
delete states;
}
gos_PopCurrentHeap();
//
//-------------------------------
// Set the position of the entity
//-------------------------------
//
initialLocalToParent = message->localToParent;
entityElement->SetLocalToParent(message->localToParent);
NeedMatrixSync();
//
//------------------------------
// Load up the execution engines
//------------------------------
//
Check_Object(executionState);
executionState->Reuse(&message->executionState);
//
//------------------------------------------------
//Load the instance Name if it exists in the Table
//------------------------------------------------
//
objectID = message->nameID;
dontHit = NULL;
if (oldCollisions)
{
delete oldCollisions;
oldCollisions = NULL;
}
Verify(!newCollisions);
alignment = message->alignment;
isDestroyed = 0;
// if (visualRepresentation == PrestineBothState || visualRepresentation == DestroyedBothState )
// visualRepresentation=PrestineBothState;
// else
visualRepresentation=PrestineInternalState;
ClearDestroyedFlag();
ClearTriedToMoveOffMapThisFrameFlag();
RendererComponentWeb *renderer_web = GetComponentWeb(RendererManager::VideoRendererType);
if(renderer_web)
{
VideoComponentWeb *video_web = Cast_Object(VideoComponentWeb *, renderer_web);
video_web->CleanDamage();
}
ExecuteChildComponentWebs();
}
//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
//
void
Entity::Respawn(CreateMessage *message)
{
Check_Object(this);
Check_Object(message);
BaseClass::Respawn(message);
//
//-----------------------------------------
// Verify that an entity can be created now
//-----------------------------------------
//
#ifdef _ARMOR
Application *app = Application::GetInstance();
Check_Object(app);
Verify(!app->InPreCollisionPhase());
#endif
#if defined(HUNT_BUG)
SPEW((HUNT_BUG, "Reusing %s(+", GetClassString()));
Spew(HUNT_BUG, GetReplicatorID());
if (owningConnection==Connection::Local)
SPEW((HUNT_BUG, "*+"));
switch (GetReplicatorMode())
{
case MasterMode:
SPEW((HUNT_BUG, ") as master"));
break;
case IndependentMode:
SPEW((HUNT_BUG, ") as independent"));
break;
case HermitMode:
SPEW((HUNT_BUG, ") as hermit"));
break;
case ReplicantMode:
SPEW((HUNT_BUG, ") as replicant"));
break;
case ClientMasterMode:
SPEW((HUNT_BUG, ") as ClientMasterMode"));
break;
case ServerMasterMode:
SPEW((HUNT_BUG, ") as ServerMasterMode"));
break;
}
#endif
//
//----------------------
// Set up the data list and
//----------------------
//
lastExecuted = gos_GetElapsedTime();
lastParameterization = lastExecuted - message->initialAge;
updateFlags = 0;
#if defined(TIME_BUG)
SPEW((TIME_BUG, "Reusing %s(+", GetClassString()));
Spew(TIME_BUG, GetReplicatorID());
SPEW((TIME_BUG, ") at time %f", lastExecuted.GetSeconds()));
#endif
lightIntensity = 0.0f;
//
//----------------------------------------------------------------------
// Set up the game model and set the flags that come from the game model
//----------------------------------------------------------------------
//
Verify(dataListResource.DoesResourceExist());
Verify(gameModelResource.DoesResourceExist());
replicatorFlags &= InterestLevelMask|GameModelMask;
replicatorFlags |= message->replicatorFlags & ~(InterestLevelMask|GameModelMask);
if (IsACollider() && IsTileBound())
replicatorFlags &= ~ColliderFlag;
// here we go...
// if we are the server than we own everything..
if (owningConnection != Connection::Hermit)
{
Verify(GetReplicatorMode() != HermitMode);
SetReplicatorMode(MasterMode);
if (Network::GetInstance()->AmIServer())
{
// if we don't own it and it is a master it will be the ServerMasterMode ( the receiver of a ClientMaster )
if ((owningConnection != Connection::Local) && (owningConnection != Connection::Hermit))
{
if (GetReplicatorMode() == MasterMode)
SetReplicatorMode(ServerMasterMode);
}
}
else
{
// we are a client so we don't own anything.
if ((owningConnection == Connection::Local) && (GetReplicatorMode() == MasterMode))
{
SetReplicatorMode(ClientMasterMode);
}
else if ((owningConnection != Connection::Local) && GetReplicatorMode() == MasterMode)
{
SetReplicatorMode(ReplicantMode);
}
}
}
if (damageBit != -1)
{
EntityManager::GetInstance()->SetNetworkDamageBit(false, damageBit);
}
//
//-------------------------------
// Set the position of the entity
//-------------------------------
//
initialLocalToParent = message->localToParent;
entityElement->SetLocalToParent(message->localToParent);
NeedMatrixSync();
//
//------------------------------
// Load up the execution engines
//------------------------------
//
if(executionState)
executionState->Reuse(&message->executionState);
//
//------------------------------------------------
//Load the instance Name if it exists in the Table
//------------------------------------------------
//
alignment = message->alignment;
isDestroyed = 0;
visualRepresentation=PrestineState;
ClearDestroyedFlag();
ClearTriedToMoveOffMapThisFrameFlag();
if (oldCollisions)
{
delete oldCollisions;
oldCollisions = NULL;
}
Verify(!newCollisions);
m_whoShotMeLast = ReplicatorID::Null;
m_weaponShotMeLast = -1;
RendererComponentWeb *renderer_web = GetComponentWeb(RendererManager::VideoRendererType);
if(renderer_web)
{
VideoComponentWeb *video_web = Cast_Object(VideoComponentWeb *, renderer_web);
video_web->CleanDamage();
}
ExecuteChildComponentWebs();
}
//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
//
void
Entity::SentenceToDeathRow()
{
Check_Object(this);
Check_Object(EntityManager::GetInstance());
if (!EntityManager::GetInstance()->deathRow.IsPlugMember(this))
EntityManager::GetInstance()->deathRow.Add(this);
}
//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
//
Entity *
Entity::CreateEntity(
MemoryStream *stream,
ReplicatorID *base_id,
bool use_armory
)
{
Check_Object(stream);
Entity::CreateMessage *message =
Cast_Pointer(Entity::CreateMessage*, stream->GetPointer());
Entity *entity;
#if 0
if(use_armory)
{
Check_Object(EntityManager::GetInstance());
if ((entity = EntityManager::GetInstance()->RequestFromArmory(message->dataListID)) != NULL)
{
Check_Object(entity);
entity->Reuse(message);
entity->PostReuse();
return entity;
}
}
#endif
RegisteredClass::ClassID class_id = message->classID;
Entity::ClassData *class_data =
Cast_Pointer(Entity::ClassData*, RegisteredClass::FindClassData(class_id));
Check_Object(class_data);
entity =
Cast_Object(
Entity*,
(*class_data->replicatorFactory)(message, base_id)
);
Check_Object(entity);
#if 0
Check_Object(EntityManager::GetInstance());
EntityManager::GetInstance()->EntityCreation(entity);
#endif
#if defined(LAB_ONLY)
class_data->creationCount++;
#endif
return entity;
}
//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
//
Entity::Entity(
ClassData *class_data,
const CreateMessage *message,
ReplicatorID *base_id,
ElementRenderer::Element *element
):
Replicator(class_data, message, base_id),
parentEntity(NULL),
childEntityChain(NULL),
m_deathEntity(NULL)
{
Check_Pointer(this);
Check_Object(message);
minTileRow=maxTileRow=0xff;
minTileColumn=maxTileColumn=0xff;
collisionAllowed=true;
executionState = NULL;
//
//-----------------------------------------
// Verify that an entity can be created now
//-----------------------------------------
//
#ifdef _ARMOR
Application *app = Application::GetInstance();
Check_Object(app);
Verify(!app->InPreCollisionPhase());
#endif
++Entity_Count;
#if defined(HUNT_BUG)
SPEW((HUNT_BUG, "Creating %s(+", GetClassString()));
Spew(HUNT_BUG, GetReplicatorID());
if (owningConnection==Connection::Local)
SPEW((HUNT_BUG, "*+"));
switch (GetReplicatorMode())
{
case MasterMode:
SPEW((HUNT_BUG, ") as master"));
break;
case IndependentMode:
SPEW((HUNT_BUG, ") as independent"));
break;
case HermitMode:
SPEW((HUNT_BUG, ") as hermit"));
break;
case ReplicantMode:
SPEW((HUNT_BUG, ") as replicant"));
break;
case ClientMasterMode:
SPEW((HUNT_BUG, ") as ClientMasterMode"));
break;
case ServerMasterMode:
SPEW((HUNT_BUG, ") as ServerMasterMode"));
break;
}
#endif
//
//----------------------
// Set up the data list and
//----------------------
//
lastExecuted = gos_GetElapsedTime();
lastParameterization = lastExecuted - message->initialAge;
updateFlags = 0;
#if defined(TIME_BUG)
SPEW((TIME_BUG, "Creating %s(+", GetClassString()));
Spew(TIME_BUG, GetReplicatorID());
SPEW((TIME_BUG, ") at time %f", lastExecuted.GetSeconds()));
#endif
isPlayerVehicle = false;
lightIntensity = 0.0f;
//
//----------------------------------------------------------------------
// Set up the game model and set the flags that come from the game model
//----------------------------------------------------------------------
//
dataListResource.FindID(message->dataListID);
Verify(dataListResource.DoesResourceExist());
ResourceID *data_list = Cast_Pointer(ResourceID*, dataListResource.GetPointer());
gameModelResource.FindID(*data_list);
Verify(gameModelResource.DoesResourceExist());
const GameModel *model = GetGameModel();
Check_Object(model);
replicatorFlags &= ~GameModelMask;
replicatorFlags |= model->defaultFlags;
if (IsACollider() && IsTileBound())
replicatorFlags &= ~ColliderFlag;
SetInterestMask(DormantInterestLevel);
//
//------------------------------------------------
//Load the instance Name if it exists in the Table
//------------------------------------------------
//
if(NameTable::GetInstance())
{
Check_Object(NameTable::GetInstance());
instanceName = NameTable::GetInstance()->FindName(message->nameID);
NameTable::GetInstance()->SetData(message->nameID, this);
// entityElement->SetName(instanceName);
#if defined(LAB_ONLY)
if (!instanceName)
g_LastEntity[0] = '\0';
else
{
strncpy(g_LastEntity, instanceName, sizeof(g_LastEntity)-1);
g_LastEntity[sizeof(g_LastEntity)-1] = '\0';
}
#endif
}
else
{
instanceName = NULL;
// entityElement->SetName(dataListResource.GetName());
#if defined(LAB_ONLY)
g_LastEntity[0] = '\0';
#endif
}
//
//--------------------------
// Create the locator object
//--------------------------
//
Check_Object(VideoRenderer::Instance);
Resource element_stream(model->elementResourceID);
Verify(element_stream.DoesResourceExist());
gos_PushCurrentHeap(ElementRenderer::GroupElement::s_Heap);
if (element)
{
Check_Object(element);
entityElement = element;
}
else
{
entityElement = new ElementRenderer::GroupElement;
Check_Object(entityElement);
}
Check_Object(entityElement);
#ifdef _DEBUG
{static void* s_p = (void*)0x08f40500;
if (s_p == (void*)this) {
int n = 0;
n++;
n--;
}}
#endif // _DEBUG
entityElement->SetClientData(this);
unsigned state;
element_stream >> state;
entityElement->SetElementState(state);
element_stream >> entityElement->m_localOBB;
solidVolume = NULL;
hierarchicalVolume = NULL;
//
//-------------------------------------------------------------------
// Read a state change from stream, but if it has no changes, kill it
//-------------------------------------------------------------------
//
ElementRenderer::StateChange *states =
new ElementRenderer::StateChange(
&element_stream,
ElementRenderer::CurrentERFVersion
);
Check_Object(states);
if (states->IsRealStateChange())
entityElement->AdoptStateChange(states);
else
{
Check_Object(states);
delete states;
}
gos_PopCurrentHeap();
//
//-------------------------------
// Set the position of the entity
//-------------------------------
//
initialLocalToParent = message->localToParent;
entityElement->SetLocalToParent(message->localToParent);
NeedMatrixSync();
//
//------------------------------
// Load up the execution engines
//------------------------------
//
ExecutionStateEngine::ClassData *execution_class =
class_data->executionStateClass;
Check_Pointer(execution_class);
executionState = execution_class->Make(this, &message->executionState);
Check_Object(executionState);
objectID = message->nameID;
dontHit = NULL;
damageBit = -1;
damageObject = NULL;
alignment = message->alignment;
isDestroyed = 0;
visualRepresentation=PrestineState;
m_doesNeedToUpdateWebs = false;
if(IsDestroyed())
{
isDestroyed = 1;
SetDestroyedRepresentation();
}
ClearTriedToMoveOffMapThisFrameFlag();
oldCollisions = NULL;
newCollisions = NULL;
m_whoShotMeLast = ReplicatorID::Null;
m_weaponShotMeLast = -1;
for (unsigned i=0; i<RendererManager::RendererTypeCount; ++i)
componentWebs[i] = NULL;
}
//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
//
Entity::~Entity()
{
DESTRUCTOR("Entity");
Check_Object(this);
if (oldCollisions)
{
DESTRUCTOR("Entity::OldCollisions");
delete oldCollisions;
oldCollisions = NULL;
}
Verify(!newCollisions);
//
//----------------
// Delete children
//----------------
//
--Entity_Count;
{
DESTRUCTOR("Entity::DeleteChildren");
DeleteChildEntities();
}
//
//-----------------------------
// Delete the collision volumes
//-----------------------------
//
{
DESTRUCTOR("Entity::Volumes");
if (solidVolume)
{
Check_Object(solidVolume);
delete solidVolume;
solidVolume = NULL;
}
if (hierarchicalVolume)
{
Check_Object(hierarchicalVolume);
delete hierarchicalVolume;
hierarchicalVolume = NULL;
}
}
{
DESTRUCTOR("Entity::Webs");
//
//------------------------------------
// Delete any remaining component webs
//------------------------------------
//
for (unsigned i=0; i<RendererManager::RendererTypeCount; ++i)
{
RendererComponentWeb *web = componentWebs[i];
if (web)
{
Check_Object(web);
if (web->ShouldWebBeKilled())
{
Check_Object(web);
delete web;
componentWebs[i] = NULL;
}
}
}
}
{
DESTRUCTOR("Entity::Element");
//
//-------------------
// Delete the element
//-------------------
//
Check_Object(entityElement);
delete entityElement;
}
if (executionState)
{
DESTRUCTOR("Entity::ExecutionState");
//
//----------------------------
// Remove the execution states
//----------------------------
//
Check_Object(executionState);
delete executionState;
}
}
//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
//
void
Entity::DestroyMessageHandler(const Message *message)
{
Check_Object(this);
Check_Object(message);
Verify(message->messageID == DestroyMessageID);
//
//-----------------
// Destroy children
//-----------------
//
STOP(("Not implemented"));
#if 0
DeleteChildEntities();
#endif
//
//---------------------------
// Entered into deathrow once
//---------------------------
//
Check_Object(EntityManager::GetInstance());
if (!EntityManager::GetInstance()->deathRow.IsPlugMember(this))
{
EntityManager::GetInstance()->deathRow.Add(this);
}
}
//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
//
void
Entity::UpdateMessageHandler(const UpdateMessage *message)
{
Check_Object(this);
Check_Object(message);
Verify(GetReplicatorMode() == ReplicantMode);
SetNewLocalToParent(message->localToParent);
SyncMatrices(true);
}
//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
//
bool
Entity::FriendlyFire(const TakeDamageMessage *message)
{
return false;
}
//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
//
void
Entity::TakeDamageMessageHandler(const TakeDamageMessage *message)
{
Check_Object(this);
Check_Object(message);
Verify(message->messageID == TakeDamageMessageID);
if(damageObject)
{
if (!FriendlyFire(message))
{
Check_Pointer(damageObject);
damageObject->TakeDamage((TakeDamageMessage *)message, this);
}
}
}
//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
//
void
Entity::BecomeInterestingMessageHandler(const BecomeInterestingMessage *message)
{
Check_Object(this);
Check_Object(message);
Verify(message->messageID == BecomeInterestingMessageID);
Verify(message->m_render);
//
//--------------------------------------------------------------------------
// Find the zone the entity lives in. If the zone is no longer interesting,
// ignore the message
//--------------------------------------------------------------------------
//
ElementRenderer::Element *element = GetElement();
Check_Object(element);
element = element->GetParentElement();
Check_Object(element);
if (element->GetClassID() == TileClassID)
{
element = element->GetParentElement();
Check_Object(element);
element = element->GetParentElement();
Check_Object(element);
}
Zone *zone = Cast_Object(Zone*, element);
//
//------------------
// Is this the hole?
//------------------
//
Entity::InterestLevel
zone_interest = zone->GetInterestLevel(),
entity_interest = GetInterestLevel();
switch ((zone_interest<<2) | entity_interest)
{
case (Entity::DormantInterestLevel<<2)|Entity::DormantInterestLevel:
STOP(("Dormant:Dormant is unhandled"));
break;
case (Entity::DormantInterestLevel<<2)|Entity::SimulationInterestLevel:
STOP(("Dormant:Simulation is unhandled"));
break;
case (Entity::DormantInterestLevel<<2)|Entity::RenderingInterestLevel:
STOP(("Dormant:Rendering is unhandled"));
break;
case (Entity::SimulationInterestLevel<<2)|Entity::DormantInterestLevel:
STOP(("Simulation:Dormant is unhandled"));
break;
case (Entity::RenderingInterestLevel<<2)|Entity::DormantInterestLevel:
Verify(zone->m_dormant.IsPlugMember(this));
Verify(!zone->m_simulated.IsPlugMember(this));
Verify(!zone->m_rendered.IsPlugMember(this));
zone->m_dormant.Remove(this);
zone->m_rendered.Add(this);
BecomeInteresting(true);
break;
case (Entity::SimulationInterestLevel<<2)|Entity::SimulationInterestLevel:
case (Entity::SimulationInterestLevel<<2)|Entity::RenderingInterestLevel:
Verify(!zone->m_dormant.IsPlugMember(this));
Verify(zone->m_simulated.IsPlugMember(this));
Verify(!zone->m_rendered.IsPlugMember(this));
break;
case (Entity::RenderingInterestLevel<<2)|Entity::SimulationInterestLevel:
Verify(!zone->m_dormant.IsPlugMember(this));
Verify(zone->m_simulated.IsPlugMember(this));
Verify(!zone->m_rendered.IsPlugMember(this));
zone->m_simulated.Remove(this);
zone->m_rendered.Add(this);
BecomeInteresting(true);
break;
case (Entity::RenderingInterestLevel<<2)|Entity::RenderingInterestLevel:
Verify(!zone->m_dormant.IsPlugMember(this));
if (zone->m_simulated.IsPlugMember(this))
{
Verify(!zone->m_rendered.IsPlugMember(this));
zone->m_simulated.Remove(this);
zone->m_rendered.Add(this);
}
else
{
Verify(!zone->m_simulated.IsPlugMember(this));
Verify(zone->m_rendered.IsPlugMember(this));
}
break;
default:
STOP(("Illegal interest level setting"));
break;
}
}
//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
//
void
Entity::RequestUpdate(int update_flags)
{
Check_Object(this);
Verify(update_flags != 0);
Verify(GetReplicatorMode() == MasterMode);
Verify(owningConnection == Connection::Local);
#if defined(HUNT_BUG)
SPEW((HUNT_BUG, "Requesting Update for %s(+", GetClassString()));
Spew(HUNT_BUG, GetReplicatorID());
SPEW((HUNT_BUG, ")"));
#endif
if (!updateFlags)
{
updateFlags = update_flags;
Check_Object(EntityManager::GetInstance());
EntityManager::GetInstance()->RequestUpdate(this);
}
else
updateFlags |= update_flags;
}
//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
//
Entity::UpdateMessage*
Entity::ConstructUpdate(Stuff::MemoryStream *stream)
{
Check_Object(this);
Check_Object(stream);
Verify(updateFlags);
Verify(GetReplicatorMode() == MasterMode);
Verify(owningConnection == Connection::Local);
#if defined(HUNT_BUG)
SPEW((HUNT_BUG, "Constructing Update for %s(+", GetClassString()));
Spew(HUNT_BUG, GetReplicatorID());
SPEW((HUNT_BUG, ")"));
#endif
//
//------------------------------------------------------------
// Make sure there is enough room for the update on the stream
//------------------------------------------------------------
//
stream->AllocateBytes(sizeof(UpdateMessage));
UpdateMessage *message =
new(stream->GetPointer()) UpdateMessage(
replicatorID,
GetLocalToWorld()
);
return message;
}
//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
//
void
Entity::SetInterestLevel(InterestLevel interest)
{
Check_Object(this);
//
//---------------------------------------------
// Tell the zone to update our interest setting
//---------------------------------------------
//
ElementRenderer::Element *element = GetElement();
Check_Object(element);
Zone *zone = Cast_Object(Zone*, element->GetParentElement());
zone->SetInterestLevel(this, interest);
}
//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
//
void
Entity::BindToZone()
{
Check_Object(this);
//
//------------------------------------------
// If we are already zone bound, just return
//------------------------------------------
//
if (!IsTileBound())
return;
//
//---------------------------------------------------------------------
// We are tile bound now, so find the tile through our element's parent
//---------------------------------------------------------------------
//
ElementRenderer::Element *element = GetElement();
Check_Object(element);
Tile *tile = Cast_Object(Tile*, element->GetParentElement());
ElementRenderer::Element *mid = tile->GetParentElement();
Check_Object(mid);
Zone *zone = Cast_Object(Zone*, mid->GetParentElement());
//
//----------------------------------------------------------------
// Unhook the collision, change the flag and hook it back up again
//----------------------------------------------------------------
//
zone->DetachChild(element);
replicatorFlags &= ~TileBoundFlag;
zone->AttachChild(element);
element->Sync();
}
//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
//
void
Entity::BindToTile()
{
Check_Object(this);
//
//------------------------------------------
// If we are already tile bound, just return
//------------------------------------------
//
if (IsTileBound())
return;
//
//---------------------------------------------------------------------
// We are tile bound now, so find the tile through our element's parent
//---------------------------------------------------------------------
//
ElementRenderer::Element *element = GetElement();
Check_Object(element);
Zone *zone = Cast_Object(Zone*, element->GetParentElement());
//
//----------------------------------------------------------------
// Unhook the collision, change the flag and hook it back up again
//----------------------------------------------------------------
//
zone->DetachChild(element);
replicatorFlags |= TileBoundFlag;
zone->AttachChild(element);
element->Sync();
}
//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
//
void
Entity::SetCollisionMask(CollisionMask mask)
{
Check_Object(this);
Verify(GetParentEntity() == Map::GetInstance());
//
//----------------------------------
// Find the zone we are connected to
//----------------------------------
//
ElementRenderer::Element *element = GetElement();
Check_Object(element);
element = element->GetParentElement();
Check_Object(element);
if (element->GetClassID() == TileClassID)
{
element = element->GetParentElement();
Check_Object(element);
element = element->GetParentElement();
Check_Object(element);
}
Zone *zone = Cast_Object(Zone*, element);
//
//-----------------------------------------------------------------------
// Unhook from the current zone and reattach to it after setting our mask
//-----------------------------------------------------------------------
//
zone->UnhookCollision(this);
replicatorFlags &= ~AlwaysCollidesMask;
replicatorFlags |= mask;
zone->HookUpCollision(this);
}
//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
//
void
Entity::SetDestroyedFlag(int damage_mode)
{
Check_Object(this);
replicatorFlags |= DestroyedFlag;
// MSL 5.05 Torso
if((damage_mode == InternalDamageObject::DestructionDamageMode) ||
(damage_mode == InternalDamageObject::DetachableDamageMode) ||
(damage_mode == InternalDamageObject::ArmLeftDamageMode) ||
(damage_mode == InternalDamageObject::ArmRightDamageMode))
{
if (solidVolume)
{
Check_Object(solidVolume);
if (!solidVolume->IsDestroyed())
solidVolume->Destroy();
}
if (hierarchicalVolume)
{
Check_Object(hierarchicalVolume);
if (!hierarchicalVolume->IsDestroyed())
hierarchicalVolume->Destroy();
}
}
}
//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
//
void
Entity::SetTriedToMoveOffMapThisFrameFlag()
{
Check_Object(this);
replicatorFlags |= TriedToMoveOffMapThisFrameFlag;
}
//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
//
void
Entity::SetDestroyedRepresentation()
{
Check_Object(this);
if(visualRepresentation == PrestineState)
visualRepresentation = DestroyedState;
else if(visualRepresentation == PrestineInternalState)
visualRepresentation = DestroyedInternalState;
else if(visualRepresentation == PrestineBothState)
visualRepresentation = DestroyedBothState;
else if(visualRepresentation == PrestineNoneState)
visualRepresentation = DestroyedNoneState;
m_doesNeedToUpdateWebs = true;
//THIS CAN'T BE CALLED HERE EVER!!!!!!!
//ExecuteChildComponentWebs();
}
//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
//
void
Entity::SetInternalRepresentation()
{
Check_Object(this);
if(visualRepresentation == PrestineState || visualRepresentation == PrestineBothState || visualRepresentation == PrestineNoneState)
visualRepresentation = PrestineInternalState;
else if(visualRepresentation == DestroyedState || visualRepresentation == DestroyedBothState || visualRepresentation == DestroyedNoneState)
visualRepresentation = DestroyedInternalState;
ChainIteratorOf<Entity *> iterator(&childEntityChain);
Entity *entity;
while((entity = iterator.ReadAndNext()) != NULL)
{
Check_Object(entity);
entity->SetInternalRepresentation();
}
}
//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
//
void
Entity::SetBothRepresentation()
{
Check_Object(this);
if(visualRepresentation == PrestineState || visualRepresentation == PrestineInternalState || visualRepresentation == PrestineNoneState)
visualRepresentation = PrestineBothState;
else if(visualRepresentation == DestroyedState || visualRepresentation == DestroyedInternalState || visualRepresentation == DestroyedNoneState)
visualRepresentation = DestroyedBothState;
ChainIteratorOf<Entity *> iterator(&childEntityChain);
Entity *entity;
while((entity = iterator.ReadAndNext()) != NULL)
{
Check_Object(entity);
entity->SetBothRepresentation();
}
}
//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
//
void
Entity::SetNoneRepresentation()
{
Check_Object(this);
if(visualRepresentation == PrestineState || visualRepresentation == PrestineInternalState || visualRepresentation == PrestineBothState)
visualRepresentation = PrestineNoneState;
else if(visualRepresentation == DestroyedState || visualRepresentation == DestroyedInternalState || visualRepresentation == DestroyedBothState)
visualRepresentation = DestroyedNoneState;
ChainIteratorOf<Entity *> iterator(&childEntityChain);
Entity *entity;
while((entity = iterator.ReadAndNext()) != NULL)
{
Check_Object(entity);
entity->SetNoneRepresentation();
}
}
//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
//
void
Entity::SetExternalRepresentation()
{
Check_Object(this);
if(visualRepresentation == PrestineInternalState || visualRepresentation == PrestineBothState || visualRepresentation == PrestineNoneState)
visualRepresentation = PrestineState;
else if(visualRepresentation == DestroyedInternalState || visualRepresentation == DestroyedBothState || visualRepresentation == DestroyedNoneState)
visualRepresentation = DestroyedState;
ChainIteratorOf<Entity *> iterator(&childEntityChain);
Entity *entity;
while((entity = iterator.ReadAndNext()) != NULL)
{
Check_Object(entity);
entity->SetExternalRepresentation();
}
}
//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
//
void
Entity::ClearDestroyedFlag()
{
Check_Object(this);
replicatorFlags &= ~DestroyedFlag;
if (solidVolume)
{
Check_Object(solidVolume);
solidVolume->Restore();
}
if (hierarchicalVolume)
{
Check_Object(hierarchicalVolume);
hierarchicalVolume->Restore();
}
}
//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
//
void
Entity::ClearTriedToMoveOffMapThisFrameFlag()
{
Check_Object(this);
replicatorFlags &= ~TriedToMoveOffMapThisFrameFlag;
}
//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
//
void
Entity::SetDamageObject(DamageObject *damage_object)
{
Check_Object(this);
Check_Object(damage_object);
ChainIteratorOf<Entity *> iterator(&childEntityChain);
Entity *entity;
//
//--------------------------------------------------------------------
//Need to set the damage object and the damage object for its children
//--------------------------------------------------------------------
//
while((entity = iterator.ReadAndNext()) != NULL)
{
Check_Object(entity);
if(entity->damageObject == NULL)
{
entity->SetDamageObject(damage_object);
}
}
damageObject = damage_object;
}
//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
//
void
Entity::DestroyChildren(int damage_mode)
{
Check_Object(this);
DestroyDamageObjects();
ChainIteratorOf<Entity *> iterator(&childEntityChain);
Entity *entity;
while((entity = iterator.ReadAndNext()) != NULL)
{
Check_Object(entity);
entity->DestroyChildren(damage_mode);
}
Entity::ReactToDestruction(damage_mode, 0);
}
//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
//
bool
Entity::IsDestroyable()
{
if (damageObject != NULL)
return true;
return false;
}
//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
//
void
Entity::ReactToDestruction(int damage_mode,int damage_type)
{
Check_Object(this);
isDestroyed = 1;
SetDestroyedRepresentation();
SetDestroyedFlag(damage_mode);
if (damageBit != -1)
{
//SPEW(("jerryeds", "ENTITY DESTROYED - TILE : %d : %d", minTileRow, minTileColumn));
EntityManager::GetInstance()->SetNetworkDamageBit(true, damageBit);
}
}
//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
//
void
Entity::ApplyVisualDamage(const TakeDamageMessage *message, int armor_zone)
{
Check_Object(this);
Check_Object(message);
if (message->quickDamage)
return;
//
//-------------------------------------------------------------------
//Apply a procedural Damage Effect to ourselves if we have not before
//-------------------------------------------------------------------
//
if(!IsDestroyed())
{
Check_Object(VideoRenderer::Instance);
LinearMatrix4D damage_matrix = LinearMatrix4D::Identity;
Point3D damage_location;
RendererComponentWeb *renderer_web = GetComponentWeb(RendererManager::VideoRendererType);
if(renderer_web)
{
VideoComponentWeb *video_web = Cast_Object(VideoComponentWeb *, renderer_web);
damage_location.MultiplyByInverse(message->hitOffset, GetLocalToWorld());
damage_matrix.BuildTranslation(damage_location);
Vector3D damage_rotation;
damage_rotation.Negate(message->normal);
damage_matrix.AlignLocalAxisToWorldVector(damage_rotation, Z_Axis, Y_Axis, X_Axis);
Scalar radius = message->amountOfDamage * 0.1f;
Clamp(radius, 0.5f, 1.0f);
if(armor_zone == DamageObject::DefaultArmorZone)
{
if(!HasPlacedDamageDecal())
{
MidLevelRenderer::MLRTexture *texture =
(*MidLevelRenderer::MLRTexturePool::Instance)((const char *)"scorch");
if(texture)
{
Check_Object(texture);
damage_matrix(3,0) -= damage_matrix(2,0);
damage_matrix(3,1) -= damage_matrix(2,1);
damage_matrix(3,2) -= damage_matrix(2,2);
radius *= 5.0f;
video_web->ApplyDamageDecal(damage_matrix, radius, texture);
SetDamageDecalFlag();
}
}
}
else
video_web->ApplyDamage(damage_matrix, radius);
}
else
{
Entity *entity_to_check = GetParentEntity();
// traverse parents looking for a web
while (entity_to_check!=NULL)
{
// stop at the map
if (entity_to_check == Map::GetInstance())
{
break;
}
else
{
// stop at a parent with a web
RendererComponentWeb *renderer_web = entity_to_check->GetComponentWeb(RendererManager::VideoRendererType);
if (renderer_web != NULL)
{
entity_to_check->ApplyVisualDamage(message,armor_zone);
break;
}
}
entity_to_check = entity_to_check->GetParentEntity();
}
}
}
}
//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
//
AttributeEntry*
Entity::GetAttributeEntry(AttributeID attribute_ID)
{
ClassData *class_data = Cast_Pointer(ClassData*, classData);
Check_Object(class_data);
return class_data->attributeTable.GetAttributeEntry(attribute_ID);
}
//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
//
AttributeEntry*
Entity::GetAttributeEntry(const char *attribute_name)
{
ClassData *class_data = Cast_Pointer(ClassData*, classData);
Check_Object(class_data);
return class_data->attributeTable.GetAttributeEntry(attribute_name);
}
//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
//
void
Entity::GetGameModelResourceFromDataListID(
Resource *resource,
const ResourceID &data_list
)
{
Resource stream(data_list);
Verify(stream.GetSize() >= sizeof(ResourceID));
ResourceID resource_id;
stream >> resource_id;
resource->FindID(resource_id);
}
//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
//
RegisteredClass::ClassID
Entity::GetClassIDFromDataListID(const ResourceID &model_list)
{
Resource resource;
GetGameModelResourceFromDataListID(&resource, model_list);
GameModel *model = Cast_Pointer(GameModel*,resource.GetPointer());
return model->classID;
}
//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
//
void
Entity::AddChild(Entity *entity)
{
Check_Object(this);
Check_Object(entity);
//
//-----------------------------
// Hook up the entity hierarchy
//-----------------------------
//
Verify(!entity->parentEntity);
entity->parentEntity = this;
childEntityChain.Add(entity);
entity->NeedMatrixSync();
ElementRenderer::Element *child_element = entity->GetElement();
Check_Object(child_element);
Check_Object(entityElement);
entityElement->AttachChild(child_element);
//
//---------------------------------------------------
// If are bounds are not locked, calculate them again
//---------------------------------------------------
//
if (
!entityElement->AreBoundsLocked()
&& entityElement->GetCullMode() == ElementRenderer::Element::VolumeCullMode
)
{
entityElement->NeedNewBounds();
NeedMatrixSync();
}
#if defined(HUNT_BUG)
SPEW((0, "Attaching %s(+", entity->GetClassString()));
Spew(0, entity->GetReplicatorID());
SPEW((0, ") to %s(+", GetClassString()));
Spew(0, GetReplicatorID());
SPEW((0, ")"));
#endif
}
//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
//
void
Entity::RemoveChild(Entity *entity)
{
Check_Object(this);
Check_Object(entity);
//
//-----------------------------
// Unhook the locator hierarchy
//-----------------------------
//
entity->parentEntity = NULL;
childEntityChain.Remove(entity);
entity->NeedMatrixSync();
ElementRenderer::Element *element = entity->GetElement();
Check_Object(element);
entityElement->DetachChild(element);
#if defined(HUNT_BUG)
SPEW((0, "Attaching %s(+", entity->GetClassString()));
Spew(0, entity->GetReplicatorID());
SPEW((0, ") to %s(+", GetClassString()));
Spew(0, GetReplicatorID());
SPEW((0, ")"));
#endif
}
//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
//
void
Entity::SetNewLocalToParent(const Stuff::LinearMatrix4D &new_local_to_world)
{
Check_Object(this);
Check_Object(entityElement);
Check_Object(parentEntity);
ClearTriedToMoveOffMapThisFrameFlag();
//
//-----------------------------------------------------------
// If our parent isn't the map, set the dirty flag and matrix
//-----------------------------------------------------------
//
if (parentEntity != Map::GetInstance())
{
entityElement->SetLocalToParent(new_local_to_world);
replicatorFlags |= DirtyMatrixFlag;
}
//
//----------------------------------------------------------------------
// If we are parented to the map, the zone is dirty, and then bodge in a
// check to make sure nothing leaves the map
//----------------------------------------------------------------------
//
else
{
Point3D translation(new_local_to_world);
Check_Object(Map::GetInstance());
if (Map::GetInstance()->FindZone(translation) == -1)
{
LinearMatrix4D adjusted_matrix = new_local_to_world;
const LinearMatrix4D &old_matrix = GetLocalToWorld();
adjusted_matrix(3,0) = old_matrix(3,0);
adjusted_matrix(3,2) = old_matrix(3,2);
entityElement->SetLocalToParent(adjusted_matrix);
replicatorFlags |= DirtyMatrixFlag | TriedToMoveOffMapThisFrameFlag;
}
else
{
entityElement->SetLocalToParent(new_local_to_world);
replicatorFlags |= DirtyMatrixFlag|DirtyZoneFlag|PostCollisionFlag;
}
}
}
//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
//
void
Entity::ChildPreCollisionChanged(Entity *entity)
{
Check_Object(this);
Check_Object(entity);
STOP(("This function should be overridden!"));
}
//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
//
void
Entity::DeleteChildEntities()
{
Check_Object(this);
childEntityChain.DeletePlugs();
}
//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
//
void
Entity::SetComponentWeb(
unsigned renderer_id,
RendererComponentWeb *web
)
{
Check_Object(this);
if(componentWebs[renderer_id])
{
delete componentWebs[renderer_id];
}
componentWebs[renderer_id] = web;
}
//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
//
void
Entity::ExecuteComponentWebs()
{
Check_Object(this);
POSTCOLLISION_LOGIC("Entity::Execute Webs");
//
//----------------------------
// Execute each registered web
//----------------------------
//
for (unsigned i=1; i<RendererManager::RendererTypeCount; ++i)
{
ComponentWeb *web = componentWebs[i];
if (web)
{
Check_Object(web);
web->ExecuteWatcherComponents();
}
}
}
//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
//
void
Entity::BecomeInteresting(bool render_me)
{
Check_Object(this);
//
//--------------------------------------
// Tell the renderers we are interesting
//--------------------------------------
//
LOAD_LOGIC("Become Interesting::Entity");
Start_Timer(Renderer_Loading);
Check_Object(RendererManager::Instance);
RendererManager::Instance->EntityIsInteresting(this, render_me);
//
//------------------------------------------------------------------------
// The entity version will just load the solid volumes. Go ahead and load
// the stream resource that should be indicated in the game model
//------------------------------------------------------------------------
//
if (!solidVolume && !hierarchicalVolume)
{
LOAD_LOGIC("Become Interesting::Entity::Load Collision Volumes");
const GameModel *game_model = GetGameModel();
Check_Object(game_model);
#if defined(LAB_ONLY)
if (!instanceName)
g_LastEntity[0] = '\0';
else
{
strncpy(g_LastEntity, instanceName, sizeof(g_LastEntity)-1);
g_LastEntity[sizeof(g_LastEntity)-1] = '\0';
}
#endif
//
//-------------------------------
// Load in the solid if it exists
//-------------------------------
//
if (game_model->obbStreamResourceID != ResourceID::Null)
{
Resource obb_stream(game_model->obbStreamResourceID);
Verify(obb_stream.DoesResourceExist());
gos_PushCurrentHeap(s_CollisionHeap);
solidVolume =
new CollisionVolume(
this,
&obb_stream,
CollisionVolume::ReadOBBVersion(&obb_stream)
);
Check_Object(solidVolume);
gos_PopCurrentHeap();
}
}
//
//------------------------------------------------------
// Mark our interest level according to the render level
//------------------------------------------------------
//
#if defined ARMOR
if (render_me)
Verify(!Application::GetInstance()->m_localMissionParameters.m_runDedicated);
#endif
{
LOAD_LOGIC("Become Interesting::Entity::Set Interest Mask");
SetInterestMask((render_me) ? RenderingInterestLevel : SimulationInterestLevel);
#if defined(_ARMOR)
ElementRenderer::Element *element = GetElement();
Check_Object(element);
element = element->GetParentElement();
if (element)
{
if (element->GetClassID() == TileClassID)
{
element = element->GetParentElement();
Check_Object(element);
element = element->GetParentElement();
Check_Object(element);
}
if (element->GetClassID() == ZoneClassID)
{
Zone *zone = Cast_Object(Zone*, element);
Verify(!zone->m_dormant.IsPlugMember(this));
if (render_me && zone->GetInterestLevel() == RenderingInterestLevel)
{
Verify(!zone->m_simulated.IsPlugMember(this));
Verify(zone->m_rendered.IsPlugMember(this));
}
else
{
Verify(zone->m_simulated.IsPlugMember(this));
Verify(!zone->m_rendered.IsPlugMember(this));
}
}
}
#endif
}
Stop_Timer(Renderer_Loading);
}
//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
//
void
Entity::BecomeUninteresting()
{
Check_Object(this);
//
//----------------------------
// Execute each registered web
//----------------------------
//
for (unsigned i=1; i<RendererManager::RendererTypeCount; ++i)
{
RendererComponentWeb *web = componentWebs[i];
if (web)
{
Check_Object(web);
if (web->ShouldWebBeKilled())
{
Check_Object(web);
delete web;
componentWebs[i] = NULL;
}
}
}
//
//------------------------
// Delete the solid volume
//------------------------
//
if (solidVolume)
{
Check_Object(solidVolume);
delete solidVolume;
solidVolume = NULL;
}
if (hierarchicalVolume)
{
Check_Object(hierarchicalVolume);
delete hierarchicalVolume;
hierarchicalVolume = NULL;
}
}
//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
//
const ResourceID&
Entity::GetRendererDataResourceID(int renderer_type)
{
Check_Object(this);
ResourceID *data_list = Cast_Pointer(ResourceID*, dataListResource.GetPointer());
Check_Pointer(data_list);
Check_Object(RendererManager::Instance);
Verify(
0 <= renderer_type &&
renderer_type < RendererManager::Instance->GetModelListSize()
);
return data_list[renderer_type];
}
//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
//
int
Entity::GetExecutionSlot()
{
Check_Object(this);
return DefaultExecutionSlot;
}
//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
//
void
Entity::PreCollisionExecute(Time till)
{
Check_Object(this);
Verify(!EntityManager::GetInstance()->isExecutionSuspended);
Verify(GetInterestLevel() != DormantInterestLevel);
collisionAllowed=true;
//
//------------------------------------------------------------------------
// Check to see if a post collision pass in necessary. If so, attach this
// entity to the entitymanager post collision chain
//------------------------------------------------------------------------
//
if (IsUsingPostCollision())
{
Check_Object(EntityManager::GetInstance());
EntityManager::GetInstance()->RequestPostCollisionExecution(this);
}
else
{
lastExecuted = till;
#if defined(TIME_BUG)
SPEW((TIME_BUG, "PreCollisionOnly execution of %s(+", GetClassString()));
Spew(TIME_BUG, GetReplicatorID());
SPEW((TIME_BUG, ") at time %f", lastExecuted.GetSeconds()));
#endif
}
}
//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
//
bool
Entity::CollisionHandler(
Stuff::LinearMatrix4D *new_position,
Stuff::DynamicArrayOf<CollisionData> *collisions
)
{
Check_Object(this);
Check_Object(collisions);
Verify(GetInterestLevel() != DormantInterestLevel);
Verify(EntityManager::GetInstance()->IsInPostCollisionExecution(this));
newCollisions = collisions;
SPEW((0, "%s should override CollisionHandler", (char*)GetClassString() ));
return false;
}
//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
//
void
Entity::SyncMatrices(bool update_matrix)
{
Check_Object(this);
SYNC_LOGIC("Entity");
#if defined(HUNT_BUG)
bool old_update=update_matrix;
if (update_matrix)
{
SPEW((0, "Entity::SyncMatrices %s(+", GetClassString()));
Spew(0, GetReplicatorID());
SPEW((0, ")"));
}
#endif
Set_Statistic(s_EntitiesSynced, s_EntitiesSynced+1);
//
//-----------------------------------------
// If we have a dirty locator, sync with it
//-----------------------------------------
//
if (IsMatrixDirty())
{
if (update_matrix)
{
Check_Object(entityElement);
entityElement->Sync();
update_matrix = false;
}
ClearNeedMatrixSync();
}
//
//-----------------------------
// Sync our children's locators
//-----------------------------
//
if (!childEntityChain.IsEmpty())
{
ChainIteratorOf<Entity *> children(&childEntityChain);
Entity *child;
while ((child = children.ReadAndNext()) != NULL)
{
Check_Object(child);
child->SyncMatrices(update_matrix);
}
}
#if defined(HUNT_BUG)
if (old_update)
SPEW((0, ""));
#endif
}
//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
//
void
Entity::SyncMatricesFirstLevelOnly(bool update_matrix)
{
Check_Object(this);
// DANGER DANGER DANGER!!!!!!!!!!!!!!!!!!!!!!!!
// THIS IS A NETWORK HACK
// USE IT AT OWN RISK
#if defined(HUNT_BUG)
bool old_update=update_matrix;
if (update_matrix)
{
SPEW((0, "Entity::SyncMatrices %s(+", GetClassString()));
Spew(0, GetReplicatorID());
SPEW((0, ")"));
}
#endif
//
//-----------------------------------------
// If we have a dirty locator, sync with it
//-----------------------------------------
//
if (IsMatrixDirty())
{
if (update_matrix)
{
Check_Object(entityElement);
entityElement->Sync();
update_matrix = false;
}
ClearNeedMatrixSync();
}
#if defined(HUNT_BUG)
if (old_update)
SPEW((0, ""));
#endif
}
//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
//
void
Entity::PostCollisionExecute(Time till)
{
Check_Object(this);
Verify(GetInterestLevel() != DormantInterestLevel);
POSTCOLLISION_LOGIC("Entity");
//
//----------------------------------------------------------------------
// Remove the old collision list if it exists, then swap to the new list
// for next time
//----------------------------------------------------------------------
//
if (oldCollisions)
delete oldCollisions;
oldCollisions = newCollisions;
newCollisions = NULL;
//
//---------------------------------------------------------------------
// If the zone is dirty, let the map figure out where the entity should
// live
//---------------------------------------------------------------------
//
if (IsZoneDirty())
{
POSTCOLLISION_LOGIC("Entity::UpdateZone");
Verify(parentEntity == Map::GetInstance());
Check_Object(Map::GetInstance());
Map::GetInstance()->UpdateZone(this);
Verify(!IsZoneDirty());
}
//
//-------------------------------------------------------------------
// Execute the component webs and update the simulation frame counter
//-------------------------------------------------------------------
//
ExecuteComponentWebs();
lastExecuted = till;
#if defined(TIME_BUG)
SPEW((TIME_BUG, "PostCollision execution of %s(+", GetClassString()));
Spew(TIME_BUG, GetReplicatorID());
SPEW((TIME_BUG, ") at time %f", lastExecuted.GetSeconds()));
#endif
if(m_doesNeedToUpdateWebs)
{
m_doesNeedToUpdateWebs = false;
ExecuteChildComponentWebs();
}
}
//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
//
void
Entity::PlaceOnEntity(
LinearMatrix4D *position,
Motion3D *velocity,
const LinearMatrix4D& initial_offset,
const Motion3D& initial_velocity
)
{
Check_Object(this);
Check_Object(position);
Check_Object(velocity);
STOP(("Not implemented"));
}
//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
//
void
Entity::FollowAndBillBoard(
Stuff::LinearMatrix4D *position,
Stuff::UnitVector3D *direction
)
{
Check_Object(this);
Check_Object(position);
Check_Object(direction);
LinearMatrix4D new_local_to_parent = *position;
Point3D new_translation;
new_translation = *position;
new_local_to_parent.BuildTranslation(new_translation);
new_local_to_parent.AlignLocalAxisToWorldVector(*direction, Y_Axis, Z_Axis, X_Axis);
SetNewLocalToParent(new_local_to_parent);
}
//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
//
void
Entity::EnterNeverExecuteState()
{
Check_Object(this);
Verify(!newCollisions);
if(parentEntity)
{
Check_Object(parentEntity);
parentEntity->ChildPreCollisionChanged(this);
}
}
//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
//
void
Entity::LeaveNeverExecuteState()
{
Check_Object(this);
lastExecuted = gos_GetElapsedTime();
collisionAllowed = false;
if(parentEntity)
{
Check_Object(parentEntity);
parentEntity->ChildPreCollisionChanged(this);
}
}
//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
//
Entity*
Entity::ProjectLine(
Line3D *line,
CollisionMask mask,
Point3D *target_offset,
Normal3D *normal
)
{
Check_Object(this);
Check_Object(line);
Check_Pointer(target_offset);
Check_Pointer(normal);
Check_Object(Map::GetInstance());
CollisionQuery query(line, normal, mask, this);
return CollisionGrid::Instance->ProjectLine(&query);
}
//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
//
bool
Entity::IsWithin(
Entity *target,
Scalar distance,
bool ignorey
)
{
Check_Object(this);
Check_Object(target);
Vector3D target_line = Vector3D::Identity;
Point3D our_position;
Point3D target_position;
our_position = GetLocalToWorld();
target_position = target->GetLocalToWorld();
if ((our_position.y < -1500) || (target_position.y < -1500)) // units in hell are never near each other
return false;
if (ignorey)
{
our_position.y = 0;
target_position.y = 0;
}
target_line.Subtract(target_position, our_position);
return target_line.GetLengthSquared() <= (distance * distance);
}
//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
//
Scalar
Entity::GetDistanceFrom(Entity *target)
{
Check_Object(this);
Check_Object(target);
Vector3D target_line = Vector3D::Identity;
Point3D our_position;
Point3D target_position;
our_position = GetLocalToWorld();
target_position = target->GetLocalToWorld();
target_line.Subtract(target_position, our_position);
return target_line.GetLength();
}
//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
//
Scalar
Entity::GetDistanceSquaredFrom(Entity *target, bool ignore_y)
{
Check_Object(this);
Check_Object(target);
Vector3D target_line = Vector3D::Identity;
Point3D our_position;
Point3D target_position;
our_position = GetLocalToWorld();
target_position = target->GetLocalToWorld();
target_line.Subtract(target_position, our_position);
if(ignore_y)
target_line.y = 0.0f;
return target_line.GetLengthSquared();
}
//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
//
void
Entity::ExecuteChildComponentWebs()
{
Check_Object(this);
ChainIteratorOf<Entity *> iterator(&childEntityChain);
Entity *entity;
while((entity = iterator.ReadAndNext()) != NULL)
{
Check_Object(entity);
entity->ExecuteChildComponentWebs();
}
ExecuteComponentWebs();
}
//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
//
void
Entity::RemoveCollision()
{
Check_Object(this);
SetCollisionMask(NeverCollidesMask);
}
//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
//
bool
Entity::IsNeverExecuteState()
{
Check_Object(this);
Check_Object(executionState);
if (executionState->GetState() == Entity::ExecutionStateEngine::NeverExecuteState)
{
return true;
}
return false;
}
//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
//
void
Entity::TestInstance()
{
Verify(IsDerivedFrom(DefaultData));
ResourceID *data_list = Cast_Pointer(ResourceID*, dataListResource.GetPointer());
if (data_list != NULL)
{
Check_Object(RendererManager::Instance);
size_t len = RendererManager::Instance->GetModelListSize();
for (size_t i = 0; i < len; i++)
{
if (data_list[i] != ResourceID::Null)
{
Resource resource(data_list[i]);
Verify(resource.DoesResourceExist());
}
}
}
}