using System.Collections.Generic; using System.Linq; using Schema; using UnityEngine; using VOID.Generic.Objects.Unit.Actions; using VOID.Generic.Objects.Unit.Events; namespace VOID.Generic.AI.Schema.Actions { [Description("This unit will patrol between given points")] [Category(SchemaCategory.RealtimeThisUnit)] public class UnitPatrol : Action { private class UnitPatrolMemory { public SchemaUnitEventWrapper onMoveEnd; public int nextStop = - 1; public bool isMoving = false; } public override void OnNodeEnter(object nodeMemory, SchemaAgent agent) { var memory = (UnitPatrolMemory)nodeMemory; var unitAgent = (UnitObjectSchemaAgent)agent; var patrolPoints = unitAgent.unitAI.patrol; var closestDistance = float.MaxValue; for (var index = 0; index < patrolPoints.Count; index++) { var distance = Vector3.Distance(unitAgent.unit.transform.position, patrolPoints[index].position); if (distance >= closestDistance) continue; closestDistance = distance; memory.nextStop = index; } memory.onMoveEnd = new SchemaUnitEventWrapper( unitAgent.unit.unitEvents.onMoveEnd, OnMoveEnd, unitAgent, memory); memory.onMoveEnd.On(); } public override NodeStatus Tick(object nodeMemory, SchemaAgent agent) { var memory = (UnitPatrolMemory)nodeMemory; var unitAgent = (UnitObjectSchemaAgent)agent; if (memory.nextStop == - 1) return NodeStatus.Failure; if (memory.isMoving) return NodeStatus.Running; // Get next patrol points in order to check var orderedPatrolPoints = new List(); orderedPatrolPoints.AddRange(unitAgent.unitAI.patrol.Skip(memory.nextStop+1)); orderedPatrolPoints.AddRange(unitAgent.unitAI.patrol.Take(memory.nextStop+1)); // Find next valid patrol point and order move to it foreach (var point in orderedPatrolPoints) { var moveAction = new MoveAction(unitAgent.unit, point.position); if (moveAction.CanDoItBoolean() == false) continue; unitAgent.unit.Order(moveAction); memory.isMoving = true; return NodeStatus.Running; } // Next point cant be found - error! return NodeStatus.Failure; } public override void OnNodeExit(object nodeMemory, SchemaAgent agent) { var memory = (UnitPatrolMemory)nodeMemory; memory.onMoveEnd.Off(); memory.isMoving = false; } public override void OnNodeAbort(object nodeMemory, SchemaAgent agent) { var memory = (UnitPatrolMemory)nodeMemory; memory.onMoveEnd.Off(); memory.isMoving = false; } private void OnMoveEnd(MoveEvent moveEvent, UnitPatrolMemory memory, UnitObjectSchemaAgent agent) { memory.nextStop = (memory.nextStop + 1) % agent.unitAI.patrol.Count; memory.isMoving = false; } } }