NPC utility queries (#15843)

This commit is contained in:
metalgearsloth
2023-05-02 04:57:11 +10:00
committed by GitHub
parent ac5afa794e
commit ca07522c03
50 changed files with 873 additions and 246 deletions

View File

@@ -0,0 +1,6 @@
namespace Content.Server.NPC.Queries.Considerations;
public sealed class FoodValueCon : UtilityConsideration
{
}

View File

@@ -0,0 +1,9 @@
namespace Content.Server.NPC.Queries.Considerations;
/// <summary>
/// Returns 1f if the target is freely accessible (e.g. not in locked storage).
/// </summary>
public sealed class TargetAccessibleCon : UtilityConsideration
{
}

View File

@@ -0,0 +1,6 @@
namespace Content.Server.NPC.Queries.Considerations;
public sealed class TargetDistanceCon : UtilityConsideration
{
}

View File

@@ -0,0 +1,6 @@
namespace Content.Server.NPC.Queries.Considerations;
public sealed class TargetHealthCon : UtilityConsideration
{
}

View File

@@ -0,0 +1,9 @@
namespace Content.Server.NPC.Queries.Considerations;
/// <summary>
/// Returns whether the target is in line-of-sight.
/// </summary>
public sealed class TargetInLOSCon : UtilityConsideration
{
}

View File

@@ -0,0 +1,9 @@
namespace Content.Server.NPC.Queries.Considerations;
/// <summary>
/// Placeholder considerations -> returns 1f if they're in LOS or the current target.
/// </summary>
public sealed class TargetInLOSOrCurrentCon : UtilityConsideration
{
}

View File

@@ -0,0 +1,9 @@
namespace Content.Server.NPC.Queries.Considerations;
/// <summary>
/// Returns 1f if the target is alive or 0f if not.
/// </summary>
public sealed class TargetIsAliveCon : UtilityConsideration
{
}

View File

@@ -0,0 +1,9 @@
namespace Content.Server.NPC.Queries.Considerations;
/// <summary>
/// Returns 1f if the target is crit or 0f if not.
/// </summary>
public sealed class TargetIsCritCon : UtilityConsideration
{
}

View File

@@ -0,0 +1,9 @@
namespace Content.Server.NPC.Queries.Considerations;
/// <summary>
/// Returns 1f if the target is dead or 0f if not.
/// </summary>
public sealed class TargetIsDeadCon : UtilityConsideration
{
}

View File

@@ -0,0 +1,11 @@
using Content.Server.NPC.Queries.Curves;
using JetBrains.Annotations;
namespace Content.Server.NPC.Queries.Considerations;
[ImplicitDataDefinitionForInheritors, MeansImplicitUse]
public abstract class UtilityConsideration
{
[DataField("curve", required: true)]
public IUtilityCurve Curve = default!;
}

View File

@@ -0,0 +1,5 @@
namespace Content.Server.NPC.Queries.Curves;
public sealed class BoolCurve : IUtilityCurve
{
}

View File

@@ -0,0 +1,7 @@
namespace Content.Server.NPC.Queries.Curves;
[ImplicitDataDefinitionForInheritors]
public interface IUtilityCurve
{
}

View File

@@ -0,0 +1,6 @@
namespace Content.Server.NPC.Queries.Curves;
public sealed class InverseBoolCurve : IUtilityCurve
{
}

View File

@@ -0,0 +1,8 @@
using Robust.Shared.Serialization.TypeSerializers.Implementations.Custom.Prototype;
namespace Content.Server.NPC.Queries.Curves;
public sealed class PresetCurve : IUtilityCurve
{
[DataField("preset", required: true, customTypeSerializer:typeof(PrototypeIdSerializer<UtilityCurvePresetPrototype>))] public readonly string Preset = default!;
}

View File

@@ -0,0 +1,12 @@
namespace Content.Server.NPC.Queries.Curves;
public sealed class QuadraticCurve : IUtilityCurve
{
[DataField("slope")] public readonly float Slope;
[DataField("exponent")] public readonly float Exponent;
[DataField("yOffset")] public readonly float YOffset;
[DataField("xOffset")] public readonly float XOffset;
}

View File

@@ -0,0 +1,11 @@
using Robust.Shared.Prototypes;
namespace Content.Server.NPC.Queries.Curves;
[Prototype("utilityCurvePreset")]
public sealed class UtilityCurvePresetPrototype : IPrototype
{
[IdDataField] public string ID { get; } = string.Empty;
[DataField("curve", required: true)] public IUtilityCurve Curve = default!;
}

View File

@@ -0,0 +1,6 @@
namespace Content.Server.NPC.Queries.Queries;
public sealed class ClothingSlotFilter : UtilityQueryFilter
{
}

View File

@@ -0,0 +1,12 @@
using Robust.Shared.Prototypes;
namespace Content.Server.NPC.Queries.Queries;
/// <summary>
/// Returns nearby components that match the specified components.
/// </summary>
public sealed class ComponentQuery : UtilityQuery
{
[DataField("components", required: true)]
public EntityPrototype.ComponentRegistry Components = default!;
}

View File

@@ -0,0 +1,9 @@
using Robust.Shared.Prototypes;
namespace Content.Server.NPC.Queries.Queries;
public sealed class NearbyComponentsQuery : UtilityQuery
{
[DataField("components")]
public EntityPrototype.ComponentRegistry Component = default!;
}

View File

@@ -0,0 +1,9 @@
namespace Content.Server.NPC.Queries.Queries;
/// <summary>
/// Returns nearby entities considered hostile from <see cref="FactionSystem"/>
/// </summary>
public sealed class NearbyHostilesQuery : UtilityQuery
{
}

View File

@@ -0,0 +1,6 @@
namespace Content.Server.NPC.Queries.Queries;
public sealed class PuddlesQuery : UtilityQuery
{
}

View File

@@ -0,0 +1,10 @@
namespace Content.Server.NPC.Queries.Queries;
/// <summary>
/// Adds entities to a query.
/// </summary>
[ImplicitDataDefinitionForInheritors]
public abstract class UtilityQuery
{
}

View File

@@ -0,0 +1,9 @@
namespace Content.Server.NPC.Queries.Queries;
/// <summary>
/// Removes entities from a query.
/// </summary>
public abstract class UtilityQueryFilter : UtilityQuery
{
}

View File

@@ -0,0 +1,29 @@
using Content.Server.NPC.Queries.Considerations;
using Content.Server.NPC.Queries.Queries;
using Robust.Shared.Prototypes;
namespace Content.Server.NPC.Queries;
/// <summary>
/// Stores data for generic queries.
/// Each query is run in turn to get the final available results.
/// These results are then run through the considerations.
/// </summary>
[Prototype("utilityQuery")]
public sealed class UtilityQueryPrototype : IPrototype
{
[IdDataField]
public string ID { get; } = default!;
[ViewVariables(VVAccess.ReadWrite), DataField("query")]
public List<UtilityQuery> Query = new();
[ViewVariables(VVAccess.ReadWrite), DataField("considerations")]
public List<UtilityConsideration> Considerations = new();
/// <summary>
/// How many entities we are allowed to consider. This is applied after all queries have run.
/// </summary>
[DataField("limit")]
public int Limit = 128;
}

View File

@@ -0,0 +1,34 @@
using Robust.Shared.Serialization.TypeSerializers.Implementations.Custom.Prototype;
namespace Content.Server.NPC.Queries;
/// <summary>
/// Utility queries that run regularly to update an NPC without re-doing their thinking logic.
/// </summary>
[DataDefinition]
public sealed class UtilityService
{
/// <summary>
/// Identifier to use for this service. This is used to track its cooldown.
/// </summary>
[DataField("id", required: true)]
public string ID = string.Empty;
/// <summary>
/// Prototype of the utility query.
/// </summary>
[DataField("proto", required: true, customTypeSerializer:typeof(PrototypeIdSerializer<UtilityQueryPrototype>))]
public string Prototype = string.Empty;
[DataField("minCooldown")]
public float MinCooldown = 0.25f;
[DataField("maxCooldown")]
public float MaxCooldown = 0.60f;
/// <summary>
/// Key to update with the utility query.
/// </summary>
[DataField("key", required: true)]
public string Key = string.Empty;
}