Page 1 of 1

Advice for Random Conversation System

Posted: Wed Jul 25, 2018 8:32 pm
by Dmangames
Hello,
In my game, the user clicks on a button that allows him to chat with a random person (like texting a random person). There is a pool of conversations that the user picks one from and some triggers such as quests will add and subtract conversations from that pool. I was thinking of just having a List<string> with all the conversation names that are allowed at the time. But then I wouldn't be able to save using the DS and would need to implement a save just for my one list. Also I'm not too sure how to write a custom lua command to add a string to list. Is this the best approach or am I missing something? Any advice is greatly appreciated!

Re: Advice for Random Conversation System

Posted: Wed Jul 25, 2018 9:46 pm
by Tony Li
Hi,

I'll suggest two completely different ways you can approach this.

Approach 1
First, you can hook into the Dialogue System's save system to save your list. Just add two methods, OnRecordPersistentData() and OnApplyPersistentData(). You can find an example with lots of instructional comments in Templates/Scripts/PersistentDataTemplate.cs. For example:

Code: Select all

using PixelCrushers.DialogueSystem;

List<string> conversations;

void OnRecordPersistentData()
{
    string s = string.Join(";", conversations.ToArray());
    DialogueLua.SetVariable("ConversationPool", s); // Save list in variable ConversationPool.
}

void OnApplyPersistentData()
{
    string s = DialogueLua.GetVariable("ConversationPool").AsString;
    conversations = new List<string>(s.Split(";"));
}
Similarly, you can register a C# method with Lua fairly easily. The Templates/Scripts/TemplateCustomLua.cs file has instructional comments. Example:

Code: Select all

using PixelCrushers.DialogueSystem;

void OnEnable()
{
    Lua.RegisterFunction("AddConversation", this, SymbolExtensions.GetMethodInfo(() => AddConversation(string.Empty)));
}

public void AddConversation(string conversation)
{
    conversations.Add(conversation);
}
Example of using this in a dialogue entry node:
  • Dialogue Text: "You should talk with my friend Adam."
  • Script: AddConversation("Adam")

Approach 2
However, you could take a completely different approach to this whole thing. This approach doesn't use anything I just mentioned above. Instead, create a special conversation -- call it Master -- with a <START> node that links to every possible conversation (Adam, Bob, Charlie, etc.). (To link to another conversation, inspect the <START> node and from the Links to: dropdown select (Another Conversation).)

Then put conditions on each of those conversations. For example, maybe the Charlie conversation's conditions require that the "Meet Angels" quest is successful. Or maybe the Bob conversation requires that a variable "Knows Bob" is true.

This means that at any given time the Master conversation will point to some amount of valid links to other conversations, depending on their conditions.

To get the list of currently-valid conversations, you'll need to create a ConversationModel. Here's an example that logs all currently-valid conversations to the console:

Code: Select all

var model = new ConversationModel(DialogueManager.masterDatabase, "Master", null, null, false, null);
foreach (var response in model.firstState.npcResponses)
{
    var conversation = DialogueManager.masterDatabase.GetConversation(response.destinationEntry.conversationID);
    Debug.Log(conversation.Title);
}
This approach is nice because all the logic (apart from the ConversationMode code just above) is contained in the dialogue database using the regular Conditions and Script fields, without any custom code to hook into the save system or Lua.

Re: Advice for Random Conversation System

Posted: Thu Jul 26, 2018 7:31 pm
by Dmangames
Hi Tony,

Thanks for the advice and code. I've decided to go with the second method you suggested, but when I try to do the Link to Conversation off the start node, model.firstState.npcResponses is empty. I also couldn't figure out where to put the conditions. I then tried to have a bunch of empty nodes branching off start that hold the conditions and a link to the new conversation. This worked and I got a pool of available conversations like I wanted, but the only problem is that when I try to get the conversation ID, it still thinks it the MASTER conversation. Is there anyway around this?

Thanks!

Re: Advice for Random Conversation System

Posted: Thu Jul 26, 2018 9:12 pm
by Tony Li
Hi,

Here's an example scene: RandomConversationHubExample_2018-07-26.unitypackage

Here's the script it uses:

RandomConversationList.cs
Spoiler

Code: Select all

using UnityEngine;
using System.Collections.Generic;
using PixelCrushers.DialogueSystem;

public class RandomConversationList : MonoBehaviour
{
    public List<string> validConversations = new List<string>();

    public void StartRandomConversation()
    {
        // Make list of valid conversations:
        Debug.Log("Valid conversations:");
        validConversations.Clear();
        var model = new ConversationModel(DialogueManager.masterDatabase, "Master", null, null, false, null);
        foreach (var response in model.firstState.npcResponses)
        {
            var conversation = DialogueManager.masterDatabase.GetConversation(response.destinationEntry.conversationID);
            validConversations.Add(conversation.Title);
            Debug.Log(conversation.Title);
        }

        // Choose one at random and start it:
        var conversationTitle = validConversations[Random.Range(0, validConversations.Count)];
        Debug.Log("Starting conversation " + conversationTitle);
        DialogueManager.StartConversation(conversationTitle);
    }
}
The trick is in the way you set up your conversations. These are the conversations in the example database:
  • Master: <START> node links directly to the first real node (not <START>) of the following conversations.
  • Abby: When played, sets variable KnowsAboutDave true.
  • Bob: When played, activates quest Talk To Ellen.
  • Claire.
  • Dave: Has condition: Variable KnowsAboutDave must be true.
  • Ellen: Has condition: Quest Talk To Ellen must not be unassigned.