update
Tests / headless (push) Waiting to run
Tests / fenster-schnell (push) Waiting to run
Tests / fenster-voll (push) Skipped
Tests / balance (push) Skipped

This commit is contained in:
team3 committed 2026-10-15 17:16:01 +02:00
1 parent 1d563b9eec
commit 04fe9716e8
22 files changed
+764 -151

No files matched your search

+35 -15
View File
@@ -1,11 +1,13 @@
class_name Campaign
## Kampagne: fünf Kapitel mit je zehn benannten Magiern, der zehnte ist der Boss. Kapitel 1 spielt
## neutrale Karten, Kapitel 2 bis 5 je ein Element; jeder Gegner spielt 30 Karten seines Elements
## nach Manakurve (DeckGen.curve_deck) mit steigendem Kostendeckel (COST_CAP), in der Stufe seines Kapitels (Kapitel 1 und 2 Common, dann je Kapitel eine höher, Kapitel 5
## Ultra Rare). Mit jedem offenen
## Kapitel gibt es den Booster seines Elements zu kaufen (Profile.booster_unlocked).
## Kampagne: zehn Kapitel mit je zehn benannten Magiern, der zehnte ist der Boss. Kapitel 1 spielt
## neutrale Karten, Kapitel 2 bis 5 je ein Element; Kapitel 6 bis 10 wiederholen die Elemente mit
## Effektkarten (Eigenschaften, DeckGen.effect_deck). Jeder Gegner spielt 30 Karten seines Elements
## nach Manakurve mit steigendem Kostendeckel (COST_CAP), in der Stufe seines Kapitels (rarity_of).
## Mit jedem offenen Kapitel der ersten Runde gibt es den Booster seines Elements
## (Profile.booster_unlocked); nach Kapitel 5 öffnet die Werkstatt (Profile.workshop_unlocked).
const STAGES_PER_CHAPTER := 10
const ROUNDS := 2 # Runde 1: Grundkarten (Kapitel 1 bis 5), Runde 2: Effektkarten (6 bis 10)
const CHAPTER_ELEMENTS: Array[String] = [Cards.NEUTRAL, "Feuer", "Wasser", "Luft", "Erde"]
const NAMES: Array[String] = ["Fenn", "Mara", "Borin", "Liska", "Vulkar", "Nyx", "Ignis", "Thalassa", "Zephyra", "Archimagier"]
const TITLES := {
@@ -22,8 +24,12 @@ const COST_CAP: Array[int] = [3, 4, 4, 5, 5, 6, 7, 8, 9, 10]
const PERK_ORDER: Array[String] = ["feuer_angriff", "leben_35", "wesen_angriff", "ziehen_gratis", "wesen_leben", "extra_mana", "kein_nachteil", "alle_flink", "alle_flink", "start_energie"]
static func chapters() -> int:
return CHAPTER_ELEMENTS.size() * ROUNDS
static func total() -> int:
return STAGES_PER_CHAPTER * CHAPTER_ELEMENTS.size()
return STAGES_PER_CHAPTER * chapters()
static func chapter(stage: int) -> int:
@@ -31,12 +37,19 @@ static func chapter(stage: int) -> int:
static func element_of(chapter_no: int) -> String:
return CHAPTER_ELEMENTS[chapter_no - 1]
return CHAPTER_ELEMENTS[(chapter_no - 1) % CHAPTER_ELEMENTS.size()]
## Merkmale je Gegner: eins, ab Kapitel 3 zwei, in Kapitel 5 drei.
## Merkmale je Gegner: eins, ab Kapitel 3 zwei, ab Kapitel 5 drei.
static func perk_count(chapter_no: int) -> int:
return (chapter_no + 1) / 2
return mini(3, (chapter_no + 1) / 2)
## Eigenschaften je Gegnerkarte: Kapitel 1 bis 5 keine, 6 und 7 eine, ab 8 zwei.
static func keyword_count(chapter_no: int) -> int:
if chapter_no <= CHAPTER_ELEMENTS.size():
return 0
return 1 if chapter_no <= CHAPTER_ELEMENTS.size() + 2 else 2
## Stufe i: Name, Titel, Leben, Belohnung (Kapitel 1: 100 bis 300, Boss 500; je Kapitel 250 mehr),
@@ -48,25 +61,32 @@ static func stage(i: int) -> Dictionary:
for n in perk_count(c):
perks.append(PERK_ORDER[(k + 3 * n) % STAGES_PER_CHAPTER])
var base := 100 + 250 * (c - 1)
return {"name": NAMES[k], "title": TITLES[element_of(c)][k], "life": LIFE[k],
var title: String = TITLES[element_of(c)][k] + (" II" if c > CHAPTER_ELEMENTS.size() else "")
return {"name": NAMES[k], "title": title, "life": LIFE[k],
"reward": base + (400 if k == STAGES_PER_CHAPTER - 1 else 50 * (k / 2)),
"perks": perks, "element": element_of(c), "max_cost": COST_CAP[k]}
"perks": perks, "element": element_of(c), "max_cost": COST_CAP[k], "keywords": keyword_count(c)}
## Gegner einer Stufe: Leben und Merkmale der Stufe, 30 Karten seines Elements nach Manakurve bis
## max_cost, in der Stufe des Kapitels (rarity_of).
## max_cost (ab Kapitel 6 Effektkarten), in der Stufe des Kapitels (rarity_of).
static func opponent(stage_index: int, r: RandomNumberGenerator = null) -> Game.Player:
var st := stage(stage_index)
var boss := Game.Player.new(st.name, false, int(st.life), st.title)
boss.perks = Array(st.perks)
if r == null:
r = Game.make_rng()
boss.deck = DeckGen.curve_deck(st.element, r, int(st.max_cost))
if int(st.keywords) > 0:
boss.deck = DeckGen.effect_deck(st.element, r, int(st.max_cost), int(st.keywords))
else:
boss.deck = DeckGen.curve_deck(st.element, r, int(st.max_cost))
for id in boss.deck:
boss.looks[id] = rarity_of(chapter(stage_index))
return boss
## Seltenheitsstufe der Gegnerkarten: Kapitel 1 und 2 Common, dann je Kapitel eine höher.
## Seltenheitsstufe der Gegnerkarten: Kapitel 1 und 2 Common, dann je Kapitel eine höher bis Ultra
## Rare; Kapitel 6 bis 9 Ultra Rare, Kapitel 10 Ultimate Rare.
static func rarity_of(chapter_no: int) -> int:
return maxi(0, chapter_no - 2)
if chapter_no >= chapters():
return Cards.RARITIES.size() - 1
return mini(3, maxi(0, chapter_no - 2))