mirror of
https://gitlab.com/OpenMW/openmw.git
synced 2025-02-24 09:39:51 +00:00
Merge pull request #2943 from elsid/sound_update_region
Put logic for the next region sound selection into a separate class
This commit is contained in:
commit
5b7f37cf46
@ -57,7 +57,7 @@ add_openmw_dir (mwscript
|
|||||||
|
|
||||||
add_openmw_dir (mwsound
|
add_openmw_dir (mwsound
|
||||||
soundmanagerimp openal_output ffmpeg_decoder sound sound_buffer sound_decoder sound_output
|
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
|
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)
|
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();
|
MWBase::World *world = MWBase::Environment::get().getWorld();
|
||||||
const MWWorld::ConstPtr player = world->getPlayerPtr();
|
const MWWorld::ConstPtr player = world->getPlayerPtr();
|
||||||
const ESM::Cell *cell = player.getCell()->getCell();
|
const ESM::Cell *cell = player.getCell()->getCell();
|
||||||
|
|
||||||
sTimePassed += duration;
|
if (!cell->isExterior())
|
||||||
if(!cell->isExterior() || sTimePassed < sTimeToNextEnvSound)
|
|
||||||
return;
|
return;
|
||||||
|
|
||||||
float a = Misc::Rng::rollClosedProbability();
|
if (const auto next = mRegionSoundSelector.getNextRandom(duration, cell->mRegion, *world))
|
||||||
// NOTE: We should use the "Minimum Time Between Environmental Sounds" and
|
playSound(*next, 1.0f, 1.0f);
|
||||||
// "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;
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
void SoundManager::updateWaterSound(float /*duration*/)
|
void SoundManager::updateWaterSound(float /*duration*/)
|
||||||
|
@ -14,6 +14,8 @@
|
|||||||
|
|
||||||
#include "../mwbase/soundmanager.hpp"
|
#include "../mwbase/soundmanager.hpp"
|
||||||
|
|
||||||
|
#include "regionsoundselector.hpp"
|
||||||
|
|
||||||
namespace VFS
|
namespace VFS
|
||||||
{
|
{
|
||||||
class Manager;
|
class Manager;
|
||||||
@ -115,6 +117,8 @@ namespace MWSound
|
|||||||
std::string mNextMusic;
|
std::string mNextMusic;
|
||||||
bool mPlaybackPaused;
|
bool mPlaybackPaused;
|
||||||
|
|
||||||
|
RegionSoundSelector mRegionSoundSelector;
|
||||||
|
|
||||||
Sound_Buffer *insertSound(const std::string &soundId, const ESM::Sound *sound);
|
Sound_Buffer *insertSound(const std::string &soundId, const ESM::Sound *sound);
|
||||||
|
|
||||||
Sound_Buffer *lookupSound(const std::string &soundId) const;
|
Sound_Buffer *lookupSound(const std::string &soundId) const;
|
||||||
|
Loading…
x
Reference in New Issue
Block a user