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

24 KiB
Raw Permalink Blame History

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 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 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 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 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 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 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 6.3K Dat 0xE000002 CharGen; 13 heritages × 330 attr credits × 52 skill credits (Olthoi 68); SpecializedCost is a DELTA; 0xF6560xF643 wire round-trip
R8 Network protocol atlas 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 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 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 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 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 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.