diff --git a/content/CONTROLS.MAP b/content/CONTROLS.MAP index 3c9ebad..fb5fb0d 100644 --- a/content/CONTROLS.MAP +++ b/content/CONTROLS.MAP @@ -176,3 +176,19 @@ key G action Flush # healthy mech refuses the button, so a stray press is a no-op. key Back action Eject pad LeftThumb action Eject + +# PILOT KEYPAD (the pod's MFD program keypad, KeyboardPilot unit). While +# PANIC mode is armed, ANY pilot-keypad key fires the eject (the binary's +# keyboardGroup[KeyboardPilot].Add(0x200000, mech, 0x19) -- its ONLY armed +# eject binding); un-armed, the keys feed program entry. Desktop numpad = +# that keypad. +key NumPad0 keypad pilot 0 +key NumPad1 keypad pilot 1 +key NumPad2 keypad pilot 2 +key NumPad3 keypad pilot 3 +key NumPad4 keypad pilot 4 +key NumPad5 keypad pilot 5 +key NumPad6 keypad pilot 6 +key NumPad7 keypad pilot 7 +key NumPad8 keypad pilot 8 +key NumPad9 keypad pilot 9 diff --git a/game/reconstructed/mechsub.cpp b/game/reconstructed/mechsub.cpp index 994e942..3c35a44 100644 --- a/game/reconstructed/mechsub.cpp +++ b/game/reconstructed/mechsub.cpp @@ -287,6 +287,13 @@ void MechSubsystem::ForceCriticalFailure() { ((DamageZone *)damageZone)->SetDamageZoneState(1); // zone+0x10 } + // Generator: also reach the OUT display state (stateAlarm 4) so the + // authored gotoEngineering + engEject FLASH invite fires (alarm stream + // conditions 4/5). [T3 inferred link -- see Generator::MarkGeneratorOut.] + { + extern void BTGeneratorMarkOut(::Subsystem *sub); // powersub.cpp + BTGeneratorMarkOut(this); + } } // issue #22 (PORT): the fresh-mech respawn repair -- the exact inverse of the diff --git a/game/reconstructed/powersub.cpp b/game/reconstructed/powersub.cpp index f8c3c01..32d78fc 100644 --- a/game/reconstructed/powersub.cpp +++ b/game/reconstructed/powersub.cpp @@ -1305,10 +1305,10 @@ void { // The THERMAL BREAKER: output collapses to 0 until the generator cools // past NormalHeat and re-spins (task #11 diag below shows the duty cycle). - if (stateAlarm.GetLevel() != GeneratorRecovered && getenv("BT_HEAT_LOG")) + if (stateAlarm.GetLevel() != GeneratorOut && getenv("BT_HEAT_LOG")) DEBUG_STREAM << "[gen] " << GetName() << " TRIPPED (T=" << currentTemperature << ")" << std::endl; - stateAlarm.SetLevel(GeneratorRecovered); // SetLevel 4 + stateAlarm.SetLevel(GeneratorOut); // SetLevel 4 } switch (stateAlarm.GetLevel()) // this[0x84] @0x210 @@ -1337,7 +1337,7 @@ void } break; - case GeneratorRecovered: // 4 + case GeneratorOut: // 4 outputVoltage = 0.0f; if (heatAlarm.GetLevel() == HeatSink::NormalHeat) // this+0x184 == 0 { @@ -1779,6 +1779,17 @@ int BTSubsystemIsGenerator(::Subsystem *sub) return (sub != 0 && sub->IsDerivedFrom(*Generator::GetClassDerivations())) ? 1 : 0; } +// Destruction -> OUT display state (see Generator::MarkGeneratorOut, the [T3 +// inferred link]): a destroyed generator must reach stateAlarm 4 or the +// authored gotoEngineering/engEject FLASH invite (alarm conditions 4/5) never +// fires and the eject evaluator's state clause never sees it. Called from +// MechSubsystem::ForceCriticalFailure (the one crit-death chokepoint). +void BTGeneratorMarkOut(::Subsystem *sub) +{ + if (sub != 0 && sub->IsDerivedFrom(*Generator::GetClassDerivations())) + ((Generator *)sub)->MarkGeneratorOut(); +} + //===========================================================================// // BTGeneratorCountsForEject -- complete-type bridge for the EJECT-permission // evaluator (Mech::EvaluateEjectPermission @0049fa1c). Binary clause: classID diff --git a/game/reconstructed/powersub.hpp b/game/reconstructed/powersub.hpp index 432d476..bd6f354 100644 --- a/game/reconstructed/powersub.hpp +++ b/game/reconstructed/powersub.hpp @@ -379,7 +379,12 @@ class Generator; GeneratorIdle = 1, // off / no output GeneratorReady = 2, // producing RatedVoltage GeneratorShorted = 3, // shorted; shortTimer -> shortRecoveryTime - GeneratorRecovered = 4 // TODO: confirm 4th/5th level names + GeneratorOut = 4 // generator DEAD/OUT: the eject evaluator counts + // stateAlarm==4 as not-live [T1 @0049fa1c], and the + // authored gauge-alarm streams flash gotoEngineering + + // engEject on conditions 4/5 [T1 content dump + // 2026-08-03] -- the "punch out now" invite. + // (Old name "GeneratorRecovered" was a placeholder.) }; //~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ @@ -462,6 +467,18 @@ class Generator; // Source-state queries used by PoweredSubsystem / PowerWatcher. int GeneratorStateOf() { return stateAlarm.GetLevel(); } // source+0x210 + + // DESTRUCTION -> the OUT display state (stateAlarm 4). [T3 inferred + // link, 2026-08-03]: both endpoints are byte-verified -- the eject + // evaluator treats stateAlarm==4 as generator-dead (@0049fa1c) and the + // authored alarm streams flash the gotoEngineering + engEject invite on + // conditions 4/5 -- but the binary's destroyed->SetLevel(4) call site + // sits in unexported code (no FUN_0041bbd8(+0x1fc,4) in the flat + // export). Called from MechSubsystem::ForceCriticalFailure via the + // BTGeneratorMarkOut bridge; replace with the exact site when the + // MechSubsystem::TakeDamage / OnAlarmChanged cluster is reconstructed. + void + MarkGeneratorOut() { stateAlarm.SetLevel(GeneratorOut); } Scalar MeasuredVoltage() { return outputVoltage; } // source+0x1dc Scalar