#21 closed at the true root + 'arcade shipped a brick' RETRACTED (era witnesses 6-0): _DAT_004ba830 is a DOUBLE 1.0, not float 0.0 -- the entire brick claim was a constant-width misread (dword read of a qword; the low half of 1.0's mantissa is zeros). Binary truth [T1 raw disasm @004ba738]: overcharge CLAMPS to exactly 1.0f, the ==1.0 Loaded test passes next tick, the weapon fires the stored charge at normal top-gear damage (divisor is the recommended gear). Fix: clamp corrected to 1.0f; the rescue scaffolding REMOVED (it patched our own misread -- 38 'rescues' were 38 events the machine silently clamped); gauge-side zeroing inherits the fix, which is almost certainly #21's ORIGINAL field symptom (dark recharge arc + dark ready-dot = the dial reading our zeroed ratio while the rescue kept the weapon firing). seek21 bench PASS: 65 switches / 16 wraps / 9 overcharges -> fires through all, 13 post-overcharge gauge probes FULL, zero rescue prints. Docs: field guide section 2 rewritten as settled-by-testimony (credit to the group), decomp-reference block retracted with extracted constants, drift audit energy lane -> FAITHFUL, ZERO deviations. The witnesses' 'nah, that didn't happen' was worth eight bytes read at full width
This commit is contained in:
+13
-12
@@ -436,18 +436,19 @@ From the weapon `.SUB` records + the charge-curve `.data` constants (PE-parsed a
|
||||
the Execute machine, but this handler overwrites it). The earlier "jams are
|
||||
mission-permanent / no unjam" claim was WRONG (read only the hold path) — corrected +
|
||||
swept 2026-07-23 (projweap.cpp case-5/jam-log comments, players/README.txt).
|
||||
**LATENT ARCADE BUG found + diverged (issue #21, 2026-07-21) [T1 byte-verified + T2 repro]:**
|
||||
the Emitter charge integrates toward the GENERATOR voltage (@004ba838 `fld [src+0x1dc]`), full
|
||||
is detected only inside the +-1% snap window around `seekVoltage[idx]` (ComputeOutputVoltage
|
||||
@004ba738: `|rl-1|<=0.01 -> 1.0`), and OVERCHARGE reads ZERO (`rl>1.01 -> 0`,
|
||||
`_DAT_004ba830 = 0.0` byte-verified). Toggle the seek gear while a charge is in flight and
|
||||
the level lands ABOVE the new gear's window -> rechargeLevel pinned 0, the `==1.0` Loaded test
|
||||
(`_DAT_004bac04`) never fires, charging continues to the generator ceiling where EVERY gear
|
||||
reads overcharged -> the weapon is PERMANENTLY bricked (arc dark, ready-dot dark, no fire; gen
|
||||
re-select cannot help). The arcade shipped this (locked 60 fps + rare seek use hid it); the
|
||||
port's clickable seek button triggers it in seconds. **Deliberate divergence** (emitter.cpp
|
||||
Loading tick): overcharge (`currentLevel > seekVoltage[idx]`) counts as fully charged ->
|
||||
Loaded ("full == the gear's seek voltage" is the arcade's own discharge algebra). Repro +
|
||||
**#21 RETRACTED 2026-08-13 (era testimony -> adversarial re-audit; witnesses 6-0):** the
|
||||
"LATENT ARCADE BUG / permanently bricked / the arcade shipped this" claim that stood here was
|
||||
a CONSTANT-WIDTH MISREAD. `_DAT_004ba830` is a **DOUBLE 1.0** (bytes 00..00 f0 3f @0x4ba830 --
|
||||
the old "0.0 byte-verified" read the low DWORD of a QWORD: 1.0's mantissa zeros; Ghidra's own
|
||||
"globals overlap smaller symbols" warning applies). ComputeOutputVoltage @004ba738 truth [T1
|
||||
raw disasm]: ratio = charge/seekV[idx]; snap |rl-1|<=0.01 -> 1.0f; else CLAMP to [0,1] --
|
||||
overcharge stores EXACTLY 0x3f800000, the `==1.0` Loaded test passes next tick, the weapon
|
||||
FIRES the stored charge (damage divisor is the RECOMMENDED gear, so a wrap-fired charge deals
|
||||
normal top-gear damage). ToggleSeekVoltage @004ba478 genuinely skips ResetFiringState on wrap
|
||||
[T1] -- but nothing downstream ever bricks. The machine never had a dark laser; the port's
|
||||
"rescue" was a patch over OUR misread (removed with the clamp fix, same date). Constants
|
||||
extracted: 0x4ba818=0.0f 0x4ba81c=1e-4f 0x4ba820=1.0f 0x4ba824=0.01f 0x4ba828=dbl 0.0
|
||||
0x4ba830=dbl 1.0 0x4bac04=1.0f. Gotcha family 30/31 (width/scope misreads). Repro +
|
||||
verify: BT_SEEKTEST seek-abuse -- pre-fix deadlocks at pct=0/alarm=3; post-fix 38 rescues,
|
||||
ends Loaded/pct=1. `[seek]` log prints the per-gear table + rescue events.
|
||||
- **EJECT/PANIC cluster DECODED + WIRED 2026-08-02 [T1 raw disasm]:** `@0049f854`
|
||||
|
||||
+30
-14
@@ -24,14 +24,14 @@ the queued ticket comment until the group signs off.
|
||||
| 2 | PPC/ERPPC fire chain (0xBD4) | FAITHFUL |
|
||||
| 3 | PPC rider (a) victim display scramble | KNOWN-DIVERGENCE [T3] (unimplemented; visual OPEN) |
|
||||
| 4 | PPC rider (b) victim generator short | FAITHFUL (tag-label scope OPEN) |
|
||||
| 5 | Seek-voltage gears + #21 overcharge brick | KNOWN-DIVERGENCE (deliberate rescue) |
|
||||
| 5 | Seek-voltage gears (#21) | FAITHFUL (brick claim RETRACTED 2026-08-13 -- constant-width misread; binary clamps overcharge to 1.0 and fires; witnesses 6-0) |
|
||||
| 6 | Autocannons AFC25/50/100 (0xBCD) | FIXED-THIS-BUILD (#171; T2 field receipts pending) |
|
||||
| 7 | AC cosmetic tracer visual | KNOWN-DIVERGENCE [T3] (cosmetic; constants recovered — close) |
|
||||
| 8 | GAUSS (fielded, 0xBCD record) | FAITHFUL (correction sweep owed, HELD) |
|
||||
| 9 | GaussRifle class 0xBCE (+ shell 0xBD1) | FAITHFUL (dead code both sides) |
|
||||
| 10 | MissileLauncher core (0xBD0, all racks) | FAITHFUL |
|
||||
| 11 | Missile presentation (salvo visuals/gains) | KNOWN-DIVERGENCE [T3] (presentation-only) |
|
||||
| 12 | Missile bystander sweep | KNOWN-DIVERGENCE [T3] (largest remaining gap) |
|
||||
| 12 | Missile bystander sweep | FIXED-THIS-BUILD (capsule sweep [T3 radius]; T2 field receipts pending) |
|
||||
| 13 | Missile splash (@0042fad0) | FAITHFUL under stock content (gate wiring [T3] on custom eggs) |
|
||||
| 14 | LRM flight + loft | FAITHFUL |
|
||||
| 15 | Streak racks (strk model) | FAITHFUL |
|
||||
@@ -94,11 +94,13 @@ content.
|
||||
- **Verdict:** FAITHFUL (tag-label scope OPEN). NOTE: the two riders'
|
||||
port status differs — never lump them in vet-facing docs.
|
||||
|
||||
### 5. Seek-voltage gears + #21 overcharge brick (all energy weapons)
|
||||
### 5. Seek-voltage gears (#21) -- brick claim RETRACTED 2026-08-13
|
||||
- **Binary [T1]:** `ToggleSeekVoltage` @004ba478 (vet/expert only): wrap
|
||||
from gear 4→1 skips `ResetFiringState` → charge above snap window →
|
||||
`ComputeOutputVoltage` overcharge reads ZERO → weapon PERMANENTLY
|
||||
BRICKED. The arcade shipped this latent brick.
|
||||
~~overcharge reads ZERO → PERMANENTLY BRICKED~~ **RETRACTED: _DAT_004ba830
|
||||
is a DOUBLE 1.0 (width misread); the binary CLAMPS overcharge to 1.0 and
|
||||
the weapon fires -- the machine never bricked. Era witnesses (6-0) triggered
|
||||
the re-audit; full detail in context/decomp-reference.md.**
|
||||
- **Port [T3 deliberate, documented]:** overcharge counts as Loaded (issue
|
||||
#21, 38 benched rescues) — the port's ONE deliberate energy-lane
|
||||
divergence; lives in the deviations appendix.
|
||||
@@ -200,12 +202,25 @@ One class, data-differentiated.
|
||||
- **Binary [T1]:** FUN_0042291c swept real world geometry including movers
|
||||
each tick — a third mech in the flight path could be struck by someone
|
||||
else's missile.
|
||||
- **Port [T3]:** pool rounds contact only the locked target + terrain; a
|
||||
mech between shooter and target is flown through (splash alone can touch
|
||||
bystanders).
|
||||
- **Verdict:** KNOWN-DIVERGENCE [T3] — largest remaining missile-physics
|
||||
gap. Field-guide watch item for Friday ("hit by missiles aimed at
|
||||
someone else" beyond splash range).
|
||||
- **Port [T3 radius / port-shape, landed 2026-08-13]:** `mech4.cpp
|
||||
BTUpdateProjectiles` — per frame, damage-carrying GUIDED rounds (the one
|
||||
salvo lead) run a nearest-approach test of the flight segment against a
|
||||
VERTICAL CAPSULE per other registered mech (BTGetTargetCandidates walk;
|
||||
shooter + locked target excluded — the target keeps its own 4.0u fuze).
|
||||
Capsule derived from the victim's own collision template
|
||||
(Mover::GetCollisionTemplate BoxedSolid: axis = origin up minY..maxY,
|
||||
radius = larger horizontal half-extent; fallback 3.5u × 14u when the
|
||||
template is unresolved [T3]). Earliest contact along the segment wins
|
||||
(bystander vs target fuze compared by segment param); the struck mech
|
||||
becomes the DIRECT victim through the unchanged dispatch path (cluster
|
||||
roll + splash semantics identical, splash excludes the new direct
|
||||
victim). Wrecks stay in the sweep — binary detonates on any solid; the
|
||||
#174 victim-side guard keeps dead zones from cascading/scoring. Capped
|
||||
`[projectile] BYSTANDER` receipt (24 prints) for field forensics.
|
||||
- **Verdict:** FIXED-THIS-BUILD (radius is a [T3] capsule approximation of
|
||||
the real solid sweep; T2 field receipts pending — Friday watch item
|
||||
unchanged: "hit by missiles aimed at someone else" now expected INSIDE
|
||||
splash range too).
|
||||
|
||||
### 13. Missile splash — Explosion::SplashDamage @0042fad0
|
||||
- **Binary [T1]:** gated on the FIRING player's advancedDamage (+0x264;
|
||||
@@ -368,8 +383,9 @@ Several 'LRM5/10/15' bins author nrk ammo.
|
||||
Announced to the vets in the field guide §9.
|
||||
3. PPC gauge-scramble rider: BLOCKED on era testimony (field guide §3) —
|
||||
build the visual only after the group answers.
|
||||
4. Missile bystander sweep: design exists; field guide §6 arms the Friday
|
||||
watch item.
|
||||
4. Missile bystander sweep: LANDED 2026-08-13 (lane 12 entry) together
|
||||
with coast gravity (dt-table row); field guide §6's Friday watch item
|
||||
now doubles as the T2 verification channel.
|
||||
|
||||
## Era questions shipped to the vets
|
||||
|
||||
@@ -560,7 +576,7 @@ round is a renderer cosmetic with no Mover physics.
|
||||
| **Drag** | `−COD·ρ·sign(v)·v²` per body axis, EVERY frame, burn + coast (@004bef78, power-2 inline; plain-Projectile dead class uses power 1.0 @004bddec); CODs 0.001 [T1 bytes]; terminal `sqrt(T/c)` precomputed @004bf5b4→+0x348 | **OMITTED** ("negligible") | **WAS DIVERGENT → FIXED-THIS-BUILD** | was: LRM 3030 u/s (5.5× cap), −13% time-to-800u, +40% impact speeds, map-crossing runaways past 2.5 s; now governed at 547.7/774.6 |
|
||||
| Speed clamp | none — drag IS the clamp | none — drag now is | **FAITHFUL** (post-fix) | — |
|
||||
| Velocity↔seeker slaving | burning: lateral local vel/accel zeroed each frame ⇒ velocity ≡ speed×nose; nose slerps ≤ MaxThrusterRotationRate·dt (@004be474); at burnout slaving STOPS (ballistic coast) | rotate-toward-aim at port gains 4/8·dt, speed-normalized; steers through coast | KNOWN-DIVERGENCE [T3] (lane 11) | turn dynamics shape; coast homing (real impacts are in-burn) |
|
||||
| Gravity | none during burn; coast: `worldAccel.y −= 6.5` fresh each frame (env default) + y<−1 kill plane | absent (loft arc + ttl only) | DIVERGENT [T3 **minor**, unfixed] | post-burnout flights only (beyond ~1400u SRM / ~4800u LRM); missed rounds fly level instead of dropping |
|
||||
| Gravity | none during burn; coast: `worldAccel.y −= 6.5` fresh each frame (env default) + y<−1 kill plane | absent (loft arc + ttl only) | **WAS DIVERGENT → FIXED 2026-08-13** (`vel.y −= 6.5·coast_dt` on thruster rounds after burnout, exact at the burnout boundary; speed re-synced to |vel|) | post-burnout flights only; missed rounds now drop instead of flying level |
|
||||
| Position step | `p += v_old·dt + ½a·dt²` | `p += v_new·dt` (semi-implicit) | FAITHFUL-approx | ≤ ~12u lead over a full SRM burn @60fps; imperceptible |
|
||||
| Expiry | burn+10 s, y<−1 (@004bef78 tail) | same (#168) | **FAITHFUL** | none |
|
||||
| Seeker lead | `aim += targetVel × range/terminal(+0x348)`; loft climb-gated (thruster+0xF0 > _DAT_004bec1c) | live-position re-lead; loft constants exact | KNOWN-DIVERGENCE [T3] (lane 11) | small lead-shape difference |
|
||||
|
||||
@@ -80,31 +80,32 @@ WE NEED YOUR MEMORY
|
||||
>
|
||||
|
||||
-----------------------------------------------------------------------------
|
||||
2. THE CHARGE GEAR (ALL ENERGY WEAPONS) -- AND THE BRICK THE ARCADE SHIPPED
|
||||
2. THE CHARGE GEAR (ALL ENERGY WEAPONS) -- SETTLED BY YOUR MEMORY
|
||||
-----------------------------------------------------------------------------
|
||||
THE ORIGINAL'S BEHAVIOR
|
||||
Veteran/expert pilots could cycle an energy weapon's charge gear
|
||||
(four settings). The machine shipped with a latent flaw: cycling
|
||||
PAST the top gear wrapped to the bottom without resetting the firing
|
||||
state. The stored charge now sat above the new gear's release
|
||||
window, the output read zero, and the weapon went permanently dark
|
||||
-- charged, lit, and unable to fire until re-arm. The arcade
|
||||
shipped this.
|
||||
(four settings). Cycling past the top wraps to the bottom and the
|
||||
weapon keeps working: a stored charge above the new gear's level
|
||||
simply counts as FULL and fires (a wrap-fired top-gear charge deals
|
||||
its normal top-gear damage -- no secret super-shot, no dead weapon).
|
||||
|
||||
FOR THE RECORD: an earlier version of this document claimed the
|
||||
machine shipped a flaw here -- that wrapping the gear left the
|
||||
weapon permanently dark. Several of you said flatly that never
|
||||
happened. You were right. The re-audit you triggered found our
|
||||
reading of one number in the original's code was wrong by a single
|
||||
byte-width, and the "brick" existed only in our port, never on the
|
||||
machine. This section is your correction, adopted.
|
||||
|
||||
OUR PORT TODAY
|
||||
We deliberately rescue it: an overcharged weapon counts as loaded
|
||||
and fires (#21; 38 rescues proven on the bench). This is the port's
|
||||
ONE deliberate deviation in the energy lane, and it stays on the
|
||||
deviations list so nobody mistakes it for the original.
|
||||
Fixed to match: cycling behaves exactly as you remember. (Before
|
||||
the fix our gauges could briefly read EMPTY on an over-charge where
|
||||
the machine read FULL -- if you saw that, it dies in the next
|
||||
build.)
|
||||
|
||||
CHANGING IN THE NEXT BUILD
|
||||
Nothing -- unless the group votes for the authentic brick.
|
||||
|
||||
WE NEED YOUR MEMORY
|
||||
- Did cycling a laser's gear past the top setting ever leave the
|
||||
weapon DARK -- charged but refusing to fire until re-arm? If pods
|
||||
genuinely ate weapons this way, some of you will remember it.
|
||||
|
||||
The correction above ships. The old "deviation" entry is withdrawn
|
||||
-- the energy lane now has ZERO deviations from the original.
|
||||
|
||||
YOUR NOTES (callsign first, one entry per line):
|
||||
>
|
||||
|
||||
@@ -24,7 +24,10 @@
|
||||
// _DAT_004ba820 = 00 00 80 3f = 1.0f (full-charge reference / upper clamp)
|
||||
// _DAT_004ba824 = 0a d7 23 3c = 0.01f (snap-to-1.0 tolerance)
|
||||
// _DAT_004ba828 = 00 00 00 00 = 0.0f (below-range clamp result)
|
||||
// _DAT_004ba830 = 00 00 00 00 = 0.0f (above-range clamp result)
|
||||
// _DAT_004ba830 = 00 00 00 00 00 00 f0 3f = DOUBLE 1.0 (above-range clamp result;
|
||||
// #21 CORRECTION 2026-08-13: this operand is a QWORD -- the old
|
||||
// "byte-verified 0.0f" dword-read only the LOW 4 bytes (1.0's mantissa
|
||||
// zeros) of the 8-byte constant. gotcha 30/31 literal-width family.)
|
||||
// _DAT_004ba9a4 = 00 00 00 00 = 0.0f (dischargeTimer expiry threshold)
|
||||
// _DAT_004bac04 = 00 00 80 3f = 1.0f (outputVoltage "fully charged" test)
|
||||
// _DAT_004bac08 = 00 00 00 00 = 0.0f (firing dischargeTimer expiry threshold)
|
||||
@@ -498,21 +501,16 @@ void
|
||||
// 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
|
||||
// POD-FRAME SUB-STEPPING (task #11): run the binary's own Loading
|
||||
// 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.
|
||||
// at the binary's locked 60 fps. Justification: the I^2R generator
|
||||
// feed integral -- TrackSeekVoltage's seekRate^2 heat evaluated over
|
||||
// big variable-dt steps uses a stale level and OVER-heats the
|
||||
// generators. (The former "weapon-brick fix" rationale was FALSE --
|
||||
// see the #21 correction in ComputeOutputVoltage: the >1.0 clamp
|
||||
// stores 1.0f, so an overshot charge goes Loaded next tick at any dt.)
|
||||
// Sub-step count is bounded; leftover time under extreme throttling
|
||||
// just resumes next frame.
|
||||
{
|
||||
static const Scalar kPodFrame = 1.0f / 60.0f;
|
||||
Scalar remaining = time_slice;
|
||||
@@ -531,32 +529,13 @@ void
|
||||
weaponAlarm.SetLevel(2); // -> Loaded
|
||||
break;
|
||||
}
|
||||
// OVERCHARGE RESCUE (issue #21, 2026-07-21) -- a DELIBERATE
|
||||
// divergence from the binary, which DEADLOCKS here: change the
|
||||
// seek gear while a charge is in flight and the level can land
|
||||
// ABOVE the new gear's snap window (level/seekV > 1.01) -- the
|
||||
// byte-verified ComputeOutputVoltage clamp then zeroes
|
||||
// rechargeLevel (_DAT_004ba830 = 0.0) and the ==1.0 Loaded test
|
||||
// can never fire again while TrackSeekVoltage keeps charging
|
||||
// toward the generator voltage: the weapon is PERMANENTLY
|
||||
// bricked (arc dark, dot dark, never fires -- reproduced
|
||||
// headless, and trivial to trigger from the clickable seek
|
||||
// button; the pod's locked 60 fps + rare seek use hid it).
|
||||
// The arcade's own math says "full == the gear's seek voltage"
|
||||
// (discharge energy computes from seekV[rec]), so an
|
||||
// overcharged weapon IS fully charged -- treat it as Loaded.
|
||||
if (currentLevel > seekVoltage[seekVoltageIndex]
|
||||
&& seekVoltage[seekVoltageIndex] > 0.0f)
|
||||
{
|
||||
rechargeLevel = 1.0f; // full (the display/damage ratio)
|
||||
weaponAlarm.SetLevel(2); // -> Loaded
|
||||
if (getenv("BT_SEEK_LOG"))
|
||||
DEBUG_STREAM << "[seek] " << GetName()
|
||||
<< " overcharge rescue: level=" << currentLevel
|
||||
<< " > seekV=" << seekVoltage[seekVoltageIndex]
|
||||
<< " -> Loaded" << std::endl;
|
||||
break;
|
||||
}
|
||||
// The old OVERCHARGE RESCUE (issue #21, 2026-07-21) lived here.
|
||||
// REMOVED 2026-08-13: it patched an artifact of the
|
||||
// _DAT_004ba830 width misread (double 1.0 dword-read as float
|
||||
// 0.0). With the faithful clamp in ComputeOutputVoltage an
|
||||
// overcharged weapon snaps rechargeLevel to exactly 1.0f, so
|
||||
// the ==1.0f test above takes it to Loaded naturally -- the
|
||||
// binary never deadlocked here and neither do we.
|
||||
}
|
||||
}
|
||||
break;
|
||||
@@ -801,7 +780,17 @@ void
|
||||
}
|
||||
else if (rechargeLevel > 1.0f) // _DAT_004ba820
|
||||
{
|
||||
rechargeLevel = 0.0f; // _DAT_004ba830 (NB: also 0.0f)
|
||||
// #21 CORRECTION (2026-08-13, adversarial re-audit, raw-byte disasm):
|
||||
// _DAT_004ba830 is a DOUBLE 1.0 (bytes 00 00 00 00 00 00 f0 3f), NOT
|
||||
// float 0.0 -- the old "byte-verified 0.0f" dword-read the LOW HALF of
|
||||
// the qword (1.0's mantissa zeros; gotcha 30/31 literal-width family).
|
||||
// Overcharge clamps to EXACTLY 1.0f (0x3f800000 stored), so the ==1.0f
|
||||
// Loaded test (_DAT_004bac04) passes next tick and the weapon fires.
|
||||
// The machine NEVER bricked on overcharge; era testimony that no weapon
|
||||
// ever went permanently dark triggered the re-audit. This faithful
|
||||
// clamp supersedes the old "overcharge rescue" divergence (removed
|
||||
// from EmitterSimulation's Loading case).
|
||||
rechargeLevel = 1.0f; // _DAT_004ba830 (double 1.0, stored as float)
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -0,0 +1,33 @@
|
||||
#!/usr/bin/env bash
|
||||
# #21 CORRECTION bench (2026-08-13): the faithful overcharge clamp.
|
||||
#
|
||||
# THE OLD SHAPE (21b2bfc, 2026-07-21): 2.5 min of BT_SEEKTEST abuse (dispatches
|
||||
# the SAME ReceiverDataMessageOf id-0xb press the clickable seek button sends,
|
||||
# every ~2s) bricked the laser pre-rescue and produced "38 overcharge rescues"
|
||||
# post-rescue.
|
||||
#
|
||||
# THE NEW PASS (post-correction -- _DAT_004ba830 is a DOUBLE 1.0, overcharge
|
||||
# clamps rechargeLevel to EXACTLY 1.0f):
|
||||
# 1. gear cycling happens, including WRAPS past top (prev > next skips
|
||||
# ResetFiringState -- the overcharge composition);
|
||||
# 2. overcharge compositions observed ([seek] gear-switch lines where the
|
||||
# in-flight level lands ABOVE the new gear's snap window, level > 1.01*seekV);
|
||||
# 3. the weapon KEEPS FIRING after the last overcharge (no dark state);
|
||||
# 4. gauges non-zero: [fire-probe] pct=1 (rechargeLevel, the recharge-dial
|
||||
# source) seen after the last overcharge;
|
||||
# 5. ZERO "rescue" prints anywhere in the log (the rescue block is gone).
|
||||
set -x
|
||||
. /c/git/bt411/scratchpad/night6/bench_common.sh
|
||||
cd /c/git/bt411/content || exit 1
|
||||
taskkill //F //IM btl4.exe >/dev/null 2>&1; sleep 3
|
||||
rm -f sk21.log
|
||||
bt_expert_egg MP.EGG SK21.EGG
|
||||
sed -i "s/^map=.*/map=grass/; s/^time=.*/time=day/; s/^vehicle=.*/vehicle=vulture/" SK21.EGG
|
||||
|
||||
( export BT_SEEKTEST=1 BT_AUTOFIRE=1 BT_FIRE_AT_ICON=1
|
||||
export BT_SEEK_LOG=1 BT_FIRE_LOG=1 BT_DMG_LOG=1
|
||||
bt_launch sk21.log SK21.EGG 0x03 )
|
||||
sleep 160
|
||||
bt_kill_ours; sleep 2; taskkill //F //IM btl4.exe >/dev/null 2>&1
|
||||
|
||||
python /c/git/bt411/scratchpad/night17/seek21_check.py /c/git/bt411/content/sk21.log
|
||||
@@ -0,0 +1,68 @@
|
||||
# #21 correction bench checker -- see seek21_bench.sh for the PASS contract.
|
||||
import io, re, sys
|
||||
|
||||
path = sys.argv[1] if len(sys.argv) > 1 else "/c/git/bt411/content/sk21.log"
|
||||
L = io.open(path, encoding="latin-1", errors="replace").read().splitlines()
|
||||
|
||||
# Emitter gear-switch lines (Myomers [seek] lines lack "seekV["):
|
||||
# [seek] NAME -> gear N seekV[N]=X table={...} max=M level=L genV=...
|
||||
gear_re = re.compile(
|
||||
r"\[seek\] (\S+) -> gear (\d+) seekV\[\d+\]=([-\d.eE+]+) .*level=([-\d.eE+]+)")
|
||||
gears = [] # (line_idx, name, gear, seekV, level)
|
||||
for i, l in enumerate(L):
|
||||
m = gear_re.search(l)
|
||||
if m:
|
||||
gears.append((i, m.group(1), int(m.group(2)),
|
||||
float(m.group(3)), float(m.group(4))))
|
||||
|
||||
names = sorted(set(g[1] for g in gears))
|
||||
print("=== #21 CORRECTION BENCH (faithful overcharge clamp) ===")
|
||||
print("weapon(s) under seek cycling:", names or "NONE")
|
||||
|
||||
ok = True
|
||||
if not gears:
|
||||
print("FAIL: no emitter [seek] gear lines -- rig broken (expert gate? seektest?)")
|
||||
ok = False
|
||||
|
||||
for name in names:
|
||||
G = [g for g in gears if g[1] == name]
|
||||
wraps = sum(1 for a, b in zip(G, G[1:]) if b[2] < a[2])
|
||||
over = [g for g in G if g[3] > 0.0 and g[4] > 1.01 * g[3]]
|
||||
fired_all = [i for i, l in enumerate(L) if ("FIRED '%s'" % name) in l]
|
||||
last_over = over[-1][0] if over else None
|
||||
fired_after = ([i for i in fired_all if i > last_over]
|
||||
if last_over is not None else [])
|
||||
# gauge source: [fire-probe] NAME ... pct=1 after the last overcharge
|
||||
pct1_after = 0
|
||||
if last_over is not None:
|
||||
pr = re.compile(r"\[fire-probe\] %s .*pct=([-\d.eE+]+)" % re.escape(name))
|
||||
for l in L[last_over:]:
|
||||
m = pr.search(l)
|
||||
if m and float(m.group(1)) >= 0.999:
|
||||
pct1_after += 1
|
||||
# tail liveness: still firing in the last 25% of the run
|
||||
tail = int(len(L) * 0.75)
|
||||
fired_tail = sum(1 for i in fired_all if i >= tail)
|
||||
|
||||
print("-- %s: gearSwitches=%d wraps=%d overchargeEvents=%d "
|
||||
"FIRED total=%d afterLastOver=%d pct=1 probes after=%d tailFIRED=%d"
|
||||
% (name, len(G), wraps, len(over), len(fired_all),
|
||||
len(fired_after), pct1_after, fired_tail))
|
||||
|
||||
if wraps < 1:
|
||||
ok = False; print("FAIL(%s): no wrap past top gear" % name)
|
||||
if not over:
|
||||
ok = False; print("FAIL(%s): no overcharge composition ever formed" % name)
|
||||
if last_over is not None and not fired_after:
|
||||
ok = False; print("FAIL(%s): NEVER FIRED after the last overcharge -- dark state" % name)
|
||||
if last_over is not None and pct1_after < 1:
|
||||
ok = False; print("FAIL(%s): recharge gauge (pct) never read full after overcharge" % name)
|
||||
if fired_tail < 1:
|
||||
ok = False; print("FAIL(%s): not firing in the run tail -- possible late brick" % name)
|
||||
|
||||
rescues = sum(1 for l in L if "rescue" in l)
|
||||
print("rescue prints in log:", rescues)
|
||||
if rescues != 0:
|
||||
ok = False; print("FAIL: rescue print still present")
|
||||
|
||||
print("RESULT:", "PASS" if ok else "FAIL")
|
||||
Reference in New Issue
Block a user