From 6d557fec8e08dc65683454fde47d1d01a87faa9b Mon Sep 17 00:00:00 2001 From: Chris Robinson Date: Wed, 20 Sep 2017 11:42:15 -0700 Subject: [PATCH 01/10] Increase the far clip plane when distant terrain is enabled --- apps/openmw/mwrender/renderingmanager.cpp | 20 ++++++++++++-------- apps/openmw/mwrender/renderingmanager.hpp | 4 +++- 2 files changed, 15 insertions(+), 9 deletions(-) diff --git a/apps/openmw/mwrender/renderingmanager.cpp b/apps/openmw/mwrender/renderingmanager.cpp index 3281a787b..b880943a4 100644 --- a/apps/openmw/mwrender/renderingmanager.cpp +++ b/apps/openmw/mwrender/renderingmanager.cpp @@ -179,8 +179,9 @@ namespace MWRender , mUnderwaterFog(0.f) , mUnderwaterIndoorFog(fallback->getFallbackFloat("Water_UnderwaterIndoorFog")) , mNightEyeFactor(0.f) - , mFieldOfViewOverride(0.f) + , mDistantTerrain(false) , mFieldOfViewOverridden(false) + , mFieldOfViewOverride(0.f) { resourceSystem->getSceneManager()->setParticleSystemMask(MWRender::Mask_ParticleSystem); resourceSystem->getSceneManager()->setShaderPath(resourcePath + "/shaders"); @@ -216,12 +217,12 @@ namespace MWRender mWater.reset(new Water(mRootNode, sceneRoot, mResourceSystem, mViewer->getIncrementalCompileOperation(), fallback, resourcePath)); - const bool distantTerrain = Settings::Manager::getBool("distant terrain", "Terrain"); + mDistantTerrain = Settings::Manager::getBool("distant terrain", "Terrain"); mTerrainStorage = new TerrainStorage(mResourceSystem, Settings::Manager::getString("normal map pattern", "Shaders"), Settings::Manager::getString("normal height map pattern", "Shaders"), - Settings::Manager::getBool("auto use terrain normal maps", "Shaders"), Settings::Manager::getString("terrain specular map pattern", "Shaders"), + Settings::Manager::getBool("auto use terrain normal maps", "Shaders"), Settings::Manager::getString("terrain specular map pattern", "Shaders"), Settings::Manager::getBool("auto use terrain specular maps", "Shaders")); - if (distantTerrain) + if (mDistantTerrain) mTerrain.reset(new Terrain::QuadTreeWorld(sceneRoot, mRootNode, mResourceSystem, mTerrainStorage, Mask_Terrain, Mask_PreCompile)); else mTerrain.reset(new Terrain::TerrainGrid(sceneRoot, mRootNode, mResourceSystem, mTerrainStorage, Mask_Terrain, Mask_PreCompile)); @@ -288,8 +289,10 @@ namespace MWRender mFirstPersonFieldOfView = Settings::Manager::getFloat("first person field of view", "Camera"); mStateUpdater->setFogEnd(mViewDistance); + mFarClip = mDistantTerrain ? 8192.0f*5.0f : mViewDistance; + mRootNode->getOrCreateStateSet()->addUniform(new osg::Uniform("near", mNearClip)); - mRootNode->getOrCreateStateSet()->addUniform(new osg::Uniform("far", mViewDistance)); + mRootNode->getOrCreateStateSet()->addUniform(new osg::Uniform("far", mFarClip)); mUniformNear = mRootNode->getOrCreateStateSet()->getUniform("near"); mUniformFar = mRootNode->getOrCreateStateSet()->getUniform("far"); @@ -632,7 +635,7 @@ namespace MWRender rttCamera->setRenderOrder(osg::Camera::PRE_RENDER); rttCamera->setReferenceFrame(osg::Camera::ABSOLUTE_RF); rttCamera->setRenderTargetImplementation(osg::Camera::FRAME_BUFFER_OBJECT, osg::Camera::PIXEL_BUFFER_RTT); - rttCamera->setProjectionMatrixAsPerspective(mFieldOfView, w/float(h), mNearClip, mViewDistance); + rttCamera->setProjectionMatrixAsPerspective(mFieldOfView, w/float(h), mNearClip, mFarClip); rttCamera->setViewMatrix(mViewer->getCamera()->getViewMatrix()); rttCamera->setViewport(0, 0, w, h); @@ -897,10 +900,10 @@ namespace MWRender float fov = mFieldOfView; if (mFieldOfViewOverridden) fov = mFieldOfViewOverride; - mViewer->getCamera()->setProjectionMatrixAsPerspective(fov, aspect, mNearClip, mViewDistance); + mViewer->getCamera()->setProjectionMatrixAsPerspective(fov, aspect, mNearClip, mFarClip); mUniformNear->set(mNearClip); - mUniformFar->set(mViewDistance); + mUniformFar->set(mFarClip); } void RenderingManager::updateTextureFiltering() @@ -960,6 +963,7 @@ namespace MWRender else if (it->first == "Camera" && it->second == "viewing distance") { mViewDistance = Settings::Manager::getFloat("viewing distance", "Camera"); + mFarClip = mDistantTerrain ? 8192.0f*5.0f : mViewDistance; mStateUpdater->setFogEnd(mViewDistance); updateProjectionMatrix(); } diff --git a/apps/openmw/mwrender/renderingmanager.hpp b/apps/openmw/mwrender/renderingmanager.hpp index f0087e43d..16854aaea 100644 --- a/apps/openmw/mwrender/renderingmanager.hpp +++ b/apps/openmw/mwrender/renderingmanager.hpp @@ -252,9 +252,11 @@ namespace MWRender float mNightEyeFactor; float mNearClip; + float mFarClip; float mViewDistance; + bool mDistantTerrain : 1; + bool mFieldOfViewOverridden : 1; float mFieldOfViewOverride; - bool mFieldOfViewOverridden; float mFieldOfView; float mFirstPersonFieldOfView; From 154cc8c6592cfe775f0953078ad1ceeb13afd398 Mon Sep 17 00:00:00 2001 From: Chris Robinson Date: Thu, 21 Sep 2017 03:08:45 -0700 Subject: [PATCH 02/10] Use alternate fog parameters when distant land is enabled This allows the distant land to actually be seen when the user enables it. The values used are replicated from MGE XE's default settings and should probably be exposed somewhere. --- apps/openmw/mwrender/renderingmanager.cpp | 85 +++++++++++++++++------ apps/openmw/mwrender/renderingmanager.hpp | 8 ++- apps/openmw/mwrender/sky.hpp | 3 + apps/openmw/mwworld/weather.cpp | 35 ++++++---- apps/openmw/mwworld/weather.hpp | 9 +++ 5 files changed, 103 insertions(+), 37 deletions(-) diff --git a/apps/openmw/mwrender/renderingmanager.cpp b/apps/openmw/mwrender/renderingmanager.cpp index b880943a4..ea0fef197 100644 --- a/apps/openmw/mwrender/renderingmanager.cpp +++ b/apps/openmw/mwrender/renderingmanager.cpp @@ -51,6 +51,20 @@ #include "terrainstorage.hpp" #include "util.hpp" +namespace +{ + // These values are what MGE XE uses by default when distant land is enabled, and are specified + // in cells (8192 units each). Should make them settings somewhere? Or wait to expose them + // "properly"? + const float DLRenderDistance = 5.0f; + const float DLLandFogStart = 2.0f; + const float DLLandFogEnd = 5.0f; + const float DLUnderwaterFogStart = -0.5f; + const float DLUnderwaterFogEnd = 0.3f; + const float DLInteriorFogStart = 0.0f; + const float DLInteriorFogEnd = 2.0f; +} + namespace MWRender { @@ -173,10 +187,12 @@ namespace MWRender , mResourceSystem(resourceSystem) , mWorkQueue(workQueue) , mUnrefQueue(new SceneUtil::UnrefQueue) - , mFogDepth(0.f) + , mLandFogStart(0.f) + , mLandFogEnd(std::numeric_limits::max()) + , mUnderwaterFogStart(0.f) + , mUnderwaterFogEnd(std::numeric_limits::max()) , mUnderwaterColor(fallback->getFallbackColour("Water_UnderwaterColor")) , mUnderwaterWeight(fallback->getFallbackFloat("Water_UnderwaterColorWeight")) - , mUnderwaterFog(0.f) , mUnderwaterIndoorFog(fallback->getFallbackFloat("Water_UnderwaterIndoorFog")) , mNightEyeFactor(0.f) , mDistantTerrain(false) @@ -289,7 +305,7 @@ namespace MWRender mFirstPersonFieldOfView = Settings::Manager::getFloat("first person field of view", "Camera"); mStateUpdater->setFogEnd(mViewDistance); - mFarClip = mDistantTerrain ? 8192.0f*5.0f : mViewDistance; + mFarClip = mDistantTerrain ? DLRenderDistance*8192.0f : mViewDistance; mRootNode->getOrCreateStateSet()->addUniform(new osg::Uniform("near", mNearClip)); mRootNode->getOrCreateStateSet()->addUniform(new osg::Uniform("far", mFarClip)); @@ -482,14 +498,44 @@ namespace MWRender { osg::Vec4f color = SceneUtil::colourFromRGB(cell->mAmbi.mFog); - configureFog (cell->mAmbi.mFogDensity, mUnderwaterIndoorFog, color); + if(mDistantTerrain) + { + float density = std::max(0.2f, cell->mAmbi.mFogDensity); + mLandFogStart = (DLInteriorFogEnd*(1.0f-density) + DLInteriorFogStart*density) * 8192.0f; + mLandFogEnd = DLInteriorFogEnd * 8192.0f; + mUnderwaterFogStart = DLUnderwaterFogStart * 8192.0f; + mUnderwaterFogEnd = DLUnderwaterFogEnd * 8192.0f; + mFogColor = color; + } + else + configureFog(cell->mAmbi.mFogDensity, mUnderwaterIndoorFog, 1.0f, 0.0f, color); } - void RenderingManager::configureFog(float fogDepth, float underwaterFog, const osg::Vec4f &color) + void RenderingManager::configureFog(float fogDepth, float underwaterFog, float dlFactor, float dlOffset, const osg::Vec4f &color) { - mFogDepth = fogDepth; + if(mDistantTerrain) + { + mLandFogStart = dlFactor * (DLLandFogStart - dlOffset*DLLandFogEnd) * 8192.0f; + mLandFogEnd = dlFactor * (1.0f-dlOffset) * DLLandFogEnd * 8192.0f; + mUnderwaterFogStart = DLUnderwaterFogStart * 8192.0f; + mUnderwaterFogEnd = DLUnderwaterFogEnd * 8192.0f; + } + else + { + if(fogDepth == 0.0) + { + mLandFogStart = 0.0f; + mLandFogEnd = std::numeric_limits::max(); + } + else + { + mLandFogStart = mViewDistance * (1 - fogDepth); + mLandFogEnd = mViewDistance; + } + mUnderwaterFogStart = mViewDistance * (1 - underwaterFog); + mUnderwaterFogEnd = mViewDistance; + } mFogColor = color; - mUnderwaterFog = underwaterFog; } SkyManager* RenderingManager::getSkyManager() @@ -520,23 +566,15 @@ namespace MWRender float viewDistance = mViewDistance; viewDistance = std::min(viewDistance, 6666.f); setFogColor(mUnderwaterColor * mUnderwaterWeight + mFogColor * (1.f-mUnderwaterWeight)); - mStateUpdater->setFogStart(viewDistance * (1 - mUnderwaterFog)); - mStateUpdater->setFogEnd(viewDistance); + mStateUpdater->setFogStart(mUnderwaterFogStart); + mStateUpdater->setFogEnd(mUnderwaterFogEnd); } else { setFogColor(mFogColor); - if (mFogDepth == 0.f) - { - mStateUpdater->setFogStart(0.f); - mStateUpdater->setFogEnd(std::numeric_limits::max()); - } - else - { - mStateUpdater->setFogStart(mViewDistance * (1 - mFogDepth)); - mStateUpdater->setFogEnd(mViewDistance); - } + mStateUpdater->setFogStart(mLandFogStart); + mStateUpdater->setFogEnd(mLandFogEnd); } } @@ -963,9 +1001,12 @@ namespace MWRender else if (it->first == "Camera" && it->second == "viewing distance") { mViewDistance = Settings::Manager::getFloat("viewing distance", "Camera"); - mFarClip = mDistantTerrain ? 8192.0f*5.0f : mViewDistance; - mStateUpdater->setFogEnd(mViewDistance); - updateProjectionMatrix(); + if(!mDistantTerrain) + { + mFarClip = mViewDistance; + mStateUpdater->setFogEnd(mViewDistance); + updateProjectionMatrix(); + } } else if (it->first == "General" && (it->second == "texture filter" || it->second == "texture mipmap" || diff --git a/apps/openmw/mwrender/renderingmanager.hpp b/apps/openmw/mwrender/renderingmanager.hpp index 16854aaea..d44266e97 100644 --- a/apps/openmw/mwrender/renderingmanager.hpp +++ b/apps/openmw/mwrender/renderingmanager.hpp @@ -106,7 +106,7 @@ namespace MWRender void configureAmbient(const ESM::Cell* cell); void configureFog(const ESM::Cell* cell); - void configureFog(float fogDepth, float underwaterFog, const osg::Vec4f& colour); + void configureFog(float fogDepth, float underwaterFog, float dlFactor, float dlOffset, const osg::Vec4f& colour); void addCell(const MWWorld::CellStore* store); void removeCell(const MWWorld::CellStore* store); @@ -241,10 +241,12 @@ namespace MWRender osg::ref_ptr mStateUpdater; - float mFogDepth; + float mLandFogStart; + float mLandFogEnd; + float mUnderwaterFogStart; + float mUnderwaterFogEnd; osg::Vec4f mUnderwaterColor; float mUnderwaterWeight; - float mUnderwaterFog; float mUnderwaterIndoorFog; osg::Vec4f mFogColor; diff --git a/apps/openmw/mwrender/sky.hpp b/apps/openmw/mwrender/sky.hpp index 4357d468c..a9345cdb4 100644 --- a/apps/openmw/mwrender/sky.hpp +++ b/apps/openmw/mwrender/sky.hpp @@ -65,6 +65,9 @@ namespace MWRender float mFogDepth; + float mDLFogFactor; + float mDLFogOffset; + float mWindSpeed; float mCloudSpeed; diff --git a/apps/openmw/mwworld/weather.cpp b/apps/openmw/mwworld/weather.cpp index 2f0a2f8cf..bde4c4c22 100644 --- a/apps/openmw/mwworld/weather.cpp +++ b/apps/openmw/mwworld/weather.cpp @@ -103,6 +103,8 @@ Weather::Weather(const std::string& name, const Fallback::Map& fallback, float stormWindSpeed, float rainSpeed, + float dlFactor, + float dlOffset, const std::string& particleEffect) : mCloudTexture(fallback.getFallbackString("Weather_" + name + "_Cloud_Texture")) , mSkyColor(fallback.getFallbackColour("Weather_" + name +"_Sky_Sunrise_Color"), @@ -129,6 +131,7 @@ Weather::Weather(const std::string& name, , mWindSpeed(fallback.getFallbackFloat("Weather_" + name + "_Wind_Speed")) , mCloudSpeed(fallback.getFallbackFloat("Weather_" + name + "_Cloud_Speed")) , mGlareView(fallback.getFallbackFloat("Weather_" + name + "_Glare_View")) + , mDL{dlFactor, dlOffset} , mIsStorm(mWindSpeed > stormWindSpeed) , mRainSpeed(rainSpeed) , mRainFrequency(fallback.getFallbackFloat("Weather_" + name + "_Rain_Entrance_Speed")) @@ -541,16 +544,18 @@ WeatherManager::WeatherManager(MWRender::RenderingManager& rendering, const Fall mTimeSettings.mSunriseTime = mSunriseTime; mWeatherSettings.reserve(10); - addWeather("Clear", fallback); // 0 - addWeather("Cloudy", fallback); // 1 - addWeather("Foggy", fallback); // 2 - addWeather("Overcast", fallback); // 3 - addWeather("Rain", fallback); // 4 - addWeather("Thunderstorm", fallback); // 5 - addWeather("Ashstorm", fallback, "meshes\\ashcloud.nif"); // 6 - addWeather("Blight", fallback, "meshes\\blightcloud.nif"); // 7 - addWeather("Snow", fallback, "meshes\\snow.nif"); // 8 - addWeather("Blizzard", fallback, "meshes\\blizzard.nif"); // 9 + // These distant land fog factor and offset values are the defaults MGE XE provides. Should be + // provided by settings somewhere? + addWeather("Clear", fallback, 1.0f, 0.0f); // 0 + addWeather("Cloudy", fallback, 0.9f, 0.0f); // 1 + addWeather("Foggy", fallback, 0.2f, 30.0f); // 2 + addWeather("Overcast", fallback, 0.7f, 0.0f); // 3 + addWeather("Rain", fallback, 0.5f, 10.0f); // 4 + addWeather("Thunderstorm", fallback, 0.5f, 20.0f); // 5 + addWeather("Ashstorm", fallback, 0.2f, 50.0f, "meshes\\ashcloud.nif"); // 6 + addWeather("Blight", fallback, 0.2f, 60.0f, "meshes\\blightcloud.nif"); // 7 + addWeather("Snow", fallback, 0.5f, 40.0f, "meshes\\snow.nif"); // 8 + addWeather("Blizzard", fallback, 0.16f, 70.0f, "meshes\\blizzard.nif"); // 9 Store::iterator it = store.get().begin(); for(; it != store.get().end(); ++it) @@ -720,7 +725,8 @@ void WeatherManager::update(float duration, bool paused) mRendering.getSkyManager()->setMasserState(mMasser.calculateState(time)); mRendering.getSkyManager()->setSecundaState(mSecunda.calculateState(time)); - mRendering.configureFog(mResult.mFogDepth, underwaterFog, mResult.mFogColor); + mRendering.configureFog(mResult.mFogDepth, underwaterFog, mResult.mDLFogFactor, + mResult.mDLFogOffset/100.0f, mResult.mFogColor); mRendering.setAmbientColour(mResult.mAmbientColor); mRendering.setSunColour(mResult.mSunColor, mResult.mSunColor * mResult.mGlareView); @@ -866,11 +872,12 @@ void WeatherManager::clear() inline void WeatherManager::addWeather(const std::string& name, const Fallback::Map& fallback, + float dlFactor, float dlOffset, const std::string& particleEffect) { static const float fStromWindSpeed = mStore.get().find("fStromWindSpeed")->getFloat(); - Weather weather(name, fallback, fStromWindSpeed, mRainSpeed, particleEffect); + Weather weather(name, fallback, fStromWindSpeed, mRainSpeed, dlFactor, dlOffset, particleEffect); mWeatherSettings.push_back(weather); } @@ -1058,6 +1065,8 @@ inline void WeatherManager::calculateResult(const int weatherID, const float gam mResult.mNight = (gameHour < mSunriseTime || gameHour > mTimeSettings.mNightStart - 1); mResult.mFogDepth = current.mLandFogDepth.getValue(gameHour, mTimeSettings); + mResult.mDLFogFactor = current.mDL.FogFactor; + mResult.mDLFogOffset = current.mDL.FogOffset; mResult.mFogColor = current.mFogColor.getValue(gameHour, mTimeSettings); mResult.mAmbientColor = current.mAmbientColor.getValue(gameHour, mTimeSettings); mResult.mSunColor = current.mSunColor.getValue(gameHour, mTimeSettings); @@ -1113,6 +1122,8 @@ inline void WeatherManager::calculateTransitionResult(const float factor, const mResult.mAmbientColor = lerp(current.mAmbientColor, other.mAmbientColor, factor); mResult.mSunDiscColor = lerp(current.mSunDiscColor, other.mSunDiscColor, factor); 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.mCloudSpeed = lerp(current.mCloudSpeed, other.mCloudSpeed, factor); mResult.mGlareView = lerp(current.mGlareView, other.mGlareView, factor); diff --git a/apps/openmw/mwworld/weather.hpp b/apps/openmw/mwworld/weather.hpp index 84a6c5105..4555a9d2a 100644 --- a/apps/openmw/mwworld/weather.hpp +++ b/apps/openmw/mwworld/weather.hpp @@ -73,6 +73,8 @@ namespace MWWorld const Fallback::Map& fallback, float stormWindSpeed, float rainSpeed, + float dlFactor, + float dlOffset, const std::string& particleEffect); std::string mCloudTexture; @@ -102,6 +104,12 @@ namespace MWWorld // Also appears to modify how visible the sun, moons, and stars are for various weather effects. float mGlareView; + // Fog factor and offset used with distant land rendering. + struct { + float FogFactor; + float FogOffset; + } mDL; + // Sound effect // This is used for Blight, Ashstorm and Blizzard (Bloodmoon) std::string mAmbientLoopSoundID; @@ -293,6 +301,7 @@ namespace MWWorld void addWeather(const std::string& name, const Fallback::Map& fallback, + float dlFactor, float dlOffset, const std::string& particleEffect = ""); void importRegions(); From 4caa7c9674339e23d48ab076a425e272d7427c71 Mon Sep 17 00:00:00 2001 From: Chris Robinson Date: Thu, 28 Sep 2017 16:35:36 -0700 Subject: [PATCH 03/10] Workaround older MSVC quirk --- apps/openmw/mwworld/weather.cpp | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/apps/openmw/mwworld/weather.cpp b/apps/openmw/mwworld/weather.cpp index bde4c4c22..601379f08 100644 --- a/apps/openmw/mwworld/weather.cpp +++ b/apps/openmw/mwworld/weather.cpp @@ -131,7 +131,6 @@ Weather::Weather(const std::string& name, , mWindSpeed(fallback.getFallbackFloat("Weather_" + name + "_Wind_Speed")) , mCloudSpeed(fallback.getFallbackFloat("Weather_" + name + "_Cloud_Speed")) , mGlareView(fallback.getFallbackFloat("Weather_" + name + "_Glare_View")) - , mDL{dlFactor, dlOffset} , mIsStorm(mWindSpeed > stormWindSpeed) , mRainSpeed(rainSpeed) , mRainFrequency(fallback.getFallbackFloat("Weather_" + name + "_Rain_Entrance_Speed")) @@ -145,6 +144,8 @@ Weather::Weather(const std::string& name, , mFlashDecrement(fallback.getFallbackFloat("Weather_" + name + "_Flash_Decrement")) , mFlashBrightness(0.0f) { + mDL.FogFactor = dlFactor; + mDL.FogOffset = dlOffset; mThunderSoundID[0] = fallback.getFallbackString("Weather_" + name + "_Thunder_Sound_ID_0"); mThunderSoundID[1] = fallback.getFallbackString("Weather_" + name + "_Thunder_Sound_ID_1"); mThunderSoundID[2] = fallback.getFallbackString("Weather_" + name + "_Thunder_Sound_ID_2"); From 41669467aee26fb0f1e99d10b9120a0831bfcc2d Mon Sep 17 00:00:00 2001 From: Chris Robinson Date: Thu, 28 Sep 2017 17:34:44 -0700 Subject: [PATCH 04/10] Make settings for distant fog parameters --- apps/openmw/mwrender/renderingmanager.cpp | 54 +++++++++++++---------- apps/openmw/mwrender/renderingmanager.hpp | 1 + files/settings-default.cfg | 22 +++++++++ 3 files changed, 53 insertions(+), 24 deletions(-) diff --git a/apps/openmw/mwrender/renderingmanager.cpp b/apps/openmw/mwrender/renderingmanager.cpp index ea0fef197..b3fee20b5 100644 --- a/apps/openmw/mwrender/renderingmanager.cpp +++ b/apps/openmw/mwrender/renderingmanager.cpp @@ -53,16 +53,13 @@ namespace { - // These values are what MGE XE uses by default when distant land is enabled, and are specified - // in cells (8192 units each). Should make them settings somewhere? Or wait to expose them - // "properly"? - const float DLRenderDistance = 5.0f; - const float DLLandFogStart = 2.0f; - const float DLLandFogEnd = 5.0f; - const float DLUnderwaterFogStart = -0.5f; - const float DLUnderwaterFogEnd = 0.3f; - const float DLInteriorFogStart = 0.0f; - const float DLInteriorFogEnd = 2.0f; + float DLRenderDistance; + float DLLandFogStart; + float DLLandFogEnd; + float DLUnderwaterFogStart; + float DLUnderwaterFogEnd; + float DLInteriorFogStart; + float DLInteriorFogEnd; } namespace MWRender @@ -195,6 +192,7 @@ namespace MWRender , mUnderwaterWeight(fallback->getFallbackFloat("Water_UnderwaterColorWeight")) , mUnderwaterIndoorFog(fallback->getFallbackFloat("Water_UnderwaterIndoorFog")) , mNightEyeFactor(0.f) + , mDistantFog(false) , mDistantTerrain(false) , mFieldOfViewOverridden(false) , mFieldOfViewOverride(0.f) @@ -233,6 +231,15 @@ namespace MWRender mWater.reset(new Water(mRootNode, sceneRoot, mResourceSystem, mViewer->getIncrementalCompileOperation(), fallback, resourcePath)); + DLRenderDistance = Settings::Manager::getFloat("distant viewing distance", "Camera"); + DLLandFogStart = Settings::Manager::getFloat("distant land fog start", "Fog"); + DLLandFogEnd = Settings::Manager::getFloat("distant land fog end", "Fog"); + DLUnderwaterFogStart = Settings::Manager::getFloat("distant underwater fog start", "Fog"); + DLUnderwaterFogEnd = Settings::Manager::getFloat("distant underwater fog end", "Fog"); + DLInteriorFogStart = Settings::Manager::getFloat("distant interior fog start", "Fog"); + DLInteriorFogEnd = Settings::Manager::getFloat("distant interior fog end", "Fog"); + + mDistantFog = Settings::Manager::getBool("use distant fog", "Fog"); mDistantTerrain = Settings::Manager::getBool("distant terrain", "Terrain"); mTerrainStorage = new TerrainStorage(mResourceSystem, Settings::Manager::getString("normal map pattern", "Shaders"), Settings::Manager::getString("normal height map pattern", "Shaders"), Settings::Manager::getBool("auto use terrain normal maps", "Shaders"), Settings::Manager::getString("terrain specular map pattern", "Shaders"), @@ -305,7 +312,7 @@ namespace MWRender mFirstPersonFieldOfView = Settings::Manager::getFloat("first person field of view", "Camera"); mStateUpdater->setFogEnd(mViewDistance); - mFarClip = mDistantTerrain ? DLRenderDistance*8192.0f : mViewDistance; + mFarClip = mDistantTerrain ? DLRenderDistance : mViewDistance; mRootNode->getOrCreateStateSet()->addUniform(new osg::Uniform("near", mNearClip)); mRootNode->getOrCreateStateSet()->addUniform(new osg::Uniform("far", mFarClip)); @@ -498,13 +505,13 @@ namespace MWRender { osg::Vec4f color = SceneUtil::colourFromRGB(cell->mAmbi.mFog); - if(mDistantTerrain) + if(mDistantFog) { float density = std::max(0.2f, cell->mAmbi.mFogDensity); - mLandFogStart = (DLInteriorFogEnd*(1.0f-density) + DLInteriorFogStart*density) * 8192.0f; - mLandFogEnd = DLInteriorFogEnd * 8192.0f; - mUnderwaterFogStart = DLUnderwaterFogStart * 8192.0f; - mUnderwaterFogEnd = DLUnderwaterFogEnd * 8192.0f; + mLandFogStart = (DLInteriorFogEnd*(1.0f-density) + DLInteriorFogStart*density); + mLandFogEnd = DLInteriorFogEnd; + mUnderwaterFogStart = DLUnderwaterFogStart; + mUnderwaterFogEnd = DLUnderwaterFogEnd; mFogColor = color; } else @@ -513,12 +520,12 @@ namespace MWRender void RenderingManager::configureFog(float fogDepth, float underwaterFog, float dlFactor, float dlOffset, const osg::Vec4f &color) { - if(mDistantTerrain) + if(mDistantFog) { - mLandFogStart = dlFactor * (DLLandFogStart - dlOffset*DLLandFogEnd) * 8192.0f; - mLandFogEnd = dlFactor * (1.0f-dlOffset) * DLLandFogEnd * 8192.0f; - mUnderwaterFogStart = DLUnderwaterFogStart * 8192.0f; - mUnderwaterFogEnd = DLUnderwaterFogEnd * 8192.0f; + mLandFogStart = dlFactor * (DLLandFogStart - dlOffset*DLLandFogEnd); + mLandFogEnd = dlFactor * (1.0f-dlOffset) * DLLandFogEnd; + mUnderwaterFogStart = DLUnderwaterFogStart; + mUnderwaterFogEnd = DLUnderwaterFogEnd; } else { @@ -1002,11 +1009,10 @@ namespace MWRender { mViewDistance = Settings::Manager::getFloat("viewing distance", "Camera"); if(!mDistantTerrain) - { mFarClip = mViewDistance; + if(!mDistantFog) mStateUpdater->setFogEnd(mViewDistance); - updateProjectionMatrix(); - } + updateProjectionMatrix(); } else if (it->first == "General" && (it->second == "texture filter" || it->second == "texture mipmap" || diff --git a/apps/openmw/mwrender/renderingmanager.hpp b/apps/openmw/mwrender/renderingmanager.hpp index d44266e97..da79fba98 100644 --- a/apps/openmw/mwrender/renderingmanager.hpp +++ b/apps/openmw/mwrender/renderingmanager.hpp @@ -256,6 +256,7 @@ namespace MWRender float mNearClip; float mFarClip; float mViewDistance; + bool mDistantFog : 1; bool mDistantTerrain : 1; bool mFieldOfViewOverridden : 1; float mFieldOfViewOverride; diff --git a/files/settings-default.cfg b/files/settings-default.cfg index 63afa4438..c1d269e6f 100644 --- a/files/settings-default.cfg +++ b/files/settings-default.cfg @@ -25,6 +25,10 @@ small feature culling pixel size = 2.0 # can dramatically affect performance, see documentation for details. viewing distance = 6666.0 +# Maximum visible distance for distant terrain. Caution: setting this too high +# can increase the chance for Z-fighting (flickering artifacts). +distant viewing distance = 40960 + # Camera field of view in degrees (e.g. 30.0 to 110.0). # Does not affect the player's hands in the first person camera. field of view = 55.0 @@ -90,6 +94,24 @@ pointers cache size = 40 # If true, use paging and LOD algorithms to display the entire terrain. If false, only display terrain of the loaded cells distant terrain = false +[Fog] + +# If true, use extended fog parameters for distant terrain not controlled by +# viewing distance. If false, use the standard fog calculations. +use distant fog = false + +distant land fog start = 16384 + +distant land fog end = 40960 + +distant underwater fog start = -4096 + +distant underwater fog end = 2457.6 + +distant interior fog start = 0 + +distant interior fog end = 16384 + [Map] # Size of each exterior cell in pixels in the world map. (e.g. 12 to 24). From 01dbac7b1589e0c2458d5160c27bad1b212d1d31 Mon Sep 17 00:00:00 2001 From: Chris Robinson Date: Sun, 4 Mar 2018 11:37:11 -0800 Subject: [PATCH 05/10] Don't use a different setting for distant viewing distance --- apps/openmw/mwrender/renderingmanager.cpp | 14 ++++---------- apps/openmw/mwrender/renderingmanager.hpp | 1 - files/settings-default.cfg | 4 ---- 3 files changed, 4 insertions(+), 15 deletions(-) diff --git a/apps/openmw/mwrender/renderingmanager.cpp b/apps/openmw/mwrender/renderingmanager.cpp index b3fee20b5..6f0ddba3a 100644 --- a/apps/openmw/mwrender/renderingmanager.cpp +++ b/apps/openmw/mwrender/renderingmanager.cpp @@ -53,7 +53,6 @@ namespace { - float DLRenderDistance; float DLLandFogStart; float DLLandFogEnd; float DLUnderwaterFogStart; @@ -231,7 +230,6 @@ namespace MWRender mWater.reset(new Water(mRootNode, sceneRoot, mResourceSystem, mViewer->getIncrementalCompileOperation(), fallback, resourcePath)); - DLRenderDistance = Settings::Manager::getFloat("distant viewing distance", "Camera"); DLLandFogStart = Settings::Manager::getFloat("distant land fog start", "Fog"); DLLandFogEnd = Settings::Manager::getFloat("distant land fog end", "Fog"); DLUnderwaterFogStart = Settings::Manager::getFloat("distant underwater fog start", "Fog"); @@ -312,10 +310,8 @@ namespace MWRender mFirstPersonFieldOfView = Settings::Manager::getFloat("first person field of view", "Camera"); mStateUpdater->setFogEnd(mViewDistance); - mFarClip = mDistantTerrain ? DLRenderDistance : mViewDistance; - mRootNode->getOrCreateStateSet()->addUniform(new osg::Uniform("near", mNearClip)); - mRootNode->getOrCreateStateSet()->addUniform(new osg::Uniform("far", mFarClip)); + mRootNode->getOrCreateStateSet()->addUniform(new osg::Uniform("far", mViewDistance)); mUniformNear = mRootNode->getOrCreateStateSet()->getUniform("near"); mUniformFar = mRootNode->getOrCreateStateSet()->getUniform("far"); @@ -680,7 +676,7 @@ namespace MWRender rttCamera->setRenderOrder(osg::Camera::PRE_RENDER); rttCamera->setReferenceFrame(osg::Camera::ABSOLUTE_RF); rttCamera->setRenderTargetImplementation(osg::Camera::FRAME_BUFFER_OBJECT, osg::Camera::PIXEL_BUFFER_RTT); - rttCamera->setProjectionMatrixAsPerspective(mFieldOfView, w/float(h), mNearClip, mFarClip); + rttCamera->setProjectionMatrixAsPerspective(mFieldOfView, w/float(h), mNearClip, mViewDistance); rttCamera->setViewMatrix(mViewer->getCamera()->getViewMatrix()); rttCamera->setViewport(0, 0, w, h); @@ -945,10 +941,10 @@ namespace MWRender float fov = mFieldOfView; if (mFieldOfViewOverridden) fov = mFieldOfViewOverride; - mViewer->getCamera()->setProjectionMatrixAsPerspective(fov, aspect, mNearClip, mFarClip); + mViewer->getCamera()->setProjectionMatrixAsPerspective(fov, aspect, mNearClip, mViewDistance); mUniformNear->set(mNearClip); - mUniformFar->set(mFarClip); + mUniformFar->set(mViewDistance); } void RenderingManager::updateTextureFiltering() @@ -1008,8 +1004,6 @@ namespace MWRender else if (it->first == "Camera" && it->second == "viewing distance") { mViewDistance = Settings::Manager::getFloat("viewing distance", "Camera"); - if(!mDistantTerrain) - mFarClip = mViewDistance; if(!mDistantFog) mStateUpdater->setFogEnd(mViewDistance); updateProjectionMatrix(); diff --git a/apps/openmw/mwrender/renderingmanager.hpp b/apps/openmw/mwrender/renderingmanager.hpp index da79fba98..1c689d29f 100644 --- a/apps/openmw/mwrender/renderingmanager.hpp +++ b/apps/openmw/mwrender/renderingmanager.hpp @@ -254,7 +254,6 @@ namespace MWRender float mNightEyeFactor; float mNearClip; - float mFarClip; float mViewDistance; bool mDistantFog : 1; bool mDistantTerrain : 1; diff --git a/files/settings-default.cfg b/files/settings-default.cfg index c1d269e6f..dc770425f 100644 --- a/files/settings-default.cfg +++ b/files/settings-default.cfg @@ -25,10 +25,6 @@ small feature culling pixel size = 2.0 # can dramatically affect performance, see documentation for details. viewing distance = 6666.0 -# Maximum visible distance for distant terrain. Caution: setting this too high -# can increase the chance for Z-fighting (flickering artifacts). -distant viewing distance = 40960 - # Camera field of view in degrees (e.g. 30.0 to 110.0). # Does not affect the player's hands in the first person camera. field of view = 55.0 From 1aa3ed0c180812dff3608d34f6537ee432eb1346 Mon Sep 17 00:00:00 2001 From: Capostrophic Date: Sat, 31 Mar 2018 00:51:43 +0300 Subject: [PATCH 06/10] Font loader fallback character reorganization (fixes #1987) --- components/fontloader/fontloader.cpp | 114 ++++++++++++++++----------- 1 file changed, 69 insertions(+), 45 deletions(-) diff --git a/components/fontloader/fontloader.cpp b/components/fontloader/fontloader.cpp index aa92a01c6..d2c97953c 100644 --- a/components/fontloader/fontloader.cpp +++ b/components/fontloader/fontloader.cpp @@ -339,52 +339,76 @@ namespace Gui + MyGUI::utility::toString((fontSize-data[i].ascent))); code->addAttribute("size", MyGUI::IntSize(static_cast(data[i].width), static_cast(data[i].height))); - // More hacks! The french game uses several win1252 characters that are not included - // in the cp437 encoding of the font. Fall back to similar available characters. - if (mEncoding == ToUTF8::CP437) + // Fall back from unavailable Windows-1252 encoding symbols to similar characters available in the game fonts + std::multimap additional; // fallback glyph index, unicode + additional.insert(std::make_pair(156, 0x00A2)); // cent sign + additional.insert(std::make_pair(89, 0x00A5)); // yen sign + additional.insert(std::make_pair(221, 0x00A6)); // broken bar + additional.insert(std::make_pair(99, 0x00A9)); // copyright sign + additional.insert(std::make_pair(97, 0x00AA)); // prima ordinal indicator + additional.insert(std::make_pair(60, 0x00AB)); // double left-pointing angle quotation mark + additional.insert(std::make_pair(45, 0x00AD)); // soft hyphen + additional.insert(std::make_pair(114, 0x00AE)); // registered trademark symbol + additional.insert(std::make_pair(45, 0x00AF)); // macron + additional.insert(std::make_pair(241, 0x00B1)); // plus-minus sign + additional.insert(std::make_pair(50, 0x00B2)); // superscript two + additional.insert(std::make_pair(51, 0x00B3)); // superscript three + additional.insert(std::make_pair(44, 0x00B8)); // cedilla + additional.insert(std::make_pair(49, 0x00B9)); // superscript one + additional.insert(std::make_pair(111, 0x00BA)); // primo ordinal indicator + additional.insert(std::make_pair(62, 0x00BB)); // double right-pointing angle quotation mark + additional.insert(std::make_pair(63, 0x00BF)); // inverted question mark + additional.insert(std::make_pair(65, 0x00C6)); // latin capital ae ligature + additional.insert(std::make_pair(79, 0x00D8)); // latin capital o with stroke + additional.insert(std::make_pair(97, 0x00E6)); // latin small ae ligature + additional.insert(std::make_pair(111, 0x00F8)); // latin small o with stroke + additional.insert(std::make_pair(79, 0x0152)); // latin capital oe ligature + additional.insert(std::make_pair(111, 0x0153)); // latin small oe ligature + additional.insert(std::make_pair(83, 0x015A)); // latin capital s with caron + additional.insert(std::make_pair(115, 0x015B)); // latin small s with caron + additional.insert(std::make_pair(89, 0x0178)); // latin capital y with diaresis + additional.insert(std::make_pair(90, 0x017D)); // latin capital z with caron + additional.insert(std::make_pair(122, 0x017E)); // latin small z with caron + additional.insert(std::make_pair(102, 0x0192)); // latin small f with hook + additional.insert(std::make_pair(94, 0x02C6)); // circumflex modifier + additional.insert(std::make_pair(126, 0x02DC)); // small tilde + additional.insert(std::make_pair(69, 0x0401)); // cyrillic capital io (no diaeresis latin e is available) + additional.insert(std::make_pair(137, 0x0451)); // cyrillic small io + additional.insert(std::make_pair(45, 0x2012)); // figure dash + additional.insert(std::make_pair(45, 0x2013)); // en dash + additional.insert(std::make_pair(45, 0x2014)); // em dash + additional.insert(std::make_pair(39, 0x2018)); // left single quotation mark + additional.insert(std::make_pair(39, 0x2019)); // right single quotation mark + additional.insert(std::make_pair(44, 0x201A)); // single low quotation mark + additional.insert(std::make_pair(39, 0x201B)); // single high quotation mark (reversed) + additional.insert(std::make_pair(34, 0x201C)); // left double quotation mark + additional.insert(std::make_pair(34, 0x201D)); // right double quotation mark + additional.insert(std::make_pair(44, 0x201E)); // double low quotation mark + additional.insert(std::make_pair(34, 0x201F)); // double high quotation mark (reversed) + additional.insert(std::make_pair(43, 0x2020)); // dagger + additional.insert(std::make_pair(216, 0x2021)); // double dagger (note: this glyph is not available) + additional.insert(std::make_pair(46, 0x2026)); // ellipsis + additional.insert(std::make_pair(37, 0x2030)); // per mille sign + additional.insert(std::make_pair(60, 0x2039)); // single left-pointing angle quotation mark + additional.insert(std::make_pair(62, 0x203A)); // single right-pointing angle quotation mark + additional.insert(std::make_pair(101, 0x20AC)); // euro sign + additional.insert(std::make_pair(84, 0x2122)); // trademark sign + additional.insert(std::make_pair(45, 0x2212)); // minus sign + + for (std::multimap::iterator it = additional.begin(); it != additional.end(); ++it) { - std::multimap additional; // - additional.insert(std::make_pair(39, 0x2019)); // apostrophe - additional.insert(std::make_pair(45, 0x2013)); // dash - additional.insert(std::make_pair(45, 0x2014)); // dash - additional.insert(std::make_pair(34, 0x201D)); // right double quotation mark - additional.insert(std::make_pair(34, 0x201C)); // left double quotation mark - additional.insert(std::make_pair(44, 0x201A)); - additional.insert(std::make_pair(44, 0x201E)); - additional.insert(std::make_pair(43, 0x2020)); - additional.insert(std::make_pair(94, 0x02C6)); - additional.insert(std::make_pair(37, 0x2030)); - additional.insert(std::make_pair(83, 0x0160)); - additional.insert(std::make_pair(60, 0x2039)); - additional.insert(std::make_pair(79, 0x0152)); - additional.insert(std::make_pair(90, 0x017D)); - additional.insert(std::make_pair(39, 0x2019)); - additional.insert(std::make_pair(126, 0x02DC)); - additional.insert(std::make_pair(84, 0x2122)); - additional.insert(std::make_pair(83, 0x0161)); - additional.insert(std::make_pair(62, 0x203A)); - additional.insert(std::make_pair(111, 0x0153)); - additional.insert(std::make_pair(122, 0x017E)); - additional.insert(std::make_pair(89, 0x0178)); - additional.insert(std::make_pair(156, 0x00A2)); - additional.insert(std::make_pair(46, 0x2026)); - - for (std::multimap::iterator it = additional.begin(); it != additional.end(); ++it) - { - if (it->first != i) - continue; - - code = codes->createChild("Code"); - code->addAttribute("index", it->second); - code->addAttribute("coord", MyGUI::utility::toString(x1) + " " - + MyGUI::utility::toString(y1) + " " - + MyGUI::utility::toString(w) + " " - + MyGUI::utility::toString(h)); - code->addAttribute("advance", data[i].width); - code->addAttribute("bearing", MyGUI::utility::toString(data[i].kerning) + " " - + MyGUI::utility::toString((fontSize-data[i].ascent))); - code->addAttribute("size", MyGUI::IntSize(static_cast(data[i].width), static_cast(data[i].height))); - } + if (it->first != i) + continue; + code = codes->createChild("Code"); + code->addAttribute("index", it->second); + code->addAttribute("coord", MyGUI::utility::toString(x1) + " " + + MyGUI::utility::toString(y1) + " " + + MyGUI::utility::toString(w) + " " + + MyGUI::utility::toString(h)); + code->addAttribute("advance", data[i].width); + code->addAttribute("bearing", MyGUI::utility::toString(data[i].kerning) + " " + + MyGUI::utility::toString((fontSize-data[i].ascent))); + code->addAttribute("size", MyGUI::IntSize(static_cast(data[i].width), static_cast(data[i].height))); } // ASCII vertical bar, use this as text input cursor From 4f64ba7b7f7761ae4cf17a21fd5dda8a793c08a5 Mon Sep 17 00:00:00 2001 From: Capostrophic Date: Sat, 24 Mar 2018 13:43:18 +0300 Subject: [PATCH 07/10] Implement sBookSkillMessage GMST --- apps/openmw/mwmechanics/npcstats.cpp | 7 ++++++- apps/openmw/mwmechanics/npcstats.hpp | 2 +- apps/openmw/mwworld/actionread.cpp | 2 +- 3 files changed, 8 insertions(+), 3 deletions(-) diff --git a/apps/openmw/mwmechanics/npcstats.cpp b/apps/openmw/mwmechanics/npcstats.cpp index f0fc7fb6e..f15152759 100644 --- a/apps/openmw/mwmechanics/npcstats.cpp +++ b/apps/openmw/mwmechanics/npcstats.cpp @@ -214,7 +214,7 @@ void MWMechanics::NpcStats::useSkill (int skillIndex, const ESM::Class& class_, } } -void MWMechanics::NpcStats::increaseSkill(int skillIndex, const ESM::Class &class_, bool preserveProgress) +void MWMechanics::NpcStats::increaseSkill(int skillIndex, const ESM::Class &class_, bool preserveProgress, bool readBook) { int base = getSkill (skillIndex).getBase(); @@ -256,9 +256,14 @@ void MWMechanics::NpcStats::increaseSkill(int skillIndex, const ESM::Class &clas MWBase::Environment::get().getWindowManager()->playSound("skillraise"); std::stringstream message; + + if (readBook) + message << std::string("#{sBookSkillMessage}\n"); + message << boost::format(MWBase::Environment::get().getWindowManager ()->getGameSettingString ("sNotifyMessage39", "")) % std::string("#{" + ESM::Skill::sSkillNameIds[skillIndex] + "}") % static_cast (base); + MWBase::Environment::get().getWindowManager ()->messageBox(message.str(), MWGui::ShowInDialogueMode_Never); if (mLevelProgress >= gmst.find("iLevelUpTotal")->getInt()) diff --git a/apps/openmw/mwmechanics/npcstats.hpp b/apps/openmw/mwmechanics/npcstats.hpp index 9ded47c07..d2e42e994 100644 --- a/apps/openmw/mwmechanics/npcstats.hpp +++ b/apps/openmw/mwmechanics/npcstats.hpp @@ -81,7 +81,7 @@ namespace MWMechanics void useSkill (int skillIndex, const ESM::Class& class_, int usageType = -1, float extraFactor=1.f); ///< Increase skill by usage. - void increaseSkill (int skillIndex, const ESM::Class& class_, bool preserveProgress); + void increaseSkill (int skillIndex, const ESM::Class& class_, bool preserveProgress, bool readBook = false); int getLevelProgress() const; diff --git a/apps/openmw/mwworld/actionread.cpp b/apps/openmw/mwworld/actionread.cpp index d2dc972fc..58611f0af 100644 --- a/apps/openmw/mwworld/actionread.cpp +++ b/apps/openmw/mwworld/actionread.cpp @@ -52,7 +52,7 @@ namespace MWWorld playerRef->mBase->mClass ); - npcStats.increaseSkill (ref->mBase->mData.mSkillId, *class_, true); + npcStats.increaseSkill (ref->mBase->mData.mSkillId, *class_, true, true); npcStats.flagAsUsed (ref->mBase->mId); } From 27c831959ec93dd581f8e2982922eb0965ad3607 Mon Sep 17 00:00:00 2001 From: Andrei Kortunov Date: Mon, 2 Apr 2018 22:27:04 +0400 Subject: [PATCH 08/10] Handle OnPCHitMe variable (bug #2703) --- apps/openmw/mwmechanics/mechanicsmanagerimp.cpp | 15 ++++++++++++++- 1 file changed, 14 insertions(+), 1 deletion(-) diff --git a/apps/openmw/mwmechanics/mechanicsmanagerimp.cpp b/apps/openmw/mwmechanics/mechanicsmanagerimp.cpp index 225427829..07f16cc50 100644 --- a/apps/openmw/mwmechanics/mechanicsmanagerimp.cpp +++ b/apps/openmw/mwmechanics/mechanicsmanagerimp.cpp @@ -1445,7 +1445,20 @@ namespace MWMechanics // Attacker is in combat with us, but we are not in combat with the attacker yet. Time to fight back. // Note: accidental or collateral damage attacks are ignored. if (!target.getClass().getCreatureStats(target).getAiSequence().hasPackage(AiPackage::TypeIdPursue)) - startCombat(target, attacker); + { + // If an actor has OnPCHitMe declared in his script, his Fight = 0 and the attacker is player, + // he will attack the player only if we will force him (e.g. via StartCombat console command) + bool peaceful = false; + std::string script = target.getClass().getScript(target); + if (!script.empty() && target.getRefData().getLocals().hasVar(script, "onpchitme") && attacker == getPlayer()) + { + int fight = std::max(0, target.getClass().getCreatureStats(target).getAiSetting(CreatureStats::AI_Fight).getModified()); + peaceful = (fight == 0); + } + + if (!peaceful) + startCombat(target, attacker); + } } return true; From 77467f17c9259d8dc23d0b415f578e4cd2bf7db1 Mon Sep 17 00:00:00 2001 From: Capostrophic Date: Fri, 6 Apr 2018 00:10:48 +0300 Subject: [PATCH 09/10] Fix a typo --- apps/openmw/mwmechanics/spellcasting.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/apps/openmw/mwmechanics/spellcasting.cpp b/apps/openmw/mwmechanics/spellcasting.cpp index f43fd906d..0f56ea7f1 100644 --- a/apps/openmw/mwmechanics/spellcasting.cpp +++ b/apps/openmw/mwmechanics/spellcasting.cpp @@ -568,7 +568,7 @@ namespace MWMechanics ActiveSpells::ActiveEffect effect_ = effect; effect_.mMagnitude *= -1; absorbEffects.push_back(effect_); - if (reflected && Settings::Manager::getBool("classic reflected absorb attribute behavior", "Game")) + if (reflected && Settings::Manager::getBool("classic reflect absorb attribute behavior", "Game")) target.getClass().getCreatureStats(target).getActiveSpells().addSpell("", true, absorbEffects, mSourceName, caster.getClass().getCreatureStats(caster).getActorId()); else From cddc0914c87df67a987cf40caeae07913851ee2e Mon Sep 17 00:00:00 2001 From: Capostrophic Date: Mon, 9 Apr 2018 01:00:40 +0300 Subject: [PATCH 10/10] Option to charge for all companions travelling (fixes #4064) --- apps/openmw/mwgui/travelwindow.cpp | 7 ++++++- files/settings-default.cfg | 3 +++ 2 files changed, 9 insertions(+), 1 deletion(-) diff --git a/apps/openmw/mwgui/travelwindow.cpp b/apps/openmw/mwgui/travelwindow.cpp index 7586bb66a..7b65eb771 100644 --- a/apps/openmw/mwgui/travelwindow.cpp +++ b/apps/openmw/mwgui/travelwindow.cpp @@ -4,6 +4,8 @@ #include #include +#include + #include "../mwbase/environment.hpp" #include "../mwbase/world.hpp" #include "../mwbase/windowmanager.hpp" @@ -72,7 +74,10 @@ namespace MWGui MWWorld::ActionTeleport::getFollowersToTeleport(player, followers); // Apply followers cost, in vanilla one follower travels for free - price *= std::max(1, static_cast(followers.size())); + if (Settings::Manager::getBool("charge for every follower travelling", "Game")) + price *= 1 + static_cast(followers.size()); + else + price *= std::max(1, static_cast(followers.size())); MyGUI::Button* toAdd = mDestinationsView->createWidget("SandTextButton", 0, mCurrentY, 200, sLineHeight, MyGUI::Align::Default); toAdd->setEnabled(price <= playerGold); diff --git a/files/settings-default.cfg b/files/settings-default.cfg index 8a28c42e4..46d9934fd 100644 --- a/files/settings-default.cfg +++ b/files/settings-default.cfg @@ -176,6 +176,9 @@ difficulty = 0 # Show duration of magic effect and lights in the spells window. show effect duration = false +# Account for the first follower in fast travel cost calculations. +charge for every follower travelling = false + # Prevents merchants from equipping items that are sold to them. prevent merchant equipping = false