diff --git a/apps/openmw/mwmechanics/aiwander.cpp b/apps/openmw/mwmechanics/aiwander.cpp index 3224127df..c8a0c85d5 100644 --- a/apps/openmw/mwmechanics/aiwander.cpp +++ b/apps/openmw/mwmechanics/aiwander.cpp @@ -382,7 +382,7 @@ namespace MWMechanics { // infrequently used, therefore no benefit in caching it as a member const ESM::Pathgrid * - pathgrid = world->getStore().get().search(*cell, world->getCellName(currentCell)); + pathgrid = world->getStore().get().search(*cell); // cache the current cell location cachedCellX = cell->mData.mX; diff --git a/apps/openmw/mwmechanics/pathfinding.cpp b/apps/openmw/mwmechanics/pathfinding.cpp index f0e5b1d9d..f1279c415 100644 --- a/apps/openmw/mwmechanics/pathfinding.cpp +++ b/apps/openmw/mwmechanics/pathfinding.cpp @@ -188,8 +188,7 @@ namespace MWMechanics if(mCell != cell || !mPathgrid) { mCell = cell; - mPathgrid = MWBase::Environment::get().getWorld()->getStore().get().search(*mCell->getCell(), - MWBase::Environment::get().getWorld()->getCellName(mCell)); + mPathgrid = MWBase::Environment::get().getWorld()->getStore().get().search(*mCell->getCell()); } // Refer to AiWander reseach topic on openmw forums for some background. diff --git a/apps/openmw/mwmechanics/pathgrid.cpp b/apps/openmw/mwmechanics/pathgrid.cpp index d380cba4e..848d2c7a0 100644 --- a/apps/openmw/mwmechanics/pathgrid.cpp +++ b/apps/openmw/mwmechanics/pathgrid.cpp @@ -105,9 +105,7 @@ namespace MWMechanics mCell = cell->getCell(); mIsExterior = cell->getCell()->isExterior(); - mPathgrid = MWBase::Environment::get().getWorld()->getStore().get().search(*cell->getCell(), - MWBase::Environment::get().getWorld()->getCellName(cell)); - + mPathgrid = MWBase::Environment::get().getWorld()->getStore().get().search(*cell->getCell()); if(!mPathgrid) return false; diff --git a/apps/openmw/mwrender/debugging.cpp b/apps/openmw/mwrender/debugging.cpp index 553a6379f..972c1b6dd 100644 --- a/apps/openmw/mwrender/debugging.cpp +++ b/apps/openmw/mwrender/debugging.cpp @@ -233,7 +233,7 @@ void Debugging::enableCellPathgrid(MWWorld::CellStore *store) { MWBase::World* world = MWBase::Environment::get().getWorld(); const ESM::Pathgrid *pathgrid = - world->getStore().get().search(*store->getCell(), world->getCellName(store)); + world->getStore().get().search(*store->getCell()); if (!pathgrid) return; Vector3 cellPathGridPos(0, 0, 0); diff --git a/apps/openmw/mwworld/esmstore.hpp b/apps/openmw/mwworld/esmstore.hpp index 90786acd4..83e911174 100644 --- a/apps/openmw/mwworld/esmstore.hpp +++ b/apps/openmw/mwworld/esmstore.hpp @@ -141,6 +141,8 @@ namespace MWWorld mStores[ESM::REC_SSCR] = &mStartScripts; mStores[ESM::REC_STAT] = &mStatics; mStores[ESM::REC_WEAP] = &mWeapons; + + mPathgrids.setCells(mCells); } void clearDynamic () diff --git a/apps/openmw/mwworld/store.hpp b/apps/openmw/mwworld/store.hpp index 1aaf902f8..c4070f032 100644 --- a/apps/openmw/mwworld/store.hpp +++ b/apps/openmw/mwworld/store.hpp @@ -843,60 +843,103 @@ namespace MWWorld class Store : public StoreBase { private: - // Unfortunately the Pathgrid record model does not specify whether the pathgrid belongs to an interior or exterior cell. - // For interior cells, mCell is the cell name, but for exterior cells it is either the cell name or if that doesn't exist, the cell's region name. - // mX and mY will be (0,0) for interior cells, but there is also an exterior cell with the coordinates of (0,0), so that doesn't help. - // This is why we keep both interior and exterior pathgrids in the same container here. - typedef std::pair > PathgridKey; - typedef std::map Static; + typedef std::map Interior; + typedef std::map, ESM::Pathgrid> Exterior; - Static mStatic; + Interior mInt; + Exterior mExt; + + Store* mCells; public: + void setCells(Store& cells) + { + mCells = &cells; + } + void load(ESM::ESMReader &esm, const std::string &id) { ESM::Pathgrid pathgrid; pathgrid.load(esm); - PathgridKey key = std::make_pair(pathgrid.mCell, std::make_pair(pathgrid.mData.mX, pathgrid.mData.mY)); + // Unfortunately the Pathgrid record model does not specify whether the pathgrid belongs to an interior or exterior cell. + // For interior cells, mCell is the cell name, but for exterior cells it is either the cell name or if that doesn't exist, the cell's region name. + // mX and mY will be (0,0) for interior cells, but there is also an exterior cell with the coordinates of (0,0), so that doesn't help. + // Check whether mCell is an interior cell. This isn't perfect, will break if a Region with the same name as an interior cell is created. + // A proper fix should be made for future versions of the file format. + bool interior = mCells->search(pathgrid.mCell) != NULL; // Try to overwrite existing record - std::pair ret = mStatic.insert(std::make_pair(key, pathgrid)); - if (!ret.second) - ret.first->second = pathgrid; + if (interior) + { + std::pair ret = mInt.insert(std::make_pair(pathgrid.mCell, pathgrid)); + if (!ret.second) + ret.first->second = pathgrid; + } + else + { + std::pair ret = mExt.insert(std::make_pair(std::make_pair(pathgrid.mData.mX, pathgrid.mData.mY), pathgrid)); + if (!ret.second) + ret.first->second = pathgrid; + } } size_t getSize() const { - return mStatic.size(); + return mInt.size() + mExt.size(); } void setUp() { } - const ESM::Pathgrid *search(const ESM::Cell &cell, const std::string& cellName) const { - int x=0,y=0; - if (!(cell.mData.mFlags & ESM::Cell::Interior)) - { - x = cell.mData.mX; - y = cell.mData.mY; - } - PathgridKey key = std::make_pair(cellName, std::make_pair(x,y)); - - Static::const_iterator it = mStatic.find(key); - if (it != mStatic.end()) + const ESM::Pathgrid *search(int x, int y) const { + Exterior::const_iterator it = mExt.find(std::make_pair(x,y)); + if (it != mExt.end()) return &(it->second); return NULL; } - const ESM::Pathgrid *find(const ESM::Cell &cell, const std::string& cellName) const { - const ESM::Pathgrid* pathgrid = search(cell, cellName); - if (pathgrid == 0) { + const ESM::Pathgrid *search(const std::string& name) const { + Interior::const_iterator it = mInt.find(name); + if (it != mInt.end()) + return &(it->second); + return NULL; + } + + const ESM::Pathgrid *find(int x, int y) const { + const ESM::Pathgrid* pathgrid = search(x,y); + if (!pathgrid) + { std::ostringstream msg; - msg << "Pathgrid in cell '" << cellName << "' not found"; + msg << "Pathgrid in cell '" << x << " " << y << "' not found"; throw std::runtime_error(msg.str()); } return pathgrid; } + + const ESM::Pathgrid* find(const std::string& name) const { + const ESM::Pathgrid* pathgrid = search(name); + if (!pathgrid) + { + std::ostringstream msg; + msg << "Pathgrid in cell '" << name << "' not found"; + throw std::runtime_error(msg.str()); + } + return pathgrid; + } + + const ESM::Pathgrid *search(const ESM::Cell &cell) const { + if (!(cell.mData.mFlags & ESM::Cell::Interior)) + return search(cell.mData.mX, cell.mData.mY); + else + return search(cell.mName); + } + + const ESM::Pathgrid *find(const ESM::Cell &cell) const { + if (!(cell.mData.mFlags & ESM::Cell::Interior)) + return find(cell.mData.mX, cell.mData.mY); + else + return find(cell.mName); + } }; template