public IEnumerator DodgeballAttackCoroutine()
    {
        // PARAMS
        float attackPointCountdown = 0.4f;
        int   numToThrow           = Random.Range(4, 6);
        float projectileSpeed      = 8.0f;
        float throwInterval        = 0.15f;
        float backswingCountdown   = 0.4f;

        // ATTACK POINT
        animator.SetInteger(actionState, (int)ActionState.DODGEBALL_AP);
        Vector2 displacement_direction = (target.transform.position - transform.position).normalized;

        rigidBody.velocity = -chargeSpeed * displacement_direction;
        animator.SetFloat(horizontalVelocity, rigidBody.velocity.x);
        while (attackPointCountdown > 0.0f)
        {
            attackPointCountdown -= Time.deltaTime;
            yield return(null);
        }

        // ATTACK
        animator.SetInteger(actionState, (int)ActionState.DODGEBALL_ATTACK);
        while (numToThrow > 0)
        {
            for (int spawn = 0; spawn < 1; spawn += 1)
            {
                displacement_direction = (target.transform.position - transform.position).normalized;
                GameObject dodgeball = Instantiate(dodgeballPrefab);
                dodgeball.transform.position = transform.position + new Vector3(Random.Range(-0.3f, 0.3f), Random.Range(-0.3f, 0.3f));
                dodgeball.transform.rotation = Quaternion.LookRotation(Vector3.forward, displacement_direction);
                dodgeball.transform.Rotate(Vector3.forward, Random.Range(-15, 15));
                DodgeballMonoBehaviour dbmb = dodgeball.GetComponent <DodgeballMonoBehaviour>();
                dbmb.damage    = dodgeballDamage;
                dbmb.movespeed = projectileSpeed;
            }

            numToThrow -= 1;
            yield return(new WaitForSeconds(throwInterval));
        }

        // BACKSWING
        animator.SetInteger(actionState, (int)ActionState.DODGEBALL_BACKSWING);
        while (backswingCountdown > 0.0f)
        {
            backswingCountdown -= Time.deltaTime;
            yield return(null);
        }

        DetermineNextAction();
    }
    public IEnumerator SpinAttackCoroutine()
    {
        animator.SetInteger(actionState, (int)ActionState.SPINNING);

        // PARAMS
        float attackPointCountdown = 0.4f;
        int   numToThrow           = Random.Range(5, 10);
        float projectileSpeed      = 6.0f;
        float throwInterval        = 0.4f;
        float backswingCountdown   = 0.4f;

        // ATTACK POINT
        while (attackPointCountdown > 0.0f)
        {
            attackPointCountdown -= Time.deltaTime;
            yield return(null);
        }

        // ATTACK
        while (numToThrow > 0)
        {
            for (int spawn = 0; spawn < 12; spawn += 1)
            {
                GameObject dodgeball = Instantiate(dodgeballPrefab);
                dodgeball.transform.position = transform.position;
                dodgeball.transform.Rotate(Vector3.forward, Random.Range(0, 360));
                DodgeballMonoBehaviour dbmb = dodgeball.GetComponent <DodgeballMonoBehaviour>();
                dbmb.movespeed = projectileSpeed;
                dbmb.damage    = dodgeballDamage;
            }
            numToThrow        -= 1;
            rigidBody.velocity = chargeSpeed * new Vector3(Random.Range(-1.0f, 1.0f), Random.Range(-1.0f, 1.0f)).normalized;
            animator.SetFloat(horizontalVelocity, rigidBody.velocity.x);
            yield return(new WaitForSeconds(throwInterval));
        }

        // BACKSWING
        while (backswingCountdown > 0.0f)
        {
            backswingCountdown -= Time.deltaTime;
            yield return(null);
        }

        DetermineNextAction();
    }