From d9513048759ecb7fe7dfb2785204c91f8919228c Mon Sep 17 00:00:00 2001 From: Erik Date: Sat, 18 Apr 2026 13:24:11 +0200 Subject: [PATCH] memory: capture full 2026-04-17 session + permanent research index MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Two memory files landed: 1. Updated memory/project_session_2026_04_17.md — covers all three commits today: - ff325ab debug overlay + mouse controls - 7230c15 retail UI research + C# scaffold - 3f913f1 13-slice deep-dive marathon + scaffolds + roadmap Includes the "what to build tomorrow" lookup table, the architectural headline findings, and session lessons (Opus-4.7 parallel swarms are worth the cost; keystone.dll landmine; GameEvent dispatcher is the biggest network gap). 2. New memory/project_retail_research_index.md — permanent index for the 20 research docs (6 UI slices + 13 subsystem slices). Quick- lookup table "use this slice when you're doing X". Also captures the critical cross-cutting findings (architecture, wire, dat ranges) and already-extracted retail-faithful formulas for instant reference. This file is the standing invariant: before writing any retail-AC- specific code, open it first to find the matching slice. --- memory/project_retail_research_index.md | 121 ++++++++++++++++ memory/project_session_2026_04_17.md | 181 +++++++++++------------- 2 files changed, 207 insertions(+), 95 deletions(-) create mode 100644 memory/project_retail_research_index.md diff --git a/memory/project_retail_research_index.md b/memory/project_retail_research_index.md new file mode 100644 index 0000000..bdc21db --- /dev/null +++ b/memory/project_retail_research_index.md @@ -0,0 +1,121 @@ +# Retail AC research index — permanent lookup table + +Written 2026-04-17. Points at the 20 research documents produced in +that day's dual-swarm marathon (6 UI agents + 13 subsystem agents, +all Opus-4.7 high-effort). + +**When to use:** any time you're about to write code for a retail AC +subsystem. Open the slice for that subsystem BEFORE writing the first +line — every slice has pseudocode + C# port sketch + citations. + +--- + +## UI layer (`docs/research/retail-ui/`) — 6 slices, ~30,000 words + +| ID | File | Use when… | +|----|------|-----------| +| — | [`00-master-synthesis.md`](../docs/research/retail-ui/00-master-synthesis.md) | First read. Has cross-references + port decisions | +| 01 | [`01-architecture-and-init.md`](../docs/research/retail-ui/01-architecture-and-init.md) | Extending GameWindow's init flow or main loop | +| 02 | [`02-class-hierarchy.md`](../docs/research/retail-ui/02-class-hierarchy.md) | Adding new widget types to our UI toolkit | +| 03 | [`03-rendering.md`](../docs/research/retail-ui/03-rendering.md) | Building AcFont from portal.dat, dat sprites, scissor | +| 04 | [`04-input-events.md`](../docs/research/retail-ui/04-input-events.md) | Adding drag-drop, tooltip, focus, modal | +| 05 | [`05-panels.md`](../docs/research/retail-ui/05-panels.md) | Porting chat, attributes, paperdoll, spellbook, inv | +| 06 | [`06-hud-and-assets.md`](../docs/research/retail-ui/06-hud-and-assets.md) | Vital orbs, radar, compass, any dat asset lookup | + +## Subsystems (`docs/research/deepdives/`) — 13 slices, ~78,000 words + +| ID | File | Use when… | +|-----|------|-----------| +| — | [`00-master-synthesis.md`](../docs/research/deepdives/00-master-synthesis.md) | First read. Has the full dependency graph + phase sequence | +| R1 | [`r01-spell-system.md`](../docs/research/deepdives/r01-spell-system.md) | Implementing cast flow, fizzle, mana cost, buffs, recalls | +| R2 | [`r02-combat-system.md`](../docs/research/deepdives/r02-combat-system.md) | Damage formula, hit-chance, crit, body-part targeting | +| R3 | [`r03-motion-animation.md`](../docs/research/deepdives/r03-motion-animation.md) | Expanding MotionInterpreter, hook delivery, stance blends | +| R4 | [`r04-vfx-particles.md`](../docs/research/deepdives/r04-vfx-particles.md) | Building the particle system, PhysicsScript dispatch | +| R5 | [`r05-audio-sound.md`](../docs/research/deepdives/r05-audio-sound.md) | Audio engine, SoundTable + Wave loaders, 3D falloff | +| R6 | [`r06-items-inventory.md`](../docs/research/deepdives/r06-items-inventory.md) | Item model, Container, Appraise, burden, stack-split | +| R7 | [`r07-character-creation.md`](../docs/research/deepdives/r07-character-creation.md) | Char-creation panel, heritages, skill credits | +| R8 | [`r08-network-protocol-atlas.md`](../docs/research/deepdives/r08-network-protocol-atlas.md) | Anything wire-format. Complete opcode map. | +| R9 | [`r09-dungeon-portal-space.md`](../docs/research/deepdives/r09-dungeon-portal-space.md) | Dungeon streaming, PlayerTeleport flow, portal visibility | +| R10 | [`r10-quest-dialogs.md`](../docs/research/deepdives/r10-quest-dialogs.md) | Emote scripts, NPC dialog, quest timers, contract tracker | +| R11 | [`r11-allegiance.md`](../docs/research/deepdives/r11-allegiance.md) | Allegiance tree, XP passup, allegiance chat channels | +| R12 | [`r12-weather-daynight.md`](../docs/research/deepdives/r12-weather-daynight.md) | Sky dome, day/night, rain/snow, Portal Year clock | +| R13 | [`r13-dynamic-lighting.md`](../docs/research/deepdives/r13-dynamic-lighting.md) | LightInfo dat, 8-light cap, cell ambient, blob shadow | + +--- + +## Existing research from prior sessions (separate from these 20) + +- [`docs/research/acclient_function_map.md`](../docs/research/acclient_function_map.md) — already-mapped FUN_ addresses (physics, motion, terrain, landblock) +- [`docs/research/2026-04-12-movement-deep-dive.md`](../docs/research/2026-04-12-movement-deep-dive.md) — cross-client movement cross-check +- [`docs/research/2026-04-13-phase-audit.md`](../docs/research/2026-04-13-phase-audit.md) — audit of decompile-verified vs guessed AC-specific code + +--- + +## Critical cross-cutting findings (quick reference) + +### Architecture facts +- **Retail UI runs in `keystone.dll`**, not `acclient.exe`. Own-toolkit + approach is the only viable path. Use retail event codes (0x01, 0x15, + 0x3E, 0x201) so hand-ported panel code translates cleanly. +- **Weather is client-deterministic from Portal Year time.** No + `SetWeather` opcode exists. Same clock everywhere → same sky everywhere. +- **Lighting is D3D fixed-function, 8-light cap**, no attenuation inside + Range then hard cutoff. Terrain baked per-vertex via `AdjustPlanes`. +- **Motion hooks drive audio + VFX + combat timing.** R3 motion-hook + expansion is the blocker for R2, R4, R5 to feel retail-faithful. + +### Wire protocol facts +- Of 94 GameEvents (S→C envelope `0xF7B0`), **0 are handled today**. + Biggest network gap. +- GameMessage `0xF7E0` SystemChat, `0xF7DE` TurbineChat, `0xF748` + UpdateMotion, `0xF751` PlayerTeleport, `0xF750` PlaySound, `0xF755` + PlayEffect are all unhandled. +- LoginComplete (`0x00A1`) must be re-sent after `PlayerTeleport`. + +### Dat-ID ranges (de-duplicated across all 20 docs) + +| Range | Type | Used by | +|---|---|---| +| `0x0A000000..0x0A00FFFF` | Wave | R5 | +| `0x20000000..0x2000FFFF` | SoundTable | R5 | +| `0x0E000002` | CharGen | R7 | +| `0x2F…` | SpellTable | R1 | +| `0x30…` | SpellComponentsTable | R1 | +| `0x40000000..0x40000FFF` | Font | UI03 | +| `0x06……` | RenderSurface | UI03, UI06, R13 shadow `0x0600102F` | +| `0x21…` | LayoutDesc | UI06 | +| `0x14…` | MasterInputMap | UI06 | + +### Retail-faithful formulas already extracted + +``` +// Spell fizzle (R1) +chance = 1 / (1 + exp(-0.07 * (skill - difficulty))) // 0 if skill < diff-50 + +// Hit chance physical (R2) +chance = 1 - 1 / (1 + exp(0.03 * (attackSkill - defenseSkill))) + +// Hit chance magic (R2) +chance = 1 - 1 / (1 + exp(0.07 * (attackSkill - defenseSkill))) + +// Burden max (R6) +max = 150 * Strength + Strength * bonusBurden + +// Audio falloff (R5) +att = (minDist^2) / (dist^2) (clamped 0..1, no doppler/cone/HRTF) + +// Allegiance XP passup (R11) +direct = 50 + 22.5 * loyalty/291 * (1 + RT/730 * IG/720) +indirect = 16 + 8.0 * loyalty/291 * (1 + RT/730 * IG/720) +``` + +--- + +## Standing invariant for future sessions + +**Before writing any retail-AC-specific code**, grep this index for the +subsystem and open the matching slice. The sliceds give you pseudocode + +C# port sketch + citations — you'll save hours and avoid hallucinating +constants. If the subsystem isn't in the 20 slices, add it to the +roadmap and consider dispatching an Opus-agent research pass for it +before coding. diff --git a/memory/project_session_2026_04_17.md b/memory/project_session_2026_04_17.md index df6e462..5ae7cc4 100644 --- a/memory/project_session_2026_04_17.md +++ b/memory/project_session_2026_04_17.md @@ -1,113 +1,104 @@ -# Session 2026-04-17 — Debug Overlay + Control Tuning +# Session 2026-04-17 — Debug overlay → full-day retail-AC research marathon -## Headline result +## Timeline (morning → afternoon) -**On-screen HUD overlay and refined input controls for the dev client.** -- TTF-based font atlas rendered via stb_truetype -- Screen-space text + rect batcher (`TextRenderer`) -- Composite overlay with panels for position / heading / collision / - FPS / compass / keybind help -- Per-mode mouse sensitivity (Chase, Fly, Orbit) -- RMB-held free-orbit around the player (no snap-back on release) -- Mouse-wheel zoom in chase mode -- Extended chase pitch range so mouse-Y moves both ways +1. **Morning** — Debug overlay (TTF atlas + text batcher + HUD panels) + and input-control tuning (per-mode sensitivity, RMB free-orbit, wheel + zoom, F8/F9 sensitivity). Shipped in commit `ff325ab`. +2. **Midday** — User requested a deep investigation of the retail AC + client's GUI subsystem. Dispatched 6 parallel Opus-4.7 high-effort + agents, produced a 30,000-word research bundle + C# UI scaffold. + Shipped in commit `7230c15`. +3. **Afternoon** — User asked to research **all** remaining major AC + subsystems (R1-R13) while they were AFK for 2 hours. Dispatched 13 + parallel Opus-4.7 agents, produced a 78,000-word research bundle + + master synthesis + 5 C# port scaffolds + rewritten roadmap. + Shipped in commit `3f913f1`. -## Files added +## What shipped today — three commits on main -- `src/AcDream.App/Rendering/BitmapFont.cs` — TTF atlas (stb_truetype) -- `src/AcDream.App/Rendering/TextRenderer.cs` — 2D quad batcher for text + rects -- `src/AcDream.App/Rendering/DebugOverlay.cs` — composed HUD panels -- `src/AcDream.App/Rendering/Shaders/ui_text.{vert,frag}` — ortho-proj text shader -- `src/AcDream.App/Rendering/Shaders/debug_line.{vert,frag}` — wireframe shader - (carried from yesterday's scenery-alignment session but not committed then) +| Commit | Title | Insert | +|-----------|------------------------------------------------------------|--------| +| `ff325ab` | feat(ui): debug overlay + refined input controls | 2,725 | +| `7230c15` | docs+feat(ui): retail UI deep-dive research + C# scaffold | 8,042 | +| `3f913f1` | docs+feat: 13 retail-AC deep-dives + scaffolds + roadmap | 15,312 | -## Files modified +**Total 26,079 lines added, 262 deleted, 55 new files.** All three +commits green on build + 470 tests. -- `src/AcDream.App/AcDream.App.csproj` — added `StbTrueTypeSharp` 1.26.12 -- `src/AcDream.App/Rendering/Shader.cs` — added `SetVec2` / `SetVec4` -- `src/AcDream.App/Rendering/ChaseCamera.cs` - - Added `YawOffset` for RMB free-orbit - - Added `AdjustDistance` for mouse-wheel zoom - - Widened pitch clamp from `[0.05, 1.4]` to `[-0.7, 1.4]` - (mouse-Y now moves camera in both directions from neutral) - - `DistanceMin=2f`, `DistanceMax=40f` zoom envelope -- `src/AcDream.App/Rendering/GameWindow.cs` - - Field block: `_textRenderer`, `_debugFont`, `_debugOverlay`, - `_sensChase/_sensFly/_sensOrbit`, `_rmbHeld`, `_lastFps`, `_lastFrameMs` - - OnLoad: load Consolas → BitmapFont → TextRenderer → DebugOverlay - (silently skips if no system font) - - Keyboard: F1/F2/F4/F5/F6 panel toggles; F8/F9 sensitivity - (multiplicative ×1.2 steps, per-mode) - - Mouse: MouseDown / MouseUp track RMB; MouseMove routes to the - active mode's sensitivity; RMB release does NOT snap YawOffset - - OnRender: snapshot builder (player pos, heading, nearest-obj dist, - colliding flag) passed to `DebugOverlay.Draw` +## Key files to know -## Yesterday's scenery work (finally committed in this session's commit) +### Research (the goldmine) -The untracked files show that yesterday's scenery-alignment fixes lived -on disk but hadn't been committed. This session's commit includes: -- `src/AcDream.Core/Physics/BSPQuery.cs` — `localToWorld` rotation params -- `src/AcDream.Core/Physics/PhysicsDataCache.cs` — `GfxObjVisualBounds` -- `src/AcDream.Core/Physics/ShadowObjectRegistry.cs` — `Scale` + debug iter -- `src/AcDream.Core/Physics/TransitionTypes.cs` — rewritten cylinder / BSP -- `src/AcDream.Core/World/SceneryGenerator.cs` — 64-cell, ACViewer OnRoad, - baseLoc + set_heading rotation -- `src/AcDream.Core/World/WorldEntity.cs` — `Scale` field +- **`docs/research/deepdives/00-master-synthesis.md`** — start here. Nav + hub for all 13 deep-dive slices; has the dependency graph and phase + sequencing (E/F/G/H). +- **`docs/research/deepdives/r01-…-r13-…`** — 13 subsystem deep-dives, + 78,000 words total, every claim cited. +- **`docs/research/retail-ui/00-master-synthesis.md`** — UI framework + synthesis. 6 slice docs total, ~30,000 words. +- **`memory/project_retail_research_index.md`** — permanent quick-lookup + index for all 20 research docs. -## Sensitivity defaults (current) +### C# scaffolds (what to build on) -| Mode | Default | F8 step | F9 step | -|-------|---------|-------------|-----------| -| Chase | 0.15x | ÷ 1.2 | × 1.2 | -| Fly | 1.0x | ÷ 1.2 | × 1.2 | -| Orbit | 1.0x | ÷ 1.2 | × 1.2 | +- `src/AcDream.App/UI/` — retail-style widget toolkit (`UiRoot`, + `UiElement`, `UiPanel`, `UiHost`, event types matching retail codes) +- `src/AcDream.Core/Items/ItemInstance.cs` — R6 inventory data model +- `src/AcDream.Core/Spells/SpellModel.cs` — R1 spell cast state machine +- `src/AcDream.Core/Combat/CombatModel.cs` — R2 damage math +- `src/AcDream.Core/Audio/AudioModel.cs` — R5 audio interfaces +- `src/AcDream.Core/Vfx/VfxModel.cs` — R4 particle data model -Effective rate at chase 0.15x: `0.15 × 0.003 rad/px = 0.00045 rad/px` -≈ 0.026°/pixel. 1000 pixels → 26° rotation. +### Updated -Fly at 1.0x is `0.003 rad/px` ≈ 0.172°/px. +- `docs/plans/2026-04-11-roadmap.md` — rewritten Phase E-H based on + the deep-dive synthesis. Old Phase E renamed to J. -## Keybinds (full, current) +## Architectural headline findings -| Key | Action | -|-----------|--------| -| F1 | Toggle keybind help panel | -| F2 | Toggle collision wireframes | -| F3 | Console dump (pos + nearby objects) | -| F4 | Toggle HUD info panel | -| F5 | Toggle HUD stats panel | -| F6 | Toggle compass | -| F8 / F9 | Active-mode mouse sensitivity slower / faster | -| F | Toggle fly camera | -| Tab | Toggle player mode (live session only) | -| WASD | Move (player mode) / fly | -| Space | Jump (hold to charge, release to fire) | -| Shift | Run | -| Mouse | Turn character / look | -| Hold RMB | Free-orbit camera around player (stays on release) | -| Wheel | Zoom chase distance | -| Escape | Exit fly / player / close window | - -## Open issue (parked for follow-up) - -User reports mouse "feels like you can only move one way" at low -sensitivity. Diagnosed + fixed: chase `PitchMin` was clamping at -`0.05f`, preventing any upward tilt. Widened to `-0.7f`. Needs -visual verification next session. +1. **Retail UI widgets live in `keystone.dll`**, not `acclient.exe`. + We implement our own retained-mode toolkit with retail-faithful + event codes (0x01 click, 0x15 drag, 0x3E drop, 0x201 WM_LBUTTONDOWN) + and consume the same portal.dat fonts + sprites for visual identity. +2. **Of 94 GameEvents** (S→C, `0xF7B0` envelope), **zero are handled** + in acdream today. Biggest network-protocol gap; blocks inventory, + chat, quest tracking, allegiance. +3. **Motion hooks are the trigger source** for audio + VFX + combat + timing. R3 motion-hook expansion is the prereq for "feel alive" + (Phase E). +4. **Weather is 95% client-side** — deterministic from Portal Year + server clock. No `SetWeather` opcode. +5. **Retail lighting is D3D fixed-function** with 8-light cap, NO + attenuation inside Range, then hard cutoff. "Feels right" not + physical. ## Pickup for next session -**MAJOR TASK PARKED HERE**: user has asked for a deep investigation -+ port of the retail AC client's GUI subsystem. User explicitly -directed **Opus 4.7 with extra-high effort** for this work. The -agents are dispatched in this session and their output lives in -`docs/research/2026-04-17-retail-ui-*.md`. See that set of files -for the in-depth UI research + C# scaffold. +**"What should I do tomorrow?" table:** -After the retail-UI port is in place: -1. Hook the retail chat window to the existing WorldSession message - stream -2. Port the health/stamina/mana globes to real player stats (need - `CharacterCreate`/`InqStats` wire parsing first) -3. Port the inventory panel (needs CreateObject item parsing) +| If you want to… | Build… | +|---|---| +| Make the world feel alive (footsteps, sword whooshes, spell auras) | Phase E — R3 motion hooks → R5 audio → R4 particles | +| Actually fight monsters | Phase F.3 combat math + F.1 GameEvent dispatcher | +| Cast a buff + recall to lifestone | Phase F.4 spell state machine + F.1 GameEvent | +| See a character sheet | Phase F.2 item model + F.5 attributes panel (UI slice 05) | +| Enter a dungeon | Phase G.3 dungeon streaming (R9) | +| See a sky | Phase G.1 weather/day-night (R12) | +| Create a character in-client | Phase H.4 CharCreate (R7) | + +The **master synthesis** (`docs/research/deepdives/00-master-synthesis.md` +§10) recommends a specific week-by-week sequence if the user wants +one-thing-at-a-time focus. + +## Session feedback / lessons + +- **Opus-4.7 high-effort parallel agents** are the right tool for + decompile-intensive research. 13-agent swarm for R1-R13 completed in + ~13 minutes, producing ~78,000 words of grounded work. Cost is high + but quality justifies it for load-bearing research. +- **keystone.dll is a landmine** for anyone trying to "port the UI + faithfully" — the widget toolkit isn't in the decompile we have. Own- + toolkit approach is the only viable path. +- **Network protocol atlas (R8)** is the single biggest unblocker — + nearly every other system depends on opcodes we don't handle.