Plan focus cone, head ring, and radial action menu; defer host sign-in
Document the next playable pass: WASD/look stop fighting action keys, cone focus with a billboarded head ring, doughnut HUD opened by LMB or Space (click or A/D then Space to confirm, Esc/RMB cancel). Emergency stays on R. Wand leaves W. NPC rigs stay procedural but get a face/hair/neck. Host REQUIRE_SIGNIN_VIEW follow-up deferred.
This commit is contained in:
1 parent
b704a8ed61
commit
5662baa14d
3 files changed
+193
No files matched your search
@@ -15,6 +15,10 @@ Session memory for durable decisions, state, and gotchas. Keep concise, remove o
|
|||||||
|
|
||||||
## Current State
|
## Current State
|
||||||
|
|
||||||
|
- Next playable pass (planned, not coded): first-person stay, but focus becomes a camera cone +
|
||||||
|
head ring, and NPC verbs move onto a round pie menu (LMB/`Space` open, click or A/D/arrows then
|
||||||
|
`Space` confirm, `Esc`/RMB cancel). Emergency stays on `R`. Wand leaves `W` (conflicts with walk).
|
||||||
|
Host sign-in follow-up is deferred. Details in PLAN.md "Player Control, Focus, and Action Menu".
|
||||||
- **Release v0.2.1 is LIVE** (2026-10-31): CI run 1110 built the NSIS installer + AppImage
|
- **Release v0.2.1 is LIVE** (2026-10-31): CI run 1110 built the NSIS installer + AppImage
|
||||||
and published — installers/AppImage are on the releases page. Releasing = bump version → tag → push.
|
and published — installers/AppImage are on the releases page. Releasing = bump version → tag → push.
|
||||||
- NSIS gotchas (validated in a local ubuntu:24.04 docker repro): makensis uses `-D` defines
|
- NSIS gotchas (validated in a local ubuntu:24.04 docker repro): makensis uses `-D` defines
|
||||||
|
|||||||
@@ -452,6 +452,140 @@ The following commands apply once the Godot project is scaffolded:
|
|||||||
|
|
||||||
Desktop is the first target: Windows, Linux, and macOS. Web export is a later option.
|
Desktop is the first target: Windows, Linux, and macOS. Web export is a later option.
|
||||||
|
|
||||||
|
## Player Control, Focus, and Action Menu (next pass)
|
||||||
|
|
||||||
|
The prototype already walks and looks in first person, but the control scheme fights itself and targeting is a hairline. This pass replaces that with three things that belong together: solid locomotion, a visible focus on a person, and a round action menu for what to do with them.
|
||||||
|
|
||||||
|
### What is wrong today
|
||||||
|
|
||||||
|
- `W` is walk-forward in the input map and wand-screening in `GameManager._handle_key`. Walking at someone with a wand venue fires the wand.
|
||||||
|
- `A` / `D` are strafe and also allow/deny during inspection.
|
||||||
|
- `Q` is polite direction and is also bound as `cancel`.
|
||||||
|
- Focus is an 8 m physics ray from the camera. Missing a capsule by a few pixels clears the target. There is no mark in the world that you have someone.
|
||||||
|
- NPC bodies are colored capsules with props. They read as markers, not people.
|
||||||
|
- Actions live on number keys `1`–`6` plus `Q` / `E` / `W` / `R`. That is a cheat-sheet, not a verb you pick while looking at a person.
|
||||||
|
- `Esc` only toggles mouse capture. There is no "I changed my mind" for an action in progress.
|
||||||
|
|
||||||
|
### Movement and look
|
||||||
|
|
||||||
|
Keep first-person WASD + mouse look. Fix the feel and stop stealing those keys.
|
||||||
|
|
||||||
|
- Body yaw from mouse X, head pitch from mouse Y, pitch clamped (already `-80` to `80`).
|
||||||
|
- Move relative to body yaw only (already). Add short acceleration / deceleration so starts and stops are not instant.
|
||||||
|
- Gravity only when `not is_on_floor()`; `floor_snap_length` so the steps work.
|
||||||
|
- Mouse look runs only while `MOUSE_MODE_CAPTURED` and no modal UI is open (radial, inspection, wand, radio, shift review).
|
||||||
|
- Walk speed stays around 3.2 m/s. No sprint, no crouch in this pass.
|
||||||
|
- While the radial is open: freeze look and WASD so `A` / `D` can cycle the menu. Recapture the mouse when the menu closes.
|
||||||
|
- `Esc` with a modal open closes that modal and does nothing else. `Esc` with nothing open keeps the current capture/release toggle.
|
||||||
|
|
||||||
|
Equipment stays on its own keys because it is not about a person: `G` flashlight, `L` door lock, `Tab` cycle nearby people, `V` venue (debug), `F` debug overlay. `R` stays the dedicated emergency radio (hold-to-confirm on the existing panel). Those do not go on the wheel.
|
||||||
|
|
||||||
|
Wand leaves `W`. It is a slice on the wheel (greyed when the venue has no wand) and an optional extra key that is not WASD, suggested `C`.
|
||||||
|
|
||||||
|
### Focus area
|
||||||
|
|
||||||
|
Replace the hairline ray as the primary picker.
|
||||||
|
|
||||||
|
- A **focus cone** in front of the camera: people within about 10 m whose head projects inside a screen-space circle around the crosshair (about 90 px / 10 degrees).
|
||||||
|
- If several heads sit in the circle, pick the one closest to the center, then the nearer one if tied.
|
||||||
|
- The person must be in front (dot with camera forward > 0) and not fully occluded by the building. A short ray to the head is enough for occlusion.
|
||||||
|
- `Tab` still cycles people inside 12 m as the aim-free path. Cycling sets the same focused person the cone would.
|
||||||
|
- Clearing: look away until the head leaves the circle for a few frames (small grace so a bob does not drop them), or they walk out of range.
|
||||||
|
|
||||||
|
### Head ring
|
||||||
|
|
||||||
|
When a person is in focus, draw a thin ring around their head.
|
||||||
|
|
||||||
|
- Attach to the avatar `Head` node, sitting just above the skull, billboarded to the camera so it stays a circle on screen.
|
||||||
|
- Slow spin is fine; no ping-pong scale spam.
|
||||||
|
- Idle focus: pale gold, modest size. Radial open on that person: brighter, slightly larger.
|
||||||
|
- Optional small name under the ring (`display_name` only, not the archetype cheat `Violent Threat` in the world). The existing HUD target line can keep the archetype for the prototype.
|
||||||
|
- One ring at a time. Everyone else has none.
|
||||||
|
|
||||||
|
Implementation sketch: `MeshInstance3D` torus or a thin unshaded ring mesh on the avatar, toggled from `GuardController` / `GameManager` when focus changes. Screen-space fallback (unproject head, draw a `Control` circle) is acceptable if the 3D torus z-fights on hats.
|
||||||
|
|
||||||
|
### Round action HUD
|
||||||
|
|
||||||
|
A doughnut / pie menu centered on the screen, opened on the focused person.
|
||||||
|
|
||||||
|
**Open**
|
||||||
|
|
||||||
|
- Left mouse button, or `Space`, while someone is in focus and no other modal is open.
|
||||||
|
- If nobody is in focus, log the existing "aim first" line and do not open.
|
||||||
|
- The click that opens the menu must not also pick a slice.
|
||||||
|
|
||||||
|
**While open**
|
||||||
|
|
||||||
|
- Mouse becomes visible. Look and walk freeze.
|
||||||
|
- Center of the doughnut shows the focused person's `display_name`.
|
||||||
|
- Slices, clockwise from the top, de-escalation first:
|
||||||
|
1. Raise hand (stop / wait)
|
||||||
|
2. Point away
|
||||||
|
3. Head shake
|
||||||
|
4. Polite direction (old `Q`)
|
||||||
|
5. Inspect access (old `E`)
|
||||||
|
6. Wand (grey if the venue has no wand)
|
||||||
|
7. Formal warning
|
||||||
|
8. Block
|
||||||
|
9. Radio assist
|
||||||
|
- Emergency is **not** on the wheel (`R` only).
|
||||||
|
- Highlight follows the mouse angle when the cursor is over the ring. `Left` / `Right` or `A` / `D` step the highlight. Wrap around.
|
||||||
|
|
||||||
|
**Confirm**
|
||||||
|
|
||||||
|
- Click a slice: that action runs, menu closes, mouse recaptured.
|
||||||
|
- `Space` while a slice is highlighted: same.
|
||||||
|
- Inspect or wand: close the wheel, then open the existing inspect / wand panel. Allow / deny on that panel stay `A` / `D` (walk is frozen only while the wheel is up; once the inspect panel is open, WASD can move again, so allow/deny on `A` / `D` remains a press handler and must ignore repeats / echo, which it already does). Safer: keep walk frozen for inspect/wand too, until the panel closes. Prefer freeze until the whole interaction ends.
|
||||||
|
- Radio assist: close the wheel, open the existing radio panel.
|
||||||
|
|
||||||
|
**Cancel**
|
||||||
|
|
||||||
|
- `Esc` or right mouse button: hide the menu, no action, no recorder event, recapture mouse.
|
||||||
|
- Focus and the head ring stay as they were.
|
||||||
|
|
||||||
|
Number keys `1`–`6` may remain as shortcuts that skip the wheel so a smoke-test script still works. They must not fire while the wheel is open (the wheel owns `A` / `D` / `Space`). Document both in the README.
|
||||||
|
|
||||||
|
### NPC display
|
||||||
|
|
||||||
|
Stay on the procedural capsule rig (no Mixamo / GLB dependency this pass). Make them read as people at conversation distance.
|
||||||
|
|
||||||
|
- Neck between torso and head; shoes; simple hair cap (color from seed); two dark eye spheres on the face so a head has a front.
|
||||||
|
- Keep archetype props (camera, box, hat, sign, bag). Keep height / brightness variation from the visual seed.
|
||||||
|
- Collision capsule matches the scaled height so the focus ray / cone hits the body you see.
|
||||||
|
- `Head` stays a named node other systems can find (`get_node("Rig/Head")`) for the ring and the cone.
|
||||||
|
- Walk bob and the "look at the guard when noticed" cue stay.
|
||||||
|
- Do not put the internal type name (`Trespasser`, `Violent Threat`) on the body. The player should judge from clothes, props, and behavior. The debug overlay (`F`) can still print the type.
|
||||||
|
|
||||||
|
AI textures in `assets/textures/ai/` stay out of this pass unless a specific map (shirt, hair) is already the right size.
|
||||||
|
|
||||||
|
### Input map (target)
|
||||||
|
|
||||||
|
| Action | Bind |
|
||||||
|
| --- | --- |
|
||||||
|
| Walk | WASD / arrows (arrows **do not** walk while the wheel is open; they step the highlight) |
|
||||||
|
| Look | Mouse, captured |
|
||||||
|
| Open / confirm action menu | LMB, `Space` |
|
||||||
|
| Cancel menu | RMB, `Esc` |
|
||||||
|
| Step highlight | `A` / `D`, left / right arrows |
|
||||||
|
| Emergency radio | `R` |
|
||||||
|
| Flashlight | `G` |
|
||||||
|
| Door lock | `L` |
|
||||||
|
| Cycle nearby people | `Tab` |
|
||||||
|
| Wand shortcut | `C` (not `W`) |
|
||||||
|
| Inspect shortcut | `E` still allowed when the wheel is closed |
|
||||||
|
|
||||||
|
### Files this pass is expected to touch
|
||||||
|
|
||||||
|
- `src/game/guard_controller.gd` — cone focus, no look while modal, accel, floor snap.
|
||||||
|
- `src/game/npc_avatar.gd` — face / hair / neck, head marker, ring toggle.
|
||||||
|
- `src/game/ui/action_radial.gd` — new Control, `_draw` doughnut, slice pick.
|
||||||
|
- `src/game/ui/hud.gd` — host the radial; stop teaching number-key verbs as the only path.
|
||||||
|
- `src/game/game_manager.gd` — input routing, freeze flags, open/confirm/cancel.
|
||||||
|
- `project.godot` — input map.
|
||||||
|
- `src/core/strings.gd` — controls line, aim-first, no new tone-of-voice.
|
||||||
|
- `src/test/tests/test_focus_and_radial.gd` — cone pick, wrap, cancel emits nothing, `W` is not wand.
|
||||||
|
- README controls table and smoke checklist.
|
||||||
|
|
||||||
## Design Direction
|
## Design Direction
|
||||||
|
|
||||||
The game should feel like a tense workplace simulation with occasional crisis moments. The most satisfying outcome is not overpowering an NPC; it is recognizing the situation early and resolving it calmly.
|
The game should feel like a tense workplace simulation with occasional crisis moments. The most satisfying outcome is not overpowering an NPC; it is recognizing the situation early and resolving it calmly.
|
||||||
|
|||||||
@@ -1,5 +1,54 @@
|
|||||||
# TODO
|
# TODO
|
||||||
|
|
||||||
|
## Player control, focus ring, and radial action menu
|
||||||
|
|
||||||
|
Design is in `PLAN.md` → "Player Control, Focus, and Action Menu (next pass)". Distribution
|
||||||
|
follow-up (host `REQUIRE_SIGNIN_VIEW`) is deferred.
|
||||||
|
|
||||||
|
### Locomotion
|
||||||
|
|
||||||
|
- [ ] Stop stealing WASD: wand off `W` (use 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.
|
||||||
|
|
||||||
|
### 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.
|
||||||
|
|
||||||
## Distribution follow-up (findings + host config)
|
## Distribution follow-up (findings + host config)
|
||||||
|
|
||||||
Verified via API+host credentials (2026-10-31):
|
Verified via API+host credentials (2026-10-31):
|
||||||
@@ -34,3 +83,9 @@ performance hardening only.
|
|||||||
- [ ] Profile the crowd: ensure textured materials and props hold target frame rate around a
|
- [ ] Profile the crowd: ensure textured materials and props hold target frame rate around a
|
||||||
busy entrance.
|
busy entrance.
|
||||||
- [ ] Add LOD or culling for distant NPCs/props if the crowd grows.
|
- [ ] Add LOD or culling for distant NPCs/props if the crowd grows.
|
||||||
|
|
||||||
|
## Generated Asset Integration
|
||||||
|
|
||||||
|
- [ ] Regenerate the AI asset set at role-specific aspect ratios and dimensions.
|
||||||
|
- [ ] Audit, process, and wire every generated asset into the game runtime.
|
||||||
|
- [ ] Add screenshot auditing and refresh the README screenshot gallery.
|
||||||
Reference in new issue
Block a user