class_name CampaignScreen extends Control ## Kampagne als Pfad: zehn Stationen je Kapitel, darunter die gewählte Stufe im Detail. var app var chapter := 1 var selected := 0 # gewählte Stufe (Index über alle Kapitel) var perk_box: OptionButton var node_buttons: Array = [] func _ready() -> void: var p: Profile = app.profile chapter = mini(Campaign.chapter(p.campaign_stage), Campaign.CHAPTERS.size()) selected = mini(p.campaign_stage, Campaign.total() - 1) build() func build() -> void: Style.clear(self) node_buttons = [] var p: Profile = app.profile Style.header(self, "Kampagne", func(): app.show_screen(MenuScreen.new())) var n := Campaign.STAGES.size() var x := 40 for c in Campaign.CHAPTERS.size(): var b := Style.button(self, "Kapitel %d" % (c + 1), Rect2(x, 88, 150, 38), set_chapter.bind(c + 1), Style.PRIMARY if chapter == c + 1 else null) b.disabled = p.campaign_stage < c * n x += 160 if p.perk_unlocked(): Style.label(self, "Dein Merkmal:", 15, Style.MUTED, Rect2(760, 96, 130, 24), "right") perk_box = OptionButton.new() perk_box.position = Vector2(900, 88) perk_box.size = Vector2(340, 38) perk_box.add_item("keins") var keys: Array = Game.PERKS.keys() for k in keys: perk_box.add_item(Game.PERKS[k]) perk_box.select(keys.find(p.perk) + 1 if p.perk != "" else 0) perk_box.item_selected.connect(func(i: int): p.perk = "" if i == 0 else keys[i - 1] app.save()) add_child(perk_box) # Pfad mit Stationen var offset := (chapter - 1) * n var y := 190.0 var step := (1280 - 200) / float(n - 1) var centers: Array[Vector2] = [] for k in n: centers.append(Vector2(100 + k * step, y)) var path := Control.new() path.mouse_filter = Control.MOUSE_FILTER_IGNORE path.draw.connect(func(): for k in n - 1: var done: bool = offset + k + 1 <= p.campaign_stage path.draw_line(centers[k], centers[k + 1], Style.GREEN if done else Style.PANEL_LIGHT, 4.0)) add_child(path) for k in n: var i := offset + k var done := i < p.campaign_stage var next := i == p.campaign_stage var b := Button.new() b.text = str(i + 1) b.position = centers[k] - Vector2(24, 24) b.size = Vector2(48, 48) var base: Color = Style.PRIMARY if done else (Color("5a4628") if next else Style.PANEL) var edge: Color = Style.GOLD if i == selected else (Style.GREEN if done else Style.MUTED) b.add_theme_stylebox_override("normal", Style.box(base, 24, edge, 3 if i == selected else 2)) b.add_theme_stylebox_override("hover", Style.box(Style.lighter(base), 24, edge, 3)) b.add_theme_stylebox_override("pressed", Style.box(Style.darker(base), 24, edge, 3)) b.add_theme_stylebox_override("disabled", Style.box(Style.darker(Style.PANEL, 0.8), 24, Style.PANEL_LIGHT, 2)) b.add_theme_stylebox_override("focus", Style.box(Color(0, 0, 0, 0), 24, Style.GOLD, 3)) b.disabled = i > p.campaign_stage b.pressed.connect(func(): selected = i build()) Style.juice(b) add_child(b) node_buttons.append(b) if next and Style.animations: b.pivot_offset = b.size / 2 var tw := b.create_tween().set_loops() tw.tween_property(b, "scale", Vector2(1.1, 1.1), 0.6).set_trans(Tween.TRANS_SINE).set_ease(Tween.EASE_IN_OUT) tw.tween_property(b, "scale", Vector2.ONE, 0.6).set_trans(Tween.TRANS_SINE).set_ease(Tween.EASE_IN_OUT) # Gewählte Stufe var st := Campaign.stage(selected) var done := selected < p.campaign_stage var next := selected == p.campaign_stage Style.panel(self, Rect2(240, 270, 800, 300)) Style.label(self, "%s · %s" % [st.name, st.title], 28, Style.TEXT, Rect2(270, 290, 740, 40), "center", true) Style.label(self, "%s · %s" % [tr("%d Leben") % int(st.life), tr("%d Münzen") % st.reward], 16, Style.MUTED, Rect2(270, 350, 740, 24), "center") var perks: Array = st.perks var py := 390 for k in perks: Style.label(self, "★ " + tr(Game.PERKS[k]), 15, Style.GOLD, Rect2(270, py, 740, 22), "center") py += 24 if done: Style.button(self, "Wiederholen", Rect2(540, 500, 200, 50), _start.bind(selected)) elif next: var b := Style.button(self, "Kämpfen", Rect2(540, 500, 200, 50), _start.bind(selected), Style.PRIMARY) b.add_theme_font_size_override("font_size", 20) else: var b := Style.button(self, "Gesperrt", Rect2(540, 500, 200, 50), func(): pass) b.disabled = true if p.campaign_stage >= Campaign.total(): Style.label(self, "Alle Kapitel abgeschlossen", 16, Style.GREEN, Rect2(0, 600, 1280, 24), "center", true) func set_chapter(c: int) -> void: chapter = c var p: Profile = app.profile var first := (c - 1) * Campaign.STAGES.size() selected = p.campaign_stage if Campaign.chapter(mini(p.campaign_stage, Campaign.total() - 1)) == c else first build() func _start(stage: int) -> void: app.show_screen(BattleScreen.new(stage)) func _input(event: InputEvent) -> void: if event is InputEventKey and event.pressed and event.keycode == KEY_ESCAPE: app.show_screen(MenuScreen.new())