0% found this document useful (0 votes)
7 views7 pages

Dialogue Graph Guide

The DialogueGraph tutorial provides a comprehensive guide on creating NPC dialogue trees using Lua tables, detailing how to define and organize dialogue graphs, including static and dynamic nodes. It covers the structure of dialogue and selector nodes, the use of optional nextNodeId, and the significance of args for dynamic content. The guide emphasizes best practices for maintaining node identity and traversal logic while allowing for rich text formatting.

Uploaded by

spamthis192
Copyright
© All Rights Reserved
We take content rights seriously. If you suspect this is your content, claim it here.
Available Formats
Download as PDF, TXT or read online on Scribd
0% found this document useful (0 votes)
7 views7 pages

Dialogue Graph Guide

The DialogueGraph tutorial provides a comprehensive guide on creating NPC dialogue trees using Lua tables, detailing how to define and organize dialogue graphs, including static and dynamic nodes. It covers the structure of dialogue and selector nodes, the use of optional nextNodeId, and the significance of args for dynamic content. The guide emphasizes best practices for maintaining node identity and traversal logic while allowing for rich text formatting.

Uploaded by

spamthis192
Copyright
© All Rights Reserved
We take content rights seriously. If you suspect this is your content, claim it here.
Available Formats
Download as PDF, TXT or read online on Scribd

DialogueGraph Tutorial and Guide

This guide explains how to use the DialogueGraph system to write clean, declarative NPC dialogue
trees using static and dynamic Lua tables.

You’ll learn: - How to define and organize a dialogue graph - The role of dialogues , selectors ,
and choices - Why nextNodeId is optional - How to write static and dynamic nodes - How to
hydrate values using args

Anatomy of a Graph
A dialogue graph is composed of two top-level namespaces:

DialogueGraph {
dialogues = { ... },
selectors = { ... },
}

These namespaces allow you to separate one-line dialogues from multi-option selectors, and provide
sweet, sweet autocompletion when editing them.

You construct the graph by passing this table to the DialogueGraph() constructor:

local graph = DialogueGraph {


dialogues = { ... },
selectors = { ... },
}

Each key in dialogues or selectors is a NodeId . Its value is either: - A static table - A function
returning such a table, optionally using args

Example:

-- Static dialogue node


['Greet'] = {
dialogues = { 'Hi there!', 'How can I help you?' },
nextNodeId = 'Options'
},

-- Dynamic dialogue node


['Greet'] = function(args)
return {
dialogues = { `Welcome, {[Link]}!` },
nextNodeId = 'Options'

1
}
end

Dialogue Nodes
A dialogue node shows one or more lines of text in sequence.

Required Fields

• dialogues : An array of strings, shown in order


• nextNodeId (optional): A node ID string that must exist in the same graph

Static Example

['Intro'] = {
dialogues = {
'Greetings!',
'Welcome to the shop.'
},
nextNodeId = 'Options'
}

Dynamic Example

['Intro'] = function(args)
return {
dialogues = {
`Hello, {[Link]}!`,
'Ready to see what we’ve got?'
},
nextNodeId = 'Options'
}
end

Selector Nodes
A selector node offers the programmer a list of choices to present. Each choice includes a display
label and, optionally, a nextNodeId that determines the node to traverse to if selected.

Required Fields

• choices : A dictionary of choice IDs mapped to ChoiceParams

2
Each ChoiceParams must have: - displayName : What the player sees - nextNodeId : The target
node ID string (or nil to signal that traversal should exit the dialogue graph) - index (optional): A
number controlling the order (optional but useful)

Example

['Options'] = {
choices = {
Buy = {
displayName = 'Buy',
nextNodeId = 'Goodbye',
index = 1
},
Exit = {
displayName = 'Leave',
nextNodeId = 'Goodbye',
index = 2
}
}
}

Why index Is Optional but Useful

Lua tables are unordered. If you don't provide index , all choices will still work, but they may appear in
unexpected order. Internally, index is used with [Link](pos, value) , so if order matters,
use it. If not, don’t sweat it.

You can also define a choice with nextNodeId = nil to signal that the dialogue should exit after that
choice is selected:

['Options'] = {
choices = {
Exit = {
displayName = 'Nevermind',
nextNodeId = nil, -- Will exit dialogue
index = 1
}
}
}

This tells the dialogue system: stop here and close the prompt.

Dynamic Example

['Options'] = function(args)
return {
choices = {
Buy = {

3
displayName = `Buy {[Link]} items for
{[Link]} coins`,
nextNodeId = 'Goodbye',
index = 1
},
Info = {
displayName = 'What else do you offer?',
nextNodeId = 'Details',
index = 2
}
}
}
end

Why nextNodeId Is Optional


Setting nextNodeId to nil is how you signal the end of a path. This is useful when a choice or a
dialogue should exit the dialogue flow completely.

You don’t have to explicitly manage the exit logic—just omit nextNodeId and any traversal handler
that implements the dialogue graph worth its bits will know to terminate or close the dialogue UI.

This is particularly useful for things like:

['Goodbye'] = {
dialogues = {
'See you around!'
}
-- No nextNodeId means the dialogue ends here
}

Static vs Dynamic Definitions

Static

Defined as a plain Lua table. Best for fixed lines and structure.

['Farewell'] = {
dialogues = { 'Thanks for visiting!' }
}

Dynamic

Defined as a function. Called each time the node is visited, with args passed in.

4
['Farewell'] = function(args)
return {
dialogues = { `Thanks, {[Link]}!` }
}
end

With great power comes great responsibility. With args , anything below could be
defined dynamically—not just values, but structure too. Don’t.

Keep args usage limited to values only. Never use args to generate keys or change the shape of
the node structure.

Dynamic nextNodeId example (acceptable)

['Conditional Branch'] = function(args)


return {
dialogues = {
'Let’s see where you’re going next...'
},
nextNodeId = [Link] or 'FallbackNode'
}
end

This lets you push fallback logic into the graph when needed.

Dynamic key example (NOT acceptable)

['Selector'] = function(args)
return {
choices = {
[[Link]] = { -- don’t do this
displayName = 'Dynamic choice',
nextNodeId = 'Goodbye',
index = 1
}
}
}
end

Avoid this. Dynamic keys break node identity and interfere with traversal logic, debugging, and
autocompletion. The graph shape must be static.

Using args
The args table is a plain dictionary passed in during traversal. Each node can use it to dynamically
construct text. If you’re writing a dialogue, just use the keys and values you expect.

5
You don’t need to care where args comes from or how it’s built—that’s the programmer’s job. Just
leave a comment if you expect something:

-- args = { playerName: string, totalCost: number }


['CheckOut'] = function(args)
return {
dialogues = { `That’ll be {[Link]} coins,
{[Link]}.` },
nextNodeId = 'Goodbye'
}
end

You can also use the RichText utility for stylized strings:

RichText("Limited Time Offer", { color = [Link](1, 0.2, 0.2), bold =


true })

This is optional—it’s just cleaner than string concatenation and easier to support rich formatting like
stacked effects.

Example Graph

['Selling To Player'] = DialogueGraph {


dialogues = {
['Greet'] = function(args)
return {
dialogues = {
`Welcome, {[Link]}!`,
`You placed {[Link]} items in the basket.`
},
nextNodeId = 'Options'
}
end,

['Goodbye'] = {
dialogues = {
'Safe travels!'
}
}
},

selectors = {
['Options'] = function(args)
return {
choices = {
Buy = {

6
displayName = `Buy for {[Link]} coins`,
nextNodeId = 'Goodbye',
index = 1
},

Exit = {
displayName = 'Leave',
nextNodeId = 'Goodbye',
index = 2
}
}
}
end
}
}

Footer
At the end of the day, this system just helps you describe text and transitions between boxes. It’s all
syntax sugar for a graph. Whether you’re writing static tables or functions, it compiles into immutable
nodes and predictable flows.

This guide only explains how to construct the graph. How it's actually traversed—what triggers the next
node, how choices are rendered, how args are injected—is completely up to the programmer using
the graph.

It’s just text. Write it well.

You might also like