docs: file #334 — large static formations lose collision at their boundaries

User-reported in live play at Neftet: solid on approach, permeable at a
boundary between two formations, and no floor above — jumping over lands you
through.

NOT a regression from today's collision work, and that was established by
measurement rather than argument: a client was built at 52175aa1 — before
AP-22, AP-152, AP-156, AD-10 and #276's remainder — and the user reproduced
both this and the cliff-edge symptom identically on it. Pre-existing, simply
never filed.

The leading candidate is already filed as AP-158 / #333: the broadphase
measures reach from the part ORIGIN against a `+ 2 m` budget, where retail has
no distance pre-filter at all (CObjCell::find_obj_collisions 0x0052b750
dispatches unconditionally, its only early-out being INITIAL_PLACEMENT_INSERT).
118 of 477 unique BSP GfxObjs exceed that budget and 46 exceed 5 m — and a
"large stone formation" is exactly the class whose geometry sits many metres
from its origin. Solid in the middle, permeable at the edges, no floor
overhead, follows directly.

That also explains why AP-156 did not fix it, which is worth recording because
the null result looked like a failed fix: AP-156 put the object in the right
CELLS; AP-158 is why it is still rejected WITHIN them. Sequential, not
alternative — this issue is the observable proving the second half still bites.

The issue names the one measurement that settles it (the offending Setup's BSP
root-sphere origin offset) and states plainly that no fix should be attempted
first — the `+ 2f` slack is invented, so widening it would be tuning a
non-retail constant rather than removing it.

The user's other report — running off cliff edges instead of stopping — is
already covered by #32 (HIGH, open since 2026-04-29), whose row states
"Local-player edge-slide is unchanged by this work" after its remote half
closed. No new issue filed for it.

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
This commit is contained in:
Erik 2026-08-06 17:07:52 +02:00
parent e6457cc849
commit d4e956b4e2

View file

@ -10554,6 +10554,67 @@ missing is the plugin-API surface.
---
## #334 — Large static formations lose collision at their boundaries (Neftet)
**Status:** OPEN
**Severity:** HIGH — walk-through and fall-through on world geometry.
**Filed:** 2026-08-06, user-reported in live play.
**Component:** physics / collision / broadphase
**User report, verbatim in substance:** *"In Neftet I miss collision on the
large stone formations. I can run up to them, but then at a boundary between
I can run through. I can jump over it but then I just fall through."*
**NOT a regression from the 2026-08-06 collision work.** Confirmed by A/B: the
user reproduced it on a purpose-built client at `52175aa1` — before AP-22,
AP-152, AP-156, AD-10 and #276's remainder — and the behaviour was identical.
It is pre-existing and was simply never filed. AP-156's cell-membership fix
did **not** resolve it either, which is itself a diagnostic clue (see below).
**The signature:** solid on approach, permeable at a boundary *between* two
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
`TransitionTypes.cs:3898`-ish measures `currPos - obj.Position` (the part
**origin**) against `obj.Radius`, admitting a contact only when the geometry
sits within roughly `movement + 2 m` of that origin. Retail has **no distance
pre-filter at all**: `CObjCell::find_obj_collisions` @`0x0052b750` dispatches
unconditionally, its only early-out being `INITIAL_PLACEMENT_INSERT`. The 2 m
slack is acdream invention; retail's own epsilon in this family is 0.0002 m.
**118 of 477 unique BSP GfxObjs exceed that ~2.5 m budget; 46 exceed 5 m.** A
"large stone formation" is precisely the class that would: geometry extending
many metres from its part origin. Near the origin you collide; past the budget
the broadphase rejects the object before its mesh is ever consulted — solid in
the middle, permeable at the edges, no floor overhead. That matches the report
without needing a second mechanism.
This also explains why AP-156 did not help: AP-156 put the object in the right
**cells**; AP-158 is why it is still rejected *within* those cells. AP-156 was
a prerequisite, not a cure — the two are sequential, and this issue is the
observable that proves the second half still bites.
### Second candidate, if the first is disproved
Static-object collision registration at EnvCell seams — the per-cell shadow
list family (#98's architecture, closed `b3ce505`, and #137's door/wall-opening
work, closed 2026-07-08). Both are closed, so this would be a new gap rather
than a regression of either.
### How to settle it
1. Identify the specific Setup/GfxObj of a Neftet formation that reproduces,
and measure its BSP root-sphere origin offset. If it exceeds ~2.5 m, AP-158
is confirmed as the cause and this issue closes with AP-158's fix.
2. If the offset is small, the reach filter is exonerated and the second
candidate takes over.
**Do not attempt a fix before step 1.** The reach filter's `+ 2f` slack has no
retail counterpart, so "widen the budget" would be tuning an invented constant
— the fix is to remove the filter, which needs AP-158's own gate.
## #32 — Retail edge-slide / cliff-slide / precipice-slide incomplete
**Status:** REMOTE HALF CLOSED — fixed `204d0ae0`, **user-passed 2026-08-04**