From 48d5789aeb94c5916395b16929438350146ba09f Mon Sep 17 00:00:00 2001 From: scrawl Date: Mon, 1 Dec 2014 22:10:06 +0100 Subject: [PATCH] Use a separate flag for references deleted by a content file (Fixes #2018) The flag must be separate so as to not contaminate the user's savegame. Fixes the following use cases that were broken before: - Content file edits a reference that was already deleted by a previously loaded content file -> reference must stay deleted - Changed or new content file deletes a reference that is already present in the user's savegame -> reference must be deleted - Said content file is disabled again - reference must be undeleted --- apps/openmw/mwworld/cellstore.cpp | 2 +- apps/openmw/mwworld/cellstore.hpp | 2 +- apps/openmw/mwworld/localscripts.cpp | 2 +- apps/openmw/mwworld/refdata.cpp | 19 ++++++++++++++++--- apps/openmw/mwworld/refdata.hpp | 11 ++++++++++- apps/openmw/mwworld/scene.cpp | 2 +- apps/openmw/mwworld/worldimp.cpp | 2 +- 7 files changed, 31 insertions(+), 9 deletions(-) diff --git a/apps/openmw/mwworld/cellstore.cpp b/apps/openmw/mwworld/cellstore.cpp index ce8d77758..52e70fef2 100644 --- a/apps/openmw/mwworld/cellstore.cpp +++ b/apps/openmw/mwworld/cellstore.cpp @@ -156,7 +156,7 @@ namespace MWWorld LiveRef liveCellRef (ref, ptr); if (deleted) - liveCellRef.mData.setCount (0); + liveCellRef.mData.setDeleted(true); if (iter != mList.end()) *iter = liveCellRef; diff --git a/apps/openmw/mwworld/cellstore.hpp b/apps/openmw/mwworld/cellstore.hpp index e322ef4a4..05e7b0b2e 100644 --- a/apps/openmw/mwworld/cellstore.hpp +++ b/apps/openmw/mwworld/cellstore.hpp @@ -196,7 +196,7 @@ namespace MWWorld for (typename List::List::iterator iter (list.mList.begin()); iter!=list.mList.end(); ++iter) { - if (!iter->mData.getCount()) + if (iter->mData.isDeleted()) continue; if (!functor (MWWorld::Ptr(&*iter, this))) return false; diff --git a/apps/openmw/mwworld/localscripts.cpp b/apps/openmw/mwworld/localscripts.cpp index f3a647124..d74aab694 100644 --- a/apps/openmw/mwworld/localscripts.cpp +++ b/apps/openmw/mwworld/localscripts.cpp @@ -17,7 +17,7 @@ namespace cellRefList.mList.begin()); iter!=cellRefList.mList.end(); ++iter) { - if (!iter->mBase->mScript.empty() && iter->mData.getCount()) + if (!iter->mBase->mScript.empty() && !iter->mData.isDeleted()) { localScripts.add (iter->mBase->mScript, MWWorld::Ptr (&*iter, cell)); } diff --git a/apps/openmw/mwworld/refdata.cpp b/apps/openmw/mwworld/refdata.cpp index f4bc64b70..78fea2b86 100644 --- a/apps/openmw/mwworld/refdata.cpp +++ b/apps/openmw/mwworld/refdata.cpp @@ -23,6 +23,7 @@ namespace MWWorld mPosition = refData.mPosition; mLocalRotation = refData.mLocalRotation; mChanged = refData.mChanged; + mDeleted = refData.mDeleted; mCustomData = refData.mCustomData ? refData.mCustomData->clone() : 0; } @@ -36,7 +37,7 @@ namespace MWWorld } RefData::RefData() - : mBaseNode(0), mHasLocals (false), mEnabled (true), mCount (1), mCustomData (0), mChanged(false) + : mBaseNode(0), mHasLocals (false), mEnabled (true), mCount (1), mCustomData (0), mChanged(false), mDeleted(false) { for (int i=0; i<3; ++i) { @@ -49,7 +50,8 @@ namespace MWWorld RefData::RefData (const ESM::CellRef& cellRef) : mBaseNode(0), mHasLocals (false), mEnabled (true), mCount (1), mPosition (cellRef.mPos), mCustomData (0), - mChanged(false) // Loading from ESM/ESP files -> assume unchanged + mChanged(false), // Loading from ESM/ESP files -> assume unchanged + mDeleted(false) { mLocalRotation.rot[0]=0; mLocalRotation.rot[1]=0; @@ -59,7 +61,8 @@ namespace MWWorld RefData::RefData (const ESM::ObjectState& objectState) : mBaseNode (0), mHasLocals (false), mEnabled (objectState.mEnabled), mCount (objectState.mCount), mPosition (objectState.mPosition), mCustomData (0), - mChanged(true) // Loading from a savegame -> assume changed + mChanged(true), // Loading from a savegame -> assume changed + mDeleted(false) { for (int i=0; i<3; ++i) mLocalRotation.rot[i] = objectState.mLocalRotation[i]; @@ -167,6 +170,16 @@ namespace MWWorld mCount = count; } + void RefData::setDeleted(bool deleted) + { + mDeleted = deleted; + } + + bool RefData::isDeleted() const + { + return mDeleted || mCount == 0; + } + MWScript::Locals& RefData::getLocals() { return mLocals; diff --git a/apps/openmw/mwworld/refdata.hpp b/apps/openmw/mwworld/refdata.hpp index db66c091b..1ed3cd79d 100644 --- a/apps/openmw/mwworld/refdata.hpp +++ b/apps/openmw/mwworld/refdata.hpp @@ -37,6 +37,8 @@ namespace MWWorld bool mEnabled; int mCount; // 0: deleted + bool mDeleted; // separate delete flag used for deletion by a content file + ESM::Position mPosition; LocalRotation mLocalRotation; @@ -86,12 +88,19 @@ namespace MWWorld void setLocals (const ESM::Script& script); void setCount (int count); - /// Set object count (an object pile is a simple object with a count >1). + ///< Set object count (an object pile is a simple object with a count >1). /// /// \warning Do not call setCount() to add or remove objects from a /// container or an actor's inventory. Call ContainerStore::add() or /// ContainerStore::remove() instead. + /// This flag is only used for content stack loading and will not be stored in the savegame. + /// If the object was deleted by gameplay, then use setCount(0) instead. + void setDeleted(bool deleted); + + /// Returns true if the object was either deleted by the content file or by gameplay. + bool isDeleted() const; + MWScript::Locals& getLocals(); bool isEnabled() const; diff --git a/apps/openmw/mwworld/scene.cpp b/apps/openmw/mwworld/scene.cpp index 6f18a6ef3..02c9db9ea 100644 --- a/apps/openmw/mwworld/scene.cpp +++ b/apps/openmw/mwworld/scene.cpp @@ -75,7 +75,7 @@ namespace ptr.getCellRef().setScale(2); } - if (ptr.getRefData().getCount() && ptr.getRefData().isEnabled()) + if (!ptr.getRefData().isDeleted() && ptr.getRefData().isEnabled()) { try { diff --git a/apps/openmw/mwworld/worldimp.cpp b/apps/openmw/mwworld/worldimp.cpp index 4c2bd669b..7baf1d3e5 100644 --- a/apps/openmw/mwworld/worldimp.cpp +++ b/apps/openmw/mwworld/worldimp.cpp @@ -1057,7 +1057,7 @@ namespace MWWorld void World::deleteObject (const Ptr& ptr) { - if (ptr.getRefData().getCount() > 0) + if (!ptr.getRefData().isDeleted()) { ptr.getRefData().setCount(0);