diff --git a/apps/openmw/mwrender/npcanimation.cpp b/apps/openmw/mwrender/npcanimation.cpp index abf2264af..6e8640377 100644 --- a/apps/openmw/mwrender/npcanimation.cpp +++ b/apps/openmw/mwrender/npcanimation.cpp @@ -186,7 +186,9 @@ NpcAnimation::NpcAnimation(const MWWorld::Ptr& ptr, Ogre::SceneNode* node, int v mShowCarriedLeft(true), mFirstPersonOffset(0.f, 0.f, 0.f), mAlpha(1.f), - mNpcType(Type_Normal) + mNpcType(Type_Normal), + mUnequipping(false), + mFirstEquip(true) { mNpc = mPtr.get()->mBase; @@ -928,31 +930,78 @@ void NpcAnimation::applyAlpha(float alpha, Ogre::Entity *ent, NifOgre::ObjectSce } } -void NpcAnimation::equipmentChanged (const MWWorld::Ptr& actor, const MWWorld::Ptr& item, InventoryStoreListener::State state) +void NpcAnimation::equipmentChanged(const MWWorld::Ptr& actor, const MWWorld::Ptr& item, InventoryStoreListener::State state) { - if (actor.getRefData().getHandle() == "player" && !item.isEmpty()) + if (actor.getRefData().getHandle() == "player") { std::string soundId; - if (item.getTypeName() == typeid(ESM::Light).name()) - { - soundId = item.get()->mBase->mSound; - } + MWBase::SoundManager *sndMgr = MWBase::Environment::get().getSoundManager(); - if (!soundId.empty()) + if (state == InventoryStoreListener::EQUIP + || state == InventoryStoreListener::UNEQUIP) { - MWBase::SoundManager *sndMgr = MWBase::Environment::get().getSoundManager(); - - if (state == InventoryStoreListener::EQUIPPED) + if (item.getTypeName() == typeid(ESM::Light).name()) { - sndMgr->playSound3D(mPtr, soundId, 1.0f, 1.0f, MWBase::SoundManager::Play_TypeSfx, - MWBase::SoundManager::Play_Loop); + soundId = item.get()->mBase->mSound; } - else if (state == InventoryStoreListener::UNEQUIPPED) + + if (!soundId.empty()) { - sndMgr->stopSound3D(mPtr, soundId); + if (state == InventoryStoreListener::EQUIP) + { + sndMgr->playSound3D(mPtr, soundId, 1.0f, 1.0f, MWBase::SoundManager::Play_TypeSfx, + MWBase::SoundManager::Play_Loop); + } + else + { + sndMgr->stopSound3D(mPtr, soundId); + } } } + else if (state == InventoryStoreListener::AUTOEQUIP) + { + const MWWorld::Class &cls = mPtr.getClass(); + MWWorld::InventoryStore &inv = cls.getInventoryStore(mPtr); + for (int i = MWWorld::InventoryStore::Slot_Helmet; i < MWWorld::InventoryStore::Slots; ++i) + { + MWWorld::ContainerStoreIterator store = inv.getSlot(i); + + if (store != inv.end() && store->getTypeName() == typeid(ESM::Light).name()) + { + soundId = store->get()->mBase->mSound; + } + + if (!soundId.empty()) + { + sndMgr->playSound3D(mPtr, soundId, 1.0f, 1.0f, MWBase::SoundManager::Play_TypeSfx, + MWBase::SoundManager::Play_Loop); + } + } + } + } + + /** + * AUTOEQUIP is triggered just after setting listener (ie. when game is loaded from savegame), + * but not all things are initialized yet, so we have to check it (mFirstEquip variable) + * and skip one call to updateParts() method. + * + * Also call to updateParts() method will be called only once if inventory.unequipAll() + * was called (mUnequipping == true). + */ + if (state == InventoryStoreListener::UNEQUIPALL_BEGIN) + mUnequipping = true; + else if (state == InventoryStoreListener::UNEQUIPALL_END) + mUnequipping = false; + + if (!mUnequipping && !mFirstEquip) + { + updateParts(); + } + + if (mFirstEquip && state == InventoryStoreListener::AUTOEQUIP) + { + mFirstEquip = false; } } diff --git a/apps/openmw/mwrender/npcanimation.hpp b/apps/openmw/mwrender/npcanimation.hpp index a6e927fce..83f85abe0 100644 --- a/apps/openmw/mwrender/npcanimation.hpp +++ b/apps/openmw/mwrender/npcanimation.hpp @@ -51,7 +51,7 @@ public: class NpcAnimation : public Animation, public WeaponAnimation, public MWWorld::InventoryStoreListener { public: - virtual void equipmentChanged() { updateParts(); } + virtual void equipmentChanged(const MWWorld::Ptr& actor, const MWWorld::Ptr& item, InventoryStoreListener::State state); virtual void permanentEffectAdded(const ESM::MagicEffect *magicEffect, bool isNew, bool playSound); public: @@ -97,6 +97,8 @@ private: Ogre::SharedPtr mWeaponAnimationTime; float mAlpha; + bool mUnequipping; + bool mFirstEquip; void updateNpcBase(); @@ -114,10 +116,6 @@ private: void applyAlpha(float alpha, Ogre::Entity* ent, NifOgre::ObjectScenePtr scene); - /** - * Implementation of MWWorld::InventoryStoreListener equipmentChanged method - */ - void equipmentChanged (const MWWorld::Ptr& actor, const MWWorld::Ptr& item, InventoryStoreListener::State state); public: /** * @param ptr diff --git a/apps/openmw/mwworld/inventorystore.cpp b/apps/openmw/mwworld/inventorystore.cpp index 49db0025a..db58af32a 100644 --- a/apps/openmw/mwworld/inventorystore.cpp +++ b/apps/openmw/mwworld/inventorystore.cpp @@ -146,19 +146,18 @@ void MWWorld::InventoryStore::equip (int slot, const ContainerStoreIterator& ite flagAsModified(); - fireEquipmentChangedEvent(actor, *iterator, InventoryStoreListener::EQUIPPED); + fireEquipmentChangedEvent(actor, *iterator, InventoryStoreListener::EQUIP); updateMagicEffects(actor); } void MWWorld::InventoryStore::unequipAll(const MWWorld::Ptr& actor) { - // Only *one* change event should be fired - mUpdatesEnabled = false; + fireEquipmentChangedEvent(actor, MWWorld::Ptr(), InventoryStoreListener::UNEQUIPALL_BEGIN); for (int slot=0; slot < MWWorld::InventoryStore::Slots; ++slot) unequipSlot(slot, actor); - mUpdatesEnabled = true; - fireEquipmentChangedEvent(actor, MWWorld::Ptr(), InventoryStoreListener::ALL_UNEQUIPPED); + + fireEquipmentChangedEvent(actor, MWWorld::Ptr(), InventoryStoreListener::UNEQUIPALL_END); updateMagicEffects(actor); } @@ -277,17 +276,19 @@ void MWWorld::InventoryStore::autoEquip (const MWWorld::Ptr& actor) bool changed = false; for (std::size_t i=0; iequipmentChanged(actor, MWWorld::Ptr(), InventoryStoreListener::AUTOEQUIP); + } } void MWWorld::InventoryStore::fireEquipmentChangedEvent(const MWWorld::Ptr& actor, const MWWorld::Ptr& item, InventoryStoreListener::State state) diff --git a/apps/openmw/mwworld/inventorystore.hpp b/apps/openmw/mwworld/inventorystore.hpp index 475f810af..fb6d2919b 100644 --- a/apps/openmw/mwworld/inventorystore.hpp +++ b/apps/openmw/mwworld/inventorystore.hpp @@ -22,10 +22,11 @@ namespace MWWorld public: enum State { - EQUIPPED, - AUTOEQUIPPED, - UNEQUIPPED, - ALL_UNEQUIPPED + EQUIP, + AUTOEQUIP, + UNEQUIP, + UNEQUIPALL_BEGIN, + UNEQUIPALL_END }; /**