Commit Graph
10 Commits
Author SHA1 Message Date
arcattackandClaude Opus 4.8 2af401eef8 Collision damage applied: mech-vs-mech + icon-crunch via the STEP-6 unaimed path
The two deferred TakeDamage dispatches in Mech::ProcessCollision now fire,
unblocked by STEP 6 (the cylinder hit-location override that resolves zone==-1):

  - Mover branch (:15324-15358): on a collision with another Mech, dispatch the
    collision damage to it.
  - CulturalIcon branch (:15369-15401): crunch dispatch to a building/tree/prop,
    before the walk-through sentinel overwrites the amount.

Both go through a new file-scope helper BTDispatchCollisionDamage, which builds
an Entity::TakeDamageMessage{zone==-1} (the engine ctor -- same idiom as the
weapon-impact path) with the world centre of the overlap slice as the impact
point and this mech as the inflictor, then Dispatch()es it to the victim.  The
receiver turns the world impact point into a damage zone: a Mech via its cylinder
table (STEP 6), an icon via its base handler (crushable props have no zones -> a
harmless no-op).  Terrain (walls/hills) matches neither branch, so it still
BLOCKS without damage (faithful to the binary).

Faithful to the binary's raw DamageMessage dispatch (:15324-15401) but via the
engine's named TakeDamageMessage API (no databinding-trap field-by-field build);
the binary's inflictor global DAT_0050b9ac is a sentinel EntityID (only ever
read, never set -> a collision has no "shooter"), so this mech is the inflictor.

Verify: builds clean; reachability GUARANTEED (Mover::ProcessCollisionList calls
the VIRTUAL ProcessCollision -> Mech::ProcessCollision, on the active
AuthenticGroundAndCollide path); stable across runs; both mechs build their
cylinder tables.  The live dispatch was not captured headlessly (the solo
auto-walker never rammed a tree/mech), but the path is proven reachable and
composed of runtime-verified pieces (the weapon TakeDamage path + STEP 6).

Also validated STEP 6's height ref: collisionTemplate->maxY ~= 7.1 (a real mech
height), confirming CylinderReferenceHeight reads a height (not the heat value
the mech+0x2ec dual-labeling hinted at).

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
2026-07-08 08:54:21 -05:00
arcattackandClaude Opus 4.8 d07ac7dd49 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>
2026-07-08 08:32:17 -05:00
arcattackandClaude Opus 4.8 33fee712e9 context: STEP-6 content confirmed — DamageLookupTableStream (type 29), 18 present, feasible
The cylinder table resource = type 29 DamageLookupTableStream, 18 in BTL4.RES (one per mech) ->
STEP 6 is FEASIBLE, not content-blocked. Name copied from a sibling resource (local_130+0xc).
RE phase complete; build (containers + handler + load + wire) is the next phase.

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
2026-07-07 23:24:43 -05:00
arcattackandClaude Opus 4.8 970d4fbad0 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>
2026-07-07 23:20:44 -05:00
arcattackandClaude Opus 4.8 99c3d9d041 context: cylinder hit-location (STEP 6) investigated — accurate structure + addresses
Per the 'correct errors' convention: the cited FUN_004a0230/FUN_0049ed0c don't exist. The real
CylinderDamageZoneTable = a list of 0x30-byte entries (FUN_0049e740) from resource 0x1d; the recon
builds the table (FUN_0049ea48, mislabeled StandingAnimation @Mech[0x111]) with an EMPTY name -> 0
entries -> no-op. The lookup + Mech::TakeDamageMessageHandler override are NOT in the exported decomp
(need disassembly). Recorded in combat-damage + open-questions.

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
2026-07-07 23:14:39 -05:00
arcattackandClaude Opus 4.8 5b7f3a1c40 context: sweep the 0xBD3/mech+0x190 correction across all topic files
Propagate the verified finding (0xBD3 = damage/explosion hub @0x434, NOT the valve/message
gate; the valve/Myomers gates read the owning BTPlayer @mech+0x190) into the topic files that
still carried the old claim: decomp-reference (ClassID row + both offset rows), gauges-hud,
subsystems, open-questions (Myomers coupling), + frontmatter. Graph validates clean.

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
2026-07-07 23:01:45 -05:00
arcattackandClaude Opus 4.8 40fdceaf65 context: mech+0x190 IDENTIFIED = the owning BTPlayer (Mech::GetPlayerLink)
The valve/Myomers 'gates' (FUN_004ac9c8 / FUN_004ad7d4) read the owning BTPlayer's
+0x274 / +0x260 (mech+0x190 = the player, bound by FUN_0049f624). So there's no new
subsystem to build -- the wiring is 2 gate accessors -> GetPlayerLink() named members.
Open: the true semantics of player+0x260/0x274 (scoring names showKills/roleClassIndex
may not match the gate use) + the FUN_004ad7d4 HeatModelActive-vs-OwnerAdvancedDamage
label conflict + these are likely MODE flags authentically-off in the basic mission.

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
2026-07-07 22:57:18 -05:00
arcattackandClaude Opus 4.8 16af8dbffb context: correct 0xBD3 — it's the damage/explosion hub (0x434), NOT the valve/Myomers gate
Risk-4 investigation (before wiring WAVE 8) found my earlier 'keystone unblocks 4 things'
claim was wrong. Verified from the binary:
- 0xBD3 SubsystemMessageManager = a damage/explosion consolidation hub (ConsolidateAndSendDamage,
  weaponExplosions), cached to Mech[0x10d]=0x434, mislabeled 'controlsMapper' in our recon (the
  live drive squats there; the real mapper is roster slot 0 via SetMappingSubsystem).
- The valve MoveValve guard (FUN_004ac9c8 ->owner+0x190+0x274) AND the Myomers gate
  (FUN_004ad7d4 ->owner+0x190+0x260) read a DIFFERENT object at mech+0x190 (!= 0x434). So 0xBD3
  does NOT gate the valve/Myomers/MessageBoard; mech+0x190 (unidentified, no decompiled writer yet)
  is the real keystone for those gauge-adjacent routes.

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
2026-07-07 22:49:29 -05:00
arcattackandClaude Opus 4.8 f914fc040a context-system: complete migration -> CLAUDE.md is now a 160-line router (zero context lost)
Full migration of the 2236-line monolithic CLAUDE.md into the progressive-context
knowledge graph (per spark-lesson / expert-seed.md), so the deep RE knowledge loads
on-demand instead of every session.

ZERO CONTEXT LOST:
- docs/PROGRESS_LOG.md = the complete old CLAUDE.md, VERBATIM (byte-identical) -- the
  lossless safety net + the "full detail" quick-lookup fallback.
- 18 context/*.md topic files (1343 lines) digest every section (§1-3 -> project-overview,
  §4 -> content-archives, §5 -> asset-formats/bgf-format, §5a -> source-completeness,
  §5b/§8 -> wintesla-port, §7/§10 -> locomotion, §10a -> build-and-run, §10b ->
  reconstruction-method, §10c -> combat-damage + reconstruction-gotchas, §10d -> subsystems,
  render notes -> rendering, gauges -> gauges-hud, MP -> multiplayer, §9 -> open-questions).
- reference/glossary.yaml (53 terms). decomp-reference.md = the offsets/ClassIDs/addresses hub.

CLAUDE.md (160 lines) = router: identity, answer/reason protocols, quick-lookup table,
evidence tiers (T0 engine-truth / T1 decompiled+verified / T2 reconstructed+runtime /
T3 guarded / T4 hypothesis), conventions + DO-NOT (the systemic bug classes), structure.
Retains the load-bearing work directives (build recipe pointer, "keep current" mandate).

Knowledge graph validates CLEAN (scratchpad/checkctx.py -- all [[links]] + quick-lookup +
docs refs resolve; [[name]] -> topic file or glossary term). docs/*.md ledgers stay as the
detailed logs; context/*.md are the curated digests that route into them.

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
2026-07-07 22:19:50 -05:00
arcattackandClaude Opus 4.8 1cd57ade85 context-system: bootstrap the progressive-context expert knowledge base (foundation)
Adapt the spark-lesson / expert-seed.md progressive-context pattern to the bt411 port:
a thin router + context/*.md knowledge graph so the 2236-line CLAUDE.md's deep knowledge
loads on-demand instead of every session.

NON-DESTRUCTIVE foundation pass (live CLAUDE.md unchanged; proposed router is a draft):
- reference/glossary.yaml        -- ~45 terms (engine/formats/scene/reconstruction)
- context/decomp-reference.md    -- the quantitative hub: resource types, ClassID map,
                                    mech offsets, damage delivery, weapon constants, env gates, tools
- context/reconstruction-gotchas.md -- the 12 systemic bug classes (conventions/DO-NOT hub)
- context/bgf-format.md          -- geometry format + CONN/PCONN + LOD-sqrt3 + ramp shading
- context/gauges-hud.md          -- the gauge/MFD system (the just-completed wave)
- context/open-questions.md      -- deferred systems + get-from-Nick
- context/_ROUTER-DRAFT.md       -- the proposed slim CLAUDE.md (identity, protocols,
                                    quick-lookup, evidence tiers T0-T4, conventions, structure)
- phases/phase-01-context-restructure.md -- design + migration plan + status

docs/*.md ledgers stay as the DETAILED logs; context/*.md are the curated digests that
route into them. Remaining: ~10 topic files (project-overview, subsystems, combat-damage,
rendering, locomotion, wintesla-port, build-and-run, ...) then the CLAUDE.md swap.

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
2026-07-07 22:06:53 -05:00