acdream/docs/research/deepdives/00-master-synthesis.md
Erik 3f913f1999 docs+feat: 13 retail-AC deep-dives (R1-R13) + C# port scaffolds + roadmap E-H
78,000 words of grounded, citation-backed research across 13 major AC
subsystems, produced by 13 parallel Opus-4.7 high-effort agents. Plus
compact C# port scaffolds for the top-5 systems and a phase-E-through-H
roadmap update sequencing the work.

Research (docs/research/deepdives/):
- 00-master-synthesis.md          (navigation hub + dependency graph)
- r01-spell-system.md        5.4K words (fizzle sigmoid, 8 tabs, 0x004A wire)
- r02-combat-system.md       5.9K words (damage formula, crit, body table)
- r03-motion-animation.md    8.2K words (450+ commands, 27 hook types)
- r04-vfx-particles.md       5.8K words (13 ParticleType, PhysicsScript)
- r05-audio-sound.md         5.6K words (DirectSound 8, CPU falloff)
- r06-items-inventory.md     7.4K words (ItemType flags, EquipMask 31 slots)
- r07-character-creation.md  6.3K words (CharGen dat, 13 heritages)
- r08-network-protocol-atlas 9.7K words (63+149+94 opcodes mapped)
- r09-dungeon-portal-space.md 6.3K words (EnvCell, PlayerTeleport flow)
- r10-quest-dialogs.md       7.1K words (emote-script VM, 122 actions)
- r11-allegiance.md          5.4K words (tree + XP passup + 5 channels)
- r12-weather-daynight.md    4.5K words (deterministic client-side)
- r13-dynamic-lighting.md    4.9K words (8-light cap, hard Range cutoff)

Every claim cites a FUN_ address, ACE file path, DatReaderWriter type,
or holtburger/ACViewer reference. The master synthesis ties them into a
dependency graph and phase sequence.

Key architectural finding: of 94 GameEvents in the 0xF7B0 envelope,
ZERO are handled today — that's the largest network-protocol gap and
blocks F.2 (items) + F.5 (panels) + H.1 (chat).

C# scaffolds (src/AcDream.Core/):
- Items/ItemInstance.cs    — ItemType/EquipMask enums, ItemInstance,
                             Container, PropertyBundle, BurdenMath
- Spells/SpellModel.cs      — SpellDatEntry, SpellComponentEntry,
                             SpellCastStateMachine, ActiveBuff,
                             SpellMath (fizzle sigmoid + mana cost)
- Combat/CombatModel.cs     — CombatMode/AttackType/DamageType/BodyPart,
                             DamageEvent record, CombatMath (hit-chance
                             sigmoids, power/accuracy mods, damage formula),
                             ArmorBuild
- Audio/AudioModel.cs       — SoundId enum, SoundEntry, WaveData,
                             IAudioEngine / ISoundCache contracts,
                             AudioFalloff (inverse-square)
- Vfx/VfxModel.cs           — 13 ParticleType integrators, EmitterDesc,
                             PhysicsScript + hooks, Particle struct,
                             ParticleEmitter, IParticleSystem contract

All Core-layer data models; platform-backed engines live in AcDream.App.
Compiles clean; 470 tests still pass.

Roadmap (docs/plans/2026-04-11-roadmap.md):
- Phase E — "Feel alive": motion-hooks + audio + VFX
- Phase F — Fight + cast + gear: GameEvent dispatch, inventory,
            combat, spell, core panels
- Phase G — World systems: sky/weather, dynamic lighting, dungeons
- Phase H — Social + progression: chat, allegiance, quests, char creation
- Phase J — Long-tail (renumbered from old Phase E)

Quick-lookup table updated with 10+ new rows mapping observations to
new phase letters.
2026-04-18 10:32:44 +02:00

448 lines
24 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 — Retail AC Deep-Dive Master Synthesis
**Date:** 2026-04-17
**Total research output:** ~78,000 words across 13 deep-dive slices
(plus the retail-UI set from earlier the same day — 30,000 words more).
Each slice is a self-contained 4-9 KLOC document of research +
pseudocode + C# port plan, with every claim cited to a decompiled
`FUN_` address or an ACE / DatReaderWriter / holtburger / ACViewer
reference.
This document is the navigation hub and cross-reference map. It does
NOT repeat each slice's findings; it summarizes the headline, lists
cross-system dependencies, and proposes the concrete acdream phase
sequence that falls out of the research.
---
## 1. Slice inventory
| ID | Topic | File | Words | Key finding |
|-----|---------------------------------|--------------------------------------------------------------|-------|-------------|
| R1 | Spell system | [r01-spell-system.md](r01-spell-system.md) | 5.4K | Sigmoid `1/(1+e^(-0.07·(skill-difficulty)))` fizzle curve; 8 spellbook tabs at panel offset `0x638+0x1C·tab`; spell `0x004A`/`0x0048` wire; spell book unlock via `UpdateSpell (0x02C1)` |
| R2 | Combat | [r02-combat-system.md](r02-combat-system.md) | 5.9K | `PowerMod = Level + 0.5` melee; physical logistic at `k=0.03` / magic at `k=0.07`; 12-quadrant body table; 7 damage types × layered AL; 10%/5% base crit |
| R3 | Motion + animation | [r03-motion-animation.md](r03-motion-animation.md) | 8.2K | 450+ motion commands; cycle key `(style<<16)\|(cmd & 0xFFFFFF)`; 27 hook types; no crossfade — link animations ARE the transition; `-0.65` backward factor; `1.5×` run-turn |
| R4 | VFX / particles | [r04-vfx-particles.md](r04-vfx-particles.md) | 5.8K | 13 ParticleType motion integrators; no flipbook (chain hooks instead); PlayScript enum has 174 values; `PhysicsScriptTable` mod-selection; WorldBuilder's `ParticleBatcher` ports directly |
| R5 | Audio | [r05-audio-sound.md](r05-audio-sound.md) | 5.6K | DirectSound 8 + WinMM MIDI; 16-voice cap; inverse-square CPU falloff (no doppler/cone/HRTF); 204 Sound IDs; motion-driven triggers via animation hooks 1/2/21 |
| R6 | Items + inventory | [r06-items-inventory.md](r06-items-inventory.md) | 7.4K | ItemType is `[Flags]` 32-bit; 31 EquipMask slots; 7 property tables; `Appraise` C2S `0x00C8` / S2C `0x00C9`; burden = 150·STR + STR·bonusBurden; 2-deep pack depth |
| R7 | Character creation | [r07-character-creation.md](r07-character-creation.md) | 6.3K | Dat `0xE000002 CharGen`; 13 heritages × 330 attr credits × 52 skill credits (Olthoi 68); SpecializedCost is a DELTA; `0xF656``0xF643` wire round-trip |
| R8 | Network protocol atlas | [r08-network-protocol-atlas.md](r08-network-protocol-atlas.md) | 9.7K | 63 primary GameMessages + 149 GameActions + 94 GameEvents mapped. Of GameEvents (S→C, 0xF7B0 envelope), **zero handled** today — biggest gap |
| R9 | Dungeon + portal space | [r09-dungeon-portal-space.md](r09-dungeon-portal-space.md) | 6.3K | Dungeon detect = all heights 0 & NumCells>0 & no Buildings; `PlayerTeleport (0xF751)` needs LoginComplete re-send; no loading screen — "pink bubble" hides avatar |
| R10 | Quest + NPC dialogs | [r10-quest-dialogs.md](r10-quest-dialogs.md) | 7.1K | "Quests" are emote-script trees, not a first-class system; 122 EmoteType × 39 EmoteCategory; contract tracker via `0x0314/0x0315`; dialog = chat message with `<Tell:...>` markup |
| R11 | Allegiance | [r11-allegiance.md](r11-allegiance.md) | 5.4K | Max 11 direct vassals; rank `max(lower+1, higher)` capped 10; XP passup `50+22.5·loyalty/291·(1+RT/730·IG/720)`; no swear cooldown (24h applies to name only) |
| R12 | Weather + day/night | [r12-weather-daynight.md](r12-weather-daynight.md) | 4.5K | 95% client-side — server just sends Portal Year time; determinism = same sky everywhere; no `SetWeather` opcode; sky is geometry not shader ramp |
| R13 | Dynamic lighting | [r13-dynamic-lighting.md](r13-dynamic-lighting.md) | 4.9K | Hard 8-light cap (fixed function D3D); NO distance attenuation inside Range then hard cutoff; terrain baked per-vertex via `AdjustPlanes`; blob shadow at `0x0600102F` |
**Grand total: 82,500 words of grounded, citation-backed research.**
---
## 2. The big picture — how the systems wire together
```
┌─────────────────────────────────────────────────────────────────┐
│ ACE (Asheron's Call Emulator) │
│ — server authority │
└────┬────────────────────────────────────────────────────────────┘
│ UDP packets (ISAAC, fragmented, ack'd)
┌────▼────────────────────────────────────────────────────────────┐
│ WorldSession (R8 atlas) │
│ • Login (4 msg), CharList, EnterWorld, CreateObject stream │
│ • Dispatch of 63 + 94 + 149 opcodes │
└────┬──────────────┬──────────────┬──────────────┬───────────────┘
│ │ │ │
│CreateObject │UpdateMotion │UpdateHealth │UpdateSpell
│ items │ anim │ combat │ buff/debuff
▼ ▼ ▼ ▼
┌──────────┐ ┌───────────┐ ┌──────────┐ ┌───────────┐
│ Inventory│ │ Motion │ │ Combat │ │ Spell │
│ (R6) │ │ (R3) │ │ (R2) │ │ (R1) │
│ │ │ │ │ │ │ │
│ItemInst │──│ DoMotion │──│ Damage │──│ ActiveBuf │
│Container │ │ MotionTbl │ │ fromCmd │ │ Fizzle │
│Burden │ │ Hooks ────┼──┤ FootStep │ │ Recall │
└────┬─────┘ └─┬────┬────┘ └────┬─────┘ └────┬──────┘
│ │ │ │ │
│ │ └────hooks──►│ │
│ │ │ │
└──────────┴───────►┌────────▼─────────────▼──┐
│ Audio (R5) + │
│ VFX/Particles (R4) │
│ — cosmetic layer │
└──────────────┬──────────┘
┌───────────────────────────────┐
│ UI (retail-ui set) + HUD │
│ AttrPanel + SpellBar + Chat │
│ VitalOrbs + Radar + Compass │
│ (all behind UiRoot scaffold) │
└───────────────────────────────┘
┌─ World lifecycle
┌───▼─────────────────────┐
│ Streaming (existing) │
├─────────────────────────┤
│ + Dungeon / portal (R9) │
│ + Weather sky (R12) │
│ + Dynamic lights (R13) │
└─────────────────────────┘
┌─ Social / progression
┌──────────────────┐ ┌─────────────────┐
│ Allegiance (R11) │ │ Quest + dialog │
│ • Tree + ranks │ │ (R10) │
│ • XP passup │ │ • Emote scripts │
│ • Chat channels │ │ • Contract tkr │
└──────────────────┘ └─────────────────┘
┌─ Game entry
┌──────────────────┐
│ CharCreate (R7) │
│ • Heritage + skl │
│ • Appearance │
│ • Starting town │
└──────────────────┘
```
---
## 3. Critical cross-system dependencies
These are the places where one system MUST be built before another can
land cleanly. They define the port sequence.
### 3.1 Motion (R3) blocks three other systems
- **Audio (R5)** — footstep/swing/cast sounds are triggered by
AnimationHooks (types 1=Sound, 2=SoundTable, 21=SoundTweaked). Without
the hook dispatcher expanded (R3 port plan), audio has no trigger
source beyond server-pushed `PlaySound (0xF750)`.
- **VFX (R4)** — spell release, weapon trail, footstep dust attach at
specific animation hook frames (`CreateParticleHook`, hook type 18).
- **Combat (R2)** — the damage application frame is an `AttackFrame`
hook (type 20) inside the attack animation. Without R3 hook
dispatch, combat math has to guess timing.
**Implication:** R3 motion-hook expansion is a blocker for R2, R4, R5
to feel retail-faithful. It's a prerequisite for "the game feels
alive".
### 3.2 Inventory (R6) blocks three UI panels
- **Paperdoll** — drops items into slots; requires `ItemInstance` model.
- **Spellbook (R1)** — items like scarabs are consumed via R6 burden rules.
- **Quest turn-in (R10)** — emote's "Give" trigger needs item ID +
property bundle to validate.
**Implication:** R6 is the data-model foundation for any gameplay UI.
### 3.3 Network (R8) is the permanent bottleneck
Of 94 GameEvents (0xF7B0 envelope), **zero are handled today**. These
include:
- `PlayerDescription (0x0013)` — full character at login
- `AllegianceInfoResponse (0x007E)`
- `Fellowship*` events (5 opcodes)
- `Identify/Appraise response (0x00C9)`
- `SendClientContractTracker (0x0315)`
**Implication:** R8 Phase D (chat + session health) is the unlocking
step for the whole social/quest/inventory stack.
### 3.4 CharCreate (R7) needs CharGen dat + at least one class
The CharGen `0xE000002` dat has every heritage + template + appearance
config. But we also need:
- `ObjDesc` application pipeline (already in our StaticObjectManager)
- At least one working panel to host the UI (R7 uses our UiRoot scaffold)
- Appearance preview renderer — already works for outdoor characters
**Implication:** R7 is the smallest unblocker for "user makes a char
in acdream instead of using ACE admin tools".
### 3.5 Dungeon (R9) extends existing streaming
R9's `EnvCellStreamer` + `PortalVisibility` + `TeleportController` are
additive to `StreamingController`. Risk is low.
### 3.6 Weather (R12) and Lighting (R13) share a scene-state UBO
Both write sun direction + ambient color + fog. A single
`SceneLightingState` UBO fed to `terrain.frag` and `mesh.frag`
consolidates them. R13 reads it; R12 produces it.
### 3.7 VFX (R4) + Audio (R5) share PhysicsScript/PlayScript
Retail's `PlayEffect (0xF755)` bundles both particle + sound. Our
`PhysicsScript` dispatcher should fire both R4 and R5 hooks atomically.
---
## 4. Proposed phase sequence
Based on the dependency graph + what unlocks the most gameplay fastest:
### Phase E — Core gameplay loop (highest value)
| Step | What | Research | Unblocks |
|------|--------------------------------------------------------------------|----------|----------|
| E.1 | R3 Motion hooks expansion | R3 | E.2-E.4 |
| E.2 | R5 Audio engine + motion-hook wiring | R5 | immediate feel |
| E.3 | R4 Particle system + motion-hook wiring + PlayScript dispatcher | R4 | immediate feel |
| E.4 | R2 Combat math + server-broadcast damage/health | R2, R8 | can actually fight |
| E.5 | R1 Spell cast state machine (buffs + recalls first, projectiles later) | R1, R8 | can cast spells |
**Acceptance:** player swings a sword, hears the whoosh, sees the
contact spark, damage number floats up, HP bar drops on the target,
monster dies with footstep/impact sounds. Spell buff lands with
glowing aura + cast sound.
### Phase F — Inventory + UI panels
| Step | What | Research | Unblocks |
|------|--------------------------------------------------------------------|----------|----------|
| F.1 | R8 GameEvent envelope (0xF7B0) dispatcher | R8 | F.2+ |
| F.2 | R6 Item model (`ItemInstance`, `PropertyBundle`) | R6 | F.3-F.5 |
| F.3 | Attributes panel (UI slice 05 + R8 `PlayerDescription`) | UI05, R8 | char sheet |
| F.4 | Paperdoll + Inventory panel (drag-drop from UI slice 04) | R6, UI04 | gearing up |
| F.5 | Spellbook panel (R1 tabs + icons) | R1, UI05 | cast via UI |
**Acceptance:** opens all core panels, drags items between inventory
+ paperdoll, casts spells by clicking icons.
### Phase G — World systems
| Step | What | Research |
|------|--------------------------------------------------------------------|----------|
| G.1 | R12 Sky / weather / day-night | R12 |
| G.2 | R13 Dynamic lighting (8-light fixed pipeline) | R13 |
| G.3 | R9 Dungeon streaming + portal transition | R9 |
**Acceptance:** walk out of Holtburg at dusk, sky gradient rolls,
torches cast light, enter a dungeon via teleport, see the dungeon
interior.
### Phase H — Social + progression
| Step | What | Research |
|------|------------------------------------------------|----------|
| H.1 | Chat window (UI slice 05) + all 6 wire ops | UI05, R8 |
| H.2 | R11 Allegiance panel + XP passup display | R11 |
| H.3 | R10 Quest/emote/dialog system | R10 |
| H.4 | R7 Character creation panel | R7 |
**Acceptance:** talk to an NPC, get a quest, complete it, gain XP,
allegiance MOTD shows in chat.
---
## 5. What's already shipped vs what R-slices unlock
| Domain | Shipped | Next from deep-dives |
|-------------------------|-----------------------------------------------------------|----------------------|
| World rendering | Terrain + static meshes + scenery + animation + chase cam | R12 sky / R13 lights |
| Streaming | 5×5 landblock window + EnvCell walker | R9 dungeons |
| Login + wire transport | LoginRequest → EnterWorld → CreateObject stream | R8 GameEvent envelope|
| Physics / collision | Retail-faithful BSP + cylinder + sphere-sweep + scenery | R3 motion hooks |
| Input / UI | UI framework (retail-ui set) + debug overlay | R4 VFX + R5 audio panels |
| Movement | WASD + chase cam + jump + autonomous-position sync | R3 motion commands |
| Character appearance | ObjDesc + creature palette + hair/skin/clothing | R7 char-create panel |
| **Everything else** | — | R1/R2/R6/R10/R11 |
---
## 6. Consolidated dat-ID catalog (cross-slice)
Every dat range touched by the 13 slices, de-duplicated:
| Range | DBObjType | Source slices |
|-----------------------------|-------------------|---------------|
| `0x02xxxxxx` | Setup | (existing) |
| `0x04xxxxxx` | Palette | UI04 |
| `0x05xxxxxx` | PaletteSet | UI04 |
| `0x06000000..0x06FFFFFF` | RenderSurface | UI03/UI06, R13 blob shadow `0x0600102F` |
| `0x07xxxxxx` | RenderSurface | UI04 |
| `0x08xxxxxx` | Surface | UI04 |
| `0x09xxxxxx` | SurfaceTexture | (existing) |
| `0x0A000000..0x0A00FFFF` | Wave | **R5 audio** |
| `0x0E000002` | CharGen | **R7 chargen**|
| `0x0F000000..0x0FFFFFFF` | SurfaceMaterial | UI04 |
| `0x13000000` | Region | (existing) + R12 sky + R13 lights |
| `0x14xxxxxx` | MasterInputMap | UI06 |
| `0x20000000..0x2000FFFF` | SoundTable | **R5 audio** |
| `0x21xxxxxx` | LayoutDesc | UI06 |
| `0x23/0x24xxxxxx` | StringTable | UI06 |
| `0x2Fxxxxxx` | SpellTable | **R1 spell** |
| `0x30xxxxxx` | SpellComponents | **R1 spell** |
| `0x33xxxxxx` | MotionTable | (existing) + R3 |
| `0x34000000..0x34000FFF` | Animation | (existing) + R3 |
| `0x40000000..0x40000FFF` | Font | UI03 |
| `0x41xxxxxx` | LanguageInfo | UI06 |
---
## 7. Consolidated opcode quick-reference (cross-slice)
Every opcode mentioned in any slice, for rapid grep-back:
```
Login flow
0x0001 LoginRequest
0xF7B1 GameAction envelope (C→S) ← 149 sub-opcodes
0xF7B0 GameEvent envelope (S→C) ← 94 sub-opcodes
0xF657 CharacterList
0xF656 Character_SendCharGenResult (R7)
0xF643 CharGenResponseType / CharacterError (R7)
Movement (B.3 already ported)
0xF74C MoveToState / UpdatePosition (partial overlap)
0xF753 Jump / bi-directional
0xF748 UpdateMotion (R3)
0xF751 PlayerTeleport (R9)
Combat (R2)
0x0008 AttackTargetRequest
0x000A CombatStyleRequest
0x0053 TargetAttack
0x01B7 MissileAttack
0xF7xx UpdateHealth / UpdateVital (R2, R6 vitals)
Spells (R1)
0x0048 Magic_CastUntargetedSpell (R1)
0x004A Magic_CastTargetedSpell (R1)
0x02C1 UpdateSpell (spellbook add) (R1)
0x02C2-0x02C8 Enchantment lifecycle (R1)
0x02BB HearSpeech (chatType 0x11 = syllables) (R1)
Inventory / items (R6)
0x00C8 AppraiseRequest (R6)
0x00C9 IdentifyResponse (R6)
0xF7xx InventoryMove / Give / Drop / Pickup
Chat (UI05)
0xF7B0 GameEventChannelBroadcast (0x0147 / envelope)
0xF7B0 GameEventTell (0x02BD)
0xF7E0 GameMessageSystemChat
0x02BB GameMessageHearSpeech
0x02BC GameMessageHearRangedSpeech
0xF7DE GameMessageTurbineChat
0x0295 GameEventSetTurbineChatChannels
Allegiance (R11)
0x001D Swear
0x001E Break
0x007E AllegianceInfoResponse
0x00DD AllegianceMotd
0x02AB AllegianceRecall action
Quest / contracts (R10)
0x0314 SendClientContractTrackerTable
0x0315 SendClientContractTracker
0xF751 TeleportToPoi (quest-driven recall)
Audio (R5)
0xF750 PlaySound
0xF755 PlayEffect (R4 + R5 bundle)
Dungeon / portal (R9)
0xF751 PlayerTeleport (R9)
0x00A1 LoginComplete (re-send after teleport)
Attributes (UI05)
0x02E3 PrivateUpdateAttribute
0x02E7 PrivateUpdateVital
0x02E9 PrivateUpdateAttribute2ndLevel
Admin / world
0xEA60 AdminEnvirons (colored-fog override) (R12)
```
**Full table in `r08-network-protocol-atlas.md`.**
---
## 8. Open questions that surfaced
1. **keystone.dll** — blocking for truly retail-faithful widget layout.
Would need a second decompile pass. (UI slice 02)
2. **Launcher / patcher** — similarly binary-only. (out of scope)
3. **Retail fizzle mana** — R1 flagged "5 points lost on fizzle" as
tentative; would benefit from retail packet capture.
4. **Power bar timing** — R2 notes the power bar fills over some
seconds, but exact seconds unclear in decompile.
5. **Doppler on / off** — R5 says off, but this is inferred from no
`SetFrequency` on 3D buffers. Verify with retail binary trace if
audio fidelity matters later.
6. **Sky replace animation** — R12 notes `SkyObjReplace` governs dawn
mesh swap but keyframe interp unclear.
7. **Contract tracker reward delivery** — R10 notes the
`SendClientContractTrackerTable` format but quest rewards come via
a separate emote path.
8. **Allegiance passup IG/RT decay** — R11 has the XP formula but the
"generation tax" (grandpatron vs direct patron) needs a golden-value
conformance test against ACE.
---
## 9. Risk assessment for each slice's port
Low (data models + straightforward translation):
- R6 Inventory (well-typed properties + containers)
- R7 CharCreate (one dat object, one wire roundtrip)
- R8 Protocol atlas (additive handlers; Phase-F work)
- R11 Allegiance (data + math, no renderer work)
- R12 Weather (deterministic from clock)
Medium (has math or subtle corner cases):
- R1 Spell (sigmoid fizzle, mana conversion, enchant stacking)
- R2 Combat (damage formula sensitivity, crit tables, body-part)
- R3 Motion hooks (27 types, delivery during frame advance)
- R5 Audio (inverse-square falloff, 16-voice eviction)
- R9 Dungeon (portal visibility + teleport state machine)
- R13 Lighting (8-light selection + attenuation curve fidelity)
High (novel systems for us):
- R4 VFX particle systems (new renderer subsystem)
- R10 Quest / emote scripts (mini-VM with 122 action types)
---
## 10. Port sequencing recommendation
If the user wants one-and-only-one focus per week:
- **Week 1 — "Feel alive":** R3 motion hooks → R5 audio → R4 VFX.
Ship: footsteps, swing sounds, impact particles, spell aura particle.
- **Week 2 — "Fight":** R2 combat math + R8 GameEvent envelope
dispatcher (a few critical events). Ship: actual damage flow, HP
updates, death.
- **Week 3 — "Cast":** R1 spell cast state machine (buffs + recall
first, projectile spells later). Ship: heal spell works, buff spell
works, recall spell works.
- **Week 4 — "Have gear":** R6 inventory + Attributes + Paperdoll
panels. Ship: equip weapon, see stats, manage pack contents.
- **Week 5 — "World":** R12 sky + R13 lights + R9 dungeon.
Ship: enter a dungeon, see torch lights, day/night outside.
- **Week 6 — "Social":** Chat + R11 allegiance + R10 quest +
R7 char-create. Ship: complete the loop.
If the user wants parallel work: R3/R5/R4 triad can be one stream;
R6/R8 infra can be a parallel stream; R12/R13 visual can be a third.
---
## 11. Plugin API implications
The deep-dives surfaced several places where acdream's plugin API
needs to expose state (R6 item, R1 spell, R11 allegiance, R10 quest).
These are all pure data + event streams, no 3D rendering hooks. The
current `IWorldGameState` + `IEvents` architecture scales to all of
them — each system adds a new read-only interface + an event stream.
Deferred to a separate phase (plugin-api-expansion) once the core
systems land.