🔍 s&box Package Code Search

Search C# source code, UI razor templates, shaders, and configs across s&box packages.

Showing code results for query: * (89 total matches found)
utopia.npbehavesbox / BehaviorTree/Composite/Parallel.cs
Game library
using System.Collections.Generic;
using Sandbox.Diagnostics;

namespace NPBehave
{
    public class Parallel : Composite
    {
        public enum Policy
        {
            One,
            All,
        }

        // public enum Wait
        // {
        //     NEVER,
        //     ON_FAILURE,
        //     ON_SUCCESS,
        //     BOTH
        // }

        // private Wait waitForPendingChildrenRule;
        private Policy _failurePolicy;
        private Policy _successPolicy;
        private int _childrenCount = 0;
        private int _runningCount = 0;
        private int _succeededCount = 0;
        private int _failedCount = 0;
        private Dictionary<Node, bool> _childrenResults;
        private bool _successState;
        private bool _childrenAborted;

        public Parallel(Policy successPolicy, Policy failurePolicy, /*Wait waitForPendingChildrenRule,*/ params Node[] children) : base("Parallel", children)
        {
            _successPolicy = successPolicy;
            _failurePolicy = failurePolicy;
            // this.waitForPendingChildrenRule = waitForPendingChildrenRule;
            _childrenCount = children.Length;
            _childrenResults = new Dictionary<Node, bool>();
        }

        protected override void DoStart()
        {
            foreach (Node child in Children)
            {
                Assert.AreEqual(child.CurrentState, State.Inactive);
            }

            _childrenAborted = false;
            _runningCount = 0;
            _succeededCount = 0;
            _failedCount = 0;
            foreach (Node child in Children)
            {
                _runningCount++;
                child.Start();
            }
        }

        protected override void DoStop()
        {
            Assert.True(_runningCount + _succeededCount + _failedCount == _childrenCount);

            foreach (Node child in Children)
            {
                if (child.IsActive)
                {
                    child.Stop();
                }
            }
        }

        protected override void DoChildStopped(Node child, bool result)
        {
            _runningCount--;
            if (result)
            {
                _succeededCount++;
            }
            else
            {
                _failedCount++;
            }
            _childrenResults[child] = result;

            bool allChildrenStarted = _runningCount + _succeededCount + _failedCount == _childrenCount;
            if (allChildrenStarted)
            {
                if (_runningCount == 0)
                {
                    if (!_childrenAborted) // if children got aborted because rule was evaluated previously, we don't want to override the successState 
                    {
                        if (_failurePolicy == Policy.One && _failedCount > 0)
                        {
                            _successState = false;
                        }
                        else if (_successPolicy == Policy.One && _succeededCount > 0)
                        {
                            _successState = true;
                        }
                        else if (_successPolicy == Policy.All && _succeededCount == _childrenCount)
                        {
                            _successState = true;
                        }
                        else
                        {
                            _successState = false;
                        }
                    }
                    Stopped(_successState);
                }
                else if (!_childrenAborted)
                {
                    Assert.False(_succeededCount == _childrenCount);
                    Assert.False(_failedCount == _childrenCount);

                    if (_failurePolicy == Policy.One && _failedCount > 0/* && waitForPendingChildrenRule != Wait.ON_FAILURE && waitForPendingChildrenRule != Wait.BOTH*/)
                    {
                        _successState = false;
                        _childrenAborted = true;
                    }
                    else if (_successPolicy == Policy.One && _succeededCount > 0/* && waitForPendingChildrenRule != Wait.ON_SUCCESS && waitForPendingChildrenRule != Wait.BOTH*/)
                    {
                        _successState = true;
                        _childrenAborted = true;
                    }

                    if (_childrenAborted)
                    {
                        foreach (Node currentChild in Children)
                        {
                            if (currentChild.IsActive)
                            {
                                currentChild.Stop();
                            }
                        }
                    }
                }
            }
        }

        public override void StopLowerPriorityChildrenForChild(Node abortForChild, bool immediateRestart)
        {
            if (immediateRestart)
            {
                Assert.False(abortForChild.IsActive);
                if (_childrenResults[abortForChild])
                {
                    _succeededCount--;
                }
                else
                {
                    _failedCount--;
                }
                _runningCount++;
                abortForChild.Start();
            }
            else
            {
                throw new Exception("On Parallel Nodes all children have the same priority, thus the method does nothing if you pass false to 'immediateRestart'!");
            }
        }
    }
}
utopia.npbehavesbox / BehaviorTree/Composite/RandomSequence.cs
Game library
using System.Collections;
using Sandbox.Diagnostics;

namespace NPBehave
{
    public class RandomSequence : Composite
    {
        static System.Random _rng = new System.Random();


#if DEBUG
        static public void DebugSetSeed( int seed )
        {
            _rng = new System.Random( seed );
        }
#endif

        private int _currentIndex = -1;
        private int[] _randomizedOrder;

        public RandomSequence(params Node[] children) : base("Random Sequence", children)
        {
            _randomizedOrder = new int[children.Length];
            for (int i = 0; i < Children.Length; i++)
            {
                _randomizedOrder[i] = i;
            }
        }

        protected override void DoStart()
        {
            foreach (Node child in Children)
            {
                Assert.AreEqual(child.CurrentState, State.Inactive);
            }

            _currentIndex = -1;

            // Shuffling
            int n = _randomizedOrder.Length;
            while (n > 1)
            {
                int k = _rng.Next(n--);
                (_randomizedOrder[n], _randomizedOrder[k]) = (_randomizedOrder[k], _randomizedOrder[n]);
            }

            ProcessChildren();
        }

        protected override void DoStop()
        {
            Children[_randomizedOrder[_currentIndex]].Stop();
        }


        protected override void DoChildStopped(Node child, bool result)
        {
            if (result)
            {
                ProcessChildren();
            }
            else
            {
                Stopped(false);
            }
        }

        private void ProcessChildren()
        {
            if (++_currentIndex < Children.Length)
            {
                if (IsStopRequested)
                {
                    Stopped(false);
                }
                else
                {
                    Children[_randomizedOrder[_currentIndex]].Start();
                }
            }
            else
            {
                Stopped(true);
            }
        }

        public override void StopLowerPriorityChildrenForChild(Node abortForChild, bool immediateRestart)
        {
            int indexForChild = 0;
            bool found = false;
            foreach (Node currentChild in Children)
            {
                if (currentChild == abortForChild)
                {
                    found = true;
                }
                else if (!found)
                {
                    indexForChild++;
                }
                else if (found && currentChild.IsActive)
                {
                    if (immediateRestart)
                    {
                        _currentIndex = indexForChild - 1;
                    }
                    else
                    {
                        _currentIndex = Children.Length;
                    }
                    currentChild.Stop();
                    break;
                }
            }
        }

        public override string ToString()
        {
            return $"{base.ToString()}[{_currentIndex}]";
        }
    }
}
utopia.npbehavesbox / BehaviorTree/Decorator/Succeeder.cs
Game library
namespace NPBehave
{
    public class Succeeder : Decorator
    {
        public Succeeder(Node decoratee) : base("Succeeder", decoratee)
        {
        }

        protected override void DoStart()
        {
            Decoratee.Start();
        }

        protected override void DoStop()
        {
            Decoratee.Stop();
        }

        protected override void DoChildStopped(Node child, bool result)
        {
            Stopped(true);
        }
    }
}
utopia.npbehavesbox / Code/BehaviorTree/Exception.cs
Game library
using System;

namespace NPBehave
{
    public class Exception : System.Exception
    {
        public Exception(string message) : base(message)
        {
        }
    }
}
utopia.npbehavesbox / Code/BehaviorTree/Decorator/Repeater.cs
Game library
namespace NPBehave
{
    public class Repeater : Decorator
    {
        private int _loopCount = -1;
        private int _currentLoop;

        /// <param name="loopCount">number of times to execute the decoratee. Set to -1 to repeat forever, be careful with endless loops!</param>
        /// <param name="decoratee">Decorated Node</param>
        public Repeater(int loopCount, Node decoratee) : base("Repeater", decoratee)
        {
            _loopCount = loopCount;
        }

        /// <param name="decoratee">Decorated Node, repeated forever</param>
        public Repeater(Node decoratee) : base("Repeater", decoratee)
        {
        }

        protected override void DoStart()
        {
            if (_loopCount != 0)
            {
                _currentLoop = 0;
                Decoratee.Start();
            }
            else
            {
                Stopped(true);
            }
        }

        protected override void DoStop()
        {
            Clock.RemoveTimer(RestartDecoratee);
            
            if (Decoratee.IsActive)
            {
                Decoratee.Stop();
            }
            else
            {
                Stopped(false);
            }
        }

        protected override void DoChildStopped(Node child, bool result)
        {
            if (result)
            {
                if (IsStopRequested || (_loopCount > 0 && ++_currentLoop >= _loopCount))
                {
                    Stopped(true);
                }
                else
                {
                    Clock.AddTimer(0, 0, RestartDecoratee);
                }
            }
            else
            {
                Stopped(false);
            }
        }

        protected void RestartDecoratee()
        {
            Decoratee.Start();
        }
    }
}
utopia.npbehavesbox / BehaviorTree/Composite/Selector.cs
Game library
using System.Collections;
using Sandbox.Diagnostics;

namespace NPBehave
{
    public class Selector : Composite
    {
        private int _currentIndex = -1;

        public Selector(params Node[] children) : base("Selector", children)
        {
        }

		#if DEBUG
	    public override string DebugIcon => "rule";
		#endif
        protected override void DoStart()
        {
            foreach (Node child in Children)
            {
                Assert.AreEqual(child.CurrentState, State.Inactive);
            }

            _currentIndex = -1;

            ProcessChildren();
        }

        protected override void DoStop()
        {
            Children[_currentIndex].Stop();
        }

        protected override void DoChildStopped(Node child, bool result)
        {
            if (result)
            {
                Stopped(true);
            }
            else
            {
                ProcessChildren();
            }
        }

        private void ProcessChildren()
        {
            if (++_currentIndex < Children.Length)
            {
                if (IsStopRequested)
                {
                    Stopped(false);
                }
                else
                {
                    Children[_currentIndex].Start();
                }
            }
            else
            {
                Stopped(false);
            }
        }

        public override void StopLowerPriorityChildrenForChild(Node abortForChild, bool immediateRestart)
        {
            int indexForChild = 0;
            bool found = false;
            foreach (Node currentChild in Children)
            {
                if (currentChild == abortForChild)
                {
                    found = true;
                }
                else if (!found)
                {
                    indexForChild++;
                }
                else if (found && currentChild.IsActive)
                {
                    if (immediateRestart)
                    {
                        _currentIndex = indexForChild - 1;
                    }
                    else
                    {
                        _currentIndex = Children.Length;
                    }
                    currentChild.Stop();
                    break;
                }
            }
        }

        public override string ToString()
        {
            return $"{base.ToString()}[{_currentIndex}]";
        }
    }
}
utopia.npbehavesbox / BehaviorTree/Decorator/BlackboardCondition.cs
Game library
namespace NPBehave
{
    public class BlackboardCondition : ObservingDecorator
    {
        private string _key;
        private object _value;
        private Operator _op;

        public string Key
        {
            get
            {
                return _key;
            }
        }

        public object Value
        {
            get
            {
                return _value;
            }
        }

        public Operator Operator
        {
            get
            {
                return _op;
            }
        }
        
        #if DEBUG
	    public override string DebugIcon => "quiz";
	    public override string ComputedLabel
	    {
		    get
		    {
			    return $"{Key} {OperatorToString(Operator)} {Value}";
		    }
	    }

	    public string OperatorToString( Operator _op )
	    {
		    return _op switch
		    {
			    Operator.IsSet => "?=",
			    Operator.IsNotSet => "?!=",
			    Operator.IsEqual => "==",
			    Operator.IsNotEqual => "!=",
			    Operator.IsGreaterOrEqual => ">=",
			    Operator.IsGreater => ">",
			    Operator.IsSmallerOrEqual => "<=",
			    Operator.IsSmaller => "<",
			    Operator.AlwaysTrue => "ALWAYS_TRUE",
			    _ => $"<{_op}>"
		    };
	    }


#endif

        public BlackboardCondition(string key, Operator op, object value, Stops stopsOnChange, Node decoratee) : base("BlackboardCondition", stopsOnChange, decoratee)
        {
            _op = op;
            _key = key;
            _value = value;
            StopsOnChange = stopsOnChange;
        }
        
        public BlackboardCondition(string key, Operator op, Stops stopsOnChange, Node decoratee) : base("BlackboardCondition", stopsOnChange, decoratee)
        {
            _op = op;
            _key = key;
            StopsOnChange = stopsOnChange;
        }


        protected override void StartObserving()
        {
            RootNode.Blackboard.AddObserver(_key, OnValueChanged);
        }

        protected override void StopObserving()
        {
            RootNode.Blackboard.RemoveObserver(_key, OnValueChanged);
        }

        private void OnValueChanged(Blackboard.Type type, object newValue)
        {
            Evaluate();
        }

        protected override bool IsConditionMet()
        {
            if (_op == Operator.AlwaysTrue)
            {
                return true;
            }

            if (!RootNode.Blackboard.IsSet(_key))
            {
                return _op == Operator.IsNotSet;
            }

            object o = RootNode.Blackboard.Get(_key);

            switch (_op)
            {
                case Operator.IsSet: return true;
                case Operator.IsEqual: return Equals(o, _value);
                case Operator.IsNotEqual: return !Equals(o, _value);

                case Operator.IsGreaterOrEqual:
                    if (o is float)
                    {
                        return (float)o >= (float)_value;
                    }
                    else if (o is int)
                    {
                        return (int)o >= (int)_value;
                    }
                    else
                    {
                        Log.Error( $"Type not compareable: {o.GetType()}" );
                        return false;
                    }

                case Operator.IsGreater:
                    if (o is float)
                    {
                        return (float)o > (float)_value;
                    }
                    else if (o is int)
                    {
                        return (int)o > (int)_value;
                    }
                    else
                    {
	                    Log.Error( $"Type not compareable: {o.GetType()}" );
                        return false;
                    }

                case Operator.IsSmallerOrEqual:
                    if (o is float)
                    {
                        return (float)o <= (float)_value;
                    }
                    else if (o is int)
                    {
                        return (int)o <= (int)_value;
                    }
                    else
                    {
	                    Log.Error( $"Type not compareable: {o.GetType()}" );
                        return false;
                    }

                case Operator.IsSmaller:
                    if (o is float)
                    {
                        return (float)o < (float)_value;
                    }
                    else if (o is int)
                    {
                        return (int)o < (int)_value;
                    }
                    else
                    {
	                    Log.Error( $"Type not compareable: {o.GetType()}" );
                        return false;
                    }

                default: return false;
            }
        }

        public override string ToString()
        {
            return $"({_op}) {_key} ? {_value}";
        }
    }
}
utopia.npbehavesbox / BehaviorTree/Decorator/Condition.cs
Game library
using System;

namespace NPBehave
{
    public class Condition : ObservingDecorator
    {
        private Func<bool> _condition;
        private float _checkInterval;
        private float _checkVariance;

        public Condition(Func<bool> condition, Node decoratee) : base("Condition", Stops.None, decoratee)
        {
            _condition = condition;
            _checkInterval = 0.0f;
            _checkVariance = 0.0f;
        }

        public Condition(Func<bool> condition, Stops stopsOnChange, Node decoratee) : base("Condition", stopsOnChange, decoratee)
        {
            _condition = condition;
            _checkInterval = 0.0f;
            _checkVariance = 0.0f;
        }

        public Condition(Func<bool> condition, Stops stopsOnChange, float checkInterval, float randomVariance, Node decoratee) : base("Condition", stopsOnChange, decoratee)
        {
            _condition = condition;
            _checkInterval = checkInterval;
            _checkVariance = randomVariance;
        }

        protected override void StartObserving()
        {
            RootNode.Clock.AddTimer(_checkInterval, _checkVariance, -1, Evaluate);
        }

        protected override void StopObserving()
        {
            RootNode.Clock.RemoveTimer(Evaluate);
        }

        protected override bool IsConditionMet()
        {
            return _condition();
        }
    }
}
utopia.npbehavesbox / BehaviorTree/Decorator/Decorator.cs
Game library
namespace NPBehave
{

    public abstract class Decorator : Container
    {
        protected Node Decoratee;

        public Decorator(string name, Node decoratee) : base(name)
        {
            Decoratee = decoratee;
            Decoratee.SetParent(this);
        }

        public override void SetRoot(Root rootNode)
        {
            base.SetRoot(rootNode);
            Decoratee.SetRoot(rootNode);
        }


#if DEBUG

	    public override string DebugIcon => "brush";
	    public override Node[] DebugChildren
        {
            get
            {
                return new Node[] { Decoratee };
            }
        }
#endif

        public override void ParentCompositeStopped(Composite composite)
        {
            base.ParentCompositeStopped(composite);
            Decoratee.ParentCompositeStopped(composite);
        }
    }
}
utopia.npbehavesbox / BehaviorTree/Decorator/ObservingDecorator.cs
Game library
using System.Collections;
using Sandbox.Diagnostics;

namespace NPBehave
{
    public abstract class ObservingDecorator : Decorator
    {
        protected Stops StopsOnChange;
        private bool _isObserving;

        public ObservingDecorator(string name, Stops stopsOnChange, Node decoratee) : base(name, decoratee)
        {
            StopsOnChange = stopsOnChange;
            _isObserving = false;
        }

        protected override void DoStart()
        {
            if (StopsOnChange != Stops.None)
            {
                if (!_isObserving)
                {
                    _isObserving = true;
                    StartObserving();
                }
            }

            if (!IsConditionMet())
            {
                Stopped(false);
            }
            else
            {
                Decoratee.Start();
            }
        }

        protected override void DoStop()
        {
            Decoratee.Stop();
        }

        protected override void DoChildStopped(Node child, bool result)
        {
            Assert.AreNotEqual(((Node)this).CurrentState, State.Inactive);
            if (StopsOnChange is Stops.None or Stops.Self)
            {
                if (_isObserving)
                {
                    _isObserving = false;
                    StopObserving();
                }
            }
            Stopped(result);
        }

        protected override void DoParentCompositeStopped(Composite parentComposite)
        {
            if (_isObserving)
            {
                _isObserving = false;
                StopObserving();
            }
        }

        protected void Evaluate()
        {
            if (IsActive && !IsConditionMet())
            {
                if (StopsOnChange is Stops.Self or Stops.Both or Stops.ImmediateRestart)
                {
                    // Debug.Log( this.key + " stopped self ");
                    Stop();
                }
            }
            else if (!IsActive && IsConditionMet())
            {
                if (StopsOnChange == Stops.LowerPriority || StopsOnChange == Stops.Both || StopsOnChange == Stops.ImmediateRestart || StopsOnChange == Stops.LowerPriorityImmediateRestart)
                {
                    // Debug.Log( this.key + " stopped other ");
                    Container parentNode = ParentNode;
                    Node childNode = this;
                    while (parentNode != null && !(parentNode is Composite))
                    {
                        childNode = parentNode;
                        parentNode = parentNode.ParentNode;
                    }
                    Assert.NotNull(parentNode, "NTBtrStops is only valid when attached to a parent composite");
                    Assert.NotNull(childNode);
                    if (parentNode is Parallel)
                    {
                        Assert.True(StopsOnChange == Stops.ImmediateRestart, "On Parallel Nodes all children have the same priority, thus Stops.LOWER_PRIORITY or Stops.BOTH are unsupported in this context!");
                    }

                    if (StopsOnChange == Stops.ImmediateRestart || StopsOnChange == Stops.LowerPriorityImmediateRestart)
                    {
                        if (_isObserving)
                        {
                            _isObserving = false;
                            StopObserving();
                        }
                    }

                    ((Composite)parentNode)?.StopLowerPriorityChildrenForChild(childNode, StopsOnChange is Stops.ImmediateRestart or Stops.LowerPriorityImmediateRestart);
                }
            }
        }

        protected abstract void StartObserving();

        protected abstract void StopObserving();

        protected abstract bool IsConditionMet();

    }
}
utopia.npbehavesbox / BehaviorTree/Decorator/TimeMin.cs
Game library
using Sandbox.Diagnostics;

namespace NPBehave
{
    public class TimeMin : Decorator
    {
        private float _limit = 0.0f;
        private float _randomVariation;
        private bool _waitOnFailure = false;
        private bool _isLimitReached = false;
        private bool _isDecorateeDone = false;
        private bool _isDecorateeSuccess = false;

        public TimeMin(float limit, Node decoratee) : base("TimeMin", decoratee)
        {
            _limit = limit;
            _randomVariation = _limit * 0.05f;
            _waitOnFailure = false;
            Assert.True(limit > 0f, "limit has to be set");
        }

        public TimeMin(float limit, bool waitOnFailure, Node decoratee) : base("TimeMin", decoratee)
        {
            _limit = limit;
            _randomVariation = _limit * 0.05f;
            _waitOnFailure = waitOnFailure;
            Assert.True(limit > 0f, "limit has to be set");
        }

        public TimeMin(float limit, float randomVariation, bool waitOnFailure, Node decoratee) : base("TimeMin", decoratee)
        {
            _limit = limit;
            _randomVariation = randomVariation;
            _waitOnFailure = waitOnFailure;
            Assert.True(limit > 0f, "limit has to be set");
        }

        protected override void DoStart()
        {
            _isDecorateeDone = false;
            _isDecorateeSuccess = false;
            _isLimitReached = false;
            Clock.AddTimer(_limit, _randomVariation, 0, TimeoutReached);
            Decoratee.Start();
        }

        protected override void DoStop()
        {
            if (Decoratee.IsActive)
            {
                Clock.RemoveTimer(TimeoutReached);
                _isLimitReached = true;
                Decoratee.Stop();
            }
            else
            {
                Clock.RemoveTimer(TimeoutReached);
                Stopped(false);
            }
        }

        protected override void DoChildStopped(Node child, bool result)
        {
            _isDecorateeDone = true;
            _isDecorateeSuccess = result;
            if (_isLimitReached || (!result && !_waitOnFailure))
            {
                Clock.RemoveTimer(TimeoutReached);
                Stopped(_isDecorateeSuccess);
            }
            else
            {
                Assert.True(Clock.HasTimer(TimeoutReached));
            }
        }

        private void TimeoutReached()
        {
            _isLimitReached = true;
            if (_isDecorateeDone)
            {
                Stopped(_isDecorateeSuccess);
            }
            else
            {
                Assert.True(Decoratee.IsActive);
            }
        }
    }
}
utopia.npbehavesbox / UnitTests/LibraryTest.cs
UnitTest library
using Sandbox;

[TestClass]
public partial class LibraryTests
{
	[TestMethod]
	public void SceneTest()
	{
		var scene = new Scene();
		using ( scene.Push() )
		{
			var go = new GameObject();

			Assert.AreEqual( 1, scene.Directory.GameObjectCount );
		}
	}

}
utopia.npbehavesbox / BehaviorTree/Composite/RandomSelector.cs
Game library
using System.Collections;
using Sandbox.Diagnostics;


namespace NPBehave
{
    public class RandomSelector : Composite
    {
        static System.Random _rng = new System.Random();

#if DEBUG
        static public void DebugSetSeed( int seed )
        {
            _rng = new System.Random( seed );
        }
#endif

        private int _currentIndex = -1;
        private int[] _randomizedOrder;

        public RandomSelector(params Node[] children) : base("Random Selector", children)
        {
            _randomizedOrder = new int[children.Length];
            for (int i = 0; i < Children.Length; i++)
            {
                _randomizedOrder[i] = i;
            }
        }


        protected override void DoStart()
        {
            foreach (Node child in Children)
            {
                Assert.AreEqual(child.CurrentState, State.Inactive);
            }

            _currentIndex = -1;

            // Shuffling
            int n = _randomizedOrder.Length;
            while (n > 1)
            {
                int k = _rng.Next(n--);
                (_randomizedOrder[n], _randomizedOrder[k]) = (_randomizedOrder[k], _randomizedOrder[n]);
            }

            ProcessChildren();
        }



        protected override void DoStop()
        {
            Children[_randomizedOrder[_currentIndex]].Stop();
        }

        protected override void DoChildStopped(Node child, bool result)
        {
            if (result)
            {
                Stopped(true);
            }
            else
            {
                ProcessChildren();
            }
        }

        private void ProcessChildren()
        {
            if (++_currentIndex < Children.Length)
            {
                if (IsStopRequested)
                {
                    Stopped(false);
                }
                else
                {
                    Children[_randomizedOrder[_currentIndex]].Start();
                }
            }
            else
            {
                Stopped(false);
            }
        }

        public override void StopLowerPriorityChildrenForChild(Node abortForChild, bool immediateRestart)
        {
            int indexForChild = 0;
            bool found = false;
            foreach (Node currentChild in Children)
            {
                if (currentChild == abortForChild)
                {
                    found = true;
                }
                else if (!found)
                {
                    indexForChild++;
                }
                else if (found && currentChild.IsActive)
                {
                    if (immediateRestart)
                    {
                        _currentIndex = indexForChild - 1;
                    }
                    else
                    {
                        _currentIndex = Children.Length;
                    }
                    currentChild.Stop();
                    break;
                }
            }
        }

        public override string ToString()
        {
            return $"{base.ToString()}[{_currentIndex}]";
        }
    }
}
utopia.npbehavesbox / BehaviorTree/Debugger.cs
Game library
using System.Collections.Generic;
using Sandbox;

namespace NPBehave
{
    public class Debugger : Component
    {
        public Root BehaviorTree;

        private static Blackboard _customGlobalStats = null;
        public static Blackboard CustomGlobalStats
        {
            get 
            {
                if (_customGlobalStats == null)
                {
                    _customGlobalStats = SandboxContext.GetSharedBlackboard("_GlobalStats");;
                }
                return _customGlobalStats;
            }
        }

        private Blackboard _customStats = null;
        public Blackboard CustomStats
        {
            get 
            {
                if (_customStats == null)
                {
                    _customStats = new Blackboard(CustomGlobalStats, SandboxContext.GetClock());
                }
                return _customStats;
            }
        }

        public void DebugCounterInc(string key)
        {
            if (!CustomStats.IsSet(key))
            {
                CustomStats[key] = 0;
            }
            CustomStats[key] = CustomStats.Get<int>(key) + 1;
        }

        public void DebugCounterDec(string key)
        {
            if (!CustomStats.IsSet(key))
            {
                CustomStats[key] = 0;
            }
            CustomStats[key] = CustomStats.Get<int>(key) - 1;
        }

        public static void GlobalDebugCounterInc(string key)
        {
            if (!CustomGlobalStats.IsSet(key))
            {
                CustomGlobalStats[key] = 0;
            }
            CustomGlobalStats[key] = CustomGlobalStats.Get<int>(key) + 1;
        }

        public static void GlobalDebugCounterDec(string key)
        {
            if (!CustomGlobalStats.IsSet(key))
            {
                CustomGlobalStats[key] = 0;
            }
            CustomGlobalStats[key] = CustomGlobalStats.Get<int>(key) - 1;
        }

    }
}
utopia.npbehavesbox / BehaviorTree/Decorator/Inverter.cs
Game library
namespace NPBehave
{
    public class Inverter : Decorator
    {
        public Inverter(Node decoratee) : base("Inverter", decoratee)
        {
        }

        protected override void DoStart()
        {
            Decoratee.Start();
        }

        protected override void DoStop()
        {
            Decoratee.Stop();
        }

        protected override void DoChildStopped(Node child, bool result)
        {
            Stopped(!result);
        }
    }
}
utopia.npbehavesbox / BehaviorTree/Stops.cs
Game library
namespace NPBehave
{
    public enum Stops
    {
	    /// <summary>
	    /// The decorator will only check it's condition once it is started and will never stop any running nodes.
	    /// </summary>
        None,
	    /// <summary>
	    /// The decorator will check it's condition once it is started and if it is met,
	    /// it will observe the blackboard for changes.
	    /// Once the condition is no longer met, it will stop itself allowing the parent composite to proceed with it's next node.
	    /// </summary>
        Self,
	    
	    /// <summary>
	    /// The decorator will check it's condition once it is started and if it's not met, it will observe the blackboard for changes.
	    /// Once the condition is met, it will stop the lower priority node allowing the parent composite to proceed with it's next node
	    /// </summary>
        LowerPriority,
	    
	    /// <summary>
	    /// The decorator will stop both: self and lower priority nodes.
	    /// </summary>
        Both,
	    
	    /// <summary>
	    /// The decorator will check it's condition once it is started and if it's not met, it will observe the blackboard for changes.
	    /// Once the condition is met, it will stop the lower priority node and order the parent composite to restart the Decorator immediately.
	    /// </summary>
        ImmediateRestart,
	    
	    /// <summary>
	    /// The decorator will check it's condition once it is started and if it's not met, it will observe the blackboard for changes.
	    /// Once the condition is met, it will stop the lower priority node and order the parent composite to restart the Decorator immediately.
	    /// As in BOTH it will also stop itself as soon as the condition is no longer met.
	    /// </summary>
        LowerPriorityImmediateRestart
    }
}
utopia.npbehavesbox / BehaviorTree/Task/Action.cs
Game library
using Sandbox.Diagnostics;

namespace NPBehave
{
    public class Action : Task
    {
        public enum Result
        {
            Success,
            Failed,
            Blocked,
            Progress
        }

        public enum Request
        {
            Start,
            Update,
            Cancel,
        }

        private System.Func<bool> _singleFrameFunc = null;
        private System.Func<bool, Result> _multiFrameFunc = null;
        private System.Func<Request, Result> _multiFrameFunc2 = null;
        private System.Action _action = null;
        private bool _bWasBlocked = false;

        public Action(System.Action action) : base("Action")
        {
            _action = action;
        }

        public Action(System.Func<bool, Result> multiframeFunc) : base("Action")
        {
            _multiFrameFunc = multiframeFunc;
        }

        public Action(System.Func<Request, Result> multiframeFunc2) : base("Action")
        {
            _multiFrameFunc2 = multiframeFunc2;
        }


        public Action(System.Func<bool> singleFrameFunc) : base("Action")
        {
            _singleFrameFunc = singleFrameFunc;
        }

        protected override void DoStart()
        {
            if (_action != null)
            {
                _action.Invoke();
                Stopped(true);
            }
            else if (_multiFrameFunc != null)
            {
                Result result = _multiFrameFunc.Invoke(false);
                if ( result == Result.Progress )
                {
                    RootNode.Clock.AddUpdateObserver( OnUpdateFunc );
                }
                else if ( result == Result.Blocked )
                {
                    _bWasBlocked = true;
                    RootNode.Clock.AddUpdateObserver( OnUpdateFunc );
                }
                else
                {
                    Stopped(result == Result.Success);
                }
            }
            else if (_multiFrameFunc2 != null)
            {
                Result result = _multiFrameFunc2.Invoke(Request.Start);
                if (result == Result.Progress)
                {
                    RootNode.Clock.AddUpdateObserver(OnUpdateFunc2);
                }
                else if ( result == Result.Blocked )
                {
                    _bWasBlocked = true;
                    RootNode.Clock.AddUpdateObserver( OnUpdateFunc2 );
                }
                else
                {
                    Stopped(result == Result.Success);
                }
            }
            else if (_singleFrameFunc != null)
            {
                Stopped(_singleFrameFunc.Invoke());
            }
        }

        private void OnUpdateFunc()
        {
            Result result = _multiFrameFunc.Invoke(false);
            if (result != Result.Progress && result != Result.Blocked)
            {
                RootNode.Clock.RemoveUpdateObserver(OnUpdateFunc);
                Stopped(result == Result.Success);
            }
        }

        private void OnUpdateFunc2()
        {
            Result result = _multiFrameFunc2.Invoke( _bWasBlocked ? Request.Start : Request.Update);

            if ( result == Result.Blocked )
            {
                _bWasBlocked = true;
            }
            else if ( result == Result.Progress )
            {
                _bWasBlocked = false;
            }
            else
            {
                RootNode.Clock.RemoveUpdateObserver( OnUpdateFunc2 );
                Stopped( result == Result.Success );
            }
        }

        protected override void DoStop()
        {
            if (_multiFrameFunc != null)
            {
                Result result = _multiFrameFunc.Invoke(true);
                Assert.AreNotEqual(result, Result.Progress, "The Task has to return Result.SUCCESS, Result.FAILED/BLOCKED after beeing cancelled!");
                RootNode.Clock.RemoveUpdateObserver(OnUpdateFunc);
                Stopped(result == Result.Success);
            }
            else if (_multiFrameFunc2 != null)
            {
                Result result = _multiFrameFunc2.Invoke(Request.Cancel);
                Assert.AreNotEqual(result, Result.Progress, "The Task has to return Result.SUCCESS or Result.FAILED/BLOCKED after beeing cancelled!");
                RootNode.Clock.RemoveUpdateObserver(OnUpdateFunc2);
                Stopped(result == Result.Success);
            }
            else
            {
                Assert.True(false, $"DoStop called for a single frame action on {this}" );
            }
        }
    }
}
utopia.npbehavesbox / Samples/NPBehaveExampleHelloWorldAI.cs
Game library
using NPBehave;

namespace Sandbox.Samples;

public class NPBehaveExampleHelloWorldAI : Component
{
	private Root _behaviorTree;

	void Start()
	{
		_behaviorTree = new Root(
			new Sequence(
				new Action(() => Log.Info("Hello, World!"))
			)
		);
		_behaviorTree.Start();
	}
}
utopia.npbehavesbox / Code/BehaviorTree/Blackboard.cs
Game library
using System.Collections.Generic;

namespace NPBehave
{
    public class Blackboard
    {
        public enum Type
        {
            Add,
            Remove,
            Change
        }
        private struct Notification
        {
            public string Key;
            public Type Type;
            public object Value;
            public Notification(string key, Type type, object value)
            {
                Key = key;
                Type = type;
                Value = value;
            }
        }

        private Clock _clock;
        private Dictionary<string, object> _data = new Dictionary<string, object>();
        private Dictionary<string, List<System.Action<Type, object>>> _observers = new Dictionary<string, List<System.Action<Type, object>>>();
        private bool _isNotifiyng = false;
        private Dictionary<string, List<System.Action<Type, object>>> _addObservers = new Dictionary<string, List<System.Action<Type, object>>>();
        private Dictionary<string, List<System.Action<Type, object>>> _removeObservers = new Dictionary<string, List<System.Action<Type, object>>>();
        private List<Notification> _notifications = new List<Notification>();
        private List<Notification> _notificationsDispatch = new List<Notification>();
        private Blackboard _parentBlackboard;
        private HashSet<Blackboard> _children = new HashSet<Blackboard>();

        public Blackboard(Blackboard parent, Clock clock)
        {
            _clock = clock;
            _parentBlackboard = parent;
        }
        public Blackboard(Clock clock)
        {
            _parentBlackboard = null;
            _clock = clock;
        }

        public void Enable()
        {
	        _parentBlackboard?._children.Add(this);
        }

        public void Disable()
        {
	        _parentBlackboard?._children.Remove(this);
            if (_clock != null)
            {
                _clock.RemoveTimer(NotifiyObservers);
            }
        }

        public object this[string key]
        {
            get
            {
                return Get(key);
            }
            set
            {
                Set(key, value);
            }
        }

        public void Set(string key)
        {
            if (!IsSet(key))
            {
                Set(key, null);
            }
        }

        public void Set(string key, object value)
        {
            if (_parentBlackboard != null && _parentBlackboard.IsSet(key))
            {
                _parentBlackboard.Set(key, value);
            }
            else
            {
                if (_data.TryAdd(key, value))
                {
	                _notifications.Add(new Notification(key, Type.Add, value));
                    _clock.AddTimer(0f, 0, NotifiyObservers);
                }
                else
                {
                    if ((_data[key] == null && value != null) || (_data[key] != null && !_data[key].Equals(value)))
                    {
                        _data[key] = value;
                        _notifications.Add(new Notification(key, Type.Change, value));
                        _clock.AddTimer(0f, 0, NotifiyObservers);
                    }
                }
            }
        }

        public void Unset(string key)
        {
            if (_data.ContainsKey(key))
            {
                _data.Remove(key);
                _notifications.Add(new Notification(key, Type.Remove, null));
                _clock.AddTimer(0f, 0, NotifiyObservers);
            }
        }

        public T Get<T>(string key)
        {
            object result = Get(key);
            if (result == null)
            {
                return default(T);
            }
            return (T)result;
        }

        public object Get(string key)
        {
	        return _data.TryGetValue(key, out var value) ? value : _parentBlackboard?.Get(key);
        }

        public bool IsSet(string key)
        {
            return _data.ContainsKey(key) || (_parentBlackboard != null && _parentBlackboard.IsSet(key));
        }

        public void AddObserver(string key, System.Action<Type, object> observer)
        {
            List<System.Action<Type, object>> observers = GetObserverList(_observers, key);
            if (!_isNotifiyng)
            {
                if (!observers.Contains(observer))
                {
                    observers.Add(observer);
                }
            }
            else
            {
                if (!observers.Contains(observer))
                {
                    List<System.Action<Type, object>> addObservers = GetObserverList(_addObservers, key);
                    if (!addObservers.Contains(observer))
                    {
                        addObservers.Add(observer);
                    }
                }

                List<System.Action<Type, object>> removeObservers = GetObserverList(_removeObservers, key);
                if (removeObservers.Contains(observer))
                {
                    removeObservers.Remove(observer);
                }
            }
        }

        public void RemoveObserver(string key, System.Action<Type, object> observer)
        {
            List<System.Action<Type, object>> observers = GetObserverList(_observers, key);
            if (!_isNotifiyng)
            {
                if (observers.Contains(observer))
                {
                    observers.Remove(observer);
                }
            }
            else
            {
                List<System.Action<Type, object>> removeObservers = GetObserverList(_removeObservers, key);
                if (!removeObservers.Contains(observer))
                {
                    if (observers.Contains(observer))
                    {
                        removeObservers.Add(observer);
                    }
                }

                List<System.Action<Type, object>> addObservers = GetObserverList(_addObservers, key);
                if (addObservers.Contains(observer))
                {
                    addObservers.Remove(observer);
                }
            }
        }


#if DEBUG
        public List<string> Keys
        {
            get
            {
                if (_parentBlackboard != null)
                {
                    List<string> keys = this._parentBlackboard.Keys;
                    keys.AddRange(_data.Keys);
                    return keys;
                }
                else
                {
                    return new List<string>(_data.Keys);
                }
            }
        }

        public int NumObservers
        {
            get
            {
                int count = 0;
                foreach (var key in _observers.Keys)
                {
                    count += _observers[key].Count;
                }
                return count;
            }
        }
#endif


        private void NotifiyObservers()
        {
            if (_notifications.Count == 0)
            {
                return;
            }

            _notificationsDispatch.Clear();
            _notificationsDispatch.AddRange(_notifications);
            foreach (Blackboard child in _children)
            {
                child._notifications.AddRange(_notifications);
                child._clock.AddTimer(0f, 0, child.NotifiyObservers);
            }
            _notifications.Clear();

            _isNotifiyng = true;
            foreach (Notification notification in _notificationsDispatch)
            {
                if (!_observers.ContainsKey(notification.Key))
                {
                    //                Debug.Log("1 do not notify for key:" + notification.key + " value: " + notification.value);
                    continue;
                }

                List<System.Action<Type, object>> observers = GetObserverList(_observers, notification.Key);
                foreach (System.Action<Type, object> observer in observers)
                {
                    if (_removeObservers.TryGetValue( notification.Key, out List<System.Action<Type, object>> value ) && value.Contains(observer))
                    {
                        continue;
                    }
                    observer(notification.Type, notification.Value);
                }
            }

            foreach (string key in _addObservers.Keys)
            {
                GetObserverList(_observers, key).AddRange(_addObservers[key]);
            }
            foreach (string key in _removeObservers.Keys)
            {
                foreach (System.Action<Type, object> action in _removeObservers[key])
                {
                    GetObserverList(_observers, key).Remove(action);
                }
            }
            _addObservers.Clear();
            _removeObservers.Clear();

            _isNotifiyng = false;
        }

        private List<System.Action<Type, object>> GetObserverList(Dictionary<string, List<System.Action<Type, object>>> target, string key)
        {
            List<System.Action<Type, object>> observers;
            if (target.TryGetValue(key, out var value))
            {
                observers = value;
            }
            else
            {
                observers = new List<System.Action<Type, object>>();
                target[key] = observers;
            }
            return observers;
        }
    }
}
utopia.npbehavesbox / Code/BehaviorTree/Debugger.cs
Game library
using System.Collections.Generic;
using Sandbox;

namespace NPBehave
{
    public class Debugger : Component
    {
        public Root BehaviorTree;

        private static Blackboard _customGlobalStats = null;
        public static Blackboard CustomGlobalStats
        {
            get 
            {
                if (_customGlobalStats == null)
                {
                    _customGlobalStats = SandboxContext.GetSharedBlackboard("_GlobalStats");;
                }
                return _customGlobalStats;
            }
        }

        private Blackboard _customStats = null;
        public Blackboard CustomStats
        {
            get 
            {
                if (_customStats == null)
                {
                    _customStats = new Blackboard(CustomGlobalStats, SandboxContext.GetClock());
                }
                return _customStats;
            }
        }

        public void DebugCounterInc(string key)
        {
            if (!CustomStats.IsSet(key))
            {
                CustomStats[key] = 0;
            }
            CustomStats[key] = CustomStats.Get<int>(key) + 1;
        }

        public void DebugCounterDec(string key)
        {
            if (!CustomStats.IsSet(key))
            {
                CustomStats[key] = 0;
            }
            CustomStats[key] = CustomStats.Get<int>(key) - 1;
        }

        public static void GlobalDebugCounterInc(string key)
        {
            if (!CustomGlobalStats.IsSet(key))
            {
                CustomGlobalStats[key] = 0;
            }
            CustomGlobalStats[key] = CustomGlobalStats.Get<int>(key) + 1;
        }

        public static void GlobalDebugCounterDec(string key)
        {
            if (!CustomGlobalStats.IsSet(key))
            {
                CustomGlobalStats[key] = 0;
            }
            CustomGlobalStats[key] = CustomGlobalStats.Get<int>(key) - 1;
        }

    }
}
Debug: View Raw JSON Response
{
    "TotalCount": 89,
    "Files": [
        {
            "Ident": "utopia.npbehavesbox",
            "Path": "BehaviorTree/Composite/Parallel.cs",
            "FileName": "Parallel.cs",
            "PackageType": "library",
            "CodeKind": "Game",
            "AssetVersionId": 72229,
            "Code": "using System.Collections.Generic;\nusing Sandbox.Diagnostics;\n\nnamespace NPBehave\n{\n    public class Parallel : Composite\n    {\n        public enum Policy\n        {\n            One,\n            All,\n        }\n\n        // public enum Wait\n        // {\n        //     NEVER,\n        //     ON_FAILURE,\n        //     ON_SUCCESS,\n        //     BOTH\n        // }\n\n        // private Wait waitForPendingChildrenRule;\n        private Policy _failurePolicy;\n        private Policy _successPolicy;\n        private int _childrenCount = 0;\n        private int _runningCount = 0;\n        private int _succeededCount = 0;\n        private int _failedCount = 0;\n        private Dictionary<Node, bool> _childrenResults;\n        private bool _successState;\n        private bool _childrenAborted;\n\n        public Parallel(Policy successPolicy, Policy failurePolicy, /*Wait waitForPendingChildrenRule,*/ params Node[] children) : base(\"Parallel\", children)\n        {\n            _successPolicy = successPolicy;\n            _failurePolicy = failurePolicy;\n            // this.waitForPendingChildrenRule = waitForPendingChildrenRule;\n            _childrenCount = children.Length;\n            _childrenResults = new Dictionary<Node, bool>();\n        }\n\n        protected override void DoStart()\n        {\n            foreach (Node child in Children)\n            {\n                Assert.AreEqual(child.CurrentState, State.Inactive);\n            }\n\n            _childrenAborted = false;\n            _runningCount = 0;\n            _succeededCount = 0;\n            _failedCount = 0;\n            foreach (Node child in Children)\n            {\n                _runningCount++;\n                child.Start();\n            }\n        }\n\n        protected override void DoStop()\n        {\n            Assert.True(_runningCount + _succeededCount + _failedCount == _childrenCount);\n\n            foreach (Node child in Children)\n            {\n                if (child.IsActive)\n                {\n                    child.Stop();\n                }\n            }\n        }\n\n        protected override void DoChildStopped(Node child, bool result)\n        {\n            _runningCount--;\n            if (result)\n            {\n                _succeededCount++;\n            }\n            else\n            {\n                _failedCount++;\n            }\n            _childrenResults[child] = result;\n\n            bool allChildrenStarted = _runningCount + _succeededCount + _failedCount == _childrenCount;\n            if (allChildrenStarted)\n            {\n                if (_runningCount == 0)\n                {\n                    if (!_childrenAborted) // if children got aborted because rule was evaluated previously, we don't want to override the successState \n                    {\n                        if (_failurePolicy == Policy.One && _failedCount > 0)\n                        {\n                            _successState = false;\n                        }\n                        else if (_successPolicy == Policy.One && _succeededCount > 0)\n                        {\n                            _successState = true;\n                        }\n                        else if (_successPolicy == Policy.All && _succeededCount == _childrenCount)\n                        {\n                            _successState = true;\n                        }\n                        else\n                        {\n                            _successState = false;\n                        }\n                    }\n                    Stopped(_successState);\n                }\n                else if (!_childrenAborted)\n                {\n                    Assert.False(_succeededCount == _childrenCount);\n                    Assert.False(_failedCount == _childrenCount);\n\n                    if (_failurePolicy == Policy.One && _failedCount > 0/* && waitForPendingChildrenRule != Wait.ON_FAILURE && waitForPendingChildrenRule != Wait.BOTH*/)\n                    {\n                        _successState = false;\n                        _childrenAborted = true;\n                    }\n                    else if (_successPolicy == Policy.One && _succeededCount > 0/* && waitForPendingChildrenRule != Wait.ON_SUCCESS && waitForPendingChildrenRule != Wait.BOTH*/)\n                    {\n                        _successState = true;\n                        _childrenAborted = true;\n                    }\n\n                    if (_childrenAborted)\n                    {\n                        foreach (Node currentChild in Children)\n                        {\n                            if (currentChild.IsActive)\n                            {\n                                currentChild.Stop();\n                            }\n                        }\n                    }\n                }\n            }\n        }\n\n        public override void StopLowerPriorityChildrenForChild(Node abortForChild, bool immediateRestart)\n        {\n            if (immediateRestart)\n            {\n                Assert.False(abortForChild.IsActive);\n                if (_childrenResults[abortForChild])\n                {\n                    _succeededCount--;\n                }\n                else\n                {\n                    _failedCount--;\n                }\n                _runningCount++;\n                abortForChild.Start();\n            }\n            else\n            {\n                throw new Exception(\"On Parallel Nodes all children have the same priority, thus the method does nothing if you pass false to 'immediateRestart'!\");\n            }\n        }\n    }\n}\n"
        },
        {
            "Ident": "utopia.npbehavesbox",
            "Path": "BehaviorTree/Composite/RandomSequence.cs",
            "FileName": "RandomSequence.cs",
            "PackageType": "library",
            "CodeKind": "Game",
            "AssetVersionId": 72229,
            "Code": "using System.Collections;\nusing Sandbox.Diagnostics;\n\nnamespace NPBehave\n{\n    public class RandomSequence : Composite\n    {\n        static System.Random _rng = new System.Random();\n\n\n#if DEBUG\n        static public void DebugSetSeed( int seed )\n        {\n            _rng = new System.Random( seed );\n        }\n#endif\n\n        private int _currentIndex = -1;\n        private int[] _randomizedOrder;\n\n        public RandomSequence(params Node[] children) : base(\"Random Sequence\", children)\n        {\n            _randomizedOrder = new int[children.Length];\n            for (int i = 0; i < Children.Length; i++)\n            {\n                _randomizedOrder[i] = i;\n            }\n        }\n\n        protected override void DoStart()\n        {\n            foreach (Node child in Children)\n            {\n                Assert.AreEqual(child.CurrentState, State.Inactive);\n            }\n\n            _currentIndex = -1;\n\n            // Shuffling\n            int n = _randomizedOrder.Length;\n            while (n > 1)\n            {\n                int k = _rng.Next(n--);\n                (_randomizedOrder[n], _randomizedOrder[k]) = (_randomizedOrder[k], _randomizedOrder[n]);\n            }\n\n            ProcessChildren();\n        }\n\n        protected override void DoStop()\n        {\n            Children[_randomizedOrder[_currentIndex]].Stop();\n        }\n\n\n        protected override void DoChildStopped(Node child, bool result)\n        {\n            if (result)\n            {\n                ProcessChildren();\n            }\n            else\n            {\n                Stopped(false);\n            }\n        }\n\n        private void ProcessChildren()\n        {\n            if (++_currentIndex < Children.Length)\n            {\n                if (IsStopRequested)\n                {\n                    Stopped(false);\n                }\n                else\n                {\n                    Children[_randomizedOrder[_currentIndex]].Start();\n                }\n            }\n            else\n            {\n                Stopped(true);\n            }\n        }\n\n        public override void StopLowerPriorityChildrenForChild(Node abortForChild, bool immediateRestart)\n        {\n            int indexForChild = 0;\n            bool found = false;\n            foreach (Node currentChild in Children)\n            {\n                if (currentChild == abortForChild)\n                {\n                    found = true;\n                }\n                else if (!found)\n                {\n                    indexForChild++;\n                }\n                else if (found && currentChild.IsActive)\n                {\n                    if (immediateRestart)\n                    {\n                        _currentIndex = indexForChild - 1;\n                    }\n                    else\n                    {\n                        _currentIndex = Children.Length;\n                    }\n                    currentChild.Stop();\n                    break;\n                }\n            }\n        }\n\n        public override string ToString()\n        {\n            return $\"{base.ToString()}[{_currentIndex}]\";\n        }\n    }\n}\n"
        },
        {
            "Ident": "utopia.npbehavesbox",
            "Path": "BehaviorTree/Decorator/Succeeder.cs",
            "FileName": "Succeeder.cs",
            "PackageType": "library",
            "CodeKind": "Game",
            "AssetVersionId": 72229,
            "Code": "namespace NPBehave\n{\n    public class Succeeder : Decorator\n    {\n        public Succeeder(Node decoratee) : base(\"Succeeder\", decoratee)\n        {\n        }\n\n        protected override void DoStart()\n        {\n            Decoratee.Start();\n        }\n\n        protected override void DoStop()\n        {\n            Decoratee.Stop();\n        }\n\n        protected override void DoChildStopped(Node child, bool result)\n        {\n            Stopped(true);\n        }\n    }\n}"
        },
        {
            "Ident": "utopia.npbehavesbox",
            "Path": "Code/BehaviorTree/Exception.cs",
            "FileName": "Exception.cs",
            "PackageType": "library",
            "CodeKind": "Game",
            "AssetVersionId": 72229,
            "Code": "using System;\n\nnamespace NPBehave\n{\n    public class Exception : System.Exception\n    {\n        public Exception(string message) : base(message)\n        {\n        }\n    }\n}"
        },
        {
            "Ident": "utopia.npbehavesbox",
            "Path": "Code/BehaviorTree/Decorator/Repeater.cs",
            "FileName": "Repeater.cs",
            "PackageType": "library",
            "CodeKind": "Game",
            "AssetVersionId": 72229,
            "Code": "namespace NPBehave\n{\n    public class Repeater : Decorator\n    {\n        private int _loopCount = -1;\n        private int _currentLoop;\n\n        /// <param name=\"loopCount\">number of times to execute the decoratee. Set to -1 to repeat forever, be careful with endless loops!</param>\n        /// <param name=\"decoratee\">Decorated Node</param>\n        public Repeater(int loopCount, Node decoratee) : base(\"Repeater\", decoratee)\n        {\n            _loopCount = loopCount;\n        }\n\n        /// <param name=\"decoratee\">Decorated Node, repeated forever</param>\n        public Repeater(Node decoratee) : base(\"Repeater\", decoratee)\n        {\n        }\n\n        protected override void DoStart()\n        {\n            if (_loopCount != 0)\n            {\n                _currentLoop = 0;\n                Decoratee.Start();\n            }\n            else\n            {\n                Stopped(true);\n            }\n        }\n\n        protected override void DoStop()\n        {\n            Clock.RemoveTimer(RestartDecoratee);\n            \n            if (Decoratee.IsActive)\n            {\n                Decoratee.Stop();\n            }\n            else\n            {\n                Stopped(false);\n            }\n        }\n\n        protected override void DoChildStopped(Node child, bool result)\n        {\n            if (result)\n            {\n                if (IsStopRequested || (_loopCount > 0 && ++_currentLoop >= _loopCount))\n                {\n                    Stopped(true);\n                }\n                else\n                {\n                    Clock.AddTimer(0, 0, RestartDecoratee);\n                }\n            }\n            else\n            {\n                Stopped(false);\n            }\n        }\n\n        protected void RestartDecoratee()\n        {\n            Decoratee.Start();\n        }\n    }\n}"
        },
        {
            "Ident": "utopia.npbehavesbox",
            "Path": "BehaviorTree/Composite/Selector.cs",
            "FileName": "Selector.cs",
            "PackageType": "library",
            "CodeKind": "Game",
            "AssetVersionId": 72229,
            "Code": "using System.Collections;\nusing Sandbox.Diagnostics;\n\nnamespace NPBehave\n{\n    public class Selector : Composite\n    {\n        private int _currentIndex = -1;\n\n        public Selector(params Node[] children) : base(\"Selector\", children)\n        {\n        }\n\n\t\t#if DEBUG\n\t    public override string DebugIcon => \"rule\";\n\t\t#endif\n        protected override void DoStart()\n        {\n            foreach (Node child in Children)\n            {\n                Assert.AreEqual(child.CurrentState, State.Inactive);\n            }\n\n            _currentIndex = -1;\n\n            ProcessChildren();\n        }\n\n        protected override void DoStop()\n        {\n            Children[_currentIndex].Stop();\n        }\n\n        protected override void DoChildStopped(Node child, bool result)\n        {\n            if (result)\n            {\n                Stopped(true);\n            }\n            else\n            {\n                ProcessChildren();\n            }\n        }\n\n        private void ProcessChildren()\n        {\n            if (++_currentIndex < Children.Length)\n            {\n                if (IsStopRequested)\n                {\n                    Stopped(false);\n                }\n                else\n                {\n                    Children[_currentIndex].Start();\n                }\n            }\n            else\n            {\n                Stopped(false);\n            }\n        }\n\n        public override void StopLowerPriorityChildrenForChild(Node abortForChild, bool immediateRestart)\n        {\n            int indexForChild = 0;\n            bool found = false;\n            foreach (Node currentChild in Children)\n            {\n                if (currentChild == abortForChild)\n                {\n                    found = true;\n                }\n                else if (!found)\n                {\n                    indexForChild++;\n                }\n                else if (found && currentChild.IsActive)\n                {\n                    if (immediateRestart)\n                    {\n                        _currentIndex = indexForChild - 1;\n                    }\n                    else\n                    {\n                        _currentIndex = Children.Length;\n                    }\n                    currentChild.Stop();\n                    break;\n                }\n            }\n        }\n\n        public override string ToString()\n        {\n            return $\"{base.ToString()}[{_currentIndex}]\";\n        }\n    }\n}\n"
        },
        {
            "Ident": "utopia.npbehavesbox",
            "Path": "BehaviorTree/Decorator/BlackboardCondition.cs",
            "FileName": "BlackboardCondition.cs",
            "PackageType": "library",
            "CodeKind": "Game",
            "AssetVersionId": 72229,
            "Code": "namespace NPBehave\n{\n    public class BlackboardCondition : ObservingDecorator\n    {\n        private string _key;\n        private object _value;\n        private Operator _op;\n\n        public string Key\n        {\n            get\n            {\n                return _key;\n            }\n        }\n\n        public object Value\n        {\n            get\n            {\n                return _value;\n            }\n        }\n\n        public Operator Operator\n        {\n            get\n            {\n                return _op;\n            }\n        }\n        \n        #if DEBUG\n\t    public override string DebugIcon => \"quiz\";\n\t    public override string ComputedLabel\n\t    {\n\t\t    get\n\t\t    {\n\t\t\t    return $\"{Key} {OperatorToString(Operator)} {Value}\";\n\t\t    }\n\t    }\n\n\t    public string OperatorToString( Operator _op )\n\t    {\n\t\t    return _op switch\n\t\t    {\n\t\t\t    Operator.IsSet => \"?=\",\n\t\t\t    Operator.IsNotSet => \"?!=\",\n\t\t\t    Operator.IsEqual => \"==\",\n\t\t\t    Operator.IsNotEqual => \"!=\",\n\t\t\t    Operator.IsGreaterOrEqual => \">=\",\n\t\t\t    Operator.IsGreater => \">\",\n\t\t\t    Operator.IsSmallerOrEqual => \"<=\",\n\t\t\t    Operator.IsSmaller => \"<\",\n\t\t\t    Operator.AlwaysTrue => \"ALWAYS_TRUE\",\n\t\t\t    _ => $\"<{_op}>\"\n\t\t    };\n\t    }\n\n\n#endif\n\n        public BlackboardCondition(string key, Operator op, object value, Stops stopsOnChange, Node decoratee) : base(\"BlackboardCondition\", stopsOnChange, decoratee)\n        {\n            _op = op;\n            _key = key;\n            _value = value;\n            StopsOnChange = stopsOnChange;\n        }\n        \n        public BlackboardCondition(string key, Operator op, Stops stopsOnChange, Node decoratee) : base(\"BlackboardCondition\", stopsOnChange, decoratee)\n        {\n            _op = op;\n            _key = key;\n            StopsOnChange = stopsOnChange;\n        }\n\n\n        protected override void StartObserving()\n        {\n            RootNode.Blackboard.AddObserver(_key, OnValueChanged);\n        }\n\n        protected override void StopObserving()\n        {\n            RootNode.Blackboard.RemoveObserver(_key, OnValueChanged);\n        }\n\n        private void OnValueChanged(Blackboard.Type type, object newValue)\n        {\n            Evaluate();\n        }\n\n        protected override bool IsConditionMet()\n        {\n            if (_op == Operator.AlwaysTrue)\n            {\n                return true;\n            }\n\n            if (!RootNode.Blackboard.IsSet(_key))\n            {\n                return _op == Operator.IsNotSet;\n            }\n\n            object o = RootNode.Blackboard.Get(_key);\n\n            switch (_op)\n            {\n                case Operator.IsSet: return true;\n                case Operator.IsEqual: return Equals(o, _value);\n                case Operator.IsNotEqual: return !Equals(o, _value);\n\n                case Operator.IsGreaterOrEqual:\n                    if (o is float)\n                    {\n                        return (float)o >= (float)_value;\n                    }\n                    else if (o is int)\n                    {\n                        return (int)o >= (int)_value;\n                    }\n                    else\n                    {\n                        Log.Error( $\"Type not compareable: {o.GetType()}\" );\n                        return false;\n                    }\n\n                case Operator.IsGreater:\n                    if (o is float)\n                    {\n                        return (float)o > (float)_value;\n                    }\n                    else if (o is int)\n                    {\n                        return (int)o > (int)_value;\n                    }\n                    else\n                    {\n\t                    Log.Error( $\"Type not compareable: {o.GetType()}\" );\n                        return false;\n                    }\n\n                case Operator.IsSmallerOrEqual:\n                    if (o is float)\n                    {\n                        return (float)o <= (float)_value;\n                    }\n                    else if (o is int)\n                    {\n                        return (int)o <= (int)_value;\n                    }\n                    else\n                    {\n\t                    Log.Error( $\"Type not compareable: {o.GetType()}\" );\n                        return false;\n                    }\n\n                case Operator.IsSmaller:\n                    if (o is float)\n                    {\n                        return (float)o < (float)_value;\n                    }\n                    else if (o is int)\n                    {\n                        return (int)o < (int)_value;\n                    }\n                    else\n                    {\n\t                    Log.Error( $\"Type not compareable: {o.GetType()}\" );\n                        return false;\n                    }\n\n                default: return false;\n            }\n        }\n\n        public override string ToString()\n        {\n            return $\"({_op}) {_key} ? {_value}\";\n        }\n    }\n}\n"
        },
        {
            "Ident": "utopia.npbehavesbox",
            "Path": "BehaviorTree/Decorator/Condition.cs",
            "FileName": "Condition.cs",
            "PackageType": "library",
            "CodeKind": "Game",
            "AssetVersionId": 72229,
            "Code": "using System;\n\nnamespace NPBehave\n{\n    public class Condition : ObservingDecorator\n    {\n        private Func<bool> _condition;\n        private float _checkInterval;\n        private float _checkVariance;\n\n        public Condition(Func<bool> condition, Node decoratee) : base(\"Condition\", Stops.None, decoratee)\n        {\n            _condition = condition;\n            _checkInterval = 0.0f;\n            _checkVariance = 0.0f;\n        }\n\n        public Condition(Func<bool> condition, Stops stopsOnChange, Node decoratee) : base(\"Condition\", stopsOnChange, decoratee)\n        {\n            _condition = condition;\n            _checkInterval = 0.0f;\n            _checkVariance = 0.0f;\n        }\n\n        public Condition(Func<bool> condition, Stops stopsOnChange, float checkInterval, float randomVariance, Node decoratee) : base(\"Condition\", stopsOnChange, decoratee)\n        {\n            _condition = condition;\n            _checkInterval = checkInterval;\n            _checkVariance = randomVariance;\n        }\n\n        protected override void StartObserving()\n        {\n            RootNode.Clock.AddTimer(_checkInterval, _checkVariance, -1, Evaluate);\n        }\n\n        protected override void StopObserving()\n        {\n            RootNode.Clock.RemoveTimer(Evaluate);\n        }\n\n        protected override bool IsConditionMet()\n        {\n            return _condition();\n        }\n    }\n}"
        },
        {
            "Ident": "utopia.npbehavesbox",
            "Path": "BehaviorTree/Decorator/Decorator.cs",
            "FileName": "Decorator.cs",
            "PackageType": "library",
            "CodeKind": "Game",
            "AssetVersionId": 72229,
            "Code": "namespace NPBehave\n{\n\n    public abstract class Decorator : Container\n    {\n        protected Node Decoratee;\n\n        public Decorator(string name, Node decoratee) : base(name)\n        {\n            Decoratee = decoratee;\n            Decoratee.SetParent(this);\n        }\n\n        public override void SetRoot(Root rootNode)\n        {\n            base.SetRoot(rootNode);\n            Decoratee.SetRoot(rootNode);\n        }\n\n\n#if DEBUG\n\n\t    public override string DebugIcon => \"brush\";\n\t    public override Node[] DebugChildren\n        {\n            get\n            {\n                return new Node[] { Decoratee };\n            }\n        }\n#endif\n\n        public override void ParentCompositeStopped(Composite composite)\n        {\n            base.ParentCompositeStopped(composite);\n            Decoratee.ParentCompositeStopped(composite);\n        }\n    }\n}\n"
        },
        {
            "Ident": "utopia.npbehavesbox",
            "Path": "BehaviorTree/Decorator/ObservingDecorator.cs",
            "FileName": "ObservingDecorator.cs",
            "PackageType": "library",
            "CodeKind": "Game",
            "AssetVersionId": 72229,
            "Code": "using System.Collections;\nusing Sandbox.Diagnostics;\n\nnamespace NPBehave\n{\n    public abstract class ObservingDecorator : Decorator\n    {\n        protected Stops StopsOnChange;\n        private bool _isObserving;\n\n        public ObservingDecorator(string name, Stops stopsOnChange, Node decoratee) : base(name, decoratee)\n        {\n            StopsOnChange = stopsOnChange;\n            _isObserving = false;\n        }\n\n        protected override void DoStart()\n        {\n            if (StopsOnChange != Stops.None)\n            {\n                if (!_isObserving)\n                {\n                    _isObserving = true;\n                    StartObserving();\n                }\n            }\n\n            if (!IsConditionMet())\n            {\n                Stopped(false);\n            }\n            else\n            {\n                Decoratee.Start();\n            }\n        }\n\n        protected override void DoStop()\n        {\n            Decoratee.Stop();\n        }\n\n        protected override void DoChildStopped(Node child, bool result)\n        {\n            Assert.AreNotEqual(((Node)this).CurrentState, State.Inactive);\n            if (StopsOnChange is Stops.None or Stops.Self)\n            {\n                if (_isObserving)\n                {\n                    _isObserving = false;\n                    StopObserving();\n                }\n            }\n            Stopped(result);\n        }\n\n        protected override void DoParentCompositeStopped(Composite parentComposite)\n        {\n            if (_isObserving)\n            {\n                _isObserving = false;\n                StopObserving();\n            }\n        }\n\n        protected void Evaluate()\n        {\n            if (IsActive && !IsConditionMet())\n            {\n                if (StopsOnChange is Stops.Self or Stops.Both or Stops.ImmediateRestart)\n                {\n                    // Debug.Log( this.key + \" stopped self \");\n                    Stop();\n                }\n            }\n            else if (!IsActive && IsConditionMet())\n            {\n                if (StopsOnChange == Stops.LowerPriority || StopsOnChange == Stops.Both || StopsOnChange == Stops.ImmediateRestart || StopsOnChange == Stops.LowerPriorityImmediateRestart)\n                {\n                    // Debug.Log( this.key + \" stopped other \");\n                    Container parentNode = ParentNode;\n                    Node childNode = this;\n                    while (parentNode != null && !(parentNode is Composite))\n                    {\n                        childNode = parentNode;\n                        parentNode = parentNode.ParentNode;\n                    }\n                    Assert.NotNull(parentNode, \"NTBtrStops is only valid when attached to a parent composite\");\n                    Assert.NotNull(childNode);\n                    if (parentNode is Parallel)\n                    {\n                        Assert.True(StopsOnChange == Stops.ImmediateRestart, \"On Parallel Nodes all children have the same priority, thus Stops.LOWER_PRIORITY or Stops.BOTH are unsupported in this context!\");\n                    }\n\n                    if (StopsOnChange == Stops.ImmediateRestart || StopsOnChange == Stops.LowerPriorityImmediateRestart)\n                    {\n                        if (_isObserving)\n                        {\n                            _isObserving = false;\n                            StopObserving();\n                        }\n                    }\n\n                    ((Composite)parentNode)?.StopLowerPriorityChildrenForChild(childNode, StopsOnChange is Stops.ImmediateRestart or Stops.LowerPriorityImmediateRestart);\n                }\n            }\n        }\n\n        protected abstract void StartObserving();\n\n        protected abstract void StopObserving();\n\n        protected abstract bool IsConditionMet();\n\n    }\n}\n"
        },
        {
            "Ident": "utopia.npbehavesbox",
            "Path": "BehaviorTree/Decorator/TimeMin.cs",
            "FileName": "TimeMin.cs",
            "PackageType": "library",
            "CodeKind": "Game",
            "AssetVersionId": 72229,
            "Code": "using Sandbox.Diagnostics;\n\nnamespace NPBehave\n{\n    public class TimeMin : Decorator\n    {\n        private float _limit = 0.0f;\n        private float _randomVariation;\n        private bool _waitOnFailure = false;\n        private bool _isLimitReached = false;\n        private bool _isDecorateeDone = false;\n        private bool _isDecorateeSuccess = false;\n\n        public TimeMin(float limit, Node decoratee) : base(\"TimeMin\", decoratee)\n        {\n            _limit = limit;\n            _randomVariation = _limit * 0.05f;\n            _waitOnFailure = false;\n            Assert.True(limit > 0f, \"limit has to be set\");\n        }\n\n        public TimeMin(float limit, bool waitOnFailure, Node decoratee) : base(\"TimeMin\", decoratee)\n        {\n            _limit = limit;\n            _randomVariation = _limit * 0.05f;\n            _waitOnFailure = waitOnFailure;\n            Assert.True(limit > 0f, \"limit has to be set\");\n        }\n\n        public TimeMin(float limit, float randomVariation, bool waitOnFailure, Node decoratee) : base(\"TimeMin\", decoratee)\n        {\n            _limit = limit;\n            _randomVariation = randomVariation;\n            _waitOnFailure = waitOnFailure;\n            Assert.True(limit > 0f, \"limit has to be set\");\n        }\n\n        protected override void DoStart()\n        {\n            _isDecorateeDone = false;\n            _isDecorateeSuccess = false;\n            _isLimitReached = false;\n            Clock.AddTimer(_limit, _randomVariation, 0, TimeoutReached);\n            Decoratee.Start();\n        }\n\n        protected override void DoStop()\n        {\n            if (Decoratee.IsActive)\n            {\n                Clock.RemoveTimer(TimeoutReached);\n                _isLimitReached = true;\n                Decoratee.Stop();\n            }\n            else\n            {\n                Clock.RemoveTimer(TimeoutReached);\n                Stopped(false);\n            }\n        }\n\n        protected override void DoChildStopped(Node child, bool result)\n        {\n            _isDecorateeDone = true;\n            _isDecorateeSuccess = result;\n            if (_isLimitReached || (!result && !_waitOnFailure))\n            {\n                Clock.RemoveTimer(TimeoutReached);\n                Stopped(_isDecorateeSuccess);\n            }\n            else\n            {\n                Assert.True(Clock.HasTimer(TimeoutReached));\n            }\n        }\n\n        private void TimeoutReached()\n        {\n            _isLimitReached = true;\n            if (_isDecorateeDone)\n            {\n                Stopped(_isDecorateeSuccess);\n            }\n            else\n            {\n                Assert.True(Decoratee.IsActive);\n            }\n        }\n    }\n}\n"
        },
        {
            "Ident": "utopia.npbehavesbox",
            "Path": "UnitTests/LibraryTest.cs",
            "FileName": "LibraryTest.cs",
            "PackageType": "library",
            "CodeKind": "UnitTest",
            "AssetVersionId": 72229,
            "Code": "using Sandbox;\r\n\r\n[TestClass]\r\npublic partial class LibraryTests\r\n{\r\n\t[TestMethod]\r\n\tpublic void SceneTest()\r\n\t{\r\n\t\tvar scene = new Scene();\r\n\t\tusing ( scene.Push() )\r\n\t\t{\r\n\t\t\tvar go = new GameObject();\r\n\r\n\t\t\tAssert.AreEqual( 1, scene.Directory.GameObjectCount );\r\n\t\t}\r\n\t}\r\n\r\n}\r\n"
        },
        {
            "Ident": "utopia.npbehavesbox",
            "Path": "BehaviorTree/Composite/RandomSelector.cs",
            "FileName": "RandomSelector.cs",
            "PackageType": "library",
            "CodeKind": "Game",
            "AssetVersionId": 72229,
            "Code": "using System.Collections;\nusing Sandbox.Diagnostics;\n\n\nnamespace NPBehave\n{\n    public class RandomSelector : Composite\n    {\n        static System.Random _rng = new System.Random();\n\n#if DEBUG\n        static public void DebugSetSeed( int seed )\n        {\n            _rng = new System.Random( seed );\n        }\n#endif\n\n        private int _currentIndex = -1;\n        private int[] _randomizedOrder;\n\n        public RandomSelector(params Node[] children) : base(\"Random Selector\", children)\n        {\n            _randomizedOrder = new int[children.Length];\n            for (int i = 0; i < Children.Length; i++)\n            {\n                _randomizedOrder[i] = i;\n            }\n        }\n\n\n        protected override void DoStart()\n        {\n            foreach (Node child in Children)\n            {\n                Assert.AreEqual(child.CurrentState, State.Inactive);\n            }\n\n            _currentIndex = -1;\n\n            // Shuffling\n            int n = _randomizedOrder.Length;\n            while (n > 1)\n            {\n                int k = _rng.Next(n--);\n                (_randomizedOrder[n], _randomizedOrder[k]) = (_randomizedOrder[k], _randomizedOrder[n]);\n            }\n\n            ProcessChildren();\n        }\n\n\n\n        protected override void DoStop()\n        {\n            Children[_randomizedOrder[_currentIndex]].Stop();\n        }\n\n        protected override void DoChildStopped(Node child, bool result)\n        {\n            if (result)\n            {\n                Stopped(true);\n            }\n            else\n            {\n                ProcessChildren();\n            }\n        }\n\n        private void ProcessChildren()\n        {\n            if (++_currentIndex < Children.Length)\n            {\n                if (IsStopRequested)\n                {\n                    Stopped(false);\n                }\n                else\n                {\n                    Children[_randomizedOrder[_currentIndex]].Start();\n                }\n            }\n            else\n            {\n                Stopped(false);\n            }\n        }\n\n        public override void StopLowerPriorityChildrenForChild(Node abortForChild, bool immediateRestart)\n        {\n            int indexForChild = 0;\n            bool found = false;\n            foreach (Node currentChild in Children)\n            {\n                if (currentChild == abortForChild)\n                {\n                    found = true;\n                }\n                else if (!found)\n                {\n                    indexForChild++;\n                }\n                else if (found && currentChild.IsActive)\n                {\n                    if (immediateRestart)\n                    {\n                        _currentIndex = indexForChild - 1;\n                    }\n                    else\n                    {\n                        _currentIndex = Children.Length;\n                    }\n                    currentChild.Stop();\n                    break;\n                }\n            }\n        }\n\n        public override string ToString()\n        {\n            return $\"{base.ToString()}[{_currentIndex}]\";\n        }\n    }\n}\n"
        },
        {
            "Ident": "utopia.npbehavesbox",
            "Path": "BehaviorTree/Debugger.cs",
            "FileName": "Debugger.cs",
            "PackageType": "library",
            "CodeKind": "Game",
            "AssetVersionId": 72229,
            "Code": "using System.Collections.Generic;\nusing Sandbox;\n\nnamespace NPBehave\n{\n    public class Debugger : Component\n    {\n        public Root BehaviorTree;\n\n        private static Blackboard _customGlobalStats = null;\n        public static Blackboard CustomGlobalStats\n        {\n            get \n            {\n                if (_customGlobalStats == null)\n                {\n                    _customGlobalStats = SandboxContext.GetSharedBlackboard(\"_GlobalStats\");;\n                }\n                return _customGlobalStats;\n            }\n        }\n\n        private Blackboard _customStats = null;\n        public Blackboard CustomStats\n        {\n            get \n            {\n                if (_customStats == null)\n                {\n                    _customStats = new Blackboard(CustomGlobalStats, SandboxContext.GetClock());\n                }\n                return _customStats;\n            }\n        }\n\n        public void DebugCounterInc(string key)\n        {\n            if (!CustomStats.IsSet(key))\n            {\n                CustomStats[key] = 0;\n            }\n            CustomStats[key] = CustomStats.Get<int>(key) + 1;\n        }\n\n        public void DebugCounterDec(string key)\n        {\n            if (!CustomStats.IsSet(key))\n            {\n                CustomStats[key] = 0;\n            }\n            CustomStats[key] = CustomStats.Get<int>(key) - 1;\n        }\n\n        public static void GlobalDebugCounterInc(string key)\n        {\n            if (!CustomGlobalStats.IsSet(key))\n            {\n                CustomGlobalStats[key] = 0;\n            }\n            CustomGlobalStats[key] = CustomGlobalStats.Get<int>(key) + 1;\n        }\n\n        public static void GlobalDebugCounterDec(string key)\n        {\n            if (!CustomGlobalStats.IsSet(key))\n            {\n                CustomGlobalStats[key] = 0;\n            }\n            CustomGlobalStats[key] = CustomGlobalStats.Get<int>(key) - 1;\n        }\n\n    }\n}\n"
        },
        {
            "Ident": "utopia.npbehavesbox",
            "Path": "BehaviorTree/Decorator/Inverter.cs",
            "FileName": "Inverter.cs",
            "PackageType": "library",
            "CodeKind": "Game",
            "AssetVersionId": 72229,
            "Code": "namespace NPBehave\n{\n    public class Inverter : Decorator\n    {\n        public Inverter(Node decoratee) : base(\"Inverter\", decoratee)\n        {\n        }\n\n        protected override void DoStart()\n        {\n            Decoratee.Start();\n        }\n\n        protected override void DoStop()\n        {\n            Decoratee.Stop();\n        }\n\n        protected override void DoChildStopped(Node child, bool result)\n        {\n            Stopped(!result);\n        }\n    }\n}"
        },
        {
            "Ident": "utopia.npbehavesbox",
            "Path": "BehaviorTree/Stops.cs",
            "FileName": "Stops.cs",
            "PackageType": "library",
            "CodeKind": "Game",
            "AssetVersionId": 72229,
            "Code": "namespace NPBehave\n{\n    public enum Stops\n    {\n\t    /// <summary>\n\t    /// The decorator will only check it's condition once it is started and will never stop any running nodes.\n\t    /// </summary>\n        None,\n\t    /// <summary>\n\t    /// The decorator will check it's condition once it is started and if it is met,\n\t    /// it will observe the blackboard for changes.\n\t    /// Once the condition is no longer met, it will stop itself allowing the parent composite to proceed with it's next node.\n\t    /// </summary>\n        Self,\n\t    \n\t    /// <summary>\n\t    /// The decorator will check it's condition once it is started and if it's not met, it will observe the blackboard for changes.\n\t    /// Once the condition is met, it will stop the lower priority node allowing the parent composite to proceed with it's next node\n\t    /// </summary>\n        LowerPriority,\n\t    \n\t    /// <summary>\n\t    /// The decorator will stop both: self and lower priority nodes.\n\t    /// </summary>\n        Both,\n\t    \n\t    /// <summary>\n\t    /// The decorator will check it's condition once it is started and if it's not met, it will observe the blackboard for changes.\n\t    /// Once the condition is met, it will stop the lower priority node and order the parent composite to restart the Decorator immediately.\n\t    /// </summary>\n        ImmediateRestart,\n\t    \n\t    /// <summary>\n\t    /// The decorator will check it's condition once it is started and if it's not met, it will observe the blackboard for changes.\n\t    /// Once the condition is met, it will stop the lower priority node and order the parent composite to restart the Decorator immediately.\n\t    /// As in BOTH it will also stop itself as soon as the condition is no longer met.\n\t    /// </summary>\n        LowerPriorityImmediateRestart\n    }\n}\n"
        },
        {
            "Ident": "utopia.npbehavesbox",
            "Path": "BehaviorTree/Task/Action.cs",
            "FileName": "Action.cs",
            "PackageType": "library",
            "CodeKind": "Game",
            "AssetVersionId": 72229,
            "Code": "using Sandbox.Diagnostics;\n\nnamespace NPBehave\n{\n    public class Action : Task\n    {\n        public enum Result\n        {\n            Success,\n            Failed,\n            Blocked,\n            Progress\n        }\n\n        public enum Request\n        {\n            Start,\n            Update,\n            Cancel,\n        }\n\n        private System.Func<bool> _singleFrameFunc = null;\n        private System.Func<bool, Result> _multiFrameFunc = null;\n        private System.Func<Request, Result> _multiFrameFunc2 = null;\n        private System.Action _action = null;\n        private bool _bWasBlocked = false;\n\n        public Action(System.Action action) : base(\"Action\")\n        {\n            _action = action;\n        }\n\n        public Action(System.Func<bool, Result> multiframeFunc) : base(\"Action\")\n        {\n            _multiFrameFunc = multiframeFunc;\n        }\n\n        public Action(System.Func<Request, Result> multiframeFunc2) : base(\"Action\")\n        {\n            _multiFrameFunc2 = multiframeFunc2;\n        }\n\n\n        public Action(System.Func<bool> singleFrameFunc) : base(\"Action\")\n        {\n            _singleFrameFunc = singleFrameFunc;\n        }\n\n        protected override void DoStart()\n        {\n            if (_action != null)\n            {\n                _action.Invoke();\n                Stopped(true);\n            }\n            else if (_multiFrameFunc != null)\n            {\n                Result result = _multiFrameFunc.Invoke(false);\n                if ( result == Result.Progress )\n                {\n                    RootNode.Clock.AddUpdateObserver( OnUpdateFunc );\n                }\n                else if ( result == Result.Blocked )\n                {\n                    _bWasBlocked = true;\n                    RootNode.Clock.AddUpdateObserver( OnUpdateFunc );\n                }\n                else\n                {\n                    Stopped(result == Result.Success);\n                }\n            }\n            else if (_multiFrameFunc2 != null)\n            {\n                Result result = _multiFrameFunc2.Invoke(Request.Start);\n                if (result == Result.Progress)\n                {\n                    RootNode.Clock.AddUpdateObserver(OnUpdateFunc2);\n                }\n                else if ( result == Result.Blocked )\n                {\n                    _bWasBlocked = true;\n                    RootNode.Clock.AddUpdateObserver( OnUpdateFunc2 );\n                }\n                else\n                {\n                    Stopped(result == Result.Success);\n                }\n            }\n            else if (_singleFrameFunc != null)\n            {\n                Stopped(_singleFrameFunc.Invoke());\n            }\n        }\n\n        private void OnUpdateFunc()\n        {\n            Result result = _multiFrameFunc.Invoke(false);\n            if (result != Result.Progress && result != Result.Blocked)\n            {\n                RootNode.Clock.RemoveUpdateObserver(OnUpdateFunc);\n                Stopped(result == Result.Success);\n            }\n        }\n\n        private void OnUpdateFunc2()\n        {\n            Result result = _multiFrameFunc2.Invoke( _bWasBlocked ? Request.Start : Request.Update);\n\n            if ( result == Result.Blocked )\n            {\n                _bWasBlocked = true;\n            }\n            else if ( result == Result.Progress )\n            {\n                _bWasBlocked = false;\n            }\n            else\n            {\n                RootNode.Clock.RemoveUpdateObserver( OnUpdateFunc2 );\n                Stopped( result == Result.Success );\n            }\n        }\n\n        protected override void DoStop()\n        {\n            if (_multiFrameFunc != null)\n            {\n                Result result = _multiFrameFunc.Invoke(true);\n                Assert.AreNotEqual(result, Result.Progress, \"The Task has to return Result.SUCCESS, Result.FAILED/BLOCKED after beeing cancelled!\");\n                RootNode.Clock.RemoveUpdateObserver(OnUpdateFunc);\n                Stopped(result == Result.Success);\n            }\n            else if (_multiFrameFunc2 != null)\n            {\n                Result result = _multiFrameFunc2.Invoke(Request.Cancel);\n                Assert.AreNotEqual(result, Result.Progress, \"The Task has to return Result.SUCCESS or Result.FAILED/BLOCKED after beeing cancelled!\");\n                RootNode.Clock.RemoveUpdateObserver(OnUpdateFunc2);\n                Stopped(result == Result.Success);\n            }\n            else\n            {\n                Assert.True(false, $\"DoStop called for a single frame action on {this}\" );\n            }\n        }\n    }\n}\n"
        },
        {
            "Ident": "utopia.npbehavesbox",
            "Path": "Samples/NPBehaveExampleHelloWorldAI.cs",
            "FileName": "NPBehaveExampleHelloWorldAI.cs",
            "PackageType": "library",
            "CodeKind": "Game",
            "AssetVersionId": 72229,
            "Code": "using NPBehave;\r\n\r\nnamespace Sandbox.Samples;\r\n\r\npublic class NPBehaveExampleHelloWorldAI : Component\r\n{\r\n\tprivate Root _behaviorTree;\r\n\r\n\tvoid Start()\r\n\t{\r\n\t\t_behaviorTree = new Root(\r\n\t\t\tnew Sequence(\r\n\t\t\t\tnew Action(() => Log.Info(\"Hello, World!\"))\r\n\t\t\t)\r\n\t\t);\r\n\t\t_behaviorTree.Start();\r\n\t}\r\n}\r\n"
        },
        {
            "Ident": "utopia.npbehavesbox",
            "Path": "Code/BehaviorTree/Blackboard.cs",
            "FileName": "Blackboard.cs",
            "PackageType": "library",
            "CodeKind": "Game",
            "AssetVersionId": 72229,
            "Code": "using System.Collections.Generic;\n\nnamespace NPBehave\n{\n    public class Blackboard\n    {\n        public enum Type\n        {\n            Add,\n            Remove,\n            Change\n        }\n        private struct Notification\n        {\n            public string Key;\n            public Type Type;\n            public object Value;\n            public Notification(string key, Type type, object value)\n            {\n                Key = key;\n                Type = type;\n                Value = value;\n            }\n        }\n\n        private Clock _clock;\n        private Dictionary<string, object> _data = new Dictionary<string, object>();\n        private Dictionary<string, List<System.Action<Type, object>>> _observers = new Dictionary<string, List<System.Action<Type, object>>>();\n        private bool _isNotifiyng = false;\n        private Dictionary<string, List<System.Action<Type, object>>> _addObservers = new Dictionary<string, List<System.Action<Type, object>>>();\n        private Dictionary<string, List<System.Action<Type, object>>> _removeObservers = new Dictionary<string, List<System.Action<Type, object>>>();\n        private List<Notification> _notifications = new List<Notification>();\n        private List<Notification> _notificationsDispatch = new List<Notification>();\n        private Blackboard _parentBlackboard;\n        private HashSet<Blackboard> _children = new HashSet<Blackboard>();\n\n        public Blackboard(Blackboard parent, Clock clock)\n        {\n            _clock = clock;\n            _parentBlackboard = parent;\n        }\n        public Blackboard(Clock clock)\n        {\n            _parentBlackboard = null;\n            _clock = clock;\n        }\n\n        public void Enable()\n        {\n\t        _parentBlackboard?._children.Add(this);\n        }\n\n        public void Disable()\n        {\n\t        _parentBlackboard?._children.Remove(this);\n            if (_clock != null)\n            {\n                _clock.RemoveTimer(NotifiyObservers);\n            }\n        }\n\n        public object this[string key]\n        {\n            get\n            {\n                return Get(key);\n            }\n            set\n            {\n                Set(key, value);\n            }\n        }\n\n        public void Set(string key)\n        {\n            if (!IsSet(key))\n            {\n                Set(key, null);\n            }\n        }\n\n        public void Set(string key, object value)\n        {\n            if (_parentBlackboard != null && _parentBlackboard.IsSet(key))\n            {\n                _parentBlackboard.Set(key, value);\n            }\n            else\n            {\n                if (_data.TryAdd(key, value))\n                {\n\t                _notifications.Add(new Notification(key, Type.Add, value));\n                    _clock.AddTimer(0f, 0, NotifiyObservers);\n                }\n                else\n                {\n                    if ((_data[key] == null && value != null) || (_data[key] != null && !_data[key].Equals(value)))\n                    {\n                        _data[key] = value;\n                        _notifications.Add(new Notification(key, Type.Change, value));\n                        _clock.AddTimer(0f, 0, NotifiyObservers);\n                    }\n                }\n            }\n        }\n\n        public void Unset(string key)\n        {\n            if (_data.ContainsKey(key))\n            {\n                _data.Remove(key);\n                _notifications.Add(new Notification(key, Type.Remove, null));\n                _clock.AddTimer(0f, 0, NotifiyObservers);\n            }\n        }\n\n        public T Get<T>(string key)\n        {\n            object result = Get(key);\n            if (result == null)\n            {\n                return default(T);\n            }\n            return (T)result;\n        }\n\n        public object Get(string key)\n        {\n\t        return _data.TryGetValue(key, out var value) ? value : _parentBlackboard?.Get(key);\n        }\n\n        public bool IsSet(string key)\n        {\n            return _data.ContainsKey(key) || (_parentBlackboard != null && _parentBlackboard.IsSet(key));\n        }\n\n        public void AddObserver(string key, System.Action<Type, object> observer)\n        {\n            List<System.Action<Type, object>> observers = GetObserverList(_observers, key);\n            if (!_isNotifiyng)\n            {\n                if (!observers.Contains(observer))\n                {\n                    observers.Add(observer);\n                }\n            }\n            else\n            {\n                if (!observers.Contains(observer))\n                {\n                    List<System.Action<Type, object>> addObservers = GetObserverList(_addObservers, key);\n                    if (!addObservers.Contains(observer))\n                    {\n                        addObservers.Add(observer);\n                    }\n                }\n\n                List<System.Action<Type, object>> removeObservers = GetObserverList(_removeObservers, key);\n                if (removeObservers.Contains(observer))\n                {\n                    removeObservers.Remove(observer);\n                }\n            }\n        }\n\n        public void RemoveObserver(string key, System.Action<Type, object> observer)\n        {\n            List<System.Action<Type, object>> observers = GetObserverList(_observers, key);\n            if (!_isNotifiyng)\n            {\n                if (observers.Contains(observer))\n                {\n                    observers.Remove(observer);\n                }\n            }\n            else\n            {\n                List<System.Action<Type, object>> removeObservers = GetObserverList(_removeObservers, key);\n                if (!removeObservers.Contains(observer))\n                {\n                    if (observers.Contains(observer))\n                    {\n                        removeObservers.Add(observer);\n                    }\n                }\n\n                List<System.Action<Type, object>> addObservers = GetObserverList(_addObservers, key);\n                if (addObservers.Contains(observer))\n                {\n                    addObservers.Remove(observer);\n                }\n            }\n        }\n\n\n#if DEBUG\n        public List<string> Keys\n        {\n            get\n            {\n                if (_parentBlackboard != null)\n                {\n                    List<string> keys = this._parentBlackboard.Keys;\n                    keys.AddRange(_data.Keys);\n                    return keys;\n                }\n                else\n                {\n                    return new List<string>(_data.Keys);\n                }\n            }\n        }\n\n        public int NumObservers\n        {\n            get\n            {\n                int count = 0;\n                foreach (var key in _observers.Keys)\n                {\n                    count += _observers[key].Count;\n                }\n                return count;\n            }\n        }\n#endif\n\n\n        private void NotifiyObservers()\n        {\n            if (_notifications.Count == 0)\n            {\n                return;\n            }\n\n            _notificationsDispatch.Clear();\n            _notificationsDispatch.AddRange(_notifications);\n            foreach (Blackboard child in _children)\n            {\n                child._notifications.AddRange(_notifications);\n                child._clock.AddTimer(0f, 0, child.NotifiyObservers);\n            }\n            _notifications.Clear();\n\n            _isNotifiyng = true;\n            foreach (Notification notification in _notificationsDispatch)\n            {\n                if (!_observers.ContainsKey(notification.Key))\n                {\n                    //                Debug.Log(\"1 do not notify for key:\" + notification.key + \" value: \" + notification.value);\n                    continue;\n                }\n\n                List<System.Action<Type, object>> observers = GetObserverList(_observers, notification.Key);\n                foreach (System.Action<Type, object> observer in observers)\n                {\n                    if (_removeObservers.TryGetValue( notification.Key, out List<System.Action<Type, object>> value ) && value.Contains(observer))\n                    {\n                        continue;\n                    }\n                    observer(notification.Type, notification.Value);\n                }\n            }\n\n            foreach (string key in _addObservers.Keys)\n            {\n                GetObserverList(_observers, key).AddRange(_addObservers[key]);\n            }\n            foreach (string key in _removeObservers.Keys)\n            {\n                foreach (System.Action<Type, object> action in _removeObservers[key])\n                {\n                    GetObserverList(_observers, key).Remove(action);\n                }\n            }\n            _addObservers.Clear();\n            _removeObservers.Clear();\n\n            _isNotifiyng = false;\n        }\n\n        private List<System.Action<Type, object>> GetObserverList(Dictionary<string, List<System.Action<Type, object>>> target, string key)\n        {\n            List<System.Action<Type, object>> observers;\n            if (target.TryGetValue(key, out var value))\n            {\n                observers = value;\n            }\n            else\n            {\n                observers = new List<System.Action<Type, object>>();\n                target[key] = observers;\n            }\n            return observers;\n        }\n    }\n}\n"
        },
        {
            "Ident": "utopia.npbehavesbox",
            "Path": "Code/BehaviorTree/Debugger.cs",
            "FileName": "Debugger.cs",
            "PackageType": "library",
            "CodeKind": "Game",
            "AssetVersionId": 72229,
            "Code": "using System.Collections.Generic;\nusing Sandbox;\n\nnamespace NPBehave\n{\n    public class Debugger : Component\n    {\n        public Root BehaviorTree;\n\n        private static Blackboard _customGlobalStats = null;\n        public static Blackboard CustomGlobalStats\n        {\n            get \n            {\n                if (_customGlobalStats == null)\n                {\n                    _customGlobalStats = SandboxContext.GetSharedBlackboard(\"_GlobalStats\");;\n                }\n                return _customGlobalStats;\n            }\n        }\n\n        private Blackboard _customStats = null;\n        public Blackboard CustomStats\n        {\n            get \n            {\n                if (_customStats == null)\n                {\n                    _customStats = new Blackboard(CustomGlobalStats, SandboxContext.GetClock());\n                }\n                return _customStats;\n            }\n        }\n\n        public void DebugCounterInc(string key)\n        {\n            if (!CustomStats.IsSet(key))\n            {\n                CustomStats[key] = 0;\n            }\n            CustomStats[key] = CustomStats.Get<int>(key) + 1;\n        }\n\n        public void DebugCounterDec(string key)\n        {\n            if (!CustomStats.IsSet(key))\n            {\n                CustomStats[key] = 0;\n            }\n            CustomStats[key] = CustomStats.Get<int>(key) - 1;\n        }\n\n        public static void GlobalDebugCounterInc(string key)\n        {\n            if (!CustomGlobalStats.IsSet(key))\n            {\n                CustomGlobalStats[key] = 0;\n            }\n            CustomGlobalStats[key] = CustomGlobalStats.Get<int>(key) + 1;\n        }\n\n        public static void GlobalDebugCounterDec(string key)\n        {\n            if (!CustomGlobalStats.IsSet(key))\n            {\n                CustomGlobalStats[key] = 0;\n            }\n            CustomGlobalStats[key] = CustomGlobalStats.Get<int>(key) - 1;\n        }\n\n    }\n}\n"
        }
    ]
}