Only check for spelllist/equipment changes in the update loop

This commit is contained in:
Evil Eye 2025-07-13 11:18:15 +02:00
parent 2dbe30ed5c
commit c80b3d26b9

View File

@ -79,6 +79,7 @@ namespace MWMechanics
bool mUpdatedHitOverlay = false; bool mUpdatedHitOverlay = false;
bool mUpdateSpellWindow = false; bool mUpdateSpellWindow = false;
bool mPlayNonLooping = false; bool mPlayNonLooping = false;
bool mEraseRemoved = false;
bool mUpdate; bool mUpdate;
UpdateContext(bool update) UpdateContext(bool update)
@ -327,6 +328,7 @@ namespace MWMechanics
const MWWorld::Ptr player = MWMechanics::getPlayer(); const MWWorld::Ptr player = MWMechanics::getPlayer();
// Update effects // Update effects
context.mEraseRemoved = true;
for (auto spellIt = mSpells.begin(); spellIt != mSpells.end();) for (auto spellIt = mSpells.begin(); spellIt != mSpells.end();)
{ {
updateActiveSpell(ptr, duration, spellIt, context); updateActiveSpell(ptr, duration, spellIt, context);
@ -411,45 +413,48 @@ namespace MWMechanics
if (removedSpell) if (removedSpell)
return true; return true;
bool remove = false; if (context.mEraseRemoved)
if (spellIt->hasFlag(ESM::ActiveSpells::Flag_SpellStore))
{ {
try bool remove = false;
if (spellIt->hasFlag(ESM::ActiveSpells::Flag_SpellStore))
{ {
auto& spells = ptr.getClass().getCreatureStats(ptr).getSpells(); try
remove = !spells.hasSpell(spellIt->mSourceSpellId);
}
catch (const std::runtime_error& e)
{
remove = true;
Log(Debug::Error) << "Removing active effect: " << e.what();
}
}
else if (spellIt->hasFlag(ESM::ActiveSpells::Flag_Equipment))
{
// Remove effects tied to equipment that has been unequipped
const auto& store = ptr.getClass().getInventoryStore(ptr);
remove = true;
for (int slotIndex = 0; slotIndex < MWWorld::InventoryStore::Slots; slotIndex++)
{
auto slot = store.getSlot(slotIndex);
if (slot != store.end() && slot->getCellRef().getRefNum().isSet()
&& slot->getCellRef().getRefNum() == spellIt->mItem)
{ {
remove = false; auto& spells = ptr.getClass().getCreatureStats(ptr).getSpells();
break; remove = !spells.hasSpell(spellIt->mSourceSpellId);
}
catch (const std::runtime_error& e)
{
remove = true;
Log(Debug::Error) << "Removing active effect: " << e.what();
} }
} }
} else if (spellIt->hasFlag(ESM::ActiveSpells::Flag_Equipment))
if (remove) {
{ // Remove effects tied to equipment that has been unequipped
auto params = *spellIt; const auto& store = ptr.getClass().getInventoryStore(ptr);
spellIt = mSpells.erase(spellIt); remove = true;
for (const auto& effect : params.mEffects) for (int slotIndex = 0; slotIndex < MWWorld::InventoryStore::Slots; slotIndex++)
onMagicEffectRemoved(ptr, params, effect); {
applyPurges(ptr, &spellIt); auto slot = store.getSlot(slotIndex);
context.mUpdateSpellWindow = true; if (slot != store.end() && slot->getCellRef().getRefNum().isSet()
return true; && slot->getCellRef().getRefNum() == spellIt->mItem)
{
remove = false;
break;
}
}
}
if (remove)
{
auto params = *spellIt;
spellIt = mSpells.erase(spellIt);
for (const auto& effect : params.mEffects)
onMagicEffectRemoved(ptr, params, effect);
applyPurges(ptr, &spellIt);
context.mUpdateSpellWindow = true;
return true;
}
} }
++spellIt; ++spellIt;
return false; return false;