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(); } } }