fix(#171): sticky deep-overlap back-off sign pin — the runaway-to-center (gate-2 residual)

Gate 2: pack behavior good except "sometimes the monster is in the
character / too close vs retail". The ACDREAM_PROBE_STICKY capture
nailed it frame-by-frame: 1661 deep-overlap AdjustOffset ticks, ALL
steering inward (dist -0.65 -> -0.78 -> ... -> -1.9 at +0.13/tick),
monsters converging to centerDist~0 — while the suppressed-snap lines
show ACE's authoritative positions stayed properly OUTSIDE (drift up to
7.7 m). The radii were correct (tgtR=0.68, ownR=0.59-0.98).

Root cause: ACE's literal decode of StickyManager::adjust_offset
(`if (delta >= |dist|) delta = dist;`) leaves delta POSITIVE when the
overlap exceeds one tick's step — steering TOWARD the target center, a
runaway whose equilibrium is centers-coincident. ACE servers virtually
never reach that branch (quantum >=1/30 -> threshold ~1 m); at
render-rate quanta the threshold is ~0.13 m and pack jostle trips it
constantly. The BN mush (0x00555554-0x00555597) is unreadable on
exactly this compare; the retail oracle (side-by-side on the same ACE:
monsters separate) refutes the ACE-literal reading.

Pin: sign-correct clamp — `else if (dist < 0) delta = -delta` (back off
rate-limited). Identical to ACE-literal in every shallow/outside case.
Register row AP-82 (same commit) with the cdb verification note.
Conformance: StickyManagerTests.AdjustOffset_DeepOverlap_BacksOff_
RateLimited. Full suite 4039 green.

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
This commit is contained in:
Erik 2026-07-05 09:51:24 +02:00
parent 7a82317614
commit 699669502c
3 changed files with 40 additions and 1 deletions

View file

@ -236,9 +236,27 @@ public sealed class StickyManager
// Don't overshoot: clamp the per-tick step to the remaining (signed)
// distance — a negative dist inverts the direction (back off).
//
// DEEP-OVERLAP SIGN PIN (#171 gate-3, register AP row): ACE's literal
// line is only `if (delta >= |dist|) delta = dist;` — when the
// overlap is DEEPER than one tick's step, delta keeps its positive
// sign and steers TOWARD the target center, a runaway whose
// equilibrium is centers-coincident (gate-3 probe: 1661 deep-overlap
// ticks, all inward, monsters converged to centerDist≈0 — the
// "monster inside the player" report; retail side-by-side shows
// separation). ACE servers essentially never reach that branch
// (quantum ≥1/30 × speed ≈31 → threshold ~1 m); at render-rate
// quanta the threshold is ~0.13 m and pack jostle trips it
// constantly. The BN mush (0x00555554-0x00555597) is unreadable on
// exactly this compare; the sign-correct clamp below is the minimal
// interpretation consistent with the mush structure AND observed
// retail — identical to ACE everywhere except deep-overlap, where it
// backs off rate-limited instead of creeping inward.
float delta = speed * (float)quantum;
if (delta >= MathF.Abs(dist))
delta = dist;
else if (dist < 0f)
delta = -delta;
offset.Origin *= delta;
// Bounded turn to face the target (relative heading this tick).