// Copyright (c) Pixel Crushers. All rights reserved. using UnityEngine; using System; using System.Collections.Generic; namespace PixelCrushers.DialogueSystem { /// /// Add this script to your Dialogue Manager to keep track of the /// current conversation and dialogue entry. When you load a game, /// it will resume the conversation at that point. /// [AddComponentMenu("")] // Use wrapper. public class ConversationStateSaver : Saver { [Serializable] public class Data { public int conversationID; public int entryID; public string actorName; public string conversantName; public List actorGOs = null; public List actorGOPanels = null; public List actorIDs = null; public List actorIDPanels = null; public List panelOpenOnActorName = null; public string accumulatedText; } /// /// Override to make default key value "ConversationState". /// public override string key { get { if (string.IsNullOrEmpty(m_runtimeKey)) { m_runtimeKey = !string.IsNullOrEmpty(_internalKeyValue) ? _internalKeyValue : "ConversationState"; if (appendSaverTypeToKey) { var typeName = GetType().Name; if (typeName.EndsWith("Saver")) typeName.Remove(typeName.Length - "Saver".Length); m_runtimeKey += typeName; } } return m_runtimeKey; } set { _internalKeyValue = value; m_runtimeKey = value; } } public override string RecordData() { if (!DialogueManager.isConversationActive) return string.Empty; var data = new Data(); var state = DialogueManager.currentConversationState; var entry = state.subtitle.dialogueEntry; data.conversationID = entry.conversationID; data.entryID = state.subtitle.dialogueEntry.id; data.actorName = (DialogueManager.currentActor != null) ? DialogueManager.currentActor.name : string.Empty; data.conversantName = (DialogueManager.currentConversant != null) ? DialogueManager.currentConversant.name : string.Empty; var ui = DialogueManager.dialogueUI as StandardDialogueUI; if (ui != null) { ui.conversationUIElements.standardSubtitleControls.RecordActorPanelCache(out data.actorGOs, out data.actorGOPanels, out data.actorIDs, out data.actorIDPanels, out data.panelOpenOnActorName); data.accumulatedText = string.Empty; for (int i = 0; i < ui.conversationUIElements.subtitlePanels.Length; i++) { var subtitlePanel = ui.conversationUIElements.subtitlePanels[i]; if (!subtitlePanel.isOpen && 0 <= i && i < data.panelOpenOnActorName.Count) { data.panelOpenOnActorName[i] = null; } if (subtitlePanel.isOpen && subtitlePanel.accumulateText) { data.accumulatedText = subtitlePanel.accumulatedText; break; } } } return SaveSystem.Serialize(data); } public override void ApplyData(string s) { if (!enabled || string.IsNullOrEmpty(s)) return; var data = SaveSystem.Deserialize(s); if (data == null) return; StartCoroutine(StartSavedConversation(data)); } protected System.Collections.IEnumerator StartSavedConversation(Data data) { var dialogueUI = DialogueManager.dialogueUI as StandardDialogueUI; DialogueManager.StopConversation(); if (dialogueUI != null) { float safeguardTimeout = Time.realtimeSinceStartup + 5f; while (dialogueUI.isOpen && Time.realtimeSinceStartup < safeguardTimeout) { yield return null; } } var conversationID = data.conversationID; var entryID = data.entryID; var conversation = DialogueManager.masterDatabase.GetConversation(conversationID); var actorName = DialogueLua.GetVariable("CurrentConversationActor").AsString; var conversantName = DialogueLua.GetVariable("CurrentConversationConversant").AsString; if (DialogueDebug.logInfo) Debug.Log("Dialogue System: ConversationStateSaver is resuming conversation " + conversation.Title + " with actor=" + actorName + " and conversant=" + conversantName + " at entry " + entryID + ".", this); var actor = string.IsNullOrEmpty(actorName) ? null : GameObject.Find(actorName); var conversant = string.IsNullOrEmpty(conversantName) ? null : GameObject.Find(conversantName); var actorTransform = (actor != null) ? actor.transform : null; var conversantTransform = (conversant != null) ? conversant.transform : null; var ui = DialogueManager.dialogueUI as StandardDialogueUI; if (ui != null) { ui.conversationUIElements.standardSubtitleControls.QueueSavedActorPanelCache(data.actorGOs, data.actorGOPanels, data.actorIDs, data.actorIDPanels); } DialogueManager.StartConversation(conversation.Title, actorTransform, conversantTransform, entryID); if (ui != null) { for (int i = 0; i < ui.conversationUIElements.subtitlePanels.Length; i++) { var subtitlePanel = ui.conversationUIElements.subtitlePanels[i]; if (0 <= i && i < data.panelOpenOnActorName.Count && !string.IsNullOrEmpty(data.panelOpenOnActorName[i])) { var panelActorTransform = CharacterInfo.GetRegisteredActorTransform(data.panelOpenOnActorName[i]); var dialogueActor = (panelActorTransform != null) ? panelActorTransform.GetComponent() : null; var panelActor = DialogueManager.masterDatabase.GetActor(data.panelOpenOnActorName[i]); Sprite portraitSprite = panelActor.GetPortraitSprite(); string portraitName = data.panelOpenOnActorName[i]; if (dialogueActor != null) { var dialogueActorSprite = dialogueActor.GetPortraitSprite(); if (dialogueActorSprite != null) portraitSprite = dialogueActorSprite; portraitName = dialogueActor.GetActorName(); } else if (panelActor != null) { portraitSprite = panelActor.GetPortraitSprite(); portraitName = CharacterInfo.GetLocalizedDisplayNameInDatabase(portraitName); } subtitlePanel.OpenOnStartConversation(portraitSprite, portraitName, dialogueActor); } if (subtitlePanel.accumulateText) { subtitlePanel.accumulatedText = data.accumulatedText; } } } } } }