Project_WL/Assets/WL/Combat/RangeRing/WLRangeRingSettings.cs

127 lines
6.5 KiB
C#
Raw 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.

// ─────────────────────────────────────────────────────────────────────────────
// WLRangeRingSettings.cs — 플레이어 공격 사거리 원(반투명 흰색)의 튜닝 값(SO)
//
// PD 지시 #816 · 발주서 WL-816p
// 「적 공격 가능한 사정거리에 있을 때는 플레이어의 주변에 공격 가능한 범위를 반투명한 흰색 원이
// 발생되고, 플레이어의 공격 사정거리 밖에 적이 3초 이상 있을 경우 흰색 원이 소멸되도록 해줘.」
//
// 에셋 경로(고정): Assets/WL/Combat/Settings/Resources/WL/WLRangeRingSettings.asset
// → Resources.Load<WLRangeRingSettings>("WL/WLRangeRingSettings") 로 1회 로드 후 캐시.
// 에셋이 없거나 enabled = false 면 WLRangeRing 은 아무 것도 하지 않는다(원본 동작 100 %).
//
// 🔴 C45 — 사거리(반지름)는 이 에셋이 갖지 않는다. 게임이 실제 공격 판정에 쓰는 값
// (NavMeshAgent.stoppingDistance = table_classconfig.f_AttackRange + eStat.AttackRange_Up,
// + WLTargetingSettings.immediateAttackMargin)을 런타임에 읽는다. 여기 있는 것은 배율·가산뿐이다.
//
// 🔴 어셈블리 주의: Assets/WL/Combat/ 에 .asmdef 를 만들지 말 것.
// ─────────────────────────────────────────────────────────────────────────────
using UnityEngine;
namespace WL.Combat.RangeRing
{
[CreateAssetMenu(fileName = "WLRangeRingSettings", menuName = "WL/Range Ring Settings", order = 327)]
public sealed class WLRangeRingSettings : ScriptableObject
{
public const string ResourcesPath = "WL/WLRangeRingSettings";
static WLRangeRingSettings s_cached;
static bool s_lookupDone;
public static WLRangeRingSettings Instance
{
get
{
if (!s_lookupDone)
{
s_cached = Resources.Load<WLRangeRingSettings>(ResourcesPath);
s_lookupDone = true;
}
return s_cached;
}
}
/// <summary>테스트용 — 에셋 캐시를 버린다(에디터에서 값을 바꾸고 다시 읽을 때).</summary>
public static void ClearCache() { s_cached = null; s_lookupDone = false; }
[Header("① 켜기")]
[Tooltip("0 이면 원을 만들지 않는다(원본 동작 100 %).")]
public bool enabled = true;
[Tooltip("1 이면 표시/소멸 시각을 Debug.Log 로 남긴다(검증용).")]
public bool verboseLog = false;
[Header("② 모양 · 색")]
[Tooltip("원의 색. a = 반투명 정도(PD: 반투명한 흰색).")]
public Color color = new Color(1f, 1f, 1f, 0.25f);
[Tooltip("1 이면 테두리 링만, 0 이면 원판을 채운다.")]
public bool ringOnly = false;
[Tooltip("ringOnly = 1 일 때 링 두께(m).")]
public float ringWidth = 0.18f;
[Tooltip("#916 PD 「원거리 무기(예: 활)도 공격 사정거리가 원형 선으로 보이도록」 — 링 두께 = max(ringWidth, 반지름 × 이 값). 0 = 늘 ringWidth.\n" +
"근접(반지름 2 m 안팎)은 ringWidth 그대로 · 활(6 m)처럼 큰 원은 가는 선이 화면에서 1 픽셀 밑으로 떨어져 안 보이던 것을 굵게.")]
public float ringWidthPerMeter = 0f;
[Tooltip("원의 분할 수(많을수록 매끈하고 삼각형이 늘어난다). 모바일 예산 = 64.")]
[Range(12, 256)] public int segments = 64;
[Tooltip("바닥에서 띄우는 높이(m). Z-fighting 방지.")]
public float yOffset = 0.03f;
[Tooltip("렌더 큐(반투명 · 3000 이상). 지면 위·캐릭터 아래.")]
public int renderQueue = 3040;
[Tooltip("셰이더 후보(앞에서부터 Shader.Find).")]
public string[] shaderNames = new[] { "Universal Render Pipeline/Unlit", "Unlit/Transparent", "Sprites/Default" };
[Tooltip("색 프로퍼티 후보(앞에서부터 FindPropertyIndex).")]
public string[] colorProperties = new[] { "_BaseColor", "_Color", "_TintColor" };
[Header("③ 반지름 (SOT = 게임의 공격 판정 값 · 여기는 보정만)")]
[Tooltip("실측 사거리에 곱하는 배율. 1 = 판정과 같은 크기.")]
public float radiusScale = 1f;
[Tooltip("실측 사거리에 더하는 값(m). 0 = 판정과 같은 크기.")]
public float radiusBonus = 0f;
[System.Serializable]
public sealed class ClassRadius
{
[Tooltip("직업 ID(ClassConfig n_ClassID)")] public int[] classIds = new int[0];
[Tooltip("이 직업의 원 반지름(m) — 실제 피해 범위")] public float radius;
}
[Tooltip("#902 PD 「해머의 공격 범위를 표시하는 원형이 너무 짧게 보임 — 실제 범위만큼 넓혀줘」 — 여기 있는 직업은 원을 이 반지름으로 그린다(표시만).\n" +
"공격 시작 거리(f_AttackRange)는 그대로 — 해머는 #900 「적이 내려치는 위치에 닿을 때 공격 시작」 때문에 공격 시작 거리 < 실제 피해 범위.")]
public ClassRadius[] classRadius = new ClassRadius[0];
/// <summary>#902 그 PC 직업의 원 반지름 덮어쓰기(없으면 0).</summary>
public float RadiusFor(PCActor pc)
{
if (pc == null || classRadius == null) return 0f;
int cls = pc.Get_ID();
foreach (var c in classRadius) if (c != null && c.radius > 0f && c.classIds != null && System.Array.IndexOf(c.classIds, cls) >= 0) return c.radius;
return 0f;
}
[Tooltip("적 탐색 반경에 더하는 여유(m). 사거리 + 이 값 안의 적만 검사한다(전수 스캔 방지).")]
public float searchPad = 2f;
[Header("④ 시간")]
[Tooltip("사거리 안에 적이 없어진 뒤 원이 버티는 시간(s). PD: 3초.")]
public float graceSeconds = 3f;
[Tooltip("나타나는 시간(s).")]
public float fadeIn = 0.15f;
[Tooltip("사라지는 시간(s).")]
public float fadeOut = 0.4f;
[Tooltip("적 검사 주기(s). 위치 추종은 매 프레임이라 이 값과 무관하다.")]
public float pollInterval = 0.1f;
}
}