diff --git a/docs/ISSUES.md b/docs/ISSUES.md index 08f1fd8..42e098f 100644 --- a/docs/ISSUES.md +++ b/docs/ISSUES.md @@ -3480,20 +3480,21 @@ Unverified. The likely culprits, ranked by suspected probability: **Commits:** `f6305b1` — feat(physics): #101 — add IsPhantomGfxObjSource predicate; `5240d65` — fix(physics): #101 — suppress mesh-aabb-fallback for phantom GfxObj stabs; `6ca872f` — docs(test): #101 — sync stale GameWindow.cs line ref in test class doc **Component:** physics, dat-handling -**Resolution.** `PhysicsDataCache.IsPhantomGfxObjSource(gfxObjId)` predicate returns `true` when a GfxObj -has no PhysicsBSP (`PhysicsRadius == 0`) and the cyl/sphere shadow shapes would be synthesized -from the visual AABB radius alone (`vAabbR > 0`). `GameWindow.RegisterGfxObjShadow` (line 6127) -gates `ShadowShapeBuilder.FromGfxObj` behind this predicate — if the source is a phantom, the -registration is skipped entirely. The 10 phantom stair cyls from `GfxObj 0x0100081A` -(`vAabbR=0.82, hasPhys=False`) that previously blocked the player at the foot of the Holtburg -upper-floor staircase are no longer registered. Collision falls through to entity `0x40B50089` -(GfxObj `0x01000C16`, `hasPhys=True` BSP with walkable inclined polygon at `Normal.Z=0.717`, -world ramp from (111.10, 25.50, 94.00)→(107.50, 27.10, 97.50)). 3 unit tests in -`PhysicsDataCacheTests.IsPhantomGfxObjSource_*` (no BSP + AABB → true; has BSP → false; -no BSP + no AABB → false) shipped alongside the predicate. +**Resolution.** `PhysicsDataCache.IsPhantomGfxObjSource(gfxObjId)` predicate returns `true` when +the entity's `SourceGfxObjOrSetupId` has the GfxObj high byte (`0x01`) AND no cached +`GfxObjPhysics` entry exists (or its `BSP.Root` is null) — i.e., the underlying GfxObj had +`HasPhysics=False` so `PhysicsDataCache.CacheGfxObj` short-circuited. The inline +mesh-AABB-fallback gate at `GameWindow.cs:6127` checks this predicate and skips the shadow-shape +registration entirely when the source is a phantom. The 10 phantom stair cyls from +`GfxObj 0x0100081A` (`hasPhys=False`) that previously blocked the player at the foot of the +Holtburg upper-floor staircase are no longer registered. Collision falls through to entity +`0x40B50089` (GfxObj `0x01000C16`, `hasPhys=True` BSP with walkable inclined polygon at +`Normal.Z=0.717`, world ramp from (111.10, 25.50, 94.00)→(107.50, 27.10, 97.50)). 3 unit tests +in `PhysicsDataCachePhantomSourceTests.IsPhantomGfxObjSource_*` (no BSP → true; has BSP → +false; non-GfxObj high byte → false) shipped alongside the predicate. **Investigation:** [`docs/research/2026-05-25-a6-stairs-cyl-retail-investigation.md`](research/2026-05-25-a6-stairs-cyl-retail-investigation.md). -**Plan:** [`docs/superpowers/plans/2026-05-25-issue-101-stairs-cyl-phantom.md`](../superpowers/plans/2026-05-25-issue-101-stairs-cyl-phantom.md). +**Plan:** [`docs/superpowers/plans/2026-05-25-issue-101-stairs-cyl-phantom.md`](superpowers/plans/2026-05-25-issue-101-stairs-cyl-phantom.md). **Verification.** Visual-verified at Holtburg upper-floor cottage stairs 2026-05-25 — `[cyl-test]` count on `obj=0x40B500*` post-fix = 0 (was 7101 pre-fix); `src=0x0100081A` mesh-aabb-fallback