### Resource Gathering Example Source: https://github.com/bitbrain/beehave/blob/godot-4.x/docs/manual/common_patterns.md This example shows a worker unit continuously gathering resources using the UntilFail pattern. The sequence finds, moves to, and gathers resources until no more are available. ```beehave UntilFail └── Sequence ├── FindResource ├── MoveToResource └── GatherResource ``` -------------------------------- ### Serve Docs Locally with Docsify Source: https://github.com/bitbrain/beehave/blob/godot-4.x/docs/contribute.md Run this command to test your wiki documentation locally. Ensure you have Docsify installed. ```bash docsify serve /docs ``` -------------------------------- ### Install Beehave Addon Source: https://context7.com/bitbrain/beehave/llms.txt Instructions for installing the Beehave addon in Godot Engine. Ensure compatibility with your Godot version. ```plaintext # Godot version compatibility: # Godot 3.x → Beehave branch godot-3.x (Beehave 1.x) # Godot 4.x → Beehave branch godot-4.x (Beehave 2.x) # Godot 4.5+ → Beehave 2.10+ # Godot 4.1.x → Beehave 2.9.x ``` -------------------------------- ### Enemy AI States Example Source: https://github.com/bitbrain/beehave/blob/godot-4.x/docs/manual/common_patterns.md This example illustrates an enemy AI state machine with distinct states for fleeing, attacking, and patrolling. It uses 'IsInState' to check the current state and execute the corresponding behavior. ```beehave // Enemy State Machine Structure Selector ├── Sequence (Flee State) │ ├── IsInState ("flee") │ └── FleeFromPlayer ├── Sequence (Attack State) │ ├── IsInState ("attack") │ └── AttackPlayer └── Sequence (Patrol State) ├── IsInState ("patrol") └── PatrolArea ``` -------------------------------- ### Dodge Incoming Attack Example Source: https://github.com/bitbrain/beehave/blob/godot-4.x/docs/manual/common_patterns.md An example of the Interrupt pattern where an AI interrupts its attack to dodge an incoming player attack. Creates dynamic and responsive combat. ```text Selector ├── Sequence (Dodge) │ ├── IsIncomingAttack │ └── DodgeRoll └── ContinueAttacking ``` -------------------------------- ### SelectorReactiveComposite Behavior Example Source: https://github.com/bitbrain/beehave/blob/godot-4.x/docs/manual/selector.md Demonstrates the 'restart' behavior, prioritizing responsiveness to high-priority conditions like being under attack. Ongoing tasks can be interrupted. ```plaintext SelectorReactiveComposite ├─ IsUnderAttack (Condition: initially failure, later success) │ └─ DefendSelf (Action: will interrupt ongoing tasks when under attack) ├─ IsHungry (Condition: success) └─ SearchForFood (Action: interrupted when attack detected) ``` -------------------------------- ### Time-Limited Chase Example Source: https://github.com/bitbrain/beehave/blob/godot-4.x/docs/manual/common_patterns.md This example demonstrates a time-limited chase behavior. The AI will only pursue the player for a specified duration, creating tense escape sequences. ```beehave TimeLimiter (10.0) └── ChasePlayer ``` -------------------------------- ### Combat Weapon Selection Example Source: https://github.com/bitbrain/beehave/blob/godot-4.x/docs/manual/common_patterns.md An example of the Fallback Chain pattern for weapon selection in combat. AI intelligently switches between special weapons, primary weapons, and melee based on ammo availability. ```text Selector ├── Sequence (Use Special Weapon) │ ├── HasSpecialAmmo │ └── FireSpecialWeapon ├── Sequence (Use Primary Weapon) │ ├── HasPrimaryAmmo │ └── FirePrimaryWeapon └── MeleeAttack ``` -------------------------------- ### SequenceStarComposite Example Source: https://github.com/bitbrain/beehave/blob/godot-4.x/docs/manual/sequence.md Use SequenceStarComposite for performance optimization and predictable multi-step procedures where redundant checks are avoided. This is suitable for complex animation sequences. ```plaintext SequenceStarComposite ├─ StartAnimation (Action: success) ├─ PlayMainAnimation (Action: running) └─ EndAnimation (Action) ``` -------------------------------- ### Parallel Activity Pattern Example Source: https://github.com/bitbrain/beehave/blob/godot-4.x/docs/manual/common_patterns.md Performs a background activity while working on a main task using SimpleParallel. Use for more natural AI multitasking. ```BehaviorTree SimpleParallel ├── MoveToPosition └── ScanForThreats ``` -------------------------------- ### Limited Retry Pattern Example Source: https://github.com/bitbrain/beehave/blob/godot-4.x/docs/manual/common_patterns.md Restricts how many times an operation is attempted using a Limiter. Use to prevent AI from getting stuck in infinite loops trying failing actions. ```BehaviorTree Limiter (max_attempts) └── OperationToLimit ``` -------------------------------- ### SequenceReactiveComposite Example Source: https://github.com/bitbrain/beehave/blob/godot-4.x/docs/manual/sequence.md Use SequenceReactiveComposite when continuous validation of preconditions is needed, such as re-checking item availability before picking it up. ```plaintext SequenceReactiveComposite ├─ IsItemAvailable (Condition) ├─ MoveToItem (Action: running) └─ UseItem (Action) ``` -------------------------------- ### Guard Pattern Example Source: https://github.com/bitbrain/beehave/blob/godot-4.x/docs/manual/common_patterns.md Ensures behaviors only trigger when they make sense. Use when an action should be protected by a condition. ```BehaviorTree Sequence ├── IsEnemyInRange └── AttackEnemy ``` -------------------------------- ### Random Selection Pattern Example Source: https://github.com/bitbrain/beehave/blob/godot-4.x/docs/manual/common_patterns.md Chooses between equally valid options randomly using SelectorRandomComposite. Use to make AI less predictable and more lifelike. ```BehaviorTree SelectorRandom ├── PlayIdleAnimation ("idle1") ├── PlayIdleAnimation ("idle2") └── PlayIdleAnimation ("idle3") ``` -------------------------------- ### SelectorComposite Behavior Example Source: https://github.com/bitbrain/beehave/blob/godot-4.x/docs/manual/selector.md Illustrates the 'tick again' behavior where a long-running task is prioritized. Other conditions are not re-evaluated while the special ability is running. ```plaintext SelectorComposite ├─ IsSpecialAbilityTriggered (Condition: success) │ └─ PerformSpecialAbility (Action: running) ├─ IsEnemyNearby (Condition: not evaluated while ability is running) └─ Patrol (Action: not evaluated while ability is running) ``` -------------------------------- ### Cooldown Pattern Example Source: https://github.com/bitbrain/beehave/blob/godot-4.x/docs/manual/common_patterns.md Implements a cooldown on actions using the Cooldown decorator. Use to prevent ability spam and create rhythm in combat. ```BehaviorTree Cooldown (5.0) └── SpecialAttack ``` -------------------------------- ### Delayed Explosion Example Source: https://github.com/bitbrain/beehave/blob/godot-4.x/docs/manual/common_patterns.md A specific implementation of the Delayed Reaction pattern, showing a bomb that explodes after a set delay. Useful for creating fair gameplay mechanics. ```text Sequence ├── PlaceBomb └── Delayer (3.0) └── Explode ``` -------------------------------- ### Example Action: Make Actor Visible Source: https://github.com/bitbrain/beehave/blob/godot-4.x/docs/manual/README.md A custom Action leaf node that sets the actor's visibility to true. Returns FAILURE if the actor is already visible, SUCCESS otherwise. ```gdscript class_name MakeVisibleAction extends ActionLeaf func tick(actor:Node, blackboard:Blackboard) -> int: if actor.visible: return FAILURE actor.visible = true return SUCCESS ``` -------------------------------- ### Example Condition: Check Visibility Source: https://github.com/bitbrain/beehave/blob/godot-4.x/docs/manual/README.md A custom Condition leaf node that checks if the actor is currently visible. Returns SUCCESS if visible, FAILURE otherwise. ```gdscript class_name IsVisibleCondition extends ConditionLeaf func tick(actor:Node, blackboard:Blackboard) -> int: if actor.visible: return SUCCESS return FAILURE ``` -------------------------------- ### Condition Leaf: Get Blackboard Value Source: https://context7.com/bitbrain/beehave/llms.txt A ConditionLeaf that checks for the presence and truthiness of a value on the Blackboard. Returns SUCCESS if the value is true, otherwise FAILURE. ```GDScript class_name RespondToTeamAlert extends ConditionLeaf func tick(actor: Node, blackboard: Blackboard) -> int: return SUCCESS if blackboard.get_value("team_alert", false) else FAILURE ``` -------------------------------- ### Throttled Physics AI Ticking in Beehave Source: https://context7.com/bitbrain/beehave/llms.txt Configure BeehaveTree.process_thread to PHYSICS and set tick_rate to control how often the tree ticks, for example, every 3 physics frames. ```gdscript # --- Throttled physics AI (every 3 frames) --- func _ready() -> void: $BeehaveTree.process_thread = BeehaveTree.ProcessThread.PHYSICS $BeehaveTree.tick_rate = 3 # tick() called every 3 physics frames ``` -------------------------------- ### Initializing a Custom Blackboard Source: https://github.com/bitbrain/beehave/blob/godot-4.x/docs/manual/blackboard.md Shows how to initialize a custom blackboard by extending the Blackboard class and setting initial values in the _ready function. ```gdscript class_name CustomBlackboard extends Blackboard func _ready() -> void: set_value("key", 15.0) ``` -------------------------------- ### Initializing a Shared Blackboard in a Scene Source: https://github.com/bitbrain/beehave/blob/godot-4.x/docs/manual/blackboard.md Illustrates how to set up a shared blackboard node in a scene and assign initial values to it. Ensure the blackboard is also assigned to your Beehave tree. ```typescript # my_scene.ts class_name MyScene extends Node2D @onready var blackboard := $Blackboard func _ready() -> void: blackboard.set_value("key", 15.0) ``` -------------------------------- ### Initialize Shared Blackboard Source: https://context7.com/bitbrain/beehave/llms.txt Sets up a shared blackboard for multiple Beehave trees in a scene script. Ensures the blackboard is initialized with a default value before being assigned to trees. ```gdscript @onready var shared_bb: Blackboard = $SharedBlackboard @onready var guard_tree: BeehaveTree = $Guard/BeehaveTree @onready var backup_tree: BeehaveTree = $Backup/BeehaveTree func _ready() -> void: shared_bb.set_value("alert_triggered", false) guard_tree.blackboard = shared_bb backup_tree.blackboard = shared_bb ``` -------------------------------- ### Setting Values on a Blackboard Source: https://github.com/bitbrain/beehave/blob/godot-4.x/docs/manual/blackboard.md Demonstrates how to set values on the default blackboard and a custom-named blackboard. Note that setting a value on a custom blackboard does not override values on the default one. ```gdscript func tick(actor:Actor, blackboard:Blackboard) -> int: # sets the value to '15.0' for "key" on the default blackboard blackboard.set_value("key", 15.0) # sets the value to '20.0' for "key" on the "custom" blackboard # note, that this does NOT override the previous value. # Both co-exist in different blackboards. blackboard.set_value("key", 20.0, "custom") return SUCCESS ``` -------------------------------- ### Custom Pre-seeded Blackboard Source: https://context7.com/bitbrain/beehave/llms.txt Extends the `Blackboard` class to pre-seed it with initial values during its `_ready` function. ```gdscript # --- Custom pre-seeded blackboard --- class_name EnemyBlackboard extends Blackboard func _ready() -> void: set_value("patrol_speed", 50.0) set_value("attack_damage", 15) set_value("alert_range", 300.0) ``` -------------------------------- ### Team Coordination with Blackboard Source: https://github.com/bitbrain/beehave/blob/godot-4.x/docs/manual/common_patterns.md Illustrates how multiple AI agents can coordinate actions using a shared blackboard. Useful for creating cohesive squad behavior in games. ```text Selector ├── Sequence (Respond to Team Alert) │ ├── CheckTeamAlert │ └── MoveToAlertPosition ├── Sequence (Raise Team Alert) │ ├── SpotAndRememberPlayer │ └── RaiseTeamAlert └── PatrolArea (Normal Behavior) ``` -------------------------------- ### State Machine Pattern with Blackboard Source: https://github.com/bitbrain/beehave/blob/godot-4.x/docs/manual/common_patterns.md Implement a state machine using a Selector with Sequence branches and a blackboard for state tracking. This pattern is useful for managing complex AI with distinct behavioral modes. ```beehave Selector ├── Sequence (State 1) │ ├── IsInState1 │ └── State1Behavior ├── Sequence (State 2) │ ├── IsInState2 │ └── State2Behavior └── Sequence (State 3) ├── IsInState3 └── State3Behavior ``` -------------------------------- ### Blackboard Data Storage and Retrieval Source: https://github.com/bitbrain/beehave/blob/godot-4.x/docs/manual/core_concepts.md Demonstrates how to store and retrieve data on the blackboard. Use `set_value` to store data and `get_value` to retrieve it. The second argument to `get_value` provides a default value if the key is not found. ```gdscript blackboard.set_value("player_position", player.global_position) blackboard.set_value("player_detected", true) ``` ```gdscript var target = blackboard.get_value("player_position") # Move toward target... ``` ```gdscript if blackboard.get_value("player_detected", false): # Attack player... ``` -------------------------------- ### Enable Beehave Performance Monitoring Source: https://context7.com/bitbrain/beehave/llms.txt Enable per-tree performance monitoring programmatically by setting custom_monitor to true. This adds metrics to Godot's Monitors tab. ```gdscript # Enable per-tree performance monitoring programmatically: func _ready() -> void: $BeehaveTree.custom_monitor = true # Godot's Monitors tab will now show: # beehave [microseconds]/process_time_- # beehave/total_trees # beehave/total_enabled_trees ``` -------------------------------- ### Configure Enemy Behavior Tree Source: https://github.com/bitbrain/beehave/blob/godot-4.x/docs/manual/first_behavior_tree.md This script sets up the enemy character and its behavior tree, including assigning patrol points to the MoveToPatrolPoint action. Ensure the BeehaveTree node and its children are correctly structured in the scene. ```gdscript extends CharacterBody2D @onready var beehave_tree = $BeehaveTree # Add patrol points to the scene @onready var patrol_point1 = $PatrolPoint1 @onready var patrol_point2 = $PatrolPoint2 func _ready(): # Make sure to add your enemy to a group if needed for conditions add_to_group("enemies") # Set up patrol points in the move_to_patrol_point script var patrol_script = $BeehaveTree/SelectorComposite/PatrolSequence/MoveToPatrolPoint patrol_script.patrol_points = [patrol_point1.get_path(), patrol_point2.get_path()] func _physics_process(delta): # The behavior tree handles the movement logic, but you might need # additional code for animation, etc. pass ``` -------------------------------- ### Blackboard Value Reading Source: https://context7.com/bitbrain/beehave/llms.txt Shows how to read values from the Blackboard using `get_value` with a default, and check for value existence with `has_value`. ```gdscript # --- Reading values --- func tick(actor: Node, blackboard: Blackboard) -> int: # get_value(key, default, scope) var pos: Vector2 = blackboard.get_value("player_position", Vector2.ZERO) var known: bool = blackboard.has_value("player_detected") if not known: return FAILURE actor.move_toward(pos) return RUNNING ``` -------------------------------- ### PatrolAction with Lifecycle Hooks Source: https://context7.com/bitbrain/beehave/llms.txt An action node demonstrating the use of `before_run` to initialize state and `after_run` to clean up or record final state. `interrupt` is also shown for cleanup. ```gdscript class_name PatrolAction extends ActionLeaf var _start_position: Vector2 # Called once before the first tick of a new run func before_run(actor: Node, blackboard: Blackboard) -> void: _start_position = actor.global_position blackboard.set_value("patrol_origin", _start_position) func tick(actor: Node, blackboard: Blackboard) -> int: # ... movement logic ... return RUNNING # Called once after the run ends with SUCCESS or FAILURE func after_run(actor: Node, blackboard: Blackboard) -> void: blackboard.set_value("last_patrol_end", actor.global_position) func interrupt(actor: Node, blackboard: Blackboard) -> void: actor.velocity = Vector2.ZERO super.interrupt(actor, blackboard) ``` -------------------------------- ### SequenceComposite Variants for Logic Flow Source: https://context7.com/bitbrain/beehave/llms.txt Demonstrates SequenceComposite and its variants (SequenceReactiveComposite, SequenceStarComposite) for controlling execution flow based on child success or failure. Use SequenceReactiveComposite when earlier conditions must remain true, and SequenceStarComposite for deterministic multi-step procedures. ```gdscript # Scene tree for an attack sequence: # SequenceComposite # IsPlayerVisible (ConditionLeaf) → must succeed first # ChasePlayer (ActionLeaf) → returns RUNNING until in range # AttackPlayer (ActionLeaf) → fires once in range # Use SequenceReactiveComposite when earlier conditions must stay true: # SequenceReactiveComposite # IsItemAvailable (re-checked every tick even while MoveToItem is RUNNING) # MoveToItem # UseItem # Use SequenceStarComposite for deterministic multi-step procedures: # SequenceStarComposite # StartCastAnimation (SUCCESS once started) # PlayCastAnimation (RUNNING until done) # ApplySpellEffect (one-shot SUCCESS) # GDScript: random sequence (shuffles child order each run) # SequenceRandomComposite — same tick/restart rules as SequenceStarComposite # but children execute in a random order each time the sequence is entered ``` -------------------------------- ### State Machine Pattern with Beehave Source: https://context7.com/bitbrain/beehave/llms.txt Model distinct AI states using a SelectorComposite with sequences for each state. Use a ConditionLeaf to check the current state stored in the blackboard. ```gdscript # Model distinct AI states with a Selector + Blackboard # SelectorComposite # Sequence (Flee state) # │ IsInState("flee") # │ FleeFromPlayer # Sequence (Attack state) # │ IsInState("attack") # │ AttackPlayer # Sequence (Patrol state) # │ IsInState("patrol") # │ PatrolArea class_name IsInState extends ConditionLeaf @export var state_name: String = "" func tick(actor: Node, blackboard: Blackboard) -> int: return SUCCESS if blackboard.get_value("state") == state_name else FAILURE ``` -------------------------------- ### Configure BeehaveTree Root Node Source: https://context7.com/bitbrain/beehave/llms.txt Configure the BeehaveTree root node's processing thread, tick rate, and monitoring. Optionally set a custom actor or blackboard. ```gdscript # Scene tree layout: # Enemy (CharacterBody2D) # └── BeehaveTree ← add this node; actor defaults to its parent # └── SelectorComposite # ├── AttackSequence (SequenceComposite) # └── PatrolSequence (SequenceComposite) extends CharacterBody2D @onready var tree: BeehaveTree = $BeehaveTree func _ready() -> void: # process_thread options: PHYSICS (default), IDLE, MANUAL tree.process_thread = BeehaveTree.ProcessThread.PHYSICS # Tick only every 3 physics frames instead of every frame tree.tick_rate = 3 # Enable per-tree performance monitoring in Godot's Monitor tab tree.custom_monitor = true # Optionally point the tree at a different actor node # tree.actor_node_path = NodePath("../SomeOtherNode") # Optionally inject a shared blackboard # tree.blackboard = $SharedBlackboard func _on_turn_started() -> void: # MANUAL mode: drive the tick yourself (e.g., turn-based game) tree.process_thread = BeehaveTree.ProcessThread.MANUAL tree.tick() # returns SUCCESS, FAILURE, or RUNNING func pause_ai() -> void: tree.disable() # interrupts any RUNNING nodes cleanly func resume_ai() -> void: tree.enable() func debug_status() -> void: # Query runtime state var running: ActionLeaf = tree.get_running_action() var last_cond: ConditionLeaf = tree.get_last_condition() var cond_status: String = tree.get_last_condition_status() # "SUCCESS" | "FAILURE" | "RUNNING" print("Running: ", running, " | Last condition: ", last_cond, " → ", cond_status) ``` -------------------------------- ### Memory Pattern for Remembering State Source: https://context7.com/bitbrain/beehave/llms.txt Implement the Memory Pattern using a ConditionLeaf to store state in the blackboard, such as player position and time, when a condition is met. ```gdscript class_name RememberLastSeenPosition extends ConditionLeaf func tick(actor: Node, blackboard: Blackboard) -> int: var player := get_tree().get_first_node_in_group("player") if player and actor.has_line_of_sight(player): blackboard.set_value("last_seen_position", player.global_position) blackboard.set_value("last_seen_time", Time.get_ticks_msec()) return SUCCESS # Falls through even when player is hidden — position is remembered return FAILURE ``` -------------------------------- ### Chase Player Action Node Source: https://github.com/bitbrain/beehave/blob/godot-4.x/docs/manual/first_behavior_tree.md Implement an action to move the actor towards the player's position stored on the blackboard. Returns SUCCESS when within attack range, otherwise RUNNING. ```gdscript class_name ChasePlayer extends ActionLeaf @export var move_speed: float = 100.0 @export var attack_range: float = 30.0 func tick(actor: Node, blackboard: Blackboard) -> int: # Get the player position from the blackboard var player_pos = blackboard.get_value("player_position") if not player_pos: return FAILURE # Calculate direction to player var direction = (player_pos - actor.global_position).normalized() # Move toward player actor.global_position += direction * move_speed * get_physics_process_delta_time() # Store attack range in blackboard blackboard.set_value("attack_range", attack_range) # Check if within attack range var distance = actor.global_position.distance_to(player_pos) if distance <= attack_range: return SUCCESS # Still chasing return RUNNING ``` -------------------------------- ### Simple If-Else AI Logic in GDScript Source: https://github.com/bitbrain/beehave/blob/godot-4.x/docs/manual/comparison.md Use for basic AI behaviors during prototyping or for very simple entities. Becomes unwieldy and hard to maintain as complexity increases. ```gdscript func update_enemy(delta): # Check if player is visible if is_player_visible(): # Check if in attack range if distance_to_player() < attack_range: attack_player() else: move_toward_player() else: patrol() ``` -------------------------------- ### SelectorComposite Variants for OR Logic Source: https://context7.com/bitbrain/beehave/llms.txt Illustrates SelectorComposite and SelectorReactiveComposite for implementing OR logic, where the first succeeding child determines the outcome. SelectorReactiveComposite re-evaluates from the first child on each tick, useful for interruptible behaviors. ```gdscript # Priority selector: try high-priority behaviour first, fall back gracefully # SelectorComposite # Sequence (Flee — highest priority) # │ IsHealthCritical # │ FleeFromPlayer # Sequence (Attack) # │ IsPlayerInRange # │ AttackPlayer # PatrolAction ← fallback, always available # Reactive selector: re-checks IsUnderAttack every tick even while SearchForFood runs # SelectorReactiveComposite # Sequence # │ IsUnderAttack ← immediately interrupts SearchForFood when true # │ DefendSelf # Sequence # │ IsHungry # │ SearchForFood # Random selector: picks a random child order (equal-probability idle variety) # SelectorRandomComposite # PlayIdleAnimation("idle_scratch") # PlayIdleAnimation("idle_yawn") # PlayIdleAnimation("idle_stretch") ``` -------------------------------- ### Is Player Visible Condition Node Source: https://github.com/bitbrain/beehave/blob/godot-4.x/docs/manual/first_behavior_tree.md Implement a condition to check if the player is within the enemy's detection range and vision cone. Saves player position and detection status to the blackboard. ```gdscript class_name IsPlayerVisible extends ConditionLeaf @export var player_detection_range: float = 200.0 @export var vision_cone_angle: float = 45.0 # degrees func tick(actor: Node, blackboard: Blackboard) -> int: # Get player reference (could be cached in blackboard) var player = get_tree().get_first_node_in_group("player") if not player: return FAILURE # Calculate distance and direction to player var to_player = player.global_position - actor.global_position var distance = to_player.length() # Check if player is within detection range if distance > player_detection_range: return FAILURE # Check if player is within vision cone var forward_dir = Vector2.RIGHT.rotated(actor.rotation) var angle_to_player = forward_dir.angle_to(to_player.normalized()) if abs(angle_to_player) > deg_to_rad(vision_cone_angle): return FAILURE # Player is visible, save position in blackboard blackboard.set_value("player_position", player.global_position) blackboard.set_value("player_detected", true) return SUCCESS ``` -------------------------------- ### UntilFail Loop Pattern Source: https://github.com/bitbrain/beehave/blob/godot-4.x/docs/manual/common_patterns.md Use the UntilFail node to repeatedly execute a behavior until it fails. This is ideal for tasks that should continue until a specific condition is met or an error occurs. ```beehave UntilFail └── BehaviorToRepeat ``` -------------------------------- ### Limited Attempts Pattern Source: https://github.com/bitbrain/beehave/blob/godot-4.x/docs/manual/common_patterns.md Use the Limiter node to restrict the number of times a behavior can be executed. This prevents AI from endlessly repeating an action, like trying to pick a lock multiple times. ```beehave Limiter (3) └── Sequence ├── ApproachDoor └── AttemptToUnlock ``` -------------------------------- ### Blackboard Value Writing Source: https://context7.com/bitbrain/beehave/llms.txt Demonstrates writing values to the Blackboard in the default scope and a named scope. Values can be of any type. ```gdscript # --- Writing values --- func tick(actor: Node, blackboard: Blackboard) -> int: # Default (shared) scope blackboard.set_value("player_position", actor.global_position) # Named scope — does NOT collide with the key in the default scope blackboard.set_value("player_position", Vector2.ZERO, "old_data") return SUCCESS ``` -------------------------------- ### SimpleParallel for Concurrent Actions Source: https://context7.com/bitbrain/beehave/llms.txt Shows how SimpleParallel executes two children simultaneously, with the primary driving the node's status and the secondary running in the background until the primary finishes. This is useful for actions that need to occur alongside another primary behavior. ```gdscript # Move toward the player while shooting whenever possible: # SimpleParallel # MoveToPlayer ← primary: drives the overall result # SequenceComposite ← secondary: runs in the background # CanShoot # ShootAtPlayer # Implementation of the secondary condition+action pair: class_name CanShoot extends ConditionLeaf func tick(actor: Node, blackboard: Blackboard) -> int: return SUCCESS if actor.ammo > 0 and actor.shoot_cooldown <= 0.0 else FAILURE class_name ShootAtPlayer extends ActionLeaf func tick(actor: Node, blackboard: Blackboard) -> int: var target = blackboard.get_value("player_position") actor.fire_projectile_at(target) actor.shoot_cooldown = 0.5 return SUCCESS ``` -------------------------------- ### Action Leaf: Set Blackboard Values Source: https://context7.com/bitbrain/beehave/llms.txt An ActionLeaf that sets specific values on the Blackboard. Useful for signaling events or storing actor-specific data. ```GDScript class_name RaiseTeamAlert extends ActionLeaf func tick(actor: Node, blackboard: Blackboard) -> int: blackboard.set_value("alert_position", actor.global_position) blackboard.set_value("team_alert", true) return SUCCESS ``` -------------------------------- ### Fallback Chain Pattern Source: https://github.com/bitbrain/beehave/blob/godot-4.x/docs/manual/common_patterns.md Creates a chain of fallback behaviors with conditions, ensuring graceful degradation of AI actions. Prevents AI from failing to act when preferred actions are not possible. ```text Selector ├── Sequence (Primary Behavior) │ ├── CanExecutePrimary │ └── ExecutePrimary ├── Sequence (Secondary Behavior) │ ├── CanExecuteSecondary │ └── ExecuteSecondary └── FallbackBehavior ``` -------------------------------- ### Time-Limited Action Pattern Source: https://github.com/bitbrain/beehave/blob/godot-4.x/docs/manual/common_patterns.md Employ the TimeLimiter node to enforce a time constraint on an action. This is useful for behaviors that should have a sense of urgency, preventing them from running indefinitely. ```beehave TimeLimiter (seconds) └── TimedAction ``` -------------------------------- ### Guard Pattern in Beehave Source: https://context7.com/bitbrain/beehave/llms.txt Use the Guard Pattern by placing a ConditionLeaf before a protected action within a SequenceComposite. This ensures the action only executes if the condition is met. ```gdscript # Only execute an action when a condition holds # SequenceComposite # IsEnemyInRange ← guard # AttackEnemy ← protected action ``` -------------------------------- ### Default Page Load in GdUnit4 Report Source: https://github.com/bitbrain/beehave/blob/godot-4.x/addons/gdUnit4/src/reporters/html/template/index.html This line ensures that the 'test-suites' page is loaded by default when the GdUnit4 HTML report is initially opened. ```javascript loadPage('test-suites'); ``` -------------------------------- ### Delayed Reaction Pattern Source: https://github.com/bitbrain/beehave/blob/godot-4.x/docs/manual/common_patterns.md Uses the Delayer decorator to implement delayed responses to events. This pattern creates anticipation and allows players time to react to telegraphed actions. ```text Sequence ├── TriggerEvent └── Delayer (seconds) └── ReactToEvent ``` -------------------------------- ### Load Content for GdUnit4 Report Pages Source: https://github.com/bitbrain/beehave/blob/godot-4.x/addons/gdUnit4/src/reporters/html/template/index.html This JavaScript function dynamically loads content into the report's main display area based on the selected page. It supports 'test-suites', 'paths', and 'logging' views, populating them with relevant tables or an iframe for logs. ```javascript function loadPage(page) { if (page === 'test-suites') { document.getElementById('content').innerHTML = `
${report_table_testsuites}
Test Suites State Tests Skipped Flaky Failures Orphans Duration Quick State
` } else if (page === 'paths') { document.getElementById('content').innerHTML = `
${report_table_paths}
Paths State Tests Skipped Flaky Failures Orphans Duration Quick State
` } else if (page === 'logging') { document.getElementById('content').innerHTML = `

${godot_log_file}

` } } ``` -------------------------------- ### Implement Patrol Waiting Source: https://github.com/bitbrain/beehave/blob/godot-4.x/docs/manual/first_behavior_tree.md This action node makes the actor wait at a patrol point for a specified duration. It uses the blackboard to detect when a new point is reached and resets the wait timer. The wait time is configurable. ```gdscript class_name WaitAtPatrolPoint extends ActionLeaf @export var wait_time: float = 2.0 var current_wait_time: float = 0.0 func tick(actor: Node, blackboard: Blackboard) -> int: # Check if we just reached the patrol point if blackboard.get_value("patrol_point_reached", false): blackboard.set_value("patrol_point_reached", false) current_wait_time = 0.0 # Increment wait time current_wait_time += get_physics_process_delta_time() # Check if we've waited long enough if current_wait_time >= wait_time: return SUCCESS return RUNNING ``` -------------------------------- ### IsPlayerVisible Condition Node Source: https://context7.com/bitbrain/beehave/llms.txt Checks if the player is within detection range and vision angle. Writes player position and detection status to the blackboard upon success. Conditions should not return RUNNING. ```gdscript class_name IsPlayerVisible extends ConditionLeaf @export var detection_range: float = 200.0 @export var vision_angle_deg: float = 45.0 func tick(actor: Node, blackboard: Blackboard) -> int: var player := get_tree().get_first_node_in_group("player") if not player: return FAILURE var to_player: Vector2 = player.global_position - actor.global_position if to_player.length() > detection_range: return FAILURE var forward := Vector2.RIGHT.rotated(actor.rotation) if abs(forward.angle_to(to_player.normalized())) > deg_to_rad(vision_angle_deg): return FAILURE # Write discovered data to the blackboard for other nodes to consume blackboard.set_value("player_position", player.global_position) blackboard.set_value("player_detected", true) return SUCCESS ``` -------------------------------- ### Interactivity for GdUnit4 Report Table Source: https://github.com/bitbrain/beehave/blob/godot-4.x/addons/gdUnit4/src/reporters/html/template/suite_report.html Handles click events on test report rows to display detailed reports and manage row selection. ```javascript $(document).ready(function () { var report_view = $('#report_area').find('.report-column') $('#report-table tr').click(function () { var report = $(this).find('.report-column').html(); report_view.html(report) $('.selected').removeClass('selected'); $(this).addClass('selected'); }); }); ``` -------------------------------- ### Attack Player Action Node Source: https://github.com/bitbrain/beehave/blob/godot-4.x/docs/manual/first_behavior_tree.md Implement an action to perform an attack on the player. Includes a cooldown mechanism to prevent rapid attacks. Prints a message when the attack is performed. ```gdscript class_name AttackPlayer extends ActionLeaf @export var attack_cooldown: float = 1.0 var time_since_last_attack: float = 0.0 func tick(actor: Node, blackboard: Blackboard) -> int: # Check if cooldown has elapsed if time_since_last_attack < attack_cooldown: time_since_last_attack += get_physics_process_delta_time() return RUNNING # Reset cooldown time_since_last_attack = 0.0 # Perform attack print("Enemy attacks player!") # In a real game, you might trigger an animation or spawn a projectile here return SUCCESS ``` -------------------------------- ### Extend ConditionLeaf for Player Attack Range Check Source: https://github.com/bitbrain/beehave/blob/godot-4.x/docs/manual/condition_leaf.md Extend the ConditionLeaf to check if the player is within the enemy's attack range. This node returns SUCCESS if the player is within range, and FAILURE otherwise. ```gdscript class_name IsPlayerWithinAttackRange extends ConditionLeaf func tick(actor: Node, _blackboard: Blackboard) -> int: var distance_from_player = actor.get_distance_from_player() var enemy_attack_range = actor.get_attack_range() if distance_from_player <= enemy_attack_range: return SUCCESS else: return FAILURE ``` -------------------------------- ### Memory Pattern: Remember Last Seen Position Source: https://github.com/bitbrain/beehave/blob/godot-4.x/docs/manual/common_patterns.md Stores information in the blackboard to remember past events. Use for AI that needs object permanence, like remembering where a player was last seen. ```GDScript // SpotAndRememberPlayer.gd class_name SpotAndRememberPlayer extends ConditionLeaf func tick(actor: Node, blackboard: Blackboard) -> int: var player = get_tree().get_first_node_in_group("player") if player and actor.can_see(player): // Remember where we saw the player blackboard.set_value("last_seen_position", player.global_position) blackboard.set_value("last_seen_time", Time.get_ticks_msec()) return SUCCESS return FAILURE ```