@@ -45,6 +45,10 @@ public sealed class NPCTest
|
|||||||
var count = counts.GetOrNew(compound.ID);
|
var count = counts.GetOrNew(compound.ID);
|
||||||
count++;
|
count++;
|
||||||
|
|
||||||
|
// Compound tasks marked with AllowRecursion are only evaluated once
|
||||||
|
if (counts.ContainsKey(compound.ID) && compound.AllowRecursion)
|
||||||
|
continue;
|
||||||
|
|
||||||
Assert.That(count, Is.LessThan(50));
|
Assert.That(count, Is.LessThan(50));
|
||||||
counts[compound.ID] = count;
|
counts[compound.ID] = count;
|
||||||
Count(protoManager.Index<HTNCompoundPrototype>(compoundTask.Task), counts, htnSystem, protoManager);
|
Count(protoManager.Index<HTNCompoundPrototype>(compoundTask.Task), counts, htnSystem, protoManager);
|
||||||
|
|||||||
@@ -12,4 +12,10 @@ public sealed partial class HTNCompoundPrototype : IPrototype
|
|||||||
|
|
||||||
[DataField("branches", required: true)]
|
[DataField("branches", required: true)]
|
||||||
public List<HTNBranch> Branches = new();
|
public List<HTNBranch> Branches = new();
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Exclude this compound task from the CompoundRecursion integration test.
|
||||||
|
/// </summary>
|
||||||
|
[DataField]
|
||||||
|
public bool AllowRecursion = false;
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -63,8 +63,13 @@ public sealed class HTNPlanJob : Job<HTNPlan>
|
|||||||
// How many primitive tasks we've added since last record.
|
// How many primitive tasks we've added since last record.
|
||||||
var primitiveCount = 0;
|
var primitiveCount = 0;
|
||||||
|
|
||||||
|
int tasksProcessed = 0;
|
||||||
|
|
||||||
while (tasksToProcess.TryDequeue(out var currentTask))
|
while (tasksToProcess.TryDequeue(out var currentTask))
|
||||||
{
|
{
|
||||||
|
if (tasksProcessed++ > _rootTask.MaximumTasks)
|
||||||
|
throw new Exception("HTN Planner exceeded maximum tasks");
|
||||||
|
|
||||||
switch (currentTask)
|
switch (currentTask)
|
||||||
{
|
{
|
||||||
case HTNCompoundTask compound:
|
case HTNCompoundTask compound:
|
||||||
|
|||||||
@@ -3,4 +3,10 @@ namespace Content.Server.NPC.HTN;
|
|||||||
[ImplicitDataDefinitionForInheritors]
|
[ImplicitDataDefinitionForInheritors]
|
||||||
public abstract partial class HTNTask
|
public abstract partial class HTNTask
|
||||||
{
|
{
|
||||||
|
/// <summary>
|
||||||
|
/// Limit the amount of tasks the planner considers. Exceeding this value sleeps the NPC and throws an exception.
|
||||||
|
/// The expected way to hit this limit is with badly written recursive tasks.
|
||||||
|
/// </summary>
|
||||||
|
[DataField]
|
||||||
|
public int MaximumTasks = 1000;
|
||||||
}
|
}
|
||||||
|
|||||||
Reference in New Issue
Block a user