fix #270: run retail spawn placement at remote-body creation - standing monsters' attack animations restored

The [MT-FAIL] probe caught combat-stance monsters constantly failing to
dispatch 0x40000015 (Falling): their bodies were airborne-flagged while
standing. contact_allows_move (0x00528dd0) requires Contact+OnWalkable
and silently refuses every action animation for an airborne mover - a
spawned-standing monster's swings never played until it first moved.

Retail never has this state: CreateObject spawns run the placement
transition (CPhysicsObj::SetPosition -> SetPositionInternal 0x00515330),
which establishes CONTACT/ON_WALKABLE from the floor at spawn. Our
remote creation seeded a raw position with no placement.

SeedRemoteSpawnPlacement mirrors RemoteTeleportPlacement: engine
placement resolve (Setup-derived cylinder, TS-46) + the verbatim
CommitSetPositionTransition, wired at BOTH RemoteMotion creation sites
(UM-triggered creation - so a first-ever-UM attack animates in the same
packet - and ordinary first-UP creation). Unplaceable results leave the
body airborne exactly like a failed retail placement.

Also adds the [UM-ACT] (wire action items + stamp-gate verdict) and
[MT-FAIL] (refused animation dispatches) probes, riding
ACDREAM_DUMP_MOTION=1, which are what convicted the body state.

Complete Release suite: 10,032 passed / 5 skips / 0 failures.

Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
This commit is contained in:
Erik 2026-07-30 23:28:57 +02:00
parent 1390add140
commit 4da25a442b
4 changed files with 257 additions and 17 deletions

View file

@ -118,23 +118,26 @@ when the exhausted state (stamina == 0) transitions; skills/burden/stamina
still reach `PlayerWeenie` immediately (the next natural dispatch picks up
rate changes, exactly retail).
**Monster attack misses — narrowed by the 2026-07-30 retest session
(182k-line motion dump, 272 attack UMs):** the edge-drain theory is
ACQUITTED (zero [remote-edge] lines — no remote ground edges fired at
all), and the legacy stop-detector is dead code (the observation tracker
has no reader). All 272 attack UMs dispatched (`SetCycle 0x400000D3`);
171 completed visibly; 3 were killed by a Ready UM arriving almost
immediately after the swing began. Residual hypothesis: our remote UM
path HARD-SWAPS cycles on SetCycle, while retail transitions between
cycles through the motion table's LINK animations — a quick
Ready-after-attack in retail still plays the swing's follow-through via
the attack→ready link chain; ours truncates it. Next step: audit the
remote dispatch path (RemoteInboundMotionDispatch → sequencer) for link
transitions vs hard SetCycle, against retail's unpack →
apply_current_movement → motion-table link graph. User confirms casting
is FIXED; attack animations are "still a bit buggy" (occasional misses,
consistent with the ~1% fast-replace rate plus link-less truncation
visibility).
**Monster attack misses — ROOT CAUSE FOUND AND FIXED (2026-07-30, third
session):** the [MT-FAIL] probe caught combat-stance monsters constantly
failing to dispatch motion 0x40000015 = FALLING — their bodies were
airborne-FLAGGED while standing on the ground. `contact_allows_move`
(0x00528dd0) requires Contact+OnWalkable on the body and silently refuses
every action animation for an "airborne" mover — a spawned-standing
monster's attack swings never played until it first moved (movement →
resolve → floor touch → contact). Retail never has this state: CreateObject
spawns run the placement transition (`CPhysicsObj::SetPosition`
SetPositionInternal 0x00515330), which establishes contact at spawn; our
remote creation seeded a raw position with no placement. Fix:
`SeedRemoteSpawnPlacement` runs the engine placement resolve + the
verbatim `CommitSetPositionTransition` at BOTH RemoteMotion creation sites
(UM-triggered and first-UP), mirroring `RemoteTeleportPlacement`. Earlier
theories eliminated en route: remote edge-drains (zero edges fired), the
legacy stop-detector (dead code), cycle hard-swap (the funnel uses the full
motion-table link machinery), 0x00D3 misread (= CastSpell, casters animate
fine), motion-table port (offline sweep: all 27 "failures" are non-caster
tables never sent CastSpell). Probes [UM-ACT]/[MT-FAIL]/[remote-edge]
remain in place (ride ACDREAM_DUMP_MOTION=1) until the user gate passes.
---
## #269 — Slope-stop slide runs too far (post-bounce-rework residual)