1
0
Fork 0
mirror of https://github.com/OpenMW/openmw.git synced 2025-02-05 18:45:34 +00:00

Improve save cleaning

This commit is contained in:
Evil Eye 2021-07-12 20:51:13 +02:00
parent cd9fb2adad
commit 86c50ece92
3 changed files with 50 additions and 1 deletions

View file

@ -844,7 +844,12 @@ namespace MWWorld
if (type == 0) if (type == 0)
{ {
Log(Debug::Warning) << "Dropping reference to '" << cref.mRefID << "' (object no longer exists)"; Log(Debug::Warning) << "Dropping reference to '" << cref.mRefID << "' (object no longer exists)";
reader.skipHSubUntil("OBJE"); // Skip until the next OBJE or MVRF
while(reader.hasMoreSubs() && !reader.peekNextSub("OBJE") && !reader.peekNextSub("MVRF"))
{
reader.getSubName();
reader.skipHSub();
}
continue; continue;
} }

View file

@ -109,6 +109,21 @@ namespace
return npcsToReplace; return npcsToReplace;
} }
// Custom enchanted items can reference scripts that no longer exist, this doesn't necessarily mean the base item no longer exists however.
// So instead of removing the item altogether, we're only removing the script.
template<class T>
void removeMissingScripts(const MWWorld::Store<ESM::Script>& scripts, std::map<std::string, T>& items)
{
for(auto& [id, item] : items)
{
if(!item.mScript.empty() && !scripts.search(item.mScript))
{
item.mScript.clear();
Log(Debug::Verbose) << "Item '" << id << "' (" << item.mName << ") has nonexistent script '" << item.mScript << "', ignoring it.";
}
}
}
} }
namespace MWWorld namespace MWWorld
@ -366,6 +381,32 @@ void ESMStore::validateDynamic()
for (const ESM::NPC &npc : npcsToReplace) for (const ESM::NPC &npc : npcsToReplace)
mNpcs.insert(npc); mNpcs.insert(npc);
removeMissingScripts(mScripts, mArmors.mDynamic);
removeMissingScripts(mScripts, mBooks.mDynamic);
removeMissingScripts(mScripts, mClothes.mDynamic);
removeMissingScripts(mScripts, mWeapons.mDynamic);
removeMissingObjects(mCreatureLists);
removeMissingObjects(mItemLists);
}
// Leveled lists can be modified by scripts. This removes items that no longer exist (presumably because the plugin was removed) from modified lists
template<class T>
void ESMStore::removeMissingObjects(Store<T>& store)
{
for(auto& [id, list] : store.mDynamic)
{
std::remove_if(list.mList.begin(), list.mList.end(), [&] (const auto& item)
{
if(!find(item.mId))
{
Log(Debug::Verbose) << "Leveled list '" << id << "' has nonexistent object '" << item.mId << "', ignoring it.";
return true;
}
return false;
});
}
} }
int ESMStore::countSavedGameRecords() const int ESMStore::countSavedGameRecords() const

View file

@ -89,6 +89,9 @@ namespace MWWorld
void validate(); void validate();
void countRecords(); void countRecords();
template<class T>
void removeMissingObjects(Store<T>& store);
public: public:
/// \todo replace with SharedIterator<StoreBase> /// \todo replace with SharedIterator<StoreBase>
typedef std::map<int, StoreBase *>::const_iterator iterator; typedef std::map<int, StoreBase *>::const_iterator iterator;