class_name WorkshopScreen extends Control ## Werkstatt (nach Kapitel 5): eigene Karten aus Staub bauen. Links Elemente (beliebig viele), ## Angriff, Leben, Eigenschaften (beliebig viele) und der Name; rechts die Vorschau mit Kosten ## (Cards.cost_with), Wert und Preis (Profile.build_price). „Bauen“ legt die Karte als Common in ## Sammlung und Stapel. var app var elements: Array = [] var keywords: Array = [] var attack_slider: HSlider var health_slider: HSlider var attack_label: Label var health_label: Label var element_buttons := {} var keyword_boxes := {} var name_box: LineEdit var info_label: Label var msg_label: Label var dust_label: Label var preview_holder: Control var built := 0 # für den Vorschlagsnamen func _ready() -> void: Style.header(self, "Werkstatt", func(): app.show_screen(MenuScreen.new())) dust_label = Style.chip(self, "", Rect2(860, 26, 240, 38), Style.BLUE) Style.panel(self, Rect2(40, 86, 700, 696)) Style.label(self, "Baue eigene Karten aus Staub: so viele Elemente und Eigenschaften du willst, jede kostet Mana.", 14, Style.MUTED, Rect2(60, 98, 660, 22), "left") Style.label(self, "Elemente", 16, Style.TEXT, Rect2(60, 134, 140, 30), "left", true) var all_elements: Array = Cards.ELEMENTS + [Cards.NEUTRAL] for i in all_elements.size(): var e: String = all_elements[i] var b := DeckScreen.ElementButton.new(e) b.position = Vector2(200 + i * 48, 130) b.size = Vector2(40, 40) b.pressed.connect(toggle_element.bind(e)) Style.juice(b) add_child(b) element_buttons[e] = b Style.label(self, "Angriff", 16, Style.TEXT, Rect2(60, 194, 140, 30), "left", true) attack_slider = _slider(Rect2(200, 198, 400, 24), 0, 10, 3) attack_label = Style.label(self, "", 18, Style.AMBER, Rect2(620, 192, 60, 30), "center", true) Style.label(self, "Leben", 16, Style.TEXT, Rect2(60, 244, 140, 30), "left", true) health_slider = _slider(Rect2(200, 248, 400, 24), 1, 10, 3) health_label = Style.label(self, "", 18, Style.LIFE, Rect2(620, 242, 60, 30), "center", true) Style.label(self, "Eigenschaften", 16, Style.TEXT, Rect2(60, 300, 200, 30), "left", true) for k in Cards.KEYWORDS.size(): var kw: String = Cards.KEYWORDS[k] var cb := CheckButton.new() cb.text = tr(kw) cb.position = Vector2(200, 300 + k * 44) cb.size = Vector2(220, 36) cb.toggled.connect(func(on: bool): toggle_keyword(kw, on)) add_child(cb) keyword_boxes[kw] = cb Style.label(self, tr(Cards.KEYWORD_TEXT[kw]), 13, Style.MUTED, Rect2(430, 306 + k * 44, 300, 24), "left") Style.label(self, "Name", 16, Style.TEXT, Rect2(60, 490, 140, 30), "left", true) name_box = LineEdit.new() name_box.position = Vector2(200, 486) name_box.size = Vector2(400, 36) name_box.max_length = 24 name_box.text_changed.connect(func(_t: String): refresh()) add_child(name_box) info_label = Style.label(self, "", 16, Style.GOLD, Rect2(60, 546, 660, 30), "left", true) Style.button(self, "Bauen", Rect2(60, 600, 300, 50), build, Style.PRIMARY) msg_label = Style.label(self, "", 15, Style.RED, Rect2(60, 666, 660, 48), "left") msg_label.autowrap_mode = TextServer.AUTOWRAP_WORD Style.panel(self, Rect2(760, 86, 480, 696)) preview_holder = Control.new() preview_holder.mouse_filter = Control.MOUSE_FILTER_IGNORE add_child(preview_holder) _suggest_name() refresh() func _slider(rect: Rect2, lo: int, hi: int, value: int) -> HSlider: var s := HSlider.new() s.position = rect.position s.size = rect.size s.min_value = lo s.max_value = hi s.step = 1 s.value = value s.value_changed.connect(func(_v: float): refresh()) add_child(s) return s func _input(event: InputEvent) -> void: if event.is_action_pressed("ui_cancel") and not name_box.has_focus(): app.show_screen(MenuScreen.new()) func _suggest_name() -> void: name_box.text = tr("Eigenbau %d") % (app.profile.customs.size() + 1) ## Ein Element an- oder abwählen. func toggle_element(e: String) -> void: if e in elements: elements.erase(e) else: elements.append(e) say("") refresh() func toggle_keyword(kw: String, on: bool) -> void: if on and not (kw in keywords): keywords.append(kw) elif not on: keywords.erase(kw) keywords = Cards.KEYWORDS.filter(func(k): return k in keywords) refresh() func say(m: String, ok: bool = false) -> void: msg_label.text = m msg_label.add_theme_color_override("font_color", Style.GREEN if ok else Style.RED) ## Die Karte, wie sie gebaut würde (für die Vorschau ohne Element neutral). func preview_card() -> Cards.Card: var els := elements if not elements.is_empty() else [Cards.NEUTRAL] return Cards.custom("c_vorschau", name_box.text.strip_edges(), els, int(attack_slider.value), int(health_slider.value), keywords) func build() -> void: var p: Profile = app.profile var err: String = p.build_card(name_box.text, elements, int(attack_slider.value), int(health_slider.value), keywords) if err != "": say(tr(err)) return app.save() app.sfx.play("combo") say(tr("Gebaut: %s") % name_box.text.strip_edges(), true) _suggest_name() refresh() func refresh() -> void: var p: Profile = app.profile dust_label.text = "Staub: %d" % p.dust attack_label.text = str(int(attack_slider.value)) health_label.text = str(int(health_slider.value)) for e in element_buttons: var active: bool = e in elements var base: Color = Style.darker(Cards.ELEMENT_COLORS[e], 0.8) element_buttons[e].add_theme_stylebox_override("normal", Style.box(Style.lighter(base) if active else base, 8, Style.GOLD if active else Style.MUTED, 2 if active else 1)) var c := preview_card() info_label.text = tr("Kosten %d Mana · Wert %d · Preis %d Staub") % [c.cost, c.value(), p.build_price(c)] Style.clear(preview_holder) var v := CardView.new(c, Vector2(240, 336), false, "Common") v.position = Vector2(880, 160) v.mouse_filter = Control.MOUSE_FILTER_IGNORE preview_holder.add_child(v) Style.label(preview_holder, c.text(), 15, Style.MUTED, Rect2(780, 520, 440, 30), "center")