4.2 KiB
Issue #273 — Holtburg tight-gap support validation
Date: 2026-07-31 Status: implementation, automated gates, and exact live gate pass Scope: grounded player step-down support at a floor edge beside a static cylinder
Captured scene
The reproducible gap is in outdoor cell 0xA9B40032, between:
- building shell GfxObj
0x01000F69, placed at(158.178, 37.7055, 94.0)with quaternion(w=.939319, x=0, y=0, z=-.343045); - static post
0xCA9B4027, placed at(160.173, 34.487, 95.975), represented by its Setup-authored cylinder (radius=.282,height=5.564); - the local player Setup's exact two spheres (
radius=.48, originsz=.475andz=1.35).
The building's supporting ledge terminates at local x=4. The first
post-side response moved the player's foot-sphere center to approximately
local x=4.33. The full .48 movement sphere still overlapped the floor, so
the existing step-down path accepted the candidate. Repeated frames then
carried the player around the post and outside the building shell.
The fixture
tests/AcDream.Core.Tests/Fixtures/issue273/0x01000F69.gfxobj.json preserves
the installed DAT PhysicsBSP. The replay in
Issue273HoltburgTightGapReplayTests uses the captured object placement,
player spheres, static posts, and movement offsets.
Retail mechanism
The missing rule is not extra collision padding and is not a larger player sphere. It is retail's second-stage support validation:
CTransition::step_down(0x0050B2A0) performs the ordinary downward collision probe.- After finding a walkable contact plane, an EdgeSlide mover that is not in
StepUp calls
CTransition::check_walkable(0x0050AFF0). The binary sequence istest ah,2at0x0050B36A, which is state bit0x200(EdgeSlide), followed by thestep_up == 0test and call at0x0050B380. CTransition::check_walkablefirst callsSPHEREPATH::check_walkables(0x0050C3E0).SPHEREPATH::check_walkableshalves the saved foot-sphere radius and callsCPolygon::check_walkable(0x00538E60).- If the remembered polygon does not support that smaller sphere,
CTransition::check_walkableperforms a downward CheckWalkable insertion. BSP leaves require bothwalkable_hits_sphereandCPolygon::check_small_walkable(BSPLEAF::hits_walkable,0x0053D670). - If neither check finds support,
CTransition::step_downrejects the candidate and the existing edge-response chain handles it.
ACDream already had the small-radius BSP-leaf test, but
DoCheckWalkable treated the mere presence of a remembered polygon as
success, and the ordinary DoStepDown(..., runPlacement:false) path never
called it. This let a full-radius overlap stand in for actual foot support.
Port
BSPQuery.CheckWalkableSupportis the shared resolved-polygon form of retailCPolygon::check_walkable.SpherePath.CheckWalkablesimplements the retail half-radius remembered polygon check without mutating canonical sphere state.Transition.DoCheckWalkablenow tests the remembered polygon rather than treating a non-null polygon as sufficient.Transition.DoStepDownrestores the EdgeSlide/non-StepUp support gate before the existing placement-policy seam.
There are no location checks, object IDs, guessed radii, widened collision shapes, or gap-specific tolerances in the production fix.
Regression impact
The existing #271 staircase-side replay begins with its center .288 m
outside a tread whose retail half-radius support boundary is .24 m.
Retail may therefore stop that exact candidate. The test now preserves the
original user-visible invariant—never reverse or accelerate downhill—without
requiring forward progress beyond retail's support boundary. The ordinary
continuous staircase replay still requires and achieves forward progress.
Gates
- issue #273 fixture/replay: 3 passed;
- focused BSP, step-up, edge-slide, #185/#271 family: 42 passed / 1 skipped;
- complete Core tests: 4,111 passed / 2 skipped;
- Release solution build: passed;
- complete Release solution tests: 10,068 passed / 5 skipped.
The user accepted the exact in-client Holtburg gap gate on 2026-07-31: the gap blocks from the tested approach, and the adjacent movement checks remain healthy.