extends Node class_name AudioManagerInstance const MIN_VOLUME = -60. const MAX_VOLUME = 24. const DEFAULT_FADE_TIME : float = 5.0 const REGION_FIRST_PHASE = [ "RegionForestPhase1", "RegionForestPhase2", "RegionMinePhase1", "RegionMinePhase2" ] const REGION_LOOP_PHASE = [ "RegionForestLoop", "RegionForestLoop", "RegionMineLoop", "RegionMineLoop" ] @onready var settings : SettingsData = GameInfo.settings_data var music_actions : Array[AudioAction] var ambiance_actions : Array[AudioAction] var playing_musics : Array[String] = [] var playing_ambiances : Array[String] = [] var default_volumes := {} # ----------------- Partie Fonctionnelle ---------------- # Fonction s'exécutant à chaque changement de scène func _on_change_scene(scene : Scene): stop_all_ambiances() match scene.scene_id: "TITLE": play_music_alone("Title", false, 5.0) "INTRO": stop_all_musics() "REGION": play_ambiance("Exterior", false) var region_level = GameInfo.game_data.current_region_data.region_level var first_phase = REGION_FIRST_PHASE[region_level % len(REGION_FIRST_PHASE)] var loop_phase = REGION_LOOP_PHASE[region_level % len(REGION_LOOP_PHASE)] play_music_alone(first_phase) queue_music(loop_phase, first_phase) "COCKPIT": play_ambiance_alone("Ship", true, 5.0) "ASTRA": stop_all_musics() play_ambiance_alone("Astra", false) "GARAGE": stop_all_musics() play_ambiance_alone("Astra", false) "BOREA": stop_all_musics() play_ambiance_alone("Borea", false) # Fonction s'exécutant à chaque début de timeline func _on_timeline_started(): var timeline_name = Dialogic.current_timeline.resource_path.split("/")[-1].trim_suffix(".dtl") change_ambiances_volume(-10) match timeline_name: "demeter_astra_failed": play_ambiance("Demeter") "demeter_ship_presentation": play_ambiance("Demeter") "demeter_intro": play_ambiance("Demeter") "demeter_post_tutorial": play_ambiance("Demeter") "failure": play_ambiance("Demeter") # Fonction s'exécutant à chaque fin de timeline func _on_timeline_ended(): if SceneManager.actual_scene: change_ambiances_volume() stop_ambiance("Demeter") # Joue la musique définie par player_name, arrête toute les autres musiques immédiatement # - player_name : Nom de la Node dans la scène Godot sous la node Musics à jouer # - from_random_time : joue depuis un temps aléatoire (true) ou non (false) # - fade_time : durée du fondu d'arrivée func play_music_alone( player_name : String = "", from_random_time := false, fade_time := DEFAULT_FADE_TIME ): stop_all_musics() play_music(player_name,from_random_time,fade_time) # Joue la musique définie par player_name # - player_name : Nom de la Node dans la scène Godot sous la node Musics à jouer # - from_random_time : joue depuis un temps aléatoire (true) ou non (false) # - fade_time : durée du fondu d'arrivée func play_music( player_name : String = "", from_random_time := false, fade_time := DEFAULT_FADE_TIME ): music_actions.append(AudioLaunch.new( player_name, from_random_time, fade_time )) # Joue la musique définie par player_name juste après la fin de la musique after_player_name, stoppe cette dernière à ce moment # - player_name : Nom de la Node dans la scène Godot sous la node Musics à jouer # - after_player_name : Nom de la Node dans la scène Godot à attendre, puis à stopper # - from_random_time : joue depuis un temps aléatoire (true) ou non (false) # - fade_time : durée du fondu d'arrivée func queue_music( player_name : String, after_player_name : String, from_random_time := false, fade_time := DEFAULT_FADE_TIME ): var player : AudioStreamPlayer = get_player_from_node(after_player_name, %Musics) if player: await player.finished music_actions.append(AudioStop.new(after_player_name)) music_actions.append(AudioLaunch.new( player_name, from_random_time, fade_time )) # Stoppe la musique définie par player_name # - player_name : Nom de la Node dans la scène Godot sous la node Musics à jouer # - fade_time : durée du fondu de départ func stop_music(player_name : String, fade := DEFAULT_FADE_TIME): music_actions.append(AudioStop.new(player_name, fade)) # Stoppe toutes les musiques # - fade_time : durée du fondu de départ func stop_all_musics(fade := DEFAULT_FADE_TIME): music_actions.append(AudioStopAll.new(fade)) # Joue l'ambiance définie par player_name, arrête toute les autres musiques immédiatement # - player_name : Nom de la Node dans la scène Godot sous la node Ambiances à jouer # - from_random_time : joue depuis un temps aléatoire (true) ou non (false) # - fade_time : durée du fondu d'arrivée func play_ambiance_alone( player_name : String = "", from_random_time := false, fade_time := DEFAULT_FADE_TIME ): stop_all_ambiances() play_ambiance(player_name,from_random_time,fade_time) # Joue l'ambiance définie par player_name # - player_name : Nom de la Node dans la scène Godot sous la node Ambiances à jouer # - from_random_time : joue depuis un temps aléatoire (true) ou non (false) # - fade_time : durée du fondu d'arrivée func play_ambiance( player_name : String = "", from_random_time := false, fade_time := DEFAULT_FADE_TIME ): ambiance_actions.append(AudioLaunch.new( player_name, from_random_time, fade_time )) # Stoppe l'ambiance définie par player_name # - player_name : Nom de la Node dans la scène Godot sous la node Ambiances à jouer # - fade_time : durée du fondu de départ func stop_ambiance(player_name : String, fade := DEFAULT_FADE_TIME): ambiance_actions.append(AudioStop.new(player_name, fade)) # Stoppe toutes les ambiances # - fade_time : durée du fondu de départ func stop_all_ambiances(fade := DEFAULT_FADE_TIME): ambiance_actions.append(AudioStopAll.new(fade)) # Change le volume de toutes les ambiances qui jouent # - db_change : changement du volume en décibel, mettre à 0 pour reset le volume # - fade_time : durée du fondu de départ func change_ambiances_volume(db_change := 0., fade := DEFAULT_FADE_TIME): ambiance_actions.append( AudioChangeVolumeAll.new( db_change, fade ) ) # Joue un # - player_name : Nom de la Node dans la scène Godot à jouer func play_sfx(sfx_name : String): var player := %Sfx.find_child(sfx_name) as AudioStreamPlayer if player: player.play() else: printerr("Sfx %s not found" % sfx_name) # ----------------- Partie Technique (pas touche Niels ;D) ---------------- func _ready(): for player in get_all_players(): player.stop() fetch_default_volumes() # setup_players_bus() settings.sound_changed.connect( func(_s) : setup_players_bus() ) SceneManager.scene_loaded.connect(_on_change_scene) Dialogic.timeline_started.connect(_on_timeline_started) Dialogic.timeline_ended.connect(_on_timeline_ended) func _process(_d): if len(music_actions) > 0: playing_musics = process_audio_actions_for_node(music_actions, %Musics, playing_musics) music_actions = [] if len(ambiance_actions) > 0: playing_ambiances = process_audio_actions_for_node(ambiance_actions, %Ambiances, playing_ambiances) ambiance_actions = [] func process_audio_actions_for_node( audio_actions : Array[AudioAction], parent_node : Node, current_players: Array[String] ): var players : Array[String] = current_players.duplicate() for audio_action in audio_actions: players = audio_action.process( self, parent_node, players ) return players func get_player_from_node(player_name : String, parent_node : Node) -> AudioStreamPlayer: var player = parent_node.find_child(player_name) if not player: printerr("Player %s not found in category %s" % [player_name, parent_node.name]) return null return player func fetch_default_volumes(): var all_players := get_all_players() for player in all_players: default_volumes[player] = player.volume_db func setup_players_bus(): for player in get_all_players(): if player.get_parent() == %Musics: player.bus = (AudioServer.get_bus_name(SettingsData.MUSIC_BUS_ID)) elif player.get_parent() == %Sfx: player.bus = (AudioServer.get_bus_name(SettingsData.SFX_BUS_ID)) elif player.get_parent() == %Ambiances: player.bus = (AudioServer.get_bus_name(SettingsData.AMBIANCE_BUS_ID)) func get_volume(player : AudioStreamPlayer) -> float: return default_volumes[player] func get_all_players() -> Array[AudioStreamPlayer]: var players : Array[AudioStreamPlayer] = [] players.append_array(get_players_from_node(%Musics)) players.append_array(get_players_from_node(%Ambiances)) players.append_array(get_players_from_node(%Sfx)) return players static func get_players_from_node(node : Node) -> Array[AudioStreamPlayer]: var streams : Array[AudioStreamPlayer] = [] for c in node.get_children(): if c is AudioStreamPlayer: streams.append(c) return streams func set_volume(player : AudioStreamPlayer, to : float, fade_time = DEFAULT_FADE_TIME) -> Tween: var fade_tween : Tween = get_tree().create_tween() fade_tween.tween_property(player, "volume_db", to, fade_time) return fade_tween func start_player(player: AudioStreamPlayer, from_random_time = false, fade_time = DEFAULT_FADE_TIME): if player and not player.playing: player.play( 0.0 if not from_random_time else randf_range(0.0, player.stream.get_length()) ) if fade_time > 0.0: player.volume_db = MIN_VOLUME await set_volume(player, get_volume(player), fade_time).finished func stop_player(player : AudioStreamPlayer, fade_time = DEFAULT_FADE_TIME): if player and player.playing: if fade_time > 0.0: await set_volume(player, MIN_VOLUME, fade_time).finished player.stop() player.volume_db = get_volume(player) func reset_volume(player : AudioStreamPlayer): player.volume_db = get_volume(player) @abstract class AudioAction: @abstract func process( manager: AudioManagerInstance, parent_node : Node, current_players : Array[String] ) -> Array[String] class AudioLaunch extends AudioAction: var player_name : String var from_random_time : bool var fade_time : float var alone : bool func _init( _player_name : String, _from_random_time := false, _fade_time := DEFAULT_FADE_TIME, _alone := true, ): player_name = _player_name from_random_time = _from_random_time fade_time = _fade_time func process( manager: AudioManagerInstance, parent_node : Node, current_players : Array[String] ) -> Array[String]: var player := manager.get_player_from_node(player_name,parent_node) if player and not player.name in current_players: manager.start_player(player, from_random_time, fade_time) current_players.append(player_name) return current_players class AudioStop extends AudioAction: var player_name : String var fade_time : float func _init( _player_name : String, _fade_time := DEFAULT_FADE_TIME, ): player_name = _player_name fade_time = fade_time func process( manager: AudioManagerInstance, parent_node : Node, current_players : Array[String] ) -> Array[String]: var player = manager.get_player_from_node(player_name,parent_node) if player and player in current_players: manager.stop_player(player, fade_time) current_players.erase(player_name) return current_players class AudioStopAll extends AudioAction: var fade_time : float func _init( _fade_time := DEFAULT_FADE_TIME, ): fade_time = fade_time func process( manager: AudioManagerInstance, parent_node : Node, current_players : Array[String] ) -> Array[String]: for player_name in current_players: var player := manager.get_player_from_node(player_name,parent_node) if player: manager.stop_player(player, fade_time) return [] class AudioChangeVolumeAll extends AudioAction: var db_change : float var fade_time : float func _init( _db_change := 1.0, _fade_time := DEFAULT_FADE_TIME, ): db_change = _db_change fade_time = fade_time func process( manager: AudioManagerInstance, parent_node : Node, current_players : Array[String] ) -> Array[String]: for player_name in current_players: var player := manager.get_player_from_node(player_name,parent_node) if player: manager.set_volume( player, manager.get_volume(player) + db_change, fade_time ) return current_players