# 01 — Effekt-Vokabular Type: grilling Status: resolved Blocked by: — ## Question Was kann ein Effekt ausdrücken, und wie sieht er in TOML aus? Das Effekt-Vokabular ist die Mod-API: ein Modder kann exakt das bauen, was hier definiert wird. Zu klären: - Welche Wirkungen gibt es? Stat-Modifikator (flach, prozentual), Sofortschaden/Heilung, Ressourcenverbrauch, Statuseffekt anwenden/entfernen, Event auslösen. - Zeitlichkeit: permanent (Rasse), solange ausgerüstet (Item), N Runden (Statuseffekt), einmalig (Trank). - Wie werden Effekte gestapelt und in welcher Reihenfolge verrechnet? Erst flach, dann prozentual? - Wie referenziert ein Effekt sein Ziel — Träger, Gegner, alle Gegner? - Wie sieht die TOML-Repräsentation aus, und bleibt sie lesbar genug für Modder ohne Doku? Ergebnis: eine Liste der Effekt-Varianten mit TOML-Beispiel je Variante. ## Answer Begriffe sind im [Glossar](../../../CONTEXT.md) festgehalten. ### Zwei Begriffe, nicht einer **Modifikator** rechnet ein Attribut um, solange er existiert — er wird nie ausgeführt, sondern beim Auslesen aufsummiert. **Aktion** ändert Zustand einmalig. Getrennte Maschinen, getrennte TOML-Arrays. Ein gemeinsamer Oberbegriff „Effekt" ist ausdrücklich *kein* kanonischer Begriff mehr. ### Attributkatalog (Engine-Vokabular, ohne Namensraum) `strength` · `dexterity` · `constitution` · `charisma` · `luck` · `level` · `max_health` · `max_stamina` · `damage` · `hit_chance` · `critical_chance` · `critical_factor` · `resistance` (typ-indiziert) · `shop_price` · `carry_capacity` `max_health` ist ein Attribut und wird von Modifikatoren umgerechnet. Der aktuelle Lebensstand ist **kein** Attribut, sondern Zustand — den ändern Aktionen. Diese Trennung muss scharf bleiben. ### Modifikator ```toml modifiers = [ { attribute = "damage", flat = 5 }, { attribute = "strength", flat = 2, percent = 5 }, { attribute = "critical_chance", percent = 10, duration = "turns", turns = 3, target = "all_enemies", symbol = "curse", name = "Verflucht" }, ] ``` - `flat` und `percent` beide optional, mindestens eines Pflicht. - `duration`: `permanent` · `while_equipped` · `turns` · `until_floor_end`. - `target`: `self` · `target` · `all_enemies`. Der Modifikator wohnt **immer beim Träger** und wird beim Auslesen des Ziels eingesammelt — stirbt der Träger, verschwindet die Aura von selbst. - `symbol` und `name` nur bei befristeten Zuständen; Item-Boni erben beides vom Item. `symbol` ist ein Schlüssel, keine Farbe — die Zuordnung macht `ui/theme.rs`. ### Aktion ```toml actions = [ { action = "damage", amount = 12, damage_type = "fire", target = "target" }, { action = "change_attribute", attribute = "health", amount = 20, target = "self" }, { action = "apply_modifier", modifier = "core:poisoned", target = "target" }, { action = "remove_modifier", modifier = "core:poisoned", target = "self" }, { action = "give_item", item = "core:gold", count = 50, target = "self" }, { action = "remove_item", item = "core:torch", count = 1, target = "self" }, ] ``` Sechs Aktionen. `damage` bleibt eigenständig statt `change_attribute health -12`, weil Schaden durch eine Kette läuft (Resistenz mindert, Krit vervielfacht, Bedingungen greifen) und „bei erlittenem Schaden" ein Event ist. Flache Liste, keine verschachtelten Aktionen — Ketten laufen über das Event-System. ### Regeln | | | |---|---| | Stapeln | `(Basis + Σ flach) × (1 + Σ prozentual)`, intern `f32`, gerundet an genau einer Stelle | | Uhr | Ein Zug. Ein Feld gehen = ein Zug, eine Kampfaktion = ein Zug. Debuffs ticken auch beim Laufen | | Schadenstypen | `fire` `ice` `poison` `shock` `holy` `slash` `blunt` — fest, Engine-Vokabular | | Minderung | Ein Mechanismus: `resistance` je Typ. `armor` am Item ist Kurzschreibweise für Resistenz gegen `slash` und `blunt` | | Namensraum | Doppelpunkt = Modder-Inhalt (`core:poisoned`). Ohne = Engine-Vokabular (`strength`, `fire`) | | Tags | Freie namespaced Strings am Wesen, Grundlage für Bedingungen | | Sprache | Schadenstyp `poison` ≠ Modifikator `core:poisoned` („Vergiftet") | ### Nachtrag aus Ticket 08: `start_quest` Der Katalog hat **sieben** Aktionen, nicht sechs. `start_quest` kam mit [Ticket 08](08-event-trigger-system.md) dazu, weil eine Quest sonst ab dem ersten Zug mitzählte und Questketten beim Betreten des Kellers bereits erfüllt wären. ```toml { action = "start_quest", quest = "core:rattenplage", target = "self" } ``` Das hier angeforderte Bedingungsvokabular steht ebenfalls in 08, zusammen mit dem **Trigger** als vierter Wirkungsform. ### Nachtrag aus Ticket 11: `symbol` trägt das Zeichen, nicht einen Schlüssel Oben steht, `symbol` sei ein Schlüssel und die Zuordnung mache `ui/theme.rs`. Darin steckt eine Lücke: **`ui/theme.rs` ist Code.** Ein Modder, der `meinmod:frostbite` anlegt, kann dort nichts eintragen — sein Statuseffekt hätte weder Zeichen noch Farbe. Stattdessen trägt die TOML beides selbst, die Farbe als Name aus fester Liste: ```toml symbol = "†" color = "cyan" ``` `data/` kennt nur `char` und ein Farbnamen-Enum, `ui/theme.rs` übersetzt in `ratatui::Color` — `game/` und `data/` bleiben damit weiterhin ratatui-frei. ### Bewusst nicht entschieden Das **Bedingungsvokabular** für `condition`. Es kommt aus Ticket 08, damit Quests und Modifikatoren dieselbe Grammatik benutzen statt zweier, die sich subtil unterscheiden. Ticket 01 fordert es nur an. ### Folgen für bestehenden Code `ItemArmor.armor` fällt weg und wird ein Modifikator auf `resistance`. `Stats` trennt Attribute von Zustand. Der Attributkatalog braucht abgeleitete Größen, die es heute gar nicht gibt (`hit_chance`, `carry_capacity`).