fix(phys): #106 — outdoor membership crosses landblock boundaries (LandDefs global-lcoord port)
The player's outdoor cell froze at the last in-block cell the moment they
walked over a landblock boundary (10,449-frame playerCell freeze in the
2026-06-09 capture; whole neighbouring-block interiors unenterable, plus
the running-distortion from the stale render anchor). Root cause: the
add_all_outside_cells port clamped BOTH the candidate proposal and the
find_cell_list containing-cell pick to the current landblock's 8x8 grid,
in a frame that silently assumed the current block sits at world origin.
One step over the line -> zero candidates -> FindCellSet returns
currentCellId forever.
Retail has no such clamp. Its cell math runs in a GLOBAL landcell grid
(lcoord 0..2039 spanning the map): get_outside_lcoord = blockid_to_lcoord
+ floor(blockLocalPos/24) with no bounds besides the map edge, and
lcoord_to_gid re-derives the landblock id from the lcoord's upper bits —
crossings are inherent, never special-cased.
The fix, decomp-cited throughout:
- New AcDream.Core.Physics.LandDefs: in_bounds (pc:68509),
blockid_to_lcoord (pc:68520), inbound_valid_cellid (pc:163438),
gid_to_lcoord (pc:163500), lcoord_to_gid (pc:171859),
get_outside_lcoord (pc:438690), adjust_to_outside (pc:438719).
Cross-checked against ACE LandDefs.cs; three artifacts documented and
avoided: BN's int8_t mis-render of block_y, BN's dropped 192f
BlockLength constant, and ACE add_cell_block's "FIXME!" same-block
guard (an ACE divergence, not retail).
- CellTransit.AddAllOutsideCells rewritten as the faithful sphere
variant (pc:317499 @0x00533630): adjust_to_outside re-seats the
(cell, position) pair cross-block, check_add_cell_boundary (pc:317229)
adds up to 3 neighbours by global lcoord, add_outside_cell (pc:317056)
has no same-block filter. adjust_to_outside failure breaks the sphere
loop (pc:533699 verbatim).
- BuildCellSetAndPickContaining: the outdoor containing-cell pick is now
the global XY-column under the sphere centre (AdjustToOutside), not
the [0,8)-clamped current-prefix reconstruction. Interior-wins order
and current-cell-first hysteresis unchanged.
- World->block-local frame conversion via the landblock origin already
registered in CellGraph (new TryGetTerrainOrigin); Zero fallback
preserves the legacy anchor-block assumption for unregistered terrain.
- Cross-landblock building entry comes free: the candidate snapshot now
contains neighbour-block landcells, so GetBuilding/CheckBuildingTransit
fire for cottages across the line (the capture's one failing entry).
Investigated FIRST per the pickup brief: the b3ce505 #98 stopgap gate is
definitively exonerated — it is a collision-object query gate that fires
only for indoor primary cells; no membership path touches
ShadowObjectRegistry.
Tests: 31 new (25 LandDefs conformance incl. capture-geometry goldens
0xA9B40031 -> 0xA9B30038/0xA9B30034 and the northbound return; 4
AddAllOutsideCells cross-block; 3 FindCellSet membership goldens incl.
the non-anchor-frame origin conversion). Full suite: 294+218+420 green;
Core 1369 green + the 4 pre-existing door/#99-era failures + 1 skip
(unchanged from baseline).
Pseudocode + artifact notes:
docs/research/2026-06-09-landdefs-outside-cells-pseudocode.md.
Remaining acceptance: live boundary walk with ACDREAM_PROBE_CELL=1
(ISSUES.md #106).
Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
This commit is contained in:
parent
12fb408972
commit
7078264291
11 changed files with 813 additions and 88 deletions
|
|
@ -46,11 +46,26 @@ Copy this block when adding a new issue:
|
|||
|
||||
## #106 — Outdoor player-cell membership FREEZES at landblock boundaries (whole interiors unenterable)
|
||||
|
||||
**Status:** OPEN
|
||||
**Status:** FIX LANDED 2026-06-09 — pending live boundary-walk gate (acceptance below)
|
||||
**Severity:** HIGH
|
||||
**Filed:** 2026-06-09
|
||||
**Component:** physics, membership
|
||||
|
||||
**Fix (2026-06-09):** retail `LandDefs` global-lcoord math ported as
|
||||
`AcDream.Core.Physics.LandDefs` (`blockid_to_lcoord` / `gid_to_lcoord` /
|
||||
`lcoord_to_gid` / `get_outside_lcoord` / `adjust_to_outside`, decomp-cited);
|
||||
`CellTransit.AddAllOutsideCells` rewritten as the faithful sphere-variant
|
||||
(pc:317499) — candidates and the `find_cell_list` pick now run in the GLOBAL
|
||||
landcell grid, so landblock crossings are inherent (the pre-fix port clamped
|
||||
both to the current block's 8×8 grid → zero candidates one step over the line →
|
||||
frozen). World→block-local conversion via the landblock origin registered in
|
||||
`CellGraph` (`TryGetTerrainOrigin`). The `b3ce505` gate was investigated FIRST
|
||||
and definitively exonerated (collision-only, fires only for indoor primaries —
|
||||
no membership path touches it). 31 new conformance tests incl. the capture
|
||||
geometry goldens (0xA9B40031 → 0xA9B30038/0xA9B30034) and a non-anchor-frame
|
||||
northbound return. Pseudocode + decomp-artifact notes:
|
||||
`docs/research/2026-06-09-landdefs-outside-cells-pseudocode.md`.
|
||||
|
||||
**Description:** Walking outdoors across a landblock boundary does NOT update the player's
|
||||
outdoor cell: `playerCell` stays pinned to the last cell of the previous landblock,
|
||||
indefinitely. Every downstream consumer degrades: entering any building in the new landblock
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue