mirror of
https://gitlab.com/OpenMW/openmw.git
synced 2025-04-11 00:44:33 +00:00
Pass the prng from world where appropriate
This commit is contained in:
parent
b502dc12f0
commit
08fae7be6e
@ -120,7 +120,8 @@ namespace MWClass
|
|||||||
if(actor.getClass().isNpc() && actor.getClass().getNpcStats(actor).isWerewolf())
|
if(actor.getClass().isNpc() && actor.getClass().getNpcStats(actor).isWerewolf())
|
||||||
{
|
{
|
||||||
const MWWorld::ESMStore &store = MWBase::Environment::get().getWorld()->getStore();
|
const MWWorld::ESMStore &store = MWBase::Environment::get().getWorld()->getStore();
|
||||||
const ESM::Sound *sound = store.get<ESM::Sound>().searchRandom("WolfActivator");
|
auto& prng = MWBase::Environment::get().getWorld()->getPrng();
|
||||||
|
const ESM::Sound *sound = store.get<ESM::Sound>().searchRandom("WolfActivator", prng);
|
||||||
|
|
||||||
std::shared_ptr<MWWorld::Action> action(new MWWorld::FailedAction("#{sWerewolfRefusal}"));
|
std::shared_ptr<MWWorld::Action> action(new MWWorld::FailedAction("#{sWerewolfRefusal}"));
|
||||||
if(sound) action->setSound(sound->mId);
|
if(sound) action->setSound(sound->mId);
|
||||||
@ -156,6 +157,7 @@ namespace MWClass
|
|||||||
int type = getSndGenTypeFromName(name);
|
int type = getSndGenTypeFromName(name);
|
||||||
|
|
||||||
std::vector<const ESM::SoundGenerator*> fallbacksounds;
|
std::vector<const ESM::SoundGenerator*> fallbacksounds;
|
||||||
|
auto& prng = MWBase::Environment::get().getWorld()->getPrng();
|
||||||
if (!creatureId.empty())
|
if (!creatureId.empty())
|
||||||
{
|
{
|
||||||
std::vector<const ESM::SoundGenerator*> sounds;
|
std::vector<const ESM::SoundGenerator*> sounds;
|
||||||
@ -168,9 +170,9 @@ namespace MWClass
|
|||||||
}
|
}
|
||||||
|
|
||||||
if (!sounds.empty())
|
if (!sounds.empty())
|
||||||
return sounds[Misc::Rng::rollDice(sounds.size())]->mSound;
|
return sounds[Misc::Rng::rollDice(sounds.size(), prng)]->mSound;
|
||||||
if (!fallbacksounds.empty())
|
if (!fallbacksounds.empty())
|
||||||
return fallbacksounds[Misc::Rng::rollDice(fallbacksounds.size())]->mSound;
|
return fallbacksounds[Misc::Rng::rollDice(fallbacksounds.size(), prng)]->mSound;
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
@ -180,7 +182,7 @@ namespace MWClass
|
|||||||
fallbacksounds.push_back(&*sound);
|
fallbacksounds.push_back(&*sound);
|
||||||
|
|
||||||
if (!fallbacksounds.empty())
|
if (!fallbacksounds.empty())
|
||||||
return fallbacksounds[Misc::Rng::rollDice(fallbacksounds.size())]->mSound;
|
return fallbacksounds[Misc::Rng::rollDice(fallbacksounds.size(), prng)]->mSound;
|
||||||
}
|
}
|
||||||
|
|
||||||
return std::string();
|
return std::string();
|
||||||
|
@ -56,7 +56,8 @@ namespace MWClass
|
|||||||
if(actor.getClass().isNpc() && actor.getClass().getNpcStats(actor).isWerewolf())
|
if(actor.getClass().isNpc() && actor.getClass().getNpcStats(actor).isWerewolf())
|
||||||
{
|
{
|
||||||
const MWWorld::ESMStore &store = MWBase::Environment::get().getWorld()->getStore();
|
const MWWorld::ESMStore &store = MWBase::Environment::get().getWorld()->getStore();
|
||||||
const ESM::Sound *sound = store.get<ESM::Sound>().searchRandom("WolfItem");
|
auto& prng = MWBase::Environment::get().getWorld()->getPrng();
|
||||||
|
const ESM::Sound *sound = store.get<ESM::Sound>().searchRandom("WolfItem", prng);
|
||||||
|
|
||||||
std::shared_ptr<MWWorld::Action> action(new MWWorld::FailedAction("#{sWerewolfRefusal}"));
|
std::shared_ptr<MWWorld::Action> action(new MWWorld::FailedAction("#{sWerewolfRefusal}"));
|
||||||
if(sound) action->setSound(sound->mId);
|
if(sound) action->setSound(sound->mId);
|
||||||
|
@ -32,7 +32,8 @@ namespace MWClass
|
|||||||
{
|
{
|
||||||
ContainerCustomData::ContainerCustomData(const ESM::Container& container, MWWorld::CellStore* cell)
|
ContainerCustomData::ContainerCustomData(const ESM::Container& container, MWWorld::CellStore* cell)
|
||||||
{
|
{
|
||||||
unsigned int seed = Misc::Rng::rollDice(std::numeric_limits<int>::max());
|
auto& prng = MWBase::Environment::get().getWorld()->getPrng();
|
||||||
|
unsigned int seed = Misc::Rng::rollDice(std::numeric_limits<int>::max(), prng);
|
||||||
// setting ownership not needed, since taking items from a container inherits the
|
// setting ownership not needed, since taking items from a container inherits the
|
||||||
// container's owner automatically
|
// container's owner automatically
|
||||||
mStore.fillNonRandom(container.mInventory, "", seed);
|
mStore.fillNonRandom(container.mInventory, "", seed);
|
||||||
@ -139,7 +140,8 @@ namespace MWClass
|
|||||||
if(actor.getClass().isNpc() && actor.getClass().getNpcStats(actor).isWerewolf())
|
if(actor.getClass().isNpc() && actor.getClass().getNpcStats(actor).isWerewolf())
|
||||||
{
|
{
|
||||||
const MWWorld::ESMStore &store = MWBase::Environment::get().getWorld()->getStore();
|
const MWWorld::ESMStore &store = MWBase::Environment::get().getWorld()->getStore();
|
||||||
const ESM::Sound *sound = store.get<ESM::Sound>().searchRandom("WolfContainer");
|
auto& prng = MWBase::Environment::get().getWorld()->getPrng();
|
||||||
|
const ESM::Sound *sound = store.get<ESM::Sound>().searchRandom("WolfContainer", prng);
|
||||||
|
|
||||||
std::shared_ptr<MWWorld::Action> action(new MWWorld::FailedAction("#{sWerewolfRefusal}"));
|
std::shared_ptr<MWWorld::Action> action(new MWWorld::FailedAction("#{sWerewolfRefusal}"));
|
||||||
if(sound) action->setSound(sound->mId);
|
if(sound) action->setSound(sound->mId);
|
||||||
|
@ -159,7 +159,8 @@ namespace MWClass
|
|||||||
|
|
||||||
resetter.mPtr = {};
|
resetter.mPtr = {};
|
||||||
|
|
||||||
getContainerStore(ptr).fill(ref->mBase->mInventory, ptr.getCellRef().getRefId());
|
auto& prng = MWBase::Environment::get().getWorld()->getPrng();
|
||||||
|
getContainerStore(ptr).fill(ref->mBase->mInventory, ptr.getCellRef().getRefId(), prng);
|
||||||
|
|
||||||
if (hasInventory)
|
if (hasInventory)
|
||||||
getInventoryStore(ptr).autoEquip(ptr);
|
getInventoryStore(ptr).autoEquip(ptr);
|
||||||
@ -264,8 +265,8 @@ namespace MWClass
|
|||||||
osg::Vec3f hitPosition (result.second);
|
osg::Vec3f hitPosition (result.second);
|
||||||
|
|
||||||
float hitchance = MWMechanics::getHitChance(ptr, victim, ref->mBase->mData.mCombat);
|
float hitchance = MWMechanics::getHitChance(ptr, victim, ref->mBase->mData.mCombat);
|
||||||
|
auto& prng = MWBase::Environment::get().getWorld()->getPrng();
|
||||||
if(Misc::Rng::roll0to99() >= hitchance)
|
if(Misc::Rng::roll0to99(prng) >= hitchance)
|
||||||
{
|
{
|
||||||
victim.getClass().onHit(victim, 0.0f, false, MWWorld::Ptr(), ptr, osg::Vec3f(), false);
|
victim.getClass().onHit(victim, 0.0f, false, MWWorld::Ptr(), ptr, osg::Vec3f(), false);
|
||||||
MWMechanics::reduceWeaponCondition(0.f, false, weapon, ptr);
|
MWMechanics::reduceWeaponCondition(0.f, false, weapon, ptr);
|
||||||
@ -392,7 +393,8 @@ namespace MWClass
|
|||||||
float agilityTerm = stats.getAttribute(ESM::Attribute::Agility).getModified() * getGmst().fKnockDownMult->mValue.getFloat();
|
float agilityTerm = stats.getAttribute(ESM::Attribute::Agility).getModified() * getGmst().fKnockDownMult->mValue.getFloat();
|
||||||
float knockdownTerm = stats.getAttribute(ESM::Attribute::Agility).getModified()
|
float knockdownTerm = stats.getAttribute(ESM::Attribute::Agility).getModified()
|
||||||
* getGmst().iKnockDownOddsMult->mValue.getInteger() * 0.01f + getGmst().iKnockDownOddsBase->mValue.getInteger();
|
* getGmst().iKnockDownOddsMult->mValue.getInteger() * 0.01f + getGmst().iKnockDownOddsBase->mValue.getInteger();
|
||||||
if (ishealth && agilityTerm <= damage && knockdownTerm <= Misc::Rng::roll0to99())
|
auto& prng = MWBase::Environment::get().getWorld()->getPrng();
|
||||||
|
if (ishealth && agilityTerm <= damage && knockdownTerm <= Misc::Rng::roll0to99(prng))
|
||||||
stats.setKnockedDown(true);
|
stats.setKnockedDown(true);
|
||||||
else
|
else
|
||||||
stats.setHitRecovery(true); // Is this supposed to always occur?
|
stats.setHitRecovery(true); // Is this supposed to always occur?
|
||||||
@ -429,7 +431,8 @@ namespace MWClass
|
|||||||
if(actor.getClass().isNpc() && actor.getClass().getNpcStats(actor).isWerewolf())
|
if(actor.getClass().isNpc() && actor.getClass().getNpcStats(actor).isWerewolf())
|
||||||
{
|
{
|
||||||
const MWWorld::ESMStore &store = MWBase::Environment::get().getWorld()->getStore();
|
const MWWorld::ESMStore &store = MWBase::Environment::get().getWorld()->getStore();
|
||||||
const ESM::Sound *sound = store.get<ESM::Sound>().searchRandom("WolfCreature");
|
auto& prng = MWBase::Environment::get().getWorld()->getPrng();
|
||||||
|
const ESM::Sound *sound = store.get<ESM::Sound>().searchRandom("WolfCreature", prng);
|
||||||
|
|
||||||
std::shared_ptr<MWWorld::Action> action(new MWWorld::FailedAction("#{sWerewolfRefusal}"));
|
std::shared_ptr<MWWorld::Action> action(new MWWorld::FailedAction("#{sWerewolfRefusal}"));
|
||||||
if(sound) action->setSound(sound->mId);
|
if(sound) action->setSound(sound->mId);
|
||||||
@ -642,10 +645,11 @@ namespace MWClass
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
auto& prng = MWBase::Environment::get().getWorld()->getPrng();
|
||||||
if (!sounds.empty())
|
if (!sounds.empty())
|
||||||
return sounds[Misc::Rng::rollDice(sounds.size())]->mSound;
|
return sounds[Misc::Rng::rollDice(sounds.size(), prng)]->mSound;
|
||||||
if (!fallbacksounds.empty())
|
if (!fallbacksounds.empty())
|
||||||
return fallbacksounds[Misc::Rng::rollDice(fallbacksounds.size())]->mSound;
|
return fallbacksounds[Misc::Rng::rollDice(fallbacksounds.size(), prng)]->mSound;
|
||||||
|
|
||||||
return std::string();
|
return std::string();
|
||||||
}
|
}
|
||||||
|
@ -127,7 +127,8 @@ namespace MWClass
|
|||||||
MWWorld::LiveCellRef<ESM::CreatureLevList> *ref =
|
MWWorld::LiveCellRef<ESM::CreatureLevList> *ref =
|
||||||
ptr.get<ESM::CreatureLevList>();
|
ptr.get<ESM::CreatureLevList>();
|
||||||
|
|
||||||
std::string id = MWMechanics::getLevelledItem(ref->mBase, true);
|
auto& prng = MWBase::Environment::get().getWorld()->getPrng();
|
||||||
|
std::string id = MWMechanics::getLevelledItem(ref->mBase, true, prng);
|
||||||
|
|
||||||
if (!id.empty())
|
if (!id.empty())
|
||||||
{
|
{
|
||||||
|
@ -394,7 +394,8 @@ namespace MWClass
|
|||||||
|
|
||||||
// inventory
|
// inventory
|
||||||
// setting ownership is used to make the NPC auto-equip his initial equipment only, and not bartered items
|
// setting ownership is used to make the NPC auto-equip his initial equipment only, and not bartered items
|
||||||
getInventoryStore(ptr).fill(ref->mBase->mInventory, ptr.getCellRef().getRefId());
|
auto& prng = MWBase::Environment::get().getWorld()->getPrng();
|
||||||
|
getInventoryStore(ptr).fill(ref->mBase->mInventory, ptr.getCellRef().getRefId(), prng);
|
||||||
|
|
||||||
getInventoryStore(ptr).autoEquip(ptr);
|
getInventoryStore(ptr).autoEquip(ptr);
|
||||||
}
|
}
|
||||||
@ -584,7 +585,7 @@ namespace MWClass
|
|||||||
|
|
||||||
float hitchance = MWMechanics::getHitChance(ptr, victim, getSkill(ptr, weapskill));
|
float hitchance = MWMechanics::getHitChance(ptr, victim, getSkill(ptr, weapskill));
|
||||||
|
|
||||||
if (Misc::Rng::roll0to99() >= hitchance)
|
if (Misc::Rng::roll0to99(world->getPrng()) >= hitchance)
|
||||||
{
|
{
|
||||||
othercls.onHit(victim, 0.0f, false, weapon, ptr, osg::Vec3f(), false);
|
othercls.onHit(victim, 0.0f, false, weapon, ptr, osg::Vec3f(), false);
|
||||||
MWMechanics::reduceWeaponCondition(0.f, false, weapon, ptr);
|
MWMechanics::reduceWeaponCondition(0.f, false, weapon, ptr);
|
||||||
@ -726,15 +727,16 @@ namespace MWClass
|
|||||||
const MWWorld::ESMStore &store = MWBase::Environment::get().getWorld()->getStore();
|
const MWWorld::ESMStore &store = MWBase::Environment::get().getWorld()->getStore();
|
||||||
const GMST& gmst = getGmst();
|
const GMST& gmst = getGmst();
|
||||||
|
|
||||||
int chance = store.get<ESM::GameSetting>().find("iVoiceHitOdds")->mValue.getInteger();
|
int chance = store.get<ESM::GameSetting>().find("iVoiceHitOdds")->mValue.getInteger();
|
||||||
if (Misc::Rng::roll0to99() < chance)
|
auto& prng = MWBase::Environment::get().getWorld()->getPrng();
|
||||||
|
if (Misc::Rng::roll0to99(prng) < chance)
|
||||||
MWBase::Environment::get().getDialogueManager()->say(ptr, "hit");
|
MWBase::Environment::get().getDialogueManager()->say(ptr, "hit");
|
||||||
|
|
||||||
// Check for knockdown
|
// Check for knockdown
|
||||||
float agilityTerm = stats.getAttribute(ESM::Attribute::Agility).getModified() * gmst.fKnockDownMult->mValue.getFloat();
|
float agilityTerm = stats.getAttribute(ESM::Attribute::Agility).getModified() * gmst.fKnockDownMult->mValue.getFloat();
|
||||||
float knockdownTerm = stats.getAttribute(ESM::Attribute::Agility).getModified()
|
float knockdownTerm = stats.getAttribute(ESM::Attribute::Agility).getModified()
|
||||||
* gmst.iKnockDownOddsMult->mValue.getInteger() * 0.01f + gmst.iKnockDownOddsBase->mValue.getInteger();
|
* gmst.iKnockDownOddsMult->mValue.getInteger() * 0.01f + gmst.iKnockDownOddsBase->mValue.getInteger();
|
||||||
if (ishealth && agilityTerm <= damage && knockdownTerm <= Misc::Rng::roll0to99())
|
if (ishealth && agilityTerm <= damage && knockdownTerm <= Misc::Rng::roll0to99(prng))
|
||||||
stats.setKnockedDown(true);
|
stats.setKnockedDown(true);
|
||||||
else
|
else
|
||||||
stats.setHitRecovery(true); // Is this supposed to always occur?
|
stats.setHitRecovery(true); // Is this supposed to always occur?
|
||||||
@ -757,7 +759,7 @@ namespace MWClass
|
|||||||
MWWorld::InventoryStore::Slot_RightPauldron, MWWorld::InventoryStore::Slot_RightPauldron,
|
MWWorld::InventoryStore::Slot_RightPauldron, MWWorld::InventoryStore::Slot_RightPauldron,
|
||||||
MWWorld::InventoryStore::Slot_LeftGauntlet, MWWorld::InventoryStore::Slot_RightGauntlet
|
MWWorld::InventoryStore::Slot_LeftGauntlet, MWWorld::InventoryStore::Slot_RightGauntlet
|
||||||
};
|
};
|
||||||
int hitslot = hitslots[Misc::Rng::rollDice(20)];
|
int hitslot = hitslots[Misc::Rng::rollDice(20, prng)];
|
||||||
|
|
||||||
float unmitigatedDamage = damage;
|
float unmitigatedDamage = damage;
|
||||||
float x = damage / (damage + getArmorRating(ptr));
|
float x = damage / (damage + getArmorRating(ptr));
|
||||||
@ -773,7 +775,7 @@ namespace MWClass
|
|||||||
// If there's no item in the carried left slot or if it is not a shield redistribute the hit.
|
// If there's no item in the carried left slot or if it is not a shield redistribute the hit.
|
||||||
if (!hasArmor && hitslot == MWWorld::InventoryStore::Slot_CarriedLeft)
|
if (!hasArmor && hitslot == MWWorld::InventoryStore::Slot_CarriedLeft)
|
||||||
{
|
{
|
||||||
if (Misc::Rng::rollDice(2) == 0)
|
if (Misc::Rng::rollDice(2, prng) == 0)
|
||||||
hitslot = MWWorld::InventoryStore::Slot_Cuirass;
|
hitslot = MWWorld::InventoryStore::Slot_Cuirass;
|
||||||
else
|
else
|
||||||
hitslot = MWWorld::InventoryStore::Slot_LeftPauldron;
|
hitslot = MWWorld::InventoryStore::Slot_LeftPauldron;
|
||||||
@ -865,7 +867,8 @@ namespace MWClass
|
|||||||
if(actor.getClass().isNpc() && actor.getClass().getNpcStats(actor).isWerewolf())
|
if(actor.getClass().isNpc() && actor.getClass().getNpcStats(actor).isWerewolf())
|
||||||
{
|
{
|
||||||
const MWWorld::ESMStore &store = MWBase::Environment::get().getWorld()->getStore();
|
const MWWorld::ESMStore &store = MWBase::Environment::get().getWorld()->getStore();
|
||||||
const ESM::Sound *sound = store.get<ESM::Sound>().searchRandom("WolfNPC");
|
auto& prng = MWBase::Environment::get().getWorld()->getPrng();
|
||||||
|
const ESM::Sound *sound = store.get<ESM::Sound>().searchRandom("WolfNPC", prng);
|
||||||
|
|
||||||
std::shared_ptr<MWWorld::Action> action(new MWWorld::FailedAction("#{sWerewolfRefusal}"));
|
std::shared_ptr<MWWorld::Action> action(new MWWorld::FailedAction("#{sWerewolfRefusal}"));
|
||||||
if(sound) action->setSound(sound->mId);
|
if(sound) action->setSound(sound->mId);
|
||||||
|
@ -87,7 +87,8 @@ namespace MWGui
|
|||||||
std::set<int> skills;
|
std::set<int> skills;
|
||||||
for (int day=0; day<mDays; ++day)
|
for (int day=0; day<mDays; ++day)
|
||||||
{
|
{
|
||||||
int skill = Misc::Rng::rollDice(ESM::Skill::Length);
|
auto& prng = MWBase::Environment::get().getWorld()->getPrng();
|
||||||
|
int skill = Misc::Rng::rollDice(ESM::Skill::Length, prng);
|
||||||
skills.insert(skill);
|
skills.insert(skill);
|
||||||
|
|
||||||
MWMechanics::SkillValue& value = player.getClass().getNpcStats(player).getSkill(skill);
|
MWMechanics::SkillValue& value = player.getClass().getNpcStats(player).getSkill(skill);
|
||||||
|
@ -24,13 +24,13 @@ namespace MWGui
|
|||||||
float chance = player.getClass().getSkill(player, ESM::Skill::Sneak);
|
float chance = player.getClass().getSkill(player, ESM::Skill::Sneak);
|
||||||
|
|
||||||
mSourceModel->update();
|
mSourceModel->update();
|
||||||
|
|
||||||
// build list of items that player is unable to find when attempts to pickpocket.
|
// build list of items that player is unable to find when attempts to pickpocket.
|
||||||
if (hideItems)
|
if (hideItems)
|
||||||
{
|
{
|
||||||
|
auto& prng = MWBase::Environment::get().getWorld()->getPrng();
|
||||||
for (size_t i = 0; i<mSourceModel->getItemCount(); ++i)
|
for (size_t i = 0; i<mSourceModel->getItemCount(); ++i)
|
||||||
{
|
{
|
||||||
if (Misc::Rng::roll0to99() > chance)
|
if (Misc::Rng::roll0to99(prng) > chance)
|
||||||
mHiddenItems.push_back(mSourceModel->getItem(i));
|
mHiddenItems.push_back(mSourceModel->getItem(i));
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -191,7 +191,7 @@ namespace MWGui
|
|||||||
if (!region->mSleepList.empty())
|
if (!region->mSleepList.empty())
|
||||||
{
|
{
|
||||||
// figure out if player will be woken while sleeping
|
// figure out if player will be woken while sleeping
|
||||||
int x = Misc::Rng::rollDice(hoursToWait);
|
int x = Misc::Rng::rollDice(hoursToWait, world->getPrng());
|
||||||
float fSleepRandMod = world->getStore().get<ESM::GameSetting>().find("fSleepRandMod")->mValue.getFloat();
|
float fSleepRandMod = world->getStore().get<ESM::GameSetting>().find("fSleepRandMod")->mValue.getFloat();
|
||||||
if (x < fSleepRandMod * hoursToWait)
|
if (x < fSleepRandMod * hoursToWait)
|
||||||
{
|
{
|
||||||
|
@ -60,6 +60,11 @@ namespace MWMechanics
|
|||||||
mIsTurningToPlayer = turning;
|
mIsTurningToPlayer = turning;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
Misc::TimerStatus Actor::updateEngageCombatTimer(float duration)
|
||||||
|
{
|
||||||
|
return mEngageCombat.update(duration, MWBase::Environment::get().getWorld()->getPrng());
|
||||||
|
}
|
||||||
|
|
||||||
void Actor::setPositionAdjusted(bool adjusted)
|
void Actor::setPositionAdjusted(bool adjusted)
|
||||||
{
|
{
|
||||||
mPositionAdjusted = adjusted;
|
mPositionAdjusted = adjusted;
|
||||||
|
@ -43,10 +43,7 @@ namespace MWMechanics
|
|||||||
bool isTurningToPlayer() const;
|
bool isTurningToPlayer() const;
|
||||||
void setTurningToPlayer(bool turning);
|
void setTurningToPlayer(bool turning);
|
||||||
|
|
||||||
Misc::TimerStatus updateEngageCombatTimer(float duration)
|
Misc::TimerStatus updateEngageCombatTimer(float duration);
|
||||||
{
|
|
||||||
return mEngageCombat.update(duration);
|
|
||||||
}
|
|
||||||
|
|
||||||
void setPositionAdjusted(bool adjusted);
|
void setPositionAdjusted(bool adjusted);
|
||||||
bool getPositionAdjusted() const;
|
bool getPositionAdjusted() const;
|
||||||
@ -57,7 +54,7 @@ namespace MWMechanics
|
|||||||
float mTargetAngleRadians{0.f};
|
float mTargetAngleRadians{0.f};
|
||||||
GreetingState mGreetingState{Greet_None};
|
GreetingState mGreetingState{Greet_None};
|
||||||
bool mIsTurningToPlayer{false};
|
bool mIsTurningToPlayer{false};
|
||||||
Misc::DeviatingPeriodicTimer mEngageCombat{1.0f, 0.25f, Misc::Rng::deviate(0, 0.25f)};
|
Misc::DeviatingPeriodicTimer mEngageCombat{1.0f, 0.25f, Misc::Rng::deviate(0, 0.25f, MWBase::Environment::get().getWorld()->getPrng())};
|
||||||
bool mPositionAdjusted;
|
bool mPositionAdjusted;
|
||||||
};
|
};
|
||||||
|
|
||||||
|
@ -305,7 +305,7 @@ namespace MWMechanics
|
|||||||
// We chose to use the chance MW would have when run at 60 FPS with the default value of the GMST.
|
// We chose to use the chance MW would have when run at 60 FPS with the default value of the GMST.
|
||||||
const float delta = MWBase::Environment::get().getFrameDuration() * 6.f;
|
const float delta = MWBase::Environment::get().getFrameDuration() * 6.f;
|
||||||
static const float fVoiceIdleOdds = world->getStore().get<ESM::GameSetting>().find("fVoiceIdleOdds")->mValue.getFloat();
|
static const float fVoiceIdleOdds = world->getStore().get<ESM::GameSetting>().find("fVoiceIdleOdds")->mValue.getFloat();
|
||||||
if (Misc::Rng::rollProbability() * 10000.f < fVoiceIdleOdds * delta && world->getLOS(getPlayer(), actor))
|
if (Misc::Rng::rollProbability(world->getPrng()) * 10000.f < fVoiceIdleOdds * delta && world->getLOS(getPlayer(), actor))
|
||||||
MWBase::Environment::get().getDialogueManager()->say(actor, "idle");
|
MWBase::Environment::get().getDialogueManager()->say(actor, "idle");
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -80,7 +80,8 @@ bool MWMechanics::AiAvoidDoor::isStuck(const osg::Vec3f& actorPos) const
|
|||||||
|
|
||||||
void MWMechanics::AiAvoidDoor::adjustDirection()
|
void MWMechanics::AiAvoidDoor::adjustDirection()
|
||||||
{
|
{
|
||||||
mDirection = Misc::Rng::rollDice(MAX_DIRECTIONS);
|
auto& prng = MWBase::Environment::get().getWorld()->getPrng();
|
||||||
|
mDirection = Misc::Rng::rollDice(MAX_DIRECTIONS, prng);
|
||||||
}
|
}
|
||||||
|
|
||||||
float MWMechanics::AiAvoidDoor::getAdjustedAngle() const
|
float MWMechanics::AiAvoidDoor::getAdjustedAngle() const
|
||||||
|
@ -370,7 +370,8 @@ namespace MWMechanics
|
|||||||
|
|
||||||
if (!points.empty())
|
if (!points.empty())
|
||||||
{
|
{
|
||||||
ESM::Pathgrid::Point dest = points[Misc::Rng::rollDice(points.size())];
|
auto& prng = MWBase::Environment::get().getWorld()->getPrng();
|
||||||
|
ESM::Pathgrid::Point dest = points[Misc::Rng::rollDice(points.size(), prng)];
|
||||||
coords.toWorld(dest);
|
coords.toWorld(dest);
|
||||||
|
|
||||||
state = AiCombatStorage::FleeState_RunToDestination;
|
state = AiCombatStorage::FleeState_RunToDestination;
|
||||||
@ -464,8 +465,38 @@ namespace MWMechanics
|
|||||||
sequence.mPackages.push_back(std::move(package));
|
sequence.mPackages.push_back(std::move(package));
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
AiCombatStorage::AiCombatStorage() :
|
||||||
|
mAttackCooldown(0.0f),
|
||||||
|
mReaction(MWBase::Environment::get().getWorld()->getPrng()),
|
||||||
|
mTimerCombatMove(0.0f),
|
||||||
|
mReadyToAttack(false),
|
||||||
|
mAttack(false),
|
||||||
|
mAttackRange(0.0f),
|
||||||
|
mCombatMove(false),
|
||||||
|
mRotateMove(false),
|
||||||
|
mLastTargetPos(0, 0, 0),
|
||||||
|
mCell(nullptr),
|
||||||
|
mCurrentAction(),
|
||||||
|
mActionCooldown(0.0f),
|
||||||
|
mStrength(),
|
||||||
|
mForceNoShortcut(false),
|
||||||
|
mShortcutFailPos(),
|
||||||
|
mMovement(),
|
||||||
|
mFleeState(FleeState_None),
|
||||||
|
mLOS(false),
|
||||||
|
mUpdateLOSTimer(0.0f),
|
||||||
|
mFleeBlindRunTimer(0.0f),
|
||||||
|
mUseCustomDestination(false),
|
||||||
|
mCustomDestination()
|
||||||
|
{
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
void AiCombatStorage::startCombatMove(bool isDistantCombat, float distToTarget, float rangeAttack, const MWWorld::Ptr& actor, const MWWorld::Ptr& target)
|
void AiCombatStorage::startCombatMove(bool isDistantCombat, float distToTarget, float rangeAttack, const MWWorld::Ptr& actor, const MWWorld::Ptr& target)
|
||||||
{
|
{
|
||||||
|
auto& prng = MWBase::Environment::get().getWorld()->getPrng();
|
||||||
|
|
||||||
// get the range of the target's weapon
|
// get the range of the target's weapon
|
||||||
MWWorld::Ptr targetWeapon = MWWorld::Ptr();
|
MWWorld::Ptr targetWeapon = MWWorld::Ptr();
|
||||||
const MWWorld::Class& targetClass = target.getClass();
|
const MWWorld::Class& targetClass = target.getClass();
|
||||||
@ -483,7 +514,7 @@ namespace MWMechanics
|
|||||||
|
|
||||||
if (mMovement.mPosition[0] || mMovement.mPosition[1])
|
if (mMovement.mPosition[0] || mMovement.mPosition[1])
|
||||||
{
|
{
|
||||||
mTimerCombatMove = 0.1f + 0.1f * Misc::Rng::rollClosedProbability();
|
mTimerCombatMove = 0.1f + 0.1f * Misc::Rng::rollClosedProbability(prng);
|
||||||
mCombatMove = true;
|
mCombatMove = true;
|
||||||
}
|
}
|
||||||
else if (isDistantCombat)
|
else if (isDistantCombat)
|
||||||
@ -537,11 +568,11 @@ namespace MWMechanics
|
|||||||
// if actor is within range of target's weapon.
|
// if actor is within range of target's weapon.
|
||||||
if (std::abs(angleToTarget) > osg::PI / 4)
|
if (std::abs(angleToTarget) > osg::PI / 4)
|
||||||
moveDuration = 0.2f;
|
moveDuration = 0.2f;
|
||||||
else if (distToTarget <= rangeAttackOfTarget && Misc::Rng::rollClosedProbability() < 0.25)
|
else if (distToTarget <= rangeAttackOfTarget && Misc::Rng::rollClosedProbability(prng) < 0.25)
|
||||||
moveDuration = 0.1f + 0.1f * Misc::Rng::rollClosedProbability();
|
moveDuration = 0.1f + 0.1f * Misc::Rng::rollClosedProbability(prng);
|
||||||
if (moveDuration > 0)
|
if (moveDuration > 0)
|
||||||
{
|
{
|
||||||
mMovement.mPosition[0] = Misc::Rng::rollProbability() < 0.5 ? 1.0f : -1.0f; // to the left/right
|
mMovement.mPosition[0] = Misc::Rng::rollProbability(prng) < 0.5 ? 1.0f : -1.0f; // to the left/right
|
||||||
mTimerCombatMove = moveDuration;
|
mTimerCombatMove = moveDuration;
|
||||||
mCombatMove = true;
|
mCombatMove = true;
|
||||||
}
|
}
|
||||||
@ -580,7 +611,8 @@ namespace MWMechanics
|
|||||||
if (!distantCombat)
|
if (!distantCombat)
|
||||||
characterController.setAIAttackType(chooseBestAttack(weapon));
|
characterController.setAIAttackType(chooseBestAttack(weapon));
|
||||||
|
|
||||||
mStrength = Misc::Rng::rollClosedProbability();
|
auto& prng = MWBase::Environment::get().getWorld()->getPrng();
|
||||||
|
mStrength = Misc::Rng::rollClosedProbability(prng);
|
||||||
|
|
||||||
const MWWorld::ESMStore &store = MWBase::Environment::get().getWorld()->getStore();
|
const MWWorld::ESMStore &store = MWBase::Environment::get().getWorld()->getStore();
|
||||||
|
|
||||||
@ -592,11 +624,11 @@ namespace MWMechanics
|
|||||||
|
|
||||||
// Say a provoking combat phrase
|
// Say a provoking combat phrase
|
||||||
const int iVoiceAttackOdds = store.get<ESM::GameSetting>().find("iVoiceAttackOdds")->mValue.getInteger();
|
const int iVoiceAttackOdds = store.get<ESM::GameSetting>().find("iVoiceAttackOdds")->mValue.getInteger();
|
||||||
if (Misc::Rng::roll0to99() < iVoiceAttackOdds)
|
if (Misc::Rng::roll0to99(prng) < iVoiceAttackOdds)
|
||||||
{
|
{
|
||||||
MWBase::Environment::get().getDialogueManager()->say(actor, "attack");
|
MWBase::Environment::get().getDialogueManager()->say(actor, "attack");
|
||||||
}
|
}
|
||||||
mAttackCooldown = std::min(baseDelay + 0.01 * Misc::Rng::roll0to99(), baseDelay + 0.9);
|
mAttackCooldown = std::min(baseDelay + 0.01 * Misc::Rng::roll0to99(prng), baseDelay + 0.9);
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
mAttackCooldown -= AI_REACTION_TIME;
|
mAttackCooldown -= AI_REACTION_TIME;
|
||||||
@ -657,7 +689,8 @@ std::string chooseBestAttack(const ESM::Weapon* weapon)
|
|||||||
int chop = (weapon->mData.mChop[0] + weapon->mData.mChop[1])/2;
|
int chop = (weapon->mData.mChop[0] + weapon->mData.mChop[1])/2;
|
||||||
int thrust = (weapon->mData.mThrust[0] + weapon->mData.mThrust[1])/2;
|
int thrust = (weapon->mData.mThrust[0] + weapon->mData.mThrust[1])/2;
|
||||||
|
|
||||||
float roll = Misc::Rng::rollClosedProbability() * (slash + chop + thrust);
|
auto& prng = MWBase::Environment::get().getWorld()->getPrng();
|
||||||
|
float roll = Misc::Rng::rollClosedProbability(prng) * (slash + chop + thrust);
|
||||||
if(roll <= slash)
|
if(roll <= slash)
|
||||||
attackType = "slash";
|
attackType = "slash";
|
||||||
else if(roll <= (slash + thrust))
|
else if(roll <= (slash + thrust))
|
||||||
|
@ -59,29 +59,7 @@ namespace MWMechanics
|
|||||||
bool mUseCustomDestination;
|
bool mUseCustomDestination;
|
||||||
osg::Vec3f mCustomDestination;
|
osg::Vec3f mCustomDestination;
|
||||||
|
|
||||||
AiCombatStorage():
|
AiCombatStorage();
|
||||||
mAttackCooldown(0.0f),
|
|
||||||
mTimerCombatMove(0.0f),
|
|
||||||
mReadyToAttack(false),
|
|
||||||
mAttack(false),
|
|
||||||
mAttackRange(0.0f),
|
|
||||||
mCombatMove(false),
|
|
||||||
mRotateMove(false),
|
|
||||||
mLastTargetPos(0,0,0),
|
|
||||||
mCell(nullptr),
|
|
||||||
mCurrentAction(),
|
|
||||||
mActionCooldown(0.0f),
|
|
||||||
mStrength(),
|
|
||||||
mForceNoShortcut(false),
|
|
||||||
mShortcutFailPos(),
|
|
||||||
mMovement(),
|
|
||||||
mFleeState(FleeState_None),
|
|
||||||
mLOS(false),
|
|
||||||
mUpdateLOSTimer(0.0f),
|
|
||||||
mFleeBlindRunTimer(0.0f),
|
|
||||||
mUseCustomDestination(false),
|
|
||||||
mCustomDestination()
|
|
||||||
{}
|
|
||||||
|
|
||||||
void startCombatMove(bool isDistantCombat, float distToTarget, float rangeAttack, const MWWorld::Ptr& actor, const MWWorld::Ptr& target);
|
void startCombatMove(bool isDistantCombat, float distToTarget, float rangeAttack, const MWWorld::Ptr& actor, const MWWorld::Ptr& target);
|
||||||
void updateCombatMove(float duration);
|
void updateCombatMove(float duration);
|
||||||
|
@ -43,6 +43,7 @@ namespace
|
|||||||
|
|
||||||
MWMechanics::AiPackage::AiPackage(AiPackageTypeId typeId, const Options& options) :
|
MWMechanics::AiPackage::AiPackage(AiPackageTypeId typeId, const Options& options) :
|
||||||
mTypeId(typeId),
|
mTypeId(typeId),
|
||||||
|
mReaction(MWBase::Environment::get().getWorld()->getPrng()),
|
||||||
mOptions(options),
|
mOptions(options),
|
||||||
mTargetActorRefId(""),
|
mTargetActorRefId(""),
|
||||||
mTargetActorId(-1),
|
mTargetActorId(-1),
|
||||||
|
@ -13,13 +13,20 @@ namespace MWMechanics
|
|||||||
public:
|
public:
|
||||||
static constexpr float sDeviation = 0.1f;
|
static constexpr float sDeviation = 0.1f;
|
||||||
|
|
||||||
Misc::TimerStatus update(float duration) { return mImpl.update(duration); }
|
AiReactionTimer(Misc::Rng::Generator& prng)
|
||||||
|
: mPrng{ prng }
|
||||||
|
, mImpl{ AI_REACTION_TIME, sDeviation, Misc::Rng::deviate(0, sDeviation, prng) }
|
||||||
|
{
|
||||||
|
}
|
||||||
|
|
||||||
void reset() { mImpl.reset(Misc::Rng::deviate(0, sDeviation)); }
|
Misc::TimerStatus update(float duration) { return mImpl.update(duration, mPrng); }
|
||||||
|
|
||||||
|
void reset() { mImpl.reset(Misc::Rng::deviate(0, sDeviation, mPrng)); }
|
||||||
|
|
||||||
private:
|
private:
|
||||||
Misc::DeviatingPeriodicTimer mImpl {AI_REACTION_TIME, sDeviation,
|
Misc::Rng::Generator& mPrng;
|
||||||
Misc::Rng::deviate(0, sDeviation)};
|
Misc::DeviatingPeriodicTimer mImpl;
|
||||||
|
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -36,11 +36,13 @@ namespace MWMechanics
|
|||||||
{
|
{
|
||||||
AiTravel::AiTravel(float x, float y, float z, bool repeat, AiTravel*)
|
AiTravel::AiTravel(float x, float y, float z, bool repeat, AiTravel*)
|
||||||
: TypedAiPackage<AiTravel>(repeat), mX(x), mY(y), mZ(z), mHidden(false)
|
: TypedAiPackage<AiTravel>(repeat), mX(x), mY(y), mZ(z), mHidden(false)
|
||||||
|
, mDestinationCheck(MWBase::Environment::get().getWorld()->getPrng())
|
||||||
{
|
{
|
||||||
}
|
}
|
||||||
|
|
||||||
AiTravel::AiTravel(float x, float y, float z, AiInternalTravel* derived)
|
AiTravel::AiTravel(float x, float y, float z, AiInternalTravel* derived)
|
||||||
: TypedAiPackage<AiTravel>(derived), mX(x), mY(y), mZ(z), mHidden(true)
|
: TypedAiPackage<AiTravel>(derived), mX(x), mY(y), mZ(z), mHidden(true)
|
||||||
|
, mDestinationCheck(MWBase::Environment::get().getWorld()->getPrng())
|
||||||
{
|
{
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -51,6 +53,7 @@ namespace MWMechanics
|
|||||||
|
|
||||||
AiTravel::AiTravel(const ESM::AiSequence::AiTravel *travel)
|
AiTravel::AiTravel(const ESM::AiSequence::AiTravel *travel)
|
||||||
: TypedAiPackage<AiTravel>(travel->mRepeat), mX(travel->mData.mX), mY(travel->mData.mY), mZ(travel->mData.mZ), mHidden(false)
|
: TypedAiPackage<AiTravel>(travel->mRepeat), mX(travel->mData.mX), mY(travel->mData.mY), mZ(travel->mData.mZ), mHidden(false)
|
||||||
|
, mDestinationCheck(MWBase::Environment::get().getWorld()->getPrng())
|
||||||
{
|
{
|
||||||
// Hidden ESM::AiSequence::AiTravel package should be converted into MWMechanics::AiInternalTravel type
|
// Hidden ESM::AiSequence::AiTravel package should be converted into MWMechanics::AiInternalTravel type
|
||||||
assert(!travel->mHidden);
|
assert(!travel->mHidden);
|
||||||
|
@ -59,7 +59,8 @@ namespace MWMechanics
|
|||||||
|
|
||||||
osg::Vec3f getRandomPointAround(const osg::Vec3f& position, const float distance)
|
osg::Vec3f getRandomPointAround(const osg::Vec3f& position, const float distance)
|
||||||
{
|
{
|
||||||
const float randomDirection = Misc::Rng::rollClosedProbability() * 2.0f * osg::PI;
|
auto& prng = MWBase::Environment::get().getWorld()->getPrng();
|
||||||
|
const float randomDirection = Misc::Rng::rollClosedProbability(prng) * 2.0f * osg::PI;
|
||||||
osg::Matrixf rotation;
|
osg::Matrixf rotation;
|
||||||
rotation.makeRotate(randomDirection, osg::Vec3f(0.0, 0.0, 1.0));
|
rotation.makeRotate(randomDirection, osg::Vec3f(0.0, 0.0, 1.0));
|
||||||
return position + osg::Vec3f(distance, 0.0, 0.0) * rotation;
|
return position + osg::Vec3f(distance, 0.0, 0.0) * rotation;
|
||||||
@ -102,6 +103,22 @@ namespace MWMechanics
|
|||||||
{
|
{
|
||||||
return std::vector<unsigned char>(std::begin(idle), std::end(idle));
|
return std::vector<unsigned char>(std::begin(idle), std::end(idle));
|
||||||
}
|
}
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
AiWanderStorage::AiWanderStorage() :
|
||||||
|
mState(Wander_ChooseAction),
|
||||||
|
mIsWanderingManually(false),
|
||||||
|
mCanWanderAlongPathGrid(true),
|
||||||
|
mIdleAnimation(0),
|
||||||
|
mBadIdles(),
|
||||||
|
mPopulateAvailableNodes(true),
|
||||||
|
mAllowedNodes(),
|
||||||
|
mTrimCurrentNode(false),
|
||||||
|
mCheckIdlePositionTimer(0),
|
||||||
|
mStuckCount(0),
|
||||||
|
mReaction(MWBase::Environment::get().getWorld()->getPrng())
|
||||||
|
{
|
||||||
}
|
}
|
||||||
|
|
||||||
AiWander::AiWander(int distance, int duration, int timeOfDay, const std::vector<unsigned char>& idle, bool repeat):
|
AiWander::AiWander(int distance, int duration, int timeOfDay, const std::vector<unsigned char>& idle, bool repeat):
|
||||||
@ -250,9 +267,10 @@ namespace MWMechanics
|
|||||||
getAllowedNodes(actor, actor.getCell()->getCell(), storage);
|
getAllowedNodes(actor, actor.getCell()->getCell(), storage);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
auto& prng = MWBase::Environment::get().getWorld()->getPrng();
|
||||||
if (canActorMoveByZAxis(actor) && mDistance > 0) {
|
if (canActorMoveByZAxis(actor) && mDistance > 0) {
|
||||||
// Typically want to idle for a short time before the next wander
|
// Typically want to idle for a short time before the next wander
|
||||||
if (Misc::Rng::rollDice(100) >= 92 && storage.mState != AiWanderStorage::Wander_Walking) {
|
if (Misc::Rng::rollDice(100, prng) >= 92 && storage.mState != AiWanderStorage::Wander_Walking) {
|
||||||
wanderNearStart(actor, storage, mDistance);
|
wanderNearStart(actor, storage, mDistance);
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -262,7 +280,7 @@ namespace MWMechanics
|
|||||||
// randomly idle or wander near spawn point
|
// randomly idle or wander near spawn point
|
||||||
else if(storage.mAllowedNodes.empty() && mDistance > 0 && !storage.mIsWanderingManually) {
|
else if(storage.mAllowedNodes.empty() && mDistance > 0 && !storage.mIsWanderingManually) {
|
||||||
// Typically want to idle for a short time before the next wander
|
// Typically want to idle for a short time before the next wander
|
||||||
if (Misc::Rng::rollDice(100) >= 96) {
|
if (Misc::Rng::rollDice(100, prng) >= 96) {
|
||||||
wanderNearStart(actor, storage, mDistance);
|
wanderNearStart(actor, storage, mDistance);
|
||||||
} else {
|
} else {
|
||||||
storage.setState(AiWanderStorage::Wander_IdleNow);
|
storage.setState(AiWanderStorage::Wander_IdleNow);
|
||||||
@ -330,10 +348,12 @@ namespace MWMechanics
|
|||||||
const auto navigator = world->getNavigator();
|
const auto navigator = world->getNavigator();
|
||||||
const auto navigatorFlags = getNavigatorFlags(actor);
|
const auto navigatorFlags = getNavigatorFlags(actor);
|
||||||
const auto areaCosts = getAreaCosts(actor);
|
const auto areaCosts = getAreaCosts(actor);
|
||||||
|
auto& prng = MWBase::Environment::get().getWorld()->getPrng();
|
||||||
|
|
||||||
do {
|
do {
|
||||||
|
|
||||||
// Determine a random location within radius of original position
|
// Determine a random location within radius of original position
|
||||||
const float wanderRadius = (0.2f + Misc::Rng::rollClosedProbability() * 0.8f) * wanderDistance;
|
const float wanderRadius = (0.2f + Misc::Rng::rollClosedProbability(prng) * 0.8f) * wanderDistance;
|
||||||
if (!isWaterCreature && !isFlyingCreature)
|
if (!isWaterCreature && !isFlyingCreature)
|
||||||
{
|
{
|
||||||
// findRandomPointAroundCircle uses wanderDistance as limit for random and not as exact distance
|
// findRandomPointAroundCircle uses wanderDistance as limit for random and not as exact distance
|
||||||
@ -544,7 +564,8 @@ namespace MWMechanics
|
|||||||
|
|
||||||
void AiWander::setPathToAnAllowedNode(const MWWorld::Ptr& actor, AiWanderStorage& storage, const ESM::Position& actorPos)
|
void AiWander::setPathToAnAllowedNode(const MWWorld::Ptr& actor, AiWanderStorage& storage, const ESM::Position& actorPos)
|
||||||
{
|
{
|
||||||
unsigned int randNode = Misc::Rng::rollDice(storage.mAllowedNodes.size());
|
auto& prng = MWBase::Environment::get().getWorld()->getPrng();
|
||||||
|
unsigned int randNode = Misc::Rng::rollDice(storage.mAllowedNodes.size(), prng);
|
||||||
ESM::Pathgrid::Point dest(storage.mAllowedNodes[randNode]);
|
ESM::Pathgrid::Point dest(storage.mAllowedNodes[randNode]);
|
||||||
|
|
||||||
ToWorldCoordinates(dest, actor.getCell()->getCell());
|
ToWorldCoordinates(dest, actor.getCell()->getCell());
|
||||||
@ -650,11 +671,11 @@ namespace MWMechanics
|
|||||||
|
|
||||||
for(unsigned int counter = 0; counter < mIdle.size(); counter++)
|
for(unsigned int counter = 0; counter < mIdle.size(); counter++)
|
||||||
{
|
{
|
||||||
static float fIdleChanceMultiplier = MWBase::Environment::get().getWorld()->getStore()
|
MWBase::World* world = MWBase::Environment::get().getWorld();
|
||||||
.get<ESM::GameSetting>().find("fIdleChanceMultiplier")->mValue.getFloat();
|
static float fIdleChanceMultiplier = world->getStore().get<ESM::GameSetting>().find("fIdleChanceMultiplier")->mValue.getFloat();
|
||||||
|
|
||||||
unsigned short idleChance = static_cast<unsigned short>(fIdleChanceMultiplier * mIdle[counter]);
|
unsigned short idleChance = static_cast<unsigned short>(fIdleChanceMultiplier * mIdle[counter]);
|
||||||
unsigned short randSelect = (int)(Misc::Rng::rollProbability() * int(100 / fIdleChanceMultiplier));
|
unsigned short randSelect = (int)(Misc::Rng::rollProbability(world->getPrng()) * int(100 / fIdleChanceMultiplier));
|
||||||
if(randSelect < idleChance && randSelect > idleRoll)
|
if(randSelect < idleChance && randSelect > idleRoll)
|
||||||
{
|
{
|
||||||
selectedAnimation = counter + GroupIndex_MinIdle;
|
selectedAnimation = counter + GroupIndex_MinIdle;
|
||||||
@ -678,7 +699,8 @@ namespace MWMechanics
|
|||||||
if (storage.mAllowedNodes.empty())
|
if (storage.mAllowedNodes.empty())
|
||||||
return;
|
return;
|
||||||
|
|
||||||
int index = Misc::Rng::rollDice(storage.mAllowedNodes.size());
|
auto& prng = MWBase::Environment::get().getWorld()->getPrng();
|
||||||
|
int index = Misc::Rng::rollDice(storage.mAllowedNodes.size(), prng);
|
||||||
ESM::Pathgrid::Point dest = storage.mAllowedNodes[index];
|
ESM::Pathgrid::Point dest = storage.mAllowedNodes[index];
|
||||||
ESM::Pathgrid::Point worldDest = dest;
|
ESM::Pathgrid::Point worldDest = dest;
|
||||||
ToWorldCoordinates(worldDest, actor.getCell()->getCell());
|
ToWorldCoordinates(worldDest, actor.getCell()->getCell());
|
||||||
@ -700,7 +722,7 @@ namespace MWMechanics
|
|||||||
// AI will try to move the NPC towards every neighboring node until suitable place will be found
|
// AI will try to move the NPC towards every neighboring node until suitable place will be found
|
||||||
for (int i = 0; i < initialSize; i++)
|
for (int i = 0; i < initialSize; i++)
|
||||||
{
|
{
|
||||||
int randomIndex = Misc::Rng::rollDice(points.size());
|
int randomIndex = Misc::Rng::rollDice(points.size(), prng);
|
||||||
ESM::Pathgrid::Point connDest = points[randomIndex];
|
ESM::Pathgrid::Point connDest = points[randomIndex];
|
||||||
|
|
||||||
// add an offset towards random neighboring node
|
// add an offset towards random neighboring node
|
||||||
|
@ -55,18 +55,7 @@ namespace MWMechanics
|
|||||||
float mCheckIdlePositionTimer;
|
float mCheckIdlePositionTimer;
|
||||||
int mStuckCount;
|
int mStuckCount;
|
||||||
|
|
||||||
AiWanderStorage():
|
AiWanderStorage();
|
||||||
mState(Wander_ChooseAction),
|
|
||||||
mIsWanderingManually(false),
|
|
||||||
mCanWanderAlongPathGrid(true),
|
|
||||||
mIdleAnimation(0),
|
|
||||||
mBadIdles(),
|
|
||||||
mPopulateAvailableNodes(true),
|
|
||||||
mAllowedNodes(),
|
|
||||||
mTrimCurrentNode(false),
|
|
||||||
mCheckIdlePositionTimer(0),
|
|
||||||
mStuckCount(0)
|
|
||||||
{};
|
|
||||||
|
|
||||||
void setState(const WanderState wanderState, const bool isManualWander = false)
|
void setState(const WanderState wanderState, const bool isManualWander = false)
|
||||||
{
|
{
|
||||||
|
@ -289,7 +289,8 @@ void MWMechanics::Alchemy::addPotion (const std::string& name)
|
|||||||
|
|
||||||
newRecord.mName = name;
|
newRecord.mName = name;
|
||||||
|
|
||||||
int index = Misc::Rng::rollDice(6);
|
auto& prng = MWBase::Environment::get().getWorld()->getPrng();
|
||||||
|
int index = Misc::Rng::rollDice(6, prng);
|
||||||
assert (index>=0 && index<6);
|
assert (index>=0 && index<6);
|
||||||
|
|
||||||
static const char *meshes[] = { "standard", "bargain", "cheap", "fresh", "exclusive", "quality" };
|
static const char *meshes[] = { "standard", "bargain", "cheap", "fresh", "exclusive", "quality" };
|
||||||
@ -527,8 +528,8 @@ MWMechanics::Alchemy::Result MWMechanics::Alchemy::createSingle ()
|
|||||||
removeIngredients();
|
removeIngredients();
|
||||||
return Result_RandomFailure;
|
return Result_RandomFailure;
|
||||||
}
|
}
|
||||||
|
auto& prng = MWBase::Environment::get().getWorld()->getPrng();
|
||||||
if (getAlchemyFactor() < Misc::Rng::roll0to99())
|
if (getAlchemyFactor() < Misc::Rng::roll0to99(prng))
|
||||||
{
|
{
|
||||||
removeIngredients();
|
removeIngredients();
|
||||||
return Result_RandomFailure;
|
return Result_RandomFailure;
|
||||||
|
@ -193,11 +193,13 @@ public:
|
|||||||
|
|
||||||
std::string CharacterController::chooseRandomGroup (const std::string& prefix, int* num) const
|
std::string CharacterController::chooseRandomGroup (const std::string& prefix, int* num) const
|
||||||
{
|
{
|
||||||
|
auto& prng = MWBase::Environment::get().getWorld()->getPrng();
|
||||||
|
|
||||||
int numAnims=0;
|
int numAnims=0;
|
||||||
while (mAnimation->hasAnimation(prefix + std::to_string(numAnims+1)))
|
while (mAnimation->hasAnimation(prefix + std::to_string(numAnims+1)))
|
||||||
++numAnims;
|
++numAnims;
|
||||||
|
|
||||||
int roll = Misc::Rng::rollDice(numAnims) + 1; // [1, numAnims]
|
int roll = Misc::Rng::rollDice(numAnims, prng) + 1; // [1, numAnims]
|
||||||
if (num)
|
if (num)
|
||||||
*num = roll;
|
*num = roll;
|
||||||
return prefix + std::to_string(roll);
|
return prefix + std::to_string(roll);
|
||||||
@ -209,12 +211,13 @@ void CharacterController::refreshHitRecoilAnims(CharacterState& idle)
|
|||||||
bool knockdown = mPtr.getClass().getCreatureStats(mPtr).getKnockedDown();
|
bool knockdown = mPtr.getClass().getCreatureStats(mPtr).getKnockedDown();
|
||||||
bool block = mPtr.getClass().getCreatureStats(mPtr).getBlock();
|
bool block = mPtr.getClass().getCreatureStats(mPtr).getBlock();
|
||||||
bool isSwimming = MWBase::Environment::get().getWorld()->isSwimming(mPtr);
|
bool isSwimming = MWBase::Environment::get().getWorld()->isSwimming(mPtr);
|
||||||
|
auto& prng = MWBase::Environment::get().getWorld()->getPrng();
|
||||||
if(mHitState == CharState_None)
|
if(mHitState == CharState_None)
|
||||||
{
|
{
|
||||||
if ((mPtr.getClass().getCreatureStats(mPtr).getFatigue().getCurrent() < 0
|
if ((mPtr.getClass().getCreatureStats(mPtr).getFatigue().getCurrent() < 0
|
||||||
|| mPtr.getClass().getCreatureStats(mPtr).getFatigue().getBase() == 0))
|
|| mPtr.getClass().getCreatureStats(mPtr).getFatigue().getBase() == 0))
|
||||||
{
|
{
|
||||||
mTimeUntilWake = Misc::Rng::rollClosedProbability() * 2 + 1; // Wake up after 1 to 3 seconds
|
mTimeUntilWake = Misc::Rng::rollClosedProbability(prng) * 2 + 1; // Wake up after 1 to 3 seconds
|
||||||
if (isSwimming && mAnimation->hasAnimation("swimknockout"))
|
if (isSwimming && mAnimation->hasAnimation("swimknockout"))
|
||||||
{
|
{
|
||||||
mHitState = CharState_SwimKnockOut;
|
mHitState = CharState_SwimKnockOut;
|
||||||
@ -678,7 +681,8 @@ void CharacterController::refreshIdleAnims(const std::string& weapShortGroup, Ch
|
|||||||
|
|
||||||
// play until the Loop Stop key 2 to 5 times, then play until the Stop key
|
// play until the Loop Stop key 2 to 5 times, then play until the Stop key
|
||||||
// this replicates original engine behavior for the "Idle1h" 1st-person animation
|
// this replicates original engine behavior for the "Idle1h" 1st-person animation
|
||||||
numLoops = 1 + Misc::Rng::rollDice(4);
|
auto& prng = MWBase::Environment::get().getWorld()->getPrng();
|
||||||
|
numLoops = 1 + Misc::Rng::rollDice(4, prng);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -1131,6 +1135,8 @@ bool CharacterController::updateCarriedLeftVisible(const int weaptype) const
|
|||||||
|
|
||||||
bool CharacterController::updateState(CharacterState idle)
|
bool CharacterController::updateState(CharacterState idle)
|
||||||
{
|
{
|
||||||
|
auto& prng = MWBase::Environment::get().getWorld()->getPrng();
|
||||||
|
|
||||||
const MWWorld::Class &cls = mPtr.getClass();
|
const MWWorld::Class &cls = mPtr.getClass();
|
||||||
CreatureStats &stats = cls.getCreatureStats(mPtr);
|
CreatureStats &stats = cls.getCreatureStats(mPtr);
|
||||||
int weaptype = ESM::Weapon::None;
|
int weaptype = ESM::Weapon::None;
|
||||||
@ -1288,7 +1294,7 @@ bool CharacterController::updateState(CharacterState idle)
|
|||||||
if(isWerewolf)
|
if(isWerewolf)
|
||||||
{
|
{
|
||||||
const MWWorld::ESMStore &store = MWBase::Environment::get().getWorld()->getStore();
|
const MWWorld::ESMStore &store = MWBase::Environment::get().getWorld()->getStore();
|
||||||
const ESM::Sound *sound = store.get<ESM::Sound>().searchRandom("WolfEquip");
|
const ESM::Sound *sound = store.get<ESM::Sound>().searchRandom("WolfEquip", prng);
|
||||||
if(sound)
|
if(sound)
|
||||||
{
|
{
|
||||||
MWBase::SoundManager *sndMgr = MWBase::Environment::get().getSoundManager();
|
MWBase::SoundManager *sndMgr = MWBase::Environment::get().getSoundManager();
|
||||||
@ -1563,7 +1569,7 @@ bool CharacterController::updateState(CharacterState idle)
|
|||||||
mUpperBodyState = UpperCharState_StartToMinAttack;
|
mUpperBodyState = UpperCharState_StartToMinAttack;
|
||||||
if (isRandomAttackAnimation(mCurrentWeapon))
|
if (isRandomAttackAnimation(mCurrentWeapon))
|
||||||
{
|
{
|
||||||
mAttackStrength = std::min(1.f, 0.1f + Misc::Rng::rollClosedProbability());
|
mAttackStrength = std::min(1.f, 0.1f + Misc::Rng::rollClosedProbability(prng));
|
||||||
playSwishSound(0.0f);
|
playSwishSound(0.0f);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -1596,7 +1602,7 @@ bool CharacterController::updateState(CharacterState idle)
|
|||||||
// most creatures don't actually have an attack wind-up animation, so use a uniform random value
|
// 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)
|
// (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.
|
// 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 + Misc::Rng::rollClosedProbability());
|
attackStrength = std::min(1.f, 0.1f + Misc::Rng::rollClosedProbability(prng));
|
||||||
}
|
}
|
||||||
|
|
||||||
if(weapclass != ESM::WeaponType::Ranged && weapclass != ESM::WeaponType::Thrown)
|
if(weapclass != ESM::WeaponType::Ranged && weapclass != ESM::WeaponType::Thrown)
|
||||||
@ -1606,7 +1612,7 @@ bool CharacterController::updateState(CharacterState idle)
|
|||||||
if(isWerewolf)
|
if(isWerewolf)
|
||||||
{
|
{
|
||||||
const MWWorld::ESMStore &store = MWBase::Environment::get().getWorld()->getStore();
|
const MWWorld::ESMStore &store = MWBase::Environment::get().getWorld()->getStore();
|
||||||
const ESM::Sound *sound = store.get<ESM::Sound>().searchRandom("WolfSwing");
|
const ESM::Sound *sound = store.get<ESM::Sound>().searchRandom("WolfSwing", prng);
|
||||||
if(sound)
|
if(sound)
|
||||||
sndMgr->playSound3D(mPtr, sound->mId, 1.0f, 1.0f);
|
sndMgr->playSound3D(mPtr, sound->mId, 1.0f, 1.0f);
|
||||||
}
|
}
|
||||||
@ -2771,7 +2777,8 @@ void CharacterController::setAIAttackType(const std::string& attackType)
|
|||||||
|
|
||||||
void CharacterController::setAttackTypeRandomly(std::string& attackType)
|
void CharacterController::setAttackTypeRandomly(std::string& attackType)
|
||||||
{
|
{
|
||||||
float random = Misc::Rng::rollProbability();
|
MWBase::World* world = MWBase::Environment::get().getWorld();
|
||||||
|
float random = Misc::Rng::rollProbability(world->getPrng());
|
||||||
if (random >= 2/3.f)
|
if (random >= 2/3.f)
|
||||||
attackType = "thrust";
|
attackType = "thrust";
|
||||||
else if (random >= 1/3.f)
|
else if (random >= 1/3.f)
|
||||||
|
@ -117,7 +117,8 @@ namespace MWMechanics
|
|||||||
const int iBlockMinChance = gmst.find("iBlockMinChance")->mValue.getInteger();
|
const int iBlockMinChance = gmst.find("iBlockMinChance")->mValue.getInteger();
|
||||||
int x = std::clamp<int>(blockerTerm - attackerTerm, iBlockMinChance, iBlockMaxChance);
|
int x = std::clamp<int>(blockerTerm - attackerTerm, iBlockMinChance, iBlockMaxChance);
|
||||||
|
|
||||||
if (Misc::Rng::roll0to99() < x)
|
auto& prng = MWBase::Environment::get().getWorld()->getPrng();
|
||||||
|
if (Misc::Rng::roll0to99(prng) < x)
|
||||||
{
|
{
|
||||||
// Reduce shield durability by incoming damage
|
// Reduce shield durability by incoming damage
|
||||||
int shieldhealth = shield->getClass().getItemHealth(*shield);
|
int shieldhealth = shield->getClass().getItemHealth(*shield);
|
||||||
@ -212,7 +213,7 @@ namespace MWMechanics
|
|||||||
|
|
||||||
int skillValue = attacker.getClass().getSkill(attacker, weaponSkill);
|
int skillValue = attacker.getClass().getSkill(attacker, weaponSkill);
|
||||||
|
|
||||||
if (Misc::Rng::roll0to99() >= getHitChance(attacker, victim, skillValue))
|
if (Misc::Rng::roll0to99(world->getPrng()) >= getHitChance(attacker, victim, skillValue))
|
||||||
{
|
{
|
||||||
victim.getClass().onHit(victim, damage, false, projectile, attacker, osg::Vec3f(), false);
|
victim.getClass().onHit(victim, damage, false, projectile, attacker, osg::Vec3f(), false);
|
||||||
MWMechanics::reduceWeaponCondition(damage, false, weapon, attacker);
|
MWMechanics::reduceWeaponCondition(damage, false, weapon, attacker);
|
||||||
@ -262,7 +263,7 @@ namespace MWMechanics
|
|||||||
if (victim != getPlayer() && !appliedEnchantment)
|
if (victim != getPlayer() && !appliedEnchantment)
|
||||||
{
|
{
|
||||||
float fProjectileThrownStoreChance = gmst.find("fProjectileThrownStoreChance")->mValue.getFloat();
|
float fProjectileThrownStoreChance = gmst.find("fProjectileThrownStoreChance")->mValue.getFloat();
|
||||||
if (Misc::Rng::rollProbability() < fProjectileThrownStoreChance / 100.f)
|
if (Misc::Rng::rollProbability(world->getPrng()) < fProjectileThrownStoreChance / 100.f)
|
||||||
victim.getClass().getContainerStore(victim).add(projectile, 1, victim);
|
victim.getClass().getContainerStore(victim).add(projectile, 1, victim);
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -315,6 +316,7 @@ namespace MWMechanics
|
|||||||
bool godmode = attacker == getPlayer() && MWBase::Environment::get().getWorld()->getGodModeState();
|
bool godmode = attacker == getPlayer() && MWBase::Environment::get().getWorld()->getGodModeState();
|
||||||
if (godmode)
|
if (godmode)
|
||||||
return;
|
return;
|
||||||
|
auto& prng = MWBase::Environment::get().getWorld()->getPrng();
|
||||||
for (int i=0; i<3; ++i)
|
for (int i=0; i<3; ++i)
|
||||||
{
|
{
|
||||||
float magnitude = victim.getClass().getCreatureStats(victim).getMagicEffects().get(ESM::MagicEffect::FireShield+i).getMagnitude();
|
float magnitude = victim.getClass().getCreatureStats(victim).getMagicEffects().get(ESM::MagicEffect::FireShield+i).getMagnitude();
|
||||||
@ -334,7 +336,7 @@ namespace MWMechanics
|
|||||||
|
|
||||||
saveTerm *= 1.25f * normalisedFatigue;
|
saveTerm *= 1.25f * normalisedFatigue;
|
||||||
|
|
||||||
float x = std::max(0.f, saveTerm - Misc::Rng::roll0to99());
|
float x = std::max(0.f, saveTerm - Misc::Rng::roll0to99(prng));
|
||||||
|
|
||||||
int element = ESM::MagicEffect::FireDamage;
|
int element = ESM::MagicEffect::FireDamage;
|
||||||
if (i == 1)
|
if (i == 1)
|
||||||
@ -444,7 +446,8 @@ namespace MWMechanics
|
|||||||
MWBase::SoundManager *sndMgr = MWBase::Environment::get().getSoundManager();
|
MWBase::SoundManager *sndMgr = MWBase::Environment::get().getSoundManager();
|
||||||
if(isWerewolf)
|
if(isWerewolf)
|
||||||
{
|
{
|
||||||
const ESM::Sound *sound = store.get<ESM::Sound>().searchRandom("WolfHit");
|
auto& prng = MWBase::Environment::get().getWorld()->getPrng();
|
||||||
|
const ESM::Sound *sound = store.get<ESM::Sound>().searchRandom("WolfHit", prng);
|
||||||
if(sound)
|
if(sound)
|
||||||
sndMgr->playSound3D(victim, sound->mId, 1.0f, 1.0f);
|
sndMgr->playSound3D(victim, sound->mId, 1.0f, 1.0f);
|
||||||
}
|
}
|
||||||
|
@ -52,7 +52,8 @@ namespace MWMechanics
|
|||||||
continue;
|
continue;
|
||||||
|
|
||||||
int x = static_cast<int>(fDiseaseXferChance * 100 * resist);
|
int x = static_cast<int>(fDiseaseXferChance * 100 * resist);
|
||||||
if (Misc::Rng::rollDice(10000) < x)
|
auto& prng = MWBase::Environment::get().getWorld()->getPrng();
|
||||||
|
if (Misc::Rng::rollDice(10000, prng) < x)
|
||||||
{
|
{
|
||||||
// Contracted disease!
|
// Contracted disease!
|
||||||
actor.getClass().getCreatureStats(actor).getSpells().add(spell);
|
actor.getClass().getCreatureStats(actor).getSpells().add(spell);
|
||||||
|
@ -76,7 +76,8 @@ namespace MWMechanics
|
|||||||
|
|
||||||
if(mSelfEnchanting)
|
if(mSelfEnchanting)
|
||||||
{
|
{
|
||||||
if(getEnchantChance() <= (Misc::Rng::roll0to99()))
|
auto& prng = MWBase::Environment::get().getWorld()->getPrng();
|
||||||
|
if(getEnchantChance() <= (Misc::Rng::roll0to99(prng)))
|
||||||
return false;
|
return false;
|
||||||
|
|
||||||
mEnchanter.getClass().skillUsageSucceeded (mEnchanter, ESM::Skill::Enchant, 2);
|
mEnchanter.getClass().skillUsageSucceeded (mEnchanter, ESM::Skill::Enchant, 2);
|
||||||
|
@ -19,7 +19,7 @@ namespace MWMechanics
|
|||||||
{
|
{
|
||||||
|
|
||||||
/// @return ID of resulting item, or empty if none
|
/// @return ID of resulting item, or empty if none
|
||||||
inline std::string getLevelledItem (const ESM::LevelledListBase* levItem, bool creature, Misc::Rng::Generator& prng = Misc::Rng::getGenerator())
|
inline std::string getLevelledItem (const ESM::LevelledListBase* levItem, bool creature, Misc::Rng::Generator& prng)
|
||||||
{
|
{
|
||||||
const std::vector<ESM::LevelledListBase::LevelItem>& items = levItem->mList;
|
const std::vector<ESM::LevelledListBase::LevelItem>& items = levItem->mList;
|
||||||
|
|
||||||
|
@ -651,7 +651,8 @@ namespace MWMechanics
|
|||||||
float x = 0;
|
float x = 0;
|
||||||
float y = 0;
|
float y = 0;
|
||||||
|
|
||||||
int roll = Misc::Rng::roll0to99();
|
auto& prng = MWBase::Environment::get().getWorld()->getPrng();
|
||||||
|
int roll = Misc::Rng::roll0to99(prng);
|
||||||
|
|
||||||
if (type == PT_Admire)
|
if (type == PT_Admire)
|
||||||
{
|
{
|
||||||
@ -1570,8 +1571,8 @@ namespace MWMechanics
|
|||||||
}
|
}
|
||||||
|
|
||||||
float target = x - y;
|
float target = x - y;
|
||||||
|
auto& prng = MWBase::Environment::get().getWorld()->getPrng();
|
||||||
return (Misc::Rng::roll0to99() >= target);
|
return (Misc::Rng::roll0to99(prng) >= target);
|
||||||
}
|
}
|
||||||
|
|
||||||
void MechanicsManager::startCombat(const MWWorld::Ptr &ptr, const MWWorld::Ptr &target)
|
void MechanicsManager::startCombat(const MWWorld::Ptr &ptr, const MWWorld::Ptr &target)
|
||||||
|
@ -41,7 +41,8 @@ namespace MWMechanics
|
|||||||
int iPickMaxChance = MWBase::Environment::get().getWorld()->getStore().get<ESM::GameSetting>()
|
int iPickMaxChance = MWBase::Environment::get().getWorld()->getStore().get<ESM::GameSetting>()
|
||||||
.find("iPickMaxChance")->mValue.getInteger();
|
.find("iPickMaxChance")->mValue.getInteger();
|
||||||
|
|
||||||
int roll = Misc::Rng::roll0to99();
|
auto& prng = MWBase::Environment::get().getWorld()->getPrng();
|
||||||
|
int roll = Misc::Rng::roll0to99(prng);
|
||||||
if (t < pcSneak / iPickMinChance)
|
if (t < pcSneak / iPickMinChance)
|
||||||
{
|
{
|
||||||
return (roll > int(pcSneak / iPickMinChance));
|
return (roll > int(pcSneak / iPickMinChance));
|
||||||
|
@ -49,7 +49,8 @@ bool rechargeItem(const MWWorld::Ptr &item, const MWWorld::Ptr &gem)
|
|||||||
intelligenceTerm = 1;
|
intelligenceTerm = 1;
|
||||||
|
|
||||||
float x = (player.getClass().getSkill(player, ESM::Skill::Enchant) + intelligenceTerm + luckTerm) * stats.getFatigueTerm();
|
float x = (player.getClass().getSkill(player, ESM::Skill::Enchant) + intelligenceTerm + luckTerm) * stats.getFatigueTerm();
|
||||||
int roll = Misc::Rng::roll0to99();
|
auto& prng = MWBase::Environment::get().getWorld()->getPrng();
|
||||||
|
int roll = Misc::Rng::roll0to99(prng);
|
||||||
if (roll < x)
|
if (roll < x)
|
||||||
{
|
{
|
||||||
std::string soul = gem.getCellRef().getSoul();
|
std::string soul = gem.getCellRef().getSoul();
|
||||||
|
@ -44,7 +44,8 @@ void Repair::repair(const MWWorld::Ptr &itemToRepair)
|
|||||||
|
|
||||||
float x = (0.1f * pcStrength + 0.1f * pcLuck + armorerSkill) * fatigueTerm;
|
float x = (0.1f * pcStrength + 0.1f * pcLuck + armorerSkill) * fatigueTerm;
|
||||||
|
|
||||||
int roll = Misc::Rng::roll0to99();
|
auto& prng = MWBase::Environment::get().getWorld()->getPrng();
|
||||||
|
int roll = Misc::Rng::roll0to99(prng);
|
||||||
if (roll <= x)
|
if (roll <= x)
|
||||||
{
|
{
|
||||||
int y = static_cast<int>(fRepairAmountMult * toolQuality * roll);
|
int y = static_cast<int>(fRepairAmountMult * toolQuality * roll);
|
||||||
|
@ -54,7 +54,8 @@ namespace MWMechanics
|
|||||||
resultMessage = "#{sLockImpossible}";
|
resultMessage = "#{sLockImpossible}";
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
if (Misc::Rng::roll0to99() <= x)
|
auto& prng = MWBase::Environment::get().getWorld()->getPrng();
|
||||||
|
if (Misc::Rng::roll0to99(prng) <= x)
|
||||||
{
|
{
|
||||||
lock.getCellRef().unlock();
|
lock.getCellRef().unlock();
|
||||||
resultMessage = "#{sLockSuccess}";
|
resultMessage = "#{sLockSuccess}";
|
||||||
@ -98,7 +99,8 @@ namespace MWMechanics
|
|||||||
resultMessage = "#{sTrapImpossible}";
|
resultMessage = "#{sTrapImpossible}";
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
if (Misc::Rng::roll0to99() <= x)
|
auto& prng = MWBase::Environment::get().getWorld()->getPrng();
|
||||||
|
if (Misc::Rng::roll0to99(prng) <= x)
|
||||||
{
|
{
|
||||||
trap.getCellRef().setTrap("");
|
trap.getCellRef().setTrap("");
|
||||||
|
|
||||||
|
@ -87,7 +87,8 @@ namespace MWMechanics
|
|||||||
: ESM::MagicEffect::ResistBlightDisease;
|
: ESM::MagicEffect::ResistBlightDisease;
|
||||||
float x = target.getClass().getCreatureStats(target).getMagicEffects().get(requiredResistance).getMagnitude();
|
float x = target.getClass().getCreatureStats(target).getMagicEffects().get(requiredResistance).getMagnitude();
|
||||||
|
|
||||||
if (Misc::Rng::roll0to99() <= x)
|
auto& prng = MWBase::Environment::get().getWorld()->getPrng();
|
||||||
|
if (Misc::Rng::roll0to99(prng) <= x)
|
||||||
{
|
{
|
||||||
// Fully resisted, show message
|
// Fully resisted, show message
|
||||||
if (target == getPlayer())
|
if (target == getPlayer())
|
||||||
@ -339,7 +340,8 @@ namespace MWMechanics
|
|||||||
|
|
||||||
// Check success
|
// Check success
|
||||||
float successChance = getSpellSuccessChance(spell, mCaster, nullptr, true, false);
|
float successChance = getSpellSuccessChance(spell, mCaster, nullptr, true, false);
|
||||||
if (Misc::Rng::roll0to99() >= successChance)
|
auto& prng = MWBase::Environment::get().getWorld()->getPrng();
|
||||||
|
if (Misc::Rng::roll0to99(prng) >= successChance)
|
||||||
{
|
{
|
||||||
if (mCaster == getPlayer())
|
if (mCaster == getPlayer())
|
||||||
MWBase::Environment::get().getWindowManager()->messageBox("#{sMagicSkillFail}");
|
MWBase::Environment::get().getWindowManager()->messageBox("#{sMagicSkillFail}");
|
||||||
@ -403,7 +405,8 @@ namespace MWMechanics
|
|||||||
+ 0.1f * creatureStats.getAttribute (ESM::Attribute::Luck).getModified())
|
+ 0.1f * creatureStats.getAttribute (ESM::Attribute::Luck).getModified())
|
||||||
* creatureStats.getFatigueTerm();
|
* creatureStats.getFatigueTerm();
|
||||||
|
|
||||||
int roll = Misc::Rng::roll0to99();
|
auto& prng = MWBase::Environment::get().getWorld()->getPrng();
|
||||||
|
int roll = Misc::Rng::roll0to99(prng);
|
||||||
if (roll > x)
|
if (roll > x)
|
||||||
{
|
{
|
||||||
// "X has no effect on you"
|
// "X has no effect on you"
|
||||||
|
@ -35,7 +35,8 @@ namespace
|
|||||||
{
|
{
|
||||||
if(effect.mMinMagnitude == effect.mMaxMagnitude)
|
if(effect.mMinMagnitude == effect.mMaxMagnitude)
|
||||||
return effect.mMinMagnitude;
|
return effect.mMinMagnitude;
|
||||||
return effect.mMinMagnitude + Misc::Rng::rollDice(effect.mMaxMagnitude - effect.mMinMagnitude + 1);
|
auto& prng = MWBase::Environment::get().getWorld()->getPrng();
|
||||||
|
return effect.mMinMagnitude + Misc::Rng::rollDice(effect.mMaxMagnitude - effect.mMinMagnitude + 1, prng);
|
||||||
}
|
}
|
||||||
|
|
||||||
void modifyAiSetting(const MWWorld::Ptr& target, const ESM::ActiveEffect& effect, ESM::MagicEffect::Effects creatureEffect, MWMechanics::CreatureStats::AiSetting setting, float magnitude, bool& invalid)
|
void modifyAiSetting(const MWWorld::Ptr& target, const ESM::ActiveEffect& effect, ESM::MagicEffect::Effects creatureEffect, MWMechanics::CreatureStats::AiSetting setting, float magnitude, bool& invalid)
|
||||||
@ -305,6 +306,7 @@ namespace
|
|||||||
bool canAbsorb = !(effect.mFlags & ESM::ActiveEffect::Flag_Ignore_SpellAbsorption) && magnitudes.get(ESM::MagicEffect::SpellAbsorption).getMagnitude() > 0.f;
|
bool canAbsorb = !(effect.mFlags & ESM::ActiveEffect::Flag_Ignore_SpellAbsorption) && magnitudes.get(ESM::MagicEffect::SpellAbsorption).getMagnitude() > 0.f;
|
||||||
if(canReflect || canAbsorb)
|
if(canReflect || canAbsorb)
|
||||||
{
|
{
|
||||||
|
auto& prng = MWBase::Environment::get().getWorld()->getPrng();
|
||||||
for(const auto& activeParam : stats.getActiveSpells())
|
for(const auto& activeParam : stats.getActiveSpells())
|
||||||
{
|
{
|
||||||
for(const auto& activeEffect : activeParam.getEffects())
|
for(const auto& activeEffect : activeParam.getEffects())
|
||||||
@ -313,14 +315,14 @@ namespace
|
|||||||
continue;
|
continue;
|
||||||
if(activeEffect.mEffectId == ESM::MagicEffect::Reflect)
|
if(activeEffect.mEffectId == ESM::MagicEffect::Reflect)
|
||||||
{
|
{
|
||||||
if(canReflect && Misc::Rng::roll0to99() < activeEffect.mMagnitude)
|
if(canReflect && Misc::Rng::roll0to99(prng) < activeEffect.mMagnitude)
|
||||||
{
|
{
|
||||||
return MWMechanics::MagicApplicationResult::REFLECTED;
|
return MWMechanics::MagicApplicationResult::REFLECTED;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
else if(activeEffect.mEffectId == ESM::MagicEffect::SpellAbsorption)
|
else if(activeEffect.mEffectId == ESM::MagicEffect::SpellAbsorption)
|
||||||
{
|
{
|
||||||
if(canAbsorb && Misc::Rng::roll0to99() < activeEffect.mMagnitude)
|
if(canAbsorb && Misc::Rng::roll0to99(prng) < activeEffect.mMagnitude)
|
||||||
{
|
{
|
||||||
absorbSpell(spellParams.getId(), caster, target);
|
absorbSpell(spellParams.getId(), caster, target);
|
||||||
return MWMechanics::MagicApplicationResult::REMOVED;
|
return MWMechanics::MagicApplicationResult::REMOVED;
|
||||||
@ -405,8 +407,11 @@ void applyMagicEffect(const MWWorld::Ptr& target, const MWWorld::Ptr& caster, co
|
|||||||
if(params.getType() == ESM::ActiveSpells::Type_Temporary)
|
if(params.getType() == ESM::ActiveSpells::Type_Temporary)
|
||||||
{
|
{
|
||||||
const ESM::Spell* spell = MWBase::Environment::get().getWorld()->getStore().get<ESM::Spell>().search(params.getId());
|
const ESM::Spell* spell = MWBase::Environment::get().getWorld()->getStore().get<ESM::Spell>().search(params.getId());
|
||||||
if(spell && spell->mData.mType == ESM::Spell::ST_Spell)
|
if (spell && spell->mData.mType == ESM::Spell::ST_Spell)
|
||||||
return Misc::Rng::roll0to99() < magnitude;
|
{
|
||||||
|
auto& prng = MWBase::Environment::get().getWorld()->getPrng();
|
||||||
|
return Misc::Rng::roll0to99(prng) < magnitude;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
return false;
|
return false;
|
||||||
}, target);
|
}, target);
|
||||||
|
@ -51,7 +51,8 @@ namespace MWMechanics
|
|||||||
if (castChance > 0)
|
if (castChance > 0)
|
||||||
x *= 50 / castChance;
|
x *= 50 / castChance;
|
||||||
|
|
||||||
float roll = Misc::Rng::rollClosedProbability() * 100;
|
auto& prng = MWBase::Environment::get().getWorld()->getPrng();
|
||||||
|
float roll = Misc::Rng::rollClosedProbability(prng) * 100;
|
||||||
if (magicEffect->mData.mFlags & ESM::MagicEffect::NoMagnitude)
|
if (magicEffect->mData.mFlags & ESM::MagicEffect::NoMagnitude)
|
||||||
roll -= resistance;
|
roll -= resistance;
|
||||||
|
|
||||||
|
@ -57,7 +57,8 @@ namespace MWMechanics
|
|||||||
+ gmst.find("fBargainOfferBase")->mValue.getFloat()
|
+ gmst.find("fBargainOfferBase")->mValue.getFloat()
|
||||||
+ int(pcTerm - npcTerm);
|
+ int(pcTerm - npcTerm);
|
||||||
|
|
||||||
int roll = Misc::Rng::rollDice(100) + 1;
|
auto& prng = MWBase::Environment::get().getWorld()->getPrng();
|
||||||
|
int roll = Misc::Rng::rollDice(100, prng) + 1;
|
||||||
|
|
||||||
// reject if roll fails
|
// reject if roll fails
|
||||||
// (or if player tries to buy things and get money)
|
// (or if player tries to buy things and get money)
|
||||||
|
@ -61,7 +61,8 @@ namespace
|
|||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
std::string itemId = MWMechanics::getLevelledItem(itemPtr.get<ESM::ItemLevList>()->mBase, false);
|
auto& prng = MWBase::Environment::get().getWorld()->getPrng();
|
||||||
|
std::string itemId = MWMechanics::getLevelledItem(itemPtr.get<ESM::ItemLevList>()->mBase, false, prng);
|
||||||
if (itemId.empty())
|
if (itemId.empty())
|
||||||
return;
|
return;
|
||||||
MWWorld::ManualRef manualRef(MWBase::Environment::get().getWorld()->getStore(), itemId, 1);
|
MWWorld::ManualRef manualRef(MWBase::Environment::get().getWorld()->getStore(), itemId, 1);
|
||||||
|
@ -111,7 +111,8 @@ namespace MWScript
|
|||||||
throw std::runtime_error (
|
throw std::runtime_error (
|
||||||
"random: argument out of range (Don't be so negative!)");
|
"random: argument out of range (Don't be so negative!)");
|
||||||
|
|
||||||
runtime.push (static_cast<Interpreter::Type_Float>(::Misc::Rng::rollDice(limit))); // [o, limit)
|
auto& prng = MWBase::Environment::get().getWorld()->getPrng();
|
||||||
|
runtime.push (static_cast<Interpreter::Type_Float>(::Misc::Rng::rollDice(limit, prng))); // [o, limit)
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
|
@ -466,6 +466,7 @@ void MWState::StateManager::loadGame (const Character *character, const std::str
|
|||||||
case ESM::REC_LEVI:
|
case ESM::REC_LEVI:
|
||||||
case ESM::REC_CREA:
|
case ESM::REC_CREA:
|
||||||
case ESM::REC_CONT:
|
case ESM::REC_CONT:
|
||||||
|
case ESM::REC_RAND:
|
||||||
MWBase::Environment::get().getWorld()->readRecord(reader, n.toInt(), contentFileMap);
|
MWBase::Environment::get().getWorld()->readRecord(reader, n.toInt(), contentFileMap);
|
||||||
break;
|
break;
|
||||||
|
|
||||||
|
@ -333,7 +333,8 @@ namespace MWWorld
|
|||||||
if(actor.getClass().isNpc() && actor.getClass().getNpcStats(actor).isWerewolf())
|
if(actor.getClass().isNpc() && actor.getClass().getNpcStats(actor).isWerewolf())
|
||||||
{
|
{
|
||||||
const MWWorld::ESMStore &store = MWBase::Environment::get().getWorld()->getStore();
|
const MWWorld::ESMStore &store = MWBase::Environment::get().getWorld()->getStore();
|
||||||
const ESM::Sound *sound = store.get<ESM::Sound>().searchRandom("WolfItem");
|
auto& prng = MWBase::Environment::get().getWorld()->getPrng();
|
||||||
|
const ESM::Sound *sound = store.get<ESM::Sound>().searchRandom("WolfItem", prng);
|
||||||
|
|
||||||
std::shared_ptr<MWWorld::Action> action(new MWWorld::FailedAction("#{sWerewolfRefusal}"));
|
std::shared_ptr<MWWorld::Action> action(new MWWorld::FailedAction("#{sWerewolfRefusal}"));
|
||||||
if(sound) action->setSound(sound->mId);
|
if(sound) action->setSound(sound->mId);
|
||||||
|
@ -221,7 +221,7 @@ namespace MWWorld
|
|||||||
virtual bool stacks (const ConstPtr& ptr1, const ConstPtr& ptr2) const;
|
virtual bool stacks (const ConstPtr& ptr1, const ConstPtr& ptr2) const;
|
||||||
///< @return true if the two specified objects can stack with each other
|
///< @return true if the two specified objects can stack with each other
|
||||||
|
|
||||||
void fill (const ESM::InventoryList& items, const std::string& owner, Misc::Rng::Generator& seed = Misc::Rng::getGenerator());
|
void fill (const ESM::InventoryList& items, const std::string& owner, Misc::Rng::Generator& seed);
|
||||||
///< Insert items into *this.
|
///< Insert items into *this.
|
||||||
|
|
||||||
void fillNonRandom (const ESM::InventoryList& items, const std::string& owner, unsigned int seed);
|
void fillNonRandom (const ESM::InventoryList& items, const std::string& owner, unsigned int seed);
|
||||||
|
@ -125,7 +125,7 @@ namespace MWWorld
|
|||||||
return (dit != mDynamic.end());
|
return (dit != mDynamic.end());
|
||||||
}
|
}
|
||||||
template<typename T>
|
template<typename T>
|
||||||
const T *Store<T>::searchRandom(const std::string &id) const
|
const T *Store<T>::searchRandom(const std::string &id, Misc::Rng::Generator& prng) const
|
||||||
{
|
{
|
||||||
std::vector<const T*> results;
|
std::vector<const T*> results;
|
||||||
std::copy_if(mShared.begin(), mShared.end(), std::back_inserter(results),
|
std::copy_if(mShared.begin(), mShared.end(), std::back_inserter(results),
|
||||||
@ -134,7 +134,7 @@ namespace MWWorld
|
|||||||
return Misc::StringUtils::ciCompareLen(id, item->mId, id.size()) == 0;
|
return Misc::StringUtils::ciCompareLen(id, item->mId, id.size()) == 0;
|
||||||
});
|
});
|
||||||
if(!results.empty())
|
if(!results.empty())
|
||||||
return results[Misc::Rng::rollDice(results.size())];
|
return results[Misc::Rng::rollDice(results.size(), prng)];
|
||||||
return nullptr;
|
return nullptr;
|
||||||
}
|
}
|
||||||
template<typename T>
|
template<typename T>
|
||||||
|
@ -10,6 +10,7 @@
|
|||||||
|
|
||||||
#include <components/esm/records.hpp>
|
#include <components/esm/records.hpp>
|
||||||
#include <components/misc/stringops.hpp>
|
#include <components/misc/stringops.hpp>
|
||||||
|
#include <components/misc/rng.hpp>
|
||||||
|
|
||||||
#include "../mwdialogue/keywordsearch.hpp"
|
#include "../mwdialogue/keywordsearch.hpp"
|
||||||
|
|
||||||
@ -181,7 +182,7 @@ namespace MWWorld
|
|||||||
bool isDynamic(const std::string &id) const;
|
bool isDynamic(const std::string &id) const;
|
||||||
|
|
||||||
/** Returns a random record that starts with the named ID, or nullptr if not found. */
|
/** Returns a random record that starts with the named ID, or nullptr if not found. */
|
||||||
const T *searchRandom(const std::string &id) const;
|
const T *searchRandom(const std::string &id, Misc::Rng::Generator& prng) const;
|
||||||
|
|
||||||
const T *find(const std::string &id) const;
|
const T *find(const std::string &id) const;
|
||||||
|
|
||||||
|
@ -18,7 +18,7 @@ namespace Misc
|
|||||||
: mPeriod(period), mDeviation(deviation), mTimeLeft(timeLeft)
|
: mPeriod(period), mDeviation(deviation), mTimeLeft(timeLeft)
|
||||||
{}
|
{}
|
||||||
|
|
||||||
TimerStatus update(float duration)
|
TimerStatus update(float duration, Rng::Generator& prng)
|
||||||
{
|
{
|
||||||
if (mTimeLeft > 0)
|
if (mTimeLeft > 0)
|
||||||
{
|
{
|
||||||
@ -26,7 +26,7 @@ namespace Misc
|
|||||||
return TimerStatus::Waiting;
|
return TimerStatus::Waiting;
|
||||||
}
|
}
|
||||||
|
|
||||||
mTimeLeft = Rng::deviate(mPeriod, mDeviation);
|
mTimeLeft = Rng::deviate(mPeriod, mDeviation, prng);
|
||||||
return TimerStatus::Elapsed;
|
return TimerStatus::Elapsed;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
Loading…
x
Reference in New Issue
Block a user