// WL925_Probe.cs — PD 지시 #925 시험(Play 중 · 섬) // Wave(seconds, pauseAt) : 대검 주력(1 칸) 발동 — 0.05 초마다 동작 · 상태 · 검기 앞머리 · 크기 · 명중 · 밀기 · 몹별 피격 시각 · 이동 거리 · pauseAt > 0 = 시전 뒤 그 초에 일시 정지 // Line(d0, step, count, side) : 몹 count 마리를 PC 정면 d0 m 부터 step m 간격(side = 좌우 엇갈림 m)으로 세운다(멈춤) // Body() : PC 몸 렌더러 켜짐 / 전체 // Storm(seconds) : 대검 각성(2 칸) 발동 — 끝난 시각 · 몸 켜짐 최솟값 using System.Collections.Generic; using System.Text; using UnityEngine; using WL.Combat.Weapon; public static class WL925_Probe { const string Key = "wl925log"; 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 List Mobs(PCActor pc, float within) { var l = new List(); foreach (var m in Object.FindObjectsByType(FindObjectsInactive.Exclude, FindObjectsSortMode.None)) if (m != null && !m.IsDead() && Vector3.Distance(m.Get_position(), pc.Get_position()) <= within) l.Add(m); l.Sort((a, b) => Vector3.Distance(a.Get_position(), pc.Get_position()).CompareTo(Vector3.Distance(b.Get_position(), pc.Get_position()))); return l; } public static object Line(float d0, float step, int count, float side) { var pc = MyValue.MyPC as PCActor; if (pc == null) return "PC 없음"; var f = pc.transform.forward; f.y = 0f; if (f.sqrMagnitude < 1e-4f) f = Vector3.forward; f.Normalize(); var r = Vector3.Cross(Vector3.up, f); var mobs = Mobs(pc, 40f); var sb = new StringBuilder(); for (int i = 0; i < mobs.Count && i < count; i++) { var want = pc.Get_position() + f * (d0 + step * i) + r * ((i % 2 == 0 ? 1f : -1f) * side * (i > 0 ? 1f : 0f)); UnityEngine.AI.NavMeshHit hit; if (UnityEngine.AI.NavMesh.SamplePosition(want, out hit, 1.5f, UnityEngine.AI.NavMesh.AllAreas)) want = hit.position; mobs[i].Stop(true); mobs[i].Set_Warp(want); sb.Append(mobs[i].name).Append(' ').Append(Vector3.Distance(pc.Get_position(), mobs[i].Get_position()).ToString("F1")).Append("m · "); } return "세움 " + Mathf.Min(count, mobs.Count) + " / " + mobs.Count + " · " + sb; } /// 콤보 단계 stage 가 시작되고 delay 초 뒤 — 궤적 교체 로그(WLImpactFx.LastSwing) · 켜진 WL_Impact_Swing_Ink 들의 PC 기준 위치 · 회전 · 크기 · 입자 수. public static object SwingInfo(int stage, float delay, float maxSeconds) { var pc = MyValue.MyPC as PCActor; if (pc == null) return "PC 없음"; var sb = Buf(); sb.Length = 0; float t0 = Time.time, at = -1f; int shown0 = WL.Combat.Impact.WLImpactFx.SwingShown; WL.Combat.Core.CombatHandler on = null; on = (in WL.Combat.Core.ComboStageEvent e) => { if (at < 0f && ReferenceEquals(e.actor, pc) && e.stage == stage) at = Time.time + delay; }; WL.Combat.Core.CombatEvents.ComboStage.Add(on); UnityEngine.Events.UnityAction act = null; act = () => { if ((at > 0f && Time.time >= at) || Time.time - t0 > maxSeconds) { Application.onBeforeRender -= act; WL.Combat.Core.CombatEvents.ComboStage.Remove(on); sb.Append(at > 0f ? "단계 " + stage + " +" + delay : "못 찾음").Append(" · 궤적 교체 +").Append(WL.Combat.Impact.WLImpactFx.SwingShown - shown0).Append(" · ").Append(WL.Combat.Impact.WLImpactFx.LastSwing).Append('\n'); var root = GameObject.Find("WL_ImpactFx"); if (root != null) foreach (Transform ch in root.transform) { if (!ch.gameObject.activeSelf) continue; int n = 0; foreach (var ps in ch.GetComponentsInChildren(false)) n += ps.particleCount; var rel = Quaternion.Inverse(pc.transform.rotation) * (ch.position - pc.Get_position()); sb.Append(" ").Append(ch.name).Append(" · PC 기준 ").Append(rel.ToString("F2")).Append(" · 회전 ").Append((Quaternion.Inverse(pc.transform.rotation) * ch.rotation).eulerAngles.ToString("F0")).Append(" · 크기 ").Append(ch.localScale.x.ToString("F2")).Append(" · 입자 ").Append(n).Append('\n'); } sb.Append(" 지면 ").Append(WL.Combat.Impact.WLImpactFx.LastGround).Append('\n'); } }; Application.onBeforeRender += act; return "단계 " + stage + " 대기"; } /// #927 대상 바라보기 — PC 를 더미 방향에서 awayDeg 만큼 돌려 놓고 대검 주력 발동 → 0.05 초마다 PC 정면과 더미 방향 사이 각 · 발사 순간 각. public static object Facing(float awayDeg, float seconds) { var pc = MyValue.MyPC as PCActor; var d = WL.IslandMob.WLTrailTest.Dummy; if (pc == null || d == null) return "PC/더미 없음"; var sb = Buf(); sb.Length = 0; float t0 = Time.time, tl = -1f; int f0 = WLGreatWave.Fired; float fireAng = -1f; var to0 = d.Get_position() - pc.Get_position(); to0.y = 0f; pc.transform.rotation = Quaternion.LookRotation(to0) * Quaternion.Euler(0f, awayDeg, 0f); string res = WLSkillHotkey.Fire(1); UnityEngine.Events.UnityAction act = null; act = () => { float t = Time.time - t0; var to = d.Get_position() - pc.Get_position(); to.y = 0f; var f = pc.transform.forward; f.y = 0f; float ang = Vector3.Angle(f, to); if (fireAng < 0f && WLGreatWave.Fired > f0) fireAng = ang; if (t - tl >= 0.1f || t > seconds) { tl = t; sb.AppendFormat("{0:F2} {1} 각 {2:F0}°", t, pc.Get_CurAnim(), ang).Append('\n'); } if (t > seconds) { Application.onBeforeRender -= act; sb.AppendFormat("끝 · 처음 돌려 둔 각 {0:F0}° · 발사 순간 각 {1:F0}° · {2}", awayDeg, fireAng, res).Append('\n'); } }; Application.onBeforeRender += act; return "바라보기 시험 · " + res; } public static object Body() { var pc = MyValue.MyPC as PCActor; if (pc == null) return "PC 없음"; int on = 0, all = 0; foreach (var r in pc.GetComponentsInChildren(true)) { all++; if (r.enabled && r.gameObject.activeInHierarchy) on++; } return "몸 " + on + "/" + all + " · 동작 " + pc.Get_CurAnim(); } /// 대검 주력 발동 뒤 moveAt 초부터 moveSec 초 동안 옆으로 이동 입력 — 끊김 · 발사 · 검기 · 애니메이터(속도 · 이벤트) · 검 빛 자식 수. public static object WaveMove(float moveAt, float moveSec, float seconds) { var pc = MyValue.MyPC as PCActor; if (pc == null) return "PC 없음"; var sb = Buf(); sb.Length = 0; float t0 = Time.time; bool moving = false; int f0 = WLGreatWave.Fired, s0 = WLGreatWave.Shots, a0 = WLGreatWave.Aborts, h0 = WLGreatWave.Hits; var right = pc.transform.right; right.y = 0f; right.Normalize(); string res = WLSkillHotkey.Fire(1); UnityEngine.Events.UnityAction act = null; act = () => { float t = Time.time - t0; if (t >= moveAt && t < moveAt + moveSec) { if (!moving) { moving = true; sb.AppendFormat("{0:F2} 이동 시작 · 동작 {1} · 발사 {2}", t, pc.Get_CurAnim(), WLGreatWave.Fired - f0).Append('\n'); } pc.Run_byJoystick(right); } else if (moving && t >= moveAt + moveSec) { moving = false; pc.Set_AutoBraking(true); sb.AppendFormat("{0:F2} 이동 끝 · 동작 {1}", t, pc.Get_CurAnim()).Append('\n'); } if (t > seconds) { Application.onBeforeRender -= act; int glow = 0; foreach (var tr in pc.GetComponentsInChildren(true)) if (tr.name == "[WL] Glow") glow++; var an = pc.m_animation; sb.AppendFormat("끝 · 발사 +{0} · 검기 +{1} · 끊김 +{2} · 명중 +{3} · 검기 {4:F2} 초 · 애니 속도 {5:F2} 이벤트 {6} · 검 빛 자식 {7} · 동작 {8} · {9} · {10}", WLGreatWave.Fired - f0, WLGreatWave.Shots - s0, WLGreatWave.Aborts - a0, WLGreatWave.Hits - h0, WLGreatWave.LastShotSeconds, an.speed, an.fireEvents, glow, pc.Get_CurAnim(), WLGreatWave.LastLog, res).Append('\n'); } }; Application.onBeforeRender += act; return "이동 끊기 시험 · " + res; } public static object Wave(float seconds, float pauseAt) { var pc = MyValue.MyPC as PCActor; if (pc == null) return "PC 없음"; var sb = Buf(); sb.Length = 0; float t0 = Time.time, tl = -1f; bool paused = false; int h0 = WLGreatWave.Hits, f0 = WLGreatWave.Fired, s0 = WLGreatWave.Shots, a0 = WLGreatWave.Aborts, k0 = WLGreatWave.Takeovers; WLGreatWave.MaxHitsOnOne = 0; WLGreatWave.PushDistance = 0f; var mobs = Mobs(pc, 15f); var start = new Dictionary(); foreach (var m in mobs) start[m] = m.Get_position(); var times = new Dictionary(); WL.Combat.Core.CombatHandler onDmg = null; onDmg = (in WL.Combat.Core.DamagedEvent e) => { if (!ReferenceEquals(e.attacker, pc) || e.victim == null) return; StringBuilder s; if (!times.TryGetValue(e.victim, out s)) { s = new StringBuilder(); times[e.victim] = s; } s.Append((Time.time - t0).ToString("F2")).Append(' '); }; WL.Combat.Core.CombatEvents.Damaged.Add(onDmg); float fireAt = -1f; Transform hips = null, toeL = null, toeR = null; foreach (var tr in pc.GetComponentsInChildren(true)) { if (tr.name == "Root_M") hips = tr; else if (tr.name == "ToesEnd_L") toeL = tr; else if (tr.name == "ToesEnd_R") toeR = tr; } WLGreatWave.MaxLower = 0f; WLGreatWave.LastHoldSeconds = 0f; string res = WLSkillHotkey.Fire(1); UnityEngine.Events.UnityAction act = null; act = () => { float t = Time.time - t0; var an = pc.m_animation; var si = an.GetCurrentAnimatorStateInfo(0); float gy = pc.Get_position().y; float hy = hips != null ? hips.position.y - gy : -9f, fy = toeL != null && toeR != null ? Mathf.Min(toeL.position.y, toeR.position.y) - gy : -9f; if (fireAt < 0f && WLGreatWave.Fired > f0) fireAt = t; if (!paused && pauseAt > 0f && t >= pauseAt) { paused = true; UnityEditor.EditorApplication.isPaused = true; sb.AppendFormat("■ 일시 정지 t {0:F2}", t).Append('\n'); } if (t - tl >= 0.05f || t > seconds) { tl = t; sb.AppendFormat("{0:F2} {1} {2} n={3:F2} sp {4:F2} · 엉덩이 {11:F2} 발끝 {12:F2} · 발사 {5} 검기 {6} · 앞머리 {7:F1} 크기 {8:F2} · 명중 {9} 밀기 {10:F1}m", t, pc.Get_CurAnim(), si.IsName("Attack4") ? "Attack4" : si.IsName("fatalblow") ? "fatalblow" : si.IsName("idle") ? "idle" : si.shortNameHash.ToString(), si.normalizedTime, an.speed, WLGreatWave.Fired - f0, WLGreatWave.Shots - s0, WLGreatWave.LastFront, WLGreatWave.LastScaleEnd, WLGreatWave.Hits - h0, WLGreatWave.PushDistance, hy, fy).Append('\n'); } if (t > seconds) { Application.onBeforeRender -= act; WL.Combat.Core.CombatEvents.Damaged.Remove(onDmg); sb.AppendFormat("끝 · 넘겨받음 +{0} · 발사 +{1} (t {2:F2}) · 검기 +{3} · 명중 +{4} · 한 적 최대 {5} · 끊김 +{6} · 검기 {7:F2} 초 · 내린 최대 {10:F2} m · 멈춤 {11:F2} 초 · 결과 {8} · {9}", WLGreatWave.Takeovers - k0, WLGreatWave.Fired - f0, fireAt, WLGreatWave.Shots - s0, WLGreatWave.Hits - h0, WLGreatWave.MaxHitsOnOne, WLGreatWave.Aborts - a0, WLGreatWave.LastShotSeconds, res, WLGreatWave.LastLog, WLGreatWave.MaxLower, WLGreatWave.LastHoldSeconds).Append('\n'); foreach (var m in mobs) { if (m == null) continue; StringBuilder s; times.TryGetValue(m, out s); var mv = m.Get_position() - start[m]; mv.y = 0f; var rel = m.Get_position() - pc.Get_position(); rel.y = 0f; sb.AppendFormat(" {0} · 피격 {1} · 이동 {2:F2} m · 지금 PC 앞 {3:F1} m{4}", m.name, s != null ? s.ToString() : "-", mv.magnitude, rel.magnitude, m.IsDead() ? " (죽음)" : "").Append('\n'); } } }; Application.onBeforeRender += act; return "대검 주력 관찰 " + seconds + " 초 · " + res; } }