Community Edition “New breath for an old well.”

The Quest Script

Scenes are written in a small line-by-line language. A scene starts with a SCENE header and runs until it reaches END, jumps to a fight or leaves for the map. Every line is one command; the first word says which. This page is the reference as ReBreather runs it; the Cookies page covers the #<name> values a script can read.

Every section ends with a worked example. The examples are made up for this page: the item, monster, map, token and scene numbers are placeholders, and the skins and sounds are whatever your world ships. The last section puts the pieces together into one complete scene you can paste into a test world and change.

Lines

  • Scenes go between +SCENES and -SCENES. A line that begins with SCENE before any section opens the scenes section by itself.
  • Lines are not trimmed: do not indent commands. Tabs count as spaces.
  • Only a line whose first character is a semicolon is a comment. There are no end-of-line comments.
  • Keep scripts plain ASCII. An accented letter cuts the line in two.
  • Columns are separated by spaces or commas; quote any argument that contains either. At most 32 columns.
  • The command word is matched without regard to case. An unknown word is logged with its line and skipped.
  • #include path pulls in another file, relative to the one it is in, up to 24 deep.

Example: the shape of a scene file

; quest.txt -- a semicolon in column 1 starts a comment
+SCENES
SCENE 10, village,, "The Square"
ACTOR 1, Mara, herbalist, 0, 30, 70
' Welcome to Ashford, traveller.
MENU "Who are you?=@who", "What is this place?=@place", "Goodbye=@bye"
GOTO @bye
@who
' I keep the herb stall. Nothing fancy, nothing poisonous.
GOTO @bye
@place
' Ashford. Mind the well, and mind the people too.
@bye
' Safe roads.
END
#include side/caves.txt
-SCENES

Nothing is indented, the menu items are quoted because they contain spaces, the empty style column is written as two commas, and every path reaches END. The #include line pulls the cave scenes in from a second file so the main one stays readable. The GOTO @bye after the menu only runs if the player closes the menu without choosing.

The scene header

SCENE <number>, [<background>], [<style>], [<title>], [<effect>], [<weather>], [<colour>]

Only the number is required. A background, effect or weather left out is taken from the link the scene was entered from; one written but empty reads as nothing. The style cut makes a cut scene. The title appears in the window caption.

Example: three headers

SCENE 10
SCENE 11, cellar,, "Below the Inn", 3, 0
SCENE 12, throne, cut, "The Coronation",, 5040

Scene 10 takes everything from its link. Scene 11 names a background and a title, asks for effect 3 (scanlines) and switches the weather off even if the link had rain. Scene 12 is a cut scene with medium snow in palette colour 40 and whatever effect the link had, since that column is left empty.

Labels and events

A label is @name in column 1; anything after a space is ignored. GOTO @name looks down from the current scene and stops at the next scene header, and GOTO 120@name reaches into scene 120. A missing label is logged and the line skipped.

The game itself jumps to these labels when something happens, and they keep working after END:

LabelWhen
@eventActorClick3The player clicks actor 3. Sets event.actor.
@eventActorGive3The player gives actor 3 an item, gold or a trophy. Sets item.id, item.goldGiven, item.trophyGiven.
@eventActorAttack3, @eventActorSpell3Actor 3 is attacked or has a spell cast on it. Sets item.id or spell.id.
@eventHostGiveSomething is given to the scene's host.
@eventTimer2Timer 2, started with TIMER, runs out.
@eventMissionAccepted, @eventMissionRewarded, @eventMissionAbandonedMissions book actions. Sets event.missionId.

Example: a smith who reacts to clicks and gifts

SCENE 20, forge,, "Orin's Forge"
ACTOR 1, Orin, smith, 0, 60, 70
' Click me if you want to talk. Hand me iron ore and I'll make something of it.
END

@eventActorClick1
' Still here, %2? The hammer's getting cold.
END

@eventActorGive1
COMPARE #<item.id>, 30
IF=, @ore
COMPARE #<item.goldGiven>, 0
IF>, @coins
' I've no use for that.
END
@ore
' Good ore. Give me a moment.
WAIT 2
SOUND hammer.wav
GIVE I31
' There. A blade worth the name.
END
@coins
' A tip? Kind of you. Now bring me ore.
END

The script ends at once and the scene then waits for events. Clicking Orin runs the click label; giving him anything runs the give label with item.id and item.goldGiven filled in, so the script compares them and branches. Item 30 is ore and item 31 the finished sword. A gift of gold arrives with item.id at 0 and the amount in item.goldGiven, which is why the ore test comes first.

Speech

LineEffect
' Hello or " Hello or : HelloThe selected actor says it. Write exactly one space after the mark: the text starts at the third character.
2: HelloSelects actor 2, then speaks.
H: Hello or HOST HelloThe scene's host speaks.
N: The door creaks. or NARRATION ...Narration in the chat window: no bubble, no wait.

Text is cookie-expanded and then these codes are replaced: %1 the host's name, %2 your own name, %0 the last actor to speak, %C the host's class, %L the host's title (%L-1 the level number), %K total kills (%K40 kills of monster 40), %I %M %S %T %Z the current item, monster, spell, token and trophy names, %R6 a random number from 1 to 6, %3 a random insult and %% a percent sign.

Example: two actors, narration and codes

SCENE 30, tavern,, "The Drowned Rat"
ACTOR 1, Bess, barmaid, 0, 25, 70
ACTOR 2, Tam, drunk, 0, 75, 70
N: The tavern smells of wet dog and old beer.
1: Evening, %2. A %L like you must be thirsty.
2: Don't listen to her. She waters the ale.
1: And you, %0, still owe me for last week.
HOST I'll have whatever is strongest.
' Coming up. That's %R6 coppers, and I'll thank you not to haggle.
END

1: and 2: select an actor and speak in one line; the bare ' line speaks for whoever was selected last, so it is Bess again. %0 names the last actor to speak, which is Tam by then. %L gives the hero's class title at their level, and %R6 rolls a different price every visit. The N: line goes to the chat window without a bubble and without a pause.

Flow

CommandWhat it does
GOTO @label, GOTO 120@labelJumps.
GOTO EXITLeaves the scene for the map, then runs the line beginning EXIT if there is one. With no such line ReBreather stops the script (the original restarted it).
GOTO LINK map, link, dropInEnds the script and moves the hero to a link on a map, dropping into its scene when dropIn is not 0.
GOTO SCENE nRestarts in scene n.
CALL @label, arg... / RETURN arg...A subroutine call; the arguments become cookies arg0 to arg9 and numArgs. They are stored before the label is looked up, so a missing label still sets them. A call stack that is full is logged and the script goes on.
IF condition, @labelJumps when the condition holds. See below.
IF=, IF<> (or IF!=), IF>, IF<, IF>=, IF<=, IFEVEN, IFODD @labelJump on the last compare result (from COMPARE, STRCMP, STRSTR or any arithmetic).
ENDStops the script. The scene stays open and event labels still fire.
WAIT secondsPauses (decimals allowed). Clicking does not skip it.
PUSH cookie / POP cookieSaves and restores a cookie's value, handy round a CALL.

Example: a shared toll routine

SCENE 40, gate,, "The North Gate"
ACTOR 1, Guard, guard, 0, 50, 70
' Ten gold to pass, or show the captain's token.
IF T9, @waved
CALL @pay, 10
COMPARE #<arg0>, 1
IF=, @paid
' Then you can wait out here.
END
@waved
' Captain's token. Through you go.
GOTO LINK 2, 5, 0
@paid
' Mind the mud.
GOTO LINK 2, 5, 0

; Takes arg0 gold if the hero has it. Returns 1 on success, 0 otherwise.
@pay
IF G#<arg0>, @canPay
RETURN 0
@canPay
TAKE G#<arg0>
SOUND coins.wav
RETURN 1

SCENE 41, gate,, "The South Gate"
ACTOR 1, Guard, guard, 0, 50, 70
' Five gold here. The north gate charges double.
CALL 40@pay, 5
COMPARE #<arg0>, 1
IF=, @paid
' No coin, no passage.
END
@paid
GOTO LINK 2, 9, 0

CALL @pay, 10 puts 10 in arg0, and the routine's RETURN 1 or RETURN 0 puts the result back in the same cookie for the caller to compare. The condition G#<arg0> becomes G10 before the test runs, because conditions are cookie-expanded. The south gate reuses the routine with CALL 40@pay, which reaches into scene 40 for the label exactly as GOTO would. Both gates leave with GOTO LINK, which ends the script and puts the hero on link 5 or 9 of map 2 without entering that link's scene.

Example: saving a cookie round a call

PUSH arg0
CALL @describe, "the old mill"
POP arg0

A routine overwrites arg0 to arg9; if the caller still needs an earlier value, PUSH it first and POP it back afterwards.

IF conditions

Alternatives are separated by | (a trailing one is ignored); within one, tests separated by spaces, commas or + must all hold, so quote a condition that contains spaces or join its parts with +. A leading - negates a test; a second - does not undo it, and a - after a test ends that test. A word test is judged by its first letter and must be longer than one character: WIN is WON, LOSE is LOST, and Y alone is always false, so write YES. Every test is false for a soul that has not incarnated.

TestTrue when
#5the current map is 5
ALIVE / DEADHP is above 0 / is 0
C2the hero's class is 2
E12item 12 is equipped
F4the map's flags include 4 (the test returns the raw bits, so -F4 is unreliable)
G500 / GSat least 500 gold / the soul has a serial number
H20at least 20 hours played
I12.3at least 3 of item 12 (the count defaults to 1)
JQ3, JA3, J3 (or JF3)mission 3 qualifies, is accepted, is complete. JA only answers while the Missions window is open; anywhere else it is false
KM40.5 / KB40.5at least 5 kills of monster 40 / killed at least 5 times by it (monster 0 = all)
WON / LOSTthe last fight was won (also true before any fight) / lost
M0 / M4the hero is marked as a cheater / has modder flag 4
YES / NOthe hero's last chat line began with yes, yeah, sure, si, ok or ja, or was exactly da / began with no, nah, nein, nyet or nope (an empty line counts as no)
P / P3player killing is on / on with at least 3 PK kills (like F, the raw value comes back, so -P is unreliable)
Qwordthe last chat line contains the word (^ stands for a space)
R30a 30 percent chance
S5the hero knows spell 5
T9the hero holds token 9
V10level 10 or above
XPthe countdown has expired (or none is running)
Z7.2at least 2 of trophy 7

Example: a door with several keys

SCENE 50, crypt,, "The Sealed Door"
N: The door is carved with a wolf. There is a keyhole and a small bowl.
IF T4, @open
IF "V15 I22", @open
IF Z7.3|G1000, @bribe
IF -KM40.1, @never
N: The wolf carving seems to watch you.
END
@open
N: The door swings inward.
GOTO LINK 3, 1, 1
@bribe
N: A voice from nowhere: "Three wolf pelts, or a thousand gold. Which?"
ASK 30
IF Qpelt, @pelts
IF Qgold, @gold
IF YES, @gold
N: The voice falls silent.
END
@pelts
IF -Z7.3, @never
TAKE Z7.3
GIVE T4
GOTO @open
@gold
IF -G1000, @never
TAKE G1000
GIVE T4
GOTO @open
@never
N: Nothing happens. Perhaps you have not earned this yet.
END

The first test passes anyone with token 4. The second is quoted because it holds two tests that must both be true: level 15 and item 22 in the bag. The third uses | for either three of trophy 7 or a thousand gold. -KM40.1 is true for a hero who has never killed monster 40 at all. ASK 30 waits up to thirty seconds for a typed answer; Qpelt looks for the word anywhere in it, and YES catches a plain agreement. Each payment branch checks again that the hero can pay, because the player may have typed "gold" while only qualifying through pelts. GOTO LINK 3, 1, 1 drops the hero straight into the scene behind link 1 of map 3, since the last argument is not 0.

Actors and dialog

CommandWhat it does
ACTOR n, name, skin, [pose], [x], [y], [colour], [painSound]Places actor n (0-63) with a skin from the game's skins folder and selects it. An empty skin removes the actor; x and y are percentages, 0,0 picks a free spot.
SEL n, SELECT n, SAY nSelects the actor that later speech lines speak for. The three words are one command: SAY 3 selects actor 3 and says nothing.
FACE n, mode0 left, 1 right, 2 toward the host, 3 away, 4 flip.
POSE frame, [frame], [frame]The selected actor's pose cycle.
MOVE n, x, y, [mode]Walks actor n (or H, the host) to x,y. Mode 1 jumps, 2 to 5 walk faster.
MENU "Buy=@shop", "Talk=@talk", "Leave=@bye"Up to 30 choices; waits for one. Each choice splits at its first = into the text and the label (120@shop reaches into scene 120); a choice missing either half is dropped. The text is cookie-expanded, the label is not. A leading / shows the item ticked. Closing the menu without choosing goes on with the next line.
ASK seconds, [1]Waits for the player's next chat line and stores it in the cookie lastAsk; with 1 the answer stays out of the chat. Ask the question first: there is no prompt of its own, only the ask sound. lastAsk is emptied as the wait begins, and ASK 0 gives up at once.

Example: staging a small scene

SCENE 60, road,, "The Crossroads"
ACTOR 1, Pedlar, pedlar, 0, 85, 70
ACTOR 2, Dog, dog, 0, 90, 75
FACE 1, 0
MOVE 1, 55, 70, 2
MOVE 2, 60, 75, 3
SEL 1
' Hold up, friend! Fine goods, fair prices.
FACE 2, 2
SEL 2
' Woof.
SEL 1
MENU "See the goods=@goods", "Pet the dog=@dog", "/Ask about the road=@road", "Move on=@bye"
GOTO @bye
@goods
OFFER 12, 15, 40, 41
GOTO @again
@dog
SEL 2
POSE 3, 4
' Wuff.
POSE 0
SEL 1
' He likes you. He doesn't like many.
GOTO @again
@road
' East is the mill, west is trouble. Guess which pays better.
@again
SEL 1
MENU "See the goods=@goods", "Pet the dog=@dog", "Move on=@bye"
@bye
' Safe travels, %2.
MOVE 1, 15, 70, 2
MOVE 2, 20, 75, 3
WAIT 2
ACTOR 1, Pedlar, ""
ACTOR 2, Dog, ""
END

Both actors start on the right and walk in, the dog slightly faster. FACE 2, 2 turns the dog toward the hero. The ticked menu item (the leading /) marks the road question as the one the pedlar is itching to answer. POSE 3, 4 makes the dog cycle two frames while it speaks, then POSE 0 puts it back. At the end both actors walk off and are removed by placing them again with an empty skin, written as "".

The stage

CommandWhat it does
BKGND picture[.scale.yOffset]Changes the background, from the world's scenes/ folder and then the game's.
FX n0 none, 1 wave, 2 reflection, 3 scanlines, 4 jitter, 5 ripple.
WEATHER n0 none, 1 to 3 rain, 4 to 6 snow, 7 to 9 particles, light to heavy. For snow and particles, kind*1000 + colour picks a palette colour, so 5040 is medium snow in colour 40.
COLOR nPalette colour n (modulo 1000); the thousands digit recolours the background (2), every skin (1) or both (3).
FLAGS nAdds map flags for this scene (4 dangerous, 8 safe), read by IF F and the rules.
MUSIC file, [flags]Plays a tune; an odd flag plays it once, otherwise it loops. An empty name goes back to the link's music.
SOUND file, [mode]Plays a sound once; mode 1 loops it.
THEME nSwitches the sound theme; 0 returns to the link's.
LOCK nHost only: a non-zero n stops other players joining the scene.
HTML pageOpens a page from the world's HTML/ folder, or any http:// address, in the player's browser. The script does not wait for it.
GAME nStarts a mini-game: 1 slots, 2 monster racer, 3 search for pi, 4 blackjack, 5 pet training, 6 asteroids, 7 stock market, 8 quadris.

Example: a storm rolls in

SCENE 70, cliff,, "The Headland"
MUSIC calm.mid
N: Gulls wheel over a flat grey sea.
WAIT 3
MUSIC storm.mid
WEATHER 1
WAIT 2
WEATHER 3
FX 1
COLOR 2008
SOUND thunder.wav
N: The sky splits open.
WAIT 4
FLAGS 4
LOCK 1
HTML lighthouse.htm
N: A weathered sign reads: THE LIGHT IS OUT. KEEPER WANTED.
WAIT 6
FX 0
WEATHER 0
COLOR 0
MUSIC ""
END

Light rain becomes heavy rain, the wave effect goes on, and COLOR 2008 tints the background (the 2 in the thousands) with palette colour 8 while leaving the skins alone. FLAGS 4 marks the scene dangerous for the rest of the visit, LOCK 1 keeps other players from dropping in during the set piece, and HTML opens the world's own page without pausing the script. MUSIC "" at the end hands the music back to the link.

Example: a casino corner

SCENE 71, casino,, "The Gilded Cup"
ACTOR 1, Croupier, croupier, 0, 50, 65
' Cards or cogs? Blackjack at the table, the slot machine by the door.
MENU "Blackjack=@cards", "Slots=@slots", "Leave=@bye"
GOTO @bye
@cards
GAME 4
GOTO @bye
@slots
GAME 1
@bye
END

Gifts

GIVE and TAKE reach the host and every guest; HOST_GIVE and HOST_TAKE only the host; PARTY_GIVE and PARTY_TAKE the host's party. Each takes one code: a letter, a number and an optional .count (1 to 10000, used by I and Z).

CodeGivesTakes
G500500 gold500 gold
H20heals 20 HP (a dead hero only by 1)20 HP
L20heals 20 HP and raises the dead20 HP
M2020 MP20 MP
P100100 unspent training points, up to the class's maximum100 points
I12.3three of item 12 (a pet item hatches a pet)three of item 12
Z7.2two of trophy 7two of trophy 7
S5spell 5forgets spell 5
T9token 9token 9
J3accepts mission 3 (only while the Missions window has a selection)also accepts it

GIVE S does not check that the spell exists. After every gift the equipment totals are worked out again, and a slot the hero may no longer wear is emptied.

OFFER 12, 15, 40 opens a shop with those items; OFFER2 1, 10, 12 stocks every class-12 item of levels 1 to 10 (leave the class out for any). TOKEN 9, "The mayor's thanks" declares a token while the file loads.

Example: a healer, a shop and a one-time reward

TOKEN 12, "Sister Ada's blessing"

SCENE 80, chapel,, "The Chapel"
ACTOR 1, Ada, nun, 0, 50, 70
IF DEAD, @raise
' Rest here a while.
GIVE H50
GIVE M20
GOTO @menu
@raise
N: Warmth spreads through your limbs.
GIVE L1
' Welcome back. Try to keep it that way.
@menu
MENU "Buy bandages=@shop", "Buy a charm=@charms", "I found your locket=@locket", "Thank you=@bye"
GOTO @bye
@shop
OFFER 50, 51, 52
GOTO @menu
@charms
OFFER2 1, 20, 23
GOTO @menu
@locket
IF T12, @already
IF -I77, @noLocket
' My locket! Bless you, child.
TAKE I77
GIVE G250
GIVE S9
GIVE T12
GOTO @menu
@already
' You already returned it, and I already thanked you.
GOTO @menu
@noLocket
' Then where is it?
GOTO @menu
@bye
END

GIVE H50 cannot bring a dead hero back, so the dead go through GIVE L1 instead. The locket branch is guarded twice: token 12 stops the reward repeating, and -I77 catches a hero who picked the menu item without the locket. The reward hands over gold, teaches spell 9 and grants the token that locks the branch for good. OFFER2 1, 20, 23 stocks every class-23 item of levels 1 to 20 without naming them one by one.

Fights

FIGHT 40, 41 starts a fight with monsters 40 and 41; FIGHT -40 adds monster 40 on the heroes' side; FIGHT +40 adds one that hunts the allies; FIGHT * draws a random group from the link; a bare FIGHT fights the link's usual encounter and FIGHT 0 clears the stage. Each monster may carry a position: 40.60.70.1 is monster 40 at 60 percent across, 70 down, facing left. Afterwards test IF WON, IF LOST, IF ALIVE or IF DEAD.

Example: an ambush with an ally

SCENE 90, forest,, "The Hollow Way"
ACTOR 1, Ranger, ranger, 0, 40, 70
' Quiet. Something's in the trees.
WAIT 2
SOUND growl.wav
' Wolves! Stand with me!
FIGHT 40.70.60.1, 40.80.75.1, -45
IF LOST, @lost
IF DEAD, @dead
' That's the last of them. You fight well for a %C.
GIVE Z7.2
IF R25, @bonus
END
@bonus
' Here. I found this on the big one.
GIVE I23
END
@dead
N: Everything goes dark.
END
@lost
' Run! I'll hold them!
GOTO EXIT
EXIT
N: You stumble out of the hollow, bleeding.
TAKE G50

Two wolves (monster 40) come in on the right, facing left, and the ranger's friend, monster 45, fights on the heroes' side because of the minus sign. After the fight the script checks the bad outcomes first, since WON is also true when no fight happened. Winning pays two wolf pelts (trophy 7) and a one-in-four chance of an extra item. Losing leaves through GOTO EXIT, which puts the hero on the map and then carries on from the line that begins EXIT.

Cookies and arithmetic

Commands that write a cookie take its name first, without the #<>; values are expanded, so write #<x> there.

CommandWhat it does
SET name, valueStores the value. SET name alone empties it.
ADD, SUB, MUL, DIV, MOD (or MODULUS) name, valueWhole-number arithmetic on the cookie; the result is also the compare result. Dividing by zero changes nothing.
F_ADD, F_SUB, F_MUL, F_DIV, F_MODThe same with decimals.
AND, OR, NOT, XORBitwise. Two quirks are kept from the original: NOT stores the complement of the value, and XOR always stores 0.
COMPARE a, bCompare result = a minus b.
F_COMPARE a, bDecimal compare giving only -1 or 0, so IF> never fires after it.
STRCMP a, b / STRSTR text, part0 when equal (ignoring case) / 1 when part occurs in text.
SET_LEN name, textStores the length of the text.
SET_SUBSTR name, start, count, textStores count characters from start (0 is the first). A negative start or count reads as 0, a start past the end is pulled back to the last character, and a count past the end is cut to what is left.
STRLWR name, textStores the text in lower case. The text is expanded first, % codes included, then lowered.
NTH_TOKEN name, n, text, [separator], [clip]Stores the n-th piece of the text, split on the first character of the separator (a comma unless given). An n of 0 or less gives the first piece; a piece that is not there stores nothing; a clip other than 0 strips the piece's leading spaces.
SHUFFLE base, nDeals 0 to n-1 in random order into base0 ... and sets baseCount. n runs from 1 to 255; outside that the cards are left alone and baseCount is 0.

Example: a counter that remembers

SCENE 100, inn,, "The Lamplighter"
ACTOR 1, Innkeeper, innkeeper, 0, 50, 70
ADD visits, 1
COMPARE #<visits>, 1
IF=, @first
COMPARE #<visits>, 5
IF>=, @regular
' Back again, %2. That's visit number #<visits>.
END
@first
' A new face. Welcome to the Lamplighter.
END
@regular
' The usual, %2? On the house tonight.
GIVE H999
END

visits is the world's own cookie: it starts empty, which ADD reads as 0, and it is saved in the hero's file, so the count carries over between sessions. ADD also sets the compare result, so a script that only needs to know whether the new value is above zero can jump straight to IF> without a COMPARE.

Example: a password, checked three ways

' The password?
ASK 20, 1
STRCMP #<lastAsk>, swordfish
IF=, @inside
SET_LEN n, #<lastAsk>
COMPARE #<n>, 0
IF=, @silent
STRSTR #<lastAsk>, fish
IF<>, @warm
' Wrong.
END
@warm
' Close. Something to do with fish.
END
@silent
' Cat got your tongue?
END
@inside
' In you go.
GOTO LINK 4, 2, 1

The 1 on ASK keeps the answer out of the public chat. STRCMP gives 0 for a match in any case, so IF= is the test for equality. An unanswered ASK leaves lastAsk empty, which the length check catches. STRSTR gives 1 when the part is found and 0 when it is not, so the jump after it is IF<> (or IF>) for found and IF= for not found.

Example: dealing names and doing sums

SET names, "Ash,Birch,Cedar"
SHUFFLE pick, 3
NTH_TOKEN first, #<pick0>, #<names>
NTH_TOKEN second, #<pick1>, #<names>
' Today's guards are #<first> and #<second>.
SET price, 40
MUL price, #<num.hostLevel>
DIV price, 2
' For a %L the fee is #<price> gold.
SET ratio, #<num.hostHP>
F_DIV ratio, #<num.hostMaxHP>
F_MUL ratio, 100
' You are at #<ratio> percent health.

SHUFFLE pick, 3 fills pick0, pick1 and pick2 with 0, 1 and 2 in a random order, and NTH_TOKEN counts pieces from 0, so it picks the matching name from the comma list. The whole-number commands round down, so the fee for a level 7 hero is 140. The decimal commands read whatever text is in the cookie, so a plain SET starts the ratio off.

Timing, parties and the server

CommandWhat it does
COUNTDOWN secondsStarts the countdown that IF XP tests. A negative value is read as a huge one and runs for about 49 days.
TIMER n, secondsAfter the time, jumps to @eventTimer<n> (n from 0 to 9; a larger n is ignored, a negative n clears every timer). Zero seconds leaves the timer idle; a negative time arms one that never fires.
PARTY conditionThe host sends a condition to its guests; a guest that fails it leaves the party.
EJECT conditionThe same, and the guest leaves the scene too.
GET_SERVER_VAR cookie, section, keyFetches a value kept on the server into a cookie (waits up to ten seconds).
SET_SERVER_VAR section, key, valueStores a value on the server. Neither works on a modified world.
MISSIONS 3, 4 (or MISSION)Offers missions 3 and 4 in this scene. See Missions.

Example: a flooding cellar

SCENE 110, cellar,, "The Flooding Cellar"
ACTOR 1, Guard, guard, 0, 20, 70
' The sluice is stuck. You have about a minute before this room is under water.
COUNTDOWN 60
TIMER 1, 20
TIMER 2, 45
@choose
MENU "Pull the lever=@lever", "Search the shelves=@shelves", "Climb out=@out"
GOTO @out
@lever
IF XP, @drowned
IF R50, @stuck
' It gives! The water drains away.
TIMER -1, 0
GIVE Z11.1
END
@stuck
' It won't budge. Try again, or get out.
GOTO @choose
@shelves
IF XP, @drowned
' Jars, rope, a rusted key.
GIVE I64
GOTO @choose
@out
TIMER -1, 0
' Leave it, then. The cellar's lost.
GOTO EXIT
@drowned
N: The water closes over your head.
TAKE H999
END

@eventTimer1
SEL 1
' It's up to your knees!
END
@eventTimer2
SEL 1
' Waist deep! Get out!
END

COUNTDOWN 60 starts the clock that IF XP reads, and the two timers interrupt whatever the player is doing at twenty and forty-five seconds with a shout from the guard: their labels run as events, so they fire even while a menu is open. TIMER -1, 0 cancels every timer once the room is saved or abandoned. Each branch that takes time re-checks XP first, so a player who dithered past the minute drowns rather than wins.

Example: a party gate and a high score

SCENE 120, arena,, "The Pit"
EJECT V10
N: Level ten and up only. Anyone weaker has been shown the door.
PARTY -M0
GET_SERVER_VAR best, pit, record
N: The record stands at #<best> rounds.
SET rounds, 0
@round
ADD rounds, 1
FIGHT *
IF LOST, @done
IF R70, @round
@done
COMPARE #<rounds>, #<best>
IF<=, @noRecord
SET_SERVER_VAR pit, record, #<rounds>
SET_SERVER_VAR pit, holder, #<str.name>
N: A new record: #<rounds> rounds!
END
@noRecord
N: #<rounds> rounds. The record stands.
END

EJECT V10 throws guests below level 10 out of the scene; PARTY -M0 drops marked cheaters from the party but lets them watch. The server keeps the record under section pit, so every player on that server competes for it. A world that is being modified locally gets nothing back from the server, and best stays empty, which the compare reads as zero.

A complete scene

Everything above in one small story: a herbalist who sends the hero after a plant, counts the kills on the way, and pays once. Token 20 marks the job accepted and token 21 marks it done. The moss is handed over by giving it to her, the way gifts to actors work, so the finish lives in the gift label.

TOKEN 20, "Mara's errand"
TOKEN 21, "Mara's thanks"

SCENE 10, village,, "The Square"
ACTOR 1, Mara, herbalist, 0, 30, 70
IF T21, @afterwards
IF T20, @checkErrand
' You look like someone who walks the marsh road, %2.
MENU "What of it?=@ask", "Not today=@bye"
GOTO @bye
@ask
' I need marshlight, the glowing moss. Three sprigs. The bog hounds guard it.
' Hand them to me one at a time and I will teach you something worth knowing.
MENU "I'll do it=@accept", "Find someone else=@bye"
GOTO @bye
@accept
GIVE T20
SET mossGiven, 0
SET houndsBefore, #<KM.44>
' South, past the mill. Mind the hounds.
GOTO @bye
@checkErrand
SET hounds, #<KM.44>
SUB hounds, #<houndsBefore>
COMPARE #<hounds>, 0
IF>, @someHounds
' No moss yet? The marsh is south, past the mill. Hand me what you find.
GOTO @bye
@someHounds
' #<hounds> hounds already, and #<mossGiven> sprigs so far. I need three.
GOTO @bye
@afterwards
' Good to see you, %2. Hurt?
IF DEAD, @raise
GIVE H100
GOTO @bye
@raise
GIVE L100
@bye
END

@eventActorGive1
IF -T20, @notNow
COMPARE #<item.id>, 88
IF<>, @wrongGift
ADD mossGiven, 1
COMPARE #<mossGiven>, 3
IF>=, @finish
' That's #<mossGiven>. I need three.
END
@finish
TAKE T20
GIVE T21
SET mossGiven
SOUND fanfare.wav
' Marshlight! You have my thanks, and this.
GIVE S14
GIVE G200
' Come back when you are hurt. My door is open to you now.
END
@wrongGift
' I asked for marshlight, not that.
END
@notNow
' I have not asked you for anything.
END

SCENE 11, marsh,, "The Marsh"
IF -T20, @wander
IF R40, @hounds
N: Faint green light pulses between the reeds.
GIVE I88
END
@hounds
N: Something splashes toward you through the reeds.
FIGHT 44, 44.80.70.1
IF WON, @loot
END
@loot
IF R60, @nothing
N: A sprig of marshlight glows where the hound fell.
GIVE I88
END
@nothing
N: Only mud.
END
@wander
N: Reeds, mud and the smell of rot. Nothing here calls to you.
END

Reading it top to bottom: the first visit offers the job; accepting it grants token 20, zeroes the moss count and notes the hero's kills of the bog hound, monster 44, so later visits can say how many have fallen since. The marsh scene only yields moss while the job is open, sometimes guarded by a fight. Every sprig the player gives Mara runs the gift label: the wrong item or a gift before the job is refused in words, and the third sprig finishes the job. The errand token goes, the thanks token arrives, and spell 14 and the gold are paid exactly once, because every later visit goes to @afterwards. The dead are raised there with L, since H cannot.

Where ReBreather differs

  • GOTO EXIT with no EXIT line stops the script instead of restarting it.
  • IF R and SHUFFLE use the game's own random numbers, so a sequence that was reproducible in the original is not reproducible here.
  • HTML opens the system browser and the script goes on at once instead of waiting.
  • Expanded text has no length limit; the original quietly dropped an expansion that would not fit.
  • A few command words that early ReBreather builds did not know (BKGND, COLOR, FX, COUNTDOWN, LOCK) are all handled now.
  • The version cookie answers under both names: num.engineVersion and the original's num.wosVersion both give 2817.
  • num.isTactics is always 0.