|
|
|
@ -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);
|
|
|
|
|
const MWWorld::Store<X> &store = esmStore.get<X>();
|
|
|
|
|
|
|
|
|
|
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);
|
|
|
|
|
|
|
|
|
|
// 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;
|
|
|
|
|
*iter = liveCellRef;
|
|
|
|
|
else
|
|
|
|
|
mList.push_back (liveCellRef);
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
// 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));
|
|
|
|
|
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";
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|