#ifndef GAME_MWWORLD_CELLSTORE_H #define GAME_MWWORLD_CELLSTORE_H #include #include #include #include "refdata.hpp" namespace ESMS { struct ESMStore; } namespace MWWorld { /// A reference to one object (of any type) in a cell. /// /// Constructing this with a CellRef instance in the constructor means that /// in practice (where D is RefData) the possibly mutable data is copied /// across to mData. If later adding data (such as position) to CellRef /// this would have to be manually copied across. template struct LiveCellRef { LiveCellRef(const ESM::CellRef& cref, const X* b = NULL) : base(b), ref(cref), mData(ref) {} LiveCellRef(const X* b = NULL) : base(b), mData(ref) {} // The object that this instance is based on. const X* base; /* Information about this instance, such as 3D location and rotation and individual type-dependent data. */ ESM::CellRef ref; /// runtime-data RefData mData; }; /// A list of cell references template struct CellRefList { typedef LiveCellRef LiveRef; typedef std::list List; List list; // Search for the given reference in the given reclist from // ESMStore. Insert the reference into the list if a match is // found. If not, throw an exception. template void find(ESM::CellRef &ref, const Y& recList) { const X* obj = recList.find(ref.refID); if(obj == NULL) throw std::runtime_error("Error resolving cell reference " + ref.refID); list.push_back(LiveRef(ref, obj)); } 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. class CellStore { public: enum State { State_Unloaded, State_Preloaded, State_Loaded }; CellStore (const ESM::Cell *cell_); const ESM::Cell *cell; State mState; std::vector mIds; float mWaterLevel; // Lists for each individual object type CellRefList activators; CellRefList potions; CellRefList appas; CellRefList armors; CellRefList books; CellRefList clothes; CellRefList containers; CellRefList creatures; CellRefList doors; CellRefList ingreds; CellRefList creatureLists; CellRefList itemLists; CellRefList lights; CellRefList lockpicks; CellRefList miscItems; CellRefList npcs; CellRefList probes; CellRefList repairs; CellRefList statics; CellRefList weapons; void load (const ESMS::ESMStore &store, ESM::ESMReader &esm); void preload (const ESMS::ESMStore &store, ESM::ESMReader &esm); /// Call functor (ref) for each reference. functor must return a bool. Returning /// false will abort the iteration. /// \return Iteration completed? template bool forEach (Functor& functor) { return forEachImp (functor, activators) && forEachImp (functor, potions) && forEachImp (functor, appas) && forEachImp (functor, armors) && forEachImp (functor, books) && forEachImp (functor, clothes) && forEachImp (functor, containers) && forEachImp (functor, creatures) && forEachImp (functor, doors) && forEachImp (functor, ingreds) && forEachImp (functor, creatureLists) && forEachImp (functor, itemLists) && forEachImp (functor, lights) && forEachImp (functor, lockpicks) && forEachImp (functor, miscItems) && forEachImp (functor, npcs) && forEachImp (functor, probes) && forEachImp (functor, repairs) && forEachImp (functor, statics) && forEachImp (functor, weapons); } private: template bool forEachImp (Functor& functor, List& list) { for (typename List::List::iterator iter (list.list.begin()); iter!=list.list.end(); ++iter) if (!functor (iter->ref, iter->mData)) return false; return true; } /// Run through references and store IDs void listRefs(const ESMS::ESMStore &store, ESM::ESMReader &esm); void loadRefs(const ESMS::ESMStore &store, ESM::ESMReader &esm); }; } #endif