Пример #1
0
    public void GetHit(Hit hit, int remainingFrames, Vector3 location)
    {
        // Get what animation should be played depending on the character's state
        bool airHit = false;
        bool armored = false;
        bool isKnockDown = false;
        float verticalPush = 0;
        float damageModifier = 1;
        float hitStunModifier = 1;
        BasicMoveInfo currentHitInfo;
        hitStunDeceleration = 0;

        myHitBoxesScript.isHit = true;

        if (myInfo.headLook.disableOnHit) ToggleHeadLook(false);

        if (currentMove != null && currentMove.frameLinks.Length > 0){
            foreach (FrameLink frameLink in currentMove.frameLinks){
                if (currentMove.currentFrame >= frameLink.activeFramesBegins &&
                    currentMove.currentFrame <= frameLink.activeFramesEnds) {
                    if (frameLink.linkType == LinkType.CounterMove){
                        bool cancelable = false;
                        if (frameLink.counterMoveType == CounterMoveType.SpecificMove){
                            if (frameLink.counterMoveFilter == currentMove) cancelable = true;
                        }else{
                            HitBox strokeHitBox = myHitBoxesScript.GetStrokeHitBox();
                            if ((frameLink.anyHitStrength || frameLink.hitStrength == hit.hitStrength) &&
                                (frameLink.anyStrokeHitBox || frameLink.hitBoxType == strokeHitBox.type) &&
                                (frameLink.anyHitType || frameLink.hitType == hit.hitType)){
                                cancelable = true;
                            }
                        }

                        if (cancelable){
                            frameLink.cancelable = true;
                            currentMove.cancelable = true;

                            if (frameLink.disableHitImpact) {
                                float timeLeft = (float)(currentMove.totalFrames - currentMove.currentFrame)/(float)UFE.config.fps;

                                myHitBoxesScript.ResetHit();
                                UFE.DelaySynchronizedAction(myHitBoxesScript.ResetHit, timeLeft);
                                return;
                            }
                        }
                    }
                }
            }
        }

        // Set position in case of pull enemy in
        activePullIn = null;
        if (hit.pullEnemyIn.enemyBodyPart != BodyPart.none && hit.pullEnemyIn.characterBodyPart != BodyPart.none){
            Vector3 newPos = myHitBoxesScript.GetPosition(hit.pullEnemyIn.enemyBodyPart);
            if (newPos != Vector3.zero){
                activePullIn = new PullIn();
                activePullIn.position = transform.position + (opHitBoxesScript.GetPosition(hit.pullEnemyIn.characterBodyPart) - newPos);
                activePullIn.speed = hit.pullEnemyIn.speed;
                activePullIn.forceStand = hit.pullEnemyIn.forceStand;
                activePullIn.position.z = 0;
                if (hit.pullEnemyIn.forceStand) {
                    activePullIn.position.y = 0;
                    myPhysicsScript.ForceGrounded();
                }
            }
        }

        if (myPhysicsScript.IsGrounded()) {
            if (hit.hitStrength == HitStrengh.Crumple){
                if (myMoveSetScript.basicMoves.getHitCrumple.clip1 == null)
                    Debug.LogError("Get Hit Crumple animation not found! Make sure you have it set on Character -> Basic Moves -> Get Hit Crumple");
                currentHitAnimation = myMoveSetScript.basicMoves.getHitCrumple.name;
                currentHitInfo = myMoveSetScript.basicMoves.getHitCrumple;
                if (myMoveSetScript.basicMoves.getHitCrumple.invincible) myHitBoxesScript.HideHitBoxes(true);
            }else if (hit.hitType == HitType.Launcher){
                if (myMoveSetScript.basicMoves.getHitAir.clip1 == null)
                    Debug.LogError("Get Hit Air animation not found! Make sure you have it set on Character -> Basic Moves -> Get Hit Air");
                currentHitAnimation = myMoveSetScript.basicMoves.getHitAir.name;
                currentHitInfo = myMoveSetScript.basicMoves.getHitAir;
                if (myMoveSetScript.basicMoves.getHitAir.invincible) myHitBoxesScript.HideHitBoxes(true);
                airHit = true;
            }else if (hit.hitType == HitType.KnockBack){
                if (myMoveSetScript.basicMoves.getHitKnockBack.clip1 == null)
                    Debug.LogError("Get Hit Knock Back animation not found! Make sure you have it set on Character -> Basic Moves -> Get Hit Knock Back");
                currentHitAnimation = myMoveSetScript.basicMoves.getHitKnockBack.name;
                currentHitInfo = myMoveSetScript.basicMoves.getHitKnockBack;
                if (myMoveSetScript.basicMoves.getHitKnockBack.invincible) myHitBoxesScript.HideHitBoxes(true);
                airHit = true;
            }else if (hit.hitType == HitType.HighKnockdown){
                if (myMoveSetScript.basicMoves.getHitHighKnockdown.clip1 == null)
                    Debug.LogError("Get Hit High Knockdown animation not found! Make sure you have it set on Character -> Basic Moves -> Get Hit High Knockdown");
                currentHitAnimation = myMoveSetScript.basicMoves.getHitHighKnockdown.name;
                currentHitInfo = myMoveSetScript.basicMoves.getHitHighKnockdown;
                if (myMoveSetScript.basicMoves.getHitHighKnockdown.invincible) myHitBoxesScript.HideHitBoxes(true);
                isKnockDown = true;
            }else if (hit.hitType == HitType.MidKnockdown){
                if (myMoveSetScript.basicMoves.getHitHighLowKnockdown.clip1 == null)
                    Debug.LogError("Get Hit High-Low Knockdown animation not found! Make sure you have it set on Character -> Basic Moves -> Get Hit High-Low Knockdown");
                currentHitAnimation = myMoveSetScript.basicMoves.getHitHighLowKnockdown.name;
                currentHitInfo = myMoveSetScript.basicMoves.getHitHighLowKnockdown;
                if (myMoveSetScript.basicMoves.getHitHighLowKnockdown.invincible) myHitBoxesScript.HideHitBoxes(true);
                isKnockDown = true;
            }else if (hit.hitType == HitType.Sweep){
                if (myMoveSetScript.basicMoves.getHitSweep.clip1 == null)
                    Debug.LogError("Get Hit Sweep animation not found! Make sure you have it set on Character -> Basic Moves -> Get Hit Sweep");
                currentHitAnimation = myMoveSetScript.basicMoves.getHitSweep.name;
                currentHitInfo = myMoveSetScript.basicMoves.getHitSweep;
                if (myMoveSetScript.basicMoves.getHitSweep.invincible) myHitBoxesScript.HideHitBoxes(true);
                isKnockDown = true;
            }else if (currentState == PossibleStates.Crouch){
                if (myMoveSetScript.basicMoves.getHitCrouching.clip1 == null)
                    Debug.LogError("Get Hit Crouching animation not found! Make sure you have it set on Character -> Basic Moves -> Get Hit Crouching");
                currentHitAnimation = GetHitAnimation(myMoveSetScript.basicMoves.getHitCrouching, hit);
                currentHitInfo = myMoveSetScript.basicMoves.getHitCrouching;
                if (myMoveSetScript.basicMoves.getHitCrouching.invincible) myHitBoxesScript.HideHitBoxes(true);
            }else{
                HitBox strokeHit = myHitBoxesScript.GetStrokeHitBox();
                if (strokeHit.type == HitBoxType.low && myMoveSetScript.basicMoves.getHitLow.clip1 != null){
                    currentHitAnimation = GetHitAnimation(myMoveSetScript.basicMoves.getHitLow, hit);
                    currentHitInfo = myMoveSetScript.basicMoves.getHitLow;
                    if (myMoveSetScript.basicMoves.getHitLow.invincible) myHitBoxesScript.HideHitBoxes(true);
                }else{
                    if (myMoveSetScript.basicMoves.getHitHigh.clip1 == null)
                        Debug.LogError("Get Hit High animation not found! Make sure you have it set on Character -> Basic Moves -> Get Hit High");
                    currentHitAnimation = GetHitAnimation(myMoveSetScript.basicMoves.getHitHigh, hit);
                    currentHitInfo = myMoveSetScript.basicMoves.getHitHigh;
                    if (myMoveSetScript.basicMoves.getHitHigh.invincible) myHitBoxesScript.HideHitBoxes(true);
                }
            }
        }else{
            if (hit.hitStrength == HitStrengh.Crumple && myMoveSetScript.basicMoves.getHitKnockBack.clip1 != null){
                currentHitAnimation = myMoveSetScript.basicMoves.getHitKnockBack.name;
                currentHitInfo = myMoveSetScript.basicMoves.getHitKnockBack;
            }else{
                if (myMoveSetScript.basicMoves.getHitAir.clip1 == null)
                    Debug.LogError("Get Hit Air animation not found! Make sure you have it set on Character -> Basic Moves -> Get Hit Air");
                currentHitAnimation = myMoveSetScript.basicMoves.getHitAir.name;
                currentHitInfo = myMoveSetScript.basicMoves.getHitAir;
            }
            airHit = true;
        }

        // Differenciate hit types
        HitTypeOptions hitEffects = hit.hitEffects;
        if (!hit.overrideHitEffects) {
            if (hit.hitStrength == HitStrengh.Weak) hitEffects = UFE.config.hitOptions.weakHit;
            if (hit.hitStrength == HitStrengh.Medium) hitEffects = UFE.config.hitOptions.mediumHit;
            if (hit.hitStrength == HitStrengh.Heavy) hitEffects = UFE.config.hitOptions.heavyHit;
            if (hit.hitStrength == HitStrengh.Crumple) hitEffects = UFE.config.hitOptions.crumpleHit;
            if (hit.hitStrength == HitStrengh.Custom1) hitEffects = UFE.config.hitOptions.customHit1;
            if (hit.hitStrength == HitStrengh.Custom2) hitEffects = UFE.config.hitOptions.customHit2;
            if (hit.hitStrength == HitStrengh.Custom3) hitEffects = UFE.config.hitOptions.customHit3;
        }

        // Cancel current move if any
        if (!hit.armorBreaker && currentMove != null && currentMove.armorOptions.hitAbsorption > 0 &&
            currentMove.currentFrame >= currentMove.armorOptions.activeFramesBegin &&
            currentMove.currentFrame <= currentMove.armorOptions.activeFramesEnds){
            armored = true;
            currentMove.armorOptions.hitAbsorption --;
            damageModifier -= currentMove.armorOptions.damageAbsorption * .01f;
            if (currentMove.armorOptions.overrideHitEffects)
                hitEffects = currentMove.armorOptions.hitEffects;

        }else if (currentMove != null && !currentMove.hitAnimationOverride){
            if ((UFE.config.counterHitOptions.startUpFrames && currentMove.currentFrameData == CurrentFrameData.StartupFrames) ||
                (UFE.config.counterHitOptions.activeFrames && currentMove.currentFrameData == CurrentFrameData.ActiveFrames) ||
                (UFE.config.counterHitOptions.recoveryFrames && currentMove.currentFrameData == CurrentFrameData.RecoveryFrames)){
                UFE.FireAlert(UFE.config.selectedLanguage.counterHit, opInfo);
                damageModifier += UFE.config.counterHitOptions.damageIncrease * .01f;
                hitStunModifier += UFE.config.counterHitOptions.hitStunIncrease * .01f;
            }
            storedMove = null;

            KillCurrentMove();
        }

        // Create hit effect
        if (location != Vector3.zero && hitEffects.hitParticle != null){
            GameObject pTemp = (GameObject) Instantiate(hitEffects.hitParticle, location, Quaternion.identity);
            Destroy(pTemp, hitEffects.killTime);
        }

        // Play sound
        UFE.PlaySound(hitEffects.hitSound);

        // Shake Options
        shakeCamera = hitEffects.shakeCameraOnHit;
        shakeCharacter = hitEffects.shakeCharacterOnHit;
        shakeDensity = hitEffects.shakeDensity;

        // Cast First Hit if true
        if (!firstHit && !opControlsScript.firstHit){
            opControlsScript.firstHit = true;
            UFE.FireAlert(UFE.config.selectedLanguage.firstHit, opInfo);
        }
        UFE.FireHit(myHitBoxesScript.GetStrokeHitBox(), opControlsScript.currentMove, opInfo);

        // Convert Percentage
        if (hit.damageType == DamageType.Percentage) hit.damageOnHit = myInfo.lifePoints * (hit.damageOnHit/100);

        // Damage deterioration
        float damage = 0;
        if (!hit.damageScaling || UFE.config.comboOptions.damageDeterioration == Sizes.None){
            damage = hit.damageOnHit;
        }else if (UFE.config.comboOptions.damageDeterioration == Sizes.Small){
            damage = hit.damageOnHit - (hit.damageOnHit * (float)comboHits * .1f);
        }else if (UFE.config.comboOptions.damageDeterioration == Sizes.Medium){
            damage = hit.damageOnHit - (hit.damageOnHit * (float)comboHits * .2f);
        }else if (UFE.config.comboOptions.damageDeterioration == Sizes.High){
            damage = hit.damageOnHit - (hit.damageOnHit * (float)comboHits * .4f);
        }
        if (damage < UFE.config.comboOptions.minDamage) damage = UFE.config.comboOptions.minDamage;
        damage *= damageModifier;
        comboHitDamage = damage;
        comboDamage += damage;
        comboHits ++;

        // Lose life
        isDead = DamageMe(damage, hit.doesntKill);

        // Reset hit to allow for another hit while the character is still stunned
        float spaceBetweenHits = 1;
        if (hit.spaceBetweenHits == Sizes.Small){
            spaceBetweenHits = 1.1f;
        }else if (hit.spaceBetweenHits == Sizes.Medium){
            spaceBetweenHits = 1.3f;
        }else if (hit.spaceBetweenHits == Sizes.High){
            spaceBetweenHits = 1.7f;
        }
        UFE.DelaySynchronizedAction(myHitBoxesScript.ResetHit, hitEffects.freezingTime * spaceBetweenHits);

        if ((currentMove == null || !currentMove.hitAnimationOverride) && !armored) {
            // Stun
            // Hit stun deterioration (the longer the combo gets, the harder it is to combo)
            currentSubState = SubStates.Stunned;
            int stunFrames = 0;
            if (hit.hitStunType == HitStunType.FrameAdvantage) {
                stunFrames = hit.frameAdvantageOnHit + remainingFrames;
                if (stunFrames < 1) stunFrames = 1;
                if (stunFrames < UFE.config.comboOptions.minHitStun) stunTime = UFE.config.comboOptions.minHitStun;
                stunTime = (float)stunFrames/(float)UFE.config.fps;
            }else if (hit.hitStunType == HitStunType.Frames) {
                stunFrames = (int) hit.hitStunOnHit;
                if (stunFrames < 1) stunFrames = 1;
                if (stunFrames < UFE.config.comboOptions.minHitStun) stunTime = UFE.config.comboOptions.minHitStun;
                stunTime = (float)stunFrames/(float)UFE.config.fps;
            }else{
                stunTime = hit.hitStunOnHit;
            }

            if (!hit.resetPreviousHitStun){
                if (UFE.config.comboOptions.hitStunDeterioration == Sizes.Small){
                    stunTime -= (float)comboHits * .01f;
                }else if (UFE.config.comboOptions.hitStunDeterioration == Sizes.Medium){
                    stunTime -= (float)comboHits * .02f;
                }else if (UFE.config.comboOptions.hitStunDeterioration == Sizes.High){
                    stunTime -= (float)comboHits * .04f;
                }
            }
            stunTime *= hitStunModifier;

            verticalPush = hit.pushForce.y;
            // Add force to the move
            // Air juggle deterioration (the longer the combo, the harder it is to push the opponent higher)
            if (verticalPush > 0 || (isDead && !isKnockDown)){
                if (UFE.config.comboOptions.airJuggleDeteriorationType == AirJuggleDeteriorationType.ComboHits){
                    airJuggleHits = comboHits - 1;
                }
                if (UFE.config.comboOptions.airJuggleDeterioration == Sizes.None){
                    verticalPush = hit.pushForce.y;
                }else if (UFE.config.comboOptions.airJuggleDeterioration == Sizes.Small){
                    verticalPush = hit.pushForce.y - (hit.pushForce.y * (float)airJuggleHits * .04f);
                }else if (UFE.config.comboOptions.airJuggleDeterioration == Sizes.Medium){
                    verticalPush = hit.pushForce.y - (hit.pushForce.y * (float)airJuggleHits * .1f);
                }else if (UFE.config.comboOptions.airJuggleDeterioration == Sizes.High){
                    verticalPush = hit.pushForce.y - (hit.pushForce.y * (float)airJuggleHits * .3f);
                }
                if (verticalPush < UFE.config.comboOptions.minPushForce) verticalPush = UFE.config.comboOptions.minPushForce;
                airJuggleHits ++;
            }

            if (UFE.config.comboOptions.fixJuggleWeight){
                myPhysicsScript.ApplyNewWeight(UFE.config.comboOptions.juggleWeight);
            }

            if (isDead) stunTime = 9999;

            if ((airHit || UFE.config.comboOptions.neverAirRecover) && verticalPush > 0){

                if (myMoveSetScript.basicMoves.getHitAir.clip1 == null)
                    Debug.LogError("Get Hit Air animation not found! Make sure you have it set on Character -> Basic Moves -> Get Hit Air");
                if (myMoveSetScript.basicMoves.getHitAir.invincible) myHitBoxesScript.HideHitBoxes(true);

                myPhysicsScript.ResetForces(hit.resetPreviousHorizontalPush, hit.resetPreviousVerticalPush);
                myPhysicsScript.AddForce(new Vector2(hit.pushForce.x, verticalPush), -opControlsScript.mirror);
                if (myMoveSetScript.basicMoves.getHitKnockBack.clip1 != null &&
                    hit.pushForce.x > UFE.config.comboOptions.knockBackMinForce) {
                    currentHitAnimation = myMoveSetScript.basicMoves.getHitKnockBack.name;
                    currentHitInfo = myMoveSetScript.basicMoves.getHitKnockBack;
                }else{
                    currentHitAnimation = myMoveSetScript.basicMoves.getHitAir.name;
                    currentHitInfo = myMoveSetScript.basicMoves.getHitAir;
                }

                myMoveSetScript.PlayBasicMove(currentHitInfo, currentHitAnimation, UFE.config.hitOptions.resetAnimationOnHit);

                if (currentHitInfo.autoSpeed) {
                    // if the hit was in the air, calculate the time it will take for the character to hit the ground
                    float airTime = myPhysicsScript.GetPossibleAirTime(verticalPush) * 2;
                    if (stunTime > airTime || UFE.config.comboOptions.neverAirRecover) stunTime = airTime;
                    myMoveSetScript.SetAnimationNormalizedSpeed(currentHitAnimation, (myMoveSetScript.GetAnimationLengh(currentHitAnimation) / stunTime));
                }

            }else{

                float hitAnimationSpeed = 0;
                float knockoutAnimationLenght = 0;

                if (hit.hitType == HitType.HighKnockdown){
                    // if its a knockdown, animation will run at normal speed and character will stay knockdown for -stunTime- seconds.
                    knockoutAnimationLenght = myMoveSetScript.GetAnimationLengh(currentHitAnimation)/myMoveSetScript.basicMoves.getHitHighKnockdown.animationSpeed;
                    stunTime = knockoutAnimationLenght + AdjustKnockdownVariables(UFE.config.knockDownOptions.high);
                }else if (hit.hitType == HitType.MidKnockdown){
                    // if its a knockdown, animation will run at normal speed and character will stay knockdown for -stunTime- seconds.
                    knockoutAnimationLenght = myMoveSetScript.GetAnimationLengh(currentHitAnimation)/myMoveSetScript.basicMoves.getHitHighLowKnockdown.animationSpeed;
                    stunTime = knockoutAnimationLenght + AdjustKnockdownVariables(UFE.config.knockDownOptions.highLow);
                }else if (hit.hitType == HitType.Sweep){
                    // if its a knockdown, animation will run at normal speed and character will stay knockdown for -stunTime- seconds.
                    knockoutAnimationLenght = myMoveSetScript.GetAnimationLengh(currentHitAnimation)/myMoveSetScript.basicMoves.getHitSweep.animationSpeed;
                    stunTime = knockoutAnimationLenght + AdjustKnockdownVariables(UFE.config.knockDownOptions.sweep);
                }else if (hit.hitStrength == HitStrengh.Crumple){
                    stunTime += UFE.config.knockDownOptions.crumple.standUpTime;
                }else {
                    hitAnimationSpeed = myMoveSetScript.GetAnimationLengh(currentHitAnimation)/stunTime;

                    myPhysicsScript.ResetForces(hit.resetPreviousHorizontalPush, hit.resetPreviousVerticalPush);
                    myPhysicsScript.AddForce(new Vector2(hit.pushForce.x, verticalPush), -opControlsScript.mirror);

                    // Set deceleration of hit stun animation so it can look more natural
                    if (UFE.config.hitOptions.useHitStunDeceleration) {
                        hitStunDeceleration = hitAnimationSpeed + (stunTime / 2);
                    }
                }

                myMoveSetScript.PlayBasicMove(currentHitInfo, currentHitAnimation, UFE.config.hitOptions.resetAnimationOnHit);
                if (currentHitInfo.autoSpeed && hitAnimationSpeed > 0) {
                    myMoveSetScript.SetAnimationSpeed(currentHitAnimation, hitAnimationSpeed);
                }

            }
        }

        // Freeze screen depending on how strong the hit was
        HitPause(GetHitAnimationSpeed(hit.hitStrength) * .01f);
        UFE.DelaySynchronizedAction(this.HitUnpause, hitEffects.freezingTime);
    }
Пример #2
0
    public void ReadMove(MoveInfo move)
    {
        if (move == null) return;

        potentialParry = 0;
        potentialBlock = false;

        if (move.currentTick == 0) {
            if (!myMoveSetScript.AnimationExists(move.name))
                Debug.LogError("Animation for move '"+ move.name +"' not found!");

            if (move.disableHeadLook) ToggleHeadLook(false);

            if (myPhysicsScript.IsGrounded()) {
                myPhysicsScript.isTakingOff = false;
                myPhysicsScript.isLanding = false;
            }

            if (currentState == PossibleStates.StraightJump ||
                currentState == PossibleStates.ForwardJump ||
                currentState == PossibleStates.BackJump){
                myMoveSetScript.totalAirMoves ++;
            }

            float normalizedTimeConv = myMoveSetScript.GetAnimationNormalizedTime(move.overrideStartupFrame, move);

            if (move.overrideBlendingIn) {
                myMoveSetScript.PlayAnimation(move.name, move.blendingIn, normalizedTimeConv);
            }else{
                myMoveSetScript.PlayAnimation(move.name, myInfo.blendingTime, normalizedTimeConv);
            }

            if (currentMove.invertRotationLeft && mirror == -1) InvertRotation();
            if (currentMove.forceMirrorLeft && mirror == -1) ForceMirror(true);

            if (currentMove.invertRotationRight && mirror == 1) InvertRotation();
            if (currentMove.forceMirrorRight && mirror == 1) ForceMirror(!UFE.config.characterRotationOptions.autoMirror);

            move.currentTick = move.overrideStartupFrame;
            move.currentFrame = move.overrideStartupFrame;
            move.animationSpeedTemp = move.animationSpeed;

            myMoveSetScript.SetAnimationSpeed(move.name, move.animationSpeed);
            if (move.overrideBlendingOut) myMoveSetScript.overrideNextBlendingValue = move.blendingOut;

            AddGauge(move.gaugeGainOnMiss);
            RemoveGauge(move.gaugeUsage);
        }

        // ANIMATION FRAME DATA
        if (myMoveSetScript.animationPaused) {
            move.currentTick += Time.fixedDeltaTime * UFE.config.fps * myMoveSetScript.GetAnimationSpeed();
        }else{
            move.currentTick += Time.fixedDeltaTime * UFE.config.fps;
        }
        if (move.currentTick > move.currentFrame) move.currentFrame ++;

        // deprecated
        /*if (myInfo.animationFlow == AnimationFlow.MorePrecision && !myMoveSetScript.animationPaused){

            myMoveSetScript.SetAnimationSpeed(move.name, 0);
            if (myInfo.animationType == AnimationType.Legacy){
                character.GetComponent<Animation>()[move.name].normalizedTime = myMoveSetScript.GetAnimationNormalizedTime(move.currentFrame, move);
            }else{
                myMoveSetScript.SetAnimationPosition(move.name, myMoveSetScript.GetAnimationNormalizedTime(move.currentFrame, move));
            }
        }*/

        // Assign Current Frame Data Description
        if (move.currentFrame <= move.startUpFrames) {
            move.currentFrameData = CurrentFrameData.StartupFrames;
        }else if (move.currentFrame > move.startUpFrames && move.currentFrame <= move.startUpFrames + move.activeFrames) {
            move.currentFrameData = CurrentFrameData.ActiveFrames;
        }else{
            move.currentFrameData = CurrentFrameData.RecoveryFrames;
        }

        // Check Projectiles
        foreach (Projectile projectile in move.projectiles){
            if (
                !projectile.casted &&
                projectile.projectilePrefab != null &&
                move.currentFrame >= projectile.castingFrame
                ){
                projectile.casted = true;
                projectile.gaugeGainOnHit = move.gaugeGainOnHit;
                projectile.gaugeGainOnBlock = move.gaugeGainOnBlock;
                projectile.opGaugeGainOnHit = move.opGaugeGainOnHit;
                projectile.opGaugeGainOnBlock = move.opGaugeGainOnBlock;
                projectile.opGaugeGainOnParry = move.opGaugeGainOnParry;

                Vector3 newPos = myHitBoxesScript.GetPosition(projectile.bodyPart);
                if (projectile.fixedZAxis) newPos.z = 0;
                GameObject pTemp = (GameObject) Instantiate(
                    projectile.projectilePrefab,
                    newPos,
                    Quaternion.Euler(0,0,projectile.directionAngle)
                    );

                ProjectileMoveScript projectileMoveScript = pTemp.AddComponent<ProjectileMoveScript>();
                projectileMoveScript.data = projectile;
                projectileMoveScript.opHitBoxesScript = opHitBoxesScript;
                projectileMoveScript.opControlsScript = opControlsScript;
                projectileMoveScript.myControlsScript = this;
                projectileMoveScript.mirror = mirror;

                projectiles.Add(projectileMoveScript);
            }
        }

        // Check Particle Effects
        foreach (MoveParticleEffect particleEffect in move.particleEffects){
            if (
                !particleEffect.casted &&
                particleEffect.particleEffect.prefab != null &&
                move.currentFrame >=  particleEffect.castingFrame
                ){
                particleEffect.casted = true;
                GameObject pTemp = (GameObject) Instantiate(particleEffect.particleEffect.prefab);

                Vector3 newPosition = myHitBoxesScript.GetPosition(particleEffect.particleEffect.bodyPart);
                newPosition.x += particleEffect.particleEffect.offSet.x * -mirror;
                newPosition.y += particleEffect.particleEffect.offSet.y;
                newPosition.z += particleEffect.particleEffect.offSet.z;
                pTemp.transform.position = newPosition;
                if (particleEffect.particleEffect.stick) pTemp.transform.parent = transform;

                Destroy(pTemp, particleEffect.particleEffect.duration);
            }
        }

        // Check Applied Forces
        foreach (AppliedForce addedForce in move.appliedForces){
            if (!addedForce.casted && move.currentFrame >= addedForce.castingFrame){
                myPhysicsScript.ResetForces(addedForce.resetPreviousHorizontal, addedForce.resetPreviousVertical);
                myPhysicsScript.AddForce(addedForce.force, -mirror);
                addedForce.casted = true;
            }
        }

        // Check SlowMo Effects
        foreach (SlowMoEffect slowMoEffect in move.slowMoEffects){
            if (!slowMoEffect.casted && move.currentFrame >= slowMoEffect.castingFrame){
                Time.timeScale = (slowMoEffect.percentage / 100f) * UFE.config.gameSpeed;
                UFE.DelaySynchronizedAction(this.ResetTimeScale, slowMoEffect.duration);
                slowMoEffect.casted = true;
            }
        }

        // Check Sound Effects
        foreach (SoundEffect soundEffect in move.soundEffects){
            if (!soundEffect.casted && move.currentFrame >= soundEffect.castingFrame){
                UFE.PlaySound(soundEffect.sounds);
                soundEffect.casted = true;
            }
        }

        // Check In Game Alert
        foreach (InGameAlert inGameAlert in move.inGameAlert){
            if (!inGameAlert.casted && move.currentFrame >= inGameAlert.castingFrame){
                UFE.FireAlert(inGameAlert.alert, myInfo);
                inGameAlert.casted = true;
            }
        }

        // Change Stances
        foreach (StanceChange stanceChange in move.stanceChanges){
            if (!stanceChange.casted && move.currentFrame >= stanceChange.castingFrame){
                myMoveSetScript.ChangeMoveStances(stanceChange.newStance);
                stanceChange.casted = true;
            }
        }

        #if !UFE_BASIC
        // Check Opponent Override
        foreach (OpponentOverride opponentOverride in move.opponentOverride){
            if (!opponentOverride.casted && move.currentFrame >= opponentOverride.castingFrame){
                if (opponentOverride.stun){
                    opControlsScript.stunTime = (float)opponentOverride.stunTime/(float)UFE.config.fps;
                    if (opponentOverride.stunTime > 0) opControlsScript.currentSubState = SubStates.Stunned;
                }

                opControlsScript.KillCurrentMove();
                foreach(CharacterSpecificMoves csMove in opponentOverride.characterSpecificMoves){
                    if (opInfo.characterName == csMove.characterName) {
                        opControlsScript.CastMove(csMove.move, true);
                        if (opponentOverride.stun) opControlsScript.currentMove.standUpOptions = opponentOverride.standUpOptions;
                        opControlsScript.currentMove.hitAnimationOverride = opponentOverride.overrideHitAnimations;
                    }
                }
                if (opControlsScript.currentMove == null && opponentOverride.move != null){
                    opControlsScript.CastMove(opponentOverride.move, true);
                    if (opponentOverride.stun) opControlsScript.currentMove.standUpOptions = opponentOverride.standUpOptions;
                    opControlsScript.currentMove.hitAnimationOverride = opponentOverride.overrideHitAnimations;
                }

                opControlsScript.activePullIn = new PullIn();
                Vector3 newPos = opponentOverride.position;
                newPos.x *= -mirror;
                opControlsScript.activePullIn.position = transform.position + newPos;
                opControlsScript.activePullIn.speed = opponentOverride.blendSpeed;

                if (opponentOverride.resetAppliedForces){
                    opPhysicsScript.ResetForces(true, true);
                    myPhysicsScript.ResetForces(true, true);
                }

                opponentOverride.casted = true;
            }
        }

        // Check Camera Movements (cinematics)
        foreach (CameraMovement cameraMovement in move.cameraMovements){
            if (cameraMovement.over) continue;
            if (cameraMovement.casted && !cameraMovement.over && cameraMovement.time >= cameraMovement.duration && UFE.freeCamera){
                cameraMovement.over = true;
                ReleaseCam();
            }
            if (move.currentFrame >= cameraMovement.castingFrame){
                cameraMovement.time += Time.fixedDeltaTime;
                if (cameraMovement.casted) continue;
                cameraMovement.casted = true;

                PausePlayAnimation(true, cameraMovement.myAnimationSpeed * .01f);
                opControlsScript.PausePlayAnimation(true, cameraMovement.opAnimationSpeed * .01f);
                myPhysicsScript.freeze = cameraMovement.freezePhysics;
                opPhysicsScript.freeze = cameraMovement.freezePhysics;
                cameraScript.cinematicFreeze = cameraMovement.freezePhysics;

                if (cameraMovement.cinematicType == CinematicType.CameraEditor){
                    cameraMovement.position.x *= -mirror;
                    Vector3 targetPosition = transform.TransformPoint(cameraMovement.position);
                    Vector3 targetRotation = cameraMovement.rotation;
                    targetRotation.y *= -mirror;
                    targetRotation.z *= -mirror;
                    cameraScript.MoveCameraToLocation(targetPosition,
                                                      targetRotation,
                                                      cameraMovement.fieldOfView,
                                                      cameraMovement.camSpeed, gameObject.name);

                }else if (cameraMovement.cinematicType == CinematicType.Prefab){
                    cameraScript.SetCameraOwner(gameObject.name);
                    emulatedCam = (GameObject) Instantiate(cameraMovement.prefab);
                    emulatedCam.transform.position = transform.position;

                }else if (cameraMovement.cinematicType == CinematicType.AnimationFile){
                    emulatedCam = new GameObject();
                    emulatedCam.name = "Camera Parent";
                    emulatedCam.transform.parent = transform;
                    emulatedCam.transform.localPosition = cameraMovement.gameObjectPosition;
                    emulatedCam.AddComponent(typeof(Animation));
                    emulatedCam.GetComponent<Animation>().AddClip(cameraMovement.animationClip, "cam");
                    emulatedCam.GetComponent<Animation>()["cam"].speed = cameraMovement.camAnimationSpeed;
                    emulatedCam.GetComponent<Animation>().Play("cam");
                    cameraMovement.duration = cameraMovement.animationClip.length/cameraMovement.camAnimationSpeed;

                    Camera.main.transform.parent = emulatedCam.transform;
                    cameraScript.MoveCameraToLocation(cameraMovement.position,
                                                      cameraMovement.rotation,
                                                      cameraMovement.fieldOfView,
                                                      cameraMovement.blendSpeed, gameObject.name);

                }
            }
        }
        #endif

        // Check Invincible Body Parts
        if (move.invincibleBodyParts.Length > 0) {
            foreach (InvincibleBodyParts invBodyPart in move.invincibleBodyParts){
                if (move.currentFrame >= invBodyPart.activeFramesBegin &&
                    move.currentFrame < invBodyPart.activeFramesEnds) {
                    if (invBodyPart.completelyInvincible){
                        myHitBoxesScript.HideHitBoxes(true);
                    }else{
                        myHitBoxesScript.HideHitBoxes(invBodyPart.hitBoxes, true);
                    }
                    ignoreCollisionMass = invBodyPart.ignoreBodyColliders;
                }
                if (move.currentFrame >= invBodyPart.activeFramesEnds) {
                    if (invBodyPart.completelyInvincible){
                        myHitBoxesScript.HideHitBoxes(false);
                    }else{
                        myHitBoxesScript.HideHitBoxes(invBodyPart.hitBoxes, false);
                    }
                    ignoreCollisionMass = false;
                }
            }
        }

        // Check Blockable Area
        if (move.blockableArea.bodyPart != BodyPart.none){
            if (move.currentFrame >= move.blockableArea.activeFramesBegin &&
                move.currentFrame < move.blockableArea.activeFramesEnds) {
                myHitBoxesScript.blockableArea = move.blockableArea;
                myHitBoxesScript.blockableArea.position = myHitBoxesScript.GetPosition(myHitBoxesScript.blockableArea.bodyPart);

                if (!opControlsScript.isBlocking
                    && !opControlsScript.blockStunned
                    && opControlsScript.currentSubState != SubStates.Stunned
                    && opHitBoxesScript.TestCollision(myHitBoxesScript.blockableArea) != Vector3.zero) {
                    opControlsScript.CheckBlocking(true);
                }
            }else if (move.currentFrame >= move.blockableArea.activeFramesEnds){
                if (UFE.config.blockOptions.blockType == BlockType.HoldBack ||
                    UFE.config.blockOptions.blockType == BlockType.AutoBlock) opControlsScript.CheckBlocking(false);
            }
        }

        #if !UFE_BASIC
        // Check Frame Links
        foreach (FrameLink frameLink in move.frameLinks){
            if (move.currentFrame >= frameLink.activeFramesBegins &&
                 move.currentFrame <= frameLink.activeFramesEnds) {
                if ((frameLink.linkType == LinkType.HitConfirm &&
                     (move.hitConfirmOnStrike && frameLink.onStrike) ||
                     (move.hitConfirmOnBlock && frameLink.onBlock) ||
                     (move.hitConfirmOnParry && frameLink.onParry))) {
                    frameLink.cancelable = true;
                    move.cancelable = true;
                } else if (frameLink.linkType == LinkType.NoConditions) {
                    frameLink.cancelable = true;
                    move.cancelable = true;
                }
            } else if (move.currentFrame >= (frameLink.activeFramesBegins - UFE.config.executionBufferTime) &&
                move.currentFrame <= frameLink.activeFramesEnds && frameLink.allowBuffer) {
                if ((frameLink.linkType == LinkType.HitConfirm &&
                    (move.hitConfirmOnStrike && frameLink.onStrike) ||
                    (move.hitConfirmOnBlock && frameLink.onBlock) ||
                    (move.hitConfirmOnParry && frameLink.onParry))) {
                    frameLink.cancelable = true;
                    move.cancelable = true;
                } else if (frameLink.linkType == LinkType.NoConditions) {
                    frameLink.cancelable = true;
                    move.cancelable = true;
                }
            }else{
                frameLink.cancelable = false;
                //move.cancelable = false;
            }
        }
        #endif

        // Check Hits
        foreach (Hit hit in move.hits){
            HurtBox[] activeHurtBoxes = null;
            if (move.currentFrame >= hit.activeFramesBegin &&
                move.currentFrame < hit.activeFramesEnds) {
                if (hit.hurtBoxes.Length > 0){
                    activeHurtBoxes = hit.hurtBoxes;
                    if (hit.disabled) continue;
                    if (!opControlsScript.ValidateHit(hit)) continue;

                    foreach(HurtBox hurtBox in activeHurtBoxes) {
                        hurtBox.position = myHitBoxesScript.GetPosition(hurtBox.bodyPart);
                        hurtBox.rendererBounds = myHitBoxesScript.GetBounds();
                    }

                    Vector3 collisionVector_hit = opHitBoxesScript.TestCollision(activeHurtBoxes, hit.hitConfirmType);
                    if (collisionVector_hit != Vector3.zero) { // HURTBOX TEST
                        // Tech Throw
                        if (hit.hitConfirmType == HitConfirmType.Throw
                            && hit.techable
                            && opControlsScript.currentMove != null
                            && opControlsScript.currentMove.IsThrow(true)
                            ){
                            CastMove(hit.techMove, true);
                            opControlsScript.CastMove(opControlsScript.currentMove.GetTechMove(), true);
                            return;

                        // Throw
                        }else if (hit.hitConfirmType == HitConfirmType.Throw){
                            CastMove(hit.throwMove, true);
                            return;

                        // Block
                        }else if (opControlsScript.currentSubState != SubStates.Stunned
                                  && opControlsScript.currentMove == null
                                  && opControlsScript.isBlocking
                                  && opControlsScript.TestBlockStances(hit.hitType)
                                  ){
                            opControlsScript.GetHitBlocking(hit, move.totalFrames - move.currentFrame, collisionVector_hit);
                            AddGauge(move.gaugeGainOnBlock);
                            opControlsScript.AddGauge(move.opGaugeGainOnBlock);
                            move.hitConfirmOnBlock = true;

                        // Parry
                        }else if (opControlsScript.potentialParry > 0
                                  && opControlsScript.currentMove == null
                                  && hit.hitConfirmType != HitConfirmType.Throw
                                  && opControlsScript.TestParryStances(hit.hitType)
                                  ){
                            opControlsScript.GetHitParry(hit, move.totalFrames - move.currentFrame, collisionVector_hit);
                            opControlsScript.AddGauge(move.opGaugeGainOnParry);
                            move.hitConfirmOnParry = true;

                        // Hit
                        }else {
                            opControlsScript.GetHit(hit, move.totalFrames - move.currentFrame, collisionVector_hit);
                            AddGauge(move.gaugeGainOnHit);
                            opControlsScript.AddGauge(move.opGaugeGainOnHit);

                            if (hit.pullSelfIn.enemyBodyPart != BodyPart.none && hit.pullSelfIn.characterBodyPart != BodyPart.none){
                                Vector3 newPos = opHitBoxesScript.GetPosition(hit.pullSelfIn.enemyBodyPart);
                                if (newPos != Vector3.zero){
                                    activePullIn = new PullIn();
                                    activePullIn.position = transform.position + (newPos - myHitBoxesScript.GetPosition(hit.pullSelfIn.characterBodyPart));
                                    activePullIn.speed = hit.pullSelfIn.speed;
                                    activePullIn.forceStand = hit.pullEnemyIn.forceStand;
                                    activePullIn.position.z = 0;
                                    if (hit.pullEnemyIn.forceStand){
                                        activePullIn.position.y = 0;
                                        myPhysicsScript.ForceGrounded();
                                    }
                                }
                            }
                            move.hitConfirmOnStrike = true;
                        }
                        myPhysicsScript.ResetForces(hit.resetPreviousHorizontal, hit.resetPreviousVertical);
                        myPhysicsScript.AddForce(hit.appliedForce, -mirror);

                        if ((opponent.transform.position.x >= UFE.config.selectedStage.rightBoundary - 2 ||
                             opponent.transform.position.x <= UFE.config.selectedStage.leftBoundary + 2)
                            && myPhysicsScript.IsGrounded()
                            && !UFE.config.comboOptions.neverCornerPush && hit.cornerPush
                            ){

                            myPhysicsScript.ResetForces(hit.resetPreviousHorizontalPush, false);
                            myPhysicsScript.AddForce(
                                new Vector2(hit.pushForce.x + (opPhysicsScript.airTime * opInfo.physics.friction), 0), mirror);
                        }

                        if (opPhysicsScript.freeze){
                            HitPause(GetHitAnimationSpeed(hit.hitStrength) * .01f);
                            UFE.DelaySynchronizedAction(this.HitUnpause, GetHitFreezingTime(hit.hitStrength));
                        }
                        if (!hit.continuousHit) hit.disabled = true;
                    };
                }
            }
            myHitBoxesScript.activeHurtBoxes = activeHurtBoxes;
        }

        if(move.currentFrame >= move.totalFrames) {
            if (move.name == "Intro") {
                introPlayed = true;
                UFE.CastNewRound();
            }
            KillCurrentMove();
        }
    }