public static IEnumerator StandardAttack(AIBlackboard blackboard, ComponentBlackboard components)
        {
            blackboard.Waiting = true;
            Transform         aiTransform     = components.aiObject.transform;
            Transform         playerTransform = blackboard.player.transform;
            MecanimLocomotion locomotion      = components.locomotion;
            NavMeshAgent      navigation      = components.navigation;

            locomotion.move  = false;
            locomotion.speed = 3;
            components.StopNavigating();

            while (true)
            {
                float moveTime = Time.time + Mathf.Max(2f, Random.Range(1, 8));
                locomotion.move = false;

                while (moveTime > Time.time)//stand time
                {
                    if (blackboard.distanceToPlayer > 6 || !blackboard.CanSeePlayer)
                    {
                        if (blackboard.CanSeePlayer)
                        {
                            locomotion.move          = false;
                            locomotion.moveDirection = Vector3.zero;
                            locomotion.turn          = true;
                            locomotion.lookDirection = playerTransform.position - aiTransform.position;
                            components.ShootPlayer();
                            components.AimAtPlayer(playerTransform);
                        }
                        else
                        {
                            locomotion.turn = false;
                            components.StopShootingPlayer();
                        }
                        components.StopNavigating();
                    }
                    else
                    {
                        Vector3 backUp = locomotion.transform.position - playerTransform.position * 5;
                        backUp.y = locomotion.transform.position.y;

                        locomotion.move            = true;
                        locomotion.turn            = true;
                        locomotion.lookWhereMoving = false;

                        locomotion.lookDirection = playerTransform.position - aiTransform.position;
                        components.ShootPlayer();
                        components.AimAtPlayer(playerTransform);
                        components.Navigate();

                        navigation.SetDestination(backUp);
                    }


                    yield return(null);
                }

                CoverPoint originalCover = (Random.Range(0, 10) > 3)? blackboard.BestAntiCover : blackboard.BestCover;

                if (originalCover != null)
                {
                    locomotion.move = true;
                    navigation.SetDestination(originalCover.transform.position);

                    moveTime = Time.time + Mathf.Max(1, Random.Range(2, 6));


                    bool coverValid = (originalCover.GetInstanceID() == blackboard.BestAntiCover.GetInstanceID() || originalCover.GetInstanceID() == blackboard.BestCover.GetInstanceID() || Time.time < moveTime);

                    locomotion.turn            = true;
                    locomotion.lookWhereMoving = false;

                    while (coverValid && Vector3.Distance(originalCover.transform.position, aiTransform.position) > 2)
                    {
                        components.Navigate();
                        if (blackboard.LineOfSight)
                        {
                            locomotion.lookDirection = playerTransform.position - aiTransform.position;
                            components.ShootPlayer();
                            components.AimAtPlayer(playerTransform);
                        }
                        else
                        {
                            components.StopShootingPlayer();
                        }
                        yield return(null);
                    }
                }
                else
                {
                    locomotion.turn            = false;
                    locomotion.lookWhereMoving = true;
                    locomotion.move            = true;
                    components.StopShootingPlayer();
                    while (Vector3.Distance(playerTransform.position, aiTransform.position) > blackboard.AttackRange || !blackboard.CanSeePlayer)
                    {
                        if (blackboard.CanSeePlayer)
                        {
                            components.AimAtPlayer(playerTransform);
                            components.ShootPlayer();
                        }
                        else
                        {
                            components.StopShootingPlayer();
                        }

                        navigation.SetDestination(playerTransform.position);
                        components.Navigate();
                        yield return(null);
                    }
                }
            }
        }
        IEnumerator UpdateCover()
        {
            AIController[] aiCover     = AISquad.ToArray();
            AIController[] aiAnticover = aiCover;
            yield return(null);

            int coverPointer     = 0;
            int anticoverPointer = 0;

            for (int x = 0; x < coverPoints.Length; ++x)
            {
                CoverPoint c = coverPoints[x];
                c.TraceToPlayer();
                yield return(new WaitForSeconds(coverUpdateDelayTime));

                Vector3 pos       = c.transform.position;
                Vector3 playerPos = player.transform.position;

                /*Thread coverThread = new Thread(() => SuitCoverToAI(ref aiCover, ref coverPointer, c, pos, playerPos));
                 * if (coverPointer < aiCover.Length && !c.CanSeePlayer)
                 * {
                 *  coverThread.Start();
                 * }
                 *
                 * Thread antiCoverThread = new Thread(() => SuitAnticoverToAI(ref aiAnticover, ref anticoverPointer, c, pos, playerPos));
                 * if (anticoverPointer < aiAnticover.Length && c.CanSeePlayer)
                 * {
                 *  antiCoverThread.Start();
                 * }
                 *
                 * while (coverThread.IsAlive || antiCoverThread.IsAlive)
                 * {
                 *  yield return new WaitForSeconds(coverUpdateDelayTime);
                 * }*/

                #region Cover
                for (int i = coverPointer; i < aiCover.Length; ++i)
                {
                    if (aiCover[i] == null || c.Occupied)
                    {
                        continue;
                    }

                    if (aiCover[i].customAI)
                    {
                        continue;
                    }

                    if (aiCover[i].Blackboard.BestCover != null)
                    {
                        continue;
                    }

                    float dist = Vector3.Distance(pos, aiCover[i].currentPosition);
                    float dot  = Vector3.Dot(Vector3.Normalize(playerPos - aiCover[i].currentPosition), Vector3.Normalize(pos - aiCover[i].currentPosition));
                    if (dist < coverRange && dot < 0.75f && !c.Occupied)//found cover
                    {
                        //swap it with the ai in the pointer position
                        AIController chosen = aiCover[i];
                        aiCover[i]            = aiCover[coverPointer];
                        aiCover[coverPointer] = chosen;
                        ++coverPointer;

                        //occupy it
                        c.occupier = chosen;
                        chosen.Blackboard.BestCover = c;

                        break;
                    }
                    yield return(null);
                }
                #endregion

                #region  Anticover
                for (int i = anticoverPointer; i < aiAnticover.Length; ++i)
                {
                    if (aiAnticover[i] == null || c.Occupied)
                    {
                        continue;
                    }

                    if (aiAnticover[i].customAI)
                    {
                        continue;
                    }

                    if (aiAnticover[i].Blackboard.BestAntiCover != null)
                    {
                        continue;
                    }

                    float dot        = Vector3.Dot(Vector3.Normalize(playerPos - aiAnticover[i].currentPosition), Vector3.Normalize(pos - aiAnticover[i].currentPosition));
                    float dist       = Vector3.Distance(pos, playerPos);
                    float playerDist = Vector3.Distance(playerPos, aiAnticover[i].currentPosition);

                    //Debug.Log("O: " + c.Occupied + " D: " + playerDist.ToString());

                    if (dist < antiCoverRange && playerDist > 3 && !c.Occupied)//found cover
                    {
                        //swap it with the ai in the pointer position
                        AIController chosen = aiAnticover[i];
                        aiAnticover[i] = aiAnticover[anticoverPointer];
                        aiAnticover[anticoverPointer] = chosen;
                        ++anticoverPointer;

                        //occupy it
                        c.occupier = chosen;
                        chosen.Blackboard.BestAntiCover = c;
                        break;
                    }
                    yield return(null);
                }
                #endregion
            }
            StartCoroutine(UpdateCover());
        }
        public static IEnumerator GotoCover(AIBlackboard blackboard, ComponentBlackboard components, float speed, bool strafeShoot, float waitTime, bool antiCover = false)
        {
            components.stateMachineManager.state = "COVER";
            //don't want a new instruction
            blackboard.Waiting = false;
            Debug.Log("Cover");
            components.StopShootingPlayer();

            NavMeshAgent      navigation      = components.navigation;
            MecanimLocomotion locomotion      = components.locomotion;
            Transform         aiTransform     = components.aiObject.transform;
            Transform         playerTransform = blackboard.player.transform;

            Vector3    pos   = aiTransform.position;
            CoverPoint cover = antiCover ? blackboard.BestAntiCover : blackboard.BestCover;

            if (cover != null)
            {
                pos = cover.transform.position;
            }
            else
            {
                Debug.Log("NO COVER!!");
            }


            bool validCover = true;

            //don't turn back on player
            float angle = Vector3.Angle(new Vector3(pos.x, 0, pos.z), new Vector3(aiTransform.position.x, aiTransform.position.z));

            if (angle > 100)
            {
                speed = 3;
            }

            navigation.SetDestination(pos);
            locomotion.lookWhereMoving = true;
            locomotion.turn            = false;
            locomotion.move            = true;

            while (Vector3.Distance(pos, aiTransform.position) > 3.5f && validCover)
            {
                /*if(antiCover)
                 * {
                 *  validCover = blackboard.BestAntiCover.GetInstanceID() == cover.GetInstanceID();
                 * }
                 * else
                 * {
                 *  validCover = blackboard.BestCover.GetInstanceID() == cover.GetInstanceID();
                 * }*/


                if (strafeShoot)
                {
                    if (!blackboard.LostPlayer && speed < 6)
                    {
                        locomotion.speed = speed;
                        locomotion.turn  = true;

                        if (playerTransform != null)
                        {
                            locomotion.lookDirection = playerTransform.position - aiTransform.position;
                        }

                        locomotion.lookWhereMoving = false;

                        if (blackboard.LineOfSight)
                        {
                            components.ShootPlayer();
                        }
                        else
                        {
                            components.StopShootingPlayer();
                        }

                        components.AimAtPlayer(playerTransform);
                    }
                    else
                    {
                        locomotion.speed = speed;
                        //locomotion.turn = true;
                        //locomotion.lookWhereMoving = true;
                        components.StopShootingPlayer();
                    }
                }
                navigation.SetDestination(pos);
                components.Navigate();

                yield return(null);

                cover = antiCover ? blackboard.BestAntiCover : blackboard.BestCover;
                if (cover != null)
                {
                    pos = cover.transform.position;
                }
            }

            float leaveTime = Time.time + waitTime;

            locomotion.move = false;
            components.StopNavigating();

            components.stateMachineManager.state = "AT COVER";

            while (leaveTime > Time.time)
            {
                if (blackboard.LineOfSight)
                {
                    locomotion.speed = 0;
                    locomotion.turn  = true;

                    if (playerTransform != null)
                    {
                        locomotion.lookDirection = playerTransform.position - aiTransform.position;
                    }

                    components.ShootPlayer();
                    components.AimAtPlayer(playerTransform);
                }
                else
                {
                    locomotion.lookDirection = aiTransform.forward;
                    locomotion.turn          = false;
                    components.StopShootingPlayer();
                }

                yield return(null);
            }

            components.AdvanceState();
        }