Scriptum/Assets/Scripts/REFACTORING/Application/NPC/NpcDialogueManager.cs

149 lines
4.8 KiB
C#
Raw Normal View History

2022-12-04 18:42:34 +01:00
using System;
using System.Collections;
using System.Collections.Generic;
using System.Linq;
using UnityEngine;
using UnityEngine.Events;
2022-12-20 03:30:37 +01:00
[RequireComponent(typeof(NPC))]
2022-12-04 18:42:34 +01:00
public class NpcDialogueManager : MonoBehaviour
{
[SerializeField]
public string SpeakerName;
2022-12-04 18:42:34 +01:00
[SerializeField]
2022-12-20 04:37:00 +01:00
public LanguageDetector<MultiDialogue> languageDetector;
2022-12-04 18:42:34 +01:00
/* We user object CLONED TO PREVENT overwritting changes in main object inassets */
[SerializeField]
2022-12-06 21:35:17 +01:00
public MultiDialogue Dialogue;
2022-12-04 18:42:34 +01:00
// List<Key<dialogue No, dialogue step No>, Value : UnityEvent>
public List<IndexValuePair<IndexValuePair<int, int>, UnityEvent>> EndactionEventList;
[SerializeField] public KeyCode keyToOpen = KeyCode.E;
public bool CanBeOpened = false;
/// <summary>
/// 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
/// </summary>
public bool OpenInDefaultWay = true;
2022-12-04 18:42:34 +01:00
public void Start()
{
2022-12-20 04:37:00 +01:00
Dialogue = Instantiate(languageDetector.DetectInstanceBasedOnLanguage());
2022-12-06 21:35:17 +01:00
Dialogue.SetSpeakerName(SpeakerName);
2022-12-20 04:37:00 +01:00
Dialogue.Dialogues.ForEach(dial => dial.Value.SetActionAfterDialogueStep(dial.Key, dial.Value.ResetDialogue)); // reset dial
2022-12-04 18:42:34 +01:00
}
public void Update()
{
if(OpenInDefaultWay && CanBeOpened && !GetCurrentDialoguePanelStatus() && Input.GetKeyDown(keyToOpen))
gameObject.GetComponent<NpcDialogueManager>().Dialogue.StartDialogue();
}
public void OnTriggerEnter2D(Collider2D collision)
{
// don't listen when component is disabled
if (!gameObject.GetComponent<NpcDialogueManager>().enabled)
return;
if (collision.gameObject.tag == "Player")
CheckIfCanBeOpen();
}
public void OnTriggerExit2D(Collider2D collision)
{
// don't listen when component is disabled
if (!gameObject.GetComponent<NpcDialogueManager>().enabled)
return;
if (collision.gameObject.tag == "Player")
{
CanBeOpened = false;
}
}
/// <summary>
/// Opened = 1
/// Closed = 0
/// </summary>
/// <returns></returns>
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<NPC>().State == NPCStateEnum.Talking && !GetCurrentDialoguePanelStatus())
{
CanBeOpened = true;
}
}
2022-12-04 18:42:34 +01:00
/// <summary>
/// Function to invoke actions declared in manager on object from scene not onto asset
///
/// Used in Dialogue ScriptableObject Template
/// </summary>
/// <param name="dialogueIndex"></param>
public void DialogueEndAction(int dialogueIndex)
{
GameObject.FindObjectsOfType<NpcDialogueManager>().Where(obj => obj.name == gameObject.name).First().GetComponent<NpcDialogueManager>().InvokeDialogueEndAction(dialogueIndex);
}
/// <summary>
/// Function to invoke actions declared in manager (on current object)
///
/// Use this to invoke actions which we want to occured after specific Dialogue
/// </summary>
/// <param name="dialogueIndex"></param>
protected void InvokeDialogueEndAction(int dialogueIndex)
{
EndactionEventList.Where(el => el.Key.Key == dialogueIndex).ToList().ForEach(el => el.Value.Invoke());
}
/// <summary>
/// Function to invoke actions declared in manager on object from scene not onto asset
///
/// Used in Dialogue ScriptableObject Template
/// </summary>
public void StepEndAction()
{
GameObject.FindObjectsOfType<NpcDialogueManager>().Where(obj => obj.name == gameObject.name).First().GetComponent<NpcDialogueManager>().InvokeStepEndAction();
}
/// <summary>
/// Function to invoke actions declared in manager (on current object)
///
/// Use this to invoke actions which we want to occured after specific Dialogue Step
/// </summary>
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());
}
}