fix #182: port CSphere collision family — retail-faithful crowd wiggle (retires TS-45)

Humanoid creatures/players collide as body Spheres (ShadowShapeBuilder emits
Sphere-type shadows for a Setup with Spheres + no CylSpheres), so player-vs-monster
crowd contact ran through Transition.SphereCollision — a hand-rolled 3-D wall-slide
(register TS-45), NOT a port of retail CSphere::intersects_sphere. It shaved no eps,
force-pushed each contact RADIALLY to a fixed combinedR+1cm shell, ignored the head
sphere, and always returned Slid. In a crowd the opposing radial de-penetration
pushes from neighbours fight each other -> the player wedges and can't wiggle free
(the user's live report).

Port the full CSphere family verbatim — dispatcher 0x00537A80 + step_sphere_up /
slide_sphere / land_on_sphere / collide_with_point / step_sphere_down — the direct
analog of the 2026-07-05 CCylSphere port (#172). The grounded slide now routes
through the shared crease SlideSphere (0x00537440, #116-Ghidra-confirmed) ->
tangential shuffle along the contact toward gaps, retail-faithful. isCreature
(target creature/missile) gates OFF the stand-on/land-on branches (2 & 5). ACE
Sphere.cs = readable oracle; pseudocode doc 2026-07-07-csphere-collision-family.

Retail-faithfulness verified: CTransition::validate_transition (0x0050aa70:272593)
reverts curr_pos on any non-clean-OK step, so a deep-mutual-overlap start wedges in
retail too — the realistic crowd-edge graze slides free (SphereCollisionFamilyTests
slide-around trajectory: player grazes a creature's SW, curves around its west side,
continues N).

TS-45 retired, AP-84 added (PerfectClip TOI dead in M1.5). Core 2603/0, App 741/0.
Pending user visual gate.

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
This commit is contained in:
Erik 2026-07-07 11:25:56 +02:00
parent 0cbe1102d9
commit 96ae274081
6 changed files with 908 additions and 85 deletions

View file

@ -46,6 +46,50 @@ Copy this block when adding a new issue:
---
## #182 — Player wedges in a packed monster crowd, can't wiggle free (hand-rolled SphereCollision)
**Status:** DONE (fix landed; pending user visual gate)
**Severity:** MEDIUM
**Filed:** 2026-07-07
**Component:** physics / collision
**Description:** In a large group of monsters packed around the player it was too
easy to get stuck — the player couldn't shuffle/slide out. Retail leaves room to
wiggle free.
**Root cause:** humanoid creatures/players collide as body **Spheres**
(`ShadowShapeBuilder.FromSetup` emits `ShadowCollisionType.Sphere` for a Setup with
Spheres + no CylSpheres), so the crowd contact ran through `Transition.SphereCollision`
— a hand-rolled 3-D wall-slide (register **TS-45**), NOT a port of retail
`CSphere::intersects_sphere`. It shaved no ε, force-pushed each contact **radially**
to a fixed `combinedR + 1 cm` shell, ignored the head sphere, always returned Slid,
and leaked `SetSlidingNormal`. In a crowd the opposing radial de-penetration pushes
from neighbours fight each other → wedge (the "until an oblique input clears it" feel
TS-45 predicted).
**Fix:** ported the full `CSphere::intersects_sphere` family verbatim (dispatcher
0x00537A80 + `step_sphere_up`/`slide_sphere`/`land_on_sphere`/`collide_with_point`/
`step_sphere_down`), the direct analog of the 2026-07-05 CCylSphere port (#172). The
grounded slide now routes through the shared crease `SlideSphere` (0x00537440) →
tangential shuffle along the contact toward gaps, retail-faithful. TS-45 retired,
AP-84 added (PerfectClip TOI dead in M1.5). Verified retail-faithful: retail's
`validate_transition` (0x0050aa70) reverts `curr_pos` on any non-clean-OK step, so a
deep-mutual-overlap start wedges in retail too — the realistic crowd-edge graze
slides free.
**Files:** `src/AcDream.Core/Physics/TransitionTypes.cs` (`SphereCollision` + the
six new `Sphere*` siblings + `FindSphereTimeOfCollision`; caller at
`FindObjCollisionsInCell` threads `isCreature`).
**Research:** `docs/research/2026-07-07-csphere-collision-family-pseudocode.md`.
**Acceptance:** user shuffles free of a spawned monster pack the same way retail does.
Conformance: `SphereCollisionFamilyTests` (slide-around trajectory, head-on block,
ethereal passable) + `ShadowShapeBuilderShapeSourceTests` (body-spheres → Sphere-type).
Core 2603/0, App 741/0.
---
## #181 — Facility Hub flicker at pressed camera (residual after the full 2026-07-06 fix ladder) — PARKED
**⏸️ PARKED 2026-07-06 (user decision after the static-curve gate: "flickering is still