using System.Collections; using BumpCombat.Combat; using BumpCombat.Constants; using UnityEngine; namespace BumpCombat.Player { [RequireComponent(typeof(Rigidbody2D), typeof(PlayerController))] [RequireComponent(typeof(PlayerStats))] public sealed class DashController : MonoBehaviour { private float dashDuration => GameplayConstants.Current.Artifacts.DashDuration; private float strongDashDuration => GameplayConstants.Current.Artifacts.ChargedDashDuration; private Rigidbody2D body; private PlayerController playerController; private BumpCombatResolver combatResolver; private Animator animator; private CombatFeedback combatFeedback; private static readonly int IsDashingParameter = Animator.StringToHash("IsDashing"); public bool IsDashing { get; private set; } public bool IsStrongDashing { get; private set; } private void Awake() { body = GetComponent(); playerController = GetComponent(); combatResolver = GetComponent(); animator = GetComponent(); combatFeedback = GetComponent(); if (combatFeedback == null) { combatFeedback = gameObject.AddComponent(); } } public bool TryArtifactDash( bool isCharged, ActiveArtifactDefinition definition, int castIdentity = 0) { if (definition == null || IsDashing || playerController == null || playerController.IsDamageKnockbackActive || playerController.IsHurtMovementLocked) { return false; } StartCoroutine(DashRoutine( GetDashDirection(), isCharged, definition, castIdentity)); return true; } private Vector2 GetDashDirection() { return playerController.MoveDirection.sqrMagnitude > 0f ? playerController.MoveDirection.normalized : playerController.FacingDirection.normalized; } private IEnumerator DashRoutine( Vector2 direction, bool isStrongDash, ActiveArtifactDefinition artifactDefinition, int castIdentity) { IsDashing = true; IsStrongDashing = isStrongDash; animator.SetBool(IsDashingParameter, true); float distance = isStrongDash ? artifactDefinition.ChargedRange : artifactDefinition.NormalRange; float duration = isStrongDash ? strongDashDuration : dashDuration; Vector2 start = body.position; Vector2 end = playerController.ClampToArena(start + direction * distance); combatResolver.BeginDashPathContactSession(); float elapsed = 0f; while (elapsed < duration) { yield return new WaitForFixedUpdate(); combatFeedback.EmitDashAfterimage(body.position, isStrongDash); Vector2 segmentStart = body.position; elapsed += Time.fixedDeltaTime; Vector2 segmentEnd = Vector2.Lerp( start, end, Mathf.Clamp01(elapsed / duration)); Vector2 segment = segmentEnd - segmentStart; if (segment.sqrMagnitude > 0.000001f) { combatResolver.ResolveDashPathSegment( segmentStart, segment.normalized, segment.magnitude, isStrongDash, isStrongDash ? artifactDefinition.ChargedDamage : artifactDefinition.NormalDamage, isStrongDash ? artifactDefinition.ChargedKnockback : artifactDefinition.NormalKnockback, artifactDefinition.ArtifactId, artifactDefinition.DamageTag, artifactDefinition.ArtifactColor, castIdentity, artifactDefinition.Effect); } body.MovePosition(segmentEnd); } body.position = end; IsDashing = false; IsStrongDashing = false; animator.SetBool(IsDashingParameter, false); } } }