I would like to introduce a custom sound during resting but I am not able to do it…
How can I add it?
Thanks a lot
I would like to introduce a custom sound during resting but I am not able to do it…
How can I add it?
Thanks a lot
This is quite easy. Use OnPlayerRest
event handle script. It tells when the rest begins and when it ends (or interrupts).
Depending on whether you want a one-shot or a looping sound you may need a pseudo-heartbeat.
EDIT BELOW THIS LINE
I totally forgot that PlaySound
is an action (i.e. creatures can’t play sounds when resting), which complicates things a bit. To fix that, you can:
// By NWShacker, 2020-12-06
// OnPlayerRest - plays drums every 1 second during rest.
// variable to connect PC to placeable
const string VAR = "my_rest_sound_maker";
// placeable ResRef
const string PLC = "plc_invisobj";
// sound to play
const string SOUND = "as_cv_drums1";
// sound play interval
const float DELAY = 1.0;
void play()
{
PlaySound(SOUND);
// debug - delete:
SpeakString("Playing " + SOUND);
DelayCommand(DELAY, play());
}
void main()
{
object oPC = GetLastPCRested();
object oSound;
if(GetLastRestEventType() == REST_EVENTTYPE_REST_STARTED)
{
oSound = CreateObject(OBJECT_TYPE_PLACEABLE, PLC, GetLocation(oPC));
// debug - delete:
AssignCommand(oPC, SpeakString("Creating " + GetName(oSound)));
SetLocalObject(oPC, VAR, oSound);
AssignCommand(oSound, play());
DestroyObject(oSound, 12.0);
}
else
{
oSound = GetLocalObject(oPC, VAR);
// debug - delete:
AssignCommand(oPC, SpeakString("Destroying " + GetName(oSound)));
DestroyObject(oSound);
DeleteLocalObject(oPC, VAR);
}
}
With this you can also play multiple sounds, add VFX, roll and stop the rest, etc.
Thanks a lot I will test tonight!
in nwn2 we call them “sound ninjas” :p
they spawn, play the sound, then get destroyed
but some modders just have a nearby placeable play the sound – eg. a/the campfire [ iff you know its valid ]
This made me realize that both approaches can be merged - just the existing object should not be destroyed.
So here’s another, more portable approach - everything packed into one function: call & forget at rest start. No local variables. It should also be proof against multiple concurrent calls.
@MillaJ: put a basic campfire in the area (tag Campfire
). If you rest near it, it will play fire sound. If you rest away from it (or if there is no campfire), you will hear chickens.
// nwsh_restsound.nss
// By NWShacker, 2020-12-07
// placeable ResRef
const string RESTSOUND_PLC = "plc_invisobj";
// placeable tag
const string RESTSOUND_TAG = "SOUND_NINJA_";
// initial delay
const float RESTSOUND_DELAY = 0.25;
// Plays sound sSound every fDelay seconds as long as oPC is resting.
// Leave oSound invalid to create temporary sound object at oPC location.
// If oSound is valid, it will play the sound and won't be destroyed.
void NWSH_PlaySoundDuringRest(object oPC, string sSound, float fDelay=1.0, object oSound=OBJECT_INVALID)
{
int iSound;
if(!GetIsPC(oPC))
{
return;
}
else if(GetCurrentAction(oPC) != ACTION_REST)
{
if(GetTag(oSound) == RESTSOUND_TAG + ObjectToString(oPC))
{
DestroyObject(oSound);
}
}
else if(!GetIsObjectValid(oSound))
{
while(GetIsObjectValid(oSound =
GetObjectByTag(RESTSOUND_TAG + ObjectToString(oPC), iSound++)))
{
DestroyObject(oSound);
}
oSound = CreateObject(OBJECT_TYPE_PLACEABLE, RESTSOUND_PLC,
GetLocation(oPC), FALSE, RESTSOUND_TAG + ObjectToString(oPC));
AssignCommand(oSound, DelayCommand(RESTSOUND_DELAY,
NWSH_PlaySoundDuringRest(oPC, sSound, fDelay, oSound)));
DestroyObject(oSound, 12.0);
}
else
{
AssignCommand(oSound, PlaySound(sSound));
AssignCommand(oSound, DelayCommand(fDelay,
NWSH_PlaySoundDuringRest(oPC, sSound, fDelay, oSound)));
}
}
// OnPlayerRest
#include "nwsh_restsound"
void main()
{
object oPC = GetLastPCRested();
object oSound = GetNearestObjectByTag("Campfire", oPC);
if(GetLastRestEventType() == REST_EVENTTYPE_REST_STARTED)
{
// just for test - if PC is close to a campfire,
// it will play campfire sound every 6 seconds,
// otherwise a temporary object will play chickens
if(GetIsObjectValid(oSound) && GetDistanceBetween(oPC, oSound) < 5.0)
{
NWSH_PlaySoundDuringRest(oPC, "al_cv_firecamp1", 6.0, oSound);
}
else
{
NWSH_PlaySoundDuringRest(oPC, "as_an_chickens1", 2.0);
}
}
}
There is an initial delay of 0.25 (RESTSOUND_DELAY
) needed for the temporary placeable to settle in the area - it cannot play the sound right when it spawns, which would lead to skipping of one sound loop iteration. 0.25s seems to work for me.
Works great!! Thanks a lot!