fix(phys): A6.P3 slice 4 — reset WalkInterp before placement_insert (issue #98)

Hypothesis-driven fix for issue #98 (cellar ascent stuck at top step).

Symptom (from polydump trace at scen4_cottage_cellar_polydump):
- Player walks up cellar ramp (real 46-degree slope per dat verification)
- Hits ramp polygon 0x0008 in cellar cell 0xA9B40147 270 times
- Each hit: sphere center lifted 0.75m onto ramp surface, all walk_interp
  consumed (winterp 1.0 -> 0.0)
- Step_up_slide fires 159+ times trying to recover
- Player physically stuck — never advances forward

Bug hypothesis: in DoStepDown, after the primary TransitionalInsert(5)
probe consumes WalkInterp down to 0 (the 0.75m lift), the placement_insert
call runs with WalkInterp=0. AdjustSphereToPlane's interp check
(`interp >= path.WalkInterp` where interp=0) then rejects any push-back
needed for the placement validation -> placement fails -> step_up returns
failure -> step_up_slide loop -> player stuck.

Fix: reset WalkInterp = 1.0 before the placement_insert call (mirrors
retail step_down's walk_interp = 1 reset at function entry, which is what
the placement_insert runs after in retail's flow).

Test suite: 1148 + 8 (baseline maintained).
Visual verification: pending user re-test of cellar-up walk.

If this fixes cellar-up, also likely improves other step-up-onto-slope
scenarios. If it doesn't fix cellar-up, the bug is elsewhere in the
step-up/step-down flow (separate investigation needed).

Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
This commit is contained in:
Erik 2026-05-22 13:07:06 +02:00
parent 8bd311759e
commit bbd1df46e0

View file

@ -2498,8 +2498,29 @@ public sealed class Transition
return true;
// Placement validation: can we actually stand here?
//
// A6.P3 slice 4 (2026-05-22) — reset WalkInterp to 1.0 before
// the placement_insert. The prior TransitionalInsert(5) probe
// above may have consumed WalkInterp down to 0 (e.g. on a
// step-up onto a sloped ramp — AdjustSphereToPlane lifted the
// sphere by step_down_amt and ate all the interp). With
// WalkInterp=0, subsequent AdjustSphereToPlane calls' `interp
// >= path.WalkInterp` check fires immediately (0 >= 0) and
// rejects any push-back — so any geometric overlap that needs
// push-out resolution returns false → placement fails → step-up
// returns failure → step_up_slide loop → player stuck.
//
// Retail's CTransition::step_down (acclient_2013_pseudo_c.txt:272952)
// resets walk_interp = 1 at function entry. The placement_insert
// (line 272989-272990) runs after that initial reset; we believe
// placement-insert mode doesn't consume walk_interp the same way
// because it's a "can we fit here" check, not a movement sweep.
//
// This fix is the cellar-up target (issue #98). May also help
// other "step-up onto sloped surface" scenarios.
var savedInsert = sp.InsertType;
sp.InsertType = InsertType.Placement;
sp.WalkInterp = 1.0f;
var placeState = TransitionalInsert(1, engine);