context: STEP-6 cylinder table FULLY reversed (height x angle grid) — build plan

De-risk + format-reversal pass complete. The CylinderDamageZoneTable is a passive nested-list
height x angle grid: TABLE (FUN_0049ea48) -> ROWS-by-height (FUN_0049e740, cell key i*2pi/count,
_DAT_0049e810=6.2831855) -> CELLS-by-angle (FUN_0049deb0) -> zone. All 3 vtables minimal (dtor +
2 Node slots, NO lookup method) -> the lookup is entirely in the unexported
Mech::TakeDamageMessageHandler (handler-set entry, not virtual) = the disassembly target.
Full ctor/dtor/vtable address map + the 4-step build plan recorded in combat-damage.md.

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
This commit is contained in:
arcattack
2026-07-07 23:20:44 -05:00
co-authored by Claude Opus 4.8
parent 99c3d9d041
commit 970d4fbad0
+13 -4
View File
@@ -59,10 +59,19 @@ NOT exist — the real pieces are: the **CylinderDamageZoneTable** = a list of 0
(entry ctor `FUN_0049e740`) loaded from resource type **0x1d** by the mech's cylinder-table NAME; the
table ctor is `FUN_0049ea48` (vtable 0x50bd84, alloc 0x2c, cached at `Mech[0x111]`=byte 0x444) — the recon
DOES build it (mislabeled `StandingAnimation`, mech.cpp:1221) but with an EMPTY name → 0 entries → the
lookup is a no-op. The **lookup + the `Mech::TakeDamageMessageHandler` override are NOT in the exported
decomp** (assert-anchored pass skipped them → need disassembly). So STEP 6 = fix the resource name +
reverse the 0x30-byte entry format (`FUN_0049e740`) + disassemble & reconstruct the handler/lookup + wire
the vtable override. `Mech__DamageZone::TakeDamage` → engine armor model (`damageLevel
lookup is a no-op. **Fully reversed (2026-07):** the table is a passive nested-list **height × angle grid** — 3 container
classes: TABLE (0x2c, ctor `FUN_0049ea48` / dtor `0x49eadc`, vtable 0x50bd84, `this[3]`=mech,
`this[4]`=row list, `this[10]`=row count) → ROWS by HEIGHT (0x30, ctor `FUN_0049e740` / dtor `0x49e814`,
vtable 0x50bd90, `this[0xb]`=cell count, cell key `i·(2π/count)``_DAT_0049e810`=**6.2831855=2π**;
`this[4]`=mech+0x438) → CELLS by ANGLE (0x2c, ctor `FUN_0049deb0` / dtor `0x49df80`, vtable 0x50bd9c) →
zone ref(s). All three vtables are MINIMAL (dtor + 2 Node slots, no method) → **the lookup is entirely in
the unexported `Mech::TakeDamageMessageHandler`** (a handler-SET entry, not a vtable slot — ENTITY.h has
no `virtual`; find it via the Mech message-handler registration, then disassemble). So STEP 6 remaining =
(1) fix the resource-name load (build the table WITH data, not the empty-name stub); (2) reconstruct the 3
container classes from the captured ctors; (3) disassemble + reconstruct `Mech::TakeDamageMessageHandler`
(compute the impactPoint's local height+angle → index the grid → dispatch to `damageZones[zone]->TakeDamage`);
(4) register the handler + verify unaimed hits distribute across zones. A genuine multi-pass reconstruction
(the container classes are tedious; the handler is the disassembly). `Mech__DamageZone::TakeDamage` → engine armor model (`damageLevel
+= damageAmount*damageScale[type]`) → 1.0 = zone destroyed → death. The Mech ctor populates the
inherited `damageZones[]` from the DamageZoneStream (type 0x14) resource. `class Damage{ damageType
(Collision/Ballistic/Explosive/Laser/Energy), damageAmount, damageForce, surfaceNormal, impactPoint,