feat(client): Sprint 12 — renderer fix, sound pipeline, medium-range indicators

#345: entity_renderer.gd already used entity_id; added regression tests
  confirming old "id" field is rejected and "entity_id" is accepted.

#447 (OQ-29): DIALOGUE_MAX_WIDTH = 1920 added to constants.gd. Full
  viewport width at target resolution (60 × TILE_SIZE), per D-061 Lead
  directive "max-width". Recorded as D-076 in decisions/perception.md.

#126: SoundIndicatorRenderer — fog-edge directional arrows for medium-range
  sound events (D-018). Node2D at z:951 in World scene. Color-coded per
  D-018/D-069 (neutral/voice/danger). GameState.medium_sound_events
  partitions Medium events from snapshot sound_events field. Tests added
  to test_rendering.gd; Hoshe's test_sound_indicators.gd stubs updated.

#125: Close-range stereo audio pipeline wired. AudioManager.play_sound_event()
  maps event_type to D-038 asset key (Footstep/FootstepSprint → sfx_footstep_*).
  GameState.close_sound_events partitions Close events. main.gd calls
  _play_close_sound_events() each snapshot tick. test_audio_bus_routing.gd
  Layer 4 stubs upgraded to real tests.

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
This commit is contained in:
2026-02-19 13:33:05 +01:00
co-authored by Claude Sonnet 4.6
parent f7e5b7eb63
commit c6bd7c2db2
11 changed files with 913 additions and 2 deletions
+26
View File
@@ -54,6 +54,14 @@ var rng_seed: Variant = null
# v7 fields (#431, D-059/D-060)
var pending_recognitions: Array = [] # [{entity_id, x, y, z, remaining_ticks, total_delay_ticks}]
# #126, D-018: Medium-range sound events for fog-edge directional indicators.
# Format: [{x, y, event_type, range_category}] — server sends current medium events per tick.
var medium_sound_events: Array = []
# #125, D-018: Close-range sound events for positional 2D audio.
# Format: [{x, y, event_type, range_category}] — consumed once per tick in main.gd.
var close_sound_events: Array = []
func apply_snapshot(snapshot: Dictionary) -> void:
current_snapshot = snapshot
@@ -157,6 +165,24 @@ func apply_snapshot(snapshot: Dictionary) -> void:
else:
rng_seed = null
# D-018: Sound events from server — partition by range_category.
# #126: Medium → fog-edge directional indicators.
# #125: Close → positional 2D audio via AudioManager.
if snapshot.has("sound_events") and snapshot.sound_events is Array:
medium_sound_events = []
close_sound_events = []
for se in snapshot.sound_events:
if not se is Dictionary:
continue
var rc: String = se.get("range_category", "")
if rc == "Medium":
medium_sound_events.append(se)
elif rc == "Close":
close_sound_events.append(se)
else:
medium_sound_events = []
close_sound_events = []
# v2: visible_tiles with visibility sectors
# Derives visible_positions when not explicitly provided (real server mode)
if snapshot.has("visible_tiles") and snapshot.visible_tiles is Array and snapshot.visible_tiles.size() > 0: