Gauges: the CLOSEOUT wave -- radar pips, Myomers dedup, attribute parity, ledger sweep (tasks #14-#17)
TASK #17 -- AUTHENTIC RADAR SYMBOLOGY (the cross-blip stand-in retired). The recon proved the 'missing pip raster set' never existed as BT game code: pips are the ENGINE's L4GaugeImage vector-stroke system (T0 source in tree, L4GAUIMA.cpp == FUN_0046f0c0 line-for-line), the 'pip table' is L4Warehouse:: gaugeImageBin keyed by Entity::resourceID, and BTL4.RES ships 110 type-0x12 shapes (every mech/vehicle/building/tree). The six btl4rdr stubs are wired to the real facilities: contacts draw their authentic model silhouettes with LOD selection, the target gets the binary's 4px-inflated box highlight, and player-name labels resolve via Mission::GetSmallNameBitmap (the prebuilt 64x16 egg rasters keyed by the player's bitmapindex). DECODED: the invented 'VideoObject' was Entity::owningPlayer all along (+0x190; nameID = playerBitmapIndex@0x1E0, target = BTPlayer::objectiveMech@0x284 -- new bridge BTPlayerObjectiveMechOf); the 'LabelledEntity' class is Landmark (cultural.h; label path dormant -- no landmark content ships, no runtime landmarkID writer). The L4GREND BT_DEV_GAUGES warehouse guard is removed (its AV had a different culprit, below); resource type 18 corrected to GaugeImageStream in decomp-reference (was mislabeled 'ModelList'). TASK #14 -- the Myomers ODR duplicate ELIMINATED: the powersub.cpp/hpp 'Myomers' (classID 0xBC3 -- actually Sensor) is retired whole; it duplicated ?DefaultData@Myomers@@ against the real class (dumpbin-verified) and /FORCE picked the winner by link order. The real Myomers (0xBC6) now chains PoweredSubsystem's handler set (ids 4-8) and publishes its SEVEN binary attributes (@00511588: SpeedEffect/Current/Recommended/Min/MaxSeekVoltage- Index/SeekVoltage/OutputVoltage) -- the old empty unchained index starved the Myomer engineering panel of every resolve. TASK #16 -- attribute parity: MechWeapon publishes the FULL binary table @0x511890 (11 entries; ids renumbered to binary truth -- the port aliases had squatted the binary's DistanceToTarget/TargetWithinRange ids; the streamed TriggerState 0x13 binding unchanged). Binary names resolved two TODO members: pipState -> estimatedReadyTime (attr 0x1A), and the EXT-model flag is the binary's RearFiring (0x1B). ThermalSight LightState published. HUD (offset conflicts) + missile-side tables (id encoding suspect) documented for a re-dump instead of publishing blind. THE CRASH THIS EXPOSED [T2, cdb-verified]: gotcha #11's dense-table gap is a LATENT AV, not a guaranteed one -- the old table's 0x0D..0x12 gap (task #5) survived on heap luck; the renumber reshuffled allocations and Find() AV'd on a garbage entryName in WeaponCluster's PercentDone resolve. Fixed with five named PAD entries (the mech.cpp attrPad idiom) + a static_assert locking the pad base to PoweredSubsystem::NextAttributeID. Gotcha #11 amended with the proof. TASK #15 -- stale-ledger sweep: GAUGE_COMPOSITE ('composite not yet built', Reservoir shadow, PlayerStatus/vehicleSubSystems 'remaining', valve-dormant- until-0xBD3, sensor guard, the superseded 'Heat MFD near-static' reframe -- all banner-corrected), gauges-hud frontmatter, L4VB16 + powersub comments. Verified live: 50/50 config attribute bindings resolve, 0 NULLs, 0 parse skips, mech spawns and simulates 31/31 subsystems, no cross-blip fallbacks, the pip cache fills through entity registration without the old guard. Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
This commit is contained in:
co-authored by
Claude Fable 5
parent
80cadc98c7
commit
dd27238ceb
+14
-163
@@ -849,171 +849,19 @@ int
|
||||
|
||||
//###########################################################################
|
||||
//###########################################################################
|
||||
// Myomers
|
||||
// (Myomers mislabel -- RETIRED, task #14)
|
||||
//###########################################################################
|
||||
//###########################################################################
|
||||
|
||||
//#############################################################################
|
||||
// Shared Data Support
|
||||
//
|
||||
Myomers::SharedData
|
||||
Myomers::DefaultData(
|
||||
Myomers::GetClassDerivations(),
|
||||
Myomers::GetMessageHandlers(),
|
||||
Myomers::GetAttributeIndex(),
|
||||
Myomers::StateCount
|
||||
);
|
||||
|
||||
Derivation*
|
||||
Myomers::GetClassDerivations()
|
||||
{
|
||||
static Derivation classDerivations(PoweredSubsystem::GetClassDerivations(), "Myomers");
|
||||
return &classDerivations;
|
||||
}
|
||||
|
||||
// The "Myomers" block that lived here (ctor @4b1d18, classID 0xBC3,
|
||||
// outputVoltage/powered/voltageAvailable) was a MISLABEL of Sensor (real
|
||||
// reconstruction: sensor.cpp). Its Myomers::DefaultData / ctor / dtor /
|
||||
// TestInstance / MyomersSimulation / ResetToInitialState / HandleMessage /
|
||||
// CreateStreamedSubsystem definitions ODR-DUPLICATED the REAL Myomers
|
||||
// (myomers.cpp, classID 0xBC6) -- /FORCE picked the winner by link order,
|
||||
// so which SharedData live Myomers instances got was link-order-dependent
|
||||
// (the same archetype as the fixed Condenser stub dedup). Retired whole.
|
||||
//
|
||||
// @004b1d18 -- master myomer bundle registers a separate Performance and a
|
||||
// status-flag bit (0x8); copies skip the live simulation.
|
||||
//
|
||||
Myomers::Myomers(
|
||||
Mech *owner,
|
||||
int subsystem_ID,
|
||||
SubsystemResource *subsystem_resource,
|
||||
SharedData &shared_data
|
||||
):
|
||||
PoweredSubsystem(owner, subsystem_ID, subsystem_resource, /*shared_data=*/DefaultData) // FUN_004b0f74(..,&DAT_0050fa1c,0,0)
|
||||
{
|
||||
outputVoltage = 1.0f; // this[0xc7]
|
||||
powered = 0; // this[0xc8]
|
||||
voltageAvailable = 0; // this[0xc9]
|
||||
simulationFlags |= 0x8; // this[0xa] |= 8
|
||||
|
||||
if ((subsystem_resource->subsystemFlags & SegmentCopyMask) != 4) // (flags & 0xC) != 4
|
||||
{
|
||||
SetPerformance((Performance)&Myomers::MyomersSimulation); // PTR @0050fa94
|
||||
}
|
||||
}
|
||||
|
||||
//
|
||||
// @004b1d90
|
||||
//
|
||||
Myomers::~Myomers()
|
||||
{
|
||||
Check(this);
|
||||
BT_ClearMyomers((Mech *)owner); // *(this[0x34]+0x374) = 0
|
||||
Check_Fpu();
|
||||
}
|
||||
|
||||
Logical Myomers::TestClass(Mech &) { return True; }
|
||||
Logical Myomers::TestInstance() const // @004b1e18
|
||||
{
|
||||
return IsDerivedFrom(*GetClassDerivations()); // FUN_0041a1a4(..,0x50fa2c)
|
||||
}
|
||||
|
||||
//
|
||||
// @004b1c4c -- compute the actuator drive voltage available to the locomotion
|
||||
// model from the powering generator, throttled by heat damage and gated by
|
||||
// the electrical state.
|
||||
//
|
||||
void
|
||||
Myomers::MyomersSimulation(Scalar time_slice)
|
||||
{
|
||||
PoweredSubsystem::PoweredSubsystemSimulation(time_slice); // FUN_004b0bd0
|
||||
|
||||
Generator *source = (Generator *)voltageSource.Resolve(); // this[0x38] linked source
|
||||
outputVoltage = RatedVoltageRef - source->MeasuredVoltage(); // 1.0 - *(source+0x158)
|
||||
|
||||
if (simulationState == 1) // this[0x10] @0x40
|
||||
{
|
||||
outputVoltage = 0.0f;
|
||||
powered = 0;
|
||||
}
|
||||
else
|
||||
{
|
||||
powered = 1;
|
||||
}
|
||||
|
||||
if (electricalStateAlarm.GetLevel() == Ready) // this[0x9e] == 4
|
||||
{
|
||||
voltageAvailable = 0;
|
||||
}
|
||||
else
|
||||
{
|
||||
voltageAvailable = 1;
|
||||
outputVoltage = 0.0f;
|
||||
}
|
||||
|
||||
//
|
||||
// Heat damage (HeatSink heat-state @0x184) throttles the drive.
|
||||
//
|
||||
switch (heatAlarm.GetLevel()) // this+0x184 (heat-state inside heatAlarm@0x170+0x14)
|
||||
{
|
||||
case HeatSink::NormalHeat: // 0
|
||||
powered = 1;
|
||||
break;
|
||||
case HeatSink::DegradationHeat: // 1
|
||||
outputVoltage *= DegradedDriveScale; // *= 0.5
|
||||
powered = 1;
|
||||
break;
|
||||
case HeatSink::FailureHeat: // 2
|
||||
outputVoltage = 0.0f;
|
||||
powered = 0;
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
//
|
||||
// @004b1c18 -- reset clears the myomer output state, then chains to the base.
|
||||
//
|
||||
void
|
||||
Myomers::ResetToInitialState(Logical powered_flag)
|
||||
{
|
||||
if (powered_flag)
|
||||
{
|
||||
outputVoltage = 1.0f; // this[0xc7]
|
||||
powered = 0; // this[0xc8]
|
||||
voltageAvailable = 0; // this[0xc9]
|
||||
}
|
||||
PoweredSubsystem::ResetToInitialState(powered_flag); // FUN_004b0e6c
|
||||
}
|
||||
|
||||
//
|
||||
// @004b1bfc -- straight delegation to the base.
|
||||
//
|
||||
Logical
|
||||
Myomers::HandleMessage(int message)
|
||||
{
|
||||
return PoweredSubsystem::HandleMessage(message); // FUN_004b0efc
|
||||
}
|
||||
|
||||
//
|
||||
// @004b1dcc -- no extra resource fields; just tags the record as Myomers.
|
||||
//
|
||||
int
|
||||
Myomers::CreateStreamedSubsystem(
|
||||
NotationFile *model_file,
|
||||
const char *model_name,
|
||||
const char *subsystem_name,
|
||||
SubsystemResource *subsystem_resource,
|
||||
NotationFile *subsystem_file,
|
||||
const ResourceDirectories *directories,
|
||||
int passes
|
||||
)
|
||||
{
|
||||
if (
|
||||
!PoweredSubsystem::CreateStreamedSubsystem( // FUN_004b13ac
|
||||
model_file, model_name, subsystem_name,
|
||||
subsystem_resource, subsystem_file, directories, passes
|
||||
)
|
||||
)
|
||||
{
|
||||
return False;
|
||||
}
|
||||
subsystem_resource->subsystemModelSize = 0x190;
|
||||
subsystem_resource->classID = RegisteredClass::MyomersClassID; // 0x0bc3, resource+0x20
|
||||
return True;
|
||||
}
|
||||
|
||||
|
||||
//###########################################################################
|
||||
//###########################################################################
|
||||
@@ -1509,8 +1357,11 @@ Subsystem *CreatePoweredSubsystem(Mech *owner, int id, void *seg)
|
||||
// Bridge for the vehicleSubSystems gauge factory (btl4gau2.cpp). The engineering-
|
||||
// screen assignment lives on PoweredSubsystem (auxScreenNumber / auxScreenPlacement
|
||||
// / auxScreenLabel, resource +0x104/+0x108/+0x10C). Reading it from btl4gau2.cpp
|
||||
// via a raw offset (sub+0x1dc) is wrong because the reconstructed heat-leaf branch
|
||||
// is not byte-exact -- so the gauge factory calls this bridge, which casts through
|
||||
// via a raw offset (sub+0x1dc) is wrong because raw offsets on our compiled
|
||||
// objects are the databinding trap (2026-07-12: the "heat-leaf not byte-exact"
|
||||
// wording is stale -- the leaf IS byte-exact since the sensor re-base,
|
||||
// sensor.cpp:407-413 -- but the bridge stays: named members are the rule)
|
||||
// -- so the gauge factory calls this bridge, which casts through
|
||||
// the real PoweredSubsystem type and returns the NAMED fields. Returns False for
|
||||
// non-PoweredSubsystem-derived subsystems (== the FUN_0041a1a4 / 0x50f4bc type
|
||||
// filter the vehicleSubSystems Make applies before dispatch).
|
||||
|
||||
Reference in New Issue
Block a user