|
|
|
@ -23,6 +23,21 @@
|
|
|
|
|
|
|
|
|
|
namespace
|
|
|
|
|
{
|
|
|
|
|
void addScripts(MWWorld::ContainerStore& store, MWWorld::CellStore* cell)
|
|
|
|
|
{
|
|
|
|
|
auto& scripts = MWBase::Environment::get().getWorld()->getLocalScripts();
|
|
|
|
|
for(const MWWorld::Ptr& ptr : store)
|
|
|
|
|
{
|
|
|
|
|
const std::string& script = ptr.getClass().getScript(ptr);
|
|
|
|
|
if(!script.empty())
|
|
|
|
|
{
|
|
|
|
|
MWWorld::Ptr item = ptr;
|
|
|
|
|
item.mCell = cell;
|
|
|
|
|
scripts.add(script, item);
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
template<typename T>
|
|
|
|
|
float getTotalWeight (const MWWorld::CellRefList<T>& cellRefList)
|
|
|
|
|
{
|
|
|
|
@ -44,6 +59,7 @@ namespace
|
|
|
|
|
MWWorld::Ptr searchId (MWWorld::CellRefList<T>& list, const std::string& id,
|
|
|
|
|
MWWorld::ContainerStore *store)
|
|
|
|
|
{
|
|
|
|
|
store->resolve();
|
|
|
|
|
std::string id2 = Misc::StringUtils::lowerCase (id);
|
|
|
|
|
|
|
|
|
|
for (typename MWWorld::CellRefList<T>::List::iterator iter (list.mList.begin());
|
|
|
|
@ -61,6 +77,18 @@ namespace
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
MWWorld::ResolutionListener::~ResolutionListener()
|
|
|
|
|
{
|
|
|
|
|
if(!mStore.mModified && mStore.mResolved && !mStore.mPtr.isEmpty())
|
|
|
|
|
{
|
|
|
|
|
for(const MWWorld::Ptr& ptr : mStore)
|
|
|
|
|
ptr.getRefData().setCount(0);
|
|
|
|
|
mStore.fillNonRandom(mStore.mPtr.get<ESM::Container>()->mBase->mInventory, "", mStore.mSeed);
|
|
|
|
|
addScripts(mStore, mStore.mPtr.mCell);
|
|
|
|
|
mStore.mResolved = false;
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
template<typename T>
|
|
|
|
|
MWWorld::ContainerStoreIterator MWWorld::ContainerStore::getState (CellRefList<T>& collection,
|
|
|
|
|
const ESM::ObjectState& state)
|
|
|
|
@ -119,7 +147,11 @@ MWWorld::ContainerStore::ContainerStore()
|
|
|
|
|
: mListener(nullptr)
|
|
|
|
|
, mRechargingItemsUpToDate(false)
|
|
|
|
|
, mCachedWeight (0)
|
|
|
|
|
, mWeightUpToDate (false) {}
|
|
|
|
|
, mWeightUpToDate (false)
|
|
|
|
|
, mModified(false)
|
|
|
|
|
, mResolved(false)
|
|
|
|
|
, mSeed()
|
|
|
|
|
, mPtr() {}
|
|
|
|
|
|
|
|
|
|
MWWorld::ContainerStore::~ContainerStore() {}
|
|
|
|
|
|
|
|
|
@ -153,22 +185,12 @@ 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;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
int MWWorld::ContainerStore::restockCount(const std::string &id)
|
|
|
|
|
int MWWorld::ContainerStore::count(const std::string &id) const
|
|
|
|
|
{
|
|
|
|
|
int total=0;
|
|
|
|
|
for (MWWorld::ContainerStoreIterator iter (begin()); iter!=end(); ++iter)
|
|
|
|
|
if (Misc::StringUtils::ciEqual(iter->getCellRef().getRefId(), id))
|
|
|
|
|
if (iter->getCellRef().getSoul().empty())
|
|
|
|
|
total += iter->getRefData().getCount();
|
|
|
|
|
for (const auto& iter : *this)
|
|
|
|
|
if (Misc::StringUtils::ciEqual(iter.getCellRef().getRefId(), id))
|
|
|
|
|
total += iter.getRefData().getCount();
|
|
|
|
|
return total;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
@ -185,9 +207,10 @@ void MWWorld::ContainerStore::setContListener(MWWorld::ContainerStoreListener* l
|
|
|
|
|
|
|
|
|
|
MWWorld::ContainerStoreIterator MWWorld::ContainerStore::unstack(const Ptr &ptr, const Ptr& container, int count)
|
|
|
|
|
{
|
|
|
|
|
resolve();
|
|
|
|
|
if (ptr.getRefData().getCount() <= count)
|
|
|
|
|
return end();
|
|
|
|
|
MWWorld::ContainerStoreIterator it = addNewStack(ptr, ptr.getRefData().getCount()-count);
|
|
|
|
|
MWWorld::ContainerStoreIterator it = addNewStack(ptr, subtractItems(ptr.getRefData().getCount(false), count));
|
|
|
|
|
const std::string script = it->getClass().getScript(*it);
|
|
|
|
|
if (!script.empty())
|
|
|
|
|
MWBase::Environment::get().getWorld()->getLocalScripts().add(script, *it);
|
|
|
|
@ -199,6 +222,7 @@ MWWorld::ContainerStoreIterator MWWorld::ContainerStore::unstack(const Ptr &ptr,
|
|
|
|
|
|
|
|
|
|
MWWorld::ContainerStoreIterator MWWorld::ContainerStore::restack(const MWWorld::Ptr& item)
|
|
|
|
|
{
|
|
|
|
|
resolve();
|
|
|
|
|
MWWorld::ContainerStoreIterator retval = end();
|
|
|
|
|
for (MWWorld::ContainerStoreIterator iter (begin()); iter != end(); ++iter)
|
|
|
|
|
{
|
|
|
|
@ -216,7 +240,7 @@ MWWorld::ContainerStoreIterator MWWorld::ContainerStore::restack(const MWWorld::
|
|
|
|
|
{
|
|
|
|
|
if (stacks(*iter, item))
|
|
|
|
|
{
|
|
|
|
|
iter->getRefData().setCount(iter->getRefData().getCount() + item.getRefData().getCount());
|
|
|
|
|
iter->getRefData().setCount(addItems(iter->getRefData().getCount(false), item.getRefData().getCount(false)));
|
|
|
|
|
item.getRefData().setCount(0);
|
|
|
|
|
retval = iter;
|
|
|
|
|
break;
|
|
|
|
@ -328,8 +352,10 @@ MWWorld::ContainerStoreIterator MWWorld::ContainerStore::add (const Ptr& itemPtr
|
|
|
|
|
return it;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
MWWorld::ContainerStoreIterator MWWorld::ContainerStore::addImp (const Ptr& ptr, int count)
|
|
|
|
|
MWWorld::ContainerStoreIterator MWWorld::ContainerStore::addImp (const Ptr& ptr, int count, bool markModified)
|
|
|
|
|
{
|
|
|
|
|
if(markModified)
|
|
|
|
|
resolve();
|
|
|
|
|
int type = getType(ptr);
|
|
|
|
|
|
|
|
|
|
const MWWorld::ESMStore &esmStore =
|
|
|
|
@ -345,7 +371,7 @@ MWWorld::ContainerStoreIterator MWWorld::ContainerStore::addImp (const Ptr& ptr,
|
|
|
|
|
{
|
|
|
|
|
if (Misc::StringUtils::ciEqual((*iter).getCellRef().getRefId(), MWWorld::ContainerStore::sGoldId))
|
|
|
|
|
{
|
|
|
|
|
iter->getRefData().setCount(iter->getRefData().getCount() + realCount);
|
|
|
|
|
iter->getRefData().setCount(addItems(iter->getRefData().getCount(false), realCount));
|
|
|
|
|
flagAsModified();
|
|
|
|
|
return iter;
|
|
|
|
|
}
|
|
|
|
@ -361,7 +387,7 @@ MWWorld::ContainerStoreIterator MWWorld::ContainerStore::addImp (const Ptr& ptr,
|
|
|
|
|
if (stacks(*iter, ptr))
|
|
|
|
|
{
|
|
|
|
|
// stack
|
|
|
|
|
iter->getRefData().setCount( iter->getRefData().getCount() + count );
|
|
|
|
|
iter->getRefData().setCount(addItems(iter->getRefData().getCount(false), count));
|
|
|
|
|
|
|
|
|
|
flagAsModified();
|
|
|
|
|
return iter;
|
|
|
|
@ -439,6 +465,7 @@ void MWWorld::ContainerStore::updateRechargingItems()
|
|
|
|
|
|
|
|
|
|
int MWWorld::ContainerStore::remove(const std::string& itemId, int count, const Ptr& actor)
|
|
|
|
|
{
|
|
|
|
|
resolve();
|
|
|
|
|
int toRemove = count;
|
|
|
|
|
|
|
|
|
|
for (ContainerStoreIterator iter(begin()); iter != end() && toRemove > 0; ++iter)
|
|
|
|
@ -465,6 +492,7 @@ bool MWWorld::ContainerStore::hasVisibleItems() const
|
|
|
|
|
int MWWorld::ContainerStore::remove(const Ptr& item, int count, const Ptr& actor)
|
|
|
|
|
{
|
|
|
|
|
assert(this == item.getContainerStore());
|
|
|
|
|
resolve();
|
|
|
|
|
|
|
|
|
|
int toRemove = count;
|
|
|
|
|
RefData& itemRef = item.getRefData();
|
|
|
|
@ -476,7 +504,7 @@ int MWWorld::ContainerStore::remove(const Ptr& item, int count, const Ptr& actor
|
|
|
|
|
}
|
|
|
|
|
else
|
|
|
|
|
{
|
|
|
|
|
itemRef.setCount(itemRef.getCount() - toRemove);
|
|
|
|
|
itemRef.setCount(subtractItems(itemRef.getCount(false), toRemove));
|
|
|
|
|
toRemove = 0;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
@ -490,20 +518,33 @@ int MWWorld::ContainerStore::remove(const Ptr& item, int count, const Ptr& actor
|
|
|
|
|
return count - toRemove;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
void MWWorld::ContainerStore::fill (const ESM::InventoryList& items, const std::string& owner)
|
|
|
|
|
void MWWorld::ContainerStore::fill (const ESM::InventoryList& items, const std::string& owner, Misc::Rng::Seed& seed)
|
|
|
|
|
{
|
|
|
|
|
for (const ESM::ContItem& iter : items.mList)
|
|
|
|
|
{
|
|
|
|
|
std::string id = Misc::StringUtils::lowerCase(iter.mItem);
|
|
|
|
|
addInitialItem(id, owner, iter.mCount, &seed);
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
flagAsModified();
|
|
|
|
|
mResolved = true;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
void MWWorld::ContainerStore::fillNonRandom (const ESM::InventoryList& items, const std::string& owner, unsigned int seed)
|
|
|
|
|
{
|
|
|
|
|
for (std::vector<ESM::ContItem>::const_iterator iter (items.mList.begin()); iter!=items.mList.end();
|
|
|
|
|
++iter)
|
|
|
|
|
mSeed = seed;
|
|
|
|
|
for (const ESM::ContItem& iter : items.mList)
|
|
|
|
|
{
|
|
|
|
|
std::string id = Misc::StringUtils::lowerCase(iter->mItem);
|
|
|
|
|
addInitialItem(id, owner, iter->mCount);
|
|
|
|
|
std::string id = Misc::StringUtils::lowerCase(iter.mItem);
|
|
|
|
|
addInitialItem(id, owner, iter.mCount, nullptr);
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
flagAsModified();
|
|
|
|
|
mResolved = false;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
void MWWorld::ContainerStore::addInitialItem (const std::string& id, const std::string& owner,
|
|
|
|
|
int count, bool topLevel, const std::string& levItem)
|
|
|
|
|
void MWWorld::ContainerStore::addInitialItem (const std::string& id, const std::string& owner, int count,
|
|
|
|
|
Misc::Rng::Seed* seed, bool topLevel, const std::string& levItem)
|
|
|
|
|
{
|
|
|
|
|
if (count == 0) return; //Don't restock with nothing.
|
|
|
|
|
try
|
|
|
|
@ -511,13 +552,13 @@ void MWWorld::ContainerStore::addInitialItem (const std::string& id, const std::
|
|
|
|
|
ManualRef ref (MWBase::Environment::get().getWorld()->getStore(), id, count);
|
|
|
|
|
if (ref.getPtr().getClass().getScript(ref.getPtr()).empty())
|
|
|
|
|
{
|
|
|
|
|
addInitialItemImp(ref.getPtr(), owner, count, topLevel, levItem);
|
|
|
|
|
addInitialItemImp(ref.getPtr(), owner, count, seed, topLevel, levItem);
|
|
|
|
|
}
|
|
|
|
|
else
|
|
|
|
|
{
|
|
|
|
|
// Adding just one item per time to make sure there isn't a stack of scripted items
|
|
|
|
|
for (int i = 0; i < abs(count); i++)
|
|
|
|
|
addInitialItemImp(ref.getPtr(), owner, count < 0 ? -1 : 1, topLevel, levItem);
|
|
|
|
|
for (int i = 0; i < std::abs(count); i++)
|
|
|
|
|
addInitialItemImp(ref.getPtr(), owner, count < 0 ? -1 : 1, seed, topLevel, levItem);
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
catch (const std::exception& e)
|
|
|
|
@ -526,137 +567,43 @@ void MWWorld::ContainerStore::addInitialItem (const std::string& id, const std::
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
void MWWorld::ContainerStore::addInitialItemImp(const MWWorld::Ptr& ptr, const std::string& owner,
|
|
|
|
|
int count, bool topLevel, const std::string& levItem)
|
|
|
|
|
void MWWorld::ContainerStore::addInitialItemImp(const MWWorld::Ptr& ptr, const std::string& owner, int count,
|
|
|
|
|
Misc::Rng::Seed* seed, bool topLevel, const std::string& levItem)
|
|
|
|
|
{
|
|
|
|
|
if (ptr.getTypeName()==typeid (ESM::ItemLevList).name())
|
|
|
|
|
{
|
|
|
|
|
if(!seed)
|
|
|
|
|
return;
|
|
|
|
|
const ESM::ItemLevList* levItemList = ptr.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(ptr.getCellRef().getRefId(), owner, count > 0 ? 1 : -1, true, levItemList->mId);
|
|
|
|
|
addInitialItem(ptr.getCellRef().getRefId(), owner, count > 0 ? 1 : -1, seed, true, levItemList->mId);
|
|
|
|
|
return;
|
|
|
|
|
}
|
|
|
|
|
else
|
|
|
|
|
{
|
|
|
|
|
std::string itemId = MWMechanics::getLevelledItem(ptr.get<ESM::ItemLevList>()->mBase, false);
|
|
|
|
|
std::string itemId = MWMechanics::getLevelledItem(ptr.get<ESM::ItemLevList>()->mBase, false, *seed);
|
|
|
|
|
if (itemId.empty())
|
|
|
|
|
return;
|
|
|
|
|
addInitialItem(itemId, owner, count, false, levItemList->mId);
|
|
|
|
|
addInitialItem(itemId, owner, count, seed, 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(ptr.getCellRef().getRefId(), levItem), 0)).first;
|
|
|
|
|
//Update spawned count
|
|
|
|
|
itemInMap->second += std::abs(count);
|
|
|
|
|
}
|
|
|
|
|
count = std::abs(count);
|
|
|
|
|
|
|
|
|
|
ptr.getCellRef().setOwner(owner);
|
|
|
|
|
addImp (ptr, count);
|
|
|
|
|
addImp (ptr, count, false);
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
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 = restockCount(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);
|
|
|
|
|
|
|
|
|
|
//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))
|
|
|
|
|
{
|
|
|
|
|
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 = restockCount(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();
|
|
|
|
|
mModified = true;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
void MWWorld::ContainerStore::flagAsModified()
|
|
|
|
@ -665,6 +612,45 @@ void MWWorld::ContainerStore::flagAsModified()
|
|
|
|
|
mRechargingItemsUpToDate = false;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
bool MWWorld::ContainerStore::isResolved() const
|
|
|
|
|
{
|
|
|
|
|
return mResolved;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
void MWWorld::ContainerStore::resolve()
|
|
|
|
|
{
|
|
|
|
|
if(!mResolved && !mPtr.isEmpty())
|
|
|
|
|
{
|
|
|
|
|
for(const MWWorld::Ptr& ptr : *this)
|
|
|
|
|
ptr.getRefData().setCount(0);
|
|
|
|
|
Misc::Rng::Seed seed{mSeed};
|
|
|
|
|
fill(mPtr.get<ESM::Container>()->mBase->mInventory, "", seed);
|
|
|
|
|
addScripts(*this, mPtr.mCell);
|
|
|
|
|
}
|
|
|
|
|
mModified = true;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
MWWorld::ResolutionHandle MWWorld::ContainerStore::resolveTemporarily()
|
|
|
|
|
{
|
|
|
|
|
if(mModified)
|
|
|
|
|
return {};
|
|
|
|
|
std::shared_ptr<ResolutionListener> listener = mResolutionListener.lock();
|
|
|
|
|
if(!listener)
|
|
|
|
|
{
|
|
|
|
|
listener = std::make_shared<ResolutionListener>(*this);
|
|
|
|
|
mResolutionListener = listener;
|
|
|
|
|
}
|
|
|
|
|
if(!mResolved && !mPtr.isEmpty())
|
|
|
|
|
{
|
|
|
|
|
for(const MWWorld::Ptr& ptr : *this)
|
|
|
|
|
ptr.getRefData().setCount(0);
|
|
|
|
|
Misc::Rng::Seed seed{mSeed};
|
|
|
|
|
fill(mPtr.get<ESM::Container>()->mBase->mInventory, "", seed);
|
|
|
|
|
addScripts(*this, mPtr.mCell);
|
|
|
|
|
}
|
|
|
|
|
return {listener};
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
float MWWorld::ContainerStore::getWeight() const
|
|
|
|
|
{
|
|
|
|
|
if (!mWeightUpToDate)
|
|
|
|
@ -761,6 +747,7 @@ MWWorld::Ptr MWWorld::ContainerStore::findReplacement(const std::string& id)
|
|
|
|
|
|
|
|
|
|
MWWorld::Ptr MWWorld::ContainerStore::search (const std::string& id)
|
|
|
|
|
{
|
|
|
|
|
resolve();
|
|
|
|
|
{
|
|
|
|
|
Ptr ptr = searchId (potions, id, this);
|
|
|
|
|
if (!ptr.isEmpty())
|
|
|
|
@ -836,6 +823,22 @@ MWWorld::Ptr MWWorld::ContainerStore::search (const std::string& id)
|
|
|
|
|
return Ptr();
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
int MWWorld::ContainerStore::addItems(int count1, int count2)
|
|
|
|
|
{
|
|
|
|
|
int sum = std::abs(count1) + std::abs(count2);
|
|
|
|
|
if(count1 < 0 || count2 < 0)
|
|
|
|
|
return -sum;
|
|
|
|
|
return sum;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
int MWWorld::ContainerStore::subtractItems(int count1, int count2)
|
|
|
|
|
{
|
|
|
|
|
int sum = std::abs(count1) - std::abs(count2);
|
|
|
|
|
if(count1 < 0 || count2 < 0)
|
|
|
|
|
return -sum;
|
|
|
|
|
return sum;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
void MWWorld::ContainerStore::writeState (ESM::InventoryState& state) const
|
|
|
|
|
{
|
|
|
|
|
state.mItems.clear();
|
|
|
|
@ -853,13 +856,13 @@ void MWWorld::ContainerStore::writeState (ESM::InventoryState& state) const
|
|
|
|
|
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();
|
|
|
|
|
mModified = true;
|
|
|
|
|
mResolved = true;
|
|
|
|
|
|
|
|
|
|
int index = 0;
|
|
|
|
|
for (std::vector<ESM::ObjectState>::const_iterator
|
|
|
|
@ -893,9 +896,6 @@ void MWWorld::ContainerStore::readState (const ESM::InventoryState& inventory)
|
|
|
|
|
break;
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
mLevelledItemMap = inventory.mLevelledItemMap;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
template<class PtrType>
|
|
|
|
|