WL #970 PD 지시 3건 — ① 시전 동작이 있는 스킬(스킬 표 s_NextAnimation · f_CastingTime) = 발동(SkillFired)까지 이동 · 구르기 잠금 + 발동 뒤 이동해도 스킵 안 함(WLSkillCancel castLock · 잠금 상한 = holdMaxSeconds + 시전 시간 · 실측 골렘 · 꽃 · 운석 · 블랙홀 발동 전 이동 막음 57 · 57 · 80 · 77 · 스킵 0 · 운석 · 블랙홀 이동 뒤 2.40 · 2.61 s 유지) ② 비수 주력 중 적 순간이동 = 원본 끝 Set_Warp(PC 대상 뒤 1.5 m · 화면 속 적 0.32 튐) + 테스트 씬 더미 자동 복귀(판정이 더미를 2.4~3.6 m 밀어 2.00 · 3.55 m 순간이동) → WLShadowSlash endWarp 0(원본 훅 · 그때 카메라 돌리기도 생략) + WLSkillTest autoResetPauseInSkill 1 · 실측 2회 6 s 튐 0 ③ 마법책 기본 공격 검은 꼬리 → 밝은 보라(WL_Fx_ShootCard helix_dark 시작색 0.08,0.00,0.30 → 0.60,0.38,1.00 · 수명 끝 검정 → 0.70 · 명중 WL_Fx_ShootCardHit smoke 수명 끝 검정 → 0.70)

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
This commit is contained in:
깃 관리자 2026-10-22 19:39:16 +09:00
parent 970e2cfab1
commit a78642d73c
9 changed files with 58 additions and 24 deletions

View File

@ -22,10 +22,11 @@ public class Skill_ShadowSlash : ProjectileBase
if (WL.Combat.Weapon.WLShadowSlash.SkipEnd(_data.shooter)) return; // WL #961 구르기로 캔슬된 시전 — 끝 대기 · 대상 뒤 순간이동 · 연기 · 카메라 돌리기 생략
_data.shooter.Play_Idle();
if (!DSUtil.CheckNull(_data.target))
bool warp = WL.Combat.Weapon.WLShadowSlash.EndWarp(); // WL #970 끝 순간이동 끔(WLShadowSlash.json endWarp 0) — 화면에서 적이 반대편으로 튀던 원인
if (!DSUtil.CheckNull(_data.target) && warp)
_data.shooter.Set_Warp(_data.target.Get_PositionBack(1.5f));
Show_InvisibleEffect();
Show_InvisibleEffect(warp);
});
WL.Combat.Weapon.WLShadowSlash.OnSet(this); // WL #943-⑧ 훅(1줄) — 숨김 직후 렌더러 · 무기 다시 켬 + 베기 · 연기 크기 배율(WLShadowSlash.json) · 무적 · 2.1 초 뒤 순간이동은 원본 그대로
@ -33,13 +34,13 @@ public class Skill_ShadowSlash : ProjectileBase
StartCoroutine(Co_Off(4f));
}
void Show_InvisibleEffect()
void Show_InvisibleEffect(bool turnCam = true) // WL #970 turnCam false = 끝 순간이동을 끈 때 카메라 돌리기도 생략
{
go_invisibleEffect.SetActive(false);
go_invisibleEffect.SetActive(true);
go_invisibleEffect.transform.position = m_ProjecTileData.shooter.Get_position();
if (MyValue.m_RealCamera != null) MyValue.m_RealCamera.RotateCam_TargetBack(); // WL #881 섬(메인 카메라 = FarmingIsland · RealCamera 없음)에서 NRE → 카메라 연출만 건너뜀
if (turnCam && MyValue.m_RealCamera != null) MyValue.m_RealCamera.RotateCam_TargetBack(); // WL #881 섬(메인 카메라 = FarmingIsland · RealCamera 없음)에서 NRE → 카메라 연출만 건너뜀
}
IEnumerator Co_Update()

View File

@ -10056,7 +10056,7 @@ ParticleSystem:
serializedVersion: 2
minMaxState: 0
minColor: {r: 1, g: 1, b: 1, a: 1}
maxColor: {r: 0.0808081, g: 0, b: 0.3018868, a: 1}
maxColor: {r: 0.6, g: 0.38, b: 1, a: 1}
maxGradient:
serializedVersion: 2
key0: {r: 1, g: 1, b: 1, a: 1}
@ -11209,7 +11209,7 @@ ParticleSystem:
maxGradient:
serializedVersion: 2
key0: {r: 1, g: 1, b: 1, a: 1}
key1: {r: 0, g: 0, b: 0, a: 1}
key1: {r: 0.7, g: 0.7, b: 0.7, a: 1}
key2: {r: 0, g: 0, b: 0, a: 0}
key3: {r: 0, g: 0, b: 0, a: 0}
key4: {r: 0, g: 0, b: 0, a: 0}

View File

@ -20383,7 +20383,7 @@ ParticleSystem:
serializedVersion: 2
minMaxState: 0
minColor: {r: 1, g: 1, b: 1, a: 1}
maxColor: {r: 0.8008504, g: 0.5803922, b: 1, a: 1}
maxColor: {r: 0.8, g: 0.58, b: 1, a: 1}
maxGradient:
serializedVersion: 2
key0: {r: 1, g: 1, b: 1, a: 1}
@ -21536,8 +21536,8 @@ ParticleSystem:
maxGradient:
serializedVersion: 2
key0: {r: 1, g: 1, b: 1, a: 0.29411766}
key1: {r: 0, g: 0, b: 0, a: 1}
key2: {r: 1, g: 0.23016784, b: 0, a: 0}
key1: {r: 0.7, g: 0.7, b: 0.7, a: 1}
key2: {r: 0, g: 0, b: 0, a: 0}
key3: {r: 0, g: 0, b: 0, a: 0}
key4: {r: 0, g: 0, b: 0, a: 0}
key5: {r: 0, g: 0, b: 0, a: 0}
@ -21545,7 +21545,7 @@ ParticleSystem:
key7: {r: 0, g: 0, b: 0, a: 0}
ctime0: 9830
ctime1: 32768
ctime2: 52428
ctime2: 0
ctime3: 0
ctime4: 0
ctime5: 0

View File

@ -30,6 +30,8 @@
"slashMatchFx": 1,
"invisibleMatch": 1,
"slashHitEven": 1,
"endWarp": 0,
"_note_970": "#970 PD 「비수 주력 스킬 사용 시 적이 갑자기 순간이동 하는 현상아 있는데 왜 그런건지 살펴보고 순간이동하지 못하게 해줘」 — 원인 = 적이 아니라 PC 가 움직임: 원본 끝 콜백(Set_Invisible 끝)이 PC 를 대상 뒤 1.5 m(Get_PositionBack)로 Set_Warp → 카메라가 PC 를 따라가 화면에서는 적이 PC 반대편으로 튄 것처럼 보임(Play 캡처 970_dg_a → b · 더미가 PC 오른쪽 → 위·왼쪽) → endWarp 0 = 끝 순간이동 · 그때의 카메라 돌리기 생략(원본 훅 1줄 · PC 는 난사한 자리 그대로)",
"_note_962": "#962 PD 「비수 주력 사용 시 이펙트가 두 번 연속 재생되는 것 같다 → 이펙트는 한 번만 재생하고 모션을 이펙트에 맞춰」 · 「주력 사용 시 판정이 발생되지 않는데 왜 그런지 체크 · 수정」 — 이펙트 = 정면 사본 1개만(fxRepeatInterval 0 · 이전 = 0.5 s 부터 0.2 s 마다 6개가 겹쳐 같은 6연속 초승달이 되풀이) · 시전과 동시에(fxDelay 0) · 난사 시간 = 사본 1개가 보이는 시간(slashMatchFx · 입자 분출 0~0.75 s + 수명 0.3 = 1.05 s) · 휘두름 = 초승달 간격 0.15 s 마다(배속 2.1 = 휘두름마다 클립 0.32 s · #960 과 같은 길이) · 원본 숨김 2.1 s(이동 금지 · 무적 · 끝 대기 · 대상 뒤 순간이동)도 1.05 s 로(invisibleMatch · 훅 1줄) · 판정 10회를 1.05 s 에 고르게(slashHitEven) · 판정 진단(Play 실측 · 962_probe Q): 판정은 10/10 나지만 ① 비수 스킬 타격은 적 몸에 뜨는 피격 이펙트 칸이 없고 ② 맞을 때마다 더미가 약 0.25 m 씩 밀려 2 s 동안 1.0 → 3.4 m(이펙트 밖) ③ 4.0 m 를 넘으면 실제로 빗나감(4.5 m 조건 6/10) → 피격 이펙트 WLImpactFx skillHitFx(10202 · Skill_ShadowSlash) + 넉백 끔(WLSkillHitFeel) + 판정 반경 3.5 → 4.0 m(+ 몸 반지름 ≈ 원본 판정 상자 앞 4.4 m)",
"_note_961": "#961 PD 「주력 중 캐릭터가 움직이면 이펙트만 그 자리에 남음 → 못 움직이게 · 구르기로 캔슬하면 이펙트도 같이 소멸」 · 「이펙트 소멸 타이밍에 맞게 모션도 종료 · 최소 0.5 s 딜레이 후 공격」 — 이동 = 원본이 PCMove 를 끄지만 하네스 WASD · 가상패드가 Run_byJoystick 으로 움직였음 → moveHold(WLSkillCancel.HoldMove 2.0 s · 구르기는 됨) · 구르기 = 난사 · 반복 · 잔상 · 판정 멈춤 + 살아 있는 정면 사본 지움 · 정면 사본 반복을 0.3 s(초승달 보이는 시간) 일찍 끝내 마지막 이펙트가 난사 끝 2.0 s 에 함께 사라짐 · 끝난 뒤 0.5 s 공격 금지(IsStop 매 프레임 · 하네스 공격 키 IsHolding) · endIdle = 난사 끝(마지막 이펙트 소멸 2.0 s)에 바로 대기 동작(원본은 2.1 s 콜백에서 대기 · 그사이 마지막 휘두름이 이어짐) · 구르기 캔슬이면 원본 2.1 s 끝 처리(대기 · 대상 뒤 순간이동 · 연기 · 카메라 돌리기)를 건너뜀(Skill_ShadowSlash 훅 1줄 SkipEnd) · Play 실측(961_verify): ⓐ 이동 입력은 막혔는데(WASD 막힘 72 · 패드 0 m) 시전 중 0.65~1.06 m 전진 = 강제 재생하는 1·2타 클립의 공격 전진 표(AttackRootMotion) → 난사 중 Gate 차단(IsSlashing) ⓑ 사본 1개 = 초승달 6개를 0~0.75 s 에 나눠 뿜어 약 1.05 s 보임(fxVisibleLife 0.3 가정이 틀려 입자가 2.74 s 까지 남음) → 반복을 멈추는 1.7 s 에 살아 있는 사본의 분출도 멈춤(이미 나온 초승달 수명 0.3 s 만) = 2.0 s 에 함께 소멸",
"slashHits": 10,

View File

@ -26,5 +26,7 @@
"Skill_DashSlash"
],
"holdUntilFire": 1,
"holdMaxSeconds": 1.5
"holdMaxSeconds": 1.5,
"_note_970": "#970 PD 「시전하는 모션이 존재하는 스킬은 일정 타이밍(실제 스킬 발동이 확정 된 시점)까지 못움직이게 하고, 움직여 진 경우에는 발동 된 스킬이 스킵되지 않도록 (현재는 시전 직후 움직이면 스킬 이펙트가 스킵되는 현상)」 — castLock 1 = SkillList s_NextAnimation(원본 시전 단계) 또는 f_CastingTime 이 있는 스킬은 lockUntilFire + noSkip 으로(위 목록은 표에 시전 단계가 없는 Skill_ArrowRain 등 그대로) · 잠금 상한 = holdMaxSeconds + 시전 시간",
"castLock": 1
}

View File

@ -71,6 +71,9 @@ namespace WL.Combat.Weapon
// slashHitEven 1 = 판정 slashHits 회를 난사 시간에 고르게(휘두름 수와 무관 · 그전엔 휘두름마다 1회 + 모자란 만큼 끝에 몰아서)
public int slashMatchFx = 0, invisibleMatch = 0, slashHitEven = 0;
public int endIdle = 0; // #961 1 = 난사가 끝나는 순간(= 마지막 이펙트 소멸) 대기 동작으로(원본은 0.1 s 뒤 2.1 s 콜백에서 대기 · 그사이 마지막 휘두름이 이어졌다)
// #970 PD 「비수 주력 스킬 사용 시 적이 갑자기 순간이동 하는 현상 … 순간이동하지 못하게」 — 원인 = 원본 끝 콜백이 PC 를 대상 뒤 1.5 m 로 옮겨(Set_Warp) 카메라가 따라가는 화면에서 적이 반대편으로 튐 ·
// 0 = 끝 순간이동과 그때의 카메라 돌리기(RotateCam_TargetBack)를 건너뛴다(PC 는 난사한 자리 그대로) · 1 = 원본
public int endWarp = 1;
}
public static class WLShadowSlash
@ -353,6 +356,14 @@ namespace WL.Combat.Weapon
if (Cfg.dodgeCancel == 0 || s_castSeq <= 0 || s_cancelSeq != s_castSeq || !ReferenceEquals(shooter, s_castShooter)) return false;
EndSkips++; return true;
}
public static int EndWarps, EndWarpSkips;
/// <summary>#970 원본 Skill_ShadowSlash 끝 콜백 훅 — false = 대상 뒤 순간이동 · 그때의 카메라 돌리기를 건너뜀(endWarp 0).</summary>
public static bool EndWarp()
{
var c = Cfg;
if (c.enabled == 0 || c.endWarp != 0) { EndWarps++; return true; }
EndWarpSkips++; return false;
}
static PropertyInfo s_isStop;
public static bool IsHolding(Actor a) { return a != null && ReferenceEquals(a, s_holdActor) && Time.time < s_holdUntil; }
static void SetStop(Actor a, bool v)

View File

@ -14,6 +14,7 @@
// 무시한 동안 들어온 PCActor.Set_AutoBraking(누름 false · 뗌 true)은 미뤘다가 잠금이 풀릴 때 마지막 값을 적용한다.
// ④ #912 HoldMove — 파츠 스킬이 정한 시간 동안 이동 입력 무시(해머 각성 「내려친 상태로 잠시 멈추게」 · 구르기는 허용 = 스킵) · 그동안의 뗌은 EndHoldMove 에서 적용.
// ⑤ #914 endWithMotion — 스킬 동작이 입력 없이 끝나면(대기 등) 그 스킬 이펙트(투사체 · 연출)도 바로 끈다(PD 「검 각성 … 연속 공격 모션을 끝나는 시점에 맞춰서 이펙트도 소멸」).
// ⑥ #970 castLock — 시전 동작이 있는 스킬(표 s_NextAnimation · f_CastingTime)은 목록 없이 발동(SkillFired)까지 이동 · 구르기 무시 + 발동 뒤 이동해도 스킵 안 함.
// ■ 원본 훅 = PCActor.Run_byJoystick · Set_AutoBraking 첫 줄 각 1줄 · 값 = Resources/WL/WLSkillCancel.json (C45) · 끄기 = enabled 0
// 🔴 Debug.LogError 금지(원본 ErrorLogHook 팝업).
// ─────────────────────────────────────────────────────────────────────────────
@ -35,21 +36,24 @@ namespace WL.Combat.Weapon
public string[] endWithMotion = new string[0]; // #914 스킬 동작이 입력 없이 끝나면(대기로) 그 스킬 이펙트도 바로 끈다 — 남은 이펙트 때문에 서 있지 않게
public string[] lockUntilFire = new string[0]; // #942 시전 뒤 첫 발동(SkillFired)까지 이동 · 구르기 입력 무시(holdMaxSeconds 상한) — 발동 뒤엔 자유(투사체는 noSkip 으로 유지) · PD 「플레이어가 이동해도 발동 된 스킬이 끊겨선 안돼」(실측: 이동이 발동 이벤트 전에 시전 동작을 끊어 투사체가 아예 안 나왔다)
public int holdUntilFire = 1; // 1 = 이동 키를 누른 채 쓴 스킬은 첫 발동까지 그 입력을 무시
public float holdMaxSeconds = 1.5f; // ① 의 상한(발동 이벤트가 없는 스킬 대비)
public float holdMaxSeconds = 1.5f; // ① 의 상한(발동 이벤트가 없는 스킬 대비) · 시전 시간(f_CastingTime)이 있는 스킬은 상한 = 이 값 + 시전 시간
// #970 PD 「시전하는 모션이 존재하는 스킬은 일정 타이밍(실제 스킬 발동이 확정 된 시점)까지 못움직이게 하고, 움직여 진 경우에는 발동 된 스킬이 스킵되지 않도록」 —
// 1 = 시전 동작이 있는 스킬(SkillList s_NextAnimation 있음 = 원본 Co_Casting 시전 단계 · 또는 f_CastingTime > 0)은 이름 목록 없이 lockUntilFire + noSkip 으로 취급(발동 = SkillFired · 원본 SkillEvent 의 Shoot_Skill 직전)
public int castLock = 0;
public string note = "";
}
public static class WLSkillCancel
{
public const string ResourcesPath = "WL/WLSkillCancel";
public static int Casts, Skips, SkippedObjects, MoveBlocked, DodgeBlocked, BrakeDeferred, BrakeApplied, Errors, MotionEnds;
public static int Casts, Skips, SkippedObjects, MoveBlocked, DodgeBlocked, BrakeDeferred, BrakeApplied, Errors, MotionEnds, CastLocks, SkipsAvoided;
public static string LastLog = "";
static WLSkillCancelJson s_cfg;
static PCActor s_pc;
static string s_effect = "";
static float s_castAt;
static bool s_active, s_fired, s_heldAtCast, s_lock, s_hold, s_lockFire; // s_lockFire = #942 발동까지 잠금
static float s_castAt, s_cap = 1.5f; // s_cap = 발동까지 잠금 상한(holdMaxSeconds + 시전 시간 · #970)
static bool s_active, s_fired, s_heldAtCast, s_lock, s_hold, s_lockFire, s_noSkip; // s_lockFire = #942 발동까지 잠금 · s_noSkip = 이동해도 이펙트 유지(목록 또는 #970 시전 동작)
static int s_pendingBrake = -1; // -1 없음 · 0 = Set_AutoBraking(false) · 1 = Set_AutoBraking(true)
static GameObject s_runner;
static FieldInfo s_fDicSkill;
@ -103,9 +107,18 @@ namespace WL.Combat.Weapon
s_heldAtCast = pc.JoystickStatus == 1;
s_lock = Has(c.lockMove, s_effect);
s_hold = Has(c.holdMove, s_effect);
s_lockFire = Has(c.lockUntilFire, s_effect);
Casts++;
LastLog = "시작 " + s_effect + (s_lock ? " · 이동 잠금" : "") + (s_lockFire ? " · 발동까지 잠금" : "") + (s_heldAtCast ? " · 이동 키 누른 채" : "");
bool castMotion = c.castLock != 0 && HasCastMotion(e.skill); // #970 시전 동작이 있는 스킬 = 발동까지 잠금 + 발동 뒤 이동해도 유지
s_lockFire = Has(c.lockUntilFire, s_effect) || castMotion;
s_noSkip = Has(c.noSkip, s_effect) || castMotion;
s_cap = c.holdMaxSeconds + (e.skill != null ? Mathf.Max(0f, e.skill.f_CastingTime) : 0f);
Casts++; if (castMotion) CastLocks++;
LastLog = "시작 " + s_effect + (s_lock ? " · 이동 잠금" : "") + (s_lockFire ? " · 발동까지 잠금(상한 " + s_cap.ToString("F1") + " s)" : "") + (castMotion ? " · 시전 동작" : "") + (s_heldAtCast ? " · 이동 키 누른 채" : "");
}
/// <summary>#970 시전 동작이 있는 스킬 — 원본 Actor.Play_Skill 이 Co_Casting(시전 → s_NextAnimation)을 도는 스킬(s_NextAnimation 있음) 또는 시전 시간이 있는 스킬.</summary>
static bool HasCastMotion(SkillListTableData s)
{
return s != null && (!string.IsNullOrEmpty(s.s_NextAnimation) || s.f_CastingTime > 0f);
}
static void OnFired(in SkillFiredEvent e) { if (s_active && ReferenceEquals(e.actor, s_pc)) s_fired = true; }
@ -114,7 +127,7 @@ namespace WL.Combat.Weapon
public static void ResetFor(PCActor pc)
{
if (pc == null) return;
if (ReferenceEquals(pc, s_pc)) { s_active = false; s_lock = s_hold = s_lockFire = s_heldAtCast = false; s_pendingBrake = -1; }
if (ReferenceEquals(pc, s_pc)) { s_active = false; s_lock = s_hold = s_lockFire = s_noSkip = s_heldAtCast = false; s_pendingBrake = -1; }
if (ReferenceEquals(pc, s_extPc)) { s_extPc = null; s_extPending = false; }
LastLog = "초기화(직업 전환) " + s_effect;
}
@ -152,8 +165,8 @@ namespace WL.Combat.Weapon
if (!s_active || !ReferenceEquals(pc, s_pc) || pc.Get_CurAnim() != eAnim.Skill) return false;
if (s_lock) return true;
var c = Cfg;
if (s_lockFire && !s_fired && Time.time - s_castAt < c.holdMaxSeconds) return true; // #942 발동 전엔 새 이동 입력도 무시
return c.holdUntilFire != 0 && s_heldAtCast && !s_fired && Time.time - s_castAt < c.holdMaxSeconds;
if (s_lockFire && !s_fired && Time.time - s_castAt < s_cap) return true; // #942 발동 전엔 새 이동 입력도 무시
return c.holdUntilFire != 0 && s_heldAtCast && !s_fired && Time.time - s_castAt < s_cap;
}
/// <summary>PCActor.Run_byJoystick 첫 줄 훅 — true = 이 이동 입력을 무시한다.</summary>
@ -168,7 +181,7 @@ namespace WL.Combat.Weapon
public static bool BlockDodge(PCActor pc)
{
if (pc == null || !s_active || !ReferenceEquals(pc, s_pc) || pc.Get_CurAnim() != eAnim.Skill) return false;
if (!s_lock && !(s_lockFire && !s_fired && Time.time - s_castAt < Cfg.holdMaxSeconds)) return false; // #942 발동 전 구르기도 무시
if (!s_lock && !(s_lockFire && !s_fired && Time.time - s_castAt < s_cap)) return false; // #942 발동 전 구르기도 무시
DodgeBlocked++; return true;
}
@ -222,7 +235,8 @@ namespace WL.Combat.Weapon
// 스킬 상태에서 바로 달리기 · 구르기 = 입력으로 끊김(자연 종료는 Event_Idle → 대기). 원본 구르기는 같은 프레임에 달리기로 넘어가 Dodge 를 못 볼 때가 있다(실측)
bool byInput = cur == eAnim.Run || cur == eAnim.Dodge;
var c = Cfg;
if (byInput && c.skipOnMove != 0 && !Has(c.noSkip, s_effect)) Skip(pc, s_effect, cur == eAnim.Dodge ? "구르기" : "이동");
if (byInput && c.skipOnMove != 0 && !s_noSkip) Skip(pc, s_effect, cur == eAnim.Dodge ? "구르기" : "이동");
else if (byInput && s_noSkip) { SkipsAvoided++; LastLog = "유지 " + s_effect + " · " + (cur == eAnim.Dodge ? "구르기" : "이동") + (s_fired ? " · 발동 뒤" : " · 발동 전"); }
else if (!byInput && Has(c.endWithMotion, s_effect)) { MotionEnds++; Skip(pc, s_effect, "동작 끝"); } // #914 동작 끝 = 이펙트 끝(이동 잠금 holdMove 도 함께 풀림)
if (s_pendingBrake >= 0 && !Blocking(pc)) ApplyBrake(pc);
}

View File

@ -11,6 +11,8 @@
"gameMode": "Lobby",
"combatFormCheckSeconds": 0.5,
"autoResetDummySeconds": 2.0,
"autoResetPauseInSkill": 1,
"_note_970": "#970 PD 「비수 주력 스킬 사용 시 적이 갑자기 순간이동」 — Play 실측 원인 2가지: ① 원본 끝 순간이동(PC 가 대상 뒤 1.5 m · WLShadowSlash.json endWarp 0 으로 끔) ② 이 씬의 더미 자동 복귀 — 주력 판정 10회가 더미를 2.4~3.1 m 밀어 사거리 밖 2 s 가 차면 더미가 PC 앞으로 순간이동(실측 2.00 · 3.55 m) → autoResetPauseInSkill 1 = PC 가 스킬 상태인 동안은 사거리 밖 시간을 세지 않음(스킬이 끝난 뒤부터 다시 셈 · 0 = 이전처럼)",
"moveKeys": 1,
"attackKey": "Space",
"weaponPrevKey": "O",

View File

@ -63,6 +63,7 @@ namespace WL.SkillTest
public string gameMode = "Lobby"; // InGameInfo 게임 모드 — 섬과 같은 Lobby(자동 전투·대상 찾기가 로비 규칙). Stage 로 두면 PC 가 대상 없이 달린다(#948 실측). 로비 컨트롤러(pcanim_lobby) 문제는 Set_Obj 동안만 Stage 로 바꾸는 전투 형태 적용(섬 WLIslandAvatar.ApplyCombatForm 과 같은 꼴)으로 푼다
public float combatFormCheckSeconds = 0.5f; // 이 간격으로 PC 가 로비 컨트롤러면 전투 형태 다시 적용 · 대상이 없으면 더미를 다시 겨눔
public float autoResetDummySeconds = 2.0f; // 더미가 공격 사거리 밖(넉백 누적)에 이만큼(초) 머물면 PC 앞 기본 자리로(R 키와 같음) → 콤보가 끊기지 않고 반복된다(#948 · 0 = 끔)
public int autoResetPauseInSkill = 0; // #970 1 = PC 가 스킬 상태인 동안은 사거리 밖 시간을 세지 않음(0 으로) — 비수 주력 판정이 더미를 2.4~3.1 m 밀어 스킬 중에 더미가 PC 앞으로 순간이동하던 것 · 스킬이 끝난 뒤부터 다시 셈
public int moveKeys = 1; // 1 = WASD/방향키도 이동(가상패드와 함께 · PD #947 「가상패드 + 키 입력」)
public string attackKey = "Space";
public string weaponPrevKey = "O"; // PD #947: O = 무기 왼쪽 순환
@ -275,7 +276,8 @@ namespace WL.SkillTest
if (auto > 0f && Dummy != null)
{
var d = Dummy.Get_position() - pc.Get_position(); d.y = 0f;
if (d.magnitude > pc.WL_AttackRange + 0.3f) { _outOfRange += Mathf.Max(0.1f, Cfg.combatFormCheckSeconds); if (_outOfRange >= auto) { _outOfRange = 0f; _msg = "더미 사거리 밖 " + auto + " s → " + ResetDummy(); } }
if (Cfg.autoResetPauseInSkill != 0 && pc.Get_CurAnim() == eAnim.Skill) _outOfRange = 0f; // #970 스킬 중엔 셈 멈춤(스킬 중 더미 순간이동 방지)
else if (d.magnitude > pc.WL_AttackRange + 0.3f) { _outOfRange += Mathf.Max(0.1f, Cfg.combatFormCheckSeconds); if (_outOfRange >= auto) { _outOfRange = 0f; _msg = "더미 사거리 밖 " + auto + " s → " + ResetDummy(); } }
else _outOfRange = 0f;
}
}