Files
arcattackandClaude Opus 4.8 7b7d465e5e Initial commit: bt411 -- standalone Windows BattleTech (Tesla 4.10 port)
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>
2026-07-05 21:03:40 -05:00

481 lines
12 KiB
C++

#pragma once
#include "node.h"
#include "bndgbox.h"
#include "envirnmt.h"
#include "network.h"
#include "slot.h"
class BoundingBoxTree;
//##########################################################################
//######## Support types for InterestOrigin & InterestManager ########
//##########################################################################
enum InterestType
{
VisualInterestType,
AudioInterestType,
GaugeInterestType,
CollisionInterestType
};
typedef int InterestDepth;
const InterestDepth DefaultInterestDepth = 1;
enum InterestPriority
{
LowInterestPriority = 0,
HighInterestPriority
};
//##########################################################################
//########################### LatticeZone ############################
//##########################################################################
class ExtentBox;
//
// HACK - Lattice zones support being connected to each in variously
// interesting ways. For now there is only one.
//
class LatticeZone:
public Plug
{
public:
LatticeZone(const ExtentBox &extents);
~LatticeZone();
private:
TaggedBoundingBoxOf<LatticeZone>
boundingBox;
};
//##########################################################################
//######################### EnvironmentZone ##########################
//##########################################################################
class EnvironmentZone:
public LatticeZone
{
//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
// Constructor, Destructor, and Testing
//
public:
EnvironmentZone(
const ExtentBox &extents,
const Environment &environment
);
~EnvironmentZone();
Logical
TestInstance() const;
//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
// HACK - Accessors
//
public:
Environment*
GetEnvironment()
{return &environment;}
//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
// Private data
//
private:
Environment
environment;
};
//##########################################################################
//########################### InterestZone ###########################
//##########################################################################
class BoxedSolidTree;
class CollisionOrigin;
//
// HACK - Right now the interest zone holds data that would normally
// be within its own zone, i.e., environment zones, collision zones,
// audio zones, etc..., The interest zone should hold sockets to
// zones which are included in its interesting "domain"
//
class InterestZone:
public LatticeZone
{
//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
// Constructor, Destructor, and Testing
//
public:
InterestZone(
const ExtentBox &extents,
InterestZoneID interest_zone_id,
BoxedSolidTree *collision_root,
EnvironmentZone *environment_zone,
BoundingBoxTree *existance_root
);
~InterestZone();
Logical
TestInstance() const;
//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
// HACK - Accessors
//
public:
InterestZoneID
GetInterestZoneID();
BoxedSolidTree*
GetCollisionRoot();
Environment*
GetEnvironment();
BoundingBoxTree*
GetExistanceRoot();
void
AdoptCollisionOrigin(CollisionOrigin *collision_origin);
CollisionOrigin*
GetCollisionOrigin();
//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
// Private data
//
private:
InterestZoneID
interestZoneID;
BoxedSolidTree
*collisionRoot;
EnvironmentZone
*environmentZone;
CollisionOrigin
*collisionOrigin;
BoundingBoxTree
*existanceRoot;
};
//~~~~~~~~~~~~~~~~~~~~~~~~~~~ InterestZone inlines ~~~~~~~~~~~~~~~~~~~~~~~~~
inline InterestZoneID
InterestZone::GetInterestZoneID()
{
Check(this);
return interestZoneID;
}
inline BoxedSolidTree*
InterestZone::GetCollisionRoot()
{
Check(this);
return collisionRoot;
}
inline Environment*
InterestZone::GetEnvironment()
{
Check(this);
Check(environmentZone);
return environmentZone->GetEnvironment();
}
inline BoundingBoxTree*
InterestZone::GetExistanceRoot()
{
Check(this);
return existanceRoot;
}
inline void
InterestZone::AdoptCollisionOrigin(CollisionOrigin *collision_origin)
{
Check(this);
Verify(collisionOrigin == NULL);
Check_Pointer(collision_origin);
collisionOrigin = collision_origin;
}
inline CollisionOrigin*
InterestZone::GetCollisionOrigin()
{
Check(this);
return collisionOrigin;
}
//##########################################################################
//########################### InterestArena ##########################
//##########################################################################
//
// HACK - The interest arena maintains sets of interest zones. Since
// we only have one interest zone at present the interest arena has
// only the capability to reference one interest zone
//
class InterestArena:
public Node
{
//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
// Constructor, Destructor, and Testing
//
public:
InterestArena(InterestZone *interest_zone);
~InterestArena();
Logical
TestInstance() const;
//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
// HACK - Accessors
//
public:
InterestZoneID
GetInterestZoneID();
BoxedSolidTree*
GetCollisionRoot();
Environment*
GetEnvironment();
//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
// Interest Zone and Entity support
//
public:
//
//--------------------------------------------------------------
// Boolean IncludesInterestZone(InterestArena, InterestZoneID)
//
// Description:
// Does the interest arena include the interest zone?
//
// Parameters:
// InterestArena - reference to the interest arena.
// InterestZoneID - id of the interest zone.
//
// Returns:
// True if it does, otherwise False
//--------------------------------------------------------------
//
//
//--------------------------------------------------------------
// Boolean IncludesPosition(InterestArena, 3DPosition)
//
// Description:
// Does the interest arena include the spatial position?
//
// Parameters:
// InterestArena - reference to the interest arena.
// 3DPosition- the spatial position.
//
// Returns:
// True if it does, otherwise False
//--------------------------------------------------------------
//
//
//--------------------------------------------------------------
// ArenaEntityList GetArenaList(InterestArena)
//
// Description:
// Returns a list of resident entities and associated attributes
// based on interest zone connectivity. The actual return will
// probably by a safe iterator, meaning that it is resilient to
// changes in the underlying data structures.
//
// Parameters:
// Reference to the interest arena.
//
// Return:
// ArenaEntityList - a list of resident entities and extracted
// data from interest zone connectivity.
//--------------------------------------------------------------
//
//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
// Private data
//
private:
SlotOf<InterestZone*>
interestZoneSocket;
};
//~~~~~~~~~~~~~~~~~~~~~~~~~~~ InterestArena inlines ~~~~~~~~~~~~~~~~~~~~~~~~
inline InterestZoneID
InterestArena::GetInterestZoneID()
{
Check(&interestZoneSocket);
Check(interestZoneSocket.GetCurrent());
return interestZoneSocket.GetCurrent()->GetInterestZoneID();
}
inline BoxedSolidTree*
InterestArena::GetCollisionRoot()
{
Check(&interestZoneSocket);
Check(interestZoneSocket.GetCurrent());
return interestZoneSocket.GetCurrent()->GetCollisionRoot();
}
inline Environment*
InterestArena::GetEnvironment()
{
Check(&interestZoneSocket);
Check(interestZoneSocket.GetCurrent());
return interestZoneSocket.GetCurrent()->GetEnvironment();
}
//##########################################################################
//########################### LatticeManager #########################
//##########################################################################
//
// HACK - The lattice manager managers connected lattices of zones
// of a particular type
//
class LatticeManager:
public Node
{
//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
// Constructor, Destructor, and Testing
//
public:
LatticeManager();
~LatticeManager();
};
//##########################################################################
//####################### InterestLatticeManager #####################
//##########################################################################
class EntityID;
class ResourceFile;
//
// HACK - the interest lattice manager manages the lattice of interest
// zones. Right now, is stubbed out for one interest zone.
//
class InterestLatticeManager:
public LatticeManager
{
//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
// Constructor, Destructor, and Testing
//
public:
InterestLatticeManager();
~InterestLatticeManager();
Logical
TestInstance() const;
//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
// Interest arena and entity support
//
public:
//
//--------------------------------------------------------------
// InterestArena
// MakeInterestArena(OriginInterestZoneID, Type, DepthCalibration)
//
// Description:
// Establishes an interest arena the locus of which is an interest
// zone, The arena is established with a type and depth
// specification (see interest manager).
//
// Parameters:
// OriginInterestZoneID- id of the interest zone.
// Type - a type of interest.
// DepthCalibration - a specification of the "depth" or "cost" associated
// with extent of the arena.
//
// Return:
// InterestArena - a reference to the created interest arena.
//--------------------------------------------------------------
//
InterestArena*
MakeInterestArena(
InterestZoneID,
InterestType,
InterestDepth
);
#if 0
//
//--------------------------------------------------------------
// DestroyInterestArena(InterestArena)
//
// Description:
// Destroys the interest arena.
//
// Parameters:
// InterestArena - Reference to the interest arena.
// UpdateInterestArena(InterestArena, DepthCalibration)
//
// Description:
// Updates the interest arenas internal data structures. This method
// is called by the interest manager.
//
// Parameters:
// InterestArena - Reference to the interest arena.
// DepthCalibration - new depth of arena extent.
//--------------------------------------------------------------
//
void
DestroyInterestArena(InterestArena*);
#endif
//
//--------------------------------------------------------------
// InterestZoneID
// SearchForEntityInterestZone(OriginInterestZoneID, EntityID)
//
// Description:
// If an entity has changed interest zones (its current location
// is not within the bounding volume of it interest zone) then
// this method searches prior adjacent interest zones for the entity.
//
// Parameters:
// OriginInterestZoneID - id of the interest zone to begin the
// search from.
// EntityID - id of the entity.
//
// Return:
// A reference to the interest zone if found, otherwise NULL.
//--------------------------------------------------------------
//
InterestZoneID
SearchForEntityInterestZone(
InterestZoneID old_interest_zone_ID,
const EntityID &entityID
);
//
//--------------------------------------------------------------
// InterestZoneID
//--------------------------------------------------------------
//
InterestZone*
GetInterestZone(InterestZoneID interest_zone_ID);
//
//--------------------------------------------------------------
// HACK ******************
//--------------------------------------------------------------
//
static void
CreateZoneResources(
ResourceFile *resource_file,
NotationFile *zone_notation_file
);
//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
// Private data
//
private:
SlotOf<InterestZone*>
interestZoneSocket;
};