public override ActionSet ComposeActionSet(Reflex reflex, GameActor gameActor)
        {
            ClearActionSet(actionSet);
            UpdateCanBlend(reflex);

            if (!reflex.targetSet.AnyAction)
            {
                return(actionSet);
            }

            if (reflex.targetSet.Count > 0)
            {
                if (reflex.targetSet.CullToFurthest(gameActor, BlockedFrom))
                {
                    // the targetSet is in order by distance
                    SensorTarget target = reflex.targetSet.Furthest;

                    // calculate a vector toward target
                    Vector3 value = target.Direction;

                    bool apply = reflex.ModifyHeading(gameActor, Modifier.ReferenceFrames.World, ref value);

                    if (apply)
                    {
                        // radius should be from object
                        actionSet.AddAttractor(AllocAttractor(target.Range, value, target.GameThing, reflex), 0.4f);
                    }
                }
            }

            return(actionSet);
        }
        public override ActionSet ComposeActionSet(Reflex reflex, GameActor gameActor)
        {
            ClearActionSet(actionSet);
            UpdateCanBlend(reflex);

            if (!reflex.targetSet.AnyAction)
            {
                return(actionSet);
            }

            SensorTarget target = reflex.targetSet.Nearest;

            if (target != null)
            {
                // Calculate a vector toward target.
                Vector3 value = target.Direction;

                bool apply = reflex.ModifyHeading(gameActor, Modifier.ReferenceFrames.World, ref value);

                if (apply)
                {
                    actionSet.AddAction(Action.AllocTargetLocationAction(reflex, target.Position, autoTurn: true));
                }
            }

            return(actionSet);
        }
        public override void ComposeSensorTargetSet(GameActor gameActor, Reflex reflex)
        {
            List <Filter> filters = reflex.Filters;

            SensorTargetSet.Enumerator senseSetIter = (SensorTargetSet.Enumerator)gameActor.GivenSet.GetEnumerator();
            senseSetIter.Reset();
            while (senseSetIter.MoveNext())
            {
                SensorTarget target = (SensorTarget)senseSetIter.Current;

                bool match = true;
                for (int indexFilter = 0; indexFilter < filters.Count; indexFilter++)
                {
                    Filter filter = filters[indexFilter] as Filter;
                    if (!filter.MatchTarget(reflex, target))
                    {
                        match = false;
                        break;
                    }
                }
                if (match)
                {
                    reflex.targetSet.Add(target);
                }
            }

            reflex.targetSet.Action = TestObjectSet(reflex);
        }
Exemplo n.º 4
0
        public static void Free(SensorTarget target)
        {
            target.refs--;

            Debug.Assert(target.refs == 0);

            target.Clear();
            spareSensorTargets.Add(target);
        }
Exemplo n.º 5
0
        public override bool MatchAction(Reflex reflex, out object param)
        {
            param = null;

            bool match = false;


            // Do we have enough targets to even bother?
            if (reflex.targetSet.NearestTargets.Count > count)
            {
                for (int i = 0; i < reflex.targetSet.NearestTargets.Count - count; i++)
                {
                    // Start with the cluster containing just the current element.
                    cluster.Clear();
                    cluster.Add(reflex.targetSet.NearestTargets[i]);

                    // For each of the remaining elements, see if they are near enough
                    // to cluster with any of the elements already in the cluster.
                    for (int j = i + 1; j < reflex.targetSet.NearestTargets.Count; j++)
                    {
                        SensorTarget target = reflex.targetSet.NearestTargets[j];

                        foreach (SensorTarget clusterElement in cluster)
                        {
                            float dist  = (target.Position - clusterElement.Position).Length();
                            float range = 2.0f * (target.GameThing.BoundingSphere.Radius + clusterElement.GameThing.BoundingSphere.Radius);
                            if (dist < range)
                            {
                                cluster.Add(target);
                                break;
                            }
                        }
                    }

                    // Did we find a cluster?
                    if (cluster.Count > count)
                    {
                        match = true;

                        // Change targetSet.NearestTargets to just hold the cluster.
                        reflex.targetSet.NearestTargets.Clear();
                        foreach (SensorTarget target in cluster)
                        {
                            reflex.targetSet.NearestTargets.Add(target);
                        }

                        break;
                    }
                } // end of outer loop over elements.
            }     // if we have enough elements to form a cluster.

            // Not strictly needed but it does prevent refs being held longer than needed.
            cluster.Clear();

            return(match);
        }   // end of MatchAction()
Exemplo n.º 6
0
        public override void ComposeSensorTargetSet(GameActor gameActor, Reflex reflex)
        {
            List <Filter> filters = reflex.Filters;

            // add normal sightSet of items to the targetset
            //
            senseSetIter.Reset();
            while (senseSetIter.MoveNext())
            {
                SensorTarget target = (SensorTarget)senseSetIter.Current;

                bool match = true;
                bool cursorFilterPresent = false;
                for (int indexFilter = 0; indexFilter < filters.Count; indexFilter++)
                {
                    Filter filter = filters[indexFilter] as Filter;
                    ClassificationFilter cursorFilter = filter as ClassificationFilter;
                    if (cursorFilter != null && cursorFilter.classification.IsCursor)
                    {
                        cursorFilterPresent = true;
                    }

                    if (!filter.MatchTarget(reflex, target))
                    {
                        match = false;
                        break;
                    }
                }
                if (match)
                {
                    if (!target.Classification.IsCursor || cursorFilterPresent)
                    {
                        reflex.targetSet.Add(target);
                    }
                }
            }

            if (ListeningForMusic(filters))
            {
                if (HearMusic(filters))
                {
                    SensorTarget sensorTarget = SensorTargetSpares.Alloc();
                    sensorTarget.Init(gameActor, Vector3.UnitZ, 0.0f);
                    reflex.targetSet.AddOrFree(sensorTarget);
                }
            }

            reflex.targetSet.Action = TestObjectSet(reflex);
            if (reflex.targetSet.Action)
            {
                foreach (SensorTarget targ in reflex.targetSet)
                {
                    gameActor.AddSoundLine(targ.GameThing);
                }
            }
        }
Exemplo n.º 7
0
 /// <summary>
 /// Remove all SensorTargets referencing 'thing'
 /// </summary>
 /// <param name="dropThing"></param>
 public void Remove(GameThing thing)
 {
     if (sensorTargets.ContainsKey(thing.UniqueNum))
     {
         SensorTarget target = sensorTargets[thing.UniqueNum];
         sensorTargets.Remove(thing.UniqueNum);
         target.UnRef();
         dirty = true;
     }
 }
Exemplo n.º 8
0
 public override bool MatchTarget(Reflex reflex, SensorTarget sensorTarget)
 {
     //if ((sensorCategory & Sensor.Category.Distance) != 0)
     {
         float range = GetRangeFromTweakSettings(reflex.Task.GameActor);
         bool  match = OperandCompare <float>(sensorTarget.Range, this.operand, range);
         return(match);
     }
     //return true; // not the right type, don't effect the filtering
 }
Exemplo n.º 9
0
 public override bool MatchTarget(Reflex reflex, SensorTarget sensorTarget)
 {
     // When checking a touchButton filter, the target no longer has a valid position, because
     // technically the button has no real place in the gameworld. We thus strip that data
     // from the target.
     sensorTarget.Position  = sensorTarget.GameThing.Movement.Position;
     sensorTarget.Range     = 0.0f;
     sensorTarget.Direction = Vector3.Zero;
     return(true);
 }
Exemplo n.º 10
0
 public override void FinishUpdate(GameActor gameActor)
 {
     if (gameActor.ThingBeingHeldByThisActor != null)
     {
         // presence is only thing important here
         SensorTarget target = SensorTargetSpares.Alloc();
         target.Init(gameActor, gameActor.ThingBeingHeldByThisActor);
         senseSet.AddOrFree(target);
     }
 }
Exemplo n.º 11
0
        public override void ComposeSensorTargetSet(GameActor gameActor, Reflex reflex)
        {
            List <Filter> filters = reflex.Filters;

            // add normal senseSet of items to the targetset
            //
            senseSetIter.Reset();
            while (senseSetIter.MoveNext())
            {
                SensorTarget target = (SensorTarget)senseSetIter.Current;

                bool match = true;
                bool cursorFilterPresent = false;
                for (int indexFilter = 0; indexFilter < filters.Count; indexFilter++)
                {
                    Filter filter = filters[indexFilter] as Filter;
                    ClassificationFilter cursorFilter = filter as ClassificationFilter;
                    if (cursorFilter != null && cursorFilter.classification.IsCursor)
                    {
                        cursorFilterPresent = true;
                    }

                    if (!filter.MatchTarget(reflex, target))
                    {
                        match = false;
                        break;
                    }
                }
                if (match)
                {
                    if (!target.Classification.IsCursor || cursorFilterPresent)
                    {
                        reflex.targetSet.Add(target);
                    }
                }
            }

            reflex.targetSet.Finialize();
            if (reflex.targetSet.Nearest == null)
            {
                /// Didn't come up with anything, try searching our memory
                if (SearchMemory(gameActor, reflex))
                {
                    /// Find nearest again, but don't check LOS. This matches old
                    /// behavior, which assumes that if we remember it, we could see it.
                    reflex.targetSet.Finialize();
                }
            }
            else
            {
                /// We got something, memorize it.
                gameActor.Brain.Memory.MemorizeThing(reflex.targetSet.Nearest.GameThing);
            }
            reflex.targetSet.Action = TestObjectSet(reflex);
        }   // end of ComposeSensorTargetSet()
Exemplo n.º 12
0
        public override void ComposeSensorTargetSet(GameActor gameActor, Reflex reflex)
        {
            List <Filter> filters = reflex.Filters;

            foreach (SensorTarget target in sightSet)
            {
                // Don't see things we are holding.
                if (target.GameThing == gameActor.ThingBeingHeldByThisActor)
                {
                    continue;
                }

                bool match = true;
                bool cursorFilterPresent = false;

                for (int indexFilter = 0; indexFilter < filters.Count; indexFilter++)
                {
                    Filter filter = filters[indexFilter] as Filter;
                    ClassificationFilter cursorFilter = filter as ClassificationFilter;
                    if (cursorFilter != null && cursorFilter.classification.IsCursor)
                    {
                        cursorFilterPresent = true;
                    }

                    if (!filter.MatchTarget(reflex, target))
                    {
                        match = false;
                        break;
                    }
                }
                if (match)
                {
                    if (!target.Classification.IsCursor || cursorFilterPresent)
                    {
                        reflex.targetSet.Add(target);
                    }
                }
            }


            reflex.targetSet.Action = TestObjectSet(reflex);

            if (reflex.targetSet.Action)
            {
                SensorTarget nearest = reflex.targetSet.Nearest;
                if (nearest != null)
                {
                    gameActor.AddSightLine(nearest.GameThing);
                }
            }
            else
            {
                reflex.targetSet.Clear();
            }
        }   // end of ComposeSensorTargetSet()
Exemplo n.º 13
0
        public bool Add(SensorTarget sensorTarget)
        {
            if (sensorTargets.ContainsKey(sensorTarget.GameThing.UniqueNum))
            {
                return(false);
            }

            sensorTargets.Add(sensorTarget.GameThing.UniqueNum, sensorTarget.Ref());
            dirty = true;

            return(true);
        }
Exemplo n.º 14
0
        public void Add(GameThing gameThing, Vector3 direction, float range)
        {
            if (sensorTargets.ContainsKey(gameThing.UniqueNum))
            {
                return;
            }

            SensorTarget target = SensorTargetSpares.Alloc();

            target.Init(gameThing, direction, range);
            sensorTargets.Add(gameThing.UniqueNum, target.Ref());
            dirty = true;
        }
Exemplo n.º 15
0
 /// <summary>
 /// Try adding to the set, if unsuccessful, free the SensorTarget.
 /// This is a shortcut for when you've just Alloc'd a sensor target,
 /// and then:
 ///   if(!Add(targ))
 ///     SensorTargetSpares.Release(targ);
 /// This is only appropriate where the target has just been alloc'd, so
 /// not iterating through a set, and is a local that will just fall out of scope.
 /// </summary>
 /// <param name="sensorTarget"></param>
 /// <returns>false if not added but freed, true if added</returns>
 public bool AddOrFree(SensorTarget sensorTarget)
 {
     Debug.Assert(sensorTarget.refs == 1, "Improper usage, use Add()?");
     if (!Add(sensorTarget))
     {
         if (sensorTarget.refs == 1)
         {
             SensorTargetSpares.Free(sensorTarget);
         }
         return(false);
     }
     return(true);
 }
Exemplo n.º 16
0
        public override bool MatchTarget(Reflex reflex, SensorTarget sensorTarget)
        {
            Vector3 actorPos = reflex.Task.GameActor.Movement.Position;

            actorPos.Z += reflex.Task.GameActor.EyeOffset;
            Vector3 actorFacing = reflex.Task.GameActor.Movement.Heading;
            Vector3 actorRight  = Vector3.Cross(actorFacing, Vector3.UnitZ);
            Vector3 targetPos   = sensorTarget.Position;

            if (sensorTarget.GameThing != null)
            {
                targetPos.Z += sensorTarget.GameThing.EyeOffset;
            }
            Vector3 toTarget = targetPos - actorPos;

            bool match = true;

            switch (upid)
            {
            case "filter.infront":
                match = Vector3.Dot(actorFacing, toTarget) >= 0;
                break;

            case "filter.behind":
                match = Vector3.Dot(actorFacing, toTarget) <= 0;
                break;

            case "filter.toleft":
                match = Vector3.Dot(actorRight, toTarget) <= 0;
                break;

            case "filter.toright":
                match = Vector3.Dot(actorRight, toTarget) >= 0;
                break;

            case "filter.over":
                match = toTarget.Z > 0;
                break;

            case "filter.under":
                match = toTarget.Z < 0;
                break;

            case "filter.lineofsight":
                Vector3 hit = Vector3.Zero;
                match = !Terrain.LOSCheckTerrainAndPath(actorPos, targetPos, ref hit);
                break;
            }

            return(match);
        }
Exemplo n.º 17
0
        /// <summary>
        /// Either sorts the full target list or just grabs the nearest target.
        /// Dependson whether this is called by Nearest or NearestTargets.
        /// </summary>
        /// <returns></returns>
        private void SortTargets(bool justGetFirst)
        {
            if (dirty)
            {
                nearestTargets.Clear();

                // Copy all non-ignored targets to list.
                foreach (SensorTarget target in sensorTargets.Values)
                {
                    if (target.GameThing != null || !target.GameThing.Ignored)
                    {
                        nearestTargets.Add(target);
                    }
                }

                if (justGetFirst)
                {
                    // Find the nearest target and copy into position 0.
                    // This leaves the nearest target at position 0 but
                    // leaves the rest of the list in kind of a mess so
                    // don't use it for anything else.
                    for (int i = 1; i < nearestTargets.Count; i++)
                    {
                        if (nearestTargets[0].Range > nearestTargets[i].Range)
                        {
                            nearestTargets[0] = nearestTargets[i];
                        }
                    }
                }
                else
                {
                    // Sort full list.  Rarely used and the general case
                    // will be a very short list so just bubble sort.
                    for (int i = 0; i < nearestTargets.Count - 1; i++)
                    {
                        for (int j = i + 1; j < nearestTargets.Count; j++)
                        {
                            if (nearestTargets[i].Range > nearestTargets[j].Range)
                            {
                                // Swap.
                                SensorTarget tmp = nearestTargets[i];
                                nearestTargets[i] = nearestTargets[j];
                                nearestTargets[j] = tmp;
                            }
                        }
                    }
                }
                dirty = false;
            } // end if dirty
        }     // end of SortTargets()
Exemplo n.º 18
0
        public override bool MatchTarget(Reflex reflex, SensorTarget sensorTarget)
        {
            bool result = false;

            // Try matching each line.
            for (int i = 0; i < reflex.Data.saidStrings.Count; i++)
            {
                bool atBeginning = reflex.Data.saidMode == 0;
                if (SaidStringManager.MatchText(sensorTarget.GameThing as GameActor, reflex.Data.saidStrings[i], atBeginning))
                {
                    result = true;
                    break;
                }
            }

            return(result);
        }
Exemplo n.º 19
0
        }   // end of c'tor

        public override bool MatchTarget(Reflex reflex, SensorTarget sensorTarget)
        {
            bool matched = false;

            if (sensorTarget.GameThing is NullActor)
            {
                return(matched); // Always false.
            }

            GameActor actor = sensorTarget.GameThing as GameActor;

            if (actor != null && actor.DisplayName == name)
            {
                matched = true;
            }

            return(matched);
        }   // end of MatchTarget()
Exemplo n.º 20
0
        public static SensorTarget Alloc()
        {
            SensorTarget target;

            if (spareSensorTargets.Count > 0)
            {
                int index = spareSensorTargets.Count - 1;
                target = spareSensorTargets[index];
                spareSensorTargets.RemoveAt(index);
            }
            else
            {
                target = new SensorTarget();
            }

            target.refs++;
            return(target);
        }
Exemplo n.º 21
0
        public override void FinishUpdate(GameActor gameActor)
        {
            if (terrainSensor != null)
            {
                //if (TouchEdit.HitInfo.TerrainHit)
                {
                    terrainSensor.OverrideSenseMaterial = TouchEdit.HitInfo.TerrainMaterial;
                }

                terrainSensor.FinishUpdate(gameActor);
            }
            else
            {
                if (TouchEdit.HitInfo.HaveActor)
                {
                    GameActor touchdActor = TouchEdit.HitInfo.ActorHit;

                    Vector3 actorCenter = Vector3.Transform(
                        gameActor.BoundingSphere.Center,
                        gameActor.Movement.LocalMatrix);

                    Vector3 thingCenter = Vector3.Transform(
                        touchdActor.BoundingSphere.Center,
                        touchdActor.Movement.LocalMatrix);

                    Vector3 direction = thingCenter - actorCenter;

                    float range = direction.Length();
                    if (range > 0.0f)
                    {
                        direction *= 1.0f / range; // Normalize.
                    }

                    SensorTarget target = SensorTargetSpares.Alloc();
                    target.Init(touchdActor, direction, range);
                    senseSet.AddOrFree(target);
                }

                senseSet.Add(NullActor.Instance, Vector3.Zero, float.MaxValue);
            }
        }
Exemplo n.º 22
0
        public override void ComposeSensorTargetSet(GameActor gameActor, Reflex reflex)
        {
            List <Filter> filters = reflex.Filters;

            SensorTargetSet.Enumerator beamedSetIter = gameActor.BeamedSetIter;
            beamedSetIter.Reset();
            while (beamedSetIter.MoveNext())
            {
                SensorTarget target = (SensorTarget)beamedSetIter.Current;

                bool match = true;
                bool cursorFilterPresent = false;

                for (int indexFilter = 0; indexFilter < filters.Count; indexFilter++)
                {
                    Filter filter = filters[indexFilter] as Filter;
                    ClassificationFilter cursorFilter = filter as ClassificationFilter;

                    if (cursorFilter != null && cursorFilter.classification.IsCursor)
                    {
                        cursorFilterPresent = true;
                    }

                    if (!filter.MatchTarget(reflex, target))
                    {
                        match = false;
                        break;
                    }
                }
                if (match)
                {
                    if (!target.Classification.IsCursor || cursorFilterPresent)
                    {
                        reflex.targetSet.Add(target);
                    }
                }
            }

            reflex.targetSet.Action = TestObjectSet(reflex);
        }
Exemplo n.º 23
0
        public override SensorTargetSet ComposeSensorTargetSet(GameActor gameActor, Reflex reflex)
        {
            List <Filter> filters = reflex.Filters;

            targetSet.Clear();

            for (int iSet = 0; iSet < heardSet.Count; iSet++)
            {
                bool         match = true;
                bool         cursorFilterPresent = false;
                SensorTarget target = heardSet[iSet];
                for (int indexFilter = 0; indexFilter < filters.Count; indexFilter++)
                {
                    Filter filter = filters[indexFilter] as Filter;
                    ClassificationFilter cursorFilter = filter as ClassificationFilter;
                    if (cursorFilter != null && cursorFilter.classification.IsCursor)
                    {
                        cursorFilterPresent = true;
                    }

                    if (!filter.MatchTarget(reflex, target, this.category))
                    {
                        match = false;
                        break;
                    }
                }
                if (match)
                {
                    if (!target.Classification.IsCursor || cursorFilterPresent)
                    {
                        targetSet.Add(target.Ref());
                    }
                }
            }

            targetSet.Finialize();
            targetSet.Action = TestObjectSet(reflex);
            return(targetSet);
        }
Exemplo n.º 24
0
        public int CompareTo(Object right)
        {
            if (right is SensorTarget)
            {
                SensorTarget rightTarget = right as SensorTarget;
                int          result      = 0;
                if (range < rightTarget.range)
                {
                    result = -1;
                }
                else if (range > rightTarget.range)
                {
                    result = 1;
                }
                else
                {
                    result = gameThing.CompareTo(rightTarget.gameThing);
                }
                return(result);
            }

            throw new ArgumentException("object is not a SensorTarget");
        }
 public override bool MatchTarget(Reflex reflex, SensorTarget sensorTarget)
 {
     return(false);
 }
Exemplo n.º 26
0
        public override ActionSet ComposeActionSet(Reflex reflex, GameActor gameActor)
        {
            ClearActionSet(actionSet);
            UpdateCanBlend(reflex);

            if (!reflex.targetSet.AnyAction)
            {
                return(actionSet);
            }

            Vector3   direction = Vector3.Zero; // This is either the direction to the nearest target or, if no target, the direction we want (forward, etc).
            GameThing gameThing = null;
            float     range     = 0.0f;

            // TODO (****) This was causing a null ref in the "Green Ghost V Looper" level
            // when the user pressed the mouse button to launch a wisp.  In that case the
            // targetSet has 1 element in it but it's not "valid" so it never goes into
            // the nearestTargets list, hence targetSet.Nearest is null.
            // Note I also pulled the Finalize call out of the if statement since Finialize(sic)
            // is what creates the nearestTargets list.
            // Still need to investigate the underlying cause.
            // Turns out to be an issue with Ghost.  Ghosted objects are "ignored" so not valid
            // for the Nearest list.  Should probably rethink how invisible and ghosted work.

            if (reflex.targetSet.Nearest != null && !(reflex.targetSet.Nearest.GameThing is NullActor))
            {
                // We have a "real" target.
                // The targetSet is in order by distance.
                // Pick the nearest member of the target set.
                SensorTarget target = reflex.targetSet.Nearest;

                direction = target.Direction;
                gameThing = target.GameThing;
                range     = target.Range;
            }
            else
            {
                // No explicit target.
                // This handles the case of WHEN GamePad AButton DO Shoot
                // where instead of having a target we just have a direction.
                if (reflex.targetSet.Param != null && reflex.targetSet.Param is Vector2)
                {
                    direction = new Vector3((Vector2)reflex.targetSet.Param, 0.0f);
                }
                else
                {
                    direction = Vector3.Zero;
                }
                gameThing = null;
                range     = 1.0f;
            }

            bool apply = reflex.ModifyHeading(gameActor, Modifier.ReferenceFrames.World, ref direction);

            if (apply)
            {
                // TODO (****) Probably need a TargetObject Action.
                // radius should be from object
                actionSet.AddActionTarget(Action.AllocAttractor(range, direction, gameThing, reflex), 0.4f);
            }

            return(actionSet);
        }
Exemplo n.º 27
0
 public override bool MatchTarget(Reflex reflex, SensorTarget sensorTarget)
 {
     return(true); // not the right type, don't effect the filtering
 }
Exemplo n.º 28
0
        public override bool MatchTarget(Reflex reflex, SensorTarget sensorTarget)
        {
            bool match = sensorTarget.GameThing.CurrentState == GameThing.State.Dead || sensorTarget.GameThing.PendingState == GameThing.State.Dead;

            return(match);
        }
Exemplo n.º 29
0
        public override void ComposeSensorTargetSet(GameActor gameActor, Reflex reflex)
        {
            if (terrainSensor != null)
            {
                terrainSensor.ComposeSensorTargetSet(gameActor, reflex);
            }
            else
            {
                List <Filter> filters = reflex.Filters;

                // The sensor will use the first TouchGestureFilter it finds. Since any given reflex
                // can only have a single one of these, this works well.
                TouchGestureFilter gestureFilter   = null;
                TouchButtonFilter  buttonFilter    = null;
                GUIButtonFilter    guiButtonFilter = null;

                for (int i = 0; i < filters.Count; i++)
                {
                    if (filters[i] is TouchGestureFilter)
                    {
                        Debug.Assert(null == gestureFilter);
                        gestureFilter = filters[i] as TouchGestureFilter;
                    }
                    if (filters[i] is TouchButtonFilter)
                    {
                        Debug.Assert(null == buttonFilter);
                        buttonFilter = filters[i] as TouchButtonFilter;
                    }
                    if (filters[i] is GUIButtonFilter)
                    {
                        Debug.Assert(null == guiButtonFilter);
                        guiButtonFilter = filters[i] as GUIButtonFilter;
                    }
                }

                //if we don't have a filter, do nothing
                if (null == gestureFilter &&
                    null == buttonFilter &&
                    null == guiButtonFilter)
                {
                    //Debug.Assert(false, "Did not find a touch filter for touch sensor.");
                    return;
                }

                // Cause the filter to detect what is under the touch cursor and set that information on the reflex.
                // MatchAction will be true if the TouchFilter passes but then we still need to filter on any other
                // filters including the ever annoying "not", "me" and "anything" filters.
                Object param       = null;
                bool   matchAction = false;

                bool notFilter      = reflex.Data.FilterExists("filter.not");
                bool anythingFilter = reflex.Data.FilterExists("filter.anything");

                if (gestureFilter != null)
                {
                    matchAction = gestureFilter.MatchAction(reflex, out param);
                }

                if (buttonFilter != null)
                {
                    // Make the actual on screen button visible if a reflex contains the touch button filter.
                    //TouchButtons.MakeVisible(buttonFilter.button);

                    matchAction = buttonFilter.MatchAction(reflex, out param);
                }

                if (guiButtonFilter != null)
                {
                    matchAction = guiButtonFilter.MatchAction(reflex, out param);
                }



                // Give the anythingFilter a chance to kill the action.
                if (anythingFilter && reflex.TouchActor == null)
                {
                    matchAction = false;
                }

                // Handle the "Not" filter
                if (notFilter)
                {
                    if (matchAction)
                    {
                        matchAction          = false;
                        reflex.TouchActor    = null;
                        reflex.TouchPosition = null;
                    }
                    else
                    {
                        matchAction = true;
                    }
                }

                bool touchCursorTarget = false;

                // We are moving towards a remembered target position if we're the movement actuator.
                // We do not require a match on the current frame to continue the movement.
                // Note, in the presence of a "Not" filter, there is no target to "not move" to, so this
                // is negated.
                // Also, support turning toward a remembered position.
                bool movingToTouchPos = (reflex.actuatorUpid == "actuator.movement" && !notFilter);
                movingToTouchPos |= (reflex.actuatorUpid == "actuator.turn" && !notFilter);

                if (movingToTouchPos && (reflex.TouchActor == reflex.Task.GameActor))
                {
                    // When moving with touch, going towards oneself doesn't make sense. By discarding
                    // the touch actor and using the terrain position, we have a better definition of this
                    // movement. This allows for small positional corrections around the target's bounding
                    // box as well as letting slide movements that begin on oneself to work.
                    reflex.TouchActor    = null;
                    reflex.TouchPosition = TouchEdit.HitInfo.TerrainPosition;
                }

                if (matchAction || movingToTouchPos)
                {
                    bool         validTarget = false;
                    SensorTarget target      = SensorTargetSpares.Alloc();
                    // If we have an actor touch target, check if it passes the filters.
                    // If not, null it out.
                    if (reflex.TouchActor != null)
                    {
                        // Create a target.
                        target.Init(reflex.Task.GameActor, reflex.TouchActor);
                        validTarget = true;
                    }
                    else
                    {
                        target.Init(reflex.Task.GameActor, reflex.Task.GameActor);
                        // If we've got a me filter and not TouchActor we've failed.
                        if (reflex.Data.FilterExists("filter.me"))
                        {
                            matchAction = false;
                        }

                        // NOTE: For classification purposes, if the user doesn't touch a particular actor,
                        // we create an 'empty' classification. This is because we need a classification object
                        // in order to do reflexes such as 'tap move blimp -> shoot'. If you don't tap an actor,
                        // it needs to compare the absence of an actor to the blimp.
                        if (reflex.TouchPosition != null)
                        {
                            // We need to add the touch position to the targetSet.
                            target.Classification = new Classification();
                            target.GameThing      = senseSet.Nearest.GameThing;
                            target.Position       = reflex.TouchPosition.Value;
                            target.Direction      = target.Position - reflex.Task.GameActor.Movement.Position;
                            target.Range          = target.Direction.Length();

                            // If we've arrived at the target position, clear MousePosition.
                            Vector2 dir2d = new Vector2(target.Direction.X, target.Direction.Y);
                            if (dir2d.LengthSquared() < 0.1f)
                            {
                                reflex.TouchPosition = null;
                            }

                            target.Direction /= target.Range;
                            touchCursorTarget = true;
                            validTarget       = true;
                        }
                        else
                        {
                            // We don't have an actor or a position. Only with an action match should we
                            // create a sensor target.
                            if (matchAction)
                            {
                                // Calc a fake position for this target.
                                GameActor actor = reflex.Task.GameActor;
                                Vector3   pos   = actor.Movement.Position;

                                target.Classification = new Classification();
                                target.GameThing      = senseSet.Nearest.GameThing;
                                target.Position       = pos;
                                target.Direction      = target.Position - reflex.Task.GameActor.Movement.Position;
                                target.Range          = target.Direction.Length();
                                target.Direction     /= target.Range;
                                validTarget           = true;
                            }
                        }
                    }

                    // Test the target against the filters.
                    if (validTarget)
                    {
                        for (int i = 0; i < filters.Count; i++)
                        {
                            if (!(filters[i] is TouchGestureFilter))
                            {
                                if (!filters[i].MatchTarget(reflex, target) ||
                                    !filters[i].MatchAction(reflex, out param))
                                {
                                    if (!notFilter)
                                    {
                                        // Failed a match on one of the filters and we don't have a negation
                                        // so null things out and short circuit.
                                        reflex.TouchActor = null;
                                        validTarget       = false;
                                        matchAction       = false;
                                        touchCursorTarget = false;
                                        break;
                                    }
                                }
                            }
                        }
                    }

                    // If we still have a target, add it to the target set.
                    if (validTarget)
                    {
                        reflex.targetSet.Add(target);
                    }
                    else
                    {
                        // Don't really need this target so free it.
                        SensorTargetSpares.Free(target);
                    }
                }

                reflex.targetSet.Action = reflex.targetSet.Count > 0; // && TestObjectSet(reflex);

                //reflex.targetSet.Action |= matchAction;

                // This forces the movement to keep going toward the clicked position/bot
                // even if the touch is no longer clicked.
                reflex.targetSet.ActionMouseTarget = touchCursorTarget;

                if (matchAction)
                {
                    bool postProcessCheck = PostProcessAction(matchAction, reflex);
                    if (!postProcessCheck)
                    {
                        // We matched the action, but it failed the post process check (used by "Once" modifier),
                        // so we clear the target set.
                        reflex.targetSet.Clear();
                    }
                }
            }
        }
        public override bool MatchTarget(Reflex reflex, SensorTarget sensorTarget)
        {
            if (sensorTarget.GameThing is NullActor)
            {
                return(false);
            }

            bool match = true;  // By default, don't filter.

            // Skip if no sensor category
            if (MatchType != ClassificationType.None)
            {
                switch (MatchType)
                {
                case ClassificationType.Object:
                    if (string.IsNullOrEmpty(classification.name))
                    {
                        match = true;
                    }
                    else if (classification.name == "bot")          // Handle "Any Bots" tile.
                    {
                        GameActor actor = sensorTarget.GameThing as GameActor;
                        if (actor == null || !actor.IsBot)
                        {
                            match = false;
                        }
                    }
                    else if (classification.name == "building")     // Handle "Any Building" tile.
                    {
                        GameActor actor = sensorTarget.GameThing as GameActor;
                        if (actor == null || !actor.IsBuilding)
                        {
                            match = false;
                        }
                    }
                    else
                    {
                        match = classification.name == sensorTarget.Classification.name;
                    }
                    break;

                case ClassificationType.Color:
                    match = classification.color == sensorTarget.Classification.color || classification.color == sensorTarget.Classification.glowColor;
                    break;

                case ClassificationType.PathColor:
                    //path color only matches if the color matches the last end of path color this actor has seen
                    if (sensorTarget.GameThing is GameActor)
                    {
                        match = classification.color == (sensorTarget.GameThing as GameActor).ReachedEOP;
                    }
                    else
                    {
                        match = false;
                    }

                    break;

                case ClassificationType.Expression:
                    match =
                        (classification.expression != Boku.SimWorld.Face.FaceState.NotApplicable && classification.expression == sensorTarget.Classification.expression) ||
                        (classification.emitter != ExpressModifier.Emitters.NotApplicable && classification.emitter == sensorTarget.Classification.emitter);
                    break;

                case ClassificationType.Moving:
                    match = sensorTarget.Movement.Velocity.LengthSquared() > 0.01f;
                    break;

                case ClassificationType.Camouflage:
                    match = sensorTarget.GameThing.Camouflaged;
                    break;

                default:
                    // If this fires you should probably put in a new case statement for ht6e new category.
                    Debug.Assert(false);
                    match = OnMatch(sensorTarget.Classification);
                    break;
                }
                // TODO (****) Remove this once we're sure the changes are
                // good so that we get decent perf in debug, too.

                /*
                 * if (classification.name != "building" && classification.name != "bot")
                 * {
                 *  Debug.Assert(match == OnMatch(sensorTarget.Classification), "Tell *** to fix.");
                 * }
                 */
            }

            return(match);
        }