Accessing Variables in Dialogue Tree Templates Procedurally

Announcements, support questions, and discussion for the Dialogue System.
Post Reply
Marushia Dark
Posts: 8
Joined: Sun Sep 01, 2024 8:43 am

Accessing Variables in Dialogue Tree Templates Procedurally

Post by Marushia Dark »

Given I have hundreds of characters and quests, was wondering if there's an easy way to procedurally get a particular quest associated with a character. For instance, in my Google Sheets database, I could easily have an entry that says which quest that character is tied to, or in the Actor database even. And possibly have the Google database contain various counts and items and variables.

I can import all that through JSON into Unity just fine, and hook up new fields (apart from Quest Status, which doesn't seem to be a FieldType unlike the others) but I don't know enough about LUA or the backend of the Dialogue System to parse the correct syntax for what I want. Ultimately, I'd like to make a template using generic commands and triggers since all the NPCs have more or less the same structure.

For instance, when the quest is accepted, show something like:

Code: Select all

SetQuestState(Actor.Quest, "active");
ShowAlert("New Quest:  [Actor.Quest.DisplayName]")
Instead, I only know how to apply these literally:

Code: Select all

SetQuestState("My Quest Name", "active");
ShowAlert("New Quest: Shorthand Name")
Similarly, for checks, I'd like to be able to set a generic quest's status to check and set conditions for:

Code: Select all

Variable[Actor.Quest.Condition]
And then in the Google Database, be able to write:

Code: Select all

Crates >= 3

Code: Select all

Variable["Crates.Count"] >= 3
And just assign them procedurally through code when the Actor, Item, Quest, Variable, etc. is created in a C# script and save all the generics within a JSON Dialogue Template. How can I do that? Am I on the right track?
User avatar
Tony Li
Posts: 22107
Joined: Thu Jul 18, 2013 1:27 pm

Re: Accessing Variables in Dialogue Tree Templates Procedurally

Post by Tony Li »

Hi,

Here are two ideas. The first is simpler. The second is more flexible.

First idea:
This idea doesn't require any custom scripts or custom fields in your dialogue database.

Set each quest's Name to the same as the actor's Name, following these rules (mainly, replace blank spaces with underscores). Set the quest's Display Name to the actual quest name that appears in quest UIs. Example with NPC named "Innkeeper" and quest "Kill Rats":

quests1.png
quests1.png (37.73 KiB) Viewed 85 times

Let's say you use a generic conversation in which you assign the Innkeeper as the conversation's conversant. When the conversation starts, the Dialogue System will set the variable Variable["ConversantIndex"] to the Name of the conversant (e.g., "Innkeeper"). Then you can use this Lua code in a dialogue entry's Script field:

Code: Select all

SetQuestState(Variable["Conversant"], active);
ShowAlert("New Quest: " .. Quest[Variable["ConversantIndex"]].Display_Name)
For the Innkeeper, the first line will translate to SetQuestState("Innkeeper", active). (The Dialogue System defines constants unassigned, active, success, etc, so you can use those constants or the literal string values "unassigned", "active", "success", etc.)

The second line will translate to ShowAlert("New Quest: " .. Quest["Innkeeper"].Display_Name), which will further boil down to ShowAlert("New Quest: Kill Rats").


---


Second idea:
Every "asset" type (actor, quest, conversation, etc.) in a dialogue database can have custom fields. For example, you could add a "Quest Giver" field to your quests (or quest template):

quests2.png
quests2.png (53.41 KiB) Viewed 85 times

Alternatively, you could add a field to the actor:

quests3.png
quests3.png (30.84 KiB) Viewed 85 times

Then you can look up an actor by its quest, or a quest by its actor:

Code: Select all

SetQuestState(Actor[Variable["ConversantIndex"]].Quest, active);
questDisplayName = Quest[Actor[Variable["ConversantIndex"]].Quest].Display_Name;
ShowAlert("New Quest: " .. questDisplayName)

You can get even more sophisticated by adding fields to your quest template that you handle in a standard way. In the recently released Gestalt: Steam & Cinder, we defined quest fields that were similar to this:

quests4.png
quests4.png (57.12 KiB) Viewed 85 times

Then we could programmatically increment the quest's "Counter" field (e.g., using DialogueLua.SetQuestField()), check if it has reached the "CounterGoal" value, and then set the state to success and grant the "XP Reward". There are more fields than this in Gestalt's quest template, such as a custom field type for item rewards, but this should be enough to give you an idea.

Other studios have also added custom quest fields that contain Lua code -- for example, a custom field containing Lua code to run when the player accepts the quest. This code can spawn GameObjects or otherwise set up the beginning of the quest. Or, for another example, a custom field containing Lua code to run when the player completes the quest. That code could run C# methods that give rewards to the player.
Marushia Dark
Posts: 8
Joined: Sun Sep 01, 2024 8:43 am

Re: Accessing Variables in Dialogue Tree Templates Procedurally

Post by Marushia Dark »

I think I'm starting to get the idea, but still having some trouble. I tried to write the following line in the dialogue field, rather than in scripting and it either returned null or displayed the actual string literal. How can I assign this inline to the actual text?

Code: Select all

Help [var=Quest[Actor[Variable["ConversantIndex"]].Quest].Quota] such souls find peace and I shall return you to your time.  What say you?
And then this in the conditions slot, where Condition is a string name associated with a variable and quota is a number, both of which are fields of the quest:

Code: Select all

Actor[Variable["ConversantIndex"]].Quest.Condition >= Actor[Variable["ConversantIndex"]].Quest.Quota
I tried a number of variations with and without the "var" keyword, or also choosing Variable even though it's not listed as a variable. What is the proper syntax for such a thing? Quota, in this case, is a number.
User avatar
Tony Li
Posts: 22107
Joined: Thu Jul 18, 2013 1:27 pm

Re: Accessing Variables in Dialogue Tree Templates Procedurally

Post by Tony Li »

Hi,

You're close! The [var=variableName] keyword is only for variables defined in the dialogue database's/Dialogue Editor's Variables section. Use [lua(code)] for anything else:

Code: Select all

Help [lua(Quest[Actor[Variable["ConversantIndex"]].Quest].Quota)] such souls find peace and I shall return you to your time.  What say you?
For the second one, assuming Condition and Quota are fields in the quest, you need to

Code: Select all

Quest[Actor[Variable["ConversantIndex"]].Quest].Condition >= Quest[Actor[Variable["ConversantIndex"]].Quest].Quota
Note: You can write C# methods to simplify this. Then register those methods with Lua and use them instead. Example:

In C#:

Code: Select all

public bool IsQuestConditionMet()
{
    string conversantIndex = DialogueLua.GetVariable("ConversantIndex").asString;
    string questName = DialogueLua.GetActorField(conversantIndex, "Quest").asString;
    int condition = DialogueLua.GetQuestField(questName, "Condition");
    int quota = DialogueLua.GetQuestField(questName, "Quota");
    return condition >= quota;
}
In Lua:

Code: Select all

IsCurrentQuestConditionMet()
Post Reply