diff --git a/docs/plans/NS-14-implementation-plan.md b/docs/plans/NS-14-implementation-plan.md new file mode 100644 index 0000000..0c6a742 --- /dev/null +++ b/docs/plans/NS-14-implementation-plan.md @@ -0,0 +1,82 @@ +# NS-14 — Implementation plan + +## Story reference + +| Field | Value | +|--------|--------| +| **Key** | NS-14 | +| **Title** | E1.M1: Click-to-move prototype (client-only) | +| **Jira** | [NS-14](https://neon-sprawl.atlassian.net/browse/NS-14) | +| **Parent context** | [NS-10 — E1.M1 InputAndMovementRuntime](https://neon-sprawl.atlassian.net/browse/NS-10) | + +## Goal, scope, and out-of-scope + +**Goal:** On the Godot client only, prove click-to-move locomotion and the input → world-target path before any networking or server authority. + +**In scope** + +- Placeholder avatar in the prototype scene (`main.tscn` or a dedicated movement test scene; default choice: extend `main.tscn` so F5 still runs the prototype). +- Ground pick via camera raycast; on valid hit, command movement to that point. +- Flat prototype terrain and simple obstacles sufficient to validate stopping behavior. +- Brief note in README and/or scene that this is **temporary** until authoritative movement sync exists. + +**Out of scope (per Jira)** + +- Game server, persistence, `MoveCommand` / wire protocol, Protobuf contracts. + +## Acceptance criteria checklist + +- [ ] Clicking walkable ground moves the avatar to the destination without requiring WASD (mouse-only locomotion for this prototype). +- [ ] Movement stops at obstacles when using navigation; **or** if using a direct move-to approach instead, the limitation is documented (README and/or plan). +- [ ] README or an in-editor scene note states this behavior is provisional until authoritative sync lands. + +## Technical approach + +1. **Scene setup (`main.tscn`)** + - Add a **Camera3D** suitable for ground picking (angled downward at a `StaticBody3D` floor with collision). + - Add a **CharacterBody3D** placeholder (e.g. `CapsuleMesh` + `CollisionShape3D`) as the avatar. + - Add at least one **obstacle** (`StaticBody3D`) so “stop at obstacles” is observable. + - Add a **NavigationRegion3D** covering the walkable floor; bake a navigation mesh from the floor (and subtract or exclude obstacles per Godot 4 workflow). + +2. **Movement model** + - Prefer **NavigationAgent3D** on the avatar: set `target_position` from the raycast hit on the ground; each frame move the body toward the agent’s next path position (e.g. `velocity` + `move_and_slide`, or equivalent Godot 4 pattern). This satisfies the AC path that expects stopping at obstacles via navigation. + - Fallback only if navigation proves unnecessarily heavy for the first slice: direct `move_toward` / velocity toward the click point with `move_and_slide` and document that there is no pathfinding. + +3. **Input** + - `_unhandled_input` or `_input`: on left mouse button, raycast from camera through cursor into the physics world; if the collider is the ground (or a dedicated “walkable” layer/mask), set the navigation target. + +4. **Documentation** + - Update `client/README.md` with a short “Movement prototype (NS-14)” subsection: mouse click-to-move, navigation-based obstacle avoidance, **not** server-authoritative. + - Optional: `Editable Children` note on root node in scene or a comment in `main.gd` pointing to NS-14 / temporariness. + +## Files to add + +| Path | Purpose | +|------|--------| +| None required initially | If `main.gd` grows unwieldy, optionally extract `scripts/player_navigation.gd` (or similar) attached to the avatar—only if it keeps the scene readable. | + +*(Default: implement in existing `scripts/main.gd` + scene edits unless script size forces a split.)* + +## Files to modify + +| Path | Rationale | +|------|-----------| +| `client/scenes/main.tscn` | Add camera, terrain, obstacles, navigation region, avatar, and wire scripts. | +| `client/scripts/main.gd` | Raycast-on-click, navigation target updates, and any per-frame movement driver if kept on root. | +| `client/README.md` | Document prototype movement, temporary nature, and manual verification steps. | +| `client/project.godot` | Only if needed (e.g. input map, layer names, or feature flags)—prefer minimal diffs. | + +## Tests + +- **Automated:** None for this story; the repo has no Godot test harness yet ([testing expectations](../../.cursor/rules/testing-expectations.md)). +- **Manual verification:** + 1. Open `client/` in Godot 4.2+, run main scene. + 2. Click on the floor: avatar moves to the point without using WASD. + 3. Click a destination behind an obstacle: avatar path avoids or stops appropriately per navigation behavior. + 4. Confirm README/scene note mentions provisional client-only movement. + +## Open questions / risks + +- **Navigation baking:** First-time contributors need to bake the navigation mesh in the editor after pulling scene changes; document that in README if it is not obvious. +- **Isometric later:** Camera rig may be replaced for isometric; keep movement logic independent of camera style where possible (raycast from current camera). +- **Performance:** Single-agent prototype is sufficient; no need to optimize for crowds in NS-14.