feat(physics): A4 — wire CheckOtherCells into FindEnvCollisions

After the primary cell's BSP returns OK, query every other cell the
foot-sphere overlaps via CellTransit.FindCellSet + Transition.CheckOtherCells.
Closes the Holtburg inn vestibule wall walk-through: the vestibule
(cell 0xA9B40164) has only 4 BSP polys; walls live in the adjacent
interior cell (0xA9B40157). Without A4 the adjacent cell's BSP was
never queried.

End-to-end test reduces the real Holtburg bug to a minimal synthetic
two-cell fixture: empty vestibule BSP + interior cell with the
existing BSPStepUpFixtures.TallWall (the same fixture B2 uses to
prove a grounded mover can't scale a 5m wall). Pre-A4: returns OK
(walks through). Post-A4: returns Slid (the wall halts the
transition).

FindEnvCollisions visibility tightened from private → internal so
the integration test can call it directly without going through
FindTransitionalPosition's sub-step iteration.

Retail oracle: acclient_2013_pseudo_c.txt:272717-272798
(CTransition::check_other_cells).

Spec: docs/superpowers/specs/2026-05-20-phase-a4-multi-cell-bsp-design.md
Plan: docs/superpowers/plans/2026-05-20-phase-a4-multi-cell-bsp.md

Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
This commit is contained in:
Erik 2026-05-20 16:23:00 +02:00
parent 493c5e5ff6
commit 967d065141
2 changed files with 164 additions and 1 deletions

View file

@ -1502,7 +1502,7 @@ public sealed class Transition
}
}
private TransitionState FindEnvCollisions(PhysicsEngine engine)
internal TransitionState FindEnvCollisions(PhysicsEngine engine)
{
var sp = SpherePath;
var ci = CollisionInfo;
@ -1618,6 +1618,21 @@ public sealed class Transition
return cellState;
}
// ── Phase A4 (2026-05-20): query every other cell ──────────
// Retail oracle: CTransition::check_other_cells at
// acclient_2013_pseudo_c.txt:272717-272798. The vestibule
// walls bug (cell 0xA9B40164 has only 4 polys; adjacent
// 0xA9B40157 has the actual walls) closes here.
//
// Discard the containing-cell return — sp.CheckCellId is
// already authoritative for the primary cell we just queried.
_ = CellTransit.FindCellSet(engine.DataCache, footCenter, sphereRadius,
sp.CheckCellId, out var cellSet);
var otherCellsState = CheckOtherCells(engine, footCenter, sphereRadius, cellSet);
if (otherCellsState != TransitionState.OK)
return otherCellsState;
// ──────────────────────────────────────────────────────────
// ── Synthesize indoor walkable contact plane ──────────────
// Indoor walking Phase 2 follow-up (2026-05-19). When the BSP
// returns OK (no wall collision), the player is standing on a