Elemente, Kombos, Fallen, KI mit Vorausschau, Kampagne, Hotseat und Netzwerk, Werkstatt, Erfolge, Tagesaufgaben, Tests und Exporte. Co-Authored-By: Claude Fable 5.1 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_01QPgKvy5W9WRNFHjkm5QsHx
152 lines
5.5 KiB
GDScript
152 lines
5.5 KiB
GDScript
class_name WorkshopScreen
|
|
extends Control
|
|
## Werkstatt: Karten zerlegen (Staub) und herstellen.
|
|
|
|
var app
|
|
var filter := ""
|
|
var search := ""
|
|
var selected: Cards.Card = null
|
|
var grid: CardGrid
|
|
var search_box: LineEdit
|
|
var dust_label: Label
|
|
var msg_label: Label
|
|
var preview_holder: Control
|
|
var info_label: Label
|
|
var b_dismantle: Button
|
|
var b_craft: Button
|
|
var b_extras: Button
|
|
|
|
|
|
func _ready() -> void:
|
|
Style.label(self, "Werkstatt", 30, Style.GOLD, Rect2(20, 8, 400, 40), "left", true)
|
|
Style.label(self, "Karte anklicken, dann zerlegen oder herstellen. Überschuss: alles über %d Kopien." % Game.MAX_COPIES,
|
|
14, Style.MUTED, Rect2(240, 18, 600, 24))
|
|
Style.button(self, "Alle", Rect2(20, 55, 60, 34), set_filter.bind(""))
|
|
for i in Cards.ELEMENTS.size():
|
|
var e: String = Cards.ELEMENTS[i]
|
|
Style.button(self, e, Rect2(88 + i * 76, 55, 70, 34), set_filter.bind(e), Style.darker(Cards.ELEMENT_COLORS[e], 0.8))
|
|
search_box = LineEdit.new()
|
|
search_box.position = Vector2(400, 55)
|
|
search_box.size = Vector2(200, 34)
|
|
search_box.placeholder_text = "Suche"
|
|
search_box.text_changed.connect(func(t: String):
|
|
search = t
|
|
refresh())
|
|
add_child(search_box)
|
|
grid = CardGrid.new(Rect2(20, 100, CardGrid.COLS * (CardGrid.CW + CardGrid.GAP) + 10, 690))
|
|
grid.card_clicked.connect(select)
|
|
add_child(grid)
|
|
Style.panel(self, Rect2(845, 50, 420, 680))
|
|
dust_label = Style.label(self, "", 22, Style.BLUE, Rect2(860, 58, 390, 30), "left", true)
|
|
preview_holder = Control.new()
|
|
preview_holder.mouse_filter = Control.MOUSE_FILTER_IGNORE
|
|
add_child(preview_holder)
|
|
info_label = Style.label(self, "", 14, Style.MUTED, Rect2(860, 396, 390, 66), "center")
|
|
b_dismantle = Style.button(self, "", Rect2(860, 470, 390, 44), dismantle, Color("5a3c28"))
|
|
b_craft = Style.button(self, "", Rect2(860, 524, 390, 44), craft, Color("285a3c"))
|
|
b_extras = Style.button(self, "", Rect2(860, 600, 390, 44), dismantle_extras)
|
|
msg_label = Style.label(self, "", 15, Style.GREEN, Rect2(860, 660, 390, 48), "center")
|
|
Style.button(self, "Zurück", Rect2(1150, 740, 110, 44), func(): app.show_screen(MenuScreen.new()))
|
|
refresh()
|
|
|
|
|
|
func _input(event: InputEvent) -> void:
|
|
if event is InputEventKey and event.pressed and event.keycode == KEY_ESCAPE and not search_box.has_focus():
|
|
app.show_screen(MenuScreen.new())
|
|
|
|
|
|
func set_filter(e: String) -> void:
|
|
filter = e
|
|
refresh()
|
|
|
|
|
|
func cards() -> Array:
|
|
var out: Array = Cards.all().duplicate()
|
|
if filter != "":
|
|
out = out.filter(func(c): return filter in c.elements)
|
|
if search != "":
|
|
var q := search.to_lower()
|
|
out = out.filter(func(c): return q in c.name.to_lower() or q in c.text().to_lower() or q in c.combo().to_lower())
|
|
return out
|
|
|
|
|
|
func select(card: Cards.Card) -> void:
|
|
selected = card
|
|
msg_label.text = ""
|
|
refresh()
|
|
|
|
|
|
func say(m: String, ok: bool) -> void:
|
|
msg_label.text = m
|
|
msg_label.add_theme_color_override("font_color", Style.GREEN if ok else Style.RED)
|
|
|
|
|
|
func dismantle() -> void:
|
|
if selected == null:
|
|
return
|
|
var err: String = app.profile.dismantle(selected.id)
|
|
if err == "":
|
|
app.sfx.play("click")
|
|
app.save()
|
|
say("%s zerlegt (+%d Staub)" % [selected.name, Profile.DUST_DISMANTLE[selected.rarity]], true)
|
|
else:
|
|
say(err, false)
|
|
refresh()
|
|
|
|
|
|
func craft() -> void:
|
|
if selected == null:
|
|
return
|
|
var err: String = app.profile.craft(selected.id)
|
|
if err == "":
|
|
app.sfx.play("play")
|
|
app.save()
|
|
var notes: Array[String] = app.profile.take_notices()
|
|
say("%s hergestellt" % selected.name + (" · " + " · ".join(notes) if not notes.is_empty() else ""), true)
|
|
else:
|
|
say(err, false)
|
|
refresh()
|
|
|
|
|
|
func dismantle_extras() -> void:
|
|
var got: int = app.profile.dismantle_extras()
|
|
if got > 0:
|
|
app.save()
|
|
say("Überschuss zerlegt: +%d Staub" % got, true)
|
|
else:
|
|
say("Kein Überschuss vorhanden", false)
|
|
refresh()
|
|
|
|
|
|
func refresh() -> void:
|
|
var p: Profile = app.profile
|
|
dust_label.text = "Staub: %d" % p.dust
|
|
grid.fill(cards(),
|
|
func(c): return "%dx" % p.collection.get(c.id, 0) if p.collection.get(c.id, 0) > 0 else "fehlt",
|
|
func(c): return p.collection.get(c.id, 0) == 0)
|
|
Style.clear(preview_holder)
|
|
if selected == null:
|
|
info_label.text = "Keine Karte gewählt"
|
|
b_dismantle.text = "Zerlegen"
|
|
b_craft.text = "Herstellen"
|
|
b_dismantle.disabled = true
|
|
b_craft.disabled = true
|
|
else:
|
|
var v := CardView.new(selected, Vector2(200, 280))
|
|
v.position = Vector2(955, 100)
|
|
v.mouse_filter = Control.MOUSE_FILTER_IGNORE
|
|
preview_holder.add_child(v)
|
|
var owned: int = p.collection.get(selected.id, 0)
|
|
var st: Dictionary = p.card_stats.get(selected.id, {"played": 0, "games": 0, "wins": 0})
|
|
info_label.text = "%s · %s\nIm Besitz: %dx · Gespielt %dx · %d Partien, %d Siege" % [
|
|
selected.combo(), selected.rarity, owned, st.played, st.games, st.wins]
|
|
b_dismantle.text = "Zerlegen (+%d Staub)" % Profile.DUST_DISMANTLE[selected.rarity]
|
|
b_craft.text = "Herstellen (%d Staub)" % Profile.DUST_CRAFT[selected.rarity]
|
|
b_dismantle.disabled = owned == 0
|
|
b_craft.disabled = p.dust < Profile.DUST_CRAFT[selected.rarity]
|
|
var extras := 0
|
|
for cid in p.collection:
|
|
extras += maxi(0, p.collection[cid] - Game.MAX_COPIES)
|
|
b_extras.text = "Überschuss zerlegen (%d Karten)" % extras
|
|
b_extras.disabled = extras == 0
|