Loading...
Loading...
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.
npx skill4agent add thedivergentai/gd-agentic-skills godot-genre-visual-novel[wave][shake][color]| Phase | Skills | Purpose |
|---|---|---|
| 1. Text & UI | | Dialogue box, bbcode effects, typewriting |
| 2. Logic | | Loading scripts, managing character data |
| 3. State | | Flags, history, persistent data |
| 4. Audio | | Voice acting, background music transitions |
| 5. Polish | | Character transitions, background effects |
# 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# 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)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)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")[wave][shake][color]