From 5b18edf938626c7e342500f52ffea61edfce2542 Mon Sep 17 00:00:00 2001 From: Alexei Kotov Date: Wed, 5 Mar 2025 19:55:21 +0300 Subject: [PATCH 1/2] Interrupt bound item effect if equipment failed (#8383) --- apps/openmw/mwmechanics/spelleffects.cpp | 42 ++++++++++++++---------- 1 file changed, 25 insertions(+), 17 deletions(-) diff --git a/apps/openmw/mwmechanics/spelleffects.cpp b/apps/openmw/mwmechanics/spelleffects.cpp index 7035c7f61c..c5af5f2bae 100644 --- a/apps/openmw/mwmechanics/spelleffects.cpp +++ b/apps/openmw/mwmechanics/spelleffects.cpp @@ -174,7 +174,7 @@ namespace return -1; } - void addBoundItem(const ESM::RefId& itemId, const MWWorld::Ptr& actor) + bool addBoundItem(const ESM::RefId& itemId, const MWWorld::Ptr& actor) { MWWorld::InventoryStore& store = actor.getClass().getInventoryStore(actor); MWWorld::Ptr boundPtr = *store.MWWorld::ContainerStore::add(itemId, 1); @@ -185,9 +185,6 @@ namespace MWWorld::ActionEquip action(boundPtr); action.execute(actor); - if (actor != MWMechanics::getPlayer()) - return; - MWWorld::Ptr newItem; auto it = slot >= 0 ? store.getSlot(slot) : store.end(); // Equip can fail because beast races cannot equip boots/helmets @@ -195,16 +192,24 @@ namespace newItem = *it; if (newItem.isEmpty() || boundPtr != newItem) - return; + { + store.remove(boundPtr, 1); + return false; + } - MWWorld::Player& player = MWBase::Environment::get().getWorld()->getPlayer(); + if (actor == MWMechanics::getPlayer()) + { + MWWorld::Player& player = MWBase::Environment::get().getWorld()->getPlayer(); - // change draw state only if the item is in player's right hand - if (slot == MWWorld::InventoryStore::Slot_CarriedRight) - player.setDrawState(MWMechanics::DrawState::Weapon); + // change draw state only if the item is in player's right hand + if (slot == MWWorld::InventoryStore::Slot_CarriedRight) + player.setDrawState(MWMechanics::DrawState::Weapon); - if (prevItem != store.end()) - player.setPreviousItem(itemId, prevItem->getCellRef().getRefId()); + if (prevItem != store.end()) + player.setPreviousItem(itemId, prevItem->getCellRef().getRefId()); + } + + return true; } void removeBoundItem(const ESM::RefId& itemId, const MWWorld::Ptr& actor) @@ -626,16 +631,19 @@ namespace MWMechanics case ESM::MagicEffect::BoundHelm: case ESM::MagicEffect::BoundBoots: case ESM::MagicEffect::BoundShield: + { if (!target.getClass().hasInventoryStore(target)) - invalid = true; - else { - const std::string& item = sBoundItemsMap.at(effect.mEffectId); - addBoundItem(ESM::RefId::stringRefId( - world->getStore().get().find(item)->mValue.getString()), - target); + invalid = true; + break; } + const std::string& item = sBoundItemsMap.at(effect.mEffectId); + const MWWorld::Store& gmst = world->getStore().get(); + const ESM::RefId itemId = ESM::RefId::stringRefId(gmst.find(item)->mValue.getString()); + if (!addBoundItem(itemId, target)) + invalid = true; break; + } case ESM::MagicEffect::FireDamage: case ESM::MagicEffect::ShockDamage: case ESM::MagicEffect::FrostDamage: From 918a6352e4ce3098a59ea06d69431676aecfbbf4 Mon Sep 17 00:00:00 2001 From: Alexei Kotov Date: Wed, 5 Mar 2025 23:43:35 +0300 Subject: [PATCH 2/2] Let cancelled bound item effect remain active for the frame --- apps/openmw/mwmechanics/spelleffects.cpp | 5 +---- 1 file changed, 1 insertion(+), 4 deletions(-) diff --git a/apps/openmw/mwmechanics/spelleffects.cpp b/apps/openmw/mwmechanics/spelleffects.cpp index c5af5f2bae..91e24f946f 100644 --- a/apps/openmw/mwmechanics/spelleffects.cpp +++ b/apps/openmw/mwmechanics/spelleffects.cpp @@ -192,10 +192,7 @@ namespace newItem = *it; if (newItem.isEmpty() || boundPtr != newItem) - { - store.remove(boundPtr, 1); return false; - } if (actor == MWMechanics::getPlayer()) { @@ -641,7 +638,7 @@ namespace MWMechanics const MWWorld::Store& gmst = world->getStore().get(); const ESM::RefId itemId = ESM::RefId::stringRefId(gmst.find(item)->mValue.getString()); if (!addBoundItem(itemId, target)) - invalid = true; + effect.mTimeLeft = 0.f; break; } case ESM::MagicEffect::FireDamage: