extends Node var player: Node3D var enhanced_gridmap: Node # Race state var current_lap: int = 0 var first_lap_goals: Array[int] = [] var second_lap_goals: Array[int] = [] var race_position: int = 0 var has_finished_race: bool = false static var lap1_finishers: int = 0 static var lap2_finishers: int = 0 # Goals and Playerboard var goals: Array[int] = [0, 0, 0, 0, 0, 0, 0, 0, 0] 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] var can_finish: bool = false # Finish locations (right side for 1st lap) var finish_locations = [ Vector2i(13, 0), Vector2i(13, 1), Vector2i(13, 2), Vector2i(13, 3), Vector2i(13, 4), Vector2i(13, 5), Vector2i(13, 6), Vector2i(13, 7), Vector2i(13, 8), Vector2i(13, 9), Vector2i(13, 10), Vector2i(13, 11), Vector2i(13, 12), Vector2i(13, 13) ] # Spawn locations (left side for 2nd lap finish) var spawn_locations = [ Vector2i(0, 0), Vector2i(0, 1), Vector2i(0, 2), Vector2i(0, 3), Vector2i(0, 4), Vector2i(0, 5), Vector2i(0, 6), Vector2i(0, 7), Vector2i(0, 8), Vector2i(0, 9), Vector2i(0, 10), Vector2i(0, 11), Vector2i(0, 12), Vector2i(0, 13) ] # Helper function to get current finish locations based on lap func get_current_finish_locations() -> Array: if current_lap == 0: return finish_locations # 1st lap: finish at right side else: return spawn_locations # 2nd lap: finish at left side (spawn locations) func initialize(p_player: Node3D, p_gridmap: Node): player = p_player enhanced_gridmap = p_gridmap if player.is_multiplayer_authority(): first_lap_goals = goals.duplicate() generate_second_lap_goals() 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 generate_second_lap_goals(): second_lap_goals.clear() for i in range(9): var val = (randi() % 4) + 7 second_lap_goals.append(val) if player.is_multiplayer_authority(): player.rpc("sync_second_lap_goals", second_lap_goals) func check_3x3_section(board: Array, goals_pattern: Array, start_row: int, start_col: int) -> bool: for i in range(3): for j in range(3): if goals_pattern[i][j] != -1: var board_value = board[start_row + i][start_col + j] if board_value == -1: return false for i in range(3): for j in range(3): if goals_pattern[i][j] != -1: if board[start_row + i][start_col + j] != goals_pattern[i][j]: return false return true func check_pattern_match() -> bool: if playerboard.size() != 25 or goals.size() != 9: return false var board_2d = [] var goals_2d = [] for i in range(5): var row = [] for j in range(5): row.append(playerboard[i * 5 + j]) board_2d.append(row) for i in range(3): var row = [] for j in range(3): row.append(goals[i * 3 + j]) goals_2d.append(row) for start_row in range(3): for start_col in range(3): if check_3x3_section(board_2d, goals_2d, start_row, start_col): return true return false func update_finish_availability(): can_finish = check_pattern_match() if player.is_multiplayer_authority(): if can_finish: highlight_finish_line() else: unhighlight_finish_line() func highlight_finish_line(): if not player.is_multiplayer_authority() or player.is_bot: return var current_finish = get_current_finish_locations() for finish_pos in current_finish: if enhanced_gridmap: enhanced_gridmap.set_cell_item( Vector3i(finish_pos.x, 0, finish_pos.y), enhanced_gridmap.hover_item ) func unhighlight_finish_line(): if not player.is_multiplayer_authority() or player.is_bot: return var current_finish = get_current_finish_locations() for finish_pos in current_finish: if enhanced_gridmap: enhanced_gridmap.set_cell_item( Vector3i(finish_pos.x, 0, finish_pos.y), enhanced_gridmap.normal_items[0] ) func is_at_finish_line() -> bool: var current_finish = get_current_finish_locations() return player.current_position in current_finish func finish_race(): if current_lap == 0: lap1_finishers += 1 race_position = lap1_finishers var message = "Finish 1st lap on " + get_ordinal_string(race_position) if player.is_multiplayer_authority(): player.rpc("display_message", message) current_lap += 1 start_new_lap() elif current_lap == 1: lap2_finishers += 1 race_position = lap2_finishers var message = "RACE COMPLETE! Finished " + get_ordinal_string(race_position) if player.is_multiplayer_authority(): player.rpc("display_message", message) player.rpc("complete_race", race_position) # Called when player finishes the entire race (2nd lap complete) func on_race_completed(final_position: int): has_finished_race = true race_position = final_position can_finish = false # Disable all player input player.set_process_input(false) player.set_process_unhandled_input(false) player.is_my_turn = false player.action_points = 0 # Clear any highlights if player.action_manager: player.action_manager.clear_highlights() player.action_manager.clear_playerboard_highlights() # Unhighlight finish line unhighlight_finish_line() print("Player %s finished the race in position %d!" % [player.name, final_position]) func start_new_lap(): if current_lap == 1: # Update goals to 2nd lap goals goals = second_lap_goals.duplicate() can_finish = false # Sync with all clients if player.is_multiplayer_authority(): player.rpc("sync_position", player.current_position) player.rpc("sync_playerboard", playerboard) player.rpc("sync_goals", goals) print("Started 2nd lap with new goals: ", goals) func find_valid_position_in_finish_line() -> Vector2i: var current_finish = get_current_finish_locations() for pos in current_finish: if not player.is_position_occupied(pos): return pos return Vector2i(-1, -1)