Reticle Execute @004cdcf0 RECOVERED: every HUD instrument now live (task #37)

The one un-exported gap in the reticle chain, read via capstone
(tools/disas2.py; the annotated disasm preserved at
reference/decomp/reticle_execute_004cdcf0.disasm.txt). Draw() is now a
transcription of the real per-frame logic, and the HUD attr-table names
(hud.hpp ids 4/5/6/8/A/B/C/D) are CONFIRMED by their Execute usage:

- Range ladder: BAR from ladder-top to the caret + caret translate.
- The bottom 21-tick tape is the TORSO-TWIST indicator (NOT heading):
  deflection = -/+(span/2) x (RotationOfTorsoHorizontal / twist limit),
  attrs 4/5/6. Fixed-torso BLH reads centred -- authentic static.
- The circle-with-stem is the COMPASS (attr 0xD, rad->deg rotation) at
  (botX, botY - 3*tickMajor - 0.03), with the THREAT trail (attr 0xC)
  in its rotated frame: 0.05-unit attack-direction marks, fresh < 2s
  red, expiring at 6s. Port feed: player TakeDamage pushes the impact
  direction (dormant vs the passive test dummy).
- Pips (composed into subB6): hidden when destroyed (attr 1 == 1), LIT
  when the fire cycle is LOADED (attr 0x1c == 2; port source
  rechargeLevel >= 1) else the dark charging ring; filtered by the
  weapon-GROUP bits (weaponMode & elementMask&0xF). Range plays NO part
  (the stored TargetWithinRange slots are never read by Execute).
- Lock ring: subB9 at frame centre SPINNING 4 deg/frame while locked
  ([0x9d] is the spin matrix, not a heading list).
- Target HOTBOX: a rectangle hugging the projected extents (x+-4 around
  the top-centre hotbox point, +1/-11.5 vertical; baked K=2.8145 -- the
  port projects through the live per-axis projection), switching to the
  edge arrows past +-1.6 or behind (BTProjectHotBox, L4VIDEO).
- Reticle state Off/On + PrimaryHudOn full-HUD/simple-X switch, aim
  translate on slew move, 3D marker + PNAME player-name mesh identified
  (chain still deferred).

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
This commit is contained in:
arcattack
2026-07-08 22:38:50 -05:00
co-authored by Claude Fable 5
parent cf9f56044e
commit 18d49491b7
10 changed files with 1677 additions and 108 deletions
+21 -7
View File
@@ -551,11 +551,18 @@ static Scalar gDriveHeading = 0.0f; // yaw about world up (Y)
// the HUD Draw (crosshair position) and the pick-ray each sim frame.
float gBTAimX = 0.0f;
float gBTAimY = 0.0f;
// The HUD designator feed (mech4 -> btl4vid Draw): the designated target's
// world chest point + the lock state (0 = none, 1 = designated, 2 = HOT --
// the crosshair is ON it right now).
// The HUD designator feed (mech4 -> btl4vid Draw): the locked target's
// HOTBOX point (its top-centre; the recovered Execute frames x+-4 around it,
// +1 above / -11.5 below) + the lock state (0 = none, 2 = locked).
int gBTHudLockState = 0;
float gBTHudLockWorld[3] = { 0, 0, 0 };
// Recovered-Execute instrument feeds (task #37): the compass heading, the
// torso-twist tape (deflection over the per-mech twist limit), and the
// weapon-group display mask (the Reticle element mask's low nibble).
float gBTHudHeading = 0.0f;
float gBTHudTwist = 0.0f;
float gBTHudTwistLimit = 0.0f;
int gBTHudGroupMask = 0xF;
// BT_GOTO beeline harness outputs (consumed by the mapper bridge, mechmppr.cpp)
int gBTGotoActive = 0;
float gBTGotoTurn = 0.0f;
@@ -2364,19 +2371,21 @@ void
}
}
// HUD feeds: the range caret + the designator box (world point + state).
// HUD feeds: the range caret + the hotbox (world point + state) + the
// recovered-Execute instruments (compass, twist tape, group mask).
{
extern void BTSetHudTargetRange(Scalar range);
Entity *des = MECH_TARGET_ENTITY(this);
if (des != 0)
{
Point3D dp = ((Mech *)des)->localOrigin.linearPosition;
Mech *dm = (Mech *)des;
Point3D dp = dm->localOrigin.linearPosition;
float hddx = dp.x - localOrigin.linearPosition.x;
float hddz = dp.z - localOrigin.linearPosition.z;
BTSetHudTargetRange((Scalar)sqrtf(hddx*hddx + hddz*hddz));
gBTHudLockState = 2; // locked == crosshair on it
gBTHudLockWorld[0] = dp.x;
gBTHudLockWorld[1] = dp.y + kMuzzleHeight;
gBTHudLockWorld[0] = dp.x; // the HOTBOX point: top-centre
gBTHudLockWorld[1] = dp.y + (float)dm->CylinderReferenceHeight();
gBTHudLockWorld[2] = dp.z;
}
else
@@ -2384,6 +2393,11 @@ void
BTSetHudTargetRange(1200.0f); // no target: the binary default
gBTHudLockState = 0; // (0x44960000 @part_013.c:5637)
}
gBTHudHeading = gDriveHeading; // CompassHeading (attr 0xD)
gBTHudTwist = (float)TorsoHeading(); // RotationOfTorsoHorizontal (attr 4)
gBTHudTwistLimit = (float)GetHorizontalFiringReach();// HorizontalTorsoLimit (attrs 5/6)
gBTHudGroupMask = (int)targetReticle.reticleElementMask & 0xF;
}
if (gEnemyMech != 0)