From 589fbbd8718f27926cf67365be6e85f9616e0e55 Mon Sep 17 00:00:00 2001 From: scrawl Date: Sun, 19 Jan 2014 11:42:58 +0100 Subject: [PATCH] Issue #777: Create InventoryStore for creatures with weapons/shields --- apps/openmw/mwclass/armor.cpp | 27 +++++----- apps/openmw/mwclass/clothing.cpp | 25 +++++---- apps/openmw/mwclass/creature.cpp | 52 +++++++++++++++---- apps/openmw/mwclass/creature.hpp | 5 ++ apps/openmw/mwclass/npc.hpp | 2 + apps/openmw/mwdialogue/dialoguemanagerimp.cpp | 2 +- apps/openmw/mwgui/companionitemmodel.cpp | 4 +- apps/openmw/mwgui/inventoryitemmodel.cpp | 4 +- apps/openmw/mwgui/tradeitemmodel.cpp | 2 +- apps/openmw/mwgui/tradewindow.cpp | 5 +- apps/openmw/mwmechanics/actors.cpp | 3 +- .../mwmechanics/mechanicsmanagerimp.cpp | 4 +- apps/openmw/mwrender/actors.cpp | 3 -- apps/openmw/mwrender/characterpreview.cpp | 2 +- apps/openmw/mwrender/renderingmanager.cpp | 2 - apps/openmw/mwscript/containerextensions.cpp | 2 +- apps/openmw/mwworld/actionequip.cpp | 4 +- apps/openmw/mwworld/class.cpp | 5 ++ apps/openmw/mwworld/class.hpp | 3 ++ apps/openmw/mwworld/containerstore.hpp | 2 + apps/openmw/mwworld/inventorystore.cpp | 4 +- apps/openmw/mwworld/inventorystore.hpp | 2 + apps/openmw/mwworld/worldimp.cpp | 9 ++-- 23 files changed, 111 insertions(+), 62 deletions(-) diff --git a/apps/openmw/mwclass/armor.cpp b/apps/openmw/mwclass/armor.cpp index 5e37426c9..83bda25d1 100644 --- a/apps/openmw/mwclass/armor.cpp +++ b/apps/openmw/mwclass/armor.cpp @@ -289,7 +289,7 @@ namespace MWClass std::pair Armor::canBeEquipped(const MWWorld::Ptr &ptr, const MWWorld::Ptr &npc) const { - MWWorld::InventoryStore& invStore = MWWorld::Class::get(npc).getInventoryStore(npc); + MWWorld::InventoryStore& invStore = npc.getClass().getInventoryStore(npc); if (ptr.getCellRef().mCharge == 0) return std::make_pair(0, "#{sInventoryMessage1}"); @@ -300,20 +300,23 @@ namespace MWClass if (slots_.first.empty()) return std::make_pair(0, ""); - std::string npcRace = npc.get()->mBase->mRace; - - // Beast races cannot equip shoes / boots, or full helms (head part vs hair part) - const ESM::Race* race = MWBase::Environment::get().getWorld()->getStore().get().find(npcRace); - if(race->mData.mFlags & ESM::Race::Beast) + if (npc.getClass().isNpc()) { - std::vector parts = ptr.get()->mBase->mParts.mParts; + std::string npcRace = npc.get()->mBase->mRace; - for(std::vector::iterator itr = parts.begin(); itr != parts.end(); ++itr) + // Beast races cannot equip shoes / boots, or full helms (head part vs hair part) + const ESM::Race* race = MWBase::Environment::get().getWorld()->getStore().get().find(npcRace); + if(race->mData.mFlags & ESM::Race::Beast) { - if((*itr).mPart == ESM::PRT_Head) - return std::make_pair(0, "#{sNotifyMessage13}"); - if((*itr).mPart == ESM::PRT_LFoot || (*itr).mPart == ESM::PRT_RFoot) - return std::make_pair(0, "#{sNotifyMessage14}"); + std::vector parts = ptr.get()->mBase->mParts.mParts; + + for(std::vector::iterator itr = parts.begin(); itr != parts.end(); ++itr) + { + if((*itr).mPart == ESM::PRT_Head) + return std::make_pair(0, "#{sNotifyMessage13}"); + if((*itr).mPart == ESM::PRT_LFoot || (*itr).mPart == ESM::PRT_RFoot) + return std::make_pair(0, "#{sNotifyMessage14}"); + } } } diff --git a/apps/openmw/mwclass/clothing.cpp b/apps/openmw/mwclass/clothing.cpp index 62fc26a71..a135585eb 100644 --- a/apps/openmw/mwclass/clothing.cpp +++ b/apps/openmw/mwclass/clothing.cpp @@ -238,20 +238,23 @@ namespace MWClass if (slots_.first.empty()) return std::make_pair(0, ""); - std::string npcRace = npc.get()->mBase->mRace; - - // Beast races cannot equip shoes / boots, or full helms (head part vs hair part) - const ESM::Race* race = MWBase::Environment::get().getWorld()->getStore().get().find(npcRace); - if(race->mData.mFlags & ESM::Race::Beast) + if (npc.getClass().isNpc()) { - std::vector parts = ptr.get()->mBase->mParts.mParts; + std::string npcRace = npc.get()->mBase->mRace; - for(std::vector::iterator itr = parts.begin(); itr != parts.end(); ++itr) + // Beast races cannot equip shoes / boots, or full helms (head part vs hair part) + const ESM::Race* race = MWBase::Environment::get().getWorld()->getStore().get().find(npcRace); + if(race->mData.mFlags & ESM::Race::Beast) { - if((*itr).mPart == ESM::PRT_Head) - return std::make_pair(0, "#{sNotifyMessage13}"); - if((*itr).mPart == ESM::PRT_LFoot || (*itr).mPart == ESM::PRT_RFoot) - return std::make_pair(0, "#{sNotifyMessage15}"); + std::vector parts = ptr.get()->mBase->mParts.mParts; + + for(std::vector::iterator itr = parts.begin(); itr != parts.end(); ++itr) + { + if((*itr).mPart == ESM::PRT_Head) + return std::make_pair(0, "#{sNotifyMessage13}"); + if((*itr).mPart == ESM::PRT_LFoot || (*itr).mPart == ESM::PRT_RFoot) + return std::make_pair(0, "#{sNotifyMessage15}"); + } } } diff --git a/apps/openmw/mwclass/creature.cpp b/apps/openmw/mwclass/creature.cpp index a97268318..1a8f7b5c7 100644 --- a/apps/openmw/mwclass/creature.cpp +++ b/apps/openmw/mwclass/creature.cpp @@ -26,6 +26,8 @@ #include "../mwgui/tooltips.hpp" +#include "../mwworld/inventorystore.hpp" + #include "../mwmechanics/npcstats.hpp" namespace @@ -33,15 +35,20 @@ namespace struct CustomData : public MWWorld::CustomData { MWMechanics::CreatureStats mCreatureStats; - MWWorld::ContainerStore mContainerStore; + MWWorld::ContainerStore* mContainerStore; // may be InventoryStore for some creatures MWMechanics::Movement mMovement; virtual MWWorld::CustomData *clone() const; + + CustomData() : mContainerStore(0) {} + virtual ~CustomData() { delete mContainerStore; } }; MWWorld::CustomData *CustomData::clone() const { - return new CustomData (*this); + CustomData* cloned = new CustomData (*this); + cloned->mContainerStore = mContainerStore->clone(); + return cloned; } } @@ -106,15 +113,23 @@ namespace MWClass data->mCreatureStats.getSpells().add (*iter); // inventory - data->mContainerStore.fill(ref->mBase->mInventory, getId(ptr), "", + if (ref->mBase->mFlags & ESM::Creature::Weapon) + data->mContainerStore = new MWWorld::InventoryStore(); + else + data->mContainerStore = new MWWorld::ContainerStore(); + + // store + ptr.getRefData().setCustomData (data.release()); + + getContainerStore(ptr).fill(ref->mBase->mInventory, getId(ptr), "", MWBase::Environment::get().getWorld()->getStore()); // TODO: this is not quite correct, in vanilla the merchant's gold pool is not available in his inventory. // (except for gold you gave him) - data->mContainerStore.add(MWWorld::ContainerStore::sGoldId, ref->mBase->mData.mGold, ptr); + getContainerStore(ptr).add(MWWorld::ContainerStore::sGoldId, ref->mBase->mData.mGold, ptr); - // store - ptr.getRefData().setCustomData (data.release()); + if (ref->mBase->mFlags & ESM::Creature::Weapon) + getInventoryStore(ptr).autoEquip(ptr); } } @@ -325,18 +340,33 @@ namespace MWClass return boost::shared_ptr(new MWWorld::ActionTalk(ptr)); } - MWWorld::ContainerStore& Creature::getContainerStore (const MWWorld::Ptr& ptr) - const + MWWorld::ContainerStore& Creature::getContainerStore (const MWWorld::Ptr& ptr) const { ensureCustomData (ptr); - return dynamic_cast (*ptr.getRefData().getCustomData()).mContainerStore; + return *dynamic_cast (*ptr.getRefData().getCustomData()).mContainerStore; + } + + MWWorld::InventoryStore& Creature::getInventoryStore(const MWWorld::Ptr &ptr) const + { + MWWorld::LiveCellRef *ref = ptr.get(); + + if (ref->mBase->mFlags & ESM::Creature::Weapon) + return dynamic_cast(getContainerStore(ptr)); + else + throw std::runtime_error("this creature has no inventory store"); + } + + bool Creature::hasInventoryStore(const MWWorld::Ptr &ptr) const + { + MWWorld::LiveCellRef *ref = ptr.get(); + + return (ref->mBase->mFlags & ESM::Creature::Weapon); } std::string Creature::getScript (const MWWorld::Ptr& ptr) const { - MWWorld::LiveCellRef *ref = - ptr.get(); + MWWorld::LiveCellRef *ref = ptr.get(); return ref->mBase->mScript; } diff --git a/apps/openmw/mwclass/creature.hpp b/apps/openmw/mwclass/creature.hpp index d518d0056..cfa06ed62 100644 --- a/apps/openmw/mwclass/creature.hpp +++ b/apps/openmw/mwclass/creature.hpp @@ -68,6 +68,11 @@ namespace MWClass const MWWorld::Ptr& ptr) const; ///< Return container store + virtual MWWorld::InventoryStore& getInventoryStore (const MWWorld::Ptr& ptr) const; + ///< Return inventory store + + virtual bool hasInventoryStore (const MWWorld::Ptr &ptr) const; + virtual std::string getScript (const MWWorld::Ptr& ptr) const; ///< Return name of the script attached to ptr diff --git a/apps/openmw/mwclass/npc.hpp b/apps/openmw/mwclass/npc.hpp index 497d0ced8..e658dde5f 100644 --- a/apps/openmw/mwclass/npc.hpp +++ b/apps/openmw/mwclass/npc.hpp @@ -71,6 +71,8 @@ namespace MWClass virtual MWWorld::InventoryStore& getInventoryStore (const MWWorld::Ptr& ptr) const; ///< Return inventory store + virtual bool hasInventoryStore(const MWWorld::Ptr &ptr) const { return true; } + virtual void hit(const MWWorld::Ptr& ptr, int type) const; virtual void onHit(const MWWorld::Ptr &ptr, float damage, bool ishealth, const MWWorld::Ptr &object, const MWWorld::Ptr &attacker, bool successful) const; diff --git a/apps/openmw/mwdialogue/dialoguemanagerimp.cpp b/apps/openmw/mwdialogue/dialoguemanagerimp.cpp index b2107c329..263c101e5 100644 --- a/apps/openmw/mwdialogue/dialoguemanagerimp.cpp +++ b/apps/openmw/mwdialogue/dialoguemanagerimp.cpp @@ -420,7 +420,7 @@ namespace MWDialogue MWBase::Environment::get().getWindowManager()->removeGuiMode(MWGui::GM_Dialogue); // Apply disposition change to NPC's base disposition - if (mActor.getTypeName() == typeid(ESM::NPC).name()) + if (mActor.getClass().isNpc()) { MWMechanics::NpcStats& npcStats = MWWorld::Class::get(mActor).getNpcStats(mActor); npcStats.setBaseDisposition(npcStats.getBaseDisposition() + mPermanentDispositionChange); diff --git a/apps/openmw/mwgui/companionitemmodel.cpp b/apps/openmw/mwgui/companionitemmodel.cpp index 3212ed701..bb6cf2800 100644 --- a/apps/openmw/mwgui/companionitemmodel.cpp +++ b/apps/openmw/mwgui/companionitemmodel.cpp @@ -12,7 +12,7 @@ namespace MWGui void CompanionItemModel::copyItem (const ItemStack& item, size_t count) { - if (mActor.getTypeName() == typeid(ESM::NPC).name()) + if (mActor.getClass().isNpc()) { MWMechanics::NpcStats& stats = MWWorld::Class::get(mActor).getNpcStats(mActor); stats.modifyProfit(MWWorld::Class::get(item.mBase).getValue(item.mBase) * count); @@ -23,7 +23,7 @@ namespace MWGui void CompanionItemModel::removeItem (const ItemStack& item, size_t count) { - if (mActor.getTypeName() == typeid(ESM::NPC).name()) + if (mActor.getClass().isNpc()) { MWMechanics::NpcStats& stats = MWWorld::Class::get(mActor).getNpcStats(mActor); stats.modifyProfit(-MWWorld::Class::get(item.mBase).getValue(item.mBase) * count); diff --git a/apps/openmw/mwgui/inventoryitemmodel.cpp b/apps/openmw/mwgui/inventoryitemmodel.cpp index d26feba88..97e1e9a2b 100644 --- a/apps/openmw/mwgui/inventoryitemmodel.cpp +++ b/apps/openmw/mwgui/inventoryitemmodel.cpp @@ -74,9 +74,9 @@ void InventoryItemModel::update() ItemStack newItem (item, this, item.getRefData().getCount()); - if (mActor.getTypeName() == typeid(ESM::NPC).name()) + if (mActor.getClass().hasInventoryStore(mActor)) { - MWWorld::InventoryStore& store = MWWorld::Class::get(mActor).getInventoryStore(mActor); + MWWorld::InventoryStore& store = mActor.getClass().getInventoryStore(mActor); for (int slot=0; slot(0,std::min(int(MWBase::Environment::get().getMechanicsManager()->getDerivedDisposition(mPtr) + MWBase::Environment::get().getDialogueManager()->getTemporaryDispositionChange()),100)); - const MWMechanics::NpcStats &sellerStats = mPtr.getClass().getNpcStats(mPtr); - const MWMechanics::NpcStats &playerStats = player.getClass().getNpcStats(player); + const MWMechanics::CreatureStats &sellerStats = mPtr.getClass().getCreatureStats(mPtr); + const MWMechanics::CreatureStats &playerStats = player.getClass().getCreatureStats(player); float a1 = std::min(player.getClass().getSkill(player, ESM::Skill::Mercantile), 100); float b1 = std::min(0.1f * playerStats.getAttribute(ESM::Attribute::Luck).getModified(), 10.f); diff --git a/apps/openmw/mwmechanics/actors.cpp b/apps/openmw/mwmechanics/actors.cpp index 1b65b1472..3daecbe1c 100644 --- a/apps/openmw/mwmechanics/actors.cpp +++ b/apps/openmw/mwmechanics/actors.cpp @@ -47,8 +47,7 @@ void adjustBoundItem (const std::string& item, bool bound, const MWWorld::Ptr& a bool disintegrateSlot (MWWorld::Ptr ptr, int slot, float disintegrate) { - // TODO: remove this check once creatures support inventory store - if (ptr.getTypeName() == typeid(ESM::NPC).name()) + if (ptr.getClass().hasInventoryStore(ptr)) { MWWorld::InventoryStore& inv = ptr.getClass().getInventoryStore(ptr); MWWorld::ContainerStoreIterator item = diff --git a/apps/openmw/mwmechanics/mechanicsmanagerimp.cpp b/apps/openmw/mwmechanics/mechanicsmanagerimp.cpp index 0dee4706a..fff3db8a9 100644 --- a/apps/openmw/mwmechanics/mechanicsmanagerimp.cpp +++ b/apps/openmw/mwmechanics/mechanicsmanagerimp.cpp @@ -196,8 +196,8 @@ namespace MWMechanics creatureStats.setDynamic (i, stat); } - // auto-equip again. we need this for when the race is changed to a beast race - MWWorld::InventoryStore& invStore = MWWorld::Class::get(ptr).getInventoryStore(ptr); + // auto-equip again. we need this for when the race is changed to a beast race and shoes are no longer equippable + MWWorld::InventoryStore& invStore = ptr.getClass().getInventoryStore(ptr); for (int i=0; iaddWaterRippleEmitter (ptr); - - // Create CustomData, will do autoEquip and trigger animation parts update - ptr.getClass().getInventoryStore(ptr); } void Actors::insertCreature (const MWWorld::Ptr& ptr) { diff --git a/apps/openmw/mwrender/characterpreview.cpp b/apps/openmw/mwrender/characterpreview.cpp index 2dbc72e26..32145928e 100644 --- a/apps/openmw/mwrender/characterpreview.cpp +++ b/apps/openmw/mwrender/characterpreview.cpp @@ -142,7 +142,7 @@ namespace MWRender { mAnimation->updateParts(); - MWWorld::InventoryStore &inv = MWWorld::Class::get(mCharacter).getInventoryStore(mCharacter); + MWWorld::InventoryStore &inv = mCharacter.getClass().getInventoryStore(mCharacter); MWWorld::ContainerStoreIterator iter = inv.getSlot(MWWorld::InventoryStore::Slot_CarriedRight); std::string groupname; if(iter == inv.end()) diff --git a/apps/openmw/mwrender/renderingmanager.cpp b/apps/openmw/mwrender/renderingmanager.cpp index 8a2ab1c7a..572d2abdb 100644 --- a/apps/openmw/mwrender/renderingmanager.cpp +++ b/apps/openmw/mwrender/renderingmanager.cpp @@ -892,8 +892,6 @@ void RenderingManager::renderPlayer(const MWWorld::Ptr &ptr) mPlayerAnimation->~NpcAnimation(); new(mPlayerAnimation) NpcAnimation(ptr, ptr.getRefData().getBaseNode(), RV_Actors); } - // Ensure CustomData -> autoEquip -> animation update - ptr.getClass().getInventoryStore(ptr); mCamera->setAnimation(mPlayerAnimation); mWater->removeEmitter(ptr); diff --git a/apps/openmw/mwscript/containerextensions.cpp b/apps/openmw/mwscript/containerextensions.cpp index 6674481f2..e06505e86 100644 --- a/apps/openmw/mwscript/containerextensions.cpp +++ b/apps/openmw/mwscript/containerextensions.cpp @@ -159,7 +159,7 @@ namespace MWScript std::string item = runtime.getStringLiteral (runtime[0].mInteger); runtime.pop(); - MWWorld::InventoryStore& invStore = MWWorld::Class::get(ptr).getInventoryStore (ptr); + MWWorld::InventoryStore& invStore = ptr.getClass().getInventoryStore (ptr); MWWorld::ContainerStoreIterator it = invStore.begin(); for (; it != invStore.end(); ++it) { diff --git a/apps/openmw/mwworld/actionequip.cpp b/apps/openmw/mwworld/actionequip.cpp index d34773bd5..2a1b7a3aa 100644 --- a/apps/openmw/mwworld/actionequip.cpp +++ b/apps/openmw/mwworld/actionequip.cpp @@ -19,9 +19,9 @@ namespace MWWorld void ActionEquip::executeImp (const Ptr& actor) { MWWorld::Ptr object = getTarget(); - MWWorld::InventoryStore& invStore = MWWorld::Class::get(actor).getInventoryStore(actor); + MWWorld::InventoryStore& invStore = actor.getClass().getInventoryStore(actor); - std::pair result = MWWorld::Class::get (object).canBeEquipped (object, actor); + std::pair result = object.getClass().canBeEquipped (object, actor); // display error message if the player tried to equip something if (!result.second.empty() && actor == MWBase::Environment::get().getWorld()->getPlayerPtr()) diff --git a/apps/openmw/mwworld/class.cpp b/apps/openmw/mwworld/class.cpp index 6c00b949c..c7b0d2e1f 100644 --- a/apps/openmw/mwworld/class.cpp +++ b/apps/openmw/mwworld/class.cpp @@ -122,6 +122,11 @@ namespace MWWorld throw std::runtime_error ("class does not have an inventory store"); } + bool Class::hasInventoryStore(const Ptr &ptr) const + { + return false; + } + void Class::lock (const Ptr& ptr, int lockLevel) const { throw std::runtime_error ("class does not support locking"); diff --git a/apps/openmw/mwworld/class.hpp b/apps/openmw/mwworld/class.hpp index ec22d0306..823538cf8 100644 --- a/apps/openmw/mwworld/class.hpp +++ b/apps/openmw/mwworld/class.hpp @@ -150,6 +150,9 @@ namespace MWWorld ///< Return inventory store or throw an exception, if class does not have a /// inventory store (default implementation: throw an exceoption) + virtual bool hasInventoryStore (const Ptr& ptr) const; + ///< Does this object have an inventory store, i.e. equipment slots? (default implementation: false) + virtual void lock (const Ptr& ptr, int lockLevel) const; ///< Lock object (default implementation: throw an exception) diff --git a/apps/openmw/mwworld/containerstore.hpp b/apps/openmw/mwworld/containerstore.hpp index 0a1728740..913ec544a 100644 --- a/apps/openmw/mwworld/containerstore.hpp +++ b/apps/openmw/mwworld/containerstore.hpp @@ -62,6 +62,8 @@ namespace MWWorld virtual ~ContainerStore(); + virtual ContainerStore* clone() { return new ContainerStore(*this); } + ContainerStoreIterator begin (int mask = Type_All); ContainerStoreIterator end(); diff --git a/apps/openmw/mwworld/inventorystore.cpp b/apps/openmw/mwworld/inventorystore.cpp index 82b827e75..ea43314e6 100644 --- a/apps/openmw/mwworld/inventorystore.cpp +++ b/apps/openmw/mwworld/inventorystore.cpp @@ -81,7 +81,7 @@ MWWorld::ContainerStoreIterator MWWorld::InventoryStore::add(const Ptr& itemPtr, // Auto-equip items if an armor/clothing or weapon item is added, but not for the player nor werewolves if ((actorPtr.getRefData().getHandle() != "player") - && !(MWWorld::Class::get(actorPtr).getNpcStats(actorPtr).isWerewolf()) + && !(actorPtr.getClass().isNpc() && actorPtr.getClass().getNpcStats(actorPtr).isWerewolf()) && !actorPtr.getClass().getCreatureStats(actorPtr).isDead()) { std::string type = itemPtr.getTypeName(); @@ -457,7 +457,7 @@ int MWWorld::InventoryStore::remove(const Ptr& item, int count, const Ptr& actor // If an armor/clothing item is removed, try to find a replacement, // but not for the player nor werewolves. if ((actor.getRefData().getHandle() != "player") - && !(MWWorld::Class::get(actor).getNpcStats(actor).isWerewolf())) + && !(actor.getClass().isNpc() && actor.getClass().getNpcStats(actor).isWerewolf())) { std::string type = item.getTypeName(); if (((type == typeid(ESM::Armor).name()) || (type == typeid(ESM::Clothing).name())) diff --git a/apps/openmw/mwworld/inventorystore.hpp b/apps/openmw/mwworld/inventorystore.hpp index 067c8261e..d97bdf365 100644 --- a/apps/openmw/mwworld/inventorystore.hpp +++ b/apps/openmw/mwworld/inventorystore.hpp @@ -113,6 +113,8 @@ namespace MWWorld InventoryStore& operator= (const InventoryStore& store); + virtual InventoryStore* clone() { return new InventoryStore(*this); } + virtual ContainerStoreIterator add (const Ptr& itemPtr, int count, const Ptr& actorPtr, bool setOwner=false); ///< Add the item pointed to by \a ptr to this container. (Stacks automatically if needed) /// Auto-equip items if specific conditions are fulfilled (see the implementation). diff --git a/apps/openmw/mwworld/worldimp.cpp b/apps/openmw/mwworld/worldimp.cpp index 0d7802081..e6569a178 100644 --- a/apps/openmw/mwworld/worldimp.cpp +++ b/apps/openmw/mwworld/worldimp.cpp @@ -2097,7 +2097,6 @@ namespace MWWorld void World::castSpell(const Ptr &actor) { MWMechanics::CreatureStats& stats = actor.getClass().getCreatureStats(actor); - InventoryStore& inv = actor.getClass().getInventoryStore(actor); MWWorld::Ptr target = getFacedObject(); @@ -2111,9 +2110,11 @@ namespace MWWorld cast.cast(spell); } - else if (inv.getSelectedEnchantItem() != inv.end()) + else if (actor.getClass().hasInventoryStore(actor)) { - cast.cast(*inv.getSelectedEnchantItem()); + MWWorld::InventoryStore& inv = actor.getClass().getInventoryStore(actor); + if (inv.getSelectedEnchantItem() != inv.end()) + cast.cast(*inv.getSelectedEnchantItem()); } } @@ -2282,7 +2283,7 @@ namespace MWWorld void World::breakInvisibility(const Ptr &actor) { actor.getClass().getCreatureStats(actor).getActiveSpells().purgeEffect(ESM::MagicEffect::Invisibility); - if (actor.getClass().isNpc()) + if (actor.getClass().hasInventoryStore(actor)) actor.getClass().getInventoryStore(actor).purgeEffect(ESM::MagicEffect::Invisibility); }