OpenMW
components/esm/loadcell.hpp
Go to the documentation of this file.
00001 #ifndef OPENMW_ESM_CELL_H
00002 #define OPENMW_ESM_CELL_H
00003 
00004 #include <string>
00005 #include <vector>
00006 #include <list>
00007 
00008 #include "esmcommon.hpp"
00009 #include "defs.hpp"
00010 #include "cellref.hpp"
00011 
00012 namespace MWWorld
00013 {
00014     class ESMStore;
00015 }
00016 
00017 namespace ESM
00018 {
00019 class ESMReader;
00020 class ESMWriter;
00021 
00022 /* Moved cell reference tracking object. This mainly stores the target cell
00023         of the reference, so we can easily know where it has been moved when another
00024         plugin tries to move it independently.
00025     Unfortunately, we need to implement this here.
00026     */
00027 class MovedCellRef
00028 {
00029 public:
00030     int mRefnum;
00031 
00032     // Target cell (if exterior)
00033     int mTarget[2];
00034 
00035     // TODO: Support moving references between exterior and interior cells!
00036     //  This may happen in saves, when an NPC follows the player. Tribunal
00037     //  introduces a henchman (which no one uses), so we may need this as well.
00038 };
00039 
00041 bool operator==(const MovedCellRef& ref, int pRefnum);
00042 bool operator==(const CellRef& ref, int pRefnum);
00043 
00044 typedef std::list<MovedCellRef> MovedCellRefTracker;
00045 typedef std::list<CellRef> CellRefTracker;
00046 
00047 /* Cells hold data about objects, creatures, statics (rocks, walls,
00048    buildings) and landscape (for exterior cells). Cells frequently
00049    also has other associated LAND and PGRD records. Combined, all this
00050    data can be huge, and we cannot load it all at startup. Instead,
00051    the strategy we use is to remember the file position of each cell
00052    (using ESMReader::getContext()) and jumping back into place
00053    whenever we need to load a given cell.
00054  */
00055 struct Cell
00056 {
00057     static unsigned int sRecordId;
00058 
00059   enum Flags
00060     {
00061       Interior  = 0x01, // Interior cell
00062       HasWater  = 0x02, // Does this cell have a water surface
00063       NoSleep   = 0x04, // Is it allowed to sleep here (without a bed)
00064       QuasiEx   = 0x80  // Behave like exterior (Tribunal+), with
00065                         // skybox and weather
00066     };
00067 
00068   struct DATAstruct
00069   {
00070     int mFlags;
00071     int mX, mY;
00072   };
00073 
00074   struct AMBIstruct
00075   {
00076     Color mAmbient, mSunlight, mFog;
00077     float mFogDensity;
00078   };
00079 
00080   // Interior cells are indexed by this (it's the 'id'), for exterior
00081   // cells it is optional.
00082   std::string mName;
00083 
00084   // Optional region name for exterior and quasi-exterior cells.
00085   std::string mRegion;
00086 
00087   std::vector<ESM_Context> mContextList; // File position; multiple positions for multiple plugin support
00088   DATAstruct mData;
00089   AMBIstruct mAmbi;
00090   float mWater; // Water level
00091   bool mWaterInt;
00092   int mMapColor;
00093   int mNAM0;
00094 
00095   // References "leased" from another cell (i.e. a different cell
00096   //  introduced this ref, and it has been moved here by a plugin)
00097   CellRefTracker mLeasedRefs;
00098   MovedCellRefTracker mMovedRefs;
00099 
00100   void preLoad(ESMReader &esm);
00101   void postLoad(ESMReader &esm);
00102 
00103   // This method is left in for compatibility with esmtool. Parsing moved references currently requires
00104   //  passing ESMStore, bit it does not know about this parameter, so we do it this way.
00105   void load(ESMReader &esm, bool saveContext = true);
00106   void save(ESMWriter &esm) const;
00107 
00108   bool isExterior() const
00109   {
00110       return !(mData.mFlags & Interior);
00111   }
00112 
00113   int getGridX() const
00114   {
00115       return mData.mX;
00116   }
00117 
00118   int getGridY() const
00119   {
00120       return mData.mY;
00121   }
00122 
00123   bool hasWater() const
00124   {
00125       return (mData.mFlags&HasWater);
00126   }
00127 
00128   // Restore the given reader to the stored position. Will try to open
00129   // the file matching the stored file name. If you want to read from
00130   // somewhere other than the file system, you need to pre-open the
00131   // ESMReader, and the filename must match the stored filename
00132   // exactly.
00133   void restore(ESMReader &esm, int iCtx) const;
00134 
00135   std::string getDescription() const;
00137 
00138   /* Get the next reference in this cell, if any. Returns false when
00139      there are no more references in the cell.
00140 
00141      All fields of the CellRef struct are overwritten. You can safely
00142      reuse one memory location without blanking it between calls.
00143   */
00144   static bool getNextRef(ESMReader &esm, CellRef &ref);
00145 
00146   /* This fetches an MVRF record, which is used to track moved references.
00147    * Since they are comparably rare, we use a separate method for this.
00148    */
00149   static bool getNextMVRF(ESMReader &esm, MovedCellRef &mref);
00150 
00151     void blank();
00153 };
00154 }
00155 #endif