mirror of
https://github.com/TES3MP/openmw-tes3mp.git
synced 2025-02-20 20:09:41 +00:00
Put logic for the next region sound selection into a separate class
This commit is contained in:
parent
829c26e904
commit
0594b7d1a0
5 changed files with 108 additions and 43 deletions
|
@ -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
|
||||
|
|
71
apps/openmw/mwsound/regionsoundselector.cpp
Normal file
71
apps/openmw/mwsound/regionsoundselector.cpp
Normal file
|
@ -0,0 +1,71 @@
|
|||
#include "regionsoundselector.hpp"
|
||||
|
||||
#include <components/misc/rng.hpp>
|
||||
|
||||
#include <algorithm>
|
||||
#include <numeric>
|
||||
|
||||
#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<std::string> 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<ESM::Region>().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;
|
||||
}
|
||||
}
|
29
apps/openmw/mwsound/regionsoundselector.hpp
Normal file
29
apps/openmw/mwsound/regionsoundselector.hpp
Normal file
|
@ -0,0 +1,29 @@
|
|||
#ifndef GAME_SOUND_REGIONSOUNDSELECTOR_H
|
||||
#define GAME_SOUND_REGIONSOUNDSELECTOR_H
|
||||
|
||||
#include <boost/optional.hpp>
|
||||
|
||||
#include <string>
|
||||
|
||||
namespace MWBase
|
||||
{
|
||||
class World;
|
||||
}
|
||||
|
||||
namespace MWSound
|
||||
{
|
||||
class RegionSoundSelector
|
||||
{
|
||||
public:
|
||||
boost::optional<std::string> 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
|
|
@ -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<ESM::Region>().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*/)
|
||||
|
|
|
@ -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;
|
||||
|
|
Loading…
Reference in a new issue