using System.Collections.Generic; using System.Linq; using TMPro; using UnityEngine; using UnityEngine.UI; namespace Kryz.CharacterStats.Examples { public class StatPanel : MonoBehaviour { [SerializeField] private Transform statDisplaysParent; [SerializeField] StatDisplay[] statDisplays; [SerializeField] private StatDisplay[] secondaryStatDisplays; [SerializeField] string[] statNames; [SerializeField] Button[] addStatButtons; [SerializeField] private string[] secondaryStatNames; [SerializeField] private TMP_Text characterName; [SerializeField] private TMP_Text characterLevel; [SerializeField] private TMP_Text characterRepLevel; [SerializeField] private StatDisplay unallocated; [SerializeField] private Button resetAllocated; [SerializeField] private TMP_Text rankText; [SerializeField] private TMP_Text powerLevelText; private CharacterStat[] stats; private CharacterStat[] secondaryStats; private PlayerCharacterStats playerStats; private bool InitializedListeners = false; const string almost = "≈"; /* private void OnValidate() { if (statDisplaysParent != null) { statDisplays = statDisplaysParent.GetComponentsInChildren(); UpdateStatNames(); UpdateSecondaryStatNames(); } }*/ [ContextMenu("UpdateNames")] private void UpdateNames() { UpdateStatNames(); UpdateSecondaryStatNames(); } public void SetPlayerStats(PlayerCharacterStats playerStats) { this.playerStats = playerStats; } public void SetStats(Dictionary primaryStats) { // Store both dictionary values as array (for compatibility with existing methods) stats = primaryStats.Values.ToArray(); for (int i = 0; i < statDisplays.Length && i < primaryStats.Count; i++) { var stat = primaryStats.Values.ElementAt(i); statDisplays[i].Stat = stat; statDisplays[i].NameText.text = stat.statDefinition.DisplayName; // This requires updating CharacterStat first statDisplays[i].gameObject.SetActive(true); } // Hide unused displays for (int i = primaryStats.Count; i < statDisplays.Length; i++) { statDisplays[i].gameObject.SetActive(false); } unallocated.ValueText.text = playerStats.AvailablePointsToAllocate.ToString(); unallocated.gameObject.SetActive(playerStats.AvailablePointsToAllocate > 0); if (InitializedListeners) return; InitializedListeners = true; addStatButtons[0].onClick.AddListener(() => AllocateStat(0)); addStatButtons[1].onClick.AddListener(() => AllocateStat(1)); addStatButtons[2].onClick.AddListener(() => AllocateStat(2)); resetAllocated.onClick.AddListener(ResetAllocatedStats); } public void SetSecondaryStats(Dictionary secondaryStats) { // Store as array for compatibility this.secondaryStats = secondaryStats.Values.ToArray(); int index = 0; foreach (var kvp in secondaryStats) { if (index >= secondaryStatDisplays.Length) break; secondaryStatDisplays[index].Stat = kvp.Value; secondaryStatDisplays[index].NameText.text = kvp.Value.statDefinition.DisplayName; index++; } // Hide unused displays for (int i = index; i < secondaryStatDisplays.Length; i++) { secondaryStatDisplays[i].gameObject.SetActive(false); } } int pointsToAllocate; public void AllocateStat(int index) { if (playerStats.AvailablePointsToAllocate <= 0) return; // Determine points to allocate based on shift key pointsToAllocate = Input.GetKey(KeyCode.LeftShift) || Input.GetKey(KeyCode.RightShift) ? 10 : 1; pointsToAllocate = Mathf.Min(pointsToAllocate, playerStats.AvailablePointsToAllocate); playerStats.AllocatedStatPoints[index] += pointsToAllocate; playerStats.AvailablePointsToAllocate -= pointsToAllocate; playerStats.UpdateAllocatedStats(); ToggleAllocateButtonsInteractable(playerStats.AvailablePointsToAllocate > 0); } public void ResetAllocatedStats() { for (int i = 0; i < playerStats.AllocatedStatPoints.Count; i++) { playerStats.AvailablePointsToAllocate += playerStats.AllocatedStatPoints[i]; playerStats.AllocatedStatPoints[i] = 0; } playerStats.UpdateAllocatedStats(); ToggleAllocateButtonsInteractable(playerStats.AvailablePointsToAllocate > 0); } public void SetCharacterInfo(string name, string level, string repLevel) { characterName.text = name; characterLevel.text = level; characterRepLevel.text = repLevel; } public void UpdateLevelInfo(string level, string repLevel) { characterLevel.text = level; characterRepLevel.text = repLevel; } public void UpdateStatValues() { for (int i = 0; i < stats.Length; i++) { statDisplays[i].ValueText.text = stats[i].Value.ToString(); } UpdateSecondaryStatValues(); } public void UpdateStatNames() { for (int i = 0; i < statNames.Length; i++) { statDisplays[i].NameText.text = statNames[i]; } } public void UpdateSecondaryStatNames() { for (int i = 0; i < secondaryStatNames.Length; i++) { secondaryStatDisplays[i].NameText.text = secondaryStatNames[i]; } } int relativePowerLevel; public void UpdateSecondaryStatValues() { for (int i = 0; i < secondaryStats.Length; i++) { secondaryStatDisplays[i].ValueText.text = secondaryStatDisplays[i].NameText.text.Contains("crit") ? secondaryStats[i].Value.ToString() + " %" : secondaryStats[i].Value.ToString(); } relativePowerLevel = Mathf.RoundToInt(playerStats.GetRelativePowerLevel()); if (rankText != null) rankText.text = GameConstants.CharacterBalancing.GetRankBasedOnRelativeTotalPowerLevel(relativePowerLevel) + " Rank"; if (powerLevelText != null) powerLevelText.text = almost + relativePowerLevel.ToString(); } public void ToggleAllocateButtonsInteractable(bool interactable) { unallocated.ValueText.text = playerStats.AvailablePointsToAllocate.ToString(); unallocated.gameObject.SetActive(playerStats.AvailablePointsToAllocate > 0); for (int i = 0; i < addStatButtons.Length; i++) { addStatButtons[i].gameObject.SetActive(interactable); } } } }