From 1123ffdcedc4549c6adda5ceaeb431f63fd6b30b Mon Sep 17 00:00:00 2001 From: Serhii Snitsaruk Date: Sun, 28 Aug 2022 12:54:34 +0200 Subject: [PATCH] Add first BT classes --- limboai/SCsub | 5 + limboai/bt_action.cpp | 14 ++ limboai/bt_action.h | 16 ++ limboai/bt_composite.cpp | 14 ++ limboai/bt_composite.h | 16 ++ limboai/bt_condition.cpp | 14 ++ limboai/bt_condition.h | 16 ++ limboai/bt_decorator.cpp | 14 ++ limboai/bt_decorator.h | 16 ++ limboai/bt_parallel.cpp | 50 ++++++ limboai/bt_parallel.h | 32 ++++ limboai/bt_selector.cpp | 19 +++ limboai/bt_selector.h | 18 +++ limboai/bt_sequence.cpp | 19 +++ limboai/bt_sequence.h | 20 +++ limboai/bt_task.cpp | 281 +++++++++++++++++++++++++++++++++ limboai/bt_task.h | 81 ++++++++++ limboai/config.py | 9 ++ limboai/limbo_string_names.cpp | 13 ++ limboai/limbo_string_names.h | 33 ++++ limboai/limbo_utility.cpp | 28 ++++ limboai/limbo_utility.h | 19 +++ limboai/register_types.cpp | 32 ++++ limboai/register_types.h | 4 + 24 files changed, 783 insertions(+) create mode 100644 limboai/SCsub create mode 100644 limboai/bt_action.cpp create mode 100644 limboai/bt_action.h create mode 100644 limboai/bt_composite.cpp create mode 100644 limboai/bt_composite.h create mode 100644 limboai/bt_condition.cpp create mode 100644 limboai/bt_condition.h create mode 100644 limboai/bt_decorator.cpp create mode 100644 limboai/bt_decorator.h create mode 100644 limboai/bt_parallel.cpp create mode 100644 limboai/bt_parallel.h create mode 100644 limboai/bt_selector.cpp create mode 100644 limboai/bt_selector.h create mode 100644 limboai/bt_sequence.cpp create mode 100644 limboai/bt_sequence.h create mode 100644 limboai/bt_task.cpp create mode 100644 limboai/bt_task.h create mode 100644 limboai/config.py create mode 100644 limboai/limbo_string_names.cpp create mode 100644 limboai/limbo_string_names.h create mode 100644 limboai/limbo_utility.cpp create mode 100644 limboai/limbo_utility.h create mode 100644 limboai/register_types.cpp create mode 100644 limboai/register_types.h diff --git a/limboai/SCsub b/limboai/SCsub new file mode 100644 index 0000000..e208d38 --- /dev/null +++ b/limboai/SCsub @@ -0,0 +1,5 @@ +# SCsub + +Import('env') + +env.add_source_files(env.modules_sources, "*.cpp") # Add all cpp files to the build diff --git a/limboai/bt_action.cpp b/limboai/bt_action.cpp new file mode 100644 index 0000000..9175dda --- /dev/null +++ b/limboai/bt_action.cpp @@ -0,0 +1,14 @@ +/* bt_action.cpp */ + +#include "bt_action.h" + +String BTAction::get_configuration_warning() const { + String warning = BTTask::get_configuration_warning(); + if (!warning.empty()) { + warning += "\n"; + } + if (get_child_count() != 0) { + warning += "Action can't have child tasks.\n"; + } + return warning; +} \ No newline at end of file diff --git a/limboai/bt_action.h b/limboai/bt_action.h new file mode 100644 index 0000000..648cf3e --- /dev/null +++ b/limboai/bt_action.h @@ -0,0 +1,16 @@ +/* bt_action.h */ + +#ifndef BT_ACTION_H +#define BT_ACTION_H + +#include "bt_task.h" +#include "core/object.h" + +class BTAction : public BTTask { + GDCLASS(BTAction, BTTask); + +public: + virtual String get_configuration_warning() const; +}; + +#endif // BT_ACTION_H \ No newline at end of file diff --git a/limboai/bt_composite.cpp b/limboai/bt_composite.cpp new file mode 100644 index 0000000..2325ebf --- /dev/null +++ b/limboai/bt_composite.cpp @@ -0,0 +1,14 @@ +/* bt_composite.cpp */ + +#include "bt_composite.h" + +String BTComposite::get_configuration_warning() const { + String warning = BTTask::get_configuration_warning(); + if (!warning.empty()) { + warning += "\n"; + } + if (get_child_count() < 1) { + warning += "Composite should have at least one child task.\n"; + } + return warning; +} \ No newline at end of file diff --git a/limboai/bt_composite.h b/limboai/bt_composite.h new file mode 100644 index 0000000..35c901f --- /dev/null +++ b/limboai/bt_composite.h @@ -0,0 +1,16 @@ +/* bt_composite.h */ + +#ifndef BT_COMPOSITE_H +#define BT_COMPOSITE_H + +#include "bt_task.h" +#include "core/object.h" + +class BTComposite : public BTTask { + GDCLASS(BTComposite, BTTask); + +public: + virtual String get_configuration_warning() const; +}; + +#endif // BT_COMPOSITE_H \ No newline at end of file diff --git a/limboai/bt_condition.cpp b/limboai/bt_condition.cpp new file mode 100644 index 0000000..f3c1d5b --- /dev/null +++ b/limboai/bt_condition.cpp @@ -0,0 +1,14 @@ +/* bt_condition.cpp */ + +#include "bt_condition.h" + +String BTCondition::get_configuration_warning() const { + String warning = BTTask::get_configuration_warning(); + if (!warning.empty()) { + warning += "\n"; + } + if (get_child_count() != 0) { + warning += "Condition can't have child tasks.\n"; + } + return warning; +} \ No newline at end of file diff --git a/limboai/bt_condition.h b/limboai/bt_condition.h new file mode 100644 index 0000000..83142b9 --- /dev/null +++ b/limboai/bt_condition.h @@ -0,0 +1,16 @@ +/* bt_condition.h */ + +#ifndef BT_CONDITION_H +#define BT_CONDITION_H + +#include "bt_task.h" +#include "core/object.h" + +class BTCondition : public BTTask { + GDCLASS(BTCondition, BTTask); + +public: + virtual String get_configuration_warning() const; +}; + +#endif // BT_CONDITION_H \ No newline at end of file diff --git a/limboai/bt_decorator.cpp b/limboai/bt_decorator.cpp new file mode 100644 index 0000000..afab3c5 --- /dev/null +++ b/limboai/bt_decorator.cpp @@ -0,0 +1,14 @@ +/* bt_decorator.cpp */ + +#include "bt_decorator.h" + +String BTDecorator::get_configuration_warning() const { + String warning = BTTask::get_configuration_warning(); + if (!warning.empty()) { + warning += "\n"; + } + if (get_child_count() != 1) { + warning += "Decorator should have a single child task.\n"; + } + return warning; +} diff --git a/limboai/bt_decorator.h b/limboai/bt_decorator.h new file mode 100644 index 0000000..ce531e0 --- /dev/null +++ b/limboai/bt_decorator.h @@ -0,0 +1,16 @@ +/* bt_decorator.h */ + +#ifndef BT_DECORATOR_H +#define BT_DECORATOR_H + +#include "bt_task.h" +#include "core/object.h" + +class BTDecorator : public BTTask { + GDCLASS(BTDecorator, BTTask) + +public: + virtual String get_configuration_warning() const; +}; + +#endif // BT_DECORATOR_H \ No newline at end of file diff --git a/limboai/bt_parallel.cpp b/limboai/bt_parallel.cpp new file mode 100644 index 0000000..517c84c --- /dev/null +++ b/limboai/bt_parallel.cpp @@ -0,0 +1,50 @@ +/* bt_parallel.cpp */ + +#include "bt_parallel.h" +#include "core/class_db.h" + +void BTParallel::_enter() { + for (int i = 0; i < get_child_count(); i++) { + get_child(i)->cancel(); + } +} + +int BTParallel::_tick(float p_delta) { + int num_succeeded = 0; + int num_failed = 0; + int return_status = RUNNING; + for (int i = 0; i < get_child_count(); i++) { + int status = 0; + Ref child = get_child(i); + if (!repeat && (child->get_status() == FAILURE or child->get_status() == SUCCESS)) { + status = child->get_status(); + } else { + status = child->execute(p_delta); + } + if (status == FAILURE) { + num_failed += 1; + if (num_failed >= num_failures_required && return_status == RUNNING) { + return_status = FAILURE; + } + } else if (status == SUCCESS) { + num_succeeded += 1; + if (num_succeeded >= num_successes_required && return_status == RUNNING) { + return_status = SUCCESS; + } + } + } + return return_status; +} + +void BTParallel::_bind_methods() { + ClassDB::bind_method(D_METHOD("get_num_successes_required"), &BTParallel::get_num_successes_required); + ClassDB::bind_method(D_METHOD("set_num_successes_required", "p_value"), &BTParallel::set_num_successes_required); + ClassDB::bind_method(D_METHOD("get_num_failures_required"), &BTParallel::get_num_failures_required); + ClassDB::bind_method(D_METHOD("set_num_failures_required", "p_value"), &BTParallel::set_num_failures_required); + ClassDB::bind_method(D_METHOD("get_repeat"), &BTParallel::get_repeat); + ClassDB::bind_method(D_METHOD("set_repeat", "p_value"), &BTParallel::set_repeat); + + ADD_PROPERTY(PropertyInfo(Variant::INT, "num_successes_required"), "set_num_successes_required", "get_num_successes_required"); + ADD_PROPERTY(PropertyInfo(Variant::INT, "num_failures_required"), "set_num_failures_required", "get_num_failures_required"); + ADD_PROPERTY(PropertyInfo(Variant::BOOL, "repeat"), "set_repeat", "get_repeat"); +} diff --git a/limboai/bt_parallel.h b/limboai/bt_parallel.h new file mode 100644 index 0000000..c3966c7 --- /dev/null +++ b/limboai/bt_parallel.h @@ -0,0 +1,32 @@ +/* bt_parallel.h */ + +#ifndef BT_PARALLEL_H +#define BT_PARALLEL_H + +#include "bt_composite.h" +#include "core/object.h" + +class BTParallel : public BTComposite { + GDCLASS(BTParallel, BTComposite); + +private: + int num_successes_required = 1; + int num_failures_required = 1; + bool repeat = false; + +protected: + static void _bind_methods(); + + virtual void _enter(); + virtual int _tick(float p_delta); + +public: + int get_num_successes_required() const { return num_successes_required; }; + void set_num_successes_required(int p_value) { num_successes_required = p_value; }; + int get_num_failures_required() const { return num_failures_required; }; + void set_num_failures_required(int p_value) { num_failures_required = p_value; }; + bool get_repeat() const { return repeat; }; + void set_repeat(bool p_value) { repeat = p_value; }; +}; + +#endif // BT_PARALLEL_H \ No newline at end of file diff --git a/limboai/bt_selector.cpp b/limboai/bt_selector.cpp new file mode 100644 index 0000000..367f978 --- /dev/null +++ b/limboai/bt_selector.cpp @@ -0,0 +1,19 @@ +/* bt_selector.cpp */ + +#include "bt_selector.h" + +void BTSelector::_enter() { + last_running_idx = 0; +} + +int BTSelector::_tick(float p_delta) { + int status = FRESH; + for (int i = 0; i < get_child_count(); i++) { + status = get_child(i)->execute(p_delta); + if (status != FAILURE) { + last_running_idx = i; + break; + } + } + return status; +} \ No newline at end of file diff --git a/limboai/bt_selector.h b/limboai/bt_selector.h new file mode 100644 index 0000000..5ea52d5 --- /dev/null +++ b/limboai/bt_selector.h @@ -0,0 +1,18 @@ +/* bt_selector.h */ + +#ifndef BT_SELECTOR_H +#define BT_SELECTOR_H + +#include "bt_composite.h" + +class BTSelector : public BTComposite { + GDCLASS(BTSelector, BTComposite); + +private: + int last_running_idx = 0; + +protected: + virtual void _enter(); + virtual int _tick(float p_delta); +}; +#endif // BT_SELECTOR_H \ No newline at end of file diff --git a/limboai/bt_sequence.cpp b/limboai/bt_sequence.cpp new file mode 100644 index 0000000..05b437c --- /dev/null +++ b/limboai/bt_sequence.cpp @@ -0,0 +1,19 @@ +/* bt_sequence.cpp */ + +#include "bt_sequence.h" + +void BTSequence::_enter() { + last_running_idx = 0; +} + +int BTSequence::_tick(float p_delta) { + int status = FRESH; + for (int i = 0; i < get_child_count(); i++) { + status = get_child(i)->execute(p_delta); + if (status != SUCCESS) { + last_running_idx = i; + break; + } + } + return status; +} \ No newline at end of file diff --git a/limboai/bt_sequence.h b/limboai/bt_sequence.h new file mode 100644 index 0000000..f0f9ad0 --- /dev/null +++ b/limboai/bt_sequence.h @@ -0,0 +1,20 @@ +/* bt_sequence.h */ + +#ifndef BT_SEQUENCE_H +#define BT_SEQUENCE_H + +#import "bt_composite.h" +#include "core/object.h" + +class BTSequence : public BTComposite { + GDCLASS(BTSequence, BTComposite); + +private: + int last_running_idx = 0; + +protected: + virtual void _enter(); + virtual int _tick(float p_delta); +}; + +#endif // BT_SEQUENCE_H \ No newline at end of file diff --git a/limboai/bt_task.cpp b/limboai/bt_task.cpp new file mode 100644 index 0000000..c19b421 --- /dev/null +++ b/limboai/bt_task.cpp @@ -0,0 +1,281 @@ +/* bt_task.cpp */ + +#include "bt_task.h" + +#include "core/class_db.h" +#include "core/object.h" +#include "core/script_language.h" +#include "core/variant.h" +#include "editor/editor_node.h" + +#include "limbo_string_names.h" +#include "limbo_utility.h" + +String BTTask::_generate_name() const { + if (get_script_instance()) { + if (get_script_instance()->has_method(LimboStringNames::get_singleton()->_generate_name)) { + return get_script_instance()->call(LimboStringNames::get_singleton()->_generate_name); + } + String name = get_script_instance()->get_script()->get_path(); + if (!name.empty()) { + // Generate name based on script file + name = name.get_basename().get_file(); + return name; + } + } + return get_class(); +} + +Array BTTask::_get_children() const { + Array arr; + int num_children = get_child_count(); + arr.resize(num_children); + for (int i = 0; i < num_children; i++) { + arr[i] = get_child(i).ptr(); + } + + return arr; +} + +void BTTask::_set_children(Array p_children) { + _children.clear(); + const int num_children = p_children.size(); + _children.resize(num_children); + for (int i = 0; i < num_children; i++) { + Variant task_var = p_children[i]; + const Ref task_ref = task_var; + _children.set(i, task_var); + } +} + +String BTTask::get_task_name() const { + if (_custom_name.empty()) { + return _generate_name(); + } + return _custom_name; +} + +Ref BTTask::get_root() const { + const BTTask *task = this; + while (!task->is_root()) { + task = task->get_parent().ptr(); + } + return Ref(task); +} + +void BTTask::set_custom_name(const String &p_name) { + if (_custom_name != p_name) { + _custom_name = p_name; + emit_changed(); + } +}; + +void BTTask::initialize(Object *p_agent, Dictionary p_blackboard) { + _agent = p_agent; + _blackboard = p_blackboard; + for (int i = 0; i < _children.size(); i++) { + get_child(i)->initialize(p_agent, p_blackboard); + } + if (get_script_instance() && + get_script_instance()->has_method(LimboStringNames::get_singleton()->_setup)) { + get_script_instance()->call(LimboStringNames::get_singleton()->_setup); + } else { + _setup(); + } +} + +Ref BTTask::clone() const { + Ref inst = duplicate(true); + inst.ptr()->_parent.unref(); + CRASH_COND(inst.ptr()->get_parent().is_valid()); + for (int i = 0; i < _children.size(); i++) { + Ref c = get_child(i)->clone(); + c->_parent = inst; + inst->_children.set(i, c); + } + return inst; +} + +int BTTask::execute(float p_delta) { + if (_status == RUNNING) { + if (get_script_instance() && + // get_script_instance()->get_script()->is_valid() && + get_script_instance()->has_method(LimboStringNames::get_singleton()->_enter)) { + get_script_instance()->call(LimboStringNames::get_singleton()->_enter); + } else { + _enter(); + } + } + if (get_script_instance() && + // get_script_instance()->get_script()->is_valid() && + get_script_instance()->has_method(LimboStringNames::get_singleton()->_tick)) { + _status = get_script_instance()->call(LimboStringNames::get_singleton()->_tick, Variant(p_delta)); + } else { + _status = _tick(p_delta); + } + + if (_status != RUNNING) { + if (get_script_instance() && + // get_script_instance()->get_script()->is_valid() && + get_script_instance()->has_method(LimboStringNames::get_singleton()->_exit)) { + get_script_instance()->call(LimboStringNames::get_singleton()->_exit); + } else { + _exit(); + } + } + return _status; +} + +void BTTask::cancel() { + for (int i = 0; i < _children.size(); i++) { + get_child(i)->cancel(); + } + if (_status == RUNNING) { + if (get_script_instance() && + // get_script_instance()->get_script()->is_valid() && + get_script_instance()->has_method(LimboStringNames::get_singleton()->_exit)) { + get_script_instance()->call(LimboStringNames::get_singleton()->_exit); + } else { + _exit(); + } + } + _status = FRESH; +} + +Ref BTTask::get_child(int p_idx) const { + ERR_FAIL_INDEX_V(p_idx, _children.size(), nullptr); + return _children.get(p_idx); +} + +int BTTask::get_child_count() const { + return _children.size(); +} + +void BTTask::add_child(Ref p_child) { + ERR_FAIL_COND_MSG(p_child.ptr()->get_parent().is_valid(), "p_child already has a parent!"); + p_child->_parent = Ref(this); + _children.push_back(p_child); + emit_changed(); +} + +void BTTask::add_child_at_index(Ref p_child, int p_idx) { + ERR_FAIL_COND_MSG(p_child.ptr()->get_parent().is_valid(), "p_child already has a parent!"); + if (p_idx < 0 || p_idx > _children.size()) { + p_idx = _children.size(); + } + _children.insert(p_idx, p_child); + p_child->_parent = Ref(this); + emit_changed(); +} + +void BTTask::remove_child(Ref p_child) { + int idx = _children.find(p_child); + if (idx == -1) { + ERR_FAIL_MSG("p_child not found!"); + } else { + _children.remove(idx); + p_child->_parent.unref(); + emit_changed(); + } +} + +bool BTTask::has_child(const Ref &p_child) const { + return _children.find(p_child) != -1; +} + +int BTTask::get_child_index(const Ref &p_child) const { + return _children.find(p_child); +} + +Ref BTTask::next_sibling() const { + if (_parent.is_valid()) { + int idx = _parent->get_child_index(Ref(this)); + if (idx != -1 && _parent->get_child_count() > (idx + 1)) { + return _parent->get_child(idx + 1); + } + } + return Ref(); +} + +String BTTask::get_configuration_warning() const { + return String(); +} + +Ref BTTask::get_icon() const { + return EditorNode::get_singleton()->get_class_icon("BTAction", "Object"); +} + +void BTTask::print_tree(int p_initial_tabs) const { + String tabs = "--"; + for (int i = 0; i < p_initial_tabs; i++) { + tabs += "--"; + } + print_line(vformat("%s Name: %s Instance: %s", tabs, get_task_name(), Ref(this))); + for (int i = 0; i < get_child_count(); i++) { + get_child(i)->print_tree(p_initial_tabs + 1); + } +} + +void BTTask::_bind_methods() { + // Properties. + ClassDB::bind_method(D_METHOD("get_custom_name"), &BTTask::get_custom_name); + ClassDB::bind_method(D_METHOD("set_custom_name", "p_name"), &BTTask::set_custom_name); + ADD_PROPERTY(PropertyInfo(Variant::STRING, "custom_name"), "set_custom_name", "get_custom_name"); + ClassDB::bind_method(D_METHOD("get_agent"), &BTTask::get_agent); + ADD_PROPERTY(PropertyInfo(Variant::OBJECT, "agent", PROPERTY_HINT_NONE, "", 0, "Object"), "", "get_agent"); + ClassDB::bind_method(D_METHOD("get_blackboard"), &BTTask::get_blackboard); + ADD_PROPERTY(PropertyInfo(Variant::DICTIONARY, "blackboard", PROPERTY_HINT_NONE, "", 0, "Dictionary"), "", "get_blackboard"); + ClassDB::bind_method(D_METHOD("get_parent"), &BTTask::get_parent); + ADD_PROPERTY(PropertyInfo(Variant::OBJECT, "parent", PROPERTY_HINT_NONE, "", 0, "BTTask"), "", "get_parent"); + ClassDB::bind_method(D_METHOD("get_children"), &BTTask::_get_children); + ClassDB::bind_method(D_METHOD("set_children", "p_children"), &BTTask::_set_children); + ADD_PROPERTY(PropertyInfo(Variant::ARRAY, "children", PROPERTY_HINT_NONE, "", PROPERTY_USAGE_NOEDITOR), "set_children", "get_children"); + ClassDB::bind_method(D_METHOD("get_status"), &BTTask::get_status); + ADD_PROPERTY(PropertyInfo(Variant::INT, "status"), "", "get_status"); + + // Virtual methods. + ClassDB::bind_method(D_METHOD("_setup"), &BTTask::_setup); + BIND_VMETHOD(MethodInfo("_setup")); + ClassDB::bind_method(D_METHOD("_enter"), &BTTask::_enter); + BIND_VMETHOD(MethodInfo("_enter")) + ClassDB::bind_method(D_METHOD("_exit"), &BTTask::_exit); + BIND_VMETHOD(MethodInfo("_exit")); + ClassDB::bind_method(D_METHOD("_tick", "p_delta"), &BTTask::_tick); + BIND_VMETHOD(MethodInfo(Variant::INT, "_tick", PropertyInfo(Variant::REAL, "p_delta"))); + ClassDB::bind_method(D_METHOD("_generate_name"), &BTTask::_generate_name); + BIND_VMETHOD(MethodInfo(PropertyInfo(Variant::STRING, ""), "_generate_name")); + ClassDB::bind_method(D_METHOD("_get_configuration_warning"), &BTTask::get_configuration_warning); + BIND_VMETHOD(MethodInfo(PropertyInfo(Variant::STRING, ""), "_get_configuration_warning")); + ClassDB::bind_method(D_METHOD("_get_icon"), &BTTask::get_icon); + BIND_VMETHOD(MethodInfo(PropertyInfo(Variant::OBJECT, "", PROPERTY_HINT_RESOURCE_TYPE, "Texture"), "_get_icon")); + + // Public Methods. + ClassDB::bind_method(D_METHOD("is_root"), &BTTask::is_root); + ClassDB::bind_method(D_METHOD("initialize", "p_agent", "p_blackboard"), &BTTask::initialize); + ClassDB::bind_method(D_METHOD("clone"), &BTTask::clone); + ClassDB::bind_method(D_METHOD("execute", "p_delta"), &BTTask::execute); + ClassDB::bind_method(D_METHOD("get_child", "p_idx"), &BTTask::get_child); + ClassDB::bind_method(D_METHOD("get_child_count"), &BTTask::get_child_count); + ClassDB::bind_method(D_METHOD("add_child", "p_child"), &BTTask::add_child); + ClassDB::bind_method(D_METHOD("add_child_at_index", "p_child", "p_idx"), &BTTask::add_child_at_index); + ClassDB::bind_method(D_METHOD("remove_child", "p_child"), &BTTask::remove_child); + ClassDB::bind_method(D_METHOD("has_child", "p_child"), &BTTask::has_child); + ClassDB::bind_method(D_METHOD("get_child_index", "p_child"), &BTTask::get_child_index); + ClassDB::bind_method(D_METHOD("next_sibling"), &BTTask::next_sibling); + ClassDB::bind_method(D_METHOD("print_tree", "p_initial_tabs"), &BTTask::print_tree, Variant(0)); + ClassDB::bind_method(D_METHOD("get_task_name"), &BTTask::get_task_name); + + // 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() { + _custom_name = String(); + _agent = nullptr; + _blackboard = Dictionary(); + _children = Vector>(); + _status = FRESH; +} \ No newline at end of file diff --git a/limboai/bt_task.h b/limboai/bt_task.h new file mode 100644 index 0000000..368016d --- /dev/null +++ b/limboai/bt_task.h @@ -0,0 +1,81 @@ +/* bt_task.h */ + +#ifndef BTTASK_H +#define BTTASK_H + +#include "core/array.h" +#include "core/dictionary.h" +#include "core/reference.h" +#include "core/resource.h" +#include "core/ustring.h" +#include "core/vector.h" +#include "scene/resources/texture.h" + +class BTTask : public Resource { + GDCLASS(BTTask, Resource); + +public: + enum { + FRESH, + RUNNING, + FAILURE, + SUCCESS, + }; + enum TaskType { + ACTION, + CONDITION, + COMPOSITE, + DECORATOR, + }; + +private: + String _custom_name; + Object *_agent; + Dictionary _blackboard; + Ref _parent; + Vector> _children; + int _status; + + Array _get_children() const; + void _set_children(Array children); + +protected: + static void _bind_methods(); + + virtual String _generate_name() const; + virtual void _setup(){}; + virtual void _enter(){}; + virtual void _exit(){}; + virtual int _tick(float p_delta) { return FAILURE; }; + +public: + Object *get_agent() const { return _agent; }; + Dictionary get_blackboard() const { return _blackboard; }; + Ref get_parent() const { return _parent; }; + bool is_root() const { return _parent.is_null(); }; + Ref get_root() const; + int get_status() const { return _status; }; + String get_custom_name() const { return _custom_name; }; + void set_custom_name(const String &p_name); + String get_task_name() const; + + void initialize(Object *p_agent, Dictionary p_blackboard); + virtual Ref clone() const; + int execute(float p_delta); + void cancel(); + Ref get_child(int p_idx) const; + int get_child_count() const; + void add_child(Ref p_child); + void add_child_at_index(Ref p_child, int p_idx); + void remove_child(Ref p_child); + bool has_child(const Ref &p_child) const; + int get_child_index(const Ref &p_child) const; + Ref next_sibling() const; + virtual String get_configuration_warning() const; + virtual Ref get_icon() const; + void print_tree(int p_initial_tabs = 0) const; + + BTTask(); +}; + +#endif // BTTASK_H \ No newline at end of file diff --git a/limboai/config.py b/limboai/config.py new file mode 100644 index 0000000..2df6e60 --- /dev/null +++ b/limboai/config.py @@ -0,0 +1,9 @@ +# config.py + + +def can_build(env, platform): + return True + + +def configure(env): + pass diff --git a/limboai/limbo_string_names.cpp b/limboai/limbo_string_names.cpp new file mode 100644 index 0000000..f3d6beb --- /dev/null +++ b/limboai/limbo_string_names.cpp @@ -0,0 +1,13 @@ +/* limbo_string_names.cpp */ + +#include "limbo_string_names.h" + +LimboStringNames *LimboStringNames::singleton = nullptr; + +LimboStringNames::LimboStringNames() { + _generate_name = StaticCString::create("_generate_name"); + _setup = StaticCString::create("_setup"); + _enter = StaticCString::create("_enter"); + _exit = StaticCString::create("_exit"); + _tick = StaticCString::create("_tick"); +} \ No newline at end of file diff --git a/limboai/limbo_string_names.h b/limboai/limbo_string_names.h new file mode 100644 index 0000000..d29211b --- /dev/null +++ b/limboai/limbo_string_names.h @@ -0,0 +1,33 @@ +/* limbo_string_names.h */ + +#ifndef LIMBO_STRING_NAMES_H +#define LIMBO_STRING_NAMES_H + +#include "core/string_name.h" +#include "core/typedefs.h" + +class LimboStringNames { + friend void register_limboai_types(); + friend void unregister_limboai_types(); + + static LimboStringNames *singleton; + + static void create() { singleton = memnew(LimboStringNames); } + static void free() { + memdelete(singleton); + singleton = nullptr; + } + + LimboStringNames(); + +public: + _FORCE_INLINE_ static LimboStringNames *get_singleton() { return singleton; } + + StringName _generate_name; + StringName _setup; + StringName _enter; + StringName _exit; + StringName _tick; +}; + +#endif // LIMBO_STRING_NAMES_H \ No newline at end of file diff --git a/limboai/limbo_utility.cpp b/limboai/limbo_utility.cpp new file mode 100644 index 0000000..027a8f7 --- /dev/null +++ b/limboai/limbo_utility.cpp @@ -0,0 +1,28 @@ +/* limbo_utility.cpp */ + +#include "limbo_utility.h" +#include "core/class_db.h" +#include "core/dictionary.h" +#include "core/print_string.h" +#include "core/project_settings.h" +#include "core/variant.h" + +String LimboUtility::get_script_class(const Ref