File Format

Story files are plain UTF-8 text files with the .story extension placed in StreamingAssets/Stories/. Every non-blank line is one command. Blank lines are ignored. Comments are preceded by a double slash // and extend to the end of the line. Comments are ignored by the parser.

Inline Parameters

Character parameters [...]

A bracket token resolves a randomised character dialogue string at compile time.

[new] <characterID> <parameter>
ParameterDescription
greetingA random greeting line for the character.
thanksA random thanks line for the character.
itemNeedThe name key of a random item the character needs.
rewardThe name key of a random reward the character offers.

The optional new prefix forces selection of a new, non-repeating line.

Examples
[mario greeting]
[new mario thanks]
say translated QUEST_NEED [mario itemNeed]

Variable parameters {...}

A brace token reads an integer variable from PlayerSave at compile time. Supported in the set command value position.

Example
set score to {previousScore} + 10

Control Flow Keywords

These keywords are not commands — they are structural delimiters handled directly by the parser.

KeywordDescription
end Closes a scope opened by on or other scope-creating commands.
endif Closes a conditional block opened by if.
else Begins the fallback branch of an if block.
elif Shorthand for else if. Opens a new conditional branch if the previous one failed. Can be chained arbitrarily.
Note: For now, every if must be closed with exactly one endif. Every on block must be closed with end. Mismatched delimiters produce a warning and may generate an incorrect graph. This will be fixed in a future update.

Comparison Operators

Used by if, when playtimes, and requirement. Both symbolic and English forms are accepted where noted.

Symbol English equivalent Meaning
= is Equal to
!= is not Not equal to
< is less than Less than
> is greater than Greater than
>= Greater than or equal to
<= Less than or equal to

Commands

say

Displays a dialogue popup to the player. Supports localisation keys, raw strings, and character parameter tokens. Optionally targets an NPC location first.

Literal message

say <message>

Localised key

say translated <locaKey> [[characterID parameter]] say tr <locaKey> [[characterID parameter]]

Character parameter

say [<characterID> <parameter>]

Targeted NPC interaction popup

say at <npcID> translated <locaKey|message>
Examples
say Hello there!
say translated QUEST_INTRO
say tr QUEST_NEED [mario itemNeed]
say at villager translated NPC_GREETING
say [mario greeting]

set

Sets a save variable to a value, optionally chaining arithmetic operations. Can also set the state of a world object.

Set save variable

set <varName> [to] <value|{varName}> [(+ | - | * | /) <value|{varName}> …]

Set object state

set state [of] <objectID> [to] (<stateName> | index <N>)
Note: The to keyword is optional in both forms and exists only for readability.
Note: The arithmetic operations are evaluated left-to-right, not according to standard operator precedence.
Examples
set questProgress to 1
set score 100
set score to {score} + 10
set score to {score} * 2 - 5
set state of door to open
set state of trapdoor to index 2

if / elif / else / endif

Conditional branching. The body of the passing branch executes; all branches rejoin at the endif line. Multiple elif branches can be chained.

if [variable | item | played] <name> <operator> <value> … commands … elif [variable | item | played] <name> <operator> <value> … commands … else … commands … endif
Type qualifierChecks
variable (default)A named integer save variable.
itemThe player's inventory count of an item.
playedNumber of times a mini-game has been played.

The type qualifier is optional. When omitted, a variable check is assumed and the first token after if is treated as the variable name directly. English operators (is, is not, is greater than, is less than) are also accepted.

Examples
if questProgress = 0
    say translated QUEST_NOT_STARTED
elif questProgress = 1
    say translated QUEST_IN_PROGRESS
else
    say translated QUEST_COMPLETE
endif

if variable score > 100
    give player trophy x1
endif

if item appleItem >= 3
    say translated ENOUGH_APPLES
endif

if test_var is greater than 5
    say translated BIG_NUMBER
endif

when

Registers a game-world event trigger that starts a new execution branch when the condition is met. Each when opens a new scope in the story graph; subsequent commands until the next top-level scope belong to that branch.

Player talks to an NPC / object

when talk [to | at] <locationID> [once] [id <interactionID>]

Custom interaction (custom label & icon)

when (<titleKey> <iconKey>) [to | at] <locationID> [once] [id <interactionID>]

Player uses an item on a location

when use <itemID> [on | at] <locationID> [once] [id <interactionID>]

Player gains an item

when gain [item] <itemID> [<count>]

Player arrives at a location

when arrive [at] <locationID> [once]

Mini-game play count condition

when playtimes <gameID> [<operator>] <value>
once — when present, the interaction is automatically removed after it fires for the first time.
id — assigns a custom interaction identifier, useful for later removal with remove interaction. Defaults to titleKey_locationID or use_itemID_on_locationID.
Examples
when talk to villager
    say translated NPC_GREETING

when talk at questgiver once
    say translated QUEST_INTRO

when (EXAMINE icon_magnify) at ancientRuin id ruins_examine
    say translated RUINS_DESCRIPTION

when use keyItem on lockedDoor once
    say translated DOOR_UNLOCKED

when gain item apple 3
    say translated GOT_APPLES

when arrive at marketSquare
    say translated WELCOME_TO_MARKET

when playtimes fishingGame >= 5
    say translated FISHING_VETERAN

give / take

Adds or removes an item from the player's inventory. The optional animated flag plays the item fly-to-inventory animation.

give [player] <itemID|[charParam]> [[x]<count>] [animated [<objectID>]] take [player] <itemID> [[x]<count>] [animated [<objectID>]]
player is optional and exists only for readability.
The count can be written as 3, x3, or x 3. Defaults to 1.
When animated is given, the optional objectID can specify the world object the animation originates from.
Examples
give apple
give player apple x3
give player apple 3 animated appleBush
take apple x2
take player coin 10 animated

collect

Waits for the player to collect an item or pick up a specific world object, then adds the result to the inventory.

Collect an inventory item directly

collect item <itemID> [[x]<count>]

Collect a physical world object, converting it to an item

collect object <objectID> [as] <itemID> [animated]
Examples
collect item apple
collect item coin x5
collect object woodenCrate as lumber
collect object flowerBush as flower animated

item

Registers a quest item, assigning it a unique ID and a display name localisation key. Must be declared before any commands that reference the item.

item <uid> [as] <itemID> [called] <nameLocaKey>
uid is the unique quest-instance identifier.
itemID is the game-wide item type identifier.
nameLocaKey is the localisation key for the item's display name.
The keywords as and called are optional separators.
Examples
item quest_apple as apple called ITEM_APPLE
item quest_key questKey called ITEM_KEY

key

Locks an interaction on an object behind possession of a specific item. The interaction becomes available only when the player carries the key item.

key <itemID|uid> [opens] <objectID>
Example
key questKey opens lockedChest

play

Triggers an Animator state or trigger on a world object identified by its IdTag.

play <animationState> [trigger] [as | of] <objectID>
trigger — when present, sets an Animator trigger parameter instead of a state name.
Examples
play open of door
play celebrate as villager
play Jump trigger of player

effect

Spawns or plays a named visual/audio effect at the position of a world object.

effect <effectID> [at] <objectID>
Examples
effect sparkle at treasure
effect explosion campfire

vehicle

Moves a named vehicle from one location waypoint to another.

vehicle <vehicleID> [from] <startLocationID> [to] <endLocationID>
The from and to keywords are optional separators.
Examples
vehicle ferry from dockA to dockB
vehicle cart harbourGate marketGate

checkpoint

Marks the current execution position as a checkpoint. If the player exits the game or plays a minigame, the story resumes from the most recent checkpoint when the main scene is reloaded. Use clear to remove the active checkpoint.

checkpoint [<id> | clear]
If no ID is given, a UUID is generated automatically. clear removes the currently active checkpoint.
Examples
checkpoint
checkpoint quest_start
checkpoint clear

remove

Removes a previously registered interaction from a world object, preventing it from being triggered again.

remove interaction <interactionID>
Warning: remove item is not valid. Use take to remove items from the player's inventory.
Example
remove interaction ruins_examine

requirement

Adds a gate at the current point in the graph: execution continues only if the named variable satisfies the condition. Used to guard event branches. Defaults to > 0 if no operator or value is given.

requirement [variable] <varName> [<operator> <value>]
Examples
requirement questProgress
requirement variable questProgress > 0
requirement score >= 50

on / do

on declares a named reusable sub-graph (function). The body between on and end becomes an isolated sub-graph. do calls that sub-graph by name, inserting its nodes inline.

Declare a function

on <functionName> … commands … end

Call a function

do <functionName>
Note: Function declarations with on must be closed with end, not endif.
Examples
on questComplete
    give player trophy
    set questProgress to 3
    say translated QUEST_DONE
end

when talk to questgiver
    requirement questProgress = 2
    do questComplete

Full Example

A complete quest script demonstrating most features together.

CommandQuest.story
// Register the quest item used throughout this quest
item quest_apple as apple called ITEM_APPLE

// Declare a reusable completion routine
on completeQuest
    give player reward x1 animated rewardChest
    set questProgress to 2
    say translated QUEST_COMPLETE
end

// Trigger when the player first talks to the villager
when talk to villager once
    requirement questProgress = 0
    say translated VILLAGER_INTRO
    say translated VILLAGER_NEED [villager itemNeed]
    set questProgress to 1

// Trigger when the player returns with the apple
when talk to villager
    requirement questProgress = 1
    if item apple >= 1
        take apple
        do completeQuest
    else
        say translated VILLAGER_WAITING
    endif

// Play a celebration effect when quest is done
when talk to villager
    requirement questProgress = 2
    say translated VILLAGER_THANKS
    effect confetti at villager

// Activate the key-locked chest after the quest is complete
when arrive at treasureRoom
    requirement questProgress >= 2
    key quest_apple opens treasureChest
    checkpoint afterArrival