diff --git a/apps/openmw/mwbase/world.hpp b/apps/openmw/mwbase/world.hpp index 54f5c16e65..ba52fb41ab 100644 --- a/apps/openmw/mwbase/world.hpp +++ b/apps/openmw/mwbase/world.hpp @@ -160,6 +160,8 @@ namespace MWBase virtual const MWWorld::ESMStore& getStore() const = 0; + virtual const std::vector& getESMVersions() const = 0; + virtual MWWorld::LocalScripts& getLocalScripts() = 0; virtual bool hasCellChanged() const = 0; diff --git a/apps/openmw/mwrender/objectpaging.cpp b/apps/openmw/mwrender/objectpaging.cpp index 563d2ce23c..adbf1a202b 100644 --- a/apps/openmw/mwrender/objectpaging.cpp +++ b/apps/openmw/mwrender/objectpaging.cpp @@ -421,7 +421,8 @@ namespace MWRender std::map refs; ESM::ReadersCache readers; - const MWWorld::ESMStore& store = MWBase::Environment::get().getWorld()->getStore(); + const auto& world = MWBase::Environment::get().getWorld(); + const auto& store = world->getStore(); for (int cellX = startCell.x(); cellX < startCell.x() + size; ++cellX) { @@ -557,7 +558,7 @@ namespace MWRender if (found != mLODNameCache.end() && found->first == key) model = found->second; else - model = mLODNameCache.insert(found, { key, Misc::ResourceHelpers::getLODMeshName(model, mSceneManager->getVFS(), lod) })->second; + model = mLODNameCache.insert(found, { key, Misc::ResourceHelpers::getLODMeshName(world->getESMVersions()[ref.mRefNum.mContentFile], model, mSceneManager->getVFS(), lod) })->second; } osg::ref_ptr cnode = mSceneManager->getTemplate(model, false); diff --git a/apps/openmw/mwworld/esmloader.cpp b/apps/openmw/mwworld/esmloader.cpp index 795b070dfa..1a215e2608 100644 --- a/apps/openmw/mwworld/esmloader.cpp +++ b/apps/openmw/mwworld/esmloader.cpp @@ -7,11 +7,12 @@ namespace MWWorld { -EsmLoader::EsmLoader(MWWorld::ESMStore& store, ESM::ReadersCache& readers, ToUTF8::Utf8Encoder* encoder) +EsmLoader::EsmLoader(MWWorld::ESMStore& store, ESM::ReadersCache& readers, ToUTF8::Utf8Encoder* encoder, std::vector& esmVersions) : mReaders(readers) , mStore(store) , mEncoder(encoder) , mDialogue(nullptr) // A content file containing INFO records without a DIAL record appends them to the previous file's dialogue + , mESMVersions(esmVersions) { } @@ -32,6 +33,7 @@ void EsmLoader::load(const boost::filesystem::path& filepath, int& index, Loadin + ", but it is not available or has been loaded in the wrong order. " "Please run the launcher to fix this issue."); + mESMVersions[index] = reader->getVer(); mStore.load(*reader, listener, mDialogue); if (!mMasterFileFormat.has_value() && (Misc::StringUtils::ciEndsWith(reader->getName(), ".esm") diff --git a/apps/openmw/mwworld/esmloader.hpp b/apps/openmw/mwworld/esmloader.hpp index c1cc406d92..a74a200d30 100644 --- a/apps/openmw/mwworld/esmloader.hpp +++ b/apps/openmw/mwworld/esmloader.hpp @@ -23,7 +23,7 @@ class ESMStore; struct EsmLoader : public ContentLoader { - explicit EsmLoader(MWWorld::ESMStore& store, ESM::ReadersCache& readers, ToUTF8::Utf8Encoder* encoder); + explicit EsmLoader(MWWorld::ESMStore& store, ESM::ReadersCache& readers, ToUTF8::Utf8Encoder* encoder, std::vector& esmVersions); std::optional getMasterFileFormat() const { return mMasterFileFormat; } @@ -35,6 +35,7 @@ struct EsmLoader : public ContentLoader ToUTF8::Utf8Encoder* mEncoder; ESM::Dialogue* mDialogue; std::optional mMasterFileFormat; + std::vector& mESMVersions; }; } /* namespace MWWorld */ diff --git a/apps/openmw/mwworld/worldimp.cpp b/apps/openmw/mwworld/worldimp.cpp index 3af60c3420..6984fc3023 100644 --- a/apps/openmw/mwworld/worldimp.cpp +++ b/apps/openmw/mwworld/worldimp.cpp @@ -162,6 +162,7 @@ namespace MWWorld mLevitationEnabled(true), mGoToJail(false), mDaysInPrison(0), mPlayerTraveling(false), mPlayerInJail(false), mSpellPreloadTimer(0.f) { + mESMVersions.resize(mContentFiles.size(), -1); Loading::Listener* listener = MWBase::Environment::get().getWindowManager()->getLoadingScreen(); listener->loadingOn(); @@ -620,6 +621,11 @@ namespace MWWorld return *mPlayer; } + const std::vector& World::getESMVersions() const + { + return mESMVersions; + } + const MWWorld::ESMStore& World::getStore() const { return mStore; @@ -2933,7 +2939,7 @@ namespace MWWorld ToUTF8::Utf8Encoder* encoder, Loading::Listener* listener) { GameContentLoader gameContentLoader; - EsmLoader esmLoader(mStore, mReaders, encoder); + EsmLoader esmLoader(mStore, mReaders, encoder, mESMVersions); gameContentLoader.addLoader(".esm", esmLoader); gameContentLoader.addLoader(".esp", esmLoader); diff --git a/apps/openmw/mwworld/worldimp.hpp b/apps/openmw/mwworld/worldimp.hpp index d3d2ab82e1..f530d75132 100644 --- a/apps/openmw/mwworld/worldimp.hpp +++ b/apps/openmw/mwworld/worldimp.hpp @@ -138,6 +138,8 @@ namespace MWWorld float mSimulationTimeScale = 1.0; + std::vector mESMVersions; //the versions of esm files + // not implemented World (const World&); World& operator= (const World&); @@ -249,6 +251,8 @@ namespace MWWorld const MWWorld::ESMStore& getStore() const override; + const std::vector& getESMVersions() const override; + LocalScripts& getLocalScripts() override; bool hasCellChanged() const override; diff --git a/components/misc/resourcehelpers.cpp b/components/misc/resourcehelpers.cpp index aa19855ae1..3719e8e8c7 100644 --- a/components/misc/resourcehelpers.cpp +++ b/components/misc/resourcehelpers.cpp @@ -4,6 +4,8 @@ #include #include +#include + #include #include #include @@ -184,18 +186,29 @@ std::string getBestLODMeshName(std::string const& resPath, const VFS::Manager* v } } -std::string Misc::ResourceHelpers::getLODMeshName(std::string resPath, const VFS::Manager* vfs, unsigned char lod) +std::string Misc::ResourceHelpers::getLODMeshName(int esmVersion, std::string resPath, const VFS::Manager* vfs, unsigned char lod) { - static const std::string distantMeshPattern = Settings::Manager::getString("distant mesh pattern", "Terrain"); - std::string meshName = getBestLODMeshName(resPath, vfs, distantMeshPattern + "_" + std::to_string(lod)); - if (meshName != resPath) - return meshName; - + const std::string distantMeshPattern = [&esmVersion] { + switch (esmVersion) + { + case ESM::VER_120: + case ESM::VER_130: + return "_dist"; + case ESM::VER_080: + case ESM::VER_100: + return "_far"; + case ESM::VER_094: + case ESM::VER_170: + return "_lod"; + default: + return ""; + } + }(); for (char l = lod; l >= 0; --l) { std::stringstream patern; patern << distantMeshPattern << "_" << int(l); - meshName = getBestLODMeshName(resPath, vfs, patern.str()); + std::string const meshName = getBestLODMeshName(resPath, vfs, patern.str()); if (meshName != resPath) return meshName; } diff --git a/components/misc/resourcehelpers.hpp b/components/misc/resourcehelpers.hpp index 537c05c462..96a3a4a81b 100644 --- a/components/misc/resourcehelpers.hpp +++ b/components/misc/resourcehelpers.hpp @@ -30,7 +30,7 @@ namespace Misc /// marker objects that have a hardcoded function in the game logic, should be hidden from the player bool isHiddenMarker(std::string_view id); - std::string getLODMeshName(std::string resPath, const VFS::Manager* vfs, unsigned char lod = 0); + std::string getLODMeshName(int esmVersion, std::string resPath, const VFS::Manager* vfs, unsigned char lod = 0); } } diff --git a/docs/source/reference/modding/settings/terrain.rst b/docs/source/reference/modding/settings/terrain.rst index dfcf225f1a..0aa7d9bd1b 100644 --- a/docs/source/reference/modding/settings/terrain.rst +++ b/docs/source/reference/modding/settings/terrain.rst @@ -205,12 +205,3 @@ object paging min size cost multiplier This setting adjusts the calculated cost of merging an object used in the mentioned functionality. The larger this value is, the less expensive objects can be before they are discarded. See the formula above to figure out the math. - -distant mesh pattern ------------------- - -:Type: string -:Range: -:Default: _dist - -The mesh filename pattern to look for when detecting distant meshes (it will replace original mesh outside active grid) diff --git a/files/settings-default.cfg b/files/settings-default.cfg index f3cc953967..8a6fc40fd7 100644 --- a/files/settings-default.cfg +++ b/files/settings-default.cfg @@ -119,9 +119,6 @@ object paging min size merge factor = 0.3 # Controls how inexpensive an object needs to be to utilize 'min size merge factor'. object paging min size cost multiplier = 25 -# The mesh filename pattern to look for when detecting distant meshes (it will replace original mesh outside active grid) -distant mesh pattern = _dist - [Fog] # If true, use extended fog parameters for distant terrain not controlled by