119 lines
4.8 KiB
Markdown
119 lines
4.8 KiB
Markdown
# 02 — Typ-Registry statt Enums
|
|
|
|
Type: grilling
|
|
Status: resolved
|
|
Blocked by: 01
|
|
|
|
## Question
|
|
|
|
Wie werden Item-Typen, Rassen und Klassen zu Daten statt zu Rust-Enums?
|
|
|
|
`enum ItemType` kann ein Modder nicht erweitern — es muss eine Registry aus String-IDs werden.
|
|
Zu klären:
|
|
|
|
- Was deklariert ein Typ? Ausrüstungsslot, welche Felder Pflicht sind, welche Effekte er tragen darf.
|
|
- Gibt es Slots als eigene Registry (`core:helmet`), oder ist der Slot ein fester Aufzählungswert?
|
|
- Wie prüft das Spiel beim Laden, dass ein Item einen existierenden Typ nennt — und was passiert, wenn nicht?
|
|
- Wie unterscheiden sich Rasse und Klasse strukturell, oder sind beide dasselbe: eine benannte Effektliste
|
|
plus Metadaten?
|
|
- Was verliert man ohne Enum an Compile-Zeit-Sicherheit, und was fängt das ab (Validierung beim Laden)?
|
|
|
|
Ergebnis: das Registry-Datenmodell plus TOML-Beispiel für einen selbstdefinierten Item-Typ.
|
|
|
|
## Answer
|
|
|
|
Begriffe im [Glossar](../../../CONTEXT.md).
|
|
|
|
### Fünf Registries
|
|
|
|
**Gegenstände** · **Slots** · **Charakteroption-Kategorien** · **Charakteroptionen** · **Fähigkeiten**.
|
|
Alle moddbar, alle namespaced.
|
|
|
|
### Es gibt keinen Item-Typ mehr
|
|
|
|
`enum ItemType` verschwindet ersatzlos — er vermischte drei Konzepte: `Helmet` ist ein *Slot*,
|
|
`Consumable` ein *Verhalten*, `Currency` eine *Kategorie*. Genau deshalb war er nie erweiterbar.
|
|
An seine Stelle treten drei Felder am Gegenstand: `slot` (leer = nicht ausrüstbar), `stackable`,
|
|
`consumed_on_use`.
|
|
|
|
`ItemWeapon` und `ItemArmor` entfallen ebenfalls. Ein Gegenstand ist einheitlich
|
|
`{ id, name, base_price, slot?, stackable, consumed_on_use, modifiers[], actions[], abilities[] }`.
|
|
Ein Schwert ist ein Gegenstand mit einem Modifikator auf `damage`, ein Helm einer mit einem
|
|
Modifikator auf `resistance`.
|
|
|
|
**Tragende Regel:** 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 hier mit
|
|
einem Sonderfeld umgangen.
|
|
|
|
### Fähigkeit — der dritte Begriff
|
|
|
|
Modifikator rechnet um, Aktion wirkt einmal, **Fähigkeit** ist ein benanntes, wiederholt auslösbares
|
|
Angebot an den Spieler, das Aktionen ausführt. Sie erscheint im Kampfmenü, hat Symbol und Kosten,
|
|
kann gesperrt sein. Ein Zauberspruch als Gegenstand im Inventar wäre die Alternative gewesen — dann
|
|
könnte ein Magier seine Zaubersprüche aber verkaufen oder verlieren.
|
|
|
|
Dieses Ticket legt nur fest, dass Fähigkeiten eine eigene Registry sind und von Gegenständen wie
|
|
Charakteroptionen referenziert werden. Kosten, Abklingzeit und Verfügbarkeit entscheidet Ticket 14.
|
|
|
|
### Deklarationen
|
|
|
|
```toml
|
|
# slots.toml
|
|
[[slots]]
|
|
id = "core:head"
|
|
name = "Kopf"
|
|
order = 10
|
|
|
|
# character_option_categories.toml
|
|
[[categories]]
|
|
id = "core:race"
|
|
name = "Rasse"
|
|
order = 10
|
|
pick = 1
|
|
|
|
# races.toml
|
|
[[options]]
|
|
id = "core:dwarf"
|
|
category = "core:race"
|
|
name = "Zwerg"
|
|
description = "Zäh, misstrauisch, trinkfest."
|
|
modifiers = [ { attribute = "constitution", flat = 2 } ]
|
|
abilities = ["core:stonesense"]
|
|
on_create = [ { action = "give_item", item = "core:pickaxe", count = 1, target = "self" } ]
|
|
```
|
|
|
|
Kategorien tragen `pick = N`, damit „wähle zwei Talente" ohne neue Maschine möglich ist.
|
|
|
|
**`on_create` ist keine neue Mechanik**, sondern eine Liste gewöhnlicher Aktionen, einmal beim
|
|
Charakterbau ausgeführt. Startgold, Startausrüstung und Startbuff sind damit moddbar, ohne dass die
|
|
Engine den Begriff „Startausrüstung" kennt.
|
|
|
|
### Umbenennung
|
|
|
|
`Item.value` → `base_price` (Grundwert des Gegenstands). Attribut `shop_price` → `price_modifier`
|
|
(Charaktereigenschaft, über die Charisma wirkt). Zwei Dinge, zwei Namen.
|
|
|
|
### Nachtrag aus Ticket 09: zwei Fähigkeiten sind implizit
|
|
|
|
Oben steht, Fähigkeiten würden „von Charakteroptionen und Gegenständen gewährt". Genau das erzeugt eine
|
|
Lücke: Ein Held, dessen Klasse nach einem Mod-Wechsel fehlt und der nichts trägt, hätte **gar keine**
|
|
Fähigkeit — und könnte seit Ticket 11 nicht einmal angreifen, weil `core:attack` eine Fähigkeit ist.
|
|
|
|
Deshalb: **`core:attack` und `core:flee` sind jedem [Wesen](../../../CONTEXT.md) implizit gewährt.**
|
|
|
|
Das ist keine Sonderregel für den Ladefall. Es trifft ebenso jeden Gegner ohne `abilities`-Eintrag, vor
|
|
dessen leerer Liste die KI aus Ticket 14 sonst stünde.
|
|
|
|
### Auflagen an andere Tickets
|
|
|
|
- **11 UI-Gerüst und Screen-Modell**: Charakterbogen und Charakterbau sind Schleifen über Registries,
|
|
keine fest gemauerten Layouts — Modder können Slots *und* Wahlkategorien ergänzen.
|
|
- **14 Kampfformeln und Rundenablauf**: muss Fähigkeitskosten, Abklingzeit und Verfügbarkeit
|
|
mitentscheiden. Ticketkörper wurde entsprechend erweitert.
|
|
|
|
### Folgen für bestehenden Code
|
|
|
|
`src/items/weapon.rs` und `src/items/armor.rs` werden gelöscht, `enum ItemType` entfällt,
|
|
`weapons.toml` und `armors.toml` verschmelzen zu einer gewöhnlichen Gegenstandsdatei, `items.rs`
|
|
schrumpft auf Laden plus Registry.
|