2024-06-23 19:12:22 +01:00

90 lines
2.7 KiB
C#

using System;
using System.Collections;
using System.Collections.Generic;
using UnityEngine;
namespace MBT
{
[AddComponentMenu("")]
[MBTNode(name = "Decorators/Cooldown")]
public class Cooldown : Decorator, IMonoBehaviourTreeTickListener
{
public AbortTypes abort = AbortTypes.None;
[Space]
public FloatReference time = new FloatReference(1f);
[Tooltip("When set to true, there will be no cooldown when child node returns failure")]
public bool resetOnChildFailure = false;
private float cooldownTime = 0f;
private bool entered = false;
private bool childFailed = false;
public enum AbortTypes
{
None, LowerPriority
}
public override void OnAllowInterrupt()
{
if (abort == AbortTypes.LowerPriority)
{
ObtainTreeSnapshot();
}
}
public override NodeResult Execute()
{
if (!TryGetChild(out Node node))
{
return NodeResult.failure;
}
if (node.status == Status.Success) {
return NodeResult.success;
}
if (node.status == Status.Failure) {
// If reset option is enabled flag will be raised and set true
childFailed = resetOnChildFailure;
return NodeResult.failure;
}
if (cooldownTime <= Time.time) {
entered = true;
return node.runningNodeResult;
} else {
return NodeResult.failure;
}
}
public override void OnExit()
{
// Setup cooldown and event when child was entered
// Check reset option too
if (entered && !childFailed)
{
cooldownTime = Time.time + time.Value;
// For LowerPriority try to abort after given time
if (abort == AbortTypes.LowerPriority)
{
behaviourTree.AddTickListener(this);
}
}
// Reset flags
entered = false;
childFailed = false;
}
public override void OnDisallowInterrupt()
{
behaviourTree.RemoveTickListener(this);
}
void IMonoBehaviourTreeTickListener.OnBehaviourTreeTick()
{
if (cooldownTime <= Time.time)
{
// Task should be aborted, so there is no need to listen anymore
behaviourTree.RemoveTickListener(this);
TryAbort(Abort.LowerPriority);
}
}
}
}