diff --git a/CHANGELOG.md b/CHANGELOG.md index 17337f7346..296f7d8d52 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -9,7 +9,6 @@ Bug #4203: Resurrecting an actor should close the loot GUI Bug #4700: Editor: Incorrect command implementation Bug #4744: Invisible particles must still be processed - Bug #4752: UpdateCellCommand doesn't undo properly Bug #5100: Persuasion doesn't always clamp the resulting disposition Bug #5120: Scripted object spawning updates physics system Bug #5379: Wandering NPCs falling through cantons diff --git a/apps/opencs/model/world/refcollection.cpp b/apps/opencs/model/world/refcollection.cpp index 4782bde6b9..f70e9c9fa2 100644 --- a/apps/opencs/model/world/refcollection.cpp +++ b/apps/opencs/model/world/refcollection.cpp @@ -89,12 +89,48 @@ void CSMWorld::RefCollection::load (ESM::ESMReader& reader, int cellIndex, bool else ref.mCell = cell2.mId; + if (ref.mRefNum.mContentFile != -1 && !base) + { + ref.mRefNum.mContentFile = ref.mRefNum.mIndex >> 24; + ref.mRefNum.mIndex &= 0x00ffffff; + } + unsigned int refNum = (ref.mRefNum.mIndex & 0x00ffffff) | (ref.mRefNum.hasContentFile() ? ref.mRefNum.mContentFile : 0xff) << 24; std::map::iterator iter = cache.find(refNum); - if (ref.mRefNum.mContentFile != -1 && !base) ref.mRefNum.mContentFile = ref.mRefNum.mIndex >> 24; + if (isMoved) + { + if (iter == cache.end()) + { + CSMWorld::UniversalId id(CSMWorld::UniversalId::Type_Cell, + mCells.getId(cellIndex)); + + messages.add(id, "Attempt to move a non-existent reference - RefNum index " + + std::to_string(ref.mRefNum.mIndex) + ", refID " + ref.mRefID + ", content file index " + + std::to_string(ref.mRefNum.mContentFile), + /*hint*/"", + CSMDoc::Message::Severity_Warning); + continue; + } + + int index = getIntIndex(iter->second); + + // ensure we have the same record id for setRecord() + ref.mId = getRecord(index).get().mId; + ref.mIdNum = extractIdNum(ref.mId); + + std::unique_ptr > record(new Record); + // TODO: check whether a base record be moved + record->mState = base ? RecordBase::State_BaseOnly : RecordBase::State_ModifiedOnly; + (base ? record->mBase : record->mModified) = std::move(ref); + + // overwrite original record + setRecord(index, std::move(record)); + + continue; // NOTE: assumed moved references are not deleted at the same time + } if (isDeleted) { diff --git a/apps/opencs/model/world/refcollection.hpp b/apps/opencs/model/world/refcollection.hpp index e0e88d721f..2031d2be63 100644 --- a/apps/opencs/model/world/refcollection.hpp +++ b/apps/opencs/model/world/refcollection.hpp @@ -25,7 +25,7 @@ namespace CSMWorld class RefCollection : public Collection { Collection& mCells; - std::map mRefIndex; + std::map mRefIndex; // CellRef index keyed by CSMWorld::CellRef::mIdNum int mNextId;