mirror of
https://github.com/OpenMW/openmw.git
synced 2025-02-05 17:45:34 +00:00
Also run NPC validation for modified base records
This commit is contained in:
parent
e79036f4e0
commit
cf5a93d712
6 changed files with 73 additions and 43 deletions
|
@ -443,6 +443,8 @@ namespace MWBase
|
|||
virtual void applyDeferredPreviewRotationToPlayer(float dt) = 0;
|
||||
virtual void disableDeferredPreviewRotation() = 0;
|
||||
|
||||
virtual void saveLoaded() = 0;
|
||||
|
||||
virtual void setupPlayer() = 0;
|
||||
virtual void renderPlayer() = 0;
|
||||
|
||||
|
|
|
@ -505,6 +505,7 @@ void MWState::StateManager::loadGame (const Character *character, const std::str
|
|||
character->getPath().filename().string());
|
||||
|
||||
MWBase::Environment::get().getWindowManager()->setNewGame(false);
|
||||
MWBase::Environment::get().getWorld()->saveLoaded();
|
||||
MWBase::Environment::get().getWorld()->setupPlayer();
|
||||
MWBase::Environment::get().getWorld()->renderPlayer();
|
||||
MWBase::Environment::get().getWindowManager()->updatePlayer();
|
||||
|
|
|
@ -48,6 +48,57 @@ namespace
|
|||
}
|
||||
}
|
||||
}
|
||||
|
||||
std::vector<ESM::NPC> getNPCsToReplace(const MWWorld::Store<ESM::Faction>& factions, const MWWorld::Store<ESM::Class>& classes, const std::map<std::string, ESM::NPC>& npcs)
|
||||
{
|
||||
// Cache first class from store - we will use it if current class is not found
|
||||
std::string defaultCls;
|
||||
auto it = classes.begin();
|
||||
if (it != classes.end())
|
||||
defaultCls = it->mId;
|
||||
else
|
||||
throw std::runtime_error("List of NPC classes is empty!");
|
||||
|
||||
// Validate NPCs for non-existing class and faction.
|
||||
// We will replace invalid entries by fixed ones
|
||||
std::vector<ESM::NPC> npcsToReplace;
|
||||
|
||||
for (auto it : npcs)
|
||||
{
|
||||
ESM::NPC npc = it.second;
|
||||
bool changed = false;
|
||||
|
||||
const std::string npcFaction = npc.mFaction;
|
||||
if (!npcFaction.empty())
|
||||
{
|
||||
const ESM::Faction *fact = factions.search(npcFaction);
|
||||
if (!fact)
|
||||
{
|
||||
Log(Debug::Verbose) << "NPC '" << npc.mId << "' (" << npc.mName << ") has nonexistent faction '" << npc.mFaction << "', ignoring it.";
|
||||
npc.mFaction.clear();
|
||||
npc.mNpdt.mRank = 0;
|
||||
changed = true;
|
||||
}
|
||||
}
|
||||
|
||||
std::string npcClass = npc.mClass;
|
||||
if (!npcClass.empty())
|
||||
{
|
||||
const ESM::Class *cls = classes.search(npcClass);
|
||||
if (!cls)
|
||||
{
|
||||
Log(Debug::Verbose) << "NPC '" << npc.mId << "' (" << npc.mName << ") has nonexistent class '" << npc.mClass << "', using '" << defaultCls << "' class as replacement.";
|
||||
npc.mClass = defaultCls;
|
||||
changed = true;
|
||||
}
|
||||
}
|
||||
|
||||
if (changed)
|
||||
npcsToReplace.push_back(npc);
|
||||
}
|
||||
|
||||
return npcsToReplace;
|
||||
}
|
||||
}
|
||||
|
||||
namespace MWWorld
|
||||
|
@ -218,49 +269,7 @@ int ESMStore::getRefCount(const std::string& id) const
|
|||
|
||||
void ESMStore::validate()
|
||||
{
|
||||
// Cache first class from store - we will use it if current class is not found
|
||||
std::string defaultCls = "";
|
||||
Store<ESM::Class>::iterator it = mClasses.begin();
|
||||
if (it != mClasses.end())
|
||||
defaultCls = it->mId;
|
||||
else
|
||||
throw std::runtime_error("List of NPC classes is empty!");
|
||||
|
||||
// Validate NPCs for non-existing class and faction.
|
||||
// We will replace invalid entries by fixed ones
|
||||
std::vector<ESM::NPC> npcsToReplace;
|
||||
for (ESM::NPC npc : mNpcs)
|
||||
{
|
||||
bool changed = false;
|
||||
|
||||
const std::string npcFaction = npc.mFaction;
|
||||
if (!npcFaction.empty())
|
||||
{
|
||||
const ESM::Faction *fact = mFactions.search(npcFaction);
|
||||
if (!fact)
|
||||
{
|
||||
Log(Debug::Verbose) << "NPC '" << npc.mId << "' (" << npc.mName << ") has nonexistent faction '" << npc.mFaction << "', ignoring it.";
|
||||
npc.mFaction.clear();
|
||||
npc.mNpdt.mRank = 0;
|
||||
changed = true;
|
||||
}
|
||||
}
|
||||
|
||||
std::string npcClass = npc.mClass;
|
||||
if (!npcClass.empty())
|
||||
{
|
||||
const ESM::Class *cls = mClasses.search(npcClass);
|
||||
if (!cls)
|
||||
{
|
||||
Log(Debug::Verbose) << "NPC '" << npc.mId << "' (" << npc.mName << ") has nonexistent class '" << npc.mClass << "', using '" << defaultCls << "' class as replacement.";
|
||||
npc.mClass = defaultCls;
|
||||
changed = true;
|
||||
}
|
||||
}
|
||||
|
||||
if (changed)
|
||||
npcsToReplace.push_back(npc);
|
||||
}
|
||||
std::vector<ESM::NPC> npcsToReplace = getNPCsToReplace(mFactions, mClasses, mNpcs.mStatic);
|
||||
|
||||
for (const ESM::NPC &npc : npcsToReplace)
|
||||
{
|
||||
|
@ -331,6 +340,14 @@ void ESMStore::validate()
|
|||
}
|
||||
}
|
||||
|
||||
void ESMStore::validateDynamic()
|
||||
{
|
||||
std::vector<ESM::NPC> npcsToReplace = getNPCsToReplace(mFactions, mClasses, mNpcs.mDynamic);
|
||||
|
||||
for (const ESM::NPC &npc : npcsToReplace)
|
||||
mNpcs.insert(npc);
|
||||
}
|
||||
|
||||
int ESMStore::countSavedGameRecords() const
|
||||
{
|
||||
return 1 // DYNA (dynamic name counter)
|
||||
|
|
|
@ -179,6 +179,9 @@ namespace MWWorld
|
|||
mNpcs.insert(*player);
|
||||
}
|
||||
|
||||
/// Validate entries in store after loading a save
|
||||
void validateDynamic();
|
||||
|
||||
void load(ESM::ESMReader &esm, Loading::Listener* listener);
|
||||
|
||||
template <class T>
|
||||
|
|
|
@ -2473,6 +2473,11 @@ namespace MWWorld
|
|||
mRendering->getCamera()->adjustCameraDistance(dist);
|
||||
}
|
||||
|
||||
void World::saveLoaded()
|
||||
{
|
||||
mStore.validateDynamic();
|
||||
}
|
||||
|
||||
void World::setupPlayer()
|
||||
{
|
||||
const ESM::NPC *player = mStore.get<ESM::NPC>().find("player");
|
||||
|
|
|
@ -549,6 +549,8 @@ namespace MWWorld
|
|||
void applyDeferredPreviewRotationToPlayer(float dt) override;
|
||||
void disableDeferredPreviewRotation() override;
|
||||
|
||||
void saveLoaded() override;
|
||||
|
||||
void setupPlayer() override;
|
||||
void renderPlayer() override;
|
||||
|
||||
|
|
Loading…
Reference in a new issue