|
|
|
|
@@ -83,11 +83,6 @@ func pad(button: int) -> void:
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
## Mulligan-Maske wegklicken (Hand behalten), falls sie offen ist.
|
|
|
|
|
func clear_mulligan(scr) -> void:
|
|
|
|
|
if scr.mulligan_box.visible:
|
|
|
|
|
await click(scr.b_keep)
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
func hover(node: Control) -> void:
|
|
|
|
|
var ev := InputEventMouseMotion.new()
|
|
|
|
|
ev.position = node.get_global_rect().get_center()
|
|
|
|
|
@@ -123,15 +118,6 @@ func find_button(text: String, root: Node = null) -> Button:
|
|
|
|
|
return null
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
func card_views(root: Node) -> Array:
|
|
|
|
|
var out := []
|
|
|
|
|
for c in root.get_children():
|
|
|
|
|
if c is CardView:
|
|
|
|
|
out.append(c)
|
|
|
|
|
out.append_array(card_views(c))
|
|
|
|
|
return out
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
## Wartet, bis keine Kachel mehr animiert wird (Angriffe verschieben Kacheln kurz).
|
|
|
|
|
func settle(scr) -> void:
|
|
|
|
|
for i in 40:
|
|
|
|
|
@@ -147,7 +133,6 @@ func wait_for_human(scr) -> void:
|
|
|
|
|
await frames(1)
|
|
|
|
|
wait += 1
|
|
|
|
|
await frames(1)
|
|
|
|
|
await clear_mulligan(scr)
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
func _ready() -> void:
|
|
|
|
|
@@ -164,9 +149,9 @@ func _ready() -> void:
|
|
|
|
|
add_child(main)
|
|
|
|
|
await frames(3)
|
|
|
|
|
var fast := OS.get_environment("DINGER_FAST") != ""
|
|
|
|
|
var suite := [test_menu, test_gamepad_menue, test_booster, test_deckbau, test_gegnerauswahl, test_einstellungen,
|
|
|
|
|
test_kampagne, test_sammlung, test_sprache, test_kampf_steuerung,
|
|
|
|
|
test_kampf_fortsetzen, test_gamepad_deckbau, test_deckcode, test_elementbooster]
|
|
|
|
|
var suite := [test_menu, test_gamepad_menue, test_booster, test_gegnerauswahl, test_einstellungen,
|
|
|
|
|
test_kampagne, test_sammlung, test_sprache, test_kampf_steuerung, test_kampf_feld_und_verschmelzen, test_kampf_grenzen,
|
|
|
|
|
test_kampf_fortsetzen]
|
|
|
|
|
if not fast:
|
|
|
|
|
suite += [test_kampf.bind(2, 3), test_kampf_abbrechen]
|
|
|
|
|
# Die Netzwerktests starten Bot-Prozesse und warten auf Verbindungen; das dauert Minuten.
|
|
|
|
|
@@ -209,108 +194,16 @@ func test_booster() -> void:
|
|
|
|
|
check(scr.revealed.size() == 5, "alle aufgedeckt")
|
|
|
|
|
await shot("04_booster_offen")
|
|
|
|
|
check(Profile.load_or_new(SAVE).coins == main.profile.coins, "Kauf gespeichert")
|
|
|
|
|
var ids: Array = scr.cards.map(func(c): return c.id)
|
|
|
|
|
var better: Array = main.profile.deck_suggestions(ids)
|
|
|
|
|
check(scr.b_improve.visible == (not better.is_empty()), "Deck-Vorschlag nur bei passender Karte")
|
|
|
|
|
if scr.b_improve.visible:
|
|
|
|
|
var deck_before: Array = main.profile.deck.duplicate()
|
|
|
|
|
await click(scr.b_improve)
|
|
|
|
|
check(main.profile.deck != deck_before and main.profile.deck_valid()[0] and "im Deck" in scr.msg_label.text, "Karte ins Deck übernommen")
|
|
|
|
|
for res in scr.cards:
|
|
|
|
|
if res.upgraded:
|
|
|
|
|
check(main.profile.level(res.card.id) == Cards.RARITIES.find(res.rarity), "aufgewertete Karte trägt ihre Stufe")
|
|
|
|
|
else:
|
|
|
|
|
check(res.dust > 0, "sonst gibt es Staub")
|
|
|
|
|
check(scr.b_buy.disabled == (main.profile.coins < Profile.BOOSTER_COST), "Kaufknopf folgt dem Münzstand")
|
|
|
|
|
await click(find_button("Zurück"))
|
|
|
|
|
check(screen() is MenuScreen, "zurück im Menü")
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
func test_deckbau() -> void:
|
|
|
|
|
await click(find_button("Deck bauen"))
|
|
|
|
|
var scr = screen()
|
|
|
|
|
check(scr is DeckScreen, "Deckbildschirm")
|
|
|
|
|
check(scr.deck.size() == 20, "Deck geladen")
|
|
|
|
|
check("Stärke" in scr.elems_label.text, "Deckstärke im Deckbau")
|
|
|
|
|
await shot("05_deck")
|
|
|
|
|
await click(find_button("Leeren"))
|
|
|
|
|
check(scr.deck.is_empty(), "geleert")
|
|
|
|
|
var first_id: String = card_views(scr.grid)[0].card.id
|
|
|
|
|
var allowed: int = mini(main.profile.collection[first_id], Game.MAX_COPIES)
|
|
|
|
|
await click(card_views(scr.grid)[0])
|
|
|
|
|
check(scr.deck == [first_id], "Karte hinzugefügt")
|
|
|
|
|
for i in allowed:
|
|
|
|
|
await click(card_views(scr.grid)[0])
|
|
|
|
|
check(scr.deck.count(first_id) == allowed and "Kopien" in scr.msg_label.text, "nur besessene Kopien (%d)" % allowed)
|
|
|
|
|
await click(find_button("Speichern"))
|
|
|
|
|
check(main.profile.deck.size() == 20 and scr.msg_label.text != "Deck gespeichert", "zu kleines Deck nicht gespeichert")
|
|
|
|
|
await click(find_button("Wasser"))
|
|
|
|
|
await click(card_views(scr.grid)[0])
|
|
|
|
|
await click(find_button("Erde"))
|
|
|
|
|
await click(card_views(scr.grid)[0])
|
|
|
|
|
check("Elemente" in scr.msg_label.text, "drittes Element abgelehnt")
|
|
|
|
|
await click(find_button("Alle"))
|
|
|
|
|
# Suche, Sortierung, fehlende Karten
|
|
|
|
|
var all_count := card_views(scr.grid).size()
|
|
|
|
|
scr.search_box.text = "Wächter"
|
|
|
|
|
scr.search_box.text_changed.emit("Wächter")
|
|
|
|
|
await frames(1)
|
|
|
|
|
var found := card_views(scr.grid)
|
|
|
|
|
check(found.size() > 0 and found.size() < all_count, "Suche filtert")
|
|
|
|
|
check(found.all(func(v): return "Wächter" in v.card.text() or "Wächter" in v.card.name), "Suche trifft Kartentext")
|
|
|
|
|
scr.search_box.text = ""
|
|
|
|
|
scr.search_box.text_changed.emit("")
|
|
|
|
|
scr.sort_box.select(1)
|
|
|
|
|
scr.sort_box.item_selected.emit(1)
|
|
|
|
|
await frames(1)
|
|
|
|
|
var names: Array = card_views(scr.grid).map(func(v): return v.card.name)
|
|
|
|
|
var sorted_names := names.duplicate()
|
|
|
|
|
sorted_names.sort()
|
|
|
|
|
check(names == sorted_names, "Sortierung nach Name")
|
|
|
|
|
scr.missing_box.button_pressed = true
|
|
|
|
|
await frames(1)
|
|
|
|
|
check(card_views(scr.grid).size() == Cards.all().size(), "Fehlende Karten eingeblendet")
|
|
|
|
|
var missing = card_views(scr.grid).filter(func(v): return main.profile.collection.get(v.card.id, 0) == 0)
|
|
|
|
|
check(not missing.is_empty(), "es gibt fehlende Karten")
|
|
|
|
|
await click(missing[0])
|
|
|
|
|
check("fehlt" in scr.msg_label.text, "fehlende Karte nicht ins Deck")
|
|
|
|
|
scr.missing_box.button_pressed = false
|
|
|
|
|
scr.sort_box.select(0)
|
|
|
|
|
scr.sort_box.item_selected.emit(0)
|
|
|
|
|
await frames(1)
|
|
|
|
|
var n: int = scr.deck.size()
|
|
|
|
|
await click(scr.deck_list.get_children()[0])
|
|
|
|
|
check(scr.deck.size() == n - 1, "Zeile entfernt Karte")
|
|
|
|
|
await hover(card_views(scr.grid)[0])
|
|
|
|
|
check(scr.preview.visible, "Vorschau bei Hover")
|
|
|
|
|
await shot("06_deck_bearbeitet")
|
|
|
|
|
# Slots: Deck 2 aus Deck 1 kopieren, speichern, aktiv setzen
|
|
|
|
|
await click(scr.slot_buttons[1])
|
|
|
|
|
if scr.slot != 1 or not scr.deck.is_empty():
|
|
|
|
|
print("DEBUG Slot: slot=", scr.slot, " deck=", scr.deck.size(), " rect=", scr.slot_buttons[1].get_global_rect(),
|
|
|
|
|
" hovered=", get_viewport().gui_get_hovered_control(), " decks1=", main.profile.decks[1].cards.size())
|
|
|
|
|
check(scr.slot == 1 and scr.deck.is_empty(), "Slot 2 leer")
|
|
|
|
|
scr.deck = main.profile.decks[0].cards.duplicate()
|
|
|
|
|
scr.refresh()
|
|
|
|
|
await click(find_button("Speichern"))
|
|
|
|
|
check(main.profile.decks[1].cards.size() == 20 and "gespeichert" in scr.msg_label.text, "Slot 2 gespeichert")
|
|
|
|
|
await click(find_button("Aktiv setzen"))
|
|
|
|
|
check(main.profile.active_deck == 1 and main.profile.deck_name() == "Deck 2", "Slot 2 aktiv")
|
|
|
|
|
check(Profile.load_or_new(SAVE).active_deck == 1, "aktiver Slot gespeichert")
|
|
|
|
|
scr.name_box.text = "Testdeck"
|
|
|
|
|
scr.name_box.text_submitted.emit("Testdeck")
|
|
|
|
|
check(main.profile.deck_name(1) == "Testdeck" and Profile.load_or_new(SAVE).deck_name(1) == "Testdeck", "Deck umbenannt")
|
|
|
|
|
await click(scr.slot_buttons[2])
|
|
|
|
|
check(scr.slot == 2 and scr.deck.is_empty(), "Slot 3 leer")
|
|
|
|
|
await click(find_button("Auto-Ausfüllen"))
|
|
|
|
|
check(scr.deck.size() == 20 and main.profile.deck_valid(2)[0], "Slot 3 automatisch gefüllt und spielbar")
|
|
|
|
|
await shot("25_deck_slots")
|
|
|
|
|
await click(scr.deck_list.get_children()[0]) # ungespeicherte Änderung: eine Karte entfernt
|
|
|
|
|
check(scr.dirty(), "Deck geändert")
|
|
|
|
|
await click(find_button("Zurück"))
|
|
|
|
|
check(scr.confirm.visible and screen() == scr, "Warnung bei ungespeicherten Änderungen")
|
|
|
|
|
await click(find_button("Weiter bearbeiten"))
|
|
|
|
|
check(not scr.confirm.visible, "weiter bearbeiten")
|
|
|
|
|
await click(find_button("Zurück"))
|
|
|
|
|
await click(find_button("Verwerfen"))
|
|
|
|
|
check(screen() is MenuScreen and main.profile.deck.size() == 20, "Änderungen verworfen")
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
func target_view(scr, valid: Array) -> Control:
|
|
|
|
|
for v in scr.enemy_views:
|
|
|
|
|
if v.creature in valid:
|
|
|
|
|
@@ -326,17 +219,26 @@ func target_view(scr, valid: Array) -> Control:
|
|
|
|
|
|
|
|
|
|
func human_turn(scr) -> void:
|
|
|
|
|
var g: Game = scr.game
|
|
|
|
|
await clear_mulligan(scr)
|
|
|
|
|
# erst kaufen, solange Mana und Handplatz reichen
|
|
|
|
|
for i in 12:
|
|
|
|
|
var offers: Array = scr.shop_views.filter(func(v): return g.human.energy >= v.card.cost and g.human.hand.size() < Game.MAX_HAND)
|
|
|
|
|
if offers.is_empty():
|
|
|
|
|
break
|
|
|
|
|
var offer: Cards.Card = offers[0].card
|
|
|
|
|
var mana: int = g.human.energy
|
|
|
|
|
await click(offers[0])
|
|
|
|
|
check(g.human.energy == mana - offer.cost, "gekauft: " + offer.name)
|
|
|
|
|
# dann ausspielen, das kostet nichts
|
|
|
|
|
for i in 12:
|
|
|
|
|
var playable: Array = scr.hand_views.filter(func(v): return g.can_play(g.human, v.card)[0])
|
|
|
|
|
if playable.is_empty():
|
|
|
|
|
break
|
|
|
|
|
var card: Cards.Card = playable[0].card
|
|
|
|
|
var energy: int = g.human.energy
|
|
|
|
|
var board_before: int = g.human.board.size()
|
|
|
|
|
await click(playable[0])
|
|
|
|
|
if scr.pending != null:
|
|
|
|
|
await click(target_view(scr, g.valid_targets(g.human, card.target_type())))
|
|
|
|
|
check(g.human.energy == energy - card.cost, "Karte gespielt: " + card.name)
|
|
|
|
|
check(g.human.board.size() > board_before, "Karte gespielt: " + card.name)
|
|
|
|
|
for i in 12:
|
|
|
|
|
var ready: Array = scr.own_views.filter(func(v): return v.creature.can_attack())
|
|
|
|
|
if ready.is_empty() or g.winner != "":
|
|
|
|
|
@@ -377,9 +279,8 @@ func test_gegnerauswahl() -> void:
|
|
|
|
|
await click(find_button("Einzelspieler"))
|
|
|
|
|
var sel = screen()
|
|
|
|
|
check(sel is OpponentSelectScreen, "Gegnerauswahl geöffnet")
|
|
|
|
|
check("Deckstärke" in sel.rating_label.text and "Gegnerdecks" in sel.rating_label.text
|
|
|
|
|
and not ("Archetypen" in sel.rating_label.text or "KI" in sel.rating_label.text), "unter der Schwierigkeit nur die zwei Stärken")
|
|
|
|
|
check(find_button("Neu würfeln") == null and find_button("1 Gegner") == null and find_button("Starten") != null, "kein Würfeln und keine Gegnerknöpfe, nur Starten")
|
|
|
|
|
check(find_button("Feuer") == null and find_button("Luft") == null, "keine Elementwahl mehr")
|
|
|
|
|
check(sel.count_slider.min_value == 1 and sel.count_slider.max_value == Game.MAX_OPPONENTS and sel.count_slider.step == 1, "Gegnerzahl als Schieberegler von 1 bis %d" % Game.MAX_OPPONENTS)
|
|
|
|
|
check(sel.opponents() == 1 and sel.count_label.text == "1 Gegner" and "Duell" in sel.info_label.text, "Regler beginnt beim Duell")
|
|
|
|
|
var rect: Rect2 = sel.count_slider.get_global_rect()
|
|
|
|
|
@@ -400,17 +301,17 @@ func test_gegnerauswahl() -> void:
|
|
|
|
|
await click(find_button("Starten"))
|
|
|
|
|
var hard = screen()
|
|
|
|
|
check(hard is BattleScreen and hard.game.opponents.size() == 1, "Kampf mit einem Gegner gestartet")
|
|
|
|
|
var own := Game.deck_rating(main.profile.deck_cards())
|
|
|
|
|
var opp: Game.Player = hard.game.opponents[0]
|
|
|
|
|
var opp_rating := Game.deck_rating(opp.deck + opp.hand)
|
|
|
|
|
check(opp_rating >= own * 1.05 - 0.05 and hard.smart_ai, "Schwer: Gegnerdeck stärker (%.2f zu %.2f), Vorausschau-KI" % [opp_rating, own])
|
|
|
|
|
check(opp.max_life == Profile.DIFFICULTIES.schwer.life and hard.smart_ai, "Schwer: Gegner mit %d Leben, Vorausschau-KI" % Profile.DIFFICULTIES.schwer.life)
|
|
|
|
|
check(hard.game.human.shop.size() == Game.SHOP_SIZE and hard.game.human.hand.is_empty(),
|
|
|
|
|
"Start mit vollem Laden und leerer Hand")
|
|
|
|
|
await give_up()
|
|
|
|
|
await click(find_button("Einzelspieler"))
|
|
|
|
|
await click(find_button("Leicht"))
|
|
|
|
|
await click(find_button("Starten"))
|
|
|
|
|
var easy = screen()
|
|
|
|
|
opp = easy.game.opponents[0]
|
|
|
|
|
check(Game.deck_rating(opp.deck + opp.hand) <= own * 1.0 + 0.15 and not easy.smart_ai, "Leicht: schwächeres Deck, einfache KI")
|
|
|
|
|
check(opp.max_life == Profile.DIFFICULTIES.leicht.life and not easy.smart_ai, "Leicht: Gegner mit %d Leben, einfache KI" % Profile.DIFFICULTIES.leicht.life)
|
|
|
|
|
await give_up()
|
|
|
|
|
await click(find_button("Einzelspieler"))
|
|
|
|
|
await click(find_button("Normal"))
|
|
|
|
|
@@ -438,7 +339,6 @@ func leave_battle() -> void:
|
|
|
|
|
|
|
|
|
|
func give_up() -> void:
|
|
|
|
|
var scr = screen()
|
|
|
|
|
await clear_mulligan(scr)
|
|
|
|
|
await click(find_button("Aufgeben"))
|
|
|
|
|
check(scr.confirm.visible, "Aufgeben fragt nach")
|
|
|
|
|
await click(find_button("Weiterspielen"))
|
|
|
|
|
@@ -448,71 +348,6 @@ func give_up() -> void:
|
|
|
|
|
check(screen() is MenuScreen, "Aufgeben führt ins Menü")
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
## Gamepad im Deckbau: Karten und Deckzeilen sind fokussierbar, A wirkt wie ein Klick, B geht zurück.
|
|
|
|
|
func test_gamepad_deckbau() -> void:
|
|
|
|
|
await click(find_button("Deck bauen"))
|
|
|
|
|
var scr = screen()
|
|
|
|
|
var before: int = scr.deck.size()
|
|
|
|
|
await pad(JOY_BUTTON_DPAD_DOWN)
|
|
|
|
|
check(get_viewport().gui_get_focus_owner() != null and main.pad_mode, "Gamepad setzt Fokus im Deckbau")
|
|
|
|
|
var row: Control = scr.deck_list.get_child(0)
|
|
|
|
|
row.grab_focus()
|
|
|
|
|
await frames(1)
|
|
|
|
|
check(row.has_focus() and scr.preview.visible, "Deckzeile fokussierbar, Vorschau folgt")
|
|
|
|
|
await pad(JOY_BUTTON_A)
|
|
|
|
|
check(scr.deck.size() == before - 1, "A entfernt die fokussierte Karte aus dem Deck")
|
|
|
|
|
var elems: Array = Game.deck_elements(scr.deck_cards())
|
|
|
|
|
var target: CardView = null
|
|
|
|
|
for v in scr.grid.views():
|
|
|
|
|
if not v.dim and v.card.elements.all(func(e): return e in elems):
|
|
|
|
|
target = v
|
|
|
|
|
break
|
|
|
|
|
target.grab_focus()
|
|
|
|
|
await frames(1)
|
|
|
|
|
check(target.has_focus() and scr.preview.visible and scr.preview.card == target.card, "Karte im Raster fokussierbar mit Vorschau")
|
|
|
|
|
var target_id: String = target.card.id
|
|
|
|
|
await pad(JOY_BUTTON_A) # das Raster wird danach neu aufgebaut, target ist dann freigegeben
|
|
|
|
|
check(scr.deck.size() == before and target_id in scr.deck, "A nimmt die fokussierte Karte ins Deck (%d Karten, Meldung '%s')" % [scr.deck.size(), scr.msg_label.text])
|
|
|
|
|
await shot("31_gamepad_deckbau")
|
|
|
|
|
await pad(JOY_BUTTON_B)
|
|
|
|
|
check(scr.confirm.visible, "B fragt bei ungespeicherten Änderungen nach")
|
|
|
|
|
await click(find_button("Verwerfen"))
|
|
|
|
|
check(screen() is MenuScreen, "Verwerfen führt ins Menü")
|
|
|
|
|
await hover(main)
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
## Deck-Code kopieren, einfügen und übernehmen.
|
|
|
|
|
func test_deckcode() -> void:
|
|
|
|
|
await click(find_button("Deck bauen"))
|
|
|
|
|
var scr = screen()
|
|
|
|
|
await click(find_button("Code"))
|
|
|
|
|
check(scr.code_dialog.visible and scr.code_box.text.begins_with(Profile.CODE_PREFIX), "Code-Dialog zeigt den Deck-Code")
|
|
|
|
|
await click(find_button("In Zwischenablage"))
|
|
|
|
|
check(DisplayServer.clipboard_get() == scr.code_box.text, "Code in der Zwischenablage")
|
|
|
|
|
await shot("32_deckcode")
|
|
|
|
|
scr.code_box.text = "DINGER1:f_funke*2,e_wall*1,x_nix*1"
|
|
|
|
|
await click(find_button("Übernehmen"))
|
|
|
|
|
check(scr.deck.size() == Game.DECK_SIZE and "Ungültiger Code" in scr.msg_label.text, "ungültiger Code wird abgelehnt")
|
|
|
|
|
scr.code_box.text = "DINGER1:f_funke*2,e_wall*1,fff_sonne*1"
|
|
|
|
|
await click(find_button("Übernehmen"))
|
|
|
|
|
check(scr.deck == ["f_funke", "f_funke", "e_wall"] and "Kern der Sonne" in scr.msg_label.text and not scr.code_dialog.visible, "Code übernommen, fehlende Karte gemeldet")
|
|
|
|
|
await click(find_button("Zurück"))
|
|
|
|
|
await click(find_button("Verwerfen"))
|
|
|
|
|
check(screen() is MenuScreen, "Deckbau verlassen")
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
## Elementbooster liefert nur Karten des Elements.
|
|
|
|
|
func test_elementbooster() -> void:
|
|
|
|
|
main.profile.coins = 300
|
|
|
|
|
await click(find_button("Booster öffnen"))
|
|
|
|
|
var scr = screen()
|
|
|
|
|
await click(find_button("Feuer"))
|
|
|
|
|
check(scr.cards.size() == 5 and scr.cards.all(func(c): return "Feuer" in c.elements) and main.profile.coins == 300 - Profile.ELEMENT_BOOSTER_COST, "Feuer-Booster: fünf Feuerkarten")
|
|
|
|
|
await click(find_button("Alle aufdecken"))
|
|
|
|
|
await shot("33_elementbooster")
|
|
|
|
|
await click(find_button("Zurück"))
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
## Kampf speichern, im Menü fortsetzen, Aufgeben löscht die Datei.
|
|
|
|
|
func test_kampf_fortsetzen() -> void:
|
|
|
|
|
await start_battle(1)
|
|
|
|
|
@@ -569,28 +404,20 @@ func test_sammlung() -> void:
|
|
|
|
|
var scr = screen()
|
|
|
|
|
check(scr is CollectionScreen, "Sammlung geöffnet")
|
|
|
|
|
var p: Profile = main.profile
|
|
|
|
|
p.dust = 0
|
|
|
|
|
var in_decks := {}
|
|
|
|
|
for d in p.decks:
|
|
|
|
|
for cid in d.cards:
|
|
|
|
|
in_decks[cid] = true
|
|
|
|
|
var free = scr.grid.views().filter(func(v): return p.collection.get(v.card.id, 0) > 0 and not in_decks.has(v.card.id))
|
|
|
|
|
check(not free.is_empty(), "eine freie Karte zum Zerlegen")
|
|
|
|
|
var card: Cards.Card = free[0].card
|
|
|
|
|
await click(free[0])
|
|
|
|
|
check(scr.selected == card, "Karte gewählt")
|
|
|
|
|
var before: int = p.collection[card.id]
|
|
|
|
|
await click(scr.b_dismantle)
|
|
|
|
|
check(p.collection[card.id] == before - 1 and p.dust == Profile.DUST_DISMANTLE[card.rarity], "zerlegt, Staub gutgeschrieben")
|
|
|
|
|
check(scr.grid.views().size() == Cards.all().size(), "alle Karten gehören dir")
|
|
|
|
|
p.dust = 5000
|
|
|
|
|
scr.search_box.text = "Phönix"
|
|
|
|
|
scr.search_box.text_changed.emit("Phönix")
|
|
|
|
|
await frames(1)
|
|
|
|
|
var phoenix = scr.grid.views().filter(func(v): return v.card.id == "ff_phoenix")[0]
|
|
|
|
|
await click(phoenix)
|
|
|
|
|
await click(scr.b_craft)
|
|
|
|
|
check(p.collection.get("ff_phoenix", 0) == 1 and p.dust == 5000 - Profile.DUST_CRAFT["legendär"], "Phönix hergestellt")
|
|
|
|
|
check(Profile.load_or_new(SAVE).collection.get("ff_phoenix", 0) == 1, "Sammlung gespeichert")
|
|
|
|
|
check(scr.selected.id == "ff_phoenix" and p.rarity("ff_phoenix") == "gewöhnlich", "Karte gewählt, noch gewöhnlich")
|
|
|
|
|
await click(scr.b_upgrade)
|
|
|
|
|
check(p.level("ff_phoenix") == 1 and p.dust == 5000 - Profile.DUST_UPGRADE["selten"], "auf selten aufgewertet")
|
|
|
|
|
check(Profile.load_or_new(SAVE).level("ff_phoenix") == 1, "Sammlung gespeichert")
|
|
|
|
|
var dust: int = p.dust
|
|
|
|
|
await click(scr.b_dismantle)
|
|
|
|
|
check(p.level("ff_phoenix") == 0 and p.dust == dust + Profile.DUST_DISMANTLE["selten"], "wieder zerlegt")
|
|
|
|
|
await shot("20_sammlung")
|
|
|
|
|
await click(find_button("Zurück"))
|
|
|
|
|
check(screen() is MenuScreen, "zurück im Menü")
|
|
|
|
|
@@ -634,7 +461,7 @@ func test_profil_zuruecksetzen() -> void:
|
|
|
|
|
check(not scr.confirm.visible, "abgebrochen")
|
|
|
|
|
await click(find_button("Profil zurücksetzen"))
|
|
|
|
|
await click(find_button("Ja, zurücksetzen"))
|
|
|
|
|
check(screen() is MenuScreen and main.profile.coins == Profile.START_COINS and main.profile.collection.size() > 0, "Profil zurückgesetzt")
|
|
|
|
|
check(screen() is MenuScreen and main.profile.coins == Profile.START_COINS and main.profile.collection.is_empty(), "Profil zurückgesetzt")
|
|
|
|
|
check(Profile.load_or_new(SAVE).coins == Profile.START_COINS, "zurückgesetzt gespeichert")
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
@@ -646,7 +473,7 @@ func test_sprache() -> void:
|
|
|
|
|
await frames(2)
|
|
|
|
|
check(TranslationServer.get_locale().begins_with("en") and main.profile.settings.language == "en", "Sprache auf Englisch")
|
|
|
|
|
check(TranslationServer.translate("Zurück") == "Back" and TranslationServer.translate("Einzelspieler") == "Single player", "Übersetzung geladen")
|
|
|
|
|
check(TranslationServer.translate("Zug %d · Du bist dran") == "Turn %d · Your turn" and TranslationServer.translate("Nicht genug Energie") == "Not enough energy", "dynamische Texte übersetzt")
|
|
|
|
|
check(TranslationServer.translate("Zug %d · Du bist dran") == "Turn %d · Your turn" and TranslationServer.translate("Nicht genug Mana") == "Not enough mana", "dynamische Texte übersetzt")
|
|
|
|
|
check(find_button("Back") != null, "Knöpfe übersetzt")
|
|
|
|
|
await shot("26_englisch")
|
|
|
|
|
await click(find_button("Back"))
|
|
|
|
|
@@ -670,41 +497,39 @@ func test_kampf_steuerung() -> void:
|
|
|
|
|
scr.ai_delay = 0.0
|
|
|
|
|
await wait_for_human(scr)
|
|
|
|
|
var g: Game = scr.game
|
|
|
|
|
var idx := -1
|
|
|
|
|
for i in g.human.hand.size():
|
|
|
|
|
if g.human.hand[i].is_creature() and g.can_play(g.human, g.human.hand[i])[0]:
|
|
|
|
|
idx = i
|
|
|
|
|
break
|
|
|
|
|
check(idx >= 0, "spielbares Wesen auf der Hand")
|
|
|
|
|
if idx >= 0:
|
|
|
|
|
var played_id: String = g.human.hand[idx].id
|
|
|
|
|
var board_before: int = g.human.board.size()
|
|
|
|
|
await key(KEY_1 + idx)
|
|
|
|
|
check(g.human.board.size() == board_before + 1, "Wesen per Taste gespielt")
|
|
|
|
|
# Rückgängig: Wesen zurück auf die Hand
|
|
|
|
|
check(scr.b_undo.visible, "Rückgängig angeboten")
|
|
|
|
|
var energy: int = g.human.energy
|
|
|
|
|
await click(scr.b_undo)
|
|
|
|
|
g = scr.game
|
|
|
|
|
check(g.human.board.size() == board_before and g.human.hand.any(func(c): return c.id == played_id) and g.human.energy > energy, "Rückgängig stellt Hand und Energie her")
|
|
|
|
|
check(not scr.b_undo.visible and g.log.back() == "Rückgängig.", "Rückgängig verbraucht")
|
|
|
|
|
await key(KEY_1 + idx)
|
|
|
|
|
check(g.human.board.size() == board_before + 1, "erneut gespielt")
|
|
|
|
|
g.human.energy = 20 # das Angebot ist zufällig, hier soll nur die Steuerung geprüft werden
|
|
|
|
|
scr.refresh()
|
|
|
|
|
check(scr.shop_views.size() == Game.SHOP_SIZE and g.human.hand.is_empty(), "voller Laden, leere Hand")
|
|
|
|
|
# Kaufen: Mana weg, Karte auf der Hand
|
|
|
|
|
var offer: Cards.Card = scr.shop_views[0].card
|
|
|
|
|
var mana: int = g.human.energy
|
|
|
|
|
await click(scr.shop_views[0])
|
|
|
|
|
check(g.human.hand.size() == 1 and g.human.hand[0] == offer and g.human.energy == mana - offer.cost, "Angebot gekauft")
|
|
|
|
|
# Ausspielen kostet nichts
|
|
|
|
|
var board_before: int = g.human.board.size()
|
|
|
|
|
mana = g.human.energy
|
|
|
|
|
await key(KEY_1)
|
|
|
|
|
check(g.human.board.size() == board_before + 1 and g.human.energy == mana, "Wesen per Taste gespielt, ohne Mana")
|
|
|
|
|
# Rückgängig: Wesen zurück auf die Hand
|
|
|
|
|
check(scr.b_undo.visible, "Rückgängig angeboten")
|
|
|
|
|
await click(scr.b_undo)
|
|
|
|
|
g = scr.game
|
|
|
|
|
check(g.human.board.size() == board_before and g.human.hand.any(func(c): return c.id == offer.id), "Rückgängig stellt die Hand her")
|
|
|
|
|
check(not scr.b_undo.visible and g.log.back() == "Rückgängig.", "Rückgängig verbraucht")
|
|
|
|
|
await key(KEY_1)
|
|
|
|
|
check(g.human.board.size() == board_before + 1, "erneut gespielt")
|
|
|
|
|
# Neu würfeln kostet Mana
|
|
|
|
|
var shop_before: Array = g.human.shop.duplicate()
|
|
|
|
|
mana = g.human.energy
|
|
|
|
|
await click(scr.b_reroll)
|
|
|
|
|
check(g.human.energy == mana - Game.REROLL_COST and g.human.shop != shop_before, "Laden neu gewürfelt")
|
|
|
|
|
await shot("22_kampf_steuerung")
|
|
|
|
|
# Gamepad: Zeiger bewegen, Karte spielen
|
|
|
|
|
# Gamepad: Zeiger im Laden bewegen, A kauft
|
|
|
|
|
await pad(JOY_BUTTON_DPAD_RIGHT)
|
|
|
|
|
check(scr.gp_zone == "hand" and scr.gp_index == 1 and scr.cursor_layer.get_child_count() == 1, "Gamepad-Zeiger auf zweiter Handkarte")
|
|
|
|
|
var pad_idx := -1
|
|
|
|
|
for i in g.human.hand.size():
|
|
|
|
|
if g.human.hand[i].is_creature() and g.can_play(g.human, g.human.hand[i])[0]:
|
|
|
|
|
pad_idx = i
|
|
|
|
|
break
|
|
|
|
|
if pad_idx >= 0:
|
|
|
|
|
while scr.gp_index != pad_idx:
|
|
|
|
|
await pad(JOY_BUTTON_DPAD_RIGHT)
|
|
|
|
|
var board_before2: int = g.human.board.size()
|
|
|
|
|
await pad(JOY_BUTTON_A)
|
|
|
|
|
check(g.human.board.size() == board_before2 + 1, "Gamepad A spielt das Wesen")
|
|
|
|
|
check(scr.gp_zone == "shop" and scr.gp_index == 1 and scr.cursor_layer.get_child_count() == 1, "Gamepad-Zeiger auf zweitem Angebot")
|
|
|
|
|
var hand_before: int = g.human.hand.size()
|
|
|
|
|
await pad(JOY_BUTTON_A)
|
|
|
|
|
check(g.human.hand.size() == hand_before + 1, "Gamepad A kauft das Angebot")
|
|
|
|
|
scr.ai_delay = 0.75
|
|
|
|
|
await key(KEY_SPACE)
|
|
|
|
|
check(g.current() != g.human or g.turn >= 2, "Zug per Leertaste beendet")
|
|
|
|
|
@@ -717,7 +542,6 @@ func test_kampf_steuerung() -> void:
|
|
|
|
|
w += 1
|
|
|
|
|
check(g.current() == g.human and w < 60, "Gegnerzug übersprungen (%d Bilder)" % w)
|
|
|
|
|
scr.ai_delay = 0.0
|
|
|
|
|
await clear_mulligan(scr)
|
|
|
|
|
await key(KEY_ESCAPE)
|
|
|
|
|
check(scr.confirm.visible, "Esc öffnet Aufgeben")
|
|
|
|
|
await key(KEY_ESCAPE)
|
|
|
|
|
@@ -725,6 +549,92 @@ func test_kampf_steuerung() -> void:
|
|
|
|
|
await give_up()
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
## Grenzen im Kampf: volle Hand, volles Feld, kein Mana.
|
|
|
|
|
func test_kampf_grenzen() -> void:
|
|
|
|
|
await start_battle(1)
|
|
|
|
|
var scr = screen()
|
|
|
|
|
scr.ai_delay = 0.0
|
|
|
|
|
await wait_for_human(scr)
|
|
|
|
|
var g: Game = scr.game
|
|
|
|
|
g.human.energy = 100
|
|
|
|
|
scr.refresh()
|
|
|
|
|
await frames(1)
|
|
|
|
|
# Hand voll kaufen
|
|
|
|
|
var guard := 0
|
|
|
|
|
while g.human.hand.size() < Game.MAX_HAND and guard < 30:
|
|
|
|
|
guard += 1
|
|
|
|
|
if scr.shop_views.is_empty():
|
|
|
|
|
await click(scr.b_reroll)
|
|
|
|
|
continue
|
|
|
|
|
await click(scr.shop_views[0])
|
|
|
|
|
check(g.human.hand.size() == Game.MAX_HAND, "Hand auf %d gefüllt" % Game.MAX_HAND)
|
|
|
|
|
check(scr.shop_views.all(func(v): return v.dim), "bei voller Hand ist nichts mehr kaufbar")
|
|
|
|
|
if not scr.shop_views.is_empty():
|
|
|
|
|
await click(scr.shop_views[0])
|
|
|
|
|
check(scr.msg_label.text == tr("Hand voll"), "Meldung bei voller Hand: " + scr.msg_label.text)
|
|
|
|
|
# Feld voll spielen
|
|
|
|
|
guard = 0
|
|
|
|
|
while g.human.board.size() < Game.MAX_BOARD and guard < 30:
|
|
|
|
|
guard += 1
|
|
|
|
|
await key(KEY_1)
|
|
|
|
|
if scr.pending != null: # Karte will ein Ziel
|
|
|
|
|
var valid: Array = g.valid_targets(g.human, scr.pending.target_type())
|
|
|
|
|
if valid.is_empty():
|
|
|
|
|
await right_click()
|
|
|
|
|
else:
|
|
|
|
|
await click(target_view(scr, valid))
|
|
|
|
|
check(g.human.board.size() == Game.MAX_BOARD, "Feld mit %d Wesen voll" % Game.MAX_BOARD)
|
|
|
|
|
await key(KEY_1)
|
|
|
|
|
check(scr.msg_label.text == tr("Dein Feld ist voll"), "Meldung bei vollem Feld: " + scr.msg_label.text)
|
|
|
|
|
await shot("25_kampf_voll")
|
|
|
|
|
# Verschmelzen macht wieder Platz
|
|
|
|
|
var before: int = g.human.board.size()
|
|
|
|
|
await click(scr.b_fuse)
|
|
|
|
|
await click(scr.own_views[0])
|
|
|
|
|
await click(scr.own_views[1])
|
|
|
|
|
check(g.human.board.size() == before - 1, "Verschmelzen macht einen Platz frei")
|
|
|
|
|
# Ohne Mana kein Neuwürfeln
|
|
|
|
|
g.human.energy = 0
|
|
|
|
|
scr.refresh()
|
|
|
|
|
await frames(1)
|
|
|
|
|
check(scr.b_reroll.disabled, "ohne Mana kein Neuwürfeln")
|
|
|
|
|
await give_up()
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
## Feldanzeige und Verschmelzen im Kampf.
|
|
|
|
|
func test_kampf_feld_und_verschmelzen() -> void:
|
|
|
|
|
await start_battle(1)
|
|
|
|
|
var scr = screen()
|
|
|
|
|
check(scr is BattleScreen, "Kampf gestartet")
|
|
|
|
|
scr.ai_delay = 0.0
|
|
|
|
|
await wait_for_human(scr)
|
|
|
|
|
var g: Game = scr.game
|
|
|
|
|
g.human.board.clear()
|
|
|
|
|
for id in ["f_wolf", "w_reiter"]:
|
|
|
|
|
var cr := Game.Creature.new(Cards.by_id(id), g.human, g.next_uid)
|
|
|
|
|
g.next_uid += 1
|
|
|
|
|
g.human.board.append(cr)
|
|
|
|
|
g.human.energy = 10
|
|
|
|
|
for i in Cards.FIELD_CHARGE:
|
|
|
|
|
g.charge_field(Cards.by_id("f_kobold"))
|
|
|
|
|
scr.refresh()
|
|
|
|
|
await frames(2)
|
|
|
|
|
check(scr.field_label.text.begins_with("Vulkan"), "Feldanzeige nennt das Feld: " + scr.field_label.text)
|
|
|
|
|
check(g.human.board[0].field_bonus == 1 and g.human.board[0].power() == 4, "das Feuerwesen bekommt +1 Angriff")
|
|
|
|
|
check(scr.b_fuse.visible and scr.b_fuse.text == "Verschmelzen", "Verschmelzen wird angeboten")
|
|
|
|
|
await shot("23_feld")
|
|
|
|
|
await click(scr.b_fuse)
|
|
|
|
|
check(scr.fusing and scr.b_fuse.text == "Abbrechen", "Verschmelzen ausgewählt")
|
|
|
|
|
await click(scr.own_views[0])
|
|
|
|
|
check(scr.fuse_first != null, "erstes Wesen gewählt")
|
|
|
|
|
await shot("24_verschmelzen")
|
|
|
|
|
await click(scr.own_views[1])
|
|
|
|
|
check(g.human.board.size() == 1 and g.human.board[0].name == "Dampf", "die beiden Wesen sind zu Dampf verschmolzen")
|
|
|
|
|
check(not scr.fusing and g.human.energy == 8, "Modus beendet und Mana bezahlt")
|
|
|
|
|
check(scr.own_views.size() == 1, "nur noch eine eigene Kachel")
|
|
|
|
|
await give_up()
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
func test_netzwerk() -> void:
|
|
|
|
|
await click(find_button("Netzwerkspiel"))
|
|
|
|
|
var scr = screen()
|
|
|
|
|
@@ -756,7 +666,6 @@ func test_netzwerk() -> void:
|
|
|
|
|
var rounds := 0
|
|
|
|
|
while b.game != null and b.game.winner == "" and rounds < 2:
|
|
|
|
|
if b.game.current() == b.perspective:
|
|
|
|
|
await clear_mulligan(b)
|
|
|
|
|
if b.game.current() == b.perspective:
|
|
|
|
|
await click(b.b_end)
|
|
|
|
|
var w2 := 0
|
|
|
|
|
@@ -767,7 +676,7 @@ func test_netzwerk() -> void:
|
|
|
|
|
if b.game.winner != "":
|
|
|
|
|
print("DEBUG Netz: Sieger=", b.game.winner, " Verlauf=", b.game.log.slice(maxi(0, b.game.log.size() - 12)))
|
|
|
|
|
check(b.game.turn >= 2 and b.game.winner == "", "Runden gespielt, Partie läuft (Zug %d)" % b.game.turn)
|
|
|
|
|
check(b.game.log.any(func(l): return l.begins_with("Bot spielt") or l.begins_with("Bot behält") or l.begins_with("Bot tauscht")), "Bot hat gehandelt")
|
|
|
|
|
check(b.game.log.any(func(l): return l.begins_with("Bot kauft") or l.begins_with("Bot spielt")), "Bot hat gehandelt")
|
|
|
|
|
await shot("24_netzwerk_kampf")
|
|
|
|
|
# Bot verlässt geordnet: Platz bleibt frei, Züge werden übersprungen
|
|
|
|
|
var quit_file := "user://bot_quit"
|
|
|
|
|
@@ -781,7 +690,6 @@ func test_netzwerk() -> void:
|
|
|
|
|
check(main.net.waiting.has("Bot") and b.game.log.any(func(l): return "Verbindung verloren" in l), "Platz wird freigehalten")
|
|
|
|
|
var turn_before: int = b.game.turn
|
|
|
|
|
for i in 2:
|
|
|
|
|
await clear_mulligan(b)
|
|
|
|
|
if b.game.current() == b.perspective and b.game.winner == "":
|
|
|
|
|
await click(b.b_end)
|
|
|
|
|
var w4 := 0
|
|
|
|
|
@@ -799,7 +707,6 @@ func test_netzwerk() -> void:
|
|
|
|
|
check(main.net.waiting.is_empty() and main.net.seats.size() == 2 and b.game.log.any(func(l): return l == "Bot ist zurück."), "Bot wieder verbunden, Platz zurück")
|
|
|
|
|
var turn2: int = b.game.turn
|
|
|
|
|
for i in 2:
|
|
|
|
|
await clear_mulligan(b)
|
|
|
|
|
if b.game.current() == b.perspective and b.game.winner == "":
|
|
|
|
|
await click(b.b_end)
|
|
|
|
|
var w6 := 0
|
|
|
|
|
@@ -873,7 +780,6 @@ func test_host_wechsel() -> void:
|
|
|
|
|
await shot("34_host_wechsel")
|
|
|
|
|
# Der alte Host kehrt nicht zurück: ein Zug wird übersprungen, nach der Frist scheidet er aus
|
|
|
|
|
b.ai_delay = 0.0
|
|
|
|
|
await clear_mulligan(b)
|
|
|
|
|
if b.game.current() == b.perspective:
|
|
|
|
|
await click(b.b_end)
|
|
|
|
|
w = 0
|
|
|
|
|
@@ -906,7 +812,7 @@ func test_zuschauer() -> void:
|
|
|
|
|
while (b.game == null or b.game.turn < 2) and w < 900:
|
|
|
|
|
await frames(1)
|
|
|
|
|
w += 1
|
|
|
|
|
check(b.game != null and b.game.turn >= 2 and b.hand_views.is_empty() and not b.mulligan_box.visible and not b.b_end.visible,
|
|
|
|
|
check(b.game != null and b.game.turn >= 2 and b.hand_views.is_empty() and not b.b_end.visible,
|
|
|
|
|
"Zuschauer sieht die Partie ohne Hände und ohne Züge (Zug %d)" % (b.game.turn if b.game != null else 0))
|
|
|
|
|
await shot("35_zuschauer")
|
|
|
|
|
check(not b.b_end.visible and not b.b_undo.visible, "Zuschauer hat keine Zugknöpfe")
|
|
|
|
|
@@ -964,7 +870,7 @@ func test_kampf(n_opp: int, shot_turn: int) -> void:
|
|
|
|
|
var g: Game = scr.game
|
|
|
|
|
check(g.opponents.size() == n_opp and g.log[0].begins_with("Zugreihenfolge"), "Spiel gestartet, Reihenfolge ausgelost")
|
|
|
|
|
await wait_for_human(scr)
|
|
|
|
|
check(g.current() == g.human and g.human.mulligan_done, "Spieler ist dran, Mulligan erledigt")
|
|
|
|
|
check(g.current() == g.human, "Spieler ist dran")
|
|
|
|
|
check(scr.hand_views.size() == g.human.hand.size(), "Handkarten sichtbar")
|
|
|
|
|
await shot("07_kampf_start")
|
|
|
|
|
var coins: int = main.profile.coins
|
|
|
|
|
@@ -998,35 +904,30 @@ func test_kampf_abbrechen() -> void:
|
|
|
|
|
var g: Game = scr.game
|
|
|
|
|
await wait_for_human(scr)
|
|
|
|
|
check(g.opponents.size() == 5 and g.human.max_energy == 1, "5 Gegner")
|
|
|
|
|
# Falle legen und Kombo-Hinweis prüfen
|
|
|
|
|
g.human.hand.append(Cards.by_id("f_falle"))
|
|
|
|
|
# Kartenvorschau: aufgewertete Karten zeigen ihre Seltenheit
|
|
|
|
|
g.human.energy = 10
|
|
|
|
|
var wolf := Game.Creature.new(Cards.by_id("f_wolf"), g.human, 9000)
|
|
|
|
|
g.human.board.append(wolf)
|
|
|
|
|
g.human.hand.append(Cards.by_id("w_reiter"))
|
|
|
|
|
g.human.looks["w_reiter"] = Cards.RARITIES.find("episch")
|
|
|
|
|
scr.refresh()
|
|
|
|
|
var trap_view = scr.hand_views.filter(func(v): return v.card.id == "f_falle")[0]
|
|
|
|
|
await click(trap_view)
|
|
|
|
|
check(g.human.traps.size() == 1 and scr.trap_views.size() == 1, "Falle gelegt und sichtbar")
|
|
|
|
|
var reiter_view = scr.hand_views.filter(func(v): return v.card.id == "w_reiter")[0]
|
|
|
|
|
check(reiter_view.rarity == "episch", "Handkarte trägt die eigene Stufe")
|
|
|
|
|
await hover(scr.log_box) # erst weg von der Hand, damit das Betreten sicher ausgelöst wird
|
|
|
|
|
await hover(reiter_view)
|
|
|
|
|
var hint_boxes = scr.preview_holder.get_children().filter(func(c): return c is RichTextLabel)
|
|
|
|
|
if hint_boxes.size() != 1:
|
|
|
|
|
print("DEBUG Hinweis: hints=", scr.combo_hints(Cards.by_id("w_reiter")), " kinder=", scr.preview_holder.get_children().map(func(c): return c.get_class()),
|
|
|
|
|
" brett=", g.human.board.map(func(c): return c.name), " hovered=", get_viewport().gui_get_hovered_control(), " reiter_pos=", reiter_view.get_global_rect())
|
|
|
|
|
check(hint_boxes.size() == 1 and "Feldkombo Dampf" in hint_boxes[0].text, "Kombo-Hinweis in der Vorschau")
|
|
|
|
|
await shot("21_kampf_falle_hinweis")
|
|
|
|
|
var spells: Array = scr.hand_views.filter(func(v): return v.card.target_type() != "" and g.can_play(g.human, v.card)[0])
|
|
|
|
|
if not spells.is_empty():
|
|
|
|
|
var card: Cards.Card = spells[0].card
|
|
|
|
|
await click(spells[0])
|
|
|
|
|
var previews = scr.preview_holder.get_children().filter(func(c): return c is CardView)
|
|
|
|
|
check(previews.size() == 1 and previews[0].rarity == "episch", "Vorschau ebenfalls")
|
|
|
|
|
await shot("21_kampf_vorschau")
|
|
|
|
|
var targeted: Array = scr.hand_views.filter(func(v): return v.card.target_type() != "" and g.can_play(g.human, v.card)[0])
|
|
|
|
|
if not targeted.is_empty():
|
|
|
|
|
var card: Cards.Card = targeted[0].card
|
|
|
|
|
await click(targeted[0])
|
|
|
|
|
check(scr.pending == card, "Ziel wird erwartet")
|
|
|
|
|
await right_click()
|
|
|
|
|
check(scr.pending == null and card in g.human.hand, "Rechtsklick bricht ab")
|
|
|
|
|
await hover(scr.hand_views[0])
|
|
|
|
|
if scr.preview_holder.get_child_count() == 0:
|
|
|
|
|
print("DEBUG Hover: mulligan=", scr.mulligan_box.visible, " overlay=", scr.any_overlay(), " hand=", scr.hand_views.size(),
|
|
|
|
|
print("DEBUG Hover: overlay=", scr.any_overlay(), " hand=", scr.hand_views.size(),
|
|
|
|
|
" dran=", g.current().name, " Sieger=", g.winner, " hovered=", get_viewport().gui_get_hovered_control())
|
|
|
|
|
check(scr.preview_holder.get_child_count() > 0, "Vorschau bei Hover")
|
|
|
|
|
await click(find_button("Lupe"))
|
|
|
|
|
|