CLAUDE.md edits (6 surgical ranges):
- Goal section: introduce named-retail/ as primary; old chunks
remain as fallback for chunk-by-chunk address-range navigation.
- Workflow renamed to "grep named -> decompile -> verify -> port"
with a new STEP 0 GREP NAMED FIRST. Decompile demoted to a
fallback (Step 1) for the rare obfuscated/packed minority that
pseudo-C lacks.
- Function-map citation updated to point at symbols.json + the
cross-port hand-curated table.
- "Do not guess" rule strengthened: PDB has the answer for almost
everything; guessing is now negligence.
- Phase completion checklist accepts named symbols + addresses.
- Reference hierarchy table gets a new top row pointing at
docs/research/named-retail/ as the primary oracle for any
AC-specific algorithm — beats every other reference.
memory/project_named_decompilation.md (new): evergreen crib-sheet
with file inventory, grep examples, hard rules. Pattern matches
project_ui_architecture.md.
memory/project_retail_research_index.md: updated preamble to point
named-retail/ as first stop; older slices remain useful for
pseudocode + C# port sketches.
memory/project_collision_port.md: rewrote the "Decompiled ground
truth" section to put named-retail/ first, chunks second. The
"DECOMPILE FIRST" mandate becomes "GREP NAMED FIRST, then DECOMPILE
FALLBACK".
docs/architecture/acdream-architecture.md: Guiding Principle text
updated to introduce named-retail as the primary decomp source.
docs/plans/2026-04-11-roadmap.md: new Phase R block — Retail
research infrastructure. R.1 (corpus, shipped a9a01d8), R.2
(pdb-extract, shipped 69d884a), R.3 (actestclient vendored,
shipped a9a01d8). All marked SHIPPED 2026-04-25.
Auto-loaded MEMORY.md index updated with a new entry pointing at
project_named_decompilation.md so post-compaction sessions inherit
the workflow change automatically.
Acceptance verified:
- grep -c "named-retail" CLAUDE.md = 9 (>= 3 required)
- grep -c "named-retail" MEMORY.md = 1
- dotnet build green (docs-only commit, but verified)
Foundation phases A + B + C all landed. Next: Phase D files
ISSUES #8/#9/#11 + closes #10 (KillerNotification orphan parser).
Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
28 KiB
acdream — strategic roadmap
Status: Living document. Updated 2026-04-11 after Phase 6, 7.1, 9.1, 9.2 landed.
Purpose: One source of truth for where the project is and where it's going. Every observed defect or missing feature has a named phase that owns it; when something looks wrong in-game, look here to find the phase that'll address it. Implementation details live in per-phase specs under docs/superpowers/specs/, not in this file.
Phases already shipped
| Phase | What landed | Verification |
|---|---|---|
| 1 | Terrain rendering, plugin host scaffold | Visual ✓ |
| 2a | Static stabs/buildings (126 entities) | Visual ✓ |
| 2b | Textured 3×3 landblock grid + FlyCamera + IGameState | Visual ✓ |
| 2c | Procedural scenery (419 trees/rocks/bushes) | Visual ✓ |
| 2d | Interior EnvCell walker (475 static interior objects) | Visual ✓ |
| 3a/3b | Directional sun lighting + per-vertex terrain normals | Visual ✓ |
| 3c | Per-cell terrain texture blending (alpha atlas) | Visual ✓ |
| 4 | Full UDP codec + handshake + character login + WorldSession | Live ✓ |
| 5 | ObjDesc: AnimPartChange + TextureChanges + SubPalettes + ObjScale + Placement.Resting | Live ✓ |
| 6.1 | Idle motion frame resolution (MotionResolver MVP) | Live ✓ |
| 6.2 | Server-sent MovementData stance + forward command honored |
Live ✓ |
| 6.3 | Server-supplied MotionTableId override (fixes drudge statue) |
Live ✓ |
| 6.4 | Per-frame animation playback (breathing, idle cycles) | Live ✓ |
| 6.5 | Slerp between keyframes for smooth animation | Live ✓ |
| 6.6 | UpdateMotion (0xF74C) parser + dispatch to animation tick |
Live ✓ |
| 6.7 | UpdatePosition (0xF748) parser + position reseating |
Live ✓ |
| 7.1 | EnvCell room geometry — walls/floors/ceilings via CellStruct + Environment dats | Visual ✓ |
| 9.1 | Translucent render pass (AlphaBlend / Additive / InvAlpha + per-kind blend funcs) | Visual ✓ |
| 9.2 | Back-face culling in translucent pass (fixes lifestone crystal) | Visual ✓ |
| A.1 | Streaming landblock loader — runtime-configurable visible window (default 5×5, ACDREAM_STREAM_RADIUS), camera-centered offline / player-centered live, hysteresis-based unloads, pending-spawn list for late CreateObject events |
Live ✓ |
| A.2 | Frustum culling — per-landblock AABB test (Gribb-Hartmann), terrain + static-mesh renderers skip culled landblocks, perf overlay in window title | Visual ✓ |
| A.3 | Background net receive thread — dedicated daemon thread buffers UDP into Channel, render thread drains | Visual ✓ |
| B.3 | Physics collision engine — TerrainSurface (heightmap Z), CellSurface (indoor floor polygon projection), PhysicsEngine (resolver with step-height + cell transitions). Populated from streaming pipeline. | Tests ✓ |
| B.2 | Player movement mode — Tab-toggled WASD ground walking, walk/run/idle animations, third-person chase camera, MoveToState + AutonomousPosition outbound, portal entry. Outdoor-only MVP. | Live ✓ |
| D.1 | 2D ortho overlay + font rendering (StbTrueTypeSharp atlas + TextRenderer + DebugOverlay) | Visual ✓ |
| E.1 | Motion-hook expansion — AnimationSequencer fires all 27 hook types per crossed frame; PosFrames root motion + vel/omega exposure; IAnimationHookSink + AnimationHookRouter fan-out | Tests ✓ |
| E.2 | Audio engine — OpenAL 16-voice 3D pool with retail-faithful quieter-slot eviction, SoundTable cookbook (probability-weighted variant picking), Wave PCM decoder, AudioHookSink wiring | Tests ✓ |
| E.3 | Particle system (data layer) — ParticleSystem with 13 motion integrators, EmitterDescRegistry, ParticleHookSink wiring all CreateParticle / DestroyParticle / StopParticle hooks | Tests ✓ |
| E.4 | Combat notifications + outbound — AttackTargetRequest (0x0008), 7 combat notification parsers (Victim/Defender/Attacker/Evasion/AttackDone/UpdateHealth), CombatState per-entity health tracker | Tests ✓ |
| E.5 | Spell cast wire — CastSpellRequest targeted (0x004A) + untargeted (0x0048), Spellbook (learned spells + active-enchantment layers), 5 enchantment GameEvent parsers | Tests ✓ |
| F.1 | GameEvent (0xF7B0) envelope dispatcher — all 94 sub-opcodes routed, exception-isolated handler registry, unhandled-count diagnostic bag; 18 event-payload parsers | Tests ✓ |
| F.2 | Item model + Appraise — ItemRepository with move/equip/property events, AppraiseRequest (0x00C8), IdentifyObjectResponse header, WieldObject + InventoryPutObjInContainer | Tests ✓ |
| G.1 | Sky + day/night — DerethDateTime (retail-exact 7620-tick calendar + 16-hour names + PY year), SkyStateProvider (4-keyframe default with angular-wrap lerp), WorldTimeService (server-synced clock with real-time advance) | Tests ✓ |
| G.2 | Dynamic lighting (selection) — LightSource + LightManager with retail 8-light cap, range-squared with 1.1× slack, slot 0 reserved for Sun, OwnerId-keyed unregister | Tests ✓ |
| G.1+ | Full sky visuals + weather + dynamic-light shader — SkyDescLoader parses Region 0x13000000 dat keyframes with retail fog fields (start/end/mode); WeatherSystem picks Clear/Overcast/Rain/Snow/Storm deterministically per in-game day with 10s fade; SkyRenderer draws far-plane-1e6 celestial meshes with UV scroll; SceneLightingUbo binds at std140 location=1 with 8 Light slots + fog + lightning flash; terrain.vert + mesh.frag + mesh_instanced.frag + sky.frag all consume the shared UBO; LightingHookSink auto-registers Setup.Lights per entity + flips IsLit on SetLightHook; ParticleRenderer renders rain/snow billboards; F7 cycles day time override, F10 cycles weather; WorldSession surfaces server time via ServerTimeUpdated (ConnectRequest + TimeSync flag) | Tests ✓ |
| H.1 | Chat wire layer — Talk (0x0015) / Tell (0x005D) / ChatChannel (0x0147) outbound, HearSpeech (0x02BB local + 0x02BC ranged) inbound, ChatLog ring buffer with adapters for every chat source | Tests ✓ |
| Glue | GameEventWiring.WireAll — single-call registration mapping parsed GameEvents → Core state classes (ChatLog, CombatState, Spellbook, ItemRepository); GameWindow exposes state classes + wires them to live session | Tests ✓ |
| D.2a | UI scaffold — AcDream.UI.Abstractions stable contract (IPanel / IPanelHost / IPanelRenderer / ICommandBus + VitalsVM / VitalsPanel); AcDream.UI.ImGui backend on ImGui.NET + Silk.NET.OpenGL.Extensions.ImGui (pivoted from Hexa.NET.ImGui on 2026-04-25 — Hexa's native OpenGL3 backend resolves GL via GLFW/SDL and crashed 0xC0000005 without them); VitalsPanel wired into GameWindow behind ACDREAM_DEVTOOLS=1 with ImGui.WantCaptureKeyboard WASD suppression. 11 new tests. |
Live ✓ |
Plus polish that doesn't get its own phase number:
- FlyCamera default speed lowered + Shift-to-boost
- SurfaceDecoder: PFID_P8 / PFID_R8G8B8 / PFID_X8R8G8B8 decoders
- GfxObjMesh: emit both pos and neg sides of double-sided polygons
- EnvCell mesh Z-lift to fix ground-floor / terrain flicker
Phases ahead — agreed order
Phase A — Foundation (in progress)
Goal: walk across 10+ landblocks without crashes, without hitches at landblock boundaries, and without framerate cratering.
Sub-pieces:
- ✓ SHIPPED — A.1 — Streaming landblock loader. Runtime-configurable visible window (default 5×5,
ACDREAM_STREAM_RADIUSenv var override). Center follows the fly camera offline and the server-sent player position in live mode. Currently runs synchronously on the render thread — the original async-worker design hit DatCollection's lack of thread safety and was reverted for correctness. The Channel-based outbox API is preserved so async loading can return cleanly whenPhase A.3introduces a thread-safe dat wrapper. Pending-spawn list inGpuWorldStateparks liveCreateObjectevents whose target landblock hasn't been streamed in yet and back-fills them when it arrives, so spawn-vs-streaming races are no longer racy at all.MaxCompletionsPerFrame=4spreads the 5×5 first-frame load over ~7 frames (~116ms) to avoid GPU OOM. - ✓ SHIPPED — A.2 — Frustum culling. Per-landblock AABB test (Gribb-Hartmann plane extraction + positive-vertex AABB test) in both
TerrainRenderer.DrawandStaticMeshRenderer.Draw. Per-entity culling deferred. LOD deferred to Phase C. Performance overlay in window title shows FPS, frame time, visible/total landblock ratio, entity count, animated count. ~160fps uncapped at 5×5 radius. - ✓ SHIPPED — A.3 — Background net receive thread. Dedicated daemon thread continuously pulls raw UDP datagrams from the kernel buffer into a
Channel<byte[]>. Render thread'sTick()drains the channel. All decode, fragment assembly, ISAAC crypto, event dispatch, and ack-sending remain on the render thread — minimal change that prevents packet drops during frame stalls. Thread starts afterEnterWorld()completes;PumpOnce()during handshake still reads the socket directly. - A.4 — Async dat decoding. Folded into the streaming worker — it's the worker's read path, not a separate subsystem. Called out here because regressions in dat caching could land on this surface.
Acceptance:
- Walk across 10+ landblocks in any direction, no crashes, no empty voids.
- Landblock-boundary crossings produce no visible hitch.
- Runtime window radius toggleable via environment variable.
Detailed spec: docs/superpowers/specs/2026-04-11-foundation-phase-design.md
Phase B — Gameplay / interaction
Goal: actually play the game — walk the character on the server, click NPCs, pick up items, chat, basic combat loop.
Sub-pieces:
- ✓ SHIPPED — B.1 — Outbound ack pump. Shipped as Phase 4.9 — per-packet ACK_SEQUENCE, not periodic. Server no longer drops idle clients.
- ✓ SHIPPED — B.2 — Player movement mode. Tab-toggled WASD ground walking with collision-resolved outdoor terrain, walk/run/idle/turn-right animations, third-person chase camera, outbound MoveToState (0xF61C) + AutonomousPosition (0xF753) server messages, portal entry works. Outdoor→indoor transition disabled for MVP (CellSurface floor polygons too aggressive without portal-based detection). Minor polish remaining: strafe animation, turn-left animation. Spec:
docs/superpowers/specs/2026-04-12-player-movement-design.md. - ✓ SHIPPED — B.3 — Physics collision engine. TerrainSurface (heightmap bilinear Z), CellSurface (indoor floor polygon projection via barycentric interpolation), PhysicsEngine (top-level resolver with step-height enforcement, outdoor↔indoor cell transitions, gravity reporting). Populated from streaming pipeline. 16 unit tests with fake data. Spec:
docs/superpowers/specs/2026-04-12-physics-collision-engine-design.md. - B.4 —
Use/UseWithTarget/PickUp. Outbound interaction messages. Drives opening doors, looting, talking to vendors. - B.5 — Chat.
SendTell,SendChatoutbound + receive/display inbound (display side depends on Phase D.1).
References:
references/ACE/Source/ACE.Server/Network/Handlers/MovementHandler.csreferences/ACE/Source/ACE.Server/Network/Handlers/UseObjectHandler.csreferences/holtburger/src/session/send.rsfor outbound packet-building patterns
Acceptance: walk on-server with your character, open a door, talk to an NPC, send a chat message and see the echo.
Phase C — Polish / visuals
Goal: close the visible gaps that make the world read as "old / broken" compared to retail.
Sub-pieces:
- C.1 — VFX / particle system.
PhysicsScriptparser, per-entityParticleEmitterstate, billboarded-quad particle renderer that lives in the Phase 9.1/9.2 translucent pass. Delivers portal swirls, chimney smoke, and fireplace flames in one implementation. - C.2 — Dynamic point lights. Fireplaces and lamps need local lighting; small upgrade to the mesh shader to accumulate N (e.g., 4) nearest point lights per draw. Uniform-buffer or UBO-friendly layout.
- C.3 — Palette range tuning. Small per-range offset/length tweaks to match retail skin/hair/eye colors. Mostly diff and verify work, no architecture change.
- C.4 — Double-sided translucent polys. Edge case left by Phase 9.2: neg-side translucent polys are culled because cull is always BACK. Fix by tracking per-sub-mesh
CullModeand flipping GL state per draw (or drawing twice with opposite cull). Minor. - C.5 — Shadow mapping (optional). Deferred unless it becomes a bottleneck in screenshots — dynamic shadows are a known complexity trap.
References:
references/ACE/Source/ACE.DatLoader/FileTypes/PhysicsScript.csfor the emitter schemareferences/ACViewer/ACViewer/Physics/Particles/for the visual modelreferences/WorldBuilder/Chorizite.OpenGLSDLBackend/Lib/ParticleBatcher.csfor the Silk.NET-flavored implementation
Acceptance: portals look like swirly gates, chimneys smoke, fireplaces burn, character skin matches retail screenshots.
Phase D — UI / HUD + Sound
Goal: chat window, nameplates, inventory, and audio. Can run concurrently with Phase B or C because it doesn't touch gameplay/net/rendering surfaces.
Updated 2026-04-24 — staged backend strategy. We split Phase D into two stages so game logic can be validated quickly without waiting for the full retail-look custom toolkit. See
docs/plans/2026-04-24-ui-framework.mdfor the full design. Short version:
- D.2a — ImGui as the short-term backend. Wire up in days, iterate game logic (chat-send, inventory actions, vitals HUD reading real state) in weeks. Looks like a debugger; that's fine. (Shipped 2026-04-25 on ImGui.NET +
Silk.NET.OpenGL.Extensions.ImGuiafter a day-one pivot away from Hexa.NET.ImGui; see shipped table.)- Stable
AcDream.UI.Abstractionslayer — ViewModels + Commands +IPanel/IPanelRendererinterfaces. Backend-agnostic. Plugin API publishes against this layer and never sees ImGui.- D.2b onward — custom retail-look backend using dat assets (icons, panels, fonts). Swap one panel at a time; ImGui stays forever as the
ACDREAM_DEVTOOLS=1overlay for packet trace / state dump / dat browser.Every sub-piece below (D.3 AcFont, D.4 dat sprites, D.5 core panels, D.6 HUD, D.7 cursors) ships against the abstraction layer, so it doesn't matter which backend is drawing when the port lands.
Sub-pieces:
- D.1 — 2D ortho overlay + font rendering. ✅ SHIPPED 2026-04-17 as the dev-facing debug overlay (StbTrueTypeSharp system-font atlas +
TextRenderer+DebugOverlay). - ✓ SHIPPED — D.2a — ImGui scaffold +
AcDream.UI.Abstractionslayer. Shipped 2026-04-25. Wires ImGui as the short-term backend behindACDREAM_DEVTOOLS=1. DefinesIPanel/IPanelHost/IPanelRenderer/ICommandBus+ the first ViewModel (VitalsVM) in the newAcDream.UI.Abstractionsproject. First real panel:VitalsPanelreading HP fromCombatState.GetHealthPercent. Backend pivoted Hexa.NET.ImGui → ImGui.NET +Silk.NET.OpenGL.Extensions.ImGuiduring integration — Hexa's native OpenGL3 backend does its own GL function resolution via GLFW/SDL and crashed with0xC0000005inImGuiImplOpenGL3.InitNativeagainst Silk.NET (no GLFW/SDL present). The Silk.NET extension is purpose-built for this scenario and is theImGui.NETmitigation path thatdocs/plans/2026-04-24-ui-framework.mdalready called out as a "one-morning operation". Stam/Mana returnfloat?null in D.2a because absolute values needLocalPlayerState+PlayerDescription (0x0013)parsing (filed post-D.2a). 11 newAcDream.UI.Abstractions.Testsgreen. - D.2b — Custom retail-look backend. Implements the same
IPanel/IPanelRenderercontracts using a custom retained-mode toolkit sourced from retail dat assets. Requires D.2a shipped. Panels get reskinned one at a time; ImGui stays as theACDREAM_DEVTOOLS=1overlay forever. The original 2026-04-17 scaffold research (UiRoot/UiElement/UiPanel/UiHost+ retail event codes + focus / drag-drop state machine +WorldMouseFallThrough) is the implementation foundation here — seedocs/research/retail-ui/. - D.3 — AcFont from portal.dat. Replace stb_truetype system font with retail
FontDBObjs (0x40000000..0x40000FFF) baked fromRenderSurfacesource sheets — see research slice 03 §4. Preserves retail visual identity. (D.2b dependency — needs the custom renderer.) - D.4 — Dat sprites + 9-slice panel backgrounds. Load
RenderSurface(0x06xxxxxx) as GL textures; addDrawSpritetoUiRenderContext. Enables retail panel art. (D.2b dependency.) - D.5 — Core panels. Attributes (
chunk_00470000.c:FUN_0047ba70), Skills (same), Paperdoll (chunk_004A0000.c:FUN_004A5200), Inventory, Spellbook (chunk_004C0000.c), Fellowship, Allegiance. Each uses the port sketches in slice 05. (TargetsAcDream.UI.Abstractions— ships with D.2a using ImGui-rendered widgets; reskinned by D.2b.) - D.6 — HUD. Vital orbs (scissor-rect partial fill, dat sprites
0x060013B2), radar (0x06001388/0x06004CC1, 1.18× range factor), compass strip (scrolling U), target name plate, damage floaters, selection indicator. See slice 06. (TargetsAcDream.UI.Abstractions— ships with D.2a; reskinned by D.2b.) - D.7 — Cursor manager. OS + dat-sourced custom cursors (
FUN_0043c1c0GDI HCURSOR builder pattern from slice 03). (D.2b dependency.) D.8 — Sound.Superseded — shipped as Phase E.2 (SoundTable/Sounddat decode, OpenAL 16-voice engine, per-entity 3D positional audio viaAudioHookSink). Entry kept here for history; see the shipped table.
Reference docs: docs/research/retail-ui/00-master-synthesis.md + slices 01-06. Every AC-specific behavior has a decompiled FUN_ / DAT_ citation.
Acceptance: chat messages display in a retail-style panel, health/stamina/mana orbs fill correctly, attributes panel shows player stats, inventory opens with drag-drop working, and sound plays on hit/footstep.
Phase E — "Feel alive" — motion hooks + audio + VFX
Unlocks the sensory layer: footsteps, swing whooshes, impact sparks, spell auras. All three systems share animation-hook delivery as the trigger source — motion hooks are the blocker.
Research backing: docs/research/deepdives/00-master-synthesis.md + R3 + R4 + R5.
- E.1 — Motion-hook expansion. Extend MotionInterpreter + AnimationSequencer to deliver all 27 AnimationHookType values (Sound=1, SoundTable=2, CreateParticle=18, AttackFrame=20, SoundTweaked=21, …) during frame advance. See
r03-motion-animation.md. - E.2 — Audio engine.
AudioEngineviaSilk.NET.OpenAL, inverse-square CPU falloff, 16-voice pool. SoundTable + Wave dat decoders. Motion-hook wiring for footsteps + attacks. Seer05-audio-sound.md. - E.3 — Particle system.
ParticleSystemon Silk.NET GL (port WorldBuilder'sParticleBatcher). 13 motion-type integrators.PhysicsScriptdispatcher tied to motion-hooks. Seer04-vfx-particles.md.
Acceptance: walk around, footstep sounds per material; swing a weapon, hear whoosh; combat impact shows sparks + hit sound.
Phase F — Fight + cast + gear
Core gameplay loop on top of Phase E.
Research: R1 + R2 + R6 + R8 + UI slices 04/05.
- F.1 — GameEvent envelope dispatcher. 94 sub-opcodes in
0xF7B0. Zero handled today. Start withPlayerDescription (0x0013)+ property-update events. Seer08-network-protocol-atlas.md. - F.2 — Item + inventory model.
ItemInstance/Container/PropertyBundle. Appraise round-trip (0x00C8→0x00C9). Burden math. Seer06-items-inventory.md+src/AcDream.Core/Items/. - F.3 — Combat math + damage flow. Damage formula, per-body-part AL, crit, hit-chance sigmoid. Server broadcasts damage events; client displays + HP bar. See
r02-combat-system.md+src/AcDream.Core/Combat/. - F.4 — Spell cast state machine.
SpellCastStateMachine+ active buff tracking. Buffs + recalls first, projectile spells later. Fizzle sigmoid + mana conversion. Seer01-spell-system.md+src/AcDream.Core/Spells/. - F.5 — Core panels. Attributes / Skills / Paperdoll / Inventory / Spellbook — using the retail-ui framework from Phase D.2. See
05-panels.mdunder retail-ui. (TargetsAcDream.UI.Abstractions; unblocked by D.2a — ships with ImGui widgets — and reskinned when D.2b lands.)
Acceptance: equip a weapon, swing at a monster, see damage numbers, buff yourself, recall to the lifestone.
Phase G — World systems
Research: R9 + R12 + R13.
- ✓ SHIPPED — G.1 — Sky + weather + day-night. Deterministic client-side from Portal Year time. Sky dome geometry + keyframe gradients + rain/snow particles. See
r12-weather-daynight.md. Full data + visual stack shipped: Region dat loader, keyframe interp, WeatherSystem with 5-kind PDF + transitions + storm flashes, WorldSession→WorldTimeService sync via ConnectRequest+TimeSync, SkyRenderer with sky-object arcs + UV scroll, rain/snow billboard renderer, F7/F10 debug cycle keys. - ✓ SHIPPED — G.2 — Dynamic lighting. 8-light D3D-style fixed pipeline. Hard-cutoff at Range, no attenuation inside. Cell ambient. Shader UBO per frame. See
r13-dynamic-lighting.md. SceneLightingUbo std140 at binding=1 feeds terrain + mesh + mesh_instanced + sky shaders. LightingHookSink auto-registers Setup.Lights at entity stream-in, flips IsLit on SetLightHook, unregisters on landblock unload. - G.3 — Dungeon streaming + portal space.
EnvCellStreamer, portal-visibility BFS,PlayerTeleport (0xF751)handling withLoginCompletere-send, "pink bubble" loading state. Seer09-dungeon-portal-space.md.
Acceptance: walk outside at dusk, see the sky gradient + sun moving; enter a torch-lit dungeon via portal; leave back to daylight.
Phase H — Social + progression
Research: R7 + R10 + R11 + UI slice 05.
- H.1 — Chat window. UI panel + all 6 wire opcodes (Channel, Tell, System, HearSpeech, HearRangedSpeech, TurbineChat). (Wire layer already shipped per the shipped table; remaining work is the panel, which targets
AcDream.UI.Abstractions— unblocked by D.2a, reskinned when D.2b lands.) - H.2 — Allegiance. Tree model + XP pass-up math + 5 allegiance chat channels + MOTD. See
r11-allegiance.md. - H.3 — Emote scripts + quests + dialogs. 122 EmoteType × 39 Trigger mini-VM. Contract tracker UI. NPC dialog rendered via chat with
<Tell:…>markup. Seer10-quest-dialogs.md. - H.4 — Character creation.
0xE000002 CharGendat + 13 heritages + templates + appearance picker + preview renderer. Seer07-character-creation.md.
Acceptance: create a character from scratch, talk to an NPC, get + complete a quest, gain XP that passes up to the patron.
Phase J — Long-tail (deferred / low-priority)
Not detailed here; each gets its own brainstorm when it becomes relevant.
- Player character full rig (held weapons, spell effects, death/revive animation)
- Group/fellowship UI
- Trade window (multi-player confirms)
- Salvage + tinker UI
- House ownership + hooks
- Society UI
- GM visible tools (we explicitly don't build GM powers; but DEV-mode tools like teleport anywhere are useful)
Phase R — Retail research infrastructure
Goal: sustainable, scalable access to retail-client decompilation — named symbols, struct layouts, wire schemas — so every future port is a 5-second grep instead of 30-minute archaeology.
Sub-pieces:
- ✓ SHIPPED — R.1 — Named-retail corpus committed. Shipped 2026-04-25
(commit
a9a01d8).docs/research/named-retail/{acclient_2013_pseudo_c.txt, acclient.h, acclient.c}+docs/research/data/spells.csv+ vendoredreferences/actestclient/. 1.4 M lines of named pseudo-C (99.6% function naming) + 70K lines of verbatim retail headers + 3,956 spells withFamilyfor buff stacking + machine-readable wire schema inmessages.xml. - ✓ SHIPPED — R.2 — pdb-extract tool + JSON sidecars. Shipped 2026-04-25
(commit
69d884a).tools/pdb-extract/pdb_extract.pyreadsrefs/acclient.pdb(Sept 2013 EoR build) and emitssymbols.json(18,366 named functions) +types.json(5,371 named struct types) todocs/research/named-retail/. Pure Python, no deps, runs in <1 s. - ✓ SHIPPED — R.3 — actestclient vendored. Shipped 2026-04-25 alongside
R.1.
references/actestclient/(covered byreferences/gitignore) includes the canonicalmessages.xmlAC-protocol wire schema.
Acceptance: Step 0 of CLAUDE.md's development workflow points at
named-retail/ first; subsequent issue closures (#6 / #7 / #9 / #11)
all consume this foundation.
Effects on other phases: Issue closures unblocked by Phase R land under their existing letter phases (#6 enchantment buffs → Phase D / F.5 maintenance; #7 PlayerDescription trailer → Phase H.1 / F.2 maintenance). The PDB symbols + headers also accelerate any future port in any phase — no separate listing here.
Cross-cutting work tracked in parallel
- Test coverage. Each phase lands with unit + integration tests in
tests/. Current count: 98 Core + 96 Core.Net = 194. Keep the ratio as new phases land. - Memory files. Project state under
memory/project_phase_*_state.mdis updated when a phase ships.MEMORY.mdis the index. CLAUDE.mddiscipline. Check all four references (ACE, ACViewer, WorldBuilder, Chorizite) before committing to an approach. WorldBuilder is the closest stack match and should be checked first.
Explicitly out of scope
- Server emulation — we use ACE for server, never reimplement.
- Account creation — direct user to ACE tooling.
- Anti-cheat / GM tools / live-ops — irrelevant for personal use.
- Cross-platform support — Windows-only; the dat path assumptions depend on retail Windows install layout. Silk.NET is cross-platform but we don't promise.
- Custom game content — this is a client for existing AC data, not a toolchain.
"When will my specific complaint be fixed?" — quick lookup
| Observation | Phase |
|---|---|
| Drudge statue in wrong pose | 6.3 FIXED ✓ |
| Characters in T-pose / wrong idle | 6.1 FIXED ✓ |
| No breathing on NPCs | 6.4 + sentinel fix FIXED ✓ |
| Lifestone crystal has one side missing | 9.2 FIXED ✓ |
| Ground floor flickering with terrain | 7.1 FIXED ✓ |
| Houses missing second floors / walls | 7.1 FIXED ✓ (interior mesh landed) |
| Character clothing missing / wrong | 5 FIXED ✓ |
| Statue wrong color / wrong scale | 5 FIXED ✓ |
| Holtburg sign half-buried | 5 FIXED ✓ |
| Can't walk past the loaded 3×3 window | A.1 FIXED ✓ (5×5 default, ACDREAM_STREAM_RADIUS to tune) |
| Frame hitch crossing landblock boundary | Phase A.3 (synchronous loader for now; async returns when DatCollection is thread-safe) |
| Walking around doesn't move me on the server | Phase B.3 FIXED ✓ |
| Can't talk to NPCs | Phase H.3 (emote scripts + dialogs) |
| Can't open a door | Phase F (object-use action) |
| Portals render as a rotating black disk | Phase E.3 (particle system) |
| Chimneys have no smoke | Phase E.3 |
| Houses have no fireplace fire | Phase E.3 |
| No fireplace / torch lighting | Phase G.2 (shipped; Setup.Lights auto-register, 8-light cap with hard-cutoff) |
| Skin/hair color slightly off | Phase C.3 |
| No chat window | Phase H.1 |
| No sound | Phase E.2 |
| Dungeons / foundry interior missing | Phase G.3 |
| Can't fight monsters | Phase F.3 (combat math + damage) |
| Can't cast spells | Phase F.4 |
| No inventory panel | Phase F.2 + F.5 |
| No character creation — must use ACE admin | Phase H.4 |
| Sky is a flat color | Phase G.1 (shipped; F7 cycles time, F10 cycles weather) |
| Can't join allegiance | Phase H.2 |
| No quest tracker | Phase H.3 |
If you see something not on this list, add it here and assign a phase.