Imports the current Win32 source for the pod-racing game 'Red Planet', built on the MUNGA engine and its L4 (Win32/DirectX) platform layer: - MUNGA / MUNGA_L4: cross-platform engine core and Win32 backend - RP / RP_L4: Red Planet game logic and Win32 application - DivLoader, Setup1: asset loader and installer project - lib, MUNGA_L4/openal, MUNGA_L4/sos: third-party audio dependencies Removed stale Subversion metadata and added .gitignore/.gitattributes. Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
1074 lines
24 KiB
C++
1074 lines
24 KiB
C++
#include "munga.h"
|
|
#pragma hdrstop
|
|
|
|
#include "cultural.h"
|
|
#include "terrain.h"
|
|
#include "fileutil.h"
|
|
#include "boxtree.h"
|
|
#include "boxsolid.h"
|
|
#include "scnrole.h"
|
|
#include "mission.h"
|
|
#include "explode.h"
|
|
#include "app.h"
|
|
#include "interest.h"
|
|
#include "hostmgr.h"
|
|
#include "nttmgr.h"
|
|
#include "namelist.h"
|
|
#include "console.h"
|
|
|
|
//##########################################################################
|
|
//##################### Class CulturalIcon ##########################
|
|
//##########################################################################
|
|
|
|
//#############################################################################
|
|
// Shared Data Support
|
|
//
|
|
Derivation* CulturalIcon::GetClassDerivations()
|
|
{ static Derivation classDerivations(UnscalableTerrain::GetClassDerivations(), "CulturalIcon");
|
|
return &classDerivations;
|
|
}
|
|
|
|
|
|
CulturalIcon::SharedData
|
|
CulturalIcon::DefaultData(
|
|
CulturalIcon::GetClassDerivations(),
|
|
CulturalIcon::GetMessageHandlers(),
|
|
CulturalIcon::GetAttributeIndex(),
|
|
CulturalIcon::StateCount,
|
|
(UnscalableTerrain::MakeHandler)CulturalIcon::Make
|
|
);
|
|
//#############################################################################
|
|
// Message Support
|
|
//
|
|
const Receiver::HandlerEntry
|
|
CulturalIcon::MessageHandlerEntries[]=
|
|
{
|
|
MESSAGE_ENTRY(CulturalIcon, TakeDamage),
|
|
MESSAGE_ENTRY(CulturalIcon, SetBurningState)
|
|
};
|
|
|
|
CulturalIcon::MessageHandlerSet& CulturalIcon::GetMessageHandlers()
|
|
{
|
|
static CulturalIcon::MessageHandlerSet messageHandlers(ELEMENTS(CulturalIcon::MessageHandlerEntries), CulturalIcon::MessageHandlerEntries, UnscalableTerrain::GetMessageHandlers());
|
|
return messageHandlers;
|
|
}
|
|
|
|
//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
|
|
//
|
|
|
|
|
|
void
|
|
CulturalIcon::SetBurningStateMessageHandler(Message * /*burning_message*/)
|
|
{
|
|
|
|
SetSimulationState(CulturalIcon::BurningState);
|
|
ForceUpdate(DefaultUpdateModelFlag);
|
|
AlwaysExecute();
|
|
|
|
}
|
|
//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
|
|
//
|
|
void
|
|
CulturalIcon::TakeDamageMessageHandler(TakeDamageMessage *damage_message)
|
|
{
|
|
Check(damage_message);
|
|
|
|
|
|
if (damage_message->damageZone == -1 )
|
|
{
|
|
damage_message->damageZone = 0;
|
|
}
|
|
|
|
if (GetSimulationState() == CulturalIcon::DefaultState)
|
|
{
|
|
//
|
|
//~~~~~~~~~~~~~~~~~~
|
|
// Update Replicants
|
|
//~~~~~~~~~~~~~~~~~~
|
|
//
|
|
if (GetInstance() != ReplicantInstance)
|
|
{
|
|
ForceUpdate(DamageZoneUpdateModelFlag | DefaultUpdateModelFlag);
|
|
AlwaysExecute();
|
|
}
|
|
//
|
|
//~~~~~~~~~~~~~~~~~~~~~
|
|
// Call Derived Classes
|
|
//~~~~~~~~~~~~~~~~~~~~~
|
|
//
|
|
UnscalableTerrain::TakeDamageMessageHandler(damage_message);
|
|
|
|
//
|
|
//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
|
|
// Update Collision Volumes if we died
|
|
//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
|
|
//
|
|
|
|
for(int ii=0;ii<damageZoneCount;++ii)
|
|
{
|
|
if(damageZones[ii]->GetDamageZoneState() == DamageZone::BurningState)
|
|
{
|
|
//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
|
|
// Create the explosion
|
|
//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
|
|
//
|
|
Origin explode_origin = localOrigin;
|
|
|
|
ResourceDescription::ResourceID explosion_ID;
|
|
|
|
if ((damage_message->damageData.damageType == Damage::CollisionDamageType )&&
|
|
(crunchExplosionResourceID != -1))
|
|
{
|
|
explosion_ID = crunchExplosionResourceID;
|
|
}
|
|
else
|
|
{
|
|
explosion_ID = explosionResourceID;
|
|
}
|
|
|
|
Explosion::MakeMessage exp_message(
|
|
Explosion::MakeMessageID,
|
|
sizeof(Explosion::MakeMessage),
|
|
RegisteredClass::ExplosionClassID,
|
|
EntityID::Null,
|
|
explosion_ID,
|
|
Explosion::DefaultFlags,
|
|
explode_origin,
|
|
GetEntityID(),
|
|
GetEntityID()
|
|
);
|
|
|
|
#if (DEBUG_LEVEL > 0)
|
|
Explosion *new_exp =
|
|
#endif
|
|
Explosion::Make(&exp_message);
|
|
Register_Object(new_exp);
|
|
|
|
Message dummy_message(SetBurningStateMessageID, sizeof(Message));
|
|
Check(application);
|
|
Time now = Now();
|
|
now += timeDelay;
|
|
application->Post(CreationEventPriority, this, &dummy_message, now);
|
|
|
|
SetSimulationState(WaitingToBurn);
|
|
|
|
UpdateCollisionVolumes();
|
|
break;
|
|
}
|
|
}
|
|
}
|
|
Check_Fpu();
|
|
}
|
|
|
|
|
|
|
|
|
|
//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
|
|
//
|
|
void
|
|
CulturalIcon::UpdateCollisionVolumes()
|
|
{
|
|
Check(this);
|
|
//
|
|
//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
|
|
// Get the Tree for these Collision Volumes
|
|
//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
|
|
//
|
|
InterestManager *interest_mgr =
|
|
application->GetInterestManager();
|
|
Check(interest_mgr);
|
|
InterestZone *zone =
|
|
interest_mgr->GetInterestZone(interestZoneID);
|
|
Check(zone);
|
|
BoxedSolidTree* tree = zone->GetCollisionRoot();
|
|
Check(tree);
|
|
//
|
|
//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
|
|
// Update Volumes based on RemoveVolume Flag
|
|
//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
|
|
//
|
|
BoxedSolid *box = collisionVolumes;
|
|
while (box)
|
|
{
|
|
BoxedSolid *next_box = box->GetNextSolid();
|
|
if (RemoveCollisionVolumeOnDeath())
|
|
{
|
|
//
|
|
//~~~~~~~~~~~~~~~~~~~~~~~~~~~~
|
|
// Delete the Collision Volume
|
|
//~~~~~~~~~~~~~~~~~~~~~~~~~~~~
|
|
//
|
|
tree->Remove(box);
|
|
Unregister_Object(box);
|
|
delete box;
|
|
}
|
|
else
|
|
{
|
|
//
|
|
//~~~~~~~~~~~~~~~~~~~~~~
|
|
// Move Collision Volume
|
|
//~~~~~~~~~~~~~~~~~~~~~~
|
|
//
|
|
box->minY += destroyedYTranslation;
|
|
box->maxY += destroyedYTranslation;
|
|
}
|
|
box = next_box;
|
|
}
|
|
collisionVolumes = NULL;
|
|
Check_Fpu();
|
|
}
|
|
|
|
//#############################################################################
|
|
// Attribute Support
|
|
//
|
|
const CulturalIcon::IndexEntry
|
|
CulturalIcon::AttributePointers[]=
|
|
{
|
|
ATTRIBUTE_ENTRY(CulturalIcon, TeamName, teamName)
|
|
};
|
|
|
|
CulturalIcon::AttributeIndexSet& CulturalIcon::GetAttributeIndex()
|
|
{
|
|
static CulturalIcon::AttributeIndexSet attributeIndex(ELEMENTS(CulturalIcon::AttributePointers),
|
|
CulturalIcon::AttributePointers,
|
|
UnscalableTerrain::GetAttributeIndex()
|
|
);
|
|
return attributeIndex;
|
|
}
|
|
//#############################################################################
|
|
// Construction and Destruction
|
|
//
|
|
|
|
//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
|
|
//
|
|
CulturalIcon::CulturalIcon(
|
|
MakeMessage *creation_message,
|
|
SharedData &shared_data
|
|
) :
|
|
UnscalableTerrain(creation_message, shared_data)
|
|
{
|
|
|
|
Str_Copy(teamName, "Defualt", sizeof(teamName));
|
|
//
|
|
//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
|
|
// Read in the ModelResource Information
|
|
//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
|
|
//
|
|
ResourceDescription *res =
|
|
application->GetResourceFile()->SearchList(
|
|
resourceID,
|
|
ResourceDescription::GameModelResourceType
|
|
);
|
|
Check(res);
|
|
res->Lock();
|
|
ModelResource* model_resource = (ModelResource*)res->resourceAddress;
|
|
Check_Pointer(model_resource);
|
|
//
|
|
//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
|
|
// Determine if we move or Destroy the
|
|
// Collision volume in Death of the map entity
|
|
//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
|
|
//
|
|
if (model_resource->sinkCollisionVolume)
|
|
{
|
|
destroyedYTranslation = model_resource->destroyedYTranslation;
|
|
}
|
|
else
|
|
{
|
|
destroyedYTranslation = 0.0f;
|
|
SetRemoveCollisionVolumeFlag();
|
|
}
|
|
|
|
timeDelay = model_resource->timeDelay;
|
|
|
|
//
|
|
//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
|
|
// Is Stopping Collision Volume ?
|
|
//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
|
|
//
|
|
if (model_resource->stoppingCollisionVolume)
|
|
{
|
|
SetStoppingCollisionVolumeFlag();
|
|
}
|
|
|
|
explosionResourceID = model_resource->explosionResourceID;
|
|
crunchExplosionResourceID = model_resource->crunchExplosionResourceID;
|
|
res->Unlock();
|
|
|
|
//DEBUG_STREAM << model_resource->crunchExplosionResourceID << std::endl << std::flush;
|
|
|
|
//
|
|
//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
|
|
// Read in DamageZone Information from the Resource
|
|
//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
|
|
//
|
|
ResourceDescription *dmg_res =
|
|
application->GetResourceFile()->SearchList(
|
|
resourceID,
|
|
ResourceDescription::DamageZoneStreamResourceType
|
|
);
|
|
Check(dmg_res);
|
|
dmg_res->Lock();
|
|
DynamicMemoryStream damage_stream (
|
|
dmg_res->resourceAddress,
|
|
dmg_res->resourceSize
|
|
);
|
|
//
|
|
//~~~~~~~~~~~~~~~~~~~~~~~~~~
|
|
// skip over DamageZoneCount
|
|
//~~~~~~~~~~~~~~~~~~~~~~~~~~
|
|
//
|
|
damage_stream.AdvancePointer(sizeof(damageZoneCount));
|
|
//
|
|
//~~~~~~~~~~~~~~~~~~~~~~~
|
|
// Create the DamageZones
|
|
//~~~~~~~~~~~~~~~~~~~~~~~
|
|
//
|
|
for(int ii=0;ii<damageZoneCount;++ii)
|
|
{
|
|
damageZones[ii] = new DamageZone(
|
|
this,
|
|
ii,
|
|
&damage_stream
|
|
);
|
|
Register_Object(damageZones[ii]);
|
|
}
|
|
SetValidFlag();
|
|
dmg_res->Unlock();
|
|
Check_Fpu();
|
|
}
|
|
//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
|
|
//
|
|
|
|
|
|
|
|
void
|
|
CulturalIcon::ReadUpdateRecord(Simulation::UpdateRecord *message)
|
|
{
|
|
Check(this);
|
|
Check_Pointer(message);
|
|
|
|
UnscalableTerrain::ReadUpdateRecord(message);
|
|
|
|
if (simulationState.GetOldState() != GetSimulationState() && (GetSimulationState() == BurningState))
|
|
{
|
|
UpdateCollisionVolumes();
|
|
}
|
|
Check_Fpu();
|
|
}
|
|
|
|
//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
|
|
//
|
|
|
|
Logical
|
|
CulturalIcon::CreateMakeMessage(
|
|
MakeMessage *creation_message,
|
|
NotationFile *model_file,
|
|
const ResourceDirectories *directories
|
|
)
|
|
{
|
|
Check(creation_message);
|
|
Check(model_file);
|
|
|
|
if (!UnscalableTerrain::CreateMakeMessage(creation_message, model_file, directories))
|
|
{
|
|
return False;
|
|
}
|
|
|
|
creation_message->messageLength = sizeof(MakeMessage);
|
|
creation_message->classToCreate = CulturalIconClassID;
|
|
creation_message->instanceFlags = MasterInstance|DynamicFlag|MapFlag|TrappedFlag;
|
|
return True;
|
|
}
|
|
|
|
//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
|
|
//
|
|
CulturalIcon*
|
|
CulturalIcon::Make(MakeMessage *creation_message)
|
|
{
|
|
Check_Fpu();
|
|
return new CulturalIcon(creation_message);
|
|
}
|
|
|
|
//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
|
|
//
|
|
CulturalIcon::~CulturalIcon()
|
|
{
|
|
|
|
}
|
|
//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
|
|
//
|
|
int
|
|
CulturalIcon::CreateModelResource(
|
|
#if DEBUG_LEVEL>0
|
|
ResourceFile *resource_file,
|
|
const char *model_name,
|
|
NotationFile *model_file,
|
|
const ResourceDirectories *directories,
|
|
ModelResource* model
|
|
#else
|
|
ResourceFile *resource_file,
|
|
const char *model_name,
|
|
NotationFile *model_file,
|
|
const ResourceDirectories *,
|
|
ModelResource* model
|
|
#endif
|
|
)
|
|
{
|
|
Check(resource_file);
|
|
Check_Pointer(model_name);
|
|
Check(model_file);
|
|
Check_Pointer(directories);
|
|
|
|
//
|
|
//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
|
|
// Allocate memory for the resource
|
|
//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
|
|
//
|
|
ModelResource *local_model = model;
|
|
if (!local_model)
|
|
{
|
|
local_model = new ModelResource;
|
|
Register_Pointer(local_model);
|
|
}
|
|
if (
|
|
!model_file->GetEntry(
|
|
"gamedata",
|
|
"DestroyedYTranslation",
|
|
&local_model->destroyedYTranslation
|
|
)
|
|
)
|
|
{
|
|
local_model->sinkCollisionVolume = False;
|
|
local_model->destroyedYTranslation = 0.0f;
|
|
}
|
|
else
|
|
{
|
|
local_model->sinkCollisionVolume = True;
|
|
}
|
|
|
|
if (!model_file->GetLogicalEntry(
|
|
"gamedata",
|
|
"StoppingCollisionVolume",
|
|
&local_model->stoppingCollisionVolume
|
|
)
|
|
)
|
|
{
|
|
local_model->stoppingCollisionVolume = False;
|
|
}
|
|
|
|
if (
|
|
!model_file->GetEntry(
|
|
"gamedata",
|
|
"TimeDelay",
|
|
&local_model->timeDelay
|
|
)
|
|
)
|
|
{
|
|
DEBUG_STREAM << model_name << " TimeDelay is missing " << std::endl << std::flush;
|
|
PostQuitMessage(AbortExitCodeID);
|
|
}
|
|
|
|
|
|
//
|
|
//----------------------------------------------------------------------
|
|
// Read in the Model Filename of the Explosion renderable, then find its
|
|
// resource ID in the resource file
|
|
//----------------------------------------------------------------------
|
|
//
|
|
const char *explosion = "Unspecified";
|
|
if (
|
|
!model_file->GetEntry(
|
|
"gamedata",
|
|
"ExplosionModelFile",
|
|
&explosion
|
|
)
|
|
)
|
|
{
|
|
std::cout << model_name << " missing ExplosionModelFile!\n";
|
|
Check_Fpu();
|
|
return False;
|
|
}
|
|
|
|
|
|
ResourceDescription *res = NULL;
|
|
|
|
if (strcmp(explosion,"Unspecified"))
|
|
{
|
|
res = resource_file->FindResourceDescription(
|
|
explosion,
|
|
ResourceDescription::ModelListResourceType
|
|
);
|
|
}
|
|
if (!res)
|
|
{
|
|
std::cout << model_name << " cannot find " << explosion
|
|
<< " in resource file!\n";
|
|
Check_Fpu();
|
|
return False;
|
|
}
|
|
if (res)
|
|
{
|
|
local_model->explosionResourceID = res->resourceID;
|
|
}
|
|
|
|
|
|
|
|
const char *crunch_explosion = "Unspecified";
|
|
|
|
model_file->GetEntry(
|
|
"gamedata",
|
|
"CrunchExplosionModelFile",
|
|
&crunch_explosion
|
|
);
|
|
|
|
|
|
local_model->crunchExplosionResourceID = -1;
|
|
|
|
if (strcmp(crunch_explosion,"Unspecified"))
|
|
{
|
|
//res = NULL;
|
|
res = resource_file->FindResourceDescription(
|
|
crunch_explosion,
|
|
ResourceDescription::ModelListResourceType
|
|
);
|
|
|
|
if (!res)
|
|
{
|
|
std::cout << model_name << " cannot find " << crunch_explosion
|
|
<< " in resource file!\n";
|
|
Check_Fpu();
|
|
return False;
|
|
}
|
|
else
|
|
{
|
|
local_model->crunchExplosionResourceID = res->resourceID;
|
|
}
|
|
|
|
|
|
}
|
|
|
|
//DEBUG_STREAM << ":" << local_model->crunchExplosionResourceID << std::endl << std::flush;
|
|
|
|
|
|
//
|
|
//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
|
|
// Write the model to the resource
|
|
//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
|
|
//
|
|
if (!model)
|
|
{
|
|
ResourceDescription *new_res =
|
|
resource_file->AddResource(
|
|
model_name,
|
|
ResourceDescription::GameModelResourceType,
|
|
1,
|
|
ResourceDescription::Preload,
|
|
local_model,
|
|
sizeof(*local_model)
|
|
);
|
|
Unregister_Pointer(local_model);
|
|
delete local_model;
|
|
Check(new_res);
|
|
Check_Fpu();
|
|
return new_res->resourceID;
|
|
}
|
|
else
|
|
{
|
|
Check_Fpu();
|
|
return 0;
|
|
}
|
|
}
|
|
|
|
//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
|
|
//
|
|
int
|
|
CulturalIcon::CreateDamageZoneStream(
|
|
ResourceFile *resource_file,
|
|
const char *model_name,
|
|
NotationFile *model_file,
|
|
const ResourceDirectories *directories
|
|
)
|
|
{
|
|
Check(resource_file);
|
|
Check_Pointer(model_name);
|
|
Check(model_file);
|
|
Check_Pointer(directories);
|
|
|
|
//
|
|
//-------------------
|
|
// Find the .dmg file
|
|
//-------------------
|
|
//
|
|
const char* dmg_file_cname;
|
|
if (
|
|
!model_file->GetEntry(
|
|
"gamedata",
|
|
"DamageZones",
|
|
&dmg_file_cname
|
|
)
|
|
)
|
|
{
|
|
std::cerr << model_name << " is missing .dmg file specification!\n";
|
|
return -1;
|
|
}
|
|
|
|
CString dmg_filename =
|
|
MakePathedFilename(directories->modelDirectory, dmg_file_cname);
|
|
|
|
NotationFile *dmg_file = new NotationFile(dmg_filename);
|
|
Register_Object(dmg_file);
|
|
int page_count = dmg_file->PageCount();
|
|
if (!page_count)
|
|
{
|
|
std::cerr << dmg_filename << " is empty or missing!\n";
|
|
Unregister_Object(dmg_file);
|
|
delete dmg_file;
|
|
return -1;
|
|
}
|
|
|
|
DynamicMemoryStream damage_stream;
|
|
|
|
damage_stream << page_count;
|
|
NameList *dmg_namelist = dmg_file->MakePageList();
|
|
Register_Object(dmg_namelist);
|
|
|
|
NameList::Entry *dmg_entry = dmg_namelist->GetFirstEntry();
|
|
|
|
CString dmg_page_name;
|
|
while(dmg_entry)
|
|
{
|
|
dmg_page_name = dmg_entry->GetName();
|
|
DamageZone::CreateStreamedDamageZone(
|
|
model_file,
|
|
model_name,
|
|
NULL,
|
|
dmg_page_name,
|
|
&damage_stream,
|
|
dmg_file,
|
|
directories
|
|
);
|
|
dmg_entry = dmg_entry->GetNextEntry();
|
|
}
|
|
|
|
//
|
|
//~~~~~~~~~~~~~~~~~~~~~~~
|
|
// Add Stream to Resource
|
|
//~~~~~~~~~~~~~~~~~~~~~~~
|
|
//
|
|
ResourceDescription *new_res =
|
|
resource_file->AddResourceMemoryStream(
|
|
model_name,
|
|
ResourceDescription::DamageZoneStreamResourceType,
|
|
1,
|
|
ResourceDescription::Preload,
|
|
&damage_stream
|
|
);
|
|
Check(new_res);
|
|
|
|
Unregister_Object(dmg_file);
|
|
delete dmg_file;
|
|
Unregister_Object(dmg_namelist);
|
|
delete dmg_namelist;
|
|
|
|
return new_res->resourceID;
|
|
}
|
|
|
|
//##########################################################################
|
|
//#################### Class Landmark ##########################
|
|
//##########################################################################
|
|
|
|
//#############################################################################
|
|
// Shared Data Support
|
|
//
|
|
Derivation* Landmark::GetClassDerivations()
|
|
{ static Derivation classDerivations(CulturalIcon::GetClassDerivations(), "Landmark");
|
|
return &classDerivations;
|
|
}
|
|
|
|
|
|
Landmark::SharedData
|
|
Landmark::DefaultData(
|
|
Landmark::GetClassDerivations(),
|
|
Landmark::MessageHandlers,
|
|
Landmark::GetAttributeIndex(),
|
|
Landmark::StateCount,
|
|
(Landmark::MakeHandler)Landmark::Make
|
|
);
|
|
//#############################################################################
|
|
// Message Support
|
|
//
|
|
const Receiver::HandlerEntry
|
|
Landmark::MessageHandlerEntries[]=
|
|
{
|
|
MESSAGE_ENTRY(Landmark, TakeDamage)
|
|
};
|
|
|
|
Landmark::MessageHandlerSet
|
|
Landmark::MessageHandlers(
|
|
ELEMENTS(Landmark::MessageHandlerEntries),
|
|
Landmark::MessageHandlerEntries,
|
|
CulturalIcon::GetMessageHandlers()
|
|
);
|
|
//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
|
|
//
|
|
void
|
|
Landmark::TakeDamageMessageHandler(TakeDamageMessage *damage_message)
|
|
{
|
|
Check(damage_message);
|
|
|
|
if (owningTeam == NULL)
|
|
{
|
|
//
|
|
//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
|
|
// Initialize the owning team pointer
|
|
// with the Teams entity Group
|
|
//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
|
|
//
|
|
Check(application);
|
|
EntityManager *entity_manager = application->GetEntityManager();
|
|
Check(entity_manager);
|
|
EntityGroup *team_group = entity_manager->UseGroup("Teams");
|
|
if (team_group)
|
|
{
|
|
ChainIteratorOf<Node*> team_iterator(team_group->groupMembers);
|
|
Team *current_team;
|
|
while((current_team = (Team*) team_iterator.ReadAndNext() ) != NULL)
|
|
{
|
|
if (!strcmp(current_team->teamName, teamName))
|
|
{
|
|
owningTeam = current_team;
|
|
break;
|
|
}
|
|
}
|
|
}
|
|
}
|
|
|
|
|
|
|
|
if (owningTeam == NULL)
|
|
{
|
|
DEBUG_STREAM << "TEAM : '" << teamName << "' was never found! " << std::endl << std::flush;
|
|
exit (-1);
|
|
}
|
|
|
|
|
|
if (GetSimulationState() != BurningState)
|
|
{
|
|
CulturalIcon::TakeDamageMessageHandler(damage_message);
|
|
|
|
//
|
|
//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
|
|
// Calculate the Score Loss based
|
|
// on the Scenario Data
|
|
//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
|
|
//
|
|
Check(scenarioRole);
|
|
#if 0
|
|
Logical landmark_destroyed = GetSimulationState() == BurningState;
|
|
Scalar score_loss = scenarioRole->CalcDamageReceivedScore(
|
|
damage_message->damageData.damageAmount
|
|
);
|
|
|
|
//
|
|
//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
|
|
// Tell the Console about the Damage
|
|
//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
|
|
//
|
|
Check(application);
|
|
HostManager *host_manager = application->GetHostManager();
|
|
Check(host_manager);
|
|
Host *console_host = host_manager->GetConsoleHost();
|
|
|
|
if (console_host)
|
|
{
|
|
Check(console_host);
|
|
ConsoleLandmarkDamagedMessage landmark_damaged_message(
|
|
damage_message->inflictingEntity.GetHostID(),
|
|
landmarkID,
|
|
damage_message->damageData.damageAmount,
|
|
landmark_destroyed,
|
|
score_loss
|
|
);
|
|
|
|
application->SendMessage(
|
|
console_host->GetHostID(),
|
|
NetworkClient::ConsoleClientID,
|
|
&landmark_damaged_message
|
|
);
|
|
}
|
|
#endif
|
|
}
|
|
}
|
|
|
|
Logical
|
|
CulturalIcon::TestInstance() const
|
|
{
|
|
return IsDerivedFrom(*GetClassDerivations());
|
|
}
|
|
|
|
//#############################################################################
|
|
// Construction and Destruction
|
|
//
|
|
|
|
//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
|
|
//
|
|
Landmark::Landmark(
|
|
MakeMessage *creation_message,
|
|
SharedData &shared_data
|
|
) :
|
|
CulturalIcon ( creation_message, shared_data)
|
|
{
|
|
scenarioRole = NULL;
|
|
owningTeam = NULL;
|
|
//
|
|
//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
|
|
// Initialize the owning team pointer
|
|
// with the Teams entity Group
|
|
//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
|
|
//
|
|
Check(application);
|
|
EntityManager *entity_manager = application->GetEntityManager();
|
|
Check(entity_manager);
|
|
EntityGroup *team_group = entity_manager->UseGroup("Teams");
|
|
if (team_group)
|
|
{
|
|
ChainIteratorOf<Node*> team_iterator(team_group->groupMembers);
|
|
Team *current_team;
|
|
while((current_team = (Team*) team_iterator.ReadAndNext() ) != NULL)
|
|
{
|
|
if (!strcmp(current_team->teamName, creation_message->teamName))
|
|
{
|
|
owningTeam = current_team;
|
|
break;
|
|
}
|
|
}
|
|
}
|
|
|
|
//
|
|
// If the team is null, that's ok. It will either show up over the network
|
|
// or be a free for all
|
|
//
|
|
|
|
|
|
Str_Copy(teamName, creation_message->teamName, sizeof(teamName));
|
|
|
|
|
|
Check(application->GetCurrentMission());
|
|
scenarioRole =
|
|
application->GetCurrentMission()->GetScenarioRole(creation_message->roleName);
|
|
if (!scenarioRole)
|
|
{
|
|
|
|
scenarioRole = new ScenarioRole("Role::MapAssigned",creation_message->roleName);
|
|
Register_Object(scenarioRole);
|
|
application->GetCurrentMission()->AddScenarioRole(scenarioRole);
|
|
}
|
|
//
|
|
//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
|
|
// Add this landmark to the Landmark Entity Group
|
|
//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
|
|
//
|
|
EntityGroup *landmark_group = entity_manager->UseGroup("Landmarks");
|
|
Check(landmark_group);
|
|
landmark_group->Add(this);
|
|
|
|
Check_Fpu();
|
|
}
|
|
|
|
//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
|
|
//
|
|
Landmark::~Landmark()
|
|
{
|
|
|
|
}
|
|
|
|
//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
|
|
//
|
|
Logical
|
|
Landmark::CreateMakeMessage(
|
|
MakeMessage *creation_message,
|
|
NotationFile *model_file,
|
|
const ResourceDirectories *directories
|
|
)
|
|
{
|
|
Check(creation_message);
|
|
Check(model_file);
|
|
|
|
if (!CulturalIcon::CreateMakeMessage(creation_message, model_file, directories))
|
|
{
|
|
return False;
|
|
}
|
|
|
|
creation_message->messageLength = sizeof(MakeMessage);
|
|
creation_message->classToCreate = LandmarkClassID;
|
|
|
|
char *p;
|
|
|
|
//
|
|
//----------------------------
|
|
// landmarkID allocated
|
|
// by map stream creation
|
|
//----------------------------
|
|
//
|
|
|
|
//
|
|
//~~~~~~~~~~~~~~~
|
|
// Get the teamName
|
|
//~~~~~~~~~~~~~~~
|
|
//
|
|
if ((p = strtok(NULL, ",")) == NULL)
|
|
{
|
|
std::cerr << "teamName missing!\n";
|
|
return False;
|
|
}
|
|
Str_Copy(creation_message->teamName,p, sizeof(creation_message->teamName));
|
|
|
|
|
|
//
|
|
//~~~~~~~~~~~~~~~~~
|
|
// Get the roleName
|
|
//~~~~~~~~~~~~~~~~~
|
|
//
|
|
if ((p = strtok(NULL, ",")) == NULL)
|
|
{
|
|
std::cerr << "roleName missing!\n";
|
|
return False;
|
|
}
|
|
Str_Copy(creation_message->roleName,p, sizeof(creation_message->roleName));
|
|
|
|
|
|
//
|
|
//~~~~~~~~~~~~~~~~~~~~~~
|
|
// Get the Landmark Name
|
|
//~~~~~~~~~~~~~~~~~~~~~~
|
|
//
|
|
if ((p = strtok(NULL, ",")) == NULL)
|
|
{
|
|
std::cerr << "Landmark Name missing!\n";
|
|
return False;
|
|
}
|
|
Str_Copy(creation_message->landmarkName,p, sizeof(creation_message->landmarkName));
|
|
|
|
|
|
return True;
|
|
}
|
|
|
|
//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
|
|
//
|
|
Landmark*
|
|
Landmark::Make(MakeMessage *creation_message)
|
|
{
|
|
Check_Fpu();
|
|
return new Landmark(creation_message);
|
|
}
|
|
|
|
|
|
//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
|
|
//
|
|
int
|
|
Landmark::CreateModelResource(
|
|
ResourceFile *resource_file,
|
|
const char *model_name,
|
|
NotationFile *model_file,
|
|
const ResourceDirectories *directories,
|
|
ModelResource* model
|
|
)
|
|
{
|
|
Check(resource_file);
|
|
Check_Pointer(model_name);
|
|
Check(model_file);
|
|
Check_Pointer(directories);
|
|
|
|
|
|
CulturalIcon::CreateModelResource(resource_file, model_name, model_file, directories, model);
|
|
|
|
//
|
|
//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
|
|
// Allocate memory for the resource
|
|
//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
|
|
//
|
|
ModelResource *local_model = model;
|
|
if (!local_model)
|
|
{
|
|
local_model = new ModelResource;
|
|
Register_Pointer(local_model);
|
|
}
|
|
|
|
#if 0
|
|
const char *role_model_file;
|
|
if (!model_file->GetEntry(
|
|
"gamedata",
|
|
"RoleModelFile",
|
|
&role_model_file
|
|
)
|
|
)
|
|
{
|
|
std::cerr<<model_name<<" missing RoleModelFile ! \n"<<std::endl;
|
|
Dump_And_Die:
|
|
if (local_model)
|
|
{
|
|
Unregister_Pointer(local_model);
|
|
delete local_model;
|
|
}
|
|
return -1;
|
|
}
|
|
else
|
|
{
|
|
//
|
|
//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
|
|
// Hunt for Model file in ResourceFile
|
|
//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
|
|
//
|
|
ResourceDescription *res;
|
|
|
|
res = resource_file->FindResourceDescription(
|
|
role_model_file,
|
|
ResourceDescription::ModelListResourceType
|
|
);
|
|
if (!res)
|
|
{
|
|
std::cout << model_name << " cannot find " << role_model_file
|
|
<< " in resource file!\n";
|
|
goto Dump_And_Die;
|
|
}
|
|
local_model->roleResourceID = res->resourceID;
|
|
}
|
|
#endif
|
|
|
|
|
|
//
|
|
//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
|
|
// Write the model to the resource
|
|
//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
|
|
//
|
|
if (!model)
|
|
{
|
|
ResourceDescription *new_res =
|
|
resource_file->AddResource(
|
|
model_name,
|
|
ResourceDescription::GameModelResourceType,
|
|
1,
|
|
ResourceDescription::Preload,
|
|
local_model,
|
|
sizeof(*local_model)
|
|
);
|
|
Unregister_Pointer(local_model);
|
|
delete local_model;
|
|
Check(new_res);
|
|
Check_Fpu();
|
|
return new_res->resourceID;
|
|
}
|
|
else
|
|
{
|
|
Check_Fpu();
|
|
return 0;
|
|
}
|
|
}
|
|
|
|
Logical
|
|
Landmark::TestInstance() const
|
|
{
|
|
return IsDerivedFrom(*GetClassDerivations());
|
|
}
|