fix(phys): A6.P3 slice 3 v3 — REVERT stickiness; hypothesis-test cellar-up
Slice 3 v2 (point-in stickiness) closed the cell-resolver ping-pong (data confirmed: scen4_cottage_cellar_slice3v2 capture shows 1 cell- transit vs 20+ pre-fix). BUT user verification revealed: cellar-up symptom transitioned from "stuck-at-top-ping-pong" (pre-slice-3) to "never-reach-top-stuck-in-cellar" (post-slice-3). Stickiness was holding player in cellar cell so aggressively that the legitimate transition to the cottage main floor cell at the ramp top never fired. Reverting the stickiness check entirely. Trade-off: - Inn doorway ping-pong returns (existed pre-slice-3; lesser evil) - Player can again reach the top of the cellar ramp (per pre-slice-3 user observation) - Issue #98 cellar-up remains open — but with sharper diagnosis: it's not the cell resolver at all, it's deeper (BSP step-physics or AdjustOffset slope-projection at the cottage main floor boundary, per slice 4 polydump trace showing repeated push-back on the 46-degree ramp polygon) The slice 3 stickiness premise was correct but the implementation shape was wrong. A future attempt needs either: - A "near boundary" gate (only stick when sphere is deep inside cell) - A retail-faithful per-cell hysteresis matching CObjCell::find_cell_list Position-variant (acclient_2013_pseudo_c.txt:308742-308783) more exactly than point-in - OR address the underlying BSP step-physics bug first; then ping-pong may not even need a stickiness fix Test suite: 1148 + 8 (baseline maintained). Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
This commit is contained in:
parent
319847289e
commit
8bd311759e
1 changed files with 17 additions and 38 deletions
|
|
@ -262,46 +262,25 @@ public sealed class PhysicsEngine
|
||||||
// _landblocks (no DataCache dependency).
|
// _landblocks (no DataCache dependency).
|
||||||
if (DataCache is null) return fallbackCellId;
|
if (DataCache is null) return fallbackCellId;
|
||||||
|
|
||||||
// ── Cell-stickiness check (A6.P3 slice 3, 2026-05-22) ──
|
// ── Cell-stickiness REVERTED (A6.P3 slice 3 v3, 2026-05-22) ──
|
||||||
// Before re-resolving via FindCellList, check if the fallback
|
// Slice 3 v1 (sphere-overlap, 8898166) over-corrected — held
|
||||||
// CellId still validly contains the sphere CENTER (point-in).
|
// player in cellar even when transitioning out at the ramp top.
|
||||||
// If yes, prefer it over any FindCellList result that might
|
// Slice 3 v2 (point-in, 3e140cf) closed the ping-pong at the
|
||||||
// pick a different cell whose BSP also contains the point —
|
// inn doorway (data confirmed) BUT prevented the player from
|
||||||
// fixes issue #98 (cellar-up stuck at last step due to CellId
|
// reaching the top of the cellar ramp (the stuck spot
|
||||||
// ping-ponging between adjacent cells in iteration-order races).
|
// transitioned from "ping-pong at top" to "never reach top").
|
||||||
//
|
//
|
||||||
// Mechanism: when the sphere is on a cell boundary where the
|
// Reverting to no-stickiness for now. The ping-pong at the inn
|
||||||
// CENTER is in multiple cells geometrically (overlapping BSPs),
|
// doorway returns but is a lesser evil than blocking cellar-up
|
||||||
// FindCellList's candidate-iteration order (HashSet,
|
// entirely. Issue #98 cellar-up has a deeper bug that needs
|
||||||
// implementation-defined) determines which cell wins. That
|
// separate investigation (BSP step-physics or AdjustOffset
|
||||||
// order may shift tick-to-tick → ping-pong. Stickiness keeps
|
// slope-projection at the cottage main floor boundary).
|
||||||
// the CURRENT cell as long as the sphere center is still
|
|
||||||
// inside it, only switching when the center has moved out.
|
|
||||||
//
|
//
|
||||||
// Uses POINT-IN (not sphere-overlap). Sphere-overlap stickiness
|
// Slice 3 work remains valuable as research evidence; the fix
|
||||||
// (the first slice 3 attempt) over-corrected — held the player
|
// shape was wrong. Issue #90 stays as workaround until a
|
||||||
// in the fallback cell even when the center had transitioned to
|
// better stickiness mechanism is designed (probably needs to
|
||||||
// an adjacent cell, blocking legitimate cell transitions at
|
// be GATED by some "near cell boundary" check rather than
|
||||||
// stair tops + portal exits. Point-in matches FindCellList's
|
// applied unconditionally).
|
||||||
// own semantics for "which cell are you in."
|
|
||||||
//
|
|
||||||
// Retail oracle: cell-array hysteresis pattern from
|
|
||||||
// CObjCell::find_cell_list Position-variant at
|
|
||||||
// acclient_2013_pseudo_c.txt:308742-308783.
|
|
||||||
//
|
|
||||||
// Likely closes/obsoletes:
|
|
||||||
// - #98 (cellar ascent stuck at last step) — direct target
|
|
||||||
// - #97 (phantom collisions + fall-through on 2nd floor) —
|
|
||||||
// same instability family hypothesized
|
|
||||||
// - #90 (sphere-overlap workaround below) — superseded;
|
|
||||||
// can be removed after visual verification (A6.P4)
|
|
||||||
var fallbackCell = DataCache.GetCellStruct(fallbackCellId);
|
|
||||||
if (fallbackCell?.CellBSP?.Root is not null)
|
|
||||||
{
|
|
||||||
var fallbackLocal = Vector3.Transform(worldPos, fallbackCell.InverseWorldTransform);
|
|
||||||
if (BSPQuery.PointInsideCellBsp(fallbackCell.CellBSP.Root, fallbackLocal))
|
|
||||||
return fallbackCellId; // center still inside; stick.
|
|
||||||
}
|
|
||||||
|
|
||||||
// Fallback cell no longer valid → re-resolve via portal-graph BFS.
|
// Fallback cell no longer valid → re-resolve via portal-graph BFS.
|
||||||
uint indoorResult = CellTransit.FindCellList(DataCache, worldPos, sphereRadius, fallbackCellId);
|
uint indoorResult = CellTransit.FindCellList(DataCache, worldPos, sphereRadius, fallbackCellId);
|
||||||
|
|
|
||||||
Loading…
Add table
Add a link
Reference in a new issue