Initial import of Red Planet v4.10 Win32 source
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>
This commit is contained in:
+537
@@ -0,0 +1,537 @@
|
||||
#include "munga.h"
|
||||
#pragma hdrstop
|
||||
|
||||
#include "door.h"
|
||||
#include "fileutil.h"
|
||||
#include "boxsolid.h"
|
||||
#include "doorfram.h"
|
||||
#include "app.h"
|
||||
#include "notation.h"
|
||||
|
||||
//#############################################################################
|
||||
// Shared Data Support
|
||||
//
|
||||
Door::SharedData
|
||||
Door::DefaultData(
|
||||
Door::GetClassDerivations(),
|
||||
Door::GetMessageHandlers(),
|
||||
Door::GetAttributeIndex(),
|
||||
Door::StateCount
|
||||
);
|
||||
|
||||
Derivation* Door::GetClassDerivations()
|
||||
{
|
||||
static Derivation classDerivations(Subsystem::GetClassDerivations(), "Door");
|
||||
return &classDerivations;
|
||||
}
|
||||
|
||||
|
||||
//#############################################################################
|
||||
// Messaging Support
|
||||
//
|
||||
|
||||
|
||||
//#############################################################################
|
||||
// Attribute Support
|
||||
//
|
||||
|
||||
const Door::IndexEntry
|
||||
Door::AttributePointers[]=
|
||||
{
|
||||
{
|
||||
Door::CurrentPositionAttributeID,
|
||||
"CurrentPosition",
|
||||
(Simulation::AttributePointer)&Door::currentPosition
|
||||
},
|
||||
{
|
||||
Door::VideoResourceAttributeID,
|
||||
"VideoResource",
|
||||
(Simulation::AttributePointer)&Door::videoResource
|
||||
},
|
||||
{
|
||||
Door::PercentOpenAttributeID,
|
||||
"PercentOpen",
|
||||
(Simulation::AttributePointer)&Door::percentOpen
|
||||
},
|
||||
{
|
||||
Door::CurrentVelocityAttributeID,
|
||||
"CurrentVelocity",
|
||||
(Simulation::AttributePointer)&Door::currentVelocity
|
||||
}
|
||||
};
|
||||
|
||||
Door::AttributeIndexSet& Door::GetAttributeIndex()
|
||||
{
|
||||
static Door::AttributeIndexSet attributeIndex(ELEMENTS(Door::AttributePointers),
|
||||
Door::AttributePointers,
|
||||
Subsystem::GetAttributeIndex()
|
||||
);
|
||||
return attributeIndex;
|
||||
}
|
||||
|
||||
//#############################################################################
|
||||
// Model Support
|
||||
//
|
||||
void
|
||||
Door::ReadUpdateRecord(Simulation::UpdateRecord *message)
|
||||
{
|
||||
Check(this);
|
||||
Check_Pointer(message);
|
||||
Subsystem::ReadUpdateRecord(message);
|
||||
UpdateRecord* record = (UpdateRecord*) message;
|
||||
|
||||
percentOpen = record->percentOpen;
|
||||
switch (GetSimulationState())
|
||||
{
|
||||
case Opening:
|
||||
case Closing:
|
||||
phaseTimeRemaining = travelTime;
|
||||
break;
|
||||
case Opened:
|
||||
case Closed:
|
||||
phaseTimeRemaining = deadTime;
|
||||
break;
|
||||
}
|
||||
// DEBUG_STREAM << GetEntity()->GetEntityID() << " door updated to state "
|
||||
// << GetSimulationState() << " @ "
|
||||
// << application->GetSecondsRemainingInGame() << endl;
|
||||
MoveCollisionVolume(percentOpen);
|
||||
Check_Fpu();
|
||||
}
|
||||
|
||||
//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
|
||||
//
|
||||
void
|
||||
Door::WriteUpdateRecord(Simulation::UpdateRecord *record, int update_model)
|
||||
{
|
||||
Check(this);
|
||||
Check_Pointer(record);
|
||||
|
||||
Subsystem::WriteUpdateRecord(record, update_model);
|
||||
|
||||
UpdateRecord *update = (UpdateRecord*)record;
|
||||
update->percentOpen = percentOpen;
|
||||
update->recordLength = sizeof(*update);
|
||||
Check_Fpu();
|
||||
}
|
||||
|
||||
//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
|
||||
//
|
||||
void
|
||||
Door::SlideDoor(Scalar time_slice)
|
||||
{
|
||||
Check(this);
|
||||
|
||||
//
|
||||
//------------------------------------------------------------
|
||||
// Advance the clock, then branch based upon our current state
|
||||
//------------------------------------------------------------
|
||||
//
|
||||
int new_state;
|
||||
if (time_slice > 1.0f)
|
||||
{
|
||||
Check_Fpu();
|
||||
return;
|
||||
}
|
||||
phaseTimeRemaining -= time_slice;
|
||||
Scalar percent_open;
|
||||
switch (GetSimulationState())
|
||||
{
|
||||
|
||||
//
|
||||
//------------------------------------------------------------------------
|
||||
// If the door is not done opening, set its new position, otherwise branch
|
||||
// to the opened state
|
||||
//------------------------------------------------------------------------
|
||||
//
|
||||
case Opening:
|
||||
Door_Opening:
|
||||
new_state = Opening;
|
||||
if (phaseTimeRemaining > 0.0f)
|
||||
{
|
||||
percent_open = 1.0f - phaseTimeRemaining/travelTime;
|
||||
}
|
||||
else
|
||||
{
|
||||
phaseTimeRemaining += deadTime;
|
||||
// DEBUG_STREAM << GetEntity()->GetEntityID() << " door opened @ "
|
||||
// << application->GetSecondsRemainingInGame() << endl;
|
||||
goto Door_Opened;
|
||||
}
|
||||
currentVelocity.Subtract(
|
||||
worldExtent,
|
||||
GetEntity()->localOrigin.linearPosition
|
||||
);
|
||||
currentVelocity /= travelTime;
|
||||
Check_Fpu();
|
||||
break;
|
||||
|
||||
//
|
||||
//-------------------------------------------------------------
|
||||
// If the door is ready to start closing, jump to closing state
|
||||
//-------------------------------------------------------------
|
||||
//
|
||||
case Opened:
|
||||
Door_Opened:
|
||||
new_state = Opened;
|
||||
if (phaseTimeRemaining <= 0.0f)
|
||||
{
|
||||
phaseTimeRemaining += travelTime;
|
||||
// DEBUG_STREAM << GetEntity()->GetEntityID() << " door closing @ "
|
||||
// << application->GetSecondsRemainingInGame() << endl;
|
||||
goto Door_Closing;
|
||||
}
|
||||
percent_open = 1.0f;
|
||||
currentVelocity = Vector3D::Identity;
|
||||
Check_Fpu();
|
||||
break;
|
||||
|
||||
//
|
||||
//------------------------------------------------------------------------
|
||||
// If the door is not done closing, set its new position, otherwise branch
|
||||
// to the closed state
|
||||
//------------------------------------------------------------------------
|
||||
//
|
||||
case DefaultState:
|
||||
phaseTimeRemaining = travelTime;
|
||||
// DEBUG_STREAM << GetEntity()->GetEntityID() << " door default @ "
|
||||
// << application->GetSecondsRemainingInGame() << endl;
|
||||
case Closing:
|
||||
Door_Closing:
|
||||
new_state = Closing;
|
||||
if (phaseTimeRemaining > 0.0f)
|
||||
{
|
||||
percent_open = phaseTimeRemaining/travelTime;
|
||||
}
|
||||
else
|
||||
{
|
||||
phaseTimeRemaining += deadTime;
|
||||
// DEBUG_STREAM << GetEntity()->GetEntityID() << " door closed @ "
|
||||
// << application->GetSecondsRemainingInGame() << endl;
|
||||
goto Door_Closed;
|
||||
}
|
||||
currentVelocity.Subtract(
|
||||
GetEntity()->localOrigin.linearPosition,
|
||||
worldExtent
|
||||
);
|
||||
currentVelocity /= travelTime;
|
||||
Check_Fpu();
|
||||
break;
|
||||
|
||||
//
|
||||
//-------------------------------------------------------------
|
||||
// If the door is ready to start opening, jump to opening state
|
||||
//-------------------------------------------------------------
|
||||
//
|
||||
case Closed:
|
||||
Door_Closed:
|
||||
new_state = Closed;
|
||||
if (phaseTimeRemaining <= 0.0f)
|
||||
{
|
||||
phaseTimeRemaining += travelTime;
|
||||
// DEBUG_STREAM << GetEntity()->GetEntityID() << " door opening @ "
|
||||
// << application->GetSecondsRemainingInGame() << endl;
|
||||
goto Door_Opening;
|
||||
}
|
||||
percent_open = 0.0f;
|
||||
currentVelocity = Vector3D::Identity;
|
||||
Check_Fpu();
|
||||
break;
|
||||
|
||||
}
|
||||
|
||||
//
|
||||
//-------------------------------------------------
|
||||
// Move the collision volumes and set the new state
|
||||
//-------------------------------------------------
|
||||
//
|
||||
MoveCollisionVolume(percent_open);
|
||||
SetSimulationState(new_state);
|
||||
Check_Fpu();
|
||||
}
|
||||
|
||||
//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
|
||||
//
|
||||
void
|
||||
Door::MoveCollisionVolume(Scalar percent_open)
|
||||
{
|
||||
Check(this);
|
||||
|
||||
//
|
||||
//---------------------------------------------------------
|
||||
// If the door hasn't moved, don't bother updating anything
|
||||
//---------------------------------------------------------
|
||||
//
|
||||
Entity *entity = GetEntity();
|
||||
Check(entity);
|
||||
|
||||
if (
|
||||
GetSimulationState() != simulationState.GetOldState()
|
||||
&& entity->GetInstance() == Entity::MasterInstance
|
||||
&& entity->IsDynamic()
|
||||
)
|
||||
{
|
||||
ForceUpdate();
|
||||
}
|
||||
if (percent_open == percentOpen)
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
//
|
||||
//-----------------------------------
|
||||
// Otherwise, lerp the local position
|
||||
//-----------------------------------
|
||||
//
|
||||
percentOpen = percent_open;
|
||||
currentPosition.Lerp(Point3D::Identity, localExtent, percentOpen);
|
||||
|
||||
//
|
||||
//-----------------------------------------------------------
|
||||
// Now, lerp the world position and set the collision volumes
|
||||
//-----------------------------------------------------------
|
||||
//
|
||||
Point3D world;
|
||||
world.Lerp(
|
||||
GetEntity()->localOrigin.linearPosition,
|
||||
worldExtent,
|
||||
percentOpen
|
||||
);
|
||||
|
||||
BoxedSolid* temp = collisionTemplates;
|
||||
BoxedSolid* vol = collisionVolumes;
|
||||
while (temp)
|
||||
{
|
||||
Check(temp);
|
||||
Check(vol);
|
||||
|
||||
vol->minX = temp->minX + world.x;
|
||||
vol->maxX = temp->maxX + world.x;
|
||||
vol->minY = temp->minY + world.y;
|
||||
vol->maxY = temp->maxY + world.y;
|
||||
vol->minZ = temp->minZ + world.z;
|
||||
vol->maxZ = temp->maxZ + world.z;
|
||||
|
||||
vol = vol->GetNextSolid();
|
||||
temp = temp->GetNextSolid();
|
||||
}
|
||||
Verify(!vol);
|
||||
Check_Fpu();
|
||||
}
|
||||
|
||||
//#############################################################################
|
||||
// Constructer/Destructor Support
|
||||
//
|
||||
|
||||
Door::Door(
|
||||
DoorFrame *entity,
|
||||
int subsystem_ID,
|
||||
SubsystemResource *subsystem_resource
|
||||
):
|
||||
Subsystem(entity, subsystem_ID, subsystem_resource, DefaultData)
|
||||
{
|
||||
Check_Pointer(this);
|
||||
Check(entity);
|
||||
Check_Pointer(subsystem_resource);
|
||||
|
||||
//
|
||||
// GetStream data NOTE::This must be in the same order as below!!!
|
||||
//
|
||||
localExtent = subsystem_resource->motionExtent;
|
||||
travelTime = subsystem_resource->travelTime;
|
||||
deadTime = subsystem_resource->deadTime;
|
||||
|
||||
//
|
||||
// Initialize variables
|
||||
//
|
||||
phaseTimeRemaining = 0.0f;
|
||||
currentPosition = Point3D::Identity;
|
||||
|
||||
SetPerformance(&Door::SlideDoor);
|
||||
SetSimulationState(DefaultState);
|
||||
|
||||
collisionVolumeCount = 0;
|
||||
collisionTemplates = NULL;
|
||||
collisionVolumes = NULL;
|
||||
percentOpen = -1.0f;
|
||||
|
||||
//
|
||||
//-------------------------------------
|
||||
// Establish the worldspace coordinates
|
||||
//-------------------------------------
|
||||
//
|
||||
worldExtent.Multiply(localExtent, entity->localToWorld);
|
||||
Origin local_origin = entity->localOrigin;
|
||||
local_origin.linearPosition = Point3D::Identity;
|
||||
|
||||
//
|
||||
//------------------------------
|
||||
// Read in the collision volumes
|
||||
//------------------------------
|
||||
//
|
||||
Check(application);
|
||||
ResourceFile *res_file = application->GetResourceFile();
|
||||
Check(res_file);
|
||||
ResourceDescription *res =
|
||||
res_file->FindResourceDescription(subsystem_resource->collisionID);
|
||||
Check(res);
|
||||
res->Lock();
|
||||
BoxedSolidResource* box =
|
||||
(BoxedSolidResource*)res->resourceAddress;
|
||||
Check_Pointer(box);
|
||||
collisionVolumeCount = res->resourceSize / sizeof(BoxedSolidResource);
|
||||
|
||||
for (int i=0; i<collisionVolumeCount; ++i)
|
||||
{
|
||||
BoxedSolidResource world_box,local_box;
|
||||
world_box.Instance(*box,entity->localOrigin);
|
||||
local_box.Instance(*box,local_origin);
|
||||
|
||||
collisionTemplates =
|
||||
BoxedSolid::MakeBoxedSolid(&local_box, this, collisionTemplates);
|
||||
Register_Object(collisionTemplates);
|
||||
|
||||
collisionVolumes =
|
||||
BoxedSolid::MakeBoxedSolid(&world_box, this, collisionVolumes);
|
||||
Register_Object(collisionVolumes);
|
||||
|
||||
++box;
|
||||
}
|
||||
res->Unlock();
|
||||
|
||||
MoveCollisionVolume(0.0f);
|
||||
Check(this);
|
||||
}
|
||||
|
||||
Door::~Door()
|
||||
{
|
||||
BoxedSolid *box = collisionTemplates;
|
||||
while (box)
|
||||
{
|
||||
BoxedSolid *next_box = box->GetNextSolid();
|
||||
Unregister_Object(box);
|
||||
delete box;
|
||||
box = next_box;
|
||||
}
|
||||
box = collisionVolumes;
|
||||
while (box)
|
||||
{
|
||||
BoxedSolid *next_box = box->GetNextSolid();
|
||||
Unregister_Object(box);
|
||||
delete box;
|
||||
box = next_box;
|
||||
}
|
||||
}
|
||||
|
||||
//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
|
||||
// CreateStreamedSubsystem
|
||||
//
|
||||
Logical
|
||||
Door::CreateStreamedSubsystem(
|
||||
NotationFile *model_file,
|
||||
const char *model_name,
|
||||
const char* subsystem_name,
|
||||
SubsystemResource *subsystem_resource,
|
||||
NotationFile *subsystem_file,
|
||||
const ResourceDirectories *directories,
|
||||
ResourceFile *res_file
|
||||
)
|
||||
{
|
||||
if (
|
||||
!Subsystem::CreateStreamedSubsystem(
|
||||
model_file,
|
||||
model_name,
|
||||
subsystem_name,
|
||||
subsystem_resource,
|
||||
subsystem_file,
|
||||
directories
|
||||
)
|
||||
)
|
||||
{
|
||||
return False;
|
||||
}
|
||||
|
||||
subsystem_resource->subsystemModelSize = sizeof(*subsystem_resource);
|
||||
subsystem_resource->classID = RegisteredClass::DoorClassID;
|
||||
|
||||
//
|
||||
// Get the motion Extent
|
||||
//
|
||||
const char *extent_data;
|
||||
if(
|
||||
!subsystem_file->GetEntry(
|
||||
subsystem_name,
|
||||
"MotionExtent",
|
||||
&extent_data
|
||||
)
|
||||
)
|
||||
{
|
||||
std::cerr << subsystem_name << " missing MotionExtent!!\n";
|
||||
return -1;
|
||||
}
|
||||
sscanf(
|
||||
extent_data,
|
||||
"%f %f %f",
|
||||
&subsystem_resource->motionExtent.x,
|
||||
&subsystem_resource->motionExtent.y,
|
||||
&subsystem_resource->motionExtent.z
|
||||
);
|
||||
|
||||
//
|
||||
// Get the travelTime
|
||||
//
|
||||
|
||||
if(
|
||||
!subsystem_file->GetEntry(
|
||||
subsystem_name,
|
||||
"TravelTime",
|
||||
&subsystem_resource->travelTime
|
||||
)
|
||||
)
|
||||
{
|
||||
std::cerr << subsystem_name << " missing TravelTime!\n";
|
||||
return -1;
|
||||
}
|
||||
|
||||
//
|
||||
// Read in the Deadtime
|
||||
//
|
||||
if(
|
||||
!subsystem_file->GetEntry(
|
||||
subsystem_name,
|
||||
"DeadTime",
|
||||
&subsystem_resource->deadTime
|
||||
)
|
||||
)
|
||||
{
|
||||
std::cerr << subsystem_name << " missing DeadTime!\n";
|
||||
return False;
|
||||
}
|
||||
|
||||
const char* collision_file;
|
||||
if (
|
||||
!subsystem_file->GetEntry(
|
||||
subsystem_name,
|
||||
"Collision",
|
||||
&collision_file
|
||||
)
|
||||
)
|
||||
{
|
||||
std::cerr << subsystem_name << " missing Collision!\n";
|
||||
return False;
|
||||
}
|
||||
subsystem_resource->collisionID =
|
||||
BoxedSolidResource::CreateBoxedSolidStream(
|
||||
collision_file,
|
||||
res_file,
|
||||
directories
|
||||
);
|
||||
|
||||
return True;
|
||||
}
|
||||
|
||||
Logical
|
||||
Door::TestInstance() const
|
||||
{
|
||||
return IsDerivedFrom(*GetClassDerivations());
|
||||
}
|
||||
Reference in New Issue
Block a user