From a7565b7651393ac5af429a94b846bd260c43d935 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?V=C3=ADctor=20Aguilera=20Puerto?= Date: Tue, 7 Jul 2020 23:12:12 +0200 Subject: [PATCH 01/19] Fix stunbaton issues --- .../Weapon/Melee/StunbatonComponent.cs | 25 +++++++++---------- 1 file changed, 12 insertions(+), 13 deletions(-) diff --git a/Content.Server/GameObjects/Components/Weapon/Melee/StunbatonComponent.cs b/Content.Server/GameObjects/Components/Weapon/Melee/StunbatonComponent.cs index 6914d71baf..9d77629431 100644 --- a/Content.Server/GameObjects/Components/Weapon/Melee/StunbatonComponent.cs +++ b/Content.Server/GameObjects/Components/Weapon/Melee/StunbatonComponent.cs @@ -52,7 +52,7 @@ namespace Content.Server.GameObjects.Components.Weapon.Melee [ViewVariables(VVAccess.ReadWrite)] private float _slowdownTime = 5f; - [ViewVariables(VVAccess.ReadWrite)] public float EnergyPerUse { get; set; } = 1000; + [ViewVariables(VVAccess.ReadWrite)] public float EnergyPerUse { get; set; } = 50; [ViewVariables] public bool Activated => _activated; @@ -88,13 +88,12 @@ namespace Content.Server.GameObjects.Components.Weapon.Melee protected override bool OnHitEntities(IReadOnlyList entities, AttackEventArgs eventArgs) { - var cell = Cell; - if (!Activated || entities.Count == 0 || cell == null) - return false; - if (!cell.TryUseCharge(EnergyPerUse)) - { - return false; - } + if (!Activated || entities.Count == 0 || Cell == null) + return true; + + if (!Cell.TryUseCharge(EnergyPerUse)) + return true; + EntitySystem.Get().PlayAtCoords("/Audio/Weapons/egloves.ogg", Owner.Transform.GridPosition, AudioHelpers.WithVariation(0.25f)); foreach (var entity in entities) @@ -112,11 +111,11 @@ namespace Content.Server.GameObjects.Components.Weapon.Melee else stunnable.Slowdown(_slowdownTime); } - if(cell.CurrentCharge < EnergyPerUse) - { - EntitySystem.Get().PlayAtCoords(AudioHelpers.GetRandomFileFromSoundCollection("sparks"), Owner.Transform.GridPosition, AudioHelpers.WithVariation(0.25f)); - TurnOff(); - } + + if (!(Cell.CurrentCharge < EnergyPerUse)) return true; + + EntitySystem.Get().PlayAtCoords(AudioHelpers.GetRandomFileFromSoundCollection("sparks"), Owner.Transform.GridPosition, AudioHelpers.WithVariation(0.25f)); + TurnOff(); return true; } From e27e4ed2b166abbda74801e892c43c298517a71c Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?V=C3=ADctor=20Aguilera=20Puerto?= Date: Tue, 7 Jul 2020 23:31:36 +0200 Subject: [PATCH 02/19] Fix overlays not being applied after reentering an entity --- .../Mobs/ClientOverlayEffectsComponent.cs | 20 +++++++++++++------ 1 file changed, 14 insertions(+), 6 deletions(-) diff --git a/Content.Client/GameObjects/Components/Mobs/ClientOverlayEffectsComponent.cs b/Content.Client/GameObjects/Components/Mobs/ClientOverlayEffectsComponent.cs index 580a3de334..acd8928375 100644 --- a/Content.Client/GameObjects/Components/Mobs/ClientOverlayEffectsComponent.cs +++ b/Content.Client/GameObjects/Components/Mobs/ClientOverlayEffectsComponent.cs @@ -28,7 +28,7 @@ namespace Content.Client.GameObjects.Components.Mobs /// /// An enum representing the current state being applied to the user /// - private readonly List _currentEffects = new List(); + private List _currentEffects = new List(); [ViewVariables(VVAccess.ReadOnly)] public List ActiveOverlays @@ -49,7 +49,9 @@ namespace Content.Client.GameObjects.Components.Mobs switch (message) { case PlayerAttachedMsg _: - SetEffects(ActiveOverlays); + var overlays = new List(_currentEffects); + _currentEffects.Clear(); + SetEffects(overlays); break; case PlayerDetachedMsg _: ActiveOverlays = new List(); @@ -61,14 +63,20 @@ namespace Content.Client.GameObjects.Components.Mobs { base.HandleComponentState(curState, nextState); - if(_playerManager?.LocalPlayer != null && _playerManager.LocalPlayer.ControlledEntity != Owner) - return; - - if (!(curState is OverlayEffectComponentState state) || ActiveOverlays.Equals(state.Overlays)) + if (!(curState is OverlayEffectComponentState state)) { return; } + if (_playerManager?.LocalPlayer != null && _playerManager.LocalPlayer.ControlledEntity != Owner) + { + _currentEffects = state.Overlays; + return; + } + + if (ActiveOverlays.Equals(state.Overlays)) + return; + ActiveOverlays = state.Overlays; } From f0892c20f1313f37036146435993e553a1ab1c0f Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?V=C3=ADctor=20Aguilera=20Puerto?= Date: Wed, 8 Jul 2020 00:26:54 +0200 Subject: [PATCH 03/19] Make xeno mob clickable, fixes #1310 --- Resources/Prototypes/Entities/Mobs/NPCs/xeno.yml | 1 + 1 file changed, 1 insertion(+) diff --git a/Resources/Prototypes/Entities/Mobs/NPCs/xeno.yml b/Resources/Prototypes/Entities/Mobs/NPCs/xeno.yml index f1c7228713..ed6b0bdc1c 100644 --- a/Resources/Prototypes/Entities/Mobs/NPCs/xeno.yml +++ b/Resources/Prototypes/Entities/Mobs/NPCs/xeno.yml @@ -23,6 +23,7 @@ - type: Icon sprite: Mobs/Species/xeno.rsi state: running + - type: Clickable - type: Physics mass: 85 - type: Collidable From 50562d77e6fc414cd4094b95fc3f13d6b66b9bd6 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?V=C3=ADctor=20Aguilera=20Puerto?= Date: Wed, 8 Jul 2020 00:50:09 +0200 Subject: [PATCH 04/19] Flashable is a word --- SpaceStation14.sln.DotSettings | 1 + 1 file changed, 1 insertion(+) diff --git a/SpaceStation14.sln.DotSettings b/SpaceStation14.sln.DotSettings index 961aacf984..4eed2c94d7 100644 --- a/SpaceStation14.sln.DotSettings +++ b/SpaceStation14.sln.DotSettings @@ -46,6 +46,7 @@ <data /> <data><IncludeFilters /><ExcludeFilters><Filter ModuleMask="Lidgren.Network" ModuleVersionMask="*" ClassMask="*" FunctionMask="*" IsEnabled="True" /></ExcludeFilters></data> True + True True True True From 1616b0d8677096650e5a6a52996e7ff72a2b05b5 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?V=C3=ADctor=20Aguilera=20Puerto?= Date: Wed, 8 Jul 2020 00:50:24 +0200 Subject: [PATCH 05/19] Remix flash.ogg down to mono --- Resources/Audio/Weapons/flash.ogg | Bin 9891 -> 16132 bytes 1 file changed, 0 insertions(+), 0 deletions(-) diff --git a/Resources/Audio/Weapons/flash.ogg b/Resources/Audio/Weapons/flash.ogg index eed2ed0d52410cb4047db0a99f9d2e08a664d32f..9305d698b87b1c77926ff4dee8dbecede3aeee37 100644 GIT binary patch literal 16132 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 literal 9891 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 From 271945e1a54ef47e316f0bfb5a638cffe4f99ca2 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?V=C3=ADctor=20Aguilera=20Puerto?= Date: Wed, 8 Jul 2020 00:51:08 +0200 Subject: [PATCH 06/19] Cleanup flashbangs. Fixes #1305 --- ...ableComponent.cs => FlashableComponent.cs} | 4 +- .../Explosion/FlashExplosiveComponent.cs | 6 +- .../Projectiles/FlashProjectileComponent.cs | 10 +-- .../Components/Weapon/FlashableComponent.cs | 53 +++++++++++++ .../Weapon/ServerFlashableComponent.cs | 78 ------------------- 5 files changed, 63 insertions(+), 88 deletions(-) rename Content.Client/GameObjects/Components/Weapons/{ClientFlashableComponent.cs => FlashableComponent.cs} (96%) create mode 100644 Content.Server/GameObjects/Components/Weapon/FlashableComponent.cs delete mode 100644 Content.Server/GameObjects/Components/Weapon/ServerFlashableComponent.cs diff --git a/Content.Client/GameObjects/Components/Weapons/ClientFlashableComponent.cs b/Content.Client/GameObjects/Components/Weapons/FlashableComponent.cs similarity index 96% rename from Content.Client/GameObjects/Components/Weapons/ClientFlashableComponent.cs rename to Content.Client/GameObjects/Components/Weapons/FlashableComponent.cs index b521ff0371..d7c5199396 100644 --- a/Content.Client/GameObjects/Components/Weapons/ClientFlashableComponent.cs +++ b/Content.Client/GameObjects/Components/Weapons/FlashableComponent.cs @@ -16,7 +16,7 @@ using Timer = Robust.Shared.Timers.Timer; namespace Content.Client.GameObjects.Components.Weapons { [RegisterComponent] - public sealed class ClientFlashableComponent : SharedFlashableComponent + public sealed class FlashableComponent : SharedFlashableComponent { private CancellationTokenSource _cancelToken; private TimeSpan _startTime; @@ -31,7 +31,7 @@ namespace Content.Client.GameObjects.Components.Weapons } var playerManager = IoCManager.Resolve(); - if (playerManager.LocalPlayer.ControlledEntity != Owner) + if (playerManager?.LocalPlayer != null && playerManager.LocalPlayer.ControlledEntity != Owner) { return; } diff --git a/Content.Server/GameObjects/Components/Explosion/FlashExplosiveComponent.cs b/Content.Server/GameObjects/Components/Explosion/FlashExplosiveComponent.cs index ff8a0feaef..554a722311 100644 --- a/Content.Server/GameObjects/Components/Explosion/FlashExplosiveComponent.cs +++ b/Content.Server/GameObjects/Components/Explosion/FlashExplosiveComponent.cs @@ -20,7 +20,7 @@ namespace Content.Server.GameObjects.Components.Explosion public override string Name => "FlashExplosive"; private float _range; - private double _duration; + private float _duration; private string _sound; private bool _deleteOnFlash; @@ -29,7 +29,7 @@ namespace Content.Server.GameObjects.Components.Explosion base.ExposeData(serializer); serializer.DataField(ref _range, "range", 7.0f); - serializer.DataField(ref _duration, "duration", 8.0); + serializer.DataField(ref _duration, "duration", 8.0f); serializer.DataField(ref _sound, "sound", "/Audio/Effects/flash_bang.ogg"); serializer.DataField(ref _deleteOnFlash, "deleteOnFlash", true); } @@ -40,7 +40,7 @@ namespace Content.Server.GameObjects.Components.Explosion ContainerHelpers.TryGetContainer(Owner, out var container); if (container == null || !container.Owner.HasComponent()) { - ServerFlashableComponent.FlashAreaHelper(Owner, _range, _duration); + FlashableComponent.FlashAreaHelper(Owner, _range, _duration); } if (_sound != null) diff --git a/Content.Server/GameObjects/Components/Projectiles/FlashProjectileComponent.cs b/Content.Server/GameObjects/Components/Projectiles/FlashProjectileComponent.cs index 381ebdd19e..756a37a44f 100644 --- a/Content.Server/GameObjects/Components/Projectiles/FlashProjectileComponent.cs +++ b/Content.Server/GameObjects/Components/Projectiles/FlashProjectileComponent.cs @@ -17,16 +17,16 @@ namespace Content.Server.GameObjects.Components.Projectiles { public override string Name => "FlashProjectile"; - private double _range; - private double _duration; + private float _range; + private float _duration; private bool _flashed; public override void ExposeData(ObjectSerializer serializer) { base.ExposeData(serializer); - serializer.DataField(ref _range, "range", 1.0); - serializer.DataField(ref _duration, "duration", 8.0); + serializer.DataField(ref _range, "range", 1.0f); + serializer.DataField(ref _duration, "duration", 8.0f); } public override void Initialize() @@ -45,7 +45,7 @@ namespace Content.Server.GameObjects.Components.Projectiles { return; } - ServerFlashableComponent.FlashAreaHelper(Owner, _range, _duration); + FlashableComponent.FlashAreaHelper(Owner, _range, _duration); _flashed = true; } diff --git a/Content.Server/GameObjects/Components/Weapon/FlashableComponent.cs b/Content.Server/GameObjects/Components/Weapon/FlashableComponent.cs new file mode 100644 index 0000000000..11499017b3 --- /dev/null +++ b/Content.Server/GameObjects/Components/Weapon/FlashableComponent.cs @@ -0,0 +1,53 @@ +using System; +using System.Linq; +using Content.Server.Utility; +using Content.Shared.GameObjects.Components.Weapons; +using Content.Shared.GameObjects.EntitySystems; +using Content.Shared.Physics; +using Robust.Server.GameObjects.EntitySystems; +using Robust.Shared.GameObjects; +using Robust.Shared.Interfaces.GameObjects; +using Robust.Shared.Interfaces.Physics; +using Robust.Shared.Interfaces.Timing; +using Robust.Shared.IoC; +using Robust.Shared.Maths; + +namespace Content.Server.GameObjects.Components.Weapon +{ + [RegisterComponent] + public sealed class FlashableComponent : SharedFlashableComponent + { + private double _duration; + private TimeSpan _lastFlash; + + public void Flash(double duration) + { + var timing = IoCManager.Resolve(); + _lastFlash = timing.CurTime; + _duration = duration; + Dirty(); + } + + public override ComponentState GetComponentState() + { + return new FlashComponentState(_duration, _lastFlash); + } + + public static void FlashAreaHelper(IEntity source, float range, float duration, string sound = null) + { + foreach (var entity in IoCManager.Resolve().GetEntitiesInRange(source.Transform.GridPosition, range)) + { + if (!InteractionChecks.InRangeUnobstructed(source, entity.Transform.MapPosition, range, ignoredEnt:entity)) + continue; + + if(entity.TryGetComponent(out FlashableComponent flashable)) + flashable.Flash(duration); + } + + if (!string.IsNullOrEmpty(sound)) + { + IoCManager.Resolve().GetEntitySystem().PlayAtCoords(sound, source.Transform.GridPosition); + } + } + } +} diff --git a/Content.Server/GameObjects/Components/Weapon/ServerFlashableComponent.cs b/Content.Server/GameObjects/Components/Weapon/ServerFlashableComponent.cs deleted file mode 100644 index 4dfd7c50c1..0000000000 --- a/Content.Server/GameObjects/Components/Weapon/ServerFlashableComponent.cs +++ /dev/null @@ -1,78 +0,0 @@ -using System; -using System.Linq; -using Content.Shared.GameObjects.Components.Weapons; -using Content.Shared.Physics; -using Robust.Server.GameObjects.EntitySystems; -using Robust.Shared.GameObjects; -using Robust.Shared.Interfaces.GameObjects; -using Robust.Shared.Interfaces.Physics; -using Robust.Shared.Interfaces.Timing; -using Robust.Shared.IoC; -using Robust.Shared.Maths; - -namespace Content.Server.GameObjects.Components.Weapon -{ - [RegisterComponent] - public sealed class ServerFlashableComponent : SharedFlashableComponent - { - private double _duration; - private TimeSpan _lastFlash; - - public void Flash(double duration) - { - var timing = IoCManager.Resolve(); - _lastFlash = timing.CurTime; - _duration = duration; - Dirty(); - } - - public override ComponentState GetComponentState() - { - return new FlashComponentState(_duration, _lastFlash); - } - - public static void FlashAreaHelper(IEntity source, double range, double duration, string sound = null) - { - var physicsManager = IoCManager.Resolve(); - var entityManager = IoCManager.Resolve(); - - foreach (var entity in entityManager.GetEntities(new TypeEntityQuery(typeof(ServerFlashableComponent)))) - { - if (source.Transform.MapID != entity.Transform.MapID || - entity == source) - { - continue; - } - - var direction = entity.Transform.WorldPosition - source.Transform.WorldPosition; - - if (direction.Length > range) - { - continue; - } - - // Direction will be zero if they're hit with the source only I think - if (direction == Vector2.Zero) - { - continue; - } - - var ray = new CollisionRay(source.Transform.WorldPosition, direction.Normalized, (int) CollisionGroup.Opaque); - var rayCastResults = physicsManager.IntersectRay(source.Transform.MapID, ray, direction.Length, source, false).ToList(); - if (rayCastResults.Count == 0 || - rayCastResults[0].HitEntity != entity) - { - continue; - } - - var flashable = entity.GetComponent(); - flashable.Flash(duration); - } - - if (sound != null) - { - IoCManager.Resolve().GetEntitySystem().PlayAtCoords(sound, source.Transform.GridPosition); - } - } - } -} From c25c1e10944d1ac3a445dc88eed4959d8d58d51d Mon Sep 17 00:00:00 2001 From: Pieter-Jan Briers Date: Wed, 8 Jul 2020 01:28:49 +0200 Subject: [PATCH 07/19] Probably fix moonwalking? --- .../Movement/SharedPlayerInputMoverComponent.cs | 13 ++++++++----- 1 file changed, 8 insertions(+), 5 deletions(-) diff --git a/Content.Shared/GameObjects/Components/Movement/SharedPlayerInputMoverComponent.cs b/Content.Shared/GameObjects/Components/Movement/SharedPlayerInputMoverComponent.cs index dee6b09b08..cb47ac544c 100644 --- a/Content.Shared/GameObjects/Components/Movement/SharedPlayerInputMoverComponent.cs +++ b/Content.Shared/GameObjects/Components/Movement/SharedPlayerInputMoverComponent.cs @@ -189,11 +189,16 @@ namespace Content.Shared.GameObjects.Components.Movement _lastInputSubTick = 0; } - var fraction = (subTick - _lastInputSubTick) / (float) ushort.MaxValue; + if (_lastInputSubTick >= subTick) + { + var fraction = (subTick - _lastInputSubTick) / (float) ushort.MaxValue; - ref var lastMoveAmount = ref Sprinting ? ref _curTickSprintMovement : ref _curTickWalkMovement; + ref var lastMoveAmount = ref Sprinting ? ref _curTickSprintMovement : ref _curTickWalkMovement; - lastMoveAmount += DirVecForButtons(_heldMoveButtons) * fraction; + lastMoveAmount += DirVecForButtons(_heldMoveButtons) * fraction; + + _lastInputSubTick = subTick; + } if (enabled) { @@ -204,8 +209,6 @@ namespace Content.Shared.GameObjects.Components.Movement _heldMoveButtons &= ~bit; } - _lastInputSubTick = subTick; - Dirty(); } From 5aefae184c9f6b5317addf67c29adc8252c1ee51 Mon Sep 17 00:00:00 2001 From: metalgearsloth <31366439+metalgearsloth@users.noreply.github.com> Date: Wed, 8 Jul 2020 09:37:35 +1000 Subject: [PATCH 08/19] Refactor AI considerations (#1278) Considerations are now instantiated under a manager and re-used between entities where they pass in their blackboard to get a score back. Also makes the API a bit nicer to use. Also some random cleanup. Co-authored-by: Metal Gear Sloth --- .../Actions/Clothing/Gloves/EquipGloves.cs | 21 ++++--- .../Actions/Clothing/Gloves/PickUpGloves.cs | 26 +++++--- .../Actions/Clothing/Head/EquipHead.cs | 22 ++++--- .../Actions/Clothing/Head/PickUpHead.cs | 26 +++++--- .../OuterClothing/EquipOuterClothing.cs | 21 ++++--- .../OuterClothing/PickUpOuterClothing.cs | 26 +++++--- .../Actions/Clothing/Shoes/EquipShoes.cs | 21 ++++--- .../Actions/Clothing/Shoes/PickUpShoes.cs | 26 +++++--- .../Actions/Combat/Melee/EquipMelee.cs | 29 +++++---- .../Combat/Melee/MeleeWeaponAttackEntity.cs | 51 +++++++-------- .../Actions/Combat/Melee/PickUpMeleeWeapon.cs | 38 +++++++----- .../Combat/Melee/UnarmedAttackEntity.cs | 41 ++++++------ .../Actions/Idle/CloseLastEntityStorage.cs | 25 +++++--- .../AI/Utility/Actions/Idle/WanderAndWait.cs | 26 ++++---- .../Actions/Nutrition/Drink/PickUpDrink.cs | 40 +++++++----- .../Nutrition/Drink/UseDrinkInInventory.cs | 30 +++++---- .../Actions/Nutrition/Food/PickUpFood.cs | 39 +++++++----- .../Nutrition/Food/UseFoodInInventory.cs | 32 ++++++---- .../Actions/Test/MoveRightAndLeftTen.cs | 19 ++++-- .../AI/Utility/Actions/UtilityAction.cs | 23 ++++--- .../AI/Utility/AiLogic/UtilityAI.cs | 9 +++ .../ActionBlocker/CanMoveCon.cs | 5 +- .../Clothing/ClothingInInventoryCon.cs | 20 +++--- .../Clothing/ClothingInSlotCon.cs | 15 +++-- .../Combat/Melee/CanUnarmedCombatCon.cs | 5 +- .../Combat/Melee/HasMeleeWeaponCon.cs | 7 +-- .../Combat/Melee/MeleeWeaponDamageCon.cs | 5 +- .../Combat/Melee/MeleeWeaponEquippedCon.cs | 5 +- .../Combat/Melee/MeleeWeaponSpeedCon.cs | 5 +- .../Considerations/Combat/TargetHealthCon.cs | 5 +- .../Considerations/Combat/TargetIsCritCon.cs | 6 +- .../Considerations/Combat/TargetIsDeadCon.cs | 5 +- .../Utility/Considerations/Consideration.cs | 62 ++++++++++++++++--- .../Considerations/ConsiderationsManager.cs | 29 +++++++++ .../Containers/TargetAccessibleCon.cs | 6 +- .../AI/Utility/Considerations/DummyCon.cs | 5 +- .../Considerations/Hands/FreeHandCon.cs | 5 +- .../Hands/TargetInOurHandsCon.cs | 5 +- .../Inventory/CanPutTargetInHandsCon.cs | 9 +-- .../Inventory/TargetInOurInventoryCon.cs | 8 +-- .../Considerations/Movement/DistanceCon.cs | 5 +- .../Nutrition/Drink/DrinkValueCon.cs | 5 +- .../Nutrition/Drink/ThirstCon.cs | 5 +- .../Nutrition/Food/FoodValueCon.cs | 7 +-- .../Nutrition/Food/HungerCon.cs | 7 +-- .../State/StoredStateEntityIsNullCon.cs | 26 ++++++++ .../State/StoredStateIsNullCon.cs | 24 ------- .../Clothing/Gloves/EquipAnyGlovesExp.cs | 6 +- .../Clothing/Head/EquipAnyHeadExp.cs | 2 +- .../Clothing/Head/PickUpAnyNearbyHeadExp.cs | 3 + .../OuterClothing/EquipAnyOuterClothingExp.cs | 4 +- .../Clothing/Shoes/EquipAnyShoesExp.cs | 4 +- .../Combat/Melee/EquipMeleeExp.cs | 8 ++- .../Nutrition/UseDrinkInHandsExp.cs | 8 ++- .../Nutrition/UseFoodInInventoryExp.cs | 8 ++- Content.Server/AI/WorldState/Blackboard.cs | 5 ++ Content.Server/AI/WorldState/StateData.cs | 20 ++++-- .../States/Clothing/ClothingSlotConState.cs | 13 ++++ .../Clothing/ClothingSlotFlagConState.cs | 13 ++++ .../States/Inventory/InventoryState.cs | 14 ++--- .../States/Utility/ConsiderationState.cs | 10 +++ .../States/Utility/StoredStateIsNullState.cs | 13 ++++ Content.Server/EntryPoint.cs | 4 +- Content.Server/ServerContentIoC.cs | 4 +- 64 files changed, 625 insertions(+), 396 deletions(-) create mode 100644 Content.Server/AI/Utility/Considerations/ConsiderationsManager.cs create mode 100644 Content.Server/AI/Utility/Considerations/State/StoredStateEntityIsNullCon.cs delete mode 100644 Content.Server/AI/Utility/Considerations/State/StoredStateIsNullCon.cs create mode 100644 Content.Server/AI/WorldState/States/Clothing/ClothingSlotConState.cs create mode 100644 Content.Server/AI/WorldState/States/Clothing/ClothingSlotFlagConState.cs create mode 100644 Content.Server/AI/WorldState/States/Utility/ConsiderationState.cs create mode 100644 Content.Server/AI/WorldState/States/Utility/StoredStateIsNullState.cs diff --git a/Content.Server/AI/Utility/Actions/Clothing/Gloves/EquipGloves.cs b/Content.Server/AI/Utility/Actions/Clothing/Gloves/EquipGloves.cs index 1d382044d1..96317b6ad2 100644 --- a/Content.Server/AI/Utility/Actions/Clothing/Gloves/EquipGloves.cs +++ b/Content.Server/AI/Utility/Actions/Clothing/Gloves/EquipGloves.cs @@ -1,14 +1,15 @@ +using System; 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.Utility.Curves; 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; namespace Content.Server.AI.Utility.Actions.Clothing.Gloves { @@ -36,12 +37,18 @@ namespace Content.Server.AI.Utility.Actions.Clothing.Gloves base.UpdateBlackboard(context); context.GetState().SetValue(_entity); } + + protected override IReadOnlyCollection> GetConsiderations(Blackboard context) + { + var considerationsManager = IoCManager.Resolve(); - protected override Consideration[] Considerations { get; } = { - new ClothingInSlotCon(EquipmentSlotDefines.Slots.GLOVES, - new InverseBoolCurve()), - new CanPutTargetInHandsCon( - new BoolCurve()), - }; + return new[] + { + considerationsManager.Get().Slot(EquipmentSlotDefines.Slots.GLOVES, context) + .InverseBoolCurve(context), + 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 b2402d4065..703ed5362f 100644 --- a/Content.Server/AI/Utility/Actions/Clothing/Gloves/PickUpGloves.cs +++ b/Content.Server/AI/Utility/Actions/Clothing/Gloves/PickUpGloves.cs @@ -1,12 +1,14 @@ +using System; +using System.Collections.Generic; using Content.Server.AI.Operators.Sequences; using Content.Server.AI.Utility.Considerations; using Content.Server.AI.Utility.Considerations.Clothing; using Content.Server.AI.Utility.Considerations.Inventory; -using Content.Server.AI.Utility.Curves; 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; namespace Content.Server.AI.Utility.Actions.Clothing.Gloves { @@ -30,14 +32,20 @@ namespace Content.Server.AI.Utility.Actions.Clothing.Gloves base.UpdateBlackboard(context); context.GetState().SetValue(_entity); } + + protected override IReadOnlyCollection> GetConsiderations(Blackboard context) + { + var considerationsManager = IoCManager.Resolve(); - protected override Consideration[] Considerations { get; } = { - new ClothingInSlotCon(EquipmentSlotDefines.Slots.GLOVES, - new InverseBoolCurve()), - new CanPutTargetInHandsCon( - new BoolCurve()), - new ClothingInInventoryCon(EquipmentSlotDefines.SlotFlags.GLOVES, - new InverseBoolCurve()), - }; + return new[] + { + considerationsManager.Get().Slot(EquipmentSlotDefines.Slots.GLOVES, context) + .InverseBoolCurve(context), + considerationsManager.Get() + .BoolCurve(context), + considerationsManager.Get().Slot(EquipmentSlotDefines.SlotFlags.GLOVES, context) + .InverseBoolCurve(context) + }; + } } } diff --git a/Content.Server/AI/Utility/Actions/Clothing/Head/EquipHead.cs b/Content.Server/AI/Utility/Actions/Clothing/Head/EquipHead.cs index 95bd1a772f..1935416dc7 100644 --- a/Content.Server/AI/Utility/Actions/Clothing/Head/EquipHead.cs +++ b/Content.Server/AI/Utility/Actions/Clothing/Head/EquipHead.cs @@ -1,14 +1,15 @@ +using System; 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.Utility.Curves; 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; namespace Content.Server.AI.Utility.Actions.Clothing.Head { @@ -37,11 +38,18 @@ namespace Content.Server.AI.Utility.Actions.Clothing.Head context.GetState().SetValue(_entity); } - protected override Consideration[] Considerations { get; } = { - new ClothingInSlotCon(EquipmentSlotDefines.Slots.HEAD, - new InverseBoolCurve()), - new CanPutTargetInHandsCon( - new BoolCurve()), - }; + protected override IReadOnlyCollection> GetConsiderations(Blackboard context) + { + var considerationsManager = IoCManager.Resolve(); + + return new[] + { + considerationsManager.Get().Slot(EquipmentSlotDefines.Slots.HEAD, context) + .InverseBoolCurve(context), + 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 98a999cc8d..0c06d707d5 100644 --- a/Content.Server/AI/Utility/Actions/Clothing/Head/PickUpHead.cs +++ b/Content.Server/AI/Utility/Actions/Clothing/Head/PickUpHead.cs @@ -1,12 +1,14 @@ +using System; +using System.Collections.Generic; using Content.Server.AI.Operators.Sequences; using Content.Server.AI.Utility.Considerations; using Content.Server.AI.Utility.Considerations.Clothing; using Content.Server.AI.Utility.Considerations.Inventory; -using Content.Server.AI.Utility.Curves; 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; namespace Content.Server.AI.Utility.Actions.Clothing.Head { @@ -31,13 +33,19 @@ namespace Content.Server.AI.Utility.Actions.Clothing.Head context.GetState().SetValue(_entity); } - protected override Consideration[] Considerations { get; } = { - new ClothingInSlotCon(EquipmentSlotDefines.Slots.HEAD, - new InverseBoolCurve()), - new CanPutTargetInHandsCon( - new BoolCurve()), - new ClothingInInventoryCon(EquipmentSlotDefines.SlotFlags.HEAD, - new InverseBoolCurve()), - }; + protected override IReadOnlyCollection> GetConsiderations(Blackboard context) + { + var considerationsManager = IoCManager.Resolve(); + + return new[] + { + considerationsManager.Get().Slot(EquipmentSlotDefines.Slots.HEAD, context) + .InverseBoolCurve(context), + considerationsManager.Get() + .BoolCurve(context), + considerationsManager.Get().Slot(EquipmentSlotDefines.SlotFlags.HEAD, context) + .InverseBoolCurve(context) + }; + } } } diff --git a/Content.Server/AI/Utility/Actions/Clothing/OuterClothing/EquipOuterClothing.cs b/Content.Server/AI/Utility/Actions/Clothing/OuterClothing/EquipOuterClothing.cs index 6d1eae4445..e593098cf5 100644 --- a/Content.Server/AI/Utility/Actions/Clothing/OuterClothing/EquipOuterClothing.cs +++ b/Content.Server/AI/Utility/Actions/Clothing/OuterClothing/EquipOuterClothing.cs @@ -1,14 +1,15 @@ +using System; 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.Utility.Curves; 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; namespace Content.Server.AI.Utility.Actions.Clothing.OuterClothing { @@ -37,11 +38,17 @@ namespace Content.Server.AI.Utility.Actions.Clothing.OuterClothing context.GetState().SetValue(_entity); } - protected override Consideration[] Considerations { get; } = { - new ClothingInSlotCon(EquipmentSlotDefines.Slots.OUTERCLOTHING, - new InverseBoolCurve()), - new CanPutTargetInHandsCon( - new BoolCurve()), - }; + protected override IReadOnlyCollection> GetConsiderations(Blackboard context) + { + var considerationsManager = IoCManager.Resolve(); + + return new[] + { + considerationsManager.Get().Slot(EquipmentSlotDefines.Slots.OUTERCLOTHING, context) + .InverseBoolCurve(context), + 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 359c4ccdd4..a192fda3e7 100644 --- a/Content.Server/AI/Utility/Actions/Clothing/OuterClothing/PickUpOuterClothing.cs +++ b/Content.Server/AI/Utility/Actions/Clothing/OuterClothing/PickUpOuterClothing.cs @@ -1,12 +1,14 @@ +using System; +using System.Collections.Generic; using Content.Server.AI.Operators.Sequences; using Content.Server.AI.Utility.Considerations; using Content.Server.AI.Utility.Considerations.Clothing; using Content.Server.AI.Utility.Considerations.Inventory; -using Content.Server.AI.Utility.Curves; 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; namespace Content.Server.AI.Utility.Actions.Clothing.OuterClothing { @@ -31,13 +33,19 @@ namespace Content.Server.AI.Utility.Actions.Clothing.OuterClothing context.GetState().SetValue(_entity); } - protected override Consideration[] Considerations { get; } = { - new ClothingInSlotCon(EquipmentSlotDefines.Slots.OUTERCLOTHING, - new InverseBoolCurve()), - new CanPutTargetInHandsCon( - new BoolCurve()), - new ClothingInInventoryCon(EquipmentSlotDefines.SlotFlags.OUTERCLOTHING, - new InverseBoolCurve()), - }; + protected override IReadOnlyCollection> GetConsiderations(Blackboard context) + { + var considerationsManager = IoCManager.Resolve(); + + return new[] + { + considerationsManager.Get().Slot(EquipmentSlotDefines.Slots.OUTERCLOTHING, context) + .InverseBoolCurve(context), + considerationsManager.Get() + .BoolCurve(context), + considerationsManager.Get().Slot(EquipmentSlotDefines.SlotFlags.OUTERCLOTHING, context) + .InverseBoolCurve(context) + }; + } } } diff --git a/Content.Server/AI/Utility/Actions/Clothing/Shoes/EquipShoes.cs b/Content.Server/AI/Utility/Actions/Clothing/Shoes/EquipShoes.cs index 78dd53ab73..fdbc2c78e7 100644 --- a/Content.Server/AI/Utility/Actions/Clothing/Shoes/EquipShoes.cs +++ b/Content.Server/AI/Utility/Actions/Clothing/Shoes/EquipShoes.cs @@ -1,14 +1,15 @@ +using System; 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.Utility.Curves; 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; namespace Content.Server.AI.Utility.Actions.Clothing.Shoes { @@ -37,11 +38,17 @@ namespace Content.Server.AI.Utility.Actions.Clothing.Shoes context.GetState().SetValue(_entity); } - protected override Consideration[] Considerations { get; } = { - new ClothingInSlotCon(EquipmentSlotDefines.Slots.SHOES, - new InverseBoolCurve()), - new CanPutTargetInHandsCon( - new BoolCurve()), - }; + protected override IReadOnlyCollection> GetConsiderations(Blackboard context) + { + var considerationsManager = IoCManager.Resolve(); + + return new[] + { + considerationsManager.Get().Slot(EquipmentSlotDefines.Slots.SHOES, context) + .InverseBoolCurve(context), + 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 f755873688..60e4d00196 100644 --- a/Content.Server/AI/Utility/Actions/Clothing/Shoes/PickUpShoes.cs +++ b/Content.Server/AI/Utility/Actions/Clothing/Shoes/PickUpShoes.cs @@ -1,12 +1,14 @@ +using System; +using System.Collections.Generic; using Content.Server.AI.Operators.Sequences; using Content.Server.AI.Utility.Considerations; using Content.Server.AI.Utility.Considerations.Clothing; using Content.Server.AI.Utility.Considerations.Inventory; -using Content.Server.AI.Utility.Curves; 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; namespace Content.Server.AI.Utility.Actions.Clothing.Shoes { @@ -31,13 +33,19 @@ namespace Content.Server.AI.Utility.Actions.Clothing.Shoes context.GetState().SetValue(_entity); } - protected override Consideration[] Considerations { get; } = { - new ClothingInSlotCon(EquipmentSlotDefines.Slots.SHOES, - new InverseBoolCurve()), - new CanPutTargetInHandsCon( - new BoolCurve()), - new ClothingInInventoryCon(EquipmentSlotDefines.SlotFlags.SHOES, - new InverseBoolCurve()), - }; + protected override IReadOnlyCollection> GetConsiderations(Blackboard context) + { + var considerationsManager = IoCManager.Resolve(); + + return new[] + { + considerationsManager.Get().Slot(EquipmentSlotDefines.Slots.SHOES, context) + .InverseBoolCurve(context), + considerationsManager.Get() + .BoolCurve(context), + considerationsManager.Get().Slot(EquipmentSlotDefines.SlotFlags.SHOES, context) + .InverseBoolCurve(context) + }; + } } } diff --git a/Content.Server/AI/Utility/Actions/Combat/Melee/EquipMelee.cs b/Content.Server/AI/Utility/Actions/Combat/Melee/EquipMelee.cs index 81c799701c..29bdea8394 100644 --- a/Content.Server/AI/Utility/Actions/Combat/Melee/EquipMelee.cs +++ b/Content.Server/AI/Utility/Actions/Combat/Melee/EquipMelee.cs @@ -1,14 +1,15 @@ +using System; 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.Combat.Melee; using Content.Server.AI.Utility.Considerations.Inventory; -using Content.Server.AI.Utility.Curves; using Content.Server.AI.WorldState; using Content.Server.AI.WorldState.States; using Content.Server.AI.WorldState.States.Combat; using Robust.Shared.Interfaces.GameObjects; +using Robust.Shared.IoC; namespace Content.Server.AI.Utility.Actions.Combat.Melee { @@ -37,15 +38,21 @@ namespace Content.Server.AI.Utility.Actions.Combat.Melee context.GetState().SetValue(_entity); } - protected override Consideration[] Considerations { get; } = { - new MeleeWeaponEquippedCon( - new InverseBoolCurve()), - new CanPutTargetInHandsCon( - new BoolCurve()), - new MeleeWeaponSpeedCon( - new QuadraticCurve(1.0f, 0.5f, 0.0f, 0.0f)), - new MeleeWeaponDamageCon( - new QuadraticCurve(1.0f, 0.25f, 0.0f, 0.0f)), - }; + protected override IReadOnlyCollection> GetConsiderations(Blackboard context) + { + var considerationsManager = IoCManager.Resolve(); + + return new[] + { + considerationsManager.Get() + .InverseBoolCurve(context), + considerationsManager.Get() + .BoolCurve(context), + considerationsManager.Get() + .QuadraticCurve(context, 1.0f, 0.5f, 0.0f, 0.0f), + considerationsManager.Get() + .QuadraticCurve(context, 1.0f, 0.25f, 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 2da20091a1..de65a16279 100644 --- a/Content.Server/AI/Utility/Actions/Combat/Melee/MeleeWeaponAttackEntity.cs +++ b/Content.Server/AI/Utility/Actions/Combat/Melee/MeleeWeaponAttackEntity.cs @@ -1,3 +1,4 @@ +using System; using System.Collections.Generic; using Content.Server.AI.Operators; using Content.Server.AI.Operators.Combat; @@ -7,7 +8,6 @@ using Content.Server.AI.Utility.Considerations; using Content.Server.AI.Utility.Considerations.Combat; using Content.Server.AI.Utility.Considerations.Combat.Melee; using Content.Server.AI.Utility.Considerations.Movement; -using Content.Server.AI.Utility.Curves; using Content.Server.AI.WorldState; using Content.Server.AI.WorldState.States; using Content.Server.AI.WorldState.States.Combat; @@ -15,6 +15,7 @@ using Content.Server.AI.WorldState.States.Inventory; using Content.Server.AI.WorldState.States.Movement; using Content.Server.GameObjects.Components.Weapon.Melee; using Robust.Shared.Interfaces.GameObjects; +using Robust.Shared.IoC; namespace Content.Server.AI.Utility.Actions.Combat.Melee { @@ -30,16 +31,15 @@ namespace Content.Server.AI.Utility.Actions.Combat.Melee public override void SetupOperators(Blackboard context) { - var equipped = context.GetState().GetValue(); MoveToEntityOperator moveOperator; + var equipped = context.GetState().GetValue(); if (equipped != null && equipped.TryGetComponent(out MeleeWeaponComponent meleeWeaponComponent)) { moveOperator = new MoveToEntityOperator(Owner, _entity, meleeWeaponComponent.Range - 0.01f); } - // I think it's possible for this to happen given planning is time-sliced? - // TODO: At this point we should abort else { + // TODO: Abort moveOperator = new MoveToEntityOperator(Owner, _entity); } @@ -58,27 +58,28 @@ namespace Content.Server.AI.Utility.Actions.Combat.Melee var equipped = context.GetState().GetValue(); context.GetState().SetValue(equipped); } + + protected override IReadOnlyCollection> GetConsiderations(Blackboard context) + { + var considerationsManager = IoCManager.Resolve(); - protected override Consideration[] Considerations { get; } = { - // Check if we have a weapon; easy-out - new MeleeWeaponEquippedCon( - new BoolCurve()), - // Don't attack a dead target - new TargetIsDeadCon( - new InverseBoolCurve()), - // Deprioritise a target in crit - new TargetIsCritCon( - new QuadraticCurve(-0.8f, 1.0f, 1.0f, 0.0f)), - // Somewhat prioritise distance - new DistanceCon( - new QuadraticCurve(-1.0f, 1.0f, 1.02f, 0.0f)), - // Prefer weaker targets - new TargetHealthCon( - new QuadraticCurve(1.0f, 0.4f, 0.0f, -0.02f)), - new MeleeWeaponSpeedCon( - new QuadraticCurve(1.0f, 0.5f, 0.0f, 0.0f)), - new MeleeWeaponDamageCon( - new QuadraticCurve(1.0f, 0.25f, 0.0f, 0.0f)), - }; + 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() + .QuadraticCurve(context, 1.0f, 0.4f, 0.0f, -0.02f), + considerationsManager.Get() + .QuadraticCurve(context, 1.0f, 0.5f, 0.0f, 0.0f), + considerationsManager.Get() + .QuadraticCurve(context, 1.0f, 0.25f, 0.0f, 0.0f), + }; + } } } diff --git a/Content.Server/AI/Utility/Actions/Combat/Melee/PickUpMeleeWeapon.cs b/Content.Server/AI/Utility/Actions/Combat/Melee/PickUpMeleeWeapon.cs index 216152e4d8..1d1ec0ec96 100644 --- a/Content.Server/AI/Utility/Actions/Combat/Melee/PickUpMeleeWeapon.cs +++ b/Content.Server/AI/Utility/Actions/Combat/Melee/PickUpMeleeWeapon.cs @@ -1,14 +1,16 @@ +using System; +using System.Collections.Generic; using Content.Server.AI.Operators.Sequences; using Content.Server.AI.Utility.Considerations; using Content.Server.AI.Utility.Considerations.Combat.Melee; 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.Curves; using Content.Server.AI.WorldState; using Content.Server.AI.WorldState.States; using Content.Server.AI.WorldState.States.Combat; using Robust.Shared.Interfaces.GameObjects; +using Robust.Shared.IoC; namespace Content.Server.AI.Utility.Actions.Combat.Melee { @@ -33,20 +35,26 @@ namespace Content.Server.AI.Utility.Actions.Combat.Melee context.GetState().SetValue(_entity); context.GetState().SetValue(_entity); } + + protected override IReadOnlyCollection> GetConsiderations(Blackboard context) + { + var considerationsManager = IoCManager.Resolve(); - protected override Consideration[] Considerations { get; } = { - new TargetAccessibleCon( - new BoolCurve()), - new FreeHandCon( - new BoolCurve()), - new HasMeleeWeaponCon( - new InverseBoolCurve()), - new DistanceCon( - new QuadraticCurve(-1.0f, 1.0f, 1.02f, 0.0f)), - new MeleeWeaponDamageCon( - new QuadraticCurve(1.0f, 0.25f, 0.0f, 0.0f)), - new MeleeWeaponSpeedCon( - new QuadraticCurve(-1.0f, 0.5f, 1.0f, 0.0f)), - }; + return new[] + { + considerationsManager.Get() + .BoolCurve(context), + considerationsManager.Get() + .BoolCurve(context), + considerationsManager.Get() + .InverseBoolCurve(context), + considerationsManager.Get() + .QuadraticCurve(context, 1.0f, 1.0f, 0.02f, 0.0f), + considerationsManager.Get() + .QuadraticCurve(context, 1.0f, 0.25f, 0.0f, 0.0f), + considerationsManager.Get() + .QuadraticCurve(context, -1.0f, 0.5f, 1.0f, 0.0f), + }; + } } } diff --git a/Content.Server/AI/Utility/Actions/Combat/Melee/UnarmedAttackEntity.cs b/Content.Server/AI/Utility/Actions/Combat/Melee/UnarmedAttackEntity.cs index 6883b294bf..7355e216db 100644 --- a/Content.Server/AI/Utility/Actions/Combat/Melee/UnarmedAttackEntity.cs +++ b/Content.Server/AI/Utility/Actions/Combat/Melee/UnarmedAttackEntity.cs @@ -1,3 +1,4 @@ +using System; using System.Collections.Generic; using Content.Server.AI.Operators; using Content.Server.AI.Operators.Combat.Melee; @@ -6,13 +7,13 @@ using Content.Server.AI.Utility.Considerations; using Content.Server.AI.Utility.Considerations.Combat; using Content.Server.AI.Utility.Considerations.Combat.Melee; using Content.Server.AI.Utility.Considerations.Movement; -using Content.Server.AI.Utility.Curves; using Content.Server.AI.WorldState; using Content.Server.AI.WorldState.States; using Content.Server.AI.WorldState.States.Combat; using Content.Server.AI.WorldState.States.Movement; using Content.Server.GameObjects.Components.Weapon.Melee; using Robust.Shared.Interfaces.GameObjects; +using Robust.Shared.IoC; namespace Content.Server.AI.Utility.Actions.Combat.Melee { @@ -56,23 +57,25 @@ namespace Content.Server.AI.Utility.Actions.Combat.Melee context.GetState().SetValue(Owner); } - protected override Consideration[] Considerations { get; } = { - new CanUnarmedCombatCon( - new BoolCurve()), - // Don't attack a dead target - new TargetIsDeadCon( - new InverseBoolCurve()), - // Deprioritise a target in crit - new TargetIsCritCon( - new QuadraticCurve(-0.8f, 1.0f, 1.0f, 0.0f)), - // Somewhat prioritise distance - new DistanceCon( - new QuadraticCurve(-1.0f, 1.0f, 1.02f, 0.0f)), - // Prefer weaker targets - new TargetHealthCon( - new QuadraticCurve(1.0f, 0.4f, 0.0f, -0.02f)), - // TODO: Consider our Speed and Damage to compare this to using a weapon - // Also need to unequip our weapon if we have one (xenos can't hold one so no issue for now) - }; + protected override IReadOnlyCollection> GetConsiderations(Blackboard context) + { + var considerationsManager = IoCManager.Resolve(); + + 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() + .QuadraticCurve(context, 1.0f, 0.4f, 0.0f, -0.02f), + // TODO: Consider our Speed and Damage to compare this to using a weapon + // Also need to unequip our weapon if we have one (xenos can't hold one so no issue for now) + }; + } } } \ 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 29b7e7b918..cd311a3270 100644 --- a/Content.Server/AI/Utility/Actions/Idle/CloseLastEntityStorage.cs +++ b/Content.Server/AI/Utility/Actions/Idle/CloseLastEntityStorage.cs @@ -1,3 +1,4 @@ +using System; using System.Collections.Generic; using Content.Server.AI.Operators; using Content.Server.AI.Operators.Inventory; @@ -5,10 +6,10 @@ using Content.Server.AI.Operators.Movement; using Content.Server.AI.Utility.Considerations; using Content.Server.AI.Utility.Considerations.Movement; using Content.Server.AI.Utility.Considerations.State; -using Content.Server.AI.Utility.Curves; using Content.Server.AI.WorldState; using Content.Server.AI.WorldState.States.Inventory; using Robust.Shared.Interfaces.GameObjects; +using Robust.Shared.IoC; namespace Content.Server.AI.Utility.Actions.Idle { @@ -21,13 +22,6 @@ namespace Content.Server.AI.Utility.Actions.Idle public CloseLastEntityStorage(IEntity owner) : base(owner) {} - protected override Consideration[] Considerations => new Consideration[] - { - new StoredStateIsNullCon( - new InverseBoolCurve()), - new DistanceCon( - new QuadraticCurve(-1.0f, 1.0f, 1.02f, 0.0f)), - }; public override void SetupOperators(Blackboard context) { var lastStorage = context.GetState().GetValue(); @@ -37,6 +31,21 @@ namespace Content.Server.AI.Utility.Actions.Idle new MoveToEntityOperator(Owner, lastStorage), new CloseLastStorageOperator(Owner), }); + } + + protected override IReadOnlyCollection> GetConsiderations(Blackboard context) + { + var considerationsManager = IoCManager.Resolve(); + + return new[] + { + considerationsManager.Get().Set(typeof(LastOpenedStorageState), context) + .InverseBoolCurve(context), + considerationsManager.Get() + .QuadraticCurve(context, 1.0f, 1.0f, 0.02f, 0.0f), + + }; } + } } \ No newline at end of file diff --git a/Content.Server/AI/Utility/Actions/Idle/WanderAndWait.cs b/Content.Server/AI/Utility/Actions/Idle/WanderAndWait.cs index 52f03c4046..3abb90dd3f 100644 --- a/Content.Server/AI/Utility/Actions/Idle/WanderAndWait.cs +++ b/Content.Server/AI/Utility/Actions/Idle/WanderAndWait.cs @@ -1,10 +1,11 @@ +using System; using System.Collections.Generic; using Content.Server.AI.Operators; using Content.Server.AI.Operators.Generic; using Content.Server.AI.Operators.Movement; using Content.Server.AI.Utility.Considerations; using Content.Server.AI.Utility.Considerations.ActionBlocker; -using Content.Server.AI.Utility.Curves; +using Content.Server.AI.Utility.Considerations.Containers; using Content.Server.AI.WorldState; using Robust.Shared.Interfaces.GameObjects; using Robust.Shared.Interfaces.Map; @@ -22,12 +23,9 @@ namespace Content.Server.AI.Utility.Actions.Idle public sealed class WanderAndWait : UtilityAction { public override bool CanOverride => false; - public override float Bonus => IdleBonus; + public override float Bonus => 1.0f; - public WanderAndWait(IEntity owner) : base(owner) - { - // TODO: Need a Success method that gets called to update context (e.g. when we last did X) - } + public WanderAndWait(IEntity owner) : base(owner) {} public override void SetupOperators(Blackboard context) { @@ -49,12 +47,18 @@ namespace Content.Server.AI.Utility.Actions.Idle new WaitOperator(waitTime), }); } + + protected override IReadOnlyCollection> GetConsiderations(Blackboard context) + { + var considerationsManager = IoCManager.Resolve(); - protected override Consideration[] Considerations { get; } = { - new CanMoveCon( - new BoolCurve()) - // Last wander? If we also want to sit still - }; + return new[] + { + considerationsManager.Get() + .BoolCurve(context), + + }; + } private GridCoordinates FindRandomGrid() { diff --git a/Content.Server/AI/Utility/Actions/Nutrition/Drink/PickUpDrink.cs b/Content.Server/AI/Utility/Actions/Nutrition/Drink/PickUpDrink.cs index c376641bb9..cc8f98810a 100644 --- a/Content.Server/AI/Utility/Actions/Nutrition/Drink/PickUpDrink.cs +++ b/Content.Server/AI/Utility/Actions/Nutrition/Drink/PickUpDrink.cs @@ -1,13 +1,15 @@ +using System; +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.Drink; -using Content.Server.AI.Utility.Curves; using Content.Server.AI.WorldState; using Content.Server.AI.WorldState.States; using Robust.Shared.Interfaces.GameObjects; +using Robust.Shared.IoC; namespace Content.Server.AI.Utility.Actions.Nutrition.Drink { @@ -25,25 +27,31 @@ namespace Content.Server.AI.Utility.Actions.Nutrition.Drink { ActionOperators = new GoPickupEntitySequence(Owner, _entity).Sequence; } - - protected override Consideration[] Considerations => new Consideration[] - { - new TargetAccessibleCon( - new BoolCurve()), - new FreeHandCon( - new BoolCurve()), - new ThirstCon( - new LogisticCurve(1000f, 1.3f, -1.0f, 0.5f)), - new DistanceCon( - new QuadraticCurve(-1.0f, 1.0f, 1.02f, 0.0f)), - new DrinkValueCon( - new QuadraticCurve(1.0f, 0.4f, 0.0f, 0.0f)), - }; - + protected override void UpdateBlackboard(Blackboard context) { base.UpdateBlackboard(context); context.GetState().SetValue(_entity); } + + protected override IReadOnlyCollection> GetConsiderations(Blackboard context) + { + var considerationsManager = IoCManager.Resolve(); + + return new[] + { + considerationsManager.Get() + .BoolCurve(context), + 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() + .QuadraticCurve(context, 1.0f, 0.4f, 0.0f, 0.0f), + }; + } + } } diff --git a/Content.Server/AI/Utility/Actions/Nutrition/Drink/UseDrinkInInventory.cs b/Content.Server/AI/Utility/Actions/Nutrition/Drink/UseDrinkInInventory.cs index eae360a69e..408addf0d1 100644 --- a/Content.Server/AI/Utility/Actions/Nutrition/Drink/UseDrinkInInventory.cs +++ b/Content.Server/AI/Utility/Actions/Nutrition/Drink/UseDrinkInInventory.cs @@ -1,13 +1,14 @@ +using System; 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.Nutrition.Drink; -using Content.Server.AI.Utility.Curves; using Content.Server.AI.WorldState; using Content.Server.AI.WorldState.States; using Robust.Shared.Interfaces.GameObjects; +using Robust.Shared.IoC; namespace Content.Server.AI.Utility.Actions.Nutrition.Drink { @@ -29,21 +30,26 @@ namespace Content.Server.AI.Utility.Actions.Nutrition.Drink new UseItemInHandsOperator(Owner, _entity), }); } - - protected override Consideration[] Considerations => new Consideration[] - { - new TargetInOurHandsCon( - new BoolCurve()), - new ThirstCon( - new LogisticCurve(1000f, 1.3f, -0.3f, 0.5f)), - new DrinkValueCon( - new QuadraticCurve(1.0f, 0.4f, 0.0f, 0.0f)) - }; - + protected override void UpdateBlackboard(Blackboard context) { base.UpdateBlackboard(context); context.GetState().SetValue(_entity); + } + + protected override IReadOnlyCollection> GetConsiderations(Blackboard context) + { + var considerationsManager = IoCManager.Resolve(); + + return new[] + { + 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 cd12fab1c7..4b6c54a927 100644 --- a/Content.Server/AI/Utility/Actions/Nutrition/Food/PickUpFood.cs +++ b/Content.Server/AI/Utility/Actions/Nutrition/Food/PickUpFood.cs @@ -1,13 +1,15 @@ +using System; +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; -using Content.Server.AI.Utility.Curves; +using Content.Server.AI.Utility.Considerations.Nutrition.Food; using Content.Server.AI.WorldState; using Content.Server.AI.WorldState.States; using Robust.Shared.Interfaces.GameObjects; +using Robust.Shared.IoC; namespace Content.Server.AI.Utility.Actions.Nutrition.Food { @@ -26,24 +28,29 @@ namespace Content.Server.AI.Utility.Actions.Nutrition.Food ActionOperators = new GoPickupEntitySequence(Owner, _entity).Sequence; } - protected override Consideration[] Considerations => new Consideration[] - { - new TargetAccessibleCon( - new BoolCurve()), - new FreeHandCon( - new BoolCurve()), - new HungerCon( - new LogisticCurve(1000f, 1.3f, -1.0f, 0.5f)), - new DistanceCon( - new QuadraticCurve(-1.0f, 1.0f, 1.02f, 0.0f)), - new FoodValueCon( - new QuadraticCurve(1.0f, 0.4f, 0.0f, 0.0f)), - }; - protected override void UpdateBlackboard(Blackboard context) { base.UpdateBlackboard(context); context.GetState().SetValue(_entity); + } + + protected override IReadOnlyCollection> GetConsiderations(Blackboard context) + { + var considerationsManager = IoCManager.Resolve(); + + return new[] + { + considerationsManager.Get() + .BoolCurve(context), + 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() + .QuadraticCurve(context, 1.0f, 0.4f, 0.0f, 0.0f), + }; } } } diff --git a/Content.Server/AI/Utility/Actions/Nutrition/Food/UseFoodInInventory.cs b/Content.Server/AI/Utility/Actions/Nutrition/Food/UseFoodInInventory.cs index 2996cf3769..162d69c29b 100644 --- a/Content.Server/AI/Utility/Actions/Nutrition/Food/UseFoodInInventory.cs +++ b/Content.Server/AI/Utility/Actions/Nutrition/Food/UseFoodInInventory.cs @@ -1,13 +1,15 @@ +using System; 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.Nutrition; -using Content.Server.AI.Utility.Curves; +using Content.Server.AI.Utility.Considerations.Nutrition.Food; using Content.Server.AI.WorldState; using Content.Server.AI.WorldState.States; using Robust.Shared.Interfaces.GameObjects; +using Robust.Shared.IoC; namespace Content.Server.AI.Utility.Actions.Nutrition.Food { @@ -30,20 +32,26 @@ namespace Content.Server.AI.Utility.Actions.Nutrition.Food }); } - protected override Consideration[] Considerations => new Consideration[] - { - new TargetInOurHandsCon( - new BoolCurve()), - new HungerCon( - new LogisticCurve(1000f, 1.3f, -0.3f, 0.5f)), - new FoodValueCon( - new QuadraticCurve(1.0f, 0.4f, 0.0f, 0.0f)) - }; - protected override void UpdateBlackboard(Blackboard context) { base.UpdateBlackboard(context); context.GetState().SetValue(_entity); + } + + protected override IReadOnlyCollection> GetConsiderations(Blackboard context) + { + var considerationsManager = IoCManager.Resolve(); + + return new[] + { + 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/Test/MoveRightAndLeftTen.cs b/Content.Server/AI/Utility/Actions/Test/MoveRightAndLeftTen.cs index a2f49c1c79..d2625eddb8 100644 --- a/Content.Server/AI/Utility/Actions/Test/MoveRightAndLeftTen.cs +++ b/Content.Server/AI/Utility/Actions/Test/MoveRightAndLeftTen.cs @@ -1,10 +1,11 @@ +using System; using System.Collections.Generic; using Content.Server.AI.Operators; using Content.Server.AI.Operators.Movement; using Content.Server.AI.Utility.Considerations; -using Content.Server.AI.Utility.Curves; using Content.Server.AI.WorldState; using Robust.Shared.Interfaces.GameObjects; +using Robust.Shared.IoC; using Robust.Shared.Maths; namespace Content.Server.AI.Utility.Actions.Test @@ -18,11 +19,6 @@ namespace Content.Server.AI.Utility.Actions.Test public MoveRightAndLeftTen(IEntity owner) : base(owner) {} - protected override Consideration[] Considerations { get; } = { - new DummyCon( - new BoolCurve()) - }; - public override void SetupOperators(Blackboard context) { var currentPosition = Owner.Transform.GridPosition; @@ -36,5 +32,16 @@ namespace Content.Server.AI.Utility.Actions.Test originalPosOp }); } + + protected override IReadOnlyCollection> GetConsiderations(Blackboard context) + { + var considerationsManager = IoCManager.Resolve(); + + return new[] + { + considerationsManager.Get() + .BoolCurve(context), + }; + } } } diff --git a/Content.Server/AI/Utility/Actions/UtilityAction.cs b/Content.Server/AI/Utility/Actions/UtilityAction.cs index 1d5a385beb..2453750532 100644 --- a/Content.Server/AI/Utility/Actions/UtilityAction.cs +++ b/Content.Server/AI/Utility/Actions/UtilityAction.cs @@ -3,6 +3,7 @@ using System.Collections.Generic; using Content.Server.AI.Operators; using Content.Server.AI.Utility.Considerations; using Content.Server.AI.WorldState; +using Content.Server.AI.WorldState.States.Utility; using Robust.Shared.Interfaces.GameObjects; using Robust.Shared.Utility; @@ -42,7 +43,9 @@ namespace Content.Server.AI.Utility.Actions /// All the considerations are multiplied together to get the final score; a consideration of 0.0 means the action is not possible. /// Ideally you put anything that's easy to assess and can cause an early-out first just so the rest aren't evaluated. /// - protected abstract Consideration[] Considerations { get; } + /// Uses Func as you don't want to eval the later considerations unless necessary, but we also need the total count + /// so can't use IEnumerable + protected abstract IReadOnlyCollection> GetConsiderations(Blackboard context); /// /// To keep the operators simple we can chain them together here, e.g. move to can be chained with other operators. @@ -109,7 +112,8 @@ namespace Content.Server.AI.Utility.Actions public float GetScore(Blackboard context, float min) { UpdateBlackboard(context); - DebugTools.Assert(Considerations.Length > 0); + var considerations = GetConsiderations(context); + DebugTools.Assert(considerations.Count > 0); // I used the IAUS video although I did have some confusion on how to structure it overall // as some of the slides seemed contradictory @@ -121,19 +125,14 @@ namespace Content.Server.AI.Utility.Actions // 23:00 Building a better centaur var finalScore = 1.0f; var minThreshold = min / Bonus; - var modificationFactor = 1.0f - 1.0f / Considerations.Length; + context.GetState().SetValue(considerations.Count); // See 10:09 for this and the adjustments - foreach (var consideration in Considerations) + foreach (var consideration in considerations) { - var score = consideration.GetScore(context); - var makeUpValue = (1.0f - score) * modificationFactor; - var adjustedScore = score + makeUpValue * score; - var response = consideration.ComputeResponseCurve(adjustedScore); - - finalScore *= response; - - DebugTools.Assert(!float.IsNaN(response)); + var score = consideration.Invoke(); + finalScore *= score; + DebugTools.Assert(!float.IsNaN(score)); // The score can only ever go down from each consideration so if we're below minimum no point continuing. if (0.0f >= finalScore || finalScore < minThreshold) { diff --git a/Content.Server/AI/Utility/AiLogic/UtilityAI.cs b/Content.Server/AI/Utility/AiLogic/UtilityAI.cs index e886d0ff61..5847deb850 100644 --- a/Content.Server/AI/Utility/AiLogic/UtilityAI.cs +++ b/Content.Server/AI/Utility/AiLogic/UtilityAI.cs @@ -13,6 +13,7 @@ using Content.Server.GameObjects.EntitySystems.JobQueues; using Robust.Server.AI; using Robust.Shared.Interfaces.GameObjects; using Robust.Shared.IoC; +using Robust.Shared.Log; using Robust.Shared.Utility; namespace Content.Server.AI.Utility.AiLogic @@ -147,6 +148,14 @@ namespace Content.Server.AI.Utility.AiLogic private void ReceivedAction() { + switch (_actionRequest.Exception) + { + case null: + break; + default: + Logger.FatalS("ai", _actionRequest.Exception.ToString()); + throw _actionRequest.Exception; + } var action = _actionRequest.Result; _actionRequest = null; // Actions with lower scores should be implicitly dumped by GetAction diff --git a/Content.Server/AI/Utility/Considerations/ActionBlocker/CanMoveCon.cs b/Content.Server/AI/Utility/Considerations/ActionBlocker/CanMoveCon.cs index 0a1828d495..0be12ebd50 100644 --- a/Content.Server/AI/Utility/Considerations/ActionBlocker/CanMoveCon.cs +++ b/Content.Server/AI/Utility/Considerations/ActionBlocker/CanMoveCon.cs @@ -1,4 +1,3 @@ -using Content.Server.AI.Utility.Curves; using Content.Server.AI.WorldState; using Content.Server.AI.WorldState.States; using Content.Server.GameObjects.EntitySystems; @@ -9,9 +8,7 @@ namespace Content.Server.AI.Utility.Considerations.ActionBlocker { public sealed class CanMoveCon : Consideration { - public CanMoveCon(IResponseCurve curve) : base(curve) {} - - public override float GetScore(Blackboard context) + protected override float GetScore(Blackboard context) { var self = context.GetState().GetValue(); if (!ActionBlockerSystem.CanMove(self)) diff --git a/Content.Server/AI/Utility/Considerations/Clothing/ClothingInInventoryCon.cs b/Content.Server/AI/Utility/Considerations/Clothing/ClothingInInventoryCon.cs index 7101e1ba1b..5a0dce18f6 100644 --- a/Content.Server/AI/Utility/Considerations/Clothing/ClothingInInventoryCon.cs +++ b/Content.Server/AI/Utility/Considerations/Clothing/ClothingInInventoryCon.cs @@ -1,5 +1,5 @@ -using Content.Server.AI.Utility.Curves; using Content.Server.AI.WorldState; +using Content.Server.AI.WorldState.States.Clothing; using Content.Server.AI.WorldState.States.Inventory; using Content.Server.GameObjects; using Content.Shared.GameObjects.Components.Inventory; @@ -8,25 +8,27 @@ namespace Content.Server.AI.Utility.Considerations.Clothing { public sealed class ClothingInInventoryCon : Consideration { - private readonly EquipmentSlotDefines.SlotFlags _slot; - - public ClothingInInventoryCon(EquipmentSlotDefines.SlotFlags slotFlags, IResponseCurve curve) : base(curve) + public ClothingInInventoryCon Slot(EquipmentSlotDefines.SlotFlags slotFlags, Blackboard context) { - _slot = slotFlags; + // Ideally we'd just use a variable but then if we were iterating through multiple AI at once it'd be + // Stuffed so we need to store it on the AI's context. + context.GetState().SetValue(slotFlags); + return this; } - public override float GetScore(Blackboard context) + protected override float GetScore(Blackboard context) { - var inventory = context.GetState().GetValue(); + var slots = context.GetState().GetValue(); + var slotFlags = EquipmentSlotDefines.SlotMasks[slots]; - foreach (var entity in inventory) + foreach (var entity in context.GetState().GetValue()) { if (!entity.TryGetComponent(out ClothingComponent clothingComponent)) { continue; } - if ((clothingComponent.SlotFlags & _slot) != 0) + if ((clothingComponent.SlotFlags & slotFlags) != 0) { return 1.0f; } diff --git a/Content.Server/AI/Utility/Considerations/Clothing/ClothingInSlotCon.cs b/Content.Server/AI/Utility/Considerations/Clothing/ClothingInSlotCon.cs index 11b30c0027..dfc0b548a7 100644 --- a/Content.Server/AI/Utility/Considerations/Clothing/ClothingInSlotCon.cs +++ b/Content.Server/AI/Utility/Considerations/Clothing/ClothingInSlotCon.cs @@ -1,4 +1,3 @@ -using Content.Server.AI.Utility.Curves; using Content.Server.AI.WorldState; using Content.Server.AI.WorldState.States.Clothing; using Content.Shared.GameObjects.Components.Inventory; @@ -7,18 +6,18 @@ namespace Content.Server.AI.Utility.Considerations.Clothing { public class ClothingInSlotCon : Consideration { - private EquipmentSlotDefines.Slots _slot; - public ClothingInSlotCon(EquipmentSlotDefines.Slots slot, IResponseCurve curve) : base(curve) + public ClothingInSlotCon Slot(EquipmentSlotDefines.Slots slot, Blackboard context) { - _slot = slot; + context.GetState().SetValue(slot); + return this; } - - public override float GetScore(Blackboard context) + + protected override float GetScore(Blackboard context) { + var slot = context.GetState().GetValue(); var inventory = context.GetState().GetValue(); - - return inventory.ContainsKey(_slot) ? 1.0f : 0.0f; + return inventory.ContainsKey(slot) ? 1.0f : 0.0f; } } } diff --git a/Content.Server/AI/Utility/Considerations/Combat/Melee/CanUnarmedCombatCon.cs b/Content.Server/AI/Utility/Considerations/Combat/Melee/CanUnarmedCombatCon.cs index f77e6ce5c4..ad9c4d4ea6 100644 --- a/Content.Server/AI/Utility/Considerations/Combat/Melee/CanUnarmedCombatCon.cs +++ b/Content.Server/AI/Utility/Considerations/Combat/Melee/CanUnarmedCombatCon.cs @@ -1,4 +1,3 @@ -using Content.Server.AI.Utility.Curves; using Content.Server.AI.WorldState; using Content.Server.AI.WorldState.States; using Content.Server.GameObjects.Components.Weapon.Melee; @@ -7,9 +6,7 @@ namespace Content.Server.AI.Utility.Considerations.Combat.Melee { public sealed class CanUnarmedCombatCon : Consideration { - public CanUnarmedCombatCon(IResponseCurve curve) : base(curve) {} - - public override float GetScore(Blackboard context) + protected override float GetScore(Blackboard context) { return context.GetState().GetValue().HasComponent() ? 1.0f : 0.0f; } diff --git a/Content.Server/AI/Utility/Considerations/Combat/Melee/HasMeleeWeaponCon.cs b/Content.Server/AI/Utility/Considerations/Combat/Melee/HasMeleeWeaponCon.cs index 5d9567589f..e8f9e74224 100644 --- a/Content.Server/AI/Utility/Considerations/Combat/Melee/HasMeleeWeaponCon.cs +++ b/Content.Server/AI/Utility/Considerations/Combat/Melee/HasMeleeWeaponCon.cs @@ -1,4 +1,3 @@ -using Content.Server.AI.Utility.Curves; using Content.Server.AI.WorldState; using Content.Server.AI.WorldState.States.Inventory; using Content.Server.GameObjects.Components.Weapon.Melee; @@ -7,11 +6,9 @@ namespace Content.Server.AI.Utility.Considerations.Combat.Melee { public sealed class HasMeleeWeaponCon : Consideration { - public HasMeleeWeaponCon(IResponseCurve curve) : base(curve) {} - - public override float GetScore(Blackboard context) + protected override float GetScore(Blackboard context) { - foreach (var item in context.GetState().GetValue()) + foreach (var item in context.GetState().GetValue()) { if (item.HasComponent()) { diff --git a/Content.Server/AI/Utility/Considerations/Combat/Melee/MeleeWeaponDamageCon.cs b/Content.Server/AI/Utility/Considerations/Combat/Melee/MeleeWeaponDamageCon.cs index 31165ec6c0..9f62896520 100644 --- a/Content.Server/AI/Utility/Considerations/Combat/Melee/MeleeWeaponDamageCon.cs +++ b/Content.Server/AI/Utility/Considerations/Combat/Melee/MeleeWeaponDamageCon.cs @@ -1,4 +1,3 @@ -using Content.Server.AI.Utility.Curves; using Content.Server.AI.WorldState; using Content.Server.AI.WorldState.States.Combat; using Content.Server.GameObjects.Components.Weapon.Melee; @@ -7,9 +6,7 @@ namespace Content.Server.AI.Utility.Considerations.Combat.Melee { public sealed class MeleeWeaponDamageCon : Consideration { - public MeleeWeaponDamageCon(IResponseCurve curve) : base(curve) {} - - public override float GetScore(Blackboard context) + protected override float GetScore(Blackboard context) { var target = context.GetState().GetValue(); diff --git a/Content.Server/AI/Utility/Considerations/Combat/Melee/MeleeWeaponEquippedCon.cs b/Content.Server/AI/Utility/Considerations/Combat/Melee/MeleeWeaponEquippedCon.cs index 3bca99db7a..856c8b9932 100644 --- a/Content.Server/AI/Utility/Considerations/Combat/Melee/MeleeWeaponEquippedCon.cs +++ b/Content.Server/AI/Utility/Considerations/Combat/Melee/MeleeWeaponEquippedCon.cs @@ -1,4 +1,3 @@ -using Content.Server.AI.Utility.Curves; using Content.Server.AI.WorldState; using Content.Server.AI.WorldState.States.Inventory; using Content.Server.GameObjects.Components.Weapon.Melee; @@ -7,9 +6,7 @@ namespace Content.Server.AI.Utility.Considerations.Combat.Melee { public sealed class MeleeWeaponEquippedCon : Consideration { - public MeleeWeaponEquippedCon(IResponseCurve curve) : base(curve) {} - - public override float GetScore(Blackboard context) + protected override float GetScore(Blackboard context) { var equipped = context.GetState().GetValue(); diff --git a/Content.Server/AI/Utility/Considerations/Combat/Melee/MeleeWeaponSpeedCon.cs b/Content.Server/AI/Utility/Considerations/Combat/Melee/MeleeWeaponSpeedCon.cs index 1c16870804..fc56a593f7 100644 --- a/Content.Server/AI/Utility/Considerations/Combat/Melee/MeleeWeaponSpeedCon.cs +++ b/Content.Server/AI/Utility/Considerations/Combat/Melee/MeleeWeaponSpeedCon.cs @@ -1,4 +1,3 @@ -using Content.Server.AI.Utility.Curves; using Content.Server.AI.WorldState; using Content.Server.AI.WorldState.States.Combat; using Content.Server.GameObjects.Components.Weapon.Melee; @@ -7,9 +6,7 @@ namespace Content.Server.AI.Utility.Considerations.Combat.Melee { public sealed class MeleeWeaponSpeedCon : Consideration { - public MeleeWeaponSpeedCon(IResponseCurve curve) : base(curve) {} - - public override float GetScore(Blackboard context) + protected override float GetScore(Blackboard context) { var target = context.GetState().GetValue(); diff --git a/Content.Server/AI/Utility/Considerations/Combat/TargetHealthCon.cs b/Content.Server/AI/Utility/Considerations/Combat/TargetHealthCon.cs index 5f02a42ac2..96db4f5f35 100644 --- a/Content.Server/AI/Utility/Considerations/Combat/TargetHealthCon.cs +++ b/Content.Server/AI/Utility/Considerations/Combat/TargetHealthCon.cs @@ -1,4 +1,3 @@ -using Content.Server.AI.Utility.Curves; using Content.Server.AI.WorldState; using Content.Server.AI.WorldState.States; using Content.Server.GameObjects; @@ -8,9 +7,7 @@ namespace Content.Server.AI.Utility.Considerations.Combat { public sealed class TargetHealthCon : Consideration { - public TargetHealthCon(IResponseCurve curve) : base(curve) {} - - public override float GetScore(Blackboard context) + protected override float GetScore(Blackboard context) { var target = context.GetState().GetValue(); diff --git a/Content.Server/AI/Utility/Considerations/Combat/TargetIsCritCon.cs b/Content.Server/AI/Utility/Considerations/Combat/TargetIsCritCon.cs index 7528323e9f..0fd1990748 100644 --- a/Content.Server/AI/Utility/Considerations/Combat/TargetIsCritCon.cs +++ b/Content.Server/AI/Utility/Considerations/Combat/TargetIsCritCon.cs @@ -1,16 +1,12 @@ -using Content.Server.AI.Utility.Curves; using Content.Server.AI.WorldState; using Content.Server.AI.WorldState.States; using Content.Server.GameObjects; -using Content.Shared.GameObjects; namespace Content.Server.AI.Utility.Considerations.Combat { public sealed class TargetIsCritCon : Consideration { - public TargetIsCritCon(IResponseCurve curve) : base(curve) {} - - public override float GetScore(Blackboard context) + protected override float GetScore(Blackboard context) { var target = context.GetState().GetValue(); diff --git a/Content.Server/AI/Utility/Considerations/Combat/TargetIsDeadCon.cs b/Content.Server/AI/Utility/Considerations/Combat/TargetIsDeadCon.cs index c3c7ebc80c..8cdf0b520b 100644 --- a/Content.Server/AI/Utility/Considerations/Combat/TargetIsDeadCon.cs +++ b/Content.Server/AI/Utility/Considerations/Combat/TargetIsDeadCon.cs @@ -1,4 +1,3 @@ -using Content.Server.AI.Utility.Curves; using Content.Server.AI.WorldState; using Content.Server.AI.WorldState.States; using Content.Server.GameObjects; @@ -7,9 +6,7 @@ namespace Content.Server.AI.Utility.Considerations.Combat { public sealed class TargetIsDeadCon : Consideration { - public TargetIsDeadCon(IResponseCurve curve) : base(curve) {} - - public override float GetScore(Blackboard context) + protected override float GetScore(Blackboard context) { var target = context.GetState().GetValue(); diff --git a/Content.Server/AI/Utility/Considerations/Consideration.cs b/Content.Server/AI/Utility/Considerations/Consideration.cs index 25694ec5e7..4e49b58cb9 100644 --- a/Content.Server/AI/Utility/Considerations/Consideration.cs +++ b/Content.Server/AI/Utility/Considerations/Consideration.cs @@ -1,25 +1,67 @@ using System; -using Content.Server.AI.Utility.Curves; using Content.Server.AI.WorldState; +using Content.Server.AI.WorldState.States.Utility; namespace Content.Server.AI.Utility.Considerations { public abstract class Consideration { - protected IResponseCurve Curve { get; } + protected abstract float GetScore(Blackboard context); - public Consideration(IResponseCurve curve) + private float GetAdjustedScore(Blackboard context) { - Curve = curve; + var score = GetScore(context); + var considerationsCount = context.GetState().GetValue(); + var modificationFactor = 1.0f - 1.0f / considerationsCount; + var makeUpValue = (1.0f - score) * modificationFactor; + var adjustedScore = score + makeUpValue * score; + return Math.Clamp(adjustedScore, 0.0f, 1.0f); } - public abstract float GetScore(Blackboard context); - - public float ComputeResponseCurve(float score) + public Func BoolCurve(Blackboard context) { - var clampedScore = Math.Clamp(score, 0.0f, 1.0f); - var curvedResponse = Math.Clamp(Curve.GetResponse(clampedScore), 0.0f, 1.0f); - return curvedResponse; + float Result() + { + var adjustedScore = GetAdjustedScore(context); + // ReSharper disable once CompareOfFloatsByEqualityOperator + return adjustedScore == 1.0f ? 1.0f : 0.0f; + } + + return Result; + } + + public Func InverseBoolCurve(Blackboard context) + { + float Result() + { + var adjustedScore = GetAdjustedScore(context); + // ReSharper disable once CompareOfFloatsByEqualityOperator + return adjustedScore == 1.0f ? 0.0f : 1.0f; + } + + return Result; + } + + 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 Result; + } + + 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 Result; } } } diff --git a/Content.Server/AI/Utility/Considerations/ConsiderationsManager.cs b/Content.Server/AI/Utility/Considerations/ConsiderationsManager.cs new file mode 100644 index 0000000000..1ff677f402 --- /dev/null +++ b/Content.Server/AI/Utility/Considerations/ConsiderationsManager.cs @@ -0,0 +1,29 @@ +using System; +using System.Collections.Generic; +using Robust.Shared.Interfaces.Reflection; +using Robust.Shared.IoC; + +namespace Content.Server.AI.Utility.Considerations +{ + public class ConsiderationsManager + { + private Dictionary _considerations = new Dictionary(); + + public void Initialize() + { + var reflectionManager = IoCManager.Resolve(); + var typeFactory = IoCManager.Resolve(); + + foreach (var conType in reflectionManager.GetAllChildren(typeof(Consideration))) + { + var con = (Consideration) typeFactory.CreateInstance(conType); + _considerations.Add(conType, con); + } + } + + public T Get() where T : Consideration + { + return (T) _considerations[typeof(T)]; + } + } +} \ No newline at end of file diff --git a/Content.Server/AI/Utility/Considerations/Containers/TargetAccessibleCon.cs b/Content.Server/AI/Utility/Considerations/Containers/TargetAccessibleCon.cs index 4265db6abd..d9bbd31e09 100644 --- a/Content.Server/AI/Utility/Considerations/Containers/TargetAccessibleCon.cs +++ b/Content.Server/AI/Utility/Considerations/Containers/TargetAccessibleCon.cs @@ -1,7 +1,5 @@ -using Content.Server.AI.Utility.Curves; using Content.Server.AI.WorldState; using Content.Server.AI.WorldState.States; -using Content.Server.GameObjects; using Content.Server.GameObjects.Components; using Robust.Shared.Containers; @@ -12,9 +10,7 @@ namespace Content.Server.AI.Utility.Considerations.Containers /// public sealed class TargetAccessibleCon : Consideration { - public TargetAccessibleCon(IResponseCurve curve) : base(curve) {} - - public override float GetScore(Blackboard context) + protected override float GetScore(Blackboard context) { var target = context.GetState().GetValue(); if (target == null) diff --git a/Content.Server/AI/Utility/Considerations/DummyCon.cs b/Content.Server/AI/Utility/Considerations/DummyCon.cs index 07d0587ddb..91e9135f50 100644 --- a/Content.Server/AI/Utility/Considerations/DummyCon.cs +++ b/Content.Server/AI/Utility/Considerations/DummyCon.cs @@ -1,12 +1,9 @@ -using Content.Server.AI.Utility.Curves; using Content.Server.AI.WorldState; namespace Content.Server.AI.Utility.Considerations { public class DummyCon : Consideration { - public DummyCon(IResponseCurve curve) : base(curve) {} - - public override float GetScore(Blackboard context) => 1.0f; + protected override float GetScore(Blackboard context) => 1.0f; } } diff --git a/Content.Server/AI/Utility/Considerations/Hands/FreeHandCon.cs b/Content.Server/AI/Utility/Considerations/Hands/FreeHandCon.cs index 2b2162d80f..ba968bfe25 100644 --- a/Content.Server/AI/Utility/Considerations/Hands/FreeHandCon.cs +++ b/Content.Server/AI/Utility/Considerations/Hands/FreeHandCon.cs @@ -1,4 +1,3 @@ -using Content.Server.AI.Utility.Curves; using Content.Server.AI.WorldState; using Content.Server.AI.WorldState.States; using Content.Server.GameObjects; @@ -7,9 +6,7 @@ namespace Content.Server.AI.Utility.Considerations.Hands { public class FreeHandCon : Consideration { - public FreeHandCon(IResponseCurve curve) : base(curve) {} - - public override float GetScore(Blackboard context) + protected override float GetScore(Blackboard context) { var owner = context.GetState().GetValue(); diff --git a/Content.Server/AI/Utility/Considerations/Hands/TargetInOurHandsCon.cs b/Content.Server/AI/Utility/Considerations/Hands/TargetInOurHandsCon.cs index cda872a05b..6054e93373 100644 --- a/Content.Server/AI/Utility/Considerations/Hands/TargetInOurHandsCon.cs +++ b/Content.Server/AI/Utility/Considerations/Hands/TargetInOurHandsCon.cs @@ -1,4 +1,3 @@ -using Content.Server.AI.Utility.Curves; using Content.Server.AI.WorldState; using Content.Server.AI.WorldState.States; using Content.Server.GameObjects; @@ -10,9 +9,7 @@ namespace Content.Server.AI.Utility.Considerations.Hands /// public sealed class TargetInOurHandsCon : Consideration { - public TargetInOurHandsCon(IResponseCurve curve) : base(curve) {} - - public override float GetScore(Blackboard context) + protected override float GetScore(Blackboard context) { var owner = context.GetState().GetValue(); var target = context.GetState().GetValue(); diff --git a/Content.Server/AI/Utility/Considerations/Inventory/CanPutTargetInHandsCon.cs b/Content.Server/AI/Utility/Considerations/Inventory/CanPutTargetInHandsCon.cs index 646cba8506..ed0aea239b 100644 --- a/Content.Server/AI/Utility/Considerations/Inventory/CanPutTargetInHandsCon.cs +++ b/Content.Server/AI/Utility/Considerations/Inventory/CanPutTargetInHandsCon.cs @@ -1,4 +1,3 @@ -using Content.Server.AI.Utility.Curves; using Content.Server.AI.WorldState; using Content.Server.AI.WorldState.States; using Content.Server.AI.WorldState.States.Hands; @@ -9,9 +8,7 @@ namespace Content.Server.AI.Utility.Considerations.Inventory { public class CanPutTargetInHandsCon : Consideration { - public CanPutTargetInHandsCon(IResponseCurve curve) : base(curve) {} - - public override float GetScore(Blackboard context) + protected override float GetScore(Blackboard context) { // First check if target in inventory already // If not then check if we have a free hand @@ -22,9 +19,7 @@ namespace Content.Server.AI.Utility.Considerations.Inventory return 0.0f; } - var inventory = context.GetState().GetValue(); - - foreach (var item in inventory) + foreach (var item in context.GetState().GetValue()) { if (item == target) { diff --git a/Content.Server/AI/Utility/Considerations/Inventory/TargetInOurInventoryCon.cs b/Content.Server/AI/Utility/Considerations/Inventory/TargetInOurInventoryCon.cs index 1bd645df23..a081f442a8 100644 --- a/Content.Server/AI/Utility/Considerations/Inventory/TargetInOurInventoryCon.cs +++ b/Content.Server/AI/Utility/Considerations/Inventory/TargetInOurInventoryCon.cs @@ -1,4 +1,3 @@ -using Content.Server.AI.Utility.Curves; using Content.Server.AI.WorldState; using Content.Server.AI.WorldState.States; using Content.Server.AI.WorldState.States.Inventory; @@ -8,11 +7,8 @@ namespace Content.Server.AI.Utility.Considerations.Inventory { public class TargetInOurInventoryCon : Consideration { - public TargetInOurInventoryCon(IResponseCurve curve) : base(curve) {} - - public override float GetScore(Blackboard context) + protected override float GetScore(Blackboard context) { - var inventory = context.GetState().GetValue(); var target = context.GetState().GetValue(); if (target == null || !target.HasComponent()) @@ -20,7 +16,7 @@ namespace Content.Server.AI.Utility.Considerations.Inventory return 0.0f; } - foreach (var item in inventory) + foreach (var item in context.GetState().GetValue()) { if (item == target) { diff --git a/Content.Server/AI/Utility/Considerations/Movement/DistanceCon.cs b/Content.Server/AI/Utility/Considerations/Movement/DistanceCon.cs index b8dfee7354..7b099bfcd0 100644 --- a/Content.Server/AI/Utility/Considerations/Movement/DistanceCon.cs +++ b/Content.Server/AI/Utility/Considerations/Movement/DistanceCon.cs @@ -1,4 +1,3 @@ -using Content.Server.AI.Utility.Curves; using Content.Server.AI.WorldState; using Content.Server.AI.WorldState.States; @@ -6,9 +5,7 @@ namespace Content.Server.AI.Utility.Considerations.Movement { public sealed class DistanceCon : Consideration { - public DistanceCon(IResponseCurve curve) : base(curve) {} - - public override float GetScore(Blackboard context) + protected override float GetScore(Blackboard context) { var self = context.GetState().GetValue(); var target = context.GetState().GetValue(); diff --git a/Content.Server/AI/Utility/Considerations/Nutrition/Drink/DrinkValueCon.cs b/Content.Server/AI/Utility/Considerations/Nutrition/Drink/DrinkValueCon.cs index 73e6505e7e..b69f9a53ad 100644 --- a/Content.Server/AI/Utility/Considerations/Nutrition/Drink/DrinkValueCon.cs +++ b/Content.Server/AI/Utility/Considerations/Nutrition/Drink/DrinkValueCon.cs @@ -1,4 +1,3 @@ -using Content.Server.AI.Utility.Curves; using Content.Server.AI.WorldState; using Content.Server.AI.WorldState.States; using Content.Server.GameObjects.Components.Chemistry; @@ -7,9 +6,7 @@ namespace Content.Server.AI.Utility.Considerations.Nutrition.Drink { public sealed class DrinkValueCon : Consideration { - public DrinkValueCon(IResponseCurve curve) : base(curve) {} - - public override float GetScore(Blackboard context) + protected override float GetScore(Blackboard context) { var target = context.GetState().GetValue(); diff --git a/Content.Server/AI/Utility/Considerations/Nutrition/Drink/ThirstCon.cs b/Content.Server/AI/Utility/Considerations/Nutrition/Drink/ThirstCon.cs index e2c387fbbc..b228d16026 100644 --- a/Content.Server/AI/Utility/Considerations/Nutrition/Drink/ThirstCon.cs +++ b/Content.Server/AI/Utility/Considerations/Nutrition/Drink/ThirstCon.cs @@ -1,4 +1,3 @@ -using Content.Server.AI.Utility.Curves; using Content.Server.AI.WorldState; using Content.Server.AI.WorldState.States; using Content.Server.GameObjects.Components.Nutrition; @@ -8,9 +7,7 @@ namespace Content.Server.AI.Utility.Considerations.Nutrition.Drink { public class ThirstCon : Consideration { - public ThirstCon(IResponseCurve curve) : base(curve) {} - - public override float GetScore(Blackboard context) + protected override float GetScore(Blackboard context) { var owner = context.GetState().GetValue(); diff --git a/Content.Server/AI/Utility/Considerations/Nutrition/Food/FoodValueCon.cs b/Content.Server/AI/Utility/Considerations/Nutrition/Food/FoodValueCon.cs index a316799c3d..78277572ae 100644 --- a/Content.Server/AI/Utility/Considerations/Nutrition/Food/FoodValueCon.cs +++ b/Content.Server/AI/Utility/Considerations/Nutrition/Food/FoodValueCon.cs @@ -1,15 +1,12 @@ -using Content.Server.AI.Utility.Curves; using Content.Server.AI.WorldState; using Content.Server.AI.WorldState.States; using Content.Server.GameObjects.Components.Chemistry; -namespace Content.Server.AI.Utility.Considerations.Nutrition +namespace Content.Server.AI.Utility.Considerations.Nutrition.Food { public sealed class FoodValueCon : Consideration { - public FoodValueCon(IResponseCurve curve) : base(curve) {} - - public override float GetScore(Blackboard context) + protected override float GetScore(Blackboard context) { var target = context.GetState().GetValue(); diff --git a/Content.Server/AI/Utility/Considerations/Nutrition/Food/HungerCon.cs b/Content.Server/AI/Utility/Considerations/Nutrition/Food/HungerCon.cs index 2d154e12f5..a09eff2924 100644 --- a/Content.Server/AI/Utility/Considerations/Nutrition/Food/HungerCon.cs +++ b/Content.Server/AI/Utility/Considerations/Nutrition/Food/HungerCon.cs @@ -1,17 +1,14 @@ -using Content.Server.AI.Utility.Curves; using Content.Server.AI.WorldState; using Content.Server.AI.WorldState.States; using Content.Server.GameObjects.Components.Nutrition; using Content.Shared.GameObjects.Components.Nutrition; -namespace Content.Server.AI.Utility.Considerations.Nutrition +namespace Content.Server.AI.Utility.Considerations.Nutrition.Food { public sealed class HungerCon : Consideration { - public HungerCon(IResponseCurve curve) : base(curve) {} - - public override float GetScore(Blackboard context) + protected override float GetScore(Blackboard context) { var owner = context.GetState().GetValue(); diff --git a/Content.Server/AI/Utility/Considerations/State/StoredStateEntityIsNullCon.cs b/Content.Server/AI/Utility/Considerations/State/StoredStateEntityIsNullCon.cs new file mode 100644 index 0000000000..a2750b6ed1 --- /dev/null +++ b/Content.Server/AI/Utility/Considerations/State/StoredStateEntityIsNullCon.cs @@ -0,0 +1,26 @@ +using System; +using Content.Server.AI.WorldState; +using Content.Server.AI.WorldState.States.Utility; + +namespace Content.Server.AI.Utility.Considerations.State +{ + /// + /// Simple NullCheck on a StoredState + /// + public sealed class StoredStateEntityIsNullCon : Consideration + { + public StoredStateEntityIsNullCon Set(Type type, Blackboard context) + { + // Ideally we'd just use a variable but then if we were iterating through multiple AI at once it'd be + // Stuffed so we need to store it on the AI's context. + context.GetState().SetValue(type); + return this; + } + + protected override float GetScore(Blackboard context) + { + var stateData = context.GetState().GetValue(); + return stateData == null ? 1.0f : 0.0f; + } + } +} \ No newline at end of file diff --git a/Content.Server/AI/Utility/Considerations/State/StoredStateIsNullCon.cs b/Content.Server/AI/Utility/Considerations/State/StoredStateIsNullCon.cs deleted file mode 100644 index b93757bf9e..0000000000 --- a/Content.Server/AI/Utility/Considerations/State/StoredStateIsNullCon.cs +++ /dev/null @@ -1,24 +0,0 @@ -using Content.Server.AI.Utility.Curves; -using Content.Server.AI.WorldState; - -namespace Content.Server.AI.Utility.Considerations.State -{ - /// - /// Simple NullCheck on a StoredState - /// - public sealed class StoredStateIsNullCon : Consideration where T : StoredStateData - { - public StoredStateIsNullCon(IResponseCurve curve) : base(curve) {} - - public override float GetScore(Blackboard context) - { - var state = context.GetState(); - if (state.GetValue() == null) - { - return 1.0f; - } - - return 0.0f; - } - } -} \ No newline at end of file diff --git a/Content.Server/AI/Utility/ExpandableActions/Clothing/Gloves/EquipAnyGlovesExp.cs b/Content.Server/AI/Utility/ExpandableActions/Clothing/Gloves/EquipAnyGlovesExp.cs index 700dff2f94..4a8e10b0a6 100644 --- a/Content.Server/AI/Utility/ExpandableActions/Clothing/Gloves/EquipAnyGlovesExp.cs +++ b/Content.Server/AI/Utility/ExpandableActions/Clothing/Gloves/EquipAnyGlovesExp.cs @@ -21,12 +21,8 @@ namespace Content.Server.AI.Utility.ExpandableActions.Clothing.Gloves public override IEnumerable GetActions(Blackboard context) { var owner = context.GetState().GetValue(); - if (!owner.TryGetComponent(out AiControllerComponent controller)) - { - throw new InvalidOperationException(); - } - foreach (var entity in context.GetState().GetValue()) + foreach (var entity in context.GetState().GetValue()) { if (entity.TryGetComponent(out ClothingComponent clothing) && (clothing.SlotFlags & EquipmentSlotDefines.SlotFlags.GLOVES) != 0) diff --git a/Content.Server/AI/Utility/ExpandableActions/Clothing/Head/EquipAnyHeadExp.cs b/Content.Server/AI/Utility/ExpandableActions/Clothing/Head/EquipAnyHeadExp.cs index f885e7818a..60c6f1164b 100644 --- a/Content.Server/AI/Utility/ExpandableActions/Clothing/Head/EquipAnyHeadExp.cs +++ b/Content.Server/AI/Utility/ExpandableActions/Clothing/Head/EquipAnyHeadExp.cs @@ -22,7 +22,7 @@ namespace Content.Server.AI.Utility.ExpandableActions.Clothing.Head { var owner = context.GetState().GetValue(); - foreach (var entity in context.GetState().GetValue()) + foreach (var entity in context.GetState().GetValue()) { if (entity.TryGetComponent(out ClothingComponent clothing) && (clothing.SlotFlags & EquipmentSlotDefines.SlotFlags.HEAD) != 0) diff --git a/Content.Server/AI/Utility/ExpandableActions/Clothing/Head/PickUpAnyNearbyHeadExp.cs b/Content.Server/AI/Utility/ExpandableActions/Clothing/Head/PickUpAnyNearbyHeadExp.cs index dfb2f6d2a9..85806e99ee 100644 --- a/Content.Server/AI/Utility/ExpandableActions/Clothing/Head/PickUpAnyNearbyHeadExp.cs +++ b/Content.Server/AI/Utility/ExpandableActions/Clothing/Head/PickUpAnyNearbyHeadExp.cs @@ -1,3 +1,4 @@ +using System; using System.Collections.Generic; using Content.Server.AI.Utility.Actions; using Content.Server.AI.Utility.Actions.Clothing.Head; @@ -5,6 +6,7 @@ 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; namespace Content.Server.AI.Utility.ExpandableActions.Clothing.Head @@ -16,6 +18,7 @@ namespace Content.Server.AI.Utility.ExpandableActions.Clothing.Head 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/OuterClothing/EquipAnyOuterClothingExp.cs b/Content.Server/AI/Utility/ExpandableActions/Clothing/OuterClothing/EquipAnyOuterClothingExp.cs index b7a7980974..007b801d27 100644 --- a/Content.Server/AI/Utility/ExpandableActions/Clothing/OuterClothing/EquipAnyOuterClothingExp.cs +++ b/Content.Server/AI/Utility/ExpandableActions/Clothing/OuterClothing/EquipAnyOuterClothingExp.cs @@ -1,3 +1,4 @@ +using System; using System.Collections.Generic; using Content.Server.AI.Utility.Actions; using Content.Server.AI.Utility.Actions.Clothing.OuterClothing; @@ -5,6 +6,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.Movement; using Content.Shared.GameObjects.Components.Inventory; namespace Content.Server.AI.Utility.ExpandableActions.Clothing.OuterClothing @@ -20,7 +22,7 @@ namespace Content.Server.AI.Utility.ExpandableActions.Clothing.OuterClothing { var owner = context.GetState().GetValue(); - foreach (var entity in context.GetState().GetValue()) + foreach (var entity in context.GetState().GetValue()) { if (entity.TryGetComponent(out ClothingComponent clothing) && (clothing.SlotFlags & EquipmentSlotDefines.SlotFlags.OUTERCLOTHING) != 0) diff --git a/Content.Server/AI/Utility/ExpandableActions/Clothing/Shoes/EquipAnyShoesExp.cs b/Content.Server/AI/Utility/ExpandableActions/Clothing/Shoes/EquipAnyShoesExp.cs index 517fd735c0..f750fba71a 100644 --- a/Content.Server/AI/Utility/ExpandableActions/Clothing/Shoes/EquipAnyShoesExp.cs +++ b/Content.Server/AI/Utility/ExpandableActions/Clothing/Shoes/EquipAnyShoesExp.cs @@ -1,3 +1,4 @@ +using System; using System.Collections.Generic; using Content.Server.AI.Utility.Actions; using Content.Server.AI.Utility.Actions.Clothing.Shoes; @@ -5,6 +6,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.Movement; using Content.Shared.GameObjects.Components.Inventory; namespace Content.Server.AI.Utility.ExpandableActions.Clothing.Shoes @@ -20,7 +22,7 @@ namespace Content.Server.AI.Utility.ExpandableActions.Clothing.Shoes { var owner = context.GetState().GetValue(); - foreach (var entity in context.GetState().GetValue()) + foreach (var entity in context.GetState().GetValue()) { if (entity.TryGetComponent(out ClothingComponent clothing) && (clothing.SlotFlags & EquipmentSlotDefines.SlotFlags.SHOES) != 0) diff --git a/Content.Server/AI/Utility/ExpandableActions/Combat/Melee/EquipMeleeExp.cs b/Content.Server/AI/Utility/ExpandableActions/Combat/Melee/EquipMeleeExp.cs index 67bfac1c98..d0aade8647 100644 --- a/Content.Server/AI/Utility/ExpandableActions/Combat/Melee/EquipMeleeExp.cs +++ b/Content.Server/AI/Utility/ExpandableActions/Combat/Melee/EquipMeleeExp.cs @@ -4,6 +4,7 @@ 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.Inventory; +using Content.Server.GameObjects.Components.Weapon.Melee; namespace Content.Server.AI.Utility.ExpandableActions.Combat.Melee { @@ -15,8 +16,13 @@ namespace Content.Server.AI.Utility.ExpandableActions.Combat.Melee { var owner = context.GetState().GetValue(); - foreach (var entity in context.GetState().GetValue()) + foreach (var entity in context.GetState().GetValue()) { + if (!entity.HasComponent()) + { + continue; + } + yield return new EquipMelee(owner, entity, Bonus); } } diff --git a/Content.Server/AI/Utility/ExpandableActions/Nutrition/UseDrinkInHandsExp.cs b/Content.Server/AI/Utility/ExpandableActions/Nutrition/UseDrinkInHandsExp.cs index 830249bf89..fac523cd96 100644 --- a/Content.Server/AI/Utility/ExpandableActions/Nutrition/UseDrinkInHandsExp.cs +++ b/Content.Server/AI/Utility/ExpandableActions/Nutrition/UseDrinkInHandsExp.cs @@ -4,6 +4,7 @@ using Content.Server.AI.Utility.Actions.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; namespace Content.Server.AI.Utility.ExpandableActions.Nutrition { @@ -15,8 +16,13 @@ namespace Content.Server.AI.Utility.ExpandableActions.Nutrition { var owner = context.GetState().GetValue(); - foreach (var entity in context.GetState().GetValue()) + foreach (var entity in context.GetState().GetValue()) { + if (!entity.HasComponent()) + { + continue; + } + yield return new UseDrinkInInventory(owner, entity, Bonus); } } diff --git a/Content.Server/AI/Utility/ExpandableActions/Nutrition/UseFoodInInventoryExp.cs b/Content.Server/AI/Utility/ExpandableActions/Nutrition/UseFoodInInventoryExp.cs index 69e32c7f2f..2df0385f6f 100644 --- a/Content.Server/AI/Utility/ExpandableActions/Nutrition/UseFoodInInventoryExp.cs +++ b/Content.Server/AI/Utility/ExpandableActions/Nutrition/UseFoodInInventoryExp.cs @@ -4,6 +4,7 @@ using Content.Server.AI.Utility.Actions.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; namespace Content.Server.AI.Utility.ExpandableActions.Nutrition { @@ -15,8 +16,13 @@ namespace Content.Server.AI.Utility.ExpandableActions.Nutrition { var owner = context.GetState().GetValue(); - foreach (var entity in context.GetState().GetValue()) + foreach (var entity in context.GetState().GetValue()) { + if (!entity.HasComponent()) + { + continue; + } + yield return new UseFoodInInventory(owner, entity, Bonus); } } diff --git a/Content.Server/AI/WorldState/Blackboard.cs b/Content.Server/AI/WorldState/Blackboard.cs index b40daa2baa..160a65875d 100644 --- a/Content.Server/AI/WorldState/Blackboard.cs +++ b/Content.Server/AI/WorldState/Blackboard.cs @@ -56,6 +56,11 @@ namespace Content.Server.AI.WorldState } } + public void GetState(Type type, out IAiState state) + { + state = _states[type]; + } + /// /// Get the AI state class /// diff --git a/Content.Server/AI/WorldState/StateData.cs b/Content.Server/AI/WorldState/StateData.cs index cc55f767e7..4acf5c00eb 100644 --- a/Content.Server/AI/WorldState/StateData.cs +++ b/Content.Server/AI/WorldState/StateData.cs @@ -1,6 +1,9 @@ using System; using System.Collections.Generic; +using Content.Server.Interfaces.GameTicking; using Robust.Shared.Interfaces.GameObjects; +using Robust.Shared.Interfaces.Timing; +using Robust.Shared.IoC; namespace Content.Server.AI.WorldState { @@ -22,6 +25,11 @@ namespace Content.Server.AI.WorldState void CheckCache(); } + public interface IStoredState + { + + } + /// /// The default class for state values. Also see CachedStateData and PlanningStateData /// @@ -44,7 +52,7 @@ namespace Content.Server.AI.WorldState /// Useful for group blackboard sharing or to avoid repeating the same action (e.g. bark phrases). /// /// - public abstract class StoredStateData : IAiState + public abstract class StoredStateData : IAiState, IStoredState { // Probably not the best class name but couldn't think of anything better public abstract string Name { get; } @@ -108,11 +116,11 @@ namespace Content.Server.AI.WorldState protected IEntity Owner { get; private set; } private bool _cached; protected T Value; - private DateTime _lastCache = DateTime.Now; + private TimeSpan _lastCache = TimeSpan.Zero; /// /// How long something stays in the cache before new values are retrieved /// - protected float CacheTime { get; set; } = 2.0f; + protected double CacheTime { get; set; } = 2.0f; public void Setup(IEntity owner) { @@ -121,7 +129,9 @@ namespace Content.Server.AI.WorldState public void CheckCache() { - if (!_cached || (DateTime.Now - _lastCache).TotalSeconds >= CacheTime) + var curTime = IoCManager.Resolve().CurTime; + + if (!_cached || (curTime - _lastCache).TotalSeconds >= CacheTime) { _cached = false; return; @@ -142,7 +152,7 @@ namespace Content.Server.AI.WorldState { Value = GetTrueValue(); _cached = true; - _lastCache = DateTime.Now; + _lastCache = IoCManager.Resolve().CurTime; } return Value; diff --git a/Content.Server/AI/WorldState/States/Clothing/ClothingSlotConState.cs b/Content.Server/AI/WorldState/States/Clothing/ClothingSlotConState.cs new file mode 100644 index 0000000000..e1f87353d7 --- /dev/null +++ b/Content.Server/AI/WorldState/States/Clothing/ClothingSlotConState.cs @@ -0,0 +1,13 @@ +using Content.Shared.GameObjects.Components.Inventory; + +namespace Content.Server.AI.WorldState.States.Clothing +{ + public sealed class ClothingSlotConState : PlanningStateData + { + public override string Name => "ClothingSlotCon"; + public override void Reset() + { + Value = EquipmentSlotDefines.Slots.NONE; + } + } +} \ No newline at end of file diff --git a/Content.Server/AI/WorldState/States/Clothing/ClothingSlotFlagConState.cs b/Content.Server/AI/WorldState/States/Clothing/ClothingSlotFlagConState.cs new file mode 100644 index 0000000000..6af98349a0 --- /dev/null +++ b/Content.Server/AI/WorldState/States/Clothing/ClothingSlotFlagConState.cs @@ -0,0 +1,13 @@ +using Content.Shared.GameObjects.Components.Inventory; + +namespace Content.Server.AI.WorldState.States.Clothing +{ + public sealed class ClothingSlotFlagConState : PlanningStateData + { + public override string Name => "ClothingSlotFlagCon"; + public override void Reset() + { + Value = EquipmentSlotDefines.SlotFlags.NONE; + } + } +} \ No newline at end of file diff --git a/Content.Server/AI/WorldState/States/Inventory/InventoryState.cs b/Content.Server/AI/WorldState/States/Inventory/InventoryState.cs index d139eac9cf..347dc0402e 100644 --- a/Content.Server/AI/WorldState/States/Inventory/InventoryState.cs +++ b/Content.Server/AI/WorldState/States/Inventory/InventoryState.cs @@ -6,25 +6,19 @@ using Robust.Shared.Interfaces.GameObjects; namespace Content.Server.AI.WorldState.States.Inventory { [UsedImplicitly] - public sealed class InventoryState : StateData> + public sealed class EnumerableInventoryState : StateData> { - public override string Name => "Inventory"; + public override string Name => "EnumerableInventory"; - public override List GetValue() + public override IEnumerable GetValue() { - var inventory = new List(); - if (Owner.TryGetComponent(out HandsComponent handsComponent)) { foreach (var item in handsComponent.GetAllHeldItems()) { - inventory.Add(item.Owner); + yield return item.Owner; } } - - // TODO: InventoryComponent (Pockets were throwing) - - return inventory; } } } diff --git a/Content.Server/AI/WorldState/States/Utility/ConsiderationState.cs b/Content.Server/AI/WorldState/States/Utility/ConsiderationState.cs new file mode 100644 index 0000000000..66903bee54 --- /dev/null +++ b/Content.Server/AI/WorldState/States/Utility/ConsiderationState.cs @@ -0,0 +1,10 @@ +namespace Content.Server.AI.WorldState.States.Utility +{ + /// + /// Used by the utility AI to calc the adjusted scores + /// + public class ConsiderationState : StoredStateData + { + public override string Name => "Consideration"; + } +} \ No newline at end of file diff --git a/Content.Server/AI/WorldState/States/Utility/StoredStateIsNullState.cs b/Content.Server/AI/WorldState/States/Utility/StoredStateIsNullState.cs new file mode 100644 index 0000000000..9893af3258 --- /dev/null +++ b/Content.Server/AI/WorldState/States/Utility/StoredStateIsNullState.cs @@ -0,0 +1,13 @@ +using System; + +namespace Content.Server.AI.WorldState.States.Utility +{ + public sealed class StoredStateIsNullState : PlanningStateData + { + public override string Name => "StoredStateIsNull"; + public override void Reset() + { + Value = null; + } + } +} \ No newline at end of file diff --git a/Content.Server/EntryPoint.cs b/Content.Server/EntryPoint.cs index b7220dc612..9bf2032e06 100644 --- a/Content.Server/EntryPoint.cs +++ b/Content.Server/EntryPoint.cs @@ -1,4 +1,5 @@ -using Content.Server.GameObjects.Components.NodeContainer.NodeGroups; +using Content.Server.AI.Utility.Considerations; + using Content.Server.GameObjects.Components.NodeContainer.NodeGroups; using Content.Server.GameObjects.Components.NodeContainer.Nodes; using Content.Server.Interfaces; using Content.Server.AI.WorldState; @@ -72,6 +73,7 @@ namespace Content.Server _gameTicker.Initialize(); IoCManager.Resolve().Initialize(); IoCManager.Resolve().Initialize(); + IoCManager.Resolve().Initialize(); IoCManager.Resolve().Initialize(); } diff --git a/Content.Server/ServerContentIoC.cs b/Content.Server/ServerContentIoC.cs index 5af7382d2c..fba59dfaf0 100644 --- a/Content.Server/ServerContentIoC.cs +++ b/Content.Server/ServerContentIoC.cs @@ -1,4 +1,5 @@ -using Content.Server.AI.WorldState; +using Content.Server.AI.Utility.Considerations; +using Content.Server.AI.WorldState; using Content.Server.Cargo; using Content.Server.Chat; using Content.Server.GameTicking; @@ -37,6 +38,7 @@ namespace Content.Server IoCManager.Register(); IoCManager.Register(); IoCManager.Register(); + IoCManager.Register(); } } } From e7d756811e4b4f2d9c45e9b34e476a48147ead2e Mon Sep 17 00:00:00 2001 From: DrSmugleaf Date: Wed, 8 Jul 2020 01:41:20 +0200 Subject: [PATCH 09/19] Replace CanBeNull annotations with nullable reference types (#1270) Co-authored-by: Pieter-Jan Briers --- Content.Client/ClickMapManager.cs | 3 +- .../Components/ClickableComponent.cs | 3 +- .../Instruments/InstrumentComponent.cs | 36 ++++++---------- .../Components/Mobs/StatusControl.cs | 6 +-- .../Components/Mobs/StunnableComponent.cs | 3 +- .../Movement/PlayerInputMoverComponent.cs | 5 +-- .../Components/Nutrition/HungerComponent.cs | 3 +- .../Components/Nutrition/ThirstComponent.cs | 3 +- .../Projectiles/ProjectileComponent.cs | 3 +- .../GameObjects/EntitySystems/MoverSystem.cs | 5 +-- Content.Client/UserInterface/CreditsWindow.cs | 3 +- .../Networking/SimplePredictReconcileTest.cs | 3 +- .../Components/Access/AccessComponent.cs | 3 +- .../Access/AccessReaderComponent.cs | 4 +- .../Access/PresetIdCardComponent.cs | 3 +- .../Components/Cargo/CargoConsoleComponent.cs | 43 ++++++++++++------- .../Components/Mobs/BuckleComponent.cs | 14 +++--- .../Movement/PlayerInputMoverComponent.cs | 8 +--- .../Components/PDA/PDAComponent.cs | 3 +- .../GameObjects/Components/WiresComponent.cs | 33 +++++++------- .../GameObjects/EntitySystems/MoverSystem.cs | 5 +-- Content.Server/Interfaces/IAccess.cs | 3 +- .../SharedPlayerInputMoverComponent.cs | 5 +-- .../EntitySystems/SharedMoverSystem.cs | 5 +-- SpaceStation14.sln.DotSettings | 2 + 25 files changed, 95 insertions(+), 112 deletions(-) diff --git a/Content.Client/ClickMapManager.cs b/Content.Client/ClickMapManager.cs index a9938f05c8..36d5382157 100644 --- a/Content.Client/ClickMapManager.cs +++ b/Content.Client/ClickMapManager.cs @@ -1,3 +1,4 @@ +#nullable enable using System; using System.Collections.Generic; using System.Text; @@ -11,8 +12,6 @@ using Robust.Shared.ViewVariables; using SixLabors.ImageSharp; using SixLabors.ImageSharp.PixelFormats; -#nullable enable - namespace Content.Client { internal class ClickMapManager : IClickMapManager, IPostInjectInit diff --git a/Content.Client/GameObjects/Components/ClickableComponent.cs b/Content.Client/GameObjects/Components/ClickableComponent.cs index 3b36e8d38a..57d9420167 100644 --- a/Content.Client/GameObjects/Components/ClickableComponent.cs +++ b/Content.Client/GameObjects/Components/ClickableComponent.cs @@ -1,3 +1,4 @@ +#nullable enable using System; using Robust.Client.Graphics.ClientEye; using Robust.Client.Interfaces.GameObjects.Components; @@ -8,8 +9,6 @@ using Robust.Shared.Maths; using Robust.Shared.Serialization; using Robust.Shared.ViewVariables; -#nullable enable - namespace Content.Client.GameObjects.Components { [RegisterComponent] diff --git a/Content.Client/GameObjects/Components/Instruments/InstrumentComponent.cs b/Content.Client/GameObjects/Components/Instruments/InstrumentComponent.cs index 2791aa7ddb..69d364fd5f 100644 --- a/Content.Client/GameObjects/Components/Instruments/InstrumentComponent.cs +++ b/Content.Client/GameObjects/Components/Instruments/InstrumentComponent.cs @@ -1,24 +1,17 @@ +#nullable enable using System; -using System.Collections.Concurrent; using System.Collections.Generic; using System.Linq; using Content.Shared.GameObjects.Components.Instruments; using Content.Shared.Physics; -using JetBrains.Annotations; -using NFluidsynth; using Robust.Shared.GameObjects; using Robust.Client.Audio.Midi; -using Robust.Client.Player; -using Robust.Shared.Interfaces.Log; using Robust.Shared.Interfaces.Network; using Robust.Shared.Interfaces.Timing; using Robust.Shared.IoC; -using Robust.Shared.Log; using Robust.Shared.Players; using Robust.Shared.Serialization; -using Robust.Shared.Timing; using Robust.Shared.ViewVariables; -using Logger = Robust.Shared.Log.Logger; using MidiEvent = Robust.Shared.Audio.Midi.MidiEvent; using Timer = Robust.Shared.Timers.Timer; @@ -32,24 +25,23 @@ namespace Content.Client.GameObjects.Components.Instruments /// /// Called when a midi song stops playing. /// - public event Action OnMidiPlaybackEnded; + public event Action? OnMidiPlaybackEnded; #pragma warning disable 649 - [Dependency] private readonly IMidiManager _midiManager; + [Dependency] private readonly IMidiManager _midiManager = default!; - [Dependency] private readonly IGameTiming _gameTiming; + [Dependency] private readonly IGameTiming _gameTiming = default!; - [Dependency] private readonly IClientNetManager _netManager; + [Dependency] private readonly IClientNetManager _netManager = default!; #pragma warning restore 649 - [CanBeNull] - private IMidiRenderer _renderer; + private IMidiRenderer? _renderer; private byte _instrumentProgram = 1; - private byte _instrumentBank = 0; + private byte _instrumentBank; - private uint _sequenceDelay = 0; + private uint _sequenceDelay; private uint _sequenceStartTick; @@ -209,7 +201,7 @@ namespace Content.Client.GameObjects.Components.Instruments serializer.DataField(ref _instrumentBank, "bank", (byte) 0); } - public override void HandleNetworkMessage(ComponentMessage message, INetChannel channel, ICommonSession session = null) + public override void HandleNetworkMessage(ComponentMessage message, INetChannel channel, ICommonSession? session = null) { base.HandleNetworkMessage(message, channel, session); @@ -240,7 +232,7 @@ namespace Content.Client.GameObjects.Components.Instruments .Min(x => x.Tick) - 1; } - var sqrtLag = MathF.Sqrt(_netManager.ServerChannel.Ping / 1000f); + var sqrtLag = MathF.Sqrt(_netManager.ServerChannel!.Ping / 1000f); var delay = (uint) (_renderer!.SequencerTimeScale * (.2 + sqrtLag)); var delta = delay - _sequenceStartTick; @@ -265,12 +257,12 @@ namespace Content.Client.GameObjects.Components.Instruments } break; - case InstrumentStartMidiMessage startMidiMessage: + case InstrumentStartMidiMessage _: { SetupRenderer(true); break; } - case InstrumentStopMidiMessage stopMidiMessage: + case InstrumentStopMidiMessage _: { EndRenderer(true); break; @@ -278,7 +270,7 @@ namespace Content.Client.GameObjects.Components.Instruments } } - public override void HandleComponentState(ComponentState curState, ComponentState nextState) + public override void HandleComponentState(ComponentState? curState, ComponentState? nextState) { base.HandleComponentState(curState, nextState); if (!(curState is InstrumentState state)) return; @@ -370,7 +362,7 @@ namespace Content.Client.GameObjects.Components.Instruments private TimeSpan _lastMeasured = TimeSpan.MinValue; - private int _sentWithinASec = 0; + private int _sentWithinASec; private static readonly TimeSpan OneSecAgo = TimeSpan.FromSeconds(-1); diff --git a/Content.Client/GameObjects/Components/Mobs/StatusControl.cs b/Content.Client/GameObjects/Components/Mobs/StatusControl.cs index 591bf9e1c9..7df0225a90 100644 --- a/Content.Client/GameObjects/Components/Mobs/StatusControl.cs +++ b/Content.Client/GameObjects/Components/Mobs/StatusControl.cs @@ -1,5 +1,5 @@ -using Content.Shared.GameObjects.Components.Mobs; -using JetBrains.Annotations; +#nullable enable +using Content.Shared.GameObjects.Components.Mobs; using Robust.Client.Graphics; using Robust.Client.UserInterface.Controls; @@ -9,7 +9,7 @@ namespace Content.Client.GameObjects.Components.Mobs { public readonly StatusEffect Effect; - public StatusControl(StatusEffect effect, [CanBeNull] Texture texture) + public StatusControl(StatusEffect effect, Texture? texture) { Effect = effect; diff --git a/Content.Client/GameObjects/Components/Mobs/StunnableComponent.cs b/Content.Client/GameObjects/Components/Mobs/StunnableComponent.cs index 7ff78391ca..7c01000dd4 100644 --- a/Content.Client/GameObjects/Components/Mobs/StunnableComponent.cs +++ b/Content.Client/GameObjects/Components/Mobs/StunnableComponent.cs @@ -1,9 +1,8 @@ +#nullable enable using Content.Shared.GameObjects.Components.Mobs; using Content.Shared.GameObjects.Components.Movement; using Robust.Shared.GameObjects; -#nullable enable - namespace Content.Client.GameObjects.Components.Mobs { [RegisterComponent] diff --git a/Content.Client/GameObjects/Components/Movement/PlayerInputMoverComponent.cs b/Content.Client/GameObjects/Components/Movement/PlayerInputMoverComponent.cs index 50bcbd2790..fcdde82ef8 100644 --- a/Content.Client/GameObjects/Components/Movement/PlayerInputMoverComponent.cs +++ b/Content.Client/GameObjects/Components/Movement/PlayerInputMoverComponent.cs @@ -1,14 +1,13 @@ +#nullable enable using Content.Shared.GameObjects.Components.Movement; using Robust.Shared.GameObjects; using Robust.Shared.Map; -#nullable enable - namespace Content.Client.GameObjects.Components.Movement { [RegisterComponent] [ComponentReference(typeof(IMoverComponent))] - public class PlayerInputMoverComponent : SharedPlayerInputMoverComponent, IMoverComponent + public class PlayerInputMoverComponent : SharedPlayerInputMoverComponent { public override GridCoordinates LastPosition { get; set; } public override float StepSoundDistance { get; set; } diff --git a/Content.Client/GameObjects/Components/Nutrition/HungerComponent.cs b/Content.Client/GameObjects/Components/Nutrition/HungerComponent.cs index fa66e98812..8323fb5e7a 100644 --- a/Content.Client/GameObjects/Components/Nutrition/HungerComponent.cs +++ b/Content.Client/GameObjects/Components/Nutrition/HungerComponent.cs @@ -1,9 +1,8 @@ +#nullable enable using Content.Shared.GameObjects.Components.Movement; using Content.Shared.GameObjects.Components.Nutrition; using Robust.Shared.GameObjects; -#nullable enable - namespace Content.Client.GameObjects.Components.Nutrition { [RegisterComponent] diff --git a/Content.Client/GameObjects/Components/Nutrition/ThirstComponent.cs b/Content.Client/GameObjects/Components/Nutrition/ThirstComponent.cs index 10b63d054b..b77d59a34a 100644 --- a/Content.Client/GameObjects/Components/Nutrition/ThirstComponent.cs +++ b/Content.Client/GameObjects/Components/Nutrition/ThirstComponent.cs @@ -1,9 +1,8 @@ +#nullable enable using Content.Shared.GameObjects.Components.Movement; using Content.Shared.GameObjects.Components.Nutrition; using Robust.Shared.GameObjects; -#nullable enable - namespace Content.Client.GameObjects.Components.Nutrition { [RegisterComponent] diff --git a/Content.Client/GameObjects/Components/Projectiles/ProjectileComponent.cs b/Content.Client/GameObjects/Components/Projectiles/ProjectileComponent.cs index 27e8ed6285..9abf4a557b 100644 --- a/Content.Client/GameObjects/Components/Projectiles/ProjectileComponent.cs +++ b/Content.Client/GameObjects/Components/Projectiles/ProjectileComponent.cs @@ -1,8 +1,7 @@ +#nullable enable using Content.Shared.GameObjects.Components.Projectiles; using Robust.Shared.GameObjects; -#nullable enable - namespace Content.Client.GameObjects.Components.Projectiles { [RegisterComponent] diff --git a/Content.Client/GameObjects/EntitySystems/MoverSystem.cs b/Content.Client/GameObjects/EntitySystems/MoverSystem.cs index 37689e355c..84fe87bf25 100644 --- a/Content.Client/GameObjects/EntitySystems/MoverSystem.cs +++ b/Content.Client/GameObjects/EntitySystems/MoverSystem.cs @@ -1,4 +1,5 @@ -using Content.Shared.GameObjects.Components.Movement; +#nullable enable +using Content.Shared.GameObjects.Components.Movement; using Content.Shared.GameObjects.EntitySystems; using Content.Shared.Physics; using JetBrains.Annotations; @@ -7,8 +8,6 @@ using Robust.Client.Player; using Robust.Shared.GameObjects.Components; using Robust.Shared.IoC; -#nullable enable - namespace Content.Client.GameObjects.EntitySystems { [UsedImplicitly] diff --git a/Content.Client/UserInterface/CreditsWindow.cs b/Content.Client/UserInterface/CreditsWindow.cs index 56ac89f153..1bdd4c7a76 100644 --- a/Content.Client/UserInterface/CreditsWindow.cs +++ b/Content.Client/UserInterface/CreditsWindow.cs @@ -1,3 +1,4 @@ +#nullable enable using System.Collections.Generic; using System.IO; using System.Linq; @@ -13,8 +14,6 @@ using Robust.Shared.Localization; using Robust.Shared.Maths; using Robust.Shared.Utility; -#nullable enable - namespace Content.Client.UserInterface { public sealed class CreditsWindow : SS14Window diff --git a/Content.IntegrationTests/Tests/Networking/SimplePredictReconcileTest.cs b/Content.IntegrationTests/Tests/Networking/SimplePredictReconcileTest.cs index 794dfb0fe6..93d2db7549 100644 --- a/Content.IntegrationTests/Tests/Networking/SimplePredictReconcileTest.cs +++ b/Content.IntegrationTests/Tests/Networking/SimplePredictReconcileTest.cs @@ -1,3 +1,4 @@ +#nullable enable using System.Collections.Generic; using System.Linq; using System.Threading.Tasks; @@ -15,8 +16,6 @@ using Robust.Shared.IoC; using Robust.Shared.Map; using Robust.Shared.Timing; -#nullable enable - namespace Content.IntegrationTests.Tests.Networking { // This test checks that the prediction & reconciling system is working correctly with a simple boolean flag. diff --git a/Content.Server/GameObjects/Components/Access/AccessComponent.cs b/Content.Server/GameObjects/Components/Access/AccessComponent.cs index 060f418634..101f215c15 100644 --- a/Content.Server/GameObjects/Components/Access/AccessComponent.cs +++ b/Content.Server/GameObjects/Components/Access/AccessComponent.cs @@ -1,11 +1,10 @@ +#nullable enable using System.Collections.Generic; using Content.Server.Interfaces; using Robust.Shared.GameObjects; using Robust.Shared.Serialization; using Robust.Shared.ViewVariables; -#nullable enable - namespace Content.Server.GameObjects.Components.Access { /// diff --git a/Content.Server/GameObjects/Components/Access/AccessReaderComponent.cs b/Content.Server/GameObjects/Components/Access/AccessReaderComponent.cs index 2a1d18ac41..94f06bc4a2 100644 --- a/Content.Server/GameObjects/Components/Access/AccessReaderComponent.cs +++ b/Content.Server/GameObjects/Components/Access/AccessReaderComponent.cs @@ -1,3 +1,4 @@ +#nullable enable using System; using System.Collections.Generic; using System.Linq; @@ -10,8 +11,6 @@ using Robust.Shared.Interfaces.GameObjects; using Robust.Shared.Serialization; using Robust.Shared.ViewVariables; -#nullable enable - namespace Content.Server.GameObjects.Components.Access { /// @@ -68,7 +67,6 @@ namespace Content.Server.GameObjects.Components.Access return _accessLists.Count == 0 || _accessLists.Any(a => a.IsSubsetOf(accessTags)); } - [CanBeNull] public static ICollection FindAccessTags(IEntity entity) { if (entity.TryGetComponent(out IAccess accessComponent)) diff --git a/Content.Server/GameObjects/Components/Access/PresetIdCardComponent.cs b/Content.Server/GameObjects/Components/Access/PresetIdCardComponent.cs index 3895218154..67c6d08a76 100644 --- a/Content.Server/GameObjects/Components/Access/PresetIdCardComponent.cs +++ b/Content.Server/GameObjects/Components/Access/PresetIdCardComponent.cs @@ -1,3 +1,4 @@ +#nullable enable using Content.Shared.Jobs; using Robust.Server.Interfaces.GameObjects; using Robust.Shared.GameObjects; @@ -5,8 +6,6 @@ using Robust.Shared.IoC; using Robust.Shared.Prototypes; using Robust.Shared.Serialization; -#nullable enable - namespace Content.Server.GameObjects.Components.Access { [RegisterComponent] diff --git a/Content.Server/GameObjects/Components/Cargo/CargoConsoleComponent.cs b/Content.Server/GameObjects/Components/Cargo/CargoConsoleComponent.cs index cd5effccc2..78c30dc9b4 100644 --- a/Content.Server/GameObjects/Components/Cargo/CargoConsoleComponent.cs +++ b/Content.Server/GameObjects/Components/Cargo/CargoConsoleComponent.cs @@ -1,10 +1,10 @@ -using Content.Server.Cargo; +#nullable enable +using Content.Server.Cargo; using Content.Server.GameObjects.Components.Power.ApcNetComponents; using Content.Server.GameObjects.EntitySystems; using Content.Server.Interfaces.GameObjects.Components.Interaction; using Content.Shared.GameObjects.Components.Cargo; using Content.Shared.Prototypes.Cargo; -using JetBrains.Annotations; using Robust.Server.GameObjects.Components.UserInterface; using Robust.Server.Interfaces.GameObjects; using Robust.Shared.GameObjects; @@ -20,39 +20,43 @@ namespace Content.Server.GameObjects.Components.Cargo public class CargoConsoleComponent : SharedCargoConsoleComponent, IActivate { #pragma warning disable 649 - [Dependency] private readonly ICargoOrderDataManager _cargoOrderDataManager; + [Dependency] private readonly ICargoOrderDataManager _cargoOrderDataManager = default!; #pragma warning restore 649 [ViewVariables] public int Points = 1000; - private BoundUserInterface _userInterface; + private BoundUserInterface _userInterface = default!; [ViewVariables] - public GalacticMarketComponent Market { get; private set; } - [ViewVariables] - public CargoOrderDatabaseComponent Orders { get; private set; } - - private CargoBankAccount _bankAccount; + public GalacticMarketComponent Market { get; private set; } = default!; [ViewVariables] - [CanBeNull] - public CargoBankAccount BankAccount + public CargoOrderDatabaseComponent Orders { get; private set; } = default!; + + private CargoBankAccount? _bankAccount; + + [ViewVariables] + public CargoBankAccount? BankAccount { get => _bankAccount; private set { if (_bankAccount == value) + { return; + } + if (_bankAccount != null) { _bankAccount.OnBalanceChange -= UpdateUIState; } _bankAccount = value; + if (value != null) { - _bankAccount.OnBalanceChange += UpdateUIState; + value.OnBalanceChange += UpdateUIState; } UpdateUIState(); @@ -61,9 +65,9 @@ namespace Content.Server.GameObjects.Components.Cargo private bool _requestOnly = false; - private PowerReceiverComponent _powerReceiver; + private PowerReceiverComponent _powerReceiver = default!; private bool Powered => _powerReceiver.Powered; - private CargoConsoleSystem _cargoConsoleSystem; + private CargoConsoleSystem _cargoConsoleSystem = default!; public override void Initialize() { @@ -98,8 +102,11 @@ namespace Content.Server.GameObjects.Components.Cargo { case CargoConsoleAddOrderMessage msg: { - if (msg.Amount <= 0) + if (msg.Amount <= 0 || _bankAccount == null) + { break; + } + _cargoOrderDataManager.AddOrder(Orders.Database.Id, msg.Requester, msg.Reason, msg.ProductId, msg.Amount, _bankAccount.Id); break; } @@ -111,8 +118,12 @@ namespace Content.Server.GameObjects.Components.Cargo case CargoConsoleApproveOrderMessage msg: { if (_requestOnly || - !Orders.Database.TryGetOrder(msg.OrderNumber, out var order)) + !Orders.Database.TryGetOrder(msg.OrderNumber, out var order) || + _bankAccount == null) + { break; + } + _prototypeManager.TryIndex(order.ProductId, out CargoProductPrototype product); if (product == null) break; diff --git a/Content.Server/GameObjects/Components/Mobs/BuckleComponent.cs b/Content.Server/GameObjects/Components/Mobs/BuckleComponent.cs index 485624b5de..509baf88b1 100644 --- a/Content.Server/GameObjects/Components/Mobs/BuckleComponent.cs +++ b/Content.Server/GameObjects/Components/Mobs/BuckleComponent.cs @@ -1,4 +1,5 @@ -using Content.Server.GameObjects.Components.Strap; +#nullable enable +using Content.Server.GameObjects.Components.Strap; using Content.Server.GameObjects.EntitySystems; using Content.Server.Interfaces; using Content.Server.Interfaces.GameObjects.Components.Interaction; @@ -8,7 +9,6 @@ using Content.Shared.GameObjects; using Content.Shared.GameObjects.Components.Mobs; using Content.Shared.GameObjects.Components.Strap; using Content.Shared.GameObjects.EntitySystems; -using JetBrains.Annotations; using Robust.Server.GameObjects; using Robust.Server.GameObjects.EntitySystems; using Robust.Shared.GameObjects; @@ -25,15 +25,15 @@ namespace Content.Server.GameObjects.Components.Mobs public class BuckleComponent : SharedBuckleComponent, IInteractHand, IDragDrop { #pragma warning disable 649 - [Dependency] private readonly IEntitySystemManager _entitySystem; - [Dependency] private readonly IServerNotifyManager _notifyManager; + [Dependency] private readonly IEntitySystemManager _entitySystem = default!; + [Dependency] private readonly IServerNotifyManager _notifyManager = default!; #pragma warning restore 649 - [CanBeNull] private StrapComponent _buckledTo; + private StrapComponent? _buckledTo; private int _size; - [ViewVariables, CanBeNull] - public StrapComponent BuckledTo + [ViewVariables] + public StrapComponent? BuckledTo { get => _buckledTo; private set diff --git a/Content.Server/GameObjects/Components/Movement/PlayerInputMoverComponent.cs b/Content.Server/GameObjects/Components/Movement/PlayerInputMoverComponent.cs index e1e617774e..d3ba8882db 100644 --- a/Content.Server/GameObjects/Components/Movement/PlayerInputMoverComponent.cs +++ b/Content.Server/GameObjects/Components/Movement/PlayerInputMoverComponent.cs @@ -1,11 +1,7 @@ -using Content.Shared.GameObjects.Components.Movement; +#nullable enable +using Content.Shared.GameObjects.Components.Movement; using Robust.Shared.GameObjects; -using Robust.Shared.GameObjects.Components; using Robust.Shared.Map; -using Robust.Shared.Physics; -using Robust.Shared.ViewVariables; - -#nullable enable namespace Content.Server.GameObjects.Components.Movement { diff --git a/Content.Server/GameObjects/Components/PDA/PDAComponent.cs b/Content.Server/GameObjects/Components/PDA/PDAComponent.cs index e4a02108e5..c14cce399f 100644 --- a/Content.Server/GameObjects/Components/PDA/PDAComponent.cs +++ b/Content.Server/GameObjects/Components/PDA/PDAComponent.cs @@ -1,3 +1,4 @@ +#nullable enable using System; using System.Collections; using System.Collections.Generic; @@ -22,8 +23,6 @@ using Robust.Shared.Localization; using Robust.Shared.Serialization; using Robust.Shared.ViewVariables; -#nullable enable - namespace Content.Server.GameObjects.Components.PDA { [RegisterComponent] diff --git a/Content.Server/GameObjects/Components/WiresComponent.cs b/Content.Server/GameObjects/Components/WiresComponent.cs index 2c8534edd6..8af306e51e 100644 --- a/Content.Server/GameObjects/Components/WiresComponent.cs +++ b/Content.Server/GameObjects/Components/WiresComponent.cs @@ -1,4 +1,5 @@ -using System; +#nullable enable +using System; using System.Collections.Generic; using System.Linq; using Content.Server.GameObjects.Components.Interactable; @@ -32,12 +33,12 @@ namespace Content.Server.GameObjects.Components public class WiresComponent : SharedWiresComponent, IInteractUsing, IExamine, IMapInit { #pragma warning disable 649 - [Dependency] private readonly IRobustRandom _random; - [Dependency] private readonly IServerNotifyManager _notifyManager; + [Dependency] private readonly IRobustRandom _random = default!; + [Dependency] private readonly IServerNotifyManager _notifyManager = default!; #pragma warning restore 649 - private AudioSystem _audioSystem; - private AppearanceComponent _appearance; - private BoundUserInterface _userInterface; + private AudioSystem _audioSystem = default!; + private AppearanceComponent _appearance = default!; + private BoundUserInterface _userInterface = default!; private bool _isPanelOpen; @@ -93,7 +94,7 @@ namespace Content.Server.GameObjects.Components } [ViewVariables(VVAccess.ReadWrite)] - public string SerialNumber + public string? SerialNumber { get => _serialNumber; set @@ -127,16 +128,16 @@ namespace Content.Server.GameObjects.Components private readonly List _availableLetters = new List((WireLetter[]) Enum.GetValues(typeof(WireLetter))); - private string _boardName; + private string _boardName = default!; - private string _serialNumber; + private string? _serialNumber; // Used to generate wire appearance randomization client side. // We honestly don't care what it is or such but do care that it doesn't change between UI re-opens. [ViewVariables] private int _wireSeed; [ViewVariables] - private string _layoutId; + private string? _layoutId; public override void Initialize() { @@ -186,7 +187,7 @@ namespace Content.Server.GameObjects.Components base.Startup(); - WireLayout layout = null; + WireLayout? layout = null; var hackingSystem = EntitySystem.Get(); if (_layoutId != null) { @@ -299,9 +300,9 @@ namespace Content.Server.GameObjects.Components { [NotNull] private readonly WiresComponent _wires; [NotNull] private readonly IWires _owner; - [CanBeNull] private readonly WireLayout _layout; + private readonly WireLayout? _layout; - public WiresBuilder(WiresComponent wires, IWires owner, WireLayout layout) + public WiresBuilder(WiresComponent wires, IWires owner, WireLayout? layout) { _wires = wires; _owner = owner; @@ -365,12 +366,12 @@ namespace Content.Server.GameObjects.Components { case WiresActionMessage msg: var wire = WiresList.Find(x => x.Id == msg.Id); - if (wire == null) + var player = serverMsg.Session.AttachedEntity; + if (wire == null || player == null) { return; } - var player = serverMsg.Session.AttachedEntity; if (!player.TryGetComponent(out IHandsComponent handsComponent)) { _notifyManager.PopupMessage(Owner.Transform.GridPosition, player, @@ -386,7 +387,7 @@ namespace Content.Server.GameObjects.Components } var activeHandEntity = handsComponent.GetActiveHand?.Owner; - ToolComponent tool = null; + ToolComponent? tool = null; activeHandEntity?.TryGetComponent(out tool); switch (msg.Action) diff --git a/Content.Server/GameObjects/EntitySystems/MoverSystem.cs b/Content.Server/GameObjects/EntitySystems/MoverSystem.cs index 626e86a18e..bb1d181930 100644 --- a/Content.Server/GameObjects/EntitySystems/MoverSystem.cs +++ b/Content.Server/GameObjects/EntitySystems/MoverSystem.cs @@ -1,4 +1,5 @@ -using Content.Server.GameObjects; +#nullable enable +using Content.Server.GameObjects; using Content.Server.GameObjects.Components; using Content.Server.GameObjects.Components.Mobs; using Content.Server.GameObjects.Components.Movement; @@ -23,8 +24,6 @@ using Robust.Shared.Map; using Robust.Shared.Prototypes; using Robust.Shared.Random; -#nullable enable - namespace Content.Server.GameObjects.EntitySystems { [UsedImplicitly] diff --git a/Content.Server/Interfaces/IAccess.cs b/Content.Server/Interfaces/IAccess.cs index f50cae8214..f271990545 100644 --- a/Content.Server/Interfaces/IAccess.cs +++ b/Content.Server/Interfaces/IAccess.cs @@ -1,9 +1,8 @@ +#nullable enable using System; using Content.Server.GameObjects.Components.Access; using System.Collections.Generic; -#nullable enable - namespace Content.Server.Interfaces { /// diff --git a/Content.Shared/GameObjects/Components/Movement/SharedPlayerInputMoverComponent.cs b/Content.Shared/GameObjects/Components/Movement/SharedPlayerInputMoverComponent.cs index cb47ac544c..edd3e03d37 100644 --- a/Content.Shared/GameObjects/Components/Movement/SharedPlayerInputMoverComponent.cs +++ b/Content.Shared/GameObjects/Components/Movement/SharedPlayerInputMoverComponent.cs @@ -1,4 +1,5 @@ -using System; +#nullable enable +using System; using Content.Shared.GameObjects.Components.Mobs; using Robust.Shared.GameObjects; using Robust.Shared.GameObjects.Components; @@ -13,8 +14,6 @@ using Robust.Shared.Serialization; using Robust.Shared.Timing; using Robust.Shared.ViewVariables; -#nullable enable - namespace Content.Shared.GameObjects.Components.Movement { public abstract class SharedPlayerInputMoverComponent : Component, IMoverComponent, ICollideSpecial diff --git a/Content.Shared/GameObjects/EntitySystems/SharedMoverSystem.cs b/Content.Shared/GameObjects/EntitySystems/SharedMoverSystem.cs index 931648c5f1..29b65486a1 100644 --- a/Content.Shared/GameObjects/EntitySystems/SharedMoverSystem.cs +++ b/Content.Shared/GameObjects/EntitySystems/SharedMoverSystem.cs @@ -1,4 +1,5 @@ -using System.Diagnostics.CodeAnalysis; +#nullable enable +using System.Diagnostics.CodeAnalysis; using Content.Shared.GameObjects.Components.Movement; using Content.Shared.Physics; using Robust.Shared.Configuration; @@ -15,8 +16,6 @@ using Robust.Shared.IoC; using Robust.Shared.Maths; using Robust.Shared.Players; -#nullable enable - namespace Content.Shared.GameObjects.EntitySystems { public abstract class SharedMoverSystem : EntitySystem diff --git a/SpaceStation14.sln.DotSettings b/SpaceStation14.sln.DotSettings index 4eed2c94d7..5d7127034d 100644 --- a/SpaceStation14.sln.DotSettings +++ b/SpaceStation14.sln.DotSettings @@ -1,4 +1,6 @@  + False + False WARNING WARNING WARNING From 1d96adcc2cc5978381510397476adc66d4da97d6 Mon Sep 17 00:00:00 2001 From: metalgearsloth <31366439+metalgearsloth@users.noreply.github.com> Date: Wed, 8 Jul 2020 09:41:41 +1000 Subject: [PATCH 10/19] Add Breadth-First Search pathfinder (#1283) Co-authored-by: Metal Gear Sloth --- .../Pathfinding/Accessible/BFSPathfinder.cs | 70 +++++++++++++++++++ .../AI/Pathfinding/PathfindingHelpers.cs | 13 ++-- 2 files changed, 75 insertions(+), 8 deletions(-) create mode 100644 Content.Server/GameObjects/EntitySystems/AI/Pathfinding/Accessible/BFSPathfinder.cs diff --git a/Content.Server/GameObjects/EntitySystems/AI/Pathfinding/Accessible/BFSPathfinder.cs b/Content.Server/GameObjects/EntitySystems/AI/Pathfinding/Accessible/BFSPathfinder.cs new file mode 100644 index 0000000000..ddb5628a02 --- /dev/null +++ b/Content.Server/GameObjects/EntitySystems/AI/Pathfinding/Accessible/BFSPathfinder.cs @@ -0,0 +1,70 @@ +using System.Collections.Generic; +using Content.Server.GameObjects.EntitySystems.AI.Pathfinding.Pathfinders; +using Content.Server.GameObjects.EntitySystems.Pathfinding; +using Robust.Shared.GameObjects.Systems; +using Robust.Shared.Map; + +namespace Content.Server.GameObjects.EntitySystems.AI.Pathfinding.Accessible +{ + /// + /// The simplest pathfinder + /// + public sealed class BFSPathfinder + { + /// + /// Gets all of the tiles in range that can we access + /// + /// If you want Dikstra then add distances. + /// Doesn't use the JobQueue as it will generally be encapsulated by other jobs + /// + /// + /// Whether we traverse from the starting tile or the end tile + /// + public static IEnumerable GetNodesInRange(PathfindingArgs pathfindingArgs, bool fromStart = true) + { + var pathfindingSystem = EntitySystem.Get(); + // Don't need a priority queue given not looking for shortest path + var openTiles = new Queue(); + var closedTiles = new HashSet(); + PathfindingNode startNode; + + if (fromStart) + { + startNode = pathfindingSystem.GetNode(pathfindingArgs.Start); + } + else + { + startNode = pathfindingSystem.GetNode(pathfindingArgs.End); + } + + PathfindingNode currentNode; + openTiles.Enqueue(startNode); + + while (openTiles.Count > 0) + { + currentNode = openTiles.Dequeue(); + + foreach (var neighbor in currentNode.GetNeighbors()) + { + // No distances stored so can just check closed tiles here + if (closedTiles.Contains(neighbor.TileRef)) continue; + closedTiles.Add(currentNode.TileRef); + + // So currently tileCost gets the octile distance between the 2 so we'll also use that for our range check + var tileCost = PathfindingHelpers.GetTileCost(pathfindingArgs, startNode, neighbor); + var direction = PathfindingHelpers.RelativeDirection(neighbor, currentNode); + + if (tileCost == null || + tileCost > pathfindingArgs.Proximity || + !PathfindingHelpers.DirectionTraversable(pathfindingArgs.CollisionMask, pathfindingArgs.Access, currentNode, direction)) + { + continue; + } + + openTiles.Enqueue(neighbor); + yield return neighbor; + } + } + } + } +} \ No newline at end of file diff --git a/Content.Server/GameObjects/EntitySystems/AI/Pathfinding/PathfindingHelpers.cs b/Content.Server/GameObjects/EntitySystems/AI/Pathfinding/PathfindingHelpers.cs index e4c04d5a94..4c5e25390a 100644 --- a/Content.Server/GameObjects/EntitySystems/AI/Pathfinding/PathfindingHelpers.cs +++ b/Content.Server/GameObjects/EntitySystems/AI/Pathfinding/PathfindingHelpers.cs @@ -1,5 +1,7 @@ using System; using System.Collections.Generic; +using Content.Server.GameObjects.Components.Access; +using Content.Server.GameObjects.EntitySystems.AI.Pathfinding.Accessible; using Content.Server.GameObjects.EntitySystems.AI.Pathfinding.Pathfinders; using Content.Server.GameObjects.EntitySystems.Pathfinding; using Robust.Shared.Interfaces.GameObjects; @@ -18,15 +20,10 @@ namespace Content.Server.GameObjects.EntitySystems.AI.Pathfinding { if (pathfindingArgs.Proximity > 0.0f) { - // TODO: Should make this account for proximities, - // probably some kind of breadth-first search to find a valid one - foreach (var node in endNode.GetNeighbors()) + foreach (var node in BFSPathfinder.GetNodesInRange(pathfindingArgs, false)) { - if (Traversable(pathfindingArgs.CollisionMask, pathfindingArgs.Access, node)) - { - endNode = node; - return true; - } + endNode = node; + return true; } } From 5d0b86c6590dbde8ebe989dbd94ea7cfce0f5cb9 Mon Sep 17 00:00:00 2001 From: Pieter-Jan Briers Date: Wed, 8 Jul 2020 02:53:50 +0200 Subject: [PATCH 11/19] Hide transfer verbs when right clicking reagent container in active hand. Fixes #1313 --- .../GameObjects/Components/Chemistry/SolutionComponent.cs | 2 ++ 1 file changed, 2 insertions(+) diff --git a/Content.Server/GameObjects/Components/Chemistry/SolutionComponent.cs b/Content.Server/GameObjects/Components/Chemistry/SolutionComponent.cs index 4a4dcbabef..5c5f2fd230 100644 --- a/Content.Server/GameObjects/Components/Chemistry/SolutionComponent.cs +++ b/Content.Server/GameObjects/Components/Chemistry/SolutionComponent.cs @@ -224,6 +224,7 @@ namespace Content.Server.GameObjects.Components.Chemistry if (!ActionBlockerSystem.CanInteract(user) || !user.TryGetComponent(out var hands) || hands.GetActiveHand == null || + hands.GetActiveHand.Owner == component.Owner || !hands.GetActiveHand.Owner.TryGetComponent(out var solution)) { data.Visibility = VerbVisibility.Invisible; @@ -323,6 +324,7 @@ namespace Content.Server.GameObjects.Components.Chemistry if (!ActionBlockerSystem.CanInteract(user) || !user.TryGetComponent(out var hands) || hands.GetActiveHand == null || + hands.GetActiveHand.Owner == component.Owner || !hands.GetActiveHand.Owner.TryGetComponent(out var solution)) { data.Visibility = VerbVisibility.Invisible; From 4721fd203535e08f5fbbcf8f8c6a442cd7103e16 Mon Sep 17 00:00:00 2001 From: Pieter-Jan Briers Date: Wed, 8 Jul 2020 02:59:07 +0200 Subject: [PATCH 12/19] The fix was inside us all along. --- .../Components/Movement/SharedPlayerInputMoverComponent.cs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/Content.Shared/GameObjects/Components/Movement/SharedPlayerInputMoverComponent.cs b/Content.Shared/GameObjects/Components/Movement/SharedPlayerInputMoverComponent.cs index edd3e03d37..e12c56a42e 100644 --- a/Content.Shared/GameObjects/Components/Movement/SharedPlayerInputMoverComponent.cs +++ b/Content.Shared/GameObjects/Components/Movement/SharedPlayerInputMoverComponent.cs @@ -188,7 +188,7 @@ namespace Content.Shared.GameObjects.Components.Movement _lastInputSubTick = 0; } - if (_lastInputSubTick >= subTick) + if (subTick >= _lastInputSubTick) { var fraction = (subTick - _lastInputSubTick) / (float) ushort.MaxValue; From df395b943547ccddcef189457c4517b9cccc5efb Mon Sep 17 00:00:00 2001 From: bhespiritu Date: Wed, 8 Jul 2020 05:46:54 -0400 Subject: [PATCH 13/19] Fixed Welding Tool Not Updating (#1314) MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit * Fix Welding Tool Not Updating - Added in the ISolutionChange interface so that it dirties the entity any time the amount of welding fuel changes. This applies whether it's lit or unlit. - I also removed some redundant code. * Update Content.Server/GameObjects/Components/Interactable/WelderComponent.cs Co-authored-by: Víctor Aguilera Puerto <6766154+Zumorica@users.noreply.github.com> --- .../Components/Interactable/WelderComponent.cs | 8 ++++++-- 1 file changed, 6 insertions(+), 2 deletions(-) diff --git a/Content.Server/GameObjects/Components/Interactable/WelderComponent.cs b/Content.Server/GameObjects/Components/Interactable/WelderComponent.cs index bf55f988fa..8be75e5e18 100644 --- a/Content.Server/GameObjects/Components/Interactable/WelderComponent.cs +++ b/Content.Server/GameObjects/Components/Interactable/WelderComponent.cs @@ -24,7 +24,7 @@ namespace Content.Server.GameObjects.Components.Interactable [RegisterComponent] [ComponentReference(typeof(ToolComponent))] [ComponentReference(typeof(IToolComponent))] - public class WelderComponent : ToolComponent, IExamine, IUse, ISuicideAct + public class WelderComponent : ToolComponent, IExamine, IUse, ISuicideAct, ISolutionChange { #pragma warning disable 649 [Dependency] private IEntitySystemManager _entitySystemManager; @@ -193,7 +193,6 @@ namespace Content.Server.GameObjects.Components.Interactable if (Fuel == 0) ToggleWelderStatus(); - Dirty(); } public SuicideKind Suicide(IEntity victim, IChatManager chat) @@ -207,5 +206,10 @@ namespace Content.Server.GameObjects.Components.Interactable chat.EntityMe(victim, Loc.GetString("bashes {0:themselves} with the {1}!", victim, Owner.Name)); return SuicideKind.Brute; } + + public void SolutionChanged(SolutionChangeEventArgs eventArgs) + { + Dirty(); + } } } From 2d2385032abce764f1e96e1a50b4f75488db5fe5 Mon Sep 17 00:00:00 2001 From: ike709 Date: Wed, 8 Jul 2020 05:18:16 -0500 Subject: [PATCH 14/19] Admin chat (#1287) * Admin chat * Change it to show username, not character name * moves the thing * Removes SenderEntity --- Content.Client/Chat/ChatBox.cs | 19 +++++++++++ Content.Client/Chat/ChatManager.cs | 33 +++++++++++++++++++ Content.Client/Input/ContentContexts.cs | 1 + Content.Client/State/GameScreen.cs | 18 ++++++++++ .../UserInterface/TutorialWindow.cs | 4 ++- Content.Server/Chat/ChatCommands.cs | 14 ++++++++ Content.Server/Chat/ChatManager.cs | 19 +++++++++++ .../Interfaces/Chat/IChatManager.cs | 1 + Content.Shared/Chat/ChatChannel.cs | 7 +++- Content.Shared/Chat/MsgChatMessage.cs | 6 ++-- Content.Shared/Input/ContentKeyFunctions.cs | 1 + Resources/Groups/groups.yml | 2 ++ Resources/keybinds.yml | 3 ++ 13 files changed, 124 insertions(+), 4 deletions(-) diff --git a/Content.Client/Chat/ChatBox.cs b/Content.Client/Chat/ChatBox.cs index 87bbebba1b..7f3e1aa3ec 100644 --- a/Content.Client/Chat/ChatBox.cs +++ b/Content.Client/Chat/ChatBox.cs @@ -1,5 +1,6 @@ using System.Collections.Generic; using Content.Shared.Chat; +using Robust.Client.Console; using Robust.Client.Graphics.Drawing; using Robust.Client.UserInterface; using Robust.Client.UserInterface.Controls; @@ -26,6 +27,7 @@ namespace Content.Client.Chat public Button AllButton { get; } public Button LocalButton { get; } public Button OOCButton { get; } + public Button AdminButton { get; } /// /// Default formatting string for the ClientChatConsole. @@ -59,6 +61,7 @@ namespace Content.Client.Chat outerVBox.AddChild(panelContainer); outerVBox.AddChild(hBox); + var contentMargin = new MarginContainer { MarginLeftOverride = 4, MarginRightOverride = 4, @@ -95,6 +98,17 @@ namespace Content.Client.Chat ToggleMode = true, }; + var groupController = IoCManager.Resolve(); + if(groupController.CanCommand("asay")) + { + AdminButton = new Button + { + Text = _localize.GetString("Admin"), + Name = "Admin", + ToggleMode = true, + }; + } + AllButton.OnToggled += OnFilterToggled; LocalButton.OnToggled += OnFilterToggled; OOCButton.OnToggled += OnFilterToggled; @@ -102,6 +116,11 @@ namespace Content.Client.Chat hBox.AddChild(AllButton); hBox.AddChild(LocalButton); hBox.AddChild(OOCButton); + if(AdminButton != null) + { + AdminButton.OnToggled += OnFilterToggled; + hBox.AddChild(AdminButton); + } AddChild(outerVBox); } diff --git a/Content.Client/Chat/ChatManager.cs b/Content.Client/Chat/ChatManager.cs index 61d1d4ae03..2264931496 100644 --- a/Content.Client/Chat/ChatManager.cs +++ b/Content.Client/Chat/ChatManager.cs @@ -48,6 +48,7 @@ namespace Content.Client.Chat private const char ConCmdSlash = '/'; private const char OOCAlias = '['; private const char MeAlias = '@'; + private const char AdminChatAlias = ']'; private readonly List filteredHistory = new List(); @@ -55,6 +56,7 @@ namespace Content.Client.Chat private bool _allState; private bool _localState; private bool _oocState; + private bool _adminState; // Flag Enums for holding filtered channels private ChatChannel _filteredChannels; @@ -65,6 +67,7 @@ namespace Content.Client.Chat [Dependency] private readonly IEntityManager _entityManager; [Dependency] private readonly IEyeManager _eyeManager; [Dependency] private readonly IUserInterfaceManager _userInterfaceManager; + [Dependency] private readonly IClientConGroupController _groupController = default!; #pragma warning restore 649 private ChatBox _currentChatBox; @@ -150,6 +153,8 @@ namespace Content.Client.Chat _currentChatBox.AllButton.Pressed = !_allState; _currentChatBox.LocalButton.Pressed = !_localState; _currentChatBox.OOCButton.Pressed = !_oocState; + if(chatBox.AdminButton != null) + _currentChatBox.AdminButton.Pressed = !_adminState; } public void RemoveSpeechBubble(EntityUid entityUid, SpeechBubble bubble) @@ -193,6 +198,9 @@ namespace Content.Client.Chat case ChatChannel.Dead: color = Color.MediumPurple; break; + case ChatChannel.AdminChat: + color = Color.Red; + break; } _currentChatBox?.AddLine(messageText, message.Channel, color); @@ -220,6 +228,18 @@ namespace Content.Client.Chat _console.ProcessCommand($"ooc \"{CommandParsing.Escape(conInput)}\""); break; } + case AdminChatAlias: + { + var conInput = text.Substring(1); + if(_groupController.CanCommand("asay")){ + _console.ProcessCommand($"asay \"{CommandParsing.Escape(conInput)}\""); + } + else + { + _console.ProcessCommand($"ooc \"{CommandParsing.Escape(conInput)}\""); + } + break; + } case MeAlias: { var conInput = text.Substring(1); @@ -266,10 +286,23 @@ namespace Content.Client.Chat _filteredChannels &= ~ChatChannel.OOC; break; } + case "Admin": + _adminState = !_adminState; + if (_adminState) + { + _filteredChannels |= ChatChannel.AdminChat; + break; + } + else + { + _filteredChannels &= ~ChatChannel.AdminChat; + break; + } case "ALL": chatBox.LocalButton.Pressed ^= true; chatBox.OOCButton.Pressed ^= true; + chatBox.AdminButton.Pressed ^= true; _allState = !_allState; break; } diff --git a/Content.Client/Input/ContentContexts.cs b/Content.Client/Input/ContentContexts.cs index 5e54b537dc..197774ed33 100644 --- a/Content.Client/Input/ContentContexts.cs +++ b/Content.Client/Input/ContentContexts.cs @@ -14,6 +14,7 @@ namespace Content.Client.Input var common = contexts.GetContext("common"); common.AddFunction(ContentKeyFunctions.FocusChat); common.AddFunction(ContentKeyFunctions.FocusOOC); + common.AddFunction(ContentKeyFunctions.FocusAdminChat); common.AddFunction(ContentKeyFunctions.ExamineEntity); common.AddFunction(ContentKeyFunctions.OpenTutorial); common.AddFunction(ContentKeyFunctions.TakeScreenshot); diff --git a/Content.Client/State/GameScreen.cs b/Content.Client/State/GameScreen.cs index a0d947c4e8..7e36c9cca0 100644 --- a/Content.Client/State/GameScreen.cs +++ b/Content.Client/State/GameScreen.cs @@ -4,6 +4,7 @@ using Content.Client.Chat; using Content.Client.Interfaces.Chat; using Content.Client.UserInterface; using Content.Shared.Input; +using Robust.Client.Console; using Robust.Client.Interfaces.Input; using Robust.Client.Interfaces.State; using Robust.Client.Interfaces.UserInterface; @@ -25,6 +26,7 @@ namespace Content.Client.State [Dependency] private readonly IGameHud _gameHud; [Dependency] private readonly IInputManager _inputManager; [Dependency] private readonly IChatManager _chatManager; + [Dependency] private readonly IClientConGroupController _groupController = default!; #pragma warning restore 649 [ViewVariables] private ChatBox _gameChat; @@ -34,6 +36,7 @@ namespace Content.Client.State base.Startup(); _gameChat = new ChatBox(); + _userInterfaceManager.StateRoot.AddChild(_gameChat); LayoutContainer.SetAnchorAndMarginPreset(_gameChat, LayoutContainer.LayoutPreset.TopRight, margin: 10); LayoutContainer.SetAnchorAndMarginPreset(_gameChat, LayoutContainer.LayoutPreset.TopRight, margin: 10); @@ -50,6 +53,9 @@ namespace Content.Client.State _inputManager.SetInputCommand(ContentKeyFunctions.FocusOOC, InputCmdHandler.FromDelegate(s => FocusOOC(_gameChat))); + + _inputManager.SetInputCommand(ContentKeyFunctions.FocusAdminChat, + InputCmdHandler.FromDelegate(s => FocusAdminChat(_gameChat))); } public override void Shutdown() @@ -81,5 +87,17 @@ namespace Content.Client.State chat.Input.GrabKeyboardFocus(); chat.Input.InsertAtCursor("["); } + + internal static void FocusAdminChat(ChatBox chat) + { + if (chat == null || chat.UserInterfaceManager.KeyboardFocused != null) + { + return; + } + + chat.Input.IgnoreNext = true; + chat.Input.GrabKeyboardFocus(); + chat.Input.InsertAtCursor("]"); + } } } diff --git a/Content.Client/UserInterface/TutorialWindow.cs b/Content.Client/UserInterface/TutorialWindow.cs index d34ac4cb0d..bf6796e789 100644 --- a/Content.Client/UserInterface/TutorialWindow.cs +++ b/Content.Client/UserInterface/TutorialWindow.cs @@ -76,6 +76,7 @@ Open character window: [color=#a4885c]{8}[/color] Open crafting window: [color=#a4885c]{9}[/color] Focus chat: [color=#a4885c]{10}[/color] Focus OOC: [color=#a4885c]{26}[/color] +Focus Admin Chat: [color=#a4885c]{27}[/color] Use hand/object in hand: [color=#a4885c]{22}[/color] Do wide attack: [color=#a4885c]{23}[/color] Use targeted entity: [color=#a4885c]{11}[/color] @@ -112,7 +113,8 @@ Toggle sandbox window: [color=#a4885c]{21}[/color]", Key(WideAttack), Key(SmartEquipBackpack), Key(SmartEquipBelt), - Key(FocusOOC))); + Key(FocusOOC), + Key(FocusAdminChat))); //Gameplay VBox.AddChild(new Label { FontOverride = headerFont, Text = "\nGameplay" }); diff --git a/Content.Server/Chat/ChatCommands.cs b/Content.Server/Chat/ChatCommands.cs index 99a6d06963..051c382bcf 100644 --- a/Content.Server/Chat/ChatCommands.cs +++ b/Content.Server/Chat/ChatCommands.cs @@ -4,6 +4,7 @@ using Content.Server.Interfaces.Chat; using Content.Server.Interfaces.GameObjects; using Content.Server.Players; using Content.Shared.GameObjects; +using Robust.Server.Console; using Robust.Server.Interfaces.Console; using Robust.Server.Interfaces.Player; using Robust.Shared.Enums; @@ -79,6 +80,19 @@ namespace Content.Server.Chat } } + internal class AdminChatCommand : IClientCommand + { + public string Command => "asay"; + public string Description => "Send chat messages to the private admin chat channel."; + public string Help => "asay "; + + public void Execute(IConsoleShell shell, IPlayerSession player, string[] args) + { + var chat = IoCManager.Resolve(); + chat.SendAdminChat(player, string.Join(" ", args)); + } + } + internal class SuicideCommand : IClientCommand { public string Command => "suicide"; diff --git a/Content.Server/Chat/ChatManager.cs b/Content.Server/Chat/ChatManager.cs index 60c6eb4a64..21dedca1df 100644 --- a/Content.Server/Chat/ChatManager.cs +++ b/Content.Server/Chat/ChatManager.cs @@ -7,6 +7,7 @@ using Content.Server.Observer; using Content.Server.Players; using Content.Shared.Chat; using Content.Shared.GameObjects.EntitySystems; +using Robust.Server.Console; using Robust.Server.Interfaces.Player; using Robust.Shared.Interfaces.GameObjects; using Robust.Shared.Interfaces.Network; @@ -28,6 +29,7 @@ namespace Content.Server.Chat [Dependency] private readonly IPlayerManager _playerManager; [Dependency] private readonly ILocalizationManager _localizationManager; [Dependency] private readonly IMoMMILink _mommiLink; + [Dependency] private readonly IConGroupController _conGroupController; #pragma warning restore 649 public void Initialize() @@ -112,6 +114,23 @@ namespace Content.Server.Chat _netManager.ServerSendToMany(msg, clients.ToList()); } + public void SendAdminChat(IPlayerSession player, string message) + { + if(!_conGroupController.CanCommand(player, "asay")) + { + SendOOC(player, message); + return; + } + var clients = _playerManager.GetPlayersBy(x => _conGroupController.CanCommand(x, "asay")).Select(p => p.ConnectedClient);; + + var msg = _netManager.CreateNetMessage(); + + msg.Channel = ChatChannel.AdminChat; + msg.Message = message; + msg.MessageWrap = $"{_localizationManager.GetString("ADMIN")}: {player.SessionId}: {{0}}"; + _netManager.ServerSendToMany(msg, clients.ToList()); + } + public void SendHookOOC(string sender, string message) { var msg = _netManager.CreateNetMessage(); diff --git a/Content.Server/Interfaces/Chat/IChatManager.cs b/Content.Server/Interfaces/Chat/IChatManager.cs index 26af31827a..c3c9b6ceb3 100644 --- a/Content.Server/Interfaces/Chat/IChatManager.cs +++ b/Content.Server/Interfaces/Chat/IChatManager.cs @@ -18,6 +18,7 @@ namespace Content.Server.Interfaces.Chat void EntityMe(IEntity source, string action); void SendOOC(IPlayerSession player, string message); + void SendAdminChat(IPlayerSession player, string message); void SendDeadChat(IPlayerSession player, string message); void SendHookOOC(string sender, string message); diff --git a/Content.Shared/Chat/ChatChannel.cs b/Content.Shared/Chat/ChatChannel.cs index 4c9da79f0b..4b63a75b11 100644 --- a/Content.Shared/Chat/ChatChannel.cs +++ b/Content.Shared/Chat/ChatChannel.cs @@ -51,9 +51,14 @@ namespace Content.Shared.Chat /// Dead = 128, + /// + /// Admin chat + /// + AdminChat = 256, + /// /// Unspecified. /// - Unspecified = 256, + Unspecified = 512, } } diff --git a/Content.Shared/Chat/MsgChatMessage.cs b/Content.Shared/Chat/MsgChatMessage.cs index 10e73d881e..049024ccf4 100644 --- a/Content.Shared/Chat/MsgChatMessage.cs +++ b/Content.Shared/Chat/MsgChatMessage.cs @@ -41,7 +41,7 @@ namespace Content.Shared.Chat public override void ReadFromBuffer(NetIncomingMessage buffer) { - Channel = (ChatChannel) buffer.ReadByte(); + Channel = (ChatChannel) buffer.ReadInt16(); Message = buffer.ReadString(); MessageWrap = buffer.ReadString(); @@ -49,6 +49,7 @@ namespace Content.Shared.Chat { case ChatChannel.Local: case ChatChannel.Dead: + case ChatChannel.AdminChat: case ChatChannel.Emotes: SenderEntity = buffer.ReadEntityUid(); break; @@ -57,7 +58,7 @@ namespace Content.Shared.Chat public override void WriteToBuffer(NetOutgoingMessage buffer) { - buffer.Write((byte)Channel); + buffer.Write((short)Channel); buffer.Write(Message); buffer.Write(MessageWrap); @@ -65,6 +66,7 @@ namespace Content.Shared.Chat { case ChatChannel.Local: case ChatChannel.Dead: + case ChatChannel.AdminChat: case ChatChannel.Emotes: buffer.Write(SenderEntity); break; diff --git a/Content.Shared/Input/ContentKeyFunctions.cs b/Content.Shared/Input/ContentKeyFunctions.cs index bdbc7cee49..90b5820089 100644 --- a/Content.Shared/Input/ContentKeyFunctions.cs +++ b/Content.Shared/Input/ContentKeyFunctions.cs @@ -12,6 +12,7 @@ namespace Content.Shared.Input public static readonly BoundKeyFunction ExamineEntity = "ExamineEntity"; public static readonly BoundKeyFunction FocusChat = "FocusChatWindow"; public static readonly BoundKeyFunction FocusOOC = "FocusOOCWindow"; + public static readonly BoundKeyFunction FocusAdminChat = "FocusAdminChatWindow"; public static readonly BoundKeyFunction OpenCharacterMenu = "OpenCharacterMenu"; public static readonly BoundKeyFunction OpenContextMenu = "OpenContextMenu"; public static readonly BoundKeyFunction OpenCraftingMenu = "OpenCraftingMenu"; diff --git a/Resources/Groups/groups.yml b/Resources/Groups/groups.yml index dc76b17683..30af430579 100644 --- a/Resources/Groups/groups.yml +++ b/Resources/Groups/groups.yml @@ -82,6 +82,7 @@ - warp - hostlogin - deleteewc + - asay CanViewVar: true CanAdminPlace: true @@ -152,6 +153,7 @@ - warp - deleteewc - sudo + - asay CanViewVar: true CanAdminPlace: true CanScript: true diff --git a/Resources/keybinds.yml b/Resources/keybinds.yml index 5c2a9da3c3..8a715222da 100644 --- a/Resources/keybinds.yml +++ b/Resources/keybinds.yml @@ -46,6 +46,9 @@ binds: - function: FocusOOCWindow type: State key: LBracket +- function: FocusAdminChatWindow + type: State + key: RBracket - function: EditorLinePlace type: State key: MouseLeft From ae1c578e8e4f8056000cbf69b61a355e3c193b0c Mon Sep 17 00:00:00 2001 From: Metal Gear Sloth Date: Wed, 8 Jul 2020 21:05:27 +1000 Subject: [PATCH 15/19] Fix pathfinding entity deletions Also some slight optimisations in the process. --- .../AI/Pathfinding/PathfindingChunk.cs | 3 +- .../AI/Pathfinding/PathfindingNode.cs | 32 ++-- .../AI/Pathfinding/PathfindingSystem.cs | 154 ++++++------------ 3 files changed, 67 insertions(+), 122 deletions(-) diff --git a/Content.Server/GameObjects/EntitySystems/AI/Pathfinding/PathfindingChunk.cs b/Content.Server/GameObjects/EntitySystems/AI/Pathfinding/PathfindingChunk.cs index 202961dc3f..90af19c821 100644 --- a/Content.Server/GameObjects/EntitySystems/AI/Pathfinding/PathfindingChunk.cs +++ b/Content.Server/GameObjects/EntitySystems/AI/Pathfinding/PathfindingChunk.cs @@ -29,9 +29,8 @@ namespace Content.Server.GameObjects.EntitySystems.AI.Pathfinding _indices = indices; } - public void Initialize() + public void Initialize(IMapGrid grid) { - var grid = IoCManager.Resolve().GetGrid(GridId); for (var x = 0; x < ChunkSize; x++) { for (var y = 0; y < ChunkSize; y++) diff --git a/Content.Server/GameObjects/EntitySystems/AI/Pathfinding/PathfindingNode.cs b/Content.Server/GameObjects/EntitySystems/AI/Pathfinding/PathfindingNode.cs index 855bad56e7..57e96fde61 100644 --- a/Content.Server/GameObjects/EntitySystems/AI/Pathfinding/PathfindingNode.cs +++ b/Content.Server/GameObjects/EntitySystems/AI/Pathfinding/PathfindingNode.cs @@ -98,6 +98,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) { // If we're a door @@ -128,25 +129,28 @@ namespace Content.Server.GameObjects.EntitySystems.Pathfinding } } + /// + /// Remove the entity from this node. + /// Will check each category and remove it from the applicable one + /// + /// public void RemoveEntity(IEntity entity) { - if (_accessReaders.ContainsKey(entity.Uid)) + // 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 (_physicsUids.Contains(entity.Uid)) + { + _physicsUids.Remove(entity.Uid); + } + else if (_accessReaders.ContainsKey(entity.Uid)) { _accessReaders.Remove(entity.Uid); - return; - } - - if (entity.HasComponent()) + } + else if (_blockedCollidables.ContainsKey(entity.Uid)) { - if (entity.TryGetComponent(out PhysicsComponent physicsComponent) && physicsComponent.Anchored) - { - _blockedCollidables.Remove(entity.Uid); - GenerateMask(); - } - else - { - _physicsUids.Remove(entity.Uid); - } + _blockedCollidables.Remove(entity.Uid); + GenerateMask(); } } diff --git a/Content.Server/GameObjects/EntitySystems/AI/Pathfinding/PathfindingSystem.cs b/Content.Server/GameObjects/EntitySystems/AI/Pathfinding/PathfindingSystem.cs index 5a718e01e2..efd558603b 100644 --- a/Content.Server/GameObjects/EntitySystems/AI/Pathfinding/PathfindingSystem.cs +++ b/Content.Server/GameObjects/EntitySystems/AI/Pathfinding/PathfindingSystem.cs @@ -7,6 +7,7 @@ using Content.Server.GameObjects.EntitySystems.JobQueues; using Content.Server.GameObjects.EntitySystems.JobQueues.Queues; using Content.Server.GameObjects.EntitySystems.Pathfinding; using Content.Shared.Physics; +using Robust.Shared.GameObjects; using Robust.Shared.GameObjects.Components; using Robust.Shared.GameObjects.Components.Transform; using Robust.Shared.GameObjects.Systems; @@ -40,13 +41,13 @@ namespace Content.Server.GameObjects.EntitySystems.AI.Pathfinding private readonly PathfindingJobQueue _pathfindingQueue = new PathfindingJobQueue(); // Queued pathfinding graph updates - private readonly Queue _collidableUpdateQueue = new Queue(); + private readonly Queue _collidableUpdateQueue = new Queue(); private readonly Queue _moveUpdateQueue = new Queue(); private readonly Queue _accessReaderUpdateQueue = new Queue(); 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 | @@ -88,11 +89,11 @@ namespace Content.Server.GameObjects.EntitySystems.AI.Pathfinding var entity = _entitymanager.GetEntity(update.Owner); if (update.CanCollide) { - HandleCollidableAdd(entity); + HandleEntityAdd(entity); } else { - HandleAccessRemove(entity); + HandleEntityRemove(entity); } totalUpdates++; @@ -105,11 +106,11 @@ namespace Content.Server.GameObjects.EntitySystems.AI.Pathfinding var entity = _entitymanager.GetEntity(update.Uid); if (update.Enabled) { - HandleAccessAdd(entity); + HandleEntityAdd(entity); } else { - HandleAccessRemove(entity); + HandleEntityRemove(entity); } totalUpdates++; @@ -166,15 +167,22 @@ namespace Content.Server.GameObjects.EntitySystems.AI.Pathfinding private PathfindingChunk CreateChunk(GridId gridId, MapIndices indices) { var newChunk = new PathfindingChunk(gridId, indices); - newChunk.Initialize(); if (!_graph.ContainsKey(gridId)) { _graph.Add(gridId, new Dictionary()); } + _graph[gridId].Add(indices, newChunk); + newChunk.Initialize(_mapManager.GetGrid(gridId)); + return newChunk; } + /// + /// Return the corresponding PathfindingNode for this tile + /// + /// + /// public PathfindingNode GetNode(TileRef tile) { var chunk = GetChunk(tile); @@ -185,9 +193,9 @@ namespace Content.Server.GameObjects.EntitySystems.AI.Pathfinding public override void Initialize() { - SubscribeLocalEvent(QueueCollisionEnabledEvent); - SubscribeLocalEvent(QueueCollidableMove); - SubscribeLocalEvent(QueueAccessChangeEvent); + SubscribeLocalEvent(QueueCollisionChangeMessage); + SubscribeLocalEvent(QueueMoveEvent); + SubscribeLocalEvent(QueueAccessChangeMessage); // Handle all the base grid changes // Anything that affects traversal (i.e. collision layer) is handled separately. @@ -199,7 +207,7 @@ namespace Content.Server.GameObjects.EntitySystems.AI.Pathfinding public override void Shutdown() { base.Shutdown(); - UnsubscribeLocalEvent(); + UnsubscribeLocalEvent(); UnsubscribeLocalEvent(); UnsubscribeLocalEvent(); @@ -245,14 +253,19 @@ namespace Content.Server.GameObjects.EntitySystems.AI.Pathfinding _tileUpdateQueue.Enqueue(eventArgs.NewTile); } - private void QueueAccessChangeEvent(AccessReaderChangeMessage message) + private void QueueAccessChangeMessage(AccessReaderChangeMessage message) { _accessReaderUpdateQueue.Enqueue(message); } - private void HandleAccessAdd(IEntity entity) + /// + /// Tries to add the entity to the relevant pathfinding node + /// + /// The node will filter it to the correct category (if possible) + /// + private void HandleEntityAdd(IEntity entity) { - if (entity.Deleted || !entity.HasComponent()) + if (entity.Deleted || _lastKnownPositions.ContainsKey(entity.Uid)) { return; } @@ -263,82 +276,34 @@ namespace Content.Server.GameObjects.EntitySystems.AI.Pathfinding var chunk = GetChunk(tileRef); var node = chunk.GetNode(tileRef); node.AddEntity(entity); + _lastKnownPositions.Add(entity.Uid, node); } - private void HandleAccessRemove(IEntity entity) + private void HandleEntityRemove(IEntity entity) { - if (entity.Deleted || !entity.HasComponent()) + if (!_lastKnownPositions.TryGetValue(entity.Uid, out var node)) { return; } - - var grid = _mapManager.GetGrid(entity.Transform.GridID); - var tileRef = grid.GetTileRef(entity.Transform.GridPosition); - - var chunk = GetChunk(tileRef); - var node = chunk.GetNode(tileRef); - node.RemoveEntity(entity); - } - - #region collidable - /// - /// If an entity's collision gets turned on then we need to update its current position - /// - /// - private void HandleCollidableAdd(IEntity entity) - { - if (entity.Prototype == null || - entity.Deleted || - _lastKnownPositions.ContainsKey(entity) || - !entity.TryGetComponent(out CollidableComponent collidableComponent) || - !collidableComponent.CanCollide || - (TrackedCollisionLayers & collidableComponent.CollisionLayer) == 0) - { - return; - } - - var grid = _mapManager.GetGrid(entity.Transform.GridID); - var tileRef = grid.GetTileRef(entity.Transform.GridPosition); - var chunk = GetChunk(tileRef); - var node = chunk.GetNode(tileRef); - - node.AddEntity(entity); - _lastKnownPositions.Add(entity, tileRef); - } - - /// - /// If an entity's collision is removed then stop tracking it from the graph - /// - /// - private void HandleCollidableRemove(IEntity entity) - { - if (entity.Prototype == null || - entity.Deleted || - !_lastKnownPositions.ContainsKey(entity) || - !entity.TryGetComponent(out CollidableComponent collidableComponent) || - !collidableComponent.CanCollide || - (TrackedCollisionLayers & collidableComponent.CollisionLayer) == 0) - { - return; - } - - var grid = _mapManager.GetGrid(entity.Transform.GridID); - var tileRef = grid.GetTileRef(entity.Transform.GridPosition); - var chunk = GetChunk(tileRef); - var node = chunk.GetNode(tileRef); node.RemoveEntity(entity); - _lastKnownPositions.Remove(entity); + _lastKnownPositions.Remove(entity.Uid); } - private void QueueCollidableMove(MoveEvent moveEvent) + private void QueueMoveEvent(MoveEvent moveEvent) { _moveUpdateQueue.Enqueue(moveEvent); } + /// + /// 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) { - if (!_lastKnownPositions.ContainsKey(moveEvent.Sender)) + var entityUid = moveEvent.Sender.Uid; + + if (!_lastKnownPositions.TryGetValue(entityUid, out var oldNode)) { return; } @@ -347,51 +312,28 @@ namespace Content.Server.GameObjects.EntitySystems.AI.Pathfinding // If you get entities bigger than 1 tile wide you'll need some other system so god help you. if (moveEvent.Sender.Deleted) { - HandleCollidableRemove(moveEvent.Sender); + HandleEntityRemove(moveEvent.Sender); return; } - - _lastKnownPositions.TryGetValue(moveEvent.Sender, out var oldTile); + var newTile = _mapManager.GetGrid(moveEvent.NewPosition.GridID).GetTileRef(moveEvent.NewPosition); - if (oldTile == newTile) + if (oldNode == null || oldNode.TileRef == newTile) { return; } - _lastKnownPositions[moveEvent.Sender] = newTile; + var newNode = GetNode(newTile); + _lastKnownPositions[entityUid] = newNode; - if (!moveEvent.Sender.HasComponent()) - { - HandleCollidableRemove(moveEvent.Sender); - return; - } - - var gridIds = new HashSet(2) {oldTile.GridIndex, newTile.GridIndex}; - - foreach (var gridId in gridIds) - { - if (oldTile.GridIndex == gridId) - { - var oldChunk = GetChunk(oldTile); - var oldNode = oldChunk.GetNode(oldTile); - oldNode.RemoveEntity(moveEvent.Sender); - } - - if (newTile.GridIndex == gridId) - { - var newChunk = GetChunk(newTile); - var newNode = newChunk.GetNode(newTile); - newNode.AddEntity(moveEvent.Sender); - } - } + oldNode.RemoveEntity(moveEvent.Sender); + newNode.AddEntity(moveEvent.Sender); } - private void QueueCollisionEnabledEvent(CollisionChangeEvent collisionEvent) + private void QueueCollisionChangeMessage(CollisionChangeMessage collisionMessage) { - _collidableUpdateQueue.Enqueue(collisionEvent); + _collidableUpdateQueue.Enqueue(collisionMessage); } - #endregion // TODO: Need to rethink the pathfinder utils (traversable etc.). Maybe just chuck them all in PathfindingSystem // Otherwise you get the steerer using this and the pathfinders using a different traversable. From facaee0cab0aee5ee6c84a6efec794760a6995c0 Mon Sep 17 00:00:00 2001 From: Metal Gear Sloth Date: Wed, 8 Jul 2020 21:12:23 +1000 Subject: [PATCH 16/19] Remove redundant method Not used anymore. --- .../EntitySystems/AI/Pathfinding/PathfindingChunk.cs | 6 ------ 1 file changed, 6 deletions(-) diff --git a/Content.Server/GameObjects/EntitySystems/AI/Pathfinding/PathfindingChunk.cs b/Content.Server/GameObjects/EntitySystems/AI/Pathfinding/PathfindingChunk.cs index 90af19c821..56c25d4670 100644 --- a/Content.Server/GameObjects/EntitySystems/AI/Pathfinding/PathfindingChunk.cs +++ b/Content.Server/GameObjects/EntitySystems/AI/Pathfinding/PathfindingChunk.cs @@ -156,12 +156,6 @@ namespace Content.Server.GameObjects.EntitySystems.AI.Pathfinding return _nodes[chunkX, chunkY]; } - public void UpdateNode(TileRef tile) - { - var node = GetNode(tile); - node.UpdateTile(tile); - } - private void CreateNode(TileRef tile, PathfindingChunk parent = null) { if (parent == null) From d20e4969e2d7075abb7fe854356ace90579e2505 Mon Sep 17 00:00:00 2001 From: DrSmugleaf Date: Wed, 8 Jul 2020 13:41:32 +0200 Subject: [PATCH 17/19] Add light to lit welders (#1282) * Add light to lit welders * Fix null errors * Make the welder light orange --- .../Interactable/WelderComponent.cs | 33 ++++++++++++------- Resources/Prototypes/Entities/Items/tools.yml | 5 ++- 2 files changed, 25 insertions(+), 13 deletions(-) diff --git a/Content.Server/GameObjects/Components/Interactable/WelderComponent.cs b/Content.Server/GameObjects/Components/Interactable/WelderComponent.cs index 8be75e5e18..26d1498946 100644 --- a/Content.Server/GameObjects/Components/Interactable/WelderComponent.cs +++ b/Content.Server/GameObjects/Components/Interactable/WelderComponent.cs @@ -1,4 +1,5 @@ -using System; +#nullable enable +using System; using System.Runtime.Remoting; using Content.Server.GameObjects.Components.Chemistry; using Content.Server.GameObjects.EntitySystems.Click; @@ -27,8 +28,8 @@ namespace Content.Server.GameObjects.Components.Interactable public class WelderComponent : ToolComponent, IExamine, IUse, ISuicideAct, ISolutionChange { #pragma warning disable 649 - [Dependency] private IEntitySystemManager _entitySystemManager; - [Dependency] private IServerNotifyManager _notifyManager; + [Dependency] private readonly IEntitySystemManager _entitySystemManager = default!; + [Dependency] private readonly IServerNotifyManager _notifyManager = default!; #pragma warning restore 649 public override string Name => "Welder"; @@ -44,10 +45,11 @@ namespace Content.Server.GameObjects.Components.Interactable /// public const float FuelLossRate = 0.5f; - private bool _welderLit = false; - private WelderSystem _welderSystem; - private SpriteComponent _spriteComponent; - private SolutionComponent _solutionComponent; + private bool _welderLit; + private WelderSystem _welderSystem = default!; + private SpriteComponent? _spriteComponent; + private SolutionComponent? _solutionComponent; + private PointLightComponent? _pointLightComponent; [ViewVariables] public float Fuel => _solutionComponent?.Solution.GetReagentQuantity("chem.WeldingFuel").Float() ?? 0f; @@ -79,6 +81,7 @@ namespace Content.Server.GameObjects.Components.Interactable Owner.TryGetComponent(out _solutionComponent); Owner.TryGetComponent(out _spriteComponent); + Owner.TryGetComponent(out _pointLightComponent); } public override ComponentState GetComponentState() @@ -98,7 +101,7 @@ namespace Content.Server.GameObjects.Components.Interactable return base.UseTool(user, target, toolQualityNeeded) && TryWeld(fuelConsumed, user); } - private bool TryWeld(float value, IEntity user = null, bool silent = false) + private bool TryWeld(float value, IEntity? user = null, bool silent = false) { if (!WelderLit) { @@ -131,7 +134,7 @@ namespace Content.Server.GameObjects.Components.Interactable /// /// Deactivates welding tool if active, activates welding tool if possible /// - private bool ToggleWelderStatus(IEntity user = null) + private bool ToggleWelderStatus(IEntity? user = null) { var item = Owner.GetComponent(); @@ -140,7 +143,10 @@ namespace Content.Server.GameObjects.Components.Interactable WelderLit = false; // Layer 1 is the flame. item.EquippedPrefix = "off"; - _spriteComponent.LayerSetVisible(1, false); + _spriteComponent?.LayerSetVisible(1, false); + + if (_pointLightComponent != null) _pointLightComponent.Enabled = false; + PlaySoundCollection("WelderOff", -5); _welderSystem.Unsubscribe(this); return true; @@ -154,7 +160,10 @@ namespace Content.Server.GameObjects.Components.Interactable WelderLit = true; item.EquippedPrefix = "on"; - _spriteComponent.LayerSetVisible(1, true); + _spriteComponent?.LayerSetVisible(1, true); + + if (_pointLightComponent != null) _pointLightComponent.Enabled = true; + PlaySoundCollection("WelderOn", -5); _welderSystem.Subscribe(this); return true; @@ -188,7 +197,7 @@ namespace Content.Server.GameObjects.Components.Interactable if (!HasQuality(ToolQuality.Welding) || !WelderLit) return; - _solutionComponent.TryRemoveReagent("chem.WeldingFuel", ReagentUnit.New(FuelLossRate * frameTime)); + _solutionComponent?.TryRemoveReagent("chem.WeldingFuel", ReagentUnit.New(FuelLossRate * frameTime)); if (Fuel == 0) ToggleWelderStatus(); diff --git a/Resources/Prototypes/Entities/Items/tools.yml b/Resources/Prototypes/Entities/Items/tools.yml index 12ff44c951..b7be1f5173 100644 --- a/Resources/Prototypes/Entities/Items/tools.yml +++ b/Resources/Prototypes/Entities/Items/tools.yml @@ -96,9 +96,12 @@ reagents: - ReagentId: chem.WeldingFuel Quantity: 100 - - type: Welder useSoundCollection: Welder + - type: PointLight + enabled: false + radius: 1.5 + color: orange - type: entity name: wrench From 1fbd32c9d9324e9786ffbc76057992b86a6c5831 Mon Sep 17 00:00:00 2001 From: AJCM-git <60196617+AJCM-git@users.noreply.github.com> Date: Wed, 8 Jul 2020 07:58:21 -0400 Subject: [PATCH 18/19] Misc path fixes (#1319) * fixing wall girder sprite * fixing lathe --- Resources/Prototypes/Catalog/LatheRecipes/tools.yml | 3 ++- Resources/Prototypes/Construction/structures.yml | 4 ++-- 2 files changed, 4 insertions(+), 3 deletions(-) diff --git a/Resources/Prototypes/Catalog/LatheRecipes/tools.yml b/Resources/Prototypes/Catalog/LatheRecipes/tools.yml index 87635aeb03..e07bbd3b97 100644 --- a/Resources/Prototypes/Catalog/LatheRecipes/tools.yml +++ b/Resources/Prototypes/Catalog/LatheRecipes/tools.yml @@ -10,7 +10,7 @@ id: Screwdriver icon: sprite: Objects/Tools/screwdriver.rsi - state: screwdriver + state: screwdriver-map result: Screwdriver completetime: 500 materials: @@ -38,6 +38,7 @@ - type: latheRecipe id: CableStack + name: cable coil icon: Objects/Tools/cable_coil.png result: CableStack completetime: 500 diff --git a/Resources/Prototypes/Construction/structures.yml b/Resources/Prototypes/Construction/structures.yml index 3245fe7279..7992012921 100644 --- a/Resources/Prototypes/Construction/structures.yml +++ b/Resources/Prototypes/Construction/structures.yml @@ -12,7 +12,7 @@ steps: - material: Metal amount: 2 - icon: Constructible/Walls/wall_girder.png + icon: Constructible/Structures/Walls/wall_girder.png reverse: tool: Anchoring @@ -65,7 +65,7 @@ steps: - material: Metal amount: 2 - icon: Constructible/Walls/wall_girder.png + icon: Constructible/Structures/Walls/wall_girder.png reverse: tool: Anchoring From 7e2f13dbe1724046369160feb76f4365c2b35070 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?V=C3=ADctor=20Aguilera=20Puerto?= Date: Wed, 8 Jul 2020 15:30:22 +0200 Subject: [PATCH 19/19] Update submodule --- RobustToolbox | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/RobustToolbox b/RobustToolbox index afa0eb8ada..d1ee8775f4 160000 --- a/RobustToolbox +++ b/RobustToolbox @@ -1 +1 @@ -Subproject commit afa0eb8ada3d81feb8eaa5ebecc5dd91657807d9 +Subproject commit d1ee8775f4293629ba0c1535c1cff45ea57a55c7