forked from Shardstone/trail-into-darkness
168 lines
5.7 KiB
C#
168 lines
5.7 KiB
C#
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<Type, EncounterReference> kindToReference = new();
|
|
private readonly Dictionary<Type, List<AnswerReference>> kindToAnswerPool = new();
|
|
|
|
private IEncounter currentEncounter;
|
|
private EncounterReference currentReference;
|
|
private List<AnswerReference> currentAnswerPool;
|
|
|
|
public event Action<int> 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() { }
|
|
|
|
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;
|
|
}
|
|
|
|
private List<AnswerReference> GetOrBuildAnswerPool(Type kindType, EncounterSet set) {
|
|
if(kindToAnswerPool.TryGetValue(kindType, out var pool) && pool != null) {
|
|
return pool;
|
|
}
|
|
|
|
pool = new List<AnswerReference>(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<UnityEngine.UI.Button>(true);
|
|
if(!button) {
|
|
return;
|
|
}
|
|
button.onClick.RemoveAllListeners();
|
|
button.onClick.AddListener(() => OptionSelected?.Invoke(optionIndex));
|
|
}
|
|
|
|
private static void DeactivateAnswers(List<AnswerReference> pool) {
|
|
if(pool == null) {
|
|
return;
|
|
}
|
|
for(var i = 0; i < pool.Count; i++) {
|
|
if(pool[i]) {
|
|
pool[i].gameObject.SetActive(false);
|
|
}
|
|
}
|
|
}
|
|
}
|
|
}
|