From ae4bf04798b3ad25a8490d448f8d53b06347e567 Mon Sep 17 00:00:00 2001 From: Mads Buvik Sandvei Date: Tue, 28 May 2024 23:30:28 +0200 Subject: [PATCH] Fix soul gems losing their souls when splitting stacks between containers. --- apps/openmw/mwgui/containeritemmodel.cpp | 4 +- apps/openmw/mwgui/inventoryitemmodel.cpp | 6 +- apps/openmw/mwworld/manualref.cpp | 94 ++++++++++++++++++++++++ apps/openmw/mwworld/manualref.hpp | 1 + 4 files changed, 102 insertions(+), 3 deletions(-) diff --git a/apps/openmw/mwgui/containeritemmodel.cpp b/apps/openmw/mwgui/containeritemmodel.cpp index af1b585cff..09b66672ba 100644 --- a/apps/openmw/mwgui/containeritemmodel.cpp +++ b/apps/openmw/mwgui/containeritemmodel.cpp @@ -7,6 +7,7 @@ #include "../mwworld/class.hpp" #include "../mwworld/containerstore.hpp" +#include "../mwworld/manualref.hpp" #include "../mwbase/environment.hpp" #include "../mwbase/mechanicsmanager.hpp" @@ -114,7 +115,8 @@ namespace MWGui MWWorld::ContainerStore& store = source.first.getClass().getContainerStore(source.first); if (item.mBase.getContainerStore() == &store) throw std::runtime_error("Item to copy needs to be from a different container!"); - return *store.add(item.mBase.getCellRef().getRefId(), count, allowAutoEquip); + MWWorld::ManualRef newRef(*MWBase::Environment::get().getESMStore(), item.mBase, count); + return *store.add(newRef.getPtr(), count, allowAutoEquip); } void ContainerItemModel::removeItem(const ItemStack& item, size_t count) diff --git a/apps/openmw/mwgui/inventoryitemmodel.cpp b/apps/openmw/mwgui/inventoryitemmodel.cpp index b52d49b7c2..7464290947 100644 --- a/apps/openmw/mwgui/inventoryitemmodel.cpp +++ b/apps/openmw/mwgui/inventoryitemmodel.cpp @@ -8,6 +8,7 @@ #include "../mwworld/class.hpp" #include "../mwworld/containerstore.hpp" #include "../mwworld/inventorystore.hpp" +#include "../mwworld/manualref.hpp" #include "../mwbase/environment.hpp" #include "../mwbase/mechanicsmanager.hpp" @@ -57,8 +58,9 @@ namespace MWGui { if (item.mBase.getContainerStore() == &mActor.getClass().getContainerStore(mActor)) throw std::runtime_error("Item to copy needs to be from a different container!"); - return *mActor.getClass().getContainerStore(mActor).add( - item.mBase.getCellRef().getRefId(), count, allowAutoEquip); + + MWWorld::ManualRef newRef(*MWBase::Environment::get().getESMStore(), item.mBase, count); + return *mActor.getClass().getContainerStore(mActor).add(newRef.getPtr(), count, allowAutoEquip); } void InventoryItemModel::removeItem(const ItemStack& item, size_t count) diff --git a/apps/openmw/mwworld/manualref.cpp b/apps/openmw/mwworld/manualref.cpp index c6c0444754..d4979eb494 100644 --- a/apps/openmw/mwworld/manualref.cpp +++ b/apps/openmw/mwworld/manualref.cpp @@ -19,6 +19,14 @@ namespace refValue = MWWorld::LiveCellRef(cellRef, base); ptrValue = MWWorld::Ptr(&std::any_cast&>(refValue), nullptr); } + + template + void create( + const MWWorld::Store& list, const MWWorld::Ptr& template_, std::any& refValue, MWWorld::Ptr& ptrValue) + { + refValue = *static_cast*>(template_.getBase()); + ptrValue = MWWorld::Ptr(&std::any_cast&>(refValue), nullptr); + } } MWWorld::ManualRef::ManualRef(const MWWorld::ESMStore& store, const ESM::RefId& name, const int count) @@ -103,3 +111,89 @@ MWWorld::ManualRef::ManualRef(const MWWorld::ESMStore& store, const ESM::RefId& mPtr.getCellRef().setCount(count); } + +MWWorld::ManualRef::ManualRef(const ESMStore& store, const Ptr& template_, const int count) +{ + ESM::RefId name = template_.getCellRef().getRefId(); + switch (store.find(name)) + { + case ESM::REC_ACTI: + create(store.get(), template_, mRef, mPtr); + break; + case ESM::REC_ALCH: + create(store.get(), template_, mRef, mPtr); + break; + case ESM::REC_APPA: + create(store.get(), template_, mRef, mPtr); + break; + case ESM::REC_ARMO: + create(store.get(), template_, mRef, mPtr); + break; + case ESM::REC_BOOK: + create(store.get(), template_, mRef, mPtr); + break; + case ESM::REC_CLOT: + create(store.get(), template_, mRef, mPtr); + break; + case ESM::REC_CONT: + create(store.get(), template_, mRef, mPtr); + break; + case ESM::REC_CREA: + create(store.get(), template_, mRef, mPtr); + break; + case ESM::REC_DOOR: + create(store.get(), template_, mRef, mPtr); + break; + case ESM::REC_INGR: + create(store.get(), template_, mRef, mPtr); + break; + case ESM::REC_LEVC: + create(store.get(), template_, mRef, mPtr); + break; + case ESM::REC_LEVI: + create(store.get(), template_, mRef, mPtr); + break; + case ESM::REC_LIGH: + create(store.get(), template_, mRef, mPtr); + break; + case ESM::REC_LOCK: + create(store.get(), template_, mRef, mPtr); + break; + case ESM::REC_MISC: + create(store.get(), template_, mRef, mPtr); + break; + case ESM::REC_NPC_: + create(store.get(), template_, mRef, mPtr); + break; + case ESM::REC_PROB: + create(store.get(), template_, mRef, mPtr); + break; + case ESM::REC_REPA: + create(store.get(), template_, mRef, mPtr); + break; + case ESM::REC_STAT: + create(store.get(), template_, mRef, mPtr); + break; + case ESM::REC_WEAP: + create(store.get(), template_, mRef, mPtr); + break; + case ESM::REC_BODY: + create(store.get(), template_, mRef, mPtr); + break; + case ESM::REC_STAT4: + create(store.get(), template_, mRef, mPtr); + break; + case ESM::REC_TERM4: + create(store.get(), template_, mRef, mPtr); + break; + case 0: + throw std::logic_error("failed to create manual cell ref for " + name.toDebugString() + " (unknown ID)"); + + default: + throw std::logic_error("failed to create manual cell ref for " + name.toDebugString() + " (unknown type)"); + } + + mPtr.getCellRef().setCount(count); + mPtr.getCellRef().unsetRefNum(); + mPtr.getRefData().setLuaScripts(nullptr); +} diff --git a/apps/openmw/mwworld/manualref.hpp b/apps/openmw/mwworld/manualref.hpp index 8356fd0a03..f46cde7322 100644 --- a/apps/openmw/mwworld/manualref.hpp +++ b/apps/openmw/mwworld/manualref.hpp @@ -18,6 +18,7 @@ namespace MWWorld public: ManualRef(const MWWorld::ESMStore& store, const ESM::RefId& name, const int count = 1); + ManualRef(const MWWorld::ESMStore& store, const MWWorld::Ptr& template_, const int count = 1); const Ptr& getPtr() const { return mPtr; } };