Initial commit
This commit is contained in:
commit
7becdd23b6
989 changed files with 28526 additions and 0 deletions
564
scenes/logic/vn_interpreter.gd
Normal file
564
scenes/logic/vn_interpreter.gd
Normal file
|
|
@ -0,0 +1,564 @@
|
|||
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 []
|
||||
Loading…
Add table
Add a link
Reference in a new issue