Project_WL/AgentScripts/WL908_Probe.cs

306 lines
18 KiB
C#
Raw Normal View History

// 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);
}
}