Formalize Phase L.2 as the active holistic movement/collision program, align the roadmap and architecture docs, file tactical physics follow-ups, and refresh collision memory away from rewrite-from-zero guidance. Co-authored-by: OpenAI Codex <codex@openai.com>
9.1 KiB
Phase L.2 - Movement & Collision Conformance
Status: ACTIVE planning document, created 2026-04-29.
Roadmap owner: Phase L.2 in docs/plans/2026-04-11-roadmap.md.
Scope: player movement prediction, retail collision/transition behavior,
building boundaries, edge and wall sliding, cell ownership, outbound movement
packets, and server-correction diagnostics.
Purpose
Phase B.3 shipped the first usable physics foundation: terrain contact, basic resolver behavior, streaming-populated collision inputs, and enough movement wire support to walk on ACE. That was not the complete retail collision system.
Phase L.2 is the conformance program that turns that foundation into a retail-faithful movement stack. It is the single organizing bucket for work that otherwise looks scattered across B.3 physics, L.1 animation/motion, and G.3 dungeon/portal space.
The active movement spine is:
input + motion command
-> local body prediction / root-motion source
-> PhysicsEngine.ResolveWithTransition
-> TransitionTypes + BSPQuery + ShadowObjectRegistry contact/cell result
-> MoveToState / AutonomousPosition outbound packets
-> server echo or correction diagnostics
Live ACE accepting a position, or the absence of visible rubber-banding, is not proof of retail collision parity. ACE can tolerate coarse or locally invalid fine-grained movement. L.2 therefore requires retail-decomp evidence, synthetic conformance tests, real-DAT fixtures, and live retail-observer checks.
Current Foundation
Already active in acdream:
PhysicsEngine.ResolveWithTransitionis the local player collision path.BSPQuerycontains a partial retail-style BSP dispatcher and step/contact logic.TransitionTypescarriesSpherePath,CollisionInfo,ObjectInfo, transition validation, step-up/down, and partial slide behavior.PhysicsDataCacheloads GfxObj, Setup, and CellStruct physics data from DATs.ShadowObjectRegistrygives the resolver a broadphase over nearby world objects.TerrainSurfaceuses triangle-aware terrain sampling rather than the older bilinear placeholder.
Known incomplete areas:
- Full
CELLARRAYownership andCObjCell::find_cell_list/ adjacent-cell checks are not ported. cell_bsp/CellBSPis not fully represented as a first-class runtime owner.- Building entry/exit and indoor/outdoor portal transit are not solved by the normal walking path.
- Retail
edge_slide,cliff_slide, andprecipice_slidebehavior is incomplete; failed edge/step-down cases often hard-block instead of sliding. NegPolyHithandling is a stub relative to the retail transition dispatch.- Live entities collapse to a simplified cylinder shape; exact retail sphere/cylsphere and object-shape behavior is not yet matched.
- Outbound contact/cell fields can be too optimistic, so server agreement does not necessarily mean local conformance.
Lane Model
L.2 uses five working lanes. The roadmap breaks them into six sub-lanes because real-DAT and live verification spans every lane.
| Lane | Owns | Roadmap slice |
|---|---|---|
| Diagnostics | Truth probes, dump flags, server-correction logging, retail observer harness | L.2a, L.2f |
| Transition parity | FindTransitionalPosition, step-up/down, edge-slide, cliff-slide, precipice-slide, NegPolyHit dispatch |
L.2c |
| Geometry fidelity | CSphere, CCylSphere, object shape extraction, building object collision, walkable polygon context |
L.2d |
| Cell/building ownership | outdoor cell seams, low-cell id updates, CELLARRAY, cell_bsp, building entry/exit |
L.2e |
| Movement/network authority | contact byte, full cell id, MoveToState / AutonomousPosition cadence, root motion vs velocity prediction, correction response | L.2b, L.2f |
Roadmap Slices
L.2a - Truth & Diagnostics
Goal: make every bad movement outcome explainable.
- Add targeted diagnostics for local placement, contact plane, object hit, water, cell id, outbound packet fields, server echo, and correction delta.
- Keep diagnostics opt-in via env vars and devtools panels.
- Record enough data for side-by-side retail-observer runs without drowning normal logs.
- Build real-DAT fixture capture for known walls, building ledges, rooftops, slopes, landblock seams, and dungeon entrances.
L.2b - Movement Wire / Contact Authority
Goal: stop sending movement packets that claim more certainty than the local resolver has earned.
- Fix outbound contact state so
AutonomousPositionandMoveToStatedo not always claim grounded contact. - Track local result cell id and outbound full cell id separately from the last server placement until correction proves they agree.
- Reconcile packet cadence with retail/holtburger references.
- Wire routine server correction handling and diagnostics, not only portal reseating.
L.2c - Transition Parity: Edge / Slide / Neg-Poly
Goal: match retail movement at walls, roof edges, step boundaries, and precipices.
- Port and test
edge_slide,cliff_slide,precipice_slide, andstep_up_slidebehavior from named retail. - Preserve walkable polygon context needed for precipice/edge decisions.
- Replace
NegPolyHitstub behavior with the retail dispatch path. - Confirm the user-visible rule: walk-only motion is blocked by step,
edge, walkable, and collision rules; jumping clears
OnWalkableand only succeeds when the airborne path actually clears geometry.
L.2d - Shape Fidelity: Sphere / CylSphere / Building Objects
Goal: object collisions use retail shape semantics, not one simplified fallback.
- Finish
CSphere/CCylSphereparity for static and live objects. - Stop treating all live entities as one root-centered cylinder.
- Preserve enough building identity to model
CBuildingObjcollision andbldg_checkbehavior. - Audit
Setup.Radiusand cylinder fallback behavior against retail before relying on them for conformance.
L.2e - Cell Ownership: Outdoor Seams, CELLARRAY, cell_bsp
Goal: the resolver knows which cell owns the movement and which adjacent cells must be checked.
- Update low outdoor cell id across 24m cell boundaries and landblock seams.
- Port the retail adjacent-cell search:
find_cell_list,check_other_cells, andadjust_check_pos. - Promote
cell_bsp/CellBSPfrom partial data to active runtime owner. - Hand G.3 a trustworthy building/portal boundary so dungeon streaming is not asked to solve collision ownership after the fact.
L.2f - Real-DAT and Live Retail-Observer Conformance
Goal: prove the stack against real terrain/building/cell data and what a retail client sees when observing acdream.
- Add real-DAT fixtures for representative movement cases.
- Use retail client observer runs to verify motion packets, animation/movement coupling, and server-visible placement.
- Treat ACE acceptance as a coarse compatibility check only.
- Require conformance notes in tests or research docs for every AC-specific algorithm ported under L.2.
Named Retail Anchors
Primary source: docs/research/named-retail/acclient_2013_pseudo_c.txt.
Struct source: docs/research/named-retail/acclient.h.
Address lookup: docs/research/named-retail/symbols.json.
Use these names before falling back to older docs/research/decompiled/
chunks:
CTransition::find_transitional_position-0x0050BDF0CTransition::transitional_insert-0x0050B6F0CTransition::step_up-0x0050B610CTransition::step_down-0x0050B2A0CTransition::edge_slide-0x0050B3D0CTransition::cliff_slide-0x0050A6D0SPHEREPATH::step_up_slide-0x0050C3B0SPHEREPATH::precipice_slide-0x0050CC80SPHEREPATH::adjust_check_pos-0x0050CC00CTransition::adjust_offset-0x0050A370CTransition::check_other_cells-0x0050AE50CPhysicsObj::is_valid_walkable-0x0050F530CObjCell::find_cell_list-0x0052B4E0CBuildingObj::find_building_collisionsCCellStruct::point_in_cellCCellStruct::sphere_intersects_cellCCellStruct::box_intersects_cellCCylSphere::intersects_sphereCSphere::intersects_sphereCSphere::slide_sphere
Implementation Order
- Land L.2a diagnostics first. Do not make another physics change blind.
- Fix L.2b packet/contact truth so logs and server echoes describe reality.
- Port L.2c transition parity in narrow slices with named-retail citations and conformance tests.
- Improve L.2d shape fidelity where transition parity depends on object contact semantics.
- Land L.2e cell/building ownership before G.3 dungeon/portal work relies on indoor/outdoor walking.
- Promote each synthetic case to L.2f real-DAT and live observer coverage.
Acceptance
- A developer can name the active movement path and the current incomplete pieces without reading old chat logs.
dotnet buildanddotnet teststay green for each implementation slice.- Every AC-specific port cites named retail decomp or a documented fallback.
- Real-DAT fixtures cover buildings, walls, roof edges, outdoor seams, and at least one dungeon/building entrance path before L.2 is marked shipped.
- Retail observer view and acdream local view both agree on contact, position, and movement state for the representative cases.