Project_WL/AgentScripts/WL888_Probe.cs

129 lines
8.2 KiB
C#

// WL888_Probe.cs — PD 지시 #888 · #889 시험(Play 중)
// FxTry : 방패 치기 Slash 래퍼를 PC 앞에 회전 후보로 띄운다(파일 무수정)
// Timeline: 슬롯 스킬 시험 시전 → 0.1 s(게임 시간)마다 동작 · 상태 · 위치 · 보이는 렌더러 · 타격 수를 파일에(run_script 마다 새 어셈블리 · K-DEV-023)
// Dodge2 : 더블 탭 흉내(WLDoubleTapDodge.Down/Up 직접 호출 · PC 화면 위치 + 픽셀 오프셋) → 0.9 s 뒤 이동 방향을 파일에
using System.Collections;
using System.Text;
using UnityEngine;
public static class WL888_Probe
{
static readonly string[] States = { "dashslash", "slashflurry_b1", "slashflurry_a1", "slashflurry_b2", "shieldattack", "idle", "run", "dodge", "attack", "Attack2", "Attack3", "hit" };
public static object FxTry(float ex, float ey, float ez, float fwd, float up, float scale)
{
var pc = MyValue.MyPC; if (pc == null) return "PC 없음";
var p = Resources.Load<GameObject>("WL/Fx/WL_Fx_ShieldSlash"); if (p == null) return "래퍼 없음";
var f = pc.transform.forward; f.y = 0f; f.Normalize();
var rot = Quaternion.LookRotation(f) * Quaternion.Euler(ex, ey, ez);
var old = GameObject.Find("WL888_FxTry"); if (old != null) Object.Destroy(old);
var go = Object.Instantiate(p, pc.transform.position + f * fwd + Vector3.up * up, rot);
go.name = "WL888_FxTry";
foreach (var ps in go.GetComponentsInChildren<ParticleSystem>(true)) { var m = ps.main; m.scalingMode = ParticleSystemScalingMode.Hierarchy; m.simulationSpeed = 0.15f; }
go.transform.localScale = Vector3.one * scale;
Object.Destroy(go, 6f);
return "띄움 euler(" + ex + "," + ey + "," + ez + ")";
}
public static object Timeline(string path, int slot, float seconds)
{
var pc = MyValue.MyPC; if (pc == null) return "PC 없음";
var arr = typeof(PCActor).GetField("arr_magicData", System.Reflection.BindingFlags.Instance | System.Reflection.BindingFlags.NonPublic | System.Reflection.BindingFlags.Public).GetValue(pc) as SkillListTableData[];
var data = arr != null && slot >= 0 && slot < arr.Length ? arr[slot] : null;
if (data == null) return "슬롯 비어 있음 " + slot;
System.IO.File.WriteAllText(path, "skill " + data.n_SkillID + " " + data.e_Skill + " anim=" + data.s_Animation + " range=" + data.f_SkillRange + "\n");
pc.StartCoroutine(Co(pc, data, slot, path, seconds));
return "started " + data.n_SkillID;
}
static IEnumerator Co(PCActor pc, SkillListTableData data, int slot, string path, float seconds)
{
int h0 = WL.Combat.Core.CombatEvents.HitConfirmed.Raised;
var start = pc.transform.position;
int skillHits = 0; int sid = data.n_SkillID;
WL.Combat.Core.CombatHandler<WL.Combat.Core.HitConfirmedEvent> hh = (in WL.Combat.Core.HitConfirmedEvent e) =>
{
if (e.projectile != null && e.projectile.m_SkillListTableData != null && e.projectile.m_SkillListTableData.n_SkillID == sid) skillHits++;
};
WL.Combat.Core.CombatEvents.HitConfirmed.Add(hh);
bool ok = pc.Use_Skill(data, true, slot, true);
Append(path, "cast=" + ok);
float t = 0f, next = 0f;
while (t < seconds && pc != null)
{
if (t >= next) { next += 0.1f; Append(path, Line(pc, t, h0, start)); }
yield return null;
t += Time.deltaTime;
}
WL.Combat.Core.CombatEvents.HitConfirmed.Remove(hh);
Append(path, "END " + Line(pc, t, h0, start) + " | 이 스킬 타격 " + skillHits + " | flurry " + WL.Combat.Weapon.WLSlashFlurry.LastLog + " windows=" + WL.Combat.Weapon.WLSlashFlurry.Windows + " | vfx swings=" + WL.Combat.Weapon.WLSkillVfx.Swings + " hits=" + WL.Combat.Weapon.WLSkillVfx.Hits);
}
static string Line(PCActor pc, float t, int h0, Vector3 start)
{
var an = pc.m_animation; string st = "?";
if (an != null)
{
var si = an.GetCurrentAnimatorStateInfo(0);
foreach (var n in States) if (si.IsName(n)) { st = n; break; }
if (an.IsInTransition(0)) { var ni = an.GetNextAnimatorStateInfo(0); foreach (var n in States) if (ni.IsName(n)) { st += ">" + n; break; } }
}
int on = 0, all = 0;
foreach (var r in pc.GetComponentsInChildren<Renderer>(true)) { if (r is ParticleSystemRenderer) continue; all++; if (r.enabled && r.gameObject.activeInHierarchy) on++; }
var p = pc.transform.position; var d = p - start; d.y = 0f;
string clip = "-"; if (an != null) { var ci = an.GetCurrentAnimatorClipInfo(0); if (ci.Length > 0) clip = ci[0].clip.name; }
return "t=" + t.ToString("F2") + " anim=" + pc.Get_CurAnim() + " state=" + st + " clip=" + clip + " moved=" + d.magnitude.ToString("F2") + " vis=" + on + "/" + all + " hits+" + (WL.Combat.Core.CombatEvents.HitConfirmed.Raised - h0)
+ " stop=" + IsStop(pc) + " step=" + pc.WL_CanAttackStep() + " apply=" + WL.Combat.AttackRootMotion.ApplyCount;
}
static string IsStop(PCActor pc)
{
var bf = System.Reflection.BindingFlags.Instance | System.Reflection.BindingFlags.NonPublic | System.Reflection.BindingFlags.Public;
for (var t = pc.GetType(); t != null; t = t.BaseType)
{
var f = t.GetField("IsStop", bf); if (f != null) return f.GetValue(pc).ToString();
var p = t.GetProperty("IsStop", bf); if (p != null) return p.GetValue(pc, null).ToString();
}
return "?";
}
/// <summary>PC 를 (x, z) 근처 NavMesh 위로 옮긴다(시험 자리 — 섬 가장자리 · 물가 회피).</summary>
public static object WarpNear(float x, float z)
{
var pc = MyValue.MyPC; if (pc == null) return "PC 없음";
UnityEngine.AI.NavMeshHit hit;
if (!UnityEngine.AI.NavMesh.SamplePosition(new Vector3(x, pc.transform.position.y, z), out hit, 6f, UnityEngine.AI.NavMesh.AllAreas)) return "NavMesh 없음";
var ag = pc.GetComponent<UnityEngine.AI.NavMeshAgent>(); if (ag != null && ag.enabled) ag.Warp(hit.position); else pc.transform.position = hit.position;
return "옮김 " + hit.position.ToString("F1");
}
public static object Dodge2(string path, float dxPx, float dyPx)
{
var pc = MyValue.MyPC; if (pc == null) return "PC 없음";
var cam = Camera.main; if (cam == null) return "카메라 없음";
var sp = (Vector2)cam.WorldToScreenPoint(pc.transform.position) + new Vector2(dxPx, dyPx);
var ray = cam.ScreenPointToRay(sp); var plane = new Plane(Vector3.up, pc.transform.position); float e;
Vector3 expect = plane.Raycast(ray, out e) ? ray.GetPoint(e) - pc.transform.position : Vector3.zero; expect.y = 0f;
float now = Time.unscaledTime;
WL.Combat.WLDoubleTapDodge.Down(sp, now, 0);
WL.Combat.WLDoubleTapDodge.Up(sp, now + 0.05f, false);
var before = pc.transform.position;
WL.Combat.WLDoubleTapDodge.Down(sp, now + 0.18f, 0);
WL.Combat.WLDoubleTapDodge.Up(sp, now + 0.22f, false);
System.IO.File.WriteAllText(path, "탭 화면 " + sp.ToString("F0") + " 기대 방향 " + expect.normalized.ToString("F2") + " | " + WL.Combat.WLDoubleTapDodge.LastLog + " anim=" + pc.Get_CurAnim() + "\n");
pc.StartCoroutine(CoAfter(pc, path, before, expect));
return "taps " + WL.Combat.WLDoubleTapDodge.Taps + " double " + WL.Combat.WLDoubleTapDodge.DoubleTaps + " dodges " + WL.Combat.WLDoubleTapDodge.Dodges + " blocked " + WL.Combat.WLDoubleTapDodge.Blocked;
}
static IEnumerator CoAfter(PCActor pc, string path, Vector3 before, Vector3 expect)
{
float t = 0f;
while (t < 0.9f) { t += Time.deltaTime; yield return null; }
var d = pc.transform.position - before; d.y = 0f;
float cos = d.sqrMagnitude > 1e-4f && expect.sqrMagnitude > 1e-4f ? Vector3.Dot(d.normalized, expect.normalized) : 0f;
Append(path, "0.9 s 뒤 이동 " + d.magnitude.ToString("F2") + " m 방향 " + d.normalized.ToString("F2") + " · 기대와 cos " + cos.ToString("F2") + " · anim=" + pc.Get_CurAnim());
}
static void Append(string path, string line) { try { System.IO.File.AppendAllText(path, line + "\n"); } catch { } }
}