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;
--- /dev/null
+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);
+ }
+}
--- /dev/null
+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;
+ }
+}
--- /dev/null
+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);
+ }
+}
--- /dev/null
+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;
+ }
+}
--- /dev/null
+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;
+ }
+}
--- /dev/null
+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 }
+ }
+ );
+ }
+}
--- /dev/null
+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 }
+ }
+ );
+ }
+}
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 }
+ }
+ );
}
}
--- /dev/null
+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) }
+ }
+ );
+ }
+}
--- /dev/null
+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);
+ }
+}
--- /dev/null
+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);
+ }
+}
--- /dev/null
+- 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
--- /dev/null
+- 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