using System.Threading; using Content.Server.NPC.Pathfinding; using Content.Shared.NPC; using Robust.Shared.Map; namespace Content.Server.NPC.Components; /// /// Added to NPCs that are moving. /// [RegisterComponent] public sealed class NPCSteeringComponent : Component { #region Context Steering /// /// Used to override seeking behavior for context steering. /// [ViewVariables] public bool CanSeek = true; /// /// Radius for collision avoidance. /// [ViewVariables(VVAccess.ReadWrite)] public float Radius = 0.35f; [ViewVariables] public readonly float[] Interest = new float[SharedNPCSteeringSystem.InterestDirections]; [ViewVariables] public readonly float[] Danger = new float[SharedNPCSteeringSystem.InterestDirections]; // TODO: Update radius, also danger points debug only public readonly List DangerPoints = new(); #endregion /// /// How many times per second we're allowed to update our steering frequency. /// public const byte SteerFrequency = 10; /// /// Last time the NPC steered. /// public TimeSpan LastTimeSteer; public Vector2 LastSteer; /// /// Have we currently requested a path. /// [ViewVariables] public bool Pathfind => PathfindToken != null; [ViewVariables] public CancellationTokenSource? PathfindToken = null; /// /// Current path we're following to our coordinates. /// [ViewVariables] public Queue CurrentPath = new(); /// /// End target that we're trying to move to. /// [ViewVariables(VVAccess.ReadWrite)] public EntityCoordinates Coordinates; /// /// How close are we trying to get to the coordinates before being considered in range. /// [ViewVariables(VVAccess.ReadWrite)] public float Range = 0.2f; /// /// How far does the last node in the path need to be before considering re-pathfinding. /// [ViewVariables(VVAccess.ReadWrite)] public float RepathRange = 1.5f; public const int FailedPathLimit = 3; /// /// How many times we've failed to pathfind. Once this hits the limit we'll stop steering. /// [ViewVariables] public int FailedPathCount; [ViewVariables] public SteeringStatus Status = SteeringStatus.Moving; [ViewVariables(VVAccess.ReadWrite)] public PathFlags Flags = PathFlags.None; } public enum SteeringStatus : byte { /// /// If we can't reach the target (e.g. different map). /// NoPath, /// /// Are we moving towards our target /// Moving, /// /// Are we currently in range of our target. /// InRange, }