Fix AI avoiding entities they can't collide with (#1331)
Should stop mobs getting trapped at the bar on saltern as they try to avoid light bulbs Co-authored-by: Metal Gear Sloth <metalgearsloth@gmail.com>
This commit is contained in:
@@ -27,8 +27,8 @@ namespace Content.Server.GameObjects.EntitySystems.Pathfinding
|
|||||||
public int BlockedCollisionMask { get; private set; }
|
public int BlockedCollisionMask { get; private set; }
|
||||||
private readonly Dictionary<EntityUid, int> _blockedCollidables = new Dictionary<EntityUid, int>(0);
|
private readonly Dictionary<EntityUid, int> _blockedCollidables = new Dictionary<EntityUid, int>(0);
|
||||||
|
|
||||||
public IReadOnlyCollection<EntityUid> PhysicsUids => _physicsUids;
|
public IReadOnlyDictionary<EntityUid, int> PhysicsLayers => _physicsLayers;
|
||||||
private readonly HashSet<EntityUid> _physicsUids = new HashSet<EntityUid>(0);
|
private readonly Dictionary<EntityUid, int> _physicsLayers = new Dictionary<EntityUid, int>(0);
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// The entities on this tile that require access to traverse
|
/// The entities on this tile that require access to traverse
|
||||||
@@ -115,11 +115,12 @@ namespace Content.Server.GameObjects.EntitySystems.Pathfinding
|
|||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (entity.TryGetComponent(out CollidableComponent collidableComponent))
|
if (entity.TryGetComponent(out CollidableComponent collidableComponent) &&
|
||||||
|
(PathfindingSystem.TrackedCollisionLayers & collidableComponent.CollisionLayer) != 0)
|
||||||
{
|
{
|
||||||
if (entity.TryGetComponent(out PhysicsComponent physicsComponent) && !physicsComponent.Anchored)
|
if (entity.TryGetComponent(out PhysicsComponent physicsComponent) && !physicsComponent.Anchored)
|
||||||
{
|
{
|
||||||
_physicsUids.Add(entity.Uid);
|
_physicsLayers.Add(entity.Uid, collidableComponent.CollisionLayer);
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
@@ -139,9 +140,9 @@ namespace Content.Server.GameObjects.EntitySystems.Pathfinding
|
|||||||
// There's no guarantee that the entity isn't deleted
|
// There's no guarantee that the entity isn't deleted
|
||||||
// 90% of updates are probably entities moving around
|
// 90% of updates are probably entities moving around
|
||||||
// Entity can't be under multiple categories so just checking each once is fine.
|
// Entity can't be under multiple categories so just checking each once is fine.
|
||||||
if (_physicsUids.Contains(entity.Uid))
|
if (_physicsLayers.ContainsKey(entity.Uid))
|
||||||
{
|
{
|
||||||
_physicsUids.Remove(entity.Uid);
|
_physicsLayers.Remove(entity.Uid);
|
||||||
}
|
}
|
||||||
else if (_accessReaders.ContainsKey(entity.Uid))
|
else if (_accessReaders.ContainsKey(entity.Uid))
|
||||||
{
|
{
|
||||||
|
|||||||
@@ -10,6 +10,7 @@ using Content.Server.GameObjects.EntitySystems.JobQueues;
|
|||||||
using Content.Shared.GameObjects.EntitySystems;
|
using Content.Shared.GameObjects.EntitySystems;
|
||||||
using Robust.Server.GameObjects;
|
using Robust.Server.GameObjects;
|
||||||
using Robust.Server.Interfaces.Timing;
|
using Robust.Server.Interfaces.Timing;
|
||||||
|
using Robust.Shared.GameObjects;
|
||||||
using Robust.Shared.GameObjects.Components;
|
using Robust.Shared.GameObjects.Components;
|
||||||
using Robust.Shared.GameObjects.Systems;
|
using Robust.Shared.GameObjects.Systems;
|
||||||
using Robust.Shared.Interfaces.GameObjects;
|
using Robust.Shared.Interfaces.GameObjects;
|
||||||
@@ -319,7 +320,7 @@ namespace Content.Server.GameObjects.EntitySystems.AI.Steering
|
|||||||
return SteeringStatus.Pending;
|
return SteeringStatus.Pending;
|
||||||
}
|
}
|
||||||
|
|
||||||
var ignoredCollision = new List<IEntity>();
|
var ignoredCollision = new List<EntityUid>();
|
||||||
// Check if the target entity has moved - If so then re-path
|
// Check if the target entity has moved - If so then re-path
|
||||||
// TODO: Patch the path from the target's position back towards us, stopping if it ever intersects the current path
|
// TODO: Patch the path from the target's position back towards us, stopping if it ever intersects the current path
|
||||||
// Probably need a separate "PatchPath" job
|
// Probably need a separate "PatchPath" job
|
||||||
@@ -338,7 +339,7 @@ namespace Content.Server.GameObjects.EntitySystems.AI.Steering
|
|||||||
RequestPath(entity, steeringRequest);
|
RequestPath(entity, steeringRequest);
|
||||||
}
|
}
|
||||||
|
|
||||||
ignoredCollision.Add(entitySteer.Target);
|
ignoredCollision.Add(entitySteer.Target.Uid);
|
||||||
}
|
}
|
||||||
|
|
||||||
HandleStuck(entity);
|
HandleStuck(entity);
|
||||||
@@ -596,9 +597,9 @@ namespace Content.Server.GameObjects.EntitySystems.AI.Steering
|
|||||||
/// <param name="direction">entity's travel direction</param>
|
/// <param name="direction">entity's travel direction</param>
|
||||||
/// <param name="ignoredTargets"></param>
|
/// <param name="ignoredTargets"></param>
|
||||||
/// <returns></returns>
|
/// <returns></returns>
|
||||||
private Vector2 CollisionAvoidance(IEntity entity, Vector2 direction, ICollection<IEntity> ignoredTargets)
|
private Vector2 CollisionAvoidance(IEntity entity, Vector2 direction, ICollection<EntityUid> ignoredTargets)
|
||||||
{
|
{
|
||||||
if (direction == Vector2.Zero || !entity.HasComponent<CollidableComponent>())
|
if (direction == Vector2.Zero || !entity.TryGetComponent(out CollidableComponent collidableComponent))
|
||||||
{
|
{
|
||||||
return Vector2.Zero;
|
return Vector2.Zero;
|
||||||
}
|
}
|
||||||
@@ -606,6 +607,7 @@ namespace Content.Server.GameObjects.EntitySystems.AI.Steering
|
|||||||
// We'll check tile-by-tile
|
// We'll check tile-by-tile
|
||||||
// Rewriting this frequently so not many comments as they'll go stale
|
// Rewriting this frequently so not many comments as they'll go stale
|
||||||
// I realise this is bad so please rewrite it ;-;
|
// I realise this is bad so please rewrite it ;-;
|
||||||
|
var entityCollisionMask = collidableComponent.CollisionMask;
|
||||||
var avoidanceVector = Vector2.Zero;
|
var avoidanceVector = Vector2.Zero;
|
||||||
var checkTiles = new HashSet<TileRef>();
|
var checkTiles = new HashSet<TileRef>();
|
||||||
var avoidTiles = new HashSet<TileRef>();
|
var avoidTiles = new HashSet<TileRef>();
|
||||||
@@ -625,10 +627,10 @@ namespace Content.Server.GameObjects.EntitySystems.AI.Steering
|
|||||||
{
|
{
|
||||||
var node = _pathfindingSystem.GetNode(tile);
|
var node = _pathfindingSystem.GetNode(tile);
|
||||||
// Assume the immovables have already been checked
|
// Assume the immovables have already been checked
|
||||||
foreach (var uid in node.PhysicsUids)
|
foreach (var (uid, layer) in node.PhysicsLayers)
|
||||||
{
|
{
|
||||||
// Ignore myself / my target if applicable
|
// Ignore myself / my target if applicable / if my mask doesn't collide
|
||||||
if (uid == entity.Uid || ignoredTargets.Contains(entity)) continue;
|
if (uid == entity.Uid || ignoredTargets.Contains(uid) || (entityCollisionMask & layer) == 0) continue;
|
||||||
// God there's so many ways to do this
|
// God there's so many ways to do this
|
||||||
// err for now we'll just assume the first entity is the center and just add a vector for it
|
// err for now we'll just assume the first entity is the center and just add a vector for it
|
||||||
var collisionEntity = _entityManager.GetEntity(uid);
|
var collisionEntity = _entityManager.GetEntity(uid);
|
||||||
|
|||||||
Reference in New Issue
Block a user