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.
1669 lines
44 KiB
C++
1669 lines
44 KiB
C++
//===========================================================================//
|
|
// File: Mission.cpp //
|
|
//---------------------------------------------------------------------------//
|
|
// Date Who Modification //
|
|
// -------- --- ---------------------------------------------------------- //
|
|
// 02/19/95 JMA Initial coding. //
|
|
// 08/25/97 ECH Infrastructure changes. //
|
|
//---------------------------------------------------------------------------//
|
|
// Copyright (C) 1995, Virtual World Entertainment, Inc. //
|
|
// All Rights reserved worldwide //
|
|
// This unpublished sourcecode is PROPRIETARY and CONFIDENTIAL //
|
|
//===========================================================================//
|
|
|
|
#include "AdeptHeaders.hpp"
|
|
|
|
#include "Mission.hpp"
|
|
#include "Map.hpp"
|
|
#include "Tool.hpp"
|
|
#include "EntityManager.hpp"
|
|
#include "VideoRenderer.hpp"
|
|
#include "NameTable.hpp"
|
|
#include <MLR\MLR.hpp>
|
|
#include <MLR\MLRLight.hpp>
|
|
|
|
//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
|
|
//
|
|
void
|
|
Mission__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(Mission__CreateMessage));
|
|
Entity__CreateMessage::ConstructCreateMessage(script);
|
|
Mission__CreateMessage *message =
|
|
Cast_Pointer(
|
|
Mission__CreateMessage*,
|
|
message_stream->GetPointer()
|
|
);
|
|
message->messageLength = sizeof(*message);
|
|
|
|
//
|
|
//-----------------------------------------------------------------------------
|
|
// No matter what the instance file said, all missions are independent entities
|
|
//-----------------------------------------------------------------------------
|
|
//
|
|
message->replicatorFlags &= ~Replicator::ReplicatorModeMask;
|
|
message->replicatorFlags |= Replicator::IndependentMode;
|
|
|
|
//
|
|
//---------------------------------------------------------------
|
|
// Point at the notation file and make other files relative to it
|
|
//---------------------------------------------------------------
|
|
//
|
|
Check_Object(Tool::Instance);
|
|
Page* page = script->instancePage;
|
|
Check_Object(page);
|
|
Tool::Instance->PushFilePath(page->GetNotationFile());
|
|
|
|
//
|
|
//-----------------------------------------------
|
|
// Add all Entity Names to the Mission Name Table
|
|
//-----------------------------------------------
|
|
//
|
|
Verify(NameTable::GetInstance() == NULL);
|
|
GlobalPointers::AddGlobalPointer(new NameTable(), NameTableGlobalPointerIndex);
|
|
Check_Object(NameTable::GetInstance());
|
|
|
|
{
|
|
MString table_name = page->GetName();
|
|
table_name += "{NameTable}";
|
|
Resource name_table_resource(table_name);
|
|
if (name_table_resource.DoesResourceExist() && name_table_resource.IsResourceUpToDate())
|
|
{
|
|
Verify(name_table_resource.DoesResourceExist());
|
|
name_table_resource.LoadData();
|
|
Check_Object(NameTable::GetInstance());
|
|
NameTable::GetInstance()->LoadTable(&name_table_resource);
|
|
message->m_nameTableStreamResourceID = name_table_resource.GetResourceID();
|
|
if (!name_table_resource.IsRegistered())
|
|
name_table_resource.AddFileDependenciesTo(Resource::ParentFileDependencies);
|
|
}
|
|
else
|
|
{
|
|
NotationFile table_file;
|
|
if (page->GetEntry("NameTable", &table_file))
|
|
{
|
|
Tool::Instance->PushFilePath(&table_file);
|
|
NameTable::GetInstance()->LoadTable(&table_file);
|
|
Tool::Instance->PopFilePath();
|
|
}
|
|
//
|
|
//------------------------------------------
|
|
// Write out the Mission Name Table Stream
|
|
//------------------------------------------
|
|
//
|
|
DynamicMemoryStream name_table_stream;
|
|
Check_Object(NameTable::GetInstance());
|
|
NameTable::GetInstance()->SaveTable(&name_table_stream);
|
|
|
|
if (name_table_stream.GetBytesUsed())
|
|
{
|
|
name_table_resource.Save(&name_table_stream, table_file.GetFileDependencies());
|
|
if (name_table_resource.IsRegistered())
|
|
name_table_resource.AddFileDependenciesTo(Resource::ParentFileDependencies);
|
|
Check_Object(&name_table_resource);
|
|
message->m_nameTableStreamResourceID = name_table_resource.GetResourceID();
|
|
}
|
|
else
|
|
message->m_nameTableStreamResourceID = ResourceID::Null;
|
|
}
|
|
}
|
|
|
|
//
|
|
//-----------------------------------------------------------------
|
|
// Create the map instance and stuff its resource ID in the message
|
|
//-----------------------------------------------------------------
|
|
//
|
|
{
|
|
NotationFile map_file;
|
|
page->GetEntry("Map", &map_file, true);
|
|
Resource map_instance;
|
|
Check_Object(Tool::Instance);
|
|
ReplicatorID starting_id = *script->baseID;
|
|
Tool::Instance->ConstructCreateMessage(
|
|
&map_instance,
|
|
&map_file,
|
|
script->baseID
|
|
);
|
|
message->m_mapResourceID = map_instance.GetResourceID();
|
|
WORD span =
|
|
static_cast<WORD>(script->baseID->localID - starting_id.localID);
|
|
message->replicatorID += span;
|
|
}
|
|
|
|
//
|
|
//---------------------------------------------------------------------
|
|
// 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;
|
|
}
|
|
|
|
//
|
|
//-------------------------------------------------------------
|
|
// Look for the prop stream resource to see if it is up to date
|
|
//-------------------------------------------------------------
|
|
//
|
|
else
|
|
{
|
|
const char* props_filename = props_file.GetFileName();
|
|
Resource prop_resource(props_filename);
|
|
if (
|
|
prop_resource.DoesResourceExist() &&
|
|
prop_resource.IsResourceUpToDate()
|
|
)
|
|
{
|
|
WORD span;
|
|
prop_resource.LoadData();
|
|
prop_resource >> span;
|
|
Verify(span > 0);
|
|
*script->baseID += span;
|
|
message->replicatorID += span;
|
|
message->m_propStreamResourceID = prop_resource.GetResourceID();
|
|
if (!prop_resource.IsRegistered())
|
|
prop_resource.AddFileDependenciesTo(Resource::ParentFileDependencies);
|
|
}
|
|
|
|
//
|
|
//---------------------------------------
|
|
// For each page, an entity will be built
|
|
//---------------------------------------
|
|
//
|
|
else
|
|
{
|
|
FileDependencies props_deps(*props_file.GetFileDependencies());
|
|
FileDependencies *parent = Resource::ParentFileDependencies;
|
|
Resource::ParentFileDependencies = &props_deps;
|
|
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_deps);
|
|
Check_Object(&prop_resource);
|
|
message->m_propStreamResourceID = prop_resource.GetResourceID();
|
|
}
|
|
else
|
|
message->m_propStreamResourceID = ResourceID::Null;
|
|
if (!prop_resource.IsRegistered())
|
|
parent->AddDependencies(&props_deps);
|
|
Resource::ParentFileDependencies = parent;
|
|
Tool::Instance->PopFilePath();
|
|
}
|
|
}
|
|
delete pages;
|
|
}
|
|
|
|
//
|
|
//-----------------------------------------------
|
|
// For now, no armory until we get it figured out
|
|
//-----------------------------------------------
|
|
//
|
|
{
|
|
NotationFile armory_file;
|
|
page->GetEntry("Armory", &armory_file);
|
|
NotationFile::PageIterator *pages = armory_file.MakePageIterator();
|
|
Check_Object(pages);
|
|
if (!pages->GetSize())
|
|
{
|
|
message->m_armoryStreamResourceID = ResourceID::Null;
|
|
}
|
|
|
|
//
|
|
//-------------------------------------------------------------
|
|
// Look for the prop stream resource to see if it is up to date
|
|
//-------------------------------------------------------------
|
|
//
|
|
else
|
|
{
|
|
const char* armory_filename = armory_file.GetFileName();
|
|
Resource armory_resource(armory_filename);
|
|
if (
|
|
armory_resource.DoesResourceExist() &&
|
|
armory_resource.IsResourceUpToDate()
|
|
)
|
|
{
|
|
WORD span;
|
|
armory_resource.LoadData();
|
|
armory_resource >> span;
|
|
Verify(span > 0);
|
|
*script->baseID += span;
|
|
message->replicatorID += span;
|
|
message->m_armoryStreamResourceID = armory_resource.GetResourceID();
|
|
if (!armory_resource.IsRegistered())
|
|
armory_resource.AddFileDependenciesTo(Resource::ParentFileDependencies);
|
|
}
|
|
|
|
//
|
|
//---------------------------------------
|
|
// For each page, an entity will be built
|
|
//---------------------------------------
|
|
//
|
|
else
|
|
{
|
|
FileDependencies armory_deps(*armory_file.GetFileDependencies());
|
|
FileDependencies *parent = Resource::ParentFileDependencies;
|
|
Resource::ParentFileDependencies = &armory_deps;
|
|
Check_Object(Tool::Instance);
|
|
Tool::Instance->PushFilePath(&armory_file);
|
|
DynamicMemoryStream armory_stream(sizeof(WORD));
|
|
armory_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(
|
|
&armory_stream,
|
|
instance,
|
|
script->baseID
|
|
);
|
|
Check_Object(message);
|
|
Check_Object(NameTable::GetInstance());
|
|
message->nameID = NameTable::GetInstance()->FindID(instance_name);
|
|
armory_stream.AdvancePointer(message->messageLength);
|
|
}
|
|
|
|
//
|
|
//-----------------------------------------
|
|
// Only save out the stream if there is one
|
|
//-----------------------------------------
|
|
//
|
|
if (armory_stream.GetBytesUsed() > sizeof(WORD))
|
|
{
|
|
armory_stream.Rewind();
|
|
Verify(*script->baseID != starting_id);
|
|
WORD span =
|
|
static_cast<WORD>(script->baseID->localID - starting_id.localID);
|
|
armory_stream << span;
|
|
message->replicatorID += span;
|
|
armory_resource.Save(&armory_stream, &armory_deps);
|
|
Check_Object(&armory_resource);
|
|
message->m_armoryStreamResourceID = armory_resource.GetResourceID();
|
|
}
|
|
else
|
|
message->m_armoryStreamResourceID = ResourceID::Null;
|
|
if (!armory_resource.IsRegistered())
|
|
parent->AddDependencies(&armory_deps);
|
|
Resource::ParentFileDependencies = parent;
|
|
Tool::Instance->PopFilePath();
|
|
}
|
|
}
|
|
delete pages;
|
|
}
|
|
Tool::Instance->PopFilePath();
|
|
Verify(stack_level == Tool::Instance->GetStackLevel());
|
|
|
|
//
|
|
//------------------
|
|
// Deal with the sky
|
|
//------------------
|
|
//
|
|
message->m_skyResourceID = ResourceID::Null;
|
|
const char* sky_name;
|
|
if (page->GetEntry("Sky", &sky_name))
|
|
{
|
|
//
|
|
//-------------------------------------------------------------
|
|
// If we are dealing with a 3ds file, call the 3ds resourcifier
|
|
//-------------------------------------------------------------
|
|
//
|
|
FileStream file_stream(sky_name);
|
|
const char* file_name = file_stream.GetFileName();
|
|
|
|
//
|
|
//---------------------------------------------------------------
|
|
// See if the resource already exists, and if so, just use its ID
|
|
//---------------------------------------------------------------
|
|
//
|
|
Resource sky_res(file_name);
|
|
if (!sky_res.DoesResourceExist() || !sky_res.IsResourceUpToDate())
|
|
{
|
|
FileDependencies erf_dependencies;
|
|
erf_dependencies.AddDependency(&file_stream);
|
|
sky_res.Save(&file_stream, &erf_dependencies);
|
|
if (!sky_res.IsRegistered())
|
|
Resource::ParentFileDependencies->AddDependencies(&erf_dependencies);
|
|
}
|
|
else if (!sky_res.IsRegistered())
|
|
sky_res.AddFileDependenciesTo(Resource::ParentFileDependencies);
|
|
message->m_skyResourceID = sky_res.GetResourceID();
|
|
}
|
|
|
|
//
|
|
//------------------------
|
|
// Deal with the Night sky
|
|
//------------------------
|
|
//
|
|
message->m_nightSkyResourceID = ResourceID::Null;
|
|
if (page->GetEntry("NightSky", &sky_name))
|
|
{
|
|
//
|
|
//-------------------------------------------------------------
|
|
// If we are dealing with a 3ds file, call the 3ds resourcifier
|
|
//-------------------------------------------------------------
|
|
//
|
|
FileStream file_stream(sky_name);
|
|
const char* file_name = file_stream.GetFileName();
|
|
|
|
//
|
|
//---------------------------------------------------------------
|
|
// See if the resource already exists, and if so, just use its ID
|
|
//---------------------------------------------------------------
|
|
//
|
|
Resource sky_res(file_name);
|
|
if (!sky_res.DoesResourceExist() || !sky_res.IsResourceUpToDate())
|
|
{
|
|
FileDependencies erf_dependencies;
|
|
erf_dependencies.AddDependency(&file_stream);
|
|
sky_res.Save(&file_stream, &erf_dependencies);
|
|
if (!sky_res.IsRegistered())
|
|
Resource::ParentFileDependencies->AddDependencies(&erf_dependencies);
|
|
}
|
|
else if (!sky_res.IsRegistered())
|
|
sky_res.AddFileDependenciesTo(Resource::ParentFileDependencies);
|
|
message->m_nightSkyResourceID = sky_res.GetResourceID();
|
|
}
|
|
|
|
|
|
//
|
|
//---------------------------
|
|
// Load in the warning bounds
|
|
//---------------------------
|
|
//
|
|
message->m_warningBoundsResourceID = ResourceID::Null;
|
|
const char* bounds_name;
|
|
if (page->GetEntry("WarningBounds", &bounds_name))
|
|
{
|
|
//
|
|
//-------------------------------------------------------------
|
|
// If we are dealing with a 3ds file, call the 3ds resourcifier
|
|
//-------------------------------------------------------------
|
|
//
|
|
FileStream file_stream(bounds_name);
|
|
const char* file_name = file_stream.GetFileName();
|
|
|
|
//
|
|
//---------------------------------------------------------------
|
|
// See if the resource already exists, and if so, just use its ID
|
|
//---------------------------------------------------------------
|
|
//
|
|
Resource bounds_res(file_name);
|
|
if (!bounds_res.DoesResourceExist() || !bounds_res.IsResourceUpToDate())
|
|
{
|
|
FileDependencies bounds_dependencies;
|
|
bounds_dependencies.AddDependency(&file_stream);
|
|
bounds_res.Save(&file_stream, &bounds_dependencies);
|
|
if (!bounds_res.IsRegistered())
|
|
Resource::ParentFileDependencies->AddDependencies(&bounds_dependencies);
|
|
}
|
|
else if (!bounds_res.IsRegistered())
|
|
bounds_res.AddFileDependenciesTo(Resource::ParentFileDependencies);
|
|
message->m_warningBoundsResourceID = bounds_res.GetResourceID();
|
|
}
|
|
|
|
//
|
|
//---------------------------
|
|
// Load in the mission bounds
|
|
//---------------------------
|
|
//
|
|
message->m_missionBoundsResourceID = ResourceID::Null;
|
|
if (page->GetEntry("MissionBounds", &bounds_name))
|
|
{
|
|
//
|
|
//-------------------------------------------------------------
|
|
// If we are dealing with a 3ds file, call the 3ds resourcifier
|
|
//-------------------------------------------------------------
|
|
//
|
|
FileStream file_stream(bounds_name);
|
|
const char* file_name = file_stream.GetFileName();
|
|
|
|
//
|
|
//---------------------------------------------------------------
|
|
// See if the resource already exists, and if so, just use its ID
|
|
//---------------------------------------------------------------
|
|
//
|
|
Resource bounds_res(file_name);
|
|
if (!bounds_res.DoesResourceExist() || !bounds_res.IsResourceUpToDate())
|
|
{
|
|
FileDependencies bounds_dependencies;
|
|
bounds_dependencies.AddDependency(&file_stream);
|
|
bounds_res.Save(&file_stream, &bounds_dependencies);
|
|
if (!bounds_res.IsRegistered())
|
|
Resource::ParentFileDependencies->AddDependencies(&bounds_dependencies);
|
|
}
|
|
else if (!bounds_res.IsRegistered())
|
|
bounds_res.AddFileDependenciesTo(Resource::ParentFileDependencies);
|
|
message->m_missionBoundsResourceID = bounds_res.GetResourceID();
|
|
}
|
|
|
|
message->m_isNightMission = false;
|
|
page->GetEntry("IsNight", &message->m_isNightMission);
|
|
|
|
//
|
|
//-----------------------
|
|
//Clean up the Name Table
|
|
//-----------------------
|
|
//
|
|
Check_Object(NameTable::GetInstance());
|
|
delete NameTable::GetInstance();
|
|
GlobalPointers::ClearPointer(NameTableGlobalPointerIndex);
|
|
}
|
|
|
|
//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
|
|
//
|
|
void
|
|
Mission__GameModel::ConstructGameModel(Script *script)
|
|
{
|
|
Check_Object(script);
|
|
Check_Object(Tool::Instance);
|
|
#if defined(_ARMOR)
|
|
int stack_index = Tool::Instance->GetStackLevel();
|
|
#endif
|
|
|
|
//
|
|
//--------------
|
|
// Set up stream
|
|
//--------------
|
|
//
|
|
MemoryStream *model_stream = script->modelStream;
|
|
Check_Object(model_stream);
|
|
model_stream->AllocateBytes(sizeof(Mission__GameModel));
|
|
Entity__GameModel::ConstructGameModel(script);
|
|
Mission__GameModel *model =
|
|
Cast_Pointer(Mission__GameModel*, model_stream->GetPointer());
|
|
Check_Object(model);
|
|
NotationFile *model_file = script->modelFile;
|
|
Check_Object(model_file);
|
|
Tool::Instance->PushFilePath(model_file);
|
|
|
|
//
|
|
//---------------------
|
|
// Read in the fog data
|
|
//---------------------
|
|
//
|
|
Page *page = model_file->GetPage("GameData");
|
|
Check_Object(page);
|
|
model->m_fogColor.red = 0.0f;
|
|
model->m_fogColor.green = 0.0f;
|
|
model->m_fogColor.blue = 0.0f;
|
|
model->m_fogColor.alpha = 1.0f;
|
|
page->GetEntry("FogColor", &model->m_fogColor);
|
|
|
|
// model->m_animatedTexturesResourceID = ResourceID::Null;
|
|
|
|
//
|
|
//-------------------------------------------------------
|
|
// Create messages for the light stream only if it's there
|
|
//-------------------------------------------------------
|
|
//
|
|
{
|
|
NotationFile lights_file;
|
|
if (!page->GetEntry("Lights", &lights_file))
|
|
model->m_lightStreamResourceID = ResourceID::Null;
|
|
|
|
//
|
|
//-----------------------------------------------------
|
|
// There is a light stream, so open up the contents file
|
|
//-----------------------------------------------------
|
|
//
|
|
else
|
|
{
|
|
|
|
//
|
|
//-------------------------------------------------------------
|
|
// Look for the light stream resource to see if it is up to date
|
|
//-------------------------------------------------------------
|
|
//
|
|
Resource light_resource(lights_file.GetFileName());
|
|
if (
|
|
light_resource.DoesResourceExist() &&
|
|
light_resource.IsResourceUpToDate()
|
|
)
|
|
{
|
|
model->m_lightStreamResourceID = light_resource.GetResourceID();
|
|
if (!light_resource.IsRegistered())
|
|
light_resource.AddFileDependenciesTo(Resource::ParentFileDependencies);
|
|
}
|
|
|
|
//
|
|
//------------------------------------------------------------------
|
|
// It is not up to date, so create stream to write the contents into
|
|
//------------------------------------------------------------------
|
|
//
|
|
else
|
|
{
|
|
Tool::Instance->PushFilePath(&lights_file);
|
|
DynamicMemoryStream light_stream;
|
|
|
|
//
|
|
//----------------------------------------------------
|
|
// Read each light in and write it out into the binary
|
|
//----------------------------------------------------
|
|
//
|
|
MidLevelRenderer::WriteMLRVersion(&light_stream);
|
|
NotationFile::PageIterator *pages = lights_file.MakePageIterator();
|
|
Check_Object(pages);
|
|
Page *light_page;
|
|
while ((light_page = pages->ReadAndNext()) != NULL)
|
|
{
|
|
Check_Object(light_page);
|
|
MidLevelRenderer::MLRLight* light =
|
|
MidLevelRenderer::MLRLight::Make(light_page);
|
|
Check_Object(light);
|
|
light->Save(&light_stream);
|
|
delete light;
|
|
}
|
|
|
|
//
|
|
//-----------------------------------------
|
|
// Only save out the stream if there is one
|
|
//-----------------------------------------
|
|
//
|
|
if (light_stream.GetBytesUsed() > sizeof(WORD))
|
|
{
|
|
light_stream.Rewind();
|
|
light_resource.Save(&light_stream, lights_file.GetFileDependencies());
|
|
if (!light_resource.IsRegistered())
|
|
light_resource.AddFileDependenciesTo(Resource::ParentFileDependencies);
|
|
Check_Object(&light_resource);
|
|
model->m_lightStreamResourceID = light_resource.GetResourceID();
|
|
}
|
|
else
|
|
{
|
|
model->m_lightStreamResourceID = ResourceID::Null;
|
|
if (!light_resource.IsRegistered())
|
|
Resource::ParentFileDependencies->AddDependencies(lights_file.GetFileDependencies());
|
|
}
|
|
|
|
//
|
|
//------------------------
|
|
// Clean up the tool stack
|
|
//------------------------
|
|
//
|
|
Check_Object(pages);
|
|
delete pages;
|
|
Tool::Instance->PopFilePath();
|
|
}
|
|
}
|
|
}
|
|
|
|
//
|
|
//-------------------------------------------------------
|
|
// Create messages for the light stream only if it's there
|
|
//-------------------------------------------------------
|
|
//
|
|
{
|
|
NotationFile lights_file;
|
|
if (!page->GetEntry("NightLights", &lights_file))
|
|
model->m_nightLightStreamResourceID = ResourceID::Null;
|
|
|
|
//
|
|
//-----------------------------------------------------
|
|
// There is a light stream, so open up the contents file
|
|
//-----------------------------------------------------
|
|
//
|
|
else
|
|
{
|
|
|
|
//
|
|
//-------------------------------------------------------------
|
|
// Look for the light stream resource to see if it is up to date
|
|
//-------------------------------------------------------------
|
|
//
|
|
Resource light_resource(lights_file.GetFileName());
|
|
if (
|
|
light_resource.DoesResourceExist() &&
|
|
light_resource.IsResourceUpToDate()
|
|
)
|
|
{
|
|
model->m_nightLightStreamResourceID = light_resource.GetResourceID();
|
|
if (!light_resource.IsRegistered())
|
|
light_resource.AddFileDependenciesTo(Resource::ParentFileDependencies);
|
|
}
|
|
|
|
//
|
|
//------------------------------------------------------------------
|
|
// It is not up to date, so create stream to write the contents into
|
|
//------------------------------------------------------------------
|
|
//
|
|
else
|
|
{
|
|
Tool::Instance->PushFilePath(&lights_file);
|
|
DynamicMemoryStream light_stream;
|
|
|
|
//
|
|
//----------------------------------------------------
|
|
// Read each light in and write it out into the binary
|
|
//----------------------------------------------------
|
|
//
|
|
MidLevelRenderer::WriteMLRVersion(&light_stream);
|
|
NotationFile::PageIterator *pages = lights_file.MakePageIterator();
|
|
Check_Object(pages);
|
|
Page *light_page;
|
|
while ((light_page = pages->ReadAndNext()) != NULL)
|
|
{
|
|
Check_Object(light_page);
|
|
MidLevelRenderer::MLRLight* light =
|
|
MidLevelRenderer::MLRLight::Make(light_page);
|
|
Check_Object(light);
|
|
light->Save(&light_stream);
|
|
delete light;
|
|
}
|
|
|
|
//
|
|
//-----------------------------------------
|
|
// Only save out the stream if there is one
|
|
//-----------------------------------------
|
|
//
|
|
if (light_stream.GetBytesUsed() > sizeof(WORD))
|
|
{
|
|
light_stream.Rewind();
|
|
light_resource.Save(&light_stream, lights_file.GetFileDependencies());
|
|
if (!light_resource.IsRegistered())
|
|
light_resource.AddFileDependenciesTo(Resource::ParentFileDependencies);
|
|
Check_Object(&light_resource);
|
|
model->m_nightLightStreamResourceID = light_resource.GetResourceID();
|
|
}
|
|
else
|
|
{
|
|
model->m_nightLightStreamResourceID = ResourceID::Null;
|
|
if (!light_resource.IsRegistered())
|
|
Resource::ParentFileDependencies->AddDependencies(lights_file.GetFileDependencies());
|
|
}
|
|
|
|
//
|
|
//------------------------
|
|
// Clean up the tool stack
|
|
//------------------------
|
|
//
|
|
Check_Object(pages);
|
|
delete pages;
|
|
Tool::Instance->PopFilePath();
|
|
}
|
|
}
|
|
}
|
|
|
|
Tool::Instance->PopFilePath();
|
|
Verify(stack_index == Tool::Instance->GetStackLevel());
|
|
}
|
|
|
|
|
|
//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
|
|
//
|
|
void
|
|
Mission__GameModel::SaveGameModel(
|
|
Mission__GameModel *model,
|
|
Stuff::NotationFile *data_file
|
|
)
|
|
{
|
|
Check_Object(model);
|
|
Check_Object(data_file);
|
|
|
|
Entity__GameModel::SaveGameModel(model, data_file);
|
|
Page *page = data_file->GetPage("GameData");
|
|
|
|
//Save lights file name
|
|
if(model->m_lightStreamResourceID != ResourceID::Null)
|
|
{
|
|
Resource light_resource(model->m_lightStreamResourceID);
|
|
Verify(light_resource.DoesResourceExist());
|
|
|
|
page->SetEntry("Lights", light_resource.GetName());
|
|
}
|
|
|
|
if(model->m_nightLightStreamResourceID != ResourceID::Null)
|
|
{
|
|
Resource light_resource(model->m_nightLightStreamResourceID);
|
|
Verify(light_resource.DoesResourceExist());
|
|
|
|
page->SetEntry("NightLights", light_resource.GetName());
|
|
}
|
|
}
|
|
|
|
//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
|
|
//
|
|
bool
|
|
Mission__GameModel::ReadAndVerify(
|
|
Mission__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 GeneralFogStartAttributeID:
|
|
{
|
|
if(!valid_data)
|
|
{
|
|
Scalar value = 100.0f;
|
|
attribute_entry->SetValue(model, &value);
|
|
result = true;
|
|
}
|
|
if(model->m_generalFogStart < 0.0f)
|
|
{
|
|
_snprintf(
|
|
*error,
|
|
error_buffer,
|
|
"{[GameData]GeneralFogStart=%f}: value must be >= 0!",
|
|
model->m_generalFogStart
|
|
);
|
|
result = false;
|
|
}
|
|
break;
|
|
}
|
|
case GeneralFogEndAttributeID:
|
|
{
|
|
if(!valid_data)
|
|
{
|
|
Scalar value = 1000.0f;
|
|
attribute_entry->SetValue(model, &value);
|
|
result = true;
|
|
}
|
|
if(model->m_generalFogEnd <= model->m_generalFogStart)
|
|
{
|
|
_snprintf(
|
|
*error,
|
|
error_buffer,
|
|
"{[GameData]GeneralFogEnd=%f}: value must be > GeneralFogStart!",
|
|
model->m_generalFogEnd
|
|
);
|
|
result = false;
|
|
}
|
|
break;
|
|
}
|
|
case GeneralFogDensityAttributeID:
|
|
{
|
|
if(!valid_data)
|
|
{
|
|
Scalar value = 0.0f;
|
|
attribute_entry->SetValue(model, &value);
|
|
result = true;
|
|
}
|
|
if(model->m_generalFogDensity < 0.0f || model->m_generalFogDensity > 2.0f)
|
|
{
|
|
_snprintf(
|
|
*error,
|
|
error_buffer,
|
|
"{[GameData]LightFogDensity=%f}: value must be between 0 and 2!",
|
|
model->m_generalFogDensity
|
|
);
|
|
result = false;
|
|
}
|
|
break;
|
|
}
|
|
case LightFogStartAttributeID:
|
|
{
|
|
if(!valid_data)
|
|
{
|
|
Scalar value = 100.0f;
|
|
attribute_entry->SetValue(model, &value);
|
|
result = true;
|
|
}
|
|
if(model->m_lightFogStart < 0.0f)
|
|
{
|
|
_snprintf(
|
|
*error,
|
|
error_buffer,
|
|
"{[GameData]GeneralFogStart=%f}: value must be >= 0!",
|
|
model->m_lightFogStart
|
|
);
|
|
result = false;
|
|
}
|
|
break;
|
|
}
|
|
case LightFogEndAttributeID:
|
|
{
|
|
if(!valid_data)
|
|
{
|
|
Scalar value = 1000.0f;
|
|
attribute_entry->SetValue(model, &value);
|
|
result = true;
|
|
}
|
|
if(model->m_lightFogEnd <= model->m_lightFogStart)
|
|
{
|
|
_snprintf(
|
|
*error,
|
|
error_buffer,
|
|
"{[GameData]LightFogEnd=%f}: value must be > LightFogStart!",
|
|
model->m_lightFogEnd
|
|
);
|
|
result = false;
|
|
}
|
|
break;
|
|
}
|
|
case LightFogDensityAttributeID:
|
|
{
|
|
if(!valid_data)
|
|
{
|
|
Scalar value = 1.0f;
|
|
attribute_entry->SetValue(model, &value);
|
|
result = true;
|
|
}
|
|
if(model->m_lightFogDensity < 0.0f || model->m_lightFogDensity > 2.0f)
|
|
{
|
|
_snprintf(
|
|
*error,
|
|
error_buffer,
|
|
"{[GameData]LightFogDensity=%f}: value must be between 0 and 2!",
|
|
model->m_lightFogDensity
|
|
);
|
|
result = false;
|
|
}
|
|
break;
|
|
}
|
|
case CustomFogStartAttributeID:
|
|
{
|
|
if(!valid_data)
|
|
{
|
|
Scalar value = 100.0f;
|
|
attribute_entry->SetValue(model, &value);
|
|
result = true;
|
|
}
|
|
if(model->m_customFogStart < 0.0f)
|
|
{
|
|
_snprintf(
|
|
*error,
|
|
error_buffer,
|
|
"{[GameData]CustomFogStart=%f}: value must be >= 0!",
|
|
model->m_customFogStart
|
|
);
|
|
result = false;
|
|
}
|
|
break;
|
|
}
|
|
case CustomFogEndAttributeID:
|
|
{
|
|
if(!valid_data)
|
|
{
|
|
Scalar value = 1000.0f;
|
|
attribute_entry->SetValue(model, &value);
|
|
result = true;
|
|
}
|
|
if(model->m_customFogEnd <= model->m_customFogStart)
|
|
{
|
|
_snprintf(
|
|
*error,
|
|
error_buffer,
|
|
"{[GameData]CustomFogEnd=%f}: value must be > CustomFogStart!",
|
|
model->m_customFogEnd
|
|
);
|
|
result = false;
|
|
}
|
|
break;
|
|
}
|
|
case CustomFogDensityAttributeID:
|
|
{
|
|
if(!valid_data)
|
|
{
|
|
Scalar value = 1.0f;
|
|
attribute_entry->SetValue(model, &value);
|
|
result = true;
|
|
}
|
|
if(model->m_customFogDensity < 0.0f || model->m_customFogDensity > 2.0f)
|
|
{
|
|
_snprintf(
|
|
*error,
|
|
error_buffer,
|
|
"{[GameData]CustomFogDensity=%f}: value must be between 0 and 2!",
|
|
model->m_customFogDensity
|
|
);
|
|
result = false;
|
|
}
|
|
break;
|
|
}
|
|
|
|
case GeneralFogStartUnderwaterAttributeID:
|
|
{
|
|
if(!valid_data)
|
|
{
|
|
Scalar value = 100.0f;
|
|
attribute_entry->SetValue(model, &value);
|
|
result = true;
|
|
}
|
|
if(model->m_generalFogStartUnderwater < 0.0f)
|
|
{
|
|
_snprintf(
|
|
*error,
|
|
error_buffer,
|
|
"{[GameData]GeneralFogStartUnderwater=%f}: value must be >= 0!",
|
|
model->m_generalFogStartUnderwater
|
|
);
|
|
result = false;
|
|
}
|
|
break;
|
|
}
|
|
case GeneralFogEndUnderwaterAttributeID:
|
|
{
|
|
if(!valid_data)
|
|
{
|
|
Scalar value = 1000.0f;
|
|
attribute_entry->SetValue(model, &value);
|
|
result = true;
|
|
}
|
|
if(model->m_generalFogEndUnderwater <= model->m_generalFogStartUnderwater)
|
|
{
|
|
_snprintf(
|
|
*error,
|
|
error_buffer,
|
|
"{[GameData]GeneralFogEndUnderwater=%f}: value must be > GeneralFogStartUnderwater!",
|
|
model->m_generalFogEndUnderwater
|
|
);
|
|
result = false;
|
|
}
|
|
break;
|
|
}
|
|
case GeneralFogDensityUnderwaterAttributeID:
|
|
{
|
|
if(!valid_data)
|
|
{
|
|
Scalar value = 0.0f;
|
|
attribute_entry->SetValue(model, &value);
|
|
result = true;
|
|
}
|
|
if(model->m_generalFogDensityUnderwater < 0.0f || model->m_generalFogDensityUnderwater > 2.0f)
|
|
{
|
|
_snprintf(
|
|
*error,
|
|
error_buffer,
|
|
"{[GameData]LightFogDensityUnderwater=%f}: value must be between 0 and 2!",
|
|
model->m_generalFogDensityUnderwater
|
|
);
|
|
result = false;
|
|
}
|
|
break;
|
|
}
|
|
case LightFogStartUnderwaterAttributeID:
|
|
{
|
|
if(!valid_data)
|
|
{
|
|
Scalar value = 100.0f;
|
|
attribute_entry->SetValue(model, &value);
|
|
result = true;
|
|
}
|
|
if(model->m_lightFogStartUnderwater < 0.0f)
|
|
{
|
|
_snprintf(
|
|
*error,
|
|
error_buffer,
|
|
"{[GameData]GeneralFogStartUnderwater=%f}: value must be >= 0!",
|
|
model->m_lightFogStartUnderwater
|
|
);
|
|
result = false;
|
|
}
|
|
break;
|
|
}
|
|
case LightFogEndUnderwaterAttributeID:
|
|
{
|
|
if(!valid_data)
|
|
{
|
|
Scalar value = 1000.0f;
|
|
attribute_entry->SetValue(model, &value);
|
|
result = true;
|
|
}
|
|
if(model->m_lightFogEndUnderwater <= model->m_lightFogStartUnderwater)
|
|
{
|
|
_snprintf(
|
|
*error,
|
|
error_buffer,
|
|
"{[GameData]LightFogEndUnderwater=%f}: value must be > LightFogStartUnderwater!",
|
|
model->m_lightFogEndUnderwater
|
|
);
|
|
result = false;
|
|
}
|
|
break;
|
|
}
|
|
case LightFogDensityUnderwaterAttributeID:
|
|
{
|
|
if(!valid_data)
|
|
{
|
|
Scalar value = 1.0f;
|
|
attribute_entry->SetValue(model, &value);
|
|
result = true;
|
|
}
|
|
if(model->m_lightFogDensityUnderwater < 0.0f || model->m_lightFogDensityUnderwater > 2.0f)
|
|
{
|
|
_snprintf(
|
|
*error,
|
|
error_buffer,
|
|
"{[GameData]LightFogDensityUnderwater=%f}: value must be between 0 and 2!",
|
|
model->m_lightFogDensityUnderwater
|
|
);
|
|
result = false;
|
|
}
|
|
break;
|
|
}
|
|
case CustomFogStartUnderwaterAttributeID:
|
|
{
|
|
if(!valid_data)
|
|
{
|
|
Scalar value = 100.0f;
|
|
attribute_entry->SetValue(model, &value);
|
|
result = true;
|
|
}
|
|
if(model->m_customFogStartUnderwater < 0.0f)
|
|
{
|
|
_snprintf(
|
|
*error,
|
|
error_buffer,
|
|
"{[GameData]CustomFogStartUnderwater=%f}: value must be >= 0!",
|
|
model->m_customFogStartUnderwater
|
|
);
|
|
result = false;
|
|
}
|
|
break;
|
|
}
|
|
case CustomFogEndUnderwaterAttributeID:
|
|
{
|
|
if(!valid_data)
|
|
{
|
|
Scalar value = 1000.0f;
|
|
attribute_entry->SetValue(model, &value);
|
|
result = true;
|
|
}
|
|
if(model->m_customFogEndUnderwater <= model->m_customFogStartUnderwater)
|
|
{
|
|
_snprintf(
|
|
*error,
|
|
error_buffer,
|
|
"{[GameData]CustomFogEndUnderwater=%f}: value must be > CustomFogStartUnderwater!",
|
|
model->m_customFogEndUnderwater
|
|
);
|
|
result = false;
|
|
}
|
|
break;
|
|
}
|
|
case CustomFogDensityUnderwaterAttributeID:
|
|
{
|
|
if(!valid_data)
|
|
{
|
|
Scalar value = 1.0f;
|
|
attribute_entry->SetValue(model, &value);
|
|
result = true;
|
|
}
|
|
if(model->m_customFogDensityUnderwater < 0.0f || model->m_customFogDensityUnderwater > 2.0f)
|
|
{
|
|
_snprintf(
|
|
*error,
|
|
error_buffer,
|
|
"{[GameData]CustomFogDensityUnderwater=%f}: value must be between 0 and 2!",
|
|
model->m_customFogDensityUnderwater
|
|
);
|
|
result = false;
|
|
}
|
|
break;
|
|
}
|
|
|
|
case GeneralFogStartSmokeAttributeID:
|
|
{
|
|
if(!valid_data)
|
|
{
|
|
Scalar value = 100.0f;
|
|
attribute_entry->SetValue(model, &value);
|
|
result = true;
|
|
}
|
|
if(model->m_generalFogStartSmoke < 0.0f)
|
|
{
|
|
_snprintf(
|
|
*error,
|
|
error_buffer,
|
|
"{[GameData]GeneralFogStartSmoke=%f}: value must be >= 0!",
|
|
model->m_generalFogStartSmoke
|
|
);
|
|
result = false;
|
|
}
|
|
break;
|
|
}
|
|
case GeneralFogEndSmokeAttributeID:
|
|
{
|
|
if(!valid_data)
|
|
{
|
|
Scalar value = 1000.0f;
|
|
attribute_entry->SetValue(model, &value);
|
|
result = true;
|
|
}
|
|
if(model->m_generalFogEndSmoke <= model->m_generalFogStartSmoke)
|
|
{
|
|
_snprintf(
|
|
*error,
|
|
error_buffer,
|
|
"{[GameData]GeneralFogEndSmoke=%f}: value must be > GeneralFogStartSmoke!",
|
|
model->m_generalFogEndSmoke
|
|
);
|
|
result = false;
|
|
}
|
|
break;
|
|
}
|
|
case GeneralFogDensitySmokeAttributeID:
|
|
{
|
|
if(!valid_data)
|
|
{
|
|
Scalar value = 0.0f;
|
|
attribute_entry->SetValue(model, &value);
|
|
result = true;
|
|
}
|
|
if(model->m_generalFogDensitySmoke < 0.0f || model->m_generalFogDensitySmoke > 2.0f)
|
|
{
|
|
_snprintf(
|
|
*error,
|
|
error_buffer,
|
|
"{[GameData]LightFogDensitySmoke=%f}: value must be between 0 and 2!",
|
|
model->m_generalFogDensitySmoke
|
|
);
|
|
result = false;
|
|
}
|
|
break;
|
|
}
|
|
case LightFogStartSmokeAttributeID:
|
|
{
|
|
if(!valid_data)
|
|
{
|
|
Scalar value = 100.0f;
|
|
attribute_entry->SetValue(model, &value);
|
|
result = true;
|
|
}
|
|
if(model->m_lightFogStartSmoke < 0.0f)
|
|
{
|
|
_snprintf(
|
|
*error,
|
|
error_buffer,
|
|
"{[GameData]GeneralFogStartSmoke=%f}: value must be >= 0!",
|
|
model->m_lightFogStartSmoke
|
|
);
|
|
result = false;
|
|
}
|
|
break;
|
|
}
|
|
case LightFogEndSmokeAttributeID:
|
|
{
|
|
if(!valid_data)
|
|
{
|
|
Scalar value = 1000.0f;
|
|
attribute_entry->SetValue(model, &value);
|
|
result = true;
|
|
}
|
|
if(model->m_lightFogEndSmoke <= model->m_lightFogStartSmoke)
|
|
{
|
|
_snprintf(
|
|
*error,
|
|
error_buffer,
|
|
"{[GameData]LightFogEndSmoke=%f}: value must be > LightFogStartSmoke!",
|
|
model->m_lightFogEndSmoke
|
|
);
|
|
result = false;
|
|
}
|
|
break;
|
|
}
|
|
case LightFogDensitySmokeAttributeID:
|
|
{
|
|
if(!valid_data)
|
|
{
|
|
Scalar value = 1.0f;
|
|
attribute_entry->SetValue(model, &value);
|
|
result = true;
|
|
}
|
|
if(model->m_lightFogDensitySmoke < 0.0f || model->m_lightFogDensitySmoke > 2.0f)
|
|
{
|
|
_snprintf(
|
|
*error,
|
|
error_buffer,
|
|
"{[GameData]LightFogDensitySmoke=%f}: value must be between 0 and 2!",
|
|
model->m_lightFogDensitySmoke
|
|
);
|
|
result = false;
|
|
}
|
|
break;
|
|
}
|
|
case CustomFogStartSmokeAttributeID:
|
|
{
|
|
if(!valid_data)
|
|
{
|
|
Scalar value = 100.0f;
|
|
attribute_entry->SetValue(model, &value);
|
|
result = true;
|
|
}
|
|
if(model->m_customFogStartSmoke < 0.0f)
|
|
{
|
|
_snprintf(
|
|
*error,
|
|
error_buffer,
|
|
"{[GameData]CustomFogStartSmoke=%f}: value must be >= 0!",
|
|
model->m_customFogStartSmoke
|
|
);
|
|
result = false;
|
|
}
|
|
break;
|
|
}
|
|
case CustomFogEndSmokeAttributeID:
|
|
{
|
|
if(!valid_data)
|
|
{
|
|
Scalar value = 1000.0f;
|
|
attribute_entry->SetValue(model, &value);
|
|
result = true;
|
|
}
|
|
if(model->m_customFogEndSmoke <= model->m_customFogStartSmoke)
|
|
{
|
|
_snprintf(
|
|
*error,
|
|
error_buffer,
|
|
"{[GameData]CustomFogEndSmoke=%f}: value must be > CustomFogStartSmoke!",
|
|
model->m_customFogEndSmoke
|
|
);
|
|
result = false;
|
|
}
|
|
break;
|
|
}
|
|
case CustomFogDensitySmokeAttributeID:
|
|
{
|
|
if(!valid_data)
|
|
{
|
|
Scalar value = 1.0f;
|
|
attribute_entry->SetValue(model, &value);
|
|
result = true;
|
|
}
|
|
if(model->m_customFogDensitySmoke < 0.0f || model->m_customFogDensitySmoke > 2.0f)
|
|
{
|
|
_snprintf(
|
|
*error,
|
|
error_buffer,
|
|
"{[GameData]CustomFogDensitySmoke=%f}: value must be between 0 and 2!",
|
|
model->m_customFogDensitySmoke
|
|
);
|
|
result = false;
|
|
}
|
|
break;
|
|
}
|
|
|
|
case HeightFogStartAttributeID:
|
|
{
|
|
if(!valid_data)
|
|
{
|
|
Scalar value = 0.0f;
|
|
attribute_entry->SetValue(model, &value);
|
|
result = true;
|
|
}
|
|
if(model->m_heightFogStart < 0.0f)
|
|
{
|
|
_snprintf(
|
|
*error,
|
|
error_buffer,
|
|
"{[GameData]HeightFogStart=%f}: value must be >= 0!",
|
|
model->m_heightFogStart
|
|
);
|
|
result = false;
|
|
}
|
|
break;
|
|
}
|
|
case HeightFogEndAttributeID:
|
|
{
|
|
if(!valid_data)
|
|
{
|
|
Scalar value = 1.0f;
|
|
attribute_entry->SetValue(model, &value);
|
|
result = true;
|
|
}
|
|
if(model->m_heightFogEnd <= model->m_heightFogStart)
|
|
{
|
|
_snprintf(
|
|
*error,
|
|
error_buffer,
|
|
"{[GameData]HeightFogEnd=%f}: value must be > HeightFogStart!",
|
|
model->m_heightFogEnd
|
|
);
|
|
result = false;
|
|
}
|
|
break;
|
|
}
|
|
case HeightFogOpacityAttributeID:
|
|
{
|
|
if(!valid_data)
|
|
{
|
|
Scalar value = 0.0f;
|
|
attribute_entry->SetValue(model, &value);
|
|
result = true;
|
|
}
|
|
if(model->m_heightFogOpacity < 0.0f || model->m_heightFogOpacity > 1.0f)
|
|
{
|
|
_snprintf(
|
|
*error,
|
|
error_buffer,
|
|
"{[GameData]HeightFogOpacity=%f}: value must be between 0 and 1!",
|
|
model->m_heightFogOpacity
|
|
);
|
|
result = false;
|
|
}
|
|
break;
|
|
}
|
|
case FogColorAttributeID:
|
|
{
|
|
if(!valid_data)
|
|
{
|
|
RGBAColor value;
|
|
value.red = 0.0f;
|
|
value.green = 0.0f;
|
|
value.blue = 0.0f;
|
|
value.alpha = 1.0f;
|
|
attribute_entry->SetValue(model, &value);
|
|
result = true;
|
|
}
|
|
break;
|
|
}
|
|
case FogColorUnderwaterAttributeID:
|
|
{
|
|
if(!valid_data)
|
|
{
|
|
RGBAColor value;
|
|
value.red = 0.0f;
|
|
value.green = 0.0f;
|
|
value.blue = 0.0f;
|
|
value.alpha = 1.0f;
|
|
attribute_entry->SetValue(model, &value);
|
|
result = true;
|
|
}
|
|
break;
|
|
}
|
|
case FogColorSmokeAttributeID:
|
|
{
|
|
if(!valid_data)
|
|
{
|
|
RGBAColor value;
|
|
value.red = 0.0f;
|
|
value.green = 0.0f;
|
|
value.blue = 0.0f;
|
|
value.alpha = 1.0f;
|
|
attribute_entry->SetValue(model, &value);
|
|
result = true;
|
|
}
|
|
break;
|
|
}
|
|
case AllowRespawnAttributeID:
|
|
{
|
|
if (!valid_data)
|
|
{
|
|
bool value = false;
|
|
attribute_entry->SetValue(model, &value);
|
|
result = true;
|
|
}
|
|
break;
|
|
}
|
|
case AllowSearchLightsAttributeID:
|
|
{
|
|
if (!valid_data)
|
|
{
|
|
bool value = true;
|
|
attribute_entry->SetValue(model, &value);
|
|
result = true;
|
|
}
|
|
break;
|
|
}
|
|
case AllowRunningLightsAttributeID:
|
|
{
|
|
if (!valid_data)
|
|
{
|
|
bool value = true;
|
|
attribute_entry->SetValue(model, &value);
|
|
result = true;
|
|
}
|
|
break;
|
|
}
|
|
case IsNightMissionAttributeID:
|
|
{
|
|
if (!valid_data)
|
|
{
|
|
bool value = false;
|
|
attribute_entry->SetValue(model, &value);
|
|
result = true;
|
|
}
|
|
break;
|
|
}
|
|
case WeatherEffectResourceAttributeID:
|
|
{
|
|
if(!valid_data)
|
|
{
|
|
ResourceID value = ResourceID::Null;
|
|
attribute_entry->SetValue(model, (void *)&value);
|
|
result = true;
|
|
}
|
|
break;
|
|
}
|
|
case NearClipAttributeID:
|
|
{
|
|
if(!valid_data)
|
|
{
|
|
Scalar value = 1.0f;
|
|
attribute_entry->SetValue(model, &value);
|
|
result = true;
|
|
}
|
|
if(model->m_nearClip < 0.1f)
|
|
{
|
|
_snprintf(
|
|
*error,
|
|
error_buffer,
|
|
"{[GameData]NearClip=%f}: value must be greater than 0.1!",
|
|
model->m_nearClip
|
|
);
|
|
result = false;
|
|
}
|
|
break;
|
|
}
|
|
case FarClipAttributeID:
|
|
{
|
|
if(!valid_data)
|
|
{
|
|
Scalar value = 1000.0f;
|
|
attribute_entry->SetValue(model, &value);
|
|
result = true;
|
|
}
|
|
if(model->m_farClip <= model->m_nearClip)
|
|
{
|
|
_snprintf(
|
|
*error,
|
|
error_buffer,
|
|
"{[GameData]FarClip=%f}: value must be greater than NearClip!",
|
|
model->m_farClip
|
|
);
|
|
result = false;
|
|
}
|
|
break;
|
|
}
|
|
case CanSetTimeAttributeID:
|
|
{
|
|
if (!valid_data)
|
|
{
|
|
bool value = true;
|
|
attribute_entry->SetValue(model, &value);
|
|
result = true;
|
|
}
|
|
break;
|
|
}
|
|
case NightGroundColorAttributeID:
|
|
{
|
|
if(!valid_data)
|
|
{
|
|
RGBAColor value;
|
|
value.red = 0.2f;
|
|
value.green = 0.2f;
|
|
value.blue = 0.2f;
|
|
value.alpha = 1.0f;
|
|
attribute_entry->SetValue(model, &value);
|
|
result = true;
|
|
}
|
|
break;
|
|
}
|
|
case NightFogColorAttributeID:
|
|
{
|
|
if(!valid_data)
|
|
{
|
|
RGBAColor value;
|
|
value.red = 0.0f;
|
|
value.green = 0.0f;
|
|
value.blue = 0.0f;
|
|
value.alpha = 1.0f;
|
|
attribute_entry->SetValue(model, &value);
|
|
result = true;
|
|
}
|
|
break;
|
|
}
|
|
case HeatSinkEfficiencyAttributeID:
|
|
{
|
|
if(!valid_data)
|
|
{
|
|
Scalar value = 1.0f;
|
|
attribute_entry->SetValue(model, &value);
|
|
result = true;
|
|
}
|
|
if(model->m_heatSinkEfficiency < 0.0f)
|
|
{
|
|
_snprintf(
|
|
*error,
|
|
error_buffer,
|
|
"{[GameData]HeatSinkEfficiency=%f}: value must be >= 0",
|
|
model->m_heatSinkEfficiency
|
|
);
|
|
result = false;
|
|
}
|
|
break;
|
|
}
|
|
case NightWeatherEffectResourceAttributeID:
|
|
{
|
|
if(!valid_data)
|
|
{
|
|
ResourceID value = ResourceID::Null;
|
|
attribute_entry->SetValue(model, (void *)&value);
|
|
result = true;
|
|
}
|
|
break;
|
|
}
|
|
case WaterSpecularFactorAttributeID:
|
|
{
|
|
if(!valid_data)
|
|
{
|
|
Scalar value = 345.0f;
|
|
attribute_entry->SetValue(model, (void *)&value);
|
|
result = true;
|
|
}
|
|
break;
|
|
}
|
|
case WaterAtNightSpecularFactorAttributeID:
|
|
{
|
|
if(!valid_data)
|
|
{
|
|
Scalar value = 345.0f;
|
|
attribute_entry->SetValue(model, (void *)&value);
|
|
result = true;
|
|
}
|
|
break;
|
|
}
|
|
case WaterSpecularPowerAttributeID:
|
|
{
|
|
if(!valid_data)
|
|
{
|
|
int value = 32;
|
|
attribute_entry->SetValue(model, (void *)&value);
|
|
result = true;
|
|
}
|
|
break;
|
|
}
|
|
case WaterAtNightSpecularPowerAttributeID:
|
|
{
|
|
if(!valid_data)
|
|
{
|
|
int value = 32;
|
|
attribute_entry->SetValue(model, (void *)&value);
|
|
result = true;
|
|
}
|
|
break;
|
|
}
|
|
}
|
|
return result;
|
|
} |