Project_WL/AgentScripts/WL826_WarriorPackMapping.cs

253 lines
24 KiB
C#
Raw Permalink Blame History

This file contains ambiguous Unicode characters

This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

// WL826_WarriorPackMapping.cs — 무기 계열별 공격 모션을 ExplosiveLLC Warrior Pack Super Bundle 로 교체 (매핑 에셋 재작성 · 에디터 1회)
// PD 2026-10-09 「Warrior Pack Super Bundle 을 설치했어 — 무기별 모션을 이 에셋 모션으로 교체」
// 검 = Knight · 망치 = Hammer · 단검 = Ninja · 활 = Archer · 지팡이 = Mage (창 = 번들에 창 팩이 없어 Shinabro 유지 · 2Handed 는 대안)
// v2(23:5x · PD 「일부 모션이 제대로 안 보인다」): 타격 시점 = 팩 FBX 에 구워진 Hit 이벤트 시각(정규화 · 실측) · 전이 exit = 앞 클립 Hit + 0.35(0.55~0.90)
// 이 스크립트는 CombatAnimMapping.asset 의 행만 다시 쓴다. 실제 서브클립·이벤트·컨트롤러 교체는 기존 도구가 한다:
// unity command run_script --file AgentScripts/WL826_WarriorPackMapping.cs --entry WL826_WarriorPackMapping.Run --timeout 120
// unity command run_script --file AgentScripts/WL_CombatAnimSetup.cs --entry WL_CombatAnimSetup.Run --args '[["apply"]]' --timeout 500
using System.Collections.Generic;
using System.IO;
using System.Text;
using UnityEditor;
using UnityEngine;
using WL.Combat;
public static class WL826_WarriorPackMapping
{
const string MappingPath = "Assets/WL/Combat/CombatAnimMapping.asset";
const string Root = "Assets/ExplosiveLLC/";
const string K = Root + "Knight Warrior Mecanim Animation Pack/Animations/Knight@";
const string H = Root + "Hammer Warrior Mecanim Animation Pack/Animations/Hammer@";
const string N = Root + "Ninja Warrior Mecanim Animation Pack/Animations/Ninja@";
const string A = Root + "Archer Warrior Mecanim Animation Pack/Animations/Archer@";
const string M = Root + "Mage Warrior Mecanim Animation Pack/Animations/Mage@";
// #838 대검 = 2Handed Warrior 팩 · 활 = FR(FirstRising) 휴머노이드 .anim 사본(Assets/WL/Combat/Anim/FR/ · 원본 C:\BurningTimes\FirstRising\Assets\Animation\Player\Weapon\Bow0~4.anim)
const string T = Root + "2 Handed Warrior Mecanim Animation Pack/Animations/2Handed@";
const string FR = "Assets/WL/Combat/Anim/FR/";
public const string GreatswordCtrl = "Assets/Res_Addr/Animations/pcanim_greatsword.controller";
// 팩 FBX 임포터의 원본 클립 Hit 이벤트 시각(정규화 · 2026-10-09 23:5x 실측 · 없는 클립은 0.45 가정)
const float K1 = 0.449f, K2 = 0.350f, K3 = 0.374f;
// #838 2Handed 팩 Attack1_S/2_S/3_S Hit 실측(임포터 원본 이벤트 · 2026-10-11)
const float T1 = 0.479f, T2 = 0.504f, T3 = 0.468f;
// #838 FR 활 클립(Bow0~4 = 동일 모션 · 0.8 s) — 양손 거리 실측(WL838_BowRelease): 당김 최대 f21(0.87) → 시위 놓음 f22~23(0.92) → 발사 0.92 · 다음 타 진입은 클립 끝(0.98)
const float B1 = 0.92f, BExit = 0.98f;
// #839 활 3타 — 기 모으기 이벤트 0.40(당김 구간 f6~f21 안). #840 PD 「발사 전까지 활시위 당김 유지」 → 이벤트부터 1.2 s 동안 애니메이터 0.35배(당김 자세 유지) 뒤 원속 → 발사 0.92 는 그 뒤. 3타 상태 속도는 원속(1.0).
// #843 PD 「조준이 끝난 직후 바로 발사」 — 유지(0.6 s · 속도 0.35)는 클립을 0.21 s = 0.2625 만큼 진행시키므로 발사 0.92 에서 역산한 0.66 에 시작 → 유지가 끝나는 프레임이 곧 발사 프레임(이전 0.40 은 0.2 s 더 기다렸다)
const float BCharge = 0.66f, BChargeDur = 0.6f, BSpeed3 = 1.0f; const string BHoldSpeed = "0.35"; // #841 PD 「모아쏘기 딜레이 절반」 유지 1.2 → 0.6 s · BSpeed3 1.0 = 원속(유지는 WLBowCharge)
// #839 해머 1타 재생 배율(PD 「첫 타 공격 속도를 좀 더 빠르게」) · #840 3타 진입 exit 0.55 + 3타 재생 1.3(2→3 딜레이 단축)
const float HS1 = 1.3f, HX3 = 0.55f, HS3 = 1.3f;
// #839 마법(소서리스) — Mage@Attack2_S 18~64f · 투사체 f41(0.504): 발사 구간 34~64f(31f · 1.03 s · 투사체 (41-34)/30 = 0.23) · 3타 진입 exit 0.85
const int MFirst = 34, MLast = 64; const float MF = 0.23f, MExit = 0.85f;
// #839 2Handed 4타·스킬 — MoveAttack1_S Hit 0.568 · SpecialAttack1(Hit 이벤트 없음 · 포즈 띠 찌르기 f5~9/10 → 0.50) · Run2-Attack1(0.53 s · 0.40 추정)
const float T4 = 0.568f, TSk1 = 0.50f, TSk2 = 0.40f;
// #839 Spearman 팩 Hit 실측(임포터 원본 이벤트): Attack1 0.439 · Attack2_S 0.425 · Attack3_S 0.523(Land 0.48)
const string SP = Root + "Spearman Warrior Mecanim Animation Pack/Animations/Spearman@";
const float SP1 = 0.439f, SP2 = 0.425f, SP3 = 0.523f;
// #840 창 2타 = Attack2_S(23~60f · Hit f38.7) 찌르기 구간 33~46f(14f · 0.47 s) → 타격 (38.7-33)/13 = 0.44 · 3연속(Attack2·2b·2c) · 재생 1.2배 · 다음 진입 exit 0.9
const int SPcFirst = 33, SPcLast = 46; const float SPc = 0.44f, SPcSpeed = 1.5f, SPcExit = 0.9f; // PD 「찌르기 모션을 매우 빠르게 3회」 → 1.5배(한 번 0.31 s · 3번 ≈ 0.95 s)
const float H1 = 0.370f, H2 = 0.422f, H3 = 0.448f;
const float N1 = 0.237f, N2 = 0.407f, N3 = 0.203f;
const float A1 = 0.393f, A2 = 0.45f, A3 = 0.45f;
const float M1 = 0.504f, M2 = 0.407f;
static AnimEventSpec Ev(string fn, float t, string s = "", int i = 0, float f = 0f)
{
return new AnimEventSpec { functionName = fn, useNormalized = true, normalizedTime = Mathf.Clamp01(t), time = 0f, stringParameter = s, intParameter = i, floatParameter = f };
}
// #828 검 — 베기 이펙트(ShowEffect)는 「실측 스윙 시작 프레임」에 둔다(2026-09-07 #804 · 09-15 #816v 와 같은 규칙).
// WL828_TrailBake 실측(60 Hz · 속도 트림 창 시작): Attack1 f12/50 → 0.24 · Attack2 f14/52 → 0.269 · Attack3 f16/64 → 0.25
// (Hit−0.12 규칙은 2타를 스윙보다 4프레임 앞서 띄웠다 → 호가 칼보다 먼저 돈다)
// #841 1타 정정: 60 Hz 전수 덤프(WL828 ProbeDump)로 보면 f12~f17 은 칼을 머리 뒤로 감아올리는 구간이고 실제 내려베기는 f16→f22(0.267→0.367 s · 한 샘플당 0.83~0.93 m 이동).
// ShowEffect = 베기 시작 f16/50 = 0.32 (Hit 0.449 = 베기 끝 f22 직후).
const float KS1 = 0.32f, KS2 = 0.269f, KS3 = 0.25f;
// #834 비수 3타 — 2타 타격(0.407) 직후 진입 · 재생 1.3배
const float DS3 = 0.5f, DS3Speed = 1.3f;
// #838 비수 4타(DualBlades_DodgeAttack · 원본 힘민지 클립) — 원본 이벤트 시각 유지(ShowEffect 0.155 · Projectile 0.186) · 진입 exit 0.55 · 재생 1.5배
const string AS = "Assets/Res_Addr/Animations/Animation/Assassin/";
const float D4 = 0.186f, D4Show = 0.155f, D4Exit = 0.55f, D4Speed = 1.5f;
/// <summary>근접 — 팩 Hit 시각 기준: 베기 이펙트 = Hit−0.12(showAt 지정 시 그 값) · 전진 = Hit−0.06 · 판정 = Hit · 2·3타는 LookAtTarget.</summary>
static List<AnimEventSpec> Melee(int step, float hit, float move, float showAt = -1f, int effectCid = 0)
{
var l = new List<AnimEventSpec>();
if (step > 1) l.Add(Ev("LookAtTarget", 0f));
// effectCid > 0 = 베기 이펙트·타격 상자 이름을 **템플릿 직업** 것으로(#838 대검 10801 → Effect_Slash_10101_N · Projectile_10101 · 창 10701 과 같은 재사용 규칙).
// WL 추가 직업은 템플릿 행을 복제해 들어가므로 투사체 사전(dic_projectile)에는 템플릿 이름만 있다 — Projectile_10801 로 쓰면 KeyNotFound(2026-10-11 실측 18건).
string cid = effectCid > 0 ? effectCid.ToString() : "{CID}";
l.Add(Ev("ShowEffect", showAt >= 0f ? showAt : Mathf.Max(0.05f, hit - 0.12f), "Effect_Slash_" + cid + "_" + step, 1));
if (move > 0f) l.Add(Ev("Move", Mathf.Max(0.05f, hit - 0.06f), "", 0, move));
l.Add(Ev("Projectile", hit, "Projectile_" + cid));
return l;
}
/// <summary>원거리(활·지팡이) — 조준 뒤 발사만.</summary>
static List<AnimEventSpec> Ranged(float hit)
{
return new List<AnimEventSpec> { Ev("LookAtTarget", 0f), Ev("Projectile", hit, "Projectile_{CID}") };
}
/// <summary>#839 활 3타 — 조준 → 기 모으기(WLBowCharge · float = 유지 초 · string = 유지 중 속도 #840) → 발사(당김 유지가 끝난 뒤 클립 진행대로).</summary>
static List<AnimEventSpec> RangedCharged(float hit)
{
return new List<AnimEventSpec> { Ev("LookAtTarget", 0f), Ev("WLBowCharge", BCharge, BHoldSpeed, 0, BChargeDur), Ev("Projectile", hit, "Projectile_{CID}") };
}
/// <summary>#838 대기 클립 — 힘민지 원본 대기 클립은 첫 프레임에 Event_Idle(논리 CurAnim 초기화)을 갖는다. 팩 Idle(Knight@Idle·Mage@Idle)로 바꾼 직업은 이 이벤트가 없어
/// 콤보 뒤 CurAnim 이 Attack 에 굳고(Play_Attack 가드) 두 번째 콤보가 안 나간다(2026-10-11 해머 실측: 애니메이터 idle · 논리 Attack). 서브클립에 되살린다.</summary>
static List<AnimEventSpec> IdleEv() { return new List<AnimEventSpec> { Ev("Event_Idle", 0f) }; }
/// <summary>앞 클립의 Hit 뒤 0.35 지점에서 다음 타로 넘어간다(0.55~0.90) — 타격과 뒤따르는 동작이 보이게.</summary>
static float Exit(float prevHit) { return Mathf.Clamp(prevHit + 0.35f, 0.55f, 0.90f); }
static StateClipSpec St(string state, string fbx, string sub, List<AnimEventSpec> ev, float incomingExit = 0f, float speed = 0f)
{
return new StateClipSpec { stateName = state, sourceFbxPath = fbx, subClipName = sub, sourceClipName = "", incomingExitTime = incomingExit, createIfMissing = false, speed = speed, events = ev };
}
/// <summary>#839 프레임 범위 지정(마법 발사 구간만 등) + 상태 신설(create) + 원본 클립 이름 지정.</summary>
static StateClipSpec StR(string state, string fbx, string sub, List<AnimEventSpec> ev, int first, int last, float incomingExit = 0f, float speed = 0f, bool create = false, string srcClip = "")
{
var s = St(state, fbx, sub, ev, incomingExit, speed);
s.firstFrame = first; s.lastFrame = last; s.createIfMissing = create; s.sourceClipName = srcClip;
return s;
}
/// <summary>#839 스킬 상태 — 힘민지 원본 스킬 클립 규약: SkillEvent(int 0) = 타격/발사 · (dashslash) ShowEffect Effect_Teleport i3 @0 · (combo01) SkillEvent@0 + Del_Magic@0.67.</summary>
static List<AnimEventSpec> Skill(float hit, bool teleport = false, bool delMagicAt067 = false)
{
var l = new List<AnimEventSpec>();
if (teleport) l.Add(Ev("ShowEffect", 0f, "Effect_Teleport", 3));
l.Add(Ev("SkillEvent", hit));
if (delMagicAt067) l.Add(Ev("Del_Magic", 0.67f));
return l;
}
static ClassCombatAnimSpec Row(int cid, string note, params StateClipSpec[] states)
{
var r = new ClassCombatAnimSpec { classId = cid, note = note, enabled = true, controllerPathOverride = "" };
r.states = new List<StateClipSpec>(states);
return r;
}
/// <summary>ClassConfig 에 없는 WL 추가 직업(대검 10801 등) — 컨트롤러 경로를 직접 준다.</summary>
static ClassCombatAnimSpec RowC(int cid, string ctrlPath, string note, params StateClipSpec[] states)
{
var r = Row(cid, note, states);
r.controllerPathOverride = ctrlPath;
return r;
}
public static string Run()
{
var mapping = AssetDatabase.LoadAssetAtPath<CombatAnimMapping>(MappingPath);
if (mapping == null) return "매핑 에셋 없음 " + MappingPath;
foreach (var p in new[] { K + "Attack1_S.FBX", H + "Attack1_S.FBX", N + "Attack1_S.FBX", A + "Attack1_S.FBX", M + "Attack2_S.FBX" })
if (AssetDatabase.LoadAssetAtPath<Object>(p) == null) return "팩 FBX 없음 " + p;
string bak;
try
{
string dir = Path.Combine(Path.GetDirectoryName(Application.dataPath), "AgentScripts/staging/_backup_WarriorPack_" + System.DateTime.Now.ToString("yyyyMMdd_HHmm"));
Directory.CreateDirectory(dir);
File.Copy(MappingPath, Path.Combine(dir, "CombatAnimMapping.asset"), true);
bak = dir;
}
catch (System.Exception ex) { bak = "백업 실패 " + ex.Message; }
var rows = new List<ClassCombatAnimSpec>
{
Row(10101, "검 · OneHand → Knight Warrior pack Attack1~3_S (Hit 실측 시각 · ShowEffect = 실측 스윙 시작 #828)",
St("attack", K + "Attack1_S.FBX", "Attack1_S_{CID}", Melee(1, K1, 0.3f, KS1)),
St("Attack2", K + "Attack2_S.FBX", "Attack2_S_{CID}", Melee(2, K2, 0.15f, KS2), Exit(K1)),
St("Attack3", K + "Attack3_S.FBX", "Attack3_S_{CID}", Melee(3, K3, 0.31f, KS3), Exit(K2))),
Row(10102, "검(마검) · SpellBlade → Knight Warrior pack (MoveAttack1 4타는 현행 유지 · ShowEffect = 실측 스윙 시작 #828)",
St("attack", K + "Attack1_S.FBX", "Attack1_S_{CID}", Melee(1, K1, 0.3f, KS1)),
St("Attack2", K + "Attack2_S.FBX", "Attack2_S_{CID}", Melee(2, K2, 0.15f, KS2), Exit(K1)),
St("Attack3", K + "Attack3_S.FBX", "Attack3_S_{CID}", Melee(3, K3, 0.31f, KS3), Exit(K2))),
// #838 PD 「둔기(해머) 공격 모션은 2타와 3타의 순서를 바꿔줘」 — 상태 Attack2 ← 팩 Attack3_S(회전 공격 · Hit H3) · 상태 Attack3 ← 팩 Attack2_S(Hit H2).
// 서브클립 이름(Attack2_S_{CID} 등)은 상태 기준으로 유지한다(프레임 표·검기 행 키가 상태 이름을 따르므로) → 표·검기 행은 재베이크.
// #839 PD 「현재 3타(팩 Attack2) → 1타 · 현재 1타(팩 Attack1) → 2타 · 현재 2타(팩 Attack3 회전) → 3타 · 첫 타 속도 더 빠르게」 → 1타 재생 1.3배
// #840 PD 「2타→3타 딜레이가 너무 크다」 — 3타(회전) 진입 exit 0.72 → 0.55(2타 타격 0.37 직후) · 3타 재생 1.3배(회전 감아올리기 단축). 2타 타격→3타 타격 1.49 → ≈0.9 s
Row(10501, "망치 · BluntShield → Hammer pack Attack2_S(1타 ×1.3) · Attack1_S(2타) · Attack3_S(3타 회전 ×1.3 · 빠른 진입) (#839 재배열 · #840 2→3 단축 · 대기 Event_Idle)",
St("idle", K + "Idle.FBX", "Idle_S_{CID}", IdleEv()),
St("attack", H + "Attack2_S.FBX", "Attack1_S_{CID}", Melee(1, H2, 0.15f), 0f, HS1),
St("Attack2", H + "Attack1_S.FBX", "Attack2_S_{CID}", Melee(2, H1, 0.3f), Exit(H2)),
St("Attack3", H + "Attack3_S.FBX", "Attack3_S_{CID}", Melee(3, H3, 0.31f), HX3, HS3)),
Row(10502, "망치 · Paladin → Hammer pack (상태명 Sword&Shield_Attack2/3 · #839 재배열 · 1타 ×1.3 · #840 2→3 단축)",
St("attack", H + "Attack2_S.FBX", "Attack1_S_{CID}", Melee(1, H2, 0.15f), 0f, HS1),
St("Sword&Shield_Attack2", H + "Attack1_S.FBX", "Attack2_S_{CID}", Melee(2, H1, 0.3f), Exit(H2)),
St("Sword&Shield_Attack3", H + "Attack3_S.FBX", "Attack3_S_{CID}", Melee(3, H3, 0.31f), HX3, HS3)),
// #834 PD 「비수 3타는 더 빠르게 발동되고 전진하며」 — 3타 진입 exit 0.5(2타 타격 0.407 직후) · 3타 재생 속도 1.3 · 전진은 프레임 표(Attack3_S_102 ×1.6)
// #838 PD 「단검(비수) 마지막 4타가 너무 느리게 동작 → 더 빠르게 발동」 — 4타 = 컨트롤러 체인 끝의 DualBlades_DodgeAttack(원본 힘민지 클립 · 1.167 s · 타격 0.186).
// 3타→4타 진입 exit 0.786 → 0.55(3타 타격 0.203 뒤 충분) · 4타 재생 1.5배. 이벤트는 원본 시각 유지(ShowEffect 0.155 · Projectile 0.186 · 검기 행 `_4` 그대로).
Row(10202, "단검 · Assassin → Ninja Warrior pack Attack1~3_S (3타 빠른 발동·속도 1.3 #834 · 4타 DodgeAttack 빠른 발동 #838)",
St("attack", N + "Attack1_S.FBX", "Attack1_S_{CID}", Melee(1, N1, 0.2f)),
St("DualBlades_Attack2", N + "Attack2_S.FBX", "Attack2_S_{CID}", Melee(2, N2, 0.1f), Exit(N1)),
St("DualBlades_Attack3", N + "Attack3_S.FBX", "Attack3_S_{CID}", Melee(3, N3, 0.2f), DS3, DS3Speed),
St("DualBlades_DodgeAttack", AS + "Stander@DualBlades_DodgeAttack_Attack4.FBX", "Attack4_S_{CID}", Melee(4, D4, 0.3f, D4Show), D4Exit, D4Speed)),
Row(10201, "단검 · BladeDancer → Ninja Warrior pack (3타 빠른 발동·속도 1.3 #834)",
St("attack", N + "Attack1_S.FBX", "Attack1_S_{CID}", Melee(1, N1, 0.2f)),
St("DualBlades_Attack2", N + "Attack2_S.FBX", "Attack2_S_{CID}", Melee(2, N2, 0.1f), Exit(N1)),
St("DualBlades_Attack3", N + "Attack3_S.FBX", "Attack3_S_{CID}", Melee(3, N3, 0.2f), DS3, DS3Speed)),
// #834 PD 「활시위를 당기는 게 아니라 던지는 느낌」 — 2·3타에 쓰던 MoveAttack(달리며 쏘기 · 제자리 판)이 원인의 절반 → 3타 전부 서서 쏘는 Attack1_S.
// 나머지 절반(활이 팔 방향으로 누움)은 WLWeaponClasses.json weaponOrient(활 X+90°)가 런타임에 바로잡는다.
// #838 PD 「활 공격 모션은 FR 프로젝트의 활 공격 모션으로 대체」 — FR Bow0~4 는 수치 동일(한 모션) → 3타 전부 FR_Bow0 사본(.anim · 이벤트 초 단위). 활 X+90° 보정(weaponOrient)은 그대로.
// #839 PD 「3발 중 마지막 타 = 활에 기가 모이는 임팩트 후 더 큰 화살」 — 3타 클립에 WLBowCharge 이벤트(당김 시작 0.40 · 지속 = float) · 재생 0.85배(모았다 쏘는 느낌) · 발사는 그대로 0.92.
// 수신 = Assets/WL/Combat/Weapon/WLBowCharge.cs(PC 루트에 런타임 부착 · 활 소켓에 기 모으기 VFX · 다음 화살 = 1.6배 + 글로우 · WLProjectileVisual chargedVisual).
Row(10402, "활 · Archer → FR Bow 모션 ×3 (#838) · 3타 기 모으기 + 큰 화살 (#839)",
St("attack", FR + "FR_Bow0.anim", "FR_Bow1_{CID}", Ranged(B1)),
St("Bow_Attack2", FR + "FR_Bow0.anim", "FR_Bow2_{CID}", Ranged(B1), BExit),
St("Bow_Attack3", FR + "FR_Bow0.anim", "FR_Bow3_{CID}", RangedCharged(B1), BExit, BSpeed3)),
Row(10401, "활 · RookieArcher → FR Bow 모션 ×3 (#838) · 3타 기 모으기 (#839)",
St("attack", FR + "FR_Bow0.anim", "FR_Bow1_{CID}", Ranged(B1)),
St("Bow_Attack2", FR + "FR_Bow0.anim", "FR_Bow2_{CID}", Ranged(B1), BExit),
St("Bow_Attack3", FR + "FR_Bow0.anim", "FR_Bow3_{CID}", RangedCharged(B1), BExit, BSpeed3)),
// #839 PD 「마법: 1타 = 투사체 발사 모션만 · 2타 = 투사체 · 3타 = 손 드는 동작(현재 1타 앞부분) 뒤 투사체」 — Mage 팩 Attack2_S(18~64f · 발사 f41)를 발사 구간(34~64f)과 전체로 나눠 3상태.
// 소서리스(PD 지팡이 1071 → 10302) 컨트롤러는 attack 뿐 → attack2·attack3 신설(도구가 직전 상태 전이를 걷고 체인 연결 · attack→Atk_A1_wing 전이는 폐기).
// #840 PD 「지팡이 3타 동작이 너무 어색 → 다른 마법사 모션으로」 — 팩 후보 4종 포즈 띠 비교: Attack3_S(Cast2 · 지팡이를 앞으로 겨눠 쏘고 크게 휘두름 · 1.17 s · Hit 0.407) 채택.
// #841 PD 「지팡이 2타와 3타 위치 교체」 → attack2 = Attack3_S(Cast2) · attack3 = 발사 구간
Row(10302, "지팡이 · Sorceress → 발사 구간(1타) · Attack3_S Cast2(2타) · 발사 구간(3타) (#839 체인 · #840 Cast2 · #841 2↔3)",
StR("attack", M + "Attack2_S.FBX", "CastFire1_S_{CID}", Ranged(MF), MFirst, MLast),
StR("attack2", M + "Attack3_S.FBX", "Cast2_S_{CID}", Ranged(M2), 48, 83, MExit, 0f, true),
StR("attack3", M + "Attack2_S.FBX", "CastFire2_S_{CID}", Ranged(MF), MFirst, MLast, MExit, 0f, true)),
Row(10301, "지팡이 · Mage → Mage Warrior pack Attack2_S / Attack3_S (#838 대기 Event_Idle 복원)",
St("idle", M + "Idle.FBX", "Idle_S_{CID}", IdleEv()),
St("attack", M + "Attack2_S.FBX", "Cast1_S_{CID}", Ranged(M1)),
St("attack2", M + "Attack3_S.FBX", "Cast2_S_{CID}", Ranged(M2), Exit(M1))),
Row(10303, "지팡이 · Summoner → Mage Warrior pack Attack2_S (#838 대기 Event_Idle 복원)",
St("idle", M + "Idle.FBX", "Idle_S_{CID}", IdleEv()),
St("attack", M + "Attack2_S.FBX", "Cast1_S_{CID}", Ranged(M1))),
// #838 PD 「대검 아이템 + 대검 모션(2Handed Warrior)을 쓰는 공격 타입 추가」 — WL 추가 직업 10801(한손검 컨트롤러 복제 pcanim_greatsword · WL838_GreatswordSetup).
// 베기 이펙트 이름은 창(10701)과 같은 규칙으로 템플릿 한손검 것(Effect_Slash_10101_N)을 재사용 → 검기 행은 (10801, 그 이름) 키로 베이크.
// #839 PD 「대검 마지막 4타 추가 + 액티브 스킬 모션 적용」 — 4타 = MoveAttack1_S(돌진 베기 · Hit 0.568 · 상태 Attack4 신설) · 스킬 = 한손검 스킬 상태 3종(fatalblow·dashslash·combo01)에 2Handed 팩 클립.
// #841 PD 「대검 1타→3타 · 2타→1타 · 3타→2타」 → attack ← 팩 Attack2_S(T2) · Attack2 ← Attack3_S(T3) · Attack3 ← Attack1_S(T1) · 4타(점프) 유지
RowC(10801, GreatswordCtrl, "대검 · Greatsword(WL 10801) → 2Handed Attack2_S(1타) · Attack3_S(2타) · Attack1_S(3타) + 4타 Spearman 점프 + 스킬 3종 (#838 · #839 · #840 · #841 재배열)",
St("attack", T + "Attack2_S.FBX", "Attack1_S_{CID}", Melee(1, T2, 0.15f, -1f, 10101)),
St("Attack2", T + "Attack3_S.FBX", "Attack2_S_{CID}", Melee(2, T3, 0.31f, -1f, 10101), Exit(T2)),
St("Attack3", T + "Attack1_S.FBX", "Attack3_S_{CID}", Melee(3, T1, 0.3f, -1f, 10101), Exit(T3)),
// #840 PD 「대검 4타(MoveAttack1 돌진) 제거 → 창의 3타(Spearman 점프 찌르기)를 대검 4타로」
StR("Attack4", SP + "Attack3_S.FBX", "Attack4_S_{CID}", Melee(4, SP3, 0.5f, -1f, 10101), -1, -1, Exit(T1), 0f, true),
St("fatalblow", T + "SpecialAttack1.FBX", "SkillFatal_S_{CID}", Skill(TSk1)),
St("dashslash", T + "Run2-Attack1.FBX", "SkillDash_S_{CID}", Skill(TSk2, true)),
StR("combo01", T + "Jump-Attack1.FBX", "SkillCombo_S_{CID}", Skill(0f, false, true), -1, -1, 0f, 0f, false, "Jump-Attack1Hit")),
// #839 PD 「창의 모션은 새로 추가한 에셋의 스피어맨 모션으로 대체」 — Shinabro 07_Spear → Spearman Warrior pack Attack1(루트모션 판 · 제자리 재생) · Attack2_S · Attack3_S(점프 찌르기 · Land 0.48 · Hit 0.52).
// 소켓은 메이스 자리 1 유지(포즈 띠 실측: 소켓 2 는 창끝이 뒤). 런타임 json 이벤트(attackClipTokens)는 비움 — 이벤트는 서브클립에 굽는다.
// #840 PD 「3연속 찌르기를 2타에 · 현재 2타 → 1타 · 현재 1타 → 3타」 — 팩·Shinabro 에 3연속 찌르기 클립 없음(포즈 띠 10종 확인) → Attack2_S 의 찌르기 구간(33~46f)을 3연속 상태(Attack2·2b·2c · 1.2배)로 이어 붙임.
RowC(10701, "Assets/Res_Addr/Animations/pcanim_spear.controller", "창 · Spear(WL 10701) → Spearman Attack2_S(1타) · 찌르기 구간 ×3(2타) · Attack1(3타) (#840 재배열)",
St("attack", SP + "Attack2_S.FBX", "Attack1_S_{CID}", Melee(1, SP2, 0.2f, -1f, 10101)),
StR("Attack2", SP + "Attack2_S.FBX", "Attack2_S_{CID}", Melee(2, SPc, 0.1f, -1f, 10101), SPcFirst, SPcLast, Exit(SP2), SPcSpeed),
StR("Attack2b", SP + "Attack2_S.FBX", "Attack2b_S_{CID}", Melee(2, SPc, 0.1f, -1f, 10101), SPcFirst, SPcLast, SPcExit, SPcSpeed, true),
StR("Attack2c", SP + "Attack2_S.FBX", "Attack2c_S_{CID}", Melee(2, SPc, 0.1f, -1f, 10101), SPcFirst, SPcLast, SPcExit, SPcSpeed, true),
St("Attack3", SP + "Attack1.FBX", "Attack3_S_{CID}", Melee(3, SP1, 0.3f, -1f, 10101), SPcExit)),
};
mapping.classes = rows;
mapping.source = "PD 지시 2026-10-09 — 무기 계열별 모션을 ExplosiveLLC Warrior Pack Super Bundle 로 교체(검 Knight · 망치 Hammer · 단검 Ninja · 활 Archer · 지팡이 Mage · 창 = Shinabro 유지). 타격 시점 = 팩 FBX Hit 이벤트 실측(23:5x) · 전이 exit = 앞 Hit + 0.35";
EditorUtility.SetDirty(mapping);
AssetDatabase.SaveAssets();
var sb = new StringBuilder();
sb.Append("매핑 행 ").Append(rows.Count).Append(" 재작성(Hit 시각 반영) · 백업 ").Append(bak).Append(" · 다음 = WL_CombatAnimSetup apply");
return sb.ToString();
}
}