Ladder rungs, each run-verified on the pod rig: ReportLeak (HeatSink),
GeneratorOn (Generator -- member existed, publication missing),
ConfigureActivePress (MechSubsystem -- likewise), AmmoState +
FireCountdownStarted + the rest of the AmmoBin table.
THE PINNED RANGE IS NOW THE AUTHENTIC SHAPE. Publishing ReportLeak on
HeatSink and ConfigureActivePress on MechSubsystem shifts the chain down two,
and MechWeapon's bridge to its binary-pinned PercentDone (0x12) collapses
from THREE guessed pads to ONE -- which is exactly the arithmetic the shipped
string pool predicts (MechSubsystem 1, HeatableSubsystem 3, HeatSink 6,
PoweredSubsystem 5). Three pads of guesswork replaced by a real attribute
and a real base-class row. HeatableSubsystem and Torso rebase onto
MechSubsystem::AttributeIndex; MechControlsMapper does not (it derives from
Subsystem directly).
Types were chosen deliberately this time, per the AudioWatcher families the
engine instantiates (Motion / Hinge / Scalar / StateIndicator): every *State
name resolves to a StateIndicator, ReportLeak is a Scalar.
RESULT: the pod run now gets past every authored watcher and DRAWS THE FULL
COCKPIT -- sensor cluster, myomers, cooling, the weapon panels, kills/deaths
-- with the board booted and audio running. It then exits without flushing
its redirected stdout, so the exit reason is not yet known; next step is a
run with the redirect removed so the console is readable.
Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
The full circuit, workflow-researched (5 parallel dossiers over BT411 + the
engine) and adversarially reviewed (3 lenses) before landing:
Mech side: the once-per-death transition in Simulate (freeze, motion kill,
DeathShutdown sweep, MASTER-only VehicleDead(-1) to the player link);
Mech::Reset @0049fb74 (reposition + heal every hull zone + the roster
DeathReset sweep + PreRun -- the reset-based respawn that REUSES the entity);
dead-owner terms in both weapon hard gates (wrecks fall silent).
Player side: the VehicleDead(-1) branch (deathPending dedup, deathCount
bump+stamp, scenario-role life debit, +5s re-post -> the engine drop-zone
hunt) and the DropZoneReply respawn branch (reset the dead mech at the
replied drop zone; probes on a live mech are moot).
Subsystem side: the engine base virtual DeathReset implemented across the
family -- MechSubsystem (zone heal + DestroyedState clear), MechWeapon (full
powered/thermal restore + fresh Loading cycle), AmmoBin (restock from the
ctor-cached count), HeatSink/HeatWatcher/PowerWatcher/Generator/Sensor/
MissileLauncher.
Review catches fixed before commit: AmmoBin restocked through the FREED
padBuffer pointer (use-after-free -> initialAmmoCount; MechSubsystem::
resource is now documented as never-deref-post-ctor); died-hot weapons
respawned at FailureHeat (now full thermal re-init); Generator tap counts
desynced across reset (preserved); Sensor skipped the base heal; PowerWatcher
inherited a statically-bound reset; cooling toggle + connect mode restored.
Verified: kill -> wreck (0 shots while dead) -> +5s -> drop-zone hunt ->
HEALED + placed at a real drop zone -> 134 shots after respawn incl. 12 SRM
(restock proof); unowned enemy wreck settles silently; fight/smoke/novice
regressions green, zero faults.
Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
Mech::DamageZone::TakeDamage is the full binary cascade (@0049c690): LOD
artifact router with same-attacker clustering (@0049c40c, hysteresis 0.33),
artifact parent level = mean of children, Energy-hit generator shorts
through the crit plug binding (novice-exempt), weighted CriticalHit
(@0049ccc4), zone-death allotment push (SendSubsystemDamage @0049c9a8) and
the segment-table destruction descent (RecurseSegmentTable @0049cad4 --
SIBS + DESCEND via the engine EntitySegment iterators).
Supporting bricks: Mech's OWN handler table with the TakeDamage override
(latches lastInflictingID @0x43c; gyro feed staged; cylinder table
deferred); friend class Mech__DamageZone (authentic); subsystem private
zones ARMED (structureReference + armorByFacing[5] normalized -- crits are
measurable); ApplyDamageAndMeasure; ForceCriticalFailure sets
DestroyedState so the weapon FSMs' GetSimulationState()==1 hard gate went
live; Generator::ForceShort + PoweredSubsystem::ForceShortRecovery.
Fight-verified (mutual BT_SPAWN_ENEMY + BT_FORCE_ZONE=8 concentrated fire):
arm zone to 1.0 -> sibling searchlight zone dies (Searchlight2/ThermalSight
crits destroyed, HUD degrading) -> DESCEND kills the gun zone -> PPC_2 +
ERMLaser_2 + Condenser6 DESTROYED and FALL SILENT (0 shots after death;
undamaged PPC_1 keeps firing); vital-zone hit = MECH KILL; PPC hit shorted
GeneratorD. This art has zero artifact zones (redirect=0 across all 20 --
router verified dormant-correct). Smoke + novice regressions clean.
Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
The subsystem-family cockpit buttons now work through the authentic Receiver
dispatch -> per-class handler-table path. The id space decodes cleanly:
Receiver::NextMessageID == 3, so ToggleCooling = 3 on the HeatSink chain and
the per-class id 4 is MoveValve on a Condenser / InjectCoolant on the
Reservoir -- same number, different class, the binary's per-receiver-class
convention.
- HeatSink::ToggleCoolingMessageHandler (@004ad6f8, id 3): novice-locked,
press-only; toggles coolantAvailable + coolantFlowScale together.
- Condenser::MoveValveMessageHandler (@4ae464, id 4): novice-locked; cycles
the valve 1->5->50->0->1 and calls Condenser::RecomputeValves (@0049f788):
every condenser's coolantFlowScale = valve / sum-of-valves. The ctor now
streams the AUTHENTIC flowScale=0; the Mech ctor seeds equal shares once at
spawn -- the flowScale=1 interim is retired.
- Reservoir::InjectCoolantMessageHandler (@4aee70, id 4): novice-locked;
press arms the flush when the tank holds charge, release drops it.
- MechSubsystem::NoviceLockout() (@4ac9c8): owner -> playerLink -> experience
== novice; unlinked mechs read unlocked.
- DEV harness BT_PRESS_VALVE / BT_PRESS_FLUSH: dispatch the REAL messages ~6s
into the mission from Mech::Simulate.
VERIFIED: spawn shares 6 x 0.166667; one MoveValve press -> Condenser1
valve=5 flow=0.5, others 0.1 (valve/sum exact); flush arms via the real
button message; NOVICE locks both presses (valve lines stay spawn-only, zero
flush). Zero Fail throughout.
Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
The base all ~30 mech subsystems derive from. Reconstructed against the 4.10
structure per the MECHSUB.NOTES analysis (NOT backdated from BT411's divergent
version):
- Header: expanded with the real mech-specific member set (statusAlarm =
AlarmIndicator, vitalSubsystem, alarmModel, criticalReference,
collisionCriticalHitWeight, printSimulationState, configureActivePress,
resource). Dropped the speculative MessageHandlers static -- MechSubsystem
reuses the base Subsystem sets (inherited Simulation handlers/attrs/statecount).
- CPP: statics (ClassDerivations/DefaultData), both ctors (light name+classID and
resource), dtor, TestClass/TestInstance, and the damage API on the 4.10
per-type model -- GetSubsystemDamageLevel/SetSubsystemDamageLevel read/write the
real DamageZone::damageLevel [0,1]; ForceCriticalFailure; TakeDamage delegates
to the zone. Both ctors build the damage zone the base leaves NULL.
Deferred (documented): the Mech__DamageZone per-type armour STREAM wiring (ctors
use a trivial armour-free base DamageZone placeholder for now) and
CreateStreamedSubsystem (model-load stream format). These are refinements above
the ctor frontier, not boot blockers.
Compile-verified (BT: 24 ok); full tree still links clean. Next: the subsystem
roster (GAUSS/PPC/SENSOR source + .TCP partials + decomp).
Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>