diff --git a/scratchpad/night14/fix137.py b/scratchpad/night14/fix137.py new file mode 100644 index 0000000..760c3fa --- /dev/null +++ b/scratchpad/night14/fix137.py @@ -0,0 +1,69 @@ +"""#137: post the fix write-up. ASCII only.""" +import sys +sys.path.insert(0, r"C:\git\bt411\scratchpad\night7") +import gitea + +BODY = """**FIXED** (`0d6ed40`) -- and my previous two analyses of this ticket were both wrong, so here is +the final, measured story. + +## The fix is ONE LINE, and it is the binary's own + +The binary Reset's SECOND instruction is `FUN_00408440(mech+0x58c, param_2)` -- re-seed the +Point3D at `+0x58c` to the new origin. `+0x58c` is the **previous-position memory** of the +AccelerationLastFrame ring feed (`+0x81c/0x824/0x828/0x82c`). The port reconstructed the ring +faithfully but its Reset never got that line. Restored as: + +```cpp +accelPrevPos = origin.linearPosition; // binary +0x58c re-seed +``` + +## What actually happened at a respawn + +1. The respawn TELEPORTS the mech; `accelPrevPos` still held the death position. +2. First post-respawn sample: `|newPos - prevPos| / dt` = **teleport distance / dt ~ 1e5** enters + the velocity ring; the ring-mean derivative spikes `AccelerationLastFrame` (pure forward, with + an opposite-sign echo ~15 frames later as the sample rotates out of the 15-ring). +3. The myomer drive-heat integrator `@004b8d18`: + `termAccel = (1-accEff) * |v| * |a| * m * dt = 0.2 * 40 * 1.04e5 * 75000 * 0.044 = 2.75e9` + -- one tick deposits ~3e9 into `pendingHeat -> heatEnergy`. +4. The freshly-reset myomers snaps 77 -> ~9000 against `failT=2000` -> `speedEffect 0` -> + `speedDemand *= 0` -> **"respawned with heat maxed, unable to move until it cools"**. The + excess then sheds into Condenser5 and GeneratorD -- Oracle's "loop 5 and generator D heating + up" clause, literally. + +**Why ~8% and why it eluded everyone:** the deposit needs `|v|` in the same 1-2 frames, so only +pilots whose throttle was still forward at the respawn (physical lever / HOTAS -- exactly who +reported it) got the freeze. Idle-throttle respawns deposit nothing. That is also why frozen +respawns were a strict subset of died-hot ones: died hot = was running hard = lever still forward. + +## Measured (same abusive bench: 0.95 throttle, continuous autofire) + +| | before | after | +|---|---|---| +| deposits >1e7 near resets | up to **3.35e9**, every one 3-4 lines after a reset | **0** | +| frozen respawns | 4-6 of 7 | **0 of 7** | +| post-reset myomers T | 7,700-12,100 | 77-178 (degradeT is 1000) | + +## For the record: what it was NOT (each killed by operand data) + +Not the reset (T=77 at every reset, roster-wide). Not stale pendingHeat (1-frame bound, +1.2K). +Not death-window accumulation (consumers tick the wreck). Not conduction (roster snapshot: all +partners at 77; flow trap: zero e6 flows into the myomers). Not drag or impulses (both trapped: +never fired). And not my earlier "players accelerate to top speed" close -- arithmetically +impossible (input ceiling ~60 deg/s vs the observed 1,100-21,000 deg/s snap); the KB paragraph +carrying that claim is corrected. + +The in-life governor is untouched and authentic: sustained top-speed running still derates the +myomers (constants byte-verified). What is gone is the respawn injecting a teleport-sized heat +slug. + +Credit where due: the operator called the shape of this from the start -- *"maybe the math gets +screwy in respawning while some systems are ticking while values are being reset."* + +**Unreleased; needs a build cut. Field-verify:** respawn while holding the throttle forward on a +HOTAS -- the mech should drive off cleanly with a cold heat bar every time. Gotcha #30 records the +class so the next dropped re-seed gets caught in review.""" + +gitea.comment(137, BODY) +gitea.call("/issues/137", method="PATCH", payload={"state": "closed"}) +print("posted + closed #137")