How to show node only if one child evaluates true

Announcements, support questions, and discussion for the Dialogue System.
Post Reply
User avatar
kyuubi
Posts: 52
Joined: Fri May 27, 2016 11:30 pm

How to show node only if one child evaluates true

Post by kyuubi »

Hi,
How can I avoid showing a dialog line if all the children nodes evaluate false?
For example if I have a tree "Tell me about you" with a bunch of different nodes, I only want to show that while there are still nodes to show. After I asked all of it t should not be displayed.
So far I am doing this by hardcoding all the child IDs in the conditions of the parent but it makes this hard to manage with changes.
Any way to do something like, get all child node and check if they evaluate true or false?
Thanks,
Duarte
User avatar
Tony Li
Posts: 22062
Joined: Thu Jul 18, 2013 1:27 pm

Re: How to show node only if one child evaluates true

Post by Tony Li »

That's a tough one. A lot of games, even pro games like KoToR and Witcher 1, use a fallback node like "Tell me about you." --> "There's nothing more to tell.", like this:
  • Player: "Tell me about you."
    • NPC: "I'm a warrior." {Condition: Variable["Said_Warrior"] == false}
    • NPC: "I'm a dwarf." {Condition: Variable["Said_Dwarf"] == false}
    • NPC: "There's nothing more to tell."
You could duplicate those conditions on the "Tell me about you" node:
  • Player: "Tell me about you." {Condition: Variable["Said_Warrior"] == false or Variable["Said_Dwarf"] == false}
    • NPC: "I'm a warrior." {Condition: Variable["Said_Warrior"] == false}
    • NPC: "I'm a dwarf." {Condition: Variable["Said_Dwarf"] == false}
But I can see that if you're checking SimStatus this would be an extra pain. Fortunately, the Dialogue System does have a feature that may help. You can assign a delegate to DialogueManager.IsDialogueEntryValid. In this, you can add your own logic. Return true if the entry is valid, false if not. Something like:

Code: Select all

void Start() {
    DialogueManager.IsDialogueEntryValid = IsDialogueEntryValidCustom;
}

bool IsDialogueEntryValidCustom(DialogueEntry entry) {
    return (/* your logic here */);
}
In "your logic here", you can return true if the entry has no children, or if it has at least one child whose conditions are true:

Code: Select all

bool IsDialogueEntryValidCustom(DialogueEntry entry) {
    if (entry.outgoingLinks.Count == 0) return true; // No children. Return true.
    foreach (var link in entry.outgoingLinks) {
        var destination = DialogueManager.MasterDatabase.GetDialogueEntry(link);
        if (Lua.IsTrue(destination.conditionsString)) return true; // A child is true. Return true.
    }
    return false; // All children false. Return false.
}
User avatar
kyuubi
Posts: 52
Joined: Fri May 27, 2016 11:30 pm

Re: How to show node only if one child evaluates true

Post by kyuubi »

Hi Tony,
Thanks for getting back.
I do use a fallback "nothing more to tell as well" and in fact I like that user experience.
This works well up to the point where I have said all the child dialogs and that's the issue I'm facing.
So for example:
- Tell me about you
- How long you been on the Island
- What do you think of the Sheriff
- Why are there no boats in the Wharf?
- I want to talk about something else.

The issue here is, when I already said all the child dialogs this will happen:

1) Tell me about you.
2) I want to talk about something else.

Will the solution you posted address this?
Cheers,
User avatar
Tony Li
Posts: 22062
Joined: Thu Jul 18, 2013 1:27 pm

Re: How to show node only if one child evaluates true

Post by Tony Li »

The code I provided above is just a framework that you can add your own code to; it's not a solution by itself.

What if you use actor fields or variables to track this instead?

For example:
  • "Can I ask you something?" {Condition: Actor["Adam"].ToldAbout==false or Actor["Adam"].HowLong==false or Actor["Adam"].WhyNoBoats==false}
    • "Tell me about you." {Condition: Actor["Adam"].ToldAbout==false} {Script: Actor["Adam"].ToldAbout=true}
    • "How long have you been on the island?" {Condition: Actor["Adam"].HowLong==false} {Script: Actor["Adam"].HowLong=true}
    • "Why are there no boats in the wharf?" {Condition: Actor["Adam"].WhyNoBoats==false} {Script: Actor["Adam"].WhyNoBoats=true}
    • "I want to talk about something else."
If the player has chosen the first three responses (tell me about you, how long on the island, why no boats), then "Can I ask you something?" will not be offered.

Will that help?
Post Reply