# acdream — milestones (morale + scope layer) **Status:** Living document. Created 2026-05-12. **Sits above:** [`docs/plans/2026-04-11-roadmap.md`](2026-04-11-roadmap.md) (the strategic phase index). **Currently working toward:** **M1 — Walkable + clickable world.** --- ## Why this document exists The roadmap is a phase index — week- to month-scale, ~50 phases by the time v1.0 lands. Phases ship in vertical slices (architecture-first, horizontal completion deferred), which is the right strategy for a solo open-source project at this scale — but it leaves a chronic "everything is half-built" feeling because no single phase ship feels like a real milestone. This document sits **one altitude above** the roadmap. Each milestone is: - **~6–10 weeks of focused work** (not a single phase, not a whole year). - Defined by a **concrete playable scenario** that gets recorded as a demo video when the milestone hits. - A **scope-freeze event**: when a milestone lands, the phases it covers go off-limits until v1.0's final polish pass (M7). Crossing a milestone is a real event with an artifact. Phases ship; milestones **land**. --- ## Operating rules 1. **One active milestone at a time.** Everything not on the critical path to the current milestone gets filed in `docs/ISSUES.md` with a `post-MN` tag and explicitly muted until the milestone hits. This is what kills the jumping-between-things feeling. 2. **Frozen phases are off-limits.** "Frozen" means no rework, no polish, no follow-up commits unless something is actively broken (player crash, regression). Visual nice-to-haves, "while I'm here" cleanups, and architecture second-guesses are all post-M7. The freeze is the discipline mechanism that makes the milestone meaningful — without it, M0's many shipped phases keep silently consuming attention. 3. **The milestone log is the morale instrument.** When a milestone hits: - Record a ~30-second demo video showing the scenario end-to-end. - Drop it in `docs/milestones/MN-.mp4` (create the directory on first hit). - Pin a still frame + one-paragraph writeup at the top of this doc. - Update the freeze list. Update CLAUDE.md's "currently working toward" line to the next milestone. 4. **State both altitudes at session start.** "Currently working toward M1. Current phase: L.2 collision. Next concrete step: L.2d slice 1 spec." This keeps the high-level orientation visible alongside the immediate task and makes mid-session drift obvious. --- ## The milestones ### M0 — "Connect & explore" — ✅ DONE (crossed months ago) **Demo scenario:** Log in, walk Holtburg in chase camera, see other characters animate, send a chat message and see the echo, watch day turn to night, listen to footsteps and ambient audio. **Phases included (frozen):** | Phase | What landed | |---|---| | 1–3 | Terrain + per-vertex normals + per-cell texture blending | | 4 | UDP codec + handshake + character login + WorldSession | | 5 | ObjDesc: AnimPartChange + TextureChanges + SubPalettes + ObjScale | | 6.1–6.7 | Motion + animation foundation (idle, frame playback, slerp, UpdateMotion, UpdatePosition) | | 7.1 | EnvCell room geometry — walls/floors/ceilings | | 9.1–9.2 | Translucent render pass + back-face culling | | A.1–A.5 | Streaming landblock loader → two-tier streaming | | B.1–B.3 | Outbound ack pump + player movement + physics MVP resolver | | D.1, D.2a | 2D overlay + ImGui scaffold + `AcDream.UI.Abstractions` layer | | E.1–E.5 | Motion hooks + audio + particles + combat wire + spell wire | | F.1, F.2 | GameEvent dispatcher + item model + Appraise | | G.1, G.2 | Sky + day/night + weather + dynamic lighting | | H.1, I.1–I.8 | Chat wire + UI consolidation + holtburger inbound parity + combat translator | | K, L.0 | Input architecture + retail bindings + Settings panel | | N.0–N.6.1 | WB rendering migration (modern path mandatory) | | C.1, C.1.5a/b | Particle system + portal/EnvCell static-script wiring | | R.1–R.3 | Retail research infrastructure (PDB extract + named decomp) | **Status:** This is everything shipped through 2026-05-12. ~25 phase ships. **Worth saying out loud: this is the hard half of the project.** The engine runs, the world renders correctly, the network connects, the input is wired, the data layers for combat/spells/items/audio/particles all exist. What's missing is the gameplay loop on top. --- ### M1 — "Walkable + clickable world" — 🟡 CURRENT (~4–6 weeks) **Demo scenario:** Walk through Holtburg without getting stuck on the inn doorway. Open the inn door. Click an NPC and see selection feedback. Pick up an item from the ground. **Phases to ship:** - **L.2 (all sub-lanes a–g)** — Movement & Collision Conformance. L.2a slices 1+2+3 + L.2d slice 1+1.5 + L.2g slice 1 (code) shipped 2026-05-12. L.2g slice 1 visual verification deferred to B.4b session (the inbound SetState chain can't fire until the outbound Use sends). - **B.4 / B.4b** — `Use` / `UseWithTarget` / `PickUp` interaction. B.4 (2026-04-28) shipped the wire builders, `SelectionState`, `WorldPicker`, the input-action enums, and the keybindings — but *not* the `GameWindow.OnInputAction` handler that ties them together. As of 2026-05-12, clicking on a door silently does nothing. **B.4b** is the small follow-up slice (~30-50 LOC) that subscribes `SelectDblLeft` and routes through pick → BuildUse → send. Once B.4b lands, the same Holtburg-doorway visual test verifies both L.2g slice 1 and B.4b in one pass. **Freeze on landing:** - L.2 zone (collision, cell ownership, transition parity, wire authority) - B.4 zone (interaction outbound) **What "M1 lands" looks like:** the existing Holtburg traversal works as a retail player would expect. Doorways are walkable. Buildings have solid walls. Outdoor cell seams report the right cell. Clicking an NPC selects it and sends a usable selection state to the server. The Use action opens doors. --- ### M2 — "Kill a drudge" — 🔵 NEXT (~6–10 weeks after M1) **Demo scenario:** Equip a sword. Walk to a drudge. Swing. See "You hit Drudge for 12 slashing damage (87%)" in chat. Watch the swing animation play. Drudge dies, drops loot. Pick up the loot. Open the inventory panel and see it. **Phases to ship:** - **F.2 (panels)** — Inventory panel reading `ItemRepository` (data already shipped in F.2 base; M2 ships the visual surface). - **F.3** — Combat math + damage flow. - **F.5a** — Visible-at-login dev panels (Attributes, Skills, Equipped, Inventory list) — minimal ImGui surfaces, retail-skin deferred to M5. - **L.1c** — Combat animation wiring (draw/sheath, attack swings by stance/power/height, hit reactions, evades). - **L.1b** — Command router + motion-state cleanup (prereq for L.1c). **Freeze on landing:** - Combat math zone - Inventory zone (data + dev panel; retail-skin reopens in M5) - L.1b/c combat-animation zone **What "M2 lands" looks like:** the gameplay loop is real. You can fight, take damage, kill things, see loot, manage your inventory. The game becomes a game. --- ### M3 — "Cast a spell" — 🔵 (~3–4 weeks after M2) **Demo scenario:** Cast Flame Bolt at a drudge. Watch the cast animation, the projectile, the impact. Self-cast a buff (Strength Self). See the enchantment in a buff list. Recall to lifestone — full recall animation, correct teleport, correct re-spawn. **Phases to ship:** - **F.4** — Spell cast state machine (buffs + recalls first, projectile spells second). - **L.1d** — Spell-casting animation wiring (cast command classification, windup, release, fizzle/interruption, recoil). - **F.5 (Spellbook panel)** — dev-skin surface for learned spells + active enchantments. **Freeze on landing:** - F.4 spell zone - L.1d cast-animation zone - Spellbook dev-panel surface **What "M3 lands" looks like:** mages are real characters. Buffs work, recalls work, the first projectile spells work. Combat from M2 + casting from M3 = retail-equivalent gameplay loop for melee and casters. --- ### M4 — "Live in the world" — 🔵 (~6–10 weeks) **Demo scenario:** Create a fresh character from scratch (no ACE admin). Spawn. Talk to an NPC. Accept a quest. Walk to a dungeon entrance. Portal in (pink-bubble loading). Walk through the dungeon. Complete the quest. Walk back out. **Phases to ship:** - **H.3** — Emote scripts + quests + dialogs (122 EmoteType × 39 Trigger mini-VM). - **G.3** — Dungeon streaming + portal space + `PlayerTeleport` handling. (Unblocked by L.2e from M1.) - **H.4** — Character creation (`0xE000002 CharGen` + heritages + appearance picker + preview). - **L.1e** — Emote + posture animation wiring. **Freeze on landing:** - H.3 dialog/quest zone - G.3 dungeon zone - H.4 character-creation zone - L.1e emote-animation zone **What "M4 lands" looks like:** the world feels populated and interactive. You can do quests, enter dungeons, create characters. Combined with M2/M3, the client is **functionally playable** — minus visual polish. --- ### M5 — "Looks like retail" — 🟢 PARALLELIZABLE WITH M3/M4 (~4–8 weeks) **Demo scenario:** Side-by-side screenshot of acdream vs retail at the same location, same time of day, same character. Hard to tell apart at a glance. Open the inventory panel — retail-skinned with the right font, icons, and 9-slice panel borders. **Phases to ship:** - **C.1.5c** — Sky-PES dispatch chain (closes #2 lightning, #28 aurora, #29 cloud thinness). - **C.2** — Dynamic point lights (fireplaces, lamps, torches with proper local lighting). - **C.3** — Palette range tuning (skin/hair/eye colors match retail). - **C.4** — Double-sided translucent polys. - **D.2b** — Custom retail-look UI backend. - **D.3–D.7** — AcFont + dat sprites + core panels reskinned + HUD orbs + cursor manager. - **L.1f** — NPC/monster + item-use animation coverage. **Freeze on landing:** - Visual polish zone (C.1.5c, C.2, C.3, C.4) - D.2b → D.7 UI-skin zone - L.1f NPC-anim zone **What "M5 lands" looks like:** the client visually convinces. Screenshots become postable. The "old / broken vs retail" feeling that drives most of the chronic ISSUES.md entries is gone. --- ### M6 — "Plugins ship" — 🟢 (~4 weeks) **Demo scenario:** A third party (not you) writes a small plugin against the published API — XP tracker, loot logger, simple chat filter — and it loads cleanly. Sample plugin lives in the repo with documented build steps. **Phases to ship:** - Plugin API surface: stable contract over `AcDream.Core` + `AcDream.UI.Abstractions`, versioned, with the world-state interfaces exposed. - Plugin host: load isolation, lifecycle, error containment. - Sample plugin (XP tracker or loot logger) — proves the API by using it. - Plugin docs page. **Freeze on landing:** - Plugin API v1 surface (additive changes only post-freeze). **What "M6 lands" looks like:** the differentiator vs the retail client is real. acdream offers something retail never did, and the API is documented well enough that other people can build on it. --- ### M7 — "v1.0" — 🟢 (open-ended polish) **Demo scenario:** Long-running stress test: log in, play for 4 hours across outdoor + dungeon + portal + combat + spell + chat scenarios, reconnect once mid-session, log out clean. No crashes, no protocol errors, no visual regressions, no audio dropouts. **Phases to ship:** - **Phase M** — Network stack conformance (retransmit, ACK piggybacking, echo/keepalive, fragment splitting, typed actions). Deferred until now because ACE handles loss gracefully — but v1.0 needs proper network hardening. - **H.2** — Allegiance. - **N.6 slice 2 + N.7–N.10** — Finish WB rendering migration (EnvCells, sky/particles via WB, visibility manager, GL infrastructure consolidation). - **Phase J long-tail** — Player rig polish, group/fellowship UI, trade window, salvage/tinker UI, house ownership, society UI, dev-mode tools. - **L.1g** — Animation polish + conformance. - Final visual + audio polish pass against ISSUES.md chronic backlog. **What "M7 lands" looks like:** v1.0. Ship. --- ## Estimated timeline | Milestone | Effort | Cumulative | |---|---|---| | M0 | DONE | DONE | | M1 | ~4–6 wk | ~5 wk | | M2 | ~6–10 wk | ~13 wk | | M3 | ~3–4 wk | ~17 wk | | M4 | ~6–10 wk | ~25 wk | | M5 | ~4–8 wk (parallel) | overlaps M3/M4 | | M6 | ~4 wk | ~29 wk | | M7 | open-ended | v1.0 | **Roughly 9–12 months of focused solo work from 2026-05-12 to v1.0.** That's honest for an open-source project of this scale. The biggest single rock is M2 (combat math + animations + inventory panels lining up); M5 can be chipped at in parallel by subagents while you drive M3/M4. --- ## What this document is **not** - **Not a release schedule.** Internal morale + scope layer only. If acdream goes public-alpha at some point, that's a separate decision built on top of one of these milestones. - **Not immutable.** When reality and the milestones diverge, update the milestones in the same session you discover the divergence. Same rule as the roadmap. - **Not a replacement for the roadmap.** Phases are still where the implementation details live. This doc is the orientation layer above them. - **Not granular enough for daily work.** Daily work happens at the phase / sub-phase / commit level. The milestone is the multi-week target you're aiming at.