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.
1036 lines
26 KiB
C++
1036 lines
26 KiB
C++
#include "AdeptHeaders.hpp"
|
|
|
|
#include "EntityManager.hpp"
|
|
#include "RendererManager.hpp"
|
|
#include "Application.hpp"
|
|
#include "Tool.hpp"
|
|
#include <ElementRenderer\GroupElement.hpp>
|
|
#include <ElementRenderer\StateChange.hpp>
|
|
|
|
//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
|
|
//
|
|
void
|
|
Entity__CreateMessage::ConstructCreateMessage(Script *script)
|
|
{
|
|
Check_Object(script);
|
|
|
|
//
|
|
//--------------
|
|
// Set up stream
|
|
//--------------
|
|
//
|
|
MemoryStream *message_stream = script->messageStream;
|
|
Check_Object(message_stream);
|
|
message_stream->AllocateBytes(sizeof(Entity__CreateMessage));
|
|
Replicator__CreateMessage::ConstructCreateMessage(script);
|
|
Entity__CreateMessage *message =
|
|
Cast_Pointer(
|
|
Entity__CreateMessage*,
|
|
message_stream->GetPointer()
|
|
);
|
|
message->messageLength = sizeof(*message);
|
|
|
|
//
|
|
//---------------------------------------------------------------
|
|
// Point at the notation file and make other files relative to it
|
|
//---------------------------------------------------------------
|
|
//
|
|
Page *page = script->instancePage;
|
|
Check_Object(page);
|
|
Check_Object(Tool::Instance);
|
|
Tool::Instance->PushFilePath(page->GetNotationFile());
|
|
|
|
//
|
|
//---------------
|
|
// Read the flags
|
|
//---------------
|
|
//
|
|
bool flag = false;
|
|
page->GetEntry("TileBound", &flag);
|
|
if (flag)
|
|
message->replicatorFlags |= Entity::TileBoundFlag;
|
|
|
|
//
|
|
//-------------
|
|
//Get Alignment
|
|
//-------------
|
|
//
|
|
const char *alignment_text;
|
|
int alignment_value = Entity::DefaultAlignment;
|
|
if(page->GetEntry("Alignment", &alignment_text))
|
|
alignment_value = Entity::AlignmentTextToAscii(alignment_text);
|
|
|
|
message->alignment = alignment_value;
|
|
|
|
//
|
|
//----------------------------------------------------
|
|
// Find out the GameModel we need to build and open it
|
|
//----------------------------------------------------
|
|
//
|
|
Entity::ClassData *class_data;
|
|
{
|
|
const char* model_name;
|
|
page->GetEntry("Model", &model_name, true);
|
|
Resource resource;
|
|
class_data = Tool::Instance->ConstructDataList(&resource, model_name);
|
|
Check_Object(&resource);
|
|
Verify(resource.DoesResourceExist());
|
|
message->dataListID = resource.GetResourceID();
|
|
}
|
|
|
|
//
|
|
//-------------------------------------------------------------------------
|
|
// If this entity is a collider, make sure that it has a solid volume entry
|
|
// in the game model
|
|
//-------------------------------------------------------------------------
|
|
//
|
|
if ((message->replicatorFlags&Entity::AlwaysCollidesMask) != Entity::NeverCollidesMask)
|
|
{
|
|
Resource model_res;
|
|
Entity::GetGameModelResourceFromDataListID(
|
|
&model_res,
|
|
message->dataListID
|
|
);
|
|
Verify(model_res.DoesResourceExist());
|
|
Entity::GameModel *game_model =
|
|
Cast_Pointer(Entity::GameModel*, model_res.GetPointer());
|
|
Check_Object(game_model);
|
|
if (game_model->obbStreamResourceID == ResourceID::Null)
|
|
message->replicatorFlags &= ~Entity::AlwaysCollidesMask;
|
|
}
|
|
|
|
//
|
|
//-------------------------------
|
|
// Deal with the initial position
|
|
//-------------------------------
|
|
//
|
|
Point3D translation = Point3D::Identity;
|
|
page->GetEntry("Translation", &translation);
|
|
YawPitchRoll rotation = YawPitchRoll::Identity;
|
|
page->GetEntry("Rotation", &rotation);
|
|
message->localToParent.BuildTranslation(translation);
|
|
message->localToParent.BuildRotation(rotation);
|
|
|
|
//
|
|
//-------------------------
|
|
// Save the execution state
|
|
//-------------------------
|
|
//
|
|
Entity::ExecutionStateEngine::FactoryRequest::Script state_script;
|
|
Check_Object(class_data);
|
|
Verify(class_data->IsDerivedFrom(Entity::DefaultData));
|
|
state_script.engineClass = class_data->executionStateClass;
|
|
Check_Object(state_script.engineClass);
|
|
state_script.instancePage = page;
|
|
state_script.stateEngineName = "ExecutionState";
|
|
message->executionState.ConstructFactoryRequest(&state_script);
|
|
Tool::Instance->PopFilePath();
|
|
|
|
//
|
|
//----------------------------------
|
|
// Set the initial age of the entity
|
|
//----------------------------------
|
|
//
|
|
message->initialAge = 0.0f;
|
|
page->GetEntry("Age", &message->initialAge);
|
|
|
|
//
|
|
//-------------------------
|
|
//Save the instance name id
|
|
//-------------------------
|
|
//
|
|
|
|
message->nameID = NameTable::NullObjectID;
|
|
}
|
|
|
|
//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
|
|
//
|
|
void
|
|
Entity::SaveInstanceText(Page *page)
|
|
{
|
|
Check_Object(this);
|
|
Check_Object(page);
|
|
|
|
//
|
|
//--------------------
|
|
// Save the Model Name
|
|
//--------------------
|
|
//
|
|
Check_Object(&gameModelResource);
|
|
page->SetEntry("Model", (const char *)GetModelName());
|
|
//
|
|
//-------------------------
|
|
// Save the Execution State
|
|
//-------------------------
|
|
//
|
|
if(executionState)
|
|
{
|
|
int execution_state = executionState->GetState();
|
|
MString execution_state_text;
|
|
switch(execution_state)
|
|
{
|
|
case ExecutionStateEngine::NeverExecuteState:
|
|
{
|
|
execution_state_text = "NeverExecuteState";
|
|
break;
|
|
}
|
|
case ExecutionStateEngine::ExecuteOnceState:
|
|
{
|
|
execution_state_text = "ExecuteOnceState";
|
|
break;
|
|
}
|
|
case ExecutionStateEngine::AlwaysExecuteState:
|
|
{
|
|
execution_state_text = "AlwaysExecuteState";
|
|
break;
|
|
}
|
|
default:
|
|
{
|
|
#if defined(_ARMOR)
|
|
if(*instanceName)
|
|
{
|
|
PAUSE(("Execution State for %s has not been defined", (const char *)instanceName));
|
|
}
|
|
#endif
|
|
|
|
execution_state_text = "NeverExecuteState";
|
|
break;
|
|
}
|
|
}
|
|
page->SetEntry("ExecutionState", execution_state_text);
|
|
}
|
|
else
|
|
{
|
|
page->SetEntry("ExecutionState", "NeverExecuteState");
|
|
|
|
}
|
|
//
|
|
//--------------------------
|
|
// Save all the Entity Flags
|
|
//--------------------------
|
|
//
|
|
page->SetEntry("TileBound", IsTileBound());
|
|
|
|
//
|
|
//---------------------------------------------------
|
|
// Save the Translation and Rotation in String format
|
|
//---------------------------------------------------
|
|
//
|
|
Point3D local_translation(GetLocalToParent());
|
|
page->SetEntry("Translation", local_translation);
|
|
YawPitchRoll rotation_value(GetLocalToParent());
|
|
page->SetEntry("Rotation", rotation_value);
|
|
|
|
const char *alignment_text;
|
|
alignment_text = Entity::AlignmentAsciiToText(alignment);
|
|
page->SetEntry("Alignment", alignment_text);
|
|
}
|
|
|
|
//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
|
|
//
|
|
void
|
|
Entity__GameModel::ConstructGameModel(Script *script)
|
|
{
|
|
Check_Object(script);
|
|
|
|
//
|
|
//--------------
|
|
// Set up stream
|
|
//--------------
|
|
//
|
|
MemoryStream *model_stream = script->modelStream;
|
|
Check_Object(model_stream);
|
|
model_stream->AllocateBytes(sizeof(Entity__GameModel));
|
|
Entity__GameModel *model =
|
|
Cast_Pointer(Entity__GameModel*, model_stream->GetPointer());
|
|
|
|
//
|
|
//--------------------
|
|
// Set up the class ID
|
|
//--------------------
|
|
//
|
|
Entity::ClassData *class_data = script->modelClassData;
|
|
Check_Object(class_data);
|
|
model->classID = class_data->GetClassID();
|
|
NotationFile *model_file = script->modelFile;
|
|
Check_Object(model_file);
|
|
Page *page = model_file->GetPage("GameData");
|
|
Check_Object(page);
|
|
|
|
//
|
|
//-------------------------------------------
|
|
// Read the element in from the notation file
|
|
//-------------------------------------------
|
|
//
|
|
gos_PushCurrentHeap(ElementRenderer::GroupElement::s_Heap);
|
|
ElementRenderer::Element *element = new ElementRenderer::GroupElement();
|
|
Check_Object(element);
|
|
unsigned
|
|
state=element->GetElementState(),
|
|
delta;
|
|
OBB
|
|
bounds;
|
|
ElementRenderer::Element::ReadStateFromPage(
|
|
page,
|
|
*MString::s_Empty,
|
|
&state,
|
|
&delta,
|
|
&bounds
|
|
);
|
|
ElementRenderer::StateChange *states =
|
|
new ElementRenderer::StateChange(page, *MString::s_Empty);
|
|
Check_Object(states);
|
|
|
|
//
|
|
//-------------------------------
|
|
// Write the data out to a stream
|
|
//-------------------------------
|
|
//
|
|
DynamicMemoryStream element_stream;
|
|
state &= ~ElementRenderer::Element::CullMask;
|
|
state |=
|
|
ElementRenderer::Element::RootMode
|
|
| ElementRenderer::Element::MatrixDirtyFlag;
|
|
element_stream << state << bounds;
|
|
states->Save(&element_stream);
|
|
Check_Object(states);
|
|
delete states;
|
|
gos_PopCurrentHeap();
|
|
|
|
//
|
|
//-----------------------------------------
|
|
// Save the element stream in the resources
|
|
//-----------------------------------------
|
|
//
|
|
MString element_name = model_file->GetFileName();
|
|
element_name += "{Element}";
|
|
Resource element_resource(element_name);
|
|
element_resource.Save(&element_stream, Resource::ParentFileDependencies);
|
|
Verify(element_resource.DoesResourceExist());
|
|
model->elementResourceID = element_resource.GetResourceID();
|
|
|
|
//
|
|
//-----------------------------------------
|
|
// Clear out the collision OBB resource IDs
|
|
//-----------------------------------------
|
|
//
|
|
model->obbStreamResourceID = ResourceID::Null;
|
|
if (class_data->obbFactory != NULL)
|
|
(*class_data->obbFactory)(script);
|
|
Check_Object(element);
|
|
delete element;
|
|
|
|
//
|
|
//-------------------------------------------
|
|
// Spin Through all the game model attributes
|
|
//-------------------------------------------
|
|
//
|
|
ModelAttributeEntry *attribute_entry;
|
|
TableIteratorOf<ModelAttributeEntry *, Entity__GameModel::AttributeID> iterator(
|
|
&class_data->gameModelAttributeTable.attributesByID);
|
|
int num_attributes = iterator.GetSize();
|
|
int i;
|
|
for(i=Entity__GameModel::AnyAttributeID + 1;i<num_attributes;i++)
|
|
{
|
|
attribute_entry =
|
|
class_data->gameModelAttributeTable.GetAttributeEntry(i);
|
|
Check_Object(attribute_entry);
|
|
const char *data = "";
|
|
page->GetEntry(attribute_entry->attributeName, &data);
|
|
char *error_message;
|
|
error_message = new char[128];
|
|
strcpy(error_message, "");
|
|
Check_Pointer(error_message);
|
|
if(!(*class_data->modelVerifier)(model, attribute_entry, data, &error_message, 128))
|
|
{
|
|
STOP(("%s Game Model Error : %s", model_file->GetFileName(), error_message));
|
|
}
|
|
Check_Pointer(error_message);
|
|
delete [] error_message;
|
|
}
|
|
|
|
//
|
|
//------------------------
|
|
// Set the collision flags
|
|
//------------------------
|
|
//
|
|
model->defaultFlags = 0;
|
|
if(model->collider)
|
|
model->defaultFlags |= Entity::ColliderFlag;
|
|
if(model->canBeWalkedOn)
|
|
model->defaultFlags |= Entity::CanBeWalkedOnFlag|Entity::CanBeShotFlag;
|
|
if(model->canBeShot)
|
|
model->defaultFlags |= Entity::CanBeShotFlag;
|
|
if(model->waterSurface)
|
|
model->defaultFlags |= Entity::WaterSurfaceFlag;
|
|
if(model->OBBCollides)
|
|
model->defaultFlags |= Entity::OBBCollidesFlag;
|
|
if (model->defaultFlags == Entity::OBBCollidesFlag)
|
|
model->defaultFlags = 0;
|
|
|
|
const char *walk_thru_string;
|
|
if(page->GetEntry("WalkThruFlag", &walk_thru_string))
|
|
{
|
|
model->defaultFlags |= WalkThruTextToAscii(walk_thru_string);
|
|
}
|
|
}
|
|
|
|
//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
|
|
//
|
|
void
|
|
Entity__GameModel::ConstructOBBStream(Script *script)
|
|
{
|
|
Check_Object(script);
|
|
|
|
//
|
|
//--------------
|
|
// Set up stream
|
|
//--------------
|
|
//
|
|
MemoryStream *model_stream = script->modelStream;
|
|
Check_Object(model_stream);
|
|
Entity__GameModel *model =
|
|
Cast_Pointer(Entity__GameModel*, model_stream->GetPointer());
|
|
|
|
//
|
|
//------------------------------
|
|
// See if there is an OBB stream
|
|
//------------------------------
|
|
//
|
|
NotationFile *model_file = script->modelFile;
|
|
Check_Object(model_file);
|
|
Page *page = model_file->GetPage("GameData");
|
|
Check_Object(page);
|
|
const char* obb_stream_name;
|
|
if (!page->GetEntry("SolidOBB", &obb_stream_name))
|
|
return;
|
|
|
|
//
|
|
//--------------------------------------------------------
|
|
// There is, so now we have to stuff it into the resources
|
|
//--------------------------------------------------------
|
|
//
|
|
Check_Pointer(obb_stream_name);
|
|
FileStream obb_stream(obb_stream_name);
|
|
const char* file_name = obb_stream.GetFileName();
|
|
Resource res(file_name);
|
|
if (!res.DoesResourceExist() || !res.IsResourceUpToDate())
|
|
{
|
|
FileDependencies obb_dependencies;
|
|
obb_dependencies.AddDependency(&obb_stream);
|
|
res.Save(&obb_stream, &obb_dependencies);
|
|
if (!res.IsRegistered())
|
|
Resource::ParentFileDependencies->AddDependencies(&obb_dependencies);
|
|
}
|
|
else if (!res.IsRegistered())
|
|
res.AddFileDependenciesTo(Resource::ParentFileDependencies);
|
|
model->obbStreamResourceID = res.GetResourceID();
|
|
}
|
|
|
|
//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
|
|
//
|
|
bool
|
|
Entity__GameModel::ReadAndVerify(
|
|
Entity__GameModel *model,
|
|
ModelAttributeEntry *attribute_entry,
|
|
const char *data,
|
|
char **error,
|
|
int error_buffer
|
|
)
|
|
{
|
|
Check_Object(attribute_entry);
|
|
bool result = false;
|
|
bool valid_data = (*data != '\0');
|
|
|
|
//
|
|
//----------------------------------------
|
|
//This is the Genric Type read in Section.
|
|
//----------------------------------------
|
|
//
|
|
|
|
if(valid_data)
|
|
{
|
|
switch(attribute_entry->attributeType)
|
|
{
|
|
case ScalarClassID:
|
|
{
|
|
Scalar value = AtoF(data);
|
|
attribute_entry->SetValue(model, &value);
|
|
result = true;
|
|
break;
|
|
}
|
|
case Vector3DClassID:
|
|
{
|
|
Vector3D value;
|
|
int entries = sscanf(
|
|
data,
|
|
"%f %f %f",
|
|
&value.x,
|
|
&value.y,
|
|
&value.z
|
|
);
|
|
if(entries != 3)
|
|
{
|
|
_snprintf(
|
|
*error,
|
|
error_buffer,
|
|
"{[GameData]%s=%s}Bad Vector Value",
|
|
(char *)attribute_entry->attributeName,
|
|
data
|
|
);
|
|
return false;
|
|
}
|
|
attribute_entry->SetValue(model, &value);
|
|
result = true;
|
|
break;
|
|
}
|
|
case IntClassID:
|
|
{
|
|
int value = atoi(data);
|
|
attribute_entry->SetValue(model, &value);
|
|
result = true;
|
|
break;
|
|
}
|
|
case BoolClassID:
|
|
{
|
|
bool value = (!_stricmp(data, "true") || !_stricmp(data, "yes") || atoi(data) != 0);
|
|
attribute_entry->SetValue(model, &value);
|
|
result = true;
|
|
break;
|
|
}
|
|
case RadianClassID:
|
|
{
|
|
Radian value = AtoF(data);
|
|
value = value * Stuff::Radians_Per_Degree;
|
|
attribute_entry->SetValue(model, &value);
|
|
result = true;
|
|
break;
|
|
}
|
|
case Point3DClassID:
|
|
{
|
|
Point3D value;
|
|
int entries;
|
|
entries = sscanf(
|
|
data,
|
|
"%f %f %f",
|
|
&value.x,
|
|
&value.y,
|
|
&value.z
|
|
);
|
|
if(entries != 3)
|
|
{
|
|
_snprintf(
|
|
*error,
|
|
error_buffer,
|
|
"{[GameData]%s=%s}Bad Point Value",
|
|
(char *)attribute_entry->attributeName,
|
|
data
|
|
);
|
|
return false;
|
|
}
|
|
attribute_entry->SetValue(model, &value);
|
|
result = true;
|
|
break;
|
|
}
|
|
case RGBAColorClassID:
|
|
{
|
|
RGBAColor value;
|
|
int entries;
|
|
entries = sscanf(
|
|
data,
|
|
"%f %f %f %f",
|
|
&value.red,
|
|
&value.green,
|
|
&value.blue,
|
|
&value.alpha
|
|
);
|
|
if (entries == 3)
|
|
{
|
|
value.alpha = 1.0f;
|
|
}
|
|
if (entries < 3)
|
|
{
|
|
_snprintf(
|
|
*error,
|
|
error_buffer,
|
|
"{[GameData]%s=%s}Bad RGBAColor Value",
|
|
(char *)attribute_entry->attributeName,
|
|
data
|
|
);
|
|
return false;
|
|
}
|
|
attribute_entry->SetValue(model, &value);
|
|
result = true;
|
|
break;
|
|
}
|
|
case UnitQuaternionClassID:
|
|
{
|
|
//Read in a quaternion as a YawpitchRoll angle
|
|
UnitQuaternion value;
|
|
YawPitchRoll yaw_pitch_roll;
|
|
int entries;
|
|
entries = sscanf(
|
|
data,
|
|
"%f %f %f",
|
|
&yaw_pitch_roll.yaw.angle,
|
|
&yaw_pitch_roll.pitch.angle,
|
|
&yaw_pitch_roll.roll.angle
|
|
);
|
|
if(entries != 3)
|
|
{
|
|
_snprintf(
|
|
*error,
|
|
error_buffer,
|
|
"{[GameData]%s=%s}Bad Angle Value",
|
|
(char *)attribute_entry->attributeName,
|
|
data
|
|
);
|
|
return false;
|
|
}
|
|
yaw_pitch_roll.yaw *= Radians_Per_Degree;
|
|
yaw_pitch_roll.pitch *= Radians_Per_Degree;
|
|
yaw_pitch_roll.roll *= Radians_Per_Degree;
|
|
value = yaw_pitch_roll;
|
|
value.Normalize();
|
|
attribute_entry->SetValue(model, &value);
|
|
result = true;
|
|
break;
|
|
}
|
|
case CharClassID:
|
|
{
|
|
char *value;
|
|
value = new char[MaxStringLength];
|
|
Check_Pointer(value);
|
|
Str_Copy(value, data, MaxStringLength);
|
|
attribute_entry->SetValue(model, value);
|
|
result = true;
|
|
Check_Pointer(value);
|
|
delete value;
|
|
break;
|
|
}
|
|
case ResourceIDClassID:
|
|
{
|
|
const char* resource_name = (const char *)data;
|
|
const char* resource_extension = strrchr(resource_name, '.');
|
|
|
|
// resource_extension == NULL is a valid value.
|
|
|
|
if(resource_extension && !_stricmp(resource_extension, ".data"))
|
|
{
|
|
//
|
|
//------------------------------------------------
|
|
//If we are a .data file then Create us as a model
|
|
//------------------------------------------------
|
|
//
|
|
Resource model_resource;
|
|
Tool::Instance->ConstructDataList(&model_resource, resource_name);
|
|
Check_Object(&model_resource);
|
|
Verify(model_resource.DoesResourceExist());
|
|
attribute_entry->SetValue(model, (void *)&model_resource.GetResourceID());
|
|
result = true;
|
|
}
|
|
else if(resource_extension && !_stricmp(resource_extension, ".instance"))
|
|
{
|
|
NotationFile instance_file(resource_name);
|
|
Resource instance_resource;
|
|
ReplicatorID base_id = ReplicatorID::Null;
|
|
Check_Object(Tool::Instance);
|
|
Tool::Instance->ConstructCreateMessage(
|
|
&instance_resource,
|
|
&instance_file,
|
|
&base_id
|
|
);
|
|
Verify(instance_resource.DoesResourceExist());
|
|
attribute_entry->SetValue(model, (void *)&instance_resource.GetResourceID());
|
|
result = true;
|
|
}
|
|
else
|
|
{
|
|
ResourceID default_id = ResourceID::Null;
|
|
attribute_entry->SetValue(model, (void *)&default_id);
|
|
result = true;
|
|
}
|
|
break;
|
|
}
|
|
}
|
|
}
|
|
switch(attribute_entry->attributeID)
|
|
{
|
|
case ColliderAttributeID:
|
|
{
|
|
if(!valid_data)
|
|
{
|
|
bool value = false;
|
|
attribute_entry->SetValue(model,&value);
|
|
result = true;
|
|
}
|
|
}
|
|
break;
|
|
case CanBeShotAttributeID:
|
|
{
|
|
if(!valid_data)
|
|
{
|
|
bool value = false;
|
|
attribute_entry->SetValue(model,&value);
|
|
result = true;
|
|
}
|
|
}
|
|
break;
|
|
case CanBeWalkedOnAttributeID:
|
|
{
|
|
if(!valid_data)
|
|
{
|
|
bool value = false;
|
|
attribute_entry->SetValue(model,&value);
|
|
result = true;
|
|
}
|
|
}
|
|
break;
|
|
case WaterSurfaceAttributeID:
|
|
{
|
|
if(!valid_data)
|
|
{
|
|
bool value = false;
|
|
attribute_entry->SetValue(model,&value);
|
|
result = true;
|
|
}
|
|
}
|
|
break;
|
|
case OBBCollidesAttributeID:
|
|
{
|
|
if(!valid_data)
|
|
{
|
|
bool value = true;
|
|
attribute_entry->SetValue(model,&value);
|
|
result = true;
|
|
}
|
|
}
|
|
break;
|
|
}
|
|
|
|
return result;
|
|
}
|
|
|
|
//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
|
|
//
|
|
void
|
|
Entity__GameModel::WriteToText(
|
|
Entity__GameModel *model,
|
|
ModelAttributeEntry *attribute_entry,
|
|
char **text_string
|
|
)
|
|
{
|
|
Check_Object(attribute_entry);
|
|
Check_Pointer(model);
|
|
|
|
switch(attribute_entry->attributeType)
|
|
{
|
|
case ScalarClassID:
|
|
{
|
|
Scalar value;
|
|
attribute_entry->GetValue((Entity__GameModel *)model, &value);
|
|
sprintf(
|
|
*text_string,
|
|
"%.2f",
|
|
value
|
|
);
|
|
break;
|
|
}
|
|
case RadianClassID:
|
|
{
|
|
Radian value;
|
|
attribute_entry->GetValue((Entity__GameModel *)model, &value);
|
|
value = value * Stuff::Degrees_Per_Radian;
|
|
sprintf(
|
|
*text_string,
|
|
"%.2f",
|
|
value.angle
|
|
);
|
|
break;
|
|
}
|
|
case IntClassID:
|
|
{
|
|
int value;
|
|
attribute_entry->GetValue((Entity__GameModel *)model, &value);
|
|
sprintf(
|
|
*text_string,
|
|
"%d",
|
|
value
|
|
);
|
|
break;
|
|
}
|
|
case Vector3DClassID:
|
|
{
|
|
Vector3D value;
|
|
attribute_entry->GetValue((Entity__GameModel *)model, &value);
|
|
sprintf(
|
|
*text_string,
|
|
"%.2f %.2f %.2f",
|
|
value.x,
|
|
value.y,
|
|
value.z
|
|
);
|
|
break;
|
|
}
|
|
case BoolClassID:
|
|
{
|
|
bool value;
|
|
attribute_entry->GetValue((Entity__GameModel *)model, &value);
|
|
if(value)
|
|
{
|
|
strcpy(*text_string, "yes");
|
|
}
|
|
else
|
|
{
|
|
strcpy(*text_string, "no");
|
|
}
|
|
break;
|
|
}
|
|
case Point3DClassID:
|
|
{
|
|
Point3D value;
|
|
attribute_entry->GetValue((Entity__GameModel *)model, &value);
|
|
sprintf(
|
|
*text_string,
|
|
"%.2f %.2f %.2f",
|
|
value.x,
|
|
value.y,
|
|
value.z
|
|
);
|
|
break;
|
|
}
|
|
case RGBAColorClassID:
|
|
{
|
|
RGBAColor value;
|
|
attribute_entry->GetValue((Entity__GameModel *)model, &value);
|
|
sprintf(
|
|
*text_string,
|
|
"%.2f %.2f %.2f %.2f",
|
|
value.red,
|
|
value.green,
|
|
value.blue,
|
|
value.alpha
|
|
);
|
|
break;
|
|
}
|
|
case UnitQuaternionClassID:
|
|
{
|
|
UnitQuaternion value;
|
|
YawPitchRoll yaw_pitch_roll;
|
|
attribute_entry->GetValue((Entity__GameModel *)model, &value);
|
|
yaw_pitch_roll = value;
|
|
sprintf(
|
|
*text_string,
|
|
"%.2f %.2f %.2f",
|
|
yaw_pitch_roll.yaw,
|
|
yaw_pitch_roll.pitch,
|
|
yaw_pitch_roll.roll
|
|
);
|
|
break;
|
|
}
|
|
case ResourceIDClassID:
|
|
{
|
|
ResourceID value;
|
|
attribute_entry->GetValue((Entity__GameModel *)model, &value);
|
|
char path[256],*p;
|
|
if(value != ResourceID::Null)
|
|
{
|
|
Resource resource(value);
|
|
strcpy(path,resource.GetName());
|
|
|
|
p = strrchr(path,'{');
|
|
if (p) p = 0;
|
|
p = strrchr(path,'.');
|
|
if (!stricmp(p,".data"))
|
|
{
|
|
sprintf(*text_string,"Content\\%s",path);
|
|
}
|
|
|
|
}
|
|
else
|
|
{
|
|
strcpy(path, "NULL");
|
|
sprintf(*text_string,"%s",path);
|
|
}
|
|
|
|
break;
|
|
}
|
|
}
|
|
}
|
|
|
|
//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
|
|
//
|
|
void
|
|
Entity__GameModel::SaveGameModel(
|
|
Entity__GameModel *model,
|
|
Stuff::NotationFile *data_file
|
|
)
|
|
{
|
|
Check_Object(model);
|
|
Check_Object(data_file);
|
|
|
|
//
|
|
//---------------------------------------------------------------
|
|
//First we need to spin through our attributes and write them out
|
|
//---------------------------------------------------------------
|
|
//
|
|
ModelAttributeEntry *attribute_entry;
|
|
Entity__ClassData *class_data;
|
|
class_data = (Entity__ClassData *)Entity::FindClassData(model->classID);
|
|
TableIteratorOf<ModelAttributeEntry *, Entity__GameModel::AttributeID> iterator(
|
|
&class_data->gameModelAttributeTable.attributesByID);
|
|
int num_attributes = iterator.GetSize();
|
|
int i;
|
|
|
|
|
|
Page *page = data_file->SetPage("GameData");
|
|
Check_Object(page);
|
|
|
|
page->SetEntry("Class",class_data->GetClassName());
|
|
|
|
//This is temp for right now...eventually we will need a text write function in element
|
|
if(model->elementResourceID != ResourceID::Null)
|
|
{
|
|
Resource element_resource(model->elementResourceID);
|
|
Verify(element_resource.DoesResourceExist());
|
|
|
|
//We need to yank out the cull mode from this stream
|
|
unsigned element_state;
|
|
element_resource >> element_state;
|
|
|
|
if (element_state & ElementRenderer::Element::BoundsLockedFlag)
|
|
{
|
|
page->SetEntry("Cull", "NeverCull");
|
|
}
|
|
}
|
|
|
|
for(i=Entity__GameModel::AnyAttributeID + 1;i<num_attributes;i++)
|
|
{
|
|
attribute_entry =
|
|
class_data->gameModelAttributeTable.GetAttributeEntry(i);
|
|
|
|
Check_Object(attribute_entry);
|
|
|
|
char* data = new char [Entity__GameModel::MaxStringLength];
|
|
Register_Pointer(data);
|
|
|
|
class_data->modelWriteToText(model, attribute_entry, &data);
|
|
|
|
page->SetEntry(attribute_entry->attributeName,data);
|
|
|
|
Unregister_Pointer(data);
|
|
delete [] data;
|
|
}
|
|
|
|
int flags = model->defaultFlags;
|
|
if(flags & Entity::HeavyCanWalkThruType)
|
|
page->SetEntry("WalkThruFlag", "HeavyCanWalkThru");
|
|
else if(flags & Entity::MediumCanWalkThruType)
|
|
page->SetEntry("WalkThruFlag", "MediumCanWalkThru");
|
|
else if(flags & Entity::AnythingCanWalkThruType)
|
|
page->SetEntry("WalkThruFlag", "AnythingCanWalkThru");
|
|
//
|
|
//--------------------------------------------------------
|
|
//Now we need to save out the specific non attribute stuff
|
|
//--------------------------------------------------------
|
|
//
|
|
#if 0
|
|
if(obbStreamResourceID != ResourceID::Null)
|
|
{
|
|
Resource obb_resource(obbStreamResourceID);
|
|
Verify(obb_resource.DoesResourceExist());
|
|
data_file->SetEntry("GameData",
|
|
#endif
|
|
}
|
|
|
|
//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
|
|
//
|
|
const char *
|
|
Entity::AlignmentAsciiToText(int alignment)
|
|
{
|
|
switch(alignment)
|
|
{
|
|
case Player:
|
|
return "Player";
|
|
case Enemy:
|
|
return "Enemy";
|
|
case Team1:
|
|
return "Team1";
|
|
case Team2:
|
|
return "Team2";
|
|
case Team3:
|
|
return "Team3";
|
|
case Team4:
|
|
return "Team4";
|
|
}
|
|
return "Default";
|
|
}
|
|
|
|
//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
|
|
//
|
|
int
|
|
Entity::AlignmentTextToAscii(const char *alignment)
|
|
{
|
|
if(!_stricmp(alignment, "Player"))
|
|
return Player;
|
|
else if(!_stricmp(alignment, "Enemy"))
|
|
return Enemy;
|
|
else if(!_stricmp(alignment, "Team1"))
|
|
return Team1;
|
|
else if(!_stricmp(alignment, "Team2"))
|
|
return Team2;
|
|
else if(!_stricmp(alignment, "Team3"))
|
|
return Team3;
|
|
else if(!_stricmp(alignment, "Team4"))
|
|
return Team4;
|
|
|
|
return DefaultAlignment;
|
|
}
|
|
|
|
//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
|
|
//
|
|
void
|
|
Entity__GameModel::GetEffectResourceID(ResourceID *return_id, const ResourceID& effect_stream, BYTE index)
|
|
{
|
|
ResourceID *effect_array;
|
|
Resource effect_resource(effect_stream);
|
|
Verify(effect_resource.DoesResourceExist());
|
|
|
|
BYTE material_count;
|
|
effect_resource >> material_count;
|
|
if (material_count <= index)
|
|
{
|
|
*return_id = ResourceID::Null;
|
|
return;
|
|
}
|
|
effect_array = Cast_Pointer(ResourceID *, effect_resource.GetPointer());
|
|
*return_id = effect_array[index];
|
|
|
|
#if defined(_ARMOR)
|
|
if(*return_id != ResourceID::Null)
|
|
{
|
|
Resource verify_resource(*return_id);
|
|
Verify(verify_resource.DoesResourceExist());
|
|
}
|
|
#endif
|
|
}
|
|
|
|
//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
|
|
//
|
|
int
|
|
Entity__GameModel::WalkThruTextToAscii(const char *string)
|
|
{
|
|
if(!_stricmp(string, "NothingCanWalkThru"))
|
|
return Entity::NothingCanWalkThruType;
|
|
else if(!_stricmp(string, "HeavyCanWalkThru"))
|
|
return Entity::HeavyCanWalkThruType;
|
|
else if(!_stricmp(string, "MediumCanWalkThru"))
|
|
return Entity::MediumCanWalkThruType;
|
|
else if(!_stricmp(string, "AnythingCanWalkThru"))
|
|
return Entity::AnythingCanWalkThruType;
|
|
else
|
|
STOP(("Walk Thru Type: %s is not valid", string));
|
|
return 0;
|
|
}
|
|
|