Project_WL/AgentScripts/WL916_Probe.cs

232 lines
16 KiB
C#

// WL916_Probe.cs — PD 지시 #916 시험(Play 중 · 섬)
// Bow() : 직업 · 애니메이터 컨트롤러 · 상태(이름 · 클립 · 속도 · 길이 · 이벤트) — 활 관련 상태만
// Ring() : 사거리 원 상태(반지름 · 표시 · 공격 거리)
// Rapid(seconds) : 주력(Q) 발동 → 프레임마다 상태 · 클립 · 속도 · PC 이동 · 화살 수 · 과녁 위치(대상 중심 · 카메라 쪽 거리) · 크기
// Basic(seconds) : 스킬 없이 기본 공격 동안 PC 이동(뒤로 밀림 여부)
// Log()
using System.Text;
using UnityEngine;
public static class WL916_Probe
{
const string Key = "wl916log";
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 Target(PCActor pc, float dist)
{
Actor d = WL.IslandMob.WLTrailTest.Dummy;
if (d == null || !d.isActiveAndEnabled)
{
float bd = float.MaxValue;
foreach (var m in Object.FindObjectsByType<MobActor>(FindObjectsInactive.Exclude, FindObjectsSortMode.None))
{ if (m == null || m.IsDead()) continue; float dd = Vector3.Distance(pc.Get_position(), m.Get_position()); if (dd < bd) { bd = dd; d = m; } }
}
if (d != null && dist > 0f)
{
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;
d.Stop(true); d.Set_Warp(want); pc.Change_Target(true, d);
}
return d;
}
public static object Bow()
{
var pc = MyValue.MyPC as PCActor; if (pc == null || pc.m_animation == null) return "PC 없음";
var sb = new StringBuilder();
var fId = typeof(Actor).GetField("m_ID", System.Reflection.BindingFlags.Instance | System.Reflection.BindingFlags.NonPublic | System.Reflection.BindingFlags.Public);
sb.AppendLine("직업 " + (fId != null ? fId.GetValue(pc) : "?") + " · 공격 거리 " + pc.WL_AttackRange.ToString("F2") + " · 컨트롤러 " + pc.m_animation.runtimeAnimatorController.name);
var ac = pc.m_animation.runtimeAnimatorController as UnityEditor.Animations.AnimatorController;
if (ac == null)
{
var ov = pc.m_animation.runtimeAnimatorController as AnimatorOverrideController;
if (ov != null) { ac = ov.runtimeAnimatorController as UnityEditor.Animations.AnimatorController; sb.AppendLine("오버라이드 → " + (ac != null ? ac.name : "-")); }
}
if (ac == null) return sb.Append("AnimatorController 아님").ToString();
foreach (var cs in ac.layers[0].stateMachine.states)
{
var s = cs.state; var clip = s.motion as AnimationClip;
string n = s.name.ToLower();
if (!(n.Contains("attack") || n.Contains("skill") || n.Contains("shot") || n.Contains("idle"))) continue;
sb.Append(" ").Append(s.name).Append(" · ").Append(clip != null ? clip.name + " " + clip.length.ToString("F2") + "s" : (s.motion != null ? s.motion.name : "-")).Append(" · 속도 ").Append(s.speed.ToString("F2"));
if (clip != null) foreach (var ev in clip.events) sb.Append(" · ").Append(ev.functionName).Append("@").Append(ev.time.ToString("F2"));
foreach (var tr in s.transitions) sb.Append(" → ").Append(tr.destinationState != null ? tr.destinationState.name : "-").Append(tr.hasExitTime ? "(" + tr.exitTime.ToString("F2") + ")" : "");
sb.AppendLine();
}
return sb.ToString();
}
public static object Ring()
{
var pc = MyValue.MyPC as PCActor; if (pc == null) return "PC 없음";
var s = WL.Combat.RangeRing.WLRangeRingSettings.Instance;
return "원 반지름 " + WL.Combat.RangeRing.WLRangeRing.LastRadius.ToString("F2") + " · 표시 " + WL.Combat.RangeRing.WLRangeRing.Visible + " · 알파 " + WL.Combat.RangeRing.WLRangeRing.Alpha.ToString("F2")
+ " · 기준 " + WL.Combat.RangeRing.WLRangeRing.LastBaseStop.ToString("F2") + " · 공격 거리 " + pc.WL_AttackRange.ToString("F2") + " · 직업 반지름 " + (s != null ? s.RadiusFor(pc).ToString("F2") : "-")
+ " · 선만 " + (s != null && s.ringOnly) + " · 마지막 사거리 안 " + WL.Combat.RangeRing.WLRangeRing.LastInRangeTime.ToString("F1") + " · 지금 " + Time.time.ToString("F1") + " · " + WL.Combat.RangeRing.WLRangeRing.LastInfo;
}
public static object Rapid(float dist, float seconds) { return RapidP(dist, seconds, 0f); }
public static object RapidP(float dist, float seconds, float pauseAt)
{
var pc = MyValue.MyPC as PCActor; if (pc == null) return "PC 없음";
var d = Target(pc, dist); if (d == null) return "몹 없음";
var sb = Buf(); sb.Length = 0;
float t0 = Time.time; Vector3 p0 = pc.Get_position(); string last = ""; int arrows0 = Count(); bool paused = false;
UnityEngine.Events.UnityAction act = null;
act = () =>
{
if (pc == null || pc.m_animation == null) { Application.onBeforeRender -= act; return; }
float t = Time.time - t0; var a = pc.m_animation; var si = a.GetCurrentAnimatorStateInfo(0);
var ci = a.GetCurrentAnimatorClipInfo(0); string clip = ci.Length > 0 && ci[0].clip != null ? ci[0].clip.name : "-";
string tgt = "-";
var tg = GameObject.Find("Effect_BulletTarget(Clone)");
if (tg != null && tg.activeInHierarchy && d != null)
{
var cam = Camera.main; var mid = d.Get_Center_position();
float toCam = cam != null ? Vector3.Dot(tg.transform.position - mid, (cam.transform.position - mid).normalized) : 0f;
tgt = "과녁 중심차 " + Vector3.Distance(tg.transform.position, mid).ToString("F2") + " 카메라쪽 " + toCam.ToString("F2") + " 배율 " + tg.transform.lossyScale.x.ToString("F2");
}
string key = clip + " " + pc.Get_CurAnim() + " sp" + a.speed.ToString("F1") + " 화살 +" + (Count() - arrows0);
if (key != last || Mathf.Repeat(t, 0.25f) < Time.deltaTime)
{
last = key;
var mv = pc.Get_position() - p0; mv.y = 0f; var fw = pc.transform.forward; fw.y = 0f; fw.Normalize();
sb.AppendFormat("{0:F2} {1} n={2:F2} · 이동 {3:F2} m(앞 {4:F2}) · {5}", t, key, si.normalizedTime, mv.magnitude, Vector3.Dot(mv, fw), tgt).Append('\n');
}
if (!paused && pauseAt > 0f && t >= pauseAt)
{
paused = true; UnityEditor.EditorApplication.isPaused = true;
var cam = Camera.main; var vp = cam != null && d != null ? cam.WorldToViewportPoint(d.Get_Center_position()) : Vector3.zero;
bool vis = false; if (d != null) foreach (var r in d.GetComponentsInChildren<Renderer>(false)) if (r.enabled && r.isVisible) { vis = true; break; }
int glowOn = 0; foreach (var r in Object.FindObjectsByType<MeshRenderer>(FindObjectsInactive.Exclude, FindObjectsSortMode.None)) if (r.name == "[WL] Glow" && r.enabled) glowOn++;
sb.AppendFormat("■ 일시 정지 · 몹 {0} 보임 {1} · 몹 화면 {2:F3},{3:F3} · PC 화면 {4:F3},{5:F3} · 활 빛 {6} · 모으기 {7} · ", d != null ? d.name : "-", vis, vp.x, 1f - vp.y,
cam != null ? cam.WorldToViewportPoint(pc.Get_Center_position()).x : 0f, cam != null ? 1f - cam.WorldToViewportPoint(pc.Get_Center_position()).y : 0f, glowOn,
GameObject.Find("WL_Fx_BowCharge(Clone)") != null).Append(MarkBounds()).Append('\n');
}
if (t > seconds) { Application.onBeforeRender -= act; sb.AppendFormat("끝 · 몹 크기(몸 반지름) {0:F2} · 몹 키 {1:F2}", WL.Combat.WLCombatMotionSettings.BodyRadius(d), d.Get_Top_postion().y - d.Get_position().y).Append('\n'); }
};
Application.onBeforeRender += act;
return "Q: " + WL.Combat.Weapon.WLSkillHotkey.Fire(1);
}
static string MarkBounds()
{
GameObject go = null;
foreach (var t in Object.FindObjectsByType<TurnOff_GO>(FindObjectsInactive.Exclude, FindObjectsSortMode.None)) if (t != null && t.name.StartsWith("Effect_BulletTarget")) { go = t.gameObject; break; }
if (go == null) return "과녁 없음";
Bounds b = new Bounds(); bool has = false; var sb = new StringBuilder();
foreach (var r in go.GetComponentsInChildren<ParticleSystemRenderer>(false))
{
var ps = r.GetComponent<ParticleSystem>(); if (ps == null || ps.particleCount == 0) continue;
if (!has) { b = r.bounds; has = true; } else b.Encapsulate(r.bounds);
sb.Append(ps.name).Append(" ").Append(r.bounds.size.x.ToString("F2")).Append(" ");
}
return "과녁 " + go.name + " 배율 " + go.transform.lossyScale.x.ToString("F2") + " · 전체 경계 " + (has ? b.size.ToString("F2") : "-") + " · " + sb;
}
/// <summary>과녁(Effect_BulletTarget) 파티클이 살아 있는 동안 렌더러 경계 크기 · 배율 · 파티클 크기 모드.</summary>
public static object Mark()
{
var go = GameObject.Find("Effect_BulletTarget(Clone)");
if (go == null || !go.activeInHierarchy) return "과녁 없음";
var sb = new StringBuilder(); Bounds b = new Bounds(); bool has = false;
foreach (var r in go.GetComponentsInChildren<ParticleSystemRenderer>(false))
{
var ps = r.GetComponent<ParticleSystem>(); if (ps == null || ps.particleCount == 0) continue;
if (!has) { b = r.bounds; has = true; } else b.Encapsulate(r.bounds);
sb.Append(ps.name).Append(" n ").Append(ps.particleCount).Append(" 경계 ").Append(r.bounds.size.ToString("F2")).Append(" 모드 ").Append(ps.main.scalingMode).Append(" · ");
}
return "과녁 배율 " + go.transform.lossyScale.x.ToString("F2") + " · 전체 경계 " + (has ? b.size.ToString("F2") : "-") + " · " + sb;
}
static int s_arrows;
static int Count()
{
int n = 0;
foreach (var pb in Object.FindObjectsByType<ProjectileBase>(FindObjectsInactive.Exclude, FindObjectsSortMode.None))
if (pb != null && pb.name.Contains("Arrow")) n++;
if (n > s_arrows) s_arrows = n;
return n;
}
/// <summary>#916 검 각성 걸음 전진 — 각성(E) 뒤 pushAt 초에 몹을 PC 반대쪽으로 pushDist m 옮겨(크게 밀린 상황) 프레임마다 PC-몹 거리 · 걸음 수 · 명중.</summary>
public static object SwordFollow(float pushAt, float pushDist, float seconds)
{
var pc = MyValue.MyPC as PCActor; if (pc == null) return "PC 없음";
var d = Target(pc, 1.5f); if (d == null) return "몹 없음";
var sb = Buf(); sb.Length = 0;
float t0 = Time.time; bool pushed = false; int st0 = WL.Combat.Weapon.WLSlashFlurry.Steps, w0 = WL.Combat.Weapon.WLSlashFlurry.Windows; string last = "";
UnityEngine.Events.UnityAction act = null;
act = () =>
{
if (pc == null || d == null) { Application.onBeforeRender -= act; return; }
float t = Time.time - t0;
if (!pushed && t >= pushAt)
{
pushed = true; var away = d.Get_position() - pc.Get_position(); away.y = 0f; away.Normalize();
var np = d.Get_position() + away * pushDist; var ag = d.Get_Agent();
if (ag != null && ag.isActiveAndEnabled && ag.isOnNavMesh) ag.Warp(np); d.transform.position = np;
sb.AppendFormat("{0:F2} ▶ 몹을 {1:F1} m 뒤로", t, pushDist).Append('\n');
}
var ci = pc.m_animation.GetCurrentAnimatorClipInfo(0); string clip = ci.Length > 0 && ci[0].clip != null ? ci[0].clip.name : "-";
string key = clip + " 걸음+" + (WL.Combat.Weapon.WLSlashFlurry.Steps - st0) + " 창+" + (WL.Combat.Weapon.WLSlashFlurry.Windows - w0);
if (key != last || Mathf.Repeat(t, 0.1f) < Time.deltaTime)
{
last = key; var dv = d.Get_position() - pc.Get_position(); dv.y = 0f;
sb.AppendFormat("{0:F2} {1} {2} · PC-몹 {3:F2} m", t, key, pc.Get_CurAnim(), dv.magnitude).Append('\n');
}
if (t > seconds) { Application.onBeforeRender -= act; sb.AppendFormat("끝 · 걸음 +{0} · 전진 누적 {1:F2} m", WL.Combat.Weapon.WLSlashFlurry.Steps - st0, WL.Combat.Weapon.WLSlashFlurry.StepDistance).Append('\n'); }
};
Application.onBeforeRender += act;
return "E: " + WL.Combat.Weapon.WLSkillHotkey.Fire(2);
}
/// <summary>slot 스킬 발동 뒤 seconds 동안 PC 수평 이동(대상 반대쪽 = 뒤로) 최대 · 끝 거리.</summary>
public static object SlotMove(int slot, float dist, float seconds)
{
var pc = MyValue.MyPC as PCActor; if (pc == null) return "PC 없음";
var d = Target(pc, dist);
var sb = Buf(); sb.Length = 0;
float t0 = Time.time; Vector3 p0 = pc.Get_position(); var fw = pc.transform.forward; fw.y = 0f; fw.Normalize(); float maxBack = 0f;
UnityEngine.Events.UnityAction act = null;
act = () =>
{
if (pc == null) { Application.onBeforeRender -= act; return; }
var mv = pc.Get_position() - p0; mv.y = 0f; float back = -Vector3.Dot(mv, fw); if (back > maxBack) maxBack = back;
if (Time.time - t0 > seconds) { Application.onBeforeRender -= act; sb.AppendFormat("끝 · 뒤로 최대 {0:F2} m · 끝 이동 {1:F2} m · 넉백 생략 {2}", maxBack, mv.magnitude, WL.Combat.Weapon.WLRapidShot.RecoilSkipped).Append('\n'); }
};
Application.onBeforeRender += act;
return "slot" + slot + ": " + WL.Combat.Weapon.WLSkillHotkey.Fire(slot);
}
public static object Basic(float dist, float seconds)
{
var pc = MyValue.MyPC as PCActor; if (pc == null) return "PC 없음";
var d = Target(pc, dist); if (d == null) return "몹 없음";
var sb = Buf(); sb.Length = 0;
float t0 = Time.time; Vector3 p0 = pc.Get_position(); string last = ""; Vector3 pPrev = p0; float back = 0f;
UnityEngine.Events.UnityAction act = null;
act = () =>
{
if (pc == null || pc.m_animation == null) { Application.onBeforeRender -= act; return; }
float t = Time.time - t0; var a = pc.m_animation;
var ci = a.GetCurrentAnimatorClipInfo(0); string clip = ci.Length > 0 && ci[0].clip != null ? ci[0].clip.name : "-";
var to = d != null ? d.Get_position() - pc.Get_position() : pc.transform.forward; to.y = 0f; to.Normalize();
var step = pc.Get_position() - pPrev; step.y = 0f; float away = -Vector3.Dot(step, to); if (away > 0f && pc.Get_CurAnim() == eAnim.Attack) back += away; pPrev = pc.Get_position();
string key = clip + " " + pc.Get_CurAnim();
if (key != last) { last = key; sb.AppendFormat("{0:F2} {1} · 몹 거리 {2:F2} · 공격 중 뒤로 누적 {3:F2} m", t, key, d != null ? Vector3.Distance(pc.Get_position(), d.Get_position()) : -1f, back).Append('\n'); }
if (t > seconds) { Application.onBeforeRender -= act; sb.AppendFormat("끝 · 공격 중 뒤로 누적 {0:F2} m", back).Append('\n'); }
};
Application.onBeforeRender += act;
return "기본 공격 관찰 " + seconds + " 초";
}
}