void MWWorld::Cells::writeCell (ESM::ESMWriter& writer, CellStore& cell) const { if (cell.getState()!=CellStore::State_Loaded) cell.load (); ESM::CellState cellState; cell.saveState (cellState); writer.startRecord (ESM::REC_CSTA); cellState.mId.save (writer); cellState.save (writer); cell.writeFog(writer); cell.writeReferences (writer); writer.endRecord (ESM::REC_CSTA); }
virtual void write(ESM::ESMWriter &esm) { if (!mHasGame) return; esm.startRecord(ESM::REC_WTHR); ESM::WeatherState weather; weather.mTimePassed = 0.0f; weather.mFastForward = false; weather.mWeatherUpdateTime = mGame.mGMDT.mTimeOfNextTransition - mContext->mHour; weather.mTransitionFactor = 1 - (mGame.mGMDT.mWeatherTransition / 100.0f); weather.mCurrentWeather = validateWeatherID(mGame.mGMDT.mCurrentWeather); weather.mNextWeather = validateWeatherID(mGame.mGMDT.mNextWeather); weather.mQueuedWeather = -1; // TODO: Determine how ModRegion modifiers are saved in Morrowind. weather.save(esm); esm.endRecord(ESM::REC_WTHR); }
void RefIdDataContainer<RecordT>::save (int index, ESM::ESMWriter& writer) const { CSMWorld::RecordBase::State state = mContainer.at (index).mState; if (state==CSMWorld::RecordBase::State_Modified || state==CSMWorld::RecordBase::State_ModifiedOnly) { writer.startRecord (mContainer.at (index).mModified.sRecordId); writer.writeHNCString ("NAME", getId (index)); mContainer.at (index).mModified.save (writer); writer.endRecord (mContainer.at (index).mModified.sRecordId); } else if (state==CSMWorld::RecordBase::State_Deleted) { /// \todo write record with delete flag } }
void GlobalScripts::write (ESM::ESMWriter& writer) const { for (std::map<std::string, std::pair<bool, Locals> >::const_iterator iter (mScripts.begin()); iter!=mScripts.end(); ++iter) { ESM::GlobalScript script; script.mId = iter->first; iter->second.second.write (script.mLocals, iter->first); script.mRunning = iter->second.first ? 1 : 0; writer.startRecord (ESM::REC_GSCR); script.save (writer); writer.endRecord (ESM::REC_GSCR); } }
void GlobalScripts::write (ESM::ESMWriter& writer, Loading::Listener& progress) const { for (std::map<std::string, GlobalScriptDesc>::const_iterator iter (mScripts.begin()); iter!=mScripts.end(); ++iter) { ESM::GlobalScript script; script.mId = iter->first; iter->second.mLocals.write (script.mLocals, iter->first); script.mRunning = iter->second.mRunning ? 1 : 0; script.mTargetId = iter->second.mId; writer.startRecord (ESM::REC_GSCR); script.save (writer); writer.endRecord (ESM::REC_GSCR); } }
virtual void write(ESM::ESMWriter &esm) { ESM::StolenItems items; for (std::map<std::string, std::set<Owner> >::const_iterator it = mStolenItems.begin(); it != mStolenItems.end(); ++it) { std::map<std::pair<std::string, bool>, int> owners; for (std::set<Owner>::const_iterator ownerIt = it->second.begin(); ownerIt != it->second.end(); ++ownerIt) { owners.insert(std::make_pair(std::make_pair(ownerIt->first, ownerIt->second) // Since OpenMW doesn't suffer from the owner contamination bug, // it needs a count argument. But for legacy savegames, we don't know // this count, so must assume all items of that ID are stolen, // like vanilla MW did. ,std::numeric_limits<int>::max())); } items.mStolenItems.insert(std::make_pair(it->first, owners)); } esm.startRecord(ESM::REC_STLN); items.write(esm); esm.endRecord(ESM::REC_STLN); }
void Player::write (ESM::ESMWriter& writer, Loading::Listener& progress) const { ESM::Player player; mPlayer.save (player.mObject); player.mCellId = mCellStore->getCell()->getCellId(); player.mCurrentCrimeId = mCurrentCrimeId; player.mPaidCrimeId = mPaidCrimeId; player.mBirthsign = mSign; player.mLastKnownExteriorPosition[0] = mLastKnownExteriorPosition.x(); player.mLastKnownExteriorPosition[1] = mLastKnownExteriorPosition.y(); player.mLastKnownExteriorPosition[2] = mLastKnownExteriorPosition.z(); if (mMarkedCell) { player.mHasMark = true; player.mMarkedPosition = mMarkedPosition; player.mMarkedCell = mMarkedCell->getCell()->getCellId(); } else player.mHasMark = false; player.mAutoMove = mAutoMove ? 1 : 0; for (int i=0; i<ESM::Attribute::Length; ++i) mSaveAttributes[i].writeState(player.mSaveAttributes[i]); for (int i=0; i<ESM::Skill::Length; ++i) mSaveSkills[i].writeState(player.mSaveSkills[i]); writer.startRecord (ESM::REC_PLAY); player.save (writer); writer.endRecord (ESM::REC_PLAY); }
virtual void write(ESM::ESMWriter &esm) { esm.startRecord(ESM::REC_CAM_); esm.writeHNT("FIRS", mFirstPersonCam); esm.endRecord(ESM::REC_CAM_); }
virtual void write(ESM::ESMWriter& esm) { esm.startRecord(ESM::REC_ASPL); esm.writeHNString("ID__", mSelectedSpell); esm.endRecord(ESM::REC_ASPL); }
void MWState::StateManager::saveGame (const std::string& description, const Slot *slot) { try { ESM::SavedGame profile; MWBase::World& world = *MWBase::Environment::get().getWorld(); MWWorld::Ptr player = world.getPlayerPtr(); profile.mContentFiles = world.getContentFiles(); profile.mPlayerName = player.getClass().getName (player); profile.mPlayerLevel = player.getClass().getNpcStats (player).getLevel(); std::string classId = player.get<ESM::NPC>()->mBase->mClass; if (world.getStore().get<ESM::Class>().isDynamic(classId)) profile.mPlayerClassName = world.getStore().get<ESM::Class>().find(classId)->mName; else profile.mPlayerClassId = classId; profile.mPlayerCell = world.getCellName(); profile.mInGameTime.mGameHour = world.getTimeStamp().getHour(); profile.mInGameTime.mDay = world.getDay(); profile.mInGameTime.mMonth = world.getMonth(); profile.mInGameTime.mYear = world.getYear(); profile.mTimePlayed = mTimePlayed; profile.mDescription = description; int screenshotW = 259*2, screenshotH = 133*2; // *2 to get some nice antialiasing Ogre::Image screenshot; world.screenshot(screenshot, screenshotW, screenshotH); Ogre::DataStreamPtr encoded = screenshot.encode("jpg"); profile.mScreenshot.resize(encoded->size()); encoded->read(&profile.mScreenshot[0], encoded->size()); if (!slot) slot = getCurrentCharacter()->createSlot (profile); else slot = getCurrentCharacter()->updateSlot (slot, profile); boost::filesystem::ofstream stream (slot->mPath, std::ios::binary); ESM::ESMWriter writer; const std::vector<std::string>& current = MWBase::Environment::get().getWorld()->getContentFiles(); for (std::vector<std::string>::const_iterator iter (current.begin()); iter!=current.end(); ++iter) writer.addMaster (*iter, 0); // not using the size information anyway -> use value of 0 writer.setFormat (ESM::Header::CurrentFormat); int recordCount = 1 // saved game header +MWBase::Environment::get().getJournal()->countSavedGameRecords() +MWBase::Environment::get().getWorld()->countSavedGameRecords() +MWBase::Environment::get().getScriptManager()->getGlobalScripts().countSavedGameRecords() +MWBase::Environment::get().getDialogueManager()->countSavedGameRecords() +MWBase::Environment::get().getWindowManager()->countSavedGameRecords(); writer.setRecordCount (recordCount); writer.save (stream); Loading::Listener& listener = *MWBase::Environment::get().getWindowManager()->getLoadingScreen(); listener.setProgressRange(recordCount); listener.setLabel("#{sNotifyMessage4}"); Loading::ScopedLoad load(&listener); writer.startRecord (ESM::REC_SAVE); slot->mProfile.save (writer); writer.endRecord (ESM::REC_SAVE); listener.increaseProgress(); MWBase::Environment::get().getJournal()->write (writer, listener); MWBase::Environment::get().getDialogueManager()->write (writer, listener); MWBase::Environment::get().getWorld()->write (writer, listener); MWBase::Environment::get().getScriptManager()->getGlobalScripts().write (writer, listener); MWBase::Environment::get().getWindowManager()->write(writer, listener); // Ensure we have written the number of records that was estimated if (writer.getRecordCount() != recordCount+1) // 1 extra for TES3 record std::cerr << "Warning: number of written savegame records does not match. Estimated: " << recordCount+1 << ", written: " << writer.getRecordCount() << std::endl; writer.close(); if (stream.fail()) throw std::runtime_error("Write operation failed"); Settings::Manager::setString ("character", "Saves", slot->mPath.parent_path().filename().string()); } catch (const std::exception& e) { std::stringstream error; error << "Failed to save game: " << e.what(); std::cerr << error.str() << std::endl; std::vector<std::string> buttons; buttons.push_back("#{sOk}"); MWBase::Environment::get().getWindowManager()->messageBox(error.str(), buttons); // If no file was written, clean up the slot if (slot && !boost::filesystem::exists(slot->mPath)) getCurrentCharacter()->deleteSlot(slot); } }
void MWState::StateManager::saveGame (const std::string& description, const Slot *slot) { try { ESM::SavedGame profile; MWBase::World& world = *MWBase::Environment::get().getWorld(); MWWorld::Ptr player = world.getPlayerPtr(); profile.mContentFiles = world.getContentFiles(); profile.mPlayerName = player.get<ESM::NPC>()->mBase->mName; profile.mPlayerLevel = player.getClass().getNpcStats (player).getLevel(); std::string classId = player.get<ESM::NPC>()->mBase->mClass; if (world.getStore().get<ESM::Class>().isDynamic(classId)) profile.mPlayerClassName = world.getStore().get<ESM::Class>().find(classId)->mName; else profile.mPlayerClassId = classId; profile.mPlayerCell = world.getCellName(); profile.mInGameTime.mGameHour = world.getTimeStamp().getHour(); profile.mInGameTime.mDay = world.getDay(); profile.mInGameTime.mMonth = world.getMonth(); profile.mInGameTime.mYear = world.getYear(); profile.mTimePlayed = mTimePlayed; profile.mDescription = description; writeScreenshot(profile.mScreenshot); if (!slot) slot = getCurrentCharacter()->createSlot (profile); else slot = getCurrentCharacter()->updateSlot (slot, profile); // Write to a memory stream first. If there is an exception during the save process, we don't want to trash the // existing save file we are overwriting. std::stringstream stream; ESM::ESMWriter writer; const std::vector<std::string>& current = MWBase::Environment::get().getWorld()->getContentFiles(); for (std::vector<std::string>::const_iterator iter (current.begin()); iter!=current.end(); ++iter) writer.addMaster (*iter, 0); // not using the size information anyway -> use value of 0 writer.setFormat (ESM::SavedGame::sCurrentFormat); // all unused writer.setVersion(0); writer.setType(0); writer.setAuthor(""); writer.setDescription(""); int recordCount = 1 // saved game header +MWBase::Environment::get().getJournal()->countSavedGameRecords() +MWBase::Environment::get().getWorld()->countSavedGameRecords() +MWBase::Environment::get().getScriptManager()->getGlobalScripts().countSavedGameRecords() +MWBase::Environment::get().getDialogueManager()->countSavedGameRecords() +MWBase::Environment::get().getWindowManager()->countSavedGameRecords() +MWBase::Environment::get().getMechanicsManager()->countSavedGameRecords(); writer.setRecordCount (recordCount); writer.save (stream); Loading::Listener& listener = *MWBase::Environment::get().getWindowManager()->getLoadingScreen(); // Using only Cells for progress information, since they typically have the largest records by far listener.setProgressRange(MWBase::Environment::get().getWorld()->countSavedGameCells()); listener.setLabel("#{sNotifyMessage4}", true); Loading::ScopedLoad load(&listener); writer.startRecord (ESM::REC_SAVE); slot->mProfile.save (writer); writer.endRecord (ESM::REC_SAVE); MWBase::Environment::get().getJournal()->write (writer, listener); MWBase::Environment::get().getDialogueManager()->write (writer, listener); MWBase::Environment::get().getWorld()->write (writer, listener); MWBase::Environment::get().getScriptManager()->getGlobalScripts().write (writer, listener); MWBase::Environment::get().getWindowManager()->write(writer, listener); MWBase::Environment::get().getMechanicsManager()->write(writer, listener); // Ensure we have written the number of records that was estimated if (writer.getRecordCount() != recordCount+1) // 1 extra for TES3 record std::cerr << "Warning: number of written savegame records does not match. Estimated: " << recordCount+1 << ", written: " << writer.getRecordCount() << std::endl; writer.close(); if (stream.fail()) throw std::runtime_error("Write operation failed (memory stream)"); // All good, write to file boost::filesystem::ofstream filestream (slot->mPath, std::ios::binary); filestream << stream.rdbuf(); if (filestream.fail()) throw std::runtime_error("Write operation failed (file stream)"); Settings::Manager::setString ("character", "Saves", slot->mPath.parent_path().filename().string()); } catch (const std::exception& e) { std::stringstream error; error << "Failed to save game: " << e.what(); std::cerr << error.str() << std::endl; std::vector<std::string> buttons; buttons.push_back("#{sOk}"); MWBase::Environment::get().getWindowManager()->interactiveMessageBox(error.str(), buttons); // If no file was written, clean up the slot if (slot && !boost::filesystem::exists(slot->mPath)) getCurrentCharacter()->deleteSlot(slot); } }
void CreatureStats::writeActorIdCounter (ESM::ESMWriter& esm) { esm.startRecord(ESM::REC_ACTC); esm.writeHNT("COUN", sActorId); esm.endRecord(ESM::REC_ACTC); }
void MWState::StateManager::saveGame (const std::string& description, const Slot *slot) { ESM::SavedGame profile; MWBase::World& world = *MWBase::Environment::get().getWorld(); MWWorld::Ptr player = world.getPlayer().getPlayer(); profile.mContentFiles = world.getContentFiles(); profile.mPlayerName = player.getClass().getName (player); profile.mPlayerLevel = player.getClass().getNpcStats (player).getLevel(); profile.mPlayerClass = player.get<ESM::NPC>()->mBase->mClass; profile.mPlayerCell = world.getCellName(); profile.mInGameTime.mGameHour = world.getTimeStamp().getHour(); profile.mInGameTime.mDay = world.getDay(); profile.mInGameTime.mMonth = world.getMonth(); profile.mInGameTime.mYear = world.getYear(); profile.mTimePlayed = mTimePlayed; profile.mDescription = description; int screenshotW = 259*2, screenshotH = 133*2; // *2 to get some nice antialiasing Ogre::Image screenshot; world.screenshot(screenshot, screenshotW, screenshotH); Ogre::DataStreamPtr encoded = screenshot.encode("jpg"); profile.mScreenshot.resize(encoded->size()); encoded->read(&profile.mScreenshot[0], encoded->size()); if (!slot) slot = mCharacterManager.getCurrentCharacter()->createSlot (profile); else slot = mCharacterManager.getCurrentCharacter()->updateSlot (slot, profile); std::ofstream stream (slot->mPath.string().c_str()); ESM::ESMWriter writer; const std::vector<std::string>& current = MWBase::Environment::get().getWorld()->getContentFiles(); for (std::vector<std::string>::const_iterator iter (current.begin()); iter!=current.end(); ++iter) writer.addMaster (*iter, 0); // not using the size information anyway -> use value of 0 writer.setFormat (ESM::Header::CurrentFormat); writer.setRecordCount ( 1 // saved game header +MWBase::Environment::get().getJournal()->countSavedGameRecords() +MWBase::Environment::get().getWorld()->countSavedGameRecords() +MWBase::Environment::get().getScriptManager()->getGlobalScripts().countSavedGameRecords() + 1 // global map ); writer.save (stream); writer.startRecord (ESM::REC_SAVE); slot->mProfile.save (writer); writer.endRecord (ESM::REC_SAVE); MWBase::Environment::get().getJournal()->write (writer); MWBase::Environment::get().getWorld()->write (writer); MWBase::Environment::get().getScriptManager()->getGlobalScripts().write (writer); MWBase::Environment::get().getWindowManager()->write(writer); writer.close(); Settings::Manager::setString ("character", "Saves", slot->mPath.parent_path().filename().string()); }