From 8bd311759e742044cd311dcef6bfc8e40fe45e82 Mon Sep 17 00:00:00 2001 From: Erik Date: Fri, 22 May 2026 12:43:58 +0200 Subject: [PATCH] =?UTF-8?q?fix(phys):=20A6.P3=20slice=203=20v3=20=E2=80=94?= =?UTF-8?q?=20REVERT=20stickiness;=20hypothesis-test=20cellar-up?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit 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) --- src/AcDream.Core/Physics/PhysicsEngine.cs | 55 +++++++---------------- 1 file changed, 17 insertions(+), 38 deletions(-) diff --git a/src/AcDream.Core/Physics/PhysicsEngine.cs b/src/AcDream.Core/Physics/PhysicsEngine.cs index f8eefb4..5414f2a 100644 --- a/src/AcDream.Core/Physics/PhysicsEngine.cs +++ b/src/AcDream.Core/Physics/PhysicsEngine.cs @@ -262,46 +262,25 @@ public sealed class PhysicsEngine // _landblocks (no DataCache dependency). if (DataCache is null) return fallbackCellId; - // ── Cell-stickiness check (A6.P3 slice 3, 2026-05-22) ── - // Before re-resolving via FindCellList, check if the fallback - // CellId still validly contains the sphere CENTER (point-in). - // If yes, prefer it over any FindCellList result that might - // pick a different cell whose BSP also contains the point — - // fixes issue #98 (cellar-up stuck at last step due to CellId - // ping-ponging between adjacent cells in iteration-order races). + // ── Cell-stickiness REVERTED (A6.P3 slice 3 v3, 2026-05-22) ── + // Slice 3 v1 (sphere-overlap, 8898166) over-corrected — held + // player in cellar even when transitioning out at the ramp top. + // Slice 3 v2 (point-in, 3e140cf) closed the ping-pong at the + // inn doorway (data confirmed) BUT prevented the player from + // reaching the top of the cellar ramp (the stuck spot + // transitioned from "ping-pong at top" to "never reach top"). // - // Mechanism: when the sphere is on a cell boundary where the - // CENTER is in multiple cells geometrically (overlapping BSPs), - // FindCellList's candidate-iteration order (HashSet, - // implementation-defined) determines which cell wins. That - // order may shift tick-to-tick → ping-pong. Stickiness keeps - // the CURRENT cell as long as the sphere center is still - // inside it, only switching when the center has moved out. + // Reverting to no-stickiness for now. The ping-pong at the inn + // doorway returns but is a lesser evil than blocking cellar-up + // entirely. Issue #98 cellar-up has a deeper bug that needs + // separate investigation (BSP step-physics or AdjustOffset + // slope-projection at the cottage main floor boundary). // - // Uses POINT-IN (not sphere-overlap). Sphere-overlap stickiness - // (the first slice 3 attempt) over-corrected — held the player - // in the fallback cell even when the center had transitioned to - // an adjacent cell, blocking legitimate cell transitions at - // stair tops + portal exits. Point-in matches FindCellList's - // 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. - } + // Slice 3 work remains valuable as research evidence; the fix + // shape was wrong. Issue #90 stays as workaround until a + // better stickiness mechanism is designed (probably needs to + // be GATED by some "near cell boundary" check rather than + // applied unconditionally). // Fallback cell no longer valid → re-resolve via portal-graph BFS. uint indoorResult = CellTransit.FindCellList(DataCache, worldPos, sphereRadius, fallbackCellId);