// =========================================================================================
// [GUI-Friendly] Rapid Sound v1.91
//
// ~by Reventhous
// http://www.hiveworkshop.com/threads/gui-friendly-rapid-sound.289576/
//
// ~originally by Quilnez
// http://www.hiveworkshop.com/threads/snippet-rapidsound.258991/
//
// =========================================================================================
// -----------------------------------------------------------------------------------------
// -WHAT IS THIS?
//
// A system that allows you to play sounds rapidly and flawlessly without limit.
// Supports both .mp3 and .wav file
// Remember! One sound file for one instance
// -----------------------------------------------------------------------------------------
// -----------------------------------------------------------------------------------------
//
// -HOW TO IMPORT
// 1. Go to File [tab] > Preferences. Make sure "Automatically create unknwon variables...
// is ticked.
// 2. Copy the "Rapid Sound" category with "GUI RapidSound" and "gRSound VarGen" triggers in it.
// 3. Paste it to your map.
// 4. Done.
// -----------------------------------------------------------------------------------------
//
// =========================================================================================
// -----------------------------------------------------------------------------------------
// Configurations
//
// facing problem?, turn this to true to see helpful messages
constant function GRS_IS_DEBUG_MODE takes nothing returns boolean
return false
endfunction
// auto create RapidSound. Highly recommended to set it true
constant function GRS_AUTO_CREATE takes nothing returns boolean
return true
endfunction
// auto preload sound, create RapidSound instance on map initialization and the system will
// automatically preload the sound.
constant function GRS_AUTO_PRELOAD takes nothing returns boolean
return true
endfunction
//
// End of configurations
// -----------------------------------------------------------------------------------------
// =========================================================================================
// anything you do below this line is at your own risk
// =========================================================================================
constant function GRS_MIN_DELAY_FACTOR takes nothing returns real
return 4.00
endfunction
constant function GRS_MAX_COUNT takes nothing returns integer
return 4
endfunction
// -----------------------------------------------------------------------------------------
// This function destroys/recycle stack
// -----------------------------------------------------------------------------------------
function GRS_Stack_Destroy takes integer this returns nothing
local integer last = udg_GRS_Stack_First[this]
loop
exitwhen udg_GRS_Stack_Next[last] == 0
set last = udg_GRS_Stack_Next[last]
endloop
// recycle set of nodes
set udg_GRS_Stack_Next[last] = udg_GRS_Stack_Next[0]
set udg_GRS_Stack_Next[0] = udg_GRS_Stack_First[this]
// recycle head
set udg_GRS_Stack_Recycle[this] = udg_GRS_Stack_Recycle[0]
set udg_GRS_Stack_Recycle[0] = this
endfunction
// -----------------------------------------------------------------------------------------
// Push/Add a instance to the stack
// -----------------------------------------------------------------------------------------
function GRS_Stack_Push takes integer this returns integer
local integer node
if (udg_GRS_Stack_Next[0] == 0) then
set udg_GRS_Stack_NodeCount = udg_GRS_Stack_NodeCount + 1
set node = udg_GRS_Stack_NodeCount
else
set node = udg_GRS_Stack_Next[0]
set udg_GRS_Stack_Next[0] = udg_GRS_Stack_Next[node]
endif
set udg_GRS_Stack_Next[node] = udg_GRS_Stack_First[this]
set udg_GRS_Stack_First[this] = node
return node
endfunction
// -----------------------------------------------------------------------------------------
// This function creates stack for sound
// -----------------------------------------------------------------------------------------
function GRS_Stack_Create takes nothing returns integer
local integer this
if (udg_GRS_Stack_Recycle[0] == 0) then
set udg_GRS_Stack_InstanceCount = udg_GRS_Stack_InstanceCount + 1
set this = udg_GRS_Stack_InstanceCount
else
set this = udg_GRS_Stack_Recycle[0]
set udg_GRS_Stack_Recycle[0] = udg_GRS_Stack_Recycle[this]
set udg_GRS_Stack_First[this] = 0
endif
return this
endfunction
// -----------------------------------------------------------------------------------------
// This function gives the duration of a sound
// -----------------------------------------------------------------------------------------
function GRS_GetDuration takes integer this returns real
return udg_GRS_Duration_p[this]*GRS_MIN_DELAY_FACTOR()
endfunction
// -----------------------------------------------------------------------------------------
// This function will recycle the instance and the queue
// -----------------------------------------------------------------------------------------
function GRS_Kill takes integer this returns nothing
local integer i = 0
local integer dex
loop
exitwhen i == GRS_MAX_COUNT()
set dex = udg_GRS_First_p[this] + i
call StopSound(udg_GRS_Sound_p[dex], true, false)
call DestroyTimer(udg_GRS_Timer_p[dex])
set udg_GRS_Sound_p[dex] = null
set udg_GRS_Timer_p[dex] = null
// recycle queue
set udg_GRS_Recycle_p[dex] = udg_GRS_Recycle_p[0]
set udg_GRS_Recycle_p[0] = dex
set i = i + 1
endloop
call GRS_Stack_Destroy(this)
endfunction
// -----------------------------------------------------------------------------------------
// This function stops each sound in RapidSound
// -----------------------------------------------------------------------------------------
function GRS_Stop takes integer this, boolean fadeOut returns nothing
local integer i = 0
loop
exitwhen i == GRS_MAX_COUNT()
call StopSound(udg_GRS_Sound_p[udg_GRS_List_p[udg_GRS_First_p[this] + i]], false, fadeOut)
set i = i + 1
endloop
endfunction
// -----------------------------------------------------------------------------------------
// This function plays the sound
// -----------------------------------------------------------------------------------------
function GRS_Play takes integer this, real x, real y, real z, integer volume returns nothing
// the sound cycle
if (udg_GRS_Array_p[this] == (udg_GRS_First_p[this]) + GRS_MAX_COUNT()) then
set udg_GRS_Array_p[this] = udg_GRS_First_p[this]
endif
if TimerGetRemaining(udg_GRS_Timer_p[udg_GRS_List_p[udg_GRS_Array_p[this]]]) == 0 then
call StopSound(udg_GRS_Sound_p[udg_GRS_List_p[udg_GRS_Array_p[this]]], false, false)
call SetSoundPosition(udg_GRS_Sound_p[udg_GRS_List_p[udg_GRS_Array_p[this]]], x, y, z)
call SetSoundVolume(udg_GRS_Sound_p[udg_GRS_List_p[udg_GRS_Array_p[this]]], volume)
call StartSound(udg_GRS_Sound_p[udg_GRS_List_p[udg_GRS_Array_p[this]]])
call TimerStart(udg_GRS_Timer_p[udg_GRS_List_p[udg_GRS_Array_p[this]]], udg_GRS_Duration_p[this], false, null)
endif
set udg_GRS_Array_p[this] = udg_GRS_Array_p[this] + 1
endfunction
// -----------------------------------------------------------------------------------------
// This function creates RapidSound instance
// -----------------------------------------------------------------------------------------
function GRS_Create takes string fileName, boolean is3D, boolean autoStop, integer inRate, integer outRate returns integer
local integer this
local integer i = 1
local integer s
local integer q
set this = GRS_Stack_Create()
set udg_GRS_SoundName_p[this] = fileName
set udg_GRS_Duration_p[this] = I2R(GetSoundFileDuration(fileName))/(1000.*GRS_MIN_DELAY_FACTOR())
loop
exitwhen i > GRS_MAX_COUNT()
set s = GRS_Stack_Push(this)
if udg_GRS_Recycle_p[0] == 0 then
set udg_GRS_Queue_p = udg_GRS_Queue_p + 1
set q = udg_GRS_Queue_p
else
set q = udg_GRS_Recycle_p[0]
set udg_GRS_Recycle_p[0] = udg_GRS_Recycle_p[q]
endif
set udg_GRS_List_p[q] = s
if i == 1 then
set udg_GRS_First_p[this] = q
endif
set udg_GRS_Sound_p[s] = CreateSound(fileName, false, is3D, autoStop, inRate, outRate, "")
set udg_GRS_Timer_p[s] = CreateTimer()
set i = i + 1
endloop
set udg_GRS_Array_p[this] = udg_GRS_First_p[this]
call SaveInteger(udg_GRS_Hash_p, StringHash(fileName), 0, this)
return this
endfunction
// sound preloading, By Silvenon
function PreloadSoundPath takes string path returns nothing
local sound snd = CreateSound(path, false, false, false, 10, 10, "")
call SetSoundVolume(snd, 0)
call StartSound(snd)
call KillSoundWhenDone(snd)
set snd = null
endfunction
// will tell if the sound file name is valid or not >> I couldn't find any of this function anywhere, so...
// by Reventhous
function IsSoundFileNameValid takes string fileName returns boolean
local sound snd = CreateSound(fileName, false, false, false, 10, 10, "")
local boolean b = (GetSoundDuration(snd) > 0.00)
call StopSound(snd, true, false)
set snd = null
return b
endfunction
function GRS_AutoSoundPreload takes string fileName returns nothing
if not LoadBoolean(udg_GRS_Hash_p, StringHash(fileName), 0) then
call PreloadSoundPath(fileName)
call SaveBoolean(udg_GRS_Hash_p, StringHash(fileName), 0, true)
endif
endfunction
// will search RapidSound instance by string
function GRS_Get takes string fileName returns integer
return LoadInteger(udg_GRS_Hash_p, StringHash(fileName), 0)
endfunction
// will reset the gRSParam variable to its default
function GRS_ResetParameters takes nothing returns nothing
set udg_GRS_autoStop = false
set udg_GRS_fadeOut = false
set udg_GRS_fileName = ""
set udg_GRS_inRate = 0
set udg_GRS_is3D = false
set udg_GRS_outRate = 0
set udg_GRS_State = 0
set udg_GRS_Volume = 127
set udg_GRS_X = 0.
set udg_GRS_Y = 0.
set udg_GRS_Z = 0.
endfunction
// -----------------------------------------------------------------------------------------
// The actions and the initializaion
// -----------------------------------------------------------------------------------------
function GRS_Actions takes nothing returns nothing
local integer i
// prevent the system works for nothing
if (udg_GRS_State < 1) or (udg_GRS_State > 6) then
if GRS_IS_DEBUG_MODE() then
call DisplayTimedTextToPlayer(GetLocalPlayer(), 0, 0, 30, "|CFFFFCC00[GRapid Sound]|R: " + "Using undefined GRS_State" )
endif
call GRS_ResetParameters()
return
endif
// reject invalid sound file name
if not IsSoundFileNameValid(udg_GRS_fileName) then
if GRS_IS_DEBUG_MODE() then
call DisplayTimedTextToPlayer(GetLocalPlayer(), 0, 0, 30, "|CFFFFCC00[GRapid Sound]|R: " + "invalid sound file name!" )
endif
call GRS_ResetParameters()
return
endif
if GRS_AUTO_PRELOAD() then
call GRS_AutoSoundPreload(udg_GRS_fileName)
endif
// create
if (udg_GRS_State == udg_GRS_Create) then
set udg_GRS_LastCreatedRSound = GRS_Create(udg_GRS_fileName, udg_GRS_is3D, udg_GRS_autoStop, udg_GRS_inRate, udg_GRS_outRate)
call GRS_ResetParameters()
return
endif
// find RapidSound instance by string
set i = GRS_Get(udg_GRS_fileName)
// if not found,
if (i == 0) then
// automatically create a new instance for the sound.
if GRS_AUTO_CREATE() then
set i = GRS_Create(udg_GRS_fileName, udg_GRS_is3D, udg_GRS_autoStop, udg_GRS_inRate, udg_GRS_outRate)
else
call GRS_ResetParameters()
return
endif
endif
// play
if (udg_GRS_State == udg_GRS_Play) then
call GRS_Play(i, udg_GRS_X, udg_GRS_Y, udg_GRS_Z, udg_GRS_Volume)
// stop
elseif (udg_GRS_State == udg_GRS_Stop) then
call GRS_Stop(i, udg_GRS_fadeOut)
// kill
elseif (udg_GRS_State == udg_GRS_Kill) then
call GRS_Kill(i)
// get sound duration by RapidSound instance
elseif (udg_GRS_State == udg_GRS_GetDuration) then
set udg_GRS_SoundDuration = GRS_GetDuration(i)
// preload
elseif (udg_GRS_State == udg_GRS_Preload) then
call PreloadSoundPath(udg_GRS_fileName)
endif
// reset gRSParam variables to its default
call GRS_ResetParameters()
endfunction
function InitTrig_GUI_RapidSound takes nothing returns nothing
// hashtable for instance searching
set udg_GRS_Hash_p = InitHashtable()
// the state id
set udg_GRS_Create = 1
set udg_GRS_Play = 2
set udg_GRS_Stop = 3
set udg_GRS_Kill = 4
set udg_GRS_GetDuration = 5
set udg_GRS_Preload = 6
set gg_trg_GUI_RapidSound = CreateTrigger()
call TriggerAddAction( gg_trg_GUI_RapidSound, function GRS_Actions )
endfunction