## A dolly tweens all contents to and from two destination points, and to its origin. class_name Dolly extends Node3D @export var index : int = -1 @export var signage_group : String @export_group("Motion") @export_subgroup("Arrival") @export var pre_arrival_time : float = 17.0 # hold train for this long (to sync with audio!) @export var arrival_time : float = 15.0 # train takes this long to enter (shorter = faster) @export var trans_arrival : Tween.TransitionType = Tween.TRANS_CIRC @export var ease_arrival : Tween.EaseType = Tween.EASE_OUT @export_subgroup("In Station") @export var station_wait_time : float = 20.0 @export_subgroup("Departure") @export var door_close_time : float = 1.0 @export var leave_time : float = 15.0 # train takes this long to leave the platform @export var trans_departure : Tween.TransitionType = Tween.TRANS_QUAD @export var ease_departure : Tween.EaseType = Tween.EASE_IN @onready var origination : Node3D = $Origination @onready var destination : Node3D = $Destination @onready var subway : SubwayTrain = $Subway @onready var subway_audio_main : AudioStreamPlayer3D = %SubwayTrainAudio @onready var subway_audio_2 : AudioStreamPlayer3D = %SubwayTrainAudioIntense var player_on_board : bool: get: return %EntryDetect.overlaps_body(State.player) var tween : Tween = null ## Player is about to arrive signal train_approaching(track : Dolly) ## Player has fully arrived at station signal train_arrived(track : Dolly) ## Player is departing in train signal train_departing(track : Dolly) ## Player has fully left the station with train signal train_left(track : Dolly) func _ready() -> void: reset() ## One arrival and departure func cycle() -> void: await arrive() await leave() func reset() -> void: if tween: tween.kill() subway.global_position = origination.global_position func _seat_player() -> void: prints("Player departs inside Train", self.name) State.player.reparent(subway) func _unseat_player() -> void: prints("Player arrives on Train", self.name) State.player.reparent(get_parent()) func arrive(endstation : bool = false) -> void: subway_audio_main.play() subway_audio_2.play() await get_tree().create_timer(pre_arrival_time).timeout if player_on_board: train_approaching.emit(self) if tween: tween.kill() tween = create_tween().set_trans(trans_arrival).set_ease(ease_arrival) tween.parallel().tween_property(subway, "global_position", self.global_position, arrival_time) await tween.finished subway.door_open = true if player_on_board: _unseat_player() train_arrived.emit(self) if endstation: subway_audio_main.stop() subway_audio_2.stop() func leave() -> void: await get_tree().create_timer(station_wait_time).timeout subway.door_open = false await get_tree().create_timer(door_close_time).timeout if player_on_board: _seat_player() train_departing.emit(self) if tween: tween.kill() tween = create_tween().set_trans(trans_departure).set_ease(ease_departure) tween.parallel().tween_property(subway, "global_position", destination.global_position, leave_time) # Player is on board and will be leaving await tween.finished # Player was on board and has left the station if player_on_board: train_left.emit(self) reset() # Warp back / rewind train position