You cannot select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
openmw-tes3mp/apps/openmw/mwworld/inventorystore.hpp

226 lines
8.9 KiB
C++

#ifndef GAME_MWWORLD_INVENTORYSTORE_H
#define GAME_MWWORLD_INVENTORYSTORE_H
#include "containerstore.hpp"
#include "../mwmechanics/magiceffects.hpp"
namespace ESM
{
struct MagicEffect;
}
namespace MWMechanics
{
class NpcStats;
}
namespace MWWorld
{
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?
*/
virtual void permanentEffectAdded (const ESM::MagicEffect *magicEffect, bool isNew, bool playSound) {}
};
///< \brief Variant of the ContainerStore for NPCs
class InventoryStore : public ContainerStore
{
public:
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;
static const int Slots = 19;
static const int Slot_NoSlot = -1;
private:
MWMechanics::MagicEffects mMagicEffects;
InventoryStoreListener* mListener;
// 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;
bool mFirstAutoEquip;
// 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.
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;
TEffectMagnitudes mPermanentMagicEffectMagnitudes;
typedef std::vector<ContainerStoreIterator> TSlots;
TSlots mSlots;
// selected magic item (for using enchantments of type "Cast once" or "Cast when used")
ContainerStoreIterator mSelectedEnchantItem;
// (item, max charge)
typedef std::vector<std::pair<ContainerStoreIterator, float> > TRechargingItems;
TRechargingItems mRechargingItems;
bool mRechargingItemsUpToDate;
void copySlots (const InventoryStore& store);
void initSlots (TSlots& slots_);
void updateMagicEffects(const Ptr& actor);
void updateRechargingItems();
void fireEquipmentChangedEvent(const Ptr& actor);
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);
public:
InventoryStore();
InventoryStore (const InventoryStore& store);
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).
///
/// \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!
///
/// @param setOwner Set the owner of the added item to \a actorPtr?
///
/// @return if stacking happened, return iterator to the item that was stacked against, otherwise iterator to the newly inserted item.
void equip (int slot, const ContainerStoreIterator& iterator, const Ptr& actor);
///< \warning \a iterator can not be an end()-iterator, use unequip function instead
bool isEquipped(const MWWorld::ConstPtr& item);
///< Utility function, returns true if the given item is equipped in any slot
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
ContainerStoreIterator getSlot (int slot);
void unequipAll(const MWWorld::Ptr& actor);
///< Unequip all currently equipped items.
void autoEquip (const MWWorld::Ptr& actor);
///< Auto equip items according to stats and item value.
const MWMechanics::MagicEffects& getMagicEffects() const;
///< 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.
virtual bool stacks (const ConstPtr& ptr1, const ConstPtr& ptr2);
///< @return true if the two specified objects can stack with each other
virtual int remove(const Ptr& item, int count, const Ptr& actor);
///< Remove \a count item(s) designated by \a item from this inventory.
///
/// @return the number of items actually removed
ContainerStoreIterator unequipSlot(int slot, const Ptr& actor);
///< Unequip \a slot.
///
/// @return an iterator to the item that was previously in the slot
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).
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).
void setListener (InventoryStoreListener* listener, const Ptr& actor);
///< Set a listener for various events, see \a InventoryStoreListener
InventoryStoreListener* getListener();
void visitEffectSources (MWMechanics::EffectSourceVisitor& visitor);
void rechargeItems (float duration);
///< Restore charge on enchanted items. Note this should only be done for the player.
void purgeEffect (short effectId);
///< Remove a magic effect
void purgeEffect (short effectId, const std::string& sourceId);
///< Remove a magic effect
virtual void clear();
///< Empty container.
virtual void writeState (ESM::InventoryState& state) const;
virtual void readState (const ESM::InventoryState& state);
};
}
#endif