Skip to main content

Text Substitution Reference

DialogueCraft replaces curly-brace patterns in dialogue text with runtime values. This page documents every supported pattern, the resolution order, and practical examples.


When Substitution Happens

Text substitution is performed at runtime by LocalizationManager.SubstituteAll() each time a Text node is displayed. The DialogueRunner calls LocalizationManager.SetDialogueContext() before processing each text node, which sets the current speaker and listener identifiers. The substitution then resolves patterns in the following order:

  1. Relationship patterns ({Relationship.A.B.Type})
  2. Actor field patterns ({Actor.Name.Field})
  3. Speaker/Listener field patterns ({Speaker.Field}, {Listener.Field})
  4. Simple patterns ({VarName}) -- including built-in names and global/local variables

This ordering matters because more specific patterns (with dots) are matched first, preventing them from being partially consumed by the simpler {word} pattern.

If a pattern cannot be resolved (variable not found, actor not recognized), the original {Pattern} text is left in place unchanged.


Pattern Reference

Global and Local Variables

Syntax: {VariableName}

Resolves against global variables first, then local (dialogue-scoped) variables. The variable name must consist of word characters (letters, digits, underscores).

PatternResolves To
{PlayerName}Value of the global variable PlayerName
{PlayerGold}Value of the global variable PlayerGold
{tempCount}Value of the local variable tempCount (if no global with that name exists)

Value formatting: Int values are rendered as-is (42). Float values use two decimal places (3.14). Bool values become true or false. String values are inserted directly.

Example in dialogue:

Welcome back, {PlayerName}! You have {PlayerGold} gold coins.

Actor Fields

Syntax: {Actor.NameOrID.FieldName}

Retrieves a specific character's actor field value. The NameOrID can be either:

  • The character's display name with spaces replaced by underscores (e.g., Merchant_Doran)
  • The character's internal ID (e.g., merchant_01)

The system attempts to resolve the identifier through the character database, checking both display names and IDs.

PatternResolves To
{Actor.Merchant_Doran.Friendship}Merchant Doran's Friendship field value
{Actor.merchant_01.TimesVisited}The character with ID merchant_01's TimesVisited value
{Actor.Knight.Trust}The Knight character's Trust field value

Example in dialogue:

Doran remembers you. His friendship level is {Actor.Merchant_Doran.Friendship}.

Speaker and Listener Names

Syntax: {Speaker}, {Listener}

These resolve to the display name of the current speaker or listener as set by the dialogue context.

PatternResolves To
{Speaker}Display name of the character speaking this line
{Listener}Display name of the character being spoken to

Example in dialogue:

{Speaker} turns to {Listener} and says nothing.

Speaker and Listener Field Values

Syntax: {Speaker.FieldName}, {Listener.FieldName}

Retrieves an actor field value from the current speaker or listener, without needing to know their identity at authoring time. This is useful for shared dialogues or generic lines.

PatternResolves To
{Speaker.Friendship}The current speaker's Friendship field value
{Listener.Mood}The current listener's Mood field value
{Speaker.Title}The current speaker's Title field value

Example in dialogue:

[{Speaker.Title}] {Speaker} nods approvingly. Trust level: {Speaker.Trust}.

Speaker and Listener IDs

Syntax: {SpeakerId}, {ListenerId}

These resolve to the internal character ID (not the display name) of the current speaker or listener. Useful for debugging or when your game logic needs to reference characters by ID.

PatternResolves To
{SpeakerId}Internal ID of the current speaker (e.g., merchant_01)
{ListenerId}Internal ID of the current listener (e.g., player)

Relationships

Syntax: {Relationship.FromActor.ToActor.Type}

Retrieves the relationship value between two actors. Relationships are directional -- the value from A to B may differ from B to A. The result is formatted as a whole number (no decimal places).

PatternResolves To
{Relationship.player.merchant.Trust}Player's trust toward the merchant
{Relationship.merchant.player.Trust}Merchant's trust toward the player
{Relationship.player.knight.Respect}Player's respect toward the knight

Example in dialogue:

The merchant eyes you cautiously. Trust: {Relationship.player.merchant.Trust}/100.

Complete Example

Consider a dialogue with a merchant character. The player has visited before, and various variables track the relationship:

Variables in play:

  • Global: PlayerName = "Aria", PlayerGold = 250
  • Actor (Merchant Doran): Friendship = 45, TimesVisited = 3, HasDiscount = true
  • Relationship: player -> merchant_doran Trust = 72
  • Local: itemCount = 2

Dialogue text (as authored):

Ah, {PlayerName}! Welcome back for visit number {Actor.Merchant_Doran.TimesVisited}.
I see you have {PlayerGold} gold. As a friend with {Actor.Merchant_Doran.Friendship}
friendship points and {Relationship.player.merchant_doran.Trust} trust,
I will give you a special price on those {itemCount} items.

Output at runtime:

Ah, Aria! Welcome back for visit number 3.
I see you have 250 gold. As a friend with 45
friendship points and 72 trust,
I will give you a special price on those 2 items.

Using Substitution in Text Nodes

Type patterns directly into the text field of any Text node. No special setup is required -- the DialogueRunner processes all substitution patterns automatically before displaying text to the player.

Patterns can be combined freely and placed anywhere in the text, including within rich text tags:

<color=#FFD700>{Speaker}</color> says: "Your gold: {PlayerGold}"

Substitution from C# Code

You can invoke text substitution manually in your own code:

// Full substitution using the shared variable system
string result = LocalizationManager.SubstituteAll(
"Hello {PlayerName}, trust is {Relationship.player.merchant.Trust}."
);

// Simple named variable substitution (no scope resolution)
string result = LocalizationManager.SubstituteVariables(
"You have {gold} gold and {gems} gems.",
("gold", 100), ("gems", 5)
);

// Substitution from a dictionary
var vars = new Dictionary<string, object>
{
{ "gold", 100 },
{ "gems", 5 }
};
string result = LocalizationManager.SubstituteVariables(
"You have {gold} gold and {gems} gems.", vars
);

// Substitution from a VariableStore directly
string result = LocalizationManager.SubstituteVariables(
"Gold: {PlayerGold}", variableStore
);

SubstituteAll is the method used internally by the dialogue system. It resolves all pattern types (relationships, actors, speaker/listener, globals, locals) using DialogueRunner.SharedVariables and the current dialogue context.

The simpler SubstituteVariables overloads only handle {name} patterns against explicitly provided values -- they do not resolve actor fields, relationships, or speaker/listener context.


Pattern Summary

PatternExampleDescription
{VarName}{PlayerGold}Global variable, then local variable
{Actor.Name.Field}{Actor.Merchant_Doran.Friendship}Specific actor's field (by display name or ID)
{Speaker}--Current speaker's display name
{Listener}--Current listener's display name
{Speaker.Field}{Speaker.Friendship}Current speaker's actor field value
{Listener.Field}{Listener.Mood}Current listener's actor field value
{SpeakerId}--Current speaker's internal ID
{ListenerId}--Current listener's internal ID
{Relationship.A.B.Type}{Relationship.player.merchant.Trust}Directional relationship value between two actors