update bot experimental

This commit is contained in:
2025-01-28 16:34:46 +08:00
parent 5a9092adfc
commit f3d720d91d
16 changed files with 272 additions and 375 deletions
+29 -12
View File
@@ -232,11 +232,19 @@ func _on_join_pressed():
func _on_peer_connected(new_peer_id):
if multiplayer.is_server():
await get_tree().create_timer(1).timeout
rpc("add_newly_connected_player_character", new_peer_id)
rpc_id(new_peer_id, "add_previously_connected_player_characters", connected_peer_ids)
# Increase delay to ensure scene is ready
await get_tree().create_timer(1.5).timeout
# Sync full state first
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)
rpc("add_newly_connected_player_character", new_peer_id)
replace_bot_with_player(new_peer_id)
func _on_peer_disconnected(peer_id):
@@ -270,23 +278,32 @@ func add_bot(bot_id):
@rpc("call_local")
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()
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.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("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():
bots.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):
if multiplayer.is_server() and bots.size() > 0:
+88 -44
View File
@@ -36,7 +36,6 @@ var rotation_speed: float = 10.0
rpc("display_message", "It's your turn!")
@export var has_moved_this_turn = false
@onready var main_scene = get_tree().current_scene
var highlighted_cells = []
@@ -44,40 +43,53 @@ func _ready():
name = str(get_multiplayer_authority())
$Name.text = str(name)
enhanced_gridmap = get_node(enhanced_gridmap_path)
if main_scene:
enhanced_gridmap = main_scene.get_node("EnhancedGridMap")
else:
# More robust way to get the main scene
var main_scene = get_tree().get_root().get_node_or_null("Main")
if not main_scene:
push_error("Main scene not found")
if not enhanced_gridmap:
push_error("EnhancedGridMap node not found")
return
enhanced_gridmap.initialize_astar()
enhanced_gridmap.set_diagonal_movement(use_diagonal_movement)
# Ensure proper initialization order
enhanced_gridmap = get_node(enhanced_gridmap_path)
if main_scene:
enhanced_gridmap = main_scene.get_node("EnhancedGridMap")
current_position = find_valid_starting_position()
update_player_position(current_position)
# Initialize behavior tree for bots
var behavior_tree = $BehaviorTree
# Set bot flag if in Bots group
if is_in_group("Bots"):
is_bot = true
if is_in_group("Bots") and behavior_tree:
behavior_tree.enabled = true
behavior_tree.actor = self
# Only process input if not a bot and is authority
set_process_unhandled_input(not is_bot and is_multiplayer_authority())
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()
playerboard.resize(25)
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:
var behavior_tree = $BehaviorTree
add_to_group("Bots", true) # Persistent group addition
var behavior_tree = get_node_or_null("BehaviorTree")
if behavior_tree:
behavior_tree.enabled = true
behavior_tree.actor = self
if not is_multiplayer_authority():
behavior_tree.set_physics_process(false)
behavior_tree.set_process(false)
func _physics_process(_delta):
if is_multiplayer_authority():
@@ -87,7 +99,11 @@ func _unhandled_input(event):
#if is_in_group("Bots"):
#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)):
return
@@ -102,7 +118,8 @@ func _unhandled_input(event):
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:
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 selected_playerboard_slot == -1:
select_playerboard_slot(slot_index)
@@ -120,8 +137,9 @@ func _on_slot_gui_input(event, slot_index, slot_ui) -> int:
return -1
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:
push_error("Main node not found")
return
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:
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:
return
@@ -257,7 +275,7 @@ func start_movement_along_path(path: Array):
enhanced_gridmap.clear_path_visualization()
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)
if main.turn_based_mode:
@@ -367,7 +385,7 @@ func grab_item(grid_position: Vector2i = current_position) -> bool:
_after_action_completed()
return true
else:
var main = get_node("/root/Main")
var main = get_tree().get_root().get_node_or_null("Main")
if main:
selected_gridmap_position = grid_position
clear_highlights()
@@ -414,14 +432,14 @@ func put_item(grid_position: Vector2i = current_position) -> bool:
clear_playerboard_highlights()
selected_playerboard_slot = -1
var main = get_node("/root/Main")
var main = get_tree().get_root().get_node_or_null("Main")
if main:
main.set_action_state(main.ActionState.NONE)
_after_action_completed()
return true
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:
return
@@ -437,7 +455,7 @@ func handle_put_action():
highlighted_cells.append(i)
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:
return
@@ -467,7 +485,7 @@ func handle_playerboard_slot_selected(slot_index: int):
# We also need to add handle_put_slot_selected:
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:
return
@@ -483,7 +501,7 @@ func handle_put_slot_selected(slot_index: int):
#var selected_item = playerboard[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:
#return
#
@@ -528,7 +546,7 @@ func arrange_playerboard_item(slot_index: int):
var selected_item = playerboard[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:
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:
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:
return
@@ -760,7 +778,7 @@ func highlight_occupied_playerboard_slots():
#if is_in_group("Bots"):
#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:
return
@@ -791,7 +809,7 @@ func clear_highlights():
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:
for i in range(main.playerboard_ui.get_child_count()):
var slot = main.playerboard_ui.get_child(i)
@@ -799,7 +817,7 @@ func clear_highlights():
child.hide()
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:
for i in range(main.playerboard_ui.get_child_count()):
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)
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:
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)
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:
return
@@ -902,14 +920,34 @@ func sync_playerboard(new_playerboard: Array):
playerboard = new_playerboard
_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():
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 not main.turn_based_mode and action_points <= 0:
action_points = 2
# Add this condition for bots
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_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_playerboard_ui()
@@ -917,11 +955,17 @@ func consume_action_points(points: int):
if not is_instance_valid(self) or not is_multiplayer_authority():
return
action_points -= points
var main = get_node("/root/Main")
var main = get_tree().get_root().get_node_or_null("Main")
if not main:
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 main.turn_based_mode:
main.request_end_turn()
+69 -3
View File
@@ -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="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="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://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"]
albedo_color = Color(0.85, 0.085, 0.238, 1)
@@ -87,7 +99,61 @@ autowrap_mode = 3
justification_flags = 171
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")
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")