diff --git a/docs/ISSUES.md b/docs/ISSUES.md index 4ed75097..519a5d1f 100644 --- a/docs/ISSUES.md +++ b/docs/ISSUES.md @@ -10575,7 +10575,58 @@ did **not** resolve it either, which is itself a diagnostic clue (see below). formations, and no floor above it — jumping over lands you inside/through. "Solid near the middle, absent at the edges" is the shape to reason from. -### Leading candidate — AP-158 / #333, the broadphase reach filter +### MEASURED IN GAME 2026-08-06 — cause found, and it is NOT the reach filter + +**The reach-filter theory is REFUTED.** A live probe (`ACDREAM_PROBE_REACH`, +commit `b61f5fd4`) was run with the user standing in front of, and then inside, +a Neftet formation. Evidence: `334-neftet-probe.log`, 8,401 lines. + +Standing inside the formation the collision system reported: + +``` +[reach-q] cell=0x87640019 inCell=2 exempt=2 reached=0 rejectedReach=0 tested=0 blocked=0 +``` + +**Two candidates, both the player's own body spheres.** Nothing was rejected +because there was nothing to reject — the formation is not in the collision +candidate set at all. `rejectedReach=0` kills AP-158 as the cause here. + +**The blocking part the user found is the discriminator.** One object does +collide: `gfx=0x010046D8`, a BSP with `objR=69.471` — the landblock's baked +rock geometry, one object spanning a large area. Its coverage: + +| Cell | Rock object present? | +|---|---| +| `0x8764000A`, `0x87640012` | **YES** — `tested-collided` / `tested-slid`, player blocked | +| `0x87640011`, `0x87640019`, `0x87630018` | **NO** — `inCell=2`, both entries the player | + +**Same object, same landblock, present in some cells and absent from directly +adjacent ones.** `0x87640012` is cell index 17 → grid (2,1); `0x87640011` is +index 16 → grid (2,0), immediately beside it and empty. + +### Cause: a landblock-spanning object is registered by a single bounding sphere + +`ShadowObjectRegistry.BuildFloodSpheres` derives cell membership from one +sphere per part. This object's own radius is **69.471 m** while a landblock is +**192 m** across, so a single sphere cannot geometrically reach every cell the +mesh occupies. Cells beyond its reach receive no registration and the player +walks through. + +Retail does not use a sphere here. `CPhysicsObj::calc_cross_cells` @`0x00515230` +routes BSP-bearing objects to `find_bbox_cell_list` @`0x00510fc0` → +`calc_cross_cells_static` @`0x00518160`, i.e. a walk over the object's +**extent**, not a single enclosing sphere. + +**Relationship to AP-156 (`b52967de`), which did not fix this and was not +expected to:** AP-156 moved the flood sphere to the right *place* (it was +centred on the part origin while sized from the geometry). That was necessary +and is confirmed correct — but the sphere is also the wrong *shape* for objects +whose extent exceeds their own radius. AP-156 fixed position; this issue is +about coverage. Sequential, not alternative. + +### Superseded — the original leading candidate, retained for provenance + +### Superseded detail — AP-158 / #333, the broadphase reach filter `TransitionTypes.cs:3898`-ish measures `currPos - obj.Position` (the part **origin**) against `obj.Radius`, admitting a contact only when the geometry