feat(quests): Quests als Trigger mit Zaehler

Eine Quest IST ein Trigger mit count = N — kein zweiter Mechanismus.
Gezaehlt wird erst ab start_quest, erledigte bleiben mit done = true
stehen, und die Belohnung darf die naechste starten: das ist die Kette.

- fuenfzehnte Registry, Trigger per serde(flatten) eingebettet
- give_item als Aktion, damit eine Belohnung mehr als Erfahrung zahlt
- QuestLog auf q, Fortschritt im Speicherstand, unbekannte IDs verworfen
- eine Funktion entscheidet fuer alle Traeger, wann ein Trigger feuert

Befund: Die Ordnungszahlen im Aktionskatalog widersprechen sich — vier
Tickets zaehlten je vom eigenen Stand. Sie sind raus, CONTEXT.md fuehrt
die Liste.
This commit is contained in:
2026-08-13 07:43:46 +02:00
parent 090d9ae136
commit 37b5820c5b
12 changed files with 376 additions and 22 deletions

View File

@@ -259,6 +259,28 @@ impl Default for Balance {
}
}
/// Die **siebte** Registry aus Ticket 08 (inzwischen die fuenfzehnte).
///
/// Eine Quest **ist ein Trigger mit `count = N`** — kein zweiter Mechanismus.
/// „Besitze 100 Gold" braucht deshalb keine eigene Form: `on = "item_picked_up"`,
/// `condition = has_item core:gold >= 100`, `count = 1`.
#[derive(Debug, Clone, Deserialize)]
pub struct Quest {
pub id: String,
pub name: String,
#[serde(default)]
pub description: String,
/// Wie oft das Ereignis passen muss.
#[serde(default = "one")]
pub count: u32,
/// Der Trigger selbst — `on`, `when`, `condition`, `actions`, `chance`
/// stehen flach in derselben Tabelle, weil die Quest *ist*, was er ist.
#[serde(flatten)]
pub trigger: Trigger,
#[serde(default)]
pub overrides: Option<String>,
}
/// Eine Wahlmoeglichkeit im Gespraech. **Flach, kein Knotengraph** — was erst
/// ein Graph koennte, ist Erzaehlung, und das Story-Modul steht unter
/// *Out of scope*.
@@ -475,6 +497,7 @@ pub struct Registries {
pub affixes: HashMap<String, Affix>,
pub loot_tables: HashMap<String, LootTable>,
pub npcs: HashMap<String, Npc>,
pub quests: HashMap<String, Quest>,
/// Keine Registry — ein Block mit festem Schema, feldweise verschmolzen.
pub balance: Balance,
/// Wer geladen wurde, in Ladereihenfolge. **Einziger Leser ist der
@@ -482,7 +505,7 @@ pub struct Registries {
/// spaeterer Ladelauf „`meinmod` 1.0.0 → 1.2.0 seit dem Speichern" melden
/// kann. Das ist die ganze Bilanz des `version`-Felds.
pub mods: Vec<crate::data::save::ModStamp>,
// TODO(M5+): `quests` (Ticket 08) und `scripts` (Ticket 13).
// TODO(M8): `scripts` (Ticket 13).
}
impl Registries {