Effect tokens#
Effect tokens are the verbs you chain in interactions, puzzle rules and cutscenes to
change the game — set a flag, grant an item, move an NPC, toggle a walkable area. Each
token is written as VERB:arg1|arg2 (or a bare VERB when it takes no argument), and the
editors autowire the arguments for you.
| Token | What it does | Arguments |
|---|---|---|
SETFLAG |
Remembers that something happened (flips a switch on). | Flag |
CLEARFLAG |
Forgets that something happened (flips a switch off). | Flag |
TOGGLEFLAG |
Flips a remembered switch to its opposite. | Flag |
SETVAL |
Stores a value like a password or number (blank clears it). | Flag, Value (blank = clear) |
APPENDVAL |
Adds a chunk onto a stored value, like a keypad digit. | Flag, Append, Max length (blank = no cap) |
ADDVAL |
Adds to a counter (use a minus to subtract). | Flag, Amount (+/-) |
RANDVAL |
Rolls a random number and stores it, like dice. | Flag, Min, Max |
BACKSPACEVAL |
Deletes the last character of a stored value. | Flag |
CATCHTARGET |
Picks which of your characters a chaser catches. | Antagonist NPC, Candidate chars, Mode, Out flag (def caughtChar) |
PARTYTOGGLE |
Adds or removes a character from your chosen team. | Character |
PICKUP |
Takes an object from the scene into your inventory. | Hotspot to remove, Item to grant (blank = same id) |
REMOVEITEM |
Removes an item from your inventory. | Item |
GIVEITEM |
Hands an item to a specific character. | Item, Target character |
RESTOREHOTSPOT |
Brings a removed object back into the scene. | Hotspot id |
WALKABLE_ON |
Opens up a walkable path in a room. | Walkable area |
WALKABLE_OFF |
Blocks off a walkable path in a room. | Walkable area |
REGION_ON |
Turns on a walk-over trigger zone. | Region |
REGION_OFF |
Turns off a walk-over trigger zone. | Region |
LIGHTZONE_ON |
Switches a light zone on, lighting or tinting whoever stands in it. | Light zone |
LIGHTZONE_OFF |
Switches a light zone off, leaving the area unlit. | Light zone |
NPCEXIT |
Sends a character walking off to another room. | NPC, Dest room, Walk-to |
NPCWALKTO |
Walks a character to a spot and has them wait there. | NPC, Destination, Facing (opt), Speed (dur=ms | speed=px/s), Options |
NPCRETURN |
Brings a character back from another room. | NPC, Dest room |
NPCWARPTOROOM |
Instantly places a character in a room. | NPC, Room, At, Facing (opt) |
FOLLOW |
Makes a character trail after another one. | NPC, Target, Stop distance px (opt) |
UNFOLLOW |
Stops a character from following. | NPC |
DETACHCOMPANION |
Parks a companion so it stops tagging along. | Companion |
ATTACHCOMPANION |
Brings a companion back to tag along with you. | Companion |
NPCSTOP |
Stops a character in its tracks. | NPC |
NPCWAIT |
Makes a character pause for a few seconds. | NPC, Seconds |
BEHAVIOUR |
Starts a character's daily routine of wandering about. | Behaviour |
STOPBEHAVIOUR |
Stops a character's wandering routine. | NPC |
STARTTIMER |
Starts a countdown you can react to. | Timer name, Seconds |
CLEARTIMER |
Cancels a running countdown. | Timer name |
CLEARWATCHER |
Lets a one-time rule fire again. | Watcher id |
SELECTVERB |
Pre-selects one of the nine verbs, like Use. | Verb |
SETCURSOR |
Takes over the mouse cursor — which cursor, frame or position, even visible during a cutscene. | Cursor overrides |
INVENTORY_UP |
Scrolls the inventory bar up a row. | (none — bare token) |
INVENTORY_DOWN |
Scrolls the inventory bar down a row. | (none — bare token) |
SETSENTENCE |
Pins your own text onto the action line at the bottom (the 'Walk to…' bar). | Sentence (#lid | text, {flag}) |
CLEARSENTENCE |
Clears a pinned action-line text, back to normal. | (none — bare token) |
SAY |
Makes your character or narrator speak a line. | Text ({flag}) |
NPCSAY |
Makes a specific character speak a line. | NPC, Text ({flag}) |
NARRATE |
Shows a narrator caption, not tied to any character. | Narrator text ({flag}) |
CLEARNARRATE |
Removes the narrator caption early. | (none — bare token) |
SETFRAME |
Swaps an object's picture for a different one. | Sprite path, Display text (opt) |
SETANIMFRAME |
Jumps an animation to a specific frame. | Frame index, Options |
STARTANIM |
Plays or resumes an animation on a character or object. | Target, Animation (opt), Facing (opt) |
STOPANIM |
Stops a character or object mid-animation, settling to a still pose. | Target, Animation (opt), Facing (opt) |
SHOWHOTSPOT |
Makes an object appear in the scene. | Hotspot id |
HIDEHOTSPOT |
Makes an object vanish from the scene. | Hotspot id |
ENABLEHOTSPOT |
Makes an object clickable again. | Hotspot id |
DISABLEHOTSPOT |
Makes an object stop responding to clicks. | Hotspot id |
TOGGLELIGHT |
Turns the room's light on or off. | Options (dur=ms) |
FADEOUT |
Fades an object out until it vanishes, with an optional caption. | Caption |
MOVEHOTSPOT |
Slides an object to a new spot in the scene. | Hotspot, Destination, Speed (dur=ms | speed=px/s), Options |
SETHOTSPOTMOTION |
Animates an object's scale, rotation and opacity — each loopable (pulse, spin, fade). | Hotspot, Motion channels |
SETHOTSPOTFX |
Restyles an object's sprite at runtime — shadow, glow, blur, opacity or outline. | Hotspot, FX overrides |
MOVEGUI |
Slides an on-screen panel element to a new spot. | GUI widget (gui.widget), Destination, Speed (dur=ms | speed=px/s), Options |
MODIFYWIDGET |
Restyles a panel element at runtime — colour, border or text. | GUI widget (gui.widget), Overrides |
DIALOG |
Starts a branching conversation. | Dialog id |
CUTSCENE |
Plays a scripted sequence inside the room. | Cutscene |
WARPTOROOM |
Moves the player to another room. | Room id |
WALKTO |
Walks your active character to a spot in the room. | Destination, Facing (opt), Speed (dur=ms | speed=px/s), Options |
HIDEPLAYER |
Takes the player's sprite off screen; they keep walking and taking clicks. | (none — bare token) |
SHOWPLAYER |
Brings the player's sprite back on screen. | (none — bare token) |
OPENGUI |
Opens an on-screen panel. | GUI id, Options |
CLOSEGUI |
Closes the open on-screen panel — or only the one you name. | GUI id (opt) |
OPENCOIN |
Pops the verb coin on a hotspot. | hotspot id |
CLOSECOIN |
Dismisses the verb coin. | (none — bare token) |
HIDEGUI |
Hides all on-screen panels from view. | (none — bare token) |
SHOWGUI |
Brings the on-screen panels back into view. | (none — bare token) |
SETLANG |
Switches the game's language. | Language |
SWITCHCHAR |
Switches which character you control. | Target character |
SWITCHPARTYSLOT |
Switches control to the team member in a slot. | Party slot (1-based) |
SAVEGAME |
Saves the game to a slot. | Slot (0-5) |
LOADGAME |
Loads the game from a slot. | Slot (0-5) |
SOUND |
Plays a one-off sound effect. | Sound id |
STOPSOUND |
Stops a sound effect that is still playing — the way to end one set to loop. | Sound id |
VOICE |
Plays a spoken voice line with subtitle. | Voice line |
MUSIC |
Changes the background music. | Music id |
STOPMUSIC |
Fades out the background music. | (none — bare token) |
AMBIENCE |
Starts a looping background sound, like a fan. | Ambient id |
STOPAMBIENCE |
Stops a looping background sound. | Ambient id |
TOGGLEHOTSPOTAUDIO |
Flips an object's looping sound, like a radio. | Hotspot id |
SETHOTSPOTOPEN |
Sets a door or container to open or closed. | Open state |
PLAYSCENE |
Plays a full-screen cinematic clip. | Scene |
REWINDSCENE |
Plays a cinematic clip backwards, like a rewind. | Scene (|speed=N) |
PLAYARCADE |
Launches a mini-game to play. | Arcade stage |
PLAYFX |
Plays a visual effect, like a flash or shake. | FX name, Params (key=val|…) |
ADJUST |
Applies a full-screen mood filter, like night or sepia. | Screen FX preset, Pixelate params |
TOGGLEROOMFX |
Flips a room surface effect, like a reflection. | Room FX type |
UNLOCK |
Grants the player an achievement. | Achievement |
NEXTCHAPTER |
Moves the story on to the next chapter. | (none — bare token) |
NEXTBLOCK |
Moves the story on to the next part. | (none — bare token) |
GOTOBLOCK |
Jumps the story to any part you choose — back to the beginning, or on to a bonus screen. | Block |
RESETGAME |
Wipes the current playthrough so the next one starts clean. Achievements are kept. | (none — bare token) |
WAIT |
Holds the rest of the chain for a few seconds, so a line has time to be read. | Seconds |
PARTYCOMMIT |
Confirms your chosen team and moves on. | (none — bare token) |
WAITFOR |
Holds the rest of the chain until the line on screen has finished, with no seconds to guess. | Event |
QUITGAME |
Quits the game, the right way for each platform (closes the window or app). | (none — bare token) |
SHOWTEXT |
Shows free-floating text anywhere on screen. | Pos, Color, Size px, Font, Dur seg (0=fijo), Id (opt), Text ({flag}) |
CLEARTEXT |
Removes on-screen text you showed earlier. | Id (blank=all) |
Notes#
- Token IDs are literal and always English (
SETFLAG,GIVEITEM…), even when the editor UI is in Spanish — renaming them would break every saved rule. GIVEITEM:<item>|<character>is the only token that moves an item between playable characters.- A few tokens take no argument and serialize as a bare verb (e.g.
INVENTORY_UP). - Most arguments are required, and leaving one blank is an authoring bug the engine
can't warn you about:
SETFLAG:with no name sets the empty flag, which no condition can ever read back. The Puzzle Editor's Validate now catches exactly that and blocks Save. Some arguments are optional by design and may be left blank — aPICKUPwith no item grants the hotspot's own id,CLEARTEXTwith no id clears every overlay,SETVALwith no value clears the buffer, and the trailingspeed/options/ volume-pan parts of a token can all be omitted.
Gating a path, a trigger or a light with a puzzle#
Three token pairs — WALKABLE_ON/WALKABLE_OFF, REGION_ON/REGION_OFF and
LIGHTZONE_ON/LIGHTZONE_OFF — flip a room's walkable areas, walk-over regions and light
zones on and off at runtime, so a puzzle can open a path, arm a trigger, or switch on a lamp.
All three share the same shape: TOKEN:<id> targets that entity in the current room, and
TOKEN:<id>|<roomId> reaches into another room — a lever in one room opening a path, arming
a trigger, or switching a light somewhere else entirely.
WALKABLE_ON/WALKABLE_OFFenable or disable a walkable area — a floor a character can actually stand on — the way a secret passage stays closed until a switch is thrown.REGION_ON/REGION_OFFenable or disable a walk-over region — a trigger a puzzle needs armed or disarmed, so a trap doesn't fire before its cutscene, or an intro beat doesn't refire once it's already played.LIGHTZONE_ON/LIGHTZONE_OFFswitch a light zone on or off — a lamp, a spotlight, a tinted area. It's visual only: light zones are deliberately decoupled from walkable areas, so switching one off never moves the floor, and switching a walkable area off never dims a light.
All three are overrides, not one-shot toggles: the state is remembered per room, takes priority over whatever the room author set as the default, and is re-applied every time the player re-enters that room — so a path a puzzle opened, a trigger it armed, or a lamp it switched off stays exactly as the player left it across a room change, and survives save/load.
Read the state back with the matching predicate — isWalkableOn, isRegionOn and
isLightZoneOn — in a puzzle rule's condition; see the full predicate list on the
Puzzle Editor page.
Turning the room's lights on and off#
TOGGLELIGHT flips the whole room between lit and dark — the light switch by the door,
the fuse the player pulls. It is the room-wide darkness veil, so it is a different thing from
LIGHTZONE_ON/LIGHTZONE_OFF, which turn one lamp's glow on or off inside a room.
How dark the room gets is the room's own Darkness when unlit setting. How fast it gets
there is Fade duration, the fader right beneath it — set it to 0 and the light snaps
instantly, the way a real switch does. That is the setting to reach for first: you author it
once and every light switch in that room obeys it.
When one particular switch needs to behave differently — a lamp that fades slowly while every other switch in the room snaps — give the token a duration of its own:
TOGGLELIGHT:dur=0 instant, whatever the room says
TOGGLELIGHT:dur=1500 a slow one-and-a-half-second fade
TOGGLELIGHT no opinion — use the room's fader
Leave the field blank and the room decides, which is what you want almost every time.
Walking a character to a point#
Two tokens walk a character to a spot on the floor from any rule, reaction or watcher —
without opening a cutscene. WALKTO:<x>|<y> walks the active player;
NPCWALKTO:<character>|<x>|<y> walks a named character and leaves them standing there.
Both ride the same click-to-walk pathfinding the player uses, so the character routes around
obstacles and stops the same way a normal click would.
Both share the same optional tail, and its parts can appear in any order:
- facing — a direction (
up/down/left/right) applied once the character arrives; while walking, the character faces the way it's moving. - speed — either
speed=<pixels-per-second>ordur=<milliseconds>for the trip; it's a temporary override, and the character's normal speed is restored on arrival. - block — add
block(orblock=true) to freeze the game until the character arrives, the way a cutscene step waits. Without it the walk is fire-and-forget: the game stays interactive and a player click can re-target the active character mid-walk.
For example, WALKTO:120|340|left|block walks the player to (120, 340), holds input until they
get there, and turns them to face left on arrival.
Pausing between tokens#
Every token in a chain fires in the same instant, which is usually what you want — but not when
one of them needs a moment to be seen. A spoken line is the clearest case: SAY puts the line
on screen and immediately hands over to the next token, so SAY followed by a token that changes
the scene means the line never gets read.
WAIT:<seconds> holds the rest of the chain, then carries on where it left off. Put one
between the line and the jump — SAY:…, WAIT:2, GOTOBLOCK:credits — and the line gets its
two seconds before the game moves on.
WAITFOR:say does the same job without you naming a number: it holds the chain until the
line currently on screen is gone, whoever is speaking — the player, an NPC, or the narrator.
Write SAY:…, WAITFOR:say, GOTOBLOCK:credits and the jump lands the moment the bubble does,
even if you later rewrite the line, or record a voice clip for it and let the subtitle stretch to
the audio. Reach for it whenever the number you'd type into WAIT is really just "however long
that line takes". With nothing being said it simply moves on.
The game holds still while it waits: input is locked, the same way it is during a cutscene, and the player can't skip it — so keep waits short and deliberate. Pausing still works, and a paused wait stops counting down until the player unpauses.
Where it works: anywhere you chain tokens in live play — hotspot and character reactions, item interactions, panel buttons, dialogue choices, room-entry events and walk-over regions. Scene timelines take neither of them, and the scene editor won't offer them: a scene is already a timeline, so you space its beats by moving them, not with a token. Cutscenes have their own Wait step that does the same job. Single waits are capped at 60 seconds, and the game refuses to save while one is running.
Taking the player off screen#
Sometimes the character has to leave without going anywhere — walking into a portal before the credits roll, stepping out of frame so a scene can play on an empty room, or simply not being in a shot they'd spoil.
HIDEPLAYER takes the player's sprite off screen, and SHOWPLAYER brings it back. Both
are bare tokens — no argument. The portal beat reads exactly the way you'd say it out loud:
WALKTO:588|816|up|block, HIDEPLAYER, WAIT:1, PLAYSCENE:credits.
Two things worth knowing before you reach for it:
- It only hides — it doesn't switch the character off. A hidden player still walks, still
collides, still takes clicks. If you want them to stop moving too, say so with the tokens that
already do that (
WALKTOwithblock, or a cutscene). The one thing that does follow the sprite is its shadow and its reflection in a puddle or mirror — those go with it, and a spoken line stops drawing a bubble rather than dangling one off an invisible head. For a voice with nobody on screen, useNARRATE. - It's remembered. The hidden state goes into the save, so a player who quits mid-puzzle and comes back finds the room exactly as they left it. Starting a new game always brings the player back, so you can't strand anyone invisible.
Showing a panel — or the verb coin — from a cutscene#
A cutscene hides the HUD, but a panel the cutscene itself opens is meant to be seen:
OPENGUI:<gui> in a cutscene step paints and animates its modal over the room. It's a
showcase — the cutscene keeps the input, so a click still advances the line rather than
pressing a button. Follow it with a WAIT and then a close, and a guided tour can show the
inventory or a keypad instead of only talking about it.
CLOSEGUI takes an optional target. Bare, it closes whatever modal is open — what every
close button does. CLOSEGUI:<gui> closes it only when that one is actually on screen, so a
cutscene can tidy up its own panel without snatching away a menu the player opened meanwhile.
The pop-up verb coin can't be addressed by id (it's built fresh at each click, wherever you
clicked), so it has its own pair. OPENCOIN:<hotspot> pops the real coin centred on that
hotspot's artwork — not on the floor point you'd walk to — and CLOSECOIN dismisses it.
Inside a cutscene it's a showcase like any panel; outside one the coin stays armed, and picking a
verb runs the ordinary action on that hotspot.
Restyling a panel element on the fly#
MODIFYWIDGET:<gui>.<widget> overrides a single GUI widget's look at runtime — its
background colour and opacity, its border (width and colour), or its text — without touching the
authored GUI. Like the other panel tokens it's a draw-time overlay, so the GUI's own descriptor
and layout are never mutated; but unlike a one-off visual effect it's durable: the override
rides save/load, so a colour or text change can stand in for remembered state (a lever panel
that turns green once you've pulled it). The tail is order-free key=value pairs, every one
optional, and firing the token again merges into the same override rather than replacing it.
reset=true clears the override and restores the widget's authored look. The text override
takes priority over a label's other text sources and accepts either a literal or a #lid (a
string-table entry, so it still localizes).
The target isn't limited to your own panels. The game's main HUD bar and the pop-up verb coin
are regular GUIs underneath, so MODIFYWIDGET:mainBar.verb-look|bg=#a00 tints a verb button
and MODIFYWIDGET:verbCoin.coin-talk|text=Shout relabels a coin cell — the editors suggest
both under their real ids (mainBar.*, verbCoin.*), engine defaults included when the
project hasn't authored its own. The coin is rebuilt fresh at every click, but the override
re-applies each time it opens; like every widget override these are durable, ride save/load,
and reset=true returns the widget to the game's configured default look. One caveat: a
button drawn with sprite artwork ignores the background, border and text overrides — they
apply to text-label buttons (the classic nine-verb bar and the default coin are all text).
Once a panel has been dressed up by a handful of these, putting it back one reset=true per
widget gets tedious — so leave the widget off and the reset covers the whole panel:
MODIFYWIDGET:<gui>|reset=true drops every override belonging to that GUI at once. The same
thing is available at the moment a panel opens, as OPENGUI:<gui>|reset=true, for the common
"this screen should always come up clean" case. Both are opt-in on purpose: because widget
overrides are durable and can stand in for remembered state, a plain OPENGUI never clears
them — otherwise a panel that remembers something would forget it every time it was opened.
Restyling a hotspot's sprite on the fly#
SETHOTSPOTFX:<hotspot> is the same idea aimed at the room: it overrides a sprite
hotspot's visual FX — shadow, glow, blur, opacity, and silhouette stroke — on top of whatever
the room editor authored, without touching the room file. The tail is order-free key=value
pairs (glowsize=8|glowcolor=#f0a03c, blur=3, opacity=0.5, strokew=2|strokecolor=#fff),
every one optional; firing the token again merges into the same override, and it's
durable across save/load — an amulet that keeps its glow once activated, a portrait that
stays faded after the séance. reset=true restores the authored look.
The shadow keys pick between the two shadow styles from the room editor's Sprite FX panel:
shadow=basic with shdx/shdy/shblur/shcolor/shalpha for a simple drop shadow, or
shadow=cast with shangle/shlen/shsoft/shalpha for the real silhouette shadow that
characters cast — leave the cast numbers out and it inherits the room's lighting, so the
hotspot's shadow points the same way everyone else's does. shadow=off kills the shadow
entirely, authored one included. Zero sizes switch an effect off (glowsize=0, strokew=0,
blur=0), matching the editor's "0 = off" knobs. Only hotspots with a sprite take FX —
there is nothing to outline or glow on a bare polygon.
Animating a hotspot, not just a character#
The Animations group holds the three tokens that drive playback, and all of them are
polymorphic: the same verb aims at a character or at a hotspot's object animation, so
there is one STOPANIM to remember rather than one per kind of thing.
STARTANIM:<target> resumes whatever the target was playing and STOPANIM:<target>
freezes it in place — no frame jump, which is the ergonomic SETANIMFRAME doesn't have. Aimed
at a character, STARTANIM also takes an optional clip and facing (STARTANIM:bernard|talk|left)
to hold a pose. Aimed at a hotspot, the optional clip swaps which animation the prop plays:
STARTANIM:grandfatherclock|clock_chime moves the clock from its tick loop to its chime, and
a later STARTANIM:grandfatherclock with no clip puts it back on whatever the room authored.
Facing is character-only — a prop has no facing, and the editor hides the field once you pick
a hotspot.
The clip picker follows your target: choose a character and it offers that character's clips
by their short name (talk, blink); choose a hotspot and it offers the project's object and
room animations by their full name (grandfatherclock_ticktock). Name a clip that doesn't
exist and the prop falls back to its authored animation rather than freezing — a frozen prop
looks exactly like a token that did nothing.
The swap is runtime-only: it is forgotten when the player leaves the room, and it isn't saved. The room file stays the source of truth for what a hotspot plays by default.
Pulsing, spinning and fading a prop — without the animations editor#
A baked FX clip usually already loops cleanly from frame 0. Making it also grow as it opens, pulse while it waits, or fade in and out used to mean baking more clips — but none of that is animation at all: a ramp is a curve.
SETHOTSPOTMOTION:<hotspot>|key=value|… animates three channels of a hotspot's sprite at
runtime — scale (sc* keys), rotation (rot*, degrees about the sprite centre) and
opacity (op*, 0–1) — each with its own ramp, easing and loop mode. The tail is
order-free and every key is optional; a token replaces only the channels it names, so a scale
pulse keeps running while a later token retunes the opacity.
SETHOTSPOTMOTION:chest|scfrom=1|scto=1.15|scdur=400|scease=inOutQuad|scloop=pingpong
SETHOTSPOTMOTION:fan|rotspeed=180
SETHOTSPOTMOTION:ghost|opfrom=0.4|opto=1|opdur=900|oploop=pingpong
Each channel takes the same key family, prefixed sc / rot / op:
Xfrom=/Xto=— the ramp's endpoints. LeaveXfromblank and the ramp picks up from wherever the channel already is, so two tokens in a row chain smoothly; type it and the sprite snaps there first — the pop-in shape (scfrom=0.2|scto=1).Xfromalone with noXtois an instant set.Xloop=loop|pingpong— leave it out for a one-shot that runs once and freezes at the target.loopcuts hard back to the start each cycle;pingpongplays the ramp forward and then mirrored backward, which is what makes a pulse decelerate at both extremes — useinOutQuadfor pulses.Xdur=<ms>,Xspeed=<units/s>, and (scale only)scframes=<n>— how long a leg takes.framescounts real per-frame timing of the clip the hotspot is playing at that moment, so re-timing the animation keeps the ramp in step.durwins overframeswins overspeed.Xease=<curve>— the same curve listMOVEHOTSPOTuses.outBackovershoots slightly before settling, which is what makes a portal read as opening rather than inflating.Xstop=true— kill that channel, freezing its value in place (exactly what a finished one-shot leaves behind). To ease back to rest, send a one-shot instead:scto=1|scdur=300.origin=bottom— keep the sprite's foot planted while it scales. The default scales about the anchor, which is right for anything airborne and wrong for anything standing on the floor, which would appear to sink and then rise.reset=true— all three channels off and back to rest (scale 1, rotation 0, opacity 1).
Two of the channels have a special trick. rotspeed= with no rotto= spins forever at
that rate in degrees per second — the way to make a fan or a windmill turn in place. And the
opacity channel multiplies the durable SETHOTSPOTFX opacity rather than replacing it: FX
opacity is the prop's base look ("this ghost is 50% translucent"), motion opacity is an animated
modulation on top, and when the channel resets the base look returns untouched.
A scale of 1 is the sprite's authored size and 0 is legal — it means "not there yet", which
is the natural starting point of a pop-in.
Two things worth knowing. The scale is uniform: for a permanent non-uniform flatten there is
the room editor's Sprite distort panel, which is authored rather than animated. And the hotspot's
polygon does not scale — a portal drawn at 20% is still clickable across its whole authored
polygon, the same generosity that already applies to a rotated sprite. Like MOVEHOTSPOT, the
motion is runtime-only: it is forgotten on room change and is not saved. For a pulse that should
survive re-entry, re-fire the token from a room-enter rule.
Taking over the cursor#
SETCURSOR overrides the mouse cursor itself — which cursor (and with it, which
animation) is drawn, which frame it's frozen on, where it sits, and whether it shows at all.
The tail is order-free key=value pairs, every one optional; firing the token again
merges into the same override, and reset=true restores normal cursor behaviour. Unlike
its two sibling overrides above, this one is deliberately not saved: a forced cursor is
presentation, not puzzle state — and it clears itself the moment a cutscene ends or is
skipped.
cursor=<id>forces a cursor from the project's cursor set — it beats the armed inventory item, the selected verb and any hover override.frame=<n>freezes an animated cursor on one frame; leave it out and the animation plays normally.x=<px>|y=<px>pins the cursor to a canvas position (send both); without them it keeps following the real mouse.visible=showkeeps the cursor drawn during a cutscene, where it's normally hidden. Input stays locked — the player can't click anything — so the cursor is purely yours to drive from the cutscene's own tokens: a tutorial "ghost hand" showing where to click, an eye tracking the scene.visible=hideis the mirror image: it hides the sprite cursor outside cutscenes.
A cutscene beat: SETCURSOR:cursor=eye|visible=show|x=640|y=360 shows the eye cursor pinned
mid-screen while the scene plays; the moment the cutscene ends, everything snaps back to
normal on its own.
Changing the whole screen's look#
ADJUST:<preset> drops a filter over the finished picture — room, characters, panels and
cursor together. It is how you play a flashback in black and white, a poisoning in sickly
green, or a memory as a soft dream. ADJUST:none clears it. The look is saved, so a
chapter that starts in black and white is still black and white after the player quits and
comes back.
Most presets are a look and nothing more: pick the one you want and you are done.
pixelate is the exception — it is the one you can dose, with an order-free key=value
tail:
block=<px>— how big each square is. The main dial.levels=<n>— how many shades per colour channel survive. Cutting this is what makes it read as pixel art instead of a blurry photo with squares.strength=<0..1>— how much of the effect mixes over the untouched picture.0is a clean way to switch the look off for one beat without losing the settings around it.dither=none|b4|b8— scatters the colour steps so flat areas break into a pattern. It needs the levels cut down to do anything.down=area|nearest— area averages for a softer result, nearest keeps edges hard.scope=world|all— how far the blocks reach. world stops at the edge of the room and leaves the interface sharp — verb bar, dialogs, speech bubbles, on-screen text, cursor. all takes the panels and their lettering too, which is what you want when the unreadable interface is the effect. Unlike the tonal presets above, which always cover the whole screen, pixelate is the one that can be told where to stop.
Every one is optional, and whatever you leave out keeps whatever the project already uses. So
if the game is already pixelated in Hub Config, ADJUST:pixelate|block=12 pushes the blocks
up for a moment and leaves the palette alone; ADJUST:none puts it back to the project's own
look rather than switching pixelation off.
A bigger block is cheaper here too — the effect works on a smaller copy of the picture, so pushing it further asks for less, not more.
Working with values & counters#
SETVAL, APPENDVAL and ADDVAL build up a value in a flag (a combination lock, a
dialled number, a counter) that you then check with the valueEquals or compare
condition.
SETVAL:<flag>|<value>writes an exact value, replacing whatever was there. Leave the value blank (SETVAL:code|) to wipe the flag clean — that's the Clear button on a keypad.APPENDVAL:<flag>|<text>|<max>adds text to the end of a flag, a piece at a time: it's what each digit button on a keypad fires. The optionalmaxcaps how long the value can grow, so a four-digit lock stays four digits no matter how many times the player mashes a key — extra presses simply do nothing. Leavemaxout and the value grows without limit. A text box the player types into has its own max length setting;maxis the same idea for entry driven by buttons, which never passes through the typing path.ADDVAL:<flag>|<n>adds a number to a counter — the universal "+1".nmay be negative to count down (ADDVAL:tries|-1). The result is stored as text, socompareandvalueEqualskeep reading it; an absent or non-numeric flag counts as0.RANDVAL:<flag>|<min>|<max>writes a random whole number betweenminandmax(inclusive) into a flag — then branch on it withcompare/valueEquals(e.g. "say one of three lines", a dice roll, a 30% chance). Randomness is intentionally an effect, never a condition: it's rolled once when the step fires, so a watcher checking the flag stays stable. The stream is seeded and saved, so a given playthrough is reproducible and a save/load doesn't change an already-rolled result.
Fine-tuning audio tokens: volume, pan and crossfade looping#
MUSIC, AMBIENCE, SOUND and VOICE accept an optional tail of key=value pairs after
their main argument, so you can tune a single cue without touching the mixer — the editors
show these as mini-knobs, but they're plain token text underneath.
|vol=<0-100>|pan=<-100..100>sets that cue's volume and stereo position. Volume multiplies on top of the player's own volume settings (aVOICEline's volume also multiplies the player's voice-volume slider); pan sweeps left/right, with0centered. Leave either one out and it keeps the default (full volume, centered) — a plainSOUND:door_creakstill works exactly as before.|xfade=<s>|xfadeat=<s>—MUSICandAMBIENCEonly — turns a track's loop into a smooth crossfade instead of jumping straight back to the start.xfadeis how many seconds the outgoing and incoming copies overlap;xfadeatis the point where that crossfade begins, which also sets how often the track loops (a 60-second track withxfadeat=52loops every 52 seconds). Reach for this on music or ambience whose ending doesn't already loop cleanly.
A fully tagged example: MUSIC:theme|vol=80|pan=0|xfade=1.5|xfadeat=52.
Making a sound effect loop, and stopping it#
SOUND is a one-shot: it plays once and reaps itself. To make a particular sample loop, you
don't change the token — you mark the sample in the Audio Editor,
which records loop points and a loop mode in projects/<id>/audio.json. Every SOUND that plays
that sample then loops, and STOPSOUND:<id> is what ends it. STOPSOUND stops every live
copy of that id, one-shots included, so it also works as a "cut that noise now" for a long sample
that hasn't finished.
Two things worth knowing before you lean on it: a looping SOUND started by a rule does not
survive a save/load (room ambience does, because the room re-triggers it on entry), and looping
background sound that belongs to a place is usually better expressed as AMBIENCE, which is
keyed, layered and restored automatically.
Text interpolation in spoken / on-screen text#
SAY, NPCSAY, NARRATE, SETSENTENCE and SHOWTEXT substitute {flagName} tokens in their text
from the current flag values at display time — e.g. SAY:Tienes {coins} monedas shows
Tienes 5 monedas. A missing flag becomes empty text (never an error); only {...}
names made of letters, digits and _ are touched, so stray braces and $9.99-style
amounts are left alone. Combine it with ADDVAL/RANDVAL to narrate live counters and
rolls.
Some tokens write a name into a flag for exactly this purpose. CATCHTARGET picks one
of several candidate characters (by priority or random) and stores the chosen id in an
out-flag (default caughtChar) — which you then consume by interpolation, e.g.
SWITCHCHAR:{caughtChar} or FOLLOW:monster|{caughtChar} in the same cutscene.