From cc0c21cf3526e04bd5b381432502479ee2296610 Mon Sep 17 00:00:00 2001 From: Marc Zinnschlag Date: Mon, 5 Jul 2010 12:09:04 +0200 Subject: [PATCH] added function to retrieve a live cell ref via name --- apps/openmw/mwrender/playerpos.hpp | 30 +++++++-- apps/openmw/mwworld/ptr.hpp | 5 ++ apps/openmw/mwworld/world.cpp | 101 +++++++++++++++++++++++++++- apps/openmw/mwworld/world.hpp | 10 ++- components/esm_store/cell_store.hpp | 11 +++ 5 files changed, 147 insertions(+), 10 deletions(-) diff --git a/apps/openmw/mwrender/playerpos.hpp b/apps/openmw/mwrender/playerpos.hpp index 47175651c5..44f86d7690 100644 --- a/apps/openmw/mwrender/playerpos.hpp +++ b/apps/openmw/mwrender/playerpos.hpp @@ -3,6 +3,10 @@ #include "OgreCamera.h" +#include + +#include "../mwworld/refdata.hpp" + namespace MWRender { // This class keeps track of the player position. It takes care of @@ -10,19 +14,22 @@ namespace MWRender // (to be done). class PlayerPos { - float x, y, z; + ESMS::LiveCellRef mPlayer; Ogre::Camera *camera; public: - PlayerPos(Ogre::Camera *cam) : - x(0), y(0), z(0), camera(cam) {} + PlayerPos(Ogre::Camera *cam, const ESM::NPC *player) : + camera(cam) + { + mPlayer.base = player; + } // Set the player position. Uses Morrowind coordinates. void setPos(float _x, float _y, float _z) { - x = _x; - y = _y; - z = _z; + mPlayer.ref.pos.pos[0] = _x; + mPlayer.ref.pos.pos[1] = _y; + mPlayer.ref.pos.pos[2] = _z; // TODO: Update sound listener } @@ -33,6 +40,7 @@ namespace MWRender // orientation. After the call, the new position is returned. void moveRel(float &relX, float &relY, float &relZ) { + // TODO: Update mPlayer state using namespace Ogre; // Move camera relative to its own direction @@ -53,6 +61,16 @@ namespace MWRender // Set the position setPos(relX, relY, relZ); } + + ESMS::LiveCellRef *getPlayer() + { + return &mPlayer; + } + + const ESMS::LiveCellRef *getPlayer() const + { + return &mPlayer; + } }; } #endif diff --git a/apps/openmw/mwworld/ptr.hpp b/apps/openmw/mwworld/ptr.hpp index 11ec4baf7e..9d031512d2 100644 --- a/apps/openmw/mwworld/ptr.hpp +++ b/apps/openmw/mwworld/ptr.hpp @@ -23,6 +23,11 @@ namespace MWWorld Ptr() : mCellRef (0), mRefData (0) {} + bool isEmpty() const + { + return mPtr.empty(); + } + template Ptr (ESMS::LiveCellRef *liveCellRef) { diff --git a/apps/openmw/mwworld/world.cpp b/apps/openmw/mwworld/world.cpp index 217bff7daf..22bba6c530 100644 --- a/apps/openmw/mwworld/world.cpp +++ b/apps/openmw/mwworld/world.cpp @@ -56,9 +56,74 @@ namespace MWWorld listCellScripts (mStore, cell.weapons, mLocalScripts); } + Ptr World::getPtr (const std::string& name, CellStore& cell) + { + if (ESMS::LiveCellRef *ref = cell.activators.find (name)) + return ref; + + if (ESMS::LiveCellRef *ref = cell.potions.find (name)) + return ref; + + if (ESMS::LiveCellRef *ref = cell.appas.find (name)) + return ref; + + if (ESMS::LiveCellRef *ref = cell.armors.find (name)) + return ref; + + if (ESMS::LiveCellRef *ref = cell.books.find (name)) + return ref; + + if (ESMS::LiveCellRef *ref = cell.clothes.find (name)) + return ref; + + if (ESMS::LiveCellRef *ref = cell.containers.find (name)) + return ref; + + if (ESMS::LiveCellRef *ref = cell.creatures.find (name)) + return ref; + + if (ESMS::LiveCellRef *ref = cell.doors.find (name)) + return ref; + + if (ESMS::LiveCellRef *ref = cell.ingreds.find (name)) + return ref; + + if (ESMS::LiveCellRef *ref = cell.creatureLists.find (name)) + return ref; + + if (ESMS::LiveCellRef *ref = cell.itemLists.find (name)) + return ref; + + if (ESMS::LiveCellRef *ref = cell.lights.find (name)) + return ref; + + if (ESMS::LiveCellRef *ref = cell.lockpicks.find (name)) + return ref; + + if (ESMS::LiveCellRef *ref = cell.miscItems.find (name)) + return ref; + + if (ESMS::LiveCellRef *ref = cell.npcs.find (name)) + return ref; + + if (ESMS::LiveCellRef *ref = cell.probes.find (name)) + return ref; + + if (ESMS::LiveCellRef *ref = cell.repairs.find (name)) + return ref; + + if (ESMS::LiveCellRef *ref = cell.statics.find (name)) + return ref; + + if (ESMS::LiveCellRef *ref = cell.weapons.find (name)) + return ref; + + return Ptr(); + } + World::World (Render::OgreRenderer& renderer, const boost::filesystem::path& dataDir, const std::string& master, const std::string& startCell, bool newGame) - : mSkyManager (0), mScene (renderer), mPlayerPos (mScene.getCamera()) + : mSkyManager (0), mScene (renderer), mPlayerPos (0) { boost::filesystem::path masterPath (dataDir); masterPath /= master; @@ -73,6 +138,8 @@ namespace MWWorld insertInteriorScripts (mInteriors[startCell]); + mPlayerPos = new MWRender::PlayerPos (mScene.getCamera(), mStore.npcs.find ("player")); + // global variables for (ESMS::RecListT::MapType::const_iterator iter (mStore.globals.list.begin()); @@ -114,12 +181,13 @@ namespace MWWorld iter!=mBufferedCells.end(); ++iter) delete iter->second; + delete mPlayerPos; delete mSkyManager; } MWRender::PlayerPos& World::getPlayerPos() { - return mPlayerPos; + return *mPlayerPos; } ESMS::ESMStore& World::getStore() @@ -147,4 +215,33 @@ namespace MWWorld return iter->second; } + + std::pair World::getPtr (const std::string& name, bool activeOnly) + { + // the player is always in an active cell. + if (name=="player") + { + // TODO: find real cell (might need to be stored in playerPos). For now we + // use the first active cell. This will fail the moment we move into an + // exterior cell. + return std::make_pair (mPlayerPos->getPlayer(), mActiveCells.begin()->first); + } + + // active cells + for (CellRenderCollection::iterator iter (mActiveCells.begin()); + iter!=mActiveCells.end(); ++iter) + { + Ptr ptr = getPtr (name, *iter->first); + + if (!ptr.isEmpty()) + return std::make_pair (ptr, iter->first); + } + + if (!activeOnly) + { + // TODO: inactive cells + } + + throw std::runtime_error ("unknown ID: " + name); + } } diff --git a/apps/openmw/mwworld/world.hpp b/apps/openmw/mwworld/world.hpp index d39c457d20..74a1ee159e 100644 --- a/apps/openmw/mwworld/world.hpp +++ b/apps/openmw/mwworld/world.hpp @@ -36,15 +36,15 @@ namespace MWWorld public: typedef std::vector > ScriptList; + typedef ESMS::CellStore CellStore; private: - typedef ESMS::CellStore CellStore; typedef std::map CellRenderCollection; MWRender::SkyManager* mSkyManager; MWRender::MWScene mScene; - MWRender::PlayerPos mPlayerPos; + MWRender::PlayerPos *mPlayerPos; CellRenderCollection mActiveCells; CellRenderCollection mBufferedCells; // loaded, but not active (buffering not implementd yet) ESM::ESMReader mEsm; @@ -59,6 +59,8 @@ namespace MWWorld void insertInteriorScripts (ESMS::CellStore& cell); + Ptr getPtr (const std::string& name, CellStore& cellStore); + public: World (Render::OgreRenderer& renderer, const boost::filesystem::path& master, @@ -77,6 +79,10 @@ namespace MWWorld ///< Has the player moved to a different cell, since the last frame? Interpreter::Type_Data& getGlobalVariable (const std::string& name); + + std::pair getPtr (const std::string& name, bool activeOnly); + ///< Return a pointer to a liveCellRef with the given name. + /// \param activeOnly do non search inactive cells. }; } diff --git a/components/esm_store/cell_store.hpp b/components/esm_store/cell_store.hpp index 90cd5d1a65..114a12e786 100644 --- a/components/esm_store/cell_store.hpp +++ b/components/esm_store/cell_store.hpp @@ -63,6 +63,17 @@ namespace ESMS list.push_back(lr); } + + LiveRef *find (const std::string& name) + { + for (typename std::list::iterator iter (list.begin()); iter!=list.end(); ++iter) + { + if (iter->ref.refID==name) + return &*iter; + } + + return 0; + } }; /// A storage struct for one single cell reference.