class_name InfoColumn extends Control ## Linke Spalte: Elemente im Team, Kombinationen, gewählte Einheit, Rückblick. signal upgrade_pressed const PANEL_BG := Color(0.14, 0.15, 0.19) var traits_box: VBoxContainer var info_box: VBoxContainer var log_box: VBoxContainer var _text_w := 240.0 func build(x: float, y: float, w: float, h: float) -> void: position = Vector2(x, y) size = Vector2(w, h) _text_w = w - 46.0 mouse_filter = Control.MOUSE_FILTER_IGNORE var p := UiKit.panel(PANEL_BG) p.size = size p.clip_contents = true add_child(p) var sc := ScrollContainer.new() sc.horizontal_scroll_mode = ScrollContainer.SCROLL_MODE_DISABLED p.add_child(sc) var col := VBoxContainer.new() col.add_theme_constant_override("separation", 10) col.size_flags_horizontal = Control.SIZE_EXPAND_FILL sc.add_child(col) traits_box = VBoxContainer.new() info_box = VBoxContainer.new() log_box = VBoxContainer.new() # Die gewählte Einheit zuerst: dort sitzt der Aufwerten-Knopf, der muss ohne Scrollen erreichbar sein. for b in [info_box, traits_box, log_box]: b.add_theme_constant_override("separation", 3) b.size_flags_horizontal = Control.SIZE_EXPAND_FILL col.add_child(b) col.add_child(HSeparator.new()) func refresh(game: Game, avatar: Avatar, hex: Vector2i) -> void: _refresh_traits(game) _refresh_info(game, avatar, hex) _refresh_log(game) func _wrapped(text: String, size: int, col: Color) -> Label: var l := UiKit.label(text, size, col) l.autowrap_mode = TextServer.AUTOWRAP_WORD_SMART l.custom_minimum_size = Vector2(_text_w, 0) l.size_flags_horizontal = Control.SIZE_FILL return l func _clear(box: Node) -> void: for c in box.get_children(): box.remove_child(c) c.queue_free() func _refresh_traits(game: Game) -> void: _clear(traits_box) traits_box.add_child(UiKit.label("Elemente im Team", 15, Color(0.75, 0.8, 0.95))) var counts := game.human.trait_counts() var any := false for e in Data.ELEMENT_COUNT: var c: int = counts.get(e, 0) if c == 0: continue any = true var tier := Data.trait_tier(e, c) var col: Color = Data.ELEMENT_COLORS[e] var row := HBoxContainer.new() var dot := ColorRect.new() dot.color = col if tier > 0 else col.darkened(0.55) dot.custom_minimum_size = Vector2(12, 12) row.add_child(dot) var tr: Dictionary = Data.ELEMENT_TRAITS[e] var txt := " %s %d" % [Data.ELEMENT_NAMES[e], c] if tier > 0: txt += " - " + tr["desc"][tier - 1] else: txt += " (ab 2 aktiv)" # Ausblick: was die nächste Stufe bringt. if tier < tr["steps"].size(): txt += "\n nächste Stufe bei %d: %s" % [tr["steps"][tier], tr["desc"][tier]] else: txt += "\n höchste Stufe" var el := UiKit.label(txt, 13, Color(0.9, 0.9, 0.95) if tier > 0 else Color(0.55, 0.55, 0.6)) el.autowrap_mode = TextServer.AUTOWRAP_WORD_SMART el.custom_minimum_size = Vector2(_text_w - 20.0, 0) row.add_child(el) traits_box.add_child(row) if not any: traits_box.add_child(_wrapped("Noch nichts aufgestellt.", 13, Color(0.55, 0.55, 0.6))) traits_box.add_child(UiKit.label("\nKombinationen", 15, Color(0.75, 0.8, 0.95))) var keys := [] for c in game.human.active_combos(): keys.append(c["key"]) for c in Data.COMBO_TRAITS: var on: bool = keys.has(c["key"]) var t := "%s (%s+%s): %s" % [c["name"], Data.ELEMENT_NAMES[c["a"]], Data.ELEMENT_NAMES[c["b"]], c["desc"]] traits_box.add_child(_wrapped(t, 12, Color(0.6, 0.95, 0.7) if on else Color(0.45, 0.45, 0.5))) func _refresh_info(game: Game, a: Avatar, hex: Vector2i) -> void: _clear(info_box) info_box.add_child(UiKit.label("Einheit", 15, Color(0.75, 0.8, 0.95))) if a == null: info_box.add_child(_wrapped("Einheit auf dem Feld oder der Bank anklicken.", 13, Color(0.55, 0.55, 0.6))) return var s := a.base_stats() info_box.add_child(_wrapped("%s %d-Star" % [a.display_name(), a.star], 14, a.color())) info_box.add_child(_wrapped("%s: %s" % [Data.ELEMENT_NAMES[a.primary_element()], Data.PROFILE_HINT[a.primary_element()]], 12, Color(0.75, 0.8, 0.9))) var crit := " Krit %d%%" % int(s["crit"] * 100.0) if s["crit"] > 0.0 else "" info_box.add_child(_wrapped("Leben %d Angriff %d Rüstung %d%%\nTempo %.2f Reichweite %d%s" % [int(s["hp"]), int(s["atk"]), int(s["armor"] * 100.0), s["aspd"], s["range"], crit], 12, Color(0.9, 0.9, 0.95))) info_box.add_child(_wrapped(a.counter_text(), 12, Color(1.0, 0.75, 0.9))) info_box.add_child(_wrapped(a.ability_text(), 12, Color(0.8, 0.85, 1.0))) if hex.x < 0: info_box.add_child(_wrapped("Zum Aufwerten aufs Feld ziehen.", 12, Color(0.85, 0.85, 0.9))) return var cost := a.upgrade_cost() if cost.is_empty(): info_box.add_child(_wrapped("Maximale Stufe.", 12, Color(1.0, 0.85, 0.35))) return var p := game.human var missing := p.upgrade_missing(hex) var need := [] for e in cost: need.append("%dx %s" % [cost[e], Data.ELEMENT_NAMES[e]]) info_box.add_child(_wrapped("Aufwerten braucht: " + ", ".join(need), 12, Color(0.85, 0.85, 0.9))) if missing.is_empty(): var b := UiKit.button("Aufwerten", Color(0.28, 0.55, 0.36)) b.custom_minimum_size = Vector2(140, 26) b.pressed.connect(func(): upgrade_pressed.emit()) info_box.add_child(b) else: var miss := [] for e in missing: miss.append("%dx %s" % [missing[e], Data.ELEMENT_NAMES[e]]) info_box.add_child(_wrapped("Es fehlt: " + ", ".join(miss), 12, Color(0.95, 0.6, 0.5))) func _refresh_log(game: Game) -> void: _clear(log_box) log_box.add_child(UiKit.label("Letzte Runde", 15, Color(0.75, 0.8, 0.95))) var r := game.human_recap if not r.is_empty(): var verdict := "unentschieden" var col := Color(0.85, 0.85, 0.9) if r["result"] > 0: verdict = "gewonnen" col = Color(0.6, 0.95, 0.7) elif r["result"] < 0: verdict = "verloren (-%d Leben)" % r["damage"] col = Color(1.0, 0.6, 0.55) log_box.add_child(_wrapped("Gegen %s: %s" % [r["opponent"], verdict], 13, col)) if r["total"] == 0: log_box.add_child(_wrapped("Du hattest keine Einheiten aufgestellt.", 12, Color(0.95, 0.75, 0.7))) else: log_box.add_child(_wrapped("%d von %d Einheiten überlebt, %.0f s" % [r["alive"], r["total"], r["duration"]], 12, Color(0.8, 0.8, 0.86))) var best := "Stärkste: %s (%d Schaden" % [r["best_name"], r["best_dealt"]] best += ", %d geheilt)" % r["best_healed"] if r["best_healed"] > 0 else ")" log_box.add_child(_wrapped(best, 12, Color(0.8, 0.8, 0.86))) log_box.add_child(_wrapped("Gefährlichster Gegner: %s (%d Schaden)" % [r["enemy_name"], r["enemy_dealt"]], 12, Color(0.95, 0.75, 0.7))) if game.last_round_log.is_empty() and r.is_empty(): log_box.add_child(UiKit.label("-", 12, Color(0.55, 0.55, 0.6))) for line in game.last_round_log: log_box.add_child(_wrapped(line, 11, Color(0.6, 0.6, 0.68)))