Appearance
Run Script language
Run Script is the small command language MMO Run uses for quests, NPC conversations and world events. It is deliberately not a programming language: a file is a list of triggers, each holding conditions, choices and verbs. Anything a script can do is a verb some extension registered, and anything it can read is a function on a fixed context object, so a script cannot reach files, the database or other players except through those.
Scripts live in content/scripts/*.run. Host scripts go in worlds/<name>/content/scripts/ and are what the in-game editors write. The id of a script is <owner>:<file name>.
Shape
# comments start with a hash
when talk npcs:old_wendel # trigger with an argument
if has_item("inventory:bread", 2) and not flag("wendel_fed")
take bread 2
set_flag wendel_fed
give_gold 10
say "Bread! Tell Hilde thank you."
elif flag("wendel_fed")
say "You again, {name}? Go home, it is late."
else
say "Hilde said she would send bread."
choice
"Who are you?"
say "A hermit. Go away."
"Goodbye"
stopBlocks are made by indentation (spaces or tabs, used consistently). when blocks sit at the top level; everything else is inside one.
Triggers
| Trigger | Argument | Player in context | Fires on |
|---|---|---|---|
when talk <npc> | npc id (npcs:innkeeper or innkeeper) | yes, with the NPC | a player starts talking to that NPC |
when kill <mob> | mob id or any | the killer | a player kills a mob |
when enter_zone <zone> | zone id | yes | a player enters the zone (login included) |
when login | none | yes | a character enters the world |
when quest_done <quest> | quest id | yes | a quest is turned in |
when use <item> | item id | yes | a player uses the item from the bag (consume uses it up) |
when levelup [n] | level or none | yes | a player reaches a level |
when timer 5m | a period | no | every period, world-wide |
when run | none | the player it was run for | /script run <id> [player] or the run verb |
A when talk block that says anything replaces the NPC's own dialogue tree. One that only checks and sets things lets the normal dialogue follow. dialogue shows the tree explicitly.
Conditions
if, elif and else take a Godot expression: and, or, not, ==, !=, <, >=, numbers, "strings" and these functions.
| Function | Meaning |
|---|---|
has_item("id", qty) / item_count("id") | bag contents (qty defaults to 1) |
gold() | gold coins |
flag("name") | this character's flag (false when unset) |
global("name") | a world-wide value (false when unset) |
level(), player_class() | from leveling and classes |
quest_active("id"), quest_done("id") | quest state |
name(), zone() | the player |
hour(), is_night() | from daynight (noon and day without it) |
online() | players online |
random(n) (1..n), chance(percent) | dice |
event("key") | a field of the event that fired (for example event("qty")) |
Extensions you enable may add more functions and verbs; their pages list them.
Verbs
Arguments are literal: "strings", numbers, durations (500ms, 2s, 5m, 1h) and bare words. Ids may drop the owner: bread means inventory:bread in give, rat means mobs:rat in spawn.
| Verb | Needs | Does |
|---|---|---|
say "text" | in a conversation: shows the text with a Continue button (or with the options when a choice follows); elsewhere a notice | |
notice "text" [info|warn|error] | a notice to the player | |
broadcast "text" | a notice to everyone online | |
wait 2s | pauses the script | |
set_flag name [value], clear_flag name | per-character, persistent | |
set_global name [value], clear_global name | world-wide, persistent | |
teleport zone x y | moves the player to a tile | |
give item [qty], take item [qty] | inventory | bag changes |
give_gold n, take_gold n | inventory | gold |
start_quest id, complete_quest id | quests | the player is told why when it cannot happen |
xp n | leveling | |
heal n | combat | |
spawn mob [count] | mobs | next to the player (up to 20) |
dialogue [node] | npcs | hands the conversation to the NPC's own tree |
run script_id | starts another script's when run block | |
emit ext:event | fires an extension event with {entity, npc, script, event} | |
consume | in when use: the item is used up | |
stop | ends this block |
choice lists quoted labels, each with its own indented block; the player picks one. Text in say and notice may use {name}, {zone}, {flag:x}, {global:x} and {event:x}.
Errors and limits
Problems are reported at load with file and line in plain sentences (/script errors), for example host:wendel.run:7: unknown verb 'gift'; one of: ... or ... 'give' needs the inventory extension, which is not enabled. A block that executes more than max_steps instructions is stopped, and at most max_fibers scripts may be alive at once (ones waiting on a timer or a conversation count). when timer periods are clamped to min_timer_seconds.