2020-06-28 11:12:42 +00:00
|
|
|
#include "regionsoundselector.hpp"
|
|
|
|
|
2020-10-24 16:54:46 +00:00
|
|
|
#include <components/fallback/fallback.hpp>
|
2020-06-28 11:12:42 +00:00
|
|
|
#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;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2020-10-24 16:54:46 +00:00
|
|
|
RegionSoundSelector::RegionSoundSelector()
|
|
|
|
{
|
|
|
|
mMinTimeBetweenSounds = Fallback::Map::getFloat("Weather_Minimum_Time_Between_Environmental_Sounds");
|
|
|
|
mMaxTimeBetweenSounds = Fallback::Map::getFloat("Weather_Maximum_Time_Between_Environmental_Sounds");
|
|
|
|
}
|
|
|
|
|
2020-06-28 11:12:42 +00:00
|
|
|
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();
|
2020-10-24 16:54:46 +00:00
|
|
|
mTimeToNextEnvSound = mMinTimeBetweenSounds + (mMaxTimeBetweenSounds - mMinTimeBetweenSounds) * a;
|
2020-06-28 11:12:42 +00:00
|
|
|
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 {};
|
|
|
|
}
|
|
|
|
|
2020-10-24 16:54:46 +00:00
|
|
|
const int r = Misc::Rng::rollDice(std::max(mSumChance, 100));
|
2020-06-28 11:12:42 +00:00
|
|
|
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 {};
|
|
|
|
|
2020-10-24 16:54:46 +00:00
|
|
|
// TODO
|
|
|
|
// mTimeToNextEnvSound += soundDuration
|
|
|
|
|
2020-06-28 11:12:42 +00:00
|
|
|
return it->mSound;
|
|
|
|
}
|
|
|
|
}
|