diff --git a/apps/openmw/CMakeLists.txt b/apps/openmw/CMakeLists.txt index 7aa2928da5..2582b272cf 100644 --- a/apps/openmw/CMakeLists.txt +++ b/apps/openmw/CMakeLists.txt @@ -74,7 +74,7 @@ add_openmw_dir (mwworld actionequip timestamp actionalchemy cellstore actionapply actioneat store esmstore fallback actionrepair actionsoulgem livecellref actiondoor contentloader esmloader actiontrap cellreflist cellref weather projectilemanager - cellpreloader datetimemanager groundcoverstore + cellpreloader datetimemanager groundcoverstore magiceffects ) add_openmw_dir (mwphysics diff --git a/apps/openmw/mwworld/cellstore.cpp b/apps/openmw/mwworld/cellstore.cpp index 0448d0e28a..052cc35b45 100644 --- a/apps/openmw/mwworld/cellstore.cpp +++ b/apps/openmw/mwworld/cellstore.cpp @@ -1,4 +1,5 @@ #include "cellstore.hpp" +#include "magiceffects.hpp" #include diff --git a/apps/openmw/mwworld/contentloader.hpp b/apps/openmw/mwworld/contentloader.hpp index b529ae9db8..55de77ad25 100644 --- a/apps/openmw/mwworld/contentloader.hpp +++ b/apps/openmw/mwworld/contentloader.hpp @@ -2,33 +2,20 @@ #define CONTENTLOADER_HPP #include -#include -#include -#include "components/loadinglistener/loadinglistener.hpp" +namespace Loading +{ + class Listener; +} namespace MWWorld { struct ContentLoader { - ContentLoader(Loading::Listener& listener) - : mListener(listener) - { - } + virtual ~ContentLoader() = default; - virtual ~ContentLoader() - { - } - - virtual void load(const boost::filesystem::path& filepath, int& index) - { - Log(Debug::Info) << "Loading content file " << filepath.string(); - mListener.setLabel(MyGUI::TextIterator::toTagsString(filepath.string())); - } - - protected: - Loading::Listener& mListener; + virtual void load(const boost::filesystem::path& filepath, int& index, Loading::Listener* listener) = 0; }; } /* namespace MWWorld */ diff --git a/apps/openmw/mwworld/esmloader.cpp b/apps/openmw/mwworld/esmloader.cpp index 1917c41428..de16e386f2 100644 --- a/apps/openmw/mwworld/esmloader.cpp +++ b/apps/openmw/mwworld/esmloader.cpp @@ -2,233 +2,27 @@ #include "esmstore.hpp" #include -#include - -#include "../mwbase/environment.hpp" -#include "../mwbase/world.hpp" - -#include "../mwmechanics/magiceffects.hpp" - -namespace -{ - template - void getEnchantedItem(const std::string& id, std::string& enchantment, std::string& itemName) - { - const T* item = MWBase::Environment::get().getWorld()->getStore().get().search(id); - if(item) - { - enchantment = item->mEnchant; - itemName = item->mName; - } - } -} namespace MWWorld { EsmLoader::EsmLoader(MWWorld::ESMStore& store, std::vector& readers, - ToUTF8::Utf8Encoder* encoder, Loading::Listener& listener) - : ContentLoader(listener) - , mEsm(readers) - , mStore(store) - , mEncoder(encoder) + ToUTF8::Utf8Encoder* encoder) + : mEsm(readers) + , mStore(store) + , mEncoder(encoder) { } -void EsmLoader::load(const boost::filesystem::path& filepath, int& index) +void EsmLoader::load(const boost::filesystem::path& filepath, int& index, Loading::Listener* listener) { - ContentLoader::load(filepath.filename(), index); - - ESM::ESMReader lEsm; - lEsm.setEncoder(mEncoder); - lEsm.setIndex(index); - lEsm.open(filepath.string()); - lEsm.resolveParentFileIndices(mEsm); - mEsm[index] = lEsm; - mStore.load(mEsm[index], &mListener); + ESM::ESMReader lEsm; + lEsm.setEncoder(mEncoder); + lEsm.setIndex(index); + lEsm.open(filepath.string()); + lEsm.resolveParentFileIndices(mEsm); + mEsm[index] = lEsm; + mStore.load(mEsm[index], listener); } - void convertMagicEffects(ESM::CreatureStats& creatureStats, ESM::InventoryState& inventory, ESM::NpcStats* npcStats) - { - const auto& store = MWBase::Environment::get().getWorld()->getStore(); - // Convert corprus to format 10 - for (const auto& [id, oldStats] : creatureStats.mSpells.mCorprusSpells) - { - const ESM::Spell* spell = store.get().search(id); - if (!spell) - continue; - - ESM::CreatureStats::CorprusStats stats; - stats.mNextWorsening = oldStats.mNextWorsening; - for (int i=0; imEffects.mList) - { - if (effect.mEffectID == ESM::MagicEffect::DrainAttribute) - stats.mWorsenings[effect.mAttribute] = oldStats.mWorsenings; - } - creatureStats.mCorprusSpells[id] = stats; - } - // Convert to format 17 - for(const auto& [id, oldParams] : creatureStats.mSpells.mSpellParams) - { - const ESM::Spell* spell = store.get().search(id); - if (!spell || spell->mData.mType == ESM::Spell::ST_Spell || spell->mData.mType == ESM::Spell::ST_Power) - continue; - ESM::ActiveSpells::ActiveSpellParams params; - params.mId = id; - params.mDisplayName = spell->mName; - params.mItem.unset(); - params.mCasterActorId = creatureStats.mActorId; - if(spell->mData.mType == ESM::Spell::ST_Ability) - params.mType = ESM::ActiveSpells::Type_Ability; - else - params.mType = ESM::ActiveSpells::Type_Permanent; - params.mWorsenings = -1; - int effectIndex = 0; - for(const auto& enam : spell->mEffects.mList) - { - if(oldParams.mPurgedEffects.find(effectIndex) == oldParams.mPurgedEffects.end()) - { - ESM::ActiveEffect effect; - effect.mEffectId = enam.mEffectID; - effect.mArg = MWMechanics::EffectKey(enam).mArg; - effect.mDuration = -1; - effect.mTimeLeft = -1; - effect.mEffectIndex = effectIndex; - auto rand = oldParams.mEffectRands.find(effectIndex); - if(rand != oldParams.mEffectRands.end()) - { - float magnitude = (enam.mMagnMax - enam.mMagnMin) * rand->second + enam.mMagnMin; - effect.mMagnitude = magnitude; - effect.mMinMagnitude = magnitude; - effect.mMaxMagnitude = magnitude; - // Prevent recalculation of resistances and don't reflect or absorb the effect - effect.mFlags = ESM::ActiveEffect::Flag_Ignore_Resistances | ESM::ActiveEffect::Flag_Ignore_Reflect | ESM::ActiveEffect::Flag_Ignore_SpellAbsorption; - } - else - { - effect.mMagnitude = 0.f; - effect.mMinMagnitude = enam.mMagnMin; - effect.mMaxMagnitude = enam.mMagnMax; - effect.mFlags = ESM::ActiveEffect::Flag_None; - } - params.mEffects.emplace_back(effect); - } - effectIndex++; - } - creatureStats.mActiveSpells.mSpells.emplace_back(params); - } - std::multimap equippedItems; - for(std::size_t i = 0; i < inventory.mItems.size(); ++i) - { - const ESM::ObjectState& item = inventory.mItems[i]; - auto slot = inventory.mEquipmentSlots.find(i); - if(slot != inventory.mEquipmentSlots.end()) - equippedItems.emplace(item.mRef.mRefID, slot->second); - } - for(const auto& [id, oldMagnitudes] : inventory.mPermanentMagicEffectMagnitudes) - { - std::string eId; - std::string name; - switch(store.find(id)) - { - case ESM::REC_ARMO: - getEnchantedItem(id, eId, name); - break; - case ESM::REC_CLOT: - getEnchantedItem(id, eId, name); - break; - case ESM::REC_WEAP: - getEnchantedItem(id, eId, name); - break; - } - if(eId.empty()) - continue; - const ESM::Enchantment* enchantment = store.get().search(eId); - if(!enchantment) - continue; - ESM::ActiveSpells::ActiveSpellParams params; - params.mId = id; - params.mDisplayName = name; - params.mCasterActorId = creatureStats.mActorId; - params.mType = ESM::ActiveSpells::Type_Enchantment; - params.mWorsenings = -1; - for(std::size_t effectIndex = 0; effectIndex < oldMagnitudes.size() && effectIndex < enchantment->mEffects.mList.size(); ++effectIndex) - { - const auto& enam = enchantment->mEffects.mList[effectIndex]; - auto [random, multiplier] = oldMagnitudes[effectIndex]; - float magnitude = (enam.mMagnMax - enam.mMagnMin) * random + enam.mMagnMin; - magnitude *= multiplier; - if(magnitude <= 0) - continue; - ESM::ActiveEffect effect; - effect.mEffectId = enam.mEffectID; - effect.mMagnitude = magnitude; - effect.mMinMagnitude = magnitude; - effect.mMaxMagnitude = magnitude; - effect.mArg = MWMechanics::EffectKey(enam).mArg; - effect.mDuration = -1; - effect.mTimeLeft = -1; - effect.mEffectIndex = static_cast(effectIndex); - // Prevent recalculation of resistances and don't reflect or absorb the effect - effect.mFlags = ESM::ActiveEffect::Flag_Ignore_Resistances | ESM::ActiveEffect::Flag_Ignore_Reflect | ESM::ActiveEffect::Flag_Ignore_SpellAbsorption; - params.mEffects.emplace_back(effect); - } - auto [begin, end] = equippedItems.equal_range(id); - for(auto it = begin; it != end; ++it) - { - params.mItem = { static_cast(it->second), 0 }; - creatureStats.mActiveSpells.mSpells.emplace_back(params); - } - } - for(const auto& spell : creatureStats.mCorprusSpells) - { - auto it = std::find_if(creatureStats.mActiveSpells.mSpells.begin(), creatureStats.mActiveSpells.mSpells.end(), [&] (const auto& params) { return params.mId == spell.first; }); - if(it != creatureStats.mActiveSpells.mSpells.end()) - { - it->mNextWorsening = spell.second.mNextWorsening; - int worsenings = 0; - for(int i = 0; i < ESM::Attribute::Length; ++i) - worsenings = std::max(spell.second.mWorsenings[i], worsenings); - it->mWorsenings = worsenings; - } - } - for(const auto& [key, actorId] : creatureStats.mSummonedCreatureMap) - { - if(actorId == -1) - continue; - for(auto& params : creatureStats.mActiveSpells.mSpells) - { - if(params.mId == key.mSourceId) - { - bool found = false; - for(auto& effect : params.mEffects) - { - if(effect.mEffectId == key.mEffectId && effect.mEffectIndex == key.mEffectIndex) - { - effect.mArg = actorId; - found = true; - break; - } - } - if(found) - break; - } - } - } - // Reset modifiers that were previously recalculated each frame - for(std::size_t i = 0; i < ESM::Attribute::Length; ++i) - creatureStats.mAttributes[i].mMod = 0.f; - for(std::size_t i = 0; i < 3; ++i) - creatureStats.mDynamic[i].mMod = 0.f; - for(std::size_t i = 0; i < 4; ++i) - creatureStats.mAiSettings[i].mMod = 0.f; - if(npcStats) - { - for(std::size_t i = 0; i < ESM::Skill::Length; ++i) - npcStats->mSkills[i].mMod = 0.f; - } - } } /* namespace MWWorld */ diff --git a/apps/openmw/mwworld/esmloader.hpp b/apps/openmw/mwworld/esmloader.hpp index 50631603de..db50d44146 100644 --- a/apps/openmw/mwworld/esmloader.hpp +++ b/apps/openmw/mwworld/esmloader.hpp @@ -13,9 +13,6 @@ namespace ToUTF8 namespace ESM { class ESMReader; - struct CreatureStats; - struct InventoryState; - struct NpcStats; } namespace MWWorld @@ -26,18 +23,16 @@ class ESMStore; struct EsmLoader : public ContentLoader { EsmLoader(MWWorld::ESMStore& store, std::vector& readers, - ToUTF8::Utf8Encoder* encoder, Loading::Listener& listener); + ToUTF8::Utf8Encoder* encoder); - void load(const boost::filesystem::path& filepath, int& index) override; + void load(const boost::filesystem::path& filepath, int& index, Loading::Listener* listener) override; private: - std::vector& mEsm; - MWWorld::ESMStore& mStore; - ToUTF8::Utf8Encoder* mEncoder; + std::vector& mEsm; + MWWorld::ESMStore& mStore; + ToUTF8::Utf8Encoder* mEncoder; }; -void convertMagicEffects(ESM::CreatureStats& creatureStats, ESM::InventoryState& inventory, ESM::NpcStats* npcStats = nullptr); - } /* namespace MWWorld */ #endif // ESMLOADER_HPP diff --git a/apps/openmw/mwworld/magiceffects.cpp b/apps/openmw/mwworld/magiceffects.cpp new file mode 100644 index 0000000000..7d7e2857fe --- /dev/null +++ b/apps/openmw/mwworld/magiceffects.cpp @@ -0,0 +1,210 @@ +#include "magiceffects.hpp" +#include "esmstore.hpp" + +#include + +#include "../mwbase/environment.hpp" +#include "../mwbase/world.hpp" + +#include "../mwmechanics/magiceffects.hpp" + +namespace +{ + template + void getEnchantedItem(const std::string& id, std::string& enchantment, std::string& itemName) + { + const T* item = MWBase::Environment::get().getWorld()->getStore().get().search(id); + if(item) + { + enchantment = item->mEnchant; + itemName = item->mName; + } + } +} + +namespace MWWorld +{ + void convertMagicEffects(ESM::CreatureStats& creatureStats, ESM::InventoryState& inventory, ESM::NpcStats* npcStats) + { + const auto& store = MWBase::Environment::get().getWorld()->getStore(); + // Convert corprus to format 10 + for (const auto& [id, oldStats] : creatureStats.mSpells.mCorprusSpells) + { + const ESM::Spell* spell = store.get().search(id); + if (!spell) + continue; + + ESM::CreatureStats::CorprusStats stats; + stats.mNextWorsening = oldStats.mNextWorsening; + for (int i=0; imEffects.mList) + { + if (effect.mEffectID == ESM::MagicEffect::DrainAttribute) + stats.mWorsenings[effect.mAttribute] = oldStats.mWorsenings; + } + creatureStats.mCorprusSpells[id] = stats; + } + // Convert to format 17 + for(const auto& [id, oldParams] : creatureStats.mSpells.mSpellParams) + { + const ESM::Spell* spell = store.get().search(id); + if (!spell || spell->mData.mType == ESM::Spell::ST_Spell || spell->mData.mType == ESM::Spell::ST_Power) + continue; + ESM::ActiveSpells::ActiveSpellParams params; + params.mId = id; + params.mDisplayName = spell->mName; + params.mItem.unset(); + params.mCasterActorId = creatureStats.mActorId; + if(spell->mData.mType == ESM::Spell::ST_Ability) + params.mType = ESM::ActiveSpells::Type_Ability; + else + params.mType = ESM::ActiveSpells::Type_Permanent; + params.mWorsenings = -1; + int effectIndex = 0; + for(const auto& enam : spell->mEffects.mList) + { + if(oldParams.mPurgedEffects.find(effectIndex) == oldParams.mPurgedEffects.end()) + { + ESM::ActiveEffect effect; + effect.mEffectId = enam.mEffectID; + effect.mArg = MWMechanics::EffectKey(enam).mArg; + effect.mDuration = -1; + effect.mTimeLeft = -1; + effect.mEffectIndex = effectIndex; + auto rand = oldParams.mEffectRands.find(effectIndex); + if(rand != oldParams.mEffectRands.end()) + { + float magnitude = (enam.mMagnMax - enam.mMagnMin) * rand->second + enam.mMagnMin; + effect.mMagnitude = magnitude; + effect.mMinMagnitude = magnitude; + effect.mMaxMagnitude = magnitude; + // Prevent recalculation of resistances and don't reflect or absorb the effect + effect.mFlags = ESM::ActiveEffect::Flag_Ignore_Resistances | ESM::ActiveEffect::Flag_Ignore_Reflect | ESM::ActiveEffect::Flag_Ignore_SpellAbsorption; + } + else + { + effect.mMagnitude = 0.f; + effect.mMinMagnitude = enam.mMagnMin; + effect.mMaxMagnitude = enam.mMagnMax; + effect.mFlags = ESM::ActiveEffect::Flag_None; + } + params.mEffects.emplace_back(effect); + } + effectIndex++; + } + creatureStats.mActiveSpells.mSpells.emplace_back(params); + } + std::multimap equippedItems; + for(std::size_t i = 0; i < inventory.mItems.size(); ++i) + { + const ESM::ObjectState& item = inventory.mItems[i]; + auto slot = inventory.mEquipmentSlots.find(i); + if(slot != inventory.mEquipmentSlots.end()) + equippedItems.emplace(item.mRef.mRefID, slot->second); + } + for(const auto& [id, oldMagnitudes] : inventory.mPermanentMagicEffectMagnitudes) + { + std::string eId; + std::string name; + switch(store.find(id)) + { + case ESM::REC_ARMO: + getEnchantedItem(id, eId, name); + break; + case ESM::REC_CLOT: + getEnchantedItem(id, eId, name); + break; + case ESM::REC_WEAP: + getEnchantedItem(id, eId, name); + break; + } + if(eId.empty()) + continue; + const ESM::Enchantment* enchantment = store.get().search(eId); + if(!enchantment) + continue; + ESM::ActiveSpells::ActiveSpellParams params; + params.mId = id; + params.mDisplayName = name; + params.mCasterActorId = creatureStats.mActorId; + params.mType = ESM::ActiveSpells::Type_Enchantment; + params.mWorsenings = -1; + for(std::size_t effectIndex = 0; effectIndex < oldMagnitudes.size() && effectIndex < enchantment->mEffects.mList.size(); ++effectIndex) + { + const auto& enam = enchantment->mEffects.mList[effectIndex]; + auto [random, multiplier] = oldMagnitudes[effectIndex]; + float magnitude = (enam.mMagnMax - enam.mMagnMin) * random + enam.mMagnMin; + magnitude *= multiplier; + if(magnitude <= 0) + continue; + ESM::ActiveEffect effect; + effect.mEffectId = enam.mEffectID; + effect.mMagnitude = magnitude; + effect.mMinMagnitude = magnitude; + effect.mMaxMagnitude = magnitude; + effect.mArg = MWMechanics::EffectKey(enam).mArg; + effect.mDuration = -1; + effect.mTimeLeft = -1; + effect.mEffectIndex = static_cast(effectIndex); + // Prevent recalculation of resistances and don't reflect or absorb the effect + effect.mFlags = ESM::ActiveEffect::Flag_Ignore_Resistances | ESM::ActiveEffect::Flag_Ignore_Reflect | ESM::ActiveEffect::Flag_Ignore_SpellAbsorption; + params.mEffects.emplace_back(effect); + } + auto [begin, end] = equippedItems.equal_range(id); + for(auto it = begin; it != end; ++it) + { + params.mItem = { static_cast(it->second), 0 }; + creatureStats.mActiveSpells.mSpells.emplace_back(params); + } + } + for(const auto& spell : creatureStats.mCorprusSpells) + { + auto it = std::find_if(creatureStats.mActiveSpells.mSpells.begin(), creatureStats.mActiveSpells.mSpells.end(), [&] (const auto& params) { return params.mId == spell.first; }); + if(it != creatureStats.mActiveSpells.mSpells.end()) + { + it->mNextWorsening = spell.second.mNextWorsening; + int worsenings = 0; + for(int i = 0; i < ESM::Attribute::Length; ++i) + worsenings = std::max(spell.second.mWorsenings[i], worsenings); + it->mWorsenings = worsenings; + } + } + for(const auto& [key, actorId] : creatureStats.mSummonedCreatureMap) + { + if(actorId == -1) + continue; + for(auto& params : creatureStats.mActiveSpells.mSpells) + { + if(params.mId == key.mSourceId) + { + bool found = false; + for(auto& effect : params.mEffects) + { + if(effect.mEffectId == key.mEffectId && effect.mEffectIndex == key.mEffectIndex) + { + effect.mArg = actorId; + found = true; + break; + } + } + if(found) + break; + } + } + } + // Reset modifiers that were previously recalculated each frame + for(std::size_t i = 0; i < ESM::Attribute::Length; ++i) + creatureStats.mAttributes[i].mMod = 0.f; + for(std::size_t i = 0; i < 3; ++i) + creatureStats.mDynamic[i].mMod = 0.f; + for(std::size_t i = 0; i < 4; ++i) + creatureStats.mAiSettings[i].mMod = 0.f; + if(npcStats) + { + for(std::size_t i = 0; i < ESM::Skill::Length; ++i) + npcStats->mSkills[i].mMod = 0.f; + } + } +} diff --git a/apps/openmw/mwworld/magiceffects.hpp b/apps/openmw/mwworld/magiceffects.hpp new file mode 100644 index 0000000000..31d5ed2038 --- /dev/null +++ b/apps/openmw/mwworld/magiceffects.hpp @@ -0,0 +1,17 @@ +#ifndef OPENMW_MWWORLD_MAGICEFFECTS_H +#define OPENMW_MWWORLD_MAGICEFFECTS_H + +namespace ESM +{ + struct CreatureStats; + struct InventoryState; + struct NpcStats; +} + +namespace MWWorld +{ + void convertMagicEffects(ESM::CreatureStats& creatureStats, ESM::InventoryState& inventory, + ESM::NpcStats* npcStats = nullptr); +} + +#endif diff --git a/apps/openmw/mwworld/player.cpp b/apps/openmw/mwworld/player.cpp index caa0600f7c..4687a4eddd 100644 --- a/apps/openmw/mwworld/player.cpp +++ b/apps/openmw/mwworld/player.cpp @@ -12,6 +12,7 @@ #include "../mwworld/esmstore.hpp" #include "../mwworld/inventorystore.hpp" +#include "../mwworld/magiceffects.hpp" #include "../mwbase/environment.hpp" #include "../mwbase/world.hpp" diff --git a/apps/openmw/mwworld/worldimp.cpp b/apps/openmw/mwworld/worldimp.cpp index db7bc0debd..f0ac894cfc 100644 --- a/apps/openmw/mwworld/worldimp.cpp +++ b/apps/openmw/mwworld/worldimp.cpp @@ -7,6 +7,8 @@ #include #include +#include + #include #include @@ -30,6 +32,8 @@ #include #include +#include + #include "../mwbase/environment.hpp" #include "../mwbase/soundmanager.hpp" #include "../mwbase/mechanicsmanager.hpp" @@ -79,43 +83,40 @@ namespace MWWorld { struct GameContentLoader : public ContentLoader { - GameContentLoader(Loading::Listener& listener) - : ContentLoader(listener) + void addLoader(std::string&& extension, ContentLoader& loader) { + mLoaders.emplace(std::move(extension), &loader); } - bool addLoader(const std::string& extension, ContentLoader* loader) + void load(const boost::filesystem::path& filepath, int& index, Loading::Listener* listener) override { - return mLoaders.insert(std::make_pair(extension, loader)).second; - } - - void load(const boost::filesystem::path& filepath, int& index) override - { - LoadersContainer::iterator it(mLoaders.find(Misc::StringUtils::lowerCase(filepath.extension().string()))); + const auto it = mLoaders.find(Misc::StringUtils::lowerCase(filepath.extension().string())); if (it != mLoaders.end()) { - it->second->load(filepath, index); + const std::string filename = filepath.filename().string(); + Log(Debug::Info) << "Loading content file " << filename; + if (listener != nullptr) + listener->setLabel(MyGUI::TextIterator::toTagsString(filename)); + it->second->load(filepath, index, listener); } else { - std::string msg("Cannot load file: "); - msg += filepath.string(); - throw std::runtime_error(msg.c_str()); + std::string msg("Cannot load file: "); + msg += filepath.string(); + throw std::runtime_error(msg.c_str()); } } private: - typedef std::map LoadersContainer; - LoadersContainer mLoaders; + std::map mLoaders; }; struct OMWScriptsLoader : public ContentLoader { ESMStore& mStore; - OMWScriptsLoader(Loading::Listener& listener, ESMStore& store) : ContentLoader(listener), mStore(store) {} - void load(const boost::filesystem::path& filepath, int& index) override + OMWScriptsLoader(ESMStore& store) : mStore(store) {} + void load(const boost::filesystem::path& filepath, int& /*index*/, Loading::Listener* /*listener*/) override { - ContentLoader::load(filepath.filename(), index); mStore.addOMWScripts(filepath.string()); } }; @@ -2936,18 +2937,18 @@ namespace MWWorld void World::loadContentFiles(const Files::Collections& fileCollections, const std::vector& content, ESMStore& store, std::vector& readers, ToUTF8::Utf8Encoder* encoder, Loading::Listener* listener) { - GameContentLoader gameContentLoader(*listener); - EsmLoader esmLoader(store, readers, encoder, *listener); + GameContentLoader gameContentLoader; + EsmLoader esmLoader(store, readers, encoder); validateMasterFiles(readers); - gameContentLoader.addLoader(".esm", &esmLoader); - gameContentLoader.addLoader(".esp", &esmLoader); - gameContentLoader.addLoader(".omwgame", &esmLoader); - gameContentLoader.addLoader(".omwaddon", &esmLoader); - gameContentLoader.addLoader(".project", &esmLoader); + gameContentLoader.addLoader(".esm", esmLoader); + gameContentLoader.addLoader(".esp", esmLoader); + gameContentLoader.addLoader(".omwgame", esmLoader); + gameContentLoader.addLoader(".omwaddon", esmLoader); + gameContentLoader.addLoader(".project", esmLoader); - OMWScriptsLoader omwScriptsLoader(*listener, store); - gameContentLoader.addLoader(".omwscripts", &omwScriptsLoader); + OMWScriptsLoader omwScriptsLoader(store); + gameContentLoader.addLoader(".omwscripts", omwScriptsLoader); int idx = 0; for (const std::string &file : content) @@ -2956,7 +2957,7 @@ namespace MWWorld const Files::MultiDirCollection& col = fileCollections.getCollection(filename.extension().string()); if (col.doesExist(file)) { - gameContentLoader.load(col.getPath(file), idx); + gameContentLoader.load(col.getPath(file), idx, listener); } else {