mirror of
https://github.com/TES3MP/openmw-tes3mp.git
synced 2025-01-16 05:19:55 +00:00
29556a1802
A Warning indicates a potential problem in the content file(s) that the user told OpenMW to load. E.g. this might cause an object to not display at all or as intended, however the rest of the game will run fine. An Error, however, is more likely to be a bug with the engine itself - it means that basic assumptions have been violated and the engine might not run correctly anymore. The above mostly applies to errors/warnings during game-play; startup issues are handled differently: when a file is completely invalid/corrupted to the point that the engine can not start, that might cause messages that are worded as Error due to the severity of the issue but are not necessarily the engine's fault. Hopefully, being a little more consistent here will alleviate confusion among users as to when a log message should be reported and to whom.
1206 lines
43 KiB
C++
1206 lines
43 KiB
C++
#include "containerstore.hpp"
|
|
|
|
#include <cassert>
|
|
#include <typeinfo>
|
|
#include <stdexcept>
|
|
|
|
#include <components/esm/inventorystate.hpp>
|
|
|
|
#include "../mwbase/environment.hpp"
|
|
#include "../mwbase/world.hpp"
|
|
|
|
#include "../mwmechanics/creaturestats.hpp"
|
|
#include "../mwmechanics/levelledlist.hpp"
|
|
#include "../mwmechanics/actorutil.hpp"
|
|
|
|
#include "manualref.hpp"
|
|
#include "refdata.hpp"
|
|
#include "class.hpp"
|
|
#include "localscripts.hpp"
|
|
#include "player.hpp"
|
|
|
|
namespace
|
|
{
|
|
template<typename T>
|
|
float getTotalWeight (const MWWorld::CellRefList<T>& cellRefList)
|
|
{
|
|
float sum = 0;
|
|
|
|
for (typename MWWorld::CellRefList<T>::List::const_iterator iter (
|
|
cellRefList.mList.begin());
|
|
iter!=cellRefList.mList.end();
|
|
++iter)
|
|
{
|
|
if (iter->mData.getCount()>0)
|
|
sum += iter->mData.getCount()*iter->mBase->mData.mWeight;
|
|
}
|
|
|
|
return sum;
|
|
}
|
|
|
|
template<typename T>
|
|
MWWorld::Ptr searchId (MWWorld::CellRefList<T>& list, const std::string& id,
|
|
MWWorld::ContainerStore *store)
|
|
{
|
|
std::string id2 = Misc::StringUtils::lowerCase (id);
|
|
|
|
for (typename MWWorld::CellRefList<T>::List::iterator iter (list.mList.begin());
|
|
iter!=list.mList.end(); ++iter)
|
|
{
|
|
if (Misc::StringUtils::ciEqual(iter->mBase->mId, id2))
|
|
{
|
|
MWWorld::Ptr ptr (&*iter, 0);
|
|
ptr.setContainerStore (store);
|
|
return ptr;
|
|
}
|
|
}
|
|
|
|
return MWWorld::Ptr();
|
|
}
|
|
}
|
|
|
|
template<typename T>
|
|
MWWorld::ContainerStoreIterator MWWorld::ContainerStore::getState (CellRefList<T>& collection,
|
|
const ESM::ObjectState& state)
|
|
{
|
|
if (!LiveCellRef<T>::checkState (state))
|
|
return ContainerStoreIterator (this); // not valid anymore with current content files -> skip
|
|
|
|
const T *record = MWBase::Environment::get().getWorld()->getStore().
|
|
get<T>().search (state.mRef.mRefID);
|
|
|
|
if (!record)
|
|
return ContainerStoreIterator (this);
|
|
|
|
LiveCellRef<T> ref (record);
|
|
ref.load (state);
|
|
collection.mList.push_back (ref);
|
|
|
|
return ContainerStoreIterator (this, --collection.mList.end());
|
|
}
|
|
|
|
void MWWorld::ContainerStore::storeEquipmentState(const MWWorld::LiveCellRefBase &ref, int index, ESM::InventoryState &inventory) const
|
|
{
|
|
}
|
|
|
|
void MWWorld::ContainerStore::readEquipmentState(const MWWorld::ContainerStoreIterator& iter, int index, const ESM::InventoryState &inventory)
|
|
{
|
|
}
|
|
|
|
template<typename T>
|
|
void MWWorld::ContainerStore::storeState (const LiveCellRef<T>& ref, ESM::ObjectState& state) const
|
|
{
|
|
ref.save (state);
|
|
}
|
|
|
|
template<typename T>
|
|
void MWWorld::ContainerStore::storeStates (const CellRefList<T>& collection,
|
|
ESM::InventoryState& inventory, int& index, bool equipable) const
|
|
{
|
|
for (typename CellRefList<T>::List::const_iterator iter (collection.mList.begin());
|
|
iter!=collection.mList.end(); ++iter)
|
|
{
|
|
if (iter->mData.getCount() == 0)
|
|
continue;
|
|
ESM::ObjectState state;
|
|
storeState (*iter, state);
|
|
if (equipable)
|
|
storeEquipmentState(*iter, index, inventory);
|
|
inventory.mItems.push_back (state);
|
|
++index;
|
|
}
|
|
}
|
|
|
|
const std::string MWWorld::ContainerStore::sGoldId = "gold_001";
|
|
|
|
MWWorld::ContainerStore::ContainerStore() : mListener(NULL), mCachedWeight (0), mWeightUpToDate (false) {}
|
|
|
|
MWWorld::ContainerStore::~ContainerStore() {}
|
|
|
|
MWWorld::ConstContainerStoreIterator MWWorld::ContainerStore::cbegin (int mask) const
|
|
{
|
|
return ConstContainerStoreIterator (mask, this);
|
|
}
|
|
|
|
MWWorld::ConstContainerStoreIterator MWWorld::ContainerStore::cend() const
|
|
{
|
|
return ConstContainerStoreIterator (this);
|
|
}
|
|
|
|
MWWorld::ConstContainerStoreIterator MWWorld::ContainerStore::begin (int mask) const
|
|
{
|
|
return cbegin(mask);
|
|
}
|
|
|
|
MWWorld::ConstContainerStoreIterator MWWorld::ContainerStore::end() const
|
|
{
|
|
return cend();
|
|
}
|
|
|
|
MWWorld::ContainerStoreIterator MWWorld::ContainerStore::begin (int mask)
|
|
{
|
|
return ContainerStoreIterator (mask, this);
|
|
}
|
|
|
|
MWWorld::ContainerStoreIterator MWWorld::ContainerStore::end()
|
|
{
|
|
return ContainerStoreIterator (this);
|
|
}
|
|
|
|
int MWWorld::ContainerStore::count(const std::string &id)
|
|
{
|
|
int total=0;
|
|
for (MWWorld::ContainerStoreIterator iter (begin()); iter!=end(); ++iter)
|
|
if (Misc::StringUtils::ciEqual(iter->getCellRef().getRefId(), id))
|
|
total += iter->getRefData().getCount();
|
|
return total;
|
|
}
|
|
|
|
MWWorld::ContainerStoreListener* MWWorld::ContainerStore::getContListener() const
|
|
{
|
|
return mListener;
|
|
}
|
|
|
|
|
|
void MWWorld::ContainerStore::setContListener(MWWorld::ContainerStoreListener* listener)
|
|
{
|
|
mListener = listener;
|
|
}
|
|
|
|
MWWorld::ContainerStoreIterator MWWorld::ContainerStore::unstack(const Ptr &ptr, const Ptr& container, int count)
|
|
{
|
|
if (ptr.getRefData().getCount() <= count)
|
|
return end();
|
|
MWWorld::ContainerStoreIterator it = addNewStack(ptr, ptr.getRefData().getCount()-count);
|
|
const std::string script = it->getClass().getScript(*it);
|
|
if (!script.empty())
|
|
MWBase::Environment::get().getWorld()->getLocalScripts().add(script, *it);
|
|
|
|
remove(ptr, ptr.getRefData().getCount()-count, container);
|
|
|
|
return it;
|
|
}
|
|
|
|
MWWorld::ContainerStoreIterator MWWorld::ContainerStore::restack(const MWWorld::Ptr& item)
|
|
{
|
|
MWWorld::ContainerStoreIterator retval = end();
|
|
for (MWWorld::ContainerStoreIterator iter (begin()); iter != end(); ++iter)
|
|
{
|
|
if (item == *iter)
|
|
{
|
|
retval = iter;
|
|
break;
|
|
}
|
|
}
|
|
|
|
if (retval == end())
|
|
throw std::runtime_error("item is not from this container");
|
|
|
|
for (MWWorld::ContainerStoreIterator iter (begin()); iter != end(); ++iter)
|
|
{
|
|
if (stacks(*iter, item))
|
|
{
|
|
iter->getRefData().setCount(iter->getRefData().getCount() + item.getRefData().getCount());
|
|
item.getRefData().setCount(0);
|
|
retval = iter;
|
|
break;
|
|
}
|
|
}
|
|
return retval;
|
|
}
|
|
|
|
bool MWWorld::ContainerStore::stacks(const ConstPtr& ptr1, const ConstPtr& ptr2) const
|
|
{
|
|
const MWWorld::Class& cls1 = ptr1.getClass();
|
|
const MWWorld::Class& cls2 = ptr2.getClass();
|
|
|
|
if (!Misc::StringUtils::ciEqual(ptr1.getCellRef().getRefId(), ptr2.getCellRef().getRefId()))
|
|
return false;
|
|
|
|
// If it has an enchantment, don't stack when some of the charge is already used
|
|
if (!ptr1.getClass().getEnchantment(ptr1).empty())
|
|
{
|
|
const ESM::Enchantment* enchantment = MWBase::Environment::get().getWorld()->getStore().get<ESM::Enchantment>().find(
|
|
ptr1.getClass().getEnchantment(ptr1));
|
|
float maxCharge = static_cast<float>(enchantment->mData.mCharge);
|
|
float enchantCharge1 = ptr1.getCellRef().getEnchantmentCharge() == -1 ? maxCharge : ptr1.getCellRef().getEnchantmentCharge();
|
|
float enchantCharge2 = ptr2.getCellRef().getEnchantmentCharge() == -1 ? maxCharge : ptr2.getCellRef().getEnchantmentCharge();
|
|
if (enchantCharge1 != maxCharge || enchantCharge2 != maxCharge)
|
|
return false;
|
|
}
|
|
|
|
return ptr1 != ptr2 // an item never stacks onto itself
|
|
&& ptr1.getCellRef().getOwner() == ptr2.getCellRef().getOwner()
|
|
&& ptr1.getCellRef().getSoul() == ptr2.getCellRef().getSoul()
|
|
|
|
&& ptr1.getClass().getRemainingUsageTime(ptr1) == ptr2.getClass().getRemainingUsageTime(ptr2)
|
|
|
|
&& cls1.getScript(ptr1) == cls2.getScript(ptr2)
|
|
|
|
// item that is already partly used up never stacks
|
|
&& (!cls1.hasItemHealth(ptr1) || (
|
|
cls1.getItemHealth(ptr1) == cls1.getItemMaxHealth(ptr1)
|
|
&& cls2.getItemHealth(ptr2) == cls2.getItemMaxHealth(ptr2)));
|
|
}
|
|
|
|
MWWorld::ContainerStoreIterator MWWorld::ContainerStore::add(const std::string &id, int count, const Ptr &actorPtr)
|
|
{
|
|
MWWorld::ManualRef ref(MWBase::Environment::get().getWorld()->getStore(), id, count);
|
|
// a bit pointless to set owner for the player
|
|
if (actorPtr != MWMechanics::getPlayer())
|
|
return add(ref.getPtr(), count, actorPtr, true);
|
|
else
|
|
return add(ref.getPtr(), count, actorPtr, false);
|
|
}
|
|
|
|
MWWorld::ContainerStoreIterator MWWorld::ContainerStore::add (const Ptr& itemPtr, int count, const Ptr& actorPtr, bool setOwner)
|
|
{
|
|
Ptr player = MWBase::Environment::get().getWorld ()->getPlayerPtr();
|
|
|
|
MWWorld::ContainerStoreIterator it = end();
|
|
|
|
// HACK: Set owner on the original item, then reset it after we have copied it
|
|
// If we set the owner on the copied item, it would not stack correctly...
|
|
std::string oldOwner = itemPtr.getCellRef().getOwner();
|
|
if (!setOwner || actorPtr == MWMechanics::getPlayer()) // No point in setting owner to the player - NPCs will not respect this anyway
|
|
{
|
|
itemPtr.getCellRef().setOwner("");
|
|
}
|
|
else
|
|
{
|
|
itemPtr.getCellRef().setOwner(actorPtr.getCellRef().getRefId());
|
|
}
|
|
|
|
it = addImp(itemPtr, count);
|
|
|
|
itemPtr.getCellRef().setOwner(oldOwner);
|
|
|
|
// The copy of the original item we just made
|
|
MWWorld::Ptr item = *it;
|
|
|
|
// we may have copied an item from the world, so reset a few things first
|
|
item.getRefData().setBaseNode(NULL); // Especially important, otherwise scripts on the item could think that it's actually in a cell
|
|
ESM::Position pos;
|
|
pos.rot[0] = 0;
|
|
pos.rot[1] = 0;
|
|
pos.rot[2] = 0;
|
|
pos.pos[0] = 0;
|
|
pos.pos[1] = 0;
|
|
pos.pos[2] = 0;
|
|
item.getCellRef().setPosition(pos);
|
|
|
|
// reset ownership stuff, owner was already handled above
|
|
item.getCellRef().resetGlobalVariable();
|
|
item.getCellRef().setFaction("");
|
|
item.getCellRef().setFactionRank(-1);
|
|
|
|
// must reset the RefNum on the copied item, so that the RefNum on the original item stays unique
|
|
// maybe we should do this in the copy constructor instead?
|
|
item.getCellRef().unsetRefNum(); // destroy link to content file
|
|
|
|
std::string script = item.getClass().getScript(item);
|
|
if(script != "")
|
|
{
|
|
if (actorPtr == player)
|
|
{
|
|
// Items in player's inventory have cell set to 0, so their scripts will never be removed
|
|
item.mCell = 0;
|
|
}
|
|
else
|
|
{
|
|
// Set mCell to the cell of the container/actor, so that the scripts are removed properly when
|
|
// the cell of the container/actor goes inactive
|
|
item.mCell = actorPtr.getCell();
|
|
}
|
|
|
|
item.mContainerStore = this;
|
|
|
|
MWBase::Environment::get().getWorld()->getLocalScripts().add(script, item);
|
|
|
|
// Set OnPCAdd special variable, if it is declared
|
|
// Make sure to do this *after* we have added the script to LocalScripts
|
|
if (actorPtr == player)
|
|
item.getRefData().getLocals().setVarByInt(script, "onpcadd", 1);
|
|
}
|
|
|
|
if (mListener)
|
|
mListener->itemAdded(item, count);
|
|
|
|
return it;
|
|
}
|
|
|
|
MWWorld::ContainerStoreIterator MWWorld::ContainerStore::addImp (const Ptr& ptr, int count)
|
|
{
|
|
int type = getType(ptr);
|
|
|
|
const MWWorld::ESMStore &esmStore =
|
|
MWBase::Environment::get().getWorld()->getStore();
|
|
|
|
// gold needs special handling: when it is inserted into a container, the base object automatically becomes Gold_001
|
|
// this ensures that gold piles of different sizes stack with each other (also, several scripts rely on Gold_001 for detecting player gold)
|
|
if(ptr.getClass().isGold(ptr))
|
|
{
|
|
int realCount = count * ptr.getClass().getValue(ptr);
|
|
|
|
for (MWWorld::ContainerStoreIterator iter (begin(type)); iter!=end(); ++iter)
|
|
{
|
|
if (Misc::StringUtils::ciEqual((*iter).getCellRef().getRefId(), MWWorld::ContainerStore::sGoldId))
|
|
{
|
|
iter->getRefData().setCount(iter->getRefData().getCount() + realCount);
|
|
flagAsModified();
|
|
return iter;
|
|
}
|
|
}
|
|
|
|
MWWorld::ManualRef ref(esmStore, MWWorld::ContainerStore::sGoldId, realCount);
|
|
return addNewStack(ref.getPtr(), realCount);
|
|
}
|
|
|
|
// determine whether to stack or not
|
|
for (MWWorld::ContainerStoreIterator iter (begin(type)); iter!=end(); ++iter)
|
|
{
|
|
if (stacks(*iter, ptr))
|
|
{
|
|
// stack
|
|
iter->getRefData().setCount( iter->getRefData().getCount() + count );
|
|
|
|
flagAsModified();
|
|
return iter;
|
|
}
|
|
}
|
|
// if we got here, this means no stacking
|
|
return addNewStack(ptr, count);
|
|
}
|
|
|
|
MWWorld::ContainerStoreIterator MWWorld::ContainerStore::addNewStack (const ConstPtr& ptr, int count)
|
|
{
|
|
ContainerStoreIterator it = begin();
|
|
|
|
switch (getType(ptr))
|
|
{
|
|
case Type_Potion: potions.mList.push_back (*ptr.get<ESM::Potion>()); it = ContainerStoreIterator(this, --potions.mList.end()); break;
|
|
case Type_Apparatus: appas.mList.push_back (*ptr.get<ESM::Apparatus>()); it = ContainerStoreIterator(this, --appas.mList.end()); break;
|
|
case Type_Armor: armors.mList.push_back (*ptr.get<ESM::Armor>()); it = ContainerStoreIterator(this, --armors.mList.end()); break;
|
|
case Type_Book: books.mList.push_back (*ptr.get<ESM::Book>()); it = ContainerStoreIterator(this, --books.mList.end()); break;
|
|
case Type_Clothing: clothes.mList.push_back (*ptr.get<ESM::Clothing>()); it = ContainerStoreIterator(this, --clothes.mList.end()); break;
|
|
case Type_Ingredient: ingreds.mList.push_back (*ptr.get<ESM::Ingredient>()); it = ContainerStoreIterator(this, --ingreds.mList.end()); break;
|
|
case Type_Light: lights.mList.push_back (*ptr.get<ESM::Light>()); it = ContainerStoreIterator(this, --lights.mList.end()); break;
|
|
case Type_Lockpick: lockpicks.mList.push_back (*ptr.get<ESM::Lockpick>()); it = ContainerStoreIterator(this, --lockpicks.mList.end()); break;
|
|
case Type_Miscellaneous: miscItems.mList.push_back (*ptr.get<ESM::Miscellaneous>()); it = ContainerStoreIterator(this, --miscItems.mList.end()); break;
|
|
case Type_Probe: probes.mList.push_back (*ptr.get<ESM::Probe>()); it = ContainerStoreIterator(this, --probes.mList.end()); break;
|
|
case Type_Repair: repairs.mList.push_back (*ptr.get<ESM::Repair>()); it = ContainerStoreIterator(this, --repairs.mList.end()); break;
|
|
case Type_Weapon: weapons.mList.push_back (*ptr.get<ESM::Weapon>()); it = ContainerStoreIterator(this, --weapons.mList.end()); break;
|
|
}
|
|
|
|
it->getRefData().setCount(count);
|
|
|
|
flagAsModified();
|
|
return it;
|
|
}
|
|
|
|
int MWWorld::ContainerStore::remove(const std::string& itemId, int count, const Ptr& actor)
|
|
{
|
|
int toRemove = count;
|
|
|
|
for (ContainerStoreIterator iter(begin()); iter != end() && toRemove > 0; ++iter)
|
|
if (Misc::StringUtils::ciEqual(iter->getCellRef().getRefId(), itemId))
|
|
toRemove -= remove(*iter, toRemove, actor);
|
|
|
|
flagAsModified();
|
|
|
|
// number of removed items
|
|
return count - toRemove;
|
|
}
|
|
|
|
int MWWorld::ContainerStore::remove(const Ptr& item, int count, const Ptr& actor)
|
|
{
|
|
assert(this == item.getContainerStore());
|
|
|
|
int toRemove = count;
|
|
RefData& itemRef = item.getRefData();
|
|
|
|
if (itemRef.getCount() <= toRemove)
|
|
{
|
|
toRemove -= itemRef.getCount();
|
|
itemRef.setCount(0);
|
|
}
|
|
else
|
|
{
|
|
itemRef.setCount(itemRef.getCount() - toRemove);
|
|
toRemove = 0;
|
|
}
|
|
|
|
flagAsModified();
|
|
|
|
if (mListener)
|
|
mListener->itemRemoved(item, count - toRemove);
|
|
|
|
// number of removed items
|
|
return count - toRemove;
|
|
}
|
|
|
|
void MWWorld::ContainerStore::fill (const ESM::InventoryList& items, const std::string& owner)
|
|
{
|
|
for (std::vector<ESM::ContItem>::const_iterator iter (items.mList.begin()); iter!=items.mList.end();
|
|
++iter)
|
|
{
|
|
std::string id = Misc::StringUtils::lowerCase(iter->mItem.toString());
|
|
addInitialItem(id, owner, iter->mCount);
|
|
}
|
|
|
|
flagAsModified();
|
|
}
|
|
|
|
void MWWorld::ContainerStore::addInitialItem (const std::string& id, const std::string& owner,
|
|
int count, bool topLevel, const std::string& levItem)
|
|
{
|
|
if (count == 0) return; //Don't restock with nothing.
|
|
try {
|
|
ManualRef ref (MWBase::Environment::get().getWorld()->getStore(), id, count);
|
|
|
|
if (ref.getPtr().getTypeName()==typeid (ESM::ItemLevList).name())
|
|
{
|
|
const ESM::ItemLevList* levItemList = ref.getPtr().get<ESM::ItemLevList>()->mBase;
|
|
|
|
if (topLevel && std::abs(count) > 1 && levItemList->mFlags & ESM::ItemLevList::Each)
|
|
{
|
|
for (int i=0; i<std::abs(count); ++i)
|
|
addInitialItem(id, owner, count > 0 ? 1 : -1, true, levItemList->mId);
|
|
return;
|
|
}
|
|
else
|
|
{
|
|
std::string itemId = MWMechanics::getLevelledItem(ref.getPtr().get<ESM::ItemLevList>()->mBase, false);
|
|
if (itemId.empty())
|
|
return;
|
|
addInitialItem(itemId, owner, count, false, levItemList->mId);
|
|
}
|
|
}
|
|
else
|
|
{
|
|
// A negative count indicates restocking items
|
|
// For a restocking levelled item, remember what we spawned so we can delete it later when the merchant restocks
|
|
if (!levItem.empty() && count < 0)
|
|
{
|
|
//If there is no item in map, insert it
|
|
std::map<std::pair<std::string, std::string>, int>::iterator itemInMap =
|
|
mLevelledItemMap.insert(std::make_pair(std::make_pair(id, levItem), 0)).first;
|
|
//Update spawned count
|
|
itemInMap->second += std::abs(count);
|
|
}
|
|
count = std::abs(count);
|
|
|
|
ref.getPtr().getCellRef().setOwner(owner);
|
|
addImp (ref.getPtr(), count);
|
|
}
|
|
}
|
|
catch (const std::exception& e)
|
|
{
|
|
std::cerr << "Warning: MWWorld::ContainerStore::addInitialItem: " << e.what() << std::endl;
|
|
}
|
|
|
|
}
|
|
|
|
void MWWorld::ContainerStore::restock (const ESM::InventoryList& items, const MWWorld::Ptr& ptr, const std::string& owner)
|
|
{
|
|
//allowedForReplace - Holds information about how many items from the list were not sold;
|
|
// Hence, tells us how many items we don't need to restock.
|
|
//allowedForReplace[list] <- How many items we should generate(how many of these were sold)
|
|
std::map<std::string, int> allowedForReplace;
|
|
|
|
//Check which lists need restocking:
|
|
for (std::map<std::pair<std::string, std::string>, int>::iterator it = mLevelledItemMap.begin(); it != mLevelledItemMap.end();)
|
|
{
|
|
int spawnedCount = it->second; //How many items should be in shop originally
|
|
int itemCount = count(it->first.first); //How many items are there in shop now
|
|
//If something was not sold
|
|
if(itemCount >= spawnedCount)
|
|
{
|
|
const std::string& parent = it->first.second;
|
|
// Security check for old saves:
|
|
//If item is imported from old save(doesn't have an parent) and wasn't sold
|
|
if(parent == "")
|
|
{
|
|
//Remove it, from shop,
|
|
remove(it->first.first, itemCount, ptr);//ptr is the NPC
|
|
//And remove it from map, so that when we restock, the new item will have proper parent.
|
|
mLevelledItemMap.erase(it++);
|
|
continue;
|
|
}
|
|
//Create the entry if it does not exist yet
|
|
std::map<std::string, int>::iterator listInMap = allowedForReplace.insert(
|
|
std::make_pair(it->first.second, 0)).first;
|
|
//And signal that we don't need to restock item from this list
|
|
listInMap->second += std::abs(itemCount);
|
|
}
|
|
//If every of the item was sold
|
|
else if (itemCount == 0)
|
|
{
|
|
mLevelledItemMap.erase(it++);
|
|
continue;
|
|
}
|
|
//If some was sold, but some remain
|
|
else
|
|
{
|
|
//Create entry if it does not exist yet
|
|
std::map<std::string, int>::iterator listInMap = allowedForReplace.insert(
|
|
std::make_pair(it->first.second, 0)).first;
|
|
//And signal that we don't need to restock all items from this list
|
|
listInMap->second += std::abs(itemCount);
|
|
//And update itemCount so we don't mistake it next time.
|
|
it->second = itemCount;
|
|
}
|
|
++it;
|
|
}
|
|
|
|
//Restock:
|
|
//For every item that NPC could have
|
|
for (std::vector<ESM::ContItem>::const_iterator it = items.mList.begin(); it != items.mList.end(); ++it)
|
|
{
|
|
//If he shouldn't have it restocked, don't restock it.
|
|
if (it->mCount >= 0)
|
|
continue;
|
|
|
|
std::string itemOrList = Misc::StringUtils::lowerCase(it->mItem.toString());
|
|
|
|
//If it's levelled list, restock if there's need to do so.
|
|
if (MWBase::Environment::get().getWorld()->getStore().get<ESM::ItemLevList>().search(it->mItem.toString()))
|
|
{
|
|
std::map<std::string, int>::iterator listInMap = allowedForReplace.find(itemOrList);
|
|
|
|
int restockNum = std::abs(it->mCount);
|
|
//If we know we must restock less, take it into account
|
|
if(listInMap != allowedForReplace.end())
|
|
restockNum -= std::min(restockNum, listInMap->second);
|
|
//restock
|
|
addInitialItem(itemOrList, owner, -restockNum, true);
|
|
}
|
|
else
|
|
{
|
|
//Restocking static item - just restock to the max count
|
|
int currentCount = count(itemOrList);
|
|
if (currentCount < std::abs(it->mCount))
|
|
addInitialItem(itemOrList, owner, -(std::abs(it->mCount) - currentCount), true);
|
|
}
|
|
}
|
|
flagAsModified();
|
|
}
|
|
|
|
void MWWorld::ContainerStore::clear()
|
|
{
|
|
for (ContainerStoreIterator iter (begin()); iter!=end(); ++iter)
|
|
iter->getRefData().setCount (0);
|
|
|
|
flagAsModified();
|
|
}
|
|
|
|
void MWWorld::ContainerStore::flagAsModified()
|
|
{
|
|
mWeightUpToDate = false;
|
|
}
|
|
|
|
float MWWorld::ContainerStore::getWeight() const
|
|
{
|
|
if (!mWeightUpToDate)
|
|
{
|
|
mCachedWeight = 0;
|
|
|
|
mCachedWeight += getTotalWeight (potions);
|
|
mCachedWeight += getTotalWeight (appas);
|
|
mCachedWeight += getTotalWeight (armors);
|
|
mCachedWeight += getTotalWeight (books);
|
|
mCachedWeight += getTotalWeight (clothes);
|
|
mCachedWeight += getTotalWeight (ingreds);
|
|
mCachedWeight += getTotalWeight (lights);
|
|
mCachedWeight += getTotalWeight (lockpicks);
|
|
mCachedWeight += getTotalWeight (miscItems);
|
|
mCachedWeight += getTotalWeight (probes);
|
|
mCachedWeight += getTotalWeight (repairs);
|
|
mCachedWeight += getTotalWeight (weapons);
|
|
|
|
mWeightUpToDate = true;
|
|
}
|
|
|
|
return mCachedWeight;
|
|
}
|
|
|
|
int MWWorld::ContainerStore::getType (const ConstPtr& ptr)
|
|
{
|
|
if (ptr.isEmpty())
|
|
throw std::runtime_error ("can't put a non-existent object into a container");
|
|
|
|
if (ptr.getTypeName()==typeid (ESM::Potion).name())
|
|
return Type_Potion;
|
|
|
|
if (ptr.getTypeName()==typeid (ESM::Apparatus).name())
|
|
return Type_Apparatus;
|
|
|
|
if (ptr.getTypeName()==typeid (ESM::Armor).name())
|
|
return Type_Armor;
|
|
|
|
if (ptr.getTypeName()==typeid (ESM::Book).name())
|
|
return Type_Book;
|
|
|
|
if (ptr.getTypeName()==typeid (ESM::Clothing).name())
|
|
return Type_Clothing;
|
|
|
|
if (ptr.getTypeName()==typeid (ESM::Ingredient).name())
|
|
return Type_Ingredient;
|
|
|
|
if (ptr.getTypeName()==typeid (ESM::Light).name())
|
|
return Type_Light;
|
|
|
|
if (ptr.getTypeName()==typeid (ESM::Lockpick).name())
|
|
return Type_Lockpick;
|
|
|
|
if (ptr.getTypeName()==typeid (ESM::Miscellaneous).name())
|
|
return Type_Miscellaneous;
|
|
|
|
if (ptr.getTypeName()==typeid (ESM::Probe).name())
|
|
return Type_Probe;
|
|
|
|
if (ptr.getTypeName()==typeid (ESM::Repair).name())
|
|
return Type_Repair;
|
|
|
|
if (ptr.getTypeName()==typeid (ESM::Weapon).name())
|
|
return Type_Weapon;
|
|
|
|
throw std::runtime_error (
|
|
"Object '" + ptr.getCellRef().getRefId() + "' of type " + ptr.getTypeName() + " can not be placed into a container");
|
|
}
|
|
|
|
MWWorld::Ptr MWWorld::ContainerStore::search (const std::string& id)
|
|
{
|
|
{
|
|
Ptr ptr = searchId (potions, id, this);
|
|
if (!ptr.isEmpty())
|
|
return ptr;
|
|
}
|
|
|
|
{
|
|
Ptr ptr = searchId (appas, id, this);
|
|
if (!ptr.isEmpty())
|
|
return ptr;
|
|
}
|
|
|
|
{
|
|
Ptr ptr = searchId (armors, id, this);
|
|
if (!ptr.isEmpty())
|
|
return ptr;
|
|
}
|
|
|
|
{
|
|
Ptr ptr = searchId (books, id, this);
|
|
if (!ptr.isEmpty())
|
|
return ptr;
|
|
}
|
|
|
|
{
|
|
Ptr ptr = searchId (clothes, id, this);
|
|
if (!ptr.isEmpty())
|
|
return ptr;
|
|
}
|
|
|
|
{
|
|
Ptr ptr = searchId (ingreds, id, this);
|
|
if (!ptr.isEmpty())
|
|
return ptr;
|
|
}
|
|
|
|
{
|
|
Ptr ptr = searchId (lights, id, this);
|
|
if (!ptr.isEmpty())
|
|
return ptr;
|
|
}
|
|
|
|
{
|
|
Ptr ptr = searchId (lockpicks, id, this);
|
|
if (!ptr.isEmpty())
|
|
return ptr;
|
|
}
|
|
|
|
{
|
|
Ptr ptr = searchId (miscItems, id, this);
|
|
if (!ptr.isEmpty())
|
|
return ptr;
|
|
}
|
|
|
|
{
|
|
Ptr ptr = searchId (probes, id, this);
|
|
if (!ptr.isEmpty())
|
|
return ptr;
|
|
}
|
|
|
|
{
|
|
Ptr ptr = searchId (repairs, id, this);
|
|
if (!ptr.isEmpty())
|
|
return ptr;
|
|
}
|
|
|
|
{
|
|
Ptr ptr = searchId (weapons, id, this);
|
|
if (!ptr.isEmpty())
|
|
return ptr;
|
|
}
|
|
|
|
return Ptr();
|
|
}
|
|
|
|
void MWWorld::ContainerStore::writeState (ESM::InventoryState& state) const
|
|
{
|
|
state.mItems.clear();
|
|
|
|
int index = 0;
|
|
storeStates (potions, state, index);
|
|
storeStates (appas, state, index);
|
|
storeStates (armors, state, index, true);
|
|
storeStates (books, state, index, true); // not equipable as such, but for selectedEnchantItem
|
|
storeStates (clothes, state, index, true);
|
|
storeStates (ingreds, state, index);
|
|
storeStates (lockpicks, state, index, true);
|
|
storeStates (miscItems, state, index);
|
|
storeStates (probes, state, index, true);
|
|
storeStates (repairs, state, index);
|
|
storeStates (weapons, state, index, true);
|
|
storeStates (lights, state, index, true);
|
|
|
|
state.mLevelledItemMap = mLevelledItemMap;
|
|
}
|
|
|
|
void MWWorld::ContainerStore::readState (const ESM::InventoryState& inventory)
|
|
{
|
|
clear();
|
|
|
|
int index = 0;
|
|
for (std::vector<ESM::ObjectState>::const_iterator
|
|
iter (inventory.mItems.begin()); iter!=inventory.mItems.end(); ++iter)
|
|
{
|
|
const ESM::ObjectState& state = *iter;
|
|
|
|
int type = MWBase::Environment::get().getWorld()->getStore().find(state.mRef.mRefID);
|
|
|
|
int thisIndex = index++;
|
|
|
|
switch (type)
|
|
{
|
|
case ESM::REC_ALCH: getState (potions, state); break;
|
|
case ESM::REC_APPA: getState (appas, state); break;
|
|
case ESM::REC_ARMO: readEquipmentState (getState (armors, state), thisIndex, inventory); break;
|
|
case ESM::REC_BOOK: readEquipmentState (getState (books, state), thisIndex, inventory); break; // not equipable as such, but for selectedEnchantItem
|
|
case ESM::REC_CLOT: readEquipmentState (getState (clothes, state), thisIndex, inventory); break;
|
|
case ESM::REC_INGR: getState (ingreds, state); break;
|
|
case ESM::REC_LOCK: readEquipmentState (getState (lockpicks, state), thisIndex, inventory); break;
|
|
case ESM::REC_MISC: getState (miscItems, state); break;
|
|
case ESM::REC_PROB: readEquipmentState (getState (probes, state), thisIndex, inventory); break;
|
|
case ESM::REC_REPA: getState (repairs, state); break;
|
|
case ESM::REC_WEAP: readEquipmentState (getState (weapons, state), thisIndex, inventory); break;
|
|
case ESM::REC_LIGH: readEquipmentState (getState (lights, state), thisIndex, inventory); break;
|
|
case 0:
|
|
std::cerr << "Warning: Dropping reference to '" << state.mRef.mRefID << "' (object no longer exists)" << std::endl;
|
|
break;
|
|
default:
|
|
std::cerr << "Warning: Invalid item type in inventory state, refid " << state.mRef.mRefID << std::endl;
|
|
break;
|
|
}
|
|
}
|
|
|
|
|
|
mLevelledItemMap = inventory.mLevelledItemMap;
|
|
}
|
|
|
|
template<class PtrType>
|
|
template<class T>
|
|
void MWWorld::ContainerStoreIteratorBase<PtrType>::copy (const ContainerStoreIteratorBase<T>& src)
|
|
{
|
|
mType = src.mType;
|
|
mMask = src.mMask;
|
|
mContainer = src.mContainer;
|
|
mPtr = src.mPtr;
|
|
|
|
switch (src.mType)
|
|
{
|
|
case MWWorld::ContainerStore::Type_Potion: mPotion = src.mPotion; break;
|
|
case MWWorld::ContainerStore::Type_Apparatus: mApparatus = src.mApparatus; break;
|
|
case MWWorld::ContainerStore::Type_Armor: mArmor = src.mArmor; break;
|
|
case MWWorld::ContainerStore::Type_Book: mBook = src.mBook; break;
|
|
case MWWorld::ContainerStore::Type_Clothing: mClothing = src.mClothing; break;
|
|
case MWWorld::ContainerStore::Type_Ingredient: mIngredient = src.mIngredient; break;
|
|
case MWWorld::ContainerStore::Type_Light: mLight = src.mLight; break;
|
|
case MWWorld::ContainerStore::Type_Lockpick: mLockpick = src.mLockpick; break;
|
|
case MWWorld::ContainerStore::Type_Miscellaneous: mMiscellaneous = src.mMiscellaneous; break;
|
|
case MWWorld::ContainerStore::Type_Probe: mProbe = src.mProbe; break;
|
|
case MWWorld::ContainerStore::Type_Repair: mRepair = src.mRepair; break;
|
|
case MWWorld::ContainerStore::Type_Weapon: mWeapon = src.mWeapon; break;
|
|
case -1: break;
|
|
default: assert(0);
|
|
}
|
|
}
|
|
|
|
template<class PtrType>
|
|
void MWWorld::ContainerStoreIteratorBase<PtrType>::incType()
|
|
{
|
|
if (mType==0)
|
|
mType = 1;
|
|
else if (mType!=-1)
|
|
{
|
|
mType <<= 1;
|
|
|
|
if (mType>ContainerStore::Type_Last)
|
|
mType = -1;
|
|
}
|
|
}
|
|
|
|
template<class PtrType>
|
|
void MWWorld::ContainerStoreIteratorBase<PtrType>::nextType()
|
|
{
|
|
while (mType!=-1)
|
|
{
|
|
incType();
|
|
|
|
if ((mType & mMask) && mType>0)
|
|
if (resetIterator())
|
|
break;
|
|
}
|
|
}
|
|
|
|
template<class PtrType>
|
|
bool MWWorld::ContainerStoreIteratorBase<PtrType>::resetIterator()
|
|
{
|
|
switch (mType)
|
|
{
|
|
case ContainerStore::Type_Potion:
|
|
|
|
mPotion = mContainer->potions.mList.begin();
|
|
return mPotion!=mContainer->potions.mList.end();
|
|
|
|
case ContainerStore::Type_Apparatus:
|
|
|
|
mApparatus = mContainer->appas.mList.begin();
|
|
return mApparatus!=mContainer->appas.mList.end();
|
|
|
|
case ContainerStore::Type_Armor:
|
|
|
|
mArmor = mContainer->armors.mList.begin();
|
|
return mArmor!=mContainer->armors.mList.end();
|
|
|
|
case ContainerStore::Type_Book:
|
|
|
|
mBook = mContainer->books.mList.begin();
|
|
return mBook!=mContainer->books.mList.end();
|
|
|
|
case ContainerStore::Type_Clothing:
|
|
|
|
mClothing = mContainer->clothes.mList.begin();
|
|
return mClothing!=mContainer->clothes.mList.end();
|
|
|
|
case ContainerStore::Type_Ingredient:
|
|
|
|
mIngredient = mContainer->ingreds.mList.begin();
|
|
return mIngredient!=mContainer->ingreds.mList.end();
|
|
|
|
case ContainerStore::Type_Light:
|
|
|
|
mLight = mContainer->lights.mList.begin();
|
|
return mLight!=mContainer->lights.mList.end();
|
|
|
|
case ContainerStore::Type_Lockpick:
|
|
|
|
mLockpick = mContainer->lockpicks.mList.begin();
|
|
return mLockpick!=mContainer->lockpicks.mList.end();
|
|
|
|
case ContainerStore::Type_Miscellaneous:
|
|
|
|
mMiscellaneous = mContainer->miscItems.mList.begin();
|
|
return mMiscellaneous!=mContainer->miscItems.mList.end();
|
|
|
|
case ContainerStore::Type_Probe:
|
|
|
|
mProbe = mContainer->probes.mList.begin();
|
|
return mProbe!=mContainer->probes.mList.end();
|
|
|
|
case ContainerStore::Type_Repair:
|
|
|
|
mRepair = mContainer->repairs.mList.begin();
|
|
return mRepair!=mContainer->repairs.mList.end();
|
|
|
|
case ContainerStore::Type_Weapon:
|
|
|
|
mWeapon = mContainer->weapons.mList.begin();
|
|
return mWeapon!=mContainer->weapons.mList.end();
|
|
}
|
|
|
|
return false;
|
|
}
|
|
|
|
template<class PtrType>
|
|
bool MWWorld::ContainerStoreIteratorBase<PtrType>::incIterator()
|
|
{
|
|
switch (mType)
|
|
{
|
|
case ContainerStore::Type_Potion:
|
|
|
|
++mPotion;
|
|
return mPotion==mContainer->potions.mList.end();
|
|
|
|
case ContainerStore::Type_Apparatus:
|
|
|
|
++mApparatus;
|
|
return mApparatus==mContainer->appas.mList.end();
|
|
|
|
case ContainerStore::Type_Armor:
|
|
|
|
++mArmor;
|
|
return mArmor==mContainer->armors.mList.end();
|
|
|
|
case ContainerStore::Type_Book:
|
|
|
|
++mBook;
|
|
return mBook==mContainer->books.mList.end();
|
|
|
|
case ContainerStore::Type_Clothing:
|
|
|
|
++mClothing;
|
|
return mClothing==mContainer->clothes.mList.end();
|
|
|
|
case ContainerStore::Type_Ingredient:
|
|
|
|
++mIngredient;
|
|
return mIngredient==mContainer->ingreds.mList.end();
|
|
|
|
case ContainerStore::Type_Light:
|
|
|
|
++mLight;
|
|
return mLight==mContainer->lights.mList.end();
|
|
|
|
case ContainerStore::Type_Lockpick:
|
|
|
|
++mLockpick;
|
|
return mLockpick==mContainer->lockpicks.mList.end();
|
|
|
|
case ContainerStore::Type_Miscellaneous:
|
|
|
|
++mMiscellaneous;
|
|
return mMiscellaneous==mContainer->miscItems.mList.end();
|
|
|
|
case ContainerStore::Type_Probe:
|
|
|
|
++mProbe;
|
|
return mProbe==mContainer->probes.mList.end();
|
|
|
|
case ContainerStore::Type_Repair:
|
|
|
|
++mRepair;
|
|
return mRepair==mContainer->repairs.mList.end();
|
|
|
|
case ContainerStore::Type_Weapon:
|
|
|
|
++mWeapon;
|
|
return mWeapon==mContainer->weapons.mList.end();
|
|
}
|
|
|
|
return true;
|
|
}
|
|
|
|
|
|
template<class PtrType>
|
|
template<class T>
|
|
bool MWWorld::ContainerStoreIteratorBase<PtrType>::isEqual (const ContainerStoreIteratorBase<T>& other) const
|
|
{
|
|
if (mContainer!=other.mContainer)
|
|
return false;
|
|
|
|
if (mType!=other.mType)
|
|
return false;
|
|
|
|
switch (mType)
|
|
{
|
|
case ContainerStore::Type_Potion: return mPotion==other.mPotion;
|
|
case ContainerStore::Type_Apparatus: return mApparatus==other.mApparatus;
|
|
case ContainerStore::Type_Armor: return mArmor==other.mArmor;
|
|
case ContainerStore::Type_Book: return mBook==other.mBook;
|
|
case ContainerStore::Type_Clothing: return mClothing==other.mClothing;
|
|
case ContainerStore::Type_Ingredient: return mIngredient==other.mIngredient;
|
|
case ContainerStore::Type_Light: return mLight==other.mLight;
|
|
case ContainerStore::Type_Lockpick: return mLockpick==other.mLockpick;
|
|
case ContainerStore::Type_Miscellaneous: return mMiscellaneous==other.mMiscellaneous;
|
|
case ContainerStore::Type_Probe: return mProbe==other.mProbe;
|
|
case ContainerStore::Type_Repair: return mRepair==other.mRepair;
|
|
case ContainerStore::Type_Weapon: return mWeapon==other.mWeapon;
|
|
case -1: return true;
|
|
}
|
|
|
|
return false;
|
|
}
|
|
|
|
template<class PtrType>
|
|
PtrType *MWWorld::ContainerStoreIteratorBase<PtrType>::operator->() const
|
|
{
|
|
mPtr = **this;
|
|
return &mPtr;
|
|
}
|
|
|
|
template<class PtrType>
|
|
PtrType MWWorld::ContainerStoreIteratorBase<PtrType>::operator*() const
|
|
{
|
|
PtrType ptr;
|
|
|
|
switch (mType)
|
|
{
|
|
case ContainerStore::Type_Potion: ptr = PtrType (&*mPotion, 0); break;
|
|
case ContainerStore::Type_Apparatus: ptr = PtrType (&*mApparatus, 0); break;
|
|
case ContainerStore::Type_Armor: ptr = PtrType (&*mArmor, 0); break;
|
|
case ContainerStore::Type_Book: ptr = PtrType (&*mBook, 0); break;
|
|
case ContainerStore::Type_Clothing: ptr = PtrType (&*mClothing, 0); break;
|
|
case ContainerStore::Type_Ingredient: ptr = PtrType (&*mIngredient, 0); break;
|
|
case ContainerStore::Type_Light: ptr = PtrType (&*mLight, 0); break;
|
|
case ContainerStore::Type_Lockpick: ptr = PtrType (&*mLockpick, 0); break;
|
|
case ContainerStore::Type_Miscellaneous: ptr = PtrType (&*mMiscellaneous, 0); break;
|
|
case ContainerStore::Type_Probe: ptr = PtrType (&*mProbe, 0); break;
|
|
case ContainerStore::Type_Repair: ptr = PtrType (&*mRepair, 0); break;
|
|
case ContainerStore::Type_Weapon: ptr = PtrType (&*mWeapon, 0); break;
|
|
}
|
|
|
|
if (ptr.isEmpty())
|
|
throw std::runtime_error ("invalid iterator");
|
|
|
|
ptr.setContainerStore (mContainer);
|
|
|
|
return ptr;
|
|
}
|
|
|
|
template<class PtrType>
|
|
MWWorld::ContainerStoreIteratorBase<PtrType>& MWWorld::ContainerStoreIteratorBase<PtrType>::operator++()
|
|
{
|
|
do
|
|
{
|
|
if (incIterator())
|
|
nextType();
|
|
}
|
|
while (mType!=-1 && !(**this).getRefData().getCount());
|
|
|
|
return *this;
|
|
}
|
|
|
|
template<class PtrType>
|
|
MWWorld::ContainerStoreIteratorBase<PtrType> MWWorld::ContainerStoreIteratorBase<PtrType>::operator++ (int)
|
|
{
|
|
ContainerStoreIteratorBase<PtrType> iter (*this);
|
|
++*this;
|
|
return iter;
|
|
}
|
|
|
|
template<class PtrType>
|
|
MWWorld::ContainerStoreIteratorBase<PtrType>& MWWorld::ContainerStoreIteratorBase<PtrType>::operator= (const ContainerStoreIteratorBase<PtrType>& rhs)
|
|
{
|
|
if (this!=&rhs)
|
|
{
|
|
copy(rhs);
|
|
}
|
|
return *this;
|
|
}
|
|
|
|
template<class PtrType>
|
|
int MWWorld::ContainerStoreIteratorBase<PtrType>::getType() const
|
|
{
|
|
return mType;
|
|
}
|
|
|
|
template<class PtrType>
|
|
const MWWorld::ContainerStore *MWWorld::ContainerStoreIteratorBase<PtrType>::getContainerStore() const
|
|
{
|
|
return mContainer;
|
|
}
|
|
|
|
template<class PtrType>
|
|
MWWorld::ContainerStoreIteratorBase<PtrType>::ContainerStoreIteratorBase (ContainerStoreType container)
|
|
: mType (-1), mMask (0), mContainer (container)
|
|
{}
|
|
|
|
template<class PtrType>
|
|
MWWorld::ContainerStoreIteratorBase<PtrType>::ContainerStoreIteratorBase (int mask, ContainerStoreType container)
|
|
: mType (0), mMask (mask), mContainer (container)
|
|
{
|
|
nextType();
|
|
|
|
if (mType==-1 || (**this).getRefData().getCount())
|
|
return;
|
|
|
|
++*this;
|
|
}
|
|
|
|
template<class PtrType>
|
|
MWWorld::ContainerStoreIteratorBase<PtrType>::ContainerStoreIteratorBase (ContainerStoreType container, typename Iterator<ESM::Potion>::type iterator)
|
|
: mType(MWWorld::ContainerStore::Type_Potion), mMask(MWWorld::ContainerStore::Type_All), mContainer(container), mPotion(iterator){}
|
|
|
|
template<class PtrType>
|
|
MWWorld::ContainerStoreIteratorBase<PtrType>::ContainerStoreIteratorBase (ContainerStoreType container, typename Iterator<ESM::Apparatus>::type iterator)
|
|
: mType(MWWorld::ContainerStore::Type_Apparatus), mMask(MWWorld::ContainerStore::Type_All), mContainer(container), mApparatus(iterator){}
|
|
|
|
template<class PtrType>
|
|
MWWorld::ContainerStoreIteratorBase<PtrType>::ContainerStoreIteratorBase (ContainerStoreType container, typename Iterator<ESM::Armor>::type iterator)
|
|
: mType(MWWorld::ContainerStore::Type_Armor), mMask(MWWorld::ContainerStore::Type_All), mContainer(container), mArmor(iterator){}
|
|
|
|
template<class PtrType>
|
|
MWWorld::ContainerStoreIteratorBase<PtrType>::ContainerStoreIteratorBase (ContainerStoreType container, typename Iterator<ESM::Book>::type iterator)
|
|
: mType(MWWorld::ContainerStore::Type_Book), mMask(MWWorld::ContainerStore::Type_All), mContainer(container), mBook(iterator){}
|
|
|
|
template<class PtrType>
|
|
MWWorld::ContainerStoreIteratorBase<PtrType>::ContainerStoreIteratorBase (ContainerStoreType container, typename Iterator<ESM::Clothing>::type iterator)
|
|
: mType(MWWorld::ContainerStore::Type_Clothing), mMask(MWWorld::ContainerStore::Type_All), mContainer(container), mClothing(iterator){}
|
|
|
|
template<class PtrType>
|
|
MWWorld::ContainerStoreIteratorBase<PtrType>::ContainerStoreIteratorBase (ContainerStoreType container, typename Iterator<ESM::Ingredient>::type iterator)
|
|
: mType(MWWorld::ContainerStore::Type_Ingredient), mMask(MWWorld::ContainerStore::Type_All), mContainer(container), mIngredient(iterator){}
|
|
|
|
template<class PtrType>
|
|
MWWorld::ContainerStoreIteratorBase<PtrType>::ContainerStoreIteratorBase (ContainerStoreType container, typename Iterator<ESM::Light>::type iterator)
|
|
: mType(MWWorld::ContainerStore::Type_Light), mMask(MWWorld::ContainerStore::Type_All), mContainer(container), mLight(iterator){}
|
|
|
|
template<class PtrType>
|
|
MWWorld::ContainerStoreIteratorBase<PtrType>::ContainerStoreIteratorBase (ContainerStoreType container, typename Iterator<ESM::Lockpick>::type iterator)
|
|
: mType(MWWorld::ContainerStore::Type_Lockpick), mMask(MWWorld::ContainerStore::Type_All), mContainer(container), mLockpick(iterator){}
|
|
|
|
template<class PtrType>
|
|
MWWorld::ContainerStoreIteratorBase<PtrType>::ContainerStoreIteratorBase (ContainerStoreType container, typename Iterator<ESM::Miscellaneous>::type iterator)
|
|
: mType(MWWorld::ContainerStore::Type_Miscellaneous), mMask(MWWorld::ContainerStore::Type_All), mContainer(container), mMiscellaneous(iterator){}
|
|
|
|
template<class PtrType>
|
|
MWWorld::ContainerStoreIteratorBase<PtrType>::ContainerStoreIteratorBase (ContainerStoreType container, typename Iterator<ESM::Probe>::type iterator)
|
|
: mType(MWWorld::ContainerStore::Type_Probe), mMask(MWWorld::ContainerStore::Type_All), mContainer(container), mProbe(iterator){}
|
|
|
|
template<class PtrType>
|
|
MWWorld::ContainerStoreIteratorBase<PtrType>::ContainerStoreIteratorBase (ContainerStoreType container, typename Iterator<ESM::Repair>::type iterator)
|
|
: mType(MWWorld::ContainerStore::Type_Repair), mMask(MWWorld::ContainerStore::Type_All), mContainer(container), mRepair(iterator){}
|
|
|
|
template<class PtrType>
|
|
MWWorld::ContainerStoreIteratorBase<PtrType>::ContainerStoreIteratorBase (ContainerStoreType container, typename Iterator<ESM::Weapon>::type iterator)
|
|
: mType(MWWorld::ContainerStore::Type_Weapon), mMask(MWWorld::ContainerStore::Type_All), mContainer(container), mWeapon(iterator){}
|
|
|
|
|
|
template<class T, class U>
|
|
bool MWWorld::operator== (const ContainerStoreIteratorBase<T>& left, const ContainerStoreIteratorBase<U>& right)
|
|
{
|
|
return left.isEqual (right);
|
|
}
|
|
|
|
template<class T, class U>
|
|
bool MWWorld::operator!= (const ContainerStoreIteratorBase<T>& left, const ContainerStoreIteratorBase<U>& right)
|
|
{
|
|
return !(left==right);
|
|
}
|
|
|
|
template class MWWorld::ContainerStoreIteratorBase<MWWorld::Ptr>;
|
|
template class MWWorld::ContainerStoreIteratorBase<MWWorld::ConstPtr>;
|
|
|
|
template bool MWWorld::operator== (const ContainerStoreIteratorBase<Ptr>& left, const ContainerStoreIteratorBase<Ptr>& right);
|
|
template bool MWWorld::operator!= (const ContainerStoreIteratorBase<Ptr>& left, const ContainerStoreIteratorBase<Ptr>& right);
|
|
template bool MWWorld::operator== (const ContainerStoreIteratorBase<ConstPtr>& left, const ContainerStoreIteratorBase<ConstPtr>& right);
|
|
template bool MWWorld::operator!= (const ContainerStoreIteratorBase<ConstPtr>& left, const ContainerStoreIteratorBase<ConstPtr>& right);
|
|
template bool MWWorld::operator== (const ContainerStoreIteratorBase<ConstPtr>& left, const ContainerStoreIteratorBase<Ptr>& right);
|
|
template bool MWWorld::operator!= (const ContainerStoreIteratorBase<ConstPtr>& left, const ContainerStoreIteratorBase<Ptr>& right);
|
|
template bool MWWorld::operator== (const ContainerStoreIteratorBase<Ptr>& left, const ContainerStoreIteratorBase<ConstPtr>& right);
|
|
template bool MWWorld::operator!= (const ContainerStoreIteratorBase<Ptr>& left, const ContainerStoreIteratorBase<ConstPtr>& right);
|
|
|
|
template void MWWorld::ContainerStoreIteratorBase<MWWorld::Ptr>::copy(const ContainerStoreIteratorBase<Ptr>& src);
|
|
template void MWWorld::ContainerStoreIteratorBase<MWWorld::ConstPtr>::copy(const ContainerStoreIteratorBase<Ptr>& src);
|
|
template void MWWorld::ContainerStoreIteratorBase<MWWorld::ConstPtr>::copy(const ContainerStoreIteratorBase<ConstPtr>& src);
|