Stolen item tracking overhaul part 2 (Fixes #2338)

celladd
scrawl 10 years ago
parent c1862cbfc2
commit bea88c3643

@ -138,9 +138,6 @@ namespace MWBase
/// @return was it illegal, and someone saw you doing it?
virtual bool sleepInBed (const MWWorld::Ptr& ptr, const MWWorld::Ptr& bed) = 0;
/// @return is \a ptr allowed to take/use \a item or is it a crime?
virtual bool isAllowedToUse (const MWWorld::Ptr& ptr, const MWWorld::Ptr& item, MWWorld::Ptr& victim) = 0;
enum PersuasionType
{
PT_Admire,
@ -205,6 +202,15 @@ namespace MWBase
virtual void keepPlayerAlive() = 0;
virtual bool isReadyToBlock (const MWWorld::Ptr& ptr) const = 0;
virtual void confiscateStolenItems (const MWWorld::Ptr& player, const MWWorld::Ptr& targetContainer) = 0;
/// List the owners that the player has stolen this item from (the owner can be an NPC or a faction).
/// <Owner, item count>
virtual std::vector<std::pair<std::string, int> > getStolenItemOwners(const std::string& itemid) = 0;
/// Has the player stolen this item from the given owner?
virtual bool isItemStolenFrom(const std::string& itemid, const std::string& ownerid) = 0;
};
}

@ -59,8 +59,10 @@ namespace MWClass
MWWorld::LiveCellRef<ESM::Container> *ref =
ptr.get<ESM::Container>();
// setting ownership not needed, since taking items from a container inherits the
// container's owner automatically
data->mContainerStore.fill(
ref->mBase->mInventory, ptr.getCellRef().getOwner(), ptr.getCellRef().getFaction(), ptr.getCellRef().getFactionRank(), MWBase::Environment::get().getWorld()->getStore());
ref->mBase->mInventory, "");
// store
ptr.getRefData().setCustomData (data.release());
@ -82,7 +84,10 @@ namespace MWClass
MWWorld::LiveCellRef<ESM::Container> *ref = ptr.get<ESM::Container>();
const ESM::InventoryList& list = ref->mBase->mInventory;
MWWorld::ContainerStore& store = getContainerStore(ptr);
store.restock(list, ptr, ptr.getCellRef().getOwner(), ptr.getCellRef().getFaction(), ptr.getCellRef().getFactionRank());
// setting ownership not needed, since taking items from a container inherits the
// container's owner automatically
store.restock(list, ptr, "");
}
void Container::insertObjectRendering (const MWWorld::Ptr& ptr, const std::string& model, MWRender::RenderingInterface& renderingInterface) const

@ -139,8 +139,7 @@ namespace MWClass
// store
ptr.getRefData().setCustomData(data.release());
getContainerStore(ptr).fill(ref->mBase->mInventory, getId(ptr), "", -1,
MWBase::Environment::get().getWorld()->getStore());
getContainerStore(ptr).fill(ref->mBase->mInventory, getId(ptr));
if (ref->mBase->mFlags & ESM::Creature::Weapon)
getInventoryStore(ptr).autoEquip(ptr);
@ -886,7 +885,7 @@ namespace MWClass
MWWorld::LiveCellRef<ESM::Creature> *ref = ptr.get<ESM::Creature>();
const ESM::InventoryList& list = ref->mBase->mInventory;
MWWorld::ContainerStore& store = getContainerStore(ptr);
store.restock(list, ptr, ptr.getCellRef().getRefId(), "", -1);
store.restock(list, ptr, ptr.getCellRef().getRefId());
}
int Creature::getBaseFightRating(const MWWorld::Ptr &ptr) const

@ -384,8 +384,8 @@ namespace MWClass
}
// inventory
data->mInventoryStore.fill(ref->mBase->mInventory, getId(ptr), "", -1,
MWBase::Environment::get().getWorld()->getStore());
// setting ownership is used to make the NPC auto-equip his initial equipment only, and not bartered items
data->mInventoryStore.fill(ref->mBase->mInventory, getId(ptr));
data->mNpcStats.setGoldPool(gold);
@ -1328,7 +1328,7 @@ namespace MWClass
MWWorld::LiveCellRef<ESM::NPC> *ref = ptr.get<ESM::NPC>();
const ESM::InventoryList& list = ref->mBase->mInventory;
MWWorld::ContainerStore& store = getContainerStore(ptr);
store.restock(list, ptr, ptr.getCellRef().getRefId(), "", -1);
store.restock(list, ptr, ptr.getCellRef().getRefId());
}
int Npc::getBaseFightRating (const MWWorld::Ptr& ptr) const

@ -339,7 +339,8 @@ namespace MWGui
for (int i=0; i<2; ++i)
{
MWWorld::Ptr item = (i == 0) ? mEnchanting.getOldItem() : mEnchanting.getGem();
if (Misc::StringUtils::ciEqual(item.getCellRef().getOwner(), mPtr.getCellRef().getRefId()))
if (MWBase::Environment::get().getMechanicsManager()->isItemStolenFrom(item.getCellRef().getRefId(),
mPtr.getCellRef().getRefId()))
{
std::string msg = MWBase::Environment::get().getWorld()->getStore().get<ESM::GameSetting>().find("sNotifyMessage49")->getString();
if (msg.find("%s") != std::string::npos)

@ -65,16 +65,7 @@ MWWorld::Ptr InventoryItemModel::moveItem(const ItemStack &item, size_t count, I
if (item.mFlags & ItemStack::Flag_Bound)
return MWWorld::Ptr();
bool setNewOwner = false;
// Are you dead? Then you wont need that anymore
if (mActor.getClass().isActor() && mActor.getClass().getCreatureStats(mActor).isDead()
// Make sure that the item is actually owned by the dead actor
// Prevents a potential exploit for resetting the owner of any item, by placing the item in a corpse
&& Misc::StringUtils::ciEqual(item.mBase.getCellRef().getOwner(), mActor.getCellRef().getRefId()))
setNewOwner = true;
MWWorld::Ptr ret = otherModel->copyItem(item, count, setNewOwner);
MWWorld::Ptr ret = otherModel->copyItem(item, count, false);
removeItem(item, count);
return ret;
}

@ -46,20 +46,27 @@ namespace MWGui
ItemModel();
virtual ~ItemModel() {}
typedef int ModelIndex;
typedef int ModelIndex; // -1 means invalid index
/// Throws for invalid index or out of range index
virtual ItemStack getItem (ModelIndex index) = 0;
///< throws for invalid index
/// The number of items in the model, this specifies the range of indices you can pass to
/// the getItem function (but this range is only valid until the next call to update())
virtual size_t getItemCount() = 0;
/// Returns an invalid index if the item was not found
virtual ModelIndex getIndex (ItemStack item) = 0;
/// Rebuild the item model, this will invalidate existing model indices
virtual void update() = 0;
/// Move items from this model to \a otherModel.
/// @note Derived implementations may return an empty Ptr if the move was unsuccessful.
virtual MWWorld::Ptr moveItem (const ItemStack& item, size_t count, ItemModel* otherModel);
/// @param setNewOwner Set the copied item's owner to the actor we are copying to, or keep the original owner?
/// @param setNewOwner If true, set the copied item's owner to the actor we are copying to,
/// otherwise reset owner to ""
virtual MWWorld::Ptr copyItem (const ItemStack& item, size_t count, bool setNewOwner=false) = 0;
virtual void removeItem (const ItemStack& item, size_t count) = 0;

@ -13,6 +13,7 @@
#include "../mwbase/world.hpp"
#include "../mwbase/environment.hpp"
#include "../mwbase/windowmanager.hpp"
#include "../mwbase/mechanicsmanager.hpp"
#include "../mwworld/class.hpp"
#include "../mwworld/esmstore.hpp"
@ -586,6 +587,15 @@ namespace MWGui
ret += getMiscString(cellref.getFaction(), "Faction");
if (cellref.getFactionRank() > 0)
ret += getValueString(cellref.getFactionRank(), "Rank");
std::vector<std::pair<std::string, int> > itemOwners =
MWBase::Environment::get().getMechanicsManager()->getStolenItemOwners(cellref.getRefId());
for (std::vector<std::pair<std::string, int> >::const_iterator it = itemOwners.begin(); it != itemOwners.end(); ++it)
{
ret += std::string("\nStolen ") + MyGUI::utility::toString(it->second) + " from " + it->first;
}
ret += getMiscString(cellref.getGlobalVariable(), "Global");
return ret;
}

@ -135,11 +135,9 @@ namespace MWGui
if (i == sourceModel->getItemCount())
throw std::runtime_error("The borrowed item disappeared");
// reset owner while copying, but only for items bought by the player
bool setNewOwner = (mMerchant.isEmpty());
const ItemStack& item = sourceModel->getItem(i);
// copy the borrowed items to our model
copyItem(item, it->mCount, setNewOwner);
copyItem(item, it->mCount);
// then remove them from the source model
sourceModel->removeItem(item, it->mCount);
}

@ -300,7 +300,8 @@ namespace MWGui
// check if the player is attempting to sell back an item stolen from this actor
for (std::vector<ItemStack>::iterator it = merchantBought.begin(); it != merchantBought.end(); ++it)
{
if (Misc::StringUtils::ciEqual(it->mBase.getCellRef().getOwner(), mPtr.getCellRef().getRefId()))
if (MWBase::Environment::get().getMechanicsManager()->isItemStolenFrom(it->mBase.getCellRef().getRefId(),
mPtr.getCellRef().getRefId()))
{
std::string msg = gmst.find("sNotifyMessage49")->getString();
if (msg.find("%s") != std::string::npos)
@ -315,6 +316,8 @@ namespace MWGui
}
}
// TODO: move to mwmechanics
// Is the player buying?
bool buying = (mCurrentMerchantOffer < 0);

@ -2,6 +2,8 @@
#include "mechanicsmanagerimp.hpp"
#include "npcstats.hpp"
#include <components/esm/stolenitems.hpp>
#include "../mwworld/esmstore.hpp"
#include "../mwworld/inventorystore.hpp"
@ -873,31 +875,31 @@ namespace MWMechanics
mAI = true;
}
bool MechanicsManager::isAllowedToUse (const MWWorld::Ptr& ptr, const MWWorld::Ptr& item, MWWorld::Ptr& victim)
bool MechanicsManager::isAllowedToUse (const MWWorld::Ptr& ptr, const MWWorld::CellRef& cellref, MWWorld::Ptr& victim)
{
const std::string& owner = item.getCellRef().getOwner();
const std::string& owner = cellref.getOwner();
bool isOwned = !owner.empty() && owner != "player";
const std::string& faction = item.getCellRef().getFaction();
const std::string& faction = cellref.getFaction();
bool isFactionOwned = false;
if (!faction.empty() && ptr.getClass().isNpc())
{
const std::map<std::string, int>& factions = ptr.getClass().getNpcStats(ptr).getFactionRanks();
std::map<std::string, int>::const_iterator found = factions.find(Misc::StringUtils::lowerCase(faction));
if (found == factions.end()
|| found->second < item.getCellRef().getFactionRank())
|| found->second < cellref.getFactionRank())
isFactionOwned = true;
}
const std::string& globalVariable = item.getCellRef().getGlobalVariable();
const std::string& globalVariable = cellref.getGlobalVariable();
if (!globalVariable.empty() && MWBase::Environment::get().getWorld()->getGlobalInt(Misc::StringUtils::lowerCase(globalVariable)) == 1)
{
isOwned = false;
isFactionOwned = false;
}
if (!item.getCellRef().getOwner().empty())
victim = MWBase::Environment::get().getWorld()->searchPtr(item.getCellRef().getOwner(), true);
if (!cellref.getOwner().empty())
victim = MWBase::Environment::get().getWorld()->searchPtr(cellref.getOwner(), true);
return (!isOwned && !isFactionOwned);
}
@ -916,7 +918,7 @@ namespace MWMechanics
}
MWWorld::Ptr victim;
if (isAllowedToUse(ptr, bed, victim))
if (isAllowedToUse(ptr, bed.getCellRef(), victim))
return false;
if(commitCrime(ptr, victim, OT_SleepingInOwnedBed))
@ -931,27 +933,82 @@ namespace MWMechanics
void MechanicsManager::objectOpened(const MWWorld::Ptr &ptr, const MWWorld::Ptr &item)
{
MWWorld::Ptr victim;
if (isAllowedToUse(ptr, item, victim))
if (isAllowedToUse(ptr, item.getCellRef(), victim))
return;
commitCrime(ptr, victim, OT_Trespassing);
}
std::vector<std::pair<std::string, int> > MechanicsManager::getStolenItemOwners(const std::string& itemid)
{
std::vector<std::pair<std::string, int> > result;
StolenItemsMap::const_iterator it = mStolenItems.find(Misc::StringUtils::lowerCase(itemid));
if (it == mStolenItems.end())
return result;
else
{
const OwnerMap& owners = it->second;
for (OwnerMap::const_iterator ownerIt = owners.begin(); ownerIt != owners.end(); ++ownerIt)
result.push_back(std::make_pair(ownerIt->first.first, ownerIt->second));
return result;
}
}
bool MechanicsManager::isItemStolenFrom(const std::string &itemid, const std::string &ownerid)
{
StolenItemsMap::const_iterator it = mStolenItems.find(Misc::StringUtils::lowerCase(itemid));
if (it == mStolenItems.end())
return false;
const OwnerMap& owners = it->second;
OwnerMap::const_iterator ownerFound = owners.find(std::make_pair(Misc::StringUtils::lowerCase(ownerid), false));
return ownerFound != owners.end();
}
void MechanicsManager::confiscateStolenItems(const MWWorld::Ptr &player, const MWWorld::Ptr &targetContainer)
{
MWWorld::ContainerStore& store = player.getClass().getContainerStore(player);
for (MWWorld::ContainerStoreIterator it = store.begin(); it != store.end(); ++it)
{
StolenItemsMap::iterator stolenIt = mStolenItems.find(Misc::StringUtils::lowerCase(it->getClass().getId(*it)));
if (stolenIt == mStolenItems.end())
continue;
OwnerMap& owners = stolenIt->second;
int itemCount = it->getRefData().getCount();
for (OwnerMap::iterator ownerIt = owners.begin(); ownerIt != owners.end();)
{
int toRemove = std::min(itemCount, ownerIt->second);
itemCount -= toRemove;
ownerIt->second -= toRemove;
if (ownerIt->second == 0)
owners.erase(ownerIt++);
else
++ownerIt;
}
int toMove = it->getRefData().getCount() - itemCount;
targetContainer.getClass().getContainerStore(targetContainer).add(*it, toMove, targetContainer);
store.remove(*it, toMove, player);
}
// TODO: unhardcode the locklevel
targetContainer.getClass().lock(targetContainer,50);
}
void MechanicsManager::itemTaken(const MWWorld::Ptr &ptr, const MWWorld::Ptr &item, const MWWorld::Ptr& container,
int count)
{
if (ptr != MWBase::Environment::get().getWorld()->getPlayerPtr())
return;
MWWorld::Ptr victim;
const MWWorld::CellRef* ownerCellRef = &item.getCellRef();
if (!container.isEmpty())
{
// Inherit the owner of the container
if (isAllowedToUse(ptr, container, victim))
return;
ownerCellRef = &container.getCellRef();
}
else
{
if (isAllowedToUse(ptr, item, victim))
return;
if (!item.getCellRef().hasContentFile())
{
// this is a manually placed item, which means it was already stolen
@ -959,6 +1016,20 @@ namespace MWMechanics
}
}
if (isAllowedToUse(ptr, *ownerCellRef, victim))
return;
Owner owner;
owner.first = ownerCellRef->getOwner();
owner.second = false;
if (owner.first.empty())
{
owner.first = ownerCellRef->getFaction();
owner.second = true;
}
Misc::StringUtils::toLower(owner.first);
mStolenItems[Misc::StringUtils::lowerCase(item.getClass().getId(item))][owner] += count;
commitCrime(ptr, victim, OT_Theft, item.getClass().getValue(item) * count);
}
@ -967,7 +1038,7 @@ namespace MWMechanics
// NOTE: victim may be empty
// Only player can commit crime
if (player.getRefData().getHandle() != "player")
if (player != MWBase::Environment::get().getWorld()->getPlayerPtr())
return false;
// Find all the actors within the alarm radius
@ -1369,22 +1440,37 @@ namespace MWMechanics
int MechanicsManager::countSavedGameRecords() const
{
return 1; // Death counter
return 1 // Death counter
+1; // Stolen items
}
void MechanicsManager::write(ESM::ESMWriter &writer, Loading::Listener &listener) const
{
mActors.write(writer, listener);
ESM::StolenItems items;
items.mStolenItems = mStolenItems;
writer.startRecord(ESM::REC_STLN);
items.write(writer);
writer.endRecord(ESM::REC_STLN);
}
void MechanicsManager::readRecord(ESM::ESMReader &reader, uint32_t type)
{
mActors.readRecord(reader, type);
if (type == ESM::REC_STLN)
{
ESM::StolenItems items;
items.load(reader);
mStolenItems = items.mStolenItems;
}
else
mActors.readRecord(reader, type);
}
void MechanicsManager::clear()
{
mActors.clear();
mStolenItems.clear();
}
bool MechanicsManager::isAggressive(const MWWorld::Ptr &ptr, const MWWorld::Ptr &target)

@ -35,6 +35,11 @@ namespace MWMechanics
Objects mObjects;
Actors mActors;
typedef std::pair<std::string, bool> Owner; // < Owner id, bool isFaction >
typedef std::map<Owner, int> OwnerMap; // < Owner, number of stolen items with this id from this owner >
typedef std::map<std::string, OwnerMap> StolenItemsMap;
StolenItemsMap mStolenItems;
public:
void buildPlayer();
@ -130,9 +135,6 @@ namespace MWMechanics
/// @return was it illegal, and someone saw you doing it? Also returns fail when enemies are nearby
virtual bool sleepInBed (const MWWorld::Ptr& ptr, const MWWorld::Ptr& bed);
/// @return is \a ptr allowed to take/use \a item or is it a crime?
virtual bool isAllowedToUse (const MWWorld::Ptr& ptr, const MWWorld::Ptr& item, MWWorld::Ptr& victim);
virtual void forceStateUpdate(const MWWorld::Ptr &ptr);
virtual void playAnimationGroup(const MWWorld::Ptr& ptr, const std::string& groupName, int mode, int number);
@ -170,9 +172,21 @@ namespace MWMechanics
virtual bool isReadyToBlock (const MWWorld::Ptr& ptr) const;
virtual void confiscateStolenItems (const MWWorld::Ptr& player, const MWWorld::Ptr& targetContainer);
/// List the owners that the player has stolen this item from (the owner can be an NPC or a faction).
/// <Owner, item count>
virtual std::vector<std::pair<std::string, int> > getStolenItemOwners(const std::string& itemid);
/// Has the player stolen this item from the given owner?
virtual bool isItemStolenFrom(const std::string& itemid, const std::string& ownerid);
private:
void reportCrime (const MWWorld::Ptr& ptr, const MWWorld::Ptr& victim,
OffenseType type, int arg=0);
/// @return is \a ptr allowed to take/use \a cellref or is it a crime?
virtual bool isAllowedToUse (const MWWorld::Ptr& ptr, const MWWorld::CellRef& cellref, MWWorld::Ptr& victim);
};
}

@ -421,6 +421,7 @@ void MWState::StateManager::loadGame (const Character *character, const std::str
break;
case ESM::REC_DCOU:
case ESM::REC_STLN:
MWBase::Environment::get().getMechanicsManager()->readRecord(reader, n.val);
break;

@ -117,6 +117,15 @@ namespace MWWorld
return mCellRef.mGlobalVariable;
}
void CellRef::resetGlobalVariable()
{
if (!mCellRef.mGlobalVariable.empty())
{
mChanged = true;
mCellRef.mGlobalVariable.erase();
}
}
void CellRef::setFactionRank(int factionRank)
{
if (factionRank != mCellRef.mFactionRank)

@ -75,6 +75,8 @@ namespace MWWorld
// Used by bed rent scripts to allow the player to use the bed for the duration of the rent.
std::string getGlobalVariable() const;
void resetGlobalVariable();
// ID of creature trapped in this soul gem
std::string getSoul() const;
void setSoul(const std::string& soul);

@ -80,6 +80,8 @@ namespace MWWorld
virtual std::string getId (const Ptr& ptr) const;
///< Return ID of \a ptr or throw an exception, if class does not support ID retrieval
/// (default implementation: throw an exception)
/// @note This function is currently redundant; the same ID can be retrieved by CellRef::getRefId.
/// Leaving it here for now in case we want to optimize later.
virtual void insertObjectRendering (const Ptr& ptr, const std::string& mesh, MWRender::RenderingInterface& renderingInterface) const;
virtual void insertObject(const Ptr& ptr, const std::string& mesh, MWWorld::PhysicsSystem& physics) const;

@ -222,29 +222,22 @@ MWWorld::ContainerStoreIterator MWWorld::ContainerStore::add (const Ptr& itemPtr
MWWorld::ContainerStoreIterator it = end();
if (setOwner && actorPtr.getClass().isActor())
// HACK: Set owner on the original item, then reset it after we have copied it
// If we set the owner on the copied item, it would not stack correctly...
std::string oldOwner = itemPtr.getCellRef().getOwner();
if (!setOwner || actorPtr == MWBase::Environment::get().getWorld()->getPlayerPtr()) // No point in setting owner to the player - NPCs will not respect this anyway
{
// HACK: Set owner on the original item, then reset it after we have copied it
// If we set the owner on the copied item, it would not stack correctly...
std::string oldOwner = itemPtr.getCellRef().getOwner();
if (actorPtr == player)
{
// No point in setting owner to the player - NPCs will not respect this anyway
// Additionally, setting it to "player" would make those items not stack with items that don't have an owner
itemPtr.getCellRef().setOwner("");
}
else
itemPtr.getCellRef().setOwner(actorPtr.getCellRef().getRefId());
it = addImp(itemPtr, count);
itemPtr.getCellRef().setOwner(oldOwner);
itemPtr.getCellRef().setOwner("");
}
else
{
it = addImp(itemPtr, count);
itemPtr.getCellRef().setOwner(actorPtr.getCellRef().getRefId());
}
it = addImp(itemPtr, count);
itemPtr.getCellRef().setOwner(oldOwner);
// The copy of the original item we just made
MWWorld::Ptr item = *it;
@ -258,6 +251,14 @@ MWWorld::ContainerStoreIterator MWWorld::ContainerStore::add (const Ptr& itemPtr
pos.pos[1] = 0;
pos.pos[2] = 0;
item.getCellRef().setPosition(pos);
// reset ownership stuff, owner was already handled above
item.getCellRef().resetGlobalVariable();
item.getCellRef().setFaction("");
item.getCellRef().setFactionRank(-1);
// must reset the RefNum on the copied item, so that the RefNum on the original item stays unique
// maybe we should do this in the copy constructor instead?
item.getCellRef().unsetRefNum(); // destroy link to content file
std::string script = item.getClass().getScript(item);
@ -399,19 +400,19 @@ int MWWorld::ContainerStore::remove(const Ptr& item, int count, const Ptr& actor
return count - toRemove;
}
void MWWorld::ContainerStore::fill (const ESM::InventoryList& items, const std::string& owner, const std::string& faction, int factionRank, const MWWorld::ESMStore& store)
void MWWorld::ContainerStore::fill (const ESM::InventoryList& items, const std::string& owner)
{
for (std::vector<ESM::ContItem>::const_iterator iter (items.mList.begin()); iter!=items.mList.end();
++iter)
{
std::string id = Misc::StringUtils::lowerCase(iter->mItem.toString());
addInitialItem(id, owner, faction, factionRank, iter->mCount);
addInitialItem(id, owner, iter->mCount);
}
flagAsModified();
}
void MWWorld::ContainerStore::addInitialItem (const std::string& id, const std::string& owner, const std::string& faction, int factionRank,
void MWWorld::ContainerStore::addInitialItem (const std::string& id, const std::string& owner,
int count, bool topLevel, const std::string& levItem)
{
ManualRef ref (MWBase::Environment::get().getWorld()->getStore(), id, count);
@ -423,7 +424,7 @@ void MWWorld::ContainerStore::addInitialItem (const std::string& id, const std::
if (topLevel && std::abs(count) > 1 && levItem->mFlags & ESM::ItemLevList::Each)
{
for (int i=0; i<std::abs(count); ++i)
addInitialItem(id, owner, faction, factionRank, count > 0 ? 1 : -1, true, levItem->mId);
addInitialItem(id, owner, count > 0 ? 1 : -1, true, levItem->mId);
return;
}
else
@ -431,7 +432,7 @@ void MWWorld::ContainerStore::addInitialItem (const std::string& id, const std::
std::string id = MWMechanics::getLevelledItem(ref.getPtr().get<ESM::ItemLevList>()->mBase, false);
if (id.empty())
return;
addInitialItem(id, owner, faction, factionRank, count, false, levItem->mId);
addInitialItem(id, owner, count, false, levItem->mId);
}
}
else
@ -447,13 +448,11 @@ void MWWorld::ContainerStore::addInitialItem (const std::string& id, const std::
count = std::abs(count);
ref.getPtr().getCellRef().setOwner(owner);
ref.getPtr().getCellRef().setFaction(faction);
ref.getPtr().getCellRef().setFactionRank(factionRank);
addImp (ref.getPtr(), count);
}
}
void MWWorld::ContainerStore::restock (const ESM::InventoryList& items, const MWWorld::Ptr& ptr, const std::string& owner, const std::string& faction, int factionRank)
void MWWorld::ContainerStore::restock (const ESM::InventoryList& items, const MWWorld::Ptr& ptr, const std::string& owner)
{
// Remove the items already spawned by levelled items that will restock
for (std::map<std::string, int>::iterator it = mLevelledItemMap.begin(); it != mLevelledItemMap.end(); ++it)
@ -472,13 +471,13 @@ void MWWorld::ContainerStore::restock (const ESM::InventoryList& items, const MW
if (MWBase::Environment::get().getWorld()->getStore().get<ESM::ItemLevList>().search(it->mItem.toString()))
{
addInitialItem(item, owner, faction, factionRank, it->mCount, true);
addInitialItem(item, owner, it->mCount, true);
}
else
{
int currentCount = count(item);
if (currentCount < std::abs(it->mCount))
addInitialItem(item, owner, faction, factionRank, std::abs(it->mCount) - currentCount, true);
addInitialItem(item, owner, std::abs(it->mCount) - currentCount, true);
}
}
flagAsModified();

@ -75,7 +75,7 @@ namespace MWWorld
mutable float mCachedWeight;
mutable bool mWeightUpToDate;
ContainerStoreIterator addImp (const Ptr& ptr, int count);
void addInitialItem (const std::string& id, const std::string& owner, const std::string& faction, int factionRank, int count, bool topLevel=true, const std::string& levItem = "");
void addInitialItem (const std::string& id, const std::string& owner, int count, bool topLevel=true, const std::string& levItem = "");
template<typename T>
ContainerStoreIterator getState (CellRefList<T>& collection,
@ -112,7 +112,7 @@ namespace MWWorld
/// \attention Do not add items to an existing stack by increasing the count instead of
/// calling this function!
///
/// @param setOwner Set the owner of the added item to \a actorPtr?
/// @param setOwner Set the owner of the added item to \a actorPtr? If false, the owner is reset to "".
///
/// @return if stacking happened, return iterator to the item that was stacked against, otherwise iterator to the newly inserted item.
@ -151,10 +151,10 @@ namespace MWWorld
virtual bool stacks (const Ptr& ptr1, const Ptr& ptr2);
///< @return true if the two specified objects can stack with each other
void fill (const ESM::InventoryList& items, const std::string& owner, const std::string& faction, int factionRank, const MWWorld::ESMStore& store);
void fill (const ESM::InventoryList& items, const std::string& owner);
///< Insert items into *this.
void restock (const ESM::InventoryList& items, const MWWorld::Ptr& ptr, const std::string& owner, const std::string& faction, int factionRank);
void restock (const ESM::InventoryList& items, const MWWorld::Ptr& ptr, const std::string& owner);
virtual void clear();
///< Empty container.

@ -2980,18 +2980,10 @@ namespace MWWorld
if (!closestChest.isEmpty()) //Found a close chest
{
ContainerStore& store = ptr.getClass().getContainerStore(ptr);
for (ContainerStoreIterator it = store.begin(); it != store.end(); ++it) //Move all stolen stuff into chest
{
MWWorld::Ptr dummy;
if (!MWBase::Environment::get().getMechanicsManager()->isAllowedToUse(getPlayerPtr(), *it, dummy))
{
closestChest.getClass().getContainerStore(closestChest).add(*it, it->getRefData().getCount(), closestChest);
store.remove(*it, it->getRefData().getCount(), ptr);
}
}
closestChest.getClass().lock(closestChest,50);
MWBase::Environment::get().getMechanicsManager()->confiscateStolenItems(ptr, closestChest);
}
else
std::cerr << "Failed to confiscate items: no stolen_goods container found" << std::endl;
}
void World::goToJail()

@ -63,7 +63,7 @@ add_component_dir (esm
loadweap records aipackage effectlist spelllist variant variantimp loadtes3 cellref filter
savedgame journalentry queststate locals globalscript player objectstate cellid cellstate globalmap inventorystate containerstate npcstate creaturestate dialoguestate statstate
npcstats creaturestats weatherstate quickkeys fogstate spellstate activespells creaturelevliststate doorstate projectilestate debugprofile
aisequence magiceffects util custommarkerstate
aisequence magiceffects util custommarkerstate stolenitems
)
add_component_dir (esmterrain

@ -117,6 +117,7 @@ enum RecNameInts
REC_MARK = FourCC<'M','A','R','K'>::value,
REC_ENAB = FourCC<'E','N','A','B'>::value,
REC_CAM_ = FourCC<'C','A','M','_'>::value,
REC_STLN = FourCC<'S','T','L','N'>::value,
// format 1
REC_FILT = FourCC<'F','I','L','T'>::value,

@ -0,0 +1,47 @@
#include "stolenitems.hpp"
#include <components/esm/esmreader.hpp>
#include <components/esm/esmwriter.hpp>
namespace ESM
{
void StolenItems::write(ESMWriter &esm) const
{
for (StolenItemsMap::const_iterator it = mStolenItems.begin(); it != mStolenItems.end(); ++it)
{
esm.writeHNString("NAME", it->first);
for (std::map<std::pair<std::string, bool>, int>::const_iterator ownerIt = it->second.begin();
ownerIt != it->second.end(); ++ownerIt)
{
if (ownerIt->first.second)
esm.writeHNString("FNAM", ownerIt->first.first);
else
esm.writeHNString("ONAM", ownerIt->first.first);
esm.writeHNT("COUN", ownerIt->second);
}
}
}
void StolenItems::load(ESMReader &esm)
{
while (esm.isNextSub("NAME"))
{
std::string itemid = esm.getHString();
std::map<std::pair<std::string, bool>, int> ownerMap;
while (esm.isNextSub("FNAM") || esm.isNextSub("ONAM"))
{
std::string subname = esm.retSubName().toString();
std::string owner = esm.getHString();
bool isFaction = (subname == "FNAM");
int count;
esm.getHNT(count, "COUN");
ownerMap.insert(std::make_pair(std::make_pair(owner, isFaction), count));
}
mStolenItems[itemid] = ownerMap;
}
}
}

@ -0,0 +1,24 @@
#ifndef OPENMW_COMPONENTS_ESM_STOLENITEMS_H
#define OPENMW_COMPONENTS_ESM_STOLENITEMS_H
#include <map>
#include <string>
namespace ESM
{
class ESMReader;
class ESMWriter;
// format 0, saved games only
struct StolenItems
{
typedef std::map<std::string, std::map<std::pair<std::string, bool>, int> > StolenItemsMap;
StolenItemsMap mStolenItems;
void load(ESM::ESMReader& esm);
void write(ESM::ESMWriter& esm) const;
};
}
#endif
Loading…
Cancel
Save