253 lines
7.4 KiB
GDScript
253 lines
7.4 KiB
GDScript
extends Node3D
|
|
|
|
var multiplayer_peer = ENetMultiplayerPeer.new()
|
|
const PORT = 9999
|
|
const ADDRESS = "127.0.0.1"
|
|
|
|
var connected_peer_ids = []
|
|
var local_player_character : CharacterBody3D
|
|
var player_scene = preload("res://scenes/player.tscn")
|
|
var current_turn_index = 0
|
|
@export var players = []
|
|
var game_started = false
|
|
var max_message_input_char = 51
|
|
var max_players = 4
|
|
var bots = []
|
|
|
|
@export var turn_based_mode: bool = true # Toggle between turn-based and realtime modes
|
|
var bot_move_timer: float = 0.0 # Timer for bot movement in realtime mode
|
|
const BOT_MOVE_INTERVAL: float = 2.0 # Time between bot movements in realtime mode
|
|
|
|
# Bot movement state tracking
|
|
var moving_bots = {} # Dictionary to track which bots are currently moving
|
|
|
|
func _ready():
|
|
multiplayer_peer.peer_connected.connect(_on_peer_connected)
|
|
multiplayer_peer.peer_disconnected.connect(_on_peer_disconnected)
|
|
|
|
func _process(delta):
|
|
if multiplayer.is_server():
|
|
if game_started:
|
|
if turn_based_mode:
|
|
rpc("sync_turn_index", current_turn_index)
|
|
else:
|
|
# Handle realtime bot movement
|
|
bot_move_timer += delta
|
|
if bot_move_timer >= BOT_MOVE_INTERVAL:
|
|
bot_move_timer = 0.0
|
|
for bot_id in bots:
|
|
if not moving_bots.get(bot_id, false): # Only move if bot isn't already moving
|
|
move_bot(bot_id)
|
|
|
|
func _on_host_pressed():
|
|
$NetworkInfo/NetworkSideDisplay.text = "Server"
|
|
$Menu.visible = false
|
|
multiplayer_peer.create_server(PORT)
|
|
multiplayer.multiplayer_peer = multiplayer_peer
|
|
$NetworkInfo/UniquePeerID.text = str(multiplayer.get_unique_id())
|
|
|
|
add_player_character(1)
|
|
players.append(1)
|
|
|
|
# Add bots to fill remaining slots
|
|
for i in range(2, max_players + 1):
|
|
add_bot(i)
|
|
|
|
start_game()
|
|
|
|
func _on_join_pressed():
|
|
$NetworkInfo/NetworkSideDisplay.text = "Client"
|
|
$Menu.visible = false
|
|
multiplayer_peer.create_client(ADDRESS, PORT)
|
|
multiplayer.multiplayer_peer = multiplayer_peer
|
|
$NetworkInfo/UniquePeerID.text = str(multiplayer.get_unique_id())
|
|
|
|
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)
|
|
rpc_id(new_peer_id, "sync_game_state", players, bots, game_started, turn_based_mode)
|
|
add_player_character(new_peer_id)
|
|
replace_bot_with_player(new_peer_id)
|
|
|
|
func _on_peer_disconnected(peer_id):
|
|
if multiplayer.is_server():
|
|
connected_peer_ids.erase(peer_id)
|
|
players.erase(peer_id)
|
|
add_bot(get_next_available_bot_id())
|
|
|
|
func add_player_character(peer_id):
|
|
connected_peer_ids.append(peer_id)
|
|
var player_character = player_scene.instantiate()
|
|
player_character.set_multiplayer_authority(peer_id)
|
|
add_child(player_character)
|
|
player_character.add_to_group("Players", true)
|
|
if peer_id == multiplayer.get_unique_id():
|
|
local_player_character = player_character
|
|
|
|
func add_bot(bot_id):
|
|
if multiplayer.is_server():
|
|
rpc("create_bot", bot_id)
|
|
moving_bots[bot_id] = false
|
|
|
|
@rpc("call_local")
|
|
func create_bot(bot_id):
|
|
var bot_character = player_scene.instantiate()
|
|
bot_character.set_multiplayer_authority(1) # Set server as authority for bots
|
|
bot_character.name = str(bot_id)
|
|
add_child(bot_character)
|
|
bot_character.add_to_group("Players", true)
|
|
bot_character.add_to_group("Bots", true)
|
|
if multiplayer.is_server():
|
|
bots.append(bot_id)
|
|
players.append(bot_id)
|
|
moving_bots[bot_id] = false
|
|
|
|
func replace_bot_with_player(player_id):
|
|
if multiplayer.is_server() and bots.size() > 0:
|
|
var bot_id = bots.pop_front()
|
|
players.erase(bot_id)
|
|
players.append(player_id)
|
|
moving_bots.erase(bot_id) # Remove bot from moving tracking
|
|
rpc("remove_bot", bot_id)
|
|
rpc("sync_players", players)
|
|
|
|
@rpc("call_local")
|
|
func remove_bot(bot_id):
|
|
var bot_node = get_node(str(bot_id))
|
|
if bot_node:
|
|
bot_node.queue_free()
|
|
|
|
func get_next_available_bot_id():
|
|
for i in range(2, max_players + 1):
|
|
if not i in players:
|
|
return i
|
|
return -1
|
|
|
|
@rpc
|
|
func add_newly_connected_player_character(new_peer_id):
|
|
add_player_character(new_peer_id)
|
|
|
|
@rpc
|
|
func add_previously_connected_player_characters(peer_ids):
|
|
for peer_id in peer_ids:
|
|
add_player_character(peer_id)
|
|
|
|
@rpc("call_local")
|
|
func sync_game_state(current_players, current_bots, is_game_started, is_turn_based):
|
|
players = current_players
|
|
bots = current_bots
|
|
game_started = is_game_started
|
|
turn_based_mode = is_turn_based
|
|
|
|
# Create bot characters for existing bots
|
|
for bot_id in bots:
|
|
if not has_node(str(bot_id)):
|
|
create_bot(bot_id)
|
|
|
|
func start_game():
|
|
if multiplayer.is_server():
|
|
game_started = true
|
|
connected_peer_ids.sort()
|
|
rpc("sync_game_start", connected_peer_ids, players, bots, turn_based_mode)
|
|
if turn_based_mode:
|
|
current_turn_index = -1
|
|
next_turn()
|
|
|
|
@rpc("call_local")
|
|
func sync_game_start(peer_ids, current_players, current_bots, is_turn_based):
|
|
connected_peer_ids = peer_ids
|
|
players = current_players
|
|
bots = current_bots
|
|
turn_based_mode = is_turn_based
|
|
game_started = true
|
|
|
|
@rpc("reliable")
|
|
func sync_turn_index(index):
|
|
current_turn_index = index
|
|
|
|
@rpc("reliable")
|
|
func sync_players(new_players):
|
|
players = new_players
|
|
|
|
func next_turn():
|
|
if multiplayer.is_server() and turn_based_mode:
|
|
current_turn_index += 1
|
|
if current_turn_index >= players.size():
|
|
current_turn_index = 0
|
|
rpc("set_current_turn", players[current_turn_index])
|
|
if players[current_turn_index] in bots:
|
|
move_bot(players[current_turn_index])
|
|
|
|
func request_next_turn():
|
|
if multiplayer.is_server():
|
|
end_current_turn()
|
|
else:
|
|
rpc_id(1, "server_end_current_turn")
|
|
|
|
@rpc("any_peer")
|
|
func server_end_current_turn():
|
|
if multiplayer.is_server():
|
|
end_current_turn()
|
|
|
|
@rpc("any_peer", "call_local")
|
|
func set_current_turn(player_id):
|
|
if not turn_based_mode:
|
|
return
|
|
|
|
var players = get_tree().get_nodes_in_group("Players")
|
|
for player in players:
|
|
player.is_my_turn = (player.name == str(player_id))
|
|
if player.is_my_turn:
|
|
player.start_turn()
|
|
|
|
func end_current_turn():
|
|
if multiplayer.is_server():
|
|
next_turn()
|
|
rpc("sync_turn_index", current_turn_index)
|
|
|
|
func _on_message_input_text_submitted(new_text):
|
|
if new_text.length() > max_message_input_char:
|
|
new_text = new_text.substr(0, max_message_input_char) + " ... "
|
|
local_player_character.rpc("display_message", new_text)
|
|
$MessageInput.text = ""
|
|
$MessageInput.release_focus()
|
|
|
|
func move_bot(bot_id):
|
|
if multiplayer.is_server():
|
|
if moving_bots.get(bot_id, false):
|
|
return # Skip if bot is already moving
|
|
|
|
var bot = get_node(str(bot_id))
|
|
if bot and (turn_based_mode or not bot.is_player_moving):
|
|
moving_bots[bot_id] = true # Mark bot as moving
|
|
var target_position = bot.find_random_valid_position_in_range() # Use the new function
|
|
if target_position != bot.current_position:
|
|
var path = bot.enhanced_gridmap.find_path(Vector2(bot.current_position), Vector2(target_position))
|
|
|
|
if path.size() > 1:
|
|
path.pop_front()
|
|
# Trim path to respect movement range
|
|
var trimmed_path = path.slice(0, bot.movement_range)
|
|
bot.move_bot_along_path(trimmed_path, bot_id)
|
|
else:
|
|
print("No valid path found for bot")
|
|
moving_bots[bot_id] = false
|
|
if turn_based_mode:
|
|
end_current_turn()
|
|
else:
|
|
print("No new valid position found for bot")
|
|
moving_bots[bot_id] = false
|
|
if turn_based_mode:
|
|
end_current_turn()
|
|
else:
|
|
print("Bot not found or is moving")
|
|
if turn_based_mode:
|
|
end_current_turn()
|
|
|
|
# Called when a bot finishes moving
|
|
func bot_movement_completed(bot_id):
|
|
if multiplayer.is_server():
|
|
moving_bots[bot_id] = false
|