diff --git a/bt/decorators/bt_for_each.cpp b/bt/decorators/bt_for_each.cpp new file mode 100644 index 0000000..5ff038c --- /dev/null +++ b/bt/decorators/bt_for_each.cpp @@ -0,0 +1,53 @@ +/* bt_for_each.cpp */ + +#include "bt_for_each.h" +#include "core/error_list.h" +#include "core/error_macros.h" +#include "core/variant.h" +#include "modules/limboai/blackboard.h" +#include "modules/limboai/limbo_utility.h" + +String BTForEach::_generate_name() const { + return vformat("ForEach %s in %s", + LimboUtility::get_singleton()->decorate_var(save_var), + LimboUtility::get_singleton()->decorate_var(array_var)); +} + +void BTForEach::_enter() { + current_idx = 0; +} + +int BTForEach::_tick(float p_delta) { + ERR_FAIL_COND_V_MSG(get_child_count() == 0, FAILURE, "ForEach decorator has no child."); + ERR_FAIL_COND_V_MSG(save_var.empty(), FAILURE, "ForEach save variable is not set."); + ERR_FAIL_COND_V_MSG(array_var.empty(), FAILURE, "ForEach array variable is not set."); + + Array arr = get_blackboard()->get_var(array_var, Variant()); + if (arr.size() == 0) { + return SUCCESS; + } + Variant elem = arr.get(current_idx); + get_blackboard()->set_var(save_var, elem); + + int status = get_child(0)->execute(p_delta); + if (status == RUNNING) { + return RUNNING; + } else if (status == FAILURE) { + return FAILURE; + } else if (current_idx == (arr.size() - 1)) { + return SUCCESS; + } else { + current_idx += 1; + return RUNNING; + } +} + +void BTForEach::_bind_methods() { + ClassDB::bind_method(D_METHOD("set_array_var", "p_variable"), &BTForEach::set_array_var); + ClassDB::bind_method(D_METHOD("get_array_var"), &BTForEach::get_array_var); + ClassDB::bind_method(D_METHOD("set_save_var", "p_variable"), &BTForEach::set_save_var); + ClassDB::bind_method(D_METHOD("get_save_var"), &BTForEach::get_save_var); + + ADD_PROPERTY(PropertyInfo(Variant::STRING, "array_var"), "set_array_var", "get_array_var"); + ADD_PROPERTY(PropertyInfo(Variant::STRING, "save_var"), "set_save_var", "get_save_var"); +} diff --git a/bt/decorators/bt_for_each.h b/bt/decorators/bt_for_each.h new file mode 100644 index 0000000..94aea10 --- /dev/null +++ b/bt/decorators/bt_for_each.h @@ -0,0 +1,38 @@ +/* bt_for_each.h */ + +#ifndef BT_FOR_EACH_H +#define BT_FOR_EACH_H + +#include "bt_decorator.h" +#include "core/object.h" + +class BTForEach : public BTDecorator { + GDCLASS(BTForEach, BTDecorator); + +private: + String array_var; + String save_var; + + int current_idx; + +protected: + static void _bind_methods(); + + virtual String _generate_name() const; + virtual void _enter(); + virtual int _tick(float p_delta); + +public: + void set_array_var(String p_value) { + array_var = p_value; + emit_changed(); + } + String get_array_var() const { return array_var; } + void set_save_var(String p_value) { + save_var = p_value; + emit_changed(); + } + String get_save_var() const { return save_var; } +}; + +#endif // BT_FOR_EACH_H \ No newline at end of file diff --git a/icons/icon_b_t_for_each.svg b/icons/icon_b_t_for_each.svg new file mode 100644 index 0000000..579cadc --- /dev/null +++ b/icons/icon_b_t_for_each.svg @@ -0,0 +1 @@ + \ No newline at end of file diff --git a/register_types.cpp b/register_types.cpp index 4427666..9e1a57e 100644 --- a/register_types.cpp +++ b/register_types.cpp @@ -28,6 +28,7 @@ #include "bt/decorators/bt_cooldown.h" #include "bt/decorators/bt_decorator.h" #include "bt/decorators/bt_delay.h" +#include "bt/decorators/bt_for_each.h" #include "bt/decorators/bt_invert.h" #include "bt/decorators/bt_new_scope.h" #include "bt/decorators/bt_probability.h" @@ -75,6 +76,7 @@ void register_limboai_types() { ClassDB::register_class(); ClassDB::register_class(); ClassDB::register_class(); + ClassDB::register_class(); ClassDB::register_class(); ClassDB::register_class();