Project_WL/Assets/WL/PartSkill/WLPartSkillText.cs

107 lines
6.3 KiB
C#
Raw Permalink Blame History

This file contains ambiguous Unicode characters

This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

// ─────────────────────────────────────────────────────────────────────────────
// 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 + "단계면 시너지";
}
}
}