feat(render) Campaign FW1: look-in adjudication - the GetVisible load gate

The per-building join diagnostic PASSES (001a/0022 portal tables lead
exactly to the traced a9b4016x punch cells; every BSP PortalRef indexes
validly), and the eight-arm gate-decode sweep proves NO plane-sign x
side-flag combination reproduces retail. Together they pin the missing
mechanism: CEnvCell::GetVisible gates punches by the LOADED interior
cell set around the player - retail punched only the two buildings
nearest the player cell; the replay loads every interior so geometry
alone over-punches. Next port piece: the interior load radius (the
landcell stab-list pull). Both diagnostics stay in the suite (the sweep
Skip-parked with the verdict).

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
This commit is contained in:
Erik 2026-08-30 10:43:27 +02:00
parent faba9be635
commit e5cdd2364e
3 changed files with 207 additions and 1 deletions

View file

@ -137,7 +137,7 @@ public static class WalkWorldDatAdapter
BuildingPortal portal = buildingInfo.Portals[i];
portals[i] = new WalkBldPortal
{
PortalSide = ((ushort)portal.Flags & 0x2) != 0 ? 1 : 0,
PortalSide = DecodeBuildingSide((ushort)portal.Flags),
ExactMatch = ((ushort)portal.Flags & 0x1) != 0,
OtherCellId = portal.OtherCellId == 0xFFFF
? 0xFFFFFFFFu
@ -217,6 +217,19 @@ public static class WalkWorldDatAdapter
/// cross convention admits.</summary>
public static bool FlipGfxPolygonPlanes;
/// <summary>Adjudication toggle: the BuildingPortal side-flag decode.
/// 0 = (Flags &amp; 0x2), 1 = inverted 0x2, 2 = (Flags &amp; 0x1),
/// 3 = inverted 0x1.</summary>
public static int BuildingSideMode;
private static int DecodeBuildingSide(ushort flags) => BuildingSideMode switch
{
0 => (flags & 0x2) != 0 ? 1 : 0,
1 => (flags & 0x2) != 0 ? 0 : 1,
2 => (flags & 0x1) != 0 ? 1 : 0,
_ => (flags & 0x1) != 0 ? 0 : 1,
};
private static WalkPolygon? BuildGfxPolygon(GfxObj gfxObj, ushort polygonId)
{
if (!gfxObj.Polygons.TryGetValue(polygonId, out Polygon? poly)