private void FilterFireTargetList(TargetList targets)
        {
            if (this.fireControllerLayerMask.value == 0)
            {
                return;
            }
            Vector3 position;

            if (this.fireCtrl.emitter != null)
            {
                position = this.fireCtrl.emitter.position;
            }
            else
            {
                position = this.fireCtrl.transform.position;
            }
            LayerMask mask = this.fireControllerLayerMask;

            this.FilterTargetList(targets, mask, position, Color.yellow);
        }
Beispiel #2
0
        /// <summary>
        /// Remove an object from the list explicitly.
        /// This works even if the object is still in range, effectivley hiding it from the
        /// perimiter.
        /// </summary>
        /// <param name="target">The Target to remove</param>
        /// <returns>True if somethign was removed</returns>
        public bool Remove(Target target)
        {
            // Quit if nothing was removed
            if (!this.targets.Remove(target))
            {
                return(false);
            }

            // Silence errors on game exit / unload clean-up
            if (target.transform == null || this.transform == null || this.transform.parent == null)
            {
                return(false);
            }

#if UNITY_EDITOR
            if (this.targetTracker.debugLevel > DEBUG_LEVELS.Off) // If on at all
            {
                Debug.Log(string.Format
                          (
                              "{0}  : Target Removed - {1}",
                              this.targetTracker,
                              target.targetable
                          ));
            }
#endif

            // Trigger the delegate execution for this event
            if (this.targetTracker.onNotDetectedDelegates != null)
            {
                this.targetTracker.onNotDetectedDelegates(this.targetTracker, target);
            }

            target.targetable.OnNotDetected(this.targetTracker);

            // Trigger target update: Sorting, filtering, events.
            //	 This uses AddRange internally to copy the targets so '=' is safe
            this.targetTracker.targets = this.targets;

            return(true);
        }
Beispiel #3
0
        private void OnFire()
        {
            if (this.debugLevel > DEBUG_LEVELS.Off)
            {
                string arg = string.Format("Firing on: {0}\nHitEffects{1}", this.targetsString, this.effectsOnTarget.ToString());
                UnityEngine.Debug.Log(string.Format("{0}: {1}", this, arg));
            }
            TargetList targetList = new TargetList();

            foreach (Target current in this.targets)
            {
                Target target = new Target(current);
                target.fireController = this;
                targetList.Add(target);
                switch (this.notifyTargets)
                {
                case FireController.NOTIFY_TARGET_OPTIONS.Direct:
                    target.targetable.OnHit(this.effectsOnTarget, target);
                    this.SpawnAmmunition(target, false, false);
                    break;

                case FireController.NOTIFY_TARGET_OPTIONS.PassToProjectile:
                    this.SpawnAmmunition(target, true, true);
                    break;

                case FireController.NOTIFY_TARGET_OPTIONS.UseProjectileEffects:
                    this.SpawnAmmunition(target, true, false);
                    break;
                }
                if (this.notifyTargets > FireController.NOTIFY_TARGET_OPTIONS.Off && this.debugLevel > DEBUG_LEVELS.Off)
                {
                    UnityEngine.Debug.DrawLine(this.emitter.position, target.transform.position, Color.red);
                }
            }
            this.targets = targetList;
            if (this.onFireDelegates != null)
            {
                this.onFireDelegates(this.targets);
            }
        }
        protected void FilterTrackerTargetList(TargetTracker source, TargetList targets)
        {
            // Quit if the mask is set to nothing == OFF
            if (this.targetTrackerLayerMask.value == 0)
            {
                return;
            }

            Vector3 fromPos;

            if (this.tracker.area != null)
            {
                fromPos = this.tracker.area.transform.position;
            }
            else
            {
                fromPos = this.tracker.transform.position;
            }

            LayerMask mask = this.targetTrackerLayerMask;

            this.FilterTargetList(targets, mask, fromPos, Color.red);
        }
Beispiel #5
0
        private void FilterFireTargetList(TargetList targets)
        {
            // Quit if the mask is set to nothing == OFF
            if (this.fireControllerLayerMask.value == 0)
            {
                return;
            }

            Vector3 fromPos;

            if (this.fireCtrl.emitter != null)
            {
                fromPos = this.fireCtrl.emitter.position;
            }
            else
            {
                fromPos = this.fireCtrl.transform.position;
            }

            LayerMask mask = this.fireControllerLayerMask;

            this.FilterTargetList(targets, mask, fromPos, Color.yellow);
        }
        private void FilterTargetList(TargetList targets, LayerMask mask, Vector3 fromPos, Color debugLineColor)
        {
            List <Target> list = new List <Target>(targets);

            foreach (Target current in list)
            {
                bool    flag     = false;
                Vector3 position = current.targetable.xform.position;
                if (this.testMode == LineOfSightModifier.TEST_MODE.SixPoint)
                {
                    foreach (Vector3 current2 in new List <Vector3>
                    {
                        new Vector3(position.x + this.radius, position.y, position.z),
                        new Vector3(position.x, position.y + this.radius, position.z),
                        new Vector3(position.x, position.y, position.z + this.radius),
                        new Vector3(position.x - this.radius, position.y, position.z),
                        new Vector3(position.x, position.y - this.radius, position.z),
                        new Vector3(position.x, position.y, position.z - this.radius)
                    })
                    {
                        flag = Physics.Linecast(fromPos, current2, mask);
                        if (!flag)
                        {
                            break;
                        }
                    }
                }
                else
                {
                    flag = Physics.Linecast(fromPos, position, mask);
                }
                if (flag)
                {
                    targets.Remove(current);
                }
            }
        }
Beispiel #7
0
        /// <summary>
        /// Clears the entire list explicitly
        /// This works even if the object is still in range, effectivley hiding it from the
        /// perimiter.
        /// </summary>
        public void Clear()
        {
            // Trigger the delegate execution for this event
            foreach (Target target in this.targets)
            {
                target.targetable.OnNotDetected(this.targetTracker);
            }

            this.targets.Clear();

#if UNITY_EDITOR
            if (this.targetTracker.debugLevel > DEBUG_LEVELS.Normal)             // If on at all
            {
                Debug.Log(string.Format
                          (
                              "{0}  : All Targets Cleared!",
                              this.targetTracker
                          ));
            }
#endif
            // Trigger target update: Sorting, filtering, events.
            //	 This uses AddRange internally to copy the targets so '=' is safe
            this.targetTracker.targets = this.targets;
        }
Beispiel #8
0
 public TargetList(TargetList targetList) : base(targetList)
 {
 }
Beispiel #9
0
        protected void FilterFireTargetList(TargetList targets)
        {
            // Get the position expected to be used to fire from.
            Vector3 fromPos = this.origin.position;

#if UNITY_EDITOR
            var debugRemoveNames = new List <string>();
#endif
            this.iterTargets.Clear();
            this.iterTargets.AddRange(targets);
            float dist;
            for (int i = 0; i < iterTargets.Count; i++)
            {
                this.currentTarget = iterTargets[i];
                dist = this.currentTarget.targetable.GetDistToPos(fromPos);

                // Skip if the target is in the distance range
                if (dist > this.minDistance && dist < this.maxDistance)
                {
#if UNITY_EDITOR
                    if (this.debugLevel > DEBUG_LEVELS.Off)
                    {
                        Debug.DrawLine
                        (
                            fromPos,
                            this.currentTarget.targetable.transform.position,
                            Color.green,
                            0.01f
                        );
                    }
#endif
                    continue;
                }

#if UNITY_EDITOR
                if (this.debugLevel > DEBUG_LEVELS.Off)
                {
                    Debug.DrawLine
                    (
                        fromPos,
                        this.currentTarget.targetable.transform.position,
                        Color.red,
                        0.01f
                    );
                }
#endif
                targets.Remove(this.currentTarget);

#if UNITY_EDITOR
                debugRemoveNames.Add(this.currentTarget.targetable.name);
#endif
            }

#if UNITY_EDITOR
            if (this.debugLevel == DEBUG_LEVELS.High && debugRemoveNames.Count > 0)
            {
                string msg = string.Format
                             (
                    "Holding fire due to distance: {0}",
                    string.Join(", ", debugRemoveNames.ToArray())
                             );

                Debug.Log(string.Format("{0}: {1}", this, msg));
            }
#endif
        }
        /// <summary>
        /// Handles all firing events including target aquisition and firing.
        /// Events are:
        ///     OnStart() :
        ///         Runs once when the firing system first becomes active
        ///     OnUpdate() :
        ///         Runs each frame while the firing system is active
        ///     OnTargetUpdate() :
        ///         Runs each frame while tracking a target (there is at least one target.)
        ///     OnIdleUpdate() :
        ///         Runs each frame while the firing system is idle (no targets)
        ///     OnFire() :
        ///         Runs when it is time to fire.
        ///
        /// Counter Behavior Notes:
        ///   * If there are no targets. the counter will keep running up.
        ///     This means the next target to enter will be fired upon
        ///     immediatly.
        ///
        ///   * The counter is always active so if the last target exits, then a
        ///     new target enters right after that, there may still be a wait.
        /// </summary>
        private IEnumerator FiringSystem()
        {
            // While (true) because of the timer, we want this to run all the time, not
            //   start and stop based on targets in range
            if (this.initIntervalCountdownAtZero)
            {
                this.fireIntervalCounter = 0;
            }
            else
            {
                this.fireIntervalCounter = this.interval;
            }

            this.targets.Clear();
            this.OnStart();   // EVENT TRIGGER

            while (true)
            {
                // if there is no target, counter++, handle idle behavior, and
                //   try next frame.
                // Will init this.targets for child classes as well.
                this.targets = this.targetTracker.targets;

                if (this.targets.Count != 0)
                {
                    // Let the delegate filter a copy of the list just for the OnFire
                    //   Test. We still want this.targets to remain as is.
                    //   Do this in here to still trigger OnTargetUpdate
                    var targetsCopy = new TargetList();
                    targetsCopy.AddRange(this.targets);

                    if (this.onPreFireDelegates != null)
                    {
                        this.onPreFireDelegates(targetsCopy);
                    }

                    // if all is right, fire
                    if (targetsCopy.Count != 0 && // Incase of pre-fire delegate changes
                        this.fireIntervalCounter <= 0 &&
                        this.isLockedOnTarget)    // Always true if WaitForAlignment is OFF
                    {
                        this.OnFire();
                        this.fireIntervalCounter = this.interval;  // Reset
                    }
                    else if (this.debugLevel > DEBUG_LEVELS.Off)
                    {
                        // Just for debug. Show a gizmo line to each target being tracked
                        //   OnFire() has another color, so keep this here where this
                        //   won't overlay the OnFired line.
                        foreach (Target target in targets)
                        {
                            Debug.DrawLine
                            (
                                this.emitter.position,
                                target.transform.position,
                                Color.gray
                            );
                        }
                    }

                    // Update event while tracking a target
                    this.OnTargetUpdate(targets);   // EVENT TRIGGER
                }
                else
                {
                    // Update event while NOT tracking a target
                    this.OnIdleUpdate();   // EVENT TRIGGER
                }

                this.fireIntervalCounter -= Time.deltaTime;

                // Update event no matter what
                this.OnUpdate();   // EVENT TRIGGER

                // Stager calls to get Target (the whole system actually)
                yield return(null);
            }
        }
Beispiel #11
0
 /// <summary>
 /// A delegate run by the EventTrigger component OnFire
 /// </summary>
 protected void OnEventTriggerFire(TargetList targets)
 {
     // A great place for an explosion effect to be triggered!
 }
        /// <summary>
        /// Handles all firing events including target aquisition and firing.
        /// Events are:
        ///     OnStart() :
        ///         Runs once when the firing system first becomes active
        ///     OnUpdate() :
        ///         Runs each frame while the firing system is active
        ///     OnTargetUpdate() :
        ///         Runs each frame while tracking a target (there is at least one target.)
        ///     OnIdleUpdate() :
        ///         Runs each frame while the firing system is idle (no targets)
        ///     OnFire() :
        ///         Runs when it is time to fire.
        ///
        /// Counter Behavior Notes:
        ///   * If there are no targets. the counter will keep running up.
        ///     This means the next target to enter will be fired upon
        ///     immediatly.
        ///
        ///   * The counter is always active so if the last target exits, then a
        ///     new target enters right after that, there may still be a wait.
        /// </summary>
        protected IEnumerator FiringSystem()
        {
            if (this.targetTracker == null)
            {
                this.targetTracker = this.GetComponent <TargetTracker>();
                if (this.targetTracker == null)
                {
                    // Give it a frame to see if this.targetTracker is being set by code.
                    yield return(null);

                    if (this.targetTracker == null)
                    {
                        throw new MissingComponentException
                              (
                                  "FireControllers must be on the same GameObject as a TargetTracker " +
                                  "or have it's targetTracker property set by code or drag-and-drop " +
                                  "in the inspector."
                              );
                    }
                }
            }

            // While (true) because of the timer, we want this to run all the time, not
            //   start and stop based on targets in range
            if (this.initIntervalCountdownAtZero)
            {
                this.fireIntervalCounter = 0;
            }
            else
            {
                this.fireIntervalCounter = this.interval;
            }

            this.targets.Clear();
            this.OnStart();         // EVENT TRIGGER

            this.keepFiring = true; // Can be turned off elsewhere to kill the firing system

            while (this.keepFiring)
            {
                // if there is no target, counter++, handle idle behavior, and
                //   try next frame.
                // Will init this.targets for child classes as well.
                this.targets = new TargetList(this.targetTracker.targets);

                if (this.targets.Count != 0)
                {
                    if (this.fireIntervalCounter <= 0)
                    {
                        // Let the delegate filter a copy of the list just for the OnFire
                        //   Test. We still want this.targets to remain as is.
                        //   Do this in here to still trigger OnTargetUpdate
                        this.targetsCopy.Clear();
                        this.targetsCopy.AddRange(this.targets);

                        if (targetsCopy.Count != 0 && this.onPreFireDelegates != null)
                        {
                            this.onPreFireDelegates(this.targetsCopy);
                        }

                        // If all is right, fire
                        // Check targetsCopy incase of pre-fire delegate changes
                        if (targetsCopy.Count != 0)
                        {
                            this.Fire();
                            this.fireIntervalCounter = this.interval;      // Reset
                        }
                    }

                    // Update event while tracking a target
                    this.OnTargetUpdate(this.targets);   // EVENT TRIGGER
                }
                else
                {
                    // Update event while NOT tracking a target
                    this.OnIdleUpdate();   // EVENT TRIGGER
                }

                this.fireIntervalCounter -= Time.deltaTime;

                // Update event no matter what
                this.OnUpdate();   // EVENT TRIGGER

                // Stager calls to get Target (the whole system actually)
                yield return(null);
            }

            // Wipe out the target list when stopped
            this.targets.Clear();
        }
        /// <summary>
        /// Fire on the targets
        /// </summary>
        protected void Fire()
        {
#if UNITY_EDITOR
            // Log a message to show what is being fired on
            if (this.debugLevel > DEBUG_LEVELS.Off)
            {
                string[] names = new string[this.targets.Count];
                for (int i = 0; i < this.targets.Count; i++)
                {
                    names[i] = this.targets[i].transform.name;
                }

                string msg = string.Format
                             (
                    "Firing on: {0}\nEventInfo: {1}",
                    string.Join(", ", names),
                    this.eventInfoList.ToString()
                             );

                Debug.Log(string.Format("{0}: {1}", this, msg));
            }
#endif

            //
            // Create a new list of targets which have this fire controller reference.
            //
            var    targetCopies = new TargetList();
            Target newTarget;
            foreach (Target target in this.targets)
            {
                // Can't edit a struct in a foreach loop, so need to copy and store
                newTarget = new Target(target);
                newTarget.fireController = this;  // Add reference. null before this
                targetCopies.Add(newTarget);
            }

            // Write the result over the old target list. This is for output so targets
            //   which are handled at all by this target tracker are stamped with a
            //   reference.
            this.targets = targetCopies;

            //
            // Hnadle delivery
            //
            foreach (Target target in this.targets)
            {
                switch (this.notifyTargets)
                {
                case NOTIFY_TARGET_OPTIONS.Direct:
                    target.targetable.OnHit(this.eventInfoList, target);
                    break;

                case NOTIFY_TARGET_OPTIONS.PassInfoToEventTrigger:
                    this.SpawnEventTrigger(target, true);
                    break;

                case NOTIFY_TARGET_OPTIONS.UseEventTriggerInfo:
                    this.SpawnEventTrigger(target, false);
                    break;
                }
            }

#if UNITY_EDITOR
            // When in the editor, if debugging, draw a line to each hit target.
            if (this.debugLevel > DEBUG_LEVELS.Off && this.notifyTargets > NOTIFY_TARGET_OPTIONS.Off)
            {
                foreach (Target target in this.targets)
                {
                    Debug.DrawLine(this.spawnEventTriggerAtTransform.position, target.transform.position, Color.red);
                }
            }
#endif
            // Trigger the delegates
            if (this.onFireDelegates != null)
            {
                this.onFireDelegates(this.targets);
            }
        }
Beispiel #14
0
        private IEnumerator Detonate()
        {
            if (this.debugLevel > DEBUG_LEVELS.Off)
            {
                string msg = "Detonating...";
                Debug.Log(string.Format("Detonator ({0}): {1}", this.name, msg));
            }

            // Wait for next frame to begin to be sure targets have been propegated
            // This also makes this loop easier to manage.
            yield return(new WaitForFixedUpdate());  // Because of physics...matters?

            // START EVENT
            if (this.OnDetonatingDelegates != null)
            {
                this.OnDetonatingDelegates();
            }

            // Keep track of targets which have already been processed so they
            //      aren't hit twice
            var processedTargetList = new TargetList();

            this.range = Vector3.zero;

            float timer    = 0;
            float progress = 0;  // Normalized mount processed 0-1

            // The timer can exit the loop if used
            while (true)
            {
                // UPDATE EVENT
                if (this.OnDetonatingUpdateDelegates != null)
                {
                    this.OnDetonatingUpdateDelegates(progress);
                }

                // Exit?
                if (timer >= this.durration)
                {
                    break;
                }
                timer += Time.deltaTime;

                progress = timer / this.durration;

                this.range = this.maxRange * progress;

                // Build a list of targets in range which have NOT been processed yet.
                var newTargets = new TargetList();
                foreach (Target target in this.targets)
                {
                    if (!processedTargetList.Contains(target))
                    {
                        newTargets.Add(target);
                    }
                }

                if (newTargets.Count > 0)
                {
                    if (this.debugLevel > DEBUG_LEVELS.Off)
                    {
                        string msg = string.Format("Detonation hitting targets: {0}", this.targets);
                        Debug.Log(string.Format("Detonator ({0}): {1}", this.name, msg));
                    }

                    foreach (Target target in newTargets)
                    {
                        target.targetable.OnHit
                        (
                            this.effectsOnTarget,
                            target,
                            this.perimeter.collider
                        );

                        processedTargetList.Add(target);
                    }
                }

                yield return(new WaitForFixedUpdate());  // Because of physics...matters?
            }

            // Prevent being run more than once in a frame where it has already
            //   been destroyed.
            if (!this.gameObject.activeInHierarchy)
            {
                yield break;  // Same as return
            }
            PathologicalGames.InstanceManager.Despawn(this.transform);
        }
        protected void FilterTargetList(TargetList targets, LayerMask mask, Vector3 fromPos,
                                        Color debugLineColor)
        {
#if UNITY_EDITOR
            var debugRemoveNames = new List <string>();
#endif

            Vector3  toPos;
            bool     isNotLOS;
            var      iterTargets = new List <Target>(targets);
            Collider targetColl;
            foreach (Target target in iterTargets)
            {
                isNotLOS = false;

                if (this.testMode == TEST_MODE.BoundingBox)
                {
                    targetColl = target.targetable.coll;

                    // This solution works with rotation pretty well
                    Matrix4x4 mtx = target.targetable.transform.localToWorldMatrix;

                    Vector3 ext      = targetColl.bounds.extents * 0.5f;
                    var     bboxPnts = new Vector3[8];
                    bboxPnts[0] = mtx.MultiplyPoint3x4(ext);
                    bboxPnts[1] = mtx.MultiplyPoint3x4(new Vector3(-ext.x, ext.y, ext.z));
                    bboxPnts[2] = mtx.MultiplyPoint3x4(new Vector3(ext.x, ext.y, -ext.z));
                    bboxPnts[3] = mtx.MultiplyPoint3x4(new Vector3(-ext.x, ext.y, -ext.z));
                    bboxPnts[4] = mtx.MultiplyPoint3x4(new Vector3(ext.x, -ext.y, ext.z));
                    bboxPnts[5] = mtx.MultiplyPoint3x4(new Vector3(-ext.x, -ext.y, ext.z));
                    bboxPnts[6] = mtx.MultiplyPoint3x4(new Vector3(ext.x, -ext.y, -ext.z));
                    bboxPnts[7] = mtx.MultiplyPoint3x4(-ext);

                    for (int i = 0; i < bboxPnts.Length; i++)
                    {
                        isNotLOS = Physics.Linecast(fromPos, bboxPnts[i], mask);

                        // Quit loop at first positive test
                        if (isNotLOS)
                        {
#if UNITY_EDITOR
                            if (this.debugLevel > DEBUG_LEVELS.Off)
                            {
                                Debug.DrawLine(fromPos, bboxPnts[i], debugLineColor, 0.01f);
                            }
#endif
                            continue;
                        }
                        else
                        {
                            break;
                        }
                    }
                }
                else
                {
                    toPos    = target.targetable.transform.position;
                    isNotLOS = Physics.Linecast(fromPos, toPos, mask);
#if UNITY_EDITOR
                    if (isNotLOS && this.debugLevel > DEBUG_LEVELS.Off)
                    {
                        Debug.DrawLine(fromPos, toPos, debugLineColor, 0.01f);
                    }
#endif
                }

                if (isNotLOS)
                {
                    targets.Remove(target);

#if UNITY_EDITOR
                    debugRemoveNames.Add(target.targetable.name);
#endif
                }
            }

#if UNITY_EDITOR
            if (this.debugLevel == DEBUG_LEVELS.High && debugRemoveNames.Count > 0)
            {
                Debug.Log("Holding fire for LOS: " +
                          string.Join(",", debugRemoveNames.ToArray()));
            }
#endif
        }
        /// <summary>
        /// Destroys the projectile on impact and finds objects in range to
        ///	affect if they share the same tag as target.
        /// </summary>
        public void DetonateProjectile()
        {
            // Prevent being run more than once in a frame where it has already
            //   been destroyed.
            if (!this.gameObject.activeInHierarchy)
            {
                return;
            }

            // Build a new list of targets depending on the options used
            var targetList = new TargetList();

            if (this.areaHit)
            {
                // This is turned back off OnDisable() (base class)
                this.perimeter.enabled = true;

                targetList.AddRange(this.targets); // Add all targets in range
            }
            else
            {
                if (this.target != Target.Null)
                {
                    targetList.Add(this.target); // Add projectile target
                }
            }

            if (this.debugLevel > DEBUG_LEVELS.Off)
            {
                string msg = string.Format("Detonating with targets: {0}", targetList);
                Debug.Log(string.Format("Projectile ({0}): {1}", this.name, msg));
            }

            // Create a new list of targets which have this target tracker reference.
            //   This is for output so targets which are handled at all by this Projectile
            //   are stamped with a reference.
            var    targetCopies = new TargetList();
            Target target;

            foreach (Target inTarget in targetList)
            {
                if (inTarget == Target.Null)
                {
                    continue;
                }

                // Can't edit a struct in a foreach loop, so need to copy and store
                target            = new Target(inTarget);
                target.projectile = this;  // Add reference. null before t
                targetCopies.Add(target);

                switch (this.notifyTargets)
                {
                case NOTIFY_TARGET_OPTIONS.Direct:
                    target.targetable.OnHit(this.effectsOnTarget, target, this.collider);
                    break;
                }

                // Just for debug. Show a gizmo line when firing
                if (this.debugLevel > DEBUG_LEVELS.Off)
                {
                    Debug.DrawLine
                    (
                        this.xform.position,
                        target.transform.position,
                        Color.red
                    );
                }
            }

            switch (this.notifyTargets)
            {
            case NOTIFY_TARGET_OPTIONS.Direct:
                this.SpawnDetonatorPrefab(false);
                break;

            case NOTIFY_TARGET_OPTIONS.PassToDetonator:
                this.SpawnDetonatorPrefab(true);
                break;
            }


            // Trigger delegates
            if (this.OnDetonationDelegates != null)
            {
                this.OnDetonationDelegates(targetCopies);
            }

            // Clean-up in case this instance is used in a pooling system like PoolManager
            this.target = Target.Null;

            InstanceManager.Despawn(this.transform);
        }
Beispiel #17
0
        private void FilterTargetList(TargetList targets, LayerMask mask, Vector3 fromPos,
                                      Color debugLineColor)
        {
#if UNITY_EDITOR
            var debugRemoveNames = new List <string>();
#endif

            Vector3 toPos;
            bool    isNotLOS;
            var     iterTargets = new List <Target>(targets);

            foreach (Target target in iterTargets)
            {
                isNotLOS = false;

                toPos = target.targetable.xform.position;

                if (this.testMode == TEST_MODE.SixPoint)
                {
                    var sweep = new List <Vector3>();
                    sweep.Add(new Vector3(toPos.x + this.radius, toPos.y, toPos.z));
                    sweep.Add(new Vector3(toPos.x, toPos.y + this.radius, toPos.z));
                    sweep.Add(new Vector3(toPos.x, toPos.y, toPos.z + this.radius));

                    sweep.Add(new Vector3(toPos.x - this.radius, toPos.y, toPos.z));
                    sweep.Add(new Vector3(toPos.x, toPos.y - this.radius, toPos.z));
                    sweep.Add(new Vector3(toPos.x, toPos.y, toPos.z - this.radius));

                    foreach (Vector3 pos in sweep)
                    {
                        isNotLOS = Physics.Linecast(fromPos, pos, mask);
#if UNITY_EDITOR
                        if (this.debugLevel > DEBUG_LEVELS.Off)
                        {
                            Debug.DrawLine(fromPos, pos, debugLineColor, 0.01f);
                        }
#endif
                        // Quit loop at first positive test
                        if (isNotLOS)
                        {
                            continue;
                        }
                        else
                        {
                            break;
                        }
                    }
                }
                else
                {
                    isNotLOS = Physics.Linecast(fromPos, toPos, mask);
#if UNITY_EDITOR
                    if (this.debugLevel > DEBUG_LEVELS.Off)
                    {
                        Debug.DrawLine(fromPos, toPos, debugLineColor, 0.01f);
                    }
#endif
                }

                if (isNotLOS)
                {
                    targets.Remove(target);

#if UNITY_EDITOR
                    debugRemoveNames.Add(target.targetable.name);
#endif
                }
            }

#if UNITY_EDITOR
            if (this.debugLevel == DEBUG_LEVELS.High && debugRemoveNames.Count > 0)
            {
                Debug.Log("Holding fire for LOS: " +
                          string.Join(",", debugRemoveNames.ToArray()));
            }
#endif
        }