2025-12-19 14:11:31 +00:00
class_name StoryPlayable
2026-01-17 11:11:21 +00:00
extends Playable
2025-01-16 16:32:58 +00:00
2025-02-06 17:55:05 +00:00
signal text_finished
2025-01-16 16:32:58 +00:00
signal finished
signal intro
2025-05-09 15:28:23 +00:00
signal emit_thunder
2025-01-16 16:32:58 +00:00
2026-01-11 20:33:37 +00:00
@ export var scene_id : Scenes . id
2025-01-16 16:32:58 +00:00
#TODO properly implement animation taking stage, as it should do, disabling processing when it does not have stage.
2025-02-06 17:55:05 +00:00
var max_lines : float = 0
2026-01-12 19:54:28 +00:00
@ export var story_array : PackedStringArray :
2025-05-06 22:19:09 +00:00
set ( str_array ) :
story_array = str_array
2025-10-29 21:49:29 +00:00
_rebuild ( )
2025-02-06 17:55:05 +00:00
2026-01-12 20:00:24 +00:00
@ export var paragraph_lengths : PackedInt32Array
2025-05-06 22:19:09 +00:00
2026-01-12 20:00:24 +00:00
var progress : float = 0 :
2025-01-16 16:32:58 +00:00
set ( value ) :
progress = value
2025-05-07 17:30:55 +00:00
if is_node_ready ( ) and not all_text_revealed :
2025-12-13 12:14:16 +00:00
var start_index : = 0
2025-01-16 16:32:58 +00:00
if progress > = substring_sizes . size ( ) or progress < 0 :
label . visible_ratio = 1
2025-02-06 17:55:05 +00:00
elif progress > 0 :
2025-01-16 16:32:58 +00:00
for i in range ( min ( progress , substring_sizes . size ( ) - 1 ) as int ) if progress > 0 else range ( substring_sizes . size ( ) - 1 ) :
start_index += substring_sizes [ i ]
2025-12-08 09:43:02 +00:00
2025-12-13 12:14:16 +00:00
label . visible_characters = start_index + int ( substring_sizes [ min ( progress as int , substring_sizes . size ( ) - 1 ) ] * fmod ( progress , 1 ) )
2025-02-06 17:55:05 +00:00
else :
label . visible_ratio = 0
2025-05-07 17:30:55 +00:00
var all_text_revealed : bool = false :
set ( revealed ) :
var reset_progress : = false
if revealed and not all_text_revealed :
var tween : Tween = get_tree ( ) . create_tween ( )
tween . set_ease ( Tween . EASE_OUT )
2025-05-26 19:40:13 +00:00
tween . tween_property ( label , " visible_ratio " , 1 , 0.5 )
2025-05-07 17:30:55 +00:00
elif not revealed and all_text_revealed :
reset_progress = true
all_text_revealed = revealed
if all_text_revealed : progress = - 1
if reset_progress : progress = 0
2025-02-06 17:55:05 +00:00
@ export var test_scroll : bool :
set ( scroll ) :
try_scroll ( )
2025-01-16 16:32:58 +00:00
@ onready var label : RichTextLabel = % StoryLabel
@ onready var scroll_container : ScrollContainer = % StoryScroll
@ onready var animation_player : AnimationPlayer = % AnimationPlayer
2025-02-06 17:55:05 +00:00
@ onready var skip_control : SkipControl = % SkipControl
2025-01-16 16:32:58 +00:00
@ export var animation_complete : bool = false :
set ( value ) :
animation_complete = value
if value :
2025-02-06 17:55:05 +00:00
scroll_container . vertical_scroll_mode = ScrollContainer . ScrollMode . SCROLL_MODE_AUTO
2025-01-16 16:32:58 +00:00
progress = - 1
2025-02-06 17:55:05 +00:00
else :
scroll_container . scroll_vertical = ScrollContainer . ScrollMode . SCROLL_MODE_DISABLED
2025-01-16 16:32:58 +00:00
animation_complete = value
var substring_sizes : Array [ int ]
func _ready ( ) - > void :
2025-12-19 14:11:31 +00:00
print_debug ( " StoryPlayable.gd: %s ._ready() " % self . name )
2025-12-16 22:21:54 +00:00
hide ( )
2026-01-12 19:54:28 +00:00
animation_player . play ( " RESET " )
2025-05-21 09:13:44 +00:00
State . settings_changed . connect ( func ( ) : story_array = story_array )
2025-02-06 17:55:05 +00:00
skip_control = % SkipControl
2025-03-23 13:52:45 +00:00
if skip_control is SkipControl and not Engine . is_editor_hint ( ) :
2025-02-06 17:55:05 +00:00
skip_control . skip . connect ( skip_text )
2025-12-08 09:43:02 +00:00
2026-01-12 20:43:48 +00:00
# Clunky rebuild...
2025-01-16 16:32:58 +00:00
story_array = story_array
progress = progress
2025-12-08 09:43:02 +00:00
2025-10-29 21:49:29 +00:00
func _rebuild ( ) :
2025-12-19 14:11:31 +00:00
print_debug ( " StoryPlayable.gd: %s ._rebuild() " % self . name )
2025-10-29 21:49:29 +00:00
if is_node_ready ( ) :
substring_sizes = [ ]
var p : int = 0
label . text = " [p] "
for i in range ( story_array . size ( ) ) :
label . text += TranslationServer . translate ( story_array [ i ] ) . strip_edges ( ) + " "
substring_sizes . append ( TranslationServer . translate ( story_array [ i ] ) . strip_edges ( ) . length ( ) + 1 )
if not paragraph_lengths [ - 1 ] == story_array . size ( ) - 1 :
paragraph_lengths . append ( story_array . size ( ) - 1 )
2026-01-12 20:00:24 +00:00
push_warning ( " Paragraph lenghts of scene %s are misconfigured! " % name )
2025-10-29 21:49:29 +00:00
if paragraph_lengths [ p ] == i :
p += 1
label . text += " [/p][p][font_size=8] [/font_size][/p][p] "
substring_sizes [ - 1 ] = substring_sizes [ - 1 ] + 1
label . text += " [/p] "
max_lines = float ( label . get_line_count ( ) )
2025-12-08 09:43:02 +00:00
2025-01-16 16:32:58 +00:00
func try_scroll ( ) :
2025-12-13 12:14:16 +00:00
var forward_target : float
2025-12-08 09:43:02 +00:00
2025-12-13 12:14:16 +00:00
#print( "max lines: " + str(max_lines))
#print( "current lines: " + str(label.get_character_line(label.visible_characters)))
2025-12-08 09:43:02 +00:00
2025-02-06 17:55:05 +00:00
var visible_ratio : float = float ( label . get_character_line ( label . visible_characters ) ) / max_lines
2025-12-08 09:43:02 +00:00
2025-12-13 12:14:16 +00:00
#print("Tried scrolling with ratio of %f. Comparing %f against %f" % [visible_ratio, label.size.y * visible_ratio - scroll_container.scroll_vertical, scroll_container.size.y * 0.9])
2025-12-08 09:43:02 +00:00
2025-02-06 17:55:05 +00:00
if label . size . y * visible_ratio + scroll_container . scroll_vertical > scroll_container . size . y * 0.9 :
if scroll_container . scroll_vertical + scroll_container . size . y * 0.9 < label . size . y :
2025-05-09 15:28:23 +00:00
forward_target = scroll_container . scroll_vertical + scroll_container . size . y * 0.8
2025-01-16 16:32:58 +00:00
else :
2025-12-08 09:43:02 +00:00
forward_target = label . size . y - scroll_container . size . y
2025-01-16 16:32:58 +00:00
if scroll_target != null :
2025-12-13 12:14:16 +00:00
#var tween: Tween = get_tree().create_tween()
2025-01-16 16:32:58 +00:00
##tween.set_trans()
2025-05-09 15:28:23 +00:00
scroll_target = forward_target
2025-01-16 16:32:58 +00:00
2025-12-19 14:11:31 +00:00
func play ( ) :
print_debug ( " StoryPlayable.gd: %s .play() " % self . name )
2026-01-12 20:43:48 +00:00
# There's an ugly glitch here.
2026-01-15 12:39:56 +00:00
hide ( )
animation_player . play ( " RESET " )
2026-01-12 19:54:28 +00:00
await animation_player . animation_finished
2026-01-15 12:39:56 +00:00
2026-01-05 15:04:59 +00:00
# Show ourselves before playing
2026-01-12 20:43:48 +00:00
get_parent ( ) . show ( ) # Ensure visible Canvaslayer!
2026-01-15 12:39:56 +00:00
2025-06-08 16:31:59 +00:00
scroll_target = 0
2025-12-08 09:43:02 +00:00
2025-05-21 09:13:44 +00:00
# FIXME: find out why this needs to be set to prevent scenes from being fully revealed
all_text_revealed = false
2025-01-16 16:32:58 +00:00
animation_complete = false
2025-12-08 09:43:02 +00:00
2025-06-23 16:37:01 +00:00
match State . speech_language :
2025-07-21 12:33:04 +00:00
2 :
2025-06-23 16:37:01 +00:00
animation_player . queue ( " de " )
_ :
2025-01-16 16:32:58 +00:00
animation_player . queue ( " en " )
2025-12-08 09:43:02 +00:00
2026-01-12 20:43:48 +00:00
# Wait and get ready.
await get_tree ( ) . process_frame
show ( )
Input . mouse_mode = Input . MOUSE_MODE_VISIBLE
2026-01-15 12:39:56 +00:00
2026-01-17 11:11:21 +00:00
# FIXME: Don't know how to do this.
2026-01-12 20:43:48 +00:00
#%StoryScroll.grab_focus()
2026-01-15 12:39:56 +00:00
2025-10-29 21:49:29 +00:00
if name == " draven " :
await get_tree ( ) . process_frame
$ AnimationPlayer / Music . play ( )
2025-12-08 09:43:02 +00:00
2025-02-06 17:55:05 +00:00
await text_finished
2025-12-08 09:43:02 +00:00
2025-01-16 16:32:58 +00:00
if name == " draven " :
trigger_intro ( )
2025-12-08 09:43:02 +00:00
2025-01-16 16:32:58 +00:00
animation_complete = true
2025-05-07 17:30:55 +00:00
all_text_revealed = true
2025-12-08 09:43:02 +00:00
2025-02-06 17:55:05 +00:00
skip_control . start_proceed_countdown ( )
2025-12-08 09:43:02 +00:00
2025-02-06 17:55:05 +00:00
await skip_control . proceed
2025-12-08 09:43:02 +00:00
2025-02-06 17:55:05 +00:00
animation_player . play ( " vanish " )
2025-12-08 09:43:02 +00:00
2025-02-06 17:55:05 +00:00
await animation_player . animation_finished
2025-12-08 09:43:02 +00:00
2025-01-16 16:32:58 +00:00
finished . emit ( )
2025-05-07 17:30:55 +00:00
func _unhandled_input ( event : InputEvent ) - > void :
2025-12-13 12:14:16 +00:00
var just_revealed_text : = false
2025-05-07 17:30:55 +00:00
if event is InputEventMouseButton :
if event . button_index == MOUSE_BUTTON_WHEEL_DOWN :
scroll_target += 40
2025-12-19 14:11:31 +00:00
if not all_text_revealed :
2025-12-13 12:14:16 +00:00
just_revealed_text = true
2025-05-07 17:30:55 +00:00
if event . button_index == MOUSE_BUTTON_WHEEL_UP :
scroll_target -= 40
2025-12-19 14:11:31 +00:00
if not all_text_revealed :
2025-12-13 12:14:16 +00:00
just_revealed_text = true
2025-12-19 14:11:31 +00:00
if just_revealed_text and animation_complete :
2025-12-13 12:14:16 +00:00
all_text_revealed = true
2025-05-07 17:30:55 +00:00
var scroll_target : float = 0 :
set ( value ) :
2025-05-21 09:13:44 +00:00
scroll_target = clampf ( value , 0 , label . size . y - scroll_container . size . y + 10 )
2025-12-19 14:11:31 +00:00
2025-01-16 16:32:58 +00:00
var intro_triggered : = false
func trigger_intro ( ) :
2026-01-15 20:40:00 +00:00
# Don't trigger the intro animation if the scene was skipped
if not intro_triggered and not was_skipped :
2025-01-16 16:32:58 +00:00
intro . emit ( )
2025-02-06 17:55:05 +00:00
intro_triggered = true
2025-01-16 16:32:58 +00:00
2025-12-19 14:11:31 +00:00
var was_skipped : bool = false
2025-01-16 16:32:58 +00:00
func skip_text ( ) :
2025-05-26 19:40:13 +00:00
if not all_text_revealed :
all_text_revealed = true
elif not animation_complete :
2025-02-06 17:55:05 +00:00
animation_player . stop ( true )
2025-03-28 17:20:21 +00:00
was_skipped = true
2025-02-06 17:55:05 +00:00
text_finished . emit ( )
2025-05-09 15:28:23 +00:00
if name == " draven " :
$ AnimationPlayer / Music . stop ( )
elif name == " JuiJutsu " :
_emit_thunder ( )
2025-02-06 17:55:05 +00:00
func _on_text_finished ( ) :
2025-12-19 14:11:31 +00:00
print_debug ( " StoryPlayable.gd: %s ._on_text_finished() " % self . name )
2025-02-06 17:55:05 +00:00
if not animation_complete :
text_finished . emit ( )
2025-05-09 15:28:23 +00:00
func _emit_thunder ( ) :
emit_thunder . emit ( )