129 lines
8.2 KiB
C#
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 { } }
|
|
}
|