Storyarn docs
EN
Log in
Documentation

Narrative Design

Condition Editor

Use Builder mode and Code mode to define reusable variable checks for flows and responses, and Builder mode for zones and pins.

The Condition Editor defines checks that read variables and return true or false. Storyarn uses the same editor in several places:

WhereWhat the condition controls
Condition nodesWhich flow branch runs next.
Dialogue responsesWhether a player response is available.
Scene zonesWhether an area is visible or interactive during exploration.
Scene pinsWhether a marker, character, or hotspot is visible or interactive during exploration.

Conditions only read variables. They do not change state. Use the Instruction Editor when you need to write values.

Flow editor canvas with a condition node and its branching connections

Editing modes

A condition in a condition node or a dialogue response has two editing modes. Scene zones and pins edit their conditions in Builder mode alone.

ModeBest forWhat you edit
Builder modeMost users, readable production logic, collaborative reviewSentence-style blocks made from variables, operators, values, and logic groups.
Code modeTechnical designers, fast edits, compact expressionsA text expression such as mc.jaime.health > 50 && quest.door.unlocked.

Both modes edit the same condition. Opening Code mode shows it as text and changes nothing. An edit in Code mode is read back into the blocks and groups Builder mode shows, and saved when you stop typing or leave the text. A comment (//) is refused for now: Builder mode has nowhere to keep it.

Builder mode

Builder mode creates conditions from blocks and rules.

LevelPurpose
RuleOne variable/operator/value comparison, such as mc.jaime.health > 50.
BlockA set of rules combined with All (AND) or Any (OR).
GroupA nested set of selected blocks with its own All or Any logic. Groups behave like parentheses.

A simple condition reads like a sentence:

mc.jaime · health is greater than 50

Use Group selected when a subset of blocks needs to be evaluated together:

((mc.jaime.has_key) && (door.lock_level < 3)) || mc.jaime.is_admin

In Builder mode, group the key block and the lock-level block with All, then combine that group with the admin block using Any. Code mode writes each block of a group in its own parentheses, as above.

Operators by variable type

Variable typeOperators
Number / formulaequals, not equals, greater than, greater than or equal, less than, less than or equal
Text / Rich textequals, not equals, contains, starts with, ends with, is empty
Booleanis true, is false, is not set
Selectequals, not equals, is not set
Multi-selectcontains, does not contain, is empty
Dateequals, not equals, before, after

The available operators depend on the selected variable type, so Builder mode prevents invalid comparisons where possible.

Code mode

Code mode writes the condition in the expression syntax. It is useful when you already know the variable paths or when an expression is faster to type than to assemble in Builder mode.

mc.jaime.health > 50 && (quest.door.unlocked || mc.jaime.has_key)

Each rule compares a variable, on the left, with a value:

Builder modeCode mode
equals, not equalsmc.jaime.class == "rogue", mc.jaime.class != "rogue"
greater than, less than, …>, >=, <, <=
contains, does not containmc.jaime.traits contains "brave", not_contains
starts with, ends withmc.jaime.name starts_with "Ja", ends_with
is emptymc.jaime.notes is_empty
is true, is falsequest.door.unlocked, !quest.door.unlocked
is not setmc.jaime.weapon == nil
before, afterquest.deadline before "2026-01-01", after

Numbers are written as they are, such as 50, -5 or 0.5. Any other value goes in double quotes, with \" for a quote and \\ for a backslash inside it. A rule that has no value yet shows ?: write the value there. Code mode also reads == true and == false as is true and is false, and != true and != false as their opposites.

&& (all) binds before || (any), and parentheses hold the blocks and groups of Builder mode:

  • A rule on its own is a block with that rule: mc.jaime.alive && mc.jaime.health > 50 is two blocks.
  • Parentheses around rules joined by && alone or || alone are one block: (mc.jaime.has_key || mc.jaime.is_admin).
  • Parentheses around parentheses, or around rules that mix && and ||, are a group: ((mc.jaime.has_key && door.lock_level < 3) || (mc.jaime.is_admin)).

Builder mode holds blocks inside groups and nothing deeper, so Code mode refuses more levels of parentheses.

! turns the check after it into its opposite, the comparison included: !(mc.jaime.health > 50) and !mc.jaime.health > 50 are both mc.jaime.health <= 50, and !(a.x && a.y) is !a.x || !a.y. Builder mode has no opposite for starts with, ends with, is empty, is not set, before and after, nor for a check the variable’s type would lose, such as contains on a text, so Code mode refuses to negate them. nil compares with == alone, so != nil is refused too.

A check on a value that is not set fails, and so does its opposite: while a three-state boolean has no value, neither quest.door.unlocked nor !quest.door.unlocked passes, and while a formula cannot be computed, neither mc.jaime.power == 5 nor !(mc.jaime.power == 5) does.

What Builder mode cannot hold is refused with a message where it is written, and nothing is saved until the expression reads: a value on the left, a value on its own, a comparison of two variables, or a comment. Code mode supports autocomplete, linting, and formatting. Use formatting after editing a longer expression so parentheses and logical groups remain readable.

While Builder mode holds something the syntax cannot write, such as a rule without a variable, an empty block or group, or a variable name the syntax cannot write, Code mode shows the condition read-only and says so. Finish or change it in Builder mode to edit the condition in Code mode.

Condition nodes and switch mode

The editor is shared, but some host features are specific to the place where the condition is used.

Condition nodes can use Boolean output mode or Switch output mode. In switch mode, each condition block becomes an output branch and the first matching block wins. A switch is edited in Builder mode only: each case has a name and an output, which Code mode cannot write. Dialogue responses, zones, and pins do not use switch outputs; they use the condition as a gate.