T6 (BR-7) C4: straddle-only outside-add (A6.P5 widening DELETED) + #90 stickiness removed
The two remaining flagged workarounds retired, per the BR-7 plan +
the WF1 [MEDIUM] correction (re-gate, do NOT delete the outside-add):
1. A6.P5 hasExitPortal topology widening DELETED. Outdoor cells enter the
collision cell array ONLY on the retail straddle gate - |dist| <
radius + F_EPSILON against an exterior portal plane
(CEnvCell::find_transit_cells Ghidra 0x0052c820, gate 0052c9d6,
live-binary verified) - the same flag that already gated the
membership pick (#112 rider). The widening existed so outdoor-
registered doors stayed findable from indoor cells under the old flat
registry query; with per-cell shadow lists the door is found in the
straddle-admitted outdoor cell's own list (tick-13558 pin holds).
The hasExitPortal out-param + plumbing deleted from
FindTransitCellsSphere; the AddAllOutsideCells call in
BuildCellSetAndPickContaining re-gated on exitOutsideStraddle
(once-per-walk = retail CELLARRAY.added_outside).
2. #90 ResolveCellId sphere-overlap stickiness REMOVED (the 4ca3596
workaround, deferred-to-A6.P4 in the physics digest). It was dead
code: the method's only caller is FindEnvCollisions' cache-null TEST
fallback, and the indoor branch (where the stickiness lived) required
a non-null DataCache. Production membership flows exclusively through
the collide-then-pick advance whose ordered-array hysteresis (current
cell at index 0, interior-wins-break) is the retail mechanism the
workaround approximated. ResolveCellId reduced to the bare
prefix-preserving outdoor re-derive, documented test-only.
Test updates (pins of the deleted behaviors inverted to retail):
- A6P5_BuildCellSetFromIndoorStart_ReachesDoorOutdoorCell (asserted the
topology widening verbatim) -> DeepInteriorSphere_NoStraddle_
AddsNoOutdoorCells: a deep-interior sphere admits NO outdoor cells.
- A6P5_BuildCellSetFromAlcove... -> AlcoveSphere_StraddlesExitPortal_
ReachesDoorOutdoorCell (the captured alcove position genuinely
straddles - the retail-positive half).
- Issue112MembershipTests straddle pin + the second-sphere straddle test
updated to the single-flag signature.
Suites: Core 1416/0/2, App 225, UI 420, Net 294 - green.
Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
This commit is contained in:
parent
dbfbf8506c
commit
ca4b482f8b
5 changed files with 101 additions and 205 deletions
|
|
@ -58,20 +58,6 @@ public static class CellTransit
|
|||
float sphereRadius,
|
||||
ICollection<uint> candidates,
|
||||
out bool exitOutside)
|
||||
=> FindTransitCellsSphere(
|
||||
cache, currentCell, currentCellId, worldSphereCenter, sphereRadius,
|
||||
candidates, out exitOutside, out _);
|
||||
|
||||
/// <inheritdoc cref="FindTransitCellsSphere(PhysicsDataCache, CellPhysics, uint, IReadOnlyList{Sphere}, int, ICollection{uint}, out bool, out bool)"/>
|
||||
public static void FindTransitCellsSphere(
|
||||
PhysicsDataCache cache,
|
||||
CellPhysics currentCell,
|
||||
uint currentCellId,
|
||||
Vector3 worldSphereCenter,
|
||||
float sphereRadius,
|
||||
ICollection<uint> candidates,
|
||||
out bool exitOutside,
|
||||
out bool hasExitPortal)
|
||||
{
|
||||
var spheres = new[]
|
||||
{
|
||||
|
|
@ -84,7 +70,7 @@ public static class CellTransit
|
|||
|
||||
FindTransitCellsSphere(
|
||||
cache, currentCell, currentCellId,
|
||||
spheres, spheres.Length, candidates, out exitOutside, out hasExitPortal);
|
||||
spheres, spheres.Length, candidates, out exitOutside);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
|
|
@ -98,12 +84,9 @@ public static class CellTransit
|
|||
/// This is the only condition under which retail's
|
||||
/// <c>CEnvCell::find_transit_cells</c> calls <c>add_all_outside_cells</c>
|
||||
/// (acclient.exe 0052c8e5-0052c92d straddle test, 0052c9d2-0052c9f0 gate;
|
||||
/// pseudo-C :310070-310120). Drives the membership pick's outdoor branch.</param>
|
||||
/// <param name="hasExitPortal">Topology-only: this cell has at least one
|
||||
/// exterior (0xFFFF) portal, regardless of sphere position. NOT retail —
|
||||
/// kept for the A6.P5 collision cell-set widening (outdoor-registered door
|
||||
/// entities must stay findable from indoor cells until the A6.P4 per-cell
|
||||
/// shadow architecture ships; see the exterior-portal branch comment).</param>
|
||||
/// pseudo-C :310070-310120). Drives the membership pick's outdoor branch
|
||||
/// AND (BR-7 C4, retail-faithfully) the collision cell-set outside-add —
|
||||
/// the former <c>hasExitPortal</c> topology widening is deleted.</param>
|
||||
public static void FindTransitCellsSphere(
|
||||
PhysicsDataCache cache,
|
||||
CellPhysics currentCell,
|
||||
|
|
@ -111,11 +94,9 @@ public static class CellTransit
|
|||
IReadOnlyList<Sphere> worldSpheres,
|
||||
int numSpheres,
|
||||
ICollection<uint> candidates,
|
||||
out bool exitOutside,
|
||||
out bool hasExitPortal)
|
||||
out bool exitOutside)
|
||||
{
|
||||
exitOutside = false;
|
||||
hasExitPortal = false;
|
||||
|
||||
uint lbPrefix = currentCellId & 0xFFFF0000u;
|
||||
int sphereCount = EffectiveSphereCount(worldSpheres, numSpheres);
|
||||
|
|
@ -129,8 +110,6 @@ public static class CellTransit
|
|||
|
||||
if (portal.OtherCellId == 0xFFFF)
|
||||
{
|
||||
hasExitPortal = true;
|
||||
|
||||
// #112 rider (2026-06-10): retail straddle gate, RESTORED and
|
||||
// verified against the LIVE 2013 binary (cdb attach, function
|
||||
// 0052c820; x87 decode at 0052c8e5-0052c92d):
|
||||
|
|
@ -144,19 +123,17 @@ public static class CellTransit
|
|||
// portal_side / exact_match in this branch — BN's pseudo-C
|
||||
// invented those (feedback_bn_decomp_field_names).
|
||||
//
|
||||
// History: this gate existed pre-A6.P5 and was removed
|
||||
// 2026-05-25 citing the CALLER (find_cell_list :308775-:308785
|
||||
// walks every array cell unconditionally — true, but each
|
||||
// callee still applies its own straddle gate). The A6.P5
|
||||
// symptom it fixed (outdoor-registered cottage DOORS invisible
|
||||
// to collision from indoor cells) is really the missing
|
||||
// per-cell shadow_object_list (#99/A6.P4): retail finds those
|
||||
// doors via shadow lists, not via outdoor transit cells. Until
|
||||
// A6.P4 ships, BuildCellSetAndPickContaining keeps widening the
|
||||
// COLLISION cell set on hasExitPortal — but the membership PICK
|
||||
// gates its outdoor branch on this retail flag, which is what
|
||||
// keeps deep-interior containment gaps on curr_cell (retail
|
||||
// keep-curr) instead of demoting to outdoor (#112).
|
||||
// History: this gate existed pre-A6.P5, was removed 2026-05-25
|
||||
// citing the CALLER (find_cell_list :308775-:308785 walks every
|
||||
// array cell unconditionally — true, but each callee still
|
||||
// applies its own straddle gate), and was restored for the
|
||||
// membership PICK by the #112 rider. BR-7 / A6.P4 C4
|
||||
// (2026-06-11) finished the story: the per-cell shadow
|
||||
// architecture made the A6.P5 hasExitPortal topology widening
|
||||
// unnecessary (doors are found in the straddle-admitted outdoor
|
||||
// cell's own list), so this flag now gates BOTH the pick's
|
||||
// outdoor branch AND the collision cell-set outside-add —
|
||||
// pure retail.
|
||||
if (!exitOutside)
|
||||
{
|
||||
for (int i = 0; i < sphereCount; i++)
|
||||
|
|
@ -540,7 +517,7 @@ public static class CellTransit
|
|||
|
||||
FindTransitCellsSphere(
|
||||
cache, cell, cellId, worldSpheres, sphereCount,
|
||||
candidates, out bool exitStraddle, out _);
|
||||
candidates, out bool exitStraddle);
|
||||
|
||||
if (exitStraddle && !outdoorAdded)
|
||||
{
|
||||
|
|
@ -787,7 +764,7 @@ public static class CellTransit
|
|||
|
||||
FindTransitCellsSphere(
|
||||
cache, cell, cellId, worldSpheres, sphereCount,
|
||||
candidates, out bool exitOutsideStraddle, out bool hasExitPortal);
|
||||
candidates, out bool exitOutsideStraddle);
|
||||
|
||||
// #112 rider (2026-06-10): the retail straddle flag (live-binary
|
||||
// verified — see FindTransitCellsSphere) gates the PICK's outdoor
|
||||
|
|
@ -795,16 +772,21 @@ public static class CellTransit
|
|||
// when a path sphere straddles an exterior portal plane.
|
||||
outdoorPickAllowed |= exitOutsideStraddle;
|
||||
|
||||
// A6.P5 (kept, NARROWED to the collision cell SET): the first
|
||||
// exit-portal cell triggers the outdoor neighbourhood add once, by
|
||||
// TOPOLOGY — wider than retail. This keeps outdoor-registered door
|
||||
// entities findable from indoor cells (the 2026-05-25 door capture)
|
||||
// until #99/A6.P4 ships per-cell shadow lists; the pick no longer
|
||||
// consumes these cells unless the retail flag fired, so membership
|
||||
// matches retail in both regimes. Appended AFTER the interior cells,
|
||||
// matching retail order (add_all_outside_cells at the end,
|
||||
// pseudo_c:310120) — interior-wins is preserved.
|
||||
if (hasExitPortal && !outdoorAdded)
|
||||
// BR-7 / A6.P4 C4 (2026-06-11): outdoor cells enter the array
|
||||
// on the retail STRADDLE gate — |dist| < radius + F_EPSILON
|
||||
// against an exterior portal plane (CEnvCell::find_transit_cells
|
||||
// 0x0052c820; gate at 0052c9d6) — replacing the A6.P5
|
||||
// hasExitPortal TOPOLOGY widening. The widening existed to keep
|
||||
// outdoor-registered doors findable from indoor cells under the
|
||||
// old flat query; with per-cell shadow lists the door is found
|
||||
// in the straddle-admitted outdoor cell's OWN list (and the
|
||||
// straddle fires whenever a sphere is genuinely at the
|
||||
// threshold — the tick-13558 door pin proves the admission).
|
||||
// Appended AFTER the interior cells, matching retail order
|
||||
// (add_all_outside_cells at the end, pseudo_c:310120) —
|
||||
// interior-wins is preserved. Once-per-walk via outdoorAdded =
|
||||
// retail CELLARRAY.added_outside (0x00533630).
|
||||
if (exitOutsideStraddle && !outdoorAdded)
|
||||
{
|
||||
AddAllOutsideCells(worldSpheres, sphereCount, currentCellId, blockOrigin, candidates);
|
||||
outdoorAdded = true;
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue