#131 false lock FIXED: miss-means-miss -- the pick answers only for drawn geometry
Night-12 field report (Ronin/Conn Man/Oracle, blackhawk-correlated): lock ring lit with the reticle visibly off the mech + no-reg complaints. Root cause: TWO port stand-ins answered where the 1995 card (which cast against the DRAWN geometry) would miss -- the pick's any-object sphere fallback and the caller's whole-mech AABB fallback. The regime that exposes them: a LEVEL boresight over a SHORT mech -- the blackhawk's mesh tops out below eye-ray height, so the ray clears every triangle but pierces the fat cull spheres; the ring lights with the reticle above the mech's head (the operator watched exactly this on the sweep bench). Careful aimed-down fire rides triangles, which is why Oracle's per-panel audit passed on the same build. Fix: MechSegmentPick returns 1=drawn-geometry hit / 0=TRUE MISS / -1=no render tree; the sphere may answer ONLY for a mesh the reader cannot parse (pm==0 -- currently none exist: counters objs/invFail/noTri all clean); the AABB survives ONLY as the pre-tree replicant grace. A readable mesh the ray misses is a MISS -- no lock. Verified (2-node vs bhk1 at 100u, all runs on force-relinked string- verified exes after today's stale-link flake): - LEVEL lock-sweep: 0 locks all run (pre-fix: lock band from 168 sphere answers; picksrc tri=0 sphereFB=168). - DOWN-PITCHED sweep: locks return 100%% tri-sourced (tri=158 sphereFB=0), landing on real parts (rarm/ldleg/rdleg) with honest gaps. - Full zone-walk matrix: tri=18874 sphereFB=0 box=0; victim took 156 hits across 16 zones incl. both side torsos -- combat un-regressed. New instruments (all env-gated): BT_LOCK_SWEEP=<axis> torso pan (the operator-visible lock-envelope bench), [locksweep] transition log, BT_LOCK_ENVELOPE synthetic unit-sweep probe, [picksrc]/[pickbox] source telemetry with objs/invFail/noTri localization counters. Bench: scratchpad/night12/zonewalk_bhk.sh. NOTE for the field: locking is now strictly TIGHTER (ring = reticle truly on the machine). If era testers feel the pods were more forgiving, Draco's "slight lock linger" memory becomes a deliberate investigation (sourced hysteresis), not an accidental sphere halo. Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
This commit is contained in:
co-authored by
Claude Fable 5
parent
f279e38707
commit
546aabd5ba
@@ -5584,12 +5584,30 @@ void
|
||||
Point3D hp;
|
||||
int zone = -1;
|
||||
float segHit[3];
|
||||
if (BTMechSegmentPick(m, rs, rd, 4000.0f, segHit, &zone))
|
||||
const int pickR = BTMechSegmentPick(m, rs, rd, 4000.0f, segHit, &zone);
|
||||
if (pickR > 0)
|
||||
{
|
||||
hp.x = segHit[0]; hp.y = segHit[1]; hp.z = segHit[2];
|
||||
}
|
||||
else if (!m->PickRayHit(rayStart, rayDir, 4000.0f, &hp))
|
||||
else if (pickR == 0)
|
||||
{
|
||||
// #131 MISS-MEANS-MISS: the drawn geometry was tested
|
||||
// and the ray missed -- NO lock. (The old AABB
|
||||
// fallback here answered with zone -1 and lit the
|
||||
// ring anyway: the box is far fatter than the
|
||||
// silhouette -- the second half of the false lock.)
|
||||
continue;
|
||||
}
|
||||
else if (!m->PickRayHit(rayStart, rayDir, 4000.0f, &hp))
|
||||
continue; // pickR < 0: no render tree yet -- the
|
||||
// box is the pre-tree replicant grace
|
||||
else if (getenv("BT_PICK_LOG"))
|
||||
{
|
||||
static int s_bx = 0;
|
||||
if ((++s_bx % 60) == 1)
|
||||
DEBUG_STREAM << "[pickbox] AABB grace hit #" << s_bx
|
||||
<< " (tree-absent replicant)\n" << std::flush;
|
||||
}
|
||||
float dx = hp.x - rs[0], dy = hp.y - rs[1], dz = hp.z - rs[2];
|
||||
float d = dx*dx + dy*dy + dz*dz;
|
||||
if (d < bestDist)
|
||||
@@ -5702,6 +5720,34 @@ void
|
||||
if (pickTarget != 0)
|
||||
targetReticle.rayIntersection = pickPoint;
|
||||
|
||||
// #131 LOCK-SWEEP readout: log every LOCK TRANSITION (the ring's
|
||||
// own condition -- a MECH in targetEntity) with the live twist, so
|
||||
// the sweep bench reads "lock ON at twist a .. OFF at twist b"
|
||||
// directly. Plus a 2 Hz heartbeat with zone + range.
|
||||
if (getenv("BT_LOCK_SWEEP"))
|
||||
{
|
||||
const int lockedNow = (hotTarget != 0
|
||||
&& pickTarget == hotTarget) ? 1 : 0;
|
||||
static int s_prevLock = -1;
|
||||
static float s_lsAcc = 0.0f;
|
||||
const float tw = (float)TorsoHeading();
|
||||
if (lockedNow != s_prevLock)
|
||||
{
|
||||
s_prevLock = lockedNow;
|
||||
DEBUG_STREAM << "[locksweep] " << (lockedNow ? "LOCK" : "unlock")
|
||||
<< " at twist=" << tw
|
||||
<< " zone=" << hotZone << "\n" << std::flush;
|
||||
}
|
||||
s_lsAcc += dt;
|
||||
if (s_lsAcc >= 0.5f)
|
||||
{
|
||||
s_lsAcc = 0.0f;
|
||||
DEBUG_STREAM << "[locksweep] hb lock=" << lockedNow
|
||||
<< " twist=" << tw << " zone=" << hotZone
|
||||
<< "\n" << std::flush;
|
||||
}
|
||||
}
|
||||
|
||||
// the engine-Entity target slots the whole weapon path reads
|
||||
if (pickTarget != 0)
|
||||
{
|
||||
@@ -6574,6 +6620,87 @@ void
|
||||
}
|
||||
}
|
||||
|
||||
// #131 LOCK-ENVELOPE PROBE (BT_LOCK_ENVELOPE=1): the symptom-shaped
|
||||
// measurement -- every ~2s, cast 49 rays from the eye toward the first
|
||||
// living target, yaw-offset -6..+6 deg in 0.25-deg steps, and print ONE
|
||||
// line: which source answered at each offset (T=triangle, S=sphere
|
||||
// fallback, B=whole-mech box, .=miss). The false lock reads directly:
|
||||
// S/B cells OUTSIDE the contiguous T band are lock-without-mech; misses
|
||||
// INSIDE it are no-reg-on-mech. Deterministic -- no servo, no spin.
|
||||
if ((Entity *)this == application->GetViewpointEntity()
|
||||
&& getenv("BT_LOCK_ENVELOPE"))
|
||||
{
|
||||
static float s_leT = 0.0f;
|
||||
s_leT += dt;
|
||||
if (s_leT >= 2.0f)
|
||||
{
|
||||
s_leT = 0.0f;
|
||||
extern int BTGetTargetCandidates(Entity *shooter, Entity **out, int maxOut);
|
||||
extern int BTIsRegisteredMech(Entity *e);
|
||||
extern int BTGetAimRay(float rx, float ry, float outStart[3], float outDir[3]);
|
||||
extern int BTMechSegmentPick(void *mech, const float s[3],
|
||||
const float dir[3], float max_range, float hit_out[3], int *zone_out);
|
||||
Entity *cand[8]; Mech *tgt = 0;
|
||||
int nc = BTGetTargetCandidates((Entity *)this, cand, 8);
|
||||
for (int ci = 0; ci < nc && tgt == 0; ++ci)
|
||||
if (cand[ci] != 0 && BTIsRegisteredMech(cand[ci])
|
||||
&& !((Mech *)cand[ci])->IsMechDestroyed())
|
||||
tgt = (Mech *)cand[ci];
|
||||
float rs[3], rdUnused[3];
|
||||
if (tgt != 0 && BTGetAimRay(0.0f, 0.0f, rs, rdUnused))
|
||||
{
|
||||
// bearing to the target's torso (origin + 5u up)
|
||||
float tx = (float)tgt->localOrigin.linearPosition.x - rs[0];
|
||||
float ty = ((float)tgt->localOrigin.linearPosition.y + 5.0f) - rs[1];
|
||||
float tz = (float)tgt->localOrigin.linearPosition.z - rs[2];
|
||||
float len = sqrtf(tx*tx + ty*ty + tz*tz);
|
||||
if (len > 1.0f)
|
||||
{
|
||||
tx /= len; ty /= len; tz /= len;
|
||||
char row[64];
|
||||
int nT = 0, nS = 0, nB = 0;
|
||||
for (int k = 0; k < 49; ++k)
|
||||
{
|
||||
// UNIT-based lateral sweep: -8..+8 u of miss distance
|
||||
// at the target's range (spheres inflate the lock
|
||||
// area in UNITS; a degree sweep degenerates at close
|
||||
// range -- operator caught the near-spawn scene).
|
||||
float lat = -8.0f + (16.0f / 48.0f) * (float)k;
|
||||
float rad = atan2f(lat, len);
|
||||
float c = cosf(rad), s = sinf(rad);
|
||||
float dir[3] = { tx*c + tz*s, ty, -tx*s + tz*c };
|
||||
float hp[3]; int zone = -1;
|
||||
int r = BTMechSegmentPick((void *)tgt, rs, dir, 4000.0f, hp, &zone);
|
||||
if (r)
|
||||
{
|
||||
// distinguish tri vs sphere: a sphere answer has
|
||||
// zone from segPick (>=0 possible) -- use the
|
||||
// [picksrc] counters for the split; here mark hits
|
||||
// vs the AABB probe below.
|
||||
row[k] = 'T'; ++nT;
|
||||
}
|
||||
else
|
||||
{
|
||||
Point3D bp;
|
||||
if (tgt->PickRayHit(
|
||||
Point3D(rs[0], rs[1], rs[2]),
|
||||
Point3D(dir[0], dir[1], dir[2]),
|
||||
4000.0f, &bp))
|
||||
{ row[k] = 'B'; ++nB; }
|
||||
else
|
||||
row[k] = '.';
|
||||
}
|
||||
}
|
||||
row[49] = 0;
|
||||
DEBUG_STREAM << "[lockenv] range=" << len
|
||||
<< " lat -8..+8u: " << row
|
||||
<< " (pick=" << nT << " box+=" << nB << ")\n" << std::flush;
|
||||
(void)nS;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// #124 PROBE (BT_ASPECT_TEST=1): the zero-premise frame probe. At frame
|
||||
// ~700, dispatch four self TakeDamage messages whose impact points sit
|
||||
// at KNOWN WORLD BEARINGS (+X/-X/+Z/-Z, 8 u out, torso height) around
|
||||
|
||||
Reference in New Issue
Block a user