public void resetState()
    {
        this.curState = fighterState.GROUNDED;
        curSkill      = null;
        initialFrame  = 0;
        isDash        = false;
        isGlide       = false;

        resetSkills(normalSkill);
        resetSkills(crouchingSkill);
        resetSkills(jumpingSkill);
        resetSkills(skillList);
    }
    // Performs attack that was last selected
    private void Attack(GameObject player, float minHeight, GameObject mySound)
    {
        int forward = (int)player.transform.localScale.x;

        if (curSkill == null)
        {
            AttackSel(player, minHeight, mySound);
        }

        // If the move is special cancelable, check if a special was inputted
        if (this.curSkill.isSpecialCancelable() && this.curSkill.getHasHit())
        {
            // Check the three most recent input
            bool      skillDetected = false;
            KeyCode[] inputChain    = { KeyCode.None, KeyCode.None, KeyCode.None };
            readBuffer(inputChain, 15);
            // Flip order of inputs
            inputChain[2] = inputChain[0];
            inputChain[0] = inputChain[1];
            inputChain[1] = inputChain[2];

            for (int i = 0; i < this.skillList.Count && i < (this.curLevel - 5) / 10 && !skillDetected; i++)
            {
                bool      correctInput = true;
                KeyCode[] input        = (KeyCode[])this.skillList[i].getInput().Clone();

                // Swap left and right keys if the player is facing the other way
                if (player.transform.localScale.x < 0)
                {
                    for (int j = 0; j < input.Length; j++)
                    {
                        if (input[j] == DataManager.savedOptions.controls[(int)key.LEFT])
                        {
                            input[j] = DataManager.savedOptions.controls[(int)key.RIGHT];
                        }
                        else if (input[j] == DataManager.savedOptions.controls[(int)key.RIGHT])
                        {
                            input[j] = DataManager.savedOptions.controls[(int)key.LEFT];
                        }
                    }
                }

                if (input[input.Length - 1] == DataManager.savedOptions.controls[(int)key.B1])
                {
                    correctInput = onPress[(int)key.B1];
                }
                else if (input[input.Length - 1] == DataManager.savedOptions.controls[(int)key.B2])
                {
                    correctInput = onPress[(int)key.B2];
                }
                else if (input[input.Length - 1] == DataManager.savedOptions.controls[(int)key.B3])
                {
                    correctInput = onPress[(int)key.B3];
                }
                for (int j = 0; j < inputChain.Length - 1 && correctInput; j++)
                {
                    if (j >= input.Length || input[j] != inputChain[j])
                    {
                        correctInput = false;
                        break;
                    }
                }

                if (correctInput)
                {
                    this.curSkill.resetAnims();
                    this.curSkill = this.skillList[i];
                    resetWait();
                    skillDetected = true;

                    // Play skill sound effect
                    if (curSkill != null)
                    {
                        mySound.GetComponent <AudioSource>().clip = curSkill.getSFX();
                        mySound.GetComponent <AudioSource>().Play();
                    }
                    break;
                }
            }
        }

        // Check for normal cancel
        if ((this.normalSkill.Contains(curSkill) || this.crouchingSkill.Contains(curSkill)) && this.curSkill.getHasHit())
        {
            int skillOrder = 0;
            if (this.normalSkill.Contains(curSkill))
            {
                skillOrder = this.normalSkill.IndexOf(curSkill);
            }
            else
            {
                skillOrder = this.crouchingSkill.IndexOf(curSkill);
            }

            // Find last attack input
            if (onPress[(int)key.B1] && skillOrder < 1)
            {
                this.curSkill.resetAnims();
                if (pressing[(int)key.DOWN])
                {
                    this.curSkill = crouchingSkill[0];
                }
                else
                {
                    this.curSkill = normalSkill[0];
                }
                resetWait();

                // Play skill sound effect
                if (curSkill != null)
                {
                    mySound.GetComponent <AudioSource>().clip = curSkill.getSFX();
                    mySound.GetComponent <AudioSource>().Play();
                }
            }
            else if (onPress[(int)key.B2] && skillOrder < 2)
            {
                this.curSkill.resetAnims();
                if (pressing[(int)key.DOWN])
                {
                    this.curSkill = crouchingSkill[1];
                }
                else
                {
                    this.curSkill = normalSkill[1];
                }
                resetWait();

                // Play skill sound effect
                if (curSkill != null)
                {
                    mySound.GetComponent <AudioSource>().clip = curSkill.getSFX();
                    mySound.GetComponent <AudioSource>().Play();
                }
            }
            else if (onPress[(int)key.B3] && skillOrder < 3)
            {
                this.curSkill.resetAnims();
                if (pressing[(int)key.DOWN])
                {
                    this.curSkill = crouchingSkill[2];
                }
                else
                {
                    this.curSkill = normalSkill[2];
                }
                resetWait();

                // Play skill sound effect
                if (curSkill != null)
                {
                    mySound.GetComponent <AudioSource>().clip = curSkill.getSFX();
                    mySound.GetComponent <AudioSource>().Play();
                }
            }
        }

        // Check if player has jump canceled the attack
        if (this.curSkill.isJumpCancelable() && pressing[(int)key.UP])
        {
            this.curSkill.resetAnims();
            this.curSkill = null;
            resetWait();
            this.curState = fighterState.GROUNDED;
        }
        // Otherwise play the move until the first active frame of the move
        else if (!WaitForXFrames(this.curSkill.firstActive()))
        {
            player.GetComponent <SpriteRenderer>().sprite = this.curSkill.playSkill(forward == 1);
            player.transform.Translate(forward * this.curSkill.getXShift() * Time.deltaTime, this.curSkill.getYShift() * Time.deltaTime, 0);

            if (this.curSkill.hitboxOut(player.transform.localScale.x == 1, Time.frameCount - initialFrame) && this.curSkill.isProjectile())
            {
                this.projectileOut = true;
            }

            // If jumping attack, apply gravity
            if (this.jumpingSkill.Contains(this.curSkill))
            {
                applyGravity(player);

                // Check if player touched the ground
                if (player.transform.localPosition.y <= minHeight)
                {
                    resetWait();
                    this.jumpCount = 0;
                    player.transform.localPosition = new Vector2(player.transform.localPosition.x, minHeight);
                    this.curState = fighterState.GROUNDED;
                    this.curSkill.resetAnims();
                    curSkill = null;
                }
            }
            else
            {
                // Slide back player
                if (slideBack > 0)
                {
                    player.transform.Translate(-1 * curSkill.getBasePow() * forward * slideBack * Time.deltaTime, 0, 0);
                    slideBack -= Time.deltaTime * 10;
                }
            }
        }
        // Reset everything once the attack is done
        else
        {
            this.curSkill.resetAnims();
            this.curSkill = null;

            if (player.transform.localPosition.y > minHeight)
            {
                player.GetComponent <SpriteRenderer>().sprite = chooseAnim(forward, this.inAir, this.inAirB);
                this.curState = fighterState.AERIAL;
            }
            else
            {
                this.curState = fighterState.GROUNDED;
            }
        }
    }
    private void AttackSel(GameObject player, float minHeight, GameObject mySound)
    {
        // Determine aerial attack
        if (player.transform.localPosition.y > minHeight)
        {
            if (onPress[(int)key.B1])
            {
                curSkill = this.jumpingSkill[0];
            }
            else if (onPress[(int)key.B2])
            {
                curSkill = this.jumpingSkill[1];
            }
            else
            {
                curSkill = this.jumpingSkill[2];
            }
        }
        else if (this.isCrouch)
        {
            if (onPress[(int)key.B1])
            {
                curSkill = this.crouchingSkill[0];
            }
            else if (onPress[(int)key.B2])
            {
                curSkill = this.crouchingSkill[1];
            }
            else
            {
                curSkill = this.crouchingSkill[2];
            }
        }
        // Go through the entire skillList and check for combination
        else
        {
            // Check the three most recent input
            bool      skillDetected = false;
            KeyCode[] inputChain    = { KeyCode.None, KeyCode.None, KeyCode.None };
            readBuffer(inputChain, 15);
            // Flip order of inputs
            inputChain[2] = inputChain[0];
            inputChain[0] = inputChain[1];
            inputChain[1] = inputChain[2];

            for (int i = 0; i < this.skillList.Count && i < (this.curLevel - 5) / 10; i++)
            {
                bool      correctInput = true;
                KeyCode[] input        = (KeyCode[])this.skillList[i].getInput().Clone();

                // Swap left and right keys if the player is facing the other way
                if (player.transform.localScale.x < 0)
                {
                    for (int j = 0; j < input.Length; j++)
                    {
                        if (input[j] == DataManager.savedOptions.controls[(int)key.LEFT])
                        {
                            input[j] = DataManager.savedOptions.controls[(int)key.RIGHT];
                        }
                        else if (input[j] == DataManager.savedOptions.controls[(int)key.RIGHT])
                        {
                            input[j] = DataManager.savedOptions.controls[(int)key.LEFT];
                        }
                    }
                }

                if (input[input.Length - 1] == DataManager.savedOptions.controls[(int)key.B1])
                {
                    correctInput = onPress[(int)key.B1];
                }
                else if (input[input.Length - 1] == DataManager.savedOptions.controls[(int)key.B2])
                {
                    correctInput = onPress[(int)key.B2];
                }
                else if (input[input.Length - 1] == DataManager.savedOptions.controls[(int)key.B3])
                {
                    correctInput = onPress[(int)key.B3];
                }
                for (int j = 0; j < inputChain.Length - 1 && correctInput; j++)
                {
                    if (j >= input.Length || input[j] != inputChain[j])
                    {
                        correctInput = false;
                        break;
                    }
                }

                if (correctInput)
                {
                    this.curSkill = this.skillList[i];
                    skillDetected = true;
                    break;
                }
            }

            if (!skillDetected)
            {
                if (onPress[(int)key.B1])
                {
                    curSkill = this.normalSkill[0];
                }
                else if (onPress[(int)key.B2])
                {
                    curSkill = this.normalSkill[1];
                }
                else
                {
                    curSkill = this.normalSkill[2];
                }
            }
        }

        // Play skill sound effect
        if (curSkill != null)
        {
            mySound.GetComponent <AudioSource>().clip = curSkill.getSFX();
            mySound.GetComponent <AudioSource>().Play();
        }

        this.curState = fighterState.ATTACK;
    }
    void Aerial(GameObject player, float minHeight, GameObject mySound, AudioClip[] basicSFX)
    {
        int forward = (int)player.transform.localScale.x;

        if (isGlide)
        {
            if (!WaitForXFrames(15))
            {
                int direction = (int)this.xVel / (int)this.glideSpeed;
                player.GetComponent <SpriteRenderer>().sprite = chooseAnim(direction, this.glide, this.glideB);
                player.transform.Translate(this.xVel * Time.deltaTime, 0, 0);
                player.transform.localScale = new Vector2(direction, player.transform.localScale.y);
            }
            else
            {
                isGlide = false;
                player.GetComponent <SpriteRenderer>().sprite = chooseAnim(forward, this.inAir, this.inAirB);
                this.yVel = 0;
            }
        }
        else
        {
            if (this.inJumpSquat)
            {
                if (WaitForXFrames(1))
                {
                    this.inJumpSquat = false;
                    this.jumpCount  += 1;
                    resetAnims(this.jump, this.jumpB);
                    player.GetComponent <SpriteRenderer>().sprite = chooseAnim(forward, this.inAir, this.inAirB);
                    this.yVel = Mathf.Abs(this.gravity) * 0.4f;

                    // Play jump sound effect
                    mySound.GetComponent <AudioSource>().clip = basicSFX[0];
                    mySound.GetComponent <AudioSource>().Play();
                }
            }

            // Start double jump
            else if (onPress[(int)key.UP] && this.jumpCount <= this.maxJumps)
            {
                // Decide which way the character should jump
                if (pressing[(int)key.LEFT])
                {
                    if (Mathf.Abs(this.xVel) > this.glideSpeed)
                    {
                        this.xVel = Mathf.Abs(this.dashSpeed) * -1;
                    }
                    else
                    {
                        this.xVel = Mathf.Abs(this.walkSpeed) * -1;
                    }
                }
                else if (pressing[(int)key.RIGHT])
                {
                    if (Mathf.Abs(this.xVel) > this.glideSpeed)
                    {
                        this.xVel = Mathf.Abs(this.dashSpeed);
                    }
                    else
                    {
                        this.xVel = Mathf.Abs(this.walkSpeed);
                    }
                }
                else
                {
                    this.xVel = 0;
                }

                // Place character in double jump squat
                player.GetComponent <SpriteRenderer>().sprite = chooseAnim(forward, this.djump, this.djumpB);
                this.inDJumpSquat = true;
            }
            else if (this.inDJumpSquat)
            {
                if (WaitForXFrames(2))
                {
                    this.inDJumpSquat = false;
                    this.jumpCount   += 1;
                    resetAnims(djump, djumpB);
                    player.GetComponent <SpriteRenderer>().sprite = chooseAnim(forward, this.inAir, this.inAirB);
                    this.yVel = Mathf.Abs(this.gravity) * 0.4f;

                    // Play jump sound effect
                    mySound.GetComponent <AudioSource>().clip = basicSFX[0];
                    mySound.GetComponent <AudioSource>().Play();
                }
            }

            // Check if the player inputted the right combination for gliding
            else if ((onPress[(int)key.LEFT] || onPress[(int)key.RIGHT]) && this.jumpCount <= this.maxJumps)
            {
                // Two so that you can also do up and then a direction
                KeyCode[] lastInput = { KeyCode.None, KeyCode.None };
                readBuffer(lastInput, 15);
                if (onPress[(int)key.LEFT] && lastInput[0] == DataManager.savedOptions.controls[(int)key.LEFT])
                {
                    this.isGlide    = true;
                    this.yVel       = 0;
                    this.xVel       = -this.glideSpeed;
                    this.jumpCount += 1;
                }
                else if (onPress[(int)key.RIGHT] && lastInput[0] == DataManager.savedOptions.controls[(int)key.RIGHT])
                {
                    this.isGlide    = true;
                    this.yVel       = 0;
                    this.xVel       = this.glideSpeed;
                    this.jumpCount += 1;
                }
                else if (lastInput[0] == DataManager.savedOptions.controls[(int)key.UP])
                {
                    if (onPress[(int)key.LEFT] && lastInput[1] == DataManager.savedOptions.controls[(int)key.LEFT])
                    {
                        this.isGlide    = true;
                        this.yVel       = 0;
                        this.xVel       = -this.glideSpeed;
                        this.jumpCount += 1;
                    }
                    else if (onPress[(int)key.RIGHT] && lastInput[1] == DataManager.savedOptions.controls[(int)key.RIGHT])
                    {
                        this.isGlide    = true;
                        this.yVel       = 0;
                        this.xVel       = this.glideSpeed;
                        this.jumpCount += 1;
                    }
                }

                if (isGlide)
                {
                    // Play glide sound effect
                    mySound.GetComponent <AudioSource>().clip = basicSFX[2];
                    mySound.GetComponent <AudioSource>().Play();
                }
            }

            // Go into attack state if any of the attack buttons were pressed
            else if (onPress[(int)key.B1] || onPress[(int)key.B2] || onPress[(int)key.B3])
            {
                this.curState = fighterState.ATTACK;
            }

            // Otherwise, just make the character fall down
            else
            {
                applyGravity(player);
                player.GetComponent <SpriteRenderer>().sprite = chooseAnim(forward, this.inAir, this.inAirB);

                // Check if fighter has touched the ground
                if (player.transform.localPosition.y <= minHeight)
                {
                    this.jumpCount = 0;
                    curSkill       = null;
                    player.transform.localPosition = new Vector2(player.transform.localPosition.x, minHeight);
                    this.curState = fighterState.GROUNDED;
                }
            }
        }
    }
    private void Grounded(GameObject player, float minY, GameObject mySound, AudioClip[] basicSFX)
    {
        int forward = (int)player.transform.localScale.x;

        // Slide back player
        if (slideBack > 0)
        {
            player.transform.Translate(-3 * forward * slideBack * Time.deltaTime, 0, 0);
            slideBack -= Time.deltaTime * 10;
        }

        // Move the player back for 13 frames if they're backhopping
        if (isBackHop)
        {
            if (!WaitForXFrames(7))
            {
                player.GetComponent <SpriteRenderer>().sprite = chooseAnim(forward, this.inAir, this.inAirB);
                player.transform.Translate(-1 * forward * Time.deltaTime, 0, 0);
            }
            else
            {
                this.isBackHop = false;
                this.xVel      = 0; // Prevent player from staying in backhop
            }
        }
        // Go into attack state if any of the attack buttons were pressed
        else if (onPress[(int)key.B1] || onPress[(int)key.B2] || onPress[(int)key.B3])
        {
            this.curState = fighterState.ATTACK;
        }
        else if (this.isCrouch)
        {
            player.GetComponent <SpriteRenderer>().sprite = chooseAnim(forward, this.crouch, this.crouchB);
            if (!pressing[(int)key.DOWN])
            {
                this.isCrouch = false;
            }
        }
        else
        {
            // UP KEY
            if (pressing[(int)key.UP])
            {
                // Place character in jump squat
                player.GetComponent <SpriteRenderer>().sprite = chooseAnim(forward, this.jump, this.jumpB);
                this.inJumpSquat = true;
                this.isDash      = false;
                this.curState    = fighterState.AERIAL;

                // Decide which way the character should jump
                if (pressing[(int)key.LEFT])
                {
                    if (Mathf.Abs(this.xVel) > this.glideSpeed)
                    {
                        this.xVel = Mathf.Abs(this.dashSpeed) * -1;
                    }
                    else
                    {
                        this.xVel = Mathf.Abs(this.walkSpeed) * -1;
                    }
                }
                else if (pressing[(int)key.RIGHT])
                {
                    if (Mathf.Abs(this.xVel) > this.glideSpeed)
                    {
                        this.xVel = Mathf.Abs(this.dashSpeed);
                    }
                    else
                    {
                        this.xVel = Mathf.Abs(this.walkSpeed);
                    }
                }
                else
                {
                    this.xVel = 0;
                }
            }

            // DOWN KEY
            else if (pressing[(int)key.DOWN])
            {
                this.isCrouch = true;
                this.isDash   = false;
            }

            // LEFT KEY
            else if (pressing[(int)key.LEFT])
            {
                // Check the buffer to see if the left button was already pressed
                if (onPress[(int)key.LEFT])
                {
                    KeyCode[] lastInput = { KeyCode.None };
                    readBuffer(lastInput, 15);
                    if (lastInput[0] == DataManager.savedOptions.controls[(int)key.LEFT])
                    {
                        if (forward > 0)
                        {
                            this.isBackHop = true;
                            clearBuffer();
                        }
                        else
                        {
                            this.isDash = true;

                            // Play dash sound effect
                            mySound.GetComponent <AudioSource>().clip = basicSFX[1];
                            mySound.GetComponent <AudioSource>().Play();
                        }
                    }
                }

                if (this.isDash && forward < 0)
                {
                    this.xVel = -this.dashSpeed;
                    player.GetComponent <SpriteRenderer>().sprite = chooseAnim(forward, this.dash, this.dashB);
                    player.transform.Translate(-1 * this.dashSpeed * Time.deltaTime, 0, 0);
                }
                else
                {
                    this.xVel = -this.walkSpeed;
                    player.GetComponent <SpriteRenderer>().sprite = chooseAnim(forward, this.walk, this.walkB);
                    player.transform.Translate(-1 * this.walkSpeed * Time.deltaTime, 0, 0);
                }
            }

            // RIGHT KEY
            else if (pressing[(int)key.RIGHT])
            {
                // Check the buffer to see if the left button was already pressed
                if (onPress[(int)key.RIGHT])
                {
                    KeyCode[] lastInput = { KeyCode.None };
                    readBuffer(lastInput, 15);
                    if (lastInput[0] == DataManager.savedOptions.controls[(int)key.RIGHT])
                    {
                        if (forward > 0)
                        {
                            this.isDash = true;

                            // Play dash sound effect
                            mySound.GetComponent <AudioSource>().clip = basicSFX[1];
                            mySound.GetComponent <AudioSource>().Play();
                        }
                        else
                        {
                            this.isBackHop = true;
                            clearBuffer();
                        }
                    }
                }

                if (this.isDash && forward > 0)
                {
                    this.xVel = this.dashSpeed;
                    player.GetComponent <SpriteRenderer>().sprite = chooseAnim(forward, this.dash, this.dashB);
                    player.transform.Translate(this.dashSpeed * Time.deltaTime, 0, 0);
                }
                else
                {
                    this.xVel = this.walkSpeed;
                    player.GetComponent <SpriteRenderer>().sprite = chooseAnim(forward, this.walk, this.walkB);
                    player.transform.Translate(this.walkSpeed * Time.deltaTime, 0, 0);
                }
            }

            // Character is idle
            else
            {
                this.xVel = 0;
                if (this.idleCounter < 3)
                {
                    player.GetComponent <SpriteRenderer>().sprite = chooseAnim(forward, this.idle, this.idleB);

                    /*
                     * if ((forward > 0 || !hasDiffBack) && this.idle.isDone())    { this.idleCounter += 1; }
                     * else if (this.idleB.isDone())                               { this.idleCounter += 1; }
                     */
                }
                else
                {
                    player.GetComponent <SpriteRenderer>().sprite = chooseAnim(forward, this.idleAct, this.idleActB);
                    if ((forward > 0 || !hasDiffBack) && this.idleAct.isDone())
                    {
                        this.idleCounter = 0;
                    }
                    else if (this.idleActB.isDone())
                    {
                        this.idleCounter = 1;
                    }
                }
            }

            if (released[(int)key.LEFT] || released[(int)key.RIGHT])
            {
                this.isDash = false;
            }
        }
    }