godot-genre-visual-novel
Expert blueprint for visual novels (Doki Doki Literature Club, Phoenix Wright, Steins;Gate) focusing on branching narratives, dialogue systems, choice consequences, rollback mechanics, and persistent flags. Use when building story-driven, choice-based, or dating sim games. Keywords visual novel, dialogue system, branching narrative, typewriter effect, rollback, bbcode, RichTextLabel.
What this skill does
# Genre: Visual Novel
Branching narratives, meaningful choices, and quality-of-life features define visual novels.
## Core Loop
1. **Read**: Consume narrative text and character dialogue
2. **Decide**: Choose at key moments
3. **Branch**: Story diverges based on choice
4. **Consequence**: Immediate reaction or long-term flag changes
5. **Conclude**: Reach one of multiple endings
## NEVER Do (Expert Anti-Patterns)
### Narrative & Flow
- NEVER create the "Illusion of Choice" exclusively; strictly provide **Immediate Dialogue Variations** or **Flag Changes** even if the plot converges later.
- NEVER skip mandatory QoL features; strictly implement **Auto-Play**, **Fast-Forward**, and **Backlog/History** for replayability.
- NEVER display "Walls of Text"; strictly limit dialogue boxes to **3-4 Lines** max to avoid intimidating the reader.
- NEVER hardcode dialogue text inside GDScripts; strictly store narrative scripts in **External Files** (JSON, CSV, or custom Resources) for iteration.
- NEVER ignore the **Rollback** mechanic; strictly maintain a history stack so players can undo miss-clicks or reread missed lines.
### Technical & UI
- NEVER use plain text for emotional beats; strictly use **RichTextLabel BBCode** (e.g., `[shake]`, `[wave]`) to add visual weight.
- NEVER parse massive narrative files on the main thread; strictly use **`ResourceLoader.load_threaded_request()`** to prevent transition stutters.
- NEVER use standard Strings for frequently accessed game flags; strictly use **`StringName`** (&"met_alice") for faster dictionary lookups.
- NEVER use `_process` for letter-by-letter animation; strictly use a **Tween on `visible_ratio`** for smooth, frame-independent reveals.
- NEVER neglect character **Z-ordering**; strictly ensure the active speaker is brought to the front (highest `z_index`) for visual clarity.
- NEVER use `z_index` for `Control` node priority if input handling is required; strictly use `move_to_front()` to ensure draw order and input propagation match.
- NEVER use absolute pixel positioning for character sprites; strictly rely on **Anchors & Percent-based Offsets** for responsive scaling.
- NEVER allow text animations to continue when the player skips; strictly set **`visible_ratio` to 1.0** instantly on input.
- NEVER leave orphaned character sprites; strictly use **`queue_free()`** when actors exit the stage to prevent memory leaks.
---
## ๐ Expert Components (scripts/)
### Original Expert Patterns
- [story_manager.gd](scripts/story_manager.gd) - Flag-aware dialog orchestrator with branching logic and character state persistence.
- [dialogue_ui.gd](scripts/dialogue_ui.gd) - Presentation layer with typewriter tweens and choice-window generation.
- [vn_rollback_manager.gd](scripts/vn_rollback_manager.gd) - History stack maintenance for state rollback (flags/backgrounds/index).
### Modular Components
- [visual_novel_patterns.gd](scripts/visual_novel_patterns.gd) - Reusable patterns: BBCode effects, choice filtering, and sprite layering.
- [dialogue_ui.gd](scripts/dialogue_ui.gd) - Base UI core for dialogue and character management.
---
| Phase | Skills | Purpose |
|-------|--------|---------|
| 1. Text & UI | `ui-system`, `rich-text-label` | Dialogue box, bbcode effects, typewriting |
| 2. Logic | `json-parsing`, `resource-management` | Loading scripts, managing character data |
| 3. State | `godot-save-load-systems`, `dictionaries` | Flags, history, persistent data |
| 4. Audio | `audio-system` | Voice acting, background music transitions |
| 5. Polish | `godot-tweening`, `shaders` | Character transitions, background effects |
## Architecture Overview
### 1. Story Manager (The Driver)
Parses the script and directs the other systems.
```gdscript
# story_manager.gd
extends Node
var current_script: Dictionary
var current_line_index: int = 0
var flags: Dictionary = {}
func load_script(script_path: String) -> void:
var file = FileAccess.open(script_path, FileAccess.READ)
current_script = JSON.parse_string(file.get_as_text())
current_line_index = 0
display_next_line()
func display_next_line() -> void:
if current_line_index >= current_script["lines"].size():
return
var line_data = current_script["lines"][current_line_index]
if line_data.has("choice"):
present_choices(line_data["choice"])
else:
CharacterManager.show_character(line_data.get("character"), line_data.get("expression"))
DialogueUI.show_text(line_data["text"])
current_line_index += 1
```
### 2. Dialogue UI (Typewriter Effect)
Displaying text character by character.
```gdscript
# dialogue_ui.gd
func show_text(text: String) -> void:
rich_text_label.text = text
rich_text_label.visible_ratio = 0.0
var tween = create_tween()
tween.tween_property(rich_text_label, "visible_ratio", 1.0, text.length() * 0.05)
```
### 3. History & Rollback
Essential VN feature. Store the state before every line.
```gdscript
var history: Array[Dictionary] = []
func save_state_to_history() -> void:
history.append({
"line_index": current_line_index,
"flags": flags.duplicate(),
"background": current_background,
"music": current_music
})
func rollback() -> void:
if history.is_empty(): return
var trusted_state = history.pop_back()
restore_state(trusted_state)
```
## Key Mechanics Implementation
### Branching Paths (Flags)
Track decisions to influence future scenes.
```gdscript
func make_choice(choice_id: String) -> void:
match choice_id:
"be_nice":
flags["relationship_alice"] += 1
jump_to_label("alice_happy")
"be_mean":
flags["relationship_alice"] -= 1
jump_to_label("alice_sad")
### 4. Speaker Z-Ordering (Dynamic Focus)
Bring the active speaker to the front and dim others.
```gdscript
# actor_manager.gd
func focus_speaker(active_name: String) -> void:
for actor in get_children():
if not actor is CanvasItem: continue
if actor.name == active_name:
# Move to bottom of tree to render on top & catch input events
actor.move_to_front()
actor.modulate = Color.WHITE
else:
# Dim inactive actors
actor.modulate = Color(0.5, 0.5, 0.5, 1.0)
```
### 5. Asynchronous Background Loading
Prevent stutters when switching high-res assets.
```gdscript
# background_streamer.gd
var _pending_path: String = ""
func load_background(path: String) -> void:
_pending_path = path
ResourceLoader.load_threaded_request(path)
set_process(true)
func _process(_delta: float) -> void:
var status = ResourceLoader.load_threaded_get_status(_pending_path)
if status == ResourceLoader.THREAD_LOAD_LOADED:
texture = ResourceLoader.load_threaded_get(_pending_path)
set_process(false)
```
### 6. Emotional BBCode Effects
Use `RichTextLabel` with performance-first `append_text`.
```gdscript
# dialogue_printer.gd
func print_line(speaker: String, text: String, emotion: String) -> void:
var bb: String = text
match emotion:
"angry": bb = "[shake rate=30.0 level=8]%s[/shake]" % text
"sad": bb = "[wave amp=20.0 freq=2.0]%s[/wave]" % text
# Use append_text to avoid rebuilding the entire tag stack
append_text("[b]%s:[/b] %s\n" % [speaker, bb])
```
```
### Script Format (JSON vs Resource)
* **JSON**: Easy to write externally, standard format.
* **Custom Resource**: Typosafe, editable in Inspector.
* **Text Parsers**: (e.g., Markdown-like syntax) simpler for writers.
## Common Pitfalls
1. **Too Much Text**: Walls of text are intimidating. Break it up. **Fix**: Limit lines to 3-4 rows max.
2. **Illusion of Choice**: Choices that lead to the same outcome immediately feel cheap. **Fix**: Use small variations in dialogue even if the main plot converges.
3. **Missing Quality of Life**: No Skip, No Auto, No Save. **Fix**: TheseRelated in General
modeling-omnistudio-epc-catalog
IncludedSalesforce Industries CME EPC product-modeling skill for Product2-based catalog creation. Use when creating EPC products, configuring product attributes, building offer bundles with Product Child Items, or reviewing EPC DataPack JSON metadata for product catalog changes. TRIGGER when: user creates or updates Product2 EPC records, AttributeAssignment payloads, AttributeMetadata/AttributeDefaultValues, Offer bundles, or ProductChildItem relationships. DO NOT TRIGGER when: designing OmniScripts/FlexCards/Integration Procedures (use building-omnistudio-omniscript, building-omnistudio-flexcard, or building-omnistudio-integration-procedure), implementing Apex business logic (use generating-apex), or troubleshooting deployment pipelines (use deploying-metadata).
relationship-science-coach
IncludedUse this skill for direct, practical adult relationship coaching: couples conflict, repair, trust, marriage, dating, flirting, attachment patterns, emotional connection, sex, desire differences, eroticism, kink negotiation, affection, love languages, breakups, and long-term passion. Draw on Gottman, EFT and Hold Me Tight, attachment science, modern sex research, Perel, Nagoski, Kerner, Schnarch, Love and Stosny, and flexible love-language tools. Be concrete and low-hedge. Redirect only for imminent danger, abuse, coercive control, minors, non-consent, self-harm, stalking, or medical/legal/psychiatric decisions.
building-sf-integrations
IncludedSalesforce integration architecture and runtime plumbing with 120-point scoring. Use this skill to set up Named Credentials, External Credentials, External Services, REST/SOAP callout patterns, Platform Events, and Change Data Capture. TRIGGER when: user sets up Named Credentials, External Services, REST/SOAP callouts, Platform Events, CDC, or touches .namedCredential-meta.xml files. DO NOT TRIGGER when: Connected App/OAuth config (use configuring-connected-apps), Apex-only logic (use generating-apex), or data import/export (use handling-sf-data).
venue-templates
IncludedAccess comprehensive LaTeX templates, formatting requirements, and submission guidelines for major scientific publication venues (Nature, Science, PLOS, IEEE, ACM), academic conferences (NeurIPS, ICML, CVPR, CHI), research posters, and grant proposals (NSF, NIH, DOE, DARPA). This skill should be used when preparing manuscripts for journal submission, conference papers, research posters, or grant proposals and need venue-specific formatting requirements and templates.
let-fate-decide
IncludedDraws the 12 Houses of the Zodiac Tarot spread to inject entropy into planning when prompts are vague, ambiguous, or casually delegated. Interprets the spread to guide next steps. Use when the user says 'let fate decide', 'YOLO', 'whatever', 'idk', or other nonchalant phrases, makes Yu-Gi-Oh references, or when you are about to arbitrarily pick between multiple reasonable approaches. Prefer over ask-questions-if-underspecified when the user's tone is casual or playful rather than precision-seeking.
net-ops
IncludedCross-platform network troubleshooting (Windows, macOS, Linux) via local or remote shell. Use for: DNS broken, can't resolve hostnames, nslookup/dig works but apps fail, NRPT, WFP, scutil, /etc/resolver, systemd-resolved, /etc/resolv.conf, NetworkManager, VPN DNS leak residue (ProtonVPN/Mullvad/WireGuard/AnyConnect), AV/firewall blocking DNS or DoH, Tailscale DNS interaction, intermittent connectivity, remote diagnostics over SSH.