173 lines
4.6 KiB
GDScript3
173 lines
4.6 KiB
GDScript3
|
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")
|