2012-03-10 11:43:48 +00:00
|
|
|
#ifndef GAME_MWWORLD_INVENTORYSTORE_H
|
|
|
|
#define GAME_MWWORLD_INVENTORYSTORE_H
|
|
|
|
|
|
|
|
#include "containerstore.hpp"
|
|
|
|
|
2012-05-18 13:48:55 +00:00
|
|
|
#include "../mwmechanics/magiceffects.hpp"
|
|
|
|
|
2014-02-23 19:11:05 +00:00
|
|
|
namespace ESM
|
|
|
|
{
|
|
|
|
struct MagicEffect;
|
|
|
|
}
|
|
|
|
|
2012-03-31 15:26:15 +00:00
|
|
|
namespace MWMechanics
|
|
|
|
{
|
2012-08-13 17:53:54 +00:00
|
|
|
class NpcStats;
|
2012-03-31 15:26:15 +00:00
|
|
|
}
|
|
|
|
|
2012-03-10 11:43:48 +00:00
|
|
|
namespace MWWorld
|
|
|
|
{
|
2013-11-15 01:08:36 +00:00
|
|
|
class InventoryStoreListener
|
|
|
|
{
|
|
|
|
public:
|
|
|
|
/**
|
|
|
|
* Fired when items are equipped or unequipped
|
|
|
|
*/
|
|
|
|
virtual void equipmentChanged () {}
|
|
|
|
|
|
|
|
/**
|
|
|
|
* @param effect
|
|
|
|
* @param isNew Is this effect new (e.g. the item for it was just now manually equipped)
|
|
|
|
* or was it loaded from a savegame / initial game state? \n
|
|
|
|
* If it isn't new, non-looping VFX should not be played.
|
|
|
|
* @param playSound Play effect sound?
|
|
|
|
*/
|
2016-09-15 14:41:20 +00:00
|
|
|
virtual void permanentEffectAdded (const ESM::MagicEffect *magicEffect, bool isNew) {}
|
2013-11-15 01:08:36 +00:00
|
|
|
|
|
|
|
};
|
|
|
|
|
2012-03-10 11:43:48 +00:00
|
|
|
///< \brief Variant of the ContainerStore for NPCs
|
|
|
|
class InventoryStore : public ContainerStore
|
|
|
|
{
|
2012-03-13 12:31:11 +00:00
|
|
|
public:
|
2012-03-10 11:43:48 +00:00
|
|
|
|
2012-03-13 12:31:11 +00:00
|
|
|
static const int Slot_Helmet = 0;
|
|
|
|
static const int Slot_Cuirass = 1;
|
|
|
|
static const int Slot_Greaves = 2;
|
|
|
|
static const int Slot_LeftPauldron = 3;
|
|
|
|
static const int Slot_RightPauldron = 4;
|
|
|
|
static const int Slot_LeftGauntlet = 5;
|
|
|
|
static const int Slot_RightGauntlet = 6;
|
|
|
|
static const int Slot_Boots = 7;
|
|
|
|
static const int Slot_Shirt = 8;
|
|
|
|
static const int Slot_Pants = 9;
|
|
|
|
static const int Slot_Skirt = 10;
|
|
|
|
static const int Slot_Robe = 11;
|
|
|
|
static const int Slot_LeftRing = 12;
|
|
|
|
static const int Slot_RightRing = 13;
|
|
|
|
static const int Slot_Amulet = 14;
|
|
|
|
static const int Slot_Belt = 15;
|
|
|
|
static const int Slot_CarriedRight = 16;
|
|
|
|
static const int Slot_CarriedLeft = 17;
|
|
|
|
static const int Slot_Ammunition = 18;
|
2012-03-10 11:43:48 +00:00
|
|
|
|
2012-03-13 12:31:11 +00:00
|
|
|
static const int Slots = 19;
|
|
|
|
|
|
|
|
static const int Slot_NoSlot = -1;
|
|
|
|
|
|
|
|
private:
|
|
|
|
|
2013-11-13 17:51:28 +00:00
|
|
|
MWMechanics::MagicEffects mMagicEffects;
|
|
|
|
|
2013-11-15 01:08:36 +00:00
|
|
|
InventoryStoreListener* mListener;
|
|
|
|
|
2013-11-13 17:51:28 +00:00
|
|
|
// Enables updates of magic effects and actor model whenever items are equipped or unequipped.
|
|
|
|
// This is disabled during autoequip to avoid excessive updates
|
|
|
|
bool mUpdatesEnabled;
|
|
|
|
|
2013-11-14 13:41:10 +00:00
|
|
|
bool mFirstAutoEquip;
|
|
|
|
|
2013-11-13 17:51:28 +00:00
|
|
|
// Vanilla allows permanent effects with a random magnitude, so it needs to be stored here.
|
|
|
|
// We also need this to only play sounds and particle effects when the item is equipped, rather than on every update.
|
2013-11-15 19:29:47 +00:00
|
|
|
struct EffectParams
|
|
|
|
{
|
|
|
|
// Modifier to scale between min and max magnitude
|
|
|
|
float mRandom;
|
|
|
|
// Multiplier for when an effect was fully or partially resisted
|
|
|
|
float mMultiplier;
|
|
|
|
};
|
|
|
|
|
|
|
|
typedef std::map<std::string, std::vector<EffectParams> > TEffectMagnitudes;
|
2013-11-13 17:51:28 +00:00
|
|
|
TEffectMagnitudes mPermanentMagicEffectMagnitudes;
|
2012-05-18 13:48:55 +00:00
|
|
|
|
2012-03-31 15:26:15 +00:00
|
|
|
typedef std::vector<ContainerStoreIterator> TSlots;
|
|
|
|
|
2013-11-13 17:51:28 +00:00
|
|
|
TSlots mSlots;
|
2012-03-13 12:31:11 +00:00
|
|
|
|
2012-05-29 10:35:03 +00:00
|
|
|
// selected magic item (for using enchantments of type "Cast once" or "Cast when used")
|
|
|
|
ContainerStoreIterator mSelectedEnchantItem;
|
|
|
|
|
2013-11-19 15:42:24 +00:00
|
|
|
// (item, max charge)
|
|
|
|
typedef std::vector<std::pair<ContainerStoreIterator, float> > TRechargingItems;
|
|
|
|
TRechargingItems mRechargingItems;
|
|
|
|
|
2014-10-05 16:27:26 +00:00
|
|
|
bool mRechargingItemsUpToDate;
|
|
|
|
|
2012-03-13 12:31:11 +00:00
|
|
|
void copySlots (const InventoryStore& store);
|
|
|
|
|
2013-11-12 22:23:19 +00:00
|
|
|
void initSlots (TSlots& slots_);
|
2012-03-31 15:26:15 +00:00
|
|
|
|
2013-11-15 19:29:47 +00:00
|
|
|
void updateMagicEffects(const Ptr& actor);
|
2013-11-19 15:42:24 +00:00
|
|
|
void updateRechargingItems();
|
2013-10-25 20:16:52 +00:00
|
|
|
|
2015-04-06 03:13:09 +00:00
|
|
|
void fireEquipmentChangedEvent(const Ptr& actor);
|
2013-11-13 17:51:28 +00:00
|
|
|
|
2015-01-23 15:45:47 +00:00
|
|
|
virtual void storeEquipmentState (const MWWorld::LiveCellRefBase& ref, int index, ESM::InventoryState& inventory) const;
|
|
|
|
virtual void readEquipmentState (const MWWorld::ContainerStoreIterator& iter, int index, const ESM::InventoryState& inventory);
|
2014-02-01 16:07:08 +00:00
|
|
|
|
2016-10-18 12:03:11 +00:00
|
|
|
bool canActorAutoEquip(const MWWorld::Ptr& actor, const MWWorld::Ptr& item);
|
2017-02-28 14:43:20 +00:00
|
|
|
ContainerStoreIterator findSlot (int slot) const;
|
2016-10-18 12:03:11 +00:00
|
|
|
|
2012-03-13 12:31:11 +00:00
|
|
|
public:
|
|
|
|
|
|
|
|
InventoryStore();
|
|
|
|
|
|
|
|
InventoryStore (const InventoryStore& store);
|
|
|
|
|
|
|
|
InventoryStore& operator= (const InventoryStore& store);
|
|
|
|
|
2014-01-19 10:42:58 +00:00
|
|
|
virtual InventoryStore* clone() { return new InventoryStore(*this); }
|
|
|
|
|
2014-01-05 21:23:53 +00:00
|
|
|
virtual ContainerStoreIterator add (const Ptr& itemPtr, int count, const Ptr& actorPtr, bool setOwner=false);
|
2013-08-07 12:45:23 +00:00
|
|
|
///< 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).
|
|
|
|
///
|
|
|
|
/// \note The item pointed to is not required to exist beyond this function call.
|
|
|
|
///
|
|
|
|
/// \attention Do not add items to an existing stack by increasing the count instead of
|
|
|
|
/// calling this function!
|
|
|
|
///
|
2014-01-05 21:23:53 +00:00
|
|
|
/// @param setOwner Set the owner of the added item to \a actorPtr?
|
|
|
|
///
|
2013-08-07 12:45:23 +00:00
|
|
|
/// @return if stacking happened, return iterator to the item that was stacked against, otherwise iterator to the newly inserted item.
|
|
|
|
|
2013-08-13 00:06:46 +00:00
|
|
|
void equip (int slot, const ContainerStoreIterator& iterator, const Ptr& actor);
|
2014-08-27 22:41:52 +00:00
|
|
|
///< \warning \a iterator can not be an end()-iterator, use unequip function instead
|
2012-05-29 10:35:03 +00:00
|
|
|
|
2015-12-18 16:06:58 +00:00
|
|
|
bool isEquipped(const MWWorld::ConstPtr& item);
|
2014-12-15 12:47:34 +00:00
|
|
|
///< Utility function, returns true if the given item is equipped in any slot
|
|
|
|
|
2012-05-29 10:35:03 +00:00
|
|
|
void setSelectedEnchantItem(const ContainerStoreIterator& iterator);
|
|
|
|
///< set the selected magic item (for using enchantments of type "Cast once" or "Cast when used")
|
|
|
|
/// \note to unset the selected item, call this method with end() iterator
|
|
|
|
|
|
|
|
ContainerStoreIterator getSelectedEnchantItem();
|
|
|
|
///< @return selected magic item (for using enchantments of type "Cast once" or "Cast when used")
|
|
|
|
/// \note if no item selected, return end() iterator
|
2012-03-13 12:31:11 +00:00
|
|
|
|
|
|
|
ContainerStoreIterator getSlot (int slot);
|
2017-02-26 21:24:51 +00:00
|
|
|
ConstContainerStoreIterator getSlot(int slot) const;
|
2012-03-31 15:26:15 +00:00
|
|
|
|
2013-08-06 12:55:08 +00:00
|
|
|
void unequipAll(const MWWorld::Ptr& actor);
|
2013-08-06 09:20:51 +00:00
|
|
|
///< Unequip all currently equipped items.
|
|
|
|
|
2013-11-15 19:29:47 +00:00
|
|
|
void autoEquip (const MWWorld::Ptr& actor);
|
2012-03-31 15:26:15 +00:00
|
|
|
///< Auto equip items according to stats and item value.
|
2012-05-13 12:58:38 +00:00
|
|
|
|
2017-01-08 19:52:04 +00:00
|
|
|
void autoEquipShield(const MWWorld::Ptr& actor);
|
|
|
|
///< Auto-equip the shield with most health.
|
|
|
|
|
2013-11-13 17:51:28 +00:00
|
|
|
const MWMechanics::MagicEffects& getMagicEffects() const;
|
2012-05-18 13:48:55 +00:00
|
|
|
///< Return magic effects from worn items.
|
|
|
|
|
|
|
|
virtual void flagAsModified();
|
|
|
|
///< \attention This function is internal to the world model and should not be called from
|
|
|
|
/// outside.
|
|
|
|
|
2017-03-08 00:28:56 +00:00
|
|
|
virtual bool stacks (const ConstPtr& ptr1, const ConstPtr& ptr2) const;
|
2012-05-13 12:58:38 +00:00
|
|
|
///< @return true if the two specified objects can stack with each other
|
|
|
|
|
2017-10-06 06:54:25 +00:00
|
|
|
virtual int remove(const std::string& itemId, int count, const Ptr& actor);
|
|
|
|
virtual int remove(const std::string& itemId, int count, const Ptr& actor, bool equipReplacement);
|
|
|
|
|
2017-09-11 10:49:55 +00:00
|
|
|
virtual int remove(const Ptr& item, int count, const Ptr& actor);
|
|
|
|
virtual int remove(const Ptr& item, int count, const Ptr& actor, bool equipReplacement);
|
2013-08-12 23:19:33 +00:00
|
|
|
///< Remove \a count item(s) designated by \a item from this inventory.
|
|
|
|
///
|
|
|
|
/// @return the number of items actually removed
|
2013-10-31 23:54:54 +00:00
|
|
|
|
2014-02-04 03:11:46 +00:00
|
|
|
ContainerStoreIterator unequipSlot(int slot, const Ptr& actor);
|
2013-11-01 00:01:55 +00:00
|
|
|
///< Unequip \a slot.
|
|
|
|
///
|
|
|
|
/// @return an iterator to the item that was previously in the slot
|
2013-10-31 23:21:15 +00:00
|
|
|
|
|
|
|
ContainerStoreIterator unequipItem(const Ptr& item, const Ptr& actor);
|
|
|
|
///< Unequip an item identified by its Ptr. An exception is thrown
|
|
|
|
/// if the item is not currently equipped.
|
|
|
|
///
|
|
|
|
/// @return an iterator to the item that was previously in the slot
|
|
|
|
/// (it can be re-stacked so its count may be different than when it
|
|
|
|
/// was equipped).
|
2013-11-15 01:08:36 +00:00
|
|
|
|
2016-01-19 01:56:35 +00:00
|
|
|
ContainerStoreIterator unequipItemQuantity(const Ptr& item, const Ptr& actor, int count);
|
|
|
|
///< Unequip a specific quantity of an item identified by its Ptr.
|
|
|
|
/// An exception is thrown if the item is not currently equipped,
|
|
|
|
/// if count <= 0, or if count > the item stack size.
|
|
|
|
///
|
|
|
|
/// @return an iterator to the unequipped items that were previously
|
|
|
|
/// in the slot (they can be re-stacked so its count may be different
|
|
|
|
/// than the requested count).
|
|
|
|
|
2016-10-08 01:49:50 +00:00
|
|
|
void setInvListener (InventoryStoreListener* listener, const Ptr& actor);
|
2013-11-15 01:08:36 +00:00
|
|
|
///< Set a listener for various events, see \a InventoryStoreListener
|
2013-11-15 19:29:47 +00:00
|
|
|
|
2016-10-08 01:49:50 +00:00
|
|
|
InventoryStoreListener* getInvListener();
|
2015-06-07 14:50:34 +00:00
|
|
|
|
2013-11-15 19:29:47 +00:00
|
|
|
void visitEffectSources (MWMechanics::EffectSourceVisitor& visitor);
|
2013-11-19 15:42:24 +00:00
|
|
|
|
|
|
|
void rechargeItems (float duration);
|
2013-12-08 22:36:37 +00:00
|
|
|
///< Restore charge on enchanted items. Note this should only be done for the player.
|
|
|
|
|
|
|
|
void purgeEffect (short effectId);
|
|
|
|
///< Remove a magic effect
|
2014-02-01 16:07:08 +00:00
|
|
|
|
2015-01-05 17:52:37 +00:00
|
|
|
void purgeEffect (short effectId, const std::string& sourceId);
|
|
|
|
///< Remove a magic effect
|
|
|
|
|
2014-02-01 16:07:08 +00:00
|
|
|
virtual void clear();
|
|
|
|
///< Empty container.
|
2014-12-30 00:36:31 +00:00
|
|
|
|
2015-12-17 23:18:06 +00:00
|
|
|
virtual void writeState (ESM::InventoryState& state) const;
|
2014-12-30 00:36:31 +00:00
|
|
|
|
|
|
|
virtual void readState (const ESM::InventoryState& state);
|
2012-03-10 11:43:48 +00:00
|
|
|
};
|
|
|
|
}
|
|
|
|
|
|
|
|
#endif
|