#ifndef GAME_MWWORLD_CONTAINERSTORE_H #define GAME_MWWORLD_CONTAINERSTORE_H #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include "ptr.hpp" #include "cellreflist.hpp" namespace ESM { struct InventoryList; struct InventoryState; } namespace MWWorld { class ContainerStoreIterator; class ContainerStore { public: static const int Type_Potion = 0x0001; static const int Type_Apparatus = 0x0002; static const int Type_Armor = 0x0004; static const int Type_Book = 0x0008; static const int Type_Clothing = 0x0010; static const int Type_Ingredient = 0x0020; static const int Type_Light = 0x0040; static const int Type_Lockpick = 0x0080; static const int Type_Miscellaneous = 0x0100; static const int Type_Probe = 0x0200; static const int Type_Repair = 0x0400; static const int Type_Weapon = 0x0800; static const int Type_Last = Type_Weapon; static const int Type_All = 0xffff; static const std::string sGoldId; private: MWWorld::CellRefList potions; MWWorld::CellRefList appas; MWWorld::CellRefList armors; MWWorld::CellRefList books; MWWorld::CellRefList clothes; MWWorld::CellRefList ingreds; MWWorld::CellRefList lights; MWWorld::CellRefList lockpicks; MWWorld::CellRefList miscItems; MWWorld::CellRefList probes; MWWorld::CellRefList repairs; MWWorld::CellRefList weapons; std::map, int> mLevelledItemMap; ///< Stores result of levelled item spawns. <(refId, spawningGroup), count> /// This is used to restock levelled items(s) if the old item was sold. mutable float mCachedWeight; mutable bool mWeightUpToDate; ContainerStoreIterator addImp (const Ptr& ptr, int count); void addInitialItem (const std::string& id, const std::string& owner, int count, bool topLevel=true, const std::string& levItem = ""); template ContainerStoreIterator getState (CellRefList& collection, const ESM::ObjectState& state); template void storeState (const LiveCellRef& ref, ESM::ObjectState& state) const; template void storeStates (const CellRefList& collection, ESM::InventoryState& inventory, int& index, bool equipable = false) const; 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: ContainerStore(); virtual ~ContainerStore(); virtual ContainerStore* clone() { return new ContainerStore(*this); } ContainerStoreIterator begin (int mask = Type_All); ContainerStoreIterator end(); 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) /// /// \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? If false, the owner is reset to "". /// /// @return if stacking happened, return iterator to the item that was stacked against, otherwise iterator to the newly inserted item. ContainerStoreIterator add(const std::string& id, int count, const Ptr& actorPtr); ///< Utility to construct a ManualRef and call add(ptr, count, actorPtr, true) int remove(const std::string& itemId, int count, const Ptr& actor); ///< Remove \a count item(s) designated by \a itemId from this container. /// /// @return the number of items actually removed 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 unstack (const Ptr& ptr, const Ptr& container, int count = 1); ///< Unstack an item in this container. The item's count will be set to count, then a new stack will be added with (origCount-count). /// /// @return an iterator to the new stack, or end() if no new stack was created. MWWorld::ContainerStoreIterator restack (const MWWorld::Ptr& item); ///< Attempt to re-stack an item in this container. /// If a compatible stack is found, the item's count is added to that stack, then the original is deleted. /// @return If the item was stacked, return the stack, otherwise return the old (untouched) item. /// @return How many items with refID \a id are in this container? int count (const std::string& id); protected: ContainerStoreIterator addNewStack (const ConstPtr& ptr, int count); ///< Add the item to this container (do not try to stack it onto existing items) virtual void flagAsModified(); public: virtual bool stacks (const ConstPtr& ptr1, const ConstPtr& ptr2); ///< @return true if the two specified objects can stack with each other void fill (const ESM::InventoryList& items, const std::string& owner); ///< Insert items into *this. void restock (const ESM::InventoryList& items, const MWWorld::Ptr& ptr, const std::string& owner); virtual void clear(); ///< Empty container. float getWeight() const; ///< Return total weight of the items contained in *this. static int getType (const ConstPtr& ptr); ///< This function throws an exception, if ptr does not point to an object, that can be /// put into a container. Ptr search (const std::string& id); virtual void writeState (ESM::InventoryState& state) const; virtual void readState (const ESM::InventoryState& state); friend class ContainerStoreIterator; }; /// \brief Iteration over a subset of objects in a ContainerStore /// /// \note The iterator will automatically skip over deleted objects. class ContainerStoreIterator : public std::iterator { int mType; int mMask; ContainerStore *mContainer; mutable Ptr mPtr; MWWorld::CellRefList::List::iterator mPotion; MWWorld::CellRefList::List::iterator mApparatus; MWWorld::CellRefList::List::iterator mArmor; MWWorld::CellRefList::List::iterator mBook; MWWorld::CellRefList::List::iterator mClothing; MWWorld::CellRefList::List::iterator mIngredient; MWWorld::CellRefList::List::iterator mLight; MWWorld::CellRefList::List::iterator mLockpick; MWWorld::CellRefList::List::iterator mMiscellaneous; MWWorld::CellRefList::List::iterator mProbe; MWWorld::CellRefList::List::iterator mRepair; MWWorld::CellRefList::List::iterator mWeapon; private: ContainerStoreIterator (ContainerStore *container); ///< End-iterator ContainerStoreIterator (int mask, ContainerStore *container); ///< Begin-iterator // construct iterator using a CellRefList iterator ContainerStoreIterator (ContainerStore *container, MWWorld::CellRefList::List::iterator); ContainerStoreIterator (ContainerStore *container, MWWorld::CellRefList::List::iterator); ContainerStoreIterator (ContainerStore *container, MWWorld::CellRefList::List::iterator); ContainerStoreIterator (ContainerStore *container, MWWorld::CellRefList::List::iterator); ContainerStoreIterator (ContainerStore *container, MWWorld::CellRefList::List::iterator); ContainerStoreIterator (ContainerStore *container, MWWorld::CellRefList::List::iterator); ContainerStoreIterator (ContainerStore *container, MWWorld::CellRefList::List::iterator); ContainerStoreIterator (ContainerStore *container, MWWorld::CellRefList::List::iterator); ContainerStoreIterator (ContainerStore *container, MWWorld::CellRefList::List::iterator); ContainerStoreIterator (ContainerStore *container, MWWorld::CellRefList::List::iterator); ContainerStoreIterator (ContainerStore *container, MWWorld::CellRefList::List::iterator); ContainerStoreIterator (ContainerStore *container, MWWorld::CellRefList::List::iterator); void copy (const ContainerStoreIterator& src); void incType(); void nextType(); bool resetIterator(); ///< Reset iterator for selected type. /// /// \return Type not empty? bool incIterator(); ///< Increment iterator for selected type. /// /// \return reached the end? public: ContainerStoreIterator(const ContainerStoreIterator& src); Ptr *operator->() const; Ptr operator*() const; ContainerStoreIterator& operator++(); ContainerStoreIterator operator++ (int); ContainerStoreIterator& operator= (const ContainerStoreIterator& rhs); bool isEqual (const ContainerStoreIterator& iter) const; int getType() const; const ContainerStore *getContainerStore() const; friend class ContainerStore; }; bool operator== (const ContainerStoreIterator& left, const ContainerStoreIterator& right); bool operator!= (const ContainerStoreIterator& left, const ContainerStoreIterator& right); } #endif