Death effects dispatch at the victim's death transition (task #42)

User report: enemy takes hits, starts smoking, then beams pass through
-- no more damage, no death. Root cause: the death-effects dispatch
(blhdead explosion chain + wreck swap + KILL score) lived in the
SHOOTER's laser fire block kill check. A missile killing blow lands
frames later in BTUpdateProjectiles -- outside that block -- and after
task #41 the boresight pick skips a dead mech, so the fire block never
ran against it again: the death chain was silently skipped, leaving an
internally-dead, smoking, standing, invulnerable mech.

Fix: the dispatch moved to the VICTIM's own once-per-death transition
(UpdateDeathState's movementMode->9 moment) -- fires exactly once for
ANY kill source (laser, missile, collision). Killer id for the
Explosion message = lastInflictingID (the task-#31 bookkeeping). The
BT_ENABLE_TEARDOWN cdb harness was removed with the old block (findings
preserved in docs/HARD_PROBLEMS.md).

Verified headless (75s soak, missile-heavy kill): destroyed ->
'blhdead' id=22 -> wreck swap 'blhdbr.bgf' -> smoke re-arm -> sink ->
buried INERT; post-death picks fall through to terrain; 0 crashes.

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
This commit is contained in:
arcattack
2026-07-09 00:21:03 -05:00
co-authored by Claude Fable 5
parent e30a61a62f
commit 305c928923
2 changed files with 80 additions and 102 deletions
+8
View File
@@ -271,6 +271,14 @@ Full decomp map of the death path. Two tiers:
`<prefix>dbr.bgf` on the tree root (gendbr fallback; pending-swap if death precedes tree build).
Mesh flames + the settle motion are noted follow-ups; burning reads via 1001/1007 + the wreck-smoke
re-arm. Verified: `[BTrender] wreck swap: victim -> 'blhdbr.bgf'`. [T2]
⚠ **The death-effects DISPATCH lives at the VICTIM's death transition** (`UpdateDeathState`'s
movementMode→9 moment, task #42) — NOT in any shooter's fire path. It originally sat in the
laser fire block's kill check, which a MISSILE killing blow (landing frames later in
`BTUpdateProjectiles`) never reached — and post-#41 the boresight pick skips a dead mech, so the
block never re-ran: internally dead, smoking, standing, invulnerable (user-reported). The
transition fires once for ANY kill source (laser/missile/collision); the killer id for the
Explosion message comes from `lastInflictingID` (the task-#31 bookkeeping). Verified: missile
kill → full chain (blhdead → wreck swap → smoke → sink → burial → INERT). [T2]
- `Mech::IsDestroyed()` (`FUN_0049fb54`) = `movementMode==2||9` (reconstructed as `IsDisabled`, btstubs.cpp);
`FUN_004ab1c8` freezes locomotion (zeros mech+0x298) when destroyed.
- **`MechDeathHandler`** (ctor `FUN_0042a984` + Performance `FUN_0042aa2c`, cached mech+0x850 / `mech[0x214]`) —