1
0
mirror of https://gitlab.com/OpenMW/openmw.git synced 2025-01-09 21:42:13 +00:00
OpenMW/apps/openmw/mwsound/regionsoundselector.cpp
2023-07-08 11:28:56 +02:00

77 lines
2.2 KiB
C++

#include "regionsoundselector.hpp"
#include <components/esm3/loadregn.hpp>
#include <components/fallback/fallback.hpp>
#include <components/misc/rng.hpp>
#include <algorithm>
#include <numeric>
#include "../mwbase/environment.hpp"
#include "../mwworld/esmstore.hpp"
namespace MWSound
{
namespace
{
int addChance(int result, const ESM::Region::SoundRef& v)
{
return result + v.mChance;
}
}
RegionSoundSelector::RegionSoundSelector()
: mMinTimeBetweenSounds(Fallback::Map::getFloat("Weather_Minimum_Time_Between_Environmental_Sounds"))
, mMaxTimeBetweenSounds(Fallback::Map::getFloat("Weather_Maximum_Time_Between_Environmental_Sounds"))
{
}
std::optional<ESM::RefId> RegionSoundSelector::getNextRandom(float duration, const ESM::RefId& regionName)
{
mTimePassed += duration;
if (mTimePassed < mTimeToNextEnvSound)
return {};
const float a = Misc::Rng::rollClosedProbability();
mTimeToNextEnvSound = mMinTimeBetweenSounds + (mMaxTimeBetweenSounds - mMinTimeBetweenSounds) * a;
mTimePassed = 0;
if (mLastRegionName != regionName)
{
mLastRegionName = regionName;
mSumChance = 0;
}
const ESM::Region* const region
= MWBase::Environment::get().getESMStore()->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(std::max(mSumChance, 100));
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;
}
}