Effects
Effects are changes to game state. They run in order when a dialogue node is reached or a choice is selected.
SET flag
Section titled “SET flag”Set a boolean flag to true.
SET flag metBartenderCLEAR flag
Section titled “CLEAR flag”Set a boolean flag to false.
CLEAR flag doorLockedVariables
Section titled “Variables”SET variable
Section titled “SET variable”Set a variable to a specific value.
SET variable gold 100SET variable playerName AriaADD variable
Section titled “ADD variable”Add to (or subtract from) a numeric variable.
ADD variable gold 50ADD variable gold -5ADD item
Section titled “ADD item”Add an item to the player’s inventory.
ADD item old_coinREMOVE item
Section titled “REMOVE item”Remove an item from the game by clearing its location. Afterward, hasItem
and itemAt both return false for it. Use this when an item is consumed,
destroyed, or handed over permanently.
REMOVE item rusty_keyTo put an item somewhere instead of removing it, use MOVE item.
MOVE item
Section titled “MOVE item”Move an item to a specific location.
MOVE item sword armoryLocation
Section titled “Location”GOTO location
Section titled “GOTO location”Change the player’s current location from within dialogue.
GOTO location marketGOTO nodeId routes to another dialogue node. GOTO location ends the dialogue and moves the player. Map travel through travelTo() also calculates travel time and runs location triggers.
ADVANCE time
Section titled “ADVANCE time”Advance game time by a number of hours.
ADVANCE time 2Time wraps at 24 hours and increments the day counter.
Quests
Section titled “Quests”SET questStage
Section titled “SET questStage”Set a quest to a specific stage.
SET questStage odd_jobs startedSET questStage odd_jobs completeSET trackedQuest
Section titled “SET trackedQuest”Follow an active quest, or clear tracking with none.
SET trackedQuest odd_jobsSET trackedQuest noneTracking is also cleared automatically when the followed quest is no longer active.
Journal
Section titled “Journal”ADD journalEntry
Section titled “ADD journalEntry”Unlock a journal entry.
ADD journalEntry tavern_discoveryJournal entries are only added once. Adding the same entry again has no effect.
Dialogue Flow
Section titled “Dialogue Flow”START dialogue
Section titled “START dialogue”Replace the current dialogue with a different one, starting from its first node.
START dialogue merchant_introThe current dialogue ends, and the new one begins at its first node. When the new dialogue ends, the player returns to the idle game state.
Use START dialogue for a self-contained sequence such as a cutscene, one-off encounter, or quiz.
For a branch that returns to earlier choices, keep its nodes in the same .dlg file and route them back with GOTO:
# inline: bluff nodes live in bartender_greeting.dlg and GOTO start when doneCHOICE "Try to bluff a free drink." GOTO bluff_attemptENDFor a standalone dialogue:
# START dialogue: the bluff is a standalone file, conversation ends when it's doneCHOICE "Tell me about yourself." START dialogue npc_backstoryENDEND dialogue
Section titled “END dialogue”End the current dialogue and return to the idle state.
END dialogueCharacters
Section titled “Characters”SET characterLocation
Section titled “SET characterLocation”Move a character to a specific location.
SET characterLocation merchant tavernADD toParty
Section titled “ADD toParty”Add a character to the player’s party.
ADD toParty elisaREMOVE fromParty
Section titled “REMOVE fromParty”Remove a character from the player’s party.
REMOVE fromParty elisaSET relationship
Section titled “SET relationship”Set the relationship value with a character (absolute).
SET relationship bartender 5ADD relationship
Section titled “ADD relationship”Add to (or subtract from) a character’s relationship value.
ADD relationship bartender 1ADD relationship bartender -2SET characterStat
Section titled “SET characterStat”Set a character stat to a number or string. Use the reserved character ID
player for the player character. A string must be one token or a localization
key.
SET characterStat elisa level 5SET characterStat player class @class.rangerADD characterStat
Section titled “ADD characterStat”Add to or subtract from a numeric character stat. If the stat is missing or is
a string, the supplied number becomes its new value, matching ADD variable.
ADD characterStat elisa health -10ADD characterStat player strength 0.5SET mapEnabled
Section titled “SET mapEnabled”Enable or disable the map.
SET mapEnabled trueSET mapEnabled falseChange the current music track.
MUSIC tension_theme.oggUse bare MUSIC to clear the override and return to the current location’s music.
MUSICPlay a one-shot sound effect.
SOUND door_slam.oggPlay a fullscreen video/cutscene. Bare filenames resolve to the normal video asset path.
VIDEO intro_cinematic.mp4The video appears as pendingVideo in the snapshot returned by the action. This is a transient field, meaning it lasts for one engine update. GameShell keeps the value until VideoPlayer finishes. A custom renderer needs to retain it for playback as well.
Interludes
Section titled “Interludes”INTERLUDE
Section titled “INTERLUDE”Show a narrative interlude: a full-screen text scene with scrolling text and a background image, like chapter cards in Infinity Engine games such as Baldur’s Gate.
INTERLUDE chapter_oneThe interlude ID must match an ID in content/interludes/. The interlude appears as pendingInterlude in the snapshot returned by the action. Renderers dismiss it with dismissInterlude(). See the Interludes guide for the full YAML schema.
Dice Rolling
Section titled “Dice Rolling”Roll a random whole number between min and max (inclusive) and store the result in a variable.
ROLL bluffRoll 1 20| Argument | Type | Description |
|---|---|---|
variable |
string |
Variable name to store the result in |
min |
number |
Minimum value (inclusive) |
max |
number |
Maximum value (inclusive) |
min and max must be whole numbers, and min cannot be greater than max.
The stored variable can then be displayed in dialogue using {varName} interpolation, or tested with variableGreaterThan / variableLessThan conditions.
# Roll once, then branch and display the resultROLL bluffRoll 1 20NARRATOR: You rolled a {bluffRoll}.
IF variableGreaterThan bluffRoll 14 SET flag bluffedMarcus ADD relationship bartender 2 GOTO successEND
GOTO failureEffects inside an IF block run only when that IF condition passes. If the IF block has a GOTO, the engine applies those effects before moving to the target node.
For a hidden check where you don’t need the value, use the roll condition in an IF block or triggered content:
IF roll 1 20 15 GOTO lucky_findENDSee the Dice & Randomness guide for patterns and examples.
Notifications
Section titled “Notifications”NOTIFY
Section titled “NOTIFY”Show a notification to the player. Supports @key localization.
NOTIFY @notification.quest_startedNOTIFY "You found something!"Notifications are transient: they appear in one snapshot and then clear.
TypeScript API
Section titled “TypeScript API”import { applyEffect, applyEffects } from '@doodle-engine/core';
// Single effectconst newState = applyEffect(effect, gameState);
// Multiple effects (applied sequentially)const newState = applyEffects(effects, gameState);Effect Order
Section titled “Effect Order”Effects within a node or choice are applied sequentially, top to bottom. This means later effects can depend on earlier ones:
SET flag questStartedSET questStage odd_jobs startedADD journalEntry odd_jobs_acceptedNOTIFY @notification.quest_startedThe flag is set before the quest stage changes, and the notification fires last.