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:
co-authored by
Claude Fable 5
parent
a8a56c57c9
commit
60ed54e008
@@ -2330,24 +2330,38 @@ 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)
|
||||
// TARGET (mech+0x388) is AUTO-ACQUIRED, not manually locked (task #40,
|
||||
// binary-confirmed): the weapon's fire path (Emitter FUN_004baa88 :7689
|
||||
// + FireWeapon FUN_004bace8 :7727) is DOUBLY gated on mech+0x388 != 0 --
|
||||
// no target, NO beam, ever -- but 0x388 is WRITTEN INDIRECTLY (a
|
||||
// disasm scan of the whole CODE section finds 11 reads and ZERO direct
|
||||
// stores), i.e. the game AUTO-SELECTS the target for you; you never
|
||||
// manually "lock" to fire. The spinning-ring LOCK (HudSimulation
|
||||
// 5619-5634) is a SEPARATE, stricter state layered on top. So: 0x388
|
||||
// = the enemy whenever it is alive (the pod's auto-target); firing
|
||||
// needs only that, NOT a pinpoint boresight hit. A pinpoint hull hit
|
||||
// (hotTarget) UPGRADES the shot to aimed-zone damage + the lock ring.
|
||||
Entity *autoTarget =
|
||||
(gEnemyMech != 0 && !((Mech *)gEnemyMech)->IsMechDestroyed())
|
||||
? gEnemyMech : 0;
|
||||
if (autoTarget != 0)
|
||||
{
|
||||
MECH_TARGET_ENTITY(this) = hotTarget;
|
||||
MECH_TARGET_ENTITY(this) = autoTarget;
|
||||
MECH_TARGET_SUBIDX(this) = -1;
|
||||
MECH_TARGET_POS(this) = hotPoint; // the aimed hull point
|
||||
if (hotTarget != 0)
|
||||
MECH_TARGET_POS(this) = hotPoint; // aimed: the picked hull point
|
||||
else
|
||||
{
|
||||
// no pinpoint pick -> converge on the target's centre mass
|
||||
// (the beam still fires; the zone resolves near-centre).
|
||||
Point3D cm = ((Mech *)autoTarget)->localOrigin.linearPosition;
|
||||
cm.y += kMuzzleHeight;
|
||||
MECH_TARGET_POS(this) = cm;
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
MECH_TARGET_ENTITY(this) = 0; // crosshair off -> no lock
|
||||
MECH_TARGET_ENTITY(this) = 0; // no living enemy -> no target
|
||||
MECH_TARGET_SUBIDX(this) = -1;
|
||||
}
|
||||
}
|
||||
@@ -2424,12 +2438,12 @@ void
|
||||
{
|
||||
gTargetLogAccum = 0.0f;
|
||||
DEBUG_STREAM << "[target] aim=(" << gBTAimX << "," << gBTAimY << ")"
|
||||
<< (hotTarget != 0 ? " HOT (crosshair on target)"
|
||||
: (designated ? " designated (off-crosshair)" : " no target"))
|
||||
<< (hotTarget != 0 ? " HOT-aimed (zone under crosshair)"
|
||||
: (designated ? " auto-target (fire freely, body hits)" : " no living target"))
|
||||
<< " range=" << range
|
||||
<< (range <= kWeaponRange ? " IN RANGE" : "")
|
||||
<< " [hits=" << gAimHits << " noRay=" << gAimNoRay
|
||||
<< " noPick=" << gAimNoPick << "]"
|
||||
<< " [aimedHits=" << gAimHits << " noRay=" << gAimNoRay
|
||||
<< " offHull=" << gAimNoPick << "]"
|
||||
<< "\n" << std::flush;
|
||||
gAimHits = 0; gAimNoRay = 0; gAimNoPick = 0;
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user