This commit is contained in:
2025-04-16 18:02:58 +08:00
parent 6d4407128f
commit 49cc53e230
2 changed files with 6185 additions and 4 deletions
+227 -4
View File
@@ -7,6 +7,7 @@ var enhanced_gridmap: EnhancedGridMap
@export var current_position: Vector2i
var is_player_moving: bool = false
var _verify_timer: float = 0.0
var can_finish
@export var cell_size: Vector3 = Vector3(2, 2, 2)
@export var cell_offset: Vector3 = Vector3(0, 0, 0)
@@ -32,6 +33,16 @@ var spawn_locations = [
Vector2i(0, 5) # (0,1,5)
]
# Add these as class variables at the top of the file
var finish_locations = [
Vector2i(13, 0), # (13,0,0)
Vector2i(13, 1), # (13,0,1)
Vector2i(13, 2), # (13,0,2)
Vector2i(13, 3), # (13,0,3)
Vector2i(13, 4), # (13,0,4)
Vector2i(13, 5) # (13,0,5)
]
var spawn_point_selected = false
var highlighted_spawn_points = []
@@ -99,16 +110,23 @@ func _ready():
#current_position = find_valid_starting_position()
#update_player_position(current_position)
# Spawn point handler
if enhanced_gridmap:
current_position = _find_random_spawn_position()
update_player_position(current_position)
spawn_point_selected = true
# Notify others about bot spawn position
rpc("notify_spawn_selected", current_position)
else:
# Human player initialization
if enhanced_gridmap:
enhanced_gridmap.initialize_astar()
enhanced_gridmap.set_diagonal_movement(use_diagonal_movement)
# Request current spawn positions before highlighting
request_spawn_positions_update()
highlight_available_spawn_points()
# Remove this line as goals are now managed by the host
#append_random_goals()
@@ -141,6 +159,152 @@ func _ready():
if is_multiplayer_authority():
rpc("sync_position", current_position)
# Add function to check if position is at finish line
func is_at_finish_line() -> bool:
return current_position in finish_locations
# Helper function to check if a 3x3 section matches the goals pattern
func check_3x3_section(board: Array, goals: Array, start_row: int, start_col: int) -> bool:
# First check if any required positions are empty (-1)
for i in range(3):
for j in range(3):
if goals[i][j] != -1: # Only check positions that are required by the goals
var board_value = board[start_row + i][start_col + j]
if board_value == -1: # If required position is empty
return false
# Then check if the pattern matches
for i in range(3):
for j in range(3):
if goals[i][j] != -1: # Only check positions that are required by the goals
if board[start_row + i][start_col + j] != goals[i][j]:
return false
return true
# Add function to check 3x3 pattern matching anywhere in 5x5 playerboard
func check_pattern_match() -> bool:
# Early return if playerboard or goals are not properly sized
if playerboard.size() != 25 or goals.size() != 9:
return false
# Convert 1D arrays to 2D for easier pattern matching
var board_2d = []
var goals_2d = []
# Convert playerboard to 2D (5x5)
for i in range(5):
var row = []
for j in range(5):
row.append(playerboard[i * 5 + j])
board_2d.append(row)
# Convert goals to 2D (3x3)
for i in range(3):
var row = []
for j in range(3):
row.append(goals[i * 3 + j])
goals_2d.append(row)
# Check each possible 3x3 section in the 5x5 board
for start_row in range(3): # 5-3+1 possible starting rows
for start_col in range(3): # 5-3+1 possible starting columns
if check_3x3_section(board_2d, goals_2d, start_row, start_col):
return true
return false
# Add function to handle new lap
@rpc("any_peer", "reliable")
func start_new_lap():
# Reset position to start
current_position = find_valid_starting_position()
update_player_position(current_position)
# Reset playerboard but keep the goals
playerboard.fill(-1)
# Reset can_finish flag
can_finish = false
# Sync with other clients
if is_multiplayer_authority():
rpc("sync_position", current_position)
rpc("sync_playerboard", playerboard)
# Add function to check if player can reach finish
func update_finish_availability():
can_finish = check_pattern_match()
# Update visual feedback if needed
if is_multiplayer_authority():
if can_finish:
highlight_finish_line()
else:
unhighlight_finish_line()
func unhighlight_finish_line():
if not is_multiplayer_authority() or is_bot:
return
for finish_pos in finish_locations:
if enhanced_gridmap:
enhanced_gridmap.set_cell_item(
Vector3i(finish_pos.x, 0, finish_pos.y),
enhanced_gridmap.normal_items[0]
)
# Add functions to handle finish line visualization
func highlight_finish_line():
if not is_multiplayer_authority() or is_bot:
return
for finish_pos in finish_locations:
if enhanced_gridmap:
enhanced_gridmap.set_cell_item(
Vector3i(finish_pos.x, 0, finish_pos.y),
enhanced_gridmap.hover_item
)
func request_spawn_positions_update():
if multiplayer.is_server():
# Server can directly highlight available positions
highlight_available_spawn_points()
else:
# Clients request an update from the server
rpc_id(1, "server_update_spawn_positions")
# Add server-side spawn position update handler
@rpc("any_peer", "reliable")
func server_update_spawn_positions():
if not multiplayer.is_server():
return
var sender_id = multiplayer.get_remote_sender_id()
var occupied = get_occupied_positions()
# Send the occupied positions back to the requesting client
rpc_id(sender_id, "receive_spawn_positions_update", occupied)
# Add client-side spawn position update receiver
# Add client-side spawn position update receiver
@rpc("authority", "reliable")
func receive_spawn_positions_update(occupied_positions: Array):
# Update local highlight state based on received occupied positions
for pos in highlighted_spawn_points:
if pos in occupied_positions:
highlighted_spawn_points.erase(pos)
if enhanced_gridmap:
enhanced_gridmap.set_cell_item(
Vector3i(pos.x, 0, pos.y),
enhanced_gridmap.normal_items[0]
)
# Now highlight available positions
highlight_available_spawn_points()
@rpc("any_peer", "call_local")
func sync_bot_status(is_bot_status: bool):
is_bot = is_bot_status
@@ -268,9 +432,10 @@ func handle_grid_click(grid_position: Vector2i):
if grid_position in highlighted_cells:
main.place_obstacle(grid_position)
# Modify is_position_occupied to check for selected spawn points
func is_position_occupied(pos: Vector2i) -> bool:
for player in get_tree().get_nodes_in_group("Players"):
if player != self and player.current_position == pos:
if player != self and player.spawn_point_selected and player.current_position == pos:
return true
return false
@@ -307,6 +472,9 @@ func highlight_available_spawn_points():
clear_highlights()
highlighted_spawn_points.clear()
# Get all currently occupied positions
var occupied_positions = get_occupied_positions()
# Check each spawn location
for spawn_pos in spawn_locations:
if not is_position_occupied(spawn_pos):
@@ -318,21 +486,54 @@ func highlight_available_spawn_points():
enhanced_gridmap.hover_item
)
# Add function to get all occupied positions
func get_occupied_positions() -> Array:
var occupied = []
for player in get_tree().get_nodes_in_group("Players"):
if player.spawn_point_selected: # Only count players who have selected a spawn point
occupied.append(player.current_position)
return occupied
#func select_spawn_point(spawn_pos: Vector2i) -> bool:
#if not is_multiplayer_authority() or is_bot or spawn_point_selected:
#return false
#
#if spawn_pos in highlighted_spawn_points:
#current_position = spawn_pos
#spawn_point_selected = true
#
## Update position in the world
#position = grid_to_world(spawn_pos)
#
## Clear ALL highlights comprehensively
#clear_spawn_highlights()
#
## Sync with other clients
#if is_multiplayer_authority():
#rpc("sync_position", current_position)
#
#return true
#return false
# Modify the select_spawn_point function to notify other clients
func select_spawn_point(spawn_pos: Vector2i) -> bool:
if not is_multiplayer_authority() or is_bot or spawn_point_selected:
return false
if spawn_pos in highlighted_spawn_points:
if spawn_pos in highlighted_spawn_points and not is_position_occupied(spawn_pos):
current_position = spawn_pos
spawn_point_selected = true
# Update position in the world
position = grid_to_world(spawn_pos)
# Clear ALL highlights comprehensively
# Notify all clients about the spawn selection
rpc("notify_spawn_selected", spawn_pos)
# Clear highlights locally
clear_spawn_highlights()
# Sync with other clients
# Sync position with other clients
if is_multiplayer_authority():
rpc("sync_position", current_position)
@@ -737,6 +938,22 @@ func request_server_put(grid_position: Vector2i, slot_index: int, x: int, y: int
# Notify about action completion
_after_action_completed()
# Add new RPC function to notify others about spawn selection
@rpc("any_peer", "reliable")
func notify_spawn_selected(spawn_pos: Vector2i):
# Update local highlight state for all clients
if spawn_pos in highlighted_spawn_points:
highlighted_spawn_points.erase(spawn_pos)
# Clear highlight for the selected position
if enhanced_gridmap:
enhanced_gridmap.set_cell_item(
Vector3i(spawn_pos.x, 0, spawn_pos.y),
enhanced_gridmap.normal_items[0]
)
func handle_put_action():
var main = get_tree().get_root().get_node_or_null("Main")
if not main or action_points < 1:
@@ -1318,6 +1535,9 @@ func _after_action_completed():
return
_is_processing_action = true
if is_multiplayer_authority():
update_finish_availability()
# Clear the highlights after placing the tiles. (Quickfix for Clientside)
clear_highlights()
@@ -1342,6 +1562,9 @@ func _after_action_completed():
_is_processing_action = false
func is_finish_position(pos: Vector2i) -> bool:
return pos in finish_locations
func consume_action_points(points: int):
if not is_instance_valid(self) or not is_multiplayer_authority():
return