Convert constant effect equipment slots to refnums

esm4-texture
Evil Eye 7 months ago
parent d15be7a685
commit cdfd305ac3

@ -264,8 +264,18 @@ namespace
} }
else if (state.mVersion <= ESM::MaxOldCreatureStatsFormatVersion) else if (state.mVersion <= ESM::MaxOldCreatureStatsFormatVersion)
{ {
if constexpr (std::is_same_v<T, ESM::Creature> || std::is_same_v<T, ESM::NPC>) if constexpr (std::is_same_v<T, ESM::Creature>)
MWWorld::convertStats(state.mCreatureStats);
else if constexpr (std::is_same_v<T, ESM::NPC>)
{
MWWorld::convertStats(state.mCreatureStats); MWWorld::convertStats(state.mCreatureStats);
MWWorld::convertEnchantmentSlots(state.mCreatureStats, state.mInventory);
}
}
else if (state.mVersion <= ESM::MaxActiveSpellSlotIndexFormatVersion)
{
if constexpr (std::is_same_v<T, ESM::NPC>)
MWWorld::convertEnchantmentSlots(state.mCreatureStats, state.mInventory);
} }
if (state.mRef.mRefNum.hasContentFile()) if (state.mRef.mRefNum.hasContentFile())

@ -11,6 +11,7 @@
#include <components/esm3/npcstate.hpp> #include <components/esm3/npcstate.hpp>
#include "../mwbase/environment.hpp" #include "../mwbase/environment.hpp"
#include "../mwworld/worldmodel.hpp"
#include "../mwmechanics/magiceffects.hpp" #include "../mwmechanics/magiceffects.hpp"
@ -101,13 +102,16 @@ namespace MWWorld
} }
creatureStats.mActiveSpells.mSpells.emplace_back(params); creatureStats.mActiveSpells.mSpells.emplace_back(params);
} }
std::multimap<ESM::RefId, int> equippedItems; std::multimap<ESM::RefId, ESM::RefNum> equippedItems;
for (std::size_t i = 0; i < inventory.mItems.size(); ++i) for (std::size_t i = 0; i < inventory.mItems.size(); ++i)
{ {
const ESM::ObjectState& item = inventory.mItems[i]; ESM::ObjectState& item = inventory.mItems[i];
auto slot = inventory.mEquipmentSlots.find(i); auto slot = inventory.mEquipmentSlots.find(i);
if (slot != inventory.mEquipmentSlots.end()) if (slot != inventory.mEquipmentSlots.end())
equippedItems.emplace(item.mRef.mRefID, slot->second); {
MWBase::Environment::get().getWorldModel()->assignSaveFileRefNum(item.mRef);
equippedItems.emplace(item.mRef.mRefID, item.mRef.mRefNum);
}
} }
for (const auto& [id, oldMagnitudes] : inventory.mPermanentMagicEffectMagnitudes) for (const auto& [id, oldMagnitudes] : inventory.mPermanentMagicEffectMagnitudes)
{ {
@ -161,7 +165,7 @@ namespace MWWorld
auto [begin, end] = equippedItems.equal_range(id); auto [begin, end] = equippedItems.equal_range(id);
for (auto it = begin; it != end; ++it) for (auto it = begin; it != end; ++it)
{ {
params.mItem = { static_cast<unsigned int>(it->second), 0 }; params.mItem = it->second;
creatureStats.mActiveSpells.mSpells.emplace_back(params); creatureStats.mActiveSpells.mSpells.emplace_back(params);
} }
} }
@ -229,4 +233,28 @@ namespace MWWorld
for (auto& setting : creatureStats.mAiSettings) for (auto& setting : creatureStats.mAiSettings)
setting.mMod = 0.f; setting.mMod = 0.f;
} }
// Versions 17-27 wrote an equipment slot index to mItem
void convertEnchantmentSlots(ESM::CreatureStats& creatureStats, ESM::InventoryState& inventory)
{
for (auto& activeSpell : creatureStats.mActiveSpells.mSpells)
{
if (!activeSpell.mItem.isSet())
continue;
if (activeSpell.mFlags & ESM::ActiveSpells::Flag_Equipment)
{
auto slotIndex = activeSpell.mItem.mIndex;
auto slot = std::find_if(inventory.mEquipmentSlots.begin(), inventory.mEquipmentSlots.end(),
[=](const auto& entry) { return entry.second == slotIndex; });
if (slot != inventory.mEquipmentSlots.end() && slot->first < inventory.mItems.size())
{
ESM::CellRef& ref = inventory.mItems[slot->first].mRef;
MWBase::Environment::get().getWorldModel()->assignSaveFileRefNum(ref);
activeSpell.mItem = ref.mRefNum;
continue;
}
}
activeSpell.mItem = {};
}
}
} }

@ -14,6 +14,8 @@ namespace MWWorld
ESM::CreatureStats& creatureStats, ESM::InventoryState& inventory, ESM::NpcStats* npcStats = nullptr); ESM::CreatureStats& creatureStats, ESM::InventoryState& inventory, ESM::NpcStats* npcStats = nullptr);
void convertStats(ESM::CreatureStats& creatureStats); void convertStats(ESM::CreatureStats& creatureStats);
void convertEnchantmentSlots(ESM::CreatureStats& creatureStats, ESM::InventoryState& inventory);
} }
#endif #endif

@ -317,7 +317,12 @@ namespace MWWorld
convertMagicEffects( convertMagicEffects(
player.mObject.mCreatureStats, player.mObject.mInventory, &player.mObject.mNpcStats); player.mObject.mCreatureStats, player.mObject.mInventory, &player.mObject.mNpcStats);
else if (reader.getFormatVersion() <= ESM::MaxOldCreatureStatsFormatVersion) else if (reader.getFormatVersion() <= ESM::MaxOldCreatureStatsFormatVersion)
{
convertStats(player.mObject.mCreatureStats); convertStats(player.mObject.mCreatureStats);
convertEnchantmentSlots(player.mObject.mCreatureStats, player.mObject.mInventory);
}
else if (reader.getFormatVersion() <= ESM::MaxActiveSpellSlotIndexFormatVersion)
convertEnchantmentSlots(player.mObject.mCreatureStats, player.mObject.mInventory);
if (!player.mObject.mEnabled) if (!player.mObject.mEnabled)
{ {

@ -56,6 +56,17 @@ namespace MWWorld
} }
} }
// For fixing old saves
void assign(ESM::CellRef& ref)
{
if (!ref.mRefNum.isSet())
{
CellRef temp(ref);
temp.getOrAssignRefNum(mLastGenerated);
ref.mRefNum = temp.getRefNum();
}
}
private: private:
std::size_t mRevision = 0; std::size_t mRevision = 0;
std::unordered_map<ESM::RefNum, Ptr> mIndex; std::unordered_map<ESM::RefNum, Ptr> mIndex;

@ -81,6 +81,8 @@ namespace MWWorld
void deregisterLiveCellRef(const LiveCellRefBase& ref) noexcept { mPtrRegistry.remove(ref); } void deregisterLiveCellRef(const LiveCellRefBase& ref) noexcept { mPtrRegistry.remove(ref); }
void assignSaveFileRefNum(ESM::CellRef& ref) { mPtrRegistry.assign(ref); }
template <typename Fn> template <typename Fn>
void forEachLoadedCellStore(Fn&& fn) void forEachLoadedCellStore(Fn&& fn)
{ {

@ -168,15 +168,8 @@ namespace ESM
esm.getHNT(params.mFlags, "FLAG"); esm.getHNT(params.mFlags, "FLAG");
} }
if (esm.peekNextSub("ITEM")) if (esm.peekNextSub("ITEM"))
{
if (format <= MaxActiveSpellSlotIndexFormatVersion)
// Previous versions saved slot index in this record.
// Ignore these values as we can't use them
esm.getFormId(true, "ITEM");
else
params.mItem = esm.getFormId(true, "ITEM"); params.mItem = esm.getFormId(true, "ITEM");
} }
}
if (esm.isNextSub("WORS")) if (esm.isNextSub("WORS"))
{ {
esm.getHT(params.mWorsenings); esm.getHT(params.mWorsenings);

Loading…
Cancel
Save