class_name BattleGamepad extends RefCounted ## Gamepad-Steuerung des Kampfes: Steuerkreuz bewegt einen Zeiger über Laden, Hand, eigene Wesen ## und Ziele, A bestätigt, B bricht ab, Start beendet den Zug, Y überspringt Gegnerzüge, ## X macht rückgängig. var screen # BattleScreen var active := false var zone := "shop" var index := 0 var targets: Array = [] func _init(s) -> void: screen = s func button(button: int) -> void: active = true if screen.game == null: return match button: JOY_BUTTON_START: if screen.my_turn() and not screen.any_overlay(): screen.end_turn() JOY_BUTTON_B: if screen.confirm.visible: screen.confirm.visible = false screen.cancel_all() zone = "shop" JOY_BUTTON_Y: if screen.b_skip.visible: screen.skip_ai = true JOY_BUTTON_X: if screen.b_undo.visible: screen.undo() JOY_BUTTON_A: confirm() JOY_BUTTON_DPAD_LEFT: move(-1) JOY_BUTTON_DPAD_RIGHT: move(1) JOY_BUTTON_DPAD_UP, JOY_BUTTON_DPAD_DOWN: if zone != "target": _next_zone(1 if button == JOY_BUTTON_DPAD_DOWN else -1) screen.refresh() ## Wechselt den Bereich und überspringt leere (eine leere Hand ist keine Station). ## step 0: beim aktuellen Bereich bleiben, falls er etwas enthält. func _next_zone(step: int) -> void: var order := ["shop", "hand", "own"] var at := order.find(zone) index = 0 if step == 0 and not items().is_empty(): return var dir := -1 if step < 0 else 1 for i in order.size(): at = posmod(at + dir, order.size()) zone = order[at] if not items().is_empty(): return func items() -> Array: match zone: "shop": return screen.shop_views "hand": return screen.hand_views "own": if screen.fusing: # zum Verschmelzen zählt jedes eigene Wesen, nicht nur angriffsbereite return screen.own_views return screen.own_views.filter(func(v): return v.creature.can_attack()) "target": return targets return [] func move(dir: int) -> void: var n := items().size() if n > 0: index = posmod(index + dir, n) func confirm() -> void: if screen.overlay.visible: screen.leave() return if screen.confirm.visible: return var items := items() if items.is_empty(): return index = clampi(index, 0, items.size() - 1) var item = items[index] match zone: "shop": screen.on_click("shop", int(item.get_meta("slot", 0))) "hand": screen.on_click("hand", item.card) if screen.pending != null: targets = [] var valid: Array = screen.game.valid_targets(screen.perspective, screen.pending.target_type()) for v in screen.enemy_views: if v.creature in valid: targets.append(v) for v in screen.own_views: if v.creature in valid: targets.append(v) for o in screen.others(): if o in valid: targets.append(screen.hero_panels[o]) zone = "target" index = 0 "own": screen.on_click("own", item.creature) if screen.selected != null: targets = [] for v in screen.enemy_views: if screen.game.can_attack(screen.selected, v.creature)[0]: targets.append(v) for o in screen.others(): if o.alive() and screen.game.can_attack(screen.selected, o)[0]: targets.append(screen.hero_panels[o]) zone = "target" index = 0 "target": if item is CreatureView: screen.on_tile_click(item.creature) else: for o in screen.hero_panels: if screen.hero_panels[o] == item: screen.on_click("hero", o) zone = "own" _next_zone(0) ## Pulsierender Rahmen als Zeiger. class Highlight extends Control: var t := 0.0 func _process(delta: float) -> void: t += delta queue_redraw() func _draw() -> void: var a := 0.55 + 0.45 * sin(t * 6.0) Style.border(self, Rect2(Vector2.ZERO, size), Color(Style.GOLD, a), 4, 8) func draw_cursor() -> void: Style.clear(screen.cursor_layer) if not active or screen.game == null or not screen.my_turn(): return var items := items() if items.is_empty(): return index = clampi(index, 0, items.size() - 1) var item = items[index] var r: Rect2 = Rect2(item.slot, item.size) if item is CreatureView else Rect2(item.position, item.size) var hl := Highlight.new() hl.position = r.position - Vector2(6, 6) hl.size = r.size + Vector2(12, 12) hl.mouse_filter = Control.MOUSE_FILTER_IGNORE screen.cursor_layer.add_child(hl)