Change pathgrid workaround to check for interior cell name

This commit is contained in:
scrawl 2014-12-11 15:19:48 +01:00
parent 0fe7500f74
commit 3270f0e932
6 changed files with 76 additions and 34 deletions

View file

@ -382,7 +382,7 @@ namespace MWMechanics
{
// infrequently used, therefore no benefit in caching it as a member
const ESM::Pathgrid *
pathgrid = world->getStore().get<ESM::Pathgrid>().search(*cell, world->getCellName(currentCell));
pathgrid = world->getStore().get<ESM::Pathgrid>().search(*cell);
// cache the current cell location
cachedCellX = cell->mData.mX;

View file

@ -188,8 +188,7 @@ namespace MWMechanics
if(mCell != cell || !mPathgrid)
{
mCell = cell;
mPathgrid = MWBase::Environment::get().getWorld()->getStore().get<ESM::Pathgrid>().search(*mCell->getCell(),
MWBase::Environment::get().getWorld()->getCellName(mCell));
mPathgrid = MWBase::Environment::get().getWorld()->getStore().get<ESM::Pathgrid>().search(*mCell->getCell());
}
// Refer to AiWander reseach topic on openmw forums for some background.

View file

@ -105,9 +105,7 @@ namespace MWMechanics
mCell = cell->getCell();
mIsExterior = cell->getCell()->isExterior();
mPathgrid = MWBase::Environment::get().getWorld()->getStore().get<ESM::Pathgrid>().search(*cell->getCell(),
MWBase::Environment::get().getWorld()->getCellName(cell));
mPathgrid = MWBase::Environment::get().getWorld()->getStore().get<ESM::Pathgrid>().search(*cell->getCell());
if(!mPathgrid)
return false;

View file

@ -233,7 +233,7 @@ void Debugging::enableCellPathgrid(MWWorld::CellStore *store)
{
MWBase::World* world = MWBase::Environment::get().getWorld();
const ESM::Pathgrid *pathgrid =
world->getStore().get<ESM::Pathgrid>().search(*store->getCell(), world->getCellName(store));
world->getStore().get<ESM::Pathgrid>().search(*store->getCell());
if (!pathgrid) return;
Vector3 cellPathGridPos(0, 0, 0);

View file

@ -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 ()

View file

@ -843,60 +843,103 @@ namespace MWWorld
class Store<ESM::Pathgrid> : 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<std::string, std::pair<int, int> > PathgridKey;
typedef std::map<PathgridKey, ESM::Pathgrid> Static;
typedef std::map<std::string, ESM::Pathgrid> Interior;
typedef std::map<std::pair<int, int>, ESM::Pathgrid> Exterior;
Static mStatic;
Interior mInt;
Exterior mExt;
Store<ESM::Cell>* mCells;
public:
void setCells(Store<ESM::Cell>& 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<Static::iterator, bool> ret = mStatic.insert(std::make_pair(key, pathgrid));
if (!ret.second)
ret.first->second = pathgrid;
if (interior)
{
std::pair<Interior::iterator, bool> ret = mInt.insert(std::make_pair(pathgrid.mCell, pathgrid));
if (!ret.second)
ret.first->second = pathgrid;
}
else
{
std::pair<Exterior::iterator, bool> 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 <class T>