fix(client): address PR #43 review — walk key mismatch + 5 suggestions

Fix SOUND_EVENT_ASSETS walk-speed keys to match actual filename
(sfx_footstep_metal_walk), add play_loop null guard, source indicator
colors from Constants, extract CAMERA_DEFAULT_ZOOM, document
consume-once semantics on close_sound_events.

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
This commit is contained in:
2026-02-19 15:37:20 +01:00
co-authored by Claude Opus 4.6
parent e1a1a9cfc2
commit dfcafee3ee
5 changed files with 18 additions and 11 deletions
+6 -4
View File
@@ -142,6 +142,8 @@ func play_loop(asset_key: String, bus: String = BUS_AMBIENT) -> AudioStreamPlaye
return null
stop_loop(asset_key)
var loop_stream := stream.duplicate() as AudioStream
if loop_stream == null:
return null
_enable_loop(loop_stream)
var player := AudioStreamPlayer.new()
player.stream = loop_stream
@@ -175,10 +177,10 @@ func stop_all_loops() -> void:
# No asset for Voice events in v0.1 — play_sound_event no-ops gracefully
# (D-038: "renders as audio if asset exists, or visual indicator + monologue if not").
const SOUND_EVENT_ASSETS: Dictionary = {
"Footstep": "sfx_footstep_metal",
"FootstepWalk": "sfx_footstep_metal",
"FootstepCareful":"sfx_footstep_metal",
"FootstepCrouch": "sfx_footstep_metal",
"Footstep": "sfx_footstep_metal_walk",
"FootstepWalk": "sfx_footstep_metal_walk",
"FootstepCareful":"sfx_footstep_metal_walk", # D-053: same asset until stance-differentiated audio lands
"FootstepCrouch": "sfx_footstep_metal_walk", # D-053: same asset until stance-differentiated audio lands
"FootstepSprint": "sfx_footstep_metal_run",
"FootstepRun": "sfx_footstep_metal_run",
}
+3
View File
@@ -96,6 +96,9 @@ const FACING_INDICATOR_OFFSET: float = 14.0
# two columns of text comfortably, leaves world game visible alongside.
const DIALOGUE_MAX_WIDTH: int = 640
# Default camera zoom — used as fallback when get_camera_2d() returns null
const CAMERA_DEFAULT_ZOOM: Vector2 = Vector2(2.0, 2.0)
# #517: Implant UI font color grading — avoid pure white, project through a lens
const IMPLANT_TEXT_COLOR: Color = Color("#E0F7FA") # Cyan-white — primary text
const IMPLANT_TEXT_DIM: Color = Color("#9EBFC4") # Dimmed variant — secondary text
+2
View File
@@ -201,6 +201,8 @@ func _process(_delta: float) -> void:
# D-018 #125: Play close-range sound events — fired once per snapshot tick.
# Each event is passed to AudioManager.play_sound_event() for 2D positional playback
# on the WorldSFX bus. Events with no registered asset are silently skipped (D-038).
# Consume-once: events are cleared after processing so they don't replay if
# _process runs again before the next server tick (D-009 multiplayer-safe pattern).
func _play_close_sound_events() -> void:
for evt in GameState.close_sound_events:
if not evt is Dictionary or not evt.has("x") or not evt.has("y"):
@@ -26,10 +26,10 @@ const EDGE_INSET: float = 20.0 # Pixels inward from viewport edge
const ARROW_HALF: float = 7.0 # Half-width of arrowhead base
const ARROW_LEN: float = 12.0 # Length from tip to base
# D-018/D-069 colors
const COLOR_NEUTRAL: Color = Color("#c8d0e0") # Generic / footstep
const COLOR_VOICE: Color = Color("#e8c547") # Speech / conversation
const COLOR_DANGER: Color = Color("#d45d5d") # Alert / threat / gunshot
# D-018/D-069 colors — sourced from Constants to prevent palette drift
const COLOR_NEUTRAL: Color = Constants.INSERT_COLOR_TEXT # Generic / footstep
const COLOR_VOICE: Color = Constants.ENTITY_COLOR_POI # Speech / conversation
const COLOR_DANGER: Color = Constants.ENTITY_COLOR_HOSTILE # Alert / threat / gunshot
# Indicators: [{x, y, event_type, elapsed}]
var _indicators: Array = []
@@ -89,7 +89,7 @@ func _draw() -> void:
# the fog edge and don't clip to the physical screen border.
var vp_size := get_viewport().get_visible_rect().size
var cam := get_viewport().get_camera_2d()
var zoom := cam.zoom if cam else Vector2(2.0, 2.0)
var zoom := cam.zoom if cam else Constants.CAMERA_DEFAULT_ZOOM
var half_extents: Vector2 = vp_size / (2.0 * zoom)
for ind in _indicators:
+2 -2
View File
@@ -272,9 +272,9 @@ func test_audio_manager_sound_event_assets_registry_exists() -> void:
assert_that(AudioManager.SOUND_EVENT_ASSETS.size()).is_greater(0)
func test_audio_manager_footstep_maps_to_sfx_footstep_metal() -> void:
## #125: "Footstep" event type → sfx_footstep_metal (D-038 asset).
## #125: "Footstep" event type → sfx_footstep_metal_walk (D-038 asset).
assert_that(AudioManager.SOUND_EVENT_ASSETS.has("Footstep")).is_true()
assert_that(AudioManager.SOUND_EVENT_ASSETS["Footstep"]).is_equal("sfx_footstep_metal")
assert_that(AudioManager.SOUND_EVENT_ASSETS["Footstep"]).is_equal("sfx_footstep_metal_walk")
func test_audio_manager_footstep_sprint_maps_to_sfx_footstep_metal_run() -> void:
## #125: "FootstepSprint" → sfx_footstep_metal_run (D-038 faster footstep).