From 96402839642dc8f28066c65c1db989de4e0a2742 Mon Sep 17 00:00:00 2001 From: adtpdn Date: Tue, 28 Jan 2025 14:17:29 +0800 Subject: [PATCH] update --- scenes/main.gd | 12 +- scenes/main.tscn | 2 - scenes/player.gd | 2 +- scenes/player.tscn | 6 +- scripts/behaviors/actions/do_arrange.gd | 26 ++++ scripts/behaviors/actions/do_grab.gd | 27 ++++ scripts/behaviors/actions/do_move.gd | 44 +++++++ scripts/behaviors/actions/do_put.gd | 28 ++++ scripts/behaviors/actions/grab_action.gd | 11 ++ scripts/behaviors/arrange_sequence.gd | 5 + .../behaviors/conditions/arrange_action.gd | 22 ++++ .../behaviors/conditions/arrange_condition.gd | 18 +++ scripts/behaviors/conditions/can_arrange.gd | 16 +++ scripts/behaviors/conditions/can_grab.gd | 25 ++++ scripts/behaviors/conditions/can_put.gd | 31 +++++ .../behaviors/conditions/grab_condition.gd | 21 +++ scripts/behaviors/conditions/has_ap.gd | 6 + scripts/behaviors/conditions/should_move.gd | 85 +++++++++++++ scripts/behaviors/sequences/grab_sequence.gd | 5 + scripts/behaviors/sequences/move_sequence.gd | 5 + scripts/behaviors/sequences/put_sequence.gd | 5 + scripts/bot_behavior.gd | 120 ++++++++++++++++++ 22 files changed, 512 insertions(+), 10 deletions(-) create mode 100644 scripts/behaviors/actions/do_arrange.gd create mode 100644 scripts/behaviors/actions/do_grab.gd create mode 100644 scripts/behaviors/actions/do_move.gd create mode 100644 scripts/behaviors/actions/do_put.gd create mode 100644 scripts/behaviors/actions/grab_action.gd create mode 100644 scripts/behaviors/arrange_sequence.gd create mode 100644 scripts/behaviors/conditions/arrange_action.gd create mode 100644 scripts/behaviors/conditions/arrange_condition.gd create mode 100644 scripts/behaviors/conditions/can_arrange.gd create mode 100644 scripts/behaviors/conditions/can_grab.gd create mode 100644 scripts/behaviors/conditions/can_put.gd create mode 100644 scripts/behaviors/conditions/grab_condition.gd create mode 100644 scripts/behaviors/conditions/has_ap.gd create mode 100644 scripts/behaviors/conditions/should_move.gd create mode 100644 scripts/behaviors/sequences/grab_sequence.gd create mode 100644 scripts/behaviors/sequences/move_sequence.gd create mode 100644 scripts/behaviors/sequences/put_sequence.gd create mode 100644 scripts/bot_behavior.gd diff --git a/scenes/main.gd b/scenes/main.gd index 6ea69e0..546f626 100644 --- a/scenes/main.gd +++ b/scenes/main.gd @@ -273,16 +273,16 @@ func create_bot(bot_id): var bot_character = player_scene.instantiate() bot_character.set_multiplayer_authority(1) bot_character.name = str(bot_id) - - # Add Beehave tree - var behavior_tree = preload("res://scripts/bot_behavior_tree.gd").new() - bot_character.add_child(behavior_tree) - behavior_tree.name = "BehaviorTree" - add_child(bot_character) bot_character.add_to_group("Players", true) bot_character.add_to_group("Bots", true) + # The BehaviorTree will auto-activate for bots + var behavior_tree = bot_character.get_node_or_null("BotBehavior") + if behavior_tree: + behavior_tree.enabled = true + behavior_tree.actor = bot_character + if multiplayer.is_server(): bots.append(bot_id) players.append(bot_id) diff --git a/scenes/main.tscn b/scenes/main.tscn index fd2d466..a1871a1 100644 --- a/scenes/main.tscn +++ b/scenes/main.tscn @@ -17,8 +17,6 @@ [node name="Main" type="Node3D"] script = ExtResource("1_xcpe3") -players = null -turn_based_mode = false [node name="EnhancedGridMap" type="GridMap" parent="."] mesh_library = ExtResource("1_110wo") diff --git a/scenes/player.gd b/scenes/player.gd index 5ad1c30..a4c0cf1 100644 --- a/scenes/player.gd +++ b/scenes/player.gd @@ -74,7 +74,7 @@ func _unhandled_input(event): #if is_in_group("Bots"): #return - var main = get_node("/root/Main") + var main = get_node("/root/Main/") if not is_multiplayer_authority() or (main.turn_based_mode and (not is_my_turn or is_player_moving)): return diff --git a/scenes/player.tscn b/scenes/player.tscn index 2ff53e9..814c272 100644 --- a/scenes/player.tscn +++ b/scenes/player.tscn @@ -1,4 +1,4 @@ -[gd_scene load_steps=12 format=3 uid="uid://1dbdbg3q5778"] +[gd_scene load_steps=13 format=3 uid="uid://1dbdbg3q5778"] [ext_resource type="Script" path="res://scenes/player.gd" id="1_qecr4"] [ext_resource type="PackedScene" uid="uid://ejeamn0pyey4" path="res://assets/characters/Bob.glb" id="2_3e0d5"] @@ -7,6 +7,7 @@ [ext_resource type="PackedScene" uid="uid://d4cul3w3wem5w" path="res://assets/characters/Gatot.glb" id="4_3tlf6"] [ext_resource type="PackedScene" uid="uid://bmln7v6v5kvxg" path="res://assets/characters/Oldpop.glb" id="5_alfd1"] [ext_resource type="AnimationLibrary" uid="uid://c3pyopnwibckj" path="res://assets/characters/animations/animation-pack.res" id="6_5oq5w"] +[ext_resource type="Script" path="res://scripts/bot_behavior.gd" id="8_1o2fn"] [sub_resource type="StandardMaterial3D" id="StandardMaterial3D_xqgey"] albedo_color = Color(0.85, 0.085, 0.238, 1) @@ -85,3 +86,6 @@ uppercase = true autowrap_mode = 3 justification_flags = 171 width = 700.0 + +[node name="Node" type="Node" parent="."] +script = ExtResource("8_1o2fn") diff --git a/scripts/behaviors/actions/do_arrange.gd b/scripts/behaviors/actions/do_arrange.gd new file mode 100644 index 0000000..63b4f21 --- /dev/null +++ b/scripts/behaviors/actions/do_arrange.gd @@ -0,0 +1,26 @@ +extends ActionLeaf + +func tick(actor: Node, blackboard: Blackboard) -> int: + var source_slot = blackboard.get_value("source_slot") + var target_slot = blackboard.get_value("target_slot") + + if source_slot == -1 or target_slot == -1: + return FAILURE + + # Verify conditions are still valid + if actor.action_points < 2 or actor.playerboard[source_slot] == -1: + return FAILURE + + if actor.playerboard[target_slot] != -1: + return FAILURE + + # Do the arrangement + if actor.is_multiplayer_authority(): + var item = actor.playerboard[source_slot] + actor.playerboard[target_slot] = item + actor.playerboard[source_slot] = -1 + actor.rpc("sync_playerboard", actor.playerboard) + actor.has_performed_action = true + actor.action_points -= 2 + + return SUCCESS diff --git a/scripts/behaviors/actions/do_grab.gd b/scripts/behaviors/actions/do_grab.gd new file mode 100644 index 0000000..64f32a8 --- /dev/null +++ b/scripts/behaviors/actions/do_grab.gd @@ -0,0 +1,27 @@ +extends ActionLeaf + +func tick(actor: Node, blackboard: Blackboard) -> int: + var grab_position = blackboard.get_value("grab_position") + if not grab_position: + return FAILURE + + # Find empty slot in playerboard + var empty_slot = actor.playerboard.find(-1) + if empty_slot == -1: + return FAILURE + + # Get item at position + var cell = Vector3i(grab_position.x, 1, grab_position.y) + var item = actor.enhanced_gridmap.get_cell_item(cell) + if item == -1 or actor.action_points <= 0: + return FAILURE + + # Grab the item + if actor.is_multiplayer_authority(): + actor.playerboard[empty_slot] = item + actor.rpc("sync_grid_item", cell.x, cell.y, cell.z, -1) + actor.rpc("sync_playerboard", actor.playerboard) + actor.has_performed_action = true + actor.action_points -= 1 + + return SUCCESS diff --git a/scripts/behaviors/actions/do_move.gd b/scripts/behaviors/actions/do_move.gd new file mode 100644 index 0000000..a32126f --- /dev/null +++ b/scripts/behaviors/actions/do_move.gd @@ -0,0 +1,44 @@ +extends ActionLeaf + +func tick(actor: Node, blackboard: Blackboard) -> int: + var target_pos = blackboard.get_value("move_target") + if not target_pos: + return FAILURE + + if actor.action_points <= 0: + return FAILURE + + # Verify target is still valid + if not actor.is_within_movement_range(target_pos): + return FAILURE + + if actor.is_position_occupied(target_pos): + return FAILURE + + var cell_item = actor.enhanced_gridmap.get_cell_item(Vector3i(target_pos.x, 0, target_pos.y)) + if cell_item == -1 or cell_item in actor.enhanced_gridmap.non_walkable_items: + return FAILURE + + # Move to position + actor.rotate_towards_target(target_pos) + var path = actor.enhanced_gridmap.find_path(Vector2(actor.current_position), Vector2(target_pos)) + + if path.size() <= 1: + return FAILURE + + # Verify path is clear + var valid_path = true + for point in path.slice(1): + if actor.is_position_occupied(Vector2i(point.x, point.y)): + valid_path = false + break + + if valid_path: + if actor.is_multiplayer_authority(): + path.pop_front() + actor.rpc("start_movement_along_path", path) + actor.action_points -= 1 + actor.clear_highlights() + return SUCCESS + + return FAILURE diff --git a/scripts/behaviors/actions/do_put.gd b/scripts/behaviors/actions/do_put.gd new file mode 100644 index 0000000..549b067 --- /dev/null +++ b/scripts/behaviors/actions/do_put.gd @@ -0,0 +1,28 @@ +extends ActionLeaf + +func tick(actor: Node, blackboard: Blackboard) -> int: + var put_position = blackboard.get_value("put_position") + var put_slot = blackboard.get_value("put_slot") + + if not put_position or put_slot == -1: + return FAILURE + + # Check if we still have the item and AP + if actor.action_points <= 0 or actor.playerboard[put_slot] == -1: + return FAILURE + + # Check if target position is still empty + var cell = Vector3i(put_position.x, 1, put_position.y) + if actor.enhanced_gridmap.get_cell_item(cell) != -1: + return FAILURE + + # Put the item + var item = actor.playerboard[put_slot] + if actor.is_multiplayer_authority(): + actor.rpc("sync_grid_item", cell.x, cell.y, cell.z, item) + actor.playerboard[put_slot] = -1 + actor.rpc("sync_playerboard", actor.playerboard) + actor.has_performed_action = true + actor.action_points -= 1 + + return SUCCESS diff --git a/scripts/behaviors/actions/grab_action.gd b/scripts/behaviors/actions/grab_action.gd new file mode 100644 index 0000000..954d1fb --- /dev/null +++ b/scripts/behaviors/actions/grab_action.gd @@ -0,0 +1,11 @@ +class_name GrabAction extends ActionLeaf + +func tick(actor: Node, blackboard: Blackboard) -> int: + var grab_position = blackboard.get_value("grab_position") + if not grab_position: + return FAILURE + + if actor.grab_item(grab_position): + return SUCCESS + + return FAILURE diff --git a/scripts/behaviors/arrange_sequence.gd b/scripts/behaviors/arrange_sequence.gd new file mode 100644 index 0000000..9667a38 --- /dev/null +++ b/scripts/behaviors/arrange_sequence.gd @@ -0,0 +1,5 @@ +extends SequenceComposite + +func _ready(): + add_child(ArrangeCondition.new()) + add_child(ArrangeAction.new()) diff --git a/scripts/behaviors/conditions/arrange_action.gd b/scripts/behaviors/conditions/arrange_action.gd new file mode 100644 index 0000000..8e6818b --- /dev/null +++ b/scripts/behaviors/conditions/arrange_action.gd @@ -0,0 +1,22 @@ +class_name ArrangeAction extends ActionLeaf + +func tick(actor: Node, blackboard: Blackboard) -> int: + var source_slot = blackboard.get_value("source_slot", -1) + var target_slot = blackboard.get_value("target_slot", -1) + + if source_slot == -1 or target_slot == -1: + return FAILURE + + if actor.action_points < 2: + return FAILURE + + var selected_item = actor.playerboard[source_slot] + actor.playerboard[target_slot] = selected_item + actor.playerboard[source_slot] = -1 + + if actor.is_multiplayer_authority(): + actor.rpc("sync_playerboard", actor.playerboard) + actor.action_points -= 2 + actor.has_performed_action = true + + return SUCCESS diff --git a/scripts/behaviors/conditions/arrange_condition.gd b/scripts/behaviors/conditions/arrange_condition.gd new file mode 100644 index 0000000..b2e2cd9 --- /dev/null +++ b/scripts/behaviors/conditions/arrange_condition.gd @@ -0,0 +1,18 @@ +class_name ArrangeCondition extends ConditionLeaf + +func tick(actor: Node, blackboard: Blackboard) -> int: + # Check we have enough action points + if actor.action_points < 2: + return FAILURE + + # Check for items that can be arranged + for i in range(actor.playerboard.size()): + if actor.playerboard[i] != -1: + var neighbors = actor.get_adjacent_playerboard_slots(i) + for adj_slot in neighbors: + if actor.playerboard[adj_slot] == -1 and actor.playerboard[i] in actor.goals: + blackboard.set_value("source_slot", i) + blackboard.set_value("target_slot", adj_slot) + return SUCCESS + + return FAILURE diff --git a/scripts/behaviors/conditions/can_arrange.gd b/scripts/behaviors/conditions/can_arrange.gd new file mode 100644 index 0000000..abc3236 --- /dev/null +++ b/scripts/behaviors/conditions/can_arrange.gd @@ -0,0 +1,16 @@ +extends ConditionLeaf + +func tick(actor: Node, blackboard: Blackboard) -> int: + if actor.action_points < 2: + return FAILURE + + # Look for items that match goals + for i in range(actor.playerboard.size()): + if actor.playerboard[i] in actor.goals: + var neighbors = actor.get_adjacent_playerboard_slots(i) + for adj_slot in neighbors: + if actor.playerboard[adj_slot] == -1: + blackboard.set_value("source_slot", i) + blackboard.set_value("target_slot", adj_slot) + return SUCCESS + return FAILURE diff --git a/scripts/behaviors/conditions/can_grab.gd b/scripts/behaviors/conditions/can_grab.gd new file mode 100644 index 0000000..a6bcd92 --- /dev/null +++ b/scripts/behaviors/conditions/can_grab.gd @@ -0,0 +1,25 @@ +extends ConditionLeaf + +func tick(actor: Node, blackboard: Blackboard) -> int: + if actor.playerboard_is_full(): + return FAILURE + + # Check current position + var current_cell = Vector3i(actor.current_position.x, 1, actor.current_position.y) + var item = actor.enhanced_gridmap.get_cell_item(current_cell) + if item in actor.goals: + blackboard.set_value("grab_position", actor.current_position) + return SUCCESS + + # Check adjacent cells + var neighbors = actor.enhanced_gridmap.get_neighbors(actor.current_position, 0) + for neighbor in neighbors: + if not neighbor.is_walkable: + continue + var cell = Vector3i(neighbor.position.x, 1, neighbor.position.y) + item = actor.enhanced_gridmap.get_cell_item(cell) + if item in actor.goals: + blackboard.set_value("grab_position", neighbor.position) + return SUCCESS + + return FAILURE diff --git a/scripts/behaviors/conditions/can_put.gd b/scripts/behaviors/conditions/can_put.gd new file mode 100644 index 0000000..65cb9fb --- /dev/null +++ b/scripts/behaviors/conditions/can_put.gd @@ -0,0 +1,31 @@ +extends ConditionLeaf + +func tick(actor: Node, blackboard: Blackboard) -> int: + # Find an item in playerboard that matches goals + var put_slot = -1 + for i in range(actor.playerboard.size()): + if actor.playerboard[i] in actor.goals: + put_slot = i + break + + if put_slot == -1: + return FAILURE + + # Find empty adjacent cell + var current_cell = Vector3i(actor.current_position.x, 1, actor.current_position.y) + if actor.enhanced_gridmap.get_cell_item(current_cell) == -1: + blackboard.set_value("put_position", actor.current_position) + blackboard.set_value("put_slot", put_slot) + return SUCCESS + + var neighbors = actor.enhanced_gridmap.get_neighbors(actor.current_position, 0) + for neighbor in neighbors: + if not neighbor.is_walkable: + continue + var cell = Vector3i(neighbor.position.x, 1, neighbor.position.y) + if actor.enhanced_gridmap.get_cell_item(cell) == -1: + blackboard.set_value("put_position", neighbor.position) + blackboard.set_value("put_slot", put_slot) + return SUCCESS + + return FAILURE diff --git a/scripts/behaviors/conditions/grab_condition.gd b/scripts/behaviors/conditions/grab_condition.gd new file mode 100644 index 0000000..834da45 --- /dev/null +++ b/scripts/behaviors/conditions/grab_condition.gd @@ -0,0 +1,21 @@ +class_name GrabCondition extends ConditionLeaf + +func tick(actor: Node, blackboard: Blackboard) -> int: + if actor.action_points < 1 or actor.playerboard_is_full(): + return FAILURE + + # Check current position first + var current_cell = Vector3i(actor.current_position.x, 1, actor.current_position.y) + if actor.enhanced_gridmap.get_cell_item(current_cell) in actor.goals: + blackboard.set_value("grab_position", actor.current_position) + return SUCCESS + + # Check adjacent cells + var neighbors = actor.enhanced_gridmap.get_neighbors(actor.current_position, 1) + for neighbor in neighbors: + var cell = Vector3i(neighbor.position.x, 1, neighbor.position.y) + if actor.enhanced_gridmap.get_cell_item(cell) in actor.goals: + blackboard.set_value("grab_position", neighbor.position) + return SUCCESS + + return FAILURE diff --git a/scripts/behaviors/conditions/has_ap.gd b/scripts/behaviors/conditions/has_ap.gd new file mode 100644 index 0000000..dc4a30a --- /dev/null +++ b/scripts/behaviors/conditions/has_ap.gd @@ -0,0 +1,6 @@ +extends ConditionLeaf + +func tick(actor: Node, blackboard: Blackboard) -> int: + if actor.action_points >= 1: + return SUCCESS + return FAILURE diff --git a/scripts/behaviors/conditions/should_move.gd b/scripts/behaviors/conditions/should_move.gd new file mode 100644 index 0000000..86b69b7 --- /dev/null +++ b/scripts/behaviors/conditions/should_move.gd @@ -0,0 +1,85 @@ +extends ConditionLeaf + +func tick(actor: Node, blackboard: Blackboard) -> int: + if actor.action_points <= 0: + return FAILURE + + var target_pos = find_best_move_position(actor) + if target_pos == Vector2i(-1, -1): + return FAILURE + + blackboard.set_value("move_target", target_pos) + return SUCCESS + +func find_best_move_position(actor: Node) -> Vector2i: + # First priority: Move towards items that match our goals + var closest_goal_item = find_closest_goal_item(actor) + if closest_goal_item != Vector2i(-1, -1): + return get_position_towards(actor, closest_goal_item) + + # Second priority: Move towards empty cells if we have items + if actor.has_items_in_playerboard(): + var empty_pos = find_closest_empty_cell(actor) + if empty_pos != Vector2i(-1, -1): + return get_position_towards(actor, empty_pos) + + # Last resort: Random valid move + return actor.find_random_valid_position_in_range() + +func find_closest_goal_item(actor: Node) -> Vector2i: + var min_distance = 999999 + var closest_pos = Vector2i(-1, -1) + + for x in range(actor.enhanced_gridmap.columns): + for z in range(actor.enhanced_gridmap.rows): + var cell = Vector3i(x, 1, z) + var item = actor.enhanced_gridmap.get_cell_item(cell) + if item in actor.goals: + var dist = actor.current_position.distance_squared_to(Vector2i(x, z)) + if dist < min_distance: + min_distance = dist + closest_pos = Vector2i(x, z) + + return closest_pos + +func find_closest_empty_cell(actor: Node) -> Vector2i: + var min_distance = 999999 + var closest_pos = Vector2i(-1, -1) + + for x in range(actor.enhanced_gridmap.columns): + for z in range(actor.enhanced_gridmap.rows): + var cell = Vector3i(x, 1, z) + if actor.enhanced_gridmap.get_cell_item(cell) == -1: + var dist = actor.current_position.distance_squared_to(Vector2i(x, z)) + if dist < min_distance: + min_distance = dist + closest_pos = Vector2i(x, z) + + return closest_pos + +func get_position_towards(actor: Node, target: Vector2i) -> Vector2i: + # Find a valid position within movement range that's closest to target + var best_pos = Vector2i(-1, -1) + var min_distance = 999999 + + for x in range(actor.current_position.x - actor.movement_range, + actor.current_position.x + actor.movement_range + 1): + for z in range(actor.current_position.y - actor.movement_range, + actor.current_position.y + actor.movement_range + 1): + var pos = Vector2i(x, z) + if not actor.is_within_movement_range(pos): + continue + + if actor.is_position_occupied(pos): + continue + + var cell_item = actor.enhanced_gridmap.get_cell_item(Vector3i(x, 0, z)) + if cell_item == -1 or cell_item in actor.enhanced_gridmap.non_walkable_items: + continue + + var dist = pos.distance_squared_to(target) + if dist < min_distance: + min_distance = dist + best_pos = pos + + return best_pos diff --git a/scripts/behaviors/sequences/grab_sequence.gd b/scripts/behaviors/sequences/grab_sequence.gd new file mode 100644 index 0000000..f2a1ef6 --- /dev/null +++ b/scripts/behaviors/sequences/grab_sequence.gd @@ -0,0 +1,5 @@ +class_name GrabSequence extends SequenceComposite + +func _ready(): + add_child(GrabCondition.new()) + add_child(GrabAction.new()) diff --git a/scripts/behaviors/sequences/move_sequence.gd b/scripts/behaviors/sequences/move_sequence.gd new file mode 100644 index 0000000..2a9490f --- /dev/null +++ b/scripts/behaviors/sequences/move_sequence.gd @@ -0,0 +1,5 @@ +class_name MoveSequence extends SequenceComposite + +func _ready(): + add_child(MoveCondition.new()) + add_child(MoveAction.new()) diff --git a/scripts/behaviors/sequences/put_sequence.gd b/scripts/behaviors/sequences/put_sequence.gd new file mode 100644 index 0000000..465e41e --- /dev/null +++ b/scripts/behaviors/sequences/put_sequence.gd @@ -0,0 +1,5 @@ +class_name PutSequence extends SequenceComposite + +func _ready(): + add_child(PutCondition.new()) + add_child(PutAction.new()) diff --git a/scripts/bot_behavior.gd b/scripts/bot_behavior.gd new file mode 100644 index 0000000..6c837a2 --- /dev/null +++ b/scripts/bot_behavior.gd @@ -0,0 +1,120 @@ +@tool +extends BeehaveTree + +func _ready(): + if Engine.is_editor_hint(): + return + + # Only setup for bots + if not get_parent().is_in_group("Bots"): + return + + # Create root selector + var selector = SelectorComposite.new() + add_child(selector) + + # Add sequences + selector.add_child(create_arrange_sequence()) + selector.add_child(create_grab_sequence()) + selector.add_child(create_put_sequence()) + selector.add_child(create_move_sequence()) + +func create_arrange_sequence() -> SequenceComposite: + var sequence = SequenceComposite.new() + sequence.name = "ArrangeSequence" + + # Has enough action points? + var check_ap = ConditionLeaf.new() + check_ap.name = "HasEnoughAP" + check_ap.set_script(preload("res://scripts/behaviors/conditions/has_ap.gd")) + + # Can arrange items? + var can_arrange = ConditionLeaf.new() + can_arrange.name = "CanArrange" + can_arrange.set_script(preload("res://scripts/behaviors/conditions/can_arrange.gd")) + + # Do arrange action + var do_arrange = ActionLeaf.new() + do_arrange.name = "DoArrange" + do_arrange.set_script(preload("res://scripts/behaviors/actions/do_arrange.gd")) + + sequence.add_child(check_ap) + sequence.add_child(can_arrange) + sequence.add_child(do_arrange) + + return sequence + +func create_grab_sequence() -> SequenceComposite: + var sequence = SequenceComposite.new() + sequence.name = "GrabSequence" + + # Has enough action points? + var check_ap = ConditionLeaf.new() + check_ap.name = "HasAP" + check_ap.set_script(preload("res://scripts/behaviors/conditions/has_ap.gd")) + + # Can grab item? + var can_grab = ConditionLeaf.new() + can_grab.name = "CanGrab" + can_grab.set_script(preload("res://scripts/behaviors/conditions/can_grab.gd")) + + # Do grab action + var do_grab = ActionLeaf.new() + do_grab.name = "DoGrab" + do_grab.set_script(preload("res://scripts/behaviors/actions/do_grab.gd")) + + sequence.add_child(check_ap) + sequence.add_child(can_grab) + sequence.add_child(do_grab) + + return sequence + +func create_put_sequence() -> SequenceComposite: + var sequence = SequenceComposite.new() + sequence.name = "PutSequence" + + # Has enough action points? + var check_ap = ConditionLeaf.new() + check_ap.name = "HasAP" + check_ap.set_script(preload("res://scripts/behaviors/conditions/has_ap.gd")) + + # Can put item? + var can_put = ConditionLeaf.new() + can_put.name = "CanPut" + can_put.set_script(preload("res://scripts/behaviors/conditions/can_put.gd")) + + # Do put action + var do_put = ActionLeaf.new() + do_put.name = "DoPut" + do_put.set_script(preload("res://scripts/behaviors/actions/do_put.gd")) + + sequence.add_child(check_ap) + sequence.add_child(can_put) + sequence.add_child(do_put) + + return sequence + +func create_move_sequence() -> SequenceComposite: + var sequence = SequenceComposite.new() + sequence.name = "MoveSequence" + + # Has enough action points? + var check_ap = ConditionLeaf.new() + check_ap.name = "HasAP" + check_ap.set_script(preload("res://scripts/behaviors/conditions/has_ap.gd")) + + # Should move? + var should_move = ConditionLeaf.new() + should_move.name = "ShouldMove" + should_move.set_script(preload("res://scripts/behaviors/conditions/should_move.gd")) + + # Do move action + var do_move = ActionLeaf.new() + do_move.name = "DoMove" + do_move.set_script(preload("res://scripts/behaviors/actions/do_move.gd")) + + sequence.add_child(check_ap) + sequence.add_child(should_move) + sequence.add_child(do_move) + + return sequence