diff --git a/context/combat-damage.md b/context/combat-damage.md index 3ee0725..15f23ae 100644 --- a/context/combat-damage.md +++ b/context/combat-damage.md @@ -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 diff --git a/context/open-questions.md b/context/open-questions.md index 8fa21be..388148b 100644 --- a/context/open-questions.md +++ b/context/open-questions.md @@ -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 diff --git a/game/reconstructed/mech4.cpp b/game/reconstructed/mech4.cpp index dda4e3c..f20983c 100644 --- a/game/reconstructed/mech4.cpp +++ b/game/reconstructed/mech4.cpp @@ -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;