4 KiB
Issue #269 — slope-stop capture and retail correction
Date: 2026-07-31
Status: implemented; user live gate passed
Scope: landing-bounce follow-up, CTransition::validate_transition
Symptom
After the retail 5%-elasticity landing reflection was restored for #265, the character could retain too much downhill speed after landing on a walkable slope. The user described the residual as “slides too far on landing.”
ACDream live capture
ACDREAM_CAPTURE_PLAYER_QUANTA=<jsonl-path> records the local player's
complete admitted object quantum without changing simulation order:
- quantum start;
- root/PositionManager composition;
- pre- and post-
UpdatePhysicsInternal; - transition result;
- final collision-response commit.
The accepted repro contained 2,184 quanta. The clearest landing was:
| Quantum | Event | Velocity |
|---|---|---|
| 1740 | final airborne quantum | (-12.316, 8.187, -26.266) |
| 1741 | slope collision, normal (-0.236, 0.236, 0.943) |
|
| 1741 post-response | correct 5% reflect | (-17.391, 13.262, -6.576) |
| 1742–1758 | still Contact + OnWalkable, no new collision normal | velocity unchanged |
| 1759+ | contact relationship changes | friction finally begins decaying |
The reflected velocity had dot(v, normal) = +1.0252: it pointed away
from the slope. Retail calc_friction correctly skips while this value is
at least 0.25, so friction was not the defect. ACDream was repeatedly
restoring the remembered slope plane and re-grounding the body without
performing retail's accompanying velocity stop.
Retail oracle
Named-retail:
CPhysicsObj::check_contact0x0050F5B0CPhysicsObj::get_object_info0x00511CC0CTransition::validate_transition0x0050AA70OBJECTINFO::kill_velocity0x0050CFE0
The exact validate_transition order at
0x0050AAED–0x0050AB42 is:
- enter only for a non-OK collision/adjusted/slid result;
- if
last_known_contact_plane_valid, callOBJECTINFO::kill_velocity; - test the current sphere center against the remembered plane using
radius + 0.0002; - restore the contact plane only when still within that distance;
- later, at
0x0050ACFF, overwrite last-known validity with final contact-plane validity.
OBJECTINFO::kill_velocity calls
CPhysicsObj::set_velocity({0,0,0}, 0). ACDream had ported the proximity
test and plane restore but omitted this call. It also allowed the
last-known plane to re-ground clean accepted moves, although retail only
consumes it in the non-OK recovery branch.
Correction
Transition.ValidateTransition now:
- calls
ObjectInfo.StopVelocity()before the remembered-plane proximity/restore test on a non-OK recovery; - performs that restore only in the retail branch;
- overwrites last-known validity from final contact validity, so a clean move away cannot be re-grounded from stale memory.
The existing PhysicsEngine.ResolveWithTransition consumption of
VelocityKilled applies the zero to the canonical PhysicsBody before
the collision-response tail. The initial 5% landing reflection remains;
only a following collision recovery performs the retail stop.
Gates
- New focused pins:
- collision recovery with a remembered plane kills velocity;
- clean advance with a remembered plane neither kills nor re-grounds.
- Full
AcDream.Core.Tests: 4,107 passed / 2 skipped. - Full
AcDream.Runtime.Tests: 439 passed. AcDream.AppRelease build: 0 warnings / 0 errors.- Complete Release suite: 10,061 passed / 5 skipped / 0 failed.
- User live gate: PASS — repeated slope jumps now settle correctly (“Perfect! Works great!”).
Diagnostic tools retained
tools/analyze_269_slope_stop_capture.pytools/cdb/run-issue269-slope-stop.ps1tools/cdb/issue269-slope-stop.cdb
The cdb runner refuses to attach unless the live retail executable matches the Sept 2013 named PDB. The locally installed 2015 retail executable does not match; the static named-retail decode above is therefore the retail oracle used for this correction.