using System.Collections.Generic; using System.Globalization; using UnityEngine; namespace TKS.OutGame { /// /// 로비 장면 표(Resources/UI/lobby_scene.csv · PD 2026-11-11 「로비 위치 위로 · 캐릭터가 배경과 겹치지 않게 · 배경에 움직이는 연출 · 너무 어둡지 않게」). /// 좌표 = 배경 그림(테마 bg_lobby) px · 왼쪽 위 0,0 · 아래로 + — 배경 그림을 바꾸면 이 표만 고친다(자리·크기·속도·주기·간격 = 표 · C45). /// s_kind: view(그림 위치) · slot(출전 영웅 자리 · i_n 인원 · i_slot 순번) · shadow(발밑 그림자) · flag(깃발 펄럭임) · light(불빛) · bird(새 떼) · petal(꽃잎). /// public static class LobbyScene { public const string TablePath = "UI/lobby_scene"; public class Row { public string kind = ""; public string sprite = ""; public string note = ""; public Color color = Color.white; public int n; public int slot; public int count; public float x; public float y; public float w; public float h; public float scale = 1f; public float amp; public float period = 1f; public float phase; public float waves; public float billow; public float shade = -1f; // -1 = 표에 없음(그래픽 기본값) public float min = 1f; public float max = 1f; public float speed; public float gapMin; public float gapMax; public float first; // 훈련 장면 병사 동작(내정 · PD 2026-11-12) — 서기 · 모으기 · 타격 · 유지 · 쉼(초) public float stand; public float ready; public float hit; public float hold; public float rest; public Row Clone() { return (Row)MemberwiseClone(); } /// s_sprite 의 | 로 나눈 테마 아이콘 id 들. public string[] Sprites { get { return sprite.Split(new[] { '|' }, System.StringSplitOptions.RemoveEmptyEntries); } } } static List rows; public static void Reload() { rows = null; } public static List Rows { get { Ensure(); return rows; } } public static Row First(string kind) { foreach (var r in Rows) if (r.kind == kind) return r; return null; } public static List All(string kind) { var list = new List(); foreach (var r in Rows) if (r.kind == kind) list.Add(r); return list; } /// 출전 인원 n 의 자리(i_slot 순) — 그 인원 줄이 없으면 n 보다 큰 가장 작은 인원 줄의 앞 n 개. public static List Slots(int n) { int best = int.MaxValue; foreach (var r in Rows) if (r.kind == "slot" && r.n >= n && r.n < best) best = r.n; var list = new List(); foreach (var r in Rows) if (r.kind == "slot" && r.n == best) list.Add(r); list.Sort((a, b) => a.slot.CompareTo(b.slot)); if (list.Count > n) list.RemoveRange(n, list.Count - n); return list; } static void Ensure() { if (rows != null) return; rows = Load(TablePath); } /// 같은 형식의 장면 표 읽기(로비 · 내정 domestic_scene 등 · 없으면 빈 목록). public static List Load(string path) { var list = new List(); var ta = Resources.Load(path); if (ta == null) return list; string[] head = null; foreach (var raw in ta.text.Replace("\r", "").Split('\n')) { var line = raw.TrimStart(''); if (line.Trim().Length == 0 || line.TrimStart().StartsWith("#")) continue; var cells = SkillVfx.SplitCsv(line); if (head == null) { head = cells; continue; } var r = new Row(); for (int i = 0; i < head.Length && i < cells.Length; i++) { string k = head[i].Trim(), v = cells[i].Trim(); if (v.Length == 0) continue; switch (k) { case "s_kind": r.kind = v.ToLowerInvariant(); break; case "s_sprite": r.sprite = v; break; case "s_note": r.note = v; break; case "s_color": Color c; if (ColorUtility.TryParseHtmlString(v, out c)) r.color = c; break; case "i_n": r.n = (int)F(v); break; case "i_slot": r.slot = (int)F(v); break; case "i_count": r.count = (int)F(v); break; case "f_x": r.x = F(v); break; case "f_y": r.y = F(v); break; case "f_w": r.w = F(v); break; case "f_h": r.h = F(v); break; case "f_scale": r.scale = F(v); break; case "f_amp": r.amp = F(v); break; case "f_period": r.period = F(v); break; case "f_phase": r.phase = F(v); break; case "f_waves": r.waves = F(v); break; case "f_billow": r.billow = F(v); break; case "f_shade": r.shade = F(v); break; case "f_min": r.min = F(v); break; case "f_max": r.max = F(v); break; case "f_speed": r.speed = F(v); break; case "f_gap_min": r.gapMin = F(v); break; case "f_gap_max": r.gapMax = F(v); break; case "f_first": r.first = F(v); break; case "f_stand": r.stand = F(v); break; case "f_ready": r.ready = F(v); break; case "f_hit": r.hit = F(v); break; case "f_hold": r.hold = F(v); break; case "f_rest": r.rest = F(v); break; } } if (r.kind.Length > 0) list.Add(r); } return list; } static float F(string v) { float f; return float.TryParse(v, NumberStyles.Float, CultureInfo.InvariantCulture, out f) ? f : 0f; } } }