Standardized YAML frontmatter on all 115 sprint briefing files across sprints 1-26 with title, description, type, status, sprint number, and team fields. Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
108 lines
6.1 KiB
Markdown
108 lines
6.1 KiB
Markdown
---
|
||
title: "Sprint 16 — Client Briefing"
|
||
description: "Zone ID extraction optimization, sprite camera angle adjustment"
|
||
type: sprint
|
||
status: archived
|
||
sprint: 16
|
||
team: "client"
|
||
---
|
||
|
||
# Sprint 16: Converse — Client Tasks
|
||
|
||
**Goal:** Dialogue becomes a two-way exchange — players pick options and the server responds; NPC information-giving deepens through trust and trait-shaped delivery; the sprite pipeline gets its correct art-direction angle; and housekeeping fixes land across all three active teams.
|
||
|
||
**Branch:** `client`
|
||
**Agents:** Stig (dev), Tyre (arch), Hoshe (QA)
|
||
|
||
## Carry-over from Sprint 15
|
||
|
||
None. Sprint 15 was 100% complete (16/16 done).
|
||
|
||
## New Tickets
|
||
|
||
| # | Title | Blocked by |
|
||
|---|-------|------------|
|
||
| #543 | Optimize zone_id extraction O(N) → O(1) dictionary lookup | — |
|
||
| #540 | Adjust sprite camera to D-019 angle (~15-20° from vertical) | #541 (visual, must land first) |
|
||
|
||
Use `db/connectors/ticket show <id>` for full details.
|
||
|
||
## Key Decisions
|
||
|
||
- `decisions/perception.md` — D-019 (top-down camera, angle amendment: ~15-20° from vertical, "the angle"), D-043 (visual style, functional warmth), D-049 (z-level rendering stack)
|
||
- `decisions/architecture.md` — D-066 (dual-scale grid: 0.5m sim, 1m visual, 2x retina), D-077 (zone temperature memory, server-tracked zone_id)
|
||
|
||
## Open Questions to Resolve Early
|
||
|
||
None blocking either ticket.
|
||
|
||
## Notes
|
||
|
||
### #543 — Optimize zone_id extraction O(N) → O(1) dictionary lookup
|
||
|
||
**What exists:** `client/scripts/autoloads/game_state.gd` `apply_snapshot()` function. The current zone_id extraction (lines 243-252) does a linear scan of `visible_tiles` on every snapshot to find the tile whose coordinates match the player position:
|
||
|
||
```gdscript
|
||
current_zone_id = ""
|
||
var _px := int(player_position.x)
|
||
var _py := int(player_position.y)
|
||
for _ztile in visible_tiles:
|
||
if _ztile is Dictionary and _ztile.get("x") == _px and _ztile.get("y") == _py:
|
||
current_zone_id = _ztile.get("zone_id", "")
|
||
break
|
||
```
|
||
|
||
Within the same `apply_snapshot()` call (lines 256-268), `visible_tiles` is already iterated to build `visible_positions` (a `Dictionary` of `Vector2i → true`). The optimization is to build a second dictionary `_tile_by_coord: Dictionary` (mapping `Vector2i → tile Dictionary`) in that same existing loop, then replace the O(N) zone_id scan with an O(1) lookup.
|
||
|
||
**What to deliver:**
|
||
|
||
1. Declare `_tile_by_coord` as a local variable in `apply_snapshot()` (or as a member var if AudioManager or others need tile data by coord)
|
||
2. In the existing `visible_tiles` iteration loop (lines 256-268), add: `_tile_by_coord[pos] = vtile`
|
||
3. Replace the O(N) zone_id scan (lines 243-252) with:
|
||
```gdscript
|
||
var player_pos_key := Vector2i(int(player_position.x), int(player_position.y))
|
||
var player_tile = _tile_by_coord.get(player_pos_key, null)
|
||
current_zone_id = player_tile.get("zone_id", "") if player_tile else ""
|
||
```
|
||
4. Remove the old loop block (lines 249-252)
|
||
|
||
**Gotcha:** The zone_id scan (lines 243-252) currently runs BEFORE the `visible_tiles` iteration that builds `visible_positions` (lines 256-268). You need to reorder: build `_tile_by_coord` in the main tile loop first, then do the zone_id lookup. The comment on line 244 ("O(1) via visible_positions dict would be ideal") confirms this was known and flagged by Tyre in a PR review — this ticket resolves it.
|
||
|
||
**Net-zero complexity:** The tile loop is already there. This adds one dict-set per tile in the existing loop, then removes the separate zone_id scan loop entirely. No behavioral change; the same `current_zone_id` value is produced.
|
||
|
||
**Test:** Verify `current_zone_id` is populated correctly after the refactor by checking the existing client P-tests or adding a unit test in gdUnit4.
|
||
|
||
### #540 — Adjust sprite camera to D-019 angle (~15-20° from vertical)
|
||
|
||
**Blocked by #541 (visual).** Do not start until Araminta's 3D sprite render pipeline is set up and has produced at least a test sprite at the new angle.
|
||
|
||
**What exists:** The Godot client renders entity, object, and wall sprites. Current sprites are rendered at 90° (pure top-down). D-019 amendment specifies "the angle": Camera3D at -72.5° from horizontal (= ~17.5° from vertical, the midpoint of the 15-20° range). This matches Rimworld's orthographic-with-art-tilt approach. The Godot gameplay camera stays orthographic — the tilt is entirely an art convention baked into sprites.
|
||
|
||
**What to deliver:**
|
||
|
||
Once #541 delivers the offline render pipeline and a set of test sprites at -72.5°:
|
||
1. Update `client/scripts/rendering/entity_renderer.gd` to reference the new sprite assets (path may change per Araminta's pipeline output structure)
|
||
2. Verify `client/scripts/rendering/tile_renderer.gd` and `world_renderer.gd` — wall/object sprites from #541 should slot in at the same visual tile size (64×64px runtime per D-043 resolution chain)
|
||
3. Confirm the z-sorting logic in `entity_renderer.gd` still produces correct results: entities south-facing should overlap objects on the same row correctly with the tilted perspective
|
||
4. Check that the fog shader in `fog_shader.gd` is unaffected — fog is screen-space and driven by the LOS mask, not by sprite perspective (D-019: "tile grid remains square/orthogonal, vision cone math remains pure 2D")
|
||
|
||
**Key constraint from D-066:** Entity sprites render across a 2×2 sim tile footprint. With the tilt, the south-facing face of entities/objects is now visible — confirm the sprite footprint is still contained within the 2×2 sim tile bounding box so interaction range (2 sim tiles) remains accurate.
|
||
|
||
**What NOT to change:** The `client/scripts/rendering/fog_shader.gd`, fog vision cone shape, or any LOS computation. Those are 2D sim-space and are unaffected by the art-direction angle.
|
||
|
||
## Dependency Chain
|
||
|
||
```
|
||
#543 (zone_id O(1)) → standalone, no dependencies
|
||
|
||
#541 (visual: 3D render pipeline) → #540 (sprite camera angle)
|
||
```
|
||
|
||
## PR Workflow
|
||
|
||
When ready to submit, create a PR with `tea` CLI. **All flags are required** to avoid TTY prompts (see CLAUDE.md "Gitea access" section):
|
||
|
||
```bash
|
||
tea pr create --repo jpmschweitzer/settled-reach --login schweitz --title "feat(client): sprint 16 zone lookup + sprite angle" --description "body" --base main --head client
|
||
```
|