# Behavior Trees

Behavior trees are a hierarchical model used to control the decision-making process of AI agents. They are composed of nodes that return a state of **Success**, **Failure**, or **Running**.

### Core Concepts

#### Nodes

Every node in a behavior tree is a subclass of `Node`. The tree is traversed from the root node down to leaf nodes.

* **Leaf Nodes**: Perform actions or checks (e.g., `ActionNode`, `ConditionNode`).
* **Composite Nodes**: Control the flow of execution by managing child nodes (e.g., `SequenceNode`, `SelectorNode`).
* **Decorator Nodes**: Modify the behavior of a single child node (e.g., `InverterNode`, `RepeatNode`).

#### Ticks

The tree is updated via a `tick(dt)` method, where `dt` is the delta time since the last update. This propagates down the tree, updating active nodes.

#### Node States

* `SUCCESS`: The node completed its task successfully.
* `FAILURE`: The node failed to complete its task.
* `RUNNING`: The node is currently executing and needs to be ticked again in the next frame.

### Built-in Nodes

Hology Engine provides a set of standard nodes to build your trees.

#### Composite Nodes

* **`SequenceNode`**: Runs children in order. Succeeds if all children succeed. Fails immediately if any child fails.
* **`SelectorNode`**: Runs children in order. Succeeds immediately if any child succeeds. Fails if all children fail.
* **`ParallelSequenceNode`**: Runs all children simultaneously. Succeeds if *all* children succeed. Fails if *any* child fails.
* **`ParallelSelectorNode`**: Runs all children simultaneously. Succeeds if *any* child succeeds. Fails if *all* children fail.
* **`WeightedRandomSelectorNode`**: Selects one child to run based on assigned weights.

#### Decorator Nodes

* **`InverterNode`**: Flips the result of its child (Success becomes Failure, Failure becomes Success).
* **`RepeatNode`**: Repeats the child node indefinitely.
* **`RepeatTimesNode`**: Repeats the child a specific number of times.
* **`RepeatUntilNode`**: Repeats the child until a condition function returns true.
* **`RepeatUntilFailNode`**: Repeats the child until it returns Failure.
* **`GuardNode`**: Only runs the child if a condition is met; otherwise returns Failure.
* **`CooldownNode`**: Prevents the child from running again until a cooldown period has passed.
* **`TimerNode`**: Runs the child for a specific duration, then returns Failure.
* **`DelayNode`**: Waits for a specified time before running the child.
* **`ThrottleNode`**: Limits how often the child node is ticked.

#### Leaf Nodes

* **`ActionNode`**: Executes a function that returns a `NodeState`.
* **`ConditionNode`**: Checks a condition function. Returns Success if true, Failure if false.
* **`WaitNode`**: Returns Running for a specified duration, then Success.
* **`SuccessNode`**: Always returns Success.
* **`FailNode`**: Always returns Failure.

### Creating a Behavior Tree

Behavior trees are typically constructed in your Actor's `onBeginPlay` method.

```typescript
import { 
  SelectorNode, SequenceNode, ActionNode, WaitNode, RepeatNode, 
  NodeState 
} from '@hology/core/gameplay';

// ... inside your Actor class

onBeginPlay() {
  // 1. Define leaf behaviors
  const attack = new ActionNode(() => {
    console.log("Attacking!");
    return NodeState.SUCCESS;
  });

  const patrol = new SequenceNode();
  patrol.addChild(new ActionNode(() => {
     console.log("Moving to waypoint");
     return NodeState.SUCCESS; 
  }));
  patrol.addChild(new WaitNode(1000)); // Wait 1 second

  // 2. Compose the tree
  const rootSelector = new SelectorNode();
  
  // Try to attack first, if that fails (e.g. condition not met), patrol.
  rootSelector.addChild(attack); 
  rootSelector.addChild(patrol);

  // 3. Wrap in a repeater to keep the AI active
  this.behaviorTree = new RepeatNode(rootSelector);
}

onUpdate(dt: number) {
  // 4. Update the tree every frame
  this.behaviorTree?.tick(dt);
}
```

### Custom Nodes

You can create custom nodes by extending `LeafNode` or `DecoratorNode` for more complex game-specific logic.

```typescript
import { LeafNode, NodeState } from '@hology/core/gameplay';

class CheckHealthNode extends LeafNode {
  constructor(private character: Character, private threshold: number) {
    super();
  }

  tick(dt: number): NodeState {
    if (this.character.health < this.threshold) {
      return NodeState.SUCCESS;
    }
    return NodeState.FAILURE;
  }
}
```

### Further Reading

For a complete step-by-step guide on implementing a chasing AI, check out the tutorial [character-ai-behavior](https://docs.hology.app/tutorials/character-ai-behavior "mention") .
