Stages and Dialogues
The dialogue system is built on two lists inside a stage: texts (what's said) and transfers
(where you can go). Both lists use the same trick — conditional visibility: each option carries its own
condition, and the engine picks the first one that matches, in order. An empty
condition {} always matches — a convenient way to define a "default" option at the end of the list.
texts — scene text variants
"texts": [
{ "text": "Come in if it's business — I'm busy right now.", "condition": { "has": ["sidorovich_job"] } },
{ "text": "Oh, a shooter! Come in, we need to talk.", "condition": {} }
]
This lets the same stage say different things depending on the player's progress, without creating a separate
stage for every variant. A typical pattern: the last item in the list is a variant with an empty condition
({}) as a fallback in case none of the more specific variants matched.
transfers — transitions to other stages
"transfers": [
{ "text": "I'll take the job", "stage": "stage_accept", "condition": { "!has": ["sidorovich_job"] } },
{ "text": "How's the job going?", "stage": "stage_progress", "condition": { "has": ["sidorovich_job"] } },
{ "text": "Bye, things to do", "stage": "stage_exit", "condition": {} }
]
Each transfer is a choice button the player sees, but only if its condition is satisfied. This is how
branching dialogues are made: reply options appear or disappear depending on inventory, flags, or progress.
Build your dialogue so a stage's last line always has at least one transfer with the condition {} —
otherwise a player can get stuck on a stage with no available options (if none of the other conditions were
met).
Placeholders in Text
You can interpolate the current player's data into texts and message:
| Placeholder | Substituted with |
|---|---|
@name | Character's name |
@nickname | Callsign |
@money | Amount of money |
@xp | Amount of experience |
@login | Account login |
@location | Current location |
@gang | Player's faction |
@pdaId | PDA identifier |
{ "text": "Hey, @nickname! You've got @money RU on your account — enough for a new piece." }
Transfer stages (utility types)
Not every stage shows text. Three stage types serve a technical role and don't need texts:
type_stage: 4(map transfer) — usesdata: { map, pos }to open the game map at a given point. Dialogues typically end this way: "go there" → the player sees the map.type_stage: 5(load another chapter) — hands off execution to another chapter of the story via theopenStageaction, convenient for splitting a long story into chapters without duplicating logic.type_stage: 6(transfer to a trader) — opens a specific trader's trading window via theopenSelleraction.
Node position on the canvas (editor.x / editor.y)
The editor: { x, y } field only stores the node's coordinates on the canvas in the
story editor — it has no effect on gameplay. You don't need to touch it by hand when
working with "raw" JSON — the editor lays out new nodes itself via automatic graph layout (dagre).
Next
- Conditions — a detailed look at how the
conditionlanguage works. - Actions — the full list of commands a stage can execute.