453 lines
27 KiB
C#
453 lines
27 KiB
C#
using System.Collections.Generic;
|
||
using UnityEngine;
|
||
using UnityEngine.UI;
|
||
|
||
namespace TKS.OutGame
|
||
{
|
||
/// <summary>영웅·병사 카드(2줄 · 기획 S12 v4) — 좌 초상(★ 는 초상 아래) · 1줄 = 병종 배지 · Lv · 출전 중 · 2줄 = 이름.</summary>
|
||
public static class HeroCards
|
||
{
|
||
public static Image Card(Transform content, OutGameSession s, HeroDb.Hero h, bool deployed, bool owned, System.Action onTap)
|
||
{
|
||
var cell = UiKit.Cell(content, "Card_" + h.id, owned ? UiKit.Paper : new Color(0.86f, 0.84f, 0.8f), onTap);
|
||
UiKit.Border(cell, deployed ? UiKit.Red : UiKit.Line, deployed ? 4f : 2f);
|
||
var lv = s.Save.Level(h.id);
|
||
var hs = s.Save.Hero(h.id);
|
||
UiKit.Portrait("Face", cell.transform, h, new Vector2(0f, 0.5f), new Vector2(0f, 0.5f), new Vector2(12f, 8f), new Vector2(116f, 108f), false, 2f, new Color(0.9f, 0.86f, 0.8f));
|
||
int star = hs != null ? hs.star : h.rarity;
|
||
UiKit.Label(cell.transform, UiKit.Stars(star, star), 22, UiKit.Star, TextAnchor.MiddleCenter, new Vector2(0f, 0f), new Vector2(0f, 0f), new Vector2(12f, 2f), new Vector2(116f, 30f));
|
||
UiKit.TypeBadge(cell.transform, h.type, new Vector2(0f, 1f), new Vector2(0f, 1f), new Vector2(142f, -16f), 40f);
|
||
UiKit.Label(cell.transform, owned ? "Lv " + (lv != null ? lv.lv : 1) : "미보유", 30, UiKit.Ink, TextAnchor.MiddleLeft, new Vector2(0f, 1f), new Vector2(0f, 1f), new Vector2(204f, -12f), new Vector2(150f, 48f));
|
||
if (deployed)
|
||
{
|
||
var b = UiKit.Box("Deployed", cell.transform, new Vector2(1f, 1f), new Vector2(1f, 1f), new Vector2(-12f, -14f), new Vector2(124f, 44f), UiKit.Red);
|
||
UiKit.FillLabel(b.transform, "출전 중", 24, UiKit.White);
|
||
}
|
||
if (hs != null)
|
||
{
|
||
var g = UiKit.Box("Grade", cell.transform, new Vector2(1f, 0f), new Vector2(1f, 0f), new Vector2(-12f, 14f), new Vector2(56f, 40f), UiKit.GradeColor(hs.grade));
|
||
UiKit.FillLabel(g.transform, UiKit.GradeKo(hs.grade), 24, UiKit.White);
|
||
}
|
||
var name = UiKit.Label(cell.transform, h.nameKo, 44, owned ? UiKit.Ink : UiKit.InkSoft, TextAnchor.MiddleLeft, new Vector2(0f, 0f), new Vector2(0f, 0f), new Vector2(142f, 12f), new Vector2(290f, 66f));
|
||
name.horizontalOverflow = HorizontalWrapMode.Overflow;
|
||
if (owned && s.CanGrowAny(h.id)) UiKit.Dot("New", cell.transform, new Vector2(0f, 1f), new Vector2(0.5f, 0.5f), new Vector2(14f, -10f), 26f, UiKit.Red);
|
||
return cell;
|
||
}
|
||
}
|
||
|
||
/// <summary>영웅 탭 = 보유 영웅·병사 목록(장수|병사 · 2줄 카드) → 탭 = 영웅 상세 · 도감.</summary>
|
||
public class HeroListScreen : OutGameScreen
|
||
{
|
||
bool soldiers;
|
||
RectTransform content;
|
||
ScrollRect scroll;
|
||
Button tabHero;
|
||
Button tabSoldier;
|
||
|
||
public bool ShowingSoldiers
|
||
{
|
||
get { return soldiers; }
|
||
}
|
||
|
||
public override void Build()
|
||
{
|
||
Tab = 0;
|
||
Header("영웅", "레벨 · 승급 · 진화 · 스킬", true);
|
||
var body = Body();
|
||
tabHero = UiKit.Btn("TabHero", body, "장수", 36, UiKit.Red, UiKit.White, new Vector2(0f, 1f), new Vector2(0f, 1f), new Vector2(24f, -20f), new Vector2(220f, 84f), () => SetFilter(false));
|
||
tabSoldier = UiKit.Btn("TabSoldier", body, "병사", 36, UiKit.Paper, UiKit.Ink, new Vector2(0f, 1f), new Vector2(0f, 1f), new Vector2(258f, -20f), new Vector2(220f, 84f), () => SetFilter(true));
|
||
UiKit.Btn("Codex", body, "도감", 36, UiKit.Dark, UiKit.White, new Vector2(1f, 1f), new Vector2(1f, 1f), new Vector2(-24f, -20f), new Vector2(220f, 84f), () => HeroDetailScreen.ShowCodex(Root));
|
||
content = UiKit.ScrollGrid("List", body, 24f, 24f, 124f, 16f, new Vector2(506f, 150f), new Vector2(20f, 18f), 2, out scroll);
|
||
}
|
||
|
||
public void SetFilter(bool soldier)
|
||
{
|
||
soldiers = soldier;
|
||
Refresh();
|
||
}
|
||
|
||
public override void Refresh()
|
||
{
|
||
tabHero.GetComponent<Image>().color = soldiers ? UiKit.Paper : UiKit.Red;
|
||
UiKit.LabelOf(tabHero).color = soldiers ? UiKit.Ink : UiKit.White;
|
||
tabSoldier.GetComponent<Image>().color = soldiers ? UiKit.Red : UiKit.Paper;
|
||
UiKit.LabelOf(tabSoldier).color = soldiers ? UiKit.White : UiKit.Ink;
|
||
UiKit.LabelOf(tabHero).text = "장수 " + S.Owned(false).Count;
|
||
UiKit.LabelOf(tabSoldier).text = "병사 " + S.Owned(true).Count;
|
||
UiKit.Clear(content);
|
||
foreach (var h in S.Owned(soldiers))
|
||
{
|
||
var id = h.id;
|
||
HeroCards.Card(content, S, h, S.InActivePreset(id), true, () => Root.ShowHero(id));
|
||
}
|
||
}
|
||
|
||
public int CardCount
|
||
{
|
||
get { return content.childCount; }
|
||
}
|
||
}
|
||
|
||
/// <summary>
|
||
/// 영웅 상세(img06 · 기획 S6 v4) — 전투력 · 일러 + 양옆 장비 6칸(빈 칸 탭 = 가방에서 장착 · 1칸 = 1강) · 이름 띠(병종 · 이름 · ★) ·
|
||
/// 스킬 정보(액티브·패시브 = 이름·효과·Lv·쿨 · 표시만 · 스킬 레벨업 = B 단계) · Lv/경험 바 + 레벨업(골드) · 승급(6칸) · 조각 바 + 진화 · 상세정보 · 도감 · ◀ ▶ 전환.
|
||
/// </summary>
|
||
public class HeroDetailScreen : OutGameScreen
|
||
{
|
||
string id;
|
||
readonly List<string> order = new List<string>();
|
||
|
||
Text power;
|
||
RectTransform art;
|
||
readonly Image[] slotImg = new Image[6];
|
||
readonly Text[] slotName = new Text[6];
|
||
readonly Text[] slotState = new Text[6];
|
||
Image typeDot;
|
||
Text typeMark;
|
||
Text nameText;
|
||
Text subText;
|
||
Text starText;
|
||
Text[] skillName = new Text[2];
|
||
Text[] skillDesc = new Text[2];
|
||
Text[] skillChip = new Text[2];
|
||
Text lvText;
|
||
Text expText;
|
||
RectTransform expBar;
|
||
Button levelBtn;
|
||
Button promoteBtn;
|
||
Text shardText;
|
||
RectTransform shardBar;
|
||
Button evolveBtn;
|
||
Button skillBtn;
|
||
|
||
public string HeroId
|
||
{
|
||
get { return id; }
|
||
}
|
||
|
||
public void Select(string heroId)
|
||
{
|
||
id = heroId;
|
||
var h = S.Def(heroId);
|
||
order.Clear();
|
||
if (h != null)
|
||
foreach (var o in S.Owned(h.isSoldier)) order.Add(o.id);
|
||
}
|
||
|
||
public override void Build()
|
||
{
|
||
Tab = 0;
|
||
Header("영웅", "레벨 · 승급 · 진화 · 스킬", true);
|
||
var body = Body();
|
||
|
||
// ① 카드: 전투력 · 일러 · 장비 6칸 · 이름 띠
|
||
var card = UiKit.TopBand("Card", body, 16f, 720f, 24f, 24f);
|
||
var cimg = UiKit.Paint(card, UiKit.Paper);
|
||
UiKit.Border(cimg, UiKit.Line, 3f);
|
||
UiKit.Dot("Halo", card, new Vector2(0.5f, 1f), new Vector2(0.5f, 1f), new Vector2(0f, -100f), 500f, new Color(0.93f, 0.9f, 0.84f));
|
||
power = UiKit.Label(card, "", 44, UiKit.Ink, TextAnchor.MiddleCenter, new Vector2(0.5f, 1f), new Vector2(0.5f, 1f), new Vector2(0f, -16f), new Vector2(560f, 70f));
|
||
UiKit.Btn("Prev", card, "◀", 40, UiKit.Dark, UiKit.White, new Vector2(0f, 1f), new Vector2(0f, 1f), new Vector2(20f, -16f), new Vector2(96f, 72f), () => Step(-1));
|
||
UiKit.Btn("Next", card, "▶", 40, UiKit.Dark, UiKit.White, new Vector2(1f, 1f), new Vector2(1f, 1f), new Vector2(-20f, -16f), new Vector2(96f, 72f), () => Step(1));
|
||
art = UiKit.Rect("Art", card, new Vector2(0.5f, 1f), new Vector2(0.5f, 1f), new Vector2(0f, -96f), new Vector2(560f, 500f));
|
||
for (int i = 0; i < 6; i++)
|
||
{
|
||
int k = i;
|
||
bool left = i < 3;
|
||
int row = i % 3;
|
||
var a = left ? new Vector2(0f, 1f) : new Vector2(1f, 1f);
|
||
var b = UiKit.Btn("Slot" + i, card, "", 24, UiKit.Slot, UiKit.Ink, a, a, new Vector2(left ? 22f : -22f, -104f - row * 172f), new Vector2(196f, 156f), () => OnSlot(k));
|
||
slotImg[i] = b.GetComponent<Image>();
|
||
UiKit.LabelOf(b).text = "";
|
||
slotName[i] = UiKit.Label(b.transform, "", 30, UiKit.Ink, TextAnchor.MiddleCenter, new Vector2(0.5f, 1f), new Vector2(0.5f, 1f), new Vector2(0f, -12f), new Vector2(186f, 84f));
|
||
slotState[i] = UiKit.Label(b.transform, "", 24, UiKit.InkSoft, TextAnchor.MiddleCenter, new Vector2(0.5f, 0f), new Vector2(0.5f, 0f), new Vector2(0f, 10f), new Vector2(186f, 44f), false);
|
||
}
|
||
var band = UiKit.Rect("NameBand", card, new Vector2(0.5f, 0f), new Vector2(0.5f, 0f), Vector2.zero, new Vector2(0f, 116f));
|
||
band.anchorMin = new Vector2(0f, 0f);
|
||
band.anchorMax = new Vector2(1f, 0f);
|
||
band.offsetMin = new Vector2(0f, 0f);
|
||
band.offsetMax = new Vector2(0f, 116f);
|
||
UiKit.Paint(band, UiKit.Dark);
|
||
typeDot = UiKit.Dot("TypeDot", band, new Vector2(0f, 0.5f), new Vector2(0f, 0.5f), new Vector2(24f, 0f), 80f, UiKit.Red);
|
||
typeMark = UiKit.FillLabel(typeDot.transform, "", 40, UiKit.White);
|
||
nameText = UiKit.Label(band, "", 60, UiKit.White, TextAnchor.MiddleLeft, new Vector2(0f, 0.5f), new Vector2(0f, 0.5f), new Vector2(124f, 4f), new Vector2(300f, 90f));
|
||
nameText.horizontalOverflow = HorizontalWrapMode.Overflow;
|
||
subText = UiKit.Label(band, "", 28, new Color(0.85f, 0.8f, 0.75f), TextAnchor.MiddleLeft, new Vector2(0f, 0.5f), new Vector2(0f, 0.5f), new Vector2(420f, 0f), new Vector2(330f, 80f), false);
|
||
starText = UiKit.Label(band, "", 52, UiKit.Star, TextAnchor.MiddleRight, new Vector2(1f, 0.5f), new Vector2(1f, 0.5f), new Vector2(-24f, 0f), new Vector2(300f, 80f));
|
||
|
||
// ② 스킬 정보
|
||
var skill = UiKit.TopBand("Skill", body, 752f, 400f, 24f, 24f);
|
||
var simg = UiKit.Paint(skill, UiKit.Paper);
|
||
UiKit.Border(simg, UiKit.Line, 3f);
|
||
UiKit.Label(skill, "스킬", 40, UiKit.Ink, TextAnchor.MiddleLeft, new Vector2(0f, 1f), new Vector2(0f, 1f), new Vector2(28f, -14f), new Vector2(300f, 60f));
|
||
UiKit.Label(skill, "액티브 1 · 패시브 1", 26, UiKit.InkSoft, TextAnchor.MiddleRight, new Vector2(1f, 1f), new Vector2(1f, 1f), new Vector2(-28f, -14f), new Vector2(400f, 60f), false);
|
||
for (int i = 0; i < 2; i++)
|
||
{
|
||
var c = UiKit.TopBand("Skill" + i, skill, 86f + i * 152f, 140f, 20f, 20f);
|
||
var ci = UiKit.Paint(c, new Color(0.98f, 0.96f, 0.9f));
|
||
UiKit.Border(ci, UiKit.Line, 2f);
|
||
var d = UiKit.Dot("Kind", c, new Vector2(0f, 0.5f), new Vector2(0f, 0.5f), new Vector2(18f, 0f), 92f, i == 0 ? UiKit.Red : UiKit.Dark);
|
||
UiKit.FillLabel(d.transform, i == 0 ? "액" : "패", 40, UiKit.White);
|
||
skillName[i] = UiKit.Label(c, "", 34, UiKit.Ink, TextAnchor.MiddleLeft, new Vector2(0f, 1f), new Vector2(0f, 1f), new Vector2(128f, -8f), new Vector2(560f, 56f));
|
||
skillName[i].horizontalOverflow = HorizontalWrapMode.Overflow;
|
||
skillDesc[i] = UiKit.Label(c, "", 26, UiKit.InkSoft, TextAnchor.UpperLeft, new Vector2(0f, 1f), new Vector2(0f, 1f), new Vector2(128f, -64f), new Vector2(840f, 72f), false);
|
||
var chip = UiKit.Box("Chip", c, new Vector2(1f, 1f), new Vector2(1f, 1f), new Vector2(-14f, -12f), new Vector2(240f, 46f), i == 0 ? UiKit.Red : UiKit.Dark);
|
||
skillChip[i] = UiKit.FillLabel(chip.transform, "", 24, UiKit.White);
|
||
}
|
||
|
||
// ③ 레벨 · 승급
|
||
var lvRow = UiKit.TopBand("Level", body, 1168f, 110f, 24f, 24f);
|
||
lvText = UiKit.Label(lvRow, "", 42, UiKit.Ink, TextAnchor.MiddleLeft, new Vector2(0f, 1f), new Vector2(0f, 1f), new Vector2(4f, 0f), new Vector2(330f, 60f));
|
||
lvText.horizontalOverflow = HorizontalWrapMode.Overflow;
|
||
expText = UiKit.Label(lvRow, "", 28, UiKit.Ink, TextAnchor.MiddleRight, new Vector2(0f, 1f), new Vector2(0f, 1f), new Vector2(330f, 0f), new Vector2(230f, 60f));
|
||
expBar = UiKit.Bar("ExpBar", lvRow, new Vector2(0f, 0f), new Vector2(0f, 0f), new Vector2(4f, 10f), new Vector2(556f, 30f), new Color(0.86f, 0.82f, 0.75f), new Color(0.47f, 0.38f, 0.32f));
|
||
levelBtn = UiKit.Btn("LevelUp", lvRow, "", 30, UiKit.Red, UiKit.White, new Vector2(1f, 0.5f), new Vector2(1f, 0.5f), new Vector2(-252f, 0f), new Vector2(204f, 106f), OnLevelUp);
|
||
promoteBtn = UiKit.Btn("Promote", lvRow, "", 30, UiKit.Disabled, UiKit.White, new Vector2(1f, 0.5f), new Vector2(1f, 0.5f), new Vector2(0f, 0f), new Vector2(236f, 106f), OnPromote);
|
||
|
||
// ④ 조각 · 진화
|
||
var shRow = UiKit.TopBand("Shard", body, 1290f, 96f, 24f, 24f);
|
||
var sd = UiKit.Dot("ShardDot", shRow, new Vector2(0f, 0.5f), new Vector2(0f, 0.5f), new Vector2(0f, -14f), 54f, UiKit.Purple);
|
||
UiKit.FillLabel(sd.transform, "조", 28, UiKit.White);
|
||
UiKit.Label(shRow, "영웅 조각", 32, UiKit.Ink, TextAnchor.MiddleLeft, new Vector2(0f, 1f), new Vector2(0f, 1f), new Vector2(64f, 0f), new Vector2(300f, 46f));
|
||
shardBar = UiKit.Bar("ShardBar", shRow, new Vector2(0f, 0f), new Vector2(0f, 0f), new Vector2(64f, 4f), new Vector2(690f, 42f), new Color(0.86f, 0.82f, 0.75f), UiKit.Purple);
|
||
shardText = UiKit.Label(shardBar.parent, "", 28, UiKit.Ink, TextAnchor.MiddleCenter, new Vector2(0.5f, 0.5f), new Vector2(0.5f, 0.5f), Vector2.zero, new Vector2(680f, 42f));
|
||
evolveBtn = UiKit.Btn("Evolve", shRow, "", 30, UiKit.Red, UiKit.White, new Vector2(1f, 0.5f), new Vector2(1f, 0.5f), new Vector2(0f, 0f), new Vector2(236f, 96f), OnEvolve);
|
||
|
||
// ⑤ 상세정보 · 도감 · 스킬 레벨업(B)
|
||
var btnRow = UiKit.TopBand("Buttons", body, 1402f, 96f, 24f, 24f);
|
||
float bw = (1032f - 40f) / 3f;
|
||
UiKit.Btn("Detail", btnRow, "상세정보", 36, UiKit.Dark, UiKit.White, new Vector2(0f, 0.5f), new Vector2(0f, 0.5f), Vector2.zero, new Vector2(bw, 96f), ShowStats);
|
||
UiKit.Btn("Codex", btnRow, "도감", 36, UiKit.Dark, UiKit.White, new Vector2(0.5f, 0.5f), new Vector2(0.5f, 0.5f), Vector2.zero, new Vector2(bw, 96f), () => ShowCodex(Root));
|
||
skillBtn = UiKit.Btn("SkillUp", btnRow, "스킬 레벨업", 32, UiKit.Red, UiKit.White, new Vector2(1f, 0.5f), new Vector2(1f, 0.5f), Vector2.zero, new Vector2(bw, 96f), OnSkillUp);
|
||
}
|
||
|
||
void Step(int d)
|
||
{
|
||
if (order.Count == 0) return;
|
||
int i = Mathf.Max(0, order.IndexOf(id));
|
||
id = order[(i + d + order.Count) % order.Count];
|
||
Refresh();
|
||
}
|
||
|
||
public override void Refresh()
|
||
{
|
||
var h = S.Def(id);
|
||
if (h == null) return;
|
||
var db = S.Db;
|
||
var lv = S.Save.Level(id);
|
||
var hs = S.Save.Hero(id);
|
||
var st = S.StatsOf(id);
|
||
power.text = "전투력 " + st.power.ToString("N0");
|
||
|
||
UiKit.Clear(art);
|
||
UiKit.Portrait("Hero", art, h, new Vector2(0.5f, 0.5f), new Vector2(0.5f, 0.5f), Vector2.zero, new Vector2(560f, 500f), false, 1f, new Color(1f, 1f, 1f, 0f));
|
||
|
||
for (int i = 0; i < 6; i++)
|
||
{
|
||
string need = h.isSoldier ? null : HeroRules.RequiredGear(db, h, hs, i);
|
||
var g = db.Gear.Get(need);
|
||
bool on = hs != null && i < hs.gear.Count && !string.IsNullOrEmpty(hs.gear[i]);
|
||
int have = need != null ? S.Save.inv.GearCount(need) : 0;
|
||
slotImg[i].gameObject.SetActive(need != null);
|
||
if (need == null) continue;
|
||
slotName[i].text = g != null ? g.nameKo : need;
|
||
if (on)
|
||
{
|
||
slotImg[i].color = new Color(0.9f, 0.95f, 0.86f);
|
||
slotState[i].text = "<color=#3a6a30>○ 장착</color> · " + UiKit.GradeKo(g != null ? g.grade : "");
|
||
}
|
||
else if (have > 0)
|
||
{
|
||
slotImg[i].color = new Color(1f, 0.93f, 0.86f);
|
||
slotState[i].text = "<color=#a03a22>탭하여 장착 ×" + have + "</color>";
|
||
}
|
||
else
|
||
{
|
||
slotImg[i].color = UiKit.Slot;
|
||
slotState[i].text = "없음 · " + UiKit.GradeKo(g != null ? g.grade : "");
|
||
}
|
||
}
|
||
|
||
typeDot.color = UiKit.TypeColor(h.type);
|
||
typeMark.text = UnitTypeInfo.Mark(h.type);
|
||
nameText.text = h.nameKo;
|
||
subText.text = UnitTypeInfo.Korean(h.type) + " · " + (h.isSoldier ? "병사 유닛" : UiKit.GradeKo(hs.grade) + " 등급");
|
||
starText.text = h.isSoldier ? UiKit.Stars(h.rarity, 3) : UiKit.Stars(hs.star, db.Evolve.MaxStar);
|
||
|
||
var skills = new[] { db.Skills.Get(h.skillActive), db.Skills.Get(h.skillPassive) };
|
||
for (int i = 0; i < 2; i++)
|
||
{
|
||
int cap = SkillRules.Cap(db, h, hs, i); // 등급 + ★3 액티브 +1(PD #1093 B)
|
||
var sk = skills[i];
|
||
if (sk == null)
|
||
{
|
||
skillName[i].text = h.isSoldier ? "병사 유닛 — 스킬 없음" : "—";
|
||
skillDesc[i].text = "";
|
||
skillChip[i].transform.parent.gameObject.SetActive(false);
|
||
continue;
|
||
}
|
||
skillChip[i].transform.parent.gameObject.SetActive(true);
|
||
skillName[i].text = sk.nameKo + (string.IsNullOrEmpty(sk.hanja) ? "" : "(" + sk.hanja + ")") + " · " + (sk.kind == "active" ? "액티브" : "패시브");
|
||
skillDesc[i].text = SkillInfoDb.DisplayDesc(sk);
|
||
int slv = hs != null && hs.skillLv != null && hs.skillLv.Length > i ? hs.skillLv[i] : 1;
|
||
skillChip[i].text = "Lv " + slv + "/" + cap + (sk.kind == "active" ? " · 쿨 " + sk.cooldown + "턴" : (hs != null && SkillRules.PassiveMult(db, hs.star) > 1f ? " · ★×" + SkillRules.PassiveMult(db, hs.star).ToString("0.##") : ""));
|
||
}
|
||
bool canSkill = !h.isSoldier && hs != null && (SkillRules.CanLevelUp(db, S.Save, h, hs, 0) == null || SkillRules.CanLevelUp(db, S.Save, h, hs, 1) == null);
|
||
UiKit.LabelOf(skillBtn).text = "스킬 레벨업\n<size=22>" + (h.isSoldier ? "병사 = 스킬 없음" : "스킬서 " + S.Save.inv.books.skill) + "</size>";
|
||
skillBtn.GetComponent<Image>().color = canSkill ? UiKit.Red : UiKit.Disabled;
|
||
|
||
int lvCap = HeroRules.LevelCap(db, S.Save);
|
||
var row = db.Levels.Get(lv.lv);
|
||
lvText.text = "Lv " + lv.lv + " / " + lvCap + (lvCap < db.Levels.MaxLevel ? "" : "");
|
||
float pct = row != null && row.expToNext > 0 ? lv.exp / (float)row.expToNext : 1f;
|
||
expText.text = lv.lv >= db.Levels.MaxLevel ? "최고 레벨" : pct >= 1f ? "경험치 100% ↑" : "경험치 " + (pct * 100f).ToString("0.00") + "%";
|
||
UiKit.SetBar(expBar, pct);
|
||
var lvWhy = HeroRules.CanLevelUp(db, S.Save, lv);
|
||
UiKit.LabelOf(levelBtn).text = "레벨업\n<size=24>" + (row != null && lv.lv < db.Levels.MaxLevel ? "골드 " + row.goldCost.ToString("N0") : "최고") + "</size>";
|
||
levelBtn.GetComponent<Image>().color = lvWhy == null ? UiKit.Red : UiKit.Disabled;
|
||
|
||
var promoWhy = HeroRules.CanPromote(db, h, hs);
|
||
var gearList = h.isSoldier ? null : db.Heroes.GearFor(h, hs.grade);
|
||
UiKit.LabelOf(promoteBtn).text = h.isSoldier ? "승급\n<size=24>병사 없음</size>"
|
||
: gearList == null ? "승급\n<size=24>최고 등급</size>"
|
||
: "승급\n<size=24>장비 " + HeroRules.EquippedCount(hs) + "/" + gearList.Count + "칸</size>";
|
||
promoteBtn.GetComponent<Image>().color = promoWhy == null ? UiKit.Red : UiKit.Disabled;
|
||
|
||
int need2 = HeroRules.ShardsForNext(db, hs);
|
||
if (h.isSoldier)
|
||
{
|
||
shardText.text = "병사 유닛 — 진화 없음 (중복 = 골드)";
|
||
UiKit.SetBar(shardBar, 0f);
|
||
UiKit.LabelOf(evolveBtn).text = "진화\n<size=24>없음</size>";
|
||
evolveBtn.GetComponent<Image>().color = UiKit.Disabled;
|
||
}
|
||
else
|
||
{
|
||
shardText.text = need2 > 0 ? hs.shards + " / " + need2 : hs.shards + " · 최고 ★";
|
||
UiKit.SetBar(shardBar, need2 > 0 ? hs.shards / (float)need2 : 1f);
|
||
UiKit.LabelOf(evolveBtn).text = hs.star >= db.Evolve.MaxStar ? "진화\n<size=24>최고 ★</size>" : "진화\n<size=24>다음 ★" + (hs.star + 1) + "</size>";
|
||
evolveBtn.GetComponent<Image>().color = HeroRules.CanEvolve(db, h, hs) == null ? UiKit.Red : UiKit.Disabled;
|
||
}
|
||
}
|
||
|
||
void OnSlot(int i)
|
||
{
|
||
var h = S.Def(id);
|
||
var hs = S.Save.Hero(id);
|
||
if (h == null || hs == null) return;
|
||
var need = HeroRules.RequiredGear(S.Db, h, hs, i);
|
||
var g = S.Db.Gear.Get(need);
|
||
if (need == null) return;
|
||
if (!string.IsNullOrEmpty(hs.gear[i]))
|
||
{
|
||
Root.Toast("장착됨: " + (g != null ? g.nameKo : need) + " — 6칸을 모두 채우면 승급");
|
||
return;
|
||
}
|
||
var why = S.Equip(id, i);
|
||
if (why == null)
|
||
{
|
||
Root.Toast((g != null ? g.nameKo : need) + " 장착 · 1칸 = 1강(누적 " + hs.gearTotal + ")");
|
||
return;
|
||
}
|
||
string from = g != null ? g.dropFromChapter + "장~ 스테이지 드랍" : "";
|
||
Root.Modal("필요 장비", (g != null ? g.nameKo + " (" + UiKit.GradeKo(g.grade) + " 등급)" : need) + "\n보유 0\n\n획득: " + from + " · 거래 > 상점(흰/녹)" +
|
||
(g != null && g.craftCount > 0 ? "\n합성 = 하위 " + g.craftCount + "개 + 도면 " + g.craftBlueprint + " (2차)" : ""),
|
||
new OutGameRoot.ModalButton("상점 가기", UiKit.Red, () => Root.Trade.OpenShop()),
|
||
new OutGameRoot.ModalButton("닫기", UiKit.Dark, null));
|
||
}
|
||
|
||
void OnLevelUp()
|
||
{
|
||
var why = S.LevelUp(id);
|
||
Root.Toast(why ?? S.Def(id).nameKo + " Lv " + S.Save.Level(id).lv + "!");
|
||
}
|
||
|
||
void OnPromote()
|
||
{
|
||
var h = S.Def(id);
|
||
var why = S.Promote(id);
|
||
Root.Toast(why ?? h.nameKo + " 승급 → " + UiKit.GradeKo(S.Save.Hero(id).grade) + " 등급 · 새 장비 6칸");
|
||
}
|
||
|
||
/// <summary>스킬 레벨업(PD #1093 B): 액티브·패시브 중 고르기 → 스킬서 + 골드(skill_levels.csv) · 상한 = 등급 + ★3 액티브 +1.</summary>
|
||
public void OnSkillUp()
|
||
{
|
||
var h = S.Def(id);
|
||
var hs = S.Save.Hero(id);
|
||
if (h == null || hs == null || h.isSoldier)
|
||
{
|
||
Root.Toast("병사 유닛은 스킬이 없습니다");
|
||
return;
|
||
}
|
||
var db = S.Db;
|
||
var buttons = new List<OutGameRoot.ModalButton>();
|
||
var body = new System.Text.StringBuilder("보유 스킬서 " + S.Save.inv.books.skill + " · 골드 " + S.Save.gold.ToString("N0") + "\n");
|
||
for (int i = 0; i < 2; i++)
|
||
{
|
||
int k = i;
|
||
var sk = SkillRules.Skill(db, h, i);
|
||
if (sk == null) continue;
|
||
int lv = SkillRules.Level(hs, i);
|
||
var cost = db.Skills.CostTo(lv + 1);
|
||
var why = SkillRules.CanLevelUp(db, S.Save, h, hs, i);
|
||
body.Append("\n").Append(i == 0 ? "액티브 " : "패시브 ").Append(sk.nameKo).Append(" Lv ").Append(lv).Append(" / ").Append(SkillRules.Cap(db, h, hs, i));
|
||
if (cost != null && lv < sk.lvMax) body.Append(" → 스킬서 ").Append(cost.books).Append(" · 골드 ").Append(cost.gold.ToString("N0"));
|
||
if (why != null) body.Append("\n <color=#a03a22>").Append(why).Append("</color>");
|
||
buttons.Add(new OutGameRoot.ModalButton((i == 0 ? "액티브" : "패시브") + " Lv+1", why == null ? UiKit.Red : UiKit.Disabled, () =>
|
||
{
|
||
var r = SkillRules.LevelUp(S.Db, S.Save, h, hs, k);
|
||
if (r == null) S.Commit();
|
||
Refresh();
|
||
if (r == null) OnSkillUp(); // 이어서 올릴 수 있게 다시 연다
|
||
Root.Toast(r ?? sk.nameKo + " Lv " + SkillRules.Level(hs, k) + "!");
|
||
}));
|
||
}
|
||
buttons.Add(new OutGameRoot.ModalButton("닫기", UiKit.Dark, null));
|
||
Root.Modal("스킬 레벨업 — " + h.nameKo, body.ToString(), buttons.ToArray());
|
||
}
|
||
|
||
void OnEvolve()
|
||
{
|
||
var why = S.Evolve(id);
|
||
Root.Toast(why ?? S.Def(id).nameKo + " 진화 → ★" + S.Save.Hero(id).star);
|
||
}
|
||
|
||
void ShowStats()
|
||
{
|
||
var h = S.Def(id);
|
||
var st = S.StatsOf(id);
|
||
var e = S.Db.Economy;
|
||
var hs = S.Save.Hero(id);
|
||
string body =
|
||
"기본(" + UnitTypeInfo.Korean(h.type) + ") HP " + st.baseHp + " · 공 " + st.baseAtk + " · 방 " + st.baseDef + "\n" +
|
||
"영웅 배율 ×" + st.hpMult + " · ×" + st.atkMult + " · ×" + st.defMult + "\n" +
|
||
"레벨 Lv " + S.Save.Level(id).lv + " +" + st.lvPct.ToString("0.#") + "%\n" +
|
||
"승급 " + (hs != null ? UiKit.GradeKo(hs.grade) : "—") + " +" + st.promoPct.ToString("0.#") + "% · 장비 누적 " + (hs != null ? hs.gearTotal : 0) + "개 +" + st.gearPct.ToString("0.#") + "%\n" +
|
||
"진화 " + (hs != null ? "★" + hs.star : "—") + " +" + st.starPct.ToString("0.#") + "%\n" +
|
||
"훈련(내정 · 2차) +" + st.trainPct.ToString("0.#") + "%\n\n" +
|
||
"<size=40>HP " + st.Hp + " · 공 " + st.Atk + " · 방 " + st.Def + "</size>\n" +
|
||
"전투력 " + st.power.ToString("N0") + " = HP/" + e.PowerHpDiv + " + 공×" + e.PowerAtkW + " + 방×" + e.PowerDefW;
|
||
Root.Modal("상세정보 — " + h.nameKo, body, new OutGameRoot.ModalButton("닫기", UiKit.Dark, null));
|
||
}
|
||
|
||
/// <summary>도감 = 전 영웅·병사(미보유 회색).</summary>
|
||
public static void ShowCodex(OutGameRoot root)
|
||
{
|
||
var s = root.Session;
|
||
int owned = 0;
|
||
foreach (var h in s.Db.Heroes.heroes)
|
||
if (s.Save.Owns(h.id)) owned++;
|
||
var content = root.ModalCustom("도감 " + owned + " / " + s.Db.Heroes.heroes.Count, 1560f, new OutGameRoot.ModalButton("닫기", UiKit.Dark, null));
|
||
ScrollRect sr;
|
||
var grid = UiKit.ScrollGrid("Codex", content, 0f, 0f, 0f, 0f, new Vector2(420f, 140f), new Vector2(20f, 14f), 2, out sr);
|
||
foreach (var h in s.Db.Heroes.heroes)
|
||
{
|
||
bool own = s.Save.Owns(h.id);
|
||
var hero = h;
|
||
var cell = 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 ? " · 보유" : " · 미보유 — 거래 > 뽑기")));
|
||
if (!own) cell.color = new Color(0.78f, 0.76f, 0.73f);
|
||
}
|
||
}
|
||
}
|
||
}
|