564 lines
20 KiB
GDScript
564 lines
20 KiB
GDScript
extends Node2D
|
|
|
|
# Instructions data
|
|
var vn_labels = {}
|
|
var vn_lines = []
|
|
|
|
# Runtime
|
|
var vn_can_save = false
|
|
var vn_play_advance_noise = false
|
|
var vn_hash = ""
|
|
var vn_title = ""
|
|
var vn_music = ""
|
|
var vn_pos: int = 0
|
|
var vn_pos_savestate: int = 0
|
|
var vn_pos_offset: int = 0
|
|
var vn_sprite_map = {}
|
|
var vn_bg_animation = "RESET"
|
|
var vn_overlay_color = "00000000"
|
|
var vn_vars = {}
|
|
var vn_initial_state = {}
|
|
|
|
# Instantiable scenes
|
|
@onready var vn_sprite: PackedScene = preload("res://scenes/ui_elements/vn_sprite.tscn")
|
|
|
|
enum VNInstruction {
|
|
VN_NOOP = 100,
|
|
VN_QUIT = 101,
|
|
VN_ESCAPE = 102,
|
|
VN_LOAD = 103,
|
|
VN_COMMENT = 104,
|
|
VN_SHOW_TEXTBOX = 105,
|
|
VN_HIDE_TEXTBOX = 106,
|
|
VN_EXPAND_TEXTBOX = 107,
|
|
VN_COLLAPSE_TEXTBOX = 108,
|
|
VN_TEXT = 109,
|
|
VN_CONTINUE_AFTER_TEXT = 110,
|
|
VN_STOP = 111,
|
|
VN_GOTO = 112,
|
|
VN_LABEL = 113,
|
|
VN_SET = 114,
|
|
VN_INCREMENT = 115,
|
|
VN_DECREMENT = 116,
|
|
VN_IF = 117,
|
|
VN_PROMPT = 118,
|
|
VN_WAIT = 119,
|
|
VN_CLEAR_SPRITES = 120,
|
|
VN_SET_SPRITE = 121,
|
|
VN_REMOVE_SPRITE = 122,
|
|
VN_START_MUSIC = 123,
|
|
VN_STOP_MUSIC = 124,
|
|
VN_TITLE = 125,
|
|
VN_SET_BACKGROUND = 126,
|
|
VN_OVERLAY_COLOR = 127,
|
|
VN_PLAY_VIDEO = 128,
|
|
VN_SOUND_EFFECT = 129,
|
|
}
|
|
|
|
func parse_vn_file(input_file: String):
|
|
var file = FileAccess.open(input_file, FileAccess.READ)
|
|
var parsed_labels = {}
|
|
var parsed_lines = []
|
|
var parsed_vars = []
|
|
var is_multiline_text: bool = false
|
|
var line_count = 0
|
|
while file.get_position() < file.get_length():
|
|
var line = file.get_line().lstrip(" ").rstrip(" ")
|
|
line_count += 1
|
|
if not line:
|
|
is_multiline_text = false
|
|
elif line[0] == "#":
|
|
is_multiline_text = false
|
|
parsed_lines.append([VNInstruction.VN_COMMENT, line.right(-1).lstrip(" ")])
|
|
elif line[0] == "$":
|
|
var data = line.split(" ", false)
|
|
match data[0]:
|
|
# No parameters
|
|
"$quit":
|
|
parsed_lines.append([VNInstruction.VN_QUIT])
|
|
"$end": # Alias of $quit
|
|
parsed_lines.append([VNInstruction.VN_QUIT])
|
|
"$show_textbox":
|
|
parsed_lines.append([VNInstruction.VN_SHOW_TEXTBOX])
|
|
"$hide_textbox":
|
|
parsed_lines.append([VNInstruction.VN_HIDE_TEXTBOX])
|
|
"$expand_textbox":
|
|
parsed_lines.append([VNInstruction.VN_EXPAND_TEXTBOX])
|
|
"$collapse_textbox":
|
|
parsed_lines.append([VNInstruction.VN_COLLAPSE_TEXTBOX])
|
|
"$continue_after_text":
|
|
parsed_lines.append([VNInstruction.VN_CONTINUE_AFTER_TEXT])
|
|
"$stop":
|
|
parsed_lines.append([VNInstruction.VN_STOP])
|
|
"$prompt":
|
|
parsed_lines.append([VNInstruction.VN_PROMPT])
|
|
"$clear_sprites":
|
|
parsed_lines.append([VNInstruction.VN_CLEAR_SPRITES])
|
|
"$reset_background": # Alias of $set_background RESET
|
|
parsed_lines.append([VNInstruction.VN_SET_BACKGROUND, "RESET", false])
|
|
# One parameter
|
|
"$text_new_line": # remainder_of_the_text
|
|
if is_multiline_text:
|
|
parsed_lines[-1][2] += "\n%s" % line.split(" ", false, 1)[1].lstrip(" ").rstrip(" ")
|
|
else:
|
|
assert(false, "Cannot add new line to text without a preceding text!")
|
|
continue
|
|
"$title": # some text
|
|
parsed_lines.append([VNInstruction.VN_TITLE, line.split(" ", false, 1)[1]])
|
|
"$load": # next_vn
|
|
parsed_lines.append([VNInstruction.VN_LOAD, data[1]])
|
|
"$goto": # label_name
|
|
parsed_lines.append([VNInstruction.VN_GOTO, data[1]])
|
|
"$label": # label_name
|
|
parsed_labels[data[1]] = parsed_lines.size()
|
|
parsed_lines.append([VNInstruction.VN_LABEL, data[1]])
|
|
"$increment": # var_name
|
|
# Initialize var
|
|
if not parsed_vars.has(data[1]):
|
|
parsed_vars.append(data[1])
|
|
parsed_lines.append([VNInstruction.VN_INCREMENT, data[1]])
|
|
"$decrement": # var_name
|
|
# Initialize var
|
|
if not parsed_vars.has(data[1]):
|
|
parsed_vars.append(data[1])
|
|
parsed_lines.append([VNInstruction.VN_DECREMENT, data[1]])
|
|
"$wait": # [time_secs]
|
|
parsed_lines.append([VNInstruction.VN_WAIT, float(data[1])])
|
|
"$remove_sprite": # layer_name
|
|
parsed_lines.append([VNInstruction.VN_REMOVE_SPRITE, data[1]])
|
|
"$stop_music": # [crossfade_secs]
|
|
parsed_lines.append([VNInstruction.VN_STOP_MUSIC, 5.0])
|
|
if data.size() >= 2:
|
|
parsed_lines[-1].insert(1, float(data[1]))
|
|
"$play_video": # video_name
|
|
parsed_lines.append([VNInstruction.VN_PLAY_VIDEO, data[1]])
|
|
"$sound_effect": # sfx_name
|
|
parsed_lines.append([VNInstruction.VN_SOUND_EFFECT, data[1]])
|
|
# Two parameters
|
|
"$set_background": # bg_animation_name [await_bg_animation]
|
|
if $"../Background/AnimationPlayer".has_animation(data[1]):
|
|
parsed_lines.append([VNInstruction.VN_SET_BACKGROUND, data[1], false])
|
|
if data.size() >= 3:
|
|
if data[2] == "true":
|
|
parsed_lines[-1][2] = true
|
|
elif data[2] == "false":
|
|
parsed_lines[-1][2] = false
|
|
else:
|
|
assert(false, "Invalid set_background boolean option '%s'" % data[2])
|
|
else:
|
|
assert(false, "Unknown background animation '%s'" % data[1])
|
|
"$set": # var_name var_value
|
|
# Initialize var
|
|
if not parsed_vars.has(data[1]):
|
|
parsed_vars.append(data[1])
|
|
parsed_lines.append([VNInstruction.VN_SET, data[1], int(data[2])])
|
|
"$option": # branch_label_name text
|
|
var last_line = parsed_lines[-1]
|
|
if last_line[0] == VNInstruction.VN_PROMPT:
|
|
last_line.append([data[1], line.split(" ", false, 2)[2]])
|
|
else:
|
|
assert(false, "Error on file '%s', line %d: $option command must only come after a $prompt command" % [input_file, line_count])
|
|
"$start_music": # track_name [crossfade_secs]
|
|
parsed_lines.append([VNInstruction.VN_START_MUSIC, data[1], 0.0])
|
|
if data.size() >= 3:
|
|
parsed_lines[-1].insert(2, float(data[2]))
|
|
"$overlay_color": # color [fade_secs]
|
|
parsed_lines.append([VNInstruction.VN_OVERLAY_COLOR, Color(data[1]).to_html(), 1.0])
|
|
if data.size() >= 3:
|
|
parsed_lines[-1].insert(2, float(data[2]))
|
|
# Four parameters
|
|
"$if": # var_name comparison_operator var_value branch_label_name
|
|
# Initialize var
|
|
if not parsed_vars.has(data[1]):
|
|
parsed_vars.append(data[1])
|
|
if data[2] not in [">", "<", ">=", "<=", "==", "!="]:
|
|
assert(false, "Error on file '%s', line %d: Invalid operator for $if statement: '%s'" % [input_file, line_count, data[2]])
|
|
parsed_lines.append([VNInstruction.VN_IF, data[1], data[2], int(data[3]), data[4]])
|
|
"$set_sprite": # layer_name sprite_path [animation_name [{"flip_h":true,...}]]
|
|
parsed_lines.append([VNInstruction.VN_SET_SPRITE, data[1], data[2], "RESET", {}])
|
|
if data.size() >= 4:
|
|
parsed_lines[-1][3] = data[3]
|
|
if data.size() >= 5:
|
|
parsed_lines[-1][4] = JSON.parse_string(line.split(" ", false, 4)[4])
|
|
# Variable parameters
|
|
"$escape": # [arg [...]]
|
|
parsed_lines.append([VNInstruction.VN_ESCAPE])
|
|
parsed_lines[-1].append_array(data.slice(1))
|
|
_:
|
|
assert(false, "Error on file '%s', line %d: Unknown command '%s'" % [input_file, line_count, data])
|
|
is_multiline_text = false
|
|
else:
|
|
var data = line.split(":", true, 1)
|
|
if data.size() < 1:
|
|
# Empty dialogue (i.e. line with only ":" and spaces) is ignored
|
|
continue
|
|
elif data.size() == 1:
|
|
if is_multiline_text:
|
|
parsed_lines[-1][2] += "\n%s" % data[0].lstrip(" ").rstrip(" ")
|
|
else:
|
|
parsed_lines.append([VNInstruction.VN_TEXT, "", data[0].lstrip(" ").rstrip(" ")])
|
|
is_multiline_text = true
|
|
else:
|
|
parsed_lines.append([VNInstruction.VN_TEXT, data[0].rstrip(" "), data[1].lstrip(" ")])
|
|
is_multiline_text = true
|
|
file.close()
|
|
var vn_data = {
|
|
"labels": parsed_labels,
|
|
"vars": parsed_vars,
|
|
"lines": parsed_lines,
|
|
}
|
|
# Hash data to snapshot for save states
|
|
var hash_ctx = HashingContext.new()
|
|
hash_ctx.start(HashingContext.HASH_SHA256)
|
|
# hash_ctx.update(var_to_bytes_with_objects(vn_data))
|
|
hash_ctx.update(var_to_bytes(vn_data))
|
|
vn_data["hash"] = hash_ctx.finish().hex_encode()
|
|
return vn_data
|
|
|
|
func sprite_map_to_array():
|
|
var sprite_values = vn_sprite_map.values()
|
|
sprite_values.sort_custom(func (a, b): return a["idx"] < b["idx"])
|
|
return sprite_values.map(func (sprite): return {
|
|
"layer": vn_sprite_map.find_key(sprite),
|
|
"texture": sprite["texture"],
|
|
"properties": sprite["properties"],
|
|
})
|
|
|
|
func save_vn():
|
|
return {
|
|
"hash": vn_hash,
|
|
"title": vn_title,
|
|
"pos": vn_pos_savestate - vn_pos_offset,
|
|
"sprite_list": sprite_map_to_array(),
|
|
"bg_animation": vn_bg_animation,
|
|
"overlay_color": vn_overlay_color,
|
|
"music": vn_music,
|
|
"vars": vn_vars,
|
|
"initial_state": vn_initial_state,
|
|
}
|
|
|
|
func load_vn_data(vn_data, save_state = {}):
|
|
# Next line might not be necessary...?
|
|
vn_initial_state = save_state.get("initial_state", vn_initial_state)
|
|
vn_hash = vn_data["hash"]
|
|
# Restore original VN state if hash changed (i.e. VN was modified)
|
|
if save_state.get("hash", vn_hash) != vn_hash:
|
|
save_state = save_state.get("initial_state", {})
|
|
vn_pos = save_state.get("pos", 0)
|
|
vn_vars.merge(save_state.get("vars", {}), true)
|
|
vn_title = save_state.get("title", vn_title)
|
|
vn_music = save_state.get("music", vn_music)
|
|
var sprite_list = save_state.get("sprite_list", [])
|
|
vn_bg_animation = save_state.get("bg_animation", vn_bg_animation)
|
|
vn_overlay_color = save_state.get("overlay_color", vn_overlay_color)
|
|
vn_pos_savestate = vn_pos
|
|
# Grab VN data
|
|
vn_labels = vn_data.labels
|
|
for preloaded_var in vn_data.vars:
|
|
if preloaded_var not in vn_vars:
|
|
vn_vars[preloaded_var] = 0
|
|
# vn_initial_state["vars"].merge(vn_vars, false)
|
|
vn_lines = vn_data.lines
|
|
if vn_lines.size() > 0 and vn_lines[0][0] == VNInstruction.VN_TITLE:
|
|
vn_title = vn_lines[0][1]
|
|
$"../OverlayColor/ColorRect".color = vn_overlay_color
|
|
if sprite_list:
|
|
vn_sprite_map = {}
|
|
for i in sprite_list.size():
|
|
var sprite_data = sprite_list[i]
|
|
var curr_sprite = vn_sprite.instantiate()
|
|
curr_sprite.name = sprite_data["layer"]
|
|
$"../Sprites".add_child(curr_sprite)
|
|
populate_sprite_data(curr_sprite.get_node("Sprite"), sprite_data["texture"], sprite_data["properties"])
|
|
curr_sprite.get_node("AnimationPlayer").play("RESET")
|
|
vn_sprite_map[sprite_data["layer"]] = {
|
|
"idx": i,
|
|
"texture": sprite_data["texture"],
|
|
"properties": sprite_data["properties"],
|
|
}
|
|
$"../Background/AnimationPlayer".play(vn_bg_animation)
|
|
update_window_title()
|
|
if vn_music:
|
|
if not MusicManager.is_playing("vn_music", vn_music):
|
|
MusicManager.play("vn_music", vn_music, 0.0)
|
|
# Special case: Continue main menu music only with new game
|
|
elif vn_vars.get("autostop_music", 1) == 1 and MusicManager.is_playing():
|
|
MusicManager.stop(0.0)
|
|
# Save initial state of VN (this state is restored when VN hash changes)
|
|
if save_state.is_empty() and vn_pos == 0:
|
|
vn_initial_state = {
|
|
"title": vn_title,
|
|
"pos": 0,
|
|
"sprite_list": sprite_map_to_array(),
|
|
"bg_animation": vn_bg_animation,
|
|
"overlay_color": vn_overlay_color,
|
|
"music": vn_music,
|
|
"vars": vn_vars,
|
|
}
|
|
vn_can_save = true
|
|
|
|
func populate_sprite_data(sprite_node: Sprite2D, texture: String, properties: Dictionary):
|
|
sprite_node.texture = load("res://images/sprites/%s.png" % texture)
|
|
for prop in properties:
|
|
sprite_node[prop] = properties[prop]
|
|
|
|
func update_window_title():
|
|
if vn_title:
|
|
get_window().title = "Crossing Over - %s" % vn_title
|
|
else:
|
|
get_window().title = "Crossing Over"
|
|
|
|
func can_save() -> bool:
|
|
return vn_can_save
|
|
|
|
func can_play_sfx() -> bool:
|
|
return not FileGlobals.get_global_data("muted") and not vn_vars.get("disable_sfx", 0)
|
|
|
|
func can_play_music() -> bool:
|
|
return not FileGlobals.get_global_data("muted")
|
|
|
|
func advance_sfx():
|
|
if can_play_sfx():
|
|
#SoundManager.play("vn_sfx", "advance")
|
|
SoundManager.play_varied("vn_sfx", "advance", 1.0, FileGlobals.get_global_data("volume", 0.0))
|
|
|
|
func advance_vn(label = null) -> Array:
|
|
var continue_after_text = false
|
|
if vn_play_advance_noise:
|
|
advance_sfx()
|
|
vn_play_advance_noise = false
|
|
if label:
|
|
vn_pos = vn_labels[label]
|
|
while true:
|
|
vn_can_save = false
|
|
if vn_pos >= vn_lines.size():
|
|
return ["@eof"]
|
|
var curr_line = vn_lines[vn_pos]
|
|
vn_pos_savestate = vn_pos
|
|
vn_pos_offset = 0
|
|
vn_pos += 1
|
|
match curr_line[0]:
|
|
# Textbox handling commands
|
|
VNInstruction.VN_SHOW_TEXTBOX:
|
|
await $"../Textbox".show_textbox()
|
|
VNInstruction.VN_HIDE_TEXTBOX:
|
|
await $"../Textbox".hide_textbox()
|
|
VNInstruction.VN_EXPAND_TEXTBOX:
|
|
await $"../Textbox".expand_textbox()
|
|
VNInstruction.VN_COLLAPSE_TEXTBOX:
|
|
await $"../Textbox".collapse_textbox()
|
|
VNInstruction.VN_TEXT:
|
|
vn_can_save = true
|
|
await $"../Textbox".write_text(curr_line[2], curr_line[1])
|
|
$"../ChatLog".add_line(curr_line[2], curr_line[1])
|
|
if continue_after_text:
|
|
continue_after_text = false
|
|
else:
|
|
vn_play_advance_noise = true
|
|
break
|
|
VNInstruction.VN_CONTINUE_AFTER_TEXT:
|
|
continue_after_text = true
|
|
# Control flow commands
|
|
VNInstruction.VN_NOOP:
|
|
continue
|
|
VNInstruction.VN_TITLE:
|
|
vn_title = curr_line[1]
|
|
VNInstruction.VN_QUIT:
|
|
return ["@quit"]
|
|
VNInstruction.VN_LOAD:
|
|
# return ["@load", curr_line[1], save_vn()]
|
|
return ["@load", curr_line[1]]
|
|
VNInstruction.VN_ESCAPE:
|
|
var escape_args = ["@escape"]
|
|
for arg in curr_line.slice(1):
|
|
if arg[0] == "$":
|
|
escape_args.append(vn_vars.get(arg.right(-1), arg))
|
|
else:
|
|
escape_args.append(arg)
|
|
return escape_args
|
|
VNInstruction.VN_STOP:
|
|
vn_pos_offset = 1
|
|
vn_can_save = true
|
|
vn_play_advance_noise = true
|
|
break
|
|
VNInstruction.VN_GOTO:
|
|
vn_pos = vn_labels[curr_line[1]]
|
|
VNInstruction.VN_WAIT:
|
|
$"../Textbox".disable_textbox()
|
|
$"../Timer".start(curr_line[1])
|
|
await $"../Timer".timeout
|
|
VNInstruction.VN_LABEL:
|
|
continue
|
|
VNInstruction.VN_COMMENT:
|
|
continue
|
|
VNInstruction.VN_PROMPT:
|
|
var options_array = curr_line.slice(1)
|
|
if options_array.size() <= 0:
|
|
push_warning("Skipping prompt with no complete options.")
|
|
continue
|
|
$"../Textbox".disable_textbox()
|
|
$"../Prompt".clear_options()
|
|
# Pass new options to prompt
|
|
while options_array.size() > 0:
|
|
match options_array.pop_front():
|
|
[var option_label, var option_text]:
|
|
$"../Prompt".create_option(option_label, option_text)
|
|
var invalid_option:
|
|
push_warning("Ignoring invalid option '%s'." % invalid_option)
|
|
$"../Prompt".show_prompt()
|
|
# Save any text present in the textbox
|
|
if vn_pos_savestate > 0:
|
|
if vn_lines[vn_pos_savestate - 1][0] == VNInstruction.VN_TEXT:
|
|
vn_pos_offset = 1
|
|
vn_can_save = true
|
|
#var prompt_signal = await $"../Prompt".prompt_option_selected
|
|
#var option_label = prompt_signal[0]
|
|
#var option_text = prompt_signal[1]
|
|
match await $"../Prompt".prompt_option_selected:
|
|
[var option_label, var option_text]:
|
|
advance_sfx()
|
|
await $"../Prompt".hide_prompt()
|
|
vn_pos = vn_labels[option_label]
|
|
$"../Textbox".enable_textbox()
|
|
$"../ChatLog".add_selected_option_text(option_text)
|
|
continue
|
|
VNInstruction.VN_IF:
|
|
var condition = false
|
|
match curr_line[2]:
|
|
">":
|
|
condition = vn_vars[curr_line[1]] > curr_line[3]
|
|
"<":
|
|
condition = vn_vars[curr_line[1]] < curr_line[3]
|
|
">=":
|
|
condition = vn_vars[curr_line[1]] >= curr_line[3]
|
|
"<=":
|
|
condition = vn_vars[curr_line[1]] <= curr_line[3]
|
|
"==":
|
|
condition = vn_vars[curr_line[1]] == curr_line[3]
|
|
"!=":
|
|
condition = vn_vars[curr_line[1]] != curr_line[3]
|
|
_:
|
|
push_warning("Unknown conditional operator '%s'. Not branching." % curr_line[2])
|
|
if condition:
|
|
vn_pos = vn_labels[curr_line[4]]
|
|
# Variable mangling commands
|
|
VNInstruction.VN_SET:
|
|
vn_vars[curr_line[1]] = curr_line[2]
|
|
VNInstruction.VN_INCREMENT:
|
|
vn_vars[curr_line[1]] += 1
|
|
VNInstruction.VN_DECREMENT:
|
|
vn_vars[curr_line[1]] -= 1
|
|
# Extra media
|
|
VNInstruction.VN_CLEAR_SPRITES:
|
|
vn_sprite_map = {}
|
|
for node in $"../Sprites".get_children():
|
|
node.visible = false
|
|
$"../Sprites".remove_child(node)
|
|
node.queue_free()
|
|
VNInstruction.VN_REMOVE_SPRITE:
|
|
var curr_sprite = $"../Sprites".get_node_or_null(curr_line[1])
|
|
if curr_sprite == null:
|
|
push_warning("Can't remove unknown sprite '%s'. Ignoring." % curr_line[1])
|
|
continue
|
|
#var curr_idx = vn_sprite_map.get(curr_line[1], {"idx": -1})["idx"]
|
|
var curr_idx = curr_sprite.get_index()
|
|
#if curr_idx == -1:
|
|
# push_warning("Can't remove unknown sprite '%s'. Ignoring." % curr_line[1])
|
|
# continue
|
|
vn_sprite_map.erase(curr_line[1])
|
|
for k in vn_sprite_map.keys():
|
|
if vn_sprite_map[k]["idx"] > curr_idx:
|
|
vn_sprite_map[k]["idx"] -= 1
|
|
curr_sprite.visible = false
|
|
$"../Sprites".remove_child(curr_sprite)
|
|
curr_sprite.queue_free()
|
|
VNInstruction.VN_SET_SPRITE:
|
|
var curr_sprite = $"../Sprites".get_node_or_null(curr_line[1])
|
|
# var already_exists = curr_sprite != null
|
|
if not curr_sprite:
|
|
# Create new sprite
|
|
vn_sprite_map[curr_line[1]] = {
|
|
"idx": $"../Sprites".get_children().size(),
|
|
"texture": curr_line[2],
|
|
"properties": curr_line[4],
|
|
}
|
|
curr_sprite = vn_sprite.instantiate()
|
|
curr_sprite.name = curr_line[1]
|
|
# Make sure reveal_fishing_item doesn't flash
|
|
if curr_line[3] == "reveal_fishing_item":
|
|
curr_sprite.get_node("Sprite").self_modulate = "#000"
|
|
curr_line[4].erase("self_modulate")
|
|
else:
|
|
curr_sprite.get_node("Sprite").self_modulate = "#fff"
|
|
$"../Sprites".add_child(curr_sprite)
|
|
var sprite_node = curr_sprite.get_node("Sprite") as Sprite2D
|
|
var animation_player = curr_sprite.get_node("AnimationPlayer") as AnimationPlayer
|
|
# TODO: Figure out weird bugs with sprite props
|
|
#if not already_exists:
|
|
# animation_player.queue("RESET")
|
|
populate_sprite_data(sprite_node, curr_line[2], curr_line[4])
|
|
if curr_line[3] == "RESET":
|
|
sprite_node.visible = true
|
|
sprite_node.self_modulate = "#fff"
|
|
else:
|
|
if animation_player.get_animation_library("").has_animation(curr_line[3]):
|
|
animation_player.queue(curr_line[3])
|
|
else:
|
|
push_warning("Unknown sprite animation '%s'. Skipping animation." % curr_line[3])
|
|
VNInstruction.VN_START_MUSIC:
|
|
vn_music = curr_line[1]
|
|
if MusicManager.is_playing("vn_music", vn_music):
|
|
print_debug("Already playing track '%s'" % vn_music)
|
|
else:
|
|
MusicManager.play("vn_music", vn_music, curr_line[2])
|
|
VNInstruction.VN_STOP_MUSIC:
|
|
vn_music = ""
|
|
if MusicManager.is_playing():
|
|
MusicManager.stop(curr_line[1])
|
|
VNInstruction.VN_SOUND_EFFECT:
|
|
if can_play_sfx():
|
|
#SoundManager.play("vn_sfx", curr_line[1])
|
|
SoundManager.play_varied("vn_sfx", curr_line[1], 1.0, FileGlobals.get_global_data("volume", 0.0))
|
|
VNInstruction.VN_SET_BACKGROUND:
|
|
if $"../Background/AnimationPlayer".has_animation(curr_line[1]):
|
|
vn_bg_animation = curr_line[1]
|
|
$"../Background/AnimationPlayer".play(vn_bg_animation)
|
|
if curr_line[2]:
|
|
$"../Textbox".disable_textbox()
|
|
await $"../Background/AnimationPlayer".animation_finished
|
|
else:
|
|
push_warning("Unknown background animation '%s'. Ignoring." % curr_line[1])
|
|
VNInstruction.VN_OVERLAY_COLOR:
|
|
$"../Textbox".disable_textbox()
|
|
vn_overlay_color = curr_line[1]
|
|
var color = Color.html(vn_overlay_color)
|
|
if curr_line[2] >= 0.09:
|
|
var tween = get_tree().create_tween()
|
|
tween.tween_property($"../OverlayColor/ColorRect", "color", color, curr_line[2])
|
|
await tween.finished
|
|
else:
|
|
$"../OverlayColor/ColorRect".color = color
|
|
VNInstruction.VN_PLAY_VIDEO:
|
|
var video_file = "res://media/%s.ogv" % curr_line[1]
|
|
if not FileAccess.file_exists(video_file):
|
|
assert(false, "Video '%s.ogv' not found in res://media" % curr_line[1])
|
|
continue
|
|
$"../Textbox".disable_textbox()
|
|
var video_stream = VideoStreamTheora.new()
|
|
video_stream.file = video_file
|
|
var player: VideoStreamPlayer = $"../Video/VideoStreamPlayer"
|
|
player.stream = video_stream
|
|
#if can_play_music():
|
|
# player.volume_db = -12.0 + FileGlobals.get_global_data("volume", 0.0)
|
|
#else:
|
|
# player.volume = 0
|
|
player.volume = 0
|
|
player.visible = true
|
|
player.play()
|
|
await player.finished
|
|
player.visible = false
|
|
player.stream = null
|
|
_:
|
|
push_warning("Skipping unknown command. (%s)" % curr_line)
|
|
$"../Textbox".ready_textbox()
|
|
return []
|