Cockpit: the CONFIG-MODE weapon-regrouping session + the live-play fire fixes (tasks #6+#11)
TASK #6 -- the pod's in-cockpit weapon regrouping, fully reconstructed and live-verified (hold-configure -> tap fire button -> toggle membership -> release-commit): - MechWeapon handlers id 9 ConfigureMappables @004b9550 / id 10 ChooseButton @004b95b8 (binary table @0x511860; the old "Myomers fns" mislabel swept) + the GetMessageHandlers() accessor chain through Emitter/ProjectileWeapon/ MissileLauncher/GAUSS/PPC (empty per-class sets swallowed dispatch). - Mapper vtable truth: +0x38 EnterConfiguration / +0x3C ExitConfiguration / +0x40,+0x44 AddOrErase evt/dir. No "secondary vtable @0050f498", no "CreateTemporaryEventMappings" virtual (RP-name drift; swept incl CLASSMAP). L4 Enter/Exit rebuilt complete: StartMappableButtonsConfigure (the NonMapping 0x10000 <-> Mapping 0x8000 mode flip + the gauge's active-weapon latch) + the held-button re-arm + the 4 fire-button temp maps; only the RIO mapper implements the toggle (Thrustmaster no-ops = can't regroup). - MechSubsystem +0xE8/+0xEC corrected to controlDestination/controlMessageID (ex hostEntity/subsystemId2 mislabel); MechWeapon ctor defaults the destination to &fireImpulse (@004b99a8). - ConfigMapGauge state loop reconstructed (PE-recovered DAT_00518eb4 table; buttonGroup GetMapState sampler -- the "needs ModeManager" guard rationale was wrong). Finding [T1]: the shipped binary NEVER enables this gauge (no SetColor caller) -- authentically dormant; BT_CONFIGMAP=1 is the dev enable. - Dev harness: HOLD 'G' opens the session (BT_CONFIG_SLOT picks the weapon); BT_CONFIG_TEST scripts a headless verify. @004afbc4 corrected to its real Fail-trap body (the guessed AddOrErase(NULL) body would corrupt groups). - Bonus [T1]: the binary MechWeapon ATTRIBUTE table has ELEVEN entries (PercentDone..WeaponState) -- "TriggerState is the only one" was wrong. TASK #11 -- the user-reported live-play regressions (both real bugs): - PHANTOM FIRE: the mech4 bring-up shot block painted an explosion at the victim on its OWN 0.3s cadence whenever fire was held -- desynced once the authentic recharges landed. Retired (the real impact visual flows from each discharge via the messmgr SubmitExplosion). - WEAPON BRICKING (the "cuts out" bug): the Loading->Loaded snap window (+-0.01 around seekV) assumes the pod's LOCKED 60 fps; one port dt-spike jumps it, the byte-verified >1.0 clamp (_DAT_004ba830=0) zeroes readiness, and the weapon sticks in Loading at level ~10000 forever (observed live). Fixed with pod-frame (1/60s) sub-stepping of the binary's own Loading tick -- also fixes the I^2R integral over-heating generators on big steps. NEW GOTCHA CLASS recorded: reconstruction-gotchas #12 (frame-pacing trap). - Duty-cycle measured (max-rate autofire): generators equilibrate in the degradation band (recharge stretch ~3.5-4.4x), the FailureHeat breaker never trips solo, PPCs sustain ~11.8-damage full-charge fire. The slow kill pacing and recharge gaps are the AUTHENTIC heat economy; the pilot's counters (this regrouping UI, generator reassignment, coolant valves) are the reconstruction queue. Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
This commit is contained in:
co-authored by
Claude Fable 5
parent
4e63a7b6c3
commit
092408041c
@@ -143,13 +143,22 @@ Derivation
|
||||
"Emitter"
|
||||
);
|
||||
|
||||
Receiver::MessageHandlerSet Emitter::MessageHandlers;
|
||||
// task #6: inherit MechWeapon's handler set (ids 9/10 ConfigureMappables/
|
||||
// ChooseButton) -- dispatch resolves through the CONCRETE class's SharedData,
|
||||
// so an empty own-set here silently swallowed the config messages.
|
||||
Receiver::MessageHandlerSet&
|
||||
Emitter::GetMessageHandlers()
|
||||
{
|
||||
static Receiver::MessageHandlerSet messageHandlers(
|
||||
MechWeapon::GetMessageHandlers()); // copy-inherit
|
||||
return messageHandlers;
|
||||
}
|
||||
Simulation::AttributeIndexSet Emitter::AttributeIndex;
|
||||
|
||||
Emitter::SharedData
|
||||
Emitter::DefaultData(
|
||||
&Emitter::ClassDerivations,
|
||||
Emitter::MessageHandlers,
|
||||
Emitter::GetMessageHandlers(),
|
||||
MechWeapon::GetAttributeIndex(), // gauge wave: inherit temps/InputVoltage/OutputVoltage/PercentDone (was empty)
|
||||
Emitter::StateCount
|
||||
);
|
||||
@@ -390,21 +399,44 @@ void
|
||||
weaponAlarm.SetLevel(4); // TriggerDuringLoad blip
|
||||
weaponAlarm.SetLevel(3);
|
||||
}
|
||||
// E7 RETIRED (task #10): the authentic charge path is live -- the
|
||||
// PoweredSubsystem ctor attaches the authored generator, the Emitter
|
||||
// ctor calibrates voltageScale/energyCoefficient, and TrackSeekVoltage
|
||||
// integrates the charge over the authored RechargeRate seconds. The
|
||||
// old unconditional snap-to-seek recharged every emitter in ONE frame
|
||||
// (~0.3s cycle vs the authored 2-6s), multiplying the heat input ~16x
|
||||
// (the "runaway": the routing itself was verified link-correct).
|
||||
if (GetVoltageState() == 4) // this+0x278 == Ready
|
||||
// E7 RETIRED (task #10): the authentic charge path is live (authored
|
||||
// generator + calibrated voltageScale/EC; TrackSeekVoltage integrates
|
||||
// the charge over the authored RechargeRate seconds).
|
||||
//
|
||||
// POD-FRAME SUB-STEPPING (task #11, THE WEAPON-BRICK FIX): the binary's
|
||||
// Loading tick assumes the pod's LOCKED 60 fps -- the charge integrates
|
||||
// toward the generator's 10000V and the Loaded transition only fires
|
||||
// while rechargeLevel crosses the +-0.01 snap window around seekV
|
||||
// (level in [7920, 8080]; ~15 pod frames wide). Under the port's
|
||||
// variable dt, one spike frame (dt >= ~0.25s) jumps the whole window:
|
||||
// the level overshoots, ComputeOutputVoltage's byte-verified >1.0
|
||||
// clamp (_DAT_004ba830 = 0.0) zeroes rechargeLevel, and the weapon is
|
||||
// PERMANENTLY stuck Loading at level ~10000 (observed live:
|
||||
// "level=9999.68 alarm=3 edge=1"). Fix: run the binary's own
|
||||
// tick -- TrackSeekVoltage + ComputeOutputVoltage + the Loaded test --
|
||||
// at the binary's own frame rate. This also keeps the I^2R generator
|
||||
// feed integral accurate (big steps evaluate seekRate at a stale level
|
||||
// and OVER-heat the generators). Sub-step count is bounded; leftover
|
||||
// time under extreme throttling just resumes next frame.
|
||||
{
|
||||
TrackSeekVoltage(time_slice); // @004ba838
|
||||
}
|
||||
ComputeOutputVoltage(); // (*vtable+0x44)()
|
||||
if (rechargeLevel == 1.0f) // _DAT_004bac04 -- fully charged (== inherited @0x320)
|
||||
{
|
||||
weaponAlarm.SetLevel(2); // -> Loaded
|
||||
static const Scalar kPodFrame = 1.0f / 60.0f;
|
||||
Scalar remaining = time_slice;
|
||||
int guard = 600; // bound: 10s of sim per frame
|
||||
while (remaining > 0.0f && guard-- > 0)
|
||||
{
|
||||
Scalar slice = (remaining < kPodFrame) ? remaining : kPodFrame;
|
||||
remaining -= slice;
|
||||
if (GetVoltageState() == 4) // this+0x278 == Ready
|
||||
{
|
||||
TrackSeekVoltage(slice); // @004ba838
|
||||
}
|
||||
ComputeOutputVoltage(); // (*vtable+0x44)()
|
||||
if (rechargeLevel == 1.0f) // _DAT_004bac04 -- fully charged
|
||||
{
|
||||
weaponAlarm.SetLevel(2); // -> Loaded
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
break;
|
||||
|
||||
|
||||
Reference in New Issue
Block a user