using System; using System.Collections; using System.Collections.Generic; using System.Linq; using UnityEngine; using UnityEngine.Events; [RequireComponent(typeof(NPC))] public class NpcDialogueManager : DialogueManager { public override void Start() { //base.Start(); CanBeOpened = false; OpenInDefaultWay = false; if (languageDetector.InstanceTemplates.Count() > 0) { // create and config dailogue CreateInstanceBasedOnLanguage(); Dialogue.BuildCurrentDialogue(); } // UPDATE DIALOGUE // search in scene manager list if (Dialogue != null) { var machedDialogueData = ((MultiDialogueDataManager)MultiDialogueDataManager.Instance).GetDialogue(Dialogue); if (machedDialogueData != null) { UpdateDialogueState(machedDialogueData); } else { UpdateProggres(); } } } public override void Update() { if (Input.GetKeyDown(keyToOpen) && OpenPanelCondition()) { // Refrsh dialogue language and proggres after each opening trial if (languageDetector.InstanceTemplates.Count() > 0) { // create and config dailogue CreateInstanceBasedOnLanguage(); Dialogue.BuildCurrentDialogue(); } // UPDATE DIALOGUE // search in scene manager list if (Dialogue != null) { var machedDialogueData = ((MultiDialogueDataManager)MultiDialogueDataManager.Instance).GetDialogue(Dialogue); if (machedDialogueData != null) { UpdateDialogueState(machedDialogueData); } else { UpdateProggres(); } } OpenDialoguePanel(); } } #region Open Panel API public override bool OpenPanelCondition() { /* * Conditions: * - npc bust me in Talking mode * - player is in collision range * - panel assigned to next sentence in dialogue must be closed */ return gameObject.GetComponent().State == NPCStateEnum.Talking && base.OpenPanelCondition(); } protected virtual bool ColliderTypeCondition() { return !gameObject.GetComponent().enabled; } #endregion public override void CreateInstanceBasedOnLanguage() { // DONT CLONE TO HAVE CONSTANT DATA - init - deep copy - to prevent overwritting chil;dern :D Dialogue = languageDetector.DetectInstanceBasedOnLanguage(); Dialogue.ResetDialogue(); /* var cloneDialogues = new List>(Dialogue.Dialogues); Dialogue.Dialogues.Clear(); foreach (var dial in cloneDialogues) { Dialogue.Dialogues.Add(new IndexValuePair(dial.Key, Instantiate(dial.Value))); }*/ Dialogue.SetSpeakerName(gameObject.GetComponent().Name); // Bind setted actions BindEndActionsToDialogues(); // update dial state - sync in order to prepare to save Dialogue.Dialogues.ForEach(dial => dial.Value.SetActionAfterEachDialogueStep(UpdateProggres)); } public void UpdateDialogueState(MultiDialogueData dialogueData) { // 1 Rule - speaker name shouldnt change !!! its our 'key' Dialogue.CurrentDialogue = dialogueData.CurrentDialogue; foreach(var singleDialogue in dialogueData.DialogueStepModelDataList) { Dialogue.Dialogues .Where(dial => dial.Key == singleDialogue.Key) .Select(dial => dial.Value) .ToList() .ForEach(dial => dial.UpdateDialogueState(singleDialogue.Value) ); } } /// /// Function to sync local dialogue state with remote one /// Handled in Scene Manager /// public void UpdateProggres() { ((MultiDialogueDataManager)MultiDialogueDataManager.Instance).RegisterDialogue(Dialogue); } #region Dialogue actions API /// /// Function to invoke actions declared in manager on object from scene not onto asset /// /// Used in Dialogue ScriptableObject Template /// /// public void DialogueEndAction(int dialogueIndex) { GameObject.FindObjectsOfType().Where(obj => obj.name == gameObject.name).First().GetComponent().InvokeDialogueEndAction(dialogueIndex); } /// /// Function to invoke actions declared in manager (on current object) /// /// Use this to invoke actions which we want to occured after specific Dialogue /// /// protected void InvokeDialogueEndAction(int dialogueIndex) { EndactionEventList.Where(el => el.Key.Key == dialogueIndex).ToList().ForEach(el => el.Value.Invoke()); } /// /// Function to invoke actions declared in manager on object from scene not onto asset /// /// Used in Dialogue ScriptableObject Template /// public void StepEndAction() { GameObject.FindObjectsOfType().Where(obj => obj.name == gameObject.name).First().GetComponent().InvokeStepEndAction(); } /// /// Function to invoke actions declared in manager (on current object) /// /// Use this to invoke actions which we want to occured after specific Dialogue Step /// protected void InvokeStepEndAction() { var dialogueProgress = Dialogue.DialogueStepStatus(); EndactionEventList.Where(el => el.Key.Key == dialogueProgress.Item1 & el.Key.Value == dialogueProgress.Item2).ToList().ForEach(el => el.Value.Invoke()); } #endregion }