Live gate passed. ISSUES #185 moved to DONE with the corrected root cause (registration overflow, not the collision response). The handoff's convex-edge theory and design-v1's grounding-retention theory are both recorded as superseded. Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
This commit is contained in:
parent
07c5b832cf
commit
5a9df00aa9
1 changed files with 33 additions and 44 deletions
|
|
@ -46,56 +46,45 @@ Copy this block when adding a new issue:
|
|||
|
||||
---
|
||||
|
||||
## #185 — LOCAL player jams half-way up outdoor stairs (house on stilts); a jump clears it
|
||||
## #185 — [DONE 2026-07-08 · `07c5b832`] LOCAL player jams half-way up outdoor stairs (house on stilts); a jump clears it
|
||||
|
||||
**Status:** OPEN (investigated, root cause characterised — NOT yet fixed; a fix touches the frozen collision internals → brainstorm gate first)
|
||||
**Severity:** MEDIUM
|
||||
**Filed:** 2026-07-08
|
||||
**Component:** physics / collision (building/stair BSP + step-up vs slide classification)
|
||||
**Status:** DONE (live gate PASSED — "OK works"). Root cause was NOT the collision response.
|
||||
**Severity:** MEDIUM · **Filed:** 2026-07-08 · **Component:** physics / collision-registration (landblock shadow objects)
|
||||
|
||||
**Description:** Running the LOCAL player up the outside stairs of a house-on-stilts, you hit
|
||||
an invisible block **half-way up** that you cannot walk through — you shuffle sideways but
|
||||
never advance. **Jumping clears it** and you continue up normally. Pre-existing (observed
|
||||
before the #184 work); unrelated to the remote de-overlap thread. Building object
|
||||
`0xf6822103`, landblock `0xf682`, jam at world ≈ (132, 77.8, 61.4), cell `0xF682002C`.
|
||||
**Description:** Running up the outside stairs of a house-on-stilts you hit an invisible wall
|
||||
"in the middle of the stairs" (steps look unbroken) — you shuffle sideways, never advance; a
|
||||
jump clears it. Landblock `0xf682`, jam ≈ world (132, 77.9, 61.5), cell `0xF682002C`.
|
||||
|
||||
**Root cause / status (from `ACDREAM_CAPTURE_RESOLVE` at the jam):** The staircase is a
|
||||
fairly uniform ~0.4 m-rise / **38.7°** flight of tilted tread faces (`n=(0,-0.62,0.78)`),
|
||||
which is under the ~49° walkable cutoff, so the player *glides* straight up it (long
|
||||
no-collision stretches; the wireframe shows discrete stacked step faces). At **one junction
|
||||
(~Z 61.4)** there is an anomalous **~52° face** (`collisionNormal=(0,0.78,0.62)`, constant
|
||||
across every stuck frame → a real stable face, NOT the #137 synthetic-negated-run-direction
|
||||
normal). 52° is just past the walkable cutoff, so the sweep treats it as a **wall**: it
|
||||
**flattens that normal to a pure-horizontal `(0,1,0)` sliding normal** (Z zeroed) and slides
|
||||
the player sideways in X, pinning Y+Z — instead of recognising it as a normal ~0.4 m **step**
|
||||
and stepping the player up onto the next tread. The jump clears it because the jump's +Z
|
||||
velocity is not in the horizontal `(0,1,0)` slide plane. The staircase continues climbable
|
||||
above the jam (more 38.7° treads → a flat porch at Z 63.6) — so it is ONE localised spot,
|
||||
not a general stair failure. Classic **#137 / building-collision-mesh junction-anomaly family**
|
||||
(TS-4 sliding-normal-provenance), stair edition.
|
||||
**Root cause (REAL — a uint32 overflow in the shadow-registry part-id, `07c5b832`):**
|
||||
`GameWindow.cs` registered each landblock BSP part with a synthetic id `entity.Id * 256u +
|
||||
partIndex`. That `<< 8` **overflows uint32** for class-prefixed landblock ids
|
||||
(`0x40`/`0x80`/`0xC0`…) and drops the prefix byte, so different-class entities sharing the low
|
||||
24 bits **collide on one shadow part-id**; `Register`'s deregister-then-insert silently
|
||||
overwrites one entity's collision (`0xF6822100 ← {0x40F68221, 0xC0F68221}` — 23 such collisions
|
||||
in landblock `0xF682` alone). Three mid-staircase steps therefore **rendered but had NO
|
||||
collision**; the player floats into the hole and the (retail-faithful) `PrecipiceSlide` wedge
|
||||
fires at the walkable edge = the "invisible wall." **The wedge was a symptom, not the cause.**
|
||||
The two earlier theories in this session — the handoff's "convex-tread-edge synthetic normal"
|
||||
and design-v1's "grounding-retention at a coplanar seam" — were both SUPERSEDED by the live
|
||||
`[entity-source]`/`[bsp-test]` capture (#3) that mapped the collision hole + the 23 id
|
||||
collisions.
|
||||
|
||||
**RESOLVED (artifact, not geometry) — `ACDREAM_PROBE_BUILDING=1` hit-poly capture:** at the
|
||||
jam, ALL 156 building collisions are ONE polygon — a real, walkable **38.7° tread quad**
|
||||
(`gfxObj=0x01000AC5`, `obj=0xF6822103`, `partIdx=3`, local plane `(-0.625,0,0.781)`; world
|
||||
verts X 131.25–132.75, Y 77.00–77.50, Z 60.62–61.01). **There is NO riser / wall polygon in
|
||||
the collision mesh at all.** The 52° "wall" normal from the resolve capture (`(0,0.78,0.62)`)
|
||||
is that tread normal **rotated exactly 90°** (perpendicular; dot ≈ 0) — it does not exist in
|
||||
the dat. So the block is a **synthetic sliding normal fabricated by our collision RESPONSE**,
|
||||
not real geometry and not a step-height/budget issue: the foot sphere straddles a convex tread
|
||||
edge (near a building-part seam — `partIdx=3`, neighbouring `gfxObj=0x01000ACA` present), hits
|
||||
the lower tread poly, and the slide/validate chain invents a perpendicular normal, flattens it
|
||||
to horizontal `(0,1,0)`, and slides the player sideways. **Confirmed #137 / TS-4
|
||||
sliding-normal-provenance family** (phantom wall at a convex edge/seam), stair edition. Fix
|
||||
lives in that family (where the perpendicular normal is fabricated / how a convex walkable
|
||||
tread edge is handled) — touches the frozen collision internals → brainstorm gate first.
|
||||
**Fix (Option A, retail-faithful):** register each multi-part landblock entity via
|
||||
`ShadowObjectRegistry.RegisterMultiPart` under its **unique 32-bit `entity.Id`** (retail
|
||||
`CPhysicsObj::add_shadows_to_cells` → `CPartArray::AddPartsShadow` — one object, a part array;
|
||||
no synthetic per-part id). New builder `ShadowShapeBuilder.FromLandblockBspParts`. Setup
|
||||
cyl/sphere path unchanged (runs only when `entityBsp==0`, retail BSP-xor-cyl). Despawn is
|
||||
landblock-scoped so the id change is safe. Does NOT touch the frozen collision internals.
|
||||
|
||||
**Files:** `src/AcDream.Core/Physics/TransitionTypes.cs` (step-up / slide classification, the
|
||||
sliding-normal horizontalisation); building-collision mesh generation (BSP faces for
|
||||
landblock stabs). Capture apparatus: `ACDREAM_CAPTURE_RESOLVE`.
|
||||
**Files:** `src/AcDream.Core/Physics/ShadowShapeBuilder.cs` (`FromLandblockBspParts`),
|
||||
`src/AcDream.App/Rendering/GameWindow.cs` (~7898 registration block).
|
||||
**Tests:** `ShadowRegistrationOverflowTests` (overflow arithmetic; old scheme drops one;
|
||||
`RegisterMultiPart` keeps both; builder), `Issue185OutdoorStairsSeamReplayTests` (dat-free
|
||||
clean-climb pin). Core 2629 / App 741 green. Design: `docs/superpowers/specs/2026-07-08-185-outdoor-stairs-fix-design.md` (v2).
|
||||
|
||||
**Acceptance:** the LOCAL player walks up the full outdoor staircase of the house-on-stilts
|
||||
without jumping; no sideways-slide pin at the ~Z 61.4 junction; regression pass on other
|
||||
stairs/ramps (indoor + outdoor) — no new phantom blocks.
|
||||
**Fallout note:** shared registration path → this was silently dropping collision on OTHER
|
||||
landblock objects too (23 id collisions in one landblock); likely fixed a class of
|
||||
"walked-through-a-thing-that's-clearly-there" bugs, not just these stairs.
|
||||
|
||||
---
|
||||
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue