extends Reference const Dialog = preload("res://dialog_vm.gd") # classes from vm const DialogSegment = Dialog.DialogSegment const DialogWithSubjectSegment = Dialog.DialogWithSubjectSegment const DialogWithSubjectExpressionSegment = Dialog.DialogWithSubjectExpressionSegment const QuestionSegment = Dialog.QuestionSegment const ChoiceSegment = Dialog.ChoiceSegment const ChoiceWithJump = Dialog.ChoiceWithJump const Choice = Dialog.Choice const WaitSegment = Dialog.YieldCallSegment # current dialog vm var current_dialog var audio_player # dialog controller related state, internal # speed at which dialog prints characters var chars_per_second = 16 # initialized from which character is speaking var reading_speed_mul = 1 var special_speed_mul = 1 # intermediate state for dialog var waiting_for_answer = false var print_done = false setget _on_print_set var print_target = 0 var print_delta = 0 # ui button controlled state var is_auto_advancing = false var auto_advance_delay = 1 var auto_advance_timer = 0 var is_new_word = false var is_fastforwarding = false var ff_speed_mul = 1 # character printing sound related state var sound_playing = false var sound_play_time = 2.08 # TODO: maybe adjust this too depending on voice sample/chars per second var sound_played_time = 0 # signals signal on_printing_done() signal on_printing_changed(status) signal on_update_dialog(segment) signal on_dialog_completed(d) func _init(d, a): current_dialog = d audio_player = a func reset(): self.print_done = true print_target = 0 print_delta = 0 # sfx related func sound_play(): sound_playing = true audio_player.play() func sound_stop(): audio_player.stop() sound_playing = false func sound_done_playing(delta): sound_played_time += delta * reading_speed_mul * special_speed_mul if sound_played_time >= sound_play_time / chars_per_second: sound_played_time = 0 sound_playing = false return not sound_playing # temporary hopefully func _advance_dialog(): var current_segment = current_dialog.advance() if not current_segment == null: emit_signal("on_update_dialog", current_segment) else: emit_signal("on_dialog_completed", self) func _on_body_click(is_visible, event): if is_visible and not waiting_for_answer: if event.is_action_pressed("dialog_click"): if print_done == false: # if still printing, jump forwards now print_delta = print_target - 1 self.print_done = true else: _advance_dialog() # interior callbacks func _on_print_set(v): print_done = v if print_done: emit_signal("on_printing_done") emit_signal("on_printing_changed", v) func set_reading_speed(spd): reading_speed_mul = spd func set_advance_state(s): is_auto_advancing = s func set_fastforward_state(s): is_fastforwarding = s if is_fastforwarding: is_auto_advancing = true ff_speed_mul = 10 auto_advance_delay = 0.1 else: ff_speed_mul = 1 auto_advance_delay = 1 func update_logic_dialog(segment): if segment is QuestionSegment: var new_content = segment.get_content() print_target = new_content.length() self.print_done = false print_delta = 0 elif segment is ChoiceSegment: waiting_for_answer = true elif segment is Choice: var new_content = segment.get_response() if typeof(new_content) == TYPE_OBJECT and (new_content is DialogWithSubjectSegment or new_content is DialogWithSubjectExpressionSegment): _update_logic_dialog(new_content) else: print_target = new_content.length() self.print_done = false print_delta = 0 elif segment is DialogSegment or segment is DialogWithSubjectSegment or segment is DialogWithSubjectExpressionSegment: var new_content = segment.get_content() print_target = new_content.length() self.print_done = false print_delta = 0 elif segment is WaitSegment: var new_content = segment.get_content() print_target = new_content.length() self.print_done = false print_delta = 0 else: print("encountered unknown segment: " + segment.get_content()) func tick(delta, body_label): if not current_dialog.is_eof(): var cur_segment = current_dialog.segments[current_dialog.segment_index] if cur_segment is WaitSegment and cur_segment.finished: _advance_dialog() if print_target != 0: if print_delta >= print_target: self.print_done = true auto_advance_timer = auto_advance_delay print_target = 0 print_delta = 0 else: if sound_done_playing(delta) and not is_fastforwarding: sound_play() body_label.visible_characters = print_delta print_delta += delta * (chars_per_second * reading_speed_mul) * ff_speed_mul elif print_target == 0: auto_advance_timer -= delta if auto_advance_timer <= 0 and is_auto_advancing and not waiting_for_answer: call_deferred("_advance_dialog")