Hello,
I just made a module that allows to play Voicelines similar to Team Fortress 2, Anomalous Activities and other games that use Voicelines.
You can create categories but don’t need to. Here is an example of how it could look like:
As you can see, there are Configurations and Folder and before I forget, you play anything related to the voicelines inside the Folder called “Packages”, this also where you place everything, the sort of reference.
The Cache is where the modules places the copies of the Packages folder.
How to use
The module has 1 setting as of right now, “AutomaticallyFillEmptyCache”.
AutomaticallyFillEmptyCache will, as the name suggest, automatically fill the Cache of a Package if there was no Sound to be found.
You require the module on the client side once, and if you want to other Players to hear the Voicelines/Sounds you require the module also once on the server side.
You can use Folder, or whatever you’d like to fill the Packages. Configurations represent a Voiceline, you place all Sound variations under it.
The sounds can have attributes such as “MinVolume”, “MaxVolume”, “MinSpeed” and “MaxSpeed” with numbers as values. When you use the PlayVoiceline function it will randomly pick a Volume (if Min- or MaxVolume is given) and the same counts for Speed (PlaybackSpeed).
If you add a PitchShiftSoundEffect or an AudioPitchShifter, you can also set attributes “MinOctave” and “MaxOctave”, both are numbers and work the same as the Volume and Speed attributes on the Sound.
It also doesn’t matter if the Packages are Folders or Models.
Your Humanoid needs an attribute called “VoicelinePackage” with a string as value, for the PlayVoiceline function.
API
Getting a Sound from the Cache via a Path/Table. It will return a Sound or nothing and give a warn message if.
module.GetSoundFromCache = function(voicelinePath : {}) : Sound?
Fills the Cache Folder and creates as many new Sounds/Voicelines as the amount variable. If the Packages table is nil, it will automaticly duplicate all Packages. And if the amount variable is nil it will create 1 and it will always be atleast 1. It will tho print into the output how many Cache Packages were filled out of how many it should have created.
module.FillCache = function(amount : number, packages : {string})
Playing a Voiceline/Sound from the Cache and placing it inside the Characters Head. It won’t return anything. The Characters Humanoid or Controller (Configuration) needs to have an attribute called “VoicelinePackage” (string) which will be the first index of the voiceline path to play a voiceline. The voiceline being played will be renamed to “Voiceline”. As soon as the sound stops playing, will it return into the Cache. It will randomly pick a Sound to play.
module.PlayVoiceline = function(character : Model, voicelinePath : {}, ignoreDeath : boolean, cancelOtherVoicelines : boolean, cooldown : number?)
Important Notes
I created this module for the simple purpose of playing voicelines, you can use it probably for music too if you want since it stops the previously playing “Voiceline”/Sound if you play another one.
This module is purely client sided, meaning it won’t play any sounds on the server side.
You CAN make NPC’s play voicelines and everything.
The module needs to be required on the server side ONCE for other Players to hear the voicelines from NPC’s and other Players. I’d recommend requiring in inside of the NPC Handler/Spawner and making it a global variable but it wont matter, the event will trigger multiply times tho telling the client multiply times to play the same event.
Try to keep the voiceline path table small since the module use repeat until to search for the Instances and it can affect performance if the path is too long.
“voicelineCancelAmount” can be a number or boolean, if its set to true it will stop all playing Voicelines of the character, if it’s false, it won’t stop any Voicelines and if it’s a number, it will stop as many Voicelines as the number starting with the first Voiceline played (if it hasn’t already stopped).
Usage Example
local currentVoicelinesPath = {}
function UpdateVoicelinesFrame()
voicelinesContainer:ClearAllChildren()
local newGrid = Instance.new("UIGridLayout")
newGrid.CellPadding = UDim2.new()
newGrid.CellSize = UDim2.new(1, -4, 0.1, 0)
newGrid.FillDirection = Enum.FillDirection.Horizontal
newGrid.SortOrder = Enum.SortOrder.Name
newGrid.Parent = voicelinesContainer
local currentPath = table.clone(currentVoicelinesPath)
table.move(currentPath, 1, #currentPath, 2, currentPath)
currentPath[1] = controller:GetAttribute("VoicelinePackage")
local lastObject = ReplicatedStorage.Voicelines.Packages
repeat
lastObject = lastObject:FindFirstChild(currentPath[1])
table.remove(currentPath, 1)
until typeof(currentPath[1]) ~= "string" or typeof(lastObject) ~= "Instance"
if typeof(lastObject) == "Instance" and lastObject:IsA("Folder") then
local index = 0
for i, object in ipairs(lastObject:GetChildren()) do
if object:IsA("Configuration") then
index += 1
local newText = Instance.new("TextLabel")
newText.Name = index
newText.TextStrokeTransparency = 0
newText.TextColor3 = Color3.fromRGB(255, 255, 100)
newText.TextTransparency = 0
newText.TextStrokeColor3 = Color3.fromRGB(0, 0, 0)
newText.TextScaled = true
newText.Font = Enum.Font.Sarpanch
newText.BackgroundTransparency = 1
newText.TextXAlignment = Enum.TextXAlignment.Left
newText.Text = "[ " .. index .. " ] " .. object.Name
newText.RichText = true
newText.Parent = voicelinesContainer
elseif object:IsA("Folder") then
index += 1
local newText = Instance.new("TextLabel")
newText.Name = index
newText.TextStrokeTransparency = 0
newText.TextColor3 = Color3.fromRGB(255, 255, 255)
newText.TextTransparency = 0
newText.TextStrokeColor3 = Color3.fromRGB(0, 0, 0)
newText.TextScaled = true
newText.Font = Enum.Font.Sarpanch
newText.BackgroundTransparency = 1
newText.TextXAlignment = Enum.TextXAlignment.Left
newText.Text = "[ " .. index .. " ] " .. object.Name
newText.RichText = true
newText.Parent = voicelinesContainer
end
end
elseif typeof(lastObject) == "Instance" and lastObject:IsA("Configuration") then
voicelinesFrame.Visible = false
coroutine.wrap(voicelineModule.PlayVoiceline)(own_character, currentVoicelinesPath, false)
table.clear(currentVoicelinesPath)
table.clear(currentPath)
else
voicelinesFrame.Visible = false
table.clear(currentVoicelinesPath)
table.clear(currentPath)
end
end
UserInputService.InputBegan:Connect(function(input, processed)
if processed then
return
else
if input.KeyCode == Enum.KeyCode.Q then
if voicelinesFrame.Visible == true then
voicelinesFrame.Visible = false
else
voicelinesFrame.Visible = true
UpdateVoicelinesFrame()
end
end
if input.KeyCode == Enum.KeyCode.One then
if voicelinesFrame.Visible == true then
local name = voicelinesContainer["1"].Text
name = string.gsub(name, "%[ 1", "")
name = string.gsub(name, " %] ", "")
table.insert(currentVoicelinesPath, name)
UpdateVoicelinesFrame()
end
end
if input.KeyCode == Enum.KeyCode.Two then
if voicelinesFrame.Visible == true then
local name = voicelinesContainer["2"].Text
name = string.gsub(name, "%[ 2", "")
name = string.gsub(name, " %] ", "")
table.insert(currentVoicelinesPath, name)
UpdateVoicelinesFrame()
end
end
if input.KeyCode == Enum.KeyCode.Three then
if voicelinesFrame.Visible == true then
local name = voicelinesContainer["3"].Text
name = string.gsub(name, "%[ 3", "")
name = string.gsub(name, " %] ", "")
table.insert(currentVoicelinesPath, name)
UpdateVoicelinesFrame()
end
end
if input.KeyCode == Enum.KeyCode.Four then
if voicelinesFrame.Visible == true then
local name = voicelinesContainer["4"].Text
name = string.gsub(name, "%[ 4", "")
name = string.gsub(name, " %] ", "")
table.insert(currentVoicelinesPath, name)
UpdateVoicelinesFrame()
end
end
if input.KeyCode == Enum.KeyCode.Five then
if voicelinesFrame.Visible == true then
local name = voicelinesContainer["5"].Text
name = string.gsub(name, "%[ 5", "")
name = string.gsub(name, " %] ", "")
table.insert(currentVoicelinesPath, name)
UpdateVoicelinesFrame()
end
end
if input.KeyCode == Enum.KeyCode.Six then
if voicelinesFrame.Visible == true then
local name = voicelinesContainer["6"].Text
name = string.gsub(name, "%[ 6", "")
name = string.gsub(name, " %] ", "")
table.insert(currentVoicelinesPath, name)
UpdateVoicelinesFrame()
end
end
if input.KeyCode == Enum.KeyCode.Seven then
if voicelinesFrame.Visible == true then
local name = voicelinesContainer["7"].Text
name = string.gsub(name, "%[ 7", "")
name = string.gsub(name, " %] ", "")
table.insert(currentVoicelinesPath, name)
UpdateVoicelinesFrame()
end
end
if input.KeyCode == Enum.KeyCode.Eight then
if voicelinesFrame.Visible == true then
local name = voicelinesContainer["8"].Text
name = string.gsub(name, "%[ 8", "")
name = string.gsub(name, " %] ", "")
table.insert(currentVoicelinesPath, name)
UpdateVoicelinesFrame()
end
end
if input.KeyCode == Enum.KeyCode.Nine then
if voicelinesFrame.Visible == true then
local name = voicelinesContainer["9"].Text
name = string.gsub(name, "%[ 9", "")
name = string.gsub(name, " %] ", "")
table.insert(currentVoicelinesPath, name)
UpdateVoicelinesFrame()
end
end
if input.KeyCode == Enum.KeyCode.Zero then
if voicelinesFrame.Visible == true then
local name = voicelinesContainer["10"].Text
name = string.gsub(name, "%[ 10", "")
name = string.gsub(name, " %] ", "")
table.insert(currentVoicelinesPath, name)
UpdateVoicelinesFrame()
end
end
end
end
Here’s the module link:
Voiceline Module
(This is an unfinished edit as of right now)