186 lines
7.1 KiB
C#
186 lines
7.1 KiB
C#
using System.Collections.Generic;
|
||
using System.Globalization;
|
||
using UnityEngine;
|
||
|
||
namespace TKS.OutGame
|
||
{
|
||
/// <summary>
|
||
/// 로비 장면 표(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(꽃잎).
|
||
/// </summary>
|
||
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();
|
||
}
|
||
|
||
/// <summary>s_sprite 의 | 로 나눈 테마 아이콘 id 들.</summary>
|
||
public string[] Sprites
|
||
{
|
||
get { return sprite.Split(new[] { '|' }, System.StringSplitOptions.RemoveEmptyEntries); }
|
||
}
|
||
}
|
||
|
||
static List<Row> rows;
|
||
|
||
public static void Reload()
|
||
{
|
||
rows = null;
|
||
}
|
||
|
||
public static List<Row> 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<Row> All(string kind)
|
||
{
|
||
var list = new List<Row>();
|
||
foreach (var r in Rows)
|
||
if (r.kind == kind)
|
||
list.Add(r);
|
||
return list;
|
||
}
|
||
|
||
/// <summary>출전 인원 n 의 자리(i_slot 순) — 그 인원 줄이 없으면 n 보다 큰 가장 작은 인원 줄의 앞 n 개.</summary>
|
||
public static List<Row> 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<Row>();
|
||
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);
|
||
}
|
||
|
||
/// <summary>같은 형식의 장면 표 읽기(로비 · 내정 domestic_scene 등 · 없으면 빈 목록).</summary>
|
||
public static List<Row> Load(string path)
|
||
{
|
||
var list = new List<Row>();
|
||
var ta = Resources.Load<TextAsset>(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;
|
||
}
|
||
}
|
||
}
|