extends Node # This script is basically the scene-switcher. # Global id of the last scene the player was before current scene var last_scene_global_id # Current scene room being displayed var current_scene var wait_level var screen_ofs = Vector2(0, 0) # ESCBackgroundMusic node onready var bg_music = $bg_music onready var scene_transition = $layers/curtain/scene_transition func _ready(): $layers/wait_timer.connect("timeout", self, "_on_wait_finished") func set_scene(p_scene, run_events=true): """ Sets p_scene as current scene If run_events=true, plays the events defined in :setup event """ if !p_scene: escoria.logger.report_errors("main", ["Trying to set empty scene"]) if current_scene != null: clear_scene() # get_node("/root").add_child(p_scene) add_child(p_scene) # Ensure we don't have a regular event running when changing scenes if escoria.esc_runner.running_event: assert(escoria.esc_runner.running_event.ev_name == "load") var events : Dictionary = {} if "esc_script" in p_scene and p_scene.esc_script and run_events: events = escoria.esc_compiler.load_esc_file(p_scene.esc_script) # # :setup is pretty much required in the code, but fortunately # # we can help out with cases where one isn't necessary otherwise # if not "setup" in events: # var fake_setup = escoria.esc_compiler.compile_str(":setup\n") # events["setup"] = fake_setup["setup"] # # escoria.esc_runner.run_event(events["setup"]) # # We need to ensure that :setup event is finished before adding the next event. # var setup_done = false # while !setup_done: # var event_name = yield(escoria.esc_runner, "event_done") # if event_name == "setup": # setup_done = true # # # If scene was never visited, run "ready" event # if !escoria.esc_runner.scenes_cache.has(p_scene.global_id) \ # and "ready" in events: # escoria.esc_runner.run_event(events["ready"]) # set_current_scene(p_scene, run_events) set_camera_limits() return events func set_current_scene(p_scene, run_events=true): current_scene = p_scene $"/root".move_child(current_scene, 0) # Loading a save game must set the scene but not run events if "events_path" in current_scene and current_scene.events_path and run_events: if escoria.esc_runner.game: # Having a game with `:setup` means we must wait for it to finish if "setup" in escoria.esc_runner.game: if not escoria.esc_runner.running_event: escoria.logger.report_errors("main.gd:set_current_scene()", ["escoria.esc_runner.game has setup but no running_event"]) if escoria.esc_runner.running_event.ev_name != "setup": escoria.logger.report_errors("main.gd:set_current_scene()", ["escoria.esc_runner.game has setup but it is not running: " + escoria.esc_runner.running_event.ev_name]) yield(escoria.esc_runner, "event_done") else: escoria.esc_compiler.load_file(current_scene.events_path) # For a new game, we must run `:setup` if available # and wait for it to finish if "setup" in escoria.esc_runner.game: escoria.esc_runner.run_event(escoria.esc_runner.game["setup"]) yield(escoria.esc_runner, "event_done") if not escoria.esc_runner.running_event: escoria.esc_runner.run_game() escoria.esc_runner.register_object("_scene", p_scene, true) # Force overwrite of global check_game_scene_methods() func clear_scene(): if current_scene == null: return escoria.esc_runner.clear_current_action() escoria.esc_runner.clear_current_tool() # escoria.esc_runner.hover_clear_stack() # escoria.clear_inventory() last_scene_global_id = current_scene.global_id escoria.esc_runner.set_global("ESC_LAST_SCENE", last_scene_global_id, true) get_node("/root").remove_child(current_scene) current_scene.free() current_scene = null func wait(params : Array, level): wait_level = level $layers/wait_timer.set_wait_time(float(params[0])) $layers/wait_timer.set_one_shot(true) $layers/wait_timer.start() func _on_wait_finished(): escoria.esc_level_runner.finished(wait_level) func set_camera_limits(camera_limit_id : int = 0): var limits = {} var scene_camera_limits = current_scene.camera_limits[camera_limit_id] if scene_camera_limits.size.x == 0 and scene_camera_limits.size.y == 0: var area = Rect2() for child in current_scene.get_children(): if child is ESCBackground: area = child.get_full_area_rect2() break # if the background is smaller than the viewport, we want the camera to stick centered on the background if area.size.x == 0 or area.size.y == 0 or area.size < get_viewport().size: escoria.logger.report_warning("main.gd:set_camera_limits()", "No limit area! Using viewport.") area.size = get_viewport().size escoria.logger.info("Setting camera limits from scene ", [area]) limits = { "limit_left": area.position.x, "limit_right": area.position.x + area.size.x, "limit_top": area.position.y, "limit_bottom": area.position.y + area.size.y, "set_default": true, } else: limits = { "limit_left": scene_camera_limits.position.x, "limit_right": scene_camera_limits.position.x + scene_camera_limits.size.x, "limit_top": scene_camera_limits.position.y, "limit_bottom": scene_camera_limits.position.y + scene_camera_limits.size.y + screen_ofs.y * 2, "set_default": true, } escoria.logger.info("Setting camera limits from parameter ", [scene_camera_limits]) current_scene.game.get_node("camera").set_limits(limits) current_scene.game.get_node("camera").set_offset(screen_ofs * 2) """ The game.tscn scene's root node script MUST implement the following methods. If they do not exist, stop immediately. Implement them, even if empty """ func check_game_scene_methods(): assert(current_scene.game.has_method("left_click_on_bg")) assert(current_scene.game.has_method("right_click_on_bg")) assert(current_scene.game.has_method("left_double_click_on_bg")) assert(current_scene.game.has_method("element_focused")) assert(current_scene.game.has_method("element_unfocused")) assert(current_scene.game.has_method("left_click_on_item")) assert(current_scene.game.has_method("right_click_on_item")) assert(current_scene.game.has_method("left_double_click_on_item")) assert(current_scene.game.has_method("open_inventory")) assert(current_scene.game.has_method("close_inventory")) assert(current_scene.game.has_method("left_click_on_inventory_item")) assert(current_scene.game.has_method("right_click_on_inventory_item")) assert(current_scene.game.has_method("left_double_click_on_inventory_item")) assert(current_scene.game.has_method("inventory_item_focused")) assert(current_scene.game.has_method("inventory_item_unfocused")) assert(current_scene.game.has_method("mousewheel_action")) assert(current_scene.game.has_method("hide_ui")) assert(current_scene.game.has_method("show_ui")) assert(current_scene.game.has_method("_on_event_done"))