class_name CreatureView extends Control ## Zeichnet ein Wesen auf dem Feld. Bleibt über Zustandsänderungen bestehen (für Animationen). signal clicked(view: CreatureView) signal hover(card: Cards.Card, entered: bool) var creature: Game.Creature var border = null var width := 2 var flash := false # kurz rot: wurde gerade angegriffen var slot: Vector2 # Zielposition im Raster var busy := false # wird gerade animiert (kein Neupositionieren) var mark := "" # Feldkombo, die dieses Wesen als Partner auslösen würde var matchup := 0 # Elementvorteil des gewählten Angreifers gegen dieses Wesen (+1/-1) func _init(cr: Game.Creature, sz: Vector2, b = null, w: int = 2) -> void: creature = cr border = b width = w custom_minimum_size = sz size = sz pivot_offset = sz / 2 set_process(Style.rarity_animated(rarity())) # bewegter Glanz mouse_filter = Control.MOUSE_FILTER_STOP mouse_entered.connect(func(): hover.emit(creature.card, true)) mouse_exited.connect(func(): hover.emit(creature.card, false)) func _process(_delta: float) -> void: queue_redraw() func _gui_input(event: InputEvent) -> void: if event is InputEventMouseButton and event.pressed and event.button_index == MOUSE_BUTTON_LEFT: accept_event() clicked.emit(self) func rarity() -> String: var owner = creature.owner() return Cards.RARITIES[int(owner.looks.get(creature.card.id, 0)) if owner != null else 0] func _draw() -> void: var rect := Rect2(Vector2.ZERO, size) var small := size.x < 100 var mini := size.x < 60 var rar := rarity() var seed := hash(creature.card.id) + creature.uid if rar != "gewöhnlich": Style.glow(self, rect, Style.rarity_color(rar, seed), 6, 4 if mini else 6) Style.fill_elements(self, rect, creature.card.elements, 6) if not mini: Style.glyph(self, creature.card, Vector2(size.x / 2, size.y * 0.5), size.x * 0.75, 0.3) Style.rarity_sheen(self, rect, rar, seed) var bcol: Color = border if border != null else Style.rarity_frame(rar, seed) if flash: bcol = Style.RED Style.border(self, rect, bcol, 4 if flash else width, 6) if mark != "": Style.border(self, rect.grow(3), Style.GOLD, 3, 8) if mini: _draw_mini() Style.rarity_sparkle(self, rect, rar, seed) return var fs := 11 if small else 13 var name_w: float = size.x - (30 if matchup != 0 else 6) # Platz für den Vorteilskreis oben rechts var nf := Style.fit_size(creature.card.title(), true, fs, name_w) draw_rect(Rect2(2, 2, size.x - 4, Style.fs(fs) + 8), Color(0.05, 0.05, 0.08, 0.7)) Style.text(self, Style.fit(creature.card.title(), true, Style.fs(nf), name_w), nf, Style.TEXT, Vector2(3 + name_w / 2, 6), "midtop", true) # Schlüsselwörter als Symbole var icon := 7.0 if small else 9.0 var kws: Array[String] = [] for k in Cards.KEYWORDS: if k in creature.card.keywords: kws.append(k) if creature.shield and not ("Schild" in kws): kws.append("Schild") var x := size.x / 2 - (kws.size() * (icon * 2 + 6) - 6) / 2.0 var y := Style.fs(fs) + 14 + icon for k in kws: Style.keyword_icon(self, k, Vector2(x + icon, y), icon) x += icon * 2 + 6 _draw_stats(15 if small else 17, 10 if small else 12, 12.0 if small else 14.0) Style.rarity_gem(self, rar, Vector2(size.x / 2, size.y - 9), 5, seed) if mark != "": var w := Style.FONT_BOLD.get_string_size(tr(mark), HORIZONTAL_ALIGNMENT_LEFT, -1, Style.fs(11)).x + 14 draw_style_box(Style.box(Color("14141c"), 6, Style.GOLD, 1), Rect2(size.x / 2 - w / 2, -9, w, 18)) Style.text(self, tr(mark), 11, Style.GOLD, Vector2(size.x / 2, 0), "center", true) if creature.frozen: draw_rect(rect, Color(0.55, 0.78, 1.0, 0.35)) Style.text_outlined(self, "❄", 22 if small else 28, Color("dff2ff"), size / 2, "center", 3) Style.rarity_sparkle(self, rect, rar, seed) ## Angriff (grün mit „+n“, wenn Resonanz, Feld oder Merkmale ihn heben), Leben, Elementvorteil. func _draw_stats(f: int, f_small: int, r: float) -> void: var extra := creature.power() - creature.attack var atk_col := Style.GREEN if extra > 0 else Style.AMBER Style.stat_circle(self, Vector2(r - 1, size.y - r + 1), r, str(creature.power()), atk_col, f) if extra > 0: Style.text_outlined(self, "+%d" % extra, f_small, Style.GREEN, Vector2(r * 2 + 3, size.y - r + 1), "midleft", 3) var hp_col := Style.CRIMSON if creature.health < creature.max_health else Color("b84a4a") Style.stat_circle(self, Vector2(size.x - r + 1, size.y - r + 1), r, str(creature.health), hp_col, f) if matchup != 0: var c := Vector2(size.x - 12, 12) draw_circle(c, 11, Color("14141c")) Style.text(self, ("+%d" % matchup) if matchup > 0 else ("−%d" % -matchup), f_small + 1, Style.GREEN if matchup > 0 else Style.RED, c, "center", true) ## Sehr kleine Kacheln (4 oder 5 Gegner): nur Kürzel und Werte, Details per Vorschau oder Lupe. func _draw_mini() -> void: var letters: Array[String] = [] if creature.taunt(): letters.append("W") if creature.shield: letters.append("S") if creature.attacks_per_turn() == 2: letters.append("2") if creature.frozen: letters.append("❄") Style.text(self, " ".join(letters), 10, Color("ebebf5"), Vector2(size.x / 2, 3), "midtop", true) var extra := creature.power() - creature.attack Style.text_outlined(self, str(creature.power()), 13, Style.GREEN if extra > 0 else Style.YELLOW, Vector2(9, size.y - 9), "center", 3) var hp_col := Style.RED if creature.health < creature.max_health else Color("ffc8c8") Style.text_outlined(self, str(creature.health), 13, hp_col, Vector2(size.x - 9, size.y - 9), "center", 3) if matchup != 0: Style.text(self, ("+%d" % matchup) if matchup > 0 else ("−%d" % -matchup), 10, Style.GREEN if matchup > 0 else Style.RED, Vector2(size.x - 3, 2), "topright", true) if creature.frozen: draw_rect(Rect2(Vector2.ZERO, size), Color(0.55, 0.78, 1.0, 0.35))