using System.Collections; using System.Collections.Generic; using System.IO; using UnityEngine; namespace TKS.OutGame { /// /// 아웃게임 화면 검증 캡처(에디터 DataImporter.CaptureOutGame 이 SessionState 로 출력 폴더를 넘기면 생성 · 세이브 = 메모리 전용 신규 유저). /// 로비 → 영웅 목록 → 영웅 상세(캡처용 장비 지급·장착) → 편성 → 뽑기 → 첫 10연(무료) 결과 → 상점 → 월드맵 팝업 → 전투(적 전원 처치) 결과 → 재방문 팝업. /// public class OutGameCaptureDriver : MonoBehaviour { public const string DirKey = "TKS_OUTGAME_CAPTURE_DIR"; public string OutputDir; public int Width = 720; public int Height = 1280; readonly List log = new List(); int shot = 1; #if UNITY_EDITOR [RuntimeInitializeOnLoadMethod(RuntimeInitializeLoadType.AfterSceneLoad)] static void AutoSpawn() { string dir = UnityEditor.SessionState.GetString(DirKey, ""); if (string.IsNullOrEmpty(dir)) return; UnityEditor.SessionState.EraseString(DirKey); var d = new GameObject("OutGameCaptureDriver").AddComponent(); d.OutputDir = dir; } #endif IEnumerator Start() { Directory.CreateDirectory(OutputDir); yield return null; yield return null; var root = OutGameRoot.Instance; var cam = Camera.main; if (root == null || cam == null) { Log("FAIL: OutGameRoot 또는 카메라 없음"); Finish(1); yield break; } var s = root.Session; Log("memoryOnly=" + SaveStore.MemoryOnly + " newUser=" + s.IsNewUser + " gold=" + s.Save.gold + " gem=" + s.Save.gem + " stamina=" + s.Save.stamina + " heroes=" + s.Save.heroes.Count + " preset=" + string.Join(",", s.Save.ActivePreset.slots.ToArray())); yield return Wait(); yield return Shot(cam, "lobby"); root.Show(root.HeroList); yield return Wait(); yield return Shot(cam, "hero_list"); // 영웅 상세: 두 번째 시작 영웅 · 캡처용 장비 지급(요구 장비 4칸분) → 3칸 장착 · 1칸 = 가방 보유 표시 var id = s.Db.Economy.StartHeroes.Length > 1 ? s.Db.Economy.StartHeroes[1] : s.Db.Economy.StartHeroes[0]; var h = s.Def(id); var hs = s.Save.Hero(id); for (int i = 0; i < 4; i++) s.Save.inv.AddGear(HeroRules.RequiredGear(s.Db, h, hs, i), 1); for (int i = 0; i < 3; i++) Log("equip slot " + i + " → " + (s.Equip(id, i) ?? "ok")); HeroRules.GrantExp(hs, s.Db.Levels.Get(1).expToNext + 5); s.Commit(); root.ShowHero(id); yield return Wait(); yield return Shot(cam, "hero_detail_" + id); root.Show(root.Formation); yield return Wait(); yield return Shot(cam, "formation"); root.Show(root.Trade); root.Trade.SetPage(0); yield return Wait(); yield return Shot(cam, "gacha"); root.Trade.DoDraw(s.Db.Gacha.TenCount); yield return new WaitForSecondsRealtime(0.5f); Log("gacha revealed(0.5s)=" + root.Trade.RevealedCount); root.Trade.RevealAll(); yield return Wait(); var pulls = root.Trade.LastPulls; var names = new List(); if (pulls != null) foreach (var p in pulls) names.Add(p.heroId + "★" + p.tier + (p.isNew ? "N" : p.shards > 0 ? "+" + p.shards : "+g" + p.gold)); Log("gacha 10 = " + string.Join(" ", names.ToArray()) + " · pity=" + s.Save.gacha.pity + " gem=" + s.Save.gem + " firstTenUsed=" + s.Save.gacha.firstTenUsed); yield return Shot(cam, "gacha_result"); root.Trade.CloseResult(); root.Trade.SetPage(2); yield return Wait(); yield return Shot(cam, "shop"); root.ShowLobby(); root.OpenWorldMap(); yield return Wait(); var wm = root.Map; wm.OpenPopup(0); yield return Wait(); yield return Shot(cam, "worldmap_popup"); int st0 = s.Save.stamina; wm.ConfirmPopup(); var bm = root.Battle; float t0 = Time.realtimeSinceStartup; while (bm.Phase != BattlePhase.PlayerTurn && Time.realtimeSinceStartup - t0 < 10f) yield return null; Log("battle players=" + bm.AliveCount(Faction.Player) + " enemies=" + bm.AliveCount(Faction.Enemy) + " stamina " + st0 + "→" + s.Save.stamina); foreach (var u in bm.Units) if (u != null && u.Faction == Faction.Player) Log(" " + u.DisplayName + " " + u.Type + " hp" + u.MaxHp + " atk" + u.Atk + " def" + u.Def + " @" + u.Position); yield return new WaitForSecondsRealtime(0.6f); yield return Shot(cam, "battle_start"); foreach (var e in bm.AliveUnits(Faction.Enemy)) e.TakeDamage(e.Hp); // 결과 화면 확인용(적 전원 처치) bm.CheckBattleEnd(); yield return new WaitForSecondsRealtime(0.6f); var r = s.LastReward; Log("result phase=" + bm.Phase + " stars=" + (r != null ? r.stars : -1) + " gold+" + (r != null ? r.gold : 0) + " exp+" + (r != null ? r.exp : 0) + " gem+" + (r != null ? r.gem : 0) + " gear=" + (r != null ? r.gearId : "")); yield return Shot(cam, "battle_result"); bm.ContinueAfterResult(); yield return Wait(); wm.OpenPopup(0); yield return Wait(); yield return Shot(cam, "worldmap_revisit"); Finish(0); } static IEnumerator Wait() { yield return null; yield return new WaitForSecondsRealtime(0.3f); } IEnumerator Shot(Camera cam, string name) { string file = Path.Combine(OutputDir, shot.ToString("00") + "_" + name + ".png"); shot++; yield return CaptureUtil.Capture(cam, Width, Height, file); Log("shot " + file); } void Log(string s) { log.Add(s); Debug.Log("[OutGameCapture] " + s); try { File.WriteAllLines(Path.Combine(OutputDir, "capture_log.txt"), log.ToArray()); } catch { } } void Finish(int code) { Log("finish code=" + code); #if UNITY_EDITOR UnityEditor.EditorApplication.Exit(code); #else Application.Quit(code); #endif } } }