# Collision System Port — Status and Plan ## Current State (2026-04-14) The collision system has been patched multiple times but does NOT match retail. The user has explicitly requested a **full faithful port** of the retail collision system — no shortcuts, no simplifications. ## What Went Wrong Instead of porting the decompiled code line-by-line (as CLAUDE.md mandates), I wrote simplified approximations: - Static overlap instead of swept-sphere FindTimeOfCollision - Custom FindObjCollisions instead of porting Sphere.IntersectsSphere - Custom BSP query instead of porting BSPTree.find_collisions dispatcher - Ad-hoc push-out instead of proper SlideSphere crease-projection - Incremental patches that don't address root architectural issues Each patch fixed one symptom but introduced new edge cases. The result is a patchwork that handles ~60-70% of cases but fails on the rest. ## What Must Happen Next **Delete the existing collision code and start fresh.** Port from ACE's complete C# implementation, cross-referencing the decompiled code for ground truth. ACE has the ENTIRE system already in C#: ### Files to port from ACE (in order): 1. **Sphere.cs** — `IntersectsSphere` (FUN_005387c0), `SlideSphere` (both variants), `StepSphereUp`, `StepSphereDown`, `LandOnSphere`, `CollideWithPoint`, `CollidesWithSphere` 2. **BSPTree.cs** — `find_collisions` (6-path dispatcher) 3. **BSPNode.cs** — `sphere_intersects_poly` (tree traversal with movement), `find_walkable`, `hits_walkable`, `sphere_intersects_solid` 4. **BSPLeaf.cs** — leaf-level polygon tests 5. **Polygon.cs** — `pos_hits_sphere`, `adjust_sphere_to_plane`, `check_walkable` 6. **Transition.cs** — `FindTransitionalPosition`, `TransitionalInsert`, `StepUp`, `StepDown`, `ValidateTransition`, `AdjustOffset` 7. **SpherePath.cs** — `SetCheckPos`, `AddOffsetToCheckPos`, `CacheLocalSpaceSphere`, `SetCollide`, `SetWalkable`, `SetNegPolyHit` 8. **CollisionInfo.cs** — `SetContactPlane`, `SetSlidingNormal`, `SetCollisionNormal` 9. **ObjectInfo.cs** — `ValidateWalkable` 10. **LandCell.cs** — `FindEnvCollisions` (outdoor terrain) 11. **EnvCell.cs** — `FindEnvCollisions` (indoor BSP) 12. **ObjCell.cs** — `FindObjCollisions`, `find_cell_list` ### ACE source locations: - `references/ACE/Source/ACE.Server/Physics/Sphere.cs` - `references/ACE/Source/ACE.Server/Physics/BSP/BSPTree.cs` - `references/ACE/Source/ACE.Server/Physics/BSP/BSPNode.cs` - `references/ACE/Source/ACE.Server/Physics/BSP/BSPLeaf.cs` - `references/ACE/Source/ACE.Server/Physics/Polygon.cs` - `references/ACE/Source/ACE.Server/Physics/Transition.cs` - `references/ACE/Source/ACE.Server/Physics/SpherePath.cs` - `references/ACE/Source/ACE.Server/Physics/Collision/CollisionInfo.cs` - `references/ACE/Source/ACE.Server/Physics/Collision/ObjectInfo.cs` ### Decompiled ground truth (named-retail is now primary, 2026-04-25): - **`docs/research/named-retail/acclient_2013_pseudo_c.txt`** — grep for `BSPTree::`, `BSPNode::`, `BSPLeaf::`, `CPolygon::`, `CCylSphere::`, `Transition::`, `CPhysicsObj::`, `SpherePath::` to find named bodies. - **`docs/research/named-retail/acclient.h`** — verbatim retail struct layouts for the BSP / Sphere / Transition types. - **`docs/research/named-retail/symbols.json`** — name↔address lookup. - `docs/research/decompiled/chunk_00530000.c` — older Ghidra fallback for BSP / Polygon / Sphere collision (FUN_xxx names). - `docs/research/decompiled/chunk_00500000.c` — older Ghidra fallback for PhysicsObj / transition callers. - `docs/research/acclient_function_map.md` — hand-curated cross-port index (ACE / ACME mappings + struct-offset notes). ### Pseudocode (already written): - `docs/research/transition_pseudocode.md` — full system documented ## What to Keep - `CollisionPrimitives.cs` — 9 low-level functions already faithfully ported from decompiled code. These are CORRECT and match retail. - `PhysicsDataCache.cs` — GfxObj/Setup/CellStruct physics data loading from dats. Correct. - `ShadowObjectRegistry.cs` — cell-based spatial index. Correct concept, may need refinement. - `TransitionTypes.cs` data structures — SpherePath, CollisionInfo, ObjectInfo, PhysicsGlobals. Mostly correct, may need field additions. - `PhysicsBody.cs` — Euler integration. Correct. - `MotionInterpreter.cs` — Motion state machine. Correct. - `PlayerWeenie.cs` — Run/Jump formulas. Correct. ## What to Replace - `BSPQuery.cs` — replace with faithful port of BSPTree/BSPNode/BSPLeaf - `TransitionTypes.cs` Transition methods — replace FindTransitionalPosition, TransitionalInsert, FindEnvCollisions, FindObjCollisions, SlideSphere, AdjustOffset with faithful ports - `PhysicsEngine.ResolveWithTransition` — may need restructuring ## Approach (MANDATORY — per CLAUDE.md) For EVERY function: 1. **GREP NAMED FIRST, then DECOMPILE FALLBACK.** Search the named retail decomp first: `grep -n "ClassName::Method" docs/research/named-retail/acclient_2013_pseudo_c.txt`. For struct layouts: `grep -n "^struct ClassName" docs/research/named-retail/acclient.h`. Only if the named pseudo-C lacks a function (rare), fall back to the older `docs/research/decompiled/` chunks via the function map at `docs/research/acclient_function_map.md`. 2. **CROSS-REFERENCE ACE.** Read ACE's C# port of the same function. ACE provides naming and structure. Note any differences. 3. **WRITE PSEUDOCODE.** Translate the decompiled C into readable pseudocode BEFORE porting to C#. Add to `docs/research/collision_port_pseudocode.md`. 4. **PORT FAITHFULLY.** Translate pseudocode to C# line-by-line. Same variable names, same control flow, same boundary conditions. Do NOT "improve" or "simplify" the algorithm. 5. **VERIFY.** When ACE and the decompiled code disagree, the decompiled code wins. Document the difference. ### Execution order: 1. Sphere collision (Sphere.cs) — FUN_005387c0 and sub-functions 2. BSP tree (BSPTree/Node/Leaf) — find_collisions dispatcher 3. Polygon tests (Polygon.cs) — pos_hits_sphere, adjust_sphere_to_plane 4. Transition orchestrator (Transition.cs) — FindTransitionalPosition 5. Cell collision (LandCell/EnvCell/ObjCell) — FindEnvCollisions, FindObjCollisions 6. Wire into PhysicsEngine.ResolveWithTransition 7. Test: terrain → indoor walls → objects → step-up → every object type