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.
512 lines
16 KiB
C++
512 lines
16 KiB
C++
#include "AdeptHeaders.hpp"
|
|
|
|
#include "Map.hpp"
|
|
#include "RendererManager.hpp"
|
|
#include "Tool.hpp"
|
|
#include <ElementRenderer\GridElement.hpp>
|
|
#include "NameTable.hpp"
|
|
#include "Zone.hpp"
|
|
|
|
//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
|
|
//
|
|
void
|
|
Map__CreateMessage::ConstructCreateMessage(Script *script)
|
|
{
|
|
Check_Object(script);
|
|
#if defined(_ARMOR)
|
|
int stack_level = Tool::Instance->GetStackLevel();
|
|
#endif
|
|
|
|
//
|
|
//--------------
|
|
// Set up stream
|
|
//--------------
|
|
//
|
|
MemoryStream *message_stream = script->messageStream;
|
|
Check_Object(message_stream);
|
|
message_stream->AllocateBytes(sizeof(Map__CreateMessage));
|
|
Entity__CreateMessage::ConstructCreateMessage(script);
|
|
Map__CreateMessage *message =
|
|
Cast_Pointer(
|
|
Map__CreateMessage*,
|
|
message_stream->GetPointer()
|
|
);
|
|
message->messageLength = sizeof(*message);
|
|
|
|
//
|
|
//-------------------------------------------------------------------------
|
|
// No matter what the instance file said, all maps are independent entities
|
|
//-------------------------------------------------------------------------
|
|
//
|
|
message->replicatorFlags &= ~Replicator::ReplicatorModeMask;
|
|
message->replicatorFlags |= Replicator::IndependentMode;
|
|
|
|
//
|
|
//---------------------------------------------------------------
|
|
// Point at the notation file and make other files relative to it
|
|
//---------------------------------------------------------------
|
|
//
|
|
Page *page = script->instancePage;
|
|
Check_Object(page);
|
|
|
|
//
|
|
//---------------------------------------------------------------------
|
|
// Open up the contents file, and see if its empty. If so, we are done
|
|
//---------------------------------------------------------------------
|
|
//
|
|
NotationFile props_file;
|
|
page->GetEntry("Props", &props_file);
|
|
NotationFile::PageIterator *pages = props_file.MakePageIterator();
|
|
Check_Object(pages);
|
|
if (!pages->GetSize())
|
|
{
|
|
message->m_propStreamResourceID = ResourceID::Null;
|
|
Verify(stack_level == Tool::Instance->GetStackLevel());
|
|
delete pages;
|
|
return;
|
|
}
|
|
|
|
//
|
|
//-------------------------------------------------------------
|
|
// Look for the prop stream resource to see if it is up to date
|
|
//-------------------------------------------------------------
|
|
//
|
|
STOP(("Not updated"));
|
|
const char* props_filename = props_file.GetFileName();
|
|
Resource prop_resource(props_filename);
|
|
if (
|
|
prop_resource.DoesResourceExist() &&
|
|
prop_resource.IsResourceUpToDate()
|
|
)
|
|
{
|
|
WORD span;
|
|
prop_resource >> span;
|
|
Verify(span > 0);
|
|
*script->baseID += span;
|
|
message->replicatorID += span;
|
|
message->m_propStreamResourceID = prop_resource.GetResourceID();
|
|
}
|
|
|
|
//
|
|
//---------------------------------------
|
|
// For each page, an entity will be built
|
|
//---------------------------------------
|
|
//
|
|
else
|
|
{
|
|
Check_Object(Tool::Instance);
|
|
Tool::Instance->PushFilePath(&props_file);
|
|
DynamicMemoryStream prop_stream(sizeof(WORD));
|
|
prop_stream << static_cast<WORD>(0);
|
|
Page *instance;
|
|
ReplicatorID starting_id = *script->baseID;
|
|
while ((instance = pages->ReadAndNext()) != NULL)
|
|
{
|
|
Check_Object(instance);
|
|
|
|
//
|
|
//--------------------------------
|
|
// Create the entity for this page
|
|
//--------------------------------
|
|
//
|
|
const char *instance_name = instance->GetName();
|
|
Check_Pointer(instance_name);
|
|
Entity::CreateMessage *message =
|
|
Tool::Instance->ConstructCreateMessage(
|
|
&prop_stream,
|
|
instance,
|
|
script->baseID
|
|
);
|
|
Check_Object(message);
|
|
Check_Object(NameTable::GetInstance());
|
|
message->nameID = NameTable::GetInstance()->FindID(instance_name);
|
|
prop_stream.AdvancePointer(message->messageLength);
|
|
}
|
|
|
|
//
|
|
//-----------------------------------------
|
|
// Only save out the stream if there is one
|
|
//-----------------------------------------
|
|
//
|
|
if (prop_stream.GetBytesUsed() > sizeof(WORD))
|
|
{
|
|
prop_stream.Rewind();
|
|
Verify(*script->baseID != starting_id);
|
|
WORD span =
|
|
static_cast<WORD>(script->baseID->localID - starting_id.localID);
|
|
prop_stream << span;
|
|
message->replicatorID += span;
|
|
prop_resource.Save(&prop_stream, props_file.GetFileDependencies());
|
|
Check_Object(&prop_resource);
|
|
message->m_propStreamResourceID = prop_resource.GetResourceID();
|
|
}
|
|
else
|
|
message->m_propStreamResourceID = ResourceID::Null;
|
|
Tool::Instance->PopFilePath();
|
|
}
|
|
|
|
//
|
|
//------------------------
|
|
// Clean up the tool stack
|
|
//------------------------
|
|
//
|
|
Check_Object(pages);
|
|
delete pages;
|
|
Verify(stack_level == Tool::Instance->GetStackLevel());
|
|
}
|
|
|
|
//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
|
|
//
|
|
void
|
|
Map__GameModel::ConstructGameModel(Script *script)
|
|
{
|
|
Check_Object(script);
|
|
Check_Object(Tool::Instance);
|
|
#if defined(_ARMOR)
|
|
int stack_index = Tool::Instance->GetStackLevel();
|
|
#endif
|
|
Check_Object(Resource::ParentFileDependencies);
|
|
|
|
//
|
|
//--------------
|
|
// Set up stream
|
|
//--------------
|
|
//
|
|
MemoryStream *model_stream = script->modelStream;
|
|
Check_Object(model_stream);
|
|
model_stream->AllocateBytes(sizeof(Map__GameModel));
|
|
Entity__GameModel::ConstructGameModel(script);
|
|
Map__GameModel *model =
|
|
Cast_Pointer(Map__GameModel*, model_stream->GetPointer());
|
|
Check_Object(model);
|
|
NotationFile *model_file = script->modelFile;
|
|
Check_Object(model_file);
|
|
Tool::Instance->PushFilePath(model_file);
|
|
|
|
//
|
|
//-------------------------------------
|
|
// We need to get our grid element file
|
|
//-------------------------------------
|
|
//
|
|
Page *page = model_file->FindPage("GameData");
|
|
Check_Object(page);
|
|
model->m_waterLevel = 0.0f;
|
|
page->GetEntry("WaterLevel", &model->m_waterLevel);
|
|
const char* grid_filename;
|
|
page->GetEntry("Grid", &grid_filename, true);
|
|
FileStream grid_file(grid_filename);
|
|
Tool::Instance->PushFilePath(&grid_file);
|
|
grid_filename = grid_file.GetFileName();
|
|
|
|
const char* hudmap_filename;
|
|
model->m_HudMap[0] = 0;
|
|
if (page->GetEntry ("hudmap",&hudmap_filename,false))
|
|
{
|
|
Str_Copy (model->m_HudMap,hudmap_filename,128);
|
|
}
|
|
//
|
|
//---------------------------------------------------------------
|
|
// See if the resource already exists, and if so, just use its ID
|
|
//---------------------------------------------------------------
|
|
//
|
|
Resource grid_resource(grid_filename);
|
|
MString zones_name = grid_filename;
|
|
zones_name += "{zones}";
|
|
Resource zones_resource(zones_name);
|
|
if (!grid_resource.DoesResourceExist() || !grid_resource.IsResourceUpToDate())
|
|
{
|
|
FileDependencies grid_dependencies;
|
|
grid_dependencies.AddDependency(&grid_file);
|
|
|
|
//
|
|
//--------------------------------------------------------------------
|
|
// Now, create the actual grid and see how big it is. We will need to
|
|
// resourcify that number of erf's
|
|
//--------------------------------------------------------------------
|
|
//
|
|
ElementRenderer::GridElement *grid =
|
|
Cast_Object(
|
|
ElementRenderer::GridElement*,
|
|
ElementRenderer::Element::Create(
|
|
&grid_file,
|
|
ElementRenderer::ReadERFVersion(&grid_file)
|
|
)
|
|
);
|
|
grid_file.Rewind();
|
|
BYTE x,z;
|
|
grid->GetSize(&z, &x);
|
|
WORD zone_count = static_cast<WORD>(x*z);
|
|
if (
|
|
x>26 || z>26 || !zone_count
|
|
|| !grid->IsDerivedFrom(ElementRenderer::GridElement::DefaultData)
|
|
)
|
|
{
|
|
STOP((
|
|
"%s{[GameData]Grid=%s}: Bad grid element!",
|
|
model_file->GetFileName(),
|
|
grid_filename
|
|
));
|
|
}
|
|
|
|
DynamicArrayOf<Zone::ResourceData> zones(zone_count);
|
|
Check_Object(grid);
|
|
delete grid;
|
|
|
|
//
|
|
//---------------------------------------------------------------
|
|
// For each zone in the grid, look for the corresponding erf file
|
|
//---------------------------------------------------------------
|
|
//
|
|
unsigned zone=0;
|
|
for (unsigned r=0; r<z; ++r)
|
|
{
|
|
for (unsigned c=0; c<x; ++c)
|
|
{
|
|
//
|
|
//-------------------------
|
|
// We need to tile geometry
|
|
//-------------------------
|
|
//
|
|
char buffer[17];
|
|
#if defined(_ARMOR)
|
|
int count =
|
|
#endif
|
|
sprintf(buffer, "%c%c.erf", r+'A', c+'A');
|
|
Verify(count < sizeof(buffer));
|
|
FileStream erf_file(buffer);
|
|
const char* zone_filename = erf_file.GetFileName();
|
|
|
|
//
|
|
//---------------------------------------------------------------
|
|
// See if the resource already exists, and if so, just use its ID
|
|
//---------------------------------------------------------------
|
|
//
|
|
Resource zone_resource(zone_filename);
|
|
if (!zone_resource.DoesResourceExist() || !zone_resource.IsResourceUpToDate())
|
|
{
|
|
FileDependencies zone_dependencies;
|
|
zone_dependencies.AddDependency(&erf_file);
|
|
zone_resource.Save(&erf_file, &zone_dependencies);
|
|
}
|
|
zone_resource.AddFileDependenciesTo(&grid_dependencies);
|
|
zones[zone].m_geometryResourceID = zone_resource.GetResourceID();
|
|
|
|
//
|
|
//----------------------------
|
|
// We need to get our tile bsp
|
|
//----------------------------
|
|
//
|
|
#if defined(_ARMOR)
|
|
count =
|
|
#endif
|
|
sprintf(buffer, "%c%c.bsp", r+'A', c+'A');
|
|
Verify(count < sizeof(buffer));
|
|
FileStream bsp_file(buffer);
|
|
zone_filename = bsp_file.GetFileName();
|
|
|
|
//
|
|
//---------------------------------------------------------------
|
|
// See if the resource already exists, and if so, just use its ID
|
|
//---------------------------------------------------------------
|
|
//
|
|
Resource bsp_resource(zone_filename);
|
|
if (!bsp_resource.DoesResourceExist() || !bsp_resource.IsResourceUpToDate())
|
|
{
|
|
FileDependencies zone_dependencies;
|
|
zone_dependencies.AddDependency(&bsp_file);
|
|
bsp_resource.Save(&bsp_file, &zone_dependencies);
|
|
}
|
|
bsp_resource.AddFileDependenciesTo(&grid_dependencies);
|
|
zones[zone].m_bspResourceID = bsp_resource.GetResourceID();
|
|
|
|
//
|
|
//---------------------------------
|
|
// We need to get our tile material
|
|
//---------------------------------
|
|
//
|
|
#if defined(_ARMOR)
|
|
count =
|
|
#endif
|
|
sprintf(buffer, "%c%c.material", r+'A', c+'A');
|
|
Verify(count < sizeof(buffer));
|
|
if (!gos_DoesFileExist(buffer))
|
|
zones[zone].m_materialResourceID = ResourceID::Null;
|
|
else
|
|
{
|
|
FileStream material_file(buffer);
|
|
zone_filename = material_file.GetFileName();
|
|
|
|
//
|
|
//---------------------------------------------------------------
|
|
// See if the resource already exists, and if so, just use its ID
|
|
//---------------------------------------------------------------
|
|
//
|
|
Resource material_resource(zone_filename);
|
|
if (!material_resource.DoesResourceExist() || !material_resource.IsResourceUpToDate())
|
|
{
|
|
FileDependencies zone_dependencies;
|
|
zone_dependencies.AddDependency(&material_file);
|
|
material_resource.Save(&material_file, &zone_dependencies);
|
|
}
|
|
material_resource.AddFileDependenciesTo(&grid_dependencies);
|
|
zones[zone].m_materialResourceID = material_resource.GetResourceID();
|
|
}
|
|
++zone;
|
|
}
|
|
}
|
|
|
|
//
|
|
//-------------------------------------------
|
|
// Now save out the resource IDs of the model
|
|
//-------------------------------------------
|
|
//
|
|
MemoryStream res_id_stream(zones.GetData(), zones.GetSize());
|
|
zones_resource.Save(&res_id_stream, &grid_dependencies);
|
|
grid_resource.Save(&grid_file, &grid_dependencies);
|
|
if (!zones_resource.IsRegistered())
|
|
Resource::ParentFileDependencies->AddDependencies(&grid_dependencies);
|
|
}
|
|
else if (!grid_resource.IsRegistered())
|
|
grid_resource.AddFileDependenciesTo(Resource::ParentFileDependencies);
|
|
model->m_gridElementResourceID = grid_resource.GetResourceID();
|
|
model->m_zoneArrayResourceID = zones_resource.GetResourceID();
|
|
Tool::Instance->PopFilePath();
|
|
|
|
//
|
|
//-----------------------------
|
|
// Set up the texture spec file
|
|
//-----------------------------
|
|
//
|
|
const char* texture_filename;
|
|
if (page->GetEntry("TextureData", &texture_filename))
|
|
{
|
|
FileStream file_stream(texture_filename);
|
|
const char* file_name = file_stream.GetFileName();
|
|
Resource texture_res(file_name);
|
|
if (!texture_res.DoesResourceExist() || !texture_res.IsResourceUpToDate())
|
|
{
|
|
FileDependencies tex_dependencies;
|
|
tex_dependencies.AddDependency(&file_stream);
|
|
texture_res.Save(&file_stream, &tex_dependencies);
|
|
if (!texture_res.IsRegistered())
|
|
Resource::ParentFileDependencies->AddDependencies(&tex_dependencies);
|
|
}
|
|
else if (!texture_res.IsRegistered())
|
|
texture_res.AddFileDependenciesTo(Resource::ParentFileDependencies);
|
|
model->m_textureDataResourceID = texture_res.GetResourceID();
|
|
|
|
//
|
|
//-----------------------------
|
|
// Load up the TCF file
|
|
//-----------------------------
|
|
//
|
|
const char* tcf_filename;
|
|
model->m_tcfResourceID = ResourceID::Null;
|
|
page->GetEntry("TCFFilename", &tcf_filename, true);
|
|
|
|
MString long_filename("Content\\Textures\\CompostTexture\\");
|
|
long_filename += tcf_filename;
|
|
|
|
FileStream tcf_file_stream(long_filename);
|
|
const char* tcf_file_name = tcf_file_stream.GetFileName();
|
|
Resource tcf_res(tcf_file_name);
|
|
if (!tcf_res.DoesResourceExist() || !tcf_res.IsResourceUpToDate())
|
|
{
|
|
FileDependencies tcf_dependencies;
|
|
tcf_dependencies.AddDependency(&tcf_file_stream);
|
|
tcf_res.Save(&tcf_file_stream, &tcf_dependencies);
|
|
if (!tcf_res.IsRegistered())
|
|
Resource::ParentFileDependencies->AddDependencies(&tcf_dependencies);
|
|
}
|
|
else if (!tcf_res.IsRegistered())
|
|
tcf_res.AddFileDependenciesTo(Resource::ParentFileDependencies);
|
|
model->m_tcfResourceID = tcf_res.GetResourceID();
|
|
}
|
|
else
|
|
{
|
|
model->m_textureDataResourceID = ResourceID::Null;
|
|
model->m_tcfResourceID = ResourceID::Null;
|
|
}
|
|
|
|
//
|
|
//-----------------------------
|
|
// Set up the cultural data
|
|
//-----------------------------
|
|
//
|
|
const char* cultualdata_filename;
|
|
model->m_culturalDataResourceID = ResourceID::Null;
|
|
if (page->GetEntry("CulturalData", &cultualdata_filename))
|
|
{
|
|
FileStream file_stream(cultualdata_filename);
|
|
const char* file_name = file_stream.GetFileName();
|
|
Resource culturaldata_res(file_name);
|
|
if (!culturaldata_res.DoesResourceExist() || !culturaldata_res.IsResourceUpToDate())
|
|
{
|
|
FileDependencies culturaldata_dependencies;
|
|
culturaldata_dependencies.AddDependency(&file_stream);
|
|
culturaldata_res.Save(&file_stream, &culturaldata_dependencies);
|
|
if (!culturaldata_res.IsRegistered())
|
|
Resource::ParentFileDependencies->AddDependencies(&culturaldata_dependencies);
|
|
}
|
|
else if (!culturaldata_res.IsRegistered())
|
|
culturaldata_res.AddFileDependenciesTo(Resource::ParentFileDependencies);
|
|
model->m_culturalDataResourceID = culturaldata_res.GetResourceID();
|
|
}
|
|
else
|
|
model->m_culturalDataResourceID = ResourceID::Null;
|
|
|
|
|
|
Tool::Instance->PopFilePath();
|
|
Verify(stack_index == Tool::Instance->GetStackLevel());
|
|
}
|
|
|
|
//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
|
|
//
|
|
bool
|
|
Map__GameModel::ReadAndVerify(
|
|
Map__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');
|
|
|
|
//
|
|
//----------------------------------------
|
|
//Read in the values from the data entered
|
|
//----------------------------------------
|
|
//
|
|
result =
|
|
Entity__GameModel::ReadAndVerify(
|
|
model,
|
|
attribute_entry,
|
|
data,
|
|
error,
|
|
error_buffer
|
|
);
|
|
//
|
|
//---------------------------
|
|
//Verify all the model values
|
|
//---------------------------
|
|
//
|
|
switch(attribute_entry->attributeID)
|
|
{
|
|
case DamageCraterResourceAttributeID:
|
|
{
|
|
if(!valid_data)
|
|
{
|
|
ResourceID value = ResourceID::Null;
|
|
attribute_entry->SetValue(model, (void *)&value);
|
|
result = true;
|
|
}
|
|
break;
|
|
}
|
|
}
|
|
return result;
|
|
}
|