update
Some checks failed
Tests / headless (push) Has been cancelled
Tests / fenster-schnell (push) Has been cancelled
Tests / fenster-voll (push) Has been cancelled
Tests / balance (push) Has been cancelled

This commit is contained in:
team3
2026-10-03 01:17:27 +02:00
parent 24a03ed1ee
commit 5f9442497a
27 changed files with 1040 additions and 871 deletions

View File

@@ -24,18 +24,27 @@ const COMBOS := {
# Elementkreis: Wasser löscht Feuer, Feuer verbrennt Luft, Luft trägt Erde ab, Erde saugt Wasser auf.
const BEATS := {"Wasser": "Feuer", "Feuer": "Luft", "Luft": "Erde", "Erde": "Wasser"}
# Seltenheit ist reine Optik: jede Karte gibt es in jeder Stufe, die Werte bleiben gleich.
const RARITIES: Array[String] = ["gewöhnlich", "selten", "episch", "legendär", "mythisch"]
# Stufen wie bei Yu-Gi-Oh: Common grau, Rare silber, Super Rare blau, Ultra Rare gold,
# Ultimate Rare schillert durch alle Farben.
const RARITIES: Array[String] = ["Common", "Rare", "Super Rare", "Ultra Rare", "Ultimate Rare"]
const RARITY_COLORS := {
"gewöhnlich": Color("aaaaaa"),
"selten": Color("4682e6"),
"episch": Color("aa46dc"),
"legendär": Color("f0aa28"),
"mythisch": Color("ff5a8c"),
"Common": Color("aaaaaa"),
"Rare": Color("c8d0dc"),
"Super Rare": Color("4682e6"),
"Ultra Rare": Color("f0aa28"),
"Ultimate Rare": Color("ff5a8c"),
}
# Schlüsselwörter haben Karten nicht von Haus aus; sie werden für Mana dazugekauft (Game.upgrade).
const KEYWORDS: Array[String] = ["Schild", "Doppelschlag"]
const KEYWORD_COST := {"Schild": 3, "Doppelschlag": 4}
const KEYWORD_TEXT := {"Schild": "Blockt den ersten Schaden", "Doppelschlag": "Greift zweimal je Zug"}
# Eigenschaften haben Karten nicht von Haus aus; sie werden für Mana dazugekauft (Game.upgrade)
# oder kommen vom Elementpaar der eigenen Seite (ELEMENT_KEYWORD, siehe Game.Creature.has).
const KEYWORDS: Array[String] = ["Spott", "Flink", "Regeneration", "Doppelschlag"]
const KEYWORD_COST := {"Spott": 2, "Flink": 2, "Regeneration": 3, "Doppelschlag": 4}
const KEYWORD_TEXT := {
"Spott": "Muss zuerst angegriffen werden",
"Flink": "Greift sofort an",
"Regeneration": "Heilt sich am Zugende ganz",
"Doppelschlag": "Greift zweimal je Zug",
}
const ELEMENT_KEYWORD := {"Erde": "Spott", "Luft": "Flink", "Wasser": "Regeneration", "Feuer": "Doppelschlag"}
const DATA_PATH := "res://data/karten.json"
@@ -85,17 +94,16 @@ static func best_element(own: Array, other: Array) -> String:
return best
## Welches Element ein Element schlägt (und von welchem es geschlagen wird).
static func beaten_by(element: String) -> String:
for e in BEATS:
if BEATS[e] == element:
return e
return ""
## Kosten einer Karte: Angriff plus Leben, halbiert und aufgerundet.
## Kosten einer Karte: zwei Drittel Angriff plus ein Drittel Leben, abgerundet, mindestens 1.
static func cost_of(attack: int, health: int) -> int:
return ceili((attack + health) / 2.0)
return maxi(1, (2 * attack + health) / 3)
## Wert eines verschmolzenen Wesens: der bessere Wert plus ein Drittel des schwächeren,
## aufgerundet. Bei gleichen Werten sind das zwei Drittel der Summe, sonst mehr; nie schlechter
## als das stärkere Wesen, und jeder Partner ab 1 bringt mindestens +1.
static func fusion_value(a: int, b: int) -> int:
return maxi(a, b) + ceili(mini(a, b) / 3.0)
## Name des verschmolzenen Wesens: die Kombo seiner Elemente (ein Element zählt doppelt).
@@ -103,9 +111,13 @@ static func fusion_name(elements: Array) -> String:
return combo_name(elements if elements.size() >= 2 else [elements[0], elements[0]])
## Karte des verschmolzenen Wesens: Elemente und Schlüsselwörter beider Karten, die Werte
## bestimmt Game.fuse, eine Verschmelzung mehr als der erfahrenere Elternteil.
static func fused(a: Card, b: Card, attack: int, health: int) -> Card:
## Karte des verschmolzenen Wesens: Elemente und Eigenschaften beider Karten, Werte nach
## fusion_value (oder die übergebenen), eine Verschmelzung mehr als der erfahrenere Elternteil.
static func fused(a: Card, b: Card, attack: int = -1, health: int = -1) -> Card:
if attack < 0:
attack = fusion_value(a.attack, b.attack)
if health < 0:
health = fusion_value(a.health, b.health)
var els := []
for e in a.elements + b.elements:
if not (e in els):
@@ -122,6 +134,7 @@ static func fused(a: Card, b: Card, attack: int, health: int) -> Card:
if k in a.keywords or k in b.keywords:
c.keywords.append(k)
c.fusions = maxi(a.fusions, b.fusions) + 1
c.look = maxi(a.look, b.look) # die höhere Stufe gewinnt; Game.fuse rechnet die Sammlung ein
return c
@@ -145,9 +158,10 @@ class Card extends RefCounted:
var elements: Array
var attack: int = 0
var health: int = 0
var cost: int = 0 # abgeleitet: (Angriff + Leben) / 2, aufgerundet
var cost: int = 0 # abgeleitet: (2 · Angriff + Leben) / 3, abgerundet, mindestens 1
var keywords: Array = [] # dazugekauft, je Exemplar
var fusions := 0 # wie oft verschmolzen (Verschmelzen kostet 1, 2, 4, 8 …)
var look := -1 # Seltenheitsstufe verschmolzener Karten (die höhere der Eltern); -1: aus der Sammlung des Besitzers
func to_dict() -> Dictionary:
var d := {"id": id, "name": name, "name_en": name_en, "elements": elements, "attack": attack, "health": health}
@@ -155,8 +169,14 @@ class Card extends RefCounted:
d["keywords"] = keywords
if fusions > 0:
d["fusions"] = fusions
if look >= 0:
d["look"] = look
return d
## Stufe dieser Karte für einen Besitzer mit dieser Sammlung (Game.Player.looks).
func rarity_in(looks: Dictionary) -> String:
return Cards.RARITIES[look if look >= 0 else int(looks.get(id, 0))]
static func from_dict(d: Dictionary) -> Card:
var c := Card.new()
c.id = d.id
@@ -168,6 +188,7 @@ class Card extends RefCounted:
c.cost = Cards.cost_of(c.attack, c.health)
c.keywords = Array(d.get("keywords", []))
c.fusions = int(d.get("fusions", 0))
c.look = int(d.get("look", -1))
return c
## Eigenes Exemplar (Hand, Brett): Schlüsselwörter gehören dem Exemplar, nicht dem Pool.
@@ -190,7 +211,7 @@ class Card extends RefCounted:
func fusion_cost() -> int:
return 1 << fusions
## Kartentext: die gekauften Schlüsselwörter.
## Kartentext: die gekauften Eigenschaften.
func text() -> String:
if keywords.is_empty():
return ""