bevy_behave/
lib.rs

1//! A behaviour tree system for bevy.
2#![doc = include_str!("../readme.inc.md")]
3#![deny(missing_docs)]
4use std::{borrow::Cow, ops::RangeInclusive};
5
6use bevy::prelude::*;
7use ego_tree::*;
8
9mod behave_trigger;
10mod ctx;
11mod dyn_bundle;
12mod plugin;
13
14use behave_trigger::*;
15use ctx::*;
16use dyn_bundle::prelude::*;
17
18// in case users want to construct the tree without using the macro, we reexport:
19pub use ego_tree;
20
21/// Includes the ego_tree `tree!` macro for easy tree construction.
22/// this crate also re-exports `ego_tree` so you can construct trees manually (but not in prelude).
23pub mod prelude {
24    pub use super::behave;
25    pub use super::behave_trigger::BehaveTrigger;
26    pub use super::ctx::*;
27    pub use super::plugin::*;
28    pub use super::{Behave, BehaveFinished};
29    pub use ego_tree::*;
30}
31
32/// A node on the behave tree can be in one of these states
33#[derive(Copy, Clone, PartialEq, Eq, Debug)]
34enum BehaveNodeStatus {
35    /// Node reported success
36    Success,
37    /// Node reported failure
38    Failure,
39    /// A task is in progress
40    Running,
41    /// Ticking to await a timer
42    RunningTimer,
43    /// Ticking suspended until trigger reports a status
44    AwaitingTrigger,
45    /// Next tick, reset node and descendants to initial state, for re-running.
46    PendingReset,
47}
48
49/// Inserted on the entity with the BehaveTree when the tree has finished executing.
50/// Containts the final result of the tree.
51#[derive(Component, Reflect, Debug)]
52pub struct BehaveFinished(pub bool);
53
54/// A behaviour added to the tree by a user, which we convert to a a BehaviourNode tree internally
55/// to run the tree. This is the template of the behaviour without all the internal runtime state.
56///
57/// Constuction is via static fns on Behave, so we can do the dynamic bundle stuff.
58/// although this probably makes it hard to load the tree def from an asset file?
59#[derive(Clone)]
60pub enum Behave {
61    /// Waits this many seconds before Succeeding
62    Wait(f32),
63    /// Spawns an entity, and waits for it to trigger a status report
64    /// Use the Behaviour::dynamic_bundle fn to create.
65    DynamicEntity {
66        /// The name value of the Name component for this entity.
67        name: Cow<'static, str>,
68        /// The dynamic bundle to spawn.
69        dynamic_bundel: DynamicBundel,
70    },
71    /// Runs children in sequence, failing if any fails, succeeding if all succeed
72    Sequence,
73    /// Runs children in sequence until one succeeds. If all fail, this fails.
74    Fallback,
75    /// Inverts success/failure of child. Must only have one child.
76    Invert,
77    /// Always succeeds
78    AlwaysSucceed,
79    /// Always fails
80    AlwaysFail,
81    /// Returns a result from a trigger. Can be used as a conditional (returning success or failure)
82    /// or simply to execute some bevy systems code without spawning an entity.
83    TriggerReq(DynamicTrigger),
84    /// Loops forever
85    Forever,
86    /// Runs second child as long as first child succeeds, in a loop.
87    While,
88    /// If the first child succeeds, run the second child.
89    /// (otherwise, run the third child, if present)
90    IfThen,
91}
92
93impl std::fmt::Display for Behave {
94    fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
95        match self {
96            Behave::While => write!(f, "While"),
97            Behave::Wait(secs) => write!(f, "Wait({secs}s)"),
98            Behave::DynamicEntity { name, .. } => write!(f, "Spawn({name})"),
99            Behave::Sequence => write!(f, "Sequence"),
100            Behave::Fallback => write!(f, "Fallback"),
101            Behave::Invert => write!(f, "Invert"),
102            Behave::AlwaysSucceed => write!(f, "AlwaysSucceed"),
103            Behave::AlwaysFail => write!(f, "AlwaysFail"),
104            Behave::TriggerReq(t) => write!(f, "Trigger({})", t.type_name()),
105            Behave::Forever => write!(f, "Forever"),
106            Behave::IfThen => write!(f, "IfThen"),
107        }
108    }
109}
110
111impl Behave {
112    /// Creates a new Behave::DynamicEntity, which means when this node runs, a new entity
113    /// will be spawned with the components you provide in the `bundle` (as well as a [`BehaveCtx`]).
114    pub fn spawn<T: Bundle + Clone>(bundle: T) -> Behave {
115        Behave::DynamicEntity {
116            name: "unnamed".into(),
117            dynamic_bundel: DynamicBundel::new(bundle),
118        }
119    }
120    /// Creates a new named Behave::DynamicEntity, which means when this node runs, a new entity
121    /// will be spawned with:
122    /// * the components you provide in the `bundle`
123    /// * A bevy `Name` component with the value of `name`
124    /// * [`BehaveCtx`]
125    ///
126    /// **NB** Don't include a `Name`` component in the bundle, since this fn adds on based on `name`.
127    pub fn spawn_named<T: Bundle + Clone>(name: impl Into<Cow<'static, str>>, bundle: T) -> Behave {
128        let name = name.into();
129        Behave::DynamicEntity {
130            name: name.clone(),
131            dynamic_bundel: DynamicBundel::new((Name::new(name), bundle)),
132        }
133    }
134    /// Creates a new Behave::TriggerReq, which means when this node runs, a trigger will be emitted
135    /// using `BehaveTrigger<T>`. You can access the `value` in an observer using `trigger.event().inner()`.
136    pub fn trigger<T: Clone + Send + Sync + 'static>(value: T) -> Self {
137        Behave::TriggerReq(DynamicTrigger::new(value))
138    }
139    /// The permitted number of children for this node
140    pub(crate) fn permitted_children(&self) -> RangeInclusive<usize> {
141        match self {
142            Behave::Sequence => 1..=usize::MAX,
143            Behave::Fallback => 1..=usize::MAX,
144            Behave::Forever => 1..=usize::MAX,
145            Behave::While => 1..=2,
146            Behave::IfThen => 2..=3,
147            Behave::Invert => 1..=1,
148            // Task nodes have no children:
149            Behave::Wait(_) => 0..=0,
150            Behave::TriggerReq(_) => 0..=0,
151            Behave::DynamicEntity { .. } => 0..=0,
152            // AlwaysSucceed and AlwaysFail are pseudo task nodes that don't have children:
153            Behave::AlwaysSucceed => 0..=0,
154            Behave::AlwaysFail => 0..=0,
155        }
156    }
157}
158
159/// A state wraps the behaviour, and is the node in our internal tree representation of the behaviour tree
160/// One per Behave, with extra state bits.
161// #[derive(Debug)]
162pub(crate) enum BehaveNode {
163    Forever {
164        status: Option<BehaveNodeStatus>,
165    },
166    Wait {
167        start_time: Option<f32>,
168        secs_to_wait: f32,
169        status: Option<BehaveNodeStatus>,
170    },
171    DynamicEntity {
172        // None until something spawned.
173        task_status: EntityTaskStatus,
174        status: Option<BehaveNodeStatus>,
175        bundle: DynamicBundel,
176        name: Cow<'static, str>,
177    },
178    SequenceFlow {
179        status: Option<BehaveNodeStatus>,
180    },
181    FallbackFlow {
182        status: Option<BehaveNodeStatus>,
183    },
184    Invert {
185        status: Option<BehaveNodeStatus>,
186    },
187    AlwaysSucceed {
188        status: Option<BehaveNodeStatus>,
189    },
190    AlwaysFail {
191        status: Option<BehaveNodeStatus>,
192    },
193    TriggerReq {
194        status: Option<BehaveNodeStatus>,
195        task_status: TriggerTaskStatus,
196        trigger: DynamicTrigger,
197    },
198    While {
199        status: Option<BehaveNodeStatus>,
200    },
201    IfThen {
202        status: Option<BehaveNodeStatus>,
203    },
204}
205
206#[derive(Clone, Debug)]
207enum EntityTaskStatus {
208    NotStarted,
209    Started(Entity),
210    Complete(bool),
211}
212
213#[derive(Clone, Debug)]
214enum TriggerTaskStatus {
215    NotTriggered,
216    Triggered,
217    Complete(bool),
218}
219
220impl BehaveNode {
221    fn status(&self) -> &Option<BehaveNodeStatus> {
222        match self {
223            BehaveNode::Forever { status } => status,
224            BehaveNode::TriggerReq { status, .. } => status,
225            BehaveNode::Wait { status, .. } => status,
226            BehaveNode::DynamicEntity { status, .. } => status,
227            BehaveNode::SequenceFlow { status } => status,
228            BehaveNode::FallbackFlow { status } => status,
229            BehaveNode::Invert { status } => status,
230            BehaveNode::AlwaysSucceed { status } => status,
231            BehaveNode::AlwaysFail { status } => status,
232            BehaveNode::While { status } => status,
233            BehaveNode::IfThen { status } => status,
234        }
235    }
236    fn status_mut(&mut self) -> &mut Option<BehaveNodeStatus> {
237        match self {
238            BehaveNode::Forever { status } => status,
239            BehaveNode::TriggerReq { status, .. } => status,
240            BehaveNode::Wait { status, .. } => status,
241            BehaveNode::DynamicEntity { status, .. } => status,
242            BehaveNode::SequenceFlow { status } => status,
243            BehaveNode::FallbackFlow { status } => status,
244            BehaveNode::Invert { status } => status,
245            BehaveNode::AlwaysSucceed { status } => status,
246            BehaveNode::AlwaysFail { status } => status,
247            BehaveNode::While { status } => status,
248            BehaveNode::IfThen { status } => status,
249        }
250    }
251}
252
253impl std::fmt::Display for BehaveNode {
254    #[rustfmt::skip]
255    fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
256        match self {
257            BehaveNode::Forever { .. } => write!(f, "Forever")?,
258            BehaveNode::TriggerReq { trigger, .. } => write!(f, "TriggerReq({})", trigger.type_name())?,
259            BehaveNode::Wait { secs_to_wait, .. } => write!(f, "Wait({secs_to_wait})")?,
260            BehaveNode::DynamicEntity {name, .. } => write!(f, "DynamicEntity({name})")?,
261            BehaveNode::SequenceFlow { .. } => write!(f, "SequenceFlow")?,
262            BehaveNode::FallbackFlow { .. } => write!(f, "FallbackFlow")?,
263            BehaveNode::Invert { .. } => write!(f, "Invert")?,
264            BehaveNode::AlwaysSucceed { .. } => write!(f, "AlwaysSucceed")?,
265            BehaveNode::AlwaysFail { .. } => write!(f, "AlwaysFail")?,
266            BehaveNode::While { .. } => write!(f, "While")?,
267            BehaveNode::IfThen { .. } => write!(f, "IfThen")?,
268        }
269        match self.status() {
270            Some(BehaveNodeStatus::Success) => write!(f, " --> ✅"),
271            Some(BehaveNodeStatus::Failure) => write!(f, " --> ❌"),
272            Some(BehaveNodeStatus::Running) => write!(f, " --> ⏳"),
273            Some(BehaveNodeStatus::RunningTimer) => write!(f, " --> ⏳"),
274            Some(BehaveNodeStatus::AwaitingTrigger) => write!(f, " --> ⏳"),
275            Some(BehaveNodeStatus::PendingReset) => write!(f, " --> 🔄"),
276            _ => Ok(()),
277        }
278    }
279}
280
281impl BehaveNode {
282    pub(crate) fn reset(&mut self) {
283        match self {
284            BehaveNode::Forever { status } => {
285                *status = None;
286            }
287            BehaveNode::TriggerReq {
288                status,
289                task_status,
290                ..
291            } => {
292                *status = None;
293                *task_status = TriggerTaskStatus::NotTriggered;
294            }
295            BehaveNode::Wait {
296                status, start_time, ..
297            } => {
298                *status = None;
299                *start_time = None;
300            }
301            BehaveNode::DynamicEntity {
302                status,
303                task_status,
304                ..
305            } => {
306                *status = None;
307                *task_status = EntityTaskStatus::NotStarted;
308            }
309            BehaveNode::SequenceFlow { status } => {
310                *status = None;
311            }
312            BehaveNode::FallbackFlow { status } => {
313                *status = None;
314            }
315            BehaveNode::Invert { status } => {
316                *status = None;
317            }
318            BehaveNode::AlwaysSucceed { status } => {
319                *status = None;
320            }
321            BehaveNode::AlwaysFail { status } => {
322                *status = None;
323            }
324            BehaveNode::While { status } => {
325                *status = None;
326            }
327            BehaveNode::IfThen { status } => {
328                *status = None;
329            }
330        }
331    }
332    pub(crate) fn new(behave: Behave) -> Self {
333        match behave {
334            Behave::Forever => Self::Forever { status: None },
335            Behave::TriggerReq(trig_fn) => Self::TriggerReq {
336                status: None,
337                task_status: TriggerTaskStatus::NotTriggered,
338                trigger: trig_fn,
339            },
340            Behave::Wait(secs_to_wait) => Self::Wait {
341                start_time: None,
342                secs_to_wait,
343                status: None,
344            },
345            Behave::DynamicEntity {
346                name,
347                dynamic_bundel: bundle,
348            } => Self::DynamicEntity {
349                task_status: EntityTaskStatus::NotStarted,
350                status: None,
351                bundle,
352                name,
353            },
354            Behave::While => Self::While { status: None },
355            Behave::Sequence => Self::SequenceFlow { status: None },
356            Behave::Fallback => Self::FallbackFlow { status: None },
357            Behave::Invert => Self::Invert { status: None },
358            Behave::AlwaysSucceed => Self::AlwaysSucceed { status: None },
359            Behave::AlwaysFail => Self::AlwaysFail { status: None },
360            Behave::IfThen => Self::IfThen { status: None },
361        }
362    }
363}
364
365// sucks there aren't good traversal fns on NodeMut like there are on NodeRef..
366fn reset_descendants(n: &mut NodeMut<BehaveNode>) {
367    // info!("Restting node: {:?}", n.id());
368    n.value().reset();
369    if let Some(mut sibling) = n.next_sibling() {
370        reset_descendants(&mut sibling);
371    }
372    if let Some(mut child) = n.first_child() {
373        reset_descendants(&mut child);
374    }
375}
376
377fn tick_node(
378    n: &mut NodeMut<BehaveNode>,
379    time: &Res<Time>,
380    commands: &mut Commands,
381    bt_entity: Entity,
382    target_entity: Entity,
383    logging: bool,
384) -> BehaveNodeStatus {
385    use BehaveNode::*;
386    // if logging {
387    //     info!("tick_node: {:?} = {}", n.id(), n.value());
388    // }
389    // short circuit nodes that have already got a result
390    let reset_needed = match n.value().status() {
391        Some(BehaveNodeStatus::Success) => return BehaveNodeStatus::Success,
392        Some(BehaveNodeStatus::Failure) => return BehaveNodeStatus::Failure,
393        Some(BehaveNodeStatus::PendingReset) => true,
394        _ => false,
395    };
396    if reset_needed {
397        *n.value().status_mut() = Some(BehaveNodeStatus::Running);
398        reset_descendants(n);
399    }
400    let task_node = n.id();
401    match n.value() {
402        While { .. } => {
403            *n.value().status_mut() = Some(BehaveNodeStatus::Running);
404            let mut first_child = n
405                .first_child()
406                .expect("While node first child must exist (the conditional)");
407            match tick_node(
408                &mut first_child,
409                time,
410                commands,
411                bt_entity,
412                target_entity,
413                logging,
414            ) {
415                BehaveNodeStatus::Success => {
416                    *first_child.value().status_mut() = Some(BehaveNodeStatus::Success);
417                    // if the conditional succeeds, we run the second child if present.
418                    // also supported a while node with just one child, which will simply repeat
419                    // until that child fails.
420                    if let Some(mut second_child) = first_child.next_sibling() {
421                        match tick_node(
422                            &mut second_child,
423                            time,
424                            commands,
425                            bt_entity,
426                            target_entity,
427                            logging,
428                        ) {
429                            BehaveNodeStatus::Success => {
430                                *second_child.value().status_mut() =
431                                    Some(BehaveNodeStatus::Success);
432                                // if the body succeeds, we loop back to the conditional
433                                *n.value().status_mut() = Some(BehaveNodeStatus::PendingReset);
434                                BehaveNodeStatus::PendingReset
435                            }
436                            other => {
437                                *n.value().status_mut() = Some(other);
438                                other
439                            }
440                        }
441                    } else {
442                        *n.value().status_mut() = Some(BehaveNodeStatus::PendingReset);
443                        BehaveNodeStatus::PendingReset
444                    }
445                }
446                other => {
447                    *first_child.value().status_mut() = Some(other);
448                    *n.value().status_mut() = Some(other);
449                    other
450                }
451            }
452        }
453        IfThen { .. } => {
454            *n.value().status_mut() = Some(BehaveNodeStatus::Running);
455            let mut conditional_child = n
456                .first_child()
457                .expect("IfThen node first child must exist (the 'if condition' child)");
458            // evaluate the condition child
459            match tick_node(
460                &mut conditional_child,
461                time,
462                commands,
463                bt_entity,
464                target_entity,
465                logging,
466            ) {
467                BehaveNodeStatus::Success => {
468                    // the condition child succeeded, so the If node returns the result of evaluating the then child.
469                    *conditional_child.value().status_mut() = Some(BehaveNodeStatus::Success);
470                    let mut then_child = conditional_child
471                        .next_sibling()
472                        .expect("IfThen node second child must exist (the 'then' child)");
473                    let then_result = tick_node(
474                        &mut then_child,
475                        time,
476                        commands,
477                        bt_entity,
478                        target_entity,
479                        logging,
480                    );
481                    *n.value().status_mut() = Some(then_result);
482                    then_result
483                }
484                BehaveNodeStatus::Failure => {
485                    // the condition child failed, an "else" child is optional. run if present:
486                    *conditional_child.value().status_mut() = Some(BehaveNodeStatus::Failure);
487                    if let Some(mut else_child) = conditional_child
488                        .next_sibling()
489                        .expect("If nodes must have exactly two or three children")
490                        .next_sibling()
491                    {
492                        // if there is an else child, the If node returns the result of evaluating the else child.
493                        let else_result = tick_node(
494                            &mut else_child,
495                            time,
496                            commands,
497                            bt_entity,
498                            target_entity,
499                            logging,
500                        );
501                        *n.value().status_mut() = Some(else_result);
502                        else_result
503                    } else {
504                        // if no else child, and conditional fails, the If node fails.
505                        *n.value().status_mut() = Some(BehaveNodeStatus::Failure);
506                        BehaveNodeStatus::Failure
507                    }
508                }
509                other => {
510                    *n.value().status_mut() = Some(other);
511                    other
512                }
513            }
514        }
515        Forever { .. } => {
516            *n.value().status_mut() = Some(BehaveNodeStatus::Running);
517            let mut only_child = n.first_child().expect("Forever nodes must have a child");
518            if only_child.has_siblings() {
519                panic!("Forever nodes must have a single child, not multiple children");
520            }
521            match tick_node(
522                &mut only_child,
523                time,
524                commands,
525                bt_entity,
526                target_entity,
527                logging,
528            ) {
529                // if our child node completes, reset next tick so we can run it again
530                BehaveNodeStatus::Success | BehaveNodeStatus::Failure => {
531                    *n.value().status_mut() = Some(BehaveNodeStatus::PendingReset);
532                    BehaveNodeStatus::PendingReset
533                }
534                other => other,
535            }
536        }
537        TriggerReq {
538            task_status: task_status @ TriggerTaskStatus::NotTriggered,
539            status,
540            trigger,
541        } => {
542            let ctx = BehaveCtx::new_for_trigger(bt_entity, task_node, target_entity);
543            commands.dyn_trigger(trigger.clone(), ctx);
544            // Don't use AwaitingTrigger for this, because of ordering issues..
545            // the trigger response arrives BEFORE we insert the BehaveAwaitingTrigger component,
546            // so the trigger response handler can't remove it, so it never ticks.
547            *task_status = TriggerTaskStatus::Triggered;
548            *status = Some(BehaveNodeStatus::Running);
549            BehaveNodeStatus::Running
550        }
551        #[rustfmt::skip]
552        TriggerReq {task_status: TriggerTaskStatus::Complete(true), status, ..} => {
553            *status = Some(BehaveNodeStatus::Success);
554            BehaveNodeStatus::Success
555        }
556        #[rustfmt::skip]
557        TriggerReq {task_status: TriggerTaskStatus::Complete(false), status, ..} => {
558            *status = Some(BehaveNodeStatus::Failure);
559            BehaveNodeStatus::Failure
560        }
561        // in this case, the trigger didn't report a result immediately, so we go into awaiting trigger mode.
562        // this happens if the trigger hands the ctx off to another system to report the result later.
563        #[rustfmt::skip]
564        TriggerReq {task_status: TriggerTaskStatus::Triggered, status, .. } => {
565            *status = Some(BehaveNodeStatus::AwaitingTrigger);
566            BehaveNodeStatus::AwaitingTrigger
567        }
568        Invert { .. } => {
569            let mut only_child = n.first_child().expect("Invert nodes must have a child");
570            if only_child.has_siblings() {
571                panic!("Invert nodes must have a single child, not multiple children");
572            }
573            let res = match tick_node(
574                &mut only_child,
575                time,
576                commands,
577                bt_entity,
578                target_entity,
579                logging,
580            ) {
581                BehaveNodeStatus::Success => BehaveNodeStatus::Failure, // swapped
582                BehaveNodeStatus::Failure => BehaveNodeStatus::Success, // swapped
583                other => other,
584            };
585            let Invert { status } = n.value() else {
586                unreachable!("Must be an Invert");
587            };
588            *status = Some(res);
589            res
590        }
591        AlwaysSucceed { status } => {
592            *status = Some(BehaveNodeStatus::Success);
593            BehaveNodeStatus::Success
594        }
595        AlwaysFail { status } => {
596            *status = Some(BehaveNodeStatus::Failure);
597            BehaveNodeStatus::Failure
598        }
599        // start waiting
600        Wait {
601            start_time: start_time @ None,
602            status,
603            ..
604        } => {
605            // info!("Starting wait");
606            *start_time = Some(time.elapsed_secs());
607            *status = Some(BehaveNodeStatus::Running);
608            BehaveNodeStatus::Running
609        }
610        // continue waiting
611        Wait {
612            start_time: Some(start_time),
613            secs_to_wait,
614            status,
615        } => {
616            // info!("Waiting");
617            let elapsed = time.elapsed_secs() - *start_time;
618            if elapsed > *secs_to_wait {
619                *status = Some(BehaveNodeStatus::Success);
620                return BehaveNodeStatus::Success;
621            }
622            BehaveNodeStatus::RunningTimer
623        }
624        // spawn a new entity for this task
625        DynamicEntity {
626            task_status: task_status @ EntityTaskStatus::NotStarted,
627            status,
628            bundle,
629            name: _,
630        } => {
631            let mut e = commands.spawn(());
632            e.set_parent(bt_entity);
633            let ctx = BehaveCtx::new_for_entity(bt_entity, task_node, target_entity);
634            // NB: if the component in the dyn bundle has an OnAdd which reports success or failure
635            //     immediately, the entity will be despawned instantly, so you can't do something
636            //     like .set_parent on it after doing the insertion (we set_parent above).
637            //     Else you get a "The entity with ID X does not exist" panic in bevy_hierarchy code.
638            let id = e.dyn_insert(bundle.clone(), Some(ctx)).id();
639            // info!("Spawned entity: {id:?} (parent: {bt_entity:?}) for node {task_node:?}",);
640            *task_status = EntityTaskStatus::Started(id);
641            // We go to Running for one tick, so that any OnAdd trigger that immediately reports a
642            // status we take effect properly.
643            // Next match case will set to AwaitingTrigger if we don't get a status report
644            // Otherwise there is an ordering mismatch and the AwaitingTrigger isn't removed.
645            *status = Some(BehaveNodeStatus::Running);
646            BehaveNodeStatus::Running
647        }
648        #[rustfmt::skip]
649        DynamicEntity { task_status: EntityTaskStatus::Started(_), status: status @ Some(BehaveNodeStatus::Running), .. } => {
650            // if we tick without having received a status report, it means there can't have been any OnAdd trigger 
651            // that immediately sent a report and caused a despawn, so we can go dormant:
652            *status = Some(BehaveNodeStatus::AwaitingTrigger);
653            BehaveNodeStatus::AwaitingTrigger
654        }
655        #[rustfmt::skip]
656        DynamicEntity{ task_status: EntityTaskStatus::Started(_), .. } => unreachable!("Short circuit should prevent this while AwaitingTrigger"),
657        // this is when a trigger has reported a result, and we need to process it and update status
658        #[rustfmt::skip]
659        DynamicEntity {task_status: EntityTaskStatus::Complete(true), status, ..} => {
660            *status = Some(BehaveNodeStatus::Success);
661            BehaveNodeStatus::Success
662        }
663        #[rustfmt::skip]
664        DynamicEntity {task_status: EntityTaskStatus::Complete(false), status, ..} => {
665            *status = Some(BehaveNodeStatus::Failure);
666            BehaveNodeStatus::Failure
667        }
668        // don't bind any fields here because we need to mutably borrow the node again
669        SequenceFlow { .. } => {
670            // info!("SequenceFlow. Processing children");
671            let Some(mut child) = n.first_child() else {
672                warn!("SequenceFlow with no children, returning success anyway");
673                return BehaveNodeStatus::Success;
674            };
675
676            let mut final_status;
677            loop {
678                match tick_node(
679                    &mut child,
680                    time,
681                    commands,
682                    bt_entity,
683                    target_entity,
684                    logging,
685                ) {
686                    BehaveNodeStatus::Success => {
687                        final_status = BehaveNodeStatus::Success;
688                        if let Ok(next_child) = child.into_next_sibling() {
689                            child = next_child;
690                            continue;
691                        } else {
692                            break;
693                        }
694                    }
695                    // A non-success state just gets bubbled up to the parent
696                    other => {
697                        final_status = other;
698                        break;
699                    }
700                }
701            }
702            let SequenceFlow { status, .. } = n.value() else {
703                unreachable!("Must be a SequenceFlow");
704            };
705            *status = Some(final_status);
706            final_status
707        }
708
709        FallbackFlow { .. } => {
710            let Some(mut child) = n.first_child() else {
711                warn!("FallbackFlow with no children, returning success anyway");
712                return BehaveNodeStatus::Success;
713            };
714
715            let mut final_status;
716            loop {
717                match tick_node(
718                    &mut child,
719                    time,
720                    commands,
721                    bt_entity,
722                    target_entity,
723                    logging,
724                ) {
725                    BehaveNodeStatus::Failure => {
726                        // a child fails, try the next one, or if no more children, we failed.
727                        final_status = BehaveNodeStatus::Failure;
728                        if let Ok(next_child) = child.into_next_sibling() {
729                            child = next_child;
730                            continue;
731                        } else {
732                            break;
733                        }
734                    }
735                    // A non-failure state just gets bubbled up to the parent
736                    other => {
737                        final_status = other;
738                        break;
739                    }
740                }
741            }
742            let FallbackFlow { status, .. } = n.value() else {
743                unreachable!("Must be a FallbackFlow");
744            };
745            *status = Some(final_status);
746            final_status
747        }
748    }
749}
750
751/// Modifed version of ego_tree's tree! macro, to allow merging subtrees:
752///
753/// let subtree: Tree<Behave> = get_subtree();
754/// let t = tree! {
755///     Behave::Sequence => {
756///         Behave::Wait(2),
757///         @ subtree
758///     }
759/// };
760///
761/// Also supports appending a list of children from an iterator:
762///
763/// let children: Vec<Behave> = get_children();
764/// let t = tree! {
765///     Behave::Sequence => {
766///         @[ children ]
767///     }
768/// };
769#[macro_export]
770macro_rules! behave {
771    // Append a bunch of children from an iterator
772    (@ $n:ident { @[ $children:expr ] $(, $($tail:tt)*)? }) => {{
773        for child in $children {
774            $n.append(child);
775        }
776        $( behave!(@ $n { $($tail)* }); )?
777    }};
778
779    // Use an “@” marker to indicate that the expression is a subtree, to be merged into the tree.
780    (@ $n:ident { @ $subtree:expr $(, $($tail:tt)*)? }) => {{
781        $n.append_subtree($subtree);
782        $( behave!(@ $n { $($tail)* }); )?
783    }};
784
785    // Base case: no tokens left, with optional trailing comma.
786    (@ $n:ident { $(,)? }) => { };
787
788    // Leaf: last value, with optional trailing comma.
789    (@ $n:ident { $value:expr $(,)? }) => {{
790        $n.append($value);
791    }};
792
793    // Leaf: value with additional siblings.
794    (@ $n:ident { $value:expr, $($tail:tt)* }) => {{
795        $n.append($value);
796        behave!(@ $n { $($tail)* });
797    }};
798
799    // Node: last node with children, with optional trailing comma.
800    (@ $n:ident { $value:expr => $children:tt $(,)? }) => {{
801        let mut node = $n.append($value);
802        behave!(@ node $children);
803    }};
804
805    // Node: node with children and additional siblings.
806    (@ $n:ident { $value:expr => $children:tt, $($tail:tt)* }) => {{
807        let mut node = $n.append($value);
808        behave!(@ node $children);
809        behave!(@ $n { $($tail)* });
810    }};
811
812    // Top-level: tree with a root only.
813    ($root:expr $(,)?) => { $crate::ego_tree::Tree::new($root) };
814
815    // Top-level: tree with a root and children, with optional trailing comma.
816    ($root:expr => $children:tt $(,)?) => {{
817        let mut tree = $crate::ego_tree::Tree::new($root);
818        {
819            let mut node = tree.root_mut();
820            behave!(@ node $children);
821        }
822        tree
823    }};
824}