//switch (stateMachine.state)
        //{

        //    //PlayerState
        //    case State.channeling:
        //        channel.CheckChannel();
        //        Targetting(selectedAbility);
        //        if (!channel.isChanneling)
        //        {
        //            state = State.animating;
        //        }
        //        break;

        //    //PlayerState
        //    case State.animating:

        //        print(attackInProgress);

        //        if (!attackInProgress)
        //        {
        //            AIController[] enemies = FindObjectsOfType<AIController>();
        //            foreach(AIController enemy in enemies)
        //            {
        //                if (enemy.attackInProgress == true && enemy.gameObject!= this.gameObject)
        //                {
        //                    return;
        //                }
        //            }
        //            attackInProgress = true;
        //            PerformAttack(selectedAbility);
        //        }

        //foreach (Cell cell in attackIndicator.convertedCells)
        //{
        //    cell.enemyHighlight = false;
        //    attackIndicator.areCellsColored = false;
        //    cell.DoDefaultColor();
        //    enemyTarget.SaveMaterial();
        //    enemyTarget.DoDefaultMaterial();
        //}
        //            break;
        //    }
        //}


        /* GOALS WITHIN THIS CODE
         * 1. Segment out a combat controller utilized public method pool. This pool will handle calculations that are universal such as zodiac and magic interactions
         * 2. AIController should handle the decisions of the AI. Namely, seeing which abilities are available to it. Checking to see which ones are best. and picking between them.
         * 3. An Attack Executor (should be shared with FIGHTER class) Class should handle distributing damage and effects. It will use the singleton, Combat Controller, to access universal algorithms in calculating damage.
         * 4. Animation needs to be accounted for with a separate timer. The timer will tick normally when not moving or pushing else it will wait for moving or pushing to complete then issue the same "END OF ANIMATION" method.
         * 5. AIController should resemble a player brain. Any limitations of the enemy class not related to decision making should be relegated to another class.
         * 6. NEW CLASSES: CC.AttackAlgorithms, AnimationTimer, AttackExecutor, AttackReceiver, PlayerState
         */


        //Pre targeting for relative global and support targeting
        //dont think this needed.

        private List <AttackReceiver> GetTargets(EnemyAttack ability, EnemyTarget enemy)
        {
            allPushables = FindObjectsOfType <Pushable>();
            List <AttackReceiver> newTargets           = new List <AttackReceiver>();
            List <Pushable>       translatedTargetList = new List <Pushable>();

            switch (ability.targettingClass)
            {
            case TargettingClass.global:

                foreach (Pushable pushable in allPushables)
                {
                    foreach (Vector2Int position in ability.globalTargetCells)
                    {
                        if (pushable.GetComponent <Mover>().GetGridPos() == position)
                        {
                            translatedTargetList.Add(pushable);
                        }
                    }
                }

                //remove targets based on beeline targeting
                if (ability.attackTarget == AttackTarget.beeline)
                {
                    switch (enemyTarget.wing)
                    {
                    case Wing.bow:
                        translatedTargetList.Sort(SortByY);
                        translatedTargetList.Reverse();
                        break;

                    case Wing.port:
                        translatedTargetList.Sort(SortByX);
                        break;

                    case Wing.starboard:
                        translatedTargetList.Sort(SortByX);
                        translatedTargetList.Reverse();
                        break;

                    default:
                        print("NO WING DEFINED");
                        break;
                    }
                }

                //final list
                foreach (Pushable pushable in translatedTargetList)
                {
                    if (pushable.GetComponent <AttackReceiver>() != null)
                    {
                        newTargets.Add(pushable.GetComponent <AttackReceiver>());
                    }

                    if (ability.attackTarget == AttackTarget.beeline)
                    {
                        break;
                    }
                }


                break;

            case TargettingClass.relative:

                Vector2Int[] translatedTargetCells = TranslateRelativeTargetCells(ability.relativeTargetCells, enemy);

                //print("allPushables count: " + allPushables.Length);

                foreach (Pushable pushable in allPushables)
                {
                    foreach (Vector2Int position in translatedTargetCells)
                    {
                        if (pushable.GetComponent <Mover>().GetGridPos() == position)
                        {
                            translatedTargetList.Add(pushable);
                            //print("adding pushable");
                        }
                    }
                }

                //print("translatedTargetCells: " + translatedTargetList.Count);

                //remove targets based on beeline targeting
                if (ability.attackTarget == AttackTarget.beeline)
                {
                    switch (enemyTarget.wing)
                    {
                    case Wing.bow:
                        translatedTargetList.Sort(SortByY);
                        translatedTargetList.Reverse();
                        break;

                    case Wing.port:
                        translatedTargetList.Sort(SortByX);
                        break;

                    case Wing.starboard:
                        translatedTargetList.Sort(SortByX);
                        translatedTargetList.Reverse();
                        break;

                    default:
                        print("NO WING DEFINED");
                        break;
                    }
                }

                //final list
                foreach (Pushable pushable in translatedTargetList)
                {
                    if (pushable.GetComponent <AttackReceiver>() != null)
                    {
                        newTargets.Add(pushable.GetComponent <AttackReceiver>());
                    }

                    if (pushable.GetComponent <Destroyable>() != null)
                    {
                        pushable.GetComponent <Destroyable>().DestroySelf();
                    }

                    if (ability.attackTarget == AttackTarget.beeline)
                    {
                        break;
                    }
                }

                break;

            case TargettingClass.support:

                EnemyTarget randomEnemy = SelectRandomSupportTarget();

                newTargets.Add(randomEnemy.GetComponent <AttackReceiver>());
                break;

            case TargettingClass.self:

                newTargets.Add(attackReceiver);
                break;

            //this case inherits "melee Target" from the TestAbility method. This is to reduce redundancy in finding available targets.
            case TargettingClass.melee:

                if (meleeTarget == null)
                {
                    print("no melee targets, ATTACK FILTERING ERROR");
                }

                newTargets.Add(meleeTarget.GetComponent <AttackReceiver>());

                break;

            case TargettingClass.homing:

                Fighter randomActor = SelectRandomHomingTarget();

                if (randomActor != null)
                {
                    newTargets.Add(randomActor.GetComponent <AttackReceiver>());
                }

                break;

            case TargettingClass.allAllies:

                foreach (Fighter fighter in allActors)
                {
                    if (!fighter.isDead)
                    {
                        if (!fighter.isIntangible)
                        {
                            newTargets.Add(fighter.GetComponent <AttackReceiver>());
                        }
                    }
                }

                break;

            case TargettingClass.allFoes:

                foreach (EnemyTarget target in allEnemies)
                {
                    newTargets.Add(target.GetComponent <AttackReceiver>());
                }

                break;

            default:
                print("no valid targeting class error.");
                break;
            }

            return(newTargets);
        }
Beispiel #2
0
 //CC.AA
 public static int SortByY(Fighter actor1, Fighter actor2)
 {
     return(actor1.GetComponent <Mover>().GetGridPos().y.CompareTo(actor2.GetComponent <Mover>().GetGridPos().y));
 }
        //tests to see if ability can be used in given context
        private bool TestAbility(EnemyAttack selectedAbility)
        {
            if (selectedAbility.targettingClass == TargettingClass.melee)
            {
                Vector2Int[] directions = { Vector2Int.up, Vector2Int.down, Vector2Int.right, Vector2Int.left };

                foreach (Fighter fighter in allActors)
                {
                    foreach (Vector2Int direction in directions)
                    {
                        if (fighter.GetComponent <Mover>().GetGridPos() + direction == mover.GetGridPos())
                        {
                            if (!fighter.isDead && !fighter.isIntangible)
                            {
                                meleeTarget = fighter;
                                return(true);
                            }
                        }
                    }
                }

                return(false);
            }

            if (selectedAbility.targettingClass == TargettingClass.support)
            {
                if (allEnemies.Length <= 1)
                {
                    return(false);
                }
            }

            if (selectedAbility.usesRails)
            {
                if (selectedAbility.targettingClass == TargettingClass.global)
                {
                    if (combatController.ListOfcells[selectedAbility.LandingCell].isOccupied)
                    {
                        return(false);
                    }
                }

                if (selectedAbility.targettingClass == TargettingClass.relative)
                {
                    Vector2Int[] targetCells = { selectedAbility.LandingCell };

                    if (combatController.ListOfcells[TranslateRelativeTargetCells(targetCells, enemyTarget)[0]].isOccupied)
                    {
                        return(false);
                    }
                }
            }

            if (selectedAbility.RequiredCells.Length > 0)
            {
                bool matchFound = false;

                foreach (Vector2Int coord in selectedAbility.RequiredCells)
                {
                    if (mover.GetGridPos() == coord)
                    {
                        matchFound = true;
                    }
                }

                if (!matchFound)
                {
                    return(false);
                }
            }

            if (selectedAbility.RequiredWing != Wing.none)
            {
                if (enemyTarget.wing != selectedAbility.RequiredWing)
                {
                    return(false);
                }
            }

            return(true);
        }