From a3094b808ee3ae9030e6081c2c2ed5715846dd0f Mon Sep 17 00:00:00 2001 From: greye Date: Sat, 6 Jul 2013 12:42:29 +0400 Subject: [PATCH 1/5] update coc behaviour for interior cells --- apps/openmw/mwscript/cellextensions.cpp | 82 +++++++++++++++++++++---- 1 file changed, 71 insertions(+), 11 deletions(-) diff --git a/apps/openmw/mwscript/cellextensions.cpp b/apps/openmw/mwscript/cellextensions.cpp index a4a738ca7..e1acfadb2 100644 --- a/apps/openmw/mwscript/cellextensions.cpp +++ b/apps/openmw/mwscript/cellextensions.cpp @@ -34,25 +34,85 @@ 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) + { + MWBase::World *world = MWBase::Environment::get().getWorld(); + + if (const ESM::Cell *ext = world->getExterior(name)) { + world->indexToPosition(ext->mData.mX, ext->mData.mY, pos.pos[0], pos.pos[1], true); + + return true; + } + return false; + } + virtual void execute (Interpreter::Runtime& runtime) { std::string cell = runtime.getStringLiteral (runtime[0].mInteger); runtime.pop(); ESM::Position pos; - pos.rot[0] = pos.rot[1] = pos.rot[2] = 0; - pos.pos[2] = 0; + MWBase::World *world = MWBase::Environment::get().getWorld(); - if (const ESM::Cell *exterior = MWBase::Environment::get().getWorld()->getExterior (cell)) - { - MWBase::Environment::get().getWorld()->indexToPosition (exterior->mData.mX, exterior->mData.mY, - pos.pos[0], pos.pos[1], true); - MWBase::Environment::get().getWorld()->changeToExteriorCell (pos); + if (findExteriorPosition(cell, pos)) { + world->changeToExteriorCell(pos); } - else - { - pos.pos[0] = pos.pos[1] = 0; - MWBase::Environment::get().getWorld()->changeToInteriorCell (cell, pos); + else { + // Change to interior even if findInteriorPosition() + // yields false. In this case position will be zero-point. + findInteriorPosition(cell, pos); + world->changeToInteriorCell(cell, pos); } } }; From 6bb39422881d683946746f14a1e54951476db667 Mon Sep 17 00:00:00 2001 From: greye Date: Sun, 7 Jul 2013 13:47:40 +0400 Subject: [PATCH 2/5] use Land height data for position in coc --- apps/openmw/mwscript/cellextensions.cpp | 13 ++++++++++++- 1 file changed, 12 insertions(+), 1 deletion(-) diff --git a/apps/openmw/mwscript/cellextensions.cpp b/apps/openmw/mwscript/cellextensions.cpp index e1acfadb2..dfd896778 100644 --- a/apps/openmw/mwscript/cellextensions.cpp +++ b/apps/openmw/mwscript/cellextensions.cpp @@ -87,10 +87,21 @@ namespace MWScript 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)) { - world->indexToPosition(ext->mData.mX, ext->mData.mY, pos.pos[0], pos.pos[1], true); + 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; } From 0c303aa285072f396d539c103826253f9880c63b Mon Sep 17 00:00:00 2001 From: greye Date: Sun, 7 Jul 2013 14:30:11 +0400 Subject: [PATCH 3/5] fix fading on cell transition when cell is loaded --- apps/openmw/mwworld/scene.cpp | 1 + 1 file changed, 1 insertion(+) diff --git a/apps/openmw/mwworld/scene.cpp b/apps/openmw/mwworld/scene.cpp index 22facdcaf..09fde684d 100644 --- a/apps/openmw/mwworld/scene.cpp +++ b/apps/openmw/mwworld/scene.cpp @@ -378,6 +378,7 @@ namespace MWWorld world->rotateObject(world->getPlayer().getPlayer(), x, y, z); MWWorld::Class::get(world->getPlayer().getPlayer()).adjustPosition(world->getPlayer().getPlayer()); + world->getFader()->fadeIn(0.5f); return; } From f3d54a7ba4465b28e29f505c5513fd2a08329bca Mon Sep 17 00:00:00 2001 From: greye Date: Sun, 7 Jul 2013 15:03:06 +0400 Subject: [PATCH 4/5] move finding default cell positions to World --- apps/openmw/mwbase/world.hpp | 8 +++ apps/openmw/mwscript/cellextensions.cpp | 78 +------------------------ apps/openmw/mwworld/worldimp.cpp | 76 ++++++++++++++++++++++++ apps/openmw/mwworld/worldimp.hpp | 8 +++ 4 files changed, 94 insertions(+), 76 deletions(-) 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); }; } From e553f285b8c4f4f228cb1624f2b06f3504583f2e Mon Sep 17 00:00:00 2001 From: greye Date: Sun, 7 Jul 2013 15:06:05 +0400 Subject: [PATCH 5/5] update player position on engine start --- apps/openmw/engine.cpp | 17 ++++++----------- 1 file changed, 6 insertions(+), 11 deletions(-) diff --git a/apps/openmw/engine.cpp b/apps/openmw/engine.cpp index 2918f5d8b..1050c1717 100644 --- a/apps/openmw/engine.cpp +++ b/apps/openmw/engine.cpp @@ -432,19 +432,14 @@ void OMW::Engine::prepareEngine (Settings::Manager & settings) { // load cell ESM::Position pos; - pos.rot[0] = pos.rot[1] = pos.rot[2] = 0; - pos.pos[2] = 0; + MWBase::World *world = MWBase::Environment::get().getWorld(); - if (const ESM::Cell *exterior = MWBase::Environment::get().getWorld()->getExterior (mCellName)) - { - MWBase::Environment::get().getWorld()->indexToPosition (exterior->mData.mX, exterior->mData.mY, - pos.pos[0], pos.pos[1], true); - MWBase::Environment::get().getWorld()->changeToExteriorCell (pos); + if (world->findExteriorPosition(mCellName, pos)) { + world->changeToExteriorCell (pos); } - else - { - pos.pos[0] = pos.pos[1] = 0; - MWBase::Environment::get().getWorld()->changeToInteriorCell (mCellName, pos); + else { + world->findInteriorPosition(mCellName, pos); + world->changeToInteriorCell (mCellName, pos); } } else