diff --git a/apps/openmw/mwbase/world.hpp b/apps/openmw/mwbase/world.hpp index cf41f97df..6ef1a6c2b 100644 --- a/apps/openmw/mwbase/world.hpp +++ b/apps/openmw/mwbase/world.hpp @@ -363,6 +363,14 @@ namespace MWBase virtual void playVideo(const std::string& name, bool allowSkipping) = 0; virtual void stopVideo() = 0; virtual void frameStarted (float dt) = 0; + + /// Find default position inside exterior cell specified by name + /// \return false if exterior with given name not exists, true otherwise + virtual bool findExteriorPosition(const std::string &name, ESM::Position &pos) = 0; + + /// Find default position inside interior cell specified by name + /// \return false if interior with given name not exists, true otherwise + virtual bool findInteriorPosition(const std::string &name, ESM::Position &pos) = 0; }; } diff --git a/apps/openmw/mwscript/cellextensions.cpp b/apps/openmw/mwscript/cellextensions.cpp index dfd896778..d2e11c19f 100644 --- a/apps/openmw/mwscript/cellextensions.cpp +++ b/apps/openmw/mwscript/cellextensions.cpp @@ -34,80 +34,6 @@ namespace MWScript { public: - static bool findInteriorPosition(const std::string &name, ESM::Position &pos) - { - typedef MWWorld::CellRefList::List DoorList; - - pos.rot[0] = pos.rot[1] = pos.rot[2] = 0; - pos.pos[0] = pos.pos[1] = pos.pos[2] = 0; - - MWBase::World *world = MWBase::Environment::get().getWorld(); - MWWorld::CellStore *cellStore = world->getInterior(name); - - if (0 == cellStore) { - return false; - } - const DoorList &doors = cellStore->mDoors.mList; - for (DoorList::const_iterator it = doors.begin(); it != doors.end(); ++it) { - if (!it->mRef.mTeleport) { - continue; - } - - MWWorld::CellStore *source = 0; - - // door to exterior - if (it->mRef.mDestCell.empty()) { - int x, y; - const float *pos = it->mRef.mDoorDest.pos; - world->positionToIndex(pos[0], pos[1], x, y); - source = world->getExterior(x, y); - } - // door to interior - else { - source = world->getInterior(it->mRef.mDestCell); - } - if (0 != source) { - // Find door leading to our current teleport door - // and use it destination to position inside cell. - const DoorList &doors = source->mDoors.mList; - for (DoorList::const_iterator jt = doors.begin(); jt != doors.end(); ++jt) { - if (it->mRef.mTeleport && - Misc::StringUtils::ciEqual(name, jt->mRef.mDestCell)) - { - /// \note Using _any_ door pointed to the interior, - /// not the one pointed to current door. - pos = jt->mRef.mDoorDest; - return true; - } - } - } - } - return false; - } - - static bool findExteriorPosition(const std::string &name, ESM::Position &pos) - { - pos.rot[0] = pos.rot[1] = pos.rot[2] = 0; - MWBase::World *world = MWBase::Environment::get().getWorld(); - - if (const ESM::Cell *ext = world->getExterior(name)) { - int x = ext->getGridX(); - int y = ext->getGridY(); - world->indexToPosition(x, y, pos.pos[0], pos.pos[1], true); - - ESM::Land* land = - world->getStore().get().search(x, y); - assert(land && "Correctly found exteriors must have land data"); - if (!land->isDataLoaded(ESM::Land::DATA_VHGT)) { - land->loadData(ESM::Land::DATA_VHGT); - } - pos.pos[2] = land->mLandData->mHeights[ESM::Land::LAND_NUM_VERTS / 2 + 1]; - - return true; - } - return false; - } - virtual void execute (Interpreter::Runtime& runtime) { std::string cell = runtime.getStringLiteral (runtime[0].mInteger); @@ -116,13 +42,13 @@ namespace MWScript ESM::Position pos; MWBase::World *world = MWBase::Environment::get().getWorld(); - if (findExteriorPosition(cell, pos)) { + if (world->findExteriorPosition(cell, pos)) { world->changeToExteriorCell(pos); } else { // Change to interior even if findInteriorPosition() // yields false. In this case position will be zero-point. - findInteriorPosition(cell, pos); + world->findInteriorPosition(cell, pos); world->changeToInteriorCell(cell, pos); } } diff --git a/apps/openmw/mwworld/worldimp.cpp b/apps/openmw/mwworld/worldimp.cpp index 0a1e0ccdc..256cbb217 100644 --- a/apps/openmw/mwworld/worldimp.cpp +++ b/apps/openmw/mwworld/worldimp.cpp @@ -1765,4 +1765,80 @@ namespace MWWorld physicActor->disableCollisionBody(); } } + + bool World::findInteriorPosition(const std::string &name, ESM::Position &pos) + { + typedef MWWorld::CellRefList::List DoorList; + + pos.rot[0] = pos.rot[1] = pos.rot[2] = 0; + pos.pos[0] = pos.pos[1] = pos.pos[2] = 0; + + MWWorld::CellStore *cellStore = getInterior(name); + + if (0 == cellStore) { + return false; + } + const DoorList &doors = cellStore->mDoors.mList; + for (DoorList::const_iterator it = doors.begin(); it != doors.end(); ++it) { + if (!it->mRef.mTeleport) { + continue; + } + + MWWorld::CellStore *source = 0; + + // door to exterior + if (it->mRef.mDestCell.empty()) { + int x, y; + const float *pos = it->mRef.mDoorDest.pos; + positionToIndex(pos[0], pos[1], x, y); + source = getExterior(x, y); + } + // door to interior + else { + source = getInterior(it->mRef.mDestCell); + } + if (0 != source) { + // Find door leading to our current teleport door + // and use it destination to position inside cell. + const DoorList &doors = source->mDoors.mList; + for (DoorList::const_iterator jt = doors.begin(); jt != doors.end(); ++jt) { + if (it->mRef.mTeleport && + Misc::StringUtils::ciEqual(name, jt->mRef.mDestCell)) + { + /// \note Using _any_ door pointed to the interior, + /// not the one pointed to current door. + pos = jt->mRef.mDoorDest; + return true; + } + } + } + } + return false; + } + + bool World::findExteriorPosition(const std::string &name, ESM::Position &pos) + { + pos.rot[0] = pos.rot[1] = pos.rot[2] = 0; + + if (const ESM::Cell *ext = getExterior(name)) { + int x = ext->getGridX(); + int y = ext->getGridY(); + indexToPosition(x, y, pos.pos[0], pos.pos[1], true); + + ESM::Land* land = getStore().get().search(x, y); + if (land) { + if (!land->isDataLoaded(ESM::Land::DATA_VHGT)) { + land->loadData(ESM::Land::DATA_VHGT); + } + pos.pos[2] = land->mLandData->mHeights[ESM::Land::LAND_NUM_VERTS / 2 + 1]; + } + else { + std::cerr << "Land data for cell at (" << x << ", " << y << ") not found\n"; + pos.pos[2] = 0; + } + + return true; + } + return false; + } } diff --git a/apps/openmw/mwworld/worldimp.hpp b/apps/openmw/mwworld/worldimp.hpp index 5cf3a24bf..9e9d76bd5 100644 --- a/apps/openmw/mwworld/worldimp.hpp +++ b/apps/openmw/mwworld/worldimp.hpp @@ -412,6 +412,14 @@ namespace MWWorld virtual void playVideo(const std::string& name, bool allowSkipping); virtual void stopVideo(); virtual void frameStarted (float dt); + + /// Find center of exterior cell above land surface + /// \return false if exterior with given name not exists, true otherwise + virtual bool findExteriorPosition(const std::string &name, ESM::Position &pos); + + /// Find position in interior cell near door entrance + /// \return false if interior with given name not exists, true otherwise + virtual bool findInteriorPosition(const std::string &name, ESM::Position &pos); }; }