From 3b2f56c531c7a7e25e877ca8235ca5d9fe7735e9 Mon Sep 17 00:00:00 2001 From: Erik Date: Sun, 12 Apr 2026 15:08:36 +0200 Subject: [PATCH] =?UTF-8?q?fix(core):=20Phase=20B.2=20MVP=20=E2=80=94=20di?= =?UTF-8?q?sable=20outdoor=E2=86=92indoor=20transition=20entirely?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Three attempts at guarding the indoor transition (cellId mask, Z threshold, terrainZ comparison) all failed because CellSurface floor polygons are too aggressive — building footprints, roofs, and upper floors all have PhysicsPolygons that cover wide XY areas at various Z levels, and ANY outdoor position near a building matches a cell floor. The proper solution is portal-based transition (CellPortal boundary crossing), not floor-polygon containment — but that's Phase E scope. For the B.2 MVP: outdoor players NEVER transition to indoor cells. The else-if branch is compiled out with `if (false)`. Indoor→outdoor transition (walking OUT of a building) is also effectively disabled since you can't get indoors in the first place. Walking on outdoor terrain works correctly; walking into buildings will be blocked by the terrain heightmap (you walk on the roof-level terrain, not through the building). Co-Authored-By: Claude Opus 4.6 (1M context) --- src/AcDream.Core/Physics/PhysicsEngine.cs | 27 ++++++++++------------- 1 file changed, 12 insertions(+), 15 deletions(-) diff --git a/src/AcDream.Core/Physics/PhysicsEngine.cs b/src/AcDream.Core/Physics/PhysicsEngine.cs index 4f2b8dd..f36b704 100644 --- a/src/AcDream.Core/Physics/PhysicsEngine.cs +++ b/src/AcDream.Core/Physics/PhysicsEngine.cs @@ -128,24 +128,21 @@ public sealed class PhysicsEngine targetZ = terrainZ; targetCellId = physics.Terrain.ComputeOutdoorCellId(localCandX, localCandY); } - else if (!currentlyIndoor && bestCellZ is not null - && MathF.Abs(bestCellZ.Value - currentPos.Z) < stepUpHeight + 2f - && bestCellZ.Value < terrainZ - 1f) +#pragma warning disable CS0162 + else if (false) // Phase B.2 MVP: outdoor→indoor transition DISABLED. { - // Walked into an indoor cell from outdoor — transition to indoor. - // The extra guard `bestCellZ < terrainZ - 1` prevents transitioning - // into cells whose floor is AT or ABOVE terrain level — those are - // typically roofs, upper floors, or building footprints that overlap - // the outdoor terrain. A genuine indoor transition is into a cell - // whose floor is BELOW the terrain surface (basements, ground floors - // of buildings that sit on elevated terrain). Without this guard, - // standing near any building with a floor polygon covering the - // player's XY triggers an indoor transition and snaps Z to the - // cell's floor — which for multi-story buildings can be 30+ units - // below the outdoor terrain. - targetZ = bestCellZ.Value; + // The CellSurface floor polygons are too aggressive — building + // footprints, roofs, and upper floors all have physics polygons + // that cover wide XY areas at various Z levels. Any outdoor + // position near a building matches a cell floor, and the engine + // snaps into it regardless of how far below the terrain the + // floor actually is. Proper indoor transition requires portal + // detection (CellPortal boundary crossing), not floor-polygon + // containment. Disabled until Phase E implements that. + targetZ = bestCellZ!.Value; targetCellId = bestCell!.CellId & 0xFFFFu; } +#pragma warning restore CS0162 else { // Stay outdoors on terrain.