make Class::use method return an equip action for equippable items, add sound for equipping

This commit is contained in:
scrawl 2012-05-16 16:08:55 +02:00
parent 9c4243782e
commit 0f1e09d2c1
10 changed files with 133 additions and 60 deletions

View file

@ -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

View file

@ -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<MWWorld::Action> Armor::use (const MWWorld::Ptr& ptr) const
{
MWBase::Environment::get().getSoundManager()->playSound (getUpSoundId(ptr), 1.0, 1.0);
return boost::shared_ptr<MWWorld::Action>(new MWWorld::ActionEquip(ptr));
}
}

View file

@ -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<MWWorld::Action> use (const MWWorld::Ptr& ptr)
const;
///< Generate action for using via inventory menu
};
}

View file

@ -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<MWWorld::Action> Clothing::use (const MWWorld::Ptr& ptr) const
{
MWBase::Environment::get().getSoundManager()->playSound (getUpSoundId(ptr), 1.0, 1.0);
return boost::shared_ptr<MWWorld::Action>(new MWWorld::ActionEquip(ptr));
}
}

View file

@ -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<MWWorld::Action> use (const MWWorld::Ptr& ptr)
const;
///< Generate action for using via inventory menu
};
}

View file

@ -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<MWWorld::Action> Weapon::use (const MWWorld::Ptr& ptr) const
{
MWBase::Environment::get().getSoundManager()->playSound (getUpSoundId(ptr), 1.0, 1.0);
return boost::shared_ptr<MWWorld::Action>(new MWWorld::ActionEquip(ptr));
}
}

View file

@ -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<MWWorld::Action> use (const MWWorld::Ptr& ptr)
const;
///< Generate action for using via inventory menu
};
}

View file

@ -147,73 +147,32 @@ namespace MWGui
{
MWWorld::Ptr ptr = *mDragAndDrop->mDraggedWidget->getUserData<MWWorld::Ptr>();
// can the object be equipped?
std::pair<std::vector<int>, bool> slots = MWWorld::Class::get(ptr).getEquipmentSlots(ptr);
if (slots.first.empty())
{
// can't be equipped, try to use instead
boost::shared_ptr<MWWorld::Action> 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::InventoryStore&>(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<int>::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<MWWorld::Action> 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;

View file

@ -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::InventoryStore&>(MWWorld::Class::get(player).getContainerStore(player));
// slots that this item can be equipped in
std::pair<std::vector<int>, 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<int>::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;
}
}
}
}

View file

@ -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