From c4cd2f36c33ace443fb89fa3b98cf8a2a5f0daf6 Mon Sep 17 00:00:00 2001 From: elsid Date: Tue, 23 Nov 2021 15:26:43 +0100 Subject: [PATCH] Move convertMagicEffects into separate file As completely unrelated to EsmLoader. --- apps/openmw/CMakeLists.txt | 2 +- apps/openmw/mwworld/cellstore.cpp | 1 + apps/openmw/mwworld/esmloader.cpp | 203 -------------------------- apps/openmw/mwworld/esmloader.hpp | 5 - apps/openmw/mwworld/magiceffects.cpp | 210 +++++++++++++++++++++++++++ apps/openmw/mwworld/magiceffects.hpp | 17 +++ apps/openmw/mwworld/player.cpp | 1 + 7 files changed, 230 insertions(+), 209 deletions(-) create mode 100644 apps/openmw/mwworld/magiceffects.cpp create mode 100644 apps/openmw/mwworld/magiceffects.hpp 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/esmloader.cpp b/apps/openmw/mwworld/esmloader.cpp index 8e702e7447..de16e386f2 100644 --- a/apps/openmw/mwworld/esmloader.cpp +++ b/apps/openmw/mwworld/esmloader.cpp @@ -2,26 +2,6 @@ #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 { @@ -45,187 +25,4 @@ void EsmLoader::load(const boost::filesystem::path& filepath, int& index, Loadin 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 533cf383ad..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 @@ -36,8 +33,6 @@ struct EsmLoader : public ContentLoader 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"