diff --git a/src/s_advsound.cpp b/src/s_advsound.cpp index 14742f55d..aa9de0039 100644 --- a/src/s_advsound.cpp +++ b/src/s_advsound.cpp @@ -1912,6 +1912,12 @@ private: IMPLEMENT_CLASS (AAmbientSound) +//========================================================================== +// +// AmbientSound :: Serialize +// +//========================================================================== + void AAmbientSound::Serialize (FArchive &arc) { Super::Serialize (arc); @@ -1948,6 +1954,11 @@ void AAmbientSound::Serialize (FArchive &arc) } } +//========================================================================== +// +// AmbientSound :: Tick +// +//========================================================================== void AAmbientSound::Tick () { @@ -1966,7 +1977,24 @@ void AAmbientSound::Tick () if (ambient->sound[0]) { - S_Sound(this, CHAN_BODY | loop, ambient->sound, ambient->volume, ambient->attenuation); + // The second argumens scales the ambient sound's volume. + // 0 and 128 are normal volume. The maximum volume level + // possible is always 1. + float volscale = args[1] == 0 ? 1 : args[1] / 128.f; + float usevol = clamp(ambient->volume * volscale, 0.f, 1.f); + + // The third argument is the minimum distance for audible fading, and + // the fourth argument is the maximum distance for audibility. Setting + // either of these to 0 or setting min distance > max distance will + // use the standard rolloff. + if ((args[2] | args[3]) == 0 || args[2] > args[3]) + { + S_Sound(this, CHAN_BODY | loop, ambient->sound, usevol, ambient->attenuation); + } + else + { + S_SoundMinMaxDist(this, CHAN_BODY | loop, ambient->sound, usevol, float(args[2]), float(args[3])); + } if (!loop) { SetTicker (ambient); @@ -1982,6 +2010,11 @@ void AAmbientSound::Tick () } } +//========================================================================== +// +// AmbientSound :: SetTicker +// +//========================================================================== void AAmbientSound::SetTicker (struct AmbientSound *ambient) { @@ -2001,12 +2034,26 @@ void AAmbientSound::SetTicker (struct AmbientSound *ambient) } } +//========================================================================== +// +// AmbientSound :: BeginPlay +// +//========================================================================== + void AAmbientSound::BeginPlay () { Super::BeginPlay (); Activate (NULL); } +//========================================================================== +// +// AmbientSound :: Activate +// +// Starts playing a sound (or does nothing of the sound is already playing). +// +//========================================================================== + void AAmbientSound::Activate (AActor *activator) { Super::Activate (activator); @@ -2040,6 +2087,15 @@ void AAmbientSound::Activate (AActor *activator) } } +//========================================================================== +// +// AmbientSound :: Deactivate +// +// Stops playing CONTINUOUS sounds immediately. Also prevents further +// occurrences of repeated sounds. +// +//========================================================================== + void AAmbientSound::Deactivate (AActor *activator) { Super::Deactivate (activator); diff --git a/src/s_sound.cpp b/src/s_sound.cpp index 48f5e9e9d..f309499df 100644 --- a/src/s_sound.cpp +++ b/src/s_sound.cpp @@ -108,7 +108,7 @@ static void CalcPosVel(int type, const AActor *actor, const sector_t *sector, co static void CalcSectorSoundOrg(const sector_t *sec, int channum, fixed_t *x, fixed_t *y, fixed_t *z); static void CalcPolyobjSoundOrg(const FPolyObj *poly, fixed_t *x, fixed_t *y, fixed_t *z); static FSoundChan *S_StartSound(AActor *mover, const sector_t *sec, const FPolyObj *poly, - const FVector3 *pt, int channel, FSoundID sound_id, float volume, float attenuation); + const FVector3 *pt, int channel, FSoundID sound_id, float volume, float attenuation, FRolloffInfo *rolloff); static void S_SetListener(SoundListener &listener, AActor *listenactor); // PRIVATE DATA DEFINITIONS ------------------------------------------------ @@ -808,7 +808,8 @@ static void CalcPolyobjSoundOrg(const FPolyObj *poly, fixed_t *x, fixed_t *y, fi //========================================================================== static FSoundChan *S_StartSound(AActor *actor, const sector_t *sec, const FPolyObj *poly, - const FVector3 *pt, int channel, FSoundID sound_id, float volume, float attenuation) + const FVector3 *pt, int channel, FSoundID sound_id, float volume, float attenuation, + FRolloffInfo *forcedrolloff=NULL) { sfxinfo_t *sfx; int chanflags; @@ -894,7 +895,10 @@ static FSoundChan *S_StartSound(AActor *actor, const sector_t *sec, const FPolyO near_limit = S_sfx[sound_id].NearLimit; limit_range = S_sfx[sound_id].LimitRange; } - if (rolloff->MinDistance == 0) rolloff = &S_sfx[sound_id].Rolloff; + if (rolloff->MinDistance == 0) + { + rolloff = &S_sfx[sound_id].Rolloff; + } } else { @@ -904,13 +908,25 @@ static FSoundChan *S_StartSound(AActor *actor, const sector_t *sec, const FPolyO near_limit = S_sfx[sound_id].NearLimit; limit_range = S_sfx[sound_id].LimitRange; } - if (rolloff->MinDistance == 0) rolloff = &S_sfx[sound_id].Rolloff; + if (rolloff->MinDistance == 0) + { + rolloff = &S_sfx[sound_id].Rolloff; + } } sfx = &S_sfx[sound_id]; } - // If no valid rolloff was set use the global default - if (rolloff->MinDistance == 0) rolloff = &S_Rolloff; + // The passed rolloff overrides any sound-specific rolloff. + if (forcedrolloff != NULL && forcedrolloff->MinDistance != 0) + { + rolloff = forcedrolloff; + } + + // If no valid rolloff was set, use the global default. + if (rolloff->MinDistance == 0) + { + rolloff = &S_Rolloff; + } // If this is a singular sound, don't play it if it's already playing. if (sfx->bSingular && S_CheckSingular(sound_id)) @@ -1180,6 +1196,27 @@ void S_Sound (AActor *ent, int channel, FSoundID sound_id, float volume, float a S_StartSound (ent, NULL, NULL, NULL, channel, sound_id, volume, attenuation); } +//========================================================================== +// +// S_SoundMinMaxDist - An actor is source +// +// Attenuation is specified as min and max distances, rather than a scalar. +// +//========================================================================== + +void S_SoundMinMaxDist(AActor *ent, int channel, FSoundID sound_id, float volume, float mindist, float maxdist) +{ + if (ent == NULL || ent->Sector->Flags & SECF_SILENT) + return; + + FRolloffInfo rolloff; + + rolloff.RolloffType = ROLLOFF_Doom; + rolloff.MinDistance = mindist; + rolloff.MaxDistance = maxdist; + S_StartSound(ent, NULL, NULL, NULL, channel, sound_id, volume, 1, &rolloff); +} + //========================================================================== // // S_Sound - A polyobject is source diff --git a/src/s_sound.h b/src/s_sound.h index 4dbf52aac..9ba10ac73 100644 --- a/src/s_sound.h +++ b/src/s_sound.h @@ -218,6 +218,7 @@ void S_CacheSound (sfxinfo_t *sfx); // Start sound for thing at void S_Sound (int channel, FSoundID sfxid, float volume, float attenuation); void S_Sound (AActor *ent, int channel, FSoundID sfxid, float volume, float attenuation); +void S_SoundMinMaxDist (AActor *ent, int channel, FSoundID sfxid, float volume, float mindist, float maxdist); void S_Sound (const FPolyObj *poly, int channel, FSoundID sfxid, float volume, float attenuation); void S_Sound (const sector_t *sec, int channel, FSoundID sfxid, float volume, float attenuation); void S_Sound (fixed_t x, fixed_t y, fixed_t z, int channel, FSoundID sfxid, float volume, float attenuation);