update bot experimental
This commit is contained in:
+29
-12
@@ -232,11 +232,19 @@ func _on_join_pressed():
|
|||||||
|
|
||||||
func _on_peer_connected(new_peer_id):
|
func _on_peer_connected(new_peer_id):
|
||||||
if multiplayer.is_server():
|
if multiplayer.is_server():
|
||||||
await get_tree().create_timer(1).timeout
|
# Increase delay to ensure scene is ready
|
||||||
rpc("add_newly_connected_player_character", new_peer_id)
|
await get_tree().create_timer(1.5).timeout
|
||||||
rpc_id(new_peer_id, "add_previously_connected_player_characters", connected_peer_ids)
|
|
||||||
|
# Sync full state first
|
||||||
rpc_id(new_peer_id, "sync_game_state", players, bots, game_started, turn_based_mode)
|
rpc_id(new_peer_id, "sync_game_state", players, bots, game_started, turn_based_mode)
|
||||||
|
|
||||||
|
# Then add players in correct order
|
||||||
|
for peer_id in connected_peer_ids:
|
||||||
|
rpc_id(new_peer_id, "add_player_character", peer_id)
|
||||||
|
|
||||||
|
# Finally add the new player
|
||||||
add_player_character(new_peer_id)
|
add_player_character(new_peer_id)
|
||||||
|
rpc("add_newly_connected_player_character", new_peer_id)
|
||||||
replace_bot_with_player(new_peer_id)
|
replace_bot_with_player(new_peer_id)
|
||||||
|
|
||||||
func _on_peer_disconnected(peer_id):
|
func _on_peer_disconnected(peer_id):
|
||||||
@@ -270,23 +278,32 @@ func add_bot(bot_id):
|
|||||||
|
|
||||||
@rpc("call_local")
|
@rpc("call_local")
|
||||||
func create_bot(bot_id):
|
func create_bot(bot_id):
|
||||||
|
# Ensure we're not duplicating bots
|
||||||
|
if has_node(str(bot_id)):
|
||||||
|
push_error("Bot already exists: " + str(bot_id))
|
||||||
|
return
|
||||||
|
|
||||||
var bot_character = player_scene.instantiate()
|
var bot_character = player_scene.instantiate()
|
||||||
bot_character.set_multiplayer_authority(1)
|
if not bot_character:
|
||||||
|
push_error("Failed to instantiate bot scene")
|
||||||
|
return
|
||||||
|
|
||||||
|
bot_character.set_multiplayer_authority(1) # Server controls bots
|
||||||
bot_character.name = str(bot_id)
|
bot_character.name = str(bot_id)
|
||||||
bot_character.is_bot = true # Set bot flag
|
|
||||||
add_child(bot_character)
|
# Add to scene tree
|
||||||
|
call_deferred("add_child", bot_character)
|
||||||
|
|
||||||
|
# Add to groups after adding to scene tree
|
||||||
bot_character.add_to_group("Players", true)
|
bot_character.add_to_group("Players", true)
|
||||||
bot_character.add_to_group("Bots", true)
|
bot_character.add_to_group("Bots", true)
|
||||||
|
|
||||||
# Get behavior tree reference
|
|
||||||
var behavior_tree = bot_character.get_node_or_null("BehaviorTree")
|
|
||||||
if behavior_tree:
|
|
||||||
behavior_tree.enabled = true
|
|
||||||
behavior_tree.actor = bot_character
|
|
||||||
|
|
||||||
if multiplayer.is_server():
|
if multiplayer.is_server():
|
||||||
bots.append(bot_id)
|
bots.append(bot_id)
|
||||||
players.append(bot_id)
|
players.append(bot_id)
|
||||||
|
# Sync bot status after a short delay to ensure node is ready
|
||||||
|
await get_tree().create_timer(0.1).timeout
|
||||||
|
bot_character.rpc("sync_bot_status", true)
|
||||||
|
|
||||||
func replace_bot_with_player(player_id):
|
func replace_bot_with_player(player_id):
|
||||||
if multiplayer.is_server() and bots.size() > 0:
|
if multiplayer.is_server() and bots.size() > 0:
|
||||||
|
|||||||
+87
-43
@@ -36,7 +36,6 @@ var rotation_speed: float = 10.0
|
|||||||
rpc("display_message", "It's your turn!")
|
rpc("display_message", "It's your turn!")
|
||||||
|
|
||||||
@export var has_moved_this_turn = false
|
@export var has_moved_this_turn = false
|
||||||
@onready var main_scene = get_tree().current_scene
|
|
||||||
|
|
||||||
var highlighted_cells = []
|
var highlighted_cells = []
|
||||||
|
|
||||||
@@ -44,40 +43,53 @@ func _ready():
|
|||||||
name = str(get_multiplayer_authority())
|
name = str(get_multiplayer_authority())
|
||||||
$Name.text = str(name)
|
$Name.text = str(name)
|
||||||
|
|
||||||
enhanced_gridmap = get_node(enhanced_gridmap_path)
|
# More robust way to get the main scene
|
||||||
|
var main_scene = get_tree().get_root().get_node_or_null("Main")
|
||||||
if main_scene:
|
if not main_scene:
|
||||||
enhanced_gridmap = main_scene.get_node("EnhancedGridMap")
|
|
||||||
else:
|
|
||||||
push_error("Main scene not found")
|
push_error("Main scene not found")
|
||||||
|
|
||||||
if not enhanced_gridmap:
|
|
||||||
push_error("EnhancedGridMap node not found")
|
|
||||||
return
|
return
|
||||||
|
|
||||||
enhanced_gridmap.initialize_astar()
|
# Ensure proper initialization order
|
||||||
enhanced_gridmap.set_diagonal_movement(use_diagonal_movement)
|
enhanced_gridmap = get_node(enhanced_gridmap_path)
|
||||||
|
if main_scene:
|
||||||
|
enhanced_gridmap = main_scene.get_node("EnhancedGridMap")
|
||||||
|
|
||||||
current_position = find_valid_starting_position()
|
# Initialize behavior tree for bots
|
||||||
update_player_position(current_position)
|
var behavior_tree = $BehaviorTree
|
||||||
|
|
||||||
# Set bot flag if in Bots group
|
|
||||||
if is_in_group("Bots"):
|
|
||||||
is_bot = true
|
|
||||||
|
|
||||||
# Only process input if not a bot and is authority
|
if is_in_group("Bots") and behavior_tree:
|
||||||
set_process_unhandled_input(not is_bot and is_multiplayer_authority())
|
behavior_tree.enabled = true
|
||||||
|
behavior_tree.actor = self
|
||||||
|
|
||||||
|
rpc("sync_bot_status", true)
|
||||||
|
|
||||||
|
# Rest of initialization
|
||||||
|
if enhanced_gridmap:
|
||||||
|
enhanced_gridmap.initialize_astar()
|
||||||
|
enhanced_gridmap.set_diagonal_movement(use_diagonal_movement)
|
||||||
|
|
||||||
|
current_position = find_valid_starting_position()
|
||||||
|
update_player_position(current_position)
|
||||||
|
|
||||||
|
set_process_unhandled_input(not is_in_group("Bots") and is_multiplayer_authority())
|
||||||
|
|
||||||
append_random_goals()
|
append_random_goals()
|
||||||
playerboard.resize(25)
|
playerboard.resize(25)
|
||||||
playerboard.fill(-1)
|
playerboard.fill(-1)
|
||||||
|
|
||||||
# Enable behavior tree if bot
|
@rpc("any_peer", "call_local")
|
||||||
|
func sync_bot_status(is_bot_status: bool):
|
||||||
|
is_bot = is_bot_status
|
||||||
if is_bot:
|
if is_bot:
|
||||||
var behavior_tree = $BehaviorTree
|
add_to_group("Bots", true) # Persistent group addition
|
||||||
|
var behavior_tree = get_node_or_null("BehaviorTree")
|
||||||
if behavior_tree:
|
if behavior_tree:
|
||||||
behavior_tree.enabled = true
|
behavior_tree.enabled = true
|
||||||
behavior_tree.actor = self
|
behavior_tree.actor = self
|
||||||
|
if not is_multiplayer_authority():
|
||||||
|
behavior_tree.set_physics_process(false)
|
||||||
|
behavior_tree.set_process(false)
|
||||||
|
|
||||||
func _physics_process(_delta):
|
func _physics_process(_delta):
|
||||||
if is_multiplayer_authority():
|
if is_multiplayer_authority():
|
||||||
@@ -87,7 +99,11 @@ func _unhandled_input(event):
|
|||||||
#if is_in_group("Bots"):
|
#if is_in_group("Bots"):
|
||||||
#return
|
#return
|
||||||
|
|
||||||
var main = get_node("/root/Main/")
|
# Use get_node_or_null for safer node access
|
||||||
|
var main = get_tree().get_root().get_node_or_null("Main")
|
||||||
|
if not main:
|
||||||
|
return
|
||||||
|
|
||||||
if not is_multiplayer_authority() or (main.turn_based_mode and (not is_my_turn or is_player_moving)):
|
if not is_multiplayer_authority() or (main.turn_based_mode and (not is_my_turn or is_player_moving)):
|
||||||
return
|
return
|
||||||
|
|
||||||
@@ -102,7 +118,8 @@ func _unhandled_input(event):
|
|||||||
|
|
||||||
func _on_slot_gui_input(event, slot_index, slot_ui) -> int:
|
func _on_slot_gui_input(event, slot_index, slot_ui) -> int:
|
||||||
if event is InputEventMouseButton and event.pressed and event.button_index == MOUSE_BUTTON_LEFT:
|
if event is InputEventMouseButton and event.pressed and event.button_index == MOUSE_BUTTON_LEFT:
|
||||||
var main = get_node("/root/Main")
|
var main = get_tree().get_root().get_node_or_null("Main")
|
||||||
|
|
||||||
if main.current_action_state == main.ActionState.ARRANGING:
|
if main.current_action_state == main.ActionState.ARRANGING:
|
||||||
if selected_playerboard_slot == -1:
|
if selected_playerboard_slot == -1:
|
||||||
select_playerboard_slot(slot_index)
|
select_playerboard_slot(slot_index)
|
||||||
@@ -120,8 +137,9 @@ func _on_slot_gui_input(event, slot_index, slot_ui) -> int:
|
|||||||
return -1
|
return -1
|
||||||
|
|
||||||
func handle_grid_click(grid_position: Vector2i):
|
func handle_grid_click(grid_position: Vector2i):
|
||||||
var main = get_node("/root/Main")
|
var main = get_tree().get_root().get_node_or_null("Main")
|
||||||
if not main:
|
if not main:
|
||||||
|
push_error("Main node not found")
|
||||||
return
|
return
|
||||||
|
|
||||||
match main.current_action_state:
|
match main.current_action_state:
|
||||||
@@ -210,7 +228,7 @@ func move_player_to_clicked_position(grid_position: Vector2i):
|
|||||||
if not is_multiplayer_authority() or is_player_moving or action_points <= 0:
|
if not is_multiplayer_authority() or is_player_moving or action_points <= 0:
|
||||||
return
|
return
|
||||||
|
|
||||||
var main = get_node("/root/Main")
|
var main = get_tree().get_root().get_node_or_null("Main")
|
||||||
if not main or main.current_action_state != main.ActionState.MOVING or not grid_position in highlighted_cells:
|
if not main or main.current_action_state != main.ActionState.MOVING or not grid_position in highlighted_cells:
|
||||||
return
|
return
|
||||||
|
|
||||||
@@ -257,7 +275,7 @@ func start_movement_along_path(path: Array):
|
|||||||
enhanced_gridmap.clear_path_visualization()
|
enhanced_gridmap.clear_path_visualization()
|
||||||
has_moved_this_turn = path.size() <= movement_range
|
has_moved_this_turn = path.size() <= movement_range
|
||||||
|
|
||||||
var main = get_node("/root/Main")
|
var main = get_tree().get_root().get_node_or_null("Main")
|
||||||
main.set_action_state(main.ActionState.NONE)
|
main.set_action_state(main.ActionState.NONE)
|
||||||
|
|
||||||
if main.turn_based_mode:
|
if main.turn_based_mode:
|
||||||
@@ -367,7 +385,7 @@ func grab_item(grid_position: Vector2i = current_position) -> bool:
|
|||||||
_after_action_completed()
|
_after_action_completed()
|
||||||
return true
|
return true
|
||||||
else:
|
else:
|
||||||
var main = get_node("/root/Main")
|
var main = get_tree().get_root().get_node_or_null("Main")
|
||||||
if main:
|
if main:
|
||||||
selected_gridmap_position = grid_position
|
selected_gridmap_position = grid_position
|
||||||
clear_highlights()
|
clear_highlights()
|
||||||
@@ -414,14 +432,14 @@ func put_item(grid_position: Vector2i = current_position) -> bool:
|
|||||||
clear_playerboard_highlights()
|
clear_playerboard_highlights()
|
||||||
selected_playerboard_slot = -1
|
selected_playerboard_slot = -1
|
||||||
|
|
||||||
var main = get_node("/root/Main")
|
var main = get_tree().get_root().get_node_or_null("Main")
|
||||||
if main:
|
if main:
|
||||||
main.set_action_state(main.ActionState.NONE)
|
main.set_action_state(main.ActionState.NONE)
|
||||||
_after_action_completed()
|
_after_action_completed()
|
||||||
return true
|
return true
|
||||||
|
|
||||||
func handle_put_action():
|
func handle_put_action():
|
||||||
var main = get_node("/root/Main")
|
var main = get_tree().get_root().get_node_or_null("Main")
|
||||||
if not main or action_points < 1:
|
if not main or action_points < 1:
|
||||||
return
|
return
|
||||||
|
|
||||||
@@ -437,7 +455,7 @@ func handle_put_action():
|
|||||||
highlighted_cells.append(i)
|
highlighted_cells.append(i)
|
||||||
|
|
||||||
func handle_playerboard_slot_selected(slot_index: int):
|
func handle_playerboard_slot_selected(slot_index: int):
|
||||||
var main = get_node("/root/Main")
|
var main = get_tree().get_root().get_node_or_null("Main")
|
||||||
if not main:
|
if not main:
|
||||||
return
|
return
|
||||||
|
|
||||||
@@ -467,7 +485,7 @@ func handle_playerboard_slot_selected(slot_index: int):
|
|||||||
|
|
||||||
# We also need to add handle_put_slot_selected:
|
# We also need to add handle_put_slot_selected:
|
||||||
func handle_put_slot_selected(slot_index: int):
|
func handle_put_slot_selected(slot_index: int):
|
||||||
var main = get_node("/root/Main")
|
var main = get_tree().get_root().get_node_or_null("Main")
|
||||||
if not main or main.current_action_state != main.ActionState.PUTTING:
|
if not main or main.current_action_state != main.ActionState.PUTTING:
|
||||||
return
|
return
|
||||||
|
|
||||||
@@ -483,7 +501,7 @@ func handle_put_slot_selected(slot_index: int):
|
|||||||
#var selected_item = playerboard[slot_index]
|
#var selected_item = playerboard[slot_index]
|
||||||
#var adjacent_slots = get_adjacent_playerboard_slots(slot_index)
|
#var adjacent_slots = get_adjacent_playerboard_slots(slot_index)
|
||||||
#
|
#
|
||||||
#var main = get_node("/root/Main")
|
#var main = get_tree().get_root().get_node_or_null("Main")
|
||||||
#if not main or not main.playerboard_ui:
|
#if not main or not main.playerboard_ui:
|
||||||
#return
|
#return
|
||||||
#
|
#
|
||||||
@@ -528,7 +546,7 @@ func arrange_playerboard_item(slot_index: int):
|
|||||||
var selected_item = playerboard[slot_index]
|
var selected_item = playerboard[slot_index]
|
||||||
var adjacent_slots = get_adjacent_playerboard_slots(slot_index)
|
var adjacent_slots = get_adjacent_playerboard_slots(slot_index)
|
||||||
|
|
||||||
var main = get_node("/root/Main")
|
var main = get_tree().get_root().get_node_or_null("Main")
|
||||||
if not main or not main.playerboard_ui:
|
if not main or not main.playerboard_ui:
|
||||||
return
|
return
|
||||||
|
|
||||||
@@ -558,7 +576,7 @@ func _on_slot_clicked(event: InputEvent, slot_index: int):
|
|||||||
if not event is InputEventMouseButton or not event.pressed or event.button_index != MOUSE_BUTTON_LEFT:
|
if not event is InputEventMouseButton or not event.pressed or event.button_index != MOUSE_BUTTON_LEFT:
|
||||||
return
|
return
|
||||||
|
|
||||||
var main = get_node("/root/Main")
|
var main = get_tree().get_root().get_node_or_null("Main")
|
||||||
if not main or main.current_action_state != main.ActionState.ARRANGING:
|
if not main or main.current_action_state != main.ActionState.ARRANGING:
|
||||||
return
|
return
|
||||||
|
|
||||||
@@ -760,7 +778,7 @@ func highlight_occupied_playerboard_slots():
|
|||||||
#if is_in_group("Bots"):
|
#if is_in_group("Bots"):
|
||||||
#return
|
#return
|
||||||
|
|
||||||
var main = get_node("/root/Main")
|
var main = get_tree().get_root().get_node_or_null("Main")
|
||||||
if not main or not main.playerboard_ui:
|
if not main or not main.playerboard_ui:
|
||||||
return
|
return
|
||||||
|
|
||||||
@@ -791,7 +809,7 @@ func clear_highlights():
|
|||||||
|
|
||||||
highlighted_cells.clear()
|
highlighted_cells.clear()
|
||||||
|
|
||||||
var main = get_node("/root/Main")
|
var main = get_tree().get_root().get_node_or_null("Main")
|
||||||
if main and main.playerboard_ui:
|
if main and main.playerboard_ui:
|
||||||
for i in range(main.playerboard_ui.get_child_count()):
|
for i in range(main.playerboard_ui.get_child_count()):
|
||||||
var slot = main.playerboard_ui.get_child(i)
|
var slot = main.playerboard_ui.get_child(i)
|
||||||
@@ -799,7 +817,7 @@ func clear_highlights():
|
|||||||
child.hide()
|
child.hide()
|
||||||
|
|
||||||
func clear_playerboard_highlights():
|
func clear_playerboard_highlights():
|
||||||
var main = get_node("/root/Main")
|
var main = get_tree().get_root().get_node_or_null("Main")
|
||||||
if main and main.playerboard_ui:
|
if main and main.playerboard_ui:
|
||||||
for i in range(main.playerboard_ui.get_child_count()):
|
for i in range(main.playerboard_ui.get_child_count()):
|
||||||
var slot = main.playerboard_ui.get_child(i)
|
var slot = main.playerboard_ui.get_child(i)
|
||||||
@@ -853,7 +871,7 @@ func can_move_to_target_playerboard_slot() -> bool:
|
|||||||
return adjacent_slots.has(targeted_playerboard_slot)
|
return adjacent_slots.has(targeted_playerboard_slot)
|
||||||
|
|
||||||
func _update_playerboard_slot_visual(slot_index: int):
|
func _update_playerboard_slot_visual(slot_index: int):
|
||||||
var main = get_node("/root/Main")
|
var main = get_tree().get_root().get_node_or_null("Main")
|
||||||
if not main or not main.playerboard_ui:
|
if not main or not main.playerboard_ui:
|
||||||
return
|
return
|
||||||
|
|
||||||
@@ -867,7 +885,7 @@ func _update_playerboard_slot_visual(slot_index: int):
|
|||||||
slot.get_child(2).visible = selected_playerboard_slot != -1 and get_adjacent_playerboard_slots(selected_playerboard_slot).has(slot_index)
|
slot.get_child(2).visible = selected_playerboard_slot != -1 and get_adjacent_playerboard_slots(selected_playerboard_slot).has(slot_index)
|
||||||
|
|
||||||
func _highlight_adjacent_playerboard_slots():
|
func _highlight_adjacent_playerboard_slots():
|
||||||
var main = get_node("/root/Main")
|
var main = get_tree().get_root().get_node_or_null("Main")
|
||||||
if not main or not main.playerboard_ui:
|
if not main or not main.playerboard_ui:
|
||||||
return
|
return
|
||||||
|
|
||||||
@@ -902,14 +920,34 @@ func sync_playerboard(new_playerboard: Array):
|
|||||||
playerboard = new_playerboard
|
playerboard = new_playerboard
|
||||||
_after_action_completed()
|
_after_action_completed()
|
||||||
|
|
||||||
|
@rpc("any_peer", "call_local")
|
||||||
|
func sync_behavior_tree(enabled: bool):
|
||||||
|
var behavior_tree = $BehaviorTree
|
||||||
|
if behavior_tree:
|
||||||
|
behavior_tree.enabled = enabled
|
||||||
|
behavior_tree.actor = self
|
||||||
|
#behavior_tree.blackboard = blackboard
|
||||||
|
|
||||||
|
## Ensure blackboard has required values
|
||||||
|
#blackboard.set_value("action_points", action_points)
|
||||||
|
#blackboard.set_value("goals", goals)
|
||||||
|
#blackboard.set_value("playerboard", playerboard)
|
||||||
|
|
||||||
func _after_action_completed():
|
func _after_action_completed():
|
||||||
if multiplayer.get_unique_id() == get_multiplayer_authority():
|
if multiplayer.get_unique_id() == get_multiplayer_authority():
|
||||||
var main = get_node("/root/Main")
|
var main = get_tree().get_root().get_node_or_null("Main")
|
||||||
if main:
|
if main:
|
||||||
if not main.turn_based_mode and action_points <= 0:
|
# Add this condition for bots
|
||||||
action_points = 2
|
if not main.turn_based_mode and (action_points <= 0 or is_bot):
|
||||||
|
action_points = 20 # For bots in non-turn-based mode, this will keep refreshing
|
||||||
has_performed_action = false
|
has_performed_action = false
|
||||||
has_moved_this_turn = false
|
has_moved_this_turn = false
|
||||||
|
|
||||||
|
# Update blackboard after action points change
|
||||||
|
#var blackboard = $Blackboard
|
||||||
|
#if blackboard:
|
||||||
|
#blackboard.set_value("action_points", action_points)
|
||||||
|
|
||||||
main.update_button_states()
|
main.update_button_states()
|
||||||
main.update_playerboard_ui()
|
main.update_playerboard_ui()
|
||||||
|
|
||||||
@@ -917,11 +955,17 @@ func consume_action_points(points: int):
|
|||||||
if not is_instance_valid(self) or not is_multiplayer_authority():
|
if not is_instance_valid(self) or not is_multiplayer_authority():
|
||||||
return
|
return
|
||||||
|
|
||||||
action_points -= points
|
var main = get_tree().get_root().get_node_or_null("Main")
|
||||||
var main = get_node("/root/Main")
|
|
||||||
if not main:
|
if not main:
|
||||||
return
|
return
|
||||||
|
|
||||||
|
# Don't consume points for bots in non-turn-based mode
|
||||||
|
if is_bot and not main.turn_based_mode:
|
||||||
|
_after_action_completed()
|
||||||
|
return
|
||||||
|
|
||||||
|
action_points -= points
|
||||||
|
|
||||||
if action_points <= 0:
|
if action_points <= 0:
|
||||||
if main.turn_based_mode:
|
if main.turn_based_mode:
|
||||||
main.request_end_turn()
|
main.request_end_turn()
|
||||||
|
|||||||
+69
-3
@@ -1,4 +1,4 @@
|
|||||||
[gd_scene load_steps=13 format=3 uid="uid://1dbdbg3q5778"]
|
[gd_scene load_steps=25 format=3 uid="uid://1dbdbg3q5778"]
|
||||||
|
|
||||||
[ext_resource type="Script" path="res://scenes/player.gd" id="1_qecr4"]
|
[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"]
|
[ext_resource type="PackedScene" uid="uid://ejeamn0pyey4" path="res://assets/characters/Bob.glb" id="2_3e0d5"]
|
||||||
@@ -8,6 +8,18 @@
|
|||||||
[ext_resource type="PackedScene" uid="uid://bmln7v6v5kvxg" path="res://assets/characters/Oldpop.glb" id="5_alfd1"]
|
[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="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"]
|
[ext_resource type="Script" path="res://scripts/bot_behavior.gd" id="8_1o2fn"]
|
||||||
|
[ext_resource type="Script" path="res://addons/beehave/nodes/composites/selector.gd" id="9_jspru"]
|
||||||
|
[ext_resource type="Script" path="res://addons/beehave/nodes/composites/sequence.gd" id="10_hv4ee"]
|
||||||
|
[ext_resource type="Script" path="res://scripts/behaviors/conditions/has_ap.gd" id="11_7fhpq"]
|
||||||
|
[ext_resource type="Script" path="res://scripts/behaviors/actions/do_arrange.gd" id="12_1ppih"]
|
||||||
|
[ext_resource type="Script" path="res://scripts/behaviors/conditions/can_arrange.gd" id="12_hr248"]
|
||||||
|
[ext_resource type="Script" path="res://scripts/behaviors/conditions/can_grab.gd" id="13_41jsv"]
|
||||||
|
[ext_resource type="Script" path="res://scripts/behaviors/actions/do_grab.gd" id="15_5h472"]
|
||||||
|
[ext_resource type="Script" path="res://scripts/behaviors/conditions/can_put.gd" id="16_ac2sy"]
|
||||||
|
[ext_resource type="Script" path="res://scripts/behaviors/actions/do_put.gd" id="17_e03nk"]
|
||||||
|
[ext_resource type="Script" path="res://scripts/behaviors/conditions/should_move.gd" id="18_2ghcp"]
|
||||||
|
[ext_resource type="Script" path="res://scripts/behaviors/actions/do_move.gd" id="19_dl4fn"]
|
||||||
|
[ext_resource type="Script" path="res://scripts/bot_blackboard.gd" id="20_24ja6"]
|
||||||
|
|
||||||
[sub_resource type="StandardMaterial3D" id="StandardMaterial3D_xqgey"]
|
[sub_resource type="StandardMaterial3D" id="StandardMaterial3D_xqgey"]
|
||||||
albedo_color = Color(0.85, 0.085, 0.238, 1)
|
albedo_color = Color(0.85, 0.085, 0.238, 1)
|
||||||
@@ -87,7 +99,61 @@ autowrap_mode = 3
|
|||||||
justification_flags = 171
|
justification_flags = 171
|
||||||
width = 700.0
|
width = 700.0
|
||||||
|
|
||||||
[node name="BehaviorTree" type="Node" parent="."]
|
[node name="Blackboard" type="Node" parent="."]
|
||||||
|
script = ExtResource("20_24ja6")
|
||||||
|
|
||||||
|
[node name="BehaviorTree" type="Node" parent="." node_paths=PackedStringArray("blackboard")]
|
||||||
script = ExtResource("8_1o2fn")
|
script = ExtResource("8_1o2fn")
|
||||||
tick_rate = 60
|
tick_rate = 60
|
||||||
actor_node_path = NodePath("\"..\"")
|
blackboard = NodePath("../Blackboard")
|
||||||
|
|
||||||
|
[node name="Selector" type="Node" parent="BehaviorTree"]
|
||||||
|
script = ExtResource("9_jspru")
|
||||||
|
|
||||||
|
[node name="GrabSequence" type="Node" parent="BehaviorTree/Selector"]
|
||||||
|
script = ExtResource("10_hv4ee")
|
||||||
|
|
||||||
|
[node name="HasAP" type="Node" parent="BehaviorTree/Selector/GrabSequence"]
|
||||||
|
script = ExtResource("11_7fhpq")
|
||||||
|
|
||||||
|
[node name="CanGrab" type="Node" parent="BehaviorTree/Selector/GrabSequence"]
|
||||||
|
script = ExtResource("13_41jsv")
|
||||||
|
|
||||||
|
[node name="DoGrab" type="Node" parent="BehaviorTree/Selector/GrabSequence"]
|
||||||
|
script = ExtResource("15_5h472")
|
||||||
|
|
||||||
|
[node name="MoveSequence" type="Node" parent="BehaviorTree/Selector"]
|
||||||
|
script = ExtResource("10_hv4ee")
|
||||||
|
|
||||||
|
[node name="HasAP" type="Node" parent="BehaviorTree/Selector/MoveSequence"]
|
||||||
|
script = ExtResource("11_7fhpq")
|
||||||
|
|
||||||
|
[node name="ShouldMove" type="Node" parent="BehaviorTree/Selector/MoveSequence"]
|
||||||
|
script = ExtResource("18_2ghcp")
|
||||||
|
|
||||||
|
[node name="DoMove" type="Node" parent="BehaviorTree/Selector/MoveSequence"]
|
||||||
|
script = ExtResource("19_dl4fn")
|
||||||
|
|
||||||
|
[node name="PutSequence" type="Node" parent="BehaviorTree/Selector"]
|
||||||
|
script = ExtResource("10_hv4ee")
|
||||||
|
|
||||||
|
[node name="HasAP" type="Node" parent="BehaviorTree/Selector/PutSequence"]
|
||||||
|
script = ExtResource("11_7fhpq")
|
||||||
|
|
||||||
|
[node name="CanPut" type="Node" parent="BehaviorTree/Selector/PutSequence"]
|
||||||
|
script = ExtResource("16_ac2sy")
|
||||||
|
|
||||||
|
[node name="DoPut" type="Node" parent="BehaviorTree/Selector/PutSequence"]
|
||||||
|
script = ExtResource("17_e03nk")
|
||||||
|
|
||||||
|
[node name="ArrangeSequence" type="Node" parent="BehaviorTree/Selector"]
|
||||||
|
script = ExtResource("10_hv4ee")
|
||||||
|
|
||||||
|
[node name="HasEnoughAP" type="Node" parent="BehaviorTree/Selector/ArrangeSequence"]
|
||||||
|
script = ExtResource("11_7fhpq")
|
||||||
|
|
||||||
|
[node name="CanArrange" type="Node" parent="BehaviorTree/Selector/ArrangeSequence"]
|
||||||
|
script = ExtResource("12_hr248")
|
||||||
|
|
||||||
|
[node name="DoArrange" type="Node" parent="BehaviorTree/Selector/ArrangeSequence"]
|
||||||
|
script = ExtResource("12_1ppih")
|
||||||
|
|||||||
@@ -1,6 +1,7 @@
|
|||||||
extends ActionLeaf
|
extends ActionLeaf
|
||||||
|
|
||||||
func tick(actor: Node, blackboard: Blackboard) -> int:
|
func tick(actor: Node, blackboard: Blackboard) -> int:
|
||||||
|
# Get target from blackboard
|
||||||
var target_pos = blackboard.get_value("move_target")
|
var target_pos = blackboard.get_value("move_target")
|
||||||
if not target_pos:
|
if not target_pos:
|
||||||
return FAILURE
|
return FAILURE
|
||||||
@@ -8,37 +9,18 @@ func tick(actor: Node, blackboard: Blackboard) -> int:
|
|||||||
if actor.action_points <= 0:
|
if actor.action_points <= 0:
|
||||||
return FAILURE
|
return FAILURE
|
||||||
|
|
||||||
# Verify target is still valid
|
# Execute movement
|
||||||
if not actor.is_within_movement_range(target_pos):
|
if 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():
|
if actor.is_multiplayer_authority():
|
||||||
path.pop_front()
|
var path = actor.enhanced_gridmap.find_path(
|
||||||
actor.rpc("start_movement_along_path", path)
|
Vector2(actor.current_position),
|
||||||
actor.action_points -= 1
|
Vector2(target_pos)
|
||||||
actor.clear_highlights()
|
)
|
||||||
return SUCCESS
|
if path.size() > 1:
|
||||||
|
path.pop_front()
|
||||||
|
actor.rpc("start_movement_along_path", path)
|
||||||
|
actor.action_points -= 1
|
||||||
|
blackboard.set_value("current_action", "moving")
|
||||||
|
return SUCCESS
|
||||||
|
|
||||||
return FAILURE
|
return FAILURE
|
||||||
|
|||||||
@@ -1,11 +0,0 @@
|
|||||||
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
|
|
||||||
@@ -1,5 +0,0 @@
|
|||||||
extends SequenceComposite
|
|
||||||
|
|
||||||
func _ready():
|
|
||||||
add_child(ArrangeCondition.new())
|
|
||||||
add_child(ArrangeAction.new())
|
|
||||||
@@ -1,22 +0,0 @@
|
|||||||
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
|
|
||||||
@@ -1,18 +0,0 @@
|
|||||||
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
|
|
||||||
@@ -1,21 +0,0 @@
|
|||||||
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
|
|
||||||
@@ -1,6 +1,18 @@
|
|||||||
extends ConditionLeaf
|
extends ConditionLeaf
|
||||||
|
|
||||||
func tick(actor: Node, blackboard: Blackboard) -> int:
|
func tick(actor: Node, blackboard: Blackboard) -> int:
|
||||||
|
var main = get_tree().get_root().get_node_or_null("Main")
|
||||||
|
if not main:
|
||||||
|
return FAILURE
|
||||||
|
|
||||||
|
# Always return SUCCESS for bots in non-turn-based mode
|
||||||
|
if actor.is_bot and not main.turn_based_mode:
|
||||||
|
return SUCCESS
|
||||||
|
|
||||||
|
# Update action points in blackboard
|
||||||
|
blackboard.set_value("action_points", actor.action_points)
|
||||||
|
|
||||||
|
# Check if we have enough AP
|
||||||
if actor.action_points >= 1:
|
if actor.action_points >= 1:
|
||||||
return SUCCESS
|
return SUCCESS
|
||||||
return FAILURE
|
return FAILURE
|
||||||
|
|||||||
@@ -1,85 +1,27 @@
|
|||||||
extends ConditionLeaf
|
extends ConditionLeaf
|
||||||
|
|
||||||
func tick(actor: Node, blackboard: Blackboard) -> int:
|
func tick(actor: Node, blackboard: Blackboard) -> int:
|
||||||
if actor.action_points <= 0:
|
# Find a valid movement target
|
||||||
return FAILURE
|
var target_pos = find_valid_target(actor)
|
||||||
|
if target_pos:
|
||||||
|
# Store target in blackboard
|
||||||
|
blackboard.set_value("move_target", target_pos)
|
||||||
|
return SUCCESS
|
||||||
|
return FAILURE
|
||||||
|
|
||||||
var target_pos = find_best_move_position(actor)
|
func find_valid_target(actor: Node) -> Vector2i:
|
||||||
if target_pos == Vector2i(-1, -1):
|
# Get random position in range
|
||||||
return FAILURE
|
var valid_positions = []
|
||||||
|
|
||||||
blackboard.set_value("move_target", target_pos)
|
for x in range(max(0, actor.current_position.x - actor.movement_range),
|
||||||
return SUCCESS
|
min(actor.enhanced_gridmap.columns, actor.current_position.x + actor.movement_range + 1)):
|
||||||
|
for z in range(max(0, actor.current_position.y - actor.movement_range),
|
||||||
func find_best_move_position(actor: Node) -> Vector2i:
|
min(actor.enhanced_gridmap.rows, actor.current_position.y + actor.movement_range + 1)):
|
||||||
# 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)
|
var pos = Vector2i(x, z)
|
||||||
if not actor.is_within_movement_range(pos):
|
if pos != actor.current_position and actor.is_within_movement_range(pos):
|
||||||
continue
|
if not actor.is_position_occupied(pos):
|
||||||
|
valid_positions.append(pos)
|
||||||
|
|
||||||
if actor.is_position_occupied(pos):
|
if valid_positions.size() > 0:
|
||||||
continue
|
return valid_positions[randi() % valid_positions.size()]
|
||||||
|
return Vector2i(-1, -1)
|
||||||
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
|
|
||||||
|
|||||||
@@ -1,5 +0,0 @@
|
|||||||
class_name GrabSequence extends SequenceComposite
|
|
||||||
|
|
||||||
func _ready():
|
|
||||||
add_child(GrabCondition.new())
|
|
||||||
add_child(GrabAction.new())
|
|
||||||
@@ -1,5 +0,0 @@
|
|||||||
class_name MoveSequence extends SequenceComposite
|
|
||||||
|
|
||||||
func _ready():
|
|
||||||
add_child(MoveCondition.new())
|
|
||||||
add_child(MoveAction.new())
|
|
||||||
@@ -1,5 +0,0 @@
|
|||||||
class_name PutSequence extends SequenceComposite
|
|
||||||
|
|
||||||
func _ready():
|
|
||||||
add_child(PutCondition.new())
|
|
||||||
add_child(PutAction.new())
|
|
||||||
+13
-114
@@ -1,125 +1,24 @@
|
|||||||
@tool
|
|
||||||
extends BeehaveTree
|
extends BeehaveTree
|
||||||
|
# In bot_behavior.gd
|
||||||
func _ready():
|
func _ready():
|
||||||
if Engine.is_editor_hint():
|
if Engine.is_editor_hint():
|
||||||
return
|
return
|
||||||
|
|
||||||
|
# Get parent node safely
|
||||||
|
var parent = get_parent()
|
||||||
|
if not parent:
|
||||||
|
push_error("BehaviorTree: No parent node found")
|
||||||
|
return
|
||||||
|
|
||||||
# Only setup for bots
|
# Only setup for bots
|
||||||
if not get_parent().is_in_group("Bots"):
|
if not parent.is_in_group("Bots"):
|
||||||
queue_free() # Remove tree if not a bot
|
queue_free() # Remove tree if not a bot
|
||||||
return
|
return
|
||||||
|
|
||||||
# Set this tree's actor
|
# Set this tree's actor
|
||||||
actor = get_parent()
|
actor = parent
|
||||||
|
|
||||||
|
# Wait a frame to ensure all nodes are ready
|
||||||
|
await get_tree().process_frame
|
||||||
|
|
||||||
enabled = true
|
enabled = true
|
||||||
|
|
||||||
# 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
|
|
||||||
|
|||||||
@@ -0,0 +1,27 @@
|
|||||||
|
@tool
|
||||||
|
extends Blackboard
|
||||||
|
|
||||||
|
# Default values when initializing blackboard
|
||||||
|
var default_data = {
|
||||||
|
"move_target": null, # Vector2i for movement target
|
||||||
|
"can_arrange": false, # Whether bot can arrange items
|
||||||
|
"can_grab": false, # Whether bot can grab items
|
||||||
|
"can_put": false, # Whether bot can put items
|
||||||
|
"should_move": false, # Whether bot should move
|
||||||
|
"action_points": 0, # Current action points
|
||||||
|
"current_action": "", # Current action being performed
|
||||||
|
"item_to_grab": null, # Item to grab
|
||||||
|
"grab_position": null, # Position to grab from
|
||||||
|
"put_position": null, # Position to put item
|
||||||
|
"arrange_from": -1, # Slot to arrange from
|
||||||
|
"arrange_to": -1 # Slot to arrange to
|
||||||
|
}
|
||||||
|
|
||||||
|
func _ready():
|
||||||
|
if Engine.is_editor_hint():
|
||||||
|
return
|
||||||
|
|
||||||
|
# Initialize with default values
|
||||||
|
for key in default_data:
|
||||||
|
if not has_value(key):
|
||||||
|
set_value(key, default_data[key])
|
||||||
Reference in New Issue
Block a user