From 47a841d3b7fb700fc254150f73b378b166e0cb69 Mon Sep 17 00:00:00 2001 From: cc9cii Date: Tue, 17 Aug 2021 12:29:28 +1000 Subject: [PATCH 1/3] Fix/workaround for Issue #3246 OpenMW save file assumes the presence of NPC/Creature data but the vanilla save file provides only the delta changes in most situations. The base data are not available without loading all the relevant dependency content files. Duplicating that code in the ESSImporter is not desirable. Ideally a flag should be set but that will mean a change in the save file format. For a minor change such as this doing so seems like an overkill. So a temporary workaround is introduced where the gold carried by the NPC/Creature is used as an indicator as the lack of ACDT data. --- apps/essimporter/converter.cpp | 5 +++++ apps/openmw/mwclass/creature.cpp | 25 +++++++++++++++-------- apps/openmw/mwclass/npc.cpp | 13 +++++++++--- apps/openmw/mwmechanics/creaturestats.cpp | 20 +++++++++++------- apps/openmw/mwmechanics/creaturestats.hpp | 2 ++ 5 files changed, 47 insertions(+), 18 deletions(-) diff --git a/apps/essimporter/converter.cpp b/apps/essimporter/converter.cpp index 320f7224bc..874b936baf 100644 --- a/apps/essimporter/converter.cpp +++ b/apps/essimporter/converter.cpp @@ -2,6 +2,7 @@ #include #include +#include // INT_MIN #include @@ -369,6 +370,8 @@ namespace ESSImport // from the ESM with default values if (cellref.mHasACDT) convertACDT(cellref.mACDT, objstate.mCreatureStats); + else + objstate.mCreatureStats.mGoldPool = INT_MIN; // HACK: indicates no ACDT if (cellref.mHasACSC) convertACSC(cellref.mACSC, objstate.mCreatureStats); convertNpcData(cellref, objstate.mNpcStats); @@ -410,6 +413,8 @@ namespace ESSImport // from the ESM with default values if (cellref.mHasACDT) convertACDT(cellref.mACDT, objstate.mCreatureStats); + else + objstate.mCreatureStats.mGoldPool = INT_MIN; // HACK: indicates no ACDT if (cellref.mHasACSC) convertACSC(cellref.mACSC, objstate.mCreatureStats); convertCREC(crecIt->second, objstate); diff --git a/apps/openmw/mwclass/creature.cpp b/apps/openmw/mwclass/creature.cpp index d03ea70a87..8a9f33e1bd 100644 --- a/apps/openmw/mwclass/creature.cpp +++ b/apps/openmw/mwclass/creature.cpp @@ -748,26 +748,35 @@ namespace MWClass if (!state.mHasCustomState) return; + const ESM::CreatureState& creatureState = state.asCreatureState(); + if (state.mVersion > 0) { if (!ptr.getRefData().getCustomData()) { - // Create a CustomData, but don't fill it from ESM records (not needed) - std::unique_ptr data (new CreatureCustomData); - - if (hasInventoryStore(ptr)) - data->mContainerStore = std::make_unique(); + // FIXME: the use of mGoldPool can be replaced with another flag the next time + // the save file format is changed + if (creatureState.mCreatureStats.mGoldPool == INT_MIN) + ensureCustomData(ptr); else - data->mContainerStore = std::make_unique(); + { + // Create a CustomData, but don't fill it from ESM records (not needed) + std::unique_ptr data (new CreatureCustomData); - ptr.getRefData().setCustomData (std::move(data)); + if (hasInventoryStore(ptr)) + data->mContainerStore = std::make_unique(); + else + data->mContainerStore = std::make_unique(); + + 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(); - const ESM::CreatureState& creatureState = state.asCreatureState(); + customData.mContainerStore->readState (creatureState.mInventory); bool spellsInitialised = customData.mCreatureStats.getSpells().setSpells(ptr.get()->mBase->mId); if(spellsInitialised) diff --git a/apps/openmw/mwclass/npc.cpp b/apps/openmw/mwclass/npc.cpp index 736ae537fe..030c533b23 100644 --- a/apps/openmw/mwclass/npc.cpp +++ b/apps/openmw/mwclass/npc.cpp @@ -1291,19 +1291,26 @@ namespace MWClass if (!state.mHasCustomState) return; + const ESM::NpcState& npcState = state.asNpcState(); + if (state.mVersion > 0) { if (!ptr.getRefData().getCustomData()) { - // Create a CustomData, but don't fill it from ESM records (not needed) - ptr.getRefData().setCustomData(std::make_unique()); + // FIXME: the use of mGoldPool can be replaced with another flag the next time + // the save file format is changed + if (npcState.mCreatureStats.mGoldPool == INT_MIN) + ensureCustomData(ptr); + else + // Create a CustomData, but don't fill it from ESM records (not needed) + ptr.getRefData().setCustomData(std::make_unique()); } } 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(); - const ESM::NpcState& npcState = state.asNpcState(); + customData.mInventoryStore.readState (npcState.mInventory); customData.mNpcStats.readState (npcState.mNpcStats); bool spellsInitialised = customData.mNpcStats.getSpells().setSpells(ptr.get()->mBase->mId); diff --git a/apps/openmw/mwmechanics/creaturestats.cpp b/apps/openmw/mwmechanics/creaturestats.cpp index 1ff44fcbb0..8d99664f27 100644 --- a/apps/openmw/mwmechanics/creaturestats.cpp +++ b/apps/openmw/mwmechanics/creaturestats.cpp @@ -1,6 +1,7 @@ #include "creaturestats.hpp" #include +#include #include #include @@ -562,22 +563,27 @@ namespace MWMechanics void CreatureStats::readState (const ESM::CreatureStats& state) { - for (int i=0; i Date: Tue, 17 Aug 2021 12:31:06 +1000 Subject: [PATCH 2/3] update changelog --- CHANGELOG.md | 1 + 1 file changed, 1 insertion(+) diff --git a/CHANGELOG.md b/CHANGELOG.md index c53c8401f3..cb461154d3 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -1,6 +1,7 @@ 0.48.0 ------ + Bug #3246: ESSImporter: Most NPCs are dead on save load Bug #3514: Editing a reference's position after loading an esp file makes the reference disappear Bug #3737: Scripts from The Underground 2 .esp do not play (all patched versions) Bug #3846: Strings starting with "-" fail to compile if not enclosed in quotes From b1fb3e2313f8fcd99de15c193e8eba1c9ab7a7d2 Mon Sep 17 00:00:00 2001 From: cc9cii Date: Tue, 17 Aug 2021 13:53:14 +1000 Subject: [PATCH 3/3] Add missing includes. --- apps/openmw/mwclass/creature.cpp | 2 ++ apps/openmw/mwclass/npc.cpp | 1 + 2 files changed, 3 insertions(+) diff --git a/apps/openmw/mwclass/creature.cpp b/apps/openmw/mwclass/creature.cpp index 8a9f33e1bd..50dafba39b 100644 --- a/apps/openmw/mwclass/creature.cpp +++ b/apps/openmw/mwclass/creature.cpp @@ -1,5 +1,7 @@ #include "creature.hpp" +#include // INT_MIN + #include #include #include diff --git a/apps/openmw/mwclass/npc.cpp b/apps/openmw/mwclass/npc.cpp index 030c533b23..41cf3beed5 100644 --- a/apps/openmw/mwclass/npc.cpp +++ b/apps/openmw/mwclass/npc.cpp @@ -1,6 +1,7 @@ #include "npc.hpp" #include +#include // INT_MIN #include #include