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 84cc6767..5ba387cf 100644 --- a/addons/escoria-core/game/core-scripts/esc/commands/custom.gd +++ b/addons/escoria-core/game/core-scripts/esc/commands/custom.gd @@ -1,16 +1,17 @@ -# `custom object node func_name [params]` +# `custom object node func_name [params...]` # # # Executes the specified Godot function. This function must be in a script -# attached to a child node of a registered `ESCitem`. +# attached to a child node of a registered `ESCItem`. # # **Parameters** # # - *object*: Global ID of the target `ESCItem` # - *node*: Name of the child node of the target `ESCItem` # - *func_name*: Name of the function to be called -# - params: Any arguments to be passed to the function (array and object parameters are not supported). Multiple -# parameters can be passed by using comma-separated values inside a string +# - params: Any arguments to be passed to the function (array and object parameters are not supported). +# Multiple parameters can be passed by simply passing them in as additional arguments separated by +# spaces, e.g. `custom the_object the_node the_function arg1 arg2 arg3` # # @ESC extends ESCBaseCommand @@ -22,7 +23,9 @@ func configure() -> ESCCommandArgumentDescriptor: return ESCCommandArgumentDescriptor.new( 3, [TYPE_STRING, TYPE_STRING, TYPE_STRING, TYPE_ARRAY], - [null, null, null, []] + [null, null, null, []], + [true], + true ) 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 7ad7b699..5c95fe38 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 @@ -42,14 +42,14 @@ func _init(command_string): ).strip_edges() ) for parameter in parsed_parameters.split(" "): - if parameter.begins_with('"') and parameter.ends_with('"'): + if len(parameter) > 1 and parameter.begins_with('"') and parameter.ends_with('"'): parameters.append( parameter ) elif ":" in parameter and '"' in parameter: quote_open = true parameter_values.append(parameter) - elif parameter.begins_with('"'): + elif not quote_open and parameter.begins_with('"'): quote_open = true parameter_values.append(parameter) elif parameter.ends_with('"'): 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 73d7014f..6d40f187 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 @@ -30,24 +30,30 @@ var defaults: Array = [] # Whether to strip quotes on specific arguments var strip_quotes: Array = [] +# Whether the final argument is a series of varargs +var has_varargs: bool = false + # Initialize the descriptor func _init( p_min_args: int = 0, p_types: Array = [], p_defaults: Array = [], - p_strip_quotes: Array = [true] + p_strip_quotes: Array = [true], + p_has_varargs: bool = false ): max_args = p_types.size() min_args = p_min_args types = p_types defaults = p_defaults strip_quotes = p_strip_quotes + has_varargs = p_has_varargs # Combine the default argument values with the given arguments func prepare_arguments(arguments: Array) -> Array: var complete_arguments = defaults + var varargs = [] for index in range(arguments.size()): # If we have too many arguments passed in, complete_arguments won't @@ -55,22 +61,32 @@ func prepare_arguments(arguments: Array) -> Array: # to avoid duplicating validation code, just grow complete_arguments # since the arguments won't be used anyway. if index >= complete_arguments.size(): - complete_arguments.append(arguments[index]) - continue - - complete_arguments[index] = escoria.utils.get_typed_value( - arguments[index], - types[index] - ) - var strip = strip_quotes[0] - if strip_quotes.size() == complete_arguments.size(): - strip = strip_quotes[index] - - if strip and typeof(complete_arguments[index]) == TYPE_STRING: - complete_arguments[index] = complete_arguments[index].replace( - '"', - '' + if has_varargs: + varargs.append(arguments[index]) + else: + complete_arguments.append(arguments[index]) + elif index == complete_arguments.size() - 1 and has_varargs: + # Varargs are a special case and need to be gathered and added at + # the end as an array, untyped and unchecked. They should also only + # appear at the very end of a command's argument list. + varargs.append(arguments[index]) + else: + complete_arguments[index] = escoria.utils.get_typed_value( + arguments[index], + types[index] ) + var strip = strip_quotes[0] + if strip_quotes.size() == complete_arguments.size(): + strip = strip_quotes[index] + + if strip and typeof(complete_arguments[index]) == TYPE_STRING: + complete_arguments[index] = complete_arguments[index].replace( + '"', + '' + ) + + if has_varargs: + complete_arguments[complete_arguments.size() - 1] = varargs return complete_arguments @@ -91,7 +107,7 @@ func validate(command: String, arguments: Array) -> bool: ] ) - if arguments.size() > self.max_args: + if arguments.size() > self.max_args and not has_varargs: escoria.logger.report_errors( "ESCCommandArgumentDescriptor:validate()", [ @@ -104,6 +120,11 @@ func validate(command: String, arguments: Array) -> bool: if arguments[index] == null: # No type checking for null values continue + + if has_varargs and index == arguments.size() - 1: + # If we have varargs at the end, do not validate them. + continue + var correct = false var types_index = index if types_index > types.size(): diff --git a/addons/escoria-core/game/main.gd b/addons/escoria-core/game/main.gd index fa528217..558a6e56 100644 --- a/addons/escoria-core/game/main.gd +++ b/addons/escoria-core/game/main.gd @@ -75,7 +75,8 @@ func set_scene(p_scene: Node) -> void: # # - p_scene: The scene currently being initialized by set_scene. func finish_current_scene_init(p_scene: Node) -> void: - move_child(p_scene, 0) + if is_a_parent_of(p_scene): + move_child(p_scene, 0) current_scene = p_scene diff --git a/game/rooms/room03/esc/room03_bridge.esc b/game/rooms/room03/esc/room03_bridge.esc index b796ad49..48d58ac8 100644 --- a/game/rooms/room03/esc/room03_bridge.esc +++ b/game/rooms/room03/esc/room03_bridge.esc @@ -2,6 +2,7 @@ :setup +custom r3_r_exit door_enabler enable_door a b c 1 2 345 # If the room hasn't been visited previously, open the bridge and break the button > [!room3_visited] @@ -21,7 +22,7 @@ # We use a custom function to enable the collision polygon on the door # to enable it to work as a door once the bridge is closed. # You'll find the script in room3/Hotspots/r_door/door_enabler - custom r3_r_exit door_enabler enable_door + custom r3_r_exit door_enabler enable_door > [eq ESC_LAST_SCENE room2] teleport player r3_l_exit @@ -67,4 +68,4 @@ # This is for when you close the bridge then go back to room 2 # Set the bridge closed - set_global r3_bridge_closed true \ No newline at end of file + set_global r3_bridge_closed true