Combat: critical-subsystem plugs BOUND -- zone destruction damages carried subsystems (task #2)
The binding was in the zone ctor all along: Ghidra dropped the two arg pushes @0049d0e1 (Slot::AddImplementation(subsystemArray[streamedIndex])), making it read as a bare Resolve(). DZSlot stand-in -> engine SlotOf<T>; SendSubsystemDamage rewritten to the recovered @0049c9a8 body (allotment into the subsystem's OWN private zone; vital -> graphicAlarm 9); CriticalHit -> real ApplyDamageAndMeasure; parentArtifactZone.Add revived (LOD damage averaging); videoObjectFlag renamed vitalSubsystem (+0xE4). BT_CRIT_PROBE diag added. Verified: 66 plugs bound/mech; probe-destroyed zone -> crits damaged/DESTROYED, statusAlarm + destroyed-skin chain fire; MP kill + solo un-regressed. Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
This commit is contained in:
co-authored by
Claude Fable 5
parent
a652ddcdbc
commit
87c25b9206
@@ -179,13 +179,24 @@ authentic path scoped.
|
||||
(the authentic death-row removal — needs the mech render tree unhooked from the renderer first;
|
||||
the inert wreck is the safe stand-in until then).
|
||||
Do NOT issue DestroyEntityMessage on death (before the render-tree teardown lands).
|
||||
- **Critical-subsystem plugs UNBOUND (43 skips/mech) [T3].** `MechCriticalSubsystem::subsystemPlug`
|
||||
never gets WIRED to its live subsystem (the ctor's Resolve() at mechdmg.cpp:276 only READS; the
|
||||
binding write is elsewhere/unreconstructed), so `SendSubsystemDamage` skips every entry via the
|
||||
unbound-plug guard (mechdmg.cpp, added 2026-07-08 after a live NULL-deref AV in
|
||||
`SendSubsystemDamage+0x93` — the 1995 binary derefs unchecked because there every plug is bound).
|
||||
Consequence: zone destruction does NOT yet propagate damage into carried subsystems (generator/
|
||||
gyro failures etc.). Also latent there: `SubProxy2` raw-offset reads (databinding trap) once s≠0.
|
||||
- ✅ **Critical-subsystem plugs BOUND — damage propagates (task #2, 2026-07-11) [T1/T2].**
|
||||
The "binding write is elsewhere" reading was WRONG: the binding is IN the zone ctor loop
|
||||
(@0049d0e1-0049d10d) — **Ghidra dropped the two argument pushes** ("type propagation not
|
||||
settling"), making `Slot::AddImplementation(roster[streamedIndex])` read as a bare no-arg
|
||||
call (mislabeled Resolve). The stream's third per-entry dword IS the roster index into
|
||||
`subsystemArray` (mech+0x128). Port: the `DZSlot` stand-in (always-null Resolve) replaced
|
||||
with the engine `SlotOf<T>` (binary vtables 0050bb84/0050bb7c ARE its instantiations); bind
|
||||
gated MasterInstance+DynamicFlag (`simulationFlags@+0x28`); replicant plugs stay unbound
|
||||
(master-authoritative). `SendSubsystemDamage` rewritten to the recovered @0049c9a8 logic:
|
||||
the unused crit allotment lands in the subsystem's OWN private 0x160 DamageZone (the old
|
||||
`SubProxy2` cast to a mech zone was wrong), ≥1.0 → statusAlarm Destroyed + gated PrintState
|
||||
+ zone valve, vital → `graphicAlarm 9` (mech kill); `CriticalHit` now calls the real
|
||||
`ApplyDamageAndMeasure` (@4ac07c); the artifact `parentArtifactZone.Add` back-pointer bind
|
||||
also revived (LOD damage averaging). `videoObjectFlag` was `vitalSubsystem` (+0xE4,
|
||||
res+0x48 "VitalSubsystem"). VERIFIED live (`BT_CRIT_PROBE=<zone>` diag): 66 plugs bound at
|
||||
ctor per mech, zone destroyed → crits damaged/DESTROYED with authentic accumulation.
|
||||
Residue: roster idx 0/1 (mapper installed post-ctor / voltage-bus stub) stay unbound with a
|
||||
logged skip — none of the 8 mechs' streams crit-list them in practice.
|
||||
- **Two dead Wword comparison branches (multiplayer)**: `mech.cpp:1511` + `:1613` (replicant
|
||||
leg-state/stability sync in ReadUpdateRecord) — always-false BTVal comparisons ([[reconstruction-gotchas]] §2);
|
||||
needs slots 0xf/0x10 promoted to named members when P6 replication work resumes.
|
||||
|
||||
Reference in New Issue
Block a user