private IEnumerator CrossFire()
    {
        const int NUM_FLAMES = 10;

        for (int x = 0; x < NUM_FLAMES; x++)
        {
            float xLevel = Mathf.FloorToInt(x / 2) - (NUM_FLAMES / 4f) + 0.5f;
            float xPos   = xLevel * 3f;

            GameObject darkFlame = ObjectPooler.instance.GetDanmaku(darkFlameIndex);
            if (darkFlame == null)
            {
                Debug.LogError("Dark flame not found in pool.");
            }
            DarkFlame darkFlameScript = darkFlame.GetComponent <DarkFlame>();
            if (darkFlameScript == null)
            {
                Debug.LogError("Dark flame script not found");
            }
            darkFlameScript.SetOwner(gameObject);
            darkFlame.transform.position = new Vector3(xPos, 5f, 0f);
            if (x % 2 == 0)
            {
                darkFlameScript.SetFalling(2f, 1.5f);
            }
            else
            {
                darkFlameScript.SetFalling(2f, -1.5f);
            }
            darkFlame.SetActive(true);
        }

        yield return(null);

        cooldownTimer = 3f;
        state         = DarkPlayerState.ChoosingAttack;
    }
    private IEnumerator UnholyImmolation()
    {
        const int NUM_FLAMES     = 11;
        Vector3   CENTER_POINT   = Vector3.zero;
        float     CONVERGE_SPEED = 1.2f;
        float     ANGULAR_SPEED  = 1.8f;

        // Set up
        GameObject[] flames       = new GameObject[NUM_FLAMES];
        float        randomOffset = Random.Range(0f, 2 * Mathf.PI);

        for (int x = 0; x < NUM_FLAMES; x++)
        {
            GameObject flame = ObjectPooler.instance.GetDanmaku(darkFlameIndex);
            if (flame == null)
            {
                Debug.LogError("Dark flame not found in pool.");
            }
            flames[x] = flame;
            DarkFlame darkFlameScript = flame.GetComponent <DarkFlame>();
            if (darkFlameScript == null)
            {
                Debug.LogError("Dark flame script not found.");
            }
            darkFlameScript.SetOwner(gameObject);
            darkFlameScript.SetIdle();

            float xPos = 9 * Mathf.Sin((x * 2 * Mathf.PI / (NUM_FLAMES + 1)) + randomOffset);
            float yPos = 9 * Mathf.Cos(x * 2 * Mathf.PI / (NUM_FLAMES + 1) + randomOffset);
            flame.transform.position = new Vector3(xPos, yPos, 0f);

            flame.SetActive(true);
        }

        yield return(null);

        // Attack
        float timeOut   = 20f;
        bool  converged = false;

        while (!converged && timeOut > 0)
        {
            for (int x = 0; x < NUM_FLAMES; x++)
            {
                GameObject flame          = flames[x];
                Vector3    distanceVector = flame.transform.position - CENTER_POINT;
                flame.transform.position -= distanceVector.normalized * CONVERGE_SPEED * Time.deltaTime;
                float distance = distanceVector.magnitude - CONVERGE_SPEED * Time.deltaTime;
                if (distance < 0.05f)
                {
                    converged = true;
                }
                float angle = Vector3.Angle(distanceVector, Vector3.right);
                if (distanceVector.y < 0)
                {
                    angle = -1 * Mathf.Abs(angle);
                }
                angle *= Mathf.Deg2Rad;
                angle -= ANGULAR_SPEED * Time.deltaTime;
                flame.transform.position = new Vector3(distance * Mathf.Cos(angle), distance * Mathf.Sin(angle), 0f);
            }
            yield return(null);

            timeOut -= Time.deltaTime;
        }

        // cleanup
        for (int x = 0; x < NUM_FLAMES; x++)
        {
            if (flames[x].activeSelf)
            {
                DarkFlame darkFlame = flames[x].GetComponent <DarkFlame>();
                darkFlame.Deactivate();
            }
        }
        cooldownTimer = 5f;
        state         = DarkPlayerState.ChoosingAttack;
    }