diff --git a/Assets/01.Scenes/02.Combat.unity b/Assets/01.Scenes/02.Combat.unity index 922aabc0a..2789a019b 100644 --- a/Assets/01.Scenes/02.Combat.unity +++ b/Assets/01.Scenes/02.Combat.unity @@ -1875,8 +1875,8 @@ MonoBehaviour: m_Script: {fileID: 11500000, guid: 179524db1ad20f44a8374fb83bb46495, type: 3} m_Name: m_EditorClassIdentifier: - SwitchMapsOpened: 4 - SwitchMapsClosed: 3 + SwitchMapsOpened: 5 + SwitchMapsClosed: 4 --- !u!1 &473280139 GameObject: m_ObjectHideFlags: 0 @@ -19658,8 +19658,8 @@ MonoBehaviour: m_Script: {fileID: 11500000, guid: a61520d3b25b0244685023b48f19cdee, type: 3} m_Name: m_EditorClassIdentifier: - SwitchMapsOpened: 4 - SwitchMapsClosed: 3 + SwitchMapsOpened: 5 + SwitchMapsClosed: 4 SortingDropdown: {fileID: 5518631981308585485} CurrentWeight: {fileID: 5638844555988528261} InstantiateLocation: {fileID: 2478437734520413558} diff --git a/Assets/02.Scripts/Character/AnimationController.cs b/Assets/02.Scripts/Character/AnimationController.cs index 4a1b2ce43..86fb2e824 100644 --- a/Assets/02.Scripts/Character/AnimationController.cs +++ b/Assets/02.Scripts/Character/AnimationController.cs @@ -1,5 +1,6 @@ using System; using System.Collections; +using Sirenix.OdinInspector; using UnityEngine; namespace BlueWater @@ -10,6 +11,7 @@ namespace BlueWater #region Variables // Components + [SerializeField] private Animator _animator; #endregion @@ -27,7 +29,8 @@ namespace BlueWater // Initialize methods #region Initialize Methdos - public void InitializeComponents() + [Button("컴포넌트 초기화")] + private void InitializeComponents() { _animator = GetComponentInChildren(); } diff --git a/Assets/02.Scripts/Character/CombatSkillController.cs b/Assets/02.Scripts/Character/CombatSkillController.cs new file mode 100644 index 000000000..12c74534d --- /dev/null +++ b/Assets/02.Scripts/Character/CombatSkillController.cs @@ -0,0 +1,152 @@ +using System.Collections.Generic; +using BlueWater.Interfaces; +using BlueWater.Uis; +using UnityEngine; + +namespace BlueWater +{ + public class CombatSkillController : MonoBehaviour, ISkillHandler + { + // Variables + #region Variables + + // Components + private IDashable _dashable; + private IComboAttackable _comboAttackable; + private IStunnable _stunnable; + + // Variables + [field: SerializeField] + public List Skills { get; private set; } + public Dictionary SkillInstances { get; private set; } + public BaseSkill CurrentActivatingSkill { get; private set; } + + public bool IsSkillEnabled { get; private set; } = true; + public bool IsActivatingSkill { get; private set; } + + #endregion + + // Unity events + #region Unity events + + private void Awake() + { + InitializeComponents(); + } + + private void Start() + { + Initialize(); + } + + private void OnDestroy() + { + if (SkillInstances == null) return; + + foreach (var element in SkillInstances.Values) + { + if (!element) continue; + + Destroy(element.gameObject); + } + } + + #endregion + + // Initialize methods + #region Initialize methods + + private void InitializeComponents() + { + _dashable = GetComponent(); + _comboAttackable = GetComponent(); + _stunnable = GetComponent(); + } + + private void Initialize() + { + SkillInstances = new Dictionary(Skills.Count); + + foreach (var element in Skills) + { + var newSkill = Instantiate(element); + newSkill.Initialize(gameObject); + SkillInstances.Add(newSkill.SkillName, newSkill); + } + + CurrentActivatingSkill = SkillInstances[Skills[0].SkillName]; + CombatUiManager.Instance.CombatSkillUi.ResetSkillUi(); + } + + #endregion + + // Methods + #region Methods + + public void EnableSkill() => IsSkillEnabled = true; + public void DisableSkill() => IsSkillEnabled = false; + + public bool HasSkill(string skillName = null) + { + if (string.IsNullOrEmpty(skillName)) skillName = CurrentActivatingSkill.SkillName; + + if (SkillInstances.ContainsKey(skillName)) return true; + + Debug.Log($"{skillName}(이)라는 스킬을 찾을 수 없습니다."); + return false; + } + + public bool CanSkill(string skillName = null) + { + if (string.IsNullOrEmpty(skillName)) skillName = CurrentActivatingSkill.SkillName; + + if (!IsSkillEnabled || IsActivatingSkill) return false; + + var isDashing = _dashable?.IsDashing ?? false; + var isAttacking = _comboAttackable?.CurrentComboAttackCount > 0; + var isStunned = _stunnable?.IsStunned ?? false; + + if (isDashing || isAttacking || isStunned) return false; + + return SkillInstances[skillName].CanSkill(); + } + + /// + /// HasSkill()만 확인하고 스킬을 강제로 사용 + /// + public void ActivateSkill(string skillName = null) + { + if (string.IsNullOrEmpty(skillName)) skillName = CurrentActivatingSkill.SkillName; + + if (!HasSkill(skillName)) return; + + IsSkillEnabled = false; + IsActivatingSkill = true; + CurrentActivatingSkill = SkillInstances[skillName]; + + CurrentActivatingSkill.ActivateSkill(EndSkill); + } + + /// + /// HasSkill(), CanSkill()를 모두 확인하고 스킬을 사용하기까지 모든 과정 + /// + public void TryActivateSkill(string skillName = null) + { + if (string.IsNullOrEmpty(skillName)) skillName = CurrentActivatingSkill.SkillName; + + if (!CanSkill(skillName)) return; + + ActivateSkill(skillName); + } + + private void EndSkill() + { + IsSkillEnabled = true; + IsActivatingSkill = false; + + CombatUiManager.Instance.CombatSkillUi.CoolDown(CurrentActivatingSkill.Cooldown); + } + + #endregion + } +} \ No newline at end of file diff --git a/Assets/02.Scripts/Character/Player/Combat/CombatSkillController.cs.meta b/Assets/02.Scripts/Character/CombatSkillController.cs.meta similarity index 100% rename from Assets/02.Scripts/Character/Player/Combat/CombatSkillController.cs.meta rename to Assets/02.Scripts/Character/CombatSkillController.cs.meta diff --git a/Assets/02.Scripts/Character/Enemy/Boss/BossHealthPoint.cs b/Assets/02.Scripts/Character/Enemy/Boss/BossHealthPoint.cs index ac2071cdf..c94074273 100644 --- a/Assets/02.Scripts/Character/Enemy/Boss/BossHealthPoint.cs +++ b/Assets/02.Scripts/Character/Enemy/Boss/BossHealthPoint.cs @@ -30,10 +30,10 @@ namespace BlueWater.Enemies.Bosses [field: SerializeField] public int CurrentHealthPoint { get; private set; } - [SerializeField] - private float _damageInterval = 0.1f; + public bool IsInvincible { get; private set; } - private bool _enableTakeDamage = true; + [field: SerializeField] + public float InvincibilityDuration { get; private set; } = 0.1f; // 효과 설정 [Title("효과 설정")] @@ -68,7 +68,7 @@ namespace BlueWater.Enemies.Bosses { InitializeComponent(); - _flashWhiteWaitTime = new WaitForSeconds(_damageInterval); + _flashWhiteWaitTime = new WaitForSeconds(InvincibilityDuration); _fieldBossHealthPointUi = CombatUiManager.Instance.FieldBossHealthPointUi; } @@ -104,25 +104,18 @@ namespace BlueWater.Enemies.Bosses SetCurrentHealthPoint(MaxHealthPoint); } - // Events methods - public void HandleEnableTakeDamage() => _enableTakeDamage = true; - public void HandleDisableTakeDamage() => _enableTakeDamage = false; - // Methods public void SetCurrentHealthPoint(int changedHealthPoint) { CurrentHealthPoint = changedHealthPoint; OnHealthChanged?.Invoke(changedHealthPoint); } - - public bool CanDamage() - { - return _enableTakeDamage; - } + + public bool CanDamage() => !IsInvincible; public void TakeDamage(int damageAmount) { - HandleDisableTakeDamage(); + IsInvincible = true; var changeHp = Mathf.Max(CurrentHealthPoint - damageAmount, 0); SetCurrentHealthPoint(changeHp); @@ -150,7 +143,7 @@ namespace BlueWater.Enemies.Bosses AudioManager.Instance.PlaySfx(_attackedSfxName); } - Utils.StartUniqueCoroutine(this, ref _damageIntervalCoroutine, Utils.CoolDownCoroutine(_damageInterval, EndDamageIntervalCoroutine)); + Utils.StartUniqueCoroutine(this, ref _damageIntervalCoroutine, Utils.CoolDownCoroutine(InvincibilityDuration, EndDamageIntervalCoroutine)); } public void TryTakeDamage(int damageAmount) @@ -188,8 +181,8 @@ namespace BlueWater.Enemies.Bosses private void EndDamageIntervalCoroutine() { + IsInvincible = false; Utils.EndUniqueCoroutine(this, ref _damageIntervalCoroutine); - HandleEnableTakeDamage(); } } } \ No newline at end of file diff --git a/Assets/02.Scripts/Character/Enemy/Boss/SandMole/SandMoleStatus.cs b/Assets/02.Scripts/Character/Enemy/Boss/SandMole/SandMoleStatus.cs index a0bb4d90d..735fb3ba5 100644 --- a/Assets/02.Scripts/Character/Enemy/Boss/SandMole/SandMoleStatus.cs +++ b/Assets/02.Scripts/Character/Enemy/Boss/SandMole/SandMoleStatus.cs @@ -14,7 +14,8 @@ namespace BlueWater.Enemies.Bosses.SandMole [Title("기절 효과")] [SerializeField] private ParticleSystem _stunParticle; - + + public bool IsStunEnabled { get; private set; } = true; public bool IsStunned { get; private set; } private Coroutine _stunCoolDownCoroutine; @@ -22,8 +23,12 @@ namespace BlueWater.Enemies.Bosses.SandMole #endregion // Stun + public bool CanStun() => IsStunEnabled; + public void Stun(float duration) { + if (!CanStun()) return; + IsStunned = true; if (_stunParticle) { diff --git a/Assets/02.Scripts/Character/Player/Combat/CombatAttacker.cs b/Assets/02.Scripts/Character/Player/Combat/CombatAttacker.cs index 0a5fc90c2..dd346ef57 100644 --- a/Assets/02.Scripts/Character/Player/Combat/CombatAttacker.cs +++ b/Assets/02.Scripts/Character/Player/Combat/CombatAttacker.cs @@ -1,31 +1,41 @@ -using System; using System.Collections; using BlueWater.Audios; using BlueWater.Interfaces; using BlueWater.Utility; +using Sirenix.OdinInspector; using UnityEngine; using UnityEngine.InputSystem; namespace BlueWater.Players.Combat { - public class CombatAttacker : MonoBehaviour + public class CombatAttacker : MonoBehaviour, IComboAttackable { // Variables #region Variables // Components + [SerializeField] private Rigidbody _rigidbody; + + [SerializeField] private AnimationController _animationController; - // Interfaces private IPhysicMovable _iPhysicMovable; + private IDashable _dashable; + private ISkillHandler _skillHandler; + private IStunnable _stunnable; // ComboAttack [field: SerializeField, Range(1, 21), Tooltip("한 번에 공격 가능한 개체 수")] - public int MaxHitCount { get; set; } = 10; + public int MaxHitCount { get; private set; } = 10; [field: SerializeField] - public ComboAttack[] ComboAttacks { get; set; } = new ComboAttack[2]; + public ComboAttack[] ComboAttacks { get; private set; } = new ComboAttack[2]; + + public bool IsAttackEnabled { get; private set; } = true; + + public bool IsComboAttackPossible { get; private set; } + public bool IsComboAttacking { get; private set; } private int _currentComboAttackCount; public int CurrentComboAttackCount @@ -37,18 +47,13 @@ namespace BlueWater.Players.Combat _animationController.SetAnimationParameter("comboAttackCount", CurrentComboAttackCount); } } - - public bool IsComboAttackPossible { get; set; } - public bool IsComboAttacking { get; set; } - public Collider[] HitColliders { get; set; } - - private bool _enableAttack = true; + public Collider[] HitColliders { get; private set; } [field: SerializeField] public LayerMask TargetLayer { get; private set; } - [SerializeField] - private LayerMask _mouseClickLayer; + [field: SerializeField] + public LayerMask MouseClickLayer { get; private set; } // Particles [SerializeField] @@ -62,15 +67,16 @@ namespace BlueWater.Players.Combat private Coroutine _firstComboAttackCoroutine; private Coroutine _secondComboAttackCoroutine; - // Events - public event Action OnStartAttack; - public event Action OnEndAttack; - #endregion // Unity events #region Unity events - + + private void Awake() + { + InitializeComponents(); + } + private void Start() { HitColliders = new Collider[MaxHitCount]; @@ -81,33 +87,44 @@ namespace BlueWater.Players.Combat // Initialize #region Initialize - public void InitializeComponents(Rigidbody rigidbody, AnimationController animationController, IPhysicMovable iPhysicMovable) + [Button("컴포넌트 초기화")] + private void InitializeComponents() { - _rigidbody = rigidbody; - _animationController = animationController; - _iPhysicMovable = iPhysicMovable; + _rigidbody = GetComponent(); + _animationController = GetComponent(); + + _iPhysicMovable = GetComponent(); + _dashable = GetComponent(); + _skillHandler = GetComponent(); + _stunnable = GetComponent(); } #endregion // Methods #region Methods - - // Event methods - public void HandleEnableAttack() => _enableAttack = true; - public void HandleDisableAttack() => _enableAttack = false; - public void HandleDashInAttack() + public bool CanAttack() { - if (CurrentComboAttackCount > 0) + if (!IsAttackEnabled || CurrentComboAttackCount == 2) return false; + + var isActivatingSkill = _skillHandler?.IsActivatingSkill ?? false; + var isStunned = _stunnable?.IsStunned ?? false; + + if (isActivatingSkill || isStunned) return false; + + var isDashing = _dashable?.IsDashing ?? false; + if (isDashing) { - EndComboAttack(); + _dashable.EndDash(); } - } - public void HandleAttack(bool usedMouseAttack) + return true; + } + + public void Attack(bool usedMouseAttack) { - if (!_enableAttack || CurrentComboAttackCount == 2) return; + if (!CanAttack()) return; if (CurrentComboAttackCount == 1 && IsComboAttackPossible) { @@ -126,27 +143,25 @@ namespace BlueWater.Players.Combat Utils.StartUniqueCoroutine(this, ref _firstComboAttackCoroutine, FirstComboAttackCoroutine()); } - - // Methods + private void UseMouseAttack() { var mousePos = Mouse.current.position.ReadValue(); var ray = CombatCameraManager.Instance.MainCamera.ScreenPointToRay(mousePos); - if (!Physics.Raycast(ray, out var hit, float.MaxValue, _mouseClickLayer)) + if (!Physics.Raycast(ray, out var hit, float.MaxValue, MouseClickLayer)) { - EndComboAttack(); + EndAttack(); return; } var attackDirection = (hit.point - _rigidbody.position).normalized; attackDirection.y = 0f; - _iPhysicMovable.CurrentDirection = attackDirection; + _iPhysicMovable.SetCurrentDirection(attackDirection); } private IEnumerator FirstComboAttackCoroutine() { - OnStartAttack?.Invoke(); CurrentComboAttackCount = 1; var animationStarted = false; @@ -155,7 +170,7 @@ namespace BlueWater.Players.Combat if (!animationStarted) { - EndComboAttack(); + EndAttack(); yield break; } @@ -184,7 +199,7 @@ namespace BlueWater.Players.Combat } else { - EndComboAttack(); + EndAttack(); } } @@ -200,7 +215,7 @@ namespace BlueWater.Players.Combat if (!animationStarted) { - EndComboAttack(); + EndAttack(); yield break; } @@ -222,7 +237,7 @@ namespace BlueWater.Players.Combat yield return new WaitForFixedUpdate(); } - EndComboAttack(); + EndAttack(); } private void DoDamage(int comboAttackCount, Vector3 attackDirection) @@ -254,7 +269,7 @@ namespace BlueWater.Players.Combat } } - public void EndComboAttack() + public void EndAttack() { Utils.EndUniqueCoroutine(this, ref _firstComboAttackCoroutine); Utils.EndUniqueCoroutine(this, ref _secondComboAttackCoroutine); @@ -263,7 +278,6 @@ namespace BlueWater.Players.Combat IsComboAttacking = false; IsComboAttackPossible = false; _animationController.ResetAnimationSpeed(); - OnEndAttack?.Invoke(); } #endregion diff --git a/Assets/02.Scripts/Character/Player/Combat/CombatInput.cs b/Assets/02.Scripts/Character/Player/Combat/CombatInput.cs index ec110b4f0..609eebeff 100644 --- a/Assets/02.Scripts/Character/Player/Combat/CombatInput.cs +++ b/Assets/02.Scripts/Character/Player/Combat/CombatInput.cs @@ -1,5 +1,6 @@ using System; using BlueWater.Uis; +using Sirenix.OdinInspector; using UnityEngine; using UnityEngine.InputSystem; @@ -11,22 +12,38 @@ namespace BlueWater.Players.Combat #region variables // Components + [SerializeField] private PlayerInput _playerInput; // Events public event Action OnMoveInputReceived; public event Action OnDashInputReceived; public event Action OnAttackInputReceived; - public event Action OnActivateMainSkillInputReceived; + public event Action OnActivateMainSkillInputReceived; #endregion + private void Awake() + { + InitializeComponents(); + } + + private void Start() + { + Initialize(); + } + // Initialize methods #region Initialize methods - public void InitializeComponents(PlayerInput playerInput) + [Button("컴포넌트 초기화")] + private void InitializeComponents() + { + _playerInput = GetComponent(); + } + + private void Initialize() { - _playerInput = playerInput; _playerInput.enabled = true; PlayerInputKeyManager.Instance.SetCurrentPlayerInput(_playerInput); PlayerInputKeyManager.Instance.SwitchCurrentActionMap(InputActionMaps.Combat); @@ -78,7 +95,7 @@ namespace BlueWater.Players.Combat { if (context.performed) { - OnActivateMainSkillInputReceived?.Invoke(); + OnActivateMainSkillInputReceived?.Invoke(null); } } diff --git a/Assets/02.Scripts/Character/Player/Combat/CombatMovement.cs b/Assets/02.Scripts/Character/Player/Combat/CombatMovement.cs index f15555baa..2ba563818 100644 --- a/Assets/02.Scripts/Character/Player/Combat/CombatMovement.cs +++ b/Assets/02.Scripts/Character/Player/Combat/CombatMovement.cs @@ -1,8 +1,8 @@ -using System; using System.Collections; using BlueWater.Audios; using BlueWater.Interfaces; using BlueWater.Utility; +using Sirenix.OdinInspector; using UnityEngine; namespace BlueWater.Players.Combat @@ -13,21 +13,32 @@ namespace BlueWater.Players.Combat #region Variables // Components + [field: SerializeField] public Rigidbody Rigidbody { get; private set; } + + [SerializeField] private Transform _visualLook; + + [SerializeField] private AnimationController _animationController; + + private IComboAttackable _comboAttackable; + private ISkillHandler _skillHandler; + private IStunnable _stunnable; // Move [field: SerializeField, Range(1f, 10f), Tooltip("이동 속도")] public float MoveSpeed { get; private set; } = 7f; - public bool EnableMove { get; private set; } = true; + public float MoveSpeedCoefficient { get; private set; }= 1f; + + public bool IsMoveEnabled { get; private set; } = true; private bool _isMoving; public bool IsMoving { get => _isMoving; - set + private set { _isMoving = value; _animationController.SetAnimationParameter("isMoving", _isMoving); @@ -40,7 +51,7 @@ namespace BlueWater.Players.Combat public Vector3 CurrentDirection { get => _currentDirection; - set + private set { if (value == Vector3.zero) return; @@ -51,7 +62,6 @@ namespace BlueWater.Players.Combat } private float _finalSpeed; - private float _moveSpeedCoefficient = 1f; // Dash [field: SerializeField, Range(1f, 50f), Tooltip("대쉬 속도")] @@ -63,7 +73,7 @@ namespace BlueWater.Players.Combat [field: SerializeField, Range(0f, 5f), Tooltip("대쉬 쿨타임")] public float DashCooldown { get; private set; } = 0.5f; - public bool EnableDash { get; private set; } = true; + public bool IsDashEnabled { get; private set; } = true; private bool _isDashing; public bool IsDashing @@ -80,15 +90,16 @@ namespace BlueWater.Players.Combat private Coroutine _dashCoroutine; - // Events - public event Action OnStartDash; - public event Action OnEndDash; - #endregion // Unity events #region Unity events - + + private void Awake() + { + InitializeComponents(); + } + private void Update() { FlipVisualLook(); @@ -98,7 +109,7 @@ namespace BlueWater.Players.Combat { if (!CanMove()) return; - ApplyMovement(); + Move(); } #endregion @@ -106,11 +117,16 @@ namespace BlueWater.Players.Combat // Initialize Methods #region Initialize Methods - public void InitializeComponents(Rigidbody rigidbody, Transform visualLook, AnimationController animationController) + [Button("컴포넌트 초기화")] + private void InitializeComponents() { - Rigidbody = rigidbody; - _visualLook = visualLook; - _animationController = animationController; + Rigidbody = GetComponent(); + _visualLook = transform.Find("VisualLook"); + _animationController = GetComponent(); + + _comboAttackable = GetComponent(); + _skillHandler = GetComponent(); + _stunnable = GetComponent(); } #endregion @@ -119,38 +135,14 @@ namespace BlueWater.Players.Combat #region Methods // Event methods - public void HandleInputMovement(Vector2 movementInput) + public void InputMovement(Vector2 movementInput) { _inputDirection = new Vector3(movementInput.x, 0, movementInput.y).normalized; } - public void HandleAttackInDash() - { - if (IsDashing) - { - EndDash(DashCooldown); - } - } - - public void HandleMoveSpeedCoefficient(float value) => _moveSpeedCoefficient = value; - public void HandleResetMoveSpeedCoefficient() => _moveSpeedCoefficient = 1f; - - public void HandleEnableMove() => EnableMove = true; - public void HandleDisableMove() => EnableMove = false; - public void HandleEnableDash() => EnableDash = true; - public void HandleDisableDash() => EnableDash = false; - - public void HandleEnableMoveAndDash() - { - EnableMove = true; - EnableDash = true; - } - - public void HandleDisableMoveAndDash() - { - EnableMove = false; - EnableDash = false; - } + public void SetMoveSpeedCoefficient(float value) => MoveSpeedCoefficient = value; + public void ResetMoveSpeedCoefficient() => MoveSpeedCoefficient = 1f; + public void SetCurrentDirection(Vector3 normalDirection) => CurrentDirection = normalDirection; // Methods private void FlipVisualLook() @@ -168,34 +160,50 @@ namespace BlueWater.Players.Combat // Move public bool CanMove() { - return EnableMove && !IsDashing; + if (!IsMoveEnabled || IsDashing) return false; + + var isActivatingSkill = _skillHandler?.IsActivatingSkill ?? false; + var isStunned = _stunnable?.IsStunned ?? false; + var isAttacking = _comboAttackable?.CurrentComboAttackCount > 0; + + return !isActivatingSkill && !isStunned && !isAttacking; } public void AddForce(Vector3 force, ForceMode forceMode) { - if (_isDashing) return; + if (IsDashing) return; Rigidbody.AddForce(force, forceMode); } - private void ApplyMovement() + public void Move() { CurrentDirection = _inputDirection; IsMoving = _inputDirection != Vector3.zero; - // var finalVelocity = _inputDirection * (MoveSpeed * _moveSpeedCoefficient); - // Rigidbody.linearVelocity = finalVelocity; - - var finalVelocity = _inputDirection * (MoveSpeed * _moveSpeedCoefficient * Time.deltaTime); + var finalVelocity = _inputDirection * (MoveSpeed * MoveSpeedCoefficient * Time.deltaTime); Rigidbody.MovePosition(transform.position + finalVelocity); } // Dash public bool CanDash() { - return EnableMove && EnableDash && !IsDashing && !IsDashCoolDownActive; + if (!IsDashEnabled || IsDashing || IsDashCoolDownActive) return false; + + var isActivatingSkill = _skillHandler?.IsActivatingSkill ?? false; + var isStunned = _stunnable?.IsStunned ?? false; + + if (isActivatingSkill || isStunned) return false; + + var isAttacking = _comboAttackable?.CurrentComboAttackCount > 0; + if (isAttacking) + { + _comboAttackable.EndAttack(); + } + + return true; } - public void HandleDash() + public void Dash() { if (!CanDash()) return; @@ -204,7 +212,6 @@ namespace BlueWater.Players.Combat private IEnumerator DashCoroutine() { - OnStartDash?.Invoke(); IsDashing = true; IsDashCoolDownActive = true; @@ -225,25 +232,26 @@ namespace BlueWater.Players.Combat while (_animationController.IsComparingCurrentAnimation("DashState") && _animationController.GetCurrentAnimationNormalizedTime() < 1f) { - //var finalVelocity = rb.position + dashDirection * (dashSpeed * Time.fixedDeltaTime); - //rb.MovePosition(finalVelocity); + var finalVelocity = transform.position + dashDirection * (DashSpeed * Time.fixedDeltaTime); + Rigidbody.MovePosition(finalVelocity); - var finalVelocity = dashDirection * DashSpeed; - Rigidbody.linearVelocity = finalVelocity; yield return new WaitForFixedUpdate(); } EndDash(DashCooldown); } - public void EndDash(float dashCooldown) + public void EndDash(float dashCooldown = float.PositiveInfinity) { Utils.EndUniqueCoroutine(this, ref _dashCoroutine); Rigidbody.linearVelocity = Vector3.zero; _animationController.ResetAnimationSpeed(); - OnEndDash?.Invoke(); IsDashing = false; - + + if (float.IsPositiveInfinity(dashCooldown)) + { + dashCooldown = DashCooldown; + } StartCoroutine(Utils.CoolDownCoroutine(dashCooldown, () => IsDashCoolDownActive = false)); } diff --git a/Assets/02.Scripts/Character/Player/Combat/CombatPlayer.cs b/Assets/02.Scripts/Character/Player/Combat/CombatPlayer.cs index 43a91affa..88cadf464 100644 --- a/Assets/02.Scripts/Character/Player/Combat/CombatPlayer.cs +++ b/Assets/02.Scripts/Character/Player/Combat/CombatPlayer.cs @@ -33,21 +33,21 @@ namespace BlueWater.Players.Combat [field: SerializeField] public Animator Animator { get; private set; } + [field: SerializeField] + public PlayerHealthPoint PlayerHealthPoint { get; private set; } + + [field: SerializeField] + public AnimationController AnimationController { get; private set; } + [field: SerializeField] public CombatInput CombatInput { get; private set; } [field: SerializeField] public CombatMovement CombatMovement { get; private set; } - [field: SerializeField] - public AnimationController AnimationController { get; private set; } - [field: SerializeField] public CombatAttacker CombatAttacker { get; private set; } - [field: SerializeField] - public PlayerHealthPoint PlayerHealthPoint { get; private set; } - [field: SerializeField] public CombatSkillController CombatSkillController { get; private set; } @@ -62,7 +62,6 @@ namespace BlueWater.Players.Combat private void Awake() { InitializeComponents(); - InitializeChileComponents(); } private void Start() @@ -96,24 +95,15 @@ namespace BlueWater.Players.Combat Animator = VisualLook.GetComponent(); HitBoxCollider = transform.Find("HitBox").GetComponent(); + PlayerHealthPoint = GetComponent(); + AnimationController = GetComponent(); CombatInput = GetComponent(); CombatMovement = GetComponent(); - AnimationController = GetComponent(); CombatAttacker = GetComponent(); - PlayerHealthPoint = GetComponent(); CombatSkillController = GetComponent(); CombatStatus = GetComponent(); } - private void InitializeChileComponents() - { - CombatInput.InitializeComponents(PlayerInput); - CombatMovement.InitializeComponents(Rigidbody, VisualLook, AnimationController); - CombatAttacker.InitializeComponents(Rigidbody, AnimationController, CombatMovement); - PlayerHealthPoint.InitializeComponents(SpriteRenderer); - CombatStatus.InitializeComponents(SpriteRenderer); - } - #endregion // Methods @@ -122,103 +112,25 @@ namespace BlueWater.Players.Combat private void SubscribeEvents() { // Input - CombatInput.OnMoveInputReceived += CombatMovement.HandleInputMovement; - CombatInput.OnDashInputReceived += CombatMovement.HandleDash; - CombatInput.OnAttackInputReceived += CombatAttacker.HandleAttack; - CombatInput.OnActivateMainSkillInputReceived += CombatSkillController.HandleMainSkill; - - // Movement - CombatMovement.OnStartDash += CombatAttacker.HandleDashInAttack; - CombatMovement.OnStartDash += CombatSkillController.HandleDisableSkill; - CombatMovement.OnStartDash += PlayerHealthPoint.HandleDisableTakeDamage; - CombatMovement.OnStartDash += CombatStatus.HandleCanNotApplyStatusEffect; - - CombatMovement.OnEndDash += CombatSkillController.HandleEnableSkill; - CombatMovement.OnEndDash += PlayerHealthPoint.HandleEnableTakeDamage; - CombatMovement.OnEndDash += CombatStatus.HandleCanApplyStatusEffect; - - // Attacker - CombatAttacker.OnStartAttack += CombatMovement.HandleAttackInDash; - CombatAttacker.OnStartAttack += CombatMovement.HandleDisableMove; - CombatAttacker.OnStartAttack += CombatSkillController.HandleDisableSkill; - - CombatAttacker.OnEndAttack += CombatMovement.HandleEnableMove; - CombatAttacker.OnEndAttack += CombatSkillController.HandleEnableSkill; + CombatInput.OnMoveInputReceived += CombatMovement.InputMovement; + CombatInput.OnDashInputReceived += CombatMovement.Dash; + CombatInput.OnAttackInputReceived += CombatAttacker.Attack; + CombatInput.OnActivateMainSkillInputReceived += CombatSkillController.TryActivateSkill; // PlayerHealthPoint PlayerHealthPoint.OnDead += Die; - - // SkillController - CombatSkillController.OnStartSkill += CombatMovement.HandleDisableMoveAndDash; - CombatSkillController.OnStartSkill += CombatAttacker.HandleDisableAttack; - CombatSkillController.OnStartSkill += PlayerHealthPoint.HandleDisableTakeDamage; - - CombatSkillController.OnEndSkill += CombatMovement.HandleEnableMoveAndDash; - CombatSkillController.OnEndSkill += CombatAttacker.HandleEnableAttack; - CombatSkillController.OnEndSkill += PlayerHealthPoint.HandleEnableTakeDamage; - - // Status - CombatStatus.OnStartStun += CombatMovement.HandleDisableMoveAndDash; - CombatStatus.OnStartStun += CombatAttacker.HandleDisableAttack; - CombatStatus.OnStartStun += CombatSkillController.HandleDisableSkill; - - CombatStatus.OnEndStun += CombatMovement.HandleEnableMoveAndDash; - CombatStatus.OnEndStun += CombatAttacker.HandleEnableAttack; - CombatStatus.OnEndStun += CombatSkillController.HandleEnableSkill; - - CombatStatus.OnStartSlowMoveSpeed += CombatMovement.HandleMoveSpeedCoefficient; - CombatStatus.OnEndSlowMoveSpeed += CombatMovement.HandleResetMoveSpeedCoefficient; } private void UnSubscribeEvents() { // Input - CombatInput.OnMoveInputReceived -= CombatMovement.HandleInputMovement; - CombatInput.OnDashInputReceived -= CombatMovement.HandleDash; - CombatInput.OnAttackInputReceived -= CombatAttacker.HandleAttack; - CombatInput.OnActivateMainSkillInputReceived -= CombatSkillController.HandleMainSkill; - - // Movement - CombatMovement.OnStartDash -= CombatAttacker.HandleDashInAttack; - CombatMovement.OnStartDash -= CombatSkillController.HandleDisableSkill; - CombatMovement.OnStartDash -= PlayerHealthPoint.HandleDisableTakeDamage; - CombatMovement.OnStartDash -= CombatStatus.HandleCanNotApplyStatusEffect; - - CombatMovement.OnEndDash -= CombatSkillController.HandleEnableSkill; - CombatMovement.OnEndDash -= PlayerHealthPoint.HandleEnableTakeDamage; - CombatMovement.OnEndDash -= CombatStatus.HandleCanApplyStatusEffect; - - // Attacker - CombatAttacker.OnStartAttack -= CombatMovement.HandleAttackInDash; - CombatAttacker.OnStartAttack -= CombatMovement.HandleDisableMove; - CombatAttacker.OnStartAttack -= CombatSkillController.HandleDisableSkill; - - CombatAttacker.OnEndAttack -= CombatMovement.HandleEnableMove; - CombatAttacker.OnEndAttack -= CombatSkillController.HandleEnableSkill; + CombatInput.OnMoveInputReceived -= CombatMovement.InputMovement; + CombatInput.OnDashInputReceived -= CombatMovement.Dash; + CombatInput.OnAttackInputReceived -= CombatAttacker.Attack; + CombatInput.OnActivateMainSkillInputReceived -= CombatSkillController.TryActivateSkill; // PlayerHealthPoint PlayerHealthPoint.OnDead -= Die; - - // SkillController - CombatSkillController.OnStartSkill -= CombatMovement.HandleDisableMoveAndDash; - CombatSkillController.OnStartSkill -= CombatAttacker.HandleDisableAttack; - CombatSkillController.OnStartSkill -= PlayerHealthPoint.HandleDisableTakeDamage; - - CombatSkillController.OnEndSkill -= CombatMovement.HandleEnableMoveAndDash; - CombatSkillController.OnEndSkill -= CombatAttacker.HandleEnableAttack; - CombatSkillController.OnEndSkill -= PlayerHealthPoint.HandleEnableTakeDamage; - - // Status - CombatStatus.OnStartStun -= CombatMovement.HandleDisableMoveAndDash; - CombatStatus.OnStartStun -= CombatAttacker.HandleDisableAttack; - CombatStatus.OnStartStun -= CombatSkillController.HandleDisableSkill; - - CombatStatus.OnEndStun -= CombatMovement.HandleEnableMoveAndDash; - CombatStatus.OnEndStun -= CombatAttacker.HandleEnableAttack; - CombatStatus.OnEndStun -= CombatSkillController.HandleEnableSkill; - - CombatStatus.OnStartSlowMoveSpeed -= CombatMovement.HandleMoveSpeedCoefficient; - CombatStatus.OnEndSlowMoveSpeed -= CombatMovement.HandleResetMoveSpeedCoefficient; } private void Die() @@ -259,9 +171,6 @@ namespace BlueWater.Players.Combat Destroy(gameObject); CombatUiManager.Instance.GameOverPopupUi.Open(CombatUiManager.Instance.PopupUiList); } - - // Wrapping methods - public LayerMask TargetLayer => CombatAttacker.TargetLayer; #endregion } diff --git a/Assets/02.Scripts/Character/Player/Combat/CombatSkillController.cs b/Assets/02.Scripts/Character/Player/Combat/CombatSkillController.cs deleted file mode 100644 index 8922beb8f..000000000 --- a/Assets/02.Scripts/Character/Player/Combat/CombatSkillController.cs +++ /dev/null @@ -1,92 +0,0 @@ -using System; -using BlueWater.Uis; -using UnityEngine; - -namespace BlueWater.Players.Combat -{ - public class CombatSkillController : MonoBehaviour - { - // Variables - #region Variables - - // Components - [SerializeField] - private BaseSkill _mainSkillPrefab; - private BaseSkill _instantiateMainSkill; - - // Variables - private bool _enableSkill = true; - private bool _isActivatingSkill; - - // Events - public event Action OnStartSkill; - public event Action OnEndSkill; - - #endregion - - // Unity events - #region Unity events - - private void Start() - { - InitSkill(); - } - - private void OnDestroy() - { - if (_instantiateMainSkill) - { - Destroy(_instantiateMainSkill.gameObject); - } - } - - #endregion - - // Initialize methods - #region Initialize methods - - private void InitSkill() - { - _instantiateMainSkill = Instantiate(_mainSkillPrefab); - _instantiateMainSkill.Initialize(gameObject); - CombatUiManager.Instance.CombatSkillUi.ResetSkillUi(); - } - - #endregion - - // Methods - #region Methods - - // Events methods - public void HandleEnableSkill() => _enableSkill = true; - public void HandleDisableSkill() => _enableSkill = false; - - public void HandleMainSkill() - { - if (!CanSkill()) return; - - OnStartSkill?.Invoke(); - _enableSkill = false; - _isActivatingSkill = true; - _instantiateMainSkill.ActivateSkill(EndSkill); - } - - // Methods - - private bool CanSkill() - { - if (!_enableSkill || _isActivatingSkill) return false; - - return _instantiateMainSkill.CanSkill(); - } - - private void EndSkill() - { - OnEndSkill?.Invoke(); - _isActivatingSkill = false; - _enableSkill = true; - } - - #endregion - } -} \ No newline at end of file diff --git a/Assets/02.Scripts/Character/Player/Combat/CombatStatus.cs b/Assets/02.Scripts/Character/Player/Combat/CombatStatus.cs index 2afd2f069..274566217 100644 --- a/Assets/02.Scripts/Character/Player/Combat/CombatStatus.cs +++ b/Assets/02.Scripts/Character/Player/Combat/CombatStatus.cs @@ -1,4 +1,3 @@ -using System; using BlueWater.Interfaces; using BlueWater.Utility; using Sirenix.OdinInspector; @@ -12,15 +11,22 @@ namespace BlueWater.Players.Combat #region Variables // Components + [SerializeField] private SpriteRenderer _spriteRenderer; + private IPhysicMovable _physicMovable; + private IDashable _dashable; + private IComboAttackable _comboAttackable; + private ISkillHandler _skillHandler; + // Stun [Title("기절 효과")] [SerializeField] private ParticleSystem _stunParticle; - + + public bool IsStunEnabled { get; private set; } = true; public bool IsStunned { get; private set; } - + private Coroutine _stunCoolDownCoroutine; // Slow @@ -29,29 +35,38 @@ namespace BlueWater.Players.Combat [SerializeField] private Color _slowEffectColor; + public bool IsSlowMoveEnabled { get; private set; } = true; public bool IsSlowedMoveSpeed { get; private set; } + private Coroutine _slowMoveSpeedCoolDownCoroutine; - // Variables - private bool _canApplyStatusEffect = true; - - // Events - public event Action OnStartStun; - public event Action OnEndStun; - public event Action OnStartSlowMoveSpeed; - public event Action OnEndSlowMoveSpeed; - // Hashes private static readonly int _colorHash = Shader.PropertyToID("_Color"); #endregion + // Unity events + #region Unity events + + private void Awake() + { + InitializeComponents(); + } + + #endregion + // Initialize methods #region Initialize methods - public void InitializeComponents(SpriteRenderer spriteRenderer) + [Button("컴포넌트 초기화")] + private void InitializeComponents() { - _spriteRenderer = spriteRenderer; + _spriteRenderer = GetComponentInChildren(); + + _physicMovable = GetComponent(); + _dashable = GetComponent(); + _comboAttackable = GetComponent(); + _skillHandler = GetComponent(); } #endregion @@ -59,49 +74,65 @@ namespace BlueWater.Players.Combat // Methods #region Methods - // Event methods - public void HandleCanApplyStatusEffect() => _canApplyStatusEffect = true; - public void HandleCanNotApplyStatusEffect() => _canApplyStatusEffect = false; - // Stun + public bool CanStun() + { + if (!IsStunEnabled) return false; + + var isDashing = _dashable?.IsDashing ?? false; + var isActivatingSkill = _skillHandler?.IsActivatingSkill ?? false; + + return !isDashing && !isActivatingSkill; + } + public void Stun(float duration) { - if (!_canApplyStatusEffect) return; + if (!IsStunEnabled) return; + + _stunParticle.Play(); IsStunned = true; - _stunParticle.Play(); - OnStartStun?.Invoke(); - Utils.StartUniqueCoroutine(this, ref _stunCoolDownCoroutine, Utils.CoolDownCoroutine(duration, EndStun)); } public void EndStun() { - Utils.EndUniqueCoroutine(this, ref _stunCoolDownCoroutine); + IsStunned = false; + _stunParticle.Stop(); _stunParticle.Clear(); - OnEndStun?.Invoke(); - IsStunned = false; + Utils.EndUniqueCoroutine(this, ref _stunCoolDownCoroutine); } // Slow + public bool CanSlowMove() + { + if (!IsSlowMoveEnabled) return false; + + var isDashing = _dashable?.IsDashing ?? false; + var isActivatingSkill = _skillHandler?.IsActivatingSkill ?? false; + + return !isDashing && !isActivatingSkill; + } + public void SlowMoveSpeed(float duration, float moveSpeedCoefficient) { - if (!_canApplyStatusEffect) return; + if (!IsSlowMoveEnabled) return; + + _spriteRenderer.material.SetColor(_colorHash, _slowEffectColor); + _physicMovable?.SetMoveSpeedCoefficient(moveSpeedCoefficient); IsSlowedMoveSpeed = true; - _spriteRenderer.material.SetColor(_colorHash, _slowEffectColor); - OnStartSlowMoveSpeed?.Invoke(moveSpeedCoefficient); - Utils.StartUniqueCoroutine(this, ref _slowMoveSpeedCoolDownCoroutine, Utils.CoolDownCoroutine(duration, EndSlowMoveSpeed)); } public void EndSlowMoveSpeed() { - Utils.EndUniqueCoroutine(this, ref _slowMoveSpeedCoolDownCoroutine); - _spriteRenderer.material.SetColor(_colorHash, Color.white); - OnEndSlowMoveSpeed?.Invoke(); IsSlowedMoveSpeed = false; + + _spriteRenderer.material.SetColor(_colorHash, Color.white); + _physicMovable?.ResetMoveSpeedCoefficient(); + Utils.EndUniqueCoroutine(this, ref _slowMoveSpeedCoolDownCoroutine); } #endregion diff --git a/Assets/02.Scripts/Character/Player/PlayerHealthPoint.cs b/Assets/02.Scripts/Character/Player/PlayerHealthPoint.cs index 5c7b1a193..4cd34436f 100644 --- a/Assets/02.Scripts/Character/Player/PlayerHealthPoint.cs +++ b/Assets/02.Scripts/Character/Player/PlayerHealthPoint.cs @@ -4,6 +4,7 @@ using BlueWater.Audios; using BlueWater.Interfaces; using BlueWater.Uis; using BlueWater.Utility; +using Sirenix.OdinInspector; using UnityEngine; namespace BlueWater.Players @@ -11,7 +12,11 @@ namespace BlueWater.Players public class PlayerHealthPoint : MonoBehaviour, IDamageable { // Components + [SerializeField] private SpriteRenderer _spriteRenderer; + + private IDashable _dashable; + private ISkillHandler _skillHandler; // Variables [field: SerializeField] @@ -19,11 +24,11 @@ namespace BlueWater.Players [field: SerializeField] public int CurrentHealthPoint { get; private set; } + + [field: SerializeField] + public float InvincibilityDuration { get; private set; } = 0.5f; - [SerializeField] - private float _damageInterval = 0.5f; - - private bool _enableTakeDamage = true; + public bool IsInvincible { get; private set; } private WaitForSeconds _flashWhiteWaitTime; private Coroutine _flashWhiteCoroutine; private Coroutine _damageIntervalCoroutine; @@ -36,11 +41,16 @@ namespace BlueWater.Players public event Action OnDead; // Unity events + private void Awake() + { + InitializeComponents(); + } + private void Start() { OnHealthChanged += CombatUiManager.Instance.PlayerHealthPointUi.SetCurrentHealthPoint; - _flashWhiteWaitTime = new WaitForSeconds(_damageInterval * 0.1f); + _flashWhiteWaitTime = new WaitForSeconds(InvincibilityDuration * 0.1f); SetCurrentHealthPoint(MaxHealthPoint); } @@ -53,15 +63,15 @@ namespace BlueWater.Players } // Initialize methods - public void InitializeComponents(SpriteRenderer spriteRenderer) + [Button("컴포넌트 초기화")] + private void InitializeComponents() { - _spriteRenderer = spriteRenderer; + _spriteRenderer = GetComponentInChildren(); + + _dashable = GetComponent(); + _skillHandler = GetComponent(); } - // Events methods - public void HandleEnableTakeDamage() => _enableTakeDamage = true; - public void HandleDisableTakeDamage() => _enableTakeDamage = false; - // Methods public void SetCurrentHealthPoint(int changedHealthPoint) { @@ -80,12 +90,17 @@ namespace BlueWater.Players public bool CanDamage() { - return _enableTakeDamage; + if (IsInvincible) return false; + + var isDashing = _dashable?.IsDashing ?? false; + var isActivatingSkill = _skillHandler?.IsActivatingSkill ?? false; + + return !isDashing && !isActivatingSkill; } public void TakeDamage(int damageAmount) { - HandleDisableTakeDamage(); + IsInvincible = true; var changeHp = Mathf.Max(CurrentHealthPoint - damageAmount, 0); SetCurrentHealthPoint(changeHp); AudioManager.Instance.PlaySfx("CombatPlayerAttacked"); @@ -101,7 +116,7 @@ namespace BlueWater.Players { Utils.StartUniqueCoroutine(this, ref _flashWhiteCoroutine, FlashWhiteCoroutine()); } - Utils.StartUniqueCoroutine(this, ref _damageIntervalCoroutine, Utils.CoolDownCoroutine(_damageInterval, EndDamageIntervalCoroutine)); + Utils.StartUniqueCoroutine(this, ref _damageIntervalCoroutine, Utils.CoolDownCoroutine(InvincibilityDuration, EndDamageIntervalCoroutine)); } public void TryTakeDamage(int damageAmount) @@ -131,8 +146,8 @@ namespace BlueWater.Players private void EndDamageIntervalCoroutine() { + IsInvincible = false; Utils.EndUniqueCoroutine(this, ref _damageIntervalCoroutine); - HandleEnableTakeDamage(); } } } \ No newline at end of file diff --git a/Assets/02.Scripts/Character/Player/Tycoon/TycoonMovement.cs b/Assets/02.Scripts/Character/Player/Tycoon/TycoonMovement.cs index dd257beab..cb09995bc 100644 --- a/Assets/02.Scripts/Character/Player/Tycoon/TycoonMovement.cs +++ b/Assets/02.Scripts/Character/Player/Tycoon/TycoonMovement.cs @@ -16,8 +16,10 @@ namespace BlueWater.Players.Tycoons // Move [field: SerializeField, Range(1f, 10f), Tooltip("이동 속도")] public float MoveSpeed { get; private set; } = 7f; - - public bool EnableMove { get; private set; } = true; + + public float MoveSpeedCoefficient { get; private set; } = 1f; + + public bool IsMoveEnabled { get; private set; } = true; private bool _isMoving; public bool IsMoving @@ -40,7 +42,7 @@ namespace BlueWater.Players.Tycoons public Vector3 CurrentDirection { get => _currentDirection; - set + private set { if (value == Vector3.zero) return; @@ -69,7 +71,7 @@ namespace BlueWater.Players.Tycoons { if (!CanMove()) return; - ApplyMovement(); + Move(); } #endregion @@ -93,9 +95,12 @@ namespace BlueWater.Players.Tycoons { _inputDirection = new Vector3(movementInput.x, 0, movementInput.y).normalized; } - - public void HandleEnableMove() => EnableMove = true; - public void HandleDisableMove() => EnableMove = false; + + public void SetMoveSpeedCoefficient(float value) => MoveSpeedCoefficient = value; + public void ResetMoveSpeedCoefficient() => MoveSpeedCoefficient = 1f; + public void EnableMove() => IsMoveEnabled = true; + public void DisableMove() => IsMoveEnabled = false; + public void SetCurrentDirection(Vector3 normalDirection) => CurrentDirection = normalDirection; // Methods private void FlipVisualLook() @@ -113,7 +118,7 @@ namespace BlueWater.Players.Tycoons // Move public bool CanMove() { - return EnableMove; + return IsMoveEnabled; } public void AddForce(Vector3 force, ForceMode forceMode) @@ -121,7 +126,7 @@ namespace BlueWater.Players.Tycoons Rigidbody.AddForce(force, forceMode); } - private void ApplyMovement() + public void Move() { CurrentDirection = _inputDirection; IsMoving = _inputDirection != Vector3.zero; diff --git a/Assets/02.Scripts/Interface/IComboAttackable.cs b/Assets/02.Scripts/Interface/IComboAttackable.cs new file mode 100644 index 000000000..3e5478301 --- /dev/null +++ b/Assets/02.Scripts/Interface/IComboAttackable.cs @@ -0,0 +1,22 @@ +using BlueWater.Players.Combat; +using UnityEngine; + +namespace BlueWater.Interfaces +{ + public interface IComboAttackable + { + int MaxHitCount { get; } + ComboAttack[] ComboAttacks { get; } + bool IsAttackEnabled { get; } + bool IsComboAttackPossible { get; } + bool IsComboAttacking { get; } + int CurrentComboAttackCount { get; set; } + Collider[] HitColliders { get; } + LayerMask TargetLayer { get; } + LayerMask MouseClickLayer { get; } + + bool CanAttack(); + void EndAttack(); + void Attack(bool usedMouseAttack); + } +} \ No newline at end of file diff --git a/Assets/02.Scripts/Interface/IComboAttackable.cs.meta b/Assets/02.Scripts/Interface/IComboAttackable.cs.meta new file mode 100644 index 000000000..8025db532 --- /dev/null +++ b/Assets/02.Scripts/Interface/IComboAttackable.cs.meta @@ -0,0 +1,3 @@ +fileFormatVersion: 2 +guid: 2baae403c5973434e9fad1450d077334 +timeCreated: 1716899052 diff --git a/Assets/02.Scripts/Interface/IDamagable.cs b/Assets/02.Scripts/Interface/IDamagable.cs index 395e99d75..26b805589 100644 --- a/Assets/02.Scripts/Interface/IDamagable.cs +++ b/Assets/02.Scripts/Interface/IDamagable.cs @@ -4,7 +4,9 @@ namespace BlueWater.Interfaces { int MaxHealthPoint { get; } int CurrentHealthPoint { get; } - + bool IsInvincible { get; } + float InvincibilityDuration { get; } + void SetCurrentHealthPoint(int changedHealthPoint); bool CanDamage(); void TakeDamage(int damageAmount); diff --git a/Assets/02.Scripts/Interface/IDashable.cs b/Assets/02.Scripts/Interface/IDashable.cs index dcd4bbd22..256bccc30 100644 --- a/Assets/02.Scripts/Interface/IDashable.cs +++ b/Assets/02.Scripts/Interface/IDashable.cs @@ -2,14 +2,15 @@ { public interface IDashable { - bool EnableDash { get; } + bool IsDashEnabled { get; } bool IsDashing { get; } bool IsDashCoolDownActive { get; } float DashSpeed { get; } float DashTime { get; } float DashCooldown { get; } + bool CanDash(); - void HandleEnableDash(); - void HandleDisableDash(); + void Dash(); + void EndDash(float dashCooldown = float.PositiveInfinity); } } \ No newline at end of file diff --git a/Assets/02.Scripts/Interface/IPhysicMovable.cs b/Assets/02.Scripts/Interface/IPhysicMovable.cs index 9138de501..8de979ef7 100644 --- a/Assets/02.Scripts/Interface/IPhysicMovable.cs +++ b/Assets/02.Scripts/Interface/IPhysicMovable.cs @@ -6,10 +6,16 @@ namespace BlueWater.Interfaces { Rigidbody Rigidbody { get; } float MoveSpeed { get; } - bool EnableMove { get; } + float MoveSpeedCoefficient { get; } + bool IsMoveEnabled { get; } bool IsMoving { get; } - Vector3 CurrentDirection { get; set; } + Vector3 CurrentDirection { get; } + + void SetMoveSpeedCoefficient(float value); + void ResetMoveSpeedCoefficient(); + void SetCurrentDirection(Vector3 normalDirection); bool CanMove(); + void Move(); void AddForce(Vector3 force, ForceMode forceMode); } } \ No newline at end of file diff --git a/Assets/02.Scripts/Interface/ISkillHandler.cs b/Assets/02.Scripts/Interface/ISkillHandler.cs new file mode 100644 index 000000000..4f8518901 --- /dev/null +++ b/Assets/02.Scripts/Interface/ISkillHandler.cs @@ -0,0 +1,28 @@ +using System.Collections.Generic; + +namespace BlueWater.Interfaces +{ + public interface ISkillHandler + { + List Skills { get; } + Dictionary SkillInstances { get; } + BaseSkill CurrentActivatingSkill { get; } + bool IsSkillEnabled { get; } + bool IsActivatingSkill { get; } + + void EnableSkill(); + void DisableSkill(); + bool HasSkill(string skillName); + bool CanSkill(string skillName); + + /// + /// HasSkill()만 확인하고 스킬을 강제로 사용 + /// + void ActivateSkill(string skillName); + + /// + /// HasSkill(), CanSkill()를 모두 확인하고 스킬을 사용하기까지 모든 과정 + /// + void TryActivateSkill(string skillName); + } +} \ No newline at end of file diff --git a/Assets/02.Scripts/Interface/ISkillHandler.cs.meta b/Assets/02.Scripts/Interface/ISkillHandler.cs.meta new file mode 100644 index 000000000..fd85ff9fa --- /dev/null +++ b/Assets/02.Scripts/Interface/ISkillHandler.cs.meta @@ -0,0 +1,3 @@ +fileFormatVersion: 2 +guid: 8a67c0e0914676b42b45b9b987cc6ce6 +timeCreated: 1716899052 diff --git a/Assets/02.Scripts/Interface/ISlowable.cs b/Assets/02.Scripts/Interface/ISlowable.cs index ea3279995..d8c233f9d 100644 --- a/Assets/02.Scripts/Interface/ISlowable.cs +++ b/Assets/02.Scripts/Interface/ISlowable.cs @@ -2,7 +2,10 @@ { public interface ISlowable { + bool IsSlowMoveEnabled { get; } bool IsSlowedMoveSpeed { get; } + + bool CanSlowMove(); void SlowMoveSpeed(float duration, float moveSpeedCoefficient); void EndSlowMoveSpeed(); } diff --git a/Assets/02.Scripts/Interface/IStunnable.cs b/Assets/02.Scripts/Interface/IStunnable.cs index 7d140711d..eb3e031c2 100644 --- a/Assets/02.Scripts/Interface/IStunnable.cs +++ b/Assets/02.Scripts/Interface/IStunnable.cs @@ -2,7 +2,10 @@ { public interface IStunnable { + bool IsStunEnabled { get; } bool IsStunned { get; } + + bool CanStun(); void Stun(float duration); void EndStun(); } diff --git a/Assets/02.Scripts/PlayerInputKeyManager.cs b/Assets/02.Scripts/PlayerInputKeyManager.cs index 05811ddb1..4f95a9de5 100644 --- a/Assets/02.Scripts/PlayerInputKeyManager.cs +++ b/Assets/02.Scripts/PlayerInputKeyManager.cs @@ -8,6 +8,7 @@ namespace BlueWater None = 0, Tycoon, TycoonUi, + CombatTitle, Combat, CombatUi, } @@ -16,8 +17,6 @@ namespace BlueWater { [SerializeField] private PlayerInput _currentPlayerInput; - private string _previousInputActionMaps; - private InputActionMap _previousInputActionMap; /// /// 현재 실행되고 있는 PlayerInput을 관리할 수 있게 @@ -28,7 +27,7 @@ namespace BlueWater private bool IsNullCurrentPlayerInput() { - if (_currentPlayerInput) return false; + if (_currentPlayerInput && _currentPlayerInput.enabled) return false; Debug.Log("CurrentPlayerInput가 할당되지 않았습니다."); return true; @@ -38,7 +37,6 @@ namespace BlueWater { if (IsNullCurrentPlayerInput()) return; - _previousInputActionMaps = _currentPlayerInput.currentActionMap.name; _currentPlayerInput.SwitchCurrentActionMap(inputActionMaps); } @@ -46,24 +44,9 @@ namespace BlueWater { if (IsNullCurrentPlayerInput()) return; - _previousInputActionMaps = _currentPlayerInput.currentActionMap.name; _currentPlayerInput.SwitchCurrentActionMap(inputActionMaps.ToString()); } - public void SwitchPreviousActionMap() - { - if (IsNullCurrentPlayerInput()) return; - - if (string.IsNullOrEmpty(_previousInputActionMaps)) - { - Debug.Log("저장된 _previousInputActionMaps값이 없습니다."); - return; - } - - _currentPlayerInput.SwitchCurrentActionMap(_previousInputActionMaps); - _previousInputActionMaps = null; - } - public InputActionMap GetCurrentInputActionMap() { if (IsNullCurrentPlayerInput()) return null; @@ -114,7 +97,7 @@ namespace BlueWater } } - public void EnableAllActions() + public void EnableAllActionsMaps() { if (IsNullCurrentPlayerInput()) return; diff --git a/Assets/02.Scripts/Prop/DamageableProps.cs b/Assets/02.Scripts/Prop/DamageableProps.cs index 0da64fbf8..edfcb1798 100644 --- a/Assets/02.Scripts/Prop/DamageableProps.cs +++ b/Assets/02.Scripts/Prop/DamageableProps.cs @@ -15,6 +15,11 @@ namespace BlueWater [field: SerializeField] public int CurrentHealthPoint { get; private set; } + public bool IsInvincible { get; private set; } + + [field: SerializeField] + public float InvincibilityDuration { get; private set; } + [Title("Die 설정")] [SerializeField] private string _dieSfxName; diff --git a/Assets/02.Scripts/Skill/BaseSkill.cs b/Assets/02.Scripts/Skill/BaseSkill.cs index ba507ef92..987aa158b 100644 --- a/Assets/02.Scripts/Skill/BaseSkill.cs +++ b/Assets/02.Scripts/Skill/BaseSkill.cs @@ -100,6 +100,7 @@ namespace BlueWater } public virtual bool CanSkill() => EnableSkill; + /// 0번째 actions은 스킬이 종료된 후 실행해야하는 것들 public abstract void ActivateSkill(params Action[] actions); protected void EndCooldown() @@ -109,6 +110,7 @@ namespace BlueWater } public string SkillName => SkillData.Name; + public float Cooldown => SkillData.Cooldown; #endregion } diff --git a/Assets/02.Scripts/Skill/Enemy/Boss/TitanSlime/JumpSlam.cs b/Assets/02.Scripts/Skill/Enemy/Boss/TitanSlime/JumpSlam.cs index a8275a83b..782e89774 100644 --- a/Assets/02.Scripts/Skill/Enemy/Boss/TitanSlime/JumpSlam.cs +++ b/Assets/02.Scripts/Skill/Enemy/Boss/TitanSlime/JumpSlam.cs @@ -222,8 +222,14 @@ namespace BlueWater.Enemies.Bosses.TitanSlime.Skills Utils.StartUniqueCoroutine(this, ref CooldownCoroutineInstance,Utils.CoolDownCoroutine(cooldown, EndCooldown)); } - private Vector3 CalculateRandomPosition(Vector3 startPosition, float range, int iterationCount = 100) + private Vector3 CalculateRandomPosition(Vector3 startPosition, float range, int iterationCount = 1000) { + var nearestNodeInfo = AstarPath.active.GetNearest(startPosition); + if (nearestNodeInfo.node is not { Walkable: true }) + { + startPosition = nearestNodeInfo.position; + } + for (var i = 0; i < iterationCount; i++) { var randomPosition = startPosition + Random.insideUnitSphere * range; @@ -233,8 +239,7 @@ namespace BlueWater.Enemies.Bosses.TitanSlime.Skills return randomPosition; } - - Debug.Log($"{SkillUser.name}이 랜덤으로 이동할 위치를 찾지 못했습니다."); + return startPosition; } diff --git a/Assets/02.Scripts/Skill/Player/Combat/TheWaltzOfTheSword.cs b/Assets/02.Scripts/Skill/Player/Combat/TheWaltzOfTheSword.cs index d52ff59fb..f52825b33 100644 --- a/Assets/02.Scripts/Skill/Player/Combat/TheWaltzOfTheSword.cs +++ b/Assets/02.Scripts/Skill/Player/Combat/TheWaltzOfTheSword.cs @@ -3,7 +3,6 @@ using System.Collections; using System.Linq; using BlueWater.Audios; using BlueWater.Interfaces; -using BlueWater.Uis; using BlueWater.Utility; using UnityEngine; using Random = UnityEngine.Random; @@ -194,7 +193,7 @@ namespace BlueWater.Players.Combat.Skills case Direction.None: break; case Direction.Left: - _iPhysicMovable.CurrentDirection = Vector3.right; + _iPhysicMovable.SetCurrentDirection(Vector3.right); addX = -hitCollider.bounds.extents.x; _currentDirection = Direction.Back; break; @@ -204,7 +203,7 @@ namespace BlueWater.Players.Combat.Skills _previousLeft = !_previousLeft; break; case Direction.Right: - _iPhysicMovable.CurrentDirection = Vector3.left; + _iPhysicMovable.SetCurrentDirection(Vector3.left); addX = hitCollider.bounds.extents.x; _currentDirection = Direction.Back; break; @@ -260,7 +259,6 @@ namespace BlueWater.Players.Combat.Skills } Utils.StartUniqueCoroutine(this, ref CooldownCoroutineInstance,Utils.CoolDownCoroutine(SkillData.Cooldown, EndCooldown)); - CombatUiManager.Instance.CombatSkillUi.CoolDown(SkillData.Cooldown); } private void SortCollidersByDistance() diff --git a/Assets/02.Scripts/Ui/Combat/CombatTutorialUi.cs b/Assets/02.Scripts/Ui/Combat/CombatTutorialUi.cs index 91b818d3a..b896af036 100644 --- a/Assets/02.Scripts/Ui/Combat/CombatTutorialUi.cs +++ b/Assets/02.Scripts/Ui/Combat/CombatTutorialUi.cs @@ -31,18 +31,17 @@ namespace BlueWater.Uis public void ShowFirstTutorialUi() { - PlayerInputKeyManager.Instance.DisableCurrentPlayerInput(); + PlayerInputKeyManager.Instance.DisableAllActionMaps(); gameObject.SetActive(true); _firstTutorialUi.SetActive(true); _secondTutorialUi.SetActive(false); CurrentTutorialState = TutorialState.First; - StartCoroutine(FirstTutorialCoroutine()); + + Invoke(nameof(FirstTutorialCoroutine), 0.1f); } - private IEnumerator FirstTutorialCoroutine() + private void FirstTutorialCoroutine() { - yield return new WaitForSeconds(0.1f); - PlayerInputKeyManager.Instance.EnableCurrentPlayerInput(); PlayerInputKeyManager.Instance.SwitchCurrentActionMap(InputActionMaps.CombatUi); PlayerInputKeyManager.Instance.DisableAllActionsExcept("InteractionUi"); diff --git a/Assets/02.Scripts/Ui/Combat/CombatUiManager.cs b/Assets/02.Scripts/Ui/Combat/CombatUiManager.cs index f4575f11b..cbe8befd0 100644 --- a/Assets/02.Scripts/Ui/Combat/CombatUiManager.cs +++ b/Assets/02.Scripts/Ui/Combat/CombatUiManager.cs @@ -67,6 +67,11 @@ namespace BlueWater.Uis } private void Start() + { + Invoke(nameof(StartTutorial), 0.1f); + } + + private void StartTutorial() { CombatTutorialUi.ShowFirstTutorialUi(); } diff --git a/Assets/04.Materials/TransparentLit.mat b/Assets/04.Materials/TransparentLit.mat index f51d2fad7..61abb0745 100644 --- a/Assets/04.Materials/TransparentLit.mat +++ b/Assets/04.Materials/TransparentLit.mat @@ -38,6 +38,7 @@ Material: disabledShaderPasses: - MOTIONVECTORS - DepthOnly + - SHADOWCASTER m_LockedProperties: m_SavedProperties: serializedVersion: 3 diff --git a/Assets/05.Prefabs/Characters/Players/CombatPlayer.prefab b/Assets/05.Prefabs/Characters/Players/CombatPlayer.prefab index cdb43b467..0d3e1e1a5 100644 --- a/Assets/05.Prefabs/Characters/Players/CombatPlayer.prefab +++ b/Assets/05.Prefabs/Characters/Players/CombatPlayer.prefab @@ -366,11 +366,11 @@ MonoBehaviour: k__BackingField: {fileID: 6951320512859863136} k__BackingField: {fileID: 5558898291459354456} k__BackingField: {fileID: 3031446967001791208} + k__BackingField: {fileID: 326920787583948413} + k__BackingField: {fileID: 3889238742570113982} k__BackingField: {fileID: 522031830802304584} k__BackingField: {fileID: 181082763061672982} - k__BackingField: {fileID: 3889238742570113982} k__BackingField: {fileID: 6458719908533317799} - k__BackingField: {fileID: 326920787583948413} k__BackingField: {fileID: 3677775080446906429} k__BackingField: {fileID: 9129295631914427799} --- !u!114 &522031830802304584 @@ -385,6 +385,7 @@ MonoBehaviour: m_Script: {fileID: 11500000, guid: c1832000a0f2b5d45b277c98a748c359, type: 3} m_Name: m_EditorClassIdentifier: + _playerInput: {fileID: 6401154187219196241} --- !u!114 &181082763061672982 MonoBehaviour: m_ObjectHideFlags: 0 @@ -397,6 +398,9 @@ MonoBehaviour: m_Script: {fileID: 11500000, guid: 77cb3821bc2d2f74b85d8e49b0395064, type: 3} m_Name: m_EditorClassIdentifier: + k__BackingField: {fileID: 1951754024224882079} + _visualLook: {fileID: 2668222795840865044} + _animationController: {fileID: 3889238742570113982} k__BackingField: 7 k__BackingField: 20 k__BackingField: 0.2 @@ -413,6 +417,7 @@ MonoBehaviour: m_Script: {fileID: 11500000, guid: 17488a2bea6f4126a7877ce5d934f865, type: 3} m_Name: m_EditorClassIdentifier: + _animator: {fileID: 3031446967001791208} --- !u!114 &6458719908533317799 MonoBehaviour: m_ObjectHideFlags: 0 @@ -425,6 +430,8 @@ MonoBehaviour: m_Script: {fileID: 11500000, guid: d7c20927144715848888b335473c5bf0, type: 3} m_Name: m_EditorClassIdentifier: + _rigidbody: {fileID: 1951754024224882079} + _animationController: {fileID: 3889238742570113982} k__BackingField: 10 k__BackingField: - k__BackingField: 10 @@ -440,7 +447,7 @@ MonoBehaviour: k__BackingField: serializedVersion: 2 m_Bits: 4352 - _mouseClickLayer: + k__BackingField: serializedVersion: 2 m_Bits: 32832 _swordAttackParticle: {fileID: 8523211495174882546, guid: 04437dbea0cb46d46be53d3485123127, type: 3} @@ -457,9 +464,10 @@ MonoBehaviour: m_Script: {fileID: 11500000, guid: 6ff2dc3fa7a6be445bf8e71043f86d2e, type: 3} m_Name: m_EditorClassIdentifier: + _spriteRenderer: {fileID: 5558898291459354456} k__BackingField: 4 k__BackingField: 0 - _damageInterval: 0.5 + k__BackingField: 0.5 --- !u!114 &3677775080446906429 MonoBehaviour: m_ObjectHideFlags: 0 @@ -472,7 +480,8 @@ MonoBehaviour: m_Script: {fileID: 11500000, guid: d15d270547a76a547b91e71c596e4fc7, type: 3} m_Name: m_EditorClassIdentifier: - _mainSkillPrefab: {fileID: -3797204096501760660, guid: c2dcf20bc51f1b242961ed33da1867ac, type: 3} + k__BackingField: + - {fileID: -3797204096501760660, guid: c2dcf20bc51f1b242961ed33da1867ac, type: 3} --- !u!114 &9129295631914427799 MonoBehaviour: m_ObjectHideFlags: 0 @@ -485,6 +494,7 @@ MonoBehaviour: m_Script: {fileID: 11500000, guid: 0096d36771e12834592c1d58bf8358a3, type: 3} m_Name: m_EditorClassIdentifier: + _spriteRenderer: {fileID: 5558898291459354456} _stunParticle: {fileID: 8979130989535966673} _slowEffectColor: {r: 0.5921569, g: 0.9843137, b: 0.5882353, a: 0} --- !u!114 &260539324676461127 diff --git a/ProjectSettings/ProjectSettings.asset b/ProjectSettings/ProjectSettings.asset index c7b2e66f2..cd4c52466 100644 --- a/ProjectSettings/ProjectSettings.asset +++ b/ProjectSettings/ProjectSettings.asset @@ -140,7 +140,7 @@ PlayerSettings: loadStoreDebugModeEnabled: 0 visionOSBundleVersion: 1.0 tvOSBundleVersion: 1.0 - bundleVersion: 0.2.1 + bundleVersion: 0.2.2.0 preloadedAssets: - {fileID: -944628639613478452, guid: 4ed6540e2f7ce234888adf8deff1f241, type: 3} metroInputSource: 0