From 0594b7d1a0f42c438598deb27e4dd5633943f221 Mon Sep 17 00:00:00 2001 From: elsid Date: Sun, 28 Jun 2020 13:12:42 +0200 Subject: [PATCH] Put logic for the next region sound selection into a separate class --- apps/openmw/CMakeLists.txt | 2 +- apps/openmw/mwsound/regionsoundselector.cpp | 71 +++++++++++++++++++++ apps/openmw/mwsound/regionsoundselector.hpp | 29 +++++++++ apps/openmw/mwsound/soundmanagerimp.cpp | 45 +------------ apps/openmw/mwsound/soundmanagerimp.hpp | 4 ++ 5 files changed, 108 insertions(+), 43 deletions(-) create mode 100644 apps/openmw/mwsound/regionsoundselector.cpp create mode 100644 apps/openmw/mwsound/regionsoundselector.hpp diff --git a/apps/openmw/CMakeLists.txt b/apps/openmw/CMakeLists.txt index a9f3d24e2..8631834c9 100644 --- a/apps/openmw/CMakeLists.txt +++ b/apps/openmw/CMakeLists.txt @@ -57,7 +57,7 @@ add_openmw_dir (mwscript add_openmw_dir (mwsound soundmanagerimp openal_output ffmpeg_decoder sound sound_buffer sound_decoder sound_output - loudness movieaudiofactory alext efx efx-presets + loudness movieaudiofactory alext efx efx-presets regionsoundselector ) add_openmw_dir (mwworld diff --git a/apps/openmw/mwsound/regionsoundselector.cpp b/apps/openmw/mwsound/regionsoundselector.cpp new file mode 100644 index 000000000..ac5f66721 --- /dev/null +++ b/apps/openmw/mwsound/regionsoundselector.cpp @@ -0,0 +1,71 @@ +#include "regionsoundselector.hpp" + +#include + +#include +#include + +#include "../mwbase/world.hpp" +#include "../mwworld/esmstore.hpp" + +namespace MWSound +{ + namespace + { + int addChance(int result, const ESM::Region::SoundRef &v) + { + return result + v.mChance; + } + } + + boost::optional RegionSoundSelector::getNextRandom(float duration, const std::string& regionName, + const MWBase::World& world) + { + mTimePassed += duration; + + if (mTimePassed < mTimeToNextEnvSound) + return {}; + + const float a = Misc::Rng::rollClosedProbability(); + // NOTE: We should use the "Minimum Time Between Environmental Sounds" and + // "Maximum Time Between Environmental Sounds" fallback settings here. + mTimeToNextEnvSound = 5.0f * a + 15.0f * (1.0f - a); + mTimePassed = 0; + + if (mLastRegionName != regionName) + { + mLastRegionName = regionName; + mSumChance = 0; + } + + const ESM::Region* const region = world.getStore().get().search(mLastRegionName); + + if (region == nullptr) + return {}; + + if (mSumChance == 0) + { + mSumChance = std::accumulate(region->mSoundList.begin(), region->mSoundList.end(), 0, addChance); + if (mSumChance == 0) + return {}; + } + + const int r = Misc::Rng::rollDice(mSumChance); + int pos = 0; + + const auto isSelected = [&] (const ESM::Region::SoundRef& sound) + { + if (r - pos < sound.mChance) + return true; + pos += sound.mChance; + return false; + }; + + const auto it = std::find_if(region->mSoundList.begin(), region->mSoundList.end(), isSelected); + + if (it == region->mSoundList.end()) + return {}; + + return it->mSound; + } +} diff --git a/apps/openmw/mwsound/regionsoundselector.hpp b/apps/openmw/mwsound/regionsoundselector.hpp new file mode 100644 index 000000000..00a2d5ca8 --- /dev/null +++ b/apps/openmw/mwsound/regionsoundselector.hpp @@ -0,0 +1,29 @@ +#ifndef GAME_SOUND_REGIONSOUNDSELECTOR_H +#define GAME_SOUND_REGIONSOUNDSELECTOR_H + +#include + +#include + +namespace MWBase +{ + class World; +} + +namespace MWSound +{ + class RegionSoundSelector + { + public: + boost::optional getNextRandom(float duration, const std::string& regionName, + const MWBase::World& world); + + private: + float mTimeToNextEnvSound = 0.0f; + int mSumChance = 0; + std::string mLastRegionName; + float mTimePassed = 0.0; + }; +} + +#endif diff --git a/apps/openmw/mwsound/soundmanagerimp.cpp b/apps/openmw/mwsound/soundmanagerimp.cpp index 162c176e6..36dbad1d5 100644 --- a/apps/openmw/mwsound/soundmanagerimp.cpp +++ b/apps/openmw/mwsound/soundmanagerimp.cpp @@ -907,54 +907,15 @@ namespace MWSound void SoundManager::updateRegionSound(float duration) { - static float sTimeToNextEnvSound = 0.0f; - static int total = 0; - static std::string regionName = ""; - static float sTimePassed = 0.0; MWBase::World *world = MWBase::Environment::get().getWorld(); const MWWorld::ConstPtr player = world->getPlayerPtr(); const ESM::Cell *cell = player.getCell()->getCell(); - sTimePassed += duration; - if(!cell->isExterior() || sTimePassed < sTimeToNextEnvSound) + if (!cell->isExterior()) return; - float a = Misc::Rng::rollClosedProbability(); - // NOTE: We should use the "Minimum Time Between Environmental Sounds" and - // "Maximum Time Between Environmental Sounds" fallback settings here. - sTimeToNextEnvSound = 5.0f*a + 15.0f*(1.0f-a); - sTimePassed = 0; - - if(regionName != cell->mRegion) - { - regionName = cell->mRegion; - total = 0; - } - - const ESM::Region *regn = world->getStore().get().search(regionName); - if(regn == nullptr) - return; - - if(total == 0) - { - for(const ESM::Region::SoundRef &sndref : regn->mSoundList) - total += (int)sndref.mChance; - if(total == 0) - return; - } - - int r = Misc::Rng::rollDice(total); - int pos = 0; - - for(const ESM::Region::SoundRef &sndref : regn->mSoundList) - { - if(r - pos < sndref.mChance) - { - playSound(sndref.mSound, 1.0f, 1.0f); - break; - } - pos += sndref.mChance; - } + if (const auto next = mRegionSoundSelector.getNextRandom(duration, cell->mRegion, *world)) + playSound(*next, 1.0f, 1.0f); } void SoundManager::updateWaterSound(float /*duration*/) diff --git a/apps/openmw/mwsound/soundmanagerimp.hpp b/apps/openmw/mwsound/soundmanagerimp.hpp index 55588d06f..3974bf479 100644 --- a/apps/openmw/mwsound/soundmanagerimp.hpp +++ b/apps/openmw/mwsound/soundmanagerimp.hpp @@ -14,6 +14,8 @@ #include "../mwbase/soundmanager.hpp" +#include "regionsoundselector.hpp" + namespace VFS { class Manager; @@ -115,6 +117,8 @@ namespace MWSound std::string mNextMusic; bool mPlaybackPaused; + RegionSoundSelector mRegionSoundSelector; + Sound_Buffer *insertSound(const std::string &soundId, const ESM::Sound *sound); Sound_Buffer *lookupSound(const std::string &soundId) const;