DMGTABLE born (type-29 streams, BT411 byte-verified format): the height x angle grid -- DamageLookupTable rows by height, PieSlice cells by angle (rotate-with-torso rows add the live twist), DamageZonePercentTable = the cumulative hit-distribution roll (first threshold above the roll -- the BattleTech dice scatter). Loaded in the Mech ctor by the DamageZoneStream member's NAME (mech+0x444, resident); Mech::TakeDamageMessageHandler resolves invalidDamageZone hits through it (binary @0x4a0264 tail). The missile fuse becomes the authentic unaimed producer: zone -1 + the round's world position as the impact point (ENTITY3.HPP: "damage zones are only valid via reticle based weapons"). Fight-verified on the authentic 7-row bhk1 table: flat-flying SRMs strike low -> row 0 -> FEET AND LEG zones, side-correct by impact angle (+x right, -x left), identical geometry spread across the cell distribution by the roll. 17/17 missile lifecycle, zero faults; smoke + novice green. Also fixed: the ctor's reservedState zero-loop counted past the shrunken array. Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
106 lines
3.6 KiB
C++
106 lines
3.6 KiB
C++
//===========================================================================//
|
|
// File: dmgtable.hpp //
|
|
// Project: BattleTech //
|
|
// Contents: The cylinder hit-location table (unaimed damage -> zone) //
|
|
//---------------------------------------------------------------------------//
|
|
// Copyright (C) 1995, Virtual World Entertainment, Inc. //
|
|
// All Rights reserved worldwide //
|
|
// This unpublished sourcecode is PROPRIETARY and CONFIDENTIAL //
|
|
//===========================================================================//
|
|
//
|
|
// STAGED header -- no dmgtable.hpp survives; the interface is reconstructed
|
|
// from the binary (BT411, byte-verified vs the real type-29 .RES streams):
|
|
// a passive nested height x angle grid of three container classes,
|
|
//
|
|
// DamageLookupTable (binary ctor @0049ea48, vtable @0050bd84, 0x2c)
|
|
// -> PieSlice ROWS by height (@0049e740, @0050bd90, 0x30)
|
|
// -> DamageZonePercentTable CELLS by angle (@0049deb0, @0050bd9c, 0x2c)
|
|
// -> the cumulative hit-distribution (roll -> zone index).
|
|
//
|
|
// Class names follow the BT411 reconstruction (no 1995 names survive).
|
|
// The binary keys rows/cells into refcounted keyed lists; direct-indexed
|
|
// arrays are equivalent (the float key (i+1)*2pi/count === cells[i]).
|
|
//
|
|
|
|
#if !defined(DMGTABLE_HPP)
|
|
# define DMGTABLE_HPP
|
|
|
|
//##################### Forward Class Declarations #######################
|
|
class Mech;
|
|
|
|
//###########################################################################
|
|
//##################### DamageZonePercentTable ##########################
|
|
//###########################################################################
|
|
|
|
//
|
|
// One angular CELL: the cumulative hit-distribution. Entries ascend;
|
|
// SelectZone (binary @0049de14) rolls uniform [0,1) and returns the
|
|
// first entry whose threshold exceeds the roll -- the classic
|
|
// BattleTech dice hit-scatter.
|
|
//
|
|
class DamageZonePercentTable
|
|
{
|
|
public:
|
|
DamageZonePercentTable(MemoryStream *stream);
|
|
~DamageZonePercentTable();
|
|
|
|
int
|
|
SelectZone();
|
|
|
|
int entryCount;
|
|
Scalar *thresholds; // cumulative, ascending
|
|
int *zoneIndices; // -> Entity::damageZones[]
|
|
};
|
|
|
|
//###########################################################################
|
|
//############################ PieSlice #################################
|
|
//###########################################################################
|
|
|
|
//
|
|
// One height ROW: the ring of angular cells. rotateWithTorso rows
|
|
// (upper body) add the live torso twist to the impact angle before the
|
|
// cell pick (binary @0049e678).
|
|
//
|
|
class PieSlice
|
|
{
|
|
public:
|
|
PieSlice(Mech *mech, MemoryStream *stream);
|
|
~PieSlice();
|
|
|
|
DamageZonePercentTable*
|
|
SelectSlice(Scalar angle);
|
|
|
|
Mech *owner;
|
|
int rotateWithTorso;
|
|
int cellCount;
|
|
DamageZonePercentTable
|
|
**cells;
|
|
};
|
|
|
|
//###########################################################################
|
|
//######################## DamageLookupTable ############################
|
|
//###########################################################################
|
|
|
|
//
|
|
// The table: rows stacked by height over the mech's cylinder.
|
|
// ResolveHit (binary @0049eb54 + glue @0049ed0c) maps a WORLD impact
|
|
// point -> mech-local -> (height row, impact angle) -> cell -> the
|
|
// distribution roll -> a hull zone index.
|
|
//
|
|
class DamageLookupTable
|
|
{
|
|
public:
|
|
DamageLookupTable(Mech *mech, MemoryStream *stream);
|
|
~DamageLookupTable();
|
|
|
|
int
|
|
ResolveHit(const Point3D &world_impact);
|
|
|
|
Mech *owner;
|
|
int rowCount;
|
|
PieSlice
|
|
**rows;
|
|
};
|
|
|
|
#endif
|