HUD ironing (task #38): authentic Lock producer + simple-X mode
- LOCK rules transcribed from the exported HudSimulation (part_013.c:5619-5634): lock requires a target AND your own HUD host zone damage < 0.75 (_DAT_004b7ec4 -- a shot-up targeting computer drops lock) AND the targeted zone damage < 1.0 (_DAT_004b7ec8; whole-mech target checks zone 0 -- a wreck's dead zone can't re-lock). Box and ring are now separate signals like the binary: gBTHudLockState 1 = target held (hotbox draws), 2 = LOCKED (+ the spinning ring). - SIMPLE-X mode: the ctor's [0x99] minimal-reticle list transcribed (@4689-4705: green +-0.02..0.08 cross on the aim translate); Draw switches master <-> simple X on the PrimaryHudOn element bit (0x20), completing the recovered Execute's state-list logic. - Canopy diagnosis sharpened (open-questions): blx_cop is the torso segment's inside-skeleton mesh enclosing the eye; the black box = the skeleton render branch missing its texture + PUNCH cutout (the canopy windows are punch texels). A rendering-branch task; stays hidden by default. Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
This commit is contained in:
co-authored by
Claude Fable 5
parent
18d49491b7
commit
24ea7f13af
@@ -113,8 +113,15 @@ and every instrument is now live [T2]:**
|
||||
(the weapon-GROUP bits Front/Rear/Left/Right). **Range plays NO part** — Execute never reads
|
||||
the stored TargetWithinRange slots.
|
||||
- **Lock ring** = subB9 (ring+cross) at frame centre, **SPINNING 4°/frame** while the Lock attr
|
||||
(0xA) is up (port: while a target is locked); the binary also hangs the PNAMEx.bgf player-name
|
||||
mesh on the 3D marker here (3D chain still deferred).
|
||||
(0xA) is up. The Lock PRODUCER is the authentic HudSimulation rule (part_013.c:5619-5634 [T1],
|
||||
wired task #38): lock requires a target AND your own HUD's host zone damage < **0.75** (a
|
||||
shot-up targeting computer loses lock) AND the targeted zone's damage < **1.0** (whole-mech
|
||||
target checks zone 0 — so a wreck's dead zone can't re-lock). The hotbox stays visible without
|
||||
lock (box = HotBoxVector, ring = Lock — separate signals). The binary also hangs the PNAMEx.bgf
|
||||
player-name mesh on the 3D marker here (3D chain still deferred).
|
||||
- **Simple-X mode** (PrimaryHudOn off, mask 0x20): the minimal reticle — a small green cross
|
||||
(±0.02..0.08 arms) riding the aim translate (ctor @4689-4705 [T1]) — swapped for the full HUD
|
||||
by Draw's state switch.
|
||||
- **Target HOTBOX** (attr 0xB HotBoxVector) = a rectangle hugging the projected extents — x±4
|
||||
around the hotbox point, +1/−11.5 vertical (K=2.8145 baked projection; the port uses the live
|
||||
per-axis projection) — switching to the left/right edge ARROW past ±1.6 or behind.
|
||||
|
||||
@@ -60,16 +60,18 @@ authentic path scoped.
|
||||
by the mouse — wire the real channel when pod hardware lands; (c) pre-burial, the pick still
|
||||
tests the sinking wreck's collision box at its parked position (pre-existing wreck-targeting
|
||||
behavior).
|
||||
- **Cockpit HUD leftovers (tasks #35-#37 residue, 2026-07-08)** — the reticle + 7 weapon pips +
|
||||
- **Cockpit HUD leftovers (tasks #35-#38 residue, 2026-07-08)** — the reticle + 7 weapon pips +
|
||||
ALL the instrument dynamics are LIVE (the Execute @004cdcf0 gap was RECOVERED via capstone
|
||||
disasm, task #37 — see [[gauges-hud]] for the full instrument map). Remaining: (a) the
|
||||
**blx_cop canopy shell** renders BLACK (untextured/unlit in our inside view) so it's hidden by a
|
||||
name filter — `BT_INSIDE_COCKPIT=1` shows it; the authentic look needs its material/lighting
|
||||
path; (b) the **3D marker chain** ([0x31c]/[0x320] dpl objects + the PNAME1-8.bgf player-name
|
||||
meshes the Execute hangs over the locked target); (c) the "simple X" list [0x264]
|
||||
(PrimaryHudOn off — the minimal reticle mode) is built empty in the port; (d) the HUD Lock
|
||||
attr's (0xA) own HudSimulation producer (port analog: locked == designated) and the compass
|
||||
rotation SIGN are [T3].
|
||||
disasm, task #37; the authentic Lock producer + the simple-X mode landed in #38 — see
|
||||
[[gauges-hud]] for the full instrument map). Remaining: (a) the **blx_cop canopy shell**: it is
|
||||
the torso segment's SkeletonType_A mesh and fully encloses the eye; it renders as a black box
|
||||
because the skeleton-branch render path isn't giving it its texture + the PUNCH cutout (the
|
||||
canopy WINDOWS are punch texels — with punch live the black pane texels become holes and the
|
||||
world shows through the frame). Fix lives in the [[rendering]] skeleton/punch branch, not the
|
||||
HUD; hidden by name filter until then (`BT_INSIDE_COCKPIT=1` shows it). (b) the **3D marker
|
||||
chain** ([0x31c]/[0x320] dpl objects + the PNAME1-8.bgf player-name meshes over the locked
|
||||
target — matters for MP). (c) the compass rotation SIGN is derived-not-verified [T3] (turn
|
||||
left → the stem should swing right; flip the sin sign in Draw if footage disagrees).
|
||||
- **StatusMessagePool (NULL stub, btstubs.cpp:62)** — the per-player status-message queue.
|
||||
BTPlayer+0x1dc is never populated → MessageBoard is empty (authentic for bring-up). What
|
||||
resolves it: wire the pool + decode `AddStatusMessage @0042e580` + the `Player__StatusMessage`
|
||||
|
||||
@@ -1049,6 +1049,7 @@ BTReticleRenderable::BTReticleRenderable(Entity *entity, Scalar *range_attr)
|
||||
lockSpinDeg= 0.0f;
|
||||
|
||||
masterList = dpl2d_NewDisplayList();
|
||||
simpleXList = dpl2d_NewDisplayList();
|
||||
aimDotList = dpl2d_NewDisplayList();
|
||||
rangeCaretR = dpl2d_NewDisplayList();
|
||||
rangeCaretB = dpl2d_NewDisplayList();
|
||||
@@ -1207,6 +1208,30 @@ BTReticleRenderable::BTReticleRenderable(Entity *entity, Scalar *range_attr)
|
||||
dpl2d_SetLineWidth(rightArrow, 1.0f);
|
||||
dpl2d_End(rightArrow); dpl2d_Compile(rightArrow);
|
||||
|
||||
//
|
||||
// The SIMPLE X [0x99] (ctor @4689-4705 [T1]): the minimal reticle used
|
||||
// when PrimaryHudOn is OFF -- a small green cross (arms +-0.02..0.08)
|
||||
// riding the same aim translate. Draw switches master <-> this on the
|
||||
// element-mask bit (the recovered Execute's state-list logic @4cdd9d).
|
||||
//
|
||||
dpl2d_Begin(simpleXList, 1);
|
||||
dpl2d_SetLineWidth(simpleXList, 1.0f);
|
||||
dpl2d_FullScreenClip(simpleXList);
|
||||
dpl2d_SetColor(simpleXList, 0.0f, 0.75f, 0.0f);
|
||||
dpl2d_CallList(simpleXList, aimDotList); // slews with the crosshair
|
||||
dpl2d_OpenLines(simpleXList);
|
||||
dpl2d_AddPoint(simpleXList, -0.08f, 0.0f);
|
||||
dpl2d_AddPoint(simpleXList, -0.02f, 0.0f);
|
||||
dpl2d_AddPoint(simpleXList, 0.02f, 0.0f);
|
||||
dpl2d_AddPoint(simpleXList, 0.08f, 0.0f);
|
||||
dpl2d_AddPoint(simpleXList, 0.0f, -0.08f);
|
||||
dpl2d_AddPoint(simpleXList, 0.0f, -0.02f);
|
||||
dpl2d_AddPoint(simpleXList, 0.0f, 0.02f);
|
||||
dpl2d_AddPoint(simpleXList, 0.0f, 0.08f);
|
||||
dpl2d_CloseLines(simpleXList);
|
||||
dpl2d_End(simpleXList);
|
||||
dpl2d_Compile(simpleXList);
|
||||
|
||||
// empty placeholders (filled per frame / on lock)
|
||||
dpl2d_Begin(crossList, 1); dpl2d_End(crossList); dpl2d_Compile(crossList);
|
||||
dpl2d_Begin(aimDotList, 1); dpl2d_End(aimDotList); dpl2d_Compile(aimDotList);
|
||||
@@ -1393,7 +1418,7 @@ void
|
||||
// -- the 3D marker chain remains deferred.)
|
||||
{
|
||||
extern int gBTHudLockState;
|
||||
const int locked = (gBTHudLockState != 0);
|
||||
const int locked = (gBTHudLockState == 2); // the Lock attr rule, not just a target
|
||||
if (locked != lockShown)
|
||||
{
|
||||
lockShown = locked;
|
||||
@@ -1449,7 +1474,12 @@ void
|
||||
dpl2d_Compile(crossList);
|
||||
}
|
||||
|
||||
dpl2d_ExecuteList(masterList, device);
|
||||
// the STATE-list switch (Execute @4cdd9d [T1]): PrimaryHudOn (element mask
|
||||
// 0x20) selects the full HUD; off = just the simple aim cross.
|
||||
{
|
||||
extern int gBTHudPrimary;
|
||||
dpl2d_ExecuteList(gBTHudPrimary ? masterList : simpleXList, device);
|
||||
}
|
||||
}
|
||||
|
||||
//
|
||||
|
||||
@@ -547,6 +547,7 @@ class BTReticleRenderable:
|
||||
//
|
||||
Scalar *rangeAttr2; // [0x89] the target-range source
|
||||
dpl2d_DISPLAY *masterList; // [0x98] the composed reticle
|
||||
dpl2d_DISPLAY *simpleXList; // [0x99] the minimal cross (PrimaryHudOn off)
|
||||
dpl2d_DISPLAY *aimDotList; // [0x9a] centre aim dot
|
||||
dpl2d_DISPLAY *rangeCaretR; // [0x9b] right-ladder caret
|
||||
dpl2d_DISPLAY *rangeCaretB; // [0x9c] bottom-ladder carets
|
||||
|
||||
@@ -563,6 +563,7 @@ float gBTHudHeading = 0.0f;
|
||||
float gBTHudTwist = 0.0f;
|
||||
float gBTHudTwistLimit = 0.0f;
|
||||
int gBTHudGroupMask = 0xF;
|
||||
int gBTHudPrimary = 1; // PrimaryHudOn (element mask 0x20): full HUD vs simple X
|
||||
// BT_GOTO beeline harness outputs (consumed by the mapper bridge, mechmppr.cpp)
|
||||
int gBTGotoActive = 0;
|
||||
float gBTGotoTurn = 0.0f;
|
||||
@@ -2383,10 +2384,36 @@ void
|
||||
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; // the HOTBOX point: top-centre
|
||||
gBTHudLockWorld[1] = dp.y + (float)dm->CylinderReferenceHeight();
|
||||
gBTHudLockWorld[2] = dp.z;
|
||||
|
||||
// AUTHENTIC LOCK (HudSimulation, part_013.c:5619-5634 [T1]):
|
||||
// the fire-control LOCK needs (a) a working targeting computer
|
||||
// -- your own HUD's host zone below 75% damage -- and (b) a
|
||||
// live targeted zone -- its damage below 1.0 (a whole-mech
|
||||
// target checks zone 0). So a shot-up cockpit loses the lock
|
||||
// light, and a destroyed wreck's dead zone can't be re-locked.
|
||||
int lock = 1;
|
||||
{
|
||||
MechSubsystem *hud = (MechSubsystem *)GetHudSubsystem();
|
||||
if (hud != 0 && hud->GetDamageZoneProxy() != 0)
|
||||
{
|
||||
Mech__DamageZone *hz =
|
||||
(Mech__DamageZone *)hud->GetDamageZoneProxy();
|
||||
if (hz->damageLevel >= 0.75f) // _DAT_004b7ec4
|
||||
lock = 0;
|
||||
}
|
||||
int tz = MECH_TARGET_SUBIDX(this);
|
||||
if (tz < 0) tz = 0; // whole-mech -> zone 0
|
||||
if (lock && tz < dm->damageZoneCount && dm->Zone(tz) != 0
|
||||
&& dm->Zone(tz)->damageLevel >= 1.0f) // _DAT_004b7ec8
|
||||
lock = 0;
|
||||
}
|
||||
// 1 = target held (hotbox draws); 2 = LOCKED (box + spin ring).
|
||||
// The binary keeps these separate: the box follows HotBoxVector,
|
||||
// the ring follows the Lock attr.
|
||||
gBTHudLockState = lock ? 2 : 1;
|
||||
}
|
||||
else
|
||||
{
|
||||
@@ -2398,6 +2425,7 @@ void
|
||||
gBTHudTwist = (float)TorsoHeading(); // RotationOfTorsoHorizontal (attr 4)
|
||||
gBTHudTwistLimit = (float)GetHorizontalFiringReach();// HorizontalTorsoLimit (attrs 5/6)
|
||||
gBTHudGroupMask = (int)targetReticle.reticleElementMask & 0xF;
|
||||
gBTHudPrimary = ((int)targetReticle.reticleElementMask & 0x20) != 0;
|
||||
}
|
||||
|
||||
if (gEnemyMech != 0)
|
||||
|
||||
Reference in New Issue
Block a user