Refactor to return enum instead of int in task methods

This commit is contained in:
Serhii Snitsaruk 2023-09-19 13:43:26 +02:00
parent 50bcbcf616
commit efe693347e
77 changed files with 121 additions and 106 deletions

View File

@ -35,7 +35,7 @@ String BTCheckTrigger::_generate_name() const {
return "CheckTrigger " + LimboUtility::get_singleton()->decorate_var(variable); return "CheckTrigger " + LimboUtility::get_singleton()->decorate_var(variable);
} }
int BTCheckTrigger::_tick(double p_delta) { BT::Status BTCheckTrigger::_tick(double p_delta) {
ERR_FAIL_COND_V_MSG(variable.is_empty(), FAILURE, "BBCheckVar: `variable` is not set."); ERR_FAIL_COND_V_MSG(variable.is_empty(), FAILURE, "BBCheckVar: `variable` is not set.");
Variant trigger_value = get_blackboard()->get_var(variable, false); Variant trigger_value = get_blackboard()->get_var(variable, false);
if (trigger_value == Variant(true)) { if (trigger_value == Variant(true)) {

View File

@ -27,7 +27,7 @@ protected:
static void _bind_methods(); static void _bind_methods();
virtual String _generate_name() const override; virtual String _generate_name() const override;
virtual int _tick(double p_delta) override; virtual Status _tick(double p_delta) override;
public: public:
void set_variable(String p_variable); void set_variable(String p_variable);

View File

@ -54,7 +54,7 @@ String BTCheckVar::_generate_name() const {
value.is_valid() ? Variant(value) : Variant("???")); value.is_valid() ? Variant(value) : Variant("???"));
} }
int BTCheckVar::_tick(double p_delta) { BT::Status BTCheckVar::_tick(double p_delta) {
ERR_FAIL_COND_V_MSG(variable.is_empty(), FAILURE, "BTCheckVar: `variable` is not set."); ERR_FAIL_COND_V_MSG(variable.is_empty(), FAILURE, "BTCheckVar: `variable` is not set.");
ERR_FAIL_COND_V_MSG(!value.is_valid(), FAILURE, "BTCheckVar: `value` is not set."); ERR_FAIL_COND_V_MSG(!value.is_valid(), FAILURE, "BTCheckVar: `value` is not set.");

View File

@ -30,7 +30,7 @@ protected:
static void _bind_methods(); static void _bind_methods();
virtual String _generate_name() const override; virtual String _generate_name() const override;
virtual int _tick(double p_delta) override; virtual Status _tick(double p_delta) override;
public: public:
virtual PackedStringArray get_configuration_warnings() const override; virtual PackedStringArray get_configuration_warnings() const override;

View File

@ -24,7 +24,7 @@ String BTSetVar::_generate_name() const {
value.is_valid() ? Variant(value) : Variant("???")); value.is_valid() ? Variant(value) : Variant("???"));
} }
int BTSetVar::_tick(double p_delta) { BT::Status BTSetVar::_tick(double p_delta) {
ERR_FAIL_COND_V_MSG(variable.is_empty(), FAILURE, "BTSetVar: `variable` is not set."); ERR_FAIL_COND_V_MSG(variable.is_empty(), FAILURE, "BTSetVar: `variable` is not set.");
ERR_FAIL_COND_V_MSG(!value.is_valid(), FAILURE, "BTSetVar: `value` is not set."); ERR_FAIL_COND_V_MSG(!value.is_valid(), FAILURE, "BTSetVar: `value` is not set.");
Variant error_result = SNAME("Error: BTSetVar failed to get value!"); Variant error_result = SNAME("Error: BTSetVar failed to get value!");

View File

@ -30,7 +30,7 @@ protected:
static void _bind_methods(); static void _bind_methods();
virtual String _generate_name() const override; virtual String _generate_name() const override;
virtual int _tick(double p_delta) override; virtual Status _tick(double p_delta) override;
public: public:
virtual PackedStringArray get_configuration_warnings() const override; virtual PackedStringArray get_configuration_warnings() const override;

View File

@ -26,6 +26,13 @@
#include "core/templates/hash_map.h" #include "core/templates/hash_map.h"
#include "core/variant/variant.h" #include "core/variant/variant.h"
void BT::_bind_methods() {
BIND_ENUM_CONSTANT(FRESH);
BIND_ENUM_CONSTANT(RUNNING);
BIND_ENUM_CONSTANT(FAILURE);
BIND_ENUM_CONSTANT(SUCCESS);
}
String BTTask::_generate_name() const { String BTTask::_generate_name() const {
if (get_script_instance()) { if (get_script_instance()) {
if (get_script_instance()->has_method(LimboStringNames::get_singleton()->_generate_name)) { if (get_script_instance()->has_method(LimboStringNames::get_singleton()->_generate_name)) {
@ -149,7 +156,7 @@ Ref<BTTask> BTTask::clone() const {
return inst; return inst;
} }
int BTTask::execute(double p_delta) { BT::Status BTTask::execute(double p_delta) {
if (data.status != RUNNING) { if (data.status != RUNNING) {
// Reset children status. // Reset children status.
if (data.status != FRESH) { if (data.status != FRESH) {
@ -340,12 +347,6 @@ void BTTask::_bind_methods() {
GDVIRTUAL_BIND(_tick, "p_delta"); GDVIRTUAL_BIND(_tick, "p_delta");
GDVIRTUAL_BIND(_generate_name); GDVIRTUAL_BIND(_generate_name);
GDVIRTUAL_BIND(_get_configuration_warning); GDVIRTUAL_BIND(_get_configuration_warning);
// Enums.
ClassDB::bind_integer_constant(get_class_static(), "TaskStatus", "FRESH", FRESH);
ClassDB::bind_integer_constant(get_class_static(), "TaskStatus", "RUNNING", RUNNING);
ClassDB::bind_integer_constant(get_class_static(), "TaskStatus", "FAILURE", FAILURE);
ClassDB::bind_integer_constant(get_class_static(), "TaskStatus", "SUCCESS", SUCCESS);
} }
BTTask::BTTask() { BTTask::BTTask() {

View File

@ -25,17 +25,31 @@
#include "core/variant/dictionary.h" #include "core/variant/dictionary.h"
#include "scene/resources/texture.h" #include "scene/resources/texture.h"
class BTTask : public Resource { /**
GDCLASS(BTTask, Resource); * Base class for BTTask.
* Note: In order to properly return Status in the _tick virtual method (GDVIRTUAL1R...)
* we must do VARIANT_ENUM_CAST for Status enum before the actual BTTask class declaration.
*/
class BT : public Resource {
GDCLASS(BT, Resource);
public: public:
enum TaskStatus { enum Status {
FRESH, FRESH,
RUNNING, RUNNING,
FAILURE, FAILURE,
SUCCESS, SUCCESS,
}; };
protected:
static void _bind_methods();
};
VARIANT_ENUM_CAST(BT::Status)
class BTTask : public BT {
GDCLASS(BTTask, BT);
private: private:
friend class BehaviorTree; friend class BehaviorTree;
@ -46,7 +60,7 @@ private:
Ref<Blackboard> blackboard; Ref<Blackboard> blackboard;
BTTask *parent; BTTask *parent;
Vector<Ref<BTTask>> children; Vector<Ref<BTTask>> children;
int status; Status status;
double elapsed; double elapsed;
} data; } data;
@ -60,13 +74,13 @@ protected:
virtual void _setup() {} virtual void _setup() {}
virtual void _enter() {} virtual void _enter() {}
virtual void _exit() {} virtual void _exit() {}
virtual int _tick(double p_delta) { return FAILURE; } virtual Status _tick(double p_delta) { return FAILURE; }
GDVIRTUAL0RC(String, _generate_name); GDVIRTUAL0RC(String, _generate_name);
GDVIRTUAL0(_setup); GDVIRTUAL0(_setup);
GDVIRTUAL0(_enter); GDVIRTUAL0(_enter);
GDVIRTUAL0(_exit); GDVIRTUAL0(_exit);
GDVIRTUAL1R(int, _tick, double); GDVIRTUAL1R(Status, _tick, double);
GDVIRTUAL0RC(PackedStringArray, _get_configuration_warning); GDVIRTUAL0RC(PackedStringArray, _get_configuration_warning);
public: public:
@ -88,9 +102,9 @@ public:
virtual void initialize(Node *p_agent, const Ref<Blackboard> &p_blackboard); virtual void initialize(Node *p_agent, const Ref<Blackboard> &p_blackboard);
virtual PackedStringArray get_configuration_warnings() const; virtual PackedStringArray get_configuration_warnings() const;
int execute(double p_delta); Status execute(double p_delta);
void cancel(); void cancel();
int get_status() const { return data.status; } Status get_status() const { return data.status; }
double get_elapsed_time() const { return data.elapsed; }; double get_elapsed_time() const { return data.elapsed; };
Ref<BTTask> get_child(int p_idx) const; Ref<BTTask> get_child(int p_idx) const;
@ -111,6 +125,4 @@ public:
~BTTask(); ~BTTask();
}; };
VARIANT_ENUM_CAST(BTTask::TaskStatus)
#endif // BTTASK_H #endif // BTTASK_H

View File

@ -15,8 +15,8 @@ void BTDynamicSelector::_enter() {
last_running_idx = 0; last_running_idx = 0;
} }
int BTDynamicSelector::_tick(double p_delta) { BT::Status BTDynamicSelector::_tick(double p_delta) {
int status = SUCCESS; Status status = SUCCESS;
int i; int i;
for (i = 0; i < get_child_count(); i++) { for (i = 0; i < get_child_count(); i++) {
status = get_child(i)->execute(p_delta); status = get_child(i)->execute(p_delta);

View File

@ -23,7 +23,7 @@ private:
protected: protected:
virtual void _enter() override; virtual void _enter() override;
virtual int _tick(double p_delta) override; virtual Status _tick(double p_delta) override;
}; };
#endif // BT_DYNAMIC_SELECTOR_H #endif // BT_DYNAMIC_SELECTOR_H

View File

@ -15,8 +15,8 @@ void BTDynamicSequence::_enter() {
last_running_idx = 0; last_running_idx = 0;
} }
int BTDynamicSequence::_tick(double p_delta) { BT::Status BTDynamicSequence::_tick(double p_delta) {
int status = SUCCESS; Status status = SUCCESS;
int i; int i;
for (i = 0; i < get_child_count(); i++) { for (i = 0; i < get_child_count(); i++) {
status = get_child(i)->execute(p_delta); status = get_child(i)->execute(p_delta);

View File

@ -23,7 +23,7 @@ private:
protected: protected:
virtual void _enter() override; virtual void _enter() override;
virtual int _tick(double p_delta) override; virtual Status _tick(double p_delta) override;
}; };
#endif // BT_DYNAMIC_SEQUENCE_H #endif // BT_DYNAMIC_SEQUENCE_H

View File

@ -19,12 +19,12 @@ void BTParallel::_enter() {
} }
} }
int BTParallel::_tick(double p_delta) { BT::Status BTParallel::_tick(double p_delta) {
int num_succeeded = 0; int num_succeeded = 0;
int num_failed = 0; int num_failed = 0;
int return_status = RUNNING; BT::Status return_status = RUNNING;
for (int i = 0; i < get_child_count(); i++) { for (int i = 0; i < get_child_count(); i++) {
int status = 0; Status status = BT::FRESH;
Ref<BTTask> child = get_child(i); Ref<BTTask> child = get_child(i);
if (!repeat && (child->get_status() == FAILURE || child->get_status() == SUCCESS)) { if (!repeat && (child->get_status() == FAILURE || child->get_status() == SUCCESS)) {
status = child->get_status(); status = child->get_status();

View File

@ -27,7 +27,7 @@ protected:
static void _bind_methods(); static void _bind_methods();
virtual void _enter() override; virtual void _enter() override;
virtual int _tick(double p_delta) override; virtual Status _tick(double p_delta) override;
public: public:
int get_num_successes_required() const { return num_successes_required; } int get_num_successes_required() const { return num_successes_required; }

View File

@ -22,8 +22,8 @@ void BTRandomSelector::_enter() {
indicies.shuffle(); indicies.shuffle();
} }
int BTRandomSelector::_tick(double p_delta) { BT::Status BTRandomSelector::_tick(double p_delta) {
int status = FAILURE; Status status = FAILURE;
for (int i = last_running_idx; i < get_child_count(); i++) { for (int i = last_running_idx; i < get_child_count(); i++) {
status = get_child(indicies[i])->execute(p_delta); status = get_child(indicies[i])->execute(p_delta);
if (status != FAILURE) { if (status != FAILURE) {

View File

@ -26,6 +26,6 @@ private:
protected: protected:
virtual void _enter() override; virtual void _enter() override;
virtual int _tick(double p_delta) override; virtual Status _tick(double p_delta) override;
}; };
#endif // BT_RANDOM_SELECTOR_H #endif // BT_RANDOM_SELECTOR_H

View File

@ -22,8 +22,8 @@ void BTRandomSequence::_enter() {
indicies.shuffle(); indicies.shuffle();
} }
int BTRandomSequence::_tick(double p_delta) { BT::Status BTRandomSequence::_tick(double p_delta) {
int status = SUCCESS; Status status = SUCCESS;
for (int i = last_running_idx; i < get_child_count(); i++) { for (int i = last_running_idx; i < get_child_count(); i++) {
status = get_child(indicies[i])->execute(p_delta); status = get_child(indicies[i])->execute(p_delta);
if (status != SUCCESS) { if (status != SUCCESS) {

View File

@ -26,6 +26,6 @@ private:
protected: protected:
virtual void _enter() override; virtual void _enter() override;
virtual int _tick(double p_delta) override; virtual Status _tick(double p_delta) override;
}; };
#endif // BT_RANDOM_SEQUENCE_H #endif // BT_RANDOM_SEQUENCE_H

View File

@ -15,8 +15,8 @@ void BTSelector::_enter() {
last_running_idx = 0; last_running_idx = 0;
} }
int BTSelector::_tick(double p_delta) { BT::Status BTSelector::_tick(double p_delta) {
int status = FAILURE; Status status = FAILURE;
for (int i = last_running_idx; i < get_child_count(); i++) { for (int i = last_running_idx; i < get_child_count(); i++) {
status = get_child(i)->execute(p_delta); status = get_child(i)->execute(p_delta);
if (status != FAILURE) { if (status != FAILURE) {

View File

@ -23,6 +23,6 @@ private:
protected: protected:
virtual void _enter() override; virtual void _enter() override;
virtual int _tick(double p_delta) override; virtual Status _tick(double p_delta) override;
}; };
#endif // BT_SELECTOR_H #endif // BT_SELECTOR_H

View File

@ -15,8 +15,8 @@ void BTSequence::_enter() {
last_running_idx = 0; last_running_idx = 0;
} }
int BTSequence::_tick(double p_delta) { BT::Status BTSequence::_tick(double p_delta) {
int status = SUCCESS; Status status = SUCCESS;
for (int i = last_running_idx; i < get_child_count(); i++) { for (int i = last_running_idx; i < get_child_count(); i++) {
status = get_child(i)->execute(p_delta); status = get_child(i)->execute(p_delta);
if (status != SUCCESS) { if (status != SUCCESS) {

View File

@ -23,7 +23,7 @@ private:
protected: protected:
virtual void _enter() override; virtual void _enter() override;
virtual int _tick(double p_delta) override; virtual Status _tick(double p_delta) override;
}; };
#endif // BT_SEQUENCE_H #endif // BT_SEQUENCE_H

View File

@ -11,7 +11,7 @@
#include "bt_always_fail.h" #include "bt_always_fail.h"
int BTAlwaysFail::_tick(double p_delta) { BT::Status BTAlwaysFail::_tick(double p_delta) {
if (get_child_count() > 0 && get_child(0)->execute(p_delta) == RUNNING) { if (get_child_count() > 0 && get_child(0)->execute(p_delta) == RUNNING) {
return RUNNING; return RUNNING;
} }

View File

@ -19,7 +19,7 @@ class BTAlwaysFail : public BTDecorator {
TASK_CATEGORY(Decorators); TASK_CATEGORY(Decorators);
protected: protected:
virtual int _tick(double p_delta) override; virtual Status _tick(double p_delta) override;
}; };
#endif // BT_ALWAYS_FAIL_H #endif // BT_ALWAYS_FAIL_H

View File

@ -11,7 +11,7 @@
#include "bt_always_succeed.h" #include "bt_always_succeed.h"
int BTAlwaysSucceed::_tick(double p_delta) { BT::Status BTAlwaysSucceed::_tick(double p_delta) {
if (get_child_count() > 0 && get_child(0)->execute(p_delta) == RUNNING) { if (get_child_count() > 0 && get_child(0)->execute(p_delta) == RUNNING) {
return RUNNING; return RUNNING;
} }

View File

@ -19,7 +19,7 @@ class BTAlwaysSucceed : public BTDecorator {
TASK_CATEGORY(Decorators); TASK_CATEGORY(Decorators);
protected: protected:
virtual int _tick(double p_delta) override; virtual Status _tick(double p_delta) override;
}; };
#endif // BT_ALWAYS_SUCCEED_H #endif // BT_ALWAYS_SUCCEED_H

View File

@ -59,12 +59,12 @@ void BTCooldown::_setup() {
} }
} }
int BTCooldown::_tick(double p_delta) { BT::Status BTCooldown::_tick(double p_delta) {
ERR_FAIL_COND_V_MSG(get_child_count() == 0, FAILURE, "BT decorator has no child."); ERR_FAIL_COND_V_MSG(get_child_count() == 0, FAILURE, "BT decorator has no child.");
if (get_blackboard()->get_var(cooldown_state_var, true)) { if (get_blackboard()->get_var(cooldown_state_var, true)) {
return FAILURE; return FAILURE;
} }
int status = get_child(0)->execute(p_delta); Status status = get_child(0)->execute(p_delta);
if (status == SUCCESS || (trigger_on_failure && status == FAILURE)) { if (status == SUCCESS || (trigger_on_failure && status == FAILURE)) {
_chill(); _chill();
} }

View File

@ -37,7 +37,7 @@ protected:
virtual String _generate_name() const override; virtual String _generate_name() const override;
virtual void _setup() override; virtual void _setup() override;
virtual int _tick(double p_delta) override; virtual Status _tick(double p_delta) override;
public: public:
void set_duration(double p_value); void set_duration(double p_value);

View File

@ -27,7 +27,7 @@ String BTDelay::_generate_name() const {
return vformat("Delay %s sec", Math::snapped(seconds, 0.001)); return vformat("Delay %s sec", Math::snapped(seconds, 0.001));
} }
int BTDelay::_tick(double p_delta) { BT::Status BTDelay::_tick(double p_delta) {
ERR_FAIL_COND_V_MSG(get_child_count() == 0, FAILURE, "BT decorator has no child."); ERR_FAIL_COND_V_MSG(get_child_count() == 0, FAILURE, "BT decorator has no child.");
if (get_elapsed_time() <= seconds) { if (get_elapsed_time() <= seconds) {
return RUNNING; return RUNNING;

View File

@ -25,7 +25,7 @@ protected:
static void _bind_methods(); static void _bind_methods();
virtual String _generate_name() const override; virtual String _generate_name() const override;
virtual int _tick(double p_delta) override; virtual Status _tick(double p_delta) override;
public: public:
void set_seconds(double p_value); void set_seconds(double p_value);

View File

@ -42,7 +42,7 @@ void BTForEach::_enter() {
current_idx = 0; current_idx = 0;
} }
int BTForEach::_tick(double p_delta) { BT::Status BTForEach::_tick(double p_delta) {
ERR_FAIL_COND_V_MSG(get_child_count() == 0, FAILURE, "ForEach decorator has no child."); ERR_FAIL_COND_V_MSG(get_child_count() == 0, FAILURE, "ForEach decorator has no child.");
ERR_FAIL_COND_V_MSG(save_var.is_empty(), FAILURE, "ForEach save variable is not set."); ERR_FAIL_COND_V_MSG(save_var.is_empty(), FAILURE, "ForEach save variable is not set.");
ERR_FAIL_COND_V_MSG(array_var.is_empty(), FAILURE, "ForEach array variable is not set."); ERR_FAIL_COND_V_MSG(array_var.is_empty(), FAILURE, "ForEach array variable is not set.");
@ -54,7 +54,7 @@ int BTForEach::_tick(double p_delta) {
Variant elem = arr.get(current_idx); Variant elem = arr.get(current_idx);
get_blackboard()->set_var(save_var, elem); get_blackboard()->set_var(save_var, elem);
int status = get_child(0)->execute(p_delta); Status status = get_child(0)->execute(p_delta);
if (status == RUNNING) { if (status == RUNNING) {
return RUNNING; return RUNNING;
} else if (status == FAILURE) { } else if (status == FAILURE) {

View File

@ -29,7 +29,7 @@ protected:
virtual String _generate_name() const override; virtual String _generate_name() const override;
virtual void _enter() override; virtual void _enter() override;
virtual int _tick(double p_delta) override; virtual Status _tick(double p_delta) override;
public: public:
void set_array_var(String p_value); void set_array_var(String p_value);

View File

@ -11,9 +11,9 @@
#include "bt_invert.h" #include "bt_invert.h"
int BTInvert::_tick(double p_delta) { BT::Status BTInvert::_tick(double p_delta) {
ERR_FAIL_COND_V_MSG(get_child_count() == 0, FAILURE, "BT decorator has no child."); ERR_FAIL_COND_V_MSG(get_child_count() == 0, FAILURE, "BT decorator has no child.");
int status = get_child(0)->execute(p_delta); Status status = get_child(0)->execute(p_delta);
if (status == SUCCESS) { if (status == SUCCESS) {
status = FAILURE; status = FAILURE;
} else if (status == FAILURE) { } else if (status == FAILURE) {

View File

@ -19,7 +19,7 @@ class BTInvert : public BTDecorator {
TASK_CATEGORY(Decorators); TASK_CATEGORY(Decorators);
protected: protected:
virtual int _tick(double p_delta) override; virtual Status _tick(double p_delta) override;
}; };
#endif // BT_INVERT_H #endif // BT_INVERT_H

View File

@ -29,7 +29,7 @@ void BTNewScope::initialize(Node *p_agent, const Ref<Blackboard> &p_blackboard)
BTDecorator::initialize(p_agent, bb); BTDecorator::initialize(p_agent, bb);
} }
int BTNewScope::_tick(double p_delta) { BT::Status BTNewScope::_tick(double p_delta) {
ERR_FAIL_COND_V_MSG(get_child_count() == 0, FAILURE, "BT decorator has no child."); ERR_FAIL_COND_V_MSG(get_child_count() == 0, FAILURE, "BT decorator has no child.");
return get_child(0)->execute(p_delta); return get_child(0)->execute(p_delta);
} }

View File

@ -27,7 +27,7 @@ protected:
void _set_blackboard_data(const Dictionary &p_value) { blackboard_data = p_value; } void _set_blackboard_data(const Dictionary &p_value) { blackboard_data = p_value; }
Dictionary _get_blackboard_data() const { return blackboard_data; } Dictionary _get_blackboard_data() const { return blackboard_data; }
virtual int _tick(double p_delta) override; virtual Status _tick(double p_delta) override;
public: public:
virtual void initialize(Node *p_agent, const Ref<Blackboard> &p_blackboard) override; virtual void initialize(Node *p_agent, const Ref<Blackboard> &p_blackboard) override;

View File

@ -20,7 +20,7 @@ String BTProbability::_generate_name() const {
return vformat("Probability %.1f%%", run_chance); return vformat("Probability %.1f%%", run_chance);
} }
int BTProbability::_tick(double p_delta) { BT::Status BTProbability::_tick(double p_delta) {
ERR_FAIL_COND_V_MSG(get_child_count() == 0, FAILURE, "BT decorator has no child."); ERR_FAIL_COND_V_MSG(get_child_count() == 0, FAILURE, "BT decorator has no child.");
if (get_child(0)->get_status() == RUNNING || Math::randf() <= run_chance) { if (get_child(0)->get_status() == RUNNING || Math::randf() <= run_chance) {
return get_child(0)->execute(p_delta); return get_child(0)->execute(p_delta);

View File

@ -25,7 +25,7 @@ protected:
static void _bind_methods(); static void _bind_methods();
virtual String _generate_name() const override; virtual String _generate_name() const override;
virtual int _tick(double p_delta) override; virtual Status _tick(double p_delta) override;
public: public:
void set_run_chance(float p_value); void set_run_chance(float p_value);

View File

@ -31,9 +31,9 @@ void BTRepeat::_enter() {
cur_iteration = 1; cur_iteration = 1;
} }
int BTRepeat::_tick(double p_delta) { BT::Status BTRepeat::_tick(double p_delta) {
ERR_FAIL_COND_V_MSG(get_child_count() == 0, FAILURE, "BT decorator has no child."); ERR_FAIL_COND_V_MSG(get_child_count() == 0, FAILURE, "BT decorator has no child.");
int status = get_child(0)->execute(p_delta); Status status = get_child(0)->execute(p_delta);
if (status == RUNNING || forever) { if (status == RUNNING || forever) {
return RUNNING; return RUNNING;
} else if (status == FAILURE && abort_on_failure) { } else if (status == FAILURE && abort_on_failure) {

View File

@ -31,7 +31,7 @@ protected:
virtual String _generate_name() const override; virtual String _generate_name() const override;
virtual void _enter() override; virtual void _enter() override;
virtual int _tick(double p_delta) override; virtual Status _tick(double p_delta) override;
public: public:
void set_forever(bool p_forever); void set_forever(bool p_forever);

View File

@ -11,7 +11,7 @@
#include "bt_repeat_until_failure.h" #include "bt_repeat_until_failure.h"
int BTRepeatUntilFailure::_tick(double p_delta) { BT::Status BTRepeatUntilFailure::_tick(double p_delta) {
ERR_FAIL_COND_V_MSG(get_child_count() == 0, FAILURE, "BT decorator has no child."); ERR_FAIL_COND_V_MSG(get_child_count() == 0, FAILURE, "BT decorator has no child.");
if (get_child(0)->execute(p_delta) == FAILURE) { if (get_child(0)->execute(p_delta) == FAILURE) {
return SUCCESS; return SUCCESS;

View File

@ -19,7 +19,7 @@ class BTRepeatUntilFailure : public BTDecorator {
TASK_CATEGORY(Decorators); TASK_CATEGORY(Decorators);
protected: protected:
virtual int _tick(double p_delta) override; virtual Status _tick(double p_delta) override;
}; };
#endif // BT_REPEAT_UNTIL_FAILURE_H #endif // BT_REPEAT_UNTIL_FAILURE_H

View File

@ -11,7 +11,7 @@
#include "bt_repeat_until_success.h" #include "bt_repeat_until_success.h"
int BTRepeatUntilSuccess::_tick(double p_delta) { BT::Status BTRepeatUntilSuccess::_tick(double p_delta) {
ERR_FAIL_COND_V_MSG(get_child_count() == 0, FAILURE, "BT decorator has no child."); ERR_FAIL_COND_V_MSG(get_child_count() == 0, FAILURE, "BT decorator has no child.");
if (get_child(0)->execute(p_delta) == SUCCESS) { if (get_child(0)->execute(p_delta) == SUCCESS) {
return SUCCESS; return SUCCESS;

View File

@ -19,7 +19,7 @@ class BTRepeatUntilSuccess : public BTDecorator {
TASK_CATEGORY(Decorators); TASK_CATEGORY(Decorators);
protected: protected:
virtual int _tick(double p_delta) override; virtual Status _tick(double p_delta) override;
}; };
#endif // BT_REPEAT_UNTIL_SUCCESS_H #endif // BT_REPEAT_UNTIL_SUCCESS_H

View File

@ -20,7 +20,7 @@ String BTRunLimit::_generate_name() const {
return vformat("RunLimit x%d", run_limit); return vformat("RunLimit x%d", run_limit);
} }
int BTRunLimit::_tick(double p_delta) { BT::Status BTRunLimit::_tick(double p_delta) {
ERR_FAIL_COND_V_MSG(get_child_count() == 0, FAILURE, "BT decorator has no child."); ERR_FAIL_COND_V_MSG(get_child_count() == 0, FAILURE, "BT decorator has no child.");
if (get_child(0)->get_status() != RUNNING) { if (get_child(0)->get_status() != RUNNING) {
if (num_runs >= run_limit) { if (num_runs >= run_limit) {

View File

@ -26,7 +26,7 @@ protected:
static void _bind_methods(); static void _bind_methods();
virtual String _generate_name() const override; virtual String _generate_name() const override;
virtual int _tick(double p_delta) override; virtual Status _tick(double p_delta) override;
public: public:
void set_run_limit(int p_value); void set_run_limit(int p_value);

View File

@ -46,7 +46,7 @@ void BTSubtree::initialize(Node *p_agent, const Ref<Blackboard> &p_blackboard) {
BTNewScope::initialize(p_agent, p_blackboard); BTNewScope::initialize(p_agent, p_blackboard);
} }
int BTSubtree::_tick(double p_delta) { BT::Status BTSubtree::_tick(double p_delta) {
ERR_FAIL_COND_V_MSG(get_child_count() == 0, FAILURE, "BT decorator doesn't have a child."); ERR_FAIL_COND_V_MSG(get_child_count() == 0, FAILURE, "BT decorator doesn't have a child.");
return get_child(0)->execute(p_delta); return get_child(0)->execute(p_delta);
} }

View File

@ -27,7 +27,7 @@ protected:
static void _bind_methods(); static void _bind_methods();
virtual String _generate_name() const override; virtual String _generate_name() const override;
virtual int _tick(double p_delta) override; virtual Status _tick(double p_delta) override;
public: public:
void set_subtree(const Ref<BehaviorTree> &p_value); void set_subtree(const Ref<BehaviorTree> &p_value);

View File

@ -22,9 +22,9 @@ String BTTimeLimit::_generate_name() const {
return vformat("TimeLimit %s sec", Math::snapped(time_limit, 0.001)); return vformat("TimeLimit %s sec", Math::snapped(time_limit, 0.001));
} }
int BTTimeLimit::_tick(double p_delta) { BT::Status BTTimeLimit::_tick(double p_delta) {
ERR_FAIL_COND_V_MSG(get_child_count() == 0, FAILURE, "BT decorator has no child."); ERR_FAIL_COND_V_MSG(get_child_count() == 0, FAILURE, "BT decorator has no child.");
int status = get_child(0)->execute(p_delta); Status status = get_child(0)->execute(p_delta);
if (status == RUNNING && get_elapsed_time() >= time_limit) { if (status == RUNNING && get_elapsed_time() >= time_limit) {
get_child(0)->cancel(); get_child(0)->cancel();
return FAILURE; return FAILURE;

View File

@ -25,7 +25,7 @@ protected:
static void _bind_methods(); static void _bind_methods();
virtual String _generate_name() const override; virtual String _generate_name() const override;
virtual int _tick(double p_delta) override; virtual Status _tick(double p_delta) override;
public: public:
void set_time_limit(double p_value); void set_time_limit(double p_value);

View File

@ -69,7 +69,7 @@ void BTAwaitAnimation::_setup() {
setup_failed = false; setup_failed = false;
} }
int BTAwaitAnimation::_tick(double p_delta) { BT::Status BTAwaitAnimation::_tick(double p_delta) {
ERR_FAIL_COND_V_MSG(setup_failed == true, FAILURE, "BTAwaitAnimation: _setup() failed - returning FAILURE."); ERR_FAIL_COND_V_MSG(setup_failed == true, FAILURE, "BTAwaitAnimation: _setup() failed - returning FAILURE.");
// ! Doing this check instead of using signal due to a bug in Godot: https://github.com/godotengine/godot/issues/76127 // ! Doing this check instead of using signal due to a bug in Godot: https://github.com/godotengine/godot/issues/76127

View File

@ -35,7 +35,7 @@ protected:
virtual String _generate_name() const override; virtual String _generate_name() const override;
virtual void _setup() override; virtual void _setup() override;
virtual int _tick(double p_delta) override; virtual Status _tick(double p_delta) override;
public: public:
void set_animation_player(Ref<BBNode> p_animation_player); void set_animation_player(Ref<BBNode> p_animation_player);

View File

@ -55,7 +55,7 @@ String BTCallMethod::_generate_name() const {
(node_param.is_valid() && !node_param->to_string().is_empty() ? node_param->to_string() : "???")); (node_param.is_valid() && !node_param->to_string().is_empty() ? node_param->to_string() : "???"));
} }
int BTCallMethod::_tick(double p_delta) { BT::Status BTCallMethod::_tick(double p_delta) {
ERR_FAIL_COND_V_MSG(method == StringName(), FAILURE, "BTCallMethod: Method Name is not set."); ERR_FAIL_COND_V_MSG(method == StringName(), FAILURE, "BTCallMethod: Method Name is not set.");
ERR_FAIL_COND_V_MSG(node_param.is_null(), FAILURE, "BTCallMethod: Node parameter is not set."); ERR_FAIL_COND_V_MSG(node_param.is_null(), FAILURE, "BTCallMethod: Node parameter is not set.");
Object *obj = node_param->get_value(get_agent(), get_blackboard()); Object *obj = node_param->get_value(get_agent(), get_blackboard());

View File

@ -29,7 +29,7 @@ protected:
static void _bind_methods(); static void _bind_methods();
virtual String _generate_name() const override; virtual String _generate_name() const override;
virtual int _tick(double p_delta) override; virtual Status _tick(double p_delta) override;
public: public:
void set_method(StringName p_method_name); void set_method(StringName p_method_name);

View File

@ -54,7 +54,7 @@ String BTCheckAgentProperty::_generate_name() const {
value.is_valid() ? Variant(value) : Variant("???")); value.is_valid() ? Variant(value) : Variant("???"));
} }
int BTCheckAgentProperty::_tick(double p_delta) { BT::Status BTCheckAgentProperty::_tick(double p_delta) {
ERR_FAIL_COND_V_MSG(property == StringName(), FAILURE, "BTCheckAgentProperty: `property` is not set."); ERR_FAIL_COND_V_MSG(property == StringName(), FAILURE, "BTCheckAgentProperty: `property` is not set.");
ERR_FAIL_COND_V_MSG(!value.is_valid(), FAILURE, "BTCheckAgentProperty: `value` is not set."); ERR_FAIL_COND_V_MSG(!value.is_valid(), FAILURE, "BTCheckAgentProperty: `value` is not set.");

View File

@ -32,7 +32,7 @@ protected:
static void _bind_methods(); static void _bind_methods();
virtual String _generate_name() const override; virtual String _generate_name() const override;
virtual int _tick(double p_delta) override; virtual Status _tick(double p_delta) override;
public: public:
void set_property(StringName p_prop); void set_property(StringName p_prop);

View File

@ -49,7 +49,7 @@ void BTPauseAnimation::_setup() {
setup_failed = false; setup_failed = false;
} }
int BTPauseAnimation::_tick(double p_delta) { BT::Status BTPauseAnimation::_tick(double p_delta) {
ERR_FAIL_COND_V_MSG(setup_failed == true, FAILURE, "BTPauseAnimation: _setup() failed - returning FAILURE."); ERR_FAIL_COND_V_MSG(setup_failed == true, FAILURE, "BTPauseAnimation: _setup() failed - returning FAILURE.");
animation_player->pause(); animation_player->pause();
return SUCCESS; return SUCCESS;

View File

@ -33,7 +33,7 @@ protected:
virtual String _generate_name() const override; virtual String _generate_name() const override;
virtual void _setup() override; virtual void _setup() override;
virtual int _tick(double p_delta) override; virtual Status _tick(double p_delta) override;
public: public:
void set_animation_player(Ref<BBNode> p_animation_player); void set_animation_player(Ref<BBNode> p_animation_player);

View File

@ -94,7 +94,7 @@ void BTPlayAnimation::_enter() {
} }
} }
int BTPlayAnimation::_tick(double p_delta) { BT::Status BTPlayAnimation::_tick(double p_delta) {
ERR_FAIL_COND_V_MSG(setup_failed == true, FAILURE, "BTPlayAnimation: _setup() failed - returning FAILURE."); ERR_FAIL_COND_V_MSG(setup_failed == true, FAILURE, "BTPlayAnimation: _setup() failed - returning FAILURE.");
// ! Doing this check instead of using signal due to a bug in Godot: https://github.com/godotengine/godot/issues/76127 // ! Doing this check instead of using signal due to a bug in Godot: https://github.com/godotengine/godot/issues/76127

View File

@ -39,7 +39,7 @@ protected:
virtual String _generate_name() const override; virtual String _generate_name() const override;
virtual void _setup() override; virtual void _setup() override;
virtual void _enter() override; virtual void _enter() override;
virtual int _tick(double p_delta) override; virtual Status _tick(double p_delta) override;
public: public:
void set_animation_player(Ref<BBNode> p_animation_player); void set_animation_player(Ref<BBNode> p_animation_player);

View File

@ -44,7 +44,7 @@ String BTSetAgentProperty::_generate_name() const {
value.is_valid() ? Variant(value) : Variant("???")); value.is_valid() ? Variant(value) : Variant("???"));
} }
int BTSetAgentProperty::_tick(double p_delta) { BT::Status BTSetAgentProperty::_tick(double p_delta) {
ERR_FAIL_COND_V_MSG(property == StringName(), FAILURE, "BTSetAgentProperty: `property` is not set."); ERR_FAIL_COND_V_MSG(property == StringName(), FAILURE, "BTSetAgentProperty: `property` is not set.");
ERR_FAIL_COND_V_MSG(!value.is_valid(), FAILURE, "BTSetAgentProperty: `value` is not set."); ERR_FAIL_COND_V_MSG(!value.is_valid(), FAILURE, "BTSetAgentProperty: `value` is not set.");

View File

@ -28,7 +28,7 @@ protected:
static void _bind_methods(); static void _bind_methods();
virtual String _generate_name() const override; virtual String _generate_name() const override;
virtual int _tick(double p_delta) override; virtual Status _tick(double p_delta) override;
public: public:
virtual PackedStringArray get_configuration_warnings() const override; virtual PackedStringArray get_configuration_warnings() const override;

View File

@ -64,7 +64,7 @@ void BTStopAnimation::_setup() {
setup_failed = false; setup_failed = false;
} }
int BTStopAnimation::_tick(double p_delta) { BT::Status BTStopAnimation::_tick(double p_delta) {
ERR_FAIL_COND_V_MSG(setup_failed == true, FAILURE, "BTStopAnimation: _setup() failed - returning FAILURE."); ERR_FAIL_COND_V_MSG(setup_failed == true, FAILURE, "BTStopAnimation: _setup() failed - returning FAILURE.");
if (animation_player->is_playing() && (animation_name == StringName() || animation_name == animation_player->get_assigned_animation())) { if (animation_player->is_playing() && (animation_name == StringName() || animation_name == animation_player->get_assigned_animation())) {
animation_player->stop(keep_state); animation_player->stop(keep_state);

View File

@ -35,7 +35,7 @@ protected:
virtual String _generate_name() const override; virtual String _generate_name() const override;
virtual void _setup() override; virtual void _setup() override;
virtual int _tick(double p_delta) override; virtual Status _tick(double p_delta) override;
public: public:
void set_animation_player(Ref<BBNode> p_animation_player); void set_animation_player(Ref<BBNode> p_animation_player);

View File

@ -29,7 +29,7 @@ String BTConsolePrint::_generate_name() const {
return vformat("ConsolePrint text: \"%s\"", tx); return vformat("ConsolePrint text: \"%s\"", tx);
} }
int BTConsolePrint::_tick(double p_delta) { BT::Status BTConsolePrint::_tick(double p_delta) {
switch (bb_format_parameters.size()) { switch (bb_format_parameters.size()) {
case 0: { case 0: {
print_line(text); print_line(text);

View File

@ -28,7 +28,7 @@ protected:
static void _bind_methods(); static void _bind_methods();
virtual String _generate_name() const override; virtual String _generate_name() const override;
virtual int _tick(double p_delta) override; virtual Status _tick(double p_delta) override;
public: public:
void set_text(String p_value) { void set_text(String p_value) {

View File

@ -11,6 +11,6 @@
#include "bt_fail.h" #include "bt_fail.h"
int BTFail::_tick(double p_delta) { BT::Status BTFail::_tick(double p_delta) {
return FAILURE; return FAILURE;
} }

View File

@ -19,7 +19,7 @@ class BTFail : public BTAction {
TASK_CATEGORY(Utility); TASK_CATEGORY(Utility);
protected: protected:
virtual int _tick(double p_delta) override; virtual Status _tick(double p_delta) override;
}; };
#endif // BT_FAIL_H #endif // BT_FAIL_H

View File

@ -23,7 +23,7 @@ void BTRandomWait::_enter() {
duration = Math::random(min_duration, max_duration); duration = Math::random(min_duration, max_duration);
} }
int BTRandomWait::_tick(double p_delta) { BT::Status BTRandomWait::_tick(double p_delta) {
if (get_elapsed_time() < duration) { if (get_elapsed_time() < duration) {
return RUNNING; return RUNNING;
} else { } else {

View File

@ -29,7 +29,7 @@ protected:
virtual String _generate_name() const override; virtual String _generate_name() const override;
virtual void _enter() override; virtual void _enter() override;
virtual int _tick(double p_delta) override; virtual Status _tick(double p_delta) override;
public: public:
void set_min_duration(double p_max_duration); void set_min_duration(double p_max_duration);

View File

@ -20,7 +20,7 @@ String BTWait::_generate_name() const {
return vformat("Wait %s sec", Math::snapped(duration, 0.001)); return vformat("Wait %s sec", Math::snapped(duration, 0.001));
} }
int BTWait::_tick(double p_delta) { BT::Status BTWait::_tick(double p_delta) {
if (get_elapsed_time() < duration) { if (get_elapsed_time() < duration) {
return RUNNING; return RUNNING;
} else { } else {

View File

@ -25,7 +25,7 @@ protected:
static void _bind_methods(); static void _bind_methods();
virtual String _generate_name() const override; virtual String _generate_name() const override;
virtual int _tick(double p_delta) override; virtual Status _tick(double p_delta) override;
public: public:
void set_duration(double p_value) { void set_duration(double p_value) {

View File

@ -22,7 +22,7 @@ void BTWaitTicks::_enter() {
num_passed = 0; num_passed = 0;
} }
int BTWaitTicks::_tick(double p_delta) { BT::Status BTWaitTicks::_tick(double p_delta) {
if (num_passed < num_ticks) { if (num_passed < num_ticks) {
num_passed += 1; num_passed += 1;
return RUNNING; return RUNNING;

View File

@ -28,7 +28,7 @@ protected:
virtual String _generate_name() const override; virtual String _generate_name() const override;
virtual void _enter() override; virtual void _enter() override;
virtual int _tick(double p_delta) override; virtual Status _tick(double p_delta) override;
public: public:
void set_num_ticks(int p_value) { void set_num_ticks(int p_value) {

View File

@ -57,6 +57,7 @@ def get_doc_classes():
"BehaviorTree", "BehaviorTree",
"BehaviorTreeView", "BehaviorTreeView",
"Blackboard", "Blackboard",
"BT",
"BTAction", "BTAction",
"BTAlwaysFail", "BTAlwaysFail",
"BTAlwaysSucceed", "BTAlwaysSucceed",

View File

@ -117,6 +117,7 @@ void initialize_limboai_module(ModuleInitializationLevel p_level) {
GDREGISTER_CLASS(LimboState); GDREGISTER_CLASS(LimboState);
GDREGISTER_CLASS(LimboHSM); GDREGISTER_CLASS(LimboHSM);
GDREGISTER_ABSTRACT_CLASS(BT);
GDREGISTER_ABSTRACT_CLASS(BTTask); GDREGISTER_ABSTRACT_CLASS(BTTask);
GDREGISTER_CLASS(BehaviorTree); GDREGISTER_CLASS(BehaviorTree);
GDREGISTER_CLASS(BTPlayer); GDREGISTER_CLASS(BTPlayer);

View File

@ -37,7 +37,7 @@ class BTTestAction : public BTAction {
GDCLASS(BTTestAction, BTAction); GDCLASS(BTTestAction, BTAction);
public: public:
int ret_status = BTTask::SUCCESS; Status ret_status = BTTask::SUCCESS;
int num_entries = 0; int num_entries = 0;
int num_ticks = 0; int num_ticks = 0;
int num_exits = 0; int num_exits = 0;
@ -46,15 +46,15 @@ protected:
virtual void _enter() override { num_entries += 1; } virtual void _enter() override { num_entries += 1; }
virtual void _exit() override { num_exits += 1; } virtual void _exit() override { num_exits += 1; }
virtual int _tick(double p_delta) override { virtual Status _tick(double p_delta) override {
num_ticks += 1; num_ticks += 1;
return ret_status; return ret_status;
} }
public: public:
bool is_status_either(int p_status1, int p_status2) { return (get_status() == p_status1 || get_status() == p_status2); } bool is_status_either(Status p_status1, Status p_status2) { return (get_status() == p_status1 || get_status() == p_status2); }
BTTestAction(int p_return_status) { ret_status = p_return_status; } BTTestAction(Status p_return_status) { ret_status = p_return_status; }
BTTestAction() {} BTTestAction() {}
}; };