Auto-target fire model: firing needs a target, NOT a manual lock/pinpoint (task #40)

Colleague: you fire without a lock, at "nothing." Double-checked the
binary:
- The weapon fire path is DOUBLY gated on mech+0x388 != 0:
  EmitterSimulation (FUN_004baa88:7689) only calls FireWeapon with a
  target, and FireWeapon (FUN_004bace8:7727) wraps its whole body --
  including beamFlag(+0x46c)=1 -- in the same check. So no target => no
  beam, literally (cannot fire into truly empty space). [T1]
- BUT a capstone scan of the entire CODE section finds 11 READS of
  +0x388 and ZERO direct stores: the target is written INDIRECTLY (a
  message/selector), i.e. AUTO-acquired -- there is no manual lock to
  fire. The spinning-ring LOCK (HudSimulation 5619-5634) is a separate,
  stricter state.

So the colleague is right that no lock is needed; my port was wrong to
gate firing on a pinpoint boresight-on-hull pick. Fix: mech+0x388 = the
enemy whenever it is ALIVE (auto-target); firing needs only that. A
pinpoint hull hit upgrades the shot to aimed-zone damage + the lock
ring; off-hull with the enemy present, the beam converges on centre
mass (body hits). Third correction from over-reading the RP-shared
Reticle struct (after sticky-lock and mouse-cursor).

Verified: BT_AIM="0.5 0.2" (off-hull) -> fires + lands damage (was 0
before); BT_AIM="0 0" (centred) -> HOT-aimed zone hits. KB swept;
checkctx CLEAN.

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
This commit is contained in:
arcattack
2026-07-08 23:49:29 -05:00
co-authored by Claude Fable 5
parent a8a56c57c9
commit 60ed54e008
3 changed files with 60 additions and 31 deletions
+23 -11
View File
@@ -56,17 +56,29 @@ projected through the live per-axis projection; **0 = dead-centre on the fixed-t
`BT_AIM="x y"` pins it for headless tests) → `BTGetAimRay` (the ACTIVE eye publishes pos+LookAtRH
basis via `BTSetAimCamera`, the render loop publishes proj._11/_22 + backbuffer dims) →
`Mech::PickRayHit` (world ray → local frame → `BoundingBox::HitBy` slab test vs the collision
template's ExtentBox → world hit point) → the entity target slots. The slots MIRROR the pick EACH
FRAME: locked while the boresight is ON the mech, no target otherwise — **steer to keep the enemy
under the centred crosshair; that IS the gunnery** (verified: face-to-face spawn → HOT lock;
`BT_FORCE_TURN` circling → 31 no-target vs 1 HOT). (⚠ Two earlier cuts were wrong and are
corrected: a STICKY designation — locked forever after first hover, made aim irrelevant; and a
MOUSE cursor slew — mis-sourced from the RP-shared struct, gave a free cursor the pod never had.
Both removed.) While locked the impact point = the PICKED hull point → STEP-6 resolves the zone
under the crosshair (verified: center-aim → head-band zone 13 dominant). The HUD draws the aim
group at the boresight ([0x9a] translate), the designator hotbox at the target's projected point
(subB9 hot / subB8 designated, `BTProjectHotBox`/`BTProjectToReticle`), and the edge arrows when
off-screen/behind. `BT_FIRE_ARC` is now an EXPLICIT OPT-IN presentation clamp (unset = authentic
template's ExtentBox → world hit point).
**FIRING NEEDS A TARGET BUT NOT A MANUAL LOCK / PINPOINT AIM (task #40, binary-verified [T1]).**
The weapon fire path is DOUBLY gated on `mech+0x388 != 0`: `Emitter::EmitterSimulation`
(`FUN_004baa88` :7689) only calls FireWeapon with a target, AND `Emitter::FireWeapon`
(`FUN_004bace8` :7727) wraps its ENTIRE body (incl. `beamFlag`=+0x46c=1 :7749) in the same check —
so **no target ⇒ no beam, ever** (you cannot fire into truly empty space). BUT a capstone scan of
the whole CODE section finds **11 reads of `+0x388` and ZERO direct stores** — the target is
written INDIRECTLY (a message/selector via a `this`-pointer), i.e. the game **AUTO-ACQUIRES** the
target for you; there is no manual "lock to fire." The spinning-ring **LOCK** (HudSimulation
5619-5634) is a SEPARATE, stricter state layered on top (host-zone < 0.75 damage AND targeted-zone
< 1.0). **Port model:** `mech+0x388` = the enemy whenever it is ALIVE (`!IsMechDestroyed()`) — the
pod's auto-target — so firing works freely with the enemy merely present, NO pinpoint needed
(verified: `BT_AIM="0.5 0.2"` off-hull → fires + lands damage; before this fix off-hull dealt 0).
A pinpoint hull hit (`PickRayHit``hotTarget`) UPGRADES the shot: `mech+0x37c` = the picked hull
point → STEP-6 resolves the zone under the crosshair (aimed fire; center-aim → head-band zone 13),
and lights the lock ring. Off-hull, `0x37c` = the target's centre mass (body hits, near-centre
zone). (⚠ THREE earlier cuts were wrong and are corrected: a STICKY designation — locked forever;
a MOUSE cursor slew — a free cursor the pod never had; and a PINPOINT-required fire gate — you had
to boresight the hull exactly to fire at all. All from over-reading the RP-shared `Reticle` struct;
removed.) The HUD draws the aim group at the boresight ([0x9a] translate), the designator hotbox at
the target's projected point (subB9 hot / subB8 designated, `BTProjectHotBox`/`BTProjectToReticle`),
and the edge arrows when off-screen/behind. `BT_FIRE_ARC` is now an EXPLICIT OPT-IN presentation clamp (unset = authentic
no-arc). The old hardwired lock, the ±30°-default cone, and the projectile path's gEnemyMech
fallback are all REMOVED. LMB fires lasers / RMB missiles (with SPACE/CTRL). ⚠ A view-selection
bug was fixed en route: every
+6 -3
View File
@@ -55,9 +55,12 @@ authentic path scoped.
pick-ray chain is LIVE (see [[combat-damage]] Targeting for the full port map): the crosshair =
**torso boresight** (NO free-aim mouse — the pod stick twisted the torso; you steer to aim) →
pick ray → per-frame lock (boresight ON the mech = locked; off = none) → aimed zone damage +
designator hotbox; `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 + the
HudSimulation pose derivation [T3 dynamics]); (b) our cockpit view is body-mounted, so on a
designator hotbox; `BT_FIRE_ARC` is opt-in-only now. Firing needs a target but NOT a manual
lock/pinpoint — the target is AUTO-acquired (task #40, binary-verified: FireWeapon doubly-gated
on mech+0x388, but 0x388 has 11 reads / 0 direct stores across CODE → set indirectly). Residue:
(a) the binary's own per-frame reticle→mech copy + the AUTO-TARGET SELECTOR are still in an
un-exported gap (a message/selector; our port auto-targets the single living enemy — for MP,
reconstruct the real multi-target selection: nearest/most-aligned/cycle); (b) our cockpit view is body-mounted, so on a
TWIST-CAPABLE mech the crosshair should deflect with the torso twist (`BTTwistToReticleX` is
wired for it) AND the torso should visibly lead the legs — verify on a twist mech when one is
in play (the BLH is fixed-torso, boresight always centred); (c) pre-burial, the pick still