extends Control # Main menu: one handler per game mode. Bot dropdowns are populated from # res://bots at runtime so newly trained bots appear automatically — never # maintain a hardcoded list. Selections are pushed into the GameSettings # autoload for the target mode to read, and restored when returning to the # menu within a session. const BOTS_DIR := "res://bots" @onready var bot_dropdown: OptionButton = %BotDropdown @onready var bot_a_dropdown: OptionButton = %BotADropdown @onready var bot_b_dropdown: OptionButton = %BotBDropdown func _ready() -> void: var bots := _list_bots() _populate_dropdown(bot_dropdown, bots, GameSettings.selected_bot_path) _populate_dropdown(bot_a_dropdown, bots, GameSettings.spectate_bot_a_path) _populate_dropdown(bot_b_dropdown, bots, GameSettings.spectate_bot_b_path) $CenterContainer/VBoxContainer/FreePlayButton.grab_focus() func _list_bots() -> Array[String]: var files: Array[String] = [] var dir := DirAccess.open(BOTS_DIR) if dir: for f in dir.get_files(): if f.get_extension() == "json": files.append(f) files.sort() return files # Fills a dropdown with bot names (metadata = full model path). Reselects # `preferred_path` if it's still on disk, else the newest (last) bot. func _populate_dropdown(dropdown: OptionButton, bots: Array[String], preferred_path: String) -> void: dropdown.clear() for f in bots: dropdown.add_item(f.get_basename()) dropdown.set_item_metadata(dropdown.item_count - 1, BOTS_DIR + "/" + f) if dropdown.item_count == 0: return dropdown.select(dropdown.item_count - 1) for i in dropdown.item_count: if dropdown.get_item_metadata(i) == preferred_path: dropdown.select(i) break func _selected_path(dropdown: OptionButton) -> String: if dropdown.item_count > 0 and dropdown.selected >= 0: return dropdown.get_item_metadata(dropdown.selected) return "" func _on_free_play_pressed() -> void: get_tree().change_scene_to_file("res://scenes/free_play.tscn") func _on_match_pressed() -> void: GameSettings.selected_bot_path = _selected_path(bot_dropdown) get_tree().change_scene_to_file("res://scenes/match.tscn") func _on_spectate_pressed() -> void: GameSettings.spectate_bot_a_path = _selected_path(bot_a_dropdown) GameSettings.spectate_bot_b_path = _selected_path(bot_b_dropdown) get_tree().change_scene_to_file("res://scenes/spectate.tscn")