From cb99e8643a6b2c2afab155eb2935248b47f0e8a0 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=CE=B6eh=20Matt?= <5415177+ZehMatt@users.noreply.github.com> Date: Tue, 17 May 2022 17:39:00 +0300 Subject: [PATCH 1/4] Use World prng for selection of random creature spawning --- apps/openmw/mwworld/worldimp.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/apps/openmw/mwworld/worldimp.cpp b/apps/openmw/mwworld/worldimp.cpp index cda1940ac4..8c1eb40c41 100644 --- a/apps/openmw/mwworld/worldimp.cpp +++ b/apps/openmw/mwworld/worldimp.cpp @@ -3697,7 +3697,7 @@ namespace MWWorld const ESM::CreatureLevList* list = mStore.get().find(creatureList); static int iNumberCreatures = mStore.get().find("iNumberCreatures")->mValue.getInteger(); - int numCreatures = 1 + Misc::Rng::rollDice(iNumberCreatures); // [1, iNumberCreatures] + int numCreatures = 1 + Misc::Rng::rollDice(iNumberCreatures, mPrng); // [1, iNumberCreatures] for (int i=0; i Date: Tue, 17 May 2022 17:39:37 +0300 Subject: [PATCH 2/4] Use World prng for head/blink animations --- apps/openmw/mwrender/npcanimation.cpp | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/apps/openmw/mwrender/npcanimation.cpp b/apps/openmw/mwrender/npcanimation.cpp index 7ce5594f96..8a7da4c800 100644 --- a/apps/openmw/mwrender/npcanimation.cpp +++ b/apps/openmw/mwrender/npcanimation.cpp @@ -142,7 +142,8 @@ void HeadAnimationTime::setEnabled(bool enabled) void HeadAnimationTime::resetBlinkTimer() { - mBlinkTimer = -(2.0f + Misc::Rng::rollDice(6)); + auto& prng = MWBase::Environment::get().getWorld()->getPrng(); + mBlinkTimer = -(2.0f + Misc::Rng::rollDice(6, prng)); } void HeadAnimationTime::update(float dt) From b2fab5f5adf4e00f33915419cb0a8fda4c2e805c Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=CE=B6eh=20Matt?= <5415177+ZehMatt@users.noreply.github.com> Date: Tue, 17 May 2022 17:40:58 +0300 Subject: [PATCH 3/4] Use World prng for weather system as it influences actors --- apps/openmw/mwworld/weather.cpp | 13 ++++++++----- 1 file changed, 8 insertions(+), 5 deletions(-) diff --git a/apps/openmw/mwworld/weather.cpp b/apps/openmw/mwworld/weather.cpp index eb0226d506..1e12d0b1dd 100644 --- a/apps/openmw/mwworld/weather.cpp +++ b/apps/openmw/mwworld/weather.cpp @@ -226,8 +226,8 @@ namespace MWWorld if(transitionRatio >= mThunderThreshold && mThunderFrequency > 0.0f) { flashDecrement(elapsedSeconds); - - if(Misc::Rng::rollProbability() <= thunderChance(transitionRatio, elapsedSeconds)) + auto& prng = MWBase::Environment::get().getWorld()->getPrng(); + if(Misc::Rng::rollProbability(prng) <= thunderChance(transitionRatio, elapsedSeconds)) { lightningAndThunder(); } @@ -265,7 +265,8 @@ namespace MWWorld // They appear to go from 0 (brightest, closest) to 3 (faintest, farthest). The value of 0.25 per distance // was derived by setting the Flash Decrement to 0.1 and measuring how long each value took to decay to 0. // TODO: Determine the distribution of each distance to see if it's evenly weighted. - unsigned int distance = Misc::Rng::rollDice(4); + auto& prng = MWBase::Environment::get().getWorld()->getPrng(); + unsigned int distance = Misc::Rng::rollDice(4, prng); // Flash brightness appears additive, since if multiple strikes occur, it takes longer for it to decay to 0. mFlashBrightness += 1 - (distance * 0.25f); MWBase::Environment::get().getSoundManager()->playSound(mThunderSoundID[distance], 1.0, 1.0); @@ -348,7 +349,8 @@ namespace MWWorld // All probabilities must add to 100 (responsibility of the user). // If chances A and B has values 30 and 70 then by generating 100 numbers 1..100, 30% will be lesser or equal 30 // and 70% will be greater than 30 (in theory). - int chance = Misc::Rng::rollDice(100) + 1; // 1..100 + auto& prng = MWBase::Environment::get().getWorld()->getPrng(); + int chance = Misc::Rng::rollDice(100, prng) + 1; // 1..100 int sum = 0; int i = 0; for(; static_cast(i) < mChances.size(); ++i) @@ -685,7 +687,8 @@ namespace MWWorld currentSpeed = targetSpeed; float multiplier = mWeatherSettings[weatherId].mRainEffect.empty() ? 1.f : 0.5f; - float updatedSpeed = (Misc::Rng::rollClosedProbability() - 0.5f) * multiplier * targetSpeed + currentSpeed; + auto& prng = MWBase::Environment::get().getWorld()->getPrng(); + float updatedSpeed = (Misc::Rng::rollClosedProbability(prng) - 0.5f) * multiplier * targetSpeed + currentSpeed; if (updatedSpeed > 0.5f * targetSpeed && updatedSpeed < 2.f * targetSpeed) currentSpeed = updatedSpeed; From 18f16eac4c6d8706b0d1224b14bfa3340d3fd96b Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=CE=B6eh=20Matt?= <5415177+ZehMatt@users.noreply.github.com> Date: Tue, 17 May 2022 18:04:11 +0300 Subject: [PATCH 4/4] Refactor DetourNavigator to pass prng along, use world prng for AiWander --- apps/openmw/mwmechanics/aiwander.cpp | 5 ++++- apps/openmw_test_suite/detournavigator/navigator.cpp | 3 ++- components/detournavigator/findrandompointaroundcircle.cpp | 5 +++-- components/detournavigator/findrandompointaroundcircle.hpp | 2 +- components/detournavigator/navigatorutils.cpp | 4 ++-- components/detournavigator/navigatorutils.hpp | 2 +- 6 files changed, 13 insertions(+), 8 deletions(-) diff --git a/apps/openmw/mwmechanics/aiwander.cpp b/apps/openmw/mwmechanics/aiwander.cpp index 378e5a6351..a4da1ebd68 100644 --- a/apps/openmw/mwmechanics/aiwander.cpp +++ b/apps/openmw/mwmechanics/aiwander.cpp @@ -359,7 +359,10 @@ namespace MWMechanics { // findRandomPointAroundCircle uses wanderDistance as limit for random and not as exact distance if (const auto destination = DetourNavigator::findRandomPointAroundCircle(*navigator, halfExtents, - mInitialActorPosition, wanderDistance, navigatorFlags)) + mInitialActorPosition, wanderDistance, navigatorFlags, []() { + auto& prng = MWBase::Environment::get().getWorld()->getPrng(); + return Misc::Rng::rollProbability(prng); + })) mDestination = *destination; else mDestination = getRandomPointAround(mInitialActorPosition, wanderRadius); diff --git a/apps/openmw_test_suite/detournavigator/navigator.cpp b/apps/openmw_test_suite/detournavigator/navigator.cpp index 0e9c20fb9a..c98a5b7a90 100644 --- a/apps/openmw_test_suite/detournavigator/navigator.cpp +++ b/apps/openmw_test_suite/detournavigator/navigator.cpp @@ -819,7 +819,8 @@ namespace Misc::Rng::init(42); - const auto result = findRandomPointAroundCircle(*mNavigator, mAgentHalfExtents, mStart, 100.0, Flag_walk); + const auto result = findRandomPointAroundCircle(*mNavigator, mAgentHalfExtents, mStart, 100.0, Flag_walk, + []() { return Misc::Rng::rollClosedProbability(); }); ASSERT_THAT(result, Optional(Vec3fEq(70.35845947265625, 335.592041015625, -2.6667339801788330078125))) << (result ? *result : osg::Vec3f()); diff --git a/components/detournavigator/findrandompointaroundcircle.cpp b/components/detournavigator/findrandompointaroundcircle.cpp index 1e1e2401c5..6bd761c817 100644 --- a/components/detournavigator/findrandompointaroundcircle.cpp +++ b/components/detournavigator/findrandompointaroundcircle.cpp @@ -10,7 +10,7 @@ namespace DetourNavigator { std::optional findRandomPointAroundCircle(const dtNavMesh& navMesh, const osg::Vec3f& halfExtents, - const osg::Vec3f& start, const float maxRadius, const Flags includeFlags, const DetourSettings& settings) + const osg::Vec3f& start, const float maxRadius, const Flags includeFlags, const DetourSettings& settings, float(*prng)()) { dtNavMeshQuery navMeshQuery; if (!initNavMeshQuery(navMeshQuery, navMesh, settings.mMaxNavMeshQueryNodes)) @@ -25,8 +25,9 @@ namespace DetourNavigator dtPolyRef resultRef = 0; osg::Vec3f resultPosition; + navMeshQuery.findRandomPointAroundCircle(startRef, start.ptr(), maxRadius, &queryFilter, - []() { return Misc::Rng::rollProbability(); }, &resultRef, resultPosition.ptr()); + prng, &resultRef, resultPosition.ptr()); if (resultRef == 0) return std::optional(); diff --git a/components/detournavigator/findrandompointaroundcircle.hpp b/components/detournavigator/findrandompointaroundcircle.hpp index 89a3c0964c..346ad36e4e 100644 --- a/components/detournavigator/findrandompointaroundcircle.hpp +++ b/components/detournavigator/findrandompointaroundcircle.hpp @@ -13,7 +13,7 @@ namespace DetourNavigator struct DetourSettings; std::optional findRandomPointAroundCircle(const dtNavMesh& navMesh, const osg::Vec3f& halfExtents, - const osg::Vec3f& start, const float maxRadius, const Flags includeFlags, const DetourSettings& settings); + const osg::Vec3f& start, const float maxRadius, const Flags includeFlags, const DetourSettings& settings, float(*prng)()); } #endif diff --git a/components/detournavigator/navigatorutils.cpp b/components/detournavigator/navigatorutils.cpp index bfb0946b9e..a64343905d 100644 --- a/components/detournavigator/navigatorutils.cpp +++ b/components/detournavigator/navigatorutils.cpp @@ -6,7 +6,7 @@ namespace DetourNavigator { std::optional findRandomPointAroundCircle(const Navigator& navigator, const osg::Vec3f& agentHalfExtents, - const osg::Vec3f& start, const float maxRadius, const Flags includeFlags) + const osg::Vec3f& start, const float maxRadius, const Flags includeFlags, float(*prng)()) { const auto navMesh = navigator.getNavMesh(agentHalfExtents); if (!navMesh) @@ -14,7 +14,7 @@ namespace DetourNavigator const auto& settings = navigator.getSettings(); const auto result = DetourNavigator::findRandomPointAroundCircle(navMesh->lockConst()->getImpl(), toNavMeshCoordinates(settings.mRecast, agentHalfExtents), toNavMeshCoordinates(settings.mRecast, start), - toNavMeshCoordinates(settings.mRecast, maxRadius), includeFlags, settings.mDetour); + toNavMeshCoordinates(settings.mRecast, maxRadius), includeFlags, settings.mDetour, prng); if (!result) return std::nullopt; return std::optional(fromNavMeshCoordinates(settings.mRecast, *result)); diff --git a/components/detournavigator/navigatorutils.hpp b/components/detournavigator/navigatorutils.hpp index 8f3b6161f9..8bd1499897 100644 --- a/components/detournavigator/navigatorutils.hpp +++ b/components/detournavigator/navigatorutils.hpp @@ -51,7 +51,7 @@ namespace DetourNavigator * @return not empty optional with position if point is found and empty optional if point is not found. */ std::optional findRandomPointAroundCircle(const Navigator& navigator, const osg::Vec3f& agentHalfExtents, - const osg::Vec3f& start, const float maxRadius, const Flags includeFlags); + const osg::Vec3f& start, const float maxRadius, const Flags includeFlags, float(*prng)()); /** * @brief raycast finds farest navmesh point from start on a line from start to end that has path from start.