MWWorld::ContainerStoreIterator MWWorld::ContainerStore::add (const Ptr& itemPtr, const Ptr& actorPtr) { MWWorld::ContainerStoreIterator it = addImp(itemPtr); MWWorld::Ptr item = *it; std::string script = MWWorld::Class::get(item).getScript(item); if(script != "") { CellStore *cell; Ptr player = MWBase::Environment::get().getWorld ()->getPlayer().getPlayer(); if(&(MWWorld::Class::get (player).getContainerStore (player)) == this) { cell = 0; // Items in player's inventory have cell set to 0, so their scripts will never be removed // Set OnPCAdd special variable, if it is declared item.getRefData().getLocals().setVarByInt(script, "onpcadd", 1); } else cell = player.getCell(); item.mCell = cell; item.mContainerStore = 0; MWBase::Environment::get().getWorld()->getLocalScripts().add(script, item); } return it; }
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::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; } }
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; }
void ConstraintStorage::addImp(std::vector<ReifiedLinearConstraint>&& vl) { for (auto& l : vl) addImp(std::move(l)); }