/// <inheritdoc /> public IPlayingAudioStream Play(Filter playerFilter, string filename, EntityCoordinates coordinates, AudioParams?audioParams = null) { //TODO: Calculate this from PAS var range = audioParams is null || audioParams.Value.MaxDistance <= 0 ? AudioDistanceRange : audioParams.Value.MaxDistance; var id = CacheIdentifier(); var fallbackCoordinates = GetFallbackCoordinates(coordinates.ToMap(_entityManager)); var msg = new PlayAudioPositionalMessage { FileName = filename, Coordinates = coordinates, FallbackCoordinates = fallbackCoordinates, AudioParams = audioParams ?? AudioParams.Default, Identifier = id }; // We clone the filter here as to not modify the original instance. if (range > 0.0f) { playerFilter = playerFilter.Clone().AddInRange(coordinates.ToMap(EntityManager), range); } RaiseNetworkEvent(msg, playerFilter); return(new AudioSourceServer(this, id, playerFilter.Recipients.ToArray())); }
public static bool InRangeUnOccluded(IEntity origin, EntityCoordinates other, float range, Ignored?predicate, bool ignoreInsideBlocker = true) { var originPos = origin.Transform.MapPosition; var otherPos = other.ToMap(origin.EntityManager); return(InRangeUnOccluded(originPos, otherPos, range, predicate, ignoreInsideBlocker)); }
/// <inheritdoc /> public IPlayingAudioStream Play(Filter playerFilter, string filename, EntityCoordinates coordinates, AudioParams?audioParams = null) { //TODO: Calculate this from PAS var range = audioParams is null || audioParams.Value.MaxDistance <= 0 ? AudioDistanceRange : audioParams.Value.MaxDistance; var id = CacheIdentifier(); var msg = new PlayAudioPositionalMessage { FileName = filename, Coordinates = coordinates, AudioParams = audioParams ?? AudioParams.Default, Identifier = id }; IList <ICommonSession> players; var recipients = (playerFilter as IFilter).Recipients; if (range > 0.0f) { players = PasInRange(recipients, coordinates.ToMap(EntityManager), range); } else { players = recipients; } foreach (var player in players) { RaiseNetworkEvent(msg, player.ConnectedClient); } return(new AudioSourceServer(this, id, players)); }
public static bool InRangeUnOccluded(EntityUid origin, EntityCoordinates other, float range, Ignored?predicate, bool ignoreInsideBlocker = true) { var entMan = IoCManager.Resolve <IEntityManager>(); var originPos = entMan.GetComponent <TransformComponent>(origin).MapPosition; var otherPos = other.ToMap(entMan); return(InRangeUnOccluded(originPos, otherPos, range, predicate, ignoreInsideBlocker)); }
/// <summary> /// Returns the tile ref for a grid, or a map. /// </summary> public TileRef GetTileRef(EntityCoordinates coordinates) { var mapCoords = coordinates.ToMap(pManager.EntityManager); var gridId = coordinates.GetGridId(pManager.EntityManager); return(gridId.IsValid() ? pManager.MapManager.GetGrid(gridId).GetTileRef(MouseCoords) : new TileRef(mapCoords.MapId, gridId, MouseCoords.ToVector2i(pManager.EntityManager, pManager.MapManager), Tile.Empty)); }
/// <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="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( EntityUid origin, EntityCoordinates other, float range = InteractionRange, CollisionGroup collisionMask = CollisionGroup.Impassable, Ignored?predicate = null, bool popup = false) { return(InRangeUnobstructed(origin, other.ToMap(EntityManager), range, collisionMask, predicate, popup)); }
public GridTargetSteeringRequest(EntityCoordinates targetGrid, float arrivalDistance, float pathfindingProximity = 0.5f, bool requiresInRangeUnobstructed = false) { // Get it once up front so we the manager doesn't have to continuously get it var entityManager = IoCManager.Resolve <IEntityManager>(); TargetMap = targetGrid.ToMap(entityManager); TargetGrid = targetGrid; ArrivalDistance = arrivalDistance; PathfindingProximity = pathfindingProximity; RequiresInRangeUnobstructed = requiresInRangeUnobstructed; }
private bool OnCopy(ICommonSession?session, EntityCoordinates coords, EntityUid uid) { if (!CanSandbox()) { return(false); } // Try copy entity. if (uid.IsValid() && EntityManager.TryGetComponent(uid, out MetaDataComponent? comp) && !comp.EntityDeleted) { if (comp.EntityPrototype == null || comp.EntityPrototype.NoSpawn || comp.EntityPrototype.Abstract) { return(false); } if (_placementManager.Eraser) { _placementManager.ToggleEraser(); } _placementManager.BeginPlacing(new() { EntityType = comp.EntityPrototype.ID, IsTile = false, TileType = 0, PlacementOption = comp.EntityPrototype.PlacementMode }); return(true); } // Try copy tile. if (!_mapManager.TryFindGridAt(coords.ToMap(EntityManager), out var grid) || !grid.TryGetTileRef(coords, out var tileRef)) { return(false); } if (_placementManager.Eraser) { _placementManager.ToggleEraser(); } _placementManager.BeginPlacing(new() { EntityType = null, IsTile = true, TileType = tileRef.Tile.TypeId, PlacementOption = nameof(AlignTileAny) }); return(true); }
public static bool InRangeUnOccluded( this EntityCoordinates origin, IContainer other, float range = InteractionRange, Ignored?predicate = null, bool ignoreInsideBlocker = true) { var originPosition = origin.ToMap(other.Owner.EntityManager); var otherPosition = other.Owner.Transform.MapPosition; return(ExamineSystemShared.InRangeUnOccluded(originPosition, otherPosition, range, predicate, ignoreInsideBlocker)); }
public static bool InRangeUnobstructed( this EntityCoordinates origin, IContainer other, float range = InteractionRange, CollisionGroup collisionMask = CollisionGroup.Impassable, Ignored?predicate = null, bool ignoreInsideBlocker = false) { var originPosition = origin.ToMap(IoCManager.Resolve <IEntityManager>()); var otherPosition = IoCManager.Resolve <IEntityManager>().GetComponent <TransformComponent>(other.Owner).MapPosition; return(SharedInteractionSystem.InRangeUnobstructed(originPosition, otherPosition, range, collisionMask, predicate, ignoreInsideBlocker)); }
public static bool InRangeUnOccluded( this EntityCoordinates origin, IContainer other, float range = InteractionRange, Ignored?predicate = null, bool ignoreInsideBlocker = true) { var entMan = IoCManager.Resolve <IEntityManager>(); var originPosition = origin.ToMap(entMan); var otherPosition = entMan.GetComponent <TransformComponent>(other.Owner).MapPosition; return(ExamineSystemShared.InRangeUnOccluded(originPosition, otherPosition, range, predicate, ignoreInsideBlocker)); }
public static bool InRangeUnobstructed( this EntityCoordinates origin, IEntity other, float range = InteractionRange, CollisionGroup collisionMask = CollisionGroup.Impassable, Ignored?predicate = null, bool ignoreInsideBlocker = false) { var originPosition = origin.ToMap(other.EntityManager); var otherPosition = other.Transform.MapPosition; return(SharedInteractionSystem.InRangeUnobstructed(originPosition, otherPosition, range, collisionMask, predicate, ignoreInsideBlocker)); }
public static bool InRangeUnobstructed( this MapCoordinates origin, EntityCoordinates other, float range = InteractionRange, CollisionGroup collisionMask = CollisionGroup.Impassable, Ignored predicate = null, bool ignoreInsideBlocker = false) { var entityManager = IoCManager.Resolve <IEntityManager>(); var otherPosition = other.ToMap(entityManager); return(SharedInteractionSystem.InRangeUnobstructed(origin, otherPosition, range, collisionMask, predicate, ignoreInsideBlocker)); }
public bool IsColliding(EntityCoordinates coordinates) { var bounds = pManager.ColliderAABB; var mapCoords = coordinates.ToMap(pManager.EntityManager); var(x, y) = mapCoords.Position; var collisionBox = Box2.FromDimensions( bounds.Left + x, bounds.Bottom + y, bounds.Width, bounds.Height); return(pManager.PhysicsManager.TryCollideRect(collisionBox, mapCoords.MapId)); }
public static bool InRangeUnOccluded( this MapCoordinates origin, EntityCoordinates other, float range = InteractionRange, Ignored?predicate = null, bool ignoreInsideBlocker = true, IEntityManager?entityManager = null) { IoCManager.Resolve(ref entityManager); var otherPosition = other.ToMap(entityManager); return(ExamineSystemShared.InRangeUnOccluded(origin, otherPosition, range, predicate, ignoreInsideBlocker)); }
/// <inheritdoc /> public IEnumerable <IEntity> GetEntitiesInArc(EntityCoordinates coordinates, float range, Angle direction, float arcWidth, bool approximate = false) { var position = coordinates.ToMap(this).Position; foreach (var entity in GetEntitiesInRange(coordinates, range * 2, approximate)) { 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 bool Condition(EntityUid user, EntityCoordinates location, Direction direction) { var entManager = IoCManager.Resolve <IEntityManager>(); // get blueprint and user position var userWorldPosition = entManager.GetComponent <TransformComponent>(user).WorldPosition; var objWorldPosition = location.ToMap(entManager).Position; // find direction from user to blueprint var userToObject = (objWorldPosition - userWorldPosition); // get direction of the grid being placed on as an offset. var gridRotation = entManager.GetComponent <TransformComponent>(location.EntityId).WorldRotation; var directionWithOffset = gridRotation.RotateVec(direction.ToVec()); // dot product will be positive if user direction and blueprint are co-directed var dotProd = Vector2.Dot(directionWithOffset.Normalized, userToObject.Normalized); if (dotProd > 0) { return(false); } // now we need to check that user actually tries to build wallmount on a wall var physics = EntitySystem.Get <SharedPhysicsSystem>(); var rUserToObj = new CollisionRay(userWorldPosition, userToObject.Normalized, (int)CollisionGroup.Impassable); var length = userToObject.Length; var tagSystem = EntitySystem.Get <TagSystem>(); var userToObjRaycastResults = physics.IntersectRayWithPredicate(entManager.GetComponent <TransformComponent>(user).MapID, rUserToObj, maxLength: length, predicate: (e) => !tagSystem.HasTag(e, "Wall")); var targetWall = userToObjRaycastResults.FirstOrNull(); if (targetWall == null) { return(false); } // get this wall entity // check that we didn't try to build wallmount that facing another adjacent wall var rAdjWall = new CollisionRay(objWorldPosition, directionWithOffset.Normalized, (int)CollisionGroup.Impassable); var adjWallRaycastResults = physics.IntersectRayWithPredicate(entManager.GetComponent <TransformComponent>(user).MapID, rAdjWall, maxLength: 0.5f, predicate: (e) => e == targetWall.Value.HitEntity || !tagSystem.HasTag(e, "Wall")); return(!adjWallRaycastResults.Any()); }
/// <inheritdoc /> public IPlayingAudioStream Play(Filter playerFilter, string filename, EntityCoordinates coordinates, AudioParams?audioParams = null) { var id = CacheIdentifier(); var fallbackCoordinates = GetFallbackCoordinates(coordinates.ToMap(_entityManager)); var msg = new PlayAudioPositionalMessage { FileName = filename, Coordinates = coordinates, FallbackCoordinates = fallbackCoordinates, AudioParams = audioParams ?? AudioParams.Default, Identifier = id }; RaiseNetworkEvent(msg, playerFilter); return(new AudioSourceServer(this, id, playerFilter.Recipients.ToArray())); }
public bool Condition(IEntity user, EntityCoordinates location, Direction direction) { var entManager = IoCManager.Resolve <IEntityManager>(); // get blueprint and user position var userWorldPosition = user.Transform.WorldPosition; var objWorldPosition = location.ToMap(entManager).Position; // find direction from user to blueprint var userToObject = (objWorldPosition - userWorldPosition); // dot product will be positive if user direction and blueprint are co-directed var dotProd = Vector2.Dot(direction.ToVec(), userToObject); if (dotProd > 0) { return(false); } // now we need to check that user actually tries to build wallmount on a wall var physics = EntitySystem.Get <SharedBroadphaseSystem>(); var rUserToObj = new CollisionRay(userWorldPosition, userToObject.Normalized, (int)CollisionGroup.Impassable); var length = userToObject.Length; var userToObjRaycastResults = physics.IntersectRayWithPredicate(user.Transform.MapID, rUserToObj, maxLength: length, predicate: (e) => !e.HasTag("Wall")); if (!userToObjRaycastResults.Any()) { return(false); } // get this wall entity var targetWall = userToObjRaycastResults.First().HitEntity; // check that we didn't try to build wallmount that facing another adjacent wall var rAdjWall = new CollisionRay(objWorldPosition, direction.ToVec(), (int)CollisionGroup.Impassable); var adjWallRaycastResults = physics.IntersectRayWithPredicate(user.Transform.MapID, rAdjWall, maxLength: 0.5f, predicate: (e) => e == targetWall || !e.HasTag("Wall")); return(!adjWallRaycastResults.Any()); }
/// <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, EntityCoordinates 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(EntityManager); 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(message); } return(inRange); }
public IGridAtmosphereComponent GetGridAtmosphere(EntityCoordinates coordinates) { return(GetGridAtmosphere(coordinates.ToMap(EntityManager))); }
/// <inheritdoc /> public IEnumerable <IEntity> GetEntitiesIntersecting(EntityCoordinates position, bool approximate = false) { var mapPos = position.ToMap(this); return(GetEntitiesIntersecting(mapPos.MapId, mapPos.Position, approximate)); }
public override void Shoot(GunComponent gun, List <IShootable> ammo, EntityCoordinates fromCoordinates, EntityCoordinates toCoordinates, EntityUid?user = null) { var fromMap = fromCoordinates.ToMap(EntityManager); var toMap = toCoordinates.ToMapPos(EntityManager); var mapDirection = toMap - fromMap.Position; var mapAngle = mapDirection.ToAngle(); var angle = GetRecoilAngle(Timing.CurTime, gun, mapDirection.ToAngle()); // Update shot based on the recoil toMap = fromMap.Position + angle.ToVec() * mapDirection.Length; mapDirection = toMap - fromMap.Position; var entityDirection = Transform(fromCoordinates.EntityId).InvWorldMatrix.Transform(toMap) - fromCoordinates.Position; // I must be high because this was getting tripped even when true. // DebugTools.Assert(direction != Vector2.Zero); var shotProjectiles = new List <EntityUid>(ammo.Count); foreach (var shootable in ammo) { switch (shootable) { // Cartridge shoots something else case CartridgeAmmoComponent cartridge: if (!cartridge.Spent) { if (cartridge.Count > 1) { var angles = LinearSpread(mapAngle - cartridge.Spread / 2, mapAngle + cartridge.Spread / 2, cartridge.Count); for (var i = 0; i < cartridge.Count; i++) { var uid = Spawn(cartridge.Prototype, fromCoordinates); ShootProjectile(uid, angles[i].ToVec(), user); shotProjectiles.Add(uid); } } else { var uid = Spawn(cartridge.Prototype, fromCoordinates); ShootProjectile(uid, mapDirection, user); shotProjectiles.Add(uid); } SetCartridgeSpent(cartridge, true); MuzzleFlash(gun.Owner, cartridge, user); PlaySound(gun.Owner, gun.SoundGunshot?.GetSound(Random, ProtoManager), user); if (cartridge.DeleteOnSpawn) { Del(cartridge.Owner); } } else { PlaySound(gun.Owner, gun.SoundEmpty?.GetSound(Random, ProtoManager), user); } // Something like ballistic might want to leave it in the container still if (!cartridge.DeleteOnSpawn && !Containers.IsEntityInContainer(cartridge.Owner)) { EjectCartridge(cartridge.Owner); } Dirty(cartridge); break; // Ammo shoots itself case AmmoComponent newAmmo: shotProjectiles.Add(newAmmo.Owner); MuzzleFlash(gun.Owner, newAmmo, user); PlaySound(gun.Owner, gun.SoundGunshot?.GetSound(Random, ProtoManager), user); // Do a throw if (!HasComp <ProjectileComponent>(newAmmo.Owner)) { RemComp <AmmoComponent>(newAmmo.Owner); // TODO: Someone can probably yeet this a billion miles so need to pre-validate input somewhere up the call stack. ThrowingSystem.TryThrow(newAmmo.Owner, mapDirection, 20f, user); break; } ShootProjectile(newAmmo.Owner, mapDirection, user); break; case HitscanPrototype hitscan: var ray = new CollisionRay(fromMap.Position, mapDirection.Normalized, hitscan.CollisionMask); var rayCastResults = Physics.IntersectRay(fromMap.MapId, ray, hitscan.MaxLength, user, false).ToList(); if (rayCastResults.Count >= 1) { var result = rayCastResults[0]; var distance = result.Distance; FireEffects(fromCoordinates, distance, entityDirection.ToAngle(), hitscan, result.HitEntity); var dmg = hitscan.Damage; if (dmg != null) { dmg = Damageable.TryChangeDamage(result.HitEntity, dmg); } if (dmg != null) { PlayImpactSound(result.HitEntity, dmg, hitscan.Sound, hitscan.ForceSound); if (user != null) { Logs.Add(LogType.HitScanHit, $"{ToPrettyString(user.Value):user} hit {ToPrettyString(result.HitEntity):target} using hitscan and dealt {dmg.Total:damage} damage"); } else { Logs.Add(LogType.HitScanHit, $"Hit {ToPrettyString(result.HitEntity):target} using hitscan and dealt {dmg.Total:damage} damage"); } } } else { FireEffects(fromCoordinates, hitscan.MaxLength, entityDirection.ToAngle(), hitscan); } PlaySound(gun.Owner, gun.SoundGunshot?.GetSound(Random, ProtoManager), user); break; default: throw new ArgumentOutOfRangeException(); } } RaiseLocalEvent(gun.Owner, new AmmoShotEvent() { FiredProjectiles = shotProjectiles, }, false); }
/// <summary> /// Gets all players inside of a circle. /// </summary> /// <param name="worldPos">Position of the circle in world-space.</param> /// <param name="range">Radius of the circle in world units.</param> /// <returns></returns> public List <IPlayerSession> GetPlayersInRange(EntityCoordinates worldPos, int range) { return(GetPlayersInRange(worldPos.ToMap(_entityManager), range)); }
public IList <IEntity> GetEntitiesUnderPosition(EntityCoordinates coordinates) { return(GetEntitiesUnderPosition(coordinates.ToMap(EntityManager))); }