Inheritance: MonoBehaviour
Example #1
0
    protected virtual MovementInfo ChooseMovement(ControlsScript self, ControlsScript opponent, float deltaTime)
    {
        // Find out if this AI is controlling the first or the second player.
        if (self != null && opponent != null){
            if (this.aiOutput != null){
                // Check if we want to use the best available move or the Weighted Random Selection in this decision step...
                float newRuleCompliance = (UFE.GetAIDifficulty() != null && UFE.GetAIDifficulty().overrideRuleCompliance) ?
                    UFE.GetAIDifficulty().ruleCompliance : this.ai.advancedOptions.ruleCompliance;

                bool useBestAvailableMove = UnityEngine.Random.Range(0f, 1f) < newRuleCompliance;

                // Then calculate the desirability of each possible movement...
                this.movements.Clear();

                float attackWeight = (UFE.GetAIDifficulty() != null && UFE.GetAIDifficulty().overrideAggressiveness) ?
                    UFE.GetAIDifficulty().aggressiveness : this.ai.advancedOptions.aggressiveness;

                if (self.currentMove != null && opponent.currentSubState == SubStates.Stunned) {
                    float newComboEfficiency = (UFE.GetAIDifficulty() != null && UFE.GetAIDifficulty().overrideAggressiveness) ?
                        UFE.GetAIDifficulty().comboEfficiency : this.ai.advancedOptions.comboEfficiency;

                    attackWeight = newComboEfficiency/2;
                }

                float basicMoveWeight =  1f - attackWeight;
                float weight;

                float newTimeBetweenDecisions = (UFE.GetAIDifficulty() != null && UFE.GetAIDifficulty().overrideTimeBetweenDecisions) ?
                    UFE.GetAIDifficulty().timeBetweenDecisions : this.ai.advancedOptions.timeBetweenDecisions;

                int frames = Mathf.FloorToInt(newTimeBetweenDecisions / deltaTime) + 1;

                int paddingBeforeJump = Mathf.Max(UFE.config.plinkingDelay + 1, Mathf.FloorToInt(self.myInfo.executionTiming / deltaTime) + 1);

                if (this.aiOutput.TryGetValue(AIReaction.Crouch, out weight) && this.ValidateReaction(AIReactionType.Crouch, self, opponent)){
                    this.movements.Add(new MovementInfo(AIReaction.Crouch, this.crouchSimulatedInput, weight * basicMoveWeight));
                }
                if (this.aiOutput.TryGetValue(AIReaction.Idle, out weight) && this.ValidateReaction(AIReactionType.Idle, self, opponent)){
                    this.movements.Add(new MovementInfo(AIReaction.Idle, this.idleSimulatedInput, weight * basicMoveWeight));
                }
                if (this.aiOutput.TryGetValue(AIReaction.JumpBackward, out weight) && this.ValidateReaction(AIReactionType.JumpBack, self, opponent)){
                    // We don't want to jump accidentally in the wrong direction, so we must have plinking into account
                    ButtonPress[][] jumpSimulatedInput = this.jumpBackwardSimulatedInput;

                    if (!Mathf.Approximately(this.inputBuffer[this.inputBuffer.Count - 1][this.horizontalAxis].axisRaw, 0f)){
                        List<ButtonPress[]> temp = new List<ButtonPress[]>();

                        for (int i = 0; i < paddingBeforeJump; ++i){
                            temp.Add(this.noButtonsPressed);
                        }

                        temp.AddRange(jumpSimulatedInput);
                        jumpSimulatedInput = temp.ToArray();
                    }

                    this.movements.Add(new MovementInfo(AIReaction.JumpBackward, jumpSimulatedInput.ToArray(), weight * basicMoveWeight));
                }
                if (this.aiOutput.TryGetValue(AIReaction.JumpForward, out weight) && this.ValidateReaction(AIReactionType.JumpForward, self, opponent)){
                    // We don't want to jump accidentally in the wrong direction, so we must have plinking into account
                    ButtonPress[][] jumpSimulatedInput = this.jumpForwardSimulatedInput;

                    if (!Mathf.Approximately(this.inputBuffer[this.inputBuffer.Count - 1][this.horizontalAxis].axisRaw, 0f)){
                        List<ButtonPress[]> temp = new List<ButtonPress[]>();

                        for (int i = 0; i < paddingBeforeJump; ++i){
                            temp.Add(this.noButtonsPressed);
                        }

                        temp.AddRange(jumpSimulatedInput);
                        jumpSimulatedInput = temp.ToArray();
                    }

                    this.movements.Add(new MovementInfo(AIReaction.JumpForward, jumpSimulatedInput.ToArray(), weight * basicMoveWeight));
                }
                if (this.aiOutput.TryGetValue(AIReaction.JumpStraight, out weight) && this.ValidateReaction(AIReactionType.JumpStraight, self, opponent)){
                    // We don't want to jump accidentally in the wrong direction, so we must have plinking into account
                    ButtonPress[][] jumpSimulatedInput = this.jumpBackwardSimulatedInput;

                    if (!Mathf.Approximately(this.inputBuffer[this.inputBuffer.Count - 1][this.horizontalAxis].axisRaw, 0f)){
                        List<ButtonPress[]> temp = new List<ButtonPress[]>();

                        for (int i = 0; i < paddingBeforeJump; ++i){
                            temp.Add(this.noButtonsPressed);
                        }

                        temp.AddRange(jumpSimulatedInput);
                        jumpSimulatedInput = temp.ToArray();
                    }

                    this.movements.Add(new MovementInfo(AIReaction.JumpStraight, jumpSimulatedInput.ToArray(), weight * basicMoveWeight));
                }
                if (this.aiOutput.TryGetValue(AIReaction.MoveBackward, out weight) && this.ValidateReaction(AIReactionType.MoveBack, self, opponent)){
                    this.movements.Add(new MovementInfo(AIReaction.MoveBackward, this.moveBackwardSimulatedInput, weight * basicMoveWeight));
                }
                if (this.aiOutput.TryGetValue(AIReaction.MoveForward, out weight) && this.ValidateReaction(AIReactionType.MoveForward, self, opponent)){
                    this.movements.Add(new MovementInfo(AIReaction.MoveForward, this.moveForwardSimulatedInput, weight * basicMoveWeight));
                }

                // Including blocks...
                if (this.aiOutput.TryGetValue(AIReaction.CrouchBlock, out weight) && this.ValidateReaction(AIReactionType.CrouchBlock, self, opponent)){
                    this.movements.Add(new MovementInfo(AIReaction.CrouchBlock, this.crouchBlockSimulatedInput, weight * basicMoveWeight));
                }
                if (this.aiOutput.TryGetValue(AIReaction.JumpBlock, out weight) && this.ValidateReaction(AIReactionType.JumpBlock, self, opponent)){
                    this.movements.Add(new MovementInfo(AIReaction.JumpBlock, this.jumpBlockSimulatedInput, weight * basicMoveWeight));
                }
                if (this.aiOutput.TryGetValue(AIReaction.StandBlock, out weight) && this.ValidateReaction(AIReactionType.StandBlock, self, opponent)){
                    this.movements.Add(new MovementInfo(AIReaction.StandBlock, this.standBlockSimulatedInput, weight * basicMoveWeight));
                }

                // Changing AI behaviours...
                if (this.aiOutput.TryGetValue(AIReaction.ChangeBehaviour_Aggressive, out weight)){
                    this.movements.Add(new MovementInfo(AIReaction.ChangeBehaviour_Aggressive, null, weight));
                }
                if (this.aiOutput.TryGetValue(AIReaction.ChangeBehaviour_Any, out weight)){
                    this.movements.Add(new MovementInfo(AIReaction.ChangeBehaviour_Any, null, weight));
                }
                if (this.aiOutput.TryGetValue(AIReaction.ChangeBehaviour_Balanced, out weight)){
                    this.movements.Add(new MovementInfo(AIReaction.ChangeBehaviour_Balanced, null, weight));
                }
                if (this.aiOutput.TryGetValue(AIReaction.ChangeBehaviour_Defensive, out weight)){
                    this.movements.Add(new MovementInfo(AIReaction.ChangeBehaviour_Defensive, null, weight));
                }
                if (this.aiOutput.TryGetValue(AIReaction.ChangeBehaviour_VeryAggressive, out weight)){
                    this.movements.Add(new MovementInfo(AIReaction.ChangeBehaviour_VeryAggressive, null, weight));
                }
                if (this.aiOutput.TryGetValue(AIReaction.ChangeBehaviour_VeryDefensive, out weight)){
                    this.movements.Add(new MovementInfo(AIReaction.ChangeBehaviour_VeryDefensive, null, weight));
                }

                // And attack movements...
                if(
                    this.aiOutput.ContainsKey(AIReaction.PlayMove_RandomAttack) &&
                    this.ValidateReaction(AIReactionType.PlayMove, self, opponent)
                    ){
                    this.AddValidMoves(
                        self,
                        opponent,
                        this.inferenceEngine.DefaultValue,
                        useBestAvailableMove,
                        deltaTime
                        );
                }

                // Check if the character can execute any movement...
                MovementInfo currentMovement;
                if (this.movements.Count > 0){
                    // Check if we want to select only the best available movement or if we want to choose
                    // a random movement giving higher chances to movements with higher desirability...
                    //
                    // If we want to select the best available movement, but there are several movements with
                    // the best weight, we choose one of those movements randomly.
                    this.movements.Sort(delegate(MovementInfo move1, MovementInfo move2) {
                        return move2.weight.CompareTo(move1.weight);
                    });

                    self.aiDebugger = "";
                    if (self.debugger != null && UFE.config.debugOptions.debugMode && ai.debugMode && ai.debug_ReactionWeight){
                        self.aiDebugger = "-----AI Reaction Weights-----\n";
                        StringBuilder sb = new StringBuilder();
                        sb.Append("Instruction Set: ").Append(ai.instructionsName).AppendLine();

                        foreach(MovementInfo mInfo in this.movements){
                            sb.Append(mInfo.name).Append(" = ").Append(mInfo.weight).AppendLine();
                        }

                        self.aiDebugger += sb.ToString();
                    }

                    if (useBestAvailableMove){
                        //---------------------------------------------------------------------------------------------
                        // If we want to use the best available move, find the move with the best weight and discard
                        // the rest of the moves. If there are several moves with the best weight, choose one of them
                        // randomly.
                        //---------------------------------------------------------------------------------------------
                        float maxWeight = 0f;

                        for (int i = 0; i < this.movements.Count; ++i){
                            currentMovement = this.movements[i];

                            //-----------------------------------------------------------------------------------------
                            // We know the moves are already sorted by its weight,
                            // but we want to check if the simulated input is null
                            // because those are special cases.
                            //-----------------------------------------------------------------------------------------
                            if (currentMovement != null && currentMovement.simulatedInput != null){
                                maxWeight = currentMovement.weight;
                                break;
                            }
                        }

                        for (int i = this.movements.Count - 1; i > 0; --i){
                            currentMovement = this.movements[i];

                            if (
                                currentMovement == null
                                ||
                                (
                                currentMovement.weight < maxWeight &&
                                !Mathf.Approximately(currentMovement.weight, maxWeight)
                                )
                                ){
                                this.movements.RemoveAt(i);
                            }
                        }
                    }

                    MovementInfo chosenMovement = null;
                    while (chosenMovement == null || chosenMovement.simulatedInput == null){
                        //---------------------------------------------------------------------------------------------
                        // Calculate the total weight of all possible moves
                        //---------------------------------------------------------------------------------------------

                        //---------------------------------------------------------------------------------------------
                        // It's look like the iOS AOT Compiler doesn't like this function, so I implement it myself.
                        //---------------------------------------------------------------------------------------------
                        //float totalWeight = this.movements.Sum((MovementInfo m) => m.weight);
                        float totalWeight = 0f;
                        foreach (MovementInfo movement in movements){
                            if (movement != null){
                                totalWeight += movement.weight;
                            }
                        }

                        if (totalWeight > 0f){
                            //-----------------------------------------------------------------------------------------
                            // If the total weight is greater than zero, choose a random movement
                            // (taking the weight of that movement into account)
                            //-----------------------------------------------------------------------------------------
                            float random = UnityEngine.Random.Range(0f, totalWeight);

                            int length = this.movements.Count;
                            float accumulatedWeight = 0f;
                            float currentWeight;

                            for (int i = 0; i < length - 1; ++i){
                                currentMovement = this.movements[i];

                                if (currentMovement != null){
                                    currentWeight = currentMovement.weight;

                                    if (currentWeight > 0f){
                                        accumulatedWeight += currentWeight;

                                        if (random < accumulatedWeight){
                                            chosenMovement = currentMovement;
                                            break;
                                        }
                                    }
                                }
                            }

                            if (chosenMovement == null && length > 0){
                                chosenMovement = this.movements[length - 1];
                            }

                            //-----------------------------------------------------------------------------------------
                            // If the chosen movement doesn't have a simulated input, it's a special case
                            //-----------------------------------------------------------------------------------------
                            if (chosenMovement != null && chosenMovement.simulatedInput.Length == 0){
                                if (AIReaction.ChangeBehaviour_Aggressive.Equals(chosenMovement.name)){
                                    foreach (AIInstructionsSet instructionsSet in self.myInfo.aiInstructionsSet){
                                        if (instructionsSet != null && instructionsSet.behavior == AIBehavior.Aggressive){
                                            this.SetAIInformation(instructionsSet.aiInfo);
                                            break;
                                        }
                                    }
                                }else if (AIReaction.ChangeBehaviour_Any.Equals(chosenMovement.name)){
                                    List<AIInstructionsSet> instructions = new List<AIInstructionsSet>(self.myInfo.aiInstructionsSet);
                                    AIInstructionsSet instructionsSet = null;

                                    while (instructionsSet == null && instructions.Count > 0){
                                        int r = UnityEngine.Random.Range(0, instructions.Count);
                                        instructionsSet = instructions[r];
                                        instructions.RemoveAt(r);
                                    }

                                    if (instructionsSet != null){
                                        this.SetAIInformation(instructionsSet.aiInfo);
                                    }

                                }else if (AIReaction.ChangeBehaviour_Balanced.Equals(chosenMovement.name)){
                                    foreach (AIInstructionsSet instructionsSet in self.myInfo.aiInstructionsSet){
                                        if (instructionsSet != null && instructionsSet.behavior == AIBehavior.Balanced){
                                            this.SetAIInformation(instructionsSet.aiInfo);
                                            break;
                                        }
                                    }
                                }else if (AIReaction.ChangeBehaviour_Defensive.Equals(chosenMovement.name)){
                                    foreach (AIInstructionsSet instructionsSet in self.myInfo.aiInstructionsSet){
                                        if (instructionsSet != null && instructionsSet.behavior == AIBehavior.Defensive){
                                            this.SetAIInformation(instructionsSet.aiInfo);
                                            break;
                                        }
                                    }
                                }else if (AIReaction.ChangeBehaviour_VeryAggressive.Equals(chosenMovement.name)){
                                    foreach (AIInstructionsSet instructionsSet in self.myInfo.aiInstructionsSet){
                                        if (instructionsSet != null && instructionsSet.behavior == AIBehavior.VeryAggressive){
                                            this.SetAIInformation(instructionsSet.aiInfo);
                                            break;
                                        }
                                    }
                                }else if (AIReaction.ChangeBehaviour_VeryDefensive.Equals(chosenMovement.name)){
                                    foreach (AIInstructionsSet instructionsSet in self.myInfo.aiInstructionsSet){
                                        if (instructionsSet != null && instructionsSet.behavior == AIBehavior.VeryDefensive){
                                            this.SetAIInformation(instructionsSet.aiInfo);
                                            break;
                                        }
                                    }
                                }

                                //-------------------------------------------------------------------------------------
                                // As soon as the special case is processed,
                                // remove it from the list and choose another movement
                                //-------------------------------------------------------------------------------------
                                this.movements.Remove (chosenMovement);
                            }
                        }else{
                            break;
                        }
                    }

                    if (chosenMovement == null){
                        chosenMovement = new MovementInfo(AIReaction.Idle, this.Repeat(this.noButtonsPressed, frames), 1f);
                    }

                    return chosenMovement;
                }
            }
        }

        return null;
    }
Example #2
0
    protected virtual bool ValidateReaction(AIReactionType reactionType, ControlsScript self, ControlsScript opponent)
    {
        if (self == null || opponent == null){
            return false;
        }

        if (reactionType == AIReactionType.Idle){
            //---------------------------------------------------------------------------------------------------------
            // We can always choose to not press any key, although the character won't become idle immediately
            //---------------------------------------------------------------------------------------------------------
            return true;
        }else if (self.Physics.isTakingOff){
            //---------------------------------------------------------------------------------------------------------
            // To avoid confusions (we don't know if the character is standing or jumping)
            // the AI shouldn't take any decision if the character is taking off,
            // the AI should wait until the character is in the middle of the jump.
            //---------------------------------------------------------------------------------------------------------
            return false;
        }

        bool attackMovesLocked = UFE.config.lockMovements;
        bool basicMovesLocked = UFE.config.lockInputs && !UFE.config.roundOptions.allowMovement;
        bool isAttacking = self.currentMove != null || self.storedMove != null;
        bool isDown = (!ai.advancedOptions.reactionParameters.inputWhenDown && self.currentState == PossibleStates.Down);
        bool isStunned = (!ai.advancedOptions.reactionParameters.inputWhenStunned && self.currentSubState == SubStates.Stunned);
        bool isBlocking = (!ai.advancedOptions.reactionParameters.inputWhenBlocking && self.currentSubState == SubStates.Blocking);

        bool isJumping =
            self.currentState == PossibleStates.BackJump ||
                self.currentState == PossibleStates.ForwardJump ||
                self.currentState == PossibleStates.StraightJump;

        //bool isOpponentAttacking = opponent.currentMove != null || opponent.storedMove != null;
        bool isOpponentDown = opponent.currentState == PossibleStates.Down;
        bool isOpponentStunned = opponent.currentSubState == SubStates.Stunned;
        bool isOpponentBlocking = opponent.currentSubState == SubStates.Blocking;

        //-------------------------------------------------------------------------------------------------------------
        // Check if the character can execute the desired reaction at this moment:
        //-------------------------------------------------------------------------------------------------------------
        switch(reactionType){
        case AIReactionType.Crouch:
            //---------------------------------------------------------------------------------------------------------
            // The character can't crouch while he is jumping, stunned, down or executing a non-crouched attack.
            //---------------------------------------------------------------------------------------------------------
            return !basicMovesLocked && !isJumping && !isStunned && !isDown && !isAttacking;

        case AIReactionType.CrouchBlock:
            //---------------------------------------------------------------------------------------------------------
            // The character can't crouch-block while he is jumping, stunned, down or executing any kind of attack.
            //---------------------------------------------------------------------------------------------------------
            return
                !basicMovesLocked &&
                    !isJumping &&
                    !isStunned &&
                    !isDown &&
                    !isAttacking &&
                    !(this.ai.advancedOptions.reactionParameters.stopBlockingWhenEnemyIsStunned && isOpponentStunned);

        case AIReactionType.JumpBack:
            //---------------------------------------------------------------------------------------------------------
            // The character can't jump backwards while he is stunned or down.
            //---------------------------------------------------------------------------------------------------------
            return
                !basicMovesLocked &&
                    !isStunned &&
                    !isDown &&
                    !isAttacking &&
                    self.Physics.currentAirJumps < self.myInfo.physics.multiJumps;

        case AIReactionType.JumpBlock:
            //---------------------------------------------------------------------------------------------------------
            // The character can't jump-block if he isn't jumping or if he is stunned or down.
            //---------------------------------------------------------------------------------------------------------
            return
                UFE.config.blockOptions.allowAirBlock &&
                    !basicMovesLocked &&
                    !isStunned &&
                    !isDown &&
                    isJumping &&
                    !isAttacking &&
                    !(this.ai.advancedOptions.reactionParameters.stopBlockingWhenEnemyIsStunned && isOpponentStunned);

        case AIReactionType.JumpForward:
            //---------------------------------------------------------------------------------------------------------
            // The character can't jump forwards while he is stunned or down.
            //---------------------------------------------------------------------------------------------------------
            return
                !basicMovesLocked &&
                    !isStunned &&
                    !isDown &&
                    !isAttacking &&
                    self.Physics.currentAirJumps < self.myInfo.physics.multiJumps;

        case AIReactionType.JumpStraight:
            //---------------------------------------------------------------------------------------------------------
            // The character can't jump straight while he is stunned or down.
            // He can't jump either if he is already jumping and has reached the max number of jumps without landing.
            //---------------------------------------------------------------------------------------------------------
            return
                !basicMovesLocked &&
                    !isStunned &&
                    !isDown &&
                    !isAttacking && self.Physics.currentAirJumps < self.myInfo.physics.multiJumps;

        case AIReactionType.MoveBack:
            //---------------------------------------------------------------------------------------------------------
            // The character can't move backwards if he is jumping or if he is stunned or down.
            //---------------------------------------------------------------------------------------------------------
            return !basicMovesLocked && !isStunned && !isDown && !isJumping && !isAttacking;

        case AIReactionType.MoveForward:
            //---------------------------------------------------------------------------------------------------------
            // The character can't move forwards if he is jumping or if he is stunned or down.
            //---------------------------------------------------------------------------------------------------------
            return !basicMovesLocked && !isStunned && !isDown && !isJumping && !isAttacking;

        case AIReactionType.StandBlock:
            //---------------------------------------------------------------------------------------------------------
            // The character can't stand block if he is jumping or if he is stunned or down.
            //---------------------------------------------------------------------------------------------------------
            return
                !basicMovesLocked &&
                    !isStunned &&
                    !isDown &&
                    !isJumping &&
                    !isAttacking &&
                    !(this.ai.advancedOptions.reactionParameters.stopBlockingWhenEnemyIsStunned && isOpponentStunned);

        case AIReactionType.PlayMove:
            //---------------------------------------------------------------------------------------------------------
            // The character can't execute any "attack move" while he is stunned or down.
            //---------------------------------------------------------------------------------------------------------
            return
                !basicMovesLocked &&
                    !attackMovesLocked &&
                    !isStunned &&
                    !isDown &&
                    !isBlocking &&
                    (this.ai.advancedOptions.reactionParameters.attackWhenEnemyIsDown || !isOpponentDown) &&
                    (this.ai.advancedOptions.reactionParameters.attackWhenEnemyIsBlocking || !isOpponentBlocking);
        default:
            return true;
        }
    }
Example #3
0
    protected virtual void AddValidMoves(
		ControlsScript self, 
		ControlsScript opponent, 
		float defaultValue, 
		bool useBestAvailableMove,
		float deltaTime
		)
    {
        int oldCount = this.movements.Count;
        float weight;

        //-------------------------------------------------------------------------------------------------------------
        // Cached values (required for improving performance)
        //-------------------------------------------------------------------------------------------------------------
        float attackWeight = this.ai.advancedOptions.aggressiveness;
        float maxGaugePoints = (float)(self.myInfo.maxGaugePoints);
        //float executionTiming = self.myInfo.executionTiming;
        //int plinkingDelay = UFE.config.plinkingDelay + 1;
        //int executionTimingDelay = Mathf.FloorToInt(executionTiming / deltaTime) + 2;
        //int timeBetweenActionsDelay = Mathf.FloorToInt(this.ai.advancedOptions.timeBetweenActions / deltaTime) + 2;
        //int framesAfterAttack = Mathf.Max(plinkingDelay, executionTimingDelay, timeBetweenActionsDelay);

        float attackTypeAntiAir = 0f;
        float attackTypeBackLauncher = 0f;
        float attackTypeDive = 0f;
        float attackTypeForwardLauncher = 0f;
        float attackTypeNeutral = 0f;
        float attackTypeNormalAttack = 0f;
        float attackTypeProjectile = 0f;

        float damageVeryWeak = 0f;
        float damageWeak = 0f;
        float damageMedium = 0f;
        float damageStrong = 0f;
        float damageVeryStrong = 0f;

        float gaugeUsageNone = 0f;
        float gaugeUsageQuarter = 0f;
        float gaugeUsageHalf = 0f;
        float gaugeUsageThreeQuarters = 0f;
        float gaugeUsageAll = 0f;

        float hitConfirmTypeHit = 0f;
        float hitConfirmTypeThrow = 0f;

        float hitTypeHighKnockdown = 0f;
        float hitTypeHighLow = 0f;
        float hitTypeKnockBack = 0f;
        float hitTypeLauncher = 0f;
        float hitTypeLow = 0f;
        float hitTypeMidKnockdown = 0f;
        float hitTypeOverhead = 0f;
        float hitTypeSweep = 0f;

        float preferableDistanceVeryClose = 0f;
        float preferableDistanceClose = 0f;
        float preferableDistanceMid = 0f;
        float preferableDistanceFar = 0f;
        float preferableDistanceVeryFar = 0f;

        float recoverySpeedVeryFast = 0f;
        float recoverySpeedFast = 0f;
        float recoverySpeedNormal = 0f;
        float recoverySpeedSlow = 0f;
        float recoverySpeedVerySlow = 0f;

        float startupSpeedVeryFast = 0f;
        float startupSpeedFast = 0f;
        float startupSpeedNormal = 0f;
        float startupSpeedSlow = 0f;
        float startupSpeedVerySlow = 0f;

        if (this.ai.advancedOptions.reactionParameters.enableAttackTypeFilter){
            attackTypeAntiAir = this.aiOutput[AIReaction.PlayMove_AttackType_AntiAir];
            attackTypeBackLauncher = this.aiOutput[AIReaction.PlayMove_AttackType_BackLauncher];
            attackTypeDive = this.aiOutput[AIReaction.PlayMove_AttackType_Dive];
            attackTypeForwardLauncher = this.aiOutput[AIReaction.PlayMove_AttackType_ForwardLauncher];
            attackTypeNeutral = this.aiOutput[AIReaction.PlayMove_AttackType_Neutral];
            attackTypeNormalAttack = this.aiOutput[AIReaction.PlayMove_AttackType_NormalAttack];
            attackTypeProjectile = this.aiOutput[AIReaction.PlayMove_AttackType_Projectile];
        }

        if (ai.advancedOptions.reactionParameters.enableDamageFilter){
            damageVeryWeak = this.aiOutput[AIReaction.PlayMove_Damage_VeryWeak];
            damageWeak = this.aiOutput[AIReaction.PlayMove_Damage_Weak];
            damageMedium = this.aiOutput[AIReaction.PlayMove_Damage_Medium];
            damageStrong = this.aiOutput[AIReaction.PlayMove_Damage_Strong];
            damageVeryStrong = this.aiOutput[AIReaction.PlayMove_Damage_VeryStrong];
        }

        if (ai.advancedOptions.reactionParameters.enableGaugeFilter){
            gaugeUsageNone = this.aiOutput[AIReaction.PlayMove_GaugeUsage_None];
            gaugeUsageQuarter = this.aiOutput[AIReaction.PlayMove_GaugeUsage_Quarter];
            gaugeUsageHalf = this.aiOutput[AIReaction.PlayMove_GaugeUsage_Half];
            gaugeUsageThreeQuarters = this.aiOutput[AIReaction.PlayMove_GaugeUsage_ThreeQuarters];
            gaugeUsageAll = this.aiOutput[AIReaction.PlayMove_GaugeUsage_All];
        }

        if (ai.advancedOptions.reactionParameters.enableDistanceFilter){
            preferableDistanceVeryClose = this.aiOutput[AIReaction.PlayMove_PreferableDistance_VeryClose];
            preferableDistanceClose = this.aiOutput[AIReaction.PlayMove_PreferableDistance_Close];
            preferableDistanceMid = this.aiOutput[AIReaction.PlayMove_PreferableDistance_Mid];
            preferableDistanceFar = this.aiOutput[AIReaction.PlayMove_PreferableDistance_Far];
            preferableDistanceVeryFar = this.aiOutput[AIReaction.PlayMove_PreferableDistance_VeryFar];
        }

        if (ai.advancedOptions.reactionParameters.enableHitConfirmTypeFilter){
            hitConfirmTypeHit = this.aiOutput[AIReaction.PlayMove_HitConfirmType_Hit];
            hitConfirmTypeThrow = this.aiOutput[AIReaction.PlayMove_HitConfirmType_Throw];
        }

        if (ai.advancedOptions.reactionParameters.enableAttackSpeedFilter){
            startupSpeedVeryFast = this.aiOutput[AIReaction.PlayMove_StartupSpeed_VeryFast];
            startupSpeedFast = this.aiOutput[AIReaction.PlayMove_StartupSpeed_Fast];
            startupSpeedNormal = this.aiOutput[AIReaction.PlayMove_StartupSpeed_Normal];
            startupSpeedSlow = this.aiOutput[AIReaction.PlayMove_StartupSpeed_Slow];
            startupSpeedVerySlow = this.aiOutput[AIReaction.PlayMove_StartupSpeed_VerySlow];

            recoverySpeedVeryFast = this.aiOutput[AIReaction.PlayMove_RecoverySpeed_VeryFast];
            recoverySpeedFast = this.aiOutput[AIReaction.PlayMove_RecoverySpeed_Fast];
            recoverySpeedNormal = this.aiOutput[AIReaction.PlayMove_RecoverySpeed_Normal];
            recoverySpeedSlow = this.aiOutput[AIReaction.PlayMove_RecoverySpeed_Slow];
            recoverySpeedVerySlow = this.aiOutput[AIReaction.PlayMove_RecoverySpeed_VerySlow];
        }

        if (ai.advancedOptions.reactionParameters.enableHitTypeFilter){
            hitTypeHighKnockdown = this.aiOutput[AIReaction.PlayMove_HitType_HighKnockdown];
            hitTypeHighLow = this.aiOutput[AIReaction.PlayMove_HitType_HighLow];
            hitTypeKnockBack = this.aiOutput[AIReaction.PlayMove_HitType_KnockBack];
            hitTypeLauncher = this.aiOutput[AIReaction.PlayMove_HitType_Launcher];
            hitTypeLow = this.aiOutput[AIReaction.PlayMove_HitType_Low];
            hitTypeMidKnockdown = this.aiOutput[AIReaction.PlayMove_HitType_MidKnockdown];
            hitTypeOverhead = this.aiOutput[AIReaction.PlayMove_HitType_Overhead];
            hitTypeSweep = this.aiOutput[AIReaction.PlayMove_HitType_Sweep];
        }

        //-------------------------------------------------------------------------------------------------------------
        // Retrieve a list with the movements that can be executed at this moment.
        //-------------------------------------------------------------------------------------------------------------
        // When we decide if a movement can be executed at this moment, we should take into account (for example)
        // the current stance of the character, if the character is in the middle of a combo, the gauge usage of
        // the attack or if the character is blocking, stunned or down.
        //-------------------------------------------------------------------------------------------------------------
        int index = 0;
        for (int i = 0; i < self.myInfo.moves.Length; ++i){
            MoveSetData move = self.myInfo.moves[i];

            for (int j = 0; j < move.attackMoves.Length; ++j){
                MoveInfo moveInfo = move.attackMoves[j];

                if (moveInfo != null && self.MoveSet.ValidateMoveExecution(moveInfo)){
                    //-------------------------------------------------------------------------------------------------
                    // Now that we know the attack can be executed at this moment,
                    // we simulate the input required to execute the attack...
                    //-------------------------------------------------------------------------------------------------
                    ButtonPress? chargeButton = null;
                    int chargeFrames = 0;
                    int count;

                    // Check if it's a "charge move" or not
                    if (moveInfo.buttonSequence.Length > 0){
                        if (moveInfo.chargeMove){
                            // If it's a "charge move", check if we have already started to charge the attack
                            chargeButton = moveInfo.buttonSequence[0];
                            float charged = 0f;

                            if (chargeButton == ButtonPress.Back){
                                if (this.previousInputs[this.horizontalAxis].axisRaw < 0f){
                                    charged = this.horizontalAxis.heldDown;
                                }
                            }else if (chargeButton == ButtonPress.Foward){
                                if (this.previousInputs[this.horizontalAxis].axisRaw > 0f){
                                    charged = this.horizontalAxis.heldDown;
                                }
                            }else if (chargeButton == ButtonPress.Up){
                                if (this.previousInputs[this.verticalAxis].axisRaw > 0f){
                                    charged = this.verticalAxis.heldDown;
                                }
                            }else if (chargeButton == ButtonPress.Down){
                                if (this.previousInputs[this.verticalAxis].axisRaw < 0f){
                                    charged = this.verticalAxis.heldDown;
                                }
                            }else{
                                foreach (InputReferences input in this.inputReferences){
                                    if (input.inputType == InputType.Button && input.engineRelatedButton == chargeButton){
                                        charged = input.heldDown;
                                        break;
                                    }
                                }
                            }

                            // Calculate how many frames do we need to press the button to charge the attack
                            chargeFrames = Mathf.FloorToInt((moveInfo.chargeTiming - charged) * UFE.config.fps);
                            //chargeFrames = Mathf.FloorToInt((moveInfo.chargeTiming - charged) / deltaTime) + 1;
                        }else{
                            // TODO: if it wasn't a charge attack but we already had the first button
                            // of the sequence pressed, we could use that input to execute the movement faster.

                            // If it isn't a charge move, we enter a few empty frames before the move
                            // just to be completely sure the move is executed correctly
                            //chargeFrames = Mathf.Max(plinkingDelay, executionTimingDelay);
                        }
                    }

                    List<ButtonPress[]> sequence = new List<ButtonPress[]>();
                    if (chargeButton != null){
                        // If it's a "charge move", we need to repeat the first input for several frames
                        for (int k = 0; k < chargeFrames; ++k){
                            sequence.Add(new ButtonPress[]{chargeButton.Value});
                        }
                    }else{
                        // Otherwise, add some "empty frames" before the attack
                        for (int k = 0; k < chargeFrames; ++k){
                            sequence.Add(this.noButtonsPressed);
                        }
                    }

                    sequence.AddRange(moveInfo.simulatedInputs);

                    //-------------------------------------------------------------------------------------------------
                    // Finally, calcultate the weight associated to each valid movement...
                    //-------------------------------------------------------------------------------------------------
                    float attackTypeWeight = 0f;
                    float gaugeUsageWeight = 0f;
                    float preferableDistanceWeight = 0f;
                    float hitConfirmTypeWeight = 0f;
                    float startupSpeedWeight = 0f;
                    float recoverySpeedWeight = 0f;
                    float hitTypeWeight = 0f;
                    float damageWeight = 0f;

                    weight = 0f;
                    count = 0;

                    if (this.ai.advancedOptions.reactionParameters.enableAttackTypeFilter){
                        switch(moveInfo.moveClassification.attackType){
                        case AttackType.AntiAir:		attackTypeWeight += attackTypeAntiAir;			break;
                        case AttackType.BackLauncher:	attackTypeWeight += attackTypeBackLauncher;		break;
                        case AttackType.Dive:			attackTypeWeight += attackTypeDive;				break;
                        case AttackType.ForwardLauncher:attackTypeWeight += attackTypeForwardLauncher;	break;
                        case AttackType.Neutral:		attackTypeWeight += attackTypeNeutral;			break;
                        case AttackType.NormalAttack:	attackTypeWeight += attackTypeNormalAttack;		break;
                        case AttackType.Projectile:		attackTypeWeight += attackTypeProjectile;		break;
                        default:
                            attackTypeWeight += (
                                attackTypeAntiAir +
                                attackTypeBackLauncher +
                                attackTypeDive +
                                attackTypeForwardLauncher +
                                attackTypeNeutral +
                                attackTypeNormalAttack +
                                attackTypeProjectile
                                ) / 7f;
                            break;
                        }
                        ++count;
                    }

                    if (ai.advancedOptions.reactionParameters.enableGaugeFilter){
                        float gaugeUsage = (float)(moveInfo.gaugeUsage) / maxGaugePoints;
                        gaugeUsageWeight += gaugeVar.GetLabelMembership(RuleBasedAI.gaugeUsageNone, gaugeUsage) * gaugeUsageNone;
                        gaugeUsageWeight += gaugeVar.GetLabelMembership(RuleBasedAI.gaugeUsageQuarter, gaugeUsage) * gaugeUsageQuarter;
                        gaugeUsageWeight += gaugeVar.GetLabelMembership(RuleBasedAI.gaugeUsageHalf, gaugeUsage) * gaugeUsageHalf;
                        gaugeUsageWeight += gaugeVar.GetLabelMembership(RuleBasedAI.gaugeUsageThreeQuarters, gaugeUsage) * gaugeUsageThreeQuarters;
                        gaugeUsageWeight += gaugeVar.GetLabelMembership(RuleBasedAI.gaugeUsageAll, gaugeUsage) * gaugeUsageAll;
                        ++count;
                    }

                    if (ai.advancedOptions.reactionParameters.enableDistanceFilter){
                        switch(moveInfo.moveClassification.preferableDistance){
                        case CharacterDistance.VeryClose:	preferableDistanceWeight += preferableDistanceVeryClose;	break;
                        case CharacterDistance.Close:		preferableDistanceWeight += preferableDistanceClose;		break;
                        case CharacterDistance.Mid:			preferableDistanceWeight += preferableDistanceMid;			break;
                        case CharacterDistance.Far:			preferableDistanceWeight += preferableDistanceFar;			break;
                        case CharacterDistance.VeryFar:		preferableDistanceWeight += preferableDistanceVeryFar;		break;
                        default:
                            preferableDistanceWeight += (
                                preferableDistanceVeryClose +
                                preferableDistanceClose +
                                preferableDistanceMid +
                                preferableDistanceFar +
                                preferableDistanceVeryFar
                                ) / 5f;
                            break;
                        }
                        ++count;
                    }

                    float damage = 0f;
                    foreach(Hit hit in moveInfo.hits) damage += hit.damageOnHit;

                    if (moveInfo.hits.Length > 0){
                        if (ai.advancedOptions.reactionParameters.enableDamageFilter){
                            damage /= (float)(opponent.myInfo.lifePoints);
                            damageWeight += damageVar.GetLabelMembership(RuleBasedAI.damageVeryWeak, damage) * damageVeryWeak;
                            damageWeight += damageVar.GetLabelMembership(RuleBasedAI.damageWeak, damage) * damageWeak;
                            damageWeight += damageVar.GetLabelMembership(RuleBasedAI.damageMedium, damage) * damageMedium;
                            damageWeight += damageVar.GetLabelMembership(RuleBasedAI.damageStrong, damage) * damageStrong;
                            damageWeight += damageVar.GetLabelMembership(RuleBasedAI.damageVeryStrong, damage) * damageVeryStrong;
                            ++count;
                        }

                        if (ai.advancedOptions.reactionParameters.enableHitConfirmTypeFilter){
                            switch(moveInfo.moveClassification.hitConfirmType){
                            case HitConfirmType.Hit:	hitConfirmTypeWeight += hitConfirmTypeHit;		break;
                            case HitConfirmType.Throw:	hitConfirmTypeWeight += hitConfirmTypeThrow;	break;
                            default:
                                hitConfirmTypeWeight += (hitConfirmTypeHit + hitConfirmTypeThrow) / 2f;
                                break;
                            }
                            ++count;
                        }

                        if (ai.advancedOptions.reactionParameters.enableAttackSpeedFilter){
                            switch(moveInfo.moveClassification.startupSpeed){
                            case FrameSpeed.VeryFast:	startupSpeedWeight += startupSpeedVeryFast;	break;
                            case FrameSpeed.Fast:		startupSpeedWeight += startupSpeedFast;		break;
                            case FrameSpeed.Normal:		startupSpeedWeight += startupSpeedNormal;	break;
                            case FrameSpeed.Slow:		startupSpeedWeight += startupSpeedSlow;		break;
                            case FrameSpeed.VerySlow:	startupSpeedWeight += startupSpeedVerySlow;	break;
                            default:
                                startupSpeedWeight += (
                                    startupSpeedVeryFast +
                                    startupSpeedFast +
                                    startupSpeedNormal +
                                    startupSpeedSlow +
                                    startupSpeedVerySlow
                                    ) / 5f;
                                break;
                            }
                            ++count;

                            switch(moveInfo.moveClassification.recoverySpeed){
                            case FrameSpeed.VeryFast:	recoverySpeedWeight += recoverySpeedVeryFast;	break;
                            case FrameSpeed.Fast:		recoverySpeedWeight += recoverySpeedFast;		break;
                            case FrameSpeed.Normal:		recoverySpeedWeight += recoverySpeedNormal;		break;
                            case FrameSpeed.Slow:		recoverySpeedWeight += recoverySpeedSlow;		break;
                            case FrameSpeed.VerySlow:	recoverySpeedWeight += recoverySpeedVerySlow;	break;
                            default:
                                recoverySpeedWeight += (
                                    recoverySpeedVeryFast +
                                    recoverySpeedFast +
                                    recoverySpeedNormal +
                                    recoverySpeedSlow +
                                    recoverySpeedVerySlow
                                    ) / 5f;
                                break;
                            }
                            ++count;
                        }

                        if (ai.advancedOptions.reactionParameters.enableHitTypeFilter){
                            switch(moveInfo.moveClassification.hitType){
                            case HitType.HighKnockdown:	hitTypeWeight += hitTypeHighKnockdown;	break;
                            case HitType.Mid:		hitTypeWeight += hitTypeHighLow;		break;
                            case HitType.KnockBack:		hitTypeWeight += hitTypeKnockBack;		break;
                            case HitType.Launcher:		hitTypeWeight += hitTypeLauncher;		break;
                            case HitType.Low:			hitTypeWeight += hitTypeLow;			break;
                            case HitType.MidKnockdown:	hitTypeWeight += hitTypeMidKnockdown;	break;
                            case HitType.Overhead:		hitTypeWeight += hitTypeOverhead;		break;
                            case HitType.Sweep:			hitTypeWeight += hitTypeSweep;			break;
                            default:
                                hitTypeWeight += (
                                    hitTypeHighKnockdown +
                                    hitTypeHighLow +
                                    hitTypeKnockBack +
                                    hitTypeLauncher +
                                    hitTypeLow +
                                    hitTypeMidKnockdown +
                                    hitTypeOverhead +
                                    hitTypeSweep
                                    ) / 8f;
                                break;
                            }
                            ++count;
                        }
                    }

                    if (count > 0){
                        if (this.ai.advancedOptions.attackDesirabilityCalculation == AIAttackDesirabilityCalculation.Average){
                            weight = (
                                attackTypeWeight +
                                gaugeUsageWeight +
                                preferableDistanceWeight +
                                hitConfirmTypeWeight +
                                startupSpeedWeight +
                                recoverySpeedWeight +
                                hitTypeWeight +
                                damageWeight
                                ) / (float)(count);
                        }else if (this.ai.advancedOptions.attackDesirabilityCalculation == AIAttackDesirabilityCalculation.ClampedSum){
                            weight = Mathf.Clamp01(
                                attackTypeWeight +
                                gaugeUsageWeight +
                                preferableDistanceWeight +
                                hitConfirmTypeWeight +
                                startupSpeedWeight +
                                recoverySpeedWeight +
                                hitTypeWeight +
                                damageWeight
                                );
                        }else if (this.ai.advancedOptions.attackDesirabilityCalculation == AIAttackDesirabilityCalculation.Max){
                            weight = Mathf.Max(
                                attackTypeWeight,
                                gaugeUsageWeight,
                                preferableDistanceWeight,
                                hitConfirmTypeWeight,
                                startupSpeedWeight,
                                recoverySpeedWeight,
                                hitTypeWeight,
                                damageWeight
                                );
                        }else if (this.ai.advancedOptions.attackDesirabilityCalculation == AIAttackDesirabilityCalculation.Min){
                            weight = Mathf.Min(
                                !this.ai.advancedOptions.reactionParameters.enableAttackTypeFilter ? float.PositiveInfinity : attackTypeWeight,
                                !this.ai.advancedOptions.reactionParameters.enableGaugeFilter ? float.PositiveInfinity : gaugeUsageWeight,
                                !this.ai.advancedOptions.reactionParameters.enableDistanceFilter ? float.PositiveInfinity : preferableDistanceWeight,
                                !this.ai.advancedOptions.reactionParameters.enableHitConfirmTypeFilter ? float.PositiveInfinity : hitConfirmTypeWeight,
                                !this.ai.advancedOptions.reactionParameters.enableAttackSpeedFilter ? float.PositiveInfinity : startupSpeedWeight,
                                !this.ai.advancedOptions.reactionParameters.enableHitTypeFilter ? float.PositiveInfinity : hitTypeWeight,
                                !this.ai.advancedOptions.reactionParameters.enableDamageFilter ? float.PositiveInfinity : damageWeight
                                );
                        }
                    }

                    this.movements.Add(new MovementInfo(moveInfo.moveName, sequence.ToArray(), weight * attackWeight));
                    ++index;
                }
            }
        }

        // Check if we have found any valid movement...
        int newCount = this.movements.Count;
        if (newCount > oldCount){
            // In that case, check if we're using the "Weighted Random Selection" mode to compensate the weights of the moves...
            if (!useBestAvailableMove){
                float compensation = (float)(newCount - oldCount);

                for (int i = oldCount; i < newCount; ++i){
                    this.movements[i].weight /= compensation;
                }
            }

            // And add the possibility of executing a random move...
            if (ai.advancedOptions.playRandomMoves){
                if (this.aiOutput.TryGetValue(AIReaction.PlayMove_RandomAttack, out weight)){
                    MovementInfo randomMovement = this.movements[UnityEngine.Random.Range(oldCount, newCount)];
                    this.movements.Add(new MovementInfo("Random: " + randomMovement.name, randomMovement.simulatedInput, weight * attackWeight));
                }
            }
        }
    }
Example #4
0
    public void DoFixedUpdate()
    {
        // If both controllers aren't ready, ignore the player input
        if (!UFE.GetPlayer1Controller().isReady || !UFE.GetPlayer2Controller().isReady) return;

        // Training Mode
        if ((playerNum == 1 && UFE.gameMode == GameMode.TrainingRoom && UFE.config.trainingModeOptions.p1Life == LifeBarTrainingMode.Refill) ||
            (playerNum == 2 && UFE.gameMode == GameMode.TrainingRoom && UFE.config.trainingModeOptions.p2Life == LifeBarTrainingMode.Refill)) {
            if (!UFE.FindDelaySynchronizedAction(this.RefillLife))
                UFE.DelaySynchronizedAction(this.RefillLife, UFE.config.trainingModeOptions.refillTime);
        }

        if ((playerNum == 1 && UFE.gameMode == GameMode.TrainingRoom && UFE.config.trainingModeOptions.p1Gauge == LifeBarTrainingMode.Refill) ||
            (playerNum == 2 && UFE.gameMode == GameMode.TrainingRoom && UFE.config.trainingModeOptions.p2Gauge == LifeBarTrainingMode.Refill)) {
            if (!UFE.FindDelaySynchronizedAction(this.RefillGauge))
                UFE.DelaySynchronizedAction(this.RefillGauge, UFE.config.trainingModeOptions.refillTime);
        }

        if (UFE.gameMode == GameMode.TrainingRoom && myInfo.currentGaugePoints < myInfo.maxGaugePoints &&
            ((playerNum == 1 && UFE.config.trainingModeOptions.p1Gauge == LifeBarTrainingMode.Infinite) ||
            (playerNum == 2 && UFE.config.trainingModeOptions.p2Gauge == LifeBarTrainingMode.Infinite))) RefillGauge();

        if (UFE.gameMode == GameMode.TrainingRoom && myInfo.currentLifePoints < myInfo.lifePoints &&
            ((playerNum == 1 && UFE.config.trainingModeOptions.p1Life == LifeBarTrainingMode.Infinite) ||
            (playerNum == 2 && UFE.config.trainingModeOptions.p2Life == LifeBarTrainingMode.Infinite))) RefillLife();

        // Debugger
        if (debugger != null && UFE.config.debugOptions.debugMode){
            debugger.text = "";
            if (UFE.config.debugOptions.debugMode) {
                debugger.text += "-----Character Info-----\n";
                if (debugInfo.lifePoints) debugger.text += "Life Points: " + myInfo.currentLifePoints + "\n";
                if (debugInfo.position) debugger.text += "Position: " + transform.position + "\n";
                if (debugInfo.currentState) debugger.text += "State: " + currentState + "\n";
                if (debugInfo.currentSubState) debugger.text += "Sub State: " + currentSubState + "\n";
                if (debugInfo.stunTime && stunTime > 0) debugger.text += "Stun Time: " + stunTime + "\n";
                if (opControlsScript != null && opControlsScript.comboHits > 0) {
                    debugger.text += "Current Combo\n";
                    if (debugInfo.comboHits) debugger.text += "- Total Hits: "+ opControlsScript.comboHits + "\n";
                    if (debugInfo.comboDamage) {
                        debugger.text += "- Total Damage: " + opControlsScript.comboDamage + "\n";
                        debugger.text += "- Hit Damage: " + opControlsScript.comboHitDamage + "\n";
                    }
                }

                // Other uses
                //if (potentialParry > 0) debugger.text += "Parry Window: "+ potentialParry + "\n";
                //debugger.text += "Air Jumps: "+ myPhysicsScript.currentAirJumps + "\n";

                if (UFE.config.debugOptions.p1DebugInfo.currentMove && currentMove != null) {
                    debugger.text += "Move: "+ currentMove.name + " ("+ currentMove.currentFrame +"/"+ currentMove.totalFrames +") \n";
                    /*if (currentMove.chargeMove) {
                        debugger.text += "First Input Charge: "+ myMoveSetScript.chargeValues[currentMove.buttonSequence[0]] + "\n";
                    }*/
                    //debugger.text += "StartupFrames: "+ currentMove.moveClassification.startupSpeed +" \n";
                }
            }
            if (aiDebugger != null && debugInfo.aiWeightList) debugger.text += aiDebugger;
        }

        // Once per game
        if (opHitBoxesScript == null) {
            opControlsScript = opponent.GetComponent<ControlsScript>();
            opPhysicsScript = opponent.GetComponent<PhysicsScript>();
            opHitBoxesScript = opponent.GetComponentInChildren<HitBoxesScript>();
            opInfo = opControlsScript.myInfo;

            if (myInfo.enableAlternativeColor){
                if (gameObject.name == "Player2" && character.name == opControlsScript.character.name){  // Alternative Costume
                    Renderer[] charRenders = character.GetComponentsInChildren<Renderer>();
                    foreach(Renderer charRender in charRenders){
                        charRender.material.color = myInfo.alternativeColor;
                        //charRender.material.shader = Shader.Find("VertexLit");
                        //charRender.material.SetColor("_Emission", myInfo.alternativeColor);
                    }
                }
            }

            Renderer[] charRenderers = character.GetComponentsInChildren<Renderer>();
            List<Shader> shaderList = new List<Shader>();
            List<Color> colorList = new List<Color>();
            foreach(Renderer char_rend in charRenderers){
                //if (char_rend.material.HasProperty("color") && char_rend.material.HasProperty("shader")){
                    shaderList.Add(char_rend.material.shader);
                    colorList.Add(char_rend.material.color);
                //}
            }
            normalShaders = shaderList.ToArray();
            normalColors = colorList.ToArray();

            myMoveSetScript.PlayBasicMove(myMoveSetScript.basicMoves.idle);
        }

        // Once per round
        if ((gameObject.name == "Player1" && !introPlayed && currentMove == null) ||
            (gameObject.name == "Player2" && !introPlayed && opControlsScript.introPlayed && currentMove == null))
        {
            KillCurrentMove();
            CastMove(myMoveSetScript.intro, true, true, false);
            if (currentMove == null) {
                introPlayed = true;
                UFE.CastNewRound();
            }
        }

        // Resolve move
        resolveMove();

        // Check inputs
        translateInputs(inputController);

        // Validate rotation
        validateRotation();

        // Input Viewer
        List<InputReferences> inputList = new List<InputReferences>();
        foreach (InputReferences inputRef in inputController.inputReferences){
            if (debugger != null && UFE.config.debugOptions.debugMode && debugInfo.inputs){
                debugger.text += inputRef.inputButtonName + " - "+ inputRef.heldDown + "\n";
            }
            if (inputRef.heldDown > 0 && inputRef.heldDown <= (2f/(float)UFE.config.fps)){
                inputList.Add(inputRef);
            }
        }
        UFE.CastInput(inputList.ToArray(), playerNum);

        // Force character local position
        if (ignoreAnimationTransform && (currentMove == null || !currentMove.applyRootMotion))
            character.transform.localPosition = new Vector3(0, 0, 0);

        // Force stand state
        if (!myPhysicsScript.freeze
            && !isDead
            && currentSubState != SubStates.Stunned
            && introPlayed
            && myPhysicsScript.IsGrounded()
            && !myPhysicsScript.IsMoving()
            && currentMove == null
            && !myMoveSetScript.IsBasicMovePlaying(myMoveSetScript.basicMoves.idle)
            && !myMoveSetScript.IsAnimationPlaying("fallStraight")
            && isAxisRested(inputController)
            && !myPhysicsScript.isTakingOff
            && !myPhysicsScript.isLanding
            && !blockStunned
            && currentState != PossibleStates.Crouch
            && !isBlocking
            ){

                myMoveSetScript.PlayBasicMove(myMoveSetScript.basicMoves.idle);
                currentState = PossibleStates.Stand;
                currentSubState = SubStates.Resting;
                if (UFE.config.blockOptions.blockType == BlockType.AutoBlock
                    && myMoveSetScript.basicMoves.blockEnabled) potentialBlock = true;
        }

        if (myMoveSetScript.IsAnimationPlaying("idle")
            && !UFE.config.lockInputs
            && !UFE.config.lockMovements) {
            afkTimer += Time.fixedDeltaTime;
            if (afkTimer >= myMoveSetScript.basicMoves.idle.restingClipInterval) {
                afkTimer = 0;
                int clipNum = Mathf.RoundToInt(Random.Range(2, 6));
                if (myMoveSetScript.AnimationExists("idle_" + clipNum)) {
                    myMoveSetScript.PlayBasicMove(myMoveSetScript.basicMoves.idle, "idle_" + clipNum, false);
                }
            }
        } else {
            afkTimer = 0;
        }

        // Character colliders based on collision mass and body colliders
        normalizedDistance = Mathf.Clamp01(Vector3.Distance(opponent.transform.position, transform.position) / UFE.config.cameraOptions.maxDistance);
        if (!ignoreCollisionMass && !opControlsScript.ignoreCollisionMass) {
            float pushForce = myHitBoxesScript.TestCollision(opHitBoxesScript.hitBoxes);
            if (pushForce > 0) {
                if (transform.position.x < opponent.transform.position.x) {
                    transform.Translate(new Vector3(-.1f * pushForce, 0, 0));
                }else{
                    transform.Translate(new Vector3(.1f * pushForce, 0, 0));
                }
                if (opponent.transform.position.x == UFE.config.selectedStage.rightBoundary){
                    opponent.transform.Translate(new Vector3(-.2f * pushForce, 0, 0));
                }
            }

            pushForce = myInfo.physics.groundCollisionMass - Vector3.Distance(transform.position, opponent.transform.position);
            if (pushForce > 0) {
                if (transform.position.x < opponent.transform.position.x) {
                    transform.Translate(new Vector3(-.5f * pushForce, 0, 0));
                }else{
                    transform.Translate(new Vector3(.5f * pushForce, 0, 0));
                }
                if (opponent.transform.position.x == UFE.config.selectedStage.rightBoundary){
                    opponent.transform.Translate(new Vector3(-.2f * pushForce, 0, 0));
                }
            }
        }

        // Shake character
        if (shakeDensity > 0) {
            shakeDensity -= Time.fixedDeltaTime;
            if (myHitBoxesScript.isHit && myPhysicsScript.freeze){
                if (shakeCharacter) shake();
                if (shakeCamera) shakeCam();
            }else{
                if (UFE.config.bounceOptions.shakeCamOnBounce && myPhysicsScript.isBouncing) shakeCam();
            }
        }else if (shakeDensity < 0) {
            shakeDensity = 0;
            shakeCamera = false;
            shakeCharacter = false;
        }

        // Validate Parry
        if (potentialParry > 0){
            potentialParry -= Time.fixedDeltaTime;
            if (potentialParry <= 0) potentialParry = 0;
        }

        // Update head movement
        if (headLookScript != null && opHitBoxesScript != null)
            headLookScript.target = opHitBoxesScript.GetPosition(myInfo.headLook.target);

        // Execute Move
        if (currentMove != null) ReadMove(currentMove);

        // Apply Stun
        if ((currentSubState == SubStates.Stunned || blockStunned) && stunTime > 0 && !myPhysicsScript.freeze && !isDead)
            ApplyStun();

        // Apply Forces
        myPhysicsScript.ApplyForces(currentMove);
    }
Example #5
0
    protected virtual void RequestAIUpdate(ControlsScript self, ControlsScript opponent, float deltaTime)
    {
        if (self != null && opponent != null){
            // If both ControlsScript are defined, retrieve the current position of each character...
            Vector3 currentPositionSelf = self.transform.position;
            if (this.previousPositionSelf == null){
                this.previousPositionSelf = currentPositionSelf;
            }

            Vector3 currentPositionOpponent = opponent.transform.position;
            if (this.previousPositionOpponent == null){
                this.previousPositionOpponent = currentPositionOpponent;
            }

            // Calculate the "normalized speed" of each character...
            // (if the enemy is on the left side of the screen, multiply the speed.X by -1)
            Vector3 speedSelf = (currentPositionSelf - this.previousPositionSelf.Value) / deltaTime;
            Vector3 speedOpponent = (currentPositionOpponent - this.previousPositionOpponent.Value) / deltaTime;

            if (currentPositionOpponent.x < currentPositionSelf.x){
                speedSelf = new Vector3(-speedSelf.x, speedSelf.y, speedSelf.z);
                speedOpponent = new Vector3(-speedOpponent.x, speedOpponent.y, speedOpponent.z);
            }

            // Update the "previous position" so we can calculate the speed the next time we invoke this function
            this.previousPositionSelf = currentPositionSelf;
            this.previousPositionOpponent = currentPositionOpponent;

            //---------------------------------------------------------------------------------------------------------
            // INFERENCE SYSTEM REQUEST: ASK THE GAME ENGINE THE VALUES OF THE INPUT VARIABLES
            //---------------------------------------------------------------------------------------------------------
            // Retrieve the information of the AI-Controlled character
            float attackingSelf = (float)((int)AIBoolean.FALSE);
            float attackTypeSelf = float.MinValue;
            float attackDamageSelf = float.MinValue;
            float attackGaugeSelf = float.MinValue;
            float attackHitConfirmSelf = float.MinValue;
            float attackStartupSpeedSelf = float.MinValue;
            float attackRecoverySpeedSelf = float.MinValue;
            float attackHitTypeSelf = float.MinValue;
            float attackFrameDataSelf = float.MinValue;
            float attackPreferableDistanceSelf = float.MinValue;
            float characterBlockingSelf = (float)((int)(self.isBlocking ? AIBoolean.TRUE : AIBoolean.FALSE));
            float characterDistanceSelf = self.normalizedDistance;
            float characterDownSelf = (float)((int)(self.currentState == PossibleStates.Down ? AIBoolean.TRUE : AIBoolean.FALSE));
            float characterGaugeSelf = self.myInfo.currentGaugePoints / (float)(self.myInfo.maxGaugePoints);
            float characterHealthSelf = self.myInfo.currentLifePoints / (float)(self.myInfo.lifePoints);
            float characterHorizontalMovementSelf;
            float characterHorizontalMovementSpeedSelf;
            float characterJumpArcSelf = self.normalizedJumpArc;
            float characterStunnedSelf = (float)((int)(self.currentSubState == SubStates.Stunned ? AIBoolean.TRUE : AIBoolean.FALSE));

            float normalizedHorizontalSpeedSelf = speedSelf.x;
            if (Mathf.Approximately(normalizedHorizontalSpeedSelf, 0f)){
                characterHorizontalMovementSelf = (float)((int)AIHorizontalMovement.Still);
                characterHorizontalMovementSpeedSelf = 0f;
            }else if (normalizedHorizontalSpeedSelf > 0f){
                characterHorizontalMovementSelf = (float)((int)AIHorizontalMovement.MovingForward);
                characterHorizontalMovementSpeedSelf = normalizedHorizontalSpeedSelf;
            }else{
                characterHorizontalMovementSelf = (float)((int)AIHorizontalMovement.MovingBack);
                characterHorizontalMovementSpeedSelf = -normalizedHorizontalSpeedSelf;
            }

            float characterVerticalMovementSelf = float.MinValue;
            if (self.currentState == PossibleStates.Crouch){
                characterVerticalMovementSelf = (float)((int)AIVerticalMovement.Crouching);
            }else if(self.currentState == PossibleStates.BackJump || self.currentState == PossibleStates.StraightJump || self.currentState == PossibleStates.ForwardJump){
                characterVerticalMovementSelf = (float)((int)AIVerticalMovement.Jumping);
            }else{
                characterVerticalMovementSelf = (float)((int)AIVerticalMovement.Standing);
            }

            MoveInfo myMoveInfo = self.currentMove;
            if (myMoveInfo != null){
                attackingSelf = (float)((int)AIBoolean.TRUE);
                attackTypeSelf = (float)((int)myMoveInfo.moveClassification.attackType);
                attackGaugeSelf = (float)(myMoveInfo.gaugeUsage) / (float)(self.myInfo.maxGaugePoints);
                attackFrameDataSelf = (float)((int)myMoveInfo.currentFrameData);
                attackPreferableDistanceSelf = (float)((int)myMoveInfo.moveClassification.preferableDistance);

                attackHitConfirmSelf = (float)((int)myMoveInfo.moveClassification.hitConfirmType);
                attackStartupSpeedSelf = (float)((int)myMoveInfo.moveClassification.startupSpeed);
                attackRecoverySpeedSelf = (float)((int)myMoveInfo.moveClassification.recoverySpeed);
                attackHitTypeSelf = (float)((int)myMoveInfo.moveClassification.hitType);

                attackDamageSelf = 0f;
                foreach(Hit hit in myMoveInfo.hits) attackDamageSelf += hit.damageOnHit;
            }

            // Retrieve the information about the opponent...
            float attackingOpponent = (float)((int)AIBoolean.FALSE);
            float attackTypeOpponent = float.MinValue;
            float attackDamageOpponent = float.MinValue;
            float attackGaugeOpponent = float.MinValue;
            float attackHitConfirmOpponent = float.MinValue;
            float attackStartupSpeedOpponent = float.MinValue;
            float attackRecoverySpeedOpponent = float.MinValue;
            float attackHitTypeOpponent = float.MinValue;
            float attackFrameDataOpponent = float.MinValue;
            float attackPreferableDistanceOpponent = float.MinValue;
            float characterBlockingOpponent = (float)((int)(opponent.isBlocking ? AIBoolean.TRUE : AIBoolean.FALSE));
            float characterDistanceOpponent = opponent.normalizedDistance;
            float characterDownOpponent = (float)((int)(opponent.currentState == PossibleStates.Down ? AIBoolean.TRUE : AIBoolean.FALSE));
            float characterGaugeOpponent = opponent.myInfo.currentGaugePoints / (float)(opponent.myInfo.maxGaugePoints);
            float characterHealthOpponent = opponent.myInfo.currentLifePoints / (float)(opponent.myInfo.lifePoints);
            float characterHorizontalMovementOpponent;
            float characterHorizontalMovementSpeedOpponent;
            float characterJumpArcOpponent = opponent.normalizedJumpArc;
            float characterStunnedOpponent = (float)((int)(opponent.currentSubState == SubStates.Stunned ? AIBoolean.TRUE : AIBoolean.FALSE));

            float normalizedHorizontalSpeedOpponent = speedOpponent.x;
            if (Mathf.Approximately(normalizedHorizontalSpeedOpponent, 0f)){
                characterHorizontalMovementOpponent = (float)((int)AIHorizontalMovement.Still);
                characterHorizontalMovementSpeedOpponent = 0f;
            }else if (normalizedHorizontalSpeedOpponent > 0f){
                characterHorizontalMovementOpponent = (float)((int)AIHorizontalMovement.MovingForward);
                characterHorizontalMovementSpeedOpponent = normalizedHorizontalSpeedOpponent;
            }else{
                characterHorizontalMovementOpponent = (float)((int)AIHorizontalMovement.MovingBack);
                characterHorizontalMovementSpeedOpponent = -normalizedHorizontalSpeedOpponent;
            }

            float characterVerticalMovementOpponent = float.MinValue;
            if (opponent.currentState == PossibleStates.Crouch){
                characterVerticalMovementOpponent = (float)((int)AIVerticalMovement.Crouching);
            }else if(opponent.currentState == PossibleStates.BackJump || opponent.currentState == PossibleStates.StraightJump || opponent.currentState == PossibleStates.ForwardJump){
                characterVerticalMovementOpponent = (float)((int)AIVerticalMovement.Jumping);
            }else{
                characterVerticalMovementOpponent = (float)((int)AIVerticalMovement.Standing);
            }

            MoveInfo opMoveInfo = opponent.currentMove;
            if (opMoveInfo != null){
                attackingOpponent = (float)((int)AIBoolean.TRUE);
                attackTypeOpponent = (float)((int)opMoveInfo.moveClassification.attackType);
                attackGaugeOpponent = (float)(opMoveInfo.gaugeUsage) / (float)(opponent.myInfo.maxGaugePoints);
                attackFrameDataOpponent = (float)((int)opMoveInfo.currentFrameData);
                attackPreferableDistanceOpponent =  (float)((int)opMoveInfo.moveClassification.preferableDistance);

                attackHitConfirmOpponent = (float)((int)opMoveInfo.moveClassification.hitConfirmType);
                attackStartupSpeedOpponent = (float)((int)opMoveInfo.moveClassification.startupSpeed);
                attackRecoverySpeedOpponent = (float)((int)opMoveInfo.moveClassification.recoverySpeed);
                attackHitTypeOpponent = (float)((int)opMoveInfo.moveClassification.hitType);

                attackDamageOpponent = 0f;
                foreach(Hit hit in opMoveInfo.hits) attackDamageOpponent += hit.damageOnHit;
            }

            //---------------------------------------------------------------------------------------------------------
            // INFERENCE SYSTEM REQUEST: SEND THE INFORMATION OF THE ENGINE TO THE INFERENCE ENGINE
            //---------------------------------------------------------------------------------------------------------
            this.inferenceEngine.SetInput(AICondition.Attacking_Self, attackingSelf);
            this.inferenceEngine.SetInput(AICondition.Attacking_AttackType_Self, attackTypeSelf);
            this.inferenceEngine.SetInput(AICondition.Attacking_Damage_Self, attackDamageSelf);
            this.inferenceEngine.SetInput(AICondition.Attacking_GaugeUsage_Self, attackGaugeSelf);
            this.inferenceEngine.SetInput(AICondition.Attacking_HitConfirmType_Self, attackHitConfirmSelf);
            this.inferenceEngine.SetInput(AICondition.Attacking_StartupSpeed_Self, attackStartupSpeedSelf);
            this.inferenceEngine.SetInput(AICondition.Attacking_RecoverySpeed_Self, attackRecoverySpeedSelf);
            this.inferenceEngine.SetInput(AICondition.Attacking_HitType_Self, attackHitTypeSelf);
            this.inferenceEngine.SetInput(AICondition.Attacking_FrameData_Self, attackFrameDataSelf);
            this.inferenceEngine.SetInput(AICondition.Attacking_PreferableDistance_Self, attackPreferableDistanceSelf);
            this.inferenceEngine.SetInput(AICondition.Blocking_Self, characterBlockingSelf);
            this.inferenceEngine.SetInput(AICondition.Distance_Self, characterDistanceSelf);
            this.inferenceEngine.SetInput(AICondition.Down_Self, characterDownSelf);
            this.inferenceEngine.SetInput(AICondition.Gauge_Self, characterGaugeSelf);
            this.inferenceEngine.SetInput(AICondition.Health_Self, characterHealthSelf);
            this.inferenceEngine.SetInput(AICondition.HorizontalMovement_Self, characterHorizontalMovementSelf);
            this.inferenceEngine.SetInput(AICondition.HorizontalMovementSpeed_Self, characterHorizontalMovementSpeedSelf);
            this.inferenceEngine.SetInput(AICondition.JumpArc_Self, characterJumpArcSelf);
            this.inferenceEngine.SetInput(AICondition.Stunned_Self, characterStunnedSelf);
            this.inferenceEngine.SetInput(AICondition.VerticalMovement_Self, characterVerticalMovementSelf);

            this.inferenceEngine.SetInput(AICondition.Attacking_Opponent, attackingOpponent);
            this.inferenceEngine.SetInput(AICondition.Attacking_AttackType_Opponent, attackTypeOpponent);
            this.inferenceEngine.SetInput(AICondition.Attacking_Damage_Opponent, attackDamageOpponent);
            this.inferenceEngine.SetInput(AICondition.Attacking_GaugeUsage_Opponent, attackGaugeOpponent);
            this.inferenceEngine.SetInput(AICondition.Attacking_HitConfirmType_Opponent, attackHitConfirmOpponent);
            this.inferenceEngine.SetInput(AICondition.Attacking_StartupSpeed_Opponent, attackStartupSpeedOpponent);
            this.inferenceEngine.SetInput(AICondition.Attacking_RecoverySpeed_Opponent, attackRecoverySpeedOpponent);
            this.inferenceEngine.SetInput(AICondition.Attacking_HitType_Opponent, attackHitTypeOpponent);
            this.inferenceEngine.SetInput(AICondition.Attacking_FrameData_Opponent, attackFrameDataOpponent);
            this.inferenceEngine.SetInput(AICondition.Attacking_PreferableDistance_Opponent, attackPreferableDistanceOpponent);
            this.inferenceEngine.SetInput(AICondition.Blocking_Opponent, characterBlockingOpponent);
            this.inferenceEngine.SetInput(AICondition.Distance_Opponent, characterDistanceOpponent);
            this.inferenceEngine.SetInput(AICondition.Down_Opponent, characterDownOpponent);
            this.inferenceEngine.SetInput(AICondition.Gauge_Opponent, characterGaugeOpponent);
            this.inferenceEngine.SetInput(AICondition.Health_Opponent, characterHealthOpponent);
            this.inferenceEngine.SetInput(AICondition.HorizontalMovement_Opponent, characterHorizontalMovementOpponent);
            this.inferenceEngine.SetInput(AICondition.HorizontalMovementSpeed_Opponent, characterHorizontalMovementSpeedOpponent);
            this.inferenceEngine.SetInput(AICondition.JumpArc_Opponent, characterJumpArcOpponent);
            this.inferenceEngine.SetInput(AICondition.Stunned_Opponent, characterStunnedOpponent);
            this.inferenceEngine.SetInput(AICondition.VerticalMovement_Opponent, characterVerticalMovementOpponent);

            //---------------------------------------------------------------------------------------------------------
            // INFERENCE SYSTEM REQUEST: CHECK WHICH OF THE POSSIBLE REACTIONS ARE PHISICALLY POSSIBLE AT THIS MOMENT
            //---------------------------------------------------------------------------------------------------------
            HashSet<string> requestedOutputs = new HashSet<string>();
            if (this.ValidateReaction(AIReactionType.Crouch, self, opponent)){
                requestedOutputs.Add(AIReaction.Crouch);
            }
            if (this.ValidateReaction(AIReactionType.CrouchBlock, self, opponent)){
                requestedOutputs.Add(AIReaction.CrouchBlock);
            }
            if (this.ValidateReaction(AIReactionType.Idle, self, opponent)){
                requestedOutputs.Add(AIReaction.Idle);
            }
            if (this.ValidateReaction(AIReactionType.JumpBack, self, opponent)){
                requestedOutputs.Add(AIReaction.JumpBackward);
            }
            if (this.ValidateReaction(AIReactionType.JumpBlock, self, opponent)){
                requestedOutputs.Add(AIReaction.JumpBlock);
            }
            if (this.ValidateReaction(AIReactionType.JumpForward, self, opponent)){
                requestedOutputs.Add(AIReaction.JumpForward);
            }
            if (this.ValidateReaction(AIReactionType.JumpStraight, self, opponent)){
                requestedOutputs.Add(AIReaction.JumpStraight);
            }
            if (this.ValidateReaction(AIReactionType.MoveBack, self, opponent)){
                requestedOutputs.Add(AIReaction.MoveBackward);
            }
            if (this.ValidateReaction(AIReactionType.MoveForward, self, opponent)){
                requestedOutputs.Add(AIReaction.MoveForward);
            }
            if (this.ValidateReaction(AIReactionType.StandBlock, self, opponent)){
                requestedOutputs.Add(AIReaction.StandBlock);
            }
            if (this.ValidateReaction(AIReactionType.PlayMove, self, opponent)){
                requestedOutputs.Add(AIReaction.PlayMove_RandomAttack);

                if (ai.advancedOptions.reactionParameters.enableAttackTypeFilter){
                    requestedOutputs.Add(AIReaction.PlayMove_AttackType_AntiAir);
                    requestedOutputs.Add(AIReaction.PlayMove_AttackType_BackLauncher);
                    requestedOutputs.Add(AIReaction.PlayMove_AttackType_Dive);
                    requestedOutputs.Add(AIReaction.PlayMove_AttackType_ForwardLauncher);
                    requestedOutputs.Add(AIReaction.PlayMove_AttackType_Neutral);
                    requestedOutputs.Add(AIReaction.PlayMove_AttackType_NormalAttack);
                    requestedOutputs.Add(AIReaction.PlayMove_AttackType_Projectile);
                }

                if (ai.advancedOptions.reactionParameters.enableDamageFilter){
                    requestedOutputs.Add(AIReaction.PlayMove_Damage_Medium);
                    requestedOutputs.Add(AIReaction.PlayMove_Damage_Strong);
                    requestedOutputs.Add(AIReaction.PlayMove_Damage_VeryStrong);
                    requestedOutputs.Add(AIReaction.PlayMove_Damage_VeryWeak);
                    requestedOutputs.Add(AIReaction.PlayMove_Damage_Weak);
                }

                if (ai.advancedOptions.reactionParameters.enableGaugeFilter){
                    requestedOutputs.Add(AIReaction.PlayMove_GaugeUsage_All);
                    requestedOutputs.Add(AIReaction.PlayMove_GaugeUsage_Half);
                    requestedOutputs.Add(AIReaction.PlayMove_GaugeUsage_None);
                    requestedOutputs.Add(AIReaction.PlayMove_GaugeUsage_Quarter);
                    requestedOutputs.Add(AIReaction.PlayMove_GaugeUsage_ThreeQuarters);
                }

                if (ai.advancedOptions.reactionParameters.enableHitConfirmTypeFilter){
                    requestedOutputs.Add(AIReaction.PlayMove_HitConfirmType_Hit);
                    requestedOutputs.Add(AIReaction.PlayMove_HitConfirmType_Throw);
                }

                if (ai.advancedOptions.reactionParameters.enableAttackSpeedFilter){
                    requestedOutputs.Add(AIReaction.PlayMove_StartupSpeed_VeryFast);
                    requestedOutputs.Add(AIReaction.PlayMove_StartupSpeed_Fast);
                    requestedOutputs.Add(AIReaction.PlayMove_StartupSpeed_Normal);
                    requestedOutputs.Add(AIReaction.PlayMove_StartupSpeed_Slow);
                    requestedOutputs.Add(AIReaction.PlayMove_StartupSpeed_VerySlow);

                    requestedOutputs.Add(AIReaction.PlayMove_RecoverySpeed_VeryFast);
                    requestedOutputs.Add(AIReaction.PlayMove_RecoverySpeed_Fast);
                    requestedOutputs.Add(AIReaction.PlayMove_RecoverySpeed_Normal);
                    requestedOutputs.Add(AIReaction.PlayMove_RecoverySpeed_Slow);
                    requestedOutputs.Add(AIReaction.PlayMove_RecoverySpeed_VerySlow);
                }

                if (ai.advancedOptions.reactionParameters.enableHitTypeFilter){
                    requestedOutputs.Add(AIReaction.PlayMove_HitType_HighKnockdown);
                    requestedOutputs.Add(AIReaction.PlayMove_HitType_HighLow);
                    requestedOutputs.Add(AIReaction.PlayMove_HitType_KnockBack);
                    requestedOutputs.Add(AIReaction.PlayMove_HitType_Launcher);
                    requestedOutputs.Add(AIReaction.PlayMove_HitType_Low);
                    requestedOutputs.Add(AIReaction.PlayMove_HitType_MidKnockdown);
                    requestedOutputs.Add(AIReaction.PlayMove_HitType_Overhead);
                    requestedOutputs.Add(AIReaction.PlayMove_HitType_Sweep);
                }

                if (ai.advancedOptions.reactionParameters.enableDistanceFilter){
                    requestedOutputs.Add(AIReaction.PlayMove_PreferableDistance_Close);
                    requestedOutputs.Add(AIReaction.PlayMove_PreferableDistance_Far);
                    requestedOutputs.Add(AIReaction.PlayMove_PreferableDistance_Mid);
                    requestedOutputs.Add(AIReaction.PlayMove_PreferableDistance_VeryClose);
                    requestedOutputs.Add(AIReaction.PlayMove_PreferableDistance_VeryFar);
                }
            }

            //---------------------------------------------------------------------------------------------------------
            // INFERENCE SYSTEM REQUEST: THE "CHANGE BEHAVIOUR" REACTIONS ARE ALWASY POSSIBLE
            //---------------------------------------------------------------------------------------------------------
            requestedOutputs.Add(AIReaction.ChangeBehaviour_Aggressive);
            requestedOutputs.Add(AIReaction.ChangeBehaviour_Any);
            requestedOutputs.Add(AIReaction.ChangeBehaviour_Balanced);
            requestedOutputs.Add(AIReaction.ChangeBehaviour_Defensive);
            requestedOutputs.Add(AIReaction.ChangeBehaviour_VeryAggressive);
            requestedOutputs.Add(AIReaction.ChangeBehaviour_VeryDefensive);

            //---------------------------------------------------------------------------------------------------------
            // INFERENCE SYSTEM REQUEST: FINALLY, MAKE THE REQUEST TO THE INFERENCE SYSTEM
            //---------------------------------------------------------------------------------------------------------
            if (UFE.config.aiOptions.multiCoreSupport){
                this.inferenceEngine.AsyncCalculateOutputs(requestedOutputs);
            }else{
                this.inferenceEngine.SyncCalculateOutputs(requestedOutputs);
                this.aiOutput = this.inferenceEngine.Output;
            }
        }
    }
Example #6
0
    void Start()
    {
        controlsScript = transform.parent.gameObject.GetComponent<ControlsScript>();
        myMoveSetScript = GetComponent<MoveSetScript>();
        UpdateRenderer();

        foreach(MoveInfo move in myMoveSetScript.moves){
            foreach(InvincibleBodyParts invBodyPart in move.invincibleBodyParts){
                List<HitBox> invHitBoxes = new List<HitBox>();
                foreach(BodyPart bodyPart in invBodyPart.bodyParts){
                    foreach(HitBox hitBox in hitBoxes){
                        if (bodyPart == hitBox.bodyPart) {
                            invHitBoxes.Add(hitBox);
                            break;
                        }
                    }
                }
                invBodyPart.hitBoxes = invHitBoxes.ToArray();
            }
        }
    }
    protected virtual string SetStringValues(string msg, ControlsScript controlsScript)
    {
        CharacterInfo character = controlsScript != null ? controlsScript.myInfo : null;
        if (controlsScript != null) msg = msg.Replace("%combo%", controlsScript.opControlsScript.comboHits.ToString());
        if (character != null)		msg = msg.Replace("%character%", character.characterName);
        msg = msg.Replace("%round%", UFE.config.currentRound.ToString());

        return msg;
    }
    protected virtual string ProcessMessage(string msg, ControlsScript controlsScript)
    {
        if (msg == UFE.config.selectedLanguage.combo){
            if (this.announcer != null && !this.muteAnnouncer){
                foreach(ComboAnnouncer comboAnnouncer in this.announcer.combos){
                    if (controlsScript.opControlsScript.comboHits >= comboAnnouncer.hits){
                        UFE.PlaySound(comboAnnouncer.audio);
                        break;
                    }
                }
            }
        }else if (msg == UFE.config.selectedLanguage.parry){
            if (this.announcer != null && !this.muteAnnouncer){
                UFE.PlaySound(this.announcer.parry);
            }
            UFE.PlaySound(UFE.config.blockOptions.parrySound);
        }else if (msg == UFE.config.selectedLanguage.counterHit){
            if (this.announcer != null && !this.muteAnnouncer){
                UFE.PlaySound(this.announcer.counterHit);
            }
            UFE.PlaySound(UFE.config.counterHitOptions.sound);
        }else if (msg == UFE.config.selectedLanguage.firstHit){
            if (this.announcer != null && !this.muteAnnouncer){
                UFE.PlaySound(this.announcer.firstHit);
            }
        }else{
            return this.SetStringValues(msg, null);
        }

        return this.SetStringValues(msg, controlsScript);
    }
Example #9
0
    private static void _StartGame(float fadeTime)
    {
        CameraFade.StartAlphaFade(Color.black, true, fadeTime);

        UFE.EndGame();
        UFE.HideScreen(UFE.currentScreen);
        if (UFE.config.gameGUI.battleGUI == null){
            Debug.LogError("Battle GUI not found! Make sure you have set the prefab correctly in the Global Editor");
            UFE.battleGUI = new GameObject("BattleGUI").AddComponent<UFEScreen>();
        }else{
            UFE.battleGUI = (UFEScreen) GameObject.Instantiate(UFE.config.gameGUI.battleGUI);
        }
        UFE.battleGUI.transform.SetParent(UFE.canvas != null ? UFE.canvas.transform : null, false);
        UFE.battleGUI.OnShow();
        UFE.canvasGroup.alpha = 0;

        gameEngine = new GameObject("Game");
        UFE.cameraScript = gameEngine.AddComponent<CameraScript>();

        if (UFE.config.player1Character == null){
            Debug.LogError("No character selected for player 1.");
            return;
        }
        if (UFE.config.player2Character == null){
            Debug.LogError("No character selected for player 2.");
            return;
        }
        if (UFE.config.selectedStage == null){
            Debug.LogError("No stage selected.");
            return;
        }

        if (UFE.config.aiOptions.engine == AIEngine.FuzzyAI){
            UFE.SetFuzzyAI(1, UFE.config.player1Character);
            UFE.SetFuzzyAI(2, UFE.config.player2Character);
        }

        UFE.config.player1Character.currentLifePoints = (float)UFE.config.player1Character.lifePoints;
        UFE.config.player2Character.currentLifePoints = (float)UFE.config.player2Character.lifePoints;
        UFE.config.player1Character.currentGaugePoints = 0;
        UFE.config.player2Character.currentGaugePoints = 0;

        if (UFE.config.selectedStage.prefab == null){
            Debug.LogError("Stage prefab not found! Make sure you have set the prefab correctly in the Global Editor");
        }
        GameObject stageInstance = (GameObject) Instantiate(config.selectedStage.prefab);

        stageInstance.transform.parent = gameEngine.transform;
        UFE.config.currentRound = 1;
        UFE.config.lockInputs = true;
        UFE.SetTimer(config.roundOptions.timer);
        UFE.PauseTimer();

        GameObject p1 = new GameObject("Player1");
        p1.transform.parent = gameEngine.transform;
        p1ControlsScript = p1.AddComponent<ControlsScript>();
        p1.AddComponent<PhysicsScript>();

        GameObject p2 = new GameObject("Player2");
        p2.transform.parent = gameEngine.transform;
        p2ControlsScript = p2.AddComponent<ControlsScript>();
        p2.AddComponent<PhysicsScript>();

        //Preload
        if (UFE.config.preloadHitEffects) {
            SearchAndCastGameObject(UFE.config.hitOptions);
            if (UFE.config.debugOptions.preloadedObjects) Debug.Log("Hit Effects Loaded");
        }
        if (UFE.config.preloadStage) {
            SearchAndCastGameObject(UFE.config.selectedStage);
            if (UFE.config.debugOptions.preloadedObjects) Debug.Log("Stage Loaded");
        }
        if (UFE.config.preloadCharacter1) {
            SearchAndCastGameObject(UFE.config.player1Character);
            if (UFE.config.debugOptions.preloadedObjects) Debug.Log("Character 1 Loaded");
        }
        if (UFE.config.preloadCharacter2) {
            SearchAndCastGameObject(UFE.config.player2Character);
            if (UFE.config.debugOptions.preloadedObjects) Debug.Log("Character 2 Loaded");
        }
        if (UFE.config.warmAllShaders) Shader.WarmupAllShaders();

        memoryDump.Clear();
    }
Example #10
0
    public void Start()
    {
        /*Plane groundPlane = (Plane) GameObject.FindObjectOfType(typeof(Plane));
        if (groundPlane == null) Debug.LogError("Plane not found. Please add a plane mesh to your stage prefab!");*/

        groundLayer = LayerMask.NameToLayer("Ground");
          		groundMask = 1 << groundLayer;
        myControlsScript = GetComponent<ControlsScript>();
        character = myControlsScript.character;
        myHitBoxesScript = character.GetComponent<HitBoxesScript>();
        myMoveSetScript = character.GetComponent<MoveSetScript>();
        appliedGravity = myControlsScript.myInfo.physics.weight * UFE.config.gravity;
    }