#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:
parent
2eca7f5033
commit
b94a7e8017
1 changed files with 39 additions and 0 deletions
|
|
@ -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;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue