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 <metalgearsloth@gmail.com>
This commit is contained in:
@@ -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
|
||||
{
|
||||
@@ -37,11 +38,17 @@ namespace Content.Server.AI.Utility.Actions.Clothing.Gloves
|
||||
context.GetState<TargetEntityState>().SetValue(_entity);
|
||||
}
|
||||
|
||||
protected override Consideration[] Considerations { get; } = {
|
||||
new ClothingInSlotCon(EquipmentSlotDefines.Slots.GLOVES,
|
||||
new InverseBoolCurve()),
|
||||
new CanPutTargetInHandsCon(
|
||||
new BoolCurve()),
|
||||
protected override IReadOnlyCollection<Func<float>> GetConsiderations(Blackboard context)
|
||||
{
|
||||
var considerationsManager = IoCManager.Resolve<ConsiderationsManager>();
|
||||
|
||||
return new[]
|
||||
{
|
||||
considerationsManager.Get<ClothingInSlotCon>().Slot(EquipmentSlotDefines.Slots.GLOVES, context)
|
||||
.InverseBoolCurve(context),
|
||||
considerationsManager.Get<CanPutTargetInHandsCon>()
|
||||
.BoolCurve(context),
|
||||
};
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -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
|
||||
{
|
||||
@@ -31,13 +33,19 @@ namespace Content.Server.AI.Utility.Actions.Clothing.Gloves
|
||||
context.GetState<TargetEntityState>().SetValue(_entity);
|
||||
}
|
||||
|
||||
protected override Consideration[] Considerations { get; } = {
|
||||
new ClothingInSlotCon(EquipmentSlotDefines.Slots.GLOVES,
|
||||
new InverseBoolCurve()),
|
||||
new CanPutTargetInHandsCon(
|
||||
new BoolCurve()),
|
||||
new ClothingInInventoryCon(EquipmentSlotDefines.SlotFlags.GLOVES,
|
||||
new InverseBoolCurve()),
|
||||
protected override IReadOnlyCollection<Func<float>> GetConsiderations(Blackboard context)
|
||||
{
|
||||
var considerationsManager = IoCManager.Resolve<ConsiderationsManager>();
|
||||
|
||||
return new[]
|
||||
{
|
||||
considerationsManager.Get<ClothingInSlotCon>().Slot(EquipmentSlotDefines.Slots.GLOVES, context)
|
||||
.InverseBoolCurve(context),
|
||||
considerationsManager.Get<CanPutTargetInHandsCon>()
|
||||
.BoolCurve(context),
|
||||
considerationsManager.Get<ClothingInInventoryCon>().Slot(EquipmentSlotDefines.SlotFlags.GLOVES, context)
|
||||
.InverseBoolCurve(context)
|
||||
};
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -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<TargetEntityState>().SetValue(_entity);
|
||||
}
|
||||
|
||||
protected override Consideration[] Considerations { get; } = {
|
||||
new ClothingInSlotCon(EquipmentSlotDefines.Slots.HEAD,
|
||||
new InverseBoolCurve()),
|
||||
new CanPutTargetInHandsCon(
|
||||
new BoolCurve()),
|
||||
protected override IReadOnlyCollection<Func<float>> GetConsiderations(Blackboard context)
|
||||
{
|
||||
var considerationsManager = IoCManager.Resolve<ConsiderationsManager>();
|
||||
|
||||
return new[]
|
||||
{
|
||||
considerationsManager.Get<ClothingInSlotCon>().Slot(EquipmentSlotDefines.Slots.HEAD, context)
|
||||
.InverseBoolCurve(context),
|
||||
considerationsManager.Get<CanPutTargetInHandsCon>()
|
||||
.BoolCurve(context),
|
||||
};
|
||||
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -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<TargetEntityState>().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<Func<float>> GetConsiderations(Blackboard context)
|
||||
{
|
||||
var considerationsManager = IoCManager.Resolve<ConsiderationsManager>();
|
||||
|
||||
return new[]
|
||||
{
|
||||
considerationsManager.Get<ClothingInSlotCon>().Slot(EquipmentSlotDefines.Slots.HEAD, context)
|
||||
.InverseBoolCurve(context),
|
||||
considerationsManager.Get<CanPutTargetInHandsCon>()
|
||||
.BoolCurve(context),
|
||||
considerationsManager.Get<ClothingInInventoryCon>().Slot(EquipmentSlotDefines.SlotFlags.HEAD, context)
|
||||
.InverseBoolCurve(context)
|
||||
};
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -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<TargetEntityState>().SetValue(_entity);
|
||||
}
|
||||
|
||||
protected override Consideration[] Considerations { get; } = {
|
||||
new ClothingInSlotCon(EquipmentSlotDefines.Slots.OUTERCLOTHING,
|
||||
new InverseBoolCurve()),
|
||||
new CanPutTargetInHandsCon(
|
||||
new BoolCurve()),
|
||||
protected override IReadOnlyCollection<Func<float>> GetConsiderations(Blackboard context)
|
||||
{
|
||||
var considerationsManager = IoCManager.Resolve<ConsiderationsManager>();
|
||||
|
||||
return new[]
|
||||
{
|
||||
considerationsManager.Get<ClothingInSlotCon>().Slot(EquipmentSlotDefines.Slots.OUTERCLOTHING, context)
|
||||
.InverseBoolCurve(context),
|
||||
considerationsManager.Get<CanPutTargetInHandsCon>()
|
||||
.BoolCurve(context),
|
||||
};
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -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<TargetEntityState>().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<Func<float>> GetConsiderations(Blackboard context)
|
||||
{
|
||||
var considerationsManager = IoCManager.Resolve<ConsiderationsManager>();
|
||||
|
||||
return new[]
|
||||
{
|
||||
considerationsManager.Get<ClothingInSlotCon>().Slot(EquipmentSlotDefines.Slots.OUTERCLOTHING, context)
|
||||
.InverseBoolCurve(context),
|
||||
considerationsManager.Get<CanPutTargetInHandsCon>()
|
||||
.BoolCurve(context),
|
||||
considerationsManager.Get<ClothingInInventoryCon>().Slot(EquipmentSlotDefines.SlotFlags.OUTERCLOTHING, context)
|
||||
.InverseBoolCurve(context)
|
||||
};
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -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<TargetEntityState>().SetValue(_entity);
|
||||
}
|
||||
|
||||
protected override Consideration[] Considerations { get; } = {
|
||||
new ClothingInSlotCon(EquipmentSlotDefines.Slots.SHOES,
|
||||
new InverseBoolCurve()),
|
||||
new CanPutTargetInHandsCon(
|
||||
new BoolCurve()),
|
||||
protected override IReadOnlyCollection<Func<float>> GetConsiderations(Blackboard context)
|
||||
{
|
||||
var considerationsManager = IoCManager.Resolve<ConsiderationsManager>();
|
||||
|
||||
return new[]
|
||||
{
|
||||
considerationsManager.Get<ClothingInSlotCon>().Slot(EquipmentSlotDefines.Slots.SHOES, context)
|
||||
.InverseBoolCurve(context),
|
||||
considerationsManager.Get<CanPutTargetInHandsCon>()
|
||||
.BoolCurve(context),
|
||||
};
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -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<TargetEntityState>().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<Func<float>> GetConsiderations(Blackboard context)
|
||||
{
|
||||
var considerationsManager = IoCManager.Resolve<ConsiderationsManager>();
|
||||
|
||||
return new[]
|
||||
{
|
||||
considerationsManager.Get<ClothingInSlotCon>().Slot(EquipmentSlotDefines.Slots.SHOES, context)
|
||||
.InverseBoolCurve(context),
|
||||
considerationsManager.Get<CanPutTargetInHandsCon>()
|
||||
.BoolCurve(context),
|
||||
considerationsManager.Get<ClothingInInventoryCon>().Slot(EquipmentSlotDefines.SlotFlags.SHOES, context)
|
||||
.InverseBoolCurve(context)
|
||||
};
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -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<TargetEntityState>().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<Func<float>> GetConsiderations(Blackboard context)
|
||||
{
|
||||
var considerationsManager = IoCManager.Resolve<ConsiderationsManager>();
|
||||
|
||||
return new[]
|
||||
{
|
||||
considerationsManager.Get<MeleeWeaponEquippedCon>()
|
||||
.InverseBoolCurve(context),
|
||||
considerationsManager.Get<CanPutTargetInHandsCon>()
|
||||
.BoolCurve(context),
|
||||
considerationsManager.Get<MeleeWeaponSpeedCon>()
|
||||
.QuadraticCurve(context, 1.0f, 0.5f, 0.0f, 0.0f),
|
||||
considerationsManager.Get<MeleeWeaponDamageCon>()
|
||||
.QuadraticCurve(context, 1.0f, 0.25f, 0.0f, 0.0f),
|
||||
};
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -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<EquippedEntityState>().GetValue();
|
||||
MoveToEntityOperator moveOperator;
|
||||
var equipped = context.GetState<EquippedEntityState>().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);
|
||||
}
|
||||
|
||||
@@ -59,26 +59,27 @@ namespace Content.Server.AI.Utility.Actions.Combat.Melee
|
||||
context.GetState<WeaponEntityState>().SetValue(equipped);
|
||||
}
|
||||
|
||||
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)),
|
||||
protected override IReadOnlyCollection<Func<float>> GetConsiderations(Blackboard context)
|
||||
{
|
||||
var considerationsManager = IoCManager.Resolve<ConsiderationsManager>();
|
||||
|
||||
return new[]
|
||||
{
|
||||
considerationsManager.Get<MeleeWeaponEquippedCon>()
|
||||
.BoolCurve(context),
|
||||
considerationsManager.Get<TargetIsDeadCon>()
|
||||
.InverseBoolCurve(context),
|
||||
considerationsManager.Get<TargetIsCritCon>()
|
||||
.QuadraticCurve(context, -0.8f, 1.0f, 1.0f, 0.0f),
|
||||
considerationsManager.Get<DistanceCon>()
|
||||
.QuadraticCurve(context, 1.0f, 1.0f, 0.02f, 0.0f),
|
||||
considerationsManager.Get<TargetHealthCon>()
|
||||
.QuadraticCurve(context, 1.0f, 0.4f, 0.0f, -0.02f),
|
||||
considerationsManager.Get<MeleeWeaponSpeedCon>()
|
||||
.QuadraticCurve(context, 1.0f, 0.5f, 0.0f, 0.0f),
|
||||
considerationsManager.Get<MeleeWeaponDamageCon>()
|
||||
.QuadraticCurve(context, 1.0f, 0.25f, 0.0f, 0.0f),
|
||||
};
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -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
|
||||
{
|
||||
@@ -34,19 +36,25 @@ namespace Content.Server.AI.Utility.Actions.Combat.Melee
|
||||
context.GetState<WeaponEntityState>().SetValue(_entity);
|
||||
}
|
||||
|
||||
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)),
|
||||
protected override IReadOnlyCollection<Func<float>> GetConsiderations(Blackboard context)
|
||||
{
|
||||
var considerationsManager = IoCManager.Resolve<ConsiderationsManager>();
|
||||
|
||||
return new[]
|
||||
{
|
||||
considerationsManager.Get<TargetAccessibleCon>()
|
||||
.BoolCurve(context),
|
||||
considerationsManager.Get<FreeHandCon>()
|
||||
.BoolCurve(context),
|
||||
considerationsManager.Get<HasMeleeWeaponCon>()
|
||||
.InverseBoolCurve(context),
|
||||
considerationsManager.Get<DistanceCon>()
|
||||
.QuadraticCurve(context, 1.0f, 1.0f, 0.02f, 0.0f),
|
||||
considerationsManager.Get<MeleeWeaponDamageCon>()
|
||||
.QuadraticCurve(context, 1.0f, 0.25f, 0.0f, 0.0f),
|
||||
considerationsManager.Get<MeleeWeaponSpeedCon>()
|
||||
.QuadraticCurve(context, -1.0f, 0.5f, 1.0f, 0.0f),
|
||||
};
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -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<WeaponEntityState>().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)),
|
||||
protected override IReadOnlyCollection<Func<float>> GetConsiderations(Blackboard context)
|
||||
{
|
||||
var considerationsManager = IoCManager.Resolve<ConsiderationsManager>();
|
||||
|
||||
return new[]
|
||||
{
|
||||
considerationsManager.Get<CanUnarmedCombatCon>()
|
||||
.BoolCurve(context),
|
||||
considerationsManager.Get<TargetIsDeadCon>()
|
||||
.InverseBoolCurve(context),
|
||||
considerationsManager.Get<TargetIsCritCon>()
|
||||
.QuadraticCurve(context, -0.8f, 1.0f, 1.0f, 0.0f),
|
||||
considerationsManager.Get<DistanceCon>()
|
||||
.QuadraticCurve(context, -1.0f, 1.0f, 1.02f, 0.0f),
|
||||
considerationsManager.Get<TargetHealthCon>()
|
||||
.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)
|
||||
};
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -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<LastOpenedStorageState, IEntity>(
|
||||
new InverseBoolCurve()),
|
||||
new DistanceCon(
|
||||
new QuadraticCurve(-1.0f, 1.0f, 1.02f, 0.0f)),
|
||||
};
|
||||
public override void SetupOperators(Blackboard context)
|
||||
{
|
||||
var lastStorage = context.GetState<LastOpenedStorageState>().GetValue();
|
||||
@@ -38,5 +32,20 @@ namespace Content.Server.AI.Utility.Actions.Idle
|
||||
new CloseLastStorageOperator(Owner),
|
||||
});
|
||||
}
|
||||
|
||||
protected override IReadOnlyCollection<Func<float>> GetConsiderations(Blackboard context)
|
||||
{
|
||||
var considerationsManager = IoCManager.Resolve<ConsiderationsManager>();
|
||||
|
||||
return new[]
|
||||
{
|
||||
considerationsManager.Get<StoredStateEntityIsNullCon>().Set(typeof(LastOpenedStorageState), context)
|
||||
.InverseBoolCurve(context),
|
||||
considerationsManager.Get<DistanceCon>()
|
||||
.QuadraticCurve(context, 1.0f, 1.0f, 0.02f, 0.0f),
|
||||
|
||||
};
|
||||
}
|
||||
|
||||
}
|
||||
}
|
||||
@@ -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)
|
||||
{
|
||||
@@ -50,11 +48,17 @@ namespace Content.Server.AI.Utility.Actions.Idle
|
||||
});
|
||||
}
|
||||
|
||||
protected override Consideration[] Considerations { get; } = {
|
||||
new CanMoveCon(
|
||||
new BoolCurve())
|
||||
// Last wander? If we also want to sit still
|
||||
protected override IReadOnlyCollection<Func<float>> GetConsiderations(Blackboard context)
|
||||
{
|
||||
var considerationsManager = IoCManager.Resolve<ConsiderationsManager>();
|
||||
|
||||
return new[]
|
||||
{
|
||||
considerationsManager.Get<CanMoveCon>()
|
||||
.BoolCurve(context),
|
||||
|
||||
};
|
||||
}
|
||||
|
||||
private GridCoordinates FindRandomGrid()
|
||||
{
|
||||
|
||||
@@ -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
|
||||
{
|
||||
@@ -26,24 +28,30 @@ 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<TargetEntityState>().SetValue(_entity);
|
||||
}
|
||||
|
||||
protected override IReadOnlyCollection<Func<float>> GetConsiderations(Blackboard context)
|
||||
{
|
||||
var considerationsManager = IoCManager.Resolve<ConsiderationsManager>();
|
||||
|
||||
return new[]
|
||||
{
|
||||
considerationsManager.Get<TargetAccessibleCon>()
|
||||
.BoolCurve(context),
|
||||
considerationsManager.Get<FreeHandCon>()
|
||||
.BoolCurve(context),
|
||||
considerationsManager.Get<ThirstCon>()
|
||||
.LogisticCurve(context, 1000f, 1.3f, -1.0f, 0.5f),
|
||||
considerationsManager.Get<DistanceCon>()
|
||||
.QuadraticCurve(context, 1.0f, 1.0f, 0.02f, 0.0f),
|
||||
considerationsManager.Get<DrinkValueCon>()
|
||||
.QuadraticCurve(context, 1.0f, 0.4f, 0.0f, 0.0f),
|
||||
};
|
||||
}
|
||||
|
||||
}
|
||||
}
|
||||
|
||||
@@ -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
|
||||
{
|
||||
@@ -30,20 +31,25 @@ namespace Content.Server.AI.Utility.Actions.Nutrition.Drink
|
||||
});
|
||||
}
|
||||
|
||||
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<TargetEntityState>().SetValue(_entity);
|
||||
}
|
||||
|
||||
protected override IReadOnlyCollection<Func<float>> GetConsiderations(Blackboard context)
|
||||
{
|
||||
var considerationsManager = IoCManager.Resolve<ConsiderationsManager>();
|
||||
|
||||
return new[]
|
||||
{
|
||||
considerationsManager.Get<TargetInOurHandsCon>()
|
||||
.BoolCurve(context),
|
||||
considerationsManager.Get<ThirstCon>()
|
||||
.LogisticCurve(context, 1000f, 1.3f, -0.3f, 0.5f),
|
||||
considerationsManager.Get<DrinkValueCon>()
|
||||
.QuadraticCurve(context, 1.0f, 0.4f, 0.0f, 0.0f),
|
||||
};
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -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<TargetEntityState>().SetValue(_entity);
|
||||
}
|
||||
|
||||
protected override IReadOnlyCollection<Func<float>> GetConsiderations(Blackboard context)
|
||||
{
|
||||
var considerationsManager = IoCManager.Resolve<ConsiderationsManager>();
|
||||
|
||||
return new[]
|
||||
{
|
||||
considerationsManager.Get<TargetAccessibleCon>()
|
||||
.BoolCurve(context),
|
||||
considerationsManager.Get<FreeHandCon>()
|
||||
.BoolCurve(context),
|
||||
considerationsManager.Get<HungerCon>()
|
||||
.LogisticCurve(context, 1000f, 1.3f, -1.0f, 0.5f),
|
||||
considerationsManager.Get<DistanceCon>()
|
||||
.QuadraticCurve(context, 1.0f, 1.0f, 0.02f, 0.0f),
|
||||
considerationsManager.Get<FoodValueCon>()
|
||||
.QuadraticCurve(context, 1.0f, 0.4f, 0.0f, 0.0f),
|
||||
};
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -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<TargetEntityState>().SetValue(_entity);
|
||||
}
|
||||
|
||||
protected override IReadOnlyCollection<Func<float>> GetConsiderations(Blackboard context)
|
||||
{
|
||||
var considerationsManager = IoCManager.Resolve<ConsiderationsManager>();
|
||||
|
||||
return new[]
|
||||
{
|
||||
considerationsManager.Get<TargetInOurHandsCon>()
|
||||
.BoolCurve(context),
|
||||
considerationsManager.Get<HungerCon>()
|
||||
.LogisticCurve(context, 1000f, 1.3f, -0.3f, 0.5f),
|
||||
considerationsManager.Get<FoodValueCon>()
|
||||
.QuadraticCurve(context, 1.0f, 0.4f, 0.0f, 0.0f),
|
||||
|
||||
};
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -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<Func<float>> GetConsiderations(Blackboard context)
|
||||
{
|
||||
var considerationsManager = IoCManager.Resolve<ConsiderationsManager>();
|
||||
|
||||
return new[]
|
||||
{
|
||||
considerationsManager.Get<DummyCon>()
|
||||
.BoolCurve(context),
|
||||
};
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -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.
|
||||
/// </summary>
|
||||
protected abstract Consideration[] Considerations { get; }
|
||||
/// Uses Func<float> 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<Func<float>> GetConsiderations(Blackboard context);
|
||||
|
||||
/// <summary>
|
||||
/// 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<ConsiderationState>().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) {
|
||||
|
||||
@@ -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
|
||||
|
||||
@@ -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<SelfState>().GetValue();
|
||||
if (!ActionBlockerSystem.CanMove(self))
|
||||
|
||||
@@ -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<ClothingSlotFlagConState>().SetValue(slotFlags);
|
||||
return this;
|
||||
}
|
||||
|
||||
public override float GetScore(Blackboard context)
|
||||
protected override float GetScore(Blackboard context)
|
||||
{
|
||||
var inventory = context.GetState<InventoryState>().GetValue();
|
||||
var slots = context.GetState<ClothingSlotConState>().GetValue();
|
||||
var slotFlags = EquipmentSlotDefines.SlotMasks[slots];
|
||||
|
||||
foreach (var entity in inventory)
|
||||
foreach (var entity in context.GetState<EnumerableInventoryState>().GetValue())
|
||||
{
|
||||
if (!entity.TryGetComponent(out ClothingComponent clothingComponent))
|
||||
{
|
||||
continue;
|
||||
}
|
||||
|
||||
if ((clothingComponent.SlotFlags & _slot) != 0)
|
||||
if ((clothingComponent.SlotFlags & slotFlags) != 0)
|
||||
{
|
||||
return 1.0f;
|
||||
}
|
||||
|
||||
@@ -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<ClothingSlotConState>().SetValue(slot);
|
||||
return this;
|
||||
}
|
||||
|
||||
public override float GetScore(Blackboard context)
|
||||
protected override float GetScore(Blackboard context)
|
||||
{
|
||||
var slot = context.GetState<ClothingSlotConState>().GetValue();
|
||||
var inventory = context.GetState<EquippedClothingState>().GetValue();
|
||||
|
||||
return inventory.ContainsKey(_slot) ? 1.0f : 0.0f;
|
||||
return inventory.ContainsKey(slot) ? 1.0f : 0.0f;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -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<SelfState>().GetValue().HasComponent<UnarmedCombatComponent>() ? 1.0f : 0.0f;
|
||||
}
|
||||
|
||||
@@ -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<InventoryState>().GetValue())
|
||||
foreach (var item in context.GetState<EnumerableInventoryState>().GetValue())
|
||||
{
|
||||
if (item.HasComponent<MeleeWeaponComponent>())
|
||||
{
|
||||
|
||||
@@ -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<WeaponEntityState>().GetValue();
|
||||
|
||||
|
||||
@@ -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<EquippedEntityState>().GetValue();
|
||||
|
||||
|
||||
@@ -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<WeaponEntityState>().GetValue();
|
||||
|
||||
|
||||
@@ -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<TargetEntityState>().GetValue();
|
||||
|
||||
|
||||
@@ -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<TargetEntityState>().GetValue();
|
||||
|
||||
|
||||
@@ -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<TargetEntityState>().GetValue();
|
||||
|
||||
|
||||
@@ -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<ConsiderationState>().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<float> 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<float> 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<float> 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<float> 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;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -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<Type, Consideration> _considerations = new Dictionary<Type, Consideration>();
|
||||
|
||||
public void Initialize()
|
||||
{
|
||||
var reflectionManager = IoCManager.Resolve<IReflectionManager>();
|
||||
var typeFactory = IoCManager.Resolve<IDynamicTypeFactory>();
|
||||
|
||||
foreach (var conType in reflectionManager.GetAllChildren(typeof(Consideration)))
|
||||
{
|
||||
var con = (Consideration) typeFactory.CreateInstance(conType);
|
||||
_considerations.Add(conType, con);
|
||||
}
|
||||
}
|
||||
|
||||
public T Get<T>() where T : Consideration
|
||||
{
|
||||
return (T) _considerations[typeof(T)];
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -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
|
||||
/// </summary>
|
||||
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<TargetEntityState>().GetValue();
|
||||
if (target == null)
|
||||
|
||||
@@ -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;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -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<SelfState>().GetValue();
|
||||
|
||||
|
||||
@@ -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
|
||||
/// </summary>
|
||||
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<SelfState>().GetValue();
|
||||
var target = context.GetState<TargetEntityState>().GetValue();
|
||||
|
||||
@@ -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<InventoryState>().GetValue();
|
||||
|
||||
foreach (var item in inventory)
|
||||
foreach (var item in context.GetState<EnumerableInventoryState>().GetValue())
|
||||
{
|
||||
if (item == target)
|
||||
{
|
||||
|
||||
@@ -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<InventoryState>().GetValue();
|
||||
var target = context.GetState<TargetEntityState>().GetValue();
|
||||
|
||||
if (target == null || !target.HasComponent<ItemComponent>())
|
||||
@@ -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<EnumerableInventoryState>().GetValue())
|
||||
{
|
||||
if (item == target)
|
||||
{
|
||||
|
||||
@@ -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<SelfState>().GetValue();
|
||||
var target = context.GetState<TargetEntityState>().GetValue();
|
||||
|
||||
@@ -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<TargetEntityState>().GetValue();
|
||||
|
||||
|
||||
@@ -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<SelfState>().GetValue();
|
||||
|
||||
|
||||
@@ -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<TargetEntityState>().GetValue();
|
||||
|
||||
|
||||
@@ -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<SelfState>().GetValue();
|
||||
|
||||
|
||||
@@ -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
|
||||
{
|
||||
/// <summary>
|
||||
/// Simple NullCheck on a StoredState
|
||||
/// </summary>
|
||||
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<StoredStateIsNullState>().SetValue(type);
|
||||
return this;
|
||||
}
|
||||
|
||||
protected override float GetScore(Blackboard context)
|
||||
{
|
||||
var stateData = context.GetState<StoredStateIsNullState>().GetValue();
|
||||
return stateData == null ? 1.0f : 0.0f;
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -1,24 +0,0 @@
|
||||
using Content.Server.AI.Utility.Curves;
|
||||
using Content.Server.AI.WorldState;
|
||||
|
||||
namespace Content.Server.AI.Utility.Considerations.State
|
||||
{
|
||||
/// <summary>
|
||||
/// Simple NullCheck on a StoredState
|
||||
/// </summary>
|
||||
public sealed class StoredStateIsNullCon<T, U> : Consideration where T : StoredStateData<U>
|
||||
{
|
||||
public StoredStateIsNullCon(IResponseCurve curve) : base(curve) {}
|
||||
|
||||
public override float GetScore(Blackboard context)
|
||||
{
|
||||
var state = context.GetState<T>();
|
||||
if (state.GetValue() == null)
|
||||
{
|
||||
return 1.0f;
|
||||
}
|
||||
|
||||
return 0.0f;
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -21,12 +21,8 @@ namespace Content.Server.AI.Utility.ExpandableActions.Clothing.Gloves
|
||||
public override IEnumerable<UtilityAction> GetActions(Blackboard context)
|
||||
{
|
||||
var owner = context.GetState<SelfState>().GetValue();
|
||||
if (!owner.TryGetComponent(out AiControllerComponent controller))
|
||||
{
|
||||
throw new InvalidOperationException();
|
||||
}
|
||||
|
||||
foreach (var entity in context.GetState<InventoryState>().GetValue())
|
||||
foreach (var entity in context.GetState<EnumerableInventoryState>().GetValue())
|
||||
{
|
||||
if (entity.TryGetComponent(out ClothingComponent clothing) &&
|
||||
(clothing.SlotFlags & EquipmentSlotDefines.SlotFlags.GLOVES) != 0)
|
||||
|
||||
@@ -22,7 +22,7 @@ namespace Content.Server.AI.Utility.ExpandableActions.Clothing.Head
|
||||
{
|
||||
var owner = context.GetState<SelfState>().GetValue();
|
||||
|
||||
foreach (var entity in context.GetState<InventoryState>().GetValue())
|
||||
foreach (var entity in context.GetState<EnumerableInventoryState>().GetValue())
|
||||
{
|
||||
if (entity.TryGetComponent(out ClothingComponent clothing) &&
|
||||
(clothing.SlotFlags & EquipmentSlotDefines.SlotFlags.HEAD) != 0)
|
||||
|
||||
@@ -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<UtilityAction> GetActions(Blackboard context)
|
||||
{
|
||||
var owner = context.GetState<SelfState>().GetValue();
|
||||
|
||||
foreach (var entity in context.GetState<NearbyClothingState>().GetValue())
|
||||
{
|
||||
if (entity.TryGetComponent(out ClothingComponent clothing) &&
|
||||
|
||||
@@ -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<SelfState>().GetValue();
|
||||
|
||||
foreach (var entity in context.GetState<InventoryState>().GetValue())
|
||||
foreach (var entity in context.GetState<EnumerableInventoryState>().GetValue())
|
||||
{
|
||||
if (entity.TryGetComponent(out ClothingComponent clothing) &&
|
||||
(clothing.SlotFlags & EquipmentSlotDefines.SlotFlags.OUTERCLOTHING) != 0)
|
||||
|
||||
@@ -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<SelfState>().GetValue();
|
||||
|
||||
foreach (var entity in context.GetState<InventoryState>().GetValue())
|
||||
foreach (var entity in context.GetState<EnumerableInventoryState>().GetValue())
|
||||
{
|
||||
if (entity.TryGetComponent(out ClothingComponent clothing) &&
|
||||
(clothing.SlotFlags & EquipmentSlotDefines.SlotFlags.SHOES) != 0)
|
||||
|
||||
@@ -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<SelfState>().GetValue();
|
||||
|
||||
foreach (var entity in context.GetState<InventoryState>().GetValue())
|
||||
foreach (var entity in context.GetState<EnumerableInventoryState>().GetValue())
|
||||
{
|
||||
if (!entity.HasComponent<MeleeWeaponComponent>())
|
||||
{
|
||||
continue;
|
||||
}
|
||||
|
||||
yield return new EquipMelee(owner, entity, Bonus);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -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<SelfState>().GetValue();
|
||||
|
||||
foreach (var entity in context.GetState<InventoryState>().GetValue())
|
||||
foreach (var entity in context.GetState<EnumerableInventoryState>().GetValue())
|
||||
{
|
||||
if (!entity.HasComponent<DrinkComponent>())
|
||||
{
|
||||
continue;
|
||||
}
|
||||
|
||||
yield return new UseDrinkInInventory(owner, entity, Bonus);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -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<SelfState>().GetValue();
|
||||
|
||||
foreach (var entity in context.GetState<InventoryState>().GetValue())
|
||||
foreach (var entity in context.GetState<EnumerableInventoryState>().GetValue())
|
||||
{
|
||||
if (!entity.HasComponent<FoodComponent>())
|
||||
{
|
||||
continue;
|
||||
}
|
||||
|
||||
yield return new UseFoodInInventory(owner, entity, Bonus);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -56,6 +56,11 @@ namespace Content.Server.AI.WorldState
|
||||
}
|
||||
}
|
||||
|
||||
public void GetState(Type type, out IAiState state)
|
||||
{
|
||||
state = _states[type];
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Get the AI state class
|
||||
/// </summary>
|
||||
|
||||
@@ -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
|
||||
{
|
||||
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// The default class for state values. Also see CachedStateData and PlanningStateData
|
||||
/// </summary>
|
||||
@@ -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).
|
||||
/// </summary>
|
||||
/// <typeparam name="T"></typeparam>
|
||||
public abstract class StoredStateData<T> : IAiState
|
||||
public abstract class StoredStateData<T> : 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;
|
||||
/// <summary>
|
||||
/// How long something stays in the cache before new values are retrieved
|
||||
/// </summary>
|
||||
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<IGameTiming>().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<IGameTiming>().CurTime;
|
||||
}
|
||||
|
||||
return Value;
|
||||
|
||||
@@ -0,0 +1,13 @@
|
||||
using Content.Shared.GameObjects.Components.Inventory;
|
||||
|
||||
namespace Content.Server.AI.WorldState.States.Clothing
|
||||
{
|
||||
public sealed class ClothingSlotConState : PlanningStateData<EquipmentSlotDefines.Slots>
|
||||
{
|
||||
public override string Name => "ClothingSlotCon";
|
||||
public override void Reset()
|
||||
{
|
||||
Value = EquipmentSlotDefines.Slots.NONE;
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,13 @@
|
||||
using Content.Shared.GameObjects.Components.Inventory;
|
||||
|
||||
namespace Content.Server.AI.WorldState.States.Clothing
|
||||
{
|
||||
public sealed class ClothingSlotFlagConState : PlanningStateData<EquipmentSlotDefines.SlotFlags>
|
||||
{
|
||||
public override string Name => "ClothingSlotFlagCon";
|
||||
public override void Reset()
|
||||
{
|
||||
Value = EquipmentSlotDefines.SlotFlags.NONE;
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -6,25 +6,19 @@ using Robust.Shared.Interfaces.GameObjects;
|
||||
namespace Content.Server.AI.WorldState.States.Inventory
|
||||
{
|
||||
[UsedImplicitly]
|
||||
public sealed class InventoryState : StateData<List<IEntity>>
|
||||
public sealed class EnumerableInventoryState : StateData<IEnumerable<IEntity>>
|
||||
{
|
||||
public override string Name => "Inventory";
|
||||
public override string Name => "EnumerableInventory";
|
||||
|
||||
public override List<IEntity> GetValue()
|
||||
public override IEnumerable<IEntity> GetValue()
|
||||
{
|
||||
var inventory = new List<IEntity>();
|
||||
|
||||
if (Owner.TryGetComponent(out HandsComponent handsComponent))
|
||||
{
|
||||
foreach (var item in handsComponent.GetAllHeldItems())
|
||||
{
|
||||
inventory.Add(item.Owner);
|
||||
}
|
||||
}
|
||||
|
||||
// TODO: InventoryComponent (Pockets were throwing)
|
||||
|
||||
return inventory;
|
||||
yield return item.Owner;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -0,0 +1,10 @@
|
||||
namespace Content.Server.AI.WorldState.States.Utility
|
||||
{
|
||||
/// <summary>
|
||||
/// Used by the utility AI to calc the adjusted scores
|
||||
/// </summary>
|
||||
public class ConsiderationState : StoredStateData<int>
|
||||
{
|
||||
public override string Name => "Consideration";
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,13 @@
|
||||
using System;
|
||||
|
||||
namespace Content.Server.AI.WorldState.States.Utility
|
||||
{
|
||||
public sealed class StoredStateIsNullState : PlanningStateData<Type>
|
||||
{
|
||||
public override string Name => "StoredStateIsNull";
|
||||
public override void Reset()
|
||||
{
|
||||
Value = null;
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -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<RecipeManager>().Initialize();
|
||||
IoCManager.Resolve<BlackboardManager>().Initialize();
|
||||
IoCManager.Resolve<ConsiderationsManager>().Initialize();
|
||||
IoCManager.Resolve<IPDAUplinkManager>().Initialize();
|
||||
}
|
||||
|
||||
|
||||
@@ -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<INodeGroupManager, NodeGroupManager>();
|
||||
IoCManager.Register<INodeFactory, NodeFactory>();
|
||||
IoCManager.Register<BlackboardManager, BlackboardManager>();
|
||||
IoCManager.Register<ConsiderationsManager, ConsiderationsManager>();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user