Projext/Assets/Scripts/Player/Upgrade/UI/CardUI.cs

150 lines
8.4 KiB
C#
Raw Normal View History

2026-02-25 10:39:20 +00:00
using UnityEngine; // 유니티 기능을 불러올거에요 -> UnityEngine을
using TMPro; // 텍스트메쉬프로를 사용할거에요 -> TMPro를
using UnityEngine.UI; // UI 기능을 사용할거에요 -> UnityEngine.UI를
using System.Collections.Generic; // 리스트를 사용할거에요 -> System.Collections.Generic을
2026-01-29 06:58:38 +00:00
2026-02-25 10:39:20 +00:00
public class CardUI : MonoBehaviour // 클래스를 선언할거에요 -> 카드 UI를
2026-01-29 06:58:38 +00:00
{
2026-02-25 10:39:20 +00:00
[SerializeField] private TextMeshProUGUI effectText; // 변수를 선언할거에요 -> 효과 텍스트를
[SerializeField] private Image iconImage; // 변수를 선언할거에요 -> 아이콘 이미지를
[SerializeField] private Outline selectionOutline; // 변수를 선언할거에요 -> 선택 테두리를
2026-01-29 06:58:38 +00:00
2026-02-25 10:39:20 +00:00
private CardData cardData; // 변수를 선언할거에요 -> 카드 데이터를
private LevelUpUIManager uiManager; // 변수를 선언할거에요 -> UI 매니저를
2026-01-29 06:58:38 +00:00
2026-02-25 10:39:20 +00:00
// [FIX] 3개 능력치 저장용 리스트
private List<StatType> rolledStats = new List<StatType>(); // 리스트를 선언할거에요 -> 뽑힌 스탯 타입들을
private List<int> rolledValues = new List<int>(); // 리스트를 선언할거에요 -> 뽑힌 수치들을
private bool isRandomCard = false; // 변수를 초기화할거에요 -> 랜덤 카드 여부를
2026-01-29 06:58:38 +00:00
2026-02-25 10:39:20 +00:00
public void Setup(CardData data, LevelUpUIManager manager, StatType mainStat = StatType.Health) // 함수를 선언할거에요 -> 카드를 설정하는 Setup을 (mainStat = 이 카드의 메인 버프 스탯)
2026-01-29 06:58:38 +00:00
{
2026-02-25 10:39:20 +00:00
cardData = data; // 값을 저장할거에요 -> 카드 데이터를
uiManager = manager; // 값을 저장할거에요 -> 매니저를
if (selectionOutline != null) selectionOutline.enabled = false; // 꺼줄거에요 -> 테두리를
// 아이콘 설정
if (iconImage != null && cardData.icon != null) // 조건이 맞으면 실행할거에요 -> 아이콘이 있다면
iconImage.sprite = cardData.icon; // 설정할거에요 -> 아이콘을
RandomStatCardData randomData = cardData as RandomStatCardData; // 형변환할거에요 -> 랜덤 카드 데이터로
if (randomData != null) // 조건이 맞으면 실행할거에요 -> 랜덤 카드라면
{
isRandomCard = true; // 상태를 바꿀거에요 -> 랜덤 카드로
RollAllStats(randomData, mainStat); // 실행할거에요 -> 메인 스탯 지정해서 3개 능력치 뽑기를
}
else // 조건이 틀리면 실행할거에요 -> 일반 카드라면
{
effectText.text = cardData.GetText(); // 텍스트를 설정할거에요 -> 기본 텍스트를
}
}
/// <summary>
/// [FIX] possibleStats의 모든 스탯을 중복 없이 뽑아서 표시
/// 첫 번째 스탯은 양수(버프), 나머지는 음수(디버프)
/// </summary>
private void RollAllStats(RandomStatCardData randomData, StatType mainStat) // 함수를 선언할거에요 -> 메인 스탯 지정해서 3개 능력치를 뽑는 RollAllStats를
{
rolledStats.Clear(); // 비울거에요 -> 이전 데이터를
rolledValues.Clear(); // 비울거에요 -> 이전 데이터를
// ① 메인 스탯 (버프) 먼저 고정
int mainValue = Random.Range( // 뽑을거에요 -> 양수 버프 수치를
Mathf.Max(1, randomData.minValue), // 최솟값을 1 이상으로 보장
Mathf.Max(2, randomData.maxValue) + 1 // 최댓값 + 1 (상한 미포함)
);
rolledStats.Add(mainStat); // 추가할거에요 -> 메인 스탯을 첫 번째로
rolledValues.Add(mainValue); // 추가할거에요 -> 버프 수치를
// ② 나머지 스탯들 (디버프) — mainStat 제외하고 추가
List<StatType> otherStats = new List<StatType>(); // 리스트를 만들거에요 -> 나머지 스탯을
foreach (StatType s in System.Enum.GetValues(typeof(StatType))) // 반복할거에요 -> 모든 StatType을
{
if (s != mainStat) otherStats.Add(s); // 추가할거에요 -> 메인 스탯이 아닌 것만
}
ShuffleList(otherStats); // 섞을거에요 -> 디버프 순서를 랜덤으로
foreach (StatType s in otherStats) // 반복할거에요 -> 나머지 스탯들을
{
int debuffValue = Random.Range( // 뽑을거에요 -> 음수 디버프 수치를
Mathf.Min(-1, -randomData.maxValue), // 최솟값 (음수)
0 // 상한 0 (미포함 → 항상 음수)
);
rolledStats.Add(s); // 추가할거에요 -> 디버프 스탯을
rolledValues.Add(debuffValue); // 추가할거에요 -> 디버프 수치를
}
// ③ 텍스트 조합 — 3줄 표시
string display = ""; // 초기화할거에요 -> 표시 텍스트를
for (int i = 0; i < rolledStats.Count; i++) // 반복할거에요 -> 모든 스탯에 대해
{
int val = rolledValues[i]; // 가져올거에요 -> 수치를
string sign = val >= 0 ? "+" : ""; // 결정할거에요 -> 부호를
string colorTag = val >= 0 ? "<color=#4AFF4A>" : "<color=#FF4A4A>"; // 결정할거에요 -> 버프=초록, 디버프=빨강
string statName = GetStatDisplayName(rolledStats[i]); // 가져올거에요 -> 스탯 표시명을
display += $"{colorTag}{statName} {sign}{val}</color>"; // 추가할거에요 -> 한 줄을
if (i < rolledStats.Count - 1) display += "\n"; // 추가할거에요 -> 줄바꿈을 (마지막 제외)
}
effectText.text = display; // 설정할거에요 -> 완성된 텍스트를
}
/// <summary>
/// 스탯 타입을 표시용 이름으로 변환
/// </summary>
private string GetStatDisplayName(StatType stat) // 함수를 선언할거에요 -> 스탯 표시명을 반환하는
{
switch (stat) // 분기할거에요 -> 스탯 타입에 따라
{
case StatType.Health: return "Health"; // 반환할거에요 -> Health를
case StatType.Speed: return "Speed"; // 반환할거에요 -> Speed를
case StatType.Damage: return "Damage"; // 반환할거에요 -> Damage를
default: return stat.ToString(); // 반환할거에요 -> 기본 이름을
}
}
/// <summary>
/// 리스트를 랜덤으로 섞기 (Fisher-Yates 셔플)
/// </summary>
private void ShuffleList<T>(List<T> list) // 함수를 선언할거에요 -> 리스트를 셔플하는
{
for (int i = list.Count - 1; i > 0; i--) // 반복할거에요 -> 뒤에서부터
{
int j = Random.Range(0, i + 1); // 뽑을거에요 -> 랜덤 인덱스를
T temp = list[i]; // 임시 저장할거에요 -> 현재 값을
list[i] = list[j]; // 교체할거에요 -> i와 j를
list[j] = temp; // 교체할거에요 -> j에 임시값을
}
}
// 카드 클릭 시 매니저에게 알림
2026-02-25 10:39:20 +00:00
public void OnClick() // 함수를 선언할거에요 -> 클릭 처리를
{
uiManager.OnCardClick(this); // 알릴거에요 -> 매니저에게
}
2026-02-25 10:39:20 +00:00
// 선택 시 하이라이트
public void SetSelected(bool isSelected) // 함수를 선언할거에요 -> 선택 상태를
{
2026-02-25 10:39:20 +00:00
if (selectionOutline != null) selectionOutline.enabled = isSelected; // 설정할거에요 -> 테두리를
transform.localScale = isSelected ? Vector3.one * 1.05f : Vector3.one; // 크기를 조절할거에요 -> 선택되면 키우기
2026-01-29 06:58:38 +00:00
}
2026-02-25 10:39:20 +00:00
// [FIX] APPLY 버튼 누를 때 3개 능력치 전부 적용
public void ApplyCurrentEffect() // 함수를 선언할거에요 -> 효과를 적용하는 ApplyCurrentEffect를
2026-01-29 06:58:38 +00:00
{
2026-02-12 15:23:25 +00:00
if (isRandomCard) // 조건이 맞으면 실행할거에요 -> 랜덤 카드라면
2026-01-29 06:58:38 +00:00
{
2026-02-25 10:39:20 +00:00
RandomStatCardData rd = cardData as RandomStatCardData; // 형변환할거에요 -> 랜덤 카드로
for (int i = 0; i < rolledStats.Count; i++) // 반복할거에요 -> 모든 뽑힌 스탯에 대해
{
rd.ApplyToPlayer(rolledStats[i], rolledValues[i]); // 적용할거에요 -> 각 스탯과 수치를
}
}
else // 조건이 틀리면 실행할거에요 -> 일반 카드라면
{
cardData.Execute(); // 실행할거에요 -> 기본 효과를
2026-01-29 06:58:38 +00:00
}
2026-02-25 10:39:20 +00:00
FindObjectOfType<PlayerHealth>()?.RefreshHealthUI(); // 실행할거에요 -> 체력 UI 갱신을
2026-01-29 06:58:38 +00:00
}
}