190 lines
4.7 KiB
Lua
190 lines
4.7 KiB
Lua
--[[
|
|
The Wire Sound Emitter emits a sound whose parameters can be tweaked.
|
|
See http://wiki.garrysmod.com/page/Category:CSoundPatch
|
|
--]]
|
|
|
|
AddCSLuaFile()
|
|
DEFINE_BASECLASS( "base_wire_entity" )
|
|
ENT.PrintName = "Wire Sound Emitter"
|
|
ENT.WireDebugName = "Sound Emitter"
|
|
|
|
if CLIENT then return end
|
|
|
|
local DefaultSamples = {
|
|
"synth/square.wav",
|
|
"synth/saw.wav",
|
|
"synth/tri.wav",
|
|
"synth/sine.wav"
|
|
}
|
|
for _, str in pairs(DefaultSamples) do util.PrecacheSound(str) end
|
|
|
|
function ENT:Initialize()
|
|
self:PhysicsInit( SOLID_VPHYSICS )
|
|
self:SetMoveType( MOVETYPE_VPHYSICS )
|
|
self:SetSolid( SOLID_VPHYSICS )
|
|
|
|
self.Inputs = WireLib.CreateInputs(self, { "A", "Toggle", "Volume", "Play", "Stop",
|
|
"PitchRelative", "Sample", "SampleName [STRING]" })
|
|
self.Outputs = WireLib.CreateOutputs(self, { "Duration", "Property Sound", "Properties [ARRAY]", "Memory" })
|
|
|
|
self.Samples = table.Copy(DefaultSamples)
|
|
|
|
self.Active = false
|
|
self.Volume = 100
|
|
self.Pitch = 100
|
|
self.sound = self.Samples[1]
|
|
-- self.sound is a string, self.SoundObj is a CSoundPatch
|
|
|
|
self.NeedsRefresh = true
|
|
|
|
hook.Add("PlayerConnect", self:GetClass() .. self:EntIndex(), function()
|
|
self.NeedsRefresh = true
|
|
end)
|
|
end
|
|
|
|
function ENT:OnRemove()
|
|
hook.Remove("PlayerConnect", self:GetClass() .. self:EntIndex())
|
|
self:StopSounds()
|
|
BaseClass.OnRemove(self)
|
|
end
|
|
|
|
--[[
|
|
readcells:
|
|
0: active
|
|
1: volume
|
|
2: pitchrelative
|
|
3: duration
|
|
]]
|
|
function ENT:ReadCell(address)
|
|
address = math.floor(address)
|
|
if address == 0 then
|
|
return self.Active and 1 or 0
|
|
elseif address == 1 then
|
|
return self.Volume / 100
|
|
elseif address == 2 then
|
|
return self.Pitch / 100
|
|
elseif address == 3 then
|
|
return self.Outputs.Duration.Value
|
|
end
|
|
end
|
|
|
|
|
|
-- writecells:
|
|
local cellsOut = {
|
|
[0] = "A",
|
|
[1] = "Volume",
|
|
[2] = "PitchRelative",
|
|
[3] = "Sample",
|
|
[4] = "Play",
|
|
[5] = "Stop",
|
|
}
|
|
|
|
function ENT:WriteCell(address, value)
|
|
address = math.floor(address)
|
|
if cellsOut[address] then
|
|
self:TriggerInput(cellsOut[address], value)
|
|
return true
|
|
else
|
|
return false
|
|
end
|
|
end
|
|
|
|
function ENT:TriggerInput(iname, value)
|
|
if iname == "Toggle" and value ~= 0 then
|
|
self:TriggerInput("A", not self.Active)
|
|
elseif iname == "A" then
|
|
if value ~= 0 then
|
|
self:TriggerInput("Play", 1)
|
|
else
|
|
self:TriggerInput("Stop", 1)
|
|
end
|
|
elseif iname == "Play" and value ~= 0 then
|
|
-- Property sounds need to be refreshed
|
|
-- every time to work probably especially
|
|
-- when it has multiple sounds/pitches/volumes.
|
|
if self.SoundProperties then
|
|
self.NeedsRefresh = true
|
|
WireLib.TriggerOutput(self, "Duration", SoundDuration(self.sound))
|
|
end
|
|
|
|
self.Active = true
|
|
self:StartSounds()
|
|
elseif iname == "Stop" and value ~= 0 then
|
|
self.Active = false
|
|
self:StopSounds()
|
|
elseif iname == "Volume" then
|
|
self.Volume = math.Clamp(math.floor(value*100), 0.0, 100.0)
|
|
elseif iname == "PitchRelative" then
|
|
self.Pitch = math.Clamp(math.floor(value*100), 0, 255)
|
|
elseif iname == "Sample" then
|
|
self:TriggerInput("SampleName", self.Samples[value] or self.Samples[1])
|
|
elseif iname == "SampleName" then
|
|
self:SetSound(value)
|
|
end
|
|
self:UpdateSound()
|
|
end
|
|
|
|
function ENT:UpdateSound()
|
|
if self.NeedsRefresh or self.sound ~= self.ActiveSample then
|
|
self.NeedsRefresh = nil
|
|
self.SoundObj = CreateSound(self, self.sound)
|
|
self.ActiveSample = self.sound
|
|
|
|
self.SoundProperties = sound.GetProperties(self.sound)
|
|
if self.SoundProperties then
|
|
WireLib.TriggerOutput(self, "Duration", SoundDuration(self.sound))
|
|
WireLib.TriggerOutput(self, "Property Sound", 1)
|
|
WireLib.TriggerOutput(self, "Properties", self.SoundProperties)
|
|
else
|
|
WireLib.TriggerOutput(self, "Property Sound", 0)
|
|
WireLib.TriggerOutput(self, "Properties", {})
|
|
end
|
|
|
|
if self.Active then self:StartSounds() end
|
|
end
|
|
self.SoundObj:ChangePitch(self.Pitch, 0)
|
|
self.SoundObj:ChangeVolume(self.Volume / 100.0, 0)
|
|
end
|
|
|
|
function ENT:SetSound(soundName)
|
|
self:StopSounds()
|
|
|
|
if soundName:match('["?]') then return end
|
|
parsedsound = soundName:Trim()
|
|
util.PrecacheSound(parsedsound)
|
|
|
|
self.sound = parsedsound
|
|
|
|
self.SoundProperties = sound.GetProperties(self.sound)
|
|
if self.SoundProperties then
|
|
WireLib.TriggerOutput(self, "Duration", SoundDuration(self.sound))
|
|
WireLib.TriggerOutput(self, "Property Sound", 1)
|
|
WireLib.TriggerOutput(self, "Properties", self.SoundProperties)
|
|
else
|
|
WireLib.TriggerOutput(self, "Property Sound", 0)
|
|
WireLib.TriggerOutput(self, "Properties", {})
|
|
end
|
|
|
|
self:SetOverlayText( parsedsound:gsub("[/\\]+","/") )
|
|
end
|
|
|
|
function ENT:StartSounds()
|
|
if self.NeedsRefresh then
|
|
self:UpdateSound()
|
|
end
|
|
if self.SoundObj then
|
|
self.SoundObj:Play()
|
|
end
|
|
end
|
|
|
|
function ENT:StopSounds()
|
|
if self.SoundObj then
|
|
self.SoundObj:Stop()
|
|
end
|
|
end
|
|
|
|
function ENT:Setup(sample)
|
|
self:SetSound(sample)
|
|
end
|
|
|
|
duplicator.RegisterEntityClass("gmod_wire_soundemitter", WireLib.MakeWireEnt, "Data", "sound")
|