mirror of
https://github.com/TES3MP/openmw-tes3mp.git
synced 2025-03-30 02:06:43 +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
|
||||
ESM::CellRef ref;
|
||||
if(!quiet) std::cout << " References:\n";
|
||||
while(cell.getNextRef(esm, ref))
|
||||
|
||||
bool deleted = false;
|
||||
while(cell.getNextRef(esm, ref, deleted))
|
||||
{
|
||||
if (save) {
|
||||
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 << " Gold value: '" << ref.mGoldValue << "'\n";
|
||||
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;
|
||||
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;
|
||||
|
||||
while (cell2.getNextRef (reader, ref))
|
||||
bool deleted = false;
|
||||
while (cell2.getNextRef (reader, ref, deleted))
|
||||
{
|
||||
/// \todo handle deleted and moved references
|
||||
ref.load (reader, cell2, getNewId());
|
||||
|
|
|
@ -35,32 +35,30 @@ namespace MWWorld
|
|||
{
|
||||
|
||||
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 X *ptr = store.search(ref.mRefID);
|
||||
|
||||
/// \note no longer redundant - changed to Store<X>::search(), don't throw
|
||||
/// an exception on miss, try to continue (that's how MW does it, anyway)
|
||||
if (ptr == NULL) {
|
||||
std::cout << "Warning: could not resolve cell reference " << ref.mRefID << ", trying to continue anyway" << std::endl;
|
||||
} else {
|
||||
if (iter != mList.end())
|
||||
*iter = LiveRef(ref, ptr);
|
||||
else
|
||||
mList.push_back(LiveRef(ref, ptr));
|
||||
if (const X *ptr = store.search (ref.mRefID))
|
||||
{
|
||||
typename std::list<LiveRef>::iterator iter =
|
||||
std::find(mList.begin(), mList.end(), ref.mRefnum);
|
||||
|
||||
LiveRef liveCellRef (ref, ptr);
|
||||
|
||||
if (deleted)
|
||||
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;
|
||||
|
||||
// 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 (ref.mDeleted) {
|
||||
// Right now, don't do anything. Where is "listRefs" actually used, anyway?
|
||||
// Skipping for now...
|
||||
if (deleted)
|
||||
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)
|
||||
{
|
||||
assert (mCell);
|
||||
assert (mCell);
|
||||
|
||||
if (mCell->mContextList.empty())
|
||||
return; // this is a dynamically generated cell -> skipping.
|
||||
|
@ -150,102 +145,25 @@ namespace MWWorld
|
|||
ESM::CellRef ref;
|
||||
|
||||
// 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.
|
||||
std::string lowerCase = Misc::StringUtils::lowerCase(ref.mRefID);
|
||||
ESM::MovedCellRefTracker::const_iterator iter = std::find(mCell->mMovedRefs.begin(), mCell->mMovedRefs.end(), ref.mRefnum);
|
||||
if (iter != mCell->mMovedRefs.end()) {
|
||||
continue;
|
||||
}
|
||||
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, deleted, store);
|
||||
}
|
||||
}
|
||||
|
||||
// Load moved references, from separately tracked list.
|
||||
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->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();
|
||||
}
|
||||
|
||||
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
|
||||
// so we need to pass the instantiation of the method to the lnker, when
|
||||
// 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)
|
||||
{
|
||||
|
@ -154,6 +154,11 @@ namespace MWWorld
|
|||
|
||||
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
|
||||
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);
|
||||
|
|
|
@ -10,7 +10,7 @@ void Store<ESM::Cell>::load(ESM::ESMReader &esm, const std::string &id)
|
|||
// and we merge all this data into one Cell object. However, we can't simply search for the cell id,
|
||||
// as many exterior cells do not have a name. Instead, we need to search by (x,y) coordinates - and they
|
||||
// are not available until both cells have been loaded! So first, proceed as usual.
|
||||
|
||||
|
||||
// All cells have a name record, even nameless exterior cells.
|
||||
std::string idLower = Misc::StringUtils::lowerCase(id);
|
||||
ESM::Cell *cell = new ESM::Cell;
|
||||
|
@ -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
|
||||
// implementation when the oher implementation works as well.
|
||||
cell->getNextRef(esm, ref);
|
||||
std::string lowerCase;
|
||||
bool deleted = false;
|
||||
cell->getNextRef(esm, ref, deleted);
|
||||
|
||||
std::transform (ref.mRefID.begin(), ref.mRefID.end(), std::back_inserter (lowerCase),
|
||||
(int(*)(int)) std::tolower);
|
||||
Misc::StringUtils::toLower (ref.mRefID);
|
||||
|
||||
// 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.
|
||||
|
|
|
@ -71,9 +71,6 @@ namespace ESM
|
|||
// -1 is not blocked, otherwise it is blocked.
|
||||
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
|
||||
// Brindisi Dorom", where it has the value 100. Also only for
|
||||
// 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.
|
||||
if (!esm.hasMoreSubs())
|
||||
|
@ -259,12 +259,13 @@ bool Cell::getNextRef(ESMReader &esm, CellRef &ref)
|
|||
//esm.getHNOT(NAM0, "NAM0");
|
||||
}
|
||||
|
||||
if (esm.isNextSub("DELE")) {
|
||||
if (esm.isNextSub("DELE"))
|
||||
{
|
||||
esm.skipHSub();
|
||||
ref.mDeleted = 2; // Deleted, will not respawn.
|
||||
// TODO: find out when references do respawn.
|
||||
} else
|
||||
ref.mDeleted = 0;
|
||||
deleted = true;
|
||||
}
|
||||
else
|
||||
deleted = false;
|
||||
|
||||
return true;
|
||||
}
|
||||
|
|
|
@ -141,7 +141,7 @@ struct Cell
|
|||
All fields of the CellRef struct are overwritten. You can safely
|
||||
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.
|
||||
* Since they are comparably rare, we use a separate method for this.
|
||||
|
|
Loading…
Reference in a new issue