Added new HTN operations and preconditions (#27486)
* 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
This commit is contained in:
@@ -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;
|
||||
|
||||
@@ -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);
|
||||
}
|
||||
}
|
||||
@@ -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;
|
||||
}
|
||||
}
|
||||
@@ -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);
|
||||
}
|
||||
}
|
||||
@@ -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;
|
||||
}
|
||||
}
|
||||
@@ -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;
|
||||
}
|
||||
}
|
||||
@@ -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 }
|
||||
}
|
||||
);
|
||||
}
|
||||
}
|
||||
@@ -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 }
|
||||
}
|
||||
);
|
||||
}
|
||||
}
|
||||
@@ -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 }
|
||||
}
|
||||
);
|
||||
}
|
||||
}
|
||||
@@ -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) }
|
||||
}
|
||||
);
|
||||
}
|
||||
}
|
||||
@@ -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);
|
||||
}
|
||||
}
|
||||
@@ -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);
|
||||
}
|
||||
}
|
||||
@@ -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
|
||||
90
Resources/Prototypes/NPCs/debug.yml
Normal file
90
Resources/Prototypes/NPCs/debug.yml
Normal file
@@ -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!"
|
||||
|
||||
|
||||
Reference in New Issue
Block a user