1
0
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:
Marc Zinnschlag 2013-11-10 21:30:19 +01:00
commit cfbf444628
32 changed files with 413 additions and 334 deletions

View File

@ -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;
};
}

View File

@ -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 =

View File

@ -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));

View File

@ -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()

View File

@ -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;
}

View File

@ -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();

View File

@ -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()

View File

@ -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();

View File

@ -103,7 +103,6 @@ namespace MWGui
void onAvatarClicked(MyGUI::Widget* _sender);
void onPinToggled();
void unequipItem(const MWWorld::Ptr& item);
void updateEncumbranceBar();
void notifyContentChanged();
};

View File

@ -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);
}
}

View File

@ -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)

View File

@ -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;

View File

@ -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);
}
}

View File

@ -22,7 +22,6 @@ namespace MWMechanics
std::string mNewItemName;
std::string mObjectType;
std::string mOldItemId;
int mOldItemCount;
public:
Enchanting();

View File

@ -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);
}

View File

@ -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)
{

View File

@ -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);
}
}

View File

@ -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();

View File

@ -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);

View File

@ -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}");

View File

@ -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);
}
};

View File

@ -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>);

View File

@ -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);

View File

@ -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;
}

View File

@ -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());
}

View File

@ -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.

View File

@ -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);
}

View File

@ -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).
};
}

View File

@ -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

View File

@ -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();

View File

@ -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);
}
}

View File

@ -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);
};
}