Effects
Effects are mutations 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 "Aria"ADD 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 player’s inventory.
REMOVE item rusty_keyMOVE 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 marketNote: This is different from GOTO nodeId which routes to another dialogue node. GOTO location is an effect that ends the dialogue and moves the player.
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 completeJournal
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 starts from scratch. There is no return path. Once the new dialogue ends, the player is back at the idle state, not back in the original conversation.
Use START dialogue when the sub-dialogue is self-contained and doesn’t need to flow back into the caller (a cutscene, a one-off encounter, a modal quiz).
Use inline GOTO instead when you need the player to return to earlier choices after the sub-flow. Add the sub-flow nodes directly to the same .dlg file and route them back:
# inline: bluff nodes live in bartender_greeting.dlg and GOTO start when doneCHOICE "Try to bluff a free drink." GOTO bluff_attemptENDvs.
# 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 stat value on a character.
SET characterStat elisa level 5ADD characterStat
Section titled “ADD characterStat”Add to (or subtract from) a character’s stat.
ADD characterStat elisa health -10SET mapEnabled
Section titled “SET mapEnabled”Enable or disable the map.
SET mapEnabled trueSET mapEnabled falseChange the current music track.
MUSIC tension_theme.oggPlay a one-shot sound effect.
SOUND door_slam.oggPlay a fullscreen video/cutscene. The video file path is relative to the video base path.
VIDEO intro_cinematic.mp4The video appears as pendingVideo in the snapshot. It’s transient: it appears in one snapshot and is automatically cleared. The VideoPlayer component (or GameShell) handles playback and skip.
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 entity in content/interludes/. The interlude appears as pendingInterlude in the snapshot. It’s transient: it appears in one snapshot and is automatically cleared after the player dismisses it. See the Interludes guide for the full YAML schema.
Dice Rolling
Section titled “Dice Rolling”Roll a random integer 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) |
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 GOTO successEND
GOTO failureFor a one-shot hidden check where you don’t need the value, use the roll condition instead:
REQUIRE roll 1 20 15See 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 are automatically cleared.
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.