Fix directional window blocking (#7270)

This commit is contained in:
Leon Friedrich
2022-04-02 16:11:16 +13:00
committed by GitHub
parent 8eee60da3a
commit 2884de06b6
3 changed files with 38 additions and 58 deletions

View File

@@ -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