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-01 15:49:12 +00:00
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
// 카드 클릭 시 매니저에게 알림
|
2026-02-25 10:39:20 +00:00
|
|
|
|
public void OnClick() // 함수를 선언할거에요 -> 클릭 처리를
|
|
|
|
|
|
{
|
|
|
|
|
|
uiManager.OnCardClick(this); // 알릴거에요 -> 매니저에게
|
|
|
|
|
|
}
|
2026-02-01 15:49:12 +00:00
|
|
|
|
|
2026-02-25 10:39:20 +00:00
|
|
|
|
// 선택 시 하이라이트
|
|
|
|
|
|
public void SetSelected(bool isSelected) // 함수를 선언할거에요 -> 선택 상태를
|
2026-02-01 15:49:12 +00:00
|
|
|
|
{
|
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
|
|
|
|
}
|
|
|
|
|
|
}
|