110 lines
4.1 KiB
C#
110 lines
4.1 KiB
C#
using System;
|
|
using System.Linq;
|
|
using Schema;
|
|
using UnityEngine;
|
|
using VOID.Generic.Dict;
|
|
using VOID.Generic.Objects.Unit;
|
|
using VOID.Generic.Objects.Unit.Actions;
|
|
using VOID.Generic.Objects.Unit.Events;
|
|
using VOID.ScriptableObjects.Abilities;
|
|
using Action = Schema.Action;
|
|
|
|
namespace VOID.Generic.AI.Schema.Actions
|
|
{
|
|
[Description("Order this unit to use selected ability")]
|
|
[Category(SchemaCategory.ThisUnit)]
|
|
public class UnitUseAbility : Action
|
|
{
|
|
private class UnitUseAbilityMemory
|
|
{
|
|
public SchemaUnitEventWrapper<AnimationGenericEvent, UnitUseAbilityMemory> onCastAnimationEnd;
|
|
public bool isRunning;
|
|
public bool isFinished;
|
|
}
|
|
|
|
private enum TargetType
|
|
{
|
|
Position,
|
|
Unit
|
|
}
|
|
|
|
[SerializeField] private BlackboardEntrySelector<BasicAbility> _ability;
|
|
[SerializeField, Space(15)] private TargetType _targetType;
|
|
[SerializeField] private BlackboardEntrySelector<Transform> _position;
|
|
[SerializeField] private BlackboardEntrySelector<UnitObject> _unit;
|
|
|
|
public override NodeStatus Tick(object nodeMemory, SchemaAgent agent)
|
|
{
|
|
var memory = (UnitUseAbilityMemory)nodeMemory;
|
|
var unitAgent = (UnitObjectSchemaAgent)agent;
|
|
var thisUnit = unitAgent.unit;
|
|
|
|
// Ability not selected
|
|
if (!_ability.value) return NodeStatus.Failure;
|
|
|
|
// Whenever is during casting or already done that
|
|
if (memory.isFinished) return NodeStatus.Success;
|
|
if (memory.isRunning) return NodeStatus.Running;
|
|
|
|
// Targets not selected
|
|
if (_targetType == TargetType.Position && !_position.value) return NodeStatus.Failure;
|
|
if (_targetType == TargetType.Unit && !_unit.value) return NodeStatus.Failure;
|
|
|
|
AbilityAction abilityAction;
|
|
if (_targetType is TargetType.Position)
|
|
{
|
|
// TODO: for now if ability needs multiple targets all will be identical
|
|
var targets = Enumerable.Repeat(_position.value.position, _ability.value.castUsages).ToArray();
|
|
abilityAction = new AbilityAction(thisUnit, _ability.value, targets);
|
|
}
|
|
else if (_targetType is TargetType.Unit)
|
|
{
|
|
// TODO: for now if ability needs multiple targets all will be identical
|
|
var targets = Enumerable.Repeat(_unit.value, _ability.value.castUsages).ToArray();
|
|
abilityAction = new AbilityAction(thisUnit, _ability.value, targets);
|
|
}
|
|
else
|
|
{
|
|
throw new ArgumentOutOfRangeException();
|
|
}
|
|
|
|
// Check if that action can be done
|
|
if (!abilityAction.CanDoItBoolean()) return NodeStatus.Failure;
|
|
|
|
// Listen to end of abilisty casting animation
|
|
memory.onCastAnimationEnd?.Off();
|
|
memory.onCastAnimationEnd = new SchemaUnitEventWrapper<AnimationGenericEvent, UnitUseAbilityMemory>(
|
|
thisUnit.unitEvents.onAnimation[AnimationType.Ability].onEnd, OnAbilityCastEnd, unitAgent, memory);
|
|
memory.onCastAnimationEnd.On();
|
|
|
|
// Everything seems ok - order unit to do that action
|
|
thisUnit.OrderStop();
|
|
thisUnit.Order(abilityAction);
|
|
memory.isRunning = true;
|
|
|
|
return NodeStatus.Running;
|
|
}
|
|
|
|
public override void OnNodeExit(object nodeMemory, SchemaAgent agent)
|
|
{
|
|
var memory = (UnitUseAbilityMemory)nodeMemory;
|
|
memory.onCastAnimationEnd?.Off();
|
|
memory.isFinished = false;
|
|
memory.isRunning = false;
|
|
}
|
|
|
|
public override void OnNodeAbort(object nodeMemory, SchemaAgent agent)
|
|
{
|
|
var memory = (UnitUseAbilityMemory)nodeMemory;
|
|
memory.onCastAnimationEnd?.Off();
|
|
memory.isFinished = false;
|
|
memory.isRunning = false;
|
|
}
|
|
|
|
private void OnAbilityCastEnd(AnimationGenericEvent abilityCastEvent, UnitUseAbilityMemory memory,
|
|
UnitObjectSchemaAgent agent)
|
|
{
|
|
memory.isFinished = true;
|
|
}
|
|
}
|
|
} |