Files
settled-reach/docs/sprints/sprint-15/client.md
T
jpmschweitzerandClaude Opus 4.6 c01ad011ed docs(sprints): add Sprint 15 React briefings
Server (7), client (5), copy (2) tickets. Goal: player acts and
world reacts — follow/examine, dialogue access layers, server-side
monologue events, personality and tell system.

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
2026-02-21 13:43:49 +01:00

7.0 KiB

Sprint 15: React — Client Tasks

Goal: The player acts and the world reacts — follow and examine mechanics connect the player to the living NPC simulation; the dialogue system's first two access layers open up information gating; server-side monologue events fire in context; and the personality/tell system completes the NPC data model.

Branch: client Agents: Stig (UI/rendering dev), Tyre (architect), Hoshe (QA)

New Tickets

# Title Blocked by
#71 Tilemap rendering system
#72 Entity sprite system
#73 Input capture system
#74 Basic UI framework
#117 Smooth camera movement #116 (done)

Use db/connectors/ticket show <id> for full details.

Key Decisions

  • decisions/perception.md — D-015 (camera locked to character, fixed-north for v0.1), D-019 (top-down confirmed, ~15-20° from vertical "the angle", sprite art convention not camera setting), D-033 (entity color = relationship to player), D-049 (8-layer z-stack), D-059 (fog shader five layers)
  • decisions/architecture.md — D-020 (Godot client = pure renderer, no game logic in GDScript), D-066 (dual-scale grid: 0.5m simulation, 1m visual, 64x64px visual tile), D-010 (deterministic simulation — client renders what server sends)
  • decisions/perception.md — D-043 (functional warmth art style), D-044 (entity > object > structure visual hierarchy), D-046 (three-reference lighting: Darkwood/BR2049/Hopper), D-056 (insert-styled cursor states)

Notes

  • #71 Tilemap rendering system: client/scripts/rendering/tile_renderer.gd exists and is referenced in world_renderer.gd as $FogGroup/FloorTiles (a TileMapLayer node). The current implementation may be a stub — this ticket must deliver: TileMap node with atlas management, multi-layer support for floor/walls/objects matching D-049 z-stack layers 0 (FloorTiles), 1 (FloorObjects), 2 (furniture in YSortGroup). Tile size is Constants.TILE_SIZE (32px visual, per D-066 dual-scale grid where 1 visual tile = 1m = 64x64 source, scaled to 32px runtime). Wall rendering follows D-019 amendment: Option B for structural walls (visible top + face), Option A (boundary lines) for interior partitions. Atlas must accept tiles from ObserverSnapshot.visible_tiles (format: [{x, y, z, type}]). world_renderer.gd already calls tile_renderer.update_tiles(GameState.visible_tiles) — ensure update_tiles() is the correct entry point.

  • #72 Entity sprite system: client/scripts/rendering/entity_renderer.gd is substantially implemented — it handles D-033 color derivation (Phase 1 defaults by kind, Phase 2 from RelationshipState), position lerp with LERP_SPEED = 12.0, and 0.5s color fade for relationship transitions (#521). This ticket must validate and complete: ensure all entity kinds from ObserverSnapshot.entities render correctly, including the kind.variant field dispatching to correct sprite/shape, the 24x32 entity footprint within 64x64 visual tiles (D-044), and y-sort ordering within YSortGroup. If placeholder shapes (ColorRect) are used, that is correct for v0.1 per D-014. Integration check: world_renderer.gd drives entity updates through the same update_from_state() path — confirm entity renderer is wired there. Follow-mode UI state (#241, server) will need a new field on GameState — stub a follow_target_id: int = -1 for when the server ticket lands.

  • #73 Input capture system: client/scripts/autoloads/input_mapper.gd is implemented with WASD movement (D-054 mouse-relative), stance toggles, Interact, and semantic action dispatch. InputMapper.Action enum covers: MOVE_* (8 directions), INTERACT, USE_PERCEPTION_MODE, OPEN_MENU, PAUSE/UNPAUSE, TOGGLE_STANCE_*, SET_FACING. This ticket must validate the full pipeline: physical key → Action enum → input_queue → message serialized and sent to server. Verify: movement throttle per stance (Sprint=5/s, Walk=2.5/s, Careful=1.7/s, Crouch=1.25/s) is active, facing angle updates every frame, InputMapper correctly suppresses movement when GameState.dialogue_active == true (D-061 walk-away via WASD). If any semantic actions are stubbed out or missing from the protocol send path, complete them. The Follow verb (#241 server) will arrive via nearby_interactions — confirm the client can dispatch an Interact action with a specific response_id corresponding to Follow.

  • #74 Basic UI framework: main.gd reveals the current HUD structure — $UILayer/HUD, $UILayer/MonologueDisplay, $InsertOverlay/InteractionList, $InsertOverlay/DialogueBox, $UILayer/StanceIndicator, and more are already wired. This ticket must ensure the HUD structural layout is complete and stable: monologue display area (top of screen or floating, z-layer 7 per D-049), placeholder area for insert/minimap (D-013, not yet implemented), stance indicator visible, and the overall scene hierarchy matches D-049's 8-layer z-stack. The $InsertOverlay is z-layer 6 (insert overlay), $UILayer is z-layer 7 (UI/monologue). Confirm GameState.insert_active controls visibility of z-layer 6 elements per D-056/D-057 OQ-07 resolution. This is a completion + validation ticket — identify gaps in the existing HUD structure rather than building from scratch.

  • #117 Smooth camera movement: Camera lock to character is done (#116) — camera in main.gd is a Camera2D. _camera_anchored and _teleport_in_progress flags exist for init sequencing. This ticket adds interpolated camera tracking: instead of snapping camera.position to GameState.player_position each frame, use exponential smoothing (same pattern as entity_renderer.gd's LERP_SPEED). Configurable smoothing: expose a constant or project setting for the smoothing factor. Edge cases to handle — camera must snap immediately on teleport (the _teleport_in_progress flag already exists for exactly this), and must not smooth during initial camera anchor (_camera_anchored flag). Camera is always fixed-north per D-015 v0.1 scope — no rotation logic.

Dependency Chain

#71 (Tilemap rendering) ─────────────────────────────────────────────┐
#72 (Entity sprite system) ──────────────────────────────────────────┤→ integrated in world_renderer.gd
#73 (Input capture system) → feeds server #241 (Follow), #242 (Examine)│
#74 (Basic UI framework) ────────────────────────────────────────────┘

#117 (Smooth camera) → standalone, parallel track

PR Workflow

When ready to submit, create a PR with the tea CLI. All flags are required to avoid TTY prompts (see CLAUDE.md "Gitea access" section):

tea pr create --repo jpmschweitzer/settled-reach --login schweitz --title "feat(client): sprint 15 react — client deliverables" --description "body" --base main --head client