// WL918_Probe.cs — PD 지시 #918 시험(Play 중 · 섬) // Real(dist) : 시험 더미가 아닌 가장 가까운 실제 몹을 PC 정면 dist m 에 세우고 대상으로 · 이름 · 크기 // Watch(seconds) : 그 몹의 크기(localScale.x) 최대 · 끝 · 시작 대비 · 밀린 거리 · 명중 수(검 각성) 기록 // Fire(slot) : 핫키 발동 // Log() using System.Text; using UnityEngine; public static class WL918_Probe { const string Key = "wl918log"; static StringBuilder Buf() { var sb = System.AppDomain.CurrentDomain.GetData(Key) as StringBuilder; if (sb == null) { sb = new StringBuilder(); System.AppDomain.CurrentDomain.SetData(Key, sb); } return sb; } public static object Log() { return Buf().ToString(); } static Actor s_mob; static int s_hits; static void OnHit(in WL.Combat.Core.HitConfirmedEvent e) { if (ReferenceEquals(e.victim, s_mob)) s_hits++; } public static object Real(float dist) { var pc = MyValue.MyPC as PCActor; if (pc == null) return "PC 없음"; Actor best = null; float bd = float.MaxValue; var dummy = WL.IslandMob.WLTrailTest.Dummy; foreach (var m in Object.FindObjectsByType(FindObjectsInactive.Exclude, FindObjectsSortMode.None)) { if (m == null || m.IsDead() || ReferenceEquals(m, dummy)) continue; float dd = Vector3.Distance(pc.Get_position(), m.Get_position()); if (dd < bd) { bd = dd; best = m; } } if (best == null && dummy != null && dummy.isActiveAndEnabled) best = dummy; // 섬에는 더미뿐 — 더미로 잰다(면역 여부 표시) if (best == null) return "몹 없음"; var f = pc.transform.forward; f.y = 0f; f.Normalize(); var want = pc.Get_position() + f * dist; UnityEngine.AI.NavMeshHit hit; if (UnityEngine.AI.NavMesh.SamplePosition(want, out hit, 1.5f, UnityEngine.AI.NavMesh.AllAreas)) want = hit.position; best.Stop(true); best.Set_Warp(want); pc.Change_Target(true, best); s_mob = best; return "실제 몹 " + best.name + " · 크기 " + best.transform.localScale.x.ToString("F3") + " · 넉백 면역 " + (best.Get_StatInfo() != null ? best.Get_StatInfo().Get_Stat(eStat.CC_Immunity).ToString() : "-"); } public static object Watch(float seconds) { var pc = MyValue.MyPC as PCActor; var d = s_mob; if (pc == null || d == null) return "대상 없음(Real 먼저)"; var sb = Buf(); sb.Length = 0; s_hits = 0; WL.Combat.Core.CombatEvents.HitConfirmed.Remove(OnHit); WL.Combat.Core.CombatEvents.HitConfirmed.Add(OnHit); float t0 = Time.time, s0 = d.transform.localScale.x, smax = s0; Vector3 p0 = d.Get_position(); int ks0 = WL.Combat.Reaction.WLSkillHitFeel.KnockbackSkipped, b0 = WL.Combat.Reaction.WLActorScale.Begins, e0 = WL.Combat.Reaction.WLActorScale.Ends; UnityEngine.Events.UnityAction act = null; act = () => { if (d == null) { Application.onBeforeRender -= act; return; } smax = Mathf.Max(smax, d.transform.localScale.x); if (Time.time - t0 > seconds) { Application.onBeforeRender -= act; WL.Combat.Core.CombatEvents.HitConfirmed.Remove(OnHit); var mv = d.Get_position() - p0; mv.y = 0f; sb.AppendFormat("몹 {0} · 크기 시작 {1:F3} · 최대 {2:F3} · 끝 {3:F3}(시작 대비 {4:F3}) · 밀린 거리 {5:F2} m · 명중 {6} · 넉백 생략 +{7} · 크기 효과 시작/끝 +{8}/+{9}", d.name, s0, smax, d.transform.localScale.x, d.transform.localScale.x / Mathf.Max(1e-4f, s0), mv.magnitude, s_hits, WL.Combat.Reaction.WLSkillHitFeel.KnockbackSkipped - ks0, WL.Combat.Reaction.WLActorScale.Begins - b0, WL.Combat.Reaction.WLActorScale.Ends - e0).Append('\n'); } }; Application.onBeforeRender += act; return "관찰 " + seconds + " 초"; } public static object Fire(int slot) { return WL.Combat.Weapon.WLSkillHotkey.Fire(slot); } /// 이름이 prefix 로 시작하는 투사체마다 생성(관통 · 겉모습) · 사라진 순간(마지막 위치 → 더미 몸 중심 거리)을 seconds 초 동안 기록 · 몸 중심 도착 · 명중 이펙트 수. public static object Proj(string prefix, float seconds) { var pc = MyValue.MyPC as PCActor; if (pc == null) return "PC 없음"; var sb = Buf(); sb.Length = 0; var live = new System.Collections.Generic.Dictionary(); float t0 = Time.time; int a0 = WL.Combat.Impact.WLImpactFx.Arrivals, h0 = WL.Combat.Weapon.WLProjectileHitFx.Shown, born = 0, gone = 0; UnityEngine.Events.UnityAction act = null; act = () => { float t = Time.time - t0; var d = WL.IslandMob.WLTrailTest.Dummy; foreach (var pb in Object.FindObjectsByType(FindObjectsInactive.Exclude, FindObjectsSortMode.None)) if (pb != null && pb.name.StartsWith(prefix) && !live.ContainsKey(pb)) { live[pb] = pb.transform.position; born++; sb.AppendFormat("{0:F2} 생성 {1} · 관통 {2} · 겉모습 {3}", t, pb.name, pb.m_Pierce, pb.transform.Find("~WL_Visual") != null).Append('\n'); } var off = new System.Collections.Generic.List(); foreach (var kv in live) if (kv.Key == null || !kv.Key.gameObject.activeInHierarchy) off.Add(kv.Key); foreach (var pb in off) { var lp = live[pb]; live.Remove(pb); gone++; sb.AppendFormat("{0:F2} 사라짐 · 마지막 위치 → 더미 몸 중심 {1} m", t, d != null ? Vector3.Distance(lp, d.Get_Center_position()).ToString("F2") : "-").Append('\n'); } var keys = new System.Collections.Generic.List(live.Keys); foreach (var pb in keys) live[pb] = pb.transform.position; if (t > seconds) { Application.onBeforeRender -= act; sb.AppendFormat("끝 · 생성 {0} · 사라짐 {1} · 몸 중심 도착 +{2} · 명중 이펙트 +{3} · {4}", born, gone, WL.Combat.Impact.WLImpactFx.Arrivals - a0, WL.Combat.Weapon.WLProjectileHitFx.Shown - h0, WL.Combat.Impact.WLImpactFx.LastLog).Append('\n'); } }; Application.onBeforeRender += act; return "투사체 관찰 " + prefix + " " + seconds + " 초"; } }