Page 1 of 1

Saving conversation state, interrupting and resuming from the same entry later

Posted: Thu Sep 14, 2023 3:28 pm
by urrmurrmur
Hi,

I am currently working on a system where I want to pause my currently active conversation and resume it at a later point. I know the DialogueManager class has a Pause function, but I believe I won't be able to use that. This is because it is possible that I have to run a short, different conversation while the main one is interrupted.

So the flow I want to achieve is this:
  1. Start conversation A
  2. Stop conversation A and fully hide the DSFU UI. Remember the current state (dialogue entry id). Some other UI is shown in the mean time, I have my own scripts to handle this
  3. Start conversation B and run through it fully
  4. Restart conversation A from the entry following the one where it was interrupted
For context, conversation A is a long conversation between characters. One of the characters can get distracted during the conversation, which is where I want the interrupt to occur. Conversation B would be a small feedback thing like "Hey, are you listening to me?" > "Oh sorry, what were you saying" or something to that effect.


I feel like I nearly have it solved, but I'm missing something and I may be overlooking a better way to do this. This is what I do currently:
  1. DialogueManager.StartConversation() to start conversation A
  2. Save DialogueManager.lastConversationID and DialogueManager.currentConversationState in two variables when interrupting
  3. DialogueManager.StartConversation() to start conversation B
  4. DialogueManager.StartConversation() to start conversation A again, with the previously saved conversation id as a parameter.
Step 4 is where I run into trouble. I'm saving the wrong dialogue entry and am not managing to link through to the correct one.

Below is the test conversation I'm using. Entry 11 is the one that should interrupt the conversation (note the script on it), in the final version it wouldn't have any dialogue text. Entry 12 is where the conversation should resume (pink = PC, grey = NPC).
dialogue_tree.png
dialogue_tree.png (28.02 KiB) Viewed 509 times
Code snippet for stopping conversation (this is triggered from the Lua script in entry 11):

Code: Select all

//save conversation state
_lastConversationState = DialogueManager.currentConversationState;
_lastConversationStarted = DialogueManager.lastConversationStarted;
DialogueManager.StopConversation();
Code snippet for restarting conversation:

Code: Select all

DialogueManager.StartConversation( _lastConversationStarted, null, null, _lastConversationState.PCAutoResponse.destinationEntry.id );
The problem is that _lastConversationState actually saves entry 10, not 11, even though this code is triggered from the script in entry 11. That causes PCAutoReponse to be null. I've tried to run through the chain of linked entries to get to 12 eventually, but I get stuck doing _lastConversationState.FirstNPCResponse.destinationEntry and then can't figure out how to get the follow-up entry from that. But that's already a workaround, if I were saving the correct state (entry 11) I wouldn't need to do this and my code should work, I think.


Sorry for the long post, I've tried to describe the issue in as much detail as possible.

Re: Saving conversation state, interrupting and resuming from the same entry later

Posted: Thu Sep 14, 2023 4:09 pm
by Tony Li
Hi,

Two suggestions:

1. If you know that you might branch to conversation B at entry 11, why not create a cross-conversation link from entry 11 to conversation B? At the end of conversation B, you can link back to entry 12. To make a cross-conversation link, inspect the origin node (e.g., entry 11) and from the "Links To:" dropdown select "(Another Conversation)". This way you don't need to stop and resume conversations.

2. Or, if you want to continue with your current approach, record DialogueManager.currentConversationState.subtitle.dialogueEntry.id:

Code: Select all

//save conversation state
_lastConversationStarted = DialogueManager.lastConversationStarted;
_lastEntryID = DialogueManager.currentConversationState.subtitle.dialogueEntry.id;
DialogueManager.StopConversation();
DialogueManager.StartConversation("Conversation B");'
and:

Code: Select all

DialogueManager.StopConversation();
DialogueManager.StartConversation(_lastConversationStarted, null, null, _lastEntryID);
If you want to resume at entry 12 instead of entry 11, record this:

Code: Select all

//save conversation state
_lastConversationStarted = DialogueManager.lastConversationStarted;
_resumeEntryID = DialogueManager.currentConversationState.firstNPCResponse.destinationEntry.id;
DialogueManager.StopConversation();
DialogueManager.StartConversation("Conversation B");'

Re: Saving conversation state, interrupting and resuming from the same entry later

Posted: Fri Sep 15, 2023 5:25 am
by urrmurrmur
Hi,

The issue is that this:

Code: Select all

_lastEntryID = DialogueManager.currentConversationState.subtitle.dialogueEntry.id;
Doesn't save id 11, it saves 10. Even though it's triggered from entry 11.

This is the inspector for entry 11, it's the function call ShowCrypticSaying("Brood op de plank brengen") which triggers the state save.
dsfu_entry_inspector.png
dsfu_entry_inspector.png (38.53 KiB) Viewed 498 times

Re: Saving conversation state, interrupting and resuming from the same entry later

Posted: Fri Sep 15, 2023 8:14 am
by Tony Li
The Script runs just before setting currentConversationState since the result of the Script may change what happens in the state. Wait until the end of the frame:

Code: Select all

void ShowCrypticSaying(string message)
{
    StartCoroutine(ShowCrypticSayingCoroutine(message);
}

IEnumerator ShowCrypticSayingCoroutine(string message)
{
    yield return new WaitForEndOfFrame(); // Wait for currentConversationState to be valid.
    //save conversation state
    _lastConversationStarted = DialogueManager.lastConversationStarted;
    _lastEntryID = DialogueManager.currentConversationState.subtitle.dialogueEntry.id;
    DialogueManager.StopConversation();
    DialogueManager.StartConversation("Conversation B"); // or message or whatever
}
Alternatively, use the "thisID" Lua variable, which does get set prior to running the Script:

Code: Select all

void ShowCrypticSaying(string message)
{
    //save conversation state
    _lastConversationStarted = DialogueManager.lastConversationStarted;
    _lastEntryID = Lua.Run("return thisID").asInt;
    DialogueManager.StopConversation();
    DialogueManager.StartConversation("Conversation B"); // or message or whatever
}

Re: Saving conversation state, interrupting and resuming from the same entry later

Posted: Fri Sep 15, 2023 8:29 am
by urrmurrmur
Yep, that did it. Similar issue to my previous question then. I'll try to remember it in the future.

Thanks for the help!

Re: Saving conversation state, interrupting and resuming from the same entry later

Posted: Fri Sep 15, 2023 8:32 am
by Tony Li
Glad to help! This one is poorly documented. I'll update the documentation on the Script field to make it clearer.