Scripting in articy:draft
articy:draft features its own scripting language, called articy:expresso. It is most useful when combined with Global Variables , built-in functions, and the Simulation mode, allowing users to define and test the logic of their narrative: can a player see a certain dialog branch?, increase the player's defence by 10% if they select this option, trigger the winning-animation if the player guesses correctly, etc.
You can create, manage and use Global Variables throughout the project - making it possible to define conditions and change the values of variables via instructions when reaching certain points in your game flow.
Additionally, you can call external functions and attach scripts to objects via articy:draft's template properties . Let's have a closer look at all those features.

If the scripting support is activated, the auto-completion will offer a list of all matching variable sets or variables when writing in a script textbox. You can select an entry from the list via left-click or via the arrow-keys and ENTER.

Conflicts in the script are visualized by words underlined in red 1 and the conflict icon in the upper right. Hovering over the icon will show a tooltip describing the conflict 2:

articy:expresso has two basic script types: (1) Condition and (2) Instructions. These script types can be used in different contexts.
The overall syntax of articy:expresso is based on C-like languages.
It supports the following arithmetic operators:
We will learn about more operators in the subsequent sections.
The following logical operators can be used to concatenate comparisons.
The negation operator ! is a quick way to invert a boolean value.
Additionally, articy:expresso supports the following comparison operators:
Examples of typical conditions:
You can learn more details about Condition scripts in the dedicated page on Conditions and Instructions.
While the <l-value> of an assignment has to be a defined variable (which includes pre-defined, special variables like seenCounter), the <r-value> can be an arbitrary expression that needs to evaluate to a type that can be assigned to the <l-value>.
Here are all supported assignment operators:
Examples of typical instructions:
You can learn more details about Instructions scripts in the dedicated page on Conditions and Instructions.
Example: You created a global boolean variable called "key" that is set to true, if the player finds the missing key. This variable is inside the variable set called "Inventory". To use this variable in conditions or instruction write: "Inventory.key".
You can learn more details about Instructions scripts in the dedicated page on Global Variables.
Overview over built-in functions (detailed explanations and samples in the next section):
Overview over built-in convenience keywords (detailed explanations and samples in the next section):
Remember that a Condition script must be a boolean expression. Hence, certain functions or keywords like incrementProp(...), setProp(...) or seeCounter cannot be used in Condition scripts.
ObjectRef getObj(TechnicalNameOrId, InstanceIndex = 0)
This function is used in conjunction with functions like getProp(...) and setProp(...).
You can access an object via its technical name or id.
Optionally, you can specify the instance id to access another clone of the object.
Variable getProp(ObjectRef, PropertyName)
To access a property you have to provide a reference to a specific object and the property name as a string.
You can access the template data of an object by writing the feature name and the property name separated by a dot.
Here we used getProp() in a condition, testing the returned value.
Remember that you can use keywords like self or speaker to ease accessing objects:
setProp(ObjectRef, PropertyName, Value)
To change the value of a property you have to provide a refernce to a specific object, the property name, and the new value.
Changing a template property is achieved accordingly:
Remember that you can use keywords like self or speaker to ease accessing objects:
incrementProp(ObjectRef, PropertyName, Value) and decrementProp(ObjectRef, PropertyName, Value)
Instead of nesting setProp and getProp to increment or decrement a value, you can use these convenience functions.
If no change value is specified, the value will be increased or decreased by 1.
bool isPropInRange(ObjectRef, PropertyName, LowerBound, UpperBound)
A convenience function to check if a property value is in a specific range. The bounds are both inclusive.
articy:expresso features specific keywords and functions to react to choices players have made in the past. More specifically, you can query and change what we call a "seen counter property" for a flow object using below utilities. This makes it easy to design scenarios where certain options should only be available once or a limited amount of times to a player.
bool seen
Indicates if this object has been visited (true) or not (false) by the player in a given session. It is the inverse of unseen. As with any other boolean value, you can combine this with other conditions using logical operators:
bool unseen
Indicates if this object has been visited (false) or not (true) by the player in a given session. It is the inverse of seen. As with any other boolean value, you can combine this with other conditions using logical operators:
int getSeenCounter(ObjectRef)
Returns how many times the referenced object has been visited.
setSeenCounter(ObjectRef, Value)
Sets the seenCounter to Value for the referenced object.
int seenCounter
A built-in property usable as short-hand alternative to getSeenCounter(self) and setSeenCounter(self, ...). The following statement-pairs are equivalent:
resetAllSeenCounters()
Resets all non-zero "seen counter values" to zero.
Value random(Min, Max)
Can be used to work with random values.
bool isInRange(Value, LowerBound, UpperBound)
Similar to isPropInRange(...), but not restricted to property values. The bounds are both inclusive.
It can be used for global variables ...
... or even with custom methods:
print(Text)
Useful as a debug tool when working with a game engine. Similarly to String.Format(), strings can be formatted.
bool fallback(BranchingPointReference = null) NEW in adx 4.1!
Evaluates to false if any other non-fallback branch in reference to the given branching point is currently valid. By default (i.e. without an explicit branching point reference argument), the branching point is determined by the current player environment.
Calling custom methods can be combined with built-in functions like isInRange(...) or isPropInRange(...)
In this example we have a custom method GetTime() to query the current in game time. With isInRange() we can now, for example, determine if a shop is open or closed.
You can create, manage and use Global Variables throughout the project - making it possible to define conditions and change the values of variables via instructions when reaching certain points in your game flow.
Additionally, you can call external functions and attach scripts to objects via articy:draft's template properties . Let's have a closer look at all those features.
Testing Scripts in Simulation Mode
You can test your articy:expresso scripts within articy:draft by using the simulation mode of the presentation view. Please be aware that scripts from template properties are not evaluated in the simulation mode, only scripts that are located in pins and condition / instruction nodes.Use Built-in Scripting Support
If you want to use articy:expresso and the built-in scripting support, enable the checkbox "Use built-in scripting support" within the project settings under the tab "Flow". This option activates the auto-completion, syntax highlighting and error detection for all pin labels and other script textboxes inside of articy:draft X. Additionally, this setting must be checked in order to export the scripts when targeting the Unreal or Unity engine.
If the scripting support is activated, the auto-completion will offer a list of all matching variable sets or variables when writing in a script textbox. You can select an entry from the list via left-click or via the arrow-keys and ENTER.

Conflicts in the script are visualized by words underlined in red 1 and the conflict icon in the upper right. Hovering over the icon will show a tooltip describing the conflict 2:

articy:expresso Feature Overview
articy:expresso has two basic script types: (1) Condition and (2) Instructions. These script types can be used in different contexts.
| Script type | Usable context | |
| Condition scripts | Input Pins, Condition nodes, Script properties of script type Condition | |
| Instructions scripts | Output Pins, Instructions nodes, Script properties of script type Instructions | |
The overall syntax of articy:expresso is based on C-like languages.
It supports the following arithmetic operators:
| Operator | Description | |
| <left> + <right> | Add <left> and <right> | |
| <left> - <right> | Subtract <right> from <left> | |
| <left> * <right> | Multiply <left> by <right> | |
| <left> / <right> | Divide <left> by <right> | |
| <left> % <right> | Modulo: Gets the remainder of dividing <left> by <right> (Example 5 % 2 = 1) | |
| <post>++ or ++<pre> | Increment: Usable as post- and pre- operator. Increments the operand's value by 1 and assigns it implicitely. In case of post-, reads the value first, before updating it, whereas in pre-, it first applies the update and then reads the value. | |
| <post>-- or --<pre> | Decrement: Usable as post- and pre- operator. Decrements the operand's value by 1 and assigns it implicitely. In case of post-, reads the value first, before updating it, whereas in pre-, it first applies the update and then reads the value. | |
We will learn about more operators in the subsequent sections.
Condition Scripts
A condition script has to be a boolean expression, i.e. an expression that eventually evaluates to either the value 'true' or 'false'. This allows you to test variable values in the flow and make certain parts of your narrative only available if certain conditions apply.The following logical operators can be used to concatenate comparisons.
| Operator | Description | |
| <left> && <right> | Logical AND: both <left> AND <right> expression must be true for this to be true. | |
| <left> || <right> | Logical OR: either <left> OR <right> expression must be true for this to be true. | |
The negation operator ! is a quick way to invert a boolean value.
Additionally, articy:expresso supports the following comparison operators:
| Operator | Description | |
| <left> == <right> | Equal: true if <left> is equal to <right> | |
| <left> != <right> | Not equal: true if <left> is not equal to <right> | |
| <left> <= <right> | Lower than or equal: true if <left> is lower than or equal to <right> | |
| <left> >= <right> | Greater than or equal: true if <left> is greater than or equal to <right> | |
| <left> < <right> | Lower than: true if <left> is lower than to <right> | |
| <left> > <right> | Greater than: true if <left> is greater than to <right> | |
Examples of typical conditions:
Inventory.key == true
GameState.talkedToGuard != true && Inventory.collectedTokens >= 10
!Player.tagged || Enemy.count < 5
You can learn more details about Condition scripts in the dedicated page on Conditions and Instructions.
Instructions scripts
An Instructions script is a set of value assignments in the form of <l-value> <assigment-operator> <r-value>. In contrast to Condition scripts, an Instructions script can contain an arbitrary number of assignments, separated by semicolons.While the <l-value> of an assignment has to be a defined variable (which includes pre-defined, special variables like seenCounter), the <r-value> can be an arbitrary expression that needs to evaluate to a type that can be assigned to the <l-value>.
Here are all supported assignment operators:
| Operator | Description | |
| <l-value> = <r-value> | Assign: assigns <r-value> to <l-value> | |
| <l-value> += <r-value> | Add-assign: assigns the result of <l-value> + <r-value> to <l-value> | |
| <l-value> -= <r-value> | Subtract-assign: assigns the result of <l-value> + <l-value> to <l-value> | |
| <l-value> *= <r-value> | Multiply-assign: assigns the result of <l-value> * <r-value> to <l-value> | |
| <l-value> /= <r-value> | Divide-assign: assigns the result of <l-value> / <r-value> and assigns the result to <l-value> | |
| <l-value> %= <r-value> | Modulo-assign: assigns the result of <l-value> % <r-value> to <l-value> | |
Examples of typical instructions:
Inventory.key = true;
Inventory.collectedTokens += 5;
GameState.bossDefeated = true;
Player.tagged = Enemy.count > Enemy.taggingThreshold || Enemy.distance <= 12
You can learn more details about Instructions scripts in the dedicated page on Conditions and Instructions.
Using Global Variables
Global Variables can be of type boolean (true/false), integer (number), or string ("text"). They are always addressed in the following notation: <variable-set>.<variable-name>.Example: You created a global boolean variable called "key" that is set to true, if the player finds the missing key. This variable is inside the variable set called "Inventory". To use this variable in conditions or instruction write: "Inventory.key".
You can learn more details about Instructions scripts in the dedicated page on Global Variables.
Accessing objects, properties and templates via Script
Historically, articy:expresso was designed to be used in conjunction with Global Variables. While this was sufficient for a lot of use cases, it can be more useful to store the data alongside the objects directly. Especially given the flexibility that was added with the template system, we introduced specialized functions to the scripting system to access properties and the template data of objects. Additionally, there exist several utility functions and keywords in articy:expresso to facilitate common tasks.Overview over built-in functions (detailed explanations and samples in the next section):
ObjectRef getObj(TechnicalNameOrId, InstanceIndex = 0);
Variable getProp(ObjectRef, PropertyName);
setProp(ObjectRef, PropertyName, Value);
incrementProp(ObjectRef, PropertyName, Value);
decrementProp(ObjectRef, PropertyName, Value);
bool isPropInRange(ObjectRef, PropertyName, LowerBound, UpperBound);
int getSeenCounter(ObjectRef);
setSeenCounter(ObjectRef, Value);
resetAllSeenCounters();
Value random(Min, Max);
bool isInRange(Value, LowerBound, UpperBound);
bool print(Text);
bool fallback(BranchingPointReference = null);
Overview over built-in convenience keywords (detailed explanations and samples in the next section):
ObjectRef speaker;
ObjectRef self;
bool seen;
boolean unseen;
int seenCounter;
Remember that a Condition script must be a boolean expression. Hence, certain functions or keywords like incrementProp(...), setProp(...) or seeCounter cannot be used in Condition scripts.
![]() | "How to access object properties with scripting" |
![]() | "Enhanced scripting with increment and isInRange methods" |
Details on built-in functions and keywords
Accessing and manipulating properties
ObjectRef getObj(TechnicalNameOrId, InstanceIndex = 0)
This function is used in conjunction with functions like getProp(...) and setProp(...).
You can access an object via its technical name or id.
getObj("Chr_Manfred")
getObj("0x01000001000010C6")
Optionally, you can specify the instance id to access another clone of the object.
getObj("NPC_Guard", 1)
Variable getProp(ObjectRef, PropertyName)
To access a property you have to provide a reference to a specific object and the property name as a string.
getProp(getObj("Chr_Manfred"), "DisplayName")
You can access the template data of an object by writing the feature name and the property name separated by a dot.
getProp(getObj("Chr_Manfred"), "Morale.MoraleValue") > 10
Here we used getProp() in a condition, testing the returned value.
Remember that you can use keywords like self or speaker to ease accessing objects:
getProp(speaker, "Player_Character.Morale") > 10
setProp(ObjectRef, PropertyName, Value)
To change the value of a property you have to provide a refernce to a specific object, the property name, and the new value.
setProp(getObj("Chr_Manfred"), "DisplayName", "Player1")
Changing a template property is achieved accordingly:
setProp(getObj("Chr_Manfred"), "Player_Character.Morale", 100)
Remember that you can use keywords like self or speaker to ease accessing objects:
setProp(speaker, "Morale.MoraleValue", 100)
incrementProp(ObjectRef, PropertyName, Value) and decrementProp(ObjectRef, PropertyName, Value)
Instead of nesting setProp and getProp to increment or decrement a value, you can use these convenience functions.
incrementProp(getObj("Chr_Manfred"), "Player_Character.Morale", 10)
decrementProp(speaker, "Player_Character.Morale", 20)
If no change value is specified, the value will be increased or decreased by 1.
incrementProp(speaker, "Attributes.Strength")
bool isPropInRange(ObjectRef, PropertyName, LowerBound, UpperBound)
A convenience function to check if a property value is in a specific range. The bounds are both inclusive.
isPropInRange(getObj("Chr_Manfred"), "Morale.MoraleValue", 50, 100)
Seen/Unseen utilities NEW in adx 4.1!
articy:expresso features specific keywords and functions to react to choices players have made in the past. More specifically, you can query and change what we call a "seen counter property" for a flow object using below utilities. This makes it easy to design scenarios where certain options should only be available once or a limited amount of times to a player.
bool seen
Indicates if this object has been visited (true) or not (false) by the player in a given session. It is the inverse of unseen. As with any other boolean value, you can combine this with other conditions using logical operators:
seen || Inventory.key // node visited or key in inventory
bool unseen
Indicates if this object has been visited (false) or not (true) by the player in a given session. It is the inverse of seen. As with any other boolean value, you can combine this with other conditions using logical operators:
unseen && !Inventory.key // node not visited and key not in inventory
int getSeenCounter(ObjectRef)
Returns how many times the referenced object has been visited.
getSeenCounter(self) > 12
setSeenCounter(ObjectRef, Value)
Sets the seenCounter to Value for the referenced object.
setSeenCounter(self, 2)
int seenCounter
A built-in property usable as short-hand alternative to getSeenCounter(self) and setSeenCounter(self, ...). The following statement-pairs are equivalent:
print(seenCounter);
print(getSeenCounter(self));
// --
seenCounter = 42;
setSeenCounter(self, 42);
resetAllSeenCounters()
Resets all non-zero "seen counter values" to zero.
resetAllSeenCounters()
While the fallback(...) function can be used independently of seen counters and is therefore a more general utility, in many scenarios it makes a lot of sense to combine using the seen/unseen keywords and the fallback(...) function to design scenarios where players need to first exhaust a set of choices before they are presented with a default ("fallback") option.
General utility functions
Value random(Min, Max)
Can be used to work with random values.
incrementProp(getObj("Player"), "Inventory.Gold", random(50, 100));
bool isInRange(Value, LowerBound, UpperBound)
Similar to isPropInRange(...), but not restricted to property values. The bounds are both inclusive.
It can be used for global variables ...
isInRange(Resources.ironSupply, 500, 1000)
... or even with custom methods:
isInRange(getTime(), 6, 12)
print(Text)
Useful as a debug tool when working with a game engine. Similarly to String.Format(), strings can be formatted.
print("Hello");
print("Number {0}", 42);
print(getProp( speaker, "Morale.MoraleValue"));
bool fallback(BranchingPointReference = null) NEW in adx 4.1!
Evaluates to false if any other non-fallback branch in reference to the given branching point is currently valid. By default (i.e. without an explicit branching point reference argument), the branching point is determined by the current player environment.
fallback()
fallback(getObj("0x01000000000008B1"))
Short form
Instead of writing Variable == true you can also just write Variable and instead of writing Variable == false you can write !Variable.Comments
It's possible to add comments to a script via:- // your comment here for a single-line comment and
- /* your comment here */ for multi-line comments
Script Methods
Scripts inside articy:draft can not only be used to check or modify global variables or property values. They also allow you to call arbitrary methods. While of no use inside articy:draft, those methods are much more important inside your game engine project.Calling custom methods can be combined with built-in functions like isInRange(...) or isPropInRange(...)
isInRange(GetTime(), 9, 18)In this example we have a custom method GetTime() to query the current in game time. With isInRange() we can now, for example, determine if a shop is open or closed.

