Creating custom ESC commands
Escoria is designed to abstract and streamline the most basic features for game developers and at the same time give them a lot of freedom so they can design the game they have in mind.
ESC is the domain specific language (DSL) used by Escoria to make very basic features of narrative and point and click games as easy as possible.
There are a lot of commands already included in Escoria core. If the game developer requires more commands for their specific game, it is very easy to create new commands with just a bit of GDScript knowledge.
What is an ESC command?
ESC commands consist of two things: a name and a group of one or more parameters.
say player “Hello!” <name> <parameter 1> <parameter 2> <…>
name only allows the following characters:
Lowercase characters a-z
Numbers from 0-9
Underscore _
The parameters are separated from the name and other parameters by whitespace.
If a parameter is surrounded by quotation marks, the parameter may include whitespace as well:
say player Hello!
(2 parameters)
say player “Hello! How are you doing?”
(2 parameters)
say player Hello how are you doing?
(6 parameters)
When compiling an ESC script, Escoria checks each command to see if it matches a defined set of parameters and also if the parameters have the right data type.
Additionally, a command can include a function which can test the given parameters for validity in depth.
How are ESC commands integrated?
When the ESC compiler encounters a line that it identifies as an ESC command in an ESC script, it searches for a GDScript file with the same name as the command in a list of directories (according to the :Project setting “Command directories” in the main category).
It will load the first file it finds and validate the given parameters. If everything works out fine, the command is added to the event and executed by the event manager later.
How is an ESC command structured?
Let’s look at the source code of the command camera_set_limits. It can be found in the directory addons/escoria_core/game/core-scripts/esc/commands, a directory included in the “Command directories” setting by default. The file name is “camera_set_limits.gd”
# `camera_set_limits camlimits_id`
#
# Sets the camera limits to the one defined under `camlimits_id` in
# ESCRoom's camera_limits array.
# - camlimits_id: int: id of the camera limits to apply (defined in
# ESCRoom's camera_limits array)
#
# @ESC
extends ESCBaseCommand
class_name CameraSetLimitsCommand
# Return the descriptor of the arguments of this command
func configure() -> ESCCommandArgumentDescriptor:
return ESCCommandArgumentDescriptor.new(
1,
[TYPE_INT],
[null]
)
# Validate wether the given arguments match the command descriptor
func validate(arguments: Array):
if not 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" % [
arguments[0],
escoria.main.current_scene.camera_limits.size()
]
]
)
return false
return .validate(arguments)
# Run the command
func run(command_params: Array) -> int:
escoria.main.set_camera_limits(command_params[0])
return ESCExecution.RC_OK
Documentation
The command starts with a documentation block which is used to create the API documentation for the command. The “@ESC” tag is used to build up the ESC reference. It is recommended that all custom ESC commands include a similar documentation section.
Class definition
Every ESC command has to extend the class ESCBaseCommand
and include a
class_name
statement. The class name is a PascalCase variant of the comamnd
name with an additional “Command” suffix. So the file my_custom.gd would have
a class name of “MyCustomCommand”.
Configuration function
The function configure
is used by the ESC compiler to return an
ESCCommandArgumentDescriptor
instance which describes the command
structure. The parameters to the ESCCommandArgumentDescriptor
constructor
are:
The number of mandatory parameters
A list of the types of all possible parameters. If the command is called with more parameters, the data type of the last element of the list is used. The data types correspond to the GDScript enum Variant.Type
A list of default values for each parameter. Mandatory parameters should use null` as the default value.
Validation function
The function validate
is called by the event manager prior to running the
command. It can check the given parameters and validate them against the
current state of the game (e.g. registered objects, active/inactive state,
etc.)
In the example, the command checks if the given camera limits ID is valid. It
should run the validate function from ESCBaseCommand
, which will validate
the parameters according to the ESCCommandArgumentDescriptor
returned by
the configure
function.
The run function
Finally, the run
function is executed by the event manager when the
command is successfully validated. The function should return an
ESCExecution value, which informs the event manager
whether the command was run successfully.
An example custom command
Bringing the different parts together, below is a complete example of a custom command which the developer can place in a custom directory. The custom directory should then be added to the list of “Command directories”.
# `my_custom object`
#
# Runs a custom command on the given object.
#
# @ESC
extends ESCBaseCommand
class_name MyCustomCommand
# Return the descriptor of the arguments of this command
func configure() -> ESCCommandArgumentDescriptor:
return ESCCommandArgumentDescriptor.new(
1,
[TYPE_STRING],
[null]
)
# Validate wether the given arguments match the command descriptor
func validate(arguments: Array):
if not escoria.object_manager.has(arguments[0]):
escoria.logger.report_errors(
"my_custom: invalid object",
["Object %s not registered" % arguments[0]]
)
return false
return .validate(arguments)
# Run the command
func run(command_params: Array) -> int:
# Do something with the object
return ESCExecution.RC_OK
Using Escoria classes
Please refer to the API documentation on how to use the specific classes used
by Escoria. The classes are usually available in the
Escoria main singleton.
(e.g. escoria.object_manager
to access the
ESCObjectManager)