Project_WL/Assets/WL/PartSkill/WLPartSkillText.cs

107 lines
6.3 KiB
C#
Raw Normal View History

// ─────────────────────────────────────────────────────────────────────────────
// WLPartSkillText.cs — 파츠 스킬 표시 문구(장비 화면 · 스킬 상세 · 도감) (PD 지시 #879 · 기획 v2 18 · 19장)
// 문구의 숫자 = 레벨표 행(FR 원본) 그대로 + 설정 환산(거리 m). 등급 → 단계 = WLPartSkill.json tierLevel/tierMult.
// ─────────────────────────────────────────────────────────────────────────────
using System.Text;
using UnityEngine;
using WL.Equip;
namespace WL.PartSkill
{
public static class WLPartSkillText
{
public static string AttrName(string attr)
{
switch (attr)
{
case "attack": return "공격";
case "defense": return "방어";
case "passive": return "패시브";
case "weapon": return "무기 시너지";
}
return "";
}
public static string PartName(eFREquipmentType p) { return WLEquipTables.SlotName(p); }
static string N(float v) { return Mathf.Abs(v - Mathf.Round(v)) < 0.01f ? Mathf.Round(v).ToString("0") : v.ToString("0.#"); }
/// <summary>단계 1행 요약 — 「개수 4 · 피해 90% · 범위 2.1m · 쿨 7초」(패시브 = 값).</summary>
public static string LevelSummary(WLPartSkillDef d, int level, float mult) { return LevelSummary(d, level, mult, 99); }
/// <param name="maxParts">항목 수 상한(장비 팝업 한 줄용 · #881)</param>
public static string LevelSummary(WLPartSkillDef d, int level, float mult, int maxParts)
{
if (d == null) return "";
var S = WLPartSkillData.S;
if (d.kind == WLPartKind.Passive)
{
var p = WLPartSkillData.Passive(d.lvId, Mathf.Max(1, level));
if (p == null) return "";
string s = "+" + N(p.v0 * mult) + "%";
if (p.v1 > 0f) s += " · +" + N(p.v1 * mult) + "%";
if (d.behavior == "regen") s = (d.v1 > 0f ? N(d.v1) : "5") + "초마다 " + N(p.v0 * mult) + "% 회복";
return s;
}
var r = WLPartSkillData.Level(d.lvSrc, d.lvId, Mathf.Max(1, level));
if (r == null) return "";
var sb = new StringBuilder();
int parts = 0;
System.Action<string> add = x => { if (parts >= maxParts) return; if (sb.Length > 0) sb.Append(" · "); sb.Append(x); parts++; };
if (r.count > 1f) add("개수 " + N(r.count));
if (r.dmgPct > 0f && d.behavior != "heal_heart") add("피해 " + N(r.dmgPct * mult) + "%");
if (r.Has("Heal")) add("회복 " + N(r.Eff("Heal", "Percent", 0f) * mult) + "%");
float hit = r.hitRange > 0f ? r.hitRange : r.splash;
if (hit > 0f && d.behavior != "blades" && d.behavior != "homing") add("범위 " + Mathf.Max(S.minRadius, hit * S.distanceScale).ToString("0.0") + "m");
if (r.Has("Stun")) add("기절 " + N(r.Eff("Stun", "Duration", 0f)) + "초");
if (r.Has("Daze")) add("감속 " + N(r.Eff("Daze", "DecreaseMovePercentage", 0f)) + "%");
if (r.Has("Invincible")) add("무적 " + N(r.Eff("Invincible", "Duration", 0f)) + "초");
if (r.Has("DotDamageAddiction")) add("지속 피해 " + N(r.Eff("DotDamageAddiction", "DamagePercentage", 0f)) + "%");
if (r.duration < 0f) add("상시");
else if (r.cool > 0f) add("쿨 " + N(r.cool) + "초");
return sb.ToString();
}
/// <summary>등급(1~7) 행 문구 — 「Lv3 · 개수 3 · 피해 60%」 · 불멸 · 신화 = 「Lv5 수치 × 1.2」.</summary>
public static string TierRow(WLPartSkillDef d, int tier) { return TierRow(d, tier, 99); }
public static string TierRow(WLPartSkillDef d, int tier, int maxParts)
{
int lv = WLPartSkillData.TierLevel(tier);
float m = WLPartSkillData.TierMult(tier);
if (lv <= 0) return "닫힘";
if (m > 1.0001f) return "Lv" + lv + " 수치 × " + m.ToString("0.0#");
return "Lv" + lv + " · " + LevelSummary(d, lv, 1f, maxParts);
}
/// <summary>시너지 조건 · 상태 한 줄.</summary>
public static string SynergyLine(WLPartSlot s, bool rich)
{
if (s == null || s.def == null) return "";
var d = s.def; var S = WLPartSkillData.S;
int need = S.synergyLevel;
if (!string.IsNullOrEmpty(d.combineKey))
{
var other = WLPartSkillData.Def(d.combineKey);
string on = s.synergy ? (rich ? "<color=#FFD24A>★ 시너지 [정령왕]</color>" : "★ 시너지 [정령왕]") : "둘 다 " + need + "단계면 [정령왕]";
return d.name + " " + s.level + " + " + (other != null ? other.name : "?") + " " + s.synPartnerLevel + " = " + on;
}
if (string.IsNullOrEmpty(d.synKey)) return "";
var p = WLPartSkillData.Def(d.synKey);
string pn = p != null ? p.name + "(" + PartName(p.part) + ")" : "?";
if (d.kind == WLPartKind.WeaponSyn)
{
// #895 무기와 무관 — 장착 장비 조건(짝 패시브 [+ req_key])만
string cond = pn + " " + s.synPartnerLevel;
if (!string.IsNullOrEmpty(d.reqKey)) { var q = WLPartSkillData.Def(d.reqKey); cond += " + " + (q != null ? q.name + "(" + PartName(q.part) + ")" : d.reqKey); }
if (s.synergy) return cond + " = " + (rich ? "<color=#FFD24A>★ 무기 시너지 [" + d.synName + "]</color>" : "★ 무기 시너지 [" + d.synName + "]");
return cond + " · " + need + "단계면 무기 시너지 [" + d.synName + "] (무기 무관)";
}
string head = d.name + " " + s.level + " + " + pn + " " + s.synPartnerLevel;
if (s.synergy) return head + " = " + (rich ? "<color=#FFD24A>★ 시너지 [" + d.synName + "]</color>" : "★ 시너지 [" + d.synName + "]");
return head + " · 둘 다 " + need + "단계면 시너지";
}
}
}