//The agent will use a random peice of cover that satisfies the line of sight requirements.
        TacticalAI.CoverData FindRandomCover(Vector3 targetTransformPos, Transform transformToDefend)
        {
            int i = 0;

            TacticalAI.CoverNodeScript        currentCoverNodeScript    = null;
            List <TacticalAI.CoverNodeScript> availableCoverNodeScripts = new List <TacticalAI.CoverNodeScript>();

            //Fill a list with potential nodes
            for (i = 0; i < coverNodeScripts.Length; i++)
            {
                if (!coverNodeScripts[i].isOccupied())
                {
                    if (coverNodeScripts[i].ValidCoverCheck(targetTransformPos) && (!transformToDefend || Vector3.SqrMagnitude(coverNodeScripts[i].GetPosition() - transformToDefend.position) < defendingDistSquared))
                    {
                        availableCoverNodeScripts.Add(coverNodeScripts[i]);
                    }
                }
            }

            if (availableCoverNodeScripts.Count > 0)
            {
                //Pick a random node
                currentCoverNodeScript = availableCoverNodeScripts[Random.Range(0, availableCoverNodeScripts.Count)];
                lastCoverPos           = currentCoverNodeScript.GetPosition();

                return(new TacticalAI.CoverData(true, currentCoverNodeScript.GetPosition(), currentCoverNodeScript.GetSightNodePosition(), false, currentCoverNodeScript));
            }
            //Only bother with dynamic cover if we need it
            if (shouldUseDynamicCover && !ControllerScript.pMode)
            {
                return(FindDynamicCover(targetTransformPos, transformToDefend));
            }

            return(new TacticalAI.CoverData());
        }
        //Agent will try and find cover that is within a given range of the target.
        TacticalAI.CoverData FindCoverWithinCombatRange(Vector3 targetTransformPos, Transform transformToDefend)
        {
            int     i     = 0;
            Vector3 myPos = myTransform.position;

            TacticalAI.CoverNodeScript currentCoverNodeScript = null;
            float closestDistSquared = maxDistToCover;
            float nodeCheckingNowDistSquared;
            float distToTargetSquared;

            //We will take cover outside of the desired range if we can't find any within.
            bool foundCoverWithinAcceptableRange = false;

            for (i = 0; i < coverNodeScripts.Length; i++)
            {
                //Check if the node we are checking is occupied and within acceptable distances to key points
                if (!coverNodeScripts[i].isOccupied() && coverNodeGroup == coverNodeScripts[i].coverNodeGroup && Vector3.SqrMagnitude(coverNodeScripts[i].GetPosition() - lastCoverPos) > minDistBetweenLastCoverSquared &&
                    (!transformToDefend || Vector3.SqrMagnitude(coverNodeScripts[i].GetPosition() - transformToDefend.position) < defendingDistSquared))
                {
                    distToTargetSquared        = Vector3.SqrMagnitude(coverNodeScripts[i].GetPosition() - targetTransformPos);
                    nodeCheckingNowDistSquared = Vector3.SqrMagnitude(myPos - coverNodeScripts[i].GetPosition());
                    //Check for line of sight
                    if (coverNodeScripts[i].ValidCoverCheck(targetTransformPos))
                    {
                        //Prefer nodes within othe agent's combat range
                        if (minCoverDistSqrd < distToTargetSquared && maxCoverDistSqrd > distToTargetSquared)
                        {
                            if (!foundCoverWithinAcceptableRange || (nodeCheckingNowDistSquared < closestDistSquared))
                            {
                                closestDistSquared              = nodeCheckingNowDistSquared;
                                currentCoverNodeScript          = coverNodeScripts[i];
                                foundCoverWithinAcceptableRange = true;
                            }
                        }
                        //Check if this is the closest so far
                        else if (!foundCoverWithinAcceptableRange && nodeCheckingNowDistSquared < closestDistSquared)
                        {
                            closestDistSquared     = nodeCheckingNowDistSquared;
                            currentCoverNodeScript = coverNodeScripts[i];
                        }
                    }
                }
            }

            //pass the data to the script that asked for cover
            if (currentCoverNodeScript != null)
            {
                lastCoverPos = currentCoverNodeScript.GetPosition();
                return(new TacticalAI.CoverData(true, currentCoverNodeScript.GetPosition(), currentCoverNodeScript.GetSightNodePosition(), false, currentCoverNodeScript));
            }

            //Only bother with dynamic cover if we need it
            if (shouldUseDynamicCover && !ControllerScript.pMode)
            {
                return(FindDynamicCover(targetTransformPos, transformToDefend));
            }

            return(new TacticalAI.CoverData());
        }
 public CoverData(bool f, Vector3 hp, Vector3 fP, bool d, TacticalAI.CoverNodeScript cns)
 {
     foundCover      = f;
     hidingPosition  = hp;
     firingPosition  = fP;
     isDynamicCover  = d;
     coverNodeScript = cns;
 }
        //The agent will find cover that is closer to their target each time they change cover locations
        TacticalAI.CoverData FindAdvancingCover(Vector3 targetTransformPos, Transform transformToDefend)
        {
            int     i     = 0;
            Vector3 myPos = myTransform.position;

            TacticalAI.CoverNodeScript currentCoverNodeScript = null;

            //Will find closest cover that is nearer than the last one we have if possible.
            //If not, we'll move to the target.
            Vector3 posToAdvanceTo;

            if (transformToDefend)
            {
                posToAdvanceTo = transformToDefend.position;
            }
            else
            {
                posToAdvanceTo = targetTransformPos;
            }

            float distBetweenMeAndTarget       = Vector3.SqrMagnitude(myPos - posToAdvanceTo) - minDistToAdvance;
            float closestDistBetweenMeAndCover = distBetweenMeAndTarget;

            for (i = 0; i < coverNodeScripts.Length; i++)
            {
                if (!coverNodeScripts[i].isOccupied())
                {
                    float sqrDistBetweenNodeAndTargetPos = Vector3.SqrMagnitude(coverNodeScripts[i].GetPosition() - posToAdvanceTo);
                    //Check if we'll be closer to target than we stand now
                    if (sqrDistBetweenNodeAndTargetPos < distBetweenMeAndTarget)
                    {
                        //Check if this node is closest to us
                        if (Vector3.SqrMagnitude(coverNodeScripts[i].GetPosition() - myPos) < closestDistBetweenMeAndCover)
                        {
                            //Check if node is safe
                            if (coverNodeScripts[i].ValidCoverCheck(targetTransformPos))
                            {
                                closestDistBetweenMeAndCover = sqrDistBetweenNodeAndTargetPos;
                                currentCoverNodeScript       = coverNodeScripts[i];
                            }
                        }
                    }
                }
            }
            if (currentCoverNodeScript != null)
            {
                lastCoverPos = currentCoverNodeScript.GetPosition();
                return(new TacticalAI.CoverData(true, currentCoverNodeScript.GetPosition(), currentCoverNodeScript.GetSightNodePosition(), false, currentCoverNodeScript));
            }

            //Dynamic advancing cover is NOT supported

            return(new TacticalAI.CoverData());
        }
        //Used to set variables once cover is found.
        void SetCover(Vector3 newCoverPos, Vector3 newCoverFiringSpot, bool isDynamicCover, TacticalAI.CoverNodeScript newCoverNodeScript)
        {
            timeTilNoCoverCharge = maxTimeTilNoCoverCharge;

            baseScript.currentCoverNodePos       = newCoverPos;
            baseScript.currentCoverNodeFiringPos = newCoverFiringSpot;

            navI.SetStoppingDistance(0);

            if (isDynamicCover)
            {
                foundDynamicCover = true;
                TacticalAI.ControllerScript.currentController.AddACoverSpot(baseScript.currentCoverNodeFiringPos);
            }
            else
            {
                baseScript.currentCoverNodeScript = newCoverNodeScript;
                baseScript.currentCoverNodeScript.setOccupied(true);
                if (baseScript.useAdvancedCover)
                {
                    animationScript.StartAdvancedCover(baseScript.currentCoverNodeScript.advancedCoverDirection, baseScript.currentCoverNodeScript.faceDir);
                }
            }
        }