#126: outdoor restore grounds onto elevated walkables, not through them

A zero-delta RESTORE of an outdoor claim standing far above terrain
(logged out on a building roof deck - the AAB3 tower 0x010A slab at
z=127.2 over terrain 112) was grounded to TERRAIN unconditionally,
warping the player through the roof into the building interior,
outdoor-classified -> the transparent-interior spawn the user hit on
every login while the save sat on the roof. Retail restores settle via
AdjustPosition onto real surfaces, not the heightmap.

Fix: the snap outdoor branch, zero-delta shape only, when the claim z
exceeds terrain by more than step height: ground to the nearest CELL
WALKABLE at/below the claim z (the #111 WalkableFloorZNearest query -
real floors only, never the ceiling soup), keeping the outdoor cell id
(honest: a deck-stander center sits above the slab cell BSP - the same
state the user played in all afternoon). GfxObj-shell roofs without
cells not covered - file if a real case shows.

Suites: App 242+1skip, Core 1422+2skip, UI 420, Net 294.

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
This commit is contained in:
Erik 2026-06-11 20:02:48 +02:00
parent 2eca7f5033
commit b94a7e8017

View file

@ -787,6 +787,45 @@ public sealed class PhysicsEngine
// Stay outdoors on terrain.
targetZ = terrainZ;
targetCellId = physics.Terrain.ComputeOutdoorCellId(localCandX, localCandY);
// #126 (2026-06-11): a zero-delta RESTORE of an OUTDOOR claim
// standing far ABOVE terrain means the player logged out on a
// walkable surface that is not the ground — a building roof
// deck (the AAB3 tower's 0x010A slab, z=127.2 over terrain
// 112). Grounding to terrain warps the player THROUGH the
// roof into the building's interior volume, outdoor-classified
// → the transparent-interior spawn. Retail's restore settles
// via AdjustPosition onto real surfaces, not the heightmap.
// Ground to the nearest CELL WALKABLE at/below the claim Z
// (the #111 walkable query — real floors only, never ceiling
// soup); the cell id stays OUTDOOR (the claim is honest: the
// player's center on a deck sits above the slab cell's BSP).
// GfxObj-shell roofs without cells are not covered — file if
// a real case shows.
if (snapDiag && currentPos.Z > terrainZ + stepUpHeight)
{
float? bestWalkZ = null;
float bestWalkDist = float.MaxValue;
foreach (var cell in physics.Cells)
{
float? wz = WalkableFloorZNearest(
lbPrefix | (cell.CellId & 0xFFFFu), candidatePos, currentPos.Z);
if (wz is null) continue;
if (wz.Value > currentPos.Z + stepUpHeight) continue; // above the claim — not the surface stood on
float dist = MathF.Abs(wz.Value - currentPos.Z);
if (dist < bestWalkDist)
{
bestWalkDist = dist;
bestWalkZ = wz;
}
}
if (bestWalkZ is not null && bestWalkZ.Value > terrainZ)
{
Console.WriteLine(System.FormattableString.Invariant(
$"[snap] OUTDOOR claim 0x{cellId:X8} at z={currentPos.Z:F3} stands on an elevated walkable z={bestWalkZ.Value:F3} (terrain {terrainZ:F3}) — grounding to the walkable, not through it"));
targetZ = bestWalkZ.Value;
}
}
}
}