extends SceneTree const BattleSceneScript := preload("res://scripts/scenes/battle_scene.gd") const SAVE_PATH := "user://campaign_save.json" const MANUAL_SAVE_PATH := "user://campaign_manual_save.json" const SETTINGS_PATH := "user://heros_settings.json" func _init() -> void: var save_backup := _backup_user_file(SAVE_PATH) var manual_backup := _backup_user_file(MANUAL_SAVE_PATH) var settings_backup := _backup_user_file(SETTINGS_PATH) var failures: Array[String] = [] _clear_user_file(SAVE_PATH) _clear_user_file(MANUAL_SAVE_PATH) _clear_user_file(SETTINGS_PATH) _check_title_menu_start_load_and_settings(failures) if not _restore_user_file(SAVE_PATH, save_backup): failures.append("could not restore campaign save after title menu smoke") if not _restore_user_file(MANUAL_SAVE_PATH, manual_backup): failures.append("could not restore manual campaign save after title menu smoke") if not _restore_user_file(SETTINGS_PATH, settings_backup): failures.append("could not restore title settings after title menu smoke") if failures.is_empty(): print("title menu smoke ok") quit(0) return for failure in failures: push_error(failure) quit(1) func _check_title_menu_start_load_and_settings(failures: Array[String]) -> void: var scene = BattleSceneScript.new() scene._ready() if scene.title_screen_root == null or not scene.title_screen_root.visible: failures.append("title screen should be visible on startup") if scene.briefing_panel == null or scene.briefing_panel.visible: failures.append("briefing should stay hidden behind the title screen") if scene.title_start_button == null or scene.title_start_button.text != "처음부터 시작": failures.append("title screen should expose Start from Beginning") if scene.title_load_button == null or scene.title_load_button.text != "게임 로드": failures.append("title screen should expose Game Load") elif not scene.title_load_button.disabled: failures.append("Game Load should be disabled when no save exists") if scene.title_settings_button == null or scene.title_settings_button.text != "환경 설정": failures.append("title screen should expose Settings") scene._on_title_settings_pressed() if scene.title_settings_panel == null or not scene.title_settings_panel.visible: failures.append("title settings panel should open from the title screen") if scene.title_bgm_toggle == null or scene.title_sfx_toggle == null or scene.title_edge_scroll_toggle == null: failures.append("title settings should expose BGM, SFX, and edge-scroll toggles") if scene.title_bgm_volume_slider == null or scene.title_sfx_volume_slider == null: failures.append("title settings should expose BGM and SFX volume sliders") scene._on_title_bgm_toggled(false) if scene.title_bgm_enabled: failures.append("BGM toggle should disable background music") scene._on_title_bgm_volume_changed(45.0) if scene.title_bgm_volume_percent != 45: failures.append("BGM volume slider should update the saved BGM volume percent") scene._on_title_sfx_toggled(false) if scene.title_sfx_enabled: failures.append("SFX toggle should disable sound effects") scene._on_title_sfx_volume_changed(35.0) if scene.title_sfx_volume_percent != 35: failures.append("SFX volume slider should update the saved SFX volume percent") scene._on_title_edge_scroll_toggled(false) if scene.title_edge_scroll_enabled: failures.append("edge-scroll toggle should disable edge scrolling") if scene._update_edge_scroll(0.25): failures.append("edge scrolling should not move while disabled in settings") var persisted_scene = BattleSceneScript.new() persisted_scene._ready() if persisted_scene.title_bgm_enabled or persisted_scene.title_sfx_enabled or persisted_scene.title_edge_scroll_enabled: failures.append("title settings toggles should persist into a new scene instance") if persisted_scene.title_bgm_volume_percent != 45 or persisted_scene.title_sfx_volume_percent != 35: failures.append("title settings volume values should persist into a new scene instance") persisted_scene.free() scene._on_title_settings_back_pressed() if scene.title_settings_panel != null and scene.title_settings_panel.visible: failures.append("settings back should hide the title settings panel") scene._on_title_start_pressed() if scene.title_screen_root != null and scene.title_screen_root.visible: failures.append("starting a new game should hide the title screen") if scene.briefing_panel == null or not scene.briefing_panel.visible: failures.append("starting a new game should enter the first briefing") if not scene.campaign_state.has_save(): failures.append("starting a new game should create the main campaign save") scene._show_title_menu() scene._update_title_menu_state() if scene.title_load_button == null or scene.title_load_button.disabled: failures.append("Game Load should become available after a campaign save exists") scene._on_title_load_pressed() if scene.title_screen_root != null and scene.title_screen_root.visible: failures.append("loading a saved game should hide the title screen") if scene.briefing_panel == null or not scene.briefing_panel.visible: failures.append("loading a saved game should enter the current campaign briefing") scene.free() func _backup_user_file(path: String) -> Dictionary: if not FileAccess.file_exists(path): return {"exists": false, "text": ""} return { "exists": true, "text": FileAccess.get_file_as_string(path) } func _restore_user_file(path: String, backup: Dictionary) -> bool: if bool(backup.get("exists", false)): var file := FileAccess.open(path, FileAccess.WRITE) if file == null: return false file.store_string(str(backup.get("text", ""))) return true return _clear_user_file(path) func _clear_user_file(path: String) -> bool: if not FileAccess.file_exists(path): return true return DirAccess.remove_absolute(ProjectSettings.globalize_path(path)) == OK