fix(physics): port retail slope landing stop
This commit is contained in:
parent
1d8371dbe5
commit
5a0f9868a6
13 changed files with 870 additions and 103 deletions
104
docs/research/2026-07-31-269-slope-stop-capture.md
Normal file
104
docs/research/2026-07-31-269-slope-stop-capture.md
Normal file
|
|
@ -0,0 +1,104 @@
|
|||
# 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:
|
||||
|
||||
1. quantum start;
|
||||
2. root/PositionManager composition;
|
||||
3. pre- and post-`UpdatePhysicsInternal`;
|
||||
4. transition result;
|
||||
5. 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_contact` `0x0050F5B0`
|
||||
- `CPhysicsObj::get_object_info` `0x00511CC0`
|
||||
- `CTransition::validate_transition` `0x0050AA70`
|
||||
- `OBJECTINFO::kill_velocity` `0x0050CFE0`
|
||||
|
||||
The exact `validate_transition` order at
|
||||
`0x0050AAED–0x0050AB42` is:
|
||||
|
||||
1. enter only for a non-OK collision/adjusted/slid result;
|
||||
2. if `last_known_contact_plane_valid`, call
|
||||
`OBJECTINFO::kill_velocity`;
|
||||
3. test the current sphere center against the remembered plane using
|
||||
`radius + 0.0002`;
|
||||
4. restore the contact plane only when still within that distance;
|
||||
5. 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.App` Release 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.py`
|
||||
- `tools/cdb/run-issue269-slope-stop.ps1`
|
||||
- `tools/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.
|
||||
Loading…
Add table
Add a link
Reference in a new issue