Files
BT412/engine/MUNGA/DAMAGE.h
T
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

385 lines
7.5 KiB
C++

#pragma once
#include "point3d.h"
#include "node.h"
#include "normal.h"
#include "cstr.h"
#include "table.h"
#include "schain.h"
#include "simulate.h"
class MaterialList;
class EntitySegment;
class ExplosionTable;
class Simulation;
class MemoryStream;
class NotationFile;
struct ResourceDirectories;
class Entity;
//##########################################################################
//########################### Damage #################################
//##########################################################################
class Damage
{
public:
enum {
CollisionDamageType,
BallisticDamageType,
ExplosiveDamageType,
LaserDamageType,
EnergyDamageType,
DamageTypeCount
};
Enumeration
damageType;
Scalar
damageAmount;
Vector3D
damageForce;
Normal
surfaceNormal;
// impact point should be in the global coordinate space.
Point3D
impactPoint;
//
// burst count should be thought of as number of times
// to apply the damage.
//
int
burstCount;
Damage();
};
//##########################################################################
//######################### MaterialList #############################
//##########################################################################
class MaterialList :
public Plug
{
public:
typedef PlugOf<CString> CStringPlug;
typedef SChainOf<CStringPlug*>
CStringSocket;
typedef SChainIteratorOf<CStringPlug*>
CStringSocketIterator;
protected:
CStringSocketIterator*
listIterator;
CStringSocket
materialList;
public:
MaterialList();
~MaterialList();
void
DeletePlugs()
{Check(this); listIterator->DeletePlugs();}
void
Add(CStringPlug *new_plug)
{Check(this); materialList.Add(new_plug);}
void
First()
{ Check(this);listIterator->First();}
void
Last()
{Check(this); listIterator->Last(); }
CString*
ReadAndNext()
{
Check(this);
if (!listIterator->GetCurrent())
return NULL;
else
return listIterator->ReadAndNext()->GetPointer();
}
CString*
GetCurrent()
{
Check(this);
if (!listIterator->GetCurrent())
return NULL;
else
return listIterator->GetCurrent()->GetPointer();
}
void
Next()
{Check(this); if(listIterator->GetCurrent()) listIterator->Next();}
};
//##########################################################################
//################# DamageZone::UpdateRecord #########################
//##########################################################################
struct DamageZone__UpdateRecord
{
public:
size_t recordLength;
int damageZoneIndex;
Scalar damageLevel;
Enumeration damageZoneState;
Enumeration damageZoneGraphicState;
LWord changedFlags;
};
//##########################################################################
//######################### DamageZone ###############################
//##########################################################################
class DamageZone:
public Node
{
protected:
Simulation*
owningSimulation;
//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
// State Support
//
private:
StateIndicator
damageZoneState;
StateIndicator
damageZoneGraphicState;
public:
enum{
ExistsGraphicState = 0,
DestroyedGraphicState,
GoneGraphicState,
GraphicStateCount
};
enum{
DefaultState = 0,
BurningState,
DamageStateCount
};
StateIndicator*
GetGraphicStatePointer()
{Check(this); return &damageZoneGraphicState;}
Enumeration
GetDamageZoneState()
{Check(this); return damageZoneState.GetState();}
void
SetDamageZoneState(Enumeration new_state)
{Check(this); damageZoneState.SetState(new_state); }
Enumeration
GetGraphicState()
{Check(this); return damageZoneGraphicState.GetState();}
virtual void
SetGraphicState(Enumeration new_state)
{
Check(this);
damageZoneGraphicState.SetState(new_state);
SetGraphicStateChangedFlag();
}
//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
// Flag Support
//
public:
enum {
DamageLevelChangedBit = 2,
GraphicStateChangedBit,
NextBit
};
enum {
DamageLevelChangedFlag = 1 << DamageLevelChangedBit,
GraphicStateChangedFlag = 1 << GraphicStateChangedBit
};
Logical
DamageLevelChanged() const
{Check(this); return ((changedFlags & DamageLevelChangedFlag) != 0); }
Logical
GraphicStateChanged() const
{Check(this); return ((changedFlags & GraphicStateChangedFlag) != 0); }
void
SetDamageLevelChangedFlag()
{Check(this); changedFlags |= DamageLevelChangedFlag; }
void
SetGraphicStateChangedFlag()
{Check(this); changedFlags |= GraphicStateChangedFlag; }
void
ResetChangedFlags()
{Check(this); changedFlags = 0; }
LWord
changedFlags;
//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
// Update Support
//
public:
typedef DamageZone__UpdateRecord UpdateRecord;
virtual void
ReadUpdateRecord(UpdateRecord *message);
virtual void
WriteUpdateRecord(UpdateRecord *message);
//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
// Material Support
//
public:
typedef TableOf<MaterialList*, Enumeration>
MaterialTable;
typedef TableIteratorOf<MaterialList*, Enumeration>
MaterialTableIterator;
MaterialList*
GetMaterialList(Enumeration skl_type)
{
Check(this);
return materialTable.Find(skl_type);
}
protected:
MaterialTable
materialTable;
//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
// Explosion Support
//
protected:
ExplosionTable
*explosionTable;
public:
ExplosionTable*
CreateExplosionTable(MemoryStream *explosion_stream);
ExplosionTable*
GetExplosionTable()
{Check(this); return explosionTable; }
//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
// Effect Support
//
public:
SChainOf<EntitySegment*>
defaultEffectSiteChain,
internalVideoEffectSiteChain,
externalVideoEffectSiteChain,
internalAudioEffectSiteChain,
externalAudioEffectSiteChain;
enum {
DefaultEffectSite,
ExternalVideoEffectSite,
InternalVideoEffectSite,
ExternalAudioEffectSite,
InternalAudioEffectSite,
EffectSiteCount
};
EntitySegment*
GetCurrentEffectSite(Enumeration effect_site_type = DefaultEffectSite);
static int WriteEffectSegmentIndicies(MemoryStream *damage_zone_stream, const char *damage_zone_name, NotationFile *dmg_file, NotationFile *skl_file, const char *effect_type);
//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
// Local Support
//
public:
Simulation*
GetOwningSimulation()
{return owningSimulation;}
int
damageZoneIndex;
Scalar
defaultArmorPoints;
Scalar
damageScale[Damage::DamageTypeCount];
Scalar
damageLevel;
CString damageZoneName;
virtual void
TakeDamage(Damage &damage);
void
Reset(Logical full_reset=True);
//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
// Construction / Destruction Support
//
DamageZone(
Simulation *owner,
int damage_zone_index,
MemoryStream *dzone_res
);
DamageZone(Simulation *owner, int damage_zone_index);
virtual ~DamageZone();
Logical
TestInstance() const;
//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
// Resource Support
//
static Logical
CreateStreamedDamageZone(
NotationFile *model_file,
const char *model_name,
NotationFile *skl_file,
CString damage_zone_name,
MemoryStream *damage_zone_stream,
NotationFile *dmg_file,
const ResourceDirectories *directories
);
};