From ed31a0354ab08b9d051744413026a2012692972c Mon Sep 17 00:00:00 2001 From: Alexei Kotov Date: Sat, 6 Jan 2024 18:35:51 +0300 Subject: [PATCH] Support playing ambient and rain weather SFX at the same time (bug #7761) --- CHANGELOG.md | 1 + apps/openmw/mwrender/skyutil.hpp | 1 + apps/openmw/mwworld/weather.cpp | 59 +++++++++++++++++++++++--------- apps/openmw/mwworld/weather.hpp | 10 ++++-- 4 files changed, 52 insertions(+), 19 deletions(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index 0dbd4e463f..411ff28c2f 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -122,6 +122,7 @@ Bug #7724: Guards don't help vs werewolves Bug #7742: Governing attribute training limit should use the modified attribute Bug #7758: Water walking is not taken into account to compute path cost on the water + Bug #7761: Rain and ambient loop sounds are mutually exclusive Feature #2566: Handle NAM9 records for manual cell references Feature #3537: Shader-based water ripples Feature #5173: Support for NiFogProperty diff --git a/apps/openmw/mwrender/skyutil.hpp b/apps/openmw/mwrender/skyutil.hpp index 1018724595..da038e6c58 100644 --- a/apps/openmw/mwrender/skyutil.hpp +++ b/apps/openmw/mwrender/skyutil.hpp @@ -65,6 +65,7 @@ namespace MWRender bool mIsStorm; ESM::RefId mAmbientLoopSoundID; + ESM::RefId mRainLoopSoundID; float mAmbientSoundVolume; std::string mParticleEffect; diff --git a/apps/openmw/mwworld/weather.cpp b/apps/openmw/mwworld/weather.cpp index aa75730b40..2c9b80bc5f 100644 --- a/apps/openmw/mwworld/weather.cpp +++ b/apps/openmw/mwworld/weather.cpp @@ -195,21 +195,19 @@ namespace MWWorld mThunderSoundID[3] = ESM::RefId::stringRefId(Fallback::Map::getString("Weather_" + name + "_Thunder_Sound_ID_3")); - // TODO: support weathers that have both "Ambient Loop Sound ID" and "Rain Loop Sound ID", need to play both - // sounds at the same time. - if (!mRainEffect.empty()) // NOTE: in vanilla, the weathers with rain seem to be hardcoded; changing // Using_Precip has no effect { - mAmbientLoopSoundID + mRainLoopSoundID = ESM::RefId::stringRefId(Fallback::Map::getString("Weather_" + name + "_Rain_Loop_Sound_ID")); - if (mAmbientLoopSoundID.empty()) // default to "rain" if not set - mAmbientLoopSoundID = ESM::RefId::stringRefId("rain"); + if (mRainLoopSoundID.empty()) // default to "rain" if not set + mRainLoopSoundID = ESM::RefId::stringRefId("rain"); + else if (mRainLoopSoundID == "None") + mRainLoopSoundID = ESM::RefId(); } - else - mAmbientLoopSoundID - = ESM::RefId::stringRefId(Fallback::Map::getString("Weather_" + name + "_Ambient_Loop_Sound_ID")); + mAmbientLoopSoundID + = ESM::RefId::stringRefId(Fallback::Map::getString("Weather_" + name + "_Ambient_Loop_Sound_ID")); if (mAmbientLoopSoundID == "None") mAmbientLoopSoundID = ESM::RefId(); } @@ -552,8 +550,6 @@ namespace MWWorld , mQueuedWeather(0) , mRegions() , mResult() - , mAmbientSound(nullptr) - , mPlayingSoundID() { mTimeSettings.mNightStart = mSunsetTime + mSunsetDuration; mTimeSettings.mNightEnd = mSunriseTime; @@ -794,24 +790,52 @@ namespace MWWorld mRendering.getSkyManager()->setWeather(mResult); // Play sounds - if (mPlayingSoundID != mResult.mAmbientLoopSoundID) + if (mPlayingAmbientSoundID != mResult.mAmbientLoopSoundID) { - stopSounds(); + if (mAmbientSound) + { + MWBase::Environment::get().getSoundManager()->stopSound(mAmbientSound); + mAmbientSound = nullptr; + } if (!mResult.mAmbientLoopSoundID.empty()) mAmbientSound = MWBase::Environment::get().getSoundManager()->playSound(mResult.mAmbientLoopSoundID, mResult.mAmbientSoundVolume, 1.0, MWSound::Type::Sfx, MWSound::PlayMode::Loop); - mPlayingSoundID = mResult.mAmbientLoopSoundID; + mPlayingAmbientSoundID = mResult.mAmbientLoopSoundID; } else if (mAmbientSound) mAmbientSound->setVolume(mResult.mAmbientSoundVolume); + + if (mPlayingRainSoundID != mResult.mRainLoopSoundID) + { + if (mRainSound) + { + MWBase::Environment::get().getSoundManager()->stopSound(mRainSound); + mRainSound = nullptr; + } + if (!mResult.mRainLoopSoundID.empty()) + mRainSound = MWBase::Environment::get().getSoundManager()->playSound(mResult.mRainLoopSoundID, + mResult.mAmbientSoundVolume, 1.0, MWSound::Type::Sfx, MWSound::PlayMode::Loop); + mPlayingRainSoundID = mResult.mRainLoopSoundID; + } + else if (mRainSound) + mRainSound->setVolume(mResult.mAmbientSoundVolume); } void WeatherManager::stopSounds() { if (mAmbientSound) + { MWBase::Environment::get().getSoundManager()->stopSound(mAmbientSound); - mAmbientSound = nullptr; - mPlayingSoundID = ESM::RefId(); + mAmbientSound = nullptr; + } + mPlayingAmbientSoundID = ESM::RefId(); + + if (mRainSound) + { + MWBase::Environment::get().getSoundManager()->stopSound(mRainSound); + mRainSound = nullptr; + } + mPlayingRainSoundID = ESM::RefId(); } float WeatherManager::getWindSpeed() const @@ -1118,6 +1142,7 @@ namespace MWWorld mResult.mCloudSpeed = current.mCloudSpeed; mResult.mGlareView = current.mGlareView; mResult.mAmbientLoopSoundID = current.mAmbientLoopSoundID; + mResult.mRainLoopSoundID = current.mRainLoopSoundID; mResult.mAmbientSoundVolume = 1.f; mResult.mPrecipitationAlpha = 1.f; @@ -1237,6 +1262,7 @@ namespace MWWorld mResult.mAmbientSoundVolume = 1.f - factor / threshold; mResult.mPrecipitationAlpha = mResult.mAmbientSoundVolume; mResult.mAmbientLoopSoundID = current.mAmbientLoopSoundID; + mResult.mRainLoopSoundID = current.mRainLoopSoundID; mResult.mRainDiameter = current.mRainDiameter; mResult.mRainMinHeight = current.mRainMinHeight; mResult.mRainMaxHeight = current.mRainMaxHeight; @@ -1252,6 +1278,7 @@ namespace MWWorld mResult.mAmbientSoundVolume = (factor - threshold) / (1 - threshold); mResult.mPrecipitationAlpha = mResult.mAmbientSoundVolume; mResult.mAmbientLoopSoundID = other.mAmbientLoopSoundID; + mResult.mRainLoopSoundID = other.mRainLoopSoundID; mResult.mRainDiameter = other.mRainDiameter; mResult.mRainMinHeight = other.mRainMinHeight; diff --git a/apps/openmw/mwworld/weather.hpp b/apps/openmw/mwworld/weather.hpp index 65f926c096..327136a859 100644 --- a/apps/openmw/mwworld/weather.hpp +++ b/apps/openmw/mwworld/weather.hpp @@ -156,9 +156,11 @@ namespace MWWorld float FogOffset; } mDL; - // Sound effect + // Sound effects // This is used for Blight, Ashstorm and Blizzard (Bloodmoon) ESM::RefId mAmbientLoopSoundID; + // This is used for Rain and Thunderstorm + ESM::RefId mRainLoopSoundID; // Is this an ash storm / blight storm? If so, the following will happen: // - The particles and clouds will be oriented so they appear to come from the Red Mountain. @@ -369,8 +371,10 @@ namespace MWWorld std::map mRegions; MWRender::WeatherResult mResult; - MWBase::Sound* mAmbientSound; - ESM::RefId mPlayingSoundID; + MWBase::Sound* mAmbientSound{ nullptr }; + ESM::RefId mPlayingAmbientSoundID; + MWBase::Sound* mRainSound{ nullptr }; + ESM::RefId mPlayingRainSoundID; void addWeather( const std::string& name, float dlFactor, float dlOffset, const std::string& particleEffect = "");