using UnityEngine; using Colosseum.Abnormalities; using Colosseum.Skills; namespace Colosseum.Player { /// /// 플레이어의 전투 행동 가능 여부를 한 곳에서 판정하는 상태 관리자. /// 이동, 점프, 스킬 사용 가능 여부를 사망/이상 상태/관전/시전 상태와 연동합니다. /// [DisallowMultipleComponent] public class PlayerActionState : MonoBehaviour { [Header("References")] [Tooltip("플레이어 네트워크 상태")] [SerializeField] private PlayerNetworkController networkController; [Tooltip("이상 상태 관리자")] [SerializeField] private AbnormalityManager abnormalityManager; [Tooltip("스킬 실행 관리자")] [SerializeField] private SkillController skillController; [Tooltip("피격 제어 관리자")] [SerializeField] private HitReactionController hitReactionController; [Tooltip("방어 상태 관리자")] [SerializeField] private PlayerDefenseController defenseController; [Tooltip("관전 관리자")] [SerializeField] private PlayerSpectator spectator; /// /// 사망 상태 여부 /// public bool IsDead => networkController != null && networkController.IsDead; /// /// 기절 상태 여부 /// public bool IsStunned => abnormalityManager != null && abnormalityManager.IsStunned; /// /// 경직 상태 여부 /// public bool IsStaggered => hitReactionController != null && hitReactionController.IsStaggered; /// /// 넉백 상태 여부 /// public bool IsKnockbackActive => hitReactionController != null && hitReactionController.IsKnockbackActive; /// /// 다운 상태 여부 /// public bool IsDowned => hitReactionController != null && hitReactionController.IsDowned; /// /// 다운 중 구르기 가능 구간 여부 /// public bool IsDownRecoverable => hitReactionController != null && hitReactionController.IsDownRecoverable; /// /// 침묵 상태 여부 /// public bool IsSilenced => abnormalityManager != null && abnormalityManager.IsSilenced; /// /// 관전 상태 여부 /// public bool IsSpectating => spectator != null && spectator.IsSpectating; /// /// 스킬 애니메이션 재생 중 여부 /// public bool IsCastingSkill => skillController != null && skillController.IsPlayingAnimation; /// /// 현재 시전 중인 스킬 /// public SkillData CurrentSkill => skillController != null ? skillController.CurrentSkill : null; /// /// 무적 이상상태 여부 /// public bool IsDamageImmune => abnormalityManager != null && abnormalityManager.IsInvincible; /// /// 입력을 받아도 되는지 여부 /// public bool CanReceiveInput => !IsDead && !IsSpectating; /// /// 플레이어가 직접 이동 입력을 사용할 수 있는지 여부 /// public bool CanMove => CanReceiveInput && !IsStunned && !IsStaggered && !IsKnockbackActive && !IsDowned && !BlocksMovementForCurrentSkill(); /// /// 점프 가능 여부 /// public bool CanJump => CanReceiveInput && !IsStunned && !IsStaggered && !IsKnockbackActive && !IsDowned && !BlocksJumpForCurrentSkill(); /// /// 일반 스킬 시작 가능 여부 /// public bool CanUseSkills => CanReceiveInput && !IsStunned && !IsStaggered && !IsKnockbackActive && !IsDowned && !IsSilenced && !BlocksSkillUseForCurrentSkill(); /// /// 회피 스킬 시작 가능 여부 /// public bool CanEvade => CanReceiveInput && !IsStunned && !IsStaggered && !IsKnockbackActive && !IsSilenced && (!IsDowned || IsDownRecoverable) && !BlocksSkillUseForCurrentSkill(); /// /// 특정 스킬의 시작 가능 여부. /// 스킬 이름과 무관하게 동일한 시작 규칙을 사용합니다. /// public bool CanStartSkill(SkillData skill) { if (skill == null) return false; if (!CanReceiveInput || IsStunned || IsStaggered || IsKnockbackActive || IsSilenced) return false; if (IsDowned) { if (!IsDownRecoverable || !skill.IsEvadeSkill) return false; } return !BlocksSkillUseForCurrentSkill(); } /// /// 현재 이동 속도 배율 /// public float MoveSpeedMultiplier { get { if (!CanReceiveInput || IsStunned || IsStaggered || IsKnockbackActive || IsDowned) return 0f; float abnormalityMultiplier = abnormalityManager != null ? abnormalityManager.MoveSpeedMultiplier : 1f; float defenseMultiplier = defenseController != null ? defenseController.MoveSpeedMultiplier : 1f; return abnormalityMultiplier * defenseMultiplier; } } private void Awake() { if (networkController == null) networkController = GetComponent(); if (abnormalityManager == null) abnormalityManager = GetComponent(); if (skillController == null) skillController = GetComponent(); if (hitReactionController == null) hitReactionController = GetOrCreateHitReactionController(); if (defenseController == null) defenseController = GetOrCreateDefenseController(); if (spectator == null) spectator = GetComponentInChildren(); } 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 HitReactionController GetOrCreateHitReactionController() { HitReactionController foundController = GetComponent(); if (foundController != null) return foundController; return gameObject.AddComponent(); } private PlayerDefenseController GetOrCreateDefenseController() { PlayerDefenseController foundController = GetComponent(); if (foundController != null) return foundController; return gameObject.AddComponent(); } } }