08 — Event- und Trigger-System #9
Reference in New Issue
Block a user
Delete Branch "%!s()"
Deleting a branch is permanent. Although the deleted branch may continue to exist for a short time before it actually gets removed, it CANNOT be undone in most cases. Continue?
Teil der Map #1 · Type:
wayfinder:grilling· Blocked by: #8Welche Ereignisse meldet das Spiel, und wie haengen Quests und spaeter Scripts daran?
Volle Fragestellung (kanonisch):
.scratch/rustkeep-1.0/issues/08-event-trigger-system.mdAufgeloest in
d5a6feb. Kanonische Fassung:.scratch/rustkeep-1.0/issues/08-event-trigger-system.mdDer Trigger ist die vierte Wirkungsform
Modifikator rechnet um, Aktion wirkt einmal, Faehigkeit bietet an — der Trigger sagt wann. Er darf ueberall stehen, wo
modifiersundactionsstehen: Gegenstaende, Affixe, Charakteroptionen, Quests, spaeter Scripts.Das kostet nichts (Aktionsliste plus zwei Felder, Aktionen sind seit #2 definiert). Die Alternative waere nicht weniger Code, sondern dieselbe Maschine ein zweites Mal — in #15 unter dem Namen
on_hit. Ohne Trigger waere "Flammendes Schwert: 20% Chance Brennen" nicht ausdrueckbar.Bedingungen — eine Grammatik fuer alles
Getaggtes Enum, Liste ist implizit UND, jeder Eintrag ueber
notnegierbar. Kein ODER, kein Verschachteln — ein rekursiver Ausdrucksbaum braeuchte eine Klammer-Syntax, die in TOML niemand freiwillig schreibt. Decke offen benannt: "(untot ODER daemonisch) UND Level >= 3" wird zu zwei Eintraegen dupliziert, oder der Modder haengt beiden ein Tagcore:unheiligan.Neun Events, feste Liste
turn_started·attack_hit·damage_taken·creature_died·item_picked_up·item_used·floor_entered·npc_talked·quest_completedJedes traegt
source: CreatureRefundtarget: Option<CreatureRef>plus eigene Nutzlast. Keinplayer_died— das istcreature_diedmitsource = Player.attack_hitunddamage_takenbleiben getrennt: das eine feuert beim Angreifer (flammendes Schwert), das andere beim Getroffenen (Dornenpanzer).selfist der Traeger des Triggers,targetdie andere Seite des Events. Damit ist eine Quest kein Sonderfall, sondern ein Trigger mit festem Traeger.Keine Mod-Events fuer 1.0 — ohne Scripting kann niemand eines ausloesen, es waere Vokabular ohne Sender. Kommt Stufe (c) ueber #14, wird
emit_eventeine gewoehnliche Aktion und die Liste bekommt eineCustom(String)-Variante.Warteschlange statt Rekursion
Events landen in
Game.events: Vec<Event>und werden nach der laufenden Aktion leergearbeitet. Zur Haelfte ein Rust-Fakt:Game::applyhaelt&mut self, synchrones Feuern hiesse ueberself.questsiterieren waehrendself.applyerneut laeuft — Borrow-Fehler, kein Stilproblem. Zur anderen Haelfte die Rekursionsfrage: eine Belohnung, die ein Event ausloest, haengt es hinten an.Gegen Zyklen ein Zaehler: maximal 100 Events pro Zug, dann Abbruch mit Warnzeile. Kein Zyklengraph. Trigger werden bei jedem Event gesucht, nicht indiziert — ein Index muesste bei jedem An- und Ablegen gepflegt werden, also genau das Invalidierungsproblem, das #8 vermieden hat.
Quests
Eine Quest ist ein Trigger mit
count = Nund damit die siebte Registry:"Besitze 100 Gold" braucht keine zweite Mechanik:
on = "item_picked_up",has_item >= 100,count = 1.QuestProgress { quest, count, done }— erledigte bleiben mitdone = truestehen, sonst kann eine Kette aufquest_completednicht zwischen "lief nie" und "gerade fertig" unterscheiden.Zwei Nachtraege an geschlossene Tickets
start_questkommt als siebte Aktion dazu. Ohne Aktivierung waere "geh in den Keller" erfuellt, bevor jemand die Quest erwaehnt hat, und ein Mod mit 40 Quests liesse 40 Zaehler pro Event mitlaufen.Game::attribute(who, attr, against: Option<CreatureRef>, reg). Ohne den Gegner ist "+5 Schaden gegen Untote" beim Auslesen vondamagenicht auswertbar. Als Trigger mit Zusatzschaden zu loesen waere nicht dasselbe Ergebnis — der zweite Schadensfall liefe getrennt durch Resistenz und Krit. Dazuevents: Vec<Event>als neues Feld.Auflagen
floor_entereddeckt nur die Etage abemit_eventund namespaced Events, sobald Stufe (c) stehtattack_hitunddamage_takenim Zug feuern