Death-state sequence: collapse + subsystem shutdown + freeze (wreck stays)
Reconstructs the mech DEATH state machine — the un-exported master-perf death
branch (region 0x4a9770-0x4ab188) — from its EXPORTED consumers + the RP
VTV::DeathShutdown analog, wired into the active path (the bring-up drive
override bypasses the authentic Simulate where this normally lives).
Mech::UpdateDeathState() + IsMechDestroyed() (mech4.cpp), called for every mech
early in PerformAndWatch: on a vital kill (graphicAlarm >= 9, raised by the
damage side) it
1. sets movementMode = 5 -> the collapse clip's one-shot latch in
AdvanceBodyAnimation (fall direction 5-8 is un-exported -> 5 [T3]);
2. loops the roster calling Subsystem::DeathShutdown(1) (RP VTV::DeathShutdown
analog; the base is a no-op virtual, overrides act -- a SHUTDOWN not a
teardown, so it frees nothing and never removes the entity: the wreck STAYS);
3. next frame settles to movementMode = 9 -> IsDisabled -> locomotion frozen.
The drive's lone `movementMode = 1` write (mech4.cpp ~1309) is guarded on
!IsMechDestroyed so the death state is not clobbered back to a live gait.
Runtime-verified (forced kill, BT_DEATH_LOG=1):
[death] mech destroyed -> collapse + subsystem shutdown (wreck stays)
[death] mech settled -> disabled (IsDisabled=1, frozen wreck)
mech frozen in place, subsystem tick + renderer keep running, no crash, wreck
stays.
Also records the full death-sequence decomp map in combat-damage.md (the
exported consumers: AdvanceLeg/BodyAnimation collapse latch, IsDestroyed, the
MechDeathHandler effect engine; and the un-exported orchestration gap).
Deferred (honest): the visible collapse ANIMATION latch through the active path
(gait SM shows state=0 post-death; spawned mechs don't advance body anim);
MechDeathHandler (FUN_0042a984/FUN_0042aa2c -- the exported per-subsystem
destroyed-skin + explosion engine, still a stub) for death explosions; the
whole-mech DeathSplash radius damage (un-exported).
Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
This commit is contained in:
co-authored by
Claude Opus 4.8
parent
2af401eef8
commit
a9467481c5
@@ -170,6 +170,51 @@ thing: an EXPLICIT `JointedMover::~JointedMover()` in the reconstructed `~Mech`
|
||||
chain TWICE (the dtor-epilogue rule, [[reconstruction-gotchas]] §7) → a double-free of `collisionLists`
|
||||
+ the segment table. Removing it fixed BOTH the death-row crash AND app-exit crashes. [T2]
|
||||
|
||||
## Death SEQUENCE reconstruction — the map (2026-07-08)
|
||||
Full decomp map of the death path. Two tiers:
|
||||
**EXPORTED (reconstructable) [T1 read]:**
|
||||
- `Mech::AdvanceLegAnimation` (`FUN_004a5028`) / `AdvanceBodyAnimation` (`FUN_004a5678`) — the **collapse-anim
|
||||
latch**: `movementMode` (mech+0x40) **5/6/7/8** = the four fall directions → clips **0x1c-0x1f** (via
|
||||
`SetLegAnimation`/`SetBodyAnimation` = `FUN_004a7fc4`/`FUN_004a800c`), one-shot via `deathAnimationLatched`
|
||||
(mech+0x650). Already reconstructed (mech2.cpp:550-557/817-822). The active drive path DOES call
|
||||
`AdvanceBodyAnimation` (mech4.cpp:317) → reachable.
|
||||
- `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]`) —
|
||||
the **per-subsystem destroyed-skin + explosion engine**. Each tick walks the damage subsystems
|
||||
(mech+0x120[mech+0x11c]); as a subsystem's damage crosses a descriptor-table threshold (`FUN_0042a5f4`
|
||||
detects the crossing, `FUN_0042a664` looks up the state) it applies the `GraphicState` ("Destroyed" = enum 1,
|
||||
parsed @part_003.c:9099) to the subsystem graphic (`sub+0xd4`) AND dispatches an effect-creation message
|
||||
(`FUN_0043663c`→`FUN_004364e4` to the effect mgr `app+0x38`). **Fully exported but a no-op STUB** in the
|
||||
recon (mech.cpp:221). Gamedata `DeathSplashDamage`/`Radius`/`Effect` load into a descriptor @ +0x74/78/7c
|
||||
(`FUN_004a2da8`). Destroyed-skin variant set (`destroyed`, `destroyeds`…`destroyedd`) @part_003.c:5720.
|
||||
**NOT EXPORTED (master-perf gap 0x4a9770-0x4ab188 + the un-exported TakeDamage) [T4]:**
|
||||
- The `movementMode` WRITER (sets 5-8 then 2/9 on death) + the fall-direction (5/6/7/8) selection.
|
||||
- The `Mech::DeathShutdown` roster loop (RP `VTV::DeathShutdown` analog — loop subsystems calling the
|
||||
`Subsystem::DeathShutdown(int)` vtable slot; the base is an empty virtual, SUBSYSTM.h:166).
|
||||
- The whole-mech `DeathEffect`/`DeathSplash` radius dispatch + the `graphicAlarm.SetLevel(9)` call site (the
|
||||
recon already raises the alarm in mechdmg.cpp:426/586).
|
||||
**The problem:** the orchestration lives in the per-frame Simulate that the **bring-up drive override
|
||||
bypasses** (btstubs.cpp:116-119), so the death consumer must be reconstructed from its exported consumers +
|
||||
the RP analog and wired into the active path (mech4.cpp `PerformAndWatch`).
|
||||
|
||||
### ✅ Death-STATE core DONE (2026-07-08) [T2]
|
||||
`Mech::UpdateDeathState()` + `IsMechDestroyed()` (mech4.cpp) reconstruct the un-exported death branch from
|
||||
its exported consumers + the RP analog, called for EVERY mech early in `PerformAndWatch`: on `graphicAlarm
|
||||
>= 9` it (1) sets `movementMode = 5` → the collapse clip's latch in `AdvanceBodyAnimation` (fall direction
|
||||
5-8 un-exported → 5 [T3]); (2) loops the roster calling `Subsystem::DeathShutdown(1)` (RP `VTV::DeathShutdown`
|
||||
analog; base is a no-op virtual, a SHUTDOWN not teardown → safe, wreck STAYS); (3) next frame settles to
|
||||
`movementMode = 9` → `IsDisabled` → locomotion frozen. The drive's lone `movementMode = 1` write (mech4.cpp
|
||||
~1309) is guarded on `!IsMechDestroyed` so the death state isn't clobbered. **Runtime-verified** (forced kill):
|
||||
`[death] … collapse + subsystem shutdown` → `[death] … settled -> disabled (IsDisabled=1, frozen wreck)`,
|
||||
mech frozen in place (pos unchanged), subsystem tick + renderer keep running, **no crash, wreck stays**.
|
||||
Env gate `BT_DEATH_LOG=1`.
|
||||
**Deferred (honest):** (a) the visible **collapse ANIMATION** may not latch through the active path — the
|
||||
gait SM showed `state=0` post-death (the clip trigger via `AdvanceBodyAnimation` needs the death `movementMode`
|
||||
to reach its latch; and spawned NON-player mechs don't advance their body anim at all). (b) **`MechDeathHandler`**
|
||||
(the exported per-subsystem destroyed-skin + explosion engine, `FUN_0042a984`/`FUN_0042aa2c`) is still the
|
||||
no-op stub → no death explosions/skin-swaps yet. (c) the whole-mech **DeathSplash** radius damage (un-exported).
|
||||
|
||||
## Key Relationships
|
||||
- Weapons/roster: [[subsystems]]. Aim source: [[locomotion]] (drive/facing). Effects: [[rendering]].
|
||||
- P5 forensics: `docs/HARD_PROBLEMS.md`. Data: [[decomp-reference]] §4-5.
|
||||
|
||||
@@ -98,8 +98,15 @@ authentic path scoped.
|
||||
container ctors + the lookup as a `BTCylinderResolveZone` bridge (ground the cell zone-dict stream format vs
|
||||
the real .RES bytes); 6d register the handler + verify. Feasible; the only open risk is the cell stream format.
|
||||
The earlier-cited `FUN_004a0230`/`FUN_0049ed0c` don't exist.
|
||||
- Death: reconstruct `DeathShutdown` (RP `VTV::DeathShutdown` analog) + collapse anim + destroyed
|
||||
skin. The wreck-stays behavior we ship is faithful; do NOT issue DestroyEntityMessage on death.
|
||||
- **Death sequence — CORE DONE 2026-07-08 [T2]; effects+anim deferred.** `Mech::UpdateDeathState()`
|
||||
(mech4.cpp) reconstructs the death STATE machine (collapse `movementMode` → RP `VTV::DeathShutdown`
|
||||
subsystem loop → settle to disabled/frozen; wreck stays, no crash) — runtime-verified (`BT_DEATH_LOG`).
|
||||
Full map + citations in [[combat-damage]] "Death SEQUENCE". **Remaining** (all in the un-exported master-perf
|
||||
gap 0x4a9770-0x4ab188 OR a big exported reconstruction): (a) the visible **collapse ANIMATION** latch
|
||||
through the active path (+ spawned mechs don't advance body anim); (b) reconstruct **`MechDeathHandler`**
|
||||
(`FUN_0042a984`/`FUN_0042aa2c`) — the EXPORTED per-subsystem destroyed-skin + explosion engine (still a
|
||||
stub, mech.cpp:221) — the biggest visible payoff; (c) the whole-mech **DeathSplash** radius damage. Do NOT
|
||||
issue DestroyEntityMessage on death.
|
||||
|
||||
## Multiplayer (Phase 7 / P6)
|
||||
- Cross-pod COMBAT (target a replicant + route damage to the owning master).
|
||||
|
||||
Reference in New Issue
Block a user