Skip to content

Dialogue graphs

A DialogueDefinition is a directed graph. Node IDs identify positions in the graph, and fields such as next, onTrue, and onFalse create transitions between them.

greeting (line)
question (choice) ── "Not now" ──▶ goodbye (end)
       └────────── "Help" ───────▶ checkLevel (branch)
                              true ─────┴───── false
                               ▼                 ▼
                         accept (action)     tooLow (line)
                               │                 │
                               └──────▶ done ◀───┘

Unlike a sequence stored in an array, a graph can branch, merge, skip nodes, and reuse the same ending.

Visible and silent nodes

MrDialogue separates nodes into two groups:

Category Nodes What the player sees
Visible line, choice Text, speaker information, and choices
Silent branch, action, end Nothing by itself

The server walks through silent nodes until it finds something to present or the session ends. This keeps decisions and side effects out of the client.

An action after a line waits for the player's next advance before it runs. An action reached directly after choosing an option runs immediately.

Server and client lifecycle

The adapter receives only the callback that matches the current state. A dialogue does not pass through every callback in the order shown below.

Starting and ending

Step Server Client adapter
1 Starts the session Receives OnShow
2 Resolves the entry node Receives a line or choices
3 Completes or cancels the session Receives OnEnd

If entry resolution completes or cancels before producing a visible node, the session is server-only and already inactive when returned. No client interface was opened, so the adapter receives neither OnShow nor OnEnd.

Presenting a line

Step Server Client adapter
1 Sends the line Receives OnPresentation
2 Waits for the presentation to finish Calls presentationCompleted()
3a Allows the player to continue Receives OnAdvanceReady, then calls advance()
3b Allows the player to finish Receives OnFinishReady, then calls finish()
3c Reaches a promptless choice Receives OnChoices immediately

Steps 3a, 3b, and 3c are alternatives. OnFinishReady is used when the line has no next or when its continuation currently resolves through silent nodes to an end. MrDialogue re-evaluates that continuation on the actual click, so volatile branch conditions do not remain cached while the player waits.

Presenting choices

Step Server Client adapter
1a Optionally sends the choice prompt Receives OnPresentation with kind = "choice_prompt"
1b Evaluates and sends the available options Receives OnChoices
2 Waits for a valid selection Calls choose(index)
3 Resolves the selected path Receives the next presentation or OnEnd

The callbacks passed to an adapter are valid only for the state that created them. Calling an old advance or choose callback after the server has moved on does nothing.

Authoritative choices

Choice conditions are evaluated immediately before the options are sent. When the player chooses an option, the server evaluates that option's condition again.

This prevents an option from remaining valid merely because it was visible earlier. If the condition changed, MrDialogue sends a refreshed set of available choices.

Definition validation

MrDialogue.new() validates the full graph immediately:

  • format must be 1.
  • entry and every transition must point to an existing node.
  • Choice option IDs must be unique within their node.
  • Conditions and actions must have non-empty names.
  • Speaker and emotion references must exist.
  • Arrays must be dense and one-based.
  • Definitions may contain at most 10,000 nodes, choices at most 100 options, and handler specs at most 100 arguments.
  • IDs, presentation text, speaker data, icons, results, and reasons must be valid UTF-8 and fit the byte limits exposed by MrDialogue.Limits.

The validated definition is deep-copied and frozen. Editing the source table after calling MrDialogue.new() does not change existing or future sessions for that Dialogue object.

Create once, start many times

Define dialogues when the server starts and keep the returned Dialogue object. Call Dialogue:Start() for each player interaction instead of rebuilding the same definition on every trigger.

Reusing graph data

The graph format is plain Luau data, so it can be generated by another tool or converted from a localization or quest format. Perform that conversion before MrDialogue.new() so validation catches broken targets early.

Continue with Nodes for the fields and behavior of every node type.