- KI-Bewertung mit Bedrohung und Führenden-Bremse (62:38 gegen die alte im Duell, gleichauf zu viert) - Balance: Sand +1/+1 statt Schild, Erde+Luft und Erde geschwächt, Wasser angehoben, Messlauf mit N=200 möglich - Einzelspieler-Kämpfe werden laufend gespeichert (voller Spielstand, viewer -1) und im Menü fortgesetzt - Karten, Deckzeilen und Kartenrücken fokussierbar: Gamepad in Deckbau, Werkstatt und Booster - Kartennamen (name_en) und Kartentexte übersetzbar, Übersetzungstest deckt cards.gd mit ab - Deck-Code DINGER1:id*anzahl mit Zwischenablage; acht neue Karten; Kampagne Kapitel 3; Elementbooster 120 Münzen - Netzwerk: Nachfolge-Host mit vollem Spielstand, Neuverbindung der anderen, Zuschauer (Sicht -2); Bot kann hosten - Große Schrift: Kartennamen, Kartentext, Knopfleisten, Gegnervorschau, Dialogtext - Anleitung 1 garantiert ein 1-Energie-Wesen; Tests: DINGER_ONLY für einzelne Oberflächentests - Oberflächentest auch auf Xephyr mit llvmpipe (wie Xvfb in der CI) grün Co-Authored-By: Claude Fable 5.1 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_01QPgKvy5W9WRNFHjkm5QsHx
90 lines
6.3 KiB
GDScript
90 lines
6.3 KiB
GDScript
class_name Campaign
|
|
## Kampagne: zehn benannte Magier in drei Kapiteln, jede Stufe mit mehr Gegnern am Tisch.
|
|
|
|
const STAGES := [
|
|
{"name": "Fenn", "title": "Kobold-Zähmer", "elements": ["Feuer"], "extra": 0, "reward": 100, "perk": "feuer_angriff"},
|
|
{"name": "Mara", "title": "Gezeitenhexe", "elements": ["Wasser"], "extra": 0, "reward": 100, "perk": "leben_35"},
|
|
{"name": "Borin", "title": "Steinfaust", "elements": ["Erde"], "extra": 1, "reward": 150, "perk": "waechter_leben"},
|
|
{"name": "Liska", "title": "Windläuferin", "elements": ["Luft"], "extra": 1, "reward": 150, "perk": "flink_angriff"},
|
|
{"name": "Vulkar", "title": "Herr der Lava", "elements": ["Feuer", "Erde"], "extra": 2, "reward": 200, "perk": "zauber_schaden"},
|
|
{"name": "Nyx", "title": "Sturmruferin", "elements": ["Wasser", "Luft"], "extra": 2, "reward": 200, "perk": "extra_karten"},
|
|
{"name": "Ignis", "title": "Inferno-Priester", "elements": ["Feuer"], "extra": 3, "reward": 250, "perk": "resonanz_doppelt"},
|
|
{"name": "Thalassa", "title": "Tiefseekönigin", "elements": ["Wasser"], "extra": 3, "reward": 250, "perk": "schild_wesen"},
|
|
{"name": "Zephyra", "title": "Blitzkaiserin", "elements": ["Feuer", "Luft"], "extra": 4, "reward": 300, "perk": "alle_flink"},
|
|
{"name": "Archimagier", "title": "Meister der Elemente", "elements": ["Erde", "Luft"], "extra": 4, "reward": 500, "perk": "start_energie"},
|
|
]
|
|
|
|
|
|
## Kapitel 2: die Magier kehren mit zwei Merkmalen und mehr Gefolge zurück.
|
|
const STAGES2 := [
|
|
{"name": "Fenn", "title": "Flammenzähmer", "elements": ["Feuer"], "extra": 1, "reward": 300, "perks": ["feuer_angriff", "start_energie"]},
|
|
{"name": "Mara", "title": "Herrin der Gezeiten", "elements": ["Wasser"], "extra": 1, "reward": 300, "perks": ["leben_35", "extra_karten"]},
|
|
{"name": "Borin", "title": "Fels der Ewigkeit", "elements": ["Erde"], "extra": 2, "reward": 350, "perks": ["waechter_leben", "schild_wesen"]},
|
|
{"name": "Liska", "title": "Sturmläuferin", "elements": ["Luft"], "extra": 2, "reward": 350, "perks": ["flink_angriff", "alle_flink"]},
|
|
{"name": "Vulkar", "title": "Aschekönig", "elements": ["Feuer", "Erde"], "extra": 3, "reward": 400, "perks": ["zauber_schaden", "feuer_angriff"]},
|
|
{"name": "Nyx", "title": "Gewitterruferin", "elements": ["Wasser", "Luft"], "extra": 3, "reward": 400, "perks": ["extra_karten", "flink_angriff"]},
|
|
{"name": "Ignis", "title": "Inferno-Erzpriester", "elements": ["Feuer"], "extra": 4, "reward": 450, "perks": ["resonanz_doppelt", "zauber_schaden"]},
|
|
{"name": "Thalassa", "title": "Kaiserin der Tiefe", "elements": ["Wasser"], "extra": 4, "reward": 450, "perks": ["schild_wesen", "leben_35"]},
|
|
{"name": "Zephyra", "title": "Blitzkaiserin", "elements": ["Feuer", "Luft"], "extra": 5, "reward": 500, "perks": ["alle_flink", "start_energie"]},
|
|
{"name": "Archimagier", "title": "Herr aller Elemente", "elements": ["Erde", "Luft"], "extra": 5, "reward": 800, "perks": ["start_energie", "resonanz_doppelt", "extra_karten"]},
|
|
]
|
|
|
|
|
|
## Kapitel 3: drei Merkmale, volle Tische, die stärksten Decks.
|
|
const STAGES3 := [
|
|
{"name": "Fenn", "title": "Aschefürst", "elements": ["Feuer"], "extra": 2, "reward": 600, "perks": ["feuer_angriff", "start_energie", "zauber_schaden"]},
|
|
{"name": "Mara", "title": "Sturmflut", "elements": ["Wasser"], "extra": 2, "reward": 600, "perks": ["leben_35", "extra_karten", "schild_wesen"]},
|
|
{"name": "Borin", "title": "Berg selbst", "elements": ["Erde"], "extra": 3, "reward": 700, "perks": ["waechter_leben", "schild_wesen", "leben_35"]},
|
|
{"name": "Liska", "title": "Windbraut", "elements": ["Luft"], "extra": 3, "reward": 700, "perks": ["flink_angriff", "alle_flink", "extra_karten"]},
|
|
{"name": "Vulkar", "title": "Magmakaiser", "elements": ["Feuer", "Erde"], "extra": 4, "reward": 800, "perks": ["zauber_schaden", "feuer_angriff", "waechter_leben"]},
|
|
{"name": "Nyx", "title": "Orkanmutter", "elements": ["Wasser", "Luft"], "extra": 4, "reward": 800, "perks": ["extra_karten", "flink_angriff", "resonanz_doppelt"]},
|
|
{"name": "Ignis", "title": "Sonnenpriester", "elements": ["Feuer"], "extra": 5, "reward": 900, "perks": ["resonanz_doppelt", "zauber_schaden", "start_energie"]},
|
|
{"name": "Thalassa", "title": "Herz der Tiefe", "elements": ["Wasser"], "extra": 5, "reward": 900, "perks": ["schild_wesen", "leben_35", "resonanz_doppelt"]},
|
|
{"name": "Zephyra", "title": "Gewitterkaiserin", "elements": ["Feuer", "Luft"], "extra": 5, "reward": 1000, "perks": ["alle_flink", "start_energie", "zauber_schaden"]},
|
|
{"name": "Archimagier", "title": "Ewiger Meister", "elements": ["Erde", "Luft"], "extra": 5, "reward": 1200, "perks": ["start_energie", "resonanz_doppelt", "extra_karten", "leben_35"]},
|
|
]
|
|
|
|
const CHAPTERS := [STAGES, STAGES2, STAGES3]
|
|
|
|
# Mindeststärke der Gegnerdecks je Stufe; nie unter der Stärke des eigenen Decks.
|
|
const MIN_RATING := [1.2, 1.3, 1.5, 1.6, 1.8, 1.9, 2.1, 2.2, 2.4, 2.6]
|
|
const MIN_RATING2 := [2.2, 2.3, 2.5, 2.6, 2.8, 2.9, 3.0, 3.1, 3.2, 3.4]
|
|
const MIN_RATING3 := [3.2, 3.3, 3.5, 3.6, 3.8, 3.9, 4.0, 4.1, 4.2, 4.4]
|
|
const MIN_RATINGS := [MIN_RATING, MIN_RATING2, MIN_RATING3]
|
|
|
|
|
|
static func target_rating(stage_index: int, player_rating: float) -> float:
|
|
var base: float = MIN_RATINGS[chapter(stage_index) - 1][stage_index % STAGES.size()]
|
|
return maxf(base, player_rating)
|
|
|
|
|
|
static func total() -> int:
|
|
return STAGES.size() * CHAPTERS.size()
|
|
|
|
|
|
static func chapter(stage: int) -> int:
|
|
return stage / STAGES.size() + 1
|
|
|
|
|
|
## Stufe mit einheitlichem Feld "perks".
|
|
static func stage(i: int) -> Dictionary:
|
|
if i < STAGES.size():
|
|
var st: Dictionary = STAGES[i].duplicate()
|
|
st["perks"] = [st.perk]
|
|
return st
|
|
return CHAPTERS[chapter(i) - 1][i % STAGES.size()]
|
|
|
|
|
|
## Gegner einer Stufe, Decks auf die Zielstärke (Stufe oder eigenes Deck, was höher ist).
|
|
static func opponents(stage_index: int, r: RandomNumberGenerator, player_rating: float = 0.0) -> Array:
|
|
var st := stage(stage_index)
|
|
var target := target_rating(stage_index, player_rating)
|
|
var life: int = 35 if "leben_35" in st.perks else Game.START_LIFE
|
|
var boss := Game.Player.new(st.name, Game.build_opponent_deck_rated(r, st.elements, target), false, life, st.title)
|
|
boss.perks = Array(st.perks)
|
|
var out := [boss]
|
|
var extra: int = mini(st.extra, Game.MAX_OPPONENTS - 1)
|
|
for k in extra:
|
|
out.append(Game.random_opponent(r, k + 1, Game.START_LIFE, target))
|
|
return out
|