fix: eliminates the need to run two batches of ESC commands for loading games by introducing an extra ESC command; also corrects situations where transitions that are mixed and matched don't work together; and additional cleanup
This commit is contained in:
committed by
Julian Murgia
parent
114ef2fc55
commit
503d6134dd
@@ -0,0 +1,43 @@
|
|||||||
|
# `set_active_if_exists object active`
|
||||||
|
#
|
||||||
|
# Changes the "active" state of the object in the current room.
|
||||||
|
# Inactive objects are invisible in the room.
|
||||||
|
#
|
||||||
|
# **Parameters**
|
||||||
|
#
|
||||||
|
# - *object* Global ID of the object
|
||||||
|
# - *active* Whether `object` should be active. `active` can be `true` or `false`.
|
||||||
|
#
|
||||||
|
# @ESC
|
||||||
|
extends ESCBaseCommand
|
||||||
|
class_name SetActiveIfExistsCommand
|
||||||
|
|
||||||
|
|
||||||
|
# Return the descriptor of the arguments of this command
|
||||||
|
func configure() -> ESCCommandArgumentDescriptor:
|
||||||
|
return ESCCommandArgumentDescriptor.new(
|
||||||
|
2,
|
||||||
|
[TYPE_STRING, TYPE_BOOL],
|
||||||
|
[null, null]
|
||||||
|
)
|
||||||
|
|
||||||
|
|
||||||
|
# Validate whether the given arguments match the command descriptor
|
||||||
|
func validate(arguments: Array):
|
||||||
|
if not escoria.object_manager.has(arguments[0]):
|
||||||
|
escoria.logger.report_errors(
|
||||||
|
"set_active: invalid object",
|
||||||
|
[
|
||||||
|
"Object with global id %s not found" % arguments[0]
|
||||||
|
]
|
||||||
|
)
|
||||||
|
return false
|
||||||
|
return .validate(arguments)
|
||||||
|
|
||||||
|
|
||||||
|
# Run the command
|
||||||
|
func run(command_params: Array) -> int:
|
||||||
|
if escoria.object_manager.has(command_params[0]):
|
||||||
|
escoria.object_manager.get_object(command_params[0]).active = \
|
||||||
|
command_params[1]
|
||||||
|
return ESCExecution.RC_OK
|
||||||
@@ -56,6 +56,7 @@ func run(command_params: Array) -> int:
|
|||||||
|
|
||||||
if transition_id == ESCTransitionPlayer.TRANSITION_ID_INSTANT:
|
if transition_id == ESCTransitionPlayer.TRANSITION_ID_INSTANT:
|
||||||
escoria.logger.debug("Performing instant transition.")
|
escoria.logger.debug("Performing instant transition.")
|
||||||
|
escoria.main.scene_transition.reset_shader_cutoff()
|
||||||
return ESCExecution.RC_OK
|
return ESCExecution.RC_OK
|
||||||
|
|
||||||
escoria.logger.debug("Starting transition #%s [%s, %s]"
|
escoria.logger.debug("Starting transition #%s [%s, %s]"
|
||||||
|
|||||||
@@ -268,140 +268,123 @@ func init_room(room: ESCRoom) -> void:
|
|||||||
# #### Parameters
|
# #### Parameters
|
||||||
#
|
#
|
||||||
# - room: The ESCRoom to be initialized for use.
|
# - room: The ESCRoom to be initialized for use.
|
||||||
#
|
func _perform_script_events(room: ESCRoom) -> void:
|
||||||
# *Returns* ESCExecution.RC_OK when completed or the function's state in the
|
if room.enabled_automatic_transitions \
|
||||||
# case a coroutine is yielding.
|
and not room.is_run_directly \
|
||||||
func _perform_script_events(room: ESCRoom) -> int:
|
and not room.exited_previous_room:
|
||||||
# If we're loading from a saved game, we don't want to run :setup or :ready
|
var script_transition_out = escoria.esc_compiler.compile([
|
||||||
# as it could potentially alter the loaded save state; however, we still need
|
"%s%s" % [ESCEvent.PREFIX, escoria.event_manager.EVENT_TRANSITION_OUT],
|
||||||
# to swap the scene in since it would ordinarily happen between :setup and
|
"%s %s out" %
|
||||||
# :ready. Fun, huh?
|
[
|
||||||
if not escoria.event_manager.is_channel_free(escoria.event_manager.CHANNEL_FRONT) \
|
_transition.get_command_name(),
|
||||||
and escoria.event_manager.get_running_event(
|
escoria.project_settings_manager.get_setting(
|
||||||
escoria.event_manager.CHANNEL_FRONT
|
escoria.project_settings_manager.DEFAULT_TRANSITION
|
||||||
).name == escoria.event_manager.EVENT_LOAD:
|
)
|
||||||
escoria.main.set_scene_finish(room)
|
],
|
||||||
else:
|
"%s 0.1" % _wait.get_command_name()
|
||||||
# If the room was loaded from change_scene and automatic transitions
|
])
|
||||||
# are not disabled, do the transition out now
|
escoria.event_manager.queue_event(
|
||||||
if room.enabled_automatic_transitions \
|
script_transition_out.events[escoria.event_manager.EVENT_TRANSITION_OUT]
|
||||||
and not room.is_run_directly \
|
|
||||||
and not room.exited_previous_room:
|
|
||||||
var script_transition_out = escoria.esc_compiler.compile([
|
|
||||||
"%s%s" % [ESCEvent.PREFIX, escoria.event_manager.EVENT_TRANSITION_OUT],
|
|
||||||
"%s %s out" %
|
|
||||||
[
|
|
||||||
_transition.get_command_name(),
|
|
||||||
escoria.project_settings_manager.get_setting(
|
|
||||||
escoria.project_settings_manager.DEFAULT_TRANSITION
|
|
||||||
)
|
|
||||||
],
|
|
||||||
"%s 0.1" % _wait.get_command_name()
|
|
||||||
])
|
|
||||||
escoria.event_manager.queue_event(
|
|
||||||
script_transition_out.events[escoria.event_manager.EVENT_TRANSITION_OUT]
|
|
||||||
)
|
|
||||||
|
|
||||||
# Unpause the game if it was
|
|
||||||
escoria.set_game_paused(false)
|
|
||||||
|
|
||||||
# Wait for transition_out event to be done
|
|
||||||
var rc = yield(escoria.event_manager, "event_finished")
|
|
||||||
while rc[1] != escoria.event_manager.EVENT_TRANSITION_OUT:
|
|
||||||
rc = yield(escoria.event_manager, "event_finished")
|
|
||||||
if rc[0] != ESCExecution.RC_OK:
|
|
||||||
return rc[0]
|
|
||||||
|
|
||||||
# Hide main and pause menus
|
|
||||||
escoria.game_scene.hide_main_menu()
|
|
||||||
escoria.game_scene.unpause_game()
|
|
||||||
|
|
||||||
var setup_event_added: bool = false
|
|
||||||
# Run the setup event, if there is one.
|
|
||||||
setup_event_added = _run_script_event(escoria.event_manager.EVENT_SETUP, room)
|
|
||||||
|
|
||||||
if setup_event_added:
|
|
||||||
# Wait for setup event to be done
|
|
||||||
var rc = yield(escoria.event_manager, "event_finished")
|
|
||||||
while rc[1] != escoria.event_manager.EVENT_SETUP:
|
|
||||||
rc = yield(escoria.event_manager, "event_finished")
|
|
||||||
if rc[0] != ESCExecution.RC_OK:
|
|
||||||
return rc[0]
|
|
||||||
|
|
||||||
escoria.main.set_scene_finish()
|
|
||||||
|
|
||||||
# We know the scene has been loaded. Make its global ID available for
|
|
||||||
# use by ESC script.
|
|
||||||
escoria.globals_manager.set_global(
|
|
||||||
escoria.room_manager.GLOBAL_CURRENT_SCENE,
|
|
||||||
room.global_id,
|
|
||||||
true
|
|
||||||
)
|
)
|
||||||
|
|
||||||
# Clear queued resources
|
# Unpause the game if it was
|
||||||
escoria.resource_cache.clear()
|
escoria.set_game_paused(false)
|
||||||
|
|
||||||
escoria.inputs_manager.hotspot_focused = ""
|
# Wait for transition_out event to be done
|
||||||
|
var rc = yield(escoria.event_manager, "event_finished")
|
||||||
|
while rc[1] != escoria.event_manager.EVENT_TRANSITION_OUT:
|
||||||
|
rc = yield(escoria.event_manager, "event_finished")
|
||||||
|
if rc[0] != ESCExecution.RC_OK:
|
||||||
|
return rc[0]
|
||||||
|
|
||||||
if room.enabled_automatic_transitions \
|
# Hide main and pause menus
|
||||||
or (
|
escoria.game_scene.hide_main_menu()
|
||||||
not room.enabled_automatic_transitions \
|
escoria.game_scene.unpause_game()
|
||||||
and escoria.globals_manager.get_global( \
|
|
||||||
escoria.room_manager.GLOBAL_FORCE_LAST_SCENE_NULL)
|
|
||||||
):
|
|
||||||
var script_transition_in = escoria.esc_compiler.compile([
|
|
||||||
"%s%s" % [ESCEvent.PREFIX, escoria.event_manager.EVENT_TRANSITION_IN],
|
|
||||||
"%s %s in" %
|
|
||||||
[
|
|
||||||
_transition.get_command_name(),
|
|
||||||
escoria.project_settings_manager.get_setting(
|
|
||||||
escoria.project_settings_manager.DEFAULT_TRANSITION
|
|
||||||
)
|
|
||||||
],
|
|
||||||
"%s 0.1" % _wait.get_command_name()
|
|
||||||
])
|
|
||||||
escoria.event_manager.queue_event(
|
|
||||||
script_transition_in.events[escoria.event_manager.EVENT_TRANSITION_IN]
|
|
||||||
)
|
|
||||||
|
|
||||||
var ready_event_added: bool = false
|
var setup_event_added: bool = false
|
||||||
# Run the ready event, if there is one.
|
# Run the setup event, if there is one.
|
||||||
ready_event_added = _run_script_event(escoria.event_manager.EVENT_READY, room)
|
setup_event_added = _run_script_event(escoria.event_manager.EVENT_SETUP, room)
|
||||||
|
|
||||||
if ready_event_added:
|
if setup_event_added:
|
||||||
# Wait for ready event to be done
|
# Wait for setup event to be done
|
||||||
var rc = yield(escoria.event_manager, "event_finished")
|
var rc = yield(escoria.event_manager, "event_finished")
|
||||||
while rc[1] != escoria.event_manager.EVENT_READY:
|
while rc[1] != escoria.event_manager.EVENT_SETUP:
|
||||||
rc = yield(escoria.event_manager, "event_finished")
|
rc = yield(escoria.event_manager, "event_finished")
|
||||||
if rc[0] != ESCExecution.RC_OK:
|
if rc[0] != ESCExecution.RC_OK:
|
||||||
return rc[0]
|
return rc[0]
|
||||||
|
|
||||||
# Now that :ready is finished, if FORCE_LAST_SCENE_NULL was true, reset it
|
escoria.main.set_scene_finish()
|
||||||
# to false
|
|
||||||
if escoria.globals_manager.get_global( \
|
|
||||||
escoria.room_manager.GLOBAL_FORCE_LAST_SCENE_NULL):
|
|
||||||
|
|
||||||
escoria.globals_manager.set_global(
|
# We know the scene has been loaded. Make its global ID available for
|
||||||
escoria.room_manager.GLOBAL_FORCE_LAST_SCENE_NULL,
|
# use by ESC script.
|
||||||
false,
|
escoria.globals_manager.set_global(
|
||||||
true
|
escoria.room_manager.GLOBAL_CURRENT_SCENE,
|
||||||
)
|
room.global_id,
|
||||||
escoria.globals_manager.set_global(
|
true
|
||||||
escoria.room_manager.GLOBAL_LAST_SCENE,
|
)
|
||||||
escoria.main.current_scene.global_id \
|
|
||||||
if escoria.main.current_scene != null else "",
|
# Clear queued resources
|
||||||
true
|
escoria.resource_cache.clear()
|
||||||
)
|
|
||||||
|
escoria.inputs_manager.hotspot_focused = ""
|
||||||
|
|
||||||
|
if room.enabled_automatic_transitions \
|
||||||
|
or (
|
||||||
|
not room.enabled_automatic_transitions \
|
||||||
|
and escoria.globals_manager.get_global( \
|
||||||
|
escoria.room_manager.GLOBAL_FORCE_LAST_SCENE_NULL)
|
||||||
|
):
|
||||||
|
var script_transition_in = escoria.esc_compiler.compile([
|
||||||
|
"%s%s" % [ESCEvent.PREFIX, escoria.event_manager.EVENT_TRANSITION_IN],
|
||||||
|
"%s %s in" %
|
||||||
|
[
|
||||||
|
_transition.get_command_name(),
|
||||||
|
escoria.project_settings_manager.get_setting(
|
||||||
|
escoria.project_settings_manager.DEFAULT_TRANSITION
|
||||||
|
)
|
||||||
|
],
|
||||||
|
"%s 0.1" % _wait.get_command_name()
|
||||||
|
])
|
||||||
|
escoria.event_manager.queue_event(
|
||||||
|
script_transition_in.events[escoria.event_manager.EVENT_TRANSITION_IN]
|
||||||
|
)
|
||||||
|
|
||||||
|
var ready_event_added: bool = false
|
||||||
|
# Run the ready event, if there is one.
|
||||||
|
ready_event_added = _run_script_event(escoria.event_manager.EVENT_READY, room)
|
||||||
|
|
||||||
|
if ready_event_added:
|
||||||
|
# Wait for ready event to be done
|
||||||
|
var rc = yield(escoria.event_manager, "event_finished")
|
||||||
|
while rc[1] != escoria.event_manager.EVENT_READY:
|
||||||
|
rc = yield(escoria.event_manager, "event_finished")
|
||||||
|
if rc[0] != ESCExecution.RC_OK:
|
||||||
|
return rc[0]
|
||||||
|
|
||||||
|
# Now that :ready is finished, if FORCE_LAST_SCENE_NULL was true, reset it
|
||||||
|
# to false
|
||||||
|
if escoria.globals_manager.get_global( \
|
||||||
|
escoria.room_manager.GLOBAL_FORCE_LAST_SCENE_NULL):
|
||||||
|
|
||||||
# Make the room's global ID available for use in ESC script.
|
|
||||||
escoria.globals_manager.set_global(
|
escoria.globals_manager.set_global(
|
||||||
escoria.room_manager.GLOBAL_CURRENT_SCENE,
|
escoria.room_manager.GLOBAL_FORCE_LAST_SCENE_NULL,
|
||||||
|
false,
|
||||||
|
true
|
||||||
|
)
|
||||||
|
escoria.globals_manager.set_global(
|
||||||
|
escoria.room_manager.GLOBAL_LAST_SCENE,
|
||||||
escoria.main.current_scene.global_id \
|
escoria.main.current_scene.global_id \
|
||||||
if escoria.main.current_scene != null else "",
|
if escoria.main.current_scene != null else "",
|
||||||
true
|
true
|
||||||
)
|
)
|
||||||
|
|
||||||
return ESCExecution.RC_OK
|
# Make the room's global ID available for use in ESC script.
|
||||||
|
escoria.globals_manager.set_global(
|
||||||
|
escoria.room_manager.GLOBAL_CURRENT_SCENE,
|
||||||
|
escoria.main.current_scene.global_id \
|
||||||
|
if escoria.main.current_scene != null else "",
|
||||||
|
true
|
||||||
|
)
|
||||||
|
|
||||||
|
|
||||||
# Runs the script event from the script attached, if any.
|
# Runs the script event from the script attached, if any.
|
||||||
|
|||||||
@@ -57,6 +57,9 @@ signal mouse_right_clicked_item(global_id)
|
|||||||
signal arrived(walk_context)
|
signal arrived(walk_context)
|
||||||
|
|
||||||
|
|
||||||
|
const GROUP_ITEM_CAN_COLLIDE = "item_can_collide"
|
||||||
|
|
||||||
|
|
||||||
# The global ID of this item
|
# The global ID of this item
|
||||||
export(String) var global_id
|
export(String) var global_id
|
||||||
|
|
||||||
@@ -171,6 +174,10 @@ func _ready():
|
|||||||
|
|
||||||
_detect_children()
|
_detect_children()
|
||||||
|
|
||||||
|
# We add ourselves to this group so we can easily get a reference to all
|
||||||
|
# items in a scene tree.
|
||||||
|
add_to_group(GROUP_ITEM_CAN_COLLIDE)
|
||||||
|
|
||||||
if not self.is_connected("mouse_entered", self, "_on_mouse_entered"):
|
if not self.is_connected("mouse_entered", self, "_on_mouse_entered"):
|
||||||
connect("mouse_entered", self, "_on_mouse_entered")
|
connect("mouse_entered", self, "_on_mouse_entered")
|
||||||
if not self.is_connected("mouse_exited", self, "_on_mouse_exited"):
|
if not self.is_connected("mouse_exited", self, "_on_mouse_exited"):
|
||||||
|
|||||||
@@ -29,6 +29,7 @@ var _transition: TransitionCommand
|
|||||||
var _hide_menu: HideMenuCommand
|
var _hide_menu: HideMenuCommand
|
||||||
var _change_scene: ChangeSceneCommand
|
var _change_scene: ChangeSceneCommand
|
||||||
var _set_active: SetActiveCommand
|
var _set_active: SetActiveCommand
|
||||||
|
var _set_active_if_exists: SetActiveIfExistsCommand
|
||||||
var _set_interactive: SetInteractiveCommand
|
var _set_interactive: SetInteractiveCommand
|
||||||
var _teleport_pos: TeleportPosCommand
|
var _teleport_pos: TeleportPosCommand
|
||||||
var _set_angle: SetAngleCommand
|
var _set_angle: SetAngleCommand
|
||||||
@@ -49,6 +50,7 @@ func _init():
|
|||||||
_hide_menu = HideMenuCommand.new()
|
_hide_menu = HideMenuCommand.new()
|
||||||
_change_scene = ChangeSceneCommand.new()
|
_change_scene = ChangeSceneCommand.new()
|
||||||
_set_active = SetActiveCommand.new()
|
_set_active = SetActiveCommand.new()
|
||||||
|
_set_active_if_exists = SetActiveIfExistsCommand.new()
|
||||||
_set_interactive = SetInteractiveCommand.new()
|
_set_interactive = SetInteractiveCommand.new()
|
||||||
_teleport_pos = TeleportPosCommand.new()
|
_teleport_pos = TeleportPosCommand.new()
|
||||||
_set_angle = SetAngleCommand.new()
|
_set_angle = SetAngleCommand.new()
|
||||||
@@ -291,20 +293,6 @@ func load_game(id: int):
|
|||||||
)
|
)
|
||||||
)
|
)
|
||||||
|
|
||||||
load_event.statements = load_statements
|
|
||||||
|
|
||||||
escoria.set_game_paused(false)
|
|
||||||
escoria.event_manager.queue_event(load_event)
|
|
||||||
|
|
||||||
# Wait for the scene to be loaded so we have access to objects, etc.
|
|
||||||
var rc = yield(escoria.event_manager, "event_finished")
|
|
||||||
while rc[1] != escoria.event_manager.EVENT_LOAD:
|
|
||||||
rc = yield(escoria.event_manager, "event_finished")
|
|
||||||
|
|
||||||
# We then carry on with other "load"-related commands.
|
|
||||||
escoria.set_game_paused(true)
|
|
||||||
load_statements = []
|
|
||||||
|
|
||||||
## GLOBALS
|
## GLOBALS
|
||||||
for k in save_game.globals.keys():
|
for k in save_game.globals.keys():
|
||||||
var global_value = save_game.globals[k]
|
var global_value = save_game.globals[k]
|
||||||
@@ -324,11 +312,10 @@ func load_game(id: int):
|
|||||||
|
|
||||||
## OBJECTS
|
## OBJECTS
|
||||||
for object_global_id in save_game.objects.keys():
|
for object_global_id in save_game.objects.keys():
|
||||||
if escoria.object_manager.has(object_global_id) and \
|
if save_game.objects[object_global_id].has("active"):
|
||||||
save_game.objects[object_global_id].has("active"):
|
|
||||||
load_statements.append(ESCCommand.new("%s %s %s" \
|
load_statements.append(ESCCommand.new("%s %s %s" \
|
||||||
% [
|
% [
|
||||||
_set_active.get_command_name(),
|
_set_active_if_exists.get_command_name(),
|
||||||
object_global_id,
|
object_global_id,
|
||||||
save_game.objects[object_global_id]["active"]
|
save_game.objects[object_global_id]["active"]
|
||||||
]
|
]
|
||||||
|
|||||||
@@ -42,6 +42,9 @@ func set_scene(p_scene: Node) -> void:
|
|||||||
|
|
||||||
previous_scene = current_scene
|
previous_scene = current_scene
|
||||||
|
|
||||||
|
if is_instance_valid(previous_scene):
|
||||||
|
_disable_collisions()
|
||||||
|
|
||||||
if not p_scene.is_inside_tree():
|
if not p_scene.is_inside_tree():
|
||||||
# Set the scene's visiblity for :setup events if the new room is not the
|
# Set the scene's visiblity for :setup events if the new room is not the
|
||||||
# same one as the current room.
|
# same one as the current room.
|
||||||
@@ -207,3 +210,14 @@ func _is_same_scene(scene_1: Node, scene_2: Node) -> bool:
|
|||||||
return scene_1.global_id == scene_2.global_id
|
return scene_1.global_id == scene_2.global_id
|
||||||
|
|
||||||
return false
|
return false
|
||||||
|
|
||||||
|
|
||||||
|
# Disable collisions in the previous scene so if we have two scenes in the same
|
||||||
|
# game tree, collisions won't result.
|
||||||
|
func _disable_collisions() -> void:
|
||||||
|
var items_to_disable = previous_scene.get_tree().get_nodes_in_group(ESCItem.GROUP_ITEM_CAN_COLLIDE)
|
||||||
|
|
||||||
|
for item in items_to_disable:
|
||||||
|
if is_instance_valid(item.collision):
|
||||||
|
item.collision.disabled = true
|
||||||
|
|
||||||
|
|||||||
@@ -137,6 +137,14 @@ func has_transition(name: String) -> bool:
|
|||||||
return name == TRANSITION_INSTANT or get_transition(name) != ""
|
return name == TRANSITION_INSTANT or get_transition(name) != ""
|
||||||
|
|
||||||
|
|
||||||
|
# Resets the current material's cutoff parameter instantly.
|
||||||
|
func reset_shader_cutoff() -> void:
|
||||||
|
if not is_instance_valid(material):
|
||||||
|
return
|
||||||
|
|
||||||
|
material.set_shader_param("cutoff", 1.0)
|
||||||
|
|
||||||
|
|
||||||
func _on_tween_completed():
|
func _on_tween_completed():
|
||||||
if not _was_canceled:
|
if not _was_canceled:
|
||||||
_tween.stop_all()
|
_tween.stop_all()
|
||||||
|
|||||||
@@ -180,6 +180,7 @@ pause_mode = 1
|
|||||||
script = ExtResource( 5 )
|
script = ExtResource( 5 )
|
||||||
global_id = "trigger_talk"
|
global_id = "trigger_talk"
|
||||||
esc_script = "res://game/rooms/room01/esc/trigger.esc"
|
esc_script = "res://game/rooms/room01/esc/trigger.esc"
|
||||||
|
is_trigger = true
|
||||||
player_orients_on_arrival = false
|
player_orients_on_arrival = false
|
||||||
dialog_color = Color( 1, 1, 1, 1 )
|
dialog_color = Color( 1, 1, 1, 1 )
|
||||||
animations = null
|
animations = null
|
||||||
|
|||||||
Reference in New Issue
Block a user