From 452a67032f9d17f208c6dc48be9ea9cd697231e2 Mon Sep 17 00:00:00 2001 From: metalgearsloth <31366439+metalgearsloth@users.noreply.github.com> Date: Wed, 12 Aug 2020 01:36:40 +1000 Subject: [PATCH 1/9] Fix the pathfinding leak (#1647) Off-grid entities were continually expanding the graph indefinitely which is... bad. Co-authored-by: Metal Gear Sloth --- .../Access/AccessReaderChangeMessage.cs | 8 +- .../Components/Doors/ServerDoorComponent.cs | 4 +- .../AI/Pathfinding/PathfindingNode.cs | 59 ++++++++------- .../AI/Pathfinding/PathfindingSystem.cs | 75 +++++++++++-------- .../AI/Steering/AiSteeringSystem.cs | 17 ++--- 5 files changed, 92 insertions(+), 71 deletions(-) diff --git a/Content.Server/GameObjects/Components/Access/AccessReaderChangeMessage.cs b/Content.Server/GameObjects/Components/Access/AccessReaderChangeMessage.cs index cc1ae73793..c75e913069 100644 --- a/Content.Server/GameObjects/Components/Access/AccessReaderChangeMessage.cs +++ b/Content.Server/GameObjects/Components/Access/AccessReaderChangeMessage.cs @@ -1,15 +1,17 @@ using Robust.Shared.GameObjects; +using Robust.Shared.Interfaces.GameObjects; namespace Content.Server.GameObjects.Components.Access { public sealed class AccessReaderChangeMessage : EntitySystemMessage { - public EntityUid Uid { get; } + public IEntity Sender { get; } + public bool Enabled { get; } - public AccessReaderChangeMessage(EntityUid uid, bool enabled) + public AccessReaderChangeMessage(IEntity entity, bool enabled) { - Uid = uid; + Sender = entity; Enabled = enabled; } } diff --git a/Content.Server/GameObjects/Components/Doors/ServerDoorComponent.cs b/Content.Server/GameObjects/Components/Doors/ServerDoorComponent.cs index c00b3d0499..8b1ab391c7 100644 --- a/Content.Server/GameObjects/Components/Doors/ServerDoorComponent.cs +++ b/Content.Server/GameObjects/Components/Doors/ServerDoorComponent.cs @@ -188,7 +188,7 @@ namespace Content.Server.GameObjects SetAppearance(DoorVisualState.Open); }, _cancellationTokenSource.Token); - Owner.EntityManager.EventBus.RaiseEvent(EventSource.Local, new AccessReaderChangeMessage(Owner.Uid, false)); + Owner.EntityManager.EventBus.RaiseEvent(EventSource.Local, new AccessReaderChangeMessage(Owner, false)); } public virtual bool CanClose() @@ -284,7 +284,7 @@ namespace Content.Server.GameObjects State = DoorState.Closed; SetAppearance(DoorVisualState.Closed); }, _cancellationTokenSource.Token); - Owner.EntityManager.EventBus.RaiseEvent(EventSource.Local, new AccessReaderChangeMessage(Owner.Uid, true)); + Owner.EntityManager.EventBus.RaiseEvent(EventSource.Local, new AccessReaderChangeMessage(Owner, true)); return true; } diff --git a/Content.Server/GameObjects/EntitySystems/AI/Pathfinding/PathfindingNode.cs b/Content.Server/GameObjects/EntitySystems/AI/Pathfinding/PathfindingNode.cs index 6f9d665fac..c35bf9a0f3 100644 --- a/Content.Server/GameObjects/EntitySystems/AI/Pathfinding/PathfindingNode.cs +++ b/Content.Server/GameObjects/EntitySystems/AI/Pathfinding/PathfindingNode.cs @@ -25,17 +25,17 @@ namespace Content.Server.GameObjects.EntitySystems.Pathfinding /// Whenever there's a change in the collision layers we update the mask as the graph has more reads than writes /// public int BlockedCollisionMask { get; private set; } - private readonly Dictionary _blockedCollidables = new Dictionary(0); + private readonly Dictionary _blockedCollidables = new Dictionary(0); - public IReadOnlyDictionary PhysicsLayers => _physicsLayers; - private readonly Dictionary _physicsLayers = new Dictionary(0); + public IReadOnlyDictionary PhysicsLayers => _physicsLayers; + private readonly Dictionary _physicsLayers = new Dictionary(0); /// /// The entities on this tile that require access to traverse /// /// We don't store the ICollection, at least for now, as we'd need to replicate the access code here public IReadOnlyCollection AccessReaders => _accessReaders.Values; - private readonly Dictionary _accessReaders = new Dictionary(0); + private readonly Dictionary _accessReaders = new Dictionary(0); public PathfindingNode(PathfindingChunk parent, TileRef tileRef) { @@ -44,6 +44,17 @@ namespace Content.Server.GameObjects.EntitySystems.Pathfinding GenerateMask(); } + public static bool IsRelevant(IEntity entity, ICollidableComponent collidableComponent) + { + if (entity.Transform.GridID == GridId.Invalid || + (PathfindingSystem.TrackedCollisionLayers & collidableComponent.CollisionLayer) == 0) + { + return false; + } + + return true; + } + /// /// Return our neighboring nodes (even across chunks) /// @@ -249,7 +260,7 @@ namespace Content.Server.GameObjects.EntitySystems.Pathfinding /// /// TODO: These 2 methods currently don't account for a bunch of changes (e.g. airlock unpowered, wrenching, etc.) /// TODO: Could probably optimise this slightly more. - public void AddEntity(IEntity entity) + public void AddEntity(IEntity entity, ICollidableComponent collidableComponent) { // If we're a door if (entity.HasComponent() || entity.HasComponent()) @@ -258,27 +269,25 @@ namespace Content.Server.GameObjects.EntitySystems.Pathfinding // TODO: Check for powered I think (also need an event for when it's depowered // AccessReader calls this whenever opening / closing but it can seem to get called multiple times // Which may or may not be intended? - if (entity.TryGetComponent(out AccessReader accessReader) && !_accessReaders.ContainsKey(entity.Uid)) + if (entity.TryGetComponent(out AccessReader accessReader) && !_accessReaders.ContainsKey(entity)) { - _accessReaders.Add(entity.Uid, accessReader); + _accessReaders.Add(entity, accessReader); ParentChunk.Dirty(); } return; } - if (entity.TryGetComponent(out ICollidableComponent collidableComponent) && - (PathfindingSystem.TrackedCollisionLayers & collidableComponent.CollisionLayer) != 0) + DebugTools.Assert((PathfindingSystem.TrackedCollisionLayers & collidableComponent.CollisionLayer) != 0); + + if (!collidableComponent.Anchored) { - if (entity.TryGetComponent(out IPhysicsComponent physicsComponent) && !physicsComponent.Anchored) - { - _physicsLayers.Add(entity.Uid, collidableComponent.CollisionLayer); - } - else - { - _blockedCollidables.TryAdd(entity.Uid, collidableComponent.CollisionLayer); - GenerateMask(); - ParentChunk.Dirty(); - } + _physicsLayers.Add(entity, collidableComponent.CollisionLayer); + } + else + { + _blockedCollidables.Add(entity, collidableComponent.CollisionLayer); + GenerateMask(); + ParentChunk.Dirty(); } } @@ -292,18 +301,18 @@ namespace Content.Server.GameObjects.EntitySystems.Pathfinding // There's no guarantee that the entity isn't deleted // 90% of updates are probably entities moving around // Entity can't be under multiple categories so just checking each once is fine. - if (_physicsLayers.ContainsKey(entity.Uid)) + if (_physicsLayers.ContainsKey(entity)) { - _physicsLayers.Remove(entity.Uid); + _physicsLayers.Remove(entity); } - else if (_accessReaders.ContainsKey(entity.Uid)) + else if (_accessReaders.ContainsKey(entity)) { - _accessReaders.Remove(entity.Uid); + _accessReaders.Remove(entity); ParentChunk.Dirty(); } - else if (_blockedCollidables.ContainsKey(entity.Uid)) + else if (_blockedCollidables.ContainsKey(entity)) { - _blockedCollidables.Remove(entity.Uid); + _blockedCollidables.Remove(entity); GenerateMask(); ParentChunk.Dirty(); } diff --git a/Content.Server/GameObjects/EntitySystems/AI/Pathfinding/PathfindingSystem.cs b/Content.Server/GameObjects/EntitySystems/AI/Pathfinding/PathfindingSystem.cs index 385954b9d6..05069f27fd 100644 --- a/Content.Server/GameObjects/EntitySystems/AI/Pathfinding/PathfindingSystem.cs +++ b/Content.Server/GameObjects/EntitySystems/AI/Pathfinding/PathfindingSystem.cs @@ -1,7 +1,9 @@ using System; using System.Collections.Generic; +using System.IO; using System.Threading; using Content.Server.GameObjects.Components.Access; +using Content.Server.GameObjects.Components.GUI; using Content.Server.GameObjects.EntitySystems.AI.Pathfinding.Pathfinders; using Content.Server.GameObjects.EntitySystems.JobQueues; using Content.Server.GameObjects.EntitySystems.JobQueues.Queues; @@ -20,9 +22,10 @@ using Robust.Shared.Utility; namespace Content.Server.GameObjects.EntitySystems.AI.Pathfinding { /* - // TODO: IMO use rectangular symmetry reduction on the nodes with collision at all., or + // TODO: IMO use rectangular symmetry reduction on the nodes with collision at all. (currently planned to be implemented via AiReachableSystem and expanded later). alternatively store all rooms and have an alternative graph for humanoid mobs (same collision mask, needs access etc). You could also just path from room to room as needed. // TODO: Longer term -> Handle collision layer changes? + TODO: Handle container entities so they're not tracked. */ /// /// This system handles pathfinding graph updates as well as dispatches to the pathfinder @@ -30,10 +33,7 @@ namespace Content.Server.GameObjects.EntitySystems.AI.Pathfinding /// public class PathfindingSystem : EntitySystem { -#pragma warning disable 649 - [Dependency] private readonly IEntityManager _entitymanager; - [Dependency] private readonly IMapManager _mapManager; -#pragma warning restore 649 + [Dependency] private readonly IMapManager _mapManager = default!; public IReadOnlyDictionary> Graph => _graph; private readonly Dictionary> _graph = new Dictionary>(); @@ -47,7 +47,7 @@ namespace Content.Server.GameObjects.EntitySystems.AI.Pathfinding private readonly Queue _tileUpdateQueue = new Queue(); // Need to store previously known entity positions for collidables for when they move - private readonly Dictionary _lastKnownPositions = new Dictionary(); + private readonly Dictionary _lastKnownPositions = new Dictionary(); public const int TrackedCollisionLayers = (int) (CollisionGroup.Impassable | @@ -86,7 +86,7 @@ namespace Content.Server.GameObjects.EntitySystems.AI.Pathfinding foreach (var update in _collidableUpdateQueue) { - var entity = _entitymanager.GetEntity(update.Owner); + var entity = EntityManager.GetEntity(update.Owner); if (update.CanCollide) { HandleEntityAdd(entity); @@ -103,14 +103,13 @@ namespace Content.Server.GameObjects.EntitySystems.AI.Pathfinding foreach (var update in _accessReaderUpdateQueue) { - var entity = _entitymanager.GetEntity(update.Uid); if (update.Enabled) { - HandleEntityAdd(entity); + HandleEntityAdd(update.Sender); } else { - HandleEntityRemove(entity); + HandleEntityRemove(update.Sender); } totalUpdates++; @@ -138,7 +137,7 @@ namespace Content.Server.GameObjects.EntitySystems.AI.Pathfinding for (var i = 0; i < moveUpdateCount; i++) { - HandleCollidableMove(_moveUpdateQueue.Dequeue()); + HandleEntityMove(_moveUpdateQueue.Dequeue()); } DebugTools.Assert(_moveUpdateQueue.Count < 1000); @@ -204,9 +203,6 @@ namespace Content.Server.GameObjects.EntitySystems.AI.Pathfinding public override void Initialize() { - // TODO: Remove this once the memory leaks are solved. - return; - SubscribeLocalEvent(QueueCollisionChangeMessage); SubscribeLocalEvent(QueueMoveEvent); SubscribeLocalEvent(QueueAccessChangeMessage); @@ -279,7 +275,10 @@ namespace Content.Server.GameObjects.EntitySystems.AI.Pathfinding /// private void HandleEntityAdd(IEntity entity) { - if (entity.Deleted || _lastKnownPositions.ContainsKey(entity.Uid)) + if (entity.Deleted || + _lastKnownPositions.ContainsKey(entity) || + !entity.TryGetComponent(out ICollidableComponent collidableComponent) || + !PathfindingNode.IsRelevant(entity, collidableComponent)) { return; } @@ -289,19 +288,19 @@ namespace Content.Server.GameObjects.EntitySystems.AI.Pathfinding var chunk = GetChunk(tileRef); var node = chunk.GetNode(tileRef); - node.AddEntity(entity); - _lastKnownPositions.Add(entity.Uid, node); + node.AddEntity(entity, collidableComponent); + _lastKnownPositions.Add(entity, node); } private void HandleEntityRemove(IEntity entity) { - if (!_lastKnownPositions.TryGetValue(entity.Uid, out var node)) + if (!_lastKnownPositions.TryGetValue(entity, out var node)) { return; } node.RemoveEntity(entity); - _lastKnownPositions.Remove(entity.Uid); + _lastKnownPositions.Remove(entity); } private void QueueMoveEvent(MoveEvent moveEvent) @@ -313,35 +312,47 @@ namespace Content.Server.GameObjects.EntitySystems.AI.Pathfinding /// When an entity moves around we'll remove it from its old node and add it to its new node (if applicable) /// /// - private void HandleCollidableMove(MoveEvent moveEvent) + private void HandleEntityMove(MoveEvent moveEvent) { - var entityUid = moveEvent.Sender.Uid; - - if (!_lastKnownPositions.TryGetValue(entityUid, out var oldNode)) + // If we've moved to space or the likes then remove us. + if (moveEvent.Sender.Deleted || + !moveEvent.Sender.TryGetComponent(out ICollidableComponent collidableComponent) || + !PathfindingNode.IsRelevant(moveEvent.Sender, collidableComponent)) { + HandleEntityRemove(moveEvent.Sender); + return; + } + + // Memory leak protection until grid parenting confirmed fix / you REALLY need the performance + var gridBounds = _mapManager.GetGrid(moveEvent.Sender.Transform.GridID).WorldBounds; + + if (!gridBounds.Contains(moveEvent.Sender.Transform.WorldPosition)) + { + HandleEntityRemove(moveEvent.Sender); + return; + } + + // If we move from space to a grid we may need to start tracking it. + if (!_lastKnownPositions.TryGetValue(moveEvent.Sender, out var oldNode)) + { + HandleEntityAdd(moveEvent.Sender); return; } // The pathfinding graph is tile-based so first we'll check if they're on a different tile and if we need to update. // If you get entities bigger than 1 tile wide you'll need some other system so god help you. - if (moveEvent.Sender.Deleted) - { - HandleEntityRemove(moveEvent.Sender); - return; - } - var newTile = _mapManager.GetGrid(moveEvent.NewPosition.GridID).GetTileRef(moveEvent.NewPosition); - + if (oldNode == null || oldNode.TileRef == newTile) { return; } var newNode = GetNode(newTile); - _lastKnownPositions[entityUid] = newNode; + _lastKnownPositions[moveEvent.Sender] = newNode; oldNode.RemoveEntity(moveEvent.Sender); - newNode.AddEntity(moveEvent.Sender); + newNode.AddEntity(moveEvent.Sender, collidableComponent); } private void QueueCollisionChangeMessage(CollisionChangeMessage collisionMessage) diff --git a/Content.Server/GameObjects/EntitySystems/AI/Steering/AiSteeringSystem.cs b/Content.Server/GameObjects/EntitySystems/AI/Steering/AiSteeringSystem.cs index ba92f7122d..e3c3863a80 100644 --- a/Content.Server/GameObjects/EntitySystems/AI/Steering/AiSteeringSystem.cs +++ b/Content.Server/GameObjects/EntitySystems/AI/Steering/AiSteeringSystem.cs @@ -320,7 +320,7 @@ namespace Content.Server.GameObjects.EntitySystems.AI.Steering return SteeringStatus.Pending; } - var ignoredCollision = new List(); + var ignoredCollision = new List(); // 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 // Probably need a separate "PatchPath" job @@ -339,7 +339,7 @@ namespace Content.Server.GameObjects.EntitySystems.AI.Steering RequestPath(entity, steeringRequest); } - ignoredCollision.Add(entitySteer.Target.Uid); + ignoredCollision.Add(entitySteer.Target); } HandleStuck(entity); @@ -597,7 +597,7 @@ namespace Content.Server.GameObjects.EntitySystems.AI.Steering /// entity's travel direction /// /// - private Vector2 CollisionAvoidance(IEntity entity, Vector2 direction, ICollection ignoredTargets) + private Vector2 CollisionAvoidance(IEntity entity, Vector2 direction, ICollection ignoredTargets) { if (direction == Vector2.Zero || !entity.TryGetComponent(out ICollidableComponent collidableComponent)) { @@ -627,26 +627,25 @@ namespace Content.Server.GameObjects.EntitySystems.AI.Steering { var node = _pathfindingSystem.GetNode(tile); // Assume the immovables have already been checked - foreach (var (uid, layer) in node.PhysicsLayers) + foreach (var (physicsEntity, layer) in node.PhysicsLayers) { // Ignore myself / my target if applicable / if my mask doesn't collide - if (uid == entity.Uid || ignoredTargets.Contains(uid) || (entityCollisionMask & layer) == 0) continue; + if (physicsEntity == entity || ignoredTargets.Contains(physicsEntity) || (entityCollisionMask & layer) == 0) continue; // 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 - var collisionEntity = _entityManager.GetEntity(uid); //Pathfinding updates are deferred so this may not be done yet. - if (collisionEntity.Deleted) continue; + if (physicsEntity.Deleted) continue; // if we're moving in the same direction then ignore // So if 2 entities are moving towards each other and both detect a collision they'll both move in the same direction // i.e. towards the right - if (collisionEntity.TryGetComponent(out IPhysicsComponent physicsComponent) && + if (physicsEntity.TryGetComponent(out IPhysicsComponent physicsComponent) && Vector2.Dot(physicsComponent.LinearVelocity, direction) > 0) { continue; } - var centerGrid = collisionEntity.Transform.GridPosition; + var centerGrid = physicsEntity.Transform.GridPosition; // Check how close we are to center of tile and get the inverse; if we're closer this is stronger var additionalVector = (centerGrid.Position - entityGridCoords.Position); var distance = additionalVector.Length; From 0d29b15ae00e91fb6c8116ccd634894dda17dc6d Mon Sep 17 00:00:00 2001 From: ShadowCommander <10494922+ShadowCommander@users.noreply.github.com> Date: Tue, 11 Aug 2020 08:38:00 -0700 Subject: [PATCH 2/9] Fix StackComponent not getting removed from containers when empty (#1645) --- .../Components/Items/FloorTileItemComponent.cs | 3 --- .../GameObjects/Components/Stack/StackComponent.cs | 10 +--------- .../GameObjects/Components/SharedStackComponent.cs | 5 +++++ 3 files changed, 6 insertions(+), 12 deletions(-) diff --git a/Content.Server/GameObjects/Components/Items/FloorTileItemComponent.cs b/Content.Server/GameObjects/Components/Items/FloorTileItemComponent.cs index 0d31c6c2f1..f15948fc22 100644 --- a/Content.Server/GameObjects/Components/Items/FloorTileItemComponent.cs +++ b/Content.Server/GameObjects/Components/Items/FloorTileItemComponent.cs @@ -50,9 +50,6 @@ namespace Content.Server.GameObjects.Components.Items var desiredTile = _tileDefinitionManager[_outputTile]; mapGrid.SetTile(eventArgs.ClickLocation, new Tile(desiredTile.TileId)); EntitySystem.Get().PlayAtCoords("/Audio/Items/genhit.ogg", eventArgs.ClickLocation); - if(_stack.Count < 1){ - Owner.Delete(); - } } diff --git a/Content.Server/GameObjects/Components/Stack/StackComponent.cs b/Content.Server/GameObjects/Components/Stack/StackComponent.cs index 4fe5350c49..53020796c5 100644 --- a/Content.Server/GameObjects/Components/Stack/StackComponent.cs +++ b/Content.Server/GameObjects/Components/Stack/StackComponent.cs @@ -28,15 +28,7 @@ namespace Content.Server.GameObjects.Components.Stack public override int Count { get => base.Count; - set - { - base.Count = value; - - if (Count <= 0) - { - Owner.Delete(); - } - } + set => base.Count = value; } [ViewVariables(VVAccess.ReadWrite)] diff --git a/Content.Shared/GameObjects/Components/SharedStackComponent.cs b/Content.Shared/GameObjects/Components/SharedStackComponent.cs index 57ef706559..2bdb73cbcd 100644 --- a/Content.Shared/GameObjects/Components/SharedStackComponent.cs +++ b/Content.Shared/GameObjects/Components/SharedStackComponent.cs @@ -1,4 +1,5 @@ using System; +using Robust.Shared.Containers; using Robust.Shared.GameObjects; using Robust.Shared.Interfaces.Reflection; using Robust.Shared.IoC; @@ -26,6 +27,10 @@ namespace Content.Shared.GameObjects.Components _count = value; if (_count <= 0) { + if (ContainerHelpers.TryGetContainerMan(Owner, out var containerManager)) + { + containerManager.Remove(Owner); + } Owner.Delete(); } From 58371b60abaadb27f47b8e0e884c3f3ce5e2269a Mon Sep 17 00:00:00 2001 From: Exp Date: Tue, 11 Aug 2020 17:38:14 +0200 Subject: [PATCH 3/9] Fix Exception as non admin (#1646) --- Content.Client/Chat/ChatManager.cs | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/Content.Client/Chat/ChatManager.cs b/Content.Client/Chat/ChatManager.cs index 2264931496..1cf96367a6 100644 --- a/Content.Client/Chat/ChatManager.cs +++ b/Content.Client/Chat/ChatManager.cs @@ -302,7 +302,8 @@ namespace Content.Client.Chat case "ALL": chatBox.LocalButton.Pressed ^= true; chatBox.OOCButton.Pressed ^= true; - chatBox.AdminButton.Pressed ^= true; + if (chatBox.AdminButton != null) + chatBox.AdminButton.Pressed ^= true; _allState = !_allState; break; } From 2c9ca2f44d3379a8e1cf04034bbfeac07b5ff609 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?V=C3=ADctor=20Aguilera=20Puerto?= Date: Tue, 11 Aug 2020 17:41:59 +0200 Subject: [PATCH 4/9] Removes AssumeAir from IGasMixtureHolder interface. --- Content.Server/Interfaces/IGasMixtureHolder.cs | 2 -- 1 file changed, 2 deletions(-) diff --git a/Content.Server/Interfaces/IGasMixtureHolder.cs b/Content.Server/Interfaces/IGasMixtureHolder.cs index 12f42a214f..ad7d035f88 100644 --- a/Content.Server/Interfaces/IGasMixtureHolder.cs +++ b/Content.Server/Interfaces/IGasMixtureHolder.cs @@ -5,7 +5,5 @@ namespace Content.Server.Interfaces public interface IGasMixtureHolder { public GasMixture Air { get; set; } - - bool AssumeAir(GasMixture giver); } } From c00a08f504589c035ea874726bd0a9d16e4ad952 Mon Sep 17 00:00:00 2001 From: Julian Giebel Date: Tue, 11 Aug 2020 17:52:37 +0200 Subject: [PATCH 5/9] Add disposal-charging state to disposal rsi (#1649) Add charging state to UpdateVisualState in Content.Server/DisposalUnitComponent --- .../Components/Disposal/DisposalUnitVisualizer.cs | 5 +++++ .../Components/Disposal/DisposalUnitComponent.cs | 4 ++++ .../Disposal/SharedDisposalUnitComponent.cs | 3 ++- .../Entities/Constructible/disposal.yml | 1 + .../Power/disposal.rsi/disposal-charging.png | Bin 0 -> 522 bytes .../Constructible/Power/disposal.rsi/meta.json | 2 +- 6 files changed, 13 insertions(+), 2 deletions(-) create mode 100644 Resources/Textures/Constructible/Power/disposal.rsi/disposal-charging.png diff --git a/Content.Client/GameObjects/Components/Disposal/DisposalUnitVisualizer.cs b/Content.Client/GameObjects/Components/Disposal/DisposalUnitVisualizer.cs index 084efbb71c..69d97e9fc4 100644 --- a/Content.Client/GameObjects/Components/Disposal/DisposalUnitVisualizer.cs +++ b/Content.Client/GameObjects/Components/Disposal/DisposalUnitVisualizer.cs @@ -19,6 +19,7 @@ namespace Content.Client.GameObjects.Components.Disposal private string _stateAnchored; private string _stateUnAnchored; + private string _stateCharging; private string _overlayCharging; private string _overlayReady; private string _overlayFull; @@ -47,6 +48,9 @@ namespace Content.Client.GameObjects.Components.Disposal case VisualState.Anchored: sprite.LayerSetState(DisposalUnitVisualLayers.Base, _stateAnchored); break; + case VisualState.Charging: + sprite.LayerSetState(DisposalUnitVisualLayers.Base, _stateCharging); + break; case VisualState.Flushing: sprite.LayerSetState(DisposalUnitVisualLayers.Base, _stateAnchored); @@ -111,6 +115,7 @@ namespace Content.Client.GameObjects.Components.Disposal _stateAnchored = node.GetNode("state_anchored").AsString(); _stateUnAnchored = node.GetNode("state_unanchored").AsString(); + _stateCharging = node.GetNode("state_charging").AsString(); _overlayCharging = node.GetNode("overlay_charging").AsString(); _overlayReady = node.GetNode("overlay_ready").AsString(); _overlayFull = node.GetNode("overlay_full").AsString(); diff --git a/Content.Server/GameObjects/Components/Disposal/DisposalUnitComponent.cs b/Content.Server/GameObjects/Components/Disposal/DisposalUnitComponent.cs index c4c86b38bb..ffc177fd15 100644 --- a/Content.Server/GameObjects/Components/Disposal/DisposalUnitComponent.cs +++ b/Content.Server/GameObjects/Components/Disposal/DisposalUnitComponent.cs @@ -356,6 +356,10 @@ namespace Content.Server.GameObjects.Components.Disposal appearance.SetData(Visuals.Light, LightState.Off); return; } + else if (_pressure < 1) + { + appearance.SetData(Visuals.VisualState, VisualState.Charging); + } else { appearance.SetData(Visuals.VisualState, VisualState.Anchored); diff --git a/Content.Shared/GameObjects/Components/Disposal/SharedDisposalUnitComponent.cs b/Content.Shared/GameObjects/Components/Disposal/SharedDisposalUnitComponent.cs index 12cae99e46..1ce14ae17f 100644 --- a/Content.Shared/GameObjects/Components/Disposal/SharedDisposalUnitComponent.cs +++ b/Content.Shared/GameObjects/Components/Disposal/SharedDisposalUnitComponent.cs @@ -22,7 +22,8 @@ namespace Content.Shared.GameObjects.Components.Disposal { UnAnchored, Anchored, - Flushing + Flushing, + Charging } [Serializable, NetSerializable] diff --git a/Resources/Prototypes/Entities/Constructible/disposal.yml b/Resources/Prototypes/Entities/Constructible/disposal.yml index 5e2fad5706..738ec4d1b7 100644 --- a/Resources/Prototypes/Entities/Constructible/disposal.yml +++ b/Resources/Prototypes/Entities/Constructible/disposal.yml @@ -118,6 +118,7 @@ - type: DisposalUnitVisualizer state_unanchored: condisposal state_anchored: disposal + state_charging: disposal-charging overlay_charging: dispover-charge overlay_ready: dispover-ready overlay_full: dispover-full diff --git a/Resources/Textures/Constructible/Power/disposal.rsi/disposal-charging.png b/Resources/Textures/Constructible/Power/disposal.rsi/disposal-charging.png new file mode 100644 index 0000000000000000000000000000000000000000..85a3162add4156e08329d1d1cd96359cb5ef79b6 GIT binary patch literal 522 zcmeAS@N?(olHy`uVBq!ia0vp^3LwnE1|*BCs=fdzwj^(N7l!{JxM1({$v_d#0*}aI z1_o|n5N2eUHAey{$X?><>&pIwgPUK9zjxpKW(Eev>7Fi*ArXg@6C_xfc_co1%B@XZ z-lcl&tbO6BjRF^b&%Y+8`h_xu!Lu)pw=5liDl|&D)BKfh`79DjT=%M`?WDMn=ch;@3utcKD+`CyP16&1 z9hKrxpBAD1AxMttcK!-u1A{v*kBto~vhKJ%Ocr*28o$VfcS5q|QN@Dxn_Uk#Kjr~B zicQ+RLt;%#^T&;yiqmV$^Yjl%GqGGgFf%wkGfH|>K$gRYe{~}NqK-SY0Uc&^XK#IP z72k~=b*5p3{|^MTecpakqR+@l%lh^I|B@0ik{#RTWUy;!XC+FkTC?Kl0U#*Q*PZ=P zcgv5x?kSG0o0v;@wnz$HdXzEAtfP-9=i&o-39pUJGdg;il8$7EF*Vz9C2)qc_qbTt zENYl^q~ki{iOTs?mWdU;5YU>!(Z-;;^p=LiBnF07gU&ZXf+t@CV~xSn)z4*}Q$iB} Dn&r%e literal 0 HcmV?d00001 diff --git a/Resources/Textures/Constructible/Power/disposal.rsi/meta.json b/Resources/Textures/Constructible/Power/disposal.rsi/meta.json index 78444a552e..96aadcfa66 100644 --- a/Resources/Textures/Constructible/Power/disposal.rsi/meta.json +++ b/Resources/Textures/Constructible/Power/disposal.rsi/meta.json @@ -1 +1 @@ -{"version": 1, "size": {"x": 32, "y": 32}, "license": "CC-BY-SA-3.0", "copyright": "https://github.com/discordia-space/CEV-Eris/blob/bbe32606902c90f5290b57d905a3f31b84dc6d7d/icons/obj/pipes/disposal.dmi and modified by DrSmugleaf", "states": [{"name": "condisposal", "directions": 1, "delays": [[1.0]]}, {"name": "conpipe-c", "directions": 4, "delays": [[1.0], [1.0], [1.0], [1.0]]}, {"name": "conpipe-j1", "directions": 4, "delays": [[1.0], [1.0], [1.0], [1.0]]}, {"name": "conpipe-j1s", "directions": 4, "delays": [[1.0], [1.0], [1.0], [1.0]]}, {"name": "conpipe-j2", "directions": 4, "delays": [[1.0], [1.0], [1.0], [1.0]]}, {"name": "conpipe-j2s", "directions": 4, "delays": [[1.0], [1.0], [1.0], [1.0]]}, {"name": "conpipe-s", "directions": 4, "delays": [[1.0], [1.0], [1.0], [1.0]]}, {"name": "conpipe-t", "directions": 4, "delays": [[1.0], [1.0], [1.0], [1.0]]}, {"name": "conpipe-y", "directions": 4, "delays": [[1.0], [1.0], [1.0], [1.0]]}, {"name": "disposal", "directions": 1, "delays": [[1.0]]}, {"name": "disposal-flush", "directions": 1, "delays": [[0.1, 0.1, 0.1, 0.1, 0.1, 0.5, 0.1, 0.1, 0.1]]}, {"name": "dispover-charge", "directions": 1, "delays": [[0.4, 0.4]]}, {"name": "dispover-full", "directions": 1, "delays": [[0.2, 0.2]]}, {"name": "dispover-handle", "directions": 1, "delays": [[1.0]]}, {"name": "dispover-ready", "directions": 1, "delays": [[1.0]]}, {"name": "intake", "directions": 4, "delays": [[1.0], [1.0], [1.0], [1.0]]}, {"name": "intake-closing", "directions": 4, "delays": [[0.5, 0.1, 0.1, 0.1, 0.1, 0.1, 0.1, 0.1], [0.5, 0.1, 0.1, 0.1, 0.1, 0.1, 0.1, 0.1], [0.5, 0.1, 0.1, 0.1, 0.1, 0.1, 0.1, 0.1], [0.5, 0.1, 0.1, 0.1, 0.1, 0.1, 0.1, 0.1]]}, {"name": "outlet", "directions": 4, "delays": [[1.0], [1.0], [1.0], [1.0]]}, {"name": "outlet-open", "directions": 4, "delays": [[0.5, 0.5, 0.5, 0.5, 0.5, 0.1, 1.5, 0.1], [0.5, 0.5, 0.5, 0.5, 0.5, 0.1, 1.5, 0.1], [0.5, 0.5, 0.5, 0.5, 0.5, 0.1, 1.5, 0.1], [0.5, 0.5, 0.5, 0.5, 0.5, 0.1, 1.5, 0.1]]}, {"name": "pipe-b", "directions": 4, "delays": [[1.0], [1.0], [1.0], [1.0]]}, {"name": "pipe-bf", "directions": 4, "delays": [[1.0], [1.0], [1.0], [1.0]]}, {"name": "pipe-c", "directions": 4, "delays": [[1.0], [1.0], [1.0], [1.0]]}, {"name": "pipe-cf", "directions": 4, "delays": [[1.0], [1.0], [1.0], [1.0]]}, {"name": "pipe-d", "directions": 4, "delays": [[1.0], [1.0], [1.0], [1.0]]}, {"name": "pipe-j1", "directions": 4, "delays": [[1.0], [1.0], [1.0], [1.0]]}, {"name": "pipe-j1f", "directions": 4, "delays": [[1.0], [1.0], [1.0], [1.0]]}, {"name": "pipe-j1s", "directions": 4, "delays": [[1.0], [1.0], [1.0], [1.0]]}, {"name": "pipe-j1sf", "directions": 4, "delays": [[1.0], [1.0], [1.0], [1.0]]}, {"name": "pipe-j2", "directions": 4, "delays": [[1.0], [1.0], [1.0], [1.0]]}, {"name": "pipe-j2f", "directions": 4, "delays": [[1.0], [1.0], [1.0], [1.0]]}, {"name": "pipe-j2s", "directions": 4, "delays": [[1.0], [1.0], [1.0], [1.0]]}, {"name": "pipe-j2sf", "directions": 4, "delays": [[1.0], [1.0], [1.0], [1.0]]}, {"name": "pipe-s", "directions": 4, "delays": [[1.0], [1.0], [1.0], [1.0]]}, {"name": "pipe-sf", "directions": 4, "delays": [[1.0], [1.0], [1.0], [1.0]]}, {"name": "pipe-t", "directions": 4, "delays": [[1.0], [1.0], [1.0], [1.0]]}, {"name": "pipe-tagger", "directions": 4, "delays": [[1.0], [1.0], [1.0], [1.0]]}, {"name": "pipe-tagger-partial", "directions": 4, "delays": [[1.0], [1.0], [1.0], [1.0]]}, {"name": "pipe-tf", "directions": 4, "delays": [[1.0], [1.0], [1.0], [1.0]]}, {"name": "pipe-u", "directions": 4, "delays": [[1.0], [1.0], [1.0], [1.0]]}, {"name": "pipe-y", "directions": 4, "delays": [[1.0], [1.0], [1.0], [1.0]]}, {"name": "pipe-yf", "directions": 4, "delays": [[1.0], [1.0], [1.0], [1.0]]}]} +{"version": 1, "size": {"x": 32, "y": 32}, "license": "CC-BY-SA-3.0", "copyright": "https://github.com/discordia-space/CEV-Eris/blob/bbe32606902c90f5290b57d905a3f31b84dc6d7d/icons/obj/pipes/disposal.dmi and modified by DrSmugleaf", "states": [{"name": "condisposal", "directions": 1, "delays": [[1.0]]}, {"name": "conpipe-c", "directions": 4, "delays": [[1.0], [1.0], [1.0], [1.0]]}, {"name": "conpipe-j1", "directions": 4, "delays": [[1.0], [1.0], [1.0], [1.0]]}, {"name": "conpipe-j1s", "directions": 4, "delays": [[1.0], [1.0], [1.0], [1.0]]}, {"name": "conpipe-j2", "directions": 4, "delays": [[1.0], [1.0], [1.0], [1.0]]}, {"name": "conpipe-j2s", "directions": 4, "delays": [[1.0], [1.0], [1.0], [1.0]]}, {"name": "conpipe-s", "directions": 4, "delays": [[1.0], [1.0], [1.0], [1.0]]}, {"name": "conpipe-t", "directions": 4, "delays": [[1.0], [1.0], [1.0], [1.0]]}, {"name": "conpipe-y", "directions": 4, "delays": [[1.0], [1.0], [1.0], [1.0]]}, {"name": "disposal", "directions": 1, "delays": [[1.0]]}, {"name": "disposal-charging", "directions": 1, "delays": [[1.0]]}, {"name": "disposal-flush", "directions": 1, "delays": [[0.1, 0.1, 0.1, 0.1, 0.1, 0.5, 0.1, 0.1, 0.1]]}, {"name": "dispover-charge", "directions": 1, "delays": [[0.4, 0.4]]}, {"name": "dispover-full", "directions": 1, "delays": [[0.2, 0.2]]}, {"name": "dispover-handle", "directions": 1, "delays": [[1.0]]}, {"name": "dispover-ready", "directions": 1, "delays": [[1.0]]}, {"name": "intake", "directions": 4, "delays": [[1.0], [1.0], [1.0], [1.0]]}, {"name": "intake-closing", "directions": 4, "delays": [[0.5, 0.1, 0.1, 0.1, 0.1, 0.1, 0.1, 0.1], [0.5, 0.1, 0.1, 0.1, 0.1, 0.1, 0.1, 0.1], [0.5, 0.1, 0.1, 0.1, 0.1, 0.1, 0.1, 0.1], [0.5, 0.1, 0.1, 0.1, 0.1, 0.1, 0.1, 0.1]]}, {"name": "outlet", "directions": 4, "delays": [[1.0], [1.0], [1.0], [1.0]]}, {"name": "outlet-open", "directions": 4, "delays": [[0.5, 0.5, 0.5, 0.5, 0.5, 0.1, 1.5, 0.1], [0.5, 0.5, 0.5, 0.5, 0.5, 0.1, 1.5, 0.1], [0.5, 0.5, 0.5, 0.5, 0.5, 0.1, 1.5, 0.1], [0.5, 0.5, 0.5, 0.5, 0.5, 0.1, 1.5, 0.1]]}, {"name": "pipe-b", "directions": 4, "delays": [[1.0], [1.0], [1.0], [1.0]]}, {"name": "pipe-bf", "directions": 4, "delays": [[1.0], [1.0], [1.0], [1.0]]}, {"name": "pipe-c", "directions": 4, "delays": [[1.0], [1.0], [1.0], [1.0]]}, {"name": "pipe-cf", "directions": 4, "delays": [[1.0], [1.0], [1.0], [1.0]]}, {"name": "pipe-d", "directions": 4, "delays": [[1.0], [1.0], [1.0], [1.0]]}, {"name": "pipe-j1", "directions": 4, "delays": [[1.0], [1.0], [1.0], [1.0]]}, {"name": "pipe-j1f", "directions": 4, "delays": [[1.0], [1.0], [1.0], [1.0]]}, {"name": "pipe-j1s", "directions": 4, "delays": [[1.0], [1.0], [1.0], [1.0]]}, {"name": "pipe-j1sf", "directions": 4, "delays": [[1.0], [1.0], [1.0], [1.0]]}, {"name": "pipe-j2", "directions": 4, "delays": [[1.0], [1.0], [1.0], [1.0]]}, {"name": "pipe-j2f", "directions": 4, "delays": [[1.0], [1.0], [1.0], [1.0]]}, {"name": "pipe-j2s", "directions": 4, "delays": [[1.0], [1.0], [1.0], [1.0]]}, {"name": "pipe-j2sf", "directions": 4, "delays": [[1.0], [1.0], [1.0], [1.0]]}, {"name": "pipe-s", "directions": 4, "delays": [[1.0], [1.0], [1.0], [1.0]]}, {"name": "pipe-sf", "directions": 4, "delays": [[1.0], [1.0], [1.0], [1.0]]}, {"name": "pipe-t", "directions": 4, "delays": [[1.0], [1.0], [1.0], [1.0]]}, {"name": "pipe-tagger", "directions": 4, "delays": [[1.0], [1.0], [1.0], [1.0]]}, {"name": "pipe-tagger-partial", "directions": 4, "delays": [[1.0], [1.0], [1.0], [1.0]]}, {"name": "pipe-tf", "directions": 4, "delays": [[1.0], [1.0], [1.0], [1.0]]}, {"name": "pipe-u", "directions": 4, "delays": [[1.0], [1.0], [1.0], [1.0]]}, {"name": "pipe-y", "directions": 4, "delays": [[1.0], [1.0], [1.0], [1.0]]}, {"name": "pipe-yf", "directions": 4, "delays": [[1.0], [1.0], [1.0], [1.0]]}]} \ No newline at end of file From b34bd7c188ee404a7945ce001cfb50dce0893489 Mon Sep 17 00:00:00 2001 From: metalgearsloth <31366439+metalgearsloth@users.noreply.github.com> Date: Wed, 12 Aug 2020 06:01:55 +1000 Subject: [PATCH 6/9] AI preset curves and expandable optimisation (#1346) * AI preset curves and expandable optimisation Added preset curves for considerations to use just to avoid repeating the same variables all over the shop. Moved common considerations for expanded actions onto the expandable action e.g. you need a free hand to be able to PickUpGloves so we'll just check it the once rather than for each action. * FIX PRAGMA Co-authored-by: Metal Gear Sloth --- .../Actions/Clothing/Gloves/EquipGloves.cs | 6 +- .../Actions/Clothing/Gloves/PickUpGloves.cs | 11 ++- .../Actions/Clothing/Head/EquipHead.cs | 4 +- .../Actions/Clothing/Head/PickUpHead.cs | 11 ++- .../OuterClothing/EquipOuterClothing.cs | 4 +- .../OuterClothing/PickUpOuterClothing.cs | 9 +-- .../Actions/Clothing/Shoes/EquipShoes.cs | 4 +- .../Actions/Clothing/Shoes/PickUpShoes.cs | 9 +-- .../Actions/Combat/Melee/EquipMelee.cs | 4 +- .../Combat/Melee/MeleeWeaponAttackEntity.cs | 8 +- .../Actions/Combat/Melee/PickUpMeleeWeapon.cs | 8 +- .../Combat/Melee/UnarmedAttackEntity.cs | 10 +-- .../Actions/Idle/CloseLastEntityStorage.cs | 10 +-- .../Actions/Nutrition/Drink/PickUpDrink.cs | 6 +- .../Nutrition/Drink/UseDrinkInInventory.cs | 6 +- .../Actions/Nutrition/Food/PickUpFood.cs | 9 +-- .../Nutrition/Food/UseFoodInInventory.cs | 8 +- .../AI/Utility/Actions/UtilityAction.cs | 1 - .../Utility/BehaviorSets/ThirstBehaviorSet.cs | 2 +- .../Utility/Considerations/Consideration.cs | 77 +++++++++++++++++-- .../Hands/TargetInOurHandsCon.cs | 28 ------- ...dsCon.cs => CanPutTargetInInventoryCon.cs} | 2 +- .../Inventory/TargetInOurInventoryCon.cs | 1 + .../{DistanceCon.cs => TargetDistanceCon.cs} | 6 +- .../Clothing/Gloves/EquipAnyGlovesExp.cs | 15 +++- .../Gloves/PickUpAnyNearbyGlovesExp.cs | 18 +++++ .../Clothing/Head/EquipAnyHeadExp.cs | 14 ++++ .../Clothing/Head/PickUpAnyNearbyHeadExp.cs | 17 +++- .../OuterClothing/EquipAnyOuterClothingExp.cs | 15 +++- .../PickUpAnyNearbyOuterClothingExp.cs | 18 +++++ .../Clothing/Shoes/EquipAnyShoesExp.cs | 15 +++- .../Clothing/Shoes/PickUpAnyNearbyShoesExp.cs | 18 +++++ .../Combat/Melee/EquipMeleeExp.cs | 16 ++++ .../Melee/MeleeAttackNearbyPlayerExp.cs | 14 ++++ .../Melee/MeleeAttackNearbySpeciesExp.cs | 3 + .../Combat/Melee/PickUpMeleeWeaponExp.cs | 18 +++++ .../Melee/UnarmedAttackNearbyPlayerExp.cs | 14 ++++ .../ExpandableUtilityAction.cs | 32 ++++++++ .../Nutrition/PickUpNearbyDrinkExp.cs | 15 ++++ .../Nutrition/PickUpNearbyFoodExp.cs | 15 ++++ ...nHandsExp.cs => UseDrinkInInventoryExp.cs} | 15 +++- .../Nutrition/UseFoodInInventoryExp.cs | 13 ++++ .../AI/LoadBalancer/AiActionRequestJob.cs | 7 +- 43 files changed, 409 insertions(+), 127 deletions(-) delete mode 100644 Content.Server/AI/Utility/Considerations/Hands/TargetInOurHandsCon.cs rename Content.Server/AI/Utility/Considerations/Inventory/{CanPutTargetInHandsCon.cs => CanPutTargetInInventoryCon.cs} (94%) rename Content.Server/AI/Utility/Considerations/Movement/{DistanceCon.cs => TargetDistanceCon.cs} (68%) rename Content.Server/AI/Utility/ExpandableActions/Nutrition/{UseDrinkInHandsExp.cs => UseDrinkInInventoryExp.cs} (62%) diff --git a/Content.Server/AI/Utility/Actions/Clothing/Gloves/EquipGloves.cs b/Content.Server/AI/Utility/Actions/Clothing/Gloves/EquipGloves.cs index 96317b6ad2..fcd63a2da6 100644 --- a/Content.Server/AI/Utility/Actions/Clothing/Gloves/EquipGloves.cs +++ b/Content.Server/AI/Utility/Actions/Clothing/Gloves/EquipGloves.cs @@ -3,11 +3,9 @@ using System.Collections.Generic; using Content.Server.AI.Operators; using Content.Server.AI.Operators.Inventory; using Content.Server.AI.Utility.Considerations; -using Content.Server.AI.Utility.Considerations.Clothing; using Content.Server.AI.Utility.Considerations.Inventory; using Content.Server.AI.WorldState; using Content.Server.AI.WorldState.States; -using Content.Shared.GameObjects.Components.Inventory; using Robust.Shared.Interfaces.GameObjects; using Robust.Shared.IoC; @@ -44,9 +42,7 @@ namespace Content.Server.AI.Utility.Actions.Clothing.Gloves return new[] { - considerationsManager.Get().Slot(EquipmentSlotDefines.Slots.GLOVES, context) - .InverseBoolCurve(context), - considerationsManager.Get() + considerationsManager.Get() .BoolCurve(context), }; } diff --git a/Content.Server/AI/Utility/Actions/Clothing/Gloves/PickUpGloves.cs b/Content.Server/AI/Utility/Actions/Clothing/Gloves/PickUpGloves.cs index 736db66a7f..85df65dbfc 100644 --- a/Content.Server/AI/Utility/Actions/Clothing/Gloves/PickUpGloves.cs +++ b/Content.Server/AI/Utility/Actions/Clothing/Gloves/PickUpGloves.cs @@ -5,6 +5,7 @@ using Content.Server.AI.Utility.Considerations; using Content.Server.AI.Utility.Considerations.Clothing; using Content.Server.AI.Utility.Considerations.Containers; using Content.Server.AI.Utility.Considerations.Inventory; +using Content.Server.AI.Utility.Considerations.Movement; using Content.Server.AI.WorldState; using Content.Server.AI.WorldState.States; using Content.Shared.GameObjects.Components.Inventory; @@ -40,13 +41,11 @@ namespace Content.Server.AI.Utility.Actions.Clothing.Gloves return new[] { - considerationsManager.Get().Slot(EquipmentSlotDefines.Slots.GLOVES, context) - .InverseBoolCurve(context), - considerationsManager.Get() + considerationsManager.Get() .BoolCurve(context), - considerationsManager.Get().Slot(EquipmentSlotDefines.SlotFlags.GLOVES, context) - .InverseBoolCurve(context), - considerationsManager.Get() + considerationsManager.Get() + .PresetCurve(context, PresetCurve.Distance), + considerationsManager.Get() .BoolCurve(context), }; } diff --git a/Content.Server/AI/Utility/Actions/Clothing/Head/EquipHead.cs b/Content.Server/AI/Utility/Actions/Clothing/Head/EquipHead.cs index 1935416dc7..7bffe3d92d 100644 --- a/Content.Server/AI/Utility/Actions/Clothing/Head/EquipHead.cs +++ b/Content.Server/AI/Utility/Actions/Clothing/Head/EquipHead.cs @@ -44,9 +44,7 @@ namespace Content.Server.AI.Utility.Actions.Clothing.Head return new[] { - considerationsManager.Get().Slot(EquipmentSlotDefines.Slots.HEAD, context) - .InverseBoolCurve(context), - considerationsManager.Get() + considerationsManager.Get() .BoolCurve(context), }; diff --git a/Content.Server/AI/Utility/Actions/Clothing/Head/PickUpHead.cs b/Content.Server/AI/Utility/Actions/Clothing/Head/PickUpHead.cs index 038dd54a6b..ba91121254 100644 --- a/Content.Server/AI/Utility/Actions/Clothing/Head/PickUpHead.cs +++ b/Content.Server/AI/Utility/Actions/Clothing/Head/PickUpHead.cs @@ -5,6 +5,7 @@ using Content.Server.AI.Utility.Considerations; using Content.Server.AI.Utility.Considerations.Clothing; using Content.Server.AI.Utility.Considerations.Containers; using Content.Server.AI.Utility.Considerations.Inventory; +using Content.Server.AI.Utility.Considerations.Movement; using Content.Server.AI.WorldState; using Content.Server.AI.WorldState.States; using Content.Shared.GameObjects.Components.Inventory; @@ -40,13 +41,11 @@ namespace Content.Server.AI.Utility.Actions.Clothing.Head return new[] { - considerationsManager.Get().Slot(EquipmentSlotDefines.Slots.HEAD, context) - .InverseBoolCurve(context), - considerationsManager.Get() + considerationsManager.Get() .BoolCurve(context), - considerationsManager.Get().Slot(EquipmentSlotDefines.SlotFlags.HEAD, context) - .InverseBoolCurve(context), - considerationsManager.Get() + considerationsManager.Get() + .PresetCurve(context, PresetCurve.Distance), + considerationsManager.Get() .BoolCurve(context), }; } diff --git a/Content.Server/AI/Utility/Actions/Clothing/OuterClothing/EquipOuterClothing.cs b/Content.Server/AI/Utility/Actions/Clothing/OuterClothing/EquipOuterClothing.cs index e593098cf5..9955cc49aa 100644 --- a/Content.Server/AI/Utility/Actions/Clothing/OuterClothing/EquipOuterClothing.cs +++ b/Content.Server/AI/Utility/Actions/Clothing/OuterClothing/EquipOuterClothing.cs @@ -44,9 +44,7 @@ namespace Content.Server.AI.Utility.Actions.Clothing.OuterClothing return new[] { - considerationsManager.Get().Slot(EquipmentSlotDefines.Slots.OUTERCLOTHING, context) - .InverseBoolCurve(context), - considerationsManager.Get() + considerationsManager.Get() .BoolCurve(context), }; } diff --git a/Content.Server/AI/Utility/Actions/Clothing/OuterClothing/PickUpOuterClothing.cs b/Content.Server/AI/Utility/Actions/Clothing/OuterClothing/PickUpOuterClothing.cs index 0eb4ff1cbe..22730f3659 100644 --- a/Content.Server/AI/Utility/Actions/Clothing/OuterClothing/PickUpOuterClothing.cs +++ b/Content.Server/AI/Utility/Actions/Clothing/OuterClothing/PickUpOuterClothing.cs @@ -5,6 +5,7 @@ using Content.Server.AI.Utility.Considerations; using Content.Server.AI.Utility.Considerations.Clothing; using Content.Server.AI.Utility.Considerations.Containers; using Content.Server.AI.Utility.Considerations.Inventory; +using Content.Server.AI.Utility.Considerations.Movement; using Content.Server.AI.WorldState; using Content.Server.AI.WorldState.States; using Content.Shared.GameObjects.Components.Inventory; @@ -40,12 +41,10 @@ namespace Content.Server.AI.Utility.Actions.Clothing.OuterClothing return new[] { - considerationsManager.Get().Slot(EquipmentSlotDefines.Slots.OUTERCLOTHING, context) - .InverseBoolCurve(context), - considerationsManager.Get() + considerationsManager.Get() .BoolCurve(context), - considerationsManager.Get().Slot(EquipmentSlotDefines.SlotFlags.OUTERCLOTHING, context) - .InverseBoolCurve(context), + considerationsManager.Get() + .PresetCurve(context, PresetCurve.Distance), considerationsManager.Get() .BoolCurve(context), }; diff --git a/Content.Server/AI/Utility/Actions/Clothing/Shoes/EquipShoes.cs b/Content.Server/AI/Utility/Actions/Clothing/Shoes/EquipShoes.cs index fdbc2c78e7..218e218c35 100644 --- a/Content.Server/AI/Utility/Actions/Clothing/Shoes/EquipShoes.cs +++ b/Content.Server/AI/Utility/Actions/Clothing/Shoes/EquipShoes.cs @@ -44,9 +44,7 @@ namespace Content.Server.AI.Utility.Actions.Clothing.Shoes return new[] { - considerationsManager.Get().Slot(EquipmentSlotDefines.Slots.SHOES, context) - .InverseBoolCurve(context), - considerationsManager.Get() + considerationsManager.Get() .BoolCurve(context), }; } diff --git a/Content.Server/AI/Utility/Actions/Clothing/Shoes/PickUpShoes.cs b/Content.Server/AI/Utility/Actions/Clothing/Shoes/PickUpShoes.cs index 94dd05efd4..00cd4b1cd9 100644 --- a/Content.Server/AI/Utility/Actions/Clothing/Shoes/PickUpShoes.cs +++ b/Content.Server/AI/Utility/Actions/Clothing/Shoes/PickUpShoes.cs @@ -5,6 +5,7 @@ using Content.Server.AI.Utility.Considerations; using Content.Server.AI.Utility.Considerations.Clothing; using Content.Server.AI.Utility.Considerations.Containers; using Content.Server.AI.Utility.Considerations.Inventory; +using Content.Server.AI.Utility.Considerations.Movement; using Content.Server.AI.WorldState; using Content.Server.AI.WorldState.States; using Content.Shared.GameObjects.Components.Inventory; @@ -40,12 +41,10 @@ namespace Content.Server.AI.Utility.Actions.Clothing.Shoes return new[] { - considerationsManager.Get().Slot(EquipmentSlotDefines.Slots.SHOES, context) - .InverseBoolCurve(context), - considerationsManager.Get() + considerationsManager.Get() .BoolCurve(context), - considerationsManager.Get().Slot(EquipmentSlotDefines.SlotFlags.SHOES, context) - .InverseBoolCurve(context), + considerationsManager.Get() + .PresetCurve(context, PresetCurve.Distance), considerationsManager.Get() .BoolCurve(context), }; diff --git a/Content.Server/AI/Utility/Actions/Combat/Melee/EquipMelee.cs b/Content.Server/AI/Utility/Actions/Combat/Melee/EquipMelee.cs index 29bdea8394..ce42bfd6dd 100644 --- a/Content.Server/AI/Utility/Actions/Combat/Melee/EquipMelee.cs +++ b/Content.Server/AI/Utility/Actions/Combat/Melee/EquipMelee.cs @@ -44,9 +44,7 @@ namespace Content.Server.AI.Utility.Actions.Combat.Melee return new[] { - considerationsManager.Get() - .InverseBoolCurve(context), - considerationsManager.Get() + considerationsManager.Get() .BoolCurve(context), considerationsManager.Get() .QuadraticCurve(context, 1.0f, 0.5f, 0.0f, 0.0f), diff --git a/Content.Server/AI/Utility/Actions/Combat/Melee/MeleeWeaponAttackEntity.cs b/Content.Server/AI/Utility/Actions/Combat/Melee/MeleeWeaponAttackEntity.cs index 5b9ce74248..28335ace75 100644 --- a/Content.Server/AI/Utility/Actions/Combat/Melee/MeleeWeaponAttackEntity.cs +++ b/Content.Server/AI/Utility/Actions/Combat/Melee/MeleeWeaponAttackEntity.cs @@ -66,16 +66,14 @@ namespace Content.Server.AI.Utility.Actions.Combat.Melee return new[] { - considerationsManager.Get() - .BoolCurve(context), considerationsManager.Get() .InverseBoolCurve(context), considerationsManager.Get() .QuadraticCurve(context, -0.8f, 1.0f, 1.0f, 0.0f), - considerationsManager.Get() - .QuadraticCurve(context, 1.0f, 1.0f, 0.02f, 0.0f), + considerationsManager.Get() + .PresetCurve(context, PresetCurve.Distance), considerationsManager.Get() - .QuadraticCurve(context, 1.0f, 0.4f, 0.0f, -0.02f), + .PresetCurve(context, PresetCurve.TargetHealth), considerationsManager.Get() .QuadraticCurve(context, 1.0f, 0.5f, 0.0f, 0.0f), considerationsManager.Get() diff --git a/Content.Server/AI/Utility/Actions/Combat/Melee/PickUpMeleeWeapon.cs b/Content.Server/AI/Utility/Actions/Combat/Melee/PickUpMeleeWeapon.cs index 12b502b4dd..708afc240e 100644 --- a/Content.Server/AI/Utility/Actions/Combat/Melee/PickUpMeleeWeapon.cs +++ b/Content.Server/AI/Utility/Actions/Combat/Melee/PickUpMeleeWeapon.cs @@ -42,12 +42,8 @@ namespace Content.Server.AI.Utility.Actions.Combat.Melee return new[] { - considerationsManager.Get() - .BoolCurve(context), - considerationsManager.Get() - .InverseBoolCurve(context), - considerationsManager.Get() - .QuadraticCurve(context, 1.0f, 1.0f, 0.02f, 0.0f), + considerationsManager.Get() + .PresetCurve(context, PresetCurve.Distance), considerationsManager.Get() .QuadraticCurve(context, 1.0f, 0.25f, 0.0f, 0.0f), considerationsManager.Get() diff --git a/Content.Server/AI/Utility/Actions/Combat/Melee/UnarmedAttackEntity.cs b/Content.Server/AI/Utility/Actions/Combat/Melee/UnarmedAttackEntity.cs index d3593cc982..5735b884e7 100644 --- a/Content.Server/AI/Utility/Actions/Combat/Melee/UnarmedAttackEntity.cs +++ b/Content.Server/AI/Utility/Actions/Combat/Melee/UnarmedAttackEntity.cs @@ -64,16 +64,14 @@ namespace Content.Server.AI.Utility.Actions.Combat.Melee return new[] { - considerationsManager.Get() - .BoolCurve(context), considerationsManager.Get() .InverseBoolCurve(context), considerationsManager.Get() .QuadraticCurve(context, -0.8f, 1.0f, 1.0f, 0.0f), - considerationsManager.Get() - .QuadraticCurve(context, -1.0f, 1.0f, 1.02f, 0.0f), + considerationsManager.Get() + .PresetCurve(context, PresetCurve.Distance), considerationsManager.Get() - .QuadraticCurve(context, 1.0f, 0.4f, 0.0f, -0.02f), + .PresetCurve(context, PresetCurve.TargetHealth), considerationsManager.Get() .BoolCurve(context), // TODO: Consider our Speed and Damage to compare this to using a weapon @@ -81,4 +79,4 @@ namespace Content.Server.AI.Utility.Actions.Combat.Melee }; } } -} \ No newline at end of file +} diff --git a/Content.Server/AI/Utility/Actions/Idle/CloseLastEntityStorage.cs b/Content.Server/AI/Utility/Actions/Idle/CloseLastEntityStorage.cs index 4d9fa36f8a..f1ab155f00 100644 --- a/Content.Server/AI/Utility/Actions/Idle/CloseLastEntityStorage.cs +++ b/Content.Server/AI/Utility/Actions/Idle/CloseLastEntityStorage.cs @@ -20,7 +20,7 @@ namespace Content.Server.AI.Utility.Actions.Idle /// public sealed class CloseLastEntityStorage : UtilityAction { - public override float Bonus => 1.5f; + public override float Bonus => IdleBonus + 0.01f; public CloseLastEntityStorage(IEntity owner) : base(owner) {} @@ -50,12 +50,12 @@ namespace Content.Server.AI.Utility.Actions.Idle { considerationsManager.Get().Set(typeof(LastOpenedStorageState), context) .InverseBoolCurve(context), - considerationsManager.Get() - .QuadraticCurve(context, 1.0f, 1.0f, 0.02f, 0.0f), - considerationsManager.Get() + considerationsManager.Get() + .PresetCurve(context, PresetCurve.Distance), + considerationsManager.Get() .BoolCurve(context), }; } } -} \ No newline at end of file +} diff --git a/Content.Server/AI/Utility/Actions/Nutrition/Drink/PickUpDrink.cs b/Content.Server/AI/Utility/Actions/Nutrition/Drink/PickUpDrink.cs index a7680e6eb8..0549fc1ed7 100644 --- a/Content.Server/AI/Utility/Actions/Nutrition/Drink/PickUpDrink.cs +++ b/Content.Server/AI/Utility/Actions/Nutrition/Drink/PickUpDrink.cs @@ -43,9 +43,9 @@ namespace Content.Server.AI.Utility.Actions.Nutrition.Drink considerationsManager.Get() .BoolCurve(context), considerationsManager.Get() - .LogisticCurve(context, 1000f, 1.3f, -1.0f, 0.5f), - considerationsManager.Get() - .QuadraticCurve(context, 1.0f, 1.0f, 0.02f, 0.0f), + .PresetCurve(context, PresetCurve.Nutrition), + considerationsManager.Get() + .PresetCurve(context, PresetCurve.Distance), considerationsManager.Get() .QuadraticCurve(context, 1.0f, 0.4f, 0.0f, 0.0f), considerationsManager.Get() diff --git a/Content.Server/AI/Utility/Actions/Nutrition/Drink/UseDrinkInInventory.cs b/Content.Server/AI/Utility/Actions/Nutrition/Drink/UseDrinkInInventory.cs index 408addf0d1..f05838ce22 100644 --- a/Content.Server/AI/Utility/Actions/Nutrition/Drink/UseDrinkInInventory.cs +++ b/Content.Server/AI/Utility/Actions/Nutrition/Drink/UseDrinkInInventory.cs @@ -3,7 +3,7 @@ using System.Collections.Generic; using Content.Server.AI.Operators; using Content.Server.AI.Operators.Inventory; using Content.Server.AI.Utility.Considerations; -using Content.Server.AI.Utility.Considerations.Hands; +using Content.Server.AI.Utility.Considerations.Inventory; using Content.Server.AI.Utility.Considerations.Nutrition.Drink; using Content.Server.AI.WorldState; using Content.Server.AI.WorldState.States; @@ -43,10 +43,8 @@ namespace Content.Server.AI.Utility.Actions.Nutrition.Drink return new[] { - considerationsManager.Get() + considerationsManager.Get() .BoolCurve(context), - considerationsManager.Get() - .LogisticCurve(context, 1000f, 1.3f, -0.3f, 0.5f), considerationsManager.Get() .QuadraticCurve(context, 1.0f, 0.4f, 0.0f, 0.0f), }; diff --git a/Content.Server/AI/Utility/Actions/Nutrition/Food/PickUpFood.cs b/Content.Server/AI/Utility/Actions/Nutrition/Food/PickUpFood.cs index 840d9c3cab..4c4dd08cfa 100644 --- a/Content.Server/AI/Utility/Actions/Nutrition/Food/PickUpFood.cs +++ b/Content.Server/AI/Utility/Actions/Nutrition/Food/PickUpFood.cs @@ -3,7 +3,6 @@ using System.Collections.Generic; using Content.Server.AI.Operators.Sequences; using Content.Server.AI.Utility.Considerations; using Content.Server.AI.Utility.Considerations.Containers; -using Content.Server.AI.Utility.Considerations.Hands; using Content.Server.AI.Utility.Considerations.Movement; using Content.Server.AI.Utility.Considerations.Nutrition.Food; using Content.Server.AI.WorldState; @@ -40,12 +39,8 @@ namespace Content.Server.AI.Utility.Actions.Nutrition.Food return new[] { - considerationsManager.Get() - .BoolCurve(context), - considerationsManager.Get() - .LogisticCurve(context, 1000f, 1.3f, -1.0f, 0.5f), - considerationsManager.Get() - .QuadraticCurve(context, 1.0f, 1.0f, 0.02f, 0.0f), + considerationsManager.Get() + .PresetCurve(context, PresetCurve.Distance), considerationsManager.Get() .QuadraticCurve(context, 1.0f, 0.4f, 0.0f, 0.0f), considerationsManager.Get() diff --git a/Content.Server/AI/Utility/Actions/Nutrition/Food/UseFoodInInventory.cs b/Content.Server/AI/Utility/Actions/Nutrition/Food/UseFoodInInventory.cs index 162d69c29b..6edcbb9c43 100644 --- a/Content.Server/AI/Utility/Actions/Nutrition/Food/UseFoodInInventory.cs +++ b/Content.Server/AI/Utility/Actions/Nutrition/Food/UseFoodInInventory.cs @@ -3,8 +3,7 @@ using System.Collections.Generic; using Content.Server.AI.Operators; using Content.Server.AI.Operators.Inventory; using Content.Server.AI.Utility.Considerations; -using Content.Server.AI.Utility.Considerations.Containers; -using Content.Server.AI.Utility.Considerations.Hands; +using Content.Server.AI.Utility.Considerations.Inventory; using Content.Server.AI.Utility.Considerations.Nutrition.Food; using Content.Server.AI.WorldState; using Content.Server.AI.WorldState.States; @@ -44,13 +43,10 @@ namespace Content.Server.AI.Utility.Actions.Nutrition.Food return new[] { - considerationsManager.Get() + considerationsManager.Get() .BoolCurve(context), - considerationsManager.Get() - .LogisticCurve(context, 1000f, 1.3f, -0.3f, 0.5f), considerationsManager.Get() .QuadraticCurve(context, 1.0f, 0.4f, 0.0f, 0.0f), - }; } } diff --git a/Content.Server/AI/Utility/Actions/UtilityAction.cs b/Content.Server/AI/Utility/Actions/UtilityAction.cs index 2453750532..f00ee01ddf 100644 --- a/Content.Server/AI/Utility/Actions/UtilityAction.cs +++ b/Content.Server/AI/Utility/Actions/UtilityAction.cs @@ -106,7 +106,6 @@ namespace Content.Server.AI.Utility.Actions /// This is where the magic happens /// /// - /// /// /// public float GetScore(Blackboard context, float min) diff --git a/Content.Server/AI/Utility/BehaviorSets/ThirstBehaviorSet.cs b/Content.Server/AI/Utility/BehaviorSets/ThirstBehaviorSet.cs index 7274d9034f..cc38d1babb 100644 --- a/Content.Server/AI/Utility/BehaviorSets/ThirstBehaviorSet.cs +++ b/Content.Server/AI/Utility/BehaviorSets/ThirstBehaviorSet.cs @@ -11,7 +11,7 @@ namespace Content.Server.AI.Utility.BehaviorSets Actions = new IAiUtility[] { new PickUpNearbyDrinkExp(), - new UseDrinkInHandsExp(), + new UseDrinkInInventoryExp(), }; } } diff --git a/Content.Server/AI/Utility/Considerations/Consideration.cs b/Content.Server/AI/Utility/Considerations/Consideration.cs index 4e49b58cb9..f2f0a9429d 100644 --- a/Content.Server/AI/Utility/Considerations/Consideration.cs +++ b/Content.Server/AI/Utility/Considerations/Consideration.cs @@ -1,6 +1,7 @@ using System; using Content.Server.AI.WorldState; using Content.Server.AI.WorldState.States.Utility; +using JetBrains.Annotations; namespace Content.Server.AI.Utility.Considerations { @@ -18,50 +19,114 @@ namespace Content.Server.AI.Utility.Considerations return Math.Clamp(adjustedScore, 0.0f, 1.0f); } + [Pure] + private static float BoolCurve(float x) + { + // ReSharper disable once CompareOfFloatsByEqualityOperator + return x == 1.0f ? 1.0f : 0.0f; + } + public Func BoolCurve(Blackboard context) { float Result() { var adjustedScore = GetAdjustedScore(context); - // ReSharper disable once CompareOfFloatsByEqualityOperator - return adjustedScore == 1.0f ? 1.0f : 0.0f; + return BoolCurve(adjustedScore); } return Result; } + [Pure] + private static float InverseBoolCurve(float x) + { + // ReSharper disable once CompareOfFloatsByEqualityOperator + return x == 1.0f ? 0.0f : 1.0f; + } + public Func InverseBoolCurve(Blackboard context) { float Result() { var adjustedScore = GetAdjustedScore(context); - // ReSharper disable once CompareOfFloatsByEqualityOperator - return adjustedScore == 1.0f ? 0.0f : 1.0f; + return InverseBoolCurve(adjustedScore); } return Result; } + [Pure] + private static float LogisticCurve(float x, float slope, float exponent, float yOffset, float xOffset) + { + return Math.Clamp( + exponent * (1 / (1 + (float) Math.Pow(Math.Log(1000) * slope, -1 * x + xOffset))) + yOffset, 0.0f, 1.0f); + } + public Func LogisticCurve(Blackboard context, float slope, float exponent, float yOffset, float xOffset) { float Result() { var adjustedScore = GetAdjustedScore(context); - return Math.Clamp(exponent * (1 / (1 + (float) Math.Pow(Math.Log(1000) * slope, -1 * adjustedScore + xOffset))) + yOffset, 0.0f, 1.0f); + return LogisticCurve(adjustedScore, slope, exponent, yOffset, xOffset); } return Result; } + [Pure] + private static float QuadraticCurve(float x, float slope, float exponent, float yOffset, float xOffset) + { + return Math.Clamp(slope * (float) Math.Pow(x - xOffset, exponent) + yOffset, 0.0f, 1.0f); + } + public Func QuadraticCurve(Blackboard context, float slope, float exponent, float yOffset, float xOffset) { float Result() { var adjustedScore = GetAdjustedScore(context); - return Math.Clamp(slope * (float) Math.Pow(adjustedScore - xOffset, exponent) + yOffset, 0.0f, 1.0f); + return QuadraticCurve(adjustedScore, slope, exponent, yOffset, xOffset); + } + + return Result; + } + + /// + /// For any curves that are re-used across actions so you only need to update it once. + /// + /// + /// + /// + /// + public Func PresetCurve(Blackboard context, PresetCurve preset) + { + float Result() + { + var adjustedScore = GetAdjustedScore(context); + + switch (preset) + { + case Considerations.PresetCurve.Distance: + return QuadraticCurve(adjustedScore, -1.0f, 1.0f, 1.0f, 0.02f); + case Considerations.PresetCurve.Nutrition: + return QuadraticCurve(adjustedScore, 2.0f, 1.0f, -1.0f, -0.2f); + case Considerations.PresetCurve.TargetHealth: + return QuadraticCurve(adjustedScore, 1.0f, 0.4f, 0.0f, -0.02f); + default: + throw new ArgumentOutOfRangeException(nameof(preset), preset, null); + } } return Result; } } + + /// + /// Preset response curves for considerations + /// + public enum PresetCurve + { + Distance, + Nutrition, + TargetHealth, + } } diff --git a/Content.Server/AI/Utility/Considerations/Hands/TargetInOurHandsCon.cs b/Content.Server/AI/Utility/Considerations/Hands/TargetInOurHandsCon.cs deleted file mode 100644 index 25df8fc548..0000000000 --- a/Content.Server/AI/Utility/Considerations/Hands/TargetInOurHandsCon.cs +++ /dev/null @@ -1,28 +0,0 @@ -using Content.Server.AI.WorldState; -using Content.Server.AI.WorldState.States; -using Content.Server.GameObjects.Components; -using Content.Server.GameObjects.Components.GUI; - -namespace Content.Server.AI.Utility.Considerations.Hands -{ - /// - /// Returns 1 if in our hands else 0 - /// - public sealed class TargetInOurHandsCon : Consideration - { - protected override float GetScore(Blackboard context) - { - var owner = context.GetState().GetValue(); - var target = context.GetState().GetValue(); - - if (target == null || - !target.HasComponent() || - !owner.TryGetComponent(out HandsComponent handsComponent)) - { - return 0.0f; - } - - return handsComponent.IsHolding(target) ? 1.0f : 0.0f; - } - } -} diff --git a/Content.Server/AI/Utility/Considerations/Inventory/CanPutTargetInHandsCon.cs b/Content.Server/AI/Utility/Considerations/Inventory/CanPutTargetInInventoryCon.cs similarity index 94% rename from Content.Server/AI/Utility/Considerations/Inventory/CanPutTargetInHandsCon.cs rename to Content.Server/AI/Utility/Considerations/Inventory/CanPutTargetInInventoryCon.cs index 7a75efe411..706054cb10 100644 --- a/Content.Server/AI/Utility/Considerations/Inventory/CanPutTargetInHandsCon.cs +++ b/Content.Server/AI/Utility/Considerations/Inventory/CanPutTargetInInventoryCon.cs @@ -6,7 +6,7 @@ using Content.Server.GameObjects.Components; namespace Content.Server.AI.Utility.Considerations.Inventory { - public class CanPutTargetInHandsCon : Consideration + public class CanPutTargetInInventoryCon : Consideration { protected override float GetScore(Blackboard context) { diff --git a/Content.Server/AI/Utility/Considerations/Inventory/TargetInOurInventoryCon.cs b/Content.Server/AI/Utility/Considerations/Inventory/TargetInOurInventoryCon.cs index 4d4e1b6970..100f111a7e 100644 --- a/Content.Server/AI/Utility/Considerations/Inventory/TargetInOurInventoryCon.cs +++ b/Content.Server/AI/Utility/Considerations/Inventory/TargetInOurInventoryCon.cs @@ -1,6 +1,7 @@ using Content.Server.AI.WorldState; using Content.Server.AI.WorldState.States; using Content.Server.AI.WorldState.States.Inventory; +using Content.Server.GameObjects; using Content.Server.GameObjects.Components; namespace Content.Server.AI.Utility.Considerations.Inventory diff --git a/Content.Server/AI/Utility/Considerations/Movement/DistanceCon.cs b/Content.Server/AI/Utility/Considerations/Movement/TargetDistanceCon.cs similarity index 68% rename from Content.Server/AI/Utility/Considerations/Movement/DistanceCon.cs rename to Content.Server/AI/Utility/Considerations/Movement/TargetDistanceCon.cs index 7b099bfcd0..ca63985179 100644 --- a/Content.Server/AI/Utility/Considerations/Movement/DistanceCon.cs +++ b/Content.Server/AI/Utility/Considerations/Movement/TargetDistanceCon.cs @@ -3,7 +3,7 @@ using Content.Server.AI.WorldState.States; namespace Content.Server.AI.Utility.Considerations.Movement { - public sealed class DistanceCon : Consideration + public sealed class TargetDistanceCon : Consideration { protected override float GetScore(Blackboard context) { @@ -14,8 +14,8 @@ namespace Content.Server.AI.Utility.Considerations.Movement return 0.0f; } - // Kind of just pulled a max distance out of nowhere. Add 0.01 just in case it's reaally far and we have no choice so it'll still be considered at least. - return (target.Transform.GridPosition.Position - self.Transform.GridPosition.Position).Length / 100 + 0.01f; + // Anything further than 100 tiles gets clamped + return (target.Transform.GridPosition.Position - self.Transform.GridPosition.Position).Length / 100; } } } diff --git a/Content.Server/AI/Utility/ExpandableActions/Clothing/Gloves/EquipAnyGlovesExp.cs b/Content.Server/AI/Utility/ExpandableActions/Clothing/Gloves/EquipAnyGlovesExp.cs index 4a8e10b0a6..a022113f1b 100644 --- a/Content.Server/AI/Utility/ExpandableActions/Clothing/Gloves/EquipAnyGlovesExp.cs +++ b/Content.Server/AI/Utility/ExpandableActions/Clothing/Gloves/EquipAnyGlovesExp.cs @@ -2,12 +2,14 @@ using System; using System.Collections.Generic; using Content.Server.AI.Utility.Actions; using Content.Server.AI.Utility.Actions.Clothing.Gloves; +using Content.Server.AI.Utility.Considerations; +using Content.Server.AI.Utility.Considerations.Clothing; using Content.Server.AI.WorldState; using Content.Server.AI.WorldState.States; using Content.Server.AI.WorldState.States.Inventory; using Content.Server.GameObjects; -using Content.Server.GameObjects.Components.Movement; using Content.Shared.GameObjects.Components.Inventory; +using Robust.Shared.IoC; namespace Content.Server.AI.Utility.ExpandableActions.Clothing.Gloves { @@ -18,6 +20,17 @@ namespace Content.Server.AI.Utility.ExpandableActions.Clothing.Gloves { public override float Bonus => UtilityAction.NormalBonus; + protected override IEnumerable> GetCommonConsiderations(Blackboard context) + { + var considerationsManager = IoCManager.Resolve(); + + return new [] + { + considerationsManager.Get().Slot(EquipmentSlotDefines.Slots.GLOVES, context) + .InverseBoolCurve(context), + }; + } + public override IEnumerable GetActions(Blackboard context) { var owner = context.GetState().GetValue(); diff --git a/Content.Server/AI/Utility/ExpandableActions/Clothing/Gloves/PickUpAnyNearbyGlovesExp.cs b/Content.Server/AI/Utility/ExpandableActions/Clothing/Gloves/PickUpAnyNearbyGlovesExp.cs index 7b3f165e4a..50d584aa69 100644 --- a/Content.Server/AI/Utility/ExpandableActions/Clothing/Gloves/PickUpAnyNearbyGlovesExp.cs +++ b/Content.Server/AI/Utility/ExpandableActions/Clothing/Gloves/PickUpAnyNearbyGlovesExp.cs @@ -1,11 +1,16 @@ +using System; using System.Collections.Generic; using Content.Server.AI.Utility.Actions; using Content.Server.AI.Utility.Actions.Clothing.Gloves; +using Content.Server.AI.Utility.Considerations; +using Content.Server.AI.Utility.Considerations.Clothing; +using Content.Server.AI.Utility.Considerations.Inventory; using Content.Server.AI.WorldState; using Content.Server.AI.WorldState.States; using Content.Server.AI.WorldState.States.Clothing; using Content.Server.GameObjects; using Content.Shared.GameObjects.Components.Inventory; +using Robust.Shared.IoC; namespace Content.Server.AI.Utility.ExpandableActions.Clothing.Gloves { @@ -13,9 +18,22 @@ namespace Content.Server.AI.Utility.ExpandableActions.Clothing.Gloves { public override float Bonus => UtilityAction.NormalBonus; + protected override IEnumerable> GetCommonConsiderations(Blackboard context) + { + var considerationsManager = IoCManager.Resolve(); + return new[] + { + considerationsManager.Get().Slot(EquipmentSlotDefines.Slots.GLOVES, context) + .InverseBoolCurve(context), + considerationsManager.Get().Slot(EquipmentSlotDefines.SlotFlags.GLOVES, context) + .InverseBoolCurve(context), + }; + } + public override IEnumerable GetActions(Blackboard context) { var owner = context.GetState().GetValue(); + foreach (var entity in context.GetState().GetValue()) { if (entity.TryGetComponent(out ClothingComponent clothing) && diff --git a/Content.Server/AI/Utility/ExpandableActions/Clothing/Head/EquipAnyHeadExp.cs b/Content.Server/AI/Utility/ExpandableActions/Clothing/Head/EquipAnyHeadExp.cs index 9164111d01..a98faf0804 100644 --- a/Content.Server/AI/Utility/ExpandableActions/Clothing/Head/EquipAnyHeadExp.cs +++ b/Content.Server/AI/Utility/ExpandableActions/Clothing/Head/EquipAnyHeadExp.cs @@ -1,11 +1,15 @@ +using System; using System.Collections.Generic; using Content.Server.AI.Utility.Actions; using Content.Server.AI.Utility.Actions.Clothing.Head; +using Content.Server.AI.Utility.Considerations; +using Content.Server.AI.Utility.Considerations.Clothing; using Content.Server.AI.WorldState; using Content.Server.AI.WorldState.States; using Content.Server.AI.WorldState.States.Inventory; using Content.Server.GameObjects; using Content.Shared.GameObjects.Components.Inventory; +using Robust.Shared.IoC; namespace Content.Server.AI.Utility.ExpandableActions.Clothing.Head { @@ -16,6 +20,16 @@ namespace Content.Server.AI.Utility.ExpandableActions.Clothing.Head { public override float Bonus => UtilityAction.NormalBonus; + protected override IEnumerable> GetCommonConsiderations(Blackboard context) + { + var considerationsManager = IoCManager.Resolve(); + + return new[] { + considerationsManager.Get().Slot(EquipmentSlotDefines.Slots.HEAD, context) + .InverseBoolCurve(context), + }; + } + public override IEnumerable GetActions(Blackboard context) { var owner = context.GetState().GetValue(); diff --git a/Content.Server/AI/Utility/ExpandableActions/Clothing/Head/PickUpAnyNearbyHeadExp.cs b/Content.Server/AI/Utility/ExpandableActions/Clothing/Head/PickUpAnyNearbyHeadExp.cs index 85806e99ee..f1e3d0e14f 100644 --- a/Content.Server/AI/Utility/ExpandableActions/Clothing/Head/PickUpAnyNearbyHeadExp.cs +++ b/Content.Server/AI/Utility/ExpandableActions/Clothing/Head/PickUpAnyNearbyHeadExp.cs @@ -2,12 +2,15 @@ using System; using System.Collections.Generic; using Content.Server.AI.Utility.Actions; using Content.Server.AI.Utility.Actions.Clothing.Head; +using Content.Server.AI.Utility.Considerations; +using Content.Server.AI.Utility.Considerations.Clothing; +using Content.Server.AI.Utility.Considerations.Inventory; using Content.Server.AI.WorldState; using Content.Server.AI.WorldState.States; using Content.Server.AI.WorldState.States.Clothing; using Content.Server.GameObjects; -using Content.Server.GameObjects.Components.Movement; using Content.Shared.GameObjects.Components.Inventory; +using Robust.Shared.IoC; namespace Content.Server.AI.Utility.ExpandableActions.Clothing.Head { @@ -15,6 +18,18 @@ namespace Content.Server.AI.Utility.ExpandableActions.Clothing.Head { public override float Bonus => UtilityAction.NormalBonus; + protected override IEnumerable> GetCommonConsiderations(Blackboard context) + { + var considerationsManager = IoCManager.Resolve(); + return new[] + { + considerationsManager.Get().Slot(EquipmentSlotDefines.Slots.HEAD, context) + .InverseBoolCurve(context), + considerationsManager.Get().Slot(EquipmentSlotDefines.SlotFlags.HEAD, context) + .InverseBoolCurve(context) + }; + } + public override IEnumerable GetActions(Blackboard context) { var owner = context.GetState().GetValue(); diff --git a/Content.Server/AI/Utility/ExpandableActions/Clothing/OuterClothing/EquipAnyOuterClothingExp.cs b/Content.Server/AI/Utility/ExpandableActions/Clothing/OuterClothing/EquipAnyOuterClothingExp.cs index 007b801d27..548a08f774 100644 --- a/Content.Server/AI/Utility/ExpandableActions/Clothing/OuterClothing/EquipAnyOuterClothingExp.cs +++ b/Content.Server/AI/Utility/ExpandableActions/Clothing/OuterClothing/EquipAnyOuterClothingExp.cs @@ -2,12 +2,14 @@ using System; using System.Collections.Generic; using Content.Server.AI.Utility.Actions; using Content.Server.AI.Utility.Actions.Clothing.OuterClothing; +using Content.Server.AI.Utility.Considerations; +using Content.Server.AI.Utility.Considerations.Clothing; using Content.Server.AI.WorldState; using Content.Server.AI.WorldState.States; using Content.Server.AI.WorldState.States.Inventory; using Content.Server.GameObjects; -using Content.Server.GameObjects.Components.Movement; using Content.Shared.GameObjects.Components.Inventory; +using Robust.Shared.IoC; namespace Content.Server.AI.Utility.ExpandableActions.Clothing.OuterClothing { @@ -18,6 +20,17 @@ namespace Content.Server.AI.Utility.ExpandableActions.Clothing.OuterClothing { public override float Bonus => UtilityAction.NormalBonus; + protected override IEnumerable> GetCommonConsiderations(Blackboard context) + { + var considerationsManager = IoCManager.Resolve(); + + return new[] + { + considerationsManager.Get().Slot(EquipmentSlotDefines.Slots.OUTERCLOTHING, context) + .InverseBoolCurve(context), + }; + } + public override IEnumerable GetActions(Blackboard context) { var owner = context.GetState().GetValue(); diff --git a/Content.Server/AI/Utility/ExpandableActions/Clothing/OuterClothing/PickUpAnyNearbyOuterClothingExp.cs b/Content.Server/AI/Utility/ExpandableActions/Clothing/OuterClothing/PickUpAnyNearbyOuterClothingExp.cs index dd1d06c0c7..29ec45a582 100644 --- a/Content.Server/AI/Utility/ExpandableActions/Clothing/OuterClothing/PickUpAnyNearbyOuterClothingExp.cs +++ b/Content.Server/AI/Utility/ExpandableActions/Clothing/OuterClothing/PickUpAnyNearbyOuterClothingExp.cs @@ -1,11 +1,16 @@ +using System; using System.Collections.Generic; using Content.Server.AI.Utility.Actions; using Content.Server.AI.Utility.Actions.Clothing.OuterClothing; +using Content.Server.AI.Utility.Considerations; +using Content.Server.AI.Utility.Considerations.Clothing; +using Content.Server.AI.Utility.Considerations.Inventory; using Content.Server.AI.WorldState; using Content.Server.AI.WorldState.States; using Content.Server.AI.WorldState.States.Clothing; using Content.Server.GameObjects; using Content.Shared.GameObjects.Components.Inventory; +using Robust.Shared.IoC; namespace Content.Server.AI.Utility.ExpandableActions.Clothing.OuterClothing { @@ -13,6 +18,19 @@ namespace Content.Server.AI.Utility.ExpandableActions.Clothing.OuterClothing { public override float Bonus => UtilityAction.NormalBonus; + protected override IEnumerable> GetCommonConsiderations(Blackboard context) + { + var considerationsManager = IoCManager.Resolve(); + + return new[] + { + considerationsManager.Get().Slot(EquipmentSlotDefines.Slots.OUTERCLOTHING, context) + .InverseBoolCurve(context), + considerationsManager.Get().Slot(EquipmentSlotDefines.SlotFlags.OUTERCLOTHING, context) + .InverseBoolCurve(context) + }; + } + public override IEnumerable GetActions(Blackboard context) { var owner = context.GetState().GetValue(); diff --git a/Content.Server/AI/Utility/ExpandableActions/Clothing/Shoes/EquipAnyShoesExp.cs b/Content.Server/AI/Utility/ExpandableActions/Clothing/Shoes/EquipAnyShoesExp.cs index f750fba71a..f02f7abe0f 100644 --- a/Content.Server/AI/Utility/ExpandableActions/Clothing/Shoes/EquipAnyShoesExp.cs +++ b/Content.Server/AI/Utility/ExpandableActions/Clothing/Shoes/EquipAnyShoesExp.cs @@ -2,12 +2,14 @@ using System; using System.Collections.Generic; using Content.Server.AI.Utility.Actions; using Content.Server.AI.Utility.Actions.Clothing.Shoes; +using Content.Server.AI.Utility.Considerations; +using Content.Server.AI.Utility.Considerations.Clothing; using Content.Server.AI.WorldState; using Content.Server.AI.WorldState.States; using Content.Server.AI.WorldState.States.Inventory; using Content.Server.GameObjects; -using Content.Server.GameObjects.Components.Movement; using Content.Shared.GameObjects.Components.Inventory; +using Robust.Shared.IoC; namespace Content.Server.AI.Utility.ExpandableActions.Clothing.Shoes { @@ -18,6 +20,17 @@ namespace Content.Server.AI.Utility.ExpandableActions.Clothing.Shoes { public override float Bonus => UtilityAction.NormalBonus; + protected override IEnumerable> GetCommonConsiderations(Blackboard context) + { + var considerationsManager = IoCManager.Resolve(); + + return new[] + { + considerationsManager.Get().Slot(EquipmentSlotDefines.Slots.SHOES, context) + .InverseBoolCurve(context), + }; + } + public override IEnumerable GetActions(Blackboard context) { var owner = context.GetState().GetValue(); diff --git a/Content.Server/AI/Utility/ExpandableActions/Clothing/Shoes/PickUpAnyNearbyShoesExp.cs b/Content.Server/AI/Utility/ExpandableActions/Clothing/Shoes/PickUpAnyNearbyShoesExp.cs index 598d180808..8a1fa9429e 100644 --- a/Content.Server/AI/Utility/ExpandableActions/Clothing/Shoes/PickUpAnyNearbyShoesExp.cs +++ b/Content.Server/AI/Utility/ExpandableActions/Clothing/Shoes/PickUpAnyNearbyShoesExp.cs @@ -1,11 +1,16 @@ +using System; using System.Collections.Generic; using Content.Server.AI.Utility.Actions; using Content.Server.AI.Utility.Actions.Clothing.Shoes; +using Content.Server.AI.Utility.Considerations; +using Content.Server.AI.Utility.Considerations.Clothing; +using Content.Server.AI.Utility.Considerations.Inventory; using Content.Server.AI.WorldState; using Content.Server.AI.WorldState.States; using Content.Server.AI.WorldState.States.Clothing; using Content.Server.GameObjects; using Content.Shared.GameObjects.Components.Inventory; +using Robust.Shared.IoC; namespace Content.Server.AI.Utility.ExpandableActions.Clothing.Shoes { @@ -13,6 +18,19 @@ namespace Content.Server.AI.Utility.ExpandableActions.Clothing.Shoes { public override float Bonus => UtilityAction.NormalBonus; + protected override IEnumerable> GetCommonConsiderations(Blackboard context) + { + var considerationsManager = IoCManager.Resolve(); + + return new[] + { + considerationsManager.Get().Slot(EquipmentSlotDefines.Slots.SHOES, context) + .InverseBoolCurve(context), + considerationsManager.Get().Slot(EquipmentSlotDefines.SlotFlags.SHOES, context) + .InverseBoolCurve(context) + }; + } + public override IEnumerable GetActions(Blackboard context) { var owner = context.GetState().GetValue(); diff --git a/Content.Server/AI/Utility/ExpandableActions/Combat/Melee/EquipMeleeExp.cs b/Content.Server/AI/Utility/ExpandableActions/Combat/Melee/EquipMeleeExp.cs index d0aade8647..1d993bec7b 100644 --- a/Content.Server/AI/Utility/ExpandableActions/Combat/Melee/EquipMeleeExp.cs +++ b/Content.Server/AI/Utility/ExpandableActions/Combat/Melee/EquipMeleeExp.cs @@ -1,10 +1,15 @@ +using System; using System.Collections.Generic; using Content.Server.AI.Utility.Actions; using Content.Server.AI.Utility.Actions.Combat.Melee; +using Content.Server.AI.Utility.Considerations; +using Content.Server.AI.Utility.Considerations.Combat.Melee; +using Content.Server.AI.Utility.Considerations.Inventory; using Content.Server.AI.WorldState; using Content.Server.AI.WorldState.States; using Content.Server.AI.WorldState.States.Inventory; using Content.Server.GameObjects.Components.Weapon.Melee; +using Robust.Shared.IoC; namespace Content.Server.AI.Utility.ExpandableActions.Combat.Melee { @@ -12,6 +17,17 @@ namespace Content.Server.AI.Utility.ExpandableActions.Combat.Melee { public override float Bonus => UtilityAction.CombatPrepBonus; + protected override IEnumerable> GetCommonConsiderations(Blackboard context) + { + var considerationsManager = IoCManager.Resolve(); + + return new[] + { + considerationsManager.Get() + .InverseBoolCurve(context), + }; + } + public override IEnumerable GetActions(Blackboard context) { var owner = context.GetState().GetValue(); diff --git a/Content.Server/AI/Utility/ExpandableActions/Combat/Melee/MeleeAttackNearbyPlayerExp.cs b/Content.Server/AI/Utility/ExpandableActions/Combat/Melee/MeleeAttackNearbyPlayerExp.cs index adab7f24cd..a1ee5543bf 100644 --- a/Content.Server/AI/Utility/ExpandableActions/Combat/Melee/MeleeAttackNearbyPlayerExp.cs +++ b/Content.Server/AI/Utility/ExpandableActions/Combat/Melee/MeleeAttackNearbyPlayerExp.cs @@ -2,12 +2,15 @@ using System; using System.Collections.Generic; using Content.Server.AI.Utility.Actions; using Content.Server.AI.Utility.Actions.Combat.Melee; +using Content.Server.AI.Utility.Considerations; +using Content.Server.AI.Utility.Considerations.Combat.Melee; using Content.Server.AI.Utils; using Content.Server.AI.WorldState; using Content.Server.AI.WorldState.States; using Content.Server.GameObjects; using Content.Server.GameObjects.Components.Movement; using Robust.Server.GameObjects; +using Robust.Shared.IoC; namespace Content.Server.AI.Utility.ExpandableActions.Combat.Melee { @@ -15,6 +18,17 @@ namespace Content.Server.AI.Utility.ExpandableActions.Combat.Melee { public override float Bonus => UtilityAction.CombatBonus; + protected override IEnumerable> GetCommonConsiderations(Blackboard context) + { + var considerationsManager = IoCManager.Resolve(); + + return new[] + { + considerationsManager.Get() + .BoolCurve(context), + }; + } + public override IEnumerable GetActions(Blackboard context) { var owner = context.GetState().GetValue(); diff --git a/Content.Server/AI/Utility/ExpandableActions/Combat/Melee/MeleeAttackNearbySpeciesExp.cs b/Content.Server/AI/Utility/ExpandableActions/Combat/Melee/MeleeAttackNearbySpeciesExp.cs index 617252184e..b78bb2812c 100644 --- a/Content.Server/AI/Utility/ExpandableActions/Combat/Melee/MeleeAttackNearbySpeciesExp.cs +++ b/Content.Server/AI/Utility/ExpandableActions/Combat/Melee/MeleeAttackNearbySpeciesExp.cs @@ -1,9 +1,11 @@ +using System; using System.Collections.Generic; using Content.Server.AI.Utility.Actions; using Content.Server.AI.Utility.Actions.Combat.Melee; using Content.Server.AI.WorldState; using Content.Server.AI.WorldState.States; using Content.Server.AI.WorldState.States.Mobs; +using Content.Server.GameObjects.Components.Movement; namespace Content.Server.AI.Utility.ExpandableActions.Combat.Melee { @@ -14,6 +16,7 @@ namespace Content.Server.AI.Utility.ExpandableActions.Combat.Melee public override IEnumerable GetActions(Blackboard context) { var owner = context.GetState().GetValue(); + foreach (var entity in context.GetState().GetValue()) { yield return new MeleeWeaponAttackEntity(owner, entity, Bonus); diff --git a/Content.Server/AI/Utility/ExpandableActions/Combat/Melee/PickUpMeleeWeaponExp.cs b/Content.Server/AI/Utility/ExpandableActions/Combat/Melee/PickUpMeleeWeaponExp.cs index 781a72c2a1..c91e0b065b 100644 --- a/Content.Server/AI/Utility/ExpandableActions/Combat/Melee/PickUpMeleeWeaponExp.cs +++ b/Content.Server/AI/Utility/ExpandableActions/Combat/Melee/PickUpMeleeWeaponExp.cs @@ -1,9 +1,14 @@ +using System; using System.Collections.Generic; using Content.Server.AI.Utility.Actions; using Content.Server.AI.Utility.Actions.Combat.Melee; +using Content.Server.AI.Utility.Considerations; +using Content.Server.AI.Utility.Considerations.Combat.Melee; +using Content.Server.AI.Utility.Considerations.Hands; using Content.Server.AI.WorldState; using Content.Server.AI.WorldState.States; using Content.Server.AI.WorldState.States.Combat.Nearby; +using Robust.Shared.IoC; namespace Content.Server.AI.Utility.ExpandableActions.Combat.Melee { @@ -11,6 +16,19 @@ namespace Content.Server.AI.Utility.ExpandableActions.Combat.Melee { public override float Bonus => UtilityAction.CombatPrepBonus; + protected override IEnumerable> GetCommonConsiderations(Blackboard context) + { + var considerationsManager = IoCManager.Resolve(); + + return new[] + { + considerationsManager.Get() + .BoolCurve(context), + considerationsManager.Get() + .InverseBoolCurve(context), + }; + } + public override IEnumerable GetActions(Blackboard context) { var owner = context.GetState().GetValue(); diff --git a/Content.Server/AI/Utility/ExpandableActions/Combat/Melee/UnarmedAttackNearbyPlayerExp.cs b/Content.Server/AI/Utility/ExpandableActions/Combat/Melee/UnarmedAttackNearbyPlayerExp.cs index e168116431..0fc6d162b7 100644 --- a/Content.Server/AI/Utility/ExpandableActions/Combat/Melee/UnarmedAttackNearbyPlayerExp.cs +++ b/Content.Server/AI/Utility/ExpandableActions/Combat/Melee/UnarmedAttackNearbyPlayerExp.cs @@ -2,12 +2,15 @@ using System; using System.Collections.Generic; using Content.Server.AI.Utility.Actions; using Content.Server.AI.Utility.Actions.Combat.Melee; +using Content.Server.AI.Utility.Considerations; +using Content.Server.AI.Utility.Considerations.Combat.Melee; using Content.Server.AI.Utils; using Content.Server.AI.WorldState; using Content.Server.AI.WorldState.States; using Content.Server.GameObjects; using Content.Server.GameObjects.Components.Movement; using Robust.Server.GameObjects; +using Robust.Shared.IoC; namespace Content.Server.AI.Utility.ExpandableActions.Combat.Melee { @@ -15,6 +18,17 @@ namespace Content.Server.AI.Utility.ExpandableActions.Combat.Melee { public override float Bonus => UtilityAction.CombatBonus; + protected override IEnumerable> GetCommonConsiderations(Blackboard context) + { + var considerationsManager = IoCManager.Resolve(); + + return new[] + { + considerationsManager.Get() + .BoolCurve(context), + }; + } + public override IEnumerable GetActions(Blackboard context) { var owner = context.GetState().GetValue(); diff --git a/Content.Server/AI/Utility/ExpandableActions/ExpandableUtilityAction.cs b/Content.Server/AI/Utility/ExpandableActions/ExpandableUtilityAction.cs index 619fc36139..d8f291c9f8 100644 --- a/Content.Server/AI/Utility/ExpandableActions/ExpandableUtilityAction.cs +++ b/Content.Server/AI/Utility/ExpandableActions/ExpandableUtilityAction.cs @@ -1,3 +1,4 @@ +using System; using System.Collections.Generic; using Content.Server.AI.Utility.Actions; using Content.Server.AI.WorldState; @@ -12,6 +13,37 @@ namespace Content.Server.AI.Utility.ExpandableActions { public abstract float Bonus { get; } + /// + /// No point expanding nodes if none of them can ever be valid. + /// Fails if any of the common considerations is 0.0f (i.e. invalid) + /// + /// + /// + public bool IsValid(Blackboard context) + { + foreach (var con in GetCommonConsiderations(context)) + { + // ReSharper disable once CompareOfFloatsByEqualityOperator + if (con.Invoke() == 0.0f) return false; + } + + return true; + } + + /// + /// Called by IsValid to try and early-out the expandable action. + /// No point going through all nearby clothes if we can't fit it in a slot. + /// + /// Similar to HTN's compound tasks where they can have overall conditions that have to be met before the actions are considered. + /// Ideally any binary early-outs that are common to all expanded actions would be checked once, e.g. a boolean free hand check + /// Use this if you want to optimise the expandable further. + /// + /// + protected virtual IEnumerable> GetCommonConsiderations(Blackboard context) + { + yield break; + } + // e.g. you may have a "PickupFood" action for all nearby food sources if you have the "Hungry" BehaviorSet. public abstract IEnumerable GetActions(Blackboard context); } diff --git a/Content.Server/AI/Utility/ExpandableActions/Nutrition/PickUpNearbyDrinkExp.cs b/Content.Server/AI/Utility/ExpandableActions/Nutrition/PickUpNearbyDrinkExp.cs index 87f735b7f8..c2558bcbc7 100644 --- a/Content.Server/AI/Utility/ExpandableActions/Nutrition/PickUpNearbyDrinkExp.cs +++ b/Content.Server/AI/Utility/ExpandableActions/Nutrition/PickUpNearbyDrinkExp.cs @@ -1,9 +1,14 @@ +using System; using System.Collections.Generic; using Content.Server.AI.Utility.Actions; using Content.Server.AI.Utility.Actions.Nutrition.Drink; +using Content.Server.AI.Utility.Considerations; +using Content.Server.AI.Utility.Considerations.Hands; +using Content.Server.AI.Utility.Considerations.Nutrition.Drink; using Content.Server.AI.WorldState; using Content.Server.AI.WorldState.States; using Content.Server.AI.WorldState.States.Nutrition; +using Robust.Shared.IoC; namespace Content.Server.AI.Utility.ExpandableActions.Nutrition { @@ -11,6 +16,16 @@ namespace Content.Server.AI.Utility.ExpandableActions.Nutrition { public override float Bonus => UtilityAction.NeedsBonus; + protected override IEnumerable> GetCommonConsiderations(Blackboard context) + { + var considerationsManager = IoCManager.Resolve(); + return new[] + { + considerationsManager.Get().PresetCurve(context, PresetCurve.Nutrition), + considerationsManager.Get().BoolCurve(context), + }; + } + public override IEnumerable GetActions(Blackboard context) { var owner = context.GetState().GetValue(); diff --git a/Content.Server/AI/Utility/ExpandableActions/Nutrition/PickUpNearbyFoodExp.cs b/Content.Server/AI/Utility/ExpandableActions/Nutrition/PickUpNearbyFoodExp.cs index 01affba951..e3a3409aea 100644 --- a/Content.Server/AI/Utility/ExpandableActions/Nutrition/PickUpNearbyFoodExp.cs +++ b/Content.Server/AI/Utility/ExpandableActions/Nutrition/PickUpNearbyFoodExp.cs @@ -1,9 +1,14 @@ +using System; using System.Collections.Generic; using Content.Server.AI.Utility.Actions; using Content.Server.AI.Utility.Actions.Nutrition.Food; +using Content.Server.AI.Utility.Considerations; +using Content.Server.AI.Utility.Considerations.Hands; +using Content.Server.AI.Utility.Considerations.Nutrition.Food; using Content.Server.AI.WorldState; using Content.Server.AI.WorldState.States; using Content.Server.AI.WorldState.States.Nutrition; +using Robust.Shared.IoC; namespace Content.Server.AI.Utility.ExpandableActions.Nutrition { @@ -11,6 +16,16 @@ namespace Content.Server.AI.Utility.ExpandableActions.Nutrition { public override float Bonus => UtilityAction.NeedsBonus; + protected override IEnumerable> GetCommonConsiderations(Blackboard context) + { + var considerationsManager = IoCManager.Resolve(); + return new[] + { + considerationsManager.Get().PresetCurve(context, PresetCurve.Nutrition), + considerationsManager.Get().BoolCurve(context), + }; + } + public override IEnumerable GetActions(Blackboard context) { var owner = context.GetState().GetValue(); diff --git a/Content.Server/AI/Utility/ExpandableActions/Nutrition/UseDrinkInHandsExp.cs b/Content.Server/AI/Utility/ExpandableActions/Nutrition/UseDrinkInInventoryExp.cs similarity index 62% rename from Content.Server/AI/Utility/ExpandableActions/Nutrition/UseDrinkInHandsExp.cs rename to Content.Server/AI/Utility/ExpandableActions/Nutrition/UseDrinkInInventoryExp.cs index fac523cd96..06574721c6 100644 --- a/Content.Server/AI/Utility/ExpandableActions/Nutrition/UseDrinkInHandsExp.cs +++ b/Content.Server/AI/Utility/ExpandableActions/Nutrition/UseDrinkInInventoryExp.cs @@ -1,16 +1,29 @@ +using System; using System.Collections.Generic; using Content.Server.AI.Utility.Actions; using Content.Server.AI.Utility.Actions.Nutrition.Drink; +using Content.Server.AI.Utility.Considerations; +using Content.Server.AI.Utility.Considerations.Nutrition.Drink; using Content.Server.AI.WorldState; using Content.Server.AI.WorldState.States; using Content.Server.AI.WorldState.States.Inventory; using Content.Server.GameObjects.Components.Nutrition; +using Robust.Shared.IoC; namespace Content.Server.AI.Utility.ExpandableActions.Nutrition { - public sealed class UseDrinkInHandsExp : ExpandableUtilityAction + public sealed class UseDrinkInInventoryExp : ExpandableUtilityAction { public override float Bonus => UtilityAction.NeedsBonus; + + protected override IEnumerable> GetCommonConsiderations(Blackboard context) + { + var considerationsManager = IoCManager.Resolve(); + return new[] + { + considerationsManager.Get().PresetCurve(context, PresetCurve.Nutrition) + }; + } public override IEnumerable GetActions(Blackboard context) { diff --git a/Content.Server/AI/Utility/ExpandableActions/Nutrition/UseFoodInInventoryExp.cs b/Content.Server/AI/Utility/ExpandableActions/Nutrition/UseFoodInInventoryExp.cs index 2df0385f6f..1f919b56a3 100644 --- a/Content.Server/AI/Utility/ExpandableActions/Nutrition/UseFoodInInventoryExp.cs +++ b/Content.Server/AI/Utility/ExpandableActions/Nutrition/UseFoodInInventoryExp.cs @@ -1,10 +1,14 @@ +using System; using System.Collections.Generic; using Content.Server.AI.Utility.Actions; using Content.Server.AI.Utility.Actions.Nutrition.Food; +using Content.Server.AI.Utility.Considerations; +using Content.Server.AI.Utility.Considerations.Nutrition.Food; using Content.Server.AI.WorldState; using Content.Server.AI.WorldState.States; using Content.Server.AI.WorldState.States.Inventory; using Content.Server.GameObjects.Components.Nutrition; +using Robust.Shared.IoC; namespace Content.Server.AI.Utility.ExpandableActions.Nutrition { @@ -12,6 +16,15 @@ namespace Content.Server.AI.Utility.ExpandableActions.Nutrition { public override float Bonus => UtilityAction.NeedsBonus; + protected override IEnumerable> GetCommonConsiderations(Blackboard context) + { + var considerationsManager = IoCManager.Resolve(); + return new[] + { + considerationsManager.Get().PresetCurve(context, PresetCurve.Nutrition) + }; + } + public override IEnumerable GetActions(Blackboard context) { var owner = context.GetState().GetValue(); diff --git a/Content.Server/GameObjects/EntitySystems/AI/LoadBalancer/AiActionRequestJob.cs b/Content.Server/GameObjects/EntitySystems/AI/LoadBalancer/AiActionRequestJob.cs index bd4041bf76..fda623d6e6 100644 --- a/Content.Server/GameObjects/EntitySystems/AI/LoadBalancer/AiActionRequestJob.cs +++ b/Content.Server/GameObjects/EntitySystems/AI/LoadBalancer/AiActionRequestJob.cs @@ -79,6 +79,11 @@ namespace Content.Server.GameObjects.EntitySystems.AI.LoadBalancer switch (action) { case ExpandableUtilityAction expandableUtilityAction: + if (!expandableUtilityAction.IsValid(_request.Context)) + { + break; + } + foreach (var expanded in expandableUtilityAction.GetActions(_request.Context)) { actions.Push(expanded); @@ -86,7 +91,7 @@ namespace Content.Server.GameObjects.EntitySystems.AI.LoadBalancer break; case UtilityAction utilityAction: consideredTaskCount++; - var bonus = (float) utilityAction.Bonus; + var bonus = utilityAction.Bonus; if (bonus < cutoff) { From 6fe95d635da1a557a5ddb0c80d14aad7e5725d09 Mon Sep 17 00:00:00 2001 From: DrSmugleaf Date: Tue, 11 Aug 2020 22:03:10 +0200 Subject: [PATCH 7/9] Fix thrown items not going over tables (#1652) --- Resources/Prototypes/Entities/Constructible/Ground/table.yml | 1 - 1 file changed, 1 deletion(-) diff --git a/Resources/Prototypes/Entities/Constructible/Ground/table.yml b/Resources/Prototypes/Entities/Constructible/Ground/table.yml index 6c0c97e2af..ed324df1d3 100644 --- a/Resources/Prototypes/Entities/Constructible/Ground/table.yml +++ b/Resources/Prototypes/Entities/Constructible/Ground/table.yml @@ -17,7 +17,6 @@ - !type:PhysShapeAabb layer: - SmallImpassable - - MobImpassable - type: SnapGrid offset: Center - type: IconSmooth From 32e4c24342e8fb7dcfeba134ac42af3069e8cbfb Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?V=C3=ADctor=20Aguilera=20Puerto?= Date: Tue, 11 Aug 2020 22:34:37 +0200 Subject: [PATCH 8/9] Adds atmos helpers, welding tool now lights up fires --- Content.Server/Atmos/AtmosHelpers.cs | 25 +++++++++++++++++++ .../Interactable/WelderComponent.cs | 7 ++++++ 2 files changed, 32 insertions(+) create mode 100644 Content.Server/Atmos/AtmosHelpers.cs diff --git a/Content.Server/Atmos/AtmosHelpers.cs b/Content.Server/Atmos/AtmosHelpers.cs new file mode 100644 index 0000000000..4a4eb37d0c --- /dev/null +++ b/Content.Server/Atmos/AtmosHelpers.cs @@ -0,0 +1,25 @@ +using Content.Server.GameObjects.EntitySystems; +using Robust.Shared.GameObjects.Systems; +using Robust.Shared.Map; + +#nullable enable + +namespace Content.Server.Atmos +{ + public static class AtmosHelpers + { + public static TileAtmosphere? GetTileAtmosphere(this GridCoordinates coordinates) + { + var gridAtmos = EntitySystem.Get().GetGridAtmosphere(coordinates.GridID); + + return gridAtmos?.GetTile(coordinates); + } + + public static TileAtmosphere? GetTileAtmosphere(this MapIndices indices, GridId gridId) + { + var gridAtmos = EntitySystem.Get().GetGridAtmosphere(gridId); + + return gridAtmos?.GetTile(indices); + } + } +} diff --git a/Content.Server/GameObjects/Components/Interactable/WelderComponent.cs b/Content.Server/GameObjects/Components/Interactable/WelderComponent.cs index 46e13cd038..fdaa204f91 100644 --- a/Content.Server/GameObjects/Components/Interactable/WelderComponent.cs +++ b/Content.Server/GameObjects/Components/Interactable/WelderComponent.cs @@ -1,6 +1,8 @@ #nullable enable using System; +using Content.Server.Atmos; using Content.Server.GameObjects.Components.Chemistry; +using Content.Server.GameObjects.EntitySystems; using Content.Server.GameObjects.EntitySystems.Click; using Content.Server.Interfaces.GameObjects.Components.Interaction; using Content.Server.Interfaces; @@ -19,6 +21,7 @@ using Robust.Shared.Utility; using Robust.Shared.ViewVariables; using Robust.Shared.Serialization; using Content.Shared.GameObjects.EntitySystems; +using Robust.Shared.GameObjects.Systems; namespace Content.Server.GameObjects.Components.Interactable { @@ -179,6 +182,10 @@ namespace Content.Server.GameObjects.Components.Interactable PlaySoundCollection("WelderOn", -5); _welderSystem.Subscribe(this); + + Owner.Transform.GridPosition + .GetTileAtmosphere()?.HotspotExpose(700f, 50f, true); + return true; } From cdc6ec3bfcc05cd5c2c008a3c17d7d90a13a0a6f Mon Sep 17 00:00:00 2001 From: Acruid Date: Tue, 11 Aug 2020 16:44:15 -0700 Subject: [PATCH 9/9] Ranged weapon firing does not depend on DefaultGrid anymore. --- .../Ranged/ClientRangedWeaponComponent.cs | 9 ++--- .../EntitySystems/RangedWeaponSystem.cs | 11 ++++-- .../Barrels/ServerRangedBarrelComponent.cs | 18 ++++++---- .../Ranged/ServerRangedWeaponComponent.cs | 35 ++++++++++++++++--- .../Ranged/SharedRangedWeaponComponent.cs | 28 ++++++++++++--- 5 files changed, 78 insertions(+), 23 deletions(-) diff --git a/Content.Client/GameObjects/Components/Weapons/Ranged/ClientRangedWeaponComponent.cs b/Content.Client/GameObjects/Components/Weapons/Ranged/ClientRangedWeaponComponent.cs index e37f6360b6..9bb8bc1050 100644 --- a/Content.Client/GameObjects/Components/Weapons/Ranged/ClientRangedWeaponComponent.cs +++ b/Content.Client/GameObjects/Components/Weapons/Ranged/ClientRangedWeaponComponent.cs @@ -1,6 +1,7 @@ -using Content.Shared.GameObjects.Components.Weapons.Ranged; +using Content.Shared.GameObjects.Components.Weapons.Ranged; using Robust.Shared.GameObjects; using Robust.Shared.Map; +using Robust.Shared.Maths; namespace Content.Client.GameObjects.Components.Weapons.Ranged { @@ -30,9 +31,9 @@ namespace Content.Client.GameObjects.Components.Weapons.Ranged FireRateSelector = rangedState.FireRateSelector; } - public void SyncFirePos(GridCoordinates worldPos) + public void SyncFirePos(GridId targetGrid, Vector2 targetPosition) { - SendNetworkMessage(new FirePosComponentMessage(worldPos)); + SendNetworkMessage(new FirePosComponentMessage(targetGrid, targetPosition)); } } -} \ No newline at end of file +} diff --git a/Content.Client/GameObjects/EntitySystems/RangedWeaponSystem.cs b/Content.Client/GameObjects/EntitySystems/RangedWeaponSystem.cs index ed3537fae7..027f6c6014 100644 --- a/Content.Client/GameObjects/EntitySystems/RangedWeaponSystem.cs +++ b/Content.Client/GameObjects/EntitySystems/RangedWeaponSystem.cs @@ -11,6 +11,7 @@ using Robust.Shared.Input; using Robust.Shared.Interfaces.Map; using Robust.Shared.Interfaces.Timing; using Robust.Shared.IoC; +using Robust.Shared.Map; namespace Content.Client.GameObjects.EntitySystems { @@ -96,9 +97,13 @@ namespace Content.Client.GameObjects.EntitySystems var worldPos = _eyeManager.ScreenToMap(_inputManager.MouseScreenPosition); if (!_mapManager.TryFindGridAt(worldPos, out var grid)) - grid = _mapManager.GetDefaultGrid(worldPos.MapId); - - weapon.SyncFirePos(grid.MapToGrid(worldPos)); + { + weapon.SyncFirePos(GridId.Invalid, worldPos.Position); + } + else + { + weapon.SyncFirePos(grid.Index, grid.MapToGrid(worldPos).Position); + } } } } diff --git a/Content.Server/GameObjects/Components/Weapon/Ranged/Barrels/ServerRangedBarrelComponent.cs b/Content.Server/GameObjects/Components/Weapon/Ranged/Barrels/ServerRangedBarrelComponent.cs index ff8cc75244..ce2349aea0 100644 --- a/Content.Server/GameObjects/Components/Weapon/Ranged/Barrels/ServerRangedBarrelComponent.cs +++ b/Content.Server/GameObjects/Components/Weapon/Ranged/Barrels/ServerRangedBarrelComponent.cs @@ -159,10 +159,10 @@ namespace Content.Server.GameObjects.Components.Weapon.Ranged.Barrels public override void OnAdd() { base.OnAdd(); - var rangedWeapon = Owner.GetComponent(); - rangedWeapon.Barrel = this; - rangedWeapon.FireHandler += Fire; - rangedWeapon.WeaponCanFireHandler += WeaponCanFire; + var rangedWeaponComponent = Owner.GetComponent(); + rangedWeaponComponent.Barrel = this; + rangedWeaponComponent.FireHandler += Fire; + rangedWeaponComponent.WeaponCanFireHandler += WeaponCanFire; } public override void OnRemove() @@ -208,7 +208,12 @@ namespace Content.Server.GameObjects.Components.Weapon.Ranged.Barrels return true; } - private void Fire(IEntity shooter, GridCoordinates target) + /// + /// Fires a round of ammo out of the weapon. + /// + /// Entity that is operating the weapon, usually the player. + /// Target position on the map to shoot at. + private void Fire(IEntity shooter, Vector2 targetPos) { var soundSystem = EntitySystem.Get(); if (ShotsLeft == 0) @@ -229,8 +234,7 @@ namespace Content.Server.GameObjects.Components.Weapon.Ranged.Barrels } // At this point firing is confirmed - var worldPosition = IoCManager.Resolve().GetGrid(target.GridID).LocalToWorld(target).Position; - var direction = (worldPosition - shooter.Transform.WorldPosition).ToAngle(); + var direction = (targetPos - shooter.Transform.WorldPosition).ToAngle(); var angle = GetRecoilAngle(direction); // This should really be client-side but for now we'll just leave it here if (shooter.TryGetComponent(out CameraRecoilComponent recoilComponent)) diff --git a/Content.Server/GameObjects/Components/Weapon/Ranged/ServerRangedWeaponComponent.cs b/Content.Server/GameObjects/Components/Weapon/Ranged/ServerRangedWeaponComponent.cs index 577549fa50..a2e0ea57c4 100644 --- a/Content.Server/GameObjects/Components/Weapon/Ranged/ServerRangedWeaponComponent.cs +++ b/Content.Server/GameObjects/Components/Weapon/Ranged/ServerRangedWeaponComponent.cs @@ -1,4 +1,4 @@ -using System; +using System; using Content.Server.GameObjects.Components.GUI; using Content.Server.GameObjects.Components.Mobs; using Content.Server.GameObjects.Components.Weapon.Ranged.Barrels; @@ -12,6 +12,7 @@ using Robust.Shared.Audio; using Robust.Shared.GameObjects; using Robust.Shared.GameObjects.Systems; using Robust.Shared.Interfaces.GameObjects; +using Robust.Shared.Interfaces.Map; using Robust.Shared.Interfaces.Network; using Robust.Shared.Interfaces.Random; using Robust.Shared.Interfaces.Timing; @@ -19,6 +20,7 @@ using Robust.Shared.IoC; using Robust.Shared.Localization; using Robust.Shared.Log; using Robust.Shared.Map; +using Robust.Shared.Maths; using Robust.Shared.Players; using Robust.Shared.Random; using Robust.Shared.Serialization; @@ -38,7 +40,7 @@ namespace Content.Server.GameObjects.Components.Weapon.Ranged public Func WeaponCanFireHandler; public Func UserCanFireHandler; - public Action FireHandler; + public Action FireHandler; public ServerRangedBarrelComponent Barrel { @@ -77,6 +79,7 @@ namespace Content.Server.GameObjects.Components.Weapon.Ranged serializer.DataField(this, p => p.ClumsyExplodeChance, "clumsyExplodeChance", 0.5f); } + /// public override void HandleNetworkMessage(ComponentMessage message, INetChannel channel, ICommonSession session = null) { base.HandleNetworkMessage(message, channel, session); @@ -95,7 +98,24 @@ namespace Content.Server.GameObjects.Components.Weapon.Ranged return; } - _tryFire(user, msg.Target); + if (msg.TargetGrid != GridId.Invalid) + { + // grid pos + if (!IoCManager.Resolve().TryGetGrid(msg.TargetGrid, out var grid)) + { + // Client sent us a message with an invalid grid. + break; + } + + var targetPos = grid.LocalToWorld(msg.TargetPosition); + TryFire(user, targetPos); + } + else + { + // map pos + TryFire(user, msg.TargetPosition); + } + break; } } @@ -105,7 +125,12 @@ namespace Content.Server.GameObjects.Components.Weapon.Ranged return new RangedWeaponComponentState(FireRateSelector); } - private void _tryFire(IEntity user, GridCoordinates coordinates) + /// + /// Tries to fire a round of ammo out of the weapon. + /// + /// Entity that is operating the weapon, usually the player. + /// Target position on the map to shoot at. + private void TryFire(IEntity user, Vector2 targetPos) { if (!user.TryGetComponent(out HandsComponent hands) || hands.GetActiveHand?.Owner != Owner) { @@ -158,7 +183,7 @@ namespace Content.Server.GameObjects.Components.Weapon.Ranged return; } - FireHandler?.Invoke(user, coordinates); + FireHandler?.Invoke(user, targetPos); } // Probably a better way to do this. diff --git a/Content.Shared/GameObjects/Components/Weapons/Ranged/SharedRangedWeaponComponent.cs b/Content.Shared/GameObjects/Components/Weapons/Ranged/SharedRangedWeaponComponent.cs index 0eb6a6e49b..882ae4beee 100644 --- a/Content.Shared/GameObjects/Components/Weapons/Ranged/SharedRangedWeaponComponent.cs +++ b/Content.Shared/GameObjects/Components/Weapons/Ranged/SharedRangedWeaponComponent.cs @@ -1,6 +1,7 @@ -using System; +using System; using Robust.Shared.GameObjects; using Robust.Shared.Map; +using Robust.Shared.Maths; using Robust.Shared.Serialization; namespace Content.Shared.GameObjects.Components.Weapons.Ranged @@ -26,14 +27,33 @@ namespace Content.Shared.GameObjects.Components.Weapons.Ranged } } + /// + /// A component message raised when the weapon is fired at a position on the map. + /// [Serializable, NetSerializable] public sealed class FirePosComponentMessage : ComponentMessage { - public GridCoordinates Target { get; } + /// + /// If this is not invalid, the target position is relative to the grid. + /// Otherwise, it is a map position. + /// + public GridId TargetGrid { get; } - public FirePosComponentMessage(GridCoordinates target) + /// + /// If Target Grid is not invalid, this is relative to the grid, otherwise + /// it is a map position. + /// + public Vector2 TargetPosition { get; } + + /// + /// Constructs a new instance of . + /// + /// The grid that the target position is on, if any. + /// Target position relative to the grid, or a map position if the grid is invalid. + public FirePosComponentMessage(GridId targetGrid, Vector2 targetPosition) { - Target = target; + TargetGrid = targetGrid; + TargetPosition = targetPosition; } } }