FAQ

How do I specify the first game room?

An ASHES script is used to tell Escoria which room to open as your game’s first “room”. The script is configured in Godot’s settings under Escoria/Game Start Script.

Start script configuration location

This script needs to contain two events:

  • :init - this event will run as soon as Escoria has been initialised. Place any commands to display company logos or short opening cutscenes here (see How do I add a company logo or introductory cutscene?). Alternatively, use :init to just display your game’s main menu.

:init
  # Show main menu immediately without a company logo screen
  show_menu("main")
  • :newgame - this event will run when the player selects “Start New Game” on your game’s menu. This needs to include a change_scene call to open your game’s first room.

:newgame
  change_scene("res://game/rooms/startroom/startroom.tscn")

How do I implement puzzles?

Puzzles can be broken down into two broad areas.

  • Escoria script puzzles

Escoria script puzzles are ones that can be completely made using Escoria script; that is, ASHES. Demo room 9 provides an example of this. Through the use of inventory items and game variables, puzzles can be progressed and their statuses determined.

An example of this is getting past someone guarding a door who requires a pass phrase to proceed. In the game, when the character “looks at” a note on a computer that reads “the password is abc123”, an ASHES script can be used to set a “password_obtained” variable to true. When the character later talks to the bodyguard, the script logic can check whether “password_obtained” is set to true and, based on that, provide new dialog options, or run an animation to move the guard away from the door.

  • GDscript-based puzzles

In the event you want to include a puzzle that requires more complexity than an ASHES script can provide, you can use native GDscript. Demo room 8 provides an example of this: The spawn ASHES command is used to spawn the GDScript scene that contains your puzzle (arcade puzzle, etc). Example:

spawn("puzzle", "res://game/rooms/room08/puzzle/10_buttons_puzzle.tscn")

Your Godot scene can contain anything you like - you’re only limited by Godot’s limitations and your imagination. The main requirements for your Godot scene are:

  • In your _ready() GDScript, you need to hide Escoria:

escoria.main.current_scene.game.hide_ui()
escoria.main.current_scene.hide()
  • As a result of what happens as the player progresses the puzzle, you can pass state back to Escoria via Escoria’s global variables, run an animation to change the look of the room post-puzzle, and deactivate / activate objects in your room as a result of the puzzle’s success/failure.

# set a global
escoria.globals_manager.set_global("r8_m_door_open", true)

# Run an animation to change what the player sees in the room
escoria.object_manager.get_object("r8_m_door").set_state("door_open")

# Make the puzzle no longer available to use as the player completed it
escoria.object_manager.get_object("r8_mini_puzzle_button").active = false
  • When the player quits / completes / fails the puzzle, you need to return control back to Escoria, then delete the puzzle scene using the queue_free() command in GDScript.

escoria.main.current_scene.game.show_ui()
escoria.main.current_scene.show()
queue_free()

What’s the difference between states and animations?

The features offered by the state and animation commands are rather similar. This section is meant to help you choose which command to use.

anim is used for starting an animation and immediately returning control to the next command in the script. This is good for animations that run only once (like part of a cutscene), allowing you to have additional script commands running while the animation is executing. As an example, you could start an animation of a bird flying across the screen, then a separate one of a car driving along - both animations would run simultaneously.

anim_block is used when you want to control the pacing of your game / cutscene and ensure that an animation completes before further game commands are processed. As an example, if you had separate animations of someone walking up to a door and another showing them opening it, using anim_block to play the walking animation would ensure they reached the door before being opened.

set_state is like combining a global variable with an anim command: It retains a state which can be queried (e.g. checking if the door is in an unlocked or a locked state) and runs an animation (if an animation with the same name exists in this room). State is preserved between rooms, meaning that if you set door 2’s state to “dooropen” and leave the room, when you come back, if you query the state of door 2, it will still return “dooropen”.

** Comment required here about whether state will play with “immediate” or not when you reenter a room - still under discussion

** Comment required here once ASHES supports querying the current state of an ESCItem

How do I create a cutscene?

A cutscene is a non-interactive part of a game where the player will watch part of the story unfold. It could be short, like seeing a sunrise through the bedroom window before you’re allowed to make the player wake up and move around, or long, telling the whole backstory of the game and its characters.

In Escoria, the cutscene is created through an ASHES script and just requires a series of commands to show graphics or animate sprites in your game world.

You can start your cutscene when your room appears by placing the commands as part of the :ready event. (See here.)

Alternatively, you can start your cutscene when the player walks through a trigger area or interacts with an object. For example, this script is attached to a “button” in the scene, and runs a cutscene when the button is “pushed”.

:push
  accept_input("NONE")

Blocking

ASHES commands fit into 2 main categories: blocking and non-blocking. Using commands of the correct type is essential to your cutscene running the way you expect it to. You can mix blocking and non-blocking commands.

Blocking commands have to complete entirely before the next command in the script is executed. Non-blocking commands are commands that are started with control being passed immediately to the next command in the script. Non-blocking scripts allow for commands to run in parallel.

Hint

Though blocking commands generally have “_block” as part of their names, some commands that don’t (like wait) will also block. See the command reference to confirm if the command you want to use is blocking or not. See here.

In this first example…

  • The player will walk to location (100,100).

  • Once they arrive, the “queen_arrives” animation will start.

  • As the “queen_arrives” animation is started with the non-blocking anim command, the “cat_runs_to_throne” animation will also start at the same time.

  • Once the blocking “cat_runs_to_throne” animation has completed, the “queen_leaves” animation will run.

walk_to_pos_block("player", 100, 100)
anim("queen", "queen_arrives")
anim_block("cat", "cat_runs_to_throne")
anim("queen", "queen_leaves")
Working cutscene timeline

Hint

Be wary of the lengths of animations when mixing blocking and non-blocking commands. In the above example, if the “queen_arrives” animation takes more time to complete than the “cat_runs_to_throne” animation, the cutscene will not work as expected. The “queen_leaves” animation will commence as soon as the cat animation completes (i.e while the “queen_arrives” animation is still playing).

Broken cutscene timeline

The accept_input command

Another important command for creating cutscenes is the accept_input command. It’s important that the player can’t walk away or interact with items while the story component of your game is running. For this reason, Escoria provides you the accept_input command to limit the actions the player can perform in your game. Generally you would want to disable input at the start of a cutscene and re-enable it on completion so the player can keep playing your game.

accept_input("NONE")
walk_to_pos_block("player", 100, 100)
anim("queen", "queen_arrives")
anim_block("cat", "cat_runs_to_throne")
anim("queen", "queen_leaves")
accept_input("ALL")

How do I add a company logo or introductory cutscene?

A company logo or introductory cutscene that plays before the menu of your game is displayed is optional for your game. To create one:

  • Create an ESCRoom to display your logo or cutscene introduction. Depending on your requirements this may be any combination of ASHES commands and animations driven by Godot AnimationPlayer.

  • Create an ASHES script and attach it to the ESCRoom. Put the commands in here to display your game logo / opening scene (remembering to use the | NO_UI flag so your game’s user interface is not displayed over the top of the logo/cutscene). As this animation will play every time someone starts your game, it is recommended to keep this scene to no more than a few seconds in length. An example script for an introductory logo scene driven entirely by an animation is:

# Example introductory logo script
:setup | NO_UI
  # Play the reset animation to make sure everythings as we expect it to be
  anim_block("intro_animation_player", "RESET")

:ready | NO_UI
  # Play the "intro" animation
  anim_block("intro_animation_player", "intro")

show_menu("main")
  • Ensure at the end of your logo / cutscene that you have the show_menu("main") call to pass control back to the menu.

  • Identify the main script that starts your game. This can be found in Godot’s settings under “Escoria/Game Start Script”

Start script configuration location
  • Modify your start script so that it runs your intro scene as part of the :init event. It should also have a :newgame event to define which room should be loaded when a player starts a new game.

:init
  # Play Escoria logo cutscene
  change_scene("res://game/rooms/logo/logo.tscn")

  # Showing main menu
  show_menu("main")

:newgame
  change_scene("res://game/rooms/startroom/startroom.tscn")

How do I change the characters costume?

There are two ways to change the look of a character: The first is to create an entirely new character (i.e. a new Godot Scene with an ESCPlayer node, animated sprite, collision area, etc). The second option is to change just the animations (i.e. the sprites used) for the character.

Changing the entire player scene

This option might be appropriate if you need to change something fundamental about a character for a particular scene (e.g. if for a specific level you only want the character to be able to walk in 2 directions where they normally have 8 directions defined). If you choose this option, create the character scene, then in your game room (ESCRoom) set the Player Scene parameter to point at the new character scene.

Changing the character animations

Changing the sprite set of a character so they look different (adding a hat, glasses, or changing their clothing, for example) is an easy task: The process involves creating new animations, then telling Escoria to have the character use those animations as its default at the appropriate time.

Create new animations

You should already have idle, talk, and walk animations defined for your character.

Open your character’s animated sprite.

Animated sprite node

Looking at the “Animations” window, you should see the SpriteFrames defined.

Defined animations

Create new animations matching your new spriteset and call them something appropriate. In this example, the demonstration character has had some jester clothes put on.

Updated animations

Go back to your character (ESCPlayer) node and, using the dropdown arrow on the Animations parameter, select the menu option to create a new ESCAnimationResource.

Updated animations

Just like when you created your player originally, set up the correct number of directions for the character with the associated direction angles, as well as the direction, idle, and speak animations pointing at your newly-created animations.

Updated animations

Use the dropdown again, choosing the save option. Give the file an appropriate name and location in the file dialog window that appears.

Assign the new animations to the character

Now that you have the animations defined, you need to tell Escoria when you want to use them: If the player buys a Jester outfit, for example, you may script the use event for the Jester outfit inventory item to change the animation set. The command used is set_animations, and you pass it the path to your ESCAnimationResource file.

:use

  set_animations("player", "res://game/characters/mark/mark_animations_jester.tres")

How do I add audio speech to my game?

Check here for information on how to add audio speech to your game.

How do I translate my game into other languages?

Check here to see how to translate your game into other languages.

How do I add a score to my game ?

  • In your initial game room’s setup script, create a “score” global variable and set it to 0.

  • When you pick up an ESCItem or interact with an NPC in some way that would score points, add or subtract from the score variable either using simple addition (e.g. score = score + 1) or by using the (now deprecated) inc_global and dec_global commands.

  • How you display the score will be dependent on the user interface.

  • As the score is a global variable, it will save and load without any extra work as part of Escoria’s save/load process.

Can you show me a basic room script?

A suggested template for a room script looks like this (using a library as an example)

:setup
  # The global needs to be declared ahead of its use. Note that setting the global
  # to 'false' only happens on declaration/initialization, i.e. just once.
  global room_library_visited = false

  # Check if the player has ever been in this room
  # If not, do first-time setup
  if not room_library_visited:
    # Here you'd have some steps to play a cutscene
    # e.g the librarian entering the room and sitting at the desk
    <...>
    # Set any room specific state. e.g. set a "conversation with librarian
    # not started" variable so she'll introduce herself when you talk to her

    # Make sure the room setup steps don't rerun if the player leaves the
    # room and comes back in.

    room_library_visited = true

    # Or you can use: set_global room_library_visited true

  # Position the player depending which room they've entered this one from
  if ESC_LAST_SCENE == "room_street_outside_library":
    teleport("player", "door1")
  elif ESC_LAST_SCENE == "room_library_upstairs":
    teleport("player", "door2")

Why isn’t my mouse working properly with my ESCItems?

If you use a control node like TextureRect or ColorRect, they will cause problems with mouse interactions. You will need to modify the properties of the TextureRect / ColorRect and set its Mouse Filter setting to “Ignore”.

How can I call my own GDScript function from Escoria?

Escoria script makes this possible by providing the custom command. The function must be associated with the child node of an ESCItem in your scene.

(See the command custom.)

To make use of this handy command, follow these steps:

  • Create a new node of an appropriate type as a child of an ESCItem in your scene. For example, if you have a door in your scene and you want to make a function that does something special when the door opens, you could create a child node of type Node2D underneath the ESCItem that represents the door.

Hint

Remember the global ID and name of this ESCItem: You’ll need them when you use the custom command.

  • Create your GDScript function in a .gd file and attach it to the child node as described above. This function can be called anything you want, but it must take exactly one argument. Escoria will pass in to the function any and all arguments specified in the custom command as an array. If your function doesn’t require any arguments, Escoria will pass in an empty array.

Hint

It is up to you to unpack the arguments passed in via the custom command as well as to perform any validation on these arguments that you deem necessary.

  • In the appropriate event in an Escoria script file, call the function you made above by using the custom command. For example:

    • Your game has a node with a global_id of “treasure_maps”

    • The “treasure_maps” node has a child node called “france_treasure_map”.

    • “france_treasure_map” has a Godot script (in GDscript format) attached.

      In this script is a function “draw_treasure” to show a map on the screen. In your Escoria script, you would call the script using:

:setup
  # Call the function you defined with some arguments
  # Format : custom esc_item_global_id child_node_name function_name arg1 arg2 ...
  # Note no parameters are passed to the "draw_treasure" function
  custom("treasure_maps", "france_treasure_map", "draw_treasure")

   * The GDScript it calls might look like this :
extends Node2D

# An empty array is passed as a parameter to the function so we ignore it
func draw_treasure(_ignored_parameter):
get_node("../france_map_sprite").visible = true
  • If instead you wanted to pass this script some parameters:

    • If your script took an x and y coordinate to display an “X marks the spot”

      graphic on the treasure map, your Escoria script code might look like :

:setup
  custom("treasure_maps", "france_treasure_map, "draw_treasure", x_coordinate, y_coordinate)


 * The matching GDScript code now needs to extract those coordinates from the
    parameter array that is passed to the function.
extends Node2D

# Extract coordinates from the array of parameters
func draw_treasure(list_of_parameters):
     var xcoord = list_of_parameters[0]
     var ycoord = list_of_parameters[1]
     get_node("../france_map_sprite").visible = true
     [...]

Hint

You can pass in as many arguments you want to your function. If no arguments are required, you don’t need to specify anything else after the function’s name.

How do I create an avatar to use in conversations?

How to create an avatar

Escoria’s default dialog plugin supports two types of talk animations: floating (text appears above the character’s head) and avatar (text appears in a box with an animation in its own box displayed beside the text).

The first step is to configure the location where Escoria can find any avatars you create. You specify this folder in Escoria’s project setting under Escoria/Dialog simple/Avatars Path.

The next step is to create the avatar animation (usually a close up of the character’s head with different mouth poses to make a talking animation). You will need individual sprites for each animation frame for the avatar.

To create the animation in Godot, create a new Sprite node (NOT an AnimatedSprite) in any scene in your project. Click the dropdown menu related to the “Texture” property and select New AnimatedTexture. Click this property to edit the AnimatedTexture. Select the number of frames in the frame property. A number of frame properties (Frame 0, Frame 1, …) will appear matching the frame count selected. Click and drag each animation onto the Texture of each frame.

Note

This workflow pertains to Godot 3, but should be similar in Godot 4.

Update the FPS setting to make the animation run at an appropriate speed.

Click the down arrow next to the AnimatedTexture Texture property and choose save from the list. Save the file to the avatar location selected earlier. *The file name needs to match the global ID of the character the avatar is for!*

To make the avatar appear, on any say line, append the word “avatar”.

say("worker", "Get back to work!", "avatar")

Why isn’t my room being drawn?

When you create a room it’s important that the parent node of the room scene is of type ESCRoom. If you use a different node type (Node for example), this may result in the room not being drawn. ESCRoom nodes have a “visibility” property that nodes of type Node do not: The room transition system relies on this property to draw the rooms of your game.