455 lines
29 KiB
C#
455 lines
29 KiB
C#
using System.Collections.Generic;
|
||
using UnityEngine;
|
||
using UnityEngine.UI;
|
||
|
||
namespace TKS.OutGame
|
||
{
|
||
/// <summary>
|
||
/// 연무장(로비 출정 우측 · 기획 S13 · 목업 img09 · PD #1093 C) — 첫 페이지 = 모드 카드 4(규칙 · 보상 · 입장) → 카드 탭 = 모드 페이지:
|
||
/// ① 천하제일 탑(다음 층 · 적 템플릿 · 배율 · 보상 · 입장권 + 광고) ② 일일 던전 3(요일 · 남은 입장 · 보상) ③ 투기장(메달 · 주간 순위 · 샘플 상대 10 · 메달 상점)
|
||
/// ④ 적장 토벌(이번 주 보스 · 누적 피해 · 하루 1). 도전 = OutGameRoot.StartMode → BattleManager.StartMode(적 편성 · 배율 · 제한 턴) → 결과 패널 → 탭 = 이 페이지로.
|
||
/// </summary>
|
||
public class ArenaScreen : OutGameScreen
|
||
{
|
||
public static readonly string[] ModeNames = { "천하제일 탑", "일일 던전 3", "투기장", "적장 토벌" };
|
||
static readonly string[] Ribbons = { "ribbon_blue", "ribbon_purple", "ribbon_red", "ribbon_orange" }; // 카드 리본(설계서 §3⑧ · 테마 스킨 id)
|
||
|
||
int page;
|
||
RectTransform root;
|
||
|
||
/// <summary>0 = 카드 · 1 탑 · 2 던전 · 3 투기장 · 4 적장 토벌.</summary>
|
||
public int Page
|
||
{
|
||
get { return page; }
|
||
}
|
||
|
||
public override void Build()
|
||
{
|
||
if (UISkin.On) UiKit.Paint(UiKit.Fill("ListBg", Rt), UiKit.Col("list_bg", UiKit.Bg), false); // 목록형 바탕(Fable §5-3)
|
||
Header("연무장", "탑 · 일일 던전 · 투기장 · 적장 토벌", true);
|
||
root = Body();
|
||
}
|
||
|
||
public void SetPage(int p)
|
||
{
|
||
page = Mathf.Clamp(p, 0, 4);
|
||
Refresh();
|
||
}
|
||
|
||
public override void OnShow()
|
||
{
|
||
S.Do(() =>
|
||
{
|
||
ArenaRules.RollDaily(S.Db, S.Save, S.Now);
|
||
ArenaRules.EnsureSeason(S.Db, S.Save, S.Now, S.Rng);
|
||
ArenaRules.RaidBoss(S.Db, S.Save, S.Now);
|
||
return null;
|
||
});
|
||
}
|
||
|
||
public override bool OnBack()
|
||
{
|
||
if (page == 0) return false;
|
||
SetPage(0);
|
||
return true;
|
||
}
|
||
|
||
public override void Refresh()
|
||
{
|
||
UiKit.Clear(root);
|
||
switch (page)
|
||
{
|
||
case 0: BuildCards(); break;
|
||
case 1: BuildTower(); break;
|
||
case 2: BuildDungeons(); break;
|
||
case 3: BuildArena(); break;
|
||
case 4: BuildRaid(); break;
|
||
}
|
||
}
|
||
|
||
// ---------- 카드 4 ----------
|
||
|
||
void BuildCards()
|
||
{
|
||
var db = S.Db;
|
||
var d = S.Save;
|
||
var e = db.Economy;
|
||
var now = S.Now;
|
||
string boss = db.Heroes.Get(ArenaRules.RaidBoss(db, d, now)) != null ? db.Heroes.Get(ArenaRules.RaidBoss(db, d, now)).nameKo : "";
|
||
string[,] text =
|
||
{
|
||
{ "100층 · 층마다 고정 편성 적 · 10층마다 보스", "보옥 · 도면 · 10층마다 보물 금 상자", "입장권 하루 " + e.TowerTicketsDaily + "(광고 +" + e.TowerAdTickets + ") · 진행 저장", "다음 " + ArenaRules.TowerNext(db, d) + "층 · 입장권 " + d.arena.towerTickets },
|
||
{ "군량고(골드) · 대장간(승급 장비·운철) · 사당(스킬서·영웅 조각) — 요일 순환", "던전별 재화", "각 하루 " + (db.Dungeons.dungeons.Count > 0 ? db.Dungeons.dungeons[0].entriesPerDay : 0) + "(패스 +1 준비 중)", "오늘 열림 " + OpenCount(now) + "곳" },
|
||
{ "비동기 5v5 · 상대 편성은 AI 가 조작(적 AI 재사용) · 주간 랭킹", "투기장 메달 → 영웅 조각 상점", "하루 " + db.Arena.EntriesPerDay, "메달 " + d.arena.medals + " · " + ArenaRules.Rank(d) + "위 · 남은 " + ArenaRules.ArenaLeft(db, d, now) },
|
||
{ "주간 보스(여포·조조 …) · 누적 피해", "보물 명장 상자", "하루 " + e.RaidDaily, "이번 주 " + boss + " · 누적 " + d.arena.raidDamage.ToString("N0") },
|
||
};
|
||
float w = 508f, h = 700f;
|
||
if (UISkin.Has("card4_bg") && UISkin.Has("btn_l_yellow"))
|
||
{
|
||
CardsKit(text, w, h);
|
||
return;
|
||
}
|
||
for (int i = 0; i < 4; i++)
|
||
{
|
||
int k = i;
|
||
float x = 24f + (i % 2) * (w + 16f);
|
||
float y = -18f - (i / 2) * (h + 20f);
|
||
var card = UiKit.Btn("Card" + i, root, "", 30, UiKit.Paper, UiKit.Ink, new Vector2(0f, 1f), new Vector2(0f, 1f), new Vector2(x, y), new Vector2(w, h), () => SetPage(k + 1));
|
||
if (UISkin.Has("card4_bg") && UISkin.Has(Ribbons[i]))
|
||
{
|
||
// 카드(설계서 §3⑧) = 팩 CardFrame04 카드색 + 빛 + 테두리 · 글자 판 · 리본 제목
|
||
var ci = card.GetComponent<Image>();
|
||
UISkin.Apply(ci, "card4_bg");
|
||
ci.color = UiKit.Col("arena_" + i, UiKit.Paper);
|
||
UiKit.Layer(card.transform, "Glow", "card4_glow", UiKit.Col("arena_glow", UiKit.White), 0f, 0f, 0f, h * 0.5f);
|
||
UiKit.Layer(card.transform, "Inner", "panel12", UiKit.Col("arena_inner", UiKit.Paper), 14f, 112f, 14f, 100f);
|
||
UiKit.Layer(card.transform, "Border", "card4_border", UiKit.Col("card_border", UiKit.Line));
|
||
var rib = UiKit.Skin(UiKit.Rect("Ribbon", card.transform, new Vector2(0.5f, 1f), new Vector2(0.5f, 1f), new Vector2(0f, 4f), new Vector2(w - 40f, 96f)), Ribbons[i], UiKit.White);
|
||
var rt = UiKit.Title(UiKit.FillLabel(rib.transform, ModeNames[i] + (i == 3 ? " <size=24>(이벤트)</size>" : ""), 42, UiKit.White, TextAnchor.MiddleCenter, true, 40f), true);
|
||
rt.rectTransform.offsetMin = new Vector2(rt.rectTransform.offsetMin.x, 16f);
|
||
}
|
||
else
|
||
{
|
||
UiKit.Border(card.GetComponent<Image>(), UiKit.Line, 3f);
|
||
var head = UiKit.TopBand("Head", card.transform, 0f, 110f);
|
||
UiKit.Paint(head, UiKit.Red);
|
||
UiKit.FillLabel(head, ModeNames[i] + (i == 3 ? "\n<size=26>(이벤트)</size>" : ""), 44, UiKit.White);
|
||
}
|
||
string[] tags = { "규칙", "보상", "입장" };
|
||
for (int t = 0; t < 3; t++)
|
||
{
|
||
float ty = -128f - t * 160f;
|
||
var tag = UiKit.Box("Tag" + t, card.transform, new Vector2(0f, 1f), new Vector2(0f, 1f), new Vector2(20f, ty), new Vector2(96f, 44f), UiKit.Dark);
|
||
tag.raycastTarget = false;
|
||
UiKit.FillLabel(tag.transform, tags[t], 24, UiKit.White);
|
||
UiKit.Label(card.transform, text[i, t], 28, UiKit.Ink, TextAnchor.UpperLeft, new Vector2(0f, 1f), new Vector2(0f, 1f), new Vector2(20f, ty - 52f), new Vector2(w - 40f, 104f), false);
|
||
}
|
||
var st = UiKit.Box("Status", card.transform, new Vector2(0.5f, 0f), new Vector2(0.5f, 0f), new Vector2(0f, 16f), new Vector2(w - 32f, 70f), UiKit.Dark);
|
||
st.raycastTarget = false;
|
||
UiKit.FillLabel(st.transform, text[i, 3], 26, UiKit.Red);
|
||
}
|
||
}
|
||
|
||
// 카드 그림 · 요약 · 보상 아이콘(테마 id · Fable §4-6 · 일러 N4 전까지 픽토그램 임시)
|
||
static readonly string[] Arts = { "arena_art_0", "arena_art_1", "arena_art_2", "arena_art_3" };
|
||
static readonly string[] Briefs = { "층마다 고정 편성 · 10층마다 보스", "요일 순환 재화 던전", "비동기 5v5 · 주간 랭킹", "주간 보스 · 누적 피해" };
|
||
static readonly string[][] RewardIcons =
|
||
{
|
||
new[] { "cur_gem", "cur_blueprint", "chest_gold" },
|
||
new[] { "cur_gold", "cur_iron", "cur_skillbook" },
|
||
new[] { "gear_flag", "cur_shard" },
|
||
new[] { "chest_general" },
|
||
};
|
||
static readonly string[] EntryIcons = { "cur_ticket", "lobby_event", "sword", "fire" };
|
||
|
||
/// <summary>
|
||
/// 모드 카드(Fable 제안서 §4-6 · #1104) = CardFrame04 카드색 + 리본 제목(유지) · 위 일러 자리(픽토그램 220 흰 25 %) + 요약 한 줄 ·
|
||
/// 아래 어두운 판에 칩 2줄(입장 = 아이콘 + 값 · 보상 = 아이템 칸 72) · 상태 칩 · 규칙 문장 → ⓘ 팝업 · 이벤트 = 오른쪽 위 뱃지.
|
||
/// </summary>
|
||
void CardsKit(string[,] text, float w, float h)
|
||
{
|
||
var d = S.Save;
|
||
var db = S.Db;
|
||
var now = S.Now;
|
||
string[] entry =
|
||
{
|
||
"입장권 " + d.arena.towerTickets + " / " + db.Economy.TowerTicketsDaily,
|
||
"오늘 " + OpenCount(now) + "곳 · 각 " + (db.Dungeons.dungeons.Count > 0 ? db.Dungeons.dungeons[0].entriesPerDay : 0) + "회",
|
||
"남은 " + ArenaRules.ArenaLeft(db, d, now) + " / " + db.Arena.EntriesPerDay,
|
||
"하루 " + db.Economy.RaidDaily + "회",
|
||
};
|
||
var soft = UiKit.Col("text_soft", UiKit.InkSoft);
|
||
for (int i = 0; i < 4; i++)
|
||
{
|
||
int k = i;
|
||
float x = 24f + (i % 2) * (w + 16f);
|
||
float y = 18f + (i / 2) * (h + 20f);
|
||
var ci = UiKit.Skin(UiKit.At(root, "Card" + i, x, y, w, h), "card4_bg", UiKit.Col("arena_" + i, UiKit.Paper), true);
|
||
var card = ci.transform;
|
||
card.gameObject.AddComponent<Button>().onClick.AddListener(() => SetPage(k + 1));
|
||
UiKit.Layer(card, "Glow", "card4_glow", UiKit.Col("arena_glow", UiKit.White), 0f, 0f, 0f, h * 0.5f);
|
||
// 일러 자리 = 픽토그램(흰 25 %)
|
||
var art = UiKit.Icon(card, Arts[i], new Vector2(0.5f, 1f), new Vector2(0.5f, 0.5f), new Vector2(0f, -232f), 220f);
|
||
if (art != null) art.color = UiKit.Col("arena_art", new Color(1f, 1f, 1f, 0.25f));
|
||
var brief = UiKit.Title(UiKit.Label(card, Briefs[i], 28, UiKit.White, TextAnchor.MiddleCenter, new Vector2(0.5f, 1f), new Vector2(0.5f, 1f), new Vector2(0f, -356f), new Vector2(w - 40f, 44f)), true);
|
||
brief.horizontalOverflow = HorizontalWrapMode.Overflow;
|
||
// 칩 2줄 판
|
||
var board = UiKit.Skin(UiKit.At(card, "Inner", 14f, 414f, w - 28f, 182f), "panel12", UiKit.Col("arena_inner", UiKit.Paper)).transform;
|
||
UiKit.Label(board, "입장", 26, soft, TextAnchor.MiddleLeft, new Vector2(0f, 1f), new Vector2(0f, 1f), new Vector2(20f, -14f), new Vector2(80f, 56f));
|
||
UiKit.InfoChip(board, "Entry", 96f, 16f, w - 28f - 96f - 18f, 52f, EntryIcons[i], entry[i], 26);
|
||
UiKit.Label(board, "보상", 26, soft, TextAnchor.MiddleLeft, new Vector2(0f, 1f), new Vector2(0f, 1f), new Vector2(20f, -98f), new Vector2(80f, 72f));
|
||
for (int r = 0; r < RewardIcons[i].Length; r++)
|
||
UiKit.RewardTile(board, "Rw" + r, 96f + r * 86f, 92f, 76f, "gear_white_", RewardIcons[i][r], null, false);
|
||
// 상태 칩
|
||
var st = UiKit.Skin(UiKit.At(card, "Status", 16f, h - 86f, w - 32f, 66f), "chip", UiKit.Col("chip_dark", UiKit.Dark));
|
||
var stt = UiKit.Title(UiKit.FillLabel(st.transform, text[i, 3], 26, UiKit.Col("lv_fill", UiKit.Coin), TextAnchor.MiddleCenter, true, 16f), true);
|
||
stt.horizontalOverflow = HorizontalWrapMode.Overflow;
|
||
// 리본 제목(맨 위) · 이벤트 뱃지 · ⓘ
|
||
var rib = UiKit.Skin(UiKit.Rect("Ribbon", card, new Vector2(0.5f, 1f), new Vector2(0.5f, 1f), new Vector2(0f, 4f), new Vector2(w - 40f, 96f)), Ribbons[i], UiKit.White);
|
||
var rt = UiKit.Title(UiKit.FillLabel(rib.transform, ModeNames[i], 42, UiKit.White, TextAnchor.MiddleCenter, true, 40f), true);
|
||
rt.rectTransform.offsetMin = new Vector2(rt.rectTransform.offsetMin.x, 16f);
|
||
if (i == 3)
|
||
{
|
||
// 「이벤트」 = 카드 안 오른쪽 위 꼬리 칩(카드 밖 돌출 0 · 검수2 결함 7)
|
||
var ev = UiKit.Skin(UiKit.Rect("Event", card, new Vector2(1f, 1f), new Vector2(1f, 1f), new Vector2(-20f, -102f), new Vector2(120f, 44f)), "tail", UiKit.Col("tail_red", UiKit.Red));
|
||
UiKit.Title(UiKit.FillLabel(ev.transform, "이벤트", 22, UiKit.White), true);
|
||
}
|
||
var info = UiKit.Rect("Info", card, new Vector2(0f, 1f), new Vector2(0.5f, 0.5f), new Vector2(46f, -122f), new Vector2(60f, 60f));
|
||
UiKit.Skin(info, "badge_circle", UiKit.Col("chip_dark", UiKit.Dark), true);
|
||
if (UiKit.Icon(info, "info", new Vector2(0.5f, 0.5f), new Vector2(0.5f, 0.5f), Vector2.zero, 32f) == null) UiKit.Title(UiKit.FillLabel(info, "i", 30, UiKit.White), true);
|
||
string rules = "<b>규칙</b> " + text[i, 0] + "\n\n<b>보상</b> " + text[i, 1] + "\n\n<b>입장</b> " + text[i, 2];
|
||
info.gameObject.AddComponent<Button>().onClick.AddListener(() => Root.Modal(ModeNames[k], rules, new OutGameRoot.ModalButton("확인", UiKit.Dark, null)));
|
||
}
|
||
}
|
||
|
||
int OpenCount(System.DateTime now)
|
||
{
|
||
int n = 0;
|
||
foreach (var dg in S.Db.Dungeons.dungeons)
|
||
if (ArenaRules.OpenToday(dg, now)) n++;
|
||
return n;
|
||
}
|
||
|
||
RectTransform Panel(string name, float top, float h)
|
||
{
|
||
var band = UiKit.TopBand(name, root, top, h, 24f, 24f);
|
||
var img = UiKit.Paint(band, UiKit.Paper);
|
||
UiKit.Border(img, UiKit.Line, 3f);
|
||
return band;
|
||
}
|
||
|
||
void Title(string t)
|
||
{
|
||
var band = UiKit.TopBand("Title", root, 12f, 96f, 24f, 24f);
|
||
UiKit.Paint(band, UiKit.Red);
|
||
UiKit.FillLabel(band, t, 48, UiKit.White);
|
||
}
|
||
|
||
// ---------- ① 천하제일 탑 ----------
|
||
|
||
void BuildTower()
|
||
{
|
||
var db = S.Db;
|
||
var d = S.Save;
|
||
Title("천하제일 탑");
|
||
int next = ArenaRules.TowerNext(db, d);
|
||
var f = db.Tower.Get(next);
|
||
var stage = ArenaRules.TowerStage(db, Root.Battle.Config, next);
|
||
var info = Panel("Floor", 124f, 520f);
|
||
UiKit.Label(info, next + "층", 110, UiKit.Ink, TextAnchor.MiddleCenter, new Vector2(0.5f, 1f), new Vector2(0.5f, 1f), new Vector2(0f, -20f), new Vector2(600f, 140f));
|
||
var sb = new System.Text.StringBuilder();
|
||
sb.Append("클리어 최고 ").Append(d.arena.towerFloor).Append("층 / ").Append(db.Tower.Top).Append("층\n");
|
||
if (f != null)
|
||
{
|
||
sb.Append("적 편성 = ").Append(f.templateStage).Append(stage != null ? " 「" + stage.subtitle + "」 · " + stage.enemies.Count + "기" : " (템플릿 없음)").Append("\n");
|
||
sb.Append("적 HP ×").Append(f.hpMult.ToString("0.00")).Append(" · 공격 ×").Append(f.atkMult.ToString("0.00")).Append("\n");
|
||
sb.Append("보상 보옥 ").Append(f.rewardGem).Append(" · 도면 ").Append(f.rewardBlueprint);
|
||
if (f.chest.Length > 0) sb.Append(" · ").Append(db.Chests.Get(f.chest).nameKo);
|
||
}
|
||
UiKit.Label(info, sb.ToString(), 34, UiKit.Ink, TextAnchor.UpperCenter, new Vector2(0.5f, 1f), new Vector2(0.5f, 1f), new Vector2(0f, -180f), new Vector2(980f, 320f), false).lineSpacing = 1.2f;
|
||
|
||
var tk = Panel("Tickets", 664f, 150f);
|
||
UiKit.Label(tk, "입장권 " + d.arena.towerTickets + " <size=28>(매일 " + db.Economy.TowerTicketsDaily + "장까지 채움 · 입장 = 1장)</size>", 40, UiKit.Ink, TextAnchor.MiddleLeft, new Vector2(0f, 0.5f), new Vector2(0f, 0.5f), new Vector2(24f, 0f), new Vector2(720f, 80f));
|
||
var ad = UiKit.Btn("Ad", tk, "광고 +" + db.Economy.TowerAdTickets + "\n<size=24>(시험 · " + d.dailyC.towerAd + "/1)</size>", 32, UiKit.Grain, UiKit.White, new Vector2(1f, 0.5f), new Vector2(1f, 0.5f), new Vector2(-16f, 0f), new Vector2(240f, 110f), () =>
|
||
Root.Toast(S.Do(() => ArenaRules.TowerAd(S.Db, S.Save, S.Now)) ?? "입장권 +" + S.Db.Economy.TowerAdTickets + " (광고 SDK 미연동 · 시험 지급)"));
|
||
ad.interactable = d.dailyC.towerAd < 1;
|
||
|
||
var why = ArenaRules.CanTower(db, d, S.Now);
|
||
if (stage == null && why == null) why = "템플릿 스테이지 없음";
|
||
var go = UiKit.Btn("Go", root, why == null ? "도전 — " + next + "층" : why, 48, why == null ? UiKit.Red : UiKit.Disabled, UiKit.White, new Vector2(0.5f, 1f), new Vector2(0.5f, 1f), new Vector2(0f, -840f), new Vector2(1032f, 150f), () =>
|
||
{
|
||
var w = S.Do(() => ArenaRules.EnterTower(S.Db, S.Save, S.Now));
|
||
if (w != null)
|
||
{
|
||
Root.Toast(w);
|
||
return;
|
||
}
|
||
Root.StartMode(ArenaRules.Tower, "", next, ArenaRules.TowerStage(S.Db, Root.Battle.Config, next), 0, 1);
|
||
});
|
||
go.interactable = why == null;
|
||
UiKit.Label(root, "진행 저장 · 패배해도 층 유지(입장권만 소모)", 28, UiKit.InkSoft, TextAnchor.MiddleCenter, new Vector2(0.5f, 1f), new Vector2(0.5f, 1f), new Vector2(0f, -1010f), new Vector2(1000f, 50f), false);
|
||
}
|
||
|
||
// ---------- ② 일일 던전 ----------
|
||
|
||
void BuildDungeons()
|
||
{
|
||
var db = S.Db;
|
||
var d = S.Save;
|
||
var now = S.Now;
|
||
Title("일일 던전");
|
||
var today = DungeonDb.Weekdays[(int)now.ToLocalTime().DayOfWeek];
|
||
UiKit.Label(root, "오늘 = " + DayKo(today) + "요일 · 요일 순환 · 승리 시 입장 1회 소모", 30, UiKit.InkSoft, TextAnchor.MiddleCenter, new Vector2(0.5f, 1f), new Vector2(0.5f, 1f), new Vector2(0f, -116f), new Vector2(1000f, 50f), false);
|
||
for (int i = 0; i < db.Dungeons.dungeons.Count; i++)
|
||
{
|
||
var dg = db.Dungeons.dungeons[i];
|
||
bool open = ArenaRules.OpenToday(dg, now);
|
||
int left = ArenaRules.DungeonLeft(db, d, dg, now);
|
||
var box = Panel("Dungeon_" + dg.id, 180f + i * 330f, 310f);
|
||
box.GetComponent<Image>().color = open ? UiKit.Paper : UiKit.Slot;
|
||
UiKit.Label(box, dg.nameKo, 52, UiKit.Ink, TextAnchor.MiddleLeft, new Vector2(0f, 1f), new Vector2(0f, 1f), new Vector2(28f, -16f), new Vector2(400f, 76f));
|
||
var days = new List<string>();
|
||
foreach (var w in dg.weekdays) days.Add(w == today ? "<color=#b0301e>" + DayKo(w) + "</color>" : DayKo(w));
|
||
UiKit.Label(box, "요일 " + string.Join(" · ", days.ToArray()), 30, UiKit.Ink, TextAnchor.MiddleLeft, new Vector2(0f, 1f), new Vector2(0f, 1f), new Vector2(28f, -100f), new Vector2(600f, 50f), false);
|
||
var rw = new List<string>();
|
||
foreach (var k in dg.rewardKinds) rw.Add(RewardKo(k) + " " + dg.Amount(k));
|
||
UiKit.Label(box, "보상 " + string.Join(" · ", rw.ToArray()), 30, UiKit.Ink, TextAnchor.MiddleLeft, new Vector2(0f, 1f), new Vector2(0f, 1f), new Vector2(28f, -152f), new Vector2(640f, 50f), false);
|
||
UiKit.Label(box, "적 = " + dg.templateStage + " 편성 · HP ×" + dg.hpMult.ToString("0.0#"), 28, UiKit.InkSoft, TextAnchor.MiddleLeft, new Vector2(0f, 1f), new Vector2(0f, 1f), new Vector2(28f, -204f), new Vector2(640f, 50f), false);
|
||
string id = dg.id;
|
||
var why = ArenaRules.CanDungeon(db, d, id, now);
|
||
var b = UiKit.Btn("Go", box, open ? "입장\n<size=26>남은 " + left + "/" + dg.entriesPerDay + "</size>" : "닫힘", 40, why == null ? UiKit.Red : UiKit.Disabled, UiKit.White, new Vector2(1f, 0.5f), new Vector2(1f, 0.5f), new Vector2(-24f, 0f), new Vector2(300f, 170f), () =>
|
||
{
|
||
var w = ArenaRules.CanDungeon(S.Db, S.Save, id, S.Now);
|
||
if (w != null)
|
||
{
|
||
Root.Toast(w);
|
||
return;
|
||
}
|
||
Root.StartMode(ArenaRules.Dungeon, id, 0, ArenaRules.DungeonStage(S.Db, Root.Battle.Config, id), 0, 2);
|
||
});
|
||
b.interactable = why == null;
|
||
}
|
||
}
|
||
|
||
static string DayKo(string w)
|
||
{
|
||
switch (w)
|
||
{
|
||
case "sun": return "일";
|
||
case "mon": return "월";
|
||
case "tue": return "화";
|
||
case "wed": return "수";
|
||
case "thu": return "목";
|
||
case "fri": return "금";
|
||
case "sat": return "토";
|
||
}
|
||
return w;
|
||
}
|
||
|
||
static string RewardKo(string k)
|
||
{
|
||
switch (k)
|
||
{
|
||
case "gold": return "골드";
|
||
case "gear": return "승급 장비";
|
||
case "iron": return "운철";
|
||
case "skill_book": return "스킬서";
|
||
case "shards": return "영웅 조각";
|
||
}
|
||
return k;
|
||
}
|
||
|
||
// ---------- ③ 투기장 ----------
|
||
|
||
void BuildArena()
|
||
{
|
||
var db = S.Db;
|
||
var d = S.Save;
|
||
var now = S.Now;
|
||
Title("투기장");
|
||
var me = Panel("Me", 124f, 200f);
|
||
int left = ArenaRules.ArenaLeft(db, d, now);
|
||
UiKit.Label(me, "메달 " + d.arena.medals + " · 주간 점수 " + d.arena.seasonScore + " · " + ArenaRules.Rank(d) + "위 / " + (d.arena.samples.Count + 1), 36, UiKit.Ink, TextAnchor.MiddleLeft, new Vector2(0f, 1f), new Vector2(0f, 1f), new Vector2(24f, -14f), new Vector2(980f, 56f));
|
||
var start = SaveStore.ParseIso(d.arena.seasonStart, now);
|
||
int daysLeft = Mathf.Max(0, db.Arena.SeasonDays - (int)(now - start).TotalDays);
|
||
UiKit.Label(me, "전적 " + d.arena.wins + "승 " + d.arena.losses + "패 · 오늘 남은 도전 " + left + "/" + db.Arena.EntriesPerDay + " · 시즌 " + daysLeft + "일 남음 · 승 +" + db.Arena.MedalWin + " / 패 +" + db.Arena.MedalLose + "\n" +
|
||
"<size=26>순위 보상 1~10위 보옥 " + db.Arena.RewardTop10Gem + " · 그 밖 " + db.Arena.RewardTop100Gem + (d.arena.lastSeason.Length > 0 ? " · " + d.arena.lastSeason : "") + "</size>",
|
||
30, UiKit.InkSoft, TextAnchor.UpperLeft, new Vector2(0f, 1f), new Vector2(0f, 1f), new Vector2(24f, -76f), new Vector2(980f, 110f), false);
|
||
UiKit.Btn("Shop", me, "메달 상점", 30, UiKit.Jade, UiKit.White, new Vector2(1f, 1f), new Vector2(1f, 1f), new Vector2(-16f, -12f), new Vector2(200f, 60f), MedalShop);
|
||
|
||
ScrollRect sr;
|
||
var list = UiKit.ScrollGrid("Opponents", root, 24f, 24f, 344f, 16f, new Vector2(1032f, 130f), new Vector2(0f, 12f), 1, out sr);
|
||
for (int i = 0; i < d.arena.samples.Count; i++)
|
||
{
|
||
var s = d.arena.samples[i];
|
||
int k = i;
|
||
var cell = UiKit.Cell(list, "Opp" + i, UiKit.Paper, null);
|
||
UiKit.Border(cell, UiKit.Line, 2f);
|
||
int power = 0;
|
||
for (int j = 0; j < s.heroes.Count; j++)
|
||
{
|
||
var h = db.Heroes.Get(s.heroes[j]);
|
||
if (h == null) continue;
|
||
power += HeroRules.Compute(db, Root.Battle.Config, h, new HeroState { id = h.id, lv = s.lv, grade = db.Promotion.FirstGrade, star = Mathf.Clamp(h.rarity, 1, db.Evolve.MaxStar) }).power;
|
||
UiKit.Portrait("H" + j, cell.transform, h, new Vector2(0f, 0.5f), new Vector2(0f, 0.5f), new Vector2(16f + j * 92f, 0f), new Vector2(84f, 104f), false, 1.8f, new Color(0.9f, 0.86f, 0.8f));
|
||
}
|
||
UiKit.Label(cell.transform, s.name + "\n<size=26>전투력 " + power.ToString("N0") + " · 점수 " + s.score + "</size>", 30, UiKit.Ink, TextAnchor.MiddleLeft, new Vector2(0f, 0.5f), new Vector2(0f, 0.5f), new Vector2(490f, 0f), new Vector2(330f, 110f));
|
||
var why = ArenaRules.CanArena(db, d, k, now);
|
||
var b = UiKit.Btn("Go", cell.transform, "도전", 34, why == null ? UiKit.Red : UiKit.Disabled, UiKit.White, new Vector2(1f, 0.5f), new Vector2(1f, 0.5f), new Vector2(-16f, 0f), new Vector2(180f, 96f), () =>
|
||
{
|
||
var w = ArenaRules.CanArena(S.Db, S.Save, k, S.Now);
|
||
if (w != null)
|
||
{
|
||
Root.Toast(w);
|
||
return;
|
||
}
|
||
Root.StartMode(ArenaRules.Arena, "", k, ArenaRules.ArenaStage(S.Db, Root.Battle.Config, S.Save.arena.samples[k]), 0, 3);
|
||
});
|
||
b.interactable = why == null;
|
||
}
|
||
}
|
||
|
||
public void MedalShop()
|
||
{
|
||
var db = S.Db;
|
||
var d = S.Save;
|
||
var content = Root.ModalCustom("메달 상점 — 영웅 조각", 1500f, new OutGameRoot.ModalButton("닫기", UiKit.Dark, null));
|
||
UiKit.Label(content, "메달 " + d.arena.medals + " · " + db.Arena.ShopPrice + "메달 = 조각 " + db.Arena.ShopShards + " · 오늘 " + d.dailyC.arenaShop + "/" + db.Arena.ShopDaily, 30, UiKit.Ink, TextAnchor.MiddleCenter,
|
||
new Vector2(0.5f, 1f), new Vector2(0.5f, 1f), Vector2.zero, new Vector2(860f, 50f));
|
||
ScrollRect sr;
|
||
var grid = UiKit.ScrollGrid("Heroes", content, 0f, 0f, 60f, 0f, new Vector2(200f, 260f), new Vector2(12f, 12f), 4, out sr);
|
||
foreach (var hs in d.heroes)
|
||
{
|
||
var h = db.Heroes.Get(hs.id);
|
||
if (h == null) continue;
|
||
string id = h.id;
|
||
var cell = UiKit.Cell(grid, "Buy_" + id, UiKit.Paper, () =>
|
||
{
|
||
var w = S.Do(() => ArenaRules.BuyShards(S.Db, S.Save, id, S.Now));
|
||
Root.Toast(w ?? h.nameKo + " 조각 +" + S.Db.Arena.ShopShards);
|
||
if (w == null) MedalShop();
|
||
});
|
||
UiKit.Portrait("Face", cell.transform, h, new Vector2(0.5f, 1f), new Vector2(0.5f, 1f), new Vector2(0f, -8f), new Vector2(150f, 150f), false, 1.8f, new Color(0.9f, 0.86f, 0.8f));
|
||
UiKit.Label(cell.transform, h.nameKo + "\n<size=22>조각 " + hs.shards + " · ★" + hs.star + "</size>", 26, UiKit.Ink, TextAnchor.MiddleCenter, new Vector2(0.5f, 0f), new Vector2(0.5f, 0f), new Vector2(0f, 8f), new Vector2(190f, 90f));
|
||
}
|
||
}
|
||
|
||
// ---------- ④ 적장 토벌 ----------
|
||
|
||
void BuildRaid()
|
||
{
|
||
var db = S.Db;
|
||
var d = S.Save;
|
||
var now = S.Now;
|
||
var e = db.Economy;
|
||
Title("적장 토벌 (이벤트)");
|
||
string bossId = ArenaRules.RaidBoss(db, d, now);
|
||
var h = db.Heroes.Get(bossId);
|
||
var stage = ArenaRules.RaidStage(db, Root.Battle.Config, bossId);
|
||
var box = Panel("Boss", 124f, 640f);
|
||
UiKit.Portrait("Boss", box, h, new Vector2(0.5f, 1f), new Vector2(0.5f, 1f), new Vector2(0f, -20f), new Vector2(320f, 320f), false, 1f, new Color(0.85f, 0.8f, 0.75f));
|
||
var sb = new System.Text.StringBuilder();
|
||
sb.Append("<size=52><b>이번 주 보스 — ").Append(h != null ? h.nameKo : bossId).Append("</b></size>\n");
|
||
sb.Append("보스 HP ×").Append(e.RaidHpMult.ToString("0.#")).Append(" · ").Append(e.RaidTurns).Append("턴 동안 피해를 누적").Append(stage != null ? " · 적 " + stage.enemies.Count + "기" : "").Append("\n");
|
||
sb.Append("이번 주 누적 피해 ").Append(d.arena.raidDamage.ToString("N0")).Append(" (").Append(d.arena.raidWeek).Append(" 주)\n");
|
||
sb.Append("보상 ").Append(db.Chests.Get(e.RaidChest).nameKo).Append(" · 천기 보물 확률 ").Append((e.RaidArcanaPct * 100f).ToString("0.#")).Append("%");
|
||
UiKit.Label(box, sb.ToString(), 32, UiKit.Ink, TextAnchor.UpperCenter, new Vector2(0.5f, 1f), new Vector2(0.5f, 1f), new Vector2(0f, -360f), new Vector2(980f, 270f), false).lineSpacing = 1.15f;
|
||
var why = ArenaRules.CanRaid(db, d, now);
|
||
if (stage == null && why == null) why = "보스 편성 없음";
|
||
var go = UiKit.Btn("Go", root, why == null ? "토벌 — 남은 " + ArenaRules.RaidLeft(db, d, now) + "/" + e.RaidDaily : why, 48, why == null ? UiKit.Red : UiKit.Disabled, UiKit.White,
|
||
new Vector2(0.5f, 1f), new Vector2(0.5f, 1f), new Vector2(0f, -790f), new Vector2(1032f, 150f), () =>
|
||
{
|
||
var w = ArenaRules.CanRaid(S.Db, S.Save, S.Now);
|
||
if (w != null)
|
||
{
|
||
Root.Toast(w);
|
||
return;
|
||
}
|
||
Root.StartMode(ArenaRules.Raid, bossId, 0, ArenaRules.RaidStage(S.Db, Root.Battle.Config, bossId), S.Db.Economy.RaidTurns, 4);
|
||
});
|
||
go.interactable = why == null;
|
||
UiKit.Label(root, "주간 보스 = 여포·조조 순환 · 주가 바뀌면 누적 초기화 · 천기 = 적장 토벌 전용", 28, UiKit.InkSoft, TextAnchor.MiddleCenter, new Vector2(0.5f, 1f), new Vector2(0.5f, 1f), new Vector2(0f, -960f), new Vector2(1000f, 50f), false);
|
||
}
|
||
}
|
||
}
|