using UnityEngine; using UnityEngine.UI; using TMPro; using Colosseum.Abnormalities; namespace Colosseum.UI { /// /// 개별 이상 상태 UI 슬롯 /// 버프/디버프 아이콘, 지속 시간 등을 표시합니다. /// public class AbnormalitySlotUI : MonoBehaviour { [Header("UI References")] [Tooltip("이상 상태 아이콘")] [SerializeField] private Image iconImage; [Tooltip("지속 시간 채우기 이미지 (시계 방향)")] [SerializeField] private Image durationFill; [Tooltip("남은 시간 텍스트")] [SerializeField] private TMP_Text durationText; [Tooltip("효과 이름 텍스트")] [SerializeField] private TMP_Text effectNameText; [Tooltip("배경 이미지 (버프/디버프 구분용)")] [SerializeField] private Image backgroundImage; [Header("Colors")] [Tooltip("버프 배경 색상")] [SerializeField] private Color buffColor = new Color(0.2f, 0.6f, 0.2f, 0.8f); [Tooltip("디버프 배경 색상")] [SerializeField] private Color debuffColor = new Color(0.6f, 0.2f, 0.2f, 0.8f); private ActiveAbnormality trackedAbnormality; /// /// 추적 중인 활성 이상 상태 /// public ActiveAbnormality TrackedAbnormality => trackedAbnormality; /// /// UI 초기화 /// /// 표시할 활성 이상 상태 public void Initialize(ActiveAbnormality abnormality) { trackedAbnormality = abnormality; if (abnormality?.Data == null) { Debug.LogWarning("[AbnormalitySlotUI] Initialize called with null abnormality or data"); return; } // 아이콘 설정 if (iconImage != null) { iconImage.sprite = abnormality.Data.icon; iconImage.enabled = abnormality.Data.icon != null; } // 이름 설정 if (effectNameText != null) { effectNameText.text = abnormality.Data.abnormalityName; } // 배경 색상 설정 (버프/디버프 구분) if (backgroundImage != null) { backgroundImage.color = abnormality.Data.isDebuff ? debuffColor : buffColor; } // 초기 상태 업데이트 UpdateDisplay(abnormality.RemainingDuration, abnormality.Data.duration); } /// /// 화면 표시 업데이트 /// /// 남은 시간 /// 전체 시간 public void UpdateDisplay(float remainingDuration, float totalDuration) { // 지속 시간 채우기 업데이트 if (durationFill != null) { if (totalDuration > 0f) { float fillAmount = Mathf.Clamp01(remainingDuration / totalDuration); durationFill.fillAmount = fillAmount; durationFill.enabled = true; } else { // 영구 효과 durationFill.fillAmount = 1f; } } // 남은 시간 텍스트 업데이트 if (durationText != null) { if (totalDuration > 0f) { if (remainingDuration >= 60f) { durationText.text = $"{remainingDuration / 60f:F0}m"; } else if (remainingDuration >= 1f) { durationText.text = $"{remainingDuration:F0}s"; } else { durationText.text = $"{remainingDuration:F1}s"; } } else { // 영구 효과 durationText.text = "∞"; } } } /// /// 프레임마다 호출하여 추적 중인 효과 업데이트 /// private void Update() { if (trackedAbnormality == null) { gameObject.SetActive(false); return; } UpdateDisplay(trackedAbnormality.RemainingDuration, trackedAbnormality.Data.duration); } /// /// 툴팁 표시용 정보 반환 /// public string GetTooltipText() { if (trackedAbnormality?.Data == null) return string.Empty; var data = trackedAbnormality.Data; string tooltip = $"{data.abnormalityName}\n"; if (!data.IsPermanent) { tooltip += $"지속 시간: {trackedAbnormality.RemainingDuration:F1}초\n"; } else { tooltip += "영구 효과\n"; } if (data.HasPeriodicEffect) { tooltip += $"주기적 효과: {data.periodicValue:+0}/ {data.periodicInterval}초\n"; } if (data.HasControlEffect) { tooltip += $"제어 효과: {data.controlType}\n"; } foreach (var mod in data.statModifiers) { string sign = mod.value >= 0 ? "+" : ""; tooltip += $"{mod.statType}: {sign}{mod.value}\n"; } return tooltip; } } }