#137 ("respawn came back with MYOMERS heat MAXED", Oracle; "overheating generator D", Sauron) sent us through a full two-sided audit of Mech::Reset and the whole RTIS chain. Both sides were correct. The answer was in the field log all along, one line after the reset: [respawn] Mech::Reset 3:30 healed+moved to (...) alive=1 [techstat] ... every live condition CLEARED [techstat] Myomers condition 3 SET <- Overheating, immediately [mppr] in thr=1 -> ... [gaitSM] cycleSpeed=14.6 state=12 <- already RUNNING [techstat] Condenser5 condition 3 SET <- "dumping into coolant loop 5" [techstat] GeneratorD condition 3 SET <- Sauron's generator D The mech respawns STILL UNDER POWER and earns the heat honestly. Two facts close it: 1. condition 3 is an OPERATING flag, not an alarm. Census over one match: LLaser_2 33 SET / 33 CLEARED, LLaser_1 31/31, SRM4 26/26, PPC_2 18/18 -- every volley trips it and clears it. EVERY subsystem is balanced (GeneratorD 5/4, Myomers 5/4, Condenser5 1/1; the extra SET is only the log ending mid-heat). cond 6 BadPower behaves the same (Myomers 8/8). Nothing latches. A post-respawn SET is not evidence of anything. 2. Mech::Reset's subsystem loop starts at index 2 and the ControlsMapper is index 0, so the throttle is never reset -- and the BINARY does the same. That is right for a pod: the throttle is a PHYSICAL lever still under the pilot's hand. Respawning under power is authentic and stays. Oracle's read that the myomer heat rate "felt right" was correct. WHAT IS a real defect (#146), desktop only: the glass bridge merely EMULATES that lever, with the static ramp accumulator sLever (mech4.cpp:3250) zeroed ONLY by the X all-stop and a direction-crossing snap. A pad/keyboard pilot is physically holding nothing and cannot see the lever, so they respawned at speed for no reason they could perceive -- and ate the heat load above. The Thrustmaster/RIO path was never affected: InterpretControls (@004d2150) rebuilds throttlePosition every frame from the databound throttleForward. Fix: queue the existing all-stop at Mech::Reset, reusing the proven path (it already clears the zero-crossing detent too). LOCAL VIEWPOINT MECH ONLY -- gBTDrive is the local bridge's state and Reset also runs for replicants, so an ungated write would all-stop the player whenever a REMOTE mech respawned. Pod-safe besides: with a RIO present the key bridge is off and gBTDrive.throttle is never read. BT_NO_RESPAWN_THROTTLE_RELEASE=1 reverts. Benched 2-node (scratchpad/night13/throttlerespawn.sh): the release fires 1:1 with local respawns on both nodes independently (A 2/2, B 1/1) and never spuriously. HONEST LIMIT: the viewpoint gate was NOT stressed -- B ran Mech::Reset 0 times for A's mech, so the remote-respawn path never fired. The gate is correct by construction (the isPlayerMech idiom), not proven. BT_AUTODRIVE cannot test the lever itself (forced mode reads forcedThrottle, never sLever), and the zeroing path is the X button, proven in the field. Also keeps BTReportHeatAtReset (heat.cpp, BT_HEAT_LOG): the [heat-t] census runs on a 5s timer, far too coarse to sample AT the reset. It is what proved every roster subsystem including all six Condensers sits at T=77 start=77, and it corrected an earlier false negative from filtering on IsDerivedFrom(HeatSink). KB: context/decomp-reference.md gains the routine/self-clearing condition semantics + this post-mortem, so it is not re-chased; cross-ref in context/gauges-hud.md. Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_018SgmXGNMXavXiafKXf9MDC
This commit is contained in:
co-authored by
Claude Opus 5
parent
5b7e481913
commit
7b003243ae
@@ -2249,6 +2249,54 @@ void
|
||||
BTRecomputeCondenserValves((Entity *)this);
|
||||
}
|
||||
|
||||
// #137 forensic: sample every heat-bearing subsystem's temperature AT the
|
||||
// reset, so "respawn came back with heat MAXED" can be split into "the
|
||||
// reset did not clear it" vs "it climbs again immediately".
|
||||
{
|
||||
extern void BTReportHeatAtReset(void *mech_v);
|
||||
BTReportHeatAtReset((void *)this);
|
||||
}
|
||||
|
||||
// --- DESKTOP THROTTLE RELEASE (#146) -- PORT LAYER, desktop-only ---------
|
||||
// The pod's throttle is a PHYSICAL lever and the binary deliberately
|
||||
// leaves it alone across a respawn: Reset's subsystem loop starts at
|
||||
// index 2 and the ControlsMapper is index 0, so a pod pilot comes back
|
||||
// under whatever power their hand is still holding. Authentic; it stays.
|
||||
//
|
||||
// The desktop bridge only EMULATES that lever, with the persistent ramp
|
||||
// accumulator sLever below -- and a pad/keyboard pilot is physically
|
||||
// holding nothing, with the lever position invisible to them. So they
|
||||
// respawned at speed for no reason they could see, and the mech earned a
|
||||
// real heat load straight out of the drop zone (myomers -> Condenser5 ->
|
||||
// GeneratorD all tripping Overheating inside 1-2s). That is the true
|
||||
// cause of the "#137 respawn came back with heat MAXED" reports -- the
|
||||
// reset itself was always clean. Field-diagnosed from Sauron's
|
||||
// 2026-08-06 log, which reads thr=1 / cycleSpeed=14.6 AT the reset.
|
||||
//
|
||||
// Reuse the existing all-stop path instead of touching sLever directly:
|
||||
// it already zeroes the lever AND clears the zero-crossing detent, and it
|
||||
// lives inside the virtual-controls block that owns that state.
|
||||
//
|
||||
// LOCAL VIEWPOINT MECH ONLY -- gBTDrive is the local bridge's state and
|
||||
// Reset also runs for replicants, so an ungated write here would all-stop
|
||||
// the player every time a REMOTE mech respawned. (Same guard idiom as
|
||||
// the isPlayerMech test in PerformAndWatch.) Pod-safe besides: with a RIO
|
||||
// present mechmppr's key bridge is off (BTRIODevicePresent, mechmppr.cpp
|
||||
// :672) and gBTDrive.throttle is never read at all.
|
||||
// BT_NO_RESPAWN_THROTTLE_RELEASE=1 reverts.
|
||||
if (application != 0 && (Entity *)this == application->GetViewpointEntity())
|
||||
{
|
||||
static const int s_releaseThrottle =
|
||||
getenv("BT_NO_RESPAWN_THROTTLE_RELEASE") ? 0 : 1;
|
||||
if (s_releaseThrottle)
|
||||
{
|
||||
gBTDrive.allStop = 1;
|
||||
if (getenv("BT_DEATH_LOG"))
|
||||
DEBUG_STREAM << "[respawn] desktop throttle released (all-stop queued)\n"
|
||||
<< std::flush;
|
||||
}
|
||||
}
|
||||
|
||||
// --- locomotion pre-run + interest gates (a reset master must tick) ---
|
||||
SetPreRunFlag();
|
||||
if (interestCount == 0) interestCount = 1;
|
||||
|
||||
Reference in New Issue
Block a user