90 lines
3.6 KiB
Markdown
90 lines
3.6 KiB
Markdown
# Prepared indoor transit regression
|
|
|
|
**Date:** 2026-07-26
|
|
**Scope:** Slice-I prepared collision consumer correction
|
|
**Behavioral boundary:** No collision formula, portal rule, or renderer
|
|
behavior changed. This restores the existing retail traversal over the
|
|
production flat representation.
|
|
|
|
## Symptom and connected evidence
|
|
|
|
After the Slice-I parsed-graph removal, entering houses or dungeons could:
|
|
|
|
- collide with empty space at a doorway or room boundary;
|
|
- retain the wrong indoor cell on stairs or upper floors;
|
|
- expose the world background through the interior portal view.
|
|
|
|
The connected capture at
|
|
`.test-out/indoor-visibility-20260726-220007/stdout.log` placed the player in
|
|
Holtburg cottage vestibule `0xA9B40150`, with the chase-camera eye outside the
|
|
doorway in outdoor landcell `0xA9B40029`. The original DAT graph advanced the
|
|
camera transition from `0xA9B40150` to `0xA9B40029`. The prepared production
|
|
path retained `0xA9B40150`, causing collision and portal rendering to share
|
|
the same wrong viewer-cell root.
|
|
|
|
## Retail oracle
|
|
|
|
Named retail:
|
|
|
|
- `CEnvCell::find_transit_cells @ 0x0052C820`
|
|
- `CObjCell::find_cell_list`
|
|
- `CEnvCell::find_visible_child_cell`
|
|
|
|
Consolidated pseudocode:
|
|
[`acclient_indoor_transitions_pseudocode.md`](acclient_indoor_transitions_pseudocode.md).
|
|
|
|
For each `CCellPortal`, retail reads that portal's polygon plane from the
|
|
owning `CCellStruct`. An exterior portal admits outdoor cells when any path
|
|
sphere straddles the plane. An interior portal tests the loaded neighbor's
|
|
cell-containment BSP, using the plane only as an unloaded-cell hint.
|
|
|
|
## Root cause
|
|
|
|
The prepared package was complete:
|
|
|
|
- `FlatEnvCellTopology.Portals[i].PolygonIndex` retained the direct portal
|
|
polygon index;
|
|
- `FlatCellStructureCollisionAsset.PortalPolygons` retained the exact plane;
|
|
- prepared containment and physics BSPs matched the original DAT graph.
|
|
|
|
`CellTransit.FindTransitCellsSphere`, however, still began with:
|
|
|
|
```text
|
|
if currentCell.PortalPolygons is null: return
|
|
```
|
|
|
|
`PortalPolygons` is the old parsed-DAT dictionary and is intentionally null in
|
|
production after Slice I7. Therefore every prepared indoor cell skipped its
|
|
entire portal loop. The I4/I5 differential referee covered BSP queries and
|
|
complete resolver results, but did not exercise portal-plane lookup after the
|
|
parsed graph had been removed, allowing the representation-boundary defect to
|
|
escape.
|
|
|
|
## Correction
|
|
|
|
`CellTransit` now resolves the exact same portal plane from:
|
|
|
|
1. the parsed dictionary in explicit graph-oracle fixtures; or
|
|
2. the prepared topology's direct polygon index and flat polygon table in
|
|
production.
|
|
|
|
Prepared topology/list mismatches and invalid polygon indices fail loudly as
|
|
corrupt publication rather than silently disabling indoor traversal. Portal
|
|
iteration order, comparisons, sphere transforms, neighbor containment, and
|
|
outside admission remain unchanged.
|
|
|
|
## Automated evidence
|
|
|
|
- Synthetic prepared exterior-portal test with no parsed polygon dictionary.
|
|
- Synthetic prepared loaded-neighbor test with no parsed containment tree.
|
|
- Exact connected Holtburg cottage camera path:
|
|
graph and prepared paths both end in `0xA9B40029` at identical position.
|
|
- Installed-DAT graph/flat coverage expanded across the Holtburg cottage and
|
|
inn vestibules, connectors, stairwell, upper floor, and inn shell.
|
|
- Physics-focused Release tests: 1,778 passed / 1 skipped.
|
|
- Interaction/projection focused App tests: 127 passed.
|
|
- Client-object ordering tests: 82 passed.
|
|
- Complete Release build: passed with zero warnings.
|
|
|
|
No divergence-register row is required: the correction removes an accidental
|
|
production divergence and introduces no replacement behavior.
|