2510 lines
70 KiB
GDScript
2510 lines
70 KiB
GDScript
tool
|
|
extends Control
|
|
|
|
|
|
|
|
|
|
|
|
var timeline:String
|
|
|
|
var alternativeChoicesOn = false;
|
|
var investigationOn = false;
|
|
|
|
|
|
var preview:bool = false
|
|
|
|
var windowSize;
|
|
|
|
enum state{
|
|
IDLE,
|
|
READY,
|
|
TYPING,
|
|
WAITING,
|
|
WAITING_INPUT,
|
|
ANIMATING
|
|
}
|
|
var _state:int = state.IDLE
|
|
|
|
var do_fade_in: = true
|
|
var dialog_faded_in_already = false
|
|
|
|
var definition_visible:bool = false
|
|
|
|
var last_mouse_mode = null
|
|
|
|
var current_default_theme = null
|
|
|
|
|
|
var settings:ConfigFile
|
|
var custom_events = {}
|
|
var record_history:bool = false
|
|
|
|
|
|
var definitions = {}
|
|
|
|
|
|
var questions
|
|
var anchors = {}
|
|
|
|
|
|
var current_timeline:String = ""
|
|
var dialog_script:Dictionary = {}
|
|
var current_event:Dictionary
|
|
var dialog_index:int = 0
|
|
var is_last_text:bool
|
|
|
|
var current_background = ""
|
|
|
|
|
|
var current_theme:ConfigFile
|
|
var current_theme_file_name = null
|
|
var history_theme:ConfigFile
|
|
var audio_data = {}
|
|
|
|
|
|
var button_container = null
|
|
|
|
|
|
|
|
|
|
onready var ChoiceButton = load("res://addons/dialogic/Nodes/ChoiceButton.tscn")
|
|
onready var Portrait = load("res://addons/dialogic/Nodes/Portrait.tscn")
|
|
onready var Background = load("res://addons/dialogic/Nodes/Background.tscn")
|
|
onready var HistoryTimeline = $History
|
|
|
|
|
|
|
|
|
|
|
|
signal event_start(type, event)
|
|
signal event_end(type)
|
|
|
|
signal text_complete(text_data)
|
|
|
|
signal timeline_start(timeline_name)
|
|
signal timeline_end(timeline_name)
|
|
|
|
signal dialogic_signal(value)
|
|
|
|
|
|
|
|
|
|
|
|
func _ready():
|
|
|
|
|
|
if Dialogic.get_variable("TimelineSave") == "Timeline_0":
|
|
$BackButton.visible = false
|
|
|
|
|
|
windowSize = Vector2(1920, 1080);
|
|
SetTooltips()
|
|
for i in $BackButton.get_children():
|
|
i.connect("mouse_entered", self, "_on_BackDialog_mouse_entered")
|
|
i.connect("mouse_exited", self, "_on_BackDialog_mouse_exited")
|
|
|
|
Engine.get_main_loop().set_meta("latest_dialogic_node", self)
|
|
|
|
load_config_files()
|
|
|
|
if Dialogic.get_variable("EasyMode") == "0":
|
|
$BackButton / LoadButton.visible = false
|
|
$BackButton / SaveButton.visible = false
|
|
$BackButton / KarmaButton.rect_position = $BackButton / SaveButton.rect_position
|
|
$BackButton / KarmaButton.rect_position.x -= 5
|
|
|
|
|
|
$CustomEvents.update()
|
|
|
|
|
|
if not timeline.empty():
|
|
set_current_dialog(timeline)
|
|
elif dialog_script.keys().size() == 0:
|
|
dialog_script = {
|
|
"events":[
|
|
{"event_id":"dialogic_001",
|
|
"character":"", "portrait":"",
|
|
"text":"[Dialogic Error] No timeline specified."}]
|
|
}
|
|
|
|
else :
|
|
load_dialog()
|
|
|
|
get_viewport().connect("size_changed", self, "resize_main")
|
|
resize_main()
|
|
if not DialogicResources.get_settings_value("dialog", "stop_mouse", true):
|
|
mouse_filter = Control.MOUSE_FILTER_IGNORE
|
|
|
|
$OptionsDelayedInput.connect("timeout", self, "_on_OptionsDelayedInput_timeout")
|
|
|
|
$DefinitionInfo.visible = false
|
|
$TextBubble.connect("text_completed", self, "_on_text_completed")
|
|
$TextBubble.connect("letter_written", self, "_on_letter_written")
|
|
$TextBubble.connect("signal_request", self, "_on_signal_request")
|
|
$TextBubble.text_label.connect("meta_hover_started", self, "_on_RichTextLabel_meta_hover_started")
|
|
$TextBubble.text_label.connect("meta_hover_ended", self, "_on_RichTextLabel_meta_hover_ended")
|
|
|
|
$TouchScreenButton.action = Dialogic.get_action_button()
|
|
|
|
if Engine.is_editor_hint():
|
|
if preview:
|
|
get_parent().connect("resized", self, "resize_main")
|
|
_init_dialog()
|
|
$DefinitionInfo.in_theme_editor = true
|
|
else :
|
|
if do_fade_in:_hide_dialog()
|
|
_init_dialog()
|
|
|
|
|
|
|
|
|
|
$BackButton / AutoReadButton.pressed = SettingsSingleton.GetAutoRead();
|
|
$BackButton / FastForwardButton.pressed = SettingsSingleton.GetSkipSeen();
|
|
|
|
|
|
|
|
func load_config_files():
|
|
|
|
if not Engine.is_editor_hint():
|
|
definitions = Dialogic._get_definitions()
|
|
else :
|
|
definitions = DialogicResources.get_default_definitions()
|
|
|
|
settings = DialogicResources.get_settings_config()
|
|
|
|
var theme_file = "res://addons/dialogic/Editor/ThemeEditor/default-theme.cfg"
|
|
if settings.has_section("theme"):
|
|
theme_file = settings.get_value("theme", "default")
|
|
current_default_theme = theme_file
|
|
current_theme = load_theme(theme_file)
|
|
|
|
|
|
if settings.has_section("history"):
|
|
record_history = settings.get_value("history", "enable_history_logging", false)
|
|
if settings.has_section_key("history", "history_theme"):
|
|
theme_file = settings.get_value("history", "history_theme")
|
|
history_theme = load_theme(theme_file)
|
|
HistoryTimeline.load_theme(history_theme)
|
|
if settings.has_section_key("history", "enable_history_logging"):
|
|
if settings.get_value("history", "enable_history_logging"):
|
|
HistoryTimeline.initalize_history()
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
$Menu / MenuLayer / Settings.setType(1);
|
|
$Menu / MenuLayer / Settings.connect("BackFromSettings", self, "backFromSettings");
|
|
$Menu / MenuLayer / Settings.connect("ReturnToGame", self, "returnToGame");
|
|
|
|
|
|
$Menu / Blur.set_polygon(PoolVector2Array([Vector2(0, 0),
|
|
Vector2(0, windowSize.y),
|
|
Vector2(windowSize.x, windowSize.y),
|
|
Vector2(windowSize.x, 0)
|
|
]))
|
|
|
|
|
|
$Karma / KarmaLayer / KarmaScene.connect("ReturnToGameFromKarma", self, "returnToGameFromKarma");
|
|
|
|
|
|
$Karma / Blur.set_polygon(PoolVector2Array([Vector2(0, 0),
|
|
Vector2(0, windowSize.y),
|
|
Vector2(windowSize.x, windowSize.y),
|
|
Vector2(windowSize.x, 0)
|
|
]))
|
|
|
|
var block_dialog_for_back_button = false
|
|
|
|
func _on_toggle_back():
|
|
var previous_event = dialog_script["events"][dialog_index - 1]
|
|
if previous_event["event_id"] == "dialogic_001":
|
|
_load_previous_event()
|
|
else :
|
|
var labelString = Dialogic.get_variable("CurrentLabel")
|
|
var labelInt = int(labelString.substr(1))
|
|
if (labelInt > 1):
|
|
labelInt -= 1
|
|
Dialogic.set_variable("BackPressed", 1)
|
|
labelString = "a" + str(labelInt)
|
|
Dialogic.set_variable("CurrentLabel", labelString)
|
|
if (_state == state.TYPING):
|
|
$TextBubble.skip()
|
|
Dialogic.change_timeline(Dialogic.get_variable("TimelineSave"))
|
|
|
|
func _on_BackDialog_mouse_entered():
|
|
block_dialog_for_back_button = true;
|
|
func _on_BackDialog_mouse_exited():
|
|
block_dialog_for_back_button = false;
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
func update_custom_events()->void :
|
|
custom_events = {}
|
|
var path:String = DialogicResources.get_working_directories()["CUSTOM_EVENTS_DIR"]
|
|
var dir = Directory.new()
|
|
if dir.open(path) == OK:
|
|
dir.list_dir_begin()
|
|
var file_name = dir.get_next()
|
|
|
|
while file_name != "":
|
|
|
|
if dir.current_is_dir() and not file_name in [".", ".."]:
|
|
|
|
|
|
|
|
var event = load(path.plus_file(file_name).plus_file("EventBlock.tscn")).instance()
|
|
if event:
|
|
custom_events[event.event_data["event_id"]] = {
|
|
"event_script":path.plus_file(file_name).plus_file("event_" + event.event_data["event_id"] + ".gd"),
|
|
"event_name":event.event_name,
|
|
}
|
|
event.queue_free()
|
|
else :
|
|
print("[D] An error occurred when trying to access a custom event.")
|
|
|
|
|
|
else :
|
|
pass
|
|
file_name = dir.get_next()
|
|
else :
|
|
print("[D] An error occurred when trying to access the custom event folder.")
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
func resize_main():
|
|
var reference = rect_size
|
|
if not Engine.is_editor_hint():
|
|
set_global_position(Vector2(0, 0))
|
|
if get_viewport() != null:
|
|
var referenceVisibleRect = get_viewport().get_visible_rect();
|
|
if referenceVisibleRect != null:
|
|
reference = referenceVisibleRect.size
|
|
|
|
|
|
var anchor = current_theme.get_value("box", "anchor", 9)
|
|
|
|
var margin_bottom = current_theme.get_value("box", "box_margin_bottom", current_theme.get_value("box", "box_margin_v", 40) * - 1)
|
|
var margin_top = current_theme.get_value("box", "box_margin_top", current_theme.get_value("box", "box_margin_v", 40))
|
|
var margin_left = current_theme.get_value("box", "box_margin_left", current_theme.get_value("box", "box_margin_h", 40))
|
|
var margin_right = current_theme.get_value("box", "box_margin_right", current_theme.get_value("box", "box_margin_h", 40) * - 1)
|
|
|
|
if anchor in [0, 1, 2]:
|
|
$TextBubble.rect_position.y = margin_top
|
|
elif anchor in [4, 5, 6]:
|
|
$TextBubble.rect_position.y = (reference.y / 2) - ($TextBubble.rect_size.y / 2)
|
|
else :
|
|
$TextBubble.rect_position.y = (reference.y) - ($TextBubble.rect_size.y) + margin_bottom
|
|
|
|
|
|
if anchor in [0, 4, 8]:
|
|
$TextBubble.rect_position.x = margin_left
|
|
elif anchor in [1, 5, 9]:
|
|
$TextBubble.rect_position.x = (reference.x / 2) - ($TextBubble.rect_size.x / 2)
|
|
else :
|
|
$TextBubble.rect_position.x = reference.x - ($TextBubble.rect_size.x) + margin_right
|
|
|
|
$TextBubble.set_text_label_size();
|
|
|
|
|
|
var pos_x = 0
|
|
if current_theme.get_value("background", "full_width", false):
|
|
if preview:
|
|
pos_x = get_parent().rect_global_position.x
|
|
$TextBubble / TextureRect.rect_global_position.x = pos_x
|
|
$TextBubble / ColorRect.rect_global_position.x = pos_x
|
|
$TextBubble / TextureRect.rect_size.x = reference.x
|
|
$TextBubble / ColorRect.rect_size.x = reference.x
|
|
else :
|
|
$TextBubble / TextureRect.rect_global_position.x = $TextBubble.rect_global_position.x
|
|
$TextBubble / ColorRect.rect_global_position.x = $TextBubble.rect_global_position.x
|
|
$TextBubble / TextureRect.rect_size.x = $TextBubble.rect_size.x
|
|
$TextBubble / ColorRect.rect_size.x = $TextBubble.rect_size.x
|
|
|
|
|
|
|
|
|
|
|
|
var button_anchor = current_theme.get_value("buttons", "anchor", 5)
|
|
|
|
var anchor_vertical = 1
|
|
var anchor_horizontal = 1
|
|
|
|
if button_anchor == 0:
|
|
anchor_vertical = 0
|
|
anchor_horizontal = 0
|
|
elif button_anchor == 1:
|
|
anchor_vertical = 0
|
|
elif button_anchor == 2:
|
|
anchor_vertical = 0
|
|
anchor_horizontal = 2
|
|
|
|
elif button_anchor == 4:
|
|
anchor_horizontal = 0
|
|
elif button_anchor == 6:
|
|
anchor_horizontal = 2
|
|
|
|
elif button_anchor == 8:
|
|
anchor_vertical = 2
|
|
anchor_horizontal = 0
|
|
elif button_anchor == 9:
|
|
anchor_vertical = 2
|
|
elif button_anchor == 10:
|
|
anchor_vertical = 2
|
|
anchor_horizontal = 2
|
|
|
|
var theme_choice_offset = current_theme.get_value("buttons", "offset", Vector2(0, 0))
|
|
var position_offset = Vector2(0, 0)
|
|
|
|
if anchor_horizontal == 0:
|
|
position_offset.x = (reference.x / 2) * - 1
|
|
elif anchor_horizontal == 1:
|
|
position_offset.x = 0
|
|
elif anchor_horizontal == 2:
|
|
position_offset.x = (reference.x / 2)
|
|
|
|
if anchor_vertical == 0:
|
|
position_offset.y -= (reference.y / 2)
|
|
elif anchor_vertical == 1:
|
|
position_offset.y += 0
|
|
elif anchor_vertical == 2:
|
|
position_offset.y += (reference.y / 2)
|
|
|
|
$Options.rect_global_position = Vector2(0, 0) + theme_choice_offset + position_offset
|
|
$Options.rect_size = reference
|
|
|
|
$Options.rect_global_position = Vector2($Options.rect_global_position.x, $Options.rect_global_position.y + windowSize.y * 0.15);
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
if settings.get_value("input", "clicking_dialog_action", true):
|
|
$TouchScreenButton.shape.extents = reference
|
|
|
|
|
|
var background = get_node_or_null("Background")
|
|
if background != null:
|
|
background.rect_size = reference
|
|
|
|
var portraits = get_node_or_null("Portraits")
|
|
if portraits != null:
|
|
portraits.rect_position.x = reference.x / 2
|
|
portraits.rect_position.y = reference.y
|
|
|
|
|
|
func deferred_resize(current_size, result, anchor):
|
|
if windowSize == null:
|
|
windowSize = Vector2(1920, 1080);
|
|
|
|
result = Vector2(windowSize.x * 0.8, windowSize.y * 0.2);
|
|
|
|
$TextBubble.rect_size = result
|
|
if current_size != $TextBubble.rect_size or current_theme.get_value("box", "anchor", 9) != anchor:
|
|
resize_main()
|
|
|
|
$TextBubble.set_text_label_size();
|
|
|
|
|
|
func load_theme(filename):
|
|
var current_theme_anchor = - 1
|
|
if current_theme:
|
|
current_theme_anchor = current_theme.get_value("box", "anchor", 9)
|
|
var load_theme = DialogicResources.get_theme_config(filename)
|
|
if not load_theme:
|
|
return current_theme
|
|
var theme = load_theme
|
|
current_theme_file_name = filename
|
|
|
|
call_deferred("deferred_resize", $TextBubble.rect_size, theme.get_value("box", "size", Vector2(910, 167)), current_theme_anchor)
|
|
|
|
$TextBubble.load_theme(theme)
|
|
HistoryTimeline.change_theme(theme)
|
|
$DefinitionInfo.load_theme(theme)
|
|
|
|
if theme.get_value("buttons", "layout", 0) == 0:
|
|
button_container = VBoxContainer.new()
|
|
else :
|
|
button_container = HBoxContainer.new()
|
|
button_container.name = "ButtonContainer"
|
|
button_container.alignment = 1
|
|
|
|
for n in $Options.get_children():
|
|
n.queue_free()
|
|
$Options.add_child(button_container)
|
|
|
|
load_audio(theme)
|
|
|
|
if theme.get_value("box", "portraits_behind_dialog_box", true):
|
|
move_child($Portraits, 0)
|
|
else :
|
|
move_child($Portraits, 1)
|
|
|
|
return theme
|
|
|
|
|
|
|
|
|
|
|
|
|
|
func load_audio(theme):
|
|
|
|
var default_audio_file = "res://addons/dialogic/Example Assets/Sound Effects/Beep.wav"
|
|
var default_audio_data = {
|
|
"enable":false,
|
|
"path":default_audio_file,
|
|
"volume":0.0,
|
|
"volume_rand_range":0.0,
|
|
"pitch":1.0,
|
|
"pitch_rand_range":0.0,
|
|
"allow_interrupt":true,
|
|
"audio_bus":AudioServer.get_bus_name(0)
|
|
}
|
|
|
|
for audio_node in $FX / Audio.get_children():
|
|
var name = audio_node.name.to_lower()
|
|
audio_data[name] = theme.get_value("audio", name, default_audio_data)
|
|
|
|
var file_system = Directory.new()
|
|
if file_system.dir_exists(audio_data[name].path):
|
|
audio_node.load_samples_from_folder(audio_data[name].path)
|
|
elif file_system.file_exists(audio_data[name].path) or file_system.file_exists(audio_data[name].path + ".import"):
|
|
audio_node.samples = [load(audio_data[name].path)]
|
|
|
|
audio_node.set_volume_db(audio_data[name].volume)
|
|
audio_node.random_volume_range = audio_data[name].volume_rand_range
|
|
audio_node.set_pitch_scale(audio_data[name].pitch)
|
|
audio_node.random_pitch_range = audio_data[name].pitch_rand_range
|
|
audio_node.set_bus(audio_data[name].audio_bus)
|
|
|
|
func play_audio(name):
|
|
var node = $FX / Audio.get_node(name.capitalize())
|
|
name = name.to_lower()
|
|
if audio_data[name].enable:
|
|
if audio_data[name].allow_interrupt or not node.is_playing():
|
|
node.play()
|
|
|
|
|
|
|
|
|
|
|
|
|
|
func set_current_dialog(dialog_path:String):
|
|
current_timeline = dialog_path
|
|
dialog_script = DialogicResources.get_timeline_json(dialog_path)
|
|
return load_dialog()
|
|
|
|
|
|
func load_dialog():
|
|
|
|
|
|
|
|
if settings.get_value("dialog", "auto_color_names", true):
|
|
dialog_script = DialogicParser.parse_characters(dialog_script)
|
|
dialog_script = DialogicParser.parse_text_lines(dialog_script, preview)
|
|
dialog_script = DialogicParser.parse_branches(self, dialog_script)
|
|
DialogicParser.parse_anchors(self)
|
|
|
|
return dialog_script
|
|
|
|
|
|
|
|
|
|
|
|
func _process(delta):
|
|
if isSpriteChoice:
|
|
$TextBubble.visible = false;
|
|
|
|
|
|
$TextBubble / NextIndicatorContainer / NextIndicator.visible = is_state(state.READY)
|
|
|
|
$Options.visible = is_state(state.WAITING_INPUT)
|
|
|
|
|
|
if current_event.has("text"):
|
|
if "[nw]" in current_event["text"] or "[nw=" in current_event["text"] or SettingsSingleton.GetAutoRead():
|
|
$TextBubble / NextIndicatorContainer / NextIndicator.visible = false
|
|
|
|
|
|
if current_theme and current_theme.get_value("settings", "dont_close_after_last_event", false) and is_last_text:
|
|
$TextBubble / NextIndicatorContainer / NextIndicator.visible = false
|
|
|
|
|
|
if is_state(state.ANIMATING):
|
|
$TextBubble / NextIndicatorContainer / NextIndicator.visible = false
|
|
|
|
var preventInput = [KEY_ENTER, KEY_X, JOY_BUTTON_0];
|
|
|
|
func _input(event:InputEvent)->void :
|
|
|
|
|
|
|
|
|
|
|
|
var debug = event.is_action_pressed(Dialogic.get_action_button())
|
|
|
|
if event is InputEventKey and event.scancode in preventInput:
|
|
return ;
|
|
|
|
if event is InputEventKey and event.pressed == false and event.scancode == KEY_M:
|
|
_on_MapButton_button_down();
|
|
return ;
|
|
|
|
if event is InputEventKey and event.pressed == false and event.scancode == KEY_F5:
|
|
if not $LoadSaveMenu.visible:
|
|
_on_SaveButton_button_down();
|
|
else :
|
|
BackFromSaveLoad();
|
|
return ;
|
|
|
|
if event is InputEventKey and event.pressed == false and event.scancode == KEY_F6:
|
|
if not $LoadSaveMenu.visible:
|
|
_on_LoadButton_button_down();
|
|
else :
|
|
BackFromSaveLoad();
|
|
return ;
|
|
|
|
|
|
if not Engine.is_editor_hint() and debug:
|
|
if isSpriteChoice:
|
|
|
|
return ;
|
|
|
|
if showMenu:
|
|
return ;
|
|
|
|
if catOnHover:
|
|
return ;
|
|
|
|
if HistoryTimeline.block_dialog_advance:
|
|
return
|
|
|
|
if block_dialog_for_back_button:
|
|
return ;
|
|
|
|
if is_state(state.WAITING):
|
|
if not current_event:
|
|
return
|
|
var timer = current_event.get("waiting_timer_skippable")
|
|
if timer:
|
|
timer.time_left = 0
|
|
else :
|
|
if is_state(state.TYPING):
|
|
|
|
$TextBubble.skip()
|
|
|
|
|
|
if current_event.has("seen"):
|
|
if current_event["seen"] and SettingsSingleton.GetSkipSeen():
|
|
$FX / CharacterVoice.stop_voice()
|
|
else :
|
|
if current_event.has("options") and not is_state(state.WAITING_INPUT):
|
|
pass
|
|
elif is_state(state.WAITING_INPUT) or is_state(state.ANIMATING):
|
|
pass
|
|
elif $TextBubble / NextIndicatorContainer / NextIndicator.is_visible():
|
|
$FX / CharacterVoice.stop_voice()
|
|
play_audio("passing")
|
|
_load_next_event()
|
|
else :
|
|
next_event(false)
|
|
if settings.has_section_key("dialog", "propagate_input"):
|
|
var propagate_input:bool = settings.get_value("dialog", "propagate_input")
|
|
if not propagate_input and not is_state(state.WAITING_INPUT):
|
|
get_tree().set_input_as_handled()
|
|
|
|
func next_event(discreetly:bool):
|
|
$FX / CharacterVoice.stop_voice()
|
|
if not discreetly:
|
|
play_audio("passing")
|
|
_load_next_event()
|
|
|
|
|
|
|
|
func _on_text_completed():
|
|
emit_signal("text_complete", current_event)
|
|
|
|
play_audio("waiting")
|
|
|
|
|
|
if current_event.has("options"):
|
|
|
|
set_state(state.WAITING_INPUT)
|
|
|
|
var waiting_until_options_enabled = float(settings.get_value("input", "delay_after_options", 0.1))
|
|
$OptionsDelayedInput.start(waiting_until_options_enabled)
|
|
|
|
|
|
var size = current_event["options"].size();
|
|
if current_event["options"][size - 1]["label"] != tr("choice3000.6"):
|
|
current_event["options"].shuffle();
|
|
|
|
var index = 0;
|
|
for o in current_event["options"]:
|
|
if _should_add_choice_button(o):
|
|
add_choice_button(o, index)
|
|
index += 1;
|
|
|
|
|
|
if SettingsSingleton.GetTwitchEnabled():
|
|
if not (current_event["options"].size() == 1 and current_event["options"][0]["label"] == tr("choiceEND")):
|
|
$Poll / SizeTimer.connect("timeout", self, "forTwitchResize")
|
|
$Poll / Timer.connect("timeout", self, "TwitchPollTimeout")
|
|
|
|
$Poll.Init(button_container.get_child_count())
|
|
else :
|
|
for i in button_container.get_children():
|
|
i.disabled = false;
|
|
|
|
|
|
|
|
|
|
|
|
|
|
if current_event.has("text"):
|
|
|
|
set_state(state.READY)
|
|
|
|
SeenTextSingleton.SerializeSeen()
|
|
|
|
var seenThis = false;
|
|
if current_event.has("seen"):
|
|
seenThis = current_event["seen"] and SettingsSingleton.GetSkipSeen();
|
|
|
|
|
|
|
|
if "[nw]" in current_event["text"] or "[nw=" in current_event["text"] or SettingsSingleton.GetAutoRead() or seenThis:
|
|
var waiting_time = 2
|
|
if seenThis:
|
|
waiting_time = 0.1
|
|
var current_index = dialog_index
|
|
if "[nw=" in current_event["text"]:
|
|
var regex = RegEx.new()
|
|
regex.compile("\\[nw=(.+?)\\](.*?)")
|
|
var result = regex.search(current_event["text"])
|
|
var wait_settings = result.get_string()
|
|
|
|
|
|
waiting_time = wait_settings.split("=")[1]
|
|
if (waiting_time.begins_with("v")):
|
|
waiting_time = $"FX/CharacterVoice".remaining_time()
|
|
else :
|
|
waiting_time = float(waiting_time)
|
|
|
|
|
|
|
|
|
|
|
|
elif SettingsSingleton.GetAutoRead():
|
|
waiting_time = 0.0
|
|
if current_event.has("voice_data"):
|
|
waiting_time = $"FX/CharacterVoice".remaining_time()
|
|
else :
|
|
waiting_time = float(waiting_time)
|
|
|
|
$DialogicTimer.start(waiting_time);yield ($DialogicTimer, "timeout")
|
|
|
|
while (showMenu):
|
|
$DialogicTimer.start(0.5);yield ($DialogicTimer, "timeout")
|
|
|
|
if dialog_index == current_index:
|
|
_load_next_event()
|
|
|
|
|
|
|
|
func _on_signal_request(name):
|
|
emit_signal("dialogic_signal", name)
|
|
|
|
|
|
func on_timeline_start():
|
|
if not Engine.is_editor_hint():
|
|
if settings.get_value("saving", "autosave", true):
|
|
|
|
Dialogic.save("", true)
|
|
|
|
emit_signal("event_start", "timeline", current_timeline)
|
|
emit_signal("timeline_start", current_timeline)
|
|
|
|
|
|
func on_timeline_end():
|
|
if not Engine.is_editor_hint():
|
|
if settings.get_value("saving", "autosave", true):
|
|
|
|
Dialogic.save("", true)
|
|
|
|
emit_signal("event_end", "timeline")
|
|
emit_signal("timeline_end", current_timeline)
|
|
|
|
|
|
func _emit_timeline_signals():
|
|
if dialog_script.has("events"):
|
|
if dialog_index == 0:
|
|
on_timeline_start()
|
|
elif _is_dialog_finished():
|
|
on_timeline_end()
|
|
|
|
|
|
|
|
func _init_dialog():
|
|
dialog_index = 0
|
|
var loading = int(Dialogic.get_variable("NeedCharacter"))
|
|
|
|
if loading == 0:
|
|
_load_event()
|
|
else :
|
|
Dialogic.set_variable("NeedCharacter", 0)
|
|
|
|
for i in range(1, 6):
|
|
var posSave = "Position" + str(i)
|
|
var emoteSave = "Emote" + str(i)
|
|
var mirrorSave = "Mirror" + str(i)
|
|
if Dialogic.get_variable(posSave) != "None":
|
|
var character_data = DialogicUtil.get_character(Dialogic.get_variable(posSave))
|
|
|
|
var p = Portrait.instance()
|
|
p.character_data = character_data
|
|
var char_portrait = Dialogic.get_variable(emoteSave)
|
|
p.init(char_portrait)
|
|
if (int(Dialogic.get_variable("Mirror" + str(i)))) == 1:
|
|
p.set_mirror(true)
|
|
|
|
$Portraits.add_child(p)
|
|
if i == 1:
|
|
p.current_state["position"] = [true, false, false, false, false]
|
|
p.move_to_position("left")
|
|
elif i == 2:
|
|
p.current_state["position"] = [false, true, false, false, false]
|
|
p.move_to_position("center_left")
|
|
elif i == 3:
|
|
p.current_state["position"] = [false, false, true, false, false]
|
|
p.move_to_position("center")
|
|
elif i == 4:
|
|
p.move_to_position("center_right")
|
|
p.current_state["position"] = [false, false, false, true, false]
|
|
elif i == 5:
|
|
p.current_state["position"] = [false, false, false, false, true]
|
|
p.move_to_position("right")
|
|
p.current_state["character"] = Dialogic.get_variable(posSave)
|
|
|
|
_load_event_at_index(int(Dialogic.get_variable("DialogIndex")))
|
|
|
|
|
|
|
|
|
|
|
|
func _load_event_at_index(index:int):
|
|
dialog_index = index
|
|
_load_event()
|
|
|
|
|
|
func _load_next_event():
|
|
dialog_index += 1
|
|
_load_event()
|
|
|
|
func _load_previous_event():
|
|
dialog_index -= 1
|
|
_load_event()
|
|
|
|
|
|
func _is_dialog_finished():
|
|
return dialog_index >= dialog_script["events"].size()
|
|
|
|
|
|
func _load_event():
|
|
if dialog_script.size() != 0:
|
|
|
|
if dialog_index + 1 >= dialog_script["events"].size():
|
|
is_last_text = true
|
|
else :
|
|
|
|
var next_event = dialog_script["events"][dialog_index + 1]
|
|
|
|
|
|
if next_event["event_id"] == "dialogic_001":
|
|
is_last_text = false
|
|
|
|
|
|
elif "end_branch_of" in next_event:
|
|
is_last_text = dialog_index + 2 >= dialog_script["events"].size()
|
|
|
|
|
|
elif "choice" in next_event and not "options" in dialog_script["events"][dialog_index]:
|
|
|
|
var index_in_questions = next_event["question_idx"]
|
|
var question = questions[index_in_questions]
|
|
var index_in_events = dialog_script["events"].rfind(question, dialog_index)
|
|
var end_index = question["end_idx"]
|
|
is_last_text = end_index + 1 >= dialog_script["events"].size()
|
|
|
|
_emit_timeline_signals()
|
|
_hide_definition_popup()
|
|
|
|
if dialog_script.has("events"):
|
|
if not _is_dialog_finished():
|
|
|
|
|
|
var func_state = event_handler(dialog_script["events"][dialog_index])
|
|
|
|
|
|
|
|
elif not Engine.is_editor_hint():
|
|
|
|
if not current_theme.get_value("settings", "dont_close_after_last_event", false):
|
|
queue_free()
|
|
|
|
|
|
func event_handler(event:Dictionary):
|
|
$TextBubble.reset()
|
|
clear_options()
|
|
|
|
current_event = event
|
|
|
|
if record_history:
|
|
HistoryTimeline.add_history_row_event(current_event, self, $History / HistoryPopup / ScrollHistoryContainer / MarginContainer / HistoryTimeline)
|
|
|
|
match event["event_id"]:
|
|
|
|
|
|
"dialogic_001":
|
|
if event["text"] != "":
|
|
|
|
if int(Dialogic.get_variable("DoNotSave")) != 1 and int(Dialogic.get_variable("EasyMode")) != 1:
|
|
Dialogic.set_variable("DialogIndex", dialog_index)
|
|
Dialogic.save("AutosaveNormal")
|
|
elif int(Dialogic.get_variable("DoNotSave")) != 1 and int(Dialogic.get_variable("EasyMode")) == 1:
|
|
Dialogic.set_variable("DialogIndex", dialog_index)
|
|
emit_signal("event_start", "text", event)
|
|
if fade_in_dialog():
|
|
yield (get_node("fade_in_tween_show_time"), "tween_completed")
|
|
set_state(state.TYPING)
|
|
if event.has("character"):
|
|
var character_data = DialogicUtil.get_character(event["character"])
|
|
grab_portrait_focus(character_data, event)
|
|
if character_data.get("data", {}).get("theme", "") and current_theme_file_name != character_data.get("data", {}).get("theme", ""):
|
|
current_theme = load_theme(character_data.get("data", {}).get("theme", ""))
|
|
elif not character_data.get("data", {}).get("theme", "") and current_default_theme and current_theme_file_name != current_default_theme:
|
|
current_theme = load_theme(current_default_theme)
|
|
update_name(character_data)
|
|
|
|
|
|
handle_voice(event)
|
|
SeenTextSingleton.AddSeen(event["originalText"]);
|
|
update_text(event["text"], event["seen"], event["originalText"])
|
|
|
|
if event["seen"] == true and SettingsSingleton.GetSkipSeen() == true:
|
|
$TextBubble.skip();
|
|
_on_text_completed();
|
|
|
|
"dialogic_002":
|
|
|
|
emit_signal("event_start", "action", event)
|
|
set_state(state.WAITING)
|
|
if event["character"] == "":
|
|
_load_next_event()
|
|
else :
|
|
var character_data = DialogicUtil.get_character(event["character"])
|
|
|
|
if event.get("type", 0) == 0 and not portrait_exists(character_data):
|
|
|
|
var p = Portrait.instance()
|
|
|
|
|
|
if current_theme.get_value("settings", "single_portrait_mode", false):
|
|
p.single_portrait_mode = true
|
|
p.character_data = character_data
|
|
p.dim_time = current_theme.get_value("animation", "dim_time", 0.5)
|
|
|
|
var char_portrait = get_portrait_name(event)
|
|
p.init(char_portrait)
|
|
p.set_mirror(event.get("mirror_portrait", false))
|
|
|
|
|
|
$Portraits.add_child(p)
|
|
p.move_to_position(get_character_position(event["position"]))
|
|
|
|
|
|
if get_character_position(event["position"]) == "left":
|
|
p.z_index = 0
|
|
Dialogic.set_variable("Position1", event["character"])
|
|
Dialogic.set_variable("Emote1", event["portrait"])
|
|
if event["mirror_portrait"] == true:
|
|
Dialogic.set_variable("Mirror1", 1)
|
|
else :Dialogic.set_variable("Mirror1", 0)
|
|
elif get_character_position(event["position"]) == "center_left":
|
|
p.z_index = - 1
|
|
Dialogic.set_variable("Position2", event["character"])
|
|
Dialogic.set_variable("Emote2", event["portrait"])
|
|
if event["mirror_portrait"] == true:
|
|
Dialogic.set_variable("Mirror2", 1)
|
|
else :Dialogic.set_variable("Mirror2", 0)
|
|
elif get_character_position(event["position"]) == "center":
|
|
p.z_index = - 2
|
|
Dialogic.set_variable("Position3", event["character"])
|
|
Dialogic.set_variable("Emote3", event["portrait"])
|
|
if event["mirror_portrait"] == true:
|
|
Dialogic.set_variable("Mirror3", 1)
|
|
else :Dialogic.set_variable("Mirror3", 0)
|
|
elif get_character_position(event["position"]) == "center_right":
|
|
p.z_index = - 1
|
|
Dialogic.set_variable("Position4", event["character"])
|
|
Dialogic.set_variable("Emote4", event["portrait"])
|
|
if event["mirror_portrait"] == true:
|
|
Dialogic.set_variable("Mirror4", 1)
|
|
else :Dialogic.set_variable("Mirror4", 0)
|
|
elif get_character_position(event["position"]) == "right":
|
|
p.z_index = 0
|
|
Dialogic.set_variable("Position5", event["character"])
|
|
Dialogic.set_variable("Emote5", event["portrait"])
|
|
if event["mirror_portrait"] == true:
|
|
Dialogic.set_variable("Mirror5", 1)
|
|
else :Dialogic.set_variable("Mirror5", 0)
|
|
|
|
event = insert_animation_data(event, "join", "fade_in_up.gd")
|
|
p.animate(event.get("animation", "[No Animation]"), event.get("animation_length", 1))
|
|
p.current_state["character"] = event["character"]
|
|
p.current_state["position"] = event["position"]
|
|
|
|
|
|
$Portraits.move_child(p, get_portrait_z_index_point(event.get("z_index", 0)))
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
elif event.get("type", 0) == 1:
|
|
if event["character"] == "[All]":
|
|
var positions = ["Position1", "Position2", "Position3", "Position4", "Position5"];
|
|
var cont = false;
|
|
for i in positions:
|
|
if Dialogic.get_variable(i) != "None":
|
|
cont = true;
|
|
|
|
if cont:
|
|
for i in positions:
|
|
Dialogic.set_variable(i, "None")
|
|
|
|
event = insert_animation_data(event, "leave", "fade_out_down.gd")
|
|
characters_leave_all(event.get("animation", "[No Animation]"), event.get("animation_length", - 1))
|
|
if event.get("animation_wait", false):
|
|
$DialogicTimer.start(event.get("animation_duration", 1))
|
|
yield ($DialogicTimer, "timeout")
|
|
else :
|
|
for p in $Portraits.get_children():
|
|
if is_instance_valid(p) and p.character_data["file"] == event["character"]:
|
|
for i in range(1, 5):
|
|
if Dialogic.get_variable("Position" + str(i)) == event["character"]:
|
|
Dialogic.set_variable("Position" + str(i), "None")
|
|
event = insert_animation_data(event, "leave", "fade_out_down.gd")
|
|
p.animate(event.get("animation", "instant_out.gd"), event.get("animation_length", 1), 1, true)
|
|
if event.get("animation_wait", false):
|
|
yield (p, "animation_finished")
|
|
|
|
|
|
else :
|
|
if portrait_exists(character_data):
|
|
for portrait in $Portraits.get_children():
|
|
if portrait.character_data.get("file", true) == character_data.get("file", false):
|
|
|
|
var portrait_name = get_portrait_name(event)
|
|
if portrait_name != portrait.current_state["portrait"]:
|
|
for i in range(1, 5):
|
|
if Dialogic.get_variable("Position" + str(i)) == event["character"]:
|
|
Dialogic.set_variable("Emote" + str(i), event["portrait"])
|
|
portrait.set_portrait(portrait_name)
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
if event.get("change_mirror_portrait", false):
|
|
portrait.set_mirror(event.get("mirror_portrait", false))
|
|
|
|
if event.get("change_z_index", false):
|
|
$Portraits.move_child(portrait, get_portrait_z_index_point(event.get("z_index", 0)))
|
|
portrait.z_index = event.get("z_index", 0)
|
|
|
|
|
|
|
|
|
|
|
|
set_state(state.READY)
|
|
_load_next_event()
|
|
|
|
|
|
|
|
"dialogic_010":
|
|
|
|
if int(Dialogic.get_variable("DoNotSave")) != 1 and Dialogic.get_variable("EasyMode") != "1":
|
|
Dialogic.set_variable("DialogIndex", dialog_index)
|
|
Dialogic.save("AutosaveNormal")
|
|
SceneManagerSingleton.TakeScreenShot("AutosaveNormal")
|
|
elif int(Dialogic.get_variable("DoNotSave")) != 1 and Dialogic.get_variable("EasyMode") == "1":
|
|
Dialogic.set_variable("DialogIndex", dialog_index)
|
|
emit_signal("event_start", "question", event)
|
|
if fade_in_dialog():
|
|
yield (get_node("fade_in_tween_show_time"), "tween_completed")
|
|
set_state(state.TYPING)
|
|
if event.has("name"):
|
|
update_name(event["name"])
|
|
elif event.has("character"):
|
|
var character_data = DialogicUtil.get_character(event["character"])
|
|
grab_portrait_focus(character_data, event)
|
|
|
|
if character_data.get("data", {}).get("theme", "") and current_theme_file_name != character_data.get("data", {}).get("theme", ""):
|
|
current_theme = load_theme(character_data.get("data", {}).get("theme", ""))
|
|
elif not character_data.get("data", {}).get("theme", "") and current_default_theme and current_theme_file_name != current_default_theme:
|
|
current_theme = load_theme(current_default_theme)
|
|
update_name(character_data)
|
|
|
|
handle_voice(event)
|
|
update_text(event["question"], false, event["originalText"])
|
|
|
|
"dialogic_011":
|
|
emit_signal("event_start", "choice", event)
|
|
for q in questions:
|
|
if q["question_idx"] == event["question_idx"]:
|
|
if q["answered"]:
|
|
|
|
_load_event_at_index(q["end_idx"])
|
|
|
|
"dialogic_012":
|
|
|
|
var def_value = null
|
|
var current_question = questions[event["question_idx"]]
|
|
|
|
for d in definitions["variables"]:
|
|
if d["id"] == event["definition"]:
|
|
def_value = d["value"]
|
|
|
|
var condition_met = def_value != null and DialogicUtil.compare_definitions(def_value, event["value"], event["condition"]);
|
|
|
|
current_question["answered"] = not condition_met
|
|
if not condition_met:
|
|
|
|
_load_event_at_index(current_question["end_idx"])
|
|
else :
|
|
|
|
_load_next_event()
|
|
|
|
"dialogic_013":
|
|
emit_signal("event_start", "endbranch", event)
|
|
_load_next_event()
|
|
|
|
"dialogic_014":
|
|
emit_signal("event_start", "set_value", event)
|
|
var operation = "="
|
|
if "operation" in event and not event["operation"].empty():
|
|
operation = event["operation"]
|
|
var value = event["set_value"]
|
|
if event.get("set_random", false):
|
|
value = str(randi() % int(event.get("random_upper_limit", 100) - event.get("random_lower_limit", 0)) + event.get("random_lower_limit", 0))
|
|
Dialogic.set_variable_from_id(event["definition"], value, operation)
|
|
|
|
|
|
KarmaChanged(event);
|
|
|
|
_load_next_event()
|
|
|
|
"dialogic_015":
|
|
emit_signal("event_start", "anchor", event)
|
|
_load_next_event()
|
|
|
|
"dialogic_016":
|
|
emit_signal("event_start", "goto", event)
|
|
dialog_index = anchors[event.get("anchor_id")]
|
|
_load_next_event()
|
|
|
|
|
|
|
|
|
|
"dialogic_020":
|
|
if not event["change_timeline"].empty():
|
|
change_timeline(event["change_timeline"])
|
|
|
|
"dialogic_021":
|
|
emit_signal("event_start", "background", event)
|
|
var fade_time = event.get("fade_duration", 1)
|
|
var value = event.get("background", "")
|
|
var background = get_node_or_null("Background")
|
|
|
|
current_background = event["background"]
|
|
if background != null:
|
|
background.name = "BackgroundFadingOut"
|
|
if not value:
|
|
background.fade_out(fade_time)
|
|
else :
|
|
background.remove_with_delay(fade_time)
|
|
background = null
|
|
|
|
if value != "":
|
|
background = Background.instance()
|
|
add_child(background)
|
|
if (event["background"].ends_with(".tscn")):
|
|
var bg_scene = load(event["background"])
|
|
bg_scene = bg_scene.instance()
|
|
background.modulate = Color(1, 1, 1, 0)
|
|
background.add_child(bg_scene)
|
|
background.fade_in(fade_time)
|
|
else :
|
|
background.texture = load(value)
|
|
background.fade_in(fade_time)
|
|
call_deferred("resize_main")
|
|
|
|
_load_next_event()
|
|
|
|
"dialogic_022":
|
|
emit_signal("event_start", "close_dialog", event)
|
|
set_state(state.ANIMATING)
|
|
var transition_duration = event.get("transition_duration", 1.0)
|
|
|
|
|
|
insert_animation_data(event, "leave", "fade_out_down")
|
|
characters_leave_all(event["animation"], event["animation_length"])
|
|
|
|
|
|
var background = get_node_or_null("Background")
|
|
if background != null:
|
|
background.name = "BackgroundFadingOut"
|
|
background.fade_out(transition_duration)
|
|
|
|
if transition_duration != 0:
|
|
var tween = Tween.new()
|
|
add_child(tween)
|
|
tween.interpolate_property($TextBubble, "modulate",
|
|
$TextBubble.modulate, Color("#00ffffff"), transition_duration,
|
|
Tween.TRANS_LINEAR, Tween.EASE_IN_OUT)
|
|
tween.start()
|
|
yield (tween, "tween_all_completed")
|
|
|
|
on_timeline_end()
|
|
queue_free()
|
|
|
|
"dialogic_023":
|
|
emit_signal("event_start", "wait", event)
|
|
if event.get("hide_dialogbox", true):
|
|
$TextBubble.visible = false
|
|
set_state(state.WAITING)
|
|
var timer = get_tree().create_timer(event["wait_seconds"])
|
|
if event.get("waiting_skippable", false):
|
|
event["waiting_timer_skippable"] = timer
|
|
yield (timer, "timeout")
|
|
event.erase("waiting_timer_skippable")
|
|
set_state(state.IDLE)
|
|
$TextBubble.visible = true
|
|
emit_signal("event_end", "wait")
|
|
_load_next_event()
|
|
|
|
"dialogic_024":
|
|
emit_signal("event_start", "set_theme", event)
|
|
if event["set_theme"] != "":
|
|
current_theme = load_theme(event["set_theme"])
|
|
current_default_theme = event["set_theme"]
|
|
resize_main()
|
|
_load_next_event()
|
|
|
|
"dialogic_025":
|
|
emit_signal("event_start", "set_glossary", event)
|
|
if event["glossary_id"]:
|
|
Dialogic.set_glossary_from_id(event["glossary_id"], event["title"], event["text"], event["extra"])
|
|
_load_next_event()
|
|
|
|
"dialogic_026":
|
|
emit_signal("event_start", "save", event)
|
|
var custom_slot:String = event.get("custom_slot", "").strip_edges()
|
|
if event.get("use_default_slot", true) or custom_slot == "":
|
|
|
|
var slot = Dialogic.get_variable("SaveSlotName");
|
|
Dialogic.save(slot)
|
|
SceneManagerSingleton.TakeScreenShot(slot)
|
|
else :
|
|
if custom_slot.begins_with("[") and custom_slot.ends_with("]"):
|
|
custom_slot = custom_slot.trim_prefix("[").trim_suffix("]")
|
|
var saved = false
|
|
for definition in definitions["variables"]:
|
|
if definition["name"] == custom_slot:
|
|
Dialogic.save(definition["value"])
|
|
saved = true
|
|
if not saved:
|
|
print("[D] Tried to access value definition '" + custom_slot + "' for saving, but it didn't exist.")
|
|
else :
|
|
Dialogic.save(custom_slot)
|
|
|
|
_load_next_event()
|
|
|
|
|
|
|
|
"dialogic_030":
|
|
emit_signal("event_start", "audio", event)
|
|
if event["audio"] == "play" and "file" in event.keys() and not event["file"].empty():
|
|
var audio = get_node_or_null("AudioEvent")
|
|
if audio == null:
|
|
audio = AudioStreamPlayer.new()
|
|
audio.name = "AudioEvent"
|
|
add_child(audio)
|
|
if event.has("audio_bus"):
|
|
if AudioServer.get_bus_index(event["audio_bus"]) >= 0:
|
|
audio.bus = event["audio_bus"]
|
|
if event.has("volume"):
|
|
audio.volume_db = event["volume"]
|
|
audio.stream = load(event["file"])
|
|
audio.play()
|
|
else :
|
|
var audio = get_node_or_null("AudioEvent")
|
|
if audio != null:
|
|
audio.stop()
|
|
audio.queue_free()
|
|
_load_next_event()
|
|
|
|
"dialogic_031":
|
|
emit_signal("event_start", "background-music", event)
|
|
if event["background-music"] == "play" and "file" in event.keys() and not event["file"].empty():
|
|
$FX / BackgroundMusic.crossfade_to(event["file"], event.get("audio_bus", "Master"), event.get("volume", 0), event.get("fade_length", 1))
|
|
else :
|
|
$FX / BackgroundMusic.fade_out(event.get("fade_length", 1))
|
|
_load_next_event()
|
|
|
|
|
|
|
|
"dialogic_040":
|
|
emit_signal("dialogic_signal", event["emit_signal"])
|
|
|
|
if event["emit_signal"] == "NormalSave":
|
|
if int(Dialogic.get_variable("EasyMode")) != 1:
|
|
Dialogic.set_variable("DialogIndex", dialog_index)
|
|
Dialogic.save("AutosaveNormal")
|
|
SceneManagerSingleton.TakeScreenShot("AutosaveNormal")
|
|
elif int(Dialogic.get_variable("EasyMode")) == 1:
|
|
Dialogic.set_variable("DialogIndex", dialog_index)
|
|
if event["emit_signal"] == "EasySave":
|
|
if int(Dialogic.get_variable("EasyMode")) == 1:
|
|
Dialogic.save("AutosaveCasual")
|
|
SceneManagerSingleton.TakeScreenShot("AutosaveCasual")
|
|
_load_next_event()
|
|
|
|
"dialogic_041":
|
|
if event.has("scene"):
|
|
get_tree().change_scene(event["scene"])
|
|
elif event.has("change_scene"):
|
|
get_tree().change_scene(event["change_scene"])
|
|
|
|
"dialogic_042":
|
|
emit_signal("event_start", "call_node", event)
|
|
$TextBubble.visible = false
|
|
set_state(state.WAITING)
|
|
|
|
var target = get_node_or_null(event["call_node"]["target_node_path"])
|
|
if not target:
|
|
target = get_tree().root.get_node_or_null(event["call_node"]["target_node_path"])
|
|
var method_name = event["call_node"]["method_name"]
|
|
var args = event["call_node"]["arguments"]
|
|
if ( not args is Array):
|
|
args = []
|
|
|
|
var waitBackground = false;
|
|
|
|
if is_instance_valid(target):
|
|
if target.has_method(method_name):
|
|
var func_result = target.callv(method_name, args)
|
|
|
|
if (func_result is GDScriptFunctionState):
|
|
yield (func_result, "completed")
|
|
|
|
waitBackground = func_result;
|
|
|
|
if (event["call_node"]["method_name"] == "setBackground"):
|
|
if waitBackground:
|
|
var game = get_tree().root.get_node("Root");
|
|
yield (game, "backgroundLoaded")
|
|
|
|
|
|
|
|
if (event["call_node"]["method_name"] == "AlternativeChoices"):
|
|
var game = get_tree().root.get_node("Root");
|
|
yield (game, "alt_choice_completed")
|
|
$Map.DisableAllPlaces();
|
|
|
|
if (event["call_node"]["method_name"] == "Investigation"):
|
|
var game = get_tree().root.get_node("Root");
|
|
yield (game, "alt_choice_completed")
|
|
|
|
set_state(state.IDLE)
|
|
$TextBubble.visible = true
|
|
|
|
_load_next_event()
|
|
_:
|
|
if event["event_id"] in $CustomEvents.handlers.keys():
|
|
|
|
var handler = $CustomEvents.handlers[event["event_id"]]
|
|
handler.handle_event(event, self)
|
|
else :
|
|
visible = false
|
|
|
|
func change_timeline(timeline):
|
|
dialog_script = set_current_dialog(timeline)
|
|
|
|
var timelineDict = DialogicUtil.get_timeline_dict()
|
|
|
|
|
|
var timelineRealName = timelineDict[timeline]["name"];
|
|
|
|
|
|
Dialogic.set_variable("TimelineSave", timelineRealName)
|
|
|
|
|
|
Dialogic.set_variable("DialogIndex", 0)
|
|
|
|
|
|
if int(Dialogic.get_variable("DoNotSave")) != 1 and Dialogic.get_variable("EasyMode") != "1":
|
|
Dialogic.save("AutosaveNormal")
|
|
SceneManagerSingleton.TakeScreenShot("AutosaveNormal")
|
|
_init_dialog()
|
|
|
|
|
|
|
|
|
|
|
|
func update_name(character)->void :
|
|
if character.has("name"):
|
|
var parsed_name = character["name"]
|
|
if character["data"].get("display_name_bool", false):
|
|
if character["display_name"] != "":
|
|
parsed_name = character["display_name"]
|
|
parsed_name = DialogicParser.parse_definitions(self, parsed_name, true, false)
|
|
$TextBubble.update_name(parsed_name, character.get("color", Color.white), current_theme.get_value("name", "auto_color", true))
|
|
else :
|
|
$TextBubble.update_name("")
|
|
|
|
|
|
|
|
func update_text(text:String, seen:bool, text_code:String)->String:
|
|
if settings.get_value("dialog", "translations", false):
|
|
text = tr(text)
|
|
var final_text = DialogicParser.parse_definitions(self, DialogicParser.parse_alignment(self, text))
|
|
final_text = final_text.replace("[br]", "\n")
|
|
|
|
|
|
if $TextBubble.modulate.a == 0.0:
|
|
$TextBubble.call_deferred("set_modulate", Color(1, 1, 1, 1));
|
|
|
|
|
|
$TextBubble.update_text(final_text, seen)
|
|
return final_text
|
|
|
|
|
|
func _on_letter_written():
|
|
play_audio("typing")
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
func answer_question(i, event_idx, question_idx):
|
|
|
|
if int(Dialogic.get_variable("DoNotSave")) != 1 and Dialogic.get_variable("EasyMode") == "1":
|
|
Dialogic.save("AutosaveCasual")
|
|
SceneManagerSingleton.TakeScreenShot("AutosaveCasual")
|
|
|
|
|
|
|
|
for button in button_container.get_children():
|
|
if button.disabled == true:
|
|
return ;
|
|
|
|
(i as Button).disabled = true;
|
|
|
|
|
|
if $Poll.inited:
|
|
$Poll.Disconnect();
|
|
$Poll / Timer.disconnect("timeout", self, "TwitchPollTimeout")
|
|
if $Poll / SizeTimer.is_connected("timeout", self, "forTwitchResize"):
|
|
$Poll / SizeTimer.disconnect("timeout", self, "forTwitchResize")
|
|
|
|
play_audio("selecting")
|
|
|
|
clear_options()
|
|
|
|
|
|
questions[question_idx]["answered"] = true
|
|
_load_event_at_index(event_idx + 1)
|
|
|
|
if record_history:
|
|
HistoryTimeline.add_answer_to_question(str(i.text))
|
|
|
|
|
|
if last_mouse_mode != null:
|
|
Input.set_mouse_mode(last_mouse_mode)
|
|
last_mouse_mode = null
|
|
|
|
|
|
func clear_options():
|
|
|
|
for option in button_container.get_children():
|
|
option.queue_free()
|
|
|
|
|
|
var numberKeys = [KEY_1, KEY_2, KEY_3, KEY_4, KEY_5, KEY_6, KEY_7, KEY_8, KEY_9];
|
|
|
|
|
|
func add_choice_button(option:Dictionary, index:int)->Button:
|
|
var labelText = str("#", index + 1, " ", option["label"]);
|
|
var button = get_classic_choice_button(labelText)
|
|
button_container.set("custom_constants/separation", current_theme.get_value("buttons", "gap", 20))
|
|
|
|
if SettingsSingleton.GetTwitchEnabled():
|
|
button.disabled = true;
|
|
|
|
button_container.add_child(button)
|
|
|
|
var hotkey
|
|
var buttonCount = button_container.get_child_count()
|
|
var hotkeyOption = settings.get_value("input", str("choice_hotkey_", buttonCount), "")
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
var key = numberKeys[index];
|
|
|
|
hotkey = InputEventKey.new();
|
|
hotkey.scancode = key;
|
|
|
|
if hotkeyOption != "[None]" or settings.get_value("input", "enable_default_shortcut", false) == true:
|
|
var shortcut = ShortCut.new()
|
|
shortcut.set_shortcut(hotkey)
|
|
|
|
button.set_shortcut(shortcut)
|
|
button.shortcut_in_tooltip = false
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
button.connect("focus_entered", self, "_on_option_hovered", [button])
|
|
button.connect("mouse_entered", self, "_on_option_focused")
|
|
|
|
button.set_meta("event_idx", option["event_idx"])
|
|
button.set_meta("question_idx", option["question_idx"])
|
|
|
|
if Input.get_mouse_mode() != Input.MOUSE_MODE_VISIBLE:
|
|
last_mouse_mode = Input.get_mouse_mode()
|
|
Input.set_mouse_mode(Input.MOUSE_MODE_VISIBLE)
|
|
|
|
return button
|
|
|
|
|
|
func _should_add_choice_button(option:Dictionary):
|
|
if not option["definition"].empty():
|
|
var def_value = null
|
|
for d in definitions["variables"]:
|
|
if d["id"] == option["definition"]:
|
|
def_value = d["value"]
|
|
return def_value != null and DialogicUtil.compare_definitions(def_value, option["value"], option["condition"]);
|
|
else :
|
|
return true
|
|
|
|
|
|
func get_custom_choice_button(label:String):
|
|
var theme = current_theme
|
|
var custom_path = current_theme.get_value("buttons", "custom_path", "")
|
|
var CustomChoiceButton = load(custom_path)
|
|
var button = CustomChoiceButton.instance()
|
|
button.text = label
|
|
return button
|
|
|
|
|
|
func get_classic_choice_button(label:String):
|
|
var theme = current_theme
|
|
var button:Button = ChoiceButton.instance()
|
|
|
|
var spaceText = ""
|
|
for i in range(0, label.length() / 7):
|
|
spaceText += " ";
|
|
|
|
button.text = spaceText + label + spaceText
|
|
|
|
|
|
|
|
button.set("custom_styles/focus", StyleBoxEmpty.new())
|
|
|
|
|
|
|
|
|
|
if theme.get_value("buttons", "fixed", false):
|
|
var size = theme.get_value("buttons", "fixed_size", Vector2(130, 40))
|
|
button.rect_min_size = size
|
|
button.rect_size = size
|
|
|
|
button_container.set("custom_constants/separation", theme.get_value("buttons", "gap", 20))
|
|
|
|
|
|
var default_background = "res://addons/dialogic/Example Assets/backgrounds/background-2.png"
|
|
var default_style = [
|
|
false,
|
|
Color.white,
|
|
false,
|
|
Color.black,
|
|
true,
|
|
default_background,
|
|
false,
|
|
Color.white,
|
|
]
|
|
|
|
var hover_style = [true, Color(0.698039, 0.698039, 0.698039, 1), false, Color.black, true, default_background, false, Color.white]
|
|
|
|
var style_normal = theme.get_value("buttons", "normal", default_style)
|
|
var style_hover = theme.get_value("buttons", "hover", hover_style)
|
|
var style_pressed = theme.get_value("buttons", "pressed", default_style)
|
|
var style_disabled = theme.get_value("buttons", "disabled", default_style)
|
|
|
|
|
|
var default_color:Color
|
|
if SettingsSingleton.GetDefaultTheme():
|
|
default_color = Color(theme.get_value("text", "color", "#ffffffff"))
|
|
else :
|
|
var newcolor = SettingsSingleton.GetTextColor()
|
|
default_color = Color(newcolor)
|
|
|
|
button.set("custom_colors/font_color", default_color)
|
|
button.set("custom_colors/font_color_hover", default_color.lightened(0.2))
|
|
button.set("custom_colors/font_color_pressed", default_color.darkened(0.2))
|
|
button.set("custom_colors/font_color_disabled", default_color.darkened(0.8))
|
|
|
|
if style_normal[0]:
|
|
button.set("custom_colors/font_color", style_normal[1])
|
|
if style_hover[0]:
|
|
button.set("custom_colors/font_color_hover", style_hover[1])
|
|
if style_pressed[0]:
|
|
button.set("custom_colors/font_color_pressed", style_pressed[1])
|
|
if style_disabled[0]:
|
|
button.set("custom_colors/font_color_disabled", style_disabled[1])
|
|
|
|
|
|
|
|
button_style_setter("normal", style_normal, button, theme)
|
|
button_style_setter("hover", style_hover, button, theme)
|
|
button_style_setter("pressed", style_pressed, button, theme)
|
|
button_style_setter("disabled", style_disabled, button, theme)
|
|
|
|
|
|
windowSize = SettingsSingleton.GetCurrectScreenResolutionVector2()
|
|
var font = button.get_font("font");
|
|
var fontSize = round(0.0333333 * windowSize.y - 0.333333);
|
|
font.size = fontSize;
|
|
button.add_font_override("font", font);
|
|
|
|
return button
|
|
|
|
func UpdateButtonTheme():
|
|
if current_theme == null:
|
|
return ;
|
|
|
|
var theme = current_theme
|
|
var default_background = "res://addons/dialogic/Example Assets/backgrounds/background-2.png"
|
|
var default_style = [
|
|
false,
|
|
Color.white,
|
|
false,
|
|
Color.black,
|
|
true,
|
|
default_background,
|
|
false,
|
|
Color.white,
|
|
]
|
|
|
|
var hover_style = [true, Color(0.698039, 0.698039, 0.698039, 1), false, Color.black, true, default_background, false, Color.white]
|
|
|
|
var style_normal = theme.get_value("buttons", "normal", default_style)
|
|
var style_hover = theme.get_value("buttons", "hover", hover_style)
|
|
var style_pressed = theme.get_value("buttons", "pressed", default_style)
|
|
var style_disabled = theme.get_value("buttons", "disabled", default_style)
|
|
|
|
var default_color:Color
|
|
|
|
if SettingsSingleton.GetDefaultTheme():
|
|
default_color = Color(theme.get_value("text", "color", "#ffffffff"))
|
|
for i in $Options.get_child(0).get_children():
|
|
button_style_setter("normal", style_normal, i, theme)
|
|
button_style_setter("hover", style_hover, i, theme)
|
|
button_style_setter("pressed", style_pressed, i, theme)
|
|
button_style_setter("disabled", style_disabled, i, theme)
|
|
i.set("custom_colors/font_color", default_color)
|
|
i.set("custom_colors/font_color_hover", default_color.lightened(0.2))
|
|
i.set("custom_colors/font_color_pressed", default_color.darkened(0.2))
|
|
i.set("custom_colors/font_color_disabled", default_color.darkened(0.8))
|
|
else :
|
|
var newcolor = SettingsSingleton.GetTextColor()
|
|
default_color = Color(newcolor)
|
|
for i in $Options.get_child(0).get_children():
|
|
button_style_setter("normal", style_normal, i, theme)
|
|
button_style_setter("hover", style_hover, i, theme)
|
|
button_style_setter("pressed", style_pressed, i, theme)
|
|
button_style_setter("disabled", style_disabled, i, theme)
|
|
i.set("custom_colors/font_color", default_color)
|
|
i.set("custom_colors/font_color_hover", default_color.lightened(0.2))
|
|
i.set("custom_colors/font_color_pressed", default_color.darkened(0.2))
|
|
i.set("custom_colors/font_color_disabled", default_color.darkened(0.8))
|
|
|
|
|
|
func button_style_setter(section, data, button, theme):
|
|
var style_box = StyleBoxTexture.new()
|
|
if data[2]:
|
|
|
|
style_box.set("texture", DialogicUtil.path_fixer_load("res://addons/dialogic/Images/Plugin/white-texture.png"))
|
|
style_box.set("modulate_color", data[3])
|
|
else :
|
|
if data[4]:
|
|
style_box.set("texture", DialogicUtil.path_fixer_load(data[5]))
|
|
if SettingsSingleton.GetDefaultTheme():
|
|
style_box.set("modulate_color", Color("#ffffffff"))
|
|
else :
|
|
style_box.set("texture", load("res://resources/graphics/GUI/ChoiceButtonTextureWhite.webp"))
|
|
style_box.set("modulate_color", SettingsSingleton.GetBackgroundColor())
|
|
if data[6]:
|
|
style_box.set("modulate_color", data[7])
|
|
|
|
|
|
var padding = theme.get_value("buttons", "padding", Vector2(5, 5))
|
|
style_box.set("margin_left", padding.x)
|
|
style_box.set("margin_right", padding.x)
|
|
style_box.set("margin_top", padding.y)
|
|
style_box.set("margin_bottom", padding.y)
|
|
button.set("custom_styles/" + section, style_box)
|
|
|
|
|
|
func _on_option_hovered(button):
|
|
button.grab_focus()
|
|
|
|
|
|
func _on_option_focused():
|
|
play_audio("hovering")
|
|
|
|
|
|
func _on_OptionsDelayedInput_timeout():
|
|
for button in button_container.get_children():
|
|
if button.is_connected("pressed", self, "answer_question") == false:
|
|
button.connect("pressed", self, "answer_question", [button, button.get_meta("event_idx"), button.get_meta("question_idx")])
|
|
|
|
|
|
|
|
|
|
|
|
func handle_voice(event):
|
|
var settings_file = DialogicResources.get_settings_config()
|
|
if not settings_file.get_value("dialog", "text_event_audio_enable", false):
|
|
return
|
|
|
|
if Engine.is_editor_hint():
|
|
return
|
|
|
|
if event.has("voice_data"):
|
|
var voice_data = event["voice_data"]
|
|
if voice_data.has("0"):
|
|
if current_event["event_id"] == "dialogic_010":
|
|
$FX / CharacterVoice.play_voice(voice_data["0"])
|
|
elif not (current_event["seen"] and SettingsSingleton.GetSkipSeen()):
|
|
$FX / CharacterVoice.play_voice(voice_data["0"])
|
|
return
|
|
|
|
$FX / CharacterVoice.stop_voice()
|
|
|
|
|
|
|
|
|
|
|
|
func grab_portrait_focus(character_data, event:Dictionary = {})->bool:
|
|
var exists = false
|
|
for portrait in $Portraits.get_children():
|
|
|
|
if portrait.character_data.get("file", "something") == character_data.get("file", "none"):
|
|
exists = true
|
|
portrait.focus()
|
|
if event.has("portrait"):
|
|
portrait.set_portrait(get_portrait_name(event))
|
|
if settings.get_value("dialog", "recenter_portrait", true):
|
|
portrait.move_to_position(portrait.direction)
|
|
else :
|
|
portrait.focusout(Color(current_theme.get_value("animation", "dim_color", "#ff808080")))
|
|
return exists
|
|
|
|
|
|
func portrait_exists(character_data)->bool:
|
|
var exists = false
|
|
for portrait in $Portraits.get_children():
|
|
if portrait.character_data.get("file", true) == character_data.get("file", false):
|
|
exists = true
|
|
return exists
|
|
|
|
|
|
func get_character_position(positions)->String:
|
|
if positions["0"]:
|
|
return "left"
|
|
if positions["1"]:
|
|
return "center_left"
|
|
if positions["2"]:
|
|
return "center"
|
|
if positions["3"]:
|
|
return "center_right"
|
|
if positions["4"]:
|
|
return "right"
|
|
return "left"
|
|
|
|
|
|
func get_portrait_name(event_data):
|
|
var char_portrait = event_data["portrait"]
|
|
if char_portrait == "":
|
|
char_portrait = "(Don't change)"
|
|
|
|
if char_portrait == "[Definition]" and event_data.has("port_defn"):
|
|
var portrait_definition = event_data["port_defn"]
|
|
if portrait_definition != "":
|
|
for d in Dialogic._get_definitions()["variables"]:
|
|
if d["id"] == portrait_definition:
|
|
char_portrait = d["value"]
|
|
break
|
|
return char_portrait
|
|
|
|
|
|
func insert_animation_data(event_data, type = "join", default = "fade_in_up"):
|
|
var animation = event_data.get("animation", "[Default]")
|
|
var length = event_data.get("animation_length", 0.5)
|
|
if animation == "[Default]":
|
|
animation = DialogicResources.get_settings_value("animations", "default_" + type + "_animation", default)
|
|
length = DialogicResources.get_settings_value("animations", "default_" + type + "_animation_length", 0.5)
|
|
event_data["animation"] = animation
|
|
event_data["animation_length"] = length
|
|
return event_data
|
|
|
|
|
|
func characters_leave_all(animation, time):
|
|
var portraits = get_node_or_null("Portraits")
|
|
if portraits != null:
|
|
for p in portraits.get_children():
|
|
p.animate(animation, time, 1, true)
|
|
|
|
|
|
func get_portrait_z_index_point(z_index):
|
|
for i in range($Portraits.get_child_count()):
|
|
if $Portraits.get_child(i).z_index >= z_index:
|
|
return i
|
|
return $Portraits.get_child_count()
|
|
|
|
|
|
|
|
|
|
func _should_show_glossary():
|
|
if current_theme != null:
|
|
return current_theme.get_value("definitions", "show_glossary", true)
|
|
return true
|
|
|
|
|
|
func _on_RichTextLabel_meta_hover_started(meta):
|
|
var correct_type = false
|
|
for d in definitions["glossary"]:
|
|
if d["id"] == meta:
|
|
$DefinitionInfo.load_preview({
|
|
"title":d["title"],
|
|
"body":DialogicParser.parse_definitions(self, d["text"], true, false),
|
|
"extra":d["extra"],
|
|
})
|
|
correct_type = true
|
|
|
|
if correct_type:
|
|
definition_visible = true
|
|
$DefinitionInfo.visible = definition_visible
|
|
|
|
$DefinitionInfo / Timer.stop()
|
|
|
|
|
|
func _on_RichTextLabel_meta_hover_ended(meta):
|
|
|
|
$DefinitionInfo / Timer.start(0.1)
|
|
|
|
|
|
func _hide_definition_popup():
|
|
definition_visible = false
|
|
$DefinitionInfo.visible = definition_visible
|
|
|
|
|
|
func _on_Definition_Timer_timeout():
|
|
|
|
definition_visible = false
|
|
$DefinitionInfo.visible = definition_visible
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
func _hide_dialog():
|
|
$TextBubble.clear()
|
|
$TextBubble.modulate = Color(1, 1, 1, 0)
|
|
dialog_faded_in_already = false
|
|
|
|
|
|
func fade_in_dialog(time = 0.5):
|
|
visible = true
|
|
time = current_theme.get_value("animation", "show_time", 0.5)
|
|
var has_tween = false
|
|
|
|
if Engine.is_editor_hint() == false:
|
|
if dialog_faded_in_already == false and do_fade_in:
|
|
var tween = Tween.new()
|
|
add_child(tween)
|
|
|
|
|
|
tween.name = "fade_in_tween_show_time"
|
|
$TextBubble.modulate.a = 0
|
|
tween.interpolate_property($TextBubble, "modulate",
|
|
$TextBubble.modulate, Color(1, 1, 1, 1), time,
|
|
Tween.TRANS_LINEAR, Tween.EASE_IN_OUT)
|
|
tween.start()
|
|
tween.connect("tween_completed", self, "finished_fade_in_dialog", [tween])
|
|
has_tween = true
|
|
|
|
if has_tween:
|
|
set_state(state.ANIMATING)
|
|
dialog_faded_in_already = true
|
|
return true
|
|
return false
|
|
|
|
|
|
func finished_fade_in_dialog(object, key, node):
|
|
node.queue_free()
|
|
if not current_event.has("options"):
|
|
set_state(state.IDLE)
|
|
dialog_faded_in_already = true
|
|
|
|
|
|
|
|
|
|
|
|
func get_current_state_info():
|
|
var state = {}
|
|
|
|
|
|
state["portraits"] = []
|
|
for portrait in $Portraits.get_children():
|
|
state["portraits"].append(portrait.current_state)
|
|
state["portraits"][ - 1]["z_index"] = portrait.z_index
|
|
|
|
|
|
state["background_music"] = $FX / BackgroundMusic.get_current_info()
|
|
|
|
|
|
state["timeline"] = current_timeline
|
|
state["event_idx"] = dialog_index
|
|
|
|
|
|
state["background"] = current_background
|
|
|
|
return state
|
|
|
|
|
|
func resume_state_from_info(state_info):
|
|
|
|
|
|
do_fade_in = false
|
|
yield (self, "ready")
|
|
|
|
|
|
|
|
|
|
|
|
for saved_portrait in state_info["portraits"]:
|
|
var event = saved_portrait
|
|
|
|
|
|
var character_data = DialogicUtil.get_character(event["character"])
|
|
if portrait_exists(character_data):
|
|
for portrait in $Portraits.get_children():
|
|
if portrait.character_data == character_data:
|
|
portrait.move_to_position(get_character_position(event["position"]))
|
|
portrait.set_mirror(event.get("mirror", false))
|
|
else :
|
|
var p = Portrait.instance()
|
|
var char_portrait = event["portrait"]
|
|
if char_portrait == "":
|
|
char_portrait = "Default"
|
|
|
|
if char_portrait == "[Definition]" and event.has("port_defn"):
|
|
var portrait_definition = event["port_defn"]
|
|
if portrait_definition != "":
|
|
for d in DialogicResources.get_default_definitions()["variables"]:
|
|
if d["id"] == portrait_definition:
|
|
char_portrait = d["value"]
|
|
break
|
|
|
|
if current_theme.get_value("settings", "single_portrait_mode", false):
|
|
p.single_portrait_mode = true
|
|
p.dim_time = current_theme.get_value("animation", "dim_time", 0.5)
|
|
p.character_data = character_data
|
|
p.init(char_portrait)
|
|
|
|
p.set_mirror(event.get("mirror", false))
|
|
$Portraits.add_child(p)
|
|
$Portraits.move_child(p, get_portrait_z_index_point(saved_portrait.get("z_index", 0)))
|
|
p.move_to_position(get_character_position(event["position"]))
|
|
|
|
p.current_state["character"] = event["character"]
|
|
p.current_state["position"] = event["position"]
|
|
|
|
|
|
if state_info["background_music"] != null:
|
|
$FX / BackgroundMusic.crossfade_to(state_info["background_music"]["file"], state_info["background_music"]["audio_bus"], state_info["background_music"]["volume"], 1)
|
|
|
|
|
|
if state_info["background"]:
|
|
current_background = state_info["background"]
|
|
|
|
var background = Background.instance()
|
|
call_deferred("resize_main")
|
|
|
|
add_child(background)
|
|
|
|
if (current_background.ends_with(".tscn")):
|
|
var bg_scene = load(current_background)
|
|
if (bg_scene):
|
|
bg_scene = bg_scene.instance()
|
|
background.add_child(bg_scene)
|
|
elif (current_background != ""):
|
|
background.texture = load(current_background)
|
|
|
|
|
|
set_current_dialog(state_info["timeline"])
|
|
|
|
|
|
for event_index in range(0, state_info["event_idx"]):
|
|
if dialog_script["events"][event_index]["event_id"] == "dialogic_010":
|
|
dialog_script["events"][event_index]["answered"] = true
|
|
|
|
_load_event_at_index(state_info["event_idx"])
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
func set_state(new_state):
|
|
var state_string = ["IDLE", "READY", "TYPING", "WAITING", "WAITING_INPUT", "ANIMATING", ]
|
|
|
|
_state = new_state
|
|
return _state
|
|
|
|
func is_state(check_state):
|
|
if _state == check_state:
|
|
return true
|
|
return false
|
|
|
|
var catOnHover;
|
|
|
|
var showMenu;
|
|
|
|
func ToggleMenu(state):
|
|
|
|
if $History / HistoryPopup.visible:
|
|
$History._on_toggle_history();
|
|
$BackButton.visible = true;
|
|
var game = get_tree().root.get_node("Root");
|
|
game.isMenuVisible = not game.isMenuVisible;
|
|
return ;
|
|
|
|
showMenu = state;
|
|
$Menu.visible = showMenu;
|
|
if showMenu:
|
|
$TextBubble / WritingTimer.stop();
|
|
$Menu / Blur.material.set_shader_param("blur_amount", 1.5);
|
|
|
|
$Poll.StopTimerInMenu();
|
|
else :
|
|
$TextBubble / WritingTimer.start();
|
|
$Menu / Blur.material.set_shader_param("blur_amount", 0);
|
|
|
|
block_dialog_for_back_button = false;
|
|
|
|
$Poll.ResumeTimerInMenu();
|
|
|
|
for i in $History.get_children():
|
|
if i is Button:
|
|
i.disabled = showMenu;
|
|
|
|
for i in $Options.get_child(0).get_children():
|
|
(i as Button).disabled = showMenu;
|
|
|
|
$Menu / MenuLayer / Settings.RemoveHover();
|
|
$Menu / MenuLayer / Settings.LoadTextSettings();
|
|
|
|
func ToggleKarmaMenu(state):
|
|
|
|
if $History / HistoryPopup.visible:
|
|
$History._on_toggle_history();
|
|
$BackButton.visible = true;
|
|
var game = get_tree().root.get_node("Root");
|
|
game.isMenuVisible = not game.isMenuVisible;
|
|
return ;
|
|
|
|
showMenu = state;
|
|
$Karma.visible = showMenu;
|
|
if showMenu:
|
|
$TextBubble / WritingTimer.stop();
|
|
$Karma / Blur.material.set_shader_param("blur_amount", 1.5);
|
|
$Karma / KarmaLayer / KarmaScene.Update()
|
|
$Poll.StopTimerInMenu();
|
|
|
|
else :
|
|
$TextBubble / WritingTimer.start();
|
|
$Karma / Blur.material.set_shader_param("blur_amount", 0);
|
|
|
|
block_dialog_for_back_button = false;
|
|
|
|
$Karma / KarmaLayer / KarmaScene.RemoveHover();
|
|
|
|
$Poll.ResumeTimerInMenu();
|
|
|
|
for i in $History.get_children():
|
|
if i is Button:
|
|
i.disabled = showMenu;
|
|
|
|
for i in $Options.get_child(0).get_children():
|
|
(i as Button).disabled = showMenu;
|
|
|
|
$Menu / MenuLayer / Settings.RemoveHover();
|
|
$Menu / MenuLayer / Settings.LoadTextSettings();
|
|
|
|
func backFromSettings():
|
|
Dialogic.reset_saves();
|
|
get_node("/root/BgmScene").SetBGM("99")
|
|
get_node("/root/BgmScene").StopSFX()
|
|
get_node("/root/BgmScene").StartMenuMusic()
|
|
|
|
if not SceneLoader.is_connected("on_scene_loaded", self, "MenuLoaded"):
|
|
SceneLoader.connect("on_scene_loaded", self, "MenuLoaded");
|
|
SceneLoader.load_scene("res://scenes/MainMenu.tscn")
|
|
|
|
func MenuLoaded(obj):
|
|
if obj.path != "res://scenes/MainMenu.tscn":
|
|
return
|
|
if obj.instance != null:
|
|
get_tree().root.add_child(obj.instance);
|
|
|
|
SceneLoader.disconnect("on_scene_loaded", self, "MenuLoaded");
|
|
get_tree().root.get_node("Root").DisconnectBackground();
|
|
|
|
for i in get_tree().root.get_children():
|
|
if i.name == "Root":
|
|
get_tree().root.remove_child(i);
|
|
break;
|
|
|
|
|
|
func returnToGame():
|
|
var game = get_tree().root.get_node("Root");
|
|
game.ToggleMenu();
|
|
|
|
func returnToGameFromKarma():
|
|
var game = get_tree().root.get_node("Root");
|
|
game.ToggleKarmaMenu();
|
|
|
|
var isSpriteChoice;
|
|
|
|
func ToggleSpriteChoice(value):
|
|
isSpriteChoice = value;
|
|
if (value):
|
|
var game = get_tree().root.get_node("Root");
|
|
|
|
|
|
|
|
|
|
isSpriteChoice = false;
|
|
|
|
var backButtonLocked;
|
|
|
|
func _on_BackButton_pressed():
|
|
if not backButtonLocked:
|
|
if $BackButton / FastForwardButton.pressed:
|
|
$BackButton / FastForwardButton.pressed = false;
|
|
|
|
backButtonLocked = true;
|
|
|
|
var previous_event = dialog_script["events"][dialog_index - 1]
|
|
if previous_event["event_id"] == "dialogic_001":
|
|
_load_previous_event()
|
|
else :
|
|
var labelString = Dialogic.get_variable("CurrentLabel")
|
|
var labelInt = int(labelString.substr(1))
|
|
if (labelInt > 1):
|
|
labelInt -= 1
|
|
Dialogic.set_variable("BackPressed", 1)
|
|
labelString = "a" + str(labelInt)
|
|
Dialogic.set_variable("CurrentLabel", labelString)
|
|
if (_state == state.TYPING):
|
|
$TextBubble.skip()
|
|
Dialogic.change_timeline(Dialogic.get_variable("TimelineSave"))
|
|
|
|
yield (get_tree().create_timer(1), "timeout");
|
|
backButtonLocked = false;
|
|
|
|
func _on_HistoryButton_pressed():
|
|
if get_node("Map").visible == true:
|
|
_on_MapButton_button_down();
|
|
|
|
if $History / HistoryPopup.visible == false:
|
|
$Poll.StopTimerInMenu();
|
|
else :
|
|
$Poll.ResumeTimerInMenu();
|
|
|
|
$History._on_toggle_history()
|
|
|
|
var isFastForwarding;
|
|
var isAutoRead;
|
|
|
|
func _on_LoadButton_button_down():
|
|
if get_node("Map").visible == true:
|
|
_on_MapButton_button_down();
|
|
|
|
if $History / HistoryPopup.visible:
|
|
$History._on_toggle_history();
|
|
|
|
get_tree().root.get_node("Root").isSaveLoadVisible = true;
|
|
|
|
SettingsSingleton.SetSkipSeen(false);
|
|
SettingsSingleton.SetAutoRead(false);
|
|
$TextBubble / WritingTimer.stop();
|
|
if $BackButton / FastForwardButton.pressed:
|
|
isFastForwarding = true;
|
|
if $BackButton / AutoReadButton.pressed:
|
|
isAutoRead = true;
|
|
|
|
$BackButton.visible = false
|
|
|
|
$LoadSaveMenu.visible = true
|
|
|
|
$Options.get_child(0).visible = false;
|
|
for i in $Options.get_child(0).get_children():
|
|
(i as Button).disabled = true;
|
|
$LoadSaveMenu / LoadSaveLayer / LoadSaveScene.LoadPressed()
|
|
|
|
$Poll.StopTimerInMenu();
|
|
|
|
yield (get_tree().create_timer(0.1), "timeout")
|
|
$TextBubble / WritingTimer.stop();
|
|
|
|
func _on_SaveButton_button_down():
|
|
if get_node("Map").visible == true:
|
|
_on_MapButton_button_down();
|
|
|
|
if $History / HistoryPopup.visible:
|
|
$History._on_toggle_history();
|
|
|
|
get_tree().root.get_node("Root").isSaveLoadVisible = true;
|
|
|
|
SettingsSingleton.SetSkipSeen(false);
|
|
SettingsSingleton.SetAutoRead(false);
|
|
|
|
$TextBubble / WritingTimer.stop();
|
|
|
|
if $BackButton / FastForwardButton.pressed:
|
|
isFastForwarding = true;
|
|
if $BackButton / AutoReadButton.pressed:
|
|
isAutoRead = true;
|
|
|
|
$BackButton.visible = false
|
|
|
|
$LoadSaveMenu.visible = true
|
|
|
|
$Options.get_child(0).visible = false;
|
|
for i in $Options.get_child(0).get_children():
|
|
(i as Button).disabled = true;
|
|
$LoadSaveMenu / LoadSaveLayer / LoadSaveScene.SavePressed()
|
|
|
|
$Poll.StopTimerInMenu();
|
|
|
|
yield (get_tree().create_timer(0.1), "timeout")
|
|
$TextBubble / WritingTimer.stop();
|
|
|
|
func _on_MapButton_button_down():
|
|
if $History / HistoryPopup.visible:
|
|
$History._on_toggle_history();
|
|
|
|
if not $Map.visible:
|
|
Input.set_custom_mouse_cursor(load("res://resources/cursors/arrow2.webp"));
|
|
|
|
$Map.ProcessMapFromMenuButton();
|
|
|
|
|
|
$TextBubble / WritingTimer.stop();
|
|
|
|
for i in $Options.get_child(0).get_children():
|
|
(i as Button).disabled = true;
|
|
|
|
yield (get_tree().create_timer(0.1), "timeout")
|
|
$TextBubble / WritingTimer.stop();
|
|
|
|
$Map.visible = true;
|
|
get_tree().root.get_node("Root").isSaveLoadVisible = true;
|
|
showMenu = true;
|
|
|
|
$Poll.StopTimerInMenu();
|
|
else :
|
|
|
|
$TextBubble / WritingTimer.start();
|
|
|
|
for i in $Options.get_child(0).get_children():
|
|
(i as Button).disabled = false;
|
|
|
|
$Map.visible = false;
|
|
get_tree().root.get_node("Root").isSaveLoadVisible = false;
|
|
showMenu = false;
|
|
|
|
$Poll.ResumeTimerInMenu();
|
|
|
|
func BackFromSaveLoad():
|
|
get_tree().root.get_node("Root").isSaveLoadVisible = false;
|
|
|
|
$BackButton.visible = true
|
|
$TextBubble / WritingTimer.start();
|
|
|
|
if isFastForwarding:
|
|
SettingsSingleton.SetSkipSeen(true);
|
|
if isAutoRead:
|
|
SettingsSingleton.SetAutoRead(true);
|
|
|
|
block_dialog_for_back_button = false
|
|
$LoadSaveMenu.visible = false
|
|
|
|
$Options.get_child(0).visible = true;
|
|
for i in $Options.get_child(0).get_children():
|
|
(i as Button).disabled = false;
|
|
|
|
$Poll.ResumeTimerInMenu();
|
|
|
|
func _on_OptionsButton_pressed():
|
|
if get_node("Map").visible == true:
|
|
_on_MapButton_button_down();
|
|
|
|
if $History / HistoryPopup.visible:
|
|
$History._on_toggle_history();
|
|
|
|
get_parent().get_parent().get_parent().ToggleMenu()
|
|
|
|
func _on_AutoReadButton_pressed():
|
|
var value = $BackButton / AutoReadButton.pressed;
|
|
if value and $BackButton / FastForwardButton.pressed:
|
|
$BackButton / FastForwardButton.pressed = false;
|
|
SettingsSingleton.SetSkipSeen(false);
|
|
|
|
SettingsSingleton.SetAutoRead(value);
|
|
SettingsSingleton.SaveSettings()
|
|
|
|
func _on_FastForwardButton_pressed():
|
|
var value = $BackButton / FastForwardButton.pressed;
|
|
if value and $BackButton / AutoReadButton.pressed:
|
|
SettingsSingleton.SetAutoRead(false);
|
|
$BackButton / AutoReadButton.pressed = false;
|
|
|
|
SettingsSingleton.SetSkipSeen(value);
|
|
SettingsSingleton.SaveSettings()
|
|
|
|
func _on_KarmaButton_pressed():
|
|
if get_node("Map").visible == true:
|
|
_on_MapButton_button_down();
|
|
|
|
if $History / HistoryPopup.visible:
|
|
$History._on_toggle_history();
|
|
|
|
get_parent().get_parent().get_parent().ToggleKarmaMenu()
|
|
|
|
|
|
var disableMapScenes = ["Scene8", "PoliceStation", "Train_video", "Scene4", ]
|
|
|
|
func CheckMap():
|
|
var background = Dialogic.get_variable("CurrentBackground");
|
|
var lol = background in disableMapScenes;
|
|
$BackButton / MapButton.disabled = lol;
|
|
|
|
|
|
func _on_FullView_mouse_exited():
|
|
var controlsToShow = [$Portraits, $Poll];
|
|
|
|
if not (alternativeChoicesOn or investigationOn):
|
|
controlsToShow.push_back($TextBubble)
|
|
|
|
|
|
for i in $BackButton.get_children():
|
|
controlsToShow.push_back(i);
|
|
|
|
for i in $Options.get_children():
|
|
controlsToShow.push_back(i);
|
|
|
|
$BackButton / FullView.HoverOff(controlsToShow);
|
|
|
|
$TextBubble / WritingTimer.start()
|
|
$Poll.ResumeTimerInMenu();
|
|
$Poll.AppearTimer();
|
|
|
|
func _on_FullView_button_up():
|
|
var controlsToHide = [
|
|
|
|
$Portraits,
|
|
$TextBubble,
|
|
$Poll,
|
|
]
|
|
|
|
for i in $BackButton.get_children():
|
|
controlsToHide.push_back(i)
|
|
for i in $Options.get_children():
|
|
controlsToHide.push_back(i)
|
|
|
|
$BackButton / FullView.HoverOn(controlsToHide);
|
|
|
|
$TextBubble / WritingTimer.stop()
|
|
$Poll.StopTimerInMenu();
|
|
|
|
func SetTooltips():
|
|
$BackButton / SaveButton.hint_tooltip = tr("ui_save")
|
|
$BackButton / LoadButton.hint_tooltip = tr("ui_load");
|
|
$BackButton / AutoReadButton.hint_tooltip = tr("ui_autoread")
|
|
$BackButton / FastForwardButton.hint_tooltip = tr("ui_skipseen")
|
|
$BackButton / HistoryButton.hint_tooltip = tr("ui_history")
|
|
$BackButton / MapButton.hint_tooltip = tr("ui_map")
|
|
$BackButton / OptionsButton.hint_tooltip = tr("ui_menu")
|
|
$BackButton / KarmaButton.hint_tooltip = tr("ui_relationship")
|
|
|
|
func forTwitchResize():
|
|
var widest = - 1;
|
|
var startY = - 1;
|
|
$Poll / SizeTimer.disconnect("timeout", self, "forTwitchResize")
|
|
|
|
for i in button_container.get_child_count():
|
|
var button:Button = button_container.get_child(i);
|
|
button.disabled = false;
|
|
if i == 0:
|
|
startY = button.rect_global_position.y
|
|
|
|
var right = button.rect_global_position.x + button.rect_size.x
|
|
|
|
if right > widest:
|
|
widest = right
|
|
|
|
$Poll / VBoxContainer.rect_global_position = Vector2(50 + widest, startY);
|
|
$Poll.StartTimer();
|
|
|
|
func TwitchPollTimeout():
|
|
var number = $Poll.Result();
|
|
var button:Button = button_container.get_child(number - 1)
|
|
|
|
button.modulate = Color(0.5, 0.5, 0.5, 1)
|
|
$Poll / SizeTimer.connect("timeout", self, "TwichButtonPress", [button])
|
|
$Poll / SizeTimer.start(0.25);
|
|
|
|
func TwichButtonPress(button):
|
|
$Poll / SizeTimer.disconnect("timeout", self, "TwichButtonPress")
|
|
button.emit_signal("pressed");
|
|
|
|
# Steam.set_achievement("Twitch");
|
|
|
|
const CharacterKarmas:Array = [
|
|
"1655845108-146",
|
|
"1655479805-366",
|
|
"1655481153-146",
|
|
"1655846105-918",
|
|
"1655846767-483",
|
|
"1655848122-970",
|
|
"1655481311-918",
|
|
"1655479174-787",
|
|
"1655311631-648",
|
|
"1655848676-713",
|
|
"1655478573-648",
|
|
];
|
|
const KarmaStructure:Array = [
|
|
{"charId":"1655845108-146", "charName":"ui_name_pink", "color":"#ffaedd", "sex":false, "isDead":"Is_Pink_Dead", "seen":"Pink"},
|
|
{"charId":"1655479805-366", "charName":"ui_name_gray", "color":"#ffaebad7", "sex":true, "isDead":"Is_Gray_Dead", "seen":"Gray"},
|
|
{"charId":"1655481153-146", "charName":"ui_name_red", "color":"#ff2f2f", "sex":true, "isDead":"Is_Red_Dead", "seen":"Red"},
|
|
{"charId":"1655846105-918", "charName":"ui_name_purple", "color":"#8353c1", "sex":false, "isDead":"Is_Purple_Dead", "seen":"Purple"},
|
|
{"charId":"1655846767-483", "charName":"ui_name_green", "color":"#66ff55", "sex":false, "isDead":"Is_Green_Dead", "seen":"Green"},
|
|
{"charId":"1655848122-970", "charName":"ui_name_black", "color":"#ff0f0a0a", "sex":false, "isDead":"Is_Black_Dead", "seen":"Black"},
|
|
{"charId":"1655481311-918", "charName":"ui_name_blue_m", "color":"#ff00ffff", "sex":true, "isDead":"Is_Blue_M_Dead", "seen":"Blue_M"},
|
|
{"charId":"1655479174-787", "charName":"ui_name_white", "color":"#ffffffff", "sex":true, "isDead":"Is_White_Dead", "seen":"White"},
|
|
{"charId":"1655311631-648", "charName":"ui_name_orange", "color":"#ffffad00", "sex":false, "isDead":"Is_Orange_Dead", "seen":"Orange"},
|
|
{"charId":"1655848676-713", "charName":"ui_name_blue_f", "color":"#4064ff", "sex":false, "isDead":"Is_Blue_F_Dead", "seen":"Blue_F"},
|
|
{"charId":"1655478573-648", "charName":"ui_name_yellow", "color":"#fffff500", "sex":true, "isDead":"Is_Yellow_Dead", "seen":"Yellow"},
|
|
];
|
|
|
|
func KarmaChanged(event):
|
|
|
|
if Dialogic.get_variable("EasyMode") == "0":
|
|
return ;
|
|
|
|
|
|
if Dialogic.get_variable("DisplayKarma") == "0":
|
|
return ;
|
|
|
|
|
|
if not event["definition"] in CharacterKarmas:
|
|
return ;
|
|
|
|
|
|
var structure = null;
|
|
for i in KarmaStructure:
|
|
if i["charId"] == event["definition"]:
|
|
structure = i;
|
|
break;
|
|
|
|
|
|
if Dialogic.get_variable(structure["isDead"]) == "1":
|
|
return ;
|
|
|
|
|
|
if ProgressAchievementsSingleton.IsInSeenCharacters(structure["seen"]) == false:
|
|
return ;
|
|
|
|
$BackButton / KarmaButton.StartBlinking();
|
|
$ChangeKarmaContainer.AddText(event, structure);
|
|
|
|
func DemonstrateKarma():
|
|
$BackButton / KarmaButton.StartBlinking();
|