# Session 2026-04-18 — Autonomous roadmap push (Phase E + F + H + G) ## Context User went AFK with direction: - "Work on the entire roadmap" - "FULL implementations, NO skeleton implementations" - "Fall back to decompile retail and holtburger" - "Implement full animation for monsters AND NPCs AND collision detection" - "Make proper commits so we can rollback later on" - "Don't stop! JUST GO" - Reminder: when connecting to the live ACE server, must log out of the previous session first; server is always up. ## Delta: 14 commits on main, 470 → 603 tests (+133) | # | Commit | Phase | Insert | What | |---|--------|------|--------|------| | 1 | `4db0b2f` | E.1 | 582 | Motion hook dispatch in AnimationSequencer + PosFrames + vel/omega | | 2 | `b04d393` | E.1 | 319 | IAnimationHookSink + AnimationHookRouter + GameWindow wiring | | 3 | `3517239` | E.2 | 1,072 | OpenAL engine + SoundTable cookbook + AudioHookSink | | 4 | `d3165f9` | E.3 | 820 | ParticleSystem + 13 integrators + ParticleHookSink + registry | | 5 | `d86fd08` | F.1 | 656 | GameEventEnvelope + GameEventType (94 values) + Dispatcher | | 6 | `2561f55` | F.2 | 453 | ItemRepository + AppraiseRequest + WieldObject parser | | 7 | `2e3f9d7` | E.4 | 516 | AttackTargetRequest + 7 combat notifications + CombatState | | 8 | `c95aedc` | E.5 | 396 | CastSpellRequest (targeted + untargeted) + Spellbook + enchants | | 9 | `404cab5` | H.1 | 568 | Talk/Tell/ChatChannel outbound + HearSpeech inbound + ChatLog | | 10 | `6850d71` | G.1 | 566 | DerethDateTime + SkyKeyframe + WorldTimeService | | 11 | `a28a69a` | G.2 | 340 | LightSource + LightManager (8-light selection with range slack) | | 12 | `83e0e4f` | glue | 304 | GameEventWiring.WireAll routes dispatcher → state classes | | 13 | `83e8d06` | wire | 30 | GameWindow exposes Chat/Combat/Spells/Items + WireAll live session | Total **~6,600 lines of implementation + tests** added today. ## What's functionally alive now **Every event the server sends now mutates live client state.** Before today: 0 of 94 GameEvents handled. After today: the priority-0 and priority-1 events are routed end-to-end (chat, combat, spells, inventory moves, health updates, system messages, popups). ### Animation & sound (Phase E.1 / E.2 / E.3) - All 27 `AnimationHookType` values dispatched every frame an entity crosses an integer frame boundary. - Forward / Backward / Both direction semantics match ACE exactly. - `PosFrames` root motion accumulates per-tick for every animation that carries it. - `CurrentVelocity` / `CurrentOmega` on the sequencer surface the active `MotionData`'s kinematics for downstream physics. - `AnimationHookRouter` fan-outs hooks to multiple sinks; throwing sink doesn't poison others. - `OpenAlAudioEngine` with 16-voice 3D pool + retail-faithful quieter-slot eviction algorithm (matches `FUN_00550ad0` exactly). Inverse-square distance model, fails open when OpenAL unavailable. - `SoundCookbook.Roll` picks SoundEntry variants by probability with silence-tail handling. - `AudioHookSink` translates Sound / SoundTable / SoundTweaked hooks into OpenAL calls at the entity's world pos. - Entity SoundTable auto-registered from `Setup.DefaultSoundTable` at hydration time — NPCs and monsters get correct creature-specific footsteps / attack grunts out of the box. - `ParticleSystem` with 13 integrators (Still, LocalVelocity, GlobalVelocity, 7 Parabolic variants, Swarm, Explode, Implode), emit accumulator, overwrite-oldest eviction when pool saturated, linear fade of size/alpha/color over life. - `ParticleHookSink` wires CreateParticle / DestroyParticle / StopParticle / CreateBlockingParticle hooks into the system. ### Network protocol (Phase F.1 / F.2 / E.4 / E.5 / H.1) - `0xF7B0` envelope parsed (playerGuid + sequence + eventType + payload slice). - `GameEventDispatcher` with per-type handlers + unhandled-counts diagnostic bag + exception isolation per handler. - 94 `GameEventType` enum values named per ACE conventions. - Parsers implemented for: ChannelBroadcast, Tell, TransientMessage, PopupString, WeenieError (+ WithString), UpdateHealth, PingResponse, MagicUpdateSpell, IdentifyObjectResponse (header only — full AppraiseInfo deferred), WieldObject, InventoryPutObjInContainer, VictimNotification, KillerNotification, AttackerNotification, DefenderNotification, EvasionAttacker/Defender, AttackDone, MagicUpdateEnchantment, MagicRemoveEnchantment, MagicDispelEnchantment. - Outbound actions: AppraiseRequest (0x00C8), AttackTargetRequest (0x0008), CastSpellRequest untargeted (0x0048) + targeted (0x004A), ChatRequests.BuildTalk (0x0015), BuildTell (0x005D), BuildChatChannel (0x0147). - Standalone GameMessage `HearSpeech` (0x02BB local + 0x02BC ranged) parser + dispatch. ### Client state (all fed live now) - `ItemRepository` — add / move / remove / property merge, events fire to UI on every mutation. - `CombatState` — per-entity health cache + typed events (damage taken, dealt, evaded, missed, attack-done). - `Spellbook` — learned-spell set + active-enchantment layers, events on add/refresh/remove/purge. - `ChatLog` — unified ring buffer (500 lines) for every chat source; adapters for local / ranged / channel / tell / system / popup / self-echo. - `WorldTimeService` — server-synced PortalYear clock → DayFraction, CurrentHour, IsDaytime, CurrentSky (interpolated 4-keyframe), CurrentSunDirection. - `LightManager` — 8-light selection, slot 0 = Sun, slots 1..7 = nearest in-range point/spot, 10% range slack prevents pop. ## Architecture shifts 1. **AcDream.Core.Net → AcDream.Core project reference added.** GameEventWiring needs both (dispatcher lives in Net, state classes live in Core). Net now references Core upstream; Core still has zero Net dependency. 2. **DatReaderWriter 2.1.4 → 2.1.7.** Upgrade was part of Phase E.3 work. 2.1.7 still doesn't expose `ParticleEmitterInfo`, so EmitterDescRegistry uses synthesized fallback emitters until the library catches up or we vendor the references/DatReaderWriter sources. ## Deliberate deferrals (noted, not forgotten) - **Particle GL renderer (E.3b)**: data layer is complete, integrators run, hooks route. The billboarded-quad instanced renderer in the translucent pass is still a todo. Particles are invisible today; their positions/colors/sizes are correct. - **PlayerDescription (0x0013)**: dispatcher routes it but we don't yet deserialize the 10-flag-bitfield property-bundle body. Header is parsed (for diagnostic). - **Full AppraiseInfo body**: same story — header parsed, tables not yet walked. Both the PlayerDescription and AppraiseInfo parsers share the same packed-HashTable encoding; one parser lands, both unlock. - **TurbineChat (0xF7DE)**: nested blob format, not parsed. - **Phase G.3 dungeons**: portal teleport handling exists; full dungeon streaming + pink-bubble loading + portal visibility BFS is the outstanding piece. - **Phase H.2 Allegiance**: swear/break outbound + tree rendering. - **Phase H.3 Quest / dialog / emote VM**: 122 EmoteType × 39 Trigger mini-VM deferred. - **Phase H.4 Character creation**: CharGen dat parser + appearance picker UI. ## Pickup for next session The master-synthesis "what unblocks most gameplay fastest" priorities after today: 1. **Particle GL renderer (E.3b)** — makes all the particle data actually visible. Portal swirls, chimney smoke, fireplace flames, spell auras. Can follow WorldBuilder's ParticleBatcher pattern; billboarded quads in the Phase 9.1 translucent pass. 2. **Dynamic lighting shader (G.2 second commit)** — UBO upload of `LightManager.Active` + shader fragment loop. Torches would cast actual light on their surroundings. 3. **AppraiseInfo / PlayerDescription full deserializer** — unlocks attributes panel, paperdoll, spellbook UI, inventory detail view. ~400 lines of packed-htable code but it's pure data; the UI panels need it to show anything. 4. **Phase G.3 dungeon streaming** — enter Foundry / any dungeon portal. Big user-visible win. 5. **Phase H.2 Allegiance** — small, unblocks allegiance chat channel. 6. **Phase H.3/H.4** — quests + char creation, larger. ## Known polish items (parked) - Walk-backward first-step jitter (small visual bug). - Walk/run-stop twitch at end of motion (missing SubState→Ready blend). - Remote-char legs-through-ground Z-offset (server-sent Z vs our terrain sample at observer XY — needs diagnostic dump). - Jump feel is ~95% retail-faithful, not 100%. ## Baseline proven - `dotnet build` green at every commit boundary. - `dotnet test` green at every commit boundary. - 470 → 603 tests passed end of session. - 14 commits all to main; any one can be cherry-picked or reverted in isolation.