using System.Threading.Tasks;
using Content.Server.NPC.Pathfinding;
using Content.Server.NPC.Pathfinding.Accessible;
using Robust.Shared.Random;
namespace Content.Server.NPC.HTN.PrimitiveTasks.Operators;
///
/// Chooses a nearby coordinate and puts it into the resulting key.
///
public sealed class PickAccessibleOperator : HTNOperator
{
[Dependency] private readonly IEntityManager _entManager = default!;
[Dependency] private readonly IRobustRandom _random = default!;
private AiReachableSystem _reachable = default!;
[DataField("rangeKey", required: true)]
public string RangeKey = string.Empty;
[ViewVariables, DataField("targetKey", required: true)]
public string TargetKey = string.Empty;
public override void Initialize(IEntitySystemManager sysManager)
{
base.Initialize(sysManager);
_reachable = IoCManager.Resolve().GetEntitySystem();
}
///
public override async Task<(bool Valid, Dictionary? Effects)> Plan(NPCBlackboard blackboard)
{
// Very inefficient (should weight each region by its node count) but better than the old system
var owner = blackboard.GetValue(NPCBlackboard.Owner);
if (!_entManager.TryGetComponent(_entManager.GetComponent(owner).GridUid, out IMapGridComponent? grid))
return (false, null);
var reachableArgs = ReachableArgs.GetArgs(owner, blackboard.GetValueOrDefault(RangeKey));
var entityRegion = _reachable.GetRegion(owner);
var reachableRegions = _reachable.GetReachableRegions(reachableArgs, entityRegion);
if (reachableRegions.Count == 0)
return (false, null);
var reachableNodes = new List();
foreach (var region in reachableRegions)
{
foreach (var node in region.Nodes)
{
reachableNodes.Add(node);
}
}
var targetNode = _random.Pick(reachableNodes);
var target = grid.Grid.GridTileToLocal(targetNode.TileRef.GridIndices);
return (true, new Dictionary()
{
{ TargetKey, target },
});
}
}