// WL879_PartSkillAssets.cs — PD 지시 #879 장비 파츠 스킬 : 보유 VFX · 아이콘 → Resources 복사 + 무기 발동형 스킬 켜기(에디터 전용) // unity command run_script --file AgentScripts/WL879_PartSkillAssets.cs --entry WL879_PartSkillAssets.Run // // 표 = Tools/PartSkill/partskill_assets.json(C45 — 원본 경로 · 대상 폴더는 표에만). 이미 있으면 건너뛴다(force 1 이면 덮어씀). // 무기 설정: WLWeaponSettings 에셋이 없으면(지금 = 기본값 인스턴스) 기본값으로 만들고 weaponSkills 만 표 값으로 둔다(PD 10-16 「기존 무기 스킬 유지」). using System.Collections.Generic; using System.IO; using System.Text; using UnityEngine; using UnityEditor; public static class WL879_PartSkillAssets { const string kTable = "Tools/PartSkill/partskill_assets.json"; public static object Run() { var sb = new StringBuilder(); string root = Directory.GetParent(Application.dataPath).FullName; string tablePath = Path.Combine(root, kTable); if (!File.Exists(tablePath)) return "표 없음: " + tablePath; var t = Newtonsoft.Json.Linq.JObject.Parse(File.ReadAllText(tablePath)); bool force = (int?)t["force"] == 1; var forceKeys = new HashSet(); var fk = t["forceKeys"] as Newtonsoft.Json.Linq.JArray; if (fk != null) foreach (var x in fk) forceKeys.Add((string)x); string fxDst = (string)t["fxDst"], iconDst = (string)t["iconDst"]; EnsureFolder(fxDst); EnsureFolder(iconDst); int copied = 0, skipped = 0, missing = 0; foreach (var kind in new[] { "fx", "icons" }) { var map = t[kind] as Newtonsoft.Json.Linq.JObject; if (map == null) continue; foreach (var kv in map) { string src = (string)kv.Value; string ext = Path.GetExtension(src); string dst = (kind == "fx" ? fxDst : iconDst) + "/" + kv.Key + ext; if (AssetDatabase.LoadMainAssetAtPath(src) == null) { missing++; sb.AppendLine("원본 없음 " + kv.Key + " ← " + src); continue; } if (AssetDatabase.LoadMainAssetAtPath(dst) != null) { if (!force && !forceKeys.Contains(kv.Key)) { skipped++; continue; } AssetDatabase.DeleteAsset(dst); } if (AssetDatabase.CopyAsset(src, dst)) copied++; else { missing++; sb.AppendLine("복사 실패 " + kv.Key); } } } AssetDatabase.SaveAssets(); AssetDatabase.Refresh(); sb.AppendLine("복사 " + copied + " · 건너뜀 " + skipped + " · 실패 " + missing); // 아이콘 = 스프라이트(원본이 이미 Sprite 면 그대로 · 아니면 바꾼다) var iconMap = t["icons"] as Newtonsoft.Json.Linq.JObject; int fixedType = 0; if (iconMap != null) foreach (var kv in iconMap) { string dst = iconDst + "/" + kv.Key + Path.GetExtension((string)kv.Value); var ti = AssetImporter.GetAtPath(dst) as TextureImporter; if (ti != null && (ti.textureType != TextureImporterType.Sprite || ti.spriteImportMode != SpriteImportMode.Single)) { ti.textureType = TextureImporterType.Sprite; ti.spriteImportMode = SpriteImportMode.Single; ti.SaveAndReimport(); fixedType++; } } sb.AppendLine("아이콘 스프라이트 보정 " + fixedType); // 무기 발동형 스킬 켜기 var ws = t["weaponSettings"]; if (ws != null) { string path = (string)ws["path"]; int on = (int?)ws["weaponSkills"] ?? 1; var so = AssetDatabase.LoadAssetAtPath(path); if (so == null) { EnsureFolder(Path.GetDirectoryName(path).Replace('\\', '/')); so = ScriptableObject.CreateInstance(); so.weaponSkills = on; AssetDatabase.CreateAsset(so, path); sb.AppendLine("무기 설정 에셋 생성(기본값 + weaponSkills=" + on + ") " + path); } else if (so.weaponSkills != on) { so.weaponSkills = on; EditorUtility.SetDirty(so); sb.AppendLine("무기 설정 weaponSkills → " + on); } else sb.AppendLine("무기 설정 유지(weaponSkills=" + so.weaponSkills + ")"); AssetDatabase.SaveAssets(); } var chk = Resources.Load("WL/PartSkill/Fx/fx_sigil"); sb.AppendLine("Resources.Load fx_sigil=" + (chk != null ? "ok" : "없음")); return sb.ToString(); } static void EnsureFolder(string path) { if (string.IsNullOrEmpty(path) || AssetDatabase.IsValidFolder(path)) return; string parent = Path.GetDirectoryName(path).Replace('\\', '/'); EnsureFolder(parent); AssetDatabase.CreateFolder(parent, Path.GetFileName(path)); } }