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::fill (const ESM::InventoryList& items, const ESMS::ESMStore& store) { for (std::vector<ESM::ContItem>::const_iterator iter (items.mList.begin()); iter!=items.mList.end(); ++iter) { ManualRef ref (store, iter->mItem.toString()); if (ref.getPtr().getTypeName()==typeid (ESM::ItemLevList).name()) { /// \todo implement leveled item lists continue; } ref.getPtr().getRefData().setCount (std::abs(iter->mCount)); /// \todo implement item restocking (indicated by negative count) add (ref.getPtr()); } flagAsModified(); }
void MWWorld::ContainerStore::addInitialItem (const std::string& id, const std::string& owner, int count, unsigned char failChance, bool topLevel) { count = std::abs(count); /// \todo implement item restocking (indicated by negative count) try { ManualRef ref (MWBase::Environment::get().getWorld()->getStore(), id); if (ref.getPtr().getTypeName()==typeid (ESM::ItemLevList).name()) { const ESM::ItemLevList* levItem = ref.getPtr().get<ESM::ItemLevList>()->mBase; const std::vector<ESM::LeveledListBase::LevelItem>& items = levItem->mList; MWWorld::Ptr player = MWBase::Environment::get().getWorld()->getPlayer().getPlayer(); int playerLevel = MWWorld::Class::get(player).getCreatureStats(player).getLevel(); failChance += levItem->mChanceNone; if (topLevel && count > 1 && levItem->mFlags & ESM::ItemLevList::Each) { for (int i=0; i<count; ++i) addInitialItem(id, owner, 1, failChance, false); return; } float random = static_cast<float> (std::rand()) / RAND_MAX; if (random >= failChance/100.f) { std::vector<std::string> candidates; int highestLevel = 0; for (std::vector<ESM::LeveledListBase::LevelItem>::const_iterator it = items.begin(); it != items.end(); ++it) { if (it->mLevel > highestLevel) highestLevel = it->mLevel; } std::pair<int, std::string> highest = std::make_pair(-1, ""); for (std::vector<ESM::LeveledListBase::LevelItem>::const_iterator it = items.begin(); it != items.end(); ++it) { if (playerLevel >= it->mLevel && (levItem->mFlags & ESM::ItemLevList::AllLevels || it->mLevel == highestLevel)) { candidates.push_back(it->mId); if (it->mLevel >= highest.first) highest = std::make_pair(it->mLevel, it->mId); } } if (candidates.empty()) return; std::string item = candidates[std::rand()%candidates.size()]; addInitialItem(item, owner, count, failChance, false); } } else { ref.getPtr().getRefData().setCount (count); ref.getPtr().getCellRef().mOwner = owner; addImp (ref.getPtr()); } } catch (std::logic_error& e) { // Vanilla doesn't fail on nonexistent items in levelled lists std::cerr << "Warning: ignoring nonexistent item '" << id << "'" << std::endl; return; } }