- 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.