1
0
mirror of https://gitlab.com/OpenMW/openmw.git synced 2025-02-20 06:40:09 +00:00

Merge branch 'refactor_content_loader' into 'master'

Refactor MWWorld::ContentLoader and derived classes

See merge request OpenMW/openmw!1432
This commit is contained in:
psi29a 2021-11-30 15:36:19 +00:00
commit 8d1baa9ae0
9 changed files with 282 additions and 276 deletions

View File

@ -74,7 +74,7 @@ add_openmw_dir (mwworld
actionequip timestamp actionalchemy cellstore actionapply actioneat actionequip timestamp actionalchemy cellstore actionapply actioneat
store esmstore fallback actionrepair actionsoulgem livecellref actiondoor store esmstore fallback actionrepair actionsoulgem livecellref actiondoor
contentloader esmloader actiontrap cellreflist cellref weather projectilemanager contentloader esmloader actiontrap cellreflist cellref weather projectilemanager
cellpreloader datetimemanager groundcoverstore cellpreloader datetimemanager groundcoverstore magiceffects
) )
add_openmw_dir (mwphysics add_openmw_dir (mwphysics

View File

@ -1,4 +1,5 @@
#include "cellstore.hpp" #include "cellstore.hpp"
#include "magiceffects.hpp"
#include <algorithm> #include <algorithm>

View File

@ -2,33 +2,20 @@
#define CONTENTLOADER_HPP #define CONTENTLOADER_HPP
#include <boost/filesystem/path.hpp> #include <boost/filesystem/path.hpp>
#include <MyGUI_TextIterator.h>
#include <components/debug/debuglog.hpp> namespace Loading
#include "components/loadinglistener/loadinglistener.hpp" {
class Listener;
}
namespace MWWorld namespace MWWorld
{ {
struct ContentLoader struct ContentLoader
{ {
ContentLoader(Loading::Listener& listener) virtual ~ContentLoader() = default;
: mListener(listener)
{
}
virtual ~ContentLoader() virtual void load(const boost::filesystem::path& filepath, int& index, Loading::Listener* listener) = 0;
{
}
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;
}; };
} /* namespace MWWorld */ } /* namespace MWWorld */

View File

@ -2,233 +2,27 @@
#include "esmstore.hpp" #include "esmstore.hpp"
#include <components/esm/esmreader.hpp> #include <components/esm/esmreader.hpp>
#include <components/esm/npcstate.hpp>
#include "../mwbase/environment.hpp"
#include "../mwbase/world.hpp"
#include "../mwmechanics/magiceffects.hpp"
namespace
{
template<class T>
void getEnchantedItem(const std::string& id, std::string& enchantment, std::string& itemName)
{
const T* item = MWBase::Environment::get().getWorld()->getStore().get<T>().search(id);
if(item)
{
enchantment = item->mEnchant;
itemName = item->mName;
}
}
}
namespace MWWorld namespace MWWorld
{ {
EsmLoader::EsmLoader(MWWorld::ESMStore& store, std::vector<ESM::ESMReader>& readers, EsmLoader::EsmLoader(MWWorld::ESMStore& store, std::vector<ESM::ESMReader>& readers,
ToUTF8::Utf8Encoder* encoder, Loading::Listener& listener) ToUTF8::Utf8Encoder* encoder)
: ContentLoader(listener) : mEsm(readers)
, mEsm(readers)
, mStore(store) , mStore(store)
, mEncoder(encoder) , 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; ESM::ESMReader lEsm;
lEsm.setEncoder(mEncoder); lEsm.setEncoder(mEncoder);
lEsm.setIndex(index); lEsm.setIndex(index);
lEsm.open(filepath.string()); lEsm.open(filepath.string());
lEsm.resolveParentFileIndices(mEsm); lEsm.resolveParentFileIndices(mEsm);
mEsm[index] = lEsm; mEsm[index] = lEsm;
mStore.load(mEsm[index], &mListener); 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<ESM::Spell>().search(id);
if (!spell)
continue;
ESM::CreatureStats::CorprusStats stats;
stats.mNextWorsening = oldStats.mNextWorsening;
for (int i=0; i<ESM::Attribute::Length; ++i)
stats.mWorsenings[i] = 0;
for (auto& effect : spell->mEffects.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<ESM::Spell>().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<std::string, int> 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<ESM::Armor>(id, eId, name);
break;
case ESM::REC_CLOT:
getEnchantedItem<ESM::Clothing>(id, eId, name);
break;
case ESM::REC_WEAP:
getEnchantedItem<ESM::Weapon>(id, eId, name);
break;
}
if(eId.empty())
continue;
const ESM::Enchantment* enchantment = store.get<ESM::Enchantment>().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<int>(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<unsigned int>(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 */ } /* namespace MWWorld */

View File

@ -13,9 +13,6 @@ namespace ToUTF8
namespace ESM namespace ESM
{ {
class ESMReader; class ESMReader;
struct CreatureStats;
struct InventoryState;
struct NpcStats;
} }
namespace MWWorld namespace MWWorld
@ -26,9 +23,9 @@ class ESMStore;
struct EsmLoader : public ContentLoader struct EsmLoader : public ContentLoader
{ {
EsmLoader(MWWorld::ESMStore& store, std::vector<ESM::ESMReader>& readers, EsmLoader(MWWorld::ESMStore& store, std::vector<ESM::ESMReader>& 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: private:
std::vector<ESM::ESMReader>& mEsm; std::vector<ESM::ESMReader>& mEsm;
@ -36,8 +33,6 @@ struct EsmLoader : public ContentLoader
ToUTF8::Utf8Encoder* mEncoder; ToUTF8::Utf8Encoder* mEncoder;
}; };
void convertMagicEffects(ESM::CreatureStats& creatureStats, ESM::InventoryState& inventory, ESM::NpcStats* npcStats = nullptr);
} /* namespace MWWorld */ } /* namespace MWWorld */
#endif // ESMLOADER_HPP #endif // ESMLOADER_HPP

View File

@ -0,0 +1,210 @@
#include "magiceffects.hpp"
#include "esmstore.hpp"
#include <components/esm/npcstate.hpp>
#include "../mwbase/environment.hpp"
#include "../mwbase/world.hpp"
#include "../mwmechanics/magiceffects.hpp"
namespace
{
template<class T>
void getEnchantedItem(const std::string& id, std::string& enchantment, std::string& itemName)
{
const T* item = MWBase::Environment::get().getWorld()->getStore().get<T>().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<ESM::Spell>().search(id);
if (!spell)
continue;
ESM::CreatureStats::CorprusStats stats;
stats.mNextWorsening = oldStats.mNextWorsening;
for (int i=0; i<ESM::Attribute::Length; ++i)
stats.mWorsenings[i] = 0;
for (auto& effect : spell->mEffects.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<ESM::Spell>().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<std::string, int> 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<ESM::Armor>(id, eId, name);
break;
case ESM::REC_CLOT:
getEnchantedItem<ESM::Clothing>(id, eId, name);
break;
case ESM::REC_WEAP:
getEnchantedItem<ESM::Weapon>(id, eId, name);
break;
}
if(eId.empty())
continue;
const ESM::Enchantment* enchantment = store.get<ESM::Enchantment>().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<int>(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<unsigned int>(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;
}
}
}

View File

@ -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

View File

@ -12,6 +12,7 @@
#include "../mwworld/esmstore.hpp" #include "../mwworld/esmstore.hpp"
#include "../mwworld/inventorystore.hpp" #include "../mwworld/inventorystore.hpp"
#include "../mwworld/magiceffects.hpp"
#include "../mwbase/environment.hpp" #include "../mwbase/environment.hpp"
#include "../mwbase/world.hpp" #include "../mwbase/world.hpp"

View File

@ -7,6 +7,8 @@
#include <BulletCollision/CollisionDispatch/btCollisionWorld.h> #include <BulletCollision/CollisionDispatch/btCollisionWorld.h>
#include <BulletCollision/CollisionShapes/btCompoundShape.h> #include <BulletCollision/CollisionShapes/btCompoundShape.h>
#include <MyGUI_TextIterator.h>
#include <components/debug/debuglog.hpp> #include <components/debug/debuglog.hpp>
#include <components/esm/esmreader.hpp> #include <components/esm/esmreader.hpp>
@ -30,6 +32,8 @@
#include <components/detournavigator/navigator.hpp> #include <components/detournavigator/navigator.hpp>
#include <components/detournavigator/settings.hpp> #include <components/detournavigator/settings.hpp>
#include <components/loadinglistener/loadinglistener.hpp>
#include "../mwbase/environment.hpp" #include "../mwbase/environment.hpp"
#include "../mwbase/soundmanager.hpp" #include "../mwbase/soundmanager.hpp"
#include "../mwbase/mechanicsmanager.hpp" #include "../mwbase/mechanicsmanager.hpp"
@ -79,22 +83,21 @@ namespace MWWorld
{ {
struct GameContentLoader : public ContentLoader struct GameContentLoader : public ContentLoader
{ {
GameContentLoader(Loading::Listener& listener) void addLoader(std::string&& extension, ContentLoader& loader)
: ContentLoader(listener)
{ {
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; const auto it = mLoaders.find(Misc::StringUtils::lowerCase(filepath.extension().string()));
}
void load(const boost::filesystem::path& filepath, int& index) override
{
LoadersContainer::iterator it(mLoaders.find(Misc::StringUtils::lowerCase(filepath.extension().string())));
if (it != mLoaders.end()) 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 else
{ {
@ -105,17 +108,15 @@ namespace MWWorld
} }
private: private:
typedef std::map<std::string, ContentLoader*> LoadersContainer; std::map<std::string, ContentLoader*> mLoaders;
LoadersContainer mLoaders;
}; };
struct OMWScriptsLoader : public ContentLoader struct OMWScriptsLoader : public ContentLoader
{ {
ESMStore& mStore; ESMStore& mStore;
OMWScriptsLoader(Loading::Listener& listener, ESMStore& store) : ContentLoader(listener), mStore(store) {} OMWScriptsLoader(ESMStore& store) : mStore(store) {}
void load(const boost::filesystem::path& filepath, int& index) override void load(const boost::filesystem::path& filepath, int& /*index*/, Loading::Listener* /*listener*/) override
{ {
ContentLoader::load(filepath.filename(), index);
mStore.addOMWScripts(filepath.string()); mStore.addOMWScripts(filepath.string());
} }
}; };
@ -2936,18 +2937,18 @@ namespace MWWorld
void World::loadContentFiles(const Files::Collections& fileCollections, const std::vector<std::string>& content, ESMStore& store, std::vector<ESM::ESMReader>& readers, ToUTF8::Utf8Encoder* encoder, Loading::Listener* listener) void World::loadContentFiles(const Files::Collections& fileCollections, const std::vector<std::string>& content, ESMStore& store, std::vector<ESM::ESMReader>& readers, ToUTF8::Utf8Encoder* encoder, Loading::Listener* listener)
{ {
GameContentLoader gameContentLoader(*listener); GameContentLoader gameContentLoader;
EsmLoader esmLoader(store, readers, encoder, *listener); EsmLoader esmLoader(store, readers, encoder);
validateMasterFiles(readers); validateMasterFiles(readers);
gameContentLoader.addLoader(".esm", &esmLoader); gameContentLoader.addLoader(".esm", esmLoader);
gameContentLoader.addLoader(".esp", &esmLoader); gameContentLoader.addLoader(".esp", esmLoader);
gameContentLoader.addLoader(".omwgame", &esmLoader); gameContentLoader.addLoader(".omwgame", esmLoader);
gameContentLoader.addLoader(".omwaddon", &esmLoader); gameContentLoader.addLoader(".omwaddon", esmLoader);
gameContentLoader.addLoader(".project", &esmLoader); gameContentLoader.addLoader(".project", esmLoader);
OMWScriptsLoader omwScriptsLoader(*listener, store); OMWScriptsLoader omwScriptsLoader(store);
gameContentLoader.addLoader(".omwscripts", &omwScriptsLoader); gameContentLoader.addLoader(".omwscripts", omwScriptsLoader);
int idx = 0; int idx = 0;
for (const std::string &file : content) for (const std::string &file : content)
@ -2956,7 +2957,7 @@ namespace MWWorld
const Files::MultiDirCollection& col = fileCollections.getCollection(filename.extension().string()); const Files::MultiDirCollection& col = fileCollections.getCollection(filename.extension().string());
if (col.doesExist(file)) if (col.doesExist(file))
{ {
gameContentLoader.load(col.getPath(file), idx); gameContentLoader.load(col.getPath(file), idx, listener);
} }
else else
{ {