Documentation menu

Expressions

Description: Write conditions and instructions for graph logic.

Graphs use short expressions to make decisions and change state. The language supports common comparisons, assignments, and function calls without acting as a general scripting language.

  • A condition evaluates to true or false. Gates, Hub outputs, choices, and Event Listeners use conditions such as Gold >= 10 && !HasMap.
  • An instruction changes state or calls a function. Instruction Nodes run statements such as JarlIsDead := true.

Different from text directives. Player-facing text uses @{PlayerName} and @{select ...}. These constructs follow the rules in Text directives. Don't use @{...} in expressions or expression syntax in dialogue text.

JavaScript users. Many JavaScript expressions also work in Narratyr. Narratyr adds word forms for logical operators, the in operator for list membership, and := for assignment.

Names and values

Expressions can refer to document variables and function definitions. The editor reports unknown names while you type. Press Ctrl+Space in an expression field to see the names available at the cursor.

Variable references must match the Variables view, such as Gold, Jarl_IsDead, or Player_VisitedLocations, and can't contain dots. Use underscore characters for name prefixes.

You can write these values directly:

Kind Examples
Number 42, -1.5, 0.25
Text "MacGuffin", 'a sword' with either quote style
True or false true, false
Option set entry QuestPhaseEnum.Active
List ["a", "b", "c"]
Empty null, undefined

An option set entry uses a dot between the set name and entry key. It has the form EnumName.EntryKey with no other parts. Expressions compare with the key instead of the player-facing display name:

QuestPhase == QuestPhaseEnum.Active

Conditions

A condition can use a true or false variable by itself. JarlIsDead passes when the value is true, and !JarlIsDead passes when the value is false. Numbers count as true when they aren't zero.

Operators

Operators Behavior
== != Test equality or inequality
< > <= >= Compare numbers or text
+ - * / % Perform arithmetic. + also joins text
in not in Test membership in a list or set
[ ] Read a list item by position, such as VisitedLocations[0]

Combine conditions with and, or, and not. The symbols &&, ||, and ! provide the same behavior. Choose one style for your project.

Parentheses group operations. Arithmetic runs before comparisons, comparisons run before and, and and runs before or. Add parentheses when the intended order isn't clear.

Equality compares values with the same type. A comparison between text and a number returns false. Check for an accidental quoted number when a condition such as Gold == "10" doesn't pass.

Lists and sets

Use in or not in for membership. Built-in functions provide size, occurrence count, and item position:

"MacGuffin" in Player_Inventory
ColorEnum.Red not in Banner_Colors
length(Player_Inventory) >= 3
count(Visited_Towns, "Riften") > 1
indexOf(Party_Members, "Sandra") != -1

length returns the number of items. count returns the number of matches, which is always 0 or 1 for a set. indexOf returns the zero-based position of the first match or -1 when it finds none. Reading beyond a list with [ ] returns an empty value.

Visit counts

Built-in traversal functions let dialogue respond to earlier choices. Their counts cover the complete game and form part of saved runtime state.

  • choiceTakenCount() returns the number of earlier selections for the current choice. Use it only in that choice's hide or disable condition. choiceTakenCount() > 0 can hide or disable an option after the player uses it.
  • lastChoiceTakenCount() includes the choice that the player just selected. Conditions on outgoing connections can compare the result with 1, 2, or later counts to vary the response.
  • traversed(id) returns the traversal count for a connection, node, or choice. Copy the required ID from the properties panel. The function can refer to elements in other graphs.

Use the choice-specific functions when possible because they don't require a stored ID.

Quest progress

questStatus("<quest id or name>") returns a quest status. objectiveStatus("<quest id or name>", "<objective id or technical name>") returns an objective status within that quest.

questStatus("IntroQuest") == "completed"
objectiveStatus("JarlQuest", "JarlQuest_FindTheSword") == "active"

Quest status values are "undiscovered", "inactive", "active", "failed", and "completed". Objective status values are "locked", "active", "completed", "failed", and "not_applicable". Both functions return "error" for an invalid reference or unavailable quest data.

Completion lists quest IDs for questStatus. For objectiveStatus, it first lists quests and then limits objective choices to the selected quest. It inserts an objective's technical name when available and otherwise inserts its stable ID. Completion also lists valid status values.

Quest and objective name matching ignores letter case. Document checks report an unknown literal quest reference. They also warn when a quest name or objective technical name uses different capitalization from its definition.

A Gate can create an objective condition without typed syntax. Select the objective mode and choose objectives and statuses from the lists. The editor writes the equivalent expression.

Instructions

An Instruction Node contains statements separated by newlines or semicolon characters. Each statement changes a variable or calls a function.

Jarl_IsDead := true
Gold += 5
Persuasion_Attempts++
Player_Inventory += "OldMap"
addInventoryItem("Potion", 1)
Form Behavior
Gold := 10 Assign a value. Gold = 10 has the same effect
Gold += 5 Update with +=, -=, *=, or /=
Gold++, Gold-- Add or subtract one
MyList += "a" Append to a list or add to a set
MyList -= "a" Remove the last list match or remove a set value
addInventoryItem("Potion", 1) Call a function for its effect

Compact updates state the operation directly. Gold += 5 and Gold := Gold + 5 produce the same result.

For numbers, += and -= add or subtract. For lists and sets, they add or remove an item. Adding an existing value to a set leaves the set unchanged.

Call game functions

Use a function for behavior that your game provides, such as an inventory query or an item grant. Define its name, parameters, and return type in the Functions view. Your engine integration supplies the implementation. See Function definitions.

hasInventoryItem("MacGuffin") && Gold >= 10
removeInventoryItem("OldMap", 1)

A function with a return value can appear within a condition. A function that returns void runs as a statement in an Instruction Node.

Narratyr provides built-ins for lists, traversal counts, quest status, random values, and log messages. debugLog(message) writes a message to the engine log.

Expression rules

  • Event Listener conditions can't call functions. Listeners check again after a variable changes, so they can't detect a new result from game state behind a function. Copy that state into a variable.
  • Expressions don't support comments. Use the node description or a Comment node to explain complex logic.
  • The editor reports syntax and type problems. It marks unknown names, unmatched parentheses, and incompatible comparisons. Project checks report the same problems before export.

Custom engine support

The Unreal Engine, Godot, and Unity plugins include expression interpreters. A custom engine can use the exported abstract syntax tree instead. The expression abstract syntax tree documents the parsed format and evaluation rules.

Next

Function definitions explains callable game behavior, and Variables covers expression state. Dialogues and Quests describe graph nodes that use expressions. Text directives covers the separate syntax for player-facing text.