class_name SFX # Expected files in res://assets/sfx/: # kick_player.ogg — player kicks something # kick_enemy.ogg — enemy attacks # merge.ogg — two objects merge # damage.ogg — player takes damage # ambient.ogg — looping background ambience const _BASE := "res://assets/" static func _play(name: String, parent: Node, volume_db: float = 0.0, pitch: float = 1.0) -> void: var path := _BASE + name if not ResourceLoader.exists(path): return var stream := load(path) as AudioStream if stream == null: return var ogg = stream as AudioStreamOggVorbis if ogg != null: ogg.loop = false var p := AudioStreamPlayer.new() p.stream = stream p.volume_db = volume_db p.pitch_scale = pitch + randf_range(-0.06, 0.06) p.bus = "Master" parent.add_child(p) p.play() p.connect("finished", p.queue_free) static func kick_player(parent: Node) -> void: _play("kick_player.ogg", parent, -4.0) static func kick_enemy(parent: Node) -> void: _play("kick_enemy.ogg", parent, -6.0) static func merge(parent: Node) -> void: _play("merge.ogg", parent, -3.0) static func damage(parent: Node) -> void: _play("damage.ogg", parent, -2.0) static func start_ambient(parent: Node) -> AudioStreamPlayer: var path := _BASE + "ambient.ogg" if not ResourceLoader.exists(path): return null var stream := load(path) as AudioStream if stream == null: return null var p := AudioStreamPlayer.new() p.stream = stream p.volume_db = -14.0 p.bus = "Master" p.autoplay = true (stream as AudioStreamOggVorbis).loop = true parent.add_child(p) return p