diff --git a/libs/util/include/psemek/util/behavior_tree.hpp b/libs/util/include/psemek/util/behavior_tree.hpp index 6e2e9962..48af1093 100644 --- a/libs/util/include/psemek/util/behavior_tree.hpp +++ b/libs/util/include/psemek/util/behavior_tree.hpp @@ -414,6 +414,81 @@ namespace psemek::util } }; + template + struct repeat_while + { + Condition condition; + Child child; + bool current_started = false; + int current = 0; + + repeat_while(Condition condition, Child child) + : condition(std::move(condition)) + , child(std::move(child)) + {} + + void start(Args ...) + { + current = 0; + current_started = false; + } + + status update(Time dt, Args ... args) + { + if (current == 0) + { + if (!current_started) + { + condition.start(args...); + current_started = true; + } + + auto result = condition.update(dt, args...); + if (auto f = std::get_if(&result)) + { + if (!(f->result)) + return finished{true}; + else + { + current = 1; + current_started = false; + dt = 0; + } + } + else + return result; + } + + // current == 1 + + if (!current_started) + { + child.start(args...); + current_started = true; + } + + auto result = child.update(dt, args...); + if (auto f = std::get_if(&result)) + { + if (!(f->result)) + return finished{false}; + else + { + current = 0; + current_started = false; + return running{}; + } + } + else + return result; + } + + bool event(Event const & e, Args ... args) + { + return condition.event(e, args...) || child.event(e, args...); + } + }; + template struct retry {