Files
security-game/TODO.md
T
zwitschi 8cf7745c80 Plan remaining gaps in TODO.md after a PLAN/code audit
Control pass (ADRs 0007-0010) stays first. Added the holes the audit found:
venue-correct access artifacts (override_access unread), session shell,
leftover PLAN verbs, crowd rubberneck, emergency aftermath, replay, NPC
poses, real ambience, a few Joke Shop/Studio events, and doc drift.
Host sign-in remains deferred. Generated-asset integration stays out
(already in DONE).
2026-10-31 15:17:02 +01:00

9.4 KiB
Raw Blame History

TODO

Checked against PLAN.md, ADRs 0001–0010, README.md, DONE.md, and src/ (Godot 4.3 prototype, release v0.2.1, 57 headless tests). Do the control pass first; it unblocks everything that uses focus or verbs.

Host REQUIRE_SIGNIN_VIEW stays deferred.

Player control, focus ring, and radial action menu

Design: PLAN.md → "Player Control, Focus, and Action Menu" and ADRs 0007–0010.

Locomotion

  • Stop stealing WASD: wand off W (wheel + optional C); allow/deny A/D only while inspect/wand is open; polite direction off Q as a required bind.
  • Accel/decel on walk; gravity only when airborne; floor_snap_length for the steps.
  • Mouse look only while captured and no modal UI is open. Freeze walk+look while the radial (and inspect/wand opened from it) is up. Recapture on close.
  • Esc closes the top modal first; with nothing open it still toggles mouse capture.

Focus and head ring

  • Replace the 8 m hairline ray as the primary picker with a focus cone (range ~10 m, head inside a ~90 px / 10° circle around the crosshair; closest to center wins; occluded heads skipped). Keep Tab as the 12 m cycle.
  • Small grace so walk-bob does not drop focus.
  • Billboarded ring on the focused avatar Head; gold idle, brighter while the radial is open; one at a time. Optional display_name under the ring. No internal type name in the world.
  • Add a small screen-center crosshair so the focus circle has a visible origin.

Radial HUD

  • New src/game/ui/action_radial.gd doughnut: open on LMB or Space when someone is focused. Opening click does not pick a slice. Slices (top, clockwise, de-escalation first): raise hand, point, head shake, polite direction, inspect, wand (grey if no wand), warning, block, radio assist. Emergency stays on R only.
  • Highlight by mouse angle, or A/D / arrows. Click slice or Space confirms. Esc / RMB closes with no action and no recorder event.
  • Inspect / wand / radio slices close the wheel then open the existing panels. Freeze until that panel closes.
  • Number keys 1–6 may remain as closed-menu shortcuts; they must not fire while the wheel is open.

NPC display

  • Procedural rig: neck, shoes, hair cap from seed, two eye spheres so the head has a front. Keep props, height variation, walk bob, notice-head-turn. Collision capsule matches height. Named Head node stays the attach point.

Input, copy, tests

  • Update project.godot input map (action_menu, confirm, cancel includes RMB, wand on C). Update hud.controls and the README table + smoke checklist.
  • Headless tests src/test/tests/test_focus_and_radial.gd: cone picks the centered head; highlight wrap; cancel writes no recorder event; W does not open wand.

Access artifacts actually match the venue

GameManager._artifacts_for maps NpcType → a wristband or free RECOGNITION. Joke Shop events set override_access {has_ticket, has_id} and nobody reads it, so club guests inspect as "recognized staff" instead of ID/ticket. Studio counterfeit/follow events have the same hole.

  • Build artifacts from the event (override_access, carried items) and the venue policy, not from NpcType alone.
  • Joke Shop: valid ID+ticket, ID without ticket, expired/mismatched/missing ID, no ID when required. Recognition must not auto-grant on every AUTHORIZED_GUEST.
  • Give some guests carried_items (keys / belt / phone / prohibited) so wand alerts are not always clear.
  • Studio: counterfeit wristband/credential and "follow authorized guest" use the scripted event data, not the generic type map.
  • Headless tests: Joke Shop guest_no_id is not granted by recognition; guest_valid grants only with ID+ticket; wand venues still require controller.screened.

Session shell

The game boots into a live 900 s shift. Save declares settings.json and never uses it. V cycles venues by restarting the shift.

  • Startup menu: pick venue, start shift, quit. Keyboard + click. Replaces V as the player-facing path (V may stay as a debug bind).
  • Pause overlay when Esc releases the mouse (or a dedicated pause key): resume, restart shift, settings, quit to menu.
  • Settings: mouse look sensitivity, persist through Save / settings.json. Load on boot.
  • Shift review "Run another shift" returns to the venue menu, not a silent restart of the same scenario.

Remaining PLAN verbs (after the radial exists)

  • Eye contact as a Level 1 action (PLAN / glossary). Distinct from raise-hand.
  • "I recognize this person" is a player decision recorded as evidence, not a pre-attached artifact on every staff/guest type.
  • Formal warning can activate the body-camera / security-light flag (PLAN Level 2). Overlay is currently always on; toggling should write an incident event.
  • Blocking stations the guard between the person and the door (PLAN Level 3). Today it only sends apply_player_action(BLOCKING).
  • "Request reason for entry" as a Level 3 ask, with a short NPC reply from dialogue_lines.

Crowd presentation

CrowdSystem is a mood/attention float. PLAN wants people watching, gathering, and panicking.

  • On aggressive_behavior / emergency_responder, nearby idle NPCs stop and face the incident (rubberneck). On crowd_panic, they move away from the door.
  • Profile a busy entrance with textured materials and props; add LOD or culling for distant NPCs if frame time drops.

Emergency aftermath

Responder outcomes (command / restraint / evacuation / arrest) are log lines. PLAN also wants evacuation, a closed street, and an investigation when the call was unjustified.

  • evacuation outcome actually clears the entrance (NPCs leave, door stays locked).
  • Unjustified emergency (low danger, no weapon) writes an investigation note on the shift review and applies the existing false-report / reputation hit.
  • Review copy names the responder outcome, not only battery and crowd %.

Body-camera replay

  • Shift review: a timeline of recorded incident events (ADR-0005 already stores them). Scrub or step through; no live 3D replay required in the first version.

NPC theater

Intents sit / photo / film / perform already pick waypoints. Bodies still idle-stand.

  • Sit pose at steps_end. Photo: brief raise of the influencer/tourist prop. Performer stays put and plays the hat/sign. After the ADR-0010 rig pass, not before.

Audio

AudioFeedback is sine beeps. DONE called that "crowd ambience"; it is not.

  • Loop a low crowd bed that rises with CrowdSystem.mood.
  • Radio open/close crackle on the existing radio panel, still headless-safe (no-op without an audio server).

Accessibility

  • Escalation colors that still read in grayscale (shape or label, not hue alone).
  • HUD font scale in settings.

Scenario content still missing vs PLAN lists

  • Joke Shop: guest on the reservation list without ID; borrowed/mismatched ID; guest refuses wand screening; late arrival during a performance.
  • Studio: filming-boundary repeat (influencer ignores a posted line); celebrity-arrival crowd spike (more rubberneckers, not only one arrive spawn).
  • Building: "activate body camera" and "request reason" once those verbs exist, used in at least one authored event.

Documentation drift

  • README Development Status: test count is 57, not 52. "Not yet implemented" should match this file (control pass, artifact wiring, session shell, replay, crowd presentation).
  • PLAN.md Tech Stack / Planned Commands still say GUT and GitHub Actions; the project uses src/test/test_runner.gd and .gitea/workflows/build.yml.
  • MEMORY: drop "door_staff_lines not surfaced" (they log through GameManager) and the obsolete "prototype defaults to 300 s" decision.

Distribution follow-up (host config, deferred)

Verified via API+host credentials (2026-10-31):

  • Repo is public (private:false) and account has admin rights.
  • Release v0.2.1 now carries all five artifacts (portable binaries + NSIS installer + AppImage) — the two installers were missing after CI publish (script uploaded only the portables); tools/publish_release.sh fixed to include them and re-uploaded via API.
  • Remaining host setting: instance-wide [service] REQUIRE_SIGNIN_VIEW=true makes anonymous browsing/downloads redirect to login (API-confirmed repo is public; this is a server app.ini setting, not an API or repo option). Advised path for the host admin: set REQUIRE_SIGNIN_VIEW = false in app.ini under [service], restart Gitea, then verify curl -sI https://git.allucanget.biz/zwitschi/security-game/releases/tag/v0.2.1 returns 200 (not a login redirect) and an anonymous asset download succeeds. Alternative: mirror downloads (Itch.io / GitHub Releases) for anonymous users.

Open Polish

  • Keep % placeholders stable in Strings.fmt when adding keys (positional formatting).

Tooling (when an editor workflow exists)

  • IDE/editor-based GUT integration. Until then the custom headless runner stays.
  • Optional later: author venues as .tres resources instead of ScenarioFactory functions. Not required for the control pass.