diff --git a/memory/project_session_2026_04_18.md b/memory/project_session_2026_04_18.md index 1303ccd..1ed7c61 100644 --- a/memory/project_session_2026_04_18.md +++ b/memory/project_session_2026_04_18.md @@ -12,6 +12,110 @@ User went AFK with direction: - Reminder: when connecting to the live ACE server, must log out of the previous session first; server is always up. +## Delta: 30+ commits on main, 470 → 684 tests (+214), continuing + +**Status at the time of this update**: continuing the session. The earlier +wire-layer push (E.1-H.2 + AppraiseInfoParser) is stable. The evening +was dominated by a remote-player animation bug investigation + deep-dive +agent dispatch. + +## Investigation chain + +User reported: "other players don't render properly now. Wrong clothes, +just look like they are lagging forward with run animation. And when +they stop, their running animation is still on." + +Iterated on the diagnosis: + +1. **First guess (wrong)**: today's AnimationSequencer rewrite caused + it. User tested a d910d57 worktree baseline and confirmed "No its + basically the same" — pre-existing bug, not a regression. +2. **Parser dump revealed**: the UpdateMotion parser had a 2-byte + offset error in its MovementData header skip. ACE's `Align()` + pads based on **absolute stream length** (15 → 16, pad 1 byte, + header total 6 bytes), not relative-to-block (which would pad 3 = + header 8). The old parser assumed 8 → every subsequent field + shifted by 2 → stance + command decoded as the packed-flags dword. +3. **Handler rewrite**: OnLiveMotionUpdated now uses SetCycle directly + instead of GetIdleCycle (which ignored command when stance==0); + preserves current style/motion with "no-change" semantics; full + MotionCommand reconstruction from 16-bit wire values. +4. **ACE source confirmed**: Player_Tick.cs:368 — "the client will + never send a 'client released forward' MoveToState in this + scenario unfortunately. because of this, it's better to have the + 'client blip forward' bug without it." → Server never broadcasts + explicit Ready. Observer must infer stopped from position deltas. + +Then dispatched two Opus-4.7 parallel agents with high-effort research ++ implementation mandates per user direction ("ultrathink", "super +high effort"): + +## Agent A — retail animation overhaul (MERGED to main) + +10 commits on worktree-agent-ae8eec87, +32 tests (628→660 before my +orthogonal adds). Shipped: + +- **MultiplyCyclicFramerate** on AnimationSequencer — mid-cycle speed + change without restart. Fixes "animation speed doesn't scale with run + rate" for both the local player and remote observers. +- **Dead-reckoning** per remote entity: EMA-smoothed velocity from + consecutive UpdatePosition deltas, per-tick integration using the + sequencer's current velocity rotated by entity orientation, clamp + radius to prevent runaway on lost updates. Fixes "lagging forward" + — remote chars now move smoothly between position updates. +- **Commands[] list parsing** — the InterpretedMotionState tail list + (MotionItem records) was completely unparsed. NPCs transmit waves, + attacks, death throes via this list. Now routed through PlayAction + (for Actions/Modifiers/Emotes) or SetCycle (SubStates). +- **MotionCommandResolver** — reflects the DatReaderWriter.Enums.MotionCommand + enum to reconstruct the full 32-bit command value from the 16-bit + wire field. Prior ad-hoc OR of 0x40000000 sometimes produced + invalid commands. +- **Sequence-wide Velocity/Omega** — was per-node via lookup, broke + during link transitions (cycle's velocity wasn't surfaced while a + link played). Now matches ACE Sequence.Velocity (last-added-wins, + retained across link/cycle boundary). +- **Omega integration to entity rotation** — TurnRight/TurnLeft cycles + now smoothly rotate the entity each tick between server updates. +- **Soft-snap residual** — server UpdatePosition is authoritative but + blended over ~300ms so corrections don't look like teleports. +- **Stop detection hardening** — 300ms position-stale + velocity-dead + double signal; dedup on respawn clears stale dead-reckon state. + +### Deferred by Agent A + +- PosFrames root motion drain (most AC locomotion uses MotionData.Velocity) +- Full MotionState struct port (Modifier list, Action queue, substateMod) +- AttackHook → combat damage frame sink +- ReplaceObjectHook → weapon draw mesh swap +- Stance transition double-link chain (HandCombat → SwordCombat multi-link) + +## Agent B — sky / weather / lighting (in progress) + +Still running. When it completes, will ship: +- SkyRenderer with retail GfxObj-based sky objects (not a textured sphere) +- WeatherRenderer (rain/snow/fog via existing ParticleSystem) +- Dynamic-lighting shader UBO (8-light UBO per R13 §12.3) +- Torch/fireplace/spell-aura LightSource registration via SetLightHook + +## Additional orthogonal work this session (merged on main) + +- **UpdateMotion parser fix** — 6-byte header (not 8). Committed + before agent dispatch. +- **GameWindow stop detection** — 400ms position-stale → Ready (later + superseded by Agent A's 300ms + velocity-dead version). +- **AppraiseInfoParser profile blobs** — ArmorProfile / CreatureProfile + / WeaponProfile / ArmorLevels / enchantment bitfields. +6 tests. +- **SocialActions** — QueryHealth (0x01BF), PingRequest (0x01E9), + FellowshipCreate/Quit/Dismiss/Recruit/Update, SetCharacterOptions, + AddChannel/RemoveChannel. +10 tests. +- **InventoryActions** — StackableMerge/Split×3, GiveObjectRequest, + AddShortcut, RemoveShortcut, TeleToPoi. +8 tests. +- **9 more GameEvent parsers** — UseDone, PutObjectIn3D, + InventoryServerSaveFailed, CloseGroundContainer, TradeFailure, + AddToTrade, AcceptTrade, QueryItemManaResponse, + CharacterConfirmationRequest. + ## Delta: 19 commits on main, 470 → 628 tests (+158) | # | Commit | Phase | Insert | What |