#86: destroyed weapons can no longer fire -- the fire gates read a
never-written cell (the split-cell gotcha) Both weapon fire gates (ProjectileWeapon gate 1 @4bbd36, Emitter hard-failure @4baab9) test the binary's subsystem+0x40 for Destroyed(1). In the 1995 layout that offset sits INSIDE the embedded status alarm (statusAlarm@0x2C + level@+0x14 = 0x40) -- ONE cell, written by ForceCriticalFailure when a zone's crit cascade kills the subsystem. The port models the same address as TWO members: the AlarmIndicator AND a plain int simulationState@0x40. Every destruction path writes the ALARM (so the MFD draws its X correctly) while the gates read the plain int, which nothing ever writes -- so a weapon on a blown-off arm showed destroyed on every panel and kept firing and scoring, locally and on peers (night-7: all three testers, screenshots of a missile leaving a destroyed pod). The tell had been sitting in our own logs for weeks: [ammo] SRM6_1 -> NoAmmo (gate1): destroyed=0 ... on a mech whose launcher was X'd out. Fix: both gates now read statusAlarm.GetLevel()==1 as well as the int. Also added: the crit-cascade log names the destroyed subsystem, a BT_SELF_DAMAGE_ZONE=dz_* named-zone bench mode, and BT_KILL_SUBSYS=<name> (force ForceCriticalFailure on one named subsystem -- the exact call the zone cascade makes, so a bench can ask 'the panel says dead, does it still shoot?' without hunting for the zone that carries a given weapon). Verified A/B in ONE run: before the kill both SRM6 launchers fired 2 salvos each; after, the destroyed launcher fired ZERO (gate log destroyed=1) while its twin kept firing normally. KB: new gotcha #22 (the SPLIT CELL -- one binary offset, two port members, only one written; sibling of #1) + combat-damage entry. Co-Authored-By: Claude Fable 5 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_019Zh7PTkFy4KwTzVighLR9J
This commit is contained in:
co-authored by
Claude Fable 5
parent
62fc8409b6
commit
5410371b0c
@@ -376,6 +376,17 @@ thruster table (ModelList ids aliased to their type-15 member); both launch path
|
||||
Note: the Black Hawk's "SRM6" fires **strk** (Streak) ammo per its bin -- the ammo model, not
|
||||
the launcher name, decides the flight profile.
|
||||
|
||||
## Destroyed weapons kept FIRING -- FIXED (2026-07-31, issue #86) [T1/T2]
|
||||
The fire gates (`ProjectileWeaponSimulation` gate 1 @4bbd36, `EmitterSimulation` hard-failure
|
||||
@4baab9) test `subsystem+0x40` for Destroyed(1). In the binary that offset IS the status alarm's
|
||||
level cell; the port splits it into `statusAlarm` + a never-written `int simulationState`, so the
|
||||
gates read a dead cell -- a weapon on a destroyed mount showed its X on the MFD and kept firing
|
||||
and SCORING (night-7: all three testers, with screenshots of a missile leaving a destroyed pod).
|
||||
Fixed by reading BOTH cells in both gates; the full pattern is [[reconstruction-gotchas]] §22.
|
||||
Verified A/B in one run (BT_KILL_SUBSYS bench hook -> ForceCriticalFailure, the same call the
|
||||
zone crit-cascade makes): before the kill both SRM6 launchers fired 2 salvos each; after, the
|
||||
destroyed launcher fired ZERO (gate log `destroyed=1`) while its twin kept firing.
|
||||
|
||||
## Ballistic damage type -- FIXED (2026-07-23, issue #27) [T2]
|
||||
Playtest matchlog forensics (2,591 applied-damage events over 2 rounds): the damageType
|
||||
histogram had Collision/Explosive/Laser/Energy but **Ballistic (type 1) NEVER appeared**,
|
||||
|
||||
@@ -717,3 +717,23 @@ capstone over the CODE section for the addressing form (e.g. FPU reads of `[reg+
|
||||
`[reg+reg*4+0x330]`). Minutes of scanning; it found in one pass what three decomp sweeps
|
||||
missed. Corollary: when the decomp and a PRIMARY SOURCE (the manual, a pod veteran) disagree,
|
||||
treat the disagreement as a hole in YOUR evidence first, not in theirs.
|
||||
|
||||
|
||||
## §22 — The SPLIT CELL: one binary offset, two port members (only one gets written)
|
||||
**(2026-07-31, gitea #86 "destroyed weapons keep firing".)** The binary's weapon fire gates test
|
||||
`subsystem+0x40`. In the 1995 layout that offset is *inside* the embedded status alarm
|
||||
(`statusAlarm@0x2C` + the indicator's level at `+0x14` = `0x40`) — **one cell**, written by
|
||||
`ForceCriticalFailure` when a zone's crit-cascade kills the subsystem. The port models the same
|
||||
address as TWO independent members: `AlarmIndicator statusAlarm` **and** a plain
|
||||
`int simulationState@0x40`. Every destruction path writes the ALARM (so the MFD correctly draws
|
||||
its X, the paper doll correctly greys the mount) while the fire gates read the plain int — which
|
||||
nothing ever writes. Result: a weapon on a blown-off arm shows destroyed on every panel and
|
||||
keeps firing and scoring, on the shooter's screen and on peers' (all three night-7 testers).
|
||||
**Detection smell:** a diagnostic that prints the gate's own inputs and shows a state flag
|
||||
reading 0 while the UI bound to "the same" state shows destroyed. (`[ammo] NoAmmo (gate1):
|
||||
destroyed=0` on a mech with an X'd-out launcher was the tell — it sat in the logs for weeks.)
|
||||
**Rule:** when a binary offset falls inside an embedded object in OUR layout, do not mirror it as
|
||||
a sibling scalar — read it through the object that owns it, or (if a duplicate member already
|
||||
exists) make every gate read BOTH and every writer write BOTH. Sibling of gotcha #1 (shadowed
|
||||
base field): same failure shape — two cells where the binary has one, and the readers pick the
|
||||
dead one.
|
||||
|
||||
Reference in New Issue
Block a user