Page 1 of 2

How to do Same conversation, different actors, different text?

Posted: Tue May 31, 2022 2:21 pm
by diccon
Hello,
We have a game where you make deliveries to NPCs and the conversation tree has some pretty complex logic so I don't want to duplicate it, however I do want to have unique dialogue for each NPC. In order to get across each character I'd like to replace the text entirely on some of the nodes so using variables to substitute names and so on isn't really enough.
I'm thinking of implementing some kind of lookup that indexes by actor and somehow replaces the subtitle text before it is displayed but I wondered if anyone else had tried such a thing and if there is a good way to do it, and if the dialogue text could even be stored in DS or if it would have to be in some other database?

Thanks for any help!

Re: How to do Same conversation, different actors, different text?

Posted: Tue May 31, 2022 3:28 pm
by Tony Li
Hi,

If you want to entirely replace the text, use an OnConversationLine() method. For example, to completely change the greeting message based on the actor:

Code: Select all

void OnConversationLine(Subtitle subtitle)
{
    if (subtitle.formattedText.text == "greeting") // If we set Dialogue Text to "greeting", replace with actor's text.
    {
        subtitle.formattedText.text = GetActorGreeting(subtitle.speakerInfo.nameInDatabase);
    }
}

string GetActorGreeting(string actorName)
{
    switch (actorName)
    {
        case "Adam": return "Yo! Wazzup!";
        case "Beth": return "Hello there.";
        case "Cindy": return "Howdy, y'all!";
        default: return "Hello.";
    }
}

To keep all of your text in the dialogue database, you could store those greetings in a custom actor field:

Code: Select all

void OnConversationLine(Subtitle subtitle)
{
    if (subtitle.formattedText.text == "greeting") // If we set Dialogue Text to "greeting", replace with actor's text.
    {
        subtitle.formattedText.text = DialogueLua.GetActorField(subtitle.speakerInfo.nameInDatabase, "greeting").asString;
    }
}

Similarly, if you only want to replace substrings in the text, you can use [lua(code)] tags. Example:
  • Dialogue Text: "I'm not just any [lua(Actor[Variable["ConversantIndex"]].Job]. I'm the best in the business."
Notes:
  • Variable["ConversantIndex"] is the Name of the actor that currently being used as the conversation's conversant.
  • The example above assumes Actor["some-actor-name"] has a custom field named "Job".

Re: How to do Same conversation, different actors, different text?

Posted: Tue May 31, 2022 3:36 pm
by diccon
Thanks for the quick response! This seems like it will do what I need :)

Re: How to do Same conversation, different actors, different text?

Posted: Tue May 31, 2022 3:48 pm
by Tony Li
Glad to help! There are plenty of ways to do this, so none of those approaches fit your needs, let me know.

Re: How to do Same conversation, different actors, different text?

Posted: Sun Jul 10, 2022 10:22 pm
by diccon
Following up to this thread, I got pulled onto some other tasks so I've only just started working on this and the proof of concept seems to work, but I don't really like the workflow of having to add additional fields into the Actor by hand and then write them in the inspector (the text field is really small and does not expand), especially for multiple languages.

What I would like to do is author all the custom dialogue in a spreadsheet and import it, so my question is how to go about writing a custom importer that will read from a .csv and add Fields to the Actors in the database. I know there are a bunch of importers already so I wonder if there is some kind of framework to use. The format of the data will likely be one file per Actor and then fields: entry_name, entry_text, entry_text_fra, entry_text_jap etc..

Thanks for your help!

Re: How to do Same conversation, different actors, different text?

Posted: Mon Jul 11, 2022 8:46 am
by Tony Li
You could write your own importer, or use CSV. To use CSV:
  • Define your fields in the template.
  • In the Database section, expand Export Database. Set Format to CSV. UNtick everything except Actors.
  • Export the CSV file.
  • Edit the CSV file.
  • Select menu item Tools > Pixel Crushers > Dialogue System > Import > CSV.
  • Specify the CSV file and original database. Tick Overwrite and Merge. Then click Import.
I recommend making a backup of your database first to make sure you have the process down.

Re: How to do Same conversation, different actors, different text?

Posted: Tue Jul 12, 2022 12:41 pm
by diccon
Thanks, I ended up piggybacking off CSVConverterWindow which works well, so for my next problem:

I have several generic conversations where speakers are not specified in the database but are provided at runtime (Shopkeeper_01 etc). These conversations use links so that Generic_Entry will link to Generic_Delivery or Generic_Gossip etc depending on what the player chooses, however when the conversation link takes place my specified speaker is lost. Is there a way to ensure that a designated speaker is preserved through a conversation link?

Thanks again.

Re: How to do Same conversation, different actors, different text?

Posted: Tue Jul 12, 2022 2:12 pm
by diccon
Managed to find my own workaround, seems that as long as the speaker is set to the same actor for all the generic conversations then the character cache will keep using the specified actor from the first conversation.

Re: How to do Same conversation, different actors, different text?

Posted: Tue Jul 12, 2022 2:15 pm
by Tony Li
Yup, that's the easiest solution. Then it should work fine without any extra effort.

If you end up needing to use different generic actors the current speaker switch the generic actor it's filling in for mid-conversation, it'll take a little scripting. When the first conversation starts, Shopkeeper_01 will be associated with Generic_Delivery. When you cross to another conversation that uses Generic_Gossip, nothing will be associated with Generic_Gossip. You can add an OnLinkedConversationStart() method to a script on the Dialogue Manager. In this method, you'll need to associate the Shopkeeper_01 with Generic_Gossip. Something like this should work:

Code: Select all

void OnLinkedConversationStart(Transform actor)
{
    int conversationID = DialogueManager.currentConversationState.subtitle.dialogueEntry.conversationID;
    Conversation conversation = DialogueManager.masterDatabase.GetConversation(conversationID);
    CharacterInfo characterInfo = DialogueManager.conversationModel.GetCharacterInfo(conversation.conversantID, npcTransform);
    characterInfo.Name = DialogueManager.conversationModel.conversantInfo.Name;
}
I recommend sticking with your solution -- use the same generic actor (e.g., Generic_NPC or something).

Re: How to do Same conversation, different actors, different text?

Posted: Thu Jul 14, 2022 1:45 pm
by diccon
Thanks again, so for my next question - some of the actors will have a backstory that I wish to author in a separate conversation, I'd like to be able to push this in as a variable that identifies a conversation and the player can select it as a response if it is available. Is there a way to dynamically add a link to a conversation node like this?