83 lines
4.7 KiB
C#
83 lines
4.7 KiB
C#
// ─────────────────────────────────────────────────────────────────────────────
|
|
// WLFlyingHitbox.cs — 떠 있는 몹의 피격 판정을 지면까지 늘린다 (#919 · 2026-10-18)
|
|
//
|
|
// PD 원문: 「비행 중인 몬스터도 보이는 것과 별개로 지상에서 공격이 가능하도록 해줘.」
|
|
// ■ 실측 — 원본 투사체는 OnTriggerEnter → 맞은 콜라이더의 TryGetComponent<Actor> 로 맞힌다(= 몹 루트 BoxCollider).
|
|
// 몹 프리팹 303 개 중 그 판정 상자 바닥이 발 위로 뜬 것 4 개(RPG_Bat 0.21 m · Firetree_A/B/C 0.32 m).
|
|
// 섬의 박쥐(배율 0.57) 판정 = 지면 위 0.32~1.17 m — 지면 쪽 판정(검 각성 돌진 베기 꼭대기 0.51 m)과 0.19 m 만 겹쳤다.
|
|
// ■ 방법 — 몹 등장(CombatEvents.Spawned · MobActor.On_Regen 원본 훅) 때 루트 BoxCollider 바닥이 발보다 minGap 넘게 높으면
|
|
// 바닥만 발(+ groundPad)까지 내린다(꼭대기 · 가로 · 세로 그대로). 원래 크기를 기억해 다시 등장해도 누적되지 않는다.
|
|
// 보이는 모습 · 몸 중심(Get_Center_position = 스킨 bounds · WLImpactFx.BodyCenter = 발~머리) · 몸 반지름(가로)은 그대로.
|
|
// ■ 값 = Resources/WL/WLFlyingHitbox.json (C45) · 끄기 = enabled 0
|
|
// 🔴 원본 수정 0줄 · Debug.LogError 금지.
|
|
// ─────────────────────────────────────────────────────────────────────────────
|
|
using UnityEngine;
|
|
using WL.Combat.Core;
|
|
|
|
namespace WL.Combat.Reaction
|
|
{
|
|
[System.Serializable]
|
|
public class WLFlyingHitboxJson
|
|
{
|
|
public int enabled = 1;
|
|
public float minGap = 0.1f; // 판정 바닥이 발보다 이만큼(m) 넘게 높으면 「떠 있음」
|
|
public float groundPad; // 늘린 바닥 = 발 + groundPad(m · 음수 = 땅 아래까지)
|
|
public string note = "";
|
|
}
|
|
|
|
/// <summary>늘리기 전 판정 상자(로컬) — 다시 등장할 때 이 값에서 다시 계산한다.</summary>
|
|
public sealed class WLFlyingHitboxBase : MonoBehaviour { public Vector3 center, size; }
|
|
|
|
public static class WLFlyingHitbox
|
|
{
|
|
public const string ResourcesPath = "WL/WLFlyingHitbox";
|
|
public static int Extended;
|
|
public static string LastLog = "";
|
|
static WLFlyingHitboxJson s_cfg;
|
|
|
|
static WLFlyingHitboxJson Cfg
|
|
{
|
|
get
|
|
{
|
|
if (s_cfg != null) return s_cfg;
|
|
s_cfg = new WLFlyingHitboxJson();
|
|
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; }
|
|
return s_cfg;
|
|
}
|
|
}
|
|
|
|
[RuntimeInitializeOnLoadMethod(RuntimeInitializeLoadType.AfterAssembliesLoaded)]
|
|
static void Register()
|
|
{
|
|
s_cfg = null; Extended = 0;
|
|
CombatEvents.Spawned.Remove(OnSpawned);
|
|
CombatEvents.Spawned.Add(OnSpawned);
|
|
}
|
|
|
|
static void OnSpawned(in SpawnedEvent e) { if (e.actor is MobActor) Apply(e.actor); }
|
|
|
|
/// <summary>판정 상자 바닥이 떠 있으면 발까지 내린다 — 늘렸으면 true.</summary>
|
|
public static bool Apply(Actor a)
|
|
{
|
|
var c = Cfg;
|
|
if (c.enabled == 0 || a == null) return false;
|
|
var box = a.GetComponent<BoxCollider>();
|
|
if (box == null) return false;
|
|
var bs = a.GetComponent<WLFlyingHitboxBase>();
|
|
if (bs == null) { bs = a.gameObject.AddComponent<WLFlyingHitboxBase>(); bs.center = box.center; bs.size = box.size; }
|
|
float sy = Mathf.Abs(a.transform.lossyScale.y);
|
|
if (sy < 1e-4f) return false;
|
|
float lo = bs.center.y - bs.size.y * 0.5f, hi = bs.center.y + bs.size.y * 0.5f; // 루트(= 발 · Actor.Get_position) 로컬
|
|
if (lo * sy <= c.minGap) { box.center = bs.center; box.size = bs.size; return false; }
|
|
float newLo = c.groundPad / sy;
|
|
box.size = new Vector3(bs.size.x, hi - newLo, bs.size.z);
|
|
box.center = new Vector3(bs.center.x, (hi + newLo) * 0.5f, bs.center.z);
|
|
Extended++;
|
|
LastLog = a.name + " 판정 바닥 " + (lo * sy).ToString("F2") + " m → " + c.groundPad.ToString("F2") + " m · 꼭대기 " + (hi * sy).ToString("F2") + " m";
|
|
return true;
|
|
}
|
|
}
|
|
}
|