#include "cellstore.hpp" #include #include #include "../mwbase/environment.hpp" #include "../mwbase/world.hpp" #include "ptr.hpp" #include "manualref.hpp" #include "class.hpp" namespace MWWorld { CellStore::CellStore (const ESM::Cell *cell_) : cell (cell_), mState (State_Unloaded) { mWaterLevel = cell->water; } void CellStore::load (const ESMS::ESMStore &store, ESM::ESMReader &esm) { if (mState!=State_Loaded) { if (mState==State_Preloaded) mIds.clear(); std::cout << "loading cell " << cell->getDescription() << std::endl; loadRefs (store, esm); mState = State_Loaded; } } void CellStore::preload (const ESMS::ESMStore &store, ESM::ESMReader &esm) { if (mState==State_Unloaded) { listRefs (store, esm); mState = State_Preloaded; } } void CellStore::listRefs(const ESMS::ESMStore &store, ESM::ESMReader &esm) { assert (cell); if (cell->context.filename.empty()) return; // this is a dynamically generated cell -> skipping. // Reopen the ESM reader and seek to the right position. cell->restore (esm); ESM::CellRef ref; // Get each reference in turn while (cell->getNextRef (esm, ref)) { std::string lowerCase; std::transform (ref.refID.begin(), ref.refID.end(), std::back_inserter (lowerCase), (int(*)(int)) std::tolower); mIds.push_back (lowerCase); } std::sort (mIds.begin(), mIds.end()); } void CellStore::loadRefs(const ESMS::ESMStore &store, ESM::ESMReader &esm) { assert (cell); if (cell->context.filename.empty()) return; // this is a dynamically generated cell -> skipping. // Reopen the ESM reader and seek to the right position. cell->restore(esm); ESM::CellRef ref; // Get each reference in turn while(cell->getNextRef(esm, ref)) { std::string lowerCase; std::transform (ref.refID.begin(), ref.refID.end(), std::back_inserter (lowerCase), (int(*)(int)) std::tolower); int rec = store.find(ref.refID); ref.refID = lowerCase; /* We can optimize this further by storing the pointer to the record itself in store.all, so that we don't need to look it up again here. However, never optimize. There are infinite opportunities to do that later. */ switch(rec) { case ESM::REC_ACTI: activators.find(ref, store.activators); break; case ESM::REC_ALCH: potions.find(ref, store.potions); break; case ESM::REC_APPA: appas.find(ref, store.appas); break; case ESM::REC_ARMO: armors.find(ref, store.armors); break; case ESM::REC_BOOK: books.find(ref, store.books); break; case ESM::REC_CLOT: clothes.find(ref, store.clothes); break; case ESM::REC_CONT: containers.find(ref, store.containers); break; case ESM::REC_CREA: creatures.find(ref, store.creatures); break; case ESM::REC_DOOR: doors.find(ref, store.doors); break; case ESM::REC_INGR: ingreds.find(ref, store.ingreds); break; case ESM::REC_LEVC: creatureLists.find(ref, store.creatureLists); break; case ESM::REC_LEVI: itemLists.find(ref, store.itemLists); break; case ESM::REC_LIGH: lights.find(ref, store.lights); break; case ESM::REC_LOCK: lockpicks.find(ref, store.lockpicks); break; case ESM::REC_MISC: miscItems.find(ref, store.miscItems); break; case ESM::REC_NPC_: npcs.find(ref, store.npcs); break; case ESM::REC_PROB: probes.find(ref, store.probes); break; case ESM::REC_REPA: repairs.find(ref, store.repairs); break; case ESM::REC_STAT: statics.find(ref, store.statics); break; case ESM::REC_WEAP: weapons.find(ref, store.weapons); break; case 0: std::cout << "Cell reference " + ref.refID + " not found!\n"; break; default: std::cout << "WARNING: Ignoring reference '" << ref.refID << "' of unhandled type\n"; } } } /// \todo this whole code needs major clean up const MWWorld::Ptr CellStore::insertObject (const Ptr& ptr, const ESM::Position &pos) { std::string type = ptr.getTypeName(); MWWorld::Ptr newPtr; // insert into the correct CellRefList if (type == typeid(ESM::Potion).name()) { MWWorld::LiveCellRef* ref = ptr.get(); newPtr = MWWorld::Ptr(&potions.insert(*ref), this); } else if (type == typeid(ESM::Apparatus).name()) { MWWorld::LiveCellRef* ref = ptr.get(); newPtr = MWWorld::Ptr(&appas.insert(*ref), this); } else if (type == typeid(ESM::Armor).name()) { MWWorld::LiveCellRef* ref = ptr.get(); newPtr = MWWorld::Ptr(&armors.insert(*ref), this); } else if (type == typeid(ESM::Book).name()) { MWWorld::LiveCellRef* ref = ptr.get(); newPtr = MWWorld::Ptr(&books.insert(*ref), this); } else if (type == typeid(ESM::Clothing).name()) { MWWorld::LiveCellRef* ref = ptr.get(); newPtr = MWWorld::Ptr(&clothes.insert(*ref), this); } else if (type == typeid(ESM::Ingredient).name()) { MWWorld::LiveCellRef* ref = ptr.get(); newPtr = MWWorld::Ptr(&ingreds.insert(*ref), this); } else if (type == typeid(ESM::Light).name()) { MWWorld::LiveCellRef* ref = ptr.get(); newPtr = MWWorld::Ptr(&lights.insert(*ref), this); } else if (type == typeid(ESM::Tool).name()) { MWWorld::LiveCellRef* ref = ptr.get(); newPtr = MWWorld::Ptr(&lockpicks.insert(*ref), this); } else if (type == typeid(ESM::Repair).name()) { MWWorld::LiveCellRef* ref = ptr.get(); newPtr = MWWorld::Ptr(&repairs.insert(*ref), this); } else if (type == typeid(ESM::Probe).name()) { MWWorld::LiveCellRef* ref = ptr.get(); newPtr = MWWorld::Ptr(&probes.insert(*ref), this); } else if (type == typeid(ESM::Weapon).name()) { MWWorld::LiveCellRef* ref = ptr.get(); newPtr = MWWorld::Ptr(&weapons.insert(*ref), this); } else if (type == typeid(ESM::Miscellaneous).name()) { // if this is gold, we need to fetch the correct mesh depending on the amount of gold. if (MWWorld::Class::get(ptr).getName(ptr) == MWBase::Environment::get().getWorld()->getStore().gameSettings.search("sGold")->str) { int goldAmount = ptr.getRefData().getCount(); std::string base = "Gold_001"; if (goldAmount >= 100) base = "Gold_100"; else if (goldAmount >= 25) base = "Gold_025"; else if (goldAmount >= 10) base = "Gold_010"; else if (goldAmount >= 5) base = "Gold_005"; MWWorld::ManualRef newRef( MWBase::Environment::get().getWorld()->getStore(), base); MWWorld::LiveCellRef* ref = newRef.getPtr().get(); newPtr = MWWorld::Ptr(&miscItems.insert(*ref), this); /* ESM::Position& p = newPtr.getRefData().getPosition(); p.pos[0] = ptr.getRefData().getPosition().pos[0]; p.pos[1] = ptr.getRefData().getPosition().pos[1]; p.pos[2] = ptr.getRefData().getPosition().pos[2]; */ } else { MWWorld::LiveCellRef* ref = ptr.get(); newPtr = MWWorld::Ptr(&miscItems.insert(*ref), this); } } else throw std::runtime_error("Trying to insert object of unhandled type"); newPtr.getRefData().getPosition() = pos; newPtr.getRefData().setCount(ptr.getRefData().getCount()); ptr.getRefData().setCount(0); newPtr.getRefData().enable(); return newPtr; } }