using UnityEngine; using UnityEngine.UI; using TMPro; using UnityEngine.SceneManagement; using System.Collections.Generic; namespace Gyvr.Mythril2D { public class KillsRankHUD : MonoBehaviour { [Header("Kills: Aparência (Inspector)")] [SerializeField] private TMP_FontAsset killsFonte; [SerializeField] private int killsTamanhoFonte = 28; [SerializeField] private Vector2 killsPosicao = new Vector2(12f, -12f); [SerializeField] private Color killsCor = Color.white; [SerializeField] private string killsPrefixo = "Kills: "; [System.Serializable] public struct RankStep { [Min(1)] public int killsRequeridos; // depois de X kills... public string titulo; // ...usa este título public Sprite icone; // ...e este ícone (opcional) } [Header("Rank/Título: Aparência (Inspector)")] [SerializeField] private TMP_FontAsset rankFonte; [SerializeField] private int rankTamanhoFonte = 28; [SerializeField] private Vector2 rankPosicao = new Vector2(12f, -48f); [SerializeField] private Color rankCor = Color.white; [SerializeField] private string rankPrefixo = ""; // ex: "Título: " [SerializeField] private string tituloInicial = "Novato"; [Tooltip("Adicione degraus: depois de X kills -> usa título e ícone definidos")] [SerializeField] private List rankDegraus = new List(); [Header("Ícone do Rank (Inspector)")] [SerializeField] private Sprite iconeInicial; // ícone exibido antes do primeiro degrau [SerializeField] private Vector2 iconePosicao = new Vector2(220f, -48f); [SerializeField] private Vector2 iconeTamanho = new Vector2(32f, 32f); [SerializeField] private bool iconeUsarTamanhoNativo = false; [SerializeField] private bool iconeOcultarSeNulo = true; // Referência auto-descoberta private NotificationSystem _notif; // UI / estado private Canvas _canvas; private TextMeshProUGUI _killsLabel; private TextMeshProUGUI _rankLabel; private Image _rankIcon; private int _kills; void Awake() { CriarCanvasEUISeNecessario(); AplicarEstilos(); } void OnEnable() { SceneManager.sceneLoaded += OnSceneLoaded; GarantirAssinatura(); } void OnDisable() { SceneManager.sceneLoaded -= OnSceneLoaded; Desassinar(); } void Start() { AtualizarKillsTexto(); // "Kills: 0" AtualizarRankUI(); // título + ícone inicial } // === Auto-binding do NotificationSystem === private void OnSceneLoaded(Scene s, LoadSceneMode m) { GarantirAssinatura(true); } private void GarantirAssinatura(bool forceRebind = false) { if (forceRebind && _notif != null) { _notif.monsterKilled.RemoveListener(OnMonsterKilled); _notif = null; } #if UNITY_2022_1_OR_NEWER if (_notif == null) _notif = FindFirstObjectByType(FindObjectsInactive.Include); #else if (_notif == null) { var all = Resources.FindObjectsOfTypeAll(); if (all != null && all.Length > 0) _notif = all[0]; } #endif if (_notif != null) { _notif.monsterKilled.RemoveListener(OnMonsterKilled); // evita duplicar _notif.monsterKilled.AddListener(OnMonsterKilled); } else { Debug.LogWarning("[KillsRankHUD] NotificationSystem não encontrado. Tentarei novamente ao carregar a cena."); } } private void Desassinar() { if (_notif != null) { _notif.monsterKilled.RemoveListener(OnMonsterKilled); } } // === Handler: conta qualquer monstro === private void OnMonsterKilled(MonsterSheet _) { _kills++; AtualizarKillsTexto(); AtualizarRankUI(); // atualiza título + ícone conforme degrau atingido } // === UI === private void CriarCanvasEUISeNecessario() { if (_canvas == null) { GameObject go = new GameObject("KillsRankHudCanvas"); _canvas = go.AddComponent(); _canvas.renderMode = RenderMode.ScreenSpaceOverlay; go.AddComponent(); go.AddComponent(); } if (_killsLabel == null) { GameObject killsGO = new GameObject("KillsLabel"); killsGO.transform.SetParent(_canvas.transform); _killsLabel = killsGO.AddComponent(); } if (_rankLabel == null) { GameObject rankGO = new GameObject("RankLabel"); rankGO.transform.SetParent(_canvas.transform); _rankLabel = rankGO.AddComponent(); } if (_rankIcon == null) { GameObject iconGO = new GameObject("RankIcon"); iconGO.transform.SetParent(_canvas.transform); _rankIcon = iconGO.AddComponent(); } } private void AplicarEstilos() { if (_killsLabel != null) { _killsLabel.font = killsFonte; _killsLabel.fontSize = killsTamanhoFonte; _killsLabel.color = killsCor; _killsLabel.rectTransform.anchorMin = new Vector2(0, 1); _killsLabel.rectTransform.anchorMax = new Vector2(0, 1); _killsLabel.rectTransform.pivot = new Vector2(0, 1); _killsLabel.rectTransform.anchoredPosition = killsPosicao; } if (_rankLabel != null) { _rankLabel.font = rankFonte; _rankLabel.fontSize = rankTamanhoFonte; _rankLabel.color = rankCor; _rankLabel.rectTransform.anchorMin = new Vector2(0, 1); _rankLabel.rectTransform.anchorMax = new Vector2(0, 1); _rankLabel.rectTransform.pivot = new Vector2(0, 1); _rankLabel.rectTransform.anchoredPosition = rankPosicao; } if (_rankIcon != null) { var rt = _rankIcon.rectTransform; rt.anchorMin = new Vector2(0, 1); rt.anchorMax = new Vector2(0, 1); rt.pivot = new Vector2(0, 1); rt.anchoredPosition = iconePosicao; if (iconeUsarTamanhoNativo && _rankIcon.sprite != null) _rankIcon.SetNativeSize(); else rt.sizeDelta = iconeTamanho; } } // === Atualização de textos/ícone === private void AtualizarKillsTexto() { if (_killsLabel == null) return; _killsLabel.text = $"{killsPrefixo}{_kills}"; } private void AtualizarRankUI() { string titulo = tituloInicial; Sprite icone = iconeInicial; int melhor = -1; // pega o MAIOR degrau <= kills for (int i = 0; i < rankDegraus.Count; i++) { var step = rankDegraus[i]; if (_kills >= step.killsRequeridos && step.killsRequeridos > melhor) { melhor = step.killsRequeridos; if (!string.IsNullOrEmpty(step.titulo)) titulo = step.titulo; if (step.icone != null) icone = step.icone; } } if (_rankLabel != null) { _rankLabel.text = string.IsNullOrEmpty(rankPrefixo) ? titulo : $"{rankPrefixo}{titulo}"; } if (_rankIcon != null) { _rankIcon.sprite = icone; // visibilidade _rankIcon.enabled = !(iconeOcultarSeNulo && icone == null); // tamanho: aplica nativo se solicitado if (iconeUsarTamanhoNativo && icone != null) _rankIcon.SetNativeSize(); else _rankIcon.rectTransform.sizeDelta = iconeTamanho; } } // === API pública === public void ResetKills() { _kills = 0; AtualizarKillsTexto(); AtualizarRankUI(); } public int GetKills() => _kills; } }