Scriptum/Assets/Scripts/REFACTORING/Application/Dialogue/Dialogue.cs
2023-01-03 22:44:24 +01:00

318 lines
8.9 KiB
C#

using System;
using System.Collections.Generic;
using System.Linq;
using UnityEditor;
using UnityEngine;
using UnityEngine.Events;
[Serializable]
[CreateAssetMenu(fileName = "New Dialogue", menuName = "Dialogue/New Dialogue")]
public class Dialogue : ScriptableObject, IDialogue
{
[SerializeField]
public string SpeakerName;
[SerializeField]
public int CurrentStep = 0;
[SerializeField]
public List<DialogueStepModel> DialogueSteps;
public void SetSpeakerName(string speakerName)
{
SpeakerName = speakerName;
DialogueSteps.ForEach(step => step.Header = speakerName);
}
#region finish action api
public void SetActionAfterEachDialogueStep(UnityEvent _endOfDialogueStepAction)
{
foreach(var dialogueStep in DialogueSteps)
{
dialogueStep.SetActionAfterDialogueStep(_endOfDialogueStepAction);
}
}
public void SetActionAfterEachDialogueStep(Action _finishDialogueAction)
{
foreach (var dialogueStep in DialogueSteps)
{
dialogueStep.SetActionAfterDialogueStep(_finishDialogueAction);
}
}
public void SetActionAfterDialogueStep(int dialogueStepNo, UnityEvent _endOfDialogueStepAction)
{
if(DialogueSteps.Count >= dialogueStepNo)
DialogueSteps[dialogueStepNo].SetActionAfterDialogueStep(_endOfDialogueStepAction);
}
public void SetActionAfterDialogueStep(int dialogueStepNo, Action _finishDialogueAction)
{
/* Debug.Log(dialogueStepNo); */
if (DialogueSteps.Count >= dialogueStepNo)
DialogueSteps[dialogueStepNo].SetActionAfterDialogueStep(_finishDialogueAction);
}
#endregion
#region dialogue displaying api
public void StartDialogue()
{
// 1. Build
BuildDialogue(DialogueSteps);
// 2. Show first step
ShowDialogueStepPanel();
}
public void BreakDialogueStep()
{
foreach (var DialogueStep in DialogueSteps)
{
if (!DialogueStep.WasDisplayed && DialogueStep.DialogueController.CurrentPanel != null)
{
DialogueStep.DialogueController.CloseCurrentPanel(); // close panel
break;
}
}
}
/// <summary>
/// Function to
/// - close panel
/// - INVOKE FINAL DIALOGUE ACTION
/// - mark as dispalyed
/// - increasing step number
///
/// Dont invoke final action!!!
/// </summary>
public void FinishDialogue()
{
foreach (var DialogueStep in DialogueSteps)
{
if (!DialogueStep.WasDisplayed)
{
// status must be changes before invoked final action - example - updating state
DialogueStep.WasDisplayed = true;
CurrentStep++;
DialogueStep.DialogueController.FinishCurrentDialogue(DialogueStep.DialogueController);
break;
}
}
}
/// <summary>
/// Function to
/// - close panel
/// - mark as dispalyed
/// - increasing step number
///
/// Dont invoke final action!!!
/// </summary>
public void CloseDialogue()
{
foreach (var DialogueStep in DialogueSteps)
{
if (!DialogueStep.WasDisplayed)
{
DialogueStep.WasDisplayed = true;
CurrentStep++;
DialogueStep.DialogueController.CloseCurrentPanel(DialogueStep.DialogueController);
break;
}
}
}
/// <summary>
/// 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) :)
/// </summary>
public void ShowDialogueStepPanel()
{
foreach (var DialogueStep in DialogueSteps)
{
if (!DialogueStep.WasDisplayed && DialogueStep.DialogueController.listOfDialogue.Count != 0)
{
DialogueStep.DialogueController.Show(DialogueStep.DialogueController.listOfDialogue.Dequeue()); // create panel
break;
}
}
}
/// <summary>
/// Show next sentence ONLY in the same step
///
/// Return next panel status ponly for first faounded not displayed dialogue step
///
/// TODO change name this function and one below - but this break buttons with this action assigned
///
/// It would be much safer if function were return int not void bu unity event dont allow to bind methods in that scenario
/// </summary>
/// <returns></returns>
public void ShowNextPanel()
{
// we dont use foreach and "was displayed" condition because ther is DATA LEAK
// MISLEADING - last sentence mark step ad "wasDisplayed" but not increase "CurrentPanel" index
var currentStep = GetCurrentStep();
var nextSentenceIndex = currentStep.DialogueController.ShowNextPanel(currentStep.DialogueController);
if (!nextSentenceIndex)
{
CurrentStep++;
Debug.Log($"Increase - {CurrentStep}");
}
//return nextSentenceIndex;
}
/// <summary>
/// Dialogue API
///
/// Function to automaticly go to next dialgue sentence (in this or next step eg after pressing button on panel
/// It provide that dialogue not braking after finishing current step
///
/// The dialogue follows the order of the lists ! !
///
/// It's 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
/// </summary>
public void GoToNextSentence()
{
// wskazujemy na inny krok kolejno niz nieoznaczony
// MISLEADING - last sentence mark step ad "wasDisplayed" but not increase "CurrentPanel" index
foreach (var DialogueStep in DialogueSteps)
{
if (!DialogueStep.WasDisplayed)
{
var nextSentence = DialogueStep.DialogueController.ShowNextPanel(DialogueStep.DialogueController);
if (!nextSentence)
{
DialogueStep.WasDisplayed = true;
CurrentStep++;
ShowDialogueStepPanel();
}
break;
}
}
}
#endregion
public void InvokeFinalAction()
{
foreach (var DialogueStep in DialogueSteps)
{
if (!DialogueStep.WasDisplayed)
{
DialogueStep.DialogueController.FinishDialoguStep();
break;
}
}
}
public void BuildDialogue()
{
BuildDialogue(DialogueSteps);
}
/// <summary>
/// Function to build each step of dialogue
/// </summary>
public void BuildDialogue(List<DialogueStepModel> Dialogue)
{
foreach (var dialogueStep in Dialogue)
{
dialogueStep.Header = SpeakerName;
dialogueStep.Build();
// synchronize current step counter
// cause ERROR - multi counting ....
}
}
#region Dialogue Status API
/// <summary>
/// Function to reset rememebered dialogue status
///
/// (Scriptable objects clones are overwritten during clone modification)
/// </summary>
public void ResetDialogue()
{
CurrentStep = 0;
DialogueSteps.ForEach(step => step.WasDisplayed = false);
}
public virtual void UpdateDialogueState(DialogueData dialogueData)
{
// 1 Rule - speaker name shouldnt change !!! its our 'key'
CurrentStep = dialogueData.CurrentStep;
for(int i=0; i < dialogueData.DialogueStepModelDataList.Count; i++)
{
DialogueSteps[i].WasDisplayed = dialogueData.DialogueStepModelDataList[i].WasDisplayed;
}
}
#endregion
public DialogueStepModel? GetCurrentStep()
{// TODO - argument out of colection :/
var currentStep = DialogueSteps.ElementAtOrDefault(CurrentStep);
if (currentStep != null && currentStep.WasDisplayed && CurrentStep < DialogueSteps.Count)
CurrentStep++;
return DialogueSteps.Count > CurrentStep ? DialogueSteps[CurrentStep] : null;
}
/* public DialogueStepModel GetCurrentStep()
{
foreach (var DialogueStep in DialogueSteps)
{
Debug.Log("-" + DialogueStep.DialogueController.listOfDialogue.Count);
if (!DialogueStep.WasDisplayed && DialogueStep.DialogueController.listOfDialogue.Count != 0)
{
return DialogueStep;
}
}
return null;
}*/
}