diff --git a/CHANGELOG.md b/CHANGELOG.md index 811a276f1..89dce9df3 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -27,6 +27,7 @@ Bug #4383: Bow model obscures crosshair when arrow is drawn Bug #4384: Resist Normal Weapons only checks ammunition for ranged weapons Bug #4411: Reloading a saved game while falling prevents damage in some cases + Bug #4449: Value returned by GetWindSpeed is incorrect Bug #4540: Rain delay when exiting water Bug #4600: Crash when no sound output is available or --no-sound is used. Bug #4639: Black screen after completing first mages guild mission + training diff --git a/apps/openmw/mwrender/sky.cpp b/apps/openmw/mwrender/sky.cpp index a28a9d66e..27d586ea0 100644 --- a/apps/openmw/mwrender/sky.cpp +++ b/apps/openmw/mwrender/sky.cpp @@ -1625,7 +1625,8 @@ void SkyManager::updateRainParameters() { if (mRainShooter) { - float windFactor = mWindSpeed/3.f; + // Note: an arbitrary value. An original engine seems to use a different approach to rotate raindrops. + float windFactor = mWindSpeed/32.f; float angle = windFactor * osg::PI/4; mRainShooter->setVelocity(osg::Vec3f(0, mRainSpeed * windFactor, -mRainSpeed)); mRainShooter->setAngle(angle); diff --git a/apps/openmw/mwrender/sky.hpp b/apps/openmw/mwrender/sky.hpp index f6472fbde..9bae5ca50 100644 --- a/apps/openmw/mwrender/sky.hpp +++ b/apps/openmw/mwrender/sky.hpp @@ -68,6 +68,8 @@ namespace MWRender float mDLFogOffset; float mWindSpeed; + float mCurrentWindSpeed; + float mNextWindSpeed; float mCloudSpeed; diff --git a/apps/openmw/mwworld/weather.cpp b/apps/openmw/mwworld/weather.cpp index ce328ba4a..a7fd5b9d3 100644 --- a/apps/openmw/mwworld/weather.cpp +++ b/apps/openmw/mwworld/weather.cpp @@ -538,6 +538,8 @@ WeatherManager::WeatherManager(MWRender::RenderingManager& rendering, MWWorld::E , mMasser("Masser") , mSecunda("Secunda") , mWindSpeed(0.f) + , mCurrentWindSpeed(0.f) + , mNextWindSpeed(0.f) , mIsStorm(false) , mPrecipitation(false) , mStormDirection(0,1,0) @@ -663,6 +665,40 @@ void WeatherManager::playerTeleported(const std::string& playerRegion, bool isEx } } +osg::Vec3f WeatherManager::calculateStormDirection() +{ + osg::Vec3f playerPos (MWMechanics::getPlayer().getRefData().getPosition().asVec3()); + playerPos.z() = 0; + osg::Vec3f redMountainPos (25000, 70000, 0); + osg::Vec3f stormDirection = (playerPos - redMountainPos); + stormDirection.normalize(); + + return stormDirection; +} + +float WeatherManager::calculateWindSpeed(int weatherId, float currentSpeed) +{ + float targetSpeed = std::min(8.0f * mWeatherSettings[weatherId].mWindSpeed, 70.f); + if (currentSpeed == 0.f) + currentSpeed = targetSpeed; + + float multiplier = mWeatherSettings[weatherId].mRainEffect.empty() ? 1.f : 0.5f; + float updatedSpeed = (Misc::Rng::rollClosedProbability() - 0.5f) * multiplier * targetSpeed + currentSpeed; + + if (updatedSpeed > 0.5f * targetSpeed && updatedSpeed < 2.f * targetSpeed) + { + currentSpeed = updatedSpeed; + } + + // Take in account direction to the Red Mountain, when needed + if (weatherId == 6 || weatherId == 7) + { + currentSpeed = (calculateStormDirection() * currentSpeed).length(); + } + + return currentSpeed; +} + void WeatherManager::update(float duration, bool paused, const TimeStamp& time, bool isExterior) { MWWorld::ConstPtr player = MWMechanics::getPlayer(); @@ -695,12 +731,21 @@ void WeatherManager::update(float duration, bool paused, const TimeStamp& time, { mRendering.setSkyEnabled(false); stopSounds(); + mWindSpeed = 0.f; + mCurrentWindSpeed = 0.f; + mNextWindSpeed = 0.f; return; } calculateWeatherResult(time.getHour(), duration, paused); - mWindSpeed = mResult.mWindSpeed; + if (!paused) + { + mWindSpeed = mResult.mWindSpeed; + mCurrentWindSpeed = mResult.mCurrentWindSpeed; + mNextWindSpeed = mResult.mNextWindSpeed; + } + mIsStorm = mResult.mIsStorm; // For some reason Ash Storm is not considered as a precipitation weather in game @@ -709,11 +754,7 @@ void WeatherManager::update(float duration, bool paused, const TimeStamp& time, if (mIsStorm) { - osg::Vec3f playerPos (player.getRefData().getPosition().asVec3()); - playerPos.z() = 0; - osg::Vec3f redMountainPos (25000, 70000, 0); - mStormDirection = (playerPos - redMountainPos); - mStormDirection.normalize(); + mStormDirection = calculateStormDirection(); mRendering.getSkyManager()->setStormDirection(mStormDirection); } @@ -1096,7 +1137,9 @@ inline void WeatherManager::calculateResult(const int weatherID, const float gam mResult.mCloudTexture = current.mCloudTexture; mResult.mCloudBlendFactor = 0; - mResult.mWindSpeed = current.mWindSpeed; + mResult.mNextWindSpeed = 0; + mResult.mWindSpeed = mResult.mCurrentWindSpeed = calculateWindSpeed(weatherID, mWindSpeed); + mResult.mCloudSpeed = current.mCloudSpeed; mResult.mGlareView = current.mGlareView; mResult.mAmbientLoopSoundID = current.mAmbientLoopSoundID; @@ -1180,7 +1223,11 @@ inline void WeatherManager::calculateTransitionResult(const float factor, const mResult.mFogDepth = lerp(current.mFogDepth, other.mFogDepth, factor); mResult.mDLFogFactor = lerp(current.mDLFogFactor, other.mDLFogFactor, factor); mResult.mDLFogOffset = lerp(current.mDLFogOffset, other.mDLFogOffset, factor); - mResult.mWindSpeed = lerp(current.mWindSpeed, other.mWindSpeed, factor); + + mResult.mCurrentWindSpeed = calculateWindSpeed(mCurrentWeather, mCurrentWindSpeed); + mResult.mNextWindSpeed = calculateWindSpeed(mNextWeather, mNextWindSpeed); + + mResult.mWindSpeed = lerp(mResult.mCurrentWindSpeed, mResult.mNextWindSpeed, factor); mResult.mCloudSpeed = lerp(current.mCloudSpeed, other.mCloudSpeed, factor); mResult.mGlareView = lerp(current.mGlareView, other.mGlareView, factor); mResult.mNightFade = lerp(current.mNightFade, other.mNightFade, factor); diff --git a/apps/openmw/mwworld/weather.hpp b/apps/openmw/mwworld/weather.hpp index cd2101ffc..bdd6a014a 100644 --- a/apps/openmw/mwworld/weather.hpp +++ b/apps/openmw/mwworld/weather.hpp @@ -325,6 +325,8 @@ namespace MWWorld MoonModel mSecunda; float mWindSpeed; + float mCurrentWindSpeed; + float mNextWindSpeed; bool mIsStorm; bool mPrecipitation; osg::Vec3f mStormDirection; @@ -355,6 +357,7 @@ namespace MWWorld bool updateWeatherRegion(const std::string& playerRegion); void updateWeatherTransitions(const float elapsedRealSeconds); void forceWeather(const int weatherID); + osg::Vec3f calculateStormDirection(); bool inTransition(); void addWeatherTransition(const int weatherID); @@ -362,6 +365,7 @@ namespace MWWorld void calculateWeatherResult(const float gameHour, const float elapsedSeconds, const bool isPaused); void calculateResult(const int weatherID, const float gameHour); void calculateTransitionResult(const float factor, const float gameHour); + float calculateWindSpeed(int weatherId, float currentSpeed); }; }