using Schema; using UnityEngine; using VOID.Generic.Objects.Unit; using VOID.Generic.Objects.Unit.Actions; using VOID.Generic.Objects.Unit.Events; namespace VOID.Generic.AI.Schema.Actions { [Description("This unit will move to given point")] [Category(SchemaCategory.ThisUnit)] public class UnitMoveTo : Action { private class UnitMoveToMemory { public SchemaUnitEventWrapper onMoveEnd; public bool isMoving; public bool isFinished; } private enum MoveToType { Position, Unit } [SerializeField] private MoveToType _moveTo; [SerializeField] private BlackboardEntrySelector _moveToPosition; [SerializeField] private BlackboardEntrySelector _moveToUnit; [SerializeField, Space(15)] private BlackboardEntrySelector _range; public override void OnNodeEnter(object nodeMemory, SchemaAgent agent) { var memory = (UnitMoveToMemory)nodeMemory; var unitAgent = (UnitObjectSchemaAgent)agent; memory.onMoveEnd = new SchemaUnitEventWrapper( unitAgent.unit.unitEvents.onMoveEnd, OnMoveEnd, unitAgent, memory); memory.onMoveEnd.On(); memory.isMoving = false; memory.isFinished = false; } public override NodeStatus Tick(object nodeMemory, SchemaAgent agent) { var memory = (UnitMoveToMemory)nodeMemory; var unitAgent = (UnitObjectSchemaAgent)agent; // moveTo target not defined if (_moveTo is MoveToType.Unit && !_moveToUnit.value) return NodeStatus.Failure; if (_moveTo is MoveToType.Position && !_moveToPosition.value) return NodeStatus.Failure; // unit reached target - end MoveTo with success if (memory.isFinished) return NodeStatus.Success; // not started moving yet - start moving for this unit if (!memory.isMoving) { memory.isMoving = true; memory.isFinished = false; unitAgent.unit.OrderStop(); if (_moveTo is MoveToType.Position) unitAgent.unit.Order(new MoveAction(unitAgent.unit, _moveToPosition.value.position, _range.value)); if (_moveTo is MoveToType.Unit) unitAgent.unit.Order(new MoveAction(unitAgent.unit, _moveToUnit.value, _range.value)); } // If somehow this unit don't have anything in current action (something aborted that??) // Then end with failure whole MoveTo if (unitAgent.unit.unitActionQueue.actionCurrent == null) return NodeStatus.Failure; // moving return NodeStatus.Running; } public override void OnNodeExit(object nodeMemory, SchemaAgent agent) { var memory = (UnitMoveToMemory)nodeMemory; memory.onMoveEnd.Off(); } public override void OnNodeAbort(object nodeMemory, SchemaAgent agent) { var memory = (UnitMoveToMemory)nodeMemory; memory.onMoveEnd.Off(); } private void OnMoveEnd(MoveEvent moveEvent, UnitMoveToMemory memory, UnitObjectSchemaAgent agent) { memory.isFinished = true; } } }