diff --git a/addons/escoria-core/game/core-scripts/esc/esc_event_manager.gd b/addons/escoria-core/game/core-scripts/esc/esc_event_manager.gd index a05fed91..b8ce6769 100644 --- a/addons/escoria-core/game/core-scripts/esc/esc_event_manager.gd +++ b/addons/escoria-core/game/core-scripts/esc/esc_event_manager.gd @@ -54,6 +54,14 @@ var _channels_state: Dictionary = {} # Whether we're currently waiting for an async event to complete, per channel var _yielding: Dictionary = {} +# Whether we're currently changing the scene. +var _changing_scene: bool = false setget set_changing_scene + +var _change_scene: ChangeSceneCommand + +func _init(): + _change_scene = ChangeSceneCommand.new() + # Make sure to stop when pausing the game func _ready(): @@ -70,7 +78,7 @@ func _process(delta: float) -> void: for channel_name in events_queue.keys(): channel_yielding = _yielding.get(channel_name, false) - if events_queue[channel_name].size() == 0 or channel_yielding: + if events_queue[channel_name].size() == 0 or channel_yielding or _changing_scene: continue if is_channel_free(channel_name): _channels_state[channel_name] = false @@ -159,6 +167,9 @@ func _process(delta: float) -> void: func queue_event_from_esc(script_object: ESCScript, event: String, channel: String, block: bool) -> int: + if _changing_scene: + return ESCExecution.RC_WONT_QUEUE + if channel == CHANNEL_FRONT: escoria.event_manager.queue_event(script_object.events[event]) else: @@ -191,7 +202,13 @@ func queue_event_from_esc(script_object: ESCScript, event: String, # # #### Parameters # - event: Event to run -func queue_event(event: ESCEvent) -> void: +func queue_event(event: ESCEvent, force: bool = false) -> void: + if _changing_scene and not force: + escoria.logger.info( + "Changing scenes. Won't queue event '%s'." % event.name + ) + return + # Don't queue the same event more than once in a row. var last_event = _get_last_event_queued(CHANNEL_FRONT) @@ -260,9 +277,12 @@ func queue_background_event(channel_name: String, event: ESCEvent) -> void: # Interrupt the events currently running. -func interrupt_running_event(): +# +# #### Parameters +# - exceptions: an optional list of events which should be left running +func interrupt_running_event(exceptions: PoolStringArray = []): for channel_name in _running_events.keys(): - if _running_events[channel_name] != null: + if _running_events[channel_name] != null and not channel_name in exceptions: _running_events[channel_name].interrupt() _channels_state[channel_name] = true @@ -291,6 +311,20 @@ func get_running_event(name: String) -> ESCEvent: return _running_events[name] if name in _running_events else null +# Setter for _changing_scene. +# +# #### Parameterse +# - value: boolean value to set _changing_scene to +func set_changing_scene(value: bool) -> void: + _changing_scene = value + + # If we're changing scenes, interrupt any (other) running events and purge + # all event queues. + if value: + clear_event_queue() + interrupt_running_event([_change_scene.get_command_name()]) + + # The event finished running # # #### Parameters diff --git a/addons/escoria-core/game/core-scripts/esc/esc_room_manager.gd b/addons/escoria-core/game/core-scripts/esc/esc_room_manager.gd index 66407d38..f2f4f437 100644 --- a/addons/escoria-core/game/core-scripts/esc/esc_room_manager.gd +++ b/addons/escoria-core/game/core-scripts/esc/esc_room_manager.gd @@ -52,8 +52,10 @@ func register_reserved_globals() -> void: # automatically or to leave the responsibility to the developer. func change_scene(room_path: String, enable_automatic_transitions: bool) -> void: # Clear the event queue to remove other events (there could be duplicate - # events in there so we avoid running these multiple times) - escoria.event_manager.clear_event_queue() + # events in there so we avoid running these multiple times). Also sets a + # flag indicating a changing scene and interrupts any other currently-running + # events. + escoria.event_manager.set_changing_scene(true) # If FORCE_LAST_SCENE_NULL is true, force ESC_LAST_SCENE to empty if escoria.globals_manager.get_global( \ @@ -219,7 +221,8 @@ func _perform_script_events(room: ESCRoom) -> void: get_class() ) escoria.event_manager.queue_event( - script_transition_out.events[escoria.event_manager.EVENT_TRANSITION_OUT] + script_transition_out.events[escoria.event_manager.EVENT_TRANSITION_OUT], + true ) # Unpause the game if it was @@ -354,7 +357,8 @@ func _perform_script_events(room: ESCRoom) -> void: get_class() ) escoria.event_manager.queue_event( - script_transition_in.events[escoria.event_manager.EVENT_TRANSITION_IN] + script_transition_in.events[escoria.event_manager.EVENT_TRANSITION_IN], + true ) var ready_event_added: bool = false @@ -420,7 +424,7 @@ func _run_script_event(event_name: String, room: ESCRoom): room.compiled_script.events[event_name].statements.size() ] ) - escoria.event_manager.queue_event(room.compiled_script.events[event_name]) + escoria.event_manager.queue_event(room.compiled_script.events[event_name], true) return true else: return false diff --git a/addons/escoria-core/game/core-scripts/esc/types/esc_execution.gd b/addons/escoria-core/game/core-scripts/esc/types/esc_execution.gd index 2c6b512e..781c1ea4 100644 --- a/addons/escoria-core/game/core-scripts/esc/types/esc_execution.gd +++ b/addons/escoria-core/game/core-scripts/esc/types/esc_execution.gd @@ -10,4 +10,5 @@ class_name ESCExecution # * RC_ERROR: Error running a command # * RC_REPEAT: Repeat the current scope from the beginning # * RC_INTERRUPTED: Event was interrupted -enum {RC_OK, RC_CANCEL, RC_ERROR, RC_REPEAT, RC_INTERRUPTED} +# * RC_WONT_QUEUE: Event won't or can't be queued +enum {RC_OK, RC_CANCEL, RC_ERROR, RC_REPEAT, RC_INTERRUPTED, RC_WONT_QUEUE}