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()); }
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; }
/// <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); } } }
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)); }
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); }
public IList <IEntity> GetEntitiesUnderPosition(GridCoordinates coordinates) { return(GetEntitiesUnderPosition(coordinates.ToMap(MapManager))); }
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); }
/// <inheritdoc /> public IEnumerable <IEntity> GetEntitiesIntersecting(GridCoordinates position, bool approximate = false) { var mapPos = position.ToMap(_mapManager); return(GetEntitiesIntersecting(mapPos.MapId, mapPos.Position, approximate)); }
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); }