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:
+581
@@ -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());
|
||||
}
|
||||
Reference in New Issue
Block a user