Exemplo n.º 1
0
        public IList <IEntity> GetEntitiesUnderPosition(GridCoordinates coordinates)
        {
            // Find all the entities intersecting our click
            var mapCoords = coordinates.ToMap(_mapManager);
            var entities  = _entityManager.GetEntitiesIntersecting(mapCoords.MapId, mapCoords.Position);

            // Check the entities against whether or not we can click them
            var foundEntities = new List <(IEntity clicked, int drawDepth)>();

            foreach (var entity in entities)
            {
                if (entity.TryGetComponent <IClientClickableComponent>(out var component) &&
                    entity.Transform.IsMapTransform &&
                    component.CheckClick(coordinates.Position, out var drawDepthClicked))
                {
                    foundEntities.Add((entity, drawDepthClicked));
                }
            }

            if (foundEntities.Count == 0)
            {
                return(new List <IEntity>());
            }

            foundEntities.Sort(new ClickableEntityComparer());
            // 0 is the top element.
            foundEntities.Reverse();
            return(foundEntities.Select(a => a.clicked).ToList());
        }
Exemplo n.º 2
0
        private bool TryStartStructureConstruction(IEntity placingEnt, GridCoordinates loc, string prototypeName, Angle angle)
        {
            var prototype = _prototypeManager.Index <ConstructionPrototype>(prototypeName);

            if (!InteractionChecks.InRangeUnobstructed(placingEnt, loc.ToMap(_mapManager),
                                                       ignoredEnt: placingEnt, insideBlockerValid: prototype.CanBuildInImpassable))
            {
                return(false);
            }

            if (prototype.Stages.Count < 2)
            {
                throw new InvalidOperationException($"Prototype '{prototypeName}' does not have enough stages.");
            }

            var stage0 = prototype.Stages[0];

            if (!(stage0.Forward is ConstructionStepMaterial matStep))
            {
                throw new NotImplementedException();
            }

            // Try to find the stack with the material in the user's hand.
            var hands      = placingEnt.GetComponent <HandsComponent>();
            var activeHand = hands.GetActiveHand?.Owner;

            if (activeHand == null)
            {
                return(false);
            }

            if (!activeHand.TryGetComponent(out StackComponent stack) || !ConstructionComponent.MaterialStackValidFor(matStep, stack))
            {
                return(false);
            }

            if (!stack.Use(matStep.Amount))
            {
                return(false);
            }

            // OK WE'RE GOOD CONSTRUCTION STARTED.
            Get <AudioSystem>().PlayAtCoords("/Audio/items/deconstruct.ogg", loc);
            if (prototype.Stages.Count == 2)
            {
                // Exactly 2 stages, so don't make an intermediate frame.
                var ent = _serverEntityManager.SpawnEntity(prototype.Result, loc);
                ent.Transform.LocalRotation = angle;
            }
            else
            {
                var frame        = _serverEntityManager.SpawnEntity("structureconstructionframe", loc);
                var construction = frame.GetComponent <ConstructionComponent>();
                construction.Init(prototype);
                frame.Transform.LocalRotation = angle;
            }

            return(true);
        }
        public GridTargetSteeringRequest(GridCoordinates targetGrid, float arrivalDistance, float pathfindingProximity = 0.5f)
        {
            // Get it once up front so we the manager doesn't have to continuously get it
            var mapManager = IoCManager.Resolve <IMapManager>();

            TargetMap            = targetGrid.ToMap(mapManager);
            TargetGrid           = targetGrid;
            ArrivalDistance      = arrivalDistance;
            PathfindingProximity = pathfindingProximity;
        }
Exemplo n.º 4
0
        /// <inheritdoc />
        public IEnumerable <IEntity> GetEntitiesInArc(GridCoordinates coordinates, float range, Angle direction, float arcWidth)
        {
            var position = coordinates.ToMap(_mapManager).Position;

            foreach (var entity in GetEntitiesInRange(coordinates, range * 2))
            {
                var angle = new Angle(entity.Transform.WorldPosition - position);
                if (angle.Degrees < direction.Degrees + arcWidth / 2 && angle.Degrees > direction.Degrees - arcWidth / 2)
                {
                    yield return(entity);
                }
            }
        }
Exemplo n.º 5
0
        public static bool InRangeUnobstructed(
            this MapCoordinates origin,
            GridCoordinates other,
            float range = InteractionRange,
            CollisionGroup collisionMask = CollisionGroup.Impassable,
            Ignored predicate            = null,
            bool ignoreInsideBlocker     = false)
        {
            var mapManager    = IoCManager.Resolve <IMapManager>();
            var otherPosition = other.ToMap(mapManager);

            return(SharedInteractionSystem.InRangeUnobstructed(origin, otherPosition, range, collisionMask, predicate,
                                                               ignoreInsideBlocker));
        }
Exemplo n.º 6
0
        private bool HandleDrop(ICommonSession session, GridCoordinates coords, EntityUid uid)
        {
            var ent = ((IPlayerSession)session).AttachedEntity;

            if (ent == null || !ent.IsValid())
            {
                return(false);
            }

            if (!ent.TryGetComponent(out HandsComponent handsComp))
            {
                return(false);
            }

            if (handsComp.GetActiveHand == null)
            {
                return(false);
            }

            var interactionSystem = _entitySystemManager.GetEntitySystem <InteractionSystem>();

            if (interactionSystem.InRangeUnobstructed(coords.ToMap(_mapManager), ent.Transform.WorldPosition, 0f, ignoredEnt: ent))
            {
                if (coords.InRange(_mapManager, ent.Transform.GridPosition, InteractionSystem.InteractionRange))
                {
                    handsComp.Drop(handsComp.ActiveIndex, coords);
                }
                else
                {
                    var entCoords = ent.Transform.GridPosition.Position;
                    var entToDesiredDropCoords = coords.Position - entCoords;
                    var clampedDropCoords      = ((entToDesiredDropCoords.Normalized * InteractionSystem.InteractionRange) + entCoords);

                    handsComp.Drop(handsComp.ActiveIndex, new GridCoordinates(clampedDropCoords, coords.GridID));
                }
            }
            else
            {
                handsComp.Drop(handsComp.ActiveIndex, ent.Transform.GridPosition);
            }

            return(true);
        }
        /// <summary>
        ///     Checks that an entity and a set of grid 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 entity and component.
        /// </summary>
        /// <param name="origin">The entity to use.</param>
        /// <param name="other">The grid coordinates to use.</param>
        /// <param name="range">
        ///     Maximum distance between the two entity and set of grid coordinates.
        /// </param>
        /// <param name="collisionMask">The mask to check for collisions.</param>
        /// <param name="predicate">
        ///     A predicate to check whether to ignore an entity or not.
        ///     If it returns true, it will be ignored.
        /// </param>
        /// <param name="ignoreInsideBlocker">
        ///     If true and <see cref="origin"/> or <see cref="other"/> are inside
        ///     the obstruction, ignores the obstruction and considers the interaction
        ///     unobstructed.
        ///     Therefore, setting this to true makes this check more permissive,
        ///     such as allowing an interaction to occur inside something impassable
        ///     (like a wall). The default, false, makes the check more restrictive.
        /// </param>
        /// <param name="popup">
        ///     Whether or not to popup a feedback message on the origin entity for
        ///     it to see.
        /// </param>
        /// <returns>
        ///     True if the two points are within a given range without being obstructed.
        /// </returns>
        public bool InRangeUnobstructed(
            IEntity origin,
            GridCoordinates other,
            float range = InteractionRange,
            CollisionGroup collisionMask = CollisionGroup.Impassable,
            Ignored predicate            = null,
            bool ignoreInsideBlocker     = false,
            bool popup = false)
        {
            var originPosition = origin.Transform.MapPosition;
            var otherPosition  = other.ToMap(_mapManager);

            predicate ??= e => e == origin;

            var inRange = InRangeUnobstructed(originPosition, otherPosition, range, collisionMask, predicate, ignoreInsideBlocker);

            if (!inRange && popup)
            {
                var message = Loc.GetString("You can't reach there!");
                origin.PopupMessage(origin, message);
            }

            return(inRange);
        }
Exemplo n.º 8
0
 public IList <IEntity> GetEntitiesUnderPosition(GridCoordinates coordinates)
 {
     return(GetEntitiesUnderPosition(coordinates.ToMap(MapManager)));
 }
Exemplo n.º 9
0
        private bool HandleDrop(ICommonSession session, GridCoordinates coords, EntityUid uid)
        {
            var ent = ((IPlayerSession)session).AttachedEntity;

            if (ent == null || !ent.IsValid())
            {
                return(false);
            }

            if (!ent.TryGetComponent(out HandsComponent handsComp))
            {
                return(false);
            }

            if (handsComp.GetActiveHand == null)
            {
                return(false);
            }

            var entCoords = ent.Transform.GridPosition.Position;
            var entToDesiredDropCoords = coords.Position - entCoords;
            var targetLength           = Math.Min(entToDesiredDropCoords.Length, SharedInteractionSystem.InteractionRange - 0.001f); // InteractionRange is reduced due to InRange not dealing with floating point error
            var newCoords = new GridCoordinates((entToDesiredDropCoords.Normalized * targetLength) + entCoords, coords.GridID);
            var rayLength = Get <SharedInteractionSystem>().UnobstructedDistance(ent.Transform.MapPosition, newCoords.ToMap(_mapManager), ignoredEnt: ent);

            handsComp.Drop(handsComp.ActiveHand, new GridCoordinates(entCoords + (entToDesiredDropCoords.Normalized * rayLength), coords.GridID));

            return(true);
        }
Exemplo n.º 10
0
        /// <inheritdoc />
        public IEnumerable <IEntity> GetEntitiesIntersecting(GridCoordinates position, bool approximate = false)
        {
            var mapPos = position.ToMap(_mapManager);

            return(GetEntitiesIntersecting(mapPos.MapId, mapPos.Position, approximate));
        }
Exemplo n.º 11
0
        void TryStartStructureConstruction(GridCoordinates loc, string prototypeName, Angle angle, int ack)
        {
            var prototype = _prototypeManager.Index <ConstructionPrototype>(prototypeName);

            var transform = Owner.Transform;

            var interactionSystem = _entitySystemManager.GetEntitySystem <InteractionSystem>();

            if (!interactionSystem.InRangeUnobstructed(loc.ToMap(_mapManager), Owner.Transform.WorldPosition, ignoredEnt: Owner, insideBlockerValid: prototype.CanBuildInImpassable))
            {
                _notifyManager.PopupMessage(transform.GridPosition, Owner,
                                            _localizationManager.GetString("You can't reach there!"));
                return;
            }

            if (prototype.Stages.Count < 2)
            {
                throw new InvalidOperationException($"Prototype '{prototypeName}' does not have enough stages.");
            }

            var stage0 = prototype.Stages[0];

            if (!(stage0.Forward is ConstructionStepMaterial matStep))
            {
                throw new NotImplementedException();
            }

            // Try to find the stack with the material in the user's hand.
            var hands      = Owner.GetComponent <HandsComponent>();
            var activeHand = hands.GetActiveHand?.Owner;

            if (activeHand == null)
            {
                return;
            }

            if (!activeHand.TryGetComponent(out StackComponent stack) || !ConstructionComponent.MaterialStackValidFor(matStep, stack))
            {
                return;
            }

            if (!stack.Use(matStep.Amount))
            {
                return;
            }

            // OK WE'RE GOOD CONSTRUCTION STARTED.
            _entitySystemManager.GetEntitySystem <AudioSystem>().Play("/Audio/items/deconstruct.ogg", loc);
            if (prototype.Stages.Count == 2)
            {
                // Exactly 2 stages, so don't make an intermediate frame.
                var ent = _serverEntityManager.SpawnEntity(prototype.Result, loc);
                ent.Transform.LocalRotation = angle;
            }
            else
            {
                var frame        = _serverEntityManager.SpawnEntity("structureconstructionframe", loc);
                var construction = frame.GetComponent <ConstructionComponent>();
                construction.Init(prototype);
                frame.Transform.LocalRotation = angle;
            }

            var msg = new AckStructureConstructionMessage(ack);

            SendNetworkMessage(msg);
        }