forked from Shardstone/trail-into-darkness
164 lines
5.8 KiB
C#
164 lines
5.8 KiB
C#
using Jovian.Logger;
|
|
using System.Collections.Generic;
|
|
using Jovian.PopupSystem;
|
|
using Nox.UI;
|
|
using UnityEngine;
|
|
using Object = UnityEngine.Object;
|
|
|
|
namespace Nox.Game.UI {
|
|
public class PartyGuiView {
|
|
private readonly Transform portraitsContainer;
|
|
private readonly PartyMemberSlot slotPrefab;
|
|
private readonly PortraitsHolder portraitsHolder;
|
|
private readonly IPopupSystem popupSystem;
|
|
private readonly List<PartyMemberSlot> activeSlots = new();
|
|
|
|
private PartyDefinition trackedParty;
|
|
private int trackedMemberCount;
|
|
|
|
public PartyGuiView(Transform portraitsContainer, PartyMemberSlot slotPrefab, PortraitsHolder portraitsHolder, IPopupSystem popupSystem = null) {
|
|
this.portraitsContainer = portraitsContainer;
|
|
this.slotPrefab = slotPrefab;
|
|
this.portraitsHolder = portraitsHolder;
|
|
this.popupSystem = popupSystem;
|
|
}
|
|
|
|
public void Initialize(PartyDefinition party) {
|
|
trackedParty = party;
|
|
trackedMemberCount = 0;
|
|
RebuildSlots();
|
|
}
|
|
|
|
public void Tick() {
|
|
if(trackedParty == null) {
|
|
return;
|
|
}
|
|
|
|
// Rebuild if member count changed
|
|
if(trackedParty.members.Count != trackedMemberCount) {
|
|
RebuildSlots();
|
|
}
|
|
|
|
// Update dynamic values (health, mana)
|
|
for(int i = 0; i < activeSlots.Count && i < trackedParty.members.Count; i++) {
|
|
var member = trackedParty.members[i];
|
|
var slot = activeSlots[i];
|
|
UpdateSlotStats(slot, member);
|
|
}
|
|
}
|
|
|
|
private void RebuildSlots() {
|
|
// Clear existing
|
|
foreach(var slot in activeSlots) {
|
|
Object.Destroy(slot.gameObject);
|
|
}
|
|
activeSlots.Clear();
|
|
|
|
if(trackedParty?.members == null) {
|
|
return;
|
|
}
|
|
|
|
trackedMemberCount = trackedParty.members.Count;
|
|
|
|
foreach(var member in trackedParty.members) {
|
|
var slot = Object.Instantiate(slotPrefab, portraitsContainer);
|
|
slot.gameObject.SetActive(true);
|
|
|
|
// Portrait
|
|
if(portraitsHolder != null && portraitsHolder.portraits.Length > 0) {
|
|
var idx = Mathf.Clamp(member.PortraitIndex, 0, portraitsHolder.portraits.Length - 1);
|
|
slot.portrait.sprite = portraitsHolder.portraits[idx];
|
|
}
|
|
|
|
UpdateSlotStats(slot, member);
|
|
activeSlots.Add(slot);
|
|
}
|
|
|
|
// Initialize all popup triggers under the container
|
|
popupSystem?.InitializeTriggersInChildren(portraitsContainer, (trigger, view) => {
|
|
var slot = trigger.GetComponentInParent<PartyMemberSlot>();
|
|
if(slot == null) {
|
|
return;
|
|
}
|
|
var slotIndex = activeSlots.IndexOf(slot);
|
|
if(slotIndex < 0 || slotIndex >= trackedParty.members.Count) {
|
|
return;
|
|
}
|
|
var member = trackedParty.members[slotIndex];
|
|
view.SetContent(builder => BuildCharacterPopup(builder, member));
|
|
});
|
|
}
|
|
|
|
private void BuildCharacterPopup(PopupContentBuilder builder, CharacterDefinition member) {
|
|
// Header
|
|
builder
|
|
.AddHeader(member.Name)
|
|
.AddText($"{member.Race} {member.Class}", "#CCCCCC")
|
|
.AddText($"Role: {member.Role}")
|
|
.AddSeparator();
|
|
|
|
// Stats
|
|
if(member.Stats?.stats != null) {
|
|
foreach(var stat in member.Stats.stats) {
|
|
if(stat.stat == StatType.None) {
|
|
continue;
|
|
}
|
|
builder.AddStat(stat.stat.ToString(), stat.value);
|
|
}
|
|
}
|
|
builder.AddSeparator();
|
|
|
|
// Attributes
|
|
if(member.Attributes?.attributes != null) {
|
|
foreach(var attr in member.Attributes.attributes) {
|
|
if(attr.attribute == AttributeType.None) {
|
|
continue;
|
|
}
|
|
builder.AddStat(attr.attribute.ToString(), attr.value);
|
|
}
|
|
}
|
|
builder.AddSeparator();
|
|
|
|
// Perks
|
|
if(member.Perks?.perks != null && member.Perks.perks.Count > 0) {
|
|
builder.AddText("Perks", "#FFD700");
|
|
foreach(var perk in member.Perks.perks) {
|
|
builder.AddText($" {perk.Name}");
|
|
}
|
|
builder.AddSeparator();
|
|
}
|
|
|
|
// Modifiers
|
|
if(member.Modifiers?.modifiers is { Count: > 0 }) {
|
|
builder.AddText("Modifiers", "#87CEEB");
|
|
foreach(var mod in member.Modifiers.modifiers) {
|
|
var target = mod.Target != null ? mod.Target.ToString() : "";
|
|
builder.AddText($" {mod.Name} ({mod.Operation} {mod.Value} {target})");
|
|
}
|
|
}
|
|
}
|
|
|
|
private static void UpdateSlotStats(PartyMemberSlot slot, CharacterDefinition member) {
|
|
var health = member.Stats.GetValue(StatType.Health);
|
|
var mana = member.Stats.GetValue(StatType.Mana);
|
|
|
|
if(slot.healthBar != null) {
|
|
slot.healthBar.fillAmount = Mathf.Clamp01(health / 100f);
|
|
}
|
|
|
|
if(slot.manaBar != null) {
|
|
slot.manaBar.fillAmount = Mathf.Clamp01(mana / 100f);
|
|
}
|
|
}
|
|
|
|
public void Dispose() {
|
|
foreach(var slot in activeSlots) {
|
|
if(slot != null) {
|
|
Object.Destroy(slot.gameObject);
|
|
}
|
|
}
|
|
activeSlots.Clear();
|
|
}
|
|
}
|
|
}
|