class_name VoicelineComponent extends Node @export_node_path("AudioStreamPlayer", "AudioStreamPlayer2D", "AudioListener3D") var audio_players: Array[NodePath] = []: set = set_audio_players @export var voiceline_chains: Dictionary[StringName, VoicelineChain] = {} @export var cache_voicelines: bool = false ## TODO: preload all voicelines when they need the be loaded. var voiceline_players: Array[Node] = [] var next_voicelines: Array[VoicelineChain] = [] var current_voiceline_chain_index: int = 0 var _reference_player: Node func set_audio_players(players: Array[NodePath]) -> void: audio_players = players _update_player_cache() func push_voiceline(voiceline_chain: VoicelineChain) -> void: next_voicelines.append(voiceline_chain) func push_next_voiceline() -> void: var voiceline: VoicelineChain = next_voicelines.front() if is_instance_valid(voiceline) and current_voiceline_chain_index < voiceline.voicelines.size(): current_voiceline_chain_index += 1 _play_voiceline(voiceline.voicelines[current_voiceline_chain_index]) return next_voicelines.remove_at(0) voiceline = next_voicelines.front() current_voiceline_chain_index = 0 if is_instance_valid(voiceline): _play_voiceline(voiceline.voicelines.front()) func play_voiceline(vo_name: StringName) -> void: if voiceline_chains.has(vo_name): push_voiceline(voiceline_chains[vo_name]) else: push_warning("[%s] No voiceline with the name '%s' found." % [self, vo_name]) func is_audio_player(player: Node) -> bool: return ( is_instance_valid(player) and ( player is AudioStreamPlayer or player is AudioStreamPlayer2D or player is AudioStreamPlayer3D ) ) func _play_voiceline(voiceline_data: VoicelineData) -> void: var voice: AudioStream = load(voiceline_data.voiceline_path) for player: Node in voiceline_players: player.play(voice) func _on_voiceline_finished() -> void: push_next_voiceline() func _update_player_cache() -> void: voiceline_players.clear() for audio_player: NodePath in audio_players: var player: Node = get_node_or_null(audio_player) if is_audio_player(player): voiceline_players.append(player) _reference_player = player _reference_player.finished.connect(_on_voiceline_finished)