Fix directional window blocking (#7270)
This commit is contained in:
@@ -45,6 +45,7 @@ namespace Content.Shared.Interaction
|
||||
[Dependency] private readonly RotateToFaceSystem _rotateToFaceSystem = default!;
|
||||
[Dependency] private readonly SharedPopupSystem _popupSystem = default!;
|
||||
[Dependency] private readonly UseDelaySystem _useDelay = default!;
|
||||
[Dependency] private readonly SharedPhysicsSystem _physicsSystem = default!;
|
||||
[Dependency] protected readonly SharedContainerSystem ContainerSystem = default!;
|
||||
|
||||
public const float InteractionRange = 2;
|
||||
@@ -438,22 +439,10 @@ namespace Content.Shared.Interaction
|
||||
CollisionGroup collisionMask = CollisionGroup.Impassable,
|
||||
Ignored? predicate = null,
|
||||
bool popup = false)
|
||||
{
|
||||
var originPosition = Transform(origin).MapPosition;
|
||||
var transform = Transform(other);
|
||||
var (position, rotation) = transform.GetWorldPositionRotation();
|
||||
var mapPos = new MapCoordinates(position, transform.MapID);
|
||||
var wallPredicate = AddAnchoredPredicate(other, mapPos, rotation, originPosition);
|
||||
{;
|
||||
Ignored combinedPredicate = e => e == origin || (predicate?.Invoke(e) ?? false);
|
||||
|
||||
Ignored combinedPredicate = e =>
|
||||
{
|
||||
return e == origin
|
||||
|| e == other
|
||||
|| (predicate?.Invoke(e) ?? false)
|
||||
|| (wallPredicate?.Invoke(e) ?? false);
|
||||
};
|
||||
|
||||
var inRange = InRangeUnobstructed(origin, mapPos, range, collisionMask, combinedPredicate, popup);
|
||||
var inRange = InRangeUnobstructed(Transform(origin).MapPosition, other, range, collisionMask, combinedPredicate);
|
||||
|
||||
if (!inRange && popup && _gameTiming.IsFirstTimePredicted)
|
||||
{
|
||||
@@ -475,56 +464,43 @@ namespace Content.Shared.Interaction
|
||||
var (position, rotation) = transform.GetWorldPositionRotation();
|
||||
var mapPos = new MapCoordinates(position, transform.MapID);
|
||||
|
||||
var wallPredicate = AddAnchoredPredicate(target, mapPos, rotation, origin);
|
||||
HashSet<EntityUid> ignored = new();
|
||||
|
||||
bool ignoreAnchored = false;
|
||||
|
||||
if (HasComp<SharedItemComponent>(target) && TryComp(target, out PhysicsComponent? physics) && physics.CanCollide)
|
||||
{
|
||||
// If the target is an item, we ignore any colliding entities. Currently done so that if items get stuck
|
||||
// inside of walls, users can still pick them up.
|
||||
ignored.UnionWith(_sharedBroadphaseSystem.GetEntitiesIntersectingBody(target, (int) collisionMask, false, physics));
|
||||
}
|
||||
else if (TryComp(target, out WallMountComponent? wallMount))
|
||||
{
|
||||
// wall-mount exemptions may be restricted to a specific angle range.da
|
||||
|
||||
if (wallMount.Arc >= Math.Tau)
|
||||
ignoreAnchored = true;
|
||||
else
|
||||
{
|
||||
var angle = Angle.FromWorldVec(origin.Position - position);
|
||||
var angleDelta = (wallMount.Direction + rotation - angle).Reduced().FlipPositive();
|
||||
ignoreAnchored = angleDelta < wallMount.Arc / 2 || Math.Tau - angleDelta < wallMount.Arc / 2;
|
||||
}
|
||||
|
||||
if (ignoreAnchored && _mapManager.TryFindGridAt(mapPos, out var grid))
|
||||
ignored.UnionWith(grid.GetAnchoredEntities(mapPos));
|
||||
}
|
||||
|
||||
Ignored combinedPredicate = e =>
|
||||
{
|
||||
return e == target
|
||||
|| (predicate?.Invoke(e) ?? false)
|
||||
|| (wallPredicate?.Invoke(e) ?? false);
|
||||
|| ignored.Contains(e);
|
||||
};
|
||||
|
||||
return InRangeUnobstructed(origin, mapPos, range, collisionMask, combinedPredicate);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// If the target entity is either an item or a wall-mounted object, this will add a predicate to ignore any
|
||||
/// anchored entities on that tile.
|
||||
/// </summary>
|
||||
public Ignored? AddAnchoredPredicate(
|
||||
EntityUid target,
|
||||
MapCoordinates targetPosition,
|
||||
Angle targetRotation,
|
||||
MapCoordinates origin)
|
||||
{
|
||||
if (!_mapManager.TryFindGridAt(targetPosition, out var grid))
|
||||
return null;
|
||||
|
||||
if (HasComp<SharedItemComponent>(target))
|
||||
{
|
||||
// Ignore anchored entities on that tile.
|
||||
var colliding = new HashSet<EntityUid>(grid.GetAnchoredEntities(targetPosition));
|
||||
return e => colliding.Contains(e);
|
||||
}
|
||||
|
||||
if (!TryComp(target, out WallMountComponent? wallMount))
|
||||
return null;
|
||||
|
||||
// wall-mount exemptions may be restricted to a specific angle range.
|
||||
if (wallMount.Arc < 360)
|
||||
{
|
||||
var angle = Angle.FromWorldVec(origin.Position - targetPosition.Position);
|
||||
var angleDelta = (wallMount.Direction + targetRotation - angle).Reduced().FlipPositive();
|
||||
var inArc = angleDelta < wallMount.Arc / 2 || Math.Tau - angleDelta < wallMount.Arc / 2;
|
||||
|
||||
if (!inArc)
|
||||
return null;
|
||||
}
|
||||
|
||||
// Ignore anchored entities on that tile.
|
||||
var ignored = new HashSet<EntityUid>(grid.GetAnchoredEntities(targetPosition));
|
||||
return e => ignored.Contains(e);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Checks that an entity and a set of grid coordinates are within a certain
|
||||
/// distance without any entity that matches the collision mask
|
||||
|
||||
Reference in New Issue
Block a user