private void IdleState()
        {
            if (!ActionBlockerSystem.CanMove(SelfEntity))
            {
                DisabledPositiveEdge();
                return;
            }

            if (_timeMan.CurTime < _startStateTime + IdleTimeSpan)
            {
                return;
            }

            var entWorldPos = SelfEntity.Transform.WorldPosition;

            if (SelfEntity.TryGetComponent <CollidableComponent>(out var bounds))
            {
                entWorldPos = ((IPhysBody)bounds).WorldAABB.Center;
            }

            var rngState = GenSeed();

            for (var i = 0; i < 3; i++) // you get 3 chances to find a place to walk
            {
                var dir        = new Vector2(Random01(ref rngState) * 2 - 1, Random01(ref rngState) * 2 - 1).Normalized;
                var ray        = new CollisionRay(entWorldPos, dir, (int)CollisionGroup.Impassable);
                var rayResults = _physMan.IntersectRay(SelfEntity.Transform.MapID, ray, MaxWalkDistance, SelfEntity).ToList();

                if (rayResults.Count == 1)
                {
                    var rayResult = rayResults[0];
                    if (rayResult.Distance > 1) // hit an impassable object
                    {
                        // set the new position back from the wall a bit
                        _walkTargetPos = entWorldPos + dir * (rayResult.Distance - 0.5f);
                        WalkingPositiveEdge();
                        return;
                    }
                }
                else // hit nothing (path clear)
                {
                    _walkTargetPos = dir * MaxWalkDistance;
                    WalkingPositiveEdge();
                    return;
                }
            }

            // can't find clear spot, do nothing, sleep longer
            _startStateTime = _timeMan.CurTime;
        }
示例#2
0
        /// <summary>
        ///     Checks that these coordinates are within a certain distance without any
        ///     entity that matches the collision mask obstructing them.
        ///     If the <paramref name="range"/> is zero or negative,
        ///     this method will only check if nothing obstructs the two sets of coordinates..
        /// </summary>
        /// <param name="mapManager">Map manager containing the two GridIds.</param>
        /// <param name="coords">Set of coordinates to use.</param>
        /// <param name="otherCoords">Other set of coordinates to use.</param>
        /// <param name="range">maximum distance between the two sets of coordinates.</param>
        /// <param name="collisionMask">the mask to check for collisions</param>
        /// <param name="ignoredEnt">the entity to be ignored when checking for collisions.</param>
        /// <returns>True if the two points are within a given range without being obstructed.</returns>
        public bool InRangeUnobstructed(GridCoordinates coords, GridCoordinates otherCoords, float range = InteractionRange, int collisionMask = (int)CollisionGroup.Impassable, IEntity ignoredEnt = null)
        {
            if (range > 0f && !coords.InRange(_mapManager, otherCoords, range))
            {
                return(false);
            }

            var dir = (otherCoords.Position - coords.Position);

            if (!(dir.Length > 0f))
            {
                return(true);
            }
            var ray        = new CollisionRay(coords.Position, dir.Normalized, collisionMask);
            var rayResults = _physicsManager.IntersectRay(_mapManager.GetGrid(coords.GridID).ParentMapId, ray, dir.Length, ignoredEnt);

            return(!rayResults.DidHitObject);
        }
        /// <summary>
        ///     Checks that these coordinates are within a certain distance without any
        ///     entity that matches the collision mask obstructing them.
        ///     If the <paramref name="range"/> is zero or negative,
        ///     this method will only check if nothing obstructs the two sets of coordinates..
        /// </summary>
        /// <param name="coords">Set of coordinates to use.</param>
        /// <param name="otherCoords">Other set of coordinates to use.</param>
        /// <param name="range">maximum distance between the two sets of coordinates.</param>
        /// <param name="collisionMask">the mask to check for collisions</param>
        /// <param name="ignoredEnt">the entity to be ignored when checking for collisions.</param>
        /// <param name="mapManager">Map manager containing the two GridIds.</param>
        /// <param name="insideBlockerValid">if coordinates inside obstructions count as obstructed or not</param>
        /// <returns>True if the two points are within a given range without being obstructed.</returns>
        public bool InRangeUnobstructed(MapCoordinates coords, Vector2 otherCoords, float range = InteractionRange,
                                        int collisionMask = (int)CollisionGroup.Impassable, IEntity ignoredEnt = null, bool insideBlockerValid = false)
        {
            var dir = otherCoords - coords.Position;

            if (dir.LengthSquared.Equals(0f))
            {
                return(true);
            }

            if (range > 0f && !(dir.LengthSquared <= range * range))
            {
                return(false);
            }

            var ray        = new CollisionRay(coords.Position, dir.Normalized, collisionMask);
            var rayResults = _physicsManager.IntersectRay(coords.MapId, ray, dir.Length, ignoredEnt, true);



            return(!rayResults.DidHitObject || (insideBlockerValid && rayResults.DidHitObject && rayResults.Distance < 1f));
        }
示例#4
0
        private HashSet <IEntity> ArcRayCast(Vector2 position, Angle angle, IEntity ignore)
        {
            var widthRad   = Angle.FromDegrees(ArcWidth);
            var increments = 1 + 35 * (int)Math.Ceiling(widthRad / (2 * Math.PI));
            var increment  = widthRad / increments;
            var baseAngle  = angle - widthRad / 2;

            var resSet = new HashSet <IEntity>();

            var mapId = Owner.Transform.MapID;

            for (var i = 0; i < increments; i++)
            {
                var castAngle = new Angle(baseAngle + increment * i);
                var res       = _physicsManager.IntersectRay(mapId, new CollisionRay(position, castAngle.ToVec(), (int)(CollisionGroup.Impassable | CollisionGroup.MobImpassable)), Range, ignore).FirstOrDefault();
                if (res.HitEntity != null)
                {
                    resSet.Add(res.HitEntity);
                }
            }

            return(resSet);
        }
        private IEntity FindBestTarget()
        {
            // "best" target is the closest one with LOS

            var ents        = _entMan.GetEntitiesInRange(SelfEntity, VisionRadius);
            var myTransform = SelfEntity.GetComponent <ITransformComponent>();
            var maxRayLen   = VisionRadius * 2.5f; // circle inscribed in square, square diagonal = 2*r*sqrt(2)

            _workList.Clear();
            foreach (var entity in ents)
            {
                // filter to "people" entities (entities with controllers)
                if (!entity.HasComponent <IMoverComponent>())
                {
                    continue;
                }

                // build the ray
                var dir = entity.GetComponent <ITransformComponent>().WorldPosition - myTransform.WorldPosition;
                var ray = new Ray(myTransform.WorldPosition, dir.Normalized, (int)(CollisionGroup.MobImpassable | CollisionGroup.Impassable));

                // cast the ray
                var result = _physMan.IntersectRay(myTransform.MapID, ray, maxRayLen, SelfEntity);

                // add to visible list
                if (result.HitEntity == entity)
                {
                    _workList.Add(entity);
                }
            }

            // get closest entity in list
            var closestEnt = GetClosest(myTransform.WorldPosition, _workList);

            // return closest
            return(closestEnt);
        }