diff --git a/client/scripts/autoloads/input_mapper.gd b/client/scripts/autoloads/input_mapper.gd index f947d61b8..6128d4b4d 100644 --- a/client/scripts/autoloads/input_mapper.gd +++ b/client/scripts/autoloads/input_mapper.gd @@ -128,6 +128,7 @@ func _unhandled_input(event: InputEvent) -> void: if action == Action.SAVE_GAME or action == Action.LOAD_GAME: var game_id := GameState.current_game_id if game_id.is_empty(): + get_viewport().set_input_as_handled() return # No active session — ignore save/load entry["action_data"] = {"path": "user://saves/" + game_id + "/quicksave.sav"} input_queue.append(entry) diff --git a/client/scripts/autoloads/session_manager.gd b/client/scripts/autoloads/session_manager.gd index 5b719b8ef..87bd3c90d 100644 --- a/client/scripts/autoloads/session_manager.gd +++ b/client/scripts/autoloads/session_manager.gd @@ -85,6 +85,8 @@ func quit_to_menu() -> void: func _do_quit_to_menu() -> void: _cleanup_quit_dialog() # #554: Trigger quicksave before navigating to menu. + # send_input() buffers the command — defer scene change by one frame so + # SimBridge._process() flushes the outbound buffer before teardown. if not GameState.current_game_id.is_empty(): var path := "user://saves/" + GameState.current_game_id + "/quicksave.sav" SimBridge.send_input({ @@ -92,7 +94,14 @@ func _do_quit_to_menu() -> void: "timestamp_msec": Time.get_ticks_msec(), "action_data": {"path": path}, }) - GameState.current_game_id = "" + GameState.current_game_id = "" + _navigate_to_menu.call_deferred() + else: + GameState.current_game_id = "" + get_tree().change_scene_to_file(MENU_SCENE) + + +func _navigate_to_menu() -> void: get_tree().change_scene_to_file(MENU_SCENE) diff --git a/client/ui/monologue_display.gd b/client/ui/monologue_display.gd index 0b9eacba8..37a52844d 100644 --- a/client/ui/monologue_display.gd +++ b/client/ui/monologue_display.gd @@ -64,7 +64,10 @@ func _process(delta: float) -> void: var now := float(Time.get_ticks_msec()) if now >= _next_fade_in_msec: var next: Dictionary = _queue.pop_front() - _show_line(next.text, next.duration, next.priority, next.is_urgent, next.lattice_profile) + if next.get("is_notification", false): + _show_notification_line(next.text) + else: + _show_line(next.text, next.duration, next.priority, next.is_urgent, next.lattice_profile) # Display a monologue line. @@ -82,7 +85,15 @@ func show_notification(text: String) -> void: if _visible.size() < MAX_VISIBLE and now >= _next_fade_in_msec: _show_notification_line(text) else: - _enqueue(text, _NOTIFICATION_DURATION, 1, false, "") + var entry := {text = text, duration = _NOTIFICATION_DURATION, priority = 1, is_urgent = false, lattice_profile = "", is_notification = true} + if _queue.size() < MAX_QUEUE: + _queue.append(entry) + _queue.sort_custom(func(a: Dictionary, b: Dictionary) -> bool: return a.priority > b.priority) + else: + var lowest := _lowest_priority_idx() + if 1 >= _queue[lowest].priority: + _queue[lowest] = entry + _queue.sort_custom(func(a: Dictionary, b: Dictionary) -> bool: return a.priority > b.priority) func show_monologue(text: String, duration: float, priority: int = 2, is_urgent: bool = false) -> void: