fix #137 (mechanism 2): BSP full-hit stubs leaked sliding normals — the corridor absorbing wedge
The Facility Hub corridor dead-stop's second half: after one seam hit, every forward resolve returned ok=False hit=no with zero advance. The body-persisted SlidingNormal (-1,0,0) projected the exactly-anti-parallel corridor push to zero in AdjustOffset and the step loop aborted at step 0 before any collision test could refresh the state. Audit (docs/research/2026-07-06-137-sliding-normal-lifecycle-audit.md): retail's only in-transition sliding-normal writer is validate_transition (0x0050ac21); the whole sphere/BSP layer writes NONE (grep-verified), and the body persistence (SetPositionInternal 0x005154c2, SLIDING_TS bit sync 0x005154e1) runs only on transition success. Our BSPQuery Contact-branch full-hit responses were stubs (SetCollisionNormal + SetSlidingNormal + return Slid) where retail dispatches the real slide_sphere — so the seam hit (a SUCCESSFUL full-advance resolve per the live log) persisted the phantom wall's normal, which retail's lifecycle structurally cannot do. - BSPQuery Contact foot full-hit fallback + head full-hit now route through Transition.SlideSphereInternal (CSphere::slide_sphere 0x00537440 — in-frame slide, no sliding-normal write; ACE BSPTree.cs:202,310-316). The dead stub is rewritten as the faithful BSPTREE::slide_sphere wrapper. - PhysicsEngine sliding writeback gated on ok (retail success-only placement; behaviorally latent, removes the failed-frame leak class). - Register: TS-4 amended (Path-6 steep-tangent sites still write the normal — now documented), TS-45 added (SphereCollision's write — same leak class, left for a follow-up out of #171's blast radius). - Pins: Issue137SlidingNormalLifecycleTests — both site pins RED->GREEN, plus the retail persist/absorb/clear wall lifecycle (validate-write persistence, faithful absorbed anti-parallel frame, oblique escape clears the bit). BSPQueryTests full-hit pin updated to the real slide. Mechanism 1 (PortalSide portal polys solid in the physics set) stays OPEN - #137 not closed; the corridor re-test rides that session. Suites: Core 2545 / App 713 / UI 425 / Net 385, 0 failures. Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
This commit is contained in:
parent
e73e45da54
commit
a11df5b8d3
7 changed files with 474 additions and 31 deletions
|
|
@ -699,8 +699,13 @@ public class BSPQueryTests
|
|||
// Regression guard for the FULL-HIT case in the same Path 5 branch.
|
||||
// Sphere overlaps wall AND moves INTO it: moveDot < 0, cull does NOT
|
||||
// reject, pos_hits_sphere returns 1, Path 5 takes the `if (hit0)`
|
||||
// branch. With engine=null we fall through to the slide fallback
|
||||
// (SetCollisionNormal + SetSlidingNormal + return Slid).
|
||||
// branch. With engine=null we fall through to the real slide
|
||||
// (CSphere::slide_sphere via Transition.SlideSphereInternal). No
|
||||
// contact plane is seeded on this bare Transition, so the slide takes
|
||||
// the wall-only branch (project out the into-wall displacement,
|
||||
// return Slid) — and per retail it must NOT write the sliding normal
|
||||
// (#137 mechanism 2; validate_transition 0x0050ac21 is the only
|
||||
// in-transition writer).
|
||||
var (root, resolved) = BuildSingleWallBsp();
|
||||
|
||||
var transition = new Transition();
|
||||
|
|
@ -731,6 +736,9 @@ public class BSPQueryTests
|
|||
Assert.Equal(TransitionState.Slid, state);
|
||||
Assert.True(transition.CollisionInfo.CollisionNormalValid,
|
||||
"Full hit should set the collision normal (slide fallback).");
|
||||
Assert.False(transition.CollisionInfo.SlidingNormalValid,
|
||||
"find_collisions must not write the sliding normal — retail's " +
|
||||
"only in-transition writer is validate_transition (#137).");
|
||||
Assert.False(transition.SpherePath.NegPolyHit,
|
||||
"Full hit should NOT also fire NegPolyHit — that's the near-miss " +
|
||||
"path only. Retail at acclient_2013_pseudo_c.txt:0053a647 returns " +
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue