--Welcome. I've written this code myself and heavily improved and fixed it with the help of Angelo234! Lots of Thanks to him!! I've marked sections of his code. --Anyways, you're probably here because you want to add you own music, which is fair enough, the Beam music isn't all thaat exiting --There are instructions in form of notes all over the file. If you experience any issues, feel free to contact me under Inn0centJok3r on BeamNG.com --I hope the notes are helpful enough to allow you to get your stuff working. Have a nice day! --Please read all notes. --Created by Inn0centJok3r --DO NOT USE WITHOUT PERMISSION! ASK ME AT https://www.beamng.com/members/inn0centjok3r.318168/ local M = {} local sfx_table = {} --For caching the played music local songName = "Radio Off" local songLimit = 11 --Set your new limit for the max amount of songs in a playlist here! local listLimit = 2 --Set your new limit for the max amount of playlists here! local volume = 3 local song = 0 local list = 1 local timer = 0 local musicList = "Default Music" local author = "Unknown" local play_song_dir = nil local inputBlock = false local need_to_create_sfx = false local current_sfx_playing = nil local song_dir = nil local volumeChanged = false local volumeChangedTimer = 0 local timermusic = 0 local timerrunning = false local songchanged = false local song_dir_cache = nil local autoplaytimer = 0 local songLength = 0 local autoplay = true local autoplaySetting = true local soundNode = 350 local buttonPress local function playList() if list == 1 then musicList = "Default Music" if song == 0 then songName = "How did you do this?" play_song_dir = nil author = "Unknown" autoplay = false songLength = 0 elseif song == 1 then songName = "Claire De Lune Loop" play_song_dir = "event:>Special>piano_music" author = "Claude Debussy" autoplay = true songLength = 23.5 elseif song == 2 then songName = "Ramblings" play_song_dir = "art/sound/music/dploe.mp3" author = "Gabester" autoplay = true songLength = 346 elseif song == 3 then songName = "Splendid Misanthropy" play_song_dir = "art/sound/music/woo01.mp3" author = "Gabester" autoplay = true songLength = 338 elseif song == 4 then songName = "Ample Descent" play_song_dir = "art/sound/music/deeda_1.mp3" author = "Gabester" autoplay = true songLength = 278 elseif song == 5 then songName = "Lightrunner Theme Loop" play_song_dir = "event:>Music>synthwave" author = "Mark TDK Knight" autoplay = false songLength = 0 elseif song == 6 then songName = "Drip Fountain" play_song_dir = "art/sound/music/drip_fountain" author = "Gabester and CaptainZoll" autoplay = true songLength = 66 elseif song == 7 then songName = "Lonle (Credits Theme)" play_song_dir = "art/sound/music/lonle.mp3" author = "Gabester" autoplay = true songLength = 261 elseif song == 8 then songName = "Very Bassy Music" play_song_dir = "art/sound/music/Legran_Music_interior" author = "MGR '99" autoplay = true songLength = 40 elseif song == 9 then songName = "Dicta" play_song_dir = "art/sound/music/dicta" author = "Gabester" autoplay = true songLength = 35 elseif song == 10 then songName = "Merry Christmas Jingle" play_song_dir = "art/sounds/mod_winter/Merry_Christmas_Jingle_Filtered_01.protected.ogg" author = "Unknown" autoplay = true songLength = 22.5 elseif song == 11 then songName = "Deck The Halls Bells" play_song_dir = "art/sounds/mod_winter/Deck_the_Halls_Bells_Filtered.protected.ogg" author = "Unknown" autoplay = true songLength = 20.5 end elseif list == 2 then musicList = "Custom Music" --Feel free to change the playlist name. To add more lists, you can just copy paste this one here to the spot marked --X and then change listLimit=2 to 3 or whichever --... amount of lists that you want to add. if song == 0 then songName = "How did you do this?" play_song_dir = nil author = "Unknown" autoplay = false songLength = 0 elseif song == 1 then songName = "Birdhouse in Your Soul" play_song_dir = "art/sound/music/birdhouse.ogg" author = "They Might Be Giants" autoplay = true songLength = 200 --Length of the song in seconds, PLEASE ENTER THIS INFORMATION TO USE THE AUTOPLAY FEATURE!! elseif song == 2 then songName = "They Might Be Giants" play_song_dir = "art/sound/music/giants.ogg" author = "They Might Be Giants" autoplay = true songLength = 165 --Length of the song in seconds, PLEASE ENTER THIS INFORMATION TO USE THE AUTOPLAY FEATURE!! elseif song == 3 then songName = "Minimum Wage" play_song_dir = "art/sound/music/wage.ogg" author = "They Might Be Giants" autoplay = true songLength = 47 --Length of the song in seconds, PLEASE ENTER THIS INFORMATION TO USE THE AUTOPLAY FEATURE!! elseif song == 4 then songName = "Letterbox" play_song_dir = "art/sound/music/letterbox.ogg" author = "They Might Be Giants" autoplay = true songLength = 85 --Length of the song in seconds, PLEASE ENTER THIS INFORMATION TO USE THE AUTOPLAY FEATURE!! elseif song == 5 then songName = "10's" play_song_dir = "art/sound/music/10.mp3" author = "Pantera" autoplay = true songLength = 290 --Length of the song in seconds, PLEASE ENTER THIS INFORMATION TO USE THE AUTOPLAY FEATURE!! elseif song == 6 then songName = "Floods" play_song_dir = "art/sound/music/floods.mp3" author = "Pantera" autoplay = true songLength = 420 --Length of the song in seconds, PLEASE ENTER THIS INFORMATION TO USE THE AUTOPLAY FEATURE!! elseif song == 7 then songName = "Suicide Note Part I" play_song_dir = "art/sound/music/suicide.mp3" author = "Pantera" autoplay = true songLength = 284 --Length of the song in seconds, PLEASE ENTER THIS INFORMATION TO USE THE AUTOPLAY FEATURE!! elseif song == 8 then songName = "One" play_song_dir = "art/sound/music/one.wav" author = "Metallica" autoplay = true songLength = 46 --Length of the song in seconds, PLEASE ENTER THIS INFORMATION TO USE THE AUTOPLAY FEATURE!! elseif song == 9 then songName = "Your Song Name Here" --play_song_dir = "art/sound/music/YOUR FILE NAME HERE" author = "Unknown" autoplay = true songLength = 60 --Length of the song in seconds, PLEASE ENTER THIS INFORMATION TO USE THE AUTOPLAY FEATURE!! elseif song == 10 then songName = "Your Song Name Here" --play_song_dir = "art/sound/music/YOUR FILE NAME HERE" author = "Unknown" autoplay = true songLength = 60 --Length of the song in seconds, PLEASE ENTER THIS INFORMATION TO USE THE AUTOPLAY FEATURE!! end --X new playlists -underneath- this point here! Make sure to NOT place anything UNDER the "end" end end --No need to change anything below here. Unless you know what you're doing --Code by Angelo234 start local function loadSong(song_dir) --If SFX source is not cached (has never been played), then create SFX source if not sfx_table[song_dir] then sfx_table[song_dir] = obj:createSFXSource(song_dir, "AudioDefaultLoop3D", "", soundNode) return true end return false end local function playSong(song_dir) --Stop current music if current_sfx_playing then obj:setVolumePitch(current_sfx_playing, 0, 1) obj:stopSFX(current_sfx_playing) end --Play new song local sfx_to_play = sfx_table[song_dir] obj:setVolumePitch(sfx_to_play, volume, 1) obj:playSFX(sfx_to_play) current_sfx_playing = sfx_to_play end --Code by Angelo234 end local function moreVol() buttonPress = buttonPress or sounds.createSoundscapeSound("ButtonPress") sounds.playSoundSkipAI(buttonPress) if electrics.values.ignitionLevel > 0 then if volume <= 9 then volume = volume + 1 guihooks.message("Radio Volume: " .. volume, 4, "vehicle.vertexRadio.volumeState", "volume_up") if current_sfx_playing then obj:setVolumePitch(current_sfx_playing, (volume * 0.6), 1) end end if volume >= 10 then guihooks.message("Max Radio Volume: " .. volume, 4, "vehicle.vertexRadio.volumeState", "volume_up") if current_sfx_playing then obj:setVolumePitch(current_sfx_playing, (volume * 0.6), 1) end end volumeChanged = true volumeChangedTimer = 0 else guihooks.message("Turn on ignition first", 4, "vehicle.vertexRadio.volumeState", "do_not_disturb_alt") end end local function lessVol() buttonPress = buttonPress or sounds.createSoundscapeSound("ButtonPress") sounds.playSoundSkipAI(buttonPress) if electrics.values.ignitionLevel > 0 then if volume >= 1 then volume = volume - 1 guihooks.message("Radio Volume: " .. volume, 4, "vehicle.vertexRadio.volumeState", "volume_down") if current_sfx_playing then obj:setVolumePitch(current_sfx_playing, (volume * 0.6), 1) end end if volume == 0 then guihooks.message("Lowest Radio Volume: " .. volume, 4, "vehicle.vertexRadio.volumeState", "volume_mute") if current_sfx_playing then obj:setVolumePitch(current_sfx_playing, (volume * 0.6), 1) end end volumeChanged = true volumeChangedTimer = 0 else guihooks.message("Turn on ignition first", 4, "vehicle.vertexRadio.volumeState", "do_not_disturb_alt") end end local function nextSong() buttonPress = buttonPress or sounds.createSoundscapeSound("ButtonPress") sounds.playSoundSkipAI(buttonPress) if electrics.values.ignitionLevel > 0 then if inputBlock == false then --Blocking input for a small amount of time to prevent user from spamming the function and causing a lua error if song >= songLimit then song = 1 else song = song + 1 end if song ~=0 then autoplay = false playList() guihooks.message("Next song playing. Now playing: " .. songName .. " (" .. song .. "/" .. songLimit .. ")" .. " -by " .. author, 4, "vehicle.vertexRadio.songState", "volume_up") if electrics.values['reverseactive'] == 0 then --infotainment screen stuff timerrunning = true electrics.values['musicscreenactive'] = 1 songchanged = true end end end else guihooks.message("Turn on ignition first", 4, "vehicle.vertexRadio.songState", "do_not_disturb_alt") end end local function pastSong() buttonPress = buttonPress or sounds.createSoundscapeSound("ButtonPress") sounds.playSoundSkipAI(buttonPress) if electrics.values.ignitionLevel > 0 then if song ~=0 then song = song - 1 if song == 0 then guihooks.message("Radio off", 4, "vehicle.vertexRadio.songState", "volume_off") autoplay = false songName = "Radio Off" obj:stopSFX(current_sfx_playing) songLength = 0 end end if song ~=0 then autoplay = false playList() guihooks.message("Past song playing. Now playing: " .. songName .. " (" .. song .. "/" .. songLimit .. ")" .. " -by " .. author, 4, "vehicle.vertexRadio.songState", "volume_up") if electrics.values['reverseactive'] == 0 then timerrunning = true electrics.values['musicscreenactive'] = 1 songchanged = true end end else guihooks.message("Turn on ignition first", 4, "vehicle.vertexRadio.songState", "do_not_disturb_alt") end end local function pastSongList() autoplay = false playList() song_dir_cache = sfx_table[song_dir] songName = "Radio Off" if current_sfx_playing then obj:setVolumePitch(current_sfx_playing, 0, 0) obj:stopSFX(current_sfx_playing) end end local function nextList() buttonPress = buttonPress or sounds.createSoundscapeSound("ButtonPress") sounds.playSoundSkipAI(buttonPress) if electrics.values.ignitionLevel > 0 then if list >= listLimit then list = 1 else list = list + 1 end song = 0 pastSongList() guihooks.message("Next Playlist selected: " .. musicList .. " (" .. list .. "/" .. listLimit .. ")", 4, "vehicle.vertexRadio.listState", "toc") else guihooks.message("Turn on ignition first", 4, "vehicle.vertexRadio.listState", "do_not_disturb_alt") end end local function pastList() buttonPress = buttonPress or sounds.createSoundscapeSound("ButtonPress") sounds.playSoundSkipAI(buttonPress) if electrics.values.ignitionLevel > 0 then if list ~=1 then list = list - 1 song = 0 pastSongList() guihooks.message("Past Playlist selected: " .. musicList .. " (" .. list .. "/" .. listLimit .. ")", 4, "vehicle.vertexRadio.listState", "toc") end else guihooks.message("Turn on ignition first", 4, "vehicle.vertexRadio.listState", "do_not_disturb_alt") end end local function autoplay() buttonPress = buttonPress or sounds.createSoundscapeSound("ButtonPress") sounds.playSoundSkipAI(buttonPress) if autoplaySetting == false then guihooks.message("Autoplay enabled", 4, "vehicle.vertexRadio.autoplay", "toc") autoplaySetting = true else guihooks.message("Autoplay disabled", 4, "vehicle.vertexRadio.autoplay", "toc") autoplaySetting = false end end local function turnOff() buttonPress = buttonPress or sounds.createSoundscapeSound("ButtonPress") sounds.playSoundSkipAI(buttonPress) autoplay = false song = 0 playList() song_dir_cache = sfx_table[song_dir] songName = "Radio Off" guihooks.message("Radio off", 4, "vehicle.vertexRadio.songState", "volume_off") if current_sfx_playing then obj:setVolumePitch(current_sfx_playing, 0, 0) obj:stopSFX(current_sfx_playing) end end local function updateGFX(dt) --Code by Angelo234 start if play_song_dir then --Check if we need to create SFX source if timer == 0 then need_to_create_sfx = loadSong(play_song_dir) end --If needed to create SFX source --then start timer to delay playing song if need_to_create_sfx then inputBlock = true timer = timer + dt else timer = 0.1 inputBlock = false end --If arbitrary amount of time passed then play song if timer >= 0.1 then playSong(play_song_dir) timer = 0 inputBlock = false play_song_dir = nil end end --Code by Angelo234 end --Automatically turn off any music when ignition is turned off while some is playing if electrics.values.ignitionLevel == 0 and song ~= 0 then turnOff() end --stuff for center screen if volumeChanged == true then volumeChangedTimer = volumeChangedTimer + dt if volumeChangedTimer >= 3 then volumeChanged = false volumeChangedTimer = 0 end end --Autoplay --print("RADIO DEBUG: automplaytimer: " .. autoplaytimer) if songLength > 0 then autoplaytimer = autoplaytimer + dt if autoplay == true and autoplaySetting == true then if autoplaytimer >= songLength then nextSong() end elseif autoplaytimer >= songLength then autoplaytimer = 0 end else autoplaytimer = 0 end --stuff for the infotainment screen if electrics.values['reverseactive'] == 1 then timermusic = 0 songchanged = false timerrunning = false end if timerrunning == true and electrics.values['reverseactive'] == 0 then timermusic = timermusic + dt if songchanged == true then autoplaytimer = 0 timermusic = 0 songchanged = false end if timermusic >= 5 then electrics.values['musicscreenactive'] = 0 timerrunning = false timermusic = 0 end end electrics.values["volumeChanged"] = volumeChanged electrics.values["radioAuthor"] = author electrics.values["radio"] = songName electrics.values["radioVolume"] = volume end local function onInit() if electrics.values["isSimpleTrafficCar"] then M.updateGFX = nop M.onReset = nop return end for v, node in pairs (v.data.nodes) do --for finding out the node ID if node.name == "int3" then soundNode = v end end volume = 3 song = 0 list = 1 timer = 0 songName = "Radio Off" musicList = "Default Music" author = "Unknown" play_song_dir = nil inputBlock = false need_to_create_sfx = false current_sfx_playing = nil electrics.values['musicscreenactive'] = 0 song_dir = nil volumeChanged = false volumeChangedTimer = 0 autoplaytimer = 0 timermusic = 0 timerrunning = false songchanged = false songLength = 0 end local function onReset() if song == 0 and current_sfx_playing then --To disable all previously played music that stats playing upon reset for unknown reasons song = 1 playList() song_dir = play_song_dir if song_dir_cache == nil and sfx_table[song_dir] ~= nil then song_dir_cache = sfx_table[song_dir] obj:setVolumePitch(song_dir_cache, 0, 1) obj:stopSFX(song_dir_cache) play_song_dir = nil inputBlock = false need_to_create_sfx = false current_sfx_playing = nil song = 0 songName = "Radio Off" musicList = "Default Music" author = "Unknown" elseif song_dir_cache ~= nil then obj:setVolumePitch(song_dir_cache, 0, 1) obj:stopSFX(song_dir_cache) play_song_dir = nil inputBlock = false need_to_create_sfx = false current_sfx_playing = nil song = 0 songName = "Radio Off" musicList = "Default Music" author = "Unknown" else song = 0 songName = "Radio Off" musicList = "Default Music" author = "Unknown" end end end -- public interface M.nextSong = nextSong M.pastSong = pastSong M.nextList = nextList M.pastList = pastList M.lessVol = lessVol M.moreVol = moreVol M.playList = playList M.autoplay = autoplay M.turnOff = turnOff M.onInit = onInit M.onReset = onReset M.updateGFX = updateGFX return M