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:
+503
@@ -0,0 +1,503 @@
|
||||
#include "rp.h"
|
||||
#pragma hdrstop
|
||||
|
||||
#include "rivet.h"
|
||||
#include "..\munga\line.h"
|
||||
#include "..\munga\explode.h"
|
||||
#include "..\munga\boxsolid.h"
|
||||
#include "..\munga\subsystm.h"
|
||||
#include "..\munga\app.h"
|
||||
#include "..\munga\hostmgr.h"
|
||||
#include "..\munga\interest.h"
|
||||
#include "..\munga\notation.h"
|
||||
|
||||
//#############################################################################
|
||||
// Shared Data Support
|
||||
//
|
||||
Derivation* Rivet::GetClassDerivations()
|
||||
{ static Derivation classDerivations(Mover::GetClassDerivations(), "Rivet");
|
||||
return &classDerivations;
|
||||
}
|
||||
|
||||
|
||||
Rivet::SharedData
|
||||
Rivet::DefaultData(
|
||||
Rivet::GetClassDerivations(),
|
||||
Rivet::GetMessageHandlers(),
|
||||
Rivet::GetAttributeIndex(),
|
||||
Rivet::StateCount,
|
||||
(Entity::MakeHandler)Rivet::Make
|
||||
);
|
||||
|
||||
//#############################################################################
|
||||
// Attribute Support
|
||||
//
|
||||
const Rivet::IndexEntry
|
||||
Rivet::AttributePointers[]=
|
||||
{
|
||||
ATTRIBUTE_ENTRY(Rivet, DamageData, damageData)
|
||||
};
|
||||
|
||||
Rivet::AttributeIndexSet& Rivet::GetAttributeIndex()
|
||||
{
|
||||
static Rivet::AttributeIndexSet attributeIndex(ELEMENTS(Rivet::AttributePointers), Rivet::AttributePointers, Mover::GetAttributeIndex());
|
||||
return attributeIndex;
|
||||
}
|
||||
|
||||
//#############################################################################
|
||||
// Model support
|
||||
//
|
||||
//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
|
||||
//
|
||||
void
|
||||
Rivet::MoveToTarget(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();
|
||||
ApplyWorldAccelerations(time_slice);
|
||||
|
||||
Vector3D
|
||||
motion_vector;
|
||||
motion_vector.Subtract(
|
||||
localOrigin.linearPosition,
|
||||
distance_traveled.origin
|
||||
);
|
||||
distance_traveled = motion_vector;
|
||||
Check(&distance_traveled);
|
||||
localToWorld = localOrigin;
|
||||
|
||||
BoxedSolid
|
||||
*target = FindBoxedSolidHitBy(&distance_traveled, shootingEntity);
|
||||
//
|
||||
//-------------------------------------------------------
|
||||
// If the projectile hit something, sentence it to death!
|
||||
//-------------------------------------------------------
|
||||
//
|
||||
if (target)
|
||||
{
|
||||
CondemnToDeathRow();
|
||||
Origin
|
||||
explode_origin = localOrigin;
|
||||
distance_traveled.FindEnd(&explode_origin.linearPosition);
|
||||
|
||||
//
|
||||
//-----------------------
|
||||
// Find the entity we hit
|
||||
//-----------------------
|
||||
//
|
||||
Simulation
|
||||
*sim = target->GetOwningSimulation();
|
||||
Check(sim);
|
||||
Entity
|
||||
*entity;
|
||||
if (sim->IsDerivedFrom(*Subsystem::GetClassDerivations()))
|
||||
{
|
||||
Check((Subsystem*)sim);
|
||||
entity = ((Subsystem*)sim)->GetEntity();
|
||||
}
|
||||
else if (sim->IsDerivedFrom(*Mover::GetClassDerivations()))
|
||||
{
|
||||
Mover
|
||||
*mover = (Mover*)sim;
|
||||
Check(mover);
|
||||
|
||||
Vector3D
|
||||
impact_speed;
|
||||
|
||||
impact_speed.Subtract(worldLinearVelocity, mover->worldLinearVelocity);
|
||||
Scalar
|
||||
damage_scale = impact_speed.Length() / 350.0f; // HACK
|
||||
damageData.damageAmount *= damage_scale*damage_scale;
|
||||
entity = mover;
|
||||
}
|
||||
else
|
||||
{
|
||||
entity = (Entity*)sim;
|
||||
}
|
||||
Check(entity);
|
||||
|
||||
//
|
||||
//------------------
|
||||
// Make an Explosion
|
||||
//------------------
|
||||
//
|
||||
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,
|
||||
explode_origin,
|
||||
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 the thing we hit
|
||||
//------------------------------------------
|
||||
//
|
||||
Entity::TakeDamageMessage
|
||||
take_damage(
|
||||
Entity::TakeDamageMessageID,
|
||||
sizeof(Entity::TakeDamageMessage),
|
||||
shootingEntity->GetEntityID(),
|
||||
0,
|
||||
damageData
|
||||
);
|
||||
entity->Dispatch(&take_damage);
|
||||
}
|
||||
|
||||
//
|
||||
//---------------------------------------------
|
||||
// Otherwise, see if we have to update anything
|
||||
//---------------------------------------------
|
||||
//
|
||||
else
|
||||
{
|
||||
UpdateLocalMotion();
|
||||
|
||||
//
|
||||
//------------------------------------------------------------------------
|
||||
// Run the dead reckoner, and then see how far apart the two positions are
|
||||
//------------------------------------------------------------------------
|
||||
//
|
||||
(this->*deadReckoner)();
|
||||
Vector3D
|
||||
error;
|
||||
error.Subtract(
|
||||
projectedOrigin.linearPosition,
|
||||
localOrigin.linearPosition
|
||||
);
|
||||
if (error.LengthSquared() > 0.1f)
|
||||
{
|
||||
ForceUpdate();
|
||||
}
|
||||
}
|
||||
|
||||
//
|
||||
//---------------------------------------------------
|
||||
// If the bullet has outlived its lifetime, delete it
|
||||
//---------------------------------------------------
|
||||
//
|
||||
if ((Now() - creationTime) > RIVET_MAXIMUM_LIFETIME)
|
||||
{
|
||||
CondemnToDeathRow();
|
||||
}
|
||||
Check_Fpu();
|
||||
}
|
||||
|
||||
//#############################################################################
|
||||
// Construction and Destruction
|
||||
//
|
||||
|
||||
//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
|
||||
//
|
||||
Rivet::Rivet(
|
||||
Rivet::MakeMessage *creation_message,
|
||||
Rivet::SharedData &virtual_data
|
||||
):
|
||||
Mover(creation_message, virtual_data)
|
||||
{
|
||||
Check_Pointer(this);
|
||||
|
||||
//
|
||||
//------------------------
|
||||
// Setup the initial state
|
||||
//------------------------
|
||||
//
|
||||
|
||||
SetValidFlag();
|
||||
|
||||
Check(application);
|
||||
Check(application->GetInterestManager());
|
||||
InterestZone
|
||||
*interest_zone = application->GetInterestManager()->
|
||||
GetInterestZone(interestZoneID);
|
||||
Check(interest_zone);
|
||||
|
||||
localEnvironment = interest_zone->GetEnvironment();
|
||||
Check(localEnvironment);
|
||||
|
||||
//
|
||||
//
|
||||
SetDeadReckoner(&Rivet::AcceleratedDeadReckoner);
|
||||
if (GetInstance() == ReplicantInstance)
|
||||
{
|
||||
SetPerformance(&Rivet::DeadReckon);
|
||||
}
|
||||
else
|
||||
{
|
||||
SetPerformance(&Rivet::MoveToTarget);
|
||||
StartCollisionAssistant();
|
||||
}
|
||||
|
||||
//
|
||||
// Initialize the Projectile variables
|
||||
//
|
||||
ResourceDescription *res =
|
||||
application->GetResourceFile()->SearchList(
|
||||
resourceID,
|
||||
ResourceDescription::GameModelResourceType
|
||||
);
|
||||
Check(res);
|
||||
res->Lock();
|
||||
|
||||
ModelResource
|
||||
*model = (ModelResource*)res->resourceAddress;
|
||||
Check_Pointer(model);
|
||||
|
||||
damageData.damageType = model->damageData.damageType;
|
||||
damageData.damageAmount = model->damageData.damageAmount;
|
||||
damageData.damageForce = Vector3D::Identity;
|
||||
damageData.surfaceNormal.x = 1.0f;
|
||||
damageData.surfaceNormal.y = 0.0f;
|
||||
damageData.surfaceNormal.z = 0.0f;
|
||||
damageData.impactPoint = Point3D::Identity;
|
||||
explosionResourceID = model->explosionResourceID;
|
||||
|
||||
res->Unlock();
|
||||
|
||||
HostManager
|
||||
*host_mgr = application->GetHostManager();
|
||||
Check(host_mgr);
|
||||
|
||||
shootingEntity =
|
||||
host_mgr->GetEntityPointer(creation_message->shootingEntity);
|
||||
Check_Fpu();
|
||||
}
|
||||
|
||||
//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
|
||||
//
|
||||
Rivet*
|
||||
Rivet::Make(Rivet::MakeMessage *creation_message)
|
||||
{
|
||||
return new Rivet(creation_message);
|
||||
}
|
||||
|
||||
//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
|
||||
//
|
||||
Rivet::~Rivet()
|
||||
{
|
||||
Check(this);
|
||||
Check_Fpu();
|
||||
}
|
||||
|
||||
//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
|
||||
// CreateModelResource
|
||||
//
|
||||
int
|
||||
Rivet::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(
|
||||
Mover::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",
|
||||
"DamageAmount",
|
||||
&local_model->damageData.damageAmount
|
||||
)
|
||||
)
|
||||
{
|
||||
std::cout << model_name << " missing DamageAmount!\n";
|
||||
goto Dump_And_Die;
|
||||
}
|
||||
|
||||
//
|
||||
//----------------------------------------------------------------------
|
||||
// Read in the Model Filename of the Explosion renderable, then find its
|
||||
// resource ID in the resource file
|
||||
//----------------------------------------------------------------------
|
||||
//
|
||||
const char
|
||||
*damage_type;
|
||||
if(
|
||||
!model_file->GetEntry(
|
||||
"gamedata",
|
||||
"DamageType",
|
||||
&damage_type
|
||||
)
|
||||
)
|
||||
{
|
||||
std::cout << model_name << " missing DamageType!\n";
|
||||
goto Dump_And_Die;
|
||||
}
|
||||
if (!stricmp(damage_type, "CollisionDamage"))
|
||||
{
|
||||
local_model->damageData.damageType = Damage::CollisionDamageType;
|
||||
}
|
||||
else if (!stricmp(damage_type, "BallisticDamage"))
|
||||
{
|
||||
local_model->damageData.damageType = Damage::BallisticDamageType;
|
||||
}
|
||||
else if (!stricmp(damage_type, "ExplosiveDamage"))
|
||||
{
|
||||
local_model->damageData.damageType = Damage::ExplosiveDamageType;
|
||||
}
|
||||
else if (!stricmp(damage_type, "LaserDamage"))
|
||||
{
|
||||
local_model->damageData.damageType = Damage::LaserDamageType;
|
||||
}
|
||||
else if (!stricmp(damage_type, "EnergyDamage"))
|
||||
{
|
||||
local_model->damageData.damageType = Damage::EnergyDamageType;
|
||||
}
|
||||
else
|
||||
{
|
||||
std::cout << model_name << " has an unknown DamageType of " << damage_type
|
||||
<< std::endl;
|
||||
goto Dump_And_Die;
|
||||
}
|
||||
//
|
||||
//----------------------------
|
||||
// Init damage fields
|
||||
//----------------------------
|
||||
//
|
||||
local_model->damageData.damageForce = Vector3D::Identity;
|
||||
local_model->damageData.surfaceNormal.x = 0.0f;
|
||||
local_model->damageData.surfaceNormal.y = 1.0f;
|
||||
local_model->damageData.surfaceNormal.z = 0.0f;
|
||||
local_model->damageData.impactPoint = Vector3D::Identity;
|
||||
|
||||
//
|
||||
//----------------------------------------------------------------------
|
||||
// Read in the Model Filename of the Explosion renderable, then find its
|
||||
// resource ID in the resource file
|
||||
//----------------------------------------------------------------------
|
||||
//
|
||||
const char
|
||||
*explosion;
|
||||
if(
|
||||
!model_file->GetEntry(
|
||||
"gamedata",
|
||||
"ExplosionModelFile",
|
||||
&explosion
|
||||
)
|
||||
)
|
||||
{
|
||||
std::cout << model_name << " missing ExplosionModelFile!\n";
|
||||
goto Dump_And_Die;
|
||||
}
|
||||
ResourceDescription
|
||||
*res = resource_file->FindResourceDescription(
|
||||
explosion,
|
||||
ResourceDescription::ModelListResourceType
|
||||
);
|
||||
if (!res)
|
||||
{
|
||||
std::cout << model_name << " cannot find " << explosion
|
||||
<< " in resource file!\n";
|
||||
goto Dump_And_Die;
|
||||
}
|
||||
local_model->explosionResourceID = res->resourceID;
|
||||
|
||||
//
|
||||
//-------------------------------------------------------------------------
|
||||
// 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
|
||||
Rivet::TestInstance() const
|
||||
{
|
||||
return IsDerivedFrom(*GetClassDerivations());
|
||||
}
|
||||
Reference in New Issue
Block a user