Refactor InRangeUnobstructed and add extension methods (#1925)
* Sort out InRangeUnobstructed and add extension methods * Rename client RangeChecks to RangeExtensions * Add container extension methods and test * Add missing component methods Component to container Grid coordinates to container Map coordinates to container Local player to container * Actually use the field * Merge fixes * Add popup argument to local player extension methods * Reduce code repetition for client range extensions
This commit is contained in:
@@ -142,8 +142,7 @@ namespace Content.Client.GameObjects.EntitySystems
|
|||||||
if (_entityManager.TryGetEntity(args.EntityUid, out var entity))
|
if (_entityManager.TryGetEntity(args.EntityUid, out var entity))
|
||||||
{
|
{
|
||||||
// check if the entity is reachable
|
// check if the entity is reachable
|
||||||
if (_interactionSystem.InRangeUnobstructed(dragger.Transform.MapPosition,
|
if (!_interactionSystem.InRangeUnobstructed(dragger, entity))
|
||||||
entity.Transform.MapPosition, ignoredEnt: dragger) == false)
|
|
||||||
{
|
{
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
@@ -193,8 +192,8 @@ namespace Content.Client.GameObjects.EntitySystems
|
|||||||
// tell the server we are dropping if we are over a valid drop target in range.
|
// tell the server we are dropping if we are over a valid drop target in range.
|
||||||
// We don't use args.EntityUid here because drag interactions generally should
|
// We don't use args.EntityUid here because drag interactions generally should
|
||||||
// work even if there's something "on top" of the drop target
|
// work even if there's something "on top" of the drop target
|
||||||
if (_interactionSystem.InRangeUnobstructed(_dragger.Transform.MapPosition,
|
if (!_interactionSystem.InRangeUnobstructed(_dragger,
|
||||||
args.Coordinates.ToMap(_mapManager), ignoredEnt: _dragger, ignoreInsideBlocker: true) == false)
|
args.Coordinates, ignoreInsideBlocker: true))
|
||||||
{
|
{
|
||||||
CancelDrag(false, null);
|
CancelDrag(false, null);
|
||||||
return false;
|
return false;
|
||||||
@@ -288,8 +287,7 @@ namespace Content.Client.GameObjects.EntitySystems
|
|||||||
if (anyValidDraggable)
|
if (anyValidDraggable)
|
||||||
{
|
{
|
||||||
// highlight depending on whether its in or out of range
|
// highlight depending on whether its in or out of range
|
||||||
var inRange = _interactionSystem.InRangeUnobstructed(_dragger.Transform.MapPosition,
|
var inRange = _interactionSystem.InRangeUnobstructed(_dragger, pvsEntity);
|
||||||
pvsEntity.Transform.MapPosition, ignoredEnt: _dragger);
|
|
||||||
inRangeSprite.PostShader = inRange ? _dropTargetInRangeShader : _dropTargetOutOfRangeShader;
|
inRangeSprite.PostShader = inRange ? _dropTargetInRangeShader : _dropTargetOutOfRangeShader;
|
||||||
inRangeSprite.RenderOrder = EntityManager.CurrentTick.Value;
|
inRangeSprite.RenderOrder = EntityManager.CurrentTick.Value;
|
||||||
highlightedSprites.Add(inRangeSprite);
|
highlightedSprites.Add(inRangeSprite);
|
||||||
@@ -377,8 +375,7 @@ namespace Content.Client.GameObjects.EntitySystems
|
|||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
// still in range of the thing we are dragging?
|
// still in range of the thing we are dragging?
|
||||||
if (_interactionSystem.InRangeUnobstructed(_dragger.Transform.MapPosition,
|
if (!_interactionSystem.InRangeUnobstructed(_dragger, _draggedEntity))
|
||||||
_draggedEntity.Transform.MapPosition, ignoredEnt: _dragger) == false)
|
|
||||||
{
|
{
|
||||||
CancelDrag(false, null);
|
CancelDrag(false, null);
|
||||||
return;
|
return;
|
||||||
|
|||||||
@@ -1,6 +1,7 @@
|
|||||||
using Content.Client.GameObjects.Components.Instruments;
|
using Content.Client.GameObjects.Components.Instruments;
|
||||||
using Content.Client.UserInterface.Stylesheets;
|
using Content.Client.UserInterface.Stylesheets;
|
||||||
using Content.Shared.GameObjects.EntitySystems;
|
using Content.Client.Utility;
|
||||||
|
using Content.Shared.Utility;
|
||||||
using Robust.Client.Audio.Midi;
|
using Robust.Client.Audio.Midi;
|
||||||
using Robust.Client.Graphics.Drawing;
|
using Robust.Client.Graphics.Drawing;
|
||||||
using Robust.Client.Interfaces.UserInterface;
|
using Robust.Client.Interfaces.UserInterface;
|
||||||
@@ -9,7 +10,6 @@ using Robust.Client.UserInterface;
|
|||||||
using Robust.Client.UserInterface.Controls;
|
using Robust.Client.UserInterface.Controls;
|
||||||
using Robust.Client.UserInterface.CustomControls;
|
using Robust.Client.UserInterface.CustomControls;
|
||||||
using Robust.Shared.Containers;
|
using Robust.Shared.Containers;
|
||||||
using Robust.Shared.GameObjects.Systems;
|
|
||||||
using Robust.Shared.IoC;
|
using Robust.Shared.IoC;
|
||||||
using Robust.Shared.Localization;
|
using Robust.Shared.Localization;
|
||||||
using Robust.Shared.Log;
|
using Robust.Shared.Log;
|
||||||
@@ -197,9 +197,7 @@ namespace Content.Client.Instruments
|
|||||||
|| conMan.Owner != localPlayer.ControlledEntity))) return;
|
|| conMan.Owner != localPlayer.ControlledEntity))) return;
|
||||||
|
|
||||||
// We check that we're in range unobstructed just in case.
|
// We check that we're in range unobstructed just in case.
|
||||||
if(!EntitySystem.Get<SharedInteractionSystem>()
|
if (!localPlayer.InRangeUnobstructed(instrumentEnt)) return;
|
||||||
.InRangeUnobstructed(localPlayer.ControlledEntity.Transform.MapPosition,
|
|
||||||
instrumentEnt.Transform.MapPosition, ignoredEnt:instrumentEnt)) return;
|
|
||||||
|
|
||||||
if (!_midiManager.IsMidiFile(filename))
|
if (!_midiManager.IsMidiFile(filename))
|
||||||
{
|
{
|
||||||
|
|||||||
@@ -2,7 +2,8 @@
|
|||||||
using System.Collections.Immutable;
|
using System.Collections.Immutable;
|
||||||
using System.Linq;
|
using System.Linq;
|
||||||
using Content.Client.GameObjects.Components;
|
using Content.Client.GameObjects.Components;
|
||||||
using Content.Shared.GameObjects.EntitySystems;
|
using Content.Client.Utility;
|
||||||
|
using Content.Shared.Utility;
|
||||||
using Robust.Client.GameObjects.EntitySystems;
|
using Robust.Client.GameObjects.EntitySystems;
|
||||||
using Robust.Client.Interfaces.GameObjects;
|
using Robust.Client.Interfaces.GameObjects;
|
||||||
using Robust.Client.Interfaces.Graphics.ClientEye;
|
using Robust.Client.Interfaces.Graphics.ClientEye;
|
||||||
@@ -67,13 +68,7 @@ namespace Content.Client.State
|
|||||||
var inRange = false;
|
var inRange = false;
|
||||||
if (localPlayer.ControlledEntity != null && entityToClick != null)
|
if (localPlayer.ControlledEntity != null && entityToClick != null)
|
||||||
{
|
{
|
||||||
var playerPos = localPlayer.ControlledEntity.Transform.MapPosition;
|
inRange = localPlayer.InRangeUnobstructed(entityToClick, ignoreInsideBlocker: true);
|
||||||
var entityPos = entityToClick.Transform.MapPosition;
|
|
||||||
inRange = EntitySystemManager.GetEntitySystem<SharedInteractionSystem>()
|
|
||||||
.InRangeUnobstructed(playerPos, entityPos,
|
|
||||||
predicate: entity =>
|
|
||||||
entity == localPlayer.ControlledEntity || entity == entityToClick,
|
|
||||||
ignoreInsideBlocker: true);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
InteractionOutlineComponent outline;
|
InteractionOutlineComponent outline;
|
||||||
|
|||||||
93
Content.Client/Utility/RangeExtensions.cs
Normal file
93
Content.Client/Utility/RangeExtensions.cs
Normal file
@@ -0,0 +1,93 @@
|
|||||||
|
using Content.Shared.GameObjects.EntitySystems;
|
||||||
|
using Content.Shared.Physics;
|
||||||
|
using Robust.Client.Player;
|
||||||
|
using Robust.Shared.GameObjects.Systems;
|
||||||
|
using Robust.Shared.Interfaces.GameObjects;
|
||||||
|
using Robust.Shared.Interfaces.GameObjects.Components;
|
||||||
|
using Robust.Shared.Interfaces.Map;
|
||||||
|
using Robust.Shared.IoC;
|
||||||
|
using Robust.Shared.Map;
|
||||||
|
using static Content.Shared.GameObjects.EntitySystems.SharedInteractionSystem;
|
||||||
|
|
||||||
|
namespace Content.Client.Utility
|
||||||
|
{
|
||||||
|
public static class RangeExtensions
|
||||||
|
{
|
||||||
|
private static SharedInteractionSystem SharedInteractionSystem => EntitySystem.Get<SharedInteractionSystem>();
|
||||||
|
|
||||||
|
public static bool InRangeUnobstructed(
|
||||||
|
this LocalPlayer origin,
|
||||||
|
IEntity other,
|
||||||
|
float range = InteractionRange,
|
||||||
|
CollisionGroup collisionMask = CollisionGroup.Impassable,
|
||||||
|
Ignored predicate = null,
|
||||||
|
bool ignoreInsideBlocker = false,
|
||||||
|
bool popup = false)
|
||||||
|
{
|
||||||
|
var otherPosition = other.Transform.MapPosition;
|
||||||
|
|
||||||
|
return origin.InRangeUnobstructed(otherPosition, range, collisionMask, predicate, ignoreInsideBlocker,
|
||||||
|
popup);
|
||||||
|
}
|
||||||
|
|
||||||
|
public static bool InRangeUnobstructed(
|
||||||
|
this LocalPlayer origin,
|
||||||
|
IComponent other,
|
||||||
|
float range = InteractionRange,
|
||||||
|
CollisionGroup collisionMask = CollisionGroup.Impassable,
|
||||||
|
Ignored predicate = null,
|
||||||
|
bool ignoreInsideBlocker = false,
|
||||||
|
bool popup = false)
|
||||||
|
{
|
||||||
|
return origin.InRangeUnobstructed(other.Owner, range, collisionMask, predicate, ignoreInsideBlocker, popup);
|
||||||
|
}
|
||||||
|
|
||||||
|
public static bool InRangeUnobstructed(
|
||||||
|
this LocalPlayer origin,
|
||||||
|
IContainer other,
|
||||||
|
float range = InteractionRange,
|
||||||
|
CollisionGroup collisionMask = CollisionGroup.Impassable,
|
||||||
|
Ignored predicate = null,
|
||||||
|
bool ignoreInsideBlocker = false,
|
||||||
|
bool popup = false)
|
||||||
|
{
|
||||||
|
return origin.InRangeUnobstructed(other.Owner, range, collisionMask, predicate, ignoreInsideBlocker, popup);
|
||||||
|
}
|
||||||
|
|
||||||
|
public static bool InRangeUnobstructed(
|
||||||
|
this LocalPlayer origin,
|
||||||
|
GridCoordinates other,
|
||||||
|
float range = InteractionRange,
|
||||||
|
CollisionGroup collisionMask = CollisionGroup.Impassable,
|
||||||
|
Ignored predicate = null,
|
||||||
|
bool ignoreInsideBlocker = false,
|
||||||
|
bool popup = false)
|
||||||
|
{
|
||||||
|
var mapManager = IoCManager.Resolve<IMapManager>();
|
||||||
|
var otherPosition = other.ToMap(mapManager);
|
||||||
|
|
||||||
|
return origin.InRangeUnobstructed(otherPosition, range, collisionMask, predicate, ignoreInsideBlocker,
|
||||||
|
popup);
|
||||||
|
}
|
||||||
|
|
||||||
|
public static bool InRangeUnobstructed(
|
||||||
|
this LocalPlayer origin,
|
||||||
|
MapCoordinates other,
|
||||||
|
float range = InteractionRange,
|
||||||
|
CollisionGroup collisionMask = CollisionGroup.Impassable,
|
||||||
|
Ignored predicate = null,
|
||||||
|
bool ignoreInsideBlocker = false,
|
||||||
|
bool popup = false)
|
||||||
|
{
|
||||||
|
var originEntity = origin.ControlledEntity;
|
||||||
|
if (originEntity == null)
|
||||||
|
{
|
||||||
|
// TODO: Take into account the player's camera position?
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
return SharedInteractionSystem.InRangeUnobstructed(originEntity, other, range, collisionMask, predicate,
|
||||||
|
ignoreInsideBlocker, popup);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -0,0 +1,159 @@
|
|||||||
|
using System.Threading.Tasks;
|
||||||
|
using Content.Client.Utility;
|
||||||
|
using Content.Shared.GameObjects.EntitySystems;
|
||||||
|
using Content.Shared.Utility;
|
||||||
|
using NUnit.Framework;
|
||||||
|
using Robust.Server.GameObjects.Components.Container;
|
||||||
|
using Robust.Shared.Interfaces.GameObjects;
|
||||||
|
using Robust.Shared.Interfaces.GameObjects.Components;
|
||||||
|
using Robust.Shared.Interfaces.Map;
|
||||||
|
using Robust.Shared.Map;
|
||||||
|
|
||||||
|
namespace Content.IntegrationTests.Tests.Interaction
|
||||||
|
{
|
||||||
|
[TestFixture]
|
||||||
|
[TestOf(typeof(SharedInteractionSystem))]
|
||||||
|
[TestOf(typeof(SharedRangeExtensions))]
|
||||||
|
[TestOf(typeof(RangeExtensions))]
|
||||||
|
public class InRangeUnobstructed : ContentIntegrationTest
|
||||||
|
{
|
||||||
|
private const string HumanId = "BaseHumanMob_Content";
|
||||||
|
|
||||||
|
private const float InteractionRange = SharedInteractionSystem.InteractionRange;
|
||||||
|
|
||||||
|
private const float InteractionRangeDivided15 = InteractionRange / 1.5f;
|
||||||
|
|
||||||
|
private readonly (float, float) _interactionRangeDivided15X = (InteractionRangeDivided15, 0f);
|
||||||
|
|
||||||
|
private const float InteractionRangeDivided15Times3 = InteractionRangeDivided15 * 3;
|
||||||
|
|
||||||
|
[Test]
|
||||||
|
public async Task EntityEntityTest()
|
||||||
|
{
|
||||||
|
var server = StartServerDummyTicker();
|
||||||
|
|
||||||
|
await server.WaitIdleAsync();
|
||||||
|
|
||||||
|
var entityManager = server.ResolveDependency<IEntityManager>();
|
||||||
|
var mapManager = server.ResolveDependency<IMapManager>();
|
||||||
|
|
||||||
|
IEntity origin = null;
|
||||||
|
IEntity other = null;
|
||||||
|
IContainer container = null;
|
||||||
|
IComponent component = null;
|
||||||
|
GridCoordinates gridCoordinates = default;
|
||||||
|
MapCoordinates mapCoordinates = default;
|
||||||
|
|
||||||
|
server.Assert(() =>
|
||||||
|
{
|
||||||
|
mapManager.CreateNewMapEntity(MapId.Nullspace);
|
||||||
|
var coordinates = MapCoordinates.Nullspace;
|
||||||
|
|
||||||
|
origin = entityManager.SpawnEntity(HumanId, coordinates);
|
||||||
|
other = entityManager.SpawnEntity(HumanId, coordinates);
|
||||||
|
container = ContainerManagerComponent.Ensure<Container>("InRangeUnobstructedTestOtherContainer", other);
|
||||||
|
component = other.Transform;
|
||||||
|
gridCoordinates = other.Transform.GridPosition;
|
||||||
|
mapCoordinates = other.Transform.MapPosition;
|
||||||
|
});
|
||||||
|
|
||||||
|
await server.WaitIdleAsync();
|
||||||
|
|
||||||
|
server.Assert(() =>
|
||||||
|
{
|
||||||
|
// Entity <-> Entity
|
||||||
|
Assert.True(origin.InRangeUnobstructed(other));
|
||||||
|
Assert.True(other.InRangeUnobstructed(origin));
|
||||||
|
|
||||||
|
// Entity <-> Component
|
||||||
|
Assert.True(origin.InRangeUnobstructed(component));
|
||||||
|
Assert.True(component.InRangeUnobstructed(origin));
|
||||||
|
|
||||||
|
// Entity <-> Container
|
||||||
|
Assert.True(origin.InRangeUnobstructed(container));
|
||||||
|
Assert.True(container.InRangeUnobstructed(origin));
|
||||||
|
|
||||||
|
// Entity <-> GridCoordinates
|
||||||
|
Assert.True(origin.InRangeUnobstructed(gridCoordinates));
|
||||||
|
Assert.True(gridCoordinates.InRangeUnobstructed(origin));
|
||||||
|
|
||||||
|
// Entity <-> MapCoordinates
|
||||||
|
Assert.True(origin.InRangeUnobstructed(mapCoordinates));
|
||||||
|
Assert.True(mapCoordinates.InRangeUnobstructed(origin));
|
||||||
|
|
||||||
|
|
||||||
|
// Move them slightly apart
|
||||||
|
origin.Transform.LocalPosition += _interactionRangeDivided15X;
|
||||||
|
|
||||||
|
// Entity <-> Entity
|
||||||
|
Assert.True(origin.InRangeUnobstructed(other));
|
||||||
|
Assert.True(other.InRangeUnobstructed(origin));
|
||||||
|
|
||||||
|
// Entity <-> Component
|
||||||
|
Assert.True(origin.InRangeUnobstructed(component));
|
||||||
|
Assert.True(component.InRangeUnobstructed(origin));
|
||||||
|
|
||||||
|
// Entity <-> Container
|
||||||
|
Assert.True(origin.InRangeUnobstructed(container));
|
||||||
|
Assert.True(container.InRangeUnobstructed(origin));
|
||||||
|
|
||||||
|
// Entity <-> GridCoordinates
|
||||||
|
Assert.True(origin.InRangeUnobstructed(gridCoordinates));
|
||||||
|
Assert.True(gridCoordinates.InRangeUnobstructed(origin));
|
||||||
|
|
||||||
|
// Entity <-> MapCoordinates
|
||||||
|
Assert.True(origin.InRangeUnobstructed(mapCoordinates));
|
||||||
|
Assert.True(mapCoordinates.InRangeUnobstructed(origin));
|
||||||
|
|
||||||
|
|
||||||
|
// Move them out of range
|
||||||
|
origin.Transform.LocalPosition += _interactionRangeDivided15X;
|
||||||
|
|
||||||
|
// Entity <-> Entity
|
||||||
|
Assert.False(origin.InRangeUnobstructed(other));
|
||||||
|
Assert.False(other.InRangeUnobstructed(origin));
|
||||||
|
|
||||||
|
// Entity <-> Component
|
||||||
|
Assert.False(origin.InRangeUnobstructed(component));
|
||||||
|
Assert.False(component.InRangeUnobstructed(origin));
|
||||||
|
|
||||||
|
// Entity <-> Container
|
||||||
|
Assert.False(origin.InRangeUnobstructed(container));
|
||||||
|
Assert.False(container.InRangeUnobstructed(origin));
|
||||||
|
|
||||||
|
// Entity <-> GridCoordinates
|
||||||
|
Assert.False(origin.InRangeUnobstructed(gridCoordinates));
|
||||||
|
Assert.False(gridCoordinates.InRangeUnobstructed(origin));
|
||||||
|
|
||||||
|
// Entity <-> MapCoordinates
|
||||||
|
Assert.False(origin.InRangeUnobstructed(mapCoordinates));
|
||||||
|
Assert.False(mapCoordinates.InRangeUnobstructed(origin));
|
||||||
|
|
||||||
|
|
||||||
|
// Checks with increased range
|
||||||
|
|
||||||
|
// Entity <-> Entity
|
||||||
|
Assert.True(origin.InRangeUnobstructed(other, InteractionRangeDivided15Times3));
|
||||||
|
Assert.True(other.InRangeUnobstructed(origin, InteractionRangeDivided15Times3));
|
||||||
|
|
||||||
|
// Entity <-> Component
|
||||||
|
Assert.True(origin.InRangeUnobstructed(component, InteractionRangeDivided15Times3));
|
||||||
|
Assert.True(component.InRangeUnobstructed(origin, InteractionRangeDivided15Times3));
|
||||||
|
|
||||||
|
// Entity <-> Container
|
||||||
|
Assert.True(origin.InRangeUnobstructed(container, InteractionRangeDivided15Times3));
|
||||||
|
Assert.True(container.InRangeUnobstructed(origin, InteractionRangeDivided15Times3));
|
||||||
|
|
||||||
|
// Entity <-> GridCoordinates
|
||||||
|
Assert.True(origin.InRangeUnobstructed(gridCoordinates, InteractionRangeDivided15Times3));
|
||||||
|
Assert.True(gridCoordinates.InRangeUnobstructed(origin, InteractionRangeDivided15Times3));
|
||||||
|
|
||||||
|
// Entity <-> MapCoordinates
|
||||||
|
Assert.True(origin.InRangeUnobstructed(mapCoordinates, InteractionRangeDivided15Times3));
|
||||||
|
Assert.True(mapCoordinates.InRangeUnobstructed(origin, InteractionRangeDivided15Times3));
|
||||||
|
});
|
||||||
|
|
||||||
|
await server.WaitIdleAsync();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -3,6 +3,7 @@ using Content.Server.AI.WorldState.States.Inventory;
|
|||||||
using Content.Server.GameObjects.Components.Items.Storage;
|
using Content.Server.GameObjects.Components.Items.Storage;
|
||||||
using Content.Server.Utility;
|
using Content.Server.Utility;
|
||||||
using Content.Shared.Interfaces.GameObjects.Components;
|
using Content.Shared.Interfaces.GameObjects.Components;
|
||||||
|
using Content.Shared.Utility;
|
||||||
using Robust.Shared.Interfaces.GameObjects;
|
using Robust.Shared.Interfaces.GameObjects;
|
||||||
|
|
||||||
namespace Content.Server.AI.Operators.Inventory
|
namespace Content.Server.AI.Operators.Inventory
|
||||||
@@ -50,7 +51,7 @@ namespace Content.Server.AI.Operators.Inventory
|
|||||||
|
|
||||||
public override Outcome Execute(float frameTime)
|
public override Outcome Execute(float frameTime)
|
||||||
{
|
{
|
||||||
if (!InteractionChecks.InRangeUnobstructed(_owner, _target.Transform.MapPosition))
|
if (!_owner.InRangeUnobstructed(_target, popup: true))
|
||||||
{
|
{
|
||||||
return Outcome.Failed;
|
return Outcome.Failed;
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -1,6 +1,7 @@
|
|||||||
using Content.Server.GameObjects.Components.Mobs;
|
using Content.Server.GameObjects.Components.Mobs;
|
||||||
using Content.Server.GameObjects.EntitySystems.Click;
|
using Content.Server.GameObjects.EntitySystems.Click;
|
||||||
using Content.Server.Utility;
|
using Content.Server.Utility;
|
||||||
|
using Content.Shared.Utility;
|
||||||
using Robust.Shared.Interfaces.GameObjects;
|
using Robust.Shared.Interfaces.GameObjects;
|
||||||
using Robust.Shared.IoC;
|
using Robust.Shared.IoC;
|
||||||
|
|
||||||
@@ -28,7 +29,7 @@ namespace Content.Server.AI.Operators.Inventory
|
|||||||
return Outcome.Failed;
|
return Outcome.Failed;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (!InteractionChecks.InRangeUnobstructed(_owner, _useTarget.Transform.MapPosition))
|
if (!_owner.InRangeUnobstructed(_useTarget, popup: true))
|
||||||
{
|
{
|
||||||
return Outcome.Failed;
|
return Outcome.Failed;
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -4,6 +4,7 @@ using Content.Server.AI.WorldState.States.Inventory;
|
|||||||
using Content.Server.GameObjects.Components.Items.Storage;
|
using Content.Server.GameObjects.Components.Items.Storage;
|
||||||
using Content.Server.Utility;
|
using Content.Server.Utility;
|
||||||
using Content.Shared.Interfaces.GameObjects.Components;
|
using Content.Shared.Interfaces.GameObjects.Components;
|
||||||
|
using Content.Shared.Utility;
|
||||||
using Robust.Shared.Containers;
|
using Robust.Shared.Containers;
|
||||||
using Robust.Shared.Interfaces.GameObjects;
|
using Robust.Shared.Interfaces.GameObjects;
|
||||||
|
|
||||||
@@ -30,7 +31,7 @@ namespace Content.Server.AI.Operators.Inventory
|
|||||||
return Outcome.Success;
|
return Outcome.Success;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (!InteractionChecks.InRangeUnobstructed(_owner, container.Owner.Transform.MapPosition, ignoredEnt: container.Owner))
|
if (!_owner.InRangeUnobstructed(container, popup: true))
|
||||||
{
|
{
|
||||||
return Outcome.Failed;
|
return Outcome.Failed;
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -3,6 +3,7 @@ using Content.Server.GameObjects.Components.GUI;
|
|||||||
using Content.Server.GameObjects.Components.Items.Storage;
|
using Content.Server.GameObjects.Components.Items.Storage;
|
||||||
using Content.Server.GameObjects.EntitySystems.Click;
|
using Content.Server.GameObjects.EntitySystems.Click;
|
||||||
using Content.Server.Utility;
|
using Content.Server.Utility;
|
||||||
|
using Content.Shared.Utility;
|
||||||
using Robust.Shared.Containers;
|
using Robust.Shared.Containers;
|
||||||
using Robust.Shared.Interfaces.GameObjects;
|
using Robust.Shared.Interfaces.GameObjects;
|
||||||
using Robust.Shared.IoC;
|
using Robust.Shared.IoC;
|
||||||
@@ -26,7 +27,7 @@ namespace Content.Server.AI.Operators.Inventory
|
|||||||
if (_target.Deleted ||
|
if (_target.Deleted ||
|
||||||
!_target.HasComponent<ItemComponent>() ||
|
!_target.HasComponent<ItemComponent>() ||
|
||||||
ContainerHelpers.IsInContainer(_target) ||
|
ContainerHelpers.IsInContainer(_target) ||
|
||||||
!InteractionChecks.InRangeUnobstructed(_owner, _target.Transform.MapPosition))
|
!_owner.InRangeUnobstructed(_target, popup: true))
|
||||||
{
|
{
|
||||||
return Outcome.Failed;
|
return Outcome.Failed;
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -1,5 +1,4 @@
|
|||||||
|
using Robust.Server.GameObjects;
|
||||||
using Robust.Server.GameObjects;
|
|
||||||
using Content.Shared.GameObjects.EntitySystems;
|
using Content.Shared.GameObjects.EntitySystems;
|
||||||
using Content.Shared.Interfaces;
|
using Content.Shared.Interfaces;
|
||||||
using Robust.Shared.GameObjects;
|
using Robust.Shared.GameObjects;
|
||||||
@@ -22,6 +21,8 @@ using Content.Shared.GameObjects.Components.Mobs;
|
|||||||
using Robust.Shared.Maths;
|
using Robust.Shared.Maths;
|
||||||
using System;
|
using System;
|
||||||
using System.Collections.Generic;
|
using System.Collections.Generic;
|
||||||
|
using Content.Shared.Utility;
|
||||||
|
using Serilog;
|
||||||
using Content.Server.GameObjects.Components.GUI;
|
using Content.Server.GameObjects.Components.GUI;
|
||||||
|
|
||||||
namespace Content.Server.GameObjects.Components.ActionBlocking
|
namespace Content.Server.GameObjects.Components.ActionBlocking
|
||||||
@@ -109,11 +110,7 @@ namespace Content.Server.GameObjects.Components.ActionBlocking
|
|||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (!EntitySystem.Get<SharedInteractionSystem>().InRangeUnobstructed(
|
if (!handcuff.InRangeUnobstructed(Owner, _interactRange))
|
||||||
handcuff.Transform.MapPosition,
|
|
||||||
Owner.Transform.MapPosition,
|
|
||||||
_interactRange,
|
|
||||||
ignoredEnt: Owner))
|
|
||||||
{
|
{
|
||||||
Logger.Warning("Handcuffs being applied to player are obstructed or too far away! This should not happen!");
|
Logger.Warning("Handcuffs being applied to player are obstructed or too far away! This should not happen!");
|
||||||
return;
|
return;
|
||||||
@@ -131,7 +128,7 @@ namespace Content.Server.GameObjects.Components.ActionBlocking
|
|||||||
/// <summary>
|
/// <summary>
|
||||||
/// Check the current amount of hands the owner has, and if there's less hands than active cuffs we remove some cuffs.
|
/// Check the current amount of hands the owner has, and if there's less hands than active cuffs we remove some cuffs.
|
||||||
/// </summary>
|
/// </summary>
|
||||||
private void UpdateHandCount()
|
private void UpdateHandCount()
|
||||||
{
|
{
|
||||||
var dirty = false;
|
var dirty = false;
|
||||||
var handCount = _hands.Hands.Count();
|
var handCount = _hands.Hands.Count();
|
||||||
@@ -238,22 +235,13 @@ namespace Content.Server.GameObjects.Components.ActionBlocking
|
|||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (!isOwner &&
|
if (!isOwner && user.InRangeUnobstructed(Owner, _interactRange))
|
||||||
!EntitySystem.Get<SharedInteractionSystem>().InRangeUnobstructed(
|
|
||||||
user.Transform.MapPosition,
|
|
||||||
Owner.Transform.MapPosition,
|
|
||||||
_interactRange,
|
|
||||||
ignoredEnt: Owner))
|
|
||||||
{
|
{
|
||||||
user.PopupMessage(user, Loc.GetString("You are too far away to remove the cuffs."));
|
user.PopupMessage(user, Loc.GetString("You are too far away to remove the cuffs."));
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (!EntitySystem.Get<SharedInteractionSystem>().InRangeUnobstructed(
|
if (!cuffsToRemove.InRangeUnobstructed(Owner, _interactRange))
|
||||||
cuffsToRemove.Transform.MapPosition,
|
|
||||||
Owner.Transform.MapPosition,
|
|
||||||
_interactRange,
|
|
||||||
ignoredEnt: Owner))
|
|
||||||
{
|
{
|
||||||
Logger.Warning("Handcuffs being removed from player are obstructed or too far away! This should not happen!");
|
Logger.Warning("Handcuffs being removed from player are obstructed or too far away! This should not happen!");
|
||||||
return;
|
return;
|
||||||
|
|||||||
@@ -16,6 +16,7 @@ using Content.Shared.GameObjects.Components.ActionBlocking;
|
|||||||
using Content.Server.GameObjects.Components.Mobs;
|
using Content.Server.GameObjects.Components.Mobs;
|
||||||
using Robust.Shared.Maths;
|
using Robust.Shared.Maths;
|
||||||
using System;
|
using System;
|
||||||
|
using Content.Shared.Utility;
|
||||||
|
|
||||||
namespace Content.Server.GameObjects.Components.ActionBlocking
|
namespace Content.Server.GameObjects.Components.ActionBlocking
|
||||||
{
|
{
|
||||||
@@ -115,7 +116,7 @@ namespace Content.Server.GameObjects.Components.ActionBlocking
|
|||||||
private float _interactRange;
|
private float _interactRange;
|
||||||
private DoAfterSystem _doAfterSystem;
|
private DoAfterSystem _doAfterSystem;
|
||||||
private AudioSystem _audioSystem;
|
private AudioSystem _audioSystem;
|
||||||
|
|
||||||
public override void Initialize()
|
public override void Initialize()
|
||||||
{
|
{
|
||||||
base.Initialize();
|
base.Initialize();
|
||||||
@@ -182,11 +183,7 @@ namespace Content.Server.GameObjects.Components.ActionBlocking
|
|||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (!EntitySystem.Get<SharedInteractionSystem>().InRangeUnobstructed(
|
if (!eventArgs.InRangeUnobstructed(_interactRange, ignoreInsideBlocker: true))
|
||||||
eventArgs.User.Transform.MapPosition,
|
|
||||||
eventArgs.Target.Transform.MapPosition,
|
|
||||||
_interactRange,
|
|
||||||
ignoredEnt: Owner))
|
|
||||||
{
|
{
|
||||||
_notifyManager.PopupMessage(eventArgs.User, eventArgs.User, Loc.GetString("You are too far away to use the cuffs!"));
|
_notifyManager.PopupMessage(eventArgs.User, eventArgs.User, Loc.GetString("You are too far away to use the cuffs!"));
|
||||||
return;
|
return;
|
||||||
@@ -196,7 +193,7 @@ namespace Content.Server.GameObjects.Components.ActionBlocking
|
|||||||
_notifyManager.PopupMessage(eventArgs.User, eventArgs.Target, Loc.GetString("{0:theName} starts cuffing you!", eventArgs.User));
|
_notifyManager.PopupMessage(eventArgs.User, eventArgs.Target, Loc.GetString("{0:theName} starts cuffing you!", eventArgs.User));
|
||||||
_audioSystem.PlayFromEntity(StartCuffSound, Owner);
|
_audioSystem.PlayFromEntity(StartCuffSound, Owner);
|
||||||
|
|
||||||
TryUpdateCuff(eventArgs.User, eventArgs.Target, cuffed);
|
TryUpdateCuff(eventArgs.User, eventArgs.Target, cuffed);
|
||||||
}
|
}
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
|
|||||||
@@ -7,13 +7,13 @@ using Content.Server.GameObjects.Components.Mobs.State;
|
|||||||
using Content.Server.GameObjects.Components.Strap;
|
using Content.Server.GameObjects.Components.Strap;
|
||||||
using Content.Server.GameObjects.EntitySystems;
|
using Content.Server.GameObjects.EntitySystems;
|
||||||
using Content.Server.Interfaces;
|
using Content.Server.Interfaces;
|
||||||
using Content.Server.Utility;
|
|
||||||
using Content.Shared.GameObjects.Components.Buckle;
|
using Content.Shared.GameObjects.Components.Buckle;
|
||||||
using Content.Shared.GameObjects.Components.Mobs;
|
using Content.Shared.GameObjects.Components.Mobs;
|
||||||
using Content.Shared.GameObjects.Components.Strap;
|
using Content.Shared.GameObjects.Components.Strap;
|
||||||
using Content.Shared.GameObjects.EntitySystems;
|
using Content.Shared.GameObjects.EntitySystems;
|
||||||
using Content.Shared.GameObjects.Verbs;
|
using Content.Shared.GameObjects.Verbs;
|
||||||
using Content.Shared.Interfaces.GameObjects.Components;
|
using Content.Shared.Interfaces.GameObjects.Components;
|
||||||
|
using Content.Shared.Utility;
|
||||||
using Robust.Server.GameObjects;
|
using Robust.Server.GameObjects;
|
||||||
using Robust.Server.GameObjects.EntitySystemMessages;
|
using Robust.Server.GameObjects.EntitySystemMessages;
|
||||||
using Robust.Server.GameObjects.EntitySystems;
|
using Robust.Server.GameObjects.EntitySystems;
|
||||||
@@ -190,13 +190,10 @@ namespace Content.Server.GameObjects.Components.Buckle
|
|||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
var ownerPosition = Owner.Transform.MapPosition;
|
|
||||||
var strapPosition = strap.Owner.Transform.MapPosition;
|
|
||||||
var interaction = EntitySystem.Get<SharedInteractionSystem>();
|
|
||||||
var component = strap;
|
var component = strap;
|
||||||
bool Ignored(IEntity entity) => entity == Owner || entity == user || entity == component.Owner;
|
bool Ignored(IEntity entity) => entity == Owner || entity == user || entity == component.Owner;
|
||||||
|
|
||||||
if (!interaction.InRangeUnobstructed(ownerPosition, strapPosition, _range, predicate: Ignored))
|
if (!Owner.InRangeUnobstructed(strap, _range, predicate: Ignored, popup: true))
|
||||||
{
|
{
|
||||||
_notifyManager.PopupMessage(strap.Owner, user,
|
_notifyManager.PopupMessage(strap.Owner, user,
|
||||||
Loc.GetString("You can't reach there!"));
|
Loc.GetString("You can't reach there!"));
|
||||||
@@ -346,9 +343,7 @@ namespace Content.Server.GameObjects.Components.Buckle
|
|||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
var strapPosition = Owner.Transform.MapPosition;
|
if (!user.InRangeUnobstructed(oldBuckledTo, _range, popup: true))
|
||||||
|
|
||||||
if (!InteractionChecks.InRangeUnobstructed(user, strapPosition, _range))
|
|
||||||
{
|
{
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -2,10 +2,10 @@
|
|||||||
using System;
|
using System;
|
||||||
using Content.Server.GameObjects.Components.Body.Circulatory;
|
using Content.Server.GameObjects.Components.Body.Circulatory;
|
||||||
using Content.Server.Interfaces;
|
using Content.Server.Interfaces;
|
||||||
using Content.Server.Utility;
|
|
||||||
using Content.Shared.Chemistry;
|
using Content.Shared.Chemistry;
|
||||||
using Content.Shared.GameObjects.Components.Chemistry;
|
using Content.Shared.GameObjects.Components.Chemistry;
|
||||||
using Content.Shared.Interfaces.GameObjects.Components;
|
using Content.Shared.Interfaces.GameObjects.Components;
|
||||||
|
using Content.Shared.Utility;
|
||||||
using Robust.Shared.GameObjects;
|
using Robust.Shared.GameObjects;
|
||||||
using Robust.Shared.Interfaces.GameObjects;
|
using Robust.Shared.Interfaces.GameObjects;
|
||||||
using Robust.Shared.IoC;
|
using Robust.Shared.IoC;
|
||||||
@@ -111,7 +111,7 @@ namespace Content.Server.GameObjects.Components.Chemistry
|
|||||||
/// <param name="eventArgs"></param>
|
/// <param name="eventArgs"></param>
|
||||||
void IAfterInteract.AfterInteract(AfterInteractEventArgs eventArgs)
|
void IAfterInteract.AfterInteract(AfterInteractEventArgs eventArgs)
|
||||||
{
|
{
|
||||||
if (!InteractionChecks.InRangeUnobstructed(eventArgs)) return;
|
if (!eventArgs.InRangeUnobstructed(ignoreInsideBlocker: true, popup: true)) return;
|
||||||
|
|
||||||
//Make sure we have the attacking entity
|
//Make sure we have the attacking entity
|
||||||
if (eventArgs.Target == null || !Owner.TryGetComponent(out SolutionComponent? solution) || !solution.Injector)
|
if (eventArgs.Target == null || !Owner.TryGetComponent(out SolutionComponent? solution) || !solution.Injector)
|
||||||
|
|||||||
@@ -5,6 +5,7 @@ using Content.Server.Utility;
|
|||||||
using Content.Shared.Chemistry;
|
using Content.Shared.Chemistry;
|
||||||
using Content.Shared.Interfaces;
|
using Content.Shared.Interfaces;
|
||||||
using Content.Shared.Interfaces.GameObjects.Components;
|
using Content.Shared.Interfaces.GameObjects.Components;
|
||||||
|
using Content.Shared.Utility;
|
||||||
using Robust.Server.GameObjects.EntitySystems;
|
using Robust.Server.GameObjects.EntitySystems;
|
||||||
using Robust.Shared.Audio;
|
using Robust.Shared.Audio;
|
||||||
using Robust.Shared.GameObjects;
|
using Robust.Shared.GameObjects;
|
||||||
@@ -80,7 +81,7 @@ namespace Content.Server.GameObjects.Components.Chemistry
|
|||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (!InteractionChecks.InRangeUnobstructed(user, trueTarget.Transform.MapPosition))
|
if (!user.InRangeUnobstructed(trueTarget, popup: true))
|
||||||
{
|
{
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -4,6 +4,7 @@ using Content.Server.Utility;
|
|||||||
using Content.Shared.Chemistry;
|
using Content.Shared.Chemistry;
|
||||||
using Content.Shared.Interfaces;
|
using Content.Shared.Interfaces;
|
||||||
using Content.Shared.Interfaces.GameObjects.Components;
|
using Content.Shared.Interfaces.GameObjects.Components;
|
||||||
|
using Content.Shared.Utility;
|
||||||
using Robust.Server.GameObjects.EntitySystems;
|
using Robust.Server.GameObjects.EntitySystems;
|
||||||
using Robust.Shared.GameObjects;
|
using Robust.Shared.GameObjects;
|
||||||
using Robust.Shared.GameObjects.Systems;
|
using Robust.Shared.GameObjects.Systems;
|
||||||
@@ -68,7 +69,7 @@ namespace Content.Server.GameObjects.Components.Fluids
|
|||||||
void IAfterInteract.AfterInteract(AfterInteractEventArgs eventArgs)
|
void IAfterInteract.AfterInteract(AfterInteractEventArgs eventArgs)
|
||||||
{
|
{
|
||||||
if (!Owner.TryGetComponent(out SolutionComponent? contents)) return;
|
if (!Owner.TryGetComponent(out SolutionComponent? contents)) return;
|
||||||
if (!InteractionChecks.InRangeUnobstructed(eventArgs)) return;
|
if (!eventArgs.InRangeUnobstructed(ignoreInsideBlocker: true, popup: true)) return;
|
||||||
|
|
||||||
if (CurrentVolume <= 0)
|
if (CurrentVolume <= 0)
|
||||||
{
|
{
|
||||||
|
|||||||
@@ -2,6 +2,7 @@
|
|||||||
using Content.Shared.GameObjects.Components.Interactable;
|
using Content.Shared.GameObjects.Components.Interactable;
|
||||||
using Content.Shared.Interfaces.GameObjects.Components;
|
using Content.Shared.Interfaces.GameObjects.Components;
|
||||||
using Content.Shared.Maps;
|
using Content.Shared.Maps;
|
||||||
|
using Content.Shared.Utility;
|
||||||
using Robust.Shared.GameObjects;
|
using Robust.Shared.GameObjects;
|
||||||
using Robust.Shared.Interfaces.GameObjects;
|
using Robust.Shared.Interfaces.GameObjects;
|
||||||
using Robust.Shared.Interfaces.Map;
|
using Robust.Shared.Interfaces.Map;
|
||||||
@@ -42,7 +43,7 @@ namespace Content.Server.GameObjects.Components.Interactable
|
|||||||
|
|
||||||
var coordinates = mapGrid.GridTileToLocal(tile.GridIndices);
|
var coordinates = mapGrid.GridTileToLocal(tile.GridIndices);
|
||||||
|
|
||||||
if (!_entitySystemManager.GetEntitySystem<InteractionSystem>().InRangeUnobstructed(user.Transform.MapPosition, coordinates.ToMap(_mapManager), ignoredEnt:user))
|
if (!user.InRangeUnobstructed(coordinates, popup: true))
|
||||||
return;
|
return;
|
||||||
|
|
||||||
var tileDef = (ContentTileDefinition)_tileDefinitionManager[tile.Tile.TypeId];
|
var tileDef = (ContentTileDefinition)_tileDefinitionManager[tile.Tile.TypeId];
|
||||||
|
|||||||
@@ -2,6 +2,7 @@
|
|||||||
using Content.Server.Utility;
|
using Content.Server.Utility;
|
||||||
using Content.Shared.Interfaces.GameObjects.Components;
|
using Content.Shared.Interfaces.GameObjects.Components;
|
||||||
using Content.Shared.Maps;
|
using Content.Shared.Maps;
|
||||||
|
using Content.Shared.Utility;
|
||||||
using Robust.Server.GameObjects.EntitySystems;
|
using Robust.Server.GameObjects.EntitySystems;
|
||||||
using Robust.Shared.GameObjects;
|
using Robust.Shared.GameObjects;
|
||||||
using Robust.Shared.GameObjects.Systems;
|
using Robust.Shared.GameObjects.Systems;
|
||||||
@@ -35,7 +36,7 @@ namespace Content.Server.GameObjects.Components.Items
|
|||||||
|
|
||||||
public void AfterInteract(AfterInteractEventArgs eventArgs)
|
public void AfterInteract(AfterInteractEventArgs eventArgs)
|
||||||
{
|
{
|
||||||
if (!InteractionChecks.InRangeUnobstructed(eventArgs)) return;
|
if (!eventArgs.InRangeUnobstructed(ignoreInsideBlocker: true, popup: true)) return;
|
||||||
if (!Owner.TryGetComponent(out StackComponent stack)) return;
|
if (!Owner.TryGetComponent(out StackComponent stack)) return;
|
||||||
|
|
||||||
var attacked = eventArgs.Target;
|
var attacked = eventArgs.Target;
|
||||||
|
|||||||
@@ -6,6 +6,7 @@ using Content.Server.Utility;
|
|||||||
using Content.Shared.GameObjects.EntitySystems;
|
using Content.Shared.GameObjects.EntitySystems;
|
||||||
using Content.Shared.Interfaces.GameObjects.Components;
|
using Content.Shared.Interfaces.GameObjects.Components;
|
||||||
using Content.Shared.Maps;
|
using Content.Shared.Maps;
|
||||||
|
using Content.Shared.Utility;
|
||||||
using Robust.Server.GameObjects.EntitySystems;
|
using Robust.Server.GameObjects.EntitySystems;
|
||||||
using Robust.Server.Interfaces.GameObjects;
|
using Robust.Server.Interfaces.GameObjects;
|
||||||
using Robust.Shared.GameObjects;
|
using Robust.Shared.GameObjects;
|
||||||
@@ -168,7 +169,7 @@ namespace Content.Server.GameObjects.Components.Items.RCD
|
|||||||
}
|
}
|
||||||
|
|
||||||
var coordinates = mapGrid.GridTileToLocal(tile.GridIndices);
|
var coordinates = mapGrid.GridTileToLocal(tile.GridIndices);
|
||||||
if (coordinates == GridCoordinates.InvalidGrid || !InteractionChecks.InRangeUnobstructed(eventArgs))
|
if (coordinates == GridCoordinates.InvalidGrid || !eventArgs.InRangeUnobstructed(ignoreInsideBlocker: true, popup: true))
|
||||||
{
|
{
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -8,6 +8,7 @@ using Content.Shared.GameObjects.Components.Items;
|
|||||||
using Content.Shared.GameObjects.EntitySystems;
|
using Content.Shared.GameObjects.EntitySystems;
|
||||||
using Content.Shared.GameObjects.Verbs;
|
using Content.Shared.GameObjects.Verbs;
|
||||||
using Content.Shared.Interfaces.GameObjects.Components;
|
using Content.Shared.Interfaces.GameObjects.Components;
|
||||||
|
using Content.Shared.Utility;
|
||||||
using Robust.Server.Interfaces.GameObjects;
|
using Robust.Server.Interfaces.GameObjects;
|
||||||
using Robust.Shared.Containers;
|
using Robust.Shared.Containers;
|
||||||
using Robust.Shared.GameObjects;
|
using Robust.Shared.GameObjects;
|
||||||
@@ -96,9 +97,7 @@ namespace Content.Server.GameObjects.Components.Items.Storage
|
|||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
var itemPos = Owner.Transform.MapPosition;
|
return user.InRangeUnobstructed(Owner, ignoreInsideBlocker: true, popup: true);
|
||||||
|
|
||||||
return InteractionChecks.InRangeUnobstructed(user, itemPos, ignoredEnt: Owner, ignoreInsideBlocker:true);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
public bool InteractHand(InteractHandEventArgs eventArgs)
|
public bool InteractHand(InteractHandEventArgs eventArgs)
|
||||||
|
|||||||
@@ -11,6 +11,7 @@ using Content.Shared.GameObjects.Components.Storage;
|
|||||||
using Content.Shared.GameObjects.EntitySystems;
|
using Content.Shared.GameObjects.EntitySystems;
|
||||||
using Content.Shared.Interfaces;
|
using Content.Shared.Interfaces;
|
||||||
using Content.Shared.Interfaces.GameObjects.Components;
|
using Content.Shared.Interfaces.GameObjects.Components;
|
||||||
|
using Content.Shared.Utility;
|
||||||
using Robust.Server.GameObjects;
|
using Robust.Server.GameObjects;
|
||||||
using Robust.Server.GameObjects.Components.Container;
|
using Robust.Server.GameObjects.Components.Container;
|
||||||
using Robust.Server.GameObjects.EntitySystemMessages;
|
using Robust.Server.GameObjects.EntitySystemMessages;
|
||||||
@@ -405,9 +406,7 @@ namespace Content.Server.GameObjects.Components.Items.Storage
|
|||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
|
||||||
var storagePosition = Owner.Transform.MapPosition;
|
if (!player.InRangeUnobstructed(Owner, popup: true))
|
||||||
|
|
||||||
if (!InteractionChecks.InRangeUnobstructed(player, storagePosition))
|
|
||||||
{
|
{
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -5,6 +5,7 @@ using Content.Shared.Damage;
|
|||||||
using Content.Shared.GameObjects.Components.Body;
|
using Content.Shared.GameObjects.Components.Body;
|
||||||
using Content.Shared.GameObjects.EntitySystems;
|
using Content.Shared.GameObjects.EntitySystems;
|
||||||
using Content.Shared.Interfaces.GameObjects.Components;
|
using Content.Shared.Interfaces.GameObjects.Components;
|
||||||
|
using Content.Shared.Utility;
|
||||||
using Robust.Shared.GameObjects;
|
using Robust.Shared.GameObjects;
|
||||||
using Robust.Shared.GameObjects.Systems;
|
using Robust.Shared.GameObjects.Systems;
|
||||||
using Robust.Shared.Interfaces.GameObjects;
|
using Robust.Shared.Interfaces.GameObjects;
|
||||||
@@ -43,18 +44,10 @@ namespace Content.Server.GameObjects.Components.Medical
|
|||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (eventArgs.User != eventArgs.Target)
|
if (eventArgs.User != eventArgs.Target &&
|
||||||
|
!eventArgs.InRangeUnobstructed(ignoreInsideBlocker: true, popup: true))
|
||||||
{
|
{
|
||||||
var interactionSystem = EntitySystem.Get<SharedInteractionSystem>();
|
return;
|
||||||
var from = eventArgs.User.Transform.MapPosition;
|
|
||||||
var to = eventArgs.Target.Transform.MapPosition;
|
|
||||||
bool Ignored(IEntity entity) => entity == eventArgs.User || entity == eventArgs.Target;
|
|
||||||
var inRange = interactionSystem.InRangeUnobstructed(from, to, predicate: Ignored);
|
|
||||||
|
|
||||||
if (!inRange)
|
|
||||||
{
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
if (Owner.TryGetComponent(out StackComponent stack) &&
|
if (Owner.TryGetComponent(out StackComponent stack) &&
|
||||||
|
|||||||
@@ -1,4 +1,4 @@
|
|||||||
using Content.Server.GameObjects.Components.Body;
|
using Content.Server.GameObjects.Components.Body;
|
||||||
using Content.Server.GameObjects.EntitySystems.DoAfter;
|
using Content.Server.GameObjects.EntitySystems.DoAfter;
|
||||||
using Content.Shared.GameObjects.Components.Movement;
|
using Content.Shared.GameObjects.Components.Movement;
|
||||||
using Content.Shared.GameObjects.EntitySystems;
|
using Content.Shared.GameObjects.EntitySystems;
|
||||||
@@ -18,6 +18,7 @@ using Robust.Shared.Serialization;
|
|||||||
using Robust.Shared.ViewVariables;
|
using Robust.Shared.ViewVariables;
|
||||||
using System;
|
using System;
|
||||||
using Content.Server.Utility;
|
using Content.Server.Utility;
|
||||||
|
using Content.Shared.Utility;
|
||||||
|
|
||||||
namespace Content.Server.GameObjects.Components.Movement
|
namespace Content.Server.GameObjects.Components.Movement
|
||||||
{
|
{
|
||||||
@@ -107,12 +108,7 @@ namespace Content.Server.GameObjects.Components.Movement
|
|||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
var userPosition = user.Transform.MapPosition;
|
if (!user.InRangeUnobstructed(target, _range))
|
||||||
var climbablePosition = target.Transform.MapPosition;
|
|
||||||
var interaction = EntitySystem.Get<SharedInteractionSystem>();
|
|
||||||
bool Ignored(IEntity entity) => (entity == target || entity == user);
|
|
||||||
|
|
||||||
if (!interaction.InRangeUnobstructed(userPosition, climbablePosition, _range, predicate: Ignored))
|
|
||||||
{
|
{
|
||||||
reason = Loc.GetString("You can't reach there!");
|
reason = Loc.GetString("You can't reach there!");
|
||||||
return false;
|
return false;
|
||||||
@@ -144,14 +140,10 @@ namespace Content.Server.GameObjects.Components.Movement
|
|||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
var userPosition = user.Transform.MapPosition;
|
bool Ignored(IEntity entity) => entity == target || entity == user || entity == dragged;
|
||||||
var otherUserPosition = dragged.Transform.MapPosition;
|
|
||||||
var climbablePosition = target.Transform.MapPosition;
|
|
||||||
var interaction = EntitySystem.Get<SharedInteractionSystem>();
|
|
||||||
bool Ignored(IEntity entity) => (entity == target || entity == user || entity == dragged);
|
|
||||||
|
|
||||||
if (!interaction.InRangeUnobstructed(userPosition, climbablePosition, _range, predicate: Ignored) ||
|
if (!user.InRangeUnobstructed(target, _range, predicate: Ignored) ||
|
||||||
!interaction.InRangeUnobstructed(userPosition, otherUserPosition, _range, predicate: Ignored))
|
!user.InRangeUnobstructed(dragged, _range, predicate: Ignored))
|
||||||
{
|
{
|
||||||
reason = Loc.GetString("You can't reach there!");
|
reason = Loc.GetString("You can't reach there!");
|
||||||
return false;
|
return false;
|
||||||
|
|||||||
@@ -11,6 +11,7 @@ using Content.Shared.Chemistry;
|
|||||||
using Content.Shared.GameObjects.Components.Utensil;
|
using Content.Shared.GameObjects.Components.Utensil;
|
||||||
using Content.Shared.Interfaces;
|
using Content.Shared.Interfaces;
|
||||||
using Content.Shared.Interfaces.GameObjects.Components;
|
using Content.Shared.Interfaces.GameObjects.Components;
|
||||||
|
using Content.Shared.Utility;
|
||||||
using Robust.Server.GameObjects.EntitySystems;
|
using Robust.Server.GameObjects.EntitySystems;
|
||||||
using Robust.Shared.Audio;
|
using Robust.Shared.Audio;
|
||||||
using Robust.Shared.GameObjects;
|
using Robust.Shared.GameObjects;
|
||||||
@@ -162,7 +163,7 @@ namespace Content.Server.GameObjects.Components.Nutrition
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
if (!InteractionChecks.InRangeUnobstructed(user, trueTarget.Transform.MapPosition))
|
if (!user.InRangeUnobstructed(trueTarget, popup: true))
|
||||||
{
|
{
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -3,7 +3,6 @@ using Content.Server.GameObjects.Components.GUI;
|
|||||||
using Content.Server.GameObjects.Components.Items.Storage;
|
using Content.Server.GameObjects.Components.Items.Storage;
|
||||||
using Content.Server.GameObjects.Components.NodeContainer;
|
using Content.Server.GameObjects.Components.NodeContainer;
|
||||||
using Content.Server.GameObjects.Components.NodeContainer.NodeGroups;
|
using Content.Server.GameObjects.Components.NodeContainer.NodeGroups;
|
||||||
using Content.Server.GameObjects.Components.NodeContainer.Nodes;
|
|
||||||
using Content.Server.GameObjects.Components.Power.ApcNetComponents;
|
using Content.Server.GameObjects.Components.Power.ApcNetComponents;
|
||||||
using Content.Server.GameObjects.Components.Power.PowerNetComponents;
|
using Content.Server.GameObjects.Components.Power.PowerNetComponents;
|
||||||
using Content.Server.Interfaces;
|
using Content.Server.Interfaces;
|
||||||
@@ -12,7 +11,6 @@ using Content.Server.Utility;
|
|||||||
using Content.Shared.GameObjects.Components.Power.AME;
|
using Content.Shared.GameObjects.Components.Power.AME;
|
||||||
using Content.Shared.GameObjects.EntitySystems;
|
using Content.Shared.GameObjects.EntitySystems;
|
||||||
using Content.Shared.Interfaces.GameObjects.Components;
|
using Content.Shared.Interfaces.GameObjects.Components;
|
||||||
using Microsoft.EntityFrameworkCore.Internal;
|
|
||||||
using Robust.Server.GameObjects;
|
using Robust.Server.GameObjects;
|
||||||
using Robust.Server.GameObjects.Components.Container;
|
using Robust.Server.GameObjects.Components.Container;
|
||||||
using Robust.Server.GameObjects.Components.UserInterface;
|
using Robust.Server.GameObjects.Components.UserInterface;
|
||||||
@@ -20,17 +18,12 @@ using Robust.Server.GameObjects.EntitySystems;
|
|||||||
using Robust.Server.Interfaces.GameObjects;
|
using Robust.Server.Interfaces.GameObjects;
|
||||||
using Robust.Shared.Audio;
|
using Robust.Shared.Audio;
|
||||||
using Robust.Shared.GameObjects;
|
using Robust.Shared.GameObjects;
|
||||||
using Robust.Shared.GameObjects.Components.Transform;
|
|
||||||
using Robust.Shared.GameObjects.Systems;
|
using Robust.Shared.GameObjects.Systems;
|
||||||
using Robust.Shared.Interfaces.GameObjects;
|
using Robust.Shared.Interfaces.GameObjects;
|
||||||
using Robust.Shared.Interfaces.GameObjects.Components;
|
|
||||||
using Robust.Shared.IoC;
|
using Robust.Shared.IoC;
|
||||||
using Robust.Shared.Localization;
|
using Robust.Shared.Localization;
|
||||||
using Robust.Shared.ViewVariables;
|
using Robust.Shared.ViewVariables;
|
||||||
using System;
|
|
||||||
using System.Collections.Generic;
|
|
||||||
using System.Linq;
|
using System.Linq;
|
||||||
using System.Text;
|
|
||||||
using System.Threading.Tasks;
|
using System.Threading.Tasks;
|
||||||
|
|
||||||
namespace Content.Server.GameObjects.Components.Power.AME
|
namespace Content.Server.GameObjects.Components.Power.AME
|
||||||
@@ -87,20 +80,27 @@ namespace Content.Server.GameObjects.Components.Power.AME
|
|||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
var group = GetAMENodeGroup();
|
||||||
|
|
||||||
|
if (group == null)
|
||||||
|
{
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
_jarSlot.ContainedEntity.TryGetComponent<AMEFuelContainerComponent>(out var fuelJar);
|
_jarSlot.ContainedEntity.TryGetComponent<AMEFuelContainerComponent>(out var fuelJar);
|
||||||
if(fuelJar != null && _powerSupplier != null && fuelJar.FuelAmount > InjectionAmount)
|
if(fuelJar != null && _powerSupplier != null && fuelJar.FuelAmount > InjectionAmount)
|
||||||
{
|
{
|
||||||
_powerSupplier.SupplyRate = GetAMENodeGroup().InjectFuel(InjectionAmount);
|
_powerSupplier.SupplyRate = group.InjectFuel(InjectionAmount);
|
||||||
fuelJar.FuelAmount -= InjectionAmount;
|
fuelJar.FuelAmount -= InjectionAmount;
|
||||||
InjectSound();
|
InjectSound();
|
||||||
UpdateUserInterface();
|
UpdateUserInterface();
|
||||||
}
|
}
|
||||||
|
|
||||||
_stability = GetAMENodeGroup().GetTotalStability();
|
_stability = group.GetTotalStability();
|
||||||
|
|
||||||
UpdateDisplay(_stability);
|
UpdateDisplay(_stability);
|
||||||
|
|
||||||
if(_stability <= 0) { GetAMENodeGroup().ExplodeCores(); }
|
if(_stability <= 0) { group.ExplodeCores(); }
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -213,7 +213,7 @@ namespace Content.Server.GameObjects.Components.Power.AME
|
|||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
|
||||||
GetAMENodeGroup().UpdateCoreVisuals(InjectionAmount, _injecting);
|
GetAMENodeGroup()?.UpdateCoreVisuals(InjectionAmount, _injecting);
|
||||||
|
|
||||||
UpdateUserInterface();
|
UpdateUserInterface();
|
||||||
ClickSound();
|
ClickSound();
|
||||||
@@ -272,11 +272,11 @@ namespace Content.Server.GameObjects.Components.Power.AME
|
|||||||
|
|
||||||
private void RefreshParts()
|
private void RefreshParts()
|
||||||
{
|
{
|
||||||
GetAMENodeGroup().RefreshAMENodes(this);
|
GetAMENodeGroup()?.RefreshAMENodes(this);
|
||||||
UpdateUserInterface();
|
UpdateUserInterface();
|
||||||
}
|
}
|
||||||
|
|
||||||
private AMENodeGroup GetAMENodeGroup()
|
private AMENodeGroup? GetAMENodeGroup()
|
||||||
{
|
{
|
||||||
Owner.TryGetComponent(out NodeContainerComponent? nodeContainer);
|
Owner.TryGetComponent(out NodeContainerComponent? nodeContainer);
|
||||||
|
|
||||||
@@ -285,12 +285,12 @@ namespace Content.Server.GameObjects.Components.Power.AME
|
|||||||
.OfType<AMENodeGroup>()
|
.OfType<AMENodeGroup>()
|
||||||
.First();
|
.First();
|
||||||
|
|
||||||
return engineNodeGroup ?? default!;
|
return engineNodeGroup;
|
||||||
}
|
}
|
||||||
|
|
||||||
private bool IsMasterController()
|
private bool IsMasterController()
|
||||||
{
|
{
|
||||||
if(GetAMENodeGroup().MasterController == this)
|
if(GetAMENodeGroup()?.MasterController == this)
|
||||||
{
|
{
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
@@ -301,10 +301,11 @@ namespace Content.Server.GameObjects.Components.Power.AME
|
|||||||
private int GetCoreCount()
|
private int GetCoreCount()
|
||||||
{
|
{
|
||||||
var coreCount = 0;
|
var coreCount = 0;
|
||||||
|
var group = GetAMENodeGroup();
|
||||||
|
|
||||||
if(GetAMENodeGroup() != null)
|
if (group != null)
|
||||||
{
|
{
|
||||||
coreCount = GetAMENodeGroup().CoreCount;
|
coreCount = group.CoreCount;
|
||||||
}
|
}
|
||||||
|
|
||||||
return coreCount;
|
return coreCount;
|
||||||
|
|||||||
@@ -1,6 +1,7 @@
|
|||||||
using Content.Server.GameObjects.Components.Stack;
|
using Content.Server.GameObjects.Components.Stack;
|
||||||
using Content.Server.Utility;
|
using Content.Server.Utility;
|
||||||
using Content.Shared.Interfaces.GameObjects.Components;
|
using Content.Shared.Interfaces.GameObjects.Components;
|
||||||
|
using Content.Shared.Utility;
|
||||||
using Robust.Server.Interfaces.GameObjects;
|
using Robust.Server.Interfaces.GameObjects;
|
||||||
using Robust.Shared.GameObjects;
|
using Robust.Shared.GameObjects;
|
||||||
using Robust.Shared.GameObjects.Components.Transform;
|
using Robust.Shared.GameObjects.Components.Transform;
|
||||||
@@ -36,7 +37,7 @@ namespace Content.Server.GameObjects.Components.Power
|
|||||||
/// <inheritdoc />
|
/// <inheritdoc />
|
||||||
public void AfterInteract(AfterInteractEventArgs eventArgs)
|
public void AfterInteract(AfterInteractEventArgs eventArgs)
|
||||||
{
|
{
|
||||||
if (!InteractionChecks.InRangeUnobstructed(eventArgs)) return;
|
if (!eventArgs.InRangeUnobstructed(ignoreInsideBlocker: true, popup: true)) return;
|
||||||
if(!_mapManager.TryGetGrid(eventArgs.ClickLocation.GridID, out var grid))
|
if(!_mapManager.TryGetGrid(eventArgs.ClickLocation.GridID, out var grid))
|
||||||
return;
|
return;
|
||||||
var snapPos = grid.SnapGridCellFor(eventArgs.ClickLocation, SnapGridOffset.Center);
|
var snapPos = grid.SnapGridCellFor(eventArgs.ClickLocation, SnapGridOffset.Center);
|
||||||
|
|||||||
@@ -4,6 +4,7 @@ using Content.Shared.GameObjects.Components.Strap;
|
|||||||
using Content.Shared.GameObjects.EntitySystems;
|
using Content.Shared.GameObjects.EntitySystems;
|
||||||
using Content.Shared.GameObjects.Verbs;
|
using Content.Shared.GameObjects.Verbs;
|
||||||
using Content.Shared.Interfaces.GameObjects.Components;
|
using Content.Shared.Interfaces.GameObjects.Components;
|
||||||
|
using Content.Shared.Utility;
|
||||||
using Robust.Server.GameObjects;
|
using Robust.Server.GameObjects;
|
||||||
using Robust.Shared.GameObjects;
|
using Robust.Shared.GameObjects;
|
||||||
using Robust.Shared.GameObjects.Systems;
|
using Robust.Shared.GameObjects.Systems;
|
||||||
@@ -202,14 +203,9 @@ namespace Content.Server.GameObjects.Components.Strap
|
|||||||
parent = parent.Parent;
|
parent = parent.Parent;
|
||||||
}
|
}
|
||||||
|
|
||||||
var userPosition = user.Transform.MapPosition;
|
|
||||||
var strapPosition = component.Owner.Transform.MapPosition;
|
|
||||||
var range = SharedInteractionSystem.InteractionRange / 2;
|
var range = SharedInteractionSystem.InteractionRange / 2;
|
||||||
var inRange = EntitySystem.Get<SharedInteractionSystem>()
|
|
||||||
.InRangeUnobstructed(userPosition, strapPosition, range,
|
|
||||||
predicate: entity => entity == user || entity == component.Owner);
|
|
||||||
|
|
||||||
if (!inRange)
|
if (!user.InRangeUnobstructed(component, range))
|
||||||
{
|
{
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -4,6 +4,7 @@ using Content.Server.GameObjects.Components.Nutrition;
|
|||||||
using Content.Server.Utility;
|
using Content.Server.Utility;
|
||||||
using Content.Shared.GameObjects.Components.Utensil;
|
using Content.Shared.GameObjects.Components.Utensil;
|
||||||
using Content.Shared.Interfaces.GameObjects.Components;
|
using Content.Shared.Interfaces.GameObjects.Components;
|
||||||
|
using Content.Shared.Utility;
|
||||||
using Robust.Server.GameObjects.EntitySystems;
|
using Robust.Server.GameObjects.EntitySystems;
|
||||||
using Robust.Shared.Audio;
|
using Robust.Shared.Audio;
|
||||||
using Robust.Shared.GameObjects;
|
using Robust.Shared.GameObjects;
|
||||||
@@ -121,7 +122,7 @@ namespace Content.Server.GameObjects.Components.Utensil
|
|||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (!InteractionChecks.InRangeUnobstructed(user, target.Transform.MapPosition))
|
if (!user.InRangeUnobstructed(target, popup: true))
|
||||||
{
|
{
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -1,6 +1,6 @@
|
|||||||
using System;
|
using System;
|
||||||
using Content.Server.Utility;
|
|
||||||
using Content.Shared.GameObjects.Components.Weapons;
|
using Content.Shared.GameObjects.Components.Weapons;
|
||||||
|
using Content.Shared.Utility;
|
||||||
using Robust.Server.GameObjects.EntitySystems;
|
using Robust.Server.GameObjects.EntitySystems;
|
||||||
using Robust.Shared.GameObjects;
|
using Robust.Shared.GameObjects;
|
||||||
using Robust.Shared.Interfaces.GameObjects;
|
using Robust.Shared.Interfaces.GameObjects;
|
||||||
@@ -32,7 +32,7 @@ namespace Content.Server.GameObjects.Components.Weapon
|
|||||||
{
|
{
|
||||||
foreach (var entity in IoCManager.Resolve<IEntityManager>().GetEntitiesInRange(source.Transform.GridPosition, range))
|
foreach (var entity in IoCManager.Resolve<IEntityManager>().GetEntitiesInRange(source.Transform.GridPosition, range))
|
||||||
{
|
{
|
||||||
if (!InteractionChecks.InRangeUnobstructed(source, entity.Transform.MapPosition, range, ignoredEnt:entity))
|
if (!source.InRangeUnobstructed(entity, range, popup: true))
|
||||||
continue;
|
continue;
|
||||||
|
|
||||||
if(entity.TryGetComponent(out FlashableComponent flashable))
|
if(entity.TryGetComponent(out FlashableComponent flashable))
|
||||||
|
|||||||
@@ -13,6 +13,7 @@ using Content.Shared.GameObjects.Components;
|
|||||||
using Content.Shared.GameObjects.Components.Interactable;
|
using Content.Shared.GameObjects.Components.Interactable;
|
||||||
using Content.Shared.GameObjects.EntitySystems;
|
using Content.Shared.GameObjects.EntitySystems;
|
||||||
using Content.Shared.Interfaces.GameObjects.Components;
|
using Content.Shared.Interfaces.GameObjects.Components;
|
||||||
|
using Content.Shared.Utility;
|
||||||
using JetBrains.Annotations;
|
using JetBrains.Annotations;
|
||||||
using Robust.Server.GameObjects;
|
using Robust.Server.GameObjects;
|
||||||
using Robust.Server.GameObjects.Components.UserInterface;
|
using Robust.Server.GameObjects.Components.UserInterface;
|
||||||
@@ -388,7 +389,7 @@ namespace Content.Server.GameObjects.Components
|
|||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (!EntitySystem.Get<SharedInteractionSystem>().InRangeUnobstructed(player.Transform.MapPosition, Owner.Transform.MapPosition, ignoredEnt: Owner))
|
if (!player.InRangeUnobstructed(Owner))
|
||||||
{
|
{
|
||||||
_notifyManager.PopupMessage(Owner.Transform.GridPosition, player,
|
_notifyManager.PopupMessage(Owner.Transform.GridPosition, player,
|
||||||
Loc.GetString("You can't reach there!"));
|
Loc.GetString("You can't reach there!"));
|
||||||
|
|||||||
@@ -7,8 +7,8 @@ using Content.Server.GameObjects.Components.Movement;
|
|||||||
using Content.Server.GameObjects.EntitySystems.AI.Pathfinding;
|
using Content.Server.GameObjects.EntitySystems.AI.Pathfinding;
|
||||||
using Content.Server.GameObjects.EntitySystems.AI.Pathfinding.Pathfinders;
|
using Content.Server.GameObjects.EntitySystems.AI.Pathfinding.Pathfinders;
|
||||||
using Content.Server.GameObjects.EntitySystems.JobQueues;
|
using Content.Server.GameObjects.EntitySystems.JobQueues;
|
||||||
using Content.Server.Utility;
|
|
||||||
using Content.Shared.GameObjects.EntitySystems;
|
using Content.Shared.GameObjects.EntitySystems;
|
||||||
|
using Content.Shared.Utility;
|
||||||
using Robust.Server.Interfaces.Timing;
|
using Robust.Server.Interfaces.Timing;
|
||||||
using Robust.Shared.GameObjects.Components;
|
using Robust.Shared.GameObjects.Components;
|
||||||
using Robust.Shared.GameObjects.Systems;
|
using Robust.Shared.GameObjects.Systems;
|
||||||
@@ -281,7 +281,7 @@ namespace Content.Server.GameObjects.EntitySystems.AI.Steering
|
|||||||
if (targetDistance <= steeringRequest.ArrivalDistance && steeringRequest.TimeUntilInteractionCheck <= 0.0f)
|
if (targetDistance <= steeringRequest.ArrivalDistance && steeringRequest.TimeUntilInteractionCheck <= 0.0f)
|
||||||
{
|
{
|
||||||
if (!steeringRequest.RequiresInRangeUnobstructed ||
|
if (!steeringRequest.RequiresInRangeUnobstructed ||
|
||||||
InteractionChecks.InRangeUnobstructed(entity, steeringRequest.TargetMap, steeringRequest.ArrivalDistance, ignoredEnt: entity))
|
entity.InRangeUnobstructed(steeringRequest.TargetMap, steeringRequest.ArrivalDistance, popup: true))
|
||||||
{
|
{
|
||||||
// TODO: Need cruder LOS checks for ranged weaps
|
// TODO: Need cruder LOS checks for ranged weaps
|
||||||
controller.VelocityDir = Vector2.Zero;
|
controller.VelocityDir = Vector2.Zero;
|
||||||
|
|||||||
@@ -12,8 +12,8 @@ using Content.Shared.GameObjects.EntitySystemMessages;
|
|||||||
using Content.Shared.GameObjects.EntitySystems;
|
using Content.Shared.GameObjects.EntitySystems;
|
||||||
using Content.Shared.Input;
|
using Content.Shared.Input;
|
||||||
using Content.Shared.Interfaces.GameObjects.Components;
|
using Content.Shared.Interfaces.GameObjects.Components;
|
||||||
using Content.Shared.Physics;
|
|
||||||
using Content.Shared.Physics.Pull;
|
using Content.Shared.Physics.Pull;
|
||||||
|
using Content.Shared.Utility;
|
||||||
using JetBrains.Annotations;
|
using JetBrains.Annotations;
|
||||||
using Robust.Server.GameObjects;
|
using Robust.Server.GameObjects;
|
||||||
using Robust.Server.Interfaces.Player;
|
using Robust.Server.Interfaces.Player;
|
||||||
@@ -71,7 +71,7 @@ namespace Content.Server.GameObjects.EntitySystems.Click
|
|||||||
var interactionArgs = new DragDropEventArgs(performer, msg.DropLocation, dropped, target);
|
var interactionArgs = new DragDropEventArgs(performer, msg.DropLocation, dropped, target);
|
||||||
|
|
||||||
// must be in range of both the target and the object they are drag / dropping
|
// must be in range of both the target and the object they are drag / dropping
|
||||||
if (!InteractionChecks.InRangeUnobstructed(interactionArgs)) return;
|
if (!interactionArgs.InRangeUnobstructed(ignoreInsideBlocker: true, popup: true)) return;
|
||||||
|
|
||||||
// trigger dragdrops on the dropped entity
|
// trigger dragdrops on the dropped entity
|
||||||
foreach (var dragDrop in dropped.GetAllComponents<IDragDrop>())
|
foreach (var dragDrop in dropped.GetAllComponents<IDragDrop>())
|
||||||
@@ -145,7 +145,7 @@ namespace Content.Server.GameObjects.EntitySystems.Click
|
|||||||
|
|
||||||
// all activates should only fire when in range / unbostructed
|
// all activates should only fire when in range / unbostructed
|
||||||
var activateEventArgs = new ActivateEventArgs {User = user, Target = used};
|
var activateEventArgs = new ActivateEventArgs {User = user, Target = used};
|
||||||
if (InteractionChecks.InRangeUnobstructed(activateEventArgs))
|
if (activateEventArgs.InRangeUnobstructed(ignoreInsideBlocker: true, popup: true))
|
||||||
{
|
{
|
||||||
activateComp.Activate(activateEventArgs);
|
activateComp.Activate(activateEventArgs);
|
||||||
}
|
}
|
||||||
@@ -453,7 +453,7 @@ namespace Content.Server.GameObjects.EntitySystems.Click
|
|||||||
};
|
};
|
||||||
|
|
||||||
// all AttackBys should only happen when in range / unobstructed, so no range check is needed
|
// all AttackBys should only happen when in range / unobstructed, so no range check is needed
|
||||||
if (InteractionChecks.InRangeUnobstructed(attackByEventArgs))
|
if (attackByEventArgs.InRangeUnobstructed(ignoreInsideBlocker: true, popup: true))
|
||||||
{
|
{
|
||||||
foreach (var attackBy in attackBys)
|
foreach (var attackBy in attackBys)
|
||||||
{
|
{
|
||||||
@@ -501,8 +501,8 @@ namespace Content.Server.GameObjects.EntitySystems.Click
|
|||||||
var attackHands = attacked.GetAllComponents<IInteractHand>().ToList();
|
var attackHands = attacked.GetAllComponents<IInteractHand>().ToList();
|
||||||
var attackHandEventArgs = new InteractHandEventArgs {User = user, Target = attacked};
|
var attackHandEventArgs = new InteractHandEventArgs {User = user, Target = attacked};
|
||||||
|
|
||||||
// all attackHands should only fire when in range / unbostructed
|
// all attackHands should only fire when in range / unobstructed
|
||||||
if (InteractionChecks.InRangeUnobstructed(attackHandEventArgs))
|
if (attackHandEventArgs.InRangeUnobstructed(ignoreInsideBlocker: true, popup: true))
|
||||||
{
|
{
|
||||||
foreach (var attackHand in attackHands)
|
foreach (var attackHand in attackHands)
|
||||||
{
|
{
|
||||||
|
|||||||
@@ -6,19 +6,18 @@ using Content.Server.GameObjects.Components.GUI;
|
|||||||
using Content.Server.GameObjects.Components.Interactable;
|
using Content.Server.GameObjects.Components.Interactable;
|
||||||
using Content.Server.GameObjects.Components.Items.Storage;
|
using Content.Server.GameObjects.Components.Items.Storage;
|
||||||
using Content.Server.GameObjects.Components.Stack;
|
using Content.Server.GameObjects.Components.Stack;
|
||||||
using Content.Server.GameObjects.EntitySystems.Click;
|
|
||||||
using Content.Server.Utility;
|
using Content.Server.Utility;
|
||||||
using Content.Shared.Construction;
|
using Content.Shared.Construction;
|
||||||
using Content.Shared.GameObjects.Components;
|
using Content.Shared.GameObjects.Components;
|
||||||
using Content.Shared.GameObjects.Components.Interactable;
|
using Content.Shared.GameObjects.Components.Interactable;
|
||||||
using Content.Shared.GameObjects.EntitySystems;
|
using Content.Shared.GameObjects.EntitySystems;
|
||||||
using Content.Shared.Interfaces.GameObjects.Components;
|
using Content.Shared.Interfaces.GameObjects.Components;
|
||||||
|
using Content.Shared.Utility;
|
||||||
using JetBrains.Annotations;
|
using JetBrains.Annotations;
|
||||||
using Robust.Server.GameObjects;
|
using Robust.Server.GameObjects;
|
||||||
using Robust.Server.GameObjects.EntitySystems;
|
using Robust.Server.GameObjects.EntitySystems;
|
||||||
using Robust.Server.Interfaces.Player;
|
using Robust.Server.Interfaces.Player;
|
||||||
using Robust.Shared.GameObjects;
|
using Robust.Shared.GameObjects;
|
||||||
using Robust.Shared.GameObjects.Systems;
|
|
||||||
using Robust.Shared.Interfaces.GameObjects;
|
using Robust.Shared.Interfaces.GameObjects;
|
||||||
using Robust.Shared.Interfaces.GameObjects.Components;
|
using Robust.Shared.Interfaces.GameObjects.Components;
|
||||||
using Robust.Shared.Interfaces.Map;
|
using Robust.Shared.Interfaces.Map;
|
||||||
@@ -91,8 +90,7 @@ namespace Content.Server.GameObjects.EntitySystems
|
|||||||
if(targetEnt is null || handEnt is null)
|
if(targetEnt is null || handEnt is null)
|
||||||
return;
|
return;
|
||||||
|
|
||||||
var interaction = Get<InteractionSystem>();
|
if (!handEnt.InRangeUnobstructed(targetEnt, ignoreInsideBlocker: true))
|
||||||
if(!interaction.InRangeUnobstructed(handEnt.Transform.MapPosition, targetEnt.Transform.MapPosition, ignoredEnt: targetEnt, ignoreInsideBlocker: true))
|
|
||||||
return;
|
return;
|
||||||
|
|
||||||
// Cannot deconstruct an entity with no prototype.
|
// Cannot deconstruct an entity with no prototype.
|
||||||
@@ -246,8 +244,7 @@ namespace Content.Server.GameObjects.EntitySystems
|
|||||||
{
|
{
|
||||||
var prototype = _prototypeManager.Index<ConstructionPrototype>(prototypeName);
|
var prototype = _prototypeManager.Index<ConstructionPrototype>(prototypeName);
|
||||||
|
|
||||||
if (!InteractionChecks.InRangeUnobstructed(placingEnt, loc.ToMap(_mapManager),
|
if (!placingEnt.InRangeUnobstructed(loc, ignoreInsideBlocker: prototype.CanBuildInImpassable, popup: true))
|
||||||
ignoredEnt: placingEnt, ignoreInsideBlocker: prototype.CanBuildInImpassable))
|
|
||||||
{
|
{
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
@@ -377,7 +374,7 @@ namespace Content.Server.GameObjects.EntitySystems
|
|||||||
var constructPrototype = constructionComponent.Prototype;
|
var constructPrototype = constructionComponent.Prototype;
|
||||||
if (constructPrototype.CanBuildInImpassable == false)
|
if (constructPrototype.CanBuildInImpassable == false)
|
||||||
{
|
{
|
||||||
if (!InteractionChecks.InRangeUnobstructed(user, constructEntity.Transform.MapPosition))
|
if (!user.InRangeUnobstructed(constructEntity, popup: true))
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -3,6 +3,7 @@ using System;
|
|||||||
using System.Threading;
|
using System.Threading;
|
||||||
using Content.Shared.GameObjects.EntitySystems;
|
using Content.Shared.GameObjects.EntitySystems;
|
||||||
using Content.Shared.Physics;
|
using Content.Shared.Physics;
|
||||||
|
using Content.Shared.Utility;
|
||||||
using Robust.Shared.GameObjects.Systems;
|
using Robust.Shared.GameObjects.Systems;
|
||||||
using Robust.Shared.Interfaces.GameObjects;
|
using Robust.Shared.Interfaces.GameObjects;
|
||||||
|
|
||||||
@@ -13,17 +14,17 @@ namespace Content.Server.GameObjects.EntitySystems.DoAfter
|
|||||||
public sealed class DoAfterEventArgs
|
public sealed class DoAfterEventArgs
|
||||||
{
|
{
|
||||||
// Premade checks
|
// Premade checks
|
||||||
public Func<bool> GetInRangeUnobstructed(int collisionMask = (int) CollisionGroup.MobMask)
|
public Func<bool> GetInRangeUnobstructed(CollisionGroup collisionMask = CollisionGroup.MobMask)
|
||||||
{
|
{
|
||||||
if (Target == null)
|
if (Target == null)
|
||||||
{
|
{
|
||||||
throw new InvalidOperationException("Can't supply a null target to DoAfterEventArgs.GetInRangeUnobstructed");
|
throw new InvalidOperationException("Can't supply a null target to DoAfterEventArgs.GetInRangeUnobstructed");
|
||||||
}
|
}
|
||||||
var interactionSystem = EntitySystem.Get<SharedInteractionSystem>();
|
|
||||||
Func<IEntity, bool> ignored = entity => entity == User || entity == Target;
|
bool Ignored(IEntity entity) => entity == User || entity == Target;
|
||||||
return () => interactionSystem.InRangeUnobstructed(User.Transform.MapPosition, Target.Transform.MapPosition, collisionMask: collisionMask, predicate: ignored);
|
return () => User.InRangeUnobstructed(Target, collisionMask: collisionMask, predicate: Ignored);
|
||||||
}
|
}
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// The entity invoking do_after
|
/// The entity invoking do_after
|
||||||
/// </summary>
|
/// </summary>
|
||||||
@@ -71,7 +72,7 @@ namespace Content.Server.GameObjects.EntitySystems.DoAfter
|
|||||||
/// Anything that needs a pre-check should do it itself so no DoAfterState is ever sent to the client.
|
/// Anything that needs a pre-check should do it itself so no DoAfterState is ever sent to the client.
|
||||||
/// </remarks>
|
/// </remarks>
|
||||||
public Func<bool>? PostCheck { get; set; } = null;
|
public Func<bool>? PostCheck { get; set; } = null;
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// Additional conditions that need to be met. Return false to cancel.
|
/// Additional conditions that need to be met. Return false to cancel.
|
||||||
/// </summary>
|
/// </summary>
|
||||||
|
|||||||
@@ -125,7 +125,7 @@ namespace Content.Server.GameObjects.EntitySystems
|
|||||||
var entToDesiredDropCoords = coords.Position - entCoords;
|
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 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 newCoords = new GridCoordinates((entToDesiredDropCoords.Normalized * targetLength) + entCoords, coords.GridID);
|
||||||
var rayLength = Get<SharedInteractionSystem>().UnobstructedRayLength(ent.Transform.MapPosition, newCoords.ToMap(_mapManager), ignoredEnt: ent);
|
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));
|
handsComp.Drop(handsComp.ActiveHand, new GridCoordinates(entCoords + (entToDesiredDropCoords.Normalized * rayLength), coords.GridID));
|
||||||
|
|
||||||
|
|||||||
@@ -1,124 +0,0 @@
|
|||||||
using Content.Shared.GameObjects.EntitySystems;
|
|
||||||
using Content.Shared.Interfaces;
|
|
||||||
using Content.Shared.Interfaces.GameObjects.Components;
|
|
||||||
using Content.Shared.Physics;
|
|
||||||
using Robust.Shared.GameObjects.Systems;
|
|
||||||
using Robust.Shared.Interfaces.GameObjects;
|
|
||||||
using Robust.Shared.Interfaces.Map;
|
|
||||||
using Robust.Shared.IoC;
|
|
||||||
using Robust.Shared.Localization;
|
|
||||||
using Robust.Shared.Map;
|
|
||||||
|
|
||||||
namespace Content.Server.Utility
|
|
||||||
{
|
|
||||||
/// <summary>
|
|
||||||
/// Convenient methods for checking for various conditions commonly needed
|
|
||||||
/// for interactions.
|
|
||||||
/// </summary>
|
|
||||||
public static class InteractionChecks
|
|
||||||
{
|
|
||||||
|
|
||||||
/// <summary>
|
|
||||||
/// Default interaction check for targeted attack interaction types.
|
|
||||||
/// Same as <see cref="SharedInteractionSystem.InRangeUnobstructed"/>, but defaults to ignore inside blockers
|
|
||||||
/// (making the check less restrictive).
|
|
||||||
/// Validates that attacker is in range of the attacked entity. Additionally shows a popup if
|
|
||||||
/// validation fails.
|
|
||||||
/// </summary>
|
|
||||||
public static bool InRangeUnobstructed(ITargetedInteractEventArgs eventArgs, bool ignoreInsideBlocker = true)
|
|
||||||
{
|
|
||||||
if (!EntitySystem.Get<SharedInteractionSystem>().InRangeUnobstructed(eventArgs.User.Transform.MapPosition,
|
|
||||||
eventArgs.Target.Transform.MapPosition, ignoredEnt: eventArgs.Target, ignoreInsideBlocker: ignoreInsideBlocker))
|
|
||||||
{
|
|
||||||
var localizationManager = IoCManager.Resolve<ILocalizationManager>();
|
|
||||||
eventArgs.Target.PopupMessage(eventArgs.User, localizationManager.GetString("You can't reach there!"));
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
|
|
||||||
return true;
|
|
||||||
}
|
|
||||||
|
|
||||||
/// <summary>
|
|
||||||
/// Default interaction check for Drag drop interaction types.
|
|
||||||
/// Same as <see cref="SharedInteractionSystem.InRangeUnobstructed"/>, but defaults to ignore inside blockers
|
|
||||||
/// (making the check less restrictive) and checks reachability of both the target and the dragged / dropped object.
|
|
||||||
/// Additionally shows a popup if validation fails.
|
|
||||||
/// </summary>
|
|
||||||
public static bool InRangeUnobstructed(DragDropEventArgs eventArgs, bool ignoreInsideBlocker = true)
|
|
||||||
{
|
|
||||||
if (!EntitySystem.Get<SharedInteractionSystem>().InRangeUnobstructed(eventArgs.User.Transform.MapPosition,
|
|
||||||
eventArgs.Target.Transform.MapPosition, ignoredEnt: eventArgs.Target, ignoreInsideBlocker: ignoreInsideBlocker))
|
|
||||||
{
|
|
||||||
var localizationManager = IoCManager.Resolve<ILocalizationManager>();
|
|
||||||
eventArgs.Target.PopupMessage(eventArgs.User, localizationManager.GetString("You can't reach there!"));
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
if (!EntitySystem.Get<SharedInteractionSystem>().InRangeUnobstructed(eventArgs.User.Transform.MapPosition,
|
|
||||||
eventArgs.Dropped.Transform.MapPosition, ignoredEnt: eventArgs.Dropped, ignoreInsideBlocker: ignoreInsideBlocker))
|
|
||||||
{
|
|
||||||
var localizationManager = IoCManager.Resolve<ILocalizationManager>();
|
|
||||||
eventArgs.Dropped.PopupMessage(eventArgs.User, localizationManager.GetString("You can't reach there!"));
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
|
|
||||||
return true;
|
|
||||||
}
|
|
||||||
|
|
||||||
/// <summary>
|
|
||||||
/// Default interaction check for after attack interaction types.
|
|
||||||
/// Same as <see cref="SharedInteractionSystem.InRangeUnobstructed"/>, but defaults to ignore inside blockers
|
|
||||||
/// (making the check less restrictive).
|
|
||||||
/// Validates that attacker is in range of the attacked entity, if there is such an entity.
|
|
||||||
/// If there is no attacked entity, validates that they are in range of the clicked position.
|
|
||||||
/// Additionally shows a popup if validation fails.
|
|
||||||
/// </summary>
|
|
||||||
public static bool InRangeUnobstructed(AfterInteractEventArgs eventArgs, bool ignoreInsideBlocker = true)
|
|
||||||
{
|
|
||||||
if (eventArgs.Target != null)
|
|
||||||
{
|
|
||||||
if (!EntitySystem.Get<SharedInteractionSystem>().InRangeUnobstructed(eventArgs.User.Transform.MapPosition,
|
|
||||||
eventArgs.Target.Transform.MapPosition, ignoredEnt: eventArgs.Target, ignoreInsideBlocker: ignoreInsideBlocker))
|
|
||||||
{
|
|
||||||
var localizationManager = IoCManager.Resolve<ILocalizationManager>();
|
|
||||||
eventArgs.Target.PopupMessage(eventArgs.User, localizationManager.GetString("You can't reach there!"));
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
if (!EntitySystem.Get<SharedInteractionSystem>().InRangeUnobstructed(eventArgs.User.Transform.MapPosition,
|
|
||||||
eventArgs.ClickLocation.ToMap(IoCManager.Resolve<IMapManager>()), ignoredEnt: eventArgs.User, ignoreInsideBlocker: ignoreInsideBlocker))
|
|
||||||
{
|
|
||||||
var localizationManager = IoCManager.Resolve<ILocalizationManager>();
|
|
||||||
eventArgs.User.PopupMessage(eventArgs.User, localizationManager.GetString("You can't reach there!"));
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
return true;
|
|
||||||
}
|
|
||||||
|
|
||||||
/// <summary>
|
|
||||||
/// Convenient static alternative to <see cref="SharedInteractionSystem.InRangeUnobstructed"/>, which also
|
|
||||||
/// shows a popup message if not in range.
|
|
||||||
/// </summary>
|
|
||||||
public static bool InRangeUnobstructed(IEntity user, MapCoordinates otherCoords,
|
|
||||||
float range = SharedInteractionSystem.InteractionRange,
|
|
||||||
int collisionMask = (int) CollisionGroup.Impassable, IEntity ignoredEnt = null, bool ignoreInsideBlocker = false)
|
|
||||||
{
|
|
||||||
var mapManager = IoCManager.Resolve<IMapManager>();
|
|
||||||
var interactionSystem = EntitySystem.Get<SharedInteractionSystem>();
|
|
||||||
if (!interactionSystem.InRangeUnobstructed(user.Transform.MapPosition, otherCoords, range, collisionMask,
|
|
||||||
ignoredEnt, ignoreInsideBlocker))
|
|
||||||
{
|
|
||||||
var localizationManager = IoCManager.Resolve<ILocalizationManager>();
|
|
||||||
user.PopupMessage(user, localizationManager.GetString("You can't reach there!"));
|
|
||||||
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
|
|
||||||
return true;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
@@ -1,11 +1,13 @@
|
|||||||
using System;
|
using System;
|
||||||
using Content.Shared.GameObjects.Components.Mobs;
|
using Content.Shared.GameObjects.Components.Mobs;
|
||||||
|
using Content.Shared.Utility;
|
||||||
using JetBrains.Annotations;
|
using JetBrains.Annotations;
|
||||||
using Robust.Shared.Containers;
|
using Robust.Shared.Containers;
|
||||||
using Robust.Shared.GameObjects.Systems;
|
using Robust.Shared.GameObjects.Systems;
|
||||||
using Robust.Shared.Interfaces.GameObjects;
|
using Robust.Shared.Interfaces.GameObjects;
|
||||||
using Robust.Shared.Maths;
|
using Robust.Shared.Maths;
|
||||||
using Robust.Shared.Utility;
|
using Robust.Shared.Utility;
|
||||||
|
using static Content.Shared.GameObjects.EntitySystems.SharedInteractionSystem;
|
||||||
|
|
||||||
namespace Content.Shared.GameObjects.EntitySystems
|
namespace Content.Shared.GameObjects.EntitySystems
|
||||||
{
|
{
|
||||||
@@ -26,11 +28,8 @@ namespace Content.Shared.GameObjects.EntitySystems
|
|||||||
|
|
||||||
private static bool IsInDetailsRange(IEntity examiner, IEntity entity)
|
private static bool IsInDetailsRange(IEntity examiner, IEntity entity)
|
||||||
{
|
{
|
||||||
return Get<SharedInteractionSystem>()
|
return examiner.InRangeUnobstructed(entity, ExamineDetailsRange, ignoreInsideBlocker: true) &&
|
||||||
.InRangeUnobstructed(examiner.Transform.MapPosition, entity.Transform.MapPosition,
|
examiner.IsInSameOrNoContainer(entity);
|
||||||
ExamineDetailsRange, predicate: entity0 => entity0 == examiner || entity0 == entity,
|
|
||||||
ignoreInsideBlocker: true) &&
|
|
||||||
examiner.IsInSameOrNoContainer(entity);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
[Pure]
|
[Pure]
|
||||||
@@ -51,16 +50,14 @@ namespace Content.Shared.GameObjects.EntitySystems
|
|||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
Func<IEntity, bool> predicate = entity => entity == examiner || entity == examined;
|
Ignored predicate = entity => entity == examiner || entity == examined;
|
||||||
|
|
||||||
if (ContainerHelpers.TryGetContainer(examiner, out var container))
|
if (ContainerHelpers.TryGetContainer(examiner, out var container))
|
||||||
{
|
{
|
||||||
predicate += entity => entity == container.Owner;
|
predicate += entity => entity == container.Owner;
|
||||||
}
|
}
|
||||||
|
|
||||||
return Get<SharedInteractionSystem>()
|
return examiner.InRangeUnobstructed(examined, ExamineRange, predicate: predicate, ignoreInsideBlocker: true);
|
||||||
.InRangeUnobstructed(examiner.Transform.MapPosition, examined.Transform.MapPosition,
|
|
||||||
ExamineRange, predicate: predicate, ignoreInsideBlocker:true);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
public static FormattedMessage GetExamineText(IEntity entity, IEntity examiner)
|
public static FormattedMessage GetExamineText(IEntity entity, IEntity examiner)
|
||||||
|
|||||||
@@ -1,11 +1,14 @@
|
|||||||
using System;
|
using System.Linq;
|
||||||
using System.Linq;
|
using Content.Shared.Interfaces;
|
||||||
|
using Content.Shared.Interfaces.GameObjects.Components;
|
||||||
using Content.Shared.Physics;
|
using Content.Shared.Physics;
|
||||||
using JetBrains.Annotations;
|
using JetBrains.Annotations;
|
||||||
using Robust.Shared.GameObjects.Systems;
|
using Robust.Shared.GameObjects.Systems;
|
||||||
using Robust.Shared.Interfaces.GameObjects;
|
using Robust.Shared.Interfaces.GameObjects;
|
||||||
|
using Robust.Shared.Interfaces.Map;
|
||||||
using Robust.Shared.Interfaces.Physics;
|
using Robust.Shared.Interfaces.Physics;
|
||||||
using Robust.Shared.IoC;
|
using Robust.Shared.IoC;
|
||||||
|
using Robust.Shared.Localization;
|
||||||
using Robust.Shared.Map;
|
using Robust.Shared.Map;
|
||||||
using Robust.Shared.Maths;
|
using Robust.Shared.Maths;
|
||||||
|
|
||||||
@@ -18,98 +21,516 @@ namespace Content.Shared.GameObjects.EntitySystems
|
|||||||
public class SharedInteractionSystem : EntitySystem
|
public class SharedInteractionSystem : EntitySystem
|
||||||
{
|
{
|
||||||
[Dependency] private readonly IPhysicsManager _physicsManager = default!;
|
[Dependency] private readonly IPhysicsManager _physicsManager = default!;
|
||||||
|
[Dependency] private readonly IMapManager _mapManager = default!;
|
||||||
|
|
||||||
public const float InteractionRange = 2;
|
public const float InteractionRange = 2;
|
||||||
public const float InteractionRangeSquared = InteractionRange * InteractionRange;
|
public const float InteractionRangeSquared = InteractionRange * InteractionRange;
|
||||||
|
|
||||||
|
public delegate bool Ignored(IEntity entity);
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// Traces a ray from coords to otherCoords and returns the length
|
/// Traces a ray from coords to otherCoords and returns the length
|
||||||
/// of the vector between coords and the ray's first hit.
|
/// of the vector between coords and the ray's first hit.
|
||||||
/// </summary>
|
/// </summary>
|
||||||
/// <param name="coords">Set of coordinates to use.</param>
|
/// <param name="origin">Set of coordinates to use.</param>
|
||||||
/// <param name="otherCoords">Other set of coordinates to use.</param>
|
/// <param name="other">Other set of coordinates to use.</param>
|
||||||
/// <param name="collisionMask">the mask to check for collisions</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="predicate">
|
||||||
|
/// A predicate to check whether to ignore an entity or not.
|
||||||
|
/// If it returns true, it will be ignored.
|
||||||
|
/// </param>
|
||||||
/// <returns>Length of resulting ray.</returns>
|
/// <returns>Length of resulting ray.</returns>
|
||||||
public float UnobstructedRayLength(MapCoordinates coords, MapCoordinates otherCoords,
|
public float UnobstructedDistance(
|
||||||
int collisionMask = (int) CollisionGroup.Impassable, Func<IEntity, bool> predicate = null)
|
MapCoordinates origin,
|
||||||
|
MapCoordinates other,
|
||||||
|
int collisionMask = (int) CollisionGroup.Impassable,
|
||||||
|
Ignored predicate = null)
|
||||||
{
|
{
|
||||||
var dir = otherCoords.Position - coords.Position;
|
var dir = other.Position - origin.Position;
|
||||||
|
|
||||||
if (dir.LengthSquared.Equals(0f)) return 0f;
|
if (dir.LengthSquared.Equals(0f)) return 0f;
|
||||||
|
|
||||||
var ray = new CollisionRay(coords.Position, dir.Normalized, collisionMask);
|
predicate ??= _ => false;
|
||||||
var rayResults = _physicsManager.IntersectRayWithPredicate(coords.MapId, ray, dir.Length, predicate, returnOnFirstHit: false).ToList();
|
var ray = new CollisionRay(origin.Position, dir.Normalized, collisionMask);
|
||||||
|
var rayResults = _physicsManager.IntersectRayWithPredicate(origin.MapId, ray, dir.Length, predicate.Invoke, false).ToList();
|
||||||
|
|
||||||
if (rayResults.Count == 0) return dir.Length;
|
if (rayResults.Count == 0) return dir.Length;
|
||||||
return (rayResults[0].HitPos - coords.Position).Length;
|
return (rayResults[0].HitPos - origin.Position).Length;
|
||||||
}
|
}
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// Traces a ray from coords to otherCoords and returns the length
|
/// Traces a ray from coords to otherCoords and returns the length
|
||||||
/// of the vector between coords and the ray's first hit.
|
/// of the vector between coords and the ray's first hit.
|
||||||
/// </summary>
|
/// </summary>
|
||||||
/// <param name="coords">Set of coordinates to use.</param>
|
/// <param name="origin">Set of coordinates to use.</param>
|
||||||
/// <param name="otherCoords">Other set of coordinates to use.</param>
|
/// <param name="other">Other set of coordinates to use.</param>
|
||||||
/// <param name="collisionMask">the mask to check for collisions</param>
|
/// <param name="collisionMask">The mask to check for collisions</param>
|
||||||
/// <param name="ignoredEnt">the entity to be ignored when checking for collisions.</param>
|
/// <param name="ignoredEnt">
|
||||||
|
/// The entity to be ignored when checking for collisions.
|
||||||
|
/// </param>
|
||||||
/// <returns>Length of resulting ray.</returns>
|
/// <returns>Length of resulting ray.</returns>
|
||||||
public float UnobstructedRayLength(MapCoordinates coords, MapCoordinates otherCoords,
|
public float UnobstructedDistance(
|
||||||
int collisionMask = (int) CollisionGroup.Impassable, IEntity ignoredEnt = null) =>
|
MapCoordinates origin,
|
||||||
UnobstructedRayLength(coords, otherCoords, collisionMask,
|
MapCoordinates other,
|
||||||
ignoredEnt == null ? null : (Func<IEntity, bool>) (entity => ignoredEnt == entity));
|
int collisionMask = (int) CollisionGroup.Impassable,
|
||||||
|
IEntity ignoredEnt = null)
|
||||||
|
{
|
||||||
|
var predicate = ignoredEnt == null
|
||||||
|
? null
|
||||||
|
: (Ignored) (e => e == ignoredEnt);
|
||||||
|
|
||||||
|
return UnobstructedDistance(origin, other, collisionMask, predicate);
|
||||||
|
}
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// Checks that these coordinates are within a certain distance without any
|
/// Checks that these coordinates are within a certain distance without any
|
||||||
/// entity that matches the collision mask obstructing them.
|
/// entity that matches the collision mask obstructing them.
|
||||||
/// If the <paramref name="range"/> is zero or negative,
|
/// If the <paramref name="range"/> is zero or negative,
|
||||||
/// this method will only check if nothing obstructs the two sets of coordinates..
|
/// this method will only check if nothing obstructs the two sets
|
||||||
|
/// of coordinates.
|
||||||
/// </summary>
|
/// </summary>
|
||||||
/// <param name="coords">Set of coordinates to use.</param>
|
/// <param name="origin">Set of coordinates to use.</param>
|
||||||
/// <param name="otherCoords">Other set of coordinates to use.</param>
|
/// <param name="other">Other set of coordinates to use.</param>
|
||||||
/// <param name="range">maximum distance between the two sets of coordinates.</param>
|
/// <param name="range">
|
||||||
/// <param name="collisionMask">the mask to check for collisions</param>
|
/// Maximum distance between the two sets of coordinates.
|
||||||
/// <param name="predicate">A predicate to check whether to ignore an entity or not. If it returns true, it will be ignored.</param>
|
/// </param>
|
||||||
/// <param name="ignoreInsideBlocker">if true and the coordinates are inside the obstruction, ignores the obstruction and
|
/// <param name="collisionMask">The mask to check for collisions.</param>
|
||||||
/// considers the interaction unobstructed. Therefore, setting this to true makes this check more permissive, such
|
/// <param name="predicate">
|
||||||
/// as allowing an interaction to occur inside something impassable (like a wall). The default, false,
|
/// A predicate to check whether to ignore an entity or not.
|
||||||
/// makes the check more restrictive.</param>
|
/// If it returns true, it will be ignored.
|
||||||
/// <returns>True if the two points are within a given range without being obstructed.</returns>
|
/// </param>
|
||||||
public bool InRangeUnobstructed(MapCoordinates coords, MapCoordinates otherCoords, float range = InteractionRange,
|
/// <param name="ignoreInsideBlocker">
|
||||||
int collisionMask = (int)CollisionGroup.Impassable, Func<IEntity, bool> predicate = null, bool ignoreInsideBlocker = false)
|
/// 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>
|
||||||
|
/// <returns>
|
||||||
|
/// True if the two points are within a given range without being obstructed.
|
||||||
|
/// </returns>
|
||||||
|
public bool InRangeUnobstructed(
|
||||||
|
MapCoordinates origin,
|
||||||
|
MapCoordinates other,
|
||||||
|
float range = InteractionRange,
|
||||||
|
CollisionGroup collisionMask = CollisionGroup.Impassable,
|
||||||
|
Ignored predicate = null,
|
||||||
|
bool ignoreInsideBlocker = false)
|
||||||
{
|
{
|
||||||
if (!coords.InRange(otherCoords, range))
|
if (!origin.InRange(other, range)) return false;
|
||||||
return false;
|
|
||||||
|
|
||||||
var dir = otherCoords.Position - coords.Position;
|
var dir = other.Position - origin.Position;
|
||||||
|
|
||||||
if (dir.LengthSquared.Equals(0f)) return true;
|
if (dir.LengthSquared.Equals(0f)) return true;
|
||||||
if (range > 0f && !(dir.LengthSquared <= range * range)) return false;
|
if (range > 0f && !(dir.LengthSquared <= range * range)) return false;
|
||||||
|
|
||||||
var ray = new CollisionRay(coords.Position, dir.Normalized, collisionMask);
|
predicate ??= _ => false;
|
||||||
var rayResults = _physicsManager.IntersectRayWithPredicate(coords.MapId, ray, dir.Length, predicate, returnOnFirstHit: false).ToList();
|
|
||||||
return rayResults.Count == 0 || (ignoreInsideBlocker && rayResults.Count > 0 && (rayResults[0].HitPos - otherCoords.Position).Length < 1f);
|
var ray = new CollisionRay(origin.Position, dir.Normalized, (int) collisionMask);
|
||||||
|
var rayResults = _physicsManager.IntersectRayWithPredicate(origin.MapId, ray, dir.Length, predicate.Invoke, false).ToList();
|
||||||
|
|
||||||
|
if (rayResults.Count == 0) return true;
|
||||||
|
|
||||||
|
if (!ignoreInsideBlocker) return false;
|
||||||
|
|
||||||
|
if (rayResults.Count <= 0) return false;
|
||||||
|
|
||||||
|
return (rayResults[0].HitPos - other.Position).Length < 1f;
|
||||||
}
|
}
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// Checks that these coordinates are within a certain distance without any
|
/// Checks that two entities are within a certain distance without any
|
||||||
/// entity that matches the collision mask obstructing them.
|
/// entity that matches the collision mask obstructing them.
|
||||||
/// If the <paramref name="range"/> is zero or negative,
|
/// If the <paramref name="range"/> is zero or negative,
|
||||||
/// this method will only check if nothing obstructs the two sets of coordinates..
|
/// this method will only check if nothing obstructs the two entities.
|
||||||
/// </summary>
|
/// </summary>
|
||||||
/// <param name="coords">Set of coordinates to use.</param>
|
/// <param name="origin">The first entity to use.</param>
|
||||||
/// <param name="otherCoords">Other set of coordinates to use.</param>
|
/// <param name="other">Other entity to use.</param>
|
||||||
/// <param name="range">maximum distance between the two sets of coordinates.</param>
|
/// <param name="range">
|
||||||
/// <param name="collisionMask">the mask to check for collisions</param>
|
/// Maximum distance between the two entities.
|
||||||
/// <param name="ignoredEnt">the entity to be ignored when checking for collisions.</param>
|
/// </param>
|
||||||
/// <param name="ignoreInsideBlocker">if true and the coordinates are inside the obstruction, ignores the obstruction and
|
/// <param name="collisionMask">The mask to check for collisions.</param>
|
||||||
/// considers the interaction unobstructed. Therefore, setting this to true makes this check more permissive, such
|
/// <param name="predicate">
|
||||||
/// as allowing an interaction to occur inside something impassable (like a wall). The default, false,
|
/// A predicate to check whether to ignore an entity or not.
|
||||||
/// makes the check more restrictive.</param>
|
/// If it returns true, it will be ignored.
|
||||||
/// <returns>True if the two points are within a given range without being obstructed.</returns>
|
/// </param>
|
||||||
public bool InRangeUnobstructed(MapCoordinates coords, MapCoordinates otherCoords, float range = InteractionRange,
|
/// <param name="ignoreInsideBlocker">
|
||||||
int collisionMask = (int)CollisionGroup.Impassable, IEntity ignoredEnt = null, bool ignoreInsideBlocker = false) =>
|
/// If true and <see cref="origin"/> or <see cref="other"/> are inside
|
||||||
InRangeUnobstructed(coords, otherCoords, range, collisionMask,
|
/// the obstruction, ignores the obstruction and considers the interaction
|
||||||
ignoredEnt == null ? null : (Func<IEntity, bool>)(entity => ignoredEnt == entity), ignoreInsideBlocker);
|
/// 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,
|
||||||
|
IEntity 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.Transform.MapPosition;
|
||||||
|
predicate ??= e => e == origin || e == other;
|
||||||
|
|
||||||
|
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;
|
||||||
|
}
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Checks that an entity and a component 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 component to use.</param>
|
||||||
|
/// <param name="range">
|
||||||
|
/// Maximum distance between the entity and component.
|
||||||
|
/// </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,
|
||||||
|
IComponent 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.Owner.Transform.MapPosition;
|
||||||
|
predicate ??= e => e == origin || e == other.Owner;
|
||||||
|
|
||||||
|
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;
|
||||||
|
}
|
||||||
|
|
||||||
|
/// <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;
|
||||||
|
}
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Checks that an entity and a set of map 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 map coordinates to use.</param>
|
||||||
|
/// <param name="range">
|
||||||
|
/// Maximum distance between the two entity and set of map 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,
|
||||||
|
MapCoordinates other,
|
||||||
|
float range = InteractionRange,
|
||||||
|
CollisionGroup collisionMask = CollisionGroup.Impassable,
|
||||||
|
Ignored predicate = null,
|
||||||
|
bool ignoreInsideBlocker = false,
|
||||||
|
bool popup = false)
|
||||||
|
{
|
||||||
|
var originPosition = origin.Transform.MapPosition;
|
||||||
|
predicate ??= e => e == origin;
|
||||||
|
|
||||||
|
var inRange = InRangeUnobstructed(originPosition, other, range, collisionMask, predicate, ignoreInsideBlocker);
|
||||||
|
|
||||||
|
if (!inRange && popup)
|
||||||
|
{
|
||||||
|
var message = Loc.GetString("You can't reach there!");
|
||||||
|
origin.PopupMessage(origin, message);
|
||||||
|
}
|
||||||
|
|
||||||
|
return inRange;
|
||||||
|
}
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Checks that the user and target of a
|
||||||
|
/// <see cref="ITargetedInteractEventArgs"/> 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="args">The event args to use.</param>
|
||||||
|
/// <param name="range">
|
||||||
|
/// Maximum distance between the two entity and set of map 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 both the user and target 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 user entity for
|
||||||
|
/// it to see.
|
||||||
|
/// </param>
|
||||||
|
/// <returns>
|
||||||
|
/// True if the two points are within a given range without being obstructed.
|
||||||
|
/// </returns>
|
||||||
|
public bool InRangeUnobstructed(
|
||||||
|
ITargetedInteractEventArgs args,
|
||||||
|
float range = InteractionRange,
|
||||||
|
CollisionGroup collisionMask = CollisionGroup.Impassable,
|
||||||
|
Ignored predicate = null,
|
||||||
|
bool ignoreInsideBlocker = false,
|
||||||
|
bool popup = false)
|
||||||
|
{
|
||||||
|
var origin = args.User;
|
||||||
|
var other = args.Target;
|
||||||
|
|
||||||
|
return InRangeUnobstructed(origin, other, range, collisionMask, predicate, ignoreInsideBlocker, popup);
|
||||||
|
}
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Checks that the user of a <see cref="DragDropEventArgs"/> is within a
|
||||||
|
/// certain distance of the target and dropped entities 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="args">The event args to use.</param>
|
||||||
|
/// <param name="range">
|
||||||
|
/// Maximum distance between the two entity and set of map 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 both the user and target 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 user entity for
|
||||||
|
/// it to see.
|
||||||
|
/// </param>
|
||||||
|
/// <returns>
|
||||||
|
/// True if the two points are within a given range without being obstructed.
|
||||||
|
/// </returns>
|
||||||
|
public bool InRangeUnobstructed(
|
||||||
|
DragDropEventArgs args,
|
||||||
|
float range = InteractionRange,
|
||||||
|
CollisionGroup collisionMask = CollisionGroup.Impassable,
|
||||||
|
Ignored predicate = null,
|
||||||
|
bool ignoreInsideBlocker = false,
|
||||||
|
bool popup = false)
|
||||||
|
{
|
||||||
|
var user = args.User;
|
||||||
|
var dropped = args.Dropped;
|
||||||
|
var target = args.Target;
|
||||||
|
|
||||||
|
if (!InRangeUnobstructed(user, target, range, collisionMask, predicate, ignoreInsideBlocker))
|
||||||
|
{
|
||||||
|
if (popup)
|
||||||
|
{
|
||||||
|
var message = Loc.GetString("You can't reach there!");
|
||||||
|
target.PopupMessage(user, message);
|
||||||
|
}
|
||||||
|
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (!InRangeUnobstructed(user, dropped, range, collisionMask, predicate, ignoreInsideBlocker))
|
||||||
|
{
|
||||||
|
if (popup)
|
||||||
|
{
|
||||||
|
var message = Loc.GetString("You can't reach there!");
|
||||||
|
dropped.PopupMessage(user, message);
|
||||||
|
}
|
||||||
|
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Checks that the user and target of a
|
||||||
|
/// <see cref="AfterInteractEventArgs"/> 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="args">The event args to use.</param>
|
||||||
|
/// <param name="range">
|
||||||
|
/// Maximum distance between the two entity and set of map 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 both the user and target 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 user entity for
|
||||||
|
/// it to see.
|
||||||
|
/// </param>
|
||||||
|
/// <returns>
|
||||||
|
/// True if the two points are within a given range without being obstructed.
|
||||||
|
/// </returns>
|
||||||
|
public bool InRangeUnobstructed(
|
||||||
|
AfterInteractEventArgs args,
|
||||||
|
float range = InteractionRange,
|
||||||
|
CollisionGroup collisionMask = CollisionGroup.Impassable,
|
||||||
|
Ignored predicate = null,
|
||||||
|
bool ignoreInsideBlocker = false,
|
||||||
|
bool popup = false)
|
||||||
|
{
|
||||||
|
var user = args.User;
|
||||||
|
var target = args.Target;
|
||||||
|
predicate ??= e => e == user;
|
||||||
|
|
||||||
|
MapCoordinates otherPosition;
|
||||||
|
|
||||||
|
if (target == null)
|
||||||
|
{
|
||||||
|
otherPosition = args.ClickLocation.ToMap(_mapManager);
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
otherPosition = target.Transform.MapPosition;
|
||||||
|
predicate += e => e == target;
|
||||||
|
}
|
||||||
|
|
||||||
|
return InRangeUnobstructed(user, otherPosition, range, collisionMask, predicate, ignoreInsideBlocker, popup);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -1,10 +1,9 @@
|
|||||||
#nullable enable
|
#nullable enable
|
||||||
using System;
|
|
||||||
using System.Collections.Generic;
|
using System.Collections.Generic;
|
||||||
using System.Diagnostics.CodeAnalysis;
|
using System.Diagnostics.CodeAnalysis;
|
||||||
using System.Linq;
|
using System.Linq;
|
||||||
using Content.Shared.GameObjects.EntitySystems;
|
|
||||||
using Content.Shared.Physics;
|
using Content.Shared.Physics;
|
||||||
|
using Content.Shared.Utility;
|
||||||
using Robust.Shared.GameObjects;
|
using Robust.Shared.GameObjects;
|
||||||
using Robust.Shared.GameObjects.Systems;
|
using Robust.Shared.GameObjects.Systems;
|
||||||
using Robust.Shared.Interfaces.GameObjects;
|
using Robust.Shared.Interfaces.GameObjects;
|
||||||
@@ -15,14 +14,6 @@ namespace Content.Shared.GameObjects.Verbs
|
|||||||
{
|
{
|
||||||
public class SharedVerbSystem : EntitySystem
|
public class SharedVerbSystem : EntitySystem
|
||||||
{
|
{
|
||||||
private SharedInteractionSystem _interactionSystem = null!;
|
|
||||||
|
|
||||||
public override void Initialize()
|
|
||||||
{
|
|
||||||
base.Initialize();
|
|
||||||
_interactionSystem = Get<SharedInteractionSystem>();
|
|
||||||
}
|
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// Get all of the entities relevant for the contextmenu
|
/// Get all of the entities relevant for the contextmenu
|
||||||
/// </summary>
|
/// </summary>
|
||||||
@@ -35,29 +26,27 @@ namespace Content.Shared.GameObjects.Verbs
|
|||||||
{
|
{
|
||||||
contextEntities = null;
|
contextEntities = null;
|
||||||
var length = buffer ? 1.0f: 0.5f;
|
var length = buffer ? 1.0f: 0.5f;
|
||||||
|
|
||||||
var entities = EntityManager.GetEntitiesIntersecting(targetPos.MapId,
|
var entities = EntityManager.GetEntitiesIntersecting(targetPos.MapId,
|
||||||
Box2.CenteredAround(targetPos.Position, (length, length))).ToList();
|
Box2.CenteredAround(targetPos.Position, (length, length))).ToList();
|
||||||
|
|
||||||
if (entities.Count == 0)
|
if (entities.Count == 0)
|
||||||
{
|
{
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
// Check if we have LOS to the clicked-location, otherwise no popup.
|
// Check if we have LOS to the clicked-location, otherwise no popup.
|
||||||
var vectorDiff = player.Transform.MapPosition.Position - targetPos.Position;
|
var vectorDiff = player.Transform.MapPosition.Position - targetPos.Position;
|
||||||
var distance = vectorDiff.Length + 0.01f;
|
var distance = vectorDiff.Length + 0.01f;
|
||||||
Func<IEntity, bool> ignored = entity => entities.Contains(entity) ||
|
bool Ignored(IEntity entity)
|
||||||
entity == player ||
|
{
|
||||||
!entity.TryGetComponent(out OccluderComponent? occluder) ||
|
return entities.Contains(entity) ||
|
||||||
!occluder.Enabled;
|
entity == player ||
|
||||||
|
!entity.TryGetComponent(out OccluderComponent? occluder) ||
|
||||||
|
!occluder.Enabled;
|
||||||
|
}
|
||||||
|
|
||||||
var result = _interactionSystem.InRangeUnobstructed(
|
var result = player.InRangeUnobstructed(targetPos, distance, CollisionGroup.Opaque, Ignored);
|
||||||
player.Transform.MapPosition,
|
|
||||||
targetPos,
|
|
||||||
distance,
|
|
||||||
(int) CollisionGroup.Opaque,
|
|
||||||
ignored);
|
|
||||||
|
|
||||||
if (!result)
|
if (!result)
|
||||||
{
|
{
|
||||||
@@ -68,4 +57,4 @@ namespace Content.Shared.GameObjects.Verbs
|
|||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
432
Content.Shared/Utility/SharedRangeExtensions.cs
Normal file
432
Content.Shared/Utility/SharedRangeExtensions.cs
Normal file
@@ -0,0 +1,432 @@
|
|||||||
|
using Content.Shared.GameObjects.EntitySystems;
|
||||||
|
using Content.Shared.Interfaces.GameObjects.Components;
|
||||||
|
using Content.Shared.Physics;
|
||||||
|
using Robust.Shared.GameObjects.Systems;
|
||||||
|
using Robust.Shared.Interfaces.GameObjects;
|
||||||
|
using Robust.Shared.Interfaces.GameObjects.Components;
|
||||||
|
using Robust.Shared.Interfaces.Map;
|
||||||
|
using Robust.Shared.IoC;
|
||||||
|
using Robust.Shared.Map;
|
||||||
|
using static Content.Shared.GameObjects.EntitySystems.SharedInteractionSystem;
|
||||||
|
|
||||||
|
namespace Content.Shared.Utility
|
||||||
|
{
|
||||||
|
public static class SharedRangeExtensions
|
||||||
|
{
|
||||||
|
private static SharedInteractionSystem SharedInteractionSystem => EntitySystem.Get<SharedInteractionSystem>();
|
||||||
|
|
||||||
|
#region Entities
|
||||||
|
public static bool InRangeUnobstructed(
|
||||||
|
this IEntity origin,
|
||||||
|
IEntity other,
|
||||||
|
float range = InteractionRange,
|
||||||
|
CollisionGroup collisionMask = CollisionGroup.Impassable,
|
||||||
|
Ignored predicate = null,
|
||||||
|
bool ignoreInsideBlocker = false,
|
||||||
|
bool popup = false)
|
||||||
|
{
|
||||||
|
return SharedInteractionSystem.InRangeUnobstructed(origin, other, range, collisionMask, predicate,
|
||||||
|
ignoreInsideBlocker, popup);
|
||||||
|
}
|
||||||
|
|
||||||
|
public static bool InRangeUnobstructed(
|
||||||
|
this IEntity origin,
|
||||||
|
IComponent other,
|
||||||
|
float range = InteractionRange,
|
||||||
|
CollisionGroup collisionMask = CollisionGroup.Impassable,
|
||||||
|
Ignored predicate = null,
|
||||||
|
bool ignoreInsideBlocker = false,
|
||||||
|
bool popup = false)
|
||||||
|
{
|
||||||
|
return SharedInteractionSystem.InRangeUnobstructed(origin, other, range, collisionMask, predicate,
|
||||||
|
ignoreInsideBlocker, popup);
|
||||||
|
}
|
||||||
|
|
||||||
|
public static bool InRangeUnobstructed(
|
||||||
|
this IEntity origin,
|
||||||
|
IContainer other,
|
||||||
|
float range = InteractionRange,
|
||||||
|
CollisionGroup collisionMask = CollisionGroup.Impassable,
|
||||||
|
Ignored predicate = null,
|
||||||
|
bool ignoreInsideBlocker = false,
|
||||||
|
bool popup = false)
|
||||||
|
{
|
||||||
|
var otherEntity = other.Owner;
|
||||||
|
|
||||||
|
return SharedInteractionSystem.InRangeUnobstructed(origin, otherEntity, range, collisionMask, predicate,
|
||||||
|
ignoreInsideBlocker, popup);
|
||||||
|
}
|
||||||
|
|
||||||
|
public static bool InRangeUnobstructed(
|
||||||
|
this IEntity origin,
|
||||||
|
GridCoordinates other,
|
||||||
|
float range = InteractionRange,
|
||||||
|
CollisionGroup collisionMask = CollisionGroup.Impassable,
|
||||||
|
Ignored predicate = null,
|
||||||
|
bool ignoreInsideBlocker = false,
|
||||||
|
bool popup = false)
|
||||||
|
{
|
||||||
|
return SharedInteractionSystem.InRangeUnobstructed(origin, other, range, collisionMask, predicate,
|
||||||
|
ignoreInsideBlocker, popup);
|
||||||
|
}
|
||||||
|
|
||||||
|
public static bool InRangeUnobstructed(
|
||||||
|
this IEntity origin,
|
||||||
|
MapCoordinates other,
|
||||||
|
float range = InteractionRange,
|
||||||
|
CollisionGroup collisionMask = CollisionGroup.Impassable,
|
||||||
|
Ignored predicate = null,
|
||||||
|
bool ignoreInsideBlocker = false,
|
||||||
|
bool popup = false)
|
||||||
|
{
|
||||||
|
return SharedInteractionSystem.InRangeUnobstructed(origin, other, range, collisionMask, predicate,
|
||||||
|
ignoreInsideBlocker, popup);
|
||||||
|
}
|
||||||
|
#endregion
|
||||||
|
|
||||||
|
#region Components
|
||||||
|
public static bool InRangeUnobstructed(
|
||||||
|
this IComponent origin,
|
||||||
|
IEntity other,
|
||||||
|
float range = InteractionRange,
|
||||||
|
CollisionGroup collisionMask = CollisionGroup.Impassable,
|
||||||
|
Ignored predicate = null,
|
||||||
|
bool ignoreInsideBlocker = false,
|
||||||
|
bool popup = false)
|
||||||
|
{
|
||||||
|
var originEntity = origin.Owner;
|
||||||
|
|
||||||
|
return SharedInteractionSystem.InRangeUnobstructed(originEntity, other, range, collisionMask, predicate,
|
||||||
|
ignoreInsideBlocker, popup);
|
||||||
|
}
|
||||||
|
|
||||||
|
public static bool InRangeUnobstructed(
|
||||||
|
this IComponent origin,
|
||||||
|
IComponent other,
|
||||||
|
float range = InteractionRange,
|
||||||
|
CollisionGroup collisionMask = CollisionGroup.Impassable,
|
||||||
|
Ignored predicate = null,
|
||||||
|
bool ignoreInsideBlocker = false,
|
||||||
|
bool popup = false)
|
||||||
|
{
|
||||||
|
var originEntity = origin.Owner;
|
||||||
|
|
||||||
|
return SharedInteractionSystem.InRangeUnobstructed(originEntity, other, range, collisionMask, predicate,
|
||||||
|
ignoreInsideBlocker, popup);
|
||||||
|
}
|
||||||
|
|
||||||
|
public static bool InRangeUnobstructed(
|
||||||
|
this IComponent origin,
|
||||||
|
IContainer other,
|
||||||
|
float range = InteractionRange,
|
||||||
|
CollisionGroup collisionMask = CollisionGroup.Impassable,
|
||||||
|
Ignored predicate = null,
|
||||||
|
bool ignoreInsideBlocker = false,
|
||||||
|
bool popup = false)
|
||||||
|
{
|
||||||
|
var originEntity = origin.Owner;
|
||||||
|
var otherEntity = other.Owner;
|
||||||
|
|
||||||
|
return SharedInteractionSystem.InRangeUnobstructed(originEntity, otherEntity, range, collisionMask, predicate,
|
||||||
|
ignoreInsideBlocker, popup);
|
||||||
|
}
|
||||||
|
|
||||||
|
public static bool InRangeUnobstructed(
|
||||||
|
this IComponent origin,
|
||||||
|
GridCoordinates other,
|
||||||
|
float range = InteractionRange,
|
||||||
|
CollisionGroup collisionMask = CollisionGroup.Impassable,
|
||||||
|
Ignored predicate = null,
|
||||||
|
bool ignoreInsideBlocker = false,
|
||||||
|
bool popup = false)
|
||||||
|
{
|
||||||
|
var originEntity = origin.Owner;
|
||||||
|
|
||||||
|
return SharedInteractionSystem.InRangeUnobstructed(originEntity, other, range, collisionMask, predicate,
|
||||||
|
ignoreInsideBlocker, popup);
|
||||||
|
}
|
||||||
|
|
||||||
|
public static bool InRangeUnobstructed(
|
||||||
|
this IComponent origin,
|
||||||
|
MapCoordinates other,
|
||||||
|
float range = InteractionRange,
|
||||||
|
CollisionGroup collisionMask = CollisionGroup.Impassable,
|
||||||
|
Ignored predicate = null,
|
||||||
|
bool ignoreInsideBlocker = false,
|
||||||
|
bool popup = false)
|
||||||
|
{
|
||||||
|
var originEntity = origin.Owner;
|
||||||
|
|
||||||
|
return SharedInteractionSystem.InRangeUnobstructed(originEntity, other, range, collisionMask, predicate,
|
||||||
|
ignoreInsideBlocker, popup);
|
||||||
|
}
|
||||||
|
#endregion
|
||||||
|
|
||||||
|
#region Containers
|
||||||
|
public static bool InRangeUnobstructed(
|
||||||
|
this IContainer origin,
|
||||||
|
IEntity other,
|
||||||
|
float range = InteractionRange,
|
||||||
|
CollisionGroup collisionMask = CollisionGroup.Impassable,
|
||||||
|
Ignored predicate = null,
|
||||||
|
bool ignoreInsideBlocker = false)
|
||||||
|
{
|
||||||
|
var originEntity = origin.Owner;
|
||||||
|
|
||||||
|
return SharedInteractionSystem.InRangeUnobstructed(originEntity, other, range, collisionMask, predicate,
|
||||||
|
ignoreInsideBlocker);
|
||||||
|
}
|
||||||
|
|
||||||
|
public static bool InRangeUnobstructed(
|
||||||
|
this IContainer origin,
|
||||||
|
IComponent other,
|
||||||
|
float range = InteractionRange,
|
||||||
|
CollisionGroup collisionMask = CollisionGroup.Impassable,
|
||||||
|
Ignored predicate = null,
|
||||||
|
bool ignoreInsideBlocker = false,
|
||||||
|
bool popup = false)
|
||||||
|
{
|
||||||
|
var originEntity = origin.Owner;
|
||||||
|
|
||||||
|
return SharedInteractionSystem.InRangeUnobstructed(originEntity, other, range, collisionMask, predicate,
|
||||||
|
ignoreInsideBlocker, popup);
|
||||||
|
}
|
||||||
|
|
||||||
|
public static bool InRangeUnobstructed(
|
||||||
|
this IContainer origin,
|
||||||
|
IContainer other,
|
||||||
|
float range = InteractionRange,
|
||||||
|
CollisionGroup collisionMask = CollisionGroup.Impassable,
|
||||||
|
Ignored predicate = null,
|
||||||
|
bool ignoreInsideBlocker = false,
|
||||||
|
bool popup = false)
|
||||||
|
{
|
||||||
|
var originEntity = origin.Owner;
|
||||||
|
var otherEntity = other.Owner;
|
||||||
|
|
||||||
|
return SharedInteractionSystem.InRangeUnobstructed(originEntity, otherEntity, range, collisionMask,
|
||||||
|
predicate, ignoreInsideBlocker, popup);
|
||||||
|
}
|
||||||
|
|
||||||
|
public static bool InRangeUnobstructed(
|
||||||
|
this IContainer origin,
|
||||||
|
GridCoordinates other,
|
||||||
|
float range = InteractionRange,
|
||||||
|
CollisionGroup collisionMask = CollisionGroup.Impassable,
|
||||||
|
Ignored predicate = null,
|
||||||
|
bool ignoreInsideBlocker = false,
|
||||||
|
bool popup = false)
|
||||||
|
{
|
||||||
|
var originEntity = origin.Owner;
|
||||||
|
|
||||||
|
return SharedInteractionSystem.InRangeUnobstructed(originEntity, other, range, collisionMask, predicate,
|
||||||
|
ignoreInsideBlocker, popup);
|
||||||
|
}
|
||||||
|
|
||||||
|
public static bool InRangeUnobstructed(
|
||||||
|
this IContainer origin,
|
||||||
|
MapCoordinates other,
|
||||||
|
float range = InteractionRange,
|
||||||
|
CollisionGroup collisionMask = CollisionGroup.Impassable,
|
||||||
|
Ignored predicate = null,
|
||||||
|
bool ignoreInsideBlocker = false,
|
||||||
|
bool popup = false)
|
||||||
|
{
|
||||||
|
var originEntity = origin.Owner;
|
||||||
|
|
||||||
|
return SharedInteractionSystem.InRangeUnobstructed(originEntity, other, range, collisionMask, predicate,
|
||||||
|
ignoreInsideBlocker, popup);
|
||||||
|
}
|
||||||
|
#endregion
|
||||||
|
|
||||||
|
#region GridCoordinates
|
||||||
|
public static bool InRangeUnobstructed(
|
||||||
|
this GridCoordinates origin,
|
||||||
|
IEntity other,
|
||||||
|
float range = InteractionRange,
|
||||||
|
CollisionGroup collisionMask = CollisionGroup.Impassable,
|
||||||
|
Ignored predicate = null,
|
||||||
|
bool ignoreInsideBlocker = false)
|
||||||
|
{
|
||||||
|
var mapManager = IoCManager.Resolve<IMapManager>();
|
||||||
|
var originPosition = origin.ToMap(mapManager);
|
||||||
|
var otherPosition = other.Transform.MapPosition;
|
||||||
|
|
||||||
|
return SharedInteractionSystem.InRangeUnobstructed(originPosition, otherPosition, range, collisionMask,
|
||||||
|
predicate, ignoreInsideBlocker);
|
||||||
|
}
|
||||||
|
|
||||||
|
public static bool InRangeUnobstructed(
|
||||||
|
this GridCoordinates origin,
|
||||||
|
IComponent other,
|
||||||
|
float range = InteractionRange,
|
||||||
|
CollisionGroup collisionMask = CollisionGroup.Impassable,
|
||||||
|
Ignored predicate = null,
|
||||||
|
bool ignoreInsideBlocker = false)
|
||||||
|
{
|
||||||
|
var mapManager = IoCManager.Resolve<IMapManager>();
|
||||||
|
var originPosition = origin.ToMap(mapManager);
|
||||||
|
var otherPosition = other.Owner.Transform.MapPosition;
|
||||||
|
|
||||||
|
return SharedInteractionSystem.InRangeUnobstructed(originPosition, otherPosition, range, collisionMask,
|
||||||
|
predicate, ignoreInsideBlocker);
|
||||||
|
}
|
||||||
|
|
||||||
|
public static bool InRangeUnobstructed(
|
||||||
|
this GridCoordinates origin,
|
||||||
|
IContainer other,
|
||||||
|
float range = InteractionRange,
|
||||||
|
CollisionGroup collisionMask = CollisionGroup.Impassable,
|
||||||
|
Ignored predicate = null,
|
||||||
|
bool ignoreInsideBlocker = false)
|
||||||
|
{
|
||||||
|
var mapManager = IoCManager.Resolve<IMapManager>();
|
||||||
|
var originPosition = origin.ToMap(mapManager);
|
||||||
|
var otherPosition = other.Owner.Transform.MapPosition;
|
||||||
|
|
||||||
|
return SharedInteractionSystem.InRangeUnobstructed(originPosition, otherPosition, range, collisionMask,
|
||||||
|
predicate, ignoreInsideBlocker);
|
||||||
|
}
|
||||||
|
|
||||||
|
public static bool InRangeUnobstructed(
|
||||||
|
this GridCoordinates origin,
|
||||||
|
GridCoordinates other,
|
||||||
|
float range = InteractionRange,
|
||||||
|
CollisionGroup collisionMask = CollisionGroup.Impassable,
|
||||||
|
Ignored predicate = null,
|
||||||
|
bool ignoreInsideBlocker = false)
|
||||||
|
{
|
||||||
|
var mapManager = IoCManager.Resolve<IMapManager>();
|
||||||
|
var originPosition = origin.ToMap(mapManager);
|
||||||
|
var otherPosition = other.ToMap(mapManager);
|
||||||
|
|
||||||
|
return SharedInteractionSystem.InRangeUnobstructed(originPosition, otherPosition, range, collisionMask,
|
||||||
|
predicate, ignoreInsideBlocker);
|
||||||
|
}
|
||||||
|
|
||||||
|
public static bool InRangeUnobstructed(
|
||||||
|
this GridCoordinates origin,
|
||||||
|
MapCoordinates other,
|
||||||
|
float range = InteractionRange,
|
||||||
|
CollisionGroup collisionMask = CollisionGroup.Impassable,
|
||||||
|
Ignored predicate = null,
|
||||||
|
bool ignoreInsideBlocker = false)
|
||||||
|
{
|
||||||
|
var mapManager = IoCManager.Resolve<IMapManager>();
|
||||||
|
var originPosition = origin.ToMap(mapManager);
|
||||||
|
|
||||||
|
return SharedInteractionSystem.InRangeUnobstructed(originPosition, other, range, collisionMask, predicate,
|
||||||
|
ignoreInsideBlocker);
|
||||||
|
}
|
||||||
|
#endregion
|
||||||
|
|
||||||
|
#region MapCoordinates
|
||||||
|
public static bool InRangeUnobstructed(
|
||||||
|
this MapCoordinates origin,
|
||||||
|
IEntity other,
|
||||||
|
float range = InteractionRange,
|
||||||
|
CollisionGroup collisionMask = CollisionGroup.Impassable,
|
||||||
|
Ignored predicate = null,
|
||||||
|
bool ignoreInsideBlocker = false)
|
||||||
|
{
|
||||||
|
var otherPosition = other.Transform.MapPosition;
|
||||||
|
|
||||||
|
return SharedInteractionSystem.InRangeUnobstructed(origin, otherPosition, range, collisionMask, predicate,
|
||||||
|
ignoreInsideBlocker);
|
||||||
|
}
|
||||||
|
|
||||||
|
public static bool InRangeUnobstructed(
|
||||||
|
this MapCoordinates origin,
|
||||||
|
IComponent other,
|
||||||
|
float range = InteractionRange,
|
||||||
|
CollisionGroup collisionMask = CollisionGroup.Impassable,
|
||||||
|
Ignored predicate = null,
|
||||||
|
bool ignoreInsideBlocker = false)
|
||||||
|
{
|
||||||
|
var otherPosition = other.Owner.Transform.MapPosition;
|
||||||
|
|
||||||
|
return SharedInteractionSystem.InRangeUnobstructed(origin, otherPosition, range, collisionMask, predicate,
|
||||||
|
ignoreInsideBlocker);
|
||||||
|
}
|
||||||
|
|
||||||
|
public static bool InRangeUnobstructed(
|
||||||
|
this MapCoordinates origin,
|
||||||
|
IContainer other,
|
||||||
|
float range = InteractionRange,
|
||||||
|
CollisionGroup collisionMask = CollisionGroup.Impassable,
|
||||||
|
Ignored predicate = null,
|
||||||
|
bool ignoreInsideBlocker = false)
|
||||||
|
{
|
||||||
|
var otherPosition = other.Owner.Transform.MapPosition;
|
||||||
|
|
||||||
|
return SharedInteractionSystem.InRangeUnobstructed(origin, otherPosition, range, collisionMask, predicate,
|
||||||
|
ignoreInsideBlocker);
|
||||||
|
}
|
||||||
|
|
||||||
|
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);
|
||||||
|
}
|
||||||
|
|
||||||
|
public static bool InRangeUnobstructed(
|
||||||
|
this MapCoordinates origin,
|
||||||
|
MapCoordinates other,
|
||||||
|
float range = InteractionRange,
|
||||||
|
CollisionGroup collisionMask = CollisionGroup.Impassable,
|
||||||
|
Ignored predicate = null,
|
||||||
|
bool ignoreInsideBlocker = false)
|
||||||
|
{
|
||||||
|
return SharedInteractionSystem.InRangeUnobstructed(origin, other, range, collisionMask, predicate,
|
||||||
|
ignoreInsideBlocker);
|
||||||
|
}
|
||||||
|
#endregion
|
||||||
|
|
||||||
|
#region EventArgs
|
||||||
|
public static bool InRangeUnobstructed(
|
||||||
|
this ITargetedInteractEventArgs args,
|
||||||
|
float range = InteractionRange,
|
||||||
|
CollisionGroup collisionMask = CollisionGroup.Impassable,
|
||||||
|
Ignored predicate = null,
|
||||||
|
bool ignoreInsideBlocker = false,
|
||||||
|
bool popup = false)
|
||||||
|
{
|
||||||
|
return SharedInteractionSystem.InRangeUnobstructed(args, range, collisionMask, predicate,
|
||||||
|
ignoreInsideBlocker, popup);
|
||||||
|
}
|
||||||
|
|
||||||
|
public static bool InRangeUnobstructed(
|
||||||
|
this DragDropEventArgs args,
|
||||||
|
float range = InteractionRange,
|
||||||
|
CollisionGroup collisionMask = CollisionGroup.Impassable,
|
||||||
|
Ignored predicate = null,
|
||||||
|
bool ignoreInsideBlocker = false,
|
||||||
|
bool popup = false)
|
||||||
|
{
|
||||||
|
return SharedInteractionSystem.InRangeUnobstructed(args, range, collisionMask, predicate,
|
||||||
|
ignoreInsideBlocker, popup);
|
||||||
|
}
|
||||||
|
|
||||||
|
public static bool InRangeUnobstructed(
|
||||||
|
this AfterInteractEventArgs args,
|
||||||
|
float range = InteractionRange,
|
||||||
|
CollisionGroup collisionMask = CollisionGroup.Impassable,
|
||||||
|
Ignored predicate = null,
|
||||||
|
bool ignoreInsideBlocker = false,
|
||||||
|
bool popup = false)
|
||||||
|
{
|
||||||
|
return SharedInteractionSystem.InRangeUnobstructed(args, range, collisionMask, predicate,
|
||||||
|
ignoreInsideBlocker, popup);
|
||||||
|
}
|
||||||
|
#endregion
|
||||||
|
}
|
||||||
|
}
|
||||||
Reference in New Issue
Block a user