Project_WL/AgentScripts/WL919_Probe.cs

222 lines
17 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.

// WL919_Probe.cs — PD 지시 #919 시험(Play 중 · 섬)
// Bat() : 시험 더미(박쥐) · 섬의 몹 — 콜라이더(종류 · 중심 · 크기 · 트리거 · 레이어 · 월드 높이) · 렌더러 높이 · 위치 함수 높이
// Bow() : 활 노드(FindBow 규칙) · 무기 소켓 · 활 그림 중심 · 크기 · PC 키
using System.Text;
using UnityEngine;
public static class WL919_Probe
{
static string V(Vector3 v) { return v.ToString("F2"); }
public static object Bat()
{
var sb = new StringBuilder();
foreach (var m in Object.FindObjectsByType<MobActor>(FindObjectsInactive.Exclude, FindObjectsSortMode.None))
{
if (m == null) continue;
float gy = m.Get_position().y;
sb.Append(m.name).Append(" · 위치 y ").Append(gy.ToString("F2")).Append(" · 중심 +").Append((m.Get_Center_position().y - gy).ToString("F2")).Append(" · 머리 +").Append((m.Get_Top_postion().y - gy).ToString("F2"))
.Append(" · 배율 ").Append(m.transform.localScale.x.ToString("F3")).Append(" · 레이어 ").Append(LayerMask.LayerToName(m.gameObject.layer)).AppendLine();
var ag = m.GetComponent<UnityEngine.AI.NavMeshAgent>();
if (ag != null) sb.Append(" agent baseOffset ").Append(ag.baseOffset.ToString("F2")).Append(" 높이 ").Append(ag.height.ToString("F2")).Append(" 반지름 ").Append(ag.radius.ToString("F2")).AppendLine();
foreach (var c in m.GetComponentsInChildren<Collider>(true))
{
sb.Append(" C ").Append(c.GetType().Name).Append(" ").Append(c.transform == m.transform ? "(루트)" : c.transform.name).Append(" 켜짐 ").Append(c.enabled && c.gameObject.activeInHierarchy).Append(" 트리거 ").Append(c.isTrigger)
.Append(" 레이어 ").Append(LayerMask.LayerToName(c.gameObject.layer)).Append(" 월드 y ").Append((c.bounds.min.y - gy).ToString("F2")).Append("~").Append((c.bounds.max.y - gy).ToString("F2")).Append(" 폭 ").Append(c.bounds.size.x.ToString("F2"));
var cc = c as CapsuleCollider; if (cc != null) sb.Append(" 캡슐 중심 ").Append(V(cc.center)).Append(" r ").Append(cc.radius.ToString("F2")).Append(" h ").Append(cc.height.ToString("F2")).Append(" 축 ").Append(cc.direction);
var bc = c as BoxCollider; if (bc != null) sb.Append(" 상자 중심 ").Append(V(bc.center)).Append(" 크기 ").Append(V(bc.size));
var sc = c as SphereCollider; if (sc != null) sb.Append(" 구 중심 ").Append(V(sc.center)).Append(" r ").Append(sc.radius.ToString("F2"));
sb.AppendLine();
}
Bounds rb = new Bounds(); bool has = false;
foreach (var r in m.GetComponentsInChildren<Renderer>(false)) { if (!r.enabled || r is ParticleSystemRenderer) continue; if (!has) { rb = r.bounds; has = true; } else rb.Encapsulate(r.bounds); }
if (has) sb.Append(" 그림 y ").Append((rb.min.y - gy).ToString("F2")).Append("~").Append((rb.max.y - gy).ToString("F2")).AppendLine();
}
return sb.Length > 0 ? sb.ToString() : "몹 없음";
}
// ── 판정 상자 높이 · 스킬별 명중 ──
static readonly System.Collections.Generic.Dictionary<string, int> s_hit = new System.Collections.Generic.Dictionary<string, int>();
static void OnHit(in WL.Combat.Core.HitConfirmedEvent e)
{
if (!(e.victim is MobActor)) return;
var pd = e.projectile; string k = pd != null && pd.m_SkillListTableData != null ? pd.m_SkillListTableData.e_Skill.ToString() : "기본/기타";
int n; s_hit.TryGetValue(k, out n); s_hit[k] = n + 1;
}
const string Key = "wl919log";
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(); }
/// <summary>seconds 동안 PC 가 낸 판정 투사체(처음 켜진 순간의 콜라이더 높이 · PC 발 기준) · 스킬별 몹 명중 수 · 핫키 slot(0 = 안 누름).</summary>
public static object Hits(float seconds, int slot)
{
var pc = MyValue.MyPC as PCActor; if (pc == null) return "PC 없음";
var sb = Buf(); sb.Length = 0; s_hit.Clear();
WL.Combat.Core.CombatEvents.HitConfirmed.Remove(OnHit); WL.Combat.Core.CombatEvents.HitConfirmed.Add(OnHit);
var seen = new System.Collections.Generic.HashSet<int>(); float t0 = Time.time;
UnityEngine.Events.UnityAction act = null;
act = () =>
{
float t = Time.time - t0; float gy = pc.Get_position().y;
foreach (var pb in Object.FindObjectsByType<ProjectileBase>(FindObjectsInactive.Exclude, FindObjectsSortMode.None))
{
if (pb == null) continue; var pd = pb.Get_ProjectTileData(); if (pd == null || !ReferenceEquals(pd.shooter, pc)) continue;
var cols = pb.GetComponentsInChildren<Collider>(false); if (cols.Length == 0) continue;
bool on = false; Bounds b = new Bounds();
foreach (var c in cols) { if (!c.enabled) continue; if (!on) { b = c.bounds; on = true; } else b.Encapsulate(c.bounds); }
if (!on) continue;
if (!seen.Add(pb.GetInstanceID())) continue;
sb.AppendFormat("{0:F2} 판정 {1} · y {2:F2}~{3:F2} · 폭 {4:F2}×{5:F2}", t, pb.name.Replace("(Clone)", ""), b.min.y - gy, b.max.y - gy, b.size.x, b.size.z).Append('\n');
}
if (t > seconds)
{
Application.onBeforeRender -= act; WL.Combat.Core.CombatEvents.HitConfirmed.Remove(OnHit);
sb.Append("끝 · 명중");
foreach (var kv in s_hit) sb.Append(' ').Append(kv.Key).Append(' ').Append(kv.Value);
sb.Append('\n');
}
};
Application.onBeforeRender += act;
return slot > 0 ? "slot" + slot + ": " + WL.Combat.Weapon.WLSkillHotkey.Fire(slot) : "관찰 " + seconds + " 초";
}
/// <summary>3타 모으기(~WL_BowCharge) — 위치 · 부모 · 파티클별 공간 · 모양 위치 · 살아 있는 입자 중심(월드) vs 활 그림(렌더러 bounds) 중심 · 화면 좌표.</summary>
public static object Charge()
{
var pc = MyValue.MyPC as PCActor; if (pc == null) return "PC 없음";
var sb = new StringBuilder(); var cam = Camera.main;
Bounds bow = new Bounds(); bool hasBow = false;
if (pc.tfs_weapon != null) foreach (var s in pc.tfs_weapon) if (s != null && s.name == "w_archer_l" && s.gameObject.activeInHierarchy)
foreach (var r in s.GetComponentsInChildren<MeshRenderer>(false)) { if (!r.enabled || r.name == "[WL] Glow") continue; if (!hasBow) { bow = r.bounds; hasBow = true; } else bow.Encapsulate(r.bounds); }
sb.Append("활 그림 중심 ").Append(hasBow ? V(bow.center - pc.Get_position()) : "-").Append(" · 화면 ").Append(hasBow && cam != null ? cam.WorldToViewportPoint(bow.center).ToString("F3") : "-").AppendLine();
foreach (var t in Object.FindObjectsByType<Transform>(FindObjectsInactive.Exclude, FindObjectsSortMode.None))
{
if (t.name != "~WL_BowCharge") continue;
sb.Append("모으기 원점 ").Append(V(t.position - pc.Get_position())).Append(" · 부모 ").Append(t.parent != null ? t.parent.name : "-").Append(" · lossy ").Append(t.lossyScale.x.ToString("F3")).Append(" · 활 중심까지 ").Append(hasBow ? Vector3.Distance(t.position, bow.center).ToString("F2") : "-").AppendLine();
foreach (var ps in t.GetComponentsInChildren<ParticleSystem>(true))
{
var m = ps.main; int n = ps.particleCount; Vector3 sum = Vector3.zero;
var arr = new ParticleSystem.Particle[Mathf.Max(1, n)]; n = ps.GetParticles(arr);
for (int i = 0; i < n; i++) sum += m.simulationSpace == ParticleSystemSimulationSpace.World ? arr[i].position : ps.transform.TransformPoint(arr[i].position);
var c = n > 0 ? sum / n : ps.transform.position;
sb.Append(" ").Append(ps.name).Append(" ").Append(ps.gameObject.activeInHierarchy ? "" : "(꺼짐) ").Append(m.simulationSpace).Append(" · 크기모드 ").Append(m.scalingMode).Append(" · 입자 ").Append(n)
.Append(" · 입자 중심 → 활 중심 ").Append(hasBow && n > 0 ? Vector3.Distance(c, bow.center).ToString("F2") : "-").Append(" m · 원점 → 활 ").Append(hasBow ? Vector3.Distance(ps.transform.position, bow.center).ToString("F2") : "-")
.Append(" · 모양 ").Append(ps.shape.enabled ? ps.shape.shapeType + " 위치 " + ps.shape.position.ToString("F2") + " r " + ps.shape.radius.ToString("F2") : "off")
.Append(" · 화면 ").Append(cam != null && n > 0 ? cam.WorldToViewportPoint(c).ToString("F3") : "-").AppendLine();
}
}
return sb.ToString();
}
// ── 날아가는 화살 붙잡기 · 가까이 찍기 ──
static ProjectileBase s_arrow;
/// <summary>mode 0 = 기본 겉모습(~WL_Visual 켜짐) · 1 = 3타(~WL_Charged 켜짐) · 2 = 속사(Projectile_ArcherSkill2Arrow) 화살이 PC 에서 minDist m 넘게 날아간 순간 일시 정지 — 진행 방향과 앞(+Z) 사이 각도.</summary>
public static object Arrow(int mode, float minDist, float maxSeconds)
{
var pc = MyValue.MyPC as PCActor; if (pc == null) return "PC 없음";
var sb = Buf(); sb.Length = 0; s_arrow = null;
var prev = new System.Collections.Generic.Dictionary<ProjectileBase, Vector3>(); float t0 = Time.time;
int ch0 = WL.Combat.Weapon.WLBowChargeReceiver.Charges; float chargeT = -1f;
UnityEngine.Events.UnityAction act = null;
act = () =>
{
float t = Time.time - t0;
if (chargeT < 0f && WL.Combat.Weapon.WLBowChargeReceiver.Charges > ch0) { chargeT = t; sb.AppendFormat("{0:F2} 3타 모으기 시작 · {1}", t, WL.Combat.Weapon.WLBowChargeReceiver.LastLog).Append('\n'); }
foreach (var pb in Object.FindObjectsByType<ProjectileBase>(FindObjectsInactive.Exclude, FindObjectsSortMode.None))
{
if (pb == null) continue;
bool basic = pb.name.StartsWith("Projectile_1040"), rapid = pb.name.StartsWith("Projectile_ArcherSkill2Arrow");
if (!basic && !rapid) continue;
var vis = pb.transform.Find("~WL_Visual"); var chg = pb.transform.Find("~WL_Charged");
bool isCharged = chg != null && chg.gameObject.activeSelf;
Vector3 p0; bool had = prev.TryGetValue(pb, out p0); prev[pb] = pb.transform.position;
if (chargeT >= 0f && isCharged && !sb.ToString().Contains("3타 화살 생성")) sb.AppendFormat("{0:F2} 3타 화살 생성 · 모으기부터 {1:F2} 초", t, t - chargeT).Append('\n');
bool want = mode == 0 ? basic && vis != null && vis.gameObject.activeSelf && !isCharged : mode == 1 ? basic && isCharged : rapid;
float dpc = Vector3.Distance(pb.transform.position, pc.Get_position());
if (!want || !had || dpc < minDist || dpc > minDist + 3f) continue; // 멀리 날아가는 옛 관통 화살 제외
var mv = pb.transform.position - p0; if (mv.sqrMagnitude < 1e-6f) continue;
Application.onBeforeRender -= act; EditorPause(); s_arrow = pb; System.AppDomain.CurrentDomain.SetData("wl919arrow", pb); // run_script 마다 어셈블리가 새로 — 정적 필드 대신
sb.AppendFormat("■ 일시 정지 {0:F2} · {1} · 진행-앞 각 {2:F0}° · 진행 높이 변화 {3:F2} · lossy {4:F3} · 기본 {5} · 3타 {6}", t, pb.name, Vector3.Angle(mv, pb.transform.forward), mv.normalized.y, pb.transform.lossyScale.x,
vis != null && vis.gameObject.activeSelf, isCharged).Append('\n');
return;
}
if (t > maxSeconds) { Application.onBeforeRender -= act; sb.Append("못 찾음\n"); }
};
Application.onBeforeRender += act;
return "화살 관찰 " + mode;
}
static void EditorPause()
{
#if UNITY_EDITOR
UnityEditor.EditorApplication.isPaused = true;
#endif
}
/// <summary>붙잡은 화살을 게임 카메라와 같은 각도로 dist m 앞에서 찍는다(PNG · w×h).</summary>
public static object Shot(string outFile, float dist, float fov)
{
if (s_arrow == null) s_arrow = System.AppDomain.CurrentDomain.GetData("wl919arrow") as ProjectileBase;
var main = Camera.main; if (main == null || s_arrow == null) return "카메라/화살 없음";
var go = new GameObject("~WL919_Shot"); var cam = go.AddComponent<Camera>(); cam.enabled = false;
cam.CopyFrom(main); cam.fieldOfView = fov;
int ui = LayerMask.NameToLayer("UI"); if (ui >= 0) cam.cullingMask &= ~(1 << ui); // 월드 HUD(HP 바 등) 빼기
go.transform.rotation = main.transform.rotation; go.transform.position = s_arrow.transform.position - main.transform.forward * dist;
var rt = new RenderTexture(1200, 800, 24, RenderTextureFormat.ARGB32); cam.targetTexture = rt; cam.aspect = 1.5f; cam.Render();
var prev = RenderTexture.active; RenderTexture.active = rt;
var tex = new Texture2D(rt.width, rt.height, TextureFormat.RGB24, false); tex.ReadPixels(new Rect(0, 0, rt.width, rt.height), 0, 0); tex.Apply();
RenderTexture.active = prev; System.IO.File.WriteAllBytes(outFile, tex.EncodeToPNG());
Object.Destroy(tex); cam.targetTexture = null; Object.Destroy(rt); Object.Destroy(go);
var sp = main.WorldToViewportPoint(s_arrow.transform.position + s_arrow.transform.forward * 0.3f) - main.WorldToViewportPoint(s_arrow.transform.position);
return "저장 " + outFile + " · 화면에서 화살 앞 방향 (" + sp.x.ToString("F3") + "," + sp.y.ToString("F3") + ")";
}
/// <summary>PC → 더미 사이 띠(반경 r m) 안의 켜진 렌더러 — 이름(경로) · 종류 · 재질 · 셰이더 · 파티클 수.</summary>
public static object Path(float r)
{
var pc = MyValue.MyPC as PCActor; var d = WL.IslandMob.WLTrailTest.Dummy; if (pc == null || d == null) return "PC/더미 없음";
Vector3 a = pc.Get_position(), b = d.Get_position(); a.y = b.y = 0f; var sb = new StringBuilder(); int n = 0;
foreach (var rd in Object.FindObjectsByType<Renderer>(FindObjectsInactive.Exclude, FindObjectsSortMode.None))
{
if (rd == null || !rd.enabled || !rd.isVisible) continue;
if (rd.transform.IsChildOf(pc.transform) || rd.transform.IsChildOf(d.transform)) continue;
var c = rd.bounds.center; c.y = 0f; var ab = b - a; float t = Mathf.Clamp01(Vector3.Dot(c - a, ab) / Mathf.Max(1e-4f, ab.sqrMagnitude));
if (Vector3.Distance(c, a + ab * t) > r || rd.bounds.size.magnitude > 30f) continue;
var ps = rd.GetComponent<ParticleSystem>(); var m = rd.sharedMaterial;
string path = rd.name; var tr = rd.transform.parent; for (int k = 0; k < 3 && tr != null; k++, tr = tr.parent) path = tr.name + "/" + path;
sb.Append(rd.GetType().Name).Append(' ').Append(path).Append(" · 재질 ").Append(m != null ? m.name + " / " + m.shader.name : "-").Append(ps != null ? " · 입자 " + ps.particleCount : "").Append(" · 크기 ").Append(rd.bounds.size.ToString("F2")).AppendLine();
if (++n > 40) break;
}
return n + " 개\n" + sb;
}
public static object Bow()
{
var pc = MyValue.MyPC as PCActor; if (pc == null) return "PC 없음";
var sb = new StringBuilder();
float gy = pc.Get_position().y;
sb.Append("PC 키 ").Append((pc.Get_Top_postion().y - gy).ToString("F2")).Append(" · 중심 +").Append((pc.Get_Center_position().y - gy).ToString("F2")).Append(" · 배율 ").Append(pc.transform.localScale.x.ToString("F3")).AppendLine();
Transform bow = null;
foreach (var t in pc.GetComponentsInChildren<Transform>(false))
if (t.gameObject.activeInHierarchy && t.name.IndexOf("Bow", System.StringComparison.OrdinalIgnoreCase) >= 0 && t.name.IndexOf("Elbow", System.StringComparison.OrdinalIgnoreCase) < 0) { bow = t; break; }
sb.Append("FindBow → ").Append(bow != null ? bow.name + " (부모 " + (bow.parent != null ? bow.parent.name : "-") + ")" : "없음").AppendLine();
if (pc.tfs_weapon != null)
foreach (var s in pc.tfs_weapon)
{
if (s == null || !s.gameObject.activeInHierarchy) continue;
var cl = WL.Combat.Weapon.WLWeaponGlowFx.CenterLocal(s); var cw = s.TransformPoint(cl);
Bounds b = new Bounds(); bool has = false;
foreach (var r in s.GetComponentsInChildren<MeshRenderer>(false)) { if (!r.enabled || r.name == "[WL] Glow") continue; if (!has) { b = r.bounds; has = true; } else b.Encapsulate(r.bounds); }
sb.Append("소켓 ").Append(s.name).Append(" · 그림 중심 ").Append(V(cw - pc.Get_position())).Append(" · 소켓 원점 ").Append(V(s.position - pc.Get_position()))
.Append(" · 원점-중심 ").Append(Vector3.Distance(s.position, cw).ToString("F2")).Append(" m · 그림 크기 ").Append(has ? V(b.size) : "-").Append(" · lossy ").Append(s.lossyScale.x.ToString("F3"));
if (bow != null) sb.Append(" · FindBow-중심 ").Append(Vector3.Distance(bow.position, cw).ToString("F2")).Append(" m");
sb.AppendLine();
}
return sb.ToString();
}
}