Custom sounds for custom levers, buttons or other animations

Talk about creating Grimrock 1 levels and mods here. Warning: forum contains spoilers!
Post Reply
User avatar
Isaac
Posts: 3185
Joined: Fri Mar 02, 2012 10:02 pm

Custom sounds for custom levers, buttons or other animations

Post by Isaac »

It's probably not an issue in the upcoming LoG2, but I was asked about custom sounds (or removing the hard coded ones) in LoG1. So here is a method that works reasonably well, and allows for the use of custom sounds for buttons, levers, or custom versions of these.

As far as I know there is no way to prevent the default sounds from playing, and there are no lever or button hooks, (and so no easy way to detect the use of switches) ~that I am aware of.
So this is the way I devised.
________________
How to do it:
First, re-define the default Button and Lever sounds to a silent sound effect, placed in your "sounds" folder. Use the following script placed in the sounds.lua file in your project.

Code: Select all

	defineSound{
		name = "modButton",
		filename = "assets/samples/env/button_01.wav",
		loop = false,
		volume = 1,
		minDistance = 1,
		maxDistance = 10,
	}

	defineSound{
		name = "modLever",
		filename = "assets/samples/env/lever_01.wav",
		loop = false,
		volume = 1,
		minDistance = 1,
		maxDistance = 10,
	}

		defineSound{
		name = "button",
		filename = "mod_assets/sounds/silent.wav",
		loop = false,
		volume = 1,
		minDistance = 1,
		maxDistance = 10,
	}

	defineSound{
		name = "lever",
		filename = "mod_assets/sounds/silent.wav",
		loop = false,
		volume = 1,
		minDistance = 1,
		maxDistance = 10,
	}
This will make ALL buttons and levers silent unless connected to the sound effect script.

Next add the soundEffect script to the map: [note:updated script, now does the connections automatically.]
Place this code in a script object and name it 'customSounds'.

Code: Select all

	for l = 1, getMaxLevels() do
		for e in allEntities(l) do
			if e.class ~= nil and e.class == "Button" then
				e:addConnector('toggle', 'customSounds', 'soundEffect')
			elseif e.class ~= nil and e.class == "Lever" then
				e:addConnector('any', 'customSounds', 'soundEffect')			
			end
		end
			print('Sound connections added to all buttons and levers!')
	end

function soundEffect(caller)
	if caller and string.match(caller.id, 'SND_') then
		local sEffect = string.match(caller.id, "SND_"..".+")
		playSoundAt(string.sub(sEffect,5),caller.level,caller.x,caller.y)
	elseif caller and caller.class == "Button" then
		playSoundAt('modButton', caller.level,caller.x,caller.y)
	elseif caller and caller.class == "Lever" then
		playSoundAt('modLever', caller.level,caller.x,caller.y)
	end
end
When connected to this script, all regular buttons and levers sound like they would normally. The feature of this is that you can now define custom sounds (usually in the sounds.lua file) and have any button or lever play that sound when used; and you do this by appending the capital letters 'SND' and then the name of the sound effect to the object.id.

In a real map you would use the name of your custom sound, but for the example I will use the Ogre's scream with a button. You do this by making a button, and adding 'SND_' plus the name of the sound; in this case: 'ogre_rush_begin'... So you add 'SND_ogre_rush_begin' and you have a button named 'wall_button_1SNDogre_rush_begin'. This makes the button scream when pressed, just as it would play any defined sound, if you used that name instead.

On large multi-floor maps, you could use copies of the sound effect script per floor, to keep from needing to connect switches to a script on a different floor. Duplicated scripts will work just the same.

Video example.

UPDATED!:
I updated the script, and it will now auto-update all levers and buttons to have sounds ~without manual connections. I also changed the token from an Asterisk to the letters 'SND_', because it seems that anything but an alphanumeric character messes up calling the object in scripts.

Code: Select all

	for l = 1, getMaxLevels() do
		for e in allEntities(l) do
			if  e.class == "Button" then
				e:addConnector('toggle', 'customSounds', 'soundEffect')
			elseif  e.class == "Lever" then
				e:addConnector('any', 'customSounds', 'soundEffect')			
			end
		end
			print('Sound connections added to all buttons and levers!')
	end

function soundEffect(caller)
	if caller and string.match(caller.id, 'SND_') then
		local sEffect = string.match(caller.id, "SND_"..".+")
		playSoundAt(string.sub(sEffect,5),caller.level,caller.x,caller.y)
	elseif caller and caller.class == "Button" then
		playSoundAt('modButton', caller.level,caller.x,caller.y)
	elseif caller and caller.class == "Lever" then
		playSoundAt('modLever', caller.level,caller.x,caller.y)
	end
end
Last edited by Isaac on Tue Jan 28, 2014 4:12 am, edited 7 times in total.
chaoscommencer
Posts: 119
Joined: Sun Jan 05, 2014 7:48 pm

Re: Custom sounds for custom levers, buttons or other animat

Post by chaoscommencer »

Neat trick. Germanny could probably use this method for his wheel (custom lever). Good timing on announcing this one. Didn't know the original sound would still be played.
Working on a dungeon that displays a massive collection of assets while sorting them into convenient reusable plugin format (concept from some of leki's mods). Will contribute some of my own models as well eventually and follow that with custom dungeon.
User avatar
Isaac
Posts: 3185
Joined: Fri Mar 02, 2012 10:02 pm

Re: Custom sounds for custom levers, buttons or other animat

Post by Isaac »

chaoscommencer wrote:Neat trick. Germanny could probably use this method for his wheel (custom lever). Good timing on announcing this one.
He's the one that asked. ;)
Didn't know the original sound would still be played.
The original sound always plays, unfortunately... So the script makes it a silent sound, and plays the custom sound along with it. In the case of regular buttons & levers (with no asterisk in the name; have to be careful on that), the 'custom' sound is the regular one from the game.
User avatar
AdrTru
Posts: 223
Joined: Sat Jan 19, 2013 10:10 pm
Location: Trutnov, Czech Republic

Re: Custom sounds for custom levers, buttons or other animat

Post by AdrTru »

Its very useful trick. Thak you much.
I made special button with special sound as scripted alcove, but this way is much better.
My LOG2 projects: virtual money, Forge recipes, liquid potions and
MultiAlcoveManager, Toolbox, Graphic text,
chaoscommencer
Posts: 119
Joined: Sun Jan 05, 2014 7:48 pm

Re: Custom sounds for custom levers, buttons or other animat

Post by chaoscommencer »

Ya I read the script. Clever work around man :)
Working on a dungeon that displays a massive collection of assets while sorting them into convenient reusable plugin format (concept from some of leki's mods). Will contribute some of my own models as well eventually and follow that with custom dungeon.
User avatar
germanny
Posts: 530
Joined: Sat Apr 07, 2012 10:52 pm
Location: Kiel, Germany

Re: Custom sounds for custom levers, buttons or other animat

Post by germanny »

Nice work Isaac.
Where will we be without this great knowledge here :)
Dungeon Master Resource Pack worker and passionated Beer drinker
User avatar
germanny
Posts: 530
Joined: Sat Apr 07, 2012 10:52 pm
Location: Kiel, Germany

Re: Custom sounds for custom levers, buttons or other animat

Post by germanny »

Isaac, this is great! :geek:

My script: Twin Custom Sounds only for levers!

What i wanted to do: Set a custom sound to each lever state - activated or deactivated.

Wow - Got it to work with another solution, maybe a bit noobish, but seems to work fine.
Isaac, i borrowed your first part - set connectors for all levers^^

Then i had a problem with sound volume, if playSoundAt() is set to lever position by script.
The custom sounds play very silent if party stands facing the lever. Strange.. is it only in my dungeon? :?
*EDIT* This was an error with my speakers xD, not necessary! I commented those lines..

*obsolete
I solved this issue by getting the facing value from current lever and add or subtract 1 to
lever.x or lever.y for moving the soundplay-position.
Now custom sounds play nice with wanted soundvolume!
obsolete*

With this script one sound for each state (activated,deactivated) is added to all levers in the dungeon.
- It is necessary to define new sounds in 'sounds.lua' first. Must be *.wav, mono, 16bit.
- a silent sound for 'lever' needed, similar to Isaac´s (see his post)
- Create a custom lever or use a community one
- Simply place this script into your dungeon, thats all.
*EDIT* - Or Dl example file at end^^

If you want to add a new custom lever inside this script, simply add:
-------------------------------------------------------------------

Code: Select all

elseif lvNam == 'MyNewLeverName' and lvState == 'activated' then 
	playSoundAt("MyNewLeverActivSound", lvLevl, lvPosX, lvPosY)

elseif lvNam == 'MyNewLeverName' and lvState == 'deactivated' then 
	playSoundAt("MyNewLeverDeactivSound", lvLevl, lvPosX, lvPosY) 
-------------------------------------------------------------------

The new defined sounds in this example are: leverwheel_open, leverwheel_close, dm_lever_on, dm_lever_off.

Twin Custom Sounds only for levers!
-----------------------------------------------------------------

Code: Select all

-- Set connectors to all levers in dungeon (thx to Isaac!)

for l = 1, getMaxLevels() do
      for e in allEntities(l) do
         if  e.class == "Lever" then
            e:addConnector('any', 'leverSndSet', 'playLvSnd')
         end
         end
end

-- The function to play custom sounds

function playLvSnd(dmDungLev)

-- declare and set variables

lvState = dmDungLev:getLeverState()
lvLevl = dmDungLev.level
lvNam = dmDungLev.name
lvFac = dmDungLev.facing
lvPosX = dmDungLev.x
lvPosY = dmDungLev.y

-- Display lever states on screen - for debugging, remove this

hudPrint(lvState..", "..lvNam..", "..lvPosX..", "..lvPosY..", "..lvFac)

-- This section is defined as comment, not needed anymore, was: Correct the position for playSoundAt()

-- if lvFac == 0 then lvPosY = lvPosY-1      -- if lever Facing North
-- elseif lvFac == 1 then lvPosX = lvPosX+1  -- if lever Facing West
-- elseif lvFac == 2 then lvPosY = lvPosY+1  -- if lever Facing South
-- else lvPosX = lvPosX-1                    -- if lever Facing East
-- end

-- play sounds for each state

if lvState == 'activated' and lvNam == 'lever' then 
	playSoundAt("dm_lever_on", lvLevl, lvPosX, lvPosY)
	
elseif lvState == 'deactivated' and lvNam == 'lever' then 
	playSoundAt("dm_lever_off", lvLevl, lvPosX, lvPosY)
	
elseif lvNam == 'dm_lever_wheel' and lvState == 'activated' then 
	playSoundAt("leverwheel_open", lvLevl, lvPosX, lvPosY)

elseif lvNam == 'dm_lever_wheel' and lvState == 'deactivated' then 
	playSoundAt("leverwheel_close", lvLevl, lvPosX, lvPosY)

end	
end
---------------------------------------------------------------------

Tested the whole thing in editor over four levels, all seems well.
Didn´t do tests with compiled (exported) level - yet!

HERE is a ready to go solution for standard lever, add custom if desired^^
Twin Sounds for Levers
DL: grimrock_lever_twin_custom_sounds.7z

Can it be done simpler?
Last edited by germanny on Sat Feb 01, 2014 12:07 am, edited 1 time in total.
Dungeon Master Resource Pack worker and passionated Beer drinker
User avatar
germanny
Posts: 530
Joined: Sat Apr 07, 2012 10:52 pm
Location: Kiel, Germany

Re: Custom sounds for custom levers, buttons or other animat

Post by germanny »

Well.. haha.. :oops:
While testing the handwheel lever custom sounds, i didn´t hear normal sound if party stood in front of the lever.
So i made an addition to the twin sound script, sound shifting +1 field to avoid that.

In fact.. mmh :D - i have a receiver with 7.1 sound coupled to my pc, and today i noticed
that the front right speaker didn´t make any noise^^
It was a loose connection with the output cables, now it is fixed :evil:

Sorry for my mistake, this was the last thing i thought about.
The script works anyway, but my fix isn´t needed. I´ll patch that by deactivate the lines..
maybe one of you has sometimes a defective speaker, he can use this then xD

Corrected:
Ready to go solution twin sounds for standard lever, add custom levers+sounds if desired^^
Twin Sounds for Levers
DL: grimrock_lever_twin_custom_sounds.7z

..Damn^^
Dungeon Master Resource Pack worker and passionated Beer drinker
User avatar
Isaac
Posts: 3185
Joined: Fri Mar 02, 2012 10:02 pm

Re: Custom sounds for custom levers, buttons or other animat

Post by Isaac »

germanny wrote:...
Diarmuid suggested a nifty change to my original script; that being to define a block of objects by name, and assign the sounds that way.

Code: Select all

customSounds = {
["customButton_1"] = "buttonSound_1",
["customButton_2"] = "buttonSound_2",
["customLever_1"] = "leverSound_1",

-- Make this list as long as you want; include what you want.
-- Define each object that you include, and each sound to be played.
}

function soundEffect(caller)
 if customSounds[caller.name] then
    playSoundAt(customSounds[caller.name], caller.level, caller.x, caller.y);
  return;
 end
This works when you define each custom button or lever as a separate object. It's very effective, but the trade off is that you have to define those objects, and that you cannot change the sound by just changing the Id; you must erase and replace the object(s) on the map. The great benefit of it is that you don't have to micro-manage the object IDs, just place and forget, and it works with engine named assets ~because it ignores the object's unique id, and plays the sound based on what it is rather than what it's called.
Post Reply