diff --git a/assets/models/meshes/block.res b/assets/models/meshes/block.res index ab6f591..0935365 100644 Binary files a/assets/models/meshes/block.res and b/assets/models/meshes/block.res differ diff --git a/scenes/main.tscn b/scenes/main.tscn index bf860c5..3726d66 100644 --- a/scenes/main.tscn +++ b/scenes/main.tscn @@ -38,7 +38,7 @@ enable_bots = false mesh_library = ExtResource("1_110wo") cell_size = Vector3(1, 1, 1) data = { -"cells": PackedInt32Array(0, 0, 0, 0, 1, 0, 0, 2, 0, 0, 3, 0, 0, 4, 0, 0, 5, 0, 1, 0, 0, 1, 1, 0, 1, 2, 0, 1, 3, 0, 1, 4, 0, 1, 5, 0, 2, 0, 0, 2, 1, 0, 2, 2, 0, 2, 3, 0, 2, 4, 0, 2, 5, 0, 3, 0, 0, 3, 1, 0, 3, 2, 0, 3, 3, 0, 3, 4, 0, 3, 5, 0, 4, 0, 0, 4, 1, 0, 4, 2, 0, 4, 3, 0, 4, 4, 0, 4, 5, 0, 5, 0, 0, 5, 1, 0, 5, 2, 0, 5, 3, 0, 5, 4, 0, 5, 5, 0, 6, 0, 0, 6, 1, 0, 6, 2, 0, 6, 3, 0, 6, 4, 0, 6, 5, 0, 7, 0, 0, 7, 1, 0, 7, 2, 0, 7, 3, 0, 7, 4, 0, 7, 5, 0, 8, 0, 0, 8, 1, 0, 8, 2, 0, 8, 3, 0, 8, 4, 0, 8, 5, 0, 9, 0, 0, 9, 1, 0, 9, 2, 0, 9, 3, 0, 9, 4, 0, 9, 5, 0, 10, 0, 0, 10, 1, 0, 10, 2, 0, 10, 3, 0, 10, 4, 0, 10, 5, 0, 11, 0, 0, 11, 1, 0, 11, 2, 0, 11, 3, 0, 11, 4, 0, 11, 5, 0, 12, 0, 0, 12, 1, 0, 12, 2, 0, 12, 3, 0, 12, 4, 0, 12, 5, 0, 13, 0, 0, 13, 1, 0, 13, 2, 0, 13, 3, 0, 13, 4, 0, 13, 5, 0, 65536, 0, 8, 65536, 1, 10, 65536, 2, 7, 65536, 3, 10, 65536, 4, 8, 65536, 5, 7, 65537, 0, 9, 65537, 1, 10, 65537, 2, 9, 65537, 3, 8, 65537, 4, 10, 65537, 5, 9, 65538, 0, 7, 65538, 1, 8, 65538, 2, 7, 65538, 3, 8, 65538, 4, 7, 65538, 5, 9, 65539, 0, 8, 65539, 1, 10, 65539, 2, 10, 65539, 3, 8, 65539, 4, 10, 65539, 5, 8, 65540, 0, 7, 65540, 1, 8, 65540, 2, 10, 65540, 3, 7, 65540, 4, 8, 65540, 5, 9, 65541, 0, 7, 65541, 1, 8, 65541, 2, 7, 65541, 3, 9, 65541, 4, 8, 65541, 5, 10, 65542, 0, 8, 65542, 1, 7, 65542, 2, 9, 65542, 3, 10, 65542, 4, 8, 65542, 5, 9, 65543, 0, 10, 65543, 1, 8, 65543, 2, 7, 65543, 3, 10, 65543, 4, 8, 65543, 5, 10, 65544, 0, 7, 65544, 1, 10, 65544, 2, 7, 65544, 3, 9, 65544, 4, 8, 65544, 5, 7, 65545, 0, 7, 65545, 1, 8, 65545, 2, 7, 65545, 3, 7, 65545, 4, 7, 65545, 5, 9, 65546, 0, 7, 65546, 1, 7, 65546, 2, 8, 65546, 3, 8, 65546, 4, 10, 65546, 5, 8, 65547, 0, 7, 65547, 1, 10, 65547, 2, 7, 65547, 3, 9, 65547, 4, 10, 65547, 5, 10, 65548, 0, 8, 65548, 1, 9, 65548, 2, 10, 65548, 3, 7, 65548, 4, 8, 65548, 5, 7, 65549, 0, 8, 65549, 1, 10, 65549, 2, 10, 65549, 3, 9, 65549, 4, 8, 65549, 5, 10, 131072, 0, 2031616, 131072, 1, 2031616, 131072, 2, 2031616, 131072, 3, 2031616, 131072, 4, 2031616, 131072, 5, 2031616, 131073, 0, 2031616, 131073, 1, 2031616, 131073, 2, 2031616, 131073, 3, 2031616, 131073, 4, 2031616, 131073, 5, 2031616, 131074, 0, 2031616, 131074, 1, 2031616, 131074, 2, 2031616, 131074, 3, 2031616, 131074, 4, 2031616, 131074, 5, 2031616, 131075, 0, 2031616, 131075, 1, 2031616, 131075, 2, 2031616, 131075, 3, 2031616, 131075, 4, 2031616, 131075, 5, 2031616, 131076, 0, 2031616, 131076, 1, 2031616, 131076, 2, 2031616, 131076, 3, 2031616, 131076, 4, 2031616, 131076, 5, 2031616, 131077, 0, 2031616, 131077, 1, 2031616, 131077, 2, 2031616, 131077, 3, 2031616, 131077, 4, 2031616, 131077, 5, 2031616, 131078, 0, 2031616, 131078, 1, 2031616, 131078, 2, 2031616, 131078, 3, 2031616, 131078, 4, 2031616, 131078, 5, 2031616, 131079, 0, 2031616, 131079, 1, 2031616, 131079, 2, 2031616, 131079, 3, 2031616, 131079, 4, 2031616, 131079, 5, 2031616, 131080, 0, 2031616, 131080, 1, 2031616, 131080, 2, 2031616, 131080, 3, 2031616, 131080, 4, 2031616, 131080, 5, 2031616, 131081, 0, 2031616, 131081, 1, 2031616, 131081, 2, 2031616, 131081, 3, 2031616, 131081, 4, 2031616, 131081, 5, 2031616, 131082, 0, 2031616, 131082, 1, 2031616, 131082, 2, 2031616, 131082, 3, 2031616, 131082, 4, 2031616, 131082, 5, 2031616, 131083, 0, 2031616, 131083, 1, 2031616, 131083, 2, 2031616, 131083, 3, 2031616, 131083, 4, 2031616, 131083, 5, 2031616, 131084, 0, 2031616, 131084, 1, 2031616, 131084, 2, 2031616, 131084, 3, 2031616, 131084, 4, 2031616, 131084, 5, 2031616, 131085, 0, 2031616, 131085, 1, 2031616, 131085, 2, 2031616, 131085, 3, 2031616, 131085, 4, 2031616, 131085, 5, 2031616) +"cells": PackedInt32Array(0, 0, 0, 0, 1, 0, 0, 2, 0, 0, 3, 0, 0, 4, 0, 0, 5, 0, 1, 0, 0, 1, 1, 0, 1, 2, 0, 1, 3, 0, 1, 4, 0, 1, 5, 0, 2, 0, 0, 2, 1, 0, 2, 2, 0, 2, 3, 0, 2, 4, 0, 2, 5, 0, 3, 0, 0, 3, 1, 0, 3, 2, 0, 3, 3, 0, 3, 4, 0, 3, 5, 0, 4, 0, 0, 4, 1, 0, 4, 2, 0, 4, 3, 0, 4, 4, 0, 4, 5, 0, 5, 0, 0, 5, 1, 0, 5, 2, 0, 5, 3, 0, 5, 4, 0, 5, 5, 0, 6, 0, 0, 6, 1, 0, 6, 2, 0, 6, 3, 0, 6, 4, 0, 6, 5, 0, 7, 0, 0, 7, 1, 0, 7, 2, 0, 7, 3, 0, 7, 4, 0, 7, 5, 0, 8, 0, 0, 8, 1, 0, 8, 2, 0, 8, 3, 0, 8, 4, 0, 8, 5, 0, 9, 0, 0, 9, 1, 0, 9, 2, 0, 9, 3, 0, 9, 4, 0, 9, 5, 0, 10, 0, 0, 10, 1, 0, 10, 2, 0, 10, 3, 0, 10, 4, 0, 10, 5, 0, 11, 0, 0, 11, 1, 0, 11, 2, 0, 11, 3, 0, 11, 4, 0, 11, 5, 0, 12, 0, 0, 12, 1, 0, 12, 2, 0, 12, 3, 0, 12, 4, 0, 12, 5, 0, 13, 0, 0, 13, 1, 0, 13, 2, 0, 13, 3, 0, 13, 4, 0, 13, 5, 0, 65537, 0, 9, 65537, 1, 10, 65537, 2, 9, 65537, 3, 8, 65537, 4, 10, 65537, 5, 9, 65538, 0, 7, 65538, 1, 8, 65538, 2, 7, 65538, 3, 8, 65538, 4, 7, 65538, 5, 9, 65539, 0, 8, 65539, 1, 10, 65539, 2, 10, 65539, 3, 8, 65539, 4, 10, 65539, 5, 8, 65540, 0, 7, 65540, 1, 8, 65540, 2, 10, 65540, 3, 7, 65540, 4, 8, 65540, 5, 9, 65541, 0, 7, 65541, 1, 8, 65541, 2, 7, 65541, 3, 9, 65541, 4, 8, 65541, 5, 10, 65542, 0, 8, 65542, 1, 7, 65542, 2, 9, 65542, 3, 10, 65542, 4, 8, 65542, 5, 9, 65543, 0, 10, 65543, 1, 8, 65543, 2, 7, 65543, 3, 10, 65543, 4, 8, 65543, 5, 10, 65544, 0, 7, 65544, 1, 10, 65544, 2, 7, 65544, 3, 9, 65544, 4, 8, 65544, 5, 7, 65545, 0, 7, 65545, 1, 8, 65545, 2, 7, 65545, 3, 7, 65545, 4, 7, 65545, 5, 9, 65546, 0, 7, 65546, 1, 7, 65546, 2, 8, 65546, 3, 8, 65546, 4, 10, 65546, 5, 8, 65547, 0, 7, 65547, 1, 10, 65547, 2, 7, 65547, 3, 9, 65547, 4, 10, 65547, 5, 10, 65548, 0, 8, 65548, 1, 9, 65548, 2, 10, 65548, 3, 7, 65548, 4, 8, 65548, 5, 7, 131072, 0, 2031616, 131072, 1, 2031616, 131072, 2, 2031616, 131072, 3, 2031616, 131072, 4, 2031616, 131072, 5, 2031616, 131073, 0, 2031616, 131073, 1, 2031616, 131073, 2, 2031616, 131073, 3, 2031616, 131073, 4, 2031616, 131073, 5, 2031616, 131074, 0, 2031616, 131074, 1, 2031616, 131074, 2, 2031616, 131074, 3, 2031616, 131074, 4, 2031616, 131074, 5, 2031616, 131075, 0, 2031616, 131075, 1, 2031616, 131075, 2, 2031616, 131075, 3, 2031616, 131075, 4, 2031616, 131075, 5, 2031616, 131076, 0, 2031616, 131076, 1, 2031616, 131076, 2, 2031616, 131076, 3, 2031616, 131076, 4, 2031616, 131076, 5, 2031616, 131077, 0, 2031616, 131077, 1, 2031616, 131077, 2, 2031616, 131077, 3, 2031616, 131077, 4, 2031616, 131077, 5, 2031616, 131078, 0, 2031616, 131078, 1, 2031616, 131078, 2, 2031616, 131078, 3, 2031616, 131078, 4, 2031616, 131078, 5, 2031616, 131079, 0, 2031616, 131079, 1, 2031616, 131079, 2, 2031616, 131079, 3, 2031616, 131079, 4, 2031616, 131079, 5, 2031616, 131080, 0, 2031616, 131080, 1, 2031616, 131080, 2, 2031616, 131080, 3, 2031616, 131080, 4, 2031616, 131080, 5, 2031616, 131081, 0, 2031616, 131081, 1, 2031616, 131081, 2, 2031616, 131081, 3, 2031616, 131081, 4, 2031616, 131081, 5, 2031616, 131082, 0, 2031616, 131082, 1, 2031616, 131082, 2, 2031616, 131082, 3, 2031616, 131082, 4, 2031616, 131082, 5, 2031616, 131083, 0, 2031616, 131083, 1, 2031616, 131083, 2, 2031616, 131083, 3, 2031616, 131083, 4, 2031616, 131083, 5, 2031616, 131084, 0, 2031616, 131084, 1, 2031616, 131084, 2, 2031616, 131084, 3, 2031616, 131084, 4, 2031616, 131084, 5, 2031616, 131085, 0, 2031616, 131085, 1, 2031616, 131085, 2, 2031616, 131085, 3, 2031616, 131085, 4, 2031616, 131085, 5, 2031616) } script = ExtResource("2_hbe1v") columns = 14 diff --git a/scenes/player.gd b/scenes/player.gd index 1cfbeba..ba35d19 100644 --- a/scenes/player.gd +++ b/scenes/player.gd @@ -15,12 +15,14 @@ var can_finish @export var goals: Array[int] = [0,0,0,0,0,0,0,0,0] @export var playerboard: Array[int] = [0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0] +# Modifier for Turn based var has_performed_action: bool = false var selected_gridmap_position = Vector2i(-1, -1) var selected_playerboard_slot = -1 var targeted_playerboard_slot = -1 var action_points: int = 2 +# Modifier for player models var target_rotation: float = 0.0 var rotation_speed: float = 10.0 @@ -44,9 +46,10 @@ var finish_locations = [ ] var spawn_point_selected = false -var highlighted_spawn_points = [] -# Action +# Action for hilighter +var highlighted_spawn_points = [] +var highlighted_cells = [] var _is_processing_action = false var _is_highlighting = false @@ -65,7 +68,22 @@ var _is_highlighting = false @export var has_moved_this_turn = false -var highlighted_cells = [] +# Track, Lap, Position +var current_lap: int = 0 +var first_lap_goals: Array[int] = [] # Current goals (partial 3x3) +var second_lap_goals: Array[int] = [] # Full 3x3 goals +var race_position: int = 0 # Track finish position +static var lap1_finishers: int = 0 # Static to track across all players +static var lap2_finishers: int = 0 + +# Function to get ordinal string (1st, 2nd, 3rd, 4th) +func get_ordinal_string(number: int) -> String: + match number: + 1: return "1st" + 2: return "2nd" + 3: return "3rd" + 4: return "4th" + _: return str(number) + "th" func _ready(): # Ensure name is set first @@ -81,6 +99,13 @@ func _ready(): push_error("Main scene not found") return + # Modifier to handle the lap + if is_multiplayer_authority(): + # Generate the first_lap_goals + first_lap_goals = goals.duplicate() + # Generate the second_lap_goals + generate_second_lap_goals() + # Ensure proper initialization order enhanced_gridmap = get_node(enhanced_gridmap_path) if main_scene: @@ -182,12 +207,60 @@ func check_3x3_section(board: Array, goals: Array, start_row: int, start_col: in return true +# Generate full 3x3 goals for second lap +func generate_second_lap_goals(): + second_lap_goals.clear() + # Generate a complete 3x3 pattern (no empty spaces) + for i in range(9): + var val = (randi() % 4) + 7 # Values between 7 and 10 + second_lap_goals.append(val) + + if is_multiplayer_authority(): + rpc("sync_second_lap_goals", second_lap_goals) + +@rpc("any_peer", "reliable") +func sync_second_lap_goals(new_goals: Array): + second_lap_goals = new_goals + +# Modify finish_race to handle lap completion +@rpc("any_peer", "reliable") +func finish_race(): + if current_lap == 0: # Finishing first lap + lap1_finishers += 1 + race_position = lap1_finishers + + # Display first lap completion message + var message = "Finish 1st lap on " + get_ordinal_string(race_position) + if is_multiplayer_authority(): + rpc("display_message", message) + + # Start second lap + current_lap += 1 + rpc("start_new_lap") + + elif current_lap == 1: # Finishing second lap + lap2_finishers += 1 + race_position = lap2_finishers + + # Display second lap completion message + var message = "Finish 2nd lap on " + get_ordinal_string(race_position) + if is_multiplayer_authority(): + rpc("display_message", message) + + # Notify game completion + var main = get_tree().get_root().get_node_or_null("Main") + if main and is_multiplayer_authority(): + main.player_finished_race(self) + + # 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 + var current_goals = goals + # Convert 1D arrays to 2D for easier pattern matching var board_2d = [] var goals_2d = [] @@ -214,23 +287,55 @@ func check_pattern_match() -> bool: return false -# Add function to handle new lap +## 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) + +# Modify start_new_lap to handle different lap goals and starting positions @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) + if current_lap == 1: # Moving to second lap + # Start from first lap finish line + var valid_finish_pos = find_valid_position_in_finish_line() + if valid_finish_pos != Vector2i(-1, -1): + current_position = valid_finish_pos + update_player_position(current_position) + + # Set new goals (full 3x3) + goals = second_lap_goals.duplicate() + + # Reset playerboard + 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) + rpc("sync_goals", goals) + +# Function to find valid position in finish line +func find_valid_position_in_finish_line() -> Vector2i: + for pos in finish_locations: + if not is_position_occupied(pos): + return pos + return Vector2i(-1, -1) # Add function to check if player can reach finish func update_finish_availability(): @@ -243,8 +348,6 @@ func update_finish_availability(): else: unhighlight_finish_line() - - func unhighlight_finish_line(): if not is_multiplayer_authority() or is_bot: return @@ -288,7 +391,6 @@ func server_update_spawn_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): @@ -439,23 +541,6 @@ func is_position_occupied(pos: Vector2i) -> bool: return true return false -#func find_valid_starting_position() -> Vector2i: - #var rng = RandomNumberGenerator.new() - #rng.randomize() -# - #var max_attempts = 100 - #var attempts = 0 -# - #while attempts < max_attempts: - #var x = rng.randi_range(0, enhanced_gridmap.columns - 1) - #var y = rng.randi_range(0, enhanced_gridmap.rows - 1) - #var pos = Vector2i(x, y) - #if not is_position_occupied(pos): - #return pos - #attempts += 1 -# - #return Vector2i.ZERO - func find_valid_starting_position() -> Vector2i: if is_bot: return _find_random_spawn_position() @@ -494,27 +579,6 @@ func get_occupied_positions() -> Array: 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: @@ -618,9 +682,26 @@ func is_within_movement_range(target_position: Vector2i) -> bool: return distance <= movement_range func move_player_to_clicked_position(grid_position: Vector2i): + if not is_multiplayer_authority() or is_player_moving or action_points <= 0: return + var is_valid_finish = false + # Make scenario for match checking laps, for handle lap count + if current_lap == 0: # first lap + is_valid_finish = grid_position in finish_locations + else: # second lap + is_valid_finish = grid_position in spawn_locations + + if is_valid_finish: + if not can_finish: + can_finish = check_pattern_match() + if not can_finish: + return + + if not is_within_movement_range(grid_position): + return + 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 @@ -651,6 +732,10 @@ func move_player_to_clicked_position(grid_position: Vector2i): # Clear highlights after moving if not (is_bot or is_in_group("Bots")): clear_highlights() + + # Handle finish line crossing + if is_valid_finish and can_finish: + rpc("finish_race") @rpc("any_peer", "call_local") func start_movement_along_path(path: Array, clear_visual: bool = true): @@ -714,6 +799,21 @@ func end_turn(): if is_multiplayer_authority(): get_tree().get_root().get_node_or_null("Main").request_next_turn() +func reset_race(): + current_lap = 0 + race_position = 0 + can_finish = false + goals = first_lap_goals.duplicate() + playerboard.fill(-1) + if is_multiplayer_authority(): + rpc("sync_goals", goals) + rpc("sync_playerboard", playerboard) + +# Add a static reset for new games +static func reset_race_stats(): + lap1_finishers = 0 + lap2_finishers = 0 + @rpc("any_peer", "call_local", "unreliable") func remote_set_position(authority_position): global_position = authority_position