using System; using System.Collections.Generic; using System.Numerics; using UnityEngine; using UnityEngine.UI; using VS.Sim; using Random = UnityEngine.Random; using Vector2 = UnityEngine.Vector2; using Vector3 = UnityEngine.Vector3; // 부가 시스템 화면 — 선물 슬롯·팝업 · 부스터 · 방치 보상 · 퀘스트 · 일일 보상 · 티켓 상점 · 채팅 · 시청자 수 (systems.md) namespace VS.View { public partial class GameApp { static readonly string[] GiftEnum = { "NoAds", "SmallMoneyPack", "BigMoneyPack", "ReducePrice", "X4TapIncome", "X4PassiveIncome", "X10Income" }; static readonly string[] GiftBadge = { "AD", "$", "$$", "%", "x4", "x4", "x10" }; readonly List<(Button b, Image icon, Text badge, Text time)> giftViews = new List<(Button, Image, Text, Text)>(); string GiftTitle(int t) => T.Loc.Get($"Content.Gift.{GiftEnum[t]}.Title", T.Gift(t)?.Title ?? GiftEnum[t]); string GiftDesc(int t) { string d = T.Loc.Get($"Content.Gift.{GiftEnum[t]}.Description", T.Gift(t)?.PopupDescription ?? ""); return d.Replace("{0}", Fmt.Time(G.GiftEffectDuration(t))); } // ---------------- 선물 슬롯 (GiftSlotView) ---------------- void BuildGiftSlots(RectTransform parent) { int n = Mathf.Max(1, T.Cfg.gift.maxVisibleSlots); for (int i = 0; i < n; i++) { int slot = i; var b = UI.Btn(parent, "GiftSlot" + i, Skin.Dark, Color.white, () => OnGiftSlot(slot)); b.GetComponent().sizeDelta = new Vector2(140, 140); var ic = UI.Icon(b.transform, "Icon", Skin.Icon("gift"), Color.white); ic.rectTransform.Fill(18, 40, 18, 12); var badge = UI.Txt(b.transform, "Badge", "", 34, Color.white, TextAnchor.MiddleCenter, true); badge.rectTransform.Place(new Vector2(0.5f, 0), new Vector2(0.5f, 0), new Vector2(0, 24), new Vector2(140, 50)); var tm = UI.Txt(b.transform, "Time", "", 26, Color.white, TextAnchor.MiddleCenter, true); tm.rectTransform.Place(new Vector2(0.5f, 0), new Vector2(0.5f, 0), new Vector2(0, -16), new Vector2(170, 40)); giftViews.Add((b, ic, badge, tm)); } } void OnGiftSlot(int slot) { if (G.GiftSlot == null || slot >= G.GiftSlot.Length) return; int t = G.GiftSlot[slot]; if (t < 0 || G.IsGiftEffectActive(t)) return; OpenGiftPopup(t); } void RefreshGiftSlots() { for (int i = 0; i < giftViews.Count; i++) { var (b, icon, badge, time) = giftViews[i]; int t = G.GiftSlot != null && i < G.GiftSlot.Length ? G.GiftSlot[i] : -1; b.gameObject.SetActive(t >= 0); if (t < 0) continue; badge.text = GiftBadge[t]; float rem = G.GiftEffectRemain(t); time.text = rem > 0 ? Fmt.Time(rem) : (t == GiftTypes.NoAds && G.Gifts.TryGetValue(t, out var gs) && gs.Rv > 0 ? $"{gs.Rv}/{T.X.giftNoAdsVideos}" : ""); b.GetComponent().color = rem > 0 ? new Color32(255, 225, 150, 255) : (Color32)Color.white; } } public void OpenGiftPopup(int t) { var p = NewPopup("Gift", GiftTitle(t), 980, Pal.Purple); var ic = UI.Icon(p.body, "Icon", Skin.Icon("gift"), Color.white); ic.rectTransform.Place(new Vector2(0.5f, 1), new Vector2(0.5f, 1), new Vector2(0, -120), new Vector2(200, 200)); UI.Txt(ic.transform, "Badge", GiftBadge[t], 64, Color.white, TextAnchor.MiddleCenter, true).rectTransform.Fill(); var desc = UI.Txt(p.body, "Desc", GiftDesc(t), 38, Pal.Ink); desc.rectTransform.Place(new Vector2(0, 1), new Vector2(1, 1), new Vector2(0, -300), new Vector2(-40, 130)); string amount = GiftTypes.IsInstant(t) ? Fmt.Num(G.MoneyPackReward(t)) + " 코인" : ""; var amt = UI.Txt(p.body, "Amount", amount, 54, Pal.PinkDark); amt.rectTransform.Place(new Vector2(0, 1), new Vector2(1, 1), new Vector2(0, -410), new Vector2(0, 80)); float x = t == GiftTypes.SmallMoneyPack ? -300 : -170; void Btn(string label, Color c, Action a) { var b = UI.TextBtn(p.body, label, label, c, 36, () => { a(); RefreshAll(); }, out _); b.GetComponent().Place(new Vector2(0.5f, 0), new Vector2(0.5f, 0), new Vector2(x, 80), new Vector2(280, 140)); x += 300; } if (t == GiftTypes.SmallMoneyPack) Btn("받기", Pal.Green, () => { ShowGot(G.ClaimGift(t, false)); ClosePopup(); }); Btn("광고 보기\n(시험)", Pal.Pink, () => { ShowGot(G.ClaimGift(t, true)); ClosePopup(); }); Btn("티켓 1장", Pal.Blue, () => { if (!G.TrySpendTicket()) { Toast("티켓이 부족합니다"); return; } ShowGot(G.ClaimGift(t, true)); ClosePopup(); }); var close = p.panel.Find("Head/Close")?.GetComponent