Text directives
Description: Make a line reflect game state — interpolate a variable, or branch its wording automatically.
Any player-facing text — a dialogue line, a choice's label — can embed a text directive: a
@{...} construct that gets resolved when the line is actually shown, using whatever the game
state is at that moment. There are two things you can do with one:
- Interpolate a variable's value into the middle of a sentence.
- Branch the wording itself — pick one of several phrasings based on state like gender, how a quest turned out, or a count.
Reach for a directive instead of authoring several near-identical lines and gating each with its own condition. The whole variant set stays together in one string, in context, and — if you localize later — as one translatable unit instead of several that can drift out of sync.
Interpolation: @{VarName}
@{VarName} is replaced by that variable's current value. The name has to be a bare variable
name — no dots, spaces, or expressions.
Welcome back, @{PlayerName}. You carry @{Gold} gold.
How a value shows up depends on its type: text appears as-is, numbers are formatted cleanly
(1.5, not 1.500000), and true/false values show as true/false. If the variable points at
an enumeration, its player-facing label appears — "Imperial Legion," not whatever internal key
that entry has. If it points at an entity, the entity's name appears.
If the name doesn't match a variable, the directive is left in the text exactly as written
(@{VarName}) rather than erroring — a visible signal in playtesting that something's misspelled
or missing.
Branching wording: @{select ...}
@{select Subject, Label {text} Label {text} other {text} } picks the first label that matches
the subject variable's current value and shows that label's text. Always include other as a
catch-all — without a match and without one, the directive shows nothing at all.
@{select Gender, Male {He} Female {She} other {They} } readies for battle.
You return to town. @{select JarlState,
Dead {The throne sits empty.}
Alive {The Jarl greets you with a nod.}
other {No one will say where the Jarl has gone.} }
A label matches against the variable's underlying value, not its display label — an enumeration
matches on its key (Dead, not "Deceased"), and a true/false variable matches against the labels
true and false.
Counting: @{plural ...}
@{plural CountVar, ... } is select, specialized for a number. =N labels match an exact
count first, then one (the count is exactly 1) and other (everything else) take over. Inside
a plural's text, # stands in for the count itself.
@{plural ArrowCount,
=0 {You are out of arrows.}
one {You have # arrow left.}
other {You have # arrows left, @{PlayerName}.} }
Only one and other are available today — the finer-grained categories some languages need
(zero, two, few, many) aren't supported yet.
Things worth knowing
- The subject of a
selectorpluralis always a bare variable, never an expression.@{select Gender, ...}works;@{select Health > 0, ...}doesn't. To branch on something computed, store the result in a variable first — an Instruction Node is the usual way — and select on that. - Directives nest. A variant's text can contain further
@{...}directives to any depth, so a count and a gendered pronoun can agree correctly inside one string. - Write a literal
@{as@@{. A lone@or{on its own needs no escaping. - A variable's value is never itself re-scanned for directives — only the authored text is.
Next
Dialogues covers where this text lives, Variables covers the state it draws from, and Expressions covers the separate language that conditions and instructions are written in.