diff --git a/apps/openmw/mwworld/storedevel/esmstore.cpp b/apps/openmw/mwworld/storedevel/esmstore.cpp new file mode 100644 index 000000000..eb236d1bc --- /dev/null +++ b/apps/openmw/mwworld/storedevel/esmstore.cpp @@ -0,0 +1,100 @@ +#include "esmstore.hpp" + +#include +#include + +namespace MWWorld +{ + +static bool isCacheableRecord(int id) +{ + if (id == ESM::REC_ACTI || id == ESM::REC_ALCH || id == ESM::REC_APPA || id == ESM::REC_ARMO || + id == ESM::REC_BOOK || id == ESM::REC_CLOT || id == ESM::REC_CONT || id == ESM::REC_CREA || + id == ESM::REC_DOOR || id == ESM::REC_INGR || id == ESM::REC_LEVC || id == ESM::REC_LEVI || + id == ESM::REC_LIGH || id == ESM::REC_LOCK || id == ESM::REC_MISC || id == ESM::REC_NPC_ || + id == ESM::REC_PROB || id == ESM::REC_REPA || id == ESM::REC_STAT || id == ESM::REC_WEAP) + { + return true; + } + return false; +} + +void ESMStore::load(ESM::ESMReader &esm) +{ + std::set missing; + + ESM::Dialogue *dialogue = 0; + + // Loop through all records + while(esm.hasMoreRecs()) + { + ESM::NAME n = esm.getRecName(); + esm.getRecHeader(); + + // Look up the record type. + std::map::iterator it = mStores.find(n.val); + + if (it == mStores.end()) { + if (n.val == ESM::REC_INFO) { + if (dialogue) { + dialogue->mInfo.push_back(ESM::DialInfo()); + dialogue->mInfo.back().load(esm); + } else { + std::cerr << "error: info record without dialog" << std::endl; + esm.skipRecord(); + } + } else if (n.val == ESM::REC_MGEF) { + mMagicEffects.load (esm); + } else if (n.val == ESM::REC_SKIL) { + mSkills.load (esm); + } else { + // Not found (this would be an error later) + esm.skipRecord(); + missing.insert(n.toString()); + } + } else { + // Load it + std::string id = esm.getHNOString("NAME"); + it->second->load(esm, id); + + if (n.val==ESM::REC_DIAL) { + // dirty hack, but it is better than non-const search() + // or friends + dialogue = const_cast(mDialogs.search(id)); + assert (dialogue != NULL); + } else { + dialogue = 0; + } + // Insert the reference into the global lookup + if (!id.empty() && isCacheableRecord(n.val)) { + mIds[id] = n.val; + } + } + } + + /* This information isn't needed on screen. But keep the code around + for debugging purposes later. + + cout << "\n" << mStores.size() << " record types:\n"; + for(RecListList::iterator it = mStores.begin(); it != mStores.end(); it++) + cout << " " << toStr(it->first) << ": " << it->second->getSize() << endl; + cout << "\nNot implemented yet: "; + for(set::iterator it = missing.begin(); + it != missing.end(); it++ ) + cout << *it << " "; + cout << endl; + */ +} + +void ESMStore::setUp() +{ + std::map::iterator it = mStores.begin(); + for (; it != mStores.end(); ++it) { + it->second->setUp(); + } + mSkills.setUp(); + mMagicEffects.setUp(); + mAttributes.setUp(); +} + +} // end namespace diff --git a/apps/openmw/mwworld/storedevel/esmstore.hpp b/apps/openmw/mwworld/storedevel/esmstore.hpp new file mode 100644 index 000000000..525341a30 --- /dev/null +++ b/apps/openmw/mwworld/storedevel/esmstore.hpp @@ -0,0 +1,362 @@ +#ifndef OPENMW_MWWORLD_ESMSTORE_H +#define OPENMW_MWWORLD_ESMSTORE_H + +#include + +#include +#include "store.hpp" + +namespace MWWorld +{ + class ESMStore + { + Store mActivators; + Store mPotions; + Store mAppas; + Store mArmors; + Store mBodyParts; + Store mBooks; + Store mBirthSigns; + Store mClasses; + Store mClothes; + Store mContChange; + Store mContainers; + Store mCreatures; + Store mCreaChange; + Store mDialogs; + Store mDoors; + Store mEnchants; + Store mFactions; + Store mGlobals; + Store mIngreds; + Store mCreatureLists; + Store mItemLists; + Store mLights; + Store mLockpicks; + Store mMiscItems; + Store mNpcs; + Store mNpcChange; + Store mProbes; + Store mRaces; + Store mRegions; + Store mRepairs; + Store mSoundGens; + Store mSounds; + Store mSpells; + Store mStartScripts; + Store mStatics; + Store mWeapons; + + Store mGameSettings; + Store mScripts; + + // Lists that need special rules + Store mCells; + Store mLands; + Store mLandTextures; + Store mPathgrids; + + Store mMagicEffects; + Store mSkills; + + // Special entry which is hardcoded and not loaded from an ESM + Store mAttributes; + + // Lookup of all IDs. Makes looking up references faster. Just + // maps the id name to the record type. + std::map mIds; + std::map mStores; + + public: + // Look up the given ID in 'all'. Returns 0 if not found. + int find(const std::string &id) const + { + std::map::const_iterator it = mIds.find(id); + if (it == mIds.end()) { + return 0; + } + return it->second; + } + + ESMStore() + { + mStores[ESM::REC_ACTI] = &mActivators; + mStores[ESM::REC_ALCH] = &mPotions; + mStores[ESM::REC_APPA] = &mAppas; + mStores[ESM::REC_ARMO] = &mArmors; + mStores[ESM::REC_BODY] = &mBodyParts; + mStores[ESM::REC_BOOK] = &mBooks; + mStores[ESM::REC_BSGN] = &mBirthSigns; + mStores[ESM::REC_CELL] = &mCells; + mStores[ESM::REC_CLAS] = &mClasses; + mStores[ESM::REC_CLOT] = &mClothes; + mStores[ESM::REC_CNTC] = &mContChange; + mStores[ESM::REC_CONT] = &mContainers; + mStores[ESM::REC_CREA] = &mCreatures; + mStores[ESM::REC_CREC] = &mCreaChange; + mStores[ESM::REC_DIAL] = &mDialogs; + mStores[ESM::REC_DOOR] = &mDoors; + mStores[ESM::REC_ENCH] = &mEnchants; + mStores[ESM::REC_FACT] = &mFactions; + mStores[ESM::REC_GLOB] = &mGlobals; + mStores[ESM::REC_GMST] = &mGameSettings; + mStores[ESM::REC_INGR] = &mIngreds; + mStores[ESM::REC_LAND] = &mLands; + mStores[ESM::REC_LEVC] = &mCreatureLists; + mStores[ESM::REC_LEVI] = &mItemLists; + mStores[ESM::REC_LIGH] = &mLights; + mStores[ESM::REC_LOCK] = &mLockpicks; + mStores[ESM::REC_LTEX] = &mLandTextures; + mStores[ESM::REC_MISC] = &mMiscItems; + mStores[ESM::REC_NPC_] = &mNpcs; + mStores[ESM::REC_NPCC] = &mNpcChange; + mStores[ESM::REC_PGRD] = &mPathgrids; + mStores[ESM::REC_PROB] = &mProbes; + mStores[ESM::REC_RACE] = &mRaces; + mStores[ESM::REC_REGN] = &mRegions; + mStores[ESM::REC_REPA] = &mRepairs; + mStores[ESM::REC_SCPT] = &mScripts; + mStores[ESM::REC_SNDG] = &mSoundGens; + mStores[ESM::REC_SOUN] = &mSounds; + mStores[ESM::REC_SPEL] = &mSpells; + mStores[ESM::REC_SSCR] = &mStartScripts; + mStores[ESM::REC_STAT] = &mStatics; + mStores[ESM::REC_WEAP] = &mWeapons; + } + + void load(ESM::ESMReader &esm); + void setUp(); + + template + const Store &get() const { + throw std::runtime_error("Storage for this type not exist"); + } + }; + + template <> + const Store &ESMStore::get() const { + return mActivators; + } + + template <> + const Store &ESMStore::get() const { + return mPotions; + } + + template <> + const Store &ESMStore::get() const { + return mAppas; + } + + template <> + const Store &ESMStore::get() const { + return mArmors; + } + + template <> + const Store &ESMStore::get() const { + return mBodyParts; + } + + template <> + const Store &ESMStore::get() const { + return mBooks; + } + + template <> + const Store &ESMStore::get() const { + return mBirthSigns; + } + + template <> + const Store &ESMStore::get() const { + return mClasses; + } + + template <> + const Store &ESMStore::get() const { + return mClothes; + } + + template <> + const Store &ESMStore::get() const { + return mContChange; + } + + template <> + const Store &ESMStore::get() const { + return mContainers; + } + + template <> + const Store &ESMStore::get() const { + return mCreatures; + } + + template <> + const Store &ESMStore::get() const { + return mCreaChange; + } + + template <> + const Store &ESMStore::get() const { + return mDialogs; + } + + template <> + const Store &ESMStore::get() const { + return mDoors; + } + + template <> + const Store &ESMStore::get() const { + return mEnchants; + } + + template <> + const Store &ESMStore::get() const { + return mFactions; + } + + template <> + const Store &ESMStore::get() const { + return mGlobals; + } + + template <> + const Store &ESMStore::get() const { + return mIngreds; + } + + template <> + const Store &ESMStore::get() const { + return mCreatureLists; + } + + template <> + const Store &ESMStore::get() const { + return mItemLists; + } + + template <> + const Store &ESMStore::get() const { + return mLights; + } + + template <> + const Store &ESMStore::get() const { + return mLockpicks; + } + + template <> + const Store &ESMStore::get() const { + return mMiscItems; + } + + template <> + const Store &ESMStore::get() const { + return mNpcs; + } + + template <> + const Store &ESMStore::get() const { + return mNpcChange; + } + + template <> + const Store &ESMStore::get() const { + return mProbes; + } + + template <> + const Store &ESMStore::get() const { + return mRaces; + } + + template <> + const Store &ESMStore::get() const { + return mRegions; + } + + template <> + const Store &ESMStore::get() const { + return mRepairs; + } + + template <> + const Store &ESMStore::get() const { + return mSoundGens; + } + + template <> + const Store &ESMStore::get() const { + return mSounds; + } + + template <> + const Store &ESMStore::get() const { + return mSpells; + } + + template <> + const Store &ESMStore::get() const { + return mStartScripts; + } + + template <> + const Store &ESMStore::get() const { + return mStatics; + } + + template <> + const Store &ESMStore::get() const { + return mWeapons; + } + + template <> + const Store &ESMStore::get() const { + return mGameSettings; + } + + template <> + const Store &ESMStore::get() const { + return mScripts; + } + + template <> + const Store &ESMStore::get() const { + return mCells; + } + + template <> + const Store &ESMStore::get() const { + return mLands; + } + + template <> + const Store &ESMStore::get() const { + return mLandTextures; + } + + template <> + const Store &ESMStore::get() const { + return mPathgrids; + } + + template <> + const Store &ESMStore::get() const { + return mMagicEffects; + } + + template <> + const Store &ESMStore::get() const { + return mSkills; + } + + template <> + const Store &ESMStore::get() const { + return mAttributes; + } +} + +#endif