mirror of
https://gitlab.com/OpenMW/openmw.git
synced 2025-02-10 12:39:53 +00:00
Merge remote-tracking branch 'potatoesmaster/inventory-remove'
This commit is contained in:
commit
cfbf444628
@ -309,14 +309,19 @@ namespace MWBase
|
||||
|
||||
virtual void update (float duration, bool paused) = 0;
|
||||
|
||||
virtual bool placeObject(const MWWorld::Ptr& object, float cursorX, float cursorY) = 0;
|
||||
///< place an object into the gameworld at the specified cursor position
|
||||
virtual bool placeObject (const MWWorld::Ptr& object, float cursorX, float cursorY, int amount) = 0;
|
||||
///< copy and place an object into the gameworld at the specified cursor position
|
||||
/// @param object
|
||||
/// @param cursor X (relative 0-1)
|
||||
/// @param cursor Y (relative 0-1)
|
||||
/// @param number of objects to place
|
||||
/// @return true if the object was placed, or false if it was rejected because the position is too far away
|
||||
|
||||
virtual void dropObjectOnGround (const MWWorld::Ptr& actor, const MWWorld::Ptr& object) = 0;
|
||||
virtual void dropObjectOnGround (const MWWorld::Ptr& actor, const MWWorld::Ptr& object, int amount) = 0;
|
||||
///< copy and place an object into the gameworld at the given actor's position
|
||||
/// @param actor giving the dropped object position
|
||||
/// @param object
|
||||
/// @param number of objects to place
|
||||
|
||||
virtual bool canPlaceObject (float cursorX, float cursorY) = 0;
|
||||
///< @return true if it is possible to place on object at specified cursor location
|
||||
@ -408,6 +413,8 @@ namespace MWBase
|
||||
virtual bool toggleGodMode() = 0;
|
||||
|
||||
virtual void castSpell (const MWWorld::Ptr& actor) = 0;
|
||||
|
||||
virtual void updateAnimParts(const MWWorld::Ptr& ptr) = 0;
|
||||
};
|
||||
}
|
||||
|
||||
|
@ -219,7 +219,6 @@ namespace MWClass
|
||||
MWWorld::LiveCellRef<ESM::Miscellaneous> *ref =
|
||||
newRef.getPtr().get<ESM::Miscellaneous>();
|
||||
newPtr = MWWorld::Ptr(&cell.mMiscItems.insert(*ref), &cell);
|
||||
newPtr.getRefData ().setCount(1);
|
||||
newPtr.getCellRef().mGoldValue = goldAmount;
|
||||
} else {
|
||||
MWWorld::LiveCellRef<ESM::Miscellaneous> *ref =
|
||||
|
@ -11,6 +11,7 @@
|
||||
#include "../mwworld/actiontake.hpp"
|
||||
#include "../mwworld/actionapply.hpp"
|
||||
#include "../mwworld/cellstore.hpp"
|
||||
#include "../mwworld/containerstore.hpp"
|
||||
#include "../mwworld/physicssystem.hpp"
|
||||
#include "../mwworld/player.hpp"
|
||||
#include "../mwworld/nullaction.hpp"
|
||||
@ -164,10 +165,11 @@ namespace MWClass
|
||||
MWWorld::LiveCellRef<ESM::Potion> *ref =
|
||||
ptr.get<ESM::Potion>();
|
||||
|
||||
ptr.getRefData().setCount (ptr.getRefData().getCount()-1);
|
||||
|
||||
MWWorld::Ptr actor = MWBase::Environment::get().getWorld()->getPlayer().getPlayer();
|
||||
|
||||
// remove used potion (assume it is present in inventory)
|
||||
ptr.getContainerStore()->remove(ptr, 1, actor);
|
||||
|
||||
boost::shared_ptr<MWWorld::Action> action (
|
||||
new MWWorld::ActionApply (actor, ref->mBase->mId));
|
||||
|
||||
|
@ -100,6 +100,9 @@ namespace MWGui
|
||||
|
||||
finish();
|
||||
targetView->update();
|
||||
|
||||
// We need to update the view since an other item could be auto-equipped.
|
||||
mSourceView->update();
|
||||
}
|
||||
|
||||
void DragAndDrop::finish()
|
||||
|
@ -94,9 +94,7 @@ void ContainerItemModel::removeItem (const ItemStack& item, size_t count)
|
||||
{
|
||||
if (stacks(*it, item.mBase))
|
||||
{
|
||||
int refCount = it->getRefData().getCount();
|
||||
it->getRefData().setCount(std::max(0, refCount - toRemove));
|
||||
toRemove -= refCount;
|
||||
toRemove -= store.remove(*it, toRemove, *source);
|
||||
if (toRemove <= 0)
|
||||
return;
|
||||
}
|
||||
|
@ -243,21 +243,16 @@ namespace MWGui
|
||||
float mouseX = cursorPosition.left / float(viewSize.width);
|
||||
float mouseY = cursorPosition.top / float(viewSize.height);
|
||||
|
||||
int origCount = object.getRefData().getCount();
|
||||
object.getRefData().setCount(mDragAndDrop->mDraggedCount);
|
||||
|
||||
if (world->canPlaceObject(mouseX, mouseY))
|
||||
world->placeObject(object, mouseX, mouseY);
|
||||
world->placeObject(object, mouseX, mouseY, mDragAndDrop->mDraggedCount);
|
||||
else
|
||||
world->dropObjectOnGround(world->getPlayer().getPlayer(), object);
|
||||
world->dropObjectOnGround(world->getPlayer().getPlayer(), object, mDragAndDrop->mDraggedCount);
|
||||
|
||||
MWBase::Environment::get().getWindowManager()->changePointer("arrow");
|
||||
|
||||
std::string sound = MWWorld::Class::get(object).getDownSoundId(object);
|
||||
MWBase::Environment::get().getSoundManager()->playSound (sound, 1.0, 1.0);
|
||||
|
||||
object.getRefData().setCount(origCount);
|
||||
|
||||
// remove object from the container it was coming from
|
||||
mDragAndDrop->mSourceModel->removeItem(mDragAndDrop->mItem, mDragAndDrop->mDraggedCount);
|
||||
mDragAndDrop->finish();
|
||||
|
@ -52,18 +52,12 @@ void InventoryItemModel::copyItem (const ItemStack& item, size_t count)
|
||||
void InventoryItemModel::removeItem (const ItemStack& item, size_t count)
|
||||
{
|
||||
MWWorld::ContainerStore& store = MWWorld::Class::get(mActor).getContainerStore(mActor);
|
||||
int removed = store.remove(item.mBase, count, mActor);
|
||||
|
||||
for (MWWorld::ContainerStoreIterator it = store.begin(); it != store.end(); ++it)
|
||||
{
|
||||
if (*it == item.mBase)
|
||||
{
|
||||
if (it->getRefData().getCount() < static_cast<int>(count))
|
||||
throw std::runtime_error("Not enough items in the stack to remove");
|
||||
it->getRefData().setCount(it->getRefData().getCount() - count);
|
||||
return;
|
||||
}
|
||||
}
|
||||
throw std::runtime_error("Item to remove not found in container store");
|
||||
if (removed == 0)
|
||||
throw std::runtime_error("Item to remove not found in container store");
|
||||
else if (removed < count)
|
||||
throw std::runtime_error("Not enough items in the stack to remove");
|
||||
}
|
||||
|
||||
void InventoryItemModel::update()
|
||||
|
@ -145,10 +145,38 @@ namespace MWGui
|
||||
|
||||
const ItemStack& item = mTradeModel->getItem(index);
|
||||
|
||||
unequipItem(item.mBase);
|
||||
|
||||
MWWorld::Ptr object = item.mBase;
|
||||
int count = item.mCount;
|
||||
|
||||
if (item.mType == ItemStack::Type_Equipped)
|
||||
{
|
||||
MWWorld::InventoryStore& invStore = MWWorld::Class::get(mPtr).getInventoryStore(mPtr);
|
||||
MWWorld::Ptr newStack = *invStore.unequipItem(item.mBase, mPtr);
|
||||
|
||||
// The unequipped item was re-stacked. We have to update the index
|
||||
// since the item pointed does not exist anymore.
|
||||
if (item.mBase != newStack)
|
||||
{
|
||||
// newIndex will store the index of the ItemStack the item was stacked on
|
||||
int newIndex = -1;
|
||||
for (size_t i=0; i < mTradeModel->getItemCount(); ++i)
|
||||
{
|
||||
if (mTradeModel->getItem(i).mBase == newStack)
|
||||
{
|
||||
newIndex = i;
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
if (newIndex == -1)
|
||||
throw std::runtime_error("Can't find restacked item");
|
||||
|
||||
index = newIndex;
|
||||
object = mTradeModel->getItem(index).mBase;
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
bool shift = MyGUI::InputManager::getInstance().isShiftPressed();
|
||||
if (MyGUI::InputManager::getInstance().isControlPressed())
|
||||
count = 1;
|
||||
@ -375,27 +403,6 @@ namespace MWGui
|
||||
return MWWorld::Ptr();
|
||||
}
|
||||
|
||||
void InventoryWindow::unequipItem(const MWWorld::Ptr& item)
|
||||
{
|
||||
MWWorld::InventoryStore& invStore = MWWorld::Class::get(mPtr).getInventoryStore(mPtr);
|
||||
|
||||
for (int slot=0; slot < MWWorld::InventoryStore::Slots; ++slot)
|
||||
{
|
||||
MWWorld::ContainerStoreIterator it = invStore.getSlot(slot);
|
||||
if (it != invStore.end() && *it == item)
|
||||
{
|
||||
invStore.equip(slot, invStore.end());
|
||||
std::string script = MWWorld::Class::get(*it).getScript(*it);
|
||||
|
||||
// Unset OnPCEquip Variable on item's script, if it has a script with that variable declared
|
||||
if(script != "")
|
||||
(*it).getRefData().getLocals().setVarByInt(script, "onpcequip", 0);
|
||||
|
||||
return;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void InventoryWindow::updateEncumbranceBar()
|
||||
{
|
||||
MWWorld::Ptr player = MWBase::Environment::get().getWorld()->getPlayer().getPlayer();
|
||||
|
@ -103,7 +103,6 @@ namespace MWGui
|
||||
void onAvatarClicked(MyGUI::Widget* _sender);
|
||||
void onPinToggled();
|
||||
|
||||
void unequipItem(const MWWorld::Ptr& item);
|
||||
void updateEncumbranceBar();
|
||||
void notifyContentChanged();
|
||||
};
|
||||
|
@ -202,30 +202,17 @@ namespace MWGui
|
||||
|
||||
void TradeWindow::addOrRemoveGold(int amount)
|
||||
{
|
||||
bool goldFound = false;
|
||||
MWWorld::Ptr gold;
|
||||
MWWorld::Ptr player = MWBase::Environment::get().getWorld()->getPlayer().getPlayer();
|
||||
MWWorld::ContainerStore& playerStore = MWWorld::Class::get(player).getContainerStore(player);
|
||||
|
||||
for (MWWorld::ContainerStoreIterator it = playerStore.begin();
|
||||
it != playerStore.end(); ++it)
|
||||
if (amount > 0)
|
||||
{
|
||||
if (Misc::StringUtils::ciEqual(it->getCellRef().mRefID, "gold_001"))
|
||||
{
|
||||
goldFound = true;
|
||||
gold = *it;
|
||||
}
|
||||
}
|
||||
if (goldFound)
|
||||
{
|
||||
gold.getRefData().setCount(gold.getRefData().getCount() + amount);
|
||||
MWWorld::ManualRef ref(MWBase::Environment::get().getWorld()->getStore(), "Gold_001", amount);
|
||||
playerStore.add(ref.getPtr(), player);
|
||||
}
|
||||
else
|
||||
{
|
||||
assert(amount > 0);
|
||||
MWWorld::ManualRef ref(MWBase::Environment::get().getWorld()->getStore(), "Gold_001");
|
||||
ref.getPtr().getRefData().setCount(amount);
|
||||
playerStore.add(ref.getPtr(), player);
|
||||
playerStore.remove("gold_001", - amount, player);
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -244,7 +244,7 @@ namespace MWMechanics
|
||||
heldIter->getClass().setRemainingUsageTime(*heldIter, timeRemaining);
|
||||
else
|
||||
{
|
||||
heldIter->getRefData().setCount(0); // remove it
|
||||
inventoryStore.remove(*heldIter, 1, ptr); // remove it
|
||||
return;
|
||||
}
|
||||
}
|
||||
@ -253,7 +253,7 @@ namespace MWMechanics
|
||||
// Both NPC and player lights extinguish in water.
|
||||
if(MWBase::Environment::get().getWorld()->isSwimming(ptr))
|
||||
{
|
||||
heldIter->getRefData().setCount(0); // remove it
|
||||
inventoryStore.remove(*heldIter, 1, ptr); // remove it
|
||||
|
||||
// ...But, only the player makes a sound.
|
||||
if(isPlayer)
|
||||
|
@ -240,7 +240,8 @@ void MWMechanics::Alchemy::removeIngredients()
|
||||
for (TIngredientsContainer::iterator iter (mIngredients.begin()); iter!=mIngredients.end(); ++iter)
|
||||
if (!iter->isEmpty())
|
||||
{
|
||||
iter->getRefData().setCount (iter->getRefData().getCount()-1);
|
||||
iter->getContainerStore()->remove(*iter, 1, mAlchemist);
|
||||
|
||||
if (iter->getRefData().getCount()<1)
|
||||
{
|
||||
needsUpdate = true;
|
||||
|
@ -14,7 +14,6 @@ namespace MWMechanics
|
||||
Enchanting::Enchanting()
|
||||
: mCastStyle(ESM::Enchantment::CastOnce)
|
||||
, mSelfEnchanting(false)
|
||||
, mOldItemCount(0)
|
||||
{}
|
||||
|
||||
void Enchanting::setOldItem(MWWorld::Ptr oldItem)
|
||||
@ -24,7 +23,6 @@ namespace MWMechanics
|
||||
{
|
||||
mObjectType = mOldItemPtr.getTypeName();
|
||||
mOldItemId = mOldItemPtr.getCellRef().mRefID;
|
||||
mOldItemCount = mOldItemPtr.getRefData().getCount();
|
||||
}
|
||||
else
|
||||
{
|
||||
@ -55,17 +53,18 @@ namespace MWMechanics
|
||||
|
||||
bool Enchanting::create()
|
||||
{
|
||||
MWWorld::Ptr player = MWBase::Environment::get().getWorld()->getPlayer().getPlayer();
|
||||
const MWWorld::Ptr& player = MWBase::Environment::get().getWorld()->getPlayer().getPlayer();
|
||||
MWWorld::ContainerStore& store = MWWorld::Class::get(player).getContainerStore(player);
|
||||
ESM::Enchantment enchantment;
|
||||
enchantment.mData.mCharge = getGemCharge();
|
||||
|
||||
mSoulGemPtr.getRefData().setCount (mSoulGemPtr.getRefData().getCount()-1);
|
||||
store.remove(mSoulGemPtr, 1, player);
|
||||
|
||||
//Exception for Azura Star, new one will be added after enchanting
|
||||
if(boost::iequals(mSoulGemPtr.get<ESM::Miscellaneous>()->mBase->mId, "Misc_SoulGem_Azura"))
|
||||
{
|
||||
MWWorld::ManualRef azura (MWBase::Environment::get().getWorld()->getStore(), "Misc_SoulGem_Azura");
|
||||
MWWorld::Class::get (player).getContainerStore (player).add (azura.getPtr(), player);
|
||||
store.add(azura.getPtr(), player);
|
||||
}
|
||||
|
||||
if(mSelfEnchanting)
|
||||
@ -84,16 +83,18 @@ namespace MWMechanics
|
||||
enchantment.mData.mCost = getEnchantPoints();
|
||||
enchantment.mEffects = mEffectList;
|
||||
|
||||
// Create a new item
|
||||
MWWorld::ManualRef ref (MWBase::Environment::get().getWorld()->getStore(), mOldItemId, 1);
|
||||
const MWWorld::Ptr& newItemPtr = ref.getPtr();
|
||||
|
||||
// Apply the enchantment
|
||||
const ESM::Enchantment *enchantmentPtr = MWBase::Environment::get().getWorld()->createRecord (enchantment);
|
||||
MWWorld::Class::get(newItemPtr).applyEnchantment(newItemPtr, enchantmentPtr->mId, getGemCharge(), mNewItemName);
|
||||
|
||||
MWWorld::Class::get(mOldItemPtr).applyEnchantment(mOldItemPtr, enchantmentPtr->mId, getGemCharge(), mNewItemName);
|
||||
// Add the new item to player inventory and remove the old one
|
||||
store.add(newItemPtr, player);
|
||||
store.remove(mOldItemPtr, 1, player);
|
||||
|
||||
mOldItemPtr.getRefData().setCount(1);
|
||||
|
||||
MWWorld::ManualRef ref (MWBase::Environment::get().getWorld()->getStore(), mOldItemId);
|
||||
ref.getPtr().getRefData().setCount (mOldItemCount-1);
|
||||
|
||||
MWWorld::Class::get (player).getContainerStore (player).add (ref.getPtr(), player);
|
||||
if(!mSelfEnchanting)
|
||||
payForEnchantment();
|
||||
|
||||
@ -299,20 +300,9 @@ namespace MWMechanics
|
||||
|
||||
void Enchanting::payForEnchantment() const
|
||||
{
|
||||
MWWorld::Ptr gold;
|
||||
|
||||
MWWorld::Ptr player = MWBase::Environment::get().getWorld()->getPlayer().getPlayer();
|
||||
const MWWorld::Ptr& player = MWBase::Environment::get().getWorld()->getPlayer().getPlayer();
|
||||
MWWorld::ContainerStore& store = MWWorld::Class::get(player).getContainerStore(player);
|
||||
|
||||
for (MWWorld::ContainerStoreIterator it = store.begin();
|
||||
it != store.end(); ++it)
|
||||
{
|
||||
if (Misc::StringUtils::ciEqual(it->getCellRef().mRefID, "gold_001"))
|
||||
{
|
||||
gold = *it;
|
||||
}
|
||||
}
|
||||
|
||||
gold.getRefData().setCount(gold.getRefData().getCount() - getEnchantPrice());
|
||||
store.remove("gold_001", getEnchantPrice(), player);
|
||||
}
|
||||
}
|
||||
|
@ -22,7 +22,6 @@ namespace MWMechanics
|
||||
std::string mNewItemName;
|
||||
std::string mObjectType;
|
||||
std::string mOldItemId;
|
||||
int mOldItemCount;
|
||||
|
||||
public:
|
||||
Enchanting();
|
||||
|
@ -159,7 +159,7 @@ namespace MWMechanics
|
||||
// auto-equip again. we need this for when the race is changed to a beast race
|
||||
MWWorld::InventoryStore& invStore = MWWorld::Class::get(ptr).getInventoryStore(ptr);
|
||||
for (int i=0; i<MWWorld::InventoryStore::Slots; ++i)
|
||||
invStore.equip(i, invStore.end());
|
||||
invStore.equip(i, invStore.end(), ptr);
|
||||
invStore.autoEquip(ptr);
|
||||
}
|
||||
|
||||
|
@ -85,7 +85,10 @@ void Repair::repair(const MWWorld::Ptr &itemToRepair)
|
||||
// tool used up?
|
||||
if (mTool.getCellRef().mCharge == 0)
|
||||
{
|
||||
mTool.getRefData().setCount(0);
|
||||
MWWorld::Ptr player = MWBase::Environment::get().getWorld()->getPlayer().getPlayer();
|
||||
MWWorld::ContainerStore& store = MWWorld::Class::get(player).getContainerStore(player);
|
||||
|
||||
store.remove(mTool, 1, player);
|
||||
|
||||
std::string message = MWBase::Environment::get().getWorld()->getStore().get<ESM::GameSetting>()
|
||||
.find("sNotifyMessage51")->getString();
|
||||
@ -93,8 +96,6 @@ void Repair::repair(const MWWorld::Ptr &itemToRepair)
|
||||
MWBase::Environment::get().getWindowManager()->messageBox((boost::format(message) % MWWorld::Class::get(mTool).getName(mTool)).str());
|
||||
|
||||
// try to find a new tool of the same ID
|
||||
MWWorld::Ptr player = MWBase::Environment::get().getWorld()->getPlayer().getPlayer();
|
||||
MWWorld::ContainerStore& store = MWWorld::Class::get(player).getContainerStore(player);
|
||||
for (MWWorld::ContainerStoreIterator iter (store.begin());
|
||||
iter!=store.end(); ++iter)
|
||||
{
|
||||
|
@ -2,6 +2,7 @@
|
||||
|
||||
#include "../mwworld/class.hpp"
|
||||
#include "../mwworld/player.hpp"
|
||||
#include "../mwworld/containerstore.hpp"
|
||||
|
||||
#include "../mwbase/world.hpp"
|
||||
#include "../mwbase/environment.hpp"
|
||||
@ -61,7 +62,7 @@ namespace MWMechanics
|
||||
lockpick.getCellRef().mCharge = lockpick.get<ESM::Lockpick>()->mBase->mData.mUses;
|
||||
--lockpick.getCellRef().mCharge;
|
||||
if (!lockpick.getCellRef().mCharge)
|
||||
lockpick.getRefData().setCount(0);
|
||||
lockpick.getContainerStore()->remove(lockpick, 1, mActor);
|
||||
}
|
||||
|
||||
void Security::probeTrap(const MWWorld::Ptr &trap, const MWWorld::Ptr &probe,
|
||||
@ -103,7 +104,7 @@ namespace MWMechanics
|
||||
probe.getCellRef().mCharge = probe.get<ESM::Probe>()->mBase->mData.mUses;
|
||||
--probe.getCellRef().mCharge;
|
||||
if (!probe.getCellRef().mCharge)
|
||||
probe.getRefData().setCount(0);
|
||||
probe.getContainerStore()->remove(probe, 1, mActor);
|
||||
}
|
||||
|
||||
}
|
||||
|
@ -327,6 +327,19 @@ void RenderingManager::rebuildPtr(const MWWorld::Ptr &ptr)
|
||||
}
|
||||
}
|
||||
|
||||
void RenderingManager::updateAnimParts(const MWWorld::Ptr& ptr)
|
||||
{
|
||||
NpcAnimation *anim = NULL;
|
||||
|
||||
if(ptr.getRefData().getHandle() == "player")
|
||||
anim = mPlayerAnimation;
|
||||
else if(MWWorld::Class::get(ptr).isActor())
|
||||
anim = dynamic_cast<NpcAnimation*>(mActors.getAnimation(ptr));
|
||||
|
||||
if(anim)
|
||||
anim->updateParts();
|
||||
}
|
||||
|
||||
void RenderingManager::update (float duration, bool paused)
|
||||
{
|
||||
MWBase::World *world = MWBase::Environment::get().getWorld();
|
||||
|
@ -141,6 +141,9 @@ public:
|
||||
/// and equipment.
|
||||
void rebuildPtr(const MWWorld::Ptr &ptr);
|
||||
|
||||
/// Update actor model parts.
|
||||
void updateAnimParts(const MWWorld::Ptr &ptr);
|
||||
|
||||
void update (float duration, bool paused);
|
||||
|
||||
void setAmbientColour(const Ogre::ColourValue& colour);
|
||||
|
@ -53,10 +53,8 @@ namespace MWScript
|
||||
if (count == 0)
|
||||
return;
|
||||
|
||||
MWWorld::ManualRef ref (MWBase::Environment::get().getWorld()->getStore(), item);
|
||||
MWWorld::ManualRef ref (MWBase::Environment::get().getWorld()->getStore(), item, count);
|
||||
|
||||
ref.getPtr().getRefData().setCount (count);
|
||||
|
||||
// Configure item's script variables
|
||||
std::string script = MWWorld::Class::get(ref.getPtr()).getScript(ref.getPtr());
|
||||
if (script != "")
|
||||
@ -136,41 +134,18 @@ namespace MWScript
|
||||
return;
|
||||
|
||||
MWWorld::ContainerStore& store = MWWorld::Class::get (ptr).getContainerStore (ptr);
|
||||
|
||||
|
||||
std::string itemName = "";
|
||||
|
||||
// originalCount holds the total number of items to remove, count holds the remaining number of items to remove
|
||||
Interpreter::Type_Integer originalCount = count;
|
||||
int numRemoved = store.remove(item, count, ptr);
|
||||
|
||||
for (MWWorld::ContainerStoreIterator iter (store.begin()); iter!=store.end() && count;
|
||||
++iter)
|
||||
{
|
||||
if (Misc::StringUtils::ciEqual(iter->getCellRef().mRefID, item))
|
||||
{
|
||||
itemName = MWWorld::Class::get(*iter).getName(*iter);
|
||||
|
||||
if (iter->getRefData().getCount()<=count)
|
||||
{
|
||||
count -= iter->getRefData().getCount();
|
||||
iter->getRefData().setCount (0);
|
||||
}
|
||||
else
|
||||
{
|
||||
iter->getRefData().setCount (iter->getRefData().getCount()-count);
|
||||
count = 0;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// Spawn a messagebox (only for items removed from player's inventory)
|
||||
if (ptr == MWBase::Environment::get().getWorld ()->getPlayer ().getPlayer())
|
||||
if ((numRemoved > 0)
|
||||
&& (ptr == MWBase::Environment::get().getWorld()->getPlayer().getPlayer()))
|
||||
{
|
||||
// The two GMST entries below expand to strings informing the player of what, and how many of it has been removed from their inventory
|
||||
std::string msgBox;
|
||||
int numRemoved = (originalCount - count);
|
||||
if (numRemoved == 0)
|
||||
return;
|
||||
|
||||
|
||||
if(numRemoved > 1)
|
||||
{
|
||||
msgBox = MyGUI::LanguageManager::getInstance().replaceTags("#{sNotifyMessage63}");
|
||||
|
@ -348,9 +348,7 @@ namespace MWScript
|
||||
const MWWorld::ESMStore& store = MWBase::Environment::get().getWorld()->getStore();
|
||||
store.get<ESM::Creature>().find(creature); // This line throws an exception if it can't find the creature
|
||||
|
||||
MWWorld::ManualRef ref (MWBase::Environment::get().getWorld()->getStore(), gem);
|
||||
|
||||
ref.getPtr().getRefData().setCount (1);
|
||||
MWWorld::ManualRef ref (MWBase::Environment::get().getWorld()->getStore(), gem, 1);
|
||||
|
||||
ref.getPtr().getCellRef().mSoul = creature;
|
||||
|
||||
@ -374,18 +372,7 @@ namespace MWScript
|
||||
|
||||
MWWorld::ContainerStore& store = MWWorld::Class::get (ptr).getContainerStore (ptr);
|
||||
|
||||
|
||||
for (MWWorld::ContainerStoreIterator iter (store.begin()); iter!=store.end(); ++iter)
|
||||
{
|
||||
if (::Misc::StringUtils::ciEqual(iter->getCellRef().mSoul, soul))
|
||||
{
|
||||
if (iter->getRefData().getCount() <= 1)
|
||||
iter->getRefData().setCount (0);
|
||||
else
|
||||
iter->getRefData().setCount (iter->getRefData().getCount() - 1);
|
||||
break;
|
||||
}
|
||||
}
|
||||
store.remove(soul, 1, ptr);
|
||||
}
|
||||
};
|
||||
|
||||
@ -415,24 +402,18 @@ namespace MWScript
|
||||
MWWorld::ContainerStore& store = MWWorld::Class::get (ptr).getContainerStore (ptr);
|
||||
|
||||
|
||||
int toRemove = amount;
|
||||
for (MWWorld::ContainerStoreIterator iter (store.begin()); iter!=store.end(); ++iter)
|
||||
{
|
||||
if (::Misc::StringUtils::ciEqual(iter->getCellRef().mRefID, item))
|
||||
{
|
||||
if(iter->getRefData().getCount() <= amount)
|
||||
{
|
||||
MWBase::Environment::get().getWorld()->dropObjectOnGround(ptr, *iter);
|
||||
iter->getRefData().setCount(0);
|
||||
}
|
||||
else
|
||||
{
|
||||
int original = iter->getRefData().getCount();
|
||||
iter->getRefData().setCount(amount);
|
||||
MWBase::Environment::get().getWorld()->dropObjectOnGround(ptr, *iter);
|
||||
iter->getRefData().setCount(original - amount);
|
||||
}
|
||||
int removed = store.remove(*iter, toRemove, ptr);
|
||||
MWBase::Environment::get().getWorld()->dropObjectOnGround(ptr, *iter, removed);
|
||||
|
||||
break;
|
||||
toRemove -= removed;
|
||||
|
||||
if (toRemove <= 0)
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
@ -458,20 +439,8 @@ namespace MWScript
|
||||
{
|
||||
if (::Misc::StringUtils::ciEqual(iter->getCellRef().mSoul, soul))
|
||||
{
|
||||
|
||||
if(iter->getRefData().getCount() <= 1)
|
||||
{
|
||||
MWBase::Environment::get().getWorld()->dropObjectOnGround(ptr, *iter);
|
||||
iter->getRefData().setCount(0);
|
||||
}
|
||||
else
|
||||
{
|
||||
int original = iter->getRefData().getCount();
|
||||
iter->getRefData().setCount(1);
|
||||
MWBase::Environment::get().getWorld()->dropObjectOnGround(ptr, *iter);
|
||||
iter->getRefData().setCount(original - 1);
|
||||
}
|
||||
|
||||
MWBase::Environment::get().getWorld()->dropObjectOnGround(ptr, *iter, 1);
|
||||
store.remove(*iter, 1, ptr);
|
||||
break;
|
||||
}
|
||||
}
|
||||
@ -541,12 +510,7 @@ namespace MWScript
|
||||
runtime.pop();
|
||||
|
||||
if (parameter == 1)
|
||||
{
|
||||
if (ptr.isInCell())
|
||||
MWBase::Environment::get().getWorld()->deleteObject (ptr);
|
||||
else
|
||||
ptr.getRefData().setCount(0);
|
||||
}
|
||||
MWBase::Environment::get().getWorld()->deleteObject(ptr);
|
||||
}
|
||||
};
|
||||
|
||||
|
@ -450,62 +450,16 @@ namespace MWScript
|
||||
}
|
||||
};
|
||||
|
||||
template<class R>
|
||||
class OpPlaceAtPc : public Interpreter::Opcode0
|
||||
template<class R, bool pc>
|
||||
class OpPlaceAt : public Interpreter::Opcode0
|
||||
{
|
||||
public:
|
||||
|
||||
virtual void execute (Interpreter::Runtime& runtime)
|
||||
{
|
||||
std::string itemID = runtime.getStringLiteral (runtime[0].mInteger);
|
||||
runtime.pop();
|
||||
|
||||
Interpreter::Type_Integer count = runtime[0].mInteger;
|
||||
runtime.pop();
|
||||
Interpreter::Type_Float distance = runtime[0].mFloat;
|
||||
runtime.pop();
|
||||
Interpreter::Type_Integer direction = runtime[0].mInteger;
|
||||
runtime.pop();
|
||||
|
||||
if (count<0)
|
||||
throw std::runtime_error ("count must be non-negative");
|
||||
|
||||
// no-op
|
||||
if (count == 0)
|
||||
return;
|
||||
|
||||
ESM::Position ipos = MWBase::Environment::get().getWorld()->getPlayer().getPlayer().getRefData().getPosition();
|
||||
Ogre::Vector3 pos(ipos.pos[0],ipos.pos[1],ipos.pos[2]);
|
||||
Ogre::Quaternion rot(Ogre::Radian(-ipos.rot[2]), Ogre::Vector3::UNIT_Z);
|
||||
if(direction == 0) pos = pos + distance*rot.yAxis();
|
||||
else if(direction == 1) pos = pos - distance*rot.yAxis();
|
||||
else if(direction == 2) pos = pos - distance*rot.xAxis();
|
||||
else if(direction == 3) pos = pos + distance*rot.xAxis();
|
||||
else throw std::runtime_error ("direction must be 0,1,2 or 3");
|
||||
|
||||
ipos.pos[0] = pos.x;
|
||||
ipos.pos[1] = pos.y;
|
||||
ipos.pos[2] = pos.z;
|
||||
ipos.rot[0] = 0;
|
||||
ipos.rot[1] = 0;
|
||||
ipos.rot[2] = 0;
|
||||
|
||||
MWWorld::CellStore* store = MWBase::Environment::get().getWorld()->getPlayer().getPlayer().getCell();
|
||||
MWWorld::ManualRef ref(MWBase::Environment::get().getWorld()->getStore(),itemID);
|
||||
ref.getPtr().getCellRef().mPos = ipos;
|
||||
ref.getPtr().getRefData().setCount(count);
|
||||
MWBase::Environment::get().getWorld()->safePlaceObject(ref.getPtr(),*store,ipos);
|
||||
}
|
||||
};
|
||||
|
||||
template<class R>
|
||||
class OpPlaceAtMe : public Interpreter::Opcode0
|
||||
{
|
||||
public:
|
||||
|
||||
virtual void execute (Interpreter::Runtime& runtime)
|
||||
{
|
||||
MWWorld::Ptr me = R()(runtime);
|
||||
MWWorld::Ptr actor = pc
|
||||
? MWBase::Environment::get().getWorld()->getPlayer().getPlayer()
|
||||
: R()(runtime);
|
||||
|
||||
std::string itemID = runtime.getStringLiteral (runtime[0].mInteger);
|
||||
runtime.pop();
|
||||
@ -524,7 +478,7 @@ namespace MWScript
|
||||
if (count == 0)
|
||||
return;
|
||||
|
||||
ESM::Position ipos = me.getRefData().getPosition();
|
||||
ESM::Position ipos = actor.getRefData().getPosition();
|
||||
Ogre::Vector3 pos(ipos.pos[0],ipos.pos[1],ipos.pos[2]);
|
||||
Ogre::Quaternion rot(Ogre::Radian(-ipos.rot[2]), Ogre::Vector3::UNIT_Z);
|
||||
if(direction == 0) pos = pos + distance*rot.yAxis();
|
||||
@ -540,12 +494,12 @@ namespace MWScript
|
||||
ipos.rot[1] = 0;
|
||||
ipos.rot[2] = 0;
|
||||
|
||||
MWWorld::CellStore* store = me.getCell();
|
||||
MWWorld::ManualRef ref(MWBase::Environment::get().getWorld()->getStore(),itemID);
|
||||
// create item
|
||||
MWWorld::CellStore* store = actor.getCell();
|
||||
MWWorld::ManualRef ref(MWBase::Environment::get().getWorld()->getStore(), itemID, count);
|
||||
ref.getPtr().getCellRef().mPos = ipos;
|
||||
ref.getPtr().getRefData().setCount(count);
|
||||
MWBase::Environment::get().getWorld()->safePlaceObject(ref.getPtr(),*store,ipos);
|
||||
|
||||
MWBase::Environment::get().getWorld()->safePlaceObject(ref.getPtr(),*store,ipos);
|
||||
}
|
||||
};
|
||||
|
||||
@ -730,9 +684,9 @@ namespace MWScript
|
||||
interpreter.installSegment5(Compiler::Transformation::opcodePositionCellExplicit,new OpPositionCell<ExplicitRef>);
|
||||
interpreter.installSegment5(Compiler::Transformation::opcodePlaceItemCell,new OpPlaceItemCell<ImplicitRef>);
|
||||
interpreter.installSegment5(Compiler::Transformation::opcodePlaceItem,new OpPlaceItem<ImplicitRef>);
|
||||
interpreter.installSegment5(Compiler::Transformation::opcodePlaceAtPc,new OpPlaceAtPc<ImplicitRef>);
|
||||
interpreter.installSegment5(Compiler::Transformation::opcodePlaceAtMe,new OpPlaceAtMe<ImplicitRef>);
|
||||
interpreter.installSegment5(Compiler::Transformation::opcodePlaceAtMeExplicit,new OpPlaceAtMe<ExplicitRef>);
|
||||
interpreter.installSegment5(Compiler::Transformation::opcodePlaceAtPc,new OpPlaceAt<ImplicitRef, true>);
|
||||
interpreter.installSegment5(Compiler::Transformation::opcodePlaceAtMe,new OpPlaceAt<ImplicitRef, false>);
|
||||
interpreter.installSegment5(Compiler::Transformation::opcodePlaceAtMeExplicit,new OpPlaceAt<ExplicitRef, false>);
|
||||
interpreter.installSegment5(Compiler::Transformation::opcodeModScale,new OpModScale<ImplicitRef>);
|
||||
interpreter.installSegment5(Compiler::Transformation::opcodeModScaleExplicit,new OpModScale<ExplicitRef>);
|
||||
interpreter.installSegment5(Compiler::Transformation::opcodeRotate,new OpRotate<ImplicitRef>);
|
||||
|
@ -11,6 +11,8 @@
|
||||
#include "../mwmechanics/creaturestats.hpp"
|
||||
#include "../mwmechanics/npcstats.hpp"
|
||||
|
||||
#include "../mwworld/containerstore.hpp"
|
||||
|
||||
#include "esmstore.hpp"
|
||||
#include "class.hpp"
|
||||
|
||||
@ -18,8 +20,8 @@ namespace MWWorld
|
||||
{
|
||||
void ActionEat::executeImp (const Ptr& actor)
|
||||
{
|
||||
// remove used item
|
||||
getTarget().getRefData().setCount (getTarget().getRefData().getCount()-1);
|
||||
// remove used item (assume the item is present in inventory)
|
||||
getTarget().getContainerStore()->remove(getTarget(), 1, actor);
|
||||
|
||||
// check for success
|
||||
const MWMechanics::CreatureStats& creatureStats = MWWorld::Class::get (actor).getCreatureStats (actor);
|
||||
|
@ -32,10 +32,10 @@ namespace MWWorld
|
||||
case 0:
|
||||
return;
|
||||
case 2:
|
||||
invStore.equip(MWWorld::InventoryStore::Slot_CarriedLeft, invStore.end());
|
||||
invStore.unequipSlot(MWWorld::InventoryStore::Slot_CarriedLeft, actor);
|
||||
break;
|
||||
case 3:
|
||||
invStore.equip(MWWorld::InventoryStore::Slot_CarriedRight, invStore.end());
|
||||
invStore.unequipSlot(MWWorld::InventoryStore::Slot_CarriedRight, actor);
|
||||
break;
|
||||
}
|
||||
|
||||
@ -64,7 +64,7 @@ namespace MWWorld
|
||||
// if all slots are occupied, replace the last slot
|
||||
if (slot == --slots.first.end())
|
||||
{
|
||||
invStore.equip(*slot, it);
|
||||
invStore.equip(*slot, it, actor);
|
||||
equipped = true;
|
||||
break;
|
||||
}
|
||||
@ -72,7 +72,7 @@ namespace MWWorld
|
||||
if (invStore.getSlot(*slot) == invStore.end())
|
||||
{
|
||||
// slot is not occupied
|
||||
invStore.equip(*slot, it);
|
||||
invStore.equip(*slot, it, actor);
|
||||
equipped = true;
|
||||
break;
|
||||
}
|
||||
|
@ -77,22 +77,31 @@ MWWorld::ContainerStoreIterator MWWorld::ContainerStore::end()
|
||||
return ContainerStoreIterator (this);
|
||||
}
|
||||
|
||||
bool MWWorld::ContainerStore::stacks(const Ptr& ptr1, const Ptr& ptr2)
|
||||
bool MWWorld::ContainerStore::stacks(const Ptr& stack, const Ptr& item)
|
||||
{
|
||||
/// \todo add current enchantment charge here when it is implemented
|
||||
if ( Misc::StringUtils::ciEqual(ptr1.getCellRef().mRefID, ptr2.getCellRef().mRefID)
|
||||
&& MWWorld::Class::get(ptr1).getScript(ptr1) == "" // item with a script never stacks
|
||||
&& MWWorld::Class::get(ptr1).getEnchantment(ptr1) == "" // item with enchantment never stacks (we could revisit this later, but for now it makes selecting items in the spell window much easier)
|
||||
&& ptr1.getCellRef().mOwner == ptr2.getCellRef().mOwner
|
||||
&& ptr1.getCellRef().mSoul == ptr2.getCellRef().mSoul
|
||||
// item that is already partly used up never stacks
|
||||
&& (!MWWorld::Class::get(ptr1).hasItemHealth(ptr1) || ptr1.getCellRef().mCharge == -1
|
||||
|| MWWorld::Class::get(ptr1).getItemMaxHealth(ptr1) == ptr1.getCellRef().mCharge)
|
||||
&& (!MWWorld::Class::get(ptr2).hasItemHealth(ptr2) || ptr2.getCellRef().mCharge == -1
|
||||
|| MWWorld::Class::get(ptr2).getItemMaxHealth(ptr2) == ptr2.getCellRef().mCharge))
|
||||
return true;
|
||||
const MWWorld::Class& cls1 = MWWorld::Class::get(stack);
|
||||
const MWWorld::Class& cls2 = MWWorld::Class::get(item);
|
||||
|
||||
return false;
|
||||
/// \todo add current enchantment charge here when it is implemented
|
||||
return stack != item // an item never stacks onto itself
|
||||
&& Misc::StringUtils::ciEqual(stack.getCellRef().mRefID, item.getCellRef().mRefID)
|
||||
&& stack.getCellRef().mOwner == item.getCellRef().mOwner
|
||||
&& stack.getCellRef().mSoul == item.getCellRef().mSoul
|
||||
|
||||
// item with a script never stacks
|
||||
&& cls1.getScript(stack) == ""
|
||||
&& cls2.getScript(item) == ""
|
||||
|
||||
// item with enchantment never stacks (we could revisit this later,
|
||||
// but for now it makes selecting items in the spell window much easier)
|
||||
&& cls1.getEnchantment(stack) == ""
|
||||
&& cls2.getEnchantment(item) == ""
|
||||
|
||||
// item that is already partly used up never stacks
|
||||
&& (!cls1.hasItemHealth(stack) || stack.getCellRef().mCharge == -1
|
||||
|| cls1.getItemMaxHealth(stack) == stack.getCellRef().mCharge)
|
||||
&& (!cls2.hasItemHealth(item) || item.getCellRef().mCharge == -1
|
||||
|| cls2.getItemMaxHealth(item) == item.getCellRef().mCharge);
|
||||
}
|
||||
|
||||
MWWorld::ContainerStoreIterator MWWorld::ContainerStore::add (const Ptr& itemPtr, const Ptr& actorPtr)
|
||||
@ -140,22 +149,20 @@ MWWorld::ContainerStoreIterator MWWorld::ContainerStore::addImp (const Ptr& ptr)
|
||||
|| Misc::StringUtils::ciEqual(ptr.getCellRef().mRefID, "gold_025")
|
||||
|| Misc::StringUtils::ciEqual(ptr.getCellRef().mRefID, "gold_100"))
|
||||
{
|
||||
MWWorld::ManualRef ref(esmStore, "Gold_001");
|
||||
|
||||
int count = MWWorld::Class::get(ptr).getValue(ptr) * ptr.getRefData().getCount();
|
||||
|
||||
ref.getPtr().getRefData().setCount(count);
|
||||
for (MWWorld::ContainerStoreIterator iter (begin(type)); iter!=end(); ++iter)
|
||||
{
|
||||
if (Misc::StringUtils::ciEqual((*iter).get<ESM::Miscellaneous>()->mRef.mRefID, "gold_001"))
|
||||
{
|
||||
(*iter).getRefData().setCount( (*iter).getRefData().getCount() + count);
|
||||
iter->getRefData().setCount(iter->getRefData().getCount() + count);
|
||||
flagAsModified();
|
||||
return iter;
|
||||
}
|
||||
}
|
||||
|
||||
return addImpl(ref.getPtr());
|
||||
MWWorld::ManualRef ref(esmStore, "Gold_001", count);
|
||||
return addNewStack(ref.getPtr());
|
||||
}
|
||||
|
||||
// determine whether to stack or not
|
||||
@ -171,10 +178,10 @@ MWWorld::ContainerStoreIterator MWWorld::ContainerStore::addImp (const Ptr& ptr)
|
||||
}
|
||||
}
|
||||
// if we got here, this means no stacking
|
||||
return addImpl(ptr);
|
||||
return addNewStack(ptr);
|
||||
}
|
||||
|
||||
MWWorld::ContainerStoreIterator MWWorld::ContainerStore::addImpl (const Ptr& ptr)
|
||||
MWWorld::ContainerStoreIterator MWWorld::ContainerStore::addNewStack (const Ptr& ptr)
|
||||
{
|
||||
ContainerStoreIterator it = begin();
|
||||
|
||||
@ -198,6 +205,40 @@ MWWorld::ContainerStoreIterator MWWorld::ContainerStore::addImpl (const Ptr& ptr
|
||||
return it;
|
||||
}
|
||||
|
||||
int MWWorld::ContainerStore::remove(const std::string& itemId, int count, const Ptr& actor)
|
||||
{
|
||||
int toRemove = count;
|
||||
|
||||
for (ContainerStoreIterator iter(begin()); iter != end() && toRemove > 0; ++iter)
|
||||
if (Misc::StringUtils::ciEqual(iter->getCellRef().mRefID, itemId))
|
||||
toRemove -= remove(*iter, toRemove, actor);
|
||||
|
||||
// number of removed items
|
||||
return count - toRemove;
|
||||
}
|
||||
|
||||
int MWWorld::ContainerStore::remove(const Ptr& item, int count, const Ptr& actor)
|
||||
{
|
||||
assert(this == item.getContainerStore());
|
||||
|
||||
int toRemove = count;
|
||||
RefData& itemRef = item.getRefData();
|
||||
|
||||
if (itemRef.getCount() <= toRemove)
|
||||
{
|
||||
toRemove -= itemRef.getCount();
|
||||
itemRef.setCount(0);
|
||||
}
|
||||
else
|
||||
{
|
||||
itemRef.setCount(itemRef.getCount() - toRemove);
|
||||
toRemove = 0;
|
||||
}
|
||||
|
||||
// number of removed items
|
||||
return count - toRemove;
|
||||
}
|
||||
|
||||
void MWWorld::ContainerStore::fill (const ESM::InventoryList& items, const std::string& owner, const MWWorld::ESMStore& store)
|
||||
{
|
||||
for (std::vector<ESM::ContItem>::const_iterator iter (items.mList.begin()); iter!=items.mList.end();
|
||||
@ -216,7 +257,7 @@ void MWWorld::ContainerStore::addInitialItem (const std::string& id, const std::
|
||||
|
||||
try
|
||||
{
|
||||
ManualRef ref (MWBase::Environment::get().getWorld()->getStore(), id);
|
||||
ManualRef ref (MWBase::Environment::get().getWorld()->getStore(), id, count);
|
||||
|
||||
if (ref.getPtr().getTypeName()==typeid (ESM::ItemLevList).name())
|
||||
{
|
||||
@ -266,7 +307,6 @@ void MWWorld::ContainerStore::addInitialItem (const std::string& id, const std::
|
||||
}
|
||||
else
|
||||
{
|
||||
ref.getPtr().getRefData().setCount (count);
|
||||
ref.getPtr().getCellRef().mOwner = owner;
|
||||
addImp (ref.getPtr());
|
||||
}
|
||||
|
@ -75,14 +75,25 @@ namespace MWWorld
|
||||
///
|
||||
/// @return if stacking happened, return iterator to the item that was stacked against, otherwise iterator to the newly inserted item.
|
||||
|
||||
int remove(const std::string& itemId, int count, const Ptr& actor);
|
||||
///< Remove \a count item(s) designated by \a itemId from this container.
|
||||
///
|
||||
/// @return the number of items actually removed
|
||||
|
||||
virtual int remove(const Ptr& item, int count, const Ptr& actor);
|
||||
///< Remove \a count item(s) designated by \a item from this inventory.
|
||||
///
|
||||
/// @return the number of items actually removed
|
||||
|
||||
protected:
|
||||
ContainerStoreIterator addImpl (const Ptr& ptr);
|
||||
///< Add the item to this container (no stacking)
|
||||
ContainerStoreIterator addNewStack (const Ptr& ptr);
|
||||
///< Add the item to this container (do not try to stack it onto existing items)
|
||||
|
||||
public:
|
||||
|
||||
virtual bool stacks (const Ptr& ptr1, const Ptr& ptr2);
|
||||
virtual bool stacks (const Ptr& stack, const Ptr& item);
|
||||
///< @return true if the two specified objects can stack with each other
|
||||
/// @note stack is the item that is already in this container
|
||||
|
||||
void fill (const ESM::InventoryList& items, const std::string& owner, const MWWorld::ESMStore& store);
|
||||
///< Insert items into *this.
|
||||
|
@ -8,6 +8,7 @@
|
||||
|
||||
#include "../mwbase/environment.hpp"
|
||||
#include "../mwbase/world.hpp"
|
||||
#include "../mwbase/windowmanager.hpp"
|
||||
|
||||
#include "../mwmechanics/npcstats.hpp"
|
||||
|
||||
@ -40,6 +41,7 @@ void MWWorld::InventoryStore::initSlots (TSlots& slots)
|
||||
|
||||
MWWorld::InventoryStore::InventoryStore() : mMagicEffectsUpToDate (false)
|
||||
, mSelectedEnchantItem(end())
|
||||
, mActorModelUpdateEnabled (true)
|
||||
{
|
||||
initSlots (mSlots);
|
||||
}
|
||||
@ -80,7 +82,7 @@ MWWorld::ContainerStoreIterator MWWorld::InventoryStore::add(const Ptr& itemPtr,
|
||||
return retVal;
|
||||
}
|
||||
|
||||
void MWWorld::InventoryStore::equip (int slot, const ContainerStoreIterator& iterator)
|
||||
void MWWorld::InventoryStore::equip (int slot, const ContainerStoreIterator& iterator, const Ptr& actor)
|
||||
{
|
||||
if (slot<0 || slot>=static_cast<int> (mSlots.size()))
|
||||
throw std::runtime_error ("slot number out of range");
|
||||
@ -97,19 +99,8 @@ void MWWorld::InventoryStore::equip (int slot, const ContainerStoreIterator& ite
|
||||
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;
|
||||
}
|
||||
}
|
||||
}
|
||||
unequipSlot(slot, actor);
|
||||
|
||||
// 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
|
||||
@ -117,30 +108,21 @@ void MWWorld::InventoryStore::equip (int slot, const ContainerStoreIterator& ite
|
||||
// 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);
|
||||
addNewStack(*iterator);
|
||||
iterator->getRefData().setCount(1);
|
||||
}
|
||||
|
||||
mSlots[slot] = iterator;
|
||||
|
||||
flagAsModified();
|
||||
|
||||
updateActorModel(actor);
|
||||
}
|
||||
|
||||
void MWWorld::InventoryStore::unequipAll(const MWWorld::Ptr& actor)
|
||||
{
|
||||
for (int slot=0; slot < MWWorld::InventoryStore::Slots; ++slot)
|
||||
{
|
||||
MWWorld::ContainerStoreIterator it = getSlot(slot);
|
||||
if (it != end())
|
||||
{
|
||||
equip(slot, end());
|
||||
std::string script = MWWorld::Class::get(*it).getScript(*it);
|
||||
|
||||
// Unset OnPCEquip Variable on item's script, if it has a script with that variable declared
|
||||
if((actor.getRefData().getHandle() == "player") && (script != ""))
|
||||
(*it).getRefData().getLocals().setVarByInt(script, "onpcequip", 0);
|
||||
}
|
||||
}
|
||||
unequipSlot(slot, actor);
|
||||
}
|
||||
|
||||
MWWorld::ContainerStoreIterator MWWorld::InventoryStore::getSlot (int slot)
|
||||
@ -169,6 +151,9 @@ void MWWorld::InventoryStore::autoEquip (const MWWorld::Ptr& npc)
|
||||
TSlots slots;
|
||||
initSlots (slots);
|
||||
|
||||
// Disable model update during auto-equip
|
||||
mActorModelUpdateEnabled = false;
|
||||
|
||||
for (ContainerStoreIterator iter (begin()); iter!=end(); ++iter)
|
||||
{
|
||||
Ptr test = *iter;
|
||||
@ -224,10 +209,10 @@ void MWWorld::InventoryStore::autoEquip (const MWWorld::Ptr& npc)
|
||||
case 0:
|
||||
continue;
|
||||
case 2:
|
||||
invStore.equip(MWWorld::InventoryStore::Slot_CarriedLeft, invStore.end());
|
||||
invStore.unequipSlot(MWWorld::InventoryStore::Slot_CarriedLeft, npc);
|
||||
break;
|
||||
case 3:
|
||||
invStore.equip(MWWorld::InventoryStore::Slot_CarriedRight, invStore.end());
|
||||
invStore.unequipSlot(MWWorld::InventoryStore::Slot_CarriedRight, npc);
|
||||
break;
|
||||
}
|
||||
|
||||
@ -239,7 +224,7 @@ void MWWorld::InventoryStore::autoEquip (const MWWorld::Ptr& npc)
|
||||
// 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);
|
||||
addNewStack(*iter);
|
||||
iter->getRefData().setCount(1);
|
||||
}
|
||||
}
|
||||
@ -257,9 +242,12 @@ void MWWorld::InventoryStore::autoEquip (const MWWorld::Ptr& npc)
|
||||
changed = true;
|
||||
}
|
||||
|
||||
mActorModelUpdateEnabled = true;
|
||||
|
||||
if (changed)
|
||||
{
|
||||
mSlots.swap (slots);
|
||||
updateActorModel(npc);
|
||||
flagAsModified();
|
||||
}
|
||||
}
|
||||
@ -297,20 +285,22 @@ void MWWorld::InventoryStore::flagAsModified()
|
||||
mMagicEffectsUpToDate = false;
|
||||
}
|
||||
|
||||
bool MWWorld::InventoryStore::stacks(const Ptr& ptr1, const Ptr& ptr2)
|
||||
bool MWWorld::InventoryStore::stacks(const Ptr& stack, const Ptr& item)
|
||||
{
|
||||
bool canStack = MWWorld::ContainerStore::stacks(ptr1, ptr2);
|
||||
bool canStack = MWWorld::ContainerStore::stacks(stack, item);
|
||||
if (!canStack)
|
||||
return false;
|
||||
|
||||
// don't stack if the item being checked against is currently equipped.
|
||||
// don't stack if 'stack' (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;
|
||||
if (*iter != end() && ptr2 == **iter)
|
||||
return false;
|
||||
if (*iter != end() && stack == **iter)
|
||||
{
|
||||
bool stackWhenEquipped = MWWorld::Class::get(**iter).getEquipmentSlots(**iter).second;
|
||||
if (!stackWhenEquipped)
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
return true;
|
||||
@ -325,3 +315,105 @@ MWWorld::ContainerStoreIterator MWWorld::InventoryStore::getSelectedEnchantItem(
|
||||
{
|
||||
return mSelectedEnchantItem;
|
||||
}
|
||||
|
||||
int MWWorld::InventoryStore::remove(const Ptr& item, int count, const Ptr& actor)
|
||||
{
|
||||
for (int slot=0; slot < MWWorld::InventoryStore::Slots; ++slot)
|
||||
{
|
||||
if (mSlots[slot] == end())
|
||||
continue;
|
||||
|
||||
if (*mSlots[slot] == item)
|
||||
{
|
||||
// restacking is disabled cause it may break removal
|
||||
unequipSlot(slot, actor, false);
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
int retCount = ContainerStore::remove(item, count, actor);
|
||||
|
||||
// If an armor/clothing item is removed, try to find a replacement,
|
||||
// but not for the player nor werewolves.
|
||||
if ((actor.getRefData().getHandle() != "player")
|
||||
&& !(MWWorld::Class::get(actor).getNpcStats(actor).isWerewolf()))
|
||||
{
|
||||
std::string type = item.getTypeName();
|
||||
if ((type == typeid(ESM::Armor).name()) || (type == typeid(ESM::Clothing).name()))
|
||||
autoEquip(actor);
|
||||
}
|
||||
|
||||
return retCount;
|
||||
}
|
||||
|
||||
MWWorld::ContainerStoreIterator MWWorld::InventoryStore::unequipSlot(int slot, const MWWorld::Ptr& actor, bool restack)
|
||||
{
|
||||
ContainerStoreIterator it = getSlot(slot);
|
||||
|
||||
if (it != end())
|
||||
{
|
||||
ContainerStoreIterator retval = it;
|
||||
|
||||
if (restack) {
|
||||
// restack item previously in this slot
|
||||
for (MWWorld::ContainerStoreIterator iter (begin()); iter != end(); ++iter)
|
||||
{
|
||||
if (stacks(*iter, *it))
|
||||
{
|
||||
iter->getRefData().setCount(iter->getRefData().getCount() + it->getRefData().getCount());
|
||||
it->getRefData().setCount(0);
|
||||
retval = iter;
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// empty this slot
|
||||
mSlots[slot] = end();
|
||||
|
||||
if (actor.getRefData().getHandle() == "player")
|
||||
{
|
||||
// Unset OnPCEquip Variable on item's script, if it has a script with that variable declared
|
||||
const std::string& script = Class::get(*it).getScript(*it);
|
||||
if (script != "")
|
||||
(*it).getRefData().getLocals().setVarByInt(script, "onpcequip", 0);
|
||||
|
||||
// Update HUD icon when removing player weapon or selected enchanted item.
|
||||
// We have to check for both as the weapon could also be the enchanted item.
|
||||
if (slot == MWWorld::InventoryStore::Slot_CarriedRight)
|
||||
{
|
||||
// weapon
|
||||
MWBase::Environment::get().getWindowManager()->unsetSelectedWeapon();
|
||||
}
|
||||
if ((mSelectedEnchantItem != end()) && (mSelectedEnchantItem == it))
|
||||
{
|
||||
// enchanted item
|
||||
MWBase::Environment::get().getWindowManager()->unsetSelectedSpell();
|
||||
}
|
||||
}
|
||||
|
||||
updateActorModel(actor);
|
||||
|
||||
return retval;
|
||||
}
|
||||
|
||||
return it;
|
||||
}
|
||||
|
||||
MWWorld::ContainerStoreIterator MWWorld::InventoryStore::unequipItem(const MWWorld::Ptr& item, const MWWorld::Ptr& actor)
|
||||
{
|
||||
for (int slot=0; slot<MWWorld::InventoryStore::Slots; ++slot)
|
||||
{
|
||||
MWWorld::ContainerStoreIterator equipped = getSlot(slot);
|
||||
if (equipped != end() && *equipped == item)
|
||||
return unequipSlot(slot, actor);
|
||||
}
|
||||
|
||||
throw std::runtime_error ("attempt to unequip an item that is not currently equipped");
|
||||
}
|
||||
|
||||
void MWWorld::InventoryStore::updateActorModel(const MWWorld::Ptr& actor)
|
||||
{
|
||||
if (mActorModelUpdateEnabled)
|
||||
MWBase::Environment::get().getWorld()->updateAnimParts(actor);
|
||||
}
|
||||
|
@ -45,6 +45,7 @@ namespace MWWorld
|
||||
|
||||
mutable MWMechanics::MagicEffects mMagicEffects;
|
||||
mutable bool mMagicEffectsUpToDate;
|
||||
bool mActorModelUpdateEnabled;
|
||||
|
||||
typedef std::vector<ContainerStoreIterator> TSlots;
|
||||
|
||||
@ -57,6 +58,8 @@ namespace MWWorld
|
||||
|
||||
void initSlots (TSlots& slots);
|
||||
|
||||
void updateActorModel (const Ptr& actor);
|
||||
|
||||
public:
|
||||
|
||||
InventoryStore();
|
||||
@ -76,7 +79,7 @@ namespace MWWorld
|
||||
///
|
||||
/// @return if stacking happened, return iterator to the item that was stacked against, otherwise iterator to the newly inserted item.
|
||||
|
||||
void equip (int slot, const ContainerStoreIterator& iterator);
|
||||
void equip (int slot, const ContainerStoreIterator& iterator, const Ptr& actor);
|
||||
///< \note \a iterator can be an end-iterator
|
||||
|
||||
void setSelectedEnchantItem(const ContainerStoreIterator& iterator);
|
||||
@ -104,10 +107,29 @@ namespace MWWorld
|
||||
///< \attention This function is internal to the world model and should not be called from
|
||||
/// outside.
|
||||
|
||||
virtual bool stacks (const Ptr& ptr1, const Ptr& ptr2);
|
||||
virtual bool stacks (const Ptr& stack, const Ptr& item);
|
||||
///< @return true if the two specified objects can stack with each other
|
||||
/// @note ptr1 is the item that is already in this container
|
||||
/// @note stack is the item that is already in this container (it may be equipped)
|
||||
|
||||
virtual int remove(const Ptr& item, int count, const Ptr& actor);
|
||||
///< Remove \a count item(s) designated by \a item from this inventory.
|
||||
///
|
||||
/// @return the number of items actually removed
|
||||
|
||||
ContainerStoreIterator unequipSlot(int slot, const Ptr& actor, bool restack = true);
|
||||
///< Unequip \a slot.
|
||||
///
|
||||
/// @return an iterator to the item that was previously in the slot
|
||||
/// (if \a restack is true, the item can be re-stacked so its count
|
||||
/// may differ from when it was equipped).
|
||||
|
||||
ContainerStoreIterator unequipItem(const Ptr& item, const Ptr& actor);
|
||||
///< Unequip an item identified by its Ptr. An exception is thrown
|
||||
/// if the item is not currently equipped.
|
||||
///
|
||||
/// @return an iterator to the item that was previously in the slot
|
||||
/// (it can be re-stacked so its count may be different than when it
|
||||
/// was equipped).
|
||||
};
|
||||
}
|
||||
|
||||
|
@ -37,7 +37,7 @@ namespace MWWorld
|
||||
|
||||
public:
|
||||
|
||||
ManualRef (const MWWorld::ESMStore& store, const std::string& name)
|
||||
ManualRef (const MWWorld::ESMStore& store, const std::string& name, const int count=1)
|
||||
{
|
||||
// create
|
||||
if (!create (store.get<ESM::Activator>(), name) &&
|
||||
@ -74,6 +74,7 @@ namespace MWWorld
|
||||
cellRef.mTeleport = false;
|
||||
cellRef.mLockLevel = 0;
|
||||
cellRef.mReferenceBlocked = 0;
|
||||
mPtr.getRefData().setCount(count);
|
||||
}
|
||||
|
||||
const Ptr& getPtr() const
|
||||
|
@ -73,6 +73,11 @@ namespace MWWorld
|
||||
void setLocals (const ESM::Script& script);
|
||||
|
||||
void setCount (int count);
|
||||
/// Set object count (an object pile is a simple object with a count >1).
|
||||
///
|
||||
/// \warning Do not call setCount() to add or remove objects from a
|
||||
/// container or an actor's inventory. Call ContainerStore::add() or
|
||||
/// ContainerStore::remove() instead.
|
||||
|
||||
MWScript::Locals& getLocals();
|
||||
|
||||
|
@ -837,12 +837,13 @@ namespace MWWorld
|
||||
|
||||
void World::deleteObject (const Ptr& ptr)
|
||||
{
|
||||
if (ptr.getRefData().getCount()>0)
|
||||
if (ptr.getRefData().getCount() > 0)
|
||||
{
|
||||
ptr.getRefData().setCount (0);
|
||||
ptr.getRefData().setCount(0);
|
||||
|
||||
if (mWorldScene->getActiveCells().find (ptr.getCell())!=mWorldScene->getActiveCells().end() &&
|
||||
ptr.getRefData().isEnabled())
|
||||
if (ptr.isInCell()
|
||||
&& mWorldScene->getActiveCells().find(ptr.getCell()) != mWorldScene->getActiveCells().end()
|
||||
&& ptr.getRefData().isEnabled())
|
||||
{
|
||||
mWorldScene->removeObjectFromScene (ptr);
|
||||
mLocalScripts.remove (ptr);
|
||||
@ -1477,7 +1478,7 @@ namespace MWWorld
|
||||
item.getRefData().getLocals().setVarByInt(script, "onpcdrop", 1);
|
||||
}
|
||||
|
||||
bool World::placeObject (const Ptr& object, float cursorX, float cursorY)
|
||||
bool World::placeObject (const MWWorld::Ptr& object, float cursorX, float cursorY, int amount)
|
||||
{
|
||||
std::pair<bool, Ogre::Vector3> result = mPhysics->castRay(cursorX, cursorY);
|
||||
|
||||
@ -1502,9 +1503,14 @@ namespace MWWorld
|
||||
pos.rot[0] = 0;
|
||||
pos.rot[1] = 0;
|
||||
|
||||
// copy the object and set its count
|
||||
int origCount = object.getRefData().getCount();
|
||||
object.getRefData().setCount(amount);
|
||||
Ptr dropped = copyObjectToCell(object, *cell, pos);
|
||||
object.getRefData().setCount(origCount);
|
||||
|
||||
// only the player place items in the world, so no need to check actor
|
||||
PCDropped(dropped);
|
||||
object.getRefData().setCount(0);
|
||||
|
||||
return true;
|
||||
}
|
||||
@ -1549,7 +1555,7 @@ namespace MWWorld
|
||||
return dropped;
|
||||
}
|
||||
|
||||
void World::dropObjectOnGround (const Ptr& actor, const Ptr& object)
|
||||
void World::dropObjectOnGround (const Ptr& actor, const Ptr& object, int amount)
|
||||
{
|
||||
MWWorld::Ptr::CellStore* cell = actor.getCell();
|
||||
|
||||
@ -1570,10 +1576,14 @@ namespace MWWorld
|
||||
mPhysics->castRay(orig, dir, len);
|
||||
pos.pos[2] = hit.second.z;
|
||||
|
||||
// copy the object and set its count
|
||||
int origCount = object.getRefData().getCount();
|
||||
object.getRefData().setCount(amount);
|
||||
Ptr dropped = copyObjectToCell(object, *cell, pos);
|
||||
object.getRefData().setCount(origCount);
|
||||
|
||||
if(actor == mPlayer->getPlayer()) // Only call if dropped by player
|
||||
PCDropped(dropped);
|
||||
object.getRefData().setCount(0);
|
||||
}
|
||||
|
||||
void World::processChangedSettings(const Settings::CategorySettingVector& settings)
|
||||
@ -1939,7 +1949,6 @@ namespace MWWorld
|
||||
if(werewolf)
|
||||
{
|
||||
ManualRef ref(getStore(), "WerewolfRobe");
|
||||
ref.getPtr().getRefData().setCount(1);
|
||||
|
||||
// Configure item's script variables
|
||||
std::string script = Class::get(ref.getPtr()).getScript(ref.getPtr());
|
||||
@ -1951,18 +1960,11 @@ namespace MWWorld
|
||||
|
||||
// Not sure this is right
|
||||
InventoryStore &inv = Class::get(actor).getInventoryStore(actor);
|
||||
inv.equip(InventoryStore::Slot_Robe, inv.add(ref.getPtr(), actor));
|
||||
inv.equip(InventoryStore::Slot_Robe, inv.add(ref.getPtr(), actor), actor);
|
||||
}
|
||||
else
|
||||
{
|
||||
ContainerStore &store = Class::get(actor).getContainerStore(actor);
|
||||
|
||||
const std::string item = "WerewolfRobe";
|
||||
for(ContainerStoreIterator iter(store.begin());iter != store.end();++iter)
|
||||
{
|
||||
if(Misc::StringUtils::ciEqual(iter->getCellRef().mRefID, item))
|
||||
iter->getRefData().setCount(0);
|
||||
}
|
||||
Class::get(actor).getContainerStore(actor).remove("WerewolfRobe", 1, actor);
|
||||
}
|
||||
|
||||
if(actor.getRefData().getHandle() == "player")
|
||||
@ -2133,4 +2135,9 @@ namespace MWWorld
|
||||
// TODO: RT_Range, RT_Touch
|
||||
}
|
||||
}
|
||||
|
||||
void World::updateAnimParts(const Ptr& actor)
|
||||
{
|
||||
mRendering->updateAnimParts(actor);
|
||||
}
|
||||
}
|
||||
|
@ -354,14 +354,19 @@ namespace MWWorld
|
||||
|
||||
virtual void update (float duration, bool paused);
|
||||
|
||||
virtual bool placeObject (const Ptr& object, float cursorX, float cursorY);
|
||||
///< place an object into the gameworld at the specified cursor position
|
||||
virtual bool placeObject (const MWWorld::Ptr& object, float cursorX, float cursorY, int amount);
|
||||
///< copy and place an object into the gameworld at the specified cursor position
|
||||
/// @param object
|
||||
/// @param cursor X (relative 0-1)
|
||||
/// @param cursor Y (relative 0-1)
|
||||
/// @param number of objects to place
|
||||
/// @return true if the object was placed, or false if it was rejected because the position is too far away
|
||||
|
||||
virtual void dropObjectOnGround (const Ptr& actor, const Ptr& object);
|
||||
virtual void dropObjectOnGround (const MWWorld::Ptr& actor, const MWWorld::Ptr& object, int amount);
|
||||
///< copy and place an object into the gameworld at the given actor's position
|
||||
/// @param actor giving the dropped object position
|
||||
/// @param object
|
||||
/// @param number of objects to place
|
||||
|
||||
virtual bool canPlaceObject(float cursorX, float cursorY);
|
||||
///< @return true if it is possible to place on object at specified cursor location
|
||||
@ -468,6 +473,8 @@ namespace MWWorld
|
||||
virtual bool toggleGodMode();
|
||||
|
||||
virtual void castSpell (const MWWorld::Ptr& actor);
|
||||
|
||||
virtual void updateAnimParts(const MWWorld::Ptr& ptr);
|
||||
};
|
||||
}
|
||||
|
||||
|
Loading…
x
Reference in New Issue
Block a user