using System; using System.Collections; using System.Collections.Generic; using System.Linq; using UnityEngine; using UnityEngine.Events; [RequireComponent(typeof(NPC))] public class NpcDialogueManager : 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 = false; /// /// 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 void Start() { Dialogue = Instantiate(languageDetector.DetectInstanceBasedOnLanguage()); Dialogue.SetSpeakerName(SpeakerName); Dialogue.Dialogues.ForEach(dial => dial.Value.SetActionAfterDialogueStep(dial.Key, dial.Value.ResetDialogue)); // reset dial } public void Update() { if(OpenInDefaultWay && CanBeOpened && !GetCurrentDialoguePanelStatus() && Input.GetKeyDown(keyToOpen)) gameObject.GetComponent().Dialogue.StartDialogue(); } public void OnTriggerEnter2D(Collider2D collision) { // don't listen when component is disabled if (!gameObject.GetComponent().enabled) return; if (collision.gameObject.tag == "Player") CheckIfCanBeOpen(); } public void OnTriggerExit2D(Collider2D collision) { // don't listen when component is disabled if (!gameObject.GetComponent().enabled) return; if (collision.gameObject.tag == "Player") { CanBeOpened = false; } } /// /// Opened = 1 /// Closed = 0 /// /// public bool GetCurrentDialoguePanelStatus() { var multiDialStatius = Dialogue.DialogueStepStatus(); return Dialogue .Dialogues .Where(dialogue => dialogue.Key == multiDialStatius.Item1) .First() .Value .DialogueSteps[multiDialStatius.Item2].DialogueController.CurrentPanel != null; } public void CheckIfCanBeOpen() { /* * Conditions: * - agent in collision must be player * - npc bust me in Talking mode * - panel assigned to next sentence in dialogue must be closed */ if(gameObject.GetComponent().State == NPCStateEnum.Talking && !GetCurrentDialoguePanelStatus()) { CanBeOpened = true; } } /// /// 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()); } }