Make NPCs a dedicated section with per-NPC stats
Replace the single shared `npc` stat template (+ npc_card_types) with an `npcs` section: each NPC keyed by a stable id, carrying its own name, description, trigger keys, and its OWN stats block. The AI addresses NPCs as npc.<id>.<stat> (id shown in context), which also fixes the old card-id-guessing problem. On adventure creation each NPC auto-creates a story card (name/keys/desc) for lore + in-scene detection, unless a same-name card already exists. All NPCs instantiate up front. - engine: npcs instantiate/apply/render/reference, npc_name/npc_triggers - builder: _visible_npcs matches each NPC's own keys - create_adventure: auto-create story cards from npcs - WorldStateDrawer: render defined NPCs with their own stats + desc tooltip - demo seed: Gwen (health/trust) + Bandit Leader (health/aggression) - tests updated (34 pass); no new migration (npcs lives in stat_schema JSON) Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
This commit is contained in:
co-authored by
Claude Opus 4.8
parent
4dac445f90
commit
cf464a48b0
@@ -98,6 +98,7 @@ def create_adventure(
|
||||
db.flush()
|
||||
|
||||
if scenario:
|
||||
existing_names = {(c.name or "").strip().lower() for c in scenario.story_cards}
|
||||
for card in scenario.story_cards:
|
||||
db.add(
|
||||
models.StoryCard(
|
||||
@@ -109,6 +110,24 @@ def create_adventure(
|
||||
notes=card.notes,
|
||||
)
|
||||
)
|
||||
# Phase 12: each defined NPC gets a story card (for its description as
|
||||
# lore + in-scene triggering), unless a card with that name already exists.
|
||||
for npc_key, ndef in (scenario.stat_schema or {}).get("npcs", {}).items():
|
||||
if not isinstance(ndef, dict):
|
||||
continue
|
||||
name = worldstate.npc_name(ndef, npc_key)
|
||||
if name.strip().lower() in existing_names:
|
||||
continue
|
||||
db.add(
|
||||
models.StoryCard(
|
||||
adventure_id=adventure.id,
|
||||
type="character",
|
||||
name=name,
|
||||
keys=fill_placeholders(str(ndef.get("keys") or name), values),
|
||||
entry=fill_placeholders(str(ndef.get("desc") or ""), values),
|
||||
notes="",
|
||||
)
|
||||
)
|
||||
for position, script in enumerate(scenario.scripts):
|
||||
db.add(
|
||||
models.AdventureScript(
|
||||
|
||||
Reference in New Issue
Block a user