void MWState::StateManager::loadGame(const std::string& filepath) { for (CharacterIterator it = mCharacterManager.begin(); it != mCharacterManager.end(); ++it) { const MWState::Character& character = *it; for (MWState::Character::SlotIterator slotIt = character.begin(); slotIt != character.end(); ++slotIt) { const MWState::Slot& slot = *slotIt; if (slot.mPath == boost::filesystem::path(filepath)) { loadGame(&character, slot.mPath.string()); return; } } } // have to peek into the save file to get the player name ESM::ESMReader reader; reader.open (filepath); if (reader.getRecName()!=ESM::REC_SAVE) return; // invalid save file -> ignore reader.getRecHeader(); ESM::SavedGame profile; profile.load (reader); reader.close(); MWState::Character* character = mCharacterManager.getCurrentCharacter(true, profile.mPlayerName); loadGame(character, filepath); mTimePlayed = profile.mTimePlayed; }
void DataFilesModel::addMasters(const QString &path) { QDir dir(path); dir.setNameFilters(QStringList(QLatin1String("*.esp"))); // Read the dependencies from the plugins foreach (const QString &path, dir.entryList()) { try { ESM::ESMReader fileReader; fileReader.setEncoding(mEncoding.toStdString()); fileReader.open(dir.absoluteFilePath(path).toStdString()); ESM::ESMReader::MasterList mlist = fileReader.getMasters(); for (unsigned int i = 0; i < mlist.size(); ++i) { QString master = QString::fromStdString(mlist[i].name); // Add the plugin to the internal dependency map mDependencies[master].append(path); // Don't add esps if (master.endsWith(".esp", Qt::CaseInsensitive)) continue; QFileInfo info(dir.absoluteFilePath(master)); EsmFile *file = new EsmFile(master); file->setDates(info.lastModified(), info.lastRead()); // Add the master to the table if (findItem(master) == 0) addFile(file); } } catch(std::runtime_error &e) { // An error occurred while reading the .esp qWarning() << "Error reading esp: " << e.what(); continue; } } // See if the masters actually exist in the filesystem dir.setNameFilters(QStringList(QLatin1String("*.esm"))); foreach (const QString &path, dir.entryList()) { QFileInfo info(dir.absoluteFilePath(path)); if (findItem(path) == 0) { EsmFile *file = new EsmFile(path); file->setDates(info.lastModified(), info.lastRead()); addFile(file); } // Make the master selectable mAvailableFiles.append(path); } }
QSet<QString> CellNameLoader::getCellNames(QStringList &contentPaths) { QSet<QString> cellNames; ESM::ESMReader esmReader; // Loop through all content files for (auto &contentPath : contentPaths) { esmReader.open(contentPath.toStdString()); // Loop through all records while(esmReader.hasMoreRecs()) { ESM::NAME recordName = esmReader.getRecName(); esmReader.getRecHeader(); if (isCellRecord(recordName)) { QString cellName = getCellName(esmReader); if (!cellName.isEmpty()) { cellNames.insert(cellName); } } // Stop loading content for this record and continue to the next esmReader.skipRecord(); } } return cellNames; }
void DataFilesModel::addPlugins(const QString &path) { QDir dir(path); dir.setNameFilters(QStringList(QLatin1String("*.esp"))); foreach (const QString &path, dir.entryList()) { QFileInfo info(dir.absoluteFilePath(path)); EsmFile *file = new EsmFile(path); try { ESM::ESMReader fileReader; ToUTF8::Utf8Encoder encoder (ToUTF8::calculateEncoding(mEncoding.toStdString())); fileReader.setEncoder(&encoder); fileReader.open(dir.absoluteFilePath(path).toStdString()); ESM::ESMReader::MasterList mlist = fileReader.getMasters(); QStringList masters; for (unsigned int i = 0; i < mlist.size(); ++i) { QString master = QString::fromStdString(mlist[i].name); masters.append(master); // Add the plugin to the internal dependency map mDependencies[master].append(path); } file->setAuthor(QString::fromStdString(fileReader.getAuthor())); file->setSize(info.size()); file->setDates(info.lastModified(), info.lastRead()); file->setVersion(fileReader.getFVer()); file->setPath(info.absoluteFilePath()); file->setMasters(masters); file->setDescription(QString::fromStdString(fileReader.getDesc())); // Put the file in the table addFile(file); } catch(std::runtime_error &e) { // An error occurred while reading the .esp qWarning() << "Error reading esp: " << e.what(); continue; } } }
void MWState::Character::addSlot (const boost::filesystem::path& path, const std::string& game) { Slot slot; slot.mPath = path; slot.mTimeStamp = boost::filesystem::last_write_time (path); ESM::ESMReader reader; reader.open (slot.mPath.string()); if (reader.getRecName()!=ESM::REC_SAVE) return; // invalid save file -> ignore reader.getRecHeader(); slot.mProfile.load (reader); if (Misc::StringUtils::lowerCase (slot.mProfile.mContentFiles.at (0))!= Misc::StringUtils::lowerCase (game)) return; // this file is for a different game -> ignore mSlots.push_back (slot); }
void CSMWorld::Data::loadFile (const boost::filesystem::path& path, bool base) { ESM::ESMReader reader; /// \todo set encoding properly, once config implementation has been fixed. ToUTF8::Utf8Encoder encoder (ToUTF8::calculateEncoding ("win1252")); reader.setEncoder (&encoder); reader.open (path.string()); // Note: We do not need to send update signals here, because at this point the model is not connected // to any view. while (reader.hasMoreRecs()) { ESM::NAME n = reader.getRecName(); reader.getRecHeader(); switch (n.val) { case ESM::REC_GLOB: mGlobals.load (reader, base); break; case ESM::REC_GMST: mGmsts.load (reader, base); break; case ESM::REC_SKIL: mSkills.load (reader, base); break; case ESM::REC_CLAS: mClasses.load (reader, base); break; case ESM::REC_FACT: mFactions.load (reader, base); break; case ESM::REC_RACE: mRaces.load (reader, base); break; case ESM::REC_SOUN: mSounds.load (reader, base); break; case ESM::REC_SCPT: mScripts.load (reader, base); break; case ESM::REC_REGN: mRegions.load (reader, base); break; case ESM::REC_BSGN: mBirthsigns.load (reader, base); break; case ESM::REC_SPEL: mSpells.load (reader, base); break; case ESM::REC_CELL: mCells.load (reader, base); break; default: /// \todo throw an exception instead, once all records are implemented reader.skipRecord(); } } }
void CSMTools::FinishMergedDocumentStage::perform (int stage, CSMDoc::Messages& messages) { // We know that the content file list contains at least two entries and that the first one // does exist on disc (otherwise it would have been impossible to initiate a merge on that // document). boost::filesystem::path path = mState.mSource.getContentFiles()[0]; ESM::ESMReader reader; reader.setEncoder (&mEncoder); reader.open (path.string()); CSMWorld::MetaData source; source.mId = "sys::meta"; source.load (reader); CSMWorld::MetaData target = mState.mTarget->getData().getMetaData(); target.mAuthor = source.mAuthor; target.mDescription = source.mDescription; mState.mTarget->getData().setMetaData (target); mState.mCompleted = true; }
void CSMWorld::Data::loadFile (const boost::filesystem::path& path, bool base) { ESM::ESMReader reader; /// \todo set encoding properly, once config implementation has been fixed. ToUTF8::Utf8Encoder encoder (ToUTF8::calculateEncoding ("win1252")); reader.setEncoder (&encoder); reader.open (path.string()); // Note: We do not need to send update signals here, because at this point the model is not connected // to any view. while (reader.hasMoreRecs()) { ESM::NAME n = reader.getRecName(); reader.getRecHeader(); switch (n.val) { case ESM::REC_GLOB: mGlobals.load (reader, base); break; case ESM::REC_GMST: mGmsts.load (reader, base); break; case ESM::REC_SKIL: mSkills.load (reader, base); break; case ESM::REC_CLAS: mClasses.load (reader, base); break; case ESM::REC_FACT: mFactions.load (reader, base); break; case ESM::REC_RACE: mRaces.load (reader, base); break; case ESM::REC_SOUN: mSounds.load (reader, base); break; case ESM::REC_SCPT: mScripts.load (reader, base); break; case ESM::REC_REGN: mRegions.load (reader, base); break; case ESM::REC_BSGN: mBirthsigns.load (reader, base); break; case ESM::REC_SPEL: mSpells.load (reader, base); break; case ESM::REC_CELL: mCells.load (reader, base); mRefs.load (reader, mCells.getSize()-1, base); break; case ESM::REC_ACTI: mReferenceables.load (reader, base, UniversalId::Type_Activator); break; case ESM::REC_ALCH: mReferenceables.load (reader, base, UniversalId::Type_Potion); break; case ESM::REC_APPA: mReferenceables.load (reader, base, UniversalId::Type_Apparatus); break; case ESM::REC_ARMO: mReferenceables.load (reader, base, UniversalId::Type_Armor); break; case ESM::REC_BOOK: mReferenceables.load (reader, base, UniversalId::Type_Book); break; case ESM::REC_CLOT: mReferenceables.load (reader, base, UniversalId::Type_Clothing); break; case ESM::REC_CONT: mReferenceables.load (reader, base, UniversalId::Type_Container); break; case ESM::REC_CREA: mReferenceables.load (reader, base, UniversalId::Type_Creature); break; case ESM::REC_DOOR: mReferenceables.load (reader, base, UniversalId::Type_Door); break; case ESM::REC_INGR: mReferenceables.load (reader, base, UniversalId::Type_Ingredient); break; case ESM::REC_LEVC: mReferenceables.load (reader, base, UniversalId::Type_CreatureLevelledList); break; case ESM::REC_LEVI: mReferenceables.load (reader, base, UniversalId::Type_ItemLevelledList); break; case ESM::REC_LIGH: mReferenceables.load (reader, base, UniversalId::Type_Light); break; case ESM::REC_LOCK: mReferenceables.load (reader, base, UniversalId::Type_Lockpick); break; case ESM::REC_MISC: mReferenceables.load (reader, base, UniversalId::Type_Miscellaneous); break; case ESM::REC_NPC_: mReferenceables.load (reader, base, UniversalId::Type_Npc); break; case ESM::REC_PROB: mReferenceables.load (reader, base, UniversalId::Type_Probe); break; case ESM::REC_REPA: mReferenceables.load (reader, base, UniversalId::Type_Repair); break; case ESM::REC_STAT: mReferenceables.load (reader, base, UniversalId::Type_Static); break; case ESM::REC_WEAP: mReferenceables.load (reader, base, UniversalId::Type_Weapon); break; default: /// \todo throw an exception instead, once all records are implemented reader.skipRecord(); } } }
void MWState::StateManager::loadGame (const Character *character, const Slot *slot) { try { cleanup(); mTimePlayed = slot->mProfile.mTimePlayed; ESM::ESMReader reader; reader.open (slot->mPath.string()); std::map<int, int> contentFileMap = buildContentFileIndexMap (reader); Loading::Listener& listener = *MWBase::Environment::get().getWindowManager()->getLoadingScreen(); listener.setProgressRange(reader.getRecordCount()); listener.setLabel("#{sLoadingMessage14}"); Loading::ScopedLoad load(&listener); while (reader.hasMoreRecs()) { ESM::NAME n = reader.getRecName(); reader.getRecHeader(); switch (n.val) { case ESM::REC_SAVE: // don't need to read that here reader.skipRecord(); break; case ESM::REC_JOUR: case ESM::REC_QUES: MWBase::Environment::get().getJournal()->readRecord (reader, n.val); break; case ESM::REC_DIAS: MWBase::Environment::get().getDialogueManager()->readRecord (reader, n.val); break; case ESM::REC_ALCH: case ESM::REC_ARMO: case ESM::REC_BOOK: case ESM::REC_CLAS: case ESM::REC_CLOT: case ESM::REC_ENCH: case ESM::REC_NPC_: case ESM::REC_SPEL: case ESM::REC_WEAP: case ESM::REC_GLOB: case ESM::REC_PLAY: case ESM::REC_CSTA: case ESM::REC_WTHR: case ESM::REC_DYNA: case ESM::REC_ACTC: case ESM::REC_PROJ: case ESM::REC_MPRJ: MWBase::Environment::get().getWorld()->readRecord (reader, n.val, contentFileMap); break; case ESM::REC_GSCR: MWBase::Environment::get().getScriptManager()->getGlobalScripts().readRecord (reader, n.val); break; case ESM::REC_GMAP: case ESM::REC_KEYS: case ESM::REC_ASPL: MWBase::Environment::get().getWindowManager()->readRecord(reader, n.val); break; default: // ignore invalid records /// \todo log error reader.skipRecord(); } listener.increaseProgress(); } mCharacterManager.setCurrentCharacter(character); mState = State_Running; Settings::Manager::setString ("character", "Saves", slot->mPath.parent_path().filename().string()); MWBase::Environment::get().getWindowManager()->setNewGame(false); MWBase::Environment::get().getWorld()->setupPlayer(); MWBase::Environment::get().getWorld()->renderPlayer(); MWBase::Environment::get().getWindowManager()->updatePlayer(); MWBase::Environment::get().getMechanicsManager()->playerLoaded(); MWWorld::Ptr ptr = MWBase::Environment::get().getWorld()->getPlayerPtr(); ESM::CellId cellId = ptr.getCell()->getCell()->getCellId(); // Use detectWorldSpaceChange=false, otherwise some of the data we just loaded would be cleared again MWBase::Environment::get().getWorld()->changeToCell (cellId, ptr.getRefData().getPosition(), false); // Do not trigger erroneous cellChanged events MWBase::Environment::get().getWorld()->markCellAsUnchanged(); } catch (const std::exception& e) { std::stringstream error; error << "Failed to load saved game: " << e.what(); std::cerr << error.str() << std::endl; cleanup (true); MWBase::Environment::get().getWindowManager()->pushGuiMode (MWGui::GM_MainMenu); std::vector<std::string> buttons; buttons.push_back("#{sOk}"); MWBase::Environment::get().getWindowManager()->messageBox(error.str(), buttons); } }
void DataFilesModel::addFiles(const QString &path) { QDir dir(path); QStringList filters; filters << "*.esp" << "*.esm"; dir.setNameFilters(filters); // Create a decoder for non-latin characters in esx metadata QTextCodec *codec; if (mEncoding == QLatin1String("win1252")) { codec = QTextCodec::codecForName("windows-1252"); } else if (mEncoding == QLatin1String("win1251")) { codec = QTextCodec::codecForName("windows-1251"); } else if (mEncoding == QLatin1String("win1250")) { codec = QTextCodec::codecForName("windows-1250"); } else { return; // This should never happen; } QTextDecoder *decoder = codec->makeDecoder(); foreach (const QString &path, dir.entryList()) { QFileInfo info(dir.absoluteFilePath(path)); EsmFile *file = new EsmFile(path); try { ESM::ESMReader fileReader; ToUTF8::Utf8Encoder encoder(ToUTF8::calculateEncoding(mEncoding.toStdString())); fileReader.setEncoder(&encoder); fileReader.open(dir.absoluteFilePath(path).toStdString()); std::vector<ESM::Header::MasterData> mlist = fileReader.getMasters(); QStringList masters; for (unsigned int i = 0; i < mlist.size(); ++i) { QString master = QString::fromStdString(mlist[i].name); masters.append(master); } file->setAuthor(decoder->toUnicode(fileReader.getAuthor().c_str())); file->setSize(info.size()); file->setDates(info.lastModified(), info.lastRead()); file->setVersion(fileReader.getFVer()); file->setPath(info.absoluteFilePath()); file->setMasters(masters); file->setDescription(decoder->toUnicode(fileReader.getDesc().c_str())); // Put the file in the table if (findItem(path) == 0) addFile(file); } catch(std::runtime_error &e) { // An error occurred while reading the .esp qWarning() << "Error reading esp: " << e.what(); continue; } } delete decoder; }
void MWState::StateManager::loadGame (const Character *character, const std::string& filepath) { try { cleanup(); ESM::ESMReader reader; reader.open (filepath); if (reader.getFormat() > ESM::SavedGame::sCurrentFormat) throw std::runtime_error("This save file was created using a newer version of OpenMW and is thus not supported. Please upgrade to the newest OpenMW version to load this file."); std::map<int, int> contentFileMap = buildContentFileIndexMap (reader); Loading::Listener& listener = *MWBase::Environment::get().getWindowManager()->getLoadingScreen(); listener.setProgressRange(100); listener.setLabel("#{sLoadingMessage14}"); Loading::ScopedLoad load(&listener); bool firstPersonCam = false; size_t total = reader.getFileSize(); int currentPercent = 0; while (reader.hasMoreRecs()) { ESM::NAME n = reader.getRecName(); reader.getRecHeader(); switch (n.val) { case ESM::REC_SAVE: { ESM::SavedGame profile; profile.load(reader); if (!verifyProfile(profile)) { cleanup (true); MWBase::Environment::get().getWindowManager()->pushGuiMode (MWGui::GM_MainMenu); return; } mTimePlayed = profile.mTimePlayed; } break; case ESM::REC_JOUR: case ESM::REC_JOUR_LEGACY: case ESM::REC_QUES: MWBase::Environment::get().getJournal()->readRecord (reader, n.val); break; case ESM::REC_DIAS: MWBase::Environment::get().getDialogueManager()->readRecord (reader, n.val); break; case ESM::REC_ALCH: case ESM::REC_ARMO: case ESM::REC_BOOK: case ESM::REC_CLAS: case ESM::REC_CLOT: case ESM::REC_ENCH: case ESM::REC_NPC_: case ESM::REC_SPEL: case ESM::REC_WEAP: case ESM::REC_GLOB: case ESM::REC_PLAY: case ESM::REC_CSTA: case ESM::REC_WTHR: case ESM::REC_DYNA: case ESM::REC_ACTC: case ESM::REC_PROJ: case ESM::REC_MPRJ: case ESM::REC_ENAB: case ESM::REC_LEVC: case ESM::REC_LEVI: MWBase::Environment::get().getWorld()->readRecord(reader, n.val, contentFileMap); break; case ESM::REC_CAM_: reader.getHNT(firstPersonCam, "FIRS"); break; case ESM::REC_GSCR: MWBase::Environment::get().getScriptManager()->getGlobalScripts().readRecord (reader, n.val); break; case ESM::REC_GMAP: case ESM::REC_KEYS: case ESM::REC_ASPL: case ESM::REC_MARK: MWBase::Environment::get().getWindowManager()->readRecord(reader, n.val); break; case ESM::REC_DCOU: case ESM::REC_STLN: MWBase::Environment::get().getMechanicsManager()->readRecord(reader, n.val); break; default: // ignore invalid records std::cerr << "Ignoring unknown record: " << n.toString() << std::endl; reader.skipRecord(); } int progressPercent = static_cast<int>(float(reader.getFileOffset())/total*100); if (progressPercent > currentPercent) { listener.increaseProgress(progressPercent-currentPercent); currentPercent = progressPercent; } } mCharacterManager.setCurrentCharacter(character); mState = State_Running; Settings::Manager::setString ("character", "Saves", character->getPath().filename().string()); MWBase::Environment::get().getWindowManager()->setNewGame(false); MWBase::Environment::get().getWorld()->setupPlayer(); MWBase::Environment::get().getWorld()->renderPlayer(); MWBase::Environment::get().getWindowManager()->updatePlayer(); MWBase::Environment::get().getMechanicsManager()->playerLoaded(); if (firstPersonCam != MWBase::Environment::get().getWorld()->isFirstPerson()) MWBase::Environment::get().getWorld()->togglePOV(); MWWorld::ConstPtr ptr = MWMechanics::getPlayer(); const ESM::CellId& cellId = ptr.getCell()->getCell()->getCellId(); // Use detectWorldSpaceChange=false, otherwise some of the data we just loaded would be cleared again MWBase::Environment::get().getWorld()->changeToCell (cellId, ptr.getRefData().getPosition(), false); // Vanilla MW will restart startup scripts when a save game is loaded. This is unintuitive, // but some mods may be using it as a reload detector. MWBase::Environment::get().getScriptManager()->getGlobalScripts().addStartup(); // Do not trigger erroneous cellChanged events MWBase::Environment::get().getWorld()->markCellAsUnchanged(); } catch (const std::exception& e) { std::stringstream error; error << "Failed to load saved game: " << e.what(); std::cerr << error.str() << std::endl; cleanup (true); MWBase::Environment::get().getWindowManager()->pushGuiMode (MWGui::GM_MainMenu); std::vector<std::string> buttons; buttons.push_back("#{sOk}"); MWBase::Environment::get().getWindowManager()->interactiveMessageBox(error.str(), buttons); } }
void MWState::StateManager::loadGame (const Character *character, const Slot *slot) { try { cleanup(); mTimePlayed = slot->mProfile.mTimePlayed; ESM::ESMReader reader; reader.open (slot->mPath.string()); std::map<int, int> contentFileMap = buildContentFileIndexMap (reader); while (reader.hasMoreRecs()) { ESM::NAME n = reader.getRecName(); reader.getRecHeader(); switch (n.val) { case ESM::REC_SAVE: // don't need to read that here reader.skipRecord(); break; case ESM::REC_JOUR: case ESM::REC_QUES: MWBase::Environment::get().getJournal()->readRecord (reader, n.val); break; case ESM::REC_ALCH: case ESM::REC_ARMO: case ESM::REC_BOOK: case ESM::REC_CLAS: case ESM::REC_CLOT: case ESM::REC_ENCH: case ESM::REC_NPC_: case ESM::REC_SPEL: case ESM::REC_WEAP: case ESM::REC_GLOB: case ESM::REC_PLAY: case ESM::REC_CSTA: MWBase::Environment::get().getWorld()->readRecord (reader, n.val, contentFileMap); break; case ESM::REC_GSCR: MWBase::Environment::get().getScriptManager()->getGlobalScripts().readRecord (reader, n.val); break; case ESM::REC_GMAP: MWBase::Environment::get().getWindowManager()->readRecord(reader, n.val); break; default: // ignore invalid records /// \todo log error reader.skipRecord(); } } mCharacterManager.setCurrentCharacter(character); mState = State_Running; Settings::Manager::setString ("character", "Saves", slot->mPath.parent_path().filename().string()); MWBase::Environment::get().getWindowManager()->setNewGame(false); MWBase::Environment::get().getWorld()->setupPlayer(); MWBase::Environment::get().getWorld()->renderPlayer(); MWBase::Environment::get().getWindowManager()->updatePlayer(); MWBase::Environment::get().getMechanicsManager()->playerLoaded(); MWWorld::Ptr ptr = MWBase::Environment::get().getWorld()->getPlayer().getPlayer(); ESM::CellId cellId = ptr.getCell()->mCell->getCellId(); MWBase::Environment::get().getWorld()->changeToCell (cellId, ptr.getRefData().getPosition()); } catch (const std::exception& e) { std::cerr << "failed to load saved game: " << e.what() << std::endl; cleanup (true); } }
void CSMWorld::Data::loadFile (const boost::filesystem::path& path, bool base, bool project) { ESM::ESMReader reader; /// \todo set encoding properly, once config implementation has been fixed. ToUTF8::Utf8Encoder encoder (ToUTF8::calculateEncoding ("win1252")); reader.setEncoder (&encoder); reader.open (path.string()); const ESM::Dialogue *dialogue = 0; mAuthor = reader.getAuthor(); mDescription = reader.getDesc(); // Note: We do not need to send update signals here, because at this point the model is not connected // to any view. while (reader.hasMoreRecs()) { ESM::NAME n = reader.getRecName(); reader.getRecHeader(); switch (n.val) { case ESM::REC_GLOB: mGlobals.load (reader, base); break; case ESM::REC_GMST: mGmsts.load (reader, base); break; case ESM::REC_SKIL: mSkills.load (reader, base); break; case ESM::REC_CLAS: mClasses.load (reader, base); break; case ESM::REC_FACT: mFactions.load (reader, base); break; case ESM::REC_RACE: mRaces.load (reader, base); break; case ESM::REC_SOUN: mSounds.load (reader, base); break; case ESM::REC_SCPT: mScripts.load (reader, base); break; case ESM::REC_REGN: mRegions.load (reader, base); break; case ESM::REC_BSGN: mBirthsigns.load (reader, base); break; case ESM::REC_SPEL: mSpells.load (reader, base); break; case ESM::REC_CELL: mCells.load (reader, base); mRefs.load (reader, mCells.getSize()-1, base); break; case ESM::REC_ACTI: mReferenceables.load (reader, base, UniversalId::Type_Activator); break; case ESM::REC_ALCH: mReferenceables.load (reader, base, UniversalId::Type_Potion); break; case ESM::REC_APPA: mReferenceables.load (reader, base, UniversalId::Type_Apparatus); break; case ESM::REC_ARMO: mReferenceables.load (reader, base, UniversalId::Type_Armor); break; case ESM::REC_BOOK: mReferenceables.load (reader, base, UniversalId::Type_Book); break; case ESM::REC_CLOT: mReferenceables.load (reader, base, UniversalId::Type_Clothing); break; case ESM::REC_CONT: mReferenceables.load (reader, base, UniversalId::Type_Container); break; case ESM::REC_CREA: mReferenceables.load (reader, base, UniversalId::Type_Creature); break; case ESM::REC_DOOR: mReferenceables.load (reader, base, UniversalId::Type_Door); break; case ESM::REC_INGR: mReferenceables.load (reader, base, UniversalId::Type_Ingredient); break; case ESM::REC_LEVC: mReferenceables.load (reader, base, UniversalId::Type_CreatureLevelledList); break; case ESM::REC_LEVI: mReferenceables.load (reader, base, UniversalId::Type_ItemLevelledList); break; case ESM::REC_LIGH: mReferenceables.load (reader, base, UniversalId::Type_Light); break; case ESM::REC_LOCK: mReferenceables.load (reader, base, UniversalId::Type_Lockpick); break; case ESM::REC_MISC: mReferenceables.load (reader, base, UniversalId::Type_Miscellaneous); break; case ESM::REC_NPC_: mReferenceables.load (reader, base, UniversalId::Type_Npc); break; case ESM::REC_PROB: mReferenceables.load (reader, base, UniversalId::Type_Probe); break; case ESM::REC_REPA: mReferenceables.load (reader, base, UniversalId::Type_Repair); break; case ESM::REC_STAT: mReferenceables.load (reader, base, UniversalId::Type_Static); break; case ESM::REC_WEAP: mReferenceables.load (reader, base, UniversalId::Type_Weapon); break; case ESM::REC_DIAL: { std::string id = reader.getHNOString ("NAME"); ESM::Dialogue record; record.mId = id; record.load (reader); if (record.mType==ESM::Dialogue::Journal) { mJournals.load (record, base); dialogue = &mJournals.getRecord (id).get(); } else if (record.mType==ESM::Dialogue::Deleted) { dialogue = 0; // record vector can be shuffled around which would make pointer // to record invalid if (mJournals.tryDelete (id)) { /// \todo handle info records } else if (mTopics.tryDelete (id)) { /// \todo handle info records } else { /// \todo report deletion of non-existing record } } else { mTopics.load (record, base); dialogue = &mTopics.getRecord (id).get(); } break; } case ESM::REC_INFO: { if (!dialogue) { /// \todo INFO record without matching DIAL record -> report to user reader.skipRecord(); break; } if (dialogue->mType==ESM::Dialogue::Journal) mJournalInfos.load (reader, base, *dialogue); else mTopicInfos.load (reader, base, *dialogue); break; } case ESM::REC_FILT: if (project) { mFilters.load (reader, base); mFilters.setData (mFilters.getSize()-1, mFilters.findColumnIndex (CSMWorld::Columns::ColumnId_Scope), static_cast<int> (CSMFilter::Filter::Scope_Project)); break; } // fall through (filter record in a content file is an error with format 0) default: /// \todo throw an exception instead, once all records are implemented /// or maybe report error and continue? reader.skipRecord(); } } }