Skip to content

Effects

Effects are changes to game state. They run in order when a dialogue node is reached or a choice is selected.

Set a boolean flag to true.

SET flag metBartender

Set a boolean flag to false.

CLEAR flag doorLocked

Set a variable to a specific value.

SET variable gold 100
SET variable playerName Aria

Add to (or subtract from) a numeric variable.

ADD variable gold 50
ADD variable gold -5

Add an item to the player’s inventory.

ADD item old_coin

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_key

To put an item somewhere instead of removing it, use MOVE item.

Move an item to a specific location.

MOVE item sword armory

Change the player’s current location from within dialogue.

GOTO location market

GOTO 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 game time by a number of hours.

ADVANCE time 2

Time wraps at 24 hours and increments the day counter.

Set a quest to a specific stage.

SET questStage odd_jobs started
SET questStage odd_jobs complete

Follow an active quest, or clear tracking with none.

SET trackedQuest odd_jobs
SET trackedQuest none

Tracking is also cleared automatically when the followed quest is no longer active.

Unlock a journal entry.

ADD journalEntry tavern_discovery

Journal entries are only added once. Adding the same entry again has no effect.

Replace the current dialogue with a different one, starting from its first node.

START dialogue merchant_intro

The 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 done
CHOICE "Try to bluff a free drink."
GOTO bluff_attempt
END

For a standalone dialogue:

# START dialogue: the bluff is a standalone file, conversation ends when it's done
CHOICE "Tell me about yourself."
START dialogue npc_backstory
END

End the current dialogue and return to the idle state.

END dialogue

Move a character to a specific location.

SET characterLocation merchant tavern

Add a character to the player’s party.

ADD toParty elisa

Remove a character from the player’s party.

REMOVE fromParty elisa

Set the relationship value with a character (absolute).

SET relationship bartender 5

Add to (or subtract from) a character’s relationship value.

ADD relationship bartender 1
ADD relationship bartender -2

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 5
SET characterStat player class @class.ranger

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 -10
ADD characterStat player strength 0.5

Enable or disable the map.

SET mapEnabled true
SET mapEnabled false

Change the current music track.

MUSIC tension_theme.ogg

Use bare MUSIC to clear the override and return to the current location’s music.

MUSIC

Play a one-shot sound effect.

SOUND door_slam.ogg

Play a fullscreen video/cutscene. Bare filenames resolve to the normal video asset path.

VIDEO intro_cinematic.mp4

The 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.

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_one

The 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.

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 result
ROLL bluffRoll 1 20
NARRATOR: You rolled a {bluffRoll}.
IF variableGreaterThan bluffRoll 14
SET flag bluffedMarcus
ADD relationship bartender 2
GOTO success
END
GOTO failure

Effects 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_find
END

See the Dice & Randomness guide for patterns and examples.

Show a notification to the player. Supports @key localization.

NOTIFY @notification.quest_started
NOTIFY "You found something!"

Notifications are transient: they appear in one snapshot and then clear.

import { applyEffect, applyEffects } from '@doodle-engine/core';
// Single effect
const newState = applyEffect(effect, gameState);
// Multiple effects (applied sequentially)
const newState = applyEffects(effects, gameState);

Effects within a node or choice are applied sequentially, top to bottom. This means later effects can depend on earlier ones:

SET flag questStarted
SET questStage odd_jobs started
ADD journalEntry odd_jobs_accepted
NOTIFY @notification.quest_started

The flag is set before the quest stage changes, and the notification fires last.