diff --git a/apps/openmw/CMakeLists.txt b/apps/openmw/CMakeLists.txt index 972c7f2e4..c105f28b1 100644 --- a/apps/openmw/CMakeLists.txt +++ b/apps/openmw/CMakeLists.txt @@ -48,6 +48,7 @@ add_openmw_dir (mwworld refdata world physicssystem scene globals class action nullaction actionteleport containerstore actiontalk actiontake manualref player cellfunctors cells localscripts customdata weather inventorystore ptr actionopen actionread + actionequip ) add_openmw_dir (mwclass diff --git a/apps/openmw/mwclass/armor.cpp b/apps/openmw/mwclass/armor.cpp index abd351fb4..83c0120c7 100644 --- a/apps/openmw/mwclass/armor.cpp +++ b/apps/openmw/mwclass/armor.cpp @@ -9,6 +9,7 @@ #include "../mwworld/ptr.hpp" #include "../mwworld/actiontake.hpp" +#include "../mwworld/actionequip.hpp" #include "../mwworld/inventorystore.hpp" #include "../mwworld/world.hpp" @@ -264,4 +265,11 @@ namespace MWClass return ref->base->enchant; } + + boost::shared_ptr Armor::use (const MWWorld::Ptr& ptr) const + { + MWBase::Environment::get().getSoundManager()->playSound (getUpSoundId(ptr), 1.0, 1.0); + + return boost::shared_ptr(new MWWorld::ActionEquip(ptr)); + } } diff --git a/apps/openmw/mwclass/armor.hpp b/apps/openmw/mwclass/armor.hpp index 9842c5020..a63806162 100644 --- a/apps/openmw/mwclass/armor.hpp +++ b/apps/openmw/mwclass/armor.hpp @@ -61,6 +61,11 @@ namespace MWClass virtual std::string getEnchantment (const MWWorld::Ptr& ptr) const; ///< @return the enchantment ID if the object is enchanted, otherwise an empty string + + virtual boost::shared_ptr use (const MWWorld::Ptr& ptr) + const; + ///< Generate action for using via inventory menu + }; } diff --git a/apps/openmw/mwclass/clothing.cpp b/apps/openmw/mwclass/clothing.cpp index 181af35cd..11b515faf 100644 --- a/apps/openmw/mwclass/clothing.cpp +++ b/apps/openmw/mwclass/clothing.cpp @@ -9,6 +9,7 @@ #include "../mwworld/ptr.hpp" #include "../mwworld/actiontake.hpp" +#include "../mwworld/actionequip.hpp" #include "../mwworld/inventorystore.hpp" #include "../mwworld/world.hpp" @@ -217,4 +218,11 @@ namespace MWClass return ref->base->enchant; } + + boost::shared_ptr Clothing::use (const MWWorld::Ptr& ptr) const + { + MWBase::Environment::get().getSoundManager()->playSound (getUpSoundId(ptr), 1.0, 1.0); + + return boost::shared_ptr(new MWWorld::ActionEquip(ptr)); + } } diff --git a/apps/openmw/mwclass/clothing.hpp b/apps/openmw/mwclass/clothing.hpp index 64b857e26..aba317be0 100644 --- a/apps/openmw/mwclass/clothing.hpp +++ b/apps/openmw/mwclass/clothing.hpp @@ -55,6 +55,10 @@ namespace MWClass virtual std::string getEnchantment (const MWWorld::Ptr& ptr) const; ///< @return the enchantment ID if the object is enchanted, otherwise an empty string + + virtual boost::shared_ptr use (const MWWorld::Ptr& ptr) + const; + ///< Generate action for using via inventory menu }; } diff --git a/apps/openmw/mwclass/weapon.cpp b/apps/openmw/mwclass/weapon.cpp index ab5a57a3d..482d618b0 100644 --- a/apps/openmw/mwclass/weapon.cpp +++ b/apps/openmw/mwclass/weapon.cpp @@ -9,6 +9,7 @@ #include "../mwworld/ptr.hpp" #include "../mwworld/actiontake.hpp" +#include "../mwworld/actionequip.hpp" #include "../mwworld/inventorystore.hpp" #include "../mwworld/world.hpp" @@ -355,4 +356,11 @@ namespace MWClass return ref->base->enchant; } + + boost::shared_ptr Weapon::use (const MWWorld::Ptr& ptr) const + { + MWBase::Environment::get().getSoundManager()->playSound (getUpSoundId(ptr), 1.0, 1.0); + + return boost::shared_ptr(new MWWorld::ActionEquip(ptr)); + } } diff --git a/apps/openmw/mwclass/weapon.hpp b/apps/openmw/mwclass/weapon.hpp index 9f9a3c4c8..92d703b4a 100644 --- a/apps/openmw/mwclass/weapon.hpp +++ b/apps/openmw/mwclass/weapon.hpp @@ -61,6 +61,11 @@ namespace MWClass virtual std::string getEnchantment (const MWWorld::Ptr& ptr) const; ///< @return the enchantment ID if the object is enchanted, otherwise an empty string + + virtual boost::shared_ptr use (const MWWorld::Ptr& ptr) + const; + ///< Generate action for using via inventory menu + }; } diff --git a/apps/openmw/mwgui/inventorywindow.cpp b/apps/openmw/mwgui/inventorywindow.cpp index 7160fa4f8..9773867ec 100644 --- a/apps/openmw/mwgui/inventorywindow.cpp +++ b/apps/openmw/mwgui/inventorywindow.cpp @@ -147,73 +147,32 @@ namespace MWGui { MWWorld::Ptr ptr = *mDragAndDrop->mDraggedWidget->getUserData(); - // can the object be equipped? - std::pair, bool> slots = MWWorld::Class::get(ptr).getEquipmentSlots(ptr); - if (slots.first.empty()) - { - // can't be equipped, try to use instead - boost::shared_ptr action = MWWorld::Class::get(ptr).use(ptr); - - action->execute(); - - /// \todo scripts - - // this is necessary for books/scrolls: if they are already in the player's inventory, - // the "Take" button should not be visible. - // NOTE: the take button is "reset" when the window opens, so we can safely do the following - // without screwing up future book windows - if (mDragAndDrop->mWasInInventory) - { - mWindowManager.getBookWindow()->setTakeButtonShow(false); - mWindowManager.getScrollWindow()->setTakeButtonShow(false); - } - } - else + if (mDragAndDrop->mDraggedFrom != this) { + // add item to the player's inventory MWWorld::InventoryStore& invStore = static_cast(MWWorld::Class::get(mContainer).getContainerStore(mContainer)); - MWWorld::ContainerStoreIterator it = invStore.begin(); - if (mDragAndDrop->mDraggedFrom != this) - { - // add item to the player's inventory - int origCount = ptr.getRefData().getCount(); - ptr.getRefData().setCount(origCount - mDragAndDrop->mDraggedCount); - it = invStore.add(ptr); - (*it).getRefData().setCount(mDragAndDrop->mDraggedCount); - } - else - { - // retrieve iterator to the item - for (; it != invStore.end(); ++it) - { - if (*it == ptr) - { - break; - } - } - } + int origCount = ptr.getRefData().getCount(); + ptr.getRefData().setCount(origCount - mDragAndDrop->mDraggedCount); + it = invStore.add(ptr); + (*it).getRefData().setCount(mDragAndDrop->mDraggedCount); + } - assert(it != invStore.end()); + /// \todo scripts - // equip the item in the first free slot - for (std::vector::const_iterator slot=slots.first.begin(); - slot!=slots.first.end(); ++slot) - { - // if all slots are occupied, replace the last slot - if (slot == --slots.first.end()) - { - invStore.equip(*slot, it); - break; - } + boost::shared_ptr action = MWWorld::Class::get(ptr).use(ptr); + + action->execute(); - if (invStore.getSlot(*slot) == invStore.end()) - { - // slot is not occupied - invStore.equip(*slot, it); - break; - } - } + // this is necessary for books/scrolls: if they are already in the player's inventory, + // the "Take" button should not be visible. + // NOTE: the take button is "reset" when the window opens, so we can safely do the following + // without screwing up future book windows + if (mDragAndDrop->mWasInInventory) + { + mWindowManager.getBookWindow()->setTakeButtonShow(false); + mWindowManager.getScrollWindow()->setTakeButtonShow(false); } mDragAndDrop->mIsOnDragAndDrop = false; diff --git a/apps/openmw/mwworld/actionequip.cpp b/apps/openmw/mwworld/actionequip.cpp new file mode 100644 index 000000000..f3bb256fd --- /dev/null +++ b/apps/openmw/mwworld/actionequip.cpp @@ -0,0 +1,54 @@ +#include "actionequip.hpp" + +#include "../mwbase/environment.hpp" +#include "../mwworld/world.hpp" +#include "../mwworld/inventorystore.hpp" +#include "../mwworld/player.hpp" + +namespace MWWorld +{ + ActionEquip::ActionEquip (const MWWorld::Ptr& object) : mObject (object) + { + } + + void ActionEquip::execute () + { + MWWorld::Ptr player = MWBase::Environment::get().getWorld()->getPlayer().getPlayer(); + MWWorld::InventoryStore& invStore = static_cast(MWWorld::Class::get(player).getContainerStore(player)); + + // slots that this item can be equipped in + std::pair, bool> slots = MWWorld::Class::get(mObject).getEquipmentSlots(mObject); + + // retrieve ContainerStoreIterator to the item + MWWorld::ContainerStoreIterator it = invStore.begin(); + for (; it != invStore.end(); ++it) + { + if (*it == mObject) + { + break; + } + } + + assert(it != invStore.end()); + + // equip the item in the first free slot + for (std::vector::const_iterator slot=slots.first.begin(); + slot!=slots.first.end(); ++slot) + { + // if all slots are occupied, replace the last slot + if (slot == --slots.first.end()) + { + invStore.equip(*slot, it); + break; + } + + if (invStore.getSlot(*slot) == invStore.end()) + { + // slot is not occupied + invStore.equip(*slot, it); + break; + } + } + } +} + diff --git a/apps/openmw/mwworld/actionequip.hpp b/apps/openmw/mwworld/actionequip.hpp new file mode 100644 index 000000000..6cf3640f8 --- /dev/null +++ b/apps/openmw/mwworld/actionequip.hpp @@ -0,0 +1,21 @@ +#ifndef GAME_MWWORLD_ACTIONEQUIP_H +#define GAME_MWWORLD_ACTIONEQUIP_H + +#include "action.hpp" +#include "ptr.hpp" + +namespace MWWorld +{ + class ActionEquip : public Action + { + Ptr mObject; + + public: + /// @param item to equip + ActionEquip (const Ptr& object); + + virtual void execute (); + }; +} + +#endif