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();