From ad79aa69d177ca13d57e40f2ef7fdbb500196305 Mon Sep 17 00:00:00 2001 From: Julian Murgia Date: Sun, 10 Jul 2022 20:40:08 +0200 Subject: [PATCH] Big refactor: Fix plugin issues when disabling/reenabling plugins (#598) Co-authored-by: balloonpopper <5151242+balloonpopper@users.noreply.github.com> Co-authored-by: Duncan Brown --- .../core-scripts/behaviors/esc_movable.gd | 71 +- .../core-scripts/esc/commands/accept_input.gd | 21 +- .../game/core-scripts/esc/commands/anim.gd | 17 +- .../core-scripts/esc/commands/anim_block.gd | 17 +- .../core-scripts/esc/commands/camera_push.gd | 37 +- .../esc/commands/camera_set_limits.gd | 18 +- .../esc/commands/camera_set_pos.gd | 8 +- .../esc/commands/camera_set_target.gd | 17 +- .../esc/commands/camera_set_zoom.gd | 8 +- .../esc/commands/camera_set_zoom_height.gd | 17 +- .../core-scripts/esc/commands/camera_shift.gd | 28 +- .../core-scripts/esc/commands/change_scene.gd | 44 +- .../game/core-scripts/esc/commands/custom.gd | 53 +- .../core-scripts/esc/commands/dec_global.gd | 9 +- .../esc/commands/enable_terrain.gd | 9 +- .../core-scripts/esc/commands/hide_menu.gd | 8 +- .../core-scripts/esc/commands/inc_global.gd | 18 +- .../esc/commands/inventory_add.gd | 9 +- .../core-scripts/esc/commands/play_snd.gd | 14 +- .../game/core-scripts/esc/commands/print.gd | 2 +- .../core-scripts/esc/commands/queue_event.gd | 32 +- .../esc/commands/queue_resource.gd | 7 +- .../game/core-scripts/esc/commands/say.gd | 41 +- .../core-scripts/esc/commands/sched_event.gd | 19 +- .../core-scripts/esc/commands/set_active.gd | 9 +- .../core-scripts/esc/commands/set_angle.gd | 10 +- .../esc/commands/set_animations.gd | 18 +- .../esc/commands/set_interactive.gd | 9 +- .../core-scripts/esc/commands/set_speed.gd | 9 +- .../core-scripts/esc/commands/set_state.gd | 9 +- .../core-scripts/esc/commands/show_menu.gd | 8 +- .../game/core-scripts/esc/commands/slide.gd | 24 +- .../game/core-scripts/esc/commands/spawn.gd | 36 +- .../core-scripts/esc/commands/stop_snd.gd | 7 +- .../core-scripts/esc/commands/teleport.gd | 18 +- .../core-scripts/esc/commands/teleport_pos.gd | 9 +- .../core-scripts/esc/commands/transition.gd | 37 +- .../game/core-scripts/esc/commands/turn_to.gd | 26 +- .../game/core-scripts/esc/commands/wait.gd | 10 +- .../game/core-scripts/esc/commands/walk.gd | 18 +- .../core-scripts/esc/commands/walk_block.gd | 18 +- .../core-scripts/esc/commands/walk_to_pos.gd | 9 +- .../esc/commands/walk_to_pos_block.gd | 9 +- .../core-scripts/esc/esc_action_manager.gd | 135 +-- .../core-scripts/esc/esc_command_registry.gd | 16 +- .../game/core-scripts/esc/esc_compiler.gd | 104 +-- .../core-scripts/esc/esc_event_manager.gd | 78 +- .../core-scripts/esc/esc_globals_manager.gd | 44 +- .../core-scripts/esc/esc_inventory_manager.gd | 11 +- .../core-scripts/esc/esc_object_manager.gd | 200 +++-- .../game/core-scripts/esc/esc_room_manager.gd | 74 +- .../esc/types/esc_base_command.gd | 17 +- .../core-scripts/esc/types/esc_command.gd | 44 +- .../types/esc_command_argument_descriptor.gd | 50 +- .../core-scripts/esc/types/esc_condition.gd | 35 +- .../game/core-scripts/esc/types/esc_dialog.gd | 32 +- .../esc/types/esc_dialog_option.gd | 13 +- .../game/core-scripts/esc/types/esc_event.gd | 18 +- .../core-scripts/esc/types/esc_execution.gd | 2 +- .../game/core-scripts/esc/types/esc_group.gd | 11 +- .../game/core-scripts/esc/types/esc_object.gd | 20 +- .../esc/types/esc_scheduled_event.gd | 2 +- .../game/core-scripts/esc/types/esc_script.gd | 2 +- .../core-scripts/esc/types/esc_statement.gd | 20 +- .../game/core-scripts/esc_game.gd | 36 +- .../game/core-scripts/esc_item.gd | 23 +- .../game/core-scripts/esc_resource_cache.gd | 4 +- .../game/core-scripts/esc_room.gd | 9 +- .../game/core-scripts/esc_terrain.gd | 20 +- .../game/core-scripts/esc_tooltip.gd | 1 + .../game/core-scripts/esc_walk_context.gd | 2 +- .../game/core-scripts/log/esc_logger.gd | 325 ------- .../core-scripts/migrations/esc_migration.gd | 2 +- .../migrations/esc_migration_manager.gd | 47 +- .../core-scripts/plugins/escoria_plugin.gd | 102 +++ .../resources/esc_resource_descriptor.gd | 2 +- .../save_data/esc_save_manager.gd | 97 ++- .../game/core-scripts/utils/esc_utils.gd | 10 +- addons/escoria-core/game/esc_autoload.gd | 195 +++++ ...nputs_manager.gd => esc_inputs_manager.gd} | 57 +- addons/escoria-core/game/esc_logger.gd | 195 +++++ ...ger.gd => esc_project_settings_manager.gd} | 28 +- addons/escoria-core/game/escoria.gd | 400 ++------- addons/escoria-core/game/escoria.tscn | 2 +- addons/escoria-core/game/main.gd | 38 +- addons/escoria-core/game/main.tscn | 2 - addons/escoria-core/game/main_scene.gd | 12 +- .../game/scenes/camera_player/esc_camera.gd | 70 +- .../scenes/camera_player/esc_camera_limits.gd | 2 +- .../dialogs/esc_dialog_options_chooser.gd | 10 +- .../game/scenes/dialogs/esc_dialog_player.gd | 68 +- .../game/scenes/inventory/inventory_ui.gd | 46 +- .../game/scenes/sound/esc_music_player.gd | 6 +- .../game/scenes/sound/esc_sound_player.gd | 6 +- .../transitions/esc_transition_player.gd | 16 +- addons/escoria-core/plugin.gd | 247 +++--- .../inventory/esc_inventory_container.gd | 13 + .../ui_library/menus/options/options.gd | 2 +- .../tools/room_select/room_select.gd | 14 +- addons/escoria-dialog-simple/plugin.gd | 124 ++- addons/escoria-ui-9verbs/game.gd | 26 +- addons/escoria-ui-9verbs/plugin.gd | 20 +- addons/escoria-ui-keyboard-9verbs/plugin.gd | 22 +- addons/escoria-ui-simplemouse/game.gd | 9 +- addons/escoria-ui-simplemouse/plugin.gd | 21 +- escoria.godot | 821 ++++++++++++++++++ .../dialog_avatars/mark_talk_down_right_2.png | Bin 7318 -> 10564 bytes .../dialog_avatars/mark_talk_down_right_3.png | Bin 7032 -> 10566 bytes game/dialog_avatars/player.tres | 1 - game/rooms/intro/intro_room.tscn | 2 - game/rooms/room12/room12.tscn | 2 +- icon.png.import | 1 + project.godot | 146 ++-- 113 files changed, 2977 insertions(+), 2072 deletions(-) delete mode 100644 addons/escoria-core/game/core-scripts/log/esc_logger.gd create mode 100644 addons/escoria-core/game/core-scripts/plugins/escoria_plugin.gd create mode 100644 addons/escoria-core/game/esc_autoload.gd rename addons/escoria-core/game/{inputs_manager.gd => esc_inputs_manager.gd} (89%) create mode 100644 addons/escoria-core/game/esc_logger.gd rename addons/escoria-core/game/{project_settings_manager.gd => esc_project_settings_manager.gd} (91%) create mode 100644 escoria.godot 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 77190873..a9ee7765 100644 --- a/addons/escoria-core/game/core-scripts/behaviors/esc_movable.gd +++ b/addons/escoria-core/game/core-scripts/behaviors/esc_movable.gd @@ -142,7 +142,7 @@ func _calculate_movement(delta: float): # # - angle: the angle X axis and object's facing direction. func _perform_walk_orientation(angle: float): - last_dir = _get_dir_deg(escoria.utils.get_deg_from_rad(angle), + last_dir = _get_dir_deg(ESCUtils.get_deg_from_rad(angle), parent.animations) var animation_player: ESCAnimationPlayer = \ @@ -158,15 +158,10 @@ func _perform_walk_orientation(angle: float): elif current_animation != animation_to_play and \ not animation_player.has_animation(animation_to_play): current_animation = animation_to_play - escoria.logger.report_warnings( - "movable.gd:_process()", - [ - "Character %s has no animation %s " - % [parent.global_id, animation_to_play], - "Bypassing missing animation and " + - "proceed movement." - ], - true + escoria.logger.warn( + self, + "Character %s has no animation %s\nBypassing the missing animation and movement command." + % [parent.global_id, animation_to_play] ) is_mirrored = parent.animations.directions[last_dir].mirrored @@ -181,21 +176,21 @@ func teleport(target: Node) -> void: if target.has_method("get_interact_position"): parent.global_position = target.get_interact_position() escoria.logger.info( - "Object %s is teleported at position %s" % [ - target.name, - parent.global_position - ] + self, + "Object %s is teleported to position %s." + % [target.name, parent.global_position] ) elif "position" in target: escoria.logger.info( - "Object %s teleported at position %s" % - [parent.global_id, str(target.global_position)] + self, + "Object %s teleported to position %s." + % [parent.global_id, str(target.global_position)] ) parent.global_position = target.global_position else: - escoria.logger.report_errors( - "ESCMovable#teleport()", - ["Couldn't understand how to manage teleport Target %s" % target] + escoria.logger.error( + self, + "Target %s could not be teleported. Please configure the interact position parameter or create a child ESCLocation node." % target ) @@ -206,8 +201,9 @@ func teleport(target: Node) -> void: # - target: Vector2 target position to teleport to func teleport_to(target: Vector2) -> void: escoria.logger.info( - "Object %s teleported to position %s" % - [parent.global_id, str(target)] + self, + "Object %s teleported to position %s." + % [parent.global_id, str(target)] ) parent.global_position = target @@ -287,14 +283,16 @@ func walk_stop(pos: Vector2) -> void: if walk_context.target_object: escoria.logger.debug( - "%s arrived at %s" % [ + self, + "%s arrived at %s." % [ parent.global_id, walk_context.target_object.global_id ] ) else: escoria.logger.debug( - "%s arrived at %s" % [ + self, + "%s arrived at %s." % [ parent.global_id, walk_context.target_position ] @@ -311,7 +309,8 @@ 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 != escoria.event_manager.EVENT_SETUP: + if on_event_finished_name != null \ + and on_event_finished_name != ESCEventManager.EVENT_SETUP: return if parent.get("is_exit"): return @@ -376,9 +375,9 @@ func _get_dir_deg(deg: int, animations: ESCAnimationResource) -> int: # It's an error to have the animations misconfigured if dir == -1: - escoria.logger.report_errors( - "esc_movable.gd:_get_dir_deg()", - ["No direction found for " + str(deg)] + escoria.logger.error( + self, + "No animation has been configured for angle %s." + str(deg) ) return dir @@ -414,9 +413,9 @@ func _is_angle_in_interval( # - wait float Wait this amount of seconds until continuing with turning around func set_angle(deg: int, wait: float = 0.0) -> void: if deg < 0 or deg > 360: - escoria.logger.report_errors( - "movable.gd:set_angle()", - ["Invalid degree to turn to " + str(deg)] + escoria.logger.error( + self, + "Invalid degree to turn to : %s. Valid angles are between 0 and 360." % str(deg) ) moved = true @@ -490,15 +489,15 @@ func _get_angle() -> int: # Integer: -1 (anti-clockwise), 1 (clockwise) or 0 (no movement needed). func get_shortest_way_to_dir(current_dir: int, target_dir: int) -> int: if current_dir < 0 or current_dir > parent.animations.dir_angles.size() - 1: - escoria.logger.report_errors( - "esc_movable.gd:get_shortest_way_to_dir()", - ["Invalid direction (current_dir) %s" % str(current_dir)] + escoria.logger.error( + self, + "Invalid direction (current_dir) %s" % str(current_dir) ) if target_dir < 0 or target_dir > parent.animations.dir_angles.size() - 1: - escoria.logger.report_errors( - "esc_movable.gd:get_shortest_way_to_dir()", - ["Invalid direction (target_dir) %s " % str(target_dir)] + escoria.logger.error( + self, + "Invalid direction (target_dir) %s " % str(target_dir) ) if current_dir == target_dir: diff --git a/addons/escoria-core/game/core-scripts/esc/commands/accept_input.gd b/addons/escoria-core/game/core-scripts/esc/commands/accept_input.gd index 46c20b1c..360d5e10 100644 --- a/addons/escoria-core/game/core-scripts/esc/commands/accept_input.gd +++ b/addons/escoria-core/game/core-scripts/esc/commands/accept_input.gd @@ -22,6 +22,10 @@ extends ESCBaseCommand class_name AcceptInputCommand +# The list of supported input types +const SUPPORTED_INPUT_TYPES = ["ALL", "NONE", "SKIP"] + + # Return the descriptor of the arguments of this command func configure() -> ESCCommandArgumentDescriptor: return ESCCommandArgumentDescriptor.new( @@ -36,13 +40,16 @@ func validate(arguments: Array): if not .validate(arguments): return false - if not arguments[0] in ["ALL", "NONE", "SKIP"]: - escoria.logger.report_errors( - "accept_input: invalid parameter", - [ - "%s is not a valid parameter value (ALL, NONE, SKIP)" %\ - arguments[0] - ] + if not arguments[0] in SUPPORTED_INPUT_TYPES: + escoria.logger.error( + self, + "[%s]: invalid parameter. %s is not a valid parameter value." + + "Should be one of %s" + % [ + get_command_name(), + arguments[0], + str(SUPPORTED_INPUT_TYPES) + ] ) return false return true diff --git a/addons/escoria-core/game/core-scripts/esc/commands/anim.gd b/addons/escoria-core/game/core-scripts/esc/commands/anim.gd index 0d3ca5e7..c58cd004 100644 --- a/addons/escoria-core/game/core-scripts/esc/commands/anim.gd +++ b/addons/escoria-core/game/core-scripts/esc/commands/anim.gd @@ -30,11 +30,10 @@ func validate(arguments: Array): return false if not escoria.object_manager.has(arguments[0]): - escoria.logger.report_errors( - "anim: invalid object", - [ - "Object with global id %s not found." % arguments[0] - ] + escoria.logger.error( + self, + "[%s]: invalid object. Object with global id %s not found." + % [get_command_name(), arguments[0]] ) return false return true @@ -56,9 +55,7 @@ func run(command_params: Array) -> int: # Function called when the command is interrupted. func interrupt(): - escoria.logger.report_warnings( - get_command_name(), - [ - "Interrupt() function not implemented" - ] + escoria.logger.warn( + self, + "[%s] interrupt() function not implemented." % get_command_name() ) diff --git a/addons/escoria-core/game/core-scripts/esc/commands/anim_block.gd b/addons/escoria-core/game/core-scripts/esc/commands/anim_block.gd index eab773e4..34c243c8 100644 --- a/addons/escoria-core/game/core-scripts/esc/commands/anim_block.gd +++ b/addons/escoria-core/game/core-scripts/esc/commands/anim_block.gd @@ -31,11 +31,10 @@ func validate(arguments: Array): return false if not escoria.object_manager.has(arguments[0]): - escoria.logger.report_errors( - "anim_block.gd:validate", - [ - "Object with global id %s not found." % arguments[0] - ] + escoria.logger.error( + self, + "[%s]: Object with global id %s not found." + % [get_command_name(), arguments[0]] ) return false return true @@ -62,9 +61,7 @@ func run(command_params: Array) -> int: # Function called when the command is interrupted. func interrupt(): - escoria.logger.report_warnings( - get_command_name(), - [ - "Interrupt() function not implemented" - ] + escoria.logger.warn( + self, + "[%s] interrupt() function not implemented." % get_command_name() ) 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 b5ada507..1e18f0d8 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 @@ -48,20 +48,25 @@ func validate(arguments: Array): return false if not escoria.object_manager.has(arguments[0]): - escoria.logger.report_errors( - "camera_push: invalid object", - [ - "Object global id %s not found" % arguments[0] - ] + escoria.logger.error( + self, + "[%s]: invalid object. Object global id %s not found." + % [get_command_name(), arguments[0]] ) return false if not arguments[2] in SUPPORTED_TRANSITIONS: - escoria.logger.report_errors( - "camera_shift: invalid transition type", - [ - "Transition type {t_type} is not one of the accepted types : {allowed_types}".format( - {"t_type":arguments[2],"allowed_types":SUPPORTED_TRANSITIONS}) - ] + escoria.logger.error( + self, + ( + "[{command_name}]: invalid transition type. Transition type {t_type} " + + "is not one of the accepted types : {allowed_types}" + ).format( + { + "command_name":get_command_name(), + "t_type":arguments[2], + "allowed_types":SUPPORTED_TRANSITIONS + } + ) ) return false @@ -74,16 +79,14 @@ func run(command_params: Array) -> int: .push( escoria.object_manager.get_object(command_params[0]).node, command_params[1], - Tween.new().get("TRANS_%s" % command_params[2]) + ClassDB.class_get_integer_constant("Tween", "TRANS_%s" % command_params[2]) ) return ESCExecution.RC_OK # Function called when the command is interrupted. func interrupt(): - escoria.logger.report_warnings( - get_command_name(), - [ - "Interrupt() function not implemented" - ] + escoria.logger.warn( + self, + "[%s] interrupt() function not implemented." % get_command_name() ) diff --git a/addons/escoria-core/game/core-scripts/esc/commands/camera_set_limits.gd b/addons/escoria-core/game/core-scripts/esc/commands/camera_set_limits.gd index e7588f14..e65a3dbb 100644 --- a/addons/escoria-core/game/core-scripts/esc/commands/camera_set_limits.gd +++ b/addons/escoria-core/game/core-scripts/esc/commands/camera_set_limits.gd @@ -33,14 +33,14 @@ func validate(arguments: Array): return false if escoria.main.current_scene.camera_limits.size() < arguments[0]: - escoria.logger.report_errors( - "camera_set_limits: invalid limits id", - [ - "Limit id %d is bigger than limits array size %d" % [ + escoria.logger.error( + self, + "[%s]: invalid limits id. Camera limit id (%d) is larger than the number of limits defined in this scene (%d)." + % [ + get_command_name(), arguments[0], escoria.main.current_scene.camera_limits.size() ] - ] ) return false @@ -55,9 +55,7 @@ func run(command_params: Array) -> int: # Function called when the command is interrupted. func interrupt(): - escoria.logger.report_warnings( - get_command_name(), - [ - "Interrupt() function not implemented" - ] + escoria.logger.warn( + self, + "[%s] interrupt() function not implemented." % get_command_name() ) 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 e7c902e2..dca9f53a 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 @@ -36,9 +36,7 @@ func run(command_params: Array) -> int: # Function called when the command is interrupted. func interrupt(): - escoria.logger.report_warnings( - get_command_name(), - [ - "Interrupt() function not implemented" - ] + escoria.logger.warn( + self, + "[%s] interrupt() function not implemented." % get_command_name() ) 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 15f7d985..4932e1e6 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 @@ -32,11 +32,10 @@ func validate(arguments: Array): return false if not escoria.object_manager.has(arguments[1]): - escoria.logger.report_errors( - "camera_set_target: invalid object", - [ - "Object with global id %s not found" % arguments[1] - ] + escoria.logger.error( + self, + "[%s]: Invalid object: Object with global id %s not found." + % [get_command_name(), arguments[1]] ) return false @@ -55,9 +54,7 @@ func run(command_params: Array) -> int: # Function called when the command is interrupted. func interrupt(): - escoria.logger.report_warnings( - get_command_name(), - [ - "Interrupt() function not implemented" - ] + escoria.logger.warn( + self, + "[%s] interrupt() function not implemented." % get_command_name() ) 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 419f68d0..8afe72ee 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 @@ -40,9 +40,7 @@ func run(command_params: Array) -> int: # Function called when the command is interrupted. func interrupt(): - escoria.logger.report_warnings( - get_command_name(), - [ - "Interrupt() function not implemented" - ] + escoria.logger.warn( + self, + "[%s] interrupt() function not implemented." % get_command_name() ) 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 c7e1d1d2..2ad02a8b 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 @@ -30,11 +30,10 @@ func validate(arguments: Array): return false if arguments[0] < 0: - escoria.logger.report_errors( - "camera_set_zoom_height: invalid height", - [ - "Can't zoom to a negative height %d" % arguments[0] - ] + escoria.logger.error( + self, + "[%s]: invalid height. Can't zoom to a negative height (%d)." + % [get_command_name(), arguments[0]] ) return false @@ -53,9 +52,7 @@ func run(command_params: Array) -> int: # Function called when the command is interrupted. func interrupt(): - escoria.logger.report_warnings( - get_command_name(), - [ - "Interrupt() function not implemented" - ] + escoria.logger.warn( + self, + "[%s] interrupt() function not implemented." % get_command_name() ) 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 45f51f88..de49d1d9 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 @@ -49,7 +49,7 @@ func run(command_params: Array) -> int: command_params[1] ), command_params[2], - Tween.new().get("TRANS_%s" % command_params[3]) + ClassDB.class_get_integer_constant("Tween", "TRANS_%s" % command_params[3]) ) return ESCExecution.RC_OK @@ -59,12 +59,18 @@ func validate(arguments: Array): return false if not arguments[3] in SUPPORTED_TRANSITIONS: - escoria.logger.report_errors( - "camera_shift: invalid transition type", - [ - "Transition type {t_type} is not one of the accepted types : {allowed_types}".format( - {"t_type":arguments[3],"allowed_types":SUPPORTED_TRANSITIONS}) - ] + escoria.logger.error( + self, + ( + "[{command_name}]: invalid transition type" + + "Transition type {t_type} is not one of the accepted types : {allowed_types}" + ).format( + { + "command_name": get_command_name(), + "t_type":arguments[3], + "allowed_types":SUPPORTED_TRANSITIONS + } + ) ) return false @@ -73,9 +79,7 @@ func validate(arguments: Array): # Function called when the command is interrupted. func interrupt(): - escoria.logger.report_warnings( - get_command_name(), - [ - "Interrupt() function not implemented" - ] + escoria.logger.warn( + self, + "[%s] interrupt() function not implemented." % get_command_name() ) 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 6978aa78..ba0d98f7 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 @@ -31,22 +31,24 @@ func validate(arguments: Array) -> bool: return false if not ResourceLoader.exists(arguments[0]): - escoria.logger.report_errors( - "change_scene: Invalid scene", - ["Scene %s was not found" % arguments[0]] + escoria.logger.error( + self, + "[%s]: Invalid scene. Scene %s was not found." + % [get_command_name(), arguments[0]] ) return false if not ResourceLoader.exists( - escoria.project_settings_manager.get_setting(escoria.project_settings_manager.GAME_SCENE) + ESCProjectSettingsManager.get_setting(ESCProjectSettingsManager.GAME_SCENE) ): - escoria.logger.report_errors( - "change_scene: Game scene not found", - [ - "The path set in 'ui/game_scene' was not found: %s" % \ - escoria.project_settings_manager.get_setting( - escoria.project_settings_manager.GAME_SCENE + escoria.logger.error( + self, + "[%s]: Game scene not found. The path set in 'ui/game_scene' was not found: %s." + % [ + get_command_name(), + ESCProjectSettingsManager.get_setting( + ESCProjectSettingsManager.GAME_SCENE ) - ] + ] ) return false @@ -56,10 +58,14 @@ func validate(arguments: Array) -> bool: # Run the command func run(command_params: Array) -> int: escoria.logger.info( - "Changing scene to %s (enable_automatic_transition = %s)" % [ - command_params[0], # scene file - command_params[1] # enable_automatic_transition - ]) + self, + "[%s] Changing scene to %s (enable_automatic_transition = %s)." + % [ + get_command_name(), + command_params[0], # scene file + command_params[1] # enable_automatic_transition + ] + ) escoria.room_manager.change_scene(command_params[0], command_params[1]) @@ -68,9 +74,7 @@ func run(command_params: Array) -> int: # Function called when the command is interrupted. func interrupt(): - escoria.logger.report_warnings( - get_command_name(), - [ - "Interrupt() function not implemented" - ] + escoria.logger.warn( + self, + "[%s] interrupt() function not implemented." % get_command_name() ) diff --git a/addons/escoria-core/game/core-scripts/esc/commands/custom.gd b/addons/escoria-core/game/core-scripts/esc/commands/custom.gd index fbafde4a..fbd01313 100644 --- a/addons/escoria-core/game/core-scripts/esc/commands/custom.gd +++ b/addons/escoria-core/game/core-scripts/esc/commands/custom.gd @@ -35,24 +35,23 @@ func validate(arguments: Array): return false if not escoria.object_manager.has(arguments[0]): - escoria.logger.report_errors( - "custom: invalid object", - [ - "Object with global id %s not found" % arguments[0] - ] + escoria.logger.error( + self, + "[%s]: invalid object. Object with global id %s not found." + % [get_command_name(), arguments[0]] ) return false elif not escoria.object_manager.get_object(arguments[0]).node.has_node( arguments[1] ): - escoria.logger.report_errors( - "custom: invalid node", - [ - "Object with global id %s has no node %s" % [ - arguments[0], - arguments[1], - ] - ] + escoria.logger.error( + self, + "[%s]: invalid node. Object with global id %s has no child node called %s." + % [ + get_command_name(), + arguments[0], + arguments[1], + ] ) return false elif not escoria.object_manager.get_object(arguments[0]).node\ @@ -62,15 +61,15 @@ func validate(arguments: Array): .has_method( arguments[2] ): - escoria.logger.report_errors( - "custom: invalid function", - [ - "Object with global id %s and node %s has no function %s" % [ - arguments[0], - arguments[1], - arguments[2], - ] - ] + escoria.logger.error( + self, + "[%s]: invalid function. Object with global id %s and node %s has no function called %s." + % [ + get_command_name(), + arguments[0], + arguments[1], + arguments[2], + ] ) return false return true @@ -84,7 +83,7 @@ func run(command_params: Array) -> int: # Global variables can be substituted into the command arguments by wrapping the global # name in braces. for loop in command_params[3].size(): - command_params[3][loop] = escoria.esc_compiler.replace_globals(command_params[3][loop]) + command_params[3][loop] = escoria.globals_manager.replace_globals(command_params[3][loop]) object.node.get_node(command_params[1]).call( command_params[2], @@ -95,9 +94,7 @@ func run(command_params: Array) -> int: # Function called when the command is interrupted. func interrupt(): - escoria.logger.report_warnings( - get_command_name(), - [ - "Interrupt() function not implemented" - ] + escoria.logger.warn( + self, + "[%s] interrupt() function not implemented." % get_command_name() ) diff --git a/addons/escoria-core/game/core-scripts/esc/commands/dec_global.gd b/addons/escoria-core/game/core-scripts/esc/commands/dec_global.gd index 07dc2633..89da8505 100644 --- a/addons/escoria-core/game/core-scripts/esc/commands/dec_global.gd +++ b/addons/escoria-core/game/core-scripts/esc/commands/dec_global.gd @@ -27,11 +27,10 @@ func validate(arguments: Array): return false if not escoria.globals_manager.get_global(arguments[0]) is int: - escoria.logger.report_errors( - "dec_global: invalid global", - [ - "Global %s didn't have an integer value." % arguments[0] - ] + escoria.logger.error( + self, + "[%s]: invalid global. Global %s isn't an integer value." + % [get_command_name(), arguments[0]] ) return false return true diff --git a/addons/escoria-core/game/core-scripts/esc/commands/enable_terrain.gd b/addons/escoria-core/game/core-scripts/esc/commands/enable_terrain.gd index 2b4fc227..742afa65 100644 --- a/addons/escoria-core/game/core-scripts/esc/commands/enable_terrain.gd +++ b/addons/escoria-core/game/core-scripts/esc/commands/enable_terrain.gd @@ -36,11 +36,10 @@ func run(command_params: Array) -> int: escoria.room_terrain.current_active_navigation_instance.enabled = true return ESCExecution.RC_OK else: - escoria.logger.report_errors( - "EnableTerrainCommand.run: Can not find terrain node", - [ - "Terrain node %s could not be found" % name - ] + escoria.logger.error( + self, + "[%s]: Can not find terrain node. Terrain node %s could not be found." + % [get_command_name(), name] ) return ESCExecution.RC_ERROR diff --git a/addons/escoria-core/game/core-scripts/esc/commands/hide_menu.gd b/addons/escoria-core/game/core-scripts/esc/commands/hide_menu.gd index eea480e2..8e057dc9 100644 --- a/addons/escoria-core/game/core-scripts/esc/commands/hide_menu.gd +++ b/addons/escoria-core/game/core-scripts/esc/commands/hide_menu.gd @@ -34,11 +34,9 @@ func validate(arguments: Array): return false if not arguments[0] in ["main", "pause"]: - escoria.logger.report_errors( - "hide_menu: invalid menu ", - [ - "menu %s is invalid" % arguments[0] - ] + escoria.logger.error( + self, + "[%s]: menu %s is invalid." % [get_command_name(), arguments[0]] ) return false return true diff --git a/addons/escoria-core/game/core-scripts/esc/commands/inc_global.gd b/addons/escoria-core/game/core-scripts/esc/commands/inc_global.gd index a3660b16..d1778e0a 100644 --- a/addons/escoria-core/game/core-scripts/esc/commands/inc_global.gd +++ b/addons/escoria-core/game/core-scripts/esc/commands/inc_global.gd @@ -27,19 +27,17 @@ func validate(arguments: Array): return false if not escoria.globals_manager.has(arguments[0]): - escoria.logger.report_errors( - "inc_global: invalid global", - [ - "Global %s does not exist." % arguments[0] - ] + escoria.logger.error( + self, + "[%s]: invalid global. Global %s does not exist." + % [get_command_name(), arguments[0]] ) return false if not escoria.globals_manager.get_global(arguments[0]) is int: - escoria.logger.report_errors( - "inc_global: invalid global", - [ - "Global %s didn't have an integer value." % arguments[0] - ] + escoria.logger.error( + self, + "[%s]: invalid global. Global %s isn't an integer value." + % [get_command_name(), arguments[0]] ) return false return true diff --git a/addons/escoria-core/game/core-scripts/esc/commands/inventory_add.gd b/addons/escoria-core/game/core-scripts/esc/commands/inventory_add.gd index e31d13bc..64cc1957 100644 --- a/addons/escoria-core/game/core-scripts/esc/commands/inventory_add.gd +++ b/addons/escoria-core/game/core-scripts/esc/commands/inventory_add.gd @@ -28,11 +28,10 @@ func validate(arguments: Array): return false if arguments[0].begins_with("i/"): - escoria.logger.report_errors( - "inventory_add: invalid item name", - [ - "Item name %s cannot start with 'i/'." % arguments[0] - ] + escoria.logger.error( + self, + "[%s]: invalid item name. Item name %s cannot start with 'i/'." + % [get_command_name(), arguments[0]] ) return false return true diff --git a/addons/escoria-core/game/core-scripts/esc/commands/play_snd.gd b/addons/escoria-core/game/core-scripts/esc/commands/play_snd.gd index 81d1aa37..7a16deae 100644 --- a/addons/escoria-core/game/core-scripts/esc/commands/play_snd.gd +++ b/addons/escoria-core/game/core-scripts/esc/commands/play_snd.gd @@ -33,15 +33,17 @@ func validate(arguments: Array): return false if not escoria.object_manager.has(arguments[1]): - escoria.logger.report_errors( - "play_snd: invalid sound player", - ["Sound player %s not registered" % arguments[1]] + escoria.logger.error( + self, + "[%s]: invalid sound player. Sound player %s not registered." + % [get_command_name(), arguments[1]] ) return false if not ResourceLoader.exists(arguments[0]): - escoria.logger.report_errors( - "play_snd: invalid parameter", - ["File %s not found" % arguments[0]] + escoria.logger.error( + self, + "[%s]: invalid parameter. File %s not found." + % [get_command_name(), arguments[0]] ) return false _snd_player = arguments[1] diff --git a/addons/escoria-core/game/core-scripts/esc/commands/print.gd b/addons/escoria-core/game/core-scripts/esc/commands/print.gd index 3c6403c5..3c14a03a 100644 --- a/addons/escoria-core/game/core-scripts/esc/commands/print.gd +++ b/addons/escoria-core/game/core-scripts/esc/commands/print.gd @@ -24,7 +24,7 @@ func configure() -> ESCCommandArgumentDescriptor: # Run the command func run(command_params: Array) -> int: # Replace the names of any globals in "{ }" with their value - print(escoria.esc_compiler.replace_globals(command_params[0])) + print(escoria.globals_manager.replace_globals(command_params[0])) return ESCExecution.RC_OK 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 08511376..2fc1cfd9 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 @@ -31,39 +31,31 @@ func validate(arguments: Array): return false if not escoria.object_manager.has(arguments[0]): - escoria.logger.report_errors( - "queue_event.gd:validate", - [ - "Object with global id %s not found" % arguments[0] - ] + escoria.logger.error( + self, + "Object with global id %s not found." % arguments[0] ) return false var node = escoria.object_manager.get_object( arguments[0] ).node if not "esc_script" in node or node.esc_script == "": - escoria.logger.report_errors( - "queue_event.gd:validate", - [ - "Object with global id %s has no ESC script" % arguments[0] - ] + escoria.logger.error( + self, + "Object with global id %s has no ESC script." % arguments[0] ) return false var esc_script = escoria.esc_compiler.load_esc_file(node.esc_script) if not arguments[1] in esc_script.events: - escoria.logger.report_errors( - "queue_event.gd:validate", - [ - "Event with name %s not found" % arguments[1] - ] + escoria.logger.error( + self, + "Event with name %s not found." % arguments[1] ) return false if arguments[3] and not escoria.event_manager.is_channel_free(arguments[2]): - escoria.logger.report_errors( - "queue_event.gd:validate", - [ - "The queue %s doesn't accept a new event." % arguments[2] - ] + escoria.logger.error( + self, + "The queue %s doesn't accept a new event." % arguments[2] ) return false return true diff --git a/addons/escoria-core/game/core-scripts/esc/commands/queue_resource.gd b/addons/escoria-core/game/core-scripts/esc/commands/queue_resource.gd index b9dc594d..df2ba527 100644 --- a/addons/escoria-core/game/core-scripts/esc/commands/queue_resource.gd +++ b/addons/escoria-core/game/core-scripts/esc/commands/queue_resource.gd @@ -28,9 +28,10 @@ func validate(arguments: Array) -> bool: return false if not ResourceLoader.exists(arguments[0]): - escoria.logger.report_errors( - "queue_resource: Invalid resource", - ["Resource %s was not found" % arguments[0]] + escoria.logger.error( + self, + "[%s]: Invalid resource. Resource %s was not found." + % [get_command_name(), arguments[0]] ) return false return true diff --git a/addons/escoria-core/game/core-scripts/esc/commands/say.gd b/addons/escoria-core/game/core-scripts/esc/commands/say.gd index 04ef1c9f..0c9d472d 100644 --- a/addons/escoria-core/game/core-scripts/esc/commands/say.gd +++ b/addons/escoria-core/game/core-scripts/esc/commands/say.gd @@ -64,21 +64,18 @@ func validate(arguments: Array): return false if not escoria.object_manager.has(arguments[0]): - escoria.logger.report_errors( - "anim: invalid object", - [ - "Object with global id %s not found." % arguments[0] - ] + escoria.logger.error( + self, + "[%s]: Invalid object: Object with global id %s not found." + % [get_command_name(), arguments[0]] ) return false - if ProjectSettings.get_setting("escoria/ui/default_dialog_type") == "" \ + if ESCProjectSettingsManager.get_setting(ESCProjectSettingsManager.DEFAULT_DIALOG_TYPE) == "" \ and arguments[2] == "": - escoria.logger.report_errors( - "say()", - [ - "Project setting 'escoria/ui/default_dialog_type' is not set.", - "Please set a default dialog type." - ] + escoria.logger.error( + self, + "[%s]: Project setting '%s' is not set. Please set a default dialog type." + % [get_command_name(), ESCProjectSettingsManager.DEFAULT_DIALOG_TYPE] ) return true @@ -91,17 +88,15 @@ func run(command_params: Array) -> int: escoria.current_state = escoria.GAME_STATE.DIALOG if !escoria.dialog_player: - escoria.logger.report_errors( - "No dialog player registered", - [ - "No dialog player was registered and the say command was" + - "encountered." - ] + escoria.logger.error( + self, + "[%s]: No dialog player was registered and the say command was encountered." + % get_command_name() ) return ESCExecution.RC_ERROR # Replace the names of any globals in "{ }" with their value - command_params[1] = escoria.esc_compiler.replace_globals(command_params[1]) + command_params[1] = escoria.globals_manager.replace_globals(command_params[1]) escoria.dialog_player.say( command_params[0], @@ -115,9 +110,7 @@ func run(command_params: Array) -> int: # Function called when the command is interrupted. func interrupt(): - escoria.logger.report_warnings( - "say", - [ - "Interrupt() function not implemented" - ] + escoria.logger.warn( + self, + "[%s] interrupt() function not implemented." % get_command_name() ) diff --git a/addons/escoria-core/game/core-scripts/esc/commands/sched_event.gd b/addons/escoria-core/game/core-scripts/esc/commands/sched_event.gd index 1847c65e..b8dcf963 100644 --- a/addons/escoria-core/game/core-scripts/esc/commands/sched_event.gd +++ b/addons/escoria-core/game/core-scripts/esc/commands/sched_event.gd @@ -32,23 +32,22 @@ func validate(arguments: Array): return false if not escoria.object_manager.has(arguments[1]): - escoria.logger.report_errors( - "sched_event: invalid object", - [ - "Object with global id %s not found" % arguments[1] - ] + escoria.logger.error( + self, + "[%s]: invalid object. Object with global id %s not found." + % [get_command_name(), arguments[1]] ) return false elif not escoria.object_manager.get_object(arguments[1]).events\ .has(arguments[2]): - escoria.logger.report_errors( - "sched_event: invalid object event", - [ - "Object with global id %s has no event %s" % [ + escoria.logger.error( + self, + "[%s]: invalid object event. Object with global id %s has no event %s." + % [ + get_command_name(), arguments[1], arguments[2], ] - ] ) return false return true diff --git a/addons/escoria-core/game/core-scripts/esc/commands/set_active.gd b/addons/escoria-core/game/core-scripts/esc/commands/set_active.gd index b00c6974..c2743f03 100644 --- a/addons/escoria-core/game/core-scripts/esc/commands/set_active.gd +++ b/addons/escoria-core/game/core-scripts/esc/commands/set_active.gd @@ -28,11 +28,10 @@ func validate(arguments: Array): return false if not escoria.object_manager.has(arguments[0]): - escoria.logger.report_errors( - "set_active: invalid object", - [ - "Object with global id %s not found" % arguments[0] - ] + escoria.logger.error( + self, + "[%s]: invalid object. Object with global id %s not found." + % [get_command_name(), arguments[0]] ) return false return true diff --git a/addons/escoria-core/game/core-scripts/esc/commands/set_angle.gd b/addons/escoria-core/game/core-scripts/esc/commands/set_angle.gd index d50b7fa3..80370e31 100644 --- a/addons/escoria-core/game/core-scripts/esc/commands/set_angle.gd +++ b/addons/escoria-core/game/core-scripts/esc/commands/set_angle.gd @@ -33,11 +33,10 @@ func validate(arguments: Array): return false if not escoria.object_manager.has(arguments[0]): - escoria.logger.report_errors( - "set_angle: invalid object", - [ - "Object with global id %s not found" % arguments[0] - ] + escoria.logger.error( + self, + "[%s]: invalid object. Object with global id %s not found." + % [get_command_name(), arguments[0]] ) return false return true @@ -60,4 +59,3 @@ func run(command_params: Array) -> int: func interrupt(): # Do nothing pass - diff --git a/addons/escoria-core/game/core-scripts/esc/commands/set_animations.gd b/addons/escoria-core/game/core-scripts/esc/commands/set_animations.gd index 50d0ade2..5555e0e3 100644 --- a/addons/escoria-core/game/core-scripts/esc/commands/set_animations.gd +++ b/addons/escoria-core/game/core-scripts/esc/commands/set_animations.gd @@ -27,19 +27,17 @@ func validate(arguments: Array): return false if not escoria.object_manager.has(arguments[0]): - escoria.logger.report_errors( - "set_animations: invalid object", - [ - "Object with global id %s not found" % arguments[0] - ] + escoria.logger.error( + self, + "[%s]: invalid object. Object with global id %s not found." + % [get_command_name(), arguments[0]] ) return false if not ResourceLoader.exists(arguments[1]): - escoria.logger.report_errors( - "set_animations: invalid animations", - [ - "The animation resource %s was not found" % arguments[1] - ] + escoria.logger.error( + self, + "[%s]: invalid animation resource. The animation resource %s was not found." + % [get_command_name(), arguments[1]] ) return false return true diff --git a/addons/escoria-core/game/core-scripts/esc/commands/set_interactive.gd b/addons/escoria-core/game/core-scripts/esc/commands/set_interactive.gd index 034bc603..9d239671 100644 --- a/addons/escoria-core/game/core-scripts/esc/commands/set_interactive.gd +++ b/addons/escoria-core/game/core-scripts/esc/commands/set_interactive.gd @@ -27,11 +27,10 @@ func validate(arguments: Array): return false if not escoria.object_manager.has(arguments[0]): - escoria.logger.report_errors( - "set_interactive: invalid object", - [ - "Object with global id %s not found" % arguments[0] - ] + escoria.logger.error( + self, + "[%s]: invalid object. Object with global id %s not found." + % [get_command_name(), arguments[0]] ) return false return true diff --git a/addons/escoria-core/game/core-scripts/esc/commands/set_speed.gd b/addons/escoria-core/game/core-scripts/esc/commands/set_speed.gd index 6443e446..5a76738d 100644 --- a/addons/escoria-core/game/core-scripts/esc/commands/set_speed.gd +++ b/addons/escoria-core/game/core-scripts/esc/commands/set_speed.gd @@ -26,11 +26,10 @@ func validate(arguments: Array): return false if not escoria.object_manager.has(arguments[0]): - escoria.logger.report_errors( - "set_speed: invalid object", - [ - "Object with global id %s not found" % arguments[0] - ] + escoria.logger.error( + self, + "[%s]: invalid object. Object with global id %s not found." + % [get_command_name(), arguments[0]] ) return false return true diff --git a/addons/escoria-core/game/core-scripts/esc/commands/set_state.gd b/addons/escoria-core/game/core-scripts/esc/commands/set_state.gd index 350356f8..41f8ab35 100644 --- a/addons/escoria-core/game/core-scripts/esc/commands/set_state.gd +++ b/addons/escoria-core/game/core-scripts/esc/commands/set_state.gd @@ -34,11 +34,10 @@ func validate(arguments: Array): return false if not escoria.object_manager.has(arguments[0]): - escoria.logger.report_errors( - "set_state: invalid object", - [ - "Object %s not found." % arguments[0] - ] + escoria.logger.error( + self, + "[%s]: invalid object. Object %s not found." + % [get_command_name(), arguments[0]] ) return false return true diff --git a/addons/escoria-core/game/core-scripts/esc/commands/show_menu.gd b/addons/escoria-core/game/core-scripts/esc/commands/show_menu.gd index 6cd6eec0..2a90315a 100644 --- a/addons/escoria-core/game/core-scripts/esc/commands/show_menu.gd +++ b/addons/escoria-core/game/core-scripts/esc/commands/show_menu.gd @@ -31,11 +31,9 @@ func validate(arguments: Array): return false if not arguments[0] in ["main", "pause"]: - escoria.logger.report_errors( - "show_menu: invalid menu ", - [ - "menu %s is invalid" % arguments[0] - ] + escoria.logger.error( + self, + "[%s]: menu %s is invalid." % [get_command_name(), arguments[0]] ) return false return true diff --git a/addons/escoria-core/game/core-scripts/esc/commands/slide.gd b/addons/escoria-core/game/core-scripts/esc/commands/slide.gd index f8d90289..2b6482a1 100644 --- a/addons/escoria-core/game/core-scripts/esc/commands/slide.gd +++ b/addons/escoria-core/game/core-scripts/esc/commands/slide.gd @@ -35,19 +35,17 @@ func validate(arguments: Array): return false if not escoria.object_manager.has(arguments[0]): - escoria.logger.report_errors( - "slide: invalid first object", - [ - "Object with global id %s not found" % arguments[0] - ] + escoria.logger.error( + self, + "[%s]: invalid first object. Object with global id %s not found." + % [get_command_name(), arguments[0]] ) return false if not escoria.object_manager.has(arguments[1]): - escoria.logger.report_errors( - "slide: invalid second object", - [ - "Object with global id %s not found" % arguments[1] - ] + escoria.logger.error( + self, + "[%s]: invalid second object. Object with global id %s not found." + % [get_command_name(), arguments[1]] ) return false return true @@ -80,6 +78,8 @@ func _slide_object( var tween = Tween.new() (escoria.main as Node).add_child(tween) + + tween.connect("tween_completed", self, "_on_tween_completed") var duration = source.node.position.distance_to( destination.node.position @@ -115,3 +115,7 @@ func run(command_params: Array) -> int: func interrupt(): for tween in _tweens: tween.stop_all() + + +func _on_tween_completed(tween: Tween): + tween.queue_free() diff --git a/addons/escoria-core/game/core-scripts/esc/commands/spawn.gd b/addons/escoria-core/game/core-scripts/esc/commands/spawn.gd index b3a2890c..54261348 100644 --- a/addons/escoria-core/game/core-scripts/esc/commands/spawn.gd +++ b/addons/escoria-core/game/core-scripts/esc/commands/spawn.gd @@ -31,27 +31,24 @@ func validate(arguments: Array): if arguments[0].empty() \ or arguments[0] in escoria.object_manager.RESERVED_OBJECTS: - escoria.logger.report_errors( - "spawn: invalid global_id", - [ - "global_id %s is invalid" % arguments[0] - ] + escoria.logger.error( + self, + "[%s]: global_id (%s) is invalid. The global_id was either empty or is reserved." + % [get_command_name(), arguments[0]] ) return false if not ResourceLoader.exists(arguments[1]): - escoria.logger.report_errors( - "spawn: invalid scene path", - [ - "Scene with path %s not found" % arguments[1] - ] + escoria.logger.error( + self, + "[%s]: Invalid scene path: %s not found." + % [get_command_name(), arguments[1]] ) return false if arguments[3] and not escoria.object_manager.has(arguments[3]): - escoria.logger.report_errors( - "spawn: invalid object", - [ - "Object with global id %s not found" % arguments[3] - ] + escoria.logger.error( + self, + "[%s]: invalid object: Object with global id %s not found." + % [get_command_name(), arguments[3]] ) return false return true @@ -83,11 +80,10 @@ func run(command_params: Array) -> int: command_params[2] else: - escoria.logger.report_errors( - "spawn: Invalid scene", - [ - "Failed loading scene %s" % command_params[1] - ] + escoria.logger.error( + self, + "[%s]: Invalid scene. Failed to load scene %s." + % [get_command_name(), command_params[1]] ) return ESCExecution.RC_OK diff --git a/addons/escoria-core/game/core-scripts/esc/commands/stop_snd.gd b/addons/escoria-core/game/core-scripts/esc/commands/stop_snd.gd index 5eecf1a2..8b50e7a6 100644 --- a/addons/escoria-core/game/core-scripts/esc/commands/stop_snd.gd +++ b/addons/escoria-core/game/core-scripts/esc/commands/stop_snd.gd @@ -35,9 +35,10 @@ func validate(arguments: Array): return false if not escoria.object_manager.has(arguments[0]): - escoria.logger.report_errors( - "stop_snd: invalid sound player", - ["Sound player %s not registered" % arguments[0]] + escoria.logger.error( + self, + "[%s]: invalid sound player. Sound player %s not registered." + % [get_command_name(), arguments[0]] ) return false _snd_player = arguments[0] diff --git a/addons/escoria-core/game/core-scripts/esc/commands/teleport.gd b/addons/escoria-core/game/core-scripts/esc/commands/teleport.gd index 97f2a9c7..966d53d4 100644 --- a/addons/escoria-core/game/core-scripts/esc/commands/teleport.gd +++ b/addons/escoria-core/game/core-scripts/esc/commands/teleport.gd @@ -28,19 +28,17 @@ func validate(arguments: Array): return false if not escoria.object_manager.has(arguments[0]): - escoria.logger.report_errors( - "teleport: invalid first object", - [ - "Object with global id %s not found" % arguments[0] - ] + escoria.logger.error( + self, + "[%s]: invalid first object. Object to teleport with global id %s not found." + % [get_command_name(), arguments[0]] ) return false if not escoria.object_manager.has(arguments[1]): - escoria.logger.report_errors( - "teleport: invalid second object", - [ - "Object with global id %s not found" % arguments[1] - ] + escoria.logger.error( + self, + "[%s]: invalid second object. Destination location to teleport to with global id %s not found." + % [get_command_name(), arguments[1]] ) return false return true diff --git a/addons/escoria-core/game/core-scripts/esc/commands/teleport_pos.gd b/addons/escoria-core/game/core-scripts/esc/commands/teleport_pos.gd index cd21ee2f..afdf0379 100644 --- a/addons/escoria-core/game/core-scripts/esc/commands/teleport_pos.gd +++ b/addons/escoria-core/game/core-scripts/esc/commands/teleport_pos.gd @@ -28,11 +28,10 @@ func validate(arguments: Array): return false if not escoria.object_manager.has(arguments[0]): - escoria.logger.report_errors( - "teleport_pos: invalid first object", - [ - "Object with global id %s not found" % arguments[0] - ] + escoria.logger.error( + self, + "[%s]: invalid first object. Object to teleport with global id %s not found." + % [get_command_name(), arguments[0]] ) return false return true diff --git a/addons/escoria-core/game/core-scripts/esc/commands/transition.gd b/addons/escoria-core/game/core-scripts/esc/commands/transition.gd index fa043bd6..eee58812 100644 --- a/addons/escoria-core/game/core-scripts/esc/commands/transition.gd +++ b/addons/escoria-core/game/core-scripts/esc/commands/transition.gd @@ -30,19 +30,18 @@ func validate(arguments: Array): if not escoria.main.scene_transition.has_transition(arguments[0]) \ and not arguments[0].empty(): - escoria.logger.report_errors( - "transition: argument invalid", - [ - "transition with name '%s' doesn't exist" % arguments[0] - ] + escoria.logger.error( + self, + "[%s]: argument invalid. Transition with name '%s' doesn't exist." + % [get_command_name(), arguments[0]] ) return false if not arguments[1] in ["in", "out"]: - escoria.logger.report_errors( - "transition: argument invalid", - [ - "'in' or 'out' expected, but got '%s'" % arguments[1] - ] + escoria.logger.error( + self, + "[%s]: argument invalid" + + "Transition type 'in' or 'out' expected, but '%s' was provided." + % [get_command_name(), arguments[1]] ) return false return true @@ -58,19 +57,27 @@ func run(command_params: Array) -> int: ) if transition_id == ESCTransitionPlayer.TRANSITION_ID_INSTANT: - escoria.logger.debug("Performing instant transition.") + escoria.logger.debug( + self, + "Performing instant transition." + ) escoria.main.scene_transition.reset_shader_cutoff() return ESCExecution.RC_OK - escoria.logger.debug("Starting transition #%s [%s, %s]" - % [transition_id, command_params[0], command_params[1]]) + escoria.logger.debug( + self, + "Starting transition #%s [%s, %s]." + % [transition_id, command_params[0], command_params[1]] + ) while yield( escoria.main.scene_transition, "transition_done" ) != transition_id: pass - escoria.logger.debug("Ending transition #%s [%s, %s]" - % [transition_id, command_params[0], command_params[1]]) + escoria.logger.debug( + self, + "Ending transition #%s [%s, %s]." + % [transition_id, command_params[0], command_params[1]]) return ESCExecution.RC_OK diff --git a/addons/escoria-core/game/core-scripts/esc/commands/turn_to.gd b/addons/escoria-core/game/core-scripts/esc/commands/turn_to.gd index 4aab04fe..a8c6991b 100644 --- a/addons/escoria-core/game/core-scripts/esc/commands/turn_to.gd +++ b/addons/escoria-core/game/core-scripts/esc/commands/turn_to.gd @@ -35,19 +35,17 @@ func validate(arguments: Array): return false if not escoria.object_manager.has(arguments[0]): - escoria.logger.report_errors( - "turn_to: invalid object", - [ - "Object with global id %s not found" % arguments[0] - ] + escoria.logger.error( + self, + "[%s]: The object to turn with global id %s was not found." + % [get_command_name(), arguments[0]] ) return false if not escoria.object_manager.has(arguments[1]): - escoria.logger.report_errors( - "turn_to: invalid target object", - [ - "Object with global id %s not found" % arguments[1] - ] + escoria.logger.error( + self, + "[%s]: The object to turn towards with global id %s was not found." + % [get_command_name(), arguments[0]] ) return false return true @@ -65,9 +63,7 @@ func run(command_params: Array) -> int: # Function called when the command is interrupted. func interrupt(): - escoria.logger.report_warnings( - "turn_to", - [ - "Interrupt() function not implemented" - ] + escoria.logger.warn( + self, + "[%s] interrupt() function not implemented." % get_command_name() ) diff --git a/addons/escoria-core/game/core-scripts/esc/commands/wait.gd b/addons/escoria-core/game/core-scripts/esc/commands/wait.gd index 947061fa..6b3c1c5c 100644 --- a/addons/escoria-core/game/core-scripts/esc/commands/wait.gd +++ b/addons/escoria-core/game/core-scripts/esc/commands/wait.gd @@ -30,12 +30,10 @@ func validate(arguments: Array): # We can't wait for 0 or fewer seconds, now, can we? if arguments[0] <= 0.0: - escoria.logger.report_errors( - "wait: argument invalid", - [ - "%ss is an invalid amount of time to wait." % arguments[0], - "Time to wait must be positive." - ] + escoria.logger.error( + self, + "[%s]: argument invalid. %s is an invalid amount of time to wait (must be positive)." + % [get_command_name(), arguments[0]] ) return false 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 6666e62e..bcfc446d 100644 --- a/addons/escoria-core/game/core-scripts/esc/commands/walk.gd +++ b/addons/escoria-core/game/core-scripts/esc/commands/walk.gd @@ -38,19 +38,17 @@ func validate(arguments: Array): return false if not escoria.object_manager.has(arguments[0]): - escoria.logger.report_errors( - "walk: invalid first object", - [ - "Object with global id %s not found" % arguments[0] - ] + escoria.logger.error( + self, + "[%s]: invalid first object. The object with global id %s to make walk was not found." + % [get_command_name(), arguments[0]] ) return false if not escoria.object_manager.has(arguments[1]): - escoria.logger.report_errors( - "walk: invalid second object", - [ - "Object with global id %s not found" % arguments[0] - ] + escoria.logger.error( + self, + ": invalid second object. The object to walk to with global id %s was not found." + % [get_command_name(), arguments[1]] ) return false 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 ef90301c..f5515e9d 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 @@ -38,19 +38,17 @@ func validate(arguments: Array): return false if not escoria.object_manager.has(arguments[0]): - escoria.logger.report_errors( - "walk_block: invalid first object", - [ - "Object with global id %s not found" % arguments[0] - ] + escoria.logger.error( + self, + "[%s]: invalid first object. The object to make walk with global id %s was not found." + % [get_command_name(), arguments[0]] ) return false if not escoria.object_manager.has(arguments[1]): - escoria.logger.report_errors( - "walk_block: invalid second object", - [ - "Object with global id %s not found" % arguments[1] - ] + escoria.logger.error( + self, + "[%s]: invalid second object. The object to walk to with global id %s was not found." + % [get_command_name(), arguments[1]] ) return false 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 fd783474..b1463ef9 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 @@ -37,11 +37,10 @@ func validate(arguments: Array): return false if not escoria.object_manager.has(arguments[0]): - escoria.logger.report_errors( - "walk_to_pos: invalid first object", - [ - "Object with global id %s not found" % arguments[0] - ] + escoria.logger.error( + self, + "[%s]: invalid first object. The object to make walk with global id %s was not found." + % [get_command_name(), arguments[0]] ) return false 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 e3fa5bd8..d75992de 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 @@ -37,11 +37,10 @@ func validate(arguments: Array): return false if not escoria.object_manager.has(arguments[0]): - escoria.logger.report_errors( - "walk_to_pos_block: invalid first object", - [ - "Object with global id %s not found" % arguments[0] - ] + escoria.logger.error( + self, + "[%s]: invalid first object. The object to make walk with global id %s was not found." + % [get_command_name(), arguments[0]] ) return false 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 78e8cfde..496a5c3d 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 @@ -1,5 +1,5 @@ # Manages currently carried out actions -extends Object +extends Resource class_name ESCActionManager @@ -90,12 +90,10 @@ func do(action: int, params: Array = [], can_interrupt: bool = false) -> void: # 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] - ] + escoria.logger.error( + self, + "Walk action requested for nonexisting object: %s." + % params[0] ) return @@ -104,12 +102,10 @@ func do(action: int, params: Array = [], can_interrupt: bool = false) -> void: 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] - ] + escoria.logger.error( + self, + "Walk action requested to nonexisting destination object: %s." + % params[1] ) return @@ -122,8 +118,8 @@ func do(action: int, params: Array = [], can_interrupt: bool = false) -> void: ACTION.ITEM_LEFT_CLICK: if params[0] is String: escoria.logger.info( - "esc_action_manager.do(): item_left_click on item ", - [params[0]] + self, + "item_left_click on item %s." % params[0] ) if can_interrupt: @@ -135,8 +131,8 @@ func do(action: int, params: Array = [], can_interrupt: bool = false) -> void: ACTION.ITEM_RIGHT_CLICK: if params[0] is String: escoria.logger.info( - "esc_action_manager.do(): item_right_click on item ", - [params[0]] + self, + "item_right_click on item %s." % params[0] ) if can_interrupt: @@ -149,10 +145,13 @@ func do(action: int, params: Array = [], can_interrupt: bool = false) -> void: 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.logger.info( + self, + "trigger_in on trigger %s activated by %s." % [ + trigger_id, + object_id + ] + ) escoria.event_manager.queue_event( escoria.object_manager.get_object(trigger_id).events[ trigger_in_verb @@ -163,10 +162,13 @@ func do(action: int, params: Array = [], can_interrupt: bool = false) -> void: 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.logger.info( + self, + "trigger_out on trigger %s activated by %s." % [ + trigger_id, + object_id + ] + ) escoria.event_manager.queue_event( escoria.object_manager.get_object(trigger_id).events[ trigger_out_verb @@ -174,8 +176,10 @@ func do(action: int, params: Array = [], can_interrupt: bool = false) -> void: ) _: - escoria.logger.report_warnings("esc_action_manager.gd:do()", - ["Action received:", action, "with params ", params]) + escoria.logger.warn( + self, + "Action received: %s with params %s.", [action, params] + ) elif escoria.current_state == escoria.GAME_STATE.WAIT: pass @@ -237,7 +241,10 @@ func _activate( target: ESCObject, combine_with: ESCObject = null ) -> int: - escoria.logger.info("Activated action %s on %s" % [action, target]) + escoria.logger.info( + self, + "Activated action %s on %s." % [action, target] + ) # If we're using an action which item requires to combine if target.node is ESCItem\ @@ -314,16 +321,16 @@ func _activate( ("Reason: %s's item interaction " +\ "is one-way.") % combine_with.global_id ) - escoria.logger.report_warnings( - "ESCActionManager.activate: Invalid action", - errors + escoria.logger.warn( + self, + "Invalid action" + str(errors) ) emit_signal("action_finished") return ESCExecution.RC_ERROR else: - escoria.logger.report_warnings( - "ESCActionManager.activate: Invalid action on item", - [ + escoria.logger.warn( + self, + "Invalid action on item: " + ( "Trying to combine object %s with %s, "+ "but %s is not in inventory." @@ -332,7 +339,6 @@ func _activate( combine_with.global_id, combine_with.global_id ] - ] ) emit_signal("action_finished") return ESCExecution.RC_ERROR @@ -344,16 +350,15 @@ func _activate( ) return ESCExecution.RC_OK else: - escoria.logger.report_warnings( - "ESCActionManager.activate: Invalid action on item", + escoria.logger.warn( + self, + "Invalid action on item" + + "Trying to run action %s on object %s, " % [ - "Trying to run %s on object %s, " % - [ - action, - target.node.global_id - ] - + "but item must be in inventory." + action, + target.node.global_id ] + + "but item must be in inventory." ) if target.events.has(action): @@ -372,14 +377,13 @@ func _activate( emit_signal("action_finished") return event_returned[0] else: - escoria.logger.report_warnings( - "ESCActionManager.activate: Invalid action", - [ + escoria.logger.warn( + self, + "Invalid action: " + "Event for action %s on object %s not found." % [ action, target.global_id ] - ] ) emit_signal("action_finished") return ESCExecution.RC_ERROR @@ -428,12 +432,10 @@ func perform_walk( moving_obj.node.walk_to(target_position, walk_context) else: - escoria.logger.report_errors( - "esc_controller.gd:perform_walk()", - [ - "Function expected either a Vector2 or ESCObject type " + \ - "for destination parameter. Actual was: %s " % destination - ] + escoria.logger.error( + self, + "Function expected either a Vector2 or ESCObject type " + \ + "for destination parameter. Destination provided was: %s." % destination ) return @@ -472,7 +474,10 @@ func perform_inputevent_on_object( In this case, perform the default_action on the item. """ - escoria.logger.info("%s left-clicked with event " % obj.global_id, [event]) + escoria.logger.info( + self, + "%s left-clicked with event %s." % [obj.global_id, event] + ) var event_flags = 0 var has_current_action: bool = false @@ -620,8 +625,10 @@ func _walk_towards_object( var dont_interact: bool = false if obj == null || obj.node == null: - escoria.logger.report_errors("esc_action_manager.gd:_walk_towards_object", - ["obj or obj.node not populated."]) + escoria.logger.error( + self, + "walk_towards_object error. obj or obj.node not populated." + ) var interact_position = obj.node.get_interact_position() # If clicked object is interactive, get destination position from it. if escoria.object_manager.get_object(obj.global_id).interactive: @@ -645,7 +652,10 @@ func _walk_towards_object( escoria.main.current_scene.player.walk_to(destination_position, walk_context) - escoria.logger.debug("Player walking to destination. Yielding.") + escoria.logger.debug( + self, + "Player walking to destination. Yielding." +) # Wait for the player to arrive before continuing with action. var context: ESCWalkContext = yield( @@ -654,11 +664,16 @@ func _walk_towards_object( ) if context.target_object != obj: - escoria.logger.debug("Original walk context target does not match " \ - + "yielded walk context. Likely interrutped walk.") + escoria.logger.debug( + self, + "Original walk context target does not match " \ + + "yielded walk context. Likely interrutped walk.") return - escoria.logger.info("Context arrived: %s" % context) + escoria.logger.info( + self, + "Context arrived: %s." % context + ) # Confirm that reached item was the one user clicked in the first place. # Don't interact if that is not the case. 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 ffa2567d..6b5aabf1 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 @@ -1,5 +1,5 @@ # A registry of ESC command objects -extends Object +extends Reference class_name ESCCommandRegistry @@ -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 escoria.project_settings_manager.get_setting( - escoria.project_settings_manager.COMMAND_DIRECTORIES + for command_directory in ESCProjectSettingsManager.get_setting( + ESCProjectSettingsManager.COMMAND_DIRECTORIES ): if ResourceLoader.exists("%s/%s.gd" % [command_directory, command_name]): registry[command_name] = load( @@ -26,12 +26,10 @@ func load_command(command_name: String) -> ESCBaseCommand: ).new() return registry[command_name] - escoria.logger.report_errors( - "ESCCommandRegistry.load_command: Command not found", - [ - "No command class could be found for command %s" % - command_name - ] + escoria.logger.error( + self, + "No command class could be found for command %s." + % command_name ) return null 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 0bd04c95..7e9e5a74 100644 --- a/addons/escoria-core/game/core-scripts/esc/esc_compiler.gd +++ b/addons/escoria-core/game/core-scripts/esc/esc_compiler.gd @@ -1,5 +1,5 @@ # Compiler of the ESC language -extends Object +extends Resource class_name ESCCompiler @@ -52,7 +52,7 @@ var _current_indent = 0 func _init(): # Assure command list preference - # (we use ProjectSettings instead of escoria.project_settings_manager + # (we use ProjectSettings instead of ESCProjectSettingsManager # here because this is called from escoria._init()) if not ProjectSettings.has_setting(COMMAND_DIRECTORIES): ProjectSettings.set_setting(COMMAND_DIRECTORIES, [ @@ -90,7 +90,7 @@ func _init(): # Load an ESC file from a file resource func load_esc_file(path: String) -> ESCScript: - escoria.logger.debug("Parsing file %s" % path) + escoria.logger.debug(self, "Parsing file %s." % path) if File.new().file_exists(path): var file = File.new() file.open(path, File.READ) @@ -99,12 +99,9 @@ func load_esc_file(path: String) -> ESCScript: lines.append(file.get_line()) return self.compile(lines, path) else: - escoria.logger.report_errors( - path, - [ - "Can not find ESC file", - "File %s could not be found" % path - ] + escoria.logger.error( + self, + "Can not find ESC file: file %s could not be found." % path ) return null @@ -128,20 +125,29 @@ func _compile(lines: Array, path: String = "") -> Array: while lines.size() > 0: var line = lines.pop_front().strip_edges(false, true) - escoria.logger.trace("Parsing line %s" % line) + escoria.logger.trace( + self, + "Parsing line %s." % 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.") + escoria.logger.trace( + self, + "Line is empty or a comment. Skipping." + ) continue var indent = \ - escoria.utils.get_re_group( + ESCUtils.get_re_group( _indent_regex.search(line), INDENT_REGEX_GROUP ).length() if _event_regex.search(line): var event = ESCEvent.new(line) - escoria.logger.trace("Line is the event %s" % event.name) + escoria.logger.trace( + self, + "Line is the event %s." % event.name + ) var event_lines = [] while lines.size() > 0: var next_line = lines.pop_front() @@ -152,14 +158,18 @@ func _compile(lines: Array, path: String = "") -> Array: break if event_lines.size() > 0: escoria.logger.trace( - "Compiling the next %d lines into the event" % \ + self, + "Compiling the next %d lines into the event." % \ event_lines.size() ) event.statements = self._compile(event_lines, path) returned.append(event) elif _group_regex.search(line): var group = ESCGroup.new(line) - escoria.logger.trace("Line is a group") + escoria.logger.trace( + self, + "Line is a group." + ) var group_lines = [] while lines.size() > 0: var next_line = lines.pop_front() @@ -167,7 +177,7 @@ func _compile(lines: Array, path: String = "") -> Array: _empty_regex.search(next_line): continue var next_line_indent = \ - escoria.utils.get_re_group( + ESCUtils.get_re_group( _indent_regex.search(next_line), INDENT_REGEX_GROUP ).length() @@ -178,7 +188,8 @@ func _compile(lines: Array, path: String = "") -> Array: break if group_lines.size() > 0: escoria.logger.trace( - "Compiling the next %d lines into the group" % \ + self, + "Compiling the next %d lines into the group." % \ group_lines.size() ) group.statements = self._compile(group_lines, path) @@ -186,7 +197,10 @@ func _compile(lines: Array, path: String = "") -> Array: elif _dialog_regex.search(line): var dialog = ESCDialog.new() dialog.load_string(line) - escoria.logger.trace("Line is a dialog") + escoria.logger.trace( + self, + "Line is a dialog." + ) var dialog_lines = [] while lines.size() > 0: var next_line = lines.pop_front() @@ -195,7 +209,7 @@ func _compile(lines: Array, path: String = "") -> Array: continue var end_line = _dialog_end_regex.search(next_line) if end_line and \ - escoria.utils.get_re_group( + ESCUtils.get_re_group( end_line, INDENT_REGEX_GROUP ).length() == indent: @@ -204,7 +218,8 @@ func _compile(lines: Array, path: String = "") -> Array: dialog_lines.append(next_line) if dialog_lines.size() > 0: escoria.logger.trace( - "Compiling the next %d lines into the dialog" % \ + self, + "Compiling the next %d lines into the dialog." % \ dialog_lines.size() ) dialog.options = self._compile(dialog_lines, path) @@ -215,7 +230,8 @@ func _compile(lines: Array, path: String = "") -> Array: var dialog_option = ESCDialogOption.new() dialog_option.load_string(line) escoria.logger.trace( - "Line is the dialog option %s" % \ + self, + "Line is the dialog option %s." % \ dialog_option.option ) var dialog_option_lines = [] @@ -225,7 +241,7 @@ func _compile(lines: Array, path: String = "") -> Array: _empty_regex.search(next_line): continue var next_line_indent = \ - escoria.utils.get_re_group( + ESCUtils.get_re_group( _indent_regex.search(next_line), INDENT_REGEX_GROUP ).length() @@ -236,8 +252,9 @@ func _compile(lines: Array, path: String = "") -> Array: break if dialog_option_lines.size() > 0: escoria.logger.trace( - "Compiling the next %d lines into the event" % \ - dialog_option_lines.size() + self, + "Compiling the next %d lines into the event." + % dialog_option_lines.size() ) dialog_option.statements = self._compile(dialog_option_lines, path) returned.append(dialog_option) @@ -246,34 +263,19 @@ func _compile(lines: Array, path: String = "") -> Array: if command.command_exists(): returned.append(command) else: - escoria.logger.report_errors( - path, - [ - "Invalid command detected: %s" % command.name, - "Command implementation not found in any command directory" - ] + escoria.logger.error( + self, + "Command \"%s\" cannot be found under folder %s.\nPlease confirm setting \"%s\" is set to the folder where ESC commands are stored." + % [ + command.name, + ProjectSettings.get_setting(COMMAND_DIRECTORIES), + ESCProjectSettingsManager.COMMAND_DIRECTORIES + ] ) else: - escoria.logger.report_errors( - path, - [ - "Invalid ESC line detected", - "Line couldn't be compiled: %s" % line - ] + escoria.logger.error( + self, + "Invalid ESC line detected.\nLine couldn't be compiled: %s." + % line ) return returned - -# Look to see if any globals (names in braces) should be interpreted -# -# #### Parameters -# -# * string: Text to log -func replace_globals(string: String) -> String: - for result in _globals_regex.search_all(string): - var globresult = escoria.globals_manager.get_global( - str(result.get_string()) - ) - string = string.replace( - "{" + result.get_string() + "}", str(globresult) - ) - return string 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 cce7d2d8..b911b1e8 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 @@ -88,16 +88,14 @@ func _process(delta: float) -> void: _running_events[channel_name] = \ events_queue[channel_name].pop_front() escoria.logger.debug( - "esc_event_manager", - [ - "Popping event '%s' from background queue %s" % [ - _running_events[channel_name].name, - channel_name, - ], - "from source %s" % _running_events[channel_name].source \ - if not _running_events[channel_name].source.empty() - else "(unknown)", - ] + self, + "Popping event '%s' from background queue %s " % [ + _running_events[channel_name].name, + channel_name, + ] + + "to source %s." % _running_events[channel_name].source \ + if not _running_events[channel_name].source.empty() + else "(unknown)" ) if not _running_events[channel_name].is_connected( "finished", self, "_on_event_finished" @@ -174,28 +172,22 @@ func queue_event_from_esc(script_object: ESCScript, event: String, return ESCExecution.RC_WONT_QUEUE if channel == CHANNEL_FRONT: - escoria.event_manager.queue_event(script_object.events[event]) + queue_event(script_object.events[event]) else: - escoria.event_manager.queue_background_event( + queue_background_event( channel, script_object.events[event] ) if block: if channel == CHANNEL_FRONT: - var rc = yield(escoria.event_manager, "event_finished") + var rc = yield(self, "event_finished") while rc[1] != event: - rc = yield(escoria.event_manager, "event_finished") + rc = yield(self, "event_finished") return rc else: - var rc = yield( - escoria.event_manager, - "background_event_finished" - ) + var rc = yield(self, "background_event_finished") while rc[1] != event and rc[2] != channel: - rc = yield( - escoria.event_manager, - "background_event_finished" - ) + rc = yield(self, "background_event_finished") return rc return ESCExecution.RC_OK @@ -208,6 +200,7 @@ func queue_event_from_esc(script_object: ESCScript, event: String, func queue_event(event: ESCEvent, force: bool = false) -> void: if _changing_scene and not force: escoria.logger.info( + self, "Changing scenes. Won't queue event '%s'." % event.name ) return @@ -222,18 +215,22 @@ func queue_event(event: ESCEvent, force: bool = false) -> void: var message = "Event '%s' is already the most-recently queued event in channel '%s'." + \ " Won't be queued again." - escoria.logger.debug(message % [event.name, CHANNEL_FRONT]) + escoria.logger.debug(self, message % [event.name, CHANNEL_FRONT]) return elif _is_event_running(event, CHANNEL_FRONT): # Don't queue the same event if it's already running. escoria.logger.debug( + self, "Event %s already running in channel '%s'. Won't be queued." % [event.name, CHANNEL_FRONT] ) return - escoria.logger.debug("Queueing %s in channel %s." % [event.name, CHANNEL_FRONT]) + escoria.logger.debug( + self, + "Queueing event %s in channel %s." % [event.name, CHANNEL_FRONT] + ) self.events_queue[CHANNEL_FRONT].append(event) @@ -266,11 +263,12 @@ func queue_background_event(channel_name: String, event: ESCEvent) -> void: var message = "Event '%s' is already the most-recently queued event in channel '%s'." + \ " Won't be queued again." - escoria.logger.debug(message % [event.name, channel_name]) + escoria.logger.debug(self, message % [event.name, channel_name]) return elif _is_event_running(event, CHANNEL_FRONT): # Don't queue the same event if it's already running. escoria.logger.debug( + self, "Event %s already running in channel '%s'. Won't be queued." % [event.name, channel_name] ) @@ -287,8 +285,10 @@ func queue_background_event(channel_name: String, event: ESCEvent) -> void: func interrupt(exceptions: PoolStringArray = []) -> void: for channel_name in _running_events.keys(): if _running_events[channel_name] != null and not _running_events[channel_name].name in exceptions: - escoria.logger.debug("Interrupting running event %s in channel %s..." - % [_running_events[channel_name].name, channel_name]) + escoria.logger.debug( + self, + "Interrupting running event %s in channel %s..." + % [_running_events[channel_name].name, channel_name]) _running_events[channel_name].interrupt() _channels_state[channel_name] = true @@ -298,8 +298,10 @@ func interrupt(exceptions: PoolStringArray = []) -> void: if event.name in exceptions: continue - escoria.logger.debug("Interrupting queued event %s in channel %s..." - % [event.name, channel_name]) + escoria.logger.debug( + self, + "Interrupting queued event %s in channel %s..." + % [event.name, channel_name]) event.interrupt() events_queue[channel_name].clear() @@ -334,7 +336,10 @@ func get_running_event(name: String) -> ESCEvent: # #### Parameterse # - value: boolean value to set _changing_scene to func set_changing_scene(p_is_changing_scene: bool) -> void: - escoria.logger.trace("Setting _changing_scene to %s." % p_is_changing_scene) + escoria.logger.trace( + self, + "Setting _changing_scene to %s." % p_is_changing_scene + ) _changing_scene = p_is_changing_scene @@ -353,17 +358,16 @@ func set_changing_scene(p_is_changing_scene: bool) -> void: func _on_event_finished(finished_statement: ESCStatement, return_code: int, channel_name: String) -> void: var event = _running_events[channel_name] if not event: - escoria.logger.report_warnings( - "esc_event_manager.gd:_on_event_finished()", - [ - "Event %s finished without being in _running_events[%s]" - % [finished_statement.name, channel_name] - ] + escoria.logger.warn( + self, + "Event %s finished without being in _running_events[%s]." + % [finished_statement.name, channel_name] ) return escoria.logger.debug( - "Event %s ended with return code %d" % [event.name, return_code] + self, + "Event %s ended with return code %d." % [event.name, return_code] ) var event_flags = event.flags diff --git a/addons/escoria-core/game/core-scripts/esc/esc_globals_manager.gd b/addons/escoria-core/game/core-scripts/esc/esc_globals_manager.gd index b1c2fe8f..b2245de0 100644 --- a/addons/escoria-core/game/core-scripts/esc/esc_globals_manager.gd +++ b/addons/escoria-core/game/core-scripts/esc/esc_globals_manager.gd @@ -16,6 +16,13 @@ export(Dictionary) var _globals = {} # Registry of globals that are to be reserved for internal use only. var _reserved_globals: Dictionary = {} +# Use look-ahead/behind to capture the term in braces +var globals_regex: RegEx = RegEx.new() + +# Constructor +func _init(): + globals_regex.compile("(?<=\\{)(.*)(?=\\})") + # Check if a global was registered # @@ -35,11 +42,11 @@ func has(key: String) -> bool: # - value: The initial value (optional) func register_reserved_global(key: String, value = null) -> void: if key in _reserved_globals: - escoria.logger.report_errors( - "ESCGlobalsManager.register_reserved_global: Can not override reserved global", - [ - "Global key %s is already registered as reserved" % key - ] + escoria.logger.error( + self, + "Can not override reserved global: Global key %s is already " + + "registered as reserved." + % key ) var old_value = _globals[key] if _globals.has(key) else "" _reserved_globals[key] = value @@ -86,11 +93,9 @@ func filter(pattern: String) -> Dictionary: # - value: The new value func set_global(key: String, value, ignore_reserved: bool = false) -> void: if key in _reserved_globals and not ignore_reserved: - escoria.logger.report_errors( - "ESCGlobalsManager.set_global: Can not override reserved global", - [ - "Global key %s is reserved and can not be overridden" % key - ] + escoria.logger.error( + self, + "Global key %s is reserved and can not be overridden." % key ) emit_signal( @@ -102,7 +107,6 @@ func set_global(key: String, value, ignore_reserved: bool = false) -> void: _globals[key] = value - # Set all globals that match the pattern to the value # Check out [the Godot docs](https://docs.godotengine.org/en/stable/classes/class_string.html#class-string-method-match) # for the pattern format @@ -117,6 +121,24 @@ func set_global_wildcard(pattern: String, value) -> void: self.set_global(global_key, value) +# Look to see if any globals (names in braces) should be interpreted +# +# #### Parameters +# +# * string: Text in which to replace globals +# +# *Returns* the provided string with globals variables replaced with their values +func replace_globals(string: String) -> String: + for result in globals_regex.search_all(string): + var globresult = escoria.globals_manager.get_global( + str(result.get_string()) + ) + string = string.replace( + "{" + result.get_string() + "}", str(globresult) + ) + return string + + # Save the state of globals in the savegame. # # #### Parameters 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 134c4e81..8a2d3245 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 @@ -1,5 +1,5 @@ # A manager for inventory objects -extends Object +extends Resource class_name ESCInventoryManager @@ -31,11 +31,10 @@ func items_in_inventory() -> Array: # - item: Inventory item id func remove_item(item: String): if not inventory_has(item): - escoria.logger.report_errors( - "ESCInventoryManager.remove_item: Error removing inventory item", - [ - "Trying to remove non-existent item %s" % item - ] + escoria.logger.error( + self, + "Error removing inventory item: " + + "Trying to remove non-existent item %s." % item ) else: escoria.globals_manager.set_global("i/%s" % item, false) 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 4c46d7f2..91655c60 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 @@ -1,5 +1,5 @@ # A manager for ESC objects -extends Node +extends Resource class_name ESCObjectManager @@ -69,15 +69,6 @@ func _init() -> void: current_room_key = ESCRoomObjectsKey.new() -# Make active objects in current room visible -func _process(_delta): - for room in room_objects: - if room.is_reserved or _is_current_room(room): - for object in room.objects: - if (object as ESCObject).node: - (object as ESCObject).node.visible = (object as ESCObject).active - - # Updates which object manager room is to be treated as the currently active one. # # #### Parameters @@ -85,12 +76,10 @@ func _process(_delta): # - room: Room to register the object with in the object manager func set_current_room(room: ESCRoom) -> void: if room == null: - escoria.logger.report_errors( - "ESCObjectManager:set_current_room()", - [ - "Unable to set current room: No valid room specified.", - "Please pass in a valid ESCRoom as an argument to the method." - ] + escoria.logger.error( + self, + "Unable to set current room: No room was specified.\n" + + "Please pass in a valid ESCRoom as an argument to the method." ) current_room_key.room_global_id = room.global_id @@ -111,13 +100,11 @@ func register_object(object: ESCObject, room: ESCRoom = null, force: bool = fals if object.global_id.empty(): object.global_id = str(object.node.get_path()).split("/root/", false)[0] object.node.global_id = object.global_id - escoria.logger.report_warnings( - "ESCObjectManager:register_object()", - [ - "Registering ESCObject %s with empty global_id." % object.name, - "Using node's full path as global_id: %s" - % object.node.global_id - ] + escoria.logger.warn( + self, + "Registering ESCObject %s with empty global_id." % object.name + + "Using node's full path as global_id: %s" + % object.node.global_id ) # If this is a reserved object, let's make sure it's in the right place. @@ -139,28 +126,25 @@ func register_object(object: ESCObject, room: ESCRoom = null, force: bool = fals if not room_key.is_valid(): # This condition should very likely never happen. - escoria.logger.report_errors( - "ESCObjectManager:register_object()", - [ - "No room was specified to register object with, and no current room is properly set.", - "Please either pass in a valid ESCRoom to this method, or " + \ - "call set_current_room() with a valid ESCRoom first." - ] + escoria.logger.error( + self, + "No room was specified to register object with, and no current room is properly set.\n" + + "Please either pass in a valid ESCRoom to this method, or " + \ + "call set_current_room() with a valid ESCRoom first." ) else: room_key.room_global_id = room.global_id room_key.room_instance_id = room.get_instance_id() - if not force and _object_exists_in_room(object, room_key): - escoria.logger.report_errors( - "ESCObjectManager:register_object()", - [ - "Object with global id %s in room (%s, %s) already registered" % - [ - object.global_id, - room_key.room_global_id, - room_key.room_instance_id - ] + if not force and _object_exists_in_room(object, room_key) \ + and _object_state_in_room_is_default(object, room_key): + escoria.logger.error( + self, + "Object with global id '%s' in room %s already registered from node path %s." + % [ + object.global_id, + room_key.room_global_id, + get_object(object.global_id, room).node.get_path() ] ) return @@ -213,17 +197,15 @@ func register_object(object: ESCObject, room: ESCRoom = null, force: bool = fals # If object state is not STATE_DEFAULT, save it in manager's object states if object.state != ESCObject.STATE_DEFAULT: if get_object(object.global_id) == null: - escoria.logger.report_errors( - "ESCObjectManager:register_object()", - [ - "Object with global id %s in room (%s, %s) not found in Object Manager" % - [ - object.global_id, - room_key.room_global_id, - room_key.room_instance_id - ] - ] - ) + escoria.logger.error( + self, + "Object with global id %s in room (%s, %s) not found in Object Manager." + % [ + object.global_id, + room_key.room_global_id, + room_key.room_instance_id + ] + ) else: get_object(object.global_id).state = object.state @@ -235,7 +217,6 @@ func register_object(object: ESCObject, room: ESCRoom = null, force: bool = fals room_container.room_instance_id = room_key.room_instance_id room_container.is_reserved = false room_container.objects = objects - room_objects.push_back(room_container) @@ -256,8 +237,9 @@ func has(global_id: String, room: ESCRoom = null) -> bool: var room_key: ESCRoomObjectsKey if room == null: - escoria.logger.trace("ESCObjectManager.has(): No room specified." \ - + " Defaulting to current room." + escoria.logger.trace( + self, + "No room specified. Defaulting to current room." ) room_key = current_room_key @@ -284,20 +266,19 @@ func get_object(global_id: String, room: ESCRoom = null) -> ESCObject: if reserved_objects_container.objects.has(global_id): return reserved_objects_container.objects[global_id] else: - escoria.logger.report_warnings( - "ESCObjectManager:get_object()", - [ - "Reserved object with global id %s not found in object manager!" - % global_id - ] + escoria.logger.warn( + self, + "Reserved object with global id %s not found in object manager!" + % global_id ) return null var room_key: ESCRoomObjectsKey if room == null: - escoria.logger.trace("ESCObjectManager.has(): No room specified." \ - + " Defaulting to current room." + escoria.logger.trace( + self, + "No room specified. Defaulting to current room." ) room_key = current_room_key @@ -307,13 +288,11 @@ func get_object(global_id: String, room: ESCRoom = null) -> ESCObject: room_key.room_instance_id = room.get_instance_id() if not _room_exists(room_key): - escoria.logger.report_warnings( - "ESCObjectManager:get_object()", - [ - "Specified room is empty/not found.", - "Object with global id %s in room instance (%s, %s) not found" - % [global_id, room_key.room_global_id, room_key.room_instance_id] - ] + escoria.logger.warn( + self, + "Specified room is empty/not found.\n" + + "Object with global id %s in room instance (%s, %s) not found." + % [global_id, room_key.room_global_id, room_key.room_instance_id] ) return null @@ -322,12 +301,10 @@ func get_object(global_id: String, room: ESCRoom = null) -> ESCObject: if objects.has(global_id): return objects[global_id] else: - escoria.logger.report_warnings( - "ESCObjectManager:get_object()", - [ - "Object with global id %s in room instance (%s, %s) not found" - % [global_id, room_key.room_global_id, room_key.room_instance_id] - ] + escoria.logger.warn( + self, + "Object with global id %s in room instance (%s, %s) not found." + % [global_id, room_key.room_global_id, room_key.room_instance_id] ) return null @@ -344,23 +321,22 @@ func unregister_object(object: ESCObject, room_key: ESCRoomObjectsKey) -> void: # called as part of an objectd's forced registration and the object not # yet being managed. escoria.logger.debug( - "ESCObjectManager:unregister_object(): Unable to unregister object.", - [ - "Object with global ID %s room (%s, %s) not found. If this was" % - [ - "?" if object == null else object.global_id, - room_key.room_global_id, - room_key.room_instance_id - ], - "part of a 'forced' registration, ignore this warning." - ] + self, + "Unable to unregister object.\n" + + "Object with global ID %s room (%s, %s) not found. If this was " + % [ + "?" if object == null else object.global_id, + room_key.room_global_id, + room_key.room_instance_id + ] + + "part of a 'forced' registration, ignore this warning." ) return var room_objects = _get_room_objects_objects(room_key) - if escoria.inventory_manager.inventory_has(object.global_id): + if not escoria.is_quitting and escoria.inventory_manager.inventory_has(object.global_id): # Re-instance the node if it is an item present in inventory; that is, # re-register it with the new current room. if object.node != null: @@ -393,11 +369,9 @@ func unregister_object_by_global_id(global_id: String, room_key: ESCRoomObjectsK # - p_savegame: The savegame resource func save_game(p_savegame: ESCSaveGame) -> void: if not current_room_key.is_valid() or not _room_exists(current_room_key): - escoria.logger.report_errors( - "ESCObjectManager:save_game()", - [ - "No current room specified or found." - ] + escoria.logger.error( + self, + "No current room specified or found." ) var objects: Dictionary = _get_room_objects_objects(current_room_key) @@ -430,13 +404,11 @@ func get_start_location() -> ESCLocation: and object.node.is_start_location: return object - escoria.logger.report_warnings( - "ESCObjectManager:get_start_location()", - [ - "Room has no ESCLocation node with 'is_start_location' enabled.", - "Player will be set at position (0,0) by default." - ] - ) + escoria.logger.warn( + self, + "Room has no ESCLocation node with 'is_start_location' enabled. " + + "Player will be set at position (0,0)." + ) return null @@ -486,11 +458,9 @@ func _room_exists(room_key: ESCRoomObjectsKey) -> bool: # **Returns** True iff object exists in the object manager entry specified by room_key. func _object_exists_in_room(object: ESCObject, room_key: ESCRoomObjectsKey) -> bool: if object == null: - escoria.logger.report_warnings( - "ESCObjectManager:_object_exists_in_room()", - [ - "Cannot check for null objects." - ] + escoria.logger.warn( + self, + "Cannot check room for \"null\" objects." ) return false @@ -503,6 +473,30 @@ func _object_exists_in_room(object: ESCObject, room_key: ESCRoomObjectsKey) -> b return false +# Checks whether the specified object's state is "default" in the specified object manager entry. +# +# #### Parameters +# +# - object: The object to check for existence. +# - room_key: The key representing the desired room in the object manager array. +# **Returns** True if object's state is "default" in the object manager entry specified by room_key. +func _object_state_in_room_is_default(object: ESCObject, room_key: ESCRoomObjectsKey) -> bool: + if object == null: + escoria.logger.warn( + self, + "Cannot check room for \"null\" objects." + ) + + return false + + for room_container in room_objects: + if _compare_container_to_key(room_container, room_key) \ + and room_container.objects.get(object.global_id).state == ESCObject.STATE_DEFAULT: + return true + + return false + + # Returns the objects currently being managed in the object manager entry specified # by the specified room key. # 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 e34c0064..f60a20f2 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 @@ -1,4 +1,4 @@ -extends Object +extends Resource class_name ESCRoomManager @@ -86,14 +86,12 @@ func change_scene(room_path: String, enable_automatic_transitions: bool) -> void # Check if game scene was loaded if not escoria.game_scene: - escoria.logger.report_errors( - "ESCRoomManager.change_scene: Failed loading game scene", - [ - "Failed loading scene %s" % \ - escoria.project_settings_manager.get_setting( - escoria.project_settings_manager.GAME_SCENE - ) - ] + escoria.logger.error( + self, + "Failed loading game scene %s." % \ + ESCProjectSettingsManager.get_setting( + ESCProjectSettingsManager.GAME_SCENE + ) ) if escoria.main.current_scene \ @@ -106,9 +104,12 @@ 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(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: + 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 @@ -138,11 +139,9 @@ func change_scene(room_path: String, enable_automatic_transitions: bool) -> void escoria.inputs_manager.hotspot_focused = "" else: - escoria.logger.report_errors( - "ESCRoomManager.change_scene: Failed loading room scene", - [ - "Failed loading scene %s" % room_path - ] + escoria.logger.error( + self, + "Failed loading room scene %s." % room_path ) @@ -154,11 +153,9 @@ func change_scene(room_path: String, enable_automatic_transitions: bool) -> void # - room: The ESCRoom to be initialized for use. func init_room(room: ESCRoom) -> void: if not is_instance_valid(room) || room == null: - escoria.logger.report_errors( - "ESCRoomManager.init_room: No valid room specified", - [ - "No valid room was specified for initialization." - ] + escoria.logger.error( + self, + "No valid room was specified for initialization." ) if room.camera_limits.empty(): @@ -189,12 +186,11 @@ func init_room(room: ESCRoom) -> void: # player by the same number of pixels when they're at the terrain edge and # move them when it shouldn't. if room.position != Vector2(0,0): - escoria.logger.report_errors( - "ESCRoomManager.init_room: Room node not at (0,0)", - [ - "The room node's coordinates must be (0,0) instead of %s." % room.position - ] - ) + escoria.logger.error( + self, + "The room node's coordinates must be (0,0) instead of %s." + % room.position + ) _perform_script_events(room) @@ -217,8 +213,8 @@ func _perform_script_events(room: ESCRoom) -> void: "%s %s out" % [ _transition.get_command_name(), - escoria.project_settings_manager.get_setting( - escoria.project_settings_manager.DEFAULT_TRANSITION + ESCProjectSettingsManager.get_setting( + ESCProjectSettingsManager.DEFAULT_TRANSITION ) ], "%s 0.1" % _wait.get_command_name() @@ -286,7 +282,9 @@ func _perform_script_events(room: ESCRoom) -> void: escoria.main.finish_current_scene_init(room) # Add new camera to scene being prepared. - var new_player_camera: ESCCamera = escoria.resource_cache.get_resource(escoria.CAMERA_SCENE_PATH).instance() + var new_player_camera: ESCCamera = escoria.resource_cache.get_resource( + escoria.CAMERA_SCENE_PATH + ).instance() new_player_camera.register() room.player_camera = new_player_camera @@ -360,8 +358,8 @@ func _perform_script_events(room: ESCRoom) -> void: command_strings.append("%s %s in" % [ _transition.get_command_name(), - escoria.project_settings_manager.get_setting( - escoria.project_settings_manager.DEFAULT_TRANSITION + ESCProjectSettingsManager.get_setting( + ESCProjectSettingsManager.DEFAULT_TRANSITION ) ] ) @@ -432,12 +430,10 @@ func _run_script_event(event_name: String, room: ESCRoom): if room.compiled_script.events.has(event_name): escoria.logger.debug( - "esc_room:_run_script_event", - [ - "Queuing room script event %s" % event_name, - "Composed of %s statements" % - room.compiled_script.events[event_name].statements.size() - ] + self, + "Queuing room script event %s " % event_name + + "composed of %s statements." + % room.compiled_script.events[event_name].statements.size() ) escoria.event_manager.queue_event(room.compiled_script.events[event_name], true) return true 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 bb5f260d..e50b59da 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 @@ -1,6 +1,6 @@ # A base class for every ESC command. # Extending classes have to override the configure and run function -extends Node +extends Resource class_name ESCBaseCommand @@ -22,7 +22,10 @@ func _init() -> void: # Return the descriptor of the arguments of this command func configure() -> ESCCommandArgumentDescriptor: - escoria.logger.error("Command %s did not override configure." % get_command_name()) + escoria.logger.error( + self, + "Command %s did not override configure. Please implement a configure() function." % get_command_name() + ) return ESCCommandArgumentDescriptor.new() @@ -33,7 +36,10 @@ func validate(arguments: Array) -> bool: # Run the command func run(command_params: Array) -> int: - escoria.logger.error("Command %s did not override run." % get_command_name()) + escoria.logger.error( + self, + "Command %s did not override run. Please implement a run() function." % get_command_name() + ) return 0 @@ -44,4 +50,7 @@ func get_command_name() -> String: # Function called when the command is interrupted. func interrupt(): - escoria.logger.trace("Command %s did not override interrupt." % get_command_name()) + escoria.logger.trace( + self, + "Command %s did not override interrupt. Please implement an interrupt() function." % get_command_name() + ) 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 4c479542..3e6f8ae9 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 @@ -28,15 +28,15 @@ func _init(command_string): if command_regex.search(command_string): for result in command_regex.search_all(command_string): if "name" in result.names: - self.name = escoria.utils.get_re_group(result, "name") + self.name = ESCUtils.get_re_group(result, "name") if "parameters" in result.names: # Split parameters by whitespace but allow quoted # parameters var quote_open = false var parameter_values = PoolStringArray([]) var parsed_parameters = \ - escoria.utils.sanitize_whitespace( - escoria.utils.get_re_group( + ESCUtils.sanitize_whitespace( + ESCUtils.get_re_group( result, "parameters" ).strip_edges() @@ -66,7 +66,7 @@ func _init(command_string): else: parameters.append(parameter) if "conditions" in result.names: - for condition in escoria.utils.get_re_group( + for condition in ESCUtils.get_re_group( result, "conditions" ).split(","): @@ -74,22 +74,20 @@ func _init(command_string): ESCCondition.new(condition.strip_edges()) ) else: - escoria.logger.report_errors( - "Invalid command detected: %s" % command_string, - [ - "Command regexp didn't match" - ] + escoria.logger.error( + self, + "Invalid command detected: %s\nCommand regexp didn't match." + % command_string ) # Check, if conditions match func is_valid() -> bool: if not command_exists(): - escoria.logger.report_errors( - "Invalid command detected: %s" % self.name, - [ - "Command implementation not found in any command directory" - ] + escoria.logger.error( + self, + "Invalid command detected: %s" % self.name + + "Command implementation not found in any command directory." ) return false @@ -100,8 +98,8 @@ func is_valid() -> bool: # # *Returns* True if the command exists, else false. func command_exists() -> bool: - for base_path in escoria.project_settings_manager.get_setting( - escoria.project_settings_manager.COMMAND_DIRECTORIES + for base_path in ESCProjectSettingsManager.get_setting( + ESCProjectSettingsManager.COMMAND_DIRECTORIES ): var command_path = "%s/%s.gd" % [ base_path.trim_suffix("/"), @@ -124,14 +122,18 @@ func run() -> int: ) if command_object.validate(prepared_arguments): - escoria.logger.debug("Running command %s with parameters %s" % [ - self.name, - prepared_arguments - ]) + escoria.logger.debug( + self, + "Running command %s with parameters %s." + % [self.name, prepared_arguments] + ) var rc = command_object.run(prepared_arguments) if rc is GDScriptFunctionState: rc = yield(rc, "completed") - escoria.logger.debug("[%s] Return code: %d" % [self.name, rc]) + escoria.logger.debug( + self, + "[%s] Return code: %d." % [self.name, rc] + ) return rc else: return ESCExecution.RC_ERROR diff --git a/addons/escoria-core/game/core-scripts/esc/types/esc_command_argument_descriptor.gd b/addons/escoria-core/game/core-scripts/esc/types/esc_command_argument_descriptor.gd index f10b071f..e9bc5de4 100644 --- a/addons/escoria-core/game/core-scripts/esc/types/esc_command_argument_descriptor.gd +++ b/addons/escoria-core/game/core-scripts/esc/types/esc_command_argument_descriptor.gd @@ -1,5 +1,5 @@ # The descriptor of the arguments of an ESC command -extends Object +extends Reference class_name ESCCommandArgumentDescriptor # As the get_type command was deprecated with Godot 2.x w we need a way to determine @@ -71,7 +71,7 @@ func prepare_arguments(arguments: Array) -> Array: # appear at the very end of a command's argument list. varargs.append(arguments[index]) else: - complete_arguments[index] = escoria.utils.get_typed_value( + complete_arguments[index] = ESCUtils.get_typed_value( arguments[index], types[index] ) @@ -98,22 +98,20 @@ func validate(command: String, arguments: Array) -> bool: if required_args_count < min_args: var verb = "was" if required_args_count == 1 else "were" - escoria.logger.report_errors( - "ESCCommandArgumentDescriptor:validate()", - [ - "Invalid arguments for command %s" % command, - "Arguments didn't match minimum size {num}: Only {args} {verb} found" \ - .format({"num":self.min_args,"args":required_args_count,"verb":verb}) - ] + escoria.logger.error( + self, + "Invalid arguments for command %s. " % command + + "Arguments didn't match minimum size {num}: Only {args} {verb} found." \ + .format({"num":self.min_args,"args":required_args_count,"verb":verb}) ) if arguments.size() > self.max_args and not has_varargs: - escoria.logger.report_errors( - "ESCCommandArgumentDescriptor:validate()", - [ - "Invalid arguments for command %s" % command, - "Maximum number of arguments ({num}) exceeded: {args}".format({"num":self.max_args,"args":arguments}) - ] + escoria.logger.error( + self, + "Invalid arguments for command %s" % command + + "Maximum number of arguments ({num}) exceeded: {args}.".format( + {"num":self.max_args,"args":arguments} + ) ) for index in range(arguments.size()): @@ -140,17 +138,17 @@ func validate(command: String, arguments: Array) -> bool: for type in self.types[types_index]: allowed_types += GODOT_TYPE_LIST[type] + " or " allowed_types = allowed_types.substr(0, allowed_types.length() - 3) + "]" - escoria.logger.report_errors( - "Argument type did not match descriptor for command \"%s\"" % - command, - [ - "Argument %d (\"%s\") is of type %s. Expected %s" % [ - index, - arguments[index], - GODOT_TYPE_LIST[typeof(arguments[index])], - allowed_types - ] - ] + escoria.logger.error( + self, + "Argument type did not match descriptor for command \"%s\"\n" + % command + + "Argument %d (\"%s\") is of type %s. Expected %s." + % [ + index, + arguments[index], + GODOT_TYPE_LIST[typeof(arguments[index])], + allowed_types + ] ) return true diff --git a/addons/escoria-core/game/core-scripts/esc/types/esc_condition.gd b/addons/escoria-core/game/core-scripts/esc/types/esc_condition.gd index d6d904a7..4e691820 100644 --- a/addons/escoria-core/game/core-scripts/esc/types/esc_condition.gd +++ b/addons/escoria-core/game/core-scripts/esc/types/esc_condition.gd @@ -1,5 +1,5 @@ # A condition to run a command -extends Object +extends Reference class_name ESCCondition @@ -56,24 +56,24 @@ func _init(comparison_string: String): if "is_negated" in result.names: self.negated = true if "comparison" in result.names: - match escoria.utils.get_re_group(result, "comparison"): + match ESCUtils.get_re_group(result, "comparison"): "eq": self.comparison = COMPARISON_EQ "gt": self.comparison = COMPARISON_GT "lt": self.comparison = COMPARISON_LT - _: escoria.logger.report_errors( - "Invalid comparison type detected: %s" % - comparison_string, - [ + _: + escoria.logger.error( + self, + "Invalid comparison type detected: %s" % + comparison_string + "Comparison type %s unknown" % - escoria.utils.get_re_group( + ESCUtils.get_re_group( result, "comparison" ) - ] - ) + ) if "comparison_value" in result.names: - self.comparison_value = escoria.utils.get_typed_value( - escoria.utils.get_re_group( + self.comparison_value = ESCUtils.get_typed_value( + ESCUtils.get_re_group( result, "comparison_value" ) @@ -83,13 +83,12 @@ func _init(comparison_string: String): if "is_activity" in result.names: self.comparison = COMPARISON_ACTIVITY if "flag" in result.names: - self.flag = escoria.utils.get_re_group(result, "flag") + self.flag = ESCUtils.get_re_group(result, "flag") else: - escoria.logger.report_errors( - "Invalid comparison detected: %s" % comparison_string, - [ - "Comparison regexp didn't match" - ] + escoria.logger.error( + self, + "Invalid comparison detected: %s\nComparison regexp didn't match." + % comparison_string ) @@ -98,6 +97,7 @@ func run() -> bool: var global_name = self.flag escoria.logger.debug( + self, COMPARISON_DESCRIPTION[self.comparison] % [ "inventory item" if self.inventory else "global value", self.flag, @@ -138,6 +138,7 @@ func run() -> bool: return_value = not return_value escoria.logger.debug( + self, "It is" if return_value else "It isn't" ) diff --git a/addons/escoria-core/game/core-scripts/esc/types/esc_dialog.gd b/addons/escoria-core/game/core-scripts/esc/types/esc_dialog.gd index a215038d..8ef261d1 100644 --- a/addons/escoria-core/game/core-scripts/esc/types/esc_dialog.gd +++ b/addons/escoria-core/game/core-scripts/esc/types/esc_dialog.gd @@ -38,37 +38,36 @@ func load_string(dialog_string: String): if dialog_regex.search(dialog_string): for result in dialog_regex.search_all(dialog_string): if "avatar" in result.names: - self.avatar = escoria.utils.get_re_group(result, "avatar") + self.avatar = ESCUtils.get_re_group(result, "avatar") if "timeout" in result.names: self.timeout = int( - escoria.utils.get_re_group(result, "timeout") + ESCUtils.get_re_group(result, "timeout") ) if "timeout_option" in result.names: self.timeout_option = int( - escoria.utils.get_re_group(result, "timeout_option") + ESCUtils.get_re_group(result, "timeout_option") ) else: - escoria.logger.report_errors( - "Invalid dialog detected: %s" % dialog_string, - [ - "Dialog regexp didn't match" - ] + escoria.logger.error( + self, + "Invalid dialog detected: %s\nDialog regexp didn't match." + % dialog_string ) # Check if dialog is valid func is_valid() -> bool: if self.avatar != "-" and not ResourceLoader.exists(self.avatar): - escoria.logger.report_errors( - "Avatar scene not found: %s" % self.avatar, - [] + escoria.logger.error( + self, + "Avatar scene not found: %s." % self.avatar ) return false if self.timeout_option > self.options.size() \ or self.timeout_option < 0: - escoria.logger.report_errors( - "Invalid timeout_option parameter given: %d" % self.timeout_option, - [] + escoria.logger.error( + self, + "Invalid timeout_option parameter given: %d." % self.timeout_option ) return false @@ -77,7 +76,10 @@ func is_valid() -> bool: # Run this dialog func run(): - escoria.logger.debug("Starting dialog") + escoria.logger.debug( + self, + "Starting dialog." + ) escoria.current_state = escoria.GAME_STATE.DIALOG if !escoria.dialog_player: escoria.dialog_player = escoria.main.current_scene.get_node( diff --git a/addons/escoria-core/game/core-scripts/esc/types/esc_dialog_option.gd b/addons/escoria-core/game/core-scripts/esc/types/esc_dialog_option.gd index 40ae7b30..28f8375b 100644 --- a/addons/escoria-core/game/core-scripts/esc/types/esc_dialog_option.gd +++ b/addons/escoria-core/game/core-scripts/esc/types/esc_dialog_option.gd @@ -30,13 +30,13 @@ func load_string(option_string: String): var _trans_key = "" if "trans_key" in result.names: _trans_key = "%s:" % \ - escoria.utils.get_re_group(result, "trans_key") + ESCUtils.get_re_group(result, "trans_key") self.option = "%s%s" % [ _trans_key, - escoria.utils.get_re_group(result, "option") + ESCUtils.get_re_group(result, "option") ] if "conditions" in result.names: - for condition_text in escoria.utils.get_re_group( + for condition_text in ESCUtils.get_re_group( result, "conditions" ).split(","): @@ -44,11 +44,10 @@ func load_string(option_string: String): ESCCondition.new(condition_text.strip_edges()) ) else: - escoria.logger.report_errors( - "Invalid dialog option detected: %s" % option_string, - [ + escoria.logger.error( + self, + "Invalid dialog option detected: %s." % option_string, "Dialog option regexp didn't match" - ] ) 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 e79f8baf..4a028a1d 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 @@ -60,10 +60,10 @@ func _init(event_string: String): if event_regex.search(event_string): for result in event_regex.search_all(event_string): if "name" in result.names: - self.name = escoria.utils.get_re_group(result, "name") \ + self.name = ESCUtils.get_re_group(result, "name") \ .strip_edges() if "flags" in result.names: - var _flags = escoria.utils.get_re_group( + var _flags = ESCUtils.get_re_group( result, "flags" ).strip_edges().split(" ") @@ -76,17 +76,19 @@ func _init(event_string: String): if "NO_SAVE" in _flags: self.flags |= FLAG_NO_SAVE else: - escoria.logger.report_errors( - "Invalid event detected: %s" % event_string, - [ - "Event regexp didn't match" - ] + escoria.logger.error( + self, + "Invalid event detected: %s\nEvent regexp didn't match." + % event_string ) # Execute this statement and return its return code func run() -> int: reset_interrupt() - escoria.logger.debug("Event %s started" % name) + escoria.logger.debug( + self, + "Event %s started." % name + ) return .run() diff --git a/addons/escoria-core/game/core-scripts/esc/types/esc_execution.gd b/addons/escoria-core/game/core-scripts/esc/types/esc_execution.gd index 781c1ea4..e11eebca 100644 --- a/addons/escoria-core/game/core-scripts/esc/types/esc_execution.gd +++ b/addons/escoria-core/game/core-scripts/esc/types/esc_execution.gd @@ -1,5 +1,5 @@ # Basic features and informations about ESC executions -extends Object +extends Resource class_name ESCExecution diff --git a/addons/escoria-core/game/core-scripts/esc/types/esc_group.gd b/addons/escoria-core/game/core-scripts/esc/types/esc_group.gd index 8094dde3..da339152 100644 --- a/addons/escoria-core/game/core-scripts/esc/types/esc_group.gd +++ b/addons/escoria-core/game/core-scripts/esc/types/esc_group.gd @@ -20,7 +20,7 @@ func _init(group_string: String): if group_regex.search(group_string): for result in group_regex.search_all(group_string): if "conditions" in result.names: - for condition in escoria.utils.get_re_group( + for condition in ESCUtils.get_re_group( result, "conditions" ).split(","): @@ -28,9 +28,8 @@ func _init(group_string: String): ESCCondition.new(condition.strip_edges()) ) else: - escoria.logger.report_errors( - "Invalid group detected: %s" % group_string, - [ - "Group regexp didn't match" - ] + escoria.logger.error( + self, + "Invalid group detected: %s\nGroup regexp didn't match." + % group_string ) diff --git a/addons/escoria-core/game/core-scripts/esc/types/esc_object.gd b/addons/escoria-core/game/core-scripts/esc/types/esc_object.gd index 28ccd31c..e2376676 100644 --- a/addons/escoria-core/game/core-scripts/esc/types/esc_object.gd +++ b/addons/escoria-core/game/core-scripts/esc/types/esc_object.gd @@ -1,5 +1,5 @@ +extends Reference # An object handled in Escoria -extends Node class_name ESCObject @@ -50,23 +50,23 @@ func set_state(p_state: String, immediate: bool = false): if animation_node.has_animation(p_state): if immediate: escoria.logger.debug( - "State \"%s\" set. Matching immediate animation executing." % [ - p_state - ] + self, + "State \"%s\" set. Matching immediate animation executing." + % p_state ) animation_node.seek_end(p_state) else: escoria.logger.debug( - "State \"%s\" set. Matching non-immediate animation executing." % [ - p_state - ] + self, + "State \"%s\" set. Matching non-immediate animation executing." + % p_state ) animation_node.play(p_state) else: escoria.logger.debug( - "State \"%s\" set. No matching animation found." % [ - p_state - ] + self, + "State \"%s\" set. No matching animation found." + % p_state ) diff --git a/addons/escoria-core/game/core-scripts/esc/types/esc_scheduled_event.gd b/addons/escoria-core/game/core-scripts/esc/types/esc_scheduled_event.gd index f45f0be3..9bd18eb1 100644 --- a/addons/escoria-core/game/core-scripts/esc/types/esc_scheduled_event.gd +++ b/addons/escoria-core/game/core-scripts/esc/types/esc_scheduled_event.gd @@ -1,5 +1,5 @@ # An event that is scheduled to run later -extends Object +extends Reference class_name ESCScheduledEvent diff --git a/addons/escoria-core/game/core-scripts/esc/types/esc_script.gd b/addons/escoria-core/game/core-scripts/esc/types/esc_script.gd index edce1e60..00e200dd 100644 --- a/addons/escoria-core/game/core-scripts/esc/types/esc_script.gd +++ b/addons/escoria-core/game/core-scripts/esc/types/esc_script.gd @@ -1,5 +1,5 @@ # A compiled ESC script -extends Object +extends Resource class_name ESCScript diff --git a/addons/escoria-core/game/core-scripts/esc/types/esc_statement.gd b/addons/escoria-core/game/core-scripts/esc/types/esc_statement.gd index 8d890c6a..c4f2db2d 100644 --- a/addons/escoria-core/game/core-scripts/esc/types/esc_statement.gd +++ b/addons/escoria-core/game/core-scripts/esc/types/esc_statement.gd @@ -1,5 +1,5 @@ # A statement in an ESC file -extends Object +extends Reference class_name ESCStatement @@ -7,7 +7,7 @@ class_name ESCStatement signal finished(event, return_code) # Emitted when the event was interrupted -signal interrupted(return_code) +signal interrupted(event, return_code) # The list of ESC commands @@ -35,7 +35,7 @@ func run() -> int: if _is_interrupted: final_rc = ESCExecution.RC_INTERRUPTED statement.interrupt() - emit_signal("interrupted", final_rc) + emit_signal("interrupted", self, final_rc) return final_rc if statement.is_valid(): @@ -43,9 +43,8 @@ func run() -> int: if rc is GDScriptFunctionState: rc = yield(rc, "completed") escoria.logger.debug( - "esc_statement", - ["Statement (%s) was completed." - % statement] + self, + "Statement (%s) was completed." % statement ) if rc == ESCExecution.RC_REPEAT: return self.run() @@ -59,11 +58,10 @@ func run() -> int: # Interrupt the statement in the middle of its execution. func interrupt(): - escoria.logger.info("Interrupting event %s (%s)" % \ - [ - self.name if "name" in self else "group", - str(self) - ] + escoria.logger.info( + self, + "Interrupting event %s (%s)." + % [self.name if "name" in self else "group", str(self)] ) _is_interrupted = true for statement in statements: diff --git a/addons/escoria-core/game/core-scripts/esc_game.gd b/addons/escoria-core/game/core-scripts/esc_game.gd index b3c0a766..0481cafa 100644 --- a/addons/escoria-core/game/core-scripts/esc_game.gd +++ b/addons/escoria-core/game/core-scripts/esc_game.gd @@ -96,7 +96,7 @@ func _ready(): # Handle debugging visualizations func _draw(): - if !Engine.is_editor_hint(): + if not Engine.is_editor_hint(): return if editor_debug_mode == EDITOR_GAME_DEBUG_DISPLAY.NONE: return @@ -131,12 +131,9 @@ func do_walk(destination, params: Array = [], can_interrupt: bool = false) -> vo # 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] - ] + escoria.logger.error( + self, + "Walk action requested on nonexisting object: %s." % params[0] ) return @@ -145,12 +142,9 @@ func do_walk(destination, params: Array = [], can_interrupt: bool = false) -> vo 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 - ] + escoria.logger.error( + self, + "Walk action requested to nonexisting object: %s." % destination ) return @@ -436,8 +430,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(escoria.project_settings_manager.get_setting( - escoria.project_settings_manager.CRASH_MESSAGE) + crash_popup.dialog_text = tr(ESCProjectSettingsManager.get_setting( + ESCProjectSettingsManager.CRASH_MESSAGE) ) % files_to_send crash_popup.popup_centered() escoria.set_game_paused(true) @@ -451,9 +445,9 @@ func escoria_hide_ui(): if ui_parent_control_node != null and not ui_parent_control_node.is_empty(): (get_node(ui_parent_control_node) as Control).visible = false else: - escoria.logger.report_warnings( - "esc_game.gd#escoria_hide_ui", - ["UI parent Control node not defined!"] + escoria.logger.warn( + self, + "UI parent Control node not defined!" ) @@ -463,9 +457,9 @@ func escoria_show_ui(): if ui_parent_control_node != null and not ui_parent_control_node.is_empty(): (get_node(ui_parent_control_node) as Control).visible = true else: - escoria.logger.report_warnings( - "esc_game.gd#escoria_show_ui", - ["UI parent Control node not defined!"] + escoria.logger.warn( + self, + "UI parent Control node not defined!" ) diff --git a/addons/escoria-core/game/core-scripts/esc_item.gd b/addons/escoria-core/game/core-scripts/esc_item.gd index 7a1188f7..d509e3e0 100644 --- a/addons/escoria-core/game/core-scripts/esc_item.gd +++ b/addons/escoria-core/game/core-scripts/esc_item.gd @@ -323,7 +323,10 @@ func _unhandled_input(input_event: InputEvent) -> void: if event is InputEventMouseButton and event.is_pressed(): if not escoria.current_state == escoria.GAME_STATE.DEFAULT: - escoria.logger.info("Game state doesn't accept interactions") + escoria.logger.info( + self, + "Current game state doesn't accept interactions." + ) return var p = get_global_mouse_position() if _is_in_shape(p): @@ -367,8 +370,9 @@ func get_animation_player() -> Node: child is AnimationPlayer: player_node_path = child.get_path() if not has_node(player_node_path): - escoria.logger.warning( - "Can not find node at path %s" % player_node_path + escoria.logger.warn( + self, + "Can not find animation_player node at path %s for %s." % [player_node_path, global_id] ) else: _animation_player = ESCAnimationPlayer.new( @@ -394,7 +398,9 @@ func get_interact_position() -> Vector2: interact_position = collision.global_position if multiple_positions_found: - escoria.logger.warning("Multiple ESClocations found to walk to for object " + + escoria.logger.warn( + self, + "Multiple ESClocations found to walk to for object " + "%s. Last one will be used." % global_id) return interact_position @@ -500,7 +506,8 @@ func get_sprite() -> Node: _sprite_node = child if _sprite_node == null: escoria.logger.error( - "No sprite node found in the scene %s" % get_path() + self, + "No sprite node found in the scene %s." % get_path() ) return _sprite_node @@ -579,7 +586,11 @@ func update_idle(): # global position of the player func get_camera_node(): if has_node(camera_node): - escoria.logger.debug("Camera node found - directing camera to the camera_node on " + global_id) + escoria.logger.debug( + self, + "Camera node found - directing camera to the camera_node on %s." + % global_id + ) return get_node(camera_node) return self 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 0fbd9622..a5e2ac00 100644 --- a/addons/escoria-core/game/core-scripts/esc_resource_cache.gd +++ b/addons/escoria-core/game/core-scripts/esc_resource_cache.gd @@ -1,5 +1,5 @@ # A cache for resources -extends Object +extends Reference class_name ESCResourceCache var thread: Thread @@ -138,7 +138,7 @@ func get_resource(path): return res else: _unlock("return") - # We can't use escoria.project_settings_manager here since this method + # We can't use ESCProjectSettingsManager here since this method # can be called from escoria._init() if not ProjectSettings.get_setting("escoria/platform/skip_cache"): var res = ResourceLoader.load(path) diff --git a/addons/escoria-core/game/core-scripts/esc_room.gd b/addons/escoria-core/game/core-scripts/esc_room.gd index 7492c4ad..edeea6d2 100644 --- a/addons/escoria-core/game/core-scripts/esc_room.gd +++ b/addons/escoria-core/game/core-scripts/esc_room.gd @@ -60,7 +60,10 @@ func _enter_tree(): # name of this node if it's not set manually func _ready(): # Might as well just check here. - if get_parent() == get_tree().root and ProjectSettings.get_setting("application/run/main_scene") != self.filename: + if get_parent() == get_tree().root \ + and ESCProjectSettingsManager.get_setting( + "application/run/main_scene" + ) != self.filename: is_run_directly = true escoria.room_manager.init_room(self) @@ -85,7 +88,9 @@ func _draw(): # Draw lines for camera limits for i in camera_limits.size(): draw_rect(camera_limits[i], camera_limits_colors[i], false, 10.0) - var default_font = Control.new().get_font("font") + var temp_control = Control.new() + var default_font = temp_control.get_font("font") + temp_control.queue_free() draw_string(default_font, Vector2(camera_limits[i].position.x + 30, camera_limits[i].position.y + 30), str(i), camera_limits_colors[i]) diff --git a/addons/escoria-core/game/core-scripts/esc_terrain.gd b/addons/escoria-core/game/core-scripts/esc_terrain.gd index b4feeb1a..c913efc0 100644 --- a/addons/escoria-core/game/core-scripts/esc_terrain.gd +++ b/addons/escoria-core/game/core-scripts/esc_terrain.gd @@ -64,20 +64,16 @@ func _ready(): if n is NavigationPolygonInstance: if n.enabled: if !Engine.is_editor_hint() and navigation_enabled_found: - escoria.logger.report_errors( - "ESCTerrain:_ready()", - [ - "Multiple NavigationPolygonInstances enabled " + \ - "at the same time." - ] + escoria.logger.error( + self, + "Multiple NavigationPolygonInstances enabled " + \ + "at the same time." ) elif Engine.is_editor_hint(): - escoria.logger.report_warnings( - "ESCTerrain:_ready()", - [ - "Multiple NavigationPolygonInstances enabled " + \ - "at the same time." - ] + escoria.logger.warn( + self, + "Multiple NavigationPolygonInstances enabled " + \ + "at the same time." ) navigation_enabled_found = true current_active_navigation_instance = n diff --git a/addons/escoria-core/game/core-scripts/esc_tooltip.gd b/addons/escoria-core/game/core-scripts/esc_tooltip.gd index 78e956d2..0f8248f2 100644 --- a/addons/escoria-core/game/core-scripts/esc_tooltip.gd +++ b/addons/escoria-core/game/core-scripts/esc_tooltip.gd @@ -85,6 +85,7 @@ func set_debug_mode(p_debug_mode: bool): else: if debug_texturerect_node: remove_child(debug_texturerect_node) + debug_texturerect_node.queue_free() # Set the first target of the label. diff --git a/addons/escoria-core/game/core-scripts/esc_walk_context.gd b/addons/escoria-core/game/core-scripts/esc_walk_context.gd index 924cb34e..1f98c54e 100644 --- a/addons/escoria-core/game/core-scripts/esc_walk_context.gd +++ b/addons/escoria-core/game/core-scripts/esc_walk_context.gd @@ -1,6 +1,6 @@ # The walk context describes the target of a walk command and if that command # should be executed fast -extends Object +extends Reference class_name ESCWalkContext diff --git a/addons/escoria-core/game/core-scripts/log/esc_logger.gd b/addons/escoria-core/game/core-scripts/log/esc_logger.gd deleted file mode 100644 index 225a448a..00000000 --- a/addons/escoria-core/game/core-scripts/log/esc_logger.gd +++ /dev/null @@ -1,325 +0,0 @@ -# Logging framework for Escoria -extends Object -class_name ESCLogger - -# Log file format -const LOG_FILE_FORMAT: String = "log_%s_%s.log" - - -# The path of the ESC file that was reported last (used for removing -# duplicate warnings -var warning_path: String - -# Log file handler -var log_file: File - -# Crash save filename -var crash_savegame_filename - -# Did we crash already? -onready var crashed = false - -# Valid log levels -enum { LOG_ERROR, LOG_WARNING, LOG_INFO, LOG_DEBUG, LOG_TRACE } - - -# A map of log level names to log level ints -var _level_map: Dictionary = { - "ERROR": LOG_ERROR, - "WARNING": LOG_WARNING, - "INFO": LOG_INFO, - "DEBUG": LOG_DEBUG, - "TRACE": LOG_TRACE, -} - - -# Logger constructor -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" - ) - var date = OS.get_datetime() - log_file_path = log_file_path.plus_file(LOG_FILE_FORMAT % [ - str(date["year"]) + str(date["month"]) + str(date["day"]), - str(date["hour"]) + str(date["minute"]) + str(date["second"]) - ]) - log_file.open( - log_file_path, - File.WRITE - ) - - -# Log a trace message -# -# Global variables can be substituted into the text by wrapping the global -# name in braces. -# e.g. trace "There are {coin_count} coins remaining". -# -# #### Parameters -# -# * string: Text to log -# * args: Additional information -func trace(string: String, args = []): - if _get_log_level() >= LOG_TRACE and !crashed: - var argsstr = str(args) if !args.empty() else "" - string = escoria.esc_compiler.replace_globals(string) - _log("(T)\t" + string + " \t" + argsstr) - - -# Log a debug message -# -# Global variables can be substituted into the text by wrapping the global -# name in braces. -# e.g. debug "There are {coin_count} coins remaining". -# -# #### Parameters -# -# * string: Text to log -# * args: Additional information -func debug(string: String, args = []): - if _get_log_level() >= LOG_DEBUG and !crashed: - string = escoria.esc_compiler.replace_globals(string) - var argsstr = str(args) if !args.empty() else "" - _log("(D)\t" + string + " \t" + argsstr) - -# Log an info message -# -# Global variables can be substituted into the text by wrapping the global -# name in braces. -# e.g. info "There are {coin_count} coins remaining". -# -# #### Parameters -# -# * string: Text to log -# * args: Additional information -func info(string: String, args = []): - if _get_log_level() >= LOG_INFO and !crashed: - var argsstr = [] - if !args.empty(): - for arg in args: - if arg is Array: - for p in arg: - argsstr.append(p.global_id) - else: - argsstr.append(str(arg)) - string = escoria.esc_compiler.replace_globals(string) - _log("(I)\t" + string + " \t" + str(argsstr)) - - -# Log a warning message -# -# Global variables can be substituted into the text by wrapping the global -# name in braces. -# e.g. warning "There are {coin_count} coins remaining". -# -# #### Parameters -# -# * string: Text to log -# * args: Additional information -func warning(string: String, args = []): - if _get_log_level() >= LOG_WARNING and !crashed: - var argsstr = str(args) if !args.empty() else "" - string = escoria.esc_compiler.replace_globals(string) - _log("(W)\t" + string + " \t" + argsstr, true) - - 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 = escoria.project_settings_manager.get_setting( - escoria.project_settings_manager.CRASH_MESSAGE - ) % files - - _log(message, true) - escoria.set_game_paused(true) - escoria.main.current_scene.game.show_crash_popup( - [log_file.get_path_absolute()] - ) - assert(false) - - -# Log an error message -# -# Global variables can be substituted into the text by wrapping the global -# name in braces. -# e.g. error "There are {coin_count} coins remaining". -# -# #### Parameters -# -# * string: Text to log -# * args: Additional information -func error(string: String, args = [], do_savegame: bool = true): - if _get_log_level() >= LOG_ERROR and !crashed: - var argsstr = str(args) if !args.empty() else "" - string = escoria.esc_compiler.replace_globals(string) - _log("(E)\t" + string + " \t" + argsstr, true) - - if escoria.project_settings_manager.get_setting( - escoria.project_settings_manager.TERMINATE_ON_ERRORS - ): - _perform_stack_trace_log() - crashed = true - if do_savegame: - _perform_save_game_log() - - var files_to_send: Array = [ - log_file.get_path_absolute().get_base_dir().plus_file( - escoria.save_manager.crash_savegame_filename.get_file() - ), - log_file.get_path_absolute() - ] - - var files = "- %s\n- %s" % files_to_send - var message = escoria.project_settings_manager.get_setting( - escoria.project_settings_manager.CRASH_MESSAGE - ) % files - - _log(message, true) - escoria.set_game_paused(true) - - if is_instance_valid(escoria.main.current_scene): - escoria.main.current_scene.game.show_crash_popup(files_to_send) - - assert(false) - - -# Log a warning message about an ESC file -# -# #### Parameters -# -# * p_path: Path to the file -# * warnings: Array of warnings to put out -# * report_once: Additional messages about the same file will be ignored -func report_warnings(p_path: String, warnings: Array, report_once = false) -> void: - var warning_is_reported = false - if p_path == warning_path: - warning_is_reported = true - - if !warning_is_reported: - var text = "Warnings in file "+p_path+"\n" - for w in warnings: - if w is Array: - text += str(w)+"\n" - else: - text += w+"\n" - warning(text) - - if report_once: - warning_is_reported = true - - -# Log an error message about an ESC file -# -# #### Parameters -# -# * p_path: Path to the file -# * errors: Array of errors to put out -func report_errors(p_path: String, errors: Array) -> void: - var text = "Errors in file "+p_path+"\n" - for e in errors: - if e is Array: - text += str(e)+"\n" - else: - text += e+"\n" - error(text) - - -# Write message: -# - in logfile -# - in stdout, or stderr if err is true. -# -# #### Parameters -# -# * message: Message to log -# * err: if true, write in stderr -func _log(message:String, err: bool = false): - message = "ESC {0} {1}".format([_formatted_date(), message]) - - if err: - printerr(message) - else: - print(message) - _write_logfile(message) - - -# Returns the current date/time, as a string -# formatted for logging. E.g. 2022-04-19T16:10:39 -func _formatted_date() -> String: - var info = OS.get_datetime() - info["year"] = "%04d" % info["year"] - info["month"] = "%02d" % info["month"] - info["day"] = "%02d" % info["day"] - info["hour"] = "%02d" % info["hour"] - info["minute"] = "%02d" % info["minute"] - info["second"] = "%02d" % info["second"] - - return "{year}-{month}-{day}T{hour}:{minute}:{second}".format(info) - - -# Returns the currently set log level -# **Returns** Log level as set in the configuration -func _get_log_level() -> int: - 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 -func _perform_save_game_log(): - _log("Performing emergency savegame.") - var error = escoria.save_manager.save_game_crash() - if error == OK: - _log( - "Emergency savegame created successfully in folder: %s" % - escoria.project_settings_manager.get_setting( - escoria.project_settings_manager.LOG_FILE_PATH - ) - ) - else: - _log("Emergency savegame creation failed!", false) - - -# Logs and writes the stack trace into stdout and log file. -func _perform_stack_trace_log(): - _log("Stack trace:") - print_stack() - _write_stack_logfile() - - -# Write a message in the output logfile -# -# #### Parameters -# -# * message: Message to write -func _write_logfile(message: String) -> void: - if log_file.is_open(): - log_file.store_string(message + "\n") - - -# Write the stacktrace in the output logfile -func _write_stack_logfile(): - var frame_number = 0 - for stack in get_stack().slice(2, get_stack().size()): - _write_logfile( - "Frame %s - %s:%s in function '%s'" % [ - str(frame_number), - stack["source"], - stack["line"], - stack["function"], - ] - ) - frame_number += 1 - - -# Close the log file cleanly -func close_logs(): - _log("Closing logs peacefully.") - log_file.close() diff --git a/addons/escoria-core/game/core-scripts/migrations/esc_migration.gd b/addons/escoria-core/game/core-scripts/migrations/esc_migration.gd index 9c89d9f9..ef277bce 100644 --- a/addons/escoria-core/game/core-scripts/migrations/esc_migration.gd +++ b/addons/escoria-core/game/core-scripts/migrations/esc_migration.gd @@ -1,6 +1,6 @@ # Base class for all migration version scripts. Extending scripts should be # named like the version they migrate the savegame to. (e.g. 1.0.0.gd, 1.0.1.gd) -extends Object +extends Reference class_name ESCMigration diff --git a/addons/escoria-core/game/core-scripts/migrations/esc_migration_manager.gd b/addons/escoria-core/game/core-scripts/migrations/esc_migration_manager.gd index 519bcd79..bd86648a 100644 --- a/addons/escoria-core/game/core-scripts/migrations/esc_migration_manager.gd +++ b/addons/escoria-core/game/core-scripts/migrations/esc_migration_manager.gd @@ -1,5 +1,5 @@ # Class that handles migrations between different game or escoria versions -extends Object +extends Reference class_name ESCMigrationManager @@ -29,10 +29,11 @@ func migrate( to: String, versions_directory: String ) -> ESCSaveGame: - escoria.logger.info("Migrating from version %s to %s" % [ - from, - to - ]) + escoria.logger.info( + self, + "Migrating savegame from version %s to version %s." + % [from, to] + ) var from_info = version_regex.search(from) var to_info = version_regex.search(to) @@ -49,14 +50,11 @@ func migrate( wrong_version = true if wrong_version: - escoria.logger.report_errors( - "esc_migration_manager:migrate", - [ - "Can not migrate savegame from version %s to version %s" % [ - from, - to - ] - ] + escoria.logger.error( + self, + "Can not migrate savegame from version %s to version %s." + + " \"To\" version must be later than \"from\" version." + % [from, to] ) var versions = _find_versions(versions_directory, from, to) @@ -67,13 +65,14 @@ func migrate( for version in versions: var migration_script = load(version).new() if not migration_script is ESCMigration: - escoria.logger.report_errors( - "esc_migration_manager:migrate", - [ - "File %s is not a valid migration script" % version - ] + escoria.logger.error( + self, + "File %s is not a valid migration script." % version ) - escoria.logger.debug("Migrating using %s" % version) + escoria.logger.debug( + self, + "Migrating savegame to version %s." % version + ) (migration_script as ESCMigration).set_savegame(savegame) (migration_script as ESCMigration).migrate() savegame = (migration_script as ESCMigration).get_savegame() @@ -90,7 +89,10 @@ func migrate( # - to: End version to check # **Returns** A list of version scripts func _find_versions(directory: String, from: String, to: String) -> Array: - escoria.logger.trace("Searching directory %s" % directory) + escoria.logger.trace( + self, + "Searching directory %s." % directory + ) var versions = [] var dir = Directory.new() dir.open(directory) @@ -106,7 +108,10 @@ func _find_versions(directory: String, from: String, to: String) -> Array: to ) elif regex_result and _version_between(version, from, to): - escoria.logger.trace("Found fitting migration script %s" % version) + escoria.logger.trace( + self, + "Found compatible savegame migration script for version %s." % version + ) versions.append( directory.plus_file(file_name) ) diff --git a/addons/escoria-core/game/core-scripts/plugins/escoria_plugin.gd b/addons/escoria-core/game/core-scripts/plugins/escoria_plugin.gd new file mode 100644 index 00000000..68ef6a4d --- /dev/null +++ b/addons/escoria-core/game/core-scripts/plugins/escoria_plugin.gd @@ -0,0 +1,102 @@ +class_name EscoriaPlugin + +# Register a user interface. This should be called in a deferred way +# from the addon's _enter_tree. +# +# #### Parameters +# - plugin: the plugin that registers +# - game_scene: Path to the game scene extending ESCGame +# +# *Returns* a boolean indicating whether the ui could be successfully registered +static func register_ui(plugin: EditorPlugin, game_scene: String) -> bool: + if not plugin.get_editor_interface().is_plugin_enabled( + Escoria.ESCORIA_CORE_PLUGIN_NAME + ): + push_error("Escoria Core must be enabled.") + return false + + var game_scene_setting_value = ESCProjectSettingsManager.get_setting( + ESCProjectSettingsManager.GAME_SCENE + ) + + if not game_scene_setting_value in [ + "", + game_scene + ]: + push_error("Can't register user interface because user interface %s is registered." + % game_scene_setting_value + ) + return false + ESCProjectSettingsManager.set_setting( + ESCProjectSettingsManager.GAME_SCENE, + game_scene + ) + return true + +# Deregister a user interface +# +# #### Parameters +# - game_scene: Path to the game scene extending ESCGame +static func deregister_ui(game_scene: String): + # If the currently configured game scene is not the one we're disabling, exit now. + if ESCProjectSettingsManager.get_setting( + ESCProjectSettingsManager.GAME_SCENE + ) != game_scene: + return + + ESCProjectSettingsManager.set_setting( + ESCProjectSettingsManager.GAME_SCENE, + "" + ) + + +# Register a dialog manager addon. This should be called in a deferred way +# from the addon's _enter_tree. +# +# #### Parameters +# - plugin: the plugin that registers +# - manager_class: Path to the manager class script +# +# *Returns* a boolean value indicating whether the dialog manager was registered +static func register_dialog_manager(plugin: EditorPlugin, manager_class: String) -> bool: + if not plugin.get_editor_interface().is_plugin_enabled( + Escoria.ESCORIA_CORE_PLUGIN_NAME + ): + push_error("Escoria Core must be enabled.") + return false + + var dialog_managers: Array = ESCProjectSettingsManager.get_setting( + ESCProjectSettingsManager.DIALOG_MANAGERS + ) + + if manager_class in dialog_managers: + return true + + dialog_managers.push_back(manager_class) + + ESCProjectSettingsManager.set_setting( + ESCProjectSettingsManager.DIALOG_MANAGERS, + dialog_managers + ) + + return true + +# Deregister a dialog manager addon +# +# #### Parameters +# - manager_class: Path to the manager class script +static func deregister_dialog_manager(manager_class: String): + var dialog_managers: Array = ESCProjectSettingsManager.get_setting( + ESCProjectSettingsManager.DIALOG_MANAGERS + ) + + # If the dialog manager we're removing in not in the registered list, return quietly. + if not manager_class in dialog_managers: + return + + dialog_managers.erase(manager_class) + + ESCProjectSettingsManager.set_setting( + ESCProjectSettingsManager.DIALOG_MANAGERS, + dialog_managers + ) 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 index 46521268..7ac3a088 100644 --- a/addons/escoria-core/game/core-scripts/resources/esc_resource_descriptor.gd +++ b/addons/escoria-core/game/core-scripts/resources/esc_resource_descriptor.gd @@ -1,5 +1,5 @@ # Describes a resource for use in the resource cache -extends Object +extends Resource class_name ESCResourceDescriptor 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 19487ed4..270d473d 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 @@ -76,9 +76,9 @@ func get_saves_list() -> Dictionary: var save_game_res: Resource = load(save_path) if save_game_res == null: - escoria.logger.report_warnings( - "esc_save_manager.gd", - ["Savegame file %s is corrupted. Skipping." % save_path] + escoria.logger.warn( + self, + "Savegame file %s is corrupted. Skipping." % save_path ) else: var save_game_data = { @@ -91,12 +91,10 @@ func get_saves_list() -> Dictionary: if matches != null and matches.get_string("slotnumber") != null: saves[int(matches.get_string("slotnumber"))] = save_game_data else: - escoria.logger.report_warnings( - "esc_save_manager.gd", - [ - "Savegame file %s contains valid data but doesn't match filename format %s. Skipping." - % [save_path, regex.get_pattern()] - ] + escoria.logger.warn( + self, + "Savegame file %s contains valid data but doesn't match filename format %s. Skipping." + % [save_path, regex.get_pattern()] ) nextfile = dirsave.get_next() return saves @@ -121,8 +119,9 @@ func save_game_exists(id: int) -> bool: func save_game(id: int, p_savename: String): if not save_enabled: escoria.logger.debug( - "esc_save_manager.gd", - ["Save requested while saving is not possible. Save canceled."]) + self, + "Save requested while saving is not possible. Save cancelled." + ) return var save_game := _do_save_game(p_savename) @@ -134,9 +133,9 @@ func save_game(id: int, p_savename: String): var save_path = save_folder.plus_file(SAVE_NAME_TEMPLATE % id) var error: int = ResourceSaver.save(save_path, save_game) if error != OK: - escoria.logger.report_errors( - "esc_save_manager.gd", - ["There was an issue writing the save %s to %s" % [id, save_path]] + escoria.logger.error( + self, + "There was an issue writing savegame number %s to %s." % [id, save_path] ) @@ -153,8 +152,8 @@ func save_game_crash(): var save_game := _do_save_game("Crash %s" % datetime_string) - var save_file_path: String = escoria.project_settings_manager.get_setting( - escoria.project_settings_manager.LOG_FILE_PATH + var save_file_path: String = ESCProjectSettingsManager.get_setting( + ESCProjectSettingsManager.LOG_FILE_PATH ) crash_savegame_filename = save_file_path.plus_file( CRASH_SAVE_NAME_TEMPLATE % [ @@ -167,10 +166,11 @@ func save_game_crash(): var error: int = ResourceSaver.save(crash_savegame_filename, save_game) if error != OK: - escoria.logger.report_errors( - "esc_save_manager.gd", - ["There was an issue writing the crash save to %s" - % crash_savegame_filename]) + escoria.logger.error( + self, + "There was an issue writing the crash save to %s." + % crash_savegame_filename + ) return error @@ -185,8 +185,8 @@ func _do_save_game(p_savename: String) -> ESCSaveGame: plugin_config.load("res://addons/escoria-core/plugin.cfg") save_game.escoria_version = plugin_config.get_value("plugin", "version") - save_game.game_version = escoria.project_settings_manager.get_setting( - escoria.project_settings_manager.GAME_VERSION + save_game.game_version = ESCProjectSettingsManager.get_setting( + ESCProjectSettingsManager.GAME_VERSION ) save_game.name = p_savename @@ -216,14 +216,16 @@ func load_game(id: int): var save_file_path: String = save_folder.plus_file(SAVE_NAME_TEMPLATE % id) var file: File = File.new() if not file.file_exists(save_file_path): - escoria.logger.report_errors( - "esc_save_manager.gd:load_game()", - ["Save file %s doesn't exist" % save_file_path]) + escoria.logger.error( + self, + "Save file %s doesn't exist." % save_file_path + ) return escoria.logger.info( - "esc_save_manager.gd:load_game()", - ["Loading savegame %s" % str(id)]) + self, + "Loading savegame %s." % str(id) + ) var save_game: ESCSaveGame = ResourceLoader.load(save_file_path) @@ -243,21 +245,21 @@ func load_game(id: int): ) # Migrate savegame through game versions - if escoria.project_settings_manager.get_setting( - escoria.project_settings_manager.GAME_VERSION + if ESCProjectSettingsManager.get_setting( + ESCProjectSettingsManager.GAME_VERSION ) != save_game.game_version \ - and escoria.project_settings_manager.get_setting( - escoria.project_settings_manager.GAME_MIGRATION_PATH + and ESCProjectSettingsManager.get_setting( + ESCProjectSettingsManager.GAME_MIGRATION_PATH ) != "": var migration_manager: ESCMigrationManager = ESCMigrationManager.new() save_game = migration_manager.migrate( save_game, save_game.game_version, - escoria.project_settings_manager.get_setting( - escoria.project_settings_manager.GAME_VERSION + ESCProjectSettingsManager.get_setting( + ESCProjectSettingsManager.GAME_VERSION ), - escoria.project_settings_manager.get_setting( - escoria.project_settings_manager.GAME_MIGRATION_PATH + ESCProjectSettingsManager.get_setting( + ESCProjectSettingsManager.GAME_MIGRATION_PATH ) ) @@ -271,8 +273,8 @@ func load_game(id: int): "%s %s out" % [ _transition.get_command_name(), - escoria.project_settings_manager.get_setting( - escoria.project_settings_manager.DEFAULT_TRANSITION + ESCProjectSettingsManager.get_setting( + ESCProjectSettingsManager.DEFAULT_TRANSITION )] ) ) @@ -391,8 +393,8 @@ func load_game(id: int): "%s %s in" % [ _transition.get_command_name(), - escoria.project_settings_manager.get_setting( - escoria.project_settings_manager.DEFAULT_TRANSITION + ESCProjectSettingsManager.get_setting( + ESCProjectSettingsManager.DEFAULT_TRANSITION )] ) ) @@ -402,9 +404,7 @@ func load_game(id: int): escoria.set_game_paused(false) escoria.event_manager.queue_event(load_event) - escoria.logger.debug( - "esc_save_manager.gd:load_game()", - ["Load event queued."]) + escoria.logger.debug(self, "Load event queued.") # Save the game settings in the settings file. @@ -432,9 +432,9 @@ func save_settings(): var save_path = settings_folder.plus_file(SETTINGS_TEMPLATE) var error: int = ResourceSaver.save(save_path, settings_res) if error != OK: - escoria.logger.report_errors( + escoria.logger.error( "esc_save_manager.gd:save_settings()", - ["There was an issue writing settings %s" % save_path]) + ["There was an issue writing settings file %s." % save_path]) # Load the game settings from the settings file @@ -444,10 +444,11 @@ func load_settings() -> Resource: settings_folder.plus_file(SETTINGS_TEMPLATE) var file: File = File.new() if not file.file_exists(save_settings_path): - escoria.logger.report_warnings( - "esc_save_manager.gd:load_settings()", - ["Settings file %s doesn't exist" % save_settings_path, - "Setting default settings."]) + escoria.logger.warn( + self, + "Settings file %s doesn't exist. Using default settings." + % save_settings_path + ) save_settings() return load(save_settings_path) diff --git a/addons/escoria-core/game/core-scripts/utils/esc_utils.gd b/addons/escoria-core/game/core-scripts/utils/esc_utils.gd index 60a2e6dc..05f5ad63 100644 --- a/addons/escoria-core/game/core-scripts/utils/esc_utils.gd +++ b/addons/escoria-core/game/core-scripts/utils/esc_utils.gd @@ -1,5 +1,5 @@ # A set of common utilities -extends Object +extends Reference class_name ESCUtils @@ -9,7 +9,7 @@ class_name ESCUtils # # - rad_angle: Angle in radians # **Returns** Degrees -func get_deg_from_rad(rad_angle: float): +static func get_deg_from_rad(rad_angle: float): var deg = rad2deg(rad_angle) if deg >= 360.0: deg = clamp(deg, 0.0, 360.0) @@ -25,7 +25,7 @@ func get_deg_from_rad(rad_angle: float): # - re_match: The RegExMatch object # - group: The name of the group # **Returns** The value of the named regex group in the match -func get_re_group(re_match: RegExMatch, group: String) -> String: +static func get_re_group(re_match: RegExMatch, group: String) -> String: if group in re_match.names: return re_match.strings[re_match.names[group]] else: @@ -39,7 +39,7 @@ func get_re_group(re_match: RegExMatch, group: String) -> String: # - value: The original value # - type_hint: The type it should be # **Returns** The typed value according to the type inference -func get_typed_value(value: String, type_hint = []): +static func get_typed_value(value: String, type_hint = []): var regex_bool = RegEx.new() regex_bool.compile("^true|false$") var regex_float = RegEx.new() @@ -68,7 +68,7 @@ func get_typed_value(value: String, type_hint = []): # # - value: String to work on # **Returns** the string with sanitized whitespaces -func sanitize_whitespace(value: String) -> String: +static func sanitize_whitespace(value: String) -> String: var tab_regex = RegEx.new() tab_regex.compile("\\t") var double_regex = RegEx.new() diff --git a/addons/escoria-core/game/esc_autoload.gd b/addons/escoria-core/game/esc_autoload.gd new file mode 100644 index 00000000..c6104787 --- /dev/null +++ b/addons/escoria-core/game/esc_autoload.gd @@ -0,0 +1,195 @@ +# This is Escoria's singleton script. +# It holds accessors to some utils, such as Escoria's logger. + +extends Node + + +# Signal sent when Escoria is paused +signal paused + +# Signal sent when Escoria is resumed from pause +signal resumed + + +# Current game state +# * DEFAULT: Common game function +# * DIALOG: Game is playing a dialog +# * WAIT: Game is waiting +enum GAME_STATE { + DEFAULT, + DIALOG, + WAIT +} + + +# Audio bus indices. +const BUS_MASTER = "Master" +const BUS_SFX = "SFX" +const BUS_MUSIC = "Music" +const BUS_SPEECH = "Speech" + +# Path to camera scene +const CAMERA_SCENE_PATH = "res://addons/escoria-core/game/scenes/camera_player/camera.tscn" + + +# Logger class +const Logger = preload("res://addons/escoria-core/game/esc_logger.gd") + + +# Logger instance +var logger = Logger.ESCLoggerFile.new() + +# ESC Compiler +var esc_compiler = ESCCompiler.new() + +# ESC Object Manager +var object_manager = ESCObjectManager.new() + +# ESC Room Manager +var room_manager = ESCRoomManager.new() + +# Terrain of the current room +var room_terrain + +# The inventory manager instance +var inventory_manager: ESCInventoryManager + +# The action manager instance +var action_manager: ESCActionManager + +# ESC Event manager instance +var event_manager: ESCEventManager + +# ESC globals registry instance +var globals_manager: ESCGlobalsManager + +# ESC command registry instance +var command_registry: ESCCommandRegistry + +# Resource cache handler +var resource_cache: ESCResourceCache + +# Dialog player instantiator. This instance is called directly for dialogs. +var dialog_player: ESCDialogPlayer + +# Inventory scene +var inventory + +# These are settings that the player can affect and save/load later +var settings: ESCSaveSettings + +# The main scene +var main + +# The escoria inputs manager +var inputs_manager: ESCInputsManager + +# Savegames and settings manager +var save_manager: ESCSaveManager + +# The game scene loaded +var game_scene: ESCGame + +# The main player camera +var player_camera: ESCCamera + +# The compiled start script loaded from ProjectSettings +# escoria/main/game_start_script +var start_script: ESCScript + +# Whether we ran a room directly from editor, not a full game +var is_direct_room_run: bool = false + +# Whether we're quitting the game +var is_quitting: bool = false + + +# The game resolution +onready var game_size = get_viewport().size + +# The current state of the game +onready var current_state = GAME_STATE.DEFAULT + + +# Ready function +func _ready(): + # We check if we run the full game or a room scene directly + if not get_tree().current_scene is ESCMain: + # Running a room scene. We need to instantiate the main scene ourselves + # so that the Escoria scene is created and managers are instanced as well. + is_direct_room_run = true + var main_scene = preload("res://addons/escoria-core/game/main_scene.tscn").instance() + add_child(main_scene) + + +# Get the Escoria node. That node gives access to the Escoria scene that's +# instanced by the main_scene (if full game is run) or by this autoload if +# room is run directly. +func get_escoria(): + # We check if we run the full game or a room scene directly + if get_tree().current_scene is ESCMain: + return get_node("/root/main_scene").escoria_node + else: + return get_node("main_scene").escoria_node + + +# Pauses or unpause the game +# +# #### Parameters +# - p_paused: if true, pauses the game. If false, unpauses the game. +func set_game_paused(p_paused: bool): + if p_paused: + emit_signal("paused") + else: + emit_signal("resumed") + + var scene_tree = get_tree() + + if is_instance_valid(scene_tree): + scene_tree.paused = p_paused + + +# Apply the loaded settings +# +# #### Parameters +# +# * p_settings: Loaded settings +func apply_settings(p_settings: ESCSaveSettings) -> void: + if not Engine.is_editor_hint(): + escoria.logger.info(self, "******* settings loaded") + if p_settings != null: + settings = p_settings + else: + settings = ESCSaveSettings.new() + + AudioServer.set_bus_volume_db( + AudioServer.get_bus_index(BUS_MASTER), + linear2db(settings.master_volume) + ) + AudioServer.set_bus_volume_db( + AudioServer.get_bus_index(BUS_SFX), + linear2db(settings.sfx_volume) + ) + AudioServer.set_bus_volume_db( + AudioServer.get_bus_index(BUS_MUSIC), + linear2db(settings.music_volume) + ) + AudioServer.set_bus_volume_db( + AudioServer.get_bus_index(BUS_SPEECH), + linear2db(settings.speech_volume) + ) + TranslationServer.set_locale(settings.text_lang) + + game_scene.apply_custom_settings(settings.custom_settings) + + +# Called from main menu's "new game" button +func new_game(): + get_escoria().new_game() + + +# Called from main menu's "quit" button +func quit(): + is_quitting = true + get_escoria().quit() + diff --git a/addons/escoria-core/game/inputs_manager.gd b/addons/escoria-core/game/esc_inputs_manager.gd similarity index 89% rename from addons/escoria-core/game/inputs_manager.gd rename to addons/escoria-core/game/esc_inputs_manager.gd index 573df471..cef54105 100644 --- a/addons/escoria-core/game/inputs_manager.gd +++ b/addons/escoria-core/game/esc_inputs_manager.gd @@ -1,6 +1,6 @@ # Escoria inputs manager # Catches, handles and distributes input events for the game -extends Node +extends Resource class_name ESCInputsManager @@ -166,7 +166,10 @@ func clear_stack(): # - position: Position of the click func _on_left_click_on_bg(position: Vector2) -> void: if input_mode == INPUT_ALL and hotspot_focused.empty(): - escoria.logger.info("Left click on background at ", [str(position)]) + escoria.logger.info( + self, + "Left click on background at %s." % str(position) + ) escoria.main.current_scene.game.left_click_on_bg(position) @@ -178,7 +181,8 @@ func _on_left_click_on_bg(position: Vector2) -> void: func _on_double_left_click_on_bg(position: Vector2) -> void: if input_mode == INPUT_ALL and hotspot_focused.empty(): escoria.logger.info( - "Double left click on background at %s" % str(position) + self, + "Double left click on background at %s." % str(position) ) escoria.main.current_scene.game.left_double_click_on_bg(position) @@ -190,7 +194,10 @@ func _on_double_left_click_on_bg(position: Vector2) -> void: # - position: Position of the click func _on_right_click_on_bg(position: Vector2) -> void: if input_mode == INPUT_ALL and hotspot_focused.empty(): - escoria.logger.info("Right click on background at ", [str(position)]) + escoria.logger.info( + self, + "Right click on background at %s." % str(position) + ) escoria.main.current_scene.game.right_click_on_bg(position) @@ -205,7 +212,8 @@ func _on_mouse_left_click_inventory_item( event: InputEvent ) -> void: escoria.logger.info( - "Inventory item left clicked %s " % inventory_item_global_id + self, + "Inventory item %s left clicked." % inventory_item_global_id ) escoria.main.current_scene.game.left_click_on_inventory_item( inventory_item_global_id, @@ -225,7 +233,8 @@ func _on_mouse_right_click_inventory_item( ) -> void: if input_mode == INPUT_ALL: escoria.logger.info( - "Inventory item right clicked %s" % inventory_item_global_id + self, + "Inventory item %s right clicked." % inventory_item_global_id ) escoria.main.current_scene.game.right_click_on_inventory_item( inventory_item_global_id, @@ -245,7 +254,8 @@ func _on_mouse_double_left_click_inventory_item( ) -> void: if input_mode == INPUT_ALL: escoria.logger.info( - "Inventory item double left clicked %s" % inventory_item_global_id + self, + "Inventory item %s double left clicked." % inventory_item_global_id ) escoria.main.current_scene.game.left_double_click_on_inventory_item( inventory_item_global_id, @@ -261,7 +271,8 @@ func _on_mouse_double_left_click_inventory_item( # that is hovered func _on_mouse_entered_inventory_item(inventory_item_global_id: String) -> void: escoria.logger.info( - "Inventory item focused %s" % inventory_item_global_id + self, + "Inventory item %s focused." % inventory_item_global_id ) escoria.main.current_scene.game.inventory_item_focused( inventory_item_global_id @@ -270,7 +281,10 @@ func _on_mouse_entered_inventory_item(inventory_item_global_id: String) -> void: # The mouse exited an inventory item func _on_mouse_exited_inventory_item() -> void: - escoria.logger.info("Inventory item unfocused") + escoria.logger.info( + self, + "Inventory item unfocused." + ) escoria.main.current_scene.game.inventory_item_unfocused() @@ -280,7 +294,10 @@ func _on_mouse_exited_inventory_item() -> void: # # - item: The Escoria item hovered func _on_mouse_entered_item(item: ESCItem) -> void: - escoria.logger.info("Item focused: ", [item.global_id]) + escoria.logger.info( + self, + "Item focused: %s" % item.global_id + ) _clean_hover_stack() if not hover_stack.empty(): @@ -301,7 +318,10 @@ func _on_mouse_entered_item(item: ESCItem) -> void: # # - item: The Escoria item hovered func _on_mouse_exited_item(item: ESCItem) -> void: - escoria.logger.info("Item unfocused: ", [item.global_id]) + escoria.logger.info( + self, + "Item unfocused: %s" % item.global_id + ) _hover_stack_erase_item(item) if hover_stack.empty(): hotspot_focused = "" @@ -320,7 +340,10 @@ func _on_mouse_exited_item(item: ESCItem) -> void: func _on_mouse_left_clicked_item(item: ESCItem, event: InputEvent) -> void: if input_mode == INPUT_ALL: if hover_stack.empty() or hover_stack.back() == item: - escoria.logger.info("Item left clicked", [item.global_id, event]) + escoria.logger.info( + self, + "Item %s left clicked with event %s." % [item.global_id, event] + ) hotspot_focused = item.global_id escoria.main.current_scene.game.left_click_on_item( item.global_id, @@ -339,7 +362,10 @@ func _on_mouse_left_double_clicked_item( event: InputEvent ) -> void: if input_mode == INPUT_ALL: - escoria.logger.info("Item left double clicked", [item.global_id, event]) + escoria.logger.info( + self, + "Item %s left double clicked with event %s." % [item.global_id, event] + ) hotspot_focused = item.global_id escoria.main.current_scene.game.left_double_click_on_item( item.global_id, @@ -355,7 +381,10 @@ func _on_mouse_left_double_clicked_item( # - event: The input event from the click func _on_mouse_right_clicked_item(item: ESCItem, event: InputEvent) -> void: if input_mode == INPUT_ALL: - escoria.logger.info("Item right clicked", [item.global_id, event]) + escoria.logger.info( + self, + "Item %s right clicked with event %s." % [item.global_id, event] + ) hotspot_focused = item.global_id escoria.main.current_scene.game.right_click_on_item( item.global_id, diff --git a/addons/escoria-core/game/esc_logger.gd b/addons/escoria-core/game/esc_logger.gd new file mode 100644 index 00000000..52077ad7 --- /dev/null +++ b/addons/escoria-core/game/esc_logger.gd @@ -0,0 +1,195 @@ +class ESCLoggerBase: + # Perform emergency savegame + signal perform_emergency_savegame + + # Valid log levels + enum { LOG_ERROR, LOG_WARNING, LOG_INFO, LOG_DEBUG, LOG_TRACE } + + # Log file format + const LOG_FILE_FORMAT: String = "log_%s_%s.log" + + # A map of log level names to log level ints + var _level_map: Dictionary = { + "ERROR": LOG_ERROR, + "WARNING": LOG_WARNING, + "INFO": LOG_INFO, + "DEBUG": LOG_DEBUG, + "TRACE": LOG_TRACE, + } + + # Configured log level + var _log_level: int + + + # Constructor + func _init(): + _log_level = _level_map[ESCProjectSettingsManager.get_setting( + ESCProjectSettingsManager.LOG_LEVEL + ).to_upper()] + + + func formatted_message(context: String, msg: String, letter: String) -> String: + return "ESC ({0}) {1} {2}: {3}".format([_formatted_date(), letter, context, msg]) + + + func trace(owner: Object, msg: String): + var context = owner.get_script().resource_path.get_file() + print(formatted_message(context, msg, "T")) + + + # Debug log + func debug(owner: Object, msg: String): + var context = owner.get_script().resource_path.get_file() + print(formatted_message(context, msg, "D")) + + + func info(owner: Object, msg: String): + var context = owner.get_script().resource_path.get_file() + print(formatted_message(context, msg, "I")) + + + # Warning log + func warn(owner: Object, msg: String): + var context = owner.get_script().resource_path.get_file() + print(formatted_message(context, msg, "W")) + push_warning(formatted_message(context, msg, "W")) + if ESCProjectSettingsManager.get_setting( + ESCProjectSettingsManager.TERMINATE_ON_WARNINGS + ): + assert(false) + escoria.get_tree().quit() + + + # Error log + func error(owner: Object, msg: String): + var context = owner.get_script().resource_path.get_file() + printerr(formatted_message(context, msg, "E")) + push_error(formatted_message(context, msg, "E")) + if ESCProjectSettingsManager.get_setting( + ESCProjectSettingsManager.TERMINATE_ON_ERRORS + ): + assert(false) + escoria.get_tree().quit() + + + func get_log_level() -> int: + return _log_level + + func _formatted_date(): + var info = OS.get_datetime() + info["year"] = "%04d" % info["year"] + info["month"] = "%02d" % info["month"] + info["day"] = "%02d" % info["day"] + info["hour"] = "%02d" % info["hour"] + info["minute"] = "%02d" % info["minute"] + info["second"] = "%02d" % info["second"] + return "{year}-{month}-{day}T{hour}:{minute}:{second}".format(info) + + +# A logger that logs to the terminal and to a log file. +class ESCLoggerFile extends ESCLoggerBase: + # Log file handler + var log_file: File + + # Constructor + 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( + ESCProjectSettingsManager.LOG_FILE_PATH + ) + var date = OS.get_datetime() + log_file_path = log_file_path.plus_file(LOG_FILE_FORMAT % [ + str(date["year"]) + str(date["month"]) + str(date["day"]), + str(date["hour"]) + str(date["minute"]) + str(date["second"]) + ]) + log_file.open( + log_file_path, + File.WRITE + ) + + func trace(owner: Object, msg: String): + if _log_level >= LOG_TRACE: + _log_to_file(owner, msg, "T") + .trace(owner, msg) + + # Debug log + func debug(owner: Object, msg: String): + if _log_level >= LOG_DEBUG: + _log_to_file(owner, msg, "D") + .debug(owner, msg) + + func info(owner: Object, msg: String): + if _log_level >= LOG_INFO: + _log_to_file(owner, msg, "I") + .info(owner, msg) + + # Warning log + func warn(owner: Object, msg: String): + if _log_level >= LOG_WARNING: + _log_to_file(owner, msg, "W") + if ESCProjectSettingsManager.get_setting( + ESCProjectSettingsManager.TERMINATE_ON_WARNINGS + ): + _log_stack_trace_to_file(owner) + print_stack() + close_logs() + .warn(owner, msg) + + # Error log + func error(owner: Object, msg: String): + if _log_level >= LOG_ERROR: + _log_to_file(owner, msg, "E") + if ESCProjectSettingsManager.get_setting( + ESCProjectSettingsManager.TERMINATE_ON_ERRORS + ): + _log_stack_trace_to_file(owner) + print_stack() + close_logs() + .error(owner, msg) + + + # Close the log file cleanly + func close_logs(): + print("Closing logs peacefully.") + _log_line_to_file("Closing logs peacefully.") + log_file.close() + + + func _log_to_file(owner: Object, msg: String, letter: String): + if log_file.is_open(): + var context = "" + if owner != null: + context = owner.get_script().resource_path.get_file() + log_file.store_string(formatted_message(context, msg, letter) + "\n") + + func _log_line_to_file(msg: String): + if log_file.is_open(): + log_file.store_string(msg + "\n") + + func _log_stack_trace_to_file(owner: Object): + var frame_number = 0 + for stack in get_stack().slice(2, get_stack().size()): + _log_line_to_file( + "Frame %s - %s:%s in function '%s'" % [ + str(frame_number), + stack["source"], + stack["line"], + stack["function"], + ] + ) + frame_number += 1 + + +# A simple logger that logs to terminal using debug() function +class ESCLoggerVerbose extends ESCLoggerBase: + func _init(): + pass + + func debug(owner: Object, msg: String): + var context = owner.get_script().resource_path.get_file() + print(context, ": ", msg) + diff --git a/addons/escoria-core/game/project_settings_manager.gd b/addons/escoria-core/game/esc_project_settings_manager.gd similarity index 91% rename from addons/escoria-core/game/project_settings_manager.gd rename to addons/escoria-core/game/esc_project_settings_manager.gd index 3f910af8..7bcdab6c 100644 --- a/addons/escoria-core/game/project_settings_manager.gd +++ b/addons/escoria-core/game/esc_project_settings_manager.gd @@ -1,5 +1,5 @@ # Registers and allows access to Escoria-specific project settings. -extends Node +extends Resource class_name ESCProjectSettingsManager @@ -75,14 +75,13 @@ const MAX_TIME_TO_DISAPPEAR = "%s/%s/max_time_to_disappear" % [_ESCORIA_SETTINGS # - 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) +static func register_setting(name: String, default, info: Dictionary) -> void: + ProjectSettings.set_setting( + name, + default + ) + info.name = name + ProjectSettings.add_property_info(info) # Retrieves the specified project setting. @@ -92,11 +91,10 @@ func register_setting(name: String, default, info: Dictionary) -> void: # - key: Project setting name. # # *Returns* the value of the project setting located with key. -func get_setting(key: String): +static 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] - ) + push_error("Parameter %s is not set!" % key) + assert(false) return ProjectSettings.get_setting(key) @@ -107,7 +105,7 @@ func get_setting(key: String): # # - key: Project setting name. # - value: Project setting value. -func set_setting(key: String, value) -> void: +static func set_setting(key: String, value) -> void: ProjectSettings.set_setting(key, value) @@ -118,5 +116,5 @@ func set_setting(key: String, value) -> void: # - key: Project setting name. # # *Returns* true iff the project setting exists. -func has_setting(key: String) -> bool: +static func has_setting(key: String) -> bool: return ProjectSettings.has_setting(key) diff --git a/addons/escoria-core/game/escoria.gd b/addons/escoria-core/game/escoria.gd index 16a4fb2d..124a5717 100644 --- a/addons/escoria-core/game/escoria.gd +++ b/addons/escoria-core/game/escoria.gd @@ -3,166 +3,98 @@ tool extends Node class_name Escoria - -# Signal sent when Escoria is paused -signal paused - -# Signal sent when Escoria is resumed from pause -signal resumed +# Signal sent when pause menu has to be displayed +signal request_pause_menu -# Current game state -# * DEFAULT: Common game function -# * DIALOG: Game is playing a dialog -# * WAIT: Game is waiting -enum GAME_STATE { - DEFAULT, - DIALOG, - WAIT -} +# Name of the Escoria core plugin +const ESCORIA_CORE_PLUGIN_NAME: String = "escoria-core" -# Audio bus indices. -const BUS_MASTER = "Master" -const BUS_SFX = "SFX" -const BUS_MUSIC = "Music" -const BUS_SPEECH = "Speech" - -const CAMERA_SCENE_PATH = "res://addons/escoria-core/game/scenes/camera_player/camera.tscn" - - -# Logger used -var logger: ESCLogger - -# Several utilities -var utils: ESCUtils - -# The inventory manager instance -var inventory_manager: ESCInventoryManager - -# The action manager instance -var action_manager: ESCActionManager - -# ESC compiler instance -var esc_compiler: ESCCompiler - -# ESC Event manager instance -var event_manager: ESCEventManager - -# ESC globals registry instance -var globals_manager: ESCGlobalsManager - -# ESC room manager instance -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 - -# Resource cache handler -var resource_cache: ESCResourceCache - -# Terrain of the current room -var room_terrain - -# Dialog player instantiator. This instance is called directly for dialogs. -var dialog_player: ESCDialogPlayer - -# Inventory scene -var inventory - -# These are settings that the player can affect and save/load later -var settings: ESCSaveSettings - -# 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 - -# Savegames and settings manager -var save_manager: ESCSaveManager - -# The game scene loaded -var game_scene: ESCGame - -# The main player camera -var player_camera: ESCCamera - -# The compiled start script loaded from ProjectSettings -# escoria/main/game_start_script -var start_script: ESCScript -# Initialize various objects func _init(): - self.logger = ESCLogger.new() - self.utils = ESCUtils.new() - self.inventory_manager = ESCInventoryManager.new() - self.action_manager = ESCActionManager.new() - self.event_manager = ESCEventManager.new() - self.globals_manager = ESCGlobalsManager.new() - self.add_child(self.event_manager) - self.object_manager = ESCObjectManager.new() - self.command_registry = ESCCommandRegistry.new() - self.esc_compiler = ESCCompiler.new() - self.resource_cache = ESCResourceCache.new() - self.resource_cache.start() - self.save_manager = ESCSaveManager.new() - self.inputs_manager = ESCInputsManager.new() - self.room_manager = ESCRoomManager.new() - self.project_settings_manager = ESCProjectSettingsManager.new() + escoria.inventory_manager = ESCInventoryManager.new() + escoria.action_manager = ESCActionManager.new() + escoria.event_manager = ESCEventManager.new() + escoria.globals_manager = ESCGlobalsManager.new() + add_child(escoria.event_manager) + escoria.object_manager = ESCObjectManager.new() + escoria.command_registry = ESCCommandRegistry.new() + escoria.resource_cache = ESCResourceCache.new() + escoria.resource_cache.start() + escoria.save_manager = ESCSaveManager.new() + escoria.inputs_manager = ESCInputsManager.new() + escoria.settings = ESCSaveSettings.new() - settings = ESCSaveSettings.new() - - if self.project_settings_manager.get_setting(self.project_settings_manager.GAME_SCENE) == "": - logger.report_errors("escoria.gd", - ["Project setting '%s' is not set!" % self.project_settings_manager.GAME_SCENE] + if ESCProjectSettingsManager.get_setting( + ESCProjectSettingsManager.GAME_SCENE + ).empty(): + escoria.logger.error( + self, + "Project setting '%s' is not set!" % ESCProjectSettingsManager.GAME_SCENE ) else: - game_scene = resource_cache.get_resource( - self.project_settings_manager.get_setting(self.project_settings_manager.GAME_SCENE) + escoria.game_scene = escoria.resource_cache.get_resource( + ESCProjectSettingsManager.get_setting(ESCProjectSettingsManager.GAME_SCENE) ).instance() - print("ESC {0}".format([get_script().get_path()])) - # Load settings func _ready(): _handle_direct_scene_run() - settings = save_manager.load_settings() - apply_settings(settings) - room_manager.register_reserved_globals() - inputs_manager.register_core() - if self.project_settings_manager.get_setting(self.project_settings_manager.GAME_START_SCRIPT).empty(): - logger.report_errors("escoria.gd", - [ - "Project setting '%s' is not set!" % self.project_settings_manager.GAME_START_SCRIPT - ]) - start_script = self.esc_compiler.load_esc_file( - self.project_settings_manager.get_setting(self.project_settings_manager.GAME_START_SCRIPT) + escoria.settings = escoria.save_manager.load_settings() + escoria.apply_settings(escoria.settings) + escoria.room_manager.register_reserved_globals() + escoria.inputs_manager.register_core() + if ESCProjectSettingsManager.get_setting( + ESCProjectSettingsManager.GAME_START_SCRIPT + ).empty(): + escoria.logger.error( + self, + "Project setting '%s' is not set!" + % ESCProjectSettingsManager.GAME_START_SCRIPT + ) + escoria.start_script = escoria.esc_compiler.load_esc_file( + ESCProjectSettingsManager.get_setting( + ESCProjectSettingsManager.GAME_START_SCRIPT + ) ) + + escoria.main = main + + _perform_plugins_checks() -func _notification(what): +# Verifies that the game is configured with required plugin(s). +# If a required plugin is missing (or disabled) we stop immediately. +func _perform_plugins_checks(): + if ESCProjectSettingsManager.get_setting( + ESCProjectSettingsManager.DIALOG_MANAGERS + ).empty(): + escoria.logger.error( + self, + "No dialog manager configured. Please add a dialog manager plugin." + ) + + +# Manage notifications received from OS +# +# #### Parameters +# - what: the notification constant received (usually defined in MainLoop) +func _notification(what: int): match what: MainLoop.NOTIFICATION_WM_QUIT_REQUEST: escoria.logger.close_logs() + escoria.is_quitting = true get_tree().quit() MainLoop.NOTIFICATION_WM_GO_BACK_REQUEST: escoria.logger.close_logs() + escoria.is_quitting = true get_tree().quit() @@ -173,69 +105,22 @@ func init(): # Don't show the UI until we're ready in order to avoid a sometimes-noticeable # blink. The UI will be "shown" later via a visibility update to the first room. escoria.game_scene.escoria_hide_ui() - 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, self.event_manager.EVENT_NEW_GAME) - - -# Apply the loaded settings -# -# #### Parameters -# -# * p_settings: Loaded settings -func apply_settings(p_settings: ESCSaveSettings) -> void: - if not Engine.is_editor_hint(): - logger.info("******* settings loaded") - if p_settings != null: - settings = p_settings - else: - settings = ESCSaveSettings.new() - - AudioServer.set_bus_volume_db( - AudioServer.get_bus_index(BUS_MASTER), - linear2db(settings.master_volume) - ) - AudioServer.set_bus_volume_db( - AudioServer.get_bus_index(BUS_SFX), - linear2db(settings.sfx_volume) - ) - AudioServer.set_bus_volume_db( - AudioServer.get_bus_index(BUS_MUSIC), - linear2db(settings.music_volume) - ) - AudioServer.set_bus_volume_db( - AudioServer.get_bus_index(BUS_SPEECH), - linear2db(settings.speech_volume) - ) - TranslationServer.set_locale(settings.text_lang) - - game_scene.apply_custom_settings(settings.custom_settings) + run_event_from_script(escoria.start_script, escoria.event_manager.EVENT_INIT) + pass # Input function to manage specific input keys -func _input(event): - 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() - - -# Pauses or unpause the game # # #### Parameters -# - p_paused: if true, pauses the game. If false, unpauses the game. -func set_game_paused(p_paused: bool): - if p_paused: - emit_signal("paused") - else: - emit_signal("resumed") +# - event: the input event to manage. +func _input(event: InputEvent): + if InputMap.has_action(ESCInputsManager.ESC_SHOW_DEBUG_PROMPT) \ + and event.is_action_pressed(ESCInputsManager.ESC_SHOW_DEBUG_PROMPT): + main.get_node("layers/debug_layer/esc_prompt_popup").popup() - var scene_tree = get_tree() - - if is_instance_valid(scene_tree): - scene_tree.paused = p_paused + if event.is_action_pressed("ui_cancel"): + emit_signal("request_pause_menu") + pass # Runs the event "event_name" from the "script" ESC script. @@ -246,121 +131,27 @@ func set_game_paused(p_paused: bool): # - event_name: Name of the event to run func run_event_from_script(script: ESCScript, event_name: String): if script == null: - logger.report_errors( - "escoria.gd:run_event_from_script()", - ["Requested action %s on unloaded script %s" % [event_name, script], - "Please load the ESC script using esc_compiler.load_esc_file()."] + escoria.logger.error( + self, + "Requested action %s on unloaded script %s." % [event_name, script] + + "Please load the ESC script using esc_compiler.load_esc_file()." ) - event_manager.queue_event(script.events[event_name]) - var rc = yield(event_manager, "event_finished") + escoria.event_manager.queue_event(script.events[event_name]) + var rc = yield(escoria.event_manager, "event_finished") while rc[1] != event_name: - rc = yield(event_manager, "event_finished") + rc = yield(escoria.event_manager, "event_finished") if rc[0] != ESCExecution.RC_OK: - self.logger.report_errors( - "Start event of the start script returned unsuccessful: %d" % rc[0], - [] + escoria.logger.error( + self, + "Start event of the start script returned unsuccessful: %d." % rc[0] ) return -# Register a user interface. This should be called in a deferred way -# from the addon's _enter_tree. -# -# #### Parameters -# - game_scene: Path to the game scene extending ESCGame -func register_ui(game_scene: String): - 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 - ]: - logger.report_errors( - "escoria.gd:register_ui()", - [ - "Can't register user interface because %s is registered" % \ - game_scene_setting_value - ] - ) - escoria.project_settings_manager.set_setting( - escoria.project_settings_manager.GAME_SCENE, - game_scene - ) - - -# Deregister a user interface -# -# #### Parameters -# - game_scene: Path to the game scene extending ESCGame -func deregister_ui(game_scene: String): - 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." - ) % game_scene_setting_value - ] - ) - escoria.project_settings_manager.set_setting( - escoria.project_settings_manager.GAME_SCENE, - "" - ) - - -# Register a dialog manager addon. This should be called in a deferred way -# from the addon's _enter_tree. -# -# #### Parameters -# - manager_class: Path to the manager class script -func register_dialog_manager(manager_class: String): - 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 = 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()", - [ - "Dialog manager %s is not registered" % manager_class - ] - ) - return - - dialog_managers.erase(manager_class) - - escoria.project_settings_manager.set_setting( - escoria.project_settings_manager.DIALOG_MANAGERS, - dialog_managers - ) +# Called from escoria autoload to start a new game. +func new_game(): + run_event_from_script(escoria.start_script, escoria.event_manager.EVENT_NEW_GAME) # Function called to quit the game. @@ -370,19 +161,8 @@ func quit(): # Handle anything necessary if the game started a scene directly. func _handle_direct_scene_run() -> void: - var current_scene_root: Node = get_tree().get_current_scene() - - if current_scene_root == null: - # there's no 'current scene' - # e.g. you're opening escoria.tscn from the editor - return - - if current_scene_root.filename == ProjectSettings.get_setting('application/run/main_scene'): - # This is a normal, full-game run, so there's nothing to do. - return - - if current_scene_root is ESCRoom: - escoria.object_manager.set_current_room(current_scene_root) + if escoria.is_direct_room_run: + escoria.object_manager.set_current_room(get_tree().get_current_scene()) # Used by game.gd to determine whether the game scene is ready to take inputs @@ -393,5 +173,5 @@ func _handle_direct_scene_run() -> void: # *Returns* # true if game scene is ready for inputs func is_ready_for_inputs() -> bool: - return escoria.main.current_scene and escoria.main.current_scene.game \ - and escoria.main.current_scene.game.room_ready_for_inputs + return main.current_scene and main.current_scene.game \ + and main.current_scene.game.room_ready_for_inputs diff --git a/addons/escoria-core/game/escoria.tscn b/addons/escoria-core/game/escoria.tscn index bf76e585..fc2eae3d 100644 --- a/addons/escoria-core/game/escoria.tscn +++ b/addons/escoria-core/game/escoria.tscn @@ -3,7 +3,7 @@ [ext_resource path="res://addons/escoria-core/game/main.tscn" type="PackedScene" id=2] [ext_resource path="res://addons/escoria-core/game/escoria.gd" type="Script" id=3] -[node name="escoria" type="Node"] +[node name="escoria_scene" type="Node"] pause_mode = 2 script = ExtResource( 3 ) diff --git a/addons/escoria-core/game/main.gd b/addons/escoria-core/game/main.gd index 558a6e56..77862eca 100644 --- a/addons/escoria-core/game/main.gd +++ b/addons/escoria-core/game/main.gd @@ -31,6 +31,10 @@ func _ready() -> void: $layers/wait_timer.connect("timeout", self, "_on_wait_finished") +func _exit_tree(): + $layers/curtain.remove_child(scene_transition) + scene_transition.queue_free() + # Set current scene # # #### Parameters @@ -38,7 +42,10 @@ func _ready() -> void: # - p_scene: Scene to set func set_scene(p_scene: Node) -> void: if !p_scene: - escoria.logger.report_errors("main", ["Trying to set empty scene"]) + escoria.logger.error( + self, + "Can't change to an empty scene. Please specify the scene name." + ) previous_scene = current_scene @@ -130,13 +137,11 @@ func set_camera_limits(camera_limit_id: int = 0, scene: Node = current_scene) -> var limits = {} var last_available_camera_limit = scene.camera_limits.size() - 1 if camera_limit_id > last_available_camera_limit: - escoria.logger.report_errors( - "main.gd:set_camera_limits()", - [ - "Camera limit %d requested. Last available camera limit is %d." % [ - camera_limit_id, - last_available_camera_limit - ] + escoria.logger.error( + self, + "Camera limit %d requested. Last available camera limit is %d." % [ + camera_limit_id, + last_available_camera_limit ] ) var scene_camera_limits = scene.camera_limits[camera_limit_id] @@ -151,15 +156,16 @@ func set_camera_limits(camera_limit_id: int = 0, scene: Node = current_scene) -> # to stick centered on the background if area.size.x == 0 or area.size.y == 0 \ or area.size < get_viewport().size: - escoria.logger.report_warnings( - "main.gd:set_camera_limits()", - [ - "No limit area! Using viewport." - ] + escoria.logger.warn( + self, + "Defined camera is smaller than the viewport. Using viewport size." ) area.size = get_viewport().size - escoria.logger.info("Setting camera limits from scene ", [area]) + escoria.logger.info( + self, + "Setting camera limits from scene " + area + ) limits = ESCCameraLimits.new( area.position.x, area.position.x + area.size.x, @@ -176,8 +182,8 @@ func set_camera_limits(camera_limit_id: int = 0, scene: Node = current_scene) -> scene_camera_limits.size.y ) escoria.logger.info( - "Setting camera limits from parameter ", - [scene_camera_limits] + self, + "Setting camera limits using configured parameters " + str(scene_camera_limits) ) escoria.object_manager.get_object( diff --git a/addons/escoria-core/game/main.tscn b/addons/escoria-core/game/main.tscn index 1e6901ff..0bb8f378 100644 --- a/addons/escoria-core/game/main.tscn +++ b/addons/escoria-core/game/main.tscn @@ -14,8 +14,6 @@ script = ExtResource( 1 ) [node name="curtain" type="CanvasLayer" parent="layers"] layer = 20 -[node name="menu" type="CanvasLayer" parent="layers"] - [node name="wait_timer" type="Timer" parent="layers"] [node name="debug_layer" type="CanvasLayer" parent="layers"] diff --git a/addons/escoria-core/game/main_scene.gd b/addons/escoria-core/game/main_scene.gd index 32aa9e57..8bd567e9 100644 --- a/addons/escoria-core/game/main_scene.gd +++ b/addons/escoria-core/game/main_scene.gd @@ -1,9 +1,17 @@ # Main_scene is the entry point for Godot Engine. # This scene sets up the main menu scene to load. extends Node +class_name ESCMain + +var escoria_node: Escoria # Start the main menu func _ready(): - escoria.init() - + escoria.logger.info(self, "Escoria starts...") + + escoria_node = preload("res://addons/escoria-core/game/escoria.tscn").instance() + add_child(escoria_node) + + if not escoria.is_direct_room_run: + escoria_node.init() 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 314e3437..cac82075 100644 --- a/addons/escoria-core/game/scenes/camera_player/esc_camera.gd +++ b/addons/escoria-core/game/scenes/camera_player/esc_camera.gd @@ -23,6 +23,12 @@ func _ready(): _tween.connect("tween_all_completed", self, "_target_reached") +func _exit_tree(): + remove_child(_tween) + if is_instance_valid(_tween): + _tween.queue_free() + + # Update the position if the followed target is moving func _process(_delta): if is_instance_valid(_follow_target) and not _tween.is_active() and _follow_target.has_moved(): @@ -103,20 +109,19 @@ func set_target(p_target, p_time : float = 0.0): _resolve_target_and_zoom(p_target) escoria.logger.info( - "Current camera position = %s " % str(self.global_position) + self, + "Current camera position = %s." % str(self.global_position) ) if p_time == 0.0: self.global_position = _target else: if _tween.is_active(): - escoria.logger.report_warnings( - "esc_camera.gd:set_target()", - [ - "Tween is still active: %f/%f" % [ - _tween.tell(), - _tween.get_runtime() - ] + escoria.logger.warn( + self, + "Tween is still active: %f seconds of %f completed." % [ + _tween.tell(), + _tween.get_runtime() ] ) _tween.emit_signal("tween_completed") @@ -140,9 +145,9 @@ func set_target(p_target, p_time : float = 0.0): # - p_time: Number of seconds for the camera to reach the zoom level func set_camera_zoom(p_zoom_level: float, p_time: float): if p_zoom_level <= 0.0: - escoria.logger.report_errors( - "esc_camera.gd:set_camera_zoom()", - ["Tried to set negative or zero zoom level"] + escoria.logger.error( + self, + "Tried to set negative or zero zoom level." ) _zoom_target = Vector2(1, 1) * p_zoom_level @@ -151,13 +156,11 @@ func set_camera_zoom(p_zoom_level: float, p_time: float): self.zoom = _zoom_target else: if _tween.is_active(): - escoria.logger.report_warnings( - "esc_camera.gd:set_camera_zoom()", - [ - "Tween is still active: %f/%f" % [ - _tween.tell(), - _tween.get_runtime() - ] + escoria.logger.warn( + self, + "Tween is still active: %f/%f" % [ + _tween.tell(), + _tween.get_runtime() ] ) _tween.emit_signal("tween_completed") @@ -199,13 +202,11 @@ func push(p_target, p_time: float = 0.0, p_type: int = 0): self.zoom = _zoom_target else: if _tween.is_active(): - escoria.logger.report_warnings( - "esc_camera.gd:push()", - [ - "Tween is still active: %f/%f" % [ - _tween.tell(), - _tween.get_runtime() - ] + escoria.logger.warn( + self, + "Tween is still active: %f seconds of %f completed." % [ + _tween.tell(), + _tween.get_runtime() ] ) _tween.emit_signal("tween_completed", null, null) @@ -251,15 +252,13 @@ func shift(p_target: Vector2, p_time: float, p_type: int): _target = new_pos if _tween.is_active(): - escoria.logger.report_warnings( - "esc_camera.gd:set_camera_zoom()", - [ - "Tween is still active: %f/%f" % [ - _tween.tell(), - _tween.get_runtime() - ] - ] - ) + escoria.logger.warn( + self, + "Tween is still active: %f seconds of %f completed." % [ + _tween.tell(), + _tween.get_runtime() + ] + ) _tween.emit_signal("tween_completed") _tween.interpolate_property( @@ -276,6 +275,3 @@ func shift(p_target: Vector2, p_time: float, p_type: int): func _target_reached(): _tween.stop_all() - - - diff --git a/addons/escoria-core/game/scenes/camera_player/esc_camera_limits.gd b/addons/escoria-core/game/scenes/camera_player/esc_camera_limits.gd index dcdc56dd..b4897464 100644 --- a/addons/escoria-core/game/scenes/camera_player/esc_camera_limits.gd +++ b/addons/escoria-core/game/scenes/camera_player/esc_camera_limits.gd @@ -1,5 +1,5 @@ # Describes a bounding box that limits the camera movement in the scene -extends Object +extends Reference class_name ESCCameraLimits diff --git a/addons/escoria-core/game/scenes/dialogs/esc_dialog_options_chooser.gd b/addons/escoria-core/game/scenes/dialogs/esc_dialog_options_chooser.gd index 6a521ab1..4cb9d424 100644 --- a/addons/escoria-core/game/scenes/dialogs/esc_dialog_options_chooser.gd +++ b/addons/escoria-core/game/scenes/dialogs/esc_dialog_options_chooser.gd @@ -26,9 +26,15 @@ func set_dialog(new_dialog: ESCDialog) -> void: # Show the dialog chooser UI func show_chooser() -> void: - escoria.logger.error("Dialog chooser did not implement the show method.") + escoria.logger.error( + self, + "Dialog chooser does not implement the show method." + ) # Hide the dialog chooser UI func hide_chooser() -> void: - escoria.logger.error("Dialog chooser did not implement the hide method.") + escoria.logger.error( + self, + "Dialog chooser does not implement the hide method." + ) 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 8d975819..27120a8b 100644 --- a/addons/escoria-core/game/scenes/dialogs/esc_dialog_player.gd +++ b/addons/escoria-core/game/scenes/dialogs/esc_dialog_player.gd @@ -62,8 +62,8 @@ func _input(event): # *Returns* The path to the matching voice file func _get_voice_file(key: String, start: String = "") -> String: if start == "": - start = escoria.project_settings_manager.get_setting( - escoria.project_settings_manager.SPEECH_FOLDER + start = ESCProjectSettingsManager.get_setting( + ESCProjectSettingsManager.SPEECH_FOLDER ) var _dir = Directory.new() if _dir.open(start) == OK: @@ -80,8 +80,8 @@ func _get_voice_file(key: String, start: String = "") -> String: else: if file_name == "%s.%s.import" % [ key, - escoria.project_settings_manager.get_setting( - escoria.project_settings_manager.SPEECH_EXTENSION + ESCProjectSettingsManager.get_setting( + ESCProjectSettingsManager.SPEECH_EXTENSION ) ]: return start.plus_file(file_name.trim_suffix(".import")) @@ -98,12 +98,12 @@ func _get_voice_file(key: String, start: String = "") -> String: # - text: Text to say func say(character: String, type: String, text: String) -> void: if type == "": - type = escoria.project_settings_manager.get_setting( - escoria.project_settings_manager.DEFAULT_DIALOG_TYPE + type = ESCProjectSettingsManager.get_setting( + ESCProjectSettingsManager.DEFAULT_DIALOG_TYPE ) is_speaking = true - for _manager_class in escoria.project_settings_manager.get_setting( - escoria.project_settings_manager.DIALOG_MANAGERS + for _manager_class in ESCProjectSettingsManager.get_setting( + ESCProjectSettingsManager.DIALOG_MANAGERS ): if ResourceLoader.exists(_manager_class): var _manager: ESCDialogManager = load(_manager_class).new() @@ -113,22 +113,18 @@ func say(character: String, type: String, text: String) -> void: _dialog_manager = null if _dialog_manager == null: - escoria.logger.report_errors( - "esc_dialog_player.gd:say", - [ - "No dialog manager supports the type %s" % type - ] + escoria.logger.error( + self, + "No dialog manager called %s configured." % type ) _dialog_manager.connect("say_finished", self, "_on_say_finished", [], CONNECT_ONESHOT) var matches = _keytext_regex.search(text) if not matches: - escoria.logger.report_errors( - "esc_dialog_player.gd:say", - [ - "Unexpected text encountered %s" % text - ] + escoria.logger.error( + self, + "Unexpected text encountered : %s." % text ) var key = matches.get_string("key") if matches.get_string("key") != "": @@ -136,11 +132,9 @@ func say(character: String, type: String, text: String) -> void: matches.get_string("key") ) if _speech_resource == "": - escoria.logger.report_warnings( - "esc_dialog_player.gd:say", - [ - "Unable to find voice file with key '%s'." % matches.get_string("key") - ] + escoria.logger.warn( + self, + "Unable to find voice file with key '%s'." % matches.get_string("key") ) else: ( @@ -153,11 +147,9 @@ func say(character: String, type: String, text: String) -> void: # Only update the text if the translated text was found; otherwise, raise # a warning and use the original, untranslated text. if translated_text == matches.get_string("key"): - escoria.logger.report_warnings( - "esc_dialog_player.gd:say", - [ - "Unable to find translation key '%s'. Using untranslated text." % matches.get_string("key") - ] + escoria.logger.warn( + self, + "Unable to find translation key '%s'. Using untranslated text." % matches.get_string("key") ) text = matches.get_string("text") else: @@ -165,8 +157,8 @@ func say(character: String, type: String, text: String) -> void: else: text = matches.get_string("text") - _dialog_manager.say(self, character, text, type) + _dialog_manager.say(self, character, text, type) # Handles the end of a say function after it has emitted say_finished. func _on_say_finished(): @@ -189,15 +181,15 @@ func speedup() -> void: # - dialog: The dialog to start func start_dialog_choices(dialog: ESCDialog, type: String = "simple"): if dialog.options.empty(): - escoria.logger.report_errors( - "esc_dialog_player.gd:start_dialog_choices()", - ["Received answers array was empty."] + escoria.logger.error( + self, + "Received dialog options array was empty." ) var _dialog_chooser_ui: ESCDialogManager = null - for _manager_class in escoria.project_settings_manager.get_setting( - escoria.project_settings_manager.DIALOG_MANAGERS + for _manager_class in ESCProjectSettingsManager.get_setting( + ESCProjectSettingsManager.DIALOG_MANAGERS ): if ResourceLoader.exists(_manager_class): var _manager: ESCDialogManager = load(_manager_class).new() @@ -205,11 +197,9 @@ func start_dialog_choices(dialog: ESCDialog, type: String = "simple"): _dialog_chooser_ui = _manager if _dialog_chooser_ui == null: - escoria.logger.report_errors( - "esc_dialog_player.gd: Unknown chooser type", - [ - "No dialog manager supports the chooser type %s" % type - ] + escoria.logger.error( + self, + "No dialog manager supports the chooser type %s." % type ) _dialog_chooser_ui.choose(self, dialog) diff --git a/addons/escoria-core/game/scenes/inventory/inventory_ui.gd b/addons/escoria-core/game/scenes/inventory/inventory_ui.gd index 9633c40b..16e7d4ce 100644 --- a/addons/escoria-core/game/scenes/inventory/inventory_ui.gd +++ b/addons/escoria-core/game/scenes/inventory/inventory_ui.gd @@ -17,9 +17,9 @@ var items_ids_in_inventory: Dictionary = {} # listen when a global has changed func _ready(): if inventory_ui_container == null or inventory_ui_container.is_empty(): - escoria.logger.report_errors( - self.get_path(), - ["Items container is empty."] + escoria.logger.error( + self, + "Inventory items container is empty." ) return @@ -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" % [ - escoria.project_settings_manager.get_setting( - escoria.project_settings_manager.ITEMS_AUTOREGISTER_PATH + ESCProjectSettingsManager.get_setting( + ESCProjectSettingsManager.ITEMS_AUTOREGISTER_PATH ).trim_suffix("/"), item_id ] @@ -58,11 +58,21 @@ func add_new_item_by_id(item_id: String) -> void: true ) else: - escoria.logger.report_errors( - "inventory_ui.gd:add_new_item_by_id()", - [ - "Item global id '%s' does not exist." % item_id - ] + escoria.logger.error( + self, + ( + "Item global id '%s' is not registered because the item's scene file was not found.\n" + + "Attempted scene file path: %s.\n" + + "Please ensure that the '%s' project setting points at **your inventory items folder** (current is: \"%s\")." + ) + % [ + item_id, + inventory_file, + ESCProjectSettingsManager.ITEMS_AUTOREGISTER_PATH, + ESCProjectSettingsManager.get_setting( + ESCProjectSettingsManager.ITEMS_AUTOREGISTER_PATH + ) + ] ) var inventory_item = ESCInventoryItem.new( @@ -90,7 +100,10 @@ func add_new_item_by_id(item_id: String) -> void: # remove item fromInventory UI using its id set in its scene func remove_item_by_id(item_id: String) -> void: if items_ids_in_inventory.has(item_id): - var item_inventory_button = items_ids_in_inventory[item_id] + var item_inventory = items_ids_in_inventory[item_id] + var item_inventory_button = get_node( + inventory_ui_container + ).get_inventory_button(item_inventory) if item_inventory_button.is_connected( "mouse_left_inventory_item", @@ -143,7 +156,7 @@ func remove_item_by_id(item_id: String) -> void: "_on_mouse_exited_inventory_item" ) - get_node(inventory_ui_container).remove_item(item_inventory_button) + get_node(inventory_ui_container).remove_item(item_inventory) items_ids_in_inventory.erase(item_id) @@ -158,10 +171,7 @@ func _on_escoria_global_changed(global: String, old_value, new_value) -> void: else: remove_item_by_id(item[0]) else: - escoria.logger.report_errors( - "inventory_ui.gd:_on_escoria_global_changed()", - [ - "Global must contain only one item name.", - "(received: %s)" % global - ] + escoria.logger.error( + self, + "Global must contain only one item name (received: %s)." % global ) 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 95f66cb1..66bde54c 100644 --- a/addons/escoria-core/game/scenes/sound/esc_music_player.gd +++ b/addons/escoria-core/game/scenes/sound/esc_music_player.gd @@ -44,9 +44,9 @@ 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 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 + if ESCProjectSettingsManager.has_setting(ESCProjectSettingsManager.MUSIC_VOLUME): + stream.volume_db = ESCProjectSettingsManager.get_setting( + ESCProjectSettingsManager.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 b57fb1d2..b95a6cee 100644 --- a/addons/escoria-core/game/scenes/sound/esc_sound_player.gd +++ b/addons/escoria-core/game/scenes/sound/esc_sound_player.gd @@ -43,9 +43,9 @@ func set_state(p_state: String, p_force: bool = false): resource.loop_mode = AudioStreamSample.LOOP_DISABLED elif "loop" in resource: 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 + if ESCProjectSettingsManager.has_setting(ESCProjectSettingsManager.SFX_VOLUME): + stream.volume_db = ESCProjectSettingsManager.get_setting( + ESCProjectSettingsManager.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 0cf3c0ad..16a7a6cf 100644 --- a/addons/escoria-core/game/scenes/transitions/esc_transition_player.gd +++ b/addons/escoria-core/game/scenes/transitions/esc_transition_player.gd @@ -67,14 +67,14 @@ func transition( _tween.connect("tween_all_completed", self, "_on_tween_completed") if transition_name.empty(): - transition_name = escoria.project_settings_manager.get_setting( - escoria.project_settings_manager.DEFAULT_TRANSITION + transition_name = ESCProjectSettingsManager.get_setting( + ESCProjectSettingsManager.DEFAULT_TRANSITION ) if not has_transition(transition_name): - escoria.logger.report_errors( - "transition: Transition %s not found" % transition_name, - [] + escoria.logger.error( + self, + "transition: Transition %s not found" % transition_name ) # If this is an "instant" transition, we need to set the alpha of the base @@ -122,8 +122,8 @@ 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: - for directory in escoria.project_settings_manager.get_setting( - escoria.project_settings_manager.TRANSITION_PATHS + for directory in ESCProjectSettingsManager.get_setting( + ESCProjectSettingsManager.TRANSITION_PATHS ): if ResourceLoader.exists(directory.plus_file("%s.material" % name)): return directory.plus_file("%s.material" % name) @@ -154,5 +154,5 @@ func _on_tween_completed(): if not _was_canceled: _tween.stop_all() _tween.remove_all() - escoria.logger.debug("Transition %s done." % str(transition_id)) + escoria.logger.debug(self, "Transition %s done." % str(transition_id)) emit_signal("transition_done", transition_id) diff --git a/addons/escoria-core/plugin.gd b/addons/escoria-core/plugin.gd index fdde35c4..e8012af7 100644 --- a/addons/escoria-core/plugin.gd +++ b/addons/escoria-core/plugin.gd @@ -2,41 +2,28 @@ tool extends EditorPlugin - -# The path to node 'escoria'. -const ESCORIA: String = "/root/escoria" - - -# Reference to "escoria" singleton instance. -var escoria_instance: Node = null - - -# Returns the 'escoria' singleton/autoload. -# -# *Returns* -# The escoria singleton. -func _get_escoria(): - if not is_instance_valid(escoria_instance): - escoria_instance = get_node(ESCORIA) - if not is_instance_valid(escoria_instance): - printerr( - "Escoria could not load the 'escoria' singleton/autoload.\n", - "Please try to disable and re-enable 'Escoria' plugin." - ) - - return escoria_instance +# The warning popup displayed on escoria-core enabling. +var popup_info: AcceptDialog # Virtual function called when plugin is enabled. -func _enable_plugin(): +func enable_plugin(): add_autoload_singleton( "escoria", - "res://addons/escoria-core/game/escoria.tscn" + "res://addons/escoria-core/game/esc_autoload.gd" ) - + # Prepare settings + set_escoria_main_settings() + set_escoria_debug_settings() + set_escoria_ui_settings() + set_escoria_sound_settings() + set_escoria_platform_settings() + # Add input actions in InputMap - InputMap.add_action(_get_escoria().inputs_manager.SWITCH_ACTION_VERB) - InputMap.add_action(_get_escoria().inputs_manager.ESC_SHOW_DEBUG_PROMPT) +# if not InputMap.has_action(ESCInputsManager.SWITCH_ACTION_VERB): +# InputMap.add_action(ESCInputsManager.SWITCH_ACTION_VERB) +# if not InputMap.has_action(ESCInputsManager.ESC_SHOW_DEBUG_PROMPT): +# InputMap.add_action(ESCInputsManager.ESC_SHOW_DEBUG_PROMPT) # Define standard settings ProjectSettings.set_setting( @@ -49,92 +36,103 @@ func _enable_plugin(): "res://addons/escoria-core/default_bus_layout.tres" ) + popup_info = AcceptDialog.new() + popup_info.dialog_text = """You enabled escoria-core plugin. + + Please ignore error messages in Output console and reload your project using + Godot editor's "Project / Reload Current Project" menu. + """ + popup_info.connect("confirmed", self, "_on_warning_popup_confirmed", [], CONNECT_ONESHOT) + add_child(popup_info) + popup_info.popup_centered() + + +func _on_warning_popup_confirmed(): + popup_info.queue_free() + # Virtual function called when plugin is disabled. -func _disable_plugin(): - InputMap.erase_action(_get_escoria().inputs_manager.SWITCH_ACTION_VERB) - InputMap.erase_action(_get_escoria().inputs_manager.ESC_SHOW_DEBUG_PROMPT) +func disable_plugin(): remove_autoload_singleton("escoria") +# if InputMap.has_action(ESCInputsManager.SWITCH_ACTION_VERB): +# InputMap.erase_action(ESCInputsManager.SWITCH_ACTION_VERB) +# if InputMap.has_action(ESCInputsManager.SWITCH_ACTION_VERB): +# InputMap.erase_action(ESCInputsManager.SWITCH_ACTION_VERB) # Setup Escoria func _enter_tree(): - _enable_plugin() - + pass + func _ready(): - # Prepare settings - set_escoria_main_settings() - set_escoria_debug_settings() - set_escoria_ui_settings() - set_escoria_sound_settings() - set_escoria_platform_settings() - ProjectSettings.save() + ProjectSettings.save_custom("escoria.godot") # Prepare the settings in the Escoria UI category func set_escoria_ui_settings(): - _get_escoria().project_settings_manager.register_setting( - _get_escoria().project_settings_manager.DEFAULT_DIALOG_TYPE, + register_setting( + ESCProjectSettingsManager.DEFAULT_DIALOG_TYPE, "", { "type": TYPE_STRING } ) + print("DEFAULT DIALOG TYPE RESET !!!") - _get_escoria().project_settings_manager.register_setting( - _get_escoria().project_settings_manager.GAME_SCENE, + register_setting( + ESCProjectSettingsManager.GAME_SCENE, "", { - "name": _get_escoria().project_settings_manager.GAME_SCENE, + "name": ESCProjectSettingsManager.GAME_SCENE, "type": TYPE_STRING, "hint": PROPERTY_HINT_FILE, "hint_string": "*.tscn, *.scn" } ) - _get_escoria().project_settings_manager.register_setting( - _get_escoria().project_settings_manager.ITEMS_AUTOREGISTER_PATH, - "res://game/items/escitems/", + register_setting( + ESCProjectSettingsManager.ITEMS_AUTOREGISTER_PATH, + "res://game/items/inventory/", { - "name": _get_escoria().project_settings_manager.ITEMS_AUTOREGISTER_PATH, + "name": ESCProjectSettingsManager.ITEMS_AUTOREGISTER_PATH, "type": TYPE_STRING, "hint": PROPERTY_HINT_DIR } ) - _get_escoria().project_settings_manager.register_setting( - _get_escoria().project_settings_manager.DEFAULT_TRANSITION, + register_setting( + ESCProjectSettingsManager.DEFAULT_TRANSITION, "curtain", { - "name": _get_escoria().project_settings_manager.DEFAULT_TRANSITION, + "name": ESCProjectSettingsManager.DEFAULT_TRANSITION, "type": TYPE_STRING } ) - _get_escoria().project_settings_manager.register_setting( - _get_escoria().project_settings_manager.TRANSITION_PATHS, + register_setting( + ESCProjectSettingsManager.TRANSITION_PATHS, [ "res://addons/escoria-core/game/scenes/transitions/shaders/" ], { - "name": _get_escoria().project_settings_manager.TRANSITION_PATHS, + "name": ESCProjectSettingsManager.TRANSITION_PATHS, "type": TYPE_STRING_ARRAY, "hint": PROPERTY_HINT_DIR } ) - _get_escoria().project_settings_manager.register_setting( - _get_escoria().project_settings_manager.INVENTORY_ITEM_SIZE, + register_setting( + ESCProjectSettingsManager.INVENTORY_ITEM_SIZE, Vector2(72, 72), { - "name": _get_escoria().project_settings_manager.INVENTORY_ITEM_SIZE, + "name": ESCProjectSettingsManager.INVENTORY_ITEM_SIZE, "type": TYPE_VECTOR2 } ) - _get_escoria().project_settings_manager.register_setting( - _get_escoria().project_settings_manager.DIALOG_MANAGERS, + register_setting( + ESCProjectSettingsManager.DIALOG_MANAGERS, [], { "type": TYPE_STRING_ARRAY @@ -144,16 +142,16 @@ func set_escoria_ui_settings(): # Prepare the settings in the Escoria main category func set_escoria_main_settings(): - _get_escoria().project_settings_manager.register_setting( - _get_escoria().project_settings_manager.GAME_VERSION, + register_setting( + ESCProjectSettingsManager.GAME_VERSION, "", { "type": TYPE_STRING } ) - _get_escoria().project_settings_manager.register_setting( - _get_escoria().project_settings_manager.GAME_START_SCRIPT, + register_setting( + ESCProjectSettingsManager.GAME_START_SCRIPT, "", { "type": TYPE_STRING, @@ -162,16 +160,16 @@ func set_escoria_main_settings(): } ) - _get_escoria().project_settings_manager.register_setting( - _get_escoria().project_settings_manager.FORCE_QUIT, + register_setting( + ESCProjectSettingsManager.FORCE_QUIT, true, { "type": TYPE_BOOL } ) - _get_escoria().project_settings_manager.register_setting( - _get_escoria().project_settings_manager.COMMAND_DIRECTORIES, + register_setting( + ESCProjectSettingsManager.COMMAND_DIRECTORIES, [ "res://addons/escoria-core/game/core-scripts/esc/commands" ], @@ -180,8 +178,8 @@ func set_escoria_main_settings(): } ) - _get_escoria().project_settings_manager.register_setting( - _get_escoria().project_settings_manager.TEXT_LANG, + register_setting( + ESCProjectSettingsManager.TEXT_LANG, TranslationServer.get_locale(), { "type": TYPE_STRING, @@ -189,8 +187,8 @@ func set_escoria_main_settings(): } ) - _get_escoria().project_settings_manager.register_setting( - _get_escoria().project_settings_manager.VOICE_LANG, + register_setting( + ESCProjectSettingsManager.VOICE_LANG, TranslationServer.get_locale(), { "type": TYPE_STRING, @@ -198,8 +196,8 @@ func set_escoria_main_settings(): } ) - _get_escoria().project_settings_manager.register_setting( - _get_escoria().project_settings_manager.SAVEGAMES_PATH, + register_setting( + ESCProjectSettingsManager.SAVEGAMES_PATH, "user://saves/", { "type": TYPE_STRING, @@ -207,8 +205,8 @@ func set_escoria_main_settings(): } ) - _get_escoria().project_settings_manager.register_setting( - _get_escoria().project_settings_manager.SETTINGS_PATH, + register_setting( + ESCProjectSettingsManager.SETTINGS_PATH, "user://", { "type": TYPE_STRING, @@ -216,8 +214,8 @@ func set_escoria_main_settings(): } ) - _get_escoria().project_settings_manager.register_setting( - _get_escoria().project_settings_manager.GAME_MIGRATION_PATH, + register_setting( + ESCProjectSettingsManager.GAME_MIGRATION_PATH, "", { "type": TYPE_STRING, @@ -228,42 +226,42 @@ func set_escoria_main_settings(): # Prepare the settings in the Escoria debug category func set_escoria_debug_settings(): - _get_escoria().project_settings_manager.register_setting( - _get_escoria().project_settings_manager.TERMINATE_ON_WARNINGS, + register_setting( + ESCProjectSettingsManager.TERMINATE_ON_WARNINGS, false, { "type": TYPE_BOOL } ) - _get_escoria().project_settings_manager.register_setting( - _get_escoria().project_settings_manager.TERMINATE_ON_ERRORS, + register_setting( + ESCProjectSettingsManager.TERMINATE_ON_ERRORS, true, { "type": TYPE_BOOL } ) - _get_escoria().project_settings_manager.register_setting( - _get_escoria().project_settings_manager.DEVELOPMENT_LANG, + register_setting( + ESCProjectSettingsManager.DEVELOPMENT_LANG, "en", { "type": TYPE_STRING } ) - _get_escoria().project_settings_manager.register_setting( - _get_escoria().project_settings_manager.LOG_LEVEL, + register_setting( + ESCProjectSettingsManager.LOG_LEVEL, "ERROR", { "type": TYPE_STRING, "hint": PROPERTY_HINT_ENUM, - "hint_string": "ERROR,WARNING,INFO,DEBUG" + "hint_string": "ERROR,WARNING,INFO,DEBUG,TRACE" } ) - _get_escoria().project_settings_manager.register_setting( - _get_escoria().project_settings_manager.LOG_FILE_PATH, + register_setting( + ESCProjectSettingsManager.LOG_FILE_PATH, "user://", { "type": TYPE_STRING, @@ -271,8 +269,8 @@ func set_escoria_debug_settings(): } ) - _get_escoria().project_settings_manager.register_setting( - _get_escoria().project_settings_manager.LOG_FILE_PATH, + register_setting( + ESCProjectSettingsManager.CRASH_MESSAGE, "We're sorry, but the game crashed. Please send us the " + "following files:\n\n%s", { @@ -281,28 +279,28 @@ func set_escoria_debug_settings(): } ) - _get_escoria().project_settings_manager.register_setting( - _get_escoria().project_settings_manager.ENABLE_ROOM_SELECTOR, + register_setting( + ESCProjectSettingsManager.ENABLE_ROOM_SELECTOR, false, { "type": TYPE_BOOL } ) - _get_escoria().project_settings_manager.register_setting( - _get_escoria().project_settings_manager.ROOM_SELECTOR_ROOM_DIR, + register_setting( + ESCProjectSettingsManager.ROOM_SELECTOR_ROOM_DIR, "", { "type": TYPE_STRING, "hint": PROPERTY_HINT_DIR } ) - + # Prepare the settings in the Escoria sound settings func set_escoria_sound_settings(): - _get_escoria().project_settings_manager.register_setting( - _get_escoria().project_settings_manager.MASTER_VOLUME, + register_setting( + ESCProjectSettingsManager.MASTER_VOLUME, 1, { "type": TYPE_REAL, @@ -311,8 +309,8 @@ func set_escoria_sound_settings(): } ) - _get_escoria().project_settings_manager.register_setting( - _get_escoria().project_settings_manager.MUSIC_VOLUME, + register_setting( + ESCProjectSettingsManager.MUSIC_VOLUME, 1, { "type": TYPE_REAL, @@ -321,8 +319,8 @@ func set_escoria_sound_settings(): } ) - _get_escoria().project_settings_manager.register_setting( - _get_escoria().project_settings_manager.SFX_VOLUME, + register_setting( + ESCProjectSettingsManager.SFX_VOLUME, 1, { "type": TYPE_REAL, @@ -331,8 +329,8 @@ func set_escoria_sound_settings(): } ) - _get_escoria().project_settings_manager.register_setting( - _get_escoria().project_settings_manager.SPEECH_VOLUME, + register_setting( + ESCProjectSettingsManager.SPEECH_VOLUME, 1, { "type": TYPE_REAL, @@ -341,16 +339,16 @@ func set_escoria_sound_settings(): } ) - _get_escoria().project_settings_manager.register_setting( - _get_escoria().project_settings_manager.SPEECH_ENABLED, - 1, + register_setting( + ESCProjectSettingsManager.SPEECH_ENABLED, + true, { "type": TYPE_BOOL } ) - _get_escoria().project_settings_manager.register_setting( - _get_escoria().project_settings_manager.SPEECH_FOLDER, + register_setting( + ESCProjectSettingsManager.SPEECH_FOLDER, "res://speech", { "type": TYPE_STRING, @@ -358,8 +356,8 @@ func set_escoria_sound_settings(): } ) - _get_escoria().project_settings_manager.register_setting( - _get_escoria().project_settings_manager.SPEECH_EXTENSION, + register_setting( + ESCProjectSettingsManager.SPEECH_EXTENSION, "ogg", { "type": TYPE_STRING @@ -374,16 +372,16 @@ func set_escoria_platform_settings(): # scenes. # If set to true, all generic scenes (UI, inventory, etc) will be loaded # as any other scene. - _get_escoria().project_settings_manager.register_setting( - _get_escoria().project_settings_manager.SKIP_CACHE, + register_setting( + ESCProjectSettingsManager.SKIP_CACHE, false, { "type": TYPE_BOOL } ) - _get_escoria().project_settings_manager.register_setting( - _get_escoria().project_settings_manager.SKIP_CACHE_MOBILE, + register_setting( + ESCProjectSettingsManager.SKIP_CACHE_MOBILE, true, { "type": TYPE_BOOL @@ -391,7 +389,18 @@ func set_escoria_platform_settings(): ) -# Uninstall plugin -func _exit_tree(): - _disable_plugin() - +# 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 +static 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) diff --git a/addons/escoria-core/ui_library/inventory/esc_inventory_container.gd b/addons/escoria-core/ui_library/inventory/esc_inventory_container.gd index 8969b0bf..09855878 100644 --- a/addons/escoria-core/ui_library/inventory/esc_inventory_container.gd +++ b/addons/escoria-core/ui_library/inventory/esc_inventory_container.gd @@ -29,3 +29,16 @@ func remove_item(inventory_item: ESCInventoryItem): if c is ESCInventoryButton and c.global_id == inventory_item.global_id: remove_child(c) c.queue_free() + + +# Return an Inventory button from the container, using an ESCInventoryItem +# +# #### Parameters +# - inventory_item: Inventory item to return the button node from +func get_inventory_button(inventory_item: ESCInventoryItem) -> ESCInventoryButton: + var inventory_button = null + for c in get_children(): + if c.global_id == inventory_item.global_id: + inventory_button = c + break + return inventory_button diff --git a/addons/escoria-core/ui_library/menus/options/options.gd b/addons/escoria-core/ui_library/menus/options/options.gd index 92a49ae6..74788f6a 100644 --- a/addons/escoria-core/ui_library/menus/options/options.gd +++ b/addons/escoria-core/ui_library/menus/options/options.gd @@ -24,6 +24,7 @@ func _ready() -> void: $VBoxContainer/MarginContainer/options/flags for child in _flags_container.get_children(): _flags_container.remove_child(child) + child.queue_free() _loaded_languages = [] @@ -38,7 +39,6 @@ func _ready() -> void: _flags_container.add_child(_lang) _lang.connect("gui_input", self, "_on_language_input", [lang]) - # Show the options func show(): backup_settings = escoria.settings.duplicate() diff --git a/addons/escoria-core/ui_library/tools/room_select/room_select.gd b/addons/escoria-core/ui_library/tools/room_select/room_select.gd index 2a46ed28..f43b7922 100644 --- a/addons/escoria-core/ui_library/tools/room_select/room_select.gd +++ b/addons/escoria-core/ui_library/tools/room_select/room_select.gd @@ -12,12 +12,12 @@ var _options_paths = [] # Build up the list of rooms func _ready(): - var rooms_folder = ProjectSettings.get_setting( - "escoria/debug/room_selector_room_dir" + var rooms_folder = ESCProjectSettingsManager.get_setting( + ESCProjectSettingsManager.ROOM_SELECTOR_ROOM_DIR ) if rooms_folder == "" or \ - not ProjectSettings.get_setting( - "escoria/debug/enable_room_selector" + not ESCProjectSettingsManager.get_setting( + ESCProjectSettingsManager.ENABLE_ROOM_SELECTOR ): return var dir = Directory.new() @@ -44,8 +44,10 @@ func _ready(): ]) else: - escoria.logger.report_warnings("room_select.gd:_ready()", - ["A problem occurred while opening rooms folder."]) + escoria.logger.warn( + self, + "A problem occurred while opening rooms folder %s." % str(path) + ) # Switch to the selected room diff --git a/addons/escoria-dialog-simple/plugin.gd b/addons/escoria-dialog-simple/plugin.gd index 5a20433e..ff685dff 100644 --- a/addons/escoria-dialog-simple/plugin.gd +++ b/addons/escoria-dialog-simple/plugin.gd @@ -2,59 +2,95 @@ tool extends EditorPlugin - -var _escoria - const MANAGER_CLASS="res://addons/escoria-dialog-simple/esc_dialog_simple.gd" -func _init() -> void: - _escoria = preload("res://addons/escoria-core/game/escoria.tscn")\ - .instance() - - -# Register ourselves after setup -func _ready() -> void: - call_deferred("_register") +# Override function to return the plugin name. +func get_plugin_name(): + return "escoria-dialog-simple" # Unregister ourselves -func _exit_tree() -> void: - _escoria.deregister_dialog_manager(MANAGER_CLASS) +func disable_plugin(): + print("Disabling plugin Escoria Dialog Simple") + ESCProjectSettingsManager.register_setting( + ESCProjectSettingsManager.DEFAULT_DIALOG_TYPE, + "", + {} + ) + ESCProjectSettingsManager.register_setting( + ESCProjectSettingsManager.AVATARS_PATH, + null, + {} + ) + + ESCProjectSettingsManager.register_setting( + ESCProjectSettingsManager.TEXT_SPEED_PER_CHARACTER, + null, + {} + ) + + ESCProjectSettingsManager.register_setting( + ESCProjectSettingsManager.FAST_TEXT_SPEED_PER_CHARACTER, + null, + {} + ) + + ESCProjectSettingsManager.register_setting( + ESCProjectSettingsManager.MAX_TIME_TO_DISAPPEAR, + null, + {} + ) + + EscoriaPlugin.deregister_dialog_manager(MANAGER_CLASS) # Add ourselves to the list of dialog managers -func _register(): - _escoria.register_dialog_manager(MANAGER_CLASS) - _escoria.project_settings_manager.register_setting( - _escoria.project_settings_manager.AVATARS_PATH, - "", - { - "type": TYPE_STRING, - "hint": PROPERTY_HINT_DIR - } - ) +func enable_plugin(): + print("Enabling plugin Escoria Dialog Simple") + if EscoriaPlugin.register_dialog_manager(self, MANAGER_CLASS): + ESCProjectSettingsManager.register_setting( + ESCProjectSettingsManager.DEFAULT_DIALOG_TYPE, + "floating", + { + "type": TYPE_STRING + } + ) + + ESCProjectSettingsManager.register_setting( + ESCProjectSettingsManager.AVATARS_PATH, + "", + { + "type": TYPE_STRING, + "hint": PROPERTY_HINT_DIR + } + ) - _escoria.project_settings_manager.register_setting( - _escoria.project_settings_manager.TEXT_SPEED_PER_CHARACTER, - 0.1, - { - "type": TYPE_REAL - } - ) + ESCProjectSettingsManager.register_setting( + ESCProjectSettingsManager.TEXT_SPEED_PER_CHARACTER, + 0.1, + { + "type": TYPE_REAL + } + ) - _escoria.project_settings_manager.register_setting( - _escoria.project_settings_manager.FAST_TEXT_SPEED_PER_CHARACTER, - 0.25, - { - "type": TYPE_REAL - } - ) + ESCProjectSettingsManager.register_setting( + ESCProjectSettingsManager.FAST_TEXT_SPEED_PER_CHARACTER, + 0.25, + { + "type": TYPE_REAL + } + ) - _escoria.project_settings_manager.register_setting( - _escoria.project_settings_manager.MAX_TIME_TO_DISAPPEAR, - 1.0, - { - "type": TYPE_REAL - } - ) + ESCProjectSettingsManager.register_setting( + ESCProjectSettingsManager.MAX_TIME_TO_DISAPPEAR, + 1.0, + { + "type": TYPE_REAL + } + ) + else: + get_editor_interface().set_plugin_enabled( + get_plugin_name(), + false + ) diff --git a/addons/escoria-ui-9verbs/game.gd b/addons/escoria-ui-9verbs/game.gd index b900017a..8cce4e8c 100644 --- a/addons/escoria-ui-9verbs/game.gd +++ b/addons/escoria-ui-9verbs/game.gd @@ -45,10 +45,9 @@ onready var verbs_menu = $ui/Control/panel_down/VBoxContainer/HBoxContainer\ /VerbsMargin/verbs_menu onready var tooltip = $ui/Control/panel_down/VBoxContainer/MarginContainer\ /tooltip -onready var room_select = $ui/Control/panel_down/VBoxContainer/HBoxContainer\ - /MainMargin/VBoxContainer/room_select onready var inventory_ui = $ui/Control/panel_down/VBoxContainer/HBoxContainer\ /InventoryMargin/inventory_ui +var room_select func _enter_tree(): var room_selector_parent = $ui/Control/panel_down/VBoxContainer\ @@ -56,12 +55,11 @@ func _enter_tree(): if ProjectSettings.get_setting("escoria/debug/enable_room_selector") and \ room_selector_parent.get_node_or_null("room_select") == null: - room_selector_parent.add_child( - preload( - "res://addons/escoria-core/ui_library/tools/room_select" +\ - "/room_select.tscn" - ).instance() - ) + room_select = preload( + "res://addons/escoria-core/ui_library/tools/room_select" +\ + "/room_select.tscn" + ).instance() + room_selector_parent.add_child(room_select) ## BACKGROUND ## @@ -121,7 +119,8 @@ 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 != VERB_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: @@ -302,7 +301,7 @@ func mousewheel_action(_direction: int): func hide_ui(): $ui/Control.hide() verbs_menu.hide() - if ProjectSettings.get("escoria/debug/enable_room_selector") == true: + if ESCProjectSettingsManager.get_setting(ESCProjectSettingsManager.ENABLE_ROOM_SELECTOR): room_select.hide() inventory_ui.hide() tooltip.hide() @@ -311,7 +310,7 @@ func hide_ui(): func show_ui(): $ui/Control.show() verbs_menu.show() - if ProjectSettings.get("escoria/debug/enable_room_selector") == true: + if ESCProjectSettingsManager.get_setting(ESCProjectSettingsManager.ENABLE_ROOM_SELECTOR): room_select.show() inventory_ui.show() tooltip.show() @@ -363,8 +362,9 @@ func _on_event_done(_return_code: int, _event_name: String): func apply_custom_settings(custom_settings: Dictionary): if custom_settings.has("a_custom_setting"): escoria.logger.info( - "custom setting value loaded:", - [custom_settings["a_custom_setting"]] + self, + "custom setting value loaded: %s." + % str(custom_settings["a_custom_setting"]) ) diff --git a/addons/escoria-ui-9verbs/plugin.gd b/addons/escoria-ui-9verbs/plugin.gd index 2e6cacc4..b6b1de54 100644 --- a/addons/escoria-ui-9verbs/plugin.gd +++ b/addons/escoria-ui-9verbs/plugin.gd @@ -3,16 +3,22 @@ tool extends EditorPlugin -# Register UI -func _enter_tree() -> void: - call_deferred("_register") +# Override function to return the plugin name. +func get_plugin_name(): + return "escoria-ui-9verbs" # Deregister UI -func _exit_tree() -> void: - escoria.deregister_ui("res://addons/escoria-ui-9verbs/game.tscn") +func disable_plugin(): + print("Disabling plugin Escoria UI 9-verbs.") + EscoriaPlugin.deregister_ui("res://addons/escoria-ui-9verbs/game.tscn") # Register UI with Escoria -func _register(): - escoria.register_ui("res://addons/escoria-ui-9verbs/game.tscn") +func enable_plugin(): + print("Enabling plugin Escoria UI 9-verbs.") + if not EscoriaPlugin.register_ui(self, "res://addons/escoria-ui-9verbs/game.tscn"): + get_editor_interface().set_plugin_enabled( + get_plugin_name(), + false + ) diff --git a/addons/escoria-ui-keyboard-9verbs/plugin.gd b/addons/escoria-ui-keyboard-9verbs/plugin.gd index d1496ff6..a861c5b9 100644 --- a/addons/escoria-ui-keyboard-9verbs/plugin.gd +++ b/addons/escoria-ui-keyboard-9verbs/plugin.gd @@ -1,18 +1,24 @@ -# Plugin script to initialize Escoria simple mouse UI +# Plugin script to initialize Escoria 9-verbs with keyboard plugin tool extends EditorPlugin -# Register UI -func _enter_tree() -> void: - call_deferred("_register") +# Override function to return the plugin name. +func get_plugin_name(): + return "escoria-ui-keyboard-9verbs" # Deregister UI -func _exit_tree() -> void: - escoria.deregister_ui("res://addons/escoria-ui-keyboard-9verbs/game.tscn") +func disable_plugin() -> void: + print("Disabling plugin Escoria UI 9-verbs with keyboard.") + EscoriaPlugin.deregister_ui("res://addons/escoria-ui-keyboard-9verbs/game.tscn") # Register UI with Escoria -func _register(): - escoria.register_ui("res://addons/escoria-ui-keyboard-9verbs/game.tscn") +func enable_plugin(): + print("Enabling plugin Escoria UI 9-verbs with keyboard.") + if not EscoriaPlugin.register_ui(self, "res://addons/escoria-ui-keyboard-9verbs/game.tscn"): + get_editor_interface().set_plugin_enabled( + get_plugin_name(), + false + ) diff --git a/addons/escoria-ui-simplemouse/game.gd b/addons/escoria-ui-simplemouse/game.gd index ddd24a74..3cbdb280 100644 --- a/addons/escoria-ui-simplemouse/game.gd +++ b/addons/escoria-ui-simplemouse/game.gd @@ -70,7 +70,7 @@ var _is_gamepad_connected = false func _enter_tree(): var room_selector_parent = $CanvasLayer/ui/HBoxContainer/VBoxContainer - if escoria.project_settings_manager.get_setting(escoria.project_settings_manager.ENABLE_ROOM_SELECTOR) \ + if ESCProjectSettingsManager.get_setting(ESCProjectSettingsManager.ENABLE_ROOM_SELECTOR) \ and room_selector_parent.get_node_or_null("room_select") == null: room_selector_parent.add_child( @@ -97,7 +97,7 @@ func _exit_tree(): func _input(event: InputEvent) -> void: - if escoria.is_ready_for_inputs(): + if escoria.get_escoria().is_ready_for_inputs(): if event is InputEventMouseMotion: escoria.main.current_scene.game. \ update_tooltip_following_mouse_position(event.position) @@ -328,8 +328,9 @@ func pause_game(): func apply_custom_settings(custom_settings: Dictionary): if custom_settings.has("a_custom_setting"): escoria.logger.info( - "custom setting value loaded:", - [custom_settings["a_custom_setting"]] + self, + "custom setting value loaded: %s." + % str(custom_settings["a_custom_setting"]) ) diff --git a/addons/escoria-ui-simplemouse/plugin.gd b/addons/escoria-ui-simplemouse/plugin.gd index 0c82fc53..20504b69 100644 --- a/addons/escoria-ui-simplemouse/plugin.gd +++ b/addons/escoria-ui-simplemouse/plugin.gd @@ -3,16 +3,23 @@ tool extends EditorPlugin -# Register UI -func _enter_tree(): - call_deferred("_register") +# Override function to return the plugin name. +func get_plugin_name(): + return "escoria-ui-simplemouse" # Deregister UI -func _exit_tree() -> void: - escoria.deregister_ui("res://addons/escoria-ui-simplemouse/game.tscn") +func disable_plugin(): + print("Disabling plugin Escoria UI Simple Mouse.") + EscoriaPlugin.deregister_ui("res://addons/escoria-ui-simplemouse/game.tscn") # Register UI with Escoria -func _register(): - escoria.register_ui("res://addons/escoria-ui-simplemouse/game.tscn") +func enable_plugin(): + print("Enabling plugin Escoria UI Simple Mouse.") + if not EscoriaPlugin.register_ui(self, "res://addons/escoria-ui-simplemouse/game.tscn"): + get_editor_interface().set_plugin_enabled( + get_plugin_name(), + false + ) + diff --git a/escoria.godot b/escoria.godot new file mode 100644 index 00000000..505221ad --- /dev/null +++ b/escoria.godot @@ -0,0 +1,821 @@ +; Engine configuration file. +; It's best edited using the editor UI and not directly, +; since the parameters that go here are not all obvious. +; +; Format: +; [section] ; section goes between [] +; param=value ; assign values to parameters + +config_version=4 + +_global_script_classes=[ { +"base": "ESCBaseCommand", +"class": "AcceptInputCommand", +"language": "GDScript", +"path": "res://addons/escoria-core/game/core-scripts/esc/commands/accept_input.gd" +}, { +"base": "ESCBaseCommand", +"class": "AnimBlockCommand", +"language": "GDScript", +"path": "res://addons/escoria-core/game/core-scripts/esc/commands/anim_block.gd" +}, { +"base": "ESCBaseCommand", +"class": "AnimCommand", +"language": "GDScript", +"path": "res://addons/escoria-core/game/core-scripts/esc/commands/anim.gd" +}, { +"base": "ESCBaseCommand", +"class": "CameraPushCommand", +"language": "GDScript", +"path": "res://addons/escoria-core/game/core-scripts/esc/commands/camera_push.gd" +}, { +"base": "ESCBaseCommand", +"class": "CameraSetLimitsCommand", +"language": "GDScript", +"path": "res://addons/escoria-core/game/core-scripts/esc/commands/camera_set_limits.gd" +}, { +"base": "ESCBaseCommand", +"class": "CameraSetPosCommand", +"language": "GDScript", +"path": "res://addons/escoria-core/game/core-scripts/esc/commands/camera_set_pos.gd" +}, { +"base": "ESCBaseCommand", +"class": "CameraSetTargetCommand", +"language": "GDScript", +"path": "res://addons/escoria-core/game/core-scripts/esc/commands/camera_set_target.gd" +}, { +"base": "ESCBaseCommand", +"class": "CameraSetZoomCommand", +"language": "GDScript", +"path": "res://addons/escoria-core/game/core-scripts/esc/commands/camera_set_zoom.gd" +}, { +"base": "ESCBaseCommand", +"class": "CameraSetZoomHeightCommand", +"language": "GDScript", +"path": "res://addons/escoria-core/game/core-scripts/esc/commands/camera_set_zoom_height.gd" +}, { +"base": "ESCBaseCommand", +"class": "CameraShiftCommand", +"language": "GDScript", +"path": "res://addons/escoria-core/game/core-scripts/esc/commands/camera_shift.gd" +}, { +"base": "ESCBaseCommand", +"class": "ChangeSceneCommand", +"language": "GDScript", +"path": "res://addons/escoria-core/game/core-scripts/esc/commands/change_scene.gd" +}, { +"base": "ESCBaseCommand", +"class": "CustomCommand", +"language": "GDScript", +"path": "res://addons/escoria-core/game/core-scripts/esc/commands/custom.gd" +}, { +"base": "ESCBaseCommand", +"class": "DecGlobalCommand", +"language": "GDScript", +"path": "res://addons/escoria-core/game/core-scripts/esc/commands/dec_global.gd" +}, { +"base": "Resource", +"class": "ESCActionManager", +"language": "GDScript", +"path": "res://addons/escoria-core/game/core-scripts/esc/esc_action_manager.gd" +}, { +"base": "Resource", +"class": "ESCAnimationName", +"language": "GDScript", +"path": "res://addons/escoria-core/game/core-scripts/resources/esc_animationname.gd" +}, { +"base": "Node", +"class": "ESCAnimationPlayer", +"language": "GDScript", +"path": "res://addons/escoria-core/game/core-scripts/esc_animation_player.gd" +}, { +"base": "Resource", +"class": "ESCAnimationResource", +"language": "GDScript", +"path": "res://addons/escoria-core/game/core-scripts/resources/esc_animationresource.gd" +}, { +"base": "TextureRect", +"class": "ESCBackground", +"language": "GDScript", +"path": "res://addons/escoria-core/game/core-scripts/esc_background.gd" +}, { +"base": "Resource", +"class": "ESCBaseCommand", +"language": "GDScript", +"path": "res://addons/escoria-core/game/core-scripts/esc/types/esc_base_command.gd" +}, { +"base": "Camera2D", +"class": "ESCCamera", +"language": "GDScript", +"path": "res://addons/escoria-core/game/scenes/camera_player/esc_camera.gd" +}, { +"base": "Reference", +"class": "ESCCameraLimits", +"language": "GDScript", +"path": "res://addons/escoria-core/game/scenes/camera_player/esc_camera_limits.gd" +}, { +"base": "ESCStatement", +"class": "ESCCommand", +"language": "GDScript", +"path": "res://addons/escoria-core/game/core-scripts/esc/types/esc_command.gd" +}, { +"base": "Reference", +"class": "ESCCommandArgumentDescriptor", +"language": "GDScript", +"path": "res://addons/escoria-core/game/core-scripts/esc/types/esc_command_argument_descriptor.gd" +}, { +"base": "Reference", +"class": "ESCCommandRegistry", +"language": "GDScript", +"path": "res://addons/escoria-core/game/core-scripts/esc/esc_command_registry.gd" +}, { +"base": "Resource", +"class": "ESCCompiler", +"language": "GDScript", +"path": "res://addons/escoria-core/game/core-scripts/esc/esc_compiler.gd" +}, { +"base": "Reference", +"class": "ESCCondition", +"language": "GDScript", +"path": "res://addons/escoria-core/game/core-scripts/esc/types/esc_condition.gd" +}, { +"base": "ESCStatement", +"class": "ESCDialog", +"language": "GDScript", +"path": "res://addons/escoria-core/game/core-scripts/esc/types/esc_dialog.gd" +}, { +"base": "Control", +"class": "ESCDialogManager", +"language": "GDScript", +"path": "res://addons/escoria-core/game/scenes/dialogs/esc_dialog_manager.gd" +}, { +"base": "ESCStatement", +"class": "ESCDialogOption", +"language": "GDScript", +"path": "res://addons/escoria-core/game/core-scripts/esc/types/esc_dialog_option.gd" +}, { +"base": "Control", +"class": "ESCDialogOptionsChooser", +"language": "GDScript", +"path": "res://addons/escoria-core/game/scenes/dialogs/esc_dialog_options_chooser.gd" +}, { +"base": "Node", +"class": "ESCDialogPlayer", +"language": "GDScript", +"path": "res://addons/escoria-core/game/scenes/dialogs/esc_dialog_player.gd" +}, { +"base": "ESCDialogManager", +"class": "ESCDialogSimple", +"language": "GDScript", +"path": "res://addons/escoria-dialog-simple/esc_dialog_simple.gd" +}, { +"base": "Resource", +"class": "ESCDirectionAngle", +"language": "GDScript", +"path": "res://addons/escoria-core/game/core-scripts/resources/esc_directionangle.gd" +}, { +"base": "ESCStatement", +"class": "ESCEvent", +"language": "GDScript", +"path": "res://addons/escoria-core/game/core-scripts/esc/types/esc_event.gd" +}, { +"base": "Node", +"class": "ESCEventManager", +"language": "GDScript", +"path": "res://addons/escoria-core/game/core-scripts/esc/esc_event_manager.gd" +}, { +"base": "Resource", +"class": "ESCExecution", +"language": "GDScript", +"path": "res://addons/escoria-core/game/core-scripts/esc/types/esc_execution.gd" +}, { +"base": "ESCItem", +"class": "ESCExit", +"language": "GDScript", +"path": "res://addons/escoria-core/game/core-scripts/esc_exit.gd" +}, { +"base": "Node2D", +"class": "ESCGame", +"language": "GDScript", +"path": "res://addons/escoria-core/game/core-scripts/esc_game.gd" +}, { +"base": "Resource", +"class": "ESCGlobalsManager", +"language": "GDScript", +"path": "res://addons/escoria-core/game/core-scripts/esc/esc_globals_manager.gd" +}, { +"base": "ESCStatement", +"class": "ESCGroup", +"language": "GDScript", +"path": "res://addons/escoria-core/game/core-scripts/esc/types/esc_group.gd" +}, { +"base": "Resource", +"class": "ESCInputsManager", +"language": "GDScript", +"path": "res://addons/escoria-core/game/esc_inputs_manager.gd" +}, { +"base": "Control", +"class": "ESCInventory", +"language": "GDScript", +"path": "res://addons/escoria-core/game/scenes/inventory/inventory_ui.gd" +}, { +"base": "TextureButton", +"class": "ESCInventoryButton", +"language": "GDScript", +"path": "res://addons/escoria-core/ui_library/inventory/esc_inventory_button.gd" +}, { +"base": "Control", +"class": "ESCInventoryContainer", +"language": "GDScript", +"path": "res://addons/escoria-core/ui_library/inventory/esc_inventory_container.gd" +}, { +"base": "Reference", +"class": "ESCInventoryItem", +"language": "GDScript", +"path": "res://addons/escoria-core/game/core-scripts/esc_inventory_item.gd" +}, { +"base": "Resource", +"class": "ESCInventoryManager", +"language": "GDScript", +"path": "res://addons/escoria-core/game/core-scripts/esc/esc_inventory_manager.gd" +}, { +"base": "Area2D", +"class": "ESCItem", +"language": "GDScript", +"path": "res://addons/escoria-core/game/core-scripts/esc_item.gd" +}, { +"base": "Position2D", +"class": "ESCLocation", +"language": "GDScript", +"path": "res://addons/escoria-core/game/core-scripts/esc_location.gd" +}, { +"base": "Node", +"class": "ESCMain", +"language": "GDScript", +"path": "res://addons/escoria-core/game/main_scene.gd" +}, { +"base": "Reference", +"class": "ESCMigration", +"language": "GDScript", +"path": "res://addons/escoria-core/game/core-scripts/migrations/esc_migration.gd" +}, { +"base": "Reference", +"class": "ESCMigrationManager", +"language": "GDScript", +"path": "res://addons/escoria-core/game/core-scripts/migrations/esc_migration_manager.gd" +}, { +"base": "Node", +"class": "ESCMovable", +"language": "GDScript", +"path": "res://addons/escoria-core/game/core-scripts/behaviors/esc_movable.gd" +}, { +"base": "Control", +"class": "ESCMusicPlayer", +"language": "GDScript", +"path": "res://addons/escoria-core/game/scenes/sound/esc_music_player.gd" +}, { +"base": "Reference", +"class": "ESCObject", +"language": "GDScript", +"path": "res://addons/escoria-core/game/core-scripts/esc/types/esc_object.gd" +}, { +"base": "Resource", +"class": "ESCObjectManager", +"language": "GDScript", +"path": "res://addons/escoria-core/game/core-scripts/esc/esc_object_manager.gd" +}, { +"base": "ESCItem", +"class": "ESCPlayer", +"language": "GDScript", +"path": "res://addons/escoria-core/game/core-scripts/esc_player.gd" +}, { +"base": "Resource", +"class": "ESCProjectSettingsManager", +"language": "GDScript", +"path": "res://addons/escoria-core/game/esc_project_settings_manager.gd" +}, { +"base": "Reference", +"class": "ESCResourceCache", +"language": "GDScript", +"path": "res://addons/escoria-core/game/core-scripts/esc_resource_cache.gd" +}, { +"base": "Resource", +"class": "ESCResourceDescriptor", +"language": "GDScript", +"path": "res://addons/escoria-core/game/core-scripts/resources/esc_resource_descriptor.gd" +}, { +"base": "Node2D", +"class": "ESCRoom", +"language": "GDScript", +"path": "res://addons/escoria-core/game/core-scripts/esc_room.gd" +}, { +"base": "Resource", +"class": "ESCRoomManager", +"language": "GDScript", +"path": "res://addons/escoria-core/game/core-scripts/esc/esc_room_manager.gd" +}, { +"base": "Reference", +"class": "ESCRoomObjects", +"language": "GDScript", +"path": "res://addons/escoria-core/game/core-scripts/esc/types/esc_room_objects.gd" +}, { +"base": "Reference", +"class": "ESCRoomObjectsKey", +"language": "GDScript", +"path": "res://addons/escoria-core/game/core-scripts/esc/types/esc_room_objects_key.gd" +}, { +"base": "Resource", +"class": "ESCSaveGame", +"language": "GDScript", +"path": "res://addons/escoria-core/game/core-scripts/save_data/esc_savegame.gd" +}, { +"base": "Reference", +"class": "ESCSaveManager", +"language": "GDScript", +"path": "res://addons/escoria-core/game/core-scripts/save_data/esc_save_manager.gd" +}, { +"base": "Resource", +"class": "ESCSaveSettings", +"language": "GDScript", +"path": "res://addons/escoria-core/game/core-scripts/save_data/esc_savesettings.gd" +}, { +"base": "Reference", +"class": "ESCScheduledEvent", +"language": "GDScript", +"path": "res://addons/escoria-core/game/core-scripts/esc/types/esc_scheduled_event.gd" +}, { +"base": "Resource", +"class": "ESCScript", +"language": "GDScript", +"path": "res://addons/escoria-core/game/core-scripts/esc/types/esc_script.gd" +}, { +"base": "Control", +"class": "ESCSoundPlayer", +"language": "GDScript", +"path": "res://addons/escoria-core/game/scenes/sound/esc_sound_player.gd" +}, { +"base": "Control", +"class": "ESCSpeechPlayer", +"language": "GDScript", +"path": "res://addons/escoria-core/game/scenes/sound/esc_speech_player.gd" +}, { +"base": "Reference", +"class": "ESCStatement", +"language": "GDScript", +"path": "res://addons/escoria-core/game/core-scripts/esc/types/esc_statement.gd" +}, { +"base": "Navigation2D", +"class": "ESCTerrain", +"language": "GDScript", +"path": "res://addons/escoria-core/game/core-scripts/esc_terrain.gd" +}, { +"base": "RichTextLabel", +"class": "ESCTooltip", +"language": "GDScript", +"path": "res://addons/escoria-core/game/core-scripts/esc_tooltip.gd" +}, { +"base": "ColorRect", +"class": "ESCTransitionPlayer", +"language": "GDScript", +"path": "res://addons/escoria-core/game/scenes/transitions/esc_transition_player.gd" +}, { +"base": "Reference", +"class": "ESCUtils", +"language": "GDScript", +"path": "res://addons/escoria-core/game/core-scripts/utils/esc_utils.gd" +}, { +"base": "Reference", +"class": "ESCWalkContext", +"language": "GDScript", +"path": "res://addons/escoria-core/game/core-scripts/esc_walk_context.gd" +}, { +"base": "ESCBaseCommand", +"class": "EnableTerrainCommand", +"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": "Reference", +"class": "EscoriaPlugin", +"language": "GDScript", +"path": "res://addons/escoria-core/game/core-scripts/plugins/escoria_plugin.gd" +}, { +"base": "ESCBaseCommand", +"class": "HideMenuCommand", +"language": "GDScript", +"path": "res://addons/escoria-core/game/core-scripts/esc/commands/hide_menu.gd" +}, { +"base": "ESCBaseCommand", +"class": "IncGlobalCommand", +"language": "GDScript", +"path": "res://addons/escoria-core/game/core-scripts/esc/commands/inc_global.gd" +}, { +"base": "ESCBaseCommand", +"class": "InventoryAddCommand", +"language": "GDScript", +"path": "res://addons/escoria-core/game/core-scripts/esc/commands/inventory_add.gd" +}, { +"base": "ESCBaseCommand", +"class": "InventoryRemoveCommand", +"language": "GDScript", +"path": "res://addons/escoria-core/game/core-scripts/esc/commands/inventory_remove.gd" +}, { +"base": "ESCBaseCommand", +"class": "PlaySndCommand", +"language": "GDScript", +"path": "res://addons/escoria-core/game/core-scripts/esc/commands/play_snd.gd" +}, { +"base": "ESCBaseCommand", +"class": "PrintCommand", +"language": "GDScript", +"path": "res://addons/escoria-core/game/core-scripts/esc/commands/print.gd" +}, { +"base": "ESCBaseCommand", +"class": "QueueEventCommand", +"language": "GDScript", +"path": "res://addons/escoria-core/game/core-scripts/esc/commands/queue_event.gd" +}, { +"base": "ESCBaseCommand", +"class": "QueueResourceCommand", +"language": "GDScript", +"path": "res://addons/escoria-core/game/core-scripts/esc/commands/queue_resource.gd" +}, { +"base": "ESCBaseCommand", +"class": "RandGlobalCommand", +"language": "GDScript", +"path": "res://addons/escoria-core/game/core-scripts/esc/commands/rand_global.gd" +}, { +"base": "ESCBaseCommand", +"class": "RepeatCommand", +"language": "GDScript", +"path": "res://addons/escoria-core/game/core-scripts/esc/commands/repeat.gd" +}, { +"base": "ESCBaseCommand", +"class": "SayCommand", +"language": "GDScript", +"path": "res://addons/escoria-core/game/core-scripts/esc/commands/say.gd" +}, { +"base": "ESCBaseCommand", +"class": "SchedEventCommand", +"language": "GDScript", +"path": "res://addons/escoria-core/game/core-scripts/esc/commands/sched_event.gd" +}, { +"base": "ESCBaseCommand", +"class": "SetActiveCommand", +"language": "GDScript", +"path": "res://addons/escoria-core/game/core-scripts/esc/commands/set_active.gd" +}, { +"base": "ESCBaseCommand", +"class": "SetActiveIfExistsCommand", +"language": "GDScript", +"path": "res://addons/escoria-core/game/core-scripts/esc/commands/set_active_if_exists.gd" +}, { +"base": "ESCBaseCommand", +"class": "SetAngleCommand", +"language": "GDScript", +"path": "res://addons/escoria-core/game/core-scripts/esc/commands/set_angle.gd" +}, { +"base": "ESCBaseCommand", +"class": "SetAnimationsCommand", +"language": "GDScript", +"path": "res://addons/escoria-core/game/core-scripts/esc/commands/set_animations.gd" +}, { +"base": "ESCBaseCommand", +"class": "SetGlobalCommand", +"language": "GDScript", +"path": "res://addons/escoria-core/game/core-scripts/esc/commands/set_global.gd" +}, { +"base": "ESCBaseCommand", +"class": "SetGlobalsCommand", +"language": "GDScript", +"path": "res://addons/escoria-core/game/core-scripts/esc/commands/set_globals.gd" +}, { +"base": "ESCBaseCommand", +"class": "SetGuiVisibleCommand", +"language": "GDScript", +"path": "res://addons/escoria-core/game/core-scripts/esc/commands/set_gui_visible.gd" +}, { +"base": "ESCBaseCommand", +"class": "SetInteractiveCommand", +"language": "GDScript", +"path": "res://addons/escoria-core/game/core-scripts/esc/commands/set_interactive.gd" +}, { +"base": "ESCBaseCommand", +"class": "SetSpeedCommand", +"language": "GDScript", +"path": "res://addons/escoria-core/game/core-scripts/esc/commands/set_speed.gd" +}, { +"base": "ESCBaseCommand", +"class": "SetStateCommand", +"language": "GDScript", +"path": "res://addons/escoria-core/game/core-scripts/esc/commands/set_state.gd" +}, { +"base": "ESCBaseCommand", +"class": "ShowMenuCommand", +"language": "GDScript", +"path": "res://addons/escoria-core/game/core-scripts/esc/commands/show_menu.gd" +}, { +"base": "SlideCommand", +"class": "SlideBlockCommand", +"language": "GDScript", +"path": "res://addons/escoria-core/game/core-scripts/esc/commands/slide_block.gd" +}, { +"base": "ESCBaseCommand", +"class": "SlideCommand", +"language": "GDScript", +"path": "res://addons/escoria-core/game/core-scripts/esc/commands/slide.gd" +}, { +"base": "ESCBaseCommand", +"class": "SpawnCommand", +"language": "GDScript", +"path": "res://addons/escoria-core/game/core-scripts/esc/commands/spawn.gd" +}, { +"base": "ESCBaseCommand", +"class": "StopCommand", +"language": "GDScript", +"path": "res://addons/escoria-core/game/core-scripts/esc/commands/stop.gd" +}, { +"base": "ESCBaseCommand", +"class": "StopSndCommand", +"language": "GDScript", +"path": "res://addons/escoria-core/game/core-scripts/esc/commands/stop_snd.gd" +}, { +"base": "ESCBaseCommand", +"class": "TeleportCommand", +"language": "GDScript", +"path": "res://addons/escoria-core/game/core-scripts/esc/commands/teleport.gd" +}, { +"base": "ESCBaseCommand", +"class": "TeleportPosCommand", +"language": "GDScript", +"path": "res://addons/escoria-core/game/core-scripts/esc/commands/teleport_pos.gd" +}, { +"base": "ESCBaseCommand", +"class": "TransitionCommand", +"language": "GDScript", +"path": "res://addons/escoria-core/game/core-scripts/esc/commands/transition.gd" +}, { +"base": "ESCBaseCommand", +"class": "TurnToCommand", +"language": "GDScript", +"path": "res://addons/escoria-core/game/core-scripts/esc/commands/turn_to.gd" +}, { +"base": "ESCBaseCommand", +"class": "WaitCommand", +"language": "GDScript", +"path": "res://addons/escoria-core/game/core-scripts/esc/commands/wait.gd" +}, { +"base": "ESCBaseCommand", +"class": "WalkBlockCommand", +"language": "GDScript", +"path": "res://addons/escoria-core/game/core-scripts/esc/commands/walk_block.gd" +}, { +"base": "ESCBaseCommand", +"class": "WalkCommand", +"language": "GDScript", +"path": "res://addons/escoria-core/game/core-scripts/esc/commands/walk.gd" +}, { +"base": "ESCBaseCommand", +"class": "WalkToPosBlockCommand", +"language": "GDScript", +"path": "res://addons/escoria-core/game/core-scripts/esc/commands/walk_to_pos_block.gd" +}, { +"base": "ESCBaseCommand", +"class": "WalkToPosCommand", +"language": "GDScript", +"path": "res://addons/escoria-core/game/core-scripts/esc/commands/walk_to_pos.gd" +} ] +_global_script_class_icons={ +"AcceptInputCommand": "", +"AnimBlockCommand": "", +"AnimCommand": "", +"CameraPushCommand": "", +"CameraSetLimitsCommand": "", +"CameraSetPosCommand": "", +"CameraSetTargetCommand": "", +"CameraSetZoomCommand": "", +"CameraSetZoomHeightCommand": "", +"CameraShiftCommand": "", +"ChangeSceneCommand": "", +"CustomCommand": "", +"DecGlobalCommand": "", +"ESCActionManager": "", +"ESCAnimationName": "", +"ESCAnimationPlayer": "", +"ESCAnimationResource": "", +"ESCBackground": "res://addons/escoria-core/design/esc_background.svg", +"ESCBaseCommand": "", +"ESCCamera": "", +"ESCCameraLimits": "", +"ESCCommand": "", +"ESCCommandArgumentDescriptor": "", +"ESCCommandRegistry": "", +"ESCCompiler": "", +"ESCCondition": "", +"ESCDialog": "", +"ESCDialogManager": "", +"ESCDialogOption": "", +"ESCDialogOptionsChooser": "", +"ESCDialogPlayer": "", +"ESCDialogSimple": "", +"ESCDirectionAngle": "", +"ESCEvent": "", +"ESCEventManager": "", +"ESCExecution": "", +"ESCExit": "res://addons/escoria-core/design/esc_exit.svg", +"ESCGame": "", +"ESCGlobalsManager": "", +"ESCGroup": "", +"ESCInputsManager": "", +"ESCInventory": "", +"ESCInventoryButton": "", +"ESCInventoryContainer": "", +"ESCInventoryItem": "", +"ESCInventoryManager": "", +"ESCItem": "res://addons/escoria-core/design/esc_item.svg", +"ESCLocation": "res://addons/escoria-core/design/esc_location.svg", +"ESCMain": "", +"ESCMigration": "", +"ESCMigrationManager": "", +"ESCMovable": "", +"ESCMusicPlayer": "", +"ESCObject": "", +"ESCObjectManager": "", +"ESCPlayer": "res://addons/escoria-core/design/esc_player.svg", +"ESCProjectSettingsManager": "", +"ESCResourceCache": "", +"ESCResourceDescriptor": "", +"ESCRoom": "res://addons/escoria-core/design/esc_room.svg", +"ESCRoomManager": "", +"ESCRoomObjects": "", +"ESCRoomObjectsKey": "", +"ESCSaveGame": "", +"ESCSaveManager": "", +"ESCSaveSettings": "", +"ESCScheduledEvent": "", +"ESCScript": "", +"ESCSoundPlayer": "", +"ESCSpeechPlayer": "", +"ESCStatement": "", +"ESCTerrain": "res://addons/escoria-core/design/esc_terrain.svg", +"ESCTooltip": "", +"ESCTransitionPlayer": "", +"ESCUtils": "", +"ESCWalkContext": "", +"EnableTerrainCommand": "", +"Escoria": "", +"EscoriaPlugin": "", +"HideMenuCommand": "", +"IncGlobalCommand": "", +"InventoryAddCommand": "", +"InventoryRemoveCommand": "", +"PlaySndCommand": "", +"PrintCommand": "", +"QueueEventCommand": "", +"QueueResourceCommand": "", +"RandGlobalCommand": "", +"RepeatCommand": "", +"SayCommand": "", +"SchedEventCommand": "", +"SetActiveCommand": "", +"SetActiveIfExistsCommand": "", +"SetAngleCommand": "", +"SetAnimationsCommand": "", +"SetGlobalCommand": "", +"SetGlobalsCommand": "", +"SetGuiVisibleCommand": "", +"SetInteractiveCommand": "", +"SetSpeedCommand": "", +"SetStateCommand": "", +"ShowMenuCommand": "", +"SlideBlockCommand": "", +"SlideCommand": "", +"SpawnCommand": "", +"StopCommand": "", +"StopSndCommand": "", +"TeleportCommand": "", +"TeleportPosCommand": "", +"TransitionCommand": "", +"TurnToCommand": "", +"WaitCommand": "", +"WalkBlockCommand": "", +"WalkCommand": "", +"WalkToPosBlockCommand": "", +"WalkToPosCommand": "" +} + +[application] + +config/name="Escoria" +run/main_scene="res://addons/escoria-core/game/main_scene.tscn" +boot_splash/image="res://addons/escoria-core/design/escoria-logo-small.png" +boot_splash/fullsize=false +boot_splash/use_filter=false +boot_splash/bg_color=Color( 0.960784, 0.384314, 0, 1 ) +config/icon="res://addons/escoria-player-creator/graphics/icon.png" + +[audio] + +default_bus_layout="res://addons/escoria-core/default_bus_layout.tres" + +[autoload] + +escoria="*res://addons/escoria-core/game/esc_autoload.gd" + +[display] + +window/size/width=1280 +window/size/height=900 +window/stretch/mode="2d" +window/stretch/aspect="keep" + +[editor] + +search_in_file_extensions=PoolStringArray( "gd", "shader", "esc" ) + +[editor_plugins] + +enabled=PoolStringArray( "res://addons/escoria-core/plugin.cfg", "res://addons/escoria-dialog-simple/plugin.cfg", "res://addons/escoria-ui-9verbs/plugin.cfg" ) + +[escoria] + +main/game_version="0.1.0" +main/game_start_script="res://game/start_game.esc" +main/force_quit=true +main/command_directories=[ "res://addons/escoria-core/game/core-scripts/esc/commands" ] +main/text_lang="fr_FR" +main/voice_lang="fr_FR" +main/savegames_path="res://saves/" +main/settings_path="user://" +main/game_migration_path="" +debug/terminate_on_warnings=false +debug/terminate_on_errors=true +debug/development_lang="en" +debug/log_level="TRACE" +debug/log_file_path="user://" +debug/crash_message="We're sorry, but the game crashed. Please send us the following files: + +%s" +debug/enable_room_selector=true +debug/room_selector_room_dir="res://game/rooms" +ui/game_scene="res://addons/escoria-ui-9verbs/game.tscn" +ui/items_autoregister_path="res://game/items/inventory" +ui/default_transition="instant" +ui/transition_paths=[ "res://addons/escoria-core/game/scenes/transitions/shaders/" ] +ui/inventory_item_size=Vector2( 72, 72 ) +ui/dialog_managers=[ "res://addons/escoria-dialog-simple/esc_dialog_simple.gd" ] +sound/master_volume=1 +sound/music_volume=1 +sound/sfx_volume=1 +sound/speech_volume=1 +sound/speech_folder="res://game/speech" +sound/speech_extension="ogg" +platform/skip_cache=false +platform/skip_cache.mobile=true +ui/default_dialog_type="floating" +sound/speech_enabled=1 +ui/tooltip_follows_mouse=false +main/escoria_version="" +ui/dialogs_chooser="res://addons/escoria-core/ui_library/dialogs/text_dialog_chooser.tscn" +ui/default_dialog_scene="res://addons/escoria-core/ui_library/dialogs/floating_dialog_player.tscn" +dialog_simple/avatars_path="" +dialog_simple/text_speed_per_character=0.1 +dialog_simple/fast_text_speed_per_character=0.25 +dialog_simple/max_time_to_disappear=1.0 + +[input] + +esc_show_debug_prompt={ +"deadzone": 0.5, +"events": [ Object(InputEventKey,"resource_local_to_scene":false,"resource_name":"","device":0,"alt":false,"shift":false,"control":false,"meta":false,"command":false,"pressed":false,"scancode":16777245,"physical_scancode":0,"unicode":0,"echo":false,"script":null) + ] +} +switch_action_verb={ +"deadzone": 0.5, +"events": [ Object(InputEventMouseButton,"resource_local_to_scene":false,"resource_name":"","device":0,"alt":false,"shift":false,"control":false,"meta":false,"command":false,"button_mask":0,"position":Vector2( 0, 0 ),"global_position":Vector2( 0, 0 ),"factor":1.0,"button_index":4,"pressed":false,"doubleclick":false,"script":null) +, Object(InputEventMouseButton,"resource_local_to_scene":false,"resource_name":"","device":0,"alt":false,"shift":false,"control":false,"meta":false,"command":false,"button_mask":0,"position":Vector2( 0, 0 ),"global_position":Vector2( 0, 0 ),"factor":1.0,"button_index":5,"pressed":false,"doubleclick":false,"script":null) + ] +} + +[locale] + +translations=PoolStringArray( "res://game/translations/game.en.translation", "res://game/translations/game.fr.translation", "res://game/translations/main_menu.en.translation", "res://game/translations/main_menu.fr.translation", "res://game/translations/game.de.translation", "res://game/translations/main_menu.de.translation" ) +locale_filter=[ 0, [ ] ] +translation_remaps={ +"res://game/speech/room01/ROOM1_look_wall_item_1.ogg": PoolStringArray( "res://game/speech/room01/ROOM1_look_wall_item_1_de.ogg:de" ), +"res://game/speech/room01/ROOM1_look_wall_item_2.ogg": PoolStringArray( "res://game/speech/room01/ROOM1_look_wall_item_2_de.ogg:de" ), +"res://game/speech/room01/ROOM1_look_wall_item_3.ogg": PoolStringArray( "res://game/speech/room01/ROOM1_look_wall_item_3_de.ogg:de" ), +"res://game/speech/room01/ROOM1_look_wall_item_4.ogg": PoolStringArray( "res://game/speech/room01/ROOM1_look_wall_item_4_de.ogg:de" ) +} + +[network] + +limits/debugger_stdout/max_chars_per_second=99999999 + +[rendering] + +environment/default_environment="res://default_env.tres" diff --git a/game/dialog_avatars/mark_talk_down_right_2.png b/game/dialog_avatars/mark_talk_down_right_2.png index 20af765e517cbf0c99ae9e471a586c642223598a..3f4eca58b544eb544340fad049f60ba7595de818 100644 GIT binary patch literal 10564 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
0&ewR3dVSV|Y_R zFnw$HSDd4zAYkrjkAAV@VR)E%+>a^z<5q9)3OPNICaQ9P>SU{Ca{=s9bY!EPl;XD{PoYK-4JGyLoL*QJ6;llTyP&2{GK zXzKC%QjKS=4g>sxsRTTIFI!q|UvhqZFkMjM<+%|saFE%j_SW89Qg$QnIcpE@HqV-3 zJx>VO78Hnz>yHBf_Q&_*5tMF?2V7*0e9 r*tp??mJc*`77?=1!p74i?pZG=*5rR8cqfIc3xI~IF1$+FCiH&*|1dT8 literal 7318 zcmV;H9BJc;P) zaB^>EX>4U6ba`-PAZ2)IW&i+q+O3*ra@@MMh5us|cL>N~IEYnu25yoTq`(qHFyj;D_gykBR0J#Omj9baD;a_<+uUqN@)@9Xm*Iqsk1F1{|*_VY__ zwR|4xcwK0|PP{{T{f{5hyI=a-d^u2v(n{PYc)x=S_WrET2!j5*(0SF*5Okj7wTBp@ zxi4=QBOqU<_x5V-=Ky^P@_xnCe2@P7Z{LFN`|Ei47R&s0q5Sh3E`2*5-f!bS-#EN} zGaUZ%MoF&xGM(4|b5=cPKeOvG6Vd#ts2gneb{S5js&2?CBg?k%Kk<9H-;M8TyPc$b z*=Yyg(>3SG$}ujw<+?j=-`D9TLyUg=!mIa_MCn)!#Wz21#-hI6@g=mdLM4~eZ$tWG z@b6=B_rC4kZ_*CSF2||faWTh7e*10y^ya_$Hs?%*$l3bDiMn81UUkhdlsWz6EE3|* zD{tur`0e|Ze*39@C{;3;ZkQ_*>~=ht7|DIqR=9Z%oR@fgTF9BQUKb!l+&eKC7s!Ck zE+m(oE#4RBh+`!|oss(x{U8G_CBGP?k0E4limzVx<}=0JbA9sJ>oC|vB2vhqkee1d z$%-*iKP6UbsHc!(N-3w3s!1*N9CFMl=UlQtu9r|^NhOz3YH6j{P-9Is*HUY3wKv}a z7?@garPbD2@7{E7)VWsY{LYc#M;LLWkw+PIw9zN!GviD%&ob+5voF8G0wz{oW!2SI z-_C51V#l3!-euR_c0bhG2`8R(@+qgDcKUnP+^cQBfB%cDxmVWw&6Lh7?^)xhDdp`F zPH>WxGcx9*BjZIGprE~SW~+ zU**mJQ|63P_y3VOL+XCb+Yeb=;<e>Jw( zw%2lNj@KxJdvS%4sX&S~QhUD5z|qs5)n!nihYbmie=HgG38)B7Y8uPO4U)vr-pELv?p+>GWoep)i9EeXuQ!8e_`l;w$426=)x|C=_jfugN?M- zNS?800Zbj#jPt@hlj%PJOvz!Nv|CB7Y|lI*edb21+tsyo18Pl2!wGgzKPEzwgw1Pdiz zOQ4ugOPy9obZ8gS&pn7dcguvQOkMPN+UIbjq-AKD1$KK?fNjI4s7p_}2T0{007j=F z*qHBP_MkxNz*fx+-^Zva&*q!~dS(x!sstHA+;cjTMDjdCKy)8UtZ%N_=)5rsAe4{V zW$b-gtyCNh%80y5hGLH4kmp@%-Z`XmxMgn_P)c+g2Kh6Tn2!UwM(UxH7J4{=rrq5F z=p8VjCW!8r7!g_tBP3zQ`<<% zMPkNmK>99J5FG?m!jusV2G|oCd5>9XlNG+7hBO{&26Kda9>O>_Gs_AiF?T`@uoAb? z0sRs4@;%WV@ib3!dP;EZ)dM7-NjL{hr#}#hiQ>-=>gUZgR!2{Iaz*t!@0(~u;}!NEcSl9|Uxy)iafvVj>93%D%%+a5crXDsyJzfaLr`{nHC z+@H?m#7S$ETM~ZrlA%g|&k6a^&0G1(4l|{a7%&)gW;-xYwhXk*d@6>7lF(-gf0C${ zVdRO>qRGfHF1sSUJFNv(qo6ad`vq>;uMxH8Ex-n-r86Dvp2#`#%Qp3Vcm=in?r zoqHi6>PZu+T&OtRYl)!{Gxzt5{U7n$O(zjCzYY@N@LXd(9Jg=%9I$%ASs* z(gG^Cq*p;tbleXG{r+lxDCk?x2vu-U5+ss|zQ3!Q3z zFL+S*4;5W$k(xR{2p6SWAW`VFn1S5dmh% zk_Y+vc{Pk=$@c4!I0U7NO)OljsW`xjz8IT;iIy1dFjcOq7x+FDsRX|t+}mhFGQMs` zXS!0ZA!={T0`n|_XhH}&4m_2~m_*y!hUyU2J5lej95@$noj6YDy5=syTZiOH;ACon zsLg@0#?!S@z0Ia1FcxmJOeGfTh5;pVHpSV!mYx&^+ODibBEWPMC_q7ux1s@c!k`B+ zTCjn13;}>h@gb9ByTj)Yo5YjB@*#NJ<$92Hm#5tntpe&BA;k=^2`0mRK}%4cT;@(0 zEvSy_J1`7Xei3`tTs(4<(e1#Gid7_EjrFqKgGa^i}UZ{*gI_?p<|V3O#Hm#~ zx$6~O7cU%(v8B$Fg*^;HLo7o3p?YgN(z6&dDodDLt_`ZY^><%S!wX&OIVs?CmO z(X7~A$8czI2o2gMX|QO(iEvl~FC$OWL9L_H`?Uo8KB&KH7Vyazwo_}|8<|9G#r;T> zjLj;ou8_t{)Xw-jlr$gcxV1WZ9-EL)d`RI$w9Scn8%hJj>3EqOtU{Nv3$;9qYnTRT zjQMhFfr^!u#IF@f7=MKqiL(VMe-MKka3PUe1X9DHs%nZY209xNL7pg$lyR?w!NXPr z1Jvvek*IHOBxa`c@TMz+HPT;~<%m++BOLe{gk)|*EON^b1acVU%n0$+i{eC%0@F~P z1|U%$Q0|&uxfiPlMtM;q+l~Uqr=ud9Ta9iy16rsJWpcZ);Jtuj?tsR}&w;dB-bjwB z!D~@7ttEp%IS?8Z_)k+%pV8!tK9Rtn4QYIyfWJ97I4&-?bb07w zLPfaVlW!R0e;Izdlw}$gowg+pBFozo}ik_;}{R2s;QeJx@U zzcbiVeZ$=K3DTp{=!f~tFMeuIgn<@>KwgRk4o3vzHLSyhEd#`1(qY=LdxjCH0U2^t zNf*=3yAlGeksVOG`ZL?OI zkjE4=dK_9irr#c$7frcj!7F*U7$MmLGzl%{tsqsgPe{4iA~T`gF}`(cwIVsj6o&EO z-vsvpY0!p^b($C0hem5E(AZvx6M&?Q6!1-!0_9llF#HodTSo5y_1B6*!|i$uS9{ z0J9ZAQjsWGt(-(GMS3viDx?Zijg?Pv!UF*ioI-bCQonpar*EUPJC!d4&_$){<=s!n z(M!INLm?l_+*(yRy*y`C`4lko!rOI$F@Z-ifzR7F#K)y5ALYXK z`tV~^iT2IkLE>zpto7(a$7ZA)29N?bc&fPQ+cV;BA*Zm{)#xOC$PMNc9W{m!B@rMn z>Qk#@Tmi|}ve(Ke(FvxZRA}IPvY$w3YL1DPh0@wV2B4kqZDhx_MK4Q*Q$qEb2TT=8 z!Z>Vr*|5ii{c`%-*@%g6Hp=|9kNRq(sN#kQ$50ORfy4N9rkDc0bS@xLVtFBqpgA`o z@tOUy9@LHKb2Jg0jGaX;`mpZ`=tvgvJJK@L{s>EA76t_QP%yO5f_GrTo8aA{SYQZk z-kx?yH_z95$$4$Gd^dp{33Jgz1un>KLX6ns0UrXu3%L)KQF$cx+wuY>PPKPK z=3Ms{E?pLsRS?`uP5B@2pf>5@-f+s?1_jq$2p&OTxOk$VJU#=I1&ziiSZrF>%IpPt zcHIP`dptk}*GoKR#jI)IUKBOEakV-wMUx1#wrAdRa<{ETh&`Ejk#T`cJvrZKmQ}$# z?g|S%BZuVXC+YW>uc2x^w%Q5x(1)_l?t~Bw6jSjDTK~e^YQc?}oSPtUz?gu1m-gbK! zDeO)S!VNUDKSI@3T;?Ws)e!?W+Zb+W(ar6GKhov#TPVfrj&`L0WPa@ghIHH}Q`~xL%c@RXT~&Ee zIf5?)&j`NLuc*CPdN%ks#=Xw!PKk4zkB6jqX=QBz(+?`v(l=y_i7pdq!wl5nj(NXU z-j4C>SPv}VWwYw5z=fCFv>JmKFBOM_O-E~QL=N!AKTsK57(T2x!`z7=;Ev#nhNcuz z?{0g;%5v~cM@RG%iK&}PqQB0wvP}VyfPTj#|3YVg{d)T&DJ?itU&hGha*L~dB ze7ZAff(U#DN?`3KkJW!Yf>@aegp2eNE{P26)@&h0xYH3Zd20;r<6NN7X>dJof|I!r zU1CJ~x+v+GP?J~?h=|U{S2VN>;Wdk#p#1Z?+pvWmbf{vk7@+-Hs2q;Xp0#3uDGavm z(b1jfTdkYV#g3XrX9CG8B#P4=U>)wJZUA})ywPJ}4Ai~Dk3c)c1L{3l5VC3^gfp}E z3?Dc4;-cKM|2KI4Wo5L)wk?JL-HeaOxsf}}sfz&>iZ;})0eZhtk4=oPE>=bR*5OTUr zv#$YWfm2@kQ7hGS%-FnX&U2-Y>o8$@Y*;jb_C|5okTjT562<6oP9fZf2JcfNcZs!9 zX4f3g*P2;%5H{Q~iO+eKot}{qoziaA5NpJXgVDG;GO3NMwmSqHW!1GxeV%n$$f369 zBXvFN{MO$sUW^tsif}?%ojQnM(JEAEofbl8=ZT=UsM%WO{veE%t?rrPKx0vcNG6DB zM#@49{ckp1@%rS-|N2RmudjGD$#yS#xfvd2%fMo%Fk$41hCr`irTwNIfRx~4k!WoR zFN_h#K|AdV!b>sKj7xEt5QMDpDD$F62$K3^rlv<|Y(p!{WlA%lM(HlV>;&Lji#(gg zC3|>BElSnPq$XeouD?%`c0dZfLLKdAtv}2j(b3Y86cb&*KvLx-p!*(`&zV|_GT2Wq z_TJjT)Fg5DRSPFat9u@yOhJu&+c zNiF=8Dr*h7%-vGgLkTG@$ZD%qqxSGQEi@cLwD`zbv7-6Ty(KLxAmZp;4SK3E7w|U&ig)1MftX&$K~XMh_dH1#1@yW&FA}R?WpUs42xRq zMSP`)^@N4wcK8;p7FfU?R2=!ylVj9GhxDg$9q$@zi&|Pp<3fn`=bIkMLF+*CxQ(Dk zptRT*_sSf_m-T90PDm$9Az}RNeb!44c7XU^kI$WUB*v-Mqvijo)d#MlE)faCAR*OJ zF~&s;ab9~mDHtv|1d9!J=h9g*0AHyI!W#!Nh+1%dbrJ;VmIf_*t)Ec=T0GXHE7-_l z7|2`E+-(eQMuyO8OR)vjuuo8rb~Lao$xo1cF*7|A5>U-z<$nCauJ1FkQqHa6o}ncv zu0RLjv?eZvQd>(crQbpnJs>ckW#6<5gpQ;L>TfEmM0>BcrS9P4Z51i0h<#@&zidJ#XU21w7 z*u9=!c|T=o7Y0vD?WXHq&}H{=kA$&0;g>xj?ftKYfchWB{BN=f!S*Qt00D(*LqkwW zLqi~Na&Km7Y-Iodc$|HaJxIe)6opSyMUjew9Ymx=s7@9{MI5yXMW_&Jg;pI*Uit@3 z8j=(jN5Qq=;Ll>!!Nplu2UkH5`~h)ub5eAX67Ne2En>XzcpvB8b9nDQK&Y3QW_64M znr@q^L|n{dSH-SZ1Q0<8!-&YtGUg;H3E%pGj4P0EeG-VIC+yMrj4B3=jDM(Am=YjV#`lc+kQ`uxacB(Rouu3*UE6v9P(r! zH5W%}F78;NA==tXzIvXXRt3YMNR?ASMovQ2DlW(XWv9Sypq4Un5&$3x zJhKe50ZHI-c6Dv;M+XN0z{cy41n&j_U^QPf*V(E8D{p;jm_5lW%QMKxNrXcYGb9Ix zN477GmtUUInHo)zlR5yXT7^00rMp}7M`K9HyM(z9>M2*Xild@x_pZ`6Czo<0>PLHf z0Btg0#Vd)K;O%@=J+_FSftz*BRPU7U0cO+y3< zK(?!0$(rc-odRhJfdY_}%g9d1yVi>H9-^|UAxz0m%FtD0kUlvNGs zU_kf$Y%zpIj^OkASI@-41OOnnm4o$s?dgO4Rgn$`bde(vIf5P^kBH!d$PveoGtNbh wP|=Wj$^oFqXYb(WuZoGrP;St@_T@nF0|05Tq0Q>LrT_o{07*qoM6N<$f)b$h761SM diff --git a/game/dialog_avatars/mark_talk_down_right_3.png b/game/dialog_avatars/mark_talk_down_right_3.png index a01d02a5aafd1593bc7dde06ef3204a7719aee8d..a6f9fbed3ff3cc70a52e635a1b436899d7701ee8 100644 GIT binary patch literal 10566 zcmeI1cQl+`*Z)WFy+sR#XfX_C7(IILB}fRyFrzc01ks~}5WV*rf(WD6L`@JxNzn;H zf<%-=$vbl2&-2{(`n~@=YyIB;?wK_+*LBX`pMCcC>~pO->%jQh^qV*CIATwxD1v&5L#`*VBwcsiln5Zsu%UI=bP0Llpf2zXzf4$d#p-Q1?$8yJq=(WMq`N1{)mG_(tDn7CmJlUi;wk=Y6^Q>*=+bQEPAd6J+V}K6cCW#z!P~Pl;3hYUUjm}WyM}9(CNrr|KprwD*>y68?TPUo zZM%sdj(yulXiJv{Sr!A7?zM8w8U-I5IEif!ao$m(xNepr@A)3SUkLX;ZXPp0?^(1R z_;742e(Z`E1E4cnQd z%>W=KrK@)uC@NV@7jDeKab;e z(I`ES<;_mkWc6*D6!<8)rYHGYV#lpftmiqtl7%f|X2xR4!&FCZx9LE%W4HOVc-jCg zP=NU+R9WEn(|LCOL-SJTh4SotE;LlKoZyx7>`7Bvk}j-I+hklTOL{W-YYC&#gsn{D z%)nN<%*RnF!<&4sxl?_b^CUEg*ZdSYkCWxr3KN9Uzv?@)>3i14e%+CDPHPX%YEwEm zGMyEbdY#))Nx@{szNOf`ggt$)?ibpb^P1+TUcT{0qf?8(?sy)#^4E^B3BMeL^j%F# zbbn)ulH9=aC>h24cltCnrxUMs^PZutM15OK#VT8UNQd?|ACgY=nUqKMZe=LwozbSh z(fjGc%z~|KkqgP`JjA#3Ta>^KzgGXqawe-NG>Mo(u=p>W)ijI)vENuRDgG2 z!-*qt$~D|dgeayRNlEg3#pHg;;mlTu_?%oX-@^WZ>-X!XmJHXLTSs-udFbY=qj zqN#rMGUkg;9mEUwgS8kPx5+17E;L)k-tzRW88_u@G_9=}d*MX^Ri&;GaOD%(+#JWN zKE2tX(#xnVrn^y7(wHLVY!o$FbL5DlHyNKwjme8Xb{}sA#gN^|f3#6iDbJHXM)ROoIkOA# zZE{XN_TKKW?@_Ubj&#k?tbnn4U&4wE{>cjeeJQPb8wIhVPv>rW_GeDcroVWH*d81* zy?6ixIqZx^0%&3P20pFqkN9MFrbC@TdY#D|&F-!rCcEOf0d_oK1JaUIQ__^gmk@cI zRw;9vIl{=b#bLpeSVBRM)WJNV5GQ$nug$nBdtV0!L!{4#gf?>FBIC0VFy@sPa%MW@ zw6tGK9+0QaMmBz*di´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

Aq< zg*hkOFVLe=bJIYNX|IDPA0NLJBAdM}{lc`f<1pVpW*{7d+pH9Z0;Cxx%n3Czlt8Fi{((RPtw%dS6+{W+huP8HLGlC vrR@M)hwtPLe$=?#wa3rJ)Q8GE`Gsf3R!`zvU2TLb3V^n{fm)r4UBv$Y)!sXg literal 7032 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