Files
rustkeep/CONTEXT.md
MDietermann 7ed15afaf9 feat(handel): NPC-Registry, Dialog, Laden und Stapelregel
Vierzehnte Registry: NPCs sind keine Wesen — kein Kampfzustand, keine
Initiative, keine Attribute. Ihre Antwortliste ist flach; was erst nach
einer Antwort erscheint, ist eine Option mit einer Bedingung.

- open_shop als elfte Aktion (game/ setzt eine Absicht, die UI schiebt)
- Talk/Choose/Buy/Sell, Talk wirkt auf das eigene Feld wie PickUp
- Preisspanne statt Goldkonto beim Haendler, Charisma in der Preisfunktion
- Warenkorb einmal bei der Etagenerzeugung gezogen
- Stapelregel aus Ticket 07 endlich gebaut: 50-120 Gold war 120 Eintraege
- Dialog- und Shop-Screen, NPC-Symbol im Grid
2026-08-12 20:31:35 +02:00

303 lines
15 KiB
Markdown

# Glossar
Kanonische Begriffe für rustkeep. Nur Sprache, keine Implementierung.
## Wesen
Held oder Gegner — im Code derselbe Typ. Träger von [Attributen](#attribut), [Zustand](#zustand),
[Tags](#tag), Inventar, Ausrüstung, gewählten [Charakteroptionen](#charakteroption) und den befristeten
[Modifikatoren](#modifikator), die gerade auf ihm liegen.
Ein Wesen ist dabei nicht in sich abgeschlossen: Eine Aura wohnt beim Träger und wird erst beim
Auslesen des Ziels eingesammelt.
Gegner werden in der [Registry](#registry) `[[creatures]]` definiert — mit Grundwerten, Tags,
Fähigkeiten und einer geordneten `ai`-Liste, deren erster passender und verfügbarer Eintrag gewinnt.
## Attribut
Eine benannte, veränderbare Größe an einem [Wesen](#wesen). Der Katalog ist fest und wird von der Engine
vorgegeben — er umfasst die Grundwerte (Stärke, Geschicklichkeit, Konstitution, Charisma, Glück,
Leben, Ausdauer, Level) *und* die abgeleiteten Kampfgrößen (Schaden, Rüstung, Trefferchance,
Kritische Chance, Kritischer Faktor, Preis-Modifikator, Tragfähigkeit).
Ein Attribut ist kein Inhalt, den ein Mod anlegt: Ein Modifikator auf ein Attribut, das keine
Spiellogik ausliest, hätte keine Wirkung. Der Katalog darf wachsen — aber durch die Engine,
nicht durch eine TOML-Datei.
## Modifikator
Eine Umrechnung eines [Attributs](#attribut), die gilt, solange eine Bedingung erfüllt ist.
Er wird nie ausgeführt, sondern beim Auslesen des Attributs aufsummiert. Quellen sind Rasse,
Klasse, ausgerüstete Gegenstände und befristete Zustände.
Beispiele: „Zwerg: +2 Konstitution", „Eisenschwert: +5 Schaden", „Segen: +10 % Kritische Chance".
Ein **benannter** Modifikator (`core:poisoned`) ist ein Bündel: mehrere Umrechnungen, eigene
[Trigger](#trigger) und eine Dauer in [Zügen](#zug). Er lebt in der Registry `[[modifiers]]` und wird
von der [Aktion](#aktion) `apply_modifier` aufgelegt. Er **wohnt beim Träger** — stirbt der, verschwindet
er mit ihm.
## Aktion
Eine einmalige Zustandsänderung. Sie feuert, wirkt, ist vorbei. Quellen sind Angriffe,
Verbrauchsgegenstände, Questbelohnungen und Fallen.
Beispiele: „12 Schaden zufügen", „20 Leben heilen", „50 Gold geben", „Gift anwenden".
Eine Aktion kann einen befristeten [Modifikator](#modifikator) erzeugen — so hängen die beiden
Begriffe zusammen, ohne dasselbe zu sein.
## Command
Ein Kommando der Oberfläche an das Spiel — „geh nach Norden", „leg das an", „kauf drei Tränke".
**Nicht dasselbe wie eine [Aktion](#aktion)**, und der Unterschied ist der Grund für den englischen
Namen: Eine Aktion ist Effektvokabular aus einer TOML, ein Command kommt von einem Tastendruck.
Jeder Command kostet einen [Zug](#zug), auch Handel — es gibt keine Ausnahmeliste. Bildschirme zu
öffnen ist dagegen kein Command, sondern reine Oberfläche und fasst den Spielzustand nicht an.
## Fähigkeit
Ein benanntes, wiederholt auslösbares Angebot an den Spieler, das [Aktionen](#aktion) ausführt.
Sie erscheint im Kampfmenü, trägt Symbol und Kosten und kann gesperrt sein.
Die dritte und letzte Wirkungsform neben [Modifikator](#modifikator) und [Aktion](#aktion), und die
Unterscheidung ist wesentlich: Eine Aktion ist eine *Wirkung*, eine Fähigkeit ist ein *Angebot*.
Fähigkeiten werden von [Charakteroptionen](#charakteroption) und Gegenständen gewährt, nicht im
Inventar getragen — sonst könnte ein Magier seine Zaubersprüche verkaufen.
## Trigger
Die vierte Wirkungsform: `{ on = <event>, condition = [...], actions = [...] }`. Ein
[Modifikator](#modifikator) rechnet um, eine [Aktion](#aktion) wirkt einmal, eine
[Fähigkeit](#fähigkeit) bietet an — der Trigger sagt **wann**.
Er darf überall stehen, wo Modifikatoren und Aktionen stehen: an [Gegenständen](#gegenstand),
[Affixen](#affix), [Charakteroptionen](#charakteroption) und [Quests](#quest). Im Trigger ist `self`
immer sein *Träger*, `target` die andere Seite des Events.
Die Events sind Engine-Vokabular ohne Namensraum und eine feste Liste — wie Attribute und
Schadenstypen.
## Bedingung
Eine Liste von Prüfungen, die *alle* zutreffen müssen — die Liste ist implizit UND, jeder Eintrag
über `not` negierbar. Es gibt kein ODER und keine Verschachtelung: Zwei Möglichkeiten werden zu zwei
Einträgen, oder der Modder fasst sie über ein gemeinsames [Tag](#tag) zusammen.
Es gibt genau eine Bedingungsgrammatik, und sie gilt an [Triggern](#trigger) wie an
[Modifikatoren](#modifikator).
## Quest
Ein [Trigger](#trigger) mit einem Zähler: `count = N` bedeutet, dass das Event N-mal mit erfüllter
[Bedingung](#bedingung) feuern muss, bevor die [Aktionen](#aktion) als Belohnung ablaufen. Moddbarer,
namespaced Inhalt.
Eine Quest zählt erst mit, nachdem die [Aktion](#aktion) `start_quest` sie angenommen hat.
## Gegenstand
Ein Ding im Spiel, einheitlich strukturiert: Kennung, Name, Grundpreis, optionaler [Slot](#slot),
Stapelbarkeit, Verbrauch beim Benutzen, plus Listen von [Modifikatoren](#modifikator),
[Aktionen](#aktion) und [Fähigkeiten](#fähigkeit).
Es gibt **keine Item-Typen**. Der frühere `enum ItemType` vermischte drei Konzepte — `Helmet` war ein
Slot, `Consumable` ein Verhalten, `Currency` eine Kategorie. Ein Schwert ist ein Gegenstand mit einem
Modifikator auf `damage`, mehr nicht.
Braucht ein Gegenstand etwas, das Modifikator, Aktion oder Fähigkeit nicht ausdrücken können, ist das
eine Lücke im Vokabular — sie wird dort geschlossen, nicht mit einem Sonderfeld umgangen.
## Affix
Eine benannte [Modifikator](#modifikator)-Liste mit Anzeigename und Preisfaktor, die an einem
*einzelnen Exemplar* eines [Gegenstands](#gegenstand) hängt — „Flammendes Eisenschwert". Moddbarer,
namespaced Inhalt (`core:flaming`).
Der Affix ist der Grund, warum ein Gegenstand im Spiel nicht dasselbe ist wie sein Katalogeintrag: Die
Definition liegt in der Registry, das Exemplar trägt zusätzlich seine Affixe.
Strukturell ist ein Affix dasselbe wie eine [Charakteroption](#charakteroption) — benannte
Modifikatorliste plus Metadaten. Der Unterschied ist, woran er hängt.
## Slot
Eine benannte Stelle am Charakter, an der genau ein [Gegenstand](#gegenstand) getragen werden kann.
Moddbarer, namespaced Inhalt mit Anzeigename und Sortierreihenfolge (`core:head`, `meinmod:umhang`).
Der Charakterbogen rendert die vorhandenen Slots, statt ein festes Layout zu mauern.
## Charakteroption
Eine Wahl beim Charakterbau — eine benannte Liste von [Modifikatoren](#modifikator),
[Fähigkeiten](#fähigkeit) und einmalig ausgeführten [Aktionen](#aktion). Rasse und Klasse sind
Charakteroptionen, keine eigenen Konzepte.
Optionen liegen in **Kategorien**, und die Kategorien sind selbst moddbarer Inhalt mit einem Feld
`pick = N`. Ein Mod kann so eine dritte Wahl („Gottheit") oder eine Mehrfachwahl („zwei Talente")
ergänzen, ohne dass die Engine davon weiß.
## Zustand
Der veränderliche Istwert eines Wesens — aktuelles Leben, aktuelle Ausdauer, getragene Gegenstände,
aktive befristete [Modifikatoren](#modifikator). Kein [Attribut](#attribut) und nicht von
Modifikatoren umrechenbar: Ein Modifikator wirkt auf `max_health`, eine [Aktion](#aktion) ändert den
Lebensstand. Die Trennung muss scharf bleiben, sonst heilt ein Ring beim Anlegen.
## Schadenstyp
Eine von sieben festen Kennzeichnungen, wie Schaden gemindert wird: `fire`, `ice`, `poison`, `shock`,
`holy`, `slash`, `blunt`. Engine-Vokabular ohne Namensraum. Zu jedem Typ gehört eine Resistenz, und
Resistenz ist der *einzige* Minderungsmechanismus — Rüstung ist Kurzschreibweise für Resistenz gegen
`slash` und `blunt`, kein eigenes Konzept.
Der Schadenstyp `poison` ist **nicht** der Modifikator `core:poisoned` („Vergiftet"). Der Typ sagt,
wie gemindert wird; der Modifikator ist ein Zustand, der über Züge tickt.
## Tag
Eine freie, namespaced Kennzeichnung an einem Wesen (`core:undead`, `meinmod:aquatisch`). Reiner
Inhalt: Die Engine kennt keine Tags, sie vergleicht nur Zeichenketten. Grundlage für Bedingungen
wie „+5 Schaden gegen Untote". Gegenpol zum [Attribut](#attribut) — der Doppelpunkt zeigt dem Modder,
auf welcher Seite er steht.
## Zug
Die einzige Zeiteinheit des Spiels. Ein Feld weitergehen ist ein Zug, eine Kampfaktion ist ein Zug.
Ein **abgewiesenes** [Command](#command) kostet dagegen keinen — gegen eine Wand zu laufen verbraucht
keine Zeit.
Es gibt keine getrennte Kampfrunden-Uhr: Befristete [Modifikatoren](#modifikator) ticken auch beim
Erkunden, damit „ich warte den Debuff draußen ab" eine Entscheidung mit Kosten bleibt.
## NPC
Eine ansprechbare Figur auf einer [Etage](#etage) — kein [Wesen](#wesen): Ein NPC hat keine
[Attribute](#attribut), keine [Initiative](#initiative) und keinen Kampfzustand. Ihn in `[[creatures]]`
zu pressen hieße, jedem Gegner ein leeres Dialogfeld und jedem Händler leere Grundwerte zu geben.
Seine Antwortliste ist **flach**, kein Knotengraph: Was erst nach einer Antwort erscheint, ist eine
Option mit einer [Bedingung](#bedingung). Jede Option trägt [Aktionen](#aktion) — `open_shop` ist die
elfte davon und öffnet den Laden, statt als Sonderfeld daneben zu stehen.
Ein NPC mit `shop` hat einen **Warenkorb**, der einmal bei der Erzeugung der Etage aus einer
[Loot-Tabelle](#loot-tabelle) gezogen wird und danach feststeht — sonst würfelte jedes Öffnen neu, und
der Spieler könnte sich das Angebot herbeischließen. Er hat **kein Goldkonto**: Die Spanne zwischen
Kauf- und Verkaufspreis, nicht ein Vorrat, begrenzt den Handel.
Angesprochen wird der NPC auf dem Feld, auf dem der Held **steht** — dieselbe Regel wie beim Aufheben
und beim Abstieg.
## Prefab
Ein von Hand gezeichneter Raum als ASCII-Block, moddbarer namespaced Inhalt. Wände, Boden und Türen
stehen als Zeichen darin, dazu Plätze für Gegner, Beute, Treppe, Eingang und NPCs.
Ein Gegner-Platz sagt „hier steht ein Gegner", **nicht welcher** — das entscheidet die [Etage](#etage).
Nur so lässt sich derselbe Raum auf Etage 1 und Etage 5 verwenden. Bei NPCs ist es umgekehrt: Die nennt
das Prefab selbst, denn ein Schmied ist auf jeder Etage derselbe Schmied.
Türen sind ausdrücklich markiert, damit der Generator keine Löcher in eine gezeichnete Wand stanzt.
Prefabs dürfen gedreht und gespiegelt werden.
## Etage
Eine Ebene des Dungeons und zugleich ihr Bauplan: Fläche, Raumzahl, Pflichträume, gewichtete
[Prefab](#prefab)- und [Wesen](#wesen)-Auswahl, Beutetabelle. Ausgewählt wird über [Tags](#tag), nie
über IDs — sonst könnte ein Mod keinen eigenen Eingangsraum beisteuern.
Es existiert immer nur **eine** Etage; beim Abstieg wird die vorige verworfen, es gibt kein
Zurückgehen. Gibt es keine Etage mit der nächsten Nummer, ist der Lauf **gewonnen** — die Zahl der
Etagen steht nirgends im Code.
## Erfahrung
Der Fortschrittszähler des Helden. Quellen sind **Tötungen** (Feld `exp_reward` am
[Wesen](#wesen)) und **Quests** (Aktion `give_exp`) — nicht das Betreten einer [Etage](#etage), denn
das belohnte das Durchrennen.
Ein Aufstieg gibt **genau einen** frei verteilbaren Punkt auf einen der fünf Grundwerte. Es gibt
**keine Obergrenze**: Die Kurve begrenzt sich über steigende Kosten. Erfahrung hat nur der Held —
Gegner tragen zwar ein Level, aber keinen Fortschritt.
## Initiative
Ein Zahlenwert am [Wesen](#wesen), einmal beim Betreten eines Kampfes aus `dexterity` plus Wurf
gewürfelt. Er bestimmt die Reihenfolge innerhalb eines [Zuges](#zug); bei Gleichstand handelt der Held
zuerst.
Initiative ist bewusst eine Zahl *am Wesen* und keine Reihenfolgeliste — eine Liste wäre eine zweite
Sammlung von Verweisen, die beim Tod eines Gegners ungültig würde.
## Speicherstand
Der serialisierte Spielzustand, TOML, **genau einer**. Er wird beim Betreten einer [Etage](#etage) und
beim Beenden automatisch geschrieben; von Hand speichern kann man nicht, und bei Tod wird er
**gelöscht** — der Lauf ist dann vorbei.
Das Etagen-Layout steht als Text darin, nicht als Generator-Seed: Ein Mod-Update würde sonst ein
anderes Layout erzeugen und den Helden in eine Wand stellen.
Fehlt beim Laden ein [Mod](#mod), wird der betroffene Eintrag verworfen und gewarnt — nie der ganze
Speicherstand abgelehnt.
## Loot-Tabelle
Eine gewichtete Liste, aus der gezogen wird. Ein Eintrag ist ein [Gegenstand](#gegenstand), ein
[Affix](#affix), eine andere Tabelle oder eine **Niete** — dieselbe Maschinerie zieht damit Beute
*und* Affixe.
Gewichtet wird mit **Gewichten, nicht mit Prozenten** — Prozente müssten sich auf 100 summieren, und
ein Eintrag, den ein [Mod](#mod) hinzufügt, machte die Summe kaputt.
Es gibt **keinen Seltenheitsbegriff**: Abstufungen sind eigene Einträge mit kleinerem Gewicht
(`core:flaming` neben `core:greater_flaming`).
## Registry
Eine benannte Sammlung moddbarer Definitionen, geschlüsselt nach namespaced ID. Es gibt **vierzehn**,
und das hier ist die kanonische Liste — sie ist über sieben Tickets und vier Meilensteine gewachsen und
stand sonst nirgends vollständig:
| Registry | TOML-Tabelle |
|---|---|
| [Gegenstände](#gegenstand) | `[[items]]` |
| [Slots](#slot) | `[[slots]]` |
| [Charakteroption-Kategorien](#charakteroption) | `[[categories]]` |
| [Charakteroptionen](#charakteroption) | `[[options]]` |
| [Fähigkeiten](#fähigkeit) | `[[abilities]]` |
| [Affixe](#affix) | `[[affixes]]` |
| [Quests](#quest) | `[[quests]]` |
| [Wesen](#wesen) | `[[creatures]]` |
| [Prefabs](#prefab) | `[[prefabs]]` |
| [Etagen](#etage) | `[[floors]]` |
| [Loot-Tabellen](#loot-tabelle) | `[[loot_tables]]` |
| Benannte [Modifikatoren](#modifikator) | `[[modifiers]]` |
| [NPCs](#npc) | `[[npcs]]` |
| Scripts | `[[scripts]]` |
Jede dieser Tabellen darf in jeder beliebigen `*.toml` eines [Mods](#mod) stehen.
Die Einstellungstabelle `[balance]` ist **keine** Registry: ein einzelner Block mit festem Schema, der
feldweise verschmilzt, statt als ganzer Eintrag ersetzt zu werden.
`[[scripts]]` gehört zu Mod-Stufe (c) und ist entschieden, aber noch nicht gebaut — Scripts lesen über
neun Funktionen und schreiben ausschließlich über [Aktionen](#aktion), damit die Engine austauschbar
bleibt.
## Mod
Ein Ordner mit einer `manifest.toml` und beliebig vielen weiteren TOML-Dateien. Das Manifest gibt dem
Mod seinen **Namensraum** — den Präfix vor dem Doppelpunkt, den der Lader jeder ID darin automatisch
voranstellt.
Das Kernspiel ist ein Mod, kein Sonderfall: `core` liegt als gewöhnlicher Ordner auf der Platte und
wird über denselben Lader gelesen wie jeder Fremdmod. Genau das ist der Sinn — was nur für Fremdmods
gilt, ist nie getestet.
## Effekt
**Kein kanonischer Begriff.** Wird umgangssprachlich für [Modifikator](#modifikator) *und*
[Aktion](#aktion) benutzt; in Code, TOML und Doku ist stattdessen immer der genaue Begriff zu
verwenden. Das Wort überlebt nur noch in „Effekt-Vokabular" als Sammelname für beide zusammen.