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:
Cyd
2026-06-30 07:59:51 -05:00
co-authored by Claude Opus 4.8
commit 4abbf8879f
551 changed files with 254956 additions and 0 deletions
+581
View File
@@ -0,0 +1,581 @@
#include "rp.h"
#pragma hdrstop
#include "demopack.h"
#include "..\munga\line.h"
#include "..\munga\explode.h"
#include "..\munga\boxsolid.h"
#include "..\munga\collasst.h"
#include "..\munga\app.h"
#include "..\munga\interest.h"
#include "vtv.h"
#include "..\munga\hostmgr.h"
#include "..\munga\notation.h"
//#############################################################################
// Shared Data Support
//
Derivation* DemolitionPack::GetClassDerivations()
{ static Derivation classDerivations(Rivet::GetClassDerivations(), "DemolitionPack");
return &classDerivations;
}
DemolitionPack::SharedData
DemolitionPack::DefaultData(
DemolitionPack::GetClassDerivations(),
DemolitionPack::GetMessageHandlers(),
DemolitionPack::GetAttributeIndex(),
DemolitionPack::StateCount,
(Entity::MakeHandler)DemolitionPack::Make
);
//#############################################################################
// Attribute Support
//
#if 0
const DemolitionPack::IndexEntry
DemolitionPack::AttributePointers[]=
{
ATTRIBUTE_ENTRY(DemolitionPack, DamageData, damageData)
};
DemolitionPack::AttributeIndexSet& DemolitionPack::GetAttributeIndex()
{
static DemolitionPack::AttributeIndexSet attributeIndex(ELEMENTS(DemolitionPack::AttributePointers), DemolitionPack::AttributePointers, Mover::GetAttributeIndex());
return attributeIndex;
}
#endif
//#############################################################################
// Model support
//
//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
//
void
DemolitionPack::MoveAndHunt(Scalar time_slice)
{
Line
distance_traveled;
distance_traveled = localOrigin.linearPosition;
//
//-----------------------------------------------------------------
// Apply the standard air resistance and gravity, then project the
// Projectile motion through the time slice and look for collisions
//-----------------------------------------------------------------
//
ApplyAirResistanceAndGravity();
Point3D old_position(localOrigin.linearPosition);
ApplyWorldAccelerations(time_slice);
//
//--------------------
// Do a collision test
//--------------------
//
MoveCollisionVolume();
BoxedSolidCollisionList*
collision_list = GetCurrentCollisions();
//
//---------------------------------------------------------------------
// If our solid didn't hit anything, and we are going fast enough, do a
// ray-cast
//---------------------------------------------------------------------
//
if (!collision_list->GetCollisionCount())
{
Line
line;
line = localOrigin.linearPosition;
Vector3D
step;
step.Subtract(localOrigin.linearPosition, old_position);
line = step;
Scalar
diameter = collisionTemplate->maxX - collisionTemplate->minX;
if (diameter < line.length)
{
CollideCenterOfMotion(&line, collision_list);
}
}
//
//-------------------------------
// Process each of the collisions
//-------------------------------
//
Damage collision_damage;
ProcessCollisionList(
collision_list,
time_slice,
old_position,
&collision_damage
);
(this->*deadReckoner)();
Vector3D
error;
error.Subtract(
projectedOrigin.linearPosition,
localOrigin.linearPosition
);
if (error.LengthSquared() > 0.5f)
{
ForceUpdate();
}
//
//----------------------
// Hunt for VTVs to kill
//----------------------
//
Check_Fpu();
Hunt(time_slice);
}
//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
//
void
DemolitionPack::Hunt(Scalar)
{
if ((lastPerformance - creationTime) >= fuseTime)
{
//
//---------------------------------
// Test against the tangible movers
//---------------------------------
//
Check(collisionAssistant);
CollisionAssistant::MovingEntityIterator
iterator(collisionAssistant);
Entity
*entity;
Check(collisionVolume);
while ((entity = iterator.ReadAndNext()) != NULL)
{
//
//------------------------------------------
// If the mover is not within range, no boom
//------------------------------------------
//
Vector3D
range;
range.Subtract(
entity->localOrigin.linearPosition,
localOrigin.linearPosition
);
if ((range.LengthSquared() >= detectionRadiusSquared) && ((lastPerformance - creationTime) <= (fuseTime + 60.0f)))
{
continue;
}
//
//----------------------------------
// We got a boom! Make an explosion
//----------------------------------
//
CondemnToDeathRow();
Check(application);
ResourceFile *resource_file = application->GetResourceFile();
Check(resource_file);
ResourceDescription
*explosion_res = resource_file->
FindResourceDescription(explosionResourceID);
Check(explosion_res);
explosion_res->Lock();
Explosion::MakeMessage exp_message(
Explosion::MakeMessageID,
sizeof(Explosion::MakeMessage),
ExplosionClassID,
EntityID::Null,
explosion_res->resourceID,
Explosion::DefaultFlags,
localOrigin,
entity->GetEntityID(),
shootingEntity->GetEntityID()
);
explosion_res->Unlock();
#if DEBUG_LEVEL>0
Explosion
*exp =
#endif
Explosion::Make(&exp_message);
Register_Object(exp);
//
//----------------------------------------------
// Send a damage message to whoever we hit
//----------------------------------------------
//
if ((lastPerformance - creationTime) <= (fuseTime + 60.0f))
{
iterator.First();
while ((entity = iterator.ReadAndNext()) != NULL)
{
if (entity->GetClassID() == RegisteredClass::VTVClassID)
{
VTV *vtv = Cast_Object(VTV*, entity);
Damage damage_data;
damage_data.damageForce.Subtract(
vtv->localOrigin.linearPosition,
localOrigin.linearPosition
);
if (damage_data.damageForce.LengthSquared() > blastRadiusSquared)
{
continue;
}
damage_data.damageForce.Normalize(damage_data.damageForce);
damage_data.damageForce *= concussiveForce;
damage_data.damageAmount = damageData.damageAmount;
damage_data.damageType = Damage::ExplosiveDamageType;
//
//------------------------------------------
// Send a damage message to the thing we hit
//------------------------------------------
//
Entity::TakeDamageMessage
take_damage(
Entity::TakeDamageMessageID,
sizeof(Entity::TakeDamageMessage),
shootingEntity->GetEntityID(),
0,
damage_data
);
entity->Dispatch(&take_damage);
}
}
break;
}
}
}
Check_Fpu();
}
//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
//
void
DemolitionPack::ProcessCollision(
Scalar time_slice,
BoxedSolidCollision &collision,
const Point3D &old_position,
Damage *damage
)
{
Scalar penetration,r;
Scalar elasticity = elasticityCoefficient;
Scalar friction = frictionCoefficient;
//
//-------------------------------------------------------------------------
// If we have hit a mover, adjust our velocity relative to it, unless we
// have collided with the VTV what dropped us, in which case we will ignore
// the hit
//-------------------------------------------------------------------------
//
BoxedSolid *box = collision.GetTreeVolume();
Check(box);
Simulation *sim = box->GetOwningSimulation();
Mover *mover = NULL;
if (sim && sim->IsDerivedFrom(*Mover::GetClassDerivations()))
{
mover = (Mover*)sim;
Check(mover);
if (mover == shootingEntity)
{
Check_Fpu();
return;
}
worldLinearVelocity -= mover->worldLinearVelocity;
}
//
//--------------------------------------------------------------------
// If we really have a collision, do a static bounce off of the normal
// generated
//--------------------------------------------------------------------
//
if (
collisionVolume->ProcessCollision(
collision,
worldLinearVelocity,
lastCollisionList,
&damage->surfaceNormal,
&penetration
)
)
{
Max_Clamp(penetration, time_slice);
r = penetration / time_slice;
Check_Fpu();
StaticBounce(
old_position,
time_slice,
r,
damage->surfaceNormal,
&elasticity,
minimumBounceSpeed,
&friction
);
//
//--------------------------
// Determine collision state
//--------------------------
//
if (!elasticity && !friction && !mover)
{
SetPerformance(&DemolitionPack::Hunt);
worldLinearVelocity = Vector3D::Identity;
worldLinearAcceleration = Vector3D::Identity;
localVelocity = Motion::Identity;
localAcceleration = Motion::Identity;
ForceUpdate();
mover = NULL;
}
}
if (mover)
{
worldLinearVelocity += mover->worldLinearVelocity;
}
Check_Fpu();
}
//#############################################################################
// Construction and Destruction
//
//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
//
DemolitionPack::DemolitionPack(
DemolitionPack::MakeMessage *creation_message,
DemolitionPack::SharedData &virtual_data
):
Rivet(creation_message, virtual_data)
{
Check_Pointer(this);
//
//------------------------
// Setup the initial state
//------------------------
//
SetValidFlag();
InterestZone *interest_zone;
Check(application);
Check(application->GetInterestManager());
interest_zone =
application->GetInterestManager()->GetInterestZone(interestZoneID);
Check(interest_zone);
localEnvironment = interest_zone->GetEnvironment();
Check(localEnvironment);
//
//
SetDeadReckoner(&DemolitionPack::AcceleratedDeadReckoner);
if (GetInstance() == ReplicantInstance)
{
SetPerformance(&DemolitionPack::DeadReckon);
}
else
{
SetPerformance(&DemolitionPack::MoveAndHunt);
}
//
// Initialize the Projectile variables
//
ResourceDescription *res =
application->GetResourceFile()->SearchList(
resourceID,
ResourceDescription::GameModelResourceType
);
Check(res);
res->Lock();
ModelResource* model = (ModelResource*)res->resourceAddress;
Check_Pointer(model);
blastRadiusSquared = model->blastRadiusSquared;
detectionRadiusSquared = model->detectionRadiusSquared;
fuseTime = model->fuseTime;
concussiveForce = model->concussiveForce;
damageData = model->damageData;
explosionResourceID = model->explosionResourceID;
res->Unlock();
HostManager *host_mgr = application->GetHostManager();
Check(host_mgr);
shootingEntity =
host_mgr->GetEntityPointer(creation_message->shootingEntity);
Check_Fpu();
}
//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
//
DemolitionPack*
DemolitionPack::Make(DemolitionPack::MakeMessage *creation_message)
{
return new DemolitionPack(creation_message);
}
//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
//
DemolitionPack::~DemolitionPack()
{
Check(this);
Check_Fpu();
}
//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
// CreateModelResource
//
int
DemolitionPack::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);
//
//-----------------------------------------------------------------------
// If we were not provided a buffer to write the model data into, we must
// create it ourselves. Then make sure that the mover stuff is read in
//-----------------------------------------------------------------------
//
ModelResource *local_model = model;
if (!local_model)
{
local_model = new ModelResource;
Register_Pointer(local_model);
}
if(
Rivet::CreateModelResource(
resource_file,
model_name,
model_file,
directories,
local_model
) == -1
)
{
Dump_And_Die:
if (!model)
{
Unregister_Pointer(local_model);
delete local_model;
}
Check_Fpu();
return -1;
}
//
//---------------------------------------
// Read in the damage amount for the ammo
//---------------------------------------
//
if(
!model_file->GetEntry(
"gamedata",
"BlastRadius",
&local_model->blastRadiusSquared
)
)
{
std::cout << model_name << " missing BlastRadius!\n";
goto Dump_And_Die;
}
{
local_model->blastRadiusSquared *= local_model->blastRadiusSquared;
}
if(
!model_file->GetEntry(
"gamedata",
"DetectionRadius",
&local_model->detectionRadiusSquared
)
)
{
std::cout << model_name << " missing DetectionRadius!\n";
goto Dump_And_Die;
}
else
{
local_model->detectionRadiusSquared *= local_model->detectionRadiusSquared;
}
if(
!model_file->GetEntry(
"gamedata",
"ConcussiveForce",
&local_model->concussiveForce
)
)
{
std::cout << model_name << " missing ConcussiveForce!\n";
goto Dump_And_Die;
}
if(
!model_file->GetEntry(
"gamedata",
"FuseTime",
&local_model->fuseTime
)
)
{
std::cout << model_name << " missing FuseTime!\n";
goto Dump_And_Die;
}
//
//-------------------------------------------------------------------------
// If we created the model buffer, then we have the responsibility to write
// it out to the resource file
//-------------------------------------------------------------------------
//
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
DemolitionPack::TestInstance() const
{
return IsDerivedFrom(*GetClassDerivations());
}