using System; using System.Collections; using BlueWater.Interfaces; using BlueWater.Tycoons; using BlueWater.Utility; using Sirenix.OdinInspector; using UnityEngine; namespace BlueWater.Players.Tycoons { public class TycoonMovement : MonoBehaviour, IDashable, IPhysicMovable { // Variables #region Variables // Components public Rigidbody Rigidbody { get; private set; } private Transform _visualLook; // Move [field: SerializeField, Range(1f, 20f), Tooltip("이동 속도")] public float MoveSpeed { get; private set; } = 7f; [field: SerializeField] public float MoveSpeedMultiplier { get; private set; } = 1f; public bool IsMoveEnabled { get; private set; } = true; public bool IsMoving { get; private set; } // Dash [field: Title("대쉬")] [field: SerializeField, Range(1f, 50f), Tooltip("대쉬 속도")] public float DashSpeed { get; private set; } = 20f; [field: SerializeField, Range(0.1f, 1f), Tooltip("대쉬 시간")] public float DashTime { get; private set; } = 0.2f; [field: SerializeField, Range(0f, 5f), Tooltip("대쉬 쿨타임")] public float DashCooldown { get; private set; } = 0.5f; [SerializeField] private ParticleSystem _dashParticle; public bool IsDashEnabled { get; private set; } = true; public bool IsDashing { get; private set; } public bool IsDashCoolDownActive { get; private set; } private Vector3 _inputDirection; private Vector3 _currentDirection = Vector3.back; public Vector3 CurrentDirection { get => _currentDirection; private set { if (value == Vector3.zero) return; _currentDirection = value; } } public Vector3 PushDirection { get; private set; } public float PushPower { get; private set; } public float PushPowerReduction { get; private set; } private Coroutine _dashInstance; private float _finalSpeed; #endregion // Unity events #region Unity events private void Awake() { InitializeComponents(); } private void Update() { FlipVisualLook(); } private void FixedUpdate() { if (!CanMove()) return; Move(); } #endregion // Initialize Methods #region Initialize Methods private void InitializeComponents() { Rigidbody = GetComponent(); _visualLook = transform.Find("VisualLook"); } #endregion // Methods #region Methods // Event methods public void HandleInputMovement(Vector2 movementInput) { _inputDirection = new Vector3(movementInput.x, 0, movementInput.y).normalized; } public void SetMoveSpeedMultiplier(float value) => MoveSpeedMultiplier = value; public void ResetMoveSpeedMultiplier() => MoveSpeedMultiplier = 1f; public void EnableMove() => IsMoveEnabled = true; public void DisableMove() => IsMoveEnabled = false; public void SetCurrentDirection(Vector3 normalDirection) => CurrentDirection = normalDirection; // Methods private void FlipVisualLook() { var localScale = _visualLook.localScale; localScale.x = CurrentDirection.x switch { > 0.01f => -Mathf.Abs(localScale.x), < -0.01f => Mathf.Abs(localScale.x), _ => localScale.x }; _visualLook.localScale = localScale; } // Move public bool CanMove() { return IsMoveEnabled; } public void AddForce(Vector3 force, ForceMode forceMode) { Rigidbody.AddForce(force, forceMode); } public void SetPush(Vector3 pushDirection, float pushPower) { throw new NotImplementedException(); } public void Move() { if (IsDashing) return; CurrentDirection = _inputDirection; IsMoving = _inputDirection != Vector3.zero; var finalVelocity = _inputDirection * (MoveSpeed * MoveSpeedMultiplier); if (!Rigidbody.isKinematic) { Rigidbody.linearVelocity = finalVelocity; } } // Dash public bool CanDash() { if (!IsDashEnabled || IsDashing || IsDashCoolDownActive) return false; return true; } public void Dash() { Utils.StartUniqueCoroutine(this, ref _dashInstance, DashCoroutine()); } private IEnumerator DashCoroutine() { IsDashing = true; IsDashCoolDownActive = true; if (_dashParticle) { _dashParticle.Play(); } var dashDirection = _inputDirection; if (dashDirection == Vector3.zero) { dashDirection = CurrentDirection; } var elapsedTime = 0f; while (elapsedTime <= DashTime) { var finalVelocity = dashDirection * DashSpeed; Rigidbody.linearVelocity = finalVelocity; elapsedTime += Time.fixedDeltaTime; yield return new WaitForFixedUpdate(); } var newDashCooldown = DashCooldown - TycoonManager.Instance.TycoonStatus.PlayerDashCooldownReduction; EndDash(newDashCooldown); } public void EndDash(float dashCooldown = float.PositiveInfinity) { Utils.EndUniqueCoroutine(this, ref _dashInstance); Rigidbody.linearVelocity = Vector3.zero; IsDashing = false; if (float.IsPositiveInfinity(dashCooldown)) { dashCooldown = DashCooldown; } StartCoroutine(Utils.CoolDownCoroutine(dashCooldown, () => IsDashCoolDownActive = false)); } #endregion } }