extends Node const SFX_PATHS := { "hit": "res://assets/audio/sfx/hit.wav", "death": "res://assets/audio/sfx/death.wav", "level_up": "res://assets/audio/sfx/level_up.wav", "ability_cast": "res://assets/audio/sfx/ability_cast.wav", "portal_spawn": "res://assets/audio/sfx/portal_spawn.wav", "invasion_alarm": "res://assets/audio/sfx/invasion_alarm.wav", "tavern_damage": "res://assets/audio/sfx/tavern_damage.wav", } const MUSIC_PATHS := { "tavern": "res://assets/audio/music/tavern.wav", "battle": "res://assets/audio/music/battle.wav", "invasion": "res://assets/audio/music/invasion.wav", } const SFX_POOL_SIZE := 8 var sfx_cache: Dictionary = {} var music_cache: Dictionary = {} var sfx_players: Array[AudioStreamPlayer] = [] var music_player: AudioStreamPlayer = null var current_music: String = "" func _ready() -> void: for i in range(SFX_POOL_SIZE): var p := AudioStreamPlayer.new() p.volume_db = -6.0 add_child(p) sfx_players.append(p) music_player = AudioStreamPlayer.new() music_player.volume_db = -12.0 music_player.finished.connect(_on_music_finished) add_child(music_player) _preload_audio() EventBus.attack_executed.connect(_on_attack_executed) EventBus.entity_died.connect(_on_entity_died) EventBus.level_up.connect(_on_level_up) EventBus.portal_spawn.connect(_on_portal_spawn) EventBus.tavern_damaged.connect(_on_tavern_damaged) EventBus.invasion_started.connect(_on_invasion_started) EventBus.invasion_ended.connect(_on_invasion_ended) EventBus.wave_started.connect(_on_wave_started) _play_music("tavern") func _preload_audio() -> void: for key in SFX_PATHS: var path: String = SFX_PATHS[key] if ResourceLoader.exists(path): var stream: AudioStream = load(path) if stream: sfx_cache[key] = stream for key in MUSIC_PATHS: var path: String = MUSIC_PATHS[key] if ResourceLoader.exists(path): var stream: AudioStream = load(path) if stream is AudioStreamWAV: (stream as AudioStreamWAV).loop_mode = AudioStreamWAV.LOOP_FORWARD (stream as AudioStreamWAV).loop_end = (stream as AudioStreamWAV).data.size() / 2 if stream: music_cache[key] = stream func play_sfx(key: String) -> void: if not sfx_cache.has(key): return for p in sfx_players: if not p.playing: p.stream = sfx_cache[key] p.play() return func _play_music(key: String) -> void: if current_music == key and music_player.playing: return if not music_cache.has(key): return music_player.stream = music_cache[key] music_player.play() current_music = key func _on_music_finished() -> void: if current_music != "" and music_cache.has(current_music): music_player.play() func _on_attack_executed(_attacker, _pos, _dir, _dmg) -> void: play_sfx("hit") func _on_entity_died(entity: Node) -> void: if entity == PlayerData: return play_sfx("death") func _on_level_up(_player, _level) -> void: play_sfx("level_up") func _on_portal_spawn(_portal, _enemies) -> void: play_sfx("portal_spawn") func _on_tavern_damaged(_current, _max_val) -> void: play_sfx("tavern_damage") func _on_invasion_started(_enemies) -> void: play_sfx("invasion_alarm") _play_music("invasion") func _on_invasion_ended(_success) -> void: _play_music("battle") func _on_wave_started(_wave) -> void: if current_music != "invasion": _play_music("battle")