diff --git a/modules/behaviour_nodes/behaviour_node.h b/modules/behaviour_nodes/behaviour_node.h index cf865e4b74..715db02584 100644 --- a/modules/behaviour_nodes/behaviour_node.h +++ b/modules/behaviour_nodes/behaviour_node.h @@ -14,15 +14,17 @@ protected: void _notification(int what); public: - virtual void enter() {} virtual void execute() {} + virtual void enter() { + set_status(Fail); + } virtual void exit() {} virtual BehaviourNode *get_next() { return this; } private: class BehaviourTree *behaviour_tree{ nullptr }; BehaviourNode *parent{ nullptr }; - Status status{}; + Status status{ Fail }; bool leaf{ false }; public: diff --git a/modules/behaviour_nodes/control_nodes.cpp b/modules/behaviour_nodes/control_nodes.cpp index a8eefbd7ea..15864a27e9 100644 --- a/modules/behaviour_nodes/control_nodes.cpp +++ b/modules/behaviour_nodes/control_nodes.cpp @@ -107,10 +107,12 @@ void BehaviourRepeatUntilFail::execute() { if (get_child_behaviours().is_empty()) { set_status(Fail); ERR_FAIL_EDMSG("BehaviourRepeatUntilFail execution with no child"); - } else { + } else if (get_status() == Running) { set_status(get_child_behaviours().get(0)->get_status() == Fail ? Success : Running); + } else { + set_status(Running); } } diff --git a/modules/behaviour_nodes/decorator_nodes.cpp b/modules/behaviour_nodes/decorator_nodes.cpp index 00bb62d881..b46b41b1af 100644 --- a/modules/behaviour_nodes/decorator_nodes.cpp +++ b/modules/behaviour_nodes/decorator_nodes.cpp @@ -2,8 +2,6 @@ #include "behaviour_nodes/behaviour_node.h" #include "core/variant/variant.h" -void BehaviourAlwaysSuccess::_bind_methods() {} - PackedStringArray BehaviourAlwaysSuccess::get_configuration_warnings() const { PackedStringArray warnings{ super_type::get_configuration_warnings() }; if (get_child_behaviours().size() != 1) { @@ -28,3 +26,41 @@ BehaviourNode *BehaviourAlwaysSuccess::get_next() { ? get_child_behaviours().get(0) : cast_to(get_parent()); } + +PackedStringArray BehaviourInvertResult::get_configuration_warnings() const { + PackedStringArray warnings{ super_type::get_configuration_warnings() }; + if (get_child_behaviours().size() != 1) { + warnings.push_back("BehaviourInvertResult should have exactly one child behaviour"); + } + return warnings; +} + +void BehaviourInvertResult::enter() { + set_status(Running); +} + +void BehaviourInvertResult::execute() { + if (get_child_behaviours().is_empty()) { + set_status(Fail); + ERR_FAIL_EDMSG("BehaviourInvertResult executed with no children"); + } else if (get_status() == Running) { + Status child_status{ get_child_behaviours().get(0)->get_status() }; + switch (child_status) { + case Fail: + set_status(Success); + return; + case Success: + set_status(Fail); + return; + case Running: + set_status(Running); + return; + } + } +} + +BehaviourNode *BehaviourInvertResult::get_next() { + return get_status() == Running + ? get_child_behaviours().get(0) + : cast_to(get_parent()); +} diff --git a/modules/behaviour_nodes/decorator_nodes.h b/modules/behaviour_nodes/decorator_nodes.h index fc95249a8d..96ac7f7ec7 100644 --- a/modules/behaviour_nodes/decorator_nodes.h +++ b/modules/behaviour_nodes/decorator_nodes.h @@ -6,10 +6,21 @@ class BehaviourAlwaysSuccess : public BehaviourComposite { GDCLASS(BehaviourAlwaysSuccess, BehaviourComposite); - static void _bind_methods(); + static void _bind_methods() {} public: PackedStringArray get_configuration_warnings() const override; void execute() override; BehaviourNode *get_next() override; }; + +class BehaviourInvertResult : public BehaviourComposite { + GDCLASS(BehaviourInvertResult, BehaviourComposite); + static void _bind_methods() {} + +public: + PackedStringArray get_configuration_warnings() const override; + void enter() override; + void execute() override; + BehaviourNode *get_next() override; +}; diff --git a/modules/behaviour_nodes/register_types.cpp b/modules/behaviour_nodes/register_types.cpp index ffb0aea7e9..cea03f315f 100644 --- a/modules/behaviour_nodes/register_types.cpp +++ b/modules/behaviour_nodes/register_types.cpp @@ -18,6 +18,7 @@ void initialize_behaviour_nodes_module(ModuleInitializationLevel p_level) { ClassDB::register_class(); ClassDB::register_class(); ClassDB::register_class(); + ClassDB::register_class(); } void uninitialize_behaviour_nodes_module(ModuleInitializationLevel p_level) {