# ClassSelectionMenu.gd # Menü zur Auswahl der Charakterklasse beim Spielstart extends CanvasLayer signal class_selected(character_class: CharacterClass) const WARRIOR_CLASS = preload("res://classes/warrior.tres") const ROGUE_CLASS = preload("res://classes/rogue.tres") const MAGE_CLASS = preload("res://classes/mage.tres") const WARRIOR_PORTRAIT = preload("res://assets/Icons/Warrior.png") const ROGUE_PORTRAIT = preload("res://assets/Icons/Schurke.png") const MAGE_PORTRAIT = preload("res://assets/Icons/Magier.png") const CLASS_DATA = [ { "key": "warrior", "name": "Krieger", "res": null, # filled in _ready "portrait": null, "description": "Meister des Nahkampfs.\nHohe Rüstung und rohe Stärke.\nNutzt Wut als Ressource.", "lore": "Einst ein einfacher Söldner, der die falschen Leute bestahl. Er überlebte das Massaker an seiner Kompanie als Einziger — nicht durch Glück, sondern weil er zu wütend war, um zu sterben. Seitdem trägt er die Narben seiner Gefallenen auf der Haut und ihre Namen auf der Klinge.", "flavor": "\"Die Toten schreien nicht. Ich schreie für sie.\"" }, { "key": "rogue", "name": "Schurke", "res": null, "portrait": null, "description": "Schnell und tödlich.\nNah- und Fernkampf.\nNutzt Energie als Ressource.", "lore": "Aufgewachsen in den Kanalrohren der Unterstadt, lernte sie früh: Wer zuerst gesehen wird, verliert. Die Gilde der Stille formte sie zur Waffe — bis sie erkannte, dass sie selbst das Ziel war. Seitdem arbeitet sie für sich. Und für einen sehr hohen Preis.", "flavor": "\"Ich war schon hier, bevor du mich bemerkt hast.\"" }, { "key": "mage", "name": "Magier", "res": null, "portrait": null, "description": "Meister der Arkanen Künste.\nElementarmagie und Kontrolle.\nNutzt Mana als Ressource.", "lore": "Er war Hofgelehrter, bis er in verbotenen Archiven Worte las, die nicht für Sterbliche bestimmt waren. Die Akademie verbrannte seine Bücher. Das Feuer übernahm er — und alles andere, was sie ihm zu nehmen versuchten. Wissen hat seinen Preis. Er zahlt ihn gerne.", "flavor": "\"Das Universum ist Text. Ich lerne noch, es umzuschreiben.\"" } ] var selected_class: CharacterClass = null var _cards: Array = [] @onready var card_container = $Background/CardContainer @onready var start_btn = $Background/BottomBar/StartBtn # Farben für Karten-Zustände const COLOR_CARD_DEFAULT = Color(0.10, 0.08, 0.13, 1.0) const COLOR_CARD_HOVER = Color(0.14, 0.11, 0.18, 1.0) const COLOR_CARD_SELECTED = Color(0.18, 0.13, 0.25, 1.0) const COLOR_BORDER_DEFAULT = Color(0.25, 0.20, 0.35, 1.0) const COLOR_BORDER_SELECTED = Color(0.85, 0.65, 0.10, 1.0) func _ready(): get_tree().paused = true process_mode = Node.PROCESS_MODE_ALWAYS CLASS_DATA[0]["res"] = WARRIOR_CLASS CLASS_DATA[0]["portrait"] = WARRIOR_PORTRAIT CLASS_DATA[1]["res"] = ROGUE_CLASS CLASS_DATA[1]["portrait"] = ROGUE_PORTRAIT CLASS_DATA[2]["res"] = MAGE_CLASS CLASS_DATA[2]["portrait"] = MAGE_PORTRAIT for i in CLASS_DATA.size(): var card = _build_card(CLASS_DATA[i], i) card_container.add_child(card) _cards.append(card) start_btn.pressed.connect(_on_start_pressed) start_btn.disabled = true func _build_card(data: Dictionary, idx: int) -> Panel: var card = Panel.new() card.custom_minimum_size = Vector2(340, 580) card.size_flags_horizontal = Control.SIZE_EXPAND_FILL var style = StyleBoxFlat.new() style.bg_color = COLOR_CARD_DEFAULT style.border_width_left = 2 style.border_width_top = 2 style.border_width_right = 2 style.border_width_bottom = 2 style.border_color = COLOR_BORDER_DEFAULT style.corner_radius_top_left = 10 style.corner_radius_top_right = 10 style.corner_radius_bottom_right = 10 style.corner_radius_bottom_left = 10 card.add_theme_stylebox_override("panel", style) card.set_meta("style", style) card.set_meta("idx", idx) var vbox = VBoxContainer.new() vbox.set_anchors_and_offsets_preset(Control.PRESET_FULL_RECT, Control.PRESET_MODE_MINSIZE, 16) vbox.add_theme_constant_override("separation", 14) card.add_child(vbox) # Portrait var portrait = TextureRect.new() portrait.texture = data["portrait"] portrait.expand_mode = TextureRect.EXPAND_IGNORE_SIZE portrait.stretch_mode = TextureRect.STRETCH_KEEP_ASPECT_CENTERED portrait.custom_minimum_size = Vector2(0, 280) portrait.size_flags_horizontal = Control.SIZE_EXPAND_FILL portrait.size_flags_vertical = Control.SIZE_EXPAND_FILL vbox.add_child(portrait) # Klassenname var name_label = Label.new() name_label.text = data["name"] name_label.horizontal_alignment = HORIZONTAL_ALIGNMENT_CENTER name_label.add_theme_font_size_override("font_size", 26) vbox.add_child(name_label) # Trennlinie var sep = HSeparator.new() vbox.add_child(sep) # Lore var lore = Label.new() lore.text = data["lore"] lore.horizontal_alignment = HORIZONTAL_ALIGNMENT_CENTER lore.add_theme_font_size_override("font_size", 12) lore.modulate = Color(0.85, 0.82, 0.75, 1.0) lore.autowrap_mode = TextServer.AUTOWRAP_WORD_SMART lore.size_flags_vertical = Control.SIZE_EXPAND_FILL vbox.add_child(lore) # Trennlinie 2 var sep2 = HSeparator.new() vbox.add_child(sep2) # Gameplay Beschreibung var desc = Label.new() desc.text = data["description"] desc.horizontal_alignment = HORIZONTAL_ALIGNMENT_CENTER desc.add_theme_font_size_override("font_size", 13) desc.modulate = Color(0.7, 0.85, 0.7, 1.0) desc.autowrap_mode = TextServer.AUTOWRAP_WORD_SMART vbox.add_child(desc) # Flavor Text var flavor = Label.new() flavor.text = data["flavor"] flavor.horizontal_alignment = HORIZONTAL_ALIGNMENT_CENTER flavor.add_theme_font_size_override("font_size", 11) flavor.modulate = Color(0.7, 0.6, 0.4, 1.0) flavor.autowrap_mode = TextServer.AUTOWRAP_WORD_SMART vbox.add_child(flavor) # Stats var stats = Label.new() var char_class: CharacterClass = data["res"] stats.text = "STR %d | AGI %d | INT %d | STA %d" % [ char_class.base_strength, char_class.base_agility, char_class.base_intelligence, char_class.base_stamina ] stats.horizontal_alignment = HORIZONTAL_ALIGNMENT_CENTER stats.add_theme_font_size_override("font_size", 12) stats.modulate = Color(0.8, 0.8, 0.8, 1.0) vbox.add_child(stats) # Auswählen-Button var btn = Button.new() btn.text = "Auswählen" btn.add_theme_font_size_override("font_size", 16) btn.pressed.connect(_on_card_selected.bind(idx)) vbox.add_child(btn) # Hover card.mouse_entered.connect(_on_card_hover.bind(idx, true)) card.mouse_exited.connect(_on_card_hover.bind(idx, false)) card.mouse_filter = Control.MOUSE_FILTER_STOP return card func _on_card_selected(idx: int): selected_class = CLASS_DATA[idx]["res"] for i in _cards.size(): var s: StyleBoxFlat = _cards[i].get_meta("style") if i == idx: s.bg_color = COLOR_CARD_SELECTED s.border_color = COLOR_BORDER_SELECTED s.border_width_left = 3 s.border_width_top = 3 s.border_width_right = 3 s.border_width_bottom = 3 else: s.bg_color = COLOR_CARD_DEFAULT s.border_color = COLOR_BORDER_DEFAULT s.border_width_left = 2 s.border_width_top = 2 s.border_width_right = 2 s.border_width_bottom = 2 start_btn.disabled = false func _on_card_hover(idx: int, hovering: bool): var card = _cards[idx] var s: StyleBoxFlat = card.get_meta("style") var is_selected = (selected_class == CLASS_DATA[idx]["res"]) if is_selected: return s.bg_color = COLOR_CARD_HOVER if hovering else COLOR_CARD_DEFAULT func _on_start_pressed(): if selected_class == null: return class_selected.emit(selected_class) get_tree().paused = false queue_free()