diff --git a/.vscode/settings.json b/.vscode/settings.json index f4af402..483b5eb 100644 --- a/.vscode/settings.json +++ b/.vscode/settings.json @@ -1,3 +1,3 @@ { - "godotTools.editorPath.godot4": "c:\\Users\\Administrator\\Desktop\\Godot_v4.4-beta4_win64.exe" + "godotTools.editorPath.godot4": "c:\\Users\\Administrator\\Desktop\\Godot_v4.4-stable_win64.exe" } \ No newline at end of file diff --git a/addons/beehave/LICENSE b/addons/beehave/LICENSE deleted file mode 100644 index caabbff..0000000 --- a/addons/beehave/LICENSE +++ /dev/null @@ -1,21 +0,0 @@ -MIT License - -Copyright (c) 2023 bitbrain - -Permission is hereby granted, free of charge, to any person obtaining a copy -of this software and associated documentation files (the "Software"), to deal -in the Software without restriction, including without limitation the rights -to use, copy, modify, merge, publish, distribute, sublicense, and/or sell -copies of the Software, and to permit persons to whom the Software is -furnished to do so, subject to the following conditions: - -The above copyright notice and this permission notice shall be included in all -copies or substantial portions of the Software. - -THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR -IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, -FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE -AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER -LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, -OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE -SOFTWARE. diff --git a/addons/beehave/blackboard.gd b/addons/beehave/blackboard.gd deleted file mode 100644 index e4ad82b..0000000 --- a/addons/beehave/blackboard.gd +++ /dev/null @@ -1,54 +0,0 @@ -@icon("icons/blackboard.svg") -class_name Blackboard extends Node - -const DEFAULT = "default" - -## The blackboard is an object that can be used to store and access data between -## multiple nodes of the behavior tree. -@export var blackboard: Dictionary = {}: - set(b): - blackboard = b - _data[DEFAULT] = blackboard - -var _data: Dictionary = {} - - -func _ready(): - _data[DEFAULT] = blackboard - - -func keys() -> Array[String]: - var keys: Array[String] - keys.assign(_data.keys().duplicate()) - return keys - - -func set_value(key: Variant, value: Variant, blackboard_name: String = DEFAULT) -> void: - if not _data.has(blackboard_name): - _data[blackboard_name] = {} - - _data[blackboard_name][key] = value - - -func get_value( - key: Variant, default_value: Variant = null, blackboard_name: String = DEFAULT -) -> Variant: - if has_value(key, blackboard_name): - return _data[blackboard_name].get(key, default_value) - return default_value - - -func has_value(key: Variant, blackboard_name: String = DEFAULT) -> bool: - return ( - _data.has(blackboard_name) - and _data[blackboard_name].has(key) - and _data[blackboard_name][key] != null - ) - - -func erase_value(key: Variant, blackboard_name: String = DEFAULT) -> void: - if _data.has(blackboard_name): - _data[blackboard_name][key] = null - -func get_debug_data() -> Dictionary: - return _data diff --git a/addons/beehave/blackboard.gd.uid b/addons/beehave/blackboard.gd.uid deleted file mode 100644 index c333597..0000000 --- a/addons/beehave/blackboard.gd.uid +++ /dev/null @@ -1 +0,0 @@ -uid://crllxirc7qsfn diff --git a/addons/beehave/debug/debugger.gd b/addons/beehave/debug/debugger.gd deleted file mode 100644 index a41e072..0000000 --- a/addons/beehave/debug/debugger.gd +++ /dev/null @@ -1,96 +0,0 @@ -@tool -extends EditorDebuggerPlugin - -const DebuggerTab := preload("debugger_tab.gd") -const BeehaveUtils := preload("res://addons/beehave/utils/utils.gd") - -var debugger_tab := DebuggerTab.new() -var floating_window: Window -var session: EditorDebuggerSession - - -func _has_capture(prefix: String) -> bool: - return prefix == "beehave" - - -func _capture(message: String, data: Array, session_id: int) -> bool: - # in case the behavior tree has invalid setup this might be null - if debugger_tab == null: - return false - - if message == "beehave:register_tree": - debugger_tab.register_tree(data[0]) - return true - if message == "beehave:unregister_tree": - debugger_tab.unregister_tree(data[0]) - return true - if message == "beehave:process_tick": - debugger_tab.graph.process_tick(data[0], data[1], data[2]) - return true - if message == "beehave:process_begin": - debugger_tab.graph.process_begin(data[0], data[1]) - return true - if message == "beehave:process_end": - debugger_tab.graph.process_end(data[0], data[1]) - return true - return false - - -func _setup_session(session_id: int) -> void: - session = get_session(session_id) - session.started.connect(debugger_tab.start) - session.stopped.connect(debugger_tab.stop) - - debugger_tab.name = "🐝 Beehave" - debugger_tab.make_floating.connect(_on_make_floating) - debugger_tab.session = session - session.add_session_tab(debugger_tab) - - -func _on_make_floating() -> void: - var plugin := BeehaveUtils.get_plugin() - if not plugin: - return - if floating_window: - _on_window_close_requested() - return - - var border_size := Vector2(4, 4) * BeehaveUtils.get_editor_scale() - var editor_interface: EditorInterface = plugin.get_editor_interface() - var editor_main_screen = editor_interface.get_editor_main_screen() - debugger_tab.get_parent().remove_child(debugger_tab) - - floating_window = Window.new() - - var panel := Panel.new() - panel.add_theme_stylebox_override( - "panel", - editor_interface.get_base_control().get_theme_stylebox("PanelForeground", "EditorStyles") - ) - panel.set_anchors_and_offsets_preset(Control.PRESET_FULL_RECT) - floating_window.add_child(panel) - - var margin := MarginContainer.new() - margin.add_child(debugger_tab) - margin.set_anchors_and_offsets_preset(Control.PRESET_FULL_RECT) - margin.add_theme_constant_override("margin_right", border_size.x) - margin.add_theme_constant_override("margin_left", border_size.x) - margin.add_theme_constant_override("margin_top", border_size.y) - margin.add_theme_constant_override("margin_bottom", border_size.y) - panel.add_child(margin) - - floating_window.title = "🐝 Beehave" - floating_window.wrap_controls = true - floating_window.min_size = Vector2i(600, 350) - floating_window.size = debugger_tab.size - floating_window.position = editor_main_screen.global_position - floating_window.transient = true - floating_window.close_requested.connect(_on_window_close_requested) - editor_interface.get_base_control().add_child(floating_window) - - -func _on_window_close_requested() -> void: - debugger_tab.get_parent().remove_child(debugger_tab) - session.add_session_tab(debugger_tab) - floating_window.queue_free() - floating_window = null diff --git a/addons/beehave/debug/debugger.gd.uid b/addons/beehave/debug/debugger.gd.uid deleted file mode 100644 index efad0c3..0000000 --- a/addons/beehave/debug/debugger.gd.uid +++ /dev/null @@ -1 +0,0 @@ -uid://c77f2xt5d4dco diff --git a/addons/beehave/debug/debugger_messages.gd b/addons/beehave/debug/debugger_messages.gd deleted file mode 100644 index caae409..0000000 --- a/addons/beehave/debug/debugger_messages.gd +++ /dev/null @@ -1,30 +0,0 @@ -class_name BeehaveDebuggerMessages - - -static func can_send_message() -> bool: - return not Engine.is_editor_hint() and OS.has_feature("editor") - - -static func register_tree(beehave_tree: Dictionary) -> void: - if can_send_message(): - EngineDebugger.send_message("beehave:register_tree", [beehave_tree]) - - -static func unregister_tree(instance_id: int) -> void: - if can_send_message(): - EngineDebugger.send_message("beehave:unregister_tree", [instance_id]) - - -static func process_tick(instance_id: int, status: int, blackboard: Dictionary = {}) -> void: - if can_send_message(): - EngineDebugger.send_message("beehave:process_tick", [instance_id, status, blackboard]) - - -static func process_begin(instance_id: int, blackboard: Dictionary = {}) -> void: - if can_send_message(): - EngineDebugger.send_message("beehave:process_begin", [instance_id, blackboard]) - - -static func process_end(instance_id: int, blackboard: Dictionary = {}) -> void: - if can_send_message(): - EngineDebugger.send_message("beehave:process_end", [instance_id, blackboard]) diff --git a/addons/beehave/debug/debugger_messages.gd.uid b/addons/beehave/debug/debugger_messages.gd.uid deleted file mode 100644 index 4174f27..0000000 --- a/addons/beehave/debug/debugger_messages.gd.uid +++ /dev/null @@ -1 +0,0 @@ -uid://cplt41hqmgca2 diff --git a/addons/beehave/debug/debugger_tab.gd b/addons/beehave/debug/debugger_tab.gd deleted file mode 100644 index ec23d29..0000000 --- a/addons/beehave/debug/debugger_tab.gd +++ /dev/null @@ -1,157 +0,0 @@ -@tool -class_name BeehaveDebuggerTab extends PanelContainer - -const BeehaveUtils := preload("res://addons/beehave/utils/utils.gd") - -signal make_floating - -const OldBeehaveGraphEdit := preload("old_graph_edit.gd") -const NewBeehaveGraphEdit := preload("new_graph_edit.gd") -const NewNodeBlackBoard := preload("new_node_blackboard.gd") - -const TREE_ICON := preload("../icons/tree.svg") - -var graph -var container: HSplitContainer -var graph_container: HSplitContainer -var item_list: ItemList -var blackboard_vbox: VBoxContainer -var message: Label - -var active_trees: Dictionary -var active_tree_id: int = -1 -var session: EditorDebuggerSession - - -func _ready() -> void: - container = HSplitContainer.new() - add_child(container) - - item_list = ItemList.new() - item_list.custom_minimum_size = Vector2(200, 0) - item_list.item_selected.connect(_on_item_selected) - container.add_child(item_list) - - graph_container = HSplitContainer.new() - graph_container.split_offset = 1920 - graph_container.set_anchors_preset(Control.PRESET_FULL_RECT) - container.add_child(graph_container) - - if Engine.get_version_info().minor >= 2: - graph = NewBeehaveGraphEdit.new(BeehaveUtils.get_frames()) - else: - graph = OldBeehaveGraphEdit.new(BeehaveUtils.get_frames()) - - graph.node_selected.connect(_on_graph_node_selected) - graph.node_deselected.connect(_on_graph_node_deselected) - graph_container.add_child(graph) - - blackboard_vbox = VBoxContainer.new() - blackboard_vbox.custom_minimum_size = Vector2(200, 0) - blackboard_vbox.set_anchors_preset(Control.PRESET_FULL_RECT) - graph_container.add_child(blackboard_vbox) - - message = Label.new() - message.text = "Run Project for debugging" - message.horizontal_alignment = HORIZONTAL_ALIGNMENT_CENTER - message.vertical_alignment = VERTICAL_ALIGNMENT_CENTER - message.set_anchors_preset(Control.PRESET_CENTER) - add_child(message) - - var button := Button.new() - button.flat = true - button.name = "MakeFloatingButton" - button.icon = get_theme_icon(&"ExternalLink", &"EditorIcons") - button.pressed.connect(func(): make_floating.emit()) - button.tooltip_text = "Make floating" - button.focus_mode = Control.FOCUS_NONE - graph.get_menu_container().add_child(button) - - var toggle_button := Button.new() - toggle_button.flat = true - toggle_button.name = "TogglePanelButton" - toggle_button.icon = get_theme_icon(&"Back", &"EditorIcons") - toggle_button.pressed.connect(_on_toggle_button_pressed.bind(toggle_button)) - toggle_button.tooltip_text = "Toggle Panel" - toggle_button.focus_mode = Control.FOCUS_NONE - graph.get_menu_container().add_child(toggle_button) - graph.get_menu_container().move_child(toggle_button, 0) - - stop() - visibility_changed.connect(_on_visibility_changed) - - -func start() -> void: - container.visible = true - message.visible = false - - -func stop() -> void: - container.visible = false - message.visible = true - - active_trees.clear() - item_list.clear() - graph.beehave_tree = {} - - -func register_tree(data: Dictionary) -> void: - if not active_trees.has(data.id): - var idx := item_list.add_item(data.name, TREE_ICON) - item_list.set_item_tooltip(idx, data.path) - item_list.set_item_metadata(idx, data.id) - - active_trees[data.id] = data - - if active_tree_id == data.id.to_int(): - graph.beehave_tree = data - - -func unregister_tree(instance_id: int) -> void: - var id := str(instance_id) - for i in item_list.item_count: - if item_list.get_item_metadata(i) == id: - item_list.remove_item(i) - break - - active_trees.erase(id) - - if graph.beehave_tree.get("id", "") == id: - graph.beehave_tree = {} - - -func _on_toggle_button_pressed(toggle_button: Button) -> void: - item_list.visible = !item_list.visible - toggle_button.icon = get_theme_icon( - &"Back" if item_list.visible else &"Forward", &"EditorIcons" - ) - - -func _on_item_selected(idx: int) -> void: - var id: StringName = item_list.get_item_metadata(idx) - graph.beehave_tree = active_trees.get(id, {}) - - # Clear our any loaded blackboards - for child in blackboard_vbox.get_children(): - child.free() - - active_tree_id = id.to_int() - if session != null: - session.send_message("beehave:activate_tree", [active_tree_id]) - -func _on_graph_node_selected(node: GraphNode) -> void: - var node_blackboard: VBoxContainer = NewNodeBlackBoard.new(BeehaveUtils.get_frames(), node) - blackboard_vbox.add_child(node_blackboard) - -func _on_graph_node_deselected(node: GraphNode) -> void: - var matches: Array = blackboard_vbox\ - .get_children()\ - .filter(func (child): return child.name == node.name) - - for child in matches: - child.free() - - -func _on_visibility_changed() -> void: - if session != null: - session.send_message("beehave:visibility_changed", [visible and is_visible_in_tree()]) diff --git a/addons/beehave/debug/debugger_tab.gd.uid b/addons/beehave/debug/debugger_tab.gd.uid deleted file mode 100644 index f4b945b..0000000 --- a/addons/beehave/debug/debugger_tab.gd.uid +++ /dev/null @@ -1 +0,0 @@ -uid://cleq4b5ah7g7h diff --git a/addons/beehave/debug/global_debugger.gd b/addons/beehave/debug/global_debugger.gd deleted file mode 100644 index 7350b3e..0000000 --- a/addons/beehave/debug/global_debugger.gd +++ /dev/null @@ -1,38 +0,0 @@ -extends Node - -var _registered_trees: Dictionary -var _active_tree - - -func _enter_tree() -> void: - EngineDebugger.register_message_capture("beehave", _on_debug_message) - - -func _on_debug_message(message: String, data: Array) -> bool: - if message == "activate_tree": - _set_active_tree(data[0]) - return true - if message == "visibility_changed": - if _active_tree && is_instance_valid(_active_tree): - _active_tree._can_send_message = data[0] - return true - return false - - -func _set_active_tree(tree_id: int) -> void: - var tree = _registered_trees.get(tree_id, null) - if not tree: - return - - if _active_tree && is_instance_valid(_active_tree): - _active_tree._can_send_message = false - _active_tree = tree - _active_tree._can_send_message = true - - -func register_tree(tree) -> void: - _registered_trees[tree.get_instance_id()] = tree - - -func unregister_tree(tree) -> void: - _registered_trees.erase(tree.get_instance_id()) diff --git a/addons/beehave/debug/global_debugger.gd.uid b/addons/beehave/debug/global_debugger.gd.uid deleted file mode 100644 index 509a956..0000000 --- a/addons/beehave/debug/global_debugger.gd.uid +++ /dev/null @@ -1 +0,0 @@ -uid://07wefmshac25 diff --git a/addons/beehave/debug/icons/horizontal_layout.svg b/addons/beehave/debug/icons/horizontal_layout.svg deleted file mode 100644 index 235dc62..0000000 --- a/addons/beehave/debug/icons/horizontal_layout.svg +++ /dev/null @@ -1 +0,0 @@ - \ No newline at end of file diff --git a/addons/beehave/debug/icons/port_bottom.svg b/addons/beehave/debug/icons/port_bottom.svg deleted file mode 100644 index 3ce70e7..0000000 --- a/addons/beehave/debug/icons/port_bottom.svg +++ /dev/null @@ -1 +0,0 @@ - \ No newline at end of file diff --git a/addons/beehave/debug/icons/port_left.svg b/addons/beehave/debug/icons/port_left.svg deleted file mode 100644 index c1f6717..0000000 --- a/addons/beehave/debug/icons/port_left.svg +++ /dev/null @@ -1 +0,0 @@ - \ No newline at end of file diff --git a/addons/beehave/debug/icons/port_right.svg b/addons/beehave/debug/icons/port_right.svg deleted file mode 100644 index 2560af5..0000000 --- a/addons/beehave/debug/icons/port_right.svg +++ /dev/null @@ -1 +0,0 @@ - \ No newline at end of file diff --git a/addons/beehave/debug/icons/port_top.svg b/addons/beehave/debug/icons/port_top.svg deleted file mode 100644 index d3b99e1..0000000 --- a/addons/beehave/debug/icons/port_top.svg +++ /dev/null @@ -1 +0,0 @@ - \ No newline at end of file diff --git a/addons/beehave/debug/icons/vertical_layout.svg b/addons/beehave/debug/icons/vertical_layout.svg deleted file mode 100644 index d59ffb0..0000000 --- a/addons/beehave/debug/icons/vertical_layout.svg +++ /dev/null @@ -1 +0,0 @@ - \ No newline at end of file diff --git a/addons/beehave/debug/new_frames.gd b/addons/beehave/debug/new_frames.gd deleted file mode 100644 index 4b739fd..0000000 --- a/addons/beehave/debug/new_frames.gd +++ /dev/null @@ -1,69 +0,0 @@ -@tool -extends RefCounted - - -const BeehaveUtils := preload("res://addons/beehave/utils/utils.gd") - - -const SUCCESS_COLOR := Color("#07783a") -const NORMAL_COLOR := Color("#15181e") -const FAILURE_COLOR := Color("#82010b") -const RUNNING_COLOR := Color("#c29c06") - -var panel_normal: StyleBoxFlat -var panel_success: StyleBoxFlat -var panel_failure: StyleBoxFlat -var panel_running: StyleBoxFlat - -var titlebar_normal: StyleBoxFlat -var titlebar_success: StyleBoxFlat -var titlebar_failure: StyleBoxFlat -var titlebar_running: StyleBoxFlat - - -func _init() -> void: - var plugin := BeehaveUtils.get_plugin() - if not plugin: - return - - - titlebar_normal = ( - plugin - .get_editor_interface() - .get_base_control() - .get_theme_stylebox(&"titlebar", &"GraphNode")\ - .duplicate() - ) - titlebar_success = titlebar_normal.duplicate() - titlebar_failure = titlebar_normal.duplicate() - titlebar_running = titlebar_normal.duplicate() - - titlebar_success.bg_color = SUCCESS_COLOR - titlebar_failure.bg_color = FAILURE_COLOR - titlebar_running.bg_color = RUNNING_COLOR - - titlebar_success.border_color = SUCCESS_COLOR - titlebar_failure.border_color = FAILURE_COLOR - titlebar_running.border_color = RUNNING_COLOR - - - panel_normal = ( - plugin - .get_editor_interface() - .get_base_control() - .get_theme_stylebox(&"panel", &"GraphNode") - .duplicate() - ) - panel_success = ( - plugin - .get_editor_interface() - .get_base_control() - .get_theme_stylebox(&"panel_selected", &"GraphNode") - .duplicate() - ) - panel_failure = panel_success.duplicate() - panel_running = panel_success.duplicate() - - panel_success.border_color = SUCCESS_COLOR - panel_failure.border_color = FAILURE_COLOR - panel_running.border_color = RUNNING_COLOR diff --git a/addons/beehave/debug/new_frames.gd.uid b/addons/beehave/debug/new_frames.gd.uid deleted file mode 100644 index 128e76b..0000000 --- a/addons/beehave/debug/new_frames.gd.uid +++ /dev/null @@ -1 +0,0 @@ -uid://dw4y5y72460ru diff --git a/addons/beehave/debug/new_graph_edit.gd b/addons/beehave/debug/new_graph_edit.gd deleted file mode 100644 index 8e0c607..0000000 --- a/addons/beehave/debug/new_graph_edit.gd +++ /dev/null @@ -1,297 +0,0 @@ -@tool -extends GraphEdit - -const BeehaveGraphNode := preload("new_graph_node.gd") - -const HORIZONTAL_LAYOUT_ICON := preload("icons/horizontal_layout.svg") -const VERTICAL_LAYOUT_ICON := preload("icons/vertical_layout.svg") - -const PROGRESS_SHIFT: int = 50 -const INACTIVE_COLOR: Color = Color("#898989") -const ACTIVE_COLOR: Color = Color("#c29c06") -const SUCCESS_COLOR: Color = Color("#07783a") - - -var updating_graph: bool = false -var arraging_nodes: bool = false -var beehave_tree: Dictionary: - set(value): - if beehave_tree == value: - return - beehave_tree = value - active_nodes.clear() - _update_graph() - -var horizontal_layout: bool = false: - set(value): - if updating_graph or arraging_nodes: - return - if horizontal_layout == value: - return - horizontal_layout = value - _update_layout_button() - _update_graph() - - -var frames:RefCounted -var active_nodes: Array[String] -var progress: int = 0 -var layout_button: Button - - -func _init(frames:RefCounted) -> void: - self.frames = frames - - -func _ready() -> void: - custom_minimum_size = Vector2(100, 300) - set("show_arrange_button", true) - minimap_enabled = false - layout_button = Button.new() - layout_button.flat = true - layout_button.focus_mode = Control.FOCUS_NONE - layout_button.pressed.connect(func(): horizontal_layout = not horizontal_layout) - get_menu_container().add_child(layout_button) - _update_layout_button() - - -func _update_graph() -> void: - if updating_graph: - return - - updating_graph = true - - clear_connections() - - for child in _get_child_nodes(): - remove_child(child) - child.queue_free() - - if not beehave_tree.is_empty(): - _add_nodes(beehave_tree) - _connect_nodes(beehave_tree) - _arrange_nodes.call_deferred(beehave_tree) - - updating_graph = false - - -func _add_nodes(node: Dictionary) -> void: - if node.is_empty(): - return - var gnode := BeehaveGraphNode.new(frames, horizontal_layout) - add_child(gnode) - gnode.title_text = node.name - gnode.name = node.id - gnode.icon = _get_icon(node.type.back()) - - if node.type.has(&"BeehaveTree"): - gnode.set_slots(false, true) - elif node.type.has(&"Leaf"): - gnode.set_slots(true, false) - elif node.type.has(&"Composite") or node.type.has(&"Decorator"): - gnode.set_slots(true, true) - - for child in node.get("children", []): - _add_nodes(child) - - -func _connect_nodes(node: Dictionary) -> void: - for child in node.get("children", []): - connect_node(node.id, 0, child.id, 0) - _connect_nodes(child) - - -func _arrange_nodes(node: Dictionary) -> void: - if arraging_nodes: - return - - arraging_nodes = true - - var tree_node := _create_tree_nodes(node) - tree_node.update_positions(horizontal_layout) - _place_nodes(tree_node) - - arraging_nodes = false - - -func _create_tree_nodes(node: Dictionary, root: TreeNode = null) -> TreeNode: - var tree_node := TreeNode.new(get_node(node.id), root) - for child in node.get("children", []): - var child_node := _create_tree_nodes(child, tree_node) - tree_node.children.push_back(child_node) - return tree_node - - -func _place_nodes(node: TreeNode) -> void: - node.item.position_offset = Vector2(node.x, node.y) - for child in node.children: - _place_nodes(child) - - -func _get_icon(type: StringName) -> Texture2D: - var classes := ProjectSettings.get_global_class_list() - for c in classes: - if c["class"] == type: - var icon_path := c.get("icon", String()) - if not icon_path.is_empty(): - return load(icon_path) - return null - - -func get_menu_container() -> Control: - return call("get_menu_hbox") - - -func get_status(status: int) -> String: - if status == 0: - return "SUCCESS" - elif status == 1: - return "FAILURE" - return "RUNNING" - - -func process_begin(instance_id: int, blackboard = null) -> void: - if not _is_same_tree(instance_id): - return - - for child in _get_child_nodes(): - child.set_meta("status", -1) - - -func process_tick(instance_id: int, status: int, blackboard = null) -> void: - var node := get_node_or_null(str(instance_id)) - if node: - node.text = "Status: %s" % get_status(status) - node.set_status(status) - node.set_meta("status", status) - node.blackboard = blackboard - if status == BeehaveNode.SUCCESS or status == BeehaveNode.RUNNING: - if not active_nodes.has(node.name): - active_nodes.push_back(node.name) - - -func process_end(instance_id: int, blackboard = null) -> void: - if not _is_same_tree(instance_id): - return - - for child in _get_child_nodes(): - var status := child.get_meta("status", -1) - match status: - BeehaveNode.SUCCESS: - active_nodes.erase(child.name) - child.set_color(SUCCESS_COLOR) - BeehaveNode.FAILURE: - active_nodes.erase(child.name) - child.set_color(INACTIVE_COLOR) - BeehaveNode.RUNNING: - child.set_color(ACTIVE_COLOR) - _: - child.text = " " - child.set_status(status) - child.set_color(INACTIVE_COLOR) - - -func _is_same_tree(instance_id: int) -> bool: - return str(instance_id) == beehave_tree.get("id", "") - - -func _get_child_nodes() -> Array[Node]: - return get_children().filter(func(child): return child is BeehaveGraphNode) - - -func _get_connection_line(from_position: Vector2, to_position: Vector2) -> PackedVector2Array: - for child in _get_child_nodes(): - for port in child.get_input_port_count(): - if not (child.position_offset + child.get_input_port_position(port)).is_equal_approx(to_position): - continue - to_position = child.position_offset + child.get_custom_input_port_position(horizontal_layout) - for port in child.get_output_port_count(): - if not (child.position_offset + child.get_output_port_position(port)).is_equal_approx(from_position): - continue - from_position = child.position_offset + child.get_custom_output_port_position(horizontal_layout) - return _get_elbow_connection_line(from_position, to_position) - - -func _get_elbow_connection_line(from_position: Vector2, to_position: Vector2) -> PackedVector2Array: - var points: PackedVector2Array - - points.push_back(from_position) - - var mid_position := ((to_position + from_position) / 2).round() - if horizontal_layout: - points.push_back(Vector2(mid_position.x, from_position.y)) - points.push_back(Vector2(mid_position.x, to_position.y)) - else: - points.push_back(Vector2(from_position.x, mid_position.y)) - points.push_back(Vector2(to_position.x, mid_position.y)) - - points.push_back(to_position) - - return points - - -func _process(delta: float) -> void: - if not active_nodes.is_empty(): - progress += 10 if delta >= 0.05 else 1 - if progress >= 1000: - progress = 0 - queue_redraw() - - -func _draw() -> void: - if active_nodes.is_empty(): - return - - var circle_size: float = max(3, 6 * zoom) - var progress_shift: float = PROGRESS_SHIFT * zoom - - var connections := get_connection_list() - for c in connections: - var from_node: StringName - var to_node: StringName - - from_node = c.from_node - to_node = c.to_node - - if not from_node in active_nodes or not c.to_node in active_nodes: - continue - - var from := get_node(String(from_node)) - var to := get_node(String(to_node)) - - if from.get_meta("status", -1) < 0 or to.get_meta("status", -1) < 0: - return - - var output_port_position: Vector2 - var input_port_position: Vector2 - - var scale_factor: float = from.get_rect().size.x / from.size.x - - var line := _get_elbow_connection_line( - from.position + from.get_custom_output_port_position(horizontal_layout) * scale_factor, - to.position + to.get_custom_input_port_position(horizontal_layout) * scale_factor - ) - - var curve = Curve2D.new() - for l in line: - curve.add_point(l) - - var max_steps := int(curve.get_baked_length()) - var current_shift := progress % max_steps - var p := curve.sample_baked(current_shift) - draw_circle(p, circle_size, ACTIVE_COLOR) - - var shift := current_shift - progress_shift - while shift >= 0: - draw_circle(curve.sample_baked(shift), circle_size, ACTIVE_COLOR) - shift -= progress_shift - - shift = current_shift + progress_shift - while shift <= curve.get_baked_length(): - draw_circle(curve.sample_baked(shift), circle_size, ACTIVE_COLOR) - shift += progress_shift - - -func _update_layout_button() -> void: - layout_button.icon = VERTICAL_LAYOUT_ICON if horizontal_layout else HORIZONTAL_LAYOUT_ICON - layout_button.tooltip_text = "Switch to Vertical layout" if horizontal_layout else "Switch to Horizontal layout" diff --git a/addons/beehave/debug/new_graph_edit.gd.uid b/addons/beehave/debug/new_graph_edit.gd.uid deleted file mode 100644 index f28ae9e..0000000 --- a/addons/beehave/debug/new_graph_edit.gd.uid +++ /dev/null @@ -1 +0,0 @@ -uid://bmvb48x7vicyg diff --git a/addons/beehave/debug/new_graph_node.gd b/addons/beehave/debug/new_graph_node.gd deleted file mode 100644 index dbef42b..0000000 --- a/addons/beehave/debug/new_graph_node.gd +++ /dev/null @@ -1,192 +0,0 @@ -@tool -extends GraphNode - -signal blackboard_updated - -const BeehaveUtils := preload("res://addons/beehave/utils/utils.gd") - -const PORT_TOP_ICON := preload("icons/port_top.svg") -const PORT_BOTTOM_ICON := preload("icons/port_bottom.svg") -const PORT_LEFT_ICON := preload("icons/port_left.svg") -const PORT_RIGHT_ICON := preload("icons/port_right.svg") - - -@export var title_text: String: - set(value): - title_text = value - if title_label: - title_label.text = value - -@export var text: String: - set(value): - text = value - if label: - label.text = " " if text.is_empty() else text - -@export var icon: Texture2D: - set(value): - icon = value - if icon_rect: - icon_rect.texture = value - -@export var blackboard: Dictionary: - set(value): - blackboard = value - blackboard_updated.emit() - -var layout_size: float: - get: - return size.y if horizontal else size.x - - -var icon_rect: TextureRect -var title_label: Label -var label: Label -var titlebar_hbox: HBoxContainer - -var frames: RefCounted -var horizontal: bool = false -var panels_tween: Tween - - -func _init(frames:RefCounted, horizontal: bool = false) -> void: - self.frames = frames - self.horizontal = horizontal - - -func _ready() -> void: - custom_minimum_size = Vector2(50, 50) * BeehaveUtils.get_editor_scale() - draggable = false - - add_theme_color_override("close_color", Color.TRANSPARENT) - add_theme_icon_override("close", ImageTexture.new()) - - # For top port - var top_port: Control = Control.new() - add_child(top_port) - - icon_rect = TextureRect.new() - icon_rect.stretch_mode = TextureRect.STRETCH_KEEP_ASPECT_CENTERED - - titlebar_hbox = get_titlebar_hbox() - titlebar_hbox.get_child(0).queue_free() - titlebar_hbox.alignment = BoxContainer.ALIGNMENT_BEGIN - titlebar_hbox.add_child(icon_rect) - - title_label = Label.new() - title_label.add_theme_color_override("font_color", Color.WHITE) - var title_font: Font = get_theme_font("title_font").duplicate() - if title_font is FontVariation: - title_font.variation_embolden = 1 - elif title_font is FontFile: - title_font.font_weight = 700 - title_label.add_theme_font_override("font", title_font) - title_label.vertical_alignment = VERTICAL_ALIGNMENT_CENTER - title_label.size_flags_horizontal = Control.SIZE_EXPAND_FILL - title_label.text = title_text - titlebar_hbox.add_child(title_label) - - label = Label.new() - label.text = " " if text.is_empty() else text - add_child(label) - - # For bottom port - add_child(Control.new()) - - minimum_size_changed.connect(_on_size_changed) - _on_size_changed.call_deferred() - - -func _draw_port(slot_index: int, port_position: Vector2i, left: bool, color: Color) -> void: - if horizontal: - if is_slot_enabled_left(1): - draw_texture(PORT_LEFT_ICON, Vector2(0, size.y / 2) + Vector2(-4, -5), color) - if is_slot_enabled_right(1): - draw_texture(PORT_RIGHT_ICON, Vector2(size.x, size.y / 2) + Vector2(-5, -4.5), color) - else: - if slot_index == 0 and is_slot_enabled_left(0): - draw_texture(PORT_TOP_ICON, Vector2(size.x / 2, 0) + Vector2(-4.5, -7), color) - elif slot_index == 1: - draw_texture(PORT_BOTTOM_ICON, Vector2(size.x / 2, size.y) + Vector2(-4.5, -5), color) - - -func get_custom_input_port_position(horizontal: bool) -> Vector2: - if horizontal: - return Vector2(0, size.y / 2) - else: - return Vector2(size.x/2, 0) - - -func get_custom_output_port_position(horizontal: bool) -> Vector2: - if horizontal: - return Vector2(size.x, size.y / 2) - else: - return Vector2(size.x / 2, size.y) - - -func set_status(status: int) -> void: - match status: - BeehaveNode.SUCCESS: _set_stylebox_overrides(frames.panel_success, frames.titlebar_success) - BeehaveNode.FAILURE: _set_stylebox_overrides(frames.panel_failure, frames.titlebar_failure) - BeehaveNode.RUNNING: _set_stylebox_overrides(frames.panel_running, frames.titlebar_running) - _: _set_stylebox_overrides(frames.panel_normal, frames.titlebar_normal) - - -func set_slots(left_enabled: bool, right_enabled: bool) -> void: - if horizontal: - set_slot(1, left_enabled, -1, Color.WHITE, right_enabled, -1, Color.WHITE, PORT_LEFT_ICON, PORT_RIGHT_ICON) - else: - set_slot(0, left_enabled, -1, Color.WHITE, false, -1, Color.TRANSPARENT, PORT_TOP_ICON, null) - set_slot(2, false, -1, Color.TRANSPARENT, right_enabled, -1, Color.WHITE, null, PORT_BOTTOM_ICON) - - -func set_color(color: Color) -> void: - set_input_color(color) - set_output_color(color) - - -func set_input_color(color: Color) -> void: - set_slot_color_left(1 if horizontal else 0, color) - - -func set_output_color(color: Color) -> void: - set_slot_color_right(1 if horizontal else 2, color) - - -func _set_stylebox_overrides(panel_stylebox: StyleBox, titlebar_stylebox: StyleBox) -> void: - # First update and any status change gets immediate panel update - if not has_theme_stylebox_override("panel") or panel_stylebox != frames.panel_normal: - if panels_tween: - panels_tween.kill() - panels_tween = null - - add_theme_stylebox_override("panel", panel_stylebox) - add_theme_stylebox_override("titlebar", titlebar_stylebox) - return - - # Don't need to do anything if we're already tweening back to normal - if panels_tween: - return - - # Don't need to do anything if our colors are already the same as a normal - var cur_panel_stylebox: StyleBox = get_theme_stylebox("panel") - var cur_titlebar_stylebox: StyleBox = get_theme_stylebox("titlebar") - if cur_panel_stylebox.bg_color == frames.panel_normal.bg_color: - return - - # Apply a duplicate of our current panels that we can tween - add_theme_stylebox_override("panel", cur_panel_stylebox.duplicate()) - add_theme_stylebox_override("titlebar", cur_titlebar_stylebox.duplicate()) - cur_panel_stylebox = get_theme_stylebox("panel") - cur_titlebar_stylebox = get_theme_stylebox("titlebar") - - # Going back to normal is a fade - panels_tween = create_tween() - panels_tween.parallel().tween_property(cur_panel_stylebox, "bg_color", panel_stylebox.bg_color, 1.0) - panels_tween.parallel().tween_property(cur_panel_stylebox, "border_color", panel_stylebox.border_color, 1.0) - panels_tween.parallel().tween_property(cur_titlebar_stylebox, "bg_color", panel_stylebox.bg_color, 1.0) - panels_tween.parallel().tween_property(cur_titlebar_stylebox, "border_color", panel_stylebox.border_color, 1.0) - - -func _on_size_changed(): - add_theme_constant_override("port_offset", 12 * BeehaveUtils.get_editor_scale() if horizontal else round(size.x)) diff --git a/addons/beehave/debug/new_graph_node.gd.uid b/addons/beehave/debug/new_graph_node.gd.uid deleted file mode 100644 index 9639810..0000000 --- a/addons/beehave/debug/new_graph_node.gd.uid +++ /dev/null @@ -1 +0,0 @@ -uid://7gnkreado2vd diff --git a/addons/beehave/debug/new_node_blackboard.gd b/addons/beehave/debug/new_node_blackboard.gd deleted file mode 100644 index 75c533f..0000000 --- a/addons/beehave/debug/new_node_blackboard.gd +++ /dev/null @@ -1,76 +0,0 @@ -extends VBoxContainer - -var frames: RefCounted -var graph_node: GraphNode - -var item_tree: Tree - -func _init(frames: RefCounted, node: GraphNode) -> void: - self.frames = frames - graph_node = node - - graph_node.blackboard_updated.connect(_update_list) - -func _ready() -> void: - name = graph_node.name - - set_anchors_preset(Control.PRESET_FULL_RECT) - - var title_panel: Panel = Panel.new() - title_panel.set_anchors_preset(Control.PRESET_FULL_RECT) - title_panel.custom_minimum_size = Vector2(200, 50) - add_child(title_panel) - var title_hbox: HBoxContainer = HBoxContainer.new() - title_hbox.alignment = BoxContainer.ALIGNMENT_CENTER - title_hbox.set_anchors_preset(Control.PRESET_FULL_RECT) - title_panel.add_child(title_hbox) - - var icon_rect: TextureRect = TextureRect.new() - icon_rect.stretch_mode = TextureRect.STRETCH_KEEP_ASPECT_CENTERED - icon_rect.texture = graph_node.icon - icon_rect.set_size(Vector2(20, 20)) - title_hbox.add_child(icon_rect) - - var title: Label = Label.new() - title.text = graph_node.title_text - title.horizontal_alignment = HORIZONTAL_ALIGNMENT_CENTER - title.set_anchors_preset(Control.PRESET_FULL_RECT) - title_hbox.add_child(title) - - item_tree = Tree.new() - item_tree.custom_minimum_size = Vector2(200, 400) - item_tree.hide_root = true - item_tree.allow_search = false - item_tree.columns = 2 - add_child(item_tree) - - _update_list() - -func _update_list() -> void: - item_tree.clear() - - var root: TreeItem = item_tree.create_item() - - if graph_node.blackboard.size() == 0: - var no_bb_message: TreeItem = item_tree.create_item(root) - no_bb_message.set_text(0, "No blackboard data") - return - - for bb_name in graph_node.blackboard: - var bb_name_branch: TreeItem = item_tree.create_item(root) - bb_name_branch.set_text(0, bb_name) - - #print(graph_node.blackboard.get(bb_name)) - for key in graph_node.blackboard.get(bb_name): - var bb_kv_leaf: TreeItem = item_tree.create_item(bb_name_branch) - bb_kv_leaf.set_text(0, str(key)) - bb_kv_leaf.set_text(1, str(graph_node.blackboard.get(bb_name).get(key))) - -func _get_icon(type: StringName) -> Texture2D: - var classes := ProjectSettings.get_global_class_list() - for c in classes: - if c["class"] == type: - var icon_path := c.get("icon", String()) - if not icon_path.is_empty(): - return load(icon_path) - return null diff --git a/addons/beehave/debug/new_node_blackboard.gd.uid b/addons/beehave/debug/new_node_blackboard.gd.uid deleted file mode 100644 index c30c8bc..0000000 --- a/addons/beehave/debug/new_node_blackboard.gd.uid +++ /dev/null @@ -1 +0,0 @@ -uid://dc6wh1rconwcv diff --git a/addons/beehave/debug/old_frames.gd b/addons/beehave/debug/old_frames.gd deleted file mode 100644 index a9f6aa8..0000000 --- a/addons/beehave/debug/old_frames.gd +++ /dev/null @@ -1,47 +0,0 @@ -@tool -extends RefCounted - -const BeehaveUtils := preload("res://addons/beehave/utils/utils.gd") - -const SUCCESS_COLOR := Color("#009944c8") -const NORMAL_COLOR := Color("#15181e") -const FAILURE_COLOR := Color("#cf000f80") -const RUNNING_COLOR := Color("#ffcc00c8") - -var empty: StyleBoxEmpty -var normal: StyleBoxFlat -var success: StyleBoxFlat -var failure: StyleBoxFlat -var running: StyleBoxFlat - - -func _init() -> void: - var plugin := BeehaveUtils.get_plugin() - if not plugin: - return - - var editor_scale := BeehaveUtils.get_editor_scale() - - empty = StyleBoxEmpty.new() - - normal = ( - plugin - . get_editor_interface() - . get_base_control() - . get_theme_stylebox(&"frame", &"GraphNode") - . duplicate() - ) - - success = ( - plugin - . get_editor_interface() - . get_base_control() - . get_theme_stylebox(&"selected_frame", &"GraphNode") - . duplicate() - ) - failure = success.duplicate() - running = success.duplicate() - - success.border_color = SUCCESS_COLOR - failure.border_color = FAILURE_COLOR - running.border_color = RUNNING_COLOR diff --git a/addons/beehave/debug/old_frames.gd.uid b/addons/beehave/debug/old_frames.gd.uid deleted file mode 100644 index 762a1c0..0000000 --- a/addons/beehave/debug/old_frames.gd.uid +++ /dev/null @@ -1 +0,0 @@ -uid://bry61nlej4ixw diff --git a/addons/beehave/debug/old_graph_edit.gd b/addons/beehave/debug/old_graph_edit.gd deleted file mode 100644 index 69c11a3..0000000 --- a/addons/beehave/debug/old_graph_edit.gd +++ /dev/null @@ -1,286 +0,0 @@ -@tool -extends GraphEdit - -const BeehaveGraphNode := preload("old_graph_node.gd") - -const HORIZONTAL_LAYOUT_ICON := preload("icons/horizontal_layout.svg") -const VERTICAL_LAYOUT_ICON := preload("icons/vertical_layout.svg") - -const PROGRESS_SHIFT: int = 50 -const INACTIVE_COLOR: Color = Color("#898989aa") -const ACTIVE_COLOR: Color = Color("#ffcc00c8") -const SUCCESS_COLOR: Color = Color("#009944c8") - -var updating_graph: bool = false -var arraging_nodes: bool = false -var beehave_tree: Dictionary: - set(value): - if beehave_tree == value: - return - beehave_tree = value - active_nodes.clear() - _update_graph() - -var horizontal_layout: bool = false: - set(value): - if updating_graph or arraging_nodes: - return - if horizontal_layout == value: - return - horizontal_layout = value - _update_layout_button() - _update_graph() - -var frames: RefCounted -var active_nodes: Array[String] -var progress: int = 0 -var layout_button: Button - - -func _init(frames: RefCounted) -> void: - self.frames = frames - - -func _ready() -> void: - custom_minimum_size = Vector2(100, 300) - set("arrange_nodes_button_hidden", true) - minimap_enabled = false - layout_button = Button.new() - layout_button.flat = true - layout_button.focus_mode = Control.FOCUS_NONE - layout_button.pressed.connect(func(): horizontal_layout = not horizontal_layout) - get_menu_container().add_child(layout_button) - _update_layout_button() - - -func _update_graph() -> void: - if updating_graph: - return - - updating_graph = true - - clear_connections() - - for child in _get_child_nodes(): - remove_child(child) - child.queue_free() - - if not beehave_tree.is_empty(): - _add_nodes(beehave_tree) - _connect_nodes(beehave_tree) - _arrange_nodes.call_deferred(beehave_tree) - - updating_graph = false - - -func _add_nodes(node: Dictionary) -> void: - if node.is_empty(): - return - var gnode := BeehaveGraphNode.new(frames, horizontal_layout) - add_child(gnode) - gnode.title_text = node.name - gnode.name = node.id - gnode.icon = _get_icon(node.type.back()) - - if node.type.has(&"BeehaveTree"): - gnode.set_slots(false, true) - elif node.type.has(&"Leaf"): - gnode.set_slots(true, false) - elif node.type.has(&"Composite") or node.type.has(&"Decorator"): - gnode.set_slots(true, true) - - for child in node.get("children", []): - _add_nodes(child) - - -func _connect_nodes(node: Dictionary) -> void: - for child in node.get("children", []): - connect_node(node.id, 0, child.id, 0) - _connect_nodes(child) - - -func _arrange_nodes(node: Dictionary) -> void: - if arraging_nodes: - return - - arraging_nodes = true - - var tree_node := _create_tree_nodes(node) - tree_node.update_positions(horizontal_layout) - _place_nodes(tree_node) - - arraging_nodes = false - - -func _create_tree_nodes(node: Dictionary, root: TreeNode = null) -> TreeNode: - var tree_node := TreeNode.new(get_node(node.id), root) - for child in node.get("children", []): - var child_node := _create_tree_nodes(child, tree_node) - tree_node.children.push_back(child_node) - return tree_node - - -func _place_nodes(node: TreeNode) -> void: - node.item.position_offset = Vector2(node.x, node.y) - for child in node.children: - _place_nodes(child) - - -func _get_icon(type: StringName) -> Texture2D: - var classes := ProjectSettings.get_global_class_list() - for c in classes: - if c["class"] == type: - var icon_path := c.get("icon", String()) - if not icon_path.is_empty(): - return load(icon_path) - return null - - -func get_menu_container() -> Control: - return call("get_zoom_hbox") - - -func get_status(status: int) -> String: - if status == 0: - return "SUCCESS" - elif status == 1: - return "FAILURE" - return "RUNNING" - - -func process_begin(instance_id: int) -> void: - if not _is_same_tree(instance_id): - return - - for child in _get_child_nodes(): - child.set_meta("status", -1) - - -func process_tick(instance_id: int, status: int) -> void: - var node := get_node_or_null(str(instance_id)) - if node: - node.text = "Status: %s" % get_status(status) - node.set_status(status) - node.set_meta("status", status) - if status == BeehaveNode.SUCCESS or status == BeehaveNode.RUNNING: - if not active_nodes.has(node.name): - active_nodes.push_back(node.name) - - -func process_end(instance_id: int) -> void: - if not _is_same_tree(instance_id): - return - - for child in _get_child_nodes(): - var status := child.get_meta("status", -1) - match status: - BeehaveNode.SUCCESS: - active_nodes.erase(child.name) - child.set_color(SUCCESS_COLOR) - BeehaveNode.FAILURE: - active_nodes.erase(child.name) - child.set_color(INACTIVE_COLOR) - BeehaveNode.RUNNING: - child.set_color(ACTIVE_COLOR) - _: - child.text = " " - child.set_status(status) - child.set_color(INACTIVE_COLOR) - - -func _is_same_tree(instance_id: int) -> bool: - return str(instance_id) == beehave_tree.get("id", "") - - -func _get_child_nodes() -> Array[Node]: - return get_children().filter(func(child): return child is BeehaveGraphNode) - - -func _get_connection_line(from_position: Vector2, to_position: Vector2) -> PackedVector2Array: - var points: PackedVector2Array - - from_position = from_position.round() - to_position = to_position.round() - - points.push_back(from_position) - - var mid_position := ((to_position + from_position) / 2).round() - if horizontal_layout: - points.push_back(Vector2(mid_position.x, from_position.y)) - points.push_back(Vector2(mid_position.x, to_position.y)) - else: - points.push_back(Vector2(from_position.x, mid_position.y)) - points.push_back(Vector2(to_position.x, mid_position.y)) - - points.push_back(to_position) - - return points - - -func _process(delta: float) -> void: - if not active_nodes.is_empty(): - progress += 10 if delta >= 0.05 else 1 - if progress >= 1000: - progress = 0 - queue_redraw() - - -func _draw() -> void: - if active_nodes.is_empty(): - return - - var circle_size: float = max(3, 6 * zoom) - var progress_shift: float = PROGRESS_SHIFT * zoom - - var connections := get_connection_list() - for c in connections: - var from_node: StringName - var to_node: StringName - - from_node = c.from - to_node = c.to - - if not from_node in active_nodes or not c.to_node in active_nodes: - continue - - var from := get_node(String(from_node)) - var to := get_node(String(to_node)) - - if from.get_meta("status", -1) < 0 or to.get_meta("status", -1) < 0: - return - - var output_port_position: Vector2 - var input_port_position: Vector2 - - output_port_position = ( - from.position + from.call("get_connection_output_position", c.from_port) - ) - input_port_position = to.position + to.call("get_connection_input_position", c.to_port) - - var line := _get_connection_line(output_port_position, input_port_position) - - var curve = Curve2D.new() - for l in line: - curve.add_point(l) - - var max_steps := int(curve.get_baked_length()) - var current_shift := progress % max_steps - var p := curve.sample_baked(current_shift) - draw_circle(p, circle_size, ACTIVE_COLOR) - - var shift := current_shift - progress_shift - while shift >= 0: - draw_circle(curve.sample_baked(shift), circle_size, ACTIVE_COLOR) - shift -= progress_shift - - shift = current_shift + progress_shift - while shift <= curve.get_baked_length(): - draw_circle(curve.sample_baked(shift), circle_size, ACTIVE_COLOR) - shift += progress_shift - - -func _update_layout_button() -> void: - layout_button.icon = VERTICAL_LAYOUT_ICON if horizontal_layout else HORIZONTAL_LAYOUT_ICON - layout_button.tooltip_text = ( - "Switch to Vertical layout" if horizontal_layout else "Switch to Horizontal layout" - ) diff --git a/addons/beehave/debug/old_graph_edit.gd.uid b/addons/beehave/debug/old_graph_edit.gd.uid deleted file mode 100644 index 72c60ed..0000000 --- a/addons/beehave/debug/old_graph_edit.gd.uid +++ /dev/null @@ -1 +0,0 @@ -uid://dn08103rb80k2 diff --git a/addons/beehave/debug/old_graph_node.gd b/addons/beehave/debug/old_graph_node.gd deleted file mode 100644 index 28503b1..0000000 --- a/addons/beehave/debug/old_graph_node.gd +++ /dev/null @@ -1,166 +0,0 @@ -@tool -extends GraphNode - -const BeehaveUtils := preload("res://addons/beehave/utils/utils.gd") - -const DEFAULT_COLOR := Color("#dad4cb") - -const PORT_TOP_ICON := preload("icons/port_top.svg") -const PORT_BOTTOM_ICON := preload("icons/port_bottom.svg") -const PORT_LEFT_ICON := preload("icons/port_left.svg") -const PORT_RIGHT_ICON := preload("icons/port_right.svg") - -@export var title_text: String: - set(value): - title_text = value - if title_label: - title_label.text = value - -@export var text: String: - set(value): - text = value - if label: - label.text = " " if text.is_empty() else text - -@export var icon: Texture2D: - set(value): - icon = value - if icon_rect: - icon_rect.texture = value - -var layout_size: float: - get: - return size.y if horizontal else size.x - -var panel: PanelContainer -var icon_rect: TextureRect -var title_label: Label -var container: VBoxContainer -var label: Label - -var frames: RefCounted -var horizontal: bool = false - - -func _init(frames: RefCounted, horizontal: bool = false) -> void: - self.frames = frames - self.horizontal = horizontal - - -func _ready() -> void: - custom_minimum_size = Vector2(50, 50) * BeehaveUtils.get_editor_scale() - draggable = false - - add_theme_stylebox_override("frame", frames.empty if frames != null else null) - add_theme_stylebox_override("selected_frame", frames.empty if frames != null else null) - add_theme_color_override("close_color", Color.TRANSPARENT) - add_theme_icon_override("close", ImageTexture.new()) - - # For top port - add_child(Control.new()) - - panel = PanelContainer.new() - panel.mouse_filter = Control.MOUSE_FILTER_PASS - panel.add_theme_stylebox_override("panel", frames.normal if frames != null else null) - add_child(panel) - - var vbox_container := VBoxContainer.new() - panel.add_child(vbox_container) - - var title_size := 24 * BeehaveUtils.get_editor_scale() - var margin_container := MarginContainer.new() - margin_container.add_theme_constant_override( - "margin_top", -title_size - 2 * BeehaveUtils.get_editor_scale() - ) - margin_container.mouse_filter = Control.MOUSE_FILTER_PASS - vbox_container.add_child(margin_container) - - var title_container := HBoxContainer.new() - title_container.add_child(Control.new()) - title_container.mouse_filter = Control.MOUSE_FILTER_PASS - title_container.size_flags_horizontal = Control.SIZE_EXPAND_FILL - margin_container.add_child(title_container) - - icon_rect = TextureRect.new() - icon_rect.stretch_mode = TextureRect.STRETCH_KEEP_ASPECT_CENTERED - title_container.add_child(icon_rect) - - title_label = Label.new() - title_label.add_theme_color_override("font_color", DEFAULT_COLOR) - title_label.add_theme_font_override("font", get_theme_font("title_font")) - title_label.vertical_alignment = VERTICAL_ALIGNMENT_CENTER - title_label.size_flags_horizontal = Control.SIZE_EXPAND_FILL - title_label.text = title_text - title_container.add_child(title_label) - - title_container.add_child(Control.new()) - - container = VBoxContainer.new() - container.size_flags_vertical = Control.SIZE_EXPAND_FILL - container.size_flags_horizontal = Control.SIZE_EXPAND_FILL - panel.add_child(container) - - label = Label.new() - label.text = " " if text.is_empty() else text - container.add_child(label) - - # For bottom port - add_child(Control.new()) - - minimum_size_changed.connect(_on_size_changed) - _on_size_changed.call_deferred() - - -func set_status(status: int) -> void: - panel.add_theme_stylebox_override("panel", _get_stylebox(status)) - - -func _get_stylebox(status: int) -> StyleBox: - match status: - BeehaveNode.SUCCESS: - return frames.success - BeehaveNode.FAILURE: - return frames.failure - BeehaveNode.RUNNING: - return frames.running - _: - return frames.normal - - -func set_slots(left_enabled: bool, right_enabled: bool) -> void: - if horizontal: - set_slot( - 1, - left_enabled, - 0, - Color.WHITE, - right_enabled, - 0, - Color.WHITE, - PORT_LEFT_ICON, - PORT_RIGHT_ICON - ) - else: - set_slot(0, left_enabled, 0, Color.WHITE, false, -2, Color.TRANSPARENT, PORT_TOP_ICON, null) - set_slot( - 2, false, -1, Color.TRANSPARENT, right_enabled, 0, Color.WHITE, null, PORT_BOTTOM_ICON - ) - - -func set_color(color: Color) -> void: - set_input_color(color) - set_output_color(color) - - -func set_input_color(color: Color) -> void: - set_slot_color_left(1 if horizontal else 0, color) - - -func set_output_color(color: Color) -> void: - set_slot_color_right(1 if horizontal else 2, color) - - -func _on_size_changed(): - add_theme_constant_override( - "port_offset", 12 * BeehaveUtils.get_editor_scale() if horizontal else round(size.x / 2.0) - ) diff --git a/addons/beehave/debug/old_graph_node.gd.uid b/addons/beehave/debug/old_graph_node.gd.uid deleted file mode 100644 index fd942be..0000000 --- a/addons/beehave/debug/old_graph_node.gd.uid +++ /dev/null @@ -1 +0,0 @@ -uid://dfxjchexaxb0v diff --git a/addons/beehave/debug/tree_node.gd b/addons/beehave/debug/tree_node.gd deleted file mode 100644 index 1377970..0000000 --- a/addons/beehave/debug/tree_node.gd +++ /dev/null @@ -1,275 +0,0 @@ -class_name TreeNode -extends RefCounted - -# Based on https://rachel53461.wordpress.com/2014/04/20/algorithm-for-drawing-trees/ - -const SIBLING_DISTANCE: float = 20.0 -const LEVEL_DISTANCE: float = 40.0 - -const BeehaveUtils := preload("res://addons/beehave/utils/utils.gd") - -var x: float -var y: float -var mod: float -var parent: TreeNode -var children: Array[TreeNode] - -var item: GraphNode - - -func _init(p_item: GraphNode = null, p_parent: TreeNode = null) -> void: - parent = p_parent - item = p_item - - -func is_leaf() -> bool: - return children.is_empty() - - -func is_most_left() -> bool: - if not parent: - return true - return parent.children.front() == self - - -func is_most_right() -> bool: - if not parent: - return true - return parent.children.back() == self - - -func get_previous_sibling() -> TreeNode: - if not parent or is_most_left(): - return null - return parent.children[parent.children.find(self) - 1] - - -func get_next_sibling() -> TreeNode: - if not parent or is_most_right(): - return null - return parent.children[parent.children.find(self) + 1] - - -func get_most_left_sibling() -> TreeNode: - if not parent: - return null - - if is_most_left(): - return self - - return parent.children.front() - - -func get_most_left_child() -> TreeNode: - if children.is_empty(): - return null - return children.front() - - -func get_most_right_child() -> TreeNode: - if children.is_empty(): - return null - return children.back() - - -func update_positions(horizontally: bool = false) -> void: - _initialize_nodes(self, 0) - _calculate_initial_x(self) - - _check_all_children_on_screen(self) - _calculate_final_positions(self, 0) - - if horizontally: - _swap_x_y(self) - _calculate_x(self, 0) - else: - _calculate_y(self, 0) - - -func _initialize_nodes(node: TreeNode, depth: int) -> void: - node.x = -1 - node.y = depth - node.mod = 0 - - for child in node.children: - _initialize_nodes(child, depth + 1) - - -func _calculate_initial_x(node: TreeNode) -> void: - for child in node.children: - _calculate_initial_x(child) - if node.is_leaf(): - if not node.is_most_left(): - node.x = ( - node.get_previous_sibling().x - + node.get_previous_sibling().item.layout_size - + SIBLING_DISTANCE - ) - else: - node.x = 0 - else: - var mid: float - if node.children.size() == 1: - var offset: float = (node.children.front().item.layout_size - node.item.layout_size) / 2 - mid = node.children.front().x + offset - else: - var left_child := node.get_most_left_child() - var right_child := node.get_most_right_child() - mid = ( - ( - left_child.x - + right_child.x - + right_child.item.layout_size - - node.item.layout_size - ) - / 2 - ) - - if node.is_most_left(): - node.x = mid - else: - node.x = ( - node.get_previous_sibling().x - + node.get_previous_sibling().item.layout_size - + SIBLING_DISTANCE - ) - node.mod = node.x - mid - - if not node.is_leaf() and not node.is_most_left(): - _check_for_conflicts(node) - - -func _calculate_final_positions(node: TreeNode, mod_sum: float) -> void: - node.x += mod_sum - mod_sum += node.mod - - for child in node.children: - _calculate_final_positions(child, mod_sum) - - -func _check_all_children_on_screen(node: TreeNode) -> void: - var node_contour: Dictionary = {} - _get_left_contour(node, 0, node_contour) - - var shift_amount: float = 0 - for y in node_contour.keys(): - if node_contour[y] + shift_amount < 0: - shift_amount = (node_contour[y] * -1) - - if shift_amount > 0: - node.x += shift_amount - node.mod += shift_amount - - -func _check_for_conflicts(node: TreeNode) -> void: - var min_distance := SIBLING_DISTANCE - var shift_value: float = 0 - var shift_sibling: TreeNode = null - - var node_contour: Dictionary = {} # { int, float } - _get_left_contour(node, 0, node_contour) - - var sibling := node.get_most_left_sibling() - while sibling != null and sibling != node: - var sibling_contour: Dictionary = {} - _get_right_contour(sibling, 0, sibling_contour) - - for level in range( - node.y + 1, min(sibling_contour.keys().max(), node_contour.keys().max()) + 1 - ): - var distance: float = node_contour[level] - sibling_contour[level] - if distance + shift_value < min_distance: - shift_value = min_distance - distance - shift_sibling = sibling - - sibling = sibling.get_next_sibling() - - if shift_value > 0: - node.x += shift_value - node.mod += shift_value - _center_nodes_between(shift_sibling, node) - - -func _center_nodes_between(left_node: TreeNode, right_node: TreeNode) -> void: - var left_index := left_node.parent.children.find(left_node) - var right_index := left_node.parent.children.find(right_node) - - var num_nodes_between: int = (right_index - left_index) - 1 - if num_nodes_between > 0: - # The extra distance that needs to be split into num_nodes_between + 1 - # in order to find the new node spacing so that nodes are equally spaced - var distance_to_allocate: float = right_node.x - left_node.x - left_node.item.layout_size - # Subtract sizes on nodes in between - for i in range(left_index + 1, right_index): - distance_to_allocate -= left_node.parent.children[i].item.layout_size - # Divide space equally - var distance_between_nodes: float = distance_to_allocate / (num_nodes_between + 1) - - var prev_node := left_node - var middle_node := left_node.get_next_sibling() - while middle_node != right_node: - var desire_x: float = prev_node.x + prev_node.item.layout_size + distance_between_nodes - var offset := desire_x - middle_node.x - middle_node.x += offset - middle_node.mod += offset - prev_node = middle_node - middle_node = middle_node.get_next_sibling() - - -func _get_left_contour(node: TreeNode, mod_sum: float, values: Dictionary) -> void: - var node_left: float = node.x + mod_sum - var depth := int(node.y) - if not values.has(depth): - values[depth] = node_left - else: - values[depth] = min(values[depth], node_left) - - mod_sum += node.mod - for child in node.children: - _get_left_contour(child, mod_sum, values) - - -func _get_right_contour(node: TreeNode, mod_sum: float, values: Dictionary) -> void: - var node_right: float = node.x + mod_sum + node.item.layout_size - var depth := int(node.y) - if not values.has(depth): - values[depth] = node_right - else: - values[depth] = max(values[depth], node_right) - - mod_sum += node.mod - for child in node.children: - _get_right_contour(child, mod_sum, values) - - -func _swap_x_y(node: TreeNode) -> void: - for child in node.children: - _swap_x_y(child) - - var temp := node.x - node.x = node.y - node.y = temp - - -func _calculate_x(node: TreeNode, offset: int) -> void: - node.x = offset - var sibling := node.get_most_left_sibling() - var max_size: int = node.item.size.x - while sibling != null: - max_size = max(sibling.item.size.x, max_size) - sibling = sibling.get_next_sibling() - - for child in node.children: - _calculate_x(child, max_size + offset + LEVEL_DISTANCE * BeehaveUtils.get_editor_scale()) - - -func _calculate_y(node: TreeNode, offset: int) -> void: - node.y = offset - var sibling := node.get_most_left_sibling() - var max_size: int = node.item.size.y - while sibling != null: - max_size = max(sibling.item.size.y, max_size) - sibling = sibling.get_next_sibling() - - for child in node.children: - _calculate_y(child, max_size + offset + LEVEL_DISTANCE * BeehaveUtils.get_editor_scale()) diff --git a/addons/beehave/debug/tree_node.gd.uid b/addons/beehave/debug/tree_node.gd.uid deleted file mode 100644 index e68c8d7..0000000 --- a/addons/beehave/debug/tree_node.gd.uid +++ /dev/null @@ -1 +0,0 @@ -uid://b6cfgaspa0yck diff --git a/addons/beehave/icons/action.svg b/addons/beehave/icons/action.svg deleted file mode 100644 index 3916c89..0000000 --- a/addons/beehave/icons/action.svg +++ /dev/null @@ -1,38 +0,0 @@ - - diff --git a/addons/beehave/icons/blackboard.svg b/addons/beehave/icons/blackboard.svg deleted file mode 100644 index e4948a5..0000000 --- a/addons/beehave/icons/blackboard.svg +++ /dev/null @@ -1,38 +0,0 @@ - - diff --git a/addons/beehave/icons/category_bt.svg b/addons/beehave/icons/category_bt.svg deleted file mode 100644 index 8be61ae..0000000 --- a/addons/beehave/icons/category_bt.svg +++ /dev/null @@ -1,38 +0,0 @@ - - diff --git a/addons/beehave/icons/category_composite.svg b/addons/beehave/icons/category_composite.svg deleted file mode 100644 index aa8b866..0000000 --- a/addons/beehave/icons/category_composite.svg +++ /dev/null @@ -1,38 +0,0 @@ - - diff --git a/addons/beehave/icons/category_composite.svg.import b/addons/beehave/icons/category_composite.svg.import deleted file mode 100644 index 0496273..0000000 --- a/addons/beehave/icons/category_composite.svg.import +++ /dev/null @@ -1,38 +0,0 @@ -[remap] - -importer="texture" -type="CompressedTexture2D" -uid="uid://863s568sneja" -path="res://.godot/imported/category_composite.svg-43f66e63a7ccfa5ac8ec6da0583b3246.ctex" -metadata={ -"has_editor_variant": true, -"vram_texture": false -} - -[deps] - -source_file="res://addons/beehave/icons/category_composite.svg" -dest_files=["res://.godot/imported/category_composite.svg-43f66e63a7ccfa5ac8ec6da0583b3246.ctex"] - -[params] - -compress/mode=0 -compress/high_quality=false -compress/lossy_quality=0.7 -compress/hdr_compression=1 -compress/normal_map=0 -compress/channel_pack=0 -mipmaps/generate=false -mipmaps/limit=-1 -roughness/mode=0 -roughness/src_normal="" -process/fix_alpha_border=true -process/premult_alpha=false -process/normal_map_invert_y=false -process/hdr_as_srgb=false -process/hdr_clamp_exposure=false -process/size_limit=0 -detect_3d/compress_to=1 -svg/scale=1.0 -editor/scale_with_editor_scale=true -editor/convert_colors_with_editor_theme=true diff --git a/addons/beehave/icons/category_decorator.svg b/addons/beehave/icons/category_decorator.svg deleted file mode 100644 index 165e3d6..0000000 --- a/addons/beehave/icons/category_decorator.svg +++ /dev/null @@ -1,38 +0,0 @@ - - diff --git a/addons/beehave/icons/category_decorator.svg.import b/addons/beehave/icons/category_decorator.svg.import deleted file mode 100644 index 492f32e..0000000 --- a/addons/beehave/icons/category_decorator.svg.import +++ /dev/null @@ -1,38 +0,0 @@ -[remap] - -importer="texture" -type="CompressedTexture2D" -uid="uid://c2ie8m4ddawlb" -path="res://.godot/imported/category_decorator.svg-79d598d6456f32724156248e09d6eaf3.ctex" -metadata={ -"has_editor_variant": true, -"vram_texture": false -} - -[deps] - -source_file="res://addons/beehave/icons/category_decorator.svg" -dest_files=["res://.godot/imported/category_decorator.svg-79d598d6456f32724156248e09d6eaf3.ctex"] - -[params] - -compress/mode=0 -compress/high_quality=false -compress/lossy_quality=0.7 -compress/hdr_compression=1 -compress/normal_map=0 -compress/channel_pack=0 -mipmaps/generate=false -mipmaps/limit=-1 -roughness/mode=0 -roughness/src_normal="" -process/fix_alpha_border=true -process/premult_alpha=false -process/normal_map_invert_y=false -process/hdr_as_srgb=false -process/hdr_clamp_exposure=false -process/size_limit=0 -detect_3d/compress_to=1 -svg/scale=1.0 -editor/scale_with_editor_scale=true -editor/convert_colors_with_editor_theme=true diff --git a/addons/beehave/icons/category_leaf.svg b/addons/beehave/icons/category_leaf.svg deleted file mode 100644 index 1482fe6..0000000 --- a/addons/beehave/icons/category_leaf.svg +++ /dev/null @@ -1,38 +0,0 @@ - - diff --git a/addons/beehave/icons/category_leaf.svg.import b/addons/beehave/icons/category_leaf.svg.import deleted file mode 100644 index 4ef9604..0000000 --- a/addons/beehave/icons/category_leaf.svg.import +++ /dev/null @@ -1,38 +0,0 @@ -[remap] - -importer="texture" -type="CompressedTexture2D" -uid="uid://eq0sp4g3s75r" -path="res://.godot/imported/category_leaf.svg-c740ecab6cfae632574ca5e39e46fd2e.ctex" -metadata={ -"has_editor_variant": true, -"vram_texture": false -} - -[deps] - -source_file="res://addons/beehave/icons/category_leaf.svg" -dest_files=["res://.godot/imported/category_leaf.svg-c740ecab6cfae632574ca5e39e46fd2e.ctex"] - -[params] - -compress/mode=0 -compress/high_quality=false -compress/lossy_quality=0.7 -compress/hdr_compression=1 -compress/normal_map=0 -compress/channel_pack=0 -mipmaps/generate=false -mipmaps/limit=-1 -roughness/mode=0 -roughness/src_normal="" -process/fix_alpha_border=true -process/premult_alpha=false -process/normal_map_invert_y=false -process/hdr_as_srgb=false -process/hdr_clamp_exposure=false -process/size_limit=0 -detect_3d/compress_to=1 -svg/scale=1.0 -editor/scale_with_editor_scale=true -editor/convert_colors_with_editor_theme=true diff --git a/addons/beehave/icons/condition.svg b/addons/beehave/icons/condition.svg deleted file mode 100644 index 37b2c7a..0000000 --- a/addons/beehave/icons/condition.svg +++ /dev/null @@ -1,38 +0,0 @@ - - diff --git a/addons/beehave/icons/cooldown.svg b/addons/beehave/icons/cooldown.svg deleted file mode 100644 index fbdfd6a..0000000 --- a/addons/beehave/icons/cooldown.svg +++ /dev/null @@ -1,38 +0,0 @@ - - diff --git a/addons/beehave/icons/cooldown.svg.import b/addons/beehave/icons/cooldown.svg.import deleted file mode 100644 index e266da3..0000000 --- a/addons/beehave/icons/cooldown.svg.import +++ /dev/null @@ -1,37 +0,0 @@ -[remap] - -importer="texture" -type="CompressedTexture2D" -uid="uid://cxsdvoi5k1jyo" -path="res://.godot/imported/cooldown.svg-2fb8975b5974e35bedad825abb9faf66.ctex" -metadata={ -"vram_texture": false -} - -[deps] - -source_file="res://addons/beehave/icons/cooldown.svg" -dest_files=["res://.godot/imported/cooldown.svg-2fb8975b5974e35bedad825abb9faf66.ctex"] - -[params] - -compress/mode=0 -compress/high_quality=false -compress/lossy_quality=0.7 -compress/hdr_compression=0 -compress/normal_map=2 -compress/channel_pack=0 -mipmaps/generate=false -mipmaps/limit=-1 -roughness/mode=0 -roughness/src_normal="" -process/fix_alpha_border=false -process/premult_alpha=false -process/normal_map_invert_y=false -process/hdr_as_srgb=false -process/hdr_clamp_exposure=false -process/size_limit=0 -detect_3d/compress_to=0 -svg/scale=1.0 -editor/scale_with_editor_scale=false -editor/convert_colors_with_editor_theme=false diff --git a/addons/beehave/icons/delayer.svg b/addons/beehave/icons/delayer.svg deleted file mode 100644 index 21cb617..0000000 --- a/addons/beehave/icons/delayer.svg +++ /dev/null @@ -1,39 +0,0 @@ - - diff --git a/addons/beehave/icons/delayer.svg.import b/addons/beehave/icons/delayer.svg.import deleted file mode 100644 index 84c5ef2..0000000 --- a/addons/beehave/icons/delayer.svg.import +++ /dev/null @@ -1,37 +0,0 @@ -[remap] - -importer="texture" -type="CompressedTexture2D" -uid="uid://wsrld65xvnst" -path="res://.godot/imported/delayer.svg-6f92c97f61b1eb8679428f438e6b08c7.ctex" -metadata={ -"vram_texture": false -} - -[deps] - -source_file="res://addons/beehave/icons/delayer.svg" -dest_files=["res://.godot/imported/delayer.svg-6f92c97f61b1eb8679428f438e6b08c7.ctex"] - -[params] - -compress/mode=0 -compress/high_quality=false -compress/lossy_quality=0.7 -compress/hdr_compression=0 -compress/normal_map=2 -compress/channel_pack=0 -mipmaps/generate=false -mipmaps/limit=-1 -roughness/mode=0 -roughness/src_normal="" -process/fix_alpha_border=false -process/premult_alpha=false -process/normal_map_invert_y=false -process/hdr_as_srgb=false -process/hdr_clamp_exposure=false -process/size_limit=0 -detect_3d/compress_to=0 -svg/scale=1.0 -editor/scale_with_editor_scale=false -editor/convert_colors_with_editor_theme=false diff --git a/addons/beehave/icons/failer.svg b/addons/beehave/icons/failer.svg deleted file mode 100644 index 968f7e1..0000000 --- a/addons/beehave/icons/failer.svg +++ /dev/null @@ -1,38 +0,0 @@ - - diff --git a/addons/beehave/icons/inverter.svg b/addons/beehave/icons/inverter.svg deleted file mode 100644 index d4e791e..0000000 --- a/addons/beehave/icons/inverter.svg +++ /dev/null @@ -1,38 +0,0 @@ - - diff --git a/addons/beehave/icons/limiter.svg b/addons/beehave/icons/limiter.svg deleted file mode 100644 index 7b3fa1d..0000000 --- a/addons/beehave/icons/limiter.svg +++ /dev/null @@ -1,38 +0,0 @@ - - diff --git a/addons/beehave/icons/repeater.svg b/addons/beehave/icons/repeater.svg deleted file mode 100644 index 47c46e9..0000000 --- a/addons/beehave/icons/repeater.svg +++ /dev/null @@ -1,40 +0,0 @@ - - diff --git a/addons/beehave/icons/repeater.svg.import b/addons/beehave/icons/repeater.svg.import deleted file mode 100644 index febd0a3..0000000 --- a/addons/beehave/icons/repeater.svg.import +++ /dev/null @@ -1,37 +0,0 @@ -[remap] - -importer="texture" -type="CompressedTexture2D" -uid="uid://blady1becl8o0" -path="res://.godot/imported/repeater.svg-be2d3a7f1a46d7ba1d1939553725f598.ctex" -metadata={ -"vram_texture": false -} - -[deps] - -source_file="res://addons/beehave/icons/repeater.svg" -dest_files=["res://.godot/imported/repeater.svg-be2d3a7f1a46d7ba1d1939553725f598.ctex"] - -[params] - -compress/mode=0 -compress/high_quality=false -compress/lossy_quality=0.7 -compress/hdr_compression=0 -compress/normal_map=2 -compress/channel_pack=0 -mipmaps/generate=false -mipmaps/limit=-1 -roughness/mode=0 -roughness/src_normal="" -process/fix_alpha_border=false -process/premult_alpha=false -process/normal_map_invert_y=false -process/hdr_as_srgb=false -process/hdr_clamp_exposure=false -process/size_limit=0 -detect_3d/compress_to=0 -svg/scale=1.0 -editor/scale_with_editor_scale=false -editor/convert_colors_with_editor_theme=false diff --git a/addons/beehave/icons/selector.svg b/addons/beehave/icons/selector.svg deleted file mode 100644 index 0ae3b7a..0000000 --- a/addons/beehave/icons/selector.svg +++ /dev/null @@ -1,38 +0,0 @@ - - diff --git a/addons/beehave/icons/selector.svg.import b/addons/beehave/icons/selector.svg.import deleted file mode 100644 index ef7326d..0000000 --- a/addons/beehave/icons/selector.svg.import +++ /dev/null @@ -1,38 +0,0 @@ -[remap] - -importer="texture" -type="CompressedTexture2D" -uid="uid://b2c5d20doh4sp" -path="res://.godot/imported/selector.svg-78bccfc448bd1676b5a29bfde4b08e5b.ctex" -metadata={ -"has_editor_variant": true, -"vram_texture": false -} - -[deps] - -source_file="res://addons/beehave/icons/selector.svg" -dest_files=["res://.godot/imported/selector.svg-78bccfc448bd1676b5a29bfde4b08e5b.ctex"] - -[params] - -compress/mode=0 -compress/high_quality=false -compress/lossy_quality=0.7 -compress/hdr_compression=1 -compress/normal_map=0 -compress/channel_pack=0 -mipmaps/generate=false -mipmaps/limit=-1 -roughness/mode=0 -roughness/src_normal="" -process/fix_alpha_border=true -process/premult_alpha=false -process/normal_map_invert_y=false -process/hdr_as_srgb=false -process/hdr_clamp_exposure=false -process/size_limit=0 -detect_3d/compress_to=1 -svg/scale=1.0 -editor/scale_with_editor_scale=true -editor/convert_colors_with_editor_theme=true diff --git a/addons/beehave/icons/selector_random.svg b/addons/beehave/icons/selector_random.svg deleted file mode 100644 index 6f631e9..0000000 --- a/addons/beehave/icons/selector_random.svg +++ /dev/null @@ -1,35 +0,0 @@ - - diff --git a/addons/beehave/icons/selector_random.svg.import b/addons/beehave/icons/selector_random.svg.import deleted file mode 100644 index 6306f76..0000000 --- a/addons/beehave/icons/selector_random.svg.import +++ /dev/null @@ -1,38 +0,0 @@ -[remap] - -importer="texture" -type="CompressedTexture2D" -uid="uid://bmnkcmk7bkdjd" -path="res://.godot/imported/selector_random.svg-d52fea1352c24483ecd9dc8609cf00f3.ctex" -metadata={ -"has_editor_variant": true, -"vram_texture": false -} - -[deps] - -source_file="res://addons/beehave/icons/selector_random.svg" -dest_files=["res://.godot/imported/selector_random.svg-d52fea1352c24483ecd9dc8609cf00f3.ctex"] - -[params] - -compress/mode=0 -compress/high_quality=false -compress/lossy_quality=0.7 -compress/hdr_compression=1 -compress/normal_map=0 -compress/channel_pack=0 -mipmaps/generate=false -mipmaps/limit=-1 -roughness/mode=0 -roughness/src_normal="" -process/fix_alpha_border=true -process/premult_alpha=false -process/normal_map_invert_y=false -process/hdr_as_srgb=false -process/hdr_clamp_exposure=false -process/size_limit=0 -detect_3d/compress_to=1 -svg/scale=1.0 -editor/scale_with_editor_scale=true -editor/convert_colors_with_editor_theme=true diff --git a/addons/beehave/icons/selector_reactive.svg b/addons/beehave/icons/selector_reactive.svg deleted file mode 100644 index 6db005f..0000000 --- a/addons/beehave/icons/selector_reactive.svg +++ /dev/null @@ -1,45 +0,0 @@ - - diff --git a/addons/beehave/icons/selector_reactive.svg.import b/addons/beehave/icons/selector_reactive.svg.import deleted file mode 100644 index 12a8c5b..0000000 --- a/addons/beehave/icons/selector_reactive.svg.import +++ /dev/null @@ -1,38 +0,0 @@ -[remap] - -importer="texture" -type="CompressedTexture2D" -uid="uid://crkbov0h8sb8l" -path="res://.godot/imported/selector_reactive.svg-dd3b8fb8cd2ffe331605aaad1e021cc0.ctex" -metadata={ -"has_editor_variant": true, -"vram_texture": false -} - -[deps] - -source_file="res://addons/beehave/icons/selector_reactive.svg" -dest_files=["res://.godot/imported/selector_reactive.svg-dd3b8fb8cd2ffe331605aaad1e021cc0.ctex"] - -[params] - -compress/mode=0 -compress/high_quality=false -compress/lossy_quality=0.7 -compress/hdr_compression=1 -compress/normal_map=0 -compress/channel_pack=0 -mipmaps/generate=false -mipmaps/limit=-1 -roughness/mode=0 -roughness/src_normal="" -process/fix_alpha_border=true -process/premult_alpha=false -process/normal_map_invert_y=false -process/hdr_as_srgb=false -process/hdr_clamp_exposure=false -process/size_limit=0 -detect_3d/compress_to=1 -svg/scale=1.0 -editor/scale_with_editor_scale=true -editor/convert_colors_with_editor_theme=true diff --git a/addons/beehave/icons/sequence.svg b/addons/beehave/icons/sequence.svg deleted file mode 100644 index 3ebedd9..0000000 --- a/addons/beehave/icons/sequence.svg +++ /dev/null @@ -1,38 +0,0 @@ - - diff --git a/addons/beehave/icons/sequence.svg.import b/addons/beehave/icons/sequence.svg.import deleted file mode 100644 index 5dadbe2..0000000 --- a/addons/beehave/icons/sequence.svg.import +++ /dev/null @@ -1,38 +0,0 @@ -[remap] - -importer="texture" -type="CompressedTexture2D" -uid="uid://c5gw354thiofm" -path="res://.godot/imported/sequence.svg-76e5600611900cc81e9ec286977b8c6a.ctex" -metadata={ -"has_editor_variant": true, -"vram_texture": false -} - -[deps] - -source_file="res://addons/beehave/icons/sequence.svg" -dest_files=["res://.godot/imported/sequence.svg-76e5600611900cc81e9ec286977b8c6a.ctex"] - -[params] - -compress/mode=0 -compress/high_quality=false -compress/lossy_quality=0.7 -compress/hdr_compression=1 -compress/normal_map=0 -compress/channel_pack=0 -mipmaps/generate=false -mipmaps/limit=-1 -roughness/mode=0 -roughness/src_normal="" -process/fix_alpha_border=true -process/premult_alpha=false -process/normal_map_invert_y=false -process/hdr_as_srgb=false -process/hdr_clamp_exposure=false -process/size_limit=0 -detect_3d/compress_to=1 -svg/scale=1.0 -editor/scale_with_editor_scale=true -editor/convert_colors_with_editor_theme=true diff --git a/addons/beehave/icons/sequence_random.svg b/addons/beehave/icons/sequence_random.svg deleted file mode 100644 index 34e4a12..0000000 --- a/addons/beehave/icons/sequence_random.svg +++ /dev/null @@ -1,38 +0,0 @@ - - diff --git a/addons/beehave/icons/sequence_random.svg.import b/addons/beehave/icons/sequence_random.svg.import deleted file mode 100644 index 3907462..0000000 --- a/addons/beehave/icons/sequence_random.svg.import +++ /dev/null @@ -1,38 +0,0 @@ -[remap] - -importer="texture" -type="CompressedTexture2D" -uid="uid://bat8ptdw5qt1d" -path="res://.godot/imported/sequence_random.svg-58cee9098c622ef87db941279206422a.ctex" -metadata={ -"has_editor_variant": true, -"vram_texture": false -} - -[deps] - -source_file="res://addons/beehave/icons/sequence_random.svg" -dest_files=["res://.godot/imported/sequence_random.svg-58cee9098c622ef87db941279206422a.ctex"] - -[params] - -compress/mode=0 -compress/high_quality=false -compress/lossy_quality=0.7 -compress/hdr_compression=1 -compress/normal_map=0 -compress/channel_pack=0 -mipmaps/generate=false -mipmaps/limit=-1 -roughness/mode=0 -roughness/src_normal="" -process/fix_alpha_border=true -process/premult_alpha=false -process/normal_map_invert_y=false -process/hdr_as_srgb=false -process/hdr_clamp_exposure=false -process/size_limit=0 -detect_3d/compress_to=1 -svg/scale=1.0 -editor/scale_with_editor_scale=true -editor/convert_colors_with_editor_theme=true diff --git a/addons/beehave/icons/sequence_reactive.svg b/addons/beehave/icons/sequence_reactive.svg deleted file mode 100644 index 33d219b..0000000 --- a/addons/beehave/icons/sequence_reactive.svg +++ /dev/null @@ -1,60 +0,0 @@ - - diff --git a/addons/beehave/icons/sequence_reactive.svg.import b/addons/beehave/icons/sequence_reactive.svg.import deleted file mode 100644 index ab0fa25..0000000 --- a/addons/beehave/icons/sequence_reactive.svg.import +++ /dev/null @@ -1,38 +0,0 @@ -[remap] - -importer="texture" -type="CompressedTexture2D" -uid="uid://rmiu1slwfkh7" -path="res://.godot/imported/sequence_reactive.svg-7d384ca290f7934adb9e17d9e7116b6c.ctex" -metadata={ -"has_editor_variant": true, -"vram_texture": false -} - -[deps] - -source_file="res://addons/beehave/icons/sequence_reactive.svg" -dest_files=["res://.godot/imported/sequence_reactive.svg-7d384ca290f7934adb9e17d9e7116b6c.ctex"] - -[params] - -compress/mode=0 -compress/high_quality=false -compress/lossy_quality=0.7 -compress/hdr_compression=1 -compress/normal_map=0 -compress/channel_pack=0 -mipmaps/generate=false -mipmaps/limit=-1 -roughness/mode=0 -roughness/src_normal="" -process/fix_alpha_border=true -process/premult_alpha=false -process/normal_map_invert_y=false -process/hdr_as_srgb=false -process/hdr_clamp_exposure=false -process/size_limit=0 -detect_3d/compress_to=1 -svg/scale=1.0 -editor/scale_with_editor_scale=true -editor/convert_colors_with_editor_theme=true diff --git a/addons/beehave/icons/simple_parallel.svg b/addons/beehave/icons/simple_parallel.svg deleted file mode 100644 index e9c8b00..0000000 --- a/addons/beehave/icons/simple_parallel.svg +++ /dev/null @@ -1,13 +0,0 @@ - \ No newline at end of file diff --git a/addons/beehave/icons/simple_parallel.svg.import b/addons/beehave/icons/simple_parallel.svg.import deleted file mode 100644 index 4c087f1..0000000 --- a/addons/beehave/icons/simple_parallel.svg.import +++ /dev/null @@ -1,37 +0,0 @@ -[remap] - -importer="texture" -type="CompressedTexture2D" -uid="uid://d350rar21nmcl" -path="res://.godot/imported/simple_parallel.svg-3d4107eaf2e46557f6d3be3249f91430.ctex" -metadata={ -"vram_texture": false -} - -[deps] - -source_file="res://addons/beehave/icons/simple_parallel.svg" -dest_files=["res://.godot/imported/simple_parallel.svg-3d4107eaf2e46557f6d3be3249f91430.ctex"] - -[params] - -compress/mode=0 -compress/high_quality=false -compress/lossy_quality=0.7 -compress/hdr_compression=0 -compress/normal_map=2 -compress/channel_pack=0 -mipmaps/generate=false -mipmaps/limit=-1 -roughness/mode=0 -roughness/src_normal="" -process/fix_alpha_border=false -process/premult_alpha=false -process/normal_map_invert_y=false -process/hdr_as_srgb=false -process/hdr_clamp_exposure=false -process/size_limit=0 -detect_3d/compress_to=0 -svg/scale=1.0 -editor/scale_with_editor_scale=false -editor/convert_colors_with_editor_theme=false diff --git a/addons/beehave/icons/succeeder.svg b/addons/beehave/icons/succeeder.svg deleted file mode 100644 index 10f5912..0000000 --- a/addons/beehave/icons/succeeder.svg +++ /dev/null @@ -1,38 +0,0 @@ - - diff --git a/addons/beehave/icons/succeeder.svg.import b/addons/beehave/icons/succeeder.svg.import deleted file mode 100644 index 0cb7334..0000000 --- a/addons/beehave/icons/succeeder.svg.import +++ /dev/null @@ -1,38 +0,0 @@ -[remap] - -importer="texture" -type="CompressedTexture2D" -uid="uid://dl6wo332kglbe" -path="res://.godot/imported/succeeder.svg-e5cf6f6e04b9b862b82fd2cb479272aa.ctex" -metadata={ -"has_editor_variant": true, -"vram_texture": false -} - -[deps] - -source_file="res://addons/beehave/icons/succeeder.svg" -dest_files=["res://.godot/imported/succeeder.svg-e5cf6f6e04b9b862b82fd2cb479272aa.ctex"] - -[params] - -compress/mode=0 -compress/high_quality=false -compress/lossy_quality=0.7 -compress/hdr_compression=1 -compress/normal_map=0 -compress/channel_pack=0 -mipmaps/generate=false -mipmaps/limit=-1 -roughness/mode=0 -roughness/src_normal="" -process/fix_alpha_border=true -process/premult_alpha=false -process/normal_map_invert_y=false -process/hdr_as_srgb=false -process/hdr_clamp_exposure=false -process/size_limit=0 -detect_3d/compress_to=1 -svg/scale=1.0 -editor/scale_with_editor_scale=true -editor/convert_colors_with_editor_theme=true diff --git a/addons/beehave/icons/tree.svg b/addons/beehave/icons/tree.svg deleted file mode 100644 index 6c85ea1..0000000 --- a/addons/beehave/icons/tree.svg +++ /dev/null @@ -1,38 +0,0 @@ - - diff --git a/addons/beehave/icons/until_fail.svg b/addons/beehave/icons/until_fail.svg deleted file mode 100644 index c64a0a0..0000000 --- a/addons/beehave/icons/until_fail.svg +++ /dev/null @@ -1,45 +0,0 @@ - - diff --git a/addons/beehave/icons/until_fail.svg.import b/addons/beehave/icons/until_fail.svg.import deleted file mode 100644 index 7689ae4..0000000 --- a/addons/beehave/icons/until_fail.svg.import +++ /dev/null @@ -1,37 +0,0 @@ -[remap] - -importer="texture" -type="CompressedTexture2D" -uid="uid://ct68hm7qd6cdc" -path="res://.godot/imported/until_fail.svg-8015014c40e91d9c2668ec34d4118b8e.ctex" -metadata={ -"vram_texture": false -} - -[deps] - -source_file="res://addons/beehave/icons/until_fail.svg" -dest_files=["res://.godot/imported/until_fail.svg-8015014c40e91d9c2668ec34d4118b8e.ctex"] - -[params] - -compress/mode=0 -compress/high_quality=false -compress/lossy_quality=0.7 -compress/hdr_compression=0 -compress/normal_map=2 -compress/channel_pack=0 -mipmaps/generate=false -mipmaps/limit=-1 -roughness/mode=0 -roughness/src_normal="" -process/fix_alpha_border=false -process/premult_alpha=false -process/normal_map_invert_y=false -process/hdr_as_srgb=false -process/hdr_clamp_exposure=false -process/size_limit=0 -detect_3d/compress_to=0 -svg/scale=1.0 -editor/scale_with_editor_scale=false -editor/convert_colors_with_editor_theme=false diff --git a/addons/beehave/metrics/beehave_global_metrics.gd b/addons/beehave/metrics/beehave_global_metrics.gd deleted file mode 100644 index ef29db2..0000000 --- a/addons/beehave/metrics/beehave_global_metrics.gd +++ /dev/null @@ -1,54 +0,0 @@ -extends Node - -var _tree_count: int = 0 -var _active_tree_count: int = 0 -var _registered_trees: Array = [] - - -func _enter_tree() -> void: - Performance.add_custom_monitor("beehave/total_trees", _get_total_trees) - Performance.add_custom_monitor("beehave/total_enabled_trees", _get_total_enabled_trees) - - -func register_tree(tree) -> void: - if _registered_trees.has(tree): - return - - _registered_trees.append(tree) - _tree_count += 1 - - if tree.enabled: - _active_tree_count += 1 - - tree.tree_enabled.connect(_on_tree_enabled) - tree.tree_disabled.connect(_on_tree_disabled) - - -func unregister_tree(tree) -> void: - if not _registered_trees.has(tree): - return - - _registered_trees.erase(tree) - _tree_count -= 1 - - if tree.enabled: - _active_tree_count -= 1 - - tree.tree_enabled.disconnect(_on_tree_enabled) - tree.tree_disabled.disconnect(_on_tree_disabled) - - -func _get_total_trees() -> int: - return _tree_count - - -func _get_total_enabled_trees() -> int: - return _active_tree_count - - -func _on_tree_enabled() -> void: - _active_tree_count += 1 - - -func _on_tree_disabled() -> void: - _active_tree_count -= 1 diff --git a/addons/beehave/metrics/beehave_global_metrics.gd.uid b/addons/beehave/metrics/beehave_global_metrics.gd.uid deleted file mode 100644 index eaa58f3..0000000 --- a/addons/beehave/metrics/beehave_global_metrics.gd.uid +++ /dev/null @@ -1 +0,0 @@ -uid://bnsi7s14y51ip diff --git a/addons/beehave/nodes/beehave_node.gd b/addons/beehave/nodes/beehave_node.gd deleted file mode 100644 index 9ab8d6e..0000000 --- a/addons/beehave/nodes/beehave_node.gd +++ /dev/null @@ -1,46 +0,0 @@ -@tool -class_name BeehaveNode extends Node - -## A node in the behavior tree. Every node must return `SUCCESS`, `FAILURE` or -## `RUNNING` when ticked. - -enum { SUCCESS, FAILURE, RUNNING } - - -func _get_configuration_warnings() -> PackedStringArray: - var warnings: PackedStringArray = [] - - if get_children().any(func(x): return not (x is BeehaveNode)): - warnings.append("All children of this node should inherit from BeehaveNode class.") - - return warnings - - -## Executes this node and returns a status code. -## This method must be overwritten. -func tick(actor: Node, blackboard: Blackboard) -> int: - return SUCCESS - - -## Called when this node needs to be interrupted before it can return FAILURE or SUCCESS. -func interrupt(actor: Node, blackboard: Blackboard) -> void: - pass - - -## Called before the first time it ticks by the parent. -func before_run(actor: Node, blackboard: Blackboard) -> void: - pass - - -## Called after the last time it ticks and returns -## [code]SUCCESS[/code] or [code]FAILURE[/code]. -func after_run(actor: Node, blackboard: Blackboard) -> void: - pass - - -func get_class_name() -> Array[StringName]: - return [&"BeehaveNode"] - - -func can_send_message(blackboard: Blackboard) -> bool: - return blackboard.get_value("can_send_message", false) diff --git a/addons/beehave/nodes/beehave_node.gd.uid b/addons/beehave/nodes/beehave_node.gd.uid deleted file mode 100644 index 7a5bc09..0000000 --- a/addons/beehave/nodes/beehave_node.gd.uid +++ /dev/null @@ -1 +0,0 @@ -uid://dt4gywh4fq1fr diff --git a/addons/beehave/nodes/beehave_tree.gd b/addons/beehave/nodes/beehave_tree.gd deleted file mode 100644 index ecdbe52..0000000 --- a/addons/beehave/nodes/beehave_tree.gd +++ /dev/null @@ -1,329 +0,0 @@ -@tool -@icon("../icons/tree.svg") -class_name BeehaveTree extends Node - -## Controls the flow of execution of the entire behavior tree. - -enum { SUCCESS, FAILURE, RUNNING } - -enum ProcessThread { IDLE, PHYSICS } - -signal tree_enabled -signal tree_disabled - -## Whether this behavior tree should be enabled or not. -@export var enabled: bool = true: - set(value): - enabled = value - set_physics_process(enabled and process_thread == ProcessThread.PHYSICS) - set_process(enabled and process_thread == ProcessThread.IDLE) - if value: - tree_enabled.emit() - else: - interrupt() - tree_disabled.emit() - - get: - return enabled - -## How often the tree should tick, in frames. The default value of 1 means -## tick() runs every frame. -@export var tick_rate: int = 1 - -## An optional node path this behavior tree should apply to. -@export_node_path var actor_node_path: NodePath: - set(anp): - actor_node_path = anp - if actor_node_path != null and str(actor_node_path) != "..": - actor = get_node(actor_node_path) - else: - actor = get_parent() - if Engine.is_editor_hint(): - update_configuration_warnings() - -## Whether to run this tree in a physics or idle thread. -@export var process_thread: ProcessThread = ProcessThread.PHYSICS: - set(value): - process_thread = value - set_physics_process(enabled and process_thread == ProcessThread.PHYSICS) - set_process(enabled and process_thread == ProcessThread.IDLE) - -## Custom blackboard node. An internal blackboard will be used -## if no blackboard is provided explicitly. -@export var blackboard: Blackboard: - set(b): - blackboard = b - if blackboard and _internal_blackboard: - remove_child(_internal_blackboard) - _internal_blackboard.free() - _internal_blackboard = null - elif not blackboard and not _internal_blackboard: - _internal_blackboard = Blackboard.new() - add_child(_internal_blackboard, false, Node.INTERNAL_MODE_BACK) - get: - # in case blackboard is accessed before this node is, - # we need to ensure that the internal blackboard is used. - if not blackboard and not _internal_blackboard: - _internal_blackboard = Blackboard.new() - add_child(_internal_blackboard, false, Node.INTERNAL_MODE_BACK) - return blackboard if blackboard else _internal_blackboard - -## When enabled, this tree is tracked individually -## as a custom monitor. -@export var custom_monitor = false: - set(b): - custom_monitor = b - if custom_monitor and _process_time_metric_name != "": - Performance.add_custom_monitor( - _process_time_metric_name, _get_process_time_metric_value - ) - _get_global_metrics().register_tree(self) - else: - if _process_time_metric_name != "": - # Remove tree metric from the engine - Performance.remove_custom_monitor(_process_time_metric_name) - _get_global_metrics().unregister_tree(self) - - BeehaveDebuggerMessages.unregister_tree(get_instance_id()) - -@export var actor: Node: - set(a): - actor = a - if actor == null: - actor = get_parent() - if Engine.is_editor_hint(): - update_configuration_warnings() - -var status: int = -1 -var last_tick: int = 0 - -var _internal_blackboard: Blackboard -var _process_time_metric_name: String -var _process_time_metric_value: float = 0.0 -var _can_send_message: bool = false - - -func _ready() -> void: - var connect_scene_tree_signal = func(signal_name: String, is_added: bool): - if not get_tree().is_connected(signal_name, _on_scene_tree_node_added_removed.bind(is_added)): - get_tree().connect(signal_name, _on_scene_tree_node_added_removed.bind(is_added)) - connect_scene_tree_signal.call("node_added", true) - connect_scene_tree_signal.call("node_removed", false) - - if not process_thread: - process_thread = ProcessThread.PHYSICS - - if not actor: - if actor_node_path: - actor = get_node(actor_node_path) - else: - actor = get_parent() - - if not blackboard: - # invoke setter to auto-initialise the blackboard. - self.blackboard = null - - # Get the name of the parent node name for metric - _process_time_metric_name = ( - "beehave [microseconds]/process_time_%s-%s" % [actor.name, get_instance_id()] - ) - - set_physics_process(enabled and process_thread == ProcessThread.PHYSICS) - set_process(enabled and process_thread == ProcessThread.IDLE) - - # Register custom metric to the engine - if custom_monitor and not Engine.is_editor_hint(): - Performance.add_custom_monitor(_process_time_metric_name, _get_process_time_metric_value) - _get_global_metrics().register_tree(self) - - if Engine.is_editor_hint(): - update_configuration_warnings.call_deferred() - else: - _get_global_debugger().register_tree(self) - BeehaveDebuggerMessages.register_tree(_get_debugger_data(self)) - - # Randomize at what frames tick() will happen to avoid stutters - last_tick = randi_range(0, tick_rate - 1) - - -func _on_scene_tree_node_added_removed(node: Node, is_added: bool) -> void: - if Engine.is_editor_hint(): - return - - if node is BeehaveNode and is_ancestor_of(node): - var sgnal := node.ready if is_added else node.tree_exited - if is_added: - sgnal.connect( - func() -> void: BeehaveDebuggerMessages.register_tree(_get_debugger_data(self)), - CONNECT_ONE_SHOT - ) - else: - sgnal.connect( - func() -> void: - BeehaveDebuggerMessages.unregister_tree(get_instance_id()) - request_ready() - ) - - -func _physics_process(_delta: float) -> void: - _process_internally() - - -func _process(_delta: float) -> void: - _process_internally() - - -func _process_internally() -> void: - if Engine.is_editor_hint(): - return - - if last_tick < tick_rate - 1: - last_tick += 1 - return - - last_tick = 0 - - # Start timing for metric - var start_time = Time.get_ticks_usec() - - blackboard.set_value("can_send_message", _can_send_message) - - if _can_send_message: - BeehaveDebuggerMessages.process_begin(get_instance_id(), blackboard.get_debug_data()) - - if self.get_child_count() == 1: - tick() - - if _can_send_message: - BeehaveDebuggerMessages.process_end(get_instance_id(), blackboard.get_debug_data()) - - # Check the cost for this frame and save it for metric report - _process_time_metric_value = Time.get_ticks_usec() - start_time - - -func tick() -> int: - if actor == null or get_child_count() == 0: - return FAILURE - var child := self.get_child(0) - if status != RUNNING: - child.before_run(actor, blackboard) - - status = child.tick(actor, blackboard) - if _can_send_message: - BeehaveDebuggerMessages.process_tick(child.get_instance_id(), status, blackboard.get_debug_data()) - BeehaveDebuggerMessages.process_tick(get_instance_id(), status, blackboard.get_debug_data()) - - # Clear running action if nothing is running - if status != RUNNING: - blackboard.set_value("running_action", null, str(actor.get_instance_id())) - child.after_run(actor, blackboard) - - return status - - -func _get_configuration_warnings() -> PackedStringArray: - var warnings: PackedStringArray = [] - - if actor == null: - warnings.append("Configure target node on tree") - - if get_children().any(func(x): return not (x is BeehaveNode)): - warnings.append("All children of this node should inherit from BeehaveNode class.") - - if get_child_count() != 1: - warnings.append("BeehaveTree should have exactly one child node.") - - return warnings - - -## Returns the currently running action -func get_running_action() -> ActionLeaf: - return blackboard.get_value("running_action", null, str(actor.get_instance_id())) - - -## Returns the last condition that was executed -func get_last_condition() -> ConditionLeaf: - return blackboard.get_value("last_condition", null, str(actor.get_instance_id())) - - -## Returns the status of the last executed condition -func get_last_condition_status() -> String: - if blackboard.has_value("last_condition_status", str(actor.get_instance_id())): - var status = blackboard.get_value( - "last_condition_status", null, str(actor.get_instance_id()) - ) - if status == SUCCESS: - return "SUCCESS" - elif status == FAILURE: - return "FAILURE" - else: - return "RUNNING" - return "" - - -## interrupts this tree if anything was running -func interrupt() -> void: - if self.get_child_count() != 0: - var first_child = self.get_child(0) - if "interrupt" in first_child: - first_child.interrupt(actor, blackboard) - - -## Enables this tree. -func enable() -> void: - self.enabled = true - - -## Disables this tree. -func disable() -> void: - self.enabled = false - - -func _exit_tree() -> void: - if custom_monitor: - if _process_time_metric_name != "": - # Remove tree metric from the engine - Performance.remove_custom_monitor(_process_time_metric_name) - _get_global_metrics().unregister_tree(self) - - BeehaveDebuggerMessages.unregister_tree(get_instance_id()) - - -# Called by the engine to profile this tree -func _get_process_time_metric_value() -> int: - return int(_process_time_metric_value) - - -func _get_debugger_data(node: Node) -> Dictionary: - if not (node is BeehaveTree or node is BeehaveNode): - return {} - - var data := { - path = node.get_path(), - name = node.name, - type = node.get_class_name(), - id = str(node.get_instance_id()) - } - if node.get_child_count() > 0: - data.children = [] - for child in node.get_children(): - var child_data := _get_debugger_data(child) - if not child_data.is_empty(): - data.children.push_back(child_data) - return data - - -func get_class_name() -> Array[StringName]: - return [&"BeehaveTree"] - - -# required to avoid lifecycle issues on initial load -# due to loading order problems with autoloads -func _get_global_metrics() -> Node: - return get_tree().root.get_node("BeehaveGlobalMetrics") - - -# required to avoid lifecycle issues on initial load -# due to loading order problems with autoloads -func _get_global_debugger() -> Node: - return get_tree().root.get_node("BeehaveGlobalDebugger") diff --git a/addons/beehave/nodes/beehave_tree.gd.uid b/addons/beehave/nodes/beehave_tree.gd.uid deleted file mode 100644 index b350bff..0000000 --- a/addons/beehave/nodes/beehave_tree.gd.uid +++ /dev/null @@ -1 +0,0 @@ -uid://bp45wgark5mhr diff --git a/addons/beehave/nodes/composites/composite.gd b/addons/beehave/nodes/composites/composite.gd deleted file mode 100644 index 53a8e90..0000000 --- a/addons/beehave/nodes/composites/composite.gd +++ /dev/null @@ -1,34 +0,0 @@ -@tool -@icon("../../icons/category_composite.svg") -class_name Composite extends BeehaveNode - -## A Composite node controls the flow of execution of its children in a specific manner. - -var running_child: BeehaveNode = null - - -func _get_configuration_warnings() -> PackedStringArray: - var warnings: PackedStringArray = super._get_configuration_warnings() - - if get_children().filter(func(x): return x is BeehaveNode).size() < 2: - warnings.append( - "Any composite node should have at least two children. Otherwise it is not useful." - ) - - return warnings - - -func interrupt(actor: Node, blackboard: Blackboard) -> void: - if running_child != null: - running_child.interrupt(actor, blackboard) - running_child = null - - -func after_run(actor: Node, blackboard: Blackboard) -> void: - running_child = null - - -func get_class_name() -> Array[StringName]: - var classes := super() - classes.push_back(&"Composite") - return classes diff --git a/addons/beehave/nodes/composites/composite.gd.uid b/addons/beehave/nodes/composites/composite.gd.uid deleted file mode 100644 index 4732f63..0000000 --- a/addons/beehave/nodes/composites/composite.gd.uid +++ /dev/null @@ -1 +0,0 @@ -uid://c4worak0yatu4 diff --git a/addons/beehave/nodes/composites/randomized_composite.gd b/addons/beehave/nodes/composites/randomized_composite.gd deleted file mode 100644 index 2afa5e9..0000000 --- a/addons/beehave/nodes/composites/randomized_composite.gd +++ /dev/null @@ -1,176 +0,0 @@ -@tool -class_name RandomizedComposite extends Composite - -const WEIGHTS_PREFIX = "Weights/" - -## Sets a predicable seed -@export var random_seed: int = 0: - set(rs): - random_seed = rs - if random_seed != 0: - seed(random_seed) - else: - randomize() - -## Wether to use weights for every child or not. -@export var use_weights: bool: - set(value): - use_weights = value - if use_weights: - _update_weights(get_children()) - _connect_children_changing_signals() - notify_property_list_changed() - -var _weights: Dictionary -var _exiting_tree: bool - - -func _ready(): - _connect_children_changing_signals() - - -func _connect_children_changing_signals(): - if not child_entered_tree.is_connected(_on_child_entered_tree): - child_entered_tree.connect(_on_child_entered_tree) - - if not child_exiting_tree.is_connected(_on_child_exiting_tree): - child_exiting_tree.connect(_on_child_exiting_tree) - - -func get_shuffled_children() -> Array[Node]: - var children_bag: Array[Node] = get_children().duplicate() - if use_weights: - var weights: Array[int] - weights.assign(children_bag.map(func(child): return _weights[child.name])) - children_bag.assign(_weighted_shuffle(children_bag, weights)) - else: - children_bag.shuffle() - return children_bag - - -## Returns a shuffled version of a given array using the supplied array of weights. -## Think of weights as the chance of a given item being the first in the array. -func _weighted_shuffle(items: Array, weights: Array[int]) -> Array: - if len(items) != len(weights): - push_error( - ( - "items and weights size mismatch: expected %d weights, got %d instead." - % [len(items), len(weights)] - ) - ) - return items - - # This method is based on the weighted random sampling algorithm - # by Efraimidis, Spirakis; 2005. This runs in O(n log(n)). - - # For each index, it will calculate random_value^(1/weight). - var chance_calc = func(i): return [i, randf() ** (1.0 / weights[i])] - var random_distribuition = range(len(items)).map(chance_calc) - - # Now we just have to order by the calculated value, descending. - random_distribuition.sort_custom(func(a, b): return a[1] > b[1]) - - return random_distribuition.map(func(dist): return items[dist[0]]) - - -func _get_property_list(): - var properties = [] - - if use_weights: - for key in _weights.keys(): - properties.append( - { - "name": WEIGHTS_PREFIX + key, - "type": TYPE_INT, - "usage": PROPERTY_USAGE_STORAGE | PROPERTY_USAGE_EDITOR, - "hint": PROPERTY_HINT_RANGE, - "hint_string": "1,100" - } - ) - - return properties - - -func _set(property: StringName, value: Variant) -> bool: - if property.begins_with(WEIGHTS_PREFIX): - var weight_name = property.trim_prefix(WEIGHTS_PREFIX) - _weights[weight_name] = value - return true - - return false - - -func _get(property: StringName): - if property.begins_with(WEIGHTS_PREFIX): - var weight_name = property.trim_prefix(WEIGHTS_PREFIX) - return _weights[weight_name] - - return null - - -func _update_weights(children: Array[Node]) -> void: - var new_weights = {} - for c in children: - if _weights.has(c.name): - new_weights[c.name] = _weights[c.name] - else: - new_weights[c.name] = 1 - _weights = new_weights - notify_property_list_changed() - - -func _exit_tree() -> void: - _exiting_tree = true - - -func _enter_tree() -> void: - _exiting_tree = false - - -func _on_child_entered_tree(node: Node): - _update_weights(get_children()) - - var renamed_callable = _on_child_renamed.bind(node.name, node) - if not node.renamed.is_connected(renamed_callable): - node.renamed.connect(renamed_callable) - - if not node.tree_exited.is_connected(_on_child_tree_exited): - node.tree_exited.connect(_on_child_tree_exited.bind(node)) - - -func _on_child_exiting_tree(node: Node): - var renamed_callable = _on_child_renamed.bind(node.name, node) - if node.renamed.is_connected(renamed_callable): - node.renamed.disconnect(renamed_callable) - - -func _on_child_tree_exited(node: Node) -> void: - # don't erase the individual child if the whole tree is exiting together - if not _exiting_tree: - var children = get_children() - children.erase(node) - _update_weights(children) - - if node.tree_exited.is_connected(_on_child_tree_exited): - node.tree_exited.disconnect(_on_child_tree_exited) - - -func _on_child_renamed(old_name: String, renamed_child: Node): - if old_name == renamed_child.name: - return # No need to update the weights. - - # Disconnect signal with old name... - renamed_child.renamed.disconnect(_on_child_renamed.bind(old_name, renamed_child)) - # ...and connect with the new name. - renamed_child.renamed.connect(_on_child_renamed.bind(renamed_child.name, renamed_child)) - - var original_weight = _weights[old_name] - _weights.erase(old_name) - _weights[renamed_child.name] = original_weight - notify_property_list_changed() - - -func get_class_name() -> Array[StringName]: - var classes := super() - classes.push_back(&"RandomizedComposite") - return classes diff --git a/addons/beehave/nodes/composites/randomized_composite.gd.uid b/addons/beehave/nodes/composites/randomized_composite.gd.uid deleted file mode 100644 index 0ac3fa8..0000000 --- a/addons/beehave/nodes/composites/randomized_composite.gd.uid +++ /dev/null @@ -1 +0,0 @@ -uid://doy7t75rh6gf2 diff --git a/addons/beehave/nodes/composites/selector.gd b/addons/beehave/nodes/composites/selector.gd deleted file mode 100644 index 69ce1e9..0000000 --- a/addons/beehave/nodes/composites/selector.gd +++ /dev/null @@ -1,69 +0,0 @@ -@tool -@icon("../../icons/selector.svg") -class_name SelectorComposite extends Composite - -## Selector nodes will attempt to execute each of its children until one of -## them return `SUCCESS`. If all children return `FAILURE`, this node will also -## return `FAILURE`. -## If a child returns `RUNNING` it will tick again. - -var last_execution_index: int = 0 - - -func tick(actor: Node, blackboard: Blackboard) -> int: - for c in get_children(): - if c.get_index() < last_execution_index: - continue - - if c != running_child: - c.before_run(actor, blackboard) - - var response: int = c.tick(actor, blackboard) - if can_send_message(blackboard): - BeehaveDebuggerMessages.process_tick(c.get_instance_id(), response, blackboard.get_debug_data()) - - if c is ConditionLeaf: - blackboard.set_value("last_condition", c, str(actor.get_instance_id())) - blackboard.set_value("last_condition_status", response, str(actor.get_instance_id())) - - match response: - SUCCESS: - _cleanup_running_task(c, actor, blackboard) - c.after_run(actor, blackboard) - return SUCCESS - FAILURE: - _cleanup_running_task(c, actor, blackboard) - last_execution_index += 1 - c.after_run(actor, blackboard) - RUNNING: - running_child = c - if c is ActionLeaf: - blackboard.set_value("running_action", c, str(actor.get_instance_id())) - return RUNNING - - return FAILURE - - -func after_run(actor: Node, blackboard: Blackboard) -> void: - last_execution_index = 0 - super(actor, blackboard) - - -func interrupt(actor: Node, blackboard: Blackboard) -> void: - last_execution_index = 0 - super(actor, blackboard) - - -## Changes `running_action` and `running_child` after the node finishes executing. -func _cleanup_running_task(finished_action: Node, actor: Node, blackboard: Blackboard): - var blackboard_name: String = str(actor.get_instance_id()) - if finished_action == running_child: - running_child = null - if finished_action == blackboard.get_value("running_action", null, blackboard_name): - blackboard.set_value("running_action", null, blackboard_name) - - -func get_class_name() -> Array[StringName]: - var classes := super() - classes.push_back(&"SelectorComposite") - return classes diff --git a/addons/beehave/nodes/composites/selector.gd.uid b/addons/beehave/nodes/composites/selector.gd.uid deleted file mode 100644 index a8fc559..0000000 --- a/addons/beehave/nodes/composites/selector.gd.uid +++ /dev/null @@ -1 +0,0 @@ -uid://b1u61op4yj40j diff --git a/addons/beehave/nodes/composites/selector_random.gd b/addons/beehave/nodes/composites/selector_random.gd deleted file mode 100644 index 54ea63e..0000000 --- a/addons/beehave/nodes/composites/selector_random.gd +++ /dev/null @@ -1,82 +0,0 @@ -@tool -@icon("../../icons/selector_random.svg") -class_name SelectorRandomComposite extends RandomizedComposite - -## This node will attempt to execute all of its children just like a -## [code]SelectorStar[/code] would, with the exception that the children -## will be executed in a random order. - -## A shuffled list of the children that will be executed in reverse order. -var _children_bag: Array[Node] = [] -var c: Node - - -func _ready() -> void: - super() - if random_seed == 0: - randomize() - - -func tick(actor: Node, blackboard: Blackboard) -> int: - if _children_bag.is_empty(): - _reset() - - # We need to traverse the array in reverse since we will be manipulating it. - for i in _get_reversed_indexes(): - c = _children_bag[i] - - if c != running_child: - c.before_run(actor, blackboard) - - var response: int = c.tick(actor, blackboard) - if can_send_message(blackboard): - BeehaveDebuggerMessages.process_tick(c.get_instance_id(), response, blackboard.get_debug_data()) - - if c is ConditionLeaf: - blackboard.set_value("last_condition", c, str(actor.get_instance_id())) - blackboard.set_value("last_condition_status", response, str(actor.get_instance_id())) - - match response: - SUCCESS: - _children_bag.erase(c) - c.after_run(actor, blackboard) - return SUCCESS - FAILURE: - _children_bag.erase(c) - c.after_run(actor, blackboard) - RUNNING: - running_child = c - if c is ActionLeaf: - blackboard.set_value("running_action", c, str(actor.get_instance_id())) - return RUNNING - - return FAILURE - - -func after_run(actor: Node, blackboard: Blackboard) -> void: - _reset() - super(actor, blackboard) - - -func interrupt(actor: Node, blackboard: Blackboard) -> void: - _reset() - super(actor, blackboard) - - -func _get_reversed_indexes() -> Array[int]: - var reversed: Array[int] - reversed.assign(range(_children_bag.size())) - reversed.reverse() - return reversed - - -func _reset() -> void: - var new_order = get_shuffled_children() - _children_bag = new_order.duplicate() - _children_bag.reverse() # It needs to run the children in reverse order. - - -func get_class_name() -> Array[StringName]: - var classes := super() - classes.push_back(&"SelectorRandomComposite") - return classes diff --git a/addons/beehave/nodes/composites/selector_random.gd.uid b/addons/beehave/nodes/composites/selector_random.gd.uid deleted file mode 100644 index 617cf42..0000000 --- a/addons/beehave/nodes/composites/selector_random.gd.uid +++ /dev/null @@ -1 +0,0 @@ -uid://cghyxe3l7iepc diff --git a/addons/beehave/nodes/composites/selector_reactive.gd b/addons/beehave/nodes/composites/selector_reactive.gd deleted file mode 100644 index 1dae759..0000000 --- a/addons/beehave/nodes/composites/selector_reactive.gd +++ /dev/null @@ -1,47 +0,0 @@ -@tool -@icon("../../icons/selector_reactive.svg") -class_name SelectorReactiveComposite extends Composite - -## Selector Reactive nodes will attempt to execute each of its children until one of -## them return `SUCCESS`. If all children return `FAILURE`, this node will also -## return `FAILURE`. -## If a child returns `RUNNING` it will restart. - - -func tick(actor: Node, blackboard: Blackboard) -> int: - for c in get_children(): - if c != running_child: - c.before_run(actor, blackboard) - - var response: int = c.tick(actor, blackboard) - if can_send_message(blackboard): - BeehaveDebuggerMessages.process_tick(c.get_instance_id(), response, blackboard.get_debug_data()) - - if c is ConditionLeaf: - blackboard.set_value("last_condition", c, str(actor.get_instance_id())) - blackboard.set_value("last_condition_status", response, str(actor.get_instance_id())) - - match response: - SUCCESS: - # Interrupt any child that was RUNNING before. - if c != running_child: - interrupt(actor, blackboard) - c.after_run(actor, blackboard) - return SUCCESS - FAILURE: - c.after_run(actor, blackboard) - RUNNING: - if c != running_child: - interrupt(actor, blackboard) - running_child = c - if c is ActionLeaf: - blackboard.set_value("running_action", c, str(actor.get_instance_id())) - return RUNNING - - return FAILURE - - -func get_class_name() -> Array[StringName]: - var classes := super() - classes.push_back(&"SelectorReactiveComposite") - return classes diff --git a/addons/beehave/nodes/composites/selector_reactive.gd.uid b/addons/beehave/nodes/composites/selector_reactive.gd.uid deleted file mode 100644 index b753ea1..0000000 --- a/addons/beehave/nodes/composites/selector_reactive.gd.uid +++ /dev/null @@ -1 +0,0 @@ -uid://dy8gicxya3svf diff --git a/addons/beehave/nodes/composites/sequence.gd b/addons/beehave/nodes/composites/sequence.gd deleted file mode 100644 index 4978d93..0000000 --- a/addons/beehave/nodes/composites/sequence.gd +++ /dev/null @@ -1,75 +0,0 @@ -@tool -@icon("../../icons/sequence.svg") -class_name SequenceComposite extends Composite - -## Sequence nodes will attempt to execute all of its children and report -## `SUCCESS` in case all of the children report a `SUCCESS` status code. -## If at least one child reports a `FAILURE` status code, this node will also -## return `FAILURE` and restart. -## In case a child returns `RUNNING` this node will tick again. - -var successful_index: int = 0 - - -func tick(actor: Node, blackboard: Blackboard) -> int: - for c in get_children(): - if c.get_index() < successful_index: - continue - - if c != running_child: - c.before_run(actor, blackboard) - - var response: int = c.tick(actor, blackboard) - if can_send_message(blackboard): - BeehaveDebuggerMessages.process_tick(c.get_instance_id(), response, blackboard.get_debug_data()) - - if c is ConditionLeaf: - blackboard.set_value("last_condition", c, str(actor.get_instance_id())) - blackboard.set_value("last_condition_status", response, str(actor.get_instance_id())) - - match response: - SUCCESS: - _cleanup_running_task(c, actor, blackboard) - successful_index += 1 - c.after_run(actor, blackboard) - FAILURE: - _cleanup_running_task(c, actor, blackboard) - # Interrupt any child that was RUNNING before. - interrupt(actor, blackboard) - c.after_run(actor, blackboard) - return FAILURE - RUNNING: - if c != running_child: - if running_child != null: - running_child.interrupt(actor, blackboard) - running_child = c - if c is ActionLeaf: - blackboard.set_value("running_action", c, str(actor.get_instance_id())) - return RUNNING - - _reset() - return SUCCESS - - -func interrupt(actor: Node, blackboard: Blackboard) -> void: - _reset() - super(actor, blackboard) - - -func _reset() -> void: - successful_index = 0 - - -## Changes `running_action` and `running_child` after the node finishes executing. -func _cleanup_running_task(finished_action: Node, actor: Node, blackboard: Blackboard): - var blackboard_name: String = str(actor.get_instance_id()) - if finished_action == running_child: - running_child = null - if finished_action == blackboard.get_value("running_action", null, blackboard_name): - blackboard.set_value("running_action", null, blackboard_name) - - -func get_class_name() -> Array[StringName]: - var classes := super() - classes.push_back(&"SequenceComposite") - return classes diff --git a/addons/beehave/nodes/composites/sequence.gd.uid b/addons/beehave/nodes/composites/sequence.gd.uid deleted file mode 100644 index 1b366a6..0000000 --- a/addons/beehave/nodes/composites/sequence.gd.uid +++ /dev/null @@ -1 +0,0 @@ -uid://dpp6sguteoq3f diff --git a/addons/beehave/nodes/composites/sequence_random.gd b/addons/beehave/nodes/composites/sequence_random.gd deleted file mode 100644 index 08709ab..0000000 --- a/addons/beehave/nodes/composites/sequence_random.gd +++ /dev/null @@ -1,96 +0,0 @@ -@tool -@icon("../../icons/sequence_random.svg") -class_name SequenceRandomComposite extends RandomizedComposite - -## This node will attempt to execute all of its children just like a -## [code]SequenceStar[/code] would, with the exception that the children -## will be executed in a random order. - -# Emitted whenever the children are shuffled. -signal reset(new_order: Array[Node]) - -## Whether the sequence should start where it left off after a previous failure. -@export var resume_on_failure: bool = false -## Whether the sequence should start where it left off after a previous interruption. -@export var resume_on_interrupt: bool = false - -## A shuffled list of the children that will be executed in reverse order. -var _children_bag: Array[Node] = [] -var c: Node - - -func _ready() -> void: - super() - if random_seed == 0: - randomize() - - -func tick(actor: Node, blackboard: Blackboard) -> int: - if _children_bag.is_empty(): - _reset() - - # We need to traverse the array in reverse since we will be manipulating it. - for i in _get_reversed_indexes(): - c = _children_bag[i] - - if c != running_child: - c.before_run(actor, blackboard) - - var response: int = c.tick(actor, blackboard) - if can_send_message(blackboard): - BeehaveDebuggerMessages.process_tick(c.get_instance_id(), response, blackboard.get_debug_data()) - - if c is ConditionLeaf: - blackboard.set_value("last_condition", c, str(actor.get_instance_id())) - blackboard.set_value("last_condition_status", response, str(actor.get_instance_id())) - - match response: - SUCCESS: - _children_bag.erase(c) - c.after_run(actor, blackboard) - FAILURE: - _children_bag.erase(c) - # Interrupt any child that was RUNNING before - # but do not reset! - super.interrupt(actor, blackboard) - c.after_run(actor, blackboard) - return FAILURE - RUNNING: - running_child = c - if c is ActionLeaf: - blackboard.set_value("running_action", c, str(actor.get_instance_id())) - return RUNNING - - return SUCCESS - - -func after_run(actor: Node, blackboard: Blackboard) -> void: - if not resume_on_failure: - _reset() - super(actor, blackboard) - - -func interrupt(actor: Node, blackboard: Blackboard) -> void: - if not resume_on_interrupt: - _reset() - super(actor, blackboard) - - -func _get_reversed_indexes() -> Array[int]: - var reversed: Array[int] - reversed.assign(range(_children_bag.size())) - reversed.reverse() - return reversed - - -func _reset() -> void: - var new_order: Array[Node] = get_shuffled_children() - _children_bag = new_order.duplicate() - _children_bag.reverse() # It needs to run the children in reverse order. - reset.emit(new_order) - - -func get_class_name() -> Array[StringName]: - var classes := super() - classes.push_back(&"SequenceRandomComposite") - return classes diff --git a/addons/beehave/nodes/composites/sequence_random.gd.uid b/addons/beehave/nodes/composites/sequence_random.gd.uid deleted file mode 100644 index 49ad283..0000000 --- a/addons/beehave/nodes/composites/sequence_random.gd.uid +++ /dev/null @@ -1 +0,0 @@ -uid://yms1po28clx5 diff --git a/addons/beehave/nodes/composites/sequence_reactive.gd b/addons/beehave/nodes/composites/sequence_reactive.gd deleted file mode 100644 index f071181..0000000 --- a/addons/beehave/nodes/composites/sequence_reactive.gd +++ /dev/null @@ -1,63 +0,0 @@ -@tool -@icon("../../icons/sequence_reactive.svg") -class_name SequenceReactiveComposite extends Composite - -## Reactive Sequence nodes will attempt to execute all of its children and report -## `SUCCESS` in case all of the children report a `SUCCESS` status code. -## If at least one child reports a `FAILURE` status code, this node will also -## return `FAILURE` and restart. -## In case a child returns `RUNNING` this node will restart. - -var successful_index: int = 0 - - -func tick(actor: Node, blackboard: Blackboard) -> int: - for c in get_children(): - if c.get_index() < successful_index: - continue - - if c != running_child: - c.before_run(actor, blackboard) - - var response: int = c.tick(actor, blackboard) - if can_send_message(blackboard): - BeehaveDebuggerMessages.process_tick(c.get_instance_id(), response, blackboard.get_debug_data()) - - if c is ConditionLeaf: - blackboard.set_value("last_condition", c, str(actor.get_instance_id())) - blackboard.set_value("last_condition_status", response, str(actor.get_instance_id())) - - match response: - SUCCESS: - successful_index += 1 - c.after_run(actor, blackboard) - FAILURE: - # Interrupt any child that was RUNNING before. - interrupt(actor, blackboard) - c.after_run(actor, blackboard) - return FAILURE - RUNNING: - _reset() - if running_child != c: - interrupt(actor, blackboard) - running_child = c - if c is ActionLeaf: - blackboard.set_value("running_action", c, str(actor.get_instance_id())) - return RUNNING - _reset() - return SUCCESS - - -func interrupt(actor: Node, blackboard: Blackboard) -> void: - _reset() - super(actor, blackboard) - - -func _reset() -> void: - successful_index = 0 - - -func get_class_name() -> Array[StringName]: - var classes := super() - classes.push_back(&"SequenceReactiveComposite") - return classes diff --git a/addons/beehave/nodes/composites/sequence_reactive.gd.uid b/addons/beehave/nodes/composites/sequence_reactive.gd.uid deleted file mode 100644 index 0630968..0000000 --- a/addons/beehave/nodes/composites/sequence_reactive.gd.uid +++ /dev/null @@ -1 +0,0 @@ -uid://qy6yh6pkmxxy diff --git a/addons/beehave/nodes/composites/sequence_star.gd b/addons/beehave/nodes/composites/sequence_star.gd deleted file mode 100644 index c608ca1..0000000 --- a/addons/beehave/nodes/composites/sequence_star.gd +++ /dev/null @@ -1,61 +0,0 @@ -@tool -@icon("../../icons/sequence_reactive.svg") -class_name SequenceStarComposite extends Composite - -## Sequence Star nodes will attempt to execute all of its children and report -## `SUCCESS` in case all of the children report a `SUCCESS` status code. -## If at least one child reports a `FAILURE` status code, this node will also -## return `FAILURE` and tick again. -## In case a child returns `RUNNING` this node will tick again. - -var successful_index: int = 0 - - -func tick(actor: Node, blackboard: Blackboard) -> int: - for c in get_children(): - if c.get_index() < successful_index: - continue - - if c != running_child: - c.before_run(actor, blackboard) - - var response: int = c.tick(actor, blackboard) - if can_send_message(blackboard): - BeehaveDebuggerMessages.process_tick(c.get_instance_id(), response, blackboard.get_debug_data()) - - if c is ConditionLeaf: - blackboard.set_value("last_condition", c, str(actor.get_instance_id())) - blackboard.set_value("last_condition_status", response, str(actor.get_instance_id())) - - match response: - SUCCESS: - successful_index += 1 - c.after_run(actor, blackboard) - FAILURE: - # Interrupt any child that was RUNNING before - # but do not reset! - super.interrupt(actor, blackboard) - c.after_run(actor, blackboard) - return FAILURE - RUNNING: - running_child = c - if c is ActionLeaf: - blackboard.set_value("running_action", c, str(actor.get_instance_id())) - return RUNNING - _reset() - return SUCCESS - - -func interrupt(actor: Node, blackboard: Blackboard) -> void: - _reset() - super(actor, blackboard) - - -func _reset() -> void: - successful_index = 0 - - -func get_class_name() -> Array[StringName]: - var classes := super() - classes.push_back(&"SequenceStarComposite") - return classes diff --git a/addons/beehave/nodes/composites/sequence_star.gd.uid b/addons/beehave/nodes/composites/sequence_star.gd.uid deleted file mode 100644 index bddc806..0000000 --- a/addons/beehave/nodes/composites/sequence_star.gd.uid +++ /dev/null @@ -1 +0,0 @@ -uid://dta6p04i1bg42 diff --git a/addons/beehave/nodes/composites/simple_parallel.gd b/addons/beehave/nodes/composites/simple_parallel.gd deleted file mode 100644 index 8511808..0000000 --- a/addons/beehave/nodes/composites/simple_parallel.gd +++ /dev/null @@ -1,122 +0,0 @@ -@tool -@icon("../../icons/simple_parallel.svg") -class_name SimpleParallelComposite extends Composite - -## Simple Parallel nodes will attampt to execute all chidren at same time and -## can only have exactly two children. First child as primary node, second -## child as secondary node. -## This node will always report primary node's state, and continue tick while -## primary node return 'RUNNING'. The state of secondary node will be ignored -## and executed like a subtree. -## If primary node return 'SUCCESS' or 'FAILURE', this node will interrupt -## secondary node and return primary node's result. -## If this node is running under delay mode, it will wait seconday node -## finish its action after primary node terminates. - -#how many times should secondary node repeat, zero means loop forever -@export var secondary_node_repeat_count: int = 0 - -#wether to wait secondary node finish its current action after primary node finished -@export var delay_mode: bool = false - -var delayed_result := SUCCESS -var main_task_finished: bool = false -var secondary_node_running: bool = false -var secondary_node_repeat_left: int = 0 - - -func _get_configuration_warnings() -> PackedStringArray: - var warnings: PackedStringArray = super._get_configuration_warnings() - - if get_child_count() != 2: - warnings.append("SimpleParallel should have exactly two child nodes.") - - if not get_child(0) is ActionLeaf: - warnings.append("SimpleParallel should have an action leaf node as first child node.") - - return warnings - - -func tick(actor, blackboard: Blackboard): - for c in get_children(): - var node_index: int = c.get_index() - if node_index == 0 and not main_task_finished: - if c != running_child: - c.before_run(actor, blackboard) - - var response: int = c.tick(actor, blackboard) - if can_send_message(blackboard): - BeehaveDebuggerMessages.process_tick(c.get_instance_id(), response, blackboard.get_debug_data()) - - delayed_result = response - match response: - SUCCESS, FAILURE: - _cleanup_running_task(c, actor, blackboard) - c.after_run(actor, blackboard) - main_task_finished = true - if not delay_mode: - if secondary_node_running: - get_child(1).interrupt(actor, blackboard) - _reset() - return delayed_result - RUNNING: - running_child = c - if c is ActionLeaf: - blackboard.set_value("running_action", c, str(actor.get_instance_id())) - - elif node_index == 1: - if secondary_node_repeat_count == 0 or secondary_node_repeat_left > 0: - if not secondary_node_running: - c.before_run(actor, blackboard) - var subtree_response = c.tick(actor, blackboard) - if subtree_response != RUNNING: - secondary_node_running = false - c.after_run(actor, blackboard) - if delay_mode and main_task_finished: - _reset() - return delayed_result - elif secondary_node_repeat_left > 0: - secondary_node_repeat_left -= 1 - else: - secondary_node_running = true - - return RUNNING - - -func before_run(actor: Node, blackboard: Blackboard) -> void: - secondary_node_repeat_left = secondary_node_repeat_count - super(actor, blackboard) - - -func interrupt(actor: Node, blackboard: Blackboard) -> void: - if not main_task_finished: - get_child(0).interrupt(actor, blackboard) - if secondary_node_running: - get_child(1).interrupt(actor, blackboard) - _reset() - super(actor, blackboard) - - -func after_run(actor: Node, blackboard: Blackboard) -> void: - _reset() - super(actor, blackboard) - - -func _reset() -> void: - main_task_finished = false - secondary_node_running = false - - -## Changes `running_action` and `running_child` after the node finishes executing. -func _cleanup_running_task(finished_action: Node, actor: Node, blackboard: Blackboard): - var blackboard_name = str(actor.get_instance_id()) - if finished_action == running_child: - running_child = null - if finished_action == blackboard.get_value("running_action", null, blackboard_name): - blackboard.set_value("running_action", null, blackboard_name) - - -func get_class_name() -> Array[StringName]: - var classes := super() - classes.push_back(&"SimpleParallelComposite") - return classes diff --git a/addons/beehave/nodes/composites/simple_parallel.gd.uid b/addons/beehave/nodes/composites/simple_parallel.gd.uid deleted file mode 100644 index 19a4d15..0000000 --- a/addons/beehave/nodes/composites/simple_parallel.gd.uid +++ /dev/null @@ -1 +0,0 @@ -uid://cvlaakk6vpu3x diff --git a/addons/beehave/nodes/decorators/cooldown.gd b/addons/beehave/nodes/decorators/cooldown.gd deleted file mode 100644 index bba1217..0000000 --- a/addons/beehave/nodes/decorators/cooldown.gd +++ /dev/null @@ -1,49 +0,0 @@ -@tool -@icon("../../icons/cooldown.svg") -extends Decorator -class_name CooldownDecorator - -## The Cooldown Decorator will return 'FAILURE' for a set amount of time -## after executing its child. -## The timer resets the next time its child is executed and it is not `RUNNING` - -## The wait time in seconds -@export var wait_time := 0.0 - -@onready var cache_key = "cooldown_%s" % self.get_instance_id() - - -func tick(actor: Node, blackboard: Blackboard) -> int: - var c: BeehaveNode = get_child(0) - var remaining_time: float = blackboard.get_value(cache_key, 0.0, str(actor.get_instance_id())) - var response: int - - if c != running_child: - c.before_run(actor, blackboard) - - if remaining_time > 0: - response = FAILURE - - remaining_time -= get_physics_process_delta_time() - blackboard.set_value(cache_key, remaining_time, str(actor.get_instance_id())) - - if can_send_message(blackboard): - BeehaveDebuggerMessages.process_tick(self.get_instance_id(), response, blackboard.get_debug_data()) - else: - response = c.tick(actor, blackboard) - - if can_send_message(blackboard): - BeehaveDebuggerMessages.process_tick(c.get_instance_id(), response, blackboard.get_debug_data()) - - if c is ConditionLeaf: - blackboard.set_value("last_condition", c, str(actor.get_instance_id())) - blackboard.set_value("last_condition_status", response, str(actor.get_instance_id())) - - if response == RUNNING and c is ActionLeaf: - running_child = c - blackboard.set_value("running_action", c, str(actor.get_instance_id())) - - if response != RUNNING: - blackboard.set_value(cache_key, wait_time, str(actor.get_instance_id())) - - return response diff --git a/addons/beehave/nodes/decorators/cooldown.gd.uid b/addons/beehave/nodes/decorators/cooldown.gd.uid deleted file mode 100644 index 09d5958..0000000 --- a/addons/beehave/nodes/decorators/cooldown.gd.uid +++ /dev/null @@ -1 +0,0 @@ -uid://bwf0rvlqcwfmc diff --git a/addons/beehave/nodes/decorators/decorator.gd b/addons/beehave/nodes/decorators/decorator.gd deleted file mode 100644 index 3b93498..0000000 --- a/addons/beehave/nodes/decorators/decorator.gd +++ /dev/null @@ -1,33 +0,0 @@ -@tool -@icon("../../icons/category_decorator.svg") -class_name Decorator extends BeehaveNode - -## Decorator nodes are used to transform the result received by its child. -## Must only have one child. - -var running_child: BeehaveNode = null - - -func _get_configuration_warnings() -> PackedStringArray: - var warnings: PackedStringArray = super._get_configuration_warnings() - - if get_child_count() != 1: - warnings.append("Decorator should have exactly one child node.") - - return warnings - - -func interrupt(actor: Node, blackboard: Blackboard) -> void: - if running_child != null: - running_child.interrupt(actor, blackboard) - running_child = null - - -func after_run(actor: Node, blackboard: Blackboard) -> void: - running_child = null - - -func get_class_name() -> Array[StringName]: - var classes := super() - classes.push_back(&"Decorator") - return classes diff --git a/addons/beehave/nodes/decorators/decorator.gd.uid b/addons/beehave/nodes/decorators/decorator.gd.uid deleted file mode 100644 index 19f51a3..0000000 --- a/addons/beehave/nodes/decorators/decorator.gd.uid +++ /dev/null @@ -1 +0,0 @@ -uid://bp6xapaqingvw diff --git a/addons/beehave/nodes/decorators/delayer.gd b/addons/beehave/nodes/decorators/delayer.gd deleted file mode 100644 index 6b023e4..0000000 --- a/addons/beehave/nodes/decorators/delayer.gd +++ /dev/null @@ -1,49 +0,0 @@ -@tool -@icon("../../icons/delayer.svg") -extends Decorator -class_name DelayDecorator - -## The Delay Decorator will return 'RUNNING' for a set amount of time -## before executing its child. -## The timer resets when both it and its child are not `RUNNING` - -## The wait time in seconds -@export var wait_time := 0.0 - -@onready var cache_key = "time_limiter_%s" % self.get_instance_id() - - -func tick(actor: Node, blackboard: Blackboard) -> int: - var c: BeehaveNode = get_child(0) - var total_time: float = blackboard.get_value(cache_key, 0.0, str(actor.get_instance_id())) - var response: int - - if c != running_child: - c.before_run(actor, blackboard) - - if total_time < wait_time: - response = RUNNING - - total_time += get_physics_process_delta_time() - blackboard.set_value(cache_key, total_time, str(actor.get_instance_id())) - - if can_send_message(blackboard): - BeehaveDebuggerMessages.process_tick(self.get_instance_id(), response, blackboard.get_debug_data()) - else: - response = c.tick(actor, blackboard) - - if can_send_message(blackboard): - BeehaveDebuggerMessages.process_tick(c.get_instance_id(), response, blackboard.get_debug_data()) - - if c is ConditionLeaf: - blackboard.set_value("last_condition", c, str(actor.get_instance_id())) - blackboard.set_value("last_condition_status", response, str(actor.get_instance_id())) - - if response == RUNNING and c is ActionLeaf: - running_child = c - blackboard.set_value("running_action", c, str(actor.get_instance_id())) - - if response != RUNNING: - blackboard.set_value(cache_key, 0.0, str(actor.get_instance_id())) - - return response diff --git a/addons/beehave/nodes/decorators/delayer.gd.uid b/addons/beehave/nodes/decorators/delayer.gd.uid deleted file mode 100644 index 94b5e12..0000000 --- a/addons/beehave/nodes/decorators/delayer.gd.uid +++ /dev/null @@ -1 +0,0 @@ -uid://ctsihhatr3rvb diff --git a/addons/beehave/nodes/decorators/failer.gd b/addons/beehave/nodes/decorators/failer.gd deleted file mode 100644 index e8c5396..0000000 --- a/addons/beehave/nodes/decorators/failer.gd +++ /dev/null @@ -1,35 +0,0 @@ -@tool -@icon("../../icons/failer.svg") -class_name AlwaysFailDecorator extends Decorator - -## A Failer node will always return a `FAILURE` status code. - - -func tick(actor: Node, blackboard: Blackboard) -> int: - var c: BeehaveNode = get_child(0) - - if c != running_child: - c.before_run(actor, blackboard) - - var response: int = c.tick(actor, blackboard) - if can_send_message(blackboard): - BeehaveDebuggerMessages.process_tick(c.get_instance_id(), response, blackboard.get_debug_data()) - - if c is ConditionLeaf: - blackboard.set_value("last_condition", c, str(actor.get_instance_id())) - blackboard.set_value("last_condition_status", response, str(actor.get_instance_id())) - - if response == RUNNING: - running_child = c - if c is ActionLeaf: - blackboard.set_value("running_action", c, str(actor.get_instance_id())) - return RUNNING - else: - c.after_run(actor, blackboard) - return FAILURE - - -func get_class_name() -> Array[StringName]: - var classes := super() - classes.push_back(&"AlwaysFailDecorator") - return classes diff --git a/addons/beehave/nodes/decorators/failer.gd.uid b/addons/beehave/nodes/decorators/failer.gd.uid deleted file mode 100644 index 7b5f2eb..0000000 --- a/addons/beehave/nodes/decorators/failer.gd.uid +++ /dev/null @@ -1 +0,0 @@ -uid://flm7owii3wyb diff --git a/addons/beehave/nodes/decorators/inverter.gd b/addons/beehave/nodes/decorators/inverter.gd deleted file mode 100644 index f6f38c5..0000000 --- a/addons/beehave/nodes/decorators/inverter.gd +++ /dev/null @@ -1,43 +0,0 @@ -@tool -@icon("../../icons/inverter.svg") -class_name InverterDecorator extends Decorator - -## An inverter will return `FAILURE` in case it's child returns a `SUCCESS` status -## code or `SUCCESS` in case its child returns a `FAILURE` status code. - - -func tick(actor: Node, blackboard: Blackboard) -> int: - var c: BeehaveNode = get_child(0) - - if c != running_child: - c.before_run(actor, blackboard) - - var response: int = c.tick(actor, blackboard) - if can_send_message(blackboard): - BeehaveDebuggerMessages.process_tick(c.get_instance_id(), response, blackboard.get_debug_data()) - - if c is ConditionLeaf: - blackboard.set_value("last_condition", c, str(actor.get_instance_id())) - blackboard.set_value("last_condition_status", response, str(actor.get_instance_id())) - - match response: - SUCCESS: - c.after_run(actor, blackboard) - return FAILURE - FAILURE: - c.after_run(actor, blackboard) - return SUCCESS - RUNNING: - running_child = c - if c is ActionLeaf: - blackboard.set_value("running_action", c, str(actor.get_instance_id())) - return RUNNING - _: - push_error("This should be unreachable") - return -1 - - -func get_class_name() -> Array[StringName]: - var classes := super() - classes.push_back(&"InverterDecorator") - return classes diff --git a/addons/beehave/nodes/decorators/inverter.gd.uid b/addons/beehave/nodes/decorators/inverter.gd.uid deleted file mode 100644 index f9b1e8e..0000000 --- a/addons/beehave/nodes/decorators/inverter.gd.uid +++ /dev/null @@ -1 +0,0 @@ -uid://cbnad7d86h0yc diff --git a/addons/beehave/nodes/decorators/limiter.gd b/addons/beehave/nodes/decorators/limiter.gd deleted file mode 100644 index 3b6127e..0000000 --- a/addons/beehave/nodes/decorators/limiter.gd +++ /dev/null @@ -1,60 +0,0 @@ -@tool -@icon("../../icons/limiter.svg") -class_name LimiterDecorator extends Decorator - -## The limiter will execute its `RUNNING` child `x` amount of times. When the number of -## maximum ticks is reached, it will return a `FAILURE` status code. -## The count resets the next time that a child is not `RUNNING` - -@onready var cache_key = "limiter_%s" % self.get_instance_id() - -@export var max_count: int = 0 - - -func tick(actor: Node, blackboard: Blackboard) -> int: - if not get_child_count() == 1: - return FAILURE - - var child: BeehaveNode = get_child(0) - var current_count: int = blackboard.get_value(cache_key, 0, str(actor.get_instance_id())) - - if current_count < max_count: - blackboard.set_value(cache_key, current_count + 1, str(actor.get_instance_id())) - var response: int = child.tick(actor, blackboard) - if can_send_message(blackboard): - BeehaveDebuggerMessages.process_tick(child.get_instance_id(), response, blackboard.get_debug_data()) - - if child is ConditionLeaf: - blackboard.set_value("last_condition", child, str(actor.get_instance_id())) - blackboard.set_value("last_condition_status", response, str(actor.get_instance_id())) - - if child is ActionLeaf and response == RUNNING: - running_child = child - blackboard.set_value("running_action", child, str(actor.get_instance_id())) - - if response != RUNNING: - child.after_run(actor, blackboard) - - return response - else: - interrupt(actor, blackboard) - child.after_run(actor, blackboard) - return FAILURE - - -func before_run(actor: Node, blackboard: Blackboard) -> void: - blackboard.set_value(cache_key, 0, str(actor.get_instance_id())) - if get_child_count() > 0: - get_child(0).before_run(actor, blackboard) - - -func get_class_name() -> Array[StringName]: - var classes := super() - classes.push_back(&"LimiterDecorator") - return classes - - -func _get_configuration_warnings() -> PackedStringArray: - if not get_child_count() == 1: - return ["Requires exactly one child node"] - return [] diff --git a/addons/beehave/nodes/decorators/limiter.gd.uid b/addons/beehave/nodes/decorators/limiter.gd.uid deleted file mode 100644 index 8464a26..0000000 --- a/addons/beehave/nodes/decorators/limiter.gd.uid +++ /dev/null @@ -1 +0,0 @@ -uid://b845o3n4goomv diff --git a/addons/beehave/nodes/decorators/repeater.gd b/addons/beehave/nodes/decorators/repeater.gd deleted file mode 100644 index d106a38..0000000 --- a/addons/beehave/nodes/decorators/repeater.gd +++ /dev/null @@ -1,58 +0,0 @@ -## The repeater will execute its child until it returns `SUCCESS` a certain amount of times. -## When the number of maximum ticks is reached, it will return a `SUCCESS` status code. -## If the child returns `FAILURE`, the repeater will return `FAILURE` immediately. -@tool -@icon("../../icons/repeater.svg") -class_name RepeaterDecorator extends Decorator - -@export var repetitions: int = 1 -var current_count: int = 0 - - -func before_run(actor: Node, blackboard: Blackboard): - current_count = 0 - - -func tick(actor: Node, blackboard: Blackboard) -> int: - var child: BeehaveNode = get_child(0) - - if current_count < repetitions: - if running_child == null: - child.before_run(actor, blackboard) - - var response: int = child.tick(actor, blackboard) - - if can_send_message(blackboard): - BeehaveDebuggerMessages.process_tick(child.get_instance_id(), response, blackboard.get_debug_data()) - - if child is ConditionLeaf: - blackboard.set_value("last_condition", child, str(actor.get_instance_id())) - blackboard.set_value("last_condition_status", response, str(actor.get_instance_id())) - - if response == RUNNING: - running_child = child - if child is ActionLeaf: - blackboard.set_value("running_action", child, str(actor.get_instance_id())) - return RUNNING - - current_count += 1 - child.after_run(actor, blackboard) - - if running_child != null: - running_child = null - - if response == FAILURE: - return FAILURE - - if current_count >= repetitions: - return SUCCESS - - return RUNNING - else: - return SUCCESS - - -func get_class_name() -> Array[StringName]: - var classes := super() - classes.push_back(&"LimiterDecorator") - return classes diff --git a/addons/beehave/nodes/decorators/repeater.gd.uid b/addons/beehave/nodes/decorators/repeater.gd.uid deleted file mode 100644 index d581232..0000000 --- a/addons/beehave/nodes/decorators/repeater.gd.uid +++ /dev/null @@ -1 +0,0 @@ -uid://c5tb6kww3y0yj diff --git a/addons/beehave/nodes/decorators/succeeder.gd b/addons/beehave/nodes/decorators/succeeder.gd deleted file mode 100644 index 2a7d5ed..0000000 --- a/addons/beehave/nodes/decorators/succeeder.gd +++ /dev/null @@ -1,35 +0,0 @@ -@tool -@icon("../../icons/succeeder.svg") -class_name AlwaysSucceedDecorator extends Decorator - -## A succeeder node will always return a `SUCCESS` status code. - - -func tick(actor: Node, blackboard: Blackboard) -> int: - var c: BeehaveNode = get_child(0) - - if c != running_child: - c.before_run(actor, blackboard) - - var response: int = c.tick(actor, blackboard) - if can_send_message(blackboard): - BeehaveDebuggerMessages.process_tick(c.get_instance_id(), response, blackboard.get_debug_data()) - - if c is ConditionLeaf: - blackboard.set_value("last_condition", c, str(actor.get_instance_id())) - blackboard.set_value("last_condition_status", response, str(actor.get_instance_id())) - - if response == RUNNING: - running_child = c - if c is ActionLeaf: - blackboard.set_value("running_action", c, str(actor.get_instance_id())) - return RUNNING - else: - c.after_run(actor, blackboard) - return SUCCESS - - -func get_class_name() -> Array[StringName]: - var classes := super() - classes.push_back(&"AlwaysSucceedDecorator") - return classes diff --git a/addons/beehave/nodes/decorators/succeeder.gd.uid b/addons/beehave/nodes/decorators/succeeder.gd.uid deleted file mode 100644 index c45b903..0000000 --- a/addons/beehave/nodes/decorators/succeeder.gd.uid +++ /dev/null @@ -1 +0,0 @@ -uid://bpdjhiyqbm1hc diff --git a/addons/beehave/nodes/decorators/time_limiter.gd b/addons/beehave/nodes/decorators/time_limiter.gd deleted file mode 100644 index c19c598..0000000 --- a/addons/beehave/nodes/decorators/time_limiter.gd +++ /dev/null @@ -1,60 +0,0 @@ -@tool -@icon("../../icons/limiter.svg") -class_name TimeLimiterDecorator extends Decorator - -## The Time Limit Decorator will give its `RUNNING` child a set amount of time to finish -## before interrupting it and return a `FAILURE` status code. -## The timer resets the next time that a child is not `RUNNING` - -@export var wait_time := 0.0 - -@onready var cache_key: String = "time_limiter_%s" % self.get_instance_id() - - -func tick(actor: Node, blackboard: Blackboard) -> int: - if not get_child_count() == 1: - return FAILURE - - var child: BeehaveNode = self.get_child(0) - var time_left: float = blackboard.get_value(cache_key, 0.0, str(actor.get_instance_id())) - - if time_left < wait_time: - time_left += get_physics_process_delta_time() - blackboard.set_value(cache_key, time_left, str(actor.get_instance_id())) - var response: int = child.tick(actor, blackboard) - if can_send_message(blackboard): - BeehaveDebuggerMessages.process_tick(child.get_instance_id(), response, blackboard.get_debug_data()) - - if child is ConditionLeaf: - blackboard.set_value("last_condition", child, str(actor.get_instance_id())) - blackboard.set_value("last_condition_status", response, str(actor.get_instance_id())) - - if response == RUNNING: - running_child = child - if child is ActionLeaf: - blackboard.set_value("running_action", child, str(actor.get_instance_id())) - else: - child.after_run(actor, blackboard) - return response - else: - interrupt(actor, blackboard) - child.after_run(actor, blackboard) - return FAILURE - - -func before_run(actor: Node, blackboard: Blackboard) -> void: - blackboard.set_value(cache_key, 0.0, str(actor.get_instance_id())) - if get_child_count() > 0: - get_child(0).before_run(actor, blackboard) - - -func get_class_name() -> Array[StringName]: - var classes := super() - classes.push_back(&"TimeLimiterDecorator") - return classes - - -func _get_configuration_warnings() -> PackedStringArray: - if not get_child_count() == 1: - return ["Requires exactly one child node"] - return [] diff --git a/addons/beehave/nodes/decorators/time_limiter.gd.uid b/addons/beehave/nodes/decorators/time_limiter.gd.uid deleted file mode 100644 index ea2033e..0000000 --- a/addons/beehave/nodes/decorators/time_limiter.gd.uid +++ /dev/null @@ -1 +0,0 @@ -uid://cjwti6iw0231n diff --git a/addons/beehave/nodes/decorators/until_fail.gd b/addons/beehave/nodes/decorators/until_fail.gd deleted file mode 100644 index 82dc686..0000000 --- a/addons/beehave/nodes/decorators/until_fail.gd +++ /dev/null @@ -1,33 +0,0 @@ -@tool -@icon("../../icons/until_fail.svg") -class_name UntilFailDecorator -extends Decorator - -## The UntilFail Decorator will return `RUNNING` if its child returns -## `SUCCESS` or `RUNNING` or it will return `SUCCESS` if its child returns -## `FAILURE` - - -func tick(actor: Node, blackboard: Blackboard) -> int: - var c: BeehaveNode = get_child(0) - - if c != running_child: - c.before_run(actor, blackboard) - - var response: int = c.tick(actor, blackboard) - if can_send_message(blackboard): - BeehaveDebuggerMessages.process_tick(c.get_instance_id(), response, blackboard.get_debug_data()) - - if c is ConditionLeaf: - blackboard.set_value("last_condition", c, str(actor.get_instance_id())) - blackboard.set_value("last_condition_status", response, str(actor.get_instance_id())) - - if response == RUNNING: - running_child = c - if c is ActionLeaf: - blackboard.set_value("running_action", c, str(actor.get_instance_id())) - return RUNNING - if response == SUCCESS: - return RUNNING - - return SUCCESS diff --git a/addons/beehave/nodes/decorators/until_fail.gd.uid b/addons/beehave/nodes/decorators/until_fail.gd.uid deleted file mode 100644 index 81b6630..0000000 --- a/addons/beehave/nodes/decorators/until_fail.gd.uid +++ /dev/null @@ -1 +0,0 @@ -uid://bm36533ik0a18 diff --git a/addons/beehave/nodes/leaves/action.gd b/addons/beehave/nodes/leaves/action.gd deleted file mode 100644 index 9074c07..0000000 --- a/addons/beehave/nodes/leaves/action.gd +++ /dev/null @@ -1,14 +0,0 @@ -@tool -@icon("../../icons/action.svg") -class_name ActionLeaf extends Leaf - -## Actions are leaf nodes that define a task to be performed by an actor. -## Their execution can be long running, potentially being called across multiple -## frame executions. In this case, the node should return `RUNNING` until the -## action is completed. - - -func get_class_name() -> Array[StringName]: - var classes := super() - classes.push_back(&"ActionLeaf") - return classes diff --git a/addons/beehave/nodes/leaves/action.gd.uid b/addons/beehave/nodes/leaves/action.gd.uid deleted file mode 100644 index f547105..0000000 --- a/addons/beehave/nodes/leaves/action.gd.uid +++ /dev/null @@ -1 +0,0 @@ -uid://cmhju2hk20nqt diff --git a/addons/beehave/nodes/leaves/blackboard_compare.gd b/addons/beehave/nodes/leaves/blackboard_compare.gd deleted file mode 100644 index 38a870d..0000000 --- a/addons/beehave/nodes/leaves/blackboard_compare.gd +++ /dev/null @@ -1,65 +0,0 @@ -@tool -class_name BlackboardCompareCondition extends ConditionLeaf - -## Compares two values using the specified comparison operator. -## Returns [code]FAILURE[/code] if any of the expression fails or the -## comparison operation returns [code]false[/code], otherwise it returns [code]SUCCESS[/code]. - -enum Operators { - EQUAL, - NOT_EQUAL, - GREATER, - LESS, - GREATER_EQUAL, - LESS_EQUAL, -} - -## Expression represetning left operand. -## This value can be any valid GDScript expression. -## In order to use the existing blackboard keys for comparison, -## use get_value("key_name") e.g. get_value("direction").length() -@export_placeholder(EXPRESSION_PLACEHOLDER) var left_operand: String = "" -## Comparison operator. -@export_enum("==", "!=", ">", "<", ">=", "<=") var operator: int = 0 -## Expression represetning right operand. -## This value can be any valid GDScript expression. -## In order to use the existing blackboard keys for comparison, -## use get_value("key_name") e.g. get_value("direction").length() -@export_placeholder(EXPRESSION_PLACEHOLDER) var right_operand: String = "" - -@onready var _left_expression: Expression = _parse_expression(left_operand) -@onready var _right_expression: Expression = _parse_expression(right_operand) - - -func tick(actor: Node, blackboard: Blackboard) -> int: - var left: Variant = _left_expression.execute([], blackboard) - - if _left_expression.has_execute_failed(): - return FAILURE - - var right: Variant = _right_expression.execute([], blackboard) - - if _right_expression.has_execute_failed(): - return FAILURE - - var result: bool = false - - match operator: - Operators.EQUAL: - result = left == right - Operators.NOT_EQUAL: - result = left != right - Operators.GREATER: - result = left > right - Operators.LESS: - result = left < right - Operators.GREATER_EQUAL: - result = left >= right - Operators.LESS_EQUAL: - result = left <= right - - return SUCCESS if result else FAILURE - - -func _get_expression_sources() -> Array[String]: - return [left_operand, right_operand] diff --git a/addons/beehave/nodes/leaves/blackboard_compare.gd.uid b/addons/beehave/nodes/leaves/blackboard_compare.gd.uid deleted file mode 100644 index 67923db..0000000 --- a/addons/beehave/nodes/leaves/blackboard_compare.gd.uid +++ /dev/null @@ -1 +0,0 @@ -uid://cu1hksqs516ob diff --git a/addons/beehave/nodes/leaves/blackboard_erase.gd b/addons/beehave/nodes/leaves/blackboard_erase.gd deleted file mode 100644 index e5cc1d4..0000000 --- a/addons/beehave/nodes/leaves/blackboard_erase.gd +++ /dev/null @@ -1,25 +0,0 @@ -@tool -class_name BlackboardEraseAction extends ActionLeaf - -## Erases the specified key from the blackboard. -## Returns [code]FAILURE[/code] if expression execution fails, otherwise [code]SUCCESS[/code]. - -## Expression representing a blackboard key. -@export_placeholder(EXPRESSION_PLACEHOLDER) var key: String = "" - -@onready var _key_expression: Expression = _parse_expression(key) - - -func tick(actor: Node, blackboard: Blackboard) -> int: - var key_value: Variant = _key_expression.execute([], blackboard) - - if _key_expression.has_execute_failed(): - return FAILURE - - blackboard.erase_value(key_value) - - return SUCCESS - - -func _get_expression_sources() -> Array[String]: - return [key] diff --git a/addons/beehave/nodes/leaves/blackboard_erase.gd.uid b/addons/beehave/nodes/leaves/blackboard_erase.gd.uid deleted file mode 100644 index de2fce4..0000000 --- a/addons/beehave/nodes/leaves/blackboard_erase.gd.uid +++ /dev/null @@ -1 +0,0 @@ -uid://bb2cjlsbsnot0 diff --git a/addons/beehave/nodes/leaves/blackboard_has.gd b/addons/beehave/nodes/leaves/blackboard_has.gd deleted file mode 100644 index 2ee5e92..0000000 --- a/addons/beehave/nodes/leaves/blackboard_has.gd +++ /dev/null @@ -1,23 +0,0 @@ -@tool -class_name BlackboardHasCondition extends ConditionLeaf - -## Returns [code]FAILURE[/code] if expression execution fails or the specified key doesn't exist. -## Returns [code]SUCCESS[/code] if blackboard has the specified key. - -## Expression representing a blackboard key. -@export_placeholder(EXPRESSION_PLACEHOLDER) var key: String = "" - -@onready var _key_expression: Expression = _parse_expression(key) - - -func tick(actor: Node, blackboard: Blackboard) -> int: - var key_value: Variant = _key_expression.execute([], blackboard) - - if _key_expression.has_execute_failed(): - return FAILURE - - return SUCCESS if blackboard.has_value(key_value) else FAILURE - - -func _get_expression_sources() -> Array[String]: - return [key] diff --git a/addons/beehave/nodes/leaves/blackboard_has.gd.uid b/addons/beehave/nodes/leaves/blackboard_has.gd.uid deleted file mode 100644 index 96eceb4..0000000 --- a/addons/beehave/nodes/leaves/blackboard_has.gd.uid +++ /dev/null @@ -1 +0,0 @@ -uid://6eot4wxyunet diff --git a/addons/beehave/nodes/leaves/blackboard_set.gd b/addons/beehave/nodes/leaves/blackboard_set.gd deleted file mode 100644 index 4f0ed9f..0000000 --- a/addons/beehave/nodes/leaves/blackboard_set.gd +++ /dev/null @@ -1,33 +0,0 @@ -@tool -class_name BlackboardSetAction extends ActionLeaf - -## Sets the specified key to the specified value. -## Returns [code]FAILURE[/code] if expression execution fails, otherwise [code]SUCCESS[/code]. - -## Expression representing a blackboard key. -@export_placeholder(EXPRESSION_PLACEHOLDER) var key: String = "" -## Expression representing a blackboard value to assign to the specified key. -@export_placeholder(EXPRESSION_PLACEHOLDER) var value: String = "" - -@onready var _key_expression: Expression = _parse_expression(key) -@onready var _value_expression: Expression = _parse_expression(value) - - -func tick(actor: Node, blackboard: Blackboard) -> int: - var key_value: Variant = _key_expression.execute([], blackboard) - - if _key_expression.has_execute_failed(): - return FAILURE - - var value_value: Variant = _value_expression.execute([], blackboard) - - if _value_expression.has_execute_failed(): - return FAILURE - - blackboard.set_value(key_value, value_value) - - return SUCCESS - - -func _get_expression_sources() -> Array[String]: - return [key, value] diff --git a/addons/beehave/nodes/leaves/blackboard_set.gd.uid b/addons/beehave/nodes/leaves/blackboard_set.gd.uid deleted file mode 100644 index cfa4cff..0000000 --- a/addons/beehave/nodes/leaves/blackboard_set.gd.uid +++ /dev/null @@ -1 +0,0 @@ -uid://b6tagfqmdwqco diff --git a/addons/beehave/nodes/leaves/condition.gd b/addons/beehave/nodes/leaves/condition.gd deleted file mode 100644 index f4610b4..0000000 --- a/addons/beehave/nodes/leaves/condition.gd +++ /dev/null @@ -1,12 +0,0 @@ -@tool -@icon("../../icons/condition.svg") -class_name ConditionLeaf extends Leaf - -## Conditions are leaf nodes that either return SUCCESS or FAILURE depending on -## a single simple condition. They should never return `RUNNING`. - - -func get_class_name() -> Array[StringName]: - var classes := super() - classes.push_back(&"ConditionLeaf") - return classes diff --git a/addons/beehave/nodes/leaves/condition.gd.uid b/addons/beehave/nodes/leaves/condition.gd.uid deleted file mode 100644 index a79e871..0000000 --- a/addons/beehave/nodes/leaves/condition.gd.uid +++ /dev/null @@ -1 +0,0 @@ -uid://dn0x056bc10ip diff --git a/addons/beehave/nodes/leaves/leaf.gd b/addons/beehave/nodes/leaves/leaf.gd deleted file mode 100644 index 4946c7d..0000000 --- a/addons/beehave/nodes/leaves/leaf.gd +++ /dev/null @@ -1,48 +0,0 @@ -@tool -@icon("../../icons/category_leaf.svg") -class_name Leaf extends BeehaveNode - -## Base class for all leaf nodes of the tree. - -const EXPRESSION_PLACEHOLDER: String = "Insert an expression..." - - -func _get_configuration_warnings() -> PackedStringArray: - var warnings: PackedStringArray = [] - - var children: Array[Node] = get_children() - - if children.any(func(x): return x is BeehaveNode): - warnings.append("Leaf nodes should not have any child nodes. They won't be ticked.") - - for source in _get_expression_sources(): - var error_text: String = _parse_expression(source).get_error_text() - if not error_text.is_empty(): - warnings.append("Expression `%s` is invalid! Error text: `%s`" % [source, error_text]) - - return warnings - - -func _parse_expression(source: String) -> Expression: - var result: Expression = Expression.new() - var error: int = result.parse(source) - - if not Engine.is_editor_hint() and error != OK: - push_error( - ( - "[Leaf] Couldn't parse expression with source: `%s` Error text: `%s`" - % [source, result.get_error_text()] - ) - ) - - return result - - -func _get_expression_sources() -> Array[String]: # virtual - return [] - - -func get_class_name() -> Array[StringName]: - var classes := super() - classes.push_back(&"Leaf") - return classes diff --git a/addons/beehave/nodes/leaves/leaf.gd.uid b/addons/beehave/nodes/leaves/leaf.gd.uid deleted file mode 100644 index 1a3865a..0000000 --- a/addons/beehave/nodes/leaves/leaf.gd.uid +++ /dev/null @@ -1 +0,0 @@ -uid://bohblcbgejfx2 diff --git a/addons/beehave/plugin.cfg b/addons/beehave/plugin.cfg deleted file mode 100644 index de9e61c..0000000 --- a/addons/beehave/plugin.cfg +++ /dev/null @@ -1,7 +0,0 @@ -[plugin] - -name="Beehave" -description="🐝 Behavior Tree addon for Godot Engine" -author="bitbrain" -version="2.8.3" -script="plugin.gd" diff --git a/addons/beehave/plugin.gd b/addons/beehave/plugin.gd deleted file mode 100644 index cda3b0d..0000000 --- a/addons/beehave/plugin.gd +++ /dev/null @@ -1,26 +0,0 @@ -@tool -extends EditorPlugin - -const BeehaveEditorDebugger := preload("debug/debugger.gd") -var editor_debugger: BeehaveEditorDebugger -var frames: RefCounted - - -func _init(): - name = "BeehavePlugin" - add_autoload_singleton("BeehaveGlobalMetrics", "metrics/beehave_global_metrics.gd") - add_autoload_singleton("BeehaveGlobalDebugger", "debug/global_debugger.gd") - print("Beehave initialized!") - - -func _enter_tree() -> void: - editor_debugger = BeehaveEditorDebugger.new() - if Engine.get_version_info().minor >= 2: - frames = preload("debug/new_frames.gd").new() - else: - frames = preload("debug/old_frames.gd").new() - add_debugger_plugin(editor_debugger) - - -func _exit_tree() -> void: - remove_debugger_plugin(editor_debugger) diff --git a/addons/beehave/plugin.gd.uid b/addons/beehave/plugin.gd.uid deleted file mode 100644 index 302dffc..0000000 --- a/addons/beehave/plugin.gd.uid +++ /dev/null @@ -1 +0,0 @@ -uid://bugoop5v8mqlc diff --git a/addons/beehave/utils/utils.gd b/addons/beehave/utils/utils.gd deleted file mode 100644 index 5f51ce7..0000000 --- a/addons/beehave/utils/utils.gd +++ /dev/null @@ -1,21 +0,0 @@ -@tool - - -static func get_plugin() -> EditorPlugin: - var tree: SceneTree = Engine.get_main_loop() - return tree.get_root().get_child(0).get_node_or_null("BeehavePlugin") - - -static func get_editor_scale() -> float: - var plugin := get_plugin() - if plugin: - return plugin.get_editor_interface().get_editor_scale() - return 1.0 - - -static func get_frames() -> RefCounted: - var plugin := get_plugin() - if plugin: - return plugin.frames - push_error("Can't find Beehave Plugin") - return null diff --git a/addons/beehave/utils/utils.gd.uid b/addons/beehave/utils/utils.gd.uid deleted file mode 100644 index 3c7211e..0000000 --- a/addons/beehave/utils/utils.gd.uid +++ /dev/null @@ -1 +0,0 @@ -uid://dimodpwjdi5l5 diff --git a/addons/editor_menu_tools/editor_menu_tools.gd b/addons/editor_menu_tools/editor_menu_tools.gd index 776fe64..02d7d97 100644 --- a/addons/editor_menu_tools/editor_menu_tools.gd +++ b/addons/editor_menu_tools/editor_menu_tools.gd @@ -34,7 +34,7 @@ func _enter_tree(): add_short_cut("配置-角色", "res://config/character") add_short_cut("配置-武器技能", "res://config/skill_player_weapon") add_short_cut("资产-技能特效", "res://scene/effect/particle") - add_short_cut("资产-AI", "res://scene/ai") + add_short_cut("资产-AI", "res://resource/ai") add_short_cut("资产-场景活动物件", "res://scene/level_active") add_short_cut("编辑场景-关卡", "res://scene/level/level.tscn") add_short_cut("编辑场景-角色", "res://scene/character/character.tscn") diff --git a/addons/limboai/LICENSE.md b/addons/limboai/LICENSE.md new file mode 100644 index 0000000..07c690f --- /dev/null +++ b/addons/limboai/LICENSE.md @@ -0,0 +1,7 @@ +Copyright (c) 2023-2025 Serhii Snitsaruk and the LimboAI contributors. + +Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files (the “Software”), to deal in the Software without restriction, including without limitation the rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, and to permit persons to whom the Software is furnished to do so, subject to the following conditions: + +The above copyright notice and this permission notice shall be included in all copies or substantial portions of the Software. + +THE SOFTWARE IS PROVIDED “AS IS”, WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. diff --git a/addons/limboai/LOGO_LICENSE.md b/addons/limboai/LOGO_LICENSE.md new file mode 100644 index 0000000..cd0de07 --- /dev/null +++ b/addons/limboai/LOGO_LICENSE.md @@ -0,0 +1,5 @@ +LimboAI Logo +Copyright (c) 2023 Aleksandra Snitsaruk + +This work is licensed under the Creative Commons Attribution 4.0 International +license (CC BY 4.0 International): https://creativecommons.org/licenses/by/4.0/ \ No newline at end of file diff --git a/addons/limboai/README.md b/addons/limboai/README.md new file mode 100644 index 0000000..3d4b780 --- /dev/null +++ b/addons/limboai/README.md @@ -0,0 +1,142 @@ +
+
+
+
+
+
+
+
+
+
+## Features
+
+- **Behavior Trees (BT):**
+ - Easily create, edit, and save `BehaviorTree` resources in the editor.
+ - Execute `BehaviorTree` resources using the `BTPlayer` node.
+ - Create complex behaviors by combining and nesting tasks in a hierarchy.
+ - Control execution flow using composite, decorator, and condition tasks.
+ - [Create custom tasks](https://limboai.readthedocs.io/en/stable/behavior-trees/custom-tasks.html) by extending core classes: `BTAction`, `BTCondition`, `BTDecorator`, and `BTComposite`.
+ - Built-in class documentation.
+ - Blackboard system: Share data seamlessly between tasks using the `Blackboard`.
+ - Blackboard plans: Define variables in the BehaviorTree resource and override their values in the BTPlayer node.
+ - Plan editor: Manage variables, their data types and property hints.
+ - Blackboard scopes: Prevent name conflicts and enable advanced techniques like [sharing data between several agents](https://limboai.readthedocs.io/en/stable/behavior-trees/using-blackboard.html#sharing-data-between-several-agents).
+ - Blackboard parameters: [Export a BB parameter](https://limboai.readthedocs.io/en/stable/behavior-trees/using-blackboard.html#task-parameters), for which user can provide a value or bind it to a blackboard variable (can be used in custom tasks).
+ - Inspector support for specifying blackboard variables (custom editor for exported `StringName` properties ending with "_var").
+ - Use the `BTSubtree` task to execute a tree from a different resource file, promoting organization and reusability.
+ - Visual Debugger: Inspect the execution of any BT in a running scene to identify and troubleshoot issues.
+ - Visualize BT in-game using `BehaviorTreeView` node (for custom in-game tools).
+ - Monitor tree performance with custom performance monitors.
+
+- **Hierarchical State Machines (HSM):**
+ - Extend the `LimboState` class to implement state logic.
+ - `LimboHSM` node serves as a state machine that manages `LimboState` instances and transitions.
+ - `LimboHSM` is a state itself and can be nested within other `LimboHSM` instances.
+ - [Event-based](https://limboai.readthedocs.io/en/stable/hierarchical-state-machines/create-hsm.html#events-and-transitions): Transitions are associated with events and are triggered by the state machine when the relevant event is dispatched, allowing for better decoupling of transitions from state logic.
+ - Combine state machines with behavior trees using `BTState` for advanced reactive AI.
+ - Delegation Option: Using the vanilla `LimboState`, [delegate the implementation](https://limboai.readthedocs.io/en/stable/hierarchical-state-machines/create-hsm.html#single-file-state-machine-setup) to your callback functions, making it perfect for rapid prototyping and game jams.
+ - 🛈 Note: State machine setup and initialization require code; there is no GUI editor.
+
+- **Tested:** Behavior tree tasks and HSM are covered by unit tests.
+
+- **GDExtension:** LimboAI can be [used as extension](https://limboai.readthedocs.io/en/stable/getting-started/getting-limboai.html#get-gdextension-version). Custom engine builds are not necessary.
+
+- **Demo + Tutorial:** Check out our extensive demo project, which includes an introduction to behavior trees using examples.
+
+## First steps
+
+Follow the [Getting started](https://limboai.readthedocs.io/en/stable/getting-started/getting-limboai.html) guide to learn how to get started with LimboAI and the demo project.
+
+## Getting LimboAI
+
+LimboAI can be used as either a C++ module or as a GDExtension shared library. GDExtension version is more convenient to use but somewhat limited in features. Whichever you choose to use, your project will stay compatible with both and you can switch from one to the other any time. See [Using GDExtension](https://limboai.readthedocs.io/en/stable/getting-started/getting-limboai.html#get-gdextension-version).
+
+### Precompiled builds
+
+- For the most recent builds, navigate to **Actions** → [**All Builds**](https://github.com/limbonaut/limboai/actions/workflows/all_builds.yml), select a build from the list, and scroll down until you find the **Artifacts** section.
+- For release builds, check [**Releases**](https://github.com/limbonaut/limboai/releases).
+
+### Compiling from source
+
+- Download the Godot Engine source code and put this module source into the `modules/limboai` directory.
+- Consult the Godot Engine documentation for instructions on [how to build from source code](https://docs.godotengine.org/en/stable/contributing/development/compiling/index.html).
+- If you plan to export a game utilizing the LimboAI module, you'll also need to build export templates.
+- To execute unit tests, compile the engine with `tests=yes` and run it with `--test --tc="*[LimboAI]*"`.
+
+#### For GDExtension
+
+- You'll need SCons build tool and a C++ compiler. See also [Compiling](https://docs.godotengine.org/en/stable/contributing/development/compiling/index.html).
+- Run `scons target=editor` to build the plugin library for your current platform.
+ - SCons will automatically clone the godot-cpp/ repository if it doesn't already exist in the `limboai/godot-cpp` directory.
+ - By default, built targets are placed in the demo project: `demo/addons/limboai/bin/`
+- Check `scons -h` for other options and targets.
+
+## Using the plugin
+
+- Online Documentation: [stable](https://limboai.readthedocs.io/en/stable/index.html), [latest](https://limboai.readthedocs.io/en/latest/index.html)
+- [Getting started](https://limboai.readthedocs.io/en/stable/getting-started/getting-limboai.html)
+- [Introduction to Behavior Trees](https://limboai.readthedocs.io/en/stable/behavior-trees/introduction.html)
+- [Creating custom tasks in GDScript](https://limboai.readthedocs.io/en/stable/behavior-trees/custom-tasks.html)
+- [Sharing data using Blackboard](https://limboai.readthedocs.io/en/stable/behavior-trees/using-blackboard.html)
+- [Accessing nodes in the scene tree](https://limboai.readthedocs.io/en/stable/behavior-trees/accessing-nodes.html)
+- [State machines](https://limboai.readthedocs.io/en/stable/hierarchical-state-machines/create-hsm.html)
+- [Using GDExtension](https://limboai.readthedocs.io/en/stable/getting-started/getting-limboai.html#get-gdextension-version)
+- [Using LimboAI with C#](https://limboai.readthedocs.io/en/stable/getting-started/c-sharp.html)
+- [Class reference](https://limboai.readthedocs.io/en/stable/classes/featured-classes.html)
+
+## Contributing
+
+Contributions are welcome! Please open issues for bug reports, feature requests, or code changes.
+For detailed guidelines on contributing to code or documentation, check out our [Contributing](https://limboai.readthedocs.io/en/latest/getting-started/contributing.html) page.
+
+If you have an idea for a behavior tree task or a feature that could be useful in a variety of projects, open an issue to discuss it.
+
+## Social
+
+Need help? We have a Discord server: https://discord.gg/N5MGC95GpP
+
+I write about LimboAI development on Mastodon: https://mastodon.gamedev.place/@limbo.
+
+## License
+
+Use of this source code is governed by an MIT-style license that can be found in the LICENSE file or at https://opensource.org/licenses/MIT
+
+LimboAI logo and demo project art assets are licensed under the Creative Commons Attribution 4.0 International license that can be found at https://creativecommons.org/licenses/by/4.0/
diff --git a/addons/limboai/bin/libliblimboai.windows.editor.x86_64.a b/addons/limboai/bin/libliblimboai.windows.editor.x86_64.a
new file mode 100644
index 0000000..186397b
Binary files /dev/null and b/addons/limboai/bin/libliblimboai.windows.editor.x86_64.a differ
diff --git a/addons/limboai/bin/libliblimboai.windows.template_release.x86_64.a b/addons/limboai/bin/libliblimboai.windows.template_release.x86_64.a
new file mode 100644
index 0000000..73dfc65
Binary files /dev/null and b/addons/limboai/bin/libliblimboai.windows.template_release.x86_64.a differ
diff --git a/addons/limboai/bin/liblimboai.android.editor.arm32.so b/addons/limboai/bin/liblimboai.android.editor.arm32.so
new file mode 100644
index 0000000..633d460
Binary files /dev/null and b/addons/limboai/bin/liblimboai.android.editor.arm32.so differ
diff --git a/addons/limboai/bin/liblimboai.android.editor.arm64.so b/addons/limboai/bin/liblimboai.android.editor.arm64.so
new file mode 100644
index 0000000..d0c3932
Binary files /dev/null and b/addons/limboai/bin/liblimboai.android.editor.arm64.so differ
diff --git a/addons/limboai/bin/liblimboai.android.editor.x86_32.so b/addons/limboai/bin/liblimboai.android.editor.x86_32.so
new file mode 100644
index 0000000..c66d3ed
Binary files /dev/null and b/addons/limboai/bin/liblimboai.android.editor.x86_32.so differ
diff --git a/addons/limboai/bin/liblimboai.android.editor.x86_64.so b/addons/limboai/bin/liblimboai.android.editor.x86_64.so
new file mode 100644
index 0000000..d94c8d4
Binary files /dev/null and b/addons/limboai/bin/liblimboai.android.editor.x86_64.so differ
diff --git a/addons/limboai/bin/liblimboai.android.template_release.arm32.so b/addons/limboai/bin/liblimboai.android.template_release.arm32.so
new file mode 100644
index 0000000..caafd9f
Binary files /dev/null and b/addons/limboai/bin/liblimboai.android.template_release.arm32.so differ
diff --git a/addons/limboai/bin/liblimboai.android.template_release.arm64.so b/addons/limboai/bin/liblimboai.android.template_release.arm64.so
new file mode 100644
index 0000000..aa3fa41
Binary files /dev/null and b/addons/limboai/bin/liblimboai.android.template_release.arm64.so differ
diff --git a/addons/limboai/bin/liblimboai.android.template_release.x86_32.so b/addons/limboai/bin/liblimboai.android.template_release.x86_32.so
new file mode 100644
index 0000000..b1f4be0
Binary files /dev/null and b/addons/limboai/bin/liblimboai.android.template_release.x86_32.so differ
diff --git a/addons/limboai/bin/liblimboai.android.template_release.x86_64.so b/addons/limboai/bin/liblimboai.android.template_release.x86_64.so
new file mode 100644
index 0000000..c7e662f
Binary files /dev/null and b/addons/limboai/bin/liblimboai.android.template_release.x86_64.so differ
diff --git a/addons/limboai/bin/liblimboai.ios.editor.arm64.dylib b/addons/limboai/bin/liblimboai.ios.editor.arm64.dylib
new file mode 100644
index 0000000..225b769
Binary files /dev/null and b/addons/limboai/bin/liblimboai.ios.editor.arm64.dylib differ
diff --git a/addons/limboai/bin/liblimboai.ios.editor.universal.simulator.dylib b/addons/limboai/bin/liblimboai.ios.editor.universal.simulator.dylib
new file mode 100644
index 0000000..d635390
Binary files /dev/null and b/addons/limboai/bin/liblimboai.ios.editor.universal.simulator.dylib differ
diff --git a/addons/limboai/bin/liblimboai.ios.template_release.arm64.dylib b/addons/limboai/bin/liblimboai.ios.template_release.arm64.dylib
new file mode 100644
index 0000000..22fa530
Binary files /dev/null and b/addons/limboai/bin/liblimboai.ios.template_release.arm64.dylib differ
diff --git a/addons/limboai/bin/liblimboai.ios.template_release.universal.simulator.dylib b/addons/limboai/bin/liblimboai.ios.template_release.universal.simulator.dylib
new file mode 100644
index 0000000..cd12262
Binary files /dev/null and b/addons/limboai/bin/liblimboai.ios.template_release.universal.simulator.dylib differ
diff --git a/addons/limboai/bin/liblimboai.linux.editor.x86_64.so b/addons/limboai/bin/liblimboai.linux.editor.x86_64.so
new file mode 100644
index 0000000..56d7360
Binary files /dev/null and b/addons/limboai/bin/liblimboai.linux.editor.x86_64.so differ
diff --git a/addons/limboai/bin/liblimboai.linux.template_release.x86_64.so b/addons/limboai/bin/liblimboai.linux.template_release.x86_64.so
new file mode 100644
index 0000000..292e1c5
Binary files /dev/null and b/addons/limboai/bin/liblimboai.linux.template_release.x86_64.so differ
diff --git a/addons/limboai/bin/liblimboai.macos.editor.framework/liblimboai.macos.editor b/addons/limboai/bin/liblimboai.macos.editor.framework/liblimboai.macos.editor
new file mode 100644
index 0000000..f9167c7
Binary files /dev/null and b/addons/limboai/bin/liblimboai.macos.editor.framework/liblimboai.macos.editor differ
diff --git a/addons/limboai/bin/liblimboai.macos.template_release.framework/liblimboai.macos.template_release b/addons/limboai/bin/liblimboai.macos.template_release.framework/liblimboai.macos.template_release
new file mode 100644
index 0000000..5cecf1d
Binary files /dev/null and b/addons/limboai/bin/liblimboai.macos.template_release.framework/liblimboai.macos.template_release differ
diff --git a/addons/limboai/bin/liblimboai.web.editor.wasm32.wasm b/addons/limboai/bin/liblimboai.web.editor.wasm32.wasm
new file mode 100644
index 0000000..9057ab4
Binary files /dev/null and b/addons/limboai/bin/liblimboai.web.editor.wasm32.wasm differ
diff --git a/addons/limboai/bin/liblimboai.web.template_release.wasm32.wasm b/addons/limboai/bin/liblimboai.web.template_release.wasm32.wasm
new file mode 100644
index 0000000..5367ab3
Binary files /dev/null and b/addons/limboai/bin/liblimboai.web.template_release.wasm32.wasm differ
diff --git a/addons/limboai/bin/liblimboai.windows.editor.x86_64.dll b/addons/limboai/bin/liblimboai.windows.editor.x86_64.dll
new file mode 100644
index 0000000..bf215ed
Binary files /dev/null and b/addons/limboai/bin/liblimboai.windows.editor.x86_64.dll differ
diff --git a/addons/limboai/bin/liblimboai.windows.template_release.x86_64.dll b/addons/limboai/bin/liblimboai.windows.template_release.x86_64.dll
new file mode 100644
index 0000000..056f757
Binary files /dev/null and b/addons/limboai/bin/liblimboai.windows.template_release.x86_64.dll differ
diff --git a/addons/limboai/bin/limboai.gdextension b/addons/limboai/bin/limboai.gdextension
new file mode 100644
index 0000000..a404920
--- /dev/null
+++ b/addons/limboai/bin/limboai.gdextension
@@ -0,0 +1,100 @@
+[configuration]
+
+entry_symbol = "limboai_init"
+compatibility_minimum = "4.2"
+
+[libraries]
+
+macos.debug = "res://addons/limboai/bin/liblimboai.macos.editor.framework"
+macos.release = "res://addons/limboai/bin/liblimboai.macos.template_release.framework"
+windows.debug.x86_32 = "res://addons/limboai/bin/liblimboai.windows.editor.x86_32.dll"
+windows.release.x86_32 = "res://addons/limboai/bin/liblimboai.windows.template_release.x86_32.dll"
+windows.debug.x86_64 = "res://addons/limboai/bin/liblimboai.windows.editor.x86_64.dll"
+windows.release.x86_64 = "res://addons/limboai/bin/liblimboai.windows.template_release.x86_64.dll"
+linux.debug.x86_64 = "res://addons/limboai/bin/liblimboai.linux.editor.x86_64.so"
+linux.release.x86_64 = "res://addons/limboai/bin/liblimboai.linux.template_release.x86_64.so"
+linux.debug.arm64 = "res://addons/limboai/bin/liblimboai.linux.editor.arm64.so"
+linux.release.arm64 = "res://addons/limboai/bin/liblimboai.linux.template_release.arm64.so"
+linux.debug.rv64 = "res://addons/limboai/bin/liblimboai.linux.editor.rv64.so"
+linux.release.rv64 = "res://addons/limboai/bin/liblimboai.linux.template_release.rv64.so"
+android.debug.arm64 = "res://addons/limboai/bin/liblimboai.android.editor.arm64.so"
+android.release.arm64 = "res://addons/limboai/bin/liblimboai.android.template_release.arm64.so"
+android.debug.arm32 = "res://addons/limboai/bin/liblimboai.android.editor.arm32.so"
+android.release.arm32 = "res://addons/limboai/bin/liblimboai.android.template_release.arm32.so"
+android.debug.x86_64 = "res://addons/limboai/bin/liblimboai.android.editor.x86_64.so"
+android.release.x86_64 = "res://addons/limboai/bin/liblimboai.android.template_release.x86_64.so"
+android.debug.x86_32 = "res://addons/limboai/bin/liblimboai.android.editor.x86_32.so"
+android.release.x86_32 = "res://addons/limboai/bin/liblimboai.android.template_release.x86_32.so"
+ios.debug.arm64 = "res://addons/limboai/bin/liblimboai.ios.editor.arm64.dylib"
+ios.release.arm64 = "res://addons/limboai/bin/liblimboai.ios.template_release.arm64.dylib"
+ios.debug.simulator = "res://addons/limboai/bin/liblimboai.ios.editor.universal.dylib"
+ios.release.simulator = "res://addons/limboai/bin/liblimboai.ios.template_release.universal.dylib"
+web.debug.wasm32 = "res://addons/limboai/bin/liblimboai.web.editor.wasm32.wasm"
+web.release.wasm32 = "res://addons/limboai/bin/liblimboai.web.template_release.wasm32.wasm"
+
+[icons]
+
+BTAction = "res://addons/limboai/icons/BTAction.svg"
+BTAlwaysFail = "res://addons/limboai/icons/BTAlwaysFail.svg"
+BTAlwaysSucceed = "res://addons/limboai/icons/BTAlwaysSucceed.svg"
+BTAwaitAnimation = "res://addons/limboai/icons/BTAwaitAnimation.svg"
+BTCallMethod = "res://addons/limboai/icons/BTCallMethod.svg"
+BTCheckAgentProperty = "res://addons/limboai/icons/BTCheckAgentProperty.svg"
+BTCheckTrigger = "res://addons/limboai/icons/BTCheckTrigger.svg"
+BTCheckVar = "res://addons/limboai/icons/BTCheckVar.svg"
+BTComment = "res://addons/limboai/icons/BTComment.svg"
+BTCondition = "res://addons/limboai/icons/BTCondition.svg"
+BTConsolePrint = "res://addons/limboai/icons/BTConsolePrint.svg"
+BTCooldown = "res://addons/limboai/icons/BTCooldown.svg"
+BTDecorator = "res://addons/limboai/icons/BTDecorator.svg"
+BTDelay = "res://addons/limboai/icons/BTDelay.svg"
+BTDynamicSelector = "res://addons/limboai/icons/BTDynamicSelector.svg"
+BTDynamicSequence = "res://addons/limboai/icons/BTDynamicSequence.svg"
+BTEvaluateExpression = "res://addons/limboai/icons/BTEvaluateExpression.svg"
+BTFail = "res://addons/limboai/icons/BTFail.svg"
+BTForEach = "res://addons/limboai/icons/BTForEach.svg"
+BTInvert = "res://addons/limboai/icons/BTInvert.svg"
+BTNewScope = "res://addons/limboai/icons/BTNewScope.svg"
+BTParallel = "res://addons/limboai/icons/BTParallel.svg"
+BTPauseAnimation = "res://addons/limboai/icons/BTPauseAnimation.svg"
+BTPlayAnimation = "res://addons/limboai/icons/BTPlayAnimation.svg"
+BTPlayer = "res://addons/limboai/icons/BTPlayer.svg"
+BTProbability = "res://addons/limboai/icons/BTProbability.svg"
+BTProbabilitySelector = "res://addons/limboai/icons/BTProbabilitySelector.svg"
+BTRandomSelector = "res://addons/limboai/icons/BTRandomSelector.svg"
+BTRandomSequence = "res://addons/limboai/icons/BTRandomSequence.svg"
+BTRandomWait = "res://addons/limboai/icons/BTRandomWait.svg"
+BTRepeat = "res://addons/limboai/icons/BTRepeat.svg"
+BTRepeatUntilFailure = "res://addons/limboai/icons/BTRepeatUntilFailure.svg"
+BTRepeatUntilSuccess = "res://addons/limboai/icons/BTRepeatUntilSuccess.svg"
+BTRunLimit = "res://addons/limboai/icons/BTRunLimit.svg"
+BTSelector = "res://addons/limboai/icons/BTSelector.svg"
+BTSequence = "res://addons/limboai/icons/BTSequence.svg"
+BTSetAgentProperty = "res://addons/limboai/icons/BTSetAgentProperty.svg"
+BTSetVar = "res://addons/limboai/icons/BTSetVar.svg"
+BTState = "res://addons/limboai/icons/BTState.svg"
+BTStopAnimation = "res://addons/limboai/icons/BTStopAnimation.svg"
+BTSubtree = "res://addons/limboai/icons/BTSubtree.svg"
+BTTimeLimit = "res://addons/limboai/icons/BTTimeLimit.svg"
+BTWait = "res://addons/limboai/icons/BTWait.svg"
+BTWaitTicks = "res://addons/limboai/icons/BTWaitTicks.svg"
+BehaviorTree = "res://addons/limboai/icons/BehaviorTree.svg"
+BehaviorTreeView = "res://addons/limboai/icons/BehaviorTreeView.svg"
+BlackboardPlan = "res://addons/limboai/icons/BlackboardPlan.svg"
+LimboAI = "res://addons/limboai/icons/LimboAI.svg"
+LimboDeselectAll = "res://addons/limboai/icons/LimboDeselectAll.svg"
+LimboEditBlackboard = "res://addons/limboai/icons/LimboEditBlackboard.svg"
+LimboExtraBlackboard = "res://addons/limboai/icons/LimboExtraBlackboard.svg"
+LimboExtraClock = "res://addons/limboai/icons/LimboExtraClock.svg"
+LimboExtraVariable = "res://addons/limboai/icons/LimboExtraVariable.svg"
+LimboExtractSubtree = "res://addons/limboai/icons/LimboExtractSubtree.svg"
+LimboHSM = "res://addons/limboai/icons/LimboHSM.svg"
+LimboPercent = "res://addons/limboai/icons/LimboPercent.svg"
+LimboSelectAll = "res://addons/limboai/icons/LimboSelectAll.svg"
+LimboState = "res://addons/limboai/icons/LimboState.svg"
+LimboVarAdd = "res://addons/limboai/icons/LimboVarAdd.svg"
+LimboVarEmpty = "res://addons/limboai/icons/LimboVarEmpty.svg"
+LimboVarError = "res://addons/limboai/icons/LimboVarError.svg"
+LimboVarExists = "res://addons/limboai/icons/LimboVarExists.svg"
+LimboVarNotFound = "res://addons/limboai/icons/LimboVarNotFound.svg"
+LimboVarPrivate = "res://addons/limboai/icons/LimboVarPrivate.svg"
diff --git a/addons/limboai/bin/limboai.gdextension.uid b/addons/limboai/bin/limboai.gdextension.uid
new file mode 100644
index 0000000..a5f89c1
--- /dev/null
+++ b/addons/limboai/bin/limboai.gdextension.uid
@@ -0,0 +1 @@
+uid://b1or4b7qgxvb8
diff --git a/addons/limboai/bin/~liblimboai.windows.editor.x86_64.dll b/addons/limboai/bin/~liblimboai.windows.editor.x86_64.dll
new file mode 100644
index 0000000..bf215ed
Binary files /dev/null and b/addons/limboai/bin/~liblimboai.windows.editor.x86_64.dll differ
diff --git a/addons/limboai/icons/BTAction.svg b/addons/limboai/icons/BTAction.svg
new file mode 100644
index 0000000..997ebbc
--- /dev/null
+++ b/addons/limboai/icons/BTAction.svg
@@ -0,0 +1 @@
+
\ No newline at end of file
diff --git a/addons/limboai/icons/BTAction.svg.import b/addons/limboai/icons/BTAction.svg.import
new file mode 100644
index 0000000..52c0ee2
--- /dev/null
+++ b/addons/limboai/icons/BTAction.svg.import
@@ -0,0 +1,38 @@
+[remap]
+
+importer="texture"
+type="CompressedTexture2D"
+uid="uid://h3stvyon3xvv"
+path="res://.godot/imported/BTAction.svg-a43c04a25802778fc1e8d98b5915e67c.ctex"
+metadata={
+"has_editor_variant": true,
+"vram_texture": false
+}
+
+[deps]
+
+source_file="res://addons/limboai/icons/BTAction.svg"
+dest_files=["res://.godot/imported/BTAction.svg-a43c04a25802778fc1e8d98b5915e67c.ctex"]
+
+[params]
+
+compress/mode=0
+compress/high_quality=false
+compress/lossy_quality=0.7
+compress/hdr_compression=1
+compress/normal_map=0
+compress/channel_pack=0
+mipmaps/generate=false
+mipmaps/limit=-1
+roughness/mode=0
+roughness/src_normal=""
+process/fix_alpha_border=true
+process/premult_alpha=false
+process/normal_map_invert_y=false
+process/hdr_as_srgb=false
+process/hdr_clamp_exposure=false
+process/size_limit=0
+detect_3d/compress_to=1
+svg/scale=1.0
+editor/scale_with_editor_scale=true
+editor/convert_colors_with_editor_theme=true
diff --git a/addons/limboai/icons/BTAlwaysFail.svg b/addons/limboai/icons/BTAlwaysFail.svg
new file mode 100644
index 0000000..7be2920
--- /dev/null
+++ b/addons/limboai/icons/BTAlwaysFail.svg
@@ -0,0 +1 @@
+
\ No newline at end of file
diff --git a/addons/beehave/debug/icons/port_right.svg.import b/addons/limboai/icons/BTAlwaysFail.svg.import
similarity index 71%
rename from addons/beehave/debug/icons/port_right.svg.import
rename to addons/limboai/icons/BTAlwaysFail.svg.import
index 20931cd..b210606 100644
--- a/addons/beehave/debug/icons/port_right.svg.import
+++ b/addons/limboai/icons/BTAlwaysFail.svg.import
@@ -2,8 +2,8 @@
importer="texture"
type="CompressedTexture2D"
-uid="uid://bbmd6vk23ympm"
-path="res://.godot/imported/port_right.svg-f760bd8be2dd613d0d3848c998c92a2a.ctex"
+uid="uid://d1cflmxdwb1le"
+path="res://.godot/imported/BTAlwaysFail.svg-9a4e083bd8ff0d6d8240b50ae0d4cea0.ctex"
metadata={
"has_editor_variant": true,
"vram_texture": false
@@ -11,8 +11,8 @@ metadata={
[deps]
-source_file="res://addons/beehave/debug/icons/port_right.svg"
-dest_files=["res://.godot/imported/port_right.svg-f760bd8be2dd613d0d3848c998c92a2a.ctex"]
+source_file="res://addons/limboai/icons/BTAlwaysFail.svg"
+dest_files=["res://.godot/imported/BTAlwaysFail.svg-9a4e083bd8ff0d6d8240b50ae0d4cea0.ctex"]
[params]
diff --git a/addons/limboai/icons/BTAlwaysSucceed.svg b/addons/limboai/icons/BTAlwaysSucceed.svg
new file mode 100644
index 0000000..248882f
--- /dev/null
+++ b/addons/limboai/icons/BTAlwaysSucceed.svg
@@ -0,0 +1 @@
+
\ No newline at end of file
diff --git a/addons/limboai/icons/BTAlwaysSucceed.svg.import b/addons/limboai/icons/BTAlwaysSucceed.svg.import
new file mode 100644
index 0000000..01e14ca
--- /dev/null
+++ b/addons/limboai/icons/BTAlwaysSucceed.svg.import
@@ -0,0 +1,38 @@
+[remap]
+
+importer="texture"
+type="CompressedTexture2D"
+uid="uid://ceddxqv0lrlwt"
+path="res://.godot/imported/BTAlwaysSucceed.svg-c8181e2fd85d1e2ad00a6c8e813e7a94.ctex"
+metadata={
+"has_editor_variant": true,
+"vram_texture": false
+}
+
+[deps]
+
+source_file="res://addons/limboai/icons/BTAlwaysSucceed.svg"
+dest_files=["res://.godot/imported/BTAlwaysSucceed.svg-c8181e2fd85d1e2ad00a6c8e813e7a94.ctex"]
+
+[params]
+
+compress/mode=0
+compress/high_quality=false
+compress/lossy_quality=0.7
+compress/hdr_compression=1
+compress/normal_map=0
+compress/channel_pack=0
+mipmaps/generate=false
+mipmaps/limit=-1
+roughness/mode=0
+roughness/src_normal=""
+process/fix_alpha_border=true
+process/premult_alpha=false
+process/normal_map_invert_y=false
+process/hdr_as_srgb=false
+process/hdr_clamp_exposure=false
+process/size_limit=0
+detect_3d/compress_to=1
+svg/scale=1.0
+editor/scale_with_editor_scale=true
+editor/convert_colors_with_editor_theme=true
diff --git a/addons/limboai/icons/BTAwaitAnimation.svg b/addons/limboai/icons/BTAwaitAnimation.svg
new file mode 100644
index 0000000..6bb4cd1
--- /dev/null
+++ b/addons/limboai/icons/BTAwaitAnimation.svg
@@ -0,0 +1 @@
+
\ No newline at end of file
diff --git a/addons/limboai/icons/BTAwaitAnimation.svg.import b/addons/limboai/icons/BTAwaitAnimation.svg.import
new file mode 100644
index 0000000..19844ff
--- /dev/null
+++ b/addons/limboai/icons/BTAwaitAnimation.svg.import
@@ -0,0 +1,38 @@
+[remap]
+
+importer="texture"
+type="CompressedTexture2D"
+uid="uid://b4p7ipif4m6m7"
+path="res://.godot/imported/BTAwaitAnimation.svg-d8d736b3e349e2f77119fde575996909.ctex"
+metadata={
+"has_editor_variant": true,
+"vram_texture": false
+}
+
+[deps]
+
+source_file="res://addons/limboai/icons/BTAwaitAnimation.svg"
+dest_files=["res://.godot/imported/BTAwaitAnimation.svg-d8d736b3e349e2f77119fde575996909.ctex"]
+
+[params]
+
+compress/mode=0
+compress/high_quality=false
+compress/lossy_quality=0.7
+compress/hdr_compression=1
+compress/normal_map=0
+compress/channel_pack=0
+mipmaps/generate=false
+mipmaps/limit=-1
+roughness/mode=0
+roughness/src_normal=""
+process/fix_alpha_border=true
+process/premult_alpha=false
+process/normal_map_invert_y=false
+process/hdr_as_srgb=false
+process/hdr_clamp_exposure=false
+process/size_limit=0
+detect_3d/compress_to=1
+svg/scale=1.0
+editor/scale_with_editor_scale=true
+editor/convert_colors_with_editor_theme=true
diff --git a/addons/limboai/icons/BTCallMethod.svg b/addons/limboai/icons/BTCallMethod.svg
new file mode 100644
index 0000000..8ed7e65
--- /dev/null
+++ b/addons/limboai/icons/BTCallMethod.svg
@@ -0,0 +1 @@
+
\ No newline at end of file
diff --git a/addons/limboai/icons/BTCallMethod.svg.import b/addons/limboai/icons/BTCallMethod.svg.import
new file mode 100644
index 0000000..30e78e0
--- /dev/null
+++ b/addons/limboai/icons/BTCallMethod.svg.import
@@ -0,0 +1,38 @@
+[remap]
+
+importer="texture"
+type="CompressedTexture2D"
+uid="uid://cn3g5agpw75hr"
+path="res://.godot/imported/BTCallMethod.svg-f41bac2a2119be3591af9424d2c32d9a.ctex"
+metadata={
+"has_editor_variant": true,
+"vram_texture": false
+}
+
+[deps]
+
+source_file="res://addons/limboai/icons/BTCallMethod.svg"
+dest_files=["res://.godot/imported/BTCallMethod.svg-f41bac2a2119be3591af9424d2c32d9a.ctex"]
+
+[params]
+
+compress/mode=0
+compress/high_quality=false
+compress/lossy_quality=0.7
+compress/hdr_compression=1
+compress/normal_map=0
+compress/channel_pack=0
+mipmaps/generate=false
+mipmaps/limit=-1
+roughness/mode=0
+roughness/src_normal=""
+process/fix_alpha_border=true
+process/premult_alpha=false
+process/normal_map_invert_y=false
+process/hdr_as_srgb=false
+process/hdr_clamp_exposure=false
+process/size_limit=0
+detect_3d/compress_to=1
+svg/scale=1.0
+editor/scale_with_editor_scale=true
+editor/convert_colors_with_editor_theme=true
diff --git a/addons/limboai/icons/BTCheckAgentProperty.svg b/addons/limboai/icons/BTCheckAgentProperty.svg
new file mode 100644
index 0000000..6c869c3
--- /dev/null
+++ b/addons/limboai/icons/BTCheckAgentProperty.svg
@@ -0,0 +1 @@
+
\ No newline at end of file
diff --git a/addons/limboai/icons/BTCheckAgentProperty.svg.import b/addons/limboai/icons/BTCheckAgentProperty.svg.import
new file mode 100644
index 0000000..b4aa47a
--- /dev/null
+++ b/addons/limboai/icons/BTCheckAgentProperty.svg.import
@@ -0,0 +1,38 @@
+[remap]
+
+importer="texture"
+type="CompressedTexture2D"
+uid="uid://7yewlkustml7"
+path="res://.godot/imported/BTCheckAgentProperty.svg-2ed4c1d109d23a5287ed6f1262e23f15.ctex"
+metadata={
+"has_editor_variant": true,
+"vram_texture": false
+}
+
+[deps]
+
+source_file="res://addons/limboai/icons/BTCheckAgentProperty.svg"
+dest_files=["res://.godot/imported/BTCheckAgentProperty.svg-2ed4c1d109d23a5287ed6f1262e23f15.ctex"]
+
+[params]
+
+compress/mode=0
+compress/high_quality=false
+compress/lossy_quality=0.7
+compress/hdr_compression=1
+compress/normal_map=0
+compress/channel_pack=0
+mipmaps/generate=false
+mipmaps/limit=-1
+roughness/mode=0
+roughness/src_normal=""
+process/fix_alpha_border=true
+process/premult_alpha=false
+process/normal_map_invert_y=false
+process/hdr_as_srgb=false
+process/hdr_clamp_exposure=false
+process/size_limit=0
+detect_3d/compress_to=1
+svg/scale=1.0
+editor/scale_with_editor_scale=true
+editor/convert_colors_with_editor_theme=true
diff --git a/addons/limboai/icons/BTCheckTrigger.svg b/addons/limboai/icons/BTCheckTrigger.svg
new file mode 100644
index 0000000..2a59673
--- /dev/null
+++ b/addons/limboai/icons/BTCheckTrigger.svg
@@ -0,0 +1 @@
+
\ No newline at end of file
diff --git a/addons/limboai/icons/BTCheckTrigger.svg.import b/addons/limboai/icons/BTCheckTrigger.svg.import
new file mode 100644
index 0000000..bbd3011
--- /dev/null
+++ b/addons/limboai/icons/BTCheckTrigger.svg.import
@@ -0,0 +1,38 @@
+[remap]
+
+importer="texture"
+type="CompressedTexture2D"
+uid="uid://f843rlt8n1bn"
+path="res://.godot/imported/BTCheckTrigger.svg-79349468c66ee41b0a126720f8ecda55.ctex"
+metadata={
+"has_editor_variant": true,
+"vram_texture": false
+}
+
+[deps]
+
+source_file="res://addons/limboai/icons/BTCheckTrigger.svg"
+dest_files=["res://.godot/imported/BTCheckTrigger.svg-79349468c66ee41b0a126720f8ecda55.ctex"]
+
+[params]
+
+compress/mode=0
+compress/high_quality=false
+compress/lossy_quality=0.7
+compress/hdr_compression=1
+compress/normal_map=0
+compress/channel_pack=0
+mipmaps/generate=false
+mipmaps/limit=-1
+roughness/mode=0
+roughness/src_normal=""
+process/fix_alpha_border=true
+process/premult_alpha=false
+process/normal_map_invert_y=false
+process/hdr_as_srgb=false
+process/hdr_clamp_exposure=false
+process/size_limit=0
+detect_3d/compress_to=1
+svg/scale=1.0
+editor/scale_with_editor_scale=true
+editor/convert_colors_with_editor_theme=true
diff --git a/addons/limboai/icons/BTCheckVar.svg b/addons/limboai/icons/BTCheckVar.svg
new file mode 100644
index 0000000..150a4f2
--- /dev/null
+++ b/addons/limboai/icons/BTCheckVar.svg
@@ -0,0 +1 @@
+
\ No newline at end of file
diff --git a/addons/beehave/debug/icons/port_top.svg.import b/addons/limboai/icons/BTCheckVar.svg.import
similarity index 72%
rename from addons/beehave/debug/icons/port_top.svg.import
rename to addons/limboai/icons/BTCheckVar.svg.import
index dec7820..18c27ab 100644
--- a/addons/beehave/debug/icons/port_top.svg.import
+++ b/addons/limboai/icons/BTCheckVar.svg.import
@@ -2,8 +2,8 @@
importer="texture"
type="CompressedTexture2D"
-uid="uid://bw8wmxdfom8eh"
-path="res://.godot/imported/port_top.svg-d1b336cdc6a0dd570305782a1e56f61d.ctex"
+uid="uid://b5758dt1d7el4"
+path="res://.godot/imported/BTCheckVar.svg-7b3af543bb4450e9a6d56df48f06064e.ctex"
metadata={
"has_editor_variant": true,
"vram_texture": false
@@ -11,8 +11,8 @@ metadata={
[deps]
-source_file="res://addons/beehave/debug/icons/port_top.svg"
-dest_files=["res://.godot/imported/port_top.svg-d1b336cdc6a0dd570305782a1e56f61d.ctex"]
+source_file="res://addons/limboai/icons/BTCheckVar.svg"
+dest_files=["res://.godot/imported/BTCheckVar.svg-7b3af543bb4450e9a6d56df48f06064e.ctex"]
[params]
diff --git a/addons/limboai/icons/BTComment.svg b/addons/limboai/icons/BTComment.svg
new file mode 100644
index 0000000..66699d4
--- /dev/null
+++ b/addons/limboai/icons/BTComment.svg
@@ -0,0 +1 @@
+
\ No newline at end of file
diff --git a/addons/beehave/icons/condition.svg.import b/addons/limboai/icons/BTComment.svg.import
similarity index 72%
rename from addons/beehave/icons/condition.svg.import
rename to addons/limboai/icons/BTComment.svg.import
index ef59099..5237e03 100644
--- a/addons/beehave/icons/condition.svg.import
+++ b/addons/limboai/icons/BTComment.svg.import
@@ -2,8 +2,8 @@
importer="texture"
type="CompressedTexture2D"
-uid="uid://ck4toqx0nggiu"
-path="res://.godot/imported/condition.svg-57892684b10a64086f68c09c388b17e5.ctex"
+uid="uid://baa2k07y7ftn1"
+path="res://.godot/imported/BTComment.svg-84a811fb1f7563bc02c1f584b4085d5c.ctex"
metadata={
"has_editor_variant": true,
"vram_texture": false
@@ -11,8 +11,8 @@ metadata={
[deps]
-source_file="res://addons/beehave/icons/condition.svg"
-dest_files=["res://.godot/imported/condition.svg-57892684b10a64086f68c09c388b17e5.ctex"]
+source_file="res://addons/limboai/icons/BTComment.svg"
+dest_files=["res://.godot/imported/BTComment.svg-84a811fb1f7563bc02c1f584b4085d5c.ctex"]
[params]
diff --git a/addons/limboai/icons/BTCondition.svg b/addons/limboai/icons/BTCondition.svg
new file mode 100644
index 0000000..7c00015
--- /dev/null
+++ b/addons/limboai/icons/BTCondition.svg
@@ -0,0 +1 @@
+
\ No newline at end of file
diff --git a/addons/beehave/debug/icons/port_left.svg.import b/addons/limboai/icons/BTCondition.svg.import
similarity index 71%
rename from addons/beehave/debug/icons/port_left.svg.import
rename to addons/limboai/icons/BTCondition.svg.import
index 7ea9827..b65eac1 100644
--- a/addons/beehave/debug/icons/port_left.svg.import
+++ b/addons/limboai/icons/BTCondition.svg.import
@@ -2,8 +2,8 @@
importer="texture"
type="CompressedTexture2D"
-uid="uid://bnufc8p6spdtn"
-path="res://.godot/imported/port_left.svg-69cd927c4db555f1edbb8d1f553ea2fd.ctex"
+uid="uid://b0ko5ds5sowl4"
+path="res://.godot/imported/BTCondition.svg-546aa4361ccfe650098b5f6867299d1a.ctex"
metadata={
"has_editor_variant": true,
"vram_texture": false
@@ -11,8 +11,8 @@ metadata={
[deps]
-source_file="res://addons/beehave/debug/icons/port_left.svg"
-dest_files=["res://.godot/imported/port_left.svg-69cd927c4db555f1edbb8d1f553ea2fd.ctex"]
+source_file="res://addons/limboai/icons/BTCondition.svg"
+dest_files=["res://.godot/imported/BTCondition.svg-546aa4361ccfe650098b5f6867299d1a.ctex"]
[params]
diff --git a/addons/limboai/icons/BTConsolePrint.svg b/addons/limboai/icons/BTConsolePrint.svg
new file mode 100644
index 0000000..cee42eb
--- /dev/null
+++ b/addons/limboai/icons/BTConsolePrint.svg
@@ -0,0 +1 @@
+
\ No newline at end of file
diff --git a/addons/limboai/icons/BTConsolePrint.svg.import b/addons/limboai/icons/BTConsolePrint.svg.import
new file mode 100644
index 0000000..35849c5
--- /dev/null
+++ b/addons/limboai/icons/BTConsolePrint.svg.import
@@ -0,0 +1,38 @@
+[remap]
+
+importer="texture"
+type="CompressedTexture2D"
+uid="uid://d0lfqtw5n3kcw"
+path="res://.godot/imported/BTConsolePrint.svg-4190426bb73da16c143878c233af4bc3.ctex"
+metadata={
+"has_editor_variant": true,
+"vram_texture": false
+}
+
+[deps]
+
+source_file="res://addons/limboai/icons/BTConsolePrint.svg"
+dest_files=["res://.godot/imported/BTConsolePrint.svg-4190426bb73da16c143878c233af4bc3.ctex"]
+
+[params]
+
+compress/mode=0
+compress/high_quality=false
+compress/lossy_quality=0.7
+compress/hdr_compression=1
+compress/normal_map=0
+compress/channel_pack=0
+mipmaps/generate=false
+mipmaps/limit=-1
+roughness/mode=0
+roughness/src_normal=""
+process/fix_alpha_border=true
+process/premult_alpha=false
+process/normal_map_invert_y=false
+process/hdr_as_srgb=false
+process/hdr_clamp_exposure=false
+process/size_limit=0
+detect_3d/compress_to=1
+svg/scale=1.0
+editor/scale_with_editor_scale=true
+editor/convert_colors_with_editor_theme=true
diff --git a/addons/limboai/icons/BTCooldown.svg b/addons/limboai/icons/BTCooldown.svg
new file mode 100644
index 0000000..2c6a237
--- /dev/null
+++ b/addons/limboai/icons/BTCooldown.svg
@@ -0,0 +1 @@
+
\ No newline at end of file
diff --git a/addons/limboai/icons/BTCooldown.svg.import b/addons/limboai/icons/BTCooldown.svg.import
new file mode 100644
index 0000000..dd11e32
--- /dev/null
+++ b/addons/limboai/icons/BTCooldown.svg.import
@@ -0,0 +1,38 @@
+[remap]
+
+importer="texture"
+type="CompressedTexture2D"
+uid="uid://cr40h5i7sgvwp"
+path="res://.godot/imported/BTCooldown.svg-b168adee5e8762abc08102408ea327d5.ctex"
+metadata={
+"has_editor_variant": true,
+"vram_texture": false
+}
+
+[deps]
+
+source_file="res://addons/limboai/icons/BTCooldown.svg"
+dest_files=["res://.godot/imported/BTCooldown.svg-b168adee5e8762abc08102408ea327d5.ctex"]
+
+[params]
+
+compress/mode=0
+compress/high_quality=false
+compress/lossy_quality=0.7
+compress/hdr_compression=1
+compress/normal_map=0
+compress/channel_pack=0
+mipmaps/generate=false
+mipmaps/limit=-1
+roughness/mode=0
+roughness/src_normal=""
+process/fix_alpha_border=true
+process/premult_alpha=false
+process/normal_map_invert_y=false
+process/hdr_as_srgb=false
+process/hdr_clamp_exposure=false
+process/size_limit=0
+detect_3d/compress_to=1
+svg/scale=1.0
+editor/scale_with_editor_scale=true
+editor/convert_colors_with_editor_theme=true
diff --git a/addons/limboai/icons/BTDecorator.svg b/addons/limboai/icons/BTDecorator.svg
new file mode 100644
index 0000000..faac1ab
--- /dev/null
+++ b/addons/limboai/icons/BTDecorator.svg
@@ -0,0 +1 @@
+
\ No newline at end of file
diff --git a/addons/beehave/icons/category_bt.svg.import b/addons/limboai/icons/BTDecorator.svg.import
similarity index 71%
rename from addons/beehave/icons/category_bt.svg.import
rename to addons/limboai/icons/BTDecorator.svg.import
index c11e4f2..966ca8e 100644
--- a/addons/beehave/icons/category_bt.svg.import
+++ b/addons/limboai/icons/BTDecorator.svg.import
@@ -2,8 +2,8 @@
importer="texture"
type="CompressedTexture2D"
-uid="uid://qpdd6ue7x82h"
-path="res://.godot/imported/category_bt.svg-8537bebd1c5f62dca3d7ee7f17efeed4.ctex"
+uid="uid://uim24qjhg75y"
+path="res://.godot/imported/BTDecorator.svg-dae9ebd6f4667ba4d2ac62518ef141d6.ctex"
metadata={
"has_editor_variant": true,
"vram_texture": false
@@ -11,8 +11,8 @@ metadata={
[deps]
-source_file="res://addons/beehave/icons/category_bt.svg"
-dest_files=["res://.godot/imported/category_bt.svg-8537bebd1c5f62dca3d7ee7f17efeed4.ctex"]
+source_file="res://addons/limboai/icons/BTDecorator.svg"
+dest_files=["res://.godot/imported/BTDecorator.svg-dae9ebd6f4667ba4d2ac62518ef141d6.ctex"]
[params]
diff --git a/addons/limboai/icons/BTDelay.svg b/addons/limboai/icons/BTDelay.svg
new file mode 100644
index 0000000..2c6a237
--- /dev/null
+++ b/addons/limboai/icons/BTDelay.svg
@@ -0,0 +1 @@
+
\ No newline at end of file
diff --git a/addons/beehave/icons/limiter.svg.import b/addons/limboai/icons/BTDelay.svg.import
similarity index 72%
rename from addons/beehave/icons/limiter.svg.import
rename to addons/limboai/icons/BTDelay.svg.import
index 7b56b08..3eea45c 100644
--- a/addons/beehave/icons/limiter.svg.import
+++ b/addons/limboai/icons/BTDelay.svg.import
@@ -2,8 +2,8 @@
importer="texture"
type="CompressedTexture2D"
-uid="uid://c7akxvsg0f2by"
-path="res://.godot/imported/limiter.svg-b4c7646605c46f53c5e403fe21d8f584.ctex"
+uid="uid://ckkeqgvgrbvlj"
+path="res://.godot/imported/BTDelay.svg-1eb814224ebee27c668e10a73d85b845.ctex"
metadata={
"has_editor_variant": true,
"vram_texture": false
@@ -11,8 +11,8 @@ metadata={
[deps]
-source_file="res://addons/beehave/icons/limiter.svg"
-dest_files=["res://.godot/imported/limiter.svg-b4c7646605c46f53c5e403fe21d8f584.ctex"]
+source_file="res://addons/limboai/icons/BTDelay.svg"
+dest_files=["res://.godot/imported/BTDelay.svg-1eb814224ebee27c668e10a73d85b845.ctex"]
[params]
diff --git a/addons/limboai/icons/BTDynamicSelector.svg b/addons/limboai/icons/BTDynamicSelector.svg
new file mode 100644
index 0000000..b9c8f02
--- /dev/null
+++ b/addons/limboai/icons/BTDynamicSelector.svg
@@ -0,0 +1 @@
+
\ No newline at end of file
diff --git a/addons/limboai/icons/BTDynamicSelector.svg.import b/addons/limboai/icons/BTDynamicSelector.svg.import
new file mode 100644
index 0000000..809a5e3
--- /dev/null
+++ b/addons/limboai/icons/BTDynamicSelector.svg.import
@@ -0,0 +1,38 @@
+[remap]
+
+importer="texture"
+type="CompressedTexture2D"
+uid="uid://bpqj4y5ipbkw1"
+path="res://.godot/imported/BTDynamicSelector.svg-d88a1aa9fb8d8826b74e69dad4c99f54.ctex"
+metadata={
+"has_editor_variant": true,
+"vram_texture": false
+}
+
+[deps]
+
+source_file="res://addons/limboai/icons/BTDynamicSelector.svg"
+dest_files=["res://.godot/imported/BTDynamicSelector.svg-d88a1aa9fb8d8826b74e69dad4c99f54.ctex"]
+
+[params]
+
+compress/mode=0
+compress/high_quality=false
+compress/lossy_quality=0.7
+compress/hdr_compression=1
+compress/normal_map=0
+compress/channel_pack=0
+mipmaps/generate=false
+mipmaps/limit=-1
+roughness/mode=0
+roughness/src_normal=""
+process/fix_alpha_border=true
+process/premult_alpha=false
+process/normal_map_invert_y=false
+process/hdr_as_srgb=false
+process/hdr_clamp_exposure=false
+process/size_limit=0
+detect_3d/compress_to=1
+svg/scale=1.0
+editor/scale_with_editor_scale=true
+editor/convert_colors_with_editor_theme=true
diff --git a/addons/limboai/icons/BTDynamicSequence.svg b/addons/limboai/icons/BTDynamicSequence.svg
new file mode 100644
index 0000000..86c8f54
--- /dev/null
+++ b/addons/limboai/icons/BTDynamicSequence.svg
@@ -0,0 +1 @@
+
\ No newline at end of file
diff --git a/addons/limboai/icons/BTDynamicSequence.svg.import b/addons/limboai/icons/BTDynamicSequence.svg.import
new file mode 100644
index 0000000..9faeeb9
--- /dev/null
+++ b/addons/limboai/icons/BTDynamicSequence.svg.import
@@ -0,0 +1,38 @@
+[remap]
+
+importer="texture"
+type="CompressedTexture2D"
+uid="uid://dmde2ngqsaqur"
+path="res://.godot/imported/BTDynamicSequence.svg-d2b6a83c37a1553bc168a9837ae0cb1d.ctex"
+metadata={
+"has_editor_variant": true,
+"vram_texture": false
+}
+
+[deps]
+
+source_file="res://addons/limboai/icons/BTDynamicSequence.svg"
+dest_files=["res://.godot/imported/BTDynamicSequence.svg-d2b6a83c37a1553bc168a9837ae0cb1d.ctex"]
+
+[params]
+
+compress/mode=0
+compress/high_quality=false
+compress/lossy_quality=0.7
+compress/hdr_compression=1
+compress/normal_map=0
+compress/channel_pack=0
+mipmaps/generate=false
+mipmaps/limit=-1
+roughness/mode=0
+roughness/src_normal=""
+process/fix_alpha_border=true
+process/premult_alpha=false
+process/normal_map_invert_y=false
+process/hdr_as_srgb=false
+process/hdr_clamp_exposure=false
+process/size_limit=0
+detect_3d/compress_to=1
+svg/scale=1.0
+editor/scale_with_editor_scale=true
+editor/convert_colors_with_editor_theme=true
diff --git a/addons/limboai/icons/BTEvaluateExpression.svg b/addons/limboai/icons/BTEvaluateExpression.svg
new file mode 100644
index 0000000..d1cf36f
--- /dev/null
+++ b/addons/limboai/icons/BTEvaluateExpression.svg
@@ -0,0 +1 @@
+
\ No newline at end of file
diff --git a/addons/limboai/icons/BTEvaluateExpression.svg.import b/addons/limboai/icons/BTEvaluateExpression.svg.import
new file mode 100644
index 0000000..64cb31f
--- /dev/null
+++ b/addons/limboai/icons/BTEvaluateExpression.svg.import
@@ -0,0 +1,38 @@
+[remap]
+
+importer="texture"
+type="CompressedTexture2D"
+uid="uid://c4g1m8ihnyliy"
+path="res://.godot/imported/BTEvaluateExpression.svg-d9edc0d3cf9dd54c6a34ffc8a23bf8e3.ctex"
+metadata={
+"has_editor_variant": true,
+"vram_texture": false
+}
+
+[deps]
+
+source_file="res://addons/limboai/icons/BTEvaluateExpression.svg"
+dest_files=["res://.godot/imported/BTEvaluateExpression.svg-d9edc0d3cf9dd54c6a34ffc8a23bf8e3.ctex"]
+
+[params]
+
+compress/mode=0
+compress/high_quality=false
+compress/lossy_quality=0.7
+compress/hdr_compression=1
+compress/normal_map=0
+compress/channel_pack=0
+mipmaps/generate=false
+mipmaps/limit=-1
+roughness/mode=0
+roughness/src_normal=""
+process/fix_alpha_border=true
+process/premult_alpha=false
+process/normal_map_invert_y=false
+process/hdr_as_srgb=false
+process/hdr_clamp_exposure=false
+process/size_limit=0
+detect_3d/compress_to=1
+svg/scale=1.0
+editor/scale_with_editor_scale=true
+editor/convert_colors_with_editor_theme=true
diff --git a/addons/limboai/icons/BTFail.svg b/addons/limboai/icons/BTFail.svg
new file mode 100644
index 0000000..7be2920
--- /dev/null
+++ b/addons/limboai/icons/BTFail.svg
@@ -0,0 +1 @@
+
\ No newline at end of file
diff --git a/addons/beehave/icons/failer.svg.import b/addons/limboai/icons/BTFail.svg.import
similarity index 72%
rename from addons/beehave/icons/failer.svg.import
rename to addons/limboai/icons/BTFail.svg.import
index 989b556..75c8278 100644
--- a/addons/beehave/icons/failer.svg.import
+++ b/addons/limboai/icons/BTFail.svg.import
@@ -2,8 +2,8 @@
importer="texture"
type="CompressedTexture2D"
-uid="uid://2fj7htaqvcud"
-path="res://.godot/imported/failer.svg-9a62b840e1eacc0437e7a67b14a302e4.ctex"
+uid="uid://b3yqe2ysg5j01"
+path="res://.godot/imported/BTFail.svg-0440819265455ee47b2cf2ca8f1b8018.ctex"
metadata={
"has_editor_variant": true,
"vram_texture": false
@@ -11,8 +11,8 @@ metadata={
[deps]
-source_file="res://addons/beehave/icons/failer.svg"
-dest_files=["res://.godot/imported/failer.svg-9a62b840e1eacc0437e7a67b14a302e4.ctex"]
+source_file="res://addons/limboai/icons/BTFail.svg"
+dest_files=["res://.godot/imported/BTFail.svg-0440819265455ee47b2cf2ca8f1b8018.ctex"]
[params]
diff --git a/addons/limboai/icons/BTForEach.svg b/addons/limboai/icons/BTForEach.svg
new file mode 100644
index 0000000..819c0ed
--- /dev/null
+++ b/addons/limboai/icons/BTForEach.svg
@@ -0,0 +1 @@
+
\ No newline at end of file
diff --git a/addons/limboai/icons/BTForEach.svg.import b/addons/limboai/icons/BTForEach.svg.import
new file mode 100644
index 0000000..8b3e778
--- /dev/null
+++ b/addons/limboai/icons/BTForEach.svg.import
@@ -0,0 +1,38 @@
+[remap]
+
+importer="texture"
+type="CompressedTexture2D"
+uid="uid://bbujgvji3e1fd"
+path="res://.godot/imported/BTForEach.svg-4ca6daee422cda100144e3414286df7f.ctex"
+metadata={
+"has_editor_variant": true,
+"vram_texture": false
+}
+
+[deps]
+
+source_file="res://addons/limboai/icons/BTForEach.svg"
+dest_files=["res://.godot/imported/BTForEach.svg-4ca6daee422cda100144e3414286df7f.ctex"]
+
+[params]
+
+compress/mode=0
+compress/high_quality=false
+compress/lossy_quality=0.7
+compress/hdr_compression=1
+compress/normal_map=0
+compress/channel_pack=0
+mipmaps/generate=false
+mipmaps/limit=-1
+roughness/mode=0
+roughness/src_normal=""
+process/fix_alpha_border=true
+process/premult_alpha=false
+process/normal_map_invert_y=false
+process/hdr_as_srgb=false
+process/hdr_clamp_exposure=false
+process/size_limit=0
+detect_3d/compress_to=1
+svg/scale=1.0
+editor/scale_with_editor_scale=true
+editor/convert_colors_with_editor_theme=true
diff --git a/addons/limboai/icons/BTInvert.svg b/addons/limboai/icons/BTInvert.svg
new file mode 100644
index 0000000..31be0d5
--- /dev/null
+++ b/addons/limboai/icons/BTInvert.svg
@@ -0,0 +1 @@
+
\ No newline at end of file
diff --git a/addons/limboai/icons/BTInvert.svg.import b/addons/limboai/icons/BTInvert.svg.import
new file mode 100644
index 0000000..ae6507a
--- /dev/null
+++ b/addons/limboai/icons/BTInvert.svg.import
@@ -0,0 +1,38 @@
+[remap]
+
+importer="texture"
+type="CompressedTexture2D"
+uid="uid://b0x75np2op00u"
+path="res://.godot/imported/BTInvert.svg-19687b5c798f968b9610763066baa2a0.ctex"
+metadata={
+"has_editor_variant": true,
+"vram_texture": false
+}
+
+[deps]
+
+source_file="res://addons/limboai/icons/BTInvert.svg"
+dest_files=["res://.godot/imported/BTInvert.svg-19687b5c798f968b9610763066baa2a0.ctex"]
+
+[params]
+
+compress/mode=0
+compress/high_quality=false
+compress/lossy_quality=0.7
+compress/hdr_compression=1
+compress/normal_map=0
+compress/channel_pack=0
+mipmaps/generate=false
+mipmaps/limit=-1
+roughness/mode=0
+roughness/src_normal=""
+process/fix_alpha_border=true
+process/premult_alpha=false
+process/normal_map_invert_y=false
+process/hdr_as_srgb=false
+process/hdr_clamp_exposure=false
+process/size_limit=0
+detect_3d/compress_to=1
+svg/scale=1.0
+editor/scale_with_editor_scale=true
+editor/convert_colors_with_editor_theme=true
diff --git a/addons/limboai/icons/BTNewScope.svg b/addons/limboai/icons/BTNewScope.svg
new file mode 100644
index 0000000..598d39b
--- /dev/null
+++ b/addons/limboai/icons/BTNewScope.svg
@@ -0,0 +1 @@
+
\ No newline at end of file
diff --git a/addons/limboai/icons/BTNewScope.svg.import b/addons/limboai/icons/BTNewScope.svg.import
new file mode 100644
index 0000000..dcf337f
--- /dev/null
+++ b/addons/limboai/icons/BTNewScope.svg.import
@@ -0,0 +1,38 @@
+[remap]
+
+importer="texture"
+type="CompressedTexture2D"
+uid="uid://cvtaenq1awu7g"
+path="res://.godot/imported/BTNewScope.svg-d536a90c30773badb76653d8c928cfe0.ctex"
+metadata={
+"has_editor_variant": true,
+"vram_texture": false
+}
+
+[deps]
+
+source_file="res://addons/limboai/icons/BTNewScope.svg"
+dest_files=["res://.godot/imported/BTNewScope.svg-d536a90c30773badb76653d8c928cfe0.ctex"]
+
+[params]
+
+compress/mode=0
+compress/high_quality=false
+compress/lossy_quality=0.7
+compress/hdr_compression=1
+compress/normal_map=0
+compress/channel_pack=0
+mipmaps/generate=false
+mipmaps/limit=-1
+roughness/mode=0
+roughness/src_normal=""
+process/fix_alpha_border=true
+process/premult_alpha=false
+process/normal_map_invert_y=false
+process/hdr_as_srgb=false
+process/hdr_clamp_exposure=false
+process/size_limit=0
+detect_3d/compress_to=1
+svg/scale=1.0
+editor/scale_with_editor_scale=true
+editor/convert_colors_with_editor_theme=true
diff --git a/addons/limboai/icons/BTParallel.svg b/addons/limboai/icons/BTParallel.svg
new file mode 100644
index 0000000..7ee727a
--- /dev/null
+++ b/addons/limboai/icons/BTParallel.svg
@@ -0,0 +1 @@
+
\ No newline at end of file
diff --git a/addons/beehave/icons/inverter.svg.import b/addons/limboai/icons/BTParallel.svg.import
similarity index 73%
rename from addons/beehave/icons/inverter.svg.import
rename to addons/limboai/icons/BTParallel.svg.import
index e9050a8..0e21cbd 100644
--- a/addons/beehave/icons/inverter.svg.import
+++ b/addons/limboai/icons/BTParallel.svg.import
@@ -2,8 +2,8 @@
importer="texture"
type="CompressedTexture2D"
-uid="uid://cffmoc3og8hux"
-path="res://.godot/imported/inverter.svg-1f1b976d95de42c4ad99a92fa9a6c5d0.ctex"
+uid="uid://d3fkfunwqhahd"
+path="res://.godot/imported/BTParallel.svg-54126e7f374b26a890ddd82c580db45c.ctex"
metadata={
"has_editor_variant": true,
"vram_texture": false
@@ -11,8 +11,8 @@ metadata={
[deps]
-source_file="res://addons/beehave/icons/inverter.svg"
-dest_files=["res://.godot/imported/inverter.svg-1f1b976d95de42c4ad99a92fa9a6c5d0.ctex"]
+source_file="res://addons/limboai/icons/BTParallel.svg"
+dest_files=["res://.godot/imported/BTParallel.svg-54126e7f374b26a890ddd82c580db45c.ctex"]
[params]
diff --git a/addons/limboai/icons/BTPauseAnimation.svg b/addons/limboai/icons/BTPauseAnimation.svg
new file mode 100644
index 0000000..d0878cd
--- /dev/null
+++ b/addons/limboai/icons/BTPauseAnimation.svg
@@ -0,0 +1 @@
+
\ No newline at end of file
diff --git a/addons/limboai/icons/BTPauseAnimation.svg.import b/addons/limboai/icons/BTPauseAnimation.svg.import
new file mode 100644
index 0000000..2b53290
--- /dev/null
+++ b/addons/limboai/icons/BTPauseAnimation.svg.import
@@ -0,0 +1,38 @@
+[remap]
+
+importer="texture"
+type="CompressedTexture2D"
+uid="uid://bwgy4y5x2kan7"
+path="res://.godot/imported/BTPauseAnimation.svg-e1bc0cf7bcd45a0faa047192242d174b.ctex"
+metadata={
+"has_editor_variant": true,
+"vram_texture": false
+}
+
+[deps]
+
+source_file="res://addons/limboai/icons/BTPauseAnimation.svg"
+dest_files=["res://.godot/imported/BTPauseAnimation.svg-e1bc0cf7bcd45a0faa047192242d174b.ctex"]
+
+[params]
+
+compress/mode=0
+compress/high_quality=false
+compress/lossy_quality=0.7
+compress/hdr_compression=1
+compress/normal_map=0
+compress/channel_pack=0
+mipmaps/generate=false
+mipmaps/limit=-1
+roughness/mode=0
+roughness/src_normal=""
+process/fix_alpha_border=true
+process/premult_alpha=false
+process/normal_map_invert_y=false
+process/hdr_as_srgb=false
+process/hdr_clamp_exposure=false
+process/size_limit=0
+detect_3d/compress_to=1
+svg/scale=1.0
+editor/scale_with_editor_scale=true
+editor/convert_colors_with_editor_theme=true
diff --git a/addons/limboai/icons/BTPlayAnimation.svg b/addons/limboai/icons/BTPlayAnimation.svg
new file mode 100644
index 0000000..d387bf6
--- /dev/null
+++ b/addons/limboai/icons/BTPlayAnimation.svg
@@ -0,0 +1 @@
+
\ No newline at end of file
diff --git a/addons/limboai/icons/BTPlayAnimation.svg.import b/addons/limboai/icons/BTPlayAnimation.svg.import
new file mode 100644
index 0000000..38ae522
--- /dev/null
+++ b/addons/limboai/icons/BTPlayAnimation.svg.import
@@ -0,0 +1,38 @@
+[remap]
+
+importer="texture"
+type="CompressedTexture2D"
+uid="uid://d0bdvl7fqh1bs"
+path="res://.godot/imported/BTPlayAnimation.svg-8821f3b3413b9b328414add0e843468c.ctex"
+metadata={
+"has_editor_variant": true,
+"vram_texture": false
+}
+
+[deps]
+
+source_file="res://addons/limboai/icons/BTPlayAnimation.svg"
+dest_files=["res://.godot/imported/BTPlayAnimation.svg-8821f3b3413b9b328414add0e843468c.ctex"]
+
+[params]
+
+compress/mode=0
+compress/high_quality=false
+compress/lossy_quality=0.7
+compress/hdr_compression=1
+compress/normal_map=0
+compress/channel_pack=0
+mipmaps/generate=false
+mipmaps/limit=-1
+roughness/mode=0
+roughness/src_normal=""
+process/fix_alpha_border=true
+process/premult_alpha=false
+process/normal_map_invert_y=false
+process/hdr_as_srgb=false
+process/hdr_clamp_exposure=false
+process/size_limit=0
+detect_3d/compress_to=1
+svg/scale=1.0
+editor/scale_with_editor_scale=true
+editor/convert_colors_with_editor_theme=true
diff --git a/addons/limboai/icons/BTPlayer.svg b/addons/limboai/icons/BTPlayer.svg
new file mode 100644
index 0000000..7a874c7
--- /dev/null
+++ b/addons/limboai/icons/BTPlayer.svg
@@ -0,0 +1 @@
+
\ No newline at end of file
diff --git a/addons/limboai/icons/BTPlayer.svg.import b/addons/limboai/icons/BTPlayer.svg.import
new file mode 100644
index 0000000..3d5b4b1
--- /dev/null
+++ b/addons/limboai/icons/BTPlayer.svg.import
@@ -0,0 +1,38 @@
+[remap]
+
+importer="texture"
+type="CompressedTexture2D"
+uid="uid://xgdht012x686"
+path="res://.godot/imported/BTPlayer.svg-ed7adc3cf4a0f3daa1e17a1a77e9a3a2.ctex"
+metadata={
+"has_editor_variant": true,
+"vram_texture": false
+}
+
+[deps]
+
+source_file="res://addons/limboai/icons/BTPlayer.svg"
+dest_files=["res://.godot/imported/BTPlayer.svg-ed7adc3cf4a0f3daa1e17a1a77e9a3a2.ctex"]
+
+[params]
+
+compress/mode=0
+compress/high_quality=false
+compress/lossy_quality=0.7
+compress/hdr_compression=1
+compress/normal_map=0
+compress/channel_pack=0
+mipmaps/generate=false
+mipmaps/limit=-1
+roughness/mode=0
+roughness/src_normal=""
+process/fix_alpha_border=true
+process/premult_alpha=false
+process/normal_map_invert_y=false
+process/hdr_as_srgb=false
+process/hdr_clamp_exposure=false
+process/size_limit=0
+detect_3d/compress_to=1
+svg/scale=1.0
+editor/scale_with_editor_scale=true
+editor/convert_colors_with_editor_theme=true
diff --git a/addons/limboai/icons/BTProbability.svg b/addons/limboai/icons/BTProbability.svg
new file mode 100644
index 0000000..b1a90d9
--- /dev/null
+++ b/addons/limboai/icons/BTProbability.svg
@@ -0,0 +1 @@
+
\ No newline at end of file
diff --git a/addons/beehave/debug/icons/port_bottom.svg.import b/addons/limboai/icons/BTProbability.svg.import
similarity index 71%
rename from addons/beehave/debug/icons/port_bottom.svg.import
rename to addons/limboai/icons/BTProbability.svg.import
index 8845c5b..ea9611c 100644
--- a/addons/beehave/debug/icons/port_bottom.svg.import
+++ b/addons/limboai/icons/BTProbability.svg.import
@@ -2,8 +2,8 @@
importer="texture"
type="CompressedTexture2D"
-uid="uid://da3b236rjbqns"
-path="res://.godot/imported/port_bottom.svg-e5c5c61b642a79ab9c2b66ff56603d34.ctex"
+uid="uid://dcvvqt5u2ijhf"
+path="res://.godot/imported/BTProbability.svg-f691fbf51ca49bc268a17742b1e04985.ctex"
metadata={
"has_editor_variant": true,
"vram_texture": false
@@ -11,8 +11,8 @@ metadata={
[deps]
-source_file="res://addons/beehave/debug/icons/port_bottom.svg"
-dest_files=["res://.godot/imported/port_bottom.svg-e5c5c61b642a79ab9c2b66ff56603d34.ctex"]
+source_file="res://addons/limboai/icons/BTProbability.svg"
+dest_files=["res://.godot/imported/BTProbability.svg-f691fbf51ca49bc268a17742b1e04985.ctex"]
[params]
diff --git a/addons/limboai/icons/BTProbabilitySelector.svg b/addons/limboai/icons/BTProbabilitySelector.svg
new file mode 100644
index 0000000..f9516a1
--- /dev/null
+++ b/addons/limboai/icons/BTProbabilitySelector.svg
@@ -0,0 +1 @@
+
\ No newline at end of file
diff --git a/addons/beehave/debug/icons/vertical_layout.svg.import b/addons/limboai/icons/BTProbabilitySelector.svg.import
similarity index 69%
rename from addons/beehave/debug/icons/vertical_layout.svg.import
rename to addons/limboai/icons/BTProbabilitySelector.svg.import
index 8ddcfca..c2b4a36 100644
--- a/addons/beehave/debug/icons/vertical_layout.svg.import
+++ b/addons/limboai/icons/BTProbabilitySelector.svg.import
@@ -2,8 +2,8 @@
importer="texture"
type="CompressedTexture2D"
-uid="uid://bpyxu6i1dx5qh"
-path="res://.godot/imported/vertical_layout.svg-1a08fee4b09812a05bcf3defb8afcc4c.ctex"
+uid="uid://d0q82oimpay5k"
+path="res://.godot/imported/BTProbabilitySelector.svg-30f59f4e802f72a701d9d31f605a64f2.ctex"
metadata={
"has_editor_variant": true,
"vram_texture": false
@@ -11,8 +11,8 @@ metadata={
[deps]
-source_file="res://addons/beehave/debug/icons/vertical_layout.svg"
-dest_files=["res://.godot/imported/vertical_layout.svg-1a08fee4b09812a05bcf3defb8afcc4c.ctex"]
+source_file="res://addons/limboai/icons/BTProbabilitySelector.svg"
+dest_files=["res://.godot/imported/BTProbabilitySelector.svg-30f59f4e802f72a701d9d31f605a64f2.ctex"]
[params]
diff --git a/addons/limboai/icons/BTRandomSelector.svg b/addons/limboai/icons/BTRandomSelector.svg
new file mode 100644
index 0000000..6dd87d1
--- /dev/null
+++ b/addons/limboai/icons/BTRandomSelector.svg
@@ -0,0 +1 @@
+
\ No newline at end of file
diff --git a/addons/limboai/icons/BTRandomSelector.svg.import b/addons/limboai/icons/BTRandomSelector.svg.import
new file mode 100644
index 0000000..dc83dbb
--- /dev/null
+++ b/addons/limboai/icons/BTRandomSelector.svg.import
@@ -0,0 +1,38 @@
+[remap]
+
+importer="texture"
+type="CompressedTexture2D"
+uid="uid://raadq7j6uuc7"
+path="res://.godot/imported/BTRandomSelector.svg-4bae5a6e3e1affdd4952e8bff4c018ff.ctex"
+metadata={
+"has_editor_variant": true,
+"vram_texture": false
+}
+
+[deps]
+
+source_file="res://addons/limboai/icons/BTRandomSelector.svg"
+dest_files=["res://.godot/imported/BTRandomSelector.svg-4bae5a6e3e1affdd4952e8bff4c018ff.ctex"]
+
+[params]
+
+compress/mode=0
+compress/high_quality=false
+compress/lossy_quality=0.7
+compress/hdr_compression=1
+compress/normal_map=0
+compress/channel_pack=0
+mipmaps/generate=false
+mipmaps/limit=-1
+roughness/mode=0
+roughness/src_normal=""
+process/fix_alpha_border=true
+process/premult_alpha=false
+process/normal_map_invert_y=false
+process/hdr_as_srgb=false
+process/hdr_clamp_exposure=false
+process/size_limit=0
+detect_3d/compress_to=1
+svg/scale=1.0
+editor/scale_with_editor_scale=true
+editor/convert_colors_with_editor_theme=true
diff --git a/addons/limboai/icons/BTRandomSequence.svg b/addons/limboai/icons/BTRandomSequence.svg
new file mode 100644
index 0000000..ff21602
--- /dev/null
+++ b/addons/limboai/icons/BTRandomSequence.svg
@@ -0,0 +1 @@
+
\ No newline at end of file
diff --git a/addons/limboai/icons/BTRandomSequence.svg.import b/addons/limboai/icons/BTRandomSequence.svg.import
new file mode 100644
index 0000000..f83fd2a
--- /dev/null
+++ b/addons/limboai/icons/BTRandomSequence.svg.import
@@ -0,0 +1,38 @@
+[remap]
+
+importer="texture"
+type="CompressedTexture2D"
+uid="uid://b1al3dllokjt7"
+path="res://.godot/imported/BTRandomSequence.svg-85ce4b080ec904d340a807de2669110d.ctex"
+metadata={
+"has_editor_variant": true,
+"vram_texture": false
+}
+
+[deps]
+
+source_file="res://addons/limboai/icons/BTRandomSequence.svg"
+dest_files=["res://.godot/imported/BTRandomSequence.svg-85ce4b080ec904d340a807de2669110d.ctex"]
+
+[params]
+
+compress/mode=0
+compress/high_quality=false
+compress/lossy_quality=0.7
+compress/hdr_compression=1
+compress/normal_map=0
+compress/channel_pack=0
+mipmaps/generate=false
+mipmaps/limit=-1
+roughness/mode=0
+roughness/src_normal=""
+process/fix_alpha_border=true
+process/premult_alpha=false
+process/normal_map_invert_y=false
+process/hdr_as_srgb=false
+process/hdr_clamp_exposure=false
+process/size_limit=0
+detect_3d/compress_to=1
+svg/scale=1.0
+editor/scale_with_editor_scale=true
+editor/convert_colors_with_editor_theme=true
diff --git a/addons/limboai/icons/BTRandomWait.svg b/addons/limboai/icons/BTRandomWait.svg
new file mode 100644
index 0000000..8174e2a
--- /dev/null
+++ b/addons/limboai/icons/BTRandomWait.svg
@@ -0,0 +1 @@
+
\ No newline at end of file
diff --git a/addons/limboai/icons/BTRandomWait.svg.import b/addons/limboai/icons/BTRandomWait.svg.import
new file mode 100644
index 0000000..750d869
--- /dev/null
+++ b/addons/limboai/icons/BTRandomWait.svg.import
@@ -0,0 +1,38 @@
+[remap]
+
+importer="texture"
+type="CompressedTexture2D"
+uid="uid://oyoxe6xxo5ix"
+path="res://.godot/imported/BTRandomWait.svg-14f03a0fb52c993ec1cdbb780d9dfea3.ctex"
+metadata={
+"has_editor_variant": true,
+"vram_texture": false
+}
+
+[deps]
+
+source_file="res://addons/limboai/icons/BTRandomWait.svg"
+dest_files=["res://.godot/imported/BTRandomWait.svg-14f03a0fb52c993ec1cdbb780d9dfea3.ctex"]
+
+[params]
+
+compress/mode=0
+compress/high_quality=false
+compress/lossy_quality=0.7
+compress/hdr_compression=1
+compress/normal_map=0
+compress/channel_pack=0
+mipmaps/generate=false
+mipmaps/limit=-1
+roughness/mode=0
+roughness/src_normal=""
+process/fix_alpha_border=true
+process/premult_alpha=false
+process/normal_map_invert_y=false
+process/hdr_as_srgb=false
+process/hdr_clamp_exposure=false
+process/size_limit=0
+detect_3d/compress_to=1
+svg/scale=1.0
+editor/scale_with_editor_scale=true
+editor/convert_colors_with_editor_theme=true
diff --git a/addons/limboai/icons/BTRepeat.svg b/addons/limboai/icons/BTRepeat.svg
new file mode 100644
index 0000000..d937bcf
--- /dev/null
+++ b/addons/limboai/icons/BTRepeat.svg
@@ -0,0 +1 @@
+
\ No newline at end of file
diff --git a/addons/limboai/icons/BTRepeat.svg.import b/addons/limboai/icons/BTRepeat.svg.import
new file mode 100644
index 0000000..52ea442
--- /dev/null
+++ b/addons/limboai/icons/BTRepeat.svg.import
@@ -0,0 +1,38 @@
+[remap]
+
+importer="texture"
+type="CompressedTexture2D"
+uid="uid://bv4ri1q3dp8lr"
+path="res://.godot/imported/BTRepeat.svg-ca1efcf8bdef890d4575f2bf66ba0a8d.ctex"
+metadata={
+"has_editor_variant": true,
+"vram_texture": false
+}
+
+[deps]
+
+source_file="res://addons/limboai/icons/BTRepeat.svg"
+dest_files=["res://.godot/imported/BTRepeat.svg-ca1efcf8bdef890d4575f2bf66ba0a8d.ctex"]
+
+[params]
+
+compress/mode=0
+compress/high_quality=false
+compress/lossy_quality=0.7
+compress/hdr_compression=1
+compress/normal_map=0
+compress/channel_pack=0
+mipmaps/generate=false
+mipmaps/limit=-1
+roughness/mode=0
+roughness/src_normal=""
+process/fix_alpha_border=true
+process/premult_alpha=false
+process/normal_map_invert_y=false
+process/hdr_as_srgb=false
+process/hdr_clamp_exposure=false
+process/size_limit=0
+detect_3d/compress_to=1
+svg/scale=1.0
+editor/scale_with_editor_scale=true
+editor/convert_colors_with_editor_theme=true
diff --git a/addons/limboai/icons/BTRepeatUntilFailure.svg b/addons/limboai/icons/BTRepeatUntilFailure.svg
new file mode 100644
index 0000000..88b1261
--- /dev/null
+++ b/addons/limboai/icons/BTRepeatUntilFailure.svg
@@ -0,0 +1 @@
+
\ No newline at end of file
diff --git a/addons/limboai/icons/BTRepeatUntilFailure.svg.import b/addons/limboai/icons/BTRepeatUntilFailure.svg.import
new file mode 100644
index 0000000..1be5716
--- /dev/null
+++ b/addons/limboai/icons/BTRepeatUntilFailure.svg.import
@@ -0,0 +1,38 @@
+[remap]
+
+importer="texture"
+type="CompressedTexture2D"
+uid="uid://neou1pnfq41i"
+path="res://.godot/imported/BTRepeatUntilFailure.svg-97ff99132cb6b229bb78050959a89118.ctex"
+metadata={
+"has_editor_variant": true,
+"vram_texture": false
+}
+
+[deps]
+
+source_file="res://addons/limboai/icons/BTRepeatUntilFailure.svg"
+dest_files=["res://.godot/imported/BTRepeatUntilFailure.svg-97ff99132cb6b229bb78050959a89118.ctex"]
+
+[params]
+
+compress/mode=0
+compress/high_quality=false
+compress/lossy_quality=0.7
+compress/hdr_compression=1
+compress/normal_map=0
+compress/channel_pack=0
+mipmaps/generate=false
+mipmaps/limit=-1
+roughness/mode=0
+roughness/src_normal=""
+process/fix_alpha_border=true
+process/premult_alpha=false
+process/normal_map_invert_y=false
+process/hdr_as_srgb=false
+process/hdr_clamp_exposure=false
+process/size_limit=0
+detect_3d/compress_to=1
+svg/scale=1.0
+editor/scale_with_editor_scale=true
+editor/convert_colors_with_editor_theme=true
diff --git a/addons/limboai/icons/BTRepeatUntilSuccess.svg b/addons/limboai/icons/BTRepeatUntilSuccess.svg
new file mode 100644
index 0000000..9087ce4
--- /dev/null
+++ b/addons/limboai/icons/BTRepeatUntilSuccess.svg
@@ -0,0 +1 @@
+
\ No newline at end of file
diff --git a/addons/limboai/icons/BTRepeatUntilSuccess.svg.import b/addons/limboai/icons/BTRepeatUntilSuccess.svg.import
new file mode 100644
index 0000000..880bcc7
--- /dev/null
+++ b/addons/limboai/icons/BTRepeatUntilSuccess.svg.import
@@ -0,0 +1,38 @@
+[remap]
+
+importer="texture"
+type="CompressedTexture2D"
+uid="uid://c7q2c3q5cdkq4"
+path="res://.godot/imported/BTRepeatUntilSuccess.svg-160e74b6885a57a745db349d6f7004a8.ctex"
+metadata={
+"has_editor_variant": true,
+"vram_texture": false
+}
+
+[deps]
+
+source_file="res://addons/limboai/icons/BTRepeatUntilSuccess.svg"
+dest_files=["res://.godot/imported/BTRepeatUntilSuccess.svg-160e74b6885a57a745db349d6f7004a8.ctex"]
+
+[params]
+
+compress/mode=0
+compress/high_quality=false
+compress/lossy_quality=0.7
+compress/hdr_compression=1
+compress/normal_map=0
+compress/channel_pack=0
+mipmaps/generate=false
+mipmaps/limit=-1
+roughness/mode=0
+roughness/src_normal=""
+process/fix_alpha_border=true
+process/premult_alpha=false
+process/normal_map_invert_y=false
+process/hdr_as_srgb=false
+process/hdr_clamp_exposure=false
+process/size_limit=0
+detect_3d/compress_to=1
+svg/scale=1.0
+editor/scale_with_editor_scale=true
+editor/convert_colors_with_editor_theme=true
diff --git a/addons/limboai/icons/BTRunLimit.svg b/addons/limboai/icons/BTRunLimit.svg
new file mode 100644
index 0000000..1ac7fa1
--- /dev/null
+++ b/addons/limboai/icons/BTRunLimit.svg
@@ -0,0 +1 @@
+
\ No newline at end of file
diff --git a/addons/limboai/icons/BTRunLimit.svg.import b/addons/limboai/icons/BTRunLimit.svg.import
new file mode 100644
index 0000000..a75b4e5
--- /dev/null
+++ b/addons/limboai/icons/BTRunLimit.svg.import
@@ -0,0 +1,38 @@
+[remap]
+
+importer="texture"
+type="CompressedTexture2D"
+uid="uid://datrvth41sv7b"
+path="res://.godot/imported/BTRunLimit.svg-eb80a597bf9102a626f8c0e9663703d1.ctex"
+metadata={
+"has_editor_variant": true,
+"vram_texture": false
+}
+
+[deps]
+
+source_file="res://addons/limboai/icons/BTRunLimit.svg"
+dest_files=["res://.godot/imported/BTRunLimit.svg-eb80a597bf9102a626f8c0e9663703d1.ctex"]
+
+[params]
+
+compress/mode=0
+compress/high_quality=false
+compress/lossy_quality=0.7
+compress/hdr_compression=1
+compress/normal_map=0
+compress/channel_pack=0
+mipmaps/generate=false
+mipmaps/limit=-1
+roughness/mode=0
+roughness/src_normal=""
+process/fix_alpha_border=true
+process/premult_alpha=false
+process/normal_map_invert_y=false
+process/hdr_as_srgb=false
+process/hdr_clamp_exposure=false
+process/size_limit=0
+detect_3d/compress_to=1
+svg/scale=1.0
+editor/scale_with_editor_scale=true
+editor/convert_colors_with_editor_theme=true
diff --git a/addons/limboai/icons/BTSelector.svg b/addons/limboai/icons/BTSelector.svg
new file mode 100644
index 0000000..d7cafe5
--- /dev/null
+++ b/addons/limboai/icons/BTSelector.svg
@@ -0,0 +1 @@
+
\ No newline at end of file
diff --git a/addons/limboai/icons/BTSelector.svg.import b/addons/limboai/icons/BTSelector.svg.import
new file mode 100644
index 0000000..2e555ac
--- /dev/null
+++ b/addons/limboai/icons/BTSelector.svg.import
@@ -0,0 +1,38 @@
+[remap]
+
+importer="texture"
+type="CompressedTexture2D"
+uid="uid://busho8agrsdf5"
+path="res://.godot/imported/BTSelector.svg-859c7746bc77c632d2a60052d2e96cf0.ctex"
+metadata={
+"has_editor_variant": true,
+"vram_texture": false
+}
+
+[deps]
+
+source_file="res://addons/limboai/icons/BTSelector.svg"
+dest_files=["res://.godot/imported/BTSelector.svg-859c7746bc77c632d2a60052d2e96cf0.ctex"]
+
+[params]
+
+compress/mode=0
+compress/high_quality=false
+compress/lossy_quality=0.7
+compress/hdr_compression=1
+compress/normal_map=0
+compress/channel_pack=0
+mipmaps/generate=false
+mipmaps/limit=-1
+roughness/mode=0
+roughness/src_normal=""
+process/fix_alpha_border=true
+process/premult_alpha=false
+process/normal_map_invert_y=false
+process/hdr_as_srgb=false
+process/hdr_clamp_exposure=false
+process/size_limit=0
+detect_3d/compress_to=1
+svg/scale=1.0
+editor/scale_with_editor_scale=true
+editor/convert_colors_with_editor_theme=true
diff --git a/addons/limboai/icons/BTSequence.svg b/addons/limboai/icons/BTSequence.svg
new file mode 100644
index 0000000..7eb8f6f
--- /dev/null
+++ b/addons/limboai/icons/BTSequence.svg
@@ -0,0 +1 @@
+
\ No newline at end of file
diff --git a/addons/limboai/icons/BTSequence.svg.import b/addons/limboai/icons/BTSequence.svg.import
new file mode 100644
index 0000000..4ad3575
--- /dev/null
+++ b/addons/limboai/icons/BTSequence.svg.import
@@ -0,0 +1,38 @@
+[remap]
+
+importer="texture"
+type="CompressedTexture2D"
+uid="uid://1oqmee31m013"
+path="res://.godot/imported/BTSequence.svg-3dfd257b3424273ac1ea2f8a48dab7b6.ctex"
+metadata={
+"has_editor_variant": true,
+"vram_texture": false
+}
+
+[deps]
+
+source_file="res://addons/limboai/icons/BTSequence.svg"
+dest_files=["res://.godot/imported/BTSequence.svg-3dfd257b3424273ac1ea2f8a48dab7b6.ctex"]
+
+[params]
+
+compress/mode=0
+compress/high_quality=false
+compress/lossy_quality=0.7
+compress/hdr_compression=1
+compress/normal_map=0
+compress/channel_pack=0
+mipmaps/generate=false
+mipmaps/limit=-1
+roughness/mode=0
+roughness/src_normal=""
+process/fix_alpha_border=true
+process/premult_alpha=false
+process/normal_map_invert_y=false
+process/hdr_as_srgb=false
+process/hdr_clamp_exposure=false
+process/size_limit=0
+detect_3d/compress_to=1
+svg/scale=1.0
+editor/scale_with_editor_scale=true
+editor/convert_colors_with_editor_theme=true
diff --git a/addons/limboai/icons/BTSetAgentProperty.svg b/addons/limboai/icons/BTSetAgentProperty.svg
new file mode 100644
index 0000000..c92a710
--- /dev/null
+++ b/addons/limboai/icons/BTSetAgentProperty.svg
@@ -0,0 +1 @@
+
\ No newline at end of file
diff --git a/addons/limboai/icons/BTSetAgentProperty.svg.import b/addons/limboai/icons/BTSetAgentProperty.svg.import
new file mode 100644
index 0000000..1f420ba
--- /dev/null
+++ b/addons/limboai/icons/BTSetAgentProperty.svg.import
@@ -0,0 +1,38 @@
+[remap]
+
+importer="texture"
+type="CompressedTexture2D"
+uid="uid://bt2qv1ctli6xv"
+path="res://.godot/imported/BTSetAgentProperty.svg-8183ecffb47d990ae67daaad34563dc5.ctex"
+metadata={
+"has_editor_variant": true,
+"vram_texture": false
+}
+
+[deps]
+
+source_file="res://addons/limboai/icons/BTSetAgentProperty.svg"
+dest_files=["res://.godot/imported/BTSetAgentProperty.svg-8183ecffb47d990ae67daaad34563dc5.ctex"]
+
+[params]
+
+compress/mode=0
+compress/high_quality=false
+compress/lossy_quality=0.7
+compress/hdr_compression=1
+compress/normal_map=0
+compress/channel_pack=0
+mipmaps/generate=false
+mipmaps/limit=-1
+roughness/mode=0
+roughness/src_normal=""
+process/fix_alpha_border=true
+process/premult_alpha=false
+process/normal_map_invert_y=false
+process/hdr_as_srgb=false
+process/hdr_clamp_exposure=false
+process/size_limit=0
+detect_3d/compress_to=1
+svg/scale=1.0
+editor/scale_with_editor_scale=true
+editor/convert_colors_with_editor_theme=true
diff --git a/addons/limboai/icons/BTSetVar.svg b/addons/limboai/icons/BTSetVar.svg
new file mode 100644
index 0000000..09f6822
--- /dev/null
+++ b/addons/limboai/icons/BTSetVar.svg
@@ -0,0 +1 @@
+
\ No newline at end of file
diff --git a/addons/limboai/icons/BTSetVar.svg.import b/addons/limboai/icons/BTSetVar.svg.import
new file mode 100644
index 0000000..13f0191
--- /dev/null
+++ b/addons/limboai/icons/BTSetVar.svg.import
@@ -0,0 +1,38 @@
+[remap]
+
+importer="texture"
+type="CompressedTexture2D"
+uid="uid://csc2jop2cfe4u"
+path="res://.godot/imported/BTSetVar.svg-a8c4f135c2df6bc3f587cbd9f1fe2d95.ctex"
+metadata={
+"has_editor_variant": true,
+"vram_texture": false
+}
+
+[deps]
+
+source_file="res://addons/limboai/icons/BTSetVar.svg"
+dest_files=["res://.godot/imported/BTSetVar.svg-a8c4f135c2df6bc3f587cbd9f1fe2d95.ctex"]
+
+[params]
+
+compress/mode=0
+compress/high_quality=false
+compress/lossy_quality=0.7
+compress/hdr_compression=1
+compress/normal_map=0
+compress/channel_pack=0
+mipmaps/generate=false
+mipmaps/limit=-1
+roughness/mode=0
+roughness/src_normal=""
+process/fix_alpha_border=true
+process/premult_alpha=false
+process/normal_map_invert_y=false
+process/hdr_as_srgb=false
+process/hdr_clamp_exposure=false
+process/size_limit=0
+detect_3d/compress_to=1
+svg/scale=1.0
+editor/scale_with_editor_scale=true
+editor/convert_colors_with_editor_theme=true
diff --git a/addons/limboai/icons/BTState.svg b/addons/limboai/icons/BTState.svg
new file mode 100644
index 0000000..7a874c7
--- /dev/null
+++ b/addons/limboai/icons/BTState.svg
@@ -0,0 +1 @@
+
\ No newline at end of file
diff --git a/addons/beehave/icons/tree.svg.import b/addons/limboai/icons/BTState.svg.import
similarity index 72%
rename from addons/beehave/icons/tree.svg.import
rename to addons/limboai/icons/BTState.svg.import
index 9ac0308..f1522d3 100644
--- a/addons/beehave/icons/tree.svg.import
+++ b/addons/limboai/icons/BTState.svg.import
@@ -2,8 +2,8 @@
importer="texture"
type="CompressedTexture2D"
-uid="uid://deryyg2hbmaaw"
-path="res://.godot/imported/tree.svg-c0b20ed88b2fe300c0296f7236049076.ctex"
+uid="uid://3mmu0q6qkria"
+path="res://.godot/imported/BTState.svg-71220d904fcc42cc20dd0af8145f86a0.ctex"
metadata={
"has_editor_variant": true,
"vram_texture": false
@@ -11,8 +11,8 @@ metadata={
[deps]
-source_file="res://addons/beehave/icons/tree.svg"
-dest_files=["res://.godot/imported/tree.svg-c0b20ed88b2fe300c0296f7236049076.ctex"]
+source_file="res://addons/limboai/icons/BTState.svg"
+dest_files=["res://.godot/imported/BTState.svg-71220d904fcc42cc20dd0af8145f86a0.ctex"]
[params]
diff --git a/addons/limboai/icons/BTStopAnimation.svg b/addons/limboai/icons/BTStopAnimation.svg
new file mode 100644
index 0000000..973b542
--- /dev/null
+++ b/addons/limboai/icons/BTStopAnimation.svg
@@ -0,0 +1 @@
+
\ No newline at end of file
diff --git a/addons/limboai/icons/BTStopAnimation.svg.import b/addons/limboai/icons/BTStopAnimation.svg.import
new file mode 100644
index 0000000..a324ac4
--- /dev/null
+++ b/addons/limboai/icons/BTStopAnimation.svg.import
@@ -0,0 +1,38 @@
+[remap]
+
+importer="texture"
+type="CompressedTexture2D"
+uid="uid://ckubaxdlaswge"
+path="res://.godot/imported/BTStopAnimation.svg-ea88498cd747a6218f7853f6be3ded34.ctex"
+metadata={
+"has_editor_variant": true,
+"vram_texture": false
+}
+
+[deps]
+
+source_file="res://addons/limboai/icons/BTStopAnimation.svg"
+dest_files=["res://.godot/imported/BTStopAnimation.svg-ea88498cd747a6218f7853f6be3ded34.ctex"]
+
+[params]
+
+compress/mode=0
+compress/high_quality=false
+compress/lossy_quality=0.7
+compress/hdr_compression=1
+compress/normal_map=0
+compress/channel_pack=0
+mipmaps/generate=false
+mipmaps/limit=-1
+roughness/mode=0
+roughness/src_normal=""
+process/fix_alpha_border=true
+process/premult_alpha=false
+process/normal_map_invert_y=false
+process/hdr_as_srgb=false
+process/hdr_clamp_exposure=false
+process/size_limit=0
+detect_3d/compress_to=1
+svg/scale=1.0
+editor/scale_with_editor_scale=true
+editor/convert_colors_with_editor_theme=true
diff --git a/addons/limboai/icons/BTSubtree.svg b/addons/limboai/icons/BTSubtree.svg
new file mode 100644
index 0000000..e95ffee
--- /dev/null
+++ b/addons/limboai/icons/BTSubtree.svg
@@ -0,0 +1 @@
+
\ No newline at end of file
diff --git a/addons/beehave/icons/blackboard.svg.import b/addons/limboai/icons/BTSubtree.svg.import
similarity index 74%
rename from addons/beehave/icons/blackboard.svg.import
rename to addons/limboai/icons/BTSubtree.svg.import
index 4650058..7511b6c 100644
--- a/addons/beehave/icons/blackboard.svg.import
+++ b/addons/limboai/icons/BTSubtree.svg.import
@@ -2,8 +2,8 @@
importer="texture"
type="CompressedTexture2D"
-uid="uid://dw7rom0hiff6c"
-path="res://.godot/imported/blackboard.svg-18d4dfd4f6de558de250b67251ff1e69.ctex"
+uid="uid://dpg4i8l1k4pmm"
+path="res://.godot/imported/BTSubtree.svg-aa8f2ece5e71aca9132a08c7af1c1ce5.ctex"
metadata={
"has_editor_variant": true,
"vram_texture": false
@@ -11,8 +11,8 @@ metadata={
[deps]
-source_file="res://addons/beehave/icons/blackboard.svg"
-dest_files=["res://.godot/imported/blackboard.svg-18d4dfd4f6de558de250b67251ff1e69.ctex"]
+source_file="res://addons/limboai/icons/BTSubtree.svg"
+dest_files=["res://.godot/imported/BTSubtree.svg-aa8f2ece5e71aca9132a08c7af1c1ce5.ctex"]
[params]
diff --git a/addons/limboai/icons/BTTimeLimit.svg b/addons/limboai/icons/BTTimeLimit.svg
new file mode 100644
index 0000000..2c6a237
--- /dev/null
+++ b/addons/limboai/icons/BTTimeLimit.svg
@@ -0,0 +1 @@
+
\ No newline at end of file
diff --git a/addons/limboai/icons/BTTimeLimit.svg.import b/addons/limboai/icons/BTTimeLimit.svg.import
new file mode 100644
index 0000000..975386d
--- /dev/null
+++ b/addons/limboai/icons/BTTimeLimit.svg.import
@@ -0,0 +1,38 @@
+[remap]
+
+importer="texture"
+type="CompressedTexture2D"
+uid="uid://bf1etfi0qcn6y"
+path="res://.godot/imported/BTTimeLimit.svg-ea3ca26eeb5c2b59f3fdb6e806985f3b.ctex"
+metadata={
+"has_editor_variant": true,
+"vram_texture": false
+}
+
+[deps]
+
+source_file="res://addons/limboai/icons/BTTimeLimit.svg"
+dest_files=["res://.godot/imported/BTTimeLimit.svg-ea3ca26eeb5c2b59f3fdb6e806985f3b.ctex"]
+
+[params]
+
+compress/mode=0
+compress/high_quality=false
+compress/lossy_quality=0.7
+compress/hdr_compression=1
+compress/normal_map=0
+compress/channel_pack=0
+mipmaps/generate=false
+mipmaps/limit=-1
+roughness/mode=0
+roughness/src_normal=""
+process/fix_alpha_border=true
+process/premult_alpha=false
+process/normal_map_invert_y=false
+process/hdr_as_srgb=false
+process/hdr_clamp_exposure=false
+process/size_limit=0
+detect_3d/compress_to=1
+svg/scale=1.0
+editor/scale_with_editor_scale=true
+editor/convert_colors_with_editor_theme=true
diff --git a/addons/limboai/icons/BTWait.svg b/addons/limboai/icons/BTWait.svg
new file mode 100644
index 0000000..8174e2a
--- /dev/null
+++ b/addons/limboai/icons/BTWait.svg
@@ -0,0 +1 @@
+
\ No newline at end of file
diff --git a/addons/beehave/icons/action.svg.import b/addons/limboai/icons/BTWait.svg.import
similarity index 72%
rename from addons/beehave/icons/action.svg.import
rename to addons/limboai/icons/BTWait.svg.import
index cf8a612..57e54b6 100644
--- a/addons/beehave/icons/action.svg.import
+++ b/addons/limboai/icons/BTWait.svg.import
@@ -2,8 +2,8 @@
importer="texture"
type="CompressedTexture2D"
-uid="uid://btrq8e0kyxthg"
-path="res://.godot/imported/action.svg-e8a91246d0ba9ba3cf84290d65648f06.ctex"
+uid="uid://djr02a3fu8mrm"
+path="res://.godot/imported/BTWait.svg-2a5d27d0c617861f027b2e66516aa5bf.ctex"
metadata={
"has_editor_variant": true,
"vram_texture": false
@@ -11,8 +11,8 @@ metadata={
[deps]
-source_file="res://addons/beehave/icons/action.svg"
-dest_files=["res://.godot/imported/action.svg-e8a91246d0ba9ba3cf84290d65648f06.ctex"]
+source_file="res://addons/limboai/icons/BTWait.svg"
+dest_files=["res://.godot/imported/BTWait.svg-2a5d27d0c617861f027b2e66516aa5bf.ctex"]
[params]
diff --git a/addons/limboai/icons/BTWaitTicks.svg b/addons/limboai/icons/BTWaitTicks.svg
new file mode 100644
index 0000000..8174e2a
--- /dev/null
+++ b/addons/limboai/icons/BTWaitTicks.svg
@@ -0,0 +1 @@
+
\ No newline at end of file
diff --git a/addons/limboai/icons/BTWaitTicks.svg.import b/addons/limboai/icons/BTWaitTicks.svg.import
new file mode 100644
index 0000000..42bee88
--- /dev/null
+++ b/addons/limboai/icons/BTWaitTicks.svg.import
@@ -0,0 +1,38 @@
+[remap]
+
+importer="texture"
+type="CompressedTexture2D"
+uid="uid://b260miy6ud5oy"
+path="res://.godot/imported/BTWaitTicks.svg-85a005f86874f6811423163f3f5673b2.ctex"
+metadata={
+"has_editor_variant": true,
+"vram_texture": false
+}
+
+[deps]
+
+source_file="res://addons/limboai/icons/BTWaitTicks.svg"
+dest_files=["res://.godot/imported/BTWaitTicks.svg-85a005f86874f6811423163f3f5673b2.ctex"]
+
+[params]
+
+compress/mode=0
+compress/high_quality=false
+compress/lossy_quality=0.7
+compress/hdr_compression=1
+compress/normal_map=0
+compress/channel_pack=0
+mipmaps/generate=false
+mipmaps/limit=-1
+roughness/mode=0
+roughness/src_normal=""
+process/fix_alpha_border=true
+process/premult_alpha=false
+process/normal_map_invert_y=false
+process/hdr_as_srgb=false
+process/hdr_clamp_exposure=false
+process/size_limit=0
+detect_3d/compress_to=1
+svg/scale=1.0
+editor/scale_with_editor_scale=true
+editor/convert_colors_with_editor_theme=true
diff --git a/addons/limboai/icons/BehaviorTree.svg b/addons/limboai/icons/BehaviorTree.svg
new file mode 100644
index 0000000..e95ffee
--- /dev/null
+++ b/addons/limboai/icons/BehaviorTree.svg
@@ -0,0 +1 @@
+
\ No newline at end of file
diff --git a/addons/limboai/icons/BehaviorTree.svg.import b/addons/limboai/icons/BehaviorTree.svg.import
new file mode 100644
index 0000000..eba1d23
--- /dev/null
+++ b/addons/limboai/icons/BehaviorTree.svg.import
@@ -0,0 +1,38 @@
+[remap]
+
+importer="texture"
+type="CompressedTexture2D"
+uid="uid://bmk3ols1ubqd"
+path="res://.godot/imported/BehaviorTree.svg-9b40a8b5e1feb368d9f11b0fb1785cca.ctex"
+metadata={
+"has_editor_variant": true,
+"vram_texture": false
+}
+
+[deps]
+
+source_file="res://addons/limboai/icons/BehaviorTree.svg"
+dest_files=["res://.godot/imported/BehaviorTree.svg-9b40a8b5e1feb368d9f11b0fb1785cca.ctex"]
+
+[params]
+
+compress/mode=0
+compress/high_quality=false
+compress/lossy_quality=0.7
+compress/hdr_compression=1
+compress/normal_map=0
+compress/channel_pack=0
+mipmaps/generate=false
+mipmaps/limit=-1
+roughness/mode=0
+roughness/src_normal=""
+process/fix_alpha_border=true
+process/premult_alpha=false
+process/normal_map_invert_y=false
+process/hdr_as_srgb=false
+process/hdr_clamp_exposure=false
+process/size_limit=0
+detect_3d/compress_to=1
+svg/scale=1.0
+editor/scale_with_editor_scale=true
+editor/convert_colors_with_editor_theme=true
diff --git a/addons/limboai/icons/BehaviorTreeView.svg b/addons/limboai/icons/BehaviorTreeView.svg
new file mode 100644
index 0000000..8deff60
--- /dev/null
+++ b/addons/limboai/icons/BehaviorTreeView.svg
@@ -0,0 +1 @@
+
\ No newline at end of file
diff --git a/addons/limboai/icons/BehaviorTreeView.svg.import b/addons/limboai/icons/BehaviorTreeView.svg.import
new file mode 100644
index 0000000..09e7e15
--- /dev/null
+++ b/addons/limboai/icons/BehaviorTreeView.svg.import
@@ -0,0 +1,38 @@
+[remap]
+
+importer="texture"
+type="CompressedTexture2D"
+uid="uid://cdnmh1xjo0r33"
+path="res://.godot/imported/BehaviorTreeView.svg-15f9bfa321ed4a264ed8404fd13b53fc.ctex"
+metadata={
+"has_editor_variant": true,
+"vram_texture": false
+}
+
+[deps]
+
+source_file="res://addons/limboai/icons/BehaviorTreeView.svg"
+dest_files=["res://.godot/imported/BehaviorTreeView.svg-15f9bfa321ed4a264ed8404fd13b53fc.ctex"]
+
+[params]
+
+compress/mode=0
+compress/high_quality=false
+compress/lossy_quality=0.7
+compress/hdr_compression=1
+compress/normal_map=0
+compress/channel_pack=0
+mipmaps/generate=false
+mipmaps/limit=-1
+roughness/mode=0
+roughness/src_normal=""
+process/fix_alpha_border=true
+process/premult_alpha=false
+process/normal_map_invert_y=false
+process/hdr_as_srgb=false
+process/hdr_clamp_exposure=false
+process/size_limit=0
+detect_3d/compress_to=1
+svg/scale=1.0
+editor/scale_with_editor_scale=true
+editor/convert_colors_with_editor_theme=true
diff --git a/addons/limboai/icons/BlackboardPlan.svg b/addons/limboai/icons/BlackboardPlan.svg
new file mode 100644
index 0000000..958fba3
--- /dev/null
+++ b/addons/limboai/icons/BlackboardPlan.svg
@@ -0,0 +1 @@
+
\ No newline at end of file
diff --git a/addons/limboai/icons/BlackboardPlan.svg.import b/addons/limboai/icons/BlackboardPlan.svg.import
new file mode 100644
index 0000000..988fb17
--- /dev/null
+++ b/addons/limboai/icons/BlackboardPlan.svg.import
@@ -0,0 +1,38 @@
+[remap]
+
+importer="texture"
+type="CompressedTexture2D"
+uid="uid://da8g4cn0050sn"
+path="res://.godot/imported/BlackboardPlan.svg-9029b7aa87de8b935d9cad63480a6a16.ctex"
+metadata={
+"has_editor_variant": true,
+"vram_texture": false
+}
+
+[deps]
+
+source_file="res://addons/limboai/icons/BlackboardPlan.svg"
+dest_files=["res://.godot/imported/BlackboardPlan.svg-9029b7aa87de8b935d9cad63480a6a16.ctex"]
+
+[params]
+
+compress/mode=0
+compress/high_quality=false
+compress/lossy_quality=0.7
+compress/hdr_compression=1
+compress/normal_map=0
+compress/channel_pack=0
+mipmaps/generate=false
+mipmaps/limit=-1
+roughness/mode=0
+roughness/src_normal=""
+process/fix_alpha_border=true
+process/premult_alpha=false
+process/normal_map_invert_y=false
+process/hdr_as_srgb=false
+process/hdr_clamp_exposure=false
+process/size_limit=0
+detect_3d/compress_to=1
+svg/scale=1.0
+editor/scale_with_editor_scale=true
+editor/convert_colors_with_editor_theme=true
diff --git a/addons/limboai/icons/LimboAI.svg b/addons/limboai/icons/LimboAI.svg
new file mode 100644
index 0000000..54b042a
--- /dev/null
+++ b/addons/limboai/icons/LimboAI.svg
@@ -0,0 +1 @@
+
\ No newline at end of file
diff --git a/addons/limboai/icons/LimboAI.svg.import b/addons/limboai/icons/LimboAI.svg.import
new file mode 100644
index 0000000..d917302
--- /dev/null
+++ b/addons/limboai/icons/LimboAI.svg.import
@@ -0,0 +1,38 @@
+[remap]
+
+importer="texture"
+type="CompressedTexture2D"
+uid="uid://b3q678pf7g2tu"
+path="res://.godot/imported/LimboAI.svg-06efe3b51f2fc280e33c37672e174b5e.ctex"
+metadata={
+"has_editor_variant": true,
+"vram_texture": false
+}
+
+[deps]
+
+source_file="res://addons/limboai/icons/LimboAI.svg"
+dest_files=["res://.godot/imported/LimboAI.svg-06efe3b51f2fc280e33c37672e174b5e.ctex"]
+
+[params]
+
+compress/mode=0
+compress/high_quality=false
+compress/lossy_quality=0.7
+compress/hdr_compression=1
+compress/normal_map=0
+compress/channel_pack=0
+mipmaps/generate=false
+mipmaps/limit=-1
+roughness/mode=0
+roughness/src_normal=""
+process/fix_alpha_border=true
+process/premult_alpha=false
+process/normal_map_invert_y=false
+process/hdr_as_srgb=false
+process/hdr_clamp_exposure=false
+process/size_limit=0
+detect_3d/compress_to=1
+svg/scale=1.0
+editor/scale_with_editor_scale=true
+editor/convert_colors_with_editor_theme=true
diff --git a/addons/limboai/icons/LimboDeselectAll.svg b/addons/limboai/icons/LimboDeselectAll.svg
new file mode 100644
index 0000000..2047080
--- /dev/null
+++ b/addons/limboai/icons/LimboDeselectAll.svg
@@ -0,0 +1 @@
+
\ No newline at end of file
diff --git a/addons/limboai/icons/LimboDeselectAll.svg.import b/addons/limboai/icons/LimboDeselectAll.svg.import
new file mode 100644
index 0000000..ec71e0d
--- /dev/null
+++ b/addons/limboai/icons/LimboDeselectAll.svg.import
@@ -0,0 +1,38 @@
+[remap]
+
+importer="texture"
+type="CompressedTexture2D"
+uid="uid://csfkf3biw46fp"
+path="res://.godot/imported/LimboDeselectAll.svg-72ebb41c0238cae163a7bf3fc821e6ad.ctex"
+metadata={
+"has_editor_variant": true,
+"vram_texture": false
+}
+
+[deps]
+
+source_file="res://addons/limboai/icons/LimboDeselectAll.svg"
+dest_files=["res://.godot/imported/LimboDeselectAll.svg-72ebb41c0238cae163a7bf3fc821e6ad.ctex"]
+
+[params]
+
+compress/mode=0
+compress/high_quality=false
+compress/lossy_quality=0.7
+compress/hdr_compression=1
+compress/normal_map=0
+compress/channel_pack=0
+mipmaps/generate=false
+mipmaps/limit=-1
+roughness/mode=0
+roughness/src_normal=""
+process/fix_alpha_border=true
+process/premult_alpha=false
+process/normal_map_invert_y=false
+process/hdr_as_srgb=false
+process/hdr_clamp_exposure=false
+process/size_limit=0
+detect_3d/compress_to=1
+svg/scale=1.0
+editor/scale_with_editor_scale=true
+editor/convert_colors_with_editor_theme=true
diff --git a/addons/limboai/icons/LimboEditBlackboard.svg b/addons/limboai/icons/LimboEditBlackboard.svg
new file mode 100644
index 0000000..45ffb92
--- /dev/null
+++ b/addons/limboai/icons/LimboEditBlackboard.svg
@@ -0,0 +1 @@
+
\ No newline at end of file
diff --git a/addons/beehave/debug/icons/horizontal_layout.svg.import b/addons/limboai/icons/LimboEditBlackboard.svg.import
similarity index 69%
rename from addons/beehave/debug/icons/horizontal_layout.svg.import
rename to addons/limboai/icons/LimboEditBlackboard.svg.import
index 539e518..6bbe55f 100644
--- a/addons/beehave/debug/icons/horizontal_layout.svg.import
+++ b/addons/limboai/icons/LimboEditBlackboard.svg.import
@@ -2,8 +2,8 @@
importer="texture"
type="CompressedTexture2D"
-uid="uid://bah77esichnyx"
-path="res://.godot/imported/horizontal_layout.svg-d2a7af351e44f9bf61d0c938b6f47fac.ctex"
+uid="uid://clnqag811gu4w"
+path="res://.godot/imported/LimboEditBlackboard.svg-eacd7cf985d654974a99a4009ffcc125.ctex"
metadata={
"has_editor_variant": true,
"vram_texture": false
@@ -11,8 +11,8 @@ metadata={
[deps]
-source_file="res://addons/beehave/debug/icons/horizontal_layout.svg"
-dest_files=["res://.godot/imported/horizontal_layout.svg-d2a7af351e44f9bf61d0c938b6f47fac.ctex"]
+source_file="res://addons/limboai/icons/LimboEditBlackboard.svg"
+dest_files=["res://.godot/imported/LimboEditBlackboard.svg-eacd7cf985d654974a99a4009ffcc125.ctex"]
[params]
diff --git a/addons/limboai/icons/LimboExtraBlackboard.svg b/addons/limboai/icons/LimboExtraBlackboard.svg
new file mode 100644
index 0000000..09f6822
--- /dev/null
+++ b/addons/limboai/icons/LimboExtraBlackboard.svg
@@ -0,0 +1 @@
+
\ No newline at end of file
diff --git a/addons/limboai/icons/LimboExtraBlackboard.svg.import b/addons/limboai/icons/LimboExtraBlackboard.svg.import
new file mode 100644
index 0000000..992d540
--- /dev/null
+++ b/addons/limboai/icons/LimboExtraBlackboard.svg.import
@@ -0,0 +1,38 @@
+[remap]
+
+importer="texture"
+type="CompressedTexture2D"
+uid="uid://bbaenmxsx2edg"
+path="res://.godot/imported/LimboExtraBlackboard.svg-45ef3f1dea682b1da438186cfcc0f47b.ctex"
+metadata={
+"has_editor_variant": true,
+"vram_texture": false
+}
+
+[deps]
+
+source_file="res://addons/limboai/icons/LimboExtraBlackboard.svg"
+dest_files=["res://.godot/imported/LimboExtraBlackboard.svg-45ef3f1dea682b1da438186cfcc0f47b.ctex"]
+
+[params]
+
+compress/mode=0
+compress/high_quality=false
+compress/lossy_quality=0.7
+compress/hdr_compression=1
+compress/normal_map=0
+compress/channel_pack=0
+mipmaps/generate=false
+mipmaps/limit=-1
+roughness/mode=0
+roughness/src_normal=""
+process/fix_alpha_border=true
+process/premult_alpha=false
+process/normal_map_invert_y=false
+process/hdr_as_srgb=false
+process/hdr_clamp_exposure=false
+process/size_limit=0
+detect_3d/compress_to=1
+svg/scale=1.0
+editor/scale_with_editor_scale=true
+editor/convert_colors_with_editor_theme=true
diff --git a/addons/limboai/icons/LimboExtraClock.svg b/addons/limboai/icons/LimboExtraClock.svg
new file mode 100644
index 0000000..a3f536a
--- /dev/null
+++ b/addons/limboai/icons/LimboExtraClock.svg
@@ -0,0 +1 @@
+
\ No newline at end of file
diff --git a/addons/limboai/icons/LimboExtraClock.svg.import b/addons/limboai/icons/LimboExtraClock.svg.import
new file mode 100644
index 0000000..6479906
--- /dev/null
+++ b/addons/limboai/icons/LimboExtraClock.svg.import
@@ -0,0 +1,38 @@
+[remap]
+
+importer="texture"
+type="CompressedTexture2D"
+uid="uid://c7cd6u2p85lhm"
+path="res://.godot/imported/LimboExtraClock.svg-840321103249948265bce58e6fb69483.ctex"
+metadata={
+"has_editor_variant": true,
+"vram_texture": false
+}
+
+[deps]
+
+source_file="res://addons/limboai/icons/LimboExtraClock.svg"
+dest_files=["res://.godot/imported/LimboExtraClock.svg-840321103249948265bce58e6fb69483.ctex"]
+
+[params]
+
+compress/mode=0
+compress/high_quality=false
+compress/lossy_quality=0.7
+compress/hdr_compression=1
+compress/normal_map=0
+compress/channel_pack=0
+mipmaps/generate=false
+mipmaps/limit=-1
+roughness/mode=0
+roughness/src_normal=""
+process/fix_alpha_border=true
+process/premult_alpha=false
+process/normal_map_invert_y=false
+process/hdr_as_srgb=false
+process/hdr_clamp_exposure=false
+process/size_limit=0
+detect_3d/compress_to=1
+svg/scale=1.0
+editor/scale_with_editor_scale=true
+editor/convert_colors_with_editor_theme=true
diff --git a/addons/limboai/icons/LimboExtraVariable.svg b/addons/limboai/icons/LimboExtraVariable.svg
new file mode 100644
index 0000000..06780f0
--- /dev/null
+++ b/addons/limboai/icons/LimboExtraVariable.svg
@@ -0,0 +1 @@
+
\ No newline at end of file
diff --git a/addons/limboai/icons/LimboExtraVariable.svg.import b/addons/limboai/icons/LimboExtraVariable.svg.import
new file mode 100644
index 0000000..1c3a052
--- /dev/null
+++ b/addons/limboai/icons/LimboExtraVariable.svg.import
@@ -0,0 +1,38 @@
+[remap]
+
+importer="texture"
+type="CompressedTexture2D"
+uid="uid://djg50xv6xwyn0"
+path="res://.godot/imported/LimboExtraVariable.svg-dc718672cf9e469886aa48452fdda7b0.ctex"
+metadata={
+"has_editor_variant": true,
+"vram_texture": false
+}
+
+[deps]
+
+source_file="res://addons/limboai/icons/LimboExtraVariable.svg"
+dest_files=["res://.godot/imported/LimboExtraVariable.svg-dc718672cf9e469886aa48452fdda7b0.ctex"]
+
+[params]
+
+compress/mode=0
+compress/high_quality=false
+compress/lossy_quality=0.7
+compress/hdr_compression=1
+compress/normal_map=0
+compress/channel_pack=0
+mipmaps/generate=false
+mipmaps/limit=-1
+roughness/mode=0
+roughness/src_normal=""
+process/fix_alpha_border=true
+process/premult_alpha=false
+process/normal_map_invert_y=false
+process/hdr_as_srgb=false
+process/hdr_clamp_exposure=false
+process/size_limit=0
+detect_3d/compress_to=1
+svg/scale=1.0
+editor/scale_with_editor_scale=true
+editor/convert_colors_with_editor_theme=true
diff --git a/addons/limboai/icons/LimboExtractSubtree.svg b/addons/limboai/icons/LimboExtractSubtree.svg
new file mode 100644
index 0000000..c3c83a2
--- /dev/null
+++ b/addons/limboai/icons/LimboExtractSubtree.svg
@@ -0,0 +1 @@
+
\ No newline at end of file
diff --git a/addons/limboai/icons/LimboExtractSubtree.svg.import b/addons/limboai/icons/LimboExtractSubtree.svg.import
new file mode 100644
index 0000000..2d48302
--- /dev/null
+++ b/addons/limboai/icons/LimboExtractSubtree.svg.import
@@ -0,0 +1,38 @@
+[remap]
+
+importer="texture"
+type="CompressedTexture2D"
+uid="uid://6dfktfxplhiv"
+path="res://.godot/imported/LimboExtractSubtree.svg-84e8d198d3be4b2b8d625d3621368079.ctex"
+metadata={
+"has_editor_variant": true,
+"vram_texture": false
+}
+
+[deps]
+
+source_file="res://addons/limboai/icons/LimboExtractSubtree.svg"
+dest_files=["res://.godot/imported/LimboExtractSubtree.svg-84e8d198d3be4b2b8d625d3621368079.ctex"]
+
+[params]
+
+compress/mode=0
+compress/high_quality=false
+compress/lossy_quality=0.7
+compress/hdr_compression=1
+compress/normal_map=0
+compress/channel_pack=0
+mipmaps/generate=false
+mipmaps/limit=-1
+roughness/mode=0
+roughness/src_normal=""
+process/fix_alpha_border=true
+process/premult_alpha=false
+process/normal_map_invert_y=false
+process/hdr_as_srgb=false
+process/hdr_clamp_exposure=false
+process/size_limit=0
+detect_3d/compress_to=1
+svg/scale=1.0
+editor/scale_with_editor_scale=true
+editor/convert_colors_with_editor_theme=true
diff --git a/addons/limboai/icons/LimboHSM.svg b/addons/limboai/icons/LimboHSM.svg
new file mode 100644
index 0000000..095cfd4
--- /dev/null
+++ b/addons/limboai/icons/LimboHSM.svg
@@ -0,0 +1 @@
+
\ No newline at end of file
diff --git a/addons/limboai/icons/LimboHSM.svg.import b/addons/limboai/icons/LimboHSM.svg.import
new file mode 100644
index 0000000..bc99bfd
--- /dev/null
+++ b/addons/limboai/icons/LimboHSM.svg.import
@@ -0,0 +1,38 @@
+[remap]
+
+importer="texture"
+type="CompressedTexture2D"
+uid="uid://d2ooysh3or7tt"
+path="res://.godot/imported/LimboHSM.svg-28cca67d246d589dd15402abd78a1ec2.ctex"
+metadata={
+"has_editor_variant": true,
+"vram_texture": false
+}
+
+[deps]
+
+source_file="res://addons/limboai/icons/LimboHSM.svg"
+dest_files=["res://.godot/imported/LimboHSM.svg-28cca67d246d589dd15402abd78a1ec2.ctex"]
+
+[params]
+
+compress/mode=0
+compress/high_quality=false
+compress/lossy_quality=0.7
+compress/hdr_compression=1
+compress/normal_map=0
+compress/channel_pack=0
+mipmaps/generate=false
+mipmaps/limit=-1
+roughness/mode=0
+roughness/src_normal=""
+process/fix_alpha_border=true
+process/premult_alpha=false
+process/normal_map_invert_y=false
+process/hdr_as_srgb=false
+process/hdr_clamp_exposure=false
+process/size_limit=0
+detect_3d/compress_to=1
+svg/scale=1.0
+editor/scale_with_editor_scale=true
+editor/convert_colors_with_editor_theme=true
diff --git a/addons/limboai/icons/LimboPercent.svg b/addons/limboai/icons/LimboPercent.svg
new file mode 100644
index 0000000..8f60917
--- /dev/null
+++ b/addons/limboai/icons/LimboPercent.svg
@@ -0,0 +1 @@
+
\ No newline at end of file
diff --git a/addons/limboai/icons/LimboPercent.svg.import b/addons/limboai/icons/LimboPercent.svg.import
new file mode 100644
index 0000000..b095d27
--- /dev/null
+++ b/addons/limboai/icons/LimboPercent.svg.import
@@ -0,0 +1,38 @@
+[remap]
+
+importer="texture"
+type="CompressedTexture2D"
+uid="uid://bx87b4peykvj5"
+path="res://.godot/imported/LimboPercent.svg-00733fc19fb3bbe7f8396b1f07a89da0.ctex"
+metadata={
+"has_editor_variant": true,
+"vram_texture": false
+}
+
+[deps]
+
+source_file="res://addons/limboai/icons/LimboPercent.svg"
+dest_files=["res://.godot/imported/LimboPercent.svg-00733fc19fb3bbe7f8396b1f07a89da0.ctex"]
+
+[params]
+
+compress/mode=0
+compress/high_quality=false
+compress/lossy_quality=0.7
+compress/hdr_compression=1
+compress/normal_map=0
+compress/channel_pack=0
+mipmaps/generate=false
+mipmaps/limit=-1
+roughness/mode=0
+roughness/src_normal=""
+process/fix_alpha_border=true
+process/premult_alpha=false
+process/normal_map_invert_y=false
+process/hdr_as_srgb=false
+process/hdr_clamp_exposure=false
+process/size_limit=0
+detect_3d/compress_to=1
+svg/scale=1.0
+editor/scale_with_editor_scale=true
+editor/convert_colors_with_editor_theme=true
diff --git a/addons/limboai/icons/LimboSelectAll.svg b/addons/limboai/icons/LimboSelectAll.svg
new file mode 100644
index 0000000..fd3df37
--- /dev/null
+++ b/addons/limboai/icons/LimboSelectAll.svg
@@ -0,0 +1 @@
+
\ No newline at end of file
diff --git a/addons/limboai/icons/LimboSelectAll.svg.import b/addons/limboai/icons/LimboSelectAll.svg.import
new file mode 100644
index 0000000..f4ed2f5
--- /dev/null
+++ b/addons/limboai/icons/LimboSelectAll.svg.import
@@ -0,0 +1,38 @@
+[remap]
+
+importer="texture"
+type="CompressedTexture2D"
+uid="uid://dyykkyd3ghmfj"
+path="res://.godot/imported/LimboSelectAll.svg-db7b91d0d0b530b8e41c9d3772e60fab.ctex"
+metadata={
+"has_editor_variant": true,
+"vram_texture": false
+}
+
+[deps]
+
+source_file="res://addons/limboai/icons/LimboSelectAll.svg"
+dest_files=["res://.godot/imported/LimboSelectAll.svg-db7b91d0d0b530b8e41c9d3772e60fab.ctex"]
+
+[params]
+
+compress/mode=0
+compress/high_quality=false
+compress/lossy_quality=0.7
+compress/hdr_compression=1
+compress/normal_map=0
+compress/channel_pack=0
+mipmaps/generate=false
+mipmaps/limit=-1
+roughness/mode=0
+roughness/src_normal=""
+process/fix_alpha_border=true
+process/premult_alpha=false
+process/normal_map_invert_y=false
+process/hdr_as_srgb=false
+process/hdr_clamp_exposure=false
+process/size_limit=0
+detect_3d/compress_to=1
+svg/scale=1.0
+editor/scale_with_editor_scale=true
+editor/convert_colors_with_editor_theme=true
diff --git a/addons/limboai/icons/LimboState.svg b/addons/limboai/icons/LimboState.svg
new file mode 100644
index 0000000..dd8e765
--- /dev/null
+++ b/addons/limboai/icons/LimboState.svg
@@ -0,0 +1 @@
+
\ No newline at end of file
diff --git a/addons/limboai/icons/LimboState.svg.import b/addons/limboai/icons/LimboState.svg.import
new file mode 100644
index 0000000..d4f0de7
--- /dev/null
+++ b/addons/limboai/icons/LimboState.svg.import
@@ -0,0 +1,38 @@
+[remap]
+
+importer="texture"
+type="CompressedTexture2D"
+uid="uid://uivr7a0a3col"
+path="res://.godot/imported/LimboState.svg-b1db06d5ed3101ee6256deae4330f6b7.ctex"
+metadata={
+"has_editor_variant": true,
+"vram_texture": false
+}
+
+[deps]
+
+source_file="res://addons/limboai/icons/LimboState.svg"
+dest_files=["res://.godot/imported/LimboState.svg-b1db06d5ed3101ee6256deae4330f6b7.ctex"]
+
+[params]
+
+compress/mode=0
+compress/high_quality=false
+compress/lossy_quality=0.7
+compress/hdr_compression=1
+compress/normal_map=0
+compress/channel_pack=0
+mipmaps/generate=false
+mipmaps/limit=-1
+roughness/mode=0
+roughness/src_normal=""
+process/fix_alpha_border=true
+process/premult_alpha=false
+process/normal_map_invert_y=false
+process/hdr_as_srgb=false
+process/hdr_clamp_exposure=false
+process/size_limit=0
+detect_3d/compress_to=1
+svg/scale=1.0
+editor/scale_with_editor_scale=true
+editor/convert_colors_with_editor_theme=true
diff --git a/addons/limboai/icons/LimboVarAdd.svg b/addons/limboai/icons/LimboVarAdd.svg
new file mode 100644
index 0000000..b2910a0
--- /dev/null
+++ b/addons/limboai/icons/LimboVarAdd.svg
@@ -0,0 +1 @@
+
\ No newline at end of file
diff --git a/addons/limboai/icons/LimboVarAdd.svg.import b/addons/limboai/icons/LimboVarAdd.svg.import
new file mode 100644
index 0000000..b41738c
--- /dev/null
+++ b/addons/limboai/icons/LimboVarAdd.svg.import
@@ -0,0 +1,38 @@
+[remap]
+
+importer="texture"
+type="CompressedTexture2D"
+uid="uid://k4ruk0fw1n35"
+path="res://.godot/imported/LimboVarAdd.svg-101bcdd036315254e4b61e13747c0788.ctex"
+metadata={
+"has_editor_variant": true,
+"vram_texture": false
+}
+
+[deps]
+
+source_file="res://addons/limboai/icons/LimboVarAdd.svg"
+dest_files=["res://.godot/imported/LimboVarAdd.svg-101bcdd036315254e4b61e13747c0788.ctex"]
+
+[params]
+
+compress/mode=0
+compress/high_quality=false
+compress/lossy_quality=0.7
+compress/hdr_compression=1
+compress/normal_map=0
+compress/channel_pack=0
+mipmaps/generate=false
+mipmaps/limit=-1
+roughness/mode=0
+roughness/src_normal=""
+process/fix_alpha_border=true
+process/premult_alpha=false
+process/normal_map_invert_y=false
+process/hdr_as_srgb=false
+process/hdr_clamp_exposure=false
+process/size_limit=0
+detect_3d/compress_to=1
+svg/scale=1.0
+editor/scale_with_editor_scale=true
+editor/convert_colors_with_editor_theme=true
diff --git a/addons/limboai/icons/LimboVarEmpty.svg b/addons/limboai/icons/LimboVarEmpty.svg
new file mode 100644
index 0000000..24f5088
--- /dev/null
+++ b/addons/limboai/icons/LimboVarEmpty.svg
@@ -0,0 +1 @@
+
\ No newline at end of file
diff --git a/addons/limboai/icons/LimboVarEmpty.svg.import b/addons/limboai/icons/LimboVarEmpty.svg.import
new file mode 100644
index 0000000..2859e85
--- /dev/null
+++ b/addons/limboai/icons/LimboVarEmpty.svg.import
@@ -0,0 +1,38 @@
+[remap]
+
+importer="texture"
+type="CompressedTexture2D"
+uid="uid://20oknalxjvaw"
+path="res://.godot/imported/LimboVarEmpty.svg-3014256fb5cd566cab45b3327d98988d.ctex"
+metadata={
+"has_editor_variant": true,
+"vram_texture": false
+}
+
+[deps]
+
+source_file="res://addons/limboai/icons/LimboVarEmpty.svg"
+dest_files=["res://.godot/imported/LimboVarEmpty.svg-3014256fb5cd566cab45b3327d98988d.ctex"]
+
+[params]
+
+compress/mode=0
+compress/high_quality=false
+compress/lossy_quality=0.7
+compress/hdr_compression=1
+compress/normal_map=0
+compress/channel_pack=0
+mipmaps/generate=false
+mipmaps/limit=-1
+roughness/mode=0
+roughness/src_normal=""
+process/fix_alpha_border=true
+process/premult_alpha=false
+process/normal_map_invert_y=false
+process/hdr_as_srgb=false
+process/hdr_clamp_exposure=false
+process/size_limit=0
+detect_3d/compress_to=1
+svg/scale=1.0
+editor/scale_with_editor_scale=true
+editor/convert_colors_with_editor_theme=true
diff --git a/addons/limboai/icons/LimboVarError.svg b/addons/limboai/icons/LimboVarError.svg
new file mode 100644
index 0000000..563d762
--- /dev/null
+++ b/addons/limboai/icons/LimboVarError.svg
@@ -0,0 +1 @@
+
\ No newline at end of file
diff --git a/addons/limboai/icons/LimboVarError.svg.import b/addons/limboai/icons/LimboVarError.svg.import
new file mode 100644
index 0000000..9766bcb
--- /dev/null
+++ b/addons/limboai/icons/LimboVarError.svg.import
@@ -0,0 +1,38 @@
+[remap]
+
+importer="texture"
+type="CompressedTexture2D"
+uid="uid://qrnphdbypssb"
+path="res://.godot/imported/LimboVarError.svg-d9f1ab3e5b2cbb6e0013b65ddb23c1cf.ctex"
+metadata={
+"has_editor_variant": true,
+"vram_texture": false
+}
+
+[deps]
+
+source_file="res://addons/limboai/icons/LimboVarError.svg"
+dest_files=["res://.godot/imported/LimboVarError.svg-d9f1ab3e5b2cbb6e0013b65ddb23c1cf.ctex"]
+
+[params]
+
+compress/mode=0
+compress/high_quality=false
+compress/lossy_quality=0.7
+compress/hdr_compression=1
+compress/normal_map=0
+compress/channel_pack=0
+mipmaps/generate=false
+mipmaps/limit=-1
+roughness/mode=0
+roughness/src_normal=""
+process/fix_alpha_border=true
+process/premult_alpha=false
+process/normal_map_invert_y=false
+process/hdr_as_srgb=false
+process/hdr_clamp_exposure=false
+process/size_limit=0
+detect_3d/compress_to=1
+svg/scale=1.0
+editor/scale_with_editor_scale=true
+editor/convert_colors_with_editor_theme=true
diff --git a/addons/limboai/icons/LimboVarExists.svg b/addons/limboai/icons/LimboVarExists.svg
new file mode 100644
index 0000000..3509c64
--- /dev/null
+++ b/addons/limboai/icons/LimboVarExists.svg
@@ -0,0 +1 @@
+
\ No newline at end of file
diff --git a/addons/limboai/icons/LimboVarExists.svg.import b/addons/limboai/icons/LimboVarExists.svg.import
new file mode 100644
index 0000000..dd8e61e
--- /dev/null
+++ b/addons/limboai/icons/LimboVarExists.svg.import
@@ -0,0 +1,38 @@
+[remap]
+
+importer="texture"
+type="CompressedTexture2D"
+uid="uid://m7s14245qq8h"
+path="res://.godot/imported/LimboVarExists.svg-20d2e0b4a7a064b9c6d2cc44711570dd.ctex"
+metadata={
+"has_editor_variant": true,
+"vram_texture": false
+}
+
+[deps]
+
+source_file="res://addons/limboai/icons/LimboVarExists.svg"
+dest_files=["res://.godot/imported/LimboVarExists.svg-20d2e0b4a7a064b9c6d2cc44711570dd.ctex"]
+
+[params]
+
+compress/mode=0
+compress/high_quality=false
+compress/lossy_quality=0.7
+compress/hdr_compression=1
+compress/normal_map=0
+compress/channel_pack=0
+mipmaps/generate=false
+mipmaps/limit=-1
+roughness/mode=0
+roughness/src_normal=""
+process/fix_alpha_border=true
+process/premult_alpha=false
+process/normal_map_invert_y=false
+process/hdr_as_srgb=false
+process/hdr_clamp_exposure=false
+process/size_limit=0
+detect_3d/compress_to=1
+svg/scale=1.0
+editor/scale_with_editor_scale=true
+editor/convert_colors_with_editor_theme=true
diff --git a/addons/limboai/icons/LimboVarNotFound.svg b/addons/limboai/icons/LimboVarNotFound.svg
new file mode 100644
index 0000000..049f6cf
--- /dev/null
+++ b/addons/limboai/icons/LimboVarNotFound.svg
@@ -0,0 +1 @@
+
\ No newline at end of file
diff --git a/addons/limboai/icons/LimboVarNotFound.svg.import b/addons/limboai/icons/LimboVarNotFound.svg.import
new file mode 100644
index 0000000..477e25d
--- /dev/null
+++ b/addons/limboai/icons/LimboVarNotFound.svg.import
@@ -0,0 +1,38 @@
+[remap]
+
+importer="texture"
+type="CompressedTexture2D"
+uid="uid://3ukat7iyidi0"
+path="res://.godot/imported/LimboVarNotFound.svg-fce88dc2c01e17a54455124e43955f9d.ctex"
+metadata={
+"has_editor_variant": true,
+"vram_texture": false
+}
+
+[deps]
+
+source_file="res://addons/limboai/icons/LimboVarNotFound.svg"
+dest_files=["res://.godot/imported/LimboVarNotFound.svg-fce88dc2c01e17a54455124e43955f9d.ctex"]
+
+[params]
+
+compress/mode=0
+compress/high_quality=false
+compress/lossy_quality=0.7
+compress/hdr_compression=1
+compress/normal_map=0
+compress/channel_pack=0
+mipmaps/generate=false
+mipmaps/limit=-1
+roughness/mode=0
+roughness/src_normal=""
+process/fix_alpha_border=true
+process/premult_alpha=false
+process/normal_map_invert_y=false
+process/hdr_as_srgb=false
+process/hdr_clamp_exposure=false
+process/size_limit=0
+detect_3d/compress_to=1
+svg/scale=1.0
+editor/scale_with_editor_scale=true
+editor/convert_colors_with_editor_theme=true
diff --git a/addons/limboai/icons/LimboVarPrivate.svg b/addons/limboai/icons/LimboVarPrivate.svg
new file mode 100644
index 0000000..87b2c0f
--- /dev/null
+++ b/addons/limboai/icons/LimboVarPrivate.svg
@@ -0,0 +1 @@
+
\ No newline at end of file
diff --git a/addons/limboai/icons/LimboVarPrivate.svg.import b/addons/limboai/icons/LimboVarPrivate.svg.import
new file mode 100644
index 0000000..c8b0a37
--- /dev/null
+++ b/addons/limboai/icons/LimboVarPrivate.svg.import
@@ -0,0 +1,38 @@
+[remap]
+
+importer="texture"
+type="CompressedTexture2D"
+uid="uid://cobsj3qjdg8ot"
+path="res://.godot/imported/LimboVarPrivate.svg-99b4229567f7f98cdabf892099c91da2.ctex"
+metadata={
+"has_editor_variant": true,
+"vram_texture": false
+}
+
+[deps]
+
+source_file="res://addons/limboai/icons/LimboVarPrivate.svg"
+dest_files=["res://.godot/imported/LimboVarPrivate.svg-99b4229567f7f98cdabf892099c91da2.ctex"]
+
+[params]
+
+compress/mode=0
+compress/high_quality=false
+compress/lossy_quality=0.7
+compress/hdr_compression=1
+compress/normal_map=0
+compress/channel_pack=0
+mipmaps/generate=false
+mipmaps/limit=-1
+roughness/mode=0
+roughness/src_normal=""
+process/fix_alpha_border=true
+process/premult_alpha=false
+process/normal_map_invert_y=false
+process/hdr_as_srgb=false
+process/hdr_clamp_exposure=false
+process/size_limit=0
+detect_3d/compress_to=1
+svg/scale=1.0
+editor/scale_with_editor_scale=true
+editor/convert_colors_with_editor_theme=true
diff --git a/addons/limboai/version.txt b/addons/limboai/version.txt
new file mode 100644
index 0000000..0d0c52f
--- /dev/null
+++ b/addons/limboai/version.txt
@@ -0,0 +1 @@
+v1.4.0
diff --git a/config/character/bullet01.tres b/config/character/bullet01.tres
index 2fbabc2..4ef1195 100644
--- a/config/character/bullet01.tres
+++ b/config/character/bullet01.tres
@@ -1,6 +1,7 @@
-[gd_resource type="Resource" script_class="CharacterCfg" load_steps=8 format=3 uid="uid://efaynwj7143w"]
+[gd_resource type="Resource" script_class="CharacterCfg" load_steps=9 format=3 uid="uid://efaynwj7143w"]
[ext_resource type="Resource" uid="uid://ctbdt77yyubxn" path="res://config/attack/blunt_normal_hit_up.tres" id="1_4vq22"]
+[ext_resource type="BehaviorTree" uid="uid://qsepxhwekky1" path="res://resource/ai/bullet_simple.tres" id="1_tm3sl"]
[ext_resource type="Resource" uid="uid://bhxq1uffxyda8" path="res://config/attack_box/circle_normal_thin.tres" id="2_ewiqr"]
[ext_resource type="Resource" uid="uid://dpajmgrlaytah" path="res://config/character_mp/normal.tres" id="2_hrxfp"]
[ext_resource type="Resource" uid="uid://iv8g1x3bkxvv" path="res://config/character_move/fly_fast.tres" id="3_gqffj"]
@@ -18,6 +19,7 @@ move = ExtResource("3_gqffj")
shield = ExtResource("4_qnn3b")
stun = ExtResource("6_y4hsh")
mp = ExtResource("2_hrxfp")
+ai_behavior_tree = ExtResource("1_tm3sl")
hp_max = 100.0
attack = 10.0
attack1 = ExtResource("1_4vq22")
diff --git a/config/character/bullet_hero01_long_stab.tres b/config/character/bullet_hero01_long_stab.tres
index 03c49de..c6a9810 100644
--- a/config/character/bullet_hero01_long_stab.tres
+++ b/config/character/bullet_hero01_long_stab.tres
@@ -1,6 +1,6 @@
[gd_resource type="Resource" script_class="CharacterCfg" load_steps=10 format=3 uid="uid://rxt1emwats2v"]
-[ext_resource type="PackedScene" uid="uid://tr65aikkpp2e" path="res://scene/ai/bullet_simple_penetrat.tscn" id="1_70j82"]
+[ext_resource type="BehaviorTree" uid="uid://qsepxhwekky1" path="res://resource/ai/bullet_simple.tres" id="1_2lpps"]
[ext_resource type="Resource" uid="uid://dmfr73m28vsqj" path="res://config/attack/sharp_normal_hit_back_hard.tres" id="2_70j82"]
[ext_resource type="Resource" uid="uid://decgfcx2xsj8i" path="res://config/attack_box/circle_mid.tres" id="3_6gt06"]
[ext_resource type="Resource" uid="uid://cw7rb4rlfw33q" path="res://config/attack/sharp_heavy_hit_back.tres" id="4_2lpps"]
@@ -20,7 +20,7 @@ move = ExtResource("4_70j82")
shield = ExtResource("7_iotq2")
stun = ExtResource("8_euuy0")
mp = ExtResource("5_1lrf8")
-ai_behavior_tree = ExtResource("1_70j82")
+ai_behavior_tree = ExtResource("1_2lpps")
hp_max = 100.0
attack = 1.0
attack1 = ExtResource("2_70j82")
diff --git a/config/character/bullet_hero01_short_stab01.tres b/config/character/bullet_hero01_short_stab01.tres
index 715d6fe..a9d9679 100644
--- a/config/character/bullet_hero01_short_stab01.tres
+++ b/config/character/bullet_hero01_short_stab01.tres
@@ -1,6 +1,6 @@
[gd_resource type="Resource" script_class="CharacterCfg" load_steps=9 format=3 uid="uid://cb4q16lmqwbin"]
-[ext_resource type="PackedScene" uid="uid://bei75ysjq2pi4" path="res://scene/ai/bullet_simple.tscn" id="1_3q8i1"]
+[ext_resource type="BehaviorTree" uid="uid://qsepxhwekky1" path="res://resource/ai/bullet_simple.tres" id="1_3q8i1"]
[ext_resource type="Resource" uid="uid://d3mcp8sf6qbmd" path="res://config/attack/sharp_normal_hit.tres" id="2_3q8i1"]
[ext_resource type="Resource" uid="uid://decgfcx2xsj8i" path="res://config/attack_box/circle_mid.tres" id="3_3q8i1"]
[ext_resource type="Resource" uid="uid://iv8g1x3bkxvv" path="res://config/character_move/fly_fast.tres" id="4_2bsgq"]
diff --git a/config/character/bullet_hero01_soul_hit01.tres b/config/character/bullet_hero01_soul_hit01.tres
index c41e3f7..d1bcd87 100644
--- a/config/character/bullet_hero01_soul_hit01.tres
+++ b/config/character/bullet_hero01_soul_hit01.tres
@@ -1,7 +1,7 @@
[gd_resource type="Resource" script_class="CharacterCfg" load_steps=9 format=3 uid="uid://d3mafsovw1mko"]
[ext_resource type="Resource" uid="uid://ckbf40c75bfqf" path="res://config/attack/sharp_normal_hit_up.tres" id="1_at6jo"]
-[ext_resource type="PackedScene" uid="uid://bei75ysjq2pi4" path="res://scene/ai/bullet_simple.tscn" id="1_m7qit"]
+[ext_resource type="BehaviorTree" uid="uid://qsepxhwekky1" path="res://resource/ai/bullet_simple.tres" id="1_m7qit"]
[ext_resource type="Resource" uid="uid://bld0vhuhgydm8" path="res://config/attack_box/direct.tres" id="2_780us"]
[ext_resource type="Resource" uid="uid://iv8g1x3bkxvv" path="res://config/character_move/fly_fast.tres" id="3_cx00u"]
[ext_resource type="Resource" uid="uid://dpajmgrlaytah" path="res://config/character_mp/normal.tres" id="4_alws1"]
diff --git a/config/character/monster02.tres b/config/character/monster02.tres
index 89cbebb..c159b76 100644
--- a/config/character/monster02.tres
+++ b/config/character/monster02.tres
@@ -1,8 +1,9 @@
-[gd_resource type="Resource" script_class="CharacterCfg" load_steps=8 format=3 uid="uid://dmfh54jffhx28"]
+[gd_resource type="Resource" script_class="CharacterCfg" load_steps=9 format=3 uid="uid://dmfh54jffhx28"]
[ext_resource type="Resource" uid="uid://dkjv5kj8mgy8v" path="res://config/character_move/slow.tres" id="1_tsstu"]
[ext_resource type="Resource" uid="uid://b26gc616anvo1" path="res://config/character_ai/normal.tres" id="1_vfyb7"]
-[ext_resource type="Script" path="res://script/config/character_cfg.gd" id="1_wkjce"]
+[ext_resource type="Script" uid="uid://dt3chi1tgnaef" path="res://script/config/character_cfg.gd" id="1_wkjce"]
+[ext_resource type="BehaviorTree" uid="uid://c8mhxoxifvt13" path="res://resource/ai/monster_simple.tres" id="2_24hy6"]
[ext_resource type="Resource" uid="uid://dpajmgrlaytah" path="res://config/character_mp/normal.tres" id="2_gly3h"]
[ext_resource type="SpriteFrames" uid="uid://crdd52skym3ir" path="res://resource/animation/character/monster02_move.aseprite" id="2_h60bf"]
[ext_resource type="Resource" uid="uid://h1curvk64vm3" path="res://config/character_shield/none.tres" id="4_uyg17"]
@@ -20,6 +21,9 @@ shield = ExtResource("4_uyg17")
stun = ExtResource("6_vlmkd")
mp = ExtResource("2_gly3h")
ai = ExtResource("1_vfyb7")
+ai_behavior_tree = ExtResource("2_24hy6")
hp_max = 50.0
attack = 10.0
sub_character_auto_create = false
+material_on = 0
+material_off = 0
diff --git a/config/character/monster03.tres b/config/character/monster03.tres
index dba680b..afe8961 100644
--- a/config/character/monster03.tres
+++ b/config/character/monster03.tres
@@ -1,9 +1,10 @@
-[gd_resource type="Resource" script_class="CharacterCfg" load_steps=8 format=3 uid="uid://c4v710n3f6pb3"]
+[gd_resource type="Resource" script_class="CharacterCfg" load_steps=9 format=3 uid="uid://c4v710n3f6pb3"]
[ext_resource type="Resource" uid="uid://b26gc616anvo1" path="res://config/character_ai/normal.tres" id="1_lr20m"]
[ext_resource type="Resource" uid="uid://dx54fjf5t0uu8" path="res://config/character_move/normal.tres" id="1_ol2gy"]
[ext_resource type="Resource" uid="uid://dpajmgrlaytah" path="res://config/character_mp/normal.tres" id="2_kkpsf"]
-[ext_resource type="Script" path="res://script/config/character_cfg.gd" id="3_0gem5"]
+[ext_resource type="BehaviorTree" uid="uid://c8mhxoxifvt13" path="res://resource/ai/monster_simple.tres" id="2_pyyy3"]
+[ext_resource type="Script" uid="uid://dt3chi1tgnaef" path="res://script/config/character_cfg.gd" id="3_0gem5"]
[ext_resource type="Resource" uid="uid://h1curvk64vm3" path="res://config/character_shield/none.tres" id="5_2xoig"]
[ext_resource type="SpriteFrames" uid="uid://bvcrc6bbufwqv" path="res://resource/animation/character/monster03_move.aseprite" id="5_4dnud"]
[ext_resource type="Resource" uid="uid://cac6mk6g078vn" path="res://config/character_stun/normal.tres" id="6_ar00t"]
@@ -20,6 +21,7 @@ shield = ExtResource("5_2xoig")
stun = ExtResource("6_ar00t")
mp = ExtResource("2_kkpsf")
ai = ExtResource("1_lr20m")
+ai_behavior_tree = ExtResource("2_pyyy3")
hp_max = 1000.0
attack = 10.0
sub_character_auto_create = false
diff --git a/project.godot b/project.godot
index 8773bb4..e165f69 100644
--- a/project.godot
+++ b/project.godot
@@ -37,8 +37,6 @@ Setting="*res://script/_global/setting.gd"
Enum="*res://script/_global/enum.gd"
Util="*res://script/_global/util.gd"
Global="*res://script/_global/global.gd"
-BeehaveGlobalMetrics="*res://addons/beehave/metrics/beehave_global_metrics.gd"
-BeehaveGlobalDebugger="*res://addons/beehave/debug/global_debugger.gd"
[display]
@@ -54,7 +52,7 @@ import/use_multiple_threads=false
[editor_plugins]
-enabled=PackedStringArray("res://addons/MagicaVoxel_Importer_with_Extensions/plugin.cfg", "res://addons/beehave/plugin.cfg", "res://addons/editor_menu_tools/plugin.cfg", "res://addons/nklbdev.aseprite_importers/plugin.cfg", "res://addons/resources_spreadsheet_view/plugin.cfg")
+enabled=PackedStringArray("res://addons/MagicaVoxel_Importer_with_Extensions/plugin.cfg", "res://addons/editor_menu_tools/plugin.cfg", "res://addons/nklbdev.aseprite_importers/plugin.cfg", "res://addons/resources_spreadsheet_view/plugin.cfg")
[file_customization]
@@ -246,6 +244,11 @@ test_3={
3d_physics/layer_2="角色"
3d_physics/layer_3="攻击框"
+[limbo_ai]
+
+behavior_tree/behavior_tree_default_dir="res://resource/ai"
+behavior_tree/user_task_dirs=PackedStringArray("res://script/ai")
+
[memory]
limits/message_queue/max_size_mb=2048
@@ -258,6 +261,8 @@ settings_file="res://setting/MetSysSettings.tres"
[physics]
3d/physics_engine="Jolt Physics"
+jolt_physics_3d/simulation/velocity_steps=2
+jolt_physics_3d/simulation/position_steps=1
[rendering]
diff --git a/resource/ai/bullet_simple.tres b/resource/ai/bullet_simple.tres
new file mode 100644
index 0000000..cc7317e
--- /dev/null
+++ b/resource/ai/bullet_simple.tres
@@ -0,0 +1,46 @@
+[gd_resource type="BehaviorTree" load_steps=16 format=3 uid="uid://qsepxhwekky1"]
+
+[ext_resource type="Script" uid="uid://ddcaceywxwt20" path="res://script/ai/action/action_attack1.gd" id="1_0ynsb"]
+[ext_resource type="Script" uid="uid://bhxaiqao7nkth" path="res://script/ai/action/action_check_hit_wall.gd" id="2_3rkyj"]
+[ext_resource type="Script" uid="uid://ci3tg5fkdn16f" path="res://script/ai/action/action_destroy.gd" id="3_h6iow"]
+[ext_resource type="Script" uid="uid://b3ulieg4i8ivy" path="res://script/ai/action/action_check_hit_character.gd" id="4_3rkyj"]
+
+[sub_resource type="BlackboardPlan" id="BlackboardPlan_0ottm"]
+
+[sub_resource type="BTAction" id="BTAction_4hjwu"]
+script = ExtResource("1_0ynsb")
+
+[sub_resource type="BTCooldown" id="BTCooldown_amj7r"]
+duration = 0.1
+children = [SubResource("BTAction_4hjwu")]
+
+[sub_resource type="BTSequence" id="BTSequence_4w0g7"]
+custom_name = "持续伤害"
+children = [SubResource("BTCooldown_amj7r")]
+
+[sub_resource type="BTAction" id="BTAction_8pno7"]
+script = ExtResource("2_3rkyj")
+
+[sub_resource type="BTAction" id="BTAction_sr08j"]
+script = ExtResource("3_h6iow")
+
+[sub_resource type="BTSequence" id="BTSequence_4uwjs"]
+custom_name = "撞墙销毁"
+children = [SubResource("BTAction_8pno7"), SubResource("BTAction_sr08j")]
+
+[sub_resource type="BTAction" id="BTAction_h6iow"]
+script = ExtResource("4_3rkyj")
+
+[sub_resource type="BTAction" id="BTAction_amj7r"]
+script = ExtResource("3_h6iow")
+
+[sub_resource type="BTSequence" id="BTSequence_8pno7"]
+custom_name = "命中销毁"
+children = [SubResource("BTAction_h6iow"), SubResource("BTAction_amj7r")]
+
+[sub_resource type="BTSelector" id="BTSelector_qk181"]
+children = [SubResource("BTSequence_4w0g7"), SubResource("BTSequence_4uwjs"), SubResource("BTSequence_8pno7")]
+
+[resource]
+blackboard_plan = SubResource("BlackboardPlan_0ottm")
+root_task = SubResource("BTSelector_qk181")
diff --git a/resource/ai/monster_simple.tres b/resource/ai/monster_simple.tres
new file mode 100644
index 0000000..c53d3cf
--- /dev/null
+++ b/resource/ai/monster_simple.tres
@@ -0,0 +1,47 @@
+[gd_resource type="BehaviorTree" load_steps=16 format=3 uid="uid://c8mhxoxifvt13"]
+
+[ext_resource type="Script" uid="uid://bobc3700ee75e" path="res://script/ai/action/action_stop_move.gd" id="1_blmqi"]
+[ext_resource type="Script" uid="uid://c0cjruogr8531" path="res://script/ai/action_check/action_alert_check.gd" id="1_u6xvt"]
+[ext_resource type="Script" uid="uid://d1cbkwu2v41cf" path="res://script/ai/action/action_find_target.gd" id="3_8escq"]
+[ext_resource type="Script" uid="uid://dq21r8kmyo51u" path="res://script/ai/action_with_target/action_move_to.gd" id="4_8jf26"]
+
+[sub_resource type="BlackboardPlan" id="BlackboardPlan_bbst0"]
+
+[sub_resource type="BTAction" id="BTAction_8escq"]
+script = ExtResource("1_u6xvt")
+key = 0
+is_alert = false
+
+[sub_resource type="BTRandomWait" id="BTRandomWait_blmqi"]
+
+[sub_resource type="BTAction" id="BTAction_xg6qs"]
+script = ExtResource("1_blmqi")
+
+[sub_resource type="BTSequence" id="BTSequence_8jf26"]
+children = [SubResource("BTAction_8escq"), SubResource("BTRandomWait_blmqi"), SubResource("BTAction_xg6qs")]
+
+[sub_resource type="BTAction" id="BTAction_3muay"]
+script = ExtResource("1_u6xvt")
+key = 0
+is_alert = true
+
+[sub_resource type="BTRandomWait" id="BTRandomWait_u6xvt"]
+
+[sub_resource type="BTAction" id="BTAction_mskgw"]
+script = ExtResource("3_8escq")
+
+[sub_resource type="BTAction" id="BTAction_kgxy5"]
+script = ExtResource("4_8jf26")
+dist_min = 0.0
+dist_max = 1.0
+offset = 0.1
+
+[sub_resource type="BTSequence" id="BTSequence_mskgw"]
+children = [SubResource("BTAction_3muay"), SubResource("BTRandomWait_u6xvt"), SubResource("BTAction_mskgw"), SubResource("BTAction_kgxy5")]
+
+[sub_resource type="BTSelector" id="BTSelector_by72h"]
+children = [SubResource("BTSequence_8jf26"), SubResource("BTSequence_mskgw")]
+
+[resource]
+blackboard_plan = SubResource("BlackboardPlan_bbst0")
+root_task = SubResource("BTSelector_by72h")
diff --git a/scene/ai/bullet_simple.tscn b/scene/ai/bullet_simple.tscn
deleted file mode 100644
index 1d3f552..0000000
--- a/scene/ai/bullet_simple.tscn
+++ /dev/null
@@ -1,59 +0,0 @@
-[gd_scene load_steps=9 format=3 uid="uid://bei75ysjq2pi4"]
-
-[ext_resource type="Script" uid="uid://mvwcxqcetiqp" path="res://addons/beehave/nodes/beehave_tree.gd" id="1_7oi2o"]
-[ext_resource type="Script" uid="uid://dcqq2mursvw5m" path="res://addons/beehave/nodes/decorators/succeeder.gd" id="3_08et5"]
-[ext_resource type="Script" uid="uid://cugftmuc8v30c" path="res://addons/beehave/nodes/composites/sequence.gd" id="3_i33jf"]
-[ext_resource type="Script" uid="uid://csd1yh0ruy3yu" path="res://script/ai/action/action_wait_tick.gd" id="3_qy88u"]
-[ext_resource type="Script" uid="uid://b3ulieg4i8ivy" path="res://script/ai/action/action_check_hit_character.gd" id="6_jq3ry"]
-[ext_resource type="Script" uid="uid://ddcaceywxwt20" path="res://script/ai/action/action_attack1.gd" id="6_oqib4"]
-[ext_resource type="Script" uid="uid://bhxaiqao7nkth" path="res://script/ai/action/action_check_hit_wall.gd" id="8_qnf6p"]
-[ext_resource type="Script" uid="uid://ci3tg5fkdn16f" path="res://script/ai/action/action_destroy.gd" id="11_i4mx4"]
-
-[node name="BeehaveTree" type="Node" node_paths=PackedStringArray("blackboard")]
-script = ExtResource("1_7oi2o")
-blackboard = NodePath("@Node@25152")
-
-[node name="SequenceComposite" type="Node" parent="."]
-script = ExtResource("3_i33jf")
-
-[node name="AlwaysSucceedDecorator" type="Node" parent="SequenceComposite"]
-script = ExtResource("3_08et5")
-metadata/_custom_type_script = ExtResource("3_08et5")
-
-[node name="保持攻击" type="Node" parent="SequenceComposite/AlwaysSucceedDecorator"]
-script = ExtResource("3_i33jf")
-
-[node name="ActionWaitTick" type="Node" parent="SequenceComposite/AlwaysSucceedDecorator/保持攻击"]
-script = ExtResource("3_qy88u")
-metadata/_custom_type_script = ExtResource("3_qy88u")
-
-[node name="ActionAttack1" type="Node" parent="SequenceComposite/AlwaysSucceedDecorator/保持攻击"]
-script = ExtResource("6_oqib4")
-
-[node name="AlwaysSucceedDecorator2" type="Node" parent="SequenceComposite"]
-script = ExtResource("3_08et5")
-metadata/_custom_type_script = ExtResource("3_08et5")
-
-[node name="检测命中角色并销毁" type="Node" parent="SequenceComposite/AlwaysSucceedDecorator2"]
-script = ExtResource("3_i33jf")
-
-[node name="ActionCheckHitCharacter" type="Node" parent="SequenceComposite/AlwaysSucceedDecorator2/检测命中角色并销毁"]
-script = ExtResource("6_jq3ry")
-metadata/_custom_type_script = ExtResource("6_jq3ry")
-
-[node name="ActionDestroy" type="Node" parent="SequenceComposite/AlwaysSucceedDecorator2/检测命中角色并销毁"]
-script = ExtResource("11_i4mx4")
-
-[node name="AlwaysSucceedDecorator3" type="Node" parent="SequenceComposite"]
-script = ExtResource("3_08et5")
-metadata/_custom_type_script = ExtResource("3_08et5")
-
-[node name="检测命中墙壁并销毁" type="Node" parent="SequenceComposite/AlwaysSucceedDecorator3"]
-script = ExtResource("3_i33jf")
-
-[node name="ActionCheckHitWall" type="Node" parent="SequenceComposite/AlwaysSucceedDecorator3/检测命中墙壁并销毁"]
-script = ExtResource("8_qnf6p")
-metadata/_custom_type_script = ExtResource("8_qnf6p")
-
-[node name="ActionDestroy" type="Node" parent="SequenceComposite/AlwaysSucceedDecorator3/检测命中墙壁并销毁"]
-script = ExtResource("11_i4mx4")
diff --git a/scene/ai/bullet_simple_penetrat.tscn b/scene/ai/bullet_simple_penetrat.tscn
deleted file mode 100644
index 84ae2e6..0000000
--- a/scene/ai/bullet_simple_penetrat.tscn
+++ /dev/null
@@ -1,49 +0,0 @@
-[gd_scene load_steps=9 format=3 uid="uid://tr65aikkpp2e"]
-
-[ext_resource type="Script" uid="uid://mvwcxqcetiqp" path="res://addons/beehave/nodes/beehave_tree.gd" id="1_6wcp2"]
-[ext_resource type="Script" uid="uid://cugftmuc8v30c" path="res://addons/beehave/nodes/composites/sequence.gd" id="2_0p8p1"]
-[ext_resource type="Script" uid="uid://dcqq2mursvw5m" path="res://addons/beehave/nodes/decorators/succeeder.gd" id="3_irjra"]
-[ext_resource type="Script" uid="uid://csd1yh0ruy3yu" path="res://script/ai/action/action_wait_tick.gd" id="4_2fqct"]
-[ext_resource type="Script" uid="uid://ddcaceywxwt20" path="res://script/ai/action/action_attack1.gd" id="4_klwmg"]
-[ext_resource type="Script" uid="uid://bhxaiqao7nkth" path="res://script/ai/action/action_check_hit_wall.gd" id="6_7sn8v"]
-[ext_resource type="Script" uid="uid://ci3tg5fkdn16f" path="res://script/ai/action/action_destroy.gd" id="7_dfpyy"]
-[ext_resource type="Script" uid="uid://scokoi8g3sm8" path="res://script/ai/action/action_attack2.gd" id="7_klwmg"]
-
-[node name="BeehaveTree" type="Node" node_paths=PackedStringArray("blackboard")]
-script = ExtResource("1_6wcp2")
-blackboard = NodePath("@Node@25188")
-
-[node name="SequenceComposite" type="Node" parent="."]
-script = ExtResource("2_0p8p1")
-
-[node name="AlwaysSucceedDecorator" type="Node" parent="SequenceComposite"]
-script = ExtResource("3_irjra")
-metadata/_custom_type_script = ExtResource("3_irjra")
-
-[node name="保持攻击" type="Node" parent="SequenceComposite/AlwaysSucceedDecorator"]
-script = ExtResource("2_0p8p1")
-
-[node name="ActionWaitTick" type="Node" parent="SequenceComposite/AlwaysSucceedDecorator/保持攻击"]
-script = ExtResource("4_2fqct")
-metadata/_custom_type_script = ExtResource("4_2fqct")
-
-[node name="ActionAttack1" type="Node" parent="SequenceComposite/AlwaysSucceedDecorator/保持攻击"]
-script = ExtResource("4_klwmg")
-
-[node name="AlwaysSucceedDecorator2" type="Node" parent="SequenceComposite"]
-script = ExtResource("3_irjra")
-metadata/_custom_type_script = ExtResource("3_irjra")
-
-[node name="检测命中墙壁并销毁" type="Node" parent="SequenceComposite/AlwaysSucceedDecorator2"]
-script = ExtResource("2_0p8p1")
-
-[node name="ActionCheckHitWall" type="Node" parent="SequenceComposite/AlwaysSucceedDecorator2/检测命中墙壁并销毁"]
-script = ExtResource("6_7sn8v")
-metadata/_custom_type_script = ExtResource("6_7sn8v")
-
-[node name="ActionAttack2" type="Node" parent="SequenceComposite/AlwaysSucceedDecorator2/检测命中墙壁并销毁"]
-script = ExtResource("7_klwmg")
-metadata/_custom_type_script = ExtResource("7_klwmg")
-
-[node name="ActionDestroy" type="Node" parent="SequenceComposite/AlwaysSucceedDecorator2/检测命中墙壁并销毁"]
-script = ExtResource("7_dfpyy")
diff --git a/scene/ai/monster00.tscn b/scene/ai/monster00.tscn
deleted file mode 100644
index d2dab69..0000000
--- a/scene/ai/monster00.tscn
+++ /dev/null
@@ -1,66 +0,0 @@
-[gd_scene load_steps=9 format=3 uid="uid://br7nhubpnjouy"]
-
-[ext_resource type="Script" path="res://addons/beehave/nodes/beehave_tree.gd" id="1_mabth"]
-[ext_resource type="Script" path="res://addons/beehave/nodes/composites/sequence.gd" id="2_j3bbo"]
-[ext_resource type="Script" path="res://script/ai/action/action_find_target.gd" id="3_nrbg0"]
-[ext_resource type="Script" path="res://addons/beehave/nodes/composites/selector.gd" id="4_gnr3y"]
-[ext_resource type="Script" path="res://script/ai/action_role_check/action_role_check_is.gd" id="5_0ogvm"]
-[ext_resource type="Script" path="res://script/ai/action_with_target/action_move_to.gd" id="6_1t362"]
-[ext_resource type="Script" path="res://script/ai/action_with_target/action_cast_skill.gd" id="7_4jw56"]
-[ext_resource type="Script" path="res://script/ai/action/action_wait.gd" id="8_i6t1a"]
-
-[node name="BeehaveTree" type="Node" node_paths=PackedStringArray("blackboard")]
-script = ExtResource("1_mabth")
-blackboard = NodePath("@Node@19482")
-
-[node name="SequenceComposite" type="Node" parent="."]
-script = ExtResource("2_j3bbo")
-
-[node name="ActionFindTarget" type="Node" parent="SequenceComposite"]
-script = ExtResource("3_nrbg0")
-
-[node name="SelectorComposite" type="Node" parent="SequenceComposite"]
-script = ExtResource("4_gnr3y")
-
-[node name="SequenceComposite" type="Node" parent="SequenceComposite/SelectorComposite"]
-script = ExtResource("2_j3bbo")
-
-[node name="ActionRoleCheckIs" type="Node" parent="SequenceComposite/SelectorComposite/SequenceComposite"]
-script = ExtResource("5_0ogvm")
-key = 1
-
-[node name="ActionMoveTo" type="Node" parent="SequenceComposite/SelectorComposite/SequenceComposite"]
-script = ExtResource("6_1t362")
-dist_max = 2.0
-
-[node name="ActionCastSkill" type="Node" parent="SequenceComposite/SelectorComposite/SequenceComposite"]
-script = ExtResource("7_4jw56")
-
-[node name="SequenceComposite2" type="Node" parent="SequenceComposite/SelectorComposite"]
-script = ExtResource("2_j3bbo")
-
-[node name="ActionRoleCheckIs" type="Node" parent="SequenceComposite/SelectorComposite/SequenceComposite2"]
-script = ExtResource("5_0ogvm")
-key = 2
-
-[node name="ActionMoveTo" type="Node" parent="SequenceComposite/SelectorComposite/SequenceComposite2"]
-script = ExtResource("6_1t362")
-dist_min = 3.0
-dist_max = 4.0
-
-[node name="ActionCastSkill" type="Node" parent="SequenceComposite/SelectorComposite/SequenceComposite2"]
-script = ExtResource("7_4jw56")
-
-[node name="SequenceComposite3" type="Node" parent="SequenceComposite/SelectorComposite"]
-script = ExtResource("2_j3bbo")
-
-[node name="ActionRoleCheckIs" type="Node" parent="SequenceComposite/SelectorComposite/SequenceComposite3"]
-script = ExtResource("5_0ogvm")
-
-[node name="ActionMoveTo" type="Node" parent="SequenceComposite/SelectorComposite/SequenceComposite3"]
-script = ExtResource("6_1t362")
-dist_min = 4.0
-
-[node name="ActionWait" type="Node" parent="SequenceComposite/SelectorComposite/SequenceComposite3"]
-script = ExtResource("8_i6t1a")
-wait_time = 2.0
diff --git a/scene/ai/monster01.tscn b/scene/ai/monster01.tscn
deleted file mode 100644
index d445dd0..0000000
--- a/scene/ai/monster01.tscn
+++ /dev/null
@@ -1,66 +0,0 @@
-[gd_scene load_steps=9 format=3 uid="uid://r4o07ns0q8rg"]
-
-[ext_resource type="Script" uid="uid://mvwcxqcetiqp" path="res://addons/beehave/nodes/beehave_tree.gd" id="1_bbyao"]
-[ext_resource type="Script" uid="uid://cugftmuc8v30c" path="res://addons/beehave/nodes/composites/sequence.gd" id="2_04nig"]
-[ext_resource type="Script" uid="uid://d1cbkwu2v41cf" path="res://script/ai/action/action_find_target.gd" id="3_c43ds"]
-[ext_resource type="Script" uid="uid://casy048cfvo0l" path="res://addons/beehave/nodes/composites/selector.gd" id="4_hf0vc"]
-[ext_resource type="Script" uid="uid://dswopca1g8ewi" path="res://script/ai/action_role_check/action_role_check_is.gd" id="5_niu75"]
-[ext_resource type="Script" uid="uid://dq21r8kmyo51u" path="res://script/ai/action_with_target/action_move_to.gd" id="6_l7hec"]
-[ext_resource type="Script" uid="uid://dalb13ecr5sx1" path="res://script/ai/action_with_target/action_cast_skill.gd" id="7_up57t"]
-[ext_resource type="Script" uid="uid://cnw25wdsd3c76" path="res://script/ai/action/action_wait.gd" id="8_pkgji"]
-
-[node name="BeehaveTree" type="Node" node_paths=PackedStringArray("blackboard")]
-script = ExtResource("1_bbyao")
-blackboard = NodePath("@Node@25153")
-
-[node name="SequenceComposite" type="Node" parent="."]
-script = ExtResource("2_04nig")
-
-[node name="ActionFindTarget" type="Node" parent="SequenceComposite"]
-script = ExtResource("3_c43ds")
-
-[node name="SelectorComposite" type="Node" parent="SequenceComposite"]
-script = ExtResource("4_hf0vc")
-
-[node name="SequenceComposite" type="Node" parent="SequenceComposite/SelectorComposite"]
-script = ExtResource("2_04nig")
-
-[node name="ActionRoleCheckIs" type="Node" parent="SequenceComposite/SelectorComposite/SequenceComposite"]
-script = ExtResource("5_niu75")
-key = 1
-
-[node name="ActionMoveTo" type="Node" parent="SequenceComposite/SelectorComposite/SequenceComposite"]
-script = ExtResource("6_l7hec")
-dist_max = 2.0
-
-[node name="ActionCastSkill" type="Node" parent="SequenceComposite/SelectorComposite/SequenceComposite"]
-script = ExtResource("7_up57t")
-
-[node name="SequenceComposite2" type="Node" parent="SequenceComposite/SelectorComposite"]
-script = ExtResource("2_04nig")
-
-[node name="ActionRoleCheckIs" type="Node" parent="SequenceComposite/SelectorComposite/SequenceComposite2"]
-script = ExtResource("5_niu75")
-key = 2
-
-[node name="ActionMoveTo" type="Node" parent="SequenceComposite/SelectorComposite/SequenceComposite2"]
-script = ExtResource("6_l7hec")
-dist_min = 3.0
-dist_max = 4.0
-
-[node name="ActionCastSkill" type="Node" parent="SequenceComposite/SelectorComposite/SequenceComposite2"]
-script = ExtResource("7_up57t")
-
-[node name="SequenceComposite3" type="Node" parent="SequenceComposite/SelectorComposite"]
-script = ExtResource("2_04nig")
-
-[node name="ActionRoleCheckIs" type="Node" parent="SequenceComposite/SelectorComposite/SequenceComposite3"]
-script = ExtResource("5_niu75")
-
-[node name="ActionMoveTo" type="Node" parent="SequenceComposite/SelectorComposite/SequenceComposite3"]
-script = ExtResource("6_l7hec")
-dist_min = 4.0
-
-[node name="ActionWait" type="Node" parent="SequenceComposite/SelectorComposite/SequenceComposite3"]
-script = ExtResource("8_pkgji")
-wait_time = 2.0
diff --git a/scene/ai/monster02.tscn b/scene/ai/monster02.tscn
deleted file mode 100644
index d9317ac..0000000
--- a/scene/ai/monster02.tscn
+++ /dev/null
@@ -1,66 +0,0 @@
-[gd_scene load_steps=9 format=3 uid="uid://c0velv8p4imxa"]
-
-[ext_resource type="Script" path="res://addons/beehave/nodes/beehave_tree.gd" id="1_c24lj"]
-[ext_resource type="Script" path="res://addons/beehave/nodes/composites/sequence.gd" id="2_jjdrd"]
-[ext_resource type="Script" path="res://script/ai/action/action_find_target.gd" id="3_82jsi"]
-[ext_resource type="Script" path="res://addons/beehave/nodes/composites/selector.gd" id="4_wtlw0"]
-[ext_resource type="Script" path="res://script/ai/action_role_check/action_role_check_is.gd" id="5_80c8u"]
-[ext_resource type="Script" path="res://script/ai/action_with_target/action_move_to.gd" id="6_u68e8"]
-[ext_resource type="Script" path="res://script/ai/action_with_target/action_cast_skill.gd" id="7_w5xrf"]
-[ext_resource type="Script" path="res://script/ai/action/action_wait.gd" id="8_kaxnh"]
-
-[node name="BeehaveTree" type="Node" node_paths=PackedStringArray("blackboard")]
-script = ExtResource("1_c24lj")
-blackboard = NodePath("@Node@19489")
-
-[node name="SequenceComposite" type="Node" parent="."]
-script = ExtResource("2_jjdrd")
-
-[node name="ActionFindTarget" type="Node" parent="SequenceComposite"]
-script = ExtResource("3_82jsi")
-
-[node name="SelectorComposite" type="Node" parent="SequenceComposite"]
-script = ExtResource("4_wtlw0")
-
-[node name="SequenceComposite" type="Node" parent="SequenceComposite/SelectorComposite"]
-script = ExtResource("2_jjdrd")
-
-[node name="ActionRoleCheckIs" type="Node" parent="SequenceComposite/SelectorComposite/SequenceComposite"]
-script = ExtResource("5_80c8u")
-key = 1
-
-[node name="ActionMoveTo" type="Node" parent="SequenceComposite/SelectorComposite/SequenceComposite"]
-script = ExtResource("6_u68e8")
-dist_max = 2.0
-
-[node name="ActionCastSkill" type="Node" parent="SequenceComposite/SelectorComposite/SequenceComposite"]
-script = ExtResource("7_w5xrf")
-
-[node name="SequenceComposite2" type="Node" parent="SequenceComposite/SelectorComposite"]
-script = ExtResource("2_jjdrd")
-
-[node name="ActionRoleCheckIs" type="Node" parent="SequenceComposite/SelectorComposite/SequenceComposite2"]
-script = ExtResource("5_80c8u")
-key = 2
-
-[node name="ActionMoveTo" type="Node" parent="SequenceComposite/SelectorComposite/SequenceComposite2"]
-script = ExtResource("6_u68e8")
-dist_min = 3.0
-dist_max = 4.0
-
-[node name="ActionCastSkill" type="Node" parent="SequenceComposite/SelectorComposite/SequenceComposite2"]
-script = ExtResource("7_w5xrf")
-
-[node name="SequenceComposite3" type="Node" parent="SequenceComposite/SelectorComposite"]
-script = ExtResource("2_jjdrd")
-
-[node name="ActionRoleCheckIs" type="Node" parent="SequenceComposite/SelectorComposite/SequenceComposite3"]
-script = ExtResource("5_80c8u")
-
-[node name="ActionMoveTo" type="Node" parent="SequenceComposite/SelectorComposite/SequenceComposite3"]
-script = ExtResource("6_u68e8")
-dist_min = 4.0
-
-[node name="ActionWait" type="Node" parent="SequenceComposite/SelectorComposite/SequenceComposite3"]
-script = ExtResource("8_kaxnh")
-wait_time = 2.0
diff --git a/scene/ai/monster03.tscn b/scene/ai/monster03.tscn
deleted file mode 100644
index b9783af..0000000
--- a/scene/ai/monster03.tscn
+++ /dev/null
@@ -1,66 +0,0 @@
-[gd_scene load_steps=9 format=3 uid="uid://bk74u53bkeckp"]
-
-[ext_resource type="Script" path="res://addons/beehave/nodes/beehave_tree.gd" id="1_tkdjh"]
-[ext_resource type="Script" path="res://addons/beehave/nodes/composites/sequence.gd" id="2_mxprp"]
-[ext_resource type="Script" path="res://script/ai/action/action_find_target.gd" id="3_wmb22"]
-[ext_resource type="Script" path="res://script/ai/action_role_check/action_role_check_is.gd" id="4_4huwy"]
-[ext_resource type="Script" path="res://addons/beehave/nodes/composites/selector.gd" id="4_x2ddi"]
-[ext_resource type="Script" path="res://script/ai/action_with_target/action_move_to.gd" id="5_x5dsk"]
-[ext_resource type="Script" path="res://script/ai/action_with_target/action_cast_skill.gd" id="7_sslsg"]
-[ext_resource type="Script" path="res://script/ai/action/action_wait.gd" id="9_n5wac"]
-
-[node name="BeehaveTree" type="Node" node_paths=PackedStringArray("blackboard")]
-script = ExtResource("1_tkdjh")
-blackboard = NodePath("@Node@19489")
-
-[node name="SequenceComposite" type="Node" parent="."]
-script = ExtResource("2_mxprp")
-
-[node name="ActionFindTarget" type="Node" parent="SequenceComposite"]
-script = ExtResource("3_wmb22")
-
-[node name="SelectorComposite" type="Node" parent="SequenceComposite"]
-script = ExtResource("4_x2ddi")
-
-[node name="SequenceComposite" type="Node" parent="SequenceComposite/SelectorComposite"]
-script = ExtResource("2_mxprp")
-
-[node name="ActionRoleCheckIs" type="Node" parent="SequenceComposite/SelectorComposite/SequenceComposite"]
-script = ExtResource("4_4huwy")
-key = 1
-
-[node name="ActionMoveTo" type="Node" parent="SequenceComposite/SelectorComposite/SequenceComposite"]
-script = ExtResource("5_x5dsk")
-dist_max = 2.0
-
-[node name="ActionCastSkill" type="Node" parent="SequenceComposite/SelectorComposite/SequenceComposite"]
-script = ExtResource("7_sslsg")
-
-[node name="SequenceComposite2" type="Node" parent="SequenceComposite/SelectorComposite"]
-script = ExtResource("2_mxprp")
-
-[node name="ActionRoleCheckIs" type="Node" parent="SequenceComposite/SelectorComposite/SequenceComposite2"]
-script = ExtResource("4_4huwy")
-key = 2
-
-[node name="ActionMoveTo" type="Node" parent="SequenceComposite/SelectorComposite/SequenceComposite2"]
-script = ExtResource("5_x5dsk")
-dist_min = 3.0
-dist_max = 4.0
-
-[node name="ActionCastSkill" type="Node" parent="SequenceComposite/SelectorComposite/SequenceComposite2"]
-script = ExtResource("7_sslsg")
-
-[node name="SequenceComposite3" type="Node" parent="SequenceComposite/SelectorComposite"]
-script = ExtResource("2_mxprp")
-
-[node name="ActionRoleCheckIs" type="Node" parent="SequenceComposite/SelectorComposite/SequenceComposite3"]
-script = ExtResource("4_4huwy")
-
-[node name="ActionMoveTo" type="Node" parent="SequenceComposite/SelectorComposite/SequenceComposite3"]
-script = ExtResource("5_x5dsk")
-dist_min = 4.0
-
-[node name="ActionWait" type="Node" parent="SequenceComposite/SelectorComposite/SequenceComposite3"]
-script = ExtResource("9_n5wac")
-wait_time = 2.0
diff --git a/scene/ai/monster04.tscn b/scene/ai/monster04.tscn
deleted file mode 100644
index 2880319..0000000
--- a/scene/ai/monster04.tscn
+++ /dev/null
@@ -1,66 +0,0 @@
-[gd_scene load_steps=9 format=3 uid="uid://c66a72aojgj43"]
-
-[ext_resource type="Script" path="res://addons/beehave/nodes/beehave_tree.gd" id="1_lfgx0"]
-[ext_resource type="Script" path="res://addons/beehave/nodes/composites/sequence.gd" id="2_mw6xw"]
-[ext_resource type="Script" path="res://script/ai/action/action_find_target.gd" id="3_lo3nv"]
-[ext_resource type="Script" path="res://addons/beehave/nodes/composites/selector.gd" id="4_utp2v"]
-[ext_resource type="Script" path="res://script/ai/action_role_check/action_role_check_is.gd" id="5_4j1dq"]
-[ext_resource type="Script" path="res://script/ai/action_with_target/action_move_to.gd" id="6_d1xy8"]
-[ext_resource type="Script" path="res://script/ai/action_with_target/action_cast_skill.gd" id="7_x51x6"]
-[ext_resource type="Script" path="res://script/ai/action/action_wait.gd" id="8_sr1ot"]
-
-[node name="BeehaveTree" type="Node" node_paths=PackedStringArray("blackboard")]
-script = ExtResource("1_lfgx0")
-blackboard = NodePath("@Node@19489")
-
-[node name="SequenceComposite" type="Node" parent="."]
-script = ExtResource("2_mw6xw")
-
-[node name="ActionFindTarget" type="Node" parent="SequenceComposite"]
-script = ExtResource("3_lo3nv")
-
-[node name="SelectorComposite" type="Node" parent="SequenceComposite"]
-script = ExtResource("4_utp2v")
-
-[node name="SequenceComposite" type="Node" parent="SequenceComposite/SelectorComposite"]
-script = ExtResource("2_mw6xw")
-
-[node name="ActionRoleCheckIs" type="Node" parent="SequenceComposite/SelectorComposite/SequenceComposite"]
-script = ExtResource("5_4j1dq")
-key = 1
-
-[node name="ActionMoveTo" type="Node" parent="SequenceComposite/SelectorComposite/SequenceComposite"]
-script = ExtResource("6_d1xy8")
-dist_max = 2.0
-
-[node name="ActionCastSkill" type="Node" parent="SequenceComposite/SelectorComposite/SequenceComposite"]
-script = ExtResource("7_x51x6")
-
-[node name="SequenceComposite2" type="Node" parent="SequenceComposite/SelectorComposite"]
-script = ExtResource("2_mw6xw")
-
-[node name="ActionRoleCheckIs" type="Node" parent="SequenceComposite/SelectorComposite/SequenceComposite2"]
-script = ExtResource("5_4j1dq")
-key = 2
-
-[node name="ActionMoveTo" type="Node" parent="SequenceComposite/SelectorComposite/SequenceComposite2"]
-script = ExtResource("6_d1xy8")
-dist_min = 3.0
-dist_max = 4.0
-
-[node name="ActionCastSkill" type="Node" parent="SequenceComposite/SelectorComposite/SequenceComposite2"]
-script = ExtResource("7_x51x6")
-
-[node name="SequenceComposite3" type="Node" parent="SequenceComposite/SelectorComposite"]
-script = ExtResource("2_mw6xw")
-
-[node name="ActionRoleCheckIs" type="Node" parent="SequenceComposite/SelectorComposite/SequenceComposite3"]
-script = ExtResource("5_4j1dq")
-
-[node name="ActionMoveTo" type="Node" parent="SequenceComposite/SelectorComposite/SequenceComposite3"]
-script = ExtResource("6_d1xy8")
-dist_min = 4.0
-
-[node name="ActionWait" type="Node" parent="SequenceComposite/SelectorComposite/SequenceComposite3"]
-script = ExtResource("8_sr1ot")
-wait_time = 2.0
diff --git a/scene/character/bullet.tscn b/scene/character/bullet.tscn
index bedc8f7..bbc0d70 100644
--- a/scene/character/bullet.tscn
+++ b/scene/character/bullet.tscn
@@ -1,16 +1,20 @@
[gd_scene load_steps=4 format=3 uid="uid://c43cuvaiu2jha"]
[ext_resource type="PackedScene" uid="uid://8rcvw1vnjcf7" path="res://scene/character/character.tscn" id="1_f620f"]
-[ext_resource type="SpriteFrames" uid="uid://bhsotj76tuovy" path="res://resource/animation/character/hero01_fist_attack.aseprite" id="2_sjv5x"]
-[ext_resource type="Script" path="res://script/character/ai/bullet_ai.gd" id="3_c6unk"]
+[ext_resource type="Script" uid="uid://clqcqu6ewvgqh" path="res://script/character/ai/bullet_ai.gd" id="3_c6unk"]
+
+[sub_resource type="BlackboardPlan" id="BlackboardPlan_oqe2c"]
[node name="Character" instance=ExtResource("1_f620f")]
[node name="View" parent="." index="3"]
cast_shadow = 0
-sprite_frames = ExtResource("2_sjv5x")
-animation = &"fist_attack01"
-frame = 0
-[node name="BulletAI" type="Node3D" parent="." index="10"]
+[node name="BulletAI" type="Node3D" parent="." index="11"]
script = ExtResource("3_c6unk")
+metadata/_custom_type_script = "uid://clqcqu6ewvgqh"
+
+[node name="BTPlayer" type="BTPlayer" parent="." index="12"]
+update_mode = 2
+blackboard_plan = SubResource("BlackboardPlan_oqe2c")
+unique_name_in_owner = true
diff --git a/scene/character/character.tscn b/scene/character/character.tscn
index 007c471..d63ea99 100644
--- a/scene/character/character.tscn
+++ b/scene/character/character.tscn
@@ -4,7 +4,7 @@
[ext_resource type="Script" uid="uid://cms637d0jt6sk" path="res://script/character/hitbox.gd" id="2_6xf87"]
[ext_resource type="Script" uid="uid://bfi4gneebe3oq" path="res://script/character/status.gd" id="2_txdip"]
[ext_resource type="Script" uid="uid://cnaqs44siwa45" path="res://script/character/move.gd" id="4_66r53"]
-[ext_resource type="SpriteFrames" uid="uid://dhfqj1dxldqao" path="res://resource/animation/character/hero01_long_skill01.aseprite" id="4_sox5o"]
+[ext_resource type="SpriteFrames" uid="uid://ce83cuqwgwwi4" path="res://resource/animation/character/hero01_long_attack.aseprite" id="4_sox5o"]
[ext_resource type="Script" uid="uid://c247mf44qb3uf" path="res://script/character/view.gd" id="4_vijjv"]
[ext_resource type="Script" uid="uid://c24is3uqqcmcn" path="res://script/character/skill.gd" id="6_h4xqy"]
[ext_resource type="AnimationLibrary" uid="uid://croik07a1qko5" path="res://resource/skill_animation_library/animation_library.tres" id="6_pakq5"]
@@ -143,7 +143,7 @@ gi_mode = 0
pixel_size = 0.02
alpha_cut = 1
sprite_frames = ExtResource("4_sox5o")
-animation = &"long_skill01"
+animation = &"long_attack02"
script = ExtResource("4_vijjv")
[node name="Move" type="Node3D" parent="."]
@@ -199,8 +199,3 @@ pixel_size = 0.02
sprite_frames = ExtResource("15_70jx1")
animation = &"airhit1"
script = ExtResource("16_ot265")
-
-[connection signal="area_entered" from="Pushbox" to="Pushbox" method="on_area_entered"]
-[connection signal="area_exited" from="Pushbox" to="Pushbox" method="on_area_exited"]
-[connection signal="animation_finished" from="View" to="View" method="_on_animation_finished"]
-[connection signal="animation_finished" from="Skill" to="Skill" method="_on_animation_finished"]
diff --git a/scene/character/monster.tscn b/scene/character/monster.tscn
index 60cc998..fbbacdd 100644
--- a/scene/character/monster.tscn
+++ b/scene/character/monster.tscn
@@ -1,9 +1,33 @@
-[gd_scene load_steps=3 format=3 uid="uid://c37rf5ecfrvwn"]
+[gd_scene load_steps=6 format=3 uid="uid://c37rf5ecfrvwn"]
[ext_resource type="PackedScene" uid="uid://8rcvw1vnjcf7" path="res://scene/character/character.tscn" id="1_eshlr"]
-[ext_resource type="Script" path="res://script/character/ai/monster_ai.gd" id="2_e8lqw"]
+[ext_resource type="Script" uid="uid://b8ftlmb0b68p2" path="res://script/character/ai/monster_ai.gd" id="2_q6iuw"]
+[ext_resource type="SpriteFrames" uid="uid://jpxh0jr8wp8g" path="res://resource/animation/character/hero01_basic.aseprite" id="2_um5kt"]
+[ext_resource type="AnimationLibrary" uid="uid://croik07a1qko5" path="res://resource/skill_animation_library/animation_library.tres" id="3_b3rg1"]
+
+[sub_resource type="BlackboardPlan" id="BlackboardPlan_q6iuw"]
[node name="Character" instance=ExtResource("1_eshlr")]
+[node name="Status" parent="." index="2"]
+is_speed_y_freeze = true
+skill_move_speed = 7.0
+break_level = 3
+
+[node name="View" parent="." index="3"]
+sprite_frames = ExtResource("2_um5kt")
+animation = &"basic_air_flash"
+
+[node name="Skill" parent="." index="5"]
+libraries = {
+&"animation_library": ExtResource("3_b3rg1")
+}
+
[node name="MonsterAI" type="Node3D" parent="." index="11"]
-script = ExtResource("2_e8lqw")
+script = ExtResource("2_q6iuw")
+metadata/_custom_type_script = "uid://b8ftlmb0b68p2"
+
+[node name="BTPlayer" type="BTPlayer" parent="." index="12"]
+update_mode = 2
+blackboard_plan = SubResource("BlackboardPlan_q6iuw")
+unique_name_in_owner = true
diff --git a/scene/level/level.tscn b/scene/level/level.tscn
index 715094f..6784071 100644
--- a/scene/level/level.tscn
+++ b/scene/level/level.tscn
@@ -36,7 +36,7 @@ data = {
}
script = ExtResource("3_gavly")
metadata/_custom_type_script = "uid://ceqaio6vw0sa3"
-metadata/_editor_floor_ = Vector3(9, 16, 0)
+metadata/_editor_floor_ = Vector3(9, 0, 0)
[node name="LevelGridSub" type="GridMap" parent="."]
mesh_library = ExtResource("2_8ku8g")
diff --git a/script/ai/action.gd b/script/ai/action.gd
index afc298b..18814ef 100644
--- a/script/ai/action.gd
+++ b/script/ai/action.gd
@@ -1,27 +1,18 @@
-extends ActionLeaf
+@tool
+extends BTAction
class_name Action
-func get_character(actor: Node) -> Character:
- if not actor is AI:
- print("行为树结构错误")
- return null
- var ai: AI = actor as AI
- return ai.character
+func get_character() -> Character:
+ return agent as Character
+func get_physics_process_delta_time() -> float:
+ return agent.get_process_delta_time()
-func before_run(actor: Node, blackboard: Blackboard) -> void:
- init(get_character(actor))
-
-
-func tick(actor: Node, blackboard: Blackboard) -> int:
- var character: Character = get_character(actor)
+func _tick(_delta: float) -> BT.Status:
+ var character: Character = get_character()
if character.get_status("is_stagger") or character.get_status("is_stun"):
return FAILURE
- return run(character, blackboard)
-
-
-func init(character: Character): pass
-
+ return run(character)
-func run(character: Character, blackboard: Blackboard) -> int:
+func run(_character: Character) -> BT.Status:
return FAILURE
diff --git a/script/ai/action/action_attack1.gd b/script/ai/action/action_attack1.gd
index e44c64f..86c803a 100644
--- a/script/ai/action/action_attack1.gd
+++ b/script/ai/action/action_attack1.gd
@@ -1,7 +1,9 @@
+@tool
extends Action
class_name ActionAttack1
-func run(character: Character, blackboard: Blackboard) -> int:
+func _generate_name(): return "释放Attack1"
+
+func run(character: Character) -> BT.Status:
character.attack1()
return SUCCESS
-
diff --git a/script/ai/action/action_attack2.gd b/script/ai/action/action_attack2.gd
index 8cc4f20..5323828 100644
--- a/script/ai/action/action_attack2.gd
+++ b/script/ai/action/action_attack2.gd
@@ -1,7 +1,9 @@
+@tool
extends Action
class_name ActionAttack2
-func run(character: Character, blackboard: Blackboard) -> int:
+func _generate_name(): return "释放Attack2"
+
+func run(character: Character) -> BT.Status:
character.attack2()
return SUCCESS
-
diff --git a/script/ai/action/action_check_hit_character.gd b/script/ai/action/action_check_hit_character.gd
index 19f464e..78b5796 100644
--- a/script/ai/action/action_check_hit_character.gd
+++ b/script/ai/action/action_check_hit_character.gd
@@ -1,7 +1,8 @@
+@tool
extends Action
class_name ActionCheckHitCharacter
-func run(character: Character, blackboard: Blackboard) -> int:
+func run(character: Character) -> BT.Status:
if character.get_status("is_hit_character"):
return SUCCESS
return FAILURE
diff --git a/script/ai/action/action_check_hit_wall.gd b/script/ai/action/action_check_hit_wall.gd
index fd6827b..ff234f4 100644
--- a/script/ai/action/action_check_hit_wall.gd
+++ b/script/ai/action/action_check_hit_wall.gd
@@ -1,7 +1,8 @@
+@tool
extends Action
class_name ActionCheckHitWall
-func run(character: Character, blackboard: Blackboard) -> int:
+func run(character: Character) -> BT.Status:
if character.get_status("is_hit_wall"):
return SUCCESS
return FAILURE
diff --git a/script/ai/action/action_destroy.gd b/script/ai/action/action_destroy.gd
index 1ea1337..90afaac 100644
--- a/script/ai/action/action_destroy.gd
+++ b/script/ai/action/action_destroy.gd
@@ -1,10 +1,11 @@
+@tool
extends Action
class_name ActionDestroy
var live_time: float = 0.05
-func run(character: Character, blackboard: Blackboard) -> int:
+func run(character: Character) -> BT.Status:
live_time -= get_physics_process_delta_time()
if live_time > 0:
return RUNNING
diff --git a/script/ai/action/action_find_target.gd b/script/ai/action/action_find_target.gd
index 651b744..e399b0a 100644
--- a/script/ai/action/action_find_target.gd
+++ b/script/ai/action/action_find_target.gd
@@ -1,7 +1,8 @@
+@tool
extends Action
class_name ActionFindTarget
-func run(character: Character, blackboard: Blackboard) -> int:
+func run(character: Character) -> BT.Status:
var player_id: int = Global.character_mgr.get_player_id()
character.set_target(player_id)
return SUCCESS
diff --git a/script/ai/action/action_print.gd b/script/ai/action/action_print.gd
deleted file mode 100644
index 45407fd..0000000
--- a/script/ai/action/action_print.gd
+++ /dev/null
@@ -1,9 +0,0 @@
-extends Action
-class_name ActionPrint
-
-@export var context: String
-
-
-func run(character: Character, blackboard: Blackboard) -> int:
- print(context)
- return SUCCESS
diff --git a/script/ai/action/action_stop_move.gd b/script/ai/action/action_stop_move.gd
index 00ff071..b2b22f3 100644
--- a/script/ai/action/action_stop_move.gd
+++ b/script/ai/action/action_stop_move.gd
@@ -1,6 +1,7 @@
+@tool
extends Action
class_name ActionStopMove
-func run(character: Character, blackboard: Blackboard) -> int:
+func run(character: Character) -> BT.Status:
character.move_stop()
return SUCCESS
diff --git a/script/ai/action/action_wait.gd b/script/ai/action/action_wait.gd
index da6032b..2210f8b 100644
--- a/script/ai/action/action_wait.gd
+++ b/script/ai/action/action_wait.gd
@@ -1,3 +1,4 @@
+@tool
extends Action
class_name ActionWait
@@ -6,7 +7,7 @@ class_name ActionWait
var wait_time_left: float
-func run(character: Character, blackboard: Blackboard) -> int:
+func run(_character: Character) -> BT.Status:
wait_time_left += get_physics_process_delta_time()
if wait_time_left >= wait_time:
wait_time_left = 0
diff --git a/script/ai/action/action_wait_tick.gd b/script/ai/action/action_wait_tick.gd
index a75a006..91b4d80 100644
--- a/script/ai/action/action_wait_tick.gd
+++ b/script/ai/action/action_wait_tick.gd
@@ -1,3 +1,4 @@
+@tool
extends Action
class_name ActionWaitTick
@@ -5,7 +6,7 @@ var wait_time: float = 0.1
var wait_time_left: float
-func run(character: Character, blackboard: Blackboard) -> int:
+func run(_character: Character) -> BT.Status:
wait_time_left += get_physics_process_delta_time()
if wait_time_left >= wait_time:
wait_time_left = 0
diff --git a/script/ai/action_blackboard.gd b/script/ai/action_blackboard.gd
deleted file mode 100644
index eb2b11a..0000000
--- a/script/ai/action_blackboard.gd
+++ /dev/null
@@ -1,3 +0,0 @@
-@icon("res://addons/beehave/icons/blackboard.svg")
-class_name ActionBlackboard
-extends Action
diff --git a/script/ai/action_blackboard/action_blackboard_add.gd b/script/ai/action_blackboard/action_blackboard_add.gd
deleted file mode 100644
index 511dd6e..0000000
--- a/script/ai/action_blackboard/action_blackboard_add.gd
+++ /dev/null
@@ -1,11 +0,0 @@
-extends ActionBlackboard
-class_name ActionBlackboardAdd
-
-@export var key: String
-@export var value: int
-
-
-func run(character: Character, blackboard: Blackboard) -> int:
- var left: int = blackboard.get_value(key, 0)
- blackboard.set_value(key, left+value)
- return SUCCESS
diff --git a/script/ai/action_blackboard/action_blackboard_add.gd.uid b/script/ai/action_blackboard/action_blackboard_add.gd.uid
deleted file mode 100644
index e9f430d..0000000
--- a/script/ai/action_blackboard/action_blackboard_add.gd.uid
+++ /dev/null
@@ -1 +0,0 @@
-uid://p6naomn4rxb4
diff --git a/script/ai/action_blackboard/action_blackboard_check.gd b/script/ai/action_blackboard/action_blackboard_check.gd
deleted file mode 100644
index f578798..0000000
--- a/script/ai/action_blackboard/action_blackboard_check.gd
+++ /dev/null
@@ -1,28 +0,0 @@
-extends ActionBlackboard
-class_name ActionBlackboardCheck
-
-enum Operators {
- EQUAL,
- NOT_EQUAL,
- GREATER,
- LESS,
- GREATER_EQUAL,
- LESS_EQUAL,
-}
-@export var key: String
-
-@export_enum("==", "!=", ">", "<", ">=", "<=") var operator: int = 0
-@export var value: int
-
-
-func run(character: Character, blackboard: Blackboard) -> int:
- var left: Variant = blackboard.get_value(key, 0)
- var result: bool = false
- match operator:
- Operators.EQUAL: result = left == value
- Operators.NOT_EQUAL: result = left != value
- Operators.GREATER: result = left > value
- Operators.LESS: result = left < value
- Operators.GREATER_EQUAL: result = left >= value
- Operators.LESS_EQUAL: result = left <= value
- return SUCCESS if result else FAILURE
diff --git a/script/ai/action_blackboard/action_blackboard_check.gd.uid b/script/ai/action_blackboard/action_blackboard_check.gd.uid
deleted file mode 100644
index 61ae58a..0000000
--- a/script/ai/action_blackboard/action_blackboard_check.gd.uid
+++ /dev/null
@@ -1 +0,0 @@
-uid://c0mplmb0d3buo
diff --git a/script/ai/action_blackboard/action_blackboard_set.gd b/script/ai/action_blackboard/action_blackboard_set.gd
deleted file mode 100644
index 67ac3df..0000000
--- a/script/ai/action_blackboard/action_blackboard_set.gd
+++ /dev/null
@@ -1,10 +0,0 @@
-extends ActionBlackboard
-class_name ActionBlackboardSet
-
-@export var key: String
-@export var value: int
-
-
-func run(character: Character, blackboard: Blackboard) -> int:
- blackboard.set_value(key, value)
- return SUCCESS
diff --git a/script/ai/action_blackboard/action_blackboard_set.gd.uid b/script/ai/action_blackboard/action_blackboard_set.gd.uid
deleted file mode 100644
index 3068bde..0000000
--- a/script/ai/action_blackboard/action_blackboard_set.gd.uid
+++ /dev/null
@@ -1 +0,0 @@
-uid://bv7w667gj8akm
diff --git a/script/ai/action_check.gd b/script/ai/action_check.gd
new file mode 100644
index 0000000..83a5668
--- /dev/null
+++ b/script/ai/action_check.gd
@@ -0,0 +1,3 @@
+@tool
+extends Action
+class_name ActionCheck
diff --git a/script/ai/action_check.gd.uid b/script/ai/action_check.gd.uid
new file mode 100644
index 0000000..a4e6320
--- /dev/null
+++ b/script/ai/action_check.gd.uid
@@ -0,0 +1 @@
+uid://b1eg1tyt2kr7j
diff --git a/script/ai/action_check/action_alert_check.gd b/script/ai/action_check/action_alert_check.gd
new file mode 100644
index 0000000..fb0286d
--- /dev/null
+++ b/script/ai/action_check/action_alert_check.gd
@@ -0,0 +1,15 @@
+@tool
+extends ActionCheck
+class_name ActionAlertCheck
+
+@export var key: Enum.EAIRoleType = Enum.EAIRoleType.None
+
+@export var is_alert: bool
+
+func _generate_name():
+ return "AI已激活" if is_alert else "AI未激活"
+
+func run(character: Character) -> BT.Status:
+ if character.get_status("ai_is_alert") == is_alert:
+ return SUCCESS
+ return FAILURE
diff --git a/script/ai/action_check/action_alert_check.gd.uid b/script/ai/action_check/action_alert_check.gd.uid
new file mode 100644
index 0000000..b09758c
--- /dev/null
+++ b/script/ai/action_check/action_alert_check.gd.uid
@@ -0,0 +1 @@
+uid://c0cjruogr8531
diff --git a/script/ai/action_role_check/action_role_check_is.gd b/script/ai/action_check/action_role_check_is.gd
similarity index 65%
rename from script/ai/action_role_check/action_role_check_is.gd
rename to script/ai/action_check/action_role_check_is.gd
index 1b659fb..1cbcf89 100644
--- a/script/ai/action_role_check/action_role_check_is.gd
+++ b/script/ai/action_check/action_role_check_is.gd
@@ -1,10 +1,11 @@
-extends ActionRoleCheck
+@tool
+extends ActionCheck
class_name ActionRoleCheckIs
@export var key: Enum.EAIRoleType = Enum.EAIRoleType.None
-func run(character: Character, blackboard: Blackboard) -> int:
+func run(character: Character) -> BT.Status:
if character.get_status("ai_role") == key:
return SUCCESS
return FAILURE
diff --git a/script/ai/action_role_check/action_role_check_is.gd.uid b/script/ai/action_check/action_role_check_is.gd.uid
similarity index 100%
rename from script/ai/action_role_check/action_role_check_is.gd.uid
rename to script/ai/action_check/action_role_check_is.gd.uid
diff --git a/script/ai/action_role_check/action_role_check_is_not.gd b/script/ai/action_check/action_role_check_is_not.gd
similarity index 66%
rename from script/ai/action_role_check/action_role_check_is_not.gd
rename to script/ai/action_check/action_role_check_is_not.gd
index d75f181..0e37297 100644
--- a/script/ai/action_role_check/action_role_check_is_not.gd
+++ b/script/ai/action_check/action_role_check_is_not.gd
@@ -1,10 +1,11 @@
-extends ActionRoleCheck
+@tool
+extends ActionCheck
class_name ActionRoleCheckIsNot
@export var key: Enum.EAIRoleType = Enum.EAIRoleType.None
-func run(character: Character, blackboard: Blackboard) -> int:
+func run(character: Character) -> BT.Status:
if character.get_status("ai_role") != key:
return SUCCESS
return FAILURE
diff --git a/script/ai/action_role_check/action_role_check_is_not.gd.uid b/script/ai/action_check/action_role_check_is_not.gd.uid
similarity index 100%
rename from script/ai/action_role_check/action_role_check_is_not.gd.uid
rename to script/ai/action_check/action_role_check_is_not.gd.uid
diff --git a/script/ai/action_role_check.gd b/script/ai/action_role_check.gd
deleted file mode 100644
index 39e60ee..0000000
--- a/script/ai/action_role_check.gd
+++ /dev/null
@@ -1,3 +0,0 @@
-@icon("res://addons/beehave/icons/category_leaf.svg")
-class_name ActionRoleCheck
-extends Action
diff --git a/script/ai/action_with_target.gd b/script/ai/action_with_target.gd
index 8f9809b..fb10f69 100644
--- a/script/ai/action_with_target.gd
+++ b/script/ai/action_with_target.gd
@@ -1,15 +1,16 @@
+@tool
extends Action
class_name ActionWithTarget
-func init(character: Character): pass
+func init(_character: Character): pass
-func run(character: Character, blackboard: Blackboard) -> int:
+func run(character: Character) -> int:
var target: Character = Global.character_mgr.get_character(character.get_status("target"))
if not target:
return FAILURE
- return execute(character, target, blackboard)
+ return run_with_target(character, target)
-func execute(character: Character, target: Character, blackboard: Blackboard) -> int:
+func run_with_target(_character: Character, _target: Character) -> BT.Status:
return FAILURE
diff --git a/script/ai/action_with_target/action_cast_skill.gd b/script/ai/action_with_target/action_cast_skill.gd
index 1434ece..fd3ddeb 100644
--- a/script/ai/action_with_target/action_cast_skill.gd
+++ b/script/ai/action_with_target/action_cast_skill.gd
@@ -1,13 +1,14 @@
+@tool
extends ActionWithTarget
class_name ActionCastSkill
-func execute(character: Character, target: Character, blackboard: Blackboard) -> int:
- var skill: Skill = character.skill
- var status: Status = character.status
- var dir: Vector2 = target.pos2D() - character.pos2D()
- var dist: float = dir.length()
- if status.is_skill_running:
- if int(status.break_level) < Enum.EBreakLevel.Break:
+func run_with_target(character: Character, target: Character) -> BT.Status:
+ var skill: Skill = character.skill
+ var character_status: Status = character.status
+ var dir: Vector2 = target.pos2D() - character.pos2D()
+ var dist: float = dir.length()
+ if character_status.is_skill_running:
+ if int(character_status.break_level) < Enum.EBreakLevel.Break:
if dist < 0.5:
character.move_to(-dir)
elif dist > 2:
@@ -15,11 +16,11 @@ func execute(character: Character, target: Character, blackboard: Blackboard) ->
return RUNNING
for skill_cfg: SkillCfg in skill.skill_dict.values():
#检查姿态
- var stance_from: int = skill_cfg.stance_from
- var check_any_ground: bool = (stance_from == Enum.EStance.GroundAny) and status.is_on_floor
- var check_any_air: bool = (stance_from == Enum.EStance.AirAny) and not status.is_on_floor
- var check_any: bool = (stance_from == Enum.EStance.Any) or check_any_ground or check_any_air
- if (stance_from != int(status.stance)) and not check_any:
+ var stance_from: int = skill_cfg.stance_from
+ var check_any_ground: bool = (stance_from == Enum.EStance.GroundAny) and character_status.is_on_floor
+ var check_any_air: bool = (stance_from == Enum.EStance.AirAny) and not character_status.is_on_floor
+ var check_any: bool = (stance_from == Enum.EStance.Any) or check_any_ground or check_any_air
+ if (stance_from != int(character_status.stance)) and not check_any:
continue
#检查距离
if dist > skill_cfg.range:
@@ -28,7 +29,7 @@ func execute(character: Character, target: Character, blackboard: Blackboard) ->
if dist < skill_cfg.range - 2:
continue
#施放技能条件检查
- if not skill.cast_skill_check(skill_cfg, status.break_level):
+ if not skill.cast_skill_check(skill_cfg, character_status.break_level):
continue
#施放技能扣除mp
if not skill.cast_skill_mp_cost(skill_cfg):
diff --git a/script/ai/action_with_target/action_move_to.gd b/script/ai/action_with_target/action_move_to.gd
index ebf680e..274362c 100644
--- a/script/ai/action_with_target/action_move_to.gd
+++ b/script/ai/action_with_target/action_move_to.gd
@@ -1,3 +1,4 @@
+@tool
extends ActionWithTarget
class_name ActionMoveTo
@@ -6,7 +7,7 @@ class_name ActionMoveTo
@export var offset: float = 0.1 #0为无偏差 1为偏差90度
-func execute(character: Character, target: Character, blackboard: Blackboard) -> int:
+func run_with_target(character: Character, target: Character) -> BT.Status:
var dir: Vector2 = target.pos2D() - character.pos2D()
var dist: float = dir.length()
if (dist > dist_min ) and (dist < dist_max):
diff --git a/script/ai/sequence.gd.uid b/script/ai/sequence.gd.uid
new file mode 100644
index 0000000..f96c8ab
--- /dev/null
+++ b/script/ai/sequence.gd.uid
@@ -0,0 +1 @@
+uid://cokadq6t6oodu
diff --git a/script/character/ai/ai.gd b/script/character/ai/ai.gd
index ac35f3b..94fe8e7 100644
--- a/script/character/ai/ai.gd
+++ b/script/character/ai/ai.gd
@@ -3,11 +3,9 @@ class_name AI
@onready var character: Character = (get_owner() as Character)
@onready var status: Status = (%Status as Status)
+@onready var btPlayer: BTPlayer = (%BTPlayer as BTPlayer)
-var ai: BeehaveTree
var is_init: bool = false
-var has_ai: bool = false
-
func _process(delta) -> void:
if not is_init:
@@ -20,26 +18,22 @@ func init() -> void:
if not status.cfg:
return
is_init = true
- var ai_scene: PackedScene = status.cfg.get_ai()
- if not ai_scene:
+ var behavior_tree_res: BehaviorTree = status.cfg.get_ai()
+ if not behavior_tree_res:
+ print("未配置AI", character.cfg().get_res_name())
+ Global.character_mgr.destroy_character(character.id())
return
- ai = ai_scene.instantiate() as BeehaveTree
- ai.tick_rate = 20
- add_child(ai)
- has_ai = true
+ btPlayer.behavior_tree = behavior_tree_res
on_init()
func process(delta) -> void:
- if has_ai and status.ai_is_alert:
- on_process(delta)
- else:
+ if not status.ai_is_alert:
if status.cfg.ai:
- stroll()
- var player: Character = Global.character_mgr.get_player()
- var dir: Vector2 = player.pos2D() - character.pos2D()
- var dist: float = dir.length()
- var can_see: bool = character.get_face_dir().angle_to(dir) < PI/2
+ var player: Character = Global.character_mgr.get_player()
+ var dir: Vector2 = player.pos2D() - character.pos2D()
+ var dist: float = dir.length()
+ var can_see: bool = character.get_face_dir().angle_to(dir) < PI / 2
var alert_range: float = status.cfg.ai.alert_range if can_see else status.cfg.ai.alert_range_back
var alert_speed: float = status.cfg.ai.alert_speed if can_see else status.cfg.ai.alert_speed_back
if dist < alert_range:
@@ -58,17 +52,9 @@ func process(delta) -> void:
else:
status.ai_is_alert = true
status.emit_status("ai_is_alert")
+ on_process(delta)
+ btPlayer.update(delta)
+func on_init() -> void: pass
-func stroll() -> void:
- #todo 闲逛
- character.move_stop()
- pass
-
-
-func on_init() -> void:
- pass
-
-
-func on_process(delta):
- pass
+func on_process(_delta) -> void: pass
diff --git a/script/character/ai/soul_ai.gd b/script/character/ai/soul_ai.gd
index ccb6535..a61cc47 100644
--- a/script/character/ai/soul_ai.gd
+++ b/script/character/ai/soul_ai.gd
@@ -11,7 +11,7 @@ class_name SoulAI
var owner_character: Character
-func _process(delta) -> void:
+func _process(_delta) -> void:
owner_character = Global.character_mgr.get_character(status.owner_id)
if not owner_character:
Global.character_mgr.destroy_character(character.id())
diff --git a/script/character/buff.gd b/script/character/buff.gd
index d905c77..4ea9a10 100644
--- a/script/character/buff.gd
+++ b/script/character/buff.gd
@@ -13,13 +13,27 @@ class BuffInfo:
var duration: float
var ignore_pause: bool
-var buff_map: Dictionary = {} #buff信息
+var buff_map: Dictionary = {} # buff信息
+var buff_tick_frame_max = 1
+var buff_tick_frame = 0
+var delta_cache: float = 0
+func _ready():
+ buff_tick_frame_max = 1
func _process(delta):
+ delta_cache += delta
+ buff_tick_frame += 1
+ if buff_tick_frame < buff_tick_frame_max:
+ return
+ tick(delta_cache)
+ buff_tick_frame = 0
+ buff_tick_frame = 0
+
+func tick(delta) -> void:
for buff_name in buff_map:
var buff_info = buff_map[buff_name]
- if has_buff("pause") and buff_name!="pause" and !buff_info.ignore_pause:
+ if has_buff("pause") and buff_name != "pause" and !buff_info.ignore_pause:
continue
if buff_info.duration_max == -1:
trigger_buff_effect(buff_info, "update")
@@ -36,10 +50,10 @@ func _process(delta):
func trigger_buff_effect(buff: BuffInfo, trigger_name: String):
- var buff_name: String = buff.name
+ var buff_name: String = buff.name
var function_name: String = "on_%s_%s" % [trigger_name, buff_name]
if has_method(function_name):
- var rate: float = buff.duration/buff.duration_max
+ var rate: float = buff.duration / buff.duration_max
call(function_name, rate)
@@ -70,158 +84,158 @@ func remove_buff(buff_name: String):
#==具体实现==
#位移
-func on_end_hit_back(rate)->void: status.hit_back_speed = 0
+func on_end_hit_back(_rate) -> void: status.set_status("hit_back_speed", 0)
-func on_end_hit_up(rate)->void: status.hit_up_speed = 0
+func on_end_hit_up(_rate) -> void: status.set_status("hit_up_speed", 0)
-func on_start_jumping(rate)->void: status.is_jumping = true
+func on_start_jumping(_rate) -> void: status.set_status("is_jumping", true)
-func on_end_jumping(rate)->void: status.is_jumping = false
+func on_end_jumping(_rate) -> void: status.set_status("is_jumping", false)
-func on_start_rising(rate)->void: status.is_rising = true
+func on_start_rising(_rate) -> void: status.set_status("is_rising", true)
-func on_end_rising(rate)->void: status.is_rising = false
+func on_end_rising(_rate) -> void: status.set_status("is_rising", false)
-func on_start_floating(rate)->void:
- status.is_floating = true
+func on_start_floating(_rate) -> void:
+ status.set_status("is_floating", true)
add_buff("rising", 0.1)
-func on_update_floating(rate) -> void:
+func on_update_floating(_rate) -> void:
if not status.is_on_floor or status.is_rising:
return
remove_buff("floating")
add_buff("stagger", 3)
-func on_end_floating(rate)->void: status.is_floating = false
+func on_end_floating(_rate) -> void: status.set_status("is_floating", false)
#战斗状态
-func on_start_die(rate)->void:
- status.is_dead = true
+func on_start_die(_rate) -> void:
+ status.set_status("is_dead", true)
SignalManager.character_die.emit(status.id)
-func on_end_die(rate)->void: add_buff("die2", -1)
+func on_end_die(_rate) -> void: add_buff("die2", -1)
-func on_update_die2(rate)->void: if status.is_on_floor and not status.is_rising: remove_buff("die2")
+func on_update_die2(_rate) -> void: if status.is_on_floor and not status.is_rising: remove_buff("die2")
-func on_end_die2(rate)->void:
+func on_end_die2(_rate) -> void:
effect.cast_corpse()
Global.character_mgr.destroy_character(status.id)
-func on_start_stagger(rate)->void:
- status.is_stagger = true
+func on_start_stagger(_rate) -> void:
+ status.set_status("is_stagger", true)
status.set_skill_break_level_add(-1)
-func on_end_stagger(rate)->void:
- status.is_stagger = false
+func on_end_stagger(_rate) -> void:
+ status.set_status("is_stagger", false)
status.set_skill_break_level_add(0)
-func on_end_shield_recover_cd(rate)->void: add_buff("shield_recover", -1)
+func on_end_shield_recover_cd(_rate) -> void: add_buff("shield_recover", -1)
-func on_update_shield_recover(rate)->void:
+func on_update_shield_recover(_rate) -> void:
var shield_add: float = get_process_delta_time() * status.cfg.shield.recover_speed
shield_add = min(status.shield_max - status.shield, shield_add)
if shield_add == status.shield_max - status.shield:
remove_buff("shield_recover")
- character.set_shield( status.shield+shield_add)
+ character.set_shield(status.shield + shield_add)
-func on_end_mp_recover_cd(rate)->void: add_buff("mp_recover", -1)
+func on_end_mp_recover_cd(_rate) -> void: add_buff("mp_recover", -1)
-func on_update_mp_recover(rate)->void:
+func on_update_mp_recover(_rate) -> void:
var mp_add: float = get_process_delta_time() * status.cfg.mp.recover_speed
character.add_mp_sub(mp_add, false)
-func on_update_charging(rate)->void:
+func on_update_charging(_rate) -> void:
var mp_add: float = get_process_delta_time() * status.cfg.mp.charging_speed
character.add_mp_sub(mp_add, true)
-func on_end_stun_recover_break_cd(rate)->void: add_buff("stun_recover_break", -1)
+func on_end_stun_recover_break_cd(_rate) -> void: add_buff("stun_recover_break", -1)
-func on_update_stun_recover_break(rate)->void:
+func on_update_stun_recover_break(_rate) -> void:
var stun_sub: float = get_process_delta_time() * status.cfg.stun.recover_break_speed
stun_sub = min(status.stun, stun_sub)
- character.set_status("stun", status.stun-stun_sub)
+ status.set_status("stun", status.stun - stun_sub)
if status.stun == 0:
remove_buff("stun_recover_break")
- character.set_status("is_stun", false)
+ status.set_status("is_stun", false)
-func on_end_stun_recover_cd(rate)->void: add_buff("stun_recover", -1)
+func on_end_stun_recover_cd(_rate) -> void: add_buff("stun_recover", -1)
-func on_update_stun_recover(rate)->void:
+func on_update_stun_recover(_rate) -> void:
var stun_sub: float = get_process_delta_time() * status.cfg.stun.recover_speed
stun_sub = min(status.stun, stun_sub)
- character.set_status("stun", status.stun-stun_sub)
+ status.set_status("stun", status.stun - stun_sub)
if status.stun == 0:
remove_buff("stun_recover")
-func on_update_weapon_index_change(rate)->void: character.set_status("weapon_index_change_rate", rate)
+func on_update_weapon_index_change(rate) -> void: status.set_status("weapon_index_change_rate", rate)
-func on_end_weapon_index_change(rate)->void:
+func on_end_weapon_index_change(_rate) -> void:
var weapon_index: int = status.weapon_index + status.weapon_index_change_dir
- var weapon_len: int = len(status.weapon_list)
+ var weapon_len: int = len(status.weapon_list)
weapon_index = (weapon_index % weapon_len + weapon_len) % weapon_len
- character.set_status("weapon_index", weapon_index)
- character.set_status("weapon_index_change_dir", 0)
+ status.set_status("weapon_index", weapon_index)
+ status.set_status("weapon_index_change_dir", 0)
#表现
-func on_start_freeze(rate)->void: status.is_pause = true
+func on_start_freeze(_rate) -> void: status.set_status("is_pause", true)
-func on_end_freeze(rate)->void: status.is_pause = false
+func on_end_freeze(_rate) -> void: status.set_status("is_pause", false)
-func on_second_pause(rate)->void: status.is_pause = true
+func on_second_pause(_rate) -> void: status.set_status("is_pause", true)
-func on_end_pause(rate)->void: status.is_pause = false
+func on_end_pause(_rate) -> void: status.set_status("is_pause", false)
-func on_start_flash_white(rate)->void: status.flash_white_rate = 1
+func on_start_flash_white(_rate) -> void: status.set_status("flash_white_rate", 1)
-func on_update_flash_white(rate)->void: status.flash_white_rate = 1 - rate
+func on_update_flash_white(rate) -> void: status.set_status("flash_white_rate", 1 - rate)
-func on_end_flash_white(rate)->void: status.flash_white_rate = 0
+func on_end_flash_white(_rate) -> void: status.set_status("flash_white_rate", 0)
-func on_update_shake_x(rate)->void:
+func on_update_shake_x(rate) -> void:
var shake_rate: float = 0.5 * status.pause_time
- status.shake_offset = Vector3((sin(rate * PI * 6) - 0.5)*shake_rate, 0, 0);
+ status.set_status("shake_offset", Vector3((sin(rate * PI * 6) - 0.5) * shake_rate, 0, 0))
-func on_end_shake_x(rate)->void: status.shake_offset = Vector3.ZERO
+func on_end_shake_x(_rate) -> void: status.set_status("shake_offset", Vector3.ZERO)
-func on_start_deformation(rate)->void: status.deformation_rate = 1;
+func on_start_deformation(_rate) -> void: status.set_status("deformation_rate", 1)
-func on_update_deformation(rate)->void: status.deformation_rate = 1 - rate
+func on_update_deformation(rate) -> void: status.set_status("deformation_rate", 1 - rate)
-func on_end_deformation(rate)->void: status.deformation_rate = 0
+func on_end_deformation(_rate) -> void: status.set_status("deformation_rate", 0)
diff --git a/script/character/character.gd b/script/character/character.gd
index 46bb64d..947fe69 100644
--- a/script/character/character.gd
+++ b/script/character/character.gd
@@ -62,11 +62,11 @@ func set_body_scale(cfg: CharacterCfg) -> void:
collision.scale = body_scale
pushbox.position = Vector3(0, half_height, 0)
pushbox.scale = body_scale
- status.basic_offset = Vector3(0, center_height, randf() * 0.001)
- status.ui_offset = Vector3(0, height * 1.25, 0)
- status.ui_center_offset = Vector3(0, half_height, 0)
- status.radius = width
- status.height = height
+ status.set_status("basic_offset", Vector3(0, center_height, randf() * 0.001))
+ status.set_status("ui_offset", Vector3(0, height * 1.25, 0))
+ status.set_status("ui_center_offset", Vector3(0, half_height, 0))
+ status.set_status("radius", width)
+ status.set_status("height", height)
effect.set_body_scale(body_scale)
@@ -132,7 +132,7 @@ func set_pos(pos_new: Vector3):
func emit_pos_changed():
SignalManager.character_pos_changed.emit(id(), pos())
-func move_to(dir: Vector2):
+func move_to(dir: Vector2):
set_status("move_dir", dir.normalized())
@@ -161,18 +161,19 @@ func has_buff(buff_name: String) -> bool: return buff.has_buff(buff_name)
func set_hit_move(hit_back_dir: Vector2, hit_back_speed: float, hit_up_speed: float):
- status.hit_back_dir = hit_back_dir
- status.hit_back_speed = hit_back_speed
- status.hit_up_speed = hit_up_speed
+ status.set_status("hit_back_dir", hit_back_dir)
+ status.set_status("hit_back_speed", hit_back_speed)
+ status.set_status("hit_up_speed", hit_up_speed)
func set_pause_time(pause_time: float):
- status.pause_time = pause_time
+ status.set_status("pause_time", pause_time)
add_buff("pause", pause_time)
func add_ai_skill_order(order: Status.SkillOrder):
status.ai_skill_order.append(order)
+ status.emit_status("ai_skill_order")
func cast_skill_by_name(skill_name: String, cast_dir: Vector2) -> void:
@@ -186,8 +187,7 @@ func cancel_skill():
func set_view_trigger(trigger_name: String):
- status.set("trigger_%s" % trigger_name, true)
- view.tick_view()
+ status.set_status("trigger_%s" % trigger_name, true)
func show_hit_text(value: String):
diff --git a/script/character/hitbox.gd b/script/character/hitbox.gd
index 797f3d8..4a1f474 100644
--- a/script/character/hitbox.gd
+++ b/script/character/hitbox.gd
@@ -4,6 +4,7 @@ class_name Hitbox
@export var pushbox_curve: Curve
@onready var character: Character = (get_owner() as Character)
+@onready var status: Status = (%Status as Status)
var radius: float
var pushbox_list: Array[Hitbox] = []
@@ -11,45 +12,49 @@ var pushbox_list: Array[Hitbox] = []
func _ready():
var collisionShape3D: CollisionShape3D = $CollisionShape3D as CollisionShape3D
- var shape: CylinderShape3D = collisionShape3D.shape as CylinderShape3D
+ var shape: CylinderShape3D = collisionShape3D.shape as CylinderShape3D
radius = shape.radius * scale.x
+ area_entered.connect(_on_area_entered)
+ area_exited.connect(_on_area_exited)
+
func _process(_delta) -> void:
- var speed_dir: Vector2 = character.get_status("speed_dir") as Vector2
- if speed_dir.length() == 0:
- return
- var is_skill_running: bool = character.get_status("is_skill_running") as bool
+ var is_skill_running: bool = status.is_skill_running
if not is_skill_running:
- character.set_status("speed_down_push_rate", 0)
return
- var skill_cfg: SkillCfg = character.get_status("skill_cfg") as SkillCfg
+ var speed_dir: Vector2 = status.speed_dir
+ if speed_dir.length() == 0:
+ return
+ var skill_cfg: SkillCfg = status.skill_cfg
if not skill_cfg:
return
if skill_cfg.ignore_push:
- character.set_status("speed_down_push_rate", 0)
+ status.speed_down_push_rate = 0
return
var speed_down_push_rate: float = 0
- var pos: Vector2 = character.pos2D()
+ var pos: Vector2 = character.pos2D()
for pushbox: Hitbox in pushbox_list:
var target_pos: Vector2 = pushbox.character.pos2D()
- var dir: Vector2 = target_pos - pos
+ var dir: Vector2 = target_pos - pos
if speed_dir.dot(dir) <= 0:
continue
var dist: float = dir.length()
if dist == 0:
continue
- var dist_rate = clamp(dist/(radius+pushbox.radius), 0, 1)
+ var dist_rate = clamp(dist / (radius + pushbox.radius), 0, 1)
speed_down_push_rate = max(speed_down_push_rate, pushbox_curve.sample(dist_rate))
- character.set_status("speed_down_push_rate", speed_down_push_rate)
+ status.speed_down_push_rate = speed_down_push_rate
return
-func on_area_entered(area: Area3D):
+func _on_area_entered(area: Area3D):
if area is Hitbox:
- pushbox_list.append(area)
+ if area.character.team() != character.team():
+ pushbox_list.append(area)
-func on_area_exited(area: Area3D):
+func _on_area_exited(area: Area3D):
if area is Hitbox:
- pushbox_list.erase(area)
+ if area.character.team() != character.team():
+ pushbox_list.erase(area)
diff --git a/script/character/move.gd b/script/character/move.gd
index f131acd..9844304 100644
--- a/script/character/move.gd
+++ b/script/character/move.gd
@@ -28,7 +28,7 @@ func move_tick(delta) -> bool:
update_move(delta)
update_speed_y(delta)
var is_against_wall: bool = update_move_check(delta)
- status.velocity_change = character.velocity.abs() - velocity_cache
+ status.set_status("velocity_change", character.velocity.abs() - velocity_cache)
velocity_cache = character.velocity.abs()
if character.velocity:
SignalManager.character_pos_changed.emit(character.id(), character.pos())
@@ -45,9 +45,9 @@ func move_tick(delta) -> bool:
func update_on_floor() -> bool:
var is_on_floor: bool = character.is_on_floor()
var is_hit: bool = not status.is_on_floor and is_on_floor
- status.is_on_floor = is_on_floor
+ status.set_status("is_on_floor", is_on_floor)
if status.is_on_floor and not status.is_jumping:
- status.is_jumped = false
+ status.set_status("is_jumped", false)
var is_skill_running: bool = status.is_skill_running and status.break_level != Enum.EBreakLevel.Walk
if is_hit and not status.is_stagger and not is_skill_running:
Global.effect_mgr.cast_particle(ResourceManager.particle_move_hit_ground, character.pos())
@@ -64,7 +64,7 @@ func update_speed_y(delta) -> void:
else:
if not status.is_on_floor:
character.velocity.y -= gravity * delta * status.cfg.move.gravity_scale
- status.speed_y = character.velocity.y
+ status.set_status("speed_y", character.velocity.y)
func update_move(delta):
@@ -73,7 +73,7 @@ func update_move(delta):
var skill_velocity: Vector2 = status.skill_move_dir * status.skill_move_speed if not status.skill_move_stop else Vector2.ZERO
var hit_back_velocity: Vector2 = status.hit_back_dir * status.hit_back_speed
move_velocity += skill_velocity + hit_back_velocity
- status.speed_dir = Vector2(move_velocity.x, move_velocity.y)
+ status.set_status("speed_dir", Vector2(move_velocity.x, move_velocity.y))
if skill_velocity.length() > 0:
move_velocity *= (1 - status.speed_down_push_rate)
@@ -87,9 +87,9 @@ func update_move(delta):
character.velocity.x = move_velocity.x
character.velocity.z = move_velocity.y
- status.speed_xz = Vector2(character.velocity.x, character.velocity.z).length()
+ status.set_status("speed_xz", Vector2(character.velocity.x, character.velocity.z).length())
if status.is_free_turn and status.move_dir.x != 0:
- status.is_right = status.move_dir.x > 0
+ status.set_status("is_right", status.move_dir.x > 0)
func update_deformation(_delta):
@@ -100,11 +100,11 @@ func update_deformation(_delta):
var dir_x: int = 1 if (velocity_change_x > 1) or (velocity_change_y < -1) else 0
var dir_y: int = 1 if (velocity_change_y > 1) or (velocity_change_x < -1) else 0
if dir_x or dir_y:
- status.deformation_dir = Vector2(dir_x, dir_y)
+ status.set_status("deformation_dir", Vector2(dir_x, dir_y))
character.add_buff("deformation", 0.4)
-func update_move_effect(delta):
+func update_move_effect(_delta):
var character_type: Enum.ECharacterType = character.cfg().type;
match character_type:
Enum.ECharacterType.Player: pass
@@ -116,7 +116,6 @@ func update_move_effect(delta):
var after_image_alpha: float = clamp(after_image_speed_curve.sample(speed_rate), 0, 1)
if after_image_alpha > 0:
effect.cast_after_image(after_image_alpha)
- pass
if speed > 6:
Global.effect_mgr.cast_particle(ResourceManager.particle_move_speed, character.view_pos(), character.velocity.normalized())
var velocity_change_sum: float = status.velocity_change.x + status.velocity_change.y + status.velocity_change.z
@@ -124,7 +123,7 @@ func update_move_effect(delta):
Global.effect_mgr.cast_particle(ResourceManager.particle_move_dash, character.view_pos(), character.velocity.normalized())
-func update_move_check(delta) -> bool:
+func update_move_check(_delta) -> bool:
var velocity: Vector3 = character.velocity
character.move_and_slide()
var collision_count: int = character.get_slide_collision_count()
@@ -164,7 +163,7 @@ func update_move_check(delta) -> bool:
func jump():
character.velocity.y = status.cfg.move.jump_velocity
# status.is_jumped = true
- status.trigger_jump = true
+ character.set_view_trigger("jump")
buff.add_buff("jumping", 0.1)
if status.is_on_floor:
Global.effect_mgr.cast_particle(ResourceManager.particle_move_jump_ground, character.pos(), character.velocity.normalized())
diff --git a/script/character/player/combo.gd b/script/character/player/combo.gd
index e0c6361..3a03649 100644
--- a/script/character/player/combo.gd
+++ b/script/character/player/combo.gd
@@ -21,7 +21,7 @@ func _ready():
# test
add_basic_skill()
add_weapon(load("res://config/weapon/long.tres") as WeaponCfg)
- # add_weapon(load("res://config/weapon/short.tres") as WeaponCfg)
+ add_weapon(load("res://config/weapon/short.tres") as WeaponCfg)
add_weapon(load("res://config/weapon/fist.tres") as WeaponCfg)
core.set_active_core(0, load("res://config/core/hero01_soul_slash.tres") as CoreCfg)
diff --git a/script/character/skill.gd b/script/character/skill.gd
index f530e2b..984df8d 100644
--- a/script/character/skill.gd
+++ b/script/character/skill.gd
@@ -15,6 +15,7 @@ var skill_map: Dictionary = {} # input -> skillCfg[]
func init():
+ animation_finished.connect(_on_animation_finished)
cancel_skill()
@@ -142,27 +143,28 @@ func cast_skill(cfg: SkillCfg, cast_dir: Vector2, action_key: String = "") -> vo
#技能重复次数
if status.skill_cfg and status.skill_cfg == cfg:
- status.skill_repeat_count += 1
+ status.set_status("skill_repeat_count", 1)
else:
- status.skill_repeat_count = 0
+ status.set_status("skill_repeat_count", 0)
break_skill()
- status.speed_up_rate = -1
- status.is_free_control = false
- status.is_free_turn = false
- status.is_skill_running = true
- status.skill_cfg = cfg
- status.skill_dir = cast_dir.normalized()
- status.skill_move_dir = skill_move_dir
- status.break_level = Enum.EBreakLevel.None
- status.stance = cfg.stance_to
- status.is_charging = cfg.is_charging
- status.skill_action_key = action_key
+ status.set_status("speed_up_rate", -1)
+ status.set_status("is_free_control", false)
+ status.set_status("is_free_turn", false)
+ status.set_status("is_skill_running", true)
+ status.set_status("skill_cfg", cfg)
+ status.set_status("skill_dir", cast_dir.normalized())
+ status.set_status("skill_move_dir", skill_move_dir)
+ status.set_status("break_level", Enum.EBreakLevel.None)
+ status.set_status("stance", cfg.stance_to)
+ status.set_status("is_charging", cfg.is_charging)
+ status.set_status("skill_action_key", action_key)
status.set_skill_break_level_add(cfg.mp_cost) # todo
character.set_body_scale(cfg.get_owner())
if cfg.is_charging:
buff.add_buff("charging", -1)
- if cast_dir.x != 0: status.is_right = cast_dir.x > 0
+ if cast_dir.x != 0:
+ status.set_status("is_right", cast_dir.x > 0)
#预警特效
match cfg.warn_type:
Enum.ESkillWarnType.Normal: character.cast_particle(ResourceManager.particle_warn_normal, true)
@@ -172,29 +174,29 @@ func cast_skill(cfg: SkillCfg, cast_dir: Vector2, action_key: String = "") -> vo
var animation_name: String = "animation_library/%s" % cfg.get_res_name()
play(animation_name, -1, Setting.animation_speed_scale)
- seek(0, true, true)
+ seek(0.05, true, true)
battle.on_skill_cast(cfg.get_res_name())
func break_skill():
stop()
- status.speed_up_rate = 0
- status.skill_move_speed = 0
- status.skill_float_speed = 0
- status.is_free_control = true
- status.is_free_turn = true
- status.is_skill_running = false
- status.skill_cfg = null
- status.break_level = Enum.EBreakLevel.Walk
- status.speed_down_push_rate = 0
- status.skill_move_stop = false
- status.is_speed_y_freeze = false
- status.is_charging = false
- status.charging_level = 0
- status.skill_action_key = ""
- status.is_hit_character = false
- status.is_hit_wall = false
+ status.set_status("speed_up_rate", 0)
+ status.set_status("skill_move_speed", 0)
+ status.set_status("skill_float_speed", 0)
+ status.set_status("is_free_control", true)
+ status.set_status("is_free_turn", true)
+ status.set_status("is_skill_running", false)
+ status.set_status("skill_cfg", null)
+ status.set_status("break_level", Enum.EBreakLevel.Walk)
+ status.set_status("speed_down_push_rate", 0)
+ status.set_status("skill_move_stop", false)
+ status.set_status("is_speed_y_freeze", false)
+ status.set_status("is_charging", false)
+ status.set_status("charging_level", 0)
+ status.set_status("skill_action_key", "")
+ status.set_status("is_hit_character", false)
+ status.set_status("is_hit_wall", false)
status.set_skill_break_level_add(0)
buff.remove_buff("charging")
buff.remove_buff("pause")
@@ -203,7 +205,7 @@ func break_skill():
var character_to: Character = Global.character_mgr.get_character(status.throw_target)
if character_to:
character_to.set_status("is_be_throw", false)
- status.throw_target = 0
+ status.set_status("throw_target", 0)
effect.release_effect()
@@ -230,7 +232,7 @@ func on_check_charging(charging_level: int) -> void:
_frame_forward()
return
if status.mp >= charging_level:
- status.charging_level += 1
+ status.set_status("charging_level", status.charging_level + 1)
_frame_forward()
return
_frame_back(1)
diff --git a/script/character/status.gd b/script/character/status.gd
index 209a54d..2b4973a 100644
--- a/script/character/status.gd
+++ b/script/character/status.gd
@@ -12,6 +12,7 @@ class BulletOrder:
var cast_dir: Vector2
var target: int
+signal character_status_changed
#实体属性
var id: int #id
@@ -129,12 +130,16 @@ func get_status(status_name: String) -> Variant: return get(status_name)
func set_status(status_name: String, value: Variant):
+ if value == get_status(status_name):
+ return
set(status_name, value)
SignalManager.character_status_changed.emit(id, status_name, value)
+ character_status_changed.emit(status_name, value)
func emit_status(status_name: String):
SignalManager.character_status_changed.emit(id, status_name, get_status(status_name))
+ character_status_changed.emit(status_name, get_status(status_name))
func set_shield(value: float):
diff --git a/script/character/view.gd b/script/character/view.gd
index 0dcefac..dd96a24 100644
--- a/script/character/view.gd
+++ b/script/character/view.gd
@@ -11,13 +11,29 @@ class Trans:
var from: StringName
var to: StringName
var trigger_name: StringName
- var on_end: bool
-var trans_dict: Dictionary = {}
+var trans_dict: Dictionary = {} # {condition/trigger:{from:Trans}}
var move_sprite_frames: SpriteFrames
+func init(default: SpriteFrames):
+ sprite_frames = default
+ move_sprite_frames = default
+
+ status.character_status_changed.connect(_on_character_status_changed)
+ animation_finished.connect(_on_animation_finished)
+ animation_changed.connect(_on_animation_changed)
+ frame_changed.connect(_on_frame_changed)
+ trans_register()
+ play_animation("idle_loop")
+
+func reset():
+ sprite_frames = move_sprite_frames
+ if status.is_on_floor:
+ play_animation("idle_loop")
+ else:
+ play_animation("jump4_loop")
-func _ready():
+func trans_register() -> void:
# 地面行走
trans("idle_loop", "run1", "speed_xz", ">", 1)
run("run1", "run2_loop")
@@ -68,60 +84,52 @@ func _ready():
trigger("any", "rebound", "trigger_rebound")
run("rebound", "airhit2_loop")
-
-func _process(_delta) -> void:
- tick_view()
-
-
-func tick_view() -> void:
- update_flip()
- if not sprite_frames: return
+func _on_character_status_changed(status_name, value) -> void:
+ if status_name == "is_right":
+ scale.x = 1 if status.is_right else -1
if status.is_be_throw: return
- if not status.is_skill_running and status.is_pause == is_playing():
- if status.is_pause: pause()
- else: play_animation(animation)
- update_view()
- if status.is_pause: return
- update_trans(false)
- update_material()
- return
+ if status_name == "is_skill_running" or status_name == "is_pause":
+ if not status.is_skill_running and status.is_pause == is_playing():
+ if status.is_pause: pause()
+ else: play_animation(animation)
+ if status_name == "basic_offset" or status_name == "shake_offset":
+ position = status.basic_offset + status.shake_offset
+ # global_position = Util.snap_vector3(global_position)
+ if status.is_pause:
+ return
+ if status_name in ["deformation_rate", "is_floating", "flash_white_rate", "deformation_rate"]:
+ update_material()
+ update_trans(status_name, value)
+
+func _on_animation_finished():
+ update_trans("animation_end", null)
-func init(default: SpriteFrames):
- sprite_frames = default
- move_sprite_frames = default
- play_animation("idle_loop")
+func _on_animation_changed() -> void:
+ update_material_tex()
+func _on_frame_changed() -> void:
+ update_material_tex()
-func reset():
- sprite_frames = move_sprite_frames
- if status.is_on_floor:
- play_animation("idle_loop")
- else:
- play_animation("jump4_loop")
func run(from: StringName, to: StringName):
- _add_trans(from, to, "", "", "", "", true)
-
-
-func run_with_condition(from: StringName, to: StringName, condition, compareType, conditionValue):
- _add_trans(from, to, condition, compareType, conditionValue, "", true)
+ _add_trans(from, to, "animation_end", "", "", "")
func trans(from: StringName, to: StringName, condition, compareType, conditionValue):
- _add_trans(from, to, condition, compareType, conditionValue, "", false)
+ _add_trans(from, to, condition, compareType, conditionValue, "")
func trigger(from: StringName, to: StringName, trigger_name: StringName):
- _add_trans(from, to, "", "", "", trigger_name, false)
+ _add_trans(from, to, "", "", "", trigger_name)
func trigger_with_condition(from: StringName, to: StringName, trigger_name: StringName, condition, compareType, conditionValue):
- _add_trans(from, to, condition, compareType, conditionValue, trigger_name, false)
+ _add_trans(from, to, condition, compareType, conditionValue, trigger_name)
-func _add_trans(from: StringName, to: StringName, condition, compareType, conditionValue, trigger_name: StringName, on_end: bool):
+func _add_trans(from: StringName, to: StringName, condition, compareType, conditionValue, trigger_name: StringName):
var new_trans = Trans.new()
new_trans.condition = condition
new_trans.compareType = compareType
@@ -129,51 +137,44 @@ func _add_trans(from: StringName, to: StringName, condition, compareType, condit
new_trans.from = from
new_trans.to = to
new_trans.trigger_name = trigger_name
- new_trans.on_end = on_end
- if not from in trans_dict:
- trans_dict[from] = []
- trans_dict[from].append(new_trans)
-
-
-func update_trans(on_end: bool):
- if not update_trans_by_from("any", on_end):
- update_trans_by_from(animation, on_end)
-
-func update_trans_by_from(from: String, on_end: bool) -> bool:
- if not from in trans_dict:
- return false
- for trans_single in trans_dict[from]:
- if on_end != trans_single.on_end:
- continue
- if trans_single.condition != "":
- var conditionValue = status.get(trans_single.condition)
- match trans_single.compareType:
- ">": if conditionValue <= trans_single.conditionValue: continue
- "<": if conditionValue >= trans_single.conditionValue: continue
- ">=": if conditionValue < trans_single.conditionValue: continue
- "<=": if conditionValue > trans_single.conditionValue: continue
- "=": if conditionValue != trans_single.conditionValue: continue
- if trans_single.trigger_name != "":
- if status.get(trans_single.trigger_name):
- status.set(trans_single.trigger_name, false)
- else: continue
- play_animation(trans_single.to)
- return true
- return false
-
-func update_flip():
- scale.x = 1 if status.is_right else -1
-func update_view():
- position = status.basic_offset + status.shake_offset
+ if trigger_name != "":
+ if not trigger_name in trans_dict:
+ trans_dict[trigger_name] = {}
+ trans_dict[trigger_name][from] = new_trans
+ else:
+ if not condition in trans_dict:
+ trans_dict[condition] = {}
+ trans_dict[condition][from] = new_trans
-# global_position = Util.snap_vector3(global_position)
+func update_trans(key: String, value) -> void:
+ if not key in trans_dict:
+ return
+ if animation in trans_dict[key]:
+ update_trans_single(trans_dict[key][animation], value)
+ if "any" in trans_dict[key]:
+ update_trans_single(trans_dict[key]["any"], value)
+
+
+func update_trans_single(trans_single: Trans, value) -> void:
+ if trans_single.condition != "":
+ match trans_single.compareType:
+ ">": if value <= trans_single.conditionValue: return
+ "<": if value >= trans_single.conditionValue: return
+ ">=": if value < trans_single.conditionValue: return
+ "<=": if value > trans_single.conditionValue: return
+ "=": if value != trans_single.conditionValue: return
+ if trans_single.trigger_name != "":
+ if status.get(trans_single.trigger_name):
+ status.set(trans_single.trigger_name, false)
+ play_animation(trans_single.to)
-func _on_animation_finished():
- update_trans(true)
+func update_view():
+ position = status.basic_offset + status.shake_offset
+# global_position = Util.snap_vector3(global_position)
func update_material() -> void:
@@ -186,17 +187,31 @@ func _update_material():
return
var material: ShaderMaterial = material_override as ShaderMaterial
var material2: ShaderMaterial = material_override.next_pass as ShaderMaterial
- var tex: Texture2D = sprite_frames.get_frame_texture(animation, frame)
var deformation_rate: float = status.deformation_rate * (0.6 if status.is_floating else 0.4)
if material:
material.set_shader_parameter("flash_white", status.flash_white_rate)
material.set_shader_parameter("deformation_dir", status.deformation_dir)
material.set_shader_parameter("deformation_rate", deformation_rate)
- material.set_shader_parameter("tex", tex)
if material2:
material2.set_shader_parameter("flash_white", status.flash_white_rate)
material2.set_shader_parameter("deformation_dir", status.deformation_dir)
material2.set_shader_parameter("deformation_rate", deformation_rate)
+
+
+func update_material_tex() -> void:
+ call_deferred("_update_material_tex")
+ return
+
+
+func _update_material_tex():
+ if not sprite_frames:
+ return
+ var material: ShaderMaterial = material_override as ShaderMaterial
+ var material2: ShaderMaterial = material_override.next_pass as ShaderMaterial
+ var tex: Texture2D = sprite_frames.get_frame_texture(animation, frame)
+ if material:
+ material.set_shader_parameter("tex", tex)
+ if material2:
material2.set_shader_parameter("tex", tex)
diff --git a/script/config/character_cfg.gd b/script/config/character_cfg.gd
index d270ab2..7d2bc3b 100644
--- a/script/config/character_cfg.gd
+++ b/script/config/character_cfg.gd
@@ -14,7 +14,7 @@ class_name CharacterCfg
@export var stun: StunCfg
@export var mp: MpCfg
@export var ai: AICfg
-@export var ai_behavior_tree: PackedScene
+@export var ai_behavior_tree: BehaviorTree
@export_group("战斗数值")
@export var hp_max: float
@export var attack: float
@@ -26,54 +26,50 @@ class_name CharacterCfg
@export var sub_character: CharacterCfg
@export var sub_character_auto_create: bool
@export_group("受击材质")
-@export var material_on: Enum.EMaterial = Enum.EMaterial.None #有护盾时材质
-@export var material_off: Enum.EMaterial = Enum.EMaterial.None #无护盾时材质
+@export var material_on: Enum.EMaterial = Enum.EMaterial.None # 有护盾时材质
+@export var material_off: Enum.EMaterial = Enum.EMaterial.None # 无护盾时材质
var core_cfg_list: Array[CoreCfg]
-func get_attack1()->AttackCfg: return attack1
+func get_attack1() -> AttackCfg: return attack1
-func get_attack1_box()->AttackBoxCfg: return attack1_box
+func get_attack1_box() -> AttackBoxCfg: return attack1_box
-func get_attack2()->AttackCfg: return attack2
+func get_attack2() -> AttackCfg: return attack2
-func get_attack2_box()->AttackBoxCfg: return attack2_box
+func get_attack2_box() -> AttackBoxCfg: return attack2_box
-func get_particle()->Resource:
- var res_name: String = get_res_name()
+func get_particle() -> Resource:
+ var res_name: String = get_res_name()
var path_default: String = "res://scene/effect/particle/%s.tscn" % res_name
if ResourceLoader.exists(path_default):
return load(path_default)
return null
-func get_ai()->PackedScene:
+func get_ai() -> BehaviorTree:
if ai_behavior_tree:
return ai_behavior_tree
- var res_name: String = get_res_name()
- var path_default: String = "res://scene/ai/%s.tscn" % res_name
- if ResourceLoader.exists(path_default):
- return load(path_default) as PackedScene
return null
-func get_core_cfg_list()->Array[CoreCfg]:
+func get_core_cfg_list() -> Array[CoreCfg]:
if core_cfg_list:
return core_cfg_list
core_cfg_list = []
var res_name: String = get_res_name()
var dir_path: String = "res://config/core"
- var dir: DirAccess = DirAccess.open(dir_path)
+ var dir: DirAccess = DirAccess.open(dir_path)
for file in dir.get_files():
if not file.begins_with(res_name):
continue
var path: String = dir_path + "/" + file
- var res = load(path)
+ var res = load(path)
if res is CoreCfg:
core_cfg_list.append(res)
return core_cfg_list
diff --git a/script/level/level.gd b/script/level/level.gd
index cd11b1a..0c86628 100644
--- a/script/level/level.gd
+++ b/script/level/level.gd
@@ -21,7 +21,7 @@ func init() -> void:
for level_instance in level_instance_list:
level_instance.init_level_character()
level_instance.init_level_main()
-
+
func get_level_instance_list() -> Array[LevelInstance]:
if not level_instance_list:
diff --git a/script/manager/ai_manager.gd b/script/manager/ai_manager.gd
index 3ca72e9..7e1cd68 100644
--- a/script/manager/ai_manager.gd
+++ b/script/manager/ai_manager.gd
@@ -16,6 +16,7 @@ func _process(delta) -> void:
tick_time_left = 0
if tick_time_left > 0:
return
+ return
var player: Character = Global.character_mgr.get_player()
if not player: return
var enemy_list: Array[Character] = Global.character_mgr.get_enemy_list(player.id())