1
0
Fork 0
mirror of https://github.com/OpenMW/openmw.git synced 2025-12-24 05:23:07 +00:00

Merge branch 'topurgeornottopurge' into 'master'

Improve parity around spell store based effects

Closes #8309

See merge request OpenMW/openmw!4827
This commit is contained in:
psi29a 2025-08-12 07:48:41 +00:00
commit 8f8723e2fc
4 changed files with 46 additions and 20 deletions

View file

@ -507,7 +507,7 @@ Ubuntu_Clang_tests_Debug:
stage: test stage: test
variables: variables:
PIP_CACHE_DIR: "$CI_PROJECT_DIR/.cache/pip" PIP_CACHE_DIR: "$CI_PROJECT_DIR/.cache/pip"
EXAMPLE_SUITE_REVISION: 599987b52bd2d064e26299d3317b11049499f32b EXAMPLE_SUITE_REVISION: 3e01d10e073474a886a9efe3658088db14869627
cache: cache:
paths: paths:
- .cache/pip - .cache/pip

View file

@ -241,7 +241,25 @@ namespace MWMechanics
// Erase no longer active spells and effects // Erase no longer active spells and effects
for (auto spellIt = mSpells.begin(); spellIt != mSpells.end();) for (auto spellIt = mSpells.begin(); spellIt != mSpells.end();)
{ {
if (!spellIt->hasFlag(ESM::ActiveSpells::Flag_Temporary)) if (spellIt->hasFlag(ESM::ActiveSpells::Flag_SpellStore))
{
const ESM::Spell* spell
= MWBase::Environment::get().getESMStore()->get<ESM::Spell>().search(spellIt->mSourceSpellId);
if (spell && ptr.getClass().getCreatureStats(ptr).getSpells().hasSpell(spell))
++spellIt;
else
{
if (spell == nullptr)
Log(Debug::Error) << "Dropping non-existent active effect: " << spellIt->mSourceSpellId;
auto params = *spellIt;
spellIt = mSpells.erase(spellIt);
for (const auto& effect : params.mEffects)
onMagicEffectRemoved(ptr, params, effect);
applyPurges(ptr, &spellIt);
}
continue;
}
else if (!spellIt->hasFlag(ESM::ActiveSpells::Flag_Temporary))
{ {
++spellIt; ++spellIt;
continue; continue;
@ -416,20 +434,7 @@ namespace MWMechanics
if (context.mEraseRemoved) if (context.mEraseRemoved)
{ {
bool remove = false; bool remove = false;
if (spellIt->hasFlag(ESM::ActiveSpells::Flag_SpellStore)) if (spellIt->hasFlag(ESM::ActiveSpells::Flag_Equipment))
{
try
{
auto& spells = ptr.getClass().getCreatureStats(ptr).getSpells();
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 // Remove effects tied to equipment that has been unequipped
const auto& store = ptr.getClass().getInventoryStore(ptr); const auto& store = ptr.getClass().getInventoryStore(ptr);

View file

@ -398,6 +398,23 @@ namespace
{ ESM::MagicEffect::BoundShield, "sMagicBoundShieldID" }, { ESM::MagicEffect::BoundShield, "sMagicBoundShieldID" },
{ ESM::MagicEffect::BoundSpear, "sMagicBoundSpearID" }, { ESM::MagicEffect::BoundSpear, "sMagicBoundSpearID" },
}; };
using SpellsPurge = void (MWMechanics::Spells::*)();
void purgePermanent(const MWWorld::Ptr& target, SpellsPurge method, ESM::Spell::SpellType type)
{
MWMechanics::CreatureStats& stats = target.getClass().getCreatureStats(target);
(stats.getSpells().*method)();
stats.getActiveSpells().purge(
[type](const MWMechanics::ActiveSpells::ActiveSpellParams& params) {
if (params.hasFlag(ESM::ActiveSpells::Flag_SpellStore))
{
const ESM::Spell* spell = params.getSpell();
return spell && spell->mData.mType == type;
}
return false;
},
target);
}
} }
namespace MWMechanics namespace MWMechanics
@ -412,13 +429,13 @@ namespace MWMechanics
switch (effect.mEffectId) switch (effect.mEffectId)
{ {
case ESM::MagicEffect::CureCommonDisease: case ESM::MagicEffect::CureCommonDisease:
target.getClass().getCreatureStats(target).getSpells().purgeCommonDisease(); purgePermanent(target, &Spells::purgeCommonDisease, ESM::Spell::ST_Disease);
break; break;
case ESM::MagicEffect::CureBlightDisease: case ESM::MagicEffect::CureBlightDisease:
target.getClass().getCreatureStats(target).getSpells().purgeBlightDisease(); purgePermanent(target, &Spells::purgeBlightDisease, ESM::Spell::ST_Blight);
break; break;
case ESM::MagicEffect::RemoveCurse: case ESM::MagicEffect::RemoveCurse:
target.getClass().getCreatureStats(target).getSpells().purgeCurses(); purgePermanent(target, &Spells::purgeCurses, ESM::Spell::ST_Curse);
break; break;
case ESM::MagicEffect::CureCorprusDisease: case ESM::MagicEffect::CureCorprusDisease:
target.getClass().getCreatureStats(target).getActiveSpells().purgeEffect( target.getClass().getCreatureStats(target).getActiveSpells().purgeEffect(

View file

@ -537,7 +537,11 @@ namespace MWScript
return; return;
MWMechanics::CreatureStats& creatureStats = ptr.getClass().getCreatureStats(ptr); MWMechanics::CreatureStats& creatureStats = ptr.getClass().getCreatureStats(ptr);
creatureStats.getSpells().remove(id); const ESM::Spell* spell = MWBase::Environment::get().getESMStore()->get<ESM::Spell>().find(id);
creatureStats.getSpells().remove(spell);
if (spell->mData.mType == ESM::Spell::ST_Ability || spell->mData.mType == ESM::Spell::ST_Blight
|| spell->mData.mType == ESM::Spell::ST_Curse || spell->mData.mType == ESM::Spell::ST_Disease)
creatureStats.getActiveSpells().removeEffectsBySourceSpellId(ptr, id);
MWBase::WindowManager* wm = MWBase::Environment::get().getWindowManager(); MWBase::WindowManager* wm = MWBase::Environment::get().getWindowManager();