- KI-Bewertung mit Bedrohung und Führenden-Bremse (62:38 gegen die alte im Duell, gleichauf zu viert) - Balance: Sand +1/+1 statt Schild, Erde+Luft und Erde geschwächt, Wasser angehoben, Messlauf mit N=200 möglich - Einzelspieler-Kämpfe werden laufend gespeichert (voller Spielstand, viewer -1) und im Menü fortgesetzt - Karten, Deckzeilen und Kartenrücken fokussierbar: Gamepad in Deckbau, Werkstatt und Booster - Kartennamen (name_en) und Kartentexte übersetzbar, Übersetzungstest deckt cards.gd mit ab - Deck-Code DINGER1:id*anzahl mit Zwischenablage; acht neue Karten; Kampagne Kapitel 3; Elementbooster 120 Münzen - Netzwerk: Nachfolge-Host mit vollem Spielstand, Neuverbindung der anderen, Zuschauer (Sicht -2); Bot kann hosten - Große Schrift: Kartennamen, Kartentext, Knopfleisten, Gegnervorschau, Dialogtext - Anleitung 1 garantiert ein 1-Energie-Wesen; Tests: DINGER_ONLY für einzelne Oberflächentests - Oberflächentest auch auf Xephyr mit llvmpipe (wie Xvfb in der CI) grün Co-Authored-By: Claude Fable 5.1 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_01QPgKvy5W9WRNFHjkm5QsHx
108 lines
5.1 KiB
GDScript
108 lines
5.1 KiB
GDScript
class_name MenuScreen
|
|
extends Control
|
|
|
|
var app
|
|
var b_single: Button
|
|
var b_campaign: Button
|
|
var b_hotseat: Button
|
|
var b_online: Button
|
|
var b_tutorial: Button
|
|
var b_challenge: Button
|
|
var b_resume: Button
|
|
var coins_label: Label
|
|
var coll_label: Label
|
|
var deck_label: Label
|
|
var daily_label: Label
|
|
var warn_label: Label
|
|
var notice_label: Label
|
|
|
|
|
|
func _ready() -> void:
|
|
var col := Style.column(self, 640, 24, 5)
|
|
Style.clabel(col, "Dinger", 64, Style.GOLD, "center", true)
|
|
Style.clabel(col, "Ein Kartenspiel: jeder gegen jeden", 22, Style.MUTED)
|
|
Style.spacer(col, 8)
|
|
coins_label = Style.clabel(col, "", 20, Style.GOLD)
|
|
coll_label = Style.clabel(col, "", 16, Style.MUTED)
|
|
deck_label = Style.clabel(col, "", 16, Style.MUTED)
|
|
daily_label = Style.clabel(col, "", 16, Style.BLUE)
|
|
Style.spacer(col, 8)
|
|
var grid := GridContainer.new()
|
|
grid.columns = 2
|
|
grid.add_theme_constant_override("h_separation", 12)
|
|
grid.add_theme_constant_override("v_separation", 8)
|
|
var center := CenterContainer.new()
|
|
center.add_child(grid)
|
|
col.add_child(center)
|
|
var sz := Vector2(270, 44)
|
|
var p0: Profile = app.profile
|
|
var part2: bool = p0.tutorial_done and not p0.tutorial2_done
|
|
if FileAccess.file_exists(app.battle_save_path()):
|
|
b_resume = Style.cbutton(grid, "Kampf fortsetzen", sz, _resume, Color("5a4628"))
|
|
b_tutorial = Style.cbutton(grid, "Anleitung 2: Fallen" if part2 else "Anleitung", sz,
|
|
func(): app.show_screen(BattleScreen.guided(2 if part2 else 1)),
|
|
Color("5a4628") if not (p0.tutorial_done and p0.tutorial2_done) else null)
|
|
b_single = Style.cbutton(grid, "Einzelspieler", sz, func(): app.show_screen(OpponentSelectScreen.new()), Color("285a3c"))
|
|
b_campaign = Style.cbutton(grid, "Kampagne", sz, func(): app.show_screen(CampaignScreen.new()), Color("285a3c"))
|
|
b_hotseat = Style.cbutton(grid, "Lokal zu mehreren", sz, func(): app.show_screen(HotseatScreen.new()), Color("285a3c"))
|
|
b_online = Style.cbutton(grid, "Netzwerkspiel", sz, func(): app.show_screen(LobbyScreen.new()), Color("285a3c"))
|
|
b_challenge = Style.cbutton(grid, "Herausforderung", sz, func(): app.show_screen(ChallengeScreen.new()), Color("285a3c"))
|
|
Style.cbutton(grid, "Booster öffnen", sz, func(): app.show_screen(BoosterScreen.new()))
|
|
Style.cbutton(grid, "Deck bauen", sz, func(): app.show_screen(DeckScreen.new()))
|
|
Style.cbutton(grid, "Werkstatt", sz, func(): app.show_screen(WorkshopScreen.new()))
|
|
Style.cbutton(grid, "Erfolge", sz, func(): app.show_screen(AchievementsScreen.new()))
|
|
Style.cbutton(grid, "Regeln", sz, func(): app.show_screen(RulesScreen.new()))
|
|
Style.cbutton(grid, "Einstellungen", sz, func(): app.show_screen(SettingsScreen.new()))
|
|
Style.cbutton(grid, "Beenden", sz, func(): get_tree().quit())
|
|
Style.spacer(col, 10)
|
|
warn_label = Style.clabel(col, "", 16, Style.RED)
|
|
notice_label = Style.clabel(col, "", 16, Style.GREEN)
|
|
notice_label.autowrap_mode = TextServer.AUTOWRAP_WORD
|
|
refresh()
|
|
|
|
|
|
## Unterbrochenen Kampf laden; eine unlesbare Datei wird verworfen.
|
|
func _resume() -> void:
|
|
var json := JSON.new()
|
|
var text := FileAccess.get_file_as_string(app.battle_save_path())
|
|
if json.parse(text) != OK or not (json.data is Dictionary) or not json.data.has("game"):
|
|
app.clear_battle_save()
|
|
app.show_screen(MenuScreen.new())
|
|
return
|
|
app.show_screen(BattleScreen.resume(json.data))
|
|
|
|
|
|
func refresh() -> void:
|
|
var p: Profile = app.profile
|
|
var ok: Array = p.deck_valid()
|
|
b_single.disabled = not ok[0]
|
|
b_campaign.disabled = not ok[0]
|
|
b_tutorial.disabled = not ok[0]
|
|
b_online.disabled = not ok[0]
|
|
b_challenge.disabled = not ok[0]
|
|
b_challenge.text = tr("Herausforderung") + (" ✓" if p.challenge_week == Challenge.week() else "")
|
|
var total := 0
|
|
for cid in p.collection:
|
|
total += p.collection[cid]
|
|
coins_label.text = tr("Münzen: %d · Staub: %d") % [p.coins, p.dust]
|
|
coll_label.text = tr("Sammlung: %d von %d Karten (%d insgesamt) · Kampagne: %d/%d") % [
|
|
p.distinct_owned(), Cards.all().size(), total, p.campaign_stage, Campaign.total()]
|
|
var elems := Game.deck_elements(p.deck_cards())
|
|
deck_label.text = tr("Aktives Deck: %s (%s)") % [p.deck_name(), ", ".join(elems.map(func(e): return tr(e))) if not elems.is_empty() else tr("leer")]
|
|
var task := p.daily_task()
|
|
if p.daily.done:
|
|
daily_label.text = tr("Tagesaufgabe erledigt: %s ✓") % task.text
|
|
else:
|
|
daily_label.text = tr("Tagesaufgabe: %s (%d/%d) · +%d Münzen") % [task.text, p.daily.progress, task.goal, task.reward]
|
|
warn_label.text = "" if ok[0] else tr("Aktives Deck nicht spielbar: ") + tr(ok[1])
|
|
if ok[0] and not p.tutorial_done:
|
|
warn_label.text = "Neu hier? Die Anleitung erklärt Energie, Angriffe, Resonanz und Feldkombos."
|
|
warn_label.add_theme_color_override("font_color", Style.GOLD)
|
|
elif ok[0] and not p.tutorial2_done:
|
|
warn_label.text = "Anleitung 2 zeigt Mulligan, Fallen und die Feldkombo Dampf."
|
|
warn_label.add_theme_color_override("font_color", Style.GOLD)
|
|
var notes := p.take_notices()
|
|
notice_label.text = " · ".join(notes)
|
|
if not notes.is_empty():
|
|
app.save()
|