diff --git a/src/AcDream.App/Rendering/GameWindow.cs b/src/AcDream.App/Rendering/GameWindow.cs index 6227452..e148d74 100644 --- a/src/AcDream.App/Rendering/GameWindow.cs +++ b/src/AcDream.App/Rendering/GameWindow.cs @@ -6100,6 +6100,17 @@ public sealed class GameWindow : IDisposable } } + // Issue #101 (2026-05-25): retail-faithful phantom check for + // GfxObj-only entity sources. Retail's CPartArray::InitParts + // emits NO collision shapes when the source GfxObj has + // HasPhysics=False / null PhysicsBSP.Root. Our mesh-aabb-fallback + // below previously synthesized a clamped [0.30, 1.50]m cylinder + // from the visual mesh AABB — that's the source of the 10 + // phantom 0.80m cyls that block the Holtburg upper-floor + // staircase (issue #101). Suppress synthesis for these. + // Spec: docs/research/2026-05-25-a6-stairs-cyl-retail-investigation.md. + bool isPhantomGfxObj = _physicsDataCache.IsPhantomGfxObjSource(entity.SourceGfxObjOrSetupId); + // VISUAL mesh-bounds collision: for SCENERY entities (IDs with // 0x80000000 bit set, indicating procedurally-placed scenery), // ALWAYS compute a cylinder from the world-space mesh AABB. @@ -6114,6 +6125,7 @@ public sealed class GameWindow : IDisposable // L-fix3: skip entirely when the Setup is phantom — retail // decorative meshes have no collision data on purpose. if (!isPhantomSetup + && !isPhantomGfxObj && !_isLandblockStab && (_isOutdoorMesh || (entityBsp == 0 && entityCyl == 0)) && entity.MeshRefs.Count > 0) diff --git a/src/AcDream.Core/Physics/PhysicsDataCache.cs b/src/AcDream.Core/Physics/PhysicsDataCache.cs index fbe8a2d..c7b65a5 100644 --- a/src/AcDream.Core/Physics/PhysicsDataCache.cs +++ b/src/AcDream.Core/Physics/PhysicsDataCache.cs @@ -370,7 +370,7 @@ public sealed class PhysicsDataCache /// short-circuited at the early-return on line 45/46. Retail's /// CPartArray::InitParts emits NO collision shapes for /// these — acdream's mesh-aabb-fallback synthesis at - /// GameWindow.cs:6116 must do the same. + /// GameWindow.cs:6127 must do the same. /// public bool IsPhantomGfxObjSource(uint sourceId) {