From 99dc1e01106ce651d1b78ae574cca9d0202c48b1 Mon Sep 17 00:00:00 2001 From: Duncan Brown Date: Fri, 4 Feb 2022 11:10:40 -0500 Subject: [PATCH] feat: refactor numerous areas and tokenize string literals where possible; also fixes some small bugs (#487) Co-authored-by: Duncan Brown --- addons/escoria-core/default_bus_layout.tres | 1 + .../core-scripts/behaviors/esc_movable.gd | 2 +- .../core-scripts/esc/commands/camera_push.gd | 2 +- .../esc/commands/camera_set_pos.gd | 2 +- .../esc/commands/camera_set_target.gd | 2 +- .../esc/commands/camera_set_zoom.gd | 2 +- .../esc/commands/camera_set_zoom_height.gd | 2 +- .../core-scripts/esc/commands/camera_shift.gd | 2 +- .../core-scripts/esc/commands/change_scene.gd | 6 +- .../core-scripts/esc/commands/queue_event.gd | 32 +-- .../game/core-scripts/esc/commands/walk.gd | 5 +- .../core-scripts/esc/commands/walk_block.gd | 7 +- .../core-scripts/esc/commands/walk_to_pos.gd | 2 +- .../esc/commands/walk_to_pos_block.gd | 2 +- .../core-scripts/esc/esc_action_manager.gd | 143 +++++++++- .../core-scripts/esc/esc_command_registry.gd | 4 +- .../game/core-scripts/esc/esc_compiler.gd | 104 ++++---- .../core-scripts/esc/esc_event_manager.gd | 69 ++++- .../core-scripts/esc/esc_inventory_manager.gd | 2 +- .../core-scripts/esc/esc_object_manager.gd | 13 +- .../game/core-scripts/esc/esc_room_manager.gd | 100 ++++--- .../esc/types/esc_base_command.gd | 21 ++ .../core-scripts/esc/types/esc_command.gd | 4 +- .../game/core-scripts/esc/types/esc_event.gd | 4 + .../game/core-scripts/esc_background.gd | 4 +- .../game/core-scripts/esc_exit.gd | 22 +- .../game/core-scripts/esc_game.gd | 86 ++++-- .../game/core-scripts/esc_item.gd | 10 +- .../game/core-scripts/esc_resource_cache.gd | 11 +- .../game/core-scripts/log/esc_logger.gd | 29 +- .../resources/esc_resource_descriptor.gd | 15 ++ .../save_data/esc_save_manager.gd | 251 +++++++++++------- .../save_data/esc_savesettings.gd | 4 +- addons/escoria-core/game/escoria.gd | 248 +++++------------ addons/escoria-core/game/inputs_manager.gd | 7 + addons/escoria-core/game/main.gd | 4 +- .../game/project_settings_manager.gd | 123 +++++++++ .../game/scenes/camera_player/esc_camera.gd | 4 +- .../game/scenes/dialogs/esc_dialog_player.gd | 30 ++- .../scenes/esc_prompt/esc_prompt_popup.gd | 15 +- .../game/scenes/inventory/inventory_ui.gd | 4 +- .../game/scenes/sound/esc_music_player.gd | 6 +- .../game/scenes/sound/esc_sound_player.gd | 8 +- .../transitions/esc_transition_player.gd | 8 +- addons/escoria-core/plugin.gd | 154 +++++------ addons/escoria-dialog-simple/plugin.gd | 16 +- addons/escoria-ui-9verbs/game.gd | 48 +++- addons/escoria-ui-simplemouse/game.gd | 36 ++- .../room10/esc/button_accept_input_test.esc | 2 +- project.godot | 18 ++ 50 files changed, 1103 insertions(+), 593 deletions(-) create mode 100644 addons/escoria-core/game/core-scripts/resources/esc_resource_descriptor.gd create mode 100644 addons/escoria-core/game/project_settings_manager.gd diff --git a/addons/escoria-core/default_bus_layout.tres b/addons/escoria-core/default_bus_layout.tres index da0bf499..1330b38d 100644 --- a/addons/escoria-core/default_bus_layout.tres +++ b/addons/escoria-core/default_bus_layout.tres @@ -1,6 +1,7 @@ [gd_resource type="AudioBusLayout" format=2] [resource] +bus/0/volume_db = -8.89811 bus/1/name = "SFX" bus/1/solo = false bus/1/mute = false diff --git a/addons/escoria-core/game/core-scripts/behaviors/esc_movable.gd b/addons/escoria-core/game/core-scripts/behaviors/esc_movable.gd index ea70c7b1..9376f226 100644 --- a/addons/escoria-core/game/core-scripts/behaviors/esc_movable.gd +++ b/addons/escoria-core/game/core-scripts/behaviors/esc_movable.gd @@ -312,7 +312,7 @@ func update_terrain(on_event_finished_name = null) -> void: if !parent.terrain or parent.terrain == null \ or !is_instance_valid(parent.terrain): return - if on_event_finished_name != null and on_event_finished_name != "setup": + if on_event_finished_name != null and on_event_finished_name != escoria.event_manager.EVENT_SETUP: return if parent.get("is_exit"): return diff --git a/addons/escoria-core/game/core-scripts/esc/commands/camera_push.gd b/addons/escoria-core/game/core-scripts/esc/commands/camera_push.gd index fc60ca5b..8e7b2f75 100644 --- a/addons/escoria-core/game/core-scripts/esc/commands/camera_push.gd +++ b/addons/escoria-core/game/core-scripts/esc/commands/camera_push.gd @@ -47,7 +47,7 @@ func validate(arguments: Array): # Run the command func run(command_params: Array) -> int: - (escoria.object_manager.get_object("_camera").node as ESCCamera)\ + (escoria.object_manager.get_object(escoria.object_manager.CAMERA).node as ESCCamera)\ .push( escoria.object_manager.get_object(command_params[0]).node, command_params[1], diff --git a/addons/escoria-core/game/core-scripts/esc/commands/camera_set_pos.gd b/addons/escoria-core/game/core-scripts/esc/commands/camera_set_pos.gd index 8b8cfd4f..39954968 100644 --- a/addons/escoria-core/game/core-scripts/esc/commands/camera_set_pos.gd +++ b/addons/escoria-core/game/core-scripts/esc/commands/camera_set_pos.gd @@ -26,7 +26,7 @@ func configure() -> ESCCommandArgumentDescriptor: # Run the command func run(command_params: Array) -> int: - (escoria.object_manager.get_object("_camera").node as ESCCamera)\ + (escoria.object_manager.get_object(escoria.object_manager.CAMERA).node as ESCCamera)\ .set_target( Vector2(command_params[1], command_params[2]), command_params[0] diff --git a/addons/escoria-core/game/core-scripts/esc/commands/camera_set_target.gd b/addons/escoria-core/game/core-scripts/esc/commands/camera_set_target.gd index ed51ac08..db2c1e0f 100644 --- a/addons/escoria-core/game/core-scripts/esc/commands/camera_set_target.gd +++ b/addons/escoria-core/game/core-scripts/esc/commands/camera_set_target.gd @@ -39,7 +39,7 @@ func validate(arguments: Array): # Run the command func run(command_params: Array) -> int: - (escoria.object_manager.get_object("_camera").node as ESCCamera)\ + (escoria.object_manager.get_object(escoria.object_manager.CAMERA).node as ESCCamera)\ .set_target( escoria.object_manager.get_object(command_params[1]).node, command_params[0] diff --git a/addons/escoria-core/game/core-scripts/esc/commands/camera_set_zoom.gd b/addons/escoria-core/game/core-scripts/esc/commands/camera_set_zoom.gd index 72377d19..0cce0a81 100644 --- a/addons/escoria-core/game/core-scripts/esc/commands/camera_set_zoom.gd +++ b/addons/escoria-core/game/core-scripts/esc/commands/camera_set_zoom.gd @@ -28,7 +28,7 @@ func configure() -> ESCCommandArgumentDescriptor: # Run the command func run(command_params: Array) -> int: - (escoria.object_manager.get_object("_camera").node as ESCCamera)\ + (escoria.object_manager.get_object(escoria.object_manager.CAMERA).node as ESCCamera)\ .set_camera_zoom( command_params[0], command_params[1] diff --git a/addons/escoria-core/game/core-scripts/esc/commands/camera_set_zoom_height.gd b/addons/escoria-core/game/core-scripts/esc/commands/camera_set_zoom_height.gd index 9203adb5..b82ec464 100644 --- a/addons/escoria-core/game/core-scripts/esc/commands/camera_set_zoom_height.gd +++ b/addons/escoria-core/game/core-scripts/esc/commands/camera_set_zoom_height.gd @@ -40,7 +40,7 @@ func validate(arguments: Array): # Run the command func run(command_params: Array) -> int: - (escoria.object_manager.get_object("_camera").node as ESCCamera)\ + (escoria.object_manager.get_object(escoria.object_manager.CAMERA).node as ESCCamera)\ .set_camera_zoom( command_params[0] / escoria.game_size.y, command_params[1] diff --git a/addons/escoria-core/game/core-scripts/esc/commands/camera_shift.gd b/addons/escoria-core/game/core-scripts/esc/commands/camera_shift.gd index b93b0764..26d3c3de 100644 --- a/addons/escoria-core/game/core-scripts/esc/commands/camera_shift.gd +++ b/addons/escoria-core/game/core-scripts/esc/commands/camera_shift.gd @@ -38,7 +38,7 @@ func configure() -> ESCCommandArgumentDescriptor: # Run the command func run(command_params: Array) -> int: - (escoria.object_manager.get_object("_camera").node as ESCCamera)\ + (escoria.object_manager.get_object(escoria.object_manager.CAMERA).node as ESCCamera)\ .shift( Vector2( command_params[0], diff --git a/addons/escoria-core/game/core-scripts/esc/commands/change_scene.gd b/addons/escoria-core/game/core-scripts/esc/commands/change_scene.gd index d70cbfa3..cea088b1 100644 --- a/addons/escoria-core/game/core-scripts/esc/commands/change_scene.gd +++ b/addons/escoria-core/game/core-scripts/esc/commands/change_scene.gd @@ -32,13 +32,15 @@ func validate(arguments: Array) -> bool: ) return false if not ResourceLoader.exists( - ProjectSettings.get_setting("escoria/ui/game_scene") + escoria.project_settings_manager.get_setting(escoria.project_settings_manager.GAME_SCENE) ): escoria.logger.report_errors( "change_scene: Game scene not found", [ "The path set in 'ui/game_scene' was not found: %s" % \ - ProjectSettings.get_setting("escoria/ui/game_scene") + escoria.project_settings_manager.get_setting( + escoria.project_settings_manager.GAME_SCENE + ) ] ) return false diff --git a/addons/escoria-core/game/core-scripts/esc/commands/queue_event.gd b/addons/escoria-core/game/core-scripts/esc/commands/queue_event.gd index aed9709e..99265180 100644 --- a/addons/escoria-core/game/core-scripts/esc/commands/queue_event.gd +++ b/addons/escoria-core/game/core-scripts/esc/commands/queue_event.gd @@ -72,28 +72,10 @@ func run(arguments: Array) -> int: arguments[0] ).node var esc_script = escoria.esc_compiler.load_esc_file(node.esc_script) - if arguments[2] == "_front": - escoria.event_manager.queue_event(esc_script.events[arguments[1]]) - else: - escoria.event_manager.queue_background_event( - arguments[2], - esc_script.events[arguments[1]] - ) - if arguments[3]: - if arguments[2] == "_front": - var rc = yield(escoria.event_manager, "event_finished") - while rc[1] != arguments[1]: - rc = yield(escoria.event_manager, "event_finished") - return rc - else: - var rc = yield( - escoria.event_manager, - "background_event_finished" - ) - while rc[1] != arguments[1] and rc[2] != arguments[2]: - rc = yield( - escoria.event_manager, - "background_event_finished" - ) - return rc - return ESCExecution.RC_OK + + return escoria.event_manager.queue_event_from_esc( + esc_script, + arguments[1], # event name + arguments[2], # channel name + arguments[3] # whether to block + ) diff --git a/addons/escoria-core/game/core-scripts/esc/commands/walk.gd b/addons/escoria-core/game/core-scripts/esc/commands/walk.gd index fd56c387..58472108 100644 --- a/addons/escoria-core/game/core-scripts/esc/commands/walk.gd +++ b/addons/escoria-core/game/core-scripts/esc/commands/walk.gd @@ -46,5 +46,8 @@ func validate(arguments: Array): # Run the command func run(command_params: Array) -> int: - escoria.do("walk", command_params) + escoria.action_manager.do( + escoria.action_manager.ACTION.BACKGROUND_CLICK, + command_params + ) return ESCExecution.RC_OK diff --git a/addons/escoria-core/game/core-scripts/esc/commands/walk_block.gd b/addons/escoria-core/game/core-scripts/esc/commands/walk_block.gd index e1dc6764..2d1424d1 100644 --- a/addons/escoria-core/game/core-scripts/esc/commands/walk_block.gd +++ b/addons/escoria-core/game/core-scripts/esc/commands/walk_block.gd @@ -37,7 +37,7 @@ func validate(arguments: Array): escoria.logger.report_errors( "walk_block: invalid second object", [ - "Object with global id %s not found" % arguments[0] + "Object with global id %s not found" % arguments[1] ] ) return false @@ -46,7 +46,10 @@ func validate(arguments: Array): # Run the command func run(command_params: Array) -> int: - escoria.do("walk", command_params) + escoria.action_manager.do( + escoria.action_manager.ACTION.BACKGROUND_CLICK, + command_params + ) yield( (escoria.object_manager.objects[command_params[0]].node as ESCItem), "arrived" diff --git a/addons/escoria-core/game/core-scripts/esc/commands/walk_to_pos.gd b/addons/escoria-core/game/core-scripts/esc/commands/walk_to_pos.gd index 2779fced..96140831 100644 --- a/addons/escoria-core/game/core-scripts/esc/commands/walk_to_pos.gd +++ b/addons/escoria-core/game/core-scripts/esc/commands/walk_to_pos.gd @@ -39,7 +39,7 @@ func validate(arguments: Array): # Run the command func run(command_params: Array) -> int: - escoria.do("walk", [ + escoria.action_manager.do(escoria.action_manager.ACTION.BACKGROUND_CLICK, [ command_params[0], Vector2(command_params[1], command_params[2]) ]) diff --git a/addons/escoria-core/game/core-scripts/esc/commands/walk_to_pos_block.gd b/addons/escoria-core/game/core-scripts/esc/commands/walk_to_pos_block.gd index 821d9efd..269a91fb 100644 --- a/addons/escoria-core/game/core-scripts/esc/commands/walk_to_pos_block.gd +++ b/addons/escoria-core/game/core-scripts/esc/commands/walk_to_pos_block.gd @@ -39,7 +39,7 @@ func validate(arguments: Array): # Run the command func run(command_params: Array) -> int: - escoria.do("walk", [ + escoria.action_manager.do(escoria.action_manager.ACTION.BACKGROUND_CLICK, [ command_params[0], Vector2(command_params[1], command_params[2]) ]) diff --git a/addons/escoria-core/game/core-scripts/esc/esc_action_manager.gd b/addons/escoria-core/game/core-scripts/esc/esc_action_manager.gd index c608299a..5756706d 100644 --- a/addons/escoria-core/game/core-scripts/esc/esc_action_manager.gd +++ b/addons/escoria-core/game/core-scripts/esc/esc_action_manager.gd @@ -34,6 +34,26 @@ enum ACTION_INPUT_STATE { COMPLETED } +# Actions understood by the do(...) method +# * BACKGROUND_CLICK: Object is to move from its current position +# * ITEM_LEFT_CLICK: Item has been clicked on with LMB. +# * ITEM_RIGHT_CLICK: Item has been clicked on with RMB. +# * TRIGGER_IN: Character has moved into a trigger area. +# * TRIGGER_OUT: Character has moved out of a trigger area. +enum ACTION { + BACKGROUND_CLICK, + ITEM_LEFT_CLICK, + ITEM_RIGHT_CLICK, + TRIGGER_IN, + TRIGGER_OUT +} + + +# Basic required internal actions +const ACTION_ARRIVED = "arrived" +const ACTION_EXIT_SCENE = "exit_scene" +const ACTION_WALK = "walk" + # Current verb used var current_action: String = "" setget set_current_action @@ -49,6 +69,119 @@ var action_state = ACTION_INPUT_STATE.AWAITING_VERB_OR_ITEM \ setget set_action_input_state +# Run a generic action +# +# #### Parameters +# +# - action: type of the action to run +# - params: Parameters for the action +# - can_interrupt: if true, this command will interrupt any ongoing event +# before it is finished +func do(action: int, params: Array = [], can_interrupt: bool = false) -> void: + if escoria.current_state == escoria.GAME_STATE.DEFAULT: + match action: + ACTION.BACKGROUND_CLICK: + if can_interrupt: + escoria.event_manager.interrupt_running_event() + + self.clear_current_action() + + var walk_fast = false + if params.size() > 2: + walk_fast = true if params[2] else false + + # Check moving object. + if not escoria.object_manager.has(params[0]): + escoria.logger.report_errors( + "esc_action_manager.gd:do()", + [ + "Walk action requested on nonexisting " + \ + "object: %s " % params[0] + ] + ) + return + + var moving_obj = escoria.object_manager.get_object(params[0]) + var target + + if params[1] is String: + if not escoria.object_manager.has(params[1]): + escoria.logger.report_errors( + "esc_action_manager.gd:do()", + [ + "Walk action requested to nonexisting " + \ + "object: %s " % params[1] + ] + ) + return + + target = escoria.object_manager.get_object(params[1]) + elif params[1] is Vector2: + target = params[1] + + self.perform_walk(moving_obj, target, walk_fast) + + ACTION.ITEM_LEFT_CLICK: + if params[0] is String: + escoria.logger.info( + "esc_action_manager.do(): item_left_click on item ", + [params[0]] + ) + + if can_interrupt: + escoria.event_manager.interrupt_running_event() + + var item = escoria.object_manager.get_object(params[0]) + self.perform_inputevent_on_object(item, params[1]) + + ACTION.ITEM_RIGHT_CLICK: + if params[0] is String: + escoria.logger.info( + "esc_action_manager.do(): item_right_click on item ", + [params[0]] + ) + + if can_interrupt: + escoria.event_manager.interrupt_running_event() + + var item = escoria.object_manager.get_object(params[0]) + self.perform_inputevent_on_object(item, params[1], true) + + ACTION.TRIGGER_IN: + var trigger_id = params[0] + var object_id = params[1] + var trigger_in_verb = params[2] + escoria.logger.info("esc_action_manager.do(): trigger_in %s by %s" % [ + trigger_id, + object_id + ]) + escoria.event_manager.queue_event( + escoria.object_manager.get_object(trigger_id).events[ + trigger_in_verb + ] + ) + + ACTION.TRIGGER_OUT: + var trigger_id = params[0] + var object_id = params[1] + var trigger_out_verb = params[2] + escoria.logger.info("esc_action_manager.do(): trigger_out %s by %s" % [ + trigger_id, + object_id + ]) + escoria.event_manager.queue_event( + escoria.object_manager.get_object(trigger_id).events[ + trigger_out_verb + ] + ) + + _: + escoria.logger.report_warnings("esc_action_manager.gd:do()", + ["Action received:", action, "with params ", params]) + elif escoria.current_state == escoria.GAME_STATE.WAIT: + pass + + # Sets the current state of action input. # # ## Parameters @@ -410,15 +543,15 @@ func perform_inputevent_on_object( return # Manage exits - if obj.node.is_exit and current_action in ["", "walk"]: - _activate("exit_scene", obj) + if obj.node.is_exit and current_action in ["", ACTION_WALK]: + _activate(ACTION_EXIT_SCENE, obj) else: # Manage movements towards object before activating it - if current_action in ["", "walk"] and \ + if current_action in ["", ACTION_WALK] and \ not escoria.inventory_manager.inventory_has(obj.global_id): - _activate("arrived", obj) + _activate(ACTION_ARRIVED, obj) # Manage action on object - elif not current_action in ["", "walk"]: + elif not current_action in ["", ACTION_WALK]: if need_combine and current_target: _activate( current_action, diff --git a/addons/escoria-core/game/core-scripts/esc/esc_command_registry.gd b/addons/escoria-core/game/core-scripts/esc/esc_command_registry.gd index d944437d..6f86f1a4 100644 --- a/addons/escoria-core/game/core-scripts/esc/esc_command_registry.gd +++ b/addons/escoria-core/game/core-scripts/esc/esc_command_registry.gd @@ -14,8 +14,8 @@ var registry: Dictionary = {} # - command_name: Name of command to load # **Returns** The command object func load_command(command_name: String) -> ESCBaseCommand: - for command_directory in ProjectSettings.get( - "escoria/main/command_directories" + for command_directory in escoria.project_settings_manager.get_setting( + escoria.project_settings_manager.COMMAND_DIRECTORIES ): if ResourceLoader.exists("%s/%s.gd" % [command_directory, command_name]): registry[command_name] = load( diff --git a/addons/escoria-core/game/core-scripts/esc/esc_compiler.gd b/addons/escoria-core/game/core-scripts/esc/esc_compiler.gd index 1c0915e2..034bd95f 100644 --- a/addons/escoria-core/game/core-scripts/esc/esc_compiler.gd +++ b/addons/escoria-core/game/core-scripts/esc/esc_compiler.gd @@ -10,9 +10,21 @@ const COMMENT_REGEX = '^\\s*#.*$' const EMPTY_REGEX = '^\\s*$' # A RegEx for finding out the indent of a line -const INDENT_REGEX = '^(?\\s*)' +const INDENT_REGEX_GROUP = "indent" +const INDENT_REGEX = '^(?<%s>\\s*)' % INDENT_REGEX_GROUP +# RegEx objects for use by the ESC compiler +var _comment_regex +var _empty_regex +var _indent_regex +var _event_regex +var _command_regex +var _dialog_regex +var _dialog_end_regex +var _dialog_option_regex +var _group_regex + # The currently compiled event var _current_event = null @@ -35,6 +47,8 @@ var _current_indent = 0 func _init(): # Assure command list preference + # (we use ProjectSettings instead of escoria.project_settings_manager + # here because this is called from escoria._init()) if not ProjectSettings.has_setting("escoria/esc/command_paths"): ProjectSettings.set_setting("escoria/esc/command_paths", [ "res://addons/escoria-core/game/core-scripts/esc/commands" @@ -44,8 +58,29 @@ func _init(): "type": TYPE_STRING_ARRAY } ProjectSettings.add_property_info(property_info) - - + + # Compile all regex objects just once + _comment_regex = RegEx.new() + _comment_regex.compile(COMMENT_REGEX) + _empty_regex = RegEx.new() + _empty_regex.compile(EMPTY_REGEX) + _indent_regex = RegEx.new() + _indent_regex.compile(INDENT_REGEX) + + _event_regex = RegEx.new() + _event_regex.compile(ESCEvent.REGEX) + _command_regex = RegEx.new() + _command_regex.compile(ESCCommand.REGEX) + _dialog_regex = RegEx.new() + _dialog_regex.compile(ESCDialog.REGEX) + _dialog_end_regex = RegEx.new() + _dialog_end_regex.compile(ESCDialog.END_REGEX) + _dialog_option_regex = RegEx.new() + _dialog_option_regex.compile(ESCDialogOption.REGEX) + _group_regex = RegEx.new() + _group_regex.compile(ESCGroup.REGEX) + + # Load an ESC file from a file resource func load_esc_file(path: String) -> ESCScript: escoria.logger.debug("Parsing file %s" % path) @@ -79,49 +114,28 @@ func compile(lines: Array) -> ESCScript: # Compile an array of ESC script lines into an array of ESC objects func _compile(lines: Array) -> Array: - - var comment_regex = RegEx.new() - comment_regex.compile(COMMENT_REGEX) - var empty_regex = RegEx.new() - empty_regex.compile(EMPTY_REGEX) - var indent_regex = RegEx.new() - indent_regex.compile(INDENT_REGEX) - - var event_regex = RegEx.new() - event_regex.compile(ESCEvent.REGEX) - var command_regex = RegEx.new() - command_regex.compile(ESCCommand.REGEX) - var dialog_regex = RegEx.new() - dialog_regex.compile(ESCDialog.REGEX) - var dialog_end_regex = RegEx.new() - dialog_end_regex.compile(ESCDialog.END_REGEX) - var dialog_option_regex = RegEx.new() - dialog_option_regex.compile(ESCDialogOption.REGEX) - var group_regex = RegEx.new() - group_regex.compile(ESCGroup.REGEX) - var returned = [] while lines.size() > 0: var line = lines.pop_front() escoria.logger.trace("Parsing line %s" % line) - if comment_regex.search(line) or empty_regex.search(line): + if _comment_regex.search(line) or _empty_regex.search(line): # Ignore comments and empty lines escoria.logger.trace("Line is empty or a comment. Skipping.") continue var indent = \ escoria.utils.get_re_group( - indent_regex.search(line), - "indent" + _indent_regex.search(line), + INDENT_REGEX_GROUP ).length() - if event_regex.search(line): + if _event_regex.search(line): var event = ESCEvent.new(line) escoria.logger.trace("Line is the event %s" % event.name) var event_lines = [] while lines.size() > 0: var next_line = lines.pop_front() - if not event_regex.search(next_line): + if not _event_regex.search(next_line): event_lines.append(next_line) else: lines.push_front(next_line) @@ -133,19 +147,19 @@ func _compile(lines: Array) -> Array: ) event.statements = self._compile(event_lines) returned.append(event) - elif group_regex.search(line): + elif _group_regex.search(line): var group = ESCGroup.new(line) escoria.logger.trace("Line is a group") var group_lines = [] while lines.size() > 0: var next_line = lines.pop_front() - if comment_regex.search(next_line) or \ - empty_regex.search(next_line): + if _comment_regex.search(next_line) or \ + _empty_regex.search(next_line): continue var next_line_indent = \ escoria.utils.get_re_group( - indent_regex.search(next_line), - "indent" + _indent_regex.search(next_line), + INDENT_REGEX_GROUP ).length() if next_line_indent > indent: group_lines.append(next_line) @@ -159,21 +173,21 @@ func _compile(lines: Array) -> Array: ) group.statements = self._compile(group_lines) returned.append(group) - elif dialog_regex.search(line): + elif _dialog_regex.search(line): var dialog = ESCDialog.new() dialog.load_string(line) escoria.logger.trace("Line is a dialog") var dialog_lines = [] while lines.size() > 0: var next_line = lines.pop_front() - if comment_regex.search(next_line) or \ - empty_regex.search(next_line): + if _comment_regex.search(next_line) or \ + _empty_regex.search(next_line): continue - var end_line = dialog_end_regex.search(next_line) + var end_line = _dialog_end_regex.search(next_line) if end_line and \ escoria.utils.get_re_group( end_line, - "indent" + INDENT_REGEX_GROUP ).length() == indent: break else: @@ -187,7 +201,7 @@ func _compile(lines: Array) -> Array: # Remove the end line from the stack lines.pop_front() returned.append(dialog) - elif dialog_option_regex.search(line): + elif _dialog_option_regex.search(line): var dialog_option = ESCDialogOption.new() dialog_option.load_string(line) escoria.logger.trace( @@ -197,13 +211,13 @@ func _compile(lines: Array) -> Array: var dialog_option_lines = [] while lines.size() > 0: var next_line = lines.pop_front() - if comment_regex.search(next_line) or \ - empty_regex.search(next_line): + if _comment_regex.search(next_line) or \ + _empty_regex.search(next_line): continue var next_line_indent = \ escoria.utils.get_re_group( - indent_regex.search(next_line), - "indent" + _indent_regex.search(next_line), + INDENT_REGEX_GROUP ).length() if next_line_indent > indent: dialog_option_lines.append(next_line) @@ -217,7 +231,7 @@ func _compile(lines: Array) -> Array: ) dialog_option.statements = self._compile(dialog_option_lines) returned.append(dialog_option) - elif command_regex.search(line): + elif _command_regex.search(line): var command = ESCCommand.new(line) if command.command_exists(): returned.append(command) 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 76bbfe8b..b3790883 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 @@ -20,12 +20,29 @@ signal event_finished(return_code, event_name) signal background_event_finished(return_code, event_name, channel_name) +# Pre-defined ESC events +const EVENT_DEBUG = "debug" +const EVENT_EXIT_SCENE = "exit_scene" +const EVENT_INIT = "init" +const EVENT_LOAD = "load" +const EVENT_NEW_GAME = "newgame" +const EVENT_READY = "ready" +const EVENT_ROOM_SELECTOR = "room_selector" +const EVENT_SETUP = "setup" +const EVENT_TRANSITION_IN = "transition_in" +const EVENT_TRANSITION_OUT = "transition_out" + + +# Event channel names +const CHANNEL_FRONT = "_front" + + # A list of currently scheduled events var scheduled_events: Array = [] # A list of constantly running events in multiple background channels var events_queue: Dictionary = { - "_front": [] + CHANNEL_FRONT: [] } # Currently running event in background channels @@ -82,7 +99,7 @@ func _process(delta: float) -> void: CONNECT_ONESHOT ) - if channel_name == "_front": + if channel_name == CHANNEL_FRONT: emit_signal( "event_started", _running_events[channel_name].name @@ -109,7 +126,49 @@ func _process(delta: float) -> void: (event as ESCScheduledEvent).timeout -= delta if (event as ESCScheduledEvent).timeout <= 0: self.scheduled_events.erase(event) - self.events_queue['_front'].append(event.event) + self.events_queue[CHANNEL_FRONT].append(event.event) + + +# Queue a new event based on input from an ESC command, most likely "queue_event" +# +# #### Parameters +# - script_object: Compiled script object, i.e. the one with the event to queue +# - event: Name of the event to queue +# - channel: Channel to run the event on (default: `_front`) +# - block: Whether to wait for the queue to finish. This is only possible, if +# the queued event is not to be run on the same event as this command +# (default: `false`) +# +# **Returns** indicator of success/status +func queue_event_from_esc(script_object: ESCScript, event: String, + channel: String, block: bool) -> int: + + if channel == CHANNEL_FRONT: + escoria.event_manager.queue_event(script_object.events[event]) + else: + escoria.event_manager.queue_background_event( + channel, + script_object.events[event] + ) + if block: + if channel == CHANNEL_FRONT: + var rc = yield(escoria.event_manager, "event_finished") + while rc[1] != event: + rc = yield(escoria.event_manager, "event_finished") + return rc + else: + var rc = yield( + escoria.event_manager, + "background_event_finished" + ) + while rc[1] != event and rc[2] != channel: + rc = yield( + escoria.event_manager, + "background_event_finished" + ) + return rc + + return ESCExecution.RC_OK # Queue a new event to run in the foreground @@ -117,7 +176,7 @@ func _process(delta: float) -> void: # #### Parameters # - event: Event to run func queue_event(event: ESCEvent) -> void: - self.events_queue['_front'].append(event) + self.events_queue[CHANNEL_FRONT].append(event) # Schedule an event to run after a timeout @@ -212,7 +271,7 @@ func _on_event_finished(finished_statement: ESCStatement, return_code: int, chan _running_events[channel_name] = null _channels_state[channel_name] = true - if channel_name == "_front": + if channel_name == CHANNEL_FRONT: emit_signal( "event_finished", return_code, diff --git a/addons/escoria-core/game/core-scripts/esc/esc_inventory_manager.gd b/addons/escoria-core/game/core-scripts/esc/esc_inventory_manager.gd index 13c0dce2..69625fa7 100644 --- a/addons/escoria-core/game/core-scripts/esc/esc_inventory_manager.gd +++ b/addons/escoria-core/game/core-scripts/esc/esc_inventory_manager.gd @@ -31,7 +31,7 @@ func items_in_inventory() -> Array: # - item: Inventory item id func remove_item(item: String): if not inventory_has(item): - self.logger.report_errors( + escoria.logger.report_errors( "ESCInventoryManager.remove_item: Error removing inventory item", [ "Trying to remove non-existent item %s" % item diff --git a/addons/escoria-core/game/core-scripts/esc/esc_object_manager.gd b/addons/escoria-core/game/core-scripts/esc/esc_object_manager.gd index 87d3d580..1c602399 100644 --- a/addons/escoria-core/game/core-scripts/esc/esc_object_manager.gd +++ b/addons/escoria-core/game/core-scripts/esc/esc_object_manager.gd @@ -3,11 +3,16 @@ extends Node class_name ESCObjectManager +const CAMERA = "_camera" +const MUSIC = "_music" +const SOUND = "_sound" +const SPEECH = "_speech" + const RESERVED_OBJECTS = [ - "_music", - "_sound", - "_speech", - "_camera" + MUSIC, + SOUND, + SPEECH, + CAMERA ] 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 11deddce..880f6f94 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 @@ -24,6 +24,16 @@ const RESERVED_GLOBALS = { } +# ESC commands kept around for references to their command names. +var _transition: TransitionCommand +var _wait: WaitCommand + + +func _init() -> void: + _transition = TransitionCommand.new() + _wait = WaitCommand.new() + + # Registers all reserved global flags for use. func register_reserved_globals() -> void: for key in RESERVED_GLOBALS: @@ -55,9 +65,13 @@ func change_scene(room_path: String, enable_automatic_transitions: bool) -> void not escoria.globals_manager.get_global( \ GLOBAL_LAST_SCENE).empty() or ( - escoria.event_manager.get_running_event("_front") != null \ - and escoria.event_manager.get_running_event("_front").name \ - in ["newgame", "exit_scene", "room_selector"] + escoria.event_manager.get_running_event(escoria.event_manager.CHANNEL_FRONT) != null \ + and escoria.event_manager.get_running_event(escoria.event_manager.CHANNEL_FRONT).name \ + in [ + escoria.event_manager.EVENT_NEW_GAME, + escoria.event_manager.EVENT_EXIT_SCENE, + escoria.event_manager.EVENT_ROOM_SELECTOR + ] and escoria.globals_manager.get_global( GLOBAL_LAST_SCENE ).empty() @@ -109,7 +123,9 @@ func change_scene(room_path: String, enable_automatic_transitions: bool) -> void "ESCRoomManager.change_scene: Failed loading game scene", [ "Failed loading scene %s" % \ - ProjectSettings.get_setting("escoria/ui/game_scene") + escoria.project_settings_manager.get_setting( + escoria.project_settings_manager.GAME_SCENE + ) ] ) @@ -123,9 +139,9 @@ func change_scene(room_path: String, enable_automatic_transitions: bool) -> void var room_scene = res_room.instance() if room_scene: if enable_automatic_transitions \ - and escoria.event_manager.get_running_event("_front") != null \ - and escoria.event_manager.get_running_event("_front").name \ - == "room_selector": + and escoria.event_manager.get_running_event(escoria.event_manager.CHANNEL_FRONT) != null \ + and escoria.event_manager.get_running_event(escoria.event_manager.CHANNEL_FRONT).name \ + == escoria.event_manager.EVENT_ROOM_SELECTOR: room_scene.enabled_automatic_transitions = true else: room_scene.enabled_automatic_transitions = enable_automatic_transitions @@ -231,7 +247,7 @@ func init_room(room: ESCRoom) -> void: animations[room.player.global_id] ) room.player.update_idle() - escoria.object_manager.get_object("_camera").node.set_target(room.player) + escoria.object_manager.get_object(escoria.object_manager.CAMERA).node.set_target(room.player) if room.global_id.empty(): room.global_id = room.name @@ -251,12 +267,12 @@ func init_room(room: ESCRoom) -> void: # # - room: The ESCRoom to be initialized for use. func _perform_script_events(room: ESCRoom): - if escoria.event_manager.is_channel_free("_front") \ + if room.esc_script and escoria.event_manager.is_channel_free(escoria.event_manager.CHANNEL_FRONT) \ or ( - not escoria.event_manager.is_channel_free("_front") and \ + not escoria.event_manager.is_channel_free(escoria.event_manager.CHANNEL_FRONT) and \ not escoria.event_manager.get_running_event( - "_front" - ).name == "load" + escoria.event_manager.CHANNEL_FRONT + ).name == escoria.event_manager.EVENT_LOAD ): # If the room was loaded from change_scene and automatic transitions @@ -265,14 +281,18 @@ func _perform_script_events(room: ESCRoom): and not room.is_run_directly \ and not room.exited_previous_room: var script_transition_out = escoria.esc_compiler.compile([ - ":transition_out", - "transition %s out" % ProjectSettings.get_setting( - "escoria/ui/default_transition" - ), - "wait 0.1" + "%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_TRANISITION + ) + ], + "%s 0.1" % _wait.get_command_name() ]) escoria.event_manager.queue_event( - script_transition_out.events['transition_out'] + script_transition_out.events[escoria.event_manager.EVENT_TRANSITION_OUT] ) # Unpause the game if it was @@ -280,7 +300,7 @@ func _perform_script_events(room: ESCRoom): # Wait for transition_out event to be done var rc = yield(escoria.event_manager, "event_finished") - while rc[1] != "transition_out": + 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] @@ -290,8 +310,7 @@ func _perform_script_events(room: ESCRoom): escoria.game_scene.unpause_game() # Run the setup event - if room.esc_script: - _run_script_event("setup", room) + _run_script_event(escoria.event_manager.EVENT_SETUP, room) if room.enabled_automatic_transitions \ or ( @@ -300,28 +319,31 @@ func _perform_script_events(room: ESCRoom): escoria.room_manager.GLOBAL_FORCE_LAST_SCENE_NULL) ): var script_transition_in = escoria.esc_compiler.compile([ - ":transition_in", - "transition %s in" % ProjectSettings.get_setting( - "escoria/ui/default_transition" - ), - "wait 0.1" + "%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_TRANISITION + ) + ], + "%s 0.1" % _wait.get_command_name() ]) escoria.event_manager.queue_event( - script_transition_in.events['transition_in'] + script_transition_in.events[escoria.event_manager.EVENT_TRANSITION_IN] ) - if room.esc_script: - var ready_event_added: bool = false - # Run the ready event, if there is one. - ready_event_added = _run_script_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] != "ready": - rc = yield(escoria.event_manager, "event_finished") - if rc[0] != ESCExecution.RC_OK: - return rc[0] + 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 diff --git a/addons/escoria-core/game/core-scripts/esc/types/esc_base_command.gd b/addons/escoria-core/game/core-scripts/esc/types/esc_base_command.gd index 811f1118..416d6889 100644 --- a/addons/escoria-core/game/core-scripts/esc/types/esc_base_command.gd +++ b/addons/escoria-core/game/core-scripts/esc/types/esc_base_command.gd @@ -4,6 +4,22 @@ extends Node class_name ESCBaseCommand +# Regex for creating command name based on the script's filename, including +# named groups +const PATH_REGEX_GROUP = "path" +const FILE_REGEX_GROUP = "file" +const EXTENSION_REGEX_GROUP = "extension" +const COMMAND_NAME_REGEX = "(?<%s>.+)\/(?<%s>[^.]+)(?<%s>\\.[^.]*$|$)" % \ + [PATH_REGEX_GROUP, FILE_REGEX_GROUP, EXTENSION_REGEX_GROUP] + +# Regex matcher for command names +var command_name_regex: RegEx = RegEx.new() + + +func _init() -> void: + command_name_regex.compile(COMMAND_NAME_REGEX) + + # Return the descriptor of the arguments of this command func configure() -> ESCCommandArgumentDescriptor: escoria.logger.error("Command %s did not override configure." % get_class()) @@ -19,3 +35,8 @@ func validate(arguments: Array) -> bool: func run(command_params: Array) -> int: escoria.logger.error("Command %s did not override run." % get_class()) return 0 + + +# Return the name of the command based on the script's filename +func get_command_name() -> String: + return command_name_regex.search(get_script().get_path()).get_string(FILE_REGEX_GROUP) diff --git a/addons/escoria-core/game/core-scripts/esc/types/esc_command.gd b/addons/escoria-core/game/core-scripts/esc/types/esc_command.gd index d18f2416..410987ad 100644 --- a/addons/escoria-core/game/core-scripts/esc/types/esc_command.gd +++ b/addons/escoria-core/game/core-scripts/esc/types/esc_command.gd @@ -99,7 +99,9 @@ func is_valid() -> bool: # *Returns* True if the command exists, else false. func command_exists() -> bool: var command_found = false - for base_path in ProjectSettings.get("escoria/main/command_directories"): + for base_path in escoria.project_settings_manager.get_setting( + escoria.project_settings_manager.COMMAND_DIRECTORIES + ): var command_path = "%s/%s.gd" % [ base_path.trim_suffix("/"), self.name diff --git a/addons/escoria-core/game/core-scripts/esc/types/esc_event.gd b/addons/escoria-core/game/core-scripts/esc/types/esc_event.gd index fb59be37..719c9086 100644 --- a/addons/escoria-core/game/core-scripts/esc/types/esc_event.gd +++ b/addons/escoria-core/game/core-scripts/esc/types/esc_event.gd @@ -16,6 +16,9 @@ const REGEX = \ '(TK|NO_TT|NO_UI|NO_SAVE)' + \ ')+))?$' +# Prefix to identify this as an ESC event. +const PREFIX = ":" + # Valid event flags # * TK: stands for "telekinetic". It means the player won't walk over to @@ -80,3 +83,4 @@ func run() -> int: reset_interrupt() escoria.logger.debug("Event %s started" % name) return .run() + diff --git a/addons/escoria-core/game/core-scripts/esc_background.gd b/addons/escoria-core/game/core-scripts/esc_background.gd index e07ae6f7..4a6f4b55 100644 --- a/addons/escoria-core/game/core-scripts/esc_background.gd +++ b/addons/escoria-core/game/core-scripts/esc_background.gd @@ -85,8 +85,8 @@ func _ready(): func _unhandled_input(event) -> void: if not escoria.current_state == escoria.GAME_STATE.DEFAULT: return - if InputMap.has_action("switch_action_verb") \ - and event.is_action_pressed("switch_action_verb"): + if InputMap.has_action(escoria.inputs_manager.SWITCH_ACTION_VERB) \ + and event.is_action_pressed(escoria.inputs_manager.SWITCH_ACTION_VERB): if event.button_index == BUTTON_WHEEL_UP: emit_signal("mouse_wheel_up") elif event.button_index == BUTTON_WHEEL_DOWN: diff --git a/addons/escoria-core/game/core-scripts/esc_exit.gd b/addons/escoria-core/game/core-scripts/esc_exit.gd index 864dfd95..84254700 100644 --- a/addons/escoria-core/game/core-scripts/esc_exit.gd +++ b/addons/escoria-core/game/core-scripts/esc_exit.gd @@ -9,36 +9,44 @@ export(String, FILE, "*.tscn") var target_scene = "" # Sound effect to play when changing the scene export(String, FILE, "*.ogg,*.mp3,*.wav") var switch_sound = "" +# ESC commands kept around for references to their command names. +var _play_snd: PlaySndCommand +var _change_scene: ChangeSceneCommand + func _enter_tree(): is_exit = true player_orients_on_arrival = false - default_action = "walk" func _ready(): + _play_snd = PlaySndCommand.new() + _change_scene = ChangeSceneCommand.new() + call_deferred("_register_event") # Registers the exit_scene event based on the properties func _register_event(): if escoria.object_manager.has(self.global_id) and\ - not "exit_scene" in escoria.object_manager.get_object( + not escoria.event_manager.EVENT_EXIT_SCENE in escoria.object_manager.get_object( self.global_id ).events: var exit_scene_event_script = [ - ":exit_scene", + "%s%s" % [ESCEvent.PREFIX, escoria.event_manager.EVENT_EXIT_SCENE] ] if switch_sound != "": exit_scene_event_script.append( - "play_snd %s" % switch_sound + "%s %s" % [_play_snd.get_command_name(), switch_sound] ) - exit_scene_event_script.append("change_scene %s" % target_scene) + exit_scene_event_script.append( + "%s %s" % [_change_scene.get_command_name(), target_scene] + ) var exit_scene_event = escoria.esc_compiler.compile( exit_scene_event_script - ).events["exit_scene"] + ).events[escoria.event_manager.EVENT_EXIT_SCENE] escoria.object_manager.get_object(self.global_id)\ - .events["exit_scene"] = exit_scene_event + .events[escoria.event_manager.EVENT_EXIT_SCENE] = exit_scene_event diff --git a/addons/escoria-core/game/core-scripts/esc_game.gd b/addons/escoria-core/game/core-scripts/esc_game.gd index eb42d941..91deb0e1 100644 --- a/addons/escoria-core/game/core-scripts/esc_game.gd +++ b/addons/escoria-core/game/core-scripts/esc_game.gd @@ -67,7 +67,7 @@ func _exit_tree(): # Ready function func _ready(): escoria.apply_settings(escoria.settings) - connect("crash_popup_confirmed", escoria, "quit", + connect("crash_popup_confirmed", escoria, "quit", [], CONNECT_ONESHOT) @@ -88,6 +88,56 @@ func _draw(): draw_rect(mouse_limits, ColorN("red"), false, 10.0) +# Sets up and performs default walking action +# +# #### Parameters +# +# - destination: Destination to walk to +# - params: Parameters for the action +# - can_interrupt: if true, this command will interrupt any ongoing event +func do_walk(destination, params: Array = [], can_interrupt: bool = false) -> void: + if can_interrupt: + escoria.event_manager.interrupt_running_event() + + escoria.action_manager.clear_current_action() + + var walk_fast = false + + if params.size() > 1: + walk_fast = true if params[1] else false + + # Check moving object. + if not escoria.object_manager.has(params[0]): + escoria.logger.report_errors( + "esc_game.gd:do_walk()", + [ + "Walk action requested on nonexisting " + \ + "object: %s " % params[0] + ] + ) + return + + var moving_obj = escoria.object_manager.get_object(params[0]) + var target + + if destination is String: + if not escoria.object_manager.has(destination): + escoria.logger.report_errors( + "esc_game.gd:do_walk()", + [ + "Walk action requested to nonexisting " + \ + "object: %s " % destination + ] + ) + return + + target = escoria.object_manager.get_object(destination) + elif destination is Vector2: + target = destination + + escoria.action_manager.perform_walk(moving_obj, target, walk_fast) + + # Called when the player left clicks on the background # (Needs to be overridden, if supported) # @@ -95,9 +145,9 @@ func _draw(): # # - position: Position clicked func left_click_on_bg(position: Vector2) -> void: - escoria.do( - "walk", - [escoria.main.current_scene.player.global_id, position], + do_walk( + position, + [escoria.main.current_scene.player.global_id], true ) @@ -109,9 +159,9 @@ func left_click_on_bg(position: Vector2) -> void: # # - position: Position clicked func right_click_on_bg(position: Vector2) -> void: - escoria.do( - "walk", - [escoria.main.current_scene.player.global_id, position], + do_walk( + position, + [escoria.main.current_scene.player.global_id], true ) @@ -123,9 +173,9 @@ func right_click_on_bg(position: Vector2) -> void: # # - position: Position clicked func left_double_click_on_bg(position: Vector2) -> void: - escoria.do( - "walk", - [escoria.main.current_scene.player.global_id, position, true], + do_walk( + position, + [escoria.main.current_scene.player.global_id, true], true ) @@ -153,8 +203,8 @@ func element_unfocused() -> void: # - item_global_id: Global id of the item that was clicked # - event: The received input event func left_click_on_item(item_global_id: String, event: InputEvent) -> void: - escoria.do( - "item_left_click", + escoria.action_manager.do( + escoria.action_manager.ACTION.ITEM_LEFT_CLICK, [item_global_id, event], true ) @@ -168,8 +218,8 @@ func left_click_on_item(item_global_id: String, event: InputEvent) -> void: # - item_global_id: Global id of the item that was clicked # - event: The received input event func right_click_on_item(item_global_id: String, event: InputEvent) -> void: - escoria.do( - "item_right_click", + escoria.action_manager.do( + escoria.action_manager.ACTION.ITEM_RIGHT_CLICK, [item_global_id, event], true ) @@ -186,8 +236,8 @@ func left_double_click_on_item( item_global_id: String, event: InputEvent ) -> void: - escoria.do( - "item_left_click", + escoria.action_manager.do( + escoria.action_manager.ACTION.ITEM_LEFT_CLICK, [item_global_id, event], true ) @@ -363,8 +413,8 @@ func show_crash_popup(files: Array = []) -> void: var files_to_send: String = "" for file in files: files_to_send += "- %s\n" % file - crash_popup.dialog_text = tr(ProjectSettings.get_setting( - "escoria/debug/crash_message") + crash_popup.dialog_text = tr(escoria.project_settings_manager.get_setting( + escoria.project_settings_manager.CRASH_MESSAGE) ) % files_to_send crash_popup.popup_centered() escoria.set_game_paused(true) diff --git a/addons/escoria-core/game/core-scripts/esc_item.gd b/addons/escoria-core/game/core-scripts/esc_item.gd index 215c2c45..e3f3f3ed 100644 --- a/addons/escoria-core/game/core-scripts/esc_item.gd +++ b/addons/escoria-core/game/core-scripts/esc_item.gd @@ -356,7 +356,10 @@ func _on_mouse_exited(): func element_entered(body): if body is ESCBackground or body.get_parent() is ESCBackground: return - escoria.do("trigger_in", [global_id, body.global_id, trigger_in_verb]) + escoria.action_manager.do( + escoria.action_manager.ACTION.TRIGGER_IN, + [global_id, body.global_id, trigger_in_verb] + ) # Another item (e.g. the player) has exited this element @@ -366,7 +369,10 @@ func element_entered(body): func element_exited(body): if body is ESCBackground or body.get_parent() is ESCBackground: return - escoria.do("trigger_out", [global_id, body.global_id, trigger_out_verb]) + escoria.action_manager.do( + escoria.action_manager.ACTION.TRIGGER_OUT, + [global_id, body.global_id, trigger_out_verb] + ) # Use the movable node to teleport this item to the target item diff --git a/addons/escoria-core/game/core-scripts/esc_resource_cache.gd b/addons/escoria-core/game/core-scripts/esc_resource_cache.gd index 1814077f..0bb530ff 100644 --- a/addons/escoria-core/game/core-scripts/esc_resource_cache.gd +++ b/addons/escoria-core/game/core-scripts/esc_resource_cache.gd @@ -39,7 +39,7 @@ func queue_resource(path: String, p_in_front: bool = false, p_permanent: bool = elif ResourceLoader.has(path): var res = ResourceLoader.load(path) - pending[path] = { "res": res, "permanent": p_permanent } + pending[path] = ESCResourceDescriptor.new(res, p_permanent) _unlock("queue_resource") return else: @@ -49,7 +49,7 @@ func queue_resource(path: String, p_in_front: bool = false, p_permanent: bool = queue.insert(0, res) else: queue.push_back(res) - pending[path] = { "res": res, "permanent": p_permanent } + pending[path] = ESCResourceDescriptor.new(res, p_permanent) _post("queue_resource") _unlock("queue_resource") return @@ -138,12 +138,11 @@ func get_resource(path): return res else: _unlock("return") + # We can't use escoria.project_settings_manager here since this method + # can be called from escoria._init() if not ProjectSettings.get_setting("escoria/platform/skip_cache"): var res = ResourceLoader.load(path) - pending[path] = { - "res": res, - "permanent": true - } + pending[path] = ESCResourceDescriptor.new(res, true) return res return ResourceLoader.load(path) diff --git a/addons/escoria-core/game/core-scripts/log/esc_logger.gd b/addons/escoria-core/game/core-scripts/log/esc_logger.gd index 3764c244..b10fbfec 100644 --- a/addons/escoria-core/game/core-scripts/log/esc_logger.gd +++ b/addons/escoria-core/game/core-scripts/log/esc_logger.gd @@ -38,6 +38,9 @@ var _level_map: Dictionary = { func _init(): # Open logfile in write mode log_file = File.new() + + # this is left alone as this constructor is called from escoria.gd's own + # constructor var log_file_path = ProjectSettings.get_setting( "escoria/debug/log_file_path" ) @@ -105,14 +108,16 @@ func warning(string: String, args = []): if _get_log_level() >= LOG_WARNING and !crashed: var argsstr = str(args) if !args.empty() else "" _log("(W)\t" + string + " \t" + argsstr, true) - - if ProjectSettings.get_setting("escoria/debug/terminate_on_warnings"): + + if escoria.project_settings_manager.get_setting( + escoria.project_settings_manager.TERMINATE_ON_WARNINGS + ): _perform_stack_trace_log() crashed = true var files = "- %s" % log_file.get_path_absolute() - var message = ProjectSettings.get_setting( - "escoria/debug/crash_message" + var message = escoria.project_settings_manager.get_setting( + escoria.project_settings_manager.CRASH_MESSAGE ) % files _log(message, true) @@ -134,7 +139,9 @@ func error(string: String, args = [], do_savegame: bool = true): var argsstr = str(args) if !args.empty() else "" _log("(E)\t" + string + " \t" + argsstr, true) - if ProjectSettings.get_setting("escoria/debug/terminate_on_errors"): + if escoria.project_settings_manager.get_setting( + escoria.project_settings_manager.TERMINATE_ON_ERRORS + ): _perform_stack_trace_log() crashed = true if do_savegame: @@ -148,8 +155,8 @@ func error(string: String, args = [], do_savegame: bool = true): ] var files = "- %s\n- %s" % files_to_send - var message = ProjectSettings.get_setting( - "escoria/debug/crash_message" + var message = escoria.project_settings_manager.get_setting( + escoria.project_settings_manager.CRASH_MESSAGE ) % files _log(message, true) @@ -222,7 +229,9 @@ func _log(message:String, err: bool = false): # Returns the currently set log level # **Returns** Log level as set in the configuration func _get_log_level() -> int: - return _level_map[ProjectSettings.get_setting("escoria/debug/log_level")] + return _level_map[escoria.project_settings_manager.get_setting( + escoria.project_settings_manager.LOG_LEVEL + )] # Creates a savegame file and save it in output log location @@ -232,8 +241,8 @@ func _perform_save_game_log(): if error == OK: _log( "Emergency savegame created successfully in folder: %s" % - ProjectSettings.get_setting( - "escoria/debug/log_file_path" + escoria.project_settings_manager.get_setting( + escoria.project_settings_manager.LOG_FILE_PATH ) ) else: diff --git a/addons/escoria-core/game/core-scripts/resources/esc_resource_descriptor.gd b/addons/escoria-core/game/core-scripts/resources/esc_resource_descriptor.gd new file mode 100644 index 00000000..46521268 --- /dev/null +++ b/addons/escoria-core/game/core-scripts/resources/esc_resource_descriptor.gd @@ -0,0 +1,15 @@ +# Describes a resource for use in the resource cache +extends Object +class_name ESCResourceDescriptor + + +# The resource being described +var res: Resource + +# Whether the resource is permanent +var permanent: bool + + +func _init(res_in: Resource, permanent_in: bool) -> void: + res = res_in + permanent = permanent_in diff --git a/addons/escoria-core/game/core-scripts/save_data/esc_save_manager.gd b/addons/escoria-core/game/core-scripts/save_data/esc_save_manager.gd index e64d4ca1..bbadab85 100644 --- a/addons/escoria-core/game/core-scripts/save_data/esc_save_manager.gd +++ b/addons/escoria-core/game/core-scripts/save_data/esc_save_manager.gd @@ -1,6 +1,17 @@ # Saves and loads savegame and settings files class_name ESCSaveManager + +# Template for settings filename +const SETTINGS_TEMPLATE: String = "settings.tres" + +# Template for savegames filenames +const SAVE_NAME_TEMPLATE: String = "save_%03d.tres" + +# Template for crash savegames filenames +const CRASH_SAVE_NAME_TEMPLATE: String = "crash_autosave_%s_%s.tres" + + # If true, saving a game is enabled. Else, saving is disabled var save_enabled: bool = true @@ -10,28 +21,46 @@ var save_folder: String # Filename of the latest crash savegame file var crash_savegame_filename: String -# Template for savegames filenames -const SAVE_NAME_TEMPLATE: String = "save_%03d.tres" - -# Template for crash savegames filenames -const CRASH_SAVE_NAME_TEMPLATE: String = "crash_autosave_%s_%s.tres" - # Variable containing the settings folder obtained from Project Settings var settings_folder: String -# Template for settings filename -const SETTINGS_TEMPLATE: String = "settings.tres" +# ESC commands kept around for references to their command names. +var _transition: TransitionCommand +var _hide_menu: HideMenuCommand +var _change_scene: ChangeSceneCommand +var _set_active: SetActiveCommand +var _set_interactive: SetInteractiveCommand +var _teleport_pos: TeleportPosCommand +var _set_angle: SetAngleCommand +var _set_state: SetStateCommand +var _stop_snd: StopSndCommand +var _play_snd: PlaySndCommand + # Constructor of ESCSaveManager object. func _init(): + # We leave the calls to ProjectSettings as-is since this constructor can be + # called from escoria.gd's own. save_folder = ProjectSettings.get_setting("escoria/main/savegames_path") settings_folder = ProjectSettings.get_setting("escoria/main/settings_path") + _transition = TransitionCommand.new() + _hide_menu = HideMenuCommand.new() + _change_scene = ChangeSceneCommand.new() + _set_active = SetActiveCommand.new() + _set_interactive = SetInteractiveCommand.new() + _teleport_pos = TeleportPosCommand.new() + _set_angle = SetAngleCommand.new() + _set_state = SetStateCommand.new() + _stop_snd = StopSndCommand.new() + _play_snd = PlaySndCommand.new() + + # Return a list of savegames metadata (id, date, name and game version) func get_saves_list() -> Dictionary: var regex = RegEx.new() regex.compile("save_([0-9]{3})\\.tres") - + var saves = {} var dirsave = Directory.new() if dirsave.open(save_folder) == OK: @@ -46,7 +75,7 @@ func get_saves_list() -> Dictionary: "name": save_game_res["name"], "game_version": save_game_res["game_version"], } - + var id: int var matches = regex.search(nextfile) if matches.strings.size() > 1: @@ -76,10 +105,10 @@ func save_game_exists(id: int) -> bool: func save_game(id: int, p_savename: String): if not save_enabled: escoria.logger.debug( - "esc_save_data_resources.gd", + "esc_save_manager.gd", ["Save requested while saving is not possible. Save canceled."]) return - + var save_game := _do_save_game(p_savename) var directory: Directory = Directory.new() @@ -90,7 +119,7 @@ func save_game(id: int, p_savename: String): var error: int = ResourceSaver.save(save_path, save_game) if error != OK: escoria.logger.report_errors( - "esc_save_data_resources.gd", + "esc_save_manager.gd", ["There was an issue writing the save %s to %s" % [id, save_path]] ) @@ -105,11 +134,11 @@ func save_game_crash(): datetime["hour"], datetime["minute"], ] - + var save_game := _do_save_game("Crash %s" % datetime_string) - - var save_file_path: String = ProjectSettings.get_setting( - "escoria/debug/log_file_path" + + var save_file_path: String = escoria.project_settings_manager.get_setting( + escoria.project_settings_manager.LOG_FILE_PATH ) crash_savegame_filename = save_file_path.plus_file( CRASH_SAVE_NAME_TEMPLATE % [ @@ -119,11 +148,11 @@ func save_game_crash(): + str(datetime["second"]) ] ) - + var error: int = ResourceSaver.save(crash_savegame_filename, save_game) if error != OK: escoria.logger.report_errors( - "esc_save_data_resources.gd", + "esc_save_manager.gd", ["There was an issue writing the crash save to %s" % crash_savegame_filename]) return error @@ -135,12 +164,12 @@ func save_game_crash(): # - p_savename: name of the savegame func _do_save_game(p_savename: String) -> ESCSaveGame: var save_game = ESCSaveGame.new() - save_game.escoria_version = escoria.ESCORIA_VERSION - save_game.game_version = ProjectSettings.get_setting( - "escoria/main/game_version" + save_game.escoria_version = escoria.ESCORIA_VERSION + save_game.game_version = escoria.project_settings_manager.get_setting( + escoria.project_settings_manager.GAME_VERSION ) save_game.name = p_savename - + var datetime = OS.get_datetime() var datetime_string = "%02d/%02d/%02d %02d:%02d" % [ datetime["day"], @@ -150,7 +179,7 @@ func _do_save_game(p_savename: String) -> ESCSaveGame: datetime["minute"], ] save_game.date = datetime_string - + escoria.globals_manager.save_game(save_game) escoria.object_manager.save_game(save_game) escoria.main.save_game(save_game) @@ -175,15 +204,15 @@ func load_game(id: int): escoria.logger.info( "esc_save_manager.gd:load_game()", ["Loading savegame %s" % str(id)]) - + var save_game: ESCSaveGame = ResourceLoader.load(save_file_path) - + var plugin_config = ConfigFile.new() plugin_config.load("res://addons/escoria-core/plugin.cfg") var escoria_version = plugin_config.get_value("plugin", "version") - + # Migrate savegame through escoria versions - + if escoria_version != save_game.escoria_version: var migration_manager: ESCMigrationManager = ESCMigrationManager.new() save_game = migration_manager.migrate( @@ -193,41 +222,48 @@ func load_game(id: int): "res://addons/escoria-core/game/core-scripts/migrations/versions" ) - # Migrate savegame through game versions - - if ProjectSettings.get_setting("escoria/main/game_version") != \ - save_game.game_version and \ - ProjectSettings.get_setting( - "escoria/main/game_migration_path" - ) != "": + # Migrate savegame through game versions + + if escoria.project_settings_manager.get_setting( + escoria.project_settings_manager.GAME_VERSION + ) != save_game.game_version \ + and escoria.project_settings_manager.get_setting( + escoria.project_settings_manager.GAME_MIGRATION_PATH + ) != "": var migration_manager: ESCMigrationManager = ESCMigrationManager.new() save_game = migration_manager.migrate( save_game, save_game.game_version, - ProjectSettings.get_setting("escoria/main/game_version"), - ProjectSettings.get_setting( - "escoria/main/game_migration_path" + escoria.project_settings_manager.get_setting( + escoria.project_settings_manager.GAME_VERSION + ), + escoria.project_settings_manager.get_setting( + escoria.project_settings_manager.GAME_MIGRATION_PATH ) ) - + escoria.event_manager.interrupt_running_event() - var load_event = ESCEvent.new(":load") + var load_event = ESCEvent.new("%s%s" % [ESCEvent.PREFIX, escoria.event_manager.EVENT_LOAD]) var load_statements = [] - + load_statements.append( ESCCommand.new( - "transition %s out" % - [ProjectSettings.get_setting("escoria/ui/default_transition")] + "%s %s out" % + [ + _transition.get_command_name(), + escoria.project_settings_manager.get_setting( + escoria.project_settings_manager.DEFAULT_TRANISITION + )] ) ) load_statements.append( - ESCCommand.new("hide_menu main") + ESCCommand.new("%s main" % _hide_menu.get_command_name()) ) load_statements.append( - ESCCommand.new("hide_menu pause") + ESCCommand.new("%s pause" % _hide_menu.get_command_name()) ) - + ## GLOBALS for k in save_game.globals.keys(): escoria.globals_manager.set_global( @@ -235,83 +271,115 @@ func load_game(id: int): save_game.globals[k], true ) - + ## ROOM load_statements.append( - ESCCommand.new("change_scene %s false" \ - % save_game.main["current_scene_filename"]) + ESCCommand.new("%s %s false" % + [ + _change_scene.get_command_name(), + save_game.main["current_scene_filename"] + ] + ) ) - + ## OBJECTS for object_global_id in save_game.objects.keys(): if escoria.object_manager.has(object_global_id) and \ save_game.objects[object_global_id].has("active"): - load_statements.append(ESCCommand.new("set_active %s %s" \ - % [object_global_id, - save_game.objects[object_global_id]["active"]]) - ) - - if save_game.objects[object_global_id].has("interactive"): - load_statements.append(ESCCommand.new("set_interactive %s %s" \ - % [object_global_id, - save_game.objects[object_global_id]["interactive"]]) - ) - - if save_game.objects[object_global_id].has("state"): - load_statements.append(ESCCommand.new("set_state %s %s true" \ - % [object_global_id, - save_game.objects[object_global_id]["state"]]) - ) - - if save_game.objects[object_global_id].has("global_transform"): - load_statements.append(ESCCommand.new("teleport_pos %s %s %s" \ - % [object_global_id, - int(save_game.objects[object_global_id] \ - ["global_transform"].origin.x), - int(save_game.objects[object_global_id] \ - ["global_transform"].origin.y)] + load_statements.append(ESCCommand.new("%s %s %s" \ + % [ + _set_active.get_command_name(), + object_global_id, + save_game.objects[object_global_id]["active"] + ] ) ) - load_statements.append(ESCCommand.new("set_angle %s %s" \ - % [object_global_id, - save_game.objects[object_global_id]["last_deg"]]) + + if save_game.objects[object_global_id].has("interactive"): + load_statements.append(ESCCommand.new("%s %s %s" \ + % [ + _set_interactive.get_command_name(), + object_global_id, + save_game.objects[object_global_id]["interactive"] + ] + ) ) - - if object_global_id in ["_music", "_sound", "_speech"]: + + if save_game.objects[object_global_id].has("state"): + load_statements.append(ESCCommand.new("%s %s %s true" \ + % [ + _set_state.get_command_name(), + object_global_id, + save_game.objects[object_global_id]["state"] + ] + ) + ) + + if save_game.objects[object_global_id].has("global_transform"): + load_statements.append(ESCCommand.new("%s %s %s %s" \ + % [ + _teleport_pos.get_command_name(), + object_global_id, + int(save_game.objects[object_global_id] \ + ["global_transform"].origin.x), + int(save_game.objects[object_global_id] \ + ["global_transform"].origin.y) + ] + ) + ) + load_statements.append(ESCCommand.new("%s %s %s" \ + % [ + _set_angle.get_command_name(), + object_global_id, + save_game.objects[object_global_id]["last_deg"] + ] + ) + ) + + if object_global_id in [ + escoria.object_manager.MUSIC, + escoria.object_manager.SOUND, escoria.object_manager.SPEECH + ]: if save_game.objects[object_global_id]["state"] in [ "default", "off" ]: load_statements.append( - ESCCommand.new("stop_snd %s" % [ + ESCCommand.new("%s %s" % [ + _stop_snd.get_command_name(), object_global_id, ]) ) else: load_statements.append( - ESCCommand.new("play_snd %s %s" % [ + ESCCommand.new("%s %s %s" % [ + _play_snd.get_command_name(), save_game.objects[object_global_id]["state"], object_global_id, ]) ) - + load_statements.append( ESCCommand.new( - "transition %s in" % - [ProjectSettings.get_setting("escoria/ui/default_transition")] + "%s %s in" % + [ + _transition.get_command_name(), + escoria.project_settings_manager.get_setting( + escoria.project_settings_manager.DEFAULT_TRANISITION + )] ) ) - + load_event.statements = load_statements - + escoria.set_game_paused(false) - + escoria.event_manager.queue_event(load_event) escoria.logger.debug( "esc_save_manager.gd:load_game()", ["Load event queued."]) - - + + # Save the game settings in the settings file. func save_settings(): var settings_res := ESCSaveSettings.new() @@ -335,9 +403,10 @@ func save_settings(): var error: int = ResourceSaver.save(save_path, settings_res) if error != OK: escoria.logger.report_errors( - "esc_save_data_resources.gd:save_settings()", + "esc_save_manager.gd:save_settings()", ["There was an issue writing settings %s" % save_path]) + # Load the game settings from the settings file # **Returns** The Resource structure loaded from settings file func load_settings() -> Resource: @@ -346,7 +415,7 @@ func load_settings() -> Resource: var file: File = File.new() if not file.file_exists(save_settings_path): escoria.logger.report_warnings( - "esc_save_data_resources.gd:load_settings()", + "esc_save_manager.gd:load_settings()", ["Settings file %s doesn't exist" % save_settings_path, "Setting default settings."]) save_settings() diff --git a/addons/escoria-core/game/core-scripts/save_data/esc_savesettings.gd b/addons/escoria-core/game/core-scripts/save_data/esc_savesettings.gd index 56fb3a83..723f0736 100644 --- a/addons/escoria-core/game/core-scripts/save_data/esc_savesettings.gd +++ b/addons/escoria-core/game/core-scripts/save_data/esc_savesettings.gd @@ -1,4 +1,6 @@ -# Resource holding game settings. +# Resource holding game settings. Note that we call directly to ProjectSettings +# for instance variable initialization since this class is instantiated from +# escoria.gd. extends Resource class_name ESCSaveSettings diff --git a/addons/escoria-core/game/escoria.gd b/addons/escoria-core/game/escoria.gd index 06044896..7a1625c7 100644 --- a/addons/escoria-core/game/escoria.gd +++ b/addons/escoria-core/game/escoria.gd @@ -1,6 +1,7 @@ # The escoria main script tool extends Node +class_name Escoria # Signal sent when pause menu has to be displayed signal request_pause_menu @@ -12,9 +13,6 @@ signal paused signal resumed -# Escoria version number -const ESCORIA_VERSION = "0.1.0" - # Current game state # * DEFAULT: Common game function # * DIALOG: Game is playing a dialog @@ -26,6 +24,16 @@ enum GAME_STATE { } +# Escoria version number +const ESCORIA_VERSION = "0.1.0" + +# Audio bus indices. +const BUS_MASTER = "Master" +const BUS_SFX = "SFX" +const BUS_MUSIC = "Music" +const BUS_SPEECH = "Speech" + + # Logger used var logger: ESCLogger @@ -53,6 +61,9 @@ var room_manager: ESCRoomManager # ESC object manager instance var object_manager: ESCObjectManager +# ESC project settings manager instance +var project_settings_manager: ESCProjectSettingsManager + # ESC command registry instance var command_registry: ESCCommandRegistry @@ -71,15 +82,15 @@ var inventory # These are settings that the player can affect and save/load later var settings: ESCSaveSettings -# The current state of the game -onready var current_state = GAME_STATE.DEFAULT - # The game resolution onready var game_size = get_viewport().size # The main scene onready var main = $main +# The current state of the game +onready var current_state = GAME_STATE.DEFAULT + # The escoria inputs manager var inputs_manager: ESCInputsManager @@ -91,8 +102,7 @@ var game_scene: ESCGame # The compiled start script loaded from ProjectSettings # escoria/main/game_start_script -var start_script : ESCScript - +var start_script: ESCScript # Initialize various objects @@ -112,18 +122,21 @@ func _init(): self.save_manager = ESCSaveManager.new() self.inputs_manager = ESCInputsManager.new() self.room_manager = ESCRoomManager.new() + self.project_settings_manager = ESCProjectSettingsManager.new() settings = ESCSaveSettings.new() - if ProjectSettings.get_setting("escoria/ui/game_scene") == "": + if self.project_settings_manager.get_setting(self.project_settings_manager.GAME_SCENE) == "": logger.report_errors("escoria.gd", - ["Parameter escoria/ui/game_scene is not set!"] + ["Project setting '%s' is not set!" % self.project_settings_manager.GAME_SCENE] ) else: - self.game_scene = resource_cache.get_resource( - ProjectSettings.get_setting("escoria/ui/game_scene") + game_scene = resource_cache.get_resource( + self.project_settings_manager.get_setting(self.project_settings_manager.GAME_SCENE) ).instance() - + + print(get_script().get_path()) + # Load settings func _ready(): @@ -131,13 +144,13 @@ func _ready(): apply_settings(settings) room_manager.register_reserved_globals() inputs_manager.register_core() - if ProjectSettings.get_setting("escoria/main/game_start_script").empty(): + if self.project_settings_manager.get_setting(self.project_settings_manager.GAME_START_SCRIPT).empty(): logger.report_errors("escoria.gd", [ - "Project setting 'escoria/main/game_start_script' is not set!" + "Project setting '%s' is not set!" % self.project_settings_manager.GAME_START_SCRIPT ]) start_script = self.esc_compiler.load_esc_file( - ProjectSettings.get_setting("escoria/main/game_start_script") + self.project_settings_manager.get_setting(self.project_settings_manager.GAME_START_SCRIPT) ) @@ -155,126 +168,12 @@ func _notification(what): # Usually you'll want to show some logos animations before spawning the main # menu in the escoria/main/game_start_script 's :init event func init(): - run_event_from_script(start_script, "init") + run_event_from_script(start_script, self.event_manager.EVENT_INIT) # Called by Main menu "start new game" func new_game(): - run_event_from_script(start_script, "newgame") - - -# Run a generic action -# -# #### Parameters -# -# - action: type of the action to run -# - params: Parameters for the action -# - can_interrupt: if true, this command will interrupt any ongoing event -# before it is finished -func do(action: String, params: Array = [], can_interrupt: bool = false) -> void: - if current_state == GAME_STATE.DEFAULT: - match action: - "walk": - if can_interrupt: - event_manager.interrupt_running_event() - - self.action_manager.clear_current_action() - - var walk_fast = false - if params.size() > 2: - walk_fast = true if params[2] else false - - # Check moving object. - if not escoria.object_manager.has(params[0]): - escoria.logger.report_errors( - "escoria.gd:do()", - [ - "Walk action requested on inexisting " + \ - "object: %s " % params[0] - ] - ) - return - - var moving_obj = escoria.object_manager.get_object(params[0]) - var target - - if params[1] is String: - if not escoria.object_manager.has(params[1]): - escoria.logger.report_errors( - "escoria.gd:do()", - [ - "Walk action requested to inexisting " + \ - "object: %s " % params[1] - ] - ) - return - - target = escoria.object_manager.get_object(params[1]) - elif params[1] is Vector2: - target = params[1] - - self.action_manager.perform_walk(moving_obj, target, walk_fast) - - "item_left_click": - if params[0] is String: - self.logger.info( - "escoria.do(): item_left_click on item ", - [params[0]] - ) - - if can_interrupt: - event_manager.interrupt_running_event() - - var item = self.object_manager.get_object(params[0]) - self.action_manager.perform_inputevent_on_object(item, params[1]) - - "item_right_click": - if params[0] is String: - self.logger.info( - "escoria.do(): item_right_click on item ", - [params[0]] - ) - - if can_interrupt: - event_manager.interrupt_running_event() - - var item = self.object_manager.get_object(params[0]) - self.action_manager.perform_inputevent_on_object(item, params[1], true) - - "trigger_in": - var trigger_id = params[0] - var object_id = params[1] - var trigger_in_verb = params[2] - self.logger.info("escoria.do(): trigger_in %s by %s" % [ - trigger_id, - object_id - ]) - self.event_manager.queue_event( - object_manager.get_object(trigger_id).events[ - trigger_in_verb - ] - ) - - "trigger_out": - var trigger_id = params[0] - var object_id = params[1] - var trigger_out_verb = params[2] - self.logger.info("escoria.do(): trigger_out %s by %s" % [ - trigger_id, - object_id - ]) - self.event_manager.queue_event( - object_manager.get_object(trigger_id).events[ - trigger_out_verb - ] - ) - - _: - self.logger.report_warnings("escoria.gd:do()", - ["Action received:", action, "with params ", params]) - elif current_state == GAME_STATE.WAIT: - pass - + run_event_from_script(start_script, self.event_manager.EVENT_NEW_GAME) # Apply the loaded settings @@ -290,19 +189,19 @@ func apply_settings(p_settings: ESCSaveSettings) -> void: settings = ESCSaveSettings.new() AudioServer.set_bus_volume_db( - AudioServer.get_bus_index("Master"), + AudioServer.get_bus_index(BUS_MASTER), linear2db(settings.master_volume) ) AudioServer.set_bus_volume_db( - AudioServer.get_bus_index("SFX"), + AudioServer.get_bus_index(BUS_SFX), linear2db(settings.sfx_volume) ) AudioServer.set_bus_volume_db( - AudioServer.get_bus_index("Music"), + AudioServer.get_bus_index(BUS_MUSIC), linear2db(settings.music_volume) ) AudioServer.set_bus_volume_db( - AudioServer.get_bus_index("Speech"), + AudioServer.get_bus_index(BUS_SPEECH), linear2db(settings.speech_volume) ) TranslationServer.set_locale(settings.text_lang) @@ -312,10 +211,10 @@ func apply_settings(p_settings: ESCSaveSettings) -> void: # Input function to manage specific input keys func _input(event): - if InputMap.has_action("esc_show_debug_prompt") \ - and event.is_action_pressed("esc_show_debug_prompt"): + if InputMap.has_action(ESCInputsManager.ESC_SHOW_DEBUG_PROMPT) \ + and event.is_action_pressed(ESCInputsManager.ESC_SHOW_DEBUG_PROMPT): escoria.main.get_node("layers/debug_layer/esc_prompt_popup").popup() - + if event.is_action_pressed("ui_cancel"): emit_signal("request_pause_menu") @@ -356,24 +255,7 @@ func run_event_from_script(script: ESCScript, event_name: String): [] ) return - -# Register a new project setting if it hasn't been defined already -# -# #### Parameters -# -# - name: Name of the project setting -# - default: Default value -# - info: Property info for the setting -func register_setting(name: String, default, info: Dictionary): - if not ProjectSettings.has_setting(name): - ProjectSettings.set_setting( - name, - default - ) - info.name = name - ProjectSettings.add_property_info(info) - # Register a user interface. This should be called in a deferred way # from the addon's _enter_tree. @@ -381,7 +263,11 @@ func register_setting(name: String, default, info: Dictionary): # #### Parameters # - game_scene: Path to the game scene extending ESCGame func register_ui(game_scene: String): - if not ProjectSettings.get_setting("escoria/ui/game_scene") in [ + var game_scene_setting_value = escoria.project_settings_manager.get_setting( + escoria.project_settings_manager.GAME_SCENE + ) + + if not game_scene_setting_value in [ "", game_scene ]: @@ -389,11 +275,11 @@ func register_ui(game_scene: String): "escoria.gd:register_ui()", [ "Can't register user interface because %s is registered" % \ - ProjectSettings.get_setting("escoria/ui/game_scene") + game_scene_setting_value ] ) - ProjectSettings.set_setting( - "escoria/ui/game_scene", + escoria.project_settings_manager.set_setting( + escoria.project_settings_manager.GAME_SCENE, game_scene ) @@ -403,18 +289,22 @@ func register_ui(game_scene: String): # #### Parameters # - game_scene: Path to the game scene extending ESCGame func deregister_ui(game_scene: String): - if ProjectSettings.get_setting("escoria/ui/game_scene") != game_scene: + var game_scene_setting_value = escoria.project_settings_manager.get_setting( + escoria.project_settings_manager.GAME_SCENE + ) + + if game_scene_setting_value != game_scene: logger.report_errors( "escoria.gd:deregister_ui()", [ ( "Can't deregister user interface %s because it " + "is not registered." - ) % ProjectSettings.get_setting("escoria/ui/game_scene") + ) % game_scene_setting_value ] ) - ProjectSettings.set_setting( - "escoria/ui/game_scene", + escoria.project.set_setting( + escoria.project_settings_manager.GAME_SCENE, "" ) @@ -425,26 +315,30 @@ func deregister_ui(game_scene: String): # #### Parameters # - manager_class: Path to the manager class script func register_dialog_manager(manager_class: String): - var dialog_managers: Array = ProjectSettings.get_setting( - "escoria/ui/dialog_managers" - ) - if manager_class in dialog_managers: - return - dialog_managers.push_back(manager_class) - ProjectSettings.set_setting( - "escoria/ui/dialog_managers", - dialog_managers + var dialog_managers: Array = escoria.project_settings_manager.get_setting( + escoria.project_settings_manager.DIALOG_MANAGERS ) + if manager_class in dialog_managers: + return + + dialog_managers.push_back(manager_class) + + escoria.project_settings_manager.set_setting( + escoria.project_settings_manager.DIALOG_MANAGERS, + dialog_managers + ) + # Deregister a dialog manager addon # # #### Parameters # - manager_class: Path to the manager class script func deregister_dialog_manager(manager_class: String): - var dialog_managers: Array = ProjectSettings.get_setting( - "escoria/ui/dialog_managers" + var dialog_managers: Array = escoria.project_settings_manager.get_setting( + escoria.project_settings_manager.DIALOG_MANAGERS ) + if not manager_class in dialog_managers: logger.report_warnings( "escoria.gd:deregister_dialog_manager()", @@ -456,8 +350,8 @@ func deregister_dialog_manager(manager_class: String): dialog_managers.erase(manager_class) - ProjectSettings.set_setting( - "escoria/ui/dialog_managers", + escoria.project_settings_manager.set_setting( + escoria.project_settings_manager.DIALOG_MANAGERS, dialog_managers ) diff --git a/addons/escoria-core/game/inputs_manager.gd b/addons/escoria-core/game/inputs_manager.gd index 1e4a7ef3..96b49836 100644 --- a/addons/escoria-core/game/inputs_manager.gd +++ b/addons/escoria-core/game/inputs_manager.gd @@ -15,6 +15,13 @@ enum { } +# Input action for use by InputMap +const SWITCH_ACTION_VERB = "switch_action_verb" + +# Input action for use by InputMap +const ESC_SHOW_DEBUG_PROMPT = "esc_show_debug_prompt" + + # The current input mode var input_mode = INPUT_ALL diff --git a/addons/escoria-core/game/main.gd b/addons/escoria-core/game/main.gd index ca5ea95f..737de738 100644 --- a/addons/escoria-core/game/main.gd +++ b/addons/escoria-core/game/main.gd @@ -121,7 +121,9 @@ func set_camera_limits(camera_limit_id: int = 0) -> void: [scene_camera_limits] ) - escoria.object_manager.get_object("_camera").node.set_limits(limits) + escoria.object_manager.get_object( + escoria.object_manager.CAMERA + ).node.set_limits(limits) func save_game(p_savegame_res: Resource) -> void: diff --git a/addons/escoria-core/game/project_settings_manager.gd b/addons/escoria-core/game/project_settings_manager.gd new file mode 100644 index 00000000..0a6b0c3d --- /dev/null +++ b/addons/escoria-core/game/project_settings_manager.gd @@ -0,0 +1,123 @@ +# Registers and allows access to Escoria-specific project settings. +extends Node +class_name ESCProjectSettingsManager + + +# Root for Escoria-specific project settings +const _ESCORIA_SETTINGS_ROOT = "escoria" + +# UI-related Escoria project settings +const _UI_ROOT = "ui" + +const DEFAULT_DIALOG_TYPE = "%s/%s/default_dialog_type" % [_ESCORIA_SETTINGS_ROOT, _UI_ROOT] +const DEFAULT_TRANISITION = "%s/%s/default_transition" % [_ESCORIA_SETTINGS_ROOT, _UI_ROOT] +const DIALOG_MANAGERS = "%s/%s/dialog_managers" % [_ESCORIA_SETTINGS_ROOT, _UI_ROOT] +const GAME_SCENE = "%s/%s/game_scene" % [_ESCORIA_SETTINGS_ROOT, _UI_ROOT] +const INVENTORY_ITEM_SIZE = "%s/%s/inventory_item_size" % [_ESCORIA_SETTINGS_ROOT, _UI_ROOT] +const ITEMS_AUTOREGISTER_PATH = "%s/%s/items_autoregister_path" % [_ESCORIA_SETTINGS_ROOT, _UI_ROOT] +const TRANSITION_PATHS = "%s/%s/transition_paths" % [_ESCORIA_SETTINGS_ROOT, _UI_ROOT] + +# Main Escoria project settings +const _MAIN_ROOT = "main" + +const COMMAND_DIRECTORIES = "%s/%s/command_directories" % [_ESCORIA_SETTINGS_ROOT, _MAIN_ROOT] +const COMMAND_PATHS = "%s/%s/command_paths" % [_ESCORIA_SETTINGS_ROOT, _MAIN_ROOT] +const FORCE_QUIT = "%s/%s/force_quit" % [_ESCORIA_SETTINGS_ROOT, _MAIN_ROOT] +const GAME_MIGRATION_PATH = "%s/%s/game_migration_path" % [_ESCORIA_SETTINGS_ROOT, _MAIN_ROOT] +const GAME_VERSION = "%s/%s/game_version" % [_ESCORIA_SETTINGS_ROOT, _MAIN_ROOT] +const GAME_START_SCRIPT = "%s/%s/game_start_script" % [_ESCORIA_SETTINGS_ROOT, _MAIN_ROOT] +const SAVEGAMES_PATH = "%s/%s/savegames_path" % [_ESCORIA_SETTINGS_ROOT, _MAIN_ROOT] +const SETTINGS_PATH = "%s/%s/settings_path" % [_ESCORIA_SETTINGS_ROOT, _MAIN_ROOT] +const TEXT_LANG = "%s/%s/text_lang" % [_ESCORIA_SETTINGS_ROOT, _MAIN_ROOT] +const VOICE_LANG = "%s/%s/voice_lang" % [_ESCORIA_SETTINGS_ROOT, _MAIN_ROOT] + +# Debug-related Escoria project settings +const _DEBUG_ROOT = "debug" + +const CRASH_MESSAGE = "%s/%s/crash_message" % [_ESCORIA_SETTINGS_ROOT, _DEBUG_ROOT] +const DEVELOPMENT_LANG = "%s/%s/development_lang" % [_ESCORIA_SETTINGS_ROOT, _DEBUG_ROOT] +const ENABLE_ROOM_SELECTOR = "%s/%s/enable_room_selector" % [_ESCORIA_SETTINGS_ROOT, _DEBUG_ROOT] +const LOG_FILE_PATH = "%s/%s/log_file_path" % [_ESCORIA_SETTINGS_ROOT, _DEBUG_ROOT] +const LOG_LEVEL = "%s/%s/log_level" % [_ESCORIA_SETTINGS_ROOT, _DEBUG_ROOT] +const ROOM_SELECTOR_ROOM_DIR = "%s/%s/room_selector_room_dir" % [_ESCORIA_SETTINGS_ROOT, _DEBUG_ROOT] +const TERMINATE_ON_ERRORS = "%s/%s/terminate_on_errors" % [_ESCORIA_SETTINGS_ROOT, _DEBUG_ROOT] +const TERMINATE_ON_WARNINGS = "%s/%s/terminate_on_warnings" % [_ESCORIA_SETTINGS_ROOT, _DEBUG_ROOT] + +# Sound-related Escoria project settings +const _SOUND_ROOT = "sound" + +const MASTER_VOLUME = "%s/%s/master_volume" % [_ESCORIA_SETTINGS_ROOT, _SOUND_ROOT] +const MUSIC_VOLUME = "%s/%s/music_volume" % [_ESCORIA_SETTINGS_ROOT, _SOUND_ROOT] +const SFX_VOLUME = "%s/%s/sfx_volume" % [_ESCORIA_SETTINGS_ROOT, _SOUND_ROOT] +const SPEECH_ENABLED = "%s/%s/speech_enabled" % [_ESCORIA_SETTINGS_ROOT, _SOUND_ROOT] +const SPEECH_EXTENSION = "%s/%s/speech_extension" % [_ESCORIA_SETTINGS_ROOT, _SOUND_ROOT] +const SPEECH_FOLDER = "%s/%s/speech_folder" % [_ESCORIA_SETTINGS_ROOT, _SOUND_ROOT] +const SPEECH_VOLUME = "%s/%s/speech_volume" % [_ESCORIA_SETTINGS_ROOT, _SOUND_ROOT] + +# Platform-related Escoria project settings +const _PLATFORM_ROOT = "platform" + +const SKIP_CACHE = "%s/%s/skip_cache" % [_ESCORIA_SETTINGS_ROOT, _PLATFORM_ROOT] +const SKIP_CACHE_MOBILE = "%s/%s/skip_cache.mobile" % [_ESCORIA_SETTINGS_ROOT, _PLATFORM_ROOT] + +# Simple dialog-related Escoria project settings +const _SIMPLE_DIALOG_ROOT = "dialog_simple" + +const AVATARS_PATH = "%s/%s/avatars_path" % [_ESCORIA_SETTINGS_ROOT, _SIMPLE_DIALOG_ROOT] +const TEXT_SPEED_PER_CHARACTER = "%s/%s/text_speed_per_character" % [_ESCORIA_SETTINGS_ROOT, _SIMPLE_DIALOG_ROOT] +const FAST_TEXT_SPEED_PER_CHARACTER = "%s/%s/fast_text_speed_per_character" % [_ESCORIA_SETTINGS_ROOT, _SIMPLE_DIALOG_ROOT] +const MAX_TIME_TO_DISAPPEAR = "%s/%s/max_time_to_disappear" % [_ESCORIA_SETTINGS_ROOT, _SIMPLE_DIALOG_ROOT] + + +# Register a new project setting if it hasn't been defined already +# +# #### Parameters +# +# - name: Name of the project setting +# - default: Default value +# - info: Property info for the setting +func register_setting(name: String, default, info: Dictionary) -> void: + if not ProjectSettings.has_setting(name): + ProjectSettings.set_setting( + name, + default + ) + info.name = name + ProjectSettings.add_property_info(info) + + +# Retrieves the specified project setting. +# +# #### Parameters +# +# - key: Project setting name. +# +# *Returns* the value of the project setting located with key. +func get_setting(key: String): + if not ProjectSettings.has_setting(key): + escoria.logger.report_errors("project_settings_manager.gd", + ["Parameter %s is not set!" % key] + ) + + return ProjectSettings.get_setting(key) + + +# Sets the specified project setting to the provided value. +# +# #### Parameters +# +# - key: Project setting name. +# - value: Project setting value. +func set_setting(key: String, value) -> void: + ProjectSettings.set_setting(key, value) + + +# Simple wrapper for consistency's sake. +# +# #### Parameters +# +# - key: Project setting name. +# +# *Returns* true iff the project setting exists. +func has_setting(key: String) -> bool: + return ProjectSettings.has_setting(key) diff --git a/addons/escoria-core/game/scenes/camera_player/esc_camera.gd b/addons/escoria-core/game/scenes/camera_player/esc_camera.gd index 1b7e77e5..d3ddfc1b 100644 --- a/addons/escoria-core/game/scenes/camera_player/esc_camera.gd +++ b/addons/escoria-core/game/scenes/camera_player/esc_camera.gd @@ -23,7 +23,7 @@ func _ready(): _tween.connect("tween_all_completed", self, "_target_reached") escoria.object_manager.register_object( ESCObject.new( - "_camera", + escoria.object_manager.CAMERA, self ), true @@ -134,7 +134,7 @@ func set_target(p_target, p_speed : float = 0.0): func set_camera_zoom(p_zoom_level: float, p_time: float): if p_zoom_level <= 0.0: escoria.logger.report_errors( - "camera.gd:set_camera_zoom()", + "esc_camera.gd:set_camera_zoom()", ["Tried to set negative or zero zoom level"] ) diff --git a/addons/escoria-core/game/scenes/dialogs/esc_dialog_player.gd b/addons/escoria-core/game/scenes/dialogs/esc_dialog_player.gd index 520cfd8f..bc63d4f5 100644 --- a/addons/escoria-core/game/scenes/dialogs/esc_dialog_player.gd +++ b/addons/escoria-core/game/scenes/dialogs/esc_dialog_player.gd @@ -58,8 +58,10 @@ func _input(event): # # *Returns* The path to the matching voice file func _get_voice_file(key: String, start: String = "") -> String: - if start == "": - start = ProjectSettings.get("escoria/sound/speech_folder") + if start == "": + start = escoria.project_settings_manager.get_setting( + escoria.project_settings_manager.SPEECH_FOLDER + ) var _dir = Directory.new() if _dir.open(start) == OK: _dir.list_dir_begin(true, true) @@ -75,7 +77,9 @@ func _get_voice_file(key: String, start: String = "") -> String: else: if file_name == "%s.%s.import" % [ key, - ProjectSettings.get("escoria/sound/speech_extension") + escoria.project_settings_manager.get_setting( + escoria.project_settings_manager.SPEECH_EXTENSION + ) ]: return start.plus_file(file_name.trim_suffix(".import")) file_name = _dir.get_next() @@ -90,11 +94,13 @@ func _get_voice_file(key: String, start: String = "") -> String: # - type: UI to use for the dialog # - text: Text to say func say(character: String, type: String, text: String) -> void: - if type == "": - type = ProjectSettings.get_setting("escoria/ui/default_dialog_type") - is_speaking = true - for _manager_class in ProjectSettings.get_setting( - "escoria/ui/dialog_managers" + if type == "": + type = escoria.project_settings_manager.get_setting( + escoria.project_settings_manager.DEFAULT_DIALOG_TYPE + ) + is_speaking = true + for _manager_class in escoria.project_settings_manager.get_setting( + escoria.project_settings_manager.DIALOG_MANAGERS ): if ResourceLoader.exists(_manager_class): var _manager: ESCDialogManager = load(_manager_class).new() @@ -126,7 +132,7 @@ func say(character: String, type: String, text: String) -> void: ) if _speech_resource != "": ( - escoria.object_manager.get_object("_speech").node\ + escoria.object_manager.get_object(escoria.object_manager.SPEECH).node\ as ESCSpeechPlayer ).set_state(_speech_resource) text = tr(matches.get_string("key")) @@ -158,14 +164,14 @@ func speedup() -> void: func start_dialog_choices(dialog: ESCDialog, type: String = "simple"): if dialog.options.empty(): escoria.logger.report_errors( - "dialog_player.gd:start_dialog_choices()", + "esc_dialog_player.gd:start_dialog_choices()", ["Received answers array was empty."] ) var _dialog_chooser_ui: ESCDialogManager = null - for _manager_class in ProjectSettings.get_setting( - "escoria/ui/dialog_managers" + for _manager_class in escoria.project_settings_manager.get_setting( + escoria.project_settings_manager.DIALOG_MANAGERS ): if ResourceLoader.exists(_manager_class): var _manager: ESCDialogManager = load(_manager_class).new() diff --git a/addons/escoria-core/game/scenes/esc_prompt/esc_prompt_popup.gd b/addons/escoria-core/game/scenes/esc_prompt/esc_prompt_popup.gd index ecf016c3..a9da4db3 100644 --- a/addons/escoria-core/game/scenes/esc_prompt/esc_prompt_popup.gd +++ b/addons/escoria-core/game/scenes/esc_prompt/esc_prompt_popup.gd @@ -8,6 +8,13 @@ onready var past_actions = $VBoxContainer/past_actions # Reference to the command input onready var command = $VBoxContainer/command +# ESC commands kept around for references to their command names. +var _debug: DebugCommand + + +func _ready() -> void: + _debug = DebugCommand.new() + # Run a command # @@ -23,18 +30,16 @@ func _on_command_text_entered(p_command_str : String): past_actions.text += "# " + p_command_str past_actions.text += "\n" - var actual_command = ":debug\n" + p_command_str + "\n" - var errors = [] var script = escoria.esc_compiler.compile([ - ":debug", + "%s%s" % [ESCEvent.PREFIX, _debug.get_command_name()], p_command_str ]) if script: - escoria.event_manager.queue_event(script.events["debug"]) + escoria.event_manager.queue_event(script.events[escoria.event_manager.EVENT_DEBUG]) var ret = yield(escoria.event_manager, "event_finished") - while ret[1] != "debug": + while ret[1] != _debug.get_command_name(): ret = yield(escoria.event_manager, "event_finished") past_actions.text += "Returned code: %d" % ret[0] diff --git a/addons/escoria-core/game/scenes/inventory/inventory_ui.gd b/addons/escoria-core/game/scenes/inventory/inventory_ui.gd index 99291a7c..6c82e03a 100644 --- a/addons/escoria-core/game/scenes/inventory/inventory_ui.gd +++ b/addons/escoria-core/game/scenes/inventory/inventory_ui.gd @@ -43,8 +43,8 @@ func add_new_item_by_id(item_id: String) -> void: if not escoria.object_manager.has(item_id) or not is_instance_valid( \ escoria.object_manager.get_object(item_id).node): var inventory_file = "%s/%s.tscn" % [ - ProjectSettings.get_setting( - "escoria/ui/items_autoregister_path" + escoria.project_settings_manager.get_setting( + escoria.project_settings_manager.ITEMS_AUTOREGISTER_PATH ).trim_suffix("/"), item_id ] diff --git a/addons/escoria-core/game/scenes/sound/esc_music_player.gd b/addons/escoria-core/game/scenes/sound/esc_music_player.gd index f43a250c..9b01be86 100644 --- a/addons/escoria-core/game/scenes/sound/esc_music_player.gd +++ b/addons/escoria-core/game/scenes/sound/esc_music_player.gd @@ -44,8 +44,10 @@ func set_state(p_state: String, p_force: bool = false) -> void: resource.loop_end = resource.mix_rate * resource.get_length() elif "loop" in resource: resource.loop = true - if ProjectSettings.has_setting("escoria/sound/music_volume"): - stream.volume_db = ProjectSettings.get_setting("escoria/sound/music_volume") + if escoria.project_settings_manager.has_setting(escoria.project_settings_manager.MUSIC_VOLUME): + stream.volume_db = escoria.project_settings_manager.get_setting( + escoria.project_settings_manager.MUSIC_VOLUME + ) stream.play() diff --git a/addons/escoria-core/game/scenes/sound/esc_sound_player.gd b/addons/escoria-core/game/scenes/sound/esc_sound_player.gd index af0e5c38..eef4aa2a 100644 --- a/addons/escoria-core/game/scenes/sound/esc_sound_player.gd +++ b/addons/escoria-core/game/scenes/sound/esc_sound_player.gd @@ -42,9 +42,11 @@ func set_state(p_state: String, p_force: bool = false): if resource is AudioStreamSample: resource.loop_mode = AudioStreamSample.LOOP_DISABLED elif "loop" in resource: - resource.loop = false - if ProjectSettings.has_setting("escoria/sound/sound_volume"): - stream.volume_db = ProjectSettings.get_setting("escoria/sound/sound_volume") + resource.loop = false + if escoria.project_settings_manager.has_setting(escoria.project_settings_manager.SFX_VOLUME): + stream.volume_db = escoria.project_settings_manager.get_setting( + escoria.project_settings_manager.SFX_VOLUME + ) stream.play() diff --git a/addons/escoria-core/game/scenes/transitions/esc_transition_player.gd b/addons/escoria-core/game/scenes/transitions/esc_transition_player.gd index 586fe6d9..f1d4dab3 100644 --- a/addons/escoria-core/game/scenes/transitions/esc_transition_player.gd +++ b/addons/escoria-core/game/scenes/transitions/esc_transition_player.gd @@ -94,10 +94,12 @@ func transition( # *Returns* the full path to the shader or an empty string, if it can't be found func get_transition(name: String) -> String: if name.empty(): - name = ProjectSettings.get_setting( - "escoria/ui/default_transition" + name = escoria.project_settings_manager.get_setting( + escoria.project_settings_manager.DEFAULT_TRANISITION ) - for directory in ProjectSettings.get_setting("escoria/ui/transition_paths"): + for directory in escoria.project_settings_manager.get_setting( + escoria.project_settings_manager.TRANSITION_PATHS + ): if ResourceLoader.exists(directory.plus_file("%s.material" % name)): return directory.plus_file("%s.material" % name) return "" diff --git a/addons/escoria-core/plugin.gd b/addons/escoria-core/plugin.gd index 19ba966b..f14a0bf8 100644 --- a/addons/escoria-core/plugin.gd +++ b/addons/escoria-core/plugin.gd @@ -11,8 +11,8 @@ func _enter_tree(): ) # Add input actions in InputMap - InputMap.add_action("switch_action_verb") - InputMap.add_action("esc_show_debug_prompt") + InputMap.add_action(escoria.inputs_manager.SWITCH_ACTION_VERB) + InputMap.add_action(escoria.inputs_manager.ESC_SHOW_DEBUG_PROMPT) # Define standard settings ProjectSettings.set_setting( @@ -38,85 +38,86 @@ func _ready(): # Prepare the settings in the Escoria UI category func set_escoria_ui_settings(): - escoria.register_setting( - "escoria/ui/default_dialog_type", + escoria.project_settings_manager.register_setting( + escoria.project_settings_manager.DEFAULT_DIALOG_TYPE, "", { "type": TYPE_STRING } ) - escoria.register_setting( - "escoria/ui/game_scene", + escoria.project_settings_manager.register_setting( + escoria.project_settings_manager.GAME_SCENE, "", { - "name": "escoria/ui/game_scene", + "name": escoria.project_settings_manager.GAME_SCENE, "type": TYPE_STRING, "hint": PROPERTY_HINT_FILE, "hint_string": "*.tscn, *.scn" } ) - escoria.register_setting( - "escoria/ui/items_autoregister_path", + escoria.project_settings_manager.register_setting( + escoria.project_settings_manager.ITEMS_AUTOREGISTER_PATH, "res://game/items/escitems/", { - "name": "escoria/ui/items_autoregister_path", + "name": escoria.project_settings_manager.ITEMS_AUTOREGISTER_PATH, "type": TYPE_STRING, "hint": PROPERTY_HINT_DIR } ) - escoria.register_setting( - "escoria/ui/default_transition", + escoria.project_settings_manager.register_setting( + escoria.project_settings_manager.DEFAULT_TRANISITION, "curtain", { - "name": "escoria/ui/default_transition", + "name": escoria.project_settings_manager.DEFAULT_TRANISITION, "type": TYPE_STRING } ) - escoria.register_setting( - "escoria/ui/transition_paths", + escoria.project_settings_manager.register_setting( + escoria.project_settings_manager.TRANSITION_PATHS, [ "res://addons/escoria-core/game/scenes/transitions/shaders/" ], { - "name": "escoria/ui/transition_paths", + "name": escoria.project_settings_manager.TRANSITION_PATHS, "type": TYPE_STRING_ARRAY, "hint": PROPERTY_HINT_DIR } ) - escoria.register_setting( - "escoria/ui/inventory_item_size", + escoria.project_settings_manager.register_setting( + escoria.project_settings_manager.INVENTORY_ITEM_SIZE, Vector2(72, 72), { - "name": "escoria/ui/inventory_item_size", + "name": escoria.project_settings_manager.INVENTORY_ITEM_SIZE, "type": TYPE_VECTOR2 } ) - escoria.register_setting( - "escoria/ui/dialog_managers", + escoria.project_settings_manager.register_setting( + escoria.project_settings_manager.DIALOG_MANAGERS, [], { "type": TYPE_STRING_ARRAY } ) + # Prepare the settings in the Escoria main category func set_escoria_main_settings(): - escoria.register_setting( - "escoria/main/game_version", + escoria.project_settings_manager.register_setting( + escoria.project_settings_manager.GAME_VERSION, "", { "type": TYPE_STRING } ) - escoria.register_setting( - "escoria/main/game_start_script", + escoria.project_settings_manager.register_setting( + escoria.project_settings_manager.GAME_START_SCRIPT, "", { "type": TYPE_STRING, @@ -125,16 +126,16 @@ func set_escoria_main_settings(): } ) - escoria.register_setting( - "escoria/main/force_quit", + escoria.project_settings_manager.register_setting( + escoria.project_settings_manager.FORCE_QUIT, true, { "type": TYPE_BOOL } ) - escoria.register_setting( - "escoria/main/command_directories", + escoria.project_settings_manager.register_setting( + escoria.project_settings_manager.COMMAND_DIRECTORIES, [ "res://addons/escoria-core/game/core-scripts/esc/commands" ], @@ -143,8 +144,8 @@ func set_escoria_main_settings(): } ) - escoria.register_setting( - "escoria/main/text_lang", + escoria.project_settings_manager.register_setting( + escoria.project_settings_manager.TEXT_LANG, TranslationServer.get_locale(), { "type": TYPE_STRING, @@ -152,8 +153,8 @@ func set_escoria_main_settings(): } ) - escoria.register_setting( - "escoria/main/voice_lang", + escoria.project_settings_manager.register_setting( + escoria.project_settings_manager.VOICE_LANG, TranslationServer.get_locale(), { "type": TYPE_STRING, @@ -161,8 +162,8 @@ func set_escoria_main_settings(): } ) - escoria.register_setting( - "escoria/main/savegames_path", + escoria.project_settings_manager.register_setting( + escoria.project_settings_manager.SAVEGAMES_PATH, "user://saves/", { "type": TYPE_STRING, @@ -170,8 +171,8 @@ func set_escoria_main_settings(): } ) - escoria.register_setting( - "escoria/main/settings_path", + escoria.project_settings_manager.register_setting( + escoria.project_settings_manager.SETTINGS_PATH, "user://", { "type": TYPE_STRING, @@ -179,8 +180,8 @@ func set_escoria_main_settings(): } ) - escoria.register_setting( - "escoria/main/game_migration_path", + escoria.project_settings_manager.register_setting( + escoria.project_settings_manager.GAME_MIGRATION_PATH, "", { "type": TYPE_STRING, @@ -191,32 +192,32 @@ func set_escoria_main_settings(): # Prepare the settings in the Escoria debug category func set_escoria_debug_settings(): - escoria.register_setting( - "escoria/debug/terminate_on_warnings", + escoria.project_settings_manager.register_setting( + escoria.project_settings_manager.TERMINATE_ON_WARNINGS, false, { "type": TYPE_BOOL } ) - escoria.register_setting( - "escoria/debug/terminate_on_errors", + escoria.project_settings_manager.register_setting( + escoria.project_settings_manager.TERMINATE_ON_ERRORS, true, { "type": TYPE_BOOL } ) - escoria.register_setting( - "escoria/debug/development_lang", + escoria.project_settings_manager.register_setting( + escoria.project_settings_manager.DEVELOPMENT_LANG, "en", { "type": TYPE_STRING } ) - escoria.register_setting( - "escoria/debug/log_level", + escoria.project_settings_manager.register_setting( + escoria.project_settings_manager.LOG_LEVEL, "ERROR", { "type": TYPE_STRING, @@ -225,8 +226,8 @@ func set_escoria_debug_settings(): } ) - escoria.register_setting( - "escoria/debug/log_file_path", + escoria.project_settings_manager.register_setting( + escoria.project_settings_manager.LOG_FILE_PATH, "user://", { "type": TYPE_STRING, @@ -234,8 +235,8 @@ func set_escoria_debug_settings(): } ) - escoria.register_setting( - "escoria/debug/crash_message", + escoria.project_settings_manager.register_setting( + escoria.project_settings_manager.LOG_FILE_PATH, "We're sorry, but the game crashed. Please send us the " + "following files:\n\n%s", { @@ -244,16 +245,16 @@ func set_escoria_debug_settings(): } ) - escoria.register_setting( - "escoria/debug/enable_room_selector", + escoria.project_settings_manager.register_setting( + escoria.project_settings_manager.ENABLE_ROOM_SELECTOR, false, { "type": TYPE_BOOL } ) - escoria.register_setting( - "escoria/debug/room_selector_room_dir", + escoria.project_settings_manager.register_setting( + escoria.project_settings_manager.ROOM_SELECTOR_ROOM_DIR, "", { "type": TYPE_STRING, @@ -264,8 +265,8 @@ func set_escoria_debug_settings(): # Prepare the settings in the Escoria sound settings func set_escoria_sound_settings(): - escoria.register_setting( - "escoria/sound/master_volume", + escoria.project_settings_manager.register_setting( + escoria.project_settings_manager.MASTER_VOLUME, 1, { "type": TYPE_REAL, @@ -274,8 +275,8 @@ func set_escoria_sound_settings(): } ) - escoria.register_setting( - "escoria/sound/music_volume", + escoria.project_settings_manager.register_setting( + escoria.project_settings_manager.MUSIC_VOLUME, 1, { "type": TYPE_REAL, @@ -284,8 +285,8 @@ func set_escoria_sound_settings(): } ) - escoria.register_setting( - "escoria/sound/sfx_volume", + escoria.project_settings_manager.register_setting( + escoria.project_settings_manager.SFX_VOLUME, 1, { "type": TYPE_REAL, @@ -294,8 +295,8 @@ func set_escoria_sound_settings(): } ) - escoria.register_setting( - "escoria/sound/speech_volume", + escoria.project_settings_manager.register_setting( + escoria.project_settings_manager.SPEECH_VOLUME, 1, { "type": TYPE_REAL, @@ -304,16 +305,16 @@ func set_escoria_sound_settings(): } ) - escoria.register_setting( - "escoria/sound/speech_enabled", + escoria.project_settings_manager.register_setting( + escoria.project_settings_manager.SPEECH_ENABLED, 1, { "type": TYPE_BOOL } ) - escoria.register_setting( - "escoria/sound/speech_folder", + escoria.project_settings_manager.register_setting( + escoria.project_settings_manager.SPEECH_FOLDER, "res://speech", { "type": TYPE_STRING, @@ -321,8 +322,8 @@ func set_escoria_sound_settings(): } ) - escoria.register_setting( - "escoria/sound/speech_extension", + escoria.project_settings_manager.register_setting( + escoria.project_settings_manager.SPEECH_EXTENSION, "ogg", { "type": TYPE_STRING @@ -337,19 +338,19 @@ func set_escoria_platform_settings(): # scenes. # If set to true, all generic scenes (UI, inventory, etc) will be loaded # as any other scene. - escoria.register_setting( - "escoria/platform/skip_cache", + escoria.project_settings_manager.register_setting( + escoria.project_settings_manager.SKIP_CACHE, false, { "type": TYPE_BOOL } ) - escoria.register_setting( - "escoria/platform/skip_cache.mobile", + escoria.project_settings_manager.register_setting( + escoria.project_settings_manager.SKIP_CACHE_MOBILE, true, { - "type": "TYPE_BOOL" + "type": TYPE_BOOL } ) @@ -358,5 +359,6 @@ func set_escoria_platform_settings(): func _exit_tree(): remove_autoload_singleton("escoria") - InputMap.erase_action("switch_action_verb") - InputMap.erase_action("esc_show_debug_prompt") + InputMap.erase_action(escoria.inputs_manager.SWITCH_ACTION_VERB) + InputMap.erase_action(escoria.inputs_manager.ESC_SHOW_DEBUG_PROMPT) + diff --git a/addons/escoria-dialog-simple/plugin.gd b/addons/escoria-dialog-simple/plugin.gd index 3370daee..d64dbd96 100644 --- a/addons/escoria-dialog-simple/plugin.gd +++ b/addons/escoria-dialog-simple/plugin.gd @@ -26,8 +26,8 @@ func _exit_tree() -> void: # Add ourselves to the list of dialog managers func _register(): _escoria.register_dialog_manager(MANAGER_CLASS) - _escoria.register_setting( - "escoria/dialog_simple/avatars_path", + _escoria.project_settings_manager.register_setting( + _escoria.project_settings_manager.AVATARS_PATH, "", { "type": TYPE_STRING, @@ -35,24 +35,24 @@ func _register(): } ) - _escoria.register_setting( - "escoria/dialog_simple/text_speed_per_character", + _escoria.project_settings_manager.register_setting( + _escoria.project_settings_manager.TEXT_SPEED_PER_CHARACTER, 0.1, { "type": TYPE_REAL } ) - _escoria.register_setting( - "escoria/dialog_simple/fast_text_speed_per_character", + _escoria.project_settings_manager.register_setting( + _escoria.project_settings_manager.FAST_TEXT_SPEED_PER_CHARACTER, 0.25, { "type": TYPE_REAL } ) - _escoria.register_setting( - "escoria/dialog_simple/max_time_to_disappear", + _escoria.project_settings_manager.register_setting( + _escoria.project_settings_manager.MAX_TIME_TO_DISAPPEAR, 1.0, { "type": TYPE_REAL diff --git a/addons/escoria-ui-9verbs/game.gd b/addons/escoria-ui-9verbs/game.gd index 82391463..a5680ade 100644 --- a/addons/escoria-ui-9verbs/game.gd +++ b/addons/escoria-ui-9verbs/game.gd @@ -1,5 +1,9 @@ extends ESCGame + +const VERB_USE = "use" + + """ Implement methods to react to inputs. @@ -64,8 +68,8 @@ func _enter_tree(): func left_click_on_bg(position: Vector2) -> void: if escoria.main.current_scene.player: - escoria.do( - "walk", + escoria.action_manager.do( + escoria.action_manager.ACTION.BACKGROUND_CLICK, [escoria.main.current_scene.player.global_id, position], true ) @@ -77,8 +81,8 @@ func left_click_on_bg(position: Vector2) -> void: func right_click_on_bg(position: Vector2) -> void: if escoria.main.current_scene.player: - escoria.do( - "walk", + escoria.action_manager.do( + escoria.action_manager.ACTION.BACKGROUND_CLICK, [escoria.main.current_scene.player.global_id, position], true ) @@ -90,8 +94,8 @@ func right_click_on_bg(position: Vector2) -> void: func left_double_click_on_bg(position: Vector2) -> void: if escoria.main.current_scene.player: - escoria.do( - "walk", + escoria.action_manager.do( + escoria.action_manager.ACTION.BACKGROUND_CLICK, [escoria.main.current_scene.player.global_id, position, true], true ) @@ -117,7 +121,7 @@ func element_focused(element_id: String) -> void: tooltip.set_target(target_obj.tooltip_name) # Hovering an ESCItem highlights its default action - if escoria.action_manager.current_action != "use" and target_obj is ESCItem: + if escoria.action_manager.current_action != VERB_USE and target_obj is ESCItem: verbs_menu.set_by_name(target_obj.default_action) ESCActionManager.ACTION_INPUT_STATE.AWAITING_TARGET_ITEM: @@ -145,7 +149,11 @@ func element_unfocused() -> void: ## ITEMS ## func left_click_on_item(item_global_id: String, event: InputEvent) -> void: - escoria.do("item_left_click", [item_global_id, event], true) + escoria.action_manager.do( + escoria.action_manager.ACTION.ITEM_LEFT_CLICK, + [item_global_id, event], + true + ) var target_obj = escoria.object_manager.get_object( item_global_id @@ -173,16 +181,27 @@ func left_click_on_item(item_global_id: String, event: InputEvent) -> void: func right_click_on_item(item_global_id: String, event: InputEvent) -> void: escoria.action_manager.set_current_action(verbs_menu.selected_action) - escoria.do("item_right_click", [item_global_id, event], true) + escoria.action_manager.do( + escoria.action_manager.ACTION.ITEM_RIGHT_CLICK, + [item_global_id, event], + true + ) func left_double_click_on_item(item_global_id: String, event: InputEvent) -> void: - escoria.do("item_left_click", [item_global_id, event], true) + escoria.action_manager.do( + escoria.action_manager.ACTION.ITEM_LEFT_CLICK, + [item_global_id, event], + true + ) ## INVENTORY ## func left_click_on_inventory_item(inventory_item_global_id: String, event: InputEvent) -> void: - escoria.do("item_left_click", [inventory_item_global_id, event]) + escoria.action_manager.do( + escoria.action_manager.ACTION.ITEM_LEFT_CLICK, + [inventory_item_global_id, event] + ) var target_obj = escoria.object_manager.get_object( inventory_item_global_id @@ -209,7 +228,10 @@ func left_click_on_inventory_item(inventory_item_global_id: String, event: Input func right_click_on_inventory_item(inventory_item_global_id: String, event: InputEvent) -> void: escoria.action_manager.set_current_action(verbs_menu.selected_action) - escoria.do("item_right_click", [inventory_item_global_id, event]) + escoria.action_manager.do( + escoria.action_manager.ACTION.ITEM_RIGHT_CLICK, + [inventory_item_global_id, event] + ) func left_double_click_on_inventory_item(_inventory_item_global_id: String, _event: InputEvent) -> void: @@ -234,7 +256,7 @@ func inventory_item_focused(inventory_item_global_id: String) -> void: tooltip.set_target(target_obj.tooltip_name) # Hovering an ESCItem highlights its default action - if escoria.action_manager.current_action != "use" and target_obj is ESCItem: + if escoria.action_manager.current_action != VERB_USE and target_obj is ESCItem: verbs_menu.set_by_name(target_obj.default_action) ESCActionManager.ACTION_INPUT_STATE.AWAITING_TARGET_ITEM: diff --git a/addons/escoria-ui-simplemouse/game.gd b/addons/escoria-ui-simplemouse/game.gd index 6e210335..12f574a7 100644 --- a/addons/escoria-ui-simplemouse/game.gd +++ b/addons/escoria-ui-simplemouse/game.gd @@ -1,5 +1,9 @@ extends ESCGame + +const VERB_WALK = "walk" + + """ Implement methods to react to inputs. @@ -61,12 +65,12 @@ func _input(event: InputEvent) -> void: func left_click_on_bg(position: Vector2) -> void: if escoria.main.current_scene.player: - escoria.do( - "walk", + escoria.action_manager.do( + escoria.action_manager.ACTION.BACKGROUND_CLICK, [escoria.main.current_scene.player.global_id, position], true ) - $mouse_layer/verbs_menu.set_by_name("walk") + $mouse_layer/verbs_menu.set_by_name(VERB_WALK) $mouse_layer/verbs_menu.clear_tool_texture() func right_click_on_bg(position: Vector2) -> void: @@ -74,12 +78,12 @@ func right_click_on_bg(position: Vector2) -> void: func left_double_click_on_bg(position: Vector2) -> void: if escoria.main.current_scene.player: - escoria.do( - "walk", + escoria.action_manager.do( + escoria.action_manager.ACTION.BACKGROUND_CLICK, [escoria.main.current_scene.player.global_id, position, true], true ) - $mouse_layer/verbs_menu.set_by_name("walk") + $mouse_layer/verbs_menu.set_by_name(VERB_WALK) $mouse_layer/verbs_menu.clear_tool_texture() ## ITEM/HOTSPOT FOCUS ## @@ -92,7 +96,7 @@ func element_focused(element_id: String) -> void: and escoria.action_manager.current_tool == null: if target_obj is ESCItem: $mouse_layer/verbs_menu.set_by_name( - target_obj.default_action + escoria.action_to_string(target_obj.default_action) ) func element_unfocused() -> void: @@ -102,18 +106,30 @@ func element_unfocused() -> void: ## ITEMS ## func left_click_on_item(item_global_id: String, event: InputEvent) -> void: - escoria.do("item_left_click", [item_global_id, event], true) + escoria.action_manager.do( + escoria.action_manager.ACTION.ITEM_LEFT_CLICK, + [item_global_id, event], + true + ) func right_click_on_item(item_global_id: String, event: InputEvent) -> void: mousewheel_action(1) func left_double_click_on_item(item_global_id: String, event: InputEvent) -> void: - escoria.do("item_left_click", [item_global_id, event], true) + escoria.action_manager.do( + escoria.action_manager.ACTION.ITEM_LEFT_CLICK, + [item_global_id, event], + true + ) ## INVENTORY ## func left_click_on_inventory_item(inventory_item_global_id: String, event: InputEvent) -> void: - escoria.do("item_left_click", [inventory_item_global_id, event]) + escoria.action_manager.do( + escoria.action_manager.ACTION.ITEM_LEFT_CLICK, + [inventory_item_global_id, event] + ) + if escoria.action_manager.current_action == "use": var item = escoria.object_manager.get_object( inventory_item_global_id diff --git a/game/rooms/room10/esc/button_accept_input_test.esc b/game/rooms/room10/esc/button_accept_input_test.esc index 77bcf61d..6468e4f0 100644 --- a/game/rooms/room10/esc/button_accept_input_test.esc +++ b/game/rooms/room10/esc/button_accept_input_test.esc @@ -4,7 +4,7 @@ say player "Hello. I will now walk a bit and won't listen at what you say!" #wait 1 accept_input NONE -walk_block player player_start +walk_block player r10_player_start walk_block player accept_input_location say player "Ha! Now you can't even skip this text!" avatar_dialog_player accept_input SKIP diff --git a/project.godot b/project.godot index fb9b2a9d..cfa8b478 100644 --- a/project.godot +++ b/project.godot @@ -294,11 +294,21 @@ _global_script_classes=[ { "language": "GDScript", "path": "res://addons/escoria-core/game/core-scripts/esc_player.gd" }, { +"base": "Node", +"class": "ESCProjectSettingsManager", +"language": "GDScript", +"path": "res://addons/escoria-core/game/project_settings_manager.gd" +}, { "base": "Object", "class": "ESCResourceCache", "language": "GDScript", "path": "res://addons/escoria-core/game/core-scripts/esc_resource_cache.gd" }, { +"base": "Object", +"class": "ESCResourceDescriptor", +"language": "GDScript", +"path": "res://addons/escoria-core/game/core-scripts/resources/esc_resource_descriptor.gd" +}, { "base": "Node2D", "class": "ESCRoom", "language": "GDScript", @@ -379,6 +389,11 @@ _global_script_classes=[ { "language": "GDScript", "path": "res://addons/escoria-core/game/core-scripts/esc/commands/enable_terrain.gd" }, { +"base": "Node", +"class": "Escoria", +"language": "GDScript", +"path": "res://addons/escoria-core/game/escoria.gd" +}, { "base": "ESCBaseCommand", "class": "HideMenuCommand", "language": "GDScript", @@ -612,7 +627,9 @@ _global_script_class_icons={ "ESCObject": "", "ESCObjectManager": "", "ESCPlayer": "res://addons/escoria-core/design/esc_player.svg", +"ESCProjectSettingsManager": "", "ESCResourceCache": "", +"ESCResourceDescriptor": "", "ESCRoom": "res://addons/escoria-core/design/esc_room.svg", "ESCRoomManager": "", "ESCSaveGame": "", @@ -629,6 +646,7 @@ _global_script_class_icons={ "ESCUtils": "", "ESCWalkContext": "", "EnableTerrainCommand": "", +"Escoria": "", "HideMenuCommand": "", "IncGlobalCommand": "", "InventoryAddCommand": "",