Keyboard shortcuts

Press ← or → to navigate between chapters

Press S or / to search in the book

Press ? to show this help

Press Esc to hide this help

script.txt syntax

Mode A stories are plain text under story/script.txt. Blank lines separate nodes. The parser builds the same objects as JSON — script is sugar, not a second runtime. Story nodes.

:: park
[bg street fade 0.5]
HANA [happy]:
Hello.
> Help. -> help
> Leave. -> END

→ roughly:

{
  "id": "park",
  "talking": "hana",
  "text": "Hello.",
  "commands": [
    { "type": "bg", "value": "street", "transition": "fade", "duration": 0.5 },
    { "type": "char", "name": "hana", "expression": "happy" }
  ],
  "choices": {
    "items": [
      { "text": "Help.", "target": "help" },
      { "text": "Leave.", "target": "END" }
    ]
  }
}

Usually you need

ConstructFormEffect
Label:: idNode id (:: start = New Game entry; omit → first moment)
SpeakerNAME: / NAME [expr]:Talking + optional enter char
Textfollowing linesDialogue (joined with {@w})
Choice> text / > text -> targetChoice item; bare > → NEXT
Jump-> target / -> ENDNode next
Flag[flag = …] / += / -=Node set
Command[bg …], [hana left], …Enter commands

Full construct list

ConstructFormEffect
Blank lineempty lineEnds the current node
Comment# …Ignored
Label:: idSets node id
SpeakerNAME:talking = character id (folder name)
ExpressionNAME [expr]:Also queues enter char with that expression
Custom labelLabel|NAME:label + talking
JointNAME & NAME: / NAME [expr] & NAME (silent):Multi-speaker talking; per-segment expr / silent
SilentNAME (silent):That speaker’s mouth drive off; on joints, only names marked (silent)
Textnon-special linesJoined; speaker change inserts {@talk:id}
Mid-line cmds[…] after text startedflow_commands + {@cN} markers
Choice> text / > text -> targetchoices.items[]
Text input[input flag …]input on the node
Jump-> targetnext
End-> ENDnext: null
Flag[name = lit|expr] / += / -=set
Branch[if expr -> target]next_if[]
Auto-advance[auto N]auto: N
Panel sugar[panel …], [panel_id …], [hide_panel], …Node fields or panel commands
Exit[exit: …], [exit_delay N]exit_commands / exit_delay
Locale helpers[text_ref key], [text_from id]Those node fields
Commands[keyword …] / [charname …]Enter commands (or flow if after text)

Keyword commands: bg, bgm, sfx, panel, typing_sfx, jump, jump_if, call, return, set_flag, char_layout, char_pack, choice_style, input_style, screen, plus bare character folder names → char. ([input …] writes the node’s input field, like > writes choices.)

A line that is a whole BBCode wrap ([b]…[/b], [right]…[/right], [color=…]…[/color], …) stays as text, not a command.

Line breaks inside text: a new line in the file is a pause (the player advances). To break the line on screen without a pause, write \n in the text — [right]You\nOn my way.[/right]. Write \\n for a literal \n.