Merge branch 'missmewiththatscript' into 'master'

Remove missing scripts from actors much like is done for items

Closes #7204

See merge request OpenMW/openmw!3502
macos_ci_fix
psi29a 1 year ago
commit 8380da2e1d

@ -59,6 +59,7 @@
Bug #7134: Saves with an invalid last generated RefNum can be loaded Bug #7134: Saves with an invalid last generated RefNum can be loaded
Bug #7163: Myar Aranath: Wheat breaks the GUI Bug #7163: Myar Aranath: Wheat breaks the GUI
Bug #7172: Current music playlist continues playing indefinitely if next playlist is empty Bug #7172: Current music playlist continues playing indefinitely if next playlist is empty
Bug #7204: Missing actor scripts freeze the game
Bug #7229: Error marker loading failure is not handled Bug #7229: Error marker loading failure is not handled
Bug #7243: Supporting loading external files from VFS from esm files Bug #7243: Supporting loading external files from VFS from esm files
Bug #7284: "Your weapon has no effect." message doesn't always show when the player character attempts to attack Bug #7284: "Your weapon has no effect." message doesn't always show when the player character attempts to attack

@ -84,7 +84,8 @@ namespace
} }
std::vector<ESM::NPC> getNPCsToReplace(const MWWorld::Store<ESM::Faction>& factions, std::vector<ESM::NPC> getNPCsToReplace(const MWWorld::Store<ESM::Faction>& factions,
const MWWorld::Store<ESM::Class>& classes, const std::unordered_map<ESM::RefId, ESM::NPC>& npcs) const MWWorld::Store<ESM::Class>& classes, const MWWorld::Store<ESM::Script>& scripts,
const std::unordered_map<ESM::RefId, ESM::NPC>& npcs)
{ {
// Cache first class from store - we will use it if current class is not found // Cache first class from store - we will use it if current class is not found
const ESM::RefId& defaultCls = getDefaultClass(classes); const ESM::RefId& defaultCls = getDefaultClass(classes);
@ -122,6 +123,14 @@ namespace
changed = true; changed = true;
} }
if (!npc.mScript.empty() && !scripts.search(npc.mScript))
{
Log(Debug::Verbose) << "NPC " << npc.mId << " (" << npc.mName << ") has nonexistent script "
<< npc.mScript << ", ignoring it.";
npc.mScript = ESM::RefId();
changed = true;
}
if (changed) if (changed)
npcsToReplace.push_back(npc); npcsToReplace.push_back(npc);
} }
@ -138,9 +147,9 @@ namespace
{ {
if (!item.mScript.empty() && !scripts.search(item.mScript)) if (!item.mScript.empty() && !scripts.search(item.mScript))
{ {
Log(Debug::Verbose) << MapT::mapped_type::getRecordType() << ' ' << id << " (" << item.mName
<< ") has nonexistent script " << item.mScript << ", ignoring it.";
item.mScript = ESM::RefId(); item.mScript = ESM::RefId();
Log(Debug::Verbose) << "Item " << id << " (" << item.mName << ") has nonexistent script "
<< item.mScript << ", ignoring it.";
} }
} }
} }
@ -517,8 +526,8 @@ namespace MWWorld
void ESMStore::validate() void ESMStore::validate()
{ {
auto& npcs = getWritable<ESM::NPC>(); auto& npcs = getWritable<ESM::NPC>();
std::vector<ESM::NPC> npcsToReplace std::vector<ESM::NPC> npcsToReplace = getNPCsToReplace(
= getNPCsToReplace(getWritable<ESM::Faction>(), getWritable<ESM::Class>(), npcs.mStatic); getWritable<ESM::Faction>(), getWritable<ESM::Class>(), getWritable<ESM::Script>(), npcs.mStatic);
for (const ESM::NPC& npc : npcsToReplace) for (const ESM::NPC& npc : npcsToReplace)
{ {
@ -526,6 +535,8 @@ namespace MWWorld
npcs.insertStatic(npc); npcs.insertStatic(npc);
} }
removeMissingScripts(getWritable<ESM::Script>(), getWritable<ESM::Creature>().mStatic);
// Validate spell effects for invalid arguments // Validate spell effects for invalid arguments
std::vector<ESM::Spell> spellsToReplace; std::vector<ESM::Spell> spellsToReplace;
auto& spells = getWritable<ESM::Spell>(); auto& spells = getWritable<ESM::Spell>();
@ -605,8 +616,8 @@ namespace MWWorld
auto& npcs = getWritable<ESM::NPC>(); auto& npcs = getWritable<ESM::NPC>();
auto& scripts = getWritable<ESM::Script>(); auto& scripts = getWritable<ESM::Script>();
std::vector<ESM::NPC> npcsToReplace std::vector<ESM::NPC> npcsToReplace = getNPCsToReplace(
= getNPCsToReplace(getWritable<ESM::Faction>(), getWritable<ESM::Class>(), npcs.mDynamic); getWritable<ESM::Faction>(), getWritable<ESM::Class>(), getWritable<ESM::Script>(), npcs.mDynamic);
for (const ESM::NPC& npc : npcsToReplace) for (const ESM::NPC& npc : npcsToReplace)
npcs.insert(npc); npcs.insert(npc);
@ -614,6 +625,7 @@ namespace MWWorld
removeMissingScripts(scripts, getWritable<ESM::Armor>().mDynamic); removeMissingScripts(scripts, getWritable<ESM::Armor>().mDynamic);
removeMissingScripts(scripts, getWritable<ESM::Book>().mDynamic); removeMissingScripts(scripts, getWritable<ESM::Book>().mDynamic);
removeMissingScripts(scripts, getWritable<ESM::Clothing>().mDynamic); removeMissingScripts(scripts, getWritable<ESM::Clothing>().mDynamic);
removeMissingScripts(scripts, getWritable<ESM::Creature>().mDynamic);
removeMissingScripts(scripts, getWritable<ESM::Weapon>().mDynamic); removeMissingScripts(scripts, getWritable<ESM::Weapon>().mDynamic);
removeMissingObjects(getWritable<ESM::CreatureLevList>()); removeMissingObjects(getWritable<ESM::CreatureLevList>());

Loading…
Cancel
Save