Replace node blackboard data with BlackboardSource
This commit is contained in:
parent
6ef0dd942e
commit
a247d0d67b
|
@ -34,51 +34,61 @@ Ref<Blackboard> Blackboard::top() const {
|
|||
return bb;
|
||||
}
|
||||
|
||||
Variant Blackboard::get_var(const Variant &p_key, const Variant &p_default) const {
|
||||
if (data.has(p_key)) {
|
||||
return data.get(p_key, Variant());
|
||||
Variant Blackboard::get_var(const String &p_name, const Variant &p_default) const {
|
||||
if (data.has(p_name)) {
|
||||
return data.get(p_name).get_value();
|
||||
} else if (parent.is_valid()) {
|
||||
return parent->get_var(p_key, p_default);
|
||||
return parent->get_var(p_name, p_default);
|
||||
} else {
|
||||
return p_default;
|
||||
}
|
||||
}
|
||||
|
||||
void Blackboard::set_var(const Variant &p_key, const Variant &p_value) {
|
||||
data[p_key] = p_value;
|
||||
void Blackboard::set_var(const String &p_name, const Variant &p_value) {
|
||||
// TODO: Check if p_value can be converted into required type!
|
||||
if (data.has(p_name)) {
|
||||
data[p_name].set_value(p_value);
|
||||
} else {
|
||||
BBVariable var;
|
||||
var.set_value(p_value);
|
||||
data.insert(p_name, var);
|
||||
}
|
||||
}
|
||||
|
||||
bool Blackboard::has_var(const Variant &p_key) const {
|
||||
return data.has(p_key) || (parent.is_valid() && parent->has_var(p_key));
|
||||
bool Blackboard::has_var(const String &p_name) const {
|
||||
return data.has(p_name) || (parent.is_valid() && parent->has_var(p_name));
|
||||
}
|
||||
|
||||
void Blackboard::erase_var(const Variant &p_key) {
|
||||
data.erase(p_key);
|
||||
void Blackboard::erase_var(const String &p_name) {
|
||||
data.erase(p_name);
|
||||
}
|
||||
|
||||
void Blackboard::add_var(const String &p_name, const BBVariable &p_var) {
|
||||
ERR_FAIL_COND(data.has(p_name));
|
||||
data.insert(p_name, p_var);
|
||||
}
|
||||
|
||||
void Blackboard::prefetch_nodepath_vars(Node *p_node) {
|
||||
ERR_FAIL_COND(p_node == nullptr);
|
||||
Array keys = data.keys();
|
||||
Array values = data.values();
|
||||
for (int i = 0; i < keys.size(); i++) {
|
||||
if (values[i].get_type() == Variant::NODE_PATH) {
|
||||
Node *fetched_node = p_node->get_node_or_null(values[i]);
|
||||
for (KeyValue<String, BBVariable> &kv : data) {
|
||||
if (kv.value.get_value().get_type() == Variant::NODE_PATH) {
|
||||
Node *fetched_node = p_node->get_node_or_null(kv.value.get_value());
|
||||
if (fetched_node != nullptr) {
|
||||
data[keys[i]] = fetched_node;
|
||||
kv.value.set_value(fetched_node);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void Blackboard::_bind_methods() {
|
||||
ClassDB::bind_method(D_METHOD("get_data"), &Blackboard::get_data);
|
||||
ClassDB::bind_method(D_METHOD("set_data", "p_data"), &Blackboard::set_data);
|
||||
ClassDB::bind_method(D_METHOD("get_var", "p_key", "p_default"), &Blackboard::get_var, Variant());
|
||||
ClassDB::bind_method(D_METHOD("set_var", "p_key", "p_value"), &Blackboard::set_var);
|
||||
ClassDB::bind_method(D_METHOD("has_var", "p_key"), &Blackboard::has_var);
|
||||
ClassDB::bind_method(D_METHOD("get_var", "p_name", "p_default"), &Blackboard::get_var, Variant());
|
||||
ClassDB::bind_method(D_METHOD("set_var", "p_name", "p_value"), &Blackboard::set_var);
|
||||
ClassDB::bind_method(D_METHOD("has_var", "p_name"), &Blackboard::has_var);
|
||||
ClassDB::bind_method(D_METHOD("set_parent_scope", "p_blackboard"), &Blackboard::set_parent_scope);
|
||||
ClassDB::bind_method(D_METHOD("get_parent_scope"), &Blackboard::get_parent_scope);
|
||||
ClassDB::bind_method(D_METHOD("erase_var", "p_key"), &Blackboard::erase_var);
|
||||
ClassDB::bind_method(D_METHOD("erase_var", "p_name"), &Blackboard::erase_var);
|
||||
ClassDB::bind_method(D_METHOD("prefetch_nodepath_vars", "p_node"), &Blackboard::prefetch_nodepath_vars);
|
||||
ClassDB::bind_method(D_METHOD("top"), &Blackboard::top);
|
||||
// ClassDB::bind_method(D_METHOD("get_data"), &Blackboard::get_data);
|
||||
// ClassDB::bind_method(D_METHOD("set_data", "p_data"), &Blackboard::set_data);
|
||||
}
|
||||
|
|
|
@ -12,6 +12,8 @@
|
|||
#ifndef BLACKBOARD_H
|
||||
#define BLACKBOARD_H
|
||||
|
||||
#include "bb_variable.h"
|
||||
|
||||
#ifdef LIMBOAI_MODULE
|
||||
#include "core/object/object.h"
|
||||
#include "core/object/ref_counted.h"
|
||||
|
@ -33,27 +35,30 @@ class Blackboard : public RefCounted {
|
|||
GDCLASS(Blackboard, RefCounted);
|
||||
|
||||
private:
|
||||
Dictionary data;
|
||||
HashMap<String, BBVariable> data;
|
||||
Ref<Blackboard> parent;
|
||||
|
||||
protected:
|
||||
static void _bind_methods();
|
||||
|
||||
public:
|
||||
void set_data(const Dictionary &p_value) { data = p_value; }
|
||||
Dictionary get_data() const { return data; }
|
||||
|
||||
void set_parent_scope(const Ref<Blackboard> &p_blackboard) { parent = p_blackboard; }
|
||||
Ref<Blackboard> get_parent_scope() const { return parent; }
|
||||
|
||||
Ref<Blackboard> top() const;
|
||||
|
||||
Variant get_var(const Variant &p_key, const Variant &p_default) const;
|
||||
void set_var(const Variant &p_key, const Variant &p_value);
|
||||
bool has_var(const Variant &p_key) const;
|
||||
void erase_var(const Variant &p_key);
|
||||
Variant get_var(const String &p_name, const Variant &p_default) const;
|
||||
void set_var(const String &p_name, const Variant &p_value);
|
||||
bool has_var(const String &p_name) const;
|
||||
void erase_var(const String &p_name);
|
||||
|
||||
void add_var(const String &p_name, const BBVariable &p_var);
|
||||
|
||||
void prefetch_nodepath_vars(Node *p_node);
|
||||
|
||||
// TODO: Rework serialization API.
|
||||
// void set_data(const Dictionary &p_value);
|
||||
// Dictionary get_data() const;
|
||||
};
|
||||
|
||||
#endif // BLACKBOARD_H
|
||||
#endif // BLACKBOARD_H
|
||||
|
|
|
@ -12,48 +12,48 @@
|
|||
#include "blackboard_source.h"
|
||||
|
||||
void BlackboardSource::set_value(const String &p_name, const Variant &p_value) {
|
||||
ERR_FAIL_COND(!vars.has(p_name));
|
||||
vars.get(p_name).set_value(p_value);
|
||||
ERR_FAIL_COND(!data.has(p_name));
|
||||
data.get(p_name).set_value(p_value);
|
||||
}
|
||||
|
||||
Variant BlackboardSource::get_value(const String &p_name) const {
|
||||
ERR_FAIL_COND_V(!vars.has(p_name), Variant());
|
||||
return vars.get(p_name).get_value();
|
||||
ERR_FAIL_COND_V(!data.has(p_name), Variant());
|
||||
return data.get(p_name).get_value();
|
||||
}
|
||||
|
||||
void BlackboardSource::add_var(const String &p_name, const BBVariable &p_var) {
|
||||
ERR_FAIL_COND(vars.has(p_name));
|
||||
ERR_FAIL_COND(data.has(p_name));
|
||||
ERR_FAIL_COND(base.is_valid());
|
||||
vars.insert(p_name, p_var);
|
||||
data.insert(p_name, p_var);
|
||||
}
|
||||
|
||||
void BlackboardSource::remove_var(const String &p_name) {
|
||||
ERR_FAIL_COND(!vars.has(p_name));
|
||||
ERR_FAIL_COND(!data.has(p_name));
|
||||
ERR_FAIL_COND(base.is_valid());
|
||||
vars.erase(p_name);
|
||||
data.erase(p_name);
|
||||
}
|
||||
|
||||
BBVariable BlackboardSource::get_var(const String &p_name) {
|
||||
ERR_FAIL_COND_V(!vars.has(p_name), BBVariable());
|
||||
return vars.get(p_name);
|
||||
ERR_FAIL_COND_V(!data.has(p_name), BBVariable());
|
||||
return data.get(p_name);
|
||||
}
|
||||
|
||||
PackedStringArray BlackboardSource::list_vars() const {
|
||||
PackedStringArray ret;
|
||||
for (const KeyValue<String, BBVariable> &kv : vars) {
|
||||
for (const KeyValue<String, BBVariable> &kv : data) {
|
||||
ret.append(kv.key);
|
||||
}
|
||||
return ret;
|
||||
}
|
||||
|
||||
void BlackboardSource::sync_base() {
|
||||
for (const KeyValue<String, BBVariable> &kv : base->vars) {
|
||||
if (!vars.has(kv.key)) {
|
||||
vars.insert(kv.key, kv.value.duplicate());
|
||||
for (const KeyValue<String, BBVariable> &kv : base->data) {
|
||||
if (!data.has(kv.key)) {
|
||||
data.insert(kv.key, kv.value.duplicate());
|
||||
continue;
|
||||
}
|
||||
|
||||
BBVariable var = vars.get(kv.key);
|
||||
BBVariable var = data.get(kv.key);
|
||||
if (!var.is_same_prop_info(kv.value)) {
|
||||
var.copy_prop_info(kv.value);
|
||||
}
|
||||
|
@ -63,8 +63,23 @@ void BlackboardSource::sync_base() {
|
|||
}
|
||||
}
|
||||
|
||||
Ref<Blackboard> BlackboardSource::instantiate() {
|
||||
Ref<Blackboard> BlackboardSource::create_blackboard() {
|
||||
Ref<Blackboard> bb = memnew(Blackboard);
|
||||
// TODO: fill bb
|
||||
for (const KeyValue<String, BBVariable> &kv : data) {
|
||||
bb->add_var(kv.key, kv.value.duplicate());
|
||||
}
|
||||
return bb;
|
||||
}
|
||||
|
||||
void BlackboardSource::populate_blackboard(const Ref<Blackboard> &p_blackboard, bool overwrite) {
|
||||
for (const KeyValue<String, BBVariable> &kv : data) {
|
||||
if (p_blackboard->has_var(kv.key)) {
|
||||
if (overwrite) {
|
||||
p_blackboard->erase_var(kv.key);
|
||||
} else {
|
||||
continue;
|
||||
}
|
||||
}
|
||||
p_blackboard->add_var(kv.key, kv.value.duplicate());
|
||||
}
|
||||
}
|
||||
|
|
|
@ -21,7 +21,7 @@ class BlackboardSource : public Resource {
|
|||
GDCLASS(BlackboardSource, Resource);
|
||||
|
||||
private:
|
||||
HashMap<String, BBVariable> vars;
|
||||
HashMap<String, BBVariable> data;
|
||||
Ref<BlackboardSource> base;
|
||||
// HashMap<String, BBVariable> overrides;
|
||||
|
||||
|
@ -32,9 +32,11 @@ public:
|
|||
void remove_var(const String &p_name);
|
||||
BBVariable get_var(const String &p_name);
|
||||
PackedStringArray list_vars() const;
|
||||
bool is_empty() const { return data.is_empty(); }
|
||||
|
||||
void sync_base();
|
||||
Ref<Blackboard> instantiate();
|
||||
Ref<Blackboard> create_blackboard();
|
||||
void populate_blackboard(const Ref<Blackboard> &p_blackboard, bool overwrite);
|
||||
|
||||
BlackboardSource() = default;
|
||||
};
|
||||
|
|
|
@ -160,6 +160,9 @@ void BTPlayer::_notification(int p_notification) {
|
|||
} break;
|
||||
case NOTIFICATION_READY: {
|
||||
if (!Engine::get_singleton()->is_editor_hint()) {
|
||||
if (blackboard_source.is_valid()) {
|
||||
blackboard = blackboard_source->create_blackboard();
|
||||
}
|
||||
if (behavior_tree.is_valid()) {
|
||||
_load_tree();
|
||||
}
|
||||
|
@ -196,8 +199,8 @@ void BTPlayer::_bind_methods() {
|
|||
ClassDB::bind_method(D_METHOD("set_prefetch_nodepath_vars", "p_value"), &BTPlayer::set_prefetch_nodepath_vars);
|
||||
ClassDB::bind_method(D_METHOD("get_prefetch_nodepath_vars"), &BTPlayer::get_prefetch_nodepath_vars);
|
||||
|
||||
ClassDB::bind_method(D_METHOD("_set_blackboard_data", "p_blackboard"), &BTPlayer::_set_blackboard_data);
|
||||
ClassDB::bind_method(D_METHOD("_get_blackboard_data"), &BTPlayer::_get_blackboard_data);
|
||||
ClassDB::bind_method(D_METHOD("set_blackboard_source", "p_blackboard"), &BTPlayer::set_blackboard_source);
|
||||
ClassDB::bind_method(D_METHOD("get_blackboard_source"), &BTPlayer::get_blackboard_source);
|
||||
|
||||
ClassDB::bind_method(D_METHOD("update", "p_delta"), &BTPlayer::update);
|
||||
ClassDB::bind_method(D_METHOD("restart"), &BTPlayer::restart);
|
||||
|
@ -207,7 +210,7 @@ void BTPlayer::_bind_methods() {
|
|||
ADD_PROPERTY(PropertyInfo(Variant::INT, "update_mode", PROPERTY_HINT_ENUM, "Idle,Physics,Manual"), "set_update_mode", "get_update_mode");
|
||||
ADD_PROPERTY(PropertyInfo(Variant::BOOL, "active"), "set_active", "get_active");
|
||||
ADD_PROPERTY(PropertyInfo(Variant::OBJECT, "blackboard", PROPERTY_HINT_NONE, "Blackboard", 0), "set_blackboard", "get_blackboard");
|
||||
ADD_PROPERTY(PropertyInfo(Variant::DICTIONARY, "_blackboard_data", PROPERTY_HINT_NONE, "", PROPERTY_USAGE_DEFAULT | PROPERTY_USAGE_INTERNAL), "_set_blackboard_data", "_get_blackboard_data");
|
||||
ADD_PROPERTY(PropertyInfo(Variant::OBJECT, "blackboard_source", PROPERTY_HINT_RESOURCE_TYPE, "BlackboardSource", PROPERTY_USAGE_DEFAULT), "set_blackboard_source", "get_blackboard_source");
|
||||
ADD_PROPERTY(PropertyInfo(Variant::BOOL, "prefetch_nodepath_vars"), "set_prefetch_nodepath_vars", "get_prefetch_nodepath_vars");
|
||||
|
||||
BIND_ENUM_CONSTANT(IDLE);
|
||||
|
|
|
@ -13,6 +13,7 @@
|
|||
#define BT_PLAYER_H
|
||||
|
||||
#include "../blackboard/blackboard.h"
|
||||
#include "../blackboard/blackboard_source.h"
|
||||
#include "behavior_tree.h"
|
||||
#include "tasks/bt_task.h"
|
||||
|
||||
|
@ -36,6 +37,7 @@ public:
|
|||
|
||||
private:
|
||||
Ref<BehaviorTree> behavior_tree;
|
||||
Ref<BlackboardSource> blackboard_source;
|
||||
UpdateMode update_mode = UpdateMode::PHYSICS;
|
||||
bool active = true;
|
||||
Ref<Blackboard> blackboard;
|
||||
|
@ -49,15 +51,15 @@ private:
|
|||
protected:
|
||||
static void _bind_methods();
|
||||
|
||||
void _set_blackboard_data(Dictionary p_value) { blackboard->set_data(p_value.duplicate()); }
|
||||
Dictionary _get_blackboard_data() const { return blackboard->get_data(); }
|
||||
|
||||
void _notification(int p_notification);
|
||||
|
||||
public:
|
||||
void set_behavior_tree(const Ref<BehaviorTree> &p_tree);
|
||||
Ref<BehaviorTree> get_behavior_tree() const { return behavior_tree; };
|
||||
|
||||
void set_blackboard_source(const Ref<BlackboardSource> &p_source) { blackboard_source = p_source; }
|
||||
Ref<BlackboardSource> get_blackboard_source() const { return blackboard_source; }
|
||||
|
||||
void set_update_mode(UpdateMode p_mode);
|
||||
UpdateMode get_update_mode() const { return update_mode; }
|
||||
|
||||
|
|
|
@ -15,9 +15,13 @@ void BTNewScope::initialize(Node *p_agent, const Ref<Blackboard> &p_blackboard)
|
|||
ERR_FAIL_COND(p_agent == nullptr);
|
||||
ERR_FAIL_COND(p_blackboard == nullptr);
|
||||
|
||||
Ref<Blackboard> bb = memnew(Blackboard);
|
||||
Ref<Blackboard> bb;
|
||||
if (blackboard_source.is_valid()) {
|
||||
bb = blackboard_source->create_blackboard();
|
||||
} else {
|
||||
bb = Ref<Blackboard>(memnew(Blackboard));
|
||||
}
|
||||
|
||||
bb->set_data(blackboard_data.duplicate());
|
||||
bb->set_parent_scope(p_blackboard);
|
||||
|
||||
BTDecorator::initialize(p_agent, bb);
|
||||
|
@ -29,8 +33,8 @@ BT::Status BTNewScope::_tick(double p_delta) {
|
|||
}
|
||||
|
||||
void BTNewScope::_bind_methods() {
|
||||
ClassDB::bind_method(D_METHOD("_set_blackboard_data", "p_data"), &BTNewScope::_set_blackboard_data);
|
||||
ClassDB::bind_method(D_METHOD("_get_blackboard_data"), &BTNewScope::_get_blackboard_data);
|
||||
ClassDB::bind_method(D_METHOD("set_blackboard_source", "p_source"), &BTNewScope::set_blackboard_source);
|
||||
ClassDB::bind_method(D_METHOD("get_blackboard_source"), &BTNewScope::get_blackboard_source);
|
||||
|
||||
ADD_PROPERTY(PropertyInfo(Variant::DICTIONARY, "_blackboard_data"), "_set_blackboard_data", "_get_blackboard_data");
|
||||
ADD_PROPERTY(PropertyInfo(Variant::OBJECT, "blackboard_source", PROPERTY_HINT_RESOURCE_TYPE, "BlackboardSource", PROPERTY_USAGE_DEFAULT), "set_blackboard_source", "get_blackboard_source");
|
||||
}
|
||||
|
|
|
@ -14,18 +14,20 @@
|
|||
|
||||
#include "../bt_decorator.h"
|
||||
|
||||
#include "../../../blackboard/blackboard_source.h"
|
||||
|
||||
class BTNewScope : public BTDecorator {
|
||||
GDCLASS(BTNewScope, BTDecorator);
|
||||
TASK_CATEGORY(Decorators);
|
||||
|
||||
private:
|
||||
Dictionary blackboard_data;
|
||||
Ref<BlackboardSource> blackboard_source;
|
||||
|
||||
protected:
|
||||
static void _bind_methods();
|
||||
|
||||
void _set_blackboard_data(const Dictionary &p_value) { blackboard_data = p_value; }
|
||||
Dictionary _get_blackboard_data() const { return blackboard_data; }
|
||||
void set_blackboard_source(const Ref<BlackboardSource> &p_source) { blackboard_source = p_source; }
|
||||
Ref<BlackboardSource> get_blackboard_source() const { return blackboard_source; }
|
||||
|
||||
virtual Status _tick(double p_delta) override;
|
||||
|
||||
|
|
|
@ -69,7 +69,8 @@ void LimboState::_initialize(Node *p_agent, const Ref<Blackboard> &p_blackboard)
|
|||
agent = p_agent;
|
||||
|
||||
if (!p_blackboard.is_null()) {
|
||||
if (!blackboard->get_data().is_empty()) {
|
||||
if (blackboard_source.is_valid() && !blackboard_source->is_empty()) {
|
||||
blackboard = blackboard_source->create_blackboard();
|
||||
blackboard->set_parent_scope(p_blackboard);
|
||||
} else {
|
||||
blackboard = p_blackboard;
|
||||
|
@ -179,8 +180,8 @@ void LimboState::_bind_methods() {
|
|||
ClassDB::bind_method(D_METHOD("clear_guard"), &LimboState::clear_guard);
|
||||
ClassDB::bind_method(D_METHOD("get_blackboard"), &LimboState::get_blackboard);
|
||||
|
||||
ClassDB::bind_method(D_METHOD("_set_blackboard_data", "p_blackboard"), &LimboState::_set_blackboard_data);
|
||||
ClassDB::bind_method(D_METHOD("_get_blackboard_data"), &LimboState::_get_blackboard_data);
|
||||
ClassDB::bind_method(D_METHOD("set_blackboard_source", "p_source"), &LimboState::set_blackboard_source);
|
||||
ClassDB::bind_method(D_METHOD("get_blackboard_source"), &LimboState::get_blackboard_source);
|
||||
|
||||
#ifdef LIMBOAI_MODULE
|
||||
GDVIRTUAL_BIND(_setup);
|
||||
|
@ -194,7 +195,7 @@ void LimboState::_bind_methods() {
|
|||
ADD_PROPERTY(PropertyInfo(Variant::STRING, "EVENT_FINISHED", PROPERTY_HINT_NONE, "", 0), "", "event_finished");
|
||||
ADD_PROPERTY(PropertyInfo(Variant::OBJECT, "agent", PROPERTY_HINT_RESOURCE_TYPE, "Node", 0), "set_agent", "get_agent");
|
||||
ADD_PROPERTY(PropertyInfo(Variant::OBJECT, "blackboard", PROPERTY_HINT_RESOURCE_TYPE, "Blackboard", 0), "", "get_blackboard");
|
||||
ADD_PROPERTY(PropertyInfo(Variant::DICTIONARY, "_blackboard_data", PROPERTY_HINT_NONE, "", PROPERTY_USAGE_DEFAULT | PROPERTY_USAGE_INTERNAL), "_set_blackboard_data", "_get_blackboard_data");
|
||||
ADD_PROPERTY(PropertyInfo(Variant::OBJECT, "blackboard_source", PROPERTY_HINT_RESOURCE_TYPE, "BlackboardSource", PROPERTY_USAGE_DEFAULT | PROPERTY_USAGE_INTERNAL), "set_blackboard_source", "get_blackboard_source");
|
||||
|
||||
ADD_SIGNAL(MethodInfo("setup"));
|
||||
ADD_SIGNAL(MethodInfo("entered"));
|
||||
|
|
|
@ -13,6 +13,7 @@
|
|||
#define LIMBO_STATE_H
|
||||
|
||||
#include "../blackboard/blackboard.h"
|
||||
#include "../blackboard/blackboard_source.h"
|
||||
|
||||
#include "../util/limbo_string_names.h"
|
||||
|
||||
|
@ -37,6 +38,7 @@ class LimboState : public Node {
|
|||
GDCLASS(LimboState, Node);
|
||||
|
||||
private:
|
||||
Ref<BlackboardSource> blackboard_source;
|
||||
Node *agent;
|
||||
Ref<Blackboard> blackboard;
|
||||
HashMap<String, Callable> handlers;
|
||||
|
@ -51,9 +53,6 @@ protected:
|
|||
|
||||
void _notification(int p_what);
|
||||
|
||||
void _set_blackboard_data(Dictionary p_value) { blackboard->set_data(p_value.duplicate()); }
|
||||
Dictionary _get_blackboard_data() const { return blackboard->get_data(); }
|
||||
|
||||
virtual void _initialize(Node *p_agent, const Ref<Blackboard> &p_blackboard);
|
||||
|
||||
virtual void _setup();
|
||||
|
@ -71,6 +70,9 @@ protected:
|
|||
void add_event_handler(const String &p_event, const Callable &p_handler);
|
||||
|
||||
public:
|
||||
void set_blackboard_source(const Ref<BlackboardSource> p_source) { blackboard_source = p_source; }
|
||||
Ref<BlackboardSource> get_blackboard_source() const { return blackboard_source; }
|
||||
|
||||
Ref<Blackboard> get_blackboard() const { return blackboard; }
|
||||
|
||||
Node *get_agent() const { return agent; }
|
||||
|
|
Loading…
Reference in New Issue