From 332da7c18172e722b9c19b3c22c15aa49ce9a010 Mon Sep 17 00:00:00 2001 From: hz Date: Thu, 23 Jul 2026 15:13:56 -0500 Subject: [PATCH] Fix stale-node crash in UI sound auto-wiring node_added already fires once per node as it enters the tree (including every descendant of a newly-added subtree), so the recursive call_deferred in _on_node_added was redundant and held a raw Node reference across a frame boundary. If that node got freed before the deferred call fired (e.g. a container torn down and rebuilt the same frame), the engine's message queue couldn't marshal the argument and threw "Cannot convert argument 1 from Object to Object". Wiring synchronously removes the window entirely. Also silences the intentional integer division in _duration_text, matching the same annotation already applied to _elapsed_simulated_text. --- scripts/autoload/ui_sound_service.gd | 3 ++- scripts/ui/ccs_player.gd | 1 + 2 files changed, 3 insertions(+), 1 deletion(-) diff --git a/scripts/autoload/ui_sound_service.gd b/scripts/autoload/ui_sound_service.gd index 49dca3c..21b2ce9 100644 --- a/scripts/autoload/ui_sound_service.gd +++ b/scripts/autoload/ui_sound_service.gd @@ -88,7 +88,8 @@ func _next_available_player() -> AudioStreamPlayer: func _on_node_added(node: Node) -> void: - call_deferred("_wire_node", node) + if node is Button: + _wire_button(node) func _wire_existing_buttons() -> void: diff --git a/scripts/ui/ccs_player.gd b/scripts/ui/ccs_player.gd index 7015e93..fc760a2 100644 --- a/scripts/ui/ccs_player.gd +++ b/scripts/ui/ccs_player.gd @@ -917,6 +917,7 @@ func _elapsed_simulated_text(minutes: int) -> String: func _duration_text(seconds: int) -> String: + @warning_ignore("integer_division") return "%02d:%02d" % [seconds / 60, seconds % 60]