Commit 3f28634d authored by dteviot's avatar dteviot

consolidate random number logic

Note, I suspect Rng::rollClosedProbability() is not needed.  The only difference between it and rollProbability() is that one time in 37k (on Windows), it will give an output of 1.0.
On some versions of Linux, the value of 1.0 will occur about 1 time in 4 billion.
parent cf077dcf
......@@ -10,6 +10,8 @@
#include <SDL.h>
#include <openengine/misc/rng.hpp>
#include <components/compiler/extensions0.hpp>
#include <components/bsa/resources.hpp>
......@@ -191,6 +193,7 @@ OMW::Engine::Engine(Files::ConfigurationManager& configurationManager)
, mExportFonts(false)
, mNewGame (false)
{
OEngine::Misc::Rng::init();
std::srand ( static_cast<unsigned int>(std::time(NULL)) );
MWClass::registerClasses();
......
#include "creature.hpp"
#include <openengine/misc/rng.hpp>
#include <components/esm/loadcrea.hpp>
#include <components/esm/creaturestate.hpp>
......@@ -249,7 +251,7 @@ namespace MWClass
float hitchance = MWMechanics::getHitChance(ptr, victim, ref->mBase->mData.mCombat);
if((::rand()/(RAND_MAX+1.0)) >= hitchance/100.0f)
if(OEngine::Misc::Rng::rollProbability() >= hitchance/100.0f)
{
victim.getClass().onHit(victim, 0.0f, false, MWWorld::Ptr(), ptr, false);
MWMechanics::reduceWeaponCondition(0.f, false, weapon, ptr);
......@@ -375,8 +377,7 @@ namespace MWClass
float agilityTerm = getCreatureStats(ptr).getAttribute(ESM::Attribute::Agility).getModified() * getGmst().fKnockDownMult->getFloat();
float knockdownTerm = getCreatureStats(ptr).getAttribute(ESM::Attribute::Agility).getModified()
* getGmst().iKnockDownOddsMult->getInt() * 0.01f + getGmst().iKnockDownOddsBase->getInt();
int roll = static_cast<int>(std::rand() / (static_cast<double> (RAND_MAX)+1) * 100); // [0, 99]
if (ishealth && agilityTerm <= damage && knockdownTerm <= roll)
if (ishealth && agilityTerm <= damage && knockdownTerm <= OEngine::Misc::Rng::roll0to99())
{
getCreatureStats(ptr).setKnockedDown(true);
......@@ -680,7 +681,7 @@ namespace MWClass
++sound;
}
if(!sounds.empty())
return sounds[(int)(rand()/(RAND_MAX+1.0)*sounds.size())]->mSound;
return sounds[OEngine::Misc::Rng::rollDice(sounds.size())]->mSound;
}
if (type == ESM::SoundGenerator::Land)
......
......@@ -5,6 +5,8 @@
#include <OgreSceneNode.h>
#include <openengine/misc/rng.hpp>
#include <components/esm/loadmgef.hpp>
#include <components/esm/loadnpc.hpp>
#include <components/esm/npcstate.hpp>
......@@ -513,7 +515,7 @@ namespace MWClass
float hitchance = MWMechanics::getHitChance(ptr, victim, ptr.getClass().getSkill(ptr, weapskill));
if((::rand()/(RAND_MAX+1.0)) >= hitchance/100.0f)
if (OEngine::Misc::Rng::rollProbability() >= hitchance / 100.0f)
{
othercls.onHit(victim, 0.0f, false, weapon, ptr, false);
MWMechanics::reduceWeaponCondition(0.f, false, weapon, ptr);
......@@ -643,8 +645,7 @@ namespace MWClass
const GMST& gmst = getGmst();
int chance = store.get<ESM::GameSetting>().find("iVoiceHitOdds")->getInt();
int roll = static_cast<int>(std::rand() / (static_cast<double> (RAND_MAX)+1) * 100); // [0, 99]
if (roll < chance)
if (OEngine::Misc::Rng::roll0to99() < chance)
{
MWBase::Environment::get().getDialogueManager()->say(ptr, "hit");
}
......@@ -653,8 +654,7 @@ namespace MWClass
float agilityTerm = getCreatureStats(ptr).getAttribute(ESM::Attribute::Agility).getModified() * gmst.fKnockDownMult->getFloat();
float knockdownTerm = getCreatureStats(ptr).getAttribute(ESM::Attribute::Agility).getModified()
* gmst.iKnockDownOddsMult->getInt() * 0.01f + gmst.iKnockDownOddsBase->getInt();
roll = static_cast<int>(std::rand() / (static_cast<double> (RAND_MAX)+1) * 100); // [0, 99]
if (ishealth && agilityTerm <= damage && knockdownTerm <= roll)
if (ishealth && agilityTerm <= damage && knockdownTerm <= OEngine::Misc::Rng::roll0to99())
{
getCreatureStats(ptr).setKnockedDown(true);
......@@ -680,7 +680,7 @@ namespace MWClass
MWWorld::InventoryStore::Slot_RightPauldron, MWWorld::InventoryStore::Slot_RightPauldron,
MWWorld::InventoryStore::Slot_LeftGauntlet, MWWorld::InventoryStore::Slot_RightGauntlet
};
int hitslot = hitslots[(int)(::rand()/(RAND_MAX+1.0)*20.0)];
int hitslot = hitslots[OEngine::Misc::Rng::rollDice(20)];
float unmitigatedDamage = damage;
float x = damage / (damage + getArmorRating(ptr));
......
#include <MyGUI_ScrollBar.h>
#include <openengine/misc/rng.hpp>
#include "../mwbase/windowmanager.hpp"
#include "../mwbase/mechanicsmanager.hpp"
#include "../mwbase/world.hpp"
......@@ -83,7 +85,7 @@ namespace MWGui
std::set<int> skills;
for (int day=0; day<mDays; ++day)
{
int skill = static_cast<int>(std::rand() / (static_cast<double> (RAND_MAX)+1) * ESM::Skill::Length);
int skill = OEngine::Misc::Rng::rollDice(ESM::Skill::Length);
skills.insert(skill);
MWMechanics::SkillValue& value = player.getClass().getNpcStats(player).getSkill(skill);
......
......@@ -15,6 +15,8 @@
#include <MyGUI_Gui.h>
#include <MyGUI_TextBox.h>
#include <openengine/misc/rng.hpp>
#include <components/settings/settings.hpp>
#include "../mwbase/environment.hpp"
......@@ -146,7 +148,7 @@ namespace MWGui
if (!mResources.empty())
{
std::string const & randomSplash = mResources.at (rand() % mResources.size());
std::string const & randomSplash = mResources.at(OEngine::Misc::Rng::rollDice(mResources.size()));
Ogre::TextureManager::getSingleton ().load (randomSplash, Ogre::ResourceGroupManager::AUTODETECT_RESOURCE_GROUP_NAME);
......
#include "pickpocketitemmodel.hpp"
#include <openengine/misc/rng.hpp>
#include "../mwmechanics/npcstats.hpp"
#include "../mwworld/class.hpp"
......@@ -12,11 +14,13 @@ namespace MWGui
int chance = thief.getClass().getSkill(thief, ESM::Skill::Sneak);
mSourceModel->update();
// build list of items that player is unable to find when attempts to pickpocket.
if (hideItems)
{
for (size_t i = 0; i<mSourceModel->getItemCount(); ++i)
{
if (std::rand() / static_cast<float>(RAND_MAX) * 100 > chance)
if (chance <= OEngine::Misc::Rng::roll0to99())
mHiddenItems.push_back(mSourceModel->getItem(i));
}
}
......
......@@ -5,6 +5,8 @@
#include <MyGUI_ScrollView.h>
#include <MyGUI_Gui.h>
#include <openengine/misc/rng.hpp>
#include <components/esm/records.hpp>
#include "../mwbase/world.hpp"
......@@ -161,7 +163,7 @@ void Recharge::onItemClicked(MyGUI::Widget *sender)
intelligenceTerm = 1;
float x = (npcStats.getSkill(ESM::Skill::Enchant).getModified() + intelligenceTerm + luckTerm) * stats.getFatigueTerm();
int roll = static_cast<int>(std::rand() / (static_cast<double> (RAND_MAX)+1) * 100); // [0, 99]
int roll = OEngine::Misc::Rng::roll0to99();
if (roll < x)
{
std::string soul = gem.getCellRef().getSoul();
......
......@@ -4,6 +4,8 @@
#include <MyGUI_InputManager.h>
#include <MyGUI_ControllerManager.h>
#include <openengine/misc/rng.hpp>
#include <components/widgets/numericeditbox.hpp>
#include "../mwbase/environment.hpp"
......@@ -365,7 +367,7 @@ namespace MWGui
else
x += abs(int(npcTerm - pcTerm));
int roll = std::rand()%100 + 1;
int roll = OEngine::Misc::Rng::rollDice(100) + 1;
if(roll > x || (mCurrentMerchantOffer < 0) != (mCurrentBalance < 0)) //trade refused
{
MWBase::Environment::get().getWindowManager()->
......
......@@ -2,6 +2,8 @@
#include <MyGUI_ProgressBar.h>
#include <openengine/misc/rng.hpp>
#include <components/widgets/box.hpp>
#include <components/settings/settings.hpp>
......@@ -152,10 +154,9 @@ namespace MWGui
const ESM::Region *region = world->getStore().get<ESM::Region>().find (regionstr);
if (!region->mSleepList.empty())
{
// figure out if player will be woken while sleeping
float fSleepRandMod = world->getStore().get<ESM::GameSetting>().find("fSleepRandMod")->getFloat();
int x = static_cast<int>(std::rand() / (static_cast<double> (RAND_MAX)+1) * hoursToWait); // [0, hoursRested]
float y = fSleepRandMod * hoursToWait;
if (x > y)
if (OEngine::Misc::Rng::rollProbability() > fSleepRandMod)
{
float fSleepRestMod = world->getStore().get<ESM::GameSetting>().find("fSleepRestMod")->getFloat();
mInterruptAt = hoursToWait - int(fSleepRestMod * hoursToWait);
......
#include "activespells.hpp"
#include <openengine/misc/rng.hpp>
#include <components/misc/stringops.hpp>
#include <components/esm/loadmgef.hpp>
......@@ -229,8 +231,7 @@ namespace MWMechanics
{
for (TContainer::iterator it = mSpells.begin(); it != mSpells.end(); )
{
int roll = static_cast<int>(std::rand() / (static_cast<double> (RAND_MAX)+1) * 100); // [0, 99]
if (roll < chance)
if (OEngine::Misc::Rng::roll0to99() < chance)
mSpells.erase(it++);
else
++it;
......
......@@ -2,6 +2,8 @@
#include <OgreMath.h>
#include <openengine/misc/rng.hpp>
#include <components/esm/aisequence.hpp>
#include "../mwworld/class.hpp"
......@@ -393,7 +395,7 @@ namespace MWMechanics
if (!distantCombat) attackType = chooseBestAttack(weapon, movement);
else attackType = ESM::Weapon::AT_Chop; // cause it's =0
strength = static_cast<float>(rand()) / RAND_MAX;
strength = OEngine::Misc::Rng::rollClosedProbability();
// Note: may be 0 for some animations
timerAttack = minMaxAttackDuration[attackType][0] +
......@@ -404,8 +406,7 @@ namespace MWMechanics
{
const MWWorld::ESMStore &store = world->getStore();
int chance = store.get<ESM::GameSetting>().find("iVoiceAttackOdds")->getInt();
int roll = static_cast<int>(std::rand() / (static_cast<double> (RAND_MAX)+1) * 100); // [0, 99]
if (roll < chance)
if (OEngine::Misc::Rng::roll0to99() < chance)
{
MWBase::Environment::get().getDialogueManager()->say(actor, "attack");
}
......@@ -512,17 +513,17 @@ namespace MWMechanics
{
if(movement.mPosition[0] || movement.mPosition[1])
{
timerCombatMove = 0.1f + 0.1f * static_cast<float>(rand())/RAND_MAX;
timerCombatMove = 0.1f + 0.1f * OEngine::Misc::Rng::rollClosedProbability();
combatMove = true;
}
// only NPCs are smart enough to use dodge movements
else if(actorClass.isNpc() && (!distantCombat || (distantCombat && distToTarget < rangeAttack/2)))
{
//apply sideway movement (kind of dodging) with some probability
if(static_cast<float>(rand())/RAND_MAX < 0.25)
if (OEngine::Misc::Rng::rollClosedProbability() < 0.25)
{
movement.mPosition[0] = static_cast<float>(rand())/RAND_MAX < 0.5? 1.0f : -1.0f;
timerCombatMove = 0.05f + 0.15f * static_cast<float>(rand())/RAND_MAX;
movement.mPosition[0] = OEngine::Misc::Rng::rollProbability() < 0.5 ? 1.0f : -1.0f;
timerCombatMove = 0.05f + 0.15f * OEngine::Misc::Rng::rollClosedProbability();
combatMove = true;
}
}
......@@ -637,7 +638,7 @@ namespace MWMechanics
float s2 = speed2 * t;
float t_swing =
minMaxAttackDuration[ESM::Weapon::AT_Thrust][0] +
(minMaxAttackDuration[ESM::Weapon::AT_Thrust][1] - minMaxAttackDuration[ESM::Weapon::AT_Thrust][0]) * static_cast<float>(rand()) / RAND_MAX;
(minMaxAttackDuration[ESM::Weapon::AT_Thrust][1] - minMaxAttackDuration[ESM::Weapon::AT_Thrust][0]) * OEngine::Misc::Rng::rollClosedProbability();
if (t + s2/speed1 <= t_swing)
{
......@@ -761,10 +762,10 @@ ESM::Weapon::AttackType chooseBestAttack(const ESM::Weapon* weapon, MWMechanics:
if (weapon == NULL)
{
//hand-to-hand deal equal damage for each type
float roll = static_cast<float>(rand())/RAND_MAX;
float roll = OEngine::Misc::Rng::rollClosedProbability();
if(roll <= 0.333f) //side punch
{
movement.mPosition[0] = (static_cast<float>(rand())/RAND_MAX < 0.5f)? 1.0f : -1.0f;
movement.mPosition[0] = OEngine::Misc::Rng::rollClosedProbability() ? 1.0f : -1.0f;
movement.mPosition[1] = 0;
attackType = ESM::Weapon::AT_Slash;
}
......@@ -788,10 +789,10 @@ ESM::Weapon::AttackType chooseBestAttack(const ESM::Weapon* weapon, MWMechanics:
float total = static_cast<float>(slash + chop + thrust);
float roll = static_cast<float>(rand())/RAND_MAX;
float roll = OEngine::Misc::Rng::rollClosedProbability();
if(roll <= (slash/total))
{
movement.mPosition[0] = (static_cast<float>(rand())/RAND_MAX < 0.5f)? 1.0f : -1.0f;
movement.mPosition[0] = (OEngine::Misc::Rng::rollClosedProbability() < 0.5f) ? 1.0f : -1.0f;
movement.mPosition[1] = 0;
attackType = ESM::Weapon::AT_Slash;
}
......
......@@ -3,6 +3,8 @@
#include <OgreVector3.h>
#include <OgreSceneNode.h>
#include <openengine/misc/rng.hpp>
#include <components/esm/aisequence.hpp>
#include "../mwbase/world.hpp"
......@@ -315,7 +317,7 @@ namespace MWMechanics
static float fVoiceIdleOdds = MWBase::Environment::get().getWorld()->getStore()
.get<ESM::GameSetting>().find("fVoiceIdleOdds")->getFloat();
float roll = std::rand()/ (static_cast<float> (RAND_MAX) + 1) * 10000;
float roll = OEngine::Misc::Rng::rollProbability() * 10000.0f;
// In vanilla MW the chance was FPS dependent, and did not allow proper changing of fVoiceIdleOdds
// due to the roll being an integer.
......@@ -490,7 +492,7 @@ namespace MWMechanics
if(!storage.mPathFinder.isPathConstructed())
{
assert(mAllowedNodes.size());
unsigned int randNode = (int)(rand() / ((double)RAND_MAX + 1) * mAllowedNodes.size());
unsigned int randNode = OEngine::Misc::Rng::rollDice(mAllowedNodes.size());
// NOTE: initially constructed with local (i.e. cell) co-ordinates
Ogre::Vector3 destNodePos(PathFinder::MakeOgreVector3(mAllowedNodes[randNode]));
......@@ -637,7 +639,7 @@ namespace MWMechanics
.get<ESM::GameSetting>().find("fIdleChanceMultiplier")->getFloat();
unsigned short idleChance = static_cast<unsigned short>(fIdleChanceMultiplier * mIdle[counter]);
unsigned short randSelect = (int)(rand() / ((double)RAND_MAX + 1) * int(100 / fIdleChanceMultiplier));
unsigned short randSelect = (int)(OEngine::Misc::Rng::rollProbability() * int(100 / fIdleChanceMultiplier));
if(randSelect < idleChance && randSelect > idleRoll)
{
playedIdle = counter+2;
......@@ -659,7 +661,7 @@ namespace MWMechanics
state.moveIn(new AiWanderStorage());
int index = static_cast<int>(std::rand() / (static_cast<double> (RAND_MAX)+1) * mAllowedNodes.size());
int index = OEngine::Misc::Rng::rollDice(mAllowedNodes.size());
ESM::Pathgrid::Point dest = mAllowedNodes[index];
// apply a slight offset to prevent overcrowding
......
......@@ -8,6 +8,8 @@
#include <stdexcept>
#include <map>
#include <openengine/misc/rng.hpp>
#include <components/esm/loadskil.hpp>
#include <components/esm/loadappa.hpp>
#include <components/esm/loadgmst.hpp>
......@@ -294,7 +296,7 @@ void MWMechanics::Alchemy::addPotion (const std::string& name)
newRecord.mName = name;
int index = static_cast<int> (std::rand()/(static_cast<double> (RAND_MAX)+1)*6);
int index = OEngine::Misc::Rng::rollDice(6);
assert (index>=0 && index<6);
static const char *meshes[] = { "standard", "bargain", "cheap", "fresh", "exclusive", "quality" };
......@@ -467,7 +469,7 @@ MWMechanics::Alchemy::Result MWMechanics::Alchemy::create (const std::string& na
return Result_RandomFailure;
}
if (getAlchemyFactor()<std::rand()/static_cast<double> (RAND_MAX)*100)
if (getAlchemyFactor() < OEngine::Misc::Rng::roll0to99())
{
removeIngredients();
return Result_RandomFailure;
......
......@@ -27,6 +27,8 @@
#include "creaturestats.hpp"
#include "security.hpp"
#include <openengine/misc/rng.hpp>
#include <components/settings/settings.hpp>
#include "../mwrender/animation.hpp"
......@@ -220,7 +222,7 @@ std::string CharacterController::chooseRandomGroup (const std::string& prefix, i
while (mAnimation->hasAnimation(prefix + Ogre::StringConverter::toString(numAnims+1)))
++numAnims;
int roll = static_cast<int>(std::rand() / (static_cast<double> (RAND_MAX)+1) * numAnims) + 1; // [1, numAnims]
int roll = OEngine::Misc::Rng::rollDice(numAnims) + 1; // [1, numAnims]
if (num)
*num = roll;
return prefix + Ogre::StringConverter::toString(roll);
......@@ -829,7 +831,7 @@ bool CharacterController::updateCreatureState()
}
if (weapType != WeapType_Spell || !mAnimation->hasAnimation("spellcast")) // Not all creatures have a dedicated spellcast animation
{
int roll = static_cast<int>(std::rand() / (static_cast<double> (RAND_MAX)+1) * 3); // [0, 2]
int roll = OEngine::Misc::Rng::rollDice(3); // [0, 2]
if (roll == 0)
mCurrentWeapon = "attack1";
else if (roll == 1)
......@@ -1125,7 +1127,7 @@ bool CharacterController::updateWeaponState()
// most creatures don't actually have an attack wind-up animation, so use a uniform random value
// (even some creatures that can use weapons don't have a wind-up animation either, e.g. Rieklings)
// Note: vanilla MW uses a random value for *all* non-player actors, but we probably don't need to go that far.
attackStrength = std::min(1.f, 0.1f + std::rand() / float(RAND_MAX));
attackStrength = std::min(1.f, 0.1f + OEngine::Misc::Rng::rollClosedProbability());
}
if(mWeaponType != WeapType_Crossbow && mWeaponType != WeapType_BowAndArrow)
......
......@@ -2,6 +2,8 @@
#include <OgreSceneNode.h>
#include <openengine/misc/rng.hpp>
#include "../mwbase/environment.hpp"
#include "../mwbase/world.hpp"
#include "../mwbase/mechanicsmanager.hpp"
......@@ -107,8 +109,7 @@ namespace MWMechanics
int iBlockMinChance = gmst.find("iBlockMinChance")->getInt();
x = std::min(iBlockMaxChance, std::max(iBlockMinChance, x));
int roll = static_cast<int>(std::rand() / (static_cast<double> (RAND_MAX)+1) * 100); // [0, 99]
if (roll < x)
if (OEngine::Misc::Rng::roll0to99() < x)
{
// Reduce shield durability by incoming damage
int shieldhealth = shield->getClass().getItemHealth(*shield);
......@@ -186,7 +187,7 @@ namespace MWMechanics
int skillValue = attacker.getClass().getSkill(attacker,
weapon.getClass().getEquipmentSkill(weapon));
if((::rand()/(RAND_MAX+1.0)) >= getHitChance(attacker, victim, skillValue)/100.0f)
if (OEngine::Misc::Rng::rollProbability() >= getHitChance(attacker, victim, skillValue) / 100.0f)
{
victim.getClass().onHit(victim, 0.0f, false, projectile, attacker, false);
MWMechanics::reduceWeaponCondition(0.f, false, weapon, attacker);
......@@ -224,7 +225,7 @@ namespace MWMechanics
&& !appliedEnchantment)
{
float fProjectileThrownStoreChance = gmst.find("fProjectileThrownStoreChance")->getFloat();
if ((::rand()/(RAND_MAX+1.0)) < fProjectileThrownStoreChance/100.f)
if (OEngine::Misc::Rng::rollProbability() < fProjectileThrownStoreChance / 100.f)
victim.getClass().getContainerStore(victim).add(projectile, 1, victim);
}
......@@ -291,8 +292,7 @@ namespace MWMechanics
saveTerm *= 1.25f * normalisedFatigue;
float roll = std::rand()/ (static_cast<float> (RAND_MAX) + 1) * 100; // [0, 99]
float x = std::max(0.f, saveTerm - roll);
float x = std::max(0.f, saveTerm - OEngine::Misc::Rng::roll0to99());
int element = ESM::MagicEffect::FireDamage;
if (i == 1)
......
#ifndef OPENMW_MECHANICS_DISEASE_H
#define OPENMW_MECHANICS_DISEASE_H
#include <openengine/misc/rng.hpp>
#include "../mwbase/windowmanager.hpp"
#include "../mwbase/environment.hpp"
#include "../mwbase/world.hpp"
......@@ -49,9 +51,7 @@ namespace MWMechanics
continue;
int x = static_cast<int>(fDiseaseXferChance * 100 * resist);
float roll = static_cast<float>(std::rand() / (static_cast<double> (RAND_MAX)+1) * 10000); // [0, 9999]
if (roll < x)
if (OEngine::Misc::Rng::rollDice(10000) < x)
{
// Contracted disease!
actor.getClass().getCreatureStats(actor).getSpells().add(it->first);
......
#include "enchanting.hpp"
#include <openengine/misc/rng.hpp>
#include "../mwworld/manualref.hpp"
#include "../mwworld/class.hpp"
#include "../mwworld/containerstore.hpp"
......@@ -67,7 +70,7 @@ namespace MWMechanics
if(mSelfEnchanting)
{
if(getEnchantChance()<std::rand()/static_cast<double> (RAND_MAX)*100)
if(getEnchantChance() <= (OEngine::Misc::Rng::roll0to99()))
return false;
mEnchanter.getClass().skillUsageSucceeded (mEnchanter, ESM::Skill::Enchant, 2);
......
#ifndef OPENMW_MECHANICS_LEVELLEDLIST_H
#define OPENMW_MECHANICS_LEVELLEDLIST_H
#include <openengine/misc/rng.hpp>
#include "../mwworld/ptr.hpp"
#include "../mwworld/esmstore.hpp"
#include "../mwworld/manualref.hpp"
......@@ -22,8 +24,7 @@ namespace MWMechanics
failChance += levItem->mChanceNone;
int random = static_cast<int>(static_cast<int>(std::rand() / (static_cast<double> (RAND_MAX)+1) * 100)); // [0, 99]
if (random < failChance)
if (OEngine::Misc::Rng::roll0to99() < failChance)
return std::string();
std::vector<std::string> candidates;
......@@ -52,7 +53,7 @@ namespace MWMechanics
}
if (candidates.empty())
return std::string();
std::string item = candidates[std::rand()%candidates.size()];
std::string item = candidates[OEngine::Misc::Rng::rollDice(candidates.size())];
// Vanilla doesn't fail on nonexistent items in levelled lists
if (!MWBase::Environment::get().getWorld()->getStore().find(Misc::StringUtils::lowerCase(item)))
......
......@@ -2,6 +2,8 @@
#include "mechanicsmanagerimp.hpp"
#include "npcstats.hpp"
#include <openengine/misc/rng.hpp>
#include <components/esm/stolenitems.hpp>
#include "../mwworld/esmstore.hpp"
......@@ -723,7 +725,7 @@ namespace MWMechanics
float x = 0;
float y = 0;
float roll = static_cast<float> (std::rand()) / RAND_MAX * 100;
float roll = OEngine::Misc::Rng::rollClosedProbability() * 100;
if (type == PT_Admire)
{
......@@ -1378,9 +1380,8 @@ namespace MWMechanics
y = obsTerm * observerStats.getFatigueTerm() * fSneakViewMult;
float target = x - y;
int roll = static_cast<int>(std::rand() / (static_cast<double> (RAND_MAX)+1) * 100); // [0, 99]
return (roll >= target);
return (OEngine::Misc::Rng::roll0to99() >= target);
}
void MechanicsManager::startCombat(const MWWorld::Ptr &ptr, const MWWorld::Ptr &target)
......
#include "pickpocket.hpp"
#include <openengine/misc/rng.hpp>
#include "../mwworld/class.hpp"
#include "../mwworld/esmstore.hpp"
......@@ -39,7 +41,7 @@ namespace MWMechanics
int iPickMaxChance = MWBase::Environment::get().getWorld(