Targeting: lock mirrors the pick per frame (sticky designation removed)

The sticky lock made aim irrelevant after the first acquisition (the
crosshair starts on the face-to-face enemy, so it locked at spawn and
never let go -- played as auto-targeting). The binary treats no-target
as a frequent live state (fire path re-checks 0x388!=0 at every step,
part_013.c:7689/7727; HUD range feed has a permanent no-target default,
:5636), so the target slots now mirror the reticle pick each frame:
locked while the crosshair is ON the mech, no lock otherwise. Keeping
the crosshair on the enemy is the gunnery.

Verified headless: BT_AIM="0 0" -> HOT + aimed zone hits; BT_AIM="0.6
0.4" -> no lock, zero damage.

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
This commit is contained in:
arcattack
2026-07-08 21:08:08 -05:00
co-authored by Claude Fable 5
parent d78bde066d
commit 9666dc5b5e
3 changed files with 24 additions and 25 deletions
+8 -4
View File
@@ -53,10 +53,14 @@ the MOUSE (dev-box stand-in for the pod stick free-aim; `BT_AIM="x y"` pins it h
`BTGetAimRay` (L4VIDEO; the ACTIVE eye publishes pos+LookAtRH basis via `BTSetAimCamera`, the
render loop publishes proj._22) → `Mech::PickRayHit` (world ray → local frame →
`BoundingBox::HitBy` slab test vs the collision template's ExtentBox → world hit point) → the
entity target slots. Designation is STICKY (persists off-crosshair; re-hover refreshes; cleared
when the target leaves the roster at burial). While HOT (crosshair on the hull) the impact point
= the PICKED point → STEP-6 resolves the zone under the crosshair (verified: center-aim at the
head band → zone 13 dominant); off-crosshair the converge point is center-mass chest. The HUD
entity target slots. The slots MIRROR the pick EACH FRAME: locked while the crosshair is ON the
mech, no target otherwise — keeping the crosshair on the enemy IS the gunnery. (⚠ A first cut
made the designation STICKY — once hovered, locked forever — which made aim irrelevant after the
first acquisition; play-tested wrong, and the binary treats no-target as a FREQUENT live state:
the fire path re-checks 0x388!=0 at every step, part_013.c:7689/7727, and the HUD range feed has
a permanent no-target default, :5636. Corrected 2026-07-08.) While locked the impact point = the
PICKED hull point → STEP-6 resolves the zone under the crosshair (verified: center-aim at the
head band → zone 13 dominant). The HUD
draws the aim group at the slewed position ([0x9a] translate list, contained by push/pop), the
designator ring at the target's projected point (subB9 hot / subB8 designated,
`BTProjectToReticle`), and the edge arrows when off-screen/behind. `BT_FIRE_ARC` is now an
+2 -2
View File
@@ -53,8 +53,8 @@ authentic path scoped.
the basic-mission behavior. The MessageBoard feed is separate (StatusMessagePool, below).
- **✅ Authentic target acquisition RECONSTRUCTED (task #36, 2026-07-08)** — the `Reticle`
pick-ray chain is LIVE (see [[combat-damage]] Targeting for the full port map): mouse slew →
pick ray → sticky designation → aimed zone damage + designator ring/arrows; `BT_FIRE_ARC` is
opt-in-only now. Residue: (a) the binary's own per-frame reticle→mech copy is still in an
pick ray → per-frame lock (crosshair ON the mech = locked; off = none) → aimed zone damage +
designator ring; `BT_FIRE_ARC` is opt-in-only now. Residue: (a) the binary's own per-frame reticle→mech copy is still in an
un-exported gap (our writer follows RETICLE.h semantics [T3 dynamics]); (b) the pod's REAL slew
device channel (stick free-aim via the controls mapper / `freeAimSlew` @HUD+0x28C) is bridged
by the mouse — wire the real channel when pod hardware lands; (c) pre-burial, the pick still
+14 -19
View File
@@ -2332,30 +2332,25 @@ void
if (hotTarget != 0)
targetReticle.rayIntersection = hotPoint;
// The target slots MIRROR the pick each frame: you are locked while
// the crosshair is ON the mech, and not otherwise. (A first cut
// made the designation STICKY -- once hovered, locked forever -- but
// that made aim irrelevant after the first acquisition, and the
// binary's own code treats no-target as a FREQUENT live state: the
// fire path re-checks 0x388!=0 at every step (part_013.c:7689/7727)
// and the HUD range feed has a permanent no-target default of 1200
// (part_013.c:5636). Keeping the crosshair on the enemy IS the
// gunnery.)
if (hotTarget != 0)
{
MECH_TARGET_ENTITY(this) = hotTarget; // designate (sticky)
MECH_TARGET_ENTITY(this) = hotTarget;
MECH_TARGET_SUBIDX(this) = -1;
MECH_TARGET_POS(this) = hotPoint; // the aimed hull point
}
else if (MECH_TARGET_ENTITY(this) != 0)
else
{
if (MECH_TARGET_ENTITY(this) != gEnemyMech)
{
// the designated mech left the target roster (wreck buried /
// entity gone): drop the designation.
MECH_TARGET_ENTITY(this) = 0;
MECH_TARGET_SUBIDX(this) = -1;
}
else
{
// crosshair off the mech: the designation persists; the
// converge point tracks the target's center mass (chest).
Mech *des = (Mech *)MECH_TARGET_ENTITY(this);
Point3D cm = des->localOrigin.linearPosition;
cm.y += kMuzzleHeight;
MECH_TARGET_POS(this) = cm;
}
MECH_TARGET_ENTITY(this) = 0; // crosshair off -> no lock
MECH_TARGET_SUBIDX(this) = -1;
}
}
@@ -2369,7 +2364,7 @@ void
float hddx = dp.x - localOrigin.linearPosition.x;
float hddz = dp.z - localOrigin.linearPosition.z;
BTSetHudTargetRange((Scalar)sqrtf(hddx*hddx + hddz*hddz));
gBTHudLockState = (hotTarget != 0) ? 2 : 1;
gBTHudLockState = 2; // locked == crosshair on it
gBTHudLockWorld[0] = dp.x;
gBTHudLockWorld[1] = dp.y + kMuzzleHeight;
gBTHudLockWorld[2] = dp.z;