2026-11-05 15:22:54 +00:00
using System.Collections.Generic ;
using UnityEngine ;
using UnityEngine.UI ;
namespace TKS.OutGame
{
/// <summary>
/// 보물(하단 탭 · 기획 S8 · 목업 img07·16·17 · 카피바라 수집품 구조 · PD #1093 C) — 상단 탭 3:
/// ① 보유 중 = 그리드 4열 · 등급 색 · ★ · 미보유 회색 · 탭 = 상세(기본 효과 · 조건 효과 n/max · 강화 ★)
/// ② 세트 = 세트마다 구성 · 조각 게이지 · [세트]/[3성]/[6성]/[10성] 효과 ③ 상자 = 상자 포인트 게이지 → 명장 상자 · 선택 상자 + 확률 · 보유 수 · 열기(상자는 이 탭에서만 연다).
/// </summary>
public class TreasureScreen : OutGameScreen
{
public static readonly string [ ] PageNames = { "보유 중" , "세트" , "상자" } ;
int page ;
int chestIdx ;
readonly List < Button > tabs = new List < Button > ( ) ;
readonly List < RectTransform > pages = new List < RectTransform > ( ) ;
public int Page
{
get { return page ; }
}
public int GridCount { get ; private set ; }
public int SetCount { get ; private set ; }
public ChestResult LastOpen { get ; private set ; }
public string SelectedChest
{
get
{
var l = S . Db . Chests . chests ;
return l . Count > 0 ? l [ Mathf . Clamp ( chestIdx , 0 , l . Count - 1 ) ] . id : "" ;
}
}
public override void Build ( )
{
Tab = 1 ;
Header ( "보물" , "수집품 · 보유만으로 상시 발동" , true ) ;
var body = Body ( ) ;
for ( int i = 0 ; i < PageNames . Length ; i + + )
{
int k = i ;
tabs . Add ( UiKit . Btn ( "Tab" + i , body , PageNames [ i ] , 36 , UiKit . Paper , UiKit . Ink , new Vector2 ( 0f , 1f ) , new Vector2 ( 0f , 1f ) , new Vector2 ( 24f + i * 348f , - 18f ) , new Vector2 ( 332f , 84f ) , ( ) = > SetPage ( k ) ) ) ;
pages . Add ( UiKit . Fill ( "Page" + i , body , 0f , 0f , 118f , 0f ) ) ;
}
}
public void SetPage ( int p )
{
page = Mathf . Clamp ( p , 0 , pages . Count - 1 ) ;
Refresh ( ) ;
}
public void SelectChest ( string id )
{
int i = S . Db . Chests . IndexOf ( id ) ;
if ( i > = 0 ) chestIdx = i ;
Refresh ( ) ;
}
public override void Refresh ( )
{
for ( int i = 0 ; i < tabs . Count ; i + + )
{
bool on = i = = page ;
tabs [ i ] . GetComponent < Image > ( ) . color = on ? UiKit . Dark : UiKit . Paper ;
UiKit . LabelOf ( tabs [ i ] ) . color = on ? UiKit . White : UiKit . Ink ;
pages [ i ] . gameObject . SetActive ( on ) ;
}
UiKit . Clear ( pages [ page ] ) ;
if ( page = = 0 ) BuildOwned ( pages [ 0 ] ) ;
else if ( page = = 1 ) BuildSets ( pages [ 1 ] ) ;
else BuildChests ( pages [ 2 ] ) ;
}
public static Color GradeColor ( string g )
{
switch ( g )
{
case "rare" : return new Color ( 0.27f , 0.45f , 0.75f ) ;
case "epic" : return new Color ( 0.55f , 0.33f , 0.66f ) ;
case "legend" : return new Color ( 0.86f , 0.45f , 0.16f ) ;
case "myth" : return new Color ( 0.75f , 0.2f , 0.18f ) ;
case "arcana" : return new Color ( 0.78f , 0.62f , 0.16f ) ;
}
return UiKit . Slot ;
}
/// <summary>보물 칸(아이콘 = 이름 첫 글자 · ★ · 등급 띠 · 미보유 = 회색 「?」).</summary>
void TreasureCell ( Transform parent , TreasureDb . Item it , bool showShards )
{
var st = S . Save . inv . Treasure ( it . id ) ;
bool owned = st ! = null ;
var cell = UiKit . Cell ( parent , "T_" + it . id , owned ? UiKit . Paper : new Color ( 0.85f , 0.82f , 0.77f ) , owned ? ( System . Action ) ( ( ) = > Detail ( it . id ) ) : null ) ;
UiKit . Border ( cell , owned ? GradeColor ( it . grade ) : new Color ( 0.7f , 0.66f , 0.62f ) , 3f ) ;
var icon = UiKit . Dot ( "Icon" , cell . transform , new Vector2 ( 0.5f , 1f ) , new Vector2 ( 0.5f , 1f ) , new Vector2 ( 0f , - 14f ) , 120f , owned ? new Color ( 0.94f , 0.9f , 0.83f ) : new Color ( 0.78f , 0.74f , 0.69f ) ) ;
2026-11-06 14:20:57 +00:00
if ( owned & & UiKit . HasFinalIcon ( "tre_" + it . id ) ) UiKit . Icon ( icon . transform , "tre_" + it . id , new Vector2 ( 0.5f , 0.5f ) , new Vector2 ( 0.5f , 0.5f ) , Vector2 . zero , 100f ) ;
else UiKit . FillLabel ( icon . transform , owned ? it . nameKo . Substring ( 0 , 1 ) : "?" , 60 , owned ? GradeColor ( it . grade ) : new Color ( 0.6f , 0.56f , 0.52f ) ) ;
2026-11-05 15:22:54 +00:00
if ( owned )
{
if ( showShards & & st . star < it . starMax )
{
int need , iron ;
TreasureRules . EnhanceCost ( S . Db , it , st . star + 1 , out need , out iron ) ;
var fill = UiKit . Bar ( "Shards" , cell . transform , new Vector2 ( 0.5f , 1f ) , new Vector2 ( 0.5f , 1f ) , new Vector2 ( 0f , - 142f ) , new Vector2 ( 150f , 26f ) , new Color ( 0.3f , 0.27f , 0.25f ) , new Color ( 0.38f , 0.62f , 0.86f ) ) ;
UiKit . SetBar ( fill , st . shards / ( float ) Mathf . Max ( 1 , need ) ) ;
UiKit . FillLabel ( fill . parent , st . shards + "/" + need , 18 , UiKit . White ) ;
}
else UiKit . Label ( cell . transform , st . star > 0 ? "★" + st . star : "☆" , 32 , UiKit . Star , TextAnchor . MiddleCenter , new Vector2 ( 0.5f , 1f ) , new Vector2 ( 0.5f , 1f ) , new Vector2 ( 0f , - 140f ) , new Vector2 ( 200f , 40f ) ) ;
}
var band = UiKit . Box ( "Name" , cell . transform , new Vector2 ( 0.5f , 0f ) , new Vector2 ( 0.5f , 0f ) , new Vector2 ( 0f , 10f ) , new Vector2 ( 210f , 56f ) , owned ? GradeColor ( it . grade ) : new Color ( 0.62f , 0.58f , 0.55f ) ) ;
UiKit . FillLabel ( band . transform , owned ? it . nameKo : "미보유" , 26 , UiKit . White ) ;
}
// ---------- ① 보유 중 ----------
void BuildOwned ( RectTransform p )
{
var db = S . Db ;
int owned = 0 ;
foreach ( var it in db . Treasures . items )
if ( S . Save . inv . Treasure ( it . id ) ! = null ) owned + + ;
UiKit . Label ( p , "보유 " + owned + " / " + db . Treasures . items . Count , 36 , UiKit . Ink , TextAnchor . MiddleLeft , new Vector2 ( 0f , 1f ) , new Vector2 ( 0f , 1f ) , new Vector2 ( 28f , - 8f ) , new Vector2 ( 360f , 56f ) ) ;
var grades = db . Economy . TreasureGrades ;
for ( int i = 0 ; i < grades . Count ; i + + )
{
var chip = UiKit . Box ( "G" + i , p , new Vector2 ( 1f , 1f ) , new Vector2 ( 1f , 1f ) , new Vector2 ( - 24f - ( grades . Count - 1 - i ) * 118f , - 12f ) , new Vector2 ( 110f , 48f ) , GradeColor ( grades [ i ] . Key ) ) ;
UiKit . FillLabel ( chip . transform , TreasureRules . GradeKo ( grades [ i ] . Key ) , 24 , UiKit . White ) ;
}
ScrollRect sr ;
var grid = UiKit . ScrollGrid ( "Grid" , p , 24f , 24f , 76f , 64f , new Vector2 ( 240f , 290f ) , new Vector2 ( 16f , 16f ) , 4 , out sr ) ;
// 정렬 = 보유 먼저 · 등급 높은 순
var list = new List < TreasureDb . Item > ( db . Treasures . items ) ;
list . Sort ( ( a , b ) = >
{
bool oa = S . Save . inv . Treasure ( a . id ) ! = null , ob = S . Save . inv . Treasure ( b . id ) ! = null ;
if ( oa ! = ob ) return oa ? - 1 : 1 ;
return db . Economy . TreasureGradeOrder ( b . grade ) . CompareTo ( db . Economy . TreasureGradeOrder ( a . grade ) ) ;
} ) ;
GridCount = 0 ;
foreach ( var it in list )
{
TreasureCell ( grid , it , false ) ;
GridCount + + ;
}
var bonus = new List < string > ( ) ;
foreach ( var s in TreasureDb . BaseStats )
{
float v = TreasureRules . StatPct ( db , S . Save , s ) ;
if ( v > 0f ) bonus . Add ( TreasureRules . StatKo ( s ) + " +" + v . ToString ( "0.#" ) + "%" ) ;
}
UiKit . Label ( p , bonus . Count > 0 ? "전체 효과 " + string . Join ( " · " , bonus . ToArray ( ) ) : "보물을 모으면 전 유닛에 상시 효과" , 26 , UiKit . InkSoft , TextAnchor . MiddleCenter ,
new Vector2 ( 0.5f , 0f ) , new Vector2 ( 0.5f , 0f ) , new Vector2 ( 0f , 8f ) , new Vector2 ( 1030f , 50f ) , false ) ;
}
public void Detail ( string id )
{
var db = S . Db ;
var d = S . Save ;
var it = db . Treasures . Get ( id ) ;
var st = d . inv . Treasure ( id ) ;
if ( it = = null | | st = = null ) return ;
var sb = new System . Text . StringBuilder ( ) ;
sb . Append ( TreasureRules . GradeKo ( it . grade ) ) . Append ( " · ★" ) . Append ( st . star ) . Append ( "/" ) . Append ( it . starMax ) ;
var tiers = it . setId . Length > 0 ? db . TreasureSets . TiersOf ( it . setId ) : null ;
if ( tiers ! = null & & tiers . Count > 0 ) sb . Append ( " · 세트 「" ) . Append ( tiers [ 0 ] . nameKo ) . Append ( "」" ) ;
sb . Append ( "\n\n<b>기본 효과</b> " ) . Append ( TreasureRules . StatKo ( it . baseStat ) ) . Append ( " +" ) . Append ( TreasureRules . BasePct ( db , it , st . star ) . ToString ( "0.##" ) ) . Append ( "%" ) ;
int stacks = TreasureRules . CondStacks ( d , it ) ;
sb . Append ( "\n<b>조건 효과</b> " ) . Append ( TreasureRules . CondKo ( it . condKey ) ) . Append ( " " ) . Append ( it . condEvery ) . Append ( "회마다 +" ) . Append ( it . condPct . ToString ( "0.##" ) ) . Append ( "% (" )
. Append ( stacks ) . Append ( "/" ) . Append ( it . condMax ) . Append ( " · 누적 " ) . Append ( TreasureRules . Counter ( d , it . condKey ) ) . Append ( ")" ) ;
sb . Append ( "\n<size=28>= 지금 " ) . Append ( TreasureRules . StatKo ( it . baseStat ) ) . Append ( " +" ) . Append ( TreasureRules . Value ( db , d , it ) . ToString ( "0.##" ) ) . Append ( "%</size>" ) ;
string btn ;
var why = TreasureRules . CanEnhance ( db , d , id ) ;
if ( st . star < it . starMax )
{
int shards , iron ;
TreasureRules . EnhanceCost ( db , it , st . star + 1 , out shards , out iron ) ;
sb . Append ( "\n\n<b>강화 ★" ) . Append ( st . star + 1 ) . Append ( "</b> 조각 " ) . Append ( st . shards ) . Append ( "/" ) . Append ( shards ) . Append ( " · 운철 " ) . Append ( d . inv . iron ) . Append ( "/" ) . Append ( iron ) ;
btn = why = = null ? "강화" : why ;
}
else btn = "최고 ★" ;
Root . Modal ( it . nameKo , sb . ToString ( ) ,
new OutGameRoot . ModalButton ( btn , why = = null ? UiKit . Red : UiKit . Disabled , ( ) = >
{
var w = S . Do ( ( ) = > TreasureRules . Enhance ( S . Db , S . Save , id ) ) ;
if ( w = = null ) Detail ( id ) ;
else Root . Toast ( w ) ;
} , true ) ,
new OutGameRoot . ModalButton ( "닫기" , UiKit . Dark , null ) ) ;
}
// ---------- ② 세트 ----------
void BuildSets ( RectTransform p )
{
var db = S . Db ;
var d = S . Save ;
ScrollRect sr ;
var list = UiKit . ScrollGrid ( "Sets" , p , 24f , 24f , 6f , 12f , new Vector2 ( 1032f , 640f ) , new Vector2 ( 0f , 24f ) , 1 , out sr ) ;
SetCount = 0 ;
foreach ( var setId in db . TreasureSets . SetIds )
{
var tiers = db . TreasureSets . TiersOf ( setId ) ;
if ( tiers . Count = = 0 ) continue ;
var head = tiers [ 0 ] ;
var block = UiKit . Cell ( list , "Set_" + setId , new Color ( 0f , 0f , 0f , 0f ) , null ) ;
block . raycastTarget = false ;
var band = UiKit . Box ( "Band" , block . transform , new Vector2 ( 0.5f , 1f ) , new Vector2 ( 0.5f , 1f ) , Vector2 . zero , new Vector2 ( 700f , 70f ) , new Color ( 0.47f , 0.33f , 0.24f ) ) ;
UiKit . FillLabel ( band . transform , head . nameKo , 40 , UiKit . White ) ;
int owned = TreasureRules . OwnedIn ( d , head ) ;
UiKit . Label ( block . transform , "보유 " + owned + "/" + head . members . Count , 30 , owned = = head . members . Count ? UiKit . Ink : UiKit . Red , TextAnchor . MiddleRight , new Vector2 ( 1f , 1f ) , new Vector2 ( 1f , 1f ) , new Vector2 ( 0f , - 10f ) , new Vector2 ( 200f , 50f ) ) ;
var row = UiKit . Rect ( "Members" , block . transform , new Vector2 ( 0.5f , 1f ) , new Vector2 ( 0.5f , 1f ) , new Vector2 ( 0f , - 84f ) , new Vector2 ( 1032f , 290f ) ) ;
var hl = row . gameObject . AddComponent < HorizontalLayoutGroup > ( ) ;
hl . spacing = 12f ;
hl . childAlignment = TextAnchor . UpperCenter ;
hl . childControlWidth = hl . childControlHeight = false ;
foreach ( var m in head . members )
{
var it = db . Treasures . Get ( m ) ;
if ( it = = null ) continue ;
var holder = UiKit . Rect ( "M" , row , new Vector2 ( 0.5f , 0.5f ) , new Vector2 ( 0.5f , 0.5f ) , Vector2 . zero , new Vector2 ( 196f , 290f ) ) ;
TreasureCell ( holder , it , true ) ;
var c = holder . GetChild ( 0 ) as RectTransform ;
c . anchorMin = Vector2 . zero ;
c . anchorMax = Vector2 . one ;
c . offsetMin = c . offsetMax = Vector2 . zero ;
}
var fx = UiKit . Box ( "Effects" , block . transform , new Vector2 ( 0.5f , 0f ) , new Vector2 ( 0.5f , 0f ) , Vector2 . zero , new Vector2 ( 1032f , 250f ) , new Color ( 0.96f , 0.93f , 0.87f ) ) ;
UiKit . Border ( fx , UiKit . Line , 2f ) ;
var best = TreasureRules . SetTier ( db , d , setId ) ;
var sb = new System . Text . StringBuilder ( "<b>기본 효과</b> <size=26>(가장 높은 달성 단계 1개)</size>" ) ;
foreach ( var t in tiers )
{
bool ok = TreasureRules . TierReached ( d , t ) ;
string label = t . stars = = 0 ? "[세트]" : "[" + t . stars + "성]" ;
string stat = TreasureRules . StatKo ( t . effectKey . Replace ( "_pct" , "" ) ) ;
sb . Append ( "\n" ) . Append ( ok ? ( t = = best ? "<color=#2c6a26><b>" : "<color=#2c6a26>" ) : "<color=#8a8078>" ) . Append ( label ) . Append ( " " ) . Append ( stat ) . Append ( " +" ) . Append ( t . pct . ToString ( "0.#" ) ) . Append ( "%" )
. Append ( ok ? ( t = = best ? " ✔ 적용</b>" : " 달성" ) : " 미달성" ) . Append ( "</color>" ) ;
}
UiKit . FillLabel ( fx . transform , sb . ToString ( ) , 30 , UiKit . Ink , TextAnchor . MiddleLeft , false , 24f ) ;
SetCount + + ;
}
}
// ---------- ③ 상자 ----------
void BuildChests ( RectTransform p )
{
var db = S . Db ;
var d = S . Save ;
var e = db . Economy ;
var goalBox = UiKit . TopBand ( "Points" , p , 6f , 150f , 24f , 24f ) ;
var gimg = UiKit . Paint ( goalBox , UiKit . Paper ) ;
UiKit . Border ( gimg , UiKit . Line , 3f ) ;
2026-11-06 14:20:57 +00:00
if ( UiKit . Icon ( goalBox , "chest_point" , new Vector2 ( 0f , 0.5f ) , new Vector2 ( 0f , 0.5f ) , new Vector2 ( 16f , 0f ) , 100f ) = = null )
UiKit . FillLabel ( UiKit . Dot ( "P" , goalBox , new Vector2 ( 0f , 0.5f ) , new Vector2 ( 0f , 0.5f ) , new Vector2 ( 20f , 0f ) , 90f , UiKit . Coin ) . transform , "P" , 44 , UiKit . Ink ) ;
2026-11-05 15:22:54 +00:00
var reward = db . Chests . Get ( e . ChestPointReward ) ;
UiKit . Label ( goalBox , ( e . ChestPointGoal - d . inv . chestPoints ) + "포인트 더 모으면 " + ( reward ! = null ? reward . nameKo : "" ) , 34 , UiKit . Ink , TextAnchor . MiddleLeft , new Vector2 ( 0f , 1f ) , new Vector2 ( 0f , 1f ) , new Vector2 ( 130f , - 12f ) , new Vector2 ( 800f , 54f ) ) ;
var fill = UiKit . Bar ( "Bar" , goalBox , new Vector2 ( 0f , 0f ) , new Vector2 ( 0f , 0f ) , new Vector2 ( 130f , 52f ) , new Vector2 ( 700f , 30f ) , new Color ( 0.88f , 0.84f , 0.77f ) , UiKit . Coin ) ;
UiKit . SetBar ( fill , d . inv . chestPoints / ( float ) Mathf . Max ( 1 , e . ChestPointGoal ) ) ;
UiKit . Label ( goalBox , "상자 포인트 " + d . inv . chestPoints + " / " + e . ChestPointGoal , 26 , UiKit . InkSoft , TextAnchor . MiddleLeft , new Vector2 ( 0f , 0f ) , new Vector2 ( 0f , 0f ) , new Vector2 ( 130f , 8f ) , new Vector2 ( 700f , 40f ) , false ) ;
var c = db . Chests . Get ( SelectedChest ) ;
if ( c = = null ) return ;
int count = TreasureRules . ChestCount ( d , c . id ) ;
var banner = UiKit . Box ( "Banner" , p , new Vector2 ( 0.5f , 1f ) , new Vector2 ( 0.5f , 1f ) , new Vector2 ( 0f , - 180f ) , new Vector2 ( 560f , 470f ) , ChestColor ( c . id ) ) ;
UiKit . Border ( banner , new Color ( 0.25f , 0.2f , 0.18f ) , 4f ) ;
2026-11-06 14:20:57 +00:00
UiKit . Title ( UiKit . Label ( banner . transform , c . nameKo , 60 , UiKit . White , TextAnchor . MiddleCenter , new Vector2 ( 0.5f , 1f ) , new Vector2 ( 0.5f , 1f ) , new Vector2 ( 0f , - 40f ) , new Vector2 ( 520f , 90f ) ) , true ) ;
UiKit . Icon ( banner . transform , "chest_" + c . id , new Vector2 ( 0f , 1f ) , new Vector2 ( 0.5f , 0.5f ) , new Vector2 ( 10f , - 10f ) , 150f ) ;
2026-11-05 15:22:54 +00:00
int line = 0 ;
for ( int i = 0 ; i < ChestDb . ProbGrades . Length ; i + + )
{
if ( c . p [ i ] < = 0f ) continue ;
var chip = UiKit . Box ( "P" + i , banner . transform , new Vector2 ( 0.5f , 1f ) , new Vector2 ( 0.5f , 1f ) , new Vector2 ( 0f , - 150f - line * 62f ) , new Vector2 ( 360f , 54f ) , GradeColor ( ChestDb . ProbGrades [ i ] ) ) ;
UiKit . FillLabel ( chip . transform , TreasureRules . GradeKo ( ChestDb . ProbGrades [ i ] ) + " " + ( c . p [ i ] * 100f ) . ToString ( "0.#" ) + " %" , 30 , UiKit . White ) ;
line + + ;
}
var extra = new List < string > ( ) ;
if ( c . goldMax > 0 ) extra . Add ( "골드 " + c . goldMin + "~" + c . goldMax ) ;
if ( c . gemMax > 0 ) extra . Add ( "보옥 " + c . gemMin + "~" + c . gemMax ) ;
if ( c . ironMax > 0 ) extra . Add ( "운철 " + c . ironMin + "~" + c . ironMax ) ;
extra . Add ( "포인트 +" + c . points ) ;
UiKit . Label ( banner . transform , string . Join ( " · " , extra . ToArray ( ) ) , 26 , UiKit . White , TextAnchor . MiddleCenter , new Vector2 ( 0.5f , 0f ) , new Vector2 ( 0.5f , 0f ) , new Vector2 ( 0f , 18f ) , new Vector2 ( 540f , 50f ) , false ) ;
UiKit . Btn ( "Prev" , p , "◁" , 70 , new Color ( 0f , 0f , 0f , 0f ) , UiKit . Ink , new Vector2 ( 0f , 1f ) , new Vector2 ( 0f , 1f ) , new Vector2 ( 40f , - 360f ) , new Vector2 ( 120f , 140f ) , ( ) = > Step ( - 1 ) ) ;
UiKit . Btn ( "Next" , p , "▷" , 70 , new Color ( 0f , 0f , 0f , 0f ) , UiKit . Ink , new Vector2 ( 1f , 1f ) , new Vector2 ( 1f , 1f ) , new Vector2 ( - 40f , - 360f ) , new Vector2 ( 120f , 140f ) , ( ) = > Step ( 1 ) ) ;
var open = UiKit . Btn ( "Open" , p , count > 0 ? "열기\n<size=28>보유 " + count + "</size>" : "열기\n<size=28>상자 없음</size>" , 46 , count > 0 ? UiKit . Red : UiKit . Disabled , UiKit . White ,
new Vector2 ( 0.5f , 1f ) , new Vector2 ( 0.5f , 1f ) , new Vector2 ( 0f , - 680f ) , new Vector2 ( 480f , 140f ) , ( ) = > DoOpen ( SelectedChest ) ) ;
open . interactable = count > 0 ;
UiKit . Label ( p , "상자는 이 탭에서만 엽니다 · 중복 = 조각 · 천기 = 적장 토벌 전용" , 26 , UiKit . InkSoft , TextAnchor . MiddleCenter , new Vector2 ( 0.5f , 1f ) , new Vector2 ( 0.5f , 1f ) , new Vector2 ( 0f , - 836f ) , new Vector2 ( 1000f , 44f ) , false ) ;
int n = db . Chests . chests . Count ;
float w = ( 1032f - ( n - 1 ) * 12f ) / n ;
for ( int i = 0 ; i < n ; i + + )
{
var ch = db . Chests . chests [ i ] ;
int k = i ;
var b = UiKit . Btn ( "Chest_" + ch . id , p , "" , 28 , i = = chestIdx ? new Color ( 1f , 0.95f , 0.8f ) : UiKit . Paper , UiKit . Ink , new Vector2 ( 0f , 0f ) , new Vector2 ( 0f , 0f ) , new Vector2 ( 24f + i * ( w + 12f ) , 24f ) , new Vector2 ( w , 220f ) , ( ) = >
{
chestIdx = k ;
Refresh ( ) ;
} ) ;
UiKit . Border ( b . GetComponent < Image > ( ) , i = = chestIdx ? UiKit . Coin : UiKit . Line , i = = chestIdx ? 5f : 2f ) ;
var box = UiKit . Box ( "Icon" , b . transform , new Vector2 ( 0.5f , 1f ) , new Vector2 ( 0.5f , 1f ) , new Vector2 ( 0f , - 20f ) , new Vector2 ( w * 0.7f , 90f ) , ChestColor ( ch . id ) ) ;
box . raycastTarget = false ;
2026-11-06 14:20:57 +00:00
UiKit . Icon ( box . transform , "chest_" + ch . id , new Vector2 ( 0.5f , 0.5f ) , new Vector2 ( 0.5f , 0.5f ) , new Vector2 ( 0f , 4f ) , 96f ) ;
2026-11-05 15:22:54 +00:00
UiKit . Label ( b . transform , ch . nameKo + "\n<size=34>× " + TreasureRules . ChestCount ( d , ch . id ) + "</size>" , 26 , UiKit . Ink , TextAnchor . MiddleCenter , new Vector2 ( 0.5f , 0f ) , new Vector2 ( 0.5f , 0f ) , new Vector2 ( 0f , 14f ) , new Vector2 ( w , 100f ) ) ;
}
}
void Step ( int dir )
{
int n = Mathf . Max ( 1 , S . Db . Chests . chests . Count ) ;
chestIdx = ( ( chestIdx + dir ) % n + n ) % n ;
Refresh ( ) ;
}
public void DoOpen ( string id )
{
var r = S . OpenChest ( id ) ;
LastOpen = r ;
if ( r = = null )
{
Root . Toast ( "상자 없음" ) ;
return ;
}
var it = r . treasureId ! = null ? S . Db . Treasures . Get ( r . treasureId ) : null ;
var sb = new System . Text . StringBuilder ( ) ;
if ( it ! = null )
sb . Append ( "<size=48><b>" ) . Append ( it . nameKo ) . Append ( "</b></size>\n" ) . Append ( TreasureRules . GradeKo ( it . grade ) ) . Append ( r . gradeUp ? " (상위 등급!)" : "" )
. Append ( r . isNew ? " <color=#b0301e>NEW</color>" : " 조각 +" + r . shards ) . Append ( "\n\n" ) ;
var parts = new List < string > ( ) ;
if ( r . gold > 0 ) parts . Add ( "골드 +" + r . gold . ToString ( "N0" ) ) ;
if ( r . gem > 0 ) parts . Add ( "보옥 +" + r . gem . ToString ( "N0" ) ) ;
if ( r . iron > 0 ) parts . Add ( "운철 +" + r . iron ) ;
parts . Add ( "상자 포인트 +" + r . points ) ;
sb . Append ( string . Join ( " · " , parts . ToArray ( ) ) ) ;
if ( r . bonusChests > 0 ) sb . Append ( "\n<color=#b0301e>포인트 달성 → " ) . Append ( S . Db . Chests . Get ( S . Db . Economy . ChestPointReward ) . nameKo ) . Append ( " +" ) . Append ( r . bonusChests ) . Append ( "</color>" ) ;
Root . Modal ( S . Db . Chests . Get ( id ) . nameKo + " 열기" , sb . ToString ( ) ,
new OutGameRoot . ModalButton ( "한 번 더" , UiKit . Red , ( ) = > DoOpen ( id ) ) ,
new OutGameRoot . ModalButton ( "확인" , UiKit . Dark , null ) ) ;
}
public static Color ChestColor ( string id )
{
switch ( id )
{
case "bronze" : return new Color ( 0.69f , 0.47f , 0.3f ) ;
case "silver" : return new Color ( 0.66f , 0.68f , 0.72f ) ;
case "gold" : return new Color ( 0.88f , 0.7f , 0.22f ) ;
case "general" : return new Color ( 0.62f , 0.25f , 0.22f ) ;
case "gem" : return new Color ( 0.3f , 0.65f , 0.57f ) ;
}
return UiKit . Slot ;
}
}
}