#include "inventorystore.hpp" #include #include #include #include #include "../mwbase/environment.hpp" #include "../mwbase/world.hpp" #include "../mwmechanics/npcstats.hpp" #include "class.hpp" void MWWorld::InventoryStore::copySlots (const InventoryStore& store) { // some const-trickery, required because of a flaw in the handling of MW-references and the // resulting workarounds for (std::vector::const_iterator iter ( const_cast (store).mSlots.begin()); iter!=const_cast (store).mSlots.end(); ++iter) { std::size_t distance = std::distance (const_cast (store).begin(), *iter); ContainerStoreIterator slot = begin(); std::advance (slot, distance); mSlots.push_back (slot); } } void MWWorld::InventoryStore::initSlots (TSlots& slots) { for (int i=0; i=static_cast (mSlots.size())) throw std::runtime_error ("slot number out of range"); if (iterator.getContainerStore()!=this) throw std::runtime_error ("attempt to equip an item that is not in the inventory"); std::pair, bool> slots; if (iterator!=end()) { slots = Class::get (*iterator).getEquipmentSlots (*iterator); if (std::find (slots.first.begin(), slots.first.end(), slot)==slots.first.end()) throw std::runtime_error ("invalid slot"); } // restack item previously in this slot (if required) if (mSlots[slot] != end()) { for (MWWorld::ContainerStoreIterator iter (begin()); iter!=end(); ++iter) { if (stacks(*iter, *mSlots[slot])) { iter->getRefData().setCount( iter->getRefData().getCount() + mSlots[slot]->getRefData().getCount() ); mSlots[slot]->getRefData().setCount(0); break; } } } // unstack item pointed to by iterator if required if (iterator!=end() && !slots.second && iterator->getRefData().getCount() > 1) // if slots.second is true, item can stay stacked when equipped { // add the item again with a count of count-1, then set the count of the original (that will be equipped) to 1 int count = iterator->getRefData().getCount(); iterator->getRefData().setCount(count-1); addImpl(*iterator); iterator->getRefData().setCount(1); } mSlots[slot] = iterator; flagAsModified(); } MWWorld::ContainerStoreIterator MWWorld::InventoryStore::getSlot (int slot) { if (slot<0 || slot>=static_cast (mSlots.size())) throw std::runtime_error ("slot number out of range"); if (mSlots[slot]==end()) return end(); if (mSlots[slot]->getRefData().getCount()<1) { // object has been deleted mSlots[slot] = end(); return end(); } return mSlots[slot]; } void MWWorld::InventoryStore::autoEquip (const MWMechanics::NpcStats& stats) { TSlots slots; initSlots (slots); for (ContainerStoreIterator iter (begin()); iter!=end(); ++iter) { Ptr test = *iter; int testSkill = MWWorld::Class::get (test).getEquipmentSkill (test); std::pair, bool> itemsSlots = MWWorld::Class::get (*iter).getEquipmentSlots (*iter); for (std::vector::const_iterator iter2 (itemsSlots.first.begin()); iter2!=itemsSlots.first.end(); ++iter2) { bool use = false; if (slots.at (*iter2)==end()) use = true; // slot was empty before -> skip all further checks else { Ptr old = *slots.at (*iter2); if (!use) { // check skill int oldSkill = MWWorld::Class::get (old).getEquipmentSkill (old); if (testSkill!=-1 && oldSkill==-1) use = true; else if (testSkill!=-1 && oldSkill!=-1 && testSkill!=oldSkill) { if (stats.getSkill (oldSkill).getModified()>stats.getSkill (testSkill).getModified()) continue; // rejected, because old item better matched the NPC's skills. if (stats.getSkill (oldSkill).getModified()= MWWorld::Class::get (test).getValue (test)) { continue; } use = true; } } if (!itemsSlots.second) // if itemsSlots.second is true, item can stay stacked when equipped { // unstack item pointed to by iterator if required if (iter->getRefData().getCount() > 1) { // add the item again with a count of count-1, then set the count of the original (that will be equipped) to 1 int count = iter->getRefData().getCount(); iter->getRefData().setCount(count-1); addImpl(*iter); iter->getRefData().setCount(1); } } slots[*iter2] = iter; break; } } bool changed = false; for (std::size_t i=0; igetStore().enchants.find (enchantmentId); if (enchantment.data.type==ESM::Enchantment::ConstantEffect) mMagicEffects.add (enchantment.effects); } } mMagicEffectsUpToDate = true; } return mMagicEffects; } void MWWorld::InventoryStore::flagAsModified() { ContainerStore::flagAsModified(); mMagicEffectsUpToDate = false; } bool MWWorld::InventoryStore::stacks(const Ptr& ptr1, const Ptr& ptr2) { bool canStack = MWWorld::ContainerStore::stacks(ptr1, ptr2); if (!canStack) return false; // don't stack if the item being checked against is currently equipped. for (TSlots::const_iterator iter (mSlots.begin()); iter!=mSlots.end(); ++iter) { if (*iter != end() && ptr1 == **iter) return false; } return true; } void MWWorld::InventoryStore::setSelectedEnchantItem(const ContainerStoreIterator& iterator) { mSelectedEnchantItem = iterator; } MWWorld::ContainerStoreIterator MWWorld::InventoryStore::getSelectedEnchantItem() { return mSelectedEnchantItem; }