fix(physics): L.2.3b — Path 5 step-up recursion guard
Path 5 (Contact mover hits BSP polygon) calls DoStepUp → DoStepDown → TransitionalInsert(5) → FindObjCollisions → which can hit the same wall again → Path 5 fires AGAIN → recursive DoStepUp. Bounded by the inner numAttempts=5 budget, but with significant per-step churn — every recursion clears and re-establishes the contact plane, finishing in an inconsistent state when the ranges decay. Also produced gratuitous slowdown against tall walls. Retail (acclient_2013_pseudo_c.txt:272954) gates step_sphere_up on `if (sp.step_up == 0 && sp.step_down == 0)`. acdream's port was missing this guard. Mid-recursion we now fall back to the wall-slide response that already exists for the no-engine path. Files: - BSPQuery.cs Path 5 (foot sphere): added `&& !path.StepUp && !path.StepDown` - BSPQuery.cs Path 5 (head sphere): same guard Live-test bug: walking into building walls intermittently locked the player in falling animation, hard to recover. After the guard, the single-shot wall-slide produces clean blocking + horizontal slide. Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
This commit is contained in:
parent
b2aaac4e52
commit
3789491394
1 changed files with 12 additions and 4 deletions
|
|
@ -1469,11 +1469,18 @@ public static class BSPQuery
|
|||
if (hit0 || hitPoly0 is not null)
|
||||
{
|
||||
var worldNormal = L2W(hitPoly0!.Plane.Normal);
|
||||
if (engine is not null)
|
||||
// L.2.3b (2026-04-29): recursion guard. Retail
|
||||
// (acclient_2013_pseudo_c.txt:272954) gates step_sphere_up on
|
||||
// `if (sp.step_up == 0 && sp.step_down == 0)`. Without this,
|
||||
// the inner TransitionalInsert spawned by DoStepDown re-enters
|
||||
// FindObjCollisions, hits the same wall, and recursively
|
||||
// re-invokes step-up — churning the contact plane until
|
||||
// numAttempts decays. Mid-recursion we fall back to wall-slide.
|
||||
if (engine is not null && !path.StepUp && !path.StepDown)
|
||||
return StepSphereUp(transition, worldNormal, engine);
|
||||
|
||||
// No engine available (env-cell path without engine param) —
|
||||
// fall back to wall-slide so existing indoor geometry still blocks.
|
||||
// No engine OR step-up/step-down already in progress — fall
|
||||
// back to wall-slide so the inner sphere doesn't recurse.
|
||||
collisions.SetCollisionNormal(worldNormal);
|
||||
collisions.SetSlidingNormal(worldNormal);
|
||||
return TransitionState.Slid;
|
||||
|
|
@ -1490,7 +1497,8 @@ public static class BSPQuery
|
|||
if (hit1 || hitPoly1 is not null)
|
||||
{
|
||||
var worldNormal = L2W(hitPoly1!.Plane.Normal);
|
||||
if (engine is not null)
|
||||
// L.2.3b: same recursion guard as the foot-sphere branch.
|
||||
if (engine is not null && !path.StepUp && !path.StepDown)
|
||||
return StepSphereUp(transition, worldNormal, engine);
|
||||
|
||||
collisions.SetCollisionNormal(worldNormal);
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue