just replace esmstore, inconsistent

actorid
greye 12 years ago
parent d205723a17
commit 7cf0b8a680

@ -53,7 +53,7 @@ add_openmw_dir (mwworld
containerstore actiontalk actiontake manualref player cellfunctors
cells localscripts customdata weather inventorystore ptr actionopen actionread
actionequip timestamp actionalchemy cellstore actionapply actioneat
esmstore reclists
esmstore store recordcmp
)
add_openmw_dir (mwclass

@ -6,6 +6,19 @@
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<std::string> missing;
@ -19,85 +32,51 @@ void ESMStore::load(ESM::ESMReader &esm)
esm.getRecHeader();
// Look up the record type.
RecListList::iterator it = recLists.find(n.val);
if(it == recLists.end())
{
if (n.val==ESM::REC_INFO)
{
if (dialogue)
{
ESM::DialInfo info;
info.load (esm);
dialogue->mInfo.push_back (info);
}
else
{
std::map<int, StoreBase *>::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)
{
magicEffects.load (esm);
}
else if (n.val==ESM::REC_SKIL)
{
skills.load (esm);
}
else
{
} 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
{
} else {
// Load it
std::string id = esm.getHNOString("NAME");
it->second->load(esm, id);
if (n.val==ESM::REC_DIAL)
{
RecListCaseT<ESM::Dialogue>& recList =
static_cast<RecListCaseT<ESM::Dialogue>& > (*it->second);
ESM::Dialogue* d = recList.search (id);
assert (d != NULL);
dialogue = d;
}
else
if (n.val==ESM::REC_DIAL) {
// dirty hack, but it is better than non-const search()
// or friends
dialogue = const_cast<ESM::Dialogue *>(mDialogs.search(id));
assert (dialogue != NULL);
} else {
dialogue = 0;
}
// Insert the reference into the global lookup
if(!id.empty() &&
(n.val==ESM::REC_ACTI || n.val==ESM::REC_ALCH || n.val==ESM::REC_APPA || n.val==ESM::REC_ARMO ||
n.val==ESM::REC_BOOK || n.val==ESM::REC_CLOT || n.val==ESM::REC_CONT || n.val==ESM::REC_CREA ||
n.val==ESM::REC_DOOR || n.val==ESM::REC_INGR || n.val==ESM::REC_LEVC || n.val==ESM::REC_LEVI ||
n.val==ESM::REC_LIGH || n.val==ESM::REC_LOCK || n.val==ESM::REC_MISC || n.val==ESM::REC_NPC_ ||
n.val==ESM::REC_PROB || n.val==ESM::REC_REPA || n.val==ESM::REC_STAT || n.val==ESM::REC_WEAP)
)
all[id] = n.val;
if (!id.empty() && isCacheableRecord(n.val)) {
mIds[id] = n.val;
}
}
}
for (int i = 0; i < ESM::Attribute::Length; ++i)
{
typedef ESM::Attribute EsmAttr;
EsmAttr::AttributeID id = EsmAttr::sAttributeIds[i];
attributes.list.insert(std::make_pair(id, ESM::Attribute(id, EsmAttr::sGmstAttributeIds[i], EsmAttr::sGmstAttributeDescIds[i])));
}
/* This information isn't needed on screen. But keep the code around
for debugging purposes later.
cout << "\n" << recLists.size() << " record types:\n";
for(RecListList::iterator it = recLists.begin(); it != recLists.end(); it++)
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<string>::iterator it = missing.begin();
@ -107,4 +86,15 @@ void ESMStore::load(ESM::ESMReader &esm)
*/
}
void ESMStore::setUp()
{
std::map<int, StoreBase *>::iterator it = mStores.begin();
for (; it != mStores.end(); ++it) {
it->second->setUp();
}
mSkills.setUp();
mMagicEffects.setUp();
mAttributes.setUp();
}
} // end namespace

@ -1,145 +1,362 @@
#ifndef OPENMW_MWWORLD_STORE_H
#define OPENMW_MWWORLD_STORE_H
#ifndef OPENMW_MWWORLD_ESMSTORE_H
#define OPENMW_MWWORLD_ESMSTORE_H
/*
The ESM storage module.
This is separate from the ESM loader module, located in esm/. It is
also unaware of the cell loading and storage module.
The advantage of this, as with all other modularizations, is that
you can replace the storage method later without touching the
loading code. Cutting down dependencies also help on the general
maintainability.
*/
#include <stdexcept>
#include <components/esm/records.hpp>
#include "reclists.hpp"
#include "store.hpp"
namespace MWWorld
{
struct ESMStore
{
/* Lists all the list types. Mostly used for quick lookup on
loading. The key is the record name (4 chars) parsed as a 32
bit int. See esm/records.hpp for the complete list.
*/
RecListList recLists;
// Each individual list
RecListT<ESM::Activator> activators;
RecListWithIDT<ESM::Potion> potions;
RecListT<ESM::Apparatus> appas;
RecListT<ESM::Armor> armors;
RecListT<ESM::BodyPart> bodyParts;
RecListWithIDT<ESM::Book> books;
RecListT<ESM::BirthSign> birthSigns;
RecListT<ESM::Class> classes;
RecListT<ESM::Clothing> clothes;
RecListT<ESM::LoadCNTC> contChange;
RecListT<ESM::Container> containers;
RecListWithIDT<ESM::Creature> creatures;
RecListT<ESM::LoadCREC> creaChange;
RecListCaseT<ESM::Dialogue> dialogs;
RecListT<ESM::Door> doors;
RecListT<ESM::Enchantment> enchants;
RecListT<ESM::Faction> factions;
RecListT<ESM::Global> globals;
RecListWithIDT<ESM::Ingredient> ingreds;
RecListT<ESM::CreatureLevList> creatureLists;
RecListT<ESM::ItemLevList> itemLists;
RecListT<ESM::Light> lights;
RecListT<ESM::Tool> lockpicks;
RecListT<ESM::Miscellaneous> miscItems;
RecListWithIDT<ESM::NPC> npcs;
RecListT<ESM::LoadNPCC> npcChange;
RecListT<ESM::Probe> probes;
RecListT<ESM::Race> races;
RecListT<ESM::Region> regions;
RecListT<ESM::Repair> repairs;
RecListT<ESM::SoundGenerator> soundGens;
RecListT<ESM::Sound> sounds;
RecListT<ESM::Spell> spells;
RecListT<ESM::StartScript> startScripts;
RecListT<ESM::Static> statics;
RecListT<ESM::Weapon> weapons;
// Lists that need special rules
CellList cells;
RecListWithIDT<ESM::GameSetting> gameSettings;
LandList lands;
LTexList landTexts;
ScriptListT<ESM::Script> scripts;
IndexListT<ESM::MagicEffect> magicEffects;
IndexListT<ESM::Skill> skills;
//RecListT<ESM::Pathgrid> pathgrids;
PathgridList pathgrids;
// Special entry which is hardcoded and not loaded from an ESM
IndexListT<ESM::Attribute> attributes;
// Lookup of all IDs. Makes looking up references faster. Just
// maps the id name to the record type.
typedef std::map<std::string, int> AllMap;
AllMap all;
// Look up the given ID in 'all'. Returns 0 if not found.
int find(const std::string &id) const
class ESMStore
{
AllMap::const_iterator it = all.find(id);
if(it == all.end()) return 0;
return it->second;
Store<ESM::Activator> mActivators;
Store<ESM::Potion> mPotions;
Store<ESM::Apparatus> mAppas;
Store<ESM::Armor> mArmors;
Store<ESM::BodyPart> mBodyParts;
Store<ESM::Book> mBooks;
Store<ESM::BirthSign> mBirthSigns;
Store<ESM::Class> mClasses;
Store<ESM::Clothing> mClothes;
Store<ESM::LoadCNTC> mContChange;
Store<ESM::Container> mContainers;
Store<ESM::Creature> mCreatures;
Store<ESM::LoadCREC> mCreaChange;
Store<ESM::Dialogue> mDialogs;
Store<ESM::Door> mDoors;
Store<ESM::Enchantment> mEnchants;
Store<ESM::Faction> mFactions;
Store<ESM::Global> mGlobals;
Store<ESM::Ingredient> mIngreds;
Store<ESM::CreatureLevList> mCreatureLists;
Store<ESM::ItemLevList> mItemLists;
Store<ESM::Light> mLights;
Store<ESM::Tool> mLockpicks;
Store<ESM::Miscellaneous> mMiscItems;
Store<ESM::NPC> mNpcs;
Store<ESM::LoadNPCC> mNpcChange;
Store<ESM::Probe> mProbes;
Store<ESM::Race> mRaces;
Store<ESM::Region> mRegions;
Store<ESM::Repair> mRepairs;
Store<ESM::SoundGenerator> mSoundGens;
Store<ESM::Sound> mSounds;
Store<ESM::Spell> mSpells;
Store<ESM::StartScript> mStartScripts;
Store<ESM::Static> mStatics;
Store<ESM::Weapon> mWeapons;
Store<ESM::GameSetting> mGameSettings;
Store<ESM::Script> mScripts;
// Lists that need special rules
Store<ESM::Cell> mCells;
Store<ESM::Land> mLands;
Store<ESM::LandTexture> mLandTextures;
Store<ESM::Pathgrid> mPathgrids;
Store<ESM::MagicEffect> mMagicEffects;
Store<ESM::Skill> mSkills;
// Special entry which is hardcoded and not loaded from an ESM
Store<ESM::Attribute> mAttributes;
// Lookup of all IDs. Makes looking up references faster. Just
// maps the id name to the record type.
std::map<std::string, int> mIds;
std::map<int, StoreBase *> mStores;
public:
// Look up the given ID in 'all'. Returns 0 if not found.
int find(const std::string &id) const
{
std::map<std::string, int>::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 <class T>
const Store<T> &get() const {
throw std::runtime_error("Storage for this type not exist");
}
};
template <>
const Store<ESM::Activator> &ESMStore::get<ESM::Activator>() const {
return mActivators;
}
ESMStore()
{
recLists[ESM::REC_ACTI] = &activators;
recLists[ESM::REC_ALCH] = &potions;
recLists[ESM::REC_APPA] = &appas;
recLists[ESM::REC_ARMO] = &armors;
recLists[ESM::REC_BODY] = &bodyParts;
recLists[ESM::REC_BOOK] = &books;
recLists[ESM::REC_BSGN] = &birthSigns;
recLists[ESM::REC_CELL] = &cells;
recLists[ESM::REC_CLAS] = &classes;
recLists[ESM::REC_CLOT] = &clothes;
recLists[ESM::REC_CNTC] = &contChange;
recLists[ESM::REC_CONT] = &containers;
recLists[ESM::REC_CREA] = &creatures;
recLists[ESM::REC_CREC] = &creaChange;
recLists[ESM::REC_DIAL] = &dialogs;
recLists[ESM::REC_DOOR] = &doors;
recLists[ESM::REC_ENCH] = &enchants;
recLists[ESM::REC_FACT] = &factions;
recLists[ESM::REC_GLOB] = &globals;
recLists[ESM::REC_GMST] = &gameSettings;
recLists[ESM::REC_INGR] = &ingreds;
recLists[ESM::REC_LAND] = &lands;
recLists[ESM::REC_LEVC] = &creatureLists;
recLists[ESM::REC_LEVI] = &itemLists;
recLists[ESM::REC_LIGH] = &lights;
recLists[ESM::REC_LOCK] = &lockpicks;
recLists[ESM::REC_LTEX] = &landTexts;
recLists[ESM::REC_MISC] = &miscItems;
recLists[ESM::REC_NPC_] = &npcs;
recLists[ESM::REC_NPCC] = &npcChange;
recLists[ESM::REC_PGRD] = &pathgrids;
recLists[ESM::REC_PROB] = &probes;
recLists[ESM::REC_RACE] = &races;
recLists[ESM::REC_REGN] = &regions;
recLists[ESM::REC_REPA] = &repairs;
recLists[ESM::REC_SCPT] = &scripts;
recLists[ESM::REC_SNDG] = &soundGens;
recLists[ESM::REC_SOUN] = &sounds;
recLists[ESM::REC_SPEL] = &spells;
recLists[ESM::REC_SSCR] = &startScripts;
recLists[ESM::REC_STAT] = &statics;
recLists[ESM::REC_WEAP] = &weapons;
}
void load(ESM::ESMReader &esm);
};
template <>
const Store<ESM::Potion> &ESMStore::get<ESM::Potion>() const {
return mPotions;
}
template <>
const Store<ESM::Apparatus> &ESMStore::get<ESM::Apparatus>() const {
return mAppas;
}
template <>
const Store<ESM::Armor> &ESMStore::get<ESM::Armor>() const {
return mArmors;
}
template <>
const Store<ESM::BodyPart> &ESMStore::get<ESM::BodyPart>() const {
return mBodyParts;
}
template <>
const Store<ESM::Book> &ESMStore::get<ESM::Book>() const {
return mBooks;
}
template <>
const Store<ESM::BirthSign> &ESMStore::get<ESM::BirthSign>() const {
return mBirthSigns;
}
template <>
const Store<ESM::Class> &ESMStore::get<ESM::Class>() const {
return mClasses;
}
template <>
const Store<ESM::Clothing> &ESMStore::get<ESM::Clothing>() const {
return mClothes;
}
template <>
const Store<ESM::LoadCNTC> &ESMStore::get<ESM::LoadCNTC>() const {
return mContChange;
}
template <>
const Store<ESM::Container> &ESMStore::get<ESM::Container>() const {
return mContainers;
}
template <>
const Store<ESM::Creature> &ESMStore::get<ESM::Creature>() const {
return mCreatures;
}
template <>
const Store<ESM::LoadCREC> &ESMStore::get<ESM::LoadCREC>() const {
return mCreaChange;
}
template <>
const Store<ESM::Dialogue> &ESMStore::get<ESM::Dialogue>() const {
return mDialogs;
}
template <>
const Store<ESM::Door> &ESMStore::get<ESM::Door>() const {
return mDoors;
}
template <>
const Store<ESM::Enchantment> &ESMStore::get<ESM::Enchantment>() const {
return mEnchants;
}
template <>
const Store<ESM::Faction> &ESMStore::get<ESM::Faction>() const {
return mFactions;
}
template <>
const Store<ESM::Global> &ESMStore::get<ESM::Global>() const {
return mGlobals;
}
template <>
const Store<ESM::Ingredient> &ESMStore::get<ESM::Ingredient>() const {
return mIngreds;
}
template <>
const Store<ESM::CreatureLevList> &ESMStore::get<ESM::CreatureLevList>() const {
return mCreatureLists;
}
template <>
const Store<ESM::ItemLevList> &ESMStore::get<ESM::ItemLevList>() const {
return mItemLists;
}
template <>
const Store<ESM::Light> &ESMStore::get<ESM::Light>() const {
return mLights;
}
template <>
const Store<ESM::Tool> &ESMStore::get<ESM::Tool>() const {
return mLockpicks;
}
template <>
const Store<ESM::Miscellaneous> &ESMStore::get<ESM::Miscellaneous>() const {
return mMiscItems;
}
template <>
const Store<ESM::NPC> &ESMStore::get<ESM::NPC>() const {
return mNpcs;
}
template <>
const Store<ESM::LoadNPCC> &ESMStore::get<ESM::LoadNPCC>() const {
return mNpcChange;
}
template <>
const Store<ESM::Probe> &ESMStore::get<ESM::Probe>() const {
return mProbes;
}
template <>
const Store<ESM::Race> &ESMStore::get<ESM::Race>() const {
return mRaces;
}
template <>
const Store<ESM::Region> &ESMStore::get<ESM::Region>() const {
return mRegions;
}
template <>
const Store<ESM::Repair> &ESMStore::get<ESM::Repair>() const {
return mRepairs;
}
template <>
const Store<ESM::SoundGenerator> &ESMStore::get<ESM::SoundGenerator>() const {
return mSoundGens;
}
template <>
const Store<ESM::Sound> &ESMStore::get<ESM::Sound>() const {
return mSounds;
}
template <>
const Store<ESM::Spell> &ESMStore::get<ESM::Spell>() const {
return mSpells;
}
template <>
const Store<ESM::StartScript> &ESMStore::get<ESM::StartScript>() const {
return mStartScripts;
}
template <>
const Store<ESM::Static> &ESMStore::get<ESM::Static>() const {
return mStatics;
}
template <>
const Store<ESM::Weapon> &ESMStore::get<ESM::Weapon>() const {
return mWeapons;
}
template <>
const Store<ESM::GameSetting> &ESMStore::get<ESM::GameSetting>() const {
return mGameSettings;
}
template <>
const Store<ESM::Script> &ESMStore::get<ESM::Script>() const {
return mScripts;
}
template <>
const Store<ESM::Cell> &ESMStore::get<ESM::Cell>() const {
return mCells;
}
template <>
const Store<ESM::Land> &ESMStore::get<ESM::Land>() const {
return mLands;
}
template <>
const Store<ESM::LandTexture> &ESMStore::get<ESM::LandTexture>() const {
return mLandTextures;
}
template <>
const Store<ESM::Pathgrid> &ESMStore::get<ESM::Pathgrid>() const {
return mPathgrids;
}
template <>
const Store<ESM::MagicEffect> &ESMStore::get<ESM::MagicEffect>() const {
return mMagicEffects;
}
template <>
const Store<ESM::Skill> &ESMStore::get<ESM::Skill>() const {
return mSkills;
}
template <>
const Store<ESM::Attribute> &ESMStore::get<ESM::Attribute>() const {
return mAttributes;
}
}
#endif

@ -1,620 +0,0 @@
#ifndef OPENMW_MWWORLD_RECLISTS_H
#define OPENMW_MWWORLD_RECLISTS_H
#include <components/esm/records.hpp>
#include <map>
#include <string>
#include <vector>
#include <algorithm>
#include <cctype>
#include <cassert>
#include <stdexcept>
#include <iterator>
#include <boost/algorithm/string.hpp>
using namespace boost::algorithm;
namespace MWWorld
{
struct RecList
{
virtual ~RecList() {}
virtual void load(ESM::ESMReader &esm, const std::string &id) = 0;
virtual int getSize() = 0;
virtual void listIdentifier (std::vector<std::string>& identifier) const = 0;
static std::string toLower (const std::string& name)
{
std::string lowerCase;
std::transform (name.begin(), name.end(), std::back_inserter (lowerCase),
(int(*)(int)) std::tolower);
return lowerCase;
}
};
typedef std::map<int,RecList*> RecListList;
template <typename X>
struct RecListT : RecList
{
virtual ~RecListT() {}
typedef std::map<std::string,X> MapType;
MapType list;
// Load one object of this type
void load(ESM::ESMReader &esm, const std::string &id)
{
std::string id2 = toLower (id);
list[id2].load(esm);
}
// Find the given object ID, or return NULL if not found.
const X* search(const std::string &id) const
{
std::string id2 = toLower (id);
typename MapType::const_iterator iter = list.find (id2);
if (iter == list.end())
return NULL;
return &iter->second;
}
// Find the given object ID (throws an exception if not found)
const X* find(const std::string &id) const
{
const X *object = search (id);
if (!object)
throw std::runtime_error ("object " + id + " not found");
return object;
}
int getSize() { return list.size(); }
virtual void listIdentifier (std::vector<std::string>& identifier) const
{
for (typename MapType::const_iterator iter (list.begin()); iter!=list.end(); ++iter)
identifier.push_back (iter->first);
}
};
// Same as RecListT, but does not case-smash the IDs
// Note that lookups (search or find) are still case insensitive
template <typename X>
struct RecListCaseT : RecList
{
virtual ~RecListCaseT() {}
typedef std::map<std::string,X> MapType;
MapType list;
// Load one object of this type
void load(ESM::ESMReader &esm, const std::string &id)
{
//std::string id2 = toLower (id);
list[id].load(esm);
}
// Find the given object ID, or return NULL if not found.
const X* search(const std::string &id) const
{
std::string id2 = toLower (id);
for (typename MapType::const_iterator iter = list.begin();
iter != list.end(); ++iter)
{
if (toLower(iter->first) == id2)
return &iter->second;
}
return NULL;
}
// non-const version
X* search(const std::string &id)
{
std::string id2 = toLower (id);
for (typename MapType::iterator iter = list.begin();
iter != list.end(); ++iter)
{
if (toLower(iter->first) == id2)
return &iter->second;
}
return NULL;
}
// Find the given object ID (throws an exception if not found)
const X* find(const std::string &id) const
{
const X *object = search (id);
if (!object)
throw std::runtime_error ("object " + id + " not found");
return object;
}
int getSize() { return list.size(); }
virtual void listIdentifier (std::vector<std::string>& identifier) const
{
for (typename MapType::const_iterator iter (list.begin()); iter!=list.end(); ++iter)
identifier.push_back (iter->first);
}
};
/// Modified version of RecListT for records, that need to store their own ID
template <typename X>
struct RecListWithIDT : RecList
{
virtual ~RecListWithIDT() {}
typedef std::map<std::string,X> MapType;
MapType list;
// Load one object of this type
void load(ESM::ESMReader &esm, const std::string &id)
{
std::string id2 = toLower (id);
list[id2].mId = id2;
list[id2].load(esm);
}
// Find the given object ID, or return NULL if not found.
const X* search(const std::string &id) const
{
std::string id2 = toLower (id);
typename MapType::const_iterator iter = list.find (id2);
if (iter == list.end())
return NULL;
return &iter->second;
}
// Find the given object ID (throws an exception if not found)
const X* find(const std::string &id) const
{
const X *object = search (id);
if (!object)
throw std::runtime_error ("object " + id + " not found");
return object;
}
int getSize() { return list.size(); }
virtual void listIdentifier (std::vector<std::string>& identifier) const
{
for (typename MapType::const_iterator iter (list.begin()); iter!=list.end(); ++iter)
identifier.push_back (iter->first);
}
};
/* Land textures are indexed by an integer number
*/
struct LTexList : RecList
{
virtual ~LTexList() {}
// TODO: For multiple ESM/ESP files we need one list per file.
std::vector<ESM::LandTexture> ltex;
LTexList()
{
// More than enough to hold Morrowind.esm.
ltex.reserve(128);
}
const ESM::LandTexture* search(size_t index) const
{
assert(index < ltex.size());
return &ltex.at(index);
}
int getSize() { return ltex.size(); }
int getSize() const { return ltex.size(); }
virtual void listIdentifier (std::vector<std::string>& identifier) const {}
void load(ESM::ESMReader &esm, const std::string &id)
{
ESM::LandTexture lt;
lt.load(esm);
lt.mId = id;
// Make sure we have room for the structure
if(lt.mIndex + 1 > (int)ltex.size())
ltex.resize(lt.mIndex+1);
// Store it
ltex[lt.mIndex] = lt;
}
};
/* Landscapes are indexed by the X,Y coordinates of the exterior
cell they belong to.
*/
struct LandList : RecList
{
virtual ~LandList()
{
for ( LandMap::iterator itr = lands.begin(); itr != lands.end(); ++itr )
{
delete itr->second;
}
}
// Map containing all landscapes
typedef std::pair<int, int> LandCoord;
typedef std::map<LandCoord, ESM::Land*> LandMap;
LandMap lands;
int count;
LandList() : count(0) {}
int getSize() { return count; }
virtual void listIdentifier (std::vector<std::string>& identifier) const {}
// Find land for the given coordinates. Return null if no mData.
ESM::Land *search(int x, int y) const
{
LandMap::const_iterator itr = lands.find(std::make_pair (x, y));
if ( itr == lands.end() )
{
return NULL;
}
return itr->second;
}
void load(ESM::ESMReader &esm, const std::string &id)
{
count++;
// Create the structure and load it. This actually skips the
// landscape data and remembers the file position for later.
ESM::Land *land = new ESM::Land();
land->load(esm);
// Store the structure
lands[std::make_pair (land->mX, land->mY)] = land;
}
};
struct ciLessBoost : std::binary_function<std::string, std::string, bool>
{
bool operator() (const std::string & s1, const std::string & s2) const {
//case insensitive version of is_less
return lexicographical_compare(s1, s2, is_iless());
}
};
// Cells aren't simply indexed by name. Exterior cells are treated
// separately.
// TODO: case handling (cell names are case-insensitive, but they are also showen to the
// player, so we can't simply smash case.
struct CellList : RecList
{
// Total cell count. Used for statistics.
int count;
CellList() : count(0) {}
int getSize() { return count; }
// List of interior cells. Indexed by cell name.
typedef std::map<std::string,ESM::Cell*, ciLessBoost> IntCells;
IntCells intCells;
// List of exterior cells. Indexed as extCells[mX][mY].
typedef std::map<std::pair<int, int>, ESM::Cell*> ExtCells;
ExtCells extCells;
virtual void listIdentifier (std::vector<std::string>& identifier) const
{
for (IntCells::const_iterator iter (intCells.begin()); iter!=intCells.end(); ++iter)
identifier.push_back (iter->first);
}
virtual ~CellList()
{
for (IntCells::iterator it = intCells.begin(); it!=intCells.end(); ++it)
delete it->second;
for (ExtCells::iterator it = extCells.begin(); it!=extCells.end(); ++it)
delete it->second;
}
const ESM::Cell* searchInt(const std::string &id) const
{
IntCells::const_iterator iter = intCells.find(id);
if (iter!=intCells.end())
return iter->second;
return 0;
}
const ESM::Cell* findInt(const std::string &id) const
{
const ESM::Cell *cell = searchInt (id);
if (!cell)
throw std::runtime_error ("Interior cell not found - " + id);
return cell;
}
const ESM::Cell *searchExt (int x, int y) const
{
ExtCells::const_iterator it = extCells.find (std::make_pair (x, y));
if (it==extCells.end())
return 0;
return it->second;
}
const ESM::Cell *findExt (int x, int y) const
{
const ESM::Cell *cell = searchExt (x, y);
if (!cell)
throw std::runtime_error ("Exterior cell not found");
return cell;
}
const ESM::Cell *searchExtByName (const std::string& id) const
{
for (ExtCells::const_iterator iter = extCells.begin(); iter!=extCells.end(); ++iter)
{
if (toLower (iter->second->mName) == toLower (id))
return iter->second;
}
return 0;
}
const ESM::Cell *searchExtByRegion (const std::string& id) const
{
std::string id2 = toLower (id);
for (ExtCells::const_iterator iter = extCells.begin(); iter!=extCells.end(); ++iter)
if (toLower (iter->second->mRegion)==id)
return iter->second;
return 0;
}
void load(ESM::ESMReader &esm, const std::string &id)
{
count++;
// All cells have a name record, even nameless exterior cells.
ESM::Cell *cell = new ESM::Cell;
cell->mName = id;
// The cell itself takes care of all the hairy details
cell->load(esm);
if(cell->mData.mFlags & ESM::Cell::Interior)
{
// Store interior cell by name
intCells[id] = cell;
}
else
{
// Store exterior cells by grid position
extCells[std::make_pair (cell->mData.mX, cell->mData.mY)] = cell;
}
}
};
struct PathgridList : RecList
{
int count;
// List of grids for interior cells. Indexed by cell name.
typedef std::map<std::string,ESM::Pathgrid*, ciLessBoost> IntGrids;
IntGrids intGrids;
// List of grids for exterior cells. Indexed as extCells[mX][mY].
typedef std::map<std::pair<int, int>, ESM::Pathgrid*> ExtGrids;
ExtGrids extGrids;
PathgridList() : count(0) {}
virtual ~PathgridList()
{
for (IntGrids::iterator it = intGrids.begin(); it!=intGrids.end(); ++it)
delete it->second;
for (ExtGrids::iterator it = extGrids.begin(); it!=extGrids.end(); ++it)
delete it->second;
}
int getSize() { return count; }
virtual void listIdentifier (std::vector<std::string>& identifier) const
{
// do nothing
}
void load(ESM::ESMReader &esm, const std::string &id)
{
count++;
ESM::Pathgrid *grid = new ESM::Pathgrid;
grid->load(esm);
if (grid->mData.mX == 0 && grid->mData.mY == 0)
{
intGrids[grid->mCell] = grid;
}
else
{
extGrids[std::make_pair(grid->mData.mX, grid->mData.mY)] = grid;
}
}
ESM::Pathgrid *find(int cellX, int cellY, const std::string &cellName) const
{
ESM::Pathgrid *result = search(cellX, cellY, cellName);
if (!result)
{
throw std::runtime_error("no pathgrid found for cell " + cellName);
}
return result;
}
ESM::Pathgrid *search(int cellX, int cellY, const std::string &cellName) const
{
ESM::Pathgrid *result = NULL;
if (cellX == 0 && cellY == 0) // possibly interior
{
IntGrids::const_iterator it = intGrids.find(cellName);
if (it != intGrids.end())
result = it->second;
}
else
{
ExtGrids::const_iterator it = extGrids.find(std::make_pair(cellX, cellY));
if (it != extGrids.end())
result = it->second;
}
return result;
}
ESM::Pathgrid *search(const ESM::Cell &cell) const
{
int cellX, cellY;
if (cell.mData.mFlags & ESM::Cell::Interior)
{
cellX = cellY = 0;
}
else
{
cellX = cell.mData.mX;
cellY = cell.mData.mY;
}
return search(cellX, cellY, cell.mName);
}
};
template <typename X>
struct ScriptListT : RecList
{
virtual ~ScriptListT() {}
typedef std::map<std::string,X> MapType;
MapType list;
// Load one object of this type
void load(ESM::ESMReader &esm, const std::string &id)
{
X ref;
ref.load (esm);
std::string realId = toLower (ref.mId);
std::swap (list[realId], ref);
}
// Find the given object ID, or return NULL if not found.
const X* search(const std::string &id) const
{
std::string id2 = toLower (id);
typename MapType::const_iterator iter = list.find (id2);
if (iter == list.end())
return NULL;
return &iter->second;
}
// Find the given object ID (throws an exception if not found)
const X* find(const std::string &id) const
{
const X *object = search (id);
if (!object)
throw std::runtime_error ("object " + id + " not found");
return object;
}
int getSize() { return list.size(); }
virtual void listIdentifier (std::vector<std::string>& identifier) const
{
for (typename MapType::const_iterator iter (list.begin()); iter!=list.end(); ++iter)
identifier.push_back (iter->first);
}
};
template <typename X>
struct IndexListT
{
virtual ~IndexListT() {}
typedef std::map<int, X> MapType;
MapType list;
void load(ESM::ESMReader &esm)
{
X ref;
ref.load (esm);
int index = ref.mIndex;
list[index] = ref;
}
int getSize()
{
return list.size();
}
virtual void listIdentifier (std::vector<std::string>& identifier) const {}
// Find the given object ID, or return NULL if not found.
const X* search (int id) const
{
typename MapType::const_iterator iter = list.find (id);
if (iter == list.end())
return NULL;
return &iter->second;
}
// Find the given object ID (throws an exception if not found)
const X* find (int id) const
{
const X *object = search (id);
if (!object)
{
std::ostringstream error;
error << "object " << id << " not found";
throw std::runtime_error (error.str());
}
return object;
}
};
}
#endif

@ -1,100 +0,0 @@
#include "esmstore.hpp"
#include <set>
#include <iostream>
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<std::string> 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<int, StoreBase *>::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<ESM::Dialogue *>(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<string>::iterator it = missing.begin();
it != missing.end(); it++ )
cout << *it << " ";
cout << endl;
*/
}
void ESMStore::setUp()
{
std::map<int, StoreBase *>::iterator it = mStores.begin();
for (; it != mStores.end(); ++it) {
it->second->setUp();
}
mSkills.setUp();
mMagicEffects.setUp();
mAttributes.setUp();
}
} // end namespace

@ -1,362 +0,0 @@
#ifndef OPENMW_MWWORLD_ESMSTORE_H
#define OPENMW_MWWORLD_ESMSTORE_H
#include <stdexcept>
#include <components/esm/records.hpp>
#include "store.hpp"
namespace MWWorld
{
class ESMStore
{
Store<ESM::Activator> mActivators;
Store<ESM::Potion> mPotions;
Store<ESM::Apparatus> mAppas;
Store<ESM::Armor> mArmors;
Store<ESM::BodyPart> mBodyParts;
Store<ESM::Book> mBooks;
Store<ESM::BirthSign> mBirthSigns;
Store<ESM::Class> mClasses;
Store<ESM::Clothing> mClothes;
Store<ESM::LoadCNTC> mContChange;
Store<ESM::Container> mContainers;
Store<ESM::Creature> mCreatures;
Store<ESM::LoadCREC> mCreaChange;
Store<ESM::Dialogue> mDialogs;
Store<ESM::Door> mDoors;
Store<ESM::Enchantment> mEnchants;
Store<ESM::Faction> mFactions;
Store<ESM::Global> mGlobals;
Store<ESM::Ingredient> mIngreds;
Store<ESM::CreatureLevList> mCreatureLists;
Store<ESM::ItemLevList> mItemLists;
Store<ESM::Light> mLights;
Store<ESM::Tool> mLockpicks;
Store<ESM::Miscellaneous> mMiscItems;
Store<ESM::NPC> mNpcs;
Store<ESM::LoadNPCC> mNpcChange;
Store<ESM::Probe> mProbes;
Store<ESM::Race> mRaces;
Store<ESM::Region> mRegions;
Store<ESM::Repair> mRepairs;
Store<ESM::SoundGenerator> mSoundGens;
Store<ESM::Sound> mSounds;
Store<ESM::Spell> mSpells;
Store<ESM::StartScript> mStartScripts;
Store<ESM::Static> mStatics;
Store<ESM::Weapon> mWeapons;
Store<ESM::GameSetting> mGameSettings;
Store<ESM::Script> mScripts;
// Lists that need special rules
Store<ESM::Cell> mCells;
Store<ESM::Land> mLands;
Store<ESM::LandTexture> mLandTextures;
Store<ESM::Pathgrid> mPathgrids;
Store<ESM::MagicEffect> mMagicEffects;
Store<ESM::Skill> mSkills;
// Special entry which is hardcoded and not loaded from an ESM
Store<ESM::Attribute> mAttributes;
// Lookup of all IDs. Makes looking up references faster. Just
// maps the id name to the record type.
std::map<std::string, int> mIds;
std::map<int, StoreBase *> mStores;
public:
// Look up the given ID in 'all'. Returns 0 if not found.
int find(const std::string &id) const
{
std::map<std::string, int>::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 <class T>
const Store<T> &get() const {
throw std::runtime_error("Storage for this type not exist");
}
};
template <>
const Store<ESM::Activator> &ESMStore::get<ESM::Activator>() const {
return mActivators;
}
template <>
const Store<ESM::Potion> &ESMStore::get<ESM::Potion>() const {
return mPotions;
}
template <>
const Store<ESM::Apparatus> &ESMStore::get<ESM::Apparatus>() const {
return mAppas;
}
template <>
const Store<ESM::Armor> &ESMStore::get<ESM::Armor>() const {
return mArmors;
}
template <>
const Store<ESM::BodyPart> &ESMStore::get<ESM::BodyPart>() const {
return mBodyParts;
}
template <>
const Store<ESM::Book> &ESMStore::get<ESM::Book>() const {
return mBooks;
}
template <>
const Store<ESM::BirthSign> &ESMStore::get<ESM::BirthSign>() const {
return mBirthSigns;
}
template <>
const Store<ESM::Class> &ESMStore::get<ESM::Class>() const {
return mClasses;
}
template <>
const Store<ESM::Clothing> &ESMStore::get<ESM::Clothing>() const {
return mClothes;
}
template <>
const Store<ESM::LoadCNTC> &ESMStore::get<ESM::LoadCNTC>() const {
return mContChange;
}
template <>
const Store<ESM::Container> &ESMStore::get<ESM::Container>() const {
return mContainers;
}
template <>
const Store<ESM::Creature> &ESMStore::get<ESM::Creature>() const {
return mCreatures;
}
template <>
const Store<ESM::LoadCREC> &ESMStore::get<ESM::LoadCREC>() const {
return mCreaChange;
}
template <>
const Store<ESM::Dialogue> &ESMStore::get<ESM::Dialogue>() const {
return mDialogs;
}
template <>
const Store<ESM::Door> &ESMStore::get<ESM::Door>() const {
return mDoors;
}
template <>
const Store<ESM::Enchantment> &ESMStore::get<ESM::Enchantment>() const {
return mEnchants;
}
template <>
const Store<ESM::Faction> &ESMStore::get<ESM::Faction>() const {
return mFactions;
}
template <>
const Store<ESM::Global> &ESMStore::get<ESM::Global>() const {
return mGlobals;
}
template <>
const Store<ESM::Ingredient> &ESMStore::get<ESM::Ingredient>() const {
return mIngreds;
}
template <>
const Store<ESM::CreatureLevList> &ESMStore::get<ESM::CreatureLevList>() const {
return mCreatureLists;
}
template <>
const Store<ESM::ItemLevList> &ESMStore::get<ESM::ItemLevList>() const {
return mItemLists;
}
template <>
const Store<ESM::Light> &ESMStore::get<ESM::Light>() const {
return mLights;
}
template <>
const Store<ESM::Tool> &ESMStore::get<ESM::Tool>() const {
return mLockpicks;
}
template <>
const Store<ESM::Miscellaneous> &ESMStore::get<ESM::Miscellaneous>() const {
return mMiscItems;
}
template <>
const Store<ESM::NPC> &ESMStore::get<ESM::NPC>() const {
return mNpcs;
}
template <>
const Store<ESM::LoadNPCC> &ESMStore::get<ESM::LoadNPCC>() const {
return mNpcChange;
}
template <>
const Store<ESM::Probe> &ESMStore::get<ESM::Probe>() const {
return mProbes;
}
template <>
const Store<ESM::Race> &ESMStore::get<ESM::Race>() const {
return mRaces;
}
template <>
const Store<ESM::Region> &ESMStore::get<ESM::Region>() const {
return mRegions;
}
template <>
const Store<ESM::Repair> &ESMStore::get<ESM::Repair>() const {
return mRepairs;
}
template <>
const Store<ESM::SoundGenerator> &ESMStore::get<ESM::SoundGenerator>() const {
return mSoundGens;
}
template <>
const Store<ESM::Sound> &ESMStore::get<ESM::Sound>() const {
return mSounds;
}
template <>
const Store<ESM::Spell> &ESMStore::get<ESM::Spell>() const {
return mSpells;
}
template <>
const Store<ESM::StartScript> &ESMStore::get<ESM::StartScript>() const {
return mStartScripts;
}
template <>
const Store<ESM::Static> &ESMStore::get<ESM::Static>() const {
return mStatics;
}
template <>
const Store<ESM::Weapon> &ESMStore::get<ESM::Weapon>() const {
return mWeapons;
}
template <>
const Store<ESM::GameSetting> &ESMStore::get<ESM::GameSetting>() const {
return mGameSettings;
}
template <>
const Store<ESM::Script> &ESMStore::get<ESM::Script>() const {
return mScripts;
}
template <>
const Store<ESM::Cell> &ESMStore::get<ESM::Cell>() const {
return mCells;
}
template <>
const Store<ESM::Land> &ESMStore::get<ESM::Land>() const {
return mLands;
}
template <>
const Store<ESM::LandTexture> &ESMStore::get<ESM::LandTexture>() const {
return mLandTextures;
}
template <>
const Store<ESM::Pathgrid> &ESMStore::get<ESM::Pathgrid>() const {
return mPathgrids;
}
template <>
const Store<ESM::MagicEffect> &ESMStore::get<ESM::MagicEffect>() const {
return mMagicEffects;
}
template <>
const Store<ESM::Skill> &ESMStore::get<ESM::Skill>() const {
return mSkills;
}
template <>
const Store<ESM::Attribute> &ESMStore::get<ESM::Attribute>() const {
return mAttributes;
}
}
#endif
Loading…
Cancel
Save