In Part One of our Developing World of Warcraft AddOns series we looked at how to create a basic "Hello, World!" AddOn. We managed to load it up in game and display a message on screen, both at initialisation time and with a slash command.
Today we'll be looking at how to play music and sound file(s) with our AddOns and creating a sound board, of sorts. It'll be slash command based, so the user will be able to type in something like:
/playsound ding
/playsound murlocs
/playsound main theme
/playsound custom
/stopsound
As you can imagine, each one allows us to play a particular sound or music file. We'll also be able to play custom sounds that we've added directly to our AddOn!
New AddOn
Let's create a new AddOn folder at Interface/AddOns/MusicPlayer
with the following MusicPlayer.toc
:
## Interface: 11303
## Title: MusicPlayer
## Notes: Play sounds and music inside of the game.
## Author: Paul Halliday
## Version: 0.0.1
MusicPlayer.lua
Finding Sounds
The easiest way to find sounds from World of Warcraft is to head over to Wowhead and find the in-game ID. For example, if we wanted to add the MurlocAggro
sound, we'd likely search for Murloc
and then click Links > Copy In-game Sound Command
:
This gives us the following command:
We can also go ahead and do the same for the Ding!
noise:
This gives us the following command:
We can also find game music with sites such as wow.tools which we can play using PlayMusic(id)
This can be played in-game by typing the following command:
/script PlayMusic("Sound\\Music\\GlueScreenMusic\\wow_main_theme.mp3")
You'll need to ensure that you've got music enabled for this to work.
If you're making an AddOn for retail, you'll want to use the fileId instead, i.e.
PlayMusic(53223)
We're then able to stop the music by typing:
Given what we now know, we can create a little MusicPlayer
which allows us to play sounds with a slash command.
It's time to write some code!
Registering Slash Commands
The first thing that we're going to do is register a slash command for our sound player. We'll want to register both /playsound
and /stopsound
inside of MusicPlayer.lua
:
SLASH_SOUND1 = "/playsound"
SLASH_STOPSOUND1 = "/stopsound"
local function playSoundHandler()
print("Play sound!")
end
local function stopSoundHandler()
print("Stop sound!")
end
SlashCmdList["SOUND"] = playSoundHandler;
SlashCmdList["STOPSOUND"] = stopSoundHandler;
If we type /reload
in-game, we should be able to see our messages if we type either of our slash commands.
Displaying Sounds
In order to play these sounds with our AddOn, we can make a table
named sounds
which contains information about the sound we'd like to play.
This allows us to either make a decision on which method we want to call to play the sound, or display information on screen to the user about the sound.
local soundType = {
SOUND = 1,
GAME_MUSIC = 2,
CUSTOM = 3
}
local sounds = {
["murloc"] = {
["sound"] = 416,
["description"] = "Mglrlrlrlrlrl!",
["type"] = soundType.SOUND
},
["ding"] = {
["sound"] = 888,
["description"] = "Grats!",
["type"] = soundType.SOUND
},
["main theme"] = {
["sound"] = "Sound\\Music\\GlueScreenMusic\\wow_main_theme.mp3",
["description"] = "DUN DUNNN... DUNNNNNNNNNN",
["type"] = soundType.GAME_MUSIC
},
["custom"] = {
["sound"] = "Interface\\AddOns\\MusicPlayer\\Sounds\\custom.mp3",
["description"] = "Custom sound!",
["type"] = soundType.CUSTOM
}
}
Feel free to add your own sounds here and experiment with different sounds from Wowhead.
I've also added a sound called custom.mp3
inside of a new folder I created at AddOns/MusicPlayer/Sounds
. This represents the ability to play a sound outside of the standard game files.
There isn't anything special about the folder name Sounds
, so feel free to add a custom sound wherever suits your use case. If you'd like to play your own sounds, go ahead and add it to the directory and sounds
table like I did.
We can now create a new function named displaySoundList
which will be used to print the potential sounds on screen to the user:
local function displaySoundList()
print("----------------------------")
for command in pairs(sounds) do
local description = sounds[command].description
print("Command: /playsound " .. command .. " - Description: " .. description)
end
print("----------------------------")
end
In order to use this, update your playSoundHandler
to call the displaySoundList
whenever we activate this command:
local function playSoundHandler()
displaySoundList()
end
Playing Sounds
Now that we've got a very helpful sound list, the user knows that they can type a particular command to play a sound!
Let's now wire up that functionality to actually play a sound by updating our playSoundHandler
:
local function playSoundHandler(trackId)
if(string.len(trackId) > 0) then
local matchesKnownTrack = sounds[trackId] ~= nil
if (matchesKnownTrack) then
local track = sounds[trackId]
playTrack(track)
else
displaySoundList()
print(trackId .. " - Doesn't match a known track.")
end
else
displaySoundList()
end
end
Our control flow now looks like the following:
- If there has been a
track
passed in by the user and it exists, play the track. - If there has been a
track
passed in by the user and it doesn't exist, display the sound list and a message. - If there is no
track
, display the sound list.
Let's write our playTrack
method so that we can actually play a sound!
local customSoundId
local function playTrack(track)
print(track.description)
if(track.type == soundType.GAME_MUSIC) then
PlayMusic(track.sound)
print("To stop the music type /stopsound")
elseif(track.type == soundType.SOUND) then
PlaySound(track.sound)
elseif(track.type == soundType.CUSTOM) then
stopSoundHandler()
customSoundId = select(2, PlaySoundFile(track.sound))
end
end
We're now able to either PlayMusic(track.sound)
, PlaySound(track.sound)
or PlaySoundFile(track.sound)
depending on the type that we determined inside of our sounds
table earlier.
Notice how we're creating a customSoundId
and only defining a value when we use PlaySoundFile
as this returns us an id
which we can use to stop the sound later in the next step.
Stopping Sounds
For the next step, I'm going to assume that any sound is just a few seconds long and a user wouldn't want to type /stopsound
to cancel it. A user may want to stop music and custom sound files though.
Let's update our stopSoundHandler
to support this:
local function stopSoundHandler()
StopMusic()
if(customSoundId ~= nil) then
StopSound(customSoundId)
customSoundId = nil
end
end
We're now able to stop sounds using /stopsound
!
You can try this out if you either play a custom sound file or some music with PlayMusic
.
Summary
In the second part of our Developing WoW AddOns series we created a little Music Player! It's not going to win AddOn of the year award by any stretch just yet, but we hopefully learned a little more about playing sound files.
Code for this article: https://github.com/PaulHalliday/wow_addon_music_player
Top comments (0)