]> git.smokeofanarchy.ru Git - space-station-14.git/commitdiff
Added new HTN operations and preconditions (#27486)
authorTornado Tech <54727692+Tornado-Technology@users.noreply.github.com>
Wed, 8 May 2024 09:18:03 +0000 (19:18 +1000)
committerGitHub <noreply@github.com>
Wed, 8 May 2024 09:18:03 +0000 (12:18 +0300)
* Added new HTN operations & preconditions

* Ok I forgot about partial

* Namespace pierce the skies

* Some fixes, debug and new operators

* Bruh git eat my files

14 files changed:
Content.Server/NPC/HTN/Preconditions/GunAmmoPrecondition.cs
Content.Server/NPC/HTN/Preconditions/KeyNotExistsPrecondition.cs [new file with mode: 0644]
Content.Server/NPC/HTN/Preconditions/Math/KeyBoolEqualsPrecondition.cs [new file with mode: 0644]
Content.Server/NPC/HTN/Preconditions/Math/KeyFloatEqualsPrecondition.cs [new file with mode: 0644]
Content.Server/NPC/HTN/Preconditions/Math/KeyFloatGreaterPrecondition.cs [new file with mode: 0644]
Content.Server/NPC/HTN/Preconditions/Math/KeyFloatLessPrecondition.cs [new file with mode: 0644]
Content.Server/NPC/HTN/PrimitiveTasks/Operators/Math/AddFloatOperator.cs [new file with mode: 0644]
Content.Server/NPC/HTN/PrimitiveTasks/Operators/Math/SetBoolOperator.cs [new file with mode: 0644]
Content.Server/NPC/HTN/PrimitiveTasks/Operators/Math/SetFloatOperator.cs [moved from Content.Server/NPC/HTN/PrimitiveTasks/Operators/SetFloatOperator.cs with 52% similarity]
Content.Server/NPC/HTN/PrimitiveTasks/Operators/Math/SetRandomFloatOperator.cs [new file with mode: 0644]
Content.Server/NPC/HTN/PrimitiveTasks/Operators/PlaySoundOperator.cs [new file with mode: 0644]
Content.Server/NPC/HTN/PrimitiveTasks/Operators/SayKeyOperator.cs [new file with mode: 0644]
Resources/Prototypes/Entities/Mobs/Debugging/debug_counter.yml [new file with mode: 0644]
Resources/Prototypes/NPCs/debug.yml [new file with mode: 0644]

index fe3b844ae34c2f089653863d22ce3b16d910b67b..58647d8874925fb36eafc2d6e6a4fe62a143b828 100644 (file)
@@ -35,7 +35,7 @@ public sealed partial class GunAmmoPrecondition : HTNPrecondition
         else
             percent = ammoEv.Count / (float) ammoEv.Capacity;
 
-        percent = Math.Clamp(percent, 0f, 1f);
+        percent = System.Math.Clamp(percent, 0f, 1f);
 
         if (MaxPercent < percent)
             return false;
diff --git a/Content.Server/NPC/HTN/Preconditions/KeyNotExistsPrecondition.cs b/Content.Server/NPC/HTN/Preconditions/KeyNotExistsPrecondition.cs
new file mode 100644 (file)
index 0000000..c126639
--- /dev/null
@@ -0,0 +1,12 @@
+namespace Content.Server.NPC.HTN.Preconditions;
+
+public sealed partial class KeyNotExistsPrecondition : HTNPrecondition
+{
+    [DataField(required: true)]
+    public string Key = string.Empty;
+
+    public override bool IsMet(NPCBlackboard blackboard)
+    {
+        return !blackboard.ContainsKey(Key);
+    }
+}
diff --git a/Content.Server/NPC/HTN/Preconditions/Math/KeyBoolEqualsPrecondition.cs b/Content.Server/NPC/HTN/Preconditions/Math/KeyBoolEqualsPrecondition.cs
new file mode 100644 (file)
index 0000000..8c7920e
--- /dev/null
@@ -0,0 +1,23 @@
+namespace Content.Server.NPC.HTN.Preconditions.Math;
+
+/// <summary>
+/// Checks for the presence of data in the blackboard and makes a comparison with the specified boolean
+/// </summary>
+public sealed partial class KeyBoolEqualsPrecondition : HTNPrecondition
+{
+    [Dependency] private readonly IEntityManager _entManager = default!;
+
+    [DataField(required: true)]
+    public string Key = string.Empty;
+
+    [DataField(required: true)]
+    public bool Value;
+
+    public override bool IsMet(NPCBlackboard blackboard)
+    {
+        if (!blackboard.TryGetValue<bool>(Key, out var value, _entManager))
+            return false;
+
+        return Value == value;
+    }
+}
diff --git a/Content.Server/NPC/HTN/Preconditions/Math/KeyFloatEqualsPrecondition.cs b/Content.Server/NPC/HTN/Preconditions/Math/KeyFloatEqualsPrecondition.cs
new file mode 100644 (file)
index 0000000..802fdaf
--- /dev/null
@@ -0,0 +1,18 @@
+namespace Content.Server.NPC.HTN.Preconditions.Math;
+
+public sealed partial class KeyFloatEqualsPrecondition : HTNPrecondition
+{
+    [Dependency] private readonly IEntityManager _entManager = default!;
+
+    [DataField(required: true)]
+    public string Key = string.Empty;
+
+    [DataField(required: true)]
+    public float Value;
+
+    public override bool IsMet(NPCBlackboard blackboard)
+    {
+        return blackboard.TryGetValue<float>(Key, out var value, _entManager) &&
+               MathHelper.CloseTo(value, value);
+    }
+}
diff --git a/Content.Server/NPC/HTN/Preconditions/Math/KeyFloatGreaterPrecondition.cs b/Content.Server/NPC/HTN/Preconditions/Math/KeyFloatGreaterPrecondition.cs
new file mode 100644 (file)
index 0000000..3a9ac36
--- /dev/null
@@ -0,0 +1,17 @@
+namespace Content.Server.NPC.HTN.Preconditions.Math;
+
+public sealed partial class KeyFloatGreaterPrecondition : HTNPrecondition
+{
+    [Dependency] private readonly IEntityManager _entManager = default!;
+
+    [DataField(required: true)]
+    public string Key = string.Empty;
+
+    [DataField(required: true)]
+    public float Value;
+
+    public override bool IsMet(NPCBlackboard blackboard)
+    {
+        return blackboard.TryGetValue<float>(Key, out var value, _entManager) && value > Value;
+    }
+}
diff --git a/Content.Server/NPC/HTN/Preconditions/Math/KeyFloatLessPrecondition.cs b/Content.Server/NPC/HTN/Preconditions/Math/KeyFloatLessPrecondition.cs
new file mode 100644 (file)
index 0000000..5cd51d7
--- /dev/null
@@ -0,0 +1,17 @@
+namespace Content.Server.NPC.HTN.Preconditions.Math;
+
+public sealed partial class KeyFloatLessPrecondition : HTNPrecondition
+{
+    [Dependency] private readonly IEntityManager _entManager = default!;
+
+    [DataField(required: true)]
+    public string Key = string.Empty;
+
+    [DataField(required: true)]
+    public float Value;
+
+    public override bool IsMet(NPCBlackboard blackboard)
+    {
+        return blackboard.TryGetValue<float>(Key, out var value, _entManager) && value < Value;
+    }
+}
diff --git a/Content.Server/NPC/HTN/PrimitiveTasks/Operators/Math/AddFloatOperator.cs b/Content.Server/NPC/HTN/PrimitiveTasks/Operators/Math/AddFloatOperator.cs
new file mode 100644 (file)
index 0000000..0040451
--- /dev/null
@@ -0,0 +1,33 @@
+using System.Threading;
+using System.Threading.Tasks;
+
+namespace Content.Server.NPC.HTN.PrimitiveTasks.Operators.Math;
+
+/// <summary>
+/// Gets the key, and adds the value to that float
+/// </summary>
+public sealed partial class AddFloatOperator : HTNOperator
+{
+    [Dependency] private readonly IEntityManager _entManager = default!;
+
+    [DataField(required: true)]
+    public string TargetKey = string.Empty;
+
+    [DataField, ViewVariables(VVAccess.ReadWrite)]
+    public float Amount;
+
+    public override async Task<(bool Valid, Dictionary<string, object>? Effects)> Plan(NPCBlackboard blackboard,
+        CancellationToken cancelToken)
+    {
+        if (!blackboard.TryGetValue<float>(TargetKey, out var value, _entManager))
+            return (false, null);
+
+        return (
+            true,
+            new Dictionary<string, object>
+            {
+                { TargetKey, value + Amount }
+            }
+        );
+    }
+}
diff --git a/Content.Server/NPC/HTN/PrimitiveTasks/Operators/Math/SetBoolOperator.cs b/Content.Server/NPC/HTN/PrimitiveTasks/Operators/Math/SetBoolOperator.cs
new file mode 100644 (file)
index 0000000..a40b967
--- /dev/null
@@ -0,0 +1,28 @@
+using System.Threading;
+using System.Threading.Tasks;
+
+namespace Content.Server.NPC.HTN.PrimitiveTasks.Operators.Math;
+
+/// <summary>
+/// Just sets a blackboard key to a bool
+/// </summary>
+public sealed partial class SetBoolOperator : HTNOperator
+{
+    [DataField(required: true)]
+    public string TargetKey = string.Empty;
+
+    [DataField, ViewVariables(VVAccess.ReadWrite)]
+    public bool Value;
+
+    public override async Task<(bool Valid, Dictionary<string, object>? Effects)> Plan(NPCBlackboard blackboard,
+        CancellationToken cancelToken)
+    {
+        return (
+            true,
+            new Dictionary<string, object>
+            {
+                { TargetKey, Value }
+            }
+        );
+    }
+}
similarity index 52%
rename from Content.Server/NPC/HTN/PrimitiveTasks/Operators/SetFloatOperator.cs
rename to Content.Server/NPC/HTN/PrimitiveTasks/Operators/Math/SetFloatOperator.cs
index 7a460592cb4249f25d29dfd0905e100a35898c09..76842b431f70181d8ff358bdc34a009588e9386f 100644 (file)
@@ -1,24 +1,28 @@
 using System.Threading;
 using System.Threading.Tasks;
 
-namespace Content.Server.NPC.HTN.PrimitiveTasks.Operators;
+namespace Content.Server.NPC.HTN.PrimitiveTasks.Operators.Math;
 
 /// <summary>
 /// Just sets a blackboard key to a float
 /// </summary>
 public sealed partial class SetFloatOperator : HTNOperator
 {
-    [DataField("targetKey", required: true)] public string TargetKey = string.Empty;
+    [DataField(required: true)]
+    public string TargetKey = string.Empty;
 
-    [ViewVariables(VVAccess.ReadWrite), DataField("amount")]
+    [DataField, ViewVariables(VVAccess.ReadWrite)]
     public float Amount;
 
     public override async Task<(bool Valid, Dictionary<string, object>? Effects)> Plan(NPCBlackboard blackboard,
         CancellationToken cancelToken)
     {
-        return (true, new Dictionary<string, object>()
-        {
-            {TargetKey, Amount},
-        });
+        return (
+            true,
+            new Dictionary<string, object>
+            {
+                { TargetKey, Amount }
+            }
+        );
     }
 }
diff --git a/Content.Server/NPC/HTN/PrimitiveTasks/Operators/Math/SetRandomFloatOperator.cs b/Content.Server/NPC/HTN/PrimitiveTasks/Operators/Math/SetRandomFloatOperator.cs
new file mode 100644 (file)
index 0000000..999756f
--- /dev/null
@@ -0,0 +1,34 @@
+using System.Threading;
+using System.Threading.Tasks;
+using Robust.Shared.Random;
+
+namespace Content.Server.NPC.HTN.PrimitiveTasks.Operators.Math;
+
+/// <summary>
+/// Sets a random float from MinAmount to MaxAmount to blackboard
+/// </summary>
+public sealed partial class SetRandomFloatOperator : HTNOperator
+{
+    [Dependency] private readonly IRobustRandom _random = default!;
+
+    [DataField(required: true)]
+    public string TargetKey = string.Empty;
+
+    [DataField, ViewVariables(VVAccess.ReadWrite)]
+    public float MaxAmount = 1f;
+
+    [DataField, ViewVariables(VVAccess.ReadWrite)]
+    public float MinAmount = 0f;
+
+    public override async Task<(bool Valid, Dictionary<string, object>? Effects)> Plan(NPCBlackboard blackboard,
+        CancellationToken cancelToken)
+    {
+        return (
+            true,
+            new Dictionary<string, object>
+            {
+                { TargetKey, _random.NextFloat(MinAmount, MaxAmount) }
+            }
+        );
+    }
+}
diff --git a/Content.Server/NPC/HTN/PrimitiveTasks/Operators/PlaySoundOperator.cs b/Content.Server/NPC/HTN/PrimitiveTasks/Operators/PlaySoundOperator.cs
new file mode 100644 (file)
index 0000000..57cc2e9
--- /dev/null
@@ -0,0 +1,28 @@
+using Robust.Server.Audio;
+using Robust.Shared.Audio;
+
+namespace Content.Server.NPC.HTN.PrimitiveTasks.Operators;
+
+public sealed partial class PlaySoundOperator : HTNOperator
+{
+    private AudioSystem _audio = default!;
+
+    [DataField(required: true)]
+    public SoundSpecifier? Sound;
+
+    public override void Initialize(IEntitySystemManager sysManager)
+    {
+        base.Initialize(sysManager);
+
+        _audio = IoCManager.Resolve<IEntitySystemManager>().GetEntitySystem<AudioSystem>();
+    }
+
+    public override HTNOperatorStatus Update(NPCBlackboard blackboard, float frameTime)
+    {
+        var uid = blackboard.GetValue<EntityUid>(NPCBlackboard.Owner);
+
+        _audio.PlayPvs(Sound, uid);
+
+        return base.Update(blackboard, frameTime);
+    }
+}
diff --git a/Content.Server/NPC/HTN/PrimitiveTasks/Operators/SayKeyOperator.cs b/Content.Server/NPC/HTN/PrimitiveTasks/Operators/SayKeyOperator.cs
new file mode 100644 (file)
index 0000000..d1c7d61
--- /dev/null
@@ -0,0 +1,36 @@
+using Content.Server.Chat.Systems;
+
+namespace Content.Server.NPC.HTN.PrimitiveTasks.Operators;
+
+public sealed partial class SayKeyOperator : HTNOperator
+{
+    [Dependency] private readonly IEntityManager _entManager = default!;
+
+    private ChatSystem _chat = default!;
+
+    [DataField(required: true)]
+    public string Key = string.Empty;
+
+    /// <summary>
+    /// Whether to hide message from chat window and logs.
+    /// </summary>
+    [DataField]
+    public bool Hidden;
+
+    public override void Initialize(IEntitySystemManager sysManager)
+    {
+        base.Initialize(sysManager);
+        _chat = IoCManager.Resolve<IEntitySystemManager>().GetEntitySystem<ChatSystem>();
+    }
+
+    public override HTNOperatorStatus Update(NPCBlackboard blackboard, float frameTime)
+    {
+        if (!blackboard.TryGetValue<object>(Key, out var value, _entManager))
+            return HTNOperatorStatus.Failed;
+
+        var speaker = blackboard.GetValue<EntityUid>(NPCBlackboard.Owner);
+        _chat.TrySendInGameICMessage(speaker, value.ToString() ?? "Oh no...", InGameICChatType.Speak, hideChat: Hidden, hideLog: Hidden);
+
+        return base.Update(blackboard, frameTime);
+    }
+}
diff --git a/Resources/Prototypes/Entities/Mobs/Debugging/debug_counter.yml b/Resources/Prototypes/Entities/Mobs/Debugging/debug_counter.yml
new file mode 100644 (file)
index 0000000..05707c7
--- /dev/null
@@ -0,0 +1,53 @@
+- type: entity
+  parent: MobHuman
+  id: MobDebugCounter
+  name: debug counter
+  description: He can count
+  suffix: AI, DEBUG
+  components:
+    - type: HTN
+      rootTask:
+        task: DebugCounterCompound
+      blackboard:
+        MinimumIdleTime: !type:Single
+          0.5
+        MaximumIdleTime: !type:Single
+          0.5
+        Count: !type:Single
+          0
+
+- type: entity
+  parent: MobHuman
+  id: MobDebugRandomCounter
+  name: debug random counter
+  description: He can randomize
+  suffix: AI, DEBUG
+  components:
+    - type: HTN
+      rootTask:
+        task: DebugRandomCounterCompound
+      blackboard:
+        MinimumIdleTime: !type:Single
+          1
+        MaximumIdleTime: !type:Single
+          1
+        Count: !type:Single
+          0
+
+- type: entity
+  parent: MobHuman
+  id: MobDebugRandomLess
+  name: debug random less
+  description: He can lessing
+  suffix: AI, DEBUG
+  components:
+    - type: HTN
+      rootTask:
+        task: DebugRandomLessCompound
+      blackboard:
+        MinimumIdleTime: !type:Single
+          1
+        MaximumIdleTime: !type:Single
+          1
+        Count: !type:Single
+          0
diff --git a/Resources/Prototypes/NPCs/debug.yml b/Resources/Prototypes/NPCs/debug.yml
new file mode 100644 (file)
index 0000000..c7929be
--- /dev/null
@@ -0,0 +1,90 @@
+- type: htnCompound
+  id: DebugCounterCompound
+  branches:
+    - tasks:
+      - !type:HTNPrimitiveTask
+        operator: !type:AddFloatOperator
+          targetKey: Count
+          amount: 1
+
+      - !type:HTNPrimitiveTask
+        operator: !type:SayKeyOperator
+          key: Count
+
+      - !type:HTNPrimitiveTask
+          operator: !type:RandomOperator
+            targetKey: IdleTime
+            minKey: MinimumIdleTime
+            maxKey: MaximumIdleTime
+
+      - !type:HTNPrimitiveTask
+        operator: !type:WaitOperator
+          key: IdleTime
+        preconditions:
+          - !type:KeyExistsPrecondition
+            key: IdleTime
+
+- type: htnCompound
+  id: DebugRandomCounterCompound
+  branches:
+    - tasks:
+      - !type:HTNPrimitiveTask
+        operator: !type:SetRandomFloatOperator
+          targetKey: Count
+          minAmount: 0
+          maxAmount: 100
+
+      - !type:HTNPrimitiveTask
+        operator: !type:SayKeyOperator
+          key: Count
+
+      - !type:HTNPrimitiveTask
+          operator: !type:RandomOperator
+            targetKey: IdleTime
+            minKey: MinimumIdleTime
+            maxKey: MaximumIdleTime
+
+      - !type:HTNPrimitiveTask
+        operator: !type:WaitOperator
+          key: IdleTime
+        preconditions:
+          - !type:KeyExistsPrecondition
+            key: IdleTime
+
+- type: htnCompound
+  id: DebugRandomLessCompound
+  branches:
+    - tasks:
+      - !type:HTNPrimitiveTask
+        operator: !type:SetRandomFloatOperator
+          targetKey: Count
+          minAmount: 0
+          maxAmount: 100
+
+      - !type:HTNPrimitiveTask
+        operator: !type:SayKeyOperator
+          key: Count
+        preconditions:
+          - !type:KeyFloatLessPrecondition
+            key: Count
+            value: 50
+      
+      - !type:HTNPrimitiveTask
+          operator: !type:RandomOperator
+            targetKey: IdleTime
+            minKey: MinimumIdleTime
+            maxKey: MaximumIdleTime
+
+      - !type:HTNPrimitiveTask
+        operator: !type:WaitOperator
+          key: IdleTime
+        preconditions:
+          - !type:KeyExistsPrecondition
+            key: IdleTime
+
+    - tasks:
+      - !type:HTNPrimitiveTask
+        operator: !type:SpeakOperator
+          speech: "fuck!"
+
\ No newline at end of file