update
This commit is contained in:
12
README.md
12
README.md
@@ -20,19 +20,19 @@ Der Spielstand liegt unter `user://spielstand.json`
|
|||||||
|
|
||||||
## Spielsysteme
|
## Spielsysteme
|
||||||
|
|
||||||
- 77 Karten in `data/karten.json`, alle Wesen, jede mit genau einem der vier Elemente; Kombos sind die Namen verschmolzener Wesen
|
- 81 Karten in `data/karten.json`, alle Wesen, jede mit genau einem der vier Elemente; Kombos sind die Namen verschmolzener Wesen
|
||||||
- Karten haben nur Element, Angriff und Leben; die Kosten sind zwei Drittel Angriff plus ein Drittel Leben, abgerundet, mindestens 1
|
- Karten haben nur Element, Angriff und Leben; die Kosten sind zwei Drittel Angriff plus ein Drittel Leben, abgerundet; je Element gibt es ein 0/2-Wesen für 0 Mana
|
||||||
- Mana: 5 im ersten Zug, jede Runde eins mehr ohne Grenze; was übrig bleibt, verfällt. Mana geht in Ziehen, Legen, Verbessern und Verschmelzen
|
- Mana: 1 im ersten Zug, jede Runde eins mehr ohne Grenze; was übrig bleibt, verfällt. Mana geht in Ziehen, Legen, Verbessern und Verschmelzen
|
||||||
- Kein Deckbau: beide ziehen vom gemeinsamen Stapel (jede Karte dreimal). Zu Beginn fünf Karten, Ziehen kostet 1 Mana und bringt eine; es kommt nur, was das Mana dieses Zugs hergibt, der Rest wandert unter den Stapel
|
- Kein Deckbau: beide ziehen vom gemeinsamen Stapel (jede Karte dreimal). Zu Beginn fünf Karten, alle im ersten Zug spielbar; jeder Zug beginnt mit einer Karte vom Stapel (nicht bei voller Hand), weiteres Ziehen kostet 2 Mana; es kommt nur, was das Mana dieses Zugs hergibt, der Rest wandert unter den Stapel
|
||||||
- Eigenschaften: Spott (2, muss zuerst angegriffen werden), Flink (2, greift sofort an), Regeneration (3, heilt am Zugende ganz) und Doppelschlag (4) lassen sich für Mana auf jede Hand- oder Brettkarte kaufen (Rechtsklick oder Y). Gelegte Wesen greifen erst im nächsten Zug an, außer sie sind flink; verletzte Wesen heilen nicht von selbst
|
- Eigenschaften: Spott (2, muss zuerst angegriffen werden), Flink (2, greift sofort an), Regeneration (3, heilt am Zugende ganz) und Doppelschlag (4) lassen sich für Mana auf jede Hand- oder Brettkarte kaufen (Rechtsklick oder Y). Gelegte Wesen greifen erst im nächsten Zug an, außer sie sind flink; verletzte Wesen heilen nicht von selbst
|
||||||
- Verdeckt legen (mittlere Maustaste auf die Handkarte oder im Kartenmenü): gleich teuer, das Wesen greift nicht an und zählt nicht für die Elementboni; aufdecken ist kostenlos, frühestens im nächsten Zug, danach greift es sofort an; ein Angriff deckt es auf
|
- Verdeckt legen (mittlere Maustaste auf die Handkarte oder im Kartenmenü): gleich teuer, das Wesen greift nicht an und zählt nicht für die Elementboni; aufdecken ist kostenlos, frühestens im nächsten Zug, danach greift es sofort an; ein Angriff deckt es auf
|
||||||
- Jede Karte gehört jedem von Anfang an. Gesammelt wird die Seltenheitsstufe, und die ist reine Optik wie bei Yu-Gi-Oh: Common matt, Rare silberner Name und Rahmen mit Glanzstreifen, Super Rare Holo-Bild, Ultra Rare goldener Name und Rahmen mit Holo-Bild, Ultimate Rare Relief, Holo auf Bild und Rahmen, Funkeln und schillernde Farben; auch auf dem Feld für alle sichtbar, Werte bleiben gleich. Verschmolzene Wesen tragen die höhere Stufe ihrer Eltern
|
- Jede Karte gehört jedem von Anfang an. Gesammelt wird die Seltenheitsstufe, und die ist reine Optik wie bei Yu-Gi-Oh: Common matt, Rare silberner Name und Rahmen mit Glanzstreifen, Super Rare Holo-Bild, Ultra Rare goldener Name und Rahmen mit Holo-Bild, Ultimate Rare Relief, Holo auf Bild und Rahmen, Funkeln und schillernde Farben; auch auf dem Feld für alle sichtbar, Werte bleiben gleich. Verschmolzene Wesen tragen die höhere Stufe ihrer Eltern
|
||||||
- Booster (100 Münzen): fünf Karten mit gewürfelter Stufe (50/25/15/8/2 %, mindestens eine Rare), höhere werten die Karte auf, der Rest wird zu Staub (50/100/200/500/1000). Aufwerten kostet 100/200/500/1000 Staub, eine Stufe abgeben bringt den Zerlegewert zurück
|
- Booster (100 Münzen): fünf Karten mit gewürfelter Stufe (50/25/15/8/2 %, mindestens eine Rare), höhere werten die Karte auf, der Rest wird zu Staub (50/100/200/500/1000). Aufwerten kostet 100/200/500/1000 Staub, eine Stufe abgeben bringt den Zerlegewert zurück
|
||||||
- Elementboni: zwei eigene offene Wesen eines Elements geben allen eigenen Wesen dieses Elements seinen Effekt (Erde Spott, Luft Flink, Wasser Regeneration, Feuer Doppelschlag); drei offene Wesen eines Elements auf dem Tisch geben dem Element +1/+1 (fällt der Bonus weg, sinkt nur das Höchstleben). Verschmolzene Wesen zählen für alle ihre Elemente und bekommen alle Boni
|
- Elementboni: zwei eigene offene Wesen eines Elements geben allen eigenen Wesen dieses Elements seinen Effekt (Erde Spott, Luft Flink, Wasser Regeneration, Feuer Doppelschlag); drei offene Wesen eines Elements auf dem Tisch geben dem Element +1/+1 (fällt der Bonus weg, sinkt nur das Höchstleben). Verschmolzene Wesen zählen für alle ihre Elemente und bekommen alle Boni
|
||||||
- Elementvorteil beim Kampf (Wasser > Feuer > Luft > Erde > Wasser): der Angreifer macht 1 Schaden mehr im Vorteil und 1 weniger im Nachteil, der Konter bleibt gleich, gegen Helden nichts; ein Wesen mit mehreren Elementen kämpft mit dem, das gegen den Gegner am besten steht
|
- Elementvorteil beim Kampf (Wasser > Feuer > Luft > Erde > Wasser): wer im Vorteil ist, macht 1 Schaden mehr, wer im Nachteil ist, 1 weniger, beim Angriff wie beim Konter, gegen Helden nichts; ein Wesen mit mehreren Elementen kämpft mit dem, das gegen den Gegner am besten steht. Ist ein Angreifer gewählt, zeigen die Gegnerkarten ihren Konter gegen ihn (grün mehr, rot weniger); über einem Ziel zeigt der Angreifer seinen Angriff mit Vorteil, und wer stirbt, trägt die Marke „stirbt“
|
||||||
- Angriffe treffen erst Wesen (Wesen mit Spott zuerst); das Leben ist nur ohne Wesen angreifbar. Nichts schlägt durch
|
- Angriffe treffen erst Wesen (Wesen mit Spott zuerst); das Leben ist nur ohne Wesen angreifbar. Nichts schlägt durch
|
||||||
- Verschmelzen: eine Karte auf eine andere ziehen und eine Sekunde halten, auf dem Brett wie auf der Hand (Gamepad: Y, „Verschmelzen mit …“). Das neue Wesen hat je Wert den besseren plus ein Drittel des schwächeren (aufgerundet), Kosten passend dazu, Elemente und Eigenschaften beider; kostet 1 Mana, verdoppelt je weiterer Verschmelzung (1, 2, 4, 8); drei oder mehr Elemente ergeben eine Chimäre
|
- Verschmelzen: eine Karte auf eine andere ziehen und eine Sekunde halten, auf dem Brett wie auf der Hand (Gamepad: Y, „Verschmelzen mit …“). Das neue Wesen hat je Wert den besseren plus ein Drittel des schwächeren (aufgerundet), Kosten passend dazu, Elemente und Eigenschaften beider; kostet 1 Mana, verdoppelt je weiterer Verschmelzung (1, 2, 4, 8); drei oder mehr Elemente ergeben eine Chimäre
|
||||||
- Duell mit ausgeloster Zugreihenfolge, wer nicht beginnt, bekommt einmalig 1 Mana; die Hand fasst 5 Karten, das Feld 5 Wesen
|
- Duell mit ausgeloster Zugreihenfolge, beide beginnen mit 1 Mana; die Hand fasst 5 Karten, das Feld 5 Wesen
|
||||||
- Schwierigkeit Leicht/Normal/Schwer: Gegner mit 25/30/35 Leben, einfache oder Vorausschau-KI, Münzen 0,75/1/1,5-fach
|
- Schwierigkeit Leicht/Normal/Schwer: Gegner mit 25/30/35 Leben, einfache oder Vorausschau-KI, Münzen 0,75/1/1,5-fach
|
||||||
- KI mit Vorausschau in zwei Stufen und Zeitbudget (150 ms), sie rechnet im Hintergrund-Thread
|
- KI mit Vorausschau in zwei Stufen und Zeitbudget (150 ms), sie rechnet im Hintergrund-Thread
|
||||||
- Kampagne: drei Kapitel mit je zehn Magiern, Bosse mit ein bis drei Merkmalen, eigenes Merkmal nach Kapitel 1
|
- Kampagne: drei Kapitel mit je zehn Magiern, Bosse mit ein bis drei Merkmalen, eigenes Merkmal nach Kapitel 1
|
||||||
|
|||||||
@@ -15,8 +15,8 @@
|
|||||||
- Gesammelt wird die Seltenheitsstufe einer Karte (Common, Rare, Super Rare, Ultra Rare, Ultimate Rare), und die ist reine Optik wie bei Yu-Gi-Oh: silberner oder goldener Name, Holo-Bild, Relief, Funkeln, Schillern; auch im Netzwerkspiel sichtbar; Fusionen tragen die höhere Stufe der Eltern
|
- Gesammelt wird die Seltenheitsstufe einer Karte (Common, Rare, Super Rare, Ultra Rare, Ultimate Rare), und die ist reine Optik wie bei Yu-Gi-Oh: silberner oder goldener Name, Holo-Bild, Relief, Funkeln, Schillern; auch im Netzwerkspiel sichtbar; Fusionen tragen die höhere Stufe der Eltern
|
||||||
- Booster öffnen (Chancen 50/25/15/8/2 %, mindestens eine Rare): höhere Stufen werten Karten auf, der Rest wird zu Staub (50/100/200/500/1000)
|
- Booster öffnen (Chancen 50/25/15/8/2 %, mindestens eine Rare): höhere Stufen werten Karten auf, der Rest wird zu Staub (50/100/200/500/1000)
|
||||||
- Staub wertet gezielt auf (100/200/500/1000), eine Stufe abgeben bringt den Zerlegewert zurück
|
- Staub wertet gezielt auf (100/200/500/1000), eine Stufe abgeben bringt den Zerlegewert zurück
|
||||||
- Kein Deckbau: alle ziehen vom gemeinsamen Stapel (jede Karte dreimal); zu Beginn fünf Karten; Ziehen kostet 1 Mana und bringt eine Karte; es kommt nur, was man sich in diesem Zug leisten kann
|
- Kein Deckbau: alle ziehen vom gemeinsamen Stapel (jede Karte dreimal); zu Beginn fünf Karten, alle im ersten Zug spielbar; jeder Zug beginnt mit einer Karte vom Stapel (nicht bei voller Hand), weiteres Ziehen kostet 2 Mana; es kommt nur, was man sich in diesem Zug leisten kann
|
||||||
- Mana für Ziehen, Legen (Kosten = 2/3 Angriff + 1/3 Leben, abgerundet, mindestens 1), Verbessern und Verschmelzen; 5 im ersten Zug, dann je Runde eins mehr; der Rest verfällt; höchstens 5 Handkarten
|
- Mana für Ziehen, Legen (Kosten = 2/3 Angriff + 1/3 Leben, abgerundet; 0/2 kostet 0), Verbessern und Verschmelzen; 1 im ersten Zug, dann je Runde eins mehr; der Rest verfällt; höchstens 5 Handkarten
|
||||||
- Karten haben nur Angriff und Leben; Eigenschaften kauft man per Rechtsklick für Mana dazu, auf Hand und Brett: Spott 2 (muss zuerst angegriffen werden), Flink 2 (greift sofort an), Regeneration 3 (heilt sich am Zugende ganz), Doppelschlag 4
|
- Karten haben nur Angriff und Leben; Eigenschaften kauft man per Rechtsklick für Mana dazu, auf Hand und Brett: Spott 2 (muss zuerst angegriffen werden), Flink 2 (greift sofort an), Regeneration 3 (heilt sich am Zugende ganz), Doppelschlag 4
|
||||||
- Gelegte Wesen greifen erst im nächsten Zug an, außer sie sind flink (auch im ersten Zug); verletzte Wesen heilen nicht von selbst
|
- Gelegte Wesen greifen erst im nächsten Zug an, außer sie sind flink (auch im ersten Zug); verletzte Wesen heilen nicht von selbst
|
||||||
- Wesen lassen sich verdeckt legen (mittlere Maustaste oder Kartenmenü); aufdecken ist frei, frühestens im nächsten Zug, dann greift es sofort an; ein Angriff deckt auf
|
- Wesen lassen sich verdeckt legen (mittlere Maustaste oder Kartenmenü); aufdecken ist frei, frühestens im nächsten Zug, dann greift es sofort an; ein Angriff deckt auf
|
||||||
@@ -28,6 +28,6 @@
|
|||||||
- Kombos sind die Namen verschmolzener Wesen (Feuer + Wasser wird Dampf, gleiche Elemente werden Inferno, Tiefsee, Berg, Orkan)
|
- Kombos sind die Namen verschmolzener Wesen (Feuer + Wasser wird Dampf, gleiche Elemente werden Inferno, Tiefsee, Berg, Orkan)
|
||||||
- Zwei eigene offene Wesen eines Elements: Sondereffekt für alle eigenen Wesen des Elements (Erde Spott, Luft Flink, Wasser Regeneration, Feuer Doppelschlag)
|
- Zwei eigene offene Wesen eines Elements: Sondereffekt für alle eigenen Wesen des Elements (Erde Spott, Luft Flink, Wasser Regeneration, Feuer Doppelschlag)
|
||||||
- Drei offene Wesen eines Elements auf dem Tisch: +1/+1 für das Element, kein Malus; die Karte zeigt vorher, was sie bekäme; verschmolzene Wesen zählen für alle ihre Elemente und bekommen alle Effekte und Boni
|
- Drei offene Wesen eines Elements auf dem Tisch: +1/+1 für das Element, kein Malus; die Karte zeigt vorher, was sie bekäme; verschmolzene Wesen zählen für alle ihre Elemente und bekommen alle Effekte und Boni
|
||||||
- Elementvorteil im Kreis: Wasser schlägt Feuer, Feuer schlägt Luft, Luft schlägt Erde, Erde schlägt Wasser (der Angreifer macht 1 Schaden mehr im Vorteil, 1 weniger im Nachteil, der Konter bleibt gleich; ein Wesen mit mehreren Elementen kämpft mit dem, das gegen den Gegner am besten steht)
|
- Elementvorteil im Kreis: Wasser schlägt Feuer, Feuer schlägt Luft, Luft schlägt Erde, Erde schlägt Wasser (wer im Vorteil ist, macht 1 Schaden mehr, wer im Nachteil ist, 1 weniger, beim Angriff wie beim Konter; ein Wesen mit mehreren Elementen kämpft mit dem, das gegen den Gegner am besten steht)
|
||||||
- Verschmelzen: eine Karte auf eine andere ziehen und eine Sekunde stillhalten, auf dem Brett oder auf der Hand (Gamepad: über das Kartenmenü); das neue erbt Elemente und Eigenschaften beider, je Wert den besseren plus ein Drittel des schwächeren (aufgerundet), Kosten folgen den Werten; Fusionskosten 1 Mana, verdoppelt je weiterer Verschmelzung
|
- Verschmelzen: eine Karte auf eine andere ziehen und eine Sekunde stillhalten, auf dem Brett oder auf der Hand (Gamepad: über das Kartenmenü); das neue erbt Elemente und Eigenschaften beider, je Wert den besseren plus ein Drittel des schwächeren (aufgerundet), Kosten folgen den Werten; Fusionskosten 1 Mana, verdoppelt je weiterer Verschmelzung
|
||||||
- Alle Karten sind Wesen: keine Zauber, keine Fallen; Effekte lösen beim Ausspielen aus
|
- Alle Karten sind Wesen: keine Zauber, keine Fallen; Effekte lösen beim Ausspielen aus
|
||||||
|
|||||||
@@ -769,6 +769,46 @@
|
|||||||
],
|
],
|
||||||
"attack": 5,
|
"attack": 5,
|
||||||
"health": 4
|
"health": 4
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"id": "f_funke",
|
||||||
|
"name": "Glutfunke",
|
||||||
|
"name_en": "Ember Spark",
|
||||||
|
"elements": [
|
||||||
|
"Feuer"
|
||||||
|
],
|
||||||
|
"attack": 0,
|
||||||
|
"health": 2
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"id": "w_tropfen",
|
||||||
|
"name": "Tautropfen",
|
||||||
|
"name_en": "Dewdrop",
|
||||||
|
"elements": [
|
||||||
|
"Wasser"
|
||||||
|
],
|
||||||
|
"attack": 0,
|
||||||
|
"health": 2
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"id": "e_kruemel",
|
||||||
|
"name": "Erdkrümel",
|
||||||
|
"name_en": "Soil Crumb",
|
||||||
|
"elements": [
|
||||||
|
"Erde"
|
||||||
|
],
|
||||||
|
"attack": 0,
|
||||||
|
"health": 2
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"id": "l_hauch",
|
||||||
|
"name": "Windhauch",
|
||||||
|
"name_en": "Breeze",
|
||||||
|
"elements": [
|
||||||
|
"Luft"
|
||||||
|
],
|
||||||
|
"attack": 0,
|
||||||
|
"health": 2
|
||||||
}
|
}
|
||||||
]
|
]
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -39,7 +39,7 @@ Stand: September 2026. Kein Enddesign, sondern die Richtung mit umgesetztem Entw
|
|||||||
|
|
||||||
Nur, was gerade zählt, ist zu sehen. Von unten nach oben:
|
Nur, was gerade zählt, ist zu sehen. Von unten nach oben:
|
||||||
|
|
||||||
- **Hand** als bis zu fünf große Karten, links der Zieh-Stapel mit „◆ 1“ (Klick zieht), rechts
|
- **Hand** als bis zu fünf große Karten, links der Zieh-Stapel mit „◆ 2“ (Klick zieht), rechts
|
||||||
„Zug beenden“.
|
„Zug beenden“.
|
||||||
- **Verschmelzen** per Ziehen: eine Hand- oder Brettkarte auf eine passende ziehen, ein
|
- **Verschmelzen** per Ziehen: eine Hand- oder Brettkarte auf eine passende ziehen, ein
|
||||||
goldener Ring füllt sich eine Sekunde lang, dann verschmelzen die beiden. Mit Gamepad über
|
goldener Ring füllt sich eine Sekunde lang, dann verschmelzen die beiden. Mit Gamepad über
|
||||||
|
|||||||
@@ -94,9 +94,9 @@ static func best_element(own: Array, other: Array) -> String:
|
|||||||
return best
|
return best
|
||||||
|
|
||||||
|
|
||||||
## Kosten einer Karte: zwei Drittel Angriff plus ein Drittel Leben, abgerundet, mindestens 1.
|
## Kosten einer Karte: zwei Drittel Angriff plus ein Drittel Leben, abgerundet (0/2 kostet nichts).
|
||||||
static func cost_of(attack: int, health: int) -> int:
|
static func cost_of(attack: int, health: int) -> int:
|
||||||
return maxi(1, (2 * attack + health) / 3)
|
return (2 * attack + health) / 3
|
||||||
|
|
||||||
|
|
||||||
## Wert eines verschmolzenen Wesens: der bessere Wert plus ein Drittel des schwächeren,
|
## Wert eines verschmolzenen Wesens: der bessere Wert plus ein Drittel des schwächeren,
|
||||||
|
|||||||
@@ -6,8 +6,8 @@ extends RefCounted
|
|||||||
const MAX_BOARD := 5
|
const MAX_BOARD := 5
|
||||||
const MAX_HAND := 5
|
const MAX_HAND := 5
|
||||||
const START_HAND := 5 # Startkarten, alle im ersten Zug bezahlbar
|
const START_HAND := 5 # Startkarten, alle im ersten Zug bezahlbar
|
||||||
const START_MANA := 5 # Mana in Zug 1; jede Runde eins mehr, ohne Grenze; Rest verfällt
|
const START_MANA := 1 # Mana in Zug 1; jede Runde eins mehr, ohne Grenze; Rest verfällt
|
||||||
const DRAW_COST := 1 # Ziehen: eine bezahlbare Karte vom Stapel
|
const DRAW_COST := 2 # Ziehen: eine bezahlbare Karte vom Stapel
|
||||||
const START_LIFE := 30
|
const START_LIFE := 30
|
||||||
const ELEMENT_PAIR := 2 # so viele eigene offene Wesen eines Elements: Sondereffekt des Elements
|
const ELEMENT_PAIR := 2 # so viele eigene offene Wesen eines Elements: Sondereffekt des Elements
|
||||||
const ELEMENT_STACK := 3 # so viele offene Wesen eines Elements auf dem Tisch: +1/+1
|
const ELEMENT_STACK := 3 # so viele offene Wesen eines Elements auf dem Tisch: +1/+1
|
||||||
@@ -131,7 +131,6 @@ class Player extends RefCounted:
|
|||||||
var board: Array = []
|
var board: Array = []
|
||||||
var energy := 0 # Mana in diesem Zug; der Rest verfällt
|
var energy := 0 # Mana in diesem Zug; der Rest verfällt
|
||||||
var max_energy := 0 # Mana zu Zugbeginn (START_MANA + eigene Züge)
|
var max_energy := 0 # Mana zu Zugbeginn (START_MANA + eigene Züge)
|
||||||
var start_bonus := 0 # einmaliges Extra-Mana für den späteren Start
|
|
||||||
var order := 0 # Platz in der Zugreihenfolge
|
var order := 0 # Platz in der Zugreihenfolge
|
||||||
var perks: Array = [] # Boss-Merkmale (siehe PERKS)
|
var perks: Array = [] # Boss-Merkmale (siehe PERKS)
|
||||||
var looks := {} # Karten-ID -> Seltenheitsstufe, reine Optik (siehe Profile)
|
var looks := {} # Karten-ID -> Seltenheitsstufe, reine Optik (siehe Profile)
|
||||||
@@ -161,7 +160,6 @@ class Player extends RefCounted:
|
|||||||
p.hand = hand.duplicate()
|
p.hand = hand.duplicate()
|
||||||
p.energy = energy
|
p.energy = energy
|
||||||
p.max_energy = max_energy
|
p.max_energy = max_energy
|
||||||
p.start_bonus = start_bonus
|
|
||||||
p.order = order
|
p.order = order
|
||||||
p.perks = perks.duplicate()
|
p.perks = perks.duplicate()
|
||||||
p.looks = looks
|
p.looks = looks
|
||||||
@@ -277,9 +275,7 @@ func start(fixed_order: bool = false) -> void:
|
|||||||
for i in players.size():
|
for i in players.size():
|
||||||
var p: Player = players[i]
|
var p: Player = players[i]
|
||||||
p.order = i
|
p.order = i
|
||||||
# Wer nicht beginnt, bekommt im ersten Zug einmalig 1 Mana extra.
|
for c in draw_cards(START_HAND, START_MANA):
|
||||||
p.start_bonus = 0 if i == 0 else 1
|
|
||||||
for c in draw_cards(START_HAND, START_MANA + p.start_bonus):
|
|
||||||
p.hand.append(c.copy())
|
p.hand.append(c.copy())
|
||||||
turn = 1
|
turn = 1
|
||||||
current_idx = 0
|
current_idx = 0
|
||||||
@@ -349,16 +345,19 @@ func begin_turn(p: Player) -> void:
|
|||||||
p.energy = p.max_energy + (1 if "extra_mana" in p.perks else 0) # der Rest vom letzten Zug ist verfallen
|
p.energy = p.max_energy + (1 if "extra_mana" in p.perks else 0) # der Rest vom letzten Zug ist verfallen
|
||||||
if p.turns == 0 and "start_energie" in p.perks:
|
if p.turns == 0 and "start_energie" in p.perks:
|
||||||
p.energy += 2
|
p.energy += 2
|
||||||
if p.start_bonus > 0:
|
|
||||||
p.energy += p.start_bonus
|
|
||||||
say("%s erhält %d Mana extra für den späteren Start." % [p.name, p.start_bonus])
|
|
||||||
p.start_bonus = 0
|
|
||||||
for c in p.board:
|
for c in p.board:
|
||||||
c.ready = true # lag eine Runde: greift jetzt an, Verdecktes darf aufgedeckt werden
|
c.ready = true # lag eine Runde: greift jetzt an, Verdecktes darf aufgedeckt werden
|
||||||
c.attacks_done = 0
|
c.attacks_done = 0
|
||||||
p.turns += 1
|
p.turns += 1
|
||||||
say("--- Zug %d: %s ---" % [turn, p.name])
|
say("--- Zug %d: %s ---" % [turn, p.name])
|
||||||
emit({"type": "turn", "player": players.find(p)})
|
emit({"type": "turn", "player": players.find(p)})
|
||||||
|
# Jeder Zug beginnt mit einer Karte vom Stapel, die man sich in diesem Zug leisten kann.
|
||||||
|
if p.hand.size() < MAX_HAND:
|
||||||
|
p.hand.append(draw_cards(1, p.max_energy)[0].copy())
|
||||||
|
say("%s zieht eine Karte." % p.name)
|
||||||
|
emit({"type": "draw", "player": players.find(p)})
|
||||||
|
else:
|
||||||
|
say("%s hat die Hand voll und zieht nicht." % p.name)
|
||||||
|
|
||||||
|
|
||||||
## Zugende: Wesen mit Regeneration heilen ganz, dann ist der andere dran.
|
## Zugende: Wesen mit Regeneration heilen ganz, dann ist der andere dran.
|
||||||
@@ -661,15 +660,15 @@ func attack(cr: Creature, target) -> String:
|
|||||||
say("%s greift %s an." % [cr.name, target.name])
|
say("%s greift %s an." % [cr.name, target.name])
|
||||||
emit({"type": "attack", "attacker": ref_of(cr), "target": ref_of(target)})
|
emit({"type": "attack", "attacker": ref_of(cr), "target": ref_of(target)})
|
||||||
damage(target, cr.power() + matchup_bonus(cr, target))
|
damage(target, cr.power() + matchup_bonus(cr, target))
|
||||||
if target is Creature and target.power() > 0: # wer nichts austeilt, kontert auch nicht; der Konter kennt keinen Elementvorteil
|
if target is Creature and target.power() > 0: # wer nichts austeilt, kontert auch nicht
|
||||||
damage(cr, target.power())
|
damage(cr, target.power() + matchup_bonus(target, cr))
|
||||||
cleanup()
|
cleanup()
|
||||||
check_end()
|
check_end()
|
||||||
return ""
|
return ""
|
||||||
|
|
||||||
|
|
||||||
## Elementvorteil beim Zuschlagen: +1 im Vorteil, -1 im Nachteil (die Verteidigung des
|
## Elementvorteil beim Zuschlagen und beim Konter: +1 im Vorteil, -1 im Nachteil,
|
||||||
## Ziels), gegen Helden gibt es keinen.
|
## gegen Helden gibt es keinen.
|
||||||
static func matchup_bonus(source: Creature, target) -> int:
|
static func matchup_bonus(source: Creature, target) -> int:
|
||||||
if not (target is Creature):
|
if not (target is Creature):
|
||||||
return 0
|
return 0
|
||||||
|
|||||||
@@ -26,7 +26,7 @@ static func snapshot(g: Game, viewer: int) -> Dictionary:
|
|||||||
"max_health": 0 if masked else c.max_health, "attacks_done": c.attacks_done,
|
"max_health": 0 if masked else c.max_health, "attacks_done": c.attacks_done,
|
||||||
"ready": c.ready, "hidden": c.hidden, "aura": c.aura})
|
"ready": c.ready, "hidden": c.hidden, "aura": c.aura})
|
||||||
ps.append({"name": p.name, "title": p.title, "is_human": p.is_human, "life": p.life, "max_life": p.max_life,
|
ps.append({"name": p.name, "title": p.title, "is_human": p.is_human, "life": p.life, "max_life": p.max_life,
|
||||||
"energy": p.energy, "max_energy": p.max_energy, "start_bonus": p.start_bonus,
|
"energy": p.energy, "max_energy": p.max_energy,
|
||||||
"order": p.order, "perks": p.perks, "looks": p.looks, "turns": p.turns,
|
"order": p.order, "perks": p.perks, "looks": p.looks, "turns": p.turns,
|
||||||
"hand": p.hand.map(card_ref) if mine else p.hand.size(), "board": board})
|
"hand": p.hand.map(card_ref) if mine else p.hand.size(), "board": board})
|
||||||
var evs := []
|
var evs := []
|
||||||
@@ -50,7 +50,6 @@ static func from_snapshot(d: Dictionary) -> Game:
|
|||||||
p.max_life = int(pd.max_life)
|
p.max_life = int(pd.max_life)
|
||||||
p.energy = int(pd.energy)
|
p.energy = int(pd.energy)
|
||||||
p.max_energy = int(pd.max_energy)
|
p.max_energy = int(pd.max_energy)
|
||||||
p.start_bonus = int(pd.start_bonus)
|
|
||||||
p.order = int(pd.order)
|
p.order = int(pd.order)
|
||||||
p.perks = Array(pd.perks)
|
p.perks = Array(pd.perks)
|
||||||
for cid in pd.get("looks", {}):
|
for cid in pd.get("looks", {}):
|
||||||
|
|||||||
@@ -16,6 +16,7 @@ var game: Game
|
|||||||
var perspective: Game.Player # der Mensch, dessen Hand unten liegt
|
var perspective: Game.Player # der Mensch, dessen Hand unten liegt
|
||||||
var fx: BattleFx
|
var fx: BattleFx
|
||||||
var selected = null # Game.Creature
|
var selected = null # Game.Creature
|
||||||
|
var hover_target = null # fremdes Wesen unter der Maus: Vorschau des Angriffs mit dem gewählten Wesen
|
||||||
var fuse_first = null # Karte oder Wesen, für das im Menü „Verschmelzen mit …“ gewählt wurde
|
var fuse_first = null # Karte oder Wesen, für das im Menü „Verschmelzen mit …“ gewählt wurde
|
||||||
var hold_time := 1.0 # so lange still über dem Ziel halten, dann verschmelzen die beiden
|
var hold_time := 1.0 # so lange still über dem Ziel halten, dann verschmelzen die beiden
|
||||||
var press_target = null # Karte oder Wesen unter der gedrückten linken Maustaste
|
var press_target = null # Karte oder Wesen unter der gedrückten linken Maustaste
|
||||||
@@ -928,6 +929,23 @@ func matchup_for(cr: Game.Creature) -> int:
|
|||||||
return 0
|
return 0
|
||||||
|
|
||||||
|
|
||||||
|
## Vorschau für den Angriff auf das Wesen unter der Maus: der Angreifer zeigt seinen Angriff mit
|
||||||
|
## Elementvorteil, und wer dabei stirbt, bekommt die Marke. Verdeckte Ziele bleiben unbekannt.
|
||||||
|
func update_attack_preview() -> void:
|
||||||
|
var target = hover_target
|
||||||
|
if selected == null or target == null or target.hidden or not game.can_attack(selected, target)[0]:
|
||||||
|
target = null
|
||||||
|
for v in enemy_views:
|
||||||
|
v.doomed = target != null and v.creature == target and selected.power() + Game.matchup_bonus(selected, target) >= target.health
|
||||||
|
v.queue_redraw()
|
||||||
|
for v in own_views:
|
||||||
|
var mine: bool = v.creature == selected
|
||||||
|
v.attack_shift = Game.matchup_bonus(selected, target) if mine and target != null else 0
|
||||||
|
var counter: int = target.power() + Game.matchup_bonus(target, selected) if target != null and target.power() > 0 else 0
|
||||||
|
v.doomed = mine and target != null and counter >= selected.health
|
||||||
|
v.queue_redraw()
|
||||||
|
|
||||||
|
|
||||||
class Deck extends Control:
|
class Deck extends Control:
|
||||||
signal clicked
|
signal clicked
|
||||||
var enabled := true
|
var enabled := true
|
||||||
@@ -1078,6 +1096,8 @@ func refresh() -> void:
|
|||||||
tile_layer.add_child(tile)
|
tile_layer.add_child(tile)
|
||||||
var looks: Dictionary = p.looks
|
var looks: Dictionary = p.looks
|
||||||
tile.hover.connect(func(card, entered):
|
tile.hover.connect(func(card, entered):
|
||||||
|
hover_target = tile.creature if entered else null
|
||||||
|
update_attack_preview()
|
||||||
if tile.secret:
|
if tile.secret:
|
||||||
show_preview(null, false)
|
show_preview(null, false)
|
||||||
else:
|
else:
|
||||||
@@ -1123,6 +1143,7 @@ func refresh() -> void:
|
|||||||
var t: CreatureView = tiles[uid]
|
var t: CreatureView = tiles[uid]
|
||||||
tiles.erase(uid)
|
tiles.erase(uid)
|
||||||
fx.fade_out(t)
|
fx.fade_out(t)
|
||||||
|
update_attack_preview()
|
||||||
deck.visible = not spectating()
|
deck.visible = not spectating()
|
||||||
deck.enabled = mine and g.can_draw(h)[0]
|
deck.enabled = mine and g.can_draw(h)[0]
|
||||||
deck.count = g.deck.size()
|
deck.count = g.deck.size()
|
||||||
|
|||||||
@@ -161,7 +161,7 @@ func _draw_full(rect: Rect2, frame: Color, seed: int) -> void:
|
|||||||
fx, HORIZONTAL_ALIGNMENT_LEFT, box.size.x - 8, tsize, max_lines, Style.TEXT)
|
fx, HORIZONTAL_ALIGNMENT_LEFT, box.size.x - 8, tsize, max_lines, Style.TEXT)
|
||||||
# Werte springen aus den unteren Ecken, dazwischen der Edelstein
|
# Werte springen aus den unteren Ecken, dazwischen der Edelstein
|
||||||
Style.stat_circle(self, Vector2(r_stat - 2, size.y - r_stat + 2), r_stat, str(card.attack), Style.AMBER, f_stat)
|
Style.stat_circle(self, Vector2(r_stat - 2, size.y - r_stat + 2), r_stat, str(card.attack), Style.AMBER, f_stat)
|
||||||
Style.stat_circle(self, Vector2(size.x - r_stat + 2, size.y - r_stat + 2), r_stat, str(card.health), Style.CRIMSON, f_stat)
|
Style.stat_circle(self, Vector2(size.x - r_stat + 2, size.y - r_stat + 2), r_stat, str(card.health), Style.LIFE, f_stat)
|
||||||
if bonus > 0:
|
if bonus > 0:
|
||||||
Style.text_outlined(self, "+%d/+%d" % [bonus, bonus], f_text, Style.GREEN, Vector2(r_stat * 2 + 4, size.y - r_stat + 2), "midleft", 3)
|
Style.text_outlined(self, "+%d/+%d" % [bonus, bonus], f_text, Style.GREEN, Vector2(r_stat * 2 + 4, size.y - r_stat + 2), "midleft", 3)
|
||||||
Style.rarity_gem(self, rarity, Vector2(size.x / 2, size.y - r_stat + 1), 8 if big else 6, seed)
|
Style.rarity_gem(self, rarity, Vector2(size.x / 2, size.y - r_stat + 1), 8 if big else 6, seed)
|
||||||
@@ -188,7 +188,7 @@ func _draw_compact(rect: Rect2, frame: Color, seed: int) -> void:
|
|||||||
Style.keyword_icon(self, k, Vector2(x + 6, size.y - 13), 6)
|
Style.keyword_icon(self, k, Vector2(x + 6, size.y - 13), 6)
|
||||||
x += 18
|
x += 18
|
||||||
Style.stat_circle(self, Vector2(11, size.y - 11), 10, str(card.attack), Style.AMBER, 12)
|
Style.stat_circle(self, Vector2(11, size.y - 11), 10, str(card.attack), Style.AMBER, 12)
|
||||||
Style.stat_circle(self, Vector2(size.x - 11, size.y - 11), 10, str(card.health), Style.CRIMSON, 12)
|
Style.stat_circle(self, Vector2(size.x - 11, size.y - 11), 10, str(card.health), Style.LIFE, 12)
|
||||||
if bonus > 0:
|
if bonus > 0:
|
||||||
Style.text_outlined(self, "+%d" % bonus, 10, Style.GREEN, Vector2(4, size.y - 29), "midleft", 3)
|
Style.text_outlined(self, "+%d" % bonus, 10, Style.GREEN, Vector2(4, size.y - 29), "midleft", 3)
|
||||||
Style.rarity_sparkle(self, rect, rarity, seed)
|
Style.rarity_sparkle(self, rect, rarity, seed)
|
||||||
|
|||||||
@@ -11,7 +11,9 @@ var width := 2
|
|||||||
var flash := false # kurz rot: wurde gerade angegriffen
|
var flash := false # kurz rot: wurde gerade angegriffen
|
||||||
var slot: Vector2 # Zielposition im Raster
|
var slot: Vector2 # Zielposition im Raster
|
||||||
var busy := false # wird gerade animiert (kein Neupositionieren)
|
var busy := false # wird gerade animiert (kein Neupositionieren)
|
||||||
var matchup := 0 # Elementvorteil des gewählten Angreifers gegen dieses Wesen (+1/-1)
|
var matchup := 0 # Elementvorteil des gewählten Angreifers gegen dieses fremde Wesen (+1/-1); die Werte zeigen dann, was ihn erwartet
|
||||||
|
var attack_shift := 0 # eigener Angreifer: Elementvorteil gegen das Ziel unter der Maus
|
||||||
|
var doomed := false # stirbt bei dem Angriff, der gerade unter der Maus liegt
|
||||||
var secret := false # verdecktes fremdes Wesen: nur der Rücken ist zu sehen
|
var secret := false # verdecktes fremdes Wesen: nur der Rücken ist zu sehen
|
||||||
var hold := 0.0 # Fortschritt des Verschmelzens, wenn eine Karte darüber gehalten wird (0..1)
|
var hold := 0.0 # Fortschritt des Verschmelzens, wenn eine Karte darüber gehalten wird (0..1)
|
||||||
|
|
||||||
@@ -66,14 +68,24 @@ func _draw() -> void:
|
|||||||
bcol = Style.RED
|
bcol = Style.RED
|
||||||
Style.border(self, rect, bcol, 4 if flash else width, 6)
|
Style.border(self, rect, bcol, 4 if flash else width, 6)
|
||||||
var fs := 11 if small else 13
|
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 name_w: float = size.x - 6
|
||||||
var nf := Style.fit_size(creature.card.title(), true, fs, name_w)
|
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))
|
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.rarity_name_color(rar, seed), Vector2(3 + name_w / 2, 6), "midtop", true)
|
Style.text(self, Style.fit(creature.card.title(), true, Style.fs(nf), name_w), nf, Style.rarity_name_color(rar, seed), Vector2(3 + name_w / 2, 6), "midtop", true)
|
||||||
|
# Elementbonus als ein Abzeichen rechts unter dem Namen; die Symbole rücken dafür nach links
|
||||||
|
var badge := ""
|
||||||
|
var bw := 0.0
|
||||||
|
if creature.aura != 0:
|
||||||
|
badge = "+%d/+%d" % [creature.aura, creature.aura] if creature.aura > 0 else "−%d/−%d" % [-creature.aura, -creature.aura]
|
||||||
|
bw = Style.FONT_BOLD.get_string_size(badge, HORIZONTAL_ALIGNMENT_LEFT, -1, Style.fs(10)).x + 8
|
||||||
|
var by := Style.fs(fs) + 13
|
||||||
|
draw_rect(Rect2(size.x - bw - 4, by, bw, 16), Color(0.05, 0.05, 0.08, 0.75))
|
||||||
|
Style.text(self, badge, 10, Style.GREEN if creature.aura > 0 else Style.RED, Vector2(size.x - 4 - bw / 2, by + 8), "center", true)
|
||||||
# Eigenschaften als Symbole: gekaufte weiß, die vom Elementpaar in der Elementfarbe
|
# Eigenschaften als Symbole: gekaufte weiß, die vom Elementpaar in der Elementfarbe
|
||||||
var icon := 7.0 if small else 9.0
|
var icon := 7.0 if small else 9.0
|
||||||
var kws := creature.keywords()
|
var kws := creature.keywords()
|
||||||
var x := size.x / 2 - (kws.size() * (icon * 2 + 6) - 6) / 2.0
|
var avail := size.x - (bw + 8 if badge != "" else 0.0)
|
||||||
|
var x := avail / 2 - (kws.size() * (icon * 2 + 6) - 6) / 2.0
|
||||||
var y := Style.fs(fs) + 14 + icon
|
var y := Style.fs(fs) + 14 + icon
|
||||||
for k in kws:
|
for k in kws:
|
||||||
var col := Color("f2f2f6")
|
var col := Color("f2f2f6")
|
||||||
@@ -83,11 +95,14 @@ func _draw() -> void:
|
|||||||
col = Style.lighter(Cards.ELEMENT_COLORS[e], 0.45)
|
col = Style.lighter(Cards.ELEMENT_COLORS[e], 0.45)
|
||||||
Style.keyword_icon(self, k, Vector2(x + icon, y), icon, col)
|
Style.keyword_icon(self, k, Vector2(x + icon, y), icon, col)
|
||||||
x += icon * 2 + 6
|
x += icon * 2 + 6
|
||||||
_draw_stats(15 if small else 17, 10 if small else 12, 12.0 if small else 14.0)
|
_draw_stats(15 if small else 17, 12.0 if small else 14.0)
|
||||||
Style.rarity_gem(self, rar, Vector2(size.x / 2, size.y - 9), 5, seed)
|
Style.rarity_gem(self, rar, Vector2(size.x / 2, size.y - 9), 5, seed)
|
||||||
if creature.hidden:
|
if creature.hidden:
|
||||||
draw_rect(rect, Color(0.05, 0.05, 0.1, 0.55))
|
draw_rect(rect, Color(0.05, 0.05, 0.1, 0.55))
|
||||||
Style.text_outlined(self, tr("verdeckt"), 12, Style.TEXT, Vector2(size.x / 2, size.y / 2), "center", 3)
|
Style.text_outlined(self, tr("verdeckt"), 12, Style.TEXT, Vector2(size.x / 2, size.y / 2), "center", 3)
|
||||||
|
if doomed:
|
||||||
|
draw_rect(Rect2(0, size.y * 0.5 - 12, size.x, 24), Color(0.05, 0.02, 0.02, 0.8))
|
||||||
|
Style.text_outlined(self, tr("stirbt"), 14, Style.RED, Vector2(size.x / 2, size.y * 0.5), "center", 3)
|
||||||
Style.rarity_sparkle(self, rect, rar, seed)
|
Style.rarity_sparkle(self, rect, rar, seed)
|
||||||
_draw_hold()
|
_draw_hold()
|
||||||
|
|
||||||
@@ -110,21 +125,26 @@ func _draw_back(rect: Rect2) -> void:
|
|||||||
draw_style_box(Style.box(Color("3c285a"), 6, bcol, 4 if flash else maxi(width, 2)), rect)
|
draw_style_box(Style.box(Color("3c285a"), 6, bcol, 4 if flash else maxi(width, 2)), rect)
|
||||||
Style.border(self, rect.grow(-10), Color("5a3c82"), 2, 6)
|
Style.border(self, rect.grow(-10), Color("5a3c82"), 2, 6)
|
||||||
Style.text(self, "?", 36, Style.GOLD, size / 2, "center", true)
|
Style.text(self, "?", 36, Style.GOLD, size / 2, "center", true)
|
||||||
if matchup != 0:
|
|
||||||
pass # unbekanntes Element: kein Vorteil anzeigen
|
|
||||||
|
|
||||||
|
|
||||||
## Angriff (grün, wenn der Elementbonus ihn hebt), Leben, Elementvorteil des Angreifers.
|
## Angriff und Leben für den Angriff, der gerade vorbereitet wird. Fremdes Wesen bei gewähltem
|
||||||
func _draw_stats(f: int, f_small: int, r: float) -> void:
|
## Angreifer: sein Konter gegen ihn (im Nachteil 1 weniger, wer 0 Angriff hat, kontert gar nicht),
|
||||||
var extra := creature.power() - creature.attack
|
## das Leben bleibt echt. Eigener Angreifer über einem Ziel: sein Angriff mit Elementvorteil.
|
||||||
var atk_col := Style.GREEN if extra > 0 else (Style.RED if extra < 0 else Style.AMBER)
|
func shown_stats() -> Array:
|
||||||
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) if extra > 0 else ("−%d" % -extra), f_small, Style.GREEN if extra > 0 else Style.RED, 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:
|
if matchup != 0:
|
||||||
var c := Vector2(size.x - 12, 12)
|
var atk := 0 if creature.power() <= 0 else maxi(0, creature.power() - matchup)
|
||||||
draw_circle(c, 11, Color("14141c"))
|
return [atk, creature.health]
|
||||||
Style.text(self, ("+%d" % matchup) if matchup > 0 else ("−%d" % -matchup), f_small + 1,
|
if attack_shift != 0:
|
||||||
Style.GREEN if matchup > 0 else Style.RED, c, "center", true)
|
return [maxi(0, creature.power() + attack_shift), creature.health]
|
||||||
|
return [creature.power(), creature.health]
|
||||||
|
|
||||||
|
|
||||||
|
## Angriff gelb, Leben blau; die Zahl wird grün, wenn sie für den aktuellen Angriff steigt, rot, wenn sie sinkt.
|
||||||
|
func _draw_stats(f: int, r: float) -> void:
|
||||||
|
var shown := shown_stats()
|
||||||
|
var atk: int = shown[0]
|
||||||
|
var hp: int = shown[1]
|
||||||
|
var atk_text := Style.GREEN if atk > creature.power() else (Style.RED if atk < creature.power() else Color.WHITE)
|
||||||
|
var hp_text := Style.GREEN if hp > creature.health else (Style.RED if hp < creature.health else Color.WHITE)
|
||||||
|
Style.stat_circle(self, Vector2(r - 1, size.y - r + 1), r, str(atk), Style.AMBER, f, atk_text)
|
||||||
|
Style.stat_circle(self, Vector2(size.x - r + 1, size.y - r + 1), r, str(hp), Style.LIFE, f, hp_text)
|
||||||
|
|||||||
@@ -68,9 +68,6 @@ func _draw() -> void:
|
|||||||
draw_circle(c, 4.5, Color(0, 0, 0, 0.35))
|
draw_circle(c, 4.5, Color(0, 0, 0, 0.35))
|
||||||
draw_arc(c, 4.5, 0, TAU, 16, Color(col, 0.6), 1.0)
|
draw_arc(c, 4.5, 0, TAU, 16, Color(col, 0.6), 1.0)
|
||||||
px += Game.ELEMENT_STACK * 13 + 2
|
px += Game.ELEMENT_STACK * 13 + 2
|
||||||
if n > Game.ELEMENT_STACK:
|
|
||||||
Style.text(self, "+%d" % (n - Game.ELEMENT_STACK), 11, Style.MUTED, Vector2(px, cy), "midleft")
|
|
||||||
px += 18
|
|
||||||
if paired(e):
|
if paired(e):
|
||||||
Style.keyword_icon(self, Cards.ELEMENT_KEYWORD[e], Vector2(px + 10, cy), 7, Style.lighter(col, 0.45))
|
Style.keyword_icon(self, Cards.ELEMENT_KEYWORD[e], Vector2(px + 10, cy), 7, Style.lighter(col, 0.45))
|
||||||
if strong(e):
|
if strong(e):
|
||||||
|
|||||||
@@ -19,7 +19,7 @@ const YELLOW := Color("ffe65a")
|
|||||||
const ORANGE := Color("ff963c")
|
const ORANGE := Color("ff963c")
|
||||||
const PURPLE := Color("8c78dc")
|
const PURPLE := Color("8c78dc")
|
||||||
const AMBER := Color("f0b429") # Angriff
|
const AMBER := Color("f0b429") # Angriff
|
||||||
const CRIMSON := Color("d64545") # Leben
|
const LIFE := Color("4a86d8") # Leben
|
||||||
const MANA := Color("3a78d2") # Kostenkristall
|
const MANA := Color("3a78d2") # Kostenkristall
|
||||||
const PRIMARY := Color("285a3c") # Hauptaktion
|
const PRIMARY := Color("285a3c") # Hauptaktion
|
||||||
const DANGER := Color("5a2828")
|
const DANGER := Color("5a2828")
|
||||||
@@ -476,11 +476,11 @@ static func cost_crystal(ci: CanvasItem, c: Vector2, r: float, cost: int, font:
|
|||||||
|
|
||||||
|
|
||||||
## Wertkreis (Angriff gelb, Leben rot) mit Zahl.
|
## Wertkreis (Angriff gelb, Leben rot) mit Zahl.
|
||||||
static func stat_circle(ci: CanvasItem, c: Vector2, r: float, value: String, color: Color, font: int) -> void:
|
static func stat_circle(ci: CanvasItem, c: Vector2, r: float, value: String, color: Color, font: int, text_col: Color = Color.WHITE) -> void:
|
||||||
ci.draw_circle(c, r + 2, Color("14141c"))
|
ci.draw_circle(c, r + 2, Color("14141c"))
|
||||||
ci.draw_circle(c, r, color)
|
ci.draw_circle(c, r, color)
|
||||||
ci.draw_circle(c + Vector2(-r * 0.25, -r * 0.3), r * 0.45, Color(1, 1, 1, 0.16))
|
ci.draw_circle(c + Vector2(-r * 0.25, -r * 0.3), r * 0.45, Color(1, 1, 1, 0.16))
|
||||||
text_outlined(ci, value, font, Color.WHITE, c, "center", 3)
|
text_outlined(ci, value, font, text_col, c, "center", 3)
|
||||||
|
|
||||||
|
|
||||||
## Eigenschaft als Symbol auf dunklem Kreis: Spott Ausrufezeichen, Flink Doppelpfeil,
|
## Eigenschaft als Symbol auf dunklem Kreis: Spott Ausrufezeichen, Flink Doppelpfeil,
|
||||||
|
|||||||
@@ -90,14 +90,14 @@ func _initialize() -> void:
|
|||||||
|
|
||||||
|
|
||||||
func test_kartenpool() -> void:
|
func test_kartenpool() -> void:
|
||||||
check(Cards.all().size() == 77, "77 Karten")
|
check(Cards.all().size() == 81, "81 Karten")
|
||||||
check(Cards.all().all(func(c): return c.elements.size() == 1 and c.elements[0] in Cards.ELEMENTS), "jede Karte hat genau ein Element")
|
check(Cards.all().all(func(c): return c.elements.size() == 1 and c.elements[0] in Cards.ELEMENTS), "jede Karte hat genau ein Element")
|
||||||
for e in Cards.ELEMENTS:
|
for e in Cards.ELEMENTS:
|
||||||
check(Cards.all().any(func(c): return c.elements == [e]), "Element vorhanden: " + e)
|
check(Cards.all().any(func(c): return c.elements == [e]), "Element vorhanden: " + e)
|
||||||
for c in Cards.all():
|
for c in Cards.all():
|
||||||
check(c.health > 0 and c.cost == maxi(1, floori((2 * c.attack + c.health) / 3.0)), "Kosten = (2 · Angriff + Leben) / 3, abgerundet: " + c.id)
|
check(c.health > 0 and c.cost == floori((2 * c.attack + c.health) / 3.0), "Kosten = (2 · Angriff + Leben) / 3, abgerundet: " + c.id)
|
||||||
check(c.keywords.is_empty() and c.text() == "", "Karten kommen ohne Eigenschaften: " + c.id)
|
check(c.keywords.is_empty() and c.text() == "", "Karten kommen ohne Eigenschaften: " + c.id)
|
||||||
check(C("f_kobold").cost == 1 and C("f_wolf").cost == 2 and C("ff_phoenix").cost == 7 and C("e_wall").cost == 1 and C("f_drache").cost == 5, "Kostenbeispiele")
|
check(C("f_funke").cost == 0 and C("f_kobold").cost == 1 and C("f_wolf").cost == 2 and C("ff_phoenix").cost == 7 and C("e_wall").cost == 1 and C("f_drache").cost == 5, "Kostenbeispiele, 0/2 kostet nichts")
|
||||||
var a := C("f_wolf")
|
var a := C("f_wolf")
|
||||||
var b := C("f_wolf")
|
var b := C("f_wolf")
|
||||||
a.keywords.append("Spott")
|
a.keywords.append("Spott")
|
||||||
@@ -111,7 +111,7 @@ func test_kombos() -> void:
|
|||||||
check(Cards.combo_name(["Feuer", "Wasser", "Erde"]) == "Chimäre", "drei Elemente sind eine Chimäre")
|
check(Cards.combo_name(["Feuer", "Wasser", "Erde"]) == "Chimäre", "drei Elemente sind eine Chimäre")
|
||||||
|
|
||||||
|
|
||||||
## Mana: 5 im ersten Zug, jede Runde eins mehr, der Rest verfällt; Legen kostet die Kartenkosten.
|
## Mana: 1 im ersten Zug, jede Runde eins mehr, der Rest verfällt; Legen kostet die Kartenkosten.
|
||||||
func test_mana_und_kosten() -> void:
|
func test_mana_und_kosten() -> void:
|
||||||
var s := setup(["f_wolf", "f_drache"])
|
var s := setup(["f_wolf", "f_drache"])
|
||||||
var g: Game = s[0]
|
var g: Game = s[0]
|
||||||
@@ -120,10 +120,10 @@ func test_mana_und_kosten() -> void:
|
|||||||
h.max_energy = 0
|
h.max_energy = 0
|
||||||
h.turns = 0
|
h.turns = 0
|
||||||
g.begin_turn(h)
|
g.begin_turn(h)
|
||||||
check(h.energy == Game.START_MANA and h.max_energy == Game.START_MANA, "erster Zug: 5 Mana")
|
check(h.energy == Game.START_MANA and h.max_energy == Game.START_MANA, "erster Zug: 1 Mana")
|
||||||
h.energy = 3 # Rest
|
h.energy = 3 # Rest
|
||||||
g.begin_turn(h)
|
g.begin_turn(h)
|
||||||
check(h.energy == Game.START_MANA + 1, "zweiter Zug: 6 Mana, der Rest ist verfallen")
|
check(h.energy == Game.START_MANA + 1, "zweiter Zug: 2 Mana, der Rest ist verfallen")
|
||||||
for i in 20:
|
for i in 20:
|
||||||
g.begin_turn(h)
|
g.begin_turn(h)
|
||||||
check(h.energy == Game.START_MANA + 21, "keine Obergrenze")
|
check(h.energy == Game.START_MANA + 21, "keine Obergrenze")
|
||||||
@@ -133,7 +133,8 @@ func test_mana_und_kosten() -> void:
|
|||||||
check(Cards.fusion_value(4, 2) == 5 and Cards.fusion_value(8, 1) == 9 and Cards.fusion_value(2, 2) == 3 and Cards.fusion_value(0, 4) == 4 and Cards.fusion_value(8, 8) == 11, "Fusionswert: besserer Wert plus ein Drittel des schwächeren")
|
check(Cards.fusion_value(4, 2) == 5 and Cards.fusion_value(8, 1) == 9 and Cards.fusion_value(2, 2) == 3 and Cards.fusion_value(0, 4) == 4 and Cards.fusion_value(8, 8) == 11, "Fusionswert: besserer Wert plus ein Drittel des schwächeren")
|
||||||
|
|
||||||
|
|
||||||
## Start: fünf bezahlbare Karten, keine Wahl. Ziehen: 1 Mana, eine bezahlbare Karte vom Stapel.
|
## Start: fünf im ersten Zug bezahlbare Karten, keine Wahl. Jeder Zug beginnt mit einer Karte;
|
||||||
|
## Ziehen: 2 Mana, eine weitere bezahlbare Karte vom Stapel.
|
||||||
func test_ziehen() -> void:
|
func test_ziehen() -> void:
|
||||||
var r := RandomNumberGenerator.new()
|
var r := RandomNumberGenerator.new()
|
||||||
r.seed = 1
|
r.seed = 1
|
||||||
@@ -141,14 +142,17 @@ func test_ziehen() -> void:
|
|||||||
check(g.deck.size() == Cards.all().size() * DeckGen.COPIES - 2 * Game.START_HAND, "Stapel: jede Karte dreimal, zehn schon ausgegeben")
|
check(g.deck.size() == Cards.all().size() * DeckGen.COPIES - 2 * Game.START_HAND, "Stapel: jede Karte dreimal, zehn schon ausgegeben")
|
||||||
for p in g.players:
|
for p in g.players:
|
||||||
check(p.hand.size() == Game.START_HAND, "Start: fünf Karten auf der Hand")
|
check(p.hand.size() == Game.START_HAND, "Start: fünf Karten auf der Hand")
|
||||||
check(p.hand.all(func(c): return c.cost <= Game.START_MANA + p.start_bonus), "nur Karten, die im ersten Zug spielbar sind")
|
check(p.hand.all(func(c): return c.cost <= Game.START_MANA), "nur Karten, die im ersten Zug spielbar sind")
|
||||||
check(p.hand.all(func(c): return c != Cards.by_id(c.id)), "eigene Exemplare")
|
check(p.hand.all(func(c): return c != Cards.by_id(c.id)), "eigene Exemplare")
|
||||||
var first: Game.Player = g.current()
|
var first: Game.Player = g.current()
|
||||||
check(g.draw(first) == "Deine Hand ist voll", "fünf Handkarten sind das Limit")
|
check(g.draw(first) == "Deine Hand ist voll", "fünf Handkarten sind das Limit")
|
||||||
first.hand.pop_back()
|
first.hand.pop_back()
|
||||||
|
check(g.draw(first) == "Nicht genug Mana", "im ersten Zug reicht das Mana nicht zum Ziehen")
|
||||||
|
first.energy = 3
|
||||||
|
first.max_energy = 3
|
||||||
var mana := first.energy
|
var mana := first.energy
|
||||||
var deck_before := g.deck.size()
|
var deck_before := g.deck.size()
|
||||||
check(g.draw(first) == "" and first.energy == mana - 1 and first.hand.size() == Game.START_HAND, "gezogen: 1 Mana, eine Karte")
|
check(g.draw(first) == "" and first.energy == mana - Game.DRAW_COST and first.hand.size() == Game.START_HAND, "gezogen: 2 Mana, eine Karte")
|
||||||
check(first.hand.back().cost <= first.max_energy and g.deck.size() == deck_before - 1, "bezahlbar; zu teure liegen wieder unten im Stapel")
|
check(first.hand.back().cost <= first.max_energy and g.deck.size() == deck_before - 1, "bezahlbar; zu teure liegen wieder unten im Stapel")
|
||||||
first.energy = 0
|
first.energy = 0
|
||||||
first.hand.pop_back()
|
first.hand.pop_back()
|
||||||
@@ -165,10 +169,25 @@ func test_ziehen() -> void:
|
|||||||
var seen_expensive := false
|
var seen_expensive := false
|
||||||
for i in 12:
|
for i in 12:
|
||||||
first.hand = []
|
first.hand = []
|
||||||
|
first.energy = 20
|
||||||
g.draw(first)
|
g.draw(first)
|
||||||
if first.hand[0].cost > 5:
|
if first.hand[0].cost > 5:
|
||||||
seen_expensive = true
|
seen_expensive = true
|
||||||
check(seen_expensive, "mit 20 Mana kommen auch teure Karten")
|
check(seen_expensive, "mit 20 Mana kommen auch teure Karten")
|
||||||
|
# Zugbeginn: eine Karte gratis, solange die Hand nicht voll ist
|
||||||
|
var g5 := Game.new_battle(r)
|
||||||
|
var p1: Game.Player = g5.current()
|
||||||
|
var p2: Game.Player = g5.enemy_of(p1)
|
||||||
|
g5.end_turn()
|
||||||
|
check(p2.hand.size() == Game.START_HAND, "volle Hand: zu Zugbeginn kommt nichts")
|
||||||
|
p2.hand.pop_back()
|
||||||
|
p2.hand.pop_back()
|
||||||
|
g5.end_turn()
|
||||||
|
p1.hand.pop_back()
|
||||||
|
g5.end_turn()
|
||||||
|
check(p2.hand.size() == Game.START_HAND - 1 and p2.hand.back().cost <= p2.max_energy, "Zugbeginn: eine bezahlbare Karte gezogen")
|
||||||
|
g5.end_turn()
|
||||||
|
check(p1.hand.size() == Game.START_HAND, "auch der Startspieler zieht zu Zugbeginn")
|
||||||
|
|
||||||
|
|
||||||
## Gelegte Wesen greifen erst im nächsten Zug an; kein Durchschlag, keine Heilung zu Zugbeginn.
|
## Gelegte Wesen greifen erst im nächsten Zug an; kein Durchschlag, keine Heilung zu Zugbeginn.
|
||||||
@@ -219,12 +238,12 @@ func test_elementvorteil() -> void:
|
|||||||
var wolf := put(o, "f_wolf") # Feuer 3/2
|
var wolf := put(o, "f_wolf") # Feuer 3/2
|
||||||
var life: int = o.life
|
var life: int = o.life
|
||||||
g.attack(tiefen, wolf)
|
g.attack(tiefen, wolf)
|
||||||
check(wolf.health <= 0 and o.life == life and tiefen.health == 6 - 3, "Wasser gegen Feuer: +1 beim Zuschlagen, der Konter bleibt gleich, nichts schlägt durch")
|
check(wolf.health <= 0 and o.life == life and tiefen.health == 6 - 2, "Wasser gegen Feuer: +1 beim Zuschlagen, der Konter macht 1 weniger, nichts schlägt durch")
|
||||||
var s3 := setup()
|
var s3 := setup()
|
||||||
var w3 := put(s3[1], "f_wolf")
|
var w3 := put(s3[1], "f_wolf")
|
||||||
var t3 := put(s3[2], "w_tiefen")
|
var t3 := put(s3[2], "w_tiefen")
|
||||||
s3[0].attack(w3, t3)
|
s3[0].attack(w3, t3)
|
||||||
check(t3.health == 6 - 2 and w3.health <= 0, "Feuer gegen Wasser: 1 weniger Schaden, der Konter bleibt gleich")
|
check(t3.health == 6 - 2 and w3.health == 2 - 5, "Feuer gegen Wasser: 1 weniger Schaden, der Konter macht 1 mehr")
|
||||||
var s2 := setup()
|
var s2 := setup()
|
||||||
var g2: Game = s2[0]
|
var g2: Game = s2[0]
|
||||||
var geist := put(s2[1], "w_geist") # Wasser 2/2
|
var geist := put(s2[1], "w_geist") # Wasser 2/2
|
||||||
@@ -451,7 +470,7 @@ func test_verschmelzen() -> void:
|
|||||||
check(hc.name == "Dampf" and hc.attack == 5 and hc.health == 7 and hc.cost == 5 and hc.fusions == 1, "Dampf auf der Hand mit 5/7 und Kosten 5")
|
check(hc.name == "Dampf" and hc.attack == 5 and hc.health == 7 and hc.cost == 5 and hc.fusions == 1, "Dampf auf der Hand mit 5/7 und Kosten 5")
|
||||||
var lava := Cards.fused(C("f_asche"), C("f_kobold"), 4, 8)
|
var lava := Cards.fused(C("f_asche"), C("f_kobold"), 4, 8)
|
||||||
check(Cards.fused(lava, C("f_kobold")).attack == 5 and Cards.fused(lava, C("f_kobold")).health == 9, "ein Kobold macht Lava 4/8 zu 5/9, nie schlechter")
|
check(Cards.fused(lava, C("f_kobold")).attack == 5 and Cards.fused(lava, C("f_kobold")).health == 9, "ein Kobold macht Lava 4/8 zu 5/9, nie schlechter")
|
||||||
check(g4.play_card(h4, hc) == "" and h4.energy == 4 and h4.board.back().name == "Dampf", "Ausspielen kostet die neuen Kosten")
|
check(g4.play_card(h4, hc) == "" and h4.energy == 9 - 5 and h4.board.back().name == "Dampf", "Ausspielen kostet die neuen Kosten")
|
||||||
check(g4.log.any(func(l): return l == "Flammenwolf und Tiefenwächter verschmelzen auf der Hand zu Dampf (5/7)."), "Verlauf")
|
check(g4.log.any(func(l): return l == "Flammenwolf und Tiefenwächter verschmelzen auf der Hand zu Dampf (5/7)."), "Verlauf")
|
||||||
|
|
||||||
|
|
||||||
@@ -475,18 +494,16 @@ func test_gleiche_regeln() -> void:
|
|||||||
r.seed = 0
|
r.seed = 0
|
||||||
var g := Game.new_battle(r)
|
var g := Game.new_battle(r)
|
||||||
var first: Game.Player = g.players[0]
|
var first: Game.Player = g.players[0]
|
||||||
check(g.current() == first and first.max_energy == Game.START_MANA and first.energy == Game.START_MANA, "Startspieler: 5 Mana, kein Bonus")
|
check(g.current() == first and first.max_energy == Game.START_MANA and first.energy == Game.START_MANA, "Startspieler: 1 Mana, kein Bonus")
|
||||||
check(g.players.all(func(p): return p.hand.size() == Game.START_HAND), "jeder beginnt mit fünf Karten")
|
check(g.players.all(func(p): return p.hand.size() == Game.START_HAND), "jeder beginnt mit fünf Karten")
|
||||||
for p in g.players:
|
for p in g.players:
|
||||||
check(p.life == Game.START_LIFE, "gleiches Leben")
|
check(p.life == Game.START_LIFE, "gleiches Leben")
|
||||||
if p != first:
|
|
||||||
check(p.start_bonus == 1, "Nachzieher: Bonus offen")
|
|
||||||
g.end_turn()
|
g.end_turn()
|
||||||
var second: Game.Player = g.players[1]
|
var second: Game.Player = g.players[1]
|
||||||
check(g.current() == second and second.energy == Game.START_MANA + 1, "Nachzieher: 5 Mana plus Ausgleich")
|
check(g.current() == second and second.energy == Game.START_MANA, "Nachzieher: ebenfalls 1 Mana, kein Ausgleich")
|
||||||
for i in 2:
|
for i in 2:
|
||||||
g.end_turn()
|
g.end_turn()
|
||||||
check(g.current() == second and second.max_energy == Game.START_MANA + 1 and second.energy == Game.START_MANA + 1, "Ausgleich nur einmal, Rest verfällt")
|
check(g.current() == second and second.max_energy == Game.START_MANA + 1 and second.energy == Game.START_MANA + 1, "zweiter Zug: 2 Mana")
|
||||||
|
|
||||||
|
|
||||||
func test_zugreihenfolge() -> void:
|
func test_zugreihenfolge() -> void:
|
||||||
@@ -756,11 +773,11 @@ func test_merkmale() -> void:
|
|||||||
var archi: Game.Player = g3.opponent
|
var archi: Game.Player = g3.opponent
|
||||||
check(g3.players[0] == g3.human, "feste Reihenfolge: Mensch beginnt")
|
check(g3.players[0] == g3.human, "feste Reihenfolge: Mensch beginnt")
|
||||||
g3.end_turn()
|
g3.end_turn()
|
||||||
check(g3.current() == archi and archi.energy == Game.START_MANA + 2 + 1, "Archimagier hat im ersten Zug 2 Mana mehr (plus Ausgleich)")
|
check(g3.current() == archi and archi.energy == Game.START_MANA + 2, "Archimagier hat im ersten Zug 2 Mana mehr")
|
||||||
var nyx: Game.Player = Campaign.opponent(5)
|
var nyx: Game.Player = Campaign.opponent(5)
|
||||||
var g4 := Game.new_battle_with(nyx, r, true)
|
var g4 := Game.new_battle_with(nyx, r, true)
|
||||||
g4.end_turn()
|
g4.end_turn()
|
||||||
check(nyx.max_energy == Game.START_MANA and nyx.energy == Game.START_MANA + 1 + 1, "Nyx bekommt 1 Mana mehr je Zug")
|
check(nyx.max_energy == Game.START_MANA and nyx.energy == Game.START_MANA + 1, "Nyx bekommt 1 Mana mehr je Zug")
|
||||||
|
|
||||||
|
|
||||||
func test_ki_zwei_schritte() -> void:
|
func test_ki_zwei_schritte() -> void:
|
||||||
|
|||||||
@@ -331,7 +331,7 @@ func test_gegnerauswahl() -> void:
|
|||||||
var opp: Game.Player = hard.game.opponent
|
var opp: Game.Player = hard.game.opponent
|
||||||
check(opp.max_life == Profile.DIFFICULTIES.schwer.life and hard.smart_ai, "Schwer: Gegner mit %d Leben, Vorausschau-KI" % Profile.DIFFICULTIES.schwer.life)
|
check(opp.max_life == Profile.DIFFICULTIES.schwer.life and hard.smart_ai, "Schwer: Gegner mit %d Leben, Vorausschau-KI" % Profile.DIFFICULTIES.schwer.life)
|
||||||
check(hard.game.human.hand.size() == Game.START_HAND and hard.hand_views.size() == Game.START_HAND, "Start: fünf Karten auf der Hand")
|
check(hard.game.human.hand.size() == Game.START_HAND and hard.hand_views.size() == Game.START_HAND, "Start: fünf Karten auf der Hand")
|
||||||
check(hard.game.human.hand.all(func(c): return c.cost <= Game.START_MANA + 1), "alle fünf sind im ersten Zug spielbar")
|
check(hard.game.human.hand.all(func(c): return c.cost <= Game.START_MANA), "alle fünf sind im ersten Zug spielbar")
|
||||||
await shot("05_starthand")
|
await shot("05_starthand")
|
||||||
check(hard.hero_panels[opp].position == BattleLayout.OPP_BOX.position, "der Gegner steht oben in der Mitte")
|
check(hard.hero_panels[opp].position == BattleLayout.OPP_BOX.position, "der Gegner steht oben in der Mitte")
|
||||||
await shot("11_kampf")
|
await shot("11_kampf")
|
||||||
@@ -507,7 +507,7 @@ func test_kampf_steuerung() -> void:
|
|||||||
g.human.hand = [Cards.by_id("f_wolf").copy()]
|
g.human.hand = [Cards.by_id("f_wolf").copy()]
|
||||||
scr.refresh()
|
scr.refresh()
|
||||||
check(scr.hand_views.size() == 1 and scr.deck.enabled, "eine Handkarte, Stapel bereit")
|
check(scr.hand_views.size() == 1 and scr.deck.enabled, "eine Handkarte, Stapel bereit")
|
||||||
# Ziehen: 1 Mana weg, eine Karte landet auf der Hand
|
# Ziehen: 2 Mana weg, eine Karte landet auf der Hand
|
||||||
var mana: int = g.human.energy
|
var mana: int = g.human.energy
|
||||||
await click(scr.deck)
|
await click(scr.deck)
|
||||||
check(g.human.energy == mana - Game.DRAW_COST and g.human.hand.size() == 2 and scr.hand_views.size() == 2, "gezogen: eine Karte auf der Hand")
|
check(g.human.energy == mana - Game.DRAW_COST and g.human.hand.size() == 2 and scr.hand_views.size() == 2, "gezogen: eine Karte auf der Hand")
|
||||||
@@ -636,7 +636,7 @@ func test_kampf_elemente_und_verschmelzen() -> void:
|
|||||||
# Rechtsklick auf die Handkarte: Menü mit Verdeckt legen und Eigenschaften, ohne Verschmelzen
|
# Rechtsklick auf die Handkarte: Menü mit Verdeckt legen und Eigenschaften, ohne Verschmelzen
|
||||||
await hover(scr.hand_views[0])
|
await hover(scr.hand_views[0])
|
||||||
await right_click_at(scr.hand_views[0].get_global_rect().get_center())
|
await right_click_at(scr.hand_views[0].get_global_rect().get_center())
|
||||||
check(scr.menu_layer.visible and find_button("Verdeckt legen ◆ 1", scr.menu_layer) != null and find_button("Spott ◆ 2", scr.menu_layer) != null, "Rechtsklick öffnet das Kartenmenü")
|
check(scr.menu_layer.visible and find_button("Verdeckt legen ◆ %d" % g.human.hand[0].cost, scr.menu_layer) != null and find_button("Spott ◆ 2", scr.menu_layer) != null, "Rechtsklick öffnet das Kartenmenü")
|
||||||
check(find_button("Verschmelzen mit … ◆ 1", scr.menu_layer) == null, "kein Verschmelzen im Rechtsklick-Menü")
|
check(find_button("Verschmelzen mit … ◆ 1", scr.menu_layer) == null, "kein Verschmelzen im Rechtsklick-Menü")
|
||||||
await shot("23_kartenmenue")
|
await shot("23_kartenmenue")
|
||||||
await right_click()
|
await right_click()
|
||||||
@@ -665,6 +665,10 @@ func test_kampf_elemente_und_verschmelzen() -> void:
|
|||||||
# Angriffsziel: Elementvorteil, verdeckte ohne Anzeige, Held gesperrt
|
# Angriffsziel: Elementvorteil, verdeckte ohne Anzeige, Held gesperrt
|
||||||
await click(scr.own_views[0])
|
await click(scr.own_views[0])
|
||||||
check(scr.selected == wolf and scr.tiles[falke.uid].matchup == 1 and scr.tiles[secret.uid].matchup == 0, "Angreifer gewählt: +1 gegen Luft, nichts gegen Verdeckte")
|
check(scr.selected == wolf and scr.tiles[falke.uid].matchup == 1 and scr.tiles[secret.uid].matchup == 0, "Angreifer gewählt: +1 gegen Luft, nichts gegen Verdeckte")
|
||||||
|
check(scr.tiles[falke.uid].shown_stats() == [falke.power() - 1, falke.health], "der Falke zeigt seinen Konter gegen den Wolf (1 weniger) und sein echtes Leben")
|
||||||
|
await hover(scr.tiles[falke.uid])
|
||||||
|
check(scr.tiles[falke.uid].doomed and not scr.own_views[0].doomed and scr.own_views[0].shown_stats()[0] == wolf.power() + 1, "über dem Falken: er stirbt, der Wolf nicht, der Wolf schlägt mit +1 zu")
|
||||||
|
await shot("23c_angreifer_gewaehlt")
|
||||||
check(not g.can_attack(wolf, scr.opponent())[0], "Held nicht angreifbar, solange Wesen stehen")
|
check(not g.can_attack(wolf, scr.opponent())[0], "Held nicht angreifbar, solange Wesen stehen")
|
||||||
await click(scr.tiles[secret.uid])
|
await click(scr.tiles[secret.uid])
|
||||||
check(not secret.hidden and not (secret in scr.opponent().board), "Angriff deckt auf und tötet den Kobold")
|
check(not secret.hidden and not (secret in scr.opponent().board), "Angriff deckt auf und tötet den Kobold")
|
||||||
@@ -686,7 +690,7 @@ func test_kampf_elemente_und_verschmelzen() -> void:
|
|||||||
check(g.human.hand.size() == 2 and g.human.hand[0].name == "Inferno" and g.human.hand[0].attack == 3 and g.human.hand[0].health == 2, "zwei Kobolde auf der Hand zu Inferno 3/2")
|
check(g.human.hand.size() == 2 and g.human.hand[0].name == "Inferno" and g.human.hand[0].attack == 3 and g.human.hand[0].health == 2, "zwei Kobolde auf der Hand zu Inferno 3/2")
|
||||||
# Gamepad-Menü (Y) bietet Verdeckt legen und Verschmelzen mit …
|
# Gamepad-Menü (Y) bietet Verdeckt legen und Verschmelzen mit …
|
||||||
scr.open_menu(g.human.hand[0], Rect2(scr.hand_views[0].position, scr.hand_views[0].size), true)
|
scr.open_menu(g.human.hand[0], Rect2(scr.hand_views[0].position, scr.hand_views[0].size), true)
|
||||||
check(find_button("Verdeckt legen ◆ 2", scr.menu_layer) != null, "Gamepad-Menü: Verdeckt legen")
|
check(find_button("Verdeckt legen ◆ %d" % g.human.hand[0].cost, scr.menu_layer) != null and g.human.hand[0].cost == 2, "Gamepad-Menü: Verdeckt legen, Inferno kostet 2")
|
||||||
await click(find_button("Verschmelzen mit … ◆ 2", scr.menu_layer))
|
await click(find_button("Verschmelzen mit … ◆ 2", scr.menu_layer))
|
||||||
check(scr.fuse_first == g.human.hand[0], "Partner wählen")
|
check(scr.fuse_first == g.human.hand[0], "Partner wählen")
|
||||||
await click(scr.hand_views[1])
|
await click(scr.hand_views[1])
|
||||||
|
|||||||
@@ -154,3 +154,4 @@ Erst die Wesen mit Spott,Taunting creatures first
|
|||||||
greift erst im nächsten Zug an,attacks next turn
|
greift erst im nächsten Zug an,attacks next turn
|
||||||
%s durch das Element,%s from its element
|
%s durch das Element,%s from its element
|
||||||
Zwei verschiedene Karten wählen,Pick two different cards
|
Zwei verschiedene Karten wählen,Pick two different cards
|
||||||
|
stirbt,dies
|
||||||
|
|||||||
|
Binary file not shown.
Reference in New Issue
Block a user