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