Rez Elements & Directives Catalog
Matt Mower
Rez includes many elements and directives that you combine to create a game, starting with the @game element.
All elements in a Rez source file have a name prefixed by @ and most have an id which must be unique across the game. The @game element automatically has the id #game.
Elements
Directives
Actor (Element)
An actor represents an in-game character which could be the player avatar or a non-playable character that the player interacts with. Define an actor with the @actor element. In-game actors are represented by the RezActor object.
Actors are an optional concept and a simple game might not need them, choosing instead to represent any actors via attributes of the game or scene. But in more complex games it’s useful to be able to model actors separately.
Example
In this example of our game the player can decide which of the antagonists they wish to play as. Each has different abilities and trust other characters different amounts.
@actor sam_spade {
name: "Sam Spade"
gunplay: 6
fisticuffs: 7
drinking: 8
flirting: 6
sleuthing: 9
chat: 6
container_id: #sams_stuff
}
@rel #sam_spade -> #miss_wonderly {affinity: +2}
@rel #sam_spade -> #joel_cairo {affinity: -2}
@rel #sam_spade -> #kaspar_gutman {affinity: -4}
@actor joel_cairo {
name: "Joel Cairo"
gunplay: 3
fisticuffs: 3
drinking: 5
flirting: 9
sleuthing: 6
chat: 8
container_id: #joels_stuff
}
@rel #joel_cairo -> #sam_spade {affinity: 1}
@rel #joel_cairo -> #miss_wonderly {affinity: -1}
@rel #joel_cairo -> #kaspar_gutman {affinity: -3}
@actor miss_wonderly {
name: "Ruth Wonderly"
gunplay: 4
fisticuffs: 2
drinking: 5
flirting: 10
sleuthing: 4
chat: 9
container_id: #ruths_stuff
}
@rel #miss_wonderly -> #sam_spade {affinity: 4}
@rel #miss_wonderly -> #joel_cairo {affinity: 1}
@rel #miss_wonderly -> #kaspar_gutman {affinity: -2}
@actor kaspar_gutman {
name: "Kaspar Gutman"
gunplay: 1
fisticuffs: 3
drinking: 9
flirting: 2
sleuthing: 7
chat: 9
container_id: #kaspar_stuff
}
@rel #kaspar_gutman -> #sam_spade {affinity: 2}
@rel #kaspar_gutman -> #miss_wonderly {affinity: -2}
@rel #kaspar_gutman -> #joel_cairo {affinity: 1}
By using a set of @actors we can keep things separate and easier to understand and use the built-in @rel directive to create relationships between the actors.
Optional Attributes
|
Set |
a set of keyword tags |
|
Element Ref |
id of the |
|
Element Ref |
when set, the actor is moved to this location during initialization (see |
|
Behaviour Tree |
a behaviour tree, e.g. |
Event Handlers
on_accept_item
on_accept_item(actor, event) => {...}
The event argument is a map in the form:
{
decision: <decision_obj>,
inventory_id: <id>,
slot_id: <id>,
item_id: <id>
}
This is a script that can be called to check whether an item can be placed into an inventory slot of a container that they are owner of (See also: inventory#owner)
on_accept_item: (actor, event) => {
event.decision.no(actor.name + " doesn't want to be burdened by worldly
goods.");
}
on_init
on_init: (actor, event = {}) => {...}
This script will be called during game initialization and before the game has started.
on_enter
on_enter: (actor, event) => {...}
The event argument is a map
{
location_id: <id>
}
This callback will be received when the actor is moved to a new location with moveTo() and is
passed the id of the location to which the actor has moved.
on_leave
on_leave: (actor, event) => {...}
The event argument is a map
{
location_id: <id>
}
This callback will be received when the actor has left a location and is passed the id of the location which has been vacated.
Asset (Element)
An @asset element refers to a file on disk, typically an image, audio, or video file, that will be presented in game.
Rez automatically copies asset files into the game distribution folder when the game is compiled and manages pathing so that assets can be referred to in game without worrying about filenames and paths.
Assets can be collected into groups (using @group) dynamically choose from among related assets.
Example
Using file_name (search mode):
@asset hat_01 {
file_name: "hat_01.png"
tags: #{:hat}
}
Using file_path (exact path mode):
@asset icon_attack {
file_path: "images/icons/attack.png"
}
This defines an asset that will be copied into the game when built and which can be referred to in-game by its id. Directory structure is preserved when copying to the distribution folder.
Rez will ensure that all assets are available during compilation.
Assets are the key to using asset groups that can be used for showing different but randomised media.
Required Attributes
Assets must specify their source file using either file_name or file_path (but not both):
|
String |
Name of the asset file. The compiler searches for this file anywhere in the |
|
String |
Explicit path relative to |
Optional Attributes
|
Set |
a set of keyword tags |
|
String or Number |
display dimensions of the asset. If one is specified the other must be too |
Event Handlers
on_init
on_init: (asset, event = {}) => {...}
This script will be called during game initialization and before the game has started.
Behaviour (Element)
Behaviours are elements that describe components of a behaviour tree. There are four types of behaviour:
-
condition — these test some property of the game world
-
action — these modify the game world
-
composite — these act on a group of 'child' behaviours
-
decorators — these modify other behaviours
While the difference between conditions and actions are fairly intuitive, the difference between composites and decorators is more subtle. Composites are about coordinating between a series of other behaviours, while a decorator typically modifies the results of another behaviour.
For example the $sequence core behaviour executes its children in turn and succeeds or fails based on them, while the $invert core behaviour turns its childs succees into failure (or vice verca).
When a behaviour is executed it either succeeds or fails.
As we have seen from the examples above, a composite behaviour usually succeeds or fails based on the success or failure of its children. A decorator typically modifies the success or failure of another behaviour. Conditional behaviours succeed or fail based on a test and action behaviours succeed based on whether their implied action is successful.
From these four simple concepts some very powerful behaviours can be built.
Rez defines a number of 'core' behaviours. By convention these have $ prefix to their id to separate them from author written behaviours. The core behaviours are mostly composites and decorators that are intended to be building blocks for author written behaviours.
The core of a behaviour element is its execute: script attribute. This is intended to implement the functionality of the behaviour and return a value whether it succeeds or fails.
Each behaviour can, optionally, receive options and, again optionally, a list of child behaviours. Conditions and actions are not expected to have children while composites and decorators don’t make sense without at least one child.
A behaviour instance can access the object that owns the tree via behaviour.owner. Any state that needs to persist between runs of the tree should be stored in the world model (e.g. attributes of the owner).
Let’s look at an example. We want a condition that tests whether a given actor is in a certain location. Here’s how we could implement it.
Example
@behaviour actor_in {
options_spec: [:actor :location]
execute: (behaviour) => {
const actor = $(behaviour.option("actor"));
const location_id = behaviour.option("location");
return actor.location_id === location_id;
}
}
Here we define the actor_in condition behaviour that tests whether a specified actors is in a specifed location. We might use it like this:
In this example we have defined a condition behaviour to test whether a specified actor is in a given location. This could be used in a sequence to ensure that an action only gets performed if in the correct location.
^[$sequence [actor_in actor="sam_spade" location="sams_office"] [...] ]
The rest of the behaviours in this sequence will only be run if Sam is in his office, otherwise the sequence will fail.
Required Attributes
|
Script |
script that takes one parameter |
Optional Attributes
|
List |
keywords describing the options that this behaviour uses (default: |
|
Number |
minimum number of child behaviours (default: 0) |
|
Number |
maximum number of child behaviours (default: 0) |
|
Script |
|
|
Set |
a set of keyword tags |
Behaviour Template (Directive)
A behaviour template is a composable element of behaviour. When writing behaviour trees you may find yourself wanting to use some behaviours over and over but not want to copy a whole tree. That’s where behaviour templates come in. With a template you can include just the parts of behaviour you need.
Syntax
The syntax for a behaviour template look like:
@behaviour_template <template_id> ^[...]
Behaviour template id’s are separate to element id’s and can overlap without conflict.
Usage
Let’s look at an example. Here is an actor with some behaviours:
@actor sam_spade {
behaviours: ^[$select [$sequence [actor_in location_type=:bar] [actor_is state=:thirsty] [actor_says msg="Give me a whisky."]]
[..more behaviours..]]
}
Maybe it’s not just Sam that you want to be able to order liquor at the bar. But you don’t want to copy Sam’s entire behaviours: attribute as it contains some behaviours that are unique to Sam. We can move this specific behaviour into a template and share it among multiple actors (or any other behaviour supporting object in your game):
@behaviour_template order_whisky ^[$sequence [actor_in location_type=:bar] [actor_is state=:thirsty] [actor_says msg="Give me a whisky."]]
@actor sam_spade {
behaviours: ^[$select [&order_whisky]
[..behaviours unique to Sam..]]
}
@actor joel_cairo {
behaviours: ^[$select [&order_whisky]
[..behaviours unique to Joel..]]
}
Now both Sam and Joel can make use of the behaviour.
Templates can also include other templates allowing for clean composition of many complex behaviours.
Card (Element)
Cards are the basic unit of content & interaction in a Rez game. Cards are "played" into a scene to present what is happening to the user and offer them choices about what to do next.
A card has one or more faces. The content attribute defines the template that is rendered each time the card is played. Optionally a card may also define a back face which is what is displayed in a scene using a stack layout after the card has been used (i.e. the player has moved on from that card).
Cards can be part of the main interface but can also be used as blocks in other cards. For example a card could be defined to represent a sidebar and included into scene layout.
Internally the content and back attributes of the card are converted into template functions (stored as $content_template and $back_template) so that they render quickly.
Example
@card intro_part_1 {
content: ```
You are in a maze of twisty passages all alike.
<a card="intro_part_2">Go forward</a>
```
}
@card intro_part_2 {
content: ```
You get the idea!
<a card="intro_part_1">Go backward</a>
```
}
Required Attributes
|
Template |
primary content to be displayed when this card is played into a scene |
Optional Attributes
|
Template |
content that is presented after the card is finished, when the card’s scene uses a stack layout |
|
Set |
names of the faces that receive the card wrapper |
|
List of bindings |
bindings from a name to the card whose content can be referenced in the |
|
Keyword |
the face currently displayed. Defaults to |
|
String |
optional title for the card |
|
Set |
set of keywords used to categorise the card |
|
List |
list of bindings which can either be game object ids or functions returning a value. E.g. |
|
String |
custom CSS classes to apply to the card wrapper, "information is-primary" |
|
Boolean |
when true the card’s content is rendered without the wrapping |
|
String |
name of a custom Javascript class (extending |
Event Handlers
on_init
on_init: (card, event = {}) => {...}
This script will be called during game initialization and before the game has started.
on_will_start
on_will_start: (card, event = {}) => {...}
Called when the scene makes this card the current card, before it is rendered. event holds the params passed when the card was played.
on_did_start
on_did_start: (card, event = {}) => {...}
Called after the card has been rendered into the view, just before control passes back to the player/browser. This replaces the older on_ready card event.
on_finish
on_finish: (card, event = {}) => {...}
Called when the card is being replaced by another card (or the scene is ending).
on_will_render / on_did_render
on_will_render: (card, event = {}) => {...}
on_did_render: (card, event = {}) => {...}
Called before and after the view is re-rendered while this card is the scene’s current card.
Custom events triggered from the card’s content are handled by defining an on_<event_name> handler on the card.
Notes
Card content is written as HTML (with template expressions). Unlike Twine we do not use Markdown and style links are not supported.
Links are written as <a> (or <button>) tags. Rez transforms the following attributes into data-event / data-target attributes when the template is compiled:
|
play the card into the current scene |
|
switch to the scene |
|
run the scene as an interlude |
|
resume from an interlude |
|
trigger the named event ( |
An <a> with no href gets href="javascript:void(0)".
Custom events are handled by an on_<event> attribute on the card:
@card intro_part_1 {
content: ```
You are in a maze of twisty passages all alike.
<a event="go_forward">Go forward</a>
```
on_go_forward: (card, evt) => {...}
}
Note: in components you cannot use the card= style links, as these are only converted in template attributes. Use data-event and data-target directly (see @component).
See the COOKBOOK for more information.
Component (Directive)
A @component directive is used to specify an HTML component used in templates.
For example we may have specified a button like this:
<button class="button is-small" data-event="reload">…</button>
There’s nothing wrong with this but the details are obscured by the attribute syntax, what if we could write:
<.event_button event="reload">…</.event_button>
The . prefix in <.event_button> indicates that this tag is implemented as a user component.
Let’s write this component:
@component event_button (bindings, assigns, content) => {
return `<button class="button is-small" data-event="${assigns["event"]}">${content}</button>`;
}
Container components like <.event_button> have their contents available in the content argument, attribute values in assigns, and all bindings available at the component site in bindings. Self contained components have no content specified.
Note: In components you cannot use links like <a card="card_id"> or <a interlude="scene_id"> as these are only supported in template attributes. But they are anyway merely syntax sugar for <a data-event="card" data-target="card_id"> and <a data-event="interlude" data-target="scene_id">. In your components remember to use data-event and data-target attributes.
Const (Directive)
A @const directive declares a named value that is available both within the Rez sources and as a Javascript global.
@const BAD_PI = 3.14
Allow you to use PI as an attribute value:
@object math_professor {
knows_that_pi_is: $BAD_PI
}
Also in action and event handlers:
@object math_professor {
bad_circumference: (r) => {
return r * $BAD_PI * $BAD_PI;
}
}
Defaults (Directive)
A @defaults directive is a way to setup default attributes for a type of element or alias.
The syntax is simple:
@defaults <element_or_alias> {
attribute: value
attribute: value
}
Example
@defaults card {
hub: false
}
From this point in the source file all @card elements will pick up a hub: false attribute without you having to set it.
Note that you can later change issue a new default for @card and any @card elements defined from that point will inherit the new default instead.
It is possible to set defaults for an @elem that will only be set for elements that use the alias. So this is legal:
@defaults card {
is_storylet: false
}
@defaults storylet {
is_storylet: true
storylets: function() {
return [];
}
}
@elem storylet = card
Now a card defined using the @storylet alias will has is_storylet: true and the default implementation of the storylets: attribute while regular cards get is_storylet: false and have no storylets: attribute.
See stdlib.rez for modifiable system defaults.
Derive (Directive)
The @derive directive is used to form keywords into hierarchies of types for items, effects, and so on.
Let’s take an example of where this might be useful: inventories.
We setup a hierarchy as follows:
@derive :weapon :item @derive :sword :weapon @derive :mace :weapon @derive :potion :item
The result is that an item with type: :sword, type: :mace, or type: :potion can be placed into a slot that accepts: :item. It’s not required to list all the different types of items that are legal in that slot. Equally our sword can be placed into a slot that accepts: :sword but an item type: :mace cannot, nor can an item type: :potion.
An item hierarchy can be as simple of complex as you need. At run-time all of the item type information is converted into tags. For example an item with type: :sword would have tags as if we had written tags: #{:sword :weapon :item}.
Effect (Element)
Effects are modifiers to aspects of the game that can be applied and removed dynamically as the game progresses.
For example an item, when worn, might convey a bonus to the actor wearing it. In this case the effect, attached to the item, is applied when the item is worn and removed when the item is removed.
Effects are applied and removed by @inventory when an item carrying the effect is placed into or removed from a slot. There is no support for effects that, for example, wear off over time.
Example
@effect drunk {
name: "Drunk"
description: "you're drunk, it's so much harder to concentrate"
on_apply: (effect, event) => {
const actor = $(event.owner_id);
// Add drunkness effects
}
on_remove: (effect, event) => {
const actor = $(event.owner_id);
// Remove drunkness effects
}
}
Event Handlers
on_init
: (effect, event = {}) ⇒ {…}
This script will be called during game initialization and before the game has started.
on_apply
: (effect, event) ⇒ {…}
event = {
owner_id: <id>,
slot_id: <id>,
item_id: <id>
}
Called when the effect is applied, i.e. when an item with this effect is placed into an inventory slot.
on_remove
: (effect, event) ⇒ {…}
event = {
owner_id: <id>,
slot_id: <id>,
item_id: <id>
}
Called when the effect is removed, i.e. when the item is removed from the inventory slot.
Elem (Directive)
The @elem directive allows the author to create a specialised alias for a particular kind of element, using a convenient and meaningful name.
For example, it may be desirable to be able use @sword and @watch instead of @item and customise those items using @defaults. We can apply @defaults to custom elements.
Example
In our Maltese Parrot game hats are a big deal and a range of hat items will be needed and will include a range of hat-specific attributes but we don’t want to repeat ourselves. Using @elem we can create an alias that specifies that a hat is an item and how hats are, generally, configured. Then our hat definition just needs to supply what’s different about that hat.
Here’s an example:
@elem hat = item
@defaults hat {
type: :hat
wearable: true
usable: false
bogie_would_approve: false
}
@hat wool_fedora {
material: :wool
colour: :black
description: "A Messer black wool fedora hat"
bogie_would_approve: true
}
Is equivalent to:
@item wool_fedora {
type: :hat
wearable: true
usable: false
material: :wool
colour: :black
description: "A Messer black wool fedora hat"
bogie_would_approve: true
}
Attributes defined in #wool_fedora override their defaults from @hat or @item so that bogie_would_approve: is true.
Where appropriate you can layer one @elem upon another to any depth. So the following is legal:
@elem woollen_hat = hat
@defaults woollen_hat {
material: :wool
}
Ultimately all @elem definitions resolve to one of the built-in elements such as @actor or @item and at runtime become one of the Rez objects.
Faction (Element)
Factions represent in-game groups with their own agenda, reputation, and views
of others. Define a faction using a @faction element.
Example
@faction police {
...
}
@faction gutman {
...
}
@faction player {
...
}
Optional Attributes
|
Set of Element Refs |
ids of the elements that are members of the faction. The |
|
Set |
a set of keyword tags |
Event Handlers
on_init
: (faction, event = {}) ⇒ {…}
This script will be called during game initialization and before the game has started.
Filter (Directive)
A @filter directive defines a filter function that can be used in a subsitution Template Expression. A filter has a name which is how you refer to it in a template expression, e.g. capitalize and an impl function that takes a variable number of parameters (but at least one).
Example
Let’s say we wanted to be able to output a numeric attribute replacing any value over 4 with "a suffusion of yellow". Here’s a filter that would do that:
@filter SUFFUSION_OF_YELLOW_FILTER {
name: "soyf"
impl: (n) => {
if(n < 4) {
return ""+n;
} else {
return "a suffusion of yellow";
}
}
}
and the expression would be
${number_value | soyf}
As of v0.11.0 the Rez stdlib defines a number of filters and you can see how they are implemented by reading the stdlib.rez.
See also the filter_catalog.
Game (Element)
The game element is the top-level specification of the game and its metadata. It also defines the scene entry point of the game.
The @game element has an implicit ID of game.
Example
@game {
name: "The Maltese Parrot"
title: "The Maltese Parrot"
author: "Dachshund Hamlet"
IFID: "D2050DE2-97A2-1ED1-4CCA-AF9D3B0DD883"
archive_format: 1
layout: ```${content}```
initial_scene_id: #sam_and_wonderly_meet
}
Required Attributes
|
String |
name of the game |
|
String |
title of the game as presented to the player |
|
String |
the author of the game |
|
String |
ID of the game in the IFID database (an ID will automatically be generated when the game is created, it’s up to you whether you register it or not) |
|
Number |
version of the save-game archive format |
|
Element Ref |
id of the scene the game begins with |
Optional Attributes
|
Template |
template that surrounds the game content. It must contain |
|
String |
contact email for the author |
|
List of Strings |
URLs of stylesheets to link into the game page |
|
List of Strings |
URLs of scripts to include in the game page |
|
List |
See [Card] |
|
List |
See [Card] |
|
List |
list of events to run when the game starts |
|
Set |
a set of keyword tags |
Event Handlers
on_init
on_init: (game, event = {}) => {...}
This script will be called during game initialization and before the game has started.
on_game_will_start
: (game, event = {}) ⇒ {…}
Every element (not just the game) receives an on_game_will_start event once all elements have been initialized and just before the view is built and the first scene starts. It’s an opportunity to customise game setup.
on_game_did_start
: (game, event = {}) ⇒ {…}
Triggered after the initial scene has been started.
on_scene_will_start
: (game, event) ⇒ {…}
The on_scene_will_start script is called whenever a new scene is about to be started.
on_scene_did_end
: (game, event = {}) ⇒ {…}
Called when a scene has ended, either because a new scene replaced it or because an interlude finished.
on_scene_will_pause
: (game, event = {}) ⇒ {…}
Called when a scene is about to be interrupted by an interlude.
on_scene_did_resume
: (game, event = {}) ⇒ {…}
Called when a scene has been resumed after an interlude.
on_card_will_start, on_card_did_start, on_card_did_finish
: (game, event) ⇒ {…}
event = {
card_id: <id>,
params: {...}
}
Called as cards are played into the current scene (params is not included for on_card_did_finish). These are the game-level equivalents of the scene events of the same names.
on_will_render, on_did_render
: (game, event = {}) ⇒ {…}
Called before and after the view is rendered.
on_will_save, on_did_load
: (game, event = {}) ⇒ {…}
Called before the game is saved and after a saved game has been loaded.
Generator (Directive)
A @generator creates a list of copies of an existing element, for example a group of similar monsters. At runtime a generator becomes a RezList with the same id whose values are the ids of the newly created copies.
Example
@generator goblin_pack {
source_id: #goblin
copies: 5
shuffle: true
customize: (goblin, idx) => {
goblin.name = `Goblin ${idx + 1}`;
return goblin;
}
}
Required Attributes
|
Element Ref |
id of the element to copy |
Optional Attributes
|
Number |
a number between 1 and 100 (default: 1) |
|
Boolean |
whether to shuffle the generated list (default: false) |
|
Number, Die Roll, or Function |
how many copies to make. A die roll is rolled and a function is called to get the number |
|
Function |
|
Group (Element)
A group specifies a collection of assets that can be selected from. Groups are dynamic: they are defined by a set of tags and collect together all assets carrying any of the include_tags (or, alternatively, all assets that do not carry any of the exclude_tags).
A group can be used to select an image at random, or cycle through the collection one-by-one.
Example
@asset hat_01 {
file_name: "hat_01.png"
tags: #{:hat}
}
@group hats {
type: :image
include_tags: #{:hat}
}
Required Attributes
|
Keyword |
One of |
|
Set |
Set of tags that appear on assets that should be included in the group. Exactly one of |
|
Set |
Set of tags that appear on assets that should be excluded from the group. Exactly one of |
Optional Attributes
|
Set |
a set of keyword tags |
Event Handlers
on_init
on_init: (group, event = {}) => {...}
This script will be called during game initialization and before the game has started.
Inventory (Element)
The @inventory element describes a container that can hold heterogenous items in slots.
For example, in an RPG it is common to have different slots to hold different types of items like armour, a shield, melee weapon, range weapon, rings, and amulets. In other games you might have slots describing wardrobe items. We can also think of memory (things we know about) as an inventory (where the items are topics we know about) or spell books (where items are individual spells). The @inventory element is designed to handle such cases.
An inventory is made up of positions, each declared by a nested @contains block. The @contains block has its own id, which becomes the name of that position in the inventory, and a slot_id naming the @slot that defines what the position accepts. This allows the same @slot to be re-used for several positions.
Slots are matched against items to determine whether it’s possible to put an item in a position: an item can be placed in a position if its type (including any @derived types) is what the slot accepts.
An actor owns an inventory by naming it as its container_id.
Example
@slot hat_slot {
accepts: :hat
}
@slot ring_slot {
accepts: :ring
}
@inventory player_inventory {
@contains hat {
slot_id: #hat_slot
initial_contents: [#black_fedora]
}
@contains left_ring {
slot_id: #ring_slot
}
@contains right_ring {
slot_id: #ring_slot
initial_enabled: false
}
}
@actor player {
container_id: #player_inventory
}
@contains Attributes
|
Element Ref |
id of the |
|
List of Element Refs |
ids of the |
|
Boolean |
whether this position is enabled when the game begins (default: true) |
Inventories may not also specify a slots: attribute directly, it is derived from the @contains blocks.
Required Attributes
An inventory must have at least one @contains block.
Optional Attributes
|
Element Ref |
id of the actor that owns the inventory. If not specified this is the actor that names the inventory as its |
|
Boolean |
whether the effects of items are applied when they are placed in the inventory (default: true) |
|
Number |
maximum total |
|
Set |
a set of keyword tags |
Event Handlers
on_init
on_init: (inventory, event = {}) => {...}
This script will be called during game initialization and before the game has started.
on_insert
on_insert: (inventory, event) => {...}
event = {
slot_id: <id>,
slot_binding: <name of the position>,
item_id: <id>,
owner_id: <id>,
owner: <object>
}
This script will be called when an item has been added to a position of this inventory.
on_remove
on_remove: (inventory, event) => {...}
event = {
slot_id: <id>,
slot_binding: <name of the position>,
item_id: <id>,
owner_id: <id>,
owner: <object>
}
This script will be called after an item has been removed from a position of this inventory.
Item (Alias)
@item is an alias, defined using @elem, of the @object element. Items are ordinary objects with some extra attributes and defaults, and they do not have content so they aren’t rendered directly. They can, of course, be referred to by cards.
The @item element defines a conceptual item the player (or potentially an NPC) can acquire and add to an inventory. Items don’t have to represent physical objects but anything a player has for example a spell could be an item or even a memory.
Items have a type keyword-attribute (defaulting to :item) that connects them to compatible slots in inventories. That might include a shop, a wardobe, and a players backpack inventories.
The Item/Inventory system is quite flexible so we can also think about spells as Items with the Inventory being a spell-book, or knowledge as Items with an Inventory being memory.
Some items can grant effects, which are applied when the item is put into a slot that has effects enabled (e.g. equipped) and removed when it is taken out.
Example
@item black_fedora {
type: :hat
name: "black fedora"
description: "A Messer wool fedora hat. Classy."
weight: 1
}
Note that this example throws up a design issue to be aware of: tags and boolean attributes are equivalent. For example wearable: true can also be represented by presence or absence of a tag wearable. In the case of Item elements its further possible to use the type system:
@derive :wearable :item @derive :hat :wearable
In this case an Item with type: :hat will automatically be tagged as :wearable and :item.
Optional attributes
|
Keyword |
a keyword representing the type of the item, e.g. |
|
Element Ref |
|
|
Number |
where slots have a |
|
Number |
where inventories have a |
|
Number |
number of uses the item has, assumed >= 0 |
|
List of Element Refs |
|
|
Element Ref |
|
|
Set |
a set of keyword tags |
Items may carry any other attributes you need (such as name or description).
Event Handlers
on_init
: (item, event = {}) ⇒ {…}
This script will be called during game initialization and before the game has started.
on_insert
: (item, event) ⇒ {…}
event = {
inventory_id: <id>,
slot_id: <id>,
slot_binding: <name of the position>,
owner_id: <id>,
owner: <object>
}
Called when the item is placed into an inventory position.
on_remove
: (item, event) ⇒ {…}
Called, with the same event as on_insert, when the item is removed from an inventory position.
Keybinding (Directive)
Use the @keybinding directive to generate custom events from the user pressing a specific key, optionally with modifiers.
The syntax is:
(modifiers)? + keyName
Example
@keybinding ctrl+shift+C :show_character_sheet
Notes
Available modifiers are:
-
shift
-
ctrl
-
meta (the Command key on Mac computers)
-
alt (the Option key on Mac computers)
Modifiers are optional. Where the shift modifier is used the keyName should be in upper case.
KeyNames follow the Javascript KeyboardEvent rules.
Event processing follows the usual custom event processing rules (card → scene → game) allowing for processing events in different places.
List (Element)
A list is a named collection of values that can be used by other in-game elements, for example lists of names, locations, actors, and so on. Lists are defined using the @list element.
The run-time API supports selecting randomly from lists including with & without replacement.
Example
@list antagnoists {
values: [#sam_spade #miss_wonderly #kaspar_gutman #joel_cairo]
}
@list lines {
values: [
"I distrust a man that says when. If he's got to be careful not to drink to much it's because he's not to be trusted when he does."
"The cheaper the crook, the gaudier the patter."
"I couldn't be fonder of you if you were my own son. But, well, if you lose a son, its possible to get another. There's only one Maltese Falcon."
"What do you want me to do, learn to stutter?"
]
}
Optional Attributes
|
List |
the values in the list |
|
List of Element Refs |
ids of other |
|
Set |
a set of keyword tags |
Event Handlers
on_init
: (list, event = {}) ⇒ {…}
This script will be called during game initialization and before the game has started.
Mixin (Directive)
A @mixin defines attributes that can be included into an object at runtime. This differs from @defaults which are applied to an element at compile time and become attributes of that object. Essentially each object gets a copy of their defaults. By contrast using a mixin there is only one copy which is shared by all instances using it.
@mixin named {
name: ^p{return `${this.given_name} ${this.family_name}`}
}
An element uses a mixin by listing it in its $mixins attribute:
@actor sam_spade {
$mixins: #{#named}
given_name: "Sam"
family_name: "Spade"
}
Now that @elem supports arbitrary nesting it is possible that @mixin is not required.
Pragma (Directive)
The @pragma directive specifies an instruction to be run during the compilation process. For example this pragma runs the pragmas/source_explorer.lua file after the compiler has run a first pass processing the abstract syntax tree (AST).
@pragma(after_process_ast) source_explorer("source_explorer.html")
A pragma is specified using a timing instruction:
-
after_build_schema -
after_schema_apply -
after_process_ast -
before_create_runtime -
after_copy_assets
a name e.g. source_explorer which corresponds either to one of the built-in pragmas (write_content, write_id_map, write_hierarchy, and write_obj_map) or to a Lua source file in the pragmas project folder, followed optionally by values that get passed to the pragma script.
A pragma receives the Rez internal %Compilation{} struct as a value compilation and any parameters as values and can use the plugin API to query & modify the compilation (for example adding new assets). It is expected to return either the original or a modified compilation.
Use with care.
Object (Element)
An @object element describes an author-driven concept. Isn’t everything in Rez an object of some kind? Yes, but elements like @actor, @plot, and @inventory have built-in meaning and functionality (@item is a specialised alias of @object). By contrast @object is a blank canvas that an author can use for anything they think of.
Example
Imagine we are building a role-playing game and we want to introduce the notion skills and perks. Rez does not provide either of these concepts out of the box but we can use the @object element to make them ourselves.
@elem skill = object
@defaults skill {
description: "Something an actor has acquired the ability to do"
min: 0
max: 5
cur: 0
}
@elem perk = object
@defaults perk {
cost: 1
}
@perk gun_license {
description: "Without this cops might pick you up for flashing your lead pumper."
}
@perk dont_go_down_easy {
description: "Takes more than a bullet to put you down."
}
@perk beguile {
description: "One look into your eyes and they're putty in your hands."
cost: 2
}
@skill puzzling {
description: "Figuring out how the clues fit together."
...
}
@skill gunplay {
description: "Shooting straight, esp. when it matters."
...
}
@skill drinking {
description: "Hold your liquour, yes sir!"
...
}
@skill fisticuffs {
description: "Marquis of Queensbury be damned, hit 'em where it hurts."
...
}
@skill intimidate {
description: "You don't actually **need** to shoot 'em."
...
}
@skill evade {
description: "Never end up in the wrong place at the wrong time."
...
}
@skill fast_talk {
description: "They'll think it was you doing a favour for them!"
...
}
@skill scheming {
description: "They'll never see it coming."
...
}
In a real-game we’d expect to see more definition of what skills & perks do but at least we can talk about them meaningfully even though Rez knows nothing about them. As a consequence Rez cannot validate their attributes (unless you provide a @schema).
Extra care should be taken here that they are well-formed.
Patch (Directive)
A @patch adds a new function or method to a built-in Javascript class when the runtime is created. The Rez stdlib uses patches to extend classes such as Boolean and Object.
Patches have no id. Specify the class to patch with patch: and either function: (a static function added to the class) or method: (a method added to instances) but not both.
Example
@patch {
patch: "Number"
method: "double"
impl: function() {
return this * 2;
}
}
Required Attributes
|
String |
name of the Javascript class to patch |
|
Function |
the implementation of the function or method |
|
String |
name of the function or method to add (exactly one is required) |
Plot (Element)
A @plot element represents a 'plot clock' or 'progress track' such as you might find in games like
'Blades in the Dark' and 'IronSworn: Starforged'. Each @plot has a number of stages and can be
advanced.
As well as the plot itself firing events when advancing, it notifies it’s subcribers (which can be other plots).
In general the plot mechanism can be satisifed with a simple variable on any other object such as
the game or an actor. However where plot requirements are more complex the @plot is available.
Example
@plot main_quest {
stages: 5
priority: 100
}
@plot build_fortress {
stages: 3
%% The build_fortress plot is automatically triggered when the main
%% plot reaches stage 3
on_init: (plot) => {
$("main_quest").subscribe(plot.id);
}
on_plot_did_advance: (plot, params) => {
const source = params.source;
if(source.id === "main_quest" && source.stage === 3) {
plot.start();
}
}
}
Required Attributes
|
Number |
the number of stages in the plot (minimum 1) |
Optional Attributes
|
Number |
from 1 to 100, higher priorities break plot deadlocks (default: 1) |
|
Number |
the current stage of the plot (default: 0) |
|
Boolean |
whether the plot has been started (default: false) |
|
List of Element Refs |
elements to be notified of changes to the plot. Usually maintained with |
|
Set |
a set of keyword tags |
Event Handlers
on_init
: (plot, event = {}) ⇒ {…}
This script will be called during game initialization and before the game has started.
on_start
: (plot, event = {}) ⇒ {…}
Called when the plot is started with start().
on_advance
: (plot, event = {}) ⇒ {…}
Called whenever the plot has advanced by 1 or more stages with advance().
on_complete
: (plot, event = {}) ⇒ {…}
Called when the plot has advanced to the final stage and is considered completed.
Subscriber Events
When a plot starts, advances, or completes it also notifies each of its subscribers (any element, including other plots) by running an event on them. The event params include source, the plot that raised the event.
-
on_plot_did_start -
on_plot_did_advance -
on_plot_did_complete -
on_plot_did_revert
Quest (Element)
The @quest element represents a quest that the player character may become aware of,
accept, and complete. It further supports becoming botched (incompletable) and unbotched.
Where the @plot elements represents a plot-clock, the @quest represents an overarching
goal of the players.
A quest has a status which moves through the states :unknown, :mentioned, :accepted, :achieved, and :completed, or is :botched. The runtime provides methods to move between them: mention(), accept(), achieve(), complete(), botch(), and unbotch(). Each is ignored unless the quest is in a state from which the change is legal.
Example
@quest find_the_falcon {
description: "Find the Maltese Falcon before Gutman does."
}
Required Attributes
|
String |
description of the quest as presented to the player |
Optional Attributes
|
Keyword |
one of |
|
List of Element Refs |
elements to be notified when the quest changes. Usually maintained with |
|
Set |
a set of keyword tags |
Subscriber Events
Whenever the status of a quest changes each of its subscribers is sent an on_quest_did_update event whose params include source, the quest that changed.
Relationship (Element)
The @rel directive describes the relationship between two game elements called the source (the element which has the relationship) and the target (the element the source has relationship with).
A relationship is unidirectional from source to target. Where applicable use a second @rel to describe the relationship in the opposite direction.
A relationship can be specified between any two elements with an id. The most obvious example being between one actor and another, but you could equally define relationships between actors and factions, factions and factions, or — if it makes sense in your game — factions and items (the holy grail anyone?).
Example
The @rel element does not follow the usual element syntax. Instead it looks like this:
@rel source_id -> target_id {
<attributes>
}
@rel #player -> #gutman_faction {
affinity: -1.0
}
A relationship element isn’t assigned an id but automatically derives its id from the source and target id, in the example above the id would be rel_player_gutman_faction.
The syntax uses the → symbol to help understand the unidirectionality of a relationship as being from a source element upon a target element.
The getRelationship(source, target) API on the RezGame object is a short-
hand for doing this lookup manually. The inverse property of a relationship returns the relationship in the opposite direction.
We can use @rel to define all kinds of relationships:
%% the Gutman faction loves the Falcon
@object falcon {}
@rel #gutman_faction -> #falcon {
affinity: 1.0
}
%% the player hates brocolli
@object brocolli {}
@rel #player -> #brocolli {
affinity: -1.0
}
In these examples we have used an affinity: attribute (range: -1.0 to +1.0) to define the strength of the relationship but you can use any attributes you like. The following would be equally valid:
@rel #player -> #miss_wannalee {
love: 65
suspicion: 25
}
An alternative approach is to use tags:
@rel #player -> #miss_wannalee {
tags: #{:lover :suspicious}
}
Optional Attributes
|
Set |
a set of keyword tags |
The source_id and target_id attributes are set automatically from the @rel syntax. Any other attributes may be used to describe the relationship.
Event Handlers
on_init
on_init: (relationship, event) => {...}
event = {}
Scene (Element)
A Game in Rez is authored in terms of @scenes and @cards. Each @card represents some content that is presented to the player. By contrast the @scene represent the structure and intelligence about which @cards to represent and how to respond to player input.
For example you might use different scenes for moving around the map, examining items, interacting with NPCs, buying from shops, and so on. You don’t have to, you could implement the game in a single scene, but the different layout and event handling possibilities make it easier.
A @scene requires an initial_card_id: #card_ref attribute that identifies the card that will be played when the scene begins. Optionally it has a layout: attribute that specifies the surrounding markup. The layout must contain a ${content} template expression which specifies where the scene’s cards are inserted. The default layout is just ${content}.
A @scene may have a layout_mode: attribute which must be either :single or :stack (default :single). In the :single layout mode only a single @card is ever displayed. While in :stack mode each new @card is laid out after the previous one, and finished cards that have a back face are flipped to display it.
Lastly a @scene may optionally have a blocks: [name_1: #card_id_1 name_2: #card_id_2 …] attribute, a list of bindings from a name to a card. Each referenced @card will be rendered and its content can be inserted into the layout using ${name_1}, ${name_2}, etc.
Example
@scene introduction {
initial_card_id: #intro_part_1
blocks: [sidebar_1: #sidebar_1 sidebar_2: #sidebar_2]
layout_mode: :single
layout: ```
<div class="sidebar">
${sidebar_1}
${sidebar_2}
</div>
<div>
${content}
</div>
```
on_card_will_start: (scene, evt) => {...}
}
Required Attributes
|
Element Ref |
id of the |
Optional Attributes
|
Keyword |
One of |
|
Template |
template containing the scene content in which cards are embedded. Must contain |
|
List |
See [Card] |
|
List |
See [Card] |
|
Boolean |
In reverse mode new cards are played at the top of the stack (default: false) |
|
String |
Markup content to be inserted between cards when in stack mode (defaults: "") |
|
Set |
set of keywords used to categorise the scene |
|
Function |
A function called after resume that returns a RezEvent determining what happens next. The default is to return |
Event Handlers
Scenes support a range of events:
on_init
: (scene, event = {}) ⇒ {…}
The on_init script is called during game initialization and before the player has been able to take any actions. It will be passed an empty map of arguments.
on_start
: (scene, event) ⇒ {…}
The on_start script is called when a scene is started. It receives the params passed when the scene was started.
on_ready
: (scene, event = {}) ⇒ {…}
The on_ready script is called once the scene has been started and is ready for interaction.
on_finish
: (scene, event = {}) ⇒ {…}
The on_finish script is called when a scene has ended.
on_interrupt
: (scene, event = {}) ⇒ {…}
The on_interrupt script is called when a scene is being interrupted by an interlude.
on_resume
: (scene, event = {}) ⇒ {…}
The on_resume script is called when a scene is being resumed after an interlude.
on_will_render / on_did_render
: (scene, event = {}) ⇒ {…}
Called before and after the view is rendered.
on_card_will_start
: (scene, event) ⇒ {…}
event = {
card_id: <id>,
params: {...}
}
Called when a new card is about to be played into the scene, before it is rendered.
on_card_did_start
: (scene, event) ⇒ {…}
event = {
card_id: <id>,
params: {...}
}
Called after a new card has been played into the scene and rendered.
on_card_did_finish
: (scene, event) ⇒ {…}
event = {
card_id: <id>
}
Called when a card has finished as a new card is played into the scene (or the scene ends).
Schema (Directive)
The @schema directive is used to specify validation rules for element attributes. Schemas provide compile-time validation to ensure your game elements are properly configured and catch errors early in development.
Syntax
@schema <element_type> {
attribute_name: {validation_rules}
attribute_name: {validation_rules}
}
Basic Validation Types
| Rule | Type | Description |
|---|---|---|
|
Boolean |
Validates boolean values ( |
|
Number |
Validates numeric values (integers or floats) |
|
String |
Validates string values |
|
Keyword |
Validates keyword values (e.g., |
|
List |
Validates list/array values |
|
Set |
Validates set values |
|
Element Reference |
Validates references to other elements (e.g., |
|
Map |
Validates map/table values |
|
Function |
Validates function/script attributes |
|
Template |
Validates template content |
|
Binding |
Validates a |
|
Behavior Tree |
Validates behavior tree structures ( |
|
Probability Table |
Validates probability table values |
|
Die Roll |
Validates die roll values |
Multiple Type Support
You can allow multiple types for an attribute:
@schema example {
size: {kind: [:string :number]}
}
Collection Validation
For lists and sets, use coll_kind to specify the type of collection elements:
@schema example {
tags: {kind: :set, coll_kind: :keyword}
members: {kind: :list, coll_kind: :elem_ref, ref_elem: @actor}
}
Reference Validation
Use ref_elem to specify which element types are valid for references:
@schema scene {
initial_card_id: {kind: :elem_ref, ref_elem: @card, required: true}
}
Required Attributes
Mark attributes as required using required: true:
@schema game {
name: {kind: :string, required: true}
IFID: {kind: :string, required: true}
}
Constraint Validation
Numeric Constraints
@schema plot {
priority: {kind: :number, min: 1, max: 100, required: true}
stages: {kind: :number, min: 1, required: true}
}
Collection & String Length
Use min_length and max_length to constrain the number of items in a collection or the number of characters in a string:
@schema inventory {
slots: {kind: :list, coll_kind: :list_binding, min_length: 1}
}
String Constraints
@schema game {
layout: {kind: :source_template, required: true, contains: "${content}"}
}
Enumerated Values
@schema scene {
layout_mode: {kind: :keyword, in: [:single :stack]}
}
@schema group {
type: {kind: :keyword, in: [:image :audio :video], required: true}
}
File Validation
@schema asset {
file_path: {kind: :string, file_exists}
}
Mutually Exclusive Attributes (XOR)
Use xor to ensure only one of two attributes can be present:
@schema asset {
file_name: {kind: :string, xor: file_path}
file_path: {kind: :string, xor: file_name, file_exists}
}
Dependent Attributes (AND)
Use and to require attributes to be used together:
@schema asset {
width: {kind: [:string :number], and: height}
height: {kind: [:string :number], and: width}
}
Alternative Requirements (OR)
Use or to specify that at least one of multiple attributes must be present:
@schema system {
before_event: {kind: :function, param_count: 2, or: after_event}
after_event: {kind: :function, param_count: 3, or: before_event}
}
Function Parameter Validation
For function attributes, specify the number of parameters the function must take with param_count, or a range using min_arity and max_arity:
@schema system {
before_event: {kind: :function, param_count: 2}
}
@schema actor {
on_enter: {kind: :function, min_arity: 2, max_arity: 2}
}
Overlapping Keys
Use no_key_overlap to ensure two binding lists do not use the same names:
@schema card {
bindings: {kind: :list, coll_kind: :list_binding, no_key_overlap: "blocks"}
blocks: {kind: :list, coll_kind: :list_binding, ref_elem: @card}
}
Keyword Types
Use type_exists to require that a keyword names a type that has been used by another element (for example the accepts: of a @slot must refer to an item type that exists):
@schema slot {
accepts: {kind: :keyword, required: true, type_exists}
}
Disallowing Attributes
Use allowed: false to prevent an attribute from being used. This is how elements are prevented from being used as templates:
@schema game {
$template: {allowed: false}
}
@schema timer {
$template: {allowed: false}
}
Pattern-Based Validation
Use regex patterns to validate dynamically named attributes:
@schema inventory {
?/^initial_/: {kind: :list, coll_kind: :elem_ref}
}
This validates any attribute starting with "initial_" as a list of element references.
Type Hierarchy Validation
Use is_a to validate that a value matches acceptable values from another element’s attribute, taking into account type hierarchies created with @derive:
@schema item {
type: {kind: :keyword, required: true, is_a: @slot/accepts}
}
This ensures that an item’s type: value matches the accepts: value of at least one @slot, considering the type hierarchy. For example, if you have:
@derive :sword :weapon
@derive :weapon :item
@slot weapon_slot {
accepts: :weapon
}
@item magic_sword {
type: :sword
}
The magic_sword item is valid because :sword derives from :weapon, which matches the slot’s accepts: value. The is_a validation works with the same keyword hierarchy system as @derive, similar to Clojure’s derive mechanism.
Example: Complete Schema
@schema card {
$global: {kind: :boolean}
$template: {kind: :boolean}
$auto_id_idx: {kind: :number}
$init_after: {kind: :list, coll_kind: :elem_ref}
$js_ctor: {kind: :string}
tags: {kind: :set, coll_kind: :keyword}
faces: {kind: :set, coll_kind: :keyword}
current_face: {kind: :keyword}
content: {kind: :source_template, required: true}
back: {kind: :source_template}
$suppress_wrapper: {kind: :boolean}
bindings: {kind: :list, coll_kind: :list_binding, no_key_overlap: "blocks"}
blocks: {kind: :list, coll_kind: :list_binding, ref_elem: @card}
css_class: {kind: :string}
title: {kind: :string}
on_will_start: {kind: :function}
on_did_start: {kind: :function}
on_will_render: {kind: :function}
on_did_render: {kind: :function}
on_finish: {kind: :function}
}
For more examples of schema validation in practice, see the standard library definitions in stdlib.rez.
Script (Directive)
A script is used to include arbitrary Javascript code into the compiled game. Specify a script using the @script directive.
The @script directive consists of a string containing the code to include between { and } markers.
The code defined in the game’s @script directives will be automatically included as <script> tags before the end of the <body> element of the generated HTML template.
Example
@script {
function customFunction() {
// Javascript code here
}
}
Slot (Element)
A @slot describes a component of an @inventory so that an inventory can hold different types of things.
For example an inventory representing what a player is wearing might have slots for coats, trousers, and so forth while an inventory representing a spell book might have slots for different levels of spell.
See also: [Type Hierarchy]
Example
@slot holster_slot {
accepts: :pistol
}
Required Attributes
|
Keyword |
a keyword representing the type of Items that are permitted to be in the slot |
Optional Attributes
|
String |
name of the slot e.g. "Holster" that could be displayed to the player |
|
Boolean |
whether the slot limits how much it can hold using |
|
Number |
when |
|
Boolean |
whether the effects of items placed in this slot are applied (default: true) |
|
Set |
a set of keyword tags |
|
Set of Slot Refs |
set of |
Event Handlers
on_init
: (slot, event = {}) ⇒ {…}
This script will be called during game initialization and before the game has started.
on_insert
: (slot, event) ⇒ {…}
event = {
inventory_id: <id>,
item_id: <id>,
owner_id: <id>,
owner: <object>
}
When an @item is placed into a @slot the on_insert event handler will be
called.
on_insert: (slot, event) => {
// Do something
}
on_remove
: (slot, event) ⇒ {…}
event = {
inventory_id: <id>,
item_id: <id>,
owner_id: <id>,
owner: <object>
}
When an @item is taken out of an inventory @slot the on_remove event
handler will be called.
on_remove: (slot, event) => {
// Do something
}
Styles (Directive)
The @styles directive is used to include arbitrary CSS into the compiled game.
The styles defined within a @styles directives will be automatically included as <style> tags before the end of the <head> element of the generated HTML template.
Example
@styles {
.card {
/* My custom styles here */
}
}
System (Element)
The @system element describes an author defined system that can respond to events generated in the game and modify the game world.
Systems are orthogonal to event handlers that are specific to a given event. For example, when a user clicks a link this has a specific outcome that will be meaningful to the player. However any number of systems might also respond to this event.
For example we might want to model weather in our game world and have the weather change, automatically, over time. This change is not necessarily related to any specific player activity (e.g. clicking a link to move between locations) but any event might trigger such a change.
Whenever the player generates an event all @systems whose enabled: attribute is true get the opportunity to process, and potentially modify, the event before normal processing and to change the result afterward.
Every @system must have a priority: attribute that is a number greater than 0. @systems are run in highest-priority order (so priority 100 runs before priority 99).
Every @system must define at least one of before_event:, after_event:, before_lifecycle_event:, or after_lifecycle_event: but can potentially define several.
Example
%% Here is a system that maintains wall clock time and when an event changes
%% the time, calculates new weather
@system weather_system {
enabled: true
priority: 25 %% low-priority
wall_time: 0
past_wall_time: _ %% just so we get an accessor
weather: "It is sunny"
before_event: (system, event) => {
system.past_wall_time = system.wall_time;
}
after_event: (system, event, result) => {
if(system.wall_time != system.past_wall_time) {
system.calculate_weather();
}
return result;
}
calculate_weather: function() {
this.weather = ["It is raining", "It is sunny"].randomElement();
}
}
Required Attributes
-
enabled[Boolean]: if false, this system will not be run -
priority[Number]: systems are run in descending priority order
Event Handlers
on_init
on_init: (system, event = {}) ⇒ {…}
This script will be called during game initialization and before the game has started.
before_event
before_event: (system, event = {}) ⇒ {…}
This handler will be called before the event has been processed by handleBrowserEvent(). If the handler modifies the event, the modified event will be passed on to successive systems and handleBrowserEvent().
after_event
after_event: (system, event = {}, result) ⇒ {…}
This handler will be called after the event has been processed by handleBrowserEvent() and receives both the event in question and also the result that has been generated.
If the handler modifies the result, the modified result will be passed back through successive systems and to the browser itself. Modifying the event does nothing as it has already been processed.
before_lifecycle_event
before_lifecycle_event: (system, eventName, params) ⇒ {…}
Called before the game handles one of its lifecycle events (scene and card transitions, and renders, e.g. "card_will_start"). This is observe-only: return values are ignored, though the handler may modify params.
after_lifecycle_event
after_lifecycle_event: (system, eventName, params, result) ⇒ {…}
Called after the game has handled a lifecycle event. Like before_lifecycle_event this is observe-only.
Timer (Element)
The @timer element describes a game component that generates events after specific
time interval has passed, either once or repeatedly.
Use a timer element when you want something to happen irrespective of player input.
For example a timer could be used to create a proper "wandering monster" scenario, where every minute the player is at risk of a monster wandering into their location.
Example
@timer wandering_monsters {
auto_start: true
repeats: true
interval: 60000
event: :wandering_monster
}
Required Attributes
|
Number |
The time, in milliseconds, before the timer fires. |
|
Keyword |
Specifies the name of the event that will be sent when the timer runs down. The event follows the normal rules for custom events. |
Optional Attributes
|
Boolean |
If true, this timer will start when the game starts (or a saved game is loaded). Default: true. |
|
Boolean |
If true this timer will keep sending events until it stops, otherwise it will only send one event. Default: true. |
|
Number |
With a repeating timer this specifies the number of times it should fire before stopping (minimum 1). |