Project_WL/AgentScripts/WL882_Probe.cs

125 lines
7.8 KiB
C#
Raw Normal View History

// WL882_Probe.cs — PD 지시 #882 무기 기술 이동 · 대검 오류 스모크(Play 중)
// unity command run_script --file AgentScripts/WL882_Probe.cs --entry WL882_Probe.WSkill
using System.Reflection;
using System.Text;
using UnityEngine;
public static class WL882_Probe
{
static readonly BindingFlags BF = BindingFlags.Instance | BindingFlags.NonPublic | BindingFlags.Public;
/// <summary>PC 직업 · 동작 · 기다리는 스킬 · 슬롯 0~1 스킬(직업 칸) · 지금 클립 · 무기 스킬 슬롯 로그 · 스킬 투사체 수 · 시전 수.</summary>
public static object WSkill()
{
var pc = MyValue.MyPC; if (pc == null) return "PC 없음";
var sb = new StringBuilder();
var arr = typeof(PCActor).GetField("arr_magicData", BF).GetValue(pc) as SkillListTableData[];
var cur = typeof(Actor).GetProperty("CurAnim", BF).GetValue(pc, null);
var mid = typeof(Actor).GetField("m_ID", BF).GetValue(pc);
var magic = typeof(Actor).GetField("m_Magic", BF).GetValue(pc);
sb.Append("class=").Append(mid).Append(" curAnim=").Append(cur).Append(" m_Magic=").Append(magic != null ? "set" : "null");
if (arr != null) for (int i = 0; i < 2 && i < arr.Length; i++) sb.Append(" [").Append(i).Append("]=").Append(arr[i] != null ? arr[i].n_SkillID + "/c" + arr[i].n_SkillClassID : "-");
var an = pc.m_animation;
if (an != null) { var ci = an.GetCurrentAnimatorClipInfo(0); sb.Append(" clip=").Append(ci.Length > 0 ? ci[0].clip.name : "?").Append(" ctrl=").Append(an.runtimeAnimatorController != null ? an.runtimeAnimatorController.name : "-"); }
sb.Append("\n slots: ").Append(WL.Combat.Weapon.WLWeaponSkillSlots.LastLog).Append(" applied=").Append(WL.Combat.Weapon.WLWeaponSkillSlots.Applied).Append(" skipped=").Append(WL.Combat.Weapon.WLWeaponSkillSlots.Skipped);
sb.Append("\n objs: shield=").Append(Count<Skill_ShieldAttack>()).Append(" fatal=").Append(CountByName("Skill_FatalBlow")).Append(" dash=").Append(Count<Skill_DashSlash>()).Append(" jump=").Append(CountByName("Skill_JumpAttack"));
sb.Append(" | SkillCast=").Append(WL.Combat.Core.CombatEvents.SkillCast.Raised).Append(" HitConfirmed=").Append(WL.Combat.Core.CombatEvents.HitConfirmed.Raised);
return sb.ToString();
}
static int Count<T>() where T : Object { return Object.FindObjectsByType<T>(FindObjectsInactive.Include, FindObjectsSortMode.None).Length; }
/// <summary>#883 비수 시너지(힘민지 단검 투척) 발사 수 · 마지막 · 단검 투사체 수(켜진 것/전체) · 파츠 스킬 요약.</summary>
public static object HmInfo()
{
int on = 0; foreach (var d in Object.FindObjectsByType<Skill_DaggerThrow>(FindObjectsInactive.Exclude, FindObjectsSortMode.None)) on++;
return "hm shots=" + WL.PartSkill.SkWeaponSyn.HmShots + " last=" + WL.PartSkill.SkWeaponSyn.HmLast + " daggers on=" + on + "/" + Count<Skill_DaggerThrow>()
+ " | state: " + WL.PartSkill.WLPartSkillState.LastLog + " | runner: " + WL.PartSkill.WLPartSkillRunner.LastLog;
}
static int CountByName(string typeName)
{
var t = System.Type.GetType(typeName + ", Assembly-CSharp");
if (t == null) return -1;
return Object.FindObjectsByType(t, FindObjectsInactive.Include, FindObjectsSortMode.None).Length;
}
/// <summary>스킬 1번 칸을 지금 바로 쓴다(자동 시전 대기 없이 · 대상 필요).</summary>
public static object CastSlot(int index)
{
var pc = MyValue.MyPC; if (pc == null) return "PC 없음";
var arr = typeof(PCActor).GetField("arr_magicData", BF).GetValue(pc) as SkillListTableData[];
if (arr == null || index < 0 || index >= arr.Length || arr[index] == null) return "슬롯 비어 있음 " + index;
bool ok = pc.Use_Skill(arr[index], true, index);
return "Use_Skill(" + arr[index].n_SkillID + ") = " + ok;
}
/// <summary>캡처용 — 오류를 화면 팝업으로 띄우는 원본 장치(ErrorLogHookManager)를 잠시 끄고/켠다(오류는 콘솔에 그대로 남는다) + 떠 있는 팝업 닫기.</summary>
public static object ErrHook(bool on)
{
var go = GameObject.Find("ErrorLogHookManager");
if (go != null) go.SetActive(on);
int closed = 0;
try { if (!on && Popup.Ins != null && Popup.Ins.gameObject.activeInHierarchy) { Popup.Ins.OnClick_OK(); closed++; } } catch { }
return "ErrorLogHookManager " + (go != null ? (on ? "켬" : "끔") : "없음") + " · 팝업 닫음 " + closed;
}
/// <summary>캡처용 — 힘민지 선택 스킬 · 표에 없는 스킬 효과를 PC 에 바로 띄운다(InGameInfo.Shoot_Effect · 스탯 · UI 반영 없음).</summary>
public static object SelectFx(string effectName)
{
var pc = MyValue.MyPC; if (pc == null) return "PC 없음";
eEffect e;
if (!System.Enum.TryParse(effectName, out e)) return "eEffect 없음 " + effectName;
var ptd = new ProjectileData { m_Skill = e, shooter = pc };
if (e == eEffect.Select_LeafFairy) ptd.eStartPos = eProjectileStartPos.ShooterCenter;
try { InGameInfo.Ins.Shoot_Effect(ptd); } catch (System.Exception ex) { return "실패 " + e + " — " + ex.Message; }
return "shoot " + e;
}
/// <summary>캡처 사이 정리 — 이름이 prefix 로 시작하는 스킬 투사체를 끈다.</summary>
public static object ProjClear(string prefix)
{
int n = 0;
var off = typeof(ProjectileBase).GetMethod("Off", BindingFlags.Instance | BindingFlags.NonPublic);
foreach (var pb in Object.FindObjectsByType<ProjectileBase>(FindObjectsInactive.Exclude, FindObjectsSortMode.None))
{
var d = pb.Get_ProjectTileData(); if (d == null || !d.m_Skill.ToString().StartsWith(prefix)) continue;
try { off.Invoke(pb, new object[] { true, false }); } catch { pb.gameObject.SetActive(false); }
n++;
}
return "off " + n;
}
/// <summary>캡처용 — 무기 그룹의 직업 값을 메모리(공격 표 사본)에서만 바꾼다 → 무기 직업 적용기가 다음 폴링에 PC 직업을 바꾼다(파일 무수정 · Play 끝나면 원래대로).</summary>
public static object SetClass(int weaponId, int classId)
{
var steps = WL.Combat.Weapon.WLWeaponAttackTable.Steps(weaponId);
if (steps == null) return "공격 표에 없음 " + weaponId;
int before = steps[0].classId;
foreach (var s in steps) s.classId = classId;
return weaponId + " 직업 " + before + " → " + classId;
}
/// <summary>쿨 · MP 무시 시험 시전(Use_Skill testskill) — 슬롯 index 의 스킬 또는 skillId(>0)의 표 스킬(직업 칸은 PC 직업으로 맞춘 복사본).</summary>
public static object CastTest(int index, int skillId)
{
var pc = MyValue.MyPC; if (pc == null) return "PC 없음";
SkillListTableData data;
if (skillId > 0)
{
var src = table_skilllist.Ins.Get_Data_orNull(skillId); if (src == null) return "표에 없음 " + skillId;
data = (SkillListTableData)typeof(object).GetMethod("MemberwiseClone", BindingFlags.Instance | BindingFlags.NonPublic).Invoke(src, null);
data.n_SkillClassID = (int)typeof(Actor).GetField("m_ID", BF).GetValue(pc);
data.n_MP = 0;
}
else
{
var arr = typeof(PCActor).GetField("arr_magicData", BF).GetValue(pc) as SkillListTableData[];
data = arr != null && index >= 0 && index < arr.Length ? arr[index] : null;
if (data == null) return "슬롯 비어 있음 " + index;
}
bool ok = pc.Use_Skill(data, true, index, true);
return "Use_Skill(test " + data.n_SkillID + " " + data.e_Skill + " anim=" + data.s_Animation + ") = " + ok;
}
}