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:
2026-08-12 20:31:35 +02:00
parent 197f62ce33
commit 7ed15afaf9
22 changed files with 818 additions and 26 deletions

View File

@@ -107,6 +107,7 @@ pub fn generate(def: &FloorDef, reg: &Registries, rng: &mut Rng) -> Floor {
for p in &placed {
let mut enemy_spawns = Vec::new();
let mut loot = Vec::new();
let mut npc_plaetze = Vec::new();
for y in 0..p.stamp.h {
for x in 0..p.stamp.w {
@@ -124,6 +125,7 @@ pub fn generate(def: &FloorDef, reg: &Registries, rng: &mut Rng) -> Floor {
match c {
'e' => enemy_spawns.push((gx, gy)),
'l' => loot.push((gx, gy)),
'n' => npc_plaetze.push((gx, gy)),
_ => {}
}
}
@@ -152,6 +154,23 @@ pub fn generate(def: &FloorDef, reg: &Registries, rng: &mut Rng) -> Floor {
.or_else(|| def.loot.clone())
.unwrap_or_default();
// Der i-te `n`-Platz bekommt den i-ten Eintrag aus `prefab.npcs` —
// Positionsbindung statt eines zweiten Markers je NPC.
let npcs = npc_plaetze
.into_iter()
.enumerate()
.filter_map(|(i, pos)| {
let id = reg.prefabs.get(&p.prefab)?.npcs.get(i)?.clone();
let stock = reg
.npcs
.get(&id)
.and_then(|n| n.shop.as_deref())
.map(|t| crate::game::loot::roll(t, reg, rng))
.unwrap_or_default();
Some(super::floor::NpcInstance { pos, def: id, stock })
})
.collect();
rooms.push(Room {
prefab: p.prefab.clone(),
rect: p.rect,
@@ -159,6 +178,7 @@ pub fn generate(def: &FloorDef, reg: &Registries, rng: &mut Rng) -> Floor {
enemies,
loot_table,
loot,
npcs,
cleared: false,
});
}