Controlling Looping Sounds System
Posted: Thu Dec 13, 2012 9:09 pm
Looping sounds ("sounds" in this post) have the following problems:
The door is invisible & is spawned then immediately opened thus producing the lockSound which is your defined sound. This fixes problem #4 as door produced sound does not occur on every level as playSoundAt() does. The sound can be stopped at anytime by simply destroying the door which fixes problem #1. The door never blocks anything as it's opened the moment it's spawned at a velocity of 100.
Note the following:
I have a timer on every level set to same interval (0.5 seconds ) calling this function. This function detects when the player loads a savegame and when a level change occurs and then calls restoreSound() to restart the sounds only on the current party level.
Note the following:
The restoreSound() function iterates through the sounds on the current party level & if it finds them, restarts them. Note how sounds are restarted by setting the door state to closed, then opening it again thus restarting the lockSound (your defined sound).
The sounds table stores references to all the sound doors. The example is a 3 level dungeon, you would add tables within the sounds table, one each for each level of your dungeon. Level 7 would be [7] = { },
startSound(sound, l, x, y, f, id) is called with the exact same parameters as spawn() (that's what it does, after all). Sound is the name of the sound door, not the defined sound.
stopSound(id) simply pass it the unique ID of the sound door.
Important: Door object produced sound emanates from the edge of the square (between squares). This doesn't change no matter where you place the door. You may want this, in which case, you're fine. However, if you want the sound to emanate "centrally" from the entire square you must do this:Two sound doors are spawned at opposite facings in the same square. You need to lower the volume ~50% of your defined sound since it is played twice. This works surprisingly well when compared to a single sound with playSoundAt(), no significant distortion.
Disclaimer: We may get a nice sound object from AH making this all for naught. There may be other ways, better ways, there usually is. Nevertheless, this system is working well for me (could be bugged, of course). You can implement these sound doors any way you want, my system is here for example.
- 1. Can't be stopped
2. Disappear when player loads savegame
3. Disappear when party changes level
4. Audible on every level in square they're played
Code: Select all
cloneObject{
name = "sound_wind",
baseObject = "dungeon_wall_grating",
--class = "Door",
model = "mod_assets/models/vertex.fbx",
openSound = "silence",
closeSound = "silence",
lockSound = "wind",
openVelocity = 100,
--closeVelocity = 0,
--closeAcceleration = -10,
--sparse = true,
--placement = "wall",
editorIcon = 88,
}
Note the following:
- openSound & closeSound are silent, you need your own silent .wav because you can't have the standard door sounds playing.
- You must make the door model disappear. There are several ways to do this, I use a null model (very small), I leave that up to you.
- openVelocity must be set high. I use 100, a nice round number, it opens the door instantaneously.
- You define one "sound door" for every defined sound. Easy to do, 2 steps only: change the name and set the lockSound as your defined sound.
Code: Select all
function detectParty(obj)
if obj.level == party.level then
current = party.level
if notAtStart then
if not findEntity("loopy") then
spawn("fx", 2, 25, 9, 0, "loopy"):setLight(0, 0, 0, 0, 0, 1800000, false)
restoreSound(current)
end
end
notAtStart = true
if previous and current ~= previous then
restoreSound(current)
end
previous = current
end
end
Note the following:
- The if not findEntity("loopy") section is the check for a loaded savegame, again, covered in this thread.
- Current & previous handle when the party changes level. This works well. In testing, I noticed that the level change registers before you arrive (e.g. midpoint down a pit) so there is no interruption in sound as they are restored before you arrive.
- The check for if notAtStart and if previous are required to handle the special case of the player first starting the game. I don't want restoreSound() called at game start, notAtStart & previous will only be nil once, at start, the first time the function is called. They will have values from then on and their respective tests will pass for all following function calls thus calling restoreSound().
Code: Select all
function restoreSound(current)
local l, x, y
for sound, state in pairs(sounds[current]) do
if state == "on" then
l = findEntity(sound).level
x = findEntity(sound).x
y = findEntity(sound).y
for entity in entitiesAt(l, x, y) do
if entity.name == findEntity(sound).name then
entity:setDoorState("closed")
entity:open()
end
end
end
end
end
sounds = { [1] = { },
[2] = { },
[3] = { } }
function soundStateOn(id, l)
sounds[l][id] = "on"
end
function soundStateOff(id, l)
sounds[l][id] = "off"
end
function startSound(sound, l, x, y, f, id)
spawn(sound, l, x, y, f, id):open()
soundStateOn(id, l)
end
function stopSound(id)
soundStateOff(id, findEntity(id).level)
findEntity(id):destroy()
end
The sounds table stores references to all the sound doors. The example is a 3 level dungeon, you would add tables within the sounds table, one each for each level of your dungeon. Level 7 would be [7] = { },
startSound(sound, l, x, y, f, id) is called with the exact same parameters as spawn() (that's what it does, after all). Sound is the name of the sound door, not the defined sound.
stopSound(id) simply pass it the unique ID of the sound door.
Important: Door object produced sound emanates from the edge of the square (between squares). This doesn't change no matter where you place the door. You may want this, in which case, you're fine. However, if you want the sound to emanate "centrally" from the entire square you must do this:
Code: Select all
startSound("sound_wind", 1, 27, 4, 0, "sw_1_27_4_0")
startSound("sound_wind", 1, 27, 4, 2, "sw_1_27_4_2")
Disclaimer: We may get a nice sound object from AH making this all for naught. There may be other ways, better ways, there usually is. Nevertheless, this system is working well for me (could be bugged, of course). You can implement these sound doors any way you want, my system is here for example.