272 lines
8.6 KiB
GDScript
272 lines
8.6 KiB
GDScript
extends Node2D
|
|
|
|
var can_advance_text = true
|
|
|
|
var vn_current_name = null
|
|
var vn_save_state = null
|
|
|
|
var fishing_minigame_label = ""
|
|
var fishing_minigame_finished = false
|
|
var fishing_minigame_active = false
|
|
|
|
const SHOULD_SAVE_PARSED_BUFFERS = false
|
|
const START_VN_NAME = "00_content_warning"
|
|
|
|
signal autosaved
|
|
signal quick_saved
|
|
|
|
func _ready():
|
|
if not FileGlobals.has_loaded:
|
|
await FileGlobals.loaded
|
|
if not MusicManager.has_loaded:
|
|
await MusicManager.loaded
|
|
|
|
#if SHOULD_SAVE_PARSED_BUFFERS:
|
|
# parse_all_txt_scenes()
|
|
|
|
$FishingMinigame.visible = false
|
|
$ChatLog.visible = false
|
|
|
|
# Get current load source from file globals
|
|
load_game(FileGlobals.current_load_source, FileGlobals.current_load_file)
|
|
#run_visual_novel(vn_current_name, FileGlobals.current_load_source == FileGlobals.VNLoadSource.NEW_GAME, vn_save_state)
|
|
run_visual_novel(vn_current_name, false, vn_save_state)
|
|
|
|
func _process(_delta):
|
|
if Input.is_action_just_pressed("quicksave"):
|
|
if save_game(FileGlobals.VNSaveTarget.MANUAL_SAVE):
|
|
quick_saved.emit()
|
|
elif Input.is_action_just_pressed("log"):
|
|
toggle_chatlog()
|
|
elif Input.is_action_just_pressed("ui_accept"):
|
|
if should_process_click():
|
|
#if $Textbox.is_ready():
|
|
if $Textbox.is_idle():
|
|
can_advance_text = false
|
|
$TimerCanAdvanceText.start()
|
|
vn_step()
|
|
else:
|
|
$Textbox.skip()
|
|
elif Input.is_action_just_pressed("click"):
|
|
if should_process_click():
|
|
if $Textbox.is_idle():
|
|
var mouse_position = get_global_mouse_position()
|
|
if mouse_position.x <= 60 and mouse_position.y <= 60:
|
|
toggle_chatlog()
|
|
else:
|
|
can_advance_text = false
|
|
$TimerCanAdvanceText.start()
|
|
vn_step()
|
|
else:
|
|
$Textbox.skip()
|
|
#if should_advance_textbox():
|
|
# if $Textbox.is_ready():
|
|
# vn_step()
|
|
# else:
|
|
# $Textbox.skip()
|
|
|
|
func should_process_click() -> bool:
|
|
return can_advance_text and not fishing_minigame_active and not $ChatLog.visible
|
|
|
|
#func should_advance_textbox() -> bool:
|
|
# if fishing_minigame_active or $ChatLog.visible:
|
|
# return false
|
|
# if Input.is_action_just_pressed("ui_accept"):
|
|
# return true
|
|
# if Input.is_action_just_pressed("click"):
|
|
# var mouse_position = get_global_mouse_position()
|
|
# if mouse_position.x <= 60 and mouse_position.y <= 60:
|
|
# toggle_chatlog()
|
|
# return false
|
|
# return true
|
|
# return false
|
|
|
|
func toggle_chatlog():
|
|
if $ChatLog.visible:
|
|
$ChatLog.visible = false
|
|
$VNInterpreter.advance_sfx()
|
|
elif $Textbox.is_ready():
|
|
$ChatLog.visible = true
|
|
#$ChatLog.scroll_to_end()
|
|
$ChatLog/CloseChatLogButtonContainer/CloseChatLogButton.grab_focus()
|
|
$VNInterpreter.advance_sfx()
|
|
else:
|
|
print_debug("Can't open chatlog right now!")
|
|
|
|
func load_game(load_source: FileGlobals.VNLoadSource, load_file):
|
|
var save_data = FileGlobals.load_save_file(load_source, load_file)
|
|
vn_current_name = save_data.get("current_vn", START_VN_NAME)
|
|
vn_save_state = save_data.get("save_state", {})
|
|
|
|
func save_game(save_target: FileGlobals.VNSaveTarget):
|
|
#if $FishingMinigame.visible or $ChatLog.visible or not $VNInterpreter.can_save():
|
|
if $FishingMinigame.visible or not $VNInterpreter.can_save():
|
|
print_debug("Can't save VN right now!")
|
|
return false
|
|
vn_save_state = $VNInterpreter.save_vn()
|
|
FileGlobals.create_save_file(save_target, {"current_vn": vn_current_name, "save_state": vn_save_state}, vn_save_state["title"])
|
|
return true
|
|
|
|
func parse_all_txt_scenes():
|
|
DirAccess.make_dir_absolute("user://compiled_scenes")
|
|
for path in DirAccess.get_files_at("res://scenes/visual_novels"):
|
|
if path.ends_with(".txt"):
|
|
var data = $VNInterpreter.parse_vn_file("res://scenes/visual_novels/%s" % path)
|
|
var file = FileAccess.open("user://compiled_scenes/%s.buf" % path.left(-4), FileAccess.WRITE)
|
|
file.store_buffer(var_to_bytes_with_objects(data))
|
|
file.close()
|
|
|
|
func run_visual_novel(vn_scene, should_autosave: bool = false, save_state = {}):
|
|
vn_current_name = vn_scene
|
|
# Find source for current file
|
|
var file = null
|
|
# Try pre-parsed scene first
|
|
var should_parse = false
|
|
var vn_file = "res://scenes/visual_novels/%s.buf" % vn_current_name
|
|
file = FileAccess.open(vn_file, FileAccess.READ)
|
|
if file:
|
|
file.close()
|
|
else:
|
|
# Try unparsed scene
|
|
should_parse = true
|
|
vn_file = "res://scenes/visual_novels/%s.txt" % vn_current_name
|
|
file = FileAccess.open(vn_file, FileAccess.READ)
|
|
if file:
|
|
file.close()
|
|
else:
|
|
assert(false, "Cannot find next VN scene '%s'!" % vn_scene)
|
|
push_warning("Visual novel (%s) not found. Restarting visual novel..." % vn_scene)
|
|
vn_current_name = START_VN_NAME
|
|
save_state = {}
|
|
|
|
var data = null
|
|
if should_parse:
|
|
# Parse the original file
|
|
data = $VNInterpreter.parse_vn_file(vn_file)
|
|
# Store parsed data
|
|
if SHOULD_SAVE_PARSED_BUFFERS:
|
|
DirAccess.make_dir_absolute("user://compiled_scenes")
|
|
file = FileAccess.open("user://compiled_scenes/%s.buf" % vn_current_name, FileAccess.WRITE)
|
|
file.store_buffer(var_to_bytes_with_objects(data))
|
|
file.close()
|
|
else:
|
|
# Load previously parsed data directly
|
|
file = FileAccess.open(vn_file, FileAccess.READ)
|
|
data = bytes_to_var_with_objects(file.get_buffer(file.get_length()))
|
|
file.close()
|
|
|
|
# Make sure MusicManager is ready before proceeding
|
|
if not MusicManager.has_loaded:
|
|
await MusicManager.loaded
|
|
|
|
await $VNInterpreter.load_vn_data(data, save_state)
|
|
|
|
# Autosave only when loading a new VN
|
|
if should_autosave:
|
|
var saved = save_game(FileGlobals.VNSaveTarget.AUTOSAVE)
|
|
if vn_scene != START_VN_NAME and saved:
|
|
autosaved.emit()
|
|
|
|
vn_step()
|
|
|
|
func vn_step(label = null):
|
|
while true:
|
|
var vn_value = await $VNInterpreter.advance_vn(label)
|
|
label = null
|
|
match vn_value:
|
|
[]:
|
|
return
|
|
["@escape", ..]:
|
|
match vn_value.slice(1):
|
|
# @escape print my_var $my_var
|
|
["print", var value]:
|
|
print("@print ", value)
|
|
# @escape store_global name john_doe
|
|
["store_global", var key, var value]:
|
|
FileGlobals.set_global_data(key, value)
|
|
# @escape fishing done_fishing 0.5 false {"name":"label_for_fishing_01","sprite":"sprite_name_01"} {...}
|
|
["fishing", var label_finished, var difficulty_str, var boat_is_moving_str, ..]:
|
|
fishing_minigame_label = label_finished
|
|
var difficulty = float(difficulty_str)
|
|
var is_moving = boat_is_moving_str == "true"
|
|
fishing_minigame_finished = false
|
|
var targets = []
|
|
for target_json in vn_value.slice(5):
|
|
var target = JSON.parse_string(target_json)
|
|
target["sprite"] = load("res://images/sprites/fishing_targets/%s.png" % target["sprite"])
|
|
targets.append(target)
|
|
$FishingMinigame.start_fishing_minigame(targets, difficulty, is_moving)
|
|
fishing_minigame_active = true
|
|
$FishingMinigame.visible = true
|
|
#$FishingMinigame/Net.can_move = true
|
|
$TimerNetCanMove.start()
|
|
$Sprites.visible = false
|
|
$Textbox.visible = false
|
|
$OverlayColor.visible = false
|
|
$Prompt.visible = false
|
|
# $ChatLog.visible = false
|
|
can_advance_text = false
|
|
return
|
|
["return_to_fishing"]:
|
|
if fishing_minigame_finished:
|
|
$FishingMinigame.visible = false
|
|
#$FishingMinigame/Net.can_move = false
|
|
$Sprites.visible = true
|
|
$Textbox.visible = true
|
|
$OverlayColor.visible = true
|
|
$Prompt.visible = true
|
|
# $ChatLog.visible = true
|
|
label = fishing_minigame_label
|
|
else:
|
|
fishing_minigame_active = true
|
|
#$FishingMinigame/Net.can_move = true
|
|
$TimerNetCanMove.start()
|
|
$Sprites.visible = false
|
|
$Textbox.visible = false
|
|
$OverlayColor.visible = false
|
|
$Prompt.visible = false
|
|
# $ChatLog.visible = false
|
|
return
|
|
_:
|
|
push_warning("Unhandled @escape ", vn_value.slice(1))
|
|
return
|
|
["@load", var next_scene, ..]:
|
|
run_visual_novel(next_scene, true)
|
|
return
|
|
["@eof"]:
|
|
push_warning("Reached end of VN instead of exiting gracefully!")
|
|
get_tree().change_scene_to_file("res://scenes/screens/main_menu.tscn")
|
|
return
|
|
["@quit"]:
|
|
get_tree().change_scene_to_file("res://scenes/screens/main_menu.tscn")
|
|
return
|
|
_:
|
|
push_warning("Unknown interrupt ", vn_value)
|
|
|
|
func _on_fishing_minigame_fished(target_name):
|
|
can_advance_text = false
|
|
$TimerCanAdvanceText.start()
|
|
fishing_minigame_active = false
|
|
$FishingMinigame/Net.can_move = false
|
|
$Sprites.visible = true
|
|
$Textbox.visible = true
|
|
$OverlayColor.visible = true
|
|
$Prompt.visible = true
|
|
# $ChatLog.visible = true
|
|
vn_step(target_name)
|
|
|
|
func _on_fishing_minigame_fished_all_targets():
|
|
fishing_minigame_finished = true
|
|
|
|
func _on_timer_net_can_move_timeout():
|
|
$FishingMinigame/Net.can_move = true
|
|
|
|
func _on_timer_can_advance_text_timeout():
|
|
can_advance_text = true
|
|
|
|
func _on_close_chat_log_button_pressed():
|
|
toggle_chatlog()
|
|
|
|
func _on_quicksave_button_pressed():
|
|
if save_game(FileGlobals.VNSaveTarget.MANUAL_SAVE):
|
|
quick_saved.emit()
|