diff --git a/context/combat-damage.md b/context/combat-damage.md index f458abc..eb2b2a3 100644 --- a/context/combat-damage.md +++ b/context/combat-damage.md @@ -69,6 +69,23 @@ player-only logic on `this == application->GetViewpointEntity()` (else a spawned player input). [T1] ## Targeting (mech offsets, [[decomp-reference]] §3) +**STRUCTURAL DISCOVERY (2026-07-29, the #73 pick dig): the target block is an embedded engine +`Reticle` at `mech+0x36c`** [T0 layout-verified]. `engine/MUNGA/RETICLE.h` lays out exactly: +`reticlePosition@0x36c` (Vector2D), `reticleState@0x374`, `pickPointingOn@0x378`, +**`rayIntersection@0x37c`**, **`targetEntity@0x388`**, **`targetDamageZone@0x38c`**, +`reticleElementMask@0x390`. This is why every "who writes 0x388" scan came back empty — writers +carry `&mech->reticle` (an `lea [mech+0x36c]`) and use small reticle-relative offsets. +`ENTITY3.h:131` states the model in T0 words: *"For BattleTech, damage zones are only valid via +reticle based weapons."* The engine `Reticle` is a **passive container** (ctor + resource parse +only — no pick math); `HudSimulation @0x4b7830` opens with `lea esi,[owner+0x36c]` and READS the +pick (range caret from `rayIntersection`, the designator transform) and slews `reticlePosition` +via `@0x4b7ed4`, but does not write the pick either. **The pick WRITER is BT code, still +unlocated** [T4 candidates]: the un-exported stretch `0x4a1674-0x4a2d48` (touches the reticle at +`0x4a16a5` — the Mech::Make-called init — and `0x4a1f93`, `0x4a294a/54/61` state+pickPointing+base +together near entry `0x4a2971`, which is called from `0x494483`), the two unidentified Mech vtable +overrides `+0x18=0x4a122c` / `+0x1c=0x4a0c2c` (both big switch functions), and lone sites +`0x4877a4` (byte read via the mission entity table `0x5015c8`), `0x4b0097`, `0x45fb14-24`. +Recovering it settles #73's residual box-vs-cylinder question with binary truth. `mech+0x37c` = target world Point3D; `mech+0x388` = target `Entity*` (the `HasActiveTarget()` gate); `mech+0x38c` = targeted sub-zone (−1=whole). Weapons cache hasTarget/targetPoint/muzzlePoint, refreshed each frame. [T1]