From 970d4fbad0d19747572d221676f5d617ce7c530a Mon Sep 17 00:00:00 2001 From: arcattack Date: Tue, 7 Jul 2026 23:20:44 -0500 Subject: [PATCH] =?UTF-8?q?context:=20STEP-6=20cylinder=20table=20FULLY=20?= =?UTF-8?q?reversed=20(height=20x=20angle=20grid)=20=E2=80=94=20build=20pl?= =?UTF-8?q?an?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit 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) --- context/combat-damage.md | 17 +++++++++++++---- 1 file changed, 13 insertions(+), 4 deletions(-) diff --git a/context/combat-damage.md b/context/combat-damage.md index bc03558..e69907e 100644 --- a/context/combat-damage.md +++ b/context/combat-damage.md @@ -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,