Clean, self-contained extraction of the BattleTech-specific work from the
reverse-engineering workspace -- engine + game + content + build, with nothing
from Red Planet or the raw archive dumps. Builds green (Win32) and runs the
single-player drive->animate->target->fire->damage->destroy loop out of the box.
Layout:
engine/ MUNGA + MUNGA_L4 shared 2007 engine, carrying our BT render/loader
work (bgfload/L4D3D/L4VIDEO: BSL bit-slice decode, LOD/ground/shadow
models) + image codec; the minimal rp/ headers the audio HAL needs
game/ reconstructed BT logic + surviving-original BT source + fwd shims
+ WinMain launcher
content/ full runtime tree (BTL4.RES, VIDEO/, GAUGE/, AUDIO/, eggs, BTDPL.INI)
docs/ format specs + reconstruction ledgers
reference/ raw Ghidra pseudocode (recon source-of-truth) + decomp exporter
tools/ MP console emulator + map/resource scanners
One top-level CMake builds munga_engine lib + bt410_l4 game lib + btl4.exe.
All paths relativized (186 fwd shims + ~437 CMake abs paths -> repo-relative);
DXSDK is the one external, overridable via -DDXSDK. Verified: builds to a
byte-identical 2.27MB exe and runs combat (TARGET DESTROYED, 0 crashes) against
the bundled content.
Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
164 lines
7.1 KiB
C++
164 lines
7.1 KiB
C++
//============================================================================//
|
|
// File: projtile.hpp //
|
|
// Project: BattleTech //
|
|
// Contents: In-flight projectile entity base (position/velocity/lifetime/ //
|
|
// collision); parent of Missile. //
|
|
//----------------------------------------------------------------------------//
|
|
// Date Who Modification //
|
|
// -------- --- ------------------------------------------------------------//
|
|
// 04/13/95 JM Initial coding. //
|
|
//----------------------------------------------------------------------------//
|
|
// Copyright (C) 1995, Virtual World Entertainment, Inc. All Rights reserved //
|
|
// PROPRIETARY AND CONFIDENTIAL //
|
|
//============================================================================//
|
|
//
|
|
// RECONSTRUCTED from the shipped binary (Ghidra pseudo-C, module cluster
|
|
// @004be1bc-@004be3b4 in part_013.c). NO surviving header exists for this base
|
|
// -- only the test fragment PROJTILE.TCP (Projectile::TestClass). The class
|
|
// declaration is INFERRED from:
|
|
// * the decompiled ctor @004be1bc, dtor @004be358 and allocator @004be384
|
|
// * the derived Missile (missile.hpp/cpp), whose integrator @004bef78 reads
|
|
// these base fields (position @0x100, velocity @0x1DC, segment/world @0x300)
|
|
// * PROJTILE.TCP (Projectile::TestClass -- note: takes NO argument)
|
|
// Member names past the Entity base are best-effort and flagged.
|
|
//
|
|
// Inheritance chain established from the decomp:
|
|
// Entity (FUN_004234f0 base ctor) -> Projectile (vtable @00512a5c, 0x340)
|
|
// -> Missile (vtable @00512f2c, 0x368)
|
|
// The ctor stamps vtable PTR_FUN_00512a5c, registers the projectile into the
|
|
// owning world-segment table, snapshots the launch kinematics out of the spawn
|
|
// descriptor, and installs one of two Performance variants (authoritative vs
|
|
// network-ghost) selected by the entity flags (this+0x28 & 0xC == 4).
|
|
//
|
|
// Object byte offsets (this is an int* in the decomp, word index in parens).
|
|
// Everything below +0x300 is the Entity base (transform @0x100, velocity @0x1DC,
|
|
// thrust-velocity @0x1E8, born/spawn ticks @0x10/@0x14, status flags @0x18).
|
|
//
|
|
|
|
#if !defined (PROJTILE_HPP)
|
|
# define PROJTILE_HPP
|
|
|
|
# if !defined(ENTITY_HPP)
|
|
# include <entity.hpp> // Projectile : Entity
|
|
# endif
|
|
|
|
# if !defined(POINT3D_HPP)
|
|
# include <point3d.hpp>
|
|
# endif
|
|
|
|
//######################### Forward Class Declarations ########################
|
|
class Mech;
|
|
class Segment;
|
|
|
|
//###########################################################################
|
|
//######################### CLASS -- Projectile #######################
|
|
//###########################################################################
|
|
//
|
|
// (vtable @00512a5c, ctor @004be1bc, dtor @004be358, allocator @004be384.)
|
|
//
|
|
class Projectile:
|
|
public Entity
|
|
{
|
|
//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
|
|
// Shared Data Support
|
|
//
|
|
public:
|
|
static Derivation ClassDerivations; // IsDerivedFrom tag 0x512980
|
|
static Receiver::MessageHandlerSet MessageHandlers;
|
|
static AttributeIndexSet AttributeIndex;
|
|
static SharedData DefaultData; // resolved as &DAT_005129b0
|
|
|
|
// Entity factory hook (Entity::SharedData requires a MakeHandler).
|
|
static Entity *Make(MakeMessage *creation_message);
|
|
|
|
//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
|
|
// Model Support
|
|
//
|
|
public:
|
|
typedef void
|
|
(Projectile::*Performance)(Scalar time_slice);
|
|
|
|
// The default per-frame integrate-and-collide pass. Installed by the
|
|
// ctor as the active Performance: PTR_LAB_005129e8 when authoritative
|
|
// (flags & 0xC == 4), PTR_LAB_005129f4 for a network ghost. Missile
|
|
// supplies its own override (Missile::MoveAndCollide @004bef78).
|
|
void
|
|
MoveAndCollide(Scalar time_slice);
|
|
|
|
void
|
|
SetPerformance(Performance performance)
|
|
{
|
|
Check(this);
|
|
activePerformance = (Simulation::Performance)performance;
|
|
}
|
|
|
|
//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
|
|
// TestClass Support (PROJTILE.TCP)
|
|
//
|
|
public:
|
|
static Logical
|
|
TestClass(); // PROJTILE.TCP: returns True
|
|
Logical
|
|
TestInstance() const; // @004be3b4
|
|
|
|
//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
|
|
// Construction and Destruction
|
|
//
|
|
public:
|
|
Projectile( // @004be1bc
|
|
int owner, // spawning weapon / streamed-entity ctx
|
|
const char *spawn_descriptor // launch descriptor record
|
|
);
|
|
~Projectile(); // @004be358
|
|
|
|
// @004be384 -- allocate (0x340 bytes) and construct with &DAT_005129b0.
|
|
static Projectile *
|
|
New(int spawn_context);
|
|
|
|
//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
|
|
// Model / animation update binding (Entity sub-object)
|
|
//
|
|
// this[0x94..0x97] = a bound member-function ("model update" callback,
|
|
// PTR_FUN_005129dc) invoked each frame; 0x250 is its context pointer.
|
|
//
|
|
protected:
|
|
void *modelUpdateContext; // @0x250 (word 0x94)
|
|
|
|
// hosted-subsystem roster (used by Missile; Projectile-level per the decomp)
|
|
int subsystemCount; // @0x124 (word 0x49)
|
|
Subsystem **subsystems; // @0x128 (word 0x4a)
|
|
|
|
//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
|
|
// Recovered internal helpers (engine-internal artifacts in the decomp;
|
|
// declared here so the recovered ctor / integrator compile. Bodies are
|
|
// reconstructed structurally -- the world/segment/motion plumbing lives in
|
|
// the Entity engine layer).
|
|
//
|
|
protected:
|
|
void InitSegmentLink(void *link); // FUN_0041db7c
|
|
void SetStatusLevel(int level); // FUN_0041bbd8 (status alarm)
|
|
void *ResolveWorld(void *app_context); // owning world / segment system
|
|
void *ResolveMotionSource(void *app_context); // FUN_00433ed4
|
|
void BindModelUpdate(void *callback); // bind model-update member fn
|
|
void IntegrateMotion(); // FUN_00421b2c
|
|
void AdvanceModel(Scalar time_slice); // FUN_00421bac
|
|
Entity *CollisionQuery(Scalar time_slice); // FUN_0042291c
|
|
void Retire(); // FUN_0042061c
|
|
|
|
//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
|
|
// Projectile-specific data appended past the Entity base (offsets best-effort).
|
|
//
|
|
protected:
|
|
void *world; // @0x300 (word 0xC0) owning world / segment system
|
|
Segment *currentSegment; // @0x304 (word 0xC1) segment node for this cell
|
|
int segmentIndex; // @0x308 (word 0xC2) descriptor +0x84
|
|
int sourceEntity; // @0x30C (word 0xC3) descriptor +0x88 (firing entity)
|
|
int sourceWeapon; // @0x310 (word 0xC4) descriptor +0x8C (firing weapon)
|
|
Point3D launchPosition; // @0x314 (word 0xC5) descriptor +0x90
|
|
Vector3D launchVelocity; // @0x320 (word 0xC8) descriptor +0x9C
|
|
Vector3D aimDirection; // @0x32C (word 0xCB) descriptor +0xA8
|
|
int modelIndex; // @0x338 (word 0xCE) descriptor +0xB4 (tracer/LOD model)
|
|
int damageRecord; // @0x33C (word 0xCF) descriptor +0xB8 (damage/team id)
|
|
};
|
|
#endif
|