class_name BattleTutorial extends RefCounted ## Geführte Partien: Schritte, Bedingungen und Hervorhebungen (ausgelagert aus dem Kampfbildschirm). const STEPS1 := [ ["Willkommen! Unten liegt deine Hand. Jede Karte kostet Energie (◆), du hast im ersten Zug 1. Spiele ein Wesen mit Kosten 1 per Klick.", "played_creature"], ["Wesen greifen erst ab dem nächsten Zug an. Beende deinen Zug mit dem Knopf rechts oder der Leertaste.", "turn_passed"], ["Grüne Rahmen zeigen angriffsbereite Wesen. Klicke ein Wesen und dann Fenn oder eines seiner Wesen. Wächter müssen zuerst fallen.", "attacked"], ["Resonanz: Wesen mit gleichem Element geben sich gegenseitig Angriff. Spiele ein zweites Feuer- oder Erde-Wesen.", "resonance"], ["Feldkombo: Ein Wesen neben einem eigenen Wesen mit anderem Element löst einen Effekt aus. Lava macht 1 Schaden an alle gegnerischen Wesen.", "combo"], ["Zauber wirken sofort. Funke oder Feuerball treffen auch Fenn direkt. Ziele wählst du per Klick, Rechtsklick bricht ab.", "spell"], ["Fenn verliert bei 0 Leben. Tausche im ersten Zug einer Partie schwache Starthände (Mulligan). Viel Erfolg!", ""], ] const STEPS2 := [ ["Mulligan: Im ersten Zug darfst du einmal Handkarten zurücklegen und neu ziehen. Entscheide in der Maske, was du behältst.", "mulligan"], ["Fallen liegen verdeckt und lösen im gegnerischen Zug aus. Lege die Frostfalle, sobald du 2 Energie hast.", "trap_set"], ["Beende den Zug und warte. Greift Mara dich oder ein Wesen an, verpufft der Angriff und ihr Wesen friert ein.", "trap_fired"], ["Feldkombo Dampf: Ein Wasser-Wesen neben einem Feuer-Wesen friert das stärkste gegnerische Wesen ein. Spiele beide nacheinander.", "combo_dampf"], ["Rückgängig (U) nimmt ein gerade gespieltes Wesen zurück, solange nichts ausgelöst wurde. Viel Erfolg gegen Mara!", ""], ] var screen # BattleScreen var part := 1 var step := 0 func _init(s, p: int = 1) -> void: screen = s part = p func steps() -> Array: return STEPS1 if part == 1 else STEPS2 func stage_index() -> int: return 0 if part == 1 else 1 ## Teil 2 bekommt die Lehrkarten auf die Hand. func inject_cards(hand: Array) -> void: if part == 2: hand.append(Cards.by_id("w_falle")) hand.append(Cards.by_id("w_reiter")) func condition(kind: String) -> bool: var g: Game = screen.game var h: Game.Player = g.human match kind: "played_creature": return g.log.any(func(l): return l.begins_with("Du spielt")) and h.board.size() > 0 "turn_passed": return h.turns >= 2 "attacked": return g.log.any(func(l): return l.begins_with(h.board[0].name + " greift") if not h.board.is_empty() else false) \ or g.log.any(func(l): return l.ends_with("greift Fenn an.")) "resonance": return h.board.any(func(c): return c.resonance > 0) "combo": return g.log.any(func(l): return l.begins_with("Feldkombo")) "spell": return g.log.any(func(l): return l == "Du spielt Funke." or l == "Du spielt Feuerball." or l == "Du spielt Verhärten.") "mulligan": return h.mulligan_done "trap_set": return g.log.any(func(l): return l == "Du legt eine Falle.") "trap_fired": return g.log.any(func(l): return l.begins_with("Falle von Du")) "combo_dampf": return g.log.any(func(l): return l.begins_with("Feldkombo Dampf")) return false func advance() -> void: while step < steps().size() - 1 and condition(steps()[step][1]): step += 1 func next() -> bool: if step < steps().size() - 1: step += 1 return true return false func text() -> String: return "%d/%d %s" % [step + 1, steps().size(), steps()[step][0]] func finished() -> bool: return step >= steps().size() - 1 ## Rechtecke, die der aktuelle Schritt hervorhebt. func highlight_rects(mine: bool) -> Array[Rect2]: var rects: Array[Rect2] = [] if not mine or screen.any_overlay(): return rects var g: Game = screen.game var h: Game.Player = screen.perspective match steps()[step][1]: "played_creature": for v in screen.hand_views: if v.card.is_creature() and g.can_play(h, v.card)[0]: rects.append(Rect2(v.position, v.size)) "turn_passed", "trap_fired": rects.append(screen.b_end.get_rect()) "attacked": for v in screen.own_views: if v.creature.can_attack(): rects.append(Rect2(v.slot, v.size)) if screen.own_views.any(func(v): return v.creature.can_attack()): for o in screen.others(): if o.alive() and screen.hero_panels.has(o): rects.append(screen.hero_panels[o].get_rect()) "resonance": for v in screen.hand_views: var c: Cards.Card = v.card if c.is_creature() and g.can_play(h, c)[0] and h.board.any(func(b): return b.card.elements.any(func(e): return e in c.elements)): rects.append(Rect2(v.position, v.size)) "combo": for v in screen.hand_views: var c: Cards.Card = v.card if c.is_creature() and g.can_play(h, c)[0] and h.board.any(func(b): return b.card.elements.any(func(e): return not (e in c.elements))): rects.append(Rect2(v.position, v.size)) "spell": for v in screen.hand_views: if v.card.kind == "Zauber" and g.can_play(h, v.card)[0]: rects.append(Rect2(v.position, v.size)) "trap_set": for v in screen.hand_views: if v.card.is_trap() and g.can_play(h, v.card)[0]: rects.append(Rect2(v.position, v.size)) "combo_dampf": var has_fire: bool = h.board.any(func(b): return "Feuer" in b.card.elements) for v in screen.hand_views: var c: Cards.Card = v.card if not c.is_creature() or not g.can_play(h, c)[0]: continue if (has_fire and "Wasser" in c.elements) or (not has_fire and "Feuer" in c.elements): rects.append(Rect2(v.position, v.size)) return rects