using Jovian.EncounterSystem; using Nox.Game.UI; using System; using System.Collections.Generic; using System.Linq; using UnityEngine; namespace Nox.Game { public class EncounterView : IMenuView { private const int MaxAnswers = 4; private readonly EncounterPrefabs encounterPrefabs; private readonly Dictionary kindToReference = new(); private readonly Dictionary> kindToAnswerPool = new(); private IEncounter currentEncounter; private EncounterReference currentReference; private List currentAnswerPool; public event Action OptionSelected; public EncounterView(EncounterPrefabs encounterPrefabs) { this.encounterPrefabs = encounterPrefabs; } public void SetCurrentEncounter(IEncounter encounter) { currentEncounter = encounter; } public void Initialize() { } public void Show() { if(currentEncounter?.EncounterDefinition?.Kind == null) { return; } if(currentReference) { currentReference.gameObject.SetActive(false); } var kindType = currentEncounter.EncounterDefinition.Kind.GetType(); var set = encounterPrefabs.encounterSets .FirstOrDefault(s => s.encounterKind != null && s.encounterKind.GetType() == kindType); if(set == null || !set.encounterReference) { return; } if(!kindToReference.TryGetValue(kindType, out var reference) || !reference) { reference = UnityEngine.Object.Instantiate(set.encounterReference); kindToReference[kindType] = reference; } currentReference = reference; currentAnswerPool = GetOrBuildAnswerPool(kindType, set); PopulateEncounterReference(); currentReference.gameObject.SetActive(true); } public void Hide() { if(currentReference) { currentReference.gameObject.SetActive(false); } DeactivateAnswers(currentAnswerPool); } public void Tick() { } private List GetOrBuildAnswerPool(Type kindType, EncounterSet set) { if(kindToAnswerPool.TryGetValue(kindType, out var pool) && pool != null) { return pool; } pool = new List(MaxAnswers); kindToAnswerPool[kindType] = pool; if(!set.answerReference || !currentReference.encounterOptionsContainer) { return pool; } for(var i = 0; i < MaxAnswers; i++) { var answer = UnityEngine.Object.Instantiate(set.answerReference, currentReference.encounterOptionsContainer); answer.gameObject.SetActive(false); pool.Add(answer); } return pool; } private void PopulateEncounterReference() { var definition = currentEncounter.EncounterDefinition; var visuals = currentEncounter.EncounterVisuals; if(currentReference.encounterName) { currentReference.encounterName.text = definition.name; } if(currentReference.encounterDescription) { currentReference.encounterDescription.text = definition.description; } if(currentReference.encounterArt && visuals != null) { currentReference.encounterArt.sprite = visuals.encounterArt; } PopulateAnswers(); } private void PopulateAnswers() { DeactivateAnswers(currentAnswerPool); var optionSet = currentEncounter.EncounterDialogOptionSet; if(currentAnswerPool == null || optionSet?.options == null) { return; } var count = Mathf.Min(optionSet.options.Count, currentAnswerPool.Count); for(var i = 0; i < count; i++) { var option = optionSet.options[i]; var answer = currentAnswerPool[i]; if(option == null || !answer) { continue; } if(answer.number) { answer.number.text = (i + 1).ToString(); } if(answer.dialogText) { answer.dialogText.text = option.text.Resolve(optionSet.library); } BindAnswerButton(answer, i); answer.gameObject.SetActive(true); } } private void BindAnswerButton(AnswerReference answer, int optionIndex) { var button = answer.button ? answer.button : answer.GetComponentInChildren(true); if(!button) { return; } button.onClick.RemoveAllListeners(); button.onClick.AddListener(() => OptionSelected?.Invoke(optionIndex)); } private static void DeactivateAnswers(List pool) { if(pool == null) { return; } for(var i = 0; i < pool.Count; i++) { if(pool[i]) { pool[i].gameObject.SetActive(false); } } } public void Dispose() { foreach(var reference in kindToReference.Values) { if(reference) { UnityEngine.Object.Destroy(reference.gameObject); } } kindToReference.Clear(); kindToAnswerPool.Clear(); currentReference = null; currentAnswerPool = null; currentEncounter = null; OptionSelected = null; } } }