extends Control ## #588: Character archetype select panel — shown after "New Game", before loading main.tscn. ## Two cards (Smuggler / Detective). Keyboard (left/right/enter/esc) and mouse. ## Emits archetype_confirmed(archetype: String) or archetype_cancelled on ESC. ## ## ESC cancels without creating a save directory — new_game() fires AFTER confirmation. signal archetype_confirmed(archetype: String) signal archetype_cancelled const CARD_BG_NORMAL := Color(0.07, 0.07, 0.10, 1.0) const CARD_BG_SELECTED := Color(0.10, 0.12, 0.18, 1.0) const CARD_BORDER_NORMAL := Color(0.18, 0.22, 0.28, 1.0) const CARD_BORDER_SELECTED := Color(0.906, 0.773, 0.278, 1.0) # INSERT_COLOR_HOVER # Archetypes in display order — index 0=smuggler (left card), 1=detective (right card) const ARCHETYPES := ["smuggler", "detective"] @onready var _smuggler_wrapper: Control = $Cards/CardSmugglerWrapper @onready var _detective_wrapper: Control = $Cards/CardDetectiveWrapper @onready var _confirm_btn: Button = $ConfirmBtn @onready var _title_label: Label = $TitleLabel var _selected_index: int = 0 # 0=smuggler, 1=detective func _ready() -> void: _title_label.text = UIStrings.get_text("character_select.title") _confirm_btn.text = UIStrings.get_text("character_select.confirm") # Smuggler card labels $Cards/CardSmugglerWrapper/CardInner/VBox/NameLabel.text = UIStrings.get_text("character_select.smuggler_card_name") $Cards/CardSmugglerWrapper/CardInner/VBox/RoleLabel.text = UIStrings.get_text("character_select.smuggler_card_role") $Cards/CardSmugglerWrapper/CardInner/VBox/ToneLabel.text = UIStrings.get_text("character_select.smuggler_card_tone") # Detective card labels $Cards/CardDetectiveWrapper/CardInner/VBox/NameLabel.text = UIStrings.get_text("character_select.detective_card_name") $Cards/CardDetectiveWrapper/CardInner/VBox/RoleLabel.text = UIStrings.get_text("character_select.detective_card_role") $Cards/CardDetectiveWrapper/CardInner/VBox/ToneLabel.text = UIStrings.get_text("character_select.detective_card_tone") _confirm_btn.pressed.connect(_on_confirm) _smuggler_wrapper.gui_input.connect(_on_card_input.bind(0)) _detective_wrapper.gui_input.connect(_on_card_input.bind(1)) _update_card_visuals() func _input(event: InputEvent) -> void: if not visible: return if event is InputEventKey and event.pressed and not event.is_echo(): match event.keycode: KEY_LEFT: _selected_index = 0 _update_card_visuals() get_viewport().set_input_as_handled() KEY_RIGHT: _selected_index = 1 _update_card_visuals() get_viewport().set_input_as_handled() KEY_ENTER, KEY_KP_ENTER: _on_confirm() get_viewport().set_input_as_handled() KEY_ESCAPE: archetype_cancelled.emit() get_viewport().set_input_as_handled() func _on_card_input(event: InputEvent, card_index: int) -> void: if event is InputEventMouseButton and event.pressed and event.button_index == MOUSE_BUTTON_LEFT: _selected_index = card_index _update_card_visuals() func _on_confirm() -> void: archetype_confirmed.emit(ARCHETYPES[_selected_index]) func _update_card_visuals() -> void: _set_card_selected(_smuggler_wrapper, _selected_index == 0) _set_card_selected(_detective_wrapper, _selected_index == 1) _confirm_btn.grab_focus() func _set_card_selected(wrapper: Control, selected: bool) -> void: var border: ColorRect = wrapper.get_node("CardBorder") var inner: ColorRect = wrapper.get_node("CardInner") border.color = CARD_BORDER_SELECTED if selected else CARD_BORDER_NORMAL inner.color = CARD_BG_SELECTED if selected else CARD_BG_NORMAL