using System; using System.Collections.Generic; using System.Linq; using System.Text; using System.Threading.Tasks; using UnityEngine; using UnityEngine.Events; [RequireComponent(typeof(NPC))] public class DialogueManager : MonoBehaviour { [SerializeField] public string SpeakerName; [SerializeField] public LanguageDetector languageDetector; /* We user object CLONED TO PREVENT overwritting changes in main object inassets */ [SerializeField] public MultiDialogue Dialogue; // List, Value : UnityEvent> public List, UnityEvent>> EndactionEventList; [SerializeField] public KeyCode keyToOpen = KeyCode.E; public bool CanBeOpened = true; /// /// This flag tell that manager will open dialogue automatically after /// - beeing in collision range /// - when dialogue is closed /// - when Player press KeyToOpen button /// /// Change var status in other sctipt if you want to use other triggers to open dialogue /// public bool OpenInDefaultWay = true; public virtual void Start() { if (languageDetector.InstanceTemplates.Count() > 0) { // create and config dailogue CreateInstanceBasedOnLanguage(); Dialogue.BuildCurrentDialogue(); } } public virtual void Update() { if (OpenInDefaultWay && Input.GetKeyDown(keyToOpen) && OpenPanelCondition()) { if (languageDetector.InstanceTemplates.Count() > 0) { // create and config dailogue CreateInstanceBasedOnLanguage(); Dialogue.BuildCurrentDialogue(); } OpenDialoguePanel(); } } public virtual void OnTriggerEnter2D(Collider2D collision) { // don't listen when component is disabled if (ComponentEnabledCondition()) return; if (collision.gameObject.tag == "Player") { CanBeOpened = true; } } public virtual void OnTriggerExit2D(Collider2D collision) { // don't listen when component is disabled if (ComponentEnabledCondition()) return; if (collision.gameObject.tag == "Player") { CanBeOpened = false; // Shop dont have dialoge in this script but in its own one // TODO change - pass eachd ialogue to this script and use conditions from child class if (Dialogue != null && GetCurrentDialoguePanelStatus()) { Dialogue.BreakDialogueStep(); } } } public virtual 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))); }*/ if(gameObject.GetComponent().Name != null && gameObject.GetComponent().Name != "") { Dialogue.SetSpeakerName(gameObject.GetComponent().Name); } else { Dialogue.SetSpeakerName(PlayerPrefs.GetString("name")); } // Bind setted actions BindEndActionsToDialogues(); // Add one more action - to reset proggress Dialogue.Dialogues.ForEach(dial => dial.Value.SetActionAfterEachDialogueStep(dial.Value.ResetDialogue)); // reset dial } #region Open Panel API public void OpenDialoguePanel() { if(OpenPanelCondition()) { gameObject.GetComponent().Dialogue.StartDialogue(); } } public virtual bool OpenPanelCondition() { /* * Conditions: * - player is in collision range * - panel assigned to next sentence in dialogue must be closed */ return IsInRangeCondition() && !GetCurrentDialoguePanelStatus(); } public bool IsInRangeCondition() { return CanBeOpened; } protected virtual bool ComponentEnabledCondition() { return !gameObject.GetComponent().enabled; } #endregion /// /// Opened = 1 /// Closed = 0 /// /// public virtual bool GetCurrentDialoguePanelStatus() { var multiDialStatius = Dialogue.DialogueStepStatus(); // parse result (dialoge no, step no) // dialogue not exist - finished // dialoge exists & step no > steps sum - finished // dialoge no exists && step no exists - not finished - check panel status if(!Dialogue.Dialogues.Where(dial => dial.Key == multiDialStatius.Item1).Any()) return false; var fixedDialogue = Dialogue.Dialogues.Where(dial => dial.Key == multiDialStatius.Item1).First().Value; if (fixedDialogue.CurrentStep >= fixedDialogue.DialogueSteps.Count()) return false; // CONTINUE dont increment counter - only mark checkboxes if (fixedDialogue .DialogueSteps .Where(step => step.WasDisplayed == false) .ToArray() .Count() == 0) return false; // when we are here we can be sure given points are correct return Dialogue .Dialogues .Where(dialogue => dialogue.Key == multiDialStatius.Item1) .First() .Value .DialogueSteps .ElementAtOrDefault(multiDialStatius.Item2) .DialogueController.CurrentPanel != null; } public void BindEndActionsToDialogues() { foreach(var finalAction in EndactionEventList) { // finalAction.Key.Key | .Value/ Dialogue .Dialogues .Where(dial => dial.Key == finalAction.Key.Key) .FirstOrDefault() .Value .DialogueSteps .ElementAtOrDefault(finalAction.Key.Value) .SetActionAfterDialogueStep(finalAction.Value) ; } } }