2013-07-06 15:03:18 +00:00
|
|
|
#include "refcollection.hpp"
|
|
|
|
|
2015-04-25 07:20:02 +00:00
|
|
|
#include <components/esm/loadcell.hpp>
|
2014-05-20 07:02:22 +00:00
|
|
|
|
2013-07-06 15:03:18 +00:00
|
|
|
#include "ref.hpp"
|
|
|
|
#include "cell.hpp"
|
2014-01-21 20:37:21 +00:00
|
|
|
#include "universalid.hpp"
|
|
|
|
#include "record.hpp"
|
2013-07-06 15:03:18 +00:00
|
|
|
|
2014-05-20 07:02:22 +00:00
|
|
|
void CSMWorld::RefCollection::load (ESM::ESMReader& reader, int cellIndex, bool base,
|
2015-04-26 04:55:40 +00:00
|
|
|
std::map<ESM::RefNum, std::string>& cache, CSMDoc::Messages& messages)
|
2013-07-06 15:03:18 +00:00
|
|
|
{
|
|
|
|
Record<Cell> cell = mCells.getRecord (cellIndex);
|
|
|
|
|
|
|
|
Cell& cell2 = base ? cell.mBase : cell.mModified;
|
|
|
|
|
|
|
|
CellRef ref;
|
2016-03-24 10:12:05 +00:00
|
|
|
ref.mNew = false;
|
2015-04-25 07:20:02 +00:00
|
|
|
ESM::MovedCellRef mref;
|
2020-04-06 05:43:05 +00:00
|
|
|
mref.mRefNum.mIndex = 0;
|
2015-07-21 17:25:43 +00:00
|
|
|
bool isDeleted = false;
|
2014-05-20 07:02:22 +00:00
|
|
|
|
2020-04-06 05:43:05 +00:00
|
|
|
while (ESM::Cell::getNextRef(reader, ref, isDeleted, true, &mref))
|
2013-07-06 15:03:18 +00:00
|
|
|
{
|
2015-01-10 11:35:59 +00:00
|
|
|
// Keep mOriginalCell empty when in modified (as an indicator that the
|
|
|
|
// original cell will always be equal the current cell).
|
|
|
|
ref.mOriginalCell = base ? cell2.mId : "";
|
2013-07-06 15:03:18 +00:00
|
|
|
|
2015-01-09 11:05:16 +00:00
|
|
|
if (cell.get().isExterior())
|
|
|
|
{
|
2018-12-23 16:05:00 +00:00
|
|
|
// Autocalculate the cell index from coordinates first
|
2015-01-09 11:05:16 +00:00
|
|
|
std::pair<int, int> index = ref.getCellIndex();
|
|
|
|
|
2018-12-23 16:05:00 +00:00
|
|
|
ref.mCell = "#" + std::to_string(index.first) + " " + std::to_string(index.second);
|
2015-04-26 01:35:46 +00:00
|
|
|
|
2018-12-23 16:05:00 +00:00
|
|
|
// Handle non-base moved references
|
|
|
|
if (!base && mref.mRefNum.mIndex != 0)
|
2015-04-25 07:20:02 +00:00
|
|
|
{
|
2018-12-23 16:05:00 +00:00
|
|
|
// Moved references must have a link back to their original cell
|
|
|
|
// See discussion: https://forum.openmw.org/viewtopic.php?f=6&t=577&start=30
|
2015-04-26 01:35:46 +00:00
|
|
|
ref.mOriginalCell = cell2.mId;
|
|
|
|
|
2018-12-23 16:05:00 +00:00
|
|
|
// Some mods may move references outside of the bounds, which often happens they are deleted.
|
|
|
|
// This results in nonsensical autocalculated cell IDs, so we must use the record target cell.
|
|
|
|
|
|
|
|
// Log a warning if the record target cell is different
|
2015-04-26 04:55:40 +00:00
|
|
|
if (index.first != mref.mTarget[0] || index.second != mref.mTarget[1])
|
2015-04-26 01:35:46 +00:00
|
|
|
{
|
2018-12-23 16:05:00 +00:00
|
|
|
std::string indexCell = ref.mCell;
|
|
|
|
ref.mCell = "#" + std::to_string(mref.mTarget[0]) + " " + std::to_string(mref.mTarget[1]);
|
|
|
|
|
|
|
|
CSMWorld::UniversalId id(CSMWorld::UniversalId::Type_Cell, mCells.getId (cellIndex));
|
|
|
|
messages.add(id, "The position of the moved reference " + ref.mRefID + " (cell " + indexCell + ")"
|
|
|
|
" does not match the target cell (" + ref.mCell + ")",
|
|
|
|
std::string(), CSMDoc::Message::Severity_Warning);
|
2015-04-26 01:35:46 +00:00
|
|
|
}
|
2015-04-25 07:20:02 +00:00
|
|
|
}
|
2015-01-09 11:05:16 +00:00
|
|
|
}
|
|
|
|
else
|
|
|
|
ref.mCell = cell2.mId;
|
2013-07-06 15:03:18 +00:00
|
|
|
|
2020-04-06 05:43:05 +00:00
|
|
|
mref.mRefNum.mIndex = 0;
|
|
|
|
|
2015-04-27 22:07:01 +00:00
|
|
|
// ignore content file number
|
|
|
|
std::map<ESM::RefNum, std::string>::iterator iter = cache.begin();
|
2020-12-08 22:10:58 +00:00
|
|
|
unsigned int thisIndex = ref.mRefNum.mIndex & 0x00ffffff;
|
|
|
|
if (ref.mRefNum.mContentFile != -1 && !base) ref.mRefNum.mContentFile = ref.mRefNum.mIndex >> 24;
|
|
|
|
|
2015-04-27 22:07:01 +00:00
|
|
|
for (; iter != cache.end(); ++iter)
|
|
|
|
{
|
2020-12-08 22:10:58 +00:00
|
|
|
if (thisIndex == iter->first.mIndex)
|
2015-04-27 22:07:01 +00:00
|
|
|
break;
|
|
|
|
}
|
2014-05-20 07:28:18 +00:00
|
|
|
|
2015-07-21 17:25:43 +00:00
|
|
|
if (isDeleted)
|
2014-05-20 07:02:22 +00:00
|
|
|
{
|
2015-04-26 04:55:40 +00:00
|
|
|
if (iter==cache.end())
|
2014-05-20 07:28:18 +00:00
|
|
|
{
|
|
|
|
CSMWorld::UniversalId id (CSMWorld::UniversalId::Type_Cell,
|
|
|
|
mCells.getId (cellIndex));
|
|
|
|
|
2018-12-23 16:05:00 +00:00
|
|
|
messages.add (id, "Attempt to delete a non-existent reference");
|
2014-05-20 07:28:18 +00:00
|
|
|
continue;
|
|
|
|
}
|
|
|
|
|
|
|
|
int index = getIndex (iter->second);
|
|
|
|
|
|
|
|
Record<CellRef> record = getRecord (index);
|
|
|
|
|
2015-07-15 17:53:08 +00:00
|
|
|
if (base)
|
2014-05-20 07:28:18 +00:00
|
|
|
{
|
|
|
|
removeRows (index, 1);
|
2015-04-26 04:55:40 +00:00
|
|
|
cache.erase (iter);
|
2014-05-20 07:28:18 +00:00
|
|
|
}
|
|
|
|
else
|
|
|
|
{
|
|
|
|
record.mState = RecordBase::State_Deleted;
|
|
|
|
setRecord (index, record);
|
|
|
|
}
|
2013-07-06 15:03:18 +00:00
|
|
|
|
2014-05-20 07:02:22 +00:00
|
|
|
continue;
|
|
|
|
}
|
|
|
|
|
2015-04-26 04:55:40 +00:00
|
|
|
if (iter==cache.end())
|
2014-05-20 07:02:22 +00:00
|
|
|
{
|
|
|
|
// new reference
|
|
|
|
ref.mId = getNewId();
|
|
|
|
|
|
|
|
Record<CellRef> record;
|
|
|
|
record.mState = base ? RecordBase::State_BaseOnly : RecordBase::State_ModifiedOnly;
|
|
|
|
(base ? record.mBase : record.mModified) = ref;
|
2013-07-06 15:03:18 +00:00
|
|
|
|
2014-05-20 07:02:22 +00:00
|
|
|
appendRecord (record);
|
|
|
|
|
2015-04-26 04:55:40 +00:00
|
|
|
cache.insert (std::make_pair (ref.mRefNum, ref.mId));
|
2014-05-20 07:02:22 +00:00
|
|
|
}
|
|
|
|
else
|
|
|
|
{
|
|
|
|
// old reference -> merge
|
|
|
|
ref.mId = iter->second;
|
|
|
|
|
|
|
|
int index = getIndex (ref.mId);
|
|
|
|
|
|
|
|
Record<CellRef> record = getRecord (index);
|
|
|
|
record.mState = base ? RecordBase::State_BaseOnly : RecordBase::State_Modified;
|
|
|
|
(base ? record.mBase : record.mModified) = ref;
|
|
|
|
|
|
|
|
setRecord (index, record);
|
|
|
|
}
|
|
|
|
}
|
2013-07-30 10:53:03 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
std::string CSMWorld::RefCollection::getNewId()
|
|
|
|
{
|
2018-12-23 16:05:00 +00:00
|
|
|
return "ref#" + std::to_string(mNextId++);
|
2014-01-21 20:37:21 +00:00
|
|
|
}
|