feat: 스킬별 행동 제한 정책 추가

- SkillData에 시전 중 이동, 점프, 추가 스킬 사용 제한 옵션을 추가
- PlayerActionState가 현재 스킬 정책을 읽어 행동 가능 여부를 계산하도록 변경
- 스킬 입력이 공통 행동 판정 규칙을 따르도록 정리
This commit is contained in:
2026-03-19 18:34:02 +09:00
parent 5bedf01d6c
commit 975dea8b93
3 changed files with 75 additions and 8 deletions

View File

@@ -50,6 +50,11 @@ namespace Colosseum.Player
/// </summary>
public bool IsCastingSkill => skillController != null && skillController.IsPlayingAnimation;
/// <summary>
/// 현재 시전 중인 스킬
/// </summary>
public SkillData CurrentSkill => skillController != null ? skillController.CurrentSkill : null;
/// <summary>
/// 입력을 받아도 되는지 여부
/// </summary>
@@ -58,22 +63,22 @@ namespace Colosseum.Player
/// <summary>
/// 플레이어가 직접 이동 입력을 사용할 수 있는지 여부
/// </summary>
public bool CanMove => CanReceiveInput && !IsStunned && !IsCastingSkill;
public bool CanMove => CanReceiveInput && !IsStunned && !BlocksMovementForCurrentSkill();
/// <summary>
/// 점프 가능 여부
/// </summary>
public bool CanJump => CanMove;
public bool CanJump => CanReceiveInput && !IsStunned && !BlocksJumpForCurrentSkill();
/// <summary>
/// 스킬 사용 가능 여부
/// </summary>
public bool CanUseSkills => CanReceiveInput && !IsStunned && !IsSilenced && !IsCastingSkill;
public bool CanUseSkills => CanReceiveInput && !IsStunned && !IsSilenced && !BlocksSkillUseForCurrentSkill();
/// <summary>
/// 회피 사용 가능 여부
/// </summary>
public bool CanEvade => CanUseSkills;
public bool CanEvade => CanReceiveInput && !IsStunned && !IsSilenced && !BlocksEvadeForCurrentSkill();
/// <summary>
/// 현재 이동 속도 배율
@@ -100,5 +105,37 @@ namespace Colosseum.Player
if (spectator == null)
spectator = GetComponentInChildren<PlayerSpectator>();
}
private bool BlocksMovementForCurrentSkill()
{
if (!IsCastingSkill)
return false;
return CurrentSkill == null || CurrentSkill.BlockMovementWhileCasting;
}
private bool BlocksJumpForCurrentSkill()
{
if (!IsCastingSkill)
return false;
return CurrentSkill == null || CurrentSkill.BlockJumpWhileCasting;
}
private bool BlocksSkillUseForCurrentSkill()
{
if (!IsCastingSkill)
return false;
return CurrentSkill == null || CurrentSkill.BlockOtherSkillsWhileCasting;
}
private bool BlocksEvadeForCurrentSkill()
{
if (!IsCastingSkill)
return false;
return CurrentSkill == null || CurrentSkill.BlockEvadeWhileCasting;
}
}
}

View File

@@ -123,6 +123,8 @@ namespace Colosseum.Player
if (slotIndex < 0 || slotIndex >= skillSlots.Length)
return;
bool isEvadeSlot = slotIndex == skillSlots.Length - 1;
SkillData skill = skillSlots[slotIndex];
if (skill == null)
{
@@ -131,8 +133,14 @@ namespace Colosseum.Player
}
// 사망 상태 체크
if (actionState != null && !actionState.CanUseSkills)
return;
if (actionState != null)
{
if (isEvadeSlot && !actionState.CanEvade)
return;
if (!isEvadeSlot && !actionState.CanUseSkills)
return;
}
// 로컬 체크 (빠른 피드백용)
if (skillController.IsExecutingSkill)
@@ -168,13 +176,21 @@ namespace Colosseum.Player
if (slotIndex < 0 || slotIndex >= skillSlots.Length)
return;
bool isEvadeSlot = slotIndex == skillSlots.Length - 1;
SkillData skill = skillSlots[slotIndex];
if (skill == null) return;
// 서버에서 다시 검증
// 사망 상태 체크
if (actionState != null && !actionState.CanUseSkills)
return;
if (actionState != null)
{
if (isEvadeSlot && !actionState.CanEvade)
return;
if (!isEvadeSlot && !actionState.CanUseSkills)
return;
}
if (skillController.IsExecutingSkill || skillController.IsOnCooldown(skill))
return;