diff --git a/apps/openmw/mwworld/cellstore.hpp b/apps/openmw/mwworld/cellstore.hpp index bf7581f6ed..cf09496e87 100644 --- a/apps/openmw/mwworld/cellstore.hpp +++ b/apps/openmw/mwworld/cellstore.hpp @@ -61,13 +61,14 @@ namespace MWWorld { // for throwing exception on unhandled record type const MWWorld::Store &store = esmStore.get(); - const X *ptr = store.find(ref.mRefID); + const X *ptr = store.search(ref.mRefID); - /// \note redundant because Store::find() throws exception on miss + /// \note no longer redundant - changed to Store::search(), don't throw + /// an exception on miss, try to continue (that's how MW does it, anyway) if (ptr == NULL) { - throw std::runtime_error("Error resolving cell reference " + ref.mRefID); - } - mList[ref.mRefnum] = LiveRef(ref, ptr); + std::cout << "Warning: could not resolve cell reference " << ref.mRefID << ", trying to continue anyway" << std::endl; + } else + mList[ref.mRefnum] = LiveRef(ref, ptr); } LiveRef *find (const std::string& name) diff --git a/apps/openmw/mwworld/esmstore.cpp b/apps/openmw/mwworld/esmstore.cpp index b1b9b15347..54050b38c7 100644 --- a/apps/openmw/mwworld/esmstore.cpp +++ b/apps/openmw/mwworld/esmstore.cpp @@ -87,20 +87,18 @@ void ESMStore::load(ESM::ESMReader &esm) // ... unless it got deleted! This means that the following record // has been deleted, and trying to load it using standard assumptions // on the structure will (probably) fail. - /* if (esm.isNextSub("DELE")) { esm.skipRecord(); - all.erase(id); - it->second->remove(id); + it->second->eraseStatic(id); continue; } - */ it->second->load(esm, id); if (n.val==ESM::REC_DIAL) { // dirty hack, but it is better than non-const search() // or friends - dialogue = &mDialogs.mStatic.back(); + //dialogue = &mDialogs.mStatic.back(); + dialogue = const_cast(mDialogs.find(id)); assert (dialogue->mId == id); } else { dialogue = 0; @@ -140,12 +138,11 @@ void ESMStore::setUp() ESM::NPC item; item.mId = "player"; - std::vector::iterator pIt = - std::lower_bound(mNpcs.mStatic.begin(), mNpcs.mStatic.end(), item, RecordCmp()); - assert(pIt != mNpcs.mStatic.end() && pIt->mId == "player"); + const ESM::NPC *pIt = mNpcs.find("player"); + assert(pIt != NULL); mNpcs.insert(*pIt); - mNpcs.mStatic.erase(pIt); + mNpcs.eraseStatic(pIt->mId); } } // end namespace diff --git a/apps/openmw/mwworld/store.hpp b/apps/openmw/mwworld/store.hpp index fd3e9c59c8..77c9c73574 100644 --- a/apps/openmw/mwworld/store.hpp +++ b/apps/openmw/mwworld/store.hpp @@ -19,6 +19,8 @@ namespace MWWorld virtual int getSize() const = 0; virtual void load(ESM::ESMReader &esm, const std::string &id) = 0; + + virtual bool eraseStatic(const std::string &id) {return false;} }; template @@ -85,7 +87,7 @@ namespace MWWorld template class Store : public StoreBase { - std::vector mStatic; + std::map mStatic; std::vector mShared; std::map mDynamic; @@ -107,11 +109,10 @@ namespace MWWorld T item; item.mId = StringUtils::lowerCase(id); - typename std::vector::const_iterator it = - std::lower_bound(mStatic.begin(), mStatic.end(), item, RecordCmp()); - - if (it != mStatic.end() && StringUtils::ciEqual(it->mId, id)) { - return &(*it); + typename std::map::const_iterator it = mStatic.find(item.mId); + + if (it != mStatic.end() && StringUtils::ciEqual(it->second.mId, id)) { + return &(it->second); } typename Dynamic::const_iterator dit = mDynamic.find(item.mId); @@ -133,18 +134,19 @@ namespace MWWorld } void load(ESM::ESMReader &esm, const std::string &id) { - mStatic.push_back(T()); - mStatic.back().mId = StringUtils::lowerCase(id); - mStatic.back().load(esm); + std::string idLower = StringUtils::lowerCase(id); + mStatic[idLower] = T(); + mStatic[idLower].mId = idLower; + mStatic[idLower].load(esm); } void setUp() { - std::sort(mStatic.begin(), mStatic.end(), RecordCmp()); + //std::sort(mStatic.begin(), mStatic.end(), RecordCmp()); mShared.reserve(mStatic.size()); - typename std::vector::iterator it = mStatic.begin(); + typename std::map::iterator it = mStatic.begin(); for (; it != mStatic.end(); ++it) { - mShared.push_back(&(*it)); + mShared.push_back(&(it->second)); } } @@ -181,6 +183,19 @@ namespace MWWorld return ptr; } + bool eraseStatic(const std::string &id) { + T item; + item.mId = StringUtils::lowerCase(id); + + typename std::map::const_iterator it = mStatic.find(item.mId); + + if (it != mStatic.end() && StringUtils::ciEqual(it->second.mId, id)) { + mStatic.erase(it); + } + + return true; + } + bool erase(const std::string &id) { std::string key = StringUtils::lowerCase(id); typename Dynamic::iterator it = mDynamic.find(key); @@ -204,16 +219,18 @@ namespace MWWorld template <> inline void Store::load(ESM::ESMReader &esm, const std::string &id) { - mStatic.push_back(ESM::Dialogue()); - mStatic.back().mId = id; - mStatic.back().load(esm); + std::string idLower = StringUtils::lowerCase(id); + mStatic[idLower] = ESM::Dialogue(); + mStatic[idLower].mId = id; // don't smash case here, as this line is printed... I think + mStatic[idLower].load(esm); } template <> inline void Store::load(ESM::ESMReader &esm, const std::string &id) { - mStatic.push_back(ESM::Script()); - mStatic.back().load(esm); - StringUtils::toLower(mStatic.back().mId); + ESM::Script scpt; + scpt.load(esm); + StringUtils::toLower(scpt.mId); + mStatic[scpt.mId] = scpt; } template <> @@ -478,6 +495,7 @@ namespace MWWorld // 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 = StringUtils::lowerCase(id); ESM::Cell *cell = new ESM::Cell; cell->mName = id; @@ -487,7 +505,7 @@ namespace MWWorld if(cell->mData.mFlags & ESM::Cell::Interior) { // Store interior cell by name, try to merge with existing parent data. - ESM::Cell *oldcell = const_cast(search(id)); + ESM::Cell *oldcell = const_cast(search(idLower)); if (oldcell) { // push the new references on the list of references to manage oldcell->mContextList.push_back(cell->mContextList.at(0)); @@ -496,7 +514,7 @@ namespace MWWorld // have new cell replace old cell *oldcell = *cell; } else - mInt[cell->mName] = *cell; + mInt[idLower] = *cell; delete cell; } else