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
This commit is contained in:
@@ -212,8 +212,14 @@ pub struct Balance {
|
||||
pub resistance_cap: f32,
|
||||
pub hit_floor: f32,
|
||||
pub hit_ceiling: f32,
|
||||
// TODO(M4/M5): `exp_base`, `exp_exponent` (Ticket 15) und `luck_factor`
|
||||
// (Ticket 16) — sie kommen mit ihren Lesern, nicht davor.
|
||||
/// Anteil des Preises, den ein Haendler beim Ankauf zahlt. **Die Spanne**:
|
||||
/// Ohne sie ist Handel ein Exploit oder ein No-op — kaufen und sofort
|
||||
/// zurueckverkaufen waere entweder gratis oder eine Geldmaschine.
|
||||
pub verkauf: f32,
|
||||
/// Wie stark `charisma` auf `price_modifier` wirkt (Ticket 02).
|
||||
pub charisma_preis: f32,
|
||||
// TODO(M5): `exp_base`, `exp_exponent` (Ticket 15) und `luck_factor`
|
||||
// (Ticket 16) — sie kommen mit ihren Lesern, nicht davor.
|
||||
}
|
||||
|
||||
impl Default for Balance {
|
||||
@@ -225,10 +231,54 @@ impl Default for Balance {
|
||||
resistance_cap: 0.8,
|
||||
hit_floor: 0.05,
|
||||
hit_ceiling: 0.95,
|
||||
verkauf: 0.4,
|
||||
charisma_preis: 1.5,
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/// Eine Wahlmoeglichkeit im Gespraech. **Flach, kein Knotengraph** — was erst
|
||||
/// ein Graph koennte, ist Erzaehlung, und das Story-Modul steht unter
|
||||
/// *Out of scope*.
|
||||
#[derive(Debug, Clone, Deserialize)]
|
||||
pub struct DialogOption {
|
||||
pub text: String,
|
||||
#[serde(default)]
|
||||
pub condition: Vec<Condition>,
|
||||
#[serde(default)]
|
||||
pub actions: Vec<Action>,
|
||||
}
|
||||
|
||||
/// Die **vierzehnte** Registry. Bewusst kein `creatures`-Eintrag mit
|
||||
/// `hostile = false`: Ein Haendler truege sonst `health`, `initiative`,
|
||||
/// `cooldowns`, `ai` und `exp_reward` als dauerhaft toten Ballast.
|
||||
#[derive(Debug, Clone, Deserialize)]
|
||||
pub struct Npc {
|
||||
pub id: String,
|
||||
pub name: String,
|
||||
#[serde(default = "npc_symbol")]
|
||||
pub symbol: char,
|
||||
#[serde(default)]
|
||||
pub color: Option<String>,
|
||||
#[serde(default)]
|
||||
pub greeting: String,
|
||||
/// **Der Warenbestand ist eine Beutetabelle** — dieselben Gewichte,
|
||||
/// dieselbe Tabelle-in-Tabelle, dieselben Affixe. Kein neuer
|
||||
/// „Waren"-Begriff.
|
||||
#[serde(default)]
|
||||
pub shop: Option<String>,
|
||||
#[serde(default)]
|
||||
pub options: Vec<DialogOption>,
|
||||
// TODO(M5): `triggers` — erst wenn `triggers_for` NPCs einsammelt. Als
|
||||
// Feld ohne Leser waere es eine Zusage, die niemand einloest.
|
||||
#[serde(default)]
|
||||
pub overrides: Option<String>,
|
||||
}
|
||||
|
||||
fn npc_symbol() -> char {
|
||||
'n'
|
||||
}
|
||||
|
||||
/// Eine benannte Modifikatorliste, die an einem **einzelnen Exemplar** haengt —
|
||||
/// „Flammendes Eisenschwert" (Ticket 07).
|
||||
///
|
||||
@@ -323,6 +373,11 @@ pub struct Prefab {
|
||||
/// Ersetzt die Etagentabelle fuer die `l`-Plaetze dieses Raums (Ticket 16).
|
||||
#[serde(default)]
|
||||
pub loot: Option<String>,
|
||||
/// Wer auf den `n`-Plaetzen steht. Anders als bei `e` nennt das **Prefab**
|
||||
/// den NPC, nicht die Etage: NPCs skalieren nicht mit der Tiefe — ein
|
||||
/// Schmied auf Etage 5 ist derselbe wie auf Etage 1 (Ticket 10).
|
||||
#[serde(default)]
|
||||
pub npcs: Vec<String>,
|
||||
#[serde(default)]
|
||||
pub overrides: Option<String>,
|
||||
}
|
||||
@@ -397,6 +452,7 @@ pub struct Registries {
|
||||
pub modifiers: HashMap<String, ModifierDef>,
|
||||
pub affixes: HashMap<String, Affix>,
|
||||
pub loot_tables: HashMap<String, LootTable>,
|
||||
pub npcs: HashMap<String, Npc>,
|
||||
/// Keine Registry — ein Block mit festem Schema, feldweise verschmolzen.
|
||||
pub balance: Balance,
|
||||
// TODO(M5+): `quests` (Ticket 08) und `scripts` (Ticket 13).
|
||||
|
||||
Reference in New Issue
Block a user