96 lines
5.1 KiB
C#
96 lines
5.1 KiB
C#
// ─────────────────────────────────────────────────────────────────────────────
|
||
// WLSkillHitFeel.cs — 스킬별 피격 반응 덮어쓰기(밀림 · 넉백 · 경직) (#915 · 2026-10-17)
|
||
//
|
||
// PD 원문: 「검 각성 공격에 적중 된 적은 경직 상태로 살짝만 밀리게 해줘(현재는 밀리는 거리 때문에 가장자리에 있는 적이 밀려나 맞지 않을 수 있음)」
|
||
// ■ 그 스킬(맞힌 투사체의 SkillListTableData.e_Skill)에 맞은 몹만:
|
||
// · 피격 밀기(MobStagger #903 mobHitPushDistance) 거리 × pushScale
|
||
// · 원본 넉백(능력치 AttackKnockBack → Actor.KnockBack) 거리 × knockbackScale(MobKnockbackScale 이 몹 넉백 배율 대신 쓴다)
|
||
// · 경직 = max(등급별 경직, staggerSeconds)
|
||
// ■ 값 = Resources/WL/WLSkillHitFeel.json (C45) · 끄기 = enabled 0 · RuntimeDisabled(프로브 전후 비교용)
|
||
// 🔴 Debug.LogError 금지(원본 팝업).
|
||
// ─────────────────────────────────────────────────────────────────────────────
|
||
using System.Collections.Generic;
|
||
using UnityEngine;
|
||
using WL.Combat.Core;
|
||
|
||
namespace WL.Combat.Reaction
|
||
{
|
||
[System.Serializable]
|
||
public class WLSkillHitFeelRule
|
||
{
|
||
public string skill = ""; // eEffect 이름(원본 스킬 클래스)
|
||
public float pushScale = 1f; // 피격 밀기 거리 배율
|
||
public float pushMeters; // #974 > 0 = 피격 밀기 거리 고정(m · pushScale 대신) — PD 「0.2m 정도 넉백」
|
||
public float knockbackScale = 1f; // 원본 넉백 거리 배율(몹 넉백 배율 대신)
|
||
public float staggerSeconds; // 경직 최소 시간(0 = 등급별 그대로)
|
||
}
|
||
|
||
[System.Serializable]
|
||
public class WLSkillHitFeelJson
|
||
{
|
||
public int enabled = 1;
|
||
public WLSkillHitFeelRule[] rules = new WLSkillHitFeelRule[0];
|
||
public string note = "";
|
||
}
|
||
|
||
public static class WLSkillHitFeel
|
||
{
|
||
public const string ResourcesPath = "WL/WLSkillHitFeel";
|
||
public static bool RuntimeDisabled;
|
||
public static string LastLog = "";
|
||
static WLSkillHitFeelJson s_cfg;
|
||
static readonly Dictionary<int, WLSkillHitFeelRule> s_rules = new Dictionary<int, WLSkillHitFeelRule>();
|
||
|
||
static WLSkillHitFeelJson Cfg
|
||
{
|
||
get
|
||
{
|
||
if (s_cfg != null) return s_cfg;
|
||
s_cfg = new WLSkillHitFeelJson(); s_rules.Clear();
|
||
var ta = Resources.Load<TextAsset>(ResourcesPath);
|
||
if (ta == null) { LastLog = "설정 없음 " + ResourcesPath; return s_cfg; }
|
||
try { JsonUtility.FromJsonOverwrite(ta.text, s_cfg); } catch (System.Exception ex) { LastLog = "설정 파싱 실패 — " + ex.Message; }
|
||
if (s_cfg.rules != null)
|
||
foreach (var r in s_cfg.rules)
|
||
{
|
||
eEffect ef;
|
||
if (r != null && System.Enum.TryParse(r.skill, out ef)) s_rules[(int)ef]= r;
|
||
else LastLog = "스킬 이름 없음 " + (r != null ? r.skill : "null");
|
||
}
|
||
return s_cfg;
|
||
}
|
||
}
|
||
|
||
[RuntimeInitializeOnLoadMethod(RuntimeInitializeLoadType.SubsystemRegistration)]
|
||
static void Reset() { s_cfg = null; s_rules.Clear(); RuntimeDisabled = false; }
|
||
|
||
/// <summary>#918 원본 Actor 피해 처리의 넉백 훅 1줄 — 이 피해를 낸 스킬 규칙의 knockbackScale 이 0 이하면 원본 넉백을 아예 시작하지 않는다
|
||
/// (넉백 거리 배율은 시작된 뒤에 줄이므로 0 이어도 맞을 때마다 첫 프레임만큼(약 0.07 m) 밀렸다 · 연타 8 회면 약 0.5 m).</summary>
|
||
public static bool SkipKnockback(DamageInfo d)
|
||
{
|
||
if (RuntimeDisabled || d == null) return false;
|
||
var c = Cfg;
|
||
if (c.enabled == 0 || s_rules.Count == 0) return false;
|
||
var pd = d.Beater_pd; var s = pd != null ? pd.m_SkillListTableData : null;
|
||
if (s == null) return false;
|
||
WLSkillHitFeelRule r;
|
||
if (!s_rules.TryGetValue((int)s.e_Skill, out r) || r.knockbackScale > 0f) return false;
|
||
KnockbackSkipped++;
|
||
return true;
|
||
}
|
||
public static int KnockbackSkipped;
|
||
|
||
/// <summary>이 피격을 낸 스킬의 규칙(없으면 null).</summary>
|
||
public static WLSkillHitFeelRule For(in HitConfirmedEvent e)
|
||
{
|
||
if (RuntimeDisabled) return null;
|
||
var c = Cfg;
|
||
if (c.enabled == 0 || s_rules.Count == 0) return null;
|
||
var pd = e.projectile; var s = pd != null ? pd.m_SkillListTableData : null;
|
||
if (s == null) return null;
|
||
WLSkillHitFeelRule r;
|
||
return s_rules.TryGetValue((int)s.e_Skill, out r) ? r : null;
|
||
}
|
||
}
|
||
}
|