using System; using System.Collections.Generic; using System.Linq; using Schema; using UnityEngine; using UnityEngine.AI; using VOID.Generic.Objects.Unit; using VOID.Generic.Util; using Action = Schema.Action; namespace VOID.Generic.AI.Schema.Actions { [Description("Gets point where ThisUnit can go with current MovementPoints towards given destination point")] [Category(SchemaCategory.CombatThisUnit)] public class GetReachablePosition : Action { private enum DestinationType { Position, Unit } [SerializeField] private DestinationType _destinationType; [SerializeField] private BlackboardEntrySelector _toUnit; [SerializeField] private BlackboardEntrySelector _toPosition; [SerializeField, WriteOnly, Space(15)] private BlackboardEntrySelector _saveTo; public override NodeStatus Tick(object nodeMemory, SchemaAgent agent) { var thisUnit = ((UnitObjectSchemaAgent)agent).unit; if (!thisUnit.basicState.turnManager) return NodeStatus.Failure; // Whole path to destination var path = _destinationType switch { DestinationType.Position => GetPathToPosition(thisUnit), DestinationType.Unit => GetPathToUnit(thisUnit), _ => throw new ArgumentOutOfRangeException() }; var movePoints = thisUnit.unitData.currentResources.movePoints; // Path can't be calculated if (thisUnit.unitNavAgent.GetPath().status is NavMeshPathStatus.PathInvalid) return NodeStatus.Failure; // Reachable path (within move points range) and its last possible point NavMeshPathUtil.SplitPath(path.ToArray(), movePoints, out var reachablePath, out _); _saveTo.value = reachablePath.Last(); return NodeStatus.Success; } private List GetPathToPosition(UnitObject thisUnit) { thisUnit.unitNavAgent.CalculatePathTo(_toPosition.value); return thisUnit.unitNavAgent.GetCorrectedPath(); } private List GetPathToUnit(UnitObject thisUnit) { thisUnit.unitNavAgent.CalculatePathTo(_toUnit.value); return thisUnit.unitNavAgent.GetCorrectedPath(); } } }