mirror of
https://github.com/OpenMW/openmw.git
synced 2025-02-28 17:39:42 +00:00
Merge branch 'lua_create' into 'master'
Lua commands to create/move/remove objects; consistent handling of disabled objects (#6726, #6893) See merge request OpenMW/openmw!2627
This commit is contained in:
commit
a9dbb023d7
51 changed files with 458 additions and 239 deletions
|
@ -16,6 +16,7 @@
|
|||
Bug #6645: Enemy block sounds align with animation instead of blocked hits
|
||||
Bug #6661: Saved games that have no preview screenshot cause issues or crashes
|
||||
Bug #6807: Ultimate Galleon is not working properly
|
||||
Bug #6893: Lua: Inconsistent behavior with actors affected by Disable and SetDelete commands
|
||||
Bug #6939: OpenMW-CS: ID columns are too short
|
||||
Bug #6949: Sun Damage effect doesn't work in quasi exteriors
|
||||
Bug #6964: Nerasa Dralor Won't Follow
|
||||
|
@ -35,6 +36,7 @@
|
|||
Bug #7172: Current music playlist continues playing indefinitely if next playlist is empty
|
||||
Feature #5492: Let rain and snow collide with statics
|
||||
Feature #6447: Add LOD support to Object Paging
|
||||
Feature #6726: Lua API for creating new objects
|
||||
Feature #6922: Improve launcher appearance
|
||||
Feature #6933: Support high-resolution cursor textures
|
||||
Feature #6945: Support S3TC-compressed and BGR/BGRA NiPixelData
|
||||
|
|
|
@ -170,7 +170,7 @@ namespace MWClass
|
|||
getContainerStore(ptr).fill(ref->mBase->mInventory, ptr.getCellRef().getRefId(), prng);
|
||||
|
||||
if (hasInventory)
|
||||
getInventoryStore(ptr).autoEquip(ptr);
|
||||
getInventoryStore(ptr).autoEquip();
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -507,14 +507,16 @@ namespace MWClass
|
|||
MWWorld::ContainerStore& Creature::getContainerStore(const MWWorld::Ptr& ptr) const
|
||||
{
|
||||
ensureCustomData(ptr);
|
||||
|
||||
return *ptr.getRefData().getCustomData()->asCreatureCustomData().mContainerStore;
|
||||
auto& store = *ptr.getRefData().getCustomData()->asCreatureCustomData().mContainerStore;
|
||||
if (hasInventoryStore(ptr))
|
||||
static_cast<MWWorld::InventoryStore&>(store).setActor(ptr);
|
||||
return store;
|
||||
}
|
||||
|
||||
MWWorld::InventoryStore& Creature::getInventoryStore(const MWWorld::Ptr& ptr) const
|
||||
{
|
||||
if (hasInventoryStore(ptr))
|
||||
return dynamic_cast<MWWorld::InventoryStore&>(getContainerStore(ptr));
|
||||
return static_cast<MWWorld::InventoryStore&>(getContainerStore(ptr));
|
||||
else
|
||||
throw std::runtime_error("this creature has no inventory store");
|
||||
}
|
||||
|
|
|
@ -17,6 +17,7 @@
|
|||
#include "../mwworld/esmstore.hpp"
|
||||
#include "../mwworld/manualref.hpp"
|
||||
#include "../mwworld/nullaction.hpp"
|
||||
#include "../mwworld/worldmodel.hpp"
|
||||
|
||||
#include "../mwgui/tooltips.hpp"
|
||||
#include "../mwgui/ustring.hpp"
|
||||
|
@ -208,6 +209,7 @@ namespace MWClass
|
|||
newPtr.getRefData().setCount(count);
|
||||
}
|
||||
newPtr.getCellRef().unsetRefNum();
|
||||
MWBase::Environment::get().getWorldModel()->registerPtr(newPtr);
|
||||
|
||||
return newPtr;
|
||||
}
|
||||
|
|
|
@ -414,7 +414,7 @@ namespace MWClass
|
|||
auto& prng = MWBase::Environment::get().getWorld()->getPrng();
|
||||
getInventoryStore(ptr).fill(ref->mBase->mInventory, ptr.getCellRef().getRefId(), prng);
|
||||
|
||||
getInventoryStore(ptr).autoEquip(ptr);
|
||||
getInventoryStore(ptr).autoEquip();
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -862,7 +862,7 @@ namespace MWClass
|
|||
|
||||
// Armor broken? unequip it
|
||||
if (armorhealth == 0)
|
||||
armor = *inv.unequipItem(armor, ptr);
|
||||
armor = *inv.unequipItem(armor);
|
||||
}
|
||||
|
||||
if (ptr == MWMechanics::getPlayer())
|
||||
|
@ -984,15 +984,17 @@ namespace MWClass
|
|||
MWWorld::ContainerStore& Npc::getContainerStore(const MWWorld::Ptr& ptr) const
|
||||
{
|
||||
ensureCustomData(ptr);
|
||||
|
||||
return ptr.getRefData().getCustomData()->asNpcCustomData().mInventoryStore;
|
||||
auto& store = ptr.getRefData().getCustomData()->asNpcCustomData().mInventoryStore;
|
||||
store.setActor(ptr);
|
||||
return store;
|
||||
}
|
||||
|
||||
MWWorld::InventoryStore& Npc::getInventoryStore(const MWWorld::Ptr& ptr) const
|
||||
{
|
||||
ensureCustomData(ptr);
|
||||
|
||||
return ptr.getRefData().getCustomData()->asNpcCustomData().mInventoryStore;
|
||||
auto& store = ptr.getRefData().getCustomData()->asNpcCustomData().mInventoryStore;
|
||||
store.setActor(ptr);
|
||||
return store;
|
||||
}
|
||||
|
||||
const ESM::RefId& Npc::getScript(const MWWorld::ConstPtr& ptr) const
|
||||
|
@ -1172,7 +1174,7 @@ namespace MWClass
|
|||
MWMechanics::CastSpell cast(actor, actor);
|
||||
const ESM::RefId& recordId = consumable.getCellRef().getRefId();
|
||||
MWBase::Environment::get().getLuaManager()->itemConsumed(consumable, actor);
|
||||
actor.getClass().getContainerStore(actor).remove(consumable, 1, actor);
|
||||
actor.getClass().getContainerStore(actor).remove(consumable, 1);
|
||||
return cast.cast(recordId);
|
||||
}
|
||||
|
||||
|
|
|
@ -571,8 +571,8 @@ namespace MWDialogue
|
|||
|
||||
if (gold)
|
||||
{
|
||||
player.getClass().getContainerStore(player).remove(MWWorld::ContainerStore::sGoldId, gold, player);
|
||||
mActor.getClass().getContainerStore(mActor).add(MWWorld::ContainerStore::sGoldId, gold, mActor);
|
||||
player.getClass().getContainerStore(player).remove(MWWorld::ContainerStore::sGoldId, gold);
|
||||
mActor.getClass().getContainerStore(mActor).add(MWWorld::ContainerStore::sGoldId, gold);
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
@ -211,7 +211,7 @@ namespace MWGui
|
|||
if (invStore.isEquipped(item.mBase) == false)
|
||||
continue;
|
||||
|
||||
invStore.unequipItem(item.mBase, mPtr);
|
||||
invStore.unequipItem(item.mBase);
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
@ -105,7 +105,7 @@ namespace MWGui
|
|||
MWWorld::ContainerStore& store = source.first.getClass().getContainerStore(source.first);
|
||||
if (item.mBase.getContainerStore() == &store)
|
||||
throw std::runtime_error("Item to copy needs to be from a different container!");
|
||||
return *store.add(item.mBase, count, source.first, allowAutoEquip);
|
||||
return *store.add(item.mBase, count, allowAutoEquip);
|
||||
}
|
||||
|
||||
void ContainerItemModel::removeItem(const ItemStack& item, size_t count)
|
||||
|
@ -125,7 +125,7 @@ namespace MWGui
|
|||
if (quantity < 0 && mTrading)
|
||||
toRemove += quantity;
|
||||
else
|
||||
toRemove -= store.remove(*it, toRemove, source.first);
|
||||
toRemove -= store.remove(*it, toRemove);
|
||||
if (toRemove <= 0)
|
||||
return;
|
||||
}
|
||||
|
|
|
@ -50,7 +50,7 @@ namespace MWGui
|
|||
{
|
||||
if (item.mBase.getContainerStore() == &mActor.getClass().getContainerStore(mActor))
|
||||
throw std::runtime_error("Item to copy needs to be from a different container!");
|
||||
return *mActor.getClass().getContainerStore(mActor).add(item.mBase, count, mActor, allowAutoEquip);
|
||||
return *mActor.getClass().getContainerStore(mActor).add(item.mBase, count, allowAutoEquip);
|
||||
}
|
||||
|
||||
void InventoryItemModel::removeItem(const ItemStack& item, size_t count)
|
||||
|
@ -60,12 +60,12 @@ namespace MWGui
|
|||
if (mActor.getClass().hasInventoryStore(mActor))
|
||||
{
|
||||
MWWorld::InventoryStore& store = mActor.getClass().getInventoryStore(mActor);
|
||||
removed = store.remove(item.mBase, count, mActor, true);
|
||||
removed = store.remove(item.mBase, count, true);
|
||||
}
|
||||
else
|
||||
{
|
||||
MWWorld::ContainerStore& store = mActor.getClass().getContainerStore(mActor);
|
||||
removed = store.remove(item.mBase, count, mActor);
|
||||
removed = store.remove(item.mBase, count);
|
||||
}
|
||||
|
||||
std::stringstream error;
|
||||
|
|
|
@ -322,7 +322,7 @@ namespace MWGui
|
|||
if (item.mType == ItemStack::Type_Equipped)
|
||||
{
|
||||
MWWorld::InventoryStore& invStore = mPtr.getClass().getInventoryStore(mPtr);
|
||||
MWWorld::Ptr newStack = *invStore.unequipItemQuantity(item.mBase, mPtr, count);
|
||||
MWWorld::Ptr newStack = *invStore.unequipItemQuantity(item.mBase, count);
|
||||
|
||||
// The unequipped item was re-stacked. We have to update the index
|
||||
// since the item pointed does not exist anymore.
|
||||
|
@ -743,7 +743,7 @@ namespace MWGui
|
|||
// add to player inventory
|
||||
// can't use ActionTake here because we need an MWWorld::Ptr to the newly inserted object
|
||||
MWWorld::Ptr newObject
|
||||
= *player.getClass().getContainerStore(player).add(object, object.getRefData().getCount(), player);
|
||||
= *player.getClass().getContainerStore(player).add(object, object.getRefData().getCount());
|
||||
|
||||
// remove from world
|
||||
MWBase::Environment::get().getWorld()->deleteObject(object);
|
||||
|
|
|
@ -136,7 +136,7 @@ namespace MWGui
|
|||
|
||||
MWBase::Environment::get().getWindowManager()->playSound(ESM::RefId::stringRefId("Repair"));
|
||||
|
||||
player.getClass().getContainerStore(player).remove(MWWorld::ContainerStore::sGoldId, price, player);
|
||||
player.getClass().getContainerStore(player).remove(MWWorld::ContainerStore::sGoldId, price);
|
||||
|
||||
// add gold to NPC trading gold pool
|
||||
MWMechanics::CreatureStats& actorStats = mActor.getClass().getCreatureStats(mActor);
|
||||
|
|
|
@ -444,7 +444,7 @@ namespace MWGui
|
|||
}
|
||||
else if (key->type == Type_HandToHand)
|
||||
{
|
||||
store.unequipSlot(MWWorld::InventoryStore::Slot_CarriedRight, player);
|
||||
store.unequipSlot(MWWorld::InventoryStore::Slot_CarriedRight);
|
||||
MWBase::Environment::get().getWorld()->getPlayer().setDrawState(MWMechanics::DrawState::Weapon);
|
||||
}
|
||||
}
|
||||
|
|
|
@ -152,7 +152,7 @@ namespace MWGui
|
|||
MWMechanics::CreatureStats& stats = player.getClass().getCreatureStats(player);
|
||||
MWMechanics::Spells& spells = stats.getSpells();
|
||||
spells.add(mSpellsWidgetMap.find(_sender)->second);
|
||||
player.getClass().getContainerStore(player).remove(MWWorld::ContainerStore::sGoldId, price, player);
|
||||
player.getClass().getContainerStore(player).remove(MWWorld::ContainerStore::sGoldId, price);
|
||||
|
||||
// add gold to NPC trading gold pool
|
||||
MWMechanics::CreatureStats& npcStats = mPtr.getClass().getCreatureStats(mPtr);
|
||||
|
|
|
@ -408,7 +408,7 @@ namespace MWGui
|
|||
|
||||
mSpell.mName = mNameEdit->getCaption();
|
||||
|
||||
player.getClass().getContainerStore(player).remove(MWWorld::ContainerStore::sGoldId, price, player);
|
||||
player.getClass().getContainerStore(player).remove(MWWorld::ContainerStore::sGoldId, price);
|
||||
|
||||
// add gold to NPC trading gold pool
|
||||
MWMechanics::CreatureStats& npcStats = mPtr.getClass().getCreatureStats(mPtr);
|
||||
|
|
|
@ -259,11 +259,11 @@ namespace MWGui
|
|||
|
||||
if (amount > 0)
|
||||
{
|
||||
store.add(MWWorld::ContainerStore::sGoldId, amount, actor);
|
||||
store.add(MWWorld::ContainerStore::sGoldId, amount);
|
||||
}
|
||||
else
|
||||
{
|
||||
store.remove(MWWorld::ContainerStore::sGoldId, -amount, actor);
|
||||
store.remove(MWWorld::ContainerStore::sGoldId, -amount);
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
@ -176,7 +176,7 @@ namespace MWGui
|
|||
pcStats.increaseSkill(skillId, *class_, true);
|
||||
|
||||
// remove gold
|
||||
player.getClass().getContainerStore(player).remove(MWWorld::ContainerStore::sGoldId, price, player);
|
||||
player.getClass().getContainerStore(player).remove(MWWorld::ContainerStore::sGoldId, price);
|
||||
|
||||
// add gold to NPC trading gold pool
|
||||
MWMechanics::NpcStats& npcStats = mPtr.getClass().getNpcStats(mPtr);
|
||||
|
|
|
@ -166,7 +166,7 @@ namespace MWGui
|
|||
// Interior cell -> mages guild transport
|
||||
MWBase::Environment::get().getWindowManager()->playSound(ESM::RefId::stringRefId("mysticism cast"));
|
||||
|
||||
player.getClass().getContainerStore(player).remove(MWWorld::ContainerStore::sGoldId, price, player);
|
||||
player.getClass().getContainerStore(player).remove(MWWorld::ContainerStore::sGoldId, price);
|
||||
|
||||
// add gold to NPC trading gold pool
|
||||
MWMechanics::CreatureStats& npcStats = mPtr.getClass().getCreatureStats(mPtr);
|
||||
|
|
|
@ -75,6 +75,8 @@ namespace MWLua
|
|||
const CellT& cell, sol::optional<sol::table> type) {
|
||||
ObjectIdList res = std::make_shared<std::vector<ObjectId>>();
|
||||
auto visitor = [&](const MWWorld::Ptr& ptr) {
|
||||
if (ptr.getRefData().isDeleted())
|
||||
return true;
|
||||
MWBase::Environment::get().getWorldModel()->registerPtr(ptr);
|
||||
if (getLiveCellRefType(ptr.mRef) == ptr.getType())
|
||||
res->push_back(getId(ptr));
|
||||
|
|
|
@ -23,6 +23,7 @@ namespace MWLua
|
|||
LocalScripts(LuaUtil::LuaState* lua, const LObject& obj);
|
||||
|
||||
MWBase::LuaManager::ActorControls* getActorControls() { return &mData.mControls; }
|
||||
const MWWorld::Ptr& getPtr() const { return mData.ptr(); }
|
||||
|
||||
struct SelfObject : public LObject
|
||||
{
|
||||
|
|
|
@ -7,7 +7,10 @@
|
|||
|
||||
#include "../mwbase/environment.hpp"
|
||||
#include "../mwbase/statemanager.hpp"
|
||||
#include "../mwworld/class.hpp"
|
||||
#include "../mwworld/esmstore.hpp"
|
||||
#include "../mwworld/manualref.hpp"
|
||||
#include "../mwworld/scene.hpp"
|
||||
#include "../mwworld/store.hpp"
|
||||
|
||||
#include "eventqueue.hpp"
|
||||
|
@ -48,7 +51,7 @@ namespace MWLua
|
|||
{
|
||||
auto* lua = context.mLua;
|
||||
sol::table api(lua->sol(), sol::create);
|
||||
api["API_REVISION"] = 32;
|
||||
api["API_REVISION"] = 33;
|
||||
api["quit"] = [lua]() {
|
||||
Log(Debug::Warning) << "Quit requested by a Lua script.\n" << lua->debugTraceback();
|
||||
MWBase::Environment::get().getStateManager()->requestQuit();
|
||||
|
@ -83,7 +86,17 @@ namespace MWLua
|
|||
api["getExteriorCell"]
|
||||
= [](int x, int y) { return GCell{ MWBase::Environment::get().getWorldModel()->getExterior(x, y) }; };
|
||||
api["activeActors"] = GObjectList{ worldView->getActorsInScene() };
|
||||
// TODO: add world.placeNewObject(recordId, cell, pos, [rot])
|
||||
api["createObject"] = [](std::string_view recordId, sol::optional<int> count) -> GObject {
|
||||
// Doesn't matter which cell to use because the new object will be in disabled state.
|
||||
MWWorld::CellStore* cell = MWBase::Environment::get().getWorldScene()->getCurrentCell();
|
||||
|
||||
MWWorld::ManualRef mref(
|
||||
MWBase::Environment::get().getWorld()->getStore(), ESM::RefId::stringRefId(recordId));
|
||||
const MWWorld::Ptr& ptr = mref.getPtr();
|
||||
ptr.getRefData().disable();
|
||||
MWWorld::Ptr newPtr = ptr.getClass().copyToCell(ptr, *cell, count.value_or(1));
|
||||
return GObject(getId(newPtr));
|
||||
};
|
||||
return LuaUtil::makeReadOnly(api);
|
||||
}
|
||||
|
||||
|
|
|
@ -154,6 +154,9 @@ namespace MWLua
|
|||
|
||||
mWorldView.update();
|
||||
|
||||
std::erase_if(mActiveLocalScripts,
|
||||
[](const LocalScripts* l) { return l->getPtr().isEmpty() || l->getPtr().getRefData().isDeleted(); });
|
||||
|
||||
mGlobalScripts.statsNextFrame();
|
||||
for (LocalScripts* scripts : mActiveLocalScripts)
|
||||
scripts->statsNextFrame();
|
||||
|
|
|
@ -20,6 +20,8 @@ namespace MWLua
|
|||
std::string ptrToString(const MWWorld::Ptr& ptr)
|
||||
{
|
||||
std::string res = "object";
|
||||
if (ptr.getRefData().isDeleted())
|
||||
res = "deleted object";
|
||||
res.append(idToString(getId(ptr)));
|
||||
res.append(" (");
|
||||
res.append(getLuaObjectTypeName(ptr));
|
||||
|
|
|
@ -7,6 +7,7 @@
|
|||
#include "../mwworld/class.hpp"
|
||||
#include "../mwworld/containerstore.hpp"
|
||||
#include "../mwworld/player.hpp"
|
||||
#include "../mwworld/scene.hpp"
|
||||
|
||||
#include "../mwmechanics/creaturestats.hpp"
|
||||
|
||||
|
@ -87,6 +88,8 @@ namespace MWLua
|
|||
{
|
||||
MWWorld::Ptr newObj = world->moveObject(obj, cell, mPos);
|
||||
world->rotateObject(newObj, mRot);
|
||||
if (!newObj.getRefData().isEnabled())
|
||||
world->enable(newObj);
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -198,6 +201,32 @@ namespace MWLua
|
|||
context.mLuaManager->addAction(std::make_unique<ActivateAction>(context.mLua, o.id(), actor.id()));
|
||||
};
|
||||
|
||||
auto isEnabled = [](const ObjectT& o) { return o.ptr().getRefData().isEnabled(); };
|
||||
auto setEnabled = [context](const GObject& object, bool enable) {
|
||||
if (enable && object.ptr().getRefData().isDeleted())
|
||||
throw std::runtime_error("Object is removed");
|
||||
context.mLuaManager->addAction([object, enable] {
|
||||
if (object.ptr().isInCell())
|
||||
{
|
||||
if (enable)
|
||||
MWBase::Environment::get().getWorld()->enable(object.ptr());
|
||||
else
|
||||
MWBase::Environment::get().getWorld()->disable(object.ptr());
|
||||
}
|
||||
else
|
||||
{
|
||||
if (enable)
|
||||
object.ptr().getRefData().enable();
|
||||
else
|
||||
throw std::runtime_error("Objects in containers can't be disabled");
|
||||
}
|
||||
});
|
||||
};
|
||||
if constexpr (std::is_same_v<ObjectT, GObject>)
|
||||
objectT["enabled"] = sol::property(isEnabled, setEnabled);
|
||||
else
|
||||
objectT["enabled"] = sol::readonly_property(isEnabled);
|
||||
|
||||
if constexpr (std::is_same_v<ObjectT, GObject>)
|
||||
{ // Only for global scripts
|
||||
objectT["addScript"] = [context](const GObject& object, std::string_view path, sol::object initData) {
|
||||
|
@ -243,11 +272,74 @@ namespace MWLua
|
|||
localScripts->removeScript(*scriptId);
|
||||
};
|
||||
|
||||
objectT["teleport"] = [context](const GObject& object, std::string_view cell, const osg::Vec3f& pos,
|
||||
const sol::optional<osg::Vec3f>& optRot) {
|
||||
auto removeFn = [context](const GObject& object, int countToRemove) {
|
||||
MWWorld::Ptr ptr = object.ptr();
|
||||
int currentCount = ptr.getRefData().getCount();
|
||||
if (countToRemove <= 0 || countToRemove > currentCount)
|
||||
throw std::runtime_error("Can't remove " + std::to_string(countToRemove) + " of "
|
||||
+ std::to_string(currentCount) + " items");
|
||||
ptr.getRefData().setCount(currentCount - countToRemove); // Immediately change count
|
||||
if (ptr.getContainerStore() || currentCount == countToRemove)
|
||||
{
|
||||
// Delayed action to trigger side effects
|
||||
context.mLuaManager->addAction([object, countToRemove] {
|
||||
MWWorld::Ptr ptr = object.ptr();
|
||||
// Restore original count
|
||||
ptr.getRefData().setCount(ptr.getRefData().getCount() + countToRemove);
|
||||
// And now remove properly
|
||||
if (ptr.getContainerStore())
|
||||
ptr.getContainerStore()->remove(ptr, countToRemove);
|
||||
else
|
||||
{
|
||||
MWBase::Environment::get().getWorld()->disable(object.ptr());
|
||||
MWBase::Environment::get().getWorld()->deleteObject(ptr);
|
||||
}
|
||||
});
|
||||
}
|
||||
};
|
||||
objectT["remove"] = [removeFn](const GObject& object, sol::optional<int> count) {
|
||||
removeFn(object, count.value_or(object.ptr().getRefData().getCount()));
|
||||
};
|
||||
objectT["split"] = [removeFn](const GObject& object, int count) -> GObject {
|
||||
removeFn(object, count);
|
||||
|
||||
// Doesn't matter which cell to use because the new instance will be in disabled state.
|
||||
MWWorld::CellStore* cell = MWBase::Environment::get().getWorldScene()->getCurrentCell();
|
||||
|
||||
const MWWorld::Ptr& ptr = object.ptr();
|
||||
MWWorld::Ptr splitted = ptr.getClass().copyToCell(ptr, *cell, count);
|
||||
splitted.getRefData().disable();
|
||||
return GObject(getId(splitted));
|
||||
};
|
||||
objectT["moveInto"] = [removeFn, context](const GObject& object, const Inventory<GObject>& inventory) {
|
||||
// Currently moving to or from containers makes a copy and removes the original.
|
||||
// TODO(#6148): actually move rather than copy and preserve RefNum
|
||||
int count = object.ptr().getRefData().getCount();
|
||||
removeFn(object, count);
|
||||
context.mLuaManager->addAction([item = object, count, cont = inventory.mObj] {
|
||||
auto& refData = item.ptr().getRefData();
|
||||
refData.setCount(count); // temporarily undo removal to run ContainerStore::add
|
||||
cont.ptr().getClass().getContainerStore(cont.ptr()).add(item.ptr(), count, false);
|
||||
refData.setCount(0);
|
||||
});
|
||||
};
|
||||
objectT["teleport"] = [removeFn, context](const GObject& object, std::string_view cell,
|
||||
const osg::Vec3f& pos, const sol::optional<osg::Vec3f>& optRot) {
|
||||
MWWorld::Ptr ptr = object.ptr();
|
||||
if (ptr.getRefData().isDeleted())
|
||||
throw std::runtime_error("Object is removed");
|
||||
if (ptr.getContainerStore())
|
||||
{
|
||||
// Currently moving to or from containers makes a copy and removes the original.
|
||||
// TODO(#6148): actually move rather than copy and preserve RefNum
|
||||
auto* cellStore = MWBase::Environment::get().getWorldModel()->getCellByPosition(pos, cell);
|
||||
MWWorld::Ptr newPtr = ptr.getClass().copyToCell(ptr, *cellStore, ptr.getRefData().getCount());
|
||||
newPtr.getRefData().disable();
|
||||
removeFn(object, ptr.getRefData().getCount());
|
||||
ptr = newPtr;
|
||||
}
|
||||
osg::Vec3f rot = optRot ? *optRot : ptr.getRefData().getPosition().asRotationVec3();
|
||||
auto action = std::make_unique<TeleportAction>(context.mLua, object.id(), cell, pos, rot);
|
||||
auto action = std::make_unique<TeleportAction>(context.mLua, getId(ptr), cell, pos, rot);
|
||||
if (ptr == MWBase::Environment::get().getWorld()->getPlayerPtr())
|
||||
context.mLuaManager->addTeleportPlayerAction(std::move(action));
|
||||
else
|
||||
|
@ -335,24 +427,40 @@ namespace MWLua
|
|||
return ObjectList<ObjectT>{ list };
|
||||
};
|
||||
|
||||
inventoryT["countOf"] = [](const InventoryT& inventory, const std::string& recordId) {
|
||||
inventoryT["countOf"] = [](const InventoryT& inventory, std::string_view recordId) {
|
||||
const MWWorld::Ptr& ptr = inventory.mObj.ptr();
|
||||
MWWorld::ContainerStore& store = ptr.getClass().getContainerStore(ptr);
|
||||
return store.count(ESM::RefId::stringRefId(recordId));
|
||||
};
|
||||
|
||||
if constexpr (std::is_same_v<ObjectT, GObject>)
|
||||
{ // Only for global scripts
|
||||
// TODO
|
||||
// obj.inventory:drop(obj2, [count])
|
||||
// obj.inventory:drop(recordId, [count])
|
||||
// obj.inventory:addNew(recordId, [count])
|
||||
// obj.inventory:remove(obj/recordId, [count])
|
||||
/*objectT["moveInto"] = [](const GObject& obj, const InventoryT& inventory) {};
|
||||
inventoryT["drop"] = [](const InventoryT& inventory) {};
|
||||
inventoryT["addNew"] = [](const InventoryT& inventory) {};
|
||||
inventoryT["remove"] = [](const InventoryT& inventory) {};*/
|
||||
}
|
||||
inventoryT["find"] = [](const InventoryT& inventory, std::string_view recordId) -> sol::optional<ObjectT> {
|
||||
const MWWorld::Ptr& ptr = inventory.mObj.ptr();
|
||||
MWWorld::ContainerStore& store = ptr.getClass().getContainerStore(ptr);
|
||||
auto itemId = ESM::RefId::stringRefId(recordId);
|
||||
for (const MWWorld::Ptr& item : store)
|
||||
{
|
||||
if (item.getCellRef().getRefId() == itemId)
|
||||
{
|
||||
MWBase::Environment::get().getWorldModel()->registerPtr(item);
|
||||
return ObjectT(getId(item));
|
||||
}
|
||||
}
|
||||
return sol::nullopt;
|
||||
};
|
||||
inventoryT["findAll"] = [](const InventoryT& inventory, std::string_view recordId) {
|
||||
const MWWorld::Ptr& ptr = inventory.mObj.ptr();
|
||||
MWWorld::ContainerStore& store = ptr.getClass().getContainerStore(ptr);
|
||||
auto itemId = ESM::RefId::stringRefId(recordId);
|
||||
ObjectIdList list = std::make_shared<std::vector<ObjectId>>();
|
||||
for (const MWWorld::Ptr& item : store)
|
||||
{
|
||||
if (item.getCellRef().getRefId() == itemId)
|
||||
{
|
||||
MWBase::Environment::get().getWorldModel()->registerPtr(item);
|
||||
list->push_back(getId(item));
|
||||
}
|
||||
}
|
||||
return ObjectList<ObjectT>{ list };
|
||||
};
|
||||
}
|
||||
|
||||
template <class ObjectT>
|
||||
|
|
|
@ -39,7 +39,7 @@ namespace MWLua
|
|||
std::fill(usedSlots.begin(), usedSlots.end(), false);
|
||||
|
||||
static constexpr int anySlot = -1;
|
||||
auto tryEquipToSlot = [&actor, &store, &usedSlots](int slot, const Item& item) -> bool {
|
||||
auto tryEquipToSlot = [&store, &usedSlots](int slot, const Item& item) -> bool {
|
||||
auto old_it = slot != anySlot ? store.getSlot(slot) : store.end();
|
||||
MWWorld::Ptr itemPtr;
|
||||
if (std::holds_alternative<ObjectId>(item))
|
||||
|
@ -88,7 +88,7 @@ namespace MWLua
|
|||
if (it == store.end()) // should never happen
|
||||
throw std::logic_error("Item not found in container");
|
||||
|
||||
store.equip(slot, it, actor);
|
||||
store.equip(slot, it);
|
||||
return requestedSlotIsAllowed; // return true if equipped to requested slot and false if slot was
|
||||
// changed
|
||||
};
|
||||
|
@ -100,7 +100,7 @@ namespace MWLua
|
|||
if (new_it == mEquipment.end())
|
||||
{
|
||||
if (old_it != store.end())
|
||||
store.unequipSlot(slot, actor);
|
||||
store.unequipSlot(slot);
|
||||
continue;
|
||||
}
|
||||
if (tryEquipToSlot(slot, new_it->second))
|
||||
|
|
|
@ -199,7 +199,7 @@ namespace
|
|||
continue;
|
||||
|
||||
// Set the soul on just one of the gems, not the whole stack
|
||||
gem->getContainerStore()->unstack(*gem, caster);
|
||||
gem->getContainerStore()->unstack(*gem);
|
||||
gem->getCellRef().setSoul(creature.getCellRef().getRefId());
|
||||
|
||||
// Restack the gem with other gems with the same soul
|
||||
|
@ -1021,14 +1021,14 @@ namespace MWMechanics
|
|||
{
|
||||
// For non-hostile NPCs, unequip whatever is in the left slot in favor of a light.
|
||||
if (heldIter != inventoryStore.end() && heldIter->getType() != ESM::Light::sRecordId)
|
||||
inventoryStore.unequipItem(*heldIter, ptr);
|
||||
inventoryStore.unequipItem(*heldIter);
|
||||
}
|
||||
else if (heldIter == inventoryStore.end() || heldIter->getType() == ESM::Light::sRecordId)
|
||||
{
|
||||
// For hostile NPCs, see if they have anything better to equip first
|
||||
auto shield = inventoryStore.getPreferredShield(ptr);
|
||||
auto shield = inventoryStore.getPreferredShield();
|
||||
if (shield != inventoryStore.end())
|
||||
inventoryStore.equip(MWWorld::InventoryStore::Slot_CarriedLeft, shield, ptr);
|
||||
inventoryStore.equip(MWWorld::InventoryStore::Slot_CarriedLeft, shield);
|
||||
}
|
||||
|
||||
heldIter = inventoryStore.getSlot(MWWorld::InventoryStore::Slot_CarriedLeft);
|
||||
|
@ -1036,7 +1036,7 @@ namespace MWMechanics
|
|||
// If we have a torch and can equip it, then equip it now.
|
||||
if (heldIter == inventoryStore.end())
|
||||
{
|
||||
inventoryStore.equip(MWWorld::InventoryStore::Slot_CarriedLeft, torchIter, ptr);
|
||||
inventoryStore.equip(MWWorld::InventoryStore::Slot_CarriedLeft, torchIter);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -1046,7 +1046,7 @@ namespace MWMechanics
|
|||
{
|
||||
// At day, unequip lights and auto equip shields or other suitable items
|
||||
// (Note: autoEquip will ignore lights)
|
||||
inventoryStore.autoEquip(ptr);
|
||||
inventoryStore.autoEquip();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -1069,7 +1069,7 @@ namespace MWMechanics
|
|||
timeRemaining -= duration;
|
||||
if (timeRemaining <= 0.f)
|
||||
{
|
||||
inventoryStore.remove(*heldIter, 1, ptr); // remove it
|
||||
inventoryStore.remove(*heldIter, 1); // remove it
|
||||
return;
|
||||
}
|
||||
|
||||
|
@ -1080,7 +1080,7 @@ namespace MWMechanics
|
|||
// Both NPC and player lights extinguish in water.
|
||||
if (world->isSwimming(ptr))
|
||||
{
|
||||
inventoryStore.remove(*heldIter, 1, ptr); // remove it
|
||||
inventoryStore.remove(*heldIter, 1); // remove it
|
||||
|
||||
// ...But, only the player makes a sound.
|
||||
if (isPlayer)
|
||||
|
|
|
@ -106,8 +106,7 @@ namespace MWMechanics
|
|||
if (actor.getClass().hasInventoryStore(actor))
|
||||
{
|
||||
if (mWeapon.isEmpty())
|
||||
actor.getClass().getInventoryStore(actor).unequipSlot(
|
||||
MWWorld::InventoryStore::Slot_CarriedRight, actor);
|
||||
actor.getClass().getInventoryStore(actor).unequipSlot(MWWorld::InventoryStore::Slot_CarriedRight);
|
||||
else
|
||||
{
|
||||
MWWorld::ActionEquip equip(mWeapon);
|
||||
|
|
|
@ -275,7 +275,7 @@ void MWMechanics::Alchemy::removeIngredients()
|
|||
for (TIngredientsContainer::iterator iter(mIngredients.begin()); iter != mIngredients.end(); ++iter)
|
||||
if (!iter->isEmpty())
|
||||
{
|
||||
iter->getContainerStore()->remove(*iter, 1, mAlchemist);
|
||||
iter->getContainerStore()->remove(*iter, 1);
|
||||
|
||||
if (iter->getRefData().getCount() < 1)
|
||||
*iter = MWWorld::Ptr();
|
||||
|
@ -317,7 +317,7 @@ void MWMechanics::Alchemy::addPotion(const std::string& name)
|
|||
if (!record)
|
||||
record = MWBase::Environment::get().getWorld()->createRecord(newRecord);
|
||||
|
||||
mAlchemist.getClass().getContainerStore(mAlchemist).add(record->mId, 1, mAlchemist);
|
||||
mAlchemist.getClass().getContainerStore(mAlchemist).add(record->mId, 1);
|
||||
}
|
||||
|
||||
void MWMechanics::Alchemy::increaseSkill()
|
||||
|
|
|
@ -140,7 +140,7 @@ namespace MWMechanics
|
|||
shieldhealth -= std::min(shieldhealth, int(damage));
|
||||
shield->getCellRef().setCharge(shieldhealth);
|
||||
if (shieldhealth == 0)
|
||||
inv.unequipItem(*shield, blocker);
|
||||
inv.unequipItem(*shield);
|
||||
// Reduce blocker fatigue
|
||||
static const float fFatigueBlockBase = gmst.find("fFatigueBlockBase")->mValue.getFloat();
|
||||
static const float fFatigueBlockMult = gmst.find("fFatigueBlockMult")->mValue.getFloat();
|
||||
|
@ -285,7 +285,7 @@ namespace MWMechanics
|
|||
static const float fProjectileThrownStoreChance
|
||||
= gmst.find("fProjectileThrownStoreChance")->mValue.getFloat();
|
||||
if (Misc::Rng::rollProbability(world->getPrng()) < fProjectileThrownStoreChance / 100.f)
|
||||
victim.getClass().getContainerStore(victim).add(projectile, 1, victim);
|
||||
victim.getClass().getContainerStore(victim).add(projectile, 1);
|
||||
}
|
||||
|
||||
victim.getClass().onHit(victim, damage, true, projectile, attacker, hitPosition, true);
|
||||
|
@ -422,7 +422,7 @@ namespace MWMechanics
|
|||
|
||||
// Weapon broken? unequip it
|
||||
if (weaphealth == 0)
|
||||
weapon = *attacker.getClass().getInventoryStore(attacker).unequipItem(weapon, attacker);
|
||||
weapon = *attacker.getClass().getInventoryStore(attacker).unequipItem(weapon);
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
@ -70,12 +70,12 @@ namespace MWMechanics
|
|||
enchantment.mData.mType = mCastStyle;
|
||||
enchantment.mData.mCost = getBaseCastCost();
|
||||
|
||||
store.remove(mSoulGemPtr, 1, player);
|
||||
store.remove(mSoulGemPtr, 1);
|
||||
|
||||
// Exception for Azura Star, new one will be added after enchanting
|
||||
auto azurasStarId = ESM::RefId::stringRefId("Misc_SoulGem_Azura");
|
||||
if (mSoulGemPtr.get<ESM::Miscellaneous>()->mBase->mId == azurasStarId)
|
||||
store.add(azurasStarId, 1, player);
|
||||
store.add(azurasStarId, 1);
|
||||
|
||||
if (mSelfEnchanting)
|
||||
{
|
||||
|
@ -105,8 +105,8 @@ namespace MWMechanics
|
|||
= mOldItemPtr.getClass().applyEnchantment(mOldItemPtr, enchantmentPtr->mId, getGemCharge(), mNewItemName);
|
||||
|
||||
// Add the new item to player inventory and remove the old one
|
||||
store.remove(mOldItemPtr, count, player);
|
||||
store.add(newItemId, count, player);
|
||||
store.remove(mOldItemPtr, count);
|
||||
store.add(newItemId, count);
|
||||
|
||||
if (!mSelfEnchanting)
|
||||
payForEnchantment();
|
||||
|
@ -399,7 +399,7 @@ namespace MWMechanics
|
|||
const MWWorld::Ptr& player = getPlayer();
|
||||
MWWorld::ContainerStore& store = player.getClass().getContainerStore(player);
|
||||
|
||||
store.remove(MWWorld::ContainerStore::sGoldId, getEnchantPrice(), player);
|
||||
store.remove(MWWorld::ContainerStore::sGoldId, getEnchantPrice());
|
||||
|
||||
// add gold to NPC trading gold pool
|
||||
CreatureStats& enchanterStats = mEnchanter.getClass().getCreatureStats(mEnchanter);
|
||||
|
|
|
@ -267,8 +267,8 @@ namespace MWMechanics
|
|||
// equippable
|
||||
MWWorld::InventoryStore& invStore = ptr.getClass().getInventoryStore(ptr);
|
||||
for (int i = 0; i < MWWorld::InventoryStore::Slots; ++i)
|
||||
invStore.unequipAll(ptr);
|
||||
invStore.autoEquip(ptr);
|
||||
invStore.unequipAll();
|
||||
invStore.autoEquip();
|
||||
}
|
||||
|
||||
MechanicsManager::MechanicsManager()
|
||||
|
@ -1033,8 +1033,8 @@ namespace MWMechanics
|
|||
MWWorld::ContainerStore& store = player.getClass().getContainerStore(player);
|
||||
|
||||
// move items from player to owner and report about theft
|
||||
victim.getClass().getContainerStore(victim).add(item, toRemove, victim);
|
||||
store.remove(item, toRemove, player);
|
||||
victim.getClass().getContainerStore(victim).add(item, toRemove);
|
||||
store.remove(item, toRemove);
|
||||
commitCrime(
|
||||
player, victim, OT_Theft, item.getCellRef().getFaction(), item.getClass().getValue(item) * toRemove);
|
||||
}
|
||||
|
@ -1063,8 +1063,8 @@ namespace MWMechanics
|
|||
|
||||
int toMove = it->getRefData().getCount() - itemCount;
|
||||
|
||||
containerStore.add(*it, toMove, targetContainer);
|
||||
store.remove(*it, toMove, player);
|
||||
containerStore.add(*it, toMove);
|
||||
store.remove(*it, toMove);
|
||||
}
|
||||
// TODO: unhardcode the locklevel
|
||||
targetContainer.getCellRef().lock(50);
|
||||
|
@ -1836,14 +1836,14 @@ namespace MWMechanics
|
|||
|
||||
if (werewolf)
|
||||
{
|
||||
inv.unequipAll(actor);
|
||||
inv.unequipAll();
|
||||
inv.equip(MWWorld::InventoryStore::Slot_Robe,
|
||||
inv.ContainerStore::add(ESM::RefId::stringRefId("werewolfrobe"), 1, actor), actor);
|
||||
inv.ContainerStore::add(ESM::RefId::stringRefId("werewolfrobe"), 1));
|
||||
}
|
||||
else
|
||||
{
|
||||
inv.unequipSlot(MWWorld::InventoryStore::Slot_Robe, actor);
|
||||
inv.ContainerStore::remove(ESM::RefId::stringRefId("werewolfrobe"), 1, actor);
|
||||
inv.unequipSlot(MWWorld::InventoryStore::Slot_Robe);
|
||||
inv.ContainerStore::remove(ESM::RefId::stringRefId("werewolfrobe"), 1);
|
||||
}
|
||||
|
||||
if (actor == player->getPlayer())
|
||||
|
|
|
@ -83,7 +83,7 @@ namespace MWMechanics
|
|||
}
|
||||
|
||||
player.getClass().skillUsageSucceeded(player, ESM::Skill::Enchant, 0);
|
||||
gem.getContainerStore()->remove(gem, 1, player);
|
||||
gem.getContainerStore()->remove(gem, 1);
|
||||
|
||||
if (gem.getRefData().getCount() == 0)
|
||||
{
|
||||
|
@ -100,7 +100,7 @@ namespace MWMechanics
|
|||
const ESM::RefId soulGemAzura = ESM::RefId::stringRefId("Misc_SoulGem_Azura");
|
||||
// special case: readd Azura's Star
|
||||
if (gem.get<ESM::Miscellaneous>()->mBase->mId == soulGemAzura)
|
||||
player.getClass().getContainerStore(player).add(soulGemAzura, 1, player);
|
||||
player.getClass().getContainerStore(player).add(soulGemAzura, 1);
|
||||
}
|
||||
|
||||
return true;
|
||||
|
|
|
@ -23,7 +23,7 @@ namespace MWMechanics
|
|||
MWWorld::LiveCellRef<ESM::Repair>* ref = mTool.get<ESM::Repair>();
|
||||
|
||||
// unstack tool if required
|
||||
player.getClass().getContainerStore(player).unstack(mTool, player);
|
||||
player.getClass().getContainerStore(player).unstack(mTool);
|
||||
|
||||
// reduce number of uses left
|
||||
int uses = mTool.getClass().getItemHealth(mTool);
|
||||
|
@ -85,7 +85,7 @@ namespace MWMechanics
|
|||
{
|
||||
MWWorld::ContainerStore& store = player.getClass().getContainerStore(player);
|
||||
|
||||
store.remove(mTool, 1, player);
|
||||
store.remove(mTool, 1);
|
||||
|
||||
std::string message = MWBase::Environment::get()
|
||||
.getWorld()
|
||||
|
|
|
@ -72,7 +72,7 @@ namespace MWMechanics
|
|||
|
||||
lockpick.getCellRef().setCharge(--uses);
|
||||
if (!uses)
|
||||
lockpick.getContainerStore()->remove(lockpick, 1, mActor);
|
||||
lockpick.getContainerStore()->remove(lockpick, 1);
|
||||
}
|
||||
|
||||
void Security::probeTrap(const MWWorld::Ptr& trap, const MWWorld::Ptr& probe, std::string_view& resultMessage,
|
||||
|
@ -124,7 +124,7 @@ namespace MWMechanics
|
|||
|
||||
probe.getCellRef().setCharge(--uses);
|
||||
if (!uses)
|
||||
probe.getContainerStore()->remove(probe, 1, mActor);
|
||||
probe.getContainerStore()->remove(probe, 1);
|
||||
}
|
||||
|
||||
}
|
||||
|
|
|
@ -360,7 +360,7 @@ namespace MWMechanics
|
|||
else if (type == ESM::Enchantment::CastOnce)
|
||||
{
|
||||
if (!godmode)
|
||||
item.getContainerStore()->remove(item, 1, mCaster);
|
||||
item.getContainerStore()->remove(item, 1);
|
||||
}
|
||||
else if (type == ESM::Enchantment::WhenStrikes)
|
||||
{
|
||||
|
|
|
@ -151,9 +151,9 @@ namespace
|
|||
{
|
||||
// Will unequip the broken item and try to find a replacement
|
||||
if (ptr != MWMechanics::getPlayer())
|
||||
inv.autoEquip(ptr);
|
||||
inv.autoEquip();
|
||||
else
|
||||
inv.unequipItem(*item, ptr);
|
||||
inv.unequipItem(*item);
|
||||
}
|
||||
|
||||
return true;
|
||||
|
@ -173,7 +173,7 @@ namespace
|
|||
void addBoundItem(const ESM::RefId& itemId, const MWWorld::Ptr& actor)
|
||||
{
|
||||
MWWorld::InventoryStore& store = actor.getClass().getInventoryStore(actor);
|
||||
MWWorld::Ptr boundPtr = *store.MWWorld::ContainerStore::add(itemId, 1, actor);
|
||||
MWWorld::Ptr boundPtr = *store.MWWorld::ContainerStore::add(itemId, 1);
|
||||
|
||||
int slot = getBoundItemSlot(boundPtr);
|
||||
auto prevItem = slot >= 0 ? store.getSlot(slot) : store.end();
|
||||
|
@ -217,9 +217,9 @@ namespace
|
|||
bool wasEquipped = currentItem != store.end() && currentItem->getCellRef().getRefId() == itemId;
|
||||
|
||||
if (wasEquipped)
|
||||
store.remove(*currentItem, 1, actor);
|
||||
store.remove(*currentItem, 1);
|
||||
else
|
||||
store.remove(itemId, 1, actor);
|
||||
store.remove(itemId, 1);
|
||||
|
||||
if (actor != MWMechanics::getPlayer())
|
||||
{
|
||||
|
@ -240,7 +240,7 @@ namespace
|
|||
if (actor.getClass().isNpc() && actor.getClass().getNpcStats(actor).isWerewolf())
|
||||
return;
|
||||
|
||||
actor.getClass().getInventoryStore(actor).autoEquip(actor);
|
||||
actor.getClass().getInventoryStore(actor).autoEquip();
|
||||
|
||||
return;
|
||||
}
|
||||
|
@ -517,7 +517,7 @@ namespace MWMechanics
|
|||
if (target.getClass().hasInventoryStore(target))
|
||||
{
|
||||
auto& store = target.getClass().getInventoryStore(target);
|
||||
store.unequipAll(target);
|
||||
store.unequipAll();
|
||||
}
|
||||
else
|
||||
invalid = true;
|
||||
|
@ -1072,7 +1072,7 @@ namespace MWMechanics
|
|||
break;
|
||||
case ESM::MagicEffect::ExtraSpell:
|
||||
if (magnitudes.get(effect.mEffectId).getMagnitude() <= 0.f)
|
||||
target.getClass().getInventoryStore(target).autoEquip(target);
|
||||
target.getClass().getInventoryStore(target).autoEquip();
|
||||
break;
|
||||
case ESM::MagicEffect::TurnUndead:
|
||||
{
|
||||
|
|
|
@ -52,7 +52,7 @@ namespace MWRender
|
|||
if (animated)
|
||||
addAnimSource(model, model);
|
||||
|
||||
mPtr.getClass().getInventoryStore(mPtr).setInvListener(this, mPtr);
|
||||
mPtr.getClass().getInventoryStore(mPtr).setInvListener(this);
|
||||
|
||||
updateParts();
|
||||
}
|
||||
|
|
|
@ -120,7 +120,7 @@ namespace MWRender
|
|||
|
||||
if (mObjects.emplace(ptr.mRef, anim).second)
|
||||
{
|
||||
ptr.getClass().getInventoryStore(ptr).setInvListener(anim.get(), ptr);
|
||||
ptr.getClass().getInventoryStore(ptr).setInvListener(anim.get());
|
||||
ptr.getClass().getInventoryStore(ptr).setContListener(anim.get());
|
||||
}
|
||||
}
|
||||
|
@ -140,7 +140,7 @@ namespace MWRender
|
|||
if (ptr.getClass().isActor())
|
||||
{
|
||||
if (ptr.getClass().hasInventoryStore(ptr))
|
||||
ptr.getClass().getInventoryStore(ptr).setInvListener(nullptr, ptr);
|
||||
ptr.getClass().getInventoryStore(ptr).setInvListener(nullptr);
|
||||
|
||||
ptr.getClass().getContainerStore(ptr).setContListener(nullptr);
|
||||
}
|
||||
|
@ -163,7 +163,7 @@ namespace MWRender
|
|||
if (ptr.getClass().isActor() && ptr.getRefData().getCustomData())
|
||||
{
|
||||
if (ptr.getClass().hasInventoryStore(ptr))
|
||||
ptr.getClass().getInventoryStore(ptr).setInvListener(nullptr, ptr);
|
||||
ptr.getClass().getInventoryStore(ptr).setInvListener(nullptr);
|
||||
ptr.getClass().getContainerStore(ptr).setContListener(nullptr);
|
||||
}
|
||||
|
||||
|
|
|
@ -140,7 +140,7 @@ namespace MWRender
|
|||
|
||||
showWeapon(false);
|
||||
|
||||
inv.remove(*weapon, 1, actor);
|
||||
inv.remove(*weapon, 1);
|
||||
}
|
||||
else
|
||||
{
|
||||
|
@ -167,7 +167,7 @@ namespace MWRender
|
|||
MWBase::Environment::get().getWorld()->launchProjectile(
|
||||
actor, ammoPtr, launchPos, orient, weaponPtr, speed, attackStrength);
|
||||
|
||||
inv.remove(ammoPtr, 1, actor);
|
||||
inv.remove(ammoPtr, 1);
|
||||
mAmmunition.reset();
|
||||
}
|
||||
}
|
||||
|
|
|
@ -35,23 +35,21 @@
|
|||
|
||||
namespace
|
||||
{
|
||||
void addToStore(
|
||||
const MWWorld::Ptr& itemPtr, int count, MWWorld::Ptr& ptr, MWWorld::ContainerStore& store, bool resolve = true)
|
||||
void addToStore(const MWWorld::Ptr& itemPtr, int count, MWWorld::ContainerStore& store, bool resolve = true)
|
||||
{
|
||||
if (itemPtr.getClass().getScript(itemPtr).empty())
|
||||
{
|
||||
store.add(itemPtr, count, ptr, true, resolve);
|
||||
store.add(itemPtr, count, true, resolve);
|
||||
}
|
||||
else
|
||||
{
|
||||
// Adding just one item per time to make sure there isn't a stack of scripted items
|
||||
for (int i = 0; i < count; i++)
|
||||
store.add(itemPtr, 1, ptr, true, resolve);
|
||||
store.add(itemPtr, 1, true, resolve);
|
||||
}
|
||||
}
|
||||
|
||||
void addRandomToStore(const MWWorld::Ptr& itemPtr, int count, MWWorld::Ptr& owner, MWWorld::ContainerStore& store,
|
||||
bool topLevel = true)
|
||||
void addRandomToStore(const MWWorld::Ptr& itemPtr, int count, MWWorld::ContainerStore& store, bool topLevel = true)
|
||||
{
|
||||
if (itemPtr.getType() == ESM::ItemLevList::sRecordId)
|
||||
{
|
||||
|
@ -60,7 +58,7 @@ namespace
|
|||
if (topLevel && count > 1 && levItemList->mFlags & ESM::ItemLevList::Each)
|
||||
{
|
||||
for (int i = 0; i < count; i++)
|
||||
addRandomToStore(itemPtr, 1, owner, store, true);
|
||||
addRandomToStore(itemPtr, 1, store, true);
|
||||
}
|
||||
else
|
||||
{
|
||||
|
@ -70,11 +68,11 @@ namespace
|
|||
if (itemId.empty())
|
||||
return;
|
||||
MWWorld::ManualRef manualRef(MWBase::Environment::get().getWorld()->getStore(), itemId, 1);
|
||||
addRandomToStore(manualRef.getPtr(), count, owner, store, false);
|
||||
addRandomToStore(manualRef.getPtr(), count, store, false);
|
||||
}
|
||||
}
|
||||
else
|
||||
addToStore(itemPtr, count, owner, store);
|
||||
addToStore(itemPtr, count, store);
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -141,20 +139,20 @@ namespace MWScript
|
|||
{
|
||||
if (store.isResolved())
|
||||
{
|
||||
addRandomToStore(itemPtr, count, ptr, store);
|
||||
addRandomToStore(itemPtr, count, store);
|
||||
}
|
||||
}
|
||||
else
|
||||
addToStore(itemPtr, count, ptr, store, store.isResolved());
|
||||
addToStore(itemPtr, count, store, store.isResolved());
|
||||
}
|
||||
}
|
||||
return;
|
||||
}
|
||||
MWWorld::ContainerStore& store = ptr.getClass().getContainerStore(ptr);
|
||||
if (isLevelledList)
|
||||
addRandomToStore(itemPtr, count, ptr, store);
|
||||
addRandomToStore(itemPtr, count, store);
|
||||
else
|
||||
addToStore(itemPtr, count, ptr, store);
|
||||
addToStore(itemPtr, count, store);
|
||||
|
||||
// Spawn a messagebox (only for items added to player's inventory and if player is talking to someone)
|
||||
if (ptr == MWBase::Environment::get().getWorld()->getPlayerPtr())
|
||||
|
@ -246,7 +244,7 @@ namespace MWScript
|
|||
auto& store = container.getClass().getContainerStore(container);
|
||||
// Note that unlike AddItem, RemoveItem only removes from unresolved containers
|
||||
if (!store.isResolved())
|
||||
store.remove(item, count, ptr, false, false);
|
||||
store.remove(item, count, false, false);
|
||||
}
|
||||
}
|
||||
return;
|
||||
|
@ -263,7 +261,7 @@ namespace MWScript
|
|||
}
|
||||
}
|
||||
|
||||
int numRemoved = store.remove(item, count, ptr);
|
||||
int numRemoved = store.remove(item, count);
|
||||
|
||||
// Spawn a messagebox (only for items removed from player's inventory)
|
||||
if ((numRemoved > 0) && (ptr == MWMechanics::getPlayer()))
|
||||
|
@ -318,7 +316,7 @@ namespace MWScript
|
|||
if (found == invStore.end())
|
||||
{
|
||||
MWWorld::ManualRef ref(store, item, 1);
|
||||
found = ptr.getClass().getContainerStore(ptr).add(ref.getPtr(), 1, ptr, false);
|
||||
found = ptr.getClass().getContainerStore(ptr).add(ref.getPtr(), 1, false);
|
||||
Log(Debug::Warning) << "Implicitly adding one " << item << " to the inventory store of "
|
||||
<< ptr.getCellRef().getRefId()
|
||||
<< " to fulfill the requirements of Equip instruction";
|
||||
|
|
|
@ -580,10 +580,10 @@ namespace MWScript
|
|||
store.get<ESM::Creature>().find(
|
||||
creature); // This line throws an exception if it can't find the creature
|
||||
|
||||
MWWorld::Ptr item = *ptr.getClass().getContainerStore(ptr).add(gem, 1, ptr);
|
||||
MWWorld::Ptr item = *ptr.getClass().getContainerStore(ptr).add(gem, 1);
|
||||
|
||||
// Set the soul on just one of the gems, not the whole stack
|
||||
item.getContainerStore()->unstack(item, ptr);
|
||||
item.getContainerStore()->unstack(item);
|
||||
item.getCellRef().setSoul(creature);
|
||||
|
||||
// Restack the gem with other gems with the same soul
|
||||
|
@ -614,7 +614,7 @@ namespace MWScript
|
|||
{
|
||||
if (it->getCellRef().getSoul() == soul)
|
||||
{
|
||||
store.remove(*it, 1, ptr);
|
||||
store.remove(*it, 1);
|
||||
return;
|
||||
}
|
||||
}
|
||||
|
@ -667,7 +667,7 @@ namespace MWScript
|
|||
if (it != store.end() && it->getCellRef().getRefId() == item)
|
||||
{
|
||||
int numToRemove = std::min(amount - numNotEquipped, it->getRefData().getCount());
|
||||
store.unequipItemQuantity(*it, ptr, numToRemove);
|
||||
store.unequipItemQuantity(*it, numToRemove);
|
||||
numNotEquipped += numToRemove;
|
||||
}
|
||||
}
|
||||
|
@ -676,7 +676,7 @@ namespace MWScript
|
|||
{
|
||||
if (iter->getCellRef().getRefId() == item && !store.isEquipped(*iter))
|
||||
{
|
||||
int removed = store.remove(*iter, amount, ptr);
|
||||
int removed = store.remove(*iter, amount);
|
||||
MWWorld::Ptr dropped
|
||||
= MWBase::Environment::get().getWorld()->dropObjectOnGround(ptr, *iter, removed);
|
||||
dropped.getCellRef().setOwner(ESM::RefId::sEmpty);
|
||||
|
@ -732,7 +732,7 @@ namespace MWScript
|
|||
if (iter->getCellRef().getSoul() == soul)
|
||||
{
|
||||
MWBase::Environment::get().getWorld()->dropObjectOnGround(ptr, *iter, 1);
|
||||
store.remove(*iter, 1, ptr);
|
||||
store.remove(*iter, 1);
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
|
|
@ -75,7 +75,7 @@ namespace MWWorld
|
|||
if (invStore.getSlot(*slot) == invStore.end())
|
||||
{
|
||||
// slot is not occupied
|
||||
invStore.equip(*slot, it, actor);
|
||||
invStore.equip(*slot, it);
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
@ -88,14 +88,14 @@ namespace MWWorld
|
|||
bool reEquip = false;
|
||||
for (slot = slots_.first.begin(); slot != slots_.first.end(); ++slot)
|
||||
{
|
||||
invStore.unequipSlot(*slot, actor, false);
|
||||
invStore.unequipSlot(*slot, false);
|
||||
if (slot + 1 != slots_.first.end())
|
||||
{
|
||||
invStore.equip(*slot, invStore.getSlot(*(slot + 1)), actor);
|
||||
invStore.equip(*slot, invStore.getSlot(*(slot + 1)));
|
||||
}
|
||||
else
|
||||
{
|
||||
invStore.equip(*slot, it, actor);
|
||||
invStore.equip(*slot, it);
|
||||
}
|
||||
|
||||
// Fix for issue of selected enchated item getting remmoved on cycle
|
||||
|
|
|
@ -42,8 +42,8 @@ namespace MWWorld
|
|||
// not work for a last item in the container - empty harvested containers are considered as "allowed to
|
||||
// use".
|
||||
MWBase::Environment::get().getMechanicsManager()->itemTaken(actor, *it, target, itemCount);
|
||||
actorStore.add(*it, itemCount, actor);
|
||||
store.remove(*it, itemCount, getTarget());
|
||||
actorStore.add(*it, itemCount);
|
||||
store.remove(*it, itemCount);
|
||||
std::string name{ it->getClass().getName(*it) };
|
||||
takenMap[name] += itemCount;
|
||||
}
|
||||
|
|
|
@ -33,7 +33,7 @@ namespace MWWorld
|
|||
MWBase::Environment::get().getMechanicsManager()->itemTaken(
|
||||
actor, getTarget(), MWWorld::Ptr(), getTarget().getRefData().getCount());
|
||||
MWWorld::Ptr newitem
|
||||
= *actor.getClass().getContainerStore(actor).add(getTarget(), getTarget().getRefData().getCount(), actor);
|
||||
= *actor.getClass().getContainerStore(actor).add(getTarget(), getTarget().getRefData().getCount());
|
||||
MWBase::Environment::get().getWorld()->deleteObject(getTarget());
|
||||
setTarget(newitem);
|
||||
}
|
||||
|
|
|
@ -52,6 +52,7 @@
|
|||
#include "class.hpp"
|
||||
#include "containerstore.hpp"
|
||||
#include "esmstore.hpp"
|
||||
#include "inventorystore.hpp"
|
||||
#include "ptr.hpp"
|
||||
#include "worldmodel.hpp"
|
||||
|
||||
|
@ -264,10 +265,9 @@ namespace
|
|||
if (!iter->mData.isEnabled())
|
||||
{
|
||||
iter->mData.enable();
|
||||
MWBase::Environment::get().getWorld()->disable(MWWorld::Ptr(&*iter, cellstore));
|
||||
MWBase::Environment::get().getWorld()->disable(ptr);
|
||||
}
|
||||
else
|
||||
MWBase::Environment::get().getWorldModel()->registerPtr(MWWorld::Ptr(&*iter, cellstore));
|
||||
MWBase::Environment::get().getWorldModel()->registerPtr(ptr);
|
||||
return;
|
||||
}
|
||||
|
||||
|
@ -444,7 +444,11 @@ namespace MWWorld
|
|||
mMovedToAnotherCell.insert(std::make_pair(object.getBase(), cellToMoveTo));
|
||||
|
||||
updateMergedRefs();
|
||||
return MWWorld::Ptr(object.getBase(), cellToMoveTo);
|
||||
MWWorld::Ptr ptr(object.getBase(), cellToMoveTo);
|
||||
const Class& cls = ptr.getClass();
|
||||
if (cls.hasInventoryStore(ptr))
|
||||
cls.getInventoryStore(ptr).setActor(ptr);
|
||||
return ptr;
|
||||
}
|
||||
|
||||
struct MergeVisitor
|
||||
|
|
|
@ -15,8 +15,10 @@
|
|||
#include "actiontake.hpp"
|
||||
#include "containerstore.hpp"
|
||||
#include "failedaction.hpp"
|
||||
#include "inventorystore.hpp"
|
||||
#include "nullaction.hpp"
|
||||
#include "ptr.hpp"
|
||||
#include "worldmodel.hpp"
|
||||
|
||||
#include "../mwgui/tooltips.hpp"
|
||||
|
||||
|
@ -372,6 +374,9 @@ namespace MWWorld
|
|||
Ptr newPtr = copyToCellImpl(ptr, cell);
|
||||
newPtr.getCellRef().unsetRefNum(); // This RefNum is only valid within the original cell of the reference
|
||||
newPtr.getRefData().setCount(count);
|
||||
MWBase::Environment::get().getWorldModel()->registerPtr(newPtr);
|
||||
if (hasInventoryStore(newPtr))
|
||||
getInventoryStore(newPtr).setActor(newPtr);
|
||||
return newPtr;
|
||||
}
|
||||
|
||||
|
|
|
@ -192,6 +192,12 @@ int MWWorld::ContainerStore::count(const ESM::RefId& id) const
|
|||
return total;
|
||||
}
|
||||
|
||||
void MWWorld::ContainerStore::clearRefNums()
|
||||
{
|
||||
for (const auto& iter : *this)
|
||||
iter.getCellRef().unsetRefNum();
|
||||
}
|
||||
|
||||
MWWorld::ContainerStoreListener* MWWorld::ContainerStore::getContListener() const
|
||||
{
|
||||
return mListener;
|
||||
|
@ -202,7 +208,7 @@ void MWWorld::ContainerStore::setContListener(MWWorld::ContainerStoreListener* l
|
|||
mListener = listener;
|
||||
}
|
||||
|
||||
MWWorld::ContainerStoreIterator MWWorld::ContainerStore::unstack(const Ptr& ptr, const Ptr& container, int count)
|
||||
MWWorld::ContainerStoreIterator MWWorld::ContainerStore::unstack(const Ptr& ptr, int count)
|
||||
{
|
||||
resolve();
|
||||
if (ptr.getRefData().getCount() <= count)
|
||||
|
@ -212,7 +218,7 @@ MWWorld::ContainerStoreIterator MWWorld::ContainerStore::unstack(const Ptr& ptr,
|
|||
if (!script.empty())
|
||||
MWBase::Environment::get().getWorld()->getLocalScripts().add(script, *it);
|
||||
|
||||
remove(ptr, ptr.getRefData().getCount() - count, container);
|
||||
remove(ptr, ptr.getRefData().getCount() - count);
|
||||
|
||||
return it;
|
||||
}
|
||||
|
@ -285,14 +291,14 @@ bool MWWorld::ContainerStore::stacks(const ConstPtr& ptr1, const ConstPtr& ptr2)
|
|||
&& cls2.getItemHealth(ptr2) == cls2.getItemMaxHealth(ptr2)));
|
||||
}
|
||||
|
||||
MWWorld::ContainerStoreIterator MWWorld::ContainerStore::add(const ESM::RefId& id, int count, const Ptr& actorPtr)
|
||||
MWWorld::ContainerStoreIterator MWWorld::ContainerStore::add(const ESM::RefId& id, int count)
|
||||
{
|
||||
MWWorld::ManualRef ref(MWBase::Environment::get().getWorld()->getStore(), id, count);
|
||||
return add(ref.getPtr(), count, actorPtr);
|
||||
return add(ref.getPtr(), count);
|
||||
}
|
||||
|
||||
MWWorld::ContainerStoreIterator MWWorld::ContainerStore::add(
|
||||
const Ptr& itemPtr, int count, const Ptr& actorPtr, bool /*allowAutoEquip*/, bool resolve)
|
||||
const Ptr& itemPtr, int count, bool /*allowAutoEquip*/, bool resolve)
|
||||
{
|
||||
Ptr player = MWBase::Environment::get().getWorld()->getPlayerPtr();
|
||||
|
||||
|
@ -326,7 +332,7 @@ MWWorld::ContainerStoreIterator MWWorld::ContainerStore::add(
|
|||
const ESM::RefId& script = item.getClass().getScript(item);
|
||||
if (!script.empty())
|
||||
{
|
||||
if (actorPtr == player)
|
||||
if (mActor == player)
|
||||
{
|
||||
// Items in player's inventory have cell set to 0, so their scripts will never be removed
|
||||
item.mCell = nullptr;
|
||||
|
@ -335,7 +341,10 @@ MWWorld::ContainerStoreIterator MWWorld::ContainerStore::add(
|
|||
{
|
||||
// Set mCell to the cell of the container/actor, so that the scripts are removed properly when
|
||||
// the cell of the container/actor goes inactive
|
||||
item.mCell = actorPtr.getCell();
|
||||
if (!mPtr.isEmpty())
|
||||
item.mCell = mPtr.getCell();
|
||||
else if (!mActor.isEmpty())
|
||||
item.mCell = mActor.getCell();
|
||||
}
|
||||
|
||||
item.mContainerStore = this;
|
||||
|
@ -344,12 +353,12 @@ MWWorld::ContainerStoreIterator MWWorld::ContainerStore::add(
|
|||
|
||||
// Set OnPCAdd special variable, if it is declared
|
||||
// Make sure to do this *after* we have added the script to LocalScripts
|
||||
if (actorPtr == player)
|
||||
if (mActor == player)
|
||||
item.getRefData().getLocals().setVarByInt(script, "onpcadd", 1);
|
||||
}
|
||||
|
||||
// we should not fire event for InventoryStore yet - it has some custom logic
|
||||
if (mListener && !actorPtr.getClass().hasInventoryStore(actorPtr))
|
||||
if (mListener && !(!mActor.isEmpty() && mActor.getClass().hasInventoryStore(mActor)))
|
||||
mListener->itemAdded(item, count);
|
||||
|
||||
return it;
|
||||
|
@ -504,8 +513,7 @@ void MWWorld::ContainerStore::updateRechargingItems()
|
|||
}
|
||||
}
|
||||
|
||||
int MWWorld::ContainerStore::remove(
|
||||
const ESM::RefId& itemId, int count, const Ptr& actor, bool equipReplacement, bool resolveFirst)
|
||||
int MWWorld::ContainerStore::remove(const ESM::RefId& itemId, int count, bool equipReplacement, bool resolveFirst)
|
||||
{
|
||||
if (resolveFirst)
|
||||
resolve();
|
||||
|
@ -513,7 +521,7 @@ int MWWorld::ContainerStore::remove(
|
|||
|
||||
for (ContainerStoreIterator iter(begin()); iter != end() && toRemove > 0; ++iter)
|
||||
if (iter->getCellRef().getRefId() == itemId)
|
||||
toRemove -= remove(*iter, toRemove, actor, equipReplacement, resolveFirst);
|
||||
toRemove -= remove(*iter, toRemove, equipReplacement, resolveFirst);
|
||||
|
||||
flagAsModified();
|
||||
|
||||
|
@ -532,8 +540,7 @@ bool MWWorld::ContainerStore::hasVisibleItems() const
|
|||
return false;
|
||||
}
|
||||
|
||||
int MWWorld::ContainerStore::remove(
|
||||
const Ptr& item, int count, const Ptr& actor, bool equipReplacement, bool resolveFirst)
|
||||
int MWWorld::ContainerStore::remove(const Ptr& item, int count, bool equipReplacement, bool resolveFirst)
|
||||
{
|
||||
assert(this == item.getContainerStore());
|
||||
if (resolveFirst)
|
||||
|
@ -556,7 +563,7 @@ int MWWorld::ContainerStore::remove(
|
|||
flagAsModified();
|
||||
|
||||
// we should not fire event for InventoryStore yet - it has some custom logic
|
||||
if (mListener && !actor.getClass().hasInventoryStore(actor))
|
||||
if (mListener && !(!mActor.isEmpty() && mActor.getClass().hasInventoryStore(mActor)))
|
||||
mListener->itemRemoved(item, count - toRemove);
|
||||
|
||||
// number of removed items
|
||||
|
|
|
@ -102,12 +102,21 @@ namespace MWWorld
|
|||
protected:
|
||||
ContainerStoreListener* mListener;
|
||||
|
||||
// Used in clone() to unset refnums of copies.
|
||||
// (RefNum should be unique, copy can not have the same RefNum).
|
||||
void clearRefNums();
|
||||
|
||||
// (item, max charge)
|
||||
typedef std::vector<std::pair<ContainerStoreIterator, float>> TRechargingItems;
|
||||
TRechargingItems mRechargingItems;
|
||||
|
||||
bool mRechargingItemsUpToDate;
|
||||
|
||||
// Non-empty only if is InventoryStore.
|
||||
// The actor whose inventory it is.
|
||||
// TODO: Consider merging mActor and mPtr.
|
||||
MWWorld::Ptr mActor;
|
||||
|
||||
private:
|
||||
MWWorld::CellRefList<ESM::Potion> potions;
|
||||
MWWorld::CellRefList<ESM::Apparatus> appas;
|
||||
|
@ -128,7 +137,7 @@ namespace MWWorld
|
|||
bool mModified;
|
||||
bool mResolved;
|
||||
unsigned int mSeed;
|
||||
MWWorld::Ptr mPtr;
|
||||
MWWorld::Ptr mPtr; // Container that contains this store. Set in MWClass::Container::getContainerStore
|
||||
std::weak_ptr<ResolutionListener> mResolutionListener;
|
||||
|
||||
ContainerStoreIterator addImp(const Ptr& ptr, int count, bool markModified = true);
|
||||
|
@ -160,7 +169,12 @@ namespace MWWorld
|
|||
|
||||
virtual ~ContainerStore();
|
||||
|
||||
virtual std::unique_ptr<ContainerStore> clone() { return std::make_unique<ContainerStore>(*this); }
|
||||
virtual std::unique_ptr<ContainerStore> clone()
|
||||
{
|
||||
auto res = std::make_unique<ContainerStore>(*this);
|
||||
res->clearRefNums();
|
||||
return res;
|
||||
}
|
||||
|
||||
ConstContainerStoreIterator cbegin(int mask = Type_All) const;
|
||||
ConstContainerStoreIterator cend() const;
|
||||
|
@ -173,7 +187,7 @@ namespace MWWorld
|
|||
bool hasVisibleItems() const;
|
||||
|
||||
virtual ContainerStoreIterator add(
|
||||
const Ptr& itemPtr, int count, const Ptr& actorPtr, bool allowAutoEquip = true, bool resolve = true);
|
||||
const Ptr& itemPtr, int count, bool allowAutoEquip = true, bool resolve = true);
|
||||
///< Add the item pointed to by \a ptr to this container. (Stacks automatically if needed)
|
||||
///
|
||||
/// \note The item pointed to is not required to exist beyond this function call.
|
||||
|
@ -184,17 +198,15 @@ namespace MWWorld
|
|||
/// @return if stacking happened, return iterator to the item that was stacked against, otherwise iterator to
|
||||
/// the newly inserted item.
|
||||
|
||||
ContainerStoreIterator add(const ESM::RefId& id, int count, const Ptr& actorPtr);
|
||||
ContainerStoreIterator add(const ESM::RefId& id, int count);
|
||||
///< Utility to construct a ManualRef and call add(ptr, count, actorPtr, true)
|
||||
|
||||
int remove(
|
||||
const ESM::RefId& itemId, int count, const Ptr& actor, bool equipReplacement = 0, bool resolve = true);
|
||||
int remove(const ESM::RefId& itemId, int count, bool equipReplacement = 0, bool resolve = true);
|
||||
///< 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, bool equipReplacement = 0, bool resolve = true);
|
||||
virtual int remove(const Ptr& item, int count, bool equipReplacement = 0, bool resolve = true);
|
||||
///< Remove \a count item(s) designated by \a item from this inventory.
|
||||
///
|
||||
/// @return the number of items actually removed
|
||||
|
@ -202,7 +214,7 @@ namespace MWWorld
|
|||
void rechargeItems(float duration);
|
||||
///< Restore charge on enchanted items. Note this should only be done for the player.
|
||||
|
||||
ContainerStoreIterator unstack(const Ptr& ptr, const Ptr& container, int count = 1);
|
||||
ContainerStoreIterator unstack(const Ptr& ptr, int count = 1);
|
||||
///< Unstack an item in this container. The item's count will be set to count, then a new stack will be added
|
||||
///< with (origCount-count).
|
||||
///
|
||||
|
|
|
@ -128,18 +128,18 @@ MWWorld::InventoryStore& MWWorld::InventoryStore::operator=(const InventoryStore
|
|||
}
|
||||
|
||||
MWWorld::ContainerStoreIterator MWWorld::InventoryStore::add(
|
||||
const Ptr& itemPtr, int count, const Ptr& actorPtr, bool allowAutoEquip, bool resolve)
|
||||
const Ptr& itemPtr, int count, bool allowAutoEquip, bool resolve)
|
||||
{
|
||||
const MWWorld::ContainerStoreIterator& retVal
|
||||
= MWWorld::ContainerStore::add(itemPtr, count, actorPtr, allowAutoEquip, resolve);
|
||||
= MWWorld::ContainerStore::add(itemPtr, count, allowAutoEquip, resolve);
|
||||
|
||||
// Auto-equip items if an armor/clothing item is added, but not for the player nor werewolves
|
||||
if (allowAutoEquip && actorPtr != MWMechanics::getPlayer() && actorPtr.getClass().isNpc()
|
||||
&& !actorPtr.getClass().getNpcStats(actorPtr).isWerewolf())
|
||||
if (allowAutoEquip && mActor != MWMechanics::getPlayer() && mActor.getClass().isNpc()
|
||||
&& !mActor.getClass().getNpcStats(mActor).isWerewolf())
|
||||
{
|
||||
auto type = itemPtr.getType();
|
||||
if (type == ESM::Armor::sRecordId || type == ESM::Clothing::sRecordId)
|
||||
autoEquip(actorPtr);
|
||||
autoEquip();
|
||||
}
|
||||
|
||||
if (mListener)
|
||||
|
@ -148,7 +148,7 @@ MWWorld::ContainerStoreIterator MWWorld::InventoryStore::add(
|
|||
return retVal;
|
||||
}
|
||||
|
||||
void MWWorld::InventoryStore::equip(int slot, const ContainerStoreIterator& iterator, const Ptr& actor)
|
||||
void MWWorld::InventoryStore::equip(int slot, const ContainerStoreIterator& iterator)
|
||||
{
|
||||
if (iterator == end())
|
||||
throw std::runtime_error("can't equip end() iterator, use unequip function instead");
|
||||
|
@ -167,31 +167,31 @@ void MWWorld::InventoryStore::equip(int slot, const ContainerStoreIterator& iter
|
|||
throw std::runtime_error("invalid slot");
|
||||
|
||||
if (mSlots[slot] != end())
|
||||
unequipSlot(slot, actor);
|
||||
unequipSlot(slot);
|
||||
|
||||
// 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
|
||||
{
|
||||
unstack(*iterator, actor);
|
||||
unstack(*iterator);
|
||||
}
|
||||
|
||||
mSlots[slot] = iterator;
|
||||
|
||||
flagAsModified();
|
||||
|
||||
fireEquipmentChangedEvent(actor);
|
||||
fireEquipmentChangedEvent();
|
||||
}
|
||||
|
||||
void MWWorld::InventoryStore::unequipAll(const MWWorld::Ptr& actor)
|
||||
void MWWorld::InventoryStore::unequipAll()
|
||||
{
|
||||
mUpdatesEnabled = false;
|
||||
for (int slot = 0; slot < MWWorld::InventoryStore::Slots; ++slot)
|
||||
unequipSlot(slot, actor);
|
||||
unequipSlot(slot);
|
||||
|
||||
mUpdatesEnabled = true;
|
||||
|
||||
fireEquipmentChangedEvent(actor);
|
||||
fireEquipmentChangedEvent();
|
||||
}
|
||||
|
||||
MWWorld::ContainerStoreIterator MWWorld::InventoryStore::getSlot(int slot)
|
||||
|
@ -223,14 +223,14 @@ MWWorld::ContainerStoreIterator MWWorld::InventoryStore::findSlot(int slot) cons
|
|||
return mSlots[slot];
|
||||
}
|
||||
|
||||
void MWWorld::InventoryStore::autoEquipWeapon(const MWWorld::Ptr& actor, TSlots& slots_)
|
||||
void MWWorld::InventoryStore::autoEquipWeapon(TSlots& slots_)
|
||||
{
|
||||
if (!actor.getClass().isNpc())
|
||||
if (!mActor.getClass().isNpc())
|
||||
{
|
||||
// In original game creatures do not autoequip weapon, but we need it for weapon sheathing.
|
||||
// The only case when the difference is noticable - when this creature sells weapon.
|
||||
// So just disable weapon autoequipping for creatures which sells weapon.
|
||||
int services = actor.getClass().getServices(actor);
|
||||
int services = mActor.getClass().getServices(mActor);
|
||||
bool sellsWeapon = services & (ESM::NPC::Weapon | ESM::NPC::MagicItems);
|
||||
if (sellsWeapon)
|
||||
return;
|
||||
|
@ -285,7 +285,7 @@ void MWWorld::InventoryStore::autoEquipWeapon(const MWWorld::Ptr& actor, TSlots&
|
|||
|
||||
for (int j = 0; j < static_cast<int>(weaponSkillsLength); ++j)
|
||||
{
|
||||
float skillValue = actor.getClass().getSkill(actor, static_cast<int>(weaponSkills[j]));
|
||||
float skillValue = mActor.getClass().getSkill(mActor, static_cast<int>(weaponSkills[j]));
|
||||
if (skillValue > max && !weaponSkillVisited[j])
|
||||
{
|
||||
max = skillValue;
|
||||
|
@ -328,7 +328,7 @@ void MWWorld::InventoryStore::autoEquipWeapon(const MWWorld::Ptr& actor, TSlots&
|
|||
}
|
||||
}
|
||||
|
||||
if (weapon != end() && weapon->getClass().canBeEquipped(*weapon, actor).first)
|
||||
if (weapon != end() && weapon->getClass().canBeEquipped(*weapon, mActor).first)
|
||||
{
|
||||
// Do not equip ranged weapons, if there is no suitable ammo
|
||||
bool hasAmmo = true;
|
||||
|
@ -360,7 +360,7 @@ void MWWorld::InventoryStore::autoEquipWeapon(const MWWorld::Ptr& actor, TSlots&
|
|||
{
|
||||
if (weapon->getRefData().getCount() > 1)
|
||||
{
|
||||
unstack(*weapon, actor);
|
||||
unstack(*weapon);
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -379,13 +379,13 @@ void MWWorld::InventoryStore::autoEquipWeapon(const MWWorld::Ptr& actor, TSlots&
|
|||
}
|
||||
}
|
||||
|
||||
void MWWorld::InventoryStore::autoEquipArmor(const MWWorld::Ptr& actor, TSlots& slots_)
|
||||
void MWWorld::InventoryStore::autoEquipArmor(TSlots& slots_)
|
||||
{
|
||||
// Only NPCs can wear armor for now.
|
||||
// For creatures we equip only shields.
|
||||
if (!actor.getClass().isNpc())
|
||||
if (!mActor.getClass().isNpc())
|
||||
{
|
||||
autoEquipShield(actor, slots_);
|
||||
autoEquipShield(slots_);
|
||||
return;
|
||||
}
|
||||
|
||||
|
@ -395,7 +395,7 @@ void MWWorld::InventoryStore::autoEquipArmor(const MWWorld::Ptr& actor, TSlots&
|
|||
static float fUnarmoredBase1 = store.find("fUnarmoredBase1")->mValue.getFloat();
|
||||
static float fUnarmoredBase2 = store.find("fUnarmoredBase2")->mValue.getFloat();
|
||||
|
||||
float unarmoredSkill = actor.getClass().getSkill(actor, ESM::Skill::Unarmored);
|
||||
float unarmoredSkill = mActor.getClass().getSkill(mActor, ESM::Skill::Unarmored);
|
||||
float unarmoredRating = (fUnarmoredBase1 * unarmoredSkill) * (fUnarmoredBase2 * unarmoredSkill);
|
||||
|
||||
for (ContainerStoreIterator iter(begin(ContainerStore::Type_Clothing | ContainerStore::Type_Armor)); iter != end();
|
||||
|
@ -403,7 +403,7 @@ void MWWorld::InventoryStore::autoEquipArmor(const MWWorld::Ptr& actor, TSlots&
|
|||
{
|
||||
Ptr test = *iter;
|
||||
|
||||
switch (test.getClass().canBeEquipped(test, actor).first)
|
||||
switch (test.getClass().canBeEquipped(test, mActor).first)
|
||||
{
|
||||
case 0:
|
||||
continue;
|
||||
|
@ -412,7 +412,7 @@ void MWWorld::InventoryStore::autoEquipArmor(const MWWorld::Ptr& actor, TSlots&
|
|||
}
|
||||
|
||||
if (iter.getType() == ContainerStore::Type_Armor
|
||||
&& test.getClass().getEffectiveArmorRating(test, actor) <= std::max(unarmoredRating, 0.f))
|
||||
&& test.getClass().getEffectiveArmorRating(test, mActor) <= std::max(unarmoredRating, 0.f))
|
||||
{
|
||||
continue;
|
||||
}
|
||||
|
@ -437,8 +437,8 @@ void MWWorld::InventoryStore::autoEquipArmor(const MWWorld::Ptr& actor, TSlots&
|
|||
|
||||
if (old.get<ESM::Armor>()->mBase->mData.mType == test.get<ESM::Armor>()->mBase->mData.mType)
|
||||
{
|
||||
if (old.getClass().getEffectiveArmorRating(old, actor)
|
||||
>= test.getClass().getEffectiveArmorRating(test, actor))
|
||||
if (old.getClass().getEffectiveArmorRating(old, mActor)
|
||||
>= test.getClass().getEffectiveArmorRating(test, mActor))
|
||||
// old armor had better armor rating
|
||||
continue;
|
||||
}
|
||||
|
@ -483,7 +483,7 @@ void MWWorld::InventoryStore::autoEquipArmor(const MWWorld::Ptr& actor, TSlots&
|
|||
// unstack item pointed to by iterator if required
|
||||
if (iter->getRefData().getCount() > 1)
|
||||
{
|
||||
unstack(*iter, actor);
|
||||
unstack(*iter);
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -494,13 +494,13 @@ void MWWorld::InventoryStore::autoEquipArmor(const MWWorld::Ptr& actor, TSlots&
|
|||
}
|
||||
}
|
||||
|
||||
void MWWorld::InventoryStore::autoEquipShield(const MWWorld::Ptr& actor, TSlots& slots_)
|
||||
void MWWorld::InventoryStore::autoEquipShield(TSlots& slots_)
|
||||
{
|
||||
for (ContainerStoreIterator iter(begin(ContainerStore::Type_Armor)); iter != end(); ++iter)
|
||||
{
|
||||
if (iter->get<ESM::Armor>()->mBase->mData.mType != ESM::Armor::Shield)
|
||||
continue;
|
||||
if (iter->getClass().canBeEquipped(*iter, actor).first != 1)
|
||||
if (iter->getClass().canBeEquipped(*iter, mActor).first != 1)
|
||||
continue;
|
||||
std::pair<std::vector<int>, bool> shieldSlots = iter->getClass().getEquipmentSlots(*iter);
|
||||
int slot = shieldSlots.first[0];
|
||||
|
@ -515,7 +515,7 @@ void MWWorld::InventoryStore::autoEquipShield(const MWWorld::Ptr& actor, TSlots&
|
|||
}
|
||||
}
|
||||
|
||||
void MWWorld::InventoryStore::autoEquip(const MWWorld::Ptr& actor)
|
||||
void MWWorld::InventoryStore::autoEquip()
|
||||
{
|
||||
TSlots slots_;
|
||||
initSlots(slots_);
|
||||
|
@ -527,8 +527,8 @@ void MWWorld::InventoryStore::autoEquip(const MWWorld::Ptr& actor)
|
|||
// Equipping lights is handled in Actors::updateEquippedLight based on environment light.
|
||||
// Note: creatures ignore equipment armor rating and only equip shields
|
||||
// Use custom logic for them - select shield based on its health instead of armor rating
|
||||
autoEquipWeapon(actor, slots_);
|
||||
autoEquipArmor(actor, slots_);
|
||||
autoEquipWeapon(slots_);
|
||||
autoEquipArmor(slots_);
|
||||
|
||||
bool changed = false;
|
||||
|
||||
|
@ -545,16 +545,16 @@ void MWWorld::InventoryStore::autoEquip(const MWWorld::Ptr& actor)
|
|||
if (changed)
|
||||
{
|
||||
mSlots.swap(slots_);
|
||||
fireEquipmentChangedEvent(actor);
|
||||
fireEquipmentChangedEvent();
|
||||
flagAsModified();
|
||||
}
|
||||
}
|
||||
|
||||
MWWorld::ContainerStoreIterator MWWorld::InventoryStore::getPreferredShield(const MWWorld::Ptr& actor)
|
||||
MWWorld::ContainerStoreIterator MWWorld::InventoryStore::getPreferredShield()
|
||||
{
|
||||
TSlots slots;
|
||||
initSlots(slots);
|
||||
autoEquipArmor(actor, slots);
|
||||
autoEquipArmor(slots);
|
||||
return slots[Slot_CarriedLeft];
|
||||
}
|
||||
|
||||
|
@ -588,9 +588,9 @@ MWWorld::ContainerStoreIterator MWWorld::InventoryStore::getSelectedEnchantItem(
|
|||
return mSelectedEnchantItem;
|
||||
}
|
||||
|
||||
int MWWorld::InventoryStore::remove(const Ptr& item, int count, const Ptr& actor, bool equipReplacement, bool resolve)
|
||||
int MWWorld::InventoryStore::remove(const Ptr& item, int count, bool equipReplacement, bool resolve)
|
||||
{
|
||||
int retCount = ContainerStore::remove(item, count, actor, equipReplacement, resolve);
|
||||
int retCount = ContainerStore::remove(item, count, equipReplacement, resolve);
|
||||
|
||||
bool wasEquipped = false;
|
||||
if (!item.getRefData().getCount())
|
||||
|
@ -602,7 +602,7 @@ int MWWorld::InventoryStore::remove(const Ptr& item, int count, const Ptr& actor
|
|||
|
||||
if (*mSlots[slot] == item)
|
||||
{
|
||||
unequipSlot(slot, actor);
|
||||
unequipSlot(slot);
|
||||
wasEquipped = true;
|
||||
break;
|
||||
}
|
||||
|
@ -612,12 +612,12 @@ int MWWorld::InventoryStore::remove(const Ptr& item, int count, const Ptr& actor
|
|||
// If an armor/clothing item is removed, try to find a replacement,
|
||||
// but not for the player nor werewolves, and not if the RemoveItem script command
|
||||
// was used (equipReplacement is false)
|
||||
if (equipReplacement && wasEquipped && (actor != MWMechanics::getPlayer()) && actor.getClass().isNpc()
|
||||
&& !actor.getClass().getNpcStats(actor).isWerewolf())
|
||||
if (equipReplacement && wasEquipped && (mActor != MWMechanics::getPlayer()) && mActor.getClass().isNpc()
|
||||
&& !mActor.getClass().getNpcStats(mActor).isWerewolf())
|
||||
{
|
||||
auto type = item.getType();
|
||||
if (type == ESM::Armor::sRecordId || type == ESM::Clothing::sRecordId)
|
||||
autoEquip(actor);
|
||||
autoEquip();
|
||||
}
|
||||
|
||||
if (item.getRefData().getCount() == 0 && mSelectedEnchantItem != end() && *mSelectedEnchantItem == item)
|
||||
|
@ -631,8 +631,7 @@ int MWWorld::InventoryStore::remove(const Ptr& item, int count, const Ptr& actor
|
|||
return retCount;
|
||||
}
|
||||
|
||||
MWWorld::ContainerStoreIterator MWWorld::InventoryStore::unequipSlot(
|
||||
int slot, const MWWorld::Ptr& actor, bool applyUpdates)
|
||||
MWWorld::ContainerStoreIterator MWWorld::InventoryStore::unequipSlot(int slot, bool applyUpdates)
|
||||
{
|
||||
if (slot < 0 || slot >= static_cast<int>(mSlots.size()))
|
||||
throw std::runtime_error("slot number out of range");
|
||||
|
@ -650,7 +649,7 @@ MWWorld::ContainerStoreIterator MWWorld::InventoryStore::unequipSlot(
|
|||
{
|
||||
retval = restack(*it);
|
||||
|
||||
if (actor == MWMechanics::getPlayer())
|
||||
if (mActor == MWMechanics::getPlayer())
|
||||
{
|
||||
// Unset OnPCEquip Variable on item's script, if it has a script with that variable declared
|
||||
const ESM::RefId& script = it->getClass().getScript(*it);
|
||||
|
@ -666,7 +665,7 @@ MWWorld::ContainerStoreIterator MWWorld::InventoryStore::unequipSlot(
|
|||
|
||||
if (applyUpdates)
|
||||
{
|
||||
fireEquipmentChangedEvent(actor);
|
||||
fireEquipmentChangedEvent();
|
||||
}
|
||||
|
||||
return retval;
|
||||
|
@ -675,21 +674,19 @@ MWWorld::ContainerStoreIterator MWWorld::InventoryStore::unequipSlot(
|
|||
return it;
|
||||
}
|
||||
|
||||
MWWorld::ContainerStoreIterator MWWorld::InventoryStore::unequipItem(
|
||||
const MWWorld::Ptr& item, const MWWorld::Ptr& actor)
|
||||
MWWorld::ContainerStoreIterator MWWorld::InventoryStore::unequipItem(const MWWorld::Ptr& item)
|
||||
{
|
||||
for (int slot = 0; slot < MWWorld::InventoryStore::Slots; ++slot)
|
||||
{
|
||||
MWWorld::ContainerStoreIterator equipped = getSlot(slot);
|
||||
if (equipped != end() && *equipped == item)
|
||||
return unequipSlot(slot, actor);
|
||||
return unequipSlot(slot);
|
||||
}
|
||||
|
||||
throw std::runtime_error("attempt to unequip an item that is not currently equipped");
|
||||
}
|
||||
|
||||
MWWorld::ContainerStoreIterator MWWorld::InventoryStore::unequipItemQuantity(
|
||||
const Ptr& item, const Ptr& actor, int count)
|
||||
MWWorld::ContainerStoreIterator MWWorld::InventoryStore::unequipItemQuantity(const Ptr& item, int count)
|
||||
{
|
||||
if (!isEquipped(item))
|
||||
throw std::runtime_error("attempt to unequip an item that is not currently equipped");
|
||||
|
@ -699,7 +696,7 @@ MWWorld::ContainerStoreIterator MWWorld::InventoryStore::unequipItemQuantity(
|
|||
throw std::runtime_error("attempt to unequip more items than equipped");
|
||||
|
||||
if (count == item.getRefData().getCount())
|
||||
return unequipItem(item, actor);
|
||||
return unequipItem(item);
|
||||
|
||||
// Move items to an existing stack if possible, otherwise split count items out into a new stack.
|
||||
// Moving counts manually here, since ContainerStore's restack can't target unequipped stacks.
|
||||
|
@ -713,7 +710,7 @@ MWWorld::ContainerStoreIterator MWWorld::InventoryStore::unequipItemQuantity(
|
|||
}
|
||||
}
|
||||
|
||||
return unstack(item, actor, item.getRefData().getCount() - count);
|
||||
return unstack(item, item.getRefData().getCount() - count);
|
||||
}
|
||||
|
||||
MWWorld::InventoryStoreListener* MWWorld::InventoryStore::getInvListener() const
|
||||
|
@ -721,12 +718,12 @@ MWWorld::InventoryStoreListener* MWWorld::InventoryStore::getInvListener() const
|
|||
return mInventoryListener;
|
||||
}
|
||||
|
||||
void MWWorld::InventoryStore::setInvListener(InventoryStoreListener* listener, const Ptr& actor)
|
||||
void MWWorld::InventoryStore::setInvListener(InventoryStoreListener* listener)
|
||||
{
|
||||
mInventoryListener = listener;
|
||||
}
|
||||
|
||||
void MWWorld::InventoryStore::fireEquipmentChangedEvent(const Ptr& actor)
|
||||
void MWWorld::InventoryStore::fireEquipmentChangedEvent()
|
||||
{
|
||||
if (!mUpdatesEnabled)
|
||||
return;
|
||||
|
@ -735,7 +732,7 @@ void MWWorld::InventoryStore::fireEquipmentChangedEvent(const Ptr& actor)
|
|||
|
||||
// if player, update inventory window
|
||||
/*
|
||||
if (actor == MWMechanics::getPlayer())
|
||||
if (mActor == MWMechanics::getPlayer())
|
||||
{
|
||||
MWBase::Environment::get().getWindowManager()->getInventoryWindow()->updateItemView();
|
||||
}
|
||||
|
|
|
@ -67,9 +67,9 @@ namespace MWWorld
|
|||
|
||||
TSlots mSlots;
|
||||
|
||||
void autoEquipWeapon(const MWWorld::Ptr& actor, TSlots& slots_);
|
||||
void autoEquipArmor(const MWWorld::Ptr& actor, TSlots& slots_);
|
||||
void autoEquipShield(const MWWorld::Ptr& actor, TSlots& slots_);
|
||||
void autoEquipWeapon(TSlots& slots_);
|
||||
void autoEquipArmor(TSlots& slots_);
|
||||
void autoEquipShield(TSlots& slots_);
|
||||
|
||||
// selected magic item (for using enchantments of type "Cast once" or "Cast when used")
|
||||
ContainerStoreIterator mSelectedEnchantItem;
|
||||
|
@ -78,7 +78,7 @@ namespace MWWorld
|
|||
|
||||
void initSlots(TSlots& slots_);
|
||||
|
||||
void fireEquipmentChangedEvent(const Ptr& actor);
|
||||
void fireEquipmentChangedEvent();
|
||||
|
||||
void storeEquipmentState(
|
||||
const MWWorld::LiveCellRefBase& ref, int index, ESM::InventoryState& inventory) const override;
|
||||
|
@ -94,10 +94,18 @@ namespace MWWorld
|
|||
|
||||
InventoryStore& operator=(const InventoryStore& store);
|
||||
|
||||
std::unique_ptr<ContainerStore> clone() override { return std::make_unique<InventoryStore>(*this); }
|
||||
const MWWorld::Ptr& getActor() const { return mActor; }
|
||||
void setActor(const MWWorld::Ptr& actor) { mActor = actor; }
|
||||
|
||||
ContainerStoreIterator add(const Ptr& itemPtr, int count, const Ptr& actorPtr, bool allowAutoEquip = true,
|
||||
bool resolve = true) override;
|
||||
std::unique_ptr<ContainerStore> clone() override
|
||||
{
|
||||
auto res = std::make_unique<InventoryStore>(*this);
|
||||
res->clearRefNums();
|
||||
return res;
|
||||
}
|
||||
|
||||
ContainerStoreIterator add(
|
||||
const Ptr& itemPtr, int count, bool allowAutoEquip = true, bool resolve = true) override;
|
||||
///< Add the item pointed to by \a ptr to this container. (Stacks automatically if needed)
|
||||
/// Auto-equip items if specific conditions are fulfilled and allowAutoEquip is true (see the implementation).
|
||||
///
|
||||
|
@ -109,7 +117,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, const Ptr& actor);
|
||||
void equip(int slot, const ContainerStoreIterator& iterator);
|
||||
///< \warning \a iterator can not be an end()-iterator, use unequip function instead
|
||||
|
||||
bool isEquipped(const MWWorld::ConstPtr& item);
|
||||
|
@ -126,30 +134,29 @@ namespace MWWorld
|
|||
ContainerStoreIterator getSlot(int slot);
|
||||
ConstContainerStoreIterator getSlot(int slot) const;
|
||||
|
||||
ContainerStoreIterator getPreferredShield(const MWWorld::Ptr& actor);
|
||||
ContainerStoreIterator getPreferredShield();
|
||||
|
||||
void unequipAll(const MWWorld::Ptr& actor);
|
||||
void unequipAll();
|
||||
///< Unequip all currently equipped items.
|
||||
|
||||
void autoEquip(const MWWorld::Ptr& actor);
|
||||
void autoEquip();
|
||||
///< Auto equip items according to stats and item value.
|
||||
|
||||
bool stacks(const ConstPtr& ptr1, const ConstPtr& ptr2) const override;
|
||||
///< @return true if the two specified objects can stack with each other
|
||||
|
||||
using ContainerStore::remove;
|
||||
int remove(
|
||||
const Ptr& item, int count, const Ptr& actor, bool equipReplacement = 0, bool resolve = true) override;
|
||||
int remove(const Ptr& item, int count, bool equipReplacement = 0, bool resolve = true) override;
|
||||
///< 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 applyUpdates = true);
|
||||
ContainerStoreIterator unequipSlot(int slot, bool applyUpdates = true);
|
||||
///< Unequip \a slot.
|
||||
///
|
||||
/// @return an iterator to the item that was previously in the slot
|
||||
|
||||
ContainerStoreIterator unequipItem(const Ptr& item, const Ptr& actor);
|
||||
ContainerStoreIterator unequipItem(const Ptr& item);
|
||||
///< Unequip an item identified by its Ptr. An exception is thrown
|
||||
/// if the item is not currently equipped.
|
||||
///
|
||||
|
@ -157,7 +164,7 @@ namespace MWWorld
|
|||
/// (it can be re-stacked so its count may be different than when it
|
||||
/// was equipped).
|
||||
|
||||
ContainerStoreIterator unequipItemQuantity(const Ptr& item, const Ptr& actor, int count);
|
||||
ContainerStoreIterator unequipItemQuantity(const Ptr& item, int count);
|
||||
///< Unequip a specific quantity of an item identified by its Ptr.
|
||||
/// An exception is thrown if the item is not currently equipped,
|
||||
/// if count <= 0, or if count > the item stack size.
|
||||
|
@ -166,7 +173,7 @@ namespace MWWorld
|
|||
/// in the slot (they can be re-stacked so its count may be different
|
||||
/// than the requested count).
|
||||
|
||||
void setInvListener(InventoryStoreListener* listener, const Ptr& actor);
|
||||
void setInvListener(InventoryStoreListener* listener);
|
||||
///< Set a listener for various events, see \a InventoryStoreListener
|
||||
|
||||
InventoryStoreListener* getInvListener() const;
|
||||
|
|
|
@ -788,8 +788,6 @@ namespace MWWorld
|
|||
|
||||
void World::enable(const Ptr& reference)
|
||||
{
|
||||
MWBase::Environment::get().getWorldModel()->registerPtr(reference);
|
||||
|
||||
if (!reference.isInCell())
|
||||
return;
|
||||
|
||||
|
@ -840,7 +838,6 @@ namespace MWWorld
|
|||
if (reference == getPlayerPtr())
|
||||
throw std::runtime_error("can not disable player object");
|
||||
|
||||
MWBase::Environment::get().getWorldModel()->deregisterPtr(reference);
|
||||
reference.getRefData().disable();
|
||||
|
||||
if (reference.getCellRef().getRefNum().hasContentFile())
|
||||
|
@ -2426,7 +2423,7 @@ namespace MWWorld
|
|||
|
||||
mRendering->renderPlayer(player);
|
||||
MWRender::NpcAnimation* anim = static_cast<MWRender::NpcAnimation*>(mRendering->getAnimation(player));
|
||||
player.getClass().getInventoryStore(player).setInvListener(anim, player);
|
||||
player.getClass().getInventoryStore(player).setInvListener(anim);
|
||||
player.getClass().getInventoryStore(player).setContListener(anim);
|
||||
|
||||
scaleObject(player, player.getCellRef().getScale(), true); // apply race height
|
||||
|
|
|
@ -80,7 +80,6 @@
|
|||
-- @usage
|
||||
-- # DataFiles/l10n/MyMod/en.yaml
|
||||
-- good_morning: 'Good morning.'
|
||||
--
|
||||
-- you_have_arrows: |-
|
||||
-- {count, plural,
|
||||
-- one {You have one arrow.}
|
||||
|
@ -107,11 +106,12 @@
|
|||
-- Any object that exists in the game world and has a specific location.
|
||||
-- Player, actors, items, and statics are game objects.
|
||||
-- @type GameObject
|
||||
-- @field #boolean enabled Whether the object is enabled or disabled. Global scripts can set the value. Items in containers or inventories can't be disabled.
|
||||
-- @field openmw.util#Vector3 position Object position.
|
||||
-- @field openmw.util#Vector3 rotation Object rotation (ZXY order).
|
||||
-- @field #Cell cell The cell where the object currently is. During loading a game and for objects in an inventory or a container `cell` is nil.
|
||||
-- @field #table type Type of the object (one of the tables from the package @{openmw.types#types}).
|
||||
-- @field #number count Count (makes sense if stored in a container).
|
||||
-- @field #number count Count (>1 means a stack of objects).
|
||||
-- @field #string recordId Returns record ID of the object in lowercase.
|
||||
|
||||
---
|
||||
|
@ -163,13 +163,39 @@
|
|||
|
||||
---
|
||||
-- Moves object to given cell and position.
|
||||
-- Can be called only from a global script.
|
||||
-- The effect is not immediate: the position will be updated only in the next
|
||||
-- frame. Can be called only from a global script.
|
||||
-- frame. Can be called only from a global script. Enables object if it was disabled.
|
||||
-- Can be used to move objects from an inventory or a container to the world.
|
||||
-- @function [parent=#GameObject] teleport
|
||||
-- @param self
|
||||
-- @param #string cellName Name of the cell to teleport into. For exteriors can be empty.
|
||||
-- @param openmw.util#Vector3 position New position
|
||||
-- @param openmw.util#Vector3 rotation New rotation. Optional argument. If missed, then the current rotation is used.
|
||||
-- @param openmw.util#Vector3 rotation New rotation. Optional argument. If missing, then the current rotation is used.
|
||||
|
||||
---
|
||||
-- Moves object into a container or an inventory. Enables if was disabled.
|
||||
-- Can be called only from a global script.
|
||||
-- @function [parent=#GameObject] moveInto
|
||||
-- @param self
|
||||
-- @param #Inventory dest
|
||||
-- @usage item:moveInto(types.Actor.inventory(actor))
|
||||
|
||||
---
|
||||
-- Removes an object or reduces a stack of objects.
|
||||
-- Can be called only from a global script.
|
||||
-- @function [parent=#GameObject] remove
|
||||
-- @param self
|
||||
-- @param #number count (optional) the number of items to remove (if not specified then the whole stack)
|
||||
|
||||
---
|
||||
-- Splits a stack of items. Original stack is reduced by `count`. Returns a new stack with `count` items.
|
||||
-- Can be called only from a global script.
|
||||
-- @function [parent=#GameObject] split
|
||||
-- @param self
|
||||
-- @param #number count The number of items to return.
|
||||
-- @usage -- take 50 coins from `money` and put to the container `cont`
|
||||
-- money:split(50):moveInto(types.Container.content(cont))
|
||||
|
||||
|
||||
---
|
||||
|
@ -246,6 +272,22 @@
|
|||
-- local all = playerInventory:getAll()
|
||||
-- local weapons = playerInventory:getAll(types.Weapon)
|
||||
|
||||
---
|
||||
-- Get first item with given recordId from the inventory. Returns nil if not found.
|
||||
-- @function [parent=#Inventory] find
|
||||
-- @param self
|
||||
-- @param #string recordId
|
||||
-- @return #GameObject
|
||||
-- @usage inventory:find('gold_001')
|
||||
|
||||
---
|
||||
-- Get all items with given recordId from the inventory.
|
||||
-- @function [parent=#Inventory] findAll
|
||||
-- @param self
|
||||
-- @param #string recordId
|
||||
-- @return #ObjectList
|
||||
-- @usage for _, item in ipairs(inventory:findAll('common_shirt_01')) do ... end
|
||||
|
||||
|
||||
return nil
|
||||
|
||||
|
|
|
@ -59,5 +59,19 @@
|
|||
-- @function [parent=#world] isWorldPaused
|
||||
-- @return #boolean
|
||||
|
||||
---
|
||||
-- Create a new instance of the given record.
|
||||
-- After creation the object is in the disabled state. Use :teleport to place to the world or :moveInto to put it into a container or an inventory.
|
||||
-- @function [parent=#world] createObject
|
||||
-- @param #string recordId Record ID in lowercase
|
||||
-- @param #number count (optional, 1 by default) The number of objects in stack
|
||||
-- @return openmw.core#GameObject
|
||||
-- @usage -- put 100 gold on the ground at the position of `actor`
|
||||
-- money = world.createObject('gold_001', 100)
|
||||
-- money:teleport(actor.cell.name, actor.position)
|
||||
-- @usage -- put 50 gold into the actor's inventory
|
||||
-- money = world.createObject('gold_001', 50)
|
||||
-- money:moveInto(types.Actor.inventory(actor))
|
||||
|
||||
return nil
|
||||
|
||||
|
|
Loading…
Reference in a new issue