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 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 (copied from player.gd) 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) ] 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 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 unhighlight_finish_line(): if not player.is_multiplayer_authority() or player.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] ) func is_at_finish_line() -> bool: return player.current_position in finish_locations 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 player.rpc("start_new_lap") elif current_lap == 1: lap2_finishers += 1 race_position = lap2_finishers var message = "Finish 2nd lap on " + get_ordinal_string(race_position) if player.is_multiplayer_authority(): player.rpc("display_message", message) func start_new_lap(): if current_lap == 1: var valid_finish_pos = find_valid_position_in_finish_line() if valid_finish_pos != Vector2i(-1, -1): player.current_position = valid_finish_pos player.update_player_position(player.current_position) goals = second_lap_goals.duplicate() can_finish = false if player.is_multiplayer_authority(): player.rpc("sync_position", player.current_position) player.rpc("sync_playerboard", playerboard) player.rpc("sync_goals", goals) func find_valid_position_in_finish_line() -> Vector2i: for pos in finish_locations: if not player.is_position_occupied(pos): return pos return Vector2i(-1, -1)