1
0
Fork 0
mirror of https://github.com/OpenMW/openmw.git synced 2025-06-25 13:11:37 +00:00

Merge branch 'saveformat' into 'master'

Drop support for old saves

See merge request OpenMW/openmw!3629
This commit is contained in:
jvoisin 2023-12-06 12:33:07 +00:00
commit b67d89f2e0
24 changed files with 75 additions and 159 deletions

View file

@ -111,6 +111,7 @@
Feature #6447: Add LOD support to Object Paging Feature #6447: Add LOD support to Object Paging
Feature #6491: Add support for Qt6 Feature #6491: Add support for Qt6
Feature #6556: Lua API for sounds Feature #6556: Lua API for sounds
Feature #6624: Drop support for old saves
Feature #6726: Lua API for creating new objects Feature #6726: Lua API for creating new objects
Feature #6864: Lua file access API Feature #6864: Lua file access API
Feature #6922: Improve launcher appearance Feature #6922: Improve launcher appearance

View file

@ -779,32 +779,26 @@ namespace MWClass
const ESM::CreatureState& creatureState = state.asCreatureState(); const ESM::CreatureState& creatureState = state.asCreatureState();
if (state.mVersion > 0) if (!ptr.getRefData().getCustomData())
{ {
if (!ptr.getRefData().getCustomData()) if (creatureState.mCreatureStats.mMissingACDT)
ensureCustomData(ptr);
else
{ {
if (creatureState.mCreatureStats.mMissingACDT) // Create a CustomData, but don't fill it from ESM records (not needed)
ensureCustomData(ptr); auto data = std::make_unique<CreatureCustomData>();
if (hasInventoryStore(ptr))
data->mContainerStore = std::make_unique<MWWorld::InventoryStore>();
else else
{ data->mContainerStore = std::make_unique<MWWorld::ContainerStore>();
// Create a CustomData, but don't fill it from ESM records (not needed)
auto data = std::make_unique<CreatureCustomData>();
if (hasInventoryStore(ptr)) MWBase::Environment::get().getWorldModel()->registerPtr(ptr);
data->mContainerStore = std::make_unique<MWWorld::InventoryStore>(); data->mContainerStore->setPtr(ptr);
else
data->mContainerStore = std::make_unique<MWWorld::ContainerStore>();
MWBase::Environment::get().getWorldModel()->registerPtr(ptr); ptr.getRefData().setCustomData(std::move(data));
data->mContainerStore->setPtr(ptr);
ptr.getRefData().setCustomData(std::move(data));
}
} }
} }
else
ensureCustomData(
ptr); // in openmw 0.30 savegames not all state was saved yet, so need to load it regardless.
CreatureCustomData& customData = ptr.getRefData().getCustomData()->asCreatureCustomData(); CreatureCustomData& customData = ptr.getRefData().getCustomData()->asCreatureCustomData();

View file

@ -1333,25 +1333,19 @@ namespace MWClass
const ESM::NpcState& npcState = state.asNpcState(); const ESM::NpcState& npcState = state.asNpcState();
if (state.mVersion > 0) if (!ptr.getRefData().getCustomData())
{ {
if (!ptr.getRefData().getCustomData()) if (npcState.mCreatureStats.mMissingACDT)
ensureCustomData(ptr);
else
{ {
if (npcState.mCreatureStats.mMissingACDT) // Create a CustomData, but don't fill it from ESM records (not needed)
ensureCustomData(ptr); auto data = std::make_unique<NpcCustomData>();
else MWBase::Environment::get().getWorldModel()->registerPtr(ptr);
{ data->mInventoryStore.setPtr(ptr);
// Create a CustomData, but don't fill it from ESM records (not needed) ptr.getRefData().setCustomData(std::move(data));
auto data = std::make_unique<NpcCustomData>();
MWBase::Environment::get().getWorldModel()->registerPtr(ptr);
data->mInventoryStore.setPtr(ptr);
ptr.getRefData().setCustomData(std::move(data));
}
} }
} }
else
ensureCustomData(
ptr); // in openmw 0.30 savegames not all state was saved yet, so need to load it regardless.
NpcCustomData& customData = ptr.getRefData().getCustomData()->asNpcCustomData(); NpcCustomData& customData = ptr.getRefData().getCustomData()->asNpcCustomData();

View file

@ -250,7 +250,7 @@ namespace MWDialogue
void Journal::readRecord(ESM::ESMReader& reader, uint32_t type) void Journal::readRecord(ESM::ESMReader& reader, uint32_t type)
{ {
if (type == ESM::REC_JOUR || type == ESM::REC_JOUR_LEGACY) if (type == ESM::REC_JOUR)
{ {
ESM::JournalEntry record; ESM::JournalEntry record;
record.load(reader); record.load(reader);

View file

@ -411,10 +411,25 @@ void MWState::StateManager::loadGame(const Character* character, const std::file
ESM::ESMReader reader; ESM::ESMReader reader;
reader.open(filepath); reader.open(filepath);
if (reader.getFormatVersion() > ESM::CurrentSaveGameFormatVersion) ESM::FormatVersion version = reader.getFormatVersion();
throw VersionMismatchError( if (version > ESM::CurrentSaveGameFormatVersion)
"This save file was created using a newer version of OpenMW and is thus not supported. Please upgrade " throw VersionMismatchError("#{OMWEngine:LoadingRequiresNewVersionError}");
"to the newest OpenMW version to load this file."); else if (version < ESM::MinSupportedSaveGameFormatVersion)
{
const char* release;
// Report the last version still capable of reading this save
if (version <= ESM::OpenMW0_48SaveGameFormatVersion)
release = "OpenMW 0.48.0";
else
{
// Insert additional else if statements above to cover future releases
static_assert(ESM::MinSupportedSaveGameFormatVersion <= ESM::OpenMW0_49SaveGameFormatVersion);
release = "OpenMW 0.49.0";
}
auto l10n = MWBase::Environment::get().getL10nManager()->getContext("OMWEngine");
std::string message = l10n->formatMessage("LoadingRequiresOldVersionError", { "version" }, { release });
throw VersionMismatchError(message);
}
std::map<int, int> contentFileMap = buildContentFileIndexMap(reader); std::map<int, int> contentFileMap = buildContentFileIndexMap(reader);
reader.setContentFileMapping(&contentFileMap); reader.setContentFileMapping(&contentFileMap);
@ -457,7 +472,6 @@ void MWState::StateManager::loadGame(const Character* character, const std::file
break; break;
case ESM::REC_JOUR: case ESM::REC_JOUR:
case ESM::REC_JOUR_LEGACY:
case ESM::REC_QUES: case ESM::REC_QUES:
MWBase::Environment::get().getJournal()->readRecord(reader, n.toInt()); MWBase::Environment::get().getJournal()->readRecord(reader, n.toInt());
@ -607,11 +621,7 @@ void MWState::StateManager::loadGame(const Character* character, const std::file
std::vector<std::string> buttons; std::vector<std::string> buttons;
buttons.emplace_back("#{Interface:OK}"); buttons.emplace_back("#{Interface:OK}");
std::string error; std::string error = "#{OMWEngine:LoadingFailed}: " + std::string(e.what());
if (typeid(e) == typeid(VersionMismatchError))
error = "#{OMWEngine:LoadingFailed}: #{OMWEngine:LoadingRequiresNewVersionError}";
else
error = "#{OMWEngine:LoadingFailed}: " + std::string(e.what());
MWBase::Environment::get().getWindowManager()->interactiveMessageBox(error, buttons); MWBase::Environment::get().getWindowManager()->interactiveMessageBox(error, buttons);
} }

View file

@ -252,16 +252,16 @@ namespace
if (!record) if (!record)
return; return;
if (state.mVersion < 15) if (state.mVersion <= ESM::MaxOldRestockingFormatVersion)
fixRestocking(record, state); fixRestocking(record, state);
if (state.mVersion < 17) if (state.mVersion <= ESM::MaxClearModifiersFormatVersion)
{ {
if constexpr (std::is_same_v<T, ESM::Creature>) if constexpr (std::is_same_v<T, ESM::Creature>)
MWWorld::convertMagicEffects(state.mCreatureStats, state.mInventory); MWWorld::convertMagicEffects(state.mCreatureStats, state.mInventory);
else if constexpr (std::is_same_v<T, ESM::NPC>) else if constexpr (std::is_same_v<T, ESM::NPC>)
MWWorld::convertMagicEffects(state.mCreatureStats, state.mInventory, &state.mNpcStats); MWWorld::convertMagicEffects(state.mCreatureStats, state.mInventory, &state.mNpcStats);
} }
else if (state.mVersion < 20) else if (state.mVersion <= ESM::MaxOldCreatureStatsFormatVersion)
{ {
if constexpr (std::is_same_v<T, ESM::Creature> || std::is_same_v<T, ESM::NPC>) if constexpr (std::is_same_v<T, ESM::Creature> || std::is_same_v<T, ESM::NPC>)
MWWorld::convertStats(state.mCreatureStats); MWWorld::convertStats(state.mCreatureStats);

View file

@ -334,12 +334,7 @@ namespace MWWorld
if (player.mObject.mNpcStats.mIsWerewolf) if (player.mObject.mNpcStats.mIsWerewolf)
{ {
if (player.mObject.mNpcStats.mWerewolfDeprecatedData) if (reader.getFormatVersion() <= ESM::MaxOldSkillsAndAttributesFormatVersion)
{
saveStats();
setWerewolfStats();
}
else if (reader.getFormatVersion() <= ESM::MaxOldSkillsAndAttributesFormatVersion)
{ {
setWerewolfStats(); setWerewolfStats();
if (player.mSetWerewolfAcrobatics) if (player.mSetWerewolfAcrobatics)

View file

@ -272,8 +272,8 @@ namespace
ESM::CurrentContentFormatVersion, ESM::CurrentContentFormatVersion,
ESM::MaxOldWeatherFormatVersion, ESM::MaxOldWeatherFormatVersion,
ESM::MaxOldDeathAnimationFormatVersion, ESM::MaxOldDeathAnimationFormatVersion,
ESM::MaxOldForOfWarFormatVersion, ESM::MaxOldFogOfWarFormatVersion,
ESM::MaxWerewolfDeprecatedDataFormatVersion, ESM::MaxUnoptimizedCharacterDataFormatVersion,
ESM::MaxOldTimeLeftFormatVersion, ESM::MaxOldTimeLeftFormatVersion,
ESM::MaxIntFallbackFormatVersion, ESM::MaxIntFallbackFormatVersion,
ESM::MaxClearModifiersFormatVersion, ESM::MaxClearModifiersFormatVersion,

View file

@ -146,8 +146,6 @@ namespace ESM
// format 0 - saved games // format 0 - saved games
REC_SAVE = esm3Recname("SAVE"), REC_SAVE = esm3Recname("SAVE"),
REC_JOUR_LEGACY = esm3Recname("\xa4UOR"), // "\xa4UOR", rather than "JOUR", little oversight when magic numbers
// were calculated by hand, needs to be supported for older files now
REC_JOUR = esm3Recname("JOUR"), REC_JOUR = esm3Recname("JOUR"),
REC_QUES = esm3Recname("QUES"), REC_QUES = esm3Recname("QUES"),
REC_GSCR = esm3Recname("GSCR"), REC_GSCR = esm3Recname("GSCR"),

View file

@ -38,7 +38,7 @@ namespace ESM
mHitRecovery = false; mHitRecovery = false;
mBlock = false; mBlock = false;
mRecalcDynamicStats = false; mRecalcDynamicStats = false;
if (esm.getFormatVersion() <= MaxWerewolfDeprecatedDataFormatVersion) if (esm.getFormatVersion() <= MaxUnoptimizedCharacterDataFormatVersion)
{ {
esm.getHNOT(mDead, "DEAD"); esm.getHNOT(mDead, "DEAD");
esm.getHNOT(mDeathAnimationFinished, "DFNT"); esm.getHNOT(mDeathAnimationFinished, "DFNT");
@ -46,13 +46,9 @@ namespace ESM
mDeathAnimationFinished = true; mDeathAnimationFinished = true;
esm.getHNOT(mDied, "DIED"); esm.getHNOT(mDied, "DIED");
esm.getHNOT(mMurdered, "MURD"); esm.getHNOT(mMurdered, "MURD");
if (esm.isNextSub("FRHT"))
esm.skipHSub(); // Friendly hits, no longer used
esm.getHNOT(mTalkedTo, "TALK"); esm.getHNOT(mTalkedTo, "TALK");
esm.getHNOT(mAlarmed, "ALRM"); esm.getHNOT(mAlarmed, "ALRM");
esm.getHNOT(mAttacked, "ATKD"); esm.getHNOT(mAttacked, "ATKD");
if (esm.isNextSub("HOST"))
esm.skipHSub(); // Hostile, no longer used
if (esm.isNextSub("ATCK")) if (esm.isNextSub("ATCK"))
esm.skipHSub(); // attackingOrSpell, no longer used esm.skipHSub(); // attackingOrSpell, no longer used
esm.getHNOT(mKnockdown, "KNCK"); esm.getHNOT(mKnockdown, "KNCK");
@ -82,9 +78,6 @@ namespace ESM
mMovementFlags = 0; mMovementFlags = 0;
esm.getHNOT(mMovementFlags, "MOVE"); esm.getHNOT(mMovementFlags, "MOVE");
if (esm.isNextSub("ASTR"))
esm.skipHSub(); // attackStrength, no longer used
mFallHeight = 0; mFallHeight = 0;
esm.getHNOT(mFallHeight, "FALL"); esm.getHNOT(mFallHeight, "FALL");
@ -92,7 +85,7 @@ namespace ESM
mLastHitAttemptObject = esm.getHNORefId("LHAT"); mLastHitAttemptObject = esm.getHNORefId("LHAT");
if (esm.getFormatVersion() <= MaxWerewolfDeprecatedDataFormatVersion) if (esm.getFormatVersion() <= MaxUnoptimizedCharacterDataFormatVersion)
esm.getHNOT(mRecalcDynamicStats, "CALC"); esm.getHNOT(mRecalcDynamicStats, "CALC");
mDrawState = 0; mDrawState = 0;

View file

@ -22,14 +22,6 @@ namespace ESM
esm.getHNT(reaction, "INTV"); esm.getHNT(reaction, "INTV");
mChangedFactionReaction[faction][faction2] = reaction; mChangedFactionReaction[faction][faction2] = reaction;
} }
// no longer used
while (esm.isNextSub("REAC"))
{
esm.skipHSub();
esm.getSubName();
esm.skipHSub();
}
} }
} }

View file

@ -74,7 +74,7 @@ namespace ESM
tex.mImageData.resize(imageSize); tex.mImageData.resize(imageSize);
esm.getExact(tex.mImageData.data(), imageSize); esm.getExact(tex.mImageData.data(), imageSize);
if (dataFormat <= MaxOldForOfWarFormatVersion) if (dataFormat <= MaxOldFogOfWarFormatVersion)
convertFogOfWar(tex.mImageData); convertFogOfWar(tex.mImageData);
mFogTextures.push_back(tex); mFogTextures.push_back(tex);

View file

@ -11,10 +11,11 @@ namespace ESM
inline constexpr FormatVersion CurrentContentFormatVersion = 1; inline constexpr FormatVersion CurrentContentFormatVersion = 1;
inline constexpr FormatVersion MaxOldWeatherFormatVersion = 1; inline constexpr FormatVersion MaxOldWeatherFormatVersion = 1;
inline constexpr FormatVersion MaxOldDeathAnimationFormatVersion = 2; inline constexpr FormatVersion MaxOldDeathAnimationFormatVersion = 2;
inline constexpr FormatVersion MaxOldForOfWarFormatVersion = 6; inline constexpr FormatVersion MaxOldFogOfWarFormatVersion = 6;
inline constexpr FormatVersion MaxWerewolfDeprecatedDataFormatVersion = 7; inline constexpr FormatVersion MaxUnoptimizedCharacterDataFormatVersion = 7;
inline constexpr FormatVersion MaxOldTimeLeftFormatVersion = 8; inline constexpr FormatVersion MaxOldTimeLeftFormatVersion = 8;
inline constexpr FormatVersion MaxIntFallbackFormatVersion = 10; inline constexpr FormatVersion MaxIntFallbackFormatVersion = 10;
inline constexpr FormatVersion MaxOldRestockingFormatVersion = 14;
inline constexpr FormatVersion MaxClearModifiersFormatVersion = 16; inline constexpr FormatVersion MaxClearModifiersFormatVersion = 16;
inline constexpr FormatVersion MaxOldAiPackageFormatVersion = 17; inline constexpr FormatVersion MaxOldAiPackageFormatVersion = 17;
inline constexpr FormatVersion MaxOldSkillsAndAttributesFormatVersion = 18; inline constexpr FormatVersion MaxOldSkillsAndAttributesFormatVersion = 18;
@ -26,6 +27,10 @@ namespace ESM
inline constexpr FormatVersion MaxUseEsmCellIdFormatVersion = 26; inline constexpr FormatVersion MaxUseEsmCellIdFormatVersion = 26;
inline constexpr FormatVersion MaxActiveSpellSlotIndexFormatVersion = 27; inline constexpr FormatVersion MaxActiveSpellSlotIndexFormatVersion = 27;
inline constexpr FormatVersion CurrentSaveGameFormatVersion = 29; inline constexpr FormatVersion CurrentSaveGameFormatVersion = 29;
inline constexpr FormatVersion MinSupportedSaveGameFormatVersion = 1;
inline constexpr FormatVersion OpenMW0_48SaveGameFormatVersion = 21;
inline constexpr FormatVersion OpenMW0_49SaveGameFormatVersion = CurrentSaveGameFormatVersion;
} }
#endif #endif

View file

@ -22,14 +22,6 @@ namespace ESM
ObjectState state; ObjectState state;
// obsolete
if (esm.isNextSub("SLOT"))
{
int32_t slot;
esm.getHT(slot);
mEquipmentSlots[index] = slot;
}
state.mRef.loadId(esm, true); state.mRef.loadId(esm, true);
state.load(esm); state.load(esm);

View file

@ -41,46 +41,6 @@ namespace ESM
for (auto& skill : mSkills) for (auto& skill : mSkills)
skill.load(esm, intFallback); skill.load(esm, intFallback);
mWerewolfDeprecatedData = false;
if (esm.getFormatVersion() <= MaxWerewolfDeprecatedDataFormatVersion && esm.peekNextSub("STBA"))
{
// we have deprecated werewolf skills, stored interleaved
// Load into one big vector, then remove every 2nd value
mWerewolfDeprecatedData = true;
std::vector<StatState<float>> skills(mSkills.begin(), mSkills.end());
for (size_t i = 0; i < std::size(mSkills); ++i)
{
StatState<float> skill;
skill.load(esm, intFallback);
skills.push_back(skill);
}
int i = 0;
for (std::vector<StatState<float>>::iterator it = skills.begin(); it != skills.end(); ++i)
{
if (i % 2 == 1)
it = skills.erase(it);
else
++it;
}
if (skills.size() != std::size(mSkills))
throw std::runtime_error(
"Invalid number of skill for werewolf deprecated data: " + std::to_string(skills.size()));
std::copy(skills.begin(), skills.end(), mSkills.begin());
}
// No longer used
bool hasWerewolfAttributes = false;
esm.getHNOT(hasWerewolfAttributes, "HWAT");
if (hasWerewolfAttributes)
{
StatState<int32_t> dummy;
for (int i = 0; i < ESM::Attribute::Length; ++i)
dummy.load(esm, intFallback);
mWerewolfDeprecatedData = true;
}
mIsWerewolf = false; mIsWerewolf = false;
esm.getHNOT(mIsWerewolf, "WOLF"); esm.getHNOT(mIsWerewolf, "WOLF");
@ -93,14 +53,6 @@ namespace ESM
mWerewolfKills = 0; mWerewolfKills = 0;
esm.getHNOT(mWerewolfKills, "WKIL"); esm.getHNOT(mWerewolfKills, "WKIL");
// No longer used
if (esm.isNextSub("PROF"))
esm.skipHSub(); // int profit
// No longer used
if (esm.isNextSub("ASTR"))
esm.skipHSub(); // attackStrength
mLevelProgress = 0; mLevelProgress = 0;
esm.getHNOT(mLevelProgress, "LPRO"); esm.getHNOT(mLevelProgress, "LPRO");
@ -116,14 +68,6 @@ namespace ESM
mTimeToStartDrowning = 0; mTimeToStartDrowning = 0;
esm.getHNOT(mTimeToStartDrowning, "DRTI"); esm.getHNOT(mTimeToStartDrowning, "DRTI");
// No longer used
float lastDrowningHit = 0;
esm.getHNOT(lastDrowningHit, "DRLH");
// No longer used
float levelHealthBonus = 0;
esm.getHNOT(levelHealthBonus, "LVLH");
mCrimeId = -1; mCrimeId = -1;
esm.getHNOT(mCrimeId, "CRID"); esm.getHNOT(mCrimeId, "CRID");
} }
@ -195,7 +139,6 @@ namespace ESM
void NpcStats::blank() void NpcStats::blank()
{ {
mWerewolfDeprecatedData = false;
mIsWerewolf = false; mIsWerewolf = false;
mDisposition = 0; mDisposition = 0;
mBounty = 0; mBounty = 0;

View file

@ -31,8 +31,6 @@ namespace ESM
bool mIsWerewolf; bool mIsWerewolf;
bool mWerewolfDeprecatedData;
std::map<ESM::RefId, Faction> mFactions; std::map<ESM::RefId, Faction> mFactions;
int32_t mDisposition; int32_t mDisposition;
std::array<StatState<float>, ESM::Skill::Length> mSkills; std::array<StatState<float>, ESM::Skill::Length> mSkills;

View file

@ -48,10 +48,6 @@ namespace ESM
mFlags = 0; mFlags = 0;
esm.getHNOT(mFlags, "FLAG"); esm.getHNOT(mFlags, "FLAG");
// obsolete
int32_t unused;
esm.getHNOT(unused, "LTIM");
mAnimationState.load(esm); mAnimationState.load(esm);
// FIXME: assuming "false" as default would make more sense, but also break compatibility with older save files // FIXME: assuming "false" as default would make more sense, but also break compatibility with older save files

View file

@ -8,9 +8,6 @@ namespace ESM
void QuickKeys::load(ESMReader& esm) void QuickKeys::load(ESMReader& esm)
{ {
if (esm.isNextSub("KEY_"))
esm.getSubHeader(); // no longer used, because sub-record hierachies do not work properly in esmreader
while (esm.isNextSub("TYPE")) while (esm.isNextSub("TYPE"))
{ {
QuickKey key; QuickKey key;
@ -18,9 +15,6 @@ namespace ESM
key.mId = esm.getHNRefId("ID__"); key.mId = esm.getHNRefId("ID__");
mKeys.push_back(key); mKeys.push_back(key);
if (esm.isNextSub("KEY_"))
esm.getSubHeader(); // no longer used, because sub-record hierachies do not work properly in esmreader
} }
} }

View file

@ -32,10 +32,6 @@ namespace ESM
int32_t current = 0; int32_t current = 0;
esm.getHNOT(current, "STCU"); esm.getHNOT(current, "STCU");
mCurrent = static_cast<T>(current); mCurrent = static_cast<T>(current);
int32_t oldDamage = 0;
esm.getHNOT(oldDamage, "STDA");
mDamage = static_cast<float>(oldDamage);
} }
else else
{ {

View file

@ -25,6 +25,9 @@ BuildingNavigationMesh: "Baue Navigationsgitter"
#LoadingRequiresNewVersionError: |- #LoadingRequiresNewVersionError: |-
# This save file was created using a newer version of OpenMW and is thus not supported. # 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. # Please upgrade to the newest OpenMW version to load this file.
# LoadingRequiresOldVersionError: |-
# This save file was created using an older version of OpenMW in a format that is no longer supported.
# Load and save this file using {version} to upgrade it.
#NewGameConfirmation: "Do you want to start a new game and lose the current one?" #NewGameConfirmation: "Do you want to start a new game and lose the current one?"
#SaveGameDenied: "The game cannot be saved right now." #SaveGameDenied: "The game cannot be saved right now."
#SavingInProgress: "Saving..." #SavingInProgress: "Saving..."

View file

@ -22,6 +22,9 @@ LoadingInProgress: "Loading Save Game"
LoadingRequiresNewVersionError: |- LoadingRequiresNewVersionError: |-
This save file was created using a newer version of OpenMW and is thus not supported. 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. Please upgrade to the newest OpenMW version to load this file.
LoadingRequiresOldVersionError: |-
This save file was created using an older version of OpenMW in a format that is no longer supported.
Load and save this file using {version} to upgrade it.
NewGameConfirmation: "Do you want to start a new game and lose the current one?" NewGameConfirmation: "Do you want to start a new game and lose the current one?"
SaveGameDenied: "The game cannot be saved right now." SaveGameDenied: "The game cannot be saved right now."
SavingInProgress: "Saving..." SavingInProgress: "Saving..."

View file

@ -22,6 +22,9 @@ LoadingInProgress: "Chargement de la sauvegarde"
LoadingRequiresNewVersionError: |- LoadingRequiresNewVersionError: |-
Ce fichier de sauvegarde provient d'une version plus récente d'OpenMW, il n'est par consequent pas supporté. Ce fichier de sauvegarde provient d'une version plus récente d'OpenMW, il n'est par consequent pas supporté.
Mettez à jour votre version d'OpenMW afin de pouvoir charger cette sauvegarde. Mettez à jour votre version d'OpenMW afin de pouvoir charger cette sauvegarde.
# LoadingRequiresOldVersionError: |-
# This save file was created using an older version of OpenMW in a format that is no longer supported.
# Load and save this file using {version} to upgrade it.
NewGameConfirmation: "Voulez-vous démarrer une nouvelle partie ? Toute progression non sauvegardée sera perdue." NewGameConfirmation: "Voulez-vous démarrer une nouvelle partie ? Toute progression non sauvegardée sera perdue."
SaveGameDenied: "Sauvegarde impossible" SaveGameDenied: "Sauvegarde impossible"
SavingInProgress: "Sauvegarde en cours..." SavingInProgress: "Sauvegarde en cours..."

View file

@ -22,6 +22,9 @@ LoadingInProgress: "Загрузка сохранения"
LoadingRequiresNewVersionError: |- LoadingRequiresNewVersionError: |-
Это сохранение создано более новой версией OpenMW и поэтому не может быть загружено. Это сохранение создано более новой версией OpenMW и поэтому не может быть загружено.
Обновите OpenMW до последней версии, чтобы загрузить этот файл. Обновите OpenMW до последней версии, чтобы загрузить этот файл.
LoadingRequiresOldVersionError: |-
Это сохранение создано старой версией OpenMW и использует формат, который больше не поддерживается.
Загрузите и сохраните этот файл в {version}, чтобы обновить его.
NewGameConfirmation: "Вы хотите начать новую игру? Текущая игра будет потеряна." NewGameConfirmation: "Вы хотите начать новую игру? Текущая игра будет потеряна."
SaveGameDenied: "В данный момент игру нельзя сохранить." SaveGameDenied: "В данный момент игру нельзя сохранить."
SavingInProgress: "Сохранение..." SavingInProgress: "Сохранение..."

View file

@ -22,6 +22,9 @@ LoadingInProgress: "Laddar sparat spel"
LoadingRequiresNewVersionError: |- LoadingRequiresNewVersionError: |-
Denna sparfil skapades i en nyare version av OpenMW och stöds därför inte. Denna sparfil skapades i en nyare version av OpenMW och stöds därför inte.
Uppgradera till den senaste versionen av OpenMW för att ladda filen. Uppgradera till den senaste versionen av OpenMW för att ladda filen.
# LoadingRequiresOldVersionError: |-
# This save file was created using an older version of OpenMW in a format that is no longer supported.
# Load and save this file using {version} to upgrade it.
NewGameConfirmation: "Vill du starta ett nytt spel och förlora det pågående spelet?" NewGameConfirmation: "Vill du starta ett nytt spel och förlora det pågående spelet?"
SaveGameDenied: "Spelet kan inte sparas just nu." SaveGameDenied: "Spelet kan inte sparas just nu."
SavingInProgress: "Sparar..." SavingInProgress: "Sparar..."