acdream/docs/plans/2026-05-12-milestones.md
Erik aba6c9ac7f docs(phys L.2g): slice 1 shipped handoff + B.4 gap discovery + plan-of-record
L.2g slice 1 is CODE-COMPLETE: parser + registry mutator + WorldSession
dispatcher + GameWindow subscriber (4 commits: 2459f28, d538915,
536a608, 108e386). Build clean, 6 new tests pass, baseline-stable
across the full suite. Per-commit + final integration code reviews
all approved.

Visual verification deferred: while running the Holtburg-doorway test,
Phase B.4's outbound Use handler turned out to be unwired. The wire
builders (InteractRequests.BuildUse), classes (SelectionState,
WorldPicker), input-action enums, and keybindings all exist — but
GameWindow.OnInputAction has no case for SelectDblLeft, so the click
silently does nothing. The inbound L.2g chain we just landed can't
fire until something sends an outbound Use.

This commit captures the handoff + reframes next-session work:

  * docs/research/2026-05-12-l2g-slice1-shipped-handoff.md (NEW)
    Full evidence: 4 shipped commits, end-to-end code flow, B.4
    discovery explanation, 4 minor + 1 Important review notes
    (the Important one is a test-coverage gap that the B.4b visual
    test will settle automatically), reproducibility recipe,
    next-session pick.

  * CLAUDE.md
    "Currently in Phase L.2" paragraph: L.2g slice 1 code shipped;
    visual test deferred to B.4b. Next-phase-candidates list:
    L.2g slice 1 (now done) replaced with the B.4b candidate
    pointing at the slice scope.

  * docs/plans/2026-04-29-movement-collision-conformance.md
    L.2g section gains a "Current shipped slice (2026-05-12):" table
    listing the 4 commits.

  * docs/plans/2026-05-12-milestones.md
    M1 phase-list updated: L.2g slice 1 (code) shipped; B.4 renamed
    "B.4 / B.4b" with the gap-discovery note + B.4b shape.

  * docs/ISSUES.md
    New issue #57 (HIGH) for the B.4 interaction-handler gap.
    Promoted to Phase B.4b; will close as
    DONE (promoted to Phase B.4b) when B.4b's design spec lands.

  * Memory file project_interaction_pipeline.md (in personal
    memory dir, not in this commit) updated to reflect reality.

Next session: Phase B.4b (~30-50 LOC, 1-2 subagent dispatches,
~30 min). Subscribe SelectDblLeft -> WorldPicker.Pick ->
InteractRequests.BuildUse -> _liveSession.SendGameMessage. Same
Holtburg-doorway visual test verifies both L.2g slice 1 and B.4b
in one pass.

Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
2026-05-12 23:17:05 +02:00

320 lines
13 KiB
Markdown
Raw Blame History

This file contains ambiguous Unicode characters

This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

# 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:
- **~610 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-<slug>.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 |
|---|---|
| 13 | Terrain + per-vertex normals + per-cell texture blending |
| 4 | UDP codec + handshake + character login + WorldSession |
| 5 | ObjDesc: AnimPartChange + TextureChanges + SubPalettes + ObjScale |
| 6.16.7 | Motion + animation foundation (idle, frame playback, slerp, UpdateMotion, UpdatePosition) |
| 7.1 | EnvCell room geometry — walls/floors/ceilings |
| 9.19.2 | Translucent render pass + back-face culling |
| A.1A.5 | Streaming landblock loader → two-tier streaming |
| B.1B.3 | Outbound ack pump + player movement + physics MVP resolver |
| D.1, D.2a | 2D overlay + ImGui scaffold + `AcDream.UI.Abstractions` layer |
| E.1E.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.1I.8 | Chat wire + UI consolidation + holtburger inbound parity + combat translator |
| K, L.0 | Input architecture + retail bindings + Settings panel |
| N.0N.6.1 | WB rendering migration (modern path mandatory) |
| C.1, C.1.5a/b | Particle system + portal/EnvCell static-script wiring |
| R.1R.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 (~46 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 ag)** — 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 (~610 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" — 🔵 (~34 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" — 🔵 (~610 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 (~48 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.3D.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.7N.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 | ~46 wk | ~5 wk |
| M2 | ~610 wk | ~13 wk |
| M3 | ~34 wk | ~17 wk |
| M4 | ~610 wk | ~25 wk |
| M5 | ~48 wk (parallel) | overlaps M3/M4 |
| M6 | ~4 wk | ~29 wk |
| M7 | open-ended | v1.0 |
**Roughly 912 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.