mirror of
https://github.com/TES3MP/openmw-tes3mp.git
synced 2025-01-20 07:53:51 +00:00
removed redundant deletion flag from CellRef
This commit is contained in:
parent
18e7e83585
commit
43dd3b8ef2
10 changed files with 91 additions and 133 deletions
|
@ -236,7 +236,9 @@ void loadCell(ESM::Cell &cell, ESM::ESMReader &esm, Arguments& info)
|
||||||
// Loop through all the references
|
// Loop through all the references
|
||||||
ESM::CellRef ref;
|
ESM::CellRef ref;
|
||||||
if(!quiet) std::cout << " References:\n";
|
if(!quiet) std::cout << " References:\n";
|
||||||
while(cell.getNextRef(esm, ref))
|
|
||||||
|
bool deleted = false;
|
||||||
|
while(cell.getNextRef(esm, ref, deleted))
|
||||||
{
|
{
|
||||||
if (save) {
|
if (save) {
|
||||||
info.data.mCellRefs[&cell].push_back(ref);
|
info.data.mCellRefs[&cell].push_back(ref);
|
||||||
|
@ -251,6 +253,7 @@ void loadCell(ESM::Cell &cell, ESM::ESMReader &esm, Arguments& info)
|
||||||
std::cout << " Uses/health: '" << ref.mCharge << "'\n";
|
std::cout << " Uses/health: '" << ref.mCharge << "'\n";
|
||||||
std::cout << " Gold value: '" << ref.mGoldValue << "'\n";
|
std::cout << " Gold value: '" << ref.mGoldValue << "'\n";
|
||||||
std::cout << " Blocked: '" << static_cast<int>(ref.mReferenceBlocked) << "'" << std::endl;
|
std::cout << " Blocked: '" << static_cast<int>(ref.mReferenceBlocked) << "'" << std::endl;
|
||||||
|
std::cout << " Deleted: " << deleted << std::endl;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -8,6 +8,5 @@ void CSMWorld::CellRef::load (ESM::ESMReader &esm, Cell& cell, const std::string
|
||||||
mId = id;
|
mId = id;
|
||||||
mCell = cell.mId;
|
mCell = cell.mId;
|
||||||
|
|
||||||
if (!mDeleted)
|
cell.addRef (mId);
|
||||||
cell.addRef (mId);
|
|
||||||
}
|
}
|
|
@ -14,7 +14,8 @@ void CSMWorld::RefCollection::load (ESM::ESMReader& reader, int cellIndex, bool
|
||||||
|
|
||||||
CellRef ref;
|
CellRef ref;
|
||||||
|
|
||||||
while (cell2.getNextRef (reader, ref))
|
bool deleted = false;
|
||||||
|
while (cell2.getNextRef (reader, ref, deleted))
|
||||||
{
|
{
|
||||||
/// \todo handle deleted and moved references
|
/// \todo handle deleted and moved references
|
||||||
ref.load (reader, cell2, getNewId());
|
ref.load (reader, cell2, getNewId());
|
||||||
|
|
|
@ -35,32 +35,30 @@ namespace MWWorld
|
||||||
{
|
{
|
||||||
|
|
||||||
template <typename X>
|
template <typename X>
|
||||||
void CellRefList<X>::load(ESM::CellRef &ref, const MWWorld::ESMStore &esmStore)
|
void CellRefList<X>::load(ESM::CellRef &ref, bool deleted, const MWWorld::ESMStore &esmStore)
|
||||||
{
|
{
|
||||||
// Get existing reference, in case we need to overwrite it.
|
|
||||||
typename std::list<LiveRef>::iterator iter = std::find(mList.begin(), mList.end(), ref.mRefnum);
|
|
||||||
|
|
||||||
// Skip this when reference was deleted.
|
|
||||||
// TODO: Support respawning references, in this case, we need to track it somehow.
|
|
||||||
if (ref.mDeleted) {
|
|
||||||
if (iter != mList.end())
|
|
||||||
mList.erase(iter);
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
// for throwing exception on unhandled record type
|
|
||||||
const MWWorld::Store<X> &store = esmStore.get<X>();
|
const MWWorld::Store<X> &store = esmStore.get<X>();
|
||||||
const X *ptr = store.search(ref.mRefID);
|
|
||||||
|
|
||||||
/// \note no longer redundant - changed to Store<X>::search(), don't throw
|
if (const X *ptr = store.search (ref.mRefID))
|
||||||
/// an exception on miss, try to continue (that's how MW does it, anyway)
|
{
|
||||||
if (ptr == NULL) {
|
typename std::list<LiveRef>::iterator iter =
|
||||||
std::cout << "Warning: could not resolve cell reference " << ref.mRefID << ", trying to continue anyway" << std::endl;
|
std::find(mList.begin(), mList.end(), ref.mRefnum);
|
||||||
} else {
|
|
||||||
if (iter != mList.end())
|
LiveRef liveCellRef (ref, ptr);
|
||||||
*iter = LiveRef(ref, ptr);
|
|
||||||
else
|
if (deleted)
|
||||||
mList.push_back(LiveRef(ref, ptr));
|
liveCellRef.mData.setCount (0);
|
||||||
|
|
||||||
|
if (iter != mList.end())
|
||||||
|
*iter = liveCellRef;
|
||||||
|
else
|
||||||
|
mList.push_back (liveCellRef);
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
std::cerr
|
||||||
|
<< "Error: could not resolve cell reference " << ref.mRefID
|
||||||
|
<< " (dropping reference)" << std::endl;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -117,16 +115,13 @@ namespace MWWorld
|
||||||
ESM::CellRef ref;
|
ESM::CellRef ref;
|
||||||
|
|
||||||
// Get each reference in turn
|
// Get each reference in turn
|
||||||
while (mCell->getNextRef (esm[index], ref))
|
bool deleted = false;
|
||||||
|
while (mCell->getNextRef (esm[index], ref, deleted))
|
||||||
{
|
{
|
||||||
std::string lowerCase = Misc::StringUtils::lowerCase (ref.mRefID);
|
if (deleted)
|
||||||
if (ref.mDeleted) {
|
|
||||||
// Right now, don't do anything. Where is "listRefs" actually used, anyway?
|
|
||||||
// Skipping for now...
|
|
||||||
continue;
|
continue;
|
||||||
}
|
|
||||||
|
|
||||||
mIds.push_back (lowerCase);
|
mIds.push_back (Misc::StringUtils::lowerCase (ref.mRefID));
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -135,7 +130,7 @@ namespace MWWorld
|
||||||
|
|
||||||
void CellStore::loadRefs(const MWWorld::ESMStore &store, std::vector<ESM::ESMReader> &esm)
|
void CellStore::loadRefs(const MWWorld::ESMStore &store, std::vector<ESM::ESMReader> &esm)
|
||||||
{
|
{
|
||||||
assert (mCell);
|
assert (mCell);
|
||||||
|
|
||||||
if (mCell->mContextList.empty())
|
if (mCell->mContextList.empty())
|
||||||
return; // this is a dynamically generated cell -> skipping.
|
return; // this is a dynamically generated cell -> skipping.
|
||||||
|
@ -150,102 +145,25 @@ namespace MWWorld
|
||||||
ESM::CellRef ref;
|
ESM::CellRef ref;
|
||||||
|
|
||||||
// Get each reference in turn
|
// Get each reference in turn
|
||||||
while(mCell->getNextRef(esm[index], ref))
|
bool deleted = false;
|
||||||
|
while(mCell->getNextRef(esm[index], ref, deleted))
|
||||||
{
|
{
|
||||||
// Don't load reference if it was moved to a different cell.
|
// Don't load reference if it was moved to a different cell.
|
||||||
std::string lowerCase = Misc::StringUtils::lowerCase(ref.mRefID);
|
|
||||||
ESM::MovedCellRefTracker::const_iterator iter = std::find(mCell->mMovedRefs.begin(), mCell->mMovedRefs.end(), ref.mRefnum);
|
ESM::MovedCellRefTracker::const_iterator iter = std::find(mCell->mMovedRefs.begin(), mCell->mMovedRefs.end(), ref.mRefnum);
|
||||||
if (iter != mCell->mMovedRefs.end()) {
|
if (iter != mCell->mMovedRefs.end()) {
|
||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
int rec = store.find(ref.mRefID);
|
|
||||||
|
|
||||||
ref.mRefID = lowerCase;
|
loadRef (ref, deleted, store);
|
||||||
|
|
||||||
/* We can optimize this further by storing the pointer to the
|
|
||||||
record itself in store.all, so that we don't need to look it
|
|
||||||
up again here. However, never optimize. There are infinite
|
|
||||||
opportunities to do that later.
|
|
||||||
*/
|
|
||||||
switch(rec)
|
|
||||||
{
|
|
||||||
case ESM::REC_ACTI: mActivators.load(ref, store); break;
|
|
||||||
case ESM::REC_ALCH: mPotions.load(ref, store); break;
|
|
||||||
case ESM::REC_APPA: mAppas.load(ref, store); break;
|
|
||||||
case ESM::REC_ARMO: mArmors.load(ref, store); break;
|
|
||||||
case ESM::REC_BOOK: mBooks.load(ref, store); break;
|
|
||||||
case ESM::REC_CLOT: mClothes.load(ref, store); break;
|
|
||||||
case ESM::REC_CONT: mContainers.load(ref, store); break;
|
|
||||||
case ESM::REC_CREA: mCreatures.load(ref, store); break;
|
|
||||||
case ESM::REC_DOOR: mDoors.load(ref, store); break;
|
|
||||||
case ESM::REC_INGR: mIngreds.load(ref, store); break;
|
|
||||||
case ESM::REC_LEVC: mCreatureLists.load(ref, store); break;
|
|
||||||
case ESM::REC_LEVI: mItemLists.load(ref, store); break;
|
|
||||||
case ESM::REC_LIGH: mLights.load(ref, store); break;
|
|
||||||
case ESM::REC_LOCK: mLockpicks.load(ref, store); break;
|
|
||||||
case ESM::REC_MISC: mMiscItems.load(ref, store); break;
|
|
||||||
case ESM::REC_NPC_: mNpcs.load(ref, store); break;
|
|
||||||
case ESM::REC_PROB: mProbes.load(ref, store); break;
|
|
||||||
case ESM::REC_REPA: mRepairs.load(ref, store); break;
|
|
||||||
case ESM::REC_STAT: mStatics.load(ref, store); break;
|
|
||||||
case ESM::REC_WEAP: mWeapons.load(ref, store); break;
|
|
||||||
|
|
||||||
case 0: std::cout << "Cell reference " + ref.mRefID + " not found!\n"; break;
|
|
||||||
default:
|
|
||||||
std::cout << "WARNING: Ignoring reference '" << ref.mRefID << "' of unhandled type\n";
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// Load moved references, from separately tracked list.
|
// Load moved references, from separately tracked list.
|
||||||
for (ESM::CellRefTracker::const_iterator it = mCell->mLeasedRefs.begin(); it != mCell->mLeasedRefs.end(); ++it)
|
for (ESM::CellRefTracker::const_iterator it = mCell->mLeasedRefs.begin(); it != mCell->mLeasedRefs.end(); ++it)
|
||||||
{
|
{
|
||||||
// Doesn't seem to work in one line... huh? Too sleepy to check...
|
|
||||||
ESM::CellRef &ref = const_cast<ESM::CellRef&>(*it);
|
ESM::CellRef &ref = const_cast<ESM::CellRef&>(*it);
|
||||||
//ESM::CellRef &ref = const_cast<ESM::CellRef&>(it->second);
|
|
||||||
|
|
||||||
std::string lowerCase;
|
|
||||||
|
|
||||||
std::transform (ref.mRefID.begin(), ref.mRefID.end(), std::back_inserter (lowerCase),
|
|
||||||
(int(*)(int)) std::tolower);
|
|
||||||
|
|
||||||
int rec = store.find(ref.mRefID);
|
|
||||||
|
|
||||||
ref.mRefID = lowerCase;
|
|
||||||
|
|
||||||
/* We can optimize this further by storing the pointer to the
|
|
||||||
record itself in store.all, so that we don't need to look it
|
|
||||||
up again here. However, never optimize. There are infinite
|
|
||||||
opportunities to do that later.
|
|
||||||
*/
|
|
||||||
switch(rec)
|
|
||||||
{
|
|
||||||
case ESM::REC_ACTI: mActivators.load(ref, store); break;
|
|
||||||
case ESM::REC_ALCH: mPotions.load(ref, store); break;
|
|
||||||
case ESM::REC_APPA: mAppas.load(ref, store); break;
|
|
||||||
case ESM::REC_ARMO: mArmors.load(ref, store); break;
|
|
||||||
case ESM::REC_BOOK: mBooks.load(ref, store); break;
|
|
||||||
case ESM::REC_CLOT: mClothes.load(ref, store); break;
|
|
||||||
case ESM::REC_CONT: mContainers.load(ref, store); break;
|
|
||||||
case ESM::REC_CREA: mCreatures.load(ref, store); break;
|
|
||||||
case ESM::REC_DOOR: mDoors.load(ref, store); break;
|
|
||||||
case ESM::REC_INGR: mIngreds.load(ref, store); break;
|
|
||||||
case ESM::REC_LEVC: mCreatureLists.load(ref, store); break;
|
|
||||||
case ESM::REC_LEVI: mItemLists.load(ref, store); break;
|
|
||||||
case ESM::REC_LIGH: mLights.load(ref, store); break;
|
|
||||||
case ESM::REC_LOCK: mLockpicks.load(ref, store); break;
|
|
||||||
case ESM::REC_MISC: mMiscItems.load(ref, store); break;
|
|
||||||
case ESM::REC_NPC_: mNpcs.load(ref, store); break;
|
|
||||||
case ESM::REC_PROB: mProbes.load(ref, store); break;
|
|
||||||
case ESM::REC_REPA: mRepairs.load(ref, store); break;
|
|
||||||
case ESM::REC_STAT: mStatics.load(ref, store); break;
|
|
||||||
case ESM::REC_WEAP: mWeapons.load(ref, store); break;
|
|
||||||
|
|
||||||
case 0: std::cout << "Cell reference " + ref.mRefID + " not found!\n"; break;
|
|
||||||
default:
|
|
||||||
std::cout << "WARNING: Ignoring reference '" << ref.mRefID << "' of unhandled type\n";
|
|
||||||
}
|
|
||||||
|
|
||||||
|
loadRef (ref, false, store);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -274,4 +192,39 @@ namespace MWWorld
|
||||||
|
|
||||||
return Ptr();
|
return Ptr();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void CellStore::loadRef (ESM::CellRef& ref, bool deleted, const ESMStore& store)
|
||||||
|
{
|
||||||
|
Misc::StringUtils::toLower (ref.mRefID);
|
||||||
|
|
||||||
|
switch (store.find (ref.mRefID))
|
||||||
|
{
|
||||||
|
case ESM::REC_ACTI: mActivators.load(ref, deleted, store); break;
|
||||||
|
case ESM::REC_ALCH: mPotions.load(ref, deleted, store); break;
|
||||||
|
case ESM::REC_APPA: mAppas.load(ref, deleted, store); break;
|
||||||
|
case ESM::REC_ARMO: mArmors.load(ref, deleted, store); break;
|
||||||
|
case ESM::REC_BOOK: mBooks.load(ref, deleted, store); break;
|
||||||
|
case ESM::REC_CLOT: mClothes.load(ref, deleted, store); break;
|
||||||
|
case ESM::REC_CONT: mContainers.load(ref, deleted, store); break;
|
||||||
|
case ESM::REC_CREA: mCreatures.load(ref, deleted, store); break;
|
||||||
|
case ESM::REC_DOOR: mDoors.load(ref, deleted, store); break;
|
||||||
|
case ESM::REC_INGR: mIngreds.load(ref, deleted, store); break;
|
||||||
|
case ESM::REC_LEVC: mCreatureLists.load(ref, deleted, store); break;
|
||||||
|
case ESM::REC_LEVI: mItemLists.load(ref, deleted, store); break;
|
||||||
|
case ESM::REC_LIGH: mLights.load(ref, deleted, store); break;
|
||||||
|
case ESM::REC_LOCK: mLockpicks.load(ref, deleted, store); break;
|
||||||
|
case ESM::REC_MISC: mMiscItems.load(ref, deleted, store); break;
|
||||||
|
case ESM::REC_NPC_: mNpcs.load(ref, deleted, store); break;
|
||||||
|
case ESM::REC_PROB: mProbes.load(ref, deleted, store); break;
|
||||||
|
case ESM::REC_REPA: mRepairs.load(ref, deleted, store); break;
|
||||||
|
case ESM::REC_STAT: mStatics.load(ref, deleted, store); break;
|
||||||
|
case ESM::REC_WEAP: mWeapons.load(ref, deleted, store); break;
|
||||||
|
|
||||||
|
case 0: std::cerr << "Cell reference " + ref.mRefID + " not found!\n"; break;
|
||||||
|
|
||||||
|
default:
|
||||||
|
std::cerr
|
||||||
|
<< "WARNING: Ignoring reference '" << ref.mRefID << "' of unhandled type\n";
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -25,7 +25,7 @@ namespace MWWorld
|
||||||
// and the build will fail with an ugly three-way cyclic header dependence
|
// and the build will fail with an ugly three-way cyclic header dependence
|
||||||
// so we need to pass the instantiation of the method to the lnker, when
|
// so we need to pass the instantiation of the method to the lnker, when
|
||||||
// all methods are known.
|
// all methods are known.
|
||||||
void load(ESM::CellRef &ref, const MWWorld::ESMStore &esmStore);
|
void load(ESM::CellRef &ref, bool deleted, const MWWorld::ESMStore &esmStore);
|
||||||
|
|
||||||
LiveRef *find (const std::string& name)
|
LiveRef *find (const std::string& name)
|
||||||
{
|
{
|
||||||
|
@ -154,6 +154,11 @@ namespace MWWorld
|
||||||
|
|
||||||
void loadRefs(const MWWorld::ESMStore &store, std::vector<ESM::ESMReader> &esm);
|
void loadRefs(const MWWorld::ESMStore &store, std::vector<ESM::ESMReader> &esm);
|
||||||
|
|
||||||
|
void loadRef (ESM::CellRef& ref, bool deleted, const ESMStore& store);
|
||||||
|
///< Make case-adjustments to \a ref and insert it into the respective container.
|
||||||
|
///
|
||||||
|
/// Invalid \a ref objects are silently dropped.
|
||||||
|
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -108,7 +108,7 @@ void ESMStore::load(ESM::ESMReader &esm, Loading::Listener* listener)
|
||||||
}
|
}
|
||||||
// Insert the reference into the global lookup
|
// Insert the reference into the global lookup
|
||||||
if (!id.empty() && isCacheableRecord(n.val)) {
|
if (!id.empty() && isCacheableRecord(n.val)) {
|
||||||
mIds[id] = n.val;
|
mIds[Misc::StringUtils::lowerCase (id)] = n.val;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
listener->setProgress(esm.getFileOffset() / (float)esm.getFileSize() * 1000);
|
listener->setProgress(esm.getFileOffset() / (float)esm.getFileSize() * 1000);
|
||||||
|
|
|
@ -30,11 +30,10 @@ void Store<ESM::Cell>::load(ESM::ESMReader &esm, const std::string &id)
|
||||||
|
|
||||||
// Get regular moved reference data. Adapted from CellStore::loadRefs. Maybe we can optimize the following
|
// Get regular moved reference data. Adapted from CellStore::loadRefs. Maybe we can optimize the following
|
||||||
// implementation when the oher implementation works as well.
|
// implementation when the oher implementation works as well.
|
||||||
cell->getNextRef(esm, ref);
|
bool deleted = false;
|
||||||
std::string lowerCase;
|
cell->getNextRef(esm, ref, deleted);
|
||||||
|
|
||||||
std::transform (ref.mRefID.begin(), ref.mRefID.end(), std::back_inserter (lowerCase),
|
Misc::StringUtils::toLower (ref.mRefID);
|
||||||
(int(*)(int)) std::tolower);
|
|
||||||
|
|
||||||
// Add data required to make reference appear in the correct cell.
|
// Add data required to make reference appear in the correct cell.
|
||||||
// We should not need to test for duplicates, as this part of the code is pre-cell merge.
|
// We should not need to test for duplicates, as this part of the code is pre-cell merge.
|
||||||
|
|
|
@ -71,9 +71,6 @@ namespace ESM
|
||||||
// -1 is not blocked, otherwise it is blocked.
|
// -1 is not blocked, otherwise it is blocked.
|
||||||
signed char mReferenceBlocked;
|
signed char mReferenceBlocked;
|
||||||
|
|
||||||
// Track deleted references. 0 - not deleted, 1 - deleted, but respawns, 2 - deleted and does not respawn.
|
|
||||||
int mDeleted;
|
|
||||||
|
|
||||||
// Occurs in Tribunal.esm, eg. in the cell "Mournhold, Plaza
|
// Occurs in Tribunal.esm, eg. in the cell "Mournhold, Plaza
|
||||||
// Brindisi Dorom", where it has the value 100. Also only for
|
// Brindisi Dorom", where it has the value 100. Also only for
|
||||||
// activators.
|
// activators.
|
||||||
|
|
|
@ -141,7 +141,7 @@ std::string Cell::getDescription() const
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
bool Cell::getNextRef(ESMReader &esm, CellRef &ref)
|
bool Cell::getNextRef(ESMReader &esm, CellRef &ref, bool& deleted)
|
||||||
{
|
{
|
||||||
// TODO: Try and document reference numbering, I don't think this has been done anywhere else.
|
// TODO: Try and document reference numbering, I don't think this has been done anywhere else.
|
||||||
if (!esm.hasMoreSubs())
|
if (!esm.hasMoreSubs())
|
||||||
|
@ -259,12 +259,13 @@ bool Cell::getNextRef(ESMReader &esm, CellRef &ref)
|
||||||
//esm.getHNOT(NAM0, "NAM0");
|
//esm.getHNOT(NAM0, "NAM0");
|
||||||
}
|
}
|
||||||
|
|
||||||
if (esm.isNextSub("DELE")) {
|
if (esm.isNextSub("DELE"))
|
||||||
|
{
|
||||||
esm.skipHSub();
|
esm.skipHSub();
|
||||||
ref.mDeleted = 2; // Deleted, will not respawn.
|
deleted = true;
|
||||||
// TODO: find out when references do respawn.
|
}
|
||||||
} else
|
else
|
||||||
ref.mDeleted = 0;
|
deleted = false;
|
||||||
|
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
|
@ -141,7 +141,7 @@ struct Cell
|
||||||
All fields of the CellRef struct are overwritten. You can safely
|
All fields of the CellRef struct are overwritten. You can safely
|
||||||
reuse one memory location without blanking it between calls.
|
reuse one memory location without blanking it between calls.
|
||||||
*/
|
*/
|
||||||
static bool getNextRef(ESMReader &esm, CellRef &ref);
|
static bool getNextRef(ESMReader &esm, CellRef &ref, bool& deleted);
|
||||||
|
|
||||||
/* This fetches an MVRF record, which is used to track moved references.
|
/* This fetches an MVRF record, which is used to track moved references.
|
||||||
* Since they are comparably rare, we use a separate method for this.
|
* Since they are comparably rare, we use a separate method for this.
|
||||||
|
|
Loading…
Reference in a new issue