forked from mirror/openmw-tes3mp
Merge remote branch 'scrawl/itemstacking'
This commit is contained in:
commit
73d19f9185
12 changed files with 149 additions and 8 deletions
|
@ -248,4 +248,12 @@ namespace MWClass
|
|||
|
||||
return info;
|
||||
}
|
||||
|
||||
std::string Armor::getEnchantment (const MWWorld::Ptr& ptr) const
|
||||
{
|
||||
ESMS::LiveCellRef<ESM::Armor, MWWorld::RefData> *ref =
|
||||
ptr.get<ESM::Armor>();
|
||||
|
||||
return ref->base->enchant;
|
||||
}
|
||||
}
|
||||
|
|
|
@ -55,6 +55,9 @@ namespace MWClass
|
|||
|
||||
virtual std::string getDownSoundId (const MWWorld::Ptr& ptr) const;
|
||||
///< Return the put down sound Id
|
||||
|
||||
virtual std::string getEnchantment (const MWWorld::Ptr& ptr) const;
|
||||
///< @return the enchantment ID if the object is enchanted, otherwise an empty string
|
||||
};
|
||||
}
|
||||
|
||||
|
|
|
@ -201,4 +201,12 @@ namespace MWClass
|
|||
|
||||
return info;
|
||||
}
|
||||
|
||||
std::string Clothing::getEnchantment (const MWWorld::Ptr& ptr) const
|
||||
{
|
||||
ESMS::LiveCellRef<ESM::Clothing, MWWorld::RefData> *ref =
|
||||
ptr.get<ESM::Clothing>();
|
||||
|
||||
return ref->base->enchant;
|
||||
}
|
||||
}
|
||||
|
|
|
@ -49,6 +49,9 @@ namespace MWClass
|
|||
|
||||
virtual std::string getDownSoundId (const MWWorld::Ptr& ptr) const;
|
||||
///< Return the put down sound Id
|
||||
|
||||
virtual std::string getEnchantment (const MWWorld::Ptr& ptr) const;
|
||||
///< @return the enchantment ID if the object is enchanted, otherwise an empty string
|
||||
};
|
||||
}
|
||||
|
||||
|
|
|
@ -339,4 +339,12 @@ namespace MWClass
|
|||
|
||||
return info;
|
||||
}
|
||||
|
||||
std::string Weapon::getEnchantment (const MWWorld::Ptr& ptr) const
|
||||
{
|
||||
ESMS::LiveCellRef<ESM::Weapon, MWWorld::RefData> *ref =
|
||||
ptr.get<ESM::Weapon>();
|
||||
|
||||
return ref->base->enchant;
|
||||
}
|
||||
}
|
||||
|
|
|
@ -55,6 +55,9 @@ namespace MWClass
|
|||
|
||||
virtual std::string getDownSoundId (const MWWorld::Ptr& ptr) const;
|
||||
///< Return the put down sound Id
|
||||
|
||||
virtual std::string getEnchantment (const MWWorld::Ptr& ptr) const;
|
||||
///< @return the enchantment ID if the object is enchanted, otherwise an empty string
|
||||
};
|
||||
}
|
||||
|
||||
|
|
|
@ -181,4 +181,9 @@ namespace MWWorld
|
|||
{
|
||||
return false;
|
||||
}
|
||||
|
||||
std::string Class::getEnchantment (const Ptr& ptr) const
|
||||
{
|
||||
return "";
|
||||
}
|
||||
}
|
||||
|
|
|
@ -136,7 +136,7 @@ namespace MWWorld
|
|||
///< Set or unset a stance.
|
||||
|
||||
virtual bool getStance (const Ptr& ptr, Stance stance, bool ignoreForce = false) const;
|
||||
////< Check if a stance is active or not.
|
||||
///< Check if a stance is active or not.
|
||||
|
||||
virtual float getSpeed (const Ptr& ptr) const;
|
||||
///< Return movement speed.
|
||||
|
@ -179,6 +179,10 @@ namespace MWWorld
|
|||
virtual std::string getDownSoundId (const Ptr& ptr) const;
|
||||
///< Return the down sound ID of \a ptr or throw an exception, if class does not support ID retrieval
|
||||
/// (default implementation: throw an exception)
|
||||
|
||||
virtual std::string getEnchantment (const MWWorld::Ptr& ptr) const;
|
||||
///< @return the enchantment ID if the object is enchanted, otherwise an empty string
|
||||
/// (default implementation: return empty string)
|
||||
};
|
||||
}
|
||||
|
||||
|
|
|
@ -9,6 +9,7 @@
|
|||
|
||||
#include "manualref.hpp"
|
||||
#include "refdata.hpp"
|
||||
#include "class.hpp"
|
||||
|
||||
namespace
|
||||
{
|
||||
|
@ -44,10 +45,42 @@ MWWorld::ContainerStoreIterator MWWorld::ContainerStore::end()
|
|||
return ContainerStoreIterator (this);
|
||||
}
|
||||
|
||||
bool MWWorld::ContainerStore::stacks(const Ptr& ptr1, const Ptr& ptr2) const
|
||||
{
|
||||
/// \todo add current weapon/armor health, remaining lockpick/repair uses, current enchantment charge here as soon as they are implemented
|
||||
if ( ptr1.mCellRef->refID == ptr2.mCellRef->refID
|
||||
&& MWWorld::Class::get(ptr1).getScript(ptr1) == "" // item with a script never stacks
|
||||
&& ptr1.mCellRef->owner == ptr2.mCellRef->owner
|
||||
&& ptr1.mCellRef->soul == ptr2.mCellRef->soul
|
||||
&& ptr1.mCellRef->charge == ptr2.mCellRef->charge)
|
||||
return true;
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
void MWWorld::ContainerStore::add (const Ptr& ptr)
|
||||
{
|
||||
/// \todo implement item stacking
|
||||
int type = getType(ptr);
|
||||
|
||||
// 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() + ptr.getRefData().getCount() );
|
||||
|
||||
flagAsModified();
|
||||
return;
|
||||
}
|
||||
}
|
||||
|
||||
// if we got here, this means no stacking
|
||||
addImpl(ptr);
|
||||
}
|
||||
|
||||
void MWWorld::ContainerStore::addImpl (const Ptr& ptr)
|
||||
{
|
||||
switch (getType(ptr))
|
||||
{
|
||||
case Type_Potion: potions.list.push_back (*ptr.get<ESM::Potion>()); break;
|
||||
|
|
|
@ -67,13 +67,23 @@ namespace MWWorld
|
|||
ContainerStoreIterator end();
|
||||
|
||||
void add (const Ptr& ptr);
|
||||
///< Add the item pointed to by \a ptr to this container.
|
||||
///< Add the item pointed to by \a ptr to this container. (Stacks automatically if needed)
|
||||
///
|
||||
/// \note The item pointed to is not required to exist beyond this function call.
|
||||
///
|
||||
/// \attention Do not add items to an existing stack by increasing the count instead of
|
||||
/// calling this function!
|
||||
|
||||
protected:
|
||||
void addImpl (const Ptr& ptr);
|
||||
///< Add the item to this container (no stacking)
|
||||
|
||||
virtual bool stacks (const Ptr& ptr1, const Ptr& ptr2) const;
|
||||
///< @return true if the two specified objects can stack with each other
|
||||
/// @note ptr1 is the item that is already in this container
|
||||
|
||||
public:
|
||||
|
||||
void fill (const ESM::InventoryList& items, const ESMS::ESMStore& store);
|
||||
///< Insert items into *this.
|
||||
|
||||
|
|
|
@ -59,17 +59,38 @@ void MWWorld::InventoryStore::equip (int slot, const ContainerStoreIterator& ite
|
|||
if (iterator.getContainerStore()!=this)
|
||||
throw std::runtime_error ("attempt to equip an item that is not in the inventory");
|
||||
|
||||
std::pair<std::vector<int>, bool> slots;
|
||||
if (iterator!=end())
|
||||
{
|
||||
std::pair<std::vector<int>, bool> slots = Class::get (*iterator).getEquipmentSlots (*iterator);
|
||||
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");
|
||||
}
|
||||
|
||||
/// \todo restack item previously in this slot (if required)
|
||||
// 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;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/// \todo unstack item pointed to by iterator if required)
|
||||
// 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;
|
||||
|
||||
|
@ -147,7 +168,18 @@ void MWWorld::InventoryStore::autoEquip (const MWMechanics::NpcStats& stats)
|
|||
}
|
||||
}
|
||||
|
||||
/// \todo unstack, if reqquired (itemsSlots.second)
|
||||
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;
|
||||
|
@ -168,3 +200,20 @@ void MWWorld::InventoryStore::autoEquip (const MWMechanics::NpcStats& stats)
|
|||
flagAsModified();
|
||||
}
|
||||
}
|
||||
|
||||
bool MWWorld::InventoryStore::stacks(const Ptr& ptr1, const Ptr& ptr2) const
|
||||
{
|
||||
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 (ptr1 == **iter)
|
||||
return false;
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
|
|
@ -64,6 +64,13 @@ namespace MWWorld
|
|||
|
||||
void autoEquip (const MWMechanics::NpcStats& stats);
|
||||
///< Auto equip items according to stats and item value.
|
||||
|
||||
protected:
|
||||
|
||||
virtual bool stacks (const Ptr& ptr1, const Ptr& ptr2) const;
|
||||
///< @return true if the two specified objects can stack with each other
|
||||
/// @note ptr1 is the item that is already in this container
|
||||
|
||||
};
|
||||
}
|
||||
|
||||
|
|
Loading…
Reference in a new issue