STEP 6 COMPLETE: cylinder hit-location LIVE — unaimed hits resolve to zones

The Mech per-impact hit-location resolver (the cylinder damage table) is now
functional, wired, and runtime-verified [T2].  Unaimed (zone==-1) hits — the
collision-damage path — now resolve an impact point to a damage zone via the
authentic height x angle grid + weighted dice roll, instead of dropping.

dmgtable.cpp/.hpp was a non-functional skeleton on no-op ReconTable/stream
shims; backed it with real std::vector storage and fixed 5 latent runtime bugs:
  - ReadEntries now consumes the leading cell name-string ([i32 len][len+1])
  - PieSlice ctor reads rotateWithTorso into the correct member
  - SelectSlice direct-indexes (was int lookup on a float-keyed table)
  - ResolveHit returns the zone (chains SelectSlice -> SelectZone)
  - real MemoryStream::ReadBytes (was a variadic no-op)

mech.cpp ctor: replaced the empty-name StandingAnimation stub with the real
load — FindResourceDescription(dzRes->resourceName, type 0x1d) -> stream ->
new DamageLookupTable, cached at mech[0x111]; ~Mech deletes it.

Mech::TakeDamageMessageHandler override registered (MESSAGE_ENTRY overlays
Entity's by ID): on invalidDamageZone, resolve via the table then base-route;
aimed reticle hits pass through unchanged.

Three named accessors (no databinding-trap raw reads): WorldToLocal
(localToWorld.MultiplyByInverse), CylinderReferenceHeight (standingTemplateMaxY
== collisionTemplate->maxY == binary mech+0x2ec[+0xc]), TorsoHeading via a
BTGetTorsoTwist bridge in torso.cpp (Torso::CurrentTwist == torso+0x1d8;
torso.hpp cannot be included into mech.cpp — subsystem-stub collision).

Stream format + geometry + roll + handler were all byte-verified against the
shipped BTL4.RES type-29 resources (18 tables, exact consumption) and the
disassembly (FUN_0049eb54/e678/de14, glue 0x49ed0c, handler @0x4a037a).

Runtime: boots clean, "[cyl] table 'bhk1' layers=7" (exact byte-verified layer
count, found by name), mech spawns + walks, no asserts/AV/0xCDCDCDCD.  Env gate
BT_CYL_LOG=1.  Unblocks collision-damage application.

KB updated (combat-damage.md STEP 6 COMPLETE, open-questions.md marked done).

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
This commit is contained in:
arcattack
2026-07-08 08:32:17 -05:00
co-authored by Claude Opus 4.8
parent 33fee712e9
commit d07ac7dd49
8 changed files with 504 additions and 557 deletions
+11
View File
@@ -889,3 +889,14 @@ Subsystem *CreateTorsoSubsystem(Mech *owner, int id, void *seg)
return (Subsystem *) new (Memory::Allocate(0x280))
Torso(owner, id, (Torso::SubsystemResource *)seg, Torso::DefaultData);
}
//
// STEP 6 bridge -- expose the live torso twist (Torso::currentTwist == the binary
// torso+0x1d8) to mech.cpp / the cylinder damage table without pulling the Torso
// header (which collides with mech.cpp's local subsystem stubs) into mech.cpp.
// The roster torso @mech+0x438 is a Torso (ClassID 0xBC5); 0 when absent.
//
Scalar BTGetTorsoTwist(Subsystem *torso)
{
return torso ? ((Torso *)torso)->CurrentTwist() : 0.0f;
}