fix(physics): #89 — sphere-overlap in CheckBuildingTransit closes login-inside-inn classification race
Outdoor→indoor entry path used PointInsideCellBsp (point-only) for the building-portal containment test. When the player logs in INSIDE a building and the foot-sphere center is just past the destination cell's CellBSP boundary, the point-only check failed → CellId stuck as outdoor → indoor BSP queries never ran → walls passable. User-reported symptom: "logged in in the inn, at start ran through exterior walls, ran back in and they block now." Fix: swap PointInsideCellBsp for SphereIntersectsCellBsp (the radius- aware port from #90). Promotes CellId to the interior cell the moment ANY part of the foot-sphere crosses the destination cell boundary — matches retail's CCellStruct::sphere_intersects_cell timing at acclient_2013_pseudo_c.txt:317666 exactly. The sphereRadius parameter was already plumbed through CheckBuildingTransit per #89's documented "future upgrade" note from 2026-05-19 (which is exactly today's symptom). Closes #89. 1147 + 8 baseline maintained. Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
This commit is contained in:
parent
c0d84057cb
commit
7ac8f544a7
1 changed files with 22 additions and 19 deletions
|
|
@ -155,25 +155,19 @@ public static class CellTransit
|
|||
/// <c>BuildingObj::find_building_transit_cells</c> +
|
||||
/// <c>EnvCell::check_building_transit</c>. For each portal of the
|
||||
/// outdoor building, look up the destination interior cell and test
|
||||
/// whether the sphere center is inside it via
|
||||
/// <see cref="BSPQuery.PointInsideCellBsp"/>. If so, add the interior
|
||||
/// cell to <paramref name="candidates"/>.
|
||||
/// whether the sphere overlaps it via
|
||||
/// <see cref="BSPQuery.SphereIntersectsCellBsp"/>. If so, add the
|
||||
/// interior cell to <paramref name="candidates"/>.
|
||||
///
|
||||
/// <para>
|
||||
/// <b>Retail divergence:</b> retail's <c>check_building_transit</c>
|
||||
/// uses <c>CCellStruct::sphere_intersects_cell</c> (radius-aware
|
||||
/// BSP-vs-sphere test) which fires the moment ANY part of the sphere
|
||||
/// overlaps the destination cell. Our port uses
|
||||
/// <see cref="BSPQuery.PointInsideCellBsp"/> (radius-less, tests only
|
||||
/// the sphere CENTER). Practical effect: entry into a building fires
|
||||
/// when the player's foot-sphere center crosses the destination cell
|
||||
/// boundary — roughly <paramref name="sphereRadius"/> (~0.48m) DEEPER
|
||||
/// into the doorway than retail. If visual verification at the cottage
|
||||
/// door shows a noticeable "late entry" effect (player visually inside
|
||||
/// the building before walls switch from outdoor-stab to indoor-cell),
|
||||
/// port <c>sphere_intersects_cell</c> in a follow-up.
|
||||
/// <paramref name="sphereRadius"/> is plumbed through for that future
|
||||
/// upgrade; currently unused.
|
||||
/// Issue #89 closed (2026-05-20): uses retail's radius-aware
|
||||
/// <c>CCellStruct::sphere_intersects_cell</c>
|
||||
/// (<c>acclient_2013_pseudo_c.txt:317666</c>) ported as
|
||||
/// <see cref="BSPQuery.SphereIntersectsCellBsp"/>. Promotes CellId to
|
||||
/// the interior cell the moment ANY part of the foot-sphere crosses
|
||||
/// the cell boundary — matches retail entry timing exactly and
|
||||
/// closes the login-inside-inn classification race where the player
|
||||
/// would briefly be classified outdoor and walk through walls.
|
||||
/// </para>
|
||||
/// </summary>
|
||||
public static void CheckBuildingTransit(
|
||||
|
|
@ -198,13 +192,22 @@ public static class CellTransit
|
|||
}
|
||||
|
||||
// Sphere center in the OTHER cell's local space.
|
||||
// Issue #89 closed (2026-05-20): use radius-aware sphere-overlap
|
||||
// (matches retail's CCellStruct::sphere_intersects_cell at
|
||||
// acclient_2013_pseudo_c.txt:317666) instead of point-only. This
|
||||
// promotes the player's CellId to the interior cell the moment
|
||||
// ANY part of the foot-sphere crosses the cell boundary — the
|
||||
// entry-side counterpart to issue #90's sticky-stay fix. Without
|
||||
// it, login-inside-the-inn keeps the player classified outdoor
|
||||
// until they walk further in (sphere center crosses), letting
|
||||
// them run through exterior walls on the way out.
|
||||
var localCenter = Vector3.Transform(worldSphereCenter, otherCell.InverseWorldTransform);
|
||||
bool inside = BSPQuery.PointInsideCellBsp(otherCell.CellBSP.Root, localCenter);
|
||||
bool inside = BSPQuery.SphereIntersectsCellBsp(otherCell.CellBSP.Root, localCenter, sphereRadius);
|
||||
|
||||
if (PhysicsDiagnostics.ProbeIndoorBspEnabled)
|
||||
{
|
||||
Console.WriteLine(System.FormattableString.Invariant(
|
||||
$"[check-bldg] portal->0x{portal.OtherCellId:X8} wpos=({worldSphereCenter.X:F3},{worldSphereCenter.Y:F3},{worldSphereCenter.Z:F3}) lpos=({localCenter.X:F3},{localCenter.Y:F3},{localCenter.Z:F3}) inside={inside}"));
|
||||
$"[check-bldg] portal->0x{portal.OtherCellId:X8} wpos=({worldSphereCenter.X:F3},{worldSphereCenter.Y:F3},{worldSphereCenter.Z:F3}) lpos=({localCenter.X:F3},{localCenter.Y:F3},{localCenter.Z:F3}) r={sphereRadius:F3} inside={inside}"));
|
||||
}
|
||||
|
||||
if (inside)
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue