docs(#182): crowd-collision investigation outcome + velocity-model rebuild design
The #182 CSphere port (96ae2740) failed its visual gate and introduced an
airborne "stuck in the falling animation" regression. A player-attributed retail
cdb trace (tools/cdb/retail-crowd-jump3.cdb) proved retail's LOCAL client fully
runs player-vs-creature collision (76 land_on_sphere, 188 COLLIDED, 130 SLID,
~78% OK, glides across) -- NOT server-authoritative (an earlier unfiltered
land_on_sphere=0 read was a false lead the attributed trace refuted).
acdream's same-repro capture: 50.9% OK, 22.4% stuck, 115 airborne-stuck. Root
divergence: retail CPhysicsObj::UpdateObjectInternal (0x005156b0, pc:283688) sets
cached_velocity = (resolved - old)/dt -- velocity from ACTUAL movement, so a
blocked jump collapses to ~0 -> gravity -> the player falls/glides. acdream
integrates velocity + reflects on collision (PlayerMovementController ~:1008-1069),
so the jump velocity (~18) persists against the creature -> hang.
Fix = verbatim rebuild of the per-frame player-physics loop (UpdateObjectInternal
chain), velocity model first, transition internals kept. Full design +
retail function inventory + the capture apparatus + retail target numbers:
docs/superpowers/specs/2026-07-07-player-physics-update-verbatim-rebuild-design.md.
Implementation deferred to a fresh session (user decision). Also files #183
(floating distant scenery, observed during testing). #182 stays as the base.
Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
This commit is contained in:
parent
96ae274081
commit
80881ed6f1
5 changed files with 305 additions and 1 deletions
38
tools/cdb/retail-crowd-jump.cdb
Normal file
38
tools/cdb/retail-crowd-jump.cdb
Normal file
|
|
@ -0,0 +1,38 @@
|
|||
.logopen C:\Users\erikn\source\repos\acdream\.claude\worktrees\vigorous-joliot-f0c3ad\retail-crowd-jump.log
|
||||
.sympath C:\Users\erikn\source\repos\acdream\refs
|
||||
.symopt+ 0x40
|
||||
.reload /f acclient.exe
|
||||
|
||||
r $t0 = 0
|
||||
r $t1 = 0
|
||||
r $t2 = 0
|
||||
r $t3 = 0
|
||||
|
||||
.echo === ARMED: land_on_sphere + validate_transition + FindObjCollisions; auto-detach after 25000 SetPositionInternal ===
|
||||
|
||||
* CSphere::land_on_sphere (0x005379a0) — an AIRBORNE mover's foot sphere hit another
|
||||
* sphere (a creature body or a sphere-object). If this fires when you jump onto the
|
||||
* monster pack, the LOCAL client is attempting a creature landing (branch 4 airborne).
|
||||
* Rare -> always gc, never strands.
|
||||
bp acclient!CSphere::land_on_sphere "r $t0 = @$t0 + 1; .printf \"[LAND-ON-SPHERE] #%d\\n\", @$t0; gc"
|
||||
|
||||
* CTransition::validate_transition (0x0050aa70) — the commit/revert. arg2 (at esp+4,
|
||||
* thiscall) is the transitional_insert RESULT fed in: 1=OK 2=COLLIDED 3=ADJUSTED 4=SLID.
|
||||
* Rate-limited so the log stays readable. A burst of arg2=2 (COLLIDED) during the
|
||||
* jump-land = the local transition hit the creature and reverted (server must place you).
|
||||
bp acclient!CTransition::validate_transition "r $t1 = @$t1 + 1; .if (@$t1 % 60 == 0) { .printf \"[VALIDATE] #%d arg2=%d\\n\", @$t1, poi(@esp+4) }; gc"
|
||||
|
||||
* CPhysicsObj::FindObjCollisions (0x0050f050) — count only. Confirms the local player's
|
||||
* transition is testing object collisions at all during the repro.
|
||||
bp acclient!CPhysicsObj::FindObjCollisions "r $t3 = @$t3 + 1; gc"
|
||||
|
||||
* CPhysicsObj::SetPositionInternal — the position commit AND the detach anchor. Fires for
|
||||
* every object's position set (player + creatures), so it always reaches the threshold in
|
||||
* a live crowd. On the 25000th hit it prints the summary and does NOT gc -> cdb breaks ->
|
||||
* g returns -> the top-level qd detaches cleanly. (qd is NEVER inside a bp action.)
|
||||
bp acclient!CPhysicsObj::SetPositionInternal "r $t2 = @$t2 + 1; .if (@$t2 < 25000) { gc } .else { .printf \"[SUMMARY] land_on_sphere=%d validate=%d findObjColl=%d setPos=%d\\n\", @$t0, @$t1, @$t3, @$t2 }"
|
||||
|
||||
g
|
||||
.echo === DETACHING ===
|
||||
qd
|
||||
.logclose
|
||||
28
tools/cdb/retail-crowd-jump2.cdb
Normal file
28
tools/cdb/retail-crowd-jump2.cdb
Normal file
|
|
@ -0,0 +1,28 @@
|
|||
.logopen C:\Users\erikn\source\repos\acdream\.claude\worktrees\vigorous-joliot-f0c3ad\retail-crowd-jump2.log
|
||||
.sympath C:\Users\erikn\source\repos\acdream\refs
|
||||
.symopt+ 0x40
|
||||
.reload /f acclient.exe
|
||||
|
||||
r $t0 = 0
|
||||
r $t1 = 0
|
||||
r $t2 = 0
|
||||
|
||||
.echo === ARMED v2: land_on_sphere + validate(COLLIDED count); AUTO-DETACH after 6000 validate ===
|
||||
|
||||
* CSphere::land_on_sphere (0x005379a0) — an airborne mover's foot sphere hit another
|
||||
* sphere. RARE -> cheap, no meaningful lag. $t1 (validate count) timestamps each hit so we
|
||||
* can read the PATTERN: a brief burst per jump = the local client lands on the creature;
|
||||
* a long steady burst = it's stuck locally (arming every frame) and the SERVER lifts you.
|
||||
bp acclient!CSphere::land_on_sphere "r $t0 = @$t0 + 1; .printf \"[LAND] #%d vt=%d\\n\", @$t0, @$t1; gc"
|
||||
|
||||
* CTransition::validate_transition (0x0050aa70, UNAMBIGUOUS) — the commit/revert, AND the
|
||||
* detach anchor. arg2 (poi esp+4) = the transitional_insert result: 1=OK 2=COLLIDED 4=SLID.
|
||||
* We count COLLIDED and log every 5th so a jump that reverts locally shows a COLLIDED spike.
|
||||
* On the 6000th hit (~15-20 s) it prints the summary and does NOT gc -> cdb breaks -> g
|
||||
* returns -> the top-level qd detaches cleanly. qd is NEVER inside a bp action.
|
||||
bp acclient!CTransition::validate_transition "r $t1 = @$t1 + 1; .if (@$t1 < 6000) { r $t3 = poi(@esp+4); .if (@$t3 == 2) { r $t2 = @$t2 + 1; .if (@$t2 % 5 == 0) { .printf \"[COLLIDED] #%d vt=%d\\n\", @$t2, @$t1 } }; gc } .else { .printf \"[DETACH] validate=%d land_on_sphere=%d collided=%d\\n\", @$t1, @$t0, @$t2 }"
|
||||
|
||||
g
|
||||
.echo === DETACHING ===
|
||||
qd
|
||||
.logclose
|
||||
34
tools/cdb/retail-crowd-jump3.cdb
Normal file
34
tools/cdb/retail-crowd-jump3.cdb
Normal file
|
|
@ -0,0 +1,34 @@
|
|||
.logopen C:\Users\erikn\source\repos\acdream\.claude\worktrees\vigorous-joliot-f0c3ad\retail-crowd-jump3.log
|
||||
.sympath C:\Users\erikn\source\repos\acdream\refs
|
||||
.symopt+ 0x40
|
||||
.reload /f acclient.exe
|
||||
|
||||
r $t9 = 0
|
||||
r $t0 = 0
|
||||
r $t1 = 0
|
||||
r $t2 = 0
|
||||
r $t4 = 0
|
||||
r $t5 = 0
|
||||
|
||||
.echo === ARMED v3 (PLAYER-ATTRIBUTED): capture player ptr from set_local_velocity; filter validate + land_on_sphere to it; auto-detach after 40000 validate ===
|
||||
|
||||
* Capture the LOCAL player's CPhysicsObj* from the first input-driven local-velocity set.
|
||||
* Creatures are dead-reckoned (interpolated), not set via set_local_velocity, so the first
|
||||
* hit after you start moving is the player. Printed so we can sanity-check it's one pointer.
|
||||
bp acclient!CPhysicsObj::set_local_velocity "r $t8 = @ecx; .if (@$t9 == 0) { r $t9 = @$t8; .printf \"[PLAYER-PTR] %p\\n\", @$t9 }; gc"
|
||||
|
||||
* land_on_sphere: mover = arg2->object = poi(poi(esp+4)) (OBJECTINFO.object at offset 0).
|
||||
* Log ONLY when the mover is the player. If this stays 0 while you jump onto monsters, the
|
||||
* local client is NOT computing your creature landing (server places you).
|
||||
bp acclient!CSphere::land_on_sphere "r $t7 = poi(poi(@esp+4)); .if (@$t7 == @$t9) { r $t0 = @$t0 + 1; .printf \"[PLAYER-LAND] #%d vt=%d\\n\", @$t0, @$t1 }; gc"
|
||||
|
||||
* validate_transition: mover = poi(ecx) (CTransition.object_info.object at offset 0). For the
|
||||
* PLAYER only, tally the transition result arg2 (poi esp+4): 2=COLLIDED, 4=SLID, else OK/ADJ.
|
||||
* pCOL/pSLID near 0 during the crowd jump = the player is NOT locally colliding with creatures.
|
||||
* $t1 (ALL validates) is the unambiguous detach anchor -> break at 40000 -> qd.
|
||||
bp acclient!CTransition::validate_transition "r $t1 = @$t1 + 1; .if (@$t1 >= 0n40000) { .printf \"[DETACH] pPtr=%p pValidate=%d pCOLLIDED=%d pSLID=%d pLand=%d\\n\", @$t9, @$t2, @$t4, @$t5, @$t0 } .else { .if (poi(@ecx) == @$t9) { r $t2 = @$t2 + 1; r $t3 = poi(@esp+4); .if (@$t3 == 2) { r $t4 = @$t4 + 1 } .else { .if (@$t3 == 4) { r $t5 = @$t5 + 1 } } }; gc }"
|
||||
|
||||
g
|
||||
.echo === DETACHING ===
|
||||
qd
|
||||
.logclose
|
||||
Loading…
Add table
Add a link
Reference in a new issue