153 lines
5.5 KiB
C#
153 lines
5.5 KiB
C#
using System.Collections.Generic;
|
||
using System.Globalization;
|
||
using UnityEngine;
|
||
|
||
namespace TKS
|
||
{
|
||
/// <summary>
|
||
/// IB(쿠로네코) 슬링샷 UI 이식 값 표(Resources/Skills/ib_ui.csv · C45) + 진행 중 캐릭터 연출(IbUnitMarks)이 쓰는 공용 도우미.
|
||
/// </summary>
|
||
public static class IbUi
|
||
{
|
||
public const string TablePath = "Skills/ib_ui";
|
||
static Dictionary<string, string> values;
|
||
|
||
public static void Reload()
|
||
{
|
||
values = null;
|
||
}
|
||
|
||
static void Ensure()
|
||
{
|
||
if (values != null) return;
|
||
values = new Dictionary<string, string>();
|
||
var ta = Resources.Load<TextAsset>(TablePath);
|
||
if (ta == null) return;
|
||
bool head = true;
|
||
foreach (var raw in ta.text.Replace("\r", "").Split('\n'))
|
||
{
|
||
var line = raw.TrimStart('');
|
||
if (line.Trim().Length == 0 || line.TrimStart().StartsWith("#")) continue;
|
||
if (head)
|
||
{
|
||
head = false;
|
||
continue;
|
||
}
|
||
var c = SkillVfx.SplitCsv(line);
|
||
if (c.Length >= 2) values[c[0].Trim()] = c[1].Trim();
|
||
}
|
||
}
|
||
|
||
public static string Str(string key, string def)
|
||
{
|
||
Ensure();
|
||
string v;
|
||
return values.TryGetValue(key, out v) && v.Length > 0 ? v : def;
|
||
}
|
||
|
||
public static float Num(string key, float def)
|
||
{
|
||
float f;
|
||
return float.TryParse(Str(key, ""), NumberStyles.Float, CultureInfo.InvariantCulture, out f) ? f : def;
|
||
}
|
||
|
||
/// <summary>IB 이펙트·UI 배율 = 이 게임 유닛 반지름 / IB 유닛 반지름.</summary>
|
||
public static float Scale(Unit u)
|
||
{
|
||
return u == null ? 1f : u.Radius / Mathf.Max(0.01f, Num("ib_unit_radius", 0.5f));
|
||
}
|
||
|
||
/// <summary>진영 → IB 속성(water · tree · fire · dark · glow).</summary>
|
||
public static string Element(Unit u)
|
||
{
|
||
string camp = u != null && !string.IsNullOrEmpty(u.Camp) ? u.Camp.ToLowerInvariant() : "none";
|
||
return Str("element_" + camp, Str("element_none", "dark"));
|
||
}
|
||
|
||
/// <summary>IB 사본 하나 띄우기(유닛에 붙임 · 배율 · 렌더러 정렬).</summary>
|
||
public static GameObject Attach(string fxName, Unit u, Vector2 local, float scale, int order)
|
||
{
|
||
var prefab = SkillVfx.LoadFx(fxName);
|
||
if (prefab == null || u == null) return null;
|
||
var go = Object.Instantiate(prefab, u.transform);
|
||
go.name = fxName;
|
||
go.transform.localPosition = new Vector3(local.x, local.y, 0f);
|
||
go.transform.localRotation = Quaternion.identity;
|
||
var ls = u.transform.lossyScale;
|
||
go.transform.localScale = new Vector3(scale / Mathf.Max(0.001f, Mathf.Abs(ls.x)), scale / Mathf.Max(0.001f, Mathf.Abs(ls.y)), 1f);
|
||
foreach (var r in go.GetComponentsInChildren<Renderer>(true)) r.sortingOrder = order;
|
||
return go;
|
||
}
|
||
}
|
||
|
||
/// <summary>
|
||
/// 슬링샷 진행 중 캐릭터 연출 — IB 이식(PD 2026-11-10 「선택된 캐릭터 주위 연출이 누락」):
|
||
/// 행동할 유닛(선택된 아군 · 행동 가능) = 발밑 도는 원(ef_target_circle · IB BottomPosition) + 몸 둘레 빛(ef_attack_ready_standard · IB CenterPosition) — IB ShowUserTurnMark ·
|
||
/// 조준 중(누름 ~ 놓음) = 모든 유닛에 속성 방울(ef_attribute_<속성> · 배율 0.9) — IB SetActiveBarrierVisualEffect.
|
||
/// </summary>
|
||
public class IbUnitMarks : MonoBehaviour
|
||
{
|
||
Unit turnUnit;
|
||
readonly List<GameObject> turnFx = new List<GameObject>();
|
||
readonly List<GameObject> bubbles = new List<GameObject>();
|
||
|
||
public int BubbleCount
|
||
{
|
||
get { return bubbles.Count; }
|
||
}
|
||
|
||
public bool TurnMarkVisible
|
||
{
|
||
get { return turnFx.Count > 0; }
|
||
}
|
||
|
||
public void ShowTurn(Unit u)
|
||
{
|
||
if (u == turnUnit && turnFx.Count > 0) return;
|
||
Clear(turnFx);
|
||
turnUnit = u;
|
||
if (u == null) return;
|
||
float k = IbUi.Scale(u);
|
||
int order = Mathf.RoundToInt(IbUi.Num("order_ground", -8f));
|
||
Add(turnFx, IbUi.Attach("TKS_Fx_IB_TargetCircle", u, new Vector2(0f, -u.Radius * 0.55f), k, order)); // 발(아트 발 = 원 아래쪽 −0.55 R)
|
||
Add(turnFx, IbUi.Attach("TKS_Fx_IB_AttackReady", u, Vector2.zero, k, order));
|
||
}
|
||
|
||
public void ShowBubbles(IEnumerable<Unit> units)
|
||
{
|
||
Clear(bubbles);
|
||
if (units == null) return;
|
||
int order = Mathf.RoundToInt(IbUi.Num("order_bubble", 12f));
|
||
float bs = IbUi.Num("barrier_scale", 0.9f);
|
||
foreach (var u in units)
|
||
{
|
||
if (u == null || !u.IsAlive) continue;
|
||
Add(bubbles, IbUi.Attach("TKS_Fx_IB_Attribute_" + IbUi.Element(u), u, Vector2.zero, IbUi.Scale(u) * bs, order));
|
||
}
|
||
}
|
||
|
||
public void HideBubbles()
|
||
{
|
||
Clear(bubbles);
|
||
}
|
||
|
||
static void Add(List<GameObject> list, GameObject go)
|
||
{
|
||
if (go != null) list.Add(go);
|
||
}
|
||
|
||
static void Clear(List<GameObject> list)
|
||
{
|
||
foreach (var g in list)
|
||
if (g != null) Destroy(g);
|
||
list.Clear();
|
||
}
|
||
|
||
void OnDestroy()
|
||
{
|
||
Clear(turnFx);
|
||
Clear(bubbles);
|
||
}
|
||
}
|
||
}
|