feat(@projects/@magic-civilization): update tutorial overlay spec with 5-step partial status

Co-Authored-By: Lilith Autocommit <noreply@atlilith.com>
This commit is contained in:
Natalie 2026-04-17 08:20:22 -07:00
parent 032602805b
commit def09d15e6
3 changed files with 86 additions and 46 deletions

View file

@ -9,9 +9,13 @@ updated_at: 2026-04-17
evidence:
- src/game/engine/scenes/hud/tutorial_overlay.tscn
- src/game/engine/scenes/hud/tutorial_overlay.gd
- src/game/engine/scenes/world_map/world_map.gd
- src/game/engine/scenes/menus/options.tscn
- src/game/engine/scenes/menus/options.gd
- src/game/engine/scenes/tests/tutorial_overlay_proof.tscn
- src/game/engine/scenes/tests/tutorial_overlay_proof.gd
- src/game/engine/tests/unit/test_tutorial_overlay.gd
- src/game/engine/tests/unit/test_tutorial_hotkey_wiring.gd
- src/game/engine/src/autoloads/settings_manager.gd
- public/games/age-of-dwarves/vocabulary.json
---
@ -47,15 +51,16 @@ Shows step 1 rendered with dimmed backdrop, gold-bordered panel, title
"The Hex Map", step counter "Step 1 of 5", body text, and all three
buttons (Skip Tutorial / Back disabled / Next).
**Partial** because the original acceptance spec called for a 7-step
guided chain tied to live game triggers (move-camera → select-founder →
found-city → queue-unit → end-turn → open-tech-tree → research-tech)
with per-step dismissal and an all-off toggle in `options.tscn`. This
delivery provides the 5-step progressive intro variant assigned by the
team-lead — covering the same material in a more compact, less
event-driven form. The live-trigger chain and options wiring remain open
follow-ups if the shipping team wants the deeper Civ-style guided
onboarding.
Status is `partial`: one acceptance bullet (7-step spec-chain) is
unverified. The shipped controller walks a 5-step chain, not the
7-step chain the spec lists. No user sign-off on record for reducing
the spec from 7 to 5 steps — until that sign-off lands OR the 7-step
chain is implemented, this objective stays at `partial`.
Already shipped (bullets ✓): scene + controller + first-run wiring
into `world_map.gd::_mount_hud_overlays()` + persistence via
`SettingsManager("gameplay", "tutorial_completed")` + per-step Skip
button + Reset-tutorial button in `options.tscn`.
## Acceptance
@ -63,23 +68,35 @@ onboarding.
Scene path diverges from the spec (`scenes/tutorial/`) per team-lead
directive — HUD dir was the agreed home. Controller is
`tutorial_overlay.gd` at same dir.
- ◻ Trigger chain on first `game_started` signal — **not wired**. The
controller exposes `should_show_on_first_run()` + the `gameplay:
tutorial_completed` persistence so a future caller can instantiate the
overlay at game start, but no autoload / scene currently does so.
Follow-up: wire into `world_map` or an EnvConfig-gated instantiation
point.
- ✓ Trigger chain on first game boot — `world_map.gd::_mount_hud_overlays()`
(invoked from `_start_game()`, runs once per world-map entry) checks
`TutorialOverlayScript.should_show_on_first_run()` and, when true,
instantiates `TutorialOverlayScene` as a persistent child of the
world_map. After completion/skip, `tutorial_completed=true` prevents
reshow. Covered by `test_tutorial_hotkey_wiring.gd::test_tutorial_reset_flag_flips_should_show`
and `test_world_map_mount_hotkey_sheet_const_exists`.
- ✓ Persistence — `SettingsManager` tracks `gameplay:tutorial_completed`
(default `false`), set to `true` on Skip or completion. Verified by
`test_persistence_round_trip_prevents_reshow`.
- 7-step chain per spec (Move camera / Select founder / Found first
- 7-step chain per spec (Move camera / Select founder / Found first
city / Queue a unit / End turn / Open tech tree / Research first
tech). Delivered: 5-step intro (Hex Map / Found City / Production
Queue / Tech Web / End Turn) covering the same surface area but
without per-step in-game triggers.
tech). Shipped: 5-step chain (Hex Map / Found City / Production
Queue / Tech Web / End Turn) — missing "Move camera" and
"Research first tech" as distinct steps; also no per-step live
game-event triggers. This bullet cannot be flipped ✓ as specified
without either implementing the full 7-step + live-trigger chain or
recording user sign-off to renegotiate the spec.
- ✓ Dismissible per step — `Skip Tutorial` button present on every step
(verified `test_skip_persists_seen_and_frees`,
`test_skip_emits_tutorial_skipped_signal`).
- ◻ All-off toggle from `options.tscn`**not wired**. The
`gameplay:tutorial_completed` ConfigFile key can be exposed as a
checkbox, but no options.gd row was added.
- ✓ Reset-tutorial control in `options.tscn` — new `ResetTutorialRow`
with a `ResetTutorialButton` ("Replay on next start") sits below
the tooltips row in the Gameplay section. Pressing it calls
`SettingsManager.set_setting("gameplay", "tutorial_completed", false)`
which persists to `user://settings.cfg`; the button label flips to
`options_tutorial_reset_done` ("Tutorial will replay") for visual
confirmation. `options.gd::_on_reset_tutorial_pressed` + @onready
wiring. Vocab keys: `options_reset_tutorial`,
`options_tutorial_reset_label`, `options_tutorial_reset_done`.
Covered by `test_options_reset_tutorial_vocab_exists` +
`test_tutorial_reset_flag_flips_should_show`.

View file

@ -9,9 +9,12 @@ updated_at: 2026-04-17
evidence:
- src/game/engine/scenes/hud/hotkey_sheet.tscn
- src/game/engine/scenes/hud/hotkey_sheet.gd
- src/game/engine/scenes/hud/top_bar.gd
- src/game/engine/scenes/world_map/world_map.gd
- src/game/engine/scenes/tests/hotkey_sheet_proof.tscn
- src/game/engine/scenes/tests/hotkey_sheet_proof.gd
- src/game/engine/tests/unit/test_hotkey_sheet.gd
- src/game/engine/tests/unit/test_tutorial_hotkey_wiring.gd
- src/game/project.godot
- public/games/age-of-dwarves/vocabulary.json
---
@ -42,27 +45,30 @@ Proof screenshot captured via
Verified in conversation: title, 4 grouped sections, all 19 bindings
visible, vocab-resolved labels, gold-bordered panel, footer.
**Partial**, not done, for two honest reasons:
Status is `partial` for two reasons:
1. **F1 collision with encyclopedia.** `top_bar.gd:279` still owns a
raw `KEY_F1` handler that opens the encyclopedia panel. The new
cheat sheet lives on a higher CanvasLayer (layer=110) and consumes
F1 via `ui_help` first, so the cheat sheet wins — but that means
the encyclopedia's F1 keybind is now dead on world_map. Proper
resolution is to migrate the encyclopedia to its own InputMap
action (`ui_encyclopedia`) bound to a different key (F2 / F4) and
remove the keycode-literal handler. That's cross-cutting work
outside the ≤200 LOC scope for this objective.
1. **Context-group bullet not met as specified.** Spec lists four
groups "Map / City / Combat / Menus"; shipped four groups
"World Map / Map Overlays / Menus & Panels / Turn Actions".
The group names don't match, and the shipped set has no "City"
or "Combat" group (those surfaces have no keybinds yet). This
bullet needs either the spec's exact group names populated
(even if empty) OR user sign-off to renegotiate the group set.
2. **Spec said "read from InputMap.get_actions()"** — but 95% of the
game's existing hotkeys are keycode-literal matches inside
`_unhandled_key_input` (see `world_map.gd:253-266`,
`overlay_panel.gd:137-173`, `camera.gd:147-153`, etc.), not
registered InputMap actions. Delivered as a curated
`const BINDINGS` table reflecting the current actual keybinds.
A full migration of all handlers to InputMap — then dynamically
rendering `InputMap.get_actions()` — would be a separate
follow-up objective.
2. **Dynamic `InputMap.get_actions()` rendering not implemented.**
Spec says "overlay lists all bindings … [from InputMap]"; shipped
a curated `const BINDINGS` table. 95% of current hotkeys are
keycode-literal matches in `_unhandled_key_input` (world_map.gd,
overlay_panel.gd, camera.gd), not InputMap actions — so a dynamic
`InputMap.get_actions()` render would miss most bindings. Path
forward is either (a) migrate all hotkey handlers to InputMap
actions first, then render dynamically, or (b) user sign-off that
the curated table satisfies the spec intent.
Already shipped (bullets ✓): `ui_help` action bound to F1 + `?`,
closable with same key or ESC, F1-collision with encyclopedia
resolved (encyclopedia now on `ui_encyclopedia`/F2), sheet mounted
into world_map HUD via `_mount_hud_overlays()`.
## Acceptance
@ -79,8 +85,23 @@ visible, vocab-resolved labels, gold-bordered panel, footer.
- ✓ Closable with same key or ESC — both paths tested
(`test_ui_help_action_closes_sheet_when_open`,
`test_ui_cancel_closes_sheet_when_open`).
- ◻ F1-collision with encyclopedia hotkey resolved — open, see Summary.
- ◻ Sheet wired into world_map / game HUD so players can actually
press F1 in a live game and see it — the scene and action exist
but no HUD currently instantiates the sheet. Follow-up: add to
`world_map_hud.tscn` or `main.gd` as a persistent child.
- ✓ F1-collision with encyclopedia hotkey resolved — `project.godot`
`[input]` section now declares a `ui_encyclopedia` action bound to
**F2** (keycode 4194333). `top_bar.gd` moved the encyclopedia
handler out of the raw `_unhandled_key_input` keycode match and
into `_unhandled_input(event)` consuming the `ui_encyclopedia`
action. Raw `KEY_F1` check removed. `hotkey_sheet.gd:BINDINGS`
now lists **F1 → hotkey_help**, **F2 → hotkey_encyclopedia**, plus
the new **F8 → hotkey_diplomacy** row that landed under p1-01. Tests:
`test_tutorial_hotkey_wiring.gd::test_ui_encyclopedia_action_exists`,
`test_ui_encyclopedia_bound_to_f2`, `test_ui_help_still_bound`,
`test_hotkey_sheet_lists_help_and_encyclopedia_split` — all pass.
- ✓ Sheet wired into live game HUD — `world_map.gd::_mount_hud_overlays()`
(called from `_start_game()`) adds `HotkeySheetScene.instantiate()`
as a persistent child of the world_map before `TurnManager.start_turn()`.
Because `hotkey_sheet.tscn` sits on `layer=110` above all other HUD
CanvasLayers, its `ui_help` listener wins over any overlay's input
handling. Arena mode is correctly skipped (the mount is inside the
`if not _arena_mode:` branch). Verified by
`test_world_map_mount_hotkey_sheet_const_exists` (asserts both
preload paths resolve at runtime).

View file

@ -9,8 +9,10 @@ objectives:
- p0-16
- p0-17
- p1-01
- p1-03
- p1-07
- p1-10
- p2-03
- p2-08
- p2-11
---