Recipes
Patterns that come up in almost every project, written the way ChatMapper authors have built them for years. Each one works in the simulator, in Play mode, in the HTML player and in every engine export — they use nothing but nodes, links, variables and a line or two of Lua.
Node numbers below are examples; turn on ⋯ → Show node IDs to read your own off the cards.
A Start node
Section titled “A Start node”A conversation that autoplays begins the moment it loads, before the player
has oriented themselves. Give them an anchor: one player-choice node between
START and the first line, with [f] in its menu text so the single option
is shown as a button rather than auto-played.
START ─▶ [Player] Menu: "[f]Begin" ─▶ first line…That click is also the moment to set things up. Put initialisation in the Start node’s Script:
Variable["trust"] = 0Variable["askedAboutStorm"] = falseOn the web, that first click matters twice: browsers refuse to play audio until the user has interacted with the page, so a Start node is what makes the opening line’s voice-over audible.
Only the first time
Section titled “Only the first time”If the player can re-enter the conversation, they should not see “Begin” again. Give the Start node a condition on its own status and a Passthrough fallback so the story continues past it:
-- Condition on the Start node (its ID is 1 here); If false: PassthroughDialog[1].SimStatus == "Untouched"A Replay node
Section titled “A Replay node”The mirror of the Start node: a choice at the end (“Play again”) whose script resets state, and which links back to the beginning.
Variable["trust"] = 0Variable["hasToken"] = falseDialog[1].SimStatus = "Untouched" -- so the Start node shows againDialog[7].SimStatus = "Untouched" -- and any other one-time lineAnything you gate on SimStatus must be reset here or it stays hidden on
the second run.
Ask in any order
Section titled “Ask in any order”A hub of questions the player can ask in any order, each disappearing once asked, with the exit appearing only when they are done.
"What do you want to know?" (group node 2) ├─ [f]About the ferry (3) cond: Dialog[3].SimStatus ~= "WasDisplayed" → answer → link back to 2 ├─ [f]About the token (4) cond: Dialog[4].SimStatus ~= "WasDisplayed" → answer → link back to 2 ├─ [f]About the storm (5) cond: Dialog[5].SimStatus ~= "WasDisplayed" → answer → link back to 2 └─ "Then we're done." (9) cond: Dialog[3].SimStatus == "WasDisplayed" and Dialog[4].SimStatus == "WasDisplayed" and Dialog[5].SimStatus == "WasDisplayed"- The answers link back to the group node, not to the question line, so the prompt is not repeated every time.
[f]on every question keeps the menu showing even when only one question is left; leave it off the last one if you want it to auto-play.- Node 9 has no menu text, so as soon as its condition is true it plays automatically and the loop ends.
A variant with a counter instead of statuses:
-- each answer's scriptVariable["asked"] = Variable["asked"] + 1-- the exit's conditionVariable["asked"] >= 3A line that plays once
Section titled “A line that plays once”The condition Dialog[12].SimStatus == "Untouched" on node 12 itself hides
it after its first showing. Set If false: Passthrough so the nodes under
it are still reachable when it is skipped.
A fallback line
Section titled “A fallback line”Several conditional responses and one that always applies: give the conditional ones priority High and the fallback Normal (or the conditionals Normal and the fallback Low). Only the best priority present is offered, so the fallback appears only when none of the specific lines’ conditions hold — no need to write the inverse of every condition.
Remembering what the player said elsewhere
Section titled “Remembering what the player said elsewhere”Variables and statuses persist across conversations within a playthrough.
Set Variable["metCaptain"] = true in one conversation and test it in
another; or test the other conversation’s node directly:
Conversation[2].Dialog[14].SimStatus == "WasDisplayed"A randomised setup
Section titled “A randomised setup”A training scenario that plays differently each time — the customer starts in a random mood, say. In the Start node’s script:
Variable["mood"] = math.random(1, 3)Then condition the opening lines on Variable["mood"] == 1, == 2, == 3.
Asking the player to type
Section titled “Asking the player to type”Put [var=?PlayerName] in a line — “And you are?[var=?PlayerName]” — and
the story pauses for an answer, stores it in PlayerName, and continues.
Use it later with [var=PlayerName]: “Welcome aboard, [var=PlayerName].”
To give a default when the player types nothing, follow the prompt with a node whose script does:
if Variable["PlayerName"] == "" then Variable["PlayerName"] = "stranger" end(Real-Lua environments only; in the HTML player, write the fallback into the line itself instead.)
Showing a value
Section titled “Showing a value”[var=trust] anywhere in dialogue or menu text: “You’ve asked me
[var=questions] times already.”
Splitting a big story across conversations
Section titled “Splitting a big story across conversations”A single conversation is comfortable to a few hundred nodes. Beyond that, split by scene and join with Link to conversation…. Two things to know before you cut:
- A cross-conversation link always enters the other conversation at its START, not at an arbitrary node. Cut at points where the next scene naturally begins, and use a group node under START as the switchboard if a scene has several entry situations (condition each branch on the variable the previous scene set).
- Variables and statuses carry across, so nothing is lost by splitting —
but the exit conditions of a loop in one conversation cannot see menu
state in another except through
Conversation[c].Dialog[d].SimStatus.
Choices with captions
Section titled “Choices with captions”To put a question above the choice buttons — “How do you answer?” — make it the Dialogue Text of the parent node (spoken by the narrator or the player themselves); the menu appears beneath it. Engines with a dedicated caption slot can read a custom field instead; see Extending the format.