feat: 스킬별 행동 제한 정책 추가
- SkillData에 시전 중 이동, 점프, 추가 스킬 사용 제한 옵션을 추가 - PlayerActionState가 현재 스킬 정책을 읽어 행동 가능 여부를 계산하도록 변경 - 스킬 입력이 공통 행동 판정 규칙을 따르도록 정리
This commit is contained in:
@@ -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;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -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;
|
||||
|
||||
@@ -31,6 +31,16 @@ namespace Colosseum.Skills
|
||||
[Tooltip("스킬 시전 시 대상 위치로 점프 이동 (UseRootMotion + IgnoreRootMotionY=false 필요)")]
|
||||
[SerializeField] private bool jumpToTarget = false;
|
||||
|
||||
[Header("행동 제한")]
|
||||
[Tooltip("시전 중 이동 입력 차단 여부")]
|
||||
[SerializeField] private bool blockMovementWhileCasting = true;
|
||||
[Tooltip("시전 중 점프 입력 차단 여부")]
|
||||
[SerializeField] private bool blockJumpWhileCasting = true;
|
||||
[Tooltip("시전 중 다른 스킬 입력 차단 여부")]
|
||||
[SerializeField] private bool blockOtherSkillsWhileCasting = true;
|
||||
[Tooltip("시전 중 회피 입력 차단 여부")]
|
||||
[SerializeField] private bool blockEvadeWhileCasting = true;
|
||||
|
||||
[Header("쿨타임 & 비용")]
|
||||
[Min(0f)] [SerializeField] private float cooldown = 1f;
|
||||
[Min(0f)] [SerializeField] private float manaCost = 0f;
|
||||
@@ -51,6 +61,10 @@ namespace Colosseum.Skills
|
||||
public bool UseRootMotion => useRootMotion;
|
||||
public bool IgnoreRootMotionY => ignoreRootMotionY;
|
||||
public bool JumpToTarget => jumpToTarget;
|
||||
public bool BlockMovementWhileCasting => blockMovementWhileCasting;
|
||||
public bool BlockJumpWhileCasting => blockJumpWhileCasting;
|
||||
public bool BlockOtherSkillsWhileCasting => blockOtherSkillsWhileCasting;
|
||||
public bool BlockEvadeWhileCasting => blockEvadeWhileCasting;
|
||||
public IReadOnlyList<SkillEffect> Effects => effects;
|
||||
}
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user