Jump to content

[SOLVED] How to make a sound/short song play while character is working


Recommended Posts

So I know my last issues didn't get solved, but I'm hoping with everything I have that I can get some help with doing this as it is the actual final obstacle before I can release one of my characters for limited playtesting.

So my character has a perk where he functions basically like a One-man Band when doing work, and I want a quiet little song to play while he's working to signal that the effect is active. It would play overtop the work music, hence being quiet.

I know that I'd need to use FMOD and map it under my ASSETS, but how would I go about coding that in (and even setting up the FMOD project given it's not a character voice)?

It's such a small feature but I really need to add it because otherwise the perk won't make any sense and my character won't be complete. Thank you for any help!

Edited by Garamonde
Link to comment
Share on other sites

I only did it once and it was some time ago so I'm not sure if this is correct, but you just make your sound file, names are whatever you want.

Then you load it under Assets.

Let's say this is your folder structure under FMOD:

image.png.cb340e55e84fa90807720b6ba0d6cf19.png

and it's saved under the name structureprefab.fev and structureprefab.fsb in the sound folder.

To play the sound event1, you would need to call

inst.SoundEmitter:PlaySound("structureprefab/structure/event1")

So first the name of the file it's saved under, then the folder in FMOD and then the name of the event.

Now to the part where you want to play it when doing work:

You can either listen for the event "working" and play the sound or you hook into the corresponding stategraph functions so that they play this sound while digging,hammering,...

  • Big Ups 1
  • GL Happy 1
Link to comment
Share on other sites

THANK YOU SO MUCH you don't know how much this means to me. I do have one slight problem though?

While I managed to write the function and get it to work by myself (which I am super proud of), the song starts over for every single chop, mine, strike from a hammer, etc., and it also continues to play indefinitely, even on the map and pause screens. I would like it to keep playing up until a few seconds after working has stopped, and for the sound to be killed when the game is paused, naturally. Any ideas on how to do that? Here's my current code by the way (very simple because I am still a noob coder):

local function OnWorked(inst, data)
	inst:ListenForEvent("working", OnWorked)
	inst.SoundEmitter:PlaySound("soundstudio/hungerbuff/song")
end

Thank you so much again!! :love_heart:

  • Like 1
Link to comment
Share on other sites

That's good to hear!

I think the problem is that you add the ListenForEvent in the function that is listening to the event.

local function OnWorked(inst, data)
	inst.SoundEmitter:PlaySound("soundstudio/hungerbuff/song")
end

--masterpostinit
inst:ListenForEvent("working", OnWorked)

It should look more like this in your file. The song should automatically stop to play if the file is finished.

If it still doesn't stop, you can do something like this:

local function OnWorked(inst, data)
	inst.SoundEmitter:PlaySound("soundstudio/hungerbuff/song","hungerbuffsong")
	inst:DoTaskInTime(2,function(inst)	--or whatever time you want it to stop
        inst.SoundEmitter:KillSound("hungerbuffsong")
    end)
end

--masterpostinit
inst:ListenForEvent("working", OnWorked)

 

  • Big Ups 1
  • GL Happy 1
Link to comment
Share on other sites

Hmm, the second block of code did not work, it caused a dedicated server error or crash/disconnect if I remember right. So, after a while of investigating the game's code and trying different things out, me and my friend have hit a bit of a wall. First, we tried to make it so my character's song kept playing as long as the player was working (and would also loop if the player was working for the entire duration of the song without letting that 4 second grace period run out), for up to 4 seconds of NOT working. Then it would stop. But now it's causing disconnects. Here is our current code:

local function OnWorked(inst, data)
    if inst.songkilltask ~= nil then -- If the sound is still going
        inst.songkilltask:Cancel() -- Stop our kill task
    else -- otherwise
        inst.SoundEmitter:PlaySound("soundstudio/hungerbuff/song", "hungerbuffsong") -- Start the sound
    end

    inst.songkilltask = inst:DoTaskInTime(4, function() -- Start the kill task
        inst.SoundEmitter:KillSound("hungerbuffsong")
    end)
end

I'd also like the song to fade out rather than stop abruptly after you stop working for the 4 seconds. Hopefully you can make sense of this! Sorry it's so confusing, lol.

Edited by Garamonde
Link to comment
Share on other sites

I had a look at my block of code and your current code and didn't get a crash upon using either, so a serverlog would help :)

You should also set inst.songkilltask = nil after using Cancel() on it, I don't think it will be nil after cancelling it.

You can check if your current song is playing by running inst.SoundEmitter:PlayingSound("hungerbuffsong") which returns a bool and you can set the volume of a song by running inst.SoundEmitter:SetVolume("hungerbuffsong",volume) to make the fade out part. Just run a task each frame that reduces the volume a bit each time to get a fading out effect when you want it to fade out.

I hope that helps and that I understood your problem correctly, if not let me know! :)

 

 

  • Like 1
  • Big Ups 1
Link to comment
Share on other sites

Hey, sorry this has been so much trouble! Also sorry for not directly using your code... Me and my friend have been trying different things and the result we came up with is this:

local function OnWorked(inst, data)
    inst.SoundEmitter:PlayingSound("hungerbuffsong") then -- If the sound is still going
        inst.songkilltask:Cancel() -- Stop our kill task
        inst.songkilltask = nil
    else -- otherwise
        inst.SoundEmitter:PlaySound("soundstudio/hungerbuff/song", "hungerbuffsong") -- Start the sound
    end

    inst.songkilltask = inst:DoTaskInTime(4, function() -- Start the kill task
    inst.SoundEmitter:SetParameter("hungerbuffsong", "intensity", 0)
    end)
end

As a result, I got this error:

[string "scripts/mainfunctions.lua"]:157: Error loading file prefabs/kk
[string "../mods/K_K/scripts/prefabs/kk.lua"]:193: unexpected symbol near 'then'

Though the funny thing? When I added and "if" to the beginning of the "then" line, it made the game work but the song wouldn't stop playing.

Now, I know this is going to sound noobish as all heck but... How do I set up multiple periodic tables to do what you initially suggested and what volume value should I start with? Sorry, I'm still learning and I absolutely suck at writing my own code (just because I'm still trying to understand how the game's code and LUA as a whole works), lol.

Thank you so much again! We're so close to done!

Link to comment
Share on other sites

No worries, it's always best to try it yourselves, this way you also learn a lot!

If you use else, you also need to use if. This is just the way it's used in every programming language (I think) :D You need the conditional to have your different cases.

The song never stopped because you never killed it.

To be honest, not sure which volume is the start, I think it's 1.

local function ReduceVolume(inst,volume)
    local new_volume = volume-FRAMES --new volume is old volume - FRAMES ( which is 1/30)
    inst.SoundEmitter:SetVolume("hungerbuffsong",new_volume) --set the new volume
    if volume < 0.1 then --if the volume is smaller than 0,1, kill the sound, you can also choose another value, I think with 0.1 it's not heard anymore
        inst.SoundEmitter:KillSound("hungerbuffsong")
    else
        inst:DoTaskInTime(2*FRAMES,ReduceVolume,new_volume) --else redo that in 2 frames, 
    		--if you want to have a faster reducing of the volume, change the time to 1 FRAMES or reduce the volume faster
    end
end


local function OnWorked(inst, data)
    if inst.SoundEmitter:PlayingSound("hungerbuffsong") then -- If the sound is still going
        inst.songkilltask:Cancel() -- Stop our kill task
        inst.songkilltask = nil
    else -- otherwise
        inst.SoundEmitter:PlaySound("soundstudio/hungerbuff/song", "hungerbuffsong") -- Start the sound
    end

    inst.songkilltask = inst:DoTaskInTime(3, function() -- Start the kill task
        ReduceVolume(inst,1) --start the periodic task that reduces the volume each 2 frames, start with volume = 1
    end)
end

This should be working for your case, the volume will get lower after some time. I hope that works for you, if not let me know! :)

Edited by Monti18
  • Thanks 1
  • Big Ups 1
Link to comment
Share on other sites

Update: This issue kind of ended up intertwining with the pig followers issues, so the pig issue is solved. But unfortunately the song still starts over if you begin working immediately after the song starts to fade out/end. Otherwise, works like a charm.

EDIT: Forgot to actually include the new prefab.

kk.lua

Edited by Garamonde
Link to comment
Share on other sites

Sorry for the bump post but I added the newest version of the prefab file. Technically my character's ready for pre-release playtesting, but I would like to get this small issue fixed before then, if possible. Thank you!

kk.lua

Edited by Garamonde
Link to comment
Share on other sites

On 4/15/2022 at 12:53 AM, Garamonde said:

-t- helped me with this issue and now K_K's basically done! Thank you so much to everyone who helped me!

Nice, sorry for not answering sooner, had too much on my plate :D

But good that you were able to get it resolved :)

  • Thanks 1
Link to comment
Share on other sites

Create an account or sign in to comment

You need to be a member in order to leave a comment

Create an account

Sign up for a new account in our community. It's easy!

Register a new account

Sign in

Already have an account? Sign in here.

Sign In Now
 Share

×
  • Create New...