|
|
|
|
@ -95,7 +95,8 @@ namespace TKS.OutGame
|
|
|
|
|
/// <summary>말 탄 유닛 전신(발 ~ 머리 끝) 높이 상한(카드 px) — 크기 표 실측이 튀는 그림(예 여포 size_px 449)도 다른 기병과 비슷하게.</summary>
|
|
|
|
|
const float MountedMaxBody = 460f;
|
|
|
|
|
|
|
|
|
|
public static Image Card(Transform content, OutGameSession s, HeroDb.Hero h, bool deployed, System.Action onTap)
|
|
|
|
|
/// <param name="owned">false = 미보유(PD 2026-11-10 「유닛 목록에 장수들의 모습이 보이도록」) — 일러를 테마 card_locked_art 로 조금 어둡게 · 「미보유」 꼬리 칩 · 레벨 배지·성장 점 없음</param>
|
|
|
|
|
public static Image Card(Transform content, OutGameSession s, HeroDb.Hero h, bool deployed, System.Action onTap, bool owned = true)
|
|
|
|
|
{
|
|
|
|
|
var cell = UiKit.Cell(content, "Card_" + h.id, Color.clear, onTap);
|
|
|
|
|
cell.sprite = null; // 바닥 = 클릭 판(투명) · 그림은 층으로
|
|
|
|
|
@ -138,6 +139,7 @@ namespace TKS.OutGame
|
|
|
|
|
}
|
|
|
|
|
art.sprite = sp;
|
|
|
|
|
art.raycastTarget = false;
|
|
|
|
|
if (!owned) art.color = UiKit.Col("card_locked_art", UiKit.InkSoft);
|
|
|
|
|
}
|
|
|
|
|
else
|
|
|
|
|
{
|
|
|
|
|
@ -155,10 +157,10 @@ namespace TKS.OutGame
|
|
|
|
|
int star = hs != null ? hs.star : h.rarity;
|
|
|
|
|
for (int i = star - 1; i >= 0; i--)
|
|
|
|
|
UiKit.Icon(t, "star_on", new Vector2(1f, 0f), new Vector2(1f, 1f), new Vector2(-15.5f - i * 28f, 64.8f), 44f);
|
|
|
|
|
// 레벨 배지(왼쪽 아래 · 최고 레벨 = 노랑)
|
|
|
|
|
// 레벨 배지(왼쪽 아래 · 최고 레벨 = 노랑 · 미보유 = 없음)
|
|
|
|
|
int lvn = lv != null ? lv.lv : 1;
|
|
|
|
|
bool maxLv = s.Db.Levels != null && lvn >= s.Db.Levels.MaxLevel;
|
|
|
|
|
var badge = UiKit.Icon(t, maxLv ? "lv_badge_max" : "lv_badge_s", new Vector2(0f, 0f), new Vector2(0.5f, 0.5f), new Vector2(33.9f, 36.7f), 79f);
|
|
|
|
|
var badge = owned ? UiKit.Icon(t, maxLv ? "lv_badge_max" : "lv_badge_s", new Vector2(0f, 0f), new Vector2(0.5f, 0.5f), new Vector2(33.9f, 36.7f), 79f) : null;
|
|
|
|
|
if (badge != null)
|
|
|
|
|
{
|
|
|
|
|
var bt = UiKit.Title(UiKit.Label(badge.transform, lvn.ToString(), 30, UiKit.White, TextAnchor.MiddleCenter, new Vector2(0.5f, 0.5f), new Vector2(0.5f, 0.5f), new Vector2(1f, -3f), new Vector2(74f, 50f)), true);
|
|
|
|
|
@ -171,23 +173,31 @@ namespace TKS.OutGame
|
|
|
|
|
name.resizeTextForBestFit = true;
|
|
|
|
|
name.resizeTextMinSize = 26;
|
|
|
|
|
name.resizeTextMaxSize = 45;
|
|
|
|
|
if (deployed)
|
|
|
|
|
if (deployed || !owned)
|
|
|
|
|
{
|
|
|
|
|
var tail = UiKit.Skin(UiKit.Rect("Deployed", t, new Vector2(0f, 1f), new Vector2(0f, 0.5f), new Vector2(10f, -96f), new Vector2(84f, 38f)), "tail", UiKit.Col("tail_red", UiKit.Red));
|
|
|
|
|
UiKit.Title(UiKit.FillLabel(tail.transform, "출전", 24, UiKit.White), true);
|
|
|
|
|
var tail = UiKit.Skin(UiKit.Rect(owned ? "Deployed" : "Locked", t, new Vector2(0f, 1f), new Vector2(0f, 0.5f), new Vector2(10f, -96f), new Vector2(owned ? 84f : 104f, 38f)), "tail",
|
|
|
|
|
owned ? UiKit.Col("tail_red", UiKit.Red) : UiKit.Col("tail_locked", UiKit.Dark));
|
|
|
|
|
UiKit.Title(UiKit.FillLabel(tail.transform, owned ? "출전" : "미보유", 24, UiKit.White), true);
|
|
|
|
|
}
|
|
|
|
|
// 병과 = 단색 심볼만(배경 틀 없음 · PD 2026-11-09 「심볼은 배경 프레임 없이 단색」)
|
|
|
|
|
var role = UiKit.Rect("Role", t, new Vector2(1f, 1f), new Vector2(0.5f, 0.5f), new Vector2(-42f, -42f), new Vector2(60f, 60f));
|
|
|
|
|
var sym = UiKit.Icon(role, UiKit.TypeSymbolId(h.type), new Vector2(0.5f, 0.5f), new Vector2(0.5f, 0.5f), Vector2.zero, 60f);
|
|
|
|
|
if (sym == null) UiKit.Title(UiKit.FillLabel(role, UnitTypeInfo.Mark(h.type), 28, UiKit.White), true);
|
|
|
|
|
if (s.CanGrowAny(h.id)) UiKit.Icon(t, "new_dot", new Vector2(0f, 0f), new Vector2(0.5f, 0.5f), new Vector2(64f, 70f), 30f); // 성장 가능 = 레벨 배지 오른쪽 위
|
|
|
|
|
if (owned && s.CanGrowAny(h.id)) UiKit.Icon(t, "new_dot", new Vector2(0f, 0f), new Vector2(0.5f, 0.5f), new Vector2(64f, 70f), 30f); // 성장 가능 = 레벨 배지 오른쪽 위
|
|
|
|
|
return cell;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
/// <summary>원래 크기(320×431) 카드를 holder 가운데에 배율 k 로 넣는다(편성 자리 · 편성 보유 목록).</summary>
|
|
|
|
|
public static Image CardIn(Transform holder, OutGameSession s, HeroDb.Hero h, bool deployed, System.Action onTap, float k)
|
|
|
|
|
/// <summary>원래 크기(320×431) 카드를 holder 가운데에 배율 k 로 넣는다(편성 자리 · 편성 보유 목록 · 영웅 목록 미보유 = owned false).</summary>
|
|
|
|
|
public static Image CardIn(Transform holder, OutGameSession s, HeroDb.Hero h, bool deployed, System.Action onTap, float k, bool owned = true)
|
|
|
|
|
{
|
|
|
|
|
return Fit(Card(holder, s, h, deployed, onTap), k);
|
|
|
|
|
return Fit(Card(holder, s, h, deployed, onTap, owned), k);
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
/// <summary>미보유·도감 안내 한 줄(이름(한자) · 병종 · ★ · 보유/미보유).</summary>
|
|
|
|
|
public static string InfoText(HeroDb.Hero h, bool own)
|
|
|
|
|
{
|
|
|
|
|
return h.nameKo + (string.IsNullOrEmpty(h.hanja) ? "" : "(" + h.hanja + ")") + " · " + UnitTypeInfo.Korean(h.type) + " · ★" + h.rarity +
|
|
|
|
|
(h.isSoldier ? " · 병사 유닛" : "") + (own ? " · 보유" : " · 미보유 — 거래 > 뽑기");
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
public static Image EmptyIn(Transform holder, float k)
|
|
|
|
|
@ -227,7 +237,7 @@ namespace TKS.OutGame
|
|
|
|
|
|
|
|
|
|
/// <summary>
|
|
|
|
|
/// 영웅 탭 = 영웅 목록(PD 2026-11-09 레퍼런스 = 팩 Collection_List) — 헤더(제목 · 장수/병사 고르기 ▼ · 사선 칸 「보유 / 전체」) ·
|
|
|
|
|
/// 3열 세로 카드(보유 = 레벨 높은 순) + 미보유 자리 = 빈 카드 → 탭 = 영웅 상세.
|
|
|
|
|
/// 세로 카드(보유 = 레벨 높은 순 → 탭 = 영웅 상세) + 미보유 = 그 영웅 카드(조금 어둡게 · 「미보유」 · 탭 = 획득 안내 · PD 2026-11-10).
|
|
|
|
|
/// </summary>
|
|
|
|
|
public class HeroListScreen : OutGameScreen
|
|
|
|
|
{
|
|
|
|
|
@ -237,6 +247,7 @@ namespace TKS.OutGame
|
|
|
|
|
Text filterText;
|
|
|
|
|
Text countText;
|
|
|
|
|
int ownedCards;
|
|
|
|
|
int lockedCards;
|
|
|
|
|
UiAutoGrid autoGrid;
|
|
|
|
|
|
|
|
|
|
public bool ShowingSoldiers
|
|
|
|
|
@ -315,19 +326,36 @@ namespace TKS.OutGame
|
|
|
|
|
CollectionCards.CardIn(Slot(), S, h, S.InActivePreset(id), () => Root.ShowHero(id), autoGrid.Scale);
|
|
|
|
|
ownedCards++;
|
|
|
|
|
}
|
|
|
|
|
int total = 0;
|
|
|
|
|
foreach (var h in S.Db.Heroes.heroes)
|
|
|
|
|
if (h.isSoldier == soldiers) total++;
|
|
|
|
|
for (int i = owned.Count; i < total; i++) CollectionCards.EmptyIn(Slot(), autoGrid.Scale);
|
|
|
|
|
countText.text = owned.Count + "/" + total;
|
|
|
|
|
// 미보유 = 빈 카드 대신 그 영웅 카드(일러 조금 어둡게 · 「미보유」 · 탭 = 획득 안내) · ★ 높은 순 → 표 순서
|
|
|
|
|
// PD 2026-11-10 「왜 유닛 목록에 장수들의 모습이 보이지 않는거지? 이번에 추가된 리소스가 반영되도록」
|
|
|
|
|
// (상세 화면은 레벨·세이브가 있는 보유 영웅 전제라 미보유는 열지 않는다)
|
|
|
|
|
var locked = new List<HeroDb.Hero>();
|
|
|
|
|
var all = S.Db.Heroes.heroes;
|
|
|
|
|
foreach (var h in all)
|
|
|
|
|
if (h.isSoldier == soldiers && !S.Save.Owns(h.id)) locked.Add(h);
|
|
|
|
|
locked.Sort((a, b) => a.rarity != b.rarity ? b.rarity.CompareTo(a.rarity) : all.IndexOf(a).CompareTo(all.IndexOf(b)));
|
|
|
|
|
lockedCards = 0;
|
|
|
|
|
foreach (var h in locked)
|
|
|
|
|
{
|
|
|
|
|
var hero = h;
|
|
|
|
|
CollectionCards.CardIn(Slot(), S, h, false, () => Root.Toast(CollectionCards.InfoText(hero, false)), autoGrid.Scale, false);
|
|
|
|
|
lockedCards++;
|
|
|
|
|
}
|
|
|
|
|
countText.text = owned.Count + "/" + (owned.Count + locked.Count);
|
|
|
|
|
autoGrid.Apply();
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
/// <summary>보유 카드 수(빈 카드 제외).</summary>
|
|
|
|
|
/// <summary>보유 카드 수(미보유 제외).</summary>
|
|
|
|
|
public int CardCount
|
|
|
|
|
{
|
|
|
|
|
get { return ownedCards; }
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
/// <summary>미보유 영웅 카드 수(그림 카드 · PD 2026-11-10).</summary>
|
|
|
|
|
public int LockedCount
|
|
|
|
|
{
|
|
|
|
|
get { return lockedCards; }
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
/// <summary>
|
|
|
|
|
@ -968,8 +996,7 @@ namespace TKS.OutGame
|
|
|
|
|
{
|
|
|
|
|
bool own = s.Save.Owns(h.id);
|
|
|
|
|
var hero = h;
|
|
|
|
|
HeroCards.Card(grid, s, h, false, own, () => root.Toast(hero.nameKo + (string.IsNullOrEmpty(hero.hanja) ? "" : "(" + hero.hanja + ")") + " · " +
|
|
|
|
|
UnitTypeInfo.Korean(hero.type) + " · ★" + hero.rarity + (hero.isSoldier ? " · 병사 유닛" : "") + (own ? " · 보유" : " · 미보유 — 거래 > 뽑기")));
|
|
|
|
|
HeroCards.Card(grid, s, h, false, own, () => root.Toast(CollectionCards.InfoText(hero, own)));
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|