Project_WL/AgentScripts/WL908_Probe.cs

306 lines
18 KiB
C#
Raw Permalink 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.

// WL908_Probe.cs — PD 지시 #908 시험(Play 중 · 섬)
// Setup(group, tier) : 무기 그룹 장착 + 장비 전체 등급(치트)
// CastMove(slot, dist, delay, moveSec, sec, angle) : 시험 몹을 PC 정면 dist(m)에 세우고(멈춤) 무기 스킬 slot(1 주력 Q · 2 각성 E)을 쏜 뒤
// delay 초 후 moveSec 초 동안 조이스틱 이동을 넣는다(섬 아바타와 같은 호출 순서 · angle = PC 정면 기준 이동 방향 각도) · sec 초 동안 매 프레임 기록
// Log() : 기록 · Counters() : 관련 카운터
using System.Text;
using UnityEngine;
public static class WL908_Probe
{
const string Key = "wl908log";
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;
}
static Actor Dummy()
{
var d = WL.IslandMob.WLTrailTest.Dummy;
if (d != null && d.isActiveAndEnabled) return d;
var pc = MyValue.MyPC; Actor best = null; float bd = float.MaxValue;
foreach (var m in Object.FindObjectsByType<MobActor>(FindObjectsInactive.Exclude, FindObjectsSortMode.None))
{
if (m == null || m.IsDead()) continue;
float dd = pc != null ? Vector3.Distance(pc.Get_position(), m.Get_position()) : 0f;
if (dd < bd) { bd = dd; best = m; }
}
return best;
}
static string Clip(Animator a)
{
if (a == null) return "-";
var ci = a.GetCurrentAnimatorClipInfo(0);
string s = ci.Length > 0 && ci[0].clip != null ? ci[0].clip.name : "-";
if (a.IsInTransition(0)) { var ni = a.GetNextAnimatorClipInfo(0); s += "→" + (ni.Length > 0 && ni[0].clip != null ? ni[0].clip.name : "-"); }
return s;
}
public static object Setup(int group, int tier)
{
string r = "";
if (WLInventoryReady())
foreach (var it in WL.Equip.WLInventory.SortedItems())
if (it != null && it.itemJson != null && it.itemJson.GroupNo == group) { r = "장착 " + group + " " + it.itemJson.Item_name + " → " + WL.Equip.WLInventory.Equip(it.rawItem._id); break; }
if (r == "") r = "인벤토리에 없음 " + group;
if (tier > 0) r += " · 등급 " + WL.Combat.Weapon.WLWeaponGradeCheat.Apply(tier);
return r;
}
static bool WLInventoryReady() { return WL.Equip.WLInventory.EnsureLoaded(); }
public static object CastMove(int slot, float dist, float delay, float moveSec, float seconds, float angle)
{
var pc = MyValue.MyPC as PCActor; var d = Dummy();
if (pc == null || d == null) return "PC/몹 없음";
if (dist > 0f)
{
var f = pc.transform.forward; f.y = 0f; if (f.sqrMagnitude < 1e-4f) f = Vector3.forward; 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);
}
var sb = Buf(); sb.Length = 0;
float t0 = Time.time; bool moving = false, moved = false; string last = "";
int sf0 = WL.Combat.Core.CombatEvents.SkillFired.Raised;
Vector3 fwd0 = pc.transform.forward; fwd0.y = 0f; fwd0.Normalize();
Vector3 mdir = Quaternion.Euler(0f, angle, 0f) * fwd0;
float y0 = pc.transform.position.y;
sb.Append("시작 거리 ").Append(Vector3.Distance(pc.Get_position(), d.Get_position()).ToString("F2")).Append('\n');
UnityEngine.Events.UnityAction act = null;
act = () =>
{
if (pc == null || pc.m_animation == null || d == null) { Application.onBeforeRender -= act; return; }
float t = Time.time - t0;
if (!moved && moveSec > 0f && t >= delay)
{
if (!moving) { pc.Set_AutoBraking(false); pc.Set_JoystickStatus(1); moving = true; sb.AppendFormat("{0:F2} ▶ 이동 입력 시작\n", t); }
pc.Run_byJoystick(mdir);
if (t >= delay + moveSec) { pc.Set_JoystickStatus(0); pc.Set_AutoBraking(true); moving = false; moved = true; sb.AppendFormat("{0:F2} ■ 이동 입력 끝\n", t); }
}
string key = Clip(pc.m_animation) + " " + pc.Get_CurAnim();
if (key != last)
{
last = key;
sb.AppendFormat("{0:F2} {1} · 거리 {2:F2} · 높이 {3:F2} · 조이 {4} · 스킬발사 +{5}\n", t, key, Vector3.Distance(pc.Get_position(), d.Get_position()),
pc.transform.position.y - y0, pc.JoystickStatus, WL.Combat.Core.CombatEvents.SkillFired.Raised - sf0);
}
if (t > seconds)
{
Application.onBeforeRender -= act;
if (moving) { pc.Set_JoystickStatus(0); pc.Set_AutoBraking(true); }
sb.AppendFormat("끝 · 거리 {0:F2} · 스킬발사 +{1}\n", Vector3.Distance(pc.Get_position(), d.Get_position()), WL.Combat.Core.CombatEvents.SkillFired.Raised - sf0);
}
};
Application.onBeforeRender += act;
string r = WL.Combat.Weapon.WLSkillHotkey.Fire(slot);
return "발동: " + r;
}
public static object Log() { return Buf().ToString(); }
public static object Counters()
{
return "접근 바로 " + WL.Combat.Weapon.WLSkillApproach.Immediate + " · 대쉬 " + WL.Combat.Weapon.WLSkillApproach.Dashes + " · 도착 " + WL.Combat.Weapon.WLSkillApproach.Arrivals
+ " · 시간초과 " + WL.Combat.Weapon.WLSkillApproach.Timeouts + " · 끊김 " + WL.Combat.Weapon.WLSkillApproach.Broken + " · " + WL.Combat.Weapon.WLSkillApproach.LastLog
+ " | 연속베기 " + WL.Combat.Weapon.WLSlashFlurry.Taken + " · 스킬발사 " + WL.Combat.Core.CombatEvents.SkillFired.Raised + " · 핫키 " + WL.Combat.Weapon.WLSkillHotkey.LastLog;
}
/// <summary>이동 입력을 먼저 넣고(이동 키를 누른 채) preMove 초 뒤에 slot 스킬을 쏜다 · 이동은 moveSec 초 동안 계속 · sec 초 기록.</summary>
public static object MoveCast(int slot, float dist, float preMove, float moveSec, float seconds, float angle)
{
var pc = MyValue.MyPC as PCActor; var d = Dummy();
if (pc == null || d == null) return "PC/몹 없음";
var f0 = pc.transform.forward; f0.y = 0f; if (f0.sqrMagnitude < 1e-4f) f0 = Vector3.forward; f0.Normalize();
if (dist > 0f)
{
var want = pc.Get_position() + f0 * 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);
}
var sb = Buf(); sb.Length = 0;
float t0 = Time.time; bool moving = false, fired = false; string last = "";
int sf0 = WL.Combat.Core.CombatEvents.SkillFired.Raised;
Vector3 mdir = Quaternion.Euler(0f, angle, 0f) * f0;
float y0 = pc.transform.position.y;
sb.Append("시작 거리 ").Append(Vector3.Distance(pc.Get_position(), d.Get_position()).ToString("F2")).Append('\n');
UnityEngine.Events.UnityAction act = null;
act = () =>
{
if (pc == null || pc.m_animation == null || d == null) { Application.onBeforeRender -= act; return; }
float t = Time.time - t0;
if (t < moveSec)
{
if (!moving) { pc.Set_AutoBraking(false); pc.Set_JoystickStatus(1); moving = true; sb.AppendFormat("{0:F2} ▶ 이동 입력 시작", t).Append('\n'); }
pc.Run_byJoystick(mdir);
}
else if (moving) { pc.Set_JoystickStatus(0); pc.Set_AutoBraking(true); moving = false; sb.AppendFormat("{0:F2} ■ 이동 입력 끝", t).Append('\n'); }
if (!fired && t >= preMove) { fired = true; sb.AppendFormat("{0:F2} ◆ 발동 ", t).Append(WL.Combat.Weapon.WLSkillHotkey.Fire(slot)).Append('\n'); }
string key = Clip(pc.m_animation) + " " + pc.Get_CurAnim();
if (key != last)
{
last = key;
sb.AppendFormat("{0:F2} {1} · 거리 {2:F2} · 높이 {3:F2} · 조이 {4} · 스킬발사 +{5}", t, key, Vector3.Distance(pc.Get_position(), d.Get_position()),
pc.transform.position.y - y0, pc.JoystickStatus, WL.Combat.Core.CombatEvents.SkillFired.Raised - sf0).Append('\n');
}
if (t > seconds)
{
Application.onBeforeRender -= act;
if (moving) { pc.Set_JoystickStatus(0); pc.Set_AutoBraking(true); }
sb.AppendFormat("끝 · 거리 {0:F2} · 스킬발사 +{1}", Vector3.Distance(pc.Get_position(), d.Get_position()), WL.Combat.Core.CombatEvents.SkillFired.Raised - sf0).Append('\n');
}
};
Application.onBeforeRender += act;
return "이동 먼저 · " + preMove + " s 뒤 발동";
}
/// <summary>시험 몹을 dist 에 세우고(멈춤) 해머 1타가 땅에 닿는 순간(지면 충격 이펙트 표시) 에디터를 일시 정지한다 — 캡처용.</summary>
public static object PauseOnGround(float dist, float seconds)
{
var pc = MyValue.MyPC as PCActor; var d = Dummy();
if (pc == null || d == null) return "PC/몹 없음";
var f = pc.transform.forward; f.y = 0f; f.Normalize();
d.Stop(true); d.Set_Warp(pc.Get_position() + f * dist);
int g0 = WL.Combat.Impact.WLImpactFx.GroundShown; float t0 = Time.time;
var sb = Buf(); sb.Length = 0;
UnityEngine.Events.UnityAction act = null;
act = () =>
{
if (pc == null || d == null || Time.time - t0 > seconds) { Application.onBeforeRender -= act; return; }
if (WL.Combat.Impact.WLImpactFx.GroundShown != g0)
{
Application.onBeforeRender -= act;
sb.Append("정지 · PC-적 ").Append(Vector3.Distance(pc.Get_position(), d.Get_position()).ToString("F2")).Append(" · ").Append(WL.Combat.Impact.WLImpactFx.LastGround);
UnityEditor.EditorApplication.isPaused = true;
}
};
Application.onBeforeRender += act;
return "대기 · 몹 " + Vector3.Distance(pc.Get_position(), d.Get_position()).ToString("F2");
}
/// <summary>지금 켜진 이 PC 의 원본 스킬 투사체(InGameInfo 스킬 풀) · 스킬 연출 활성 수 · 이름이 Effect_PCDash 인 켜진 먼지의 방향(대상 방향과의 내적).</summary>
public static object SkillObjs()
{
var pc = MyValue.MyPC as PCActor; if (pc == null) return "PC 없음";
var sb = new StringBuilder();
var f = typeof(InGameInfo).GetField("dic_Skill", System.Reflection.BindingFlags.Instance | System.Reflection.BindingFlags.NonPublic | System.Reflection.BindingFlags.Public);
var dic = f != null ? f.GetValue(InGameInfo.Ins) as System.Collections.IDictionary : null;
int n = 0;
if (dic != null)
foreach (System.Collections.DictionaryEntry kv in dic)
foreach (var o in (System.Collections.IList)kv.Value)
{
var go = o as GameObject; if (go == null || !go.activeInHierarchy) continue;
var pb = go.GetComponent<ProjectileBase>(); var data = pb != null ? pb.Get_ProjectTileData() : null;
if (data != null && ReferenceEquals(data.shooter, pc)) { n++; sb.Append(kv.Key).Append(' '); }
}
sb.Append("| 켜진 스킬 투사체 ").Append(n).Append(" · 연출 활성 ").Append(WL.Combat.Reaction.SkillSpectacle.ActiveCount)
.Append(" · 취소 끈 연출 ").Append(WL.Combat.Reaction.SkillSpectacle.Cancelled);
return sb.ToString();
}
public static object Cancel()
{
return "시작 " + WL.Combat.Weapon.WLSkillCancel.Casts + " · 스킵 " + WL.Combat.Weapon.WLSkillCancel.Skips + " · 끈 것 " + WL.Combat.Weapon.WLSkillCancel.SkippedObjects
+ " · 이동 무시 " + WL.Combat.Weapon.WLSkillCancel.MoveBlocked + " · 구르기 무시 " + WL.Combat.Weapon.WLSkillCancel.DodgeBlocked + " · 미룸 " + WL.Combat.Weapon.WLSkillCancel.BrakeDeferred
+ " · 적용 " + WL.Combat.Weapon.WLSkillCancel.BrakeApplied + " · 오류 " + WL.Combat.Weapon.WLSkillCancel.Errors + " · " + WL.Combat.Weapon.WLSkillCancel.LastLog;
}
/// <summary>slot 스킬을 쏘고 delay 초 뒤 구르기(원본 Play_Dodge · 옆 angle 도) · sec 초 기록.</summary>
public static object CastDodge(int slot, float dist, float delay, float seconds, float angle)
{
var pc = MyValue.MyPC as PCActor; var d = Dummy();
if (pc == null || d == null) return "PC/몹 없음";
var f0 = pc.transform.forward; f0.y = 0f; f0.Normalize();
if (dist > 0f) { d.Stop(true); d.Set_Warp(pc.Get_position() + f0 * dist); }
var sb = Buf(); sb.Length = 0;
float t0 = Time.time; bool dodged = false; string last = "";
int sf0 = WL.Combat.Core.CombatEvents.SkillFired.Raised;
UnityEngine.Events.UnityAction act = null;
act = () =>
{
if (pc == null || pc.m_animation == null) { Application.onBeforeRender -= act; return; }
float t = Time.time - t0;
if (!dodged && t >= delay) { dodged = true; var fw = pc.transform.forward; fw.y = 0f; pc.transform.rotation = Quaternion.LookRotation(Quaternion.Euler(0f, angle, 0f) * fw); pc.Play_Dodge(); sb.AppendFormat("{0:F2} ▶ 구르기 → {1}", t, pc.Get_CurAnim()).Append('\n'); }
string key = Clip(pc.m_animation) + " " + pc.Get_CurAnim();
if (key != last) { last = key; sb.AppendFormat("{0:F2} {1} · 스킬발사 +{2}", t, key, WL.Combat.Core.CombatEvents.SkillFired.Raised - sf0).Append('\n'); }
if (t > seconds) { Application.onBeforeRender -= act; sb.Append("끝").Append('\n'); }
};
Application.onBeforeRender += act;
return "발동: " + WL.Combat.Weapon.WLSkillHotkey.Fire(slot);
}
/// <summary>점프 스킬 먼지(Effect_PCDash) — 켜진 것의 앞 방향과 PC → 대상 방향의 내적(−1 = 정반대) · 크기.</summary>
public static object Dust()
{
var pc = MyValue.MyPC as PCActor; var d = Dummy(); var sb = new StringBuilder();
Vector3 to = d != null && pc != null ? d.Get_position() - pc.Get_position() : Vector3.forward; to.y = 0f; to.Normalize();
foreach (var tf in Object.FindObjectsByType<Transform>(FindObjectsInactive.Exclude, FindObjectsSortMode.None))
{
if (!tf.name.StartsWith("Effect_PCDash") || (tf.parent != null && tf.parent.name.StartsWith("Effect_PCDash"))) continue;
var fw = tf.forward; fw.y = 0f; fw.Normalize();
sb.Append(tf.name).Append(" 앞·대상방향 ").Append(Vector3.Dot(fw, to).ToString("F2")).Append(" 크기 ").Append(tf.localScale.x.ToString("F3")).Append(" | ");
}
return sb.Length > 0 ? sb.ToString() : "켜진 먼지 없음";
}
/// <summary>벽 튕김 시험 — 시험 몹을 가장 가까운 NavMesh 경계 inside m 안쪽에 두고 PC 를 그 뒤에 세워 경계 쪽으로 Fling(dist m · sec 초 · 튕김) · 몹 위치를 기록.</summary>
public static object BounceTest(float inside, float dist, float sec)
{
var pc = MyValue.MyPC as PCActor; var d = Dummy();
if (pc == null || d == null) return "PC/몹 없음";
UnityEngine.AI.NavMeshHit e;
if (!UnityEngine.AI.NavMesh.FindClosestEdge(d.Get_position(), out e, UnityEngine.AI.NavMesh.AllAreas)) return "경계 못 찾음";
var n = e.normal; n.y = 0f; n.Normalize();
var at = e.position + n * inside;
d.Stop(true); d.Set_Warp(at);
pc.Set_Warp(at + n * 1.2f);
var sb = Buf(); sb.Length = 0;
int b0 = WL.Combat.Weapon.WLLaunch.Bounces; float t0 = Time.time; Vector3 p0 = d.Get_position();
sb.Append("경계 ").Append(e.position.ToString("F2")).Append(" 법선 ").Append(n.ToString("F2")).Append(" · 몹 경계까지 ").Append(Vector3.Dot(d.Get_position() - e.position, n).ToString("F2")).Append('\n');
WL.Combat.Weapon.WLLaunch.Fling(d, pc, dist, sec, 0.5f, 0.5f, true);
UnityEngine.Events.UnityAction act = null;
act = () =>
{
if (d == null) { Application.onBeforeRender -= act; return; }
float t = Time.time - t0;
sb.AppendFormat("{0:F2} 경계까지 {1:F2} · 이동 {2:F2} · 튕김 +{3}", t, Vector3.Dot(d.Get_position() - e.position, n), Vector3.Distance(p0, d.Get_position()), WL.Combat.Weapon.WLLaunch.Bounces - b0).Append('\n');
if (t > sec + 0.1f) { Application.onBeforeRender -= act; d.Stop(false); }
};
Application.onBeforeRender += act;
return "튕김 시험 시작";
}
/// <summary>시험 몹을 dist 에 세우고 주력 스킬(Q)을 쏜 뒤 2~4 프레임째에 켜진 먼지(Effect_PCDash)의 방향 · 크기를 기록.</summary>
public static object JumpDust(float dist)
{
var pc = MyValue.MyPC as PCActor; var d = Dummy();
if (pc == null || d == null) return "PC/몹 없음";
var f0 = pc.transform.forward; f0.y = 0f; f0.Normalize();
d.Stop(true); d.Set_Warp(pc.Get_position() + f0 * dist);
var sb = Buf(); sb.Length = 0; int frames = 0;
Vector3 to = d.Get_position() - pc.Get_position(); to.y = 0f; to.Normalize();
UnityEngine.Events.UnityAction act = null;
act = () =>
{
frames++;
if (frames >= 2 && frames <= 4)
{
foreach (var tf in Object.FindObjectsByType<Transform>(FindObjectsInactive.Exclude, FindObjectsSortMode.None))
{
if (!tf.name.StartsWith("Effect_PCDash") || (tf.parent != null && tf.parent.name.StartsWith("Effect_PCDash"))) continue;
var fw = tf.forward; fw.y = 0f; fw.Normalize();
sb.AppendFormat("f{0} {1} 앞·점프방향 {2:F2} · 크기 {3:F3}", frames, tf.name, Vector3.Dot(fw, to), tf.localScale.x).Append('\n');
}
}
if (frames > 4) Application.onBeforeRender -= act;
};
Application.onBeforeRender += act;
return "발동: " + WL.Combat.Weapon.WLSkillHotkey.Fire(1);
}
}