using System; using System.Collections.Generic; using System.Linq; using UnityEngine; [Serializable] [CreateAssetMenu(fileName = "New Dialogue", menuName = "Dialogue/New Multi Dialogue")] public class MultiDialogue : ScriptableObject, IDialogue { [SerializeField] public string SpeakerName; [SerializeField] public int CurrentDialogue = 0; [SerializeField] public List> Dialogues; /* Dialogues - list of dialoges Steps bucket (one dialogue unit) - list of liner 'steps', finished special action, whole can be stopped special requirements (like go and do something - to declared in 'finish action') Steps - its a cell package contains 'sentences' (one per panel) Sentence - its a opanel with phrase and buttons */ /* * WAZNE: * Jesli przechodzimy odpowiedzia do nastepnego dialogu musi to byc osttani panel w obecnym!!! */ public void SetSpeakerName(string speakerName) { SpeakerName = speakerName; Dialogues.ForEach(dialogue => dialogue.Value.SetSpeakerName(speakerName)); } public void StartDialogue() { // 1. Start Dialogue (build + show panel) Dialogues.Where(el => el.Key == CurrentDialogue).First().Value.StartDialogue(); } public void BreakDialogueStep() { // 1. Break Dialogue (close panel without marking as displayed) Dialogues.Where(el => el.Key == CurrentDialogue).ToArray().First().Value.BreakDialogueStep(); } /// /// Dialogue API /// /// MAIN bunction to begin dialogue /// Create new panel instance on scene by force with sentence from queue /// /// The best way is to invoked its after player reaction from other script (by event - collision) :) /// public void ShowDialogueStepPanel() { Dialogues.Where(el => el.Key == CurrentDialogue).ToArray().First().Value.ShowDialogueStepPanel(); } /// /// Dialogue API /// /// Default function to get next sentence if dialogue is currently started /// It is responsible for detecting /// 1) if there is any dialogue panel already created before displaying next sentence /// 2) if its last panel sentence and invoiking 'end dialogue' action /// /// Whats more, if there was no more sentences in 'step', althroughr closing panel go to next step automatiiccally /// public void GoToNextSentence() { Dialogues.Where(el => el.Key == CurrentDialogue).ToArray().First().Value.GoToNextSentence(); } /// /// Dialogue API /// /// Function to prepare next dialogue to start after one more palyer interaction with actor /// - ends current dialogue (destroy panel & invoke finish action!! - if setupped) /// - set new dialogue pointer /// /// /// public void SetNextDialogue(int dialogueNumber) { if (Dialogues.Where(el => el.Key == dialogueNumber).ToArray().Count() == 0) return; // 1. Make sure to close current panel after finishing current dialogue and 'finish action' will invoked if setuped Dialogues.Where(el => el.Key == CurrentDialogue).ToArray().First().Value.FinishDialogue(); // 2. Chane index CurrentDialogue = dialogueNumber; } public void SetNextDialogueWithoutFinalAction(int dialogueNumber) { if (Dialogues.Where(el => el.Key == dialogueNumber).ToArray().Count() == 0) return; // 1. Make sure to close current panel after finishing current dialogue and 'finish action' will invoked if setuped Dialogues.Where(el => el.Key == CurrentDialogue).ToArray().First().Value.CloseDialogue(); // 2. Chane index CurrentDialogue = dialogueNumber; } /// /// Dialogue API /// /// Function to finish current dialog and immediately start next one /// /// /// public void GoToNextDialogue(int dialogueNumber) { // 1. Prepare necessary environoment parts SetNextDialogue(dialogueNumber); // 2. Update proggress // Savintg one more time because saving in final action invoking by line above // dont contain increased 'CurrentDialogue' index pointer !!! //((MultiDialogueDataManager)MultiDialogueDataManager.Instance).RegisterDialogue(this); // 3. Build new (next) dialogue & show panel StartDialogue(); } /// /// Function like one above but /// PREFPARED AS FINAL ACTION IN DIALOGUE WHICH IS INVOKED VIA 'Dialogue.FinishDialoge' /// to prevent looping Final aCTION INVOKING /// once from 'Dialogue.FinishDialoge' in button next time from 'MultiDialogue.SetNextDialogue -> FinishDialogue' .... /// /// public void GoToNextDialogueWithoutFinalAction(int dialogueNumber) { // 1. Prepare necessary environoment parts SetNextDialogueWithoutFinalAction(dialogueNumber); // 2. Update proggress //((MultiDialogueDataManager)MultiDialogueDataManager.Instance).RegisterDialogue(this); // 3. Build new (next) dialogue & show panel StartDialogue(); } // MUST BE IMPLEMENTED - INTERFACE RULES // USELESS IN THIS FILE public void BuildDialogue(List Dialogue) { foreach (var dialogueStep in Dialogue) { dialogueStep.Header = SpeakerName; dialogueStep.Build(); } } /// /// Build each step of dialogue /// public void BuildDialogue(Dialogue Dialogue) { Dialogue.SetSpeakerName(SpeakerName); Dialogue.BuildDialogue(); } public void BuildCurrentDialogue() { BuildDialogue(Dialogues.Where(dial => dial.Key == CurrentDialogue).ToArray().First().Value); } /// /// Function to reset rememebered dialogue status /// /// (Scriptable objects clones are overwritten during clone modification) /// public void ResetDialogue() { SpeakerName = ""; CurrentDialogue = 0; Dialogues.ForEach(dial => dial.Value.SetSpeakerName("")); Dialogues.ForEach(dial => dial.Value.CurrentStep = 0); Dialogues.ForEach(dial => dial.Value.DialogueSteps.ForEach(step => step.WasDisplayed = false)); } public (int, int) DialogueStepStatus() { /* var currentStep = Dialogues .Where(el => el.Key == CurrentDialogue) .Select(el => el.Value) .First() .CurrentStep ;*/ var currentDialogueStepIndex = Dialogues .Where(el => el.Key == CurrentDialogue) .Select(el => el.Value) .First() .DialogueSteps .Where(step => step.WasDisplayed == true) .ToArray() .Count() ; return(CurrentDialogue, currentDialogueStepIndex); } }