ThreeKingdomsSlingshot/Assets/Scripts/OutGame/UI/BattleResultPanel.cs

109 lines
5.4 KiB
C#
Raw Normal View History

아웃게임 1차(PD #1093 세션 A) — 본영 로비 · 세이브 · 군량 · 영웅(레벨·승급 6칸·진화·스킬 표시) · 편성(전열 3/후열 2 · 프리셋 3) · 거래(뽑기·골드 장비 상점) · 스테이지 보상·별 3·소탕 - 데이터: 기획 tables/ 12장 → Assets/Data/OutGame/*.csv · 메뉴 TKS/Import OutGame Data(Editor/DataImporter) → Resources/OutGame 9 자산(HeroDb·GearDb·GachaConfig·EconomyConfig·RewardTable·LevelTable·PromotionTable·EvolveTable·SkillInfoDb) · 검증(행 수·필수 열·id 유일·hero↔skill↔gear·확률 합) 오류 시 자산 불변 · BalanceConfig.heroes[]/HeroDef 삭제 → HeroDb(기존 5인 id 유지) · economy.csv 키 17 + gacha.csv 키 2 추가(기획서 본문 값 · C45) - 세이브: persistentDataPath/save.json · ver 1 · 즉시 저장 · 오프라인 군량 회복 · 일일 초기화 · 신규 유저 = 유비·관우·장비·조운·황충 Lv1 녹 ★=희귀도 · 골드 1000 · 보옥 300 · 군량 30 · 테스트·캡처 = 메모리 전용 - 화면(uGUI 와이어프레임 · img03·06·08·11): 시작 = 본영 로비(출정 → 월드맵 · 편성 · 연무장/보물/내정 준비 중 · 동맹 추후) · 재화 바(월드맵 포함 · 군량 타이머) · 하단 탭 5 · ◀/Esc 일관 · 영웅 목록·상세·상세정보·도감 · 편성(탭·드래그) · 뽑기(천장 n/80 · 확률 공개 · 첫 10연 무료 · 10연 ★★ 보장 · 카드 순차 공개) · 장비 상점(흰/녹 6종 일일 · sell×5 · 새로고침 보옥 20) - 전투 연결: BattleManager.LineupProvider/Deployed(LineupEntry · §3-2 스탯 · 방어 배율 생성 뒤) · playerSpawnPoints = 전열 (−4/0/4, −12) · 후열 (−2/2, −14) · WorldMapScreen 훅(팝업 군량·보상·별 · 입장 군량 · 노드 별 star_on/off · 소탕 · ◀ 본영 · TopInset) · 결과 패널(별 3 조건 · 골드·경험·보옥·장비) · GameBootstrap/AutoPlayDriver 로비 시작 - B 세션 파일(ActionResolver·Combat·UnitView·BattleHUD·SlingshotInput·EnemyAI) 미변경 - 테스트 56/56(기존 41 유지 · 신규 OutGameTests 15) · console error 0 · 사본 GUI 캡처 11장(DataImporter.CaptureOutGame) Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
2026-11-05 12:11:10 +00:00
using System.Text;
using UnityEngine;
using UnityEngine.UI;
namespace TKS.OutGame
{
/// <summary>
/// 전투 결과 패널(기획서 §6) — 별 3(클리어 · 전원 생존 · n턴 이내) · 골드 · 경험(출전 전원) · 보옥(첫 클리어 · 보스) · 장비 드랍.
/// 전투 HUD 의 승리/패배 판(sortingOrder 100) 위에 덮는다 · 탭 처리는 기존 그대로(SlingshotInput → 월드맵 복귀).
/// </summary>
public class BattleResultPanel
{
readonly OutGameRoot root;
readonly GameObject go;
readonly Text title;
readonly Text stars;
readonly Text conds;
readonly Text rewards;
public bool Visible
{
get { return go.activeSelf; }
}
public string RewardsText
{
get { return rewards.text; }
}
public BattleResultPanel(OutGameRoot r, RectTransform canvas)
{
root = r;
var dim = UiKit.Fill("Result", canvas);
UiKit.Paint(dim, new Color(0f, 0f, 0f, 0.55f), false);
go = dim.gameObject;
var panel = UiKit.Box("Panel", dim, new Vector2(0.5f, 0.5f), new Vector2(0.5f, 0.5f), new Vector2(0f, 40f), new Vector2(920f, 1180f), UiKit.Paper);
UiKit.Border(panel, UiKit.Line, 4f);
var head = UiKit.TopBand("Head", panel.transform, 0f, 170f);
UiKit.Paint(head, UiKit.Dark);
title = UiKit.FillLabel(head, "", 96, UiKit.White);
stars = UiKit.Label(panel.transform, "", 120, UiKit.Star, TextAnchor.MiddleCenter, new Vector2(0.5f, 1f), new Vector2(0.5f, 1f), new Vector2(0f, -190f), new Vector2(800f, 150f));
conds = UiKit.Label(panel.transform, "", 34, UiKit.Ink, TextAnchor.UpperLeft, new Vector2(0.5f, 1f), new Vector2(0.5f, 1f), new Vector2(0f, -350f), new Vector2(760f, 180f), false);
conds.lineSpacing = 1.15f;
var line = UiKit.Box("Line", panel.transform, new Vector2(0.5f, 1f), new Vector2(0.5f, 1f), new Vector2(0f, -540f), new Vector2(800f, 4f), UiKit.Slot, false);
line.raycastTarget = false;
rewards = UiKit.Label(panel.transform, "", 38, UiKit.Ink, TextAnchor.UpperLeft, new Vector2(0.5f, 1f), new Vector2(0.5f, 1f), new Vector2(0f, -566f), new Vector2(760f, 460f), false);
rewards.lineSpacing = 1.15f;
UiKit.Label(panel.transform, "화면을 탭하면 월드맵으로", 34, UiKit.InkSoft, TextAnchor.MiddleCenter, new Vector2(0.5f, 0f), new Vector2(0.5f, 0f), new Vector2(0f, 36f), new Vector2(800f, 60f), false);
go.SetActive(false);
}
public void SetVisible(bool on)
{
if (go.activeSelf != on) go.SetActive(on);
}
public void Fill(StageReward r)
{
var s = root.Session;
title.text = (r.win ? "승리" : "패배") + " <size=44>" + r.chapter + "-" + r.stage + (r.boss ? " 보스" : "") + "</size>";
stars.text = r.win ? UiKit.Stars(r.stars, 3) : UiKit.Stars(0, 3);
if (r.win)
{
conds.text = Mark(r.conds[0]) + " 클리어\n" +
Mark(r.conds[1]) + " 아군 전원 생존\n" +
Mark(r.conds[2]) + " " + r.starTurns + "턴 이내 클리어 (" + r.turns + "턴)";
rewards.text = RewardText(s, r);
}
else
{
conds.text = "아군이 전멸했습니다\n군량 " + r.stamina + " 소모 · 별 없음";
rewards.text = "보상 없음\n<size=32>영웅 레벨업 · 승급 · 편성을 바꿔 다시 도전</size>";
}
}
static string Mark(bool ok)
{
return ok ? "<color=#3a6a30>○</color>" : "<color=#a03a22>×</color>";
}
/// <summary>보상 줄(결과 화면 · 소탕 팝업 공용).</summary>
public static string RewardText(OutGameSession s, StageReward r)
{
var e = s.Db.Economy;
var sb = new StringBuilder();
sb.Append("골드 +").Append(r.gold.ToString("N0")).Append(r.first ? " <size=28>(첫 클리어)</size>" : " <size=28>(반복 ×" + e.RepeatRewardMult + ")</size>");
sb.Append("\n경험 +").Append(r.exp).Append(" <size=28>출전 ").Append(r.expTo.Count).Append("명</size>");
if (r.gem > 0) sb.Append("\n보옥 +").Append(r.gem).Append(r.boss ? " <size=28>(첫 클리어 + 보스)</size>" : " <size=28>(첫 클리어)</size>");
if (!string.IsNullOrEmpty(r.gearId))
{
var g = s.Db.Gear.Get(r.gearId);
sb.Append("\n장비 ").Append(g != null ? g.nameKo + " (" + UiKit.GradeKo(g.grade) + ")" : r.gearId).Append(" 획득");
}
else sb.Append("\n<size=30>장비 드랍 없음</size>");
if (r.sweep) sb.Append("\n<size=30>군량 ").Append(r.stamina).Append(" 소모 · 소탕(전투 없음)</size>");
var ready = new StringBuilder();
foreach (var id in r.expTo)
{
var lv = s.Save.Level(id);
if (HeroRules.CanLevelUp(s.Db, s.Save, lv) != null) continue;
if (ready.Length > 0) ready.Append(" · ");
ready.Append(s.Def(id).nameKo);
}
if (ready.Length > 0) sb.Append("\n<color=#a03a22><size=30>레벨업 가능: ").Append(ready).Append("</size></color>");
return sb.ToString();
}
}
}