Quest-Editor
Der Builder unter /dashboard/storyquests/<id>/builder ist das Werkzeug, in dem du deine Quest zusammenbaust. Eine separate Route /dashboard/storyquests/<id>/flowchart zeigt die reine Graph-Ansicht ohne die restlichen Panels — praktisch, wenn du nur die Struktur überblicken willst, ohne im Detail-Editor zu landen.
Layout
Der Builder hat drei Bereiche:
- Links: Übersichts-Liste aller Nodes, Items und Variablen. Such-Feld oben. Klick öffnet das jeweilige Element rechts.
- Mitte: Flowchart mit Nodes als Boxen und Choices als Pfeile. Zoom mit Mausrad, Pan mit Mittelklick.
- Rechts: Detail-Panel für das gerade ausgewählte Element.
Oben die Aktions-Buttons: 📊 Flowchart (springt zur reinen Graph-Route), ▶ Playtest, 📤 Export JSON, 🤖 KI-Tools, « Veröffentlichen » und « Speichern » (Auto-Save ist aktiv, der Button erzwingt einen Snapshot).
Nodes bearbeiten
Ein Node hat folgende Felder:
- Titel: Interner Name, nicht für Zuschauer sichtbar.
- Erzähltext: Markdown-fähig, wird im Overlay/Chat angezeigt. Unterstützt Slash-Vorlagen beim Tippen:
/haendlerbzw./shopfür eine fertige Händler-Node-Struktur,/secretfür einen Geheimpfad mit ⭐-Marker im Flowchart. - Node-Typ:
normal,combatoderending. Nur diese drei — es gibt keinen vierten „Quiz"- oder „Dialog"-Typ auf Node-Ebene (Dialoge/NPCs laufen über das darunterliegende Event-System, siehe unten). - Bei Typ
combat:enemy_name,enemy_hp,enemy_attack,enemy_defense— definiert den Gegner für die eingebaute W16-Kampflogik. - Hintergrund/Sound: Asset-Picker aus der Media Library (
/dashboard/media). Optional.
Choices bearbeiten
Eine Choice hat:
- Label/Text: Was im Overlay/Chat als Option auftaucht.
- Alias (optional): Zusätzliche Chat-Kommandos.
- Ziel-Node (
target_node_id): Wohin die Choice normalerweise führt. - Würfelprobe (
roll_required): Wenn aktiviert, ersetztroll_target+roll_modifier+ getrenntesuccess_node_id/failure_node_iddas einfache Ziel. Geprüft wirdW16-Wurf + roll_modifier >= roll_target. Ohne beide Ziel-Nodes (Erfolg und Misserfolg) lässt sich die Probe nicht speichern — der Builder verlangt explizit beide Pfade. - Effekte (
effect_json): eine Liste ausadd_item,remove_item,set_variable,inc_variable,dec_variable,add_hp,damage_hp. Der Builder bildet das als Formular ab — du musst kein JSON von Hand schreiben, aber es hilft zu wissen, dass genau diese sieben Effekt-Typen existieren und alles andere ignoriert wird (vorwärtskompatibel, kein Fehler). - Conditions (
condition_json): Wann die Choice angezeigt wird.
Die Effekte laufen erst nach Voting-/Klick-Ende, nicht beim Anzeigen — wichtig fürs Verständnis bei Variablen, die eine Choice selbst mit anzeigt (z.B. „nur sichtbar wenn mut >= 3" prüft den Wert vor dem Klick, nicht danach).
Variables
Unter « Variables » legst du benannte Variablen an: Integer (mut, gold), Boolean (hat_schluessel), String (held_name). Jede Variable hat einen Startwert, mit dem jede neue Session beginnt — vergiss diesen Default nicht, sonst ist der State beim ersten Zugriff null.
Items
Unter « Items » definierst du Inventar-Gegenstände mit Name, Beschreibung und optional Icon. Effekte auf Choices: Item geben (add_item) / Item entfernen (remove_item), jeweils mit Menge. Conditions: has_item mit Mindestmenge.
Conditions — der tatsächliche Satz an Typen
Anders als ein freier „AND/OR mit Klammern"-Baukasten arbeitet die Engine mit genau diesen Condition-Typen (der Builder klickt sie für dich zusammen, aber es hilft zu wissen, was darunterliegt):
has_item— Inventar enthält Item X in Mindestmenge Y.variable_equals— Variable == Wert.variable_gte/variable_lte— Variable ≥ / ≤ Wert.hp_gte— Charakter-HP ≥ Wert (nur relevant, wenn die Quest Kampf-Nodes nutzt).all— UND-Verknüpfung einer Liste von Sub-Conditions.any— ODER-Verknüpfung einer Liste von Sub-Conditions.
Ein Beispiel für „Mut mindestens 3 UND Schlüssel im Inventar" ist technisch:
{"type":"all","conditions":[
{"type":"variable_gte","var_key":"mut","value":3},
{"type":"has_item","item_key":"schluessel","qty":1}
]}
Du klickst das im Builder zusammen, ohne JSON einzugeben. Bei komplexen, verschachtelten all/any-Kombinationen lohnt sich vorher ein Playtest-Durchlauf, um das Verhalten zu bestätigen.
Erweiterte Story-Events (jenseits von Choices)
Für Storys, die mehr wollen als Node→Choice→Node, kennt die Engine zusätzlich datengetriebene Events, die z.B. beim Betreten eines Node ausgelöst werden können: loot (vergibt mehrere Items auf einmal), trap (Wahrnehmungsprobe, bei Fehlschlag automatisch Schaden), teleport (springt direkt zu einem Node, ohne Choice), random (gewichtete Zufallsverzweigung zwischen mehreren Ziel-Nodes), sowie dialogue und npc für Sprech-/NPC-Begegnungen (setzt intern Tracking-Variablen wie __npc_<key>_attitude und _met). Diese Events sind mächtiger als das reine Node/Choice-Modell, aber im Builder-UI (Stand Beta) noch nicht überall als eigenes Formular abgebildet — für sehr spezielle Verzweigungen (z.B. gewichtete Zufallspfade) ist der Weg über die API mit direktem JSON aktuell der zuverlässigste.
Validierung
Vor « Veröffentlichen » läuft eine Validierung. Sie warnt bei:
- Choices ohne Ziel-Node (bzw. Würfelproben ohne beide Erfolgs-/Misserfolgs-Ziele).
- Nodes ohne eingehende Verbindung (außer Start-Node) — also unerreichbar.
- Endlos-Schleifen ohne
ending-Node. - Referenzen auf gelöschte Variablen/Items.
- Conditions, die immer
falsesind (z.B. widersprüchlicheall-Kombination).
Warnungen blocken nicht zwingend, Fehler schon. Lies die Liste durch, bevor du veröffentlichst.
KI-Tools im Builder
Über 🤖 KI-Tools öffnest du ein Modal mit vier Funktionen: Szene generieren (aus 1-2 Sätzen einen neuen Node-Vorschlag), Choices vorschlagen (2-4 Folge-Choices für den aktuell gewählten Node), Gegner generieren (Stats + Beschreibung aus einem Prompt, für combat-Nodes), und Body umschreiben (Ton-Variante des aktuellen Erzähltexts, überschreibt erst nach „Übernehmen").
Wichtig für Erwartungsmanagement: Das Modal ist im UI noch mit „(Stub-Modus, Real-Provider folgt)" beschriftet — das Label ist aber veraltet. Im Backend prüft AiHooks, ob ein OPENAI_API_KEY gesetzt ist: Wenn ja, geht die Anfrage tatsächlich an einen echten OpenAiProvider (Modell gpt-4o-mini per Default), der die storyquest_node/branch/enemy/tone-Anfrage-Arten explizit kennt. Nur wenn dieser Call fehlschlägt oder ein ungültiges Ergebnis liefert, fällt AiHooks auf eine deterministische Heuristik zurück (Antwort enthält dann mode: stub statt mode: real). Erwarte also bei gesetztem Key kontextsensitive Vorschläge, nicht nur generische Standardwerte — nur ohne Key oder bei Ausfall greift die Heuristik. Jeder KI-Call wird über AiAuditLogger protokolliert, unabhängig vom Stub-/Real-Status.
Vorlagen (Templates)
Auf /dashboard/storyquests gibt es « Aus Vorlage erstellen » mit sechs eingebauten Beispiel-Storys: Der Erste Schritt (Mini-Tutorial mit einer Würfelprobe), Im verzauberten Wald, Das vergessene Verlies, Die Höhle des Schattenwolfs (mit Kampf-Node und Loot), Die verlassene Klinik (Horror-Genre) und Generationsschiff Aurora (Sci-Fi, inkl. KI-Drohnen-Kampf). Jede Vorlage erzeugt eine vollständige, eigenständige Kopie in deinem Account — guter Ausgangspunkt, um Kampf-Nodes oder Würfelproben am funktionierenden Beispiel zu studieren, statt sie blind zu bauen.
Import/Export
« Export » lädt deine Quest als JSON herunter — vollständiges Backup inkl. Nodes/Choices/Items/Variablen/Grundstats. Über POST /v1/storyquests/import spielst du eine exportierte Quest (oder eine der o.g. Vorlagen im gleichen Format) in einen anderen Account ein — gut für Showcase-Sharing oder Backup. Der Import-Endpunkt ist derselbe generische Importer, den auch die Vorlagen-Erstellung intern nutzt, d.h. Export→Import ist ein garantierter Round-Trip.
Die API-Routen für die Bearbeitung sind unter /v1/storyquests/<id>/nodes, /choices, /items, /variables. Für Bulk-Operationen (z.B. 50 Nodes auf einmal anlegen) lohnt sich ein Skript gegen die API statt manuelles Klicken — insbesondere für datengetriebene Events wie random mit vielen gewichteten Branches, die im UI noch keine eigene Oberfläche haben.
Analytics
Es gibt keine Dashboard-Route /dashboard/storyquests/<id>/analytics und auch keine Heatmap/Stimm-Verteilung/Drop-off-UI im Beta-Stand — das ist im aktuellen Code nicht vorhanden. Serverseitig existiert nur GET /v1/storyquests/<id>/stats mit Finish-/Abbruch-/Wipe-Rate über alle Sessions, aber ohne eigene Anzeige im Dashboard.