class_name World extends Node ## Access and flow control for the game world. const SAVE_PATH_FMT := "user://{0}.state.res" @export var pause_enabled := true @export var save_state: SaveState @export var manager: WorldManager @export var spook_manager: SpookManager @export_category("Game Scenes") @export var initial_level: PackedScene @export var pause_scene: PackedScene @export var kill_screen_scene: PackedScene var current_level: PackedScene @onready var level_root: Node3D = %LevelRoot @onready var ui_root: Control = %UIRoot @onready var save_icon: MarginContainer = %SaveIcon static var instance: World func _ready() -> void: World.instance = self manager.alert_raised.connect(spook_manager.on_alert_raised) manager.alert_cleared.connect(spook_manager.on_alert_cleared) manager.player_dead.connect(on_player_death) if initial_level: load_level(initial_level) func _unhandled_input(event: InputEvent) -> void: if event.is_action_pressed("pause") and pause_enabled: pause() func pause() -> void: get_tree().paused = true var pause_menu: Control = pause_scene.instantiate() ui_root.add_child(pause_menu) pause_menu.tree_exiting.connect(unpause) func unpause() -> void: get_tree().paused = false func load_level(level: PackedScene) -> void: for c: Node in level_root.get_children(): c.queue_free() level_root.remove_child(c) current_level = level print("Instantiating level from ", level.resource_path) var level_instance := level.instantiate() level_root.add_child(level_instance) if save_state: save_state.load_to_world(self) print("Done!") spook_manager.after_level_init() func on_player_death() -> void: var kill_screen: Control = kill_screen_scene.instantiate() kill_screen.tree_exiting.connect(on_game_over) ui_root.add_child(kill_screen) func _reload_saved(save: SaveState) -> void: save_state = save load_level(current_level) func on_game_over() -> void: # reload the level from the last save var save_path := World.get_level_save_path(current_level) if FileAccess.file_exists(save_path): Game.instance.queue_load(save_path).finally(_reload_saved) else: load_level(current_level) func save_progress() -> void: print("Preparing save state...") save_icon.show() var save := SaveState.serialize(self) var save_path := World.get_level_save_path(current_level) print("Writing save to ", save_path) ResourceSaver.save(save, save_path) save_icon.hide() print("Done!") static func get_save_path(level_path: String) -> String: return SAVE_PATH_FMT.format([level_path.get_basename().get_file()]) static func get_level_save_path(level: PackedScene) -> String: return World.get_save_path(level.resource_path)