Files
code_of_conquest_dnd/client/docs/README.md
Phillip Tarrant 31759ef848 docs(roadmap): M4-b lands; the Title screen was already built
The creation screen is done — 302 client tests (up from the 250 baseline),
content build green. Also flips the M3 Title screen from planned to done: it
shipped in a77bf03/f071392 and the roadmap never caught up, which would have
misled M4-c into thinking it must build one.

Adds six new trap species to docs/traps.md from this milestone's review
passes: substring-collision assertions, a BBCode wrapper masking an empty
ContentDB, a test asserting the script's own loop bound, a trivially-true
gating fixture, assertions already true before the action under test ran, an
"iterates everything" guard that checked three hardcoded pairs, a node-type
sweep that missed RichTextLabel, tests that called handlers instead of
pressing nodes, GUT silently skipping an unparseable class_name test file at
the old count, and a test that can hang instead of fail. Also documents the
new client-docs convention: clickable cards are Buttons with mouse_filter = 2
on every child, and pressed on a toggle_mode Button is the chosen state.

Human F6 confirmation of the rendered screen against the mock is still
outstanding and is not claimed here.
2026-07-13 16:00:17 -05:00

83 lines
4.9 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.
# /client/docs
Client-specific documentation. Scoped to the Godot project.
Put here:
- Scene tree / autoload structure
- Input model — menu vs free-text boundary, which must be visible (§15)
- Combat wiring — deterministic damage, per-encounter seeding (§10)
- Canon log data structure and fact-harvesting (§11)
- HTTP client + fallback-degradation handling (§13)
Cross-cutting design (anything touching both client and api) goes in the root [`/docs`](../../docs), not here.
## UI scene conventions (shell + all screens)
Screens are **authored editor-first** — the layout lives in the `.tscn`, not in
code. See ADR [0001](../../docs/adr/0001-editor-first-ui-scenes.md) for the why;
this is the how. Reference: `scenes/shell/{MainWindowShell,SystemDock,NarrationBook}.tscn`
+ `scripts/ui/shell/*.gd`, and `scenes/creation/CharacterCreation.tscn` +
`scripts/ui/creation/{character_creation,creation_draft,creation_copy}.gd` (M4-b).
- **Clickable cards are Buttons with `mouse_filter = 2` on every child.** A card that
holds a name, a blurb and a trait line is a `Button` (Button-base variation, so
`normal`/`hover`/`pressed` actually skin it) with a `VBoxContainer` of Labels inside.
Every child needs `mouse_filter = 2` (IGNORE) or the Label swallows the click and the
card never toggles. `pressed` on a `toggle_mode` Button *is* the "chosen" state — no
script-side stylebox swapping.
- **The `.tscn` owns the tree.** Author every node in the editor: containers,
panels, labels, buttons, art-slot placeholders. Assign the shared theme on the
scene root (`theme = game_theme.tres`) and set each node's `theme_type_variation`
(from `ThemeKeys`) in the editor, so the scene previews themed. Instance
sub-screens (`PackedScene` ext_resource) rather than rebuilding them.
- **The script does on-load work only.** `@onready var x := $Path/To/Node` refs,
signal/service wiring, animations, and binding state into the authored nodes
(label text, colours from `Palette`). Do **not** create nodes in `_ready()`.
- **Data-driven repeats = fixed authored slots, bound at runtime.** Author enough
turn-order tokens / consumable slots / etc. in the editor; the script fills the
first N from state and hides the rest. Previewable now; systems write them later.
- **Scene-root sizing.** Give the root a fixed size via offsets (e.g. 1920×1080)
for editor preview, but **no full-rect anchors on the root** — a root Control run
via F6 collapses to (0,0) under full-rect anchors. Keep `size = get_viewport_rect().size`
on `_ready` + a `size_changed` connection (the M3-a collapse lesson).
- **Button styling → Button-base variations only.** Never put a PanelContainer
variation (`DarkPanel`, `ParchmentCard`) on a `Button`; it has no `normal/hover/
pressed` styleboxes so the button renders unskinned. Use the Button-base
variations (`PrimaryCTA`, `Tab`, `TabActive`, `Chip`, `DockButton`, `ParchmentButton`).
- **`RichTextLabel` prose** reads its dark serif ink from the theme's base
`RichTextLabel` style (it does *not* inherit `default_font`/`default_color`).
Just add the `RichTextLabel` — don't override its colour per-node.
- **Theme is generated.** All colours live in `palette.gd`; `game_theme.tres` is
built by `scripts/theme/build_game_theme.gd` (source of truth). To add/adjust a
variation, edit the builder + `theme_keys.gd`, then regenerate:
`godot --headless -s res://scripts/theme/build_game_theme.gd`. Never hand-edit
the `.tres` or put a hex literal in a script or `.tscn`.
- **Wiring the DM loop / injectable services.** Follow the shell: a `service`
var settable *between* `instantiate()` and `add_child()` lets tests inject a
`FakeTransport`-backed `DmService` so on-load calls stay hermetic; `_ready`
builds the real `HttpTransport`-backed one when none was injected.
- **Visual gate.** Headless GUT proves structure (nodes mount, sizes non-zero,
bindings run); it cannot prove rendering. Every screen needs a **human F6
eyeball** before it's done. Note shader surfaces (`DarkBay`, vignette) render
their texture only on an F6 run, not in the editor.
## Narrate live smoke (M2 client HTTP loop)
The `narrate_harness` scene is a throwaway proof of the client → `/dm/narrate`
loop. It is not the game UI.
**Prereqs:** the proxy running and Ollama reachable.
1. Start the proxy: from `api/`, `uvicorn app.main:app --port 8000` (with the
`.env` from `.env.example`; Ollama up at `OLLAMA_BASE_URL`).
2. In the Godot editor, open `res://scenes/narrate_harness.tscn` and run it (F6).
3. Click **Narrate this scene**. Expect grounded prose in the Narrator's voice
(referencing Greywater / Brannoc / the washed-out bridge), tags stripped, and
`facts harvested: N` with N ≥ 0.
4. **Degraded path:** stop the proxy and click again. Expect the authored
fallback line and `(degraded)` in the status — never an error.
Override the proxy URL with the `coc_rpg/proxy_base_url` project setting.