diff --git a/apps/openmw/mwscript/cellextensions.cpp b/apps/openmw/mwscript/cellextensions.cpp index 93e77ee486..4d30254693 100644 --- a/apps/openmw/mwscript/cellextensions.cpp +++ b/apps/openmw/mwscript/cellextensions.cpp @@ -41,9 +41,20 @@ namespace MWScript runtime.pop(); ESM::Position pos; - pos.pos[0] = pos.pos[1] = pos.pos[2] = 0; pos.rot[0] = pos.rot[1] = pos.rot[2] = 0; - context.getWorld().changeCell (cell, pos); + pos.pos[2] = 0; + + if (const ESM::Cell *exterior = context.getWorld().getExterior (cell)) + { + context.getWorld().indexToPosition (exterior->data.gridX, exterior->data.gridY, + pos.pos[0], pos.pos[1], true); + context.getWorld().changeToExteriorCell (pos); + } + else + { + pos.pos[0] = pos.pos[1] = 0; + context.getWorld().changeCell (cell, pos); + } } }; @@ -64,7 +75,7 @@ namespace MWScript ESM::Position pos; - context.getWorld().indexToPosition (x, y, pos.pos[0], pos.pos[1]); + context.getWorld().indexToPosition (x, y, pos.pos[0], pos.pos[1], true); pos.pos[2] = 0; pos.rot[0] = pos.rot[1] = pos.rot[2] = 0; diff --git a/apps/openmw/mwworld/world.cpp b/apps/openmw/mwworld/world.cpp index 496da44ef6..ca29facfdf 100644 --- a/apps/openmw/mwworld/world.cpp +++ b/apps/openmw/mwworld/world.cpp @@ -691,6 +691,30 @@ namespace MWWorld changeCell (x, y, position); } + const ESM::Cell *World::getExterior (const std::string& cellName) const + { + // first try named cells + if (const ESM::Cell *cell = mStore.cells.searchExtByName (cellName)) + return cell; + + // didn't work -> now check for regions + std::string cellName2 = ESMS::RecListT::toLower (cellName); + + for (ESMS::RecListT::MapType::const_iterator iter (mStore.regions.list.begin()); + iter!=mStore.regions.list.end(); ++iter) + { + if (ESMS::RecListT::toLower (iter->second.name)==cellName2) + { + if (const ESM::Cell *cell = mStore.cells.searchExtByRegion (iter->first)) + return cell; + + break; + } + } + + return 0; + } + void World::markCellAsUnchanged() { mCellChanged = false; @@ -756,12 +780,18 @@ namespace MWWorld // TODO cell change for non-player ref } - void World::indexToPosition (int cellX, int cellY, float &x, float &y) const + void World::indexToPosition (int cellX, int cellY, float &x, float &y, bool centre) const { const int cellSize = 8192; x = cellSize * cellX; y = cellSize * cellY; + + if (centre) + { + x += cellSize/2; + y += cellSize/2; + } } void World::positionToIndex (float x, float y, int &cellX, int &cellY) const diff --git a/apps/openmw/mwworld/world.hpp b/apps/openmw/mwworld/world.hpp index 2ff2d3ccc4..832c90bf09 100644 --- a/apps/openmw/mwworld/world.hpp +++ b/apps/openmw/mwworld/world.hpp @@ -145,6 +145,9 @@ namespace MWWorld void changeToExteriorCell (const ESM::Position& position); + const ESM::Cell *getExterior (const std::string& cellName) const; + ///< Return a cell matching the given name or a 0-pointer, if there is no such cell. + void markCellAsUnchanged(); std::string getFacedHandle(); @@ -154,7 +157,7 @@ namespace MWWorld void moveObject (Ptr ptr, float x, float y, float z); - void indexToPosition (int cellX, int cellY, float &x, float &y) const; + void indexToPosition (int cellX, int cellY, float &x, float &y, bool centre = false) const; ///< Convert cell numbers to position. void positionToIndex (float x, float y, int &cellX, int &cellY) const; diff --git a/components/esm_store/reclists.hpp b/components/esm_store/reclists.hpp index 3711a20b12..81b0d60540 100644 --- a/components/esm_store/reclists.hpp +++ b/components/esm_store/reclists.hpp @@ -209,6 +209,38 @@ namespace ESMS return it2->second; } + const Cell *searchExtByName (const std::string& id) const + { + for (ExtCells::const_iterator iter = extCells.begin(); iter!=extCells.end(); ++iter) + { + const ExtCellsCol& column = iter->second; + for (ExtCellsCol::const_iterator iter = column.begin(); iter!=column.end(); ++iter) + { + if (iter->second->name==id) + return iter->second; + } + } + + return 0; + } + + const Cell *searchExtByRegion (const std::string& id) const + { + std::string id2 = toLower (id); + + for (ExtCells::const_iterator iter = extCells.begin(); iter!=extCells.end(); ++iter) + { + const ExtCellsCol& column = iter->second; + for (ExtCellsCol::const_iterator iter = column.begin(); iter!=column.end(); ++iter) + { + if (toLower (iter->second->region)==id) + return iter->second; + } + } + + return 0; + } + void load(ESMReader &esm, const std::string &id) { using namespace std;