myomer damage reaches the wheels, legs gimp at half structure, reverse refuses -- and an ODR trap unmasked (#75/#78)
The speed-demand site (MechControlsMapper::InterpretControls) now applies the
drive scale the mover's feed roster applied in 1995: speedDemand multiplies by
the myomers' live speedEffect (gear ratio, thermal curve, 1 - zone damage, via
the BTMyomersDriveOf bridge) and, while GIMPED, by 0.5 [T3: VGL Lynx's
"roughly 50%", BT_GIMP_SPEED overrides]. The gimp states were already being
raised -- mechdmg sets graphicAlarm 3 (left) / 4 (right) when a LegDamageZone-
flagged zone crosses half structure -- but nothing downstream ever saw them.
While gimped, reverse input is refused ("reverse disabled"), matching the
old-timers' account; the pod's audio cue rides the alarm's watchers.
Bench, one trajectory, arithmetically exact: a deterministic right-leg ramp
(the new BT_SELF_DAMAGE_ZONE harness) crosses 0.5 and the demand goes
44.837 -> 6.726 = 44.837 x 0.5 (gimp) x 0.3 (a crit-chewed myomers from the
same ramp -- the #80 crits composing with #75's scale, unprompted).
The reason "nothing downstream ever saw them" is the real find of the night,
now gotcha #23: AlarmIndicator is typedef'd to DIFFERENT TYPES per header
family -- mech.hpp says ReconAlarm (4 bytes), heat.hpp says GaugeAlarm (0x54)
-- so Mech::graphicAlarm and EVERY member after it sit at different offsets
depending on a TU's include order. mechdmg wrote level 4 and read it back;
mechmppr read 0 from the same object, same expression. No compiler error can
catch it: each TU only ever sees one definition. Until the split is audited,
cross-TU reads of the gimp level go through BTMechGimpLevel (compiled in
mechdmg's TU) -- and the same split-brain explains why the port carries the
binary's ONE movementMode cell as two live members (engine simulationState vs
graphicAlarm level) that never meet.
Also landed en route: the Myomers un-powered self-repair observed healing in
the field logs at exactly 0.011 x the authored Explosive scale per tick --
the 2026-07-29 reversal confirmed live; and Mech message 0x15 "RealMaxSpeed"
raw-decoded (@0x49f604: sets mech+0x7a0 from the message unless the +0x7a4
latch holds -- a console-tunable top speed).
Open on #78, documented in locomotion.md: the Gimp animation clips (authored
keys in the binary's model-record parser; mech2's state enum vs mech3's
reverse-fix disagree about slots 0x12-0x17 -- reconcile before wiring) and
the audio-cue binding.
Diags: BT_SELF_DAMAGE_ZONE, BT_DRIVE_LOG, BT_GIMP_SPEED.
Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
This commit is contained in:
co-authored by
Claude Fable 5
parent
8a99972f22
commit
520f6eecd3
@@ -414,6 +414,29 @@ Scalar Myomers::SeekVoltageResponse(Scalar input_voltage)
|
||||
// (see emitter.cpp BTSeekVoltageSample). Guarded: a non-Myomers subsystem
|
||||
// samples 0 (only emitter/myomer pages own a graph in the shipped config).
|
||||
//***************************************************************************
|
||||
//***************************************************************************
|
||||
// #75 bridge -- the myomers' live drive fraction for the mech's speed demand.
|
||||
//
|
||||
// The authentic coupling: ConnectToMover attached &speedEffect into the
|
||||
// mech's mover, which multiplied every attached feed into its drive. The
|
||||
// 2007 engine's mover has no such roster, so the port applies the same
|
||||
// multiplication at the speed-demand site (mechmppr.cpp): demand *= this.
|
||||
// speedEffect@0x31C is the wrapper's live 0..1 output -- gear ratio, thermal
|
||||
// curve and (1 - zone damage) -- already republished every tick. A mech
|
||||
// with no Myomers (or no roster yet) drives at 1.0; a DESTROYED myomers
|
||||
// drives 0.0 (no drive -- the subsystem that moves the mech is gone).
|
||||
//***************************************************************************
|
||||
Scalar BTMyomersDriveOf(void *subsystem)
|
||||
{
|
||||
Entity *entity = (Entity *)subsystem;
|
||||
if (entity == 0 || !entity->IsDerivedFrom(Myomers::ClassDerivations))
|
||||
return -1.0f; // not a Myomers
|
||||
Scalar f = ((Myomers *)entity)->SpeedEffect();
|
||||
if (f < 0.0f) f = 0.0f;
|
||||
if (f > 1.0f) f = 1.0f;
|
||||
return f;
|
||||
}
|
||||
|
||||
Scalar BTMyomersSeekSample(void *subsystem, Scalar voltage)
|
||||
{
|
||||
Entity *entity = (Entity *)subsystem;
|
||||
|
||||
Reference in New Issue
Block a user