forked from mirror/openmw-tes3mp
Merge remote-tracking branch 'zini/master' into ptr-improvements
Conflicts: apps/openmw/mwworld/containerstore.cpp
This commit is contained in:
commit
fdbf09ed40
6 changed files with 111 additions and 37 deletions
|
@ -48,7 +48,7 @@ MWWorld::Ptr MWWorld::Cells::getPtrAndCache (const std::string& name, Ptr::CellS
|
|||
{
|
||||
Ptr ptr = getPtr (name, cellStore);
|
||||
|
||||
if (!ptr.isEmpty())
|
||||
if (!ptr.isEmpty() && ptr.isInCell())
|
||||
{
|
||||
mIdCache[mIdCacheIndex].first = name;
|
||||
mIdCache[mIdCacheIndex].second = &cellStore;
|
||||
|
@ -121,7 +121,8 @@ MWWorld::Ptr::CellStore *MWWorld::Cells::getInterior (const std::string& name)
|
|||
return &result->second;
|
||||
}
|
||||
|
||||
MWWorld::Ptr MWWorld::Cells::getPtr (const std::string& name, Ptr::CellStore& cell)
|
||||
MWWorld::Ptr MWWorld::Cells::getPtr (const std::string& name, Ptr::CellStore& cell,
|
||||
bool searchInContainers)
|
||||
{
|
||||
if (cell.mState==Ptr::CellStore::State_Unloaded)
|
||||
cell.preload (mStore, mReader);
|
||||
|
@ -138,71 +139,69 @@ MWWorld::Ptr MWWorld::Cells::getPtr (const std::string& name, Ptr::CellStore& ce
|
|||
return Ptr();
|
||||
}
|
||||
|
||||
MWWorld::Ptr ptr;
|
||||
|
||||
if (MWWorld::LiveCellRef<ESM::Activator> *ref = cell.mActivators.find (name))
|
||||
ptr = Ptr (ref, &cell);
|
||||
return Ptr (ref, &cell);
|
||||
|
||||
if (MWWorld::LiveCellRef<ESM::Potion> *ref = cell.mPotions.find (name))
|
||||
ptr = Ptr (ref, &cell);
|
||||
return Ptr (ref, &cell);
|
||||
|
||||
if (MWWorld::LiveCellRef<ESM::Apparatus> *ref = cell.mAppas.find (name))
|
||||
ptr = Ptr (ref, &cell);
|
||||
return Ptr (ref, &cell);
|
||||
|
||||
if (MWWorld::LiveCellRef<ESM::Armor> *ref = cell.mArmors.find (name))
|
||||
ptr = Ptr (ref, &cell);
|
||||
return Ptr (ref, &cell);
|
||||
|
||||
if (MWWorld::LiveCellRef<ESM::Book> *ref = cell.mBooks.find (name))
|
||||
ptr = Ptr (ref, &cell);
|
||||
return Ptr (ref, &cell);
|
||||
|
||||
if (MWWorld::LiveCellRef<ESM::Clothing> *ref = cell.mClothes.find (name))
|
||||
ptr = Ptr (ref, &cell);
|
||||
return Ptr (ref, &cell);
|
||||
|
||||
if (MWWorld::LiveCellRef<ESM::Container> *ref = cell.mContainers.find (name))
|
||||
ptr = Ptr (ref, &cell);
|
||||
return Ptr (ref, &cell);
|
||||
|
||||
if (MWWorld::LiveCellRef<ESM::Creature> *ref = cell.mCreatures.find (name))
|
||||
ptr = Ptr (ref, &cell);
|
||||
return Ptr (ref, &cell);
|
||||
|
||||
if (MWWorld::LiveCellRef<ESM::Door> *ref = cell.mDoors.find (name))
|
||||
ptr = Ptr (ref, &cell);
|
||||
return Ptr (ref, &cell);
|
||||
|
||||
if (MWWorld::LiveCellRef<ESM::Ingredient> *ref = cell.mIngreds.find (name))
|
||||
ptr = Ptr (ref, &cell);
|
||||
return Ptr (ref, &cell);
|
||||
|
||||
if (MWWorld::LiveCellRef<ESM::CreatureLevList> *ref = cell.mCreatureLists.find (name))
|
||||
ptr = Ptr (ref, &cell);
|
||||
return Ptr (ref, &cell);
|
||||
|
||||
if (MWWorld::LiveCellRef<ESM::ItemLevList> *ref = cell.mItemLists.find (name))
|
||||
ptr = Ptr (ref, &cell);
|
||||
return Ptr (ref, &cell);
|
||||
|
||||
if (MWWorld::LiveCellRef<ESM::Light> *ref = cell.mLights.find (name))
|
||||
ptr = Ptr (ref, &cell);
|
||||
return Ptr (ref, &cell);
|
||||
|
||||
if (MWWorld::LiveCellRef<ESM::Lockpick> *ref = cell.mLockpicks.find (name))
|
||||
ptr = Ptr (ref, &cell);
|
||||
return Ptr (ref, &cell);
|
||||
|
||||
if (MWWorld::LiveCellRef<ESM::Miscellaneous> *ref = cell.mMiscItems.find (name))
|
||||
ptr = Ptr (ref, &cell);
|
||||
return Ptr (ref, &cell);
|
||||
|
||||
if (MWWorld::LiveCellRef<ESM::NPC> *ref = cell.mNpcs.find (name))
|
||||
ptr = Ptr (ref, &cell);
|
||||
return Ptr (ref, &cell);
|
||||
|
||||
if (MWWorld::LiveCellRef<ESM::Probe> *ref = cell.mProbes.find (name))
|
||||
ptr = Ptr (ref, &cell);
|
||||
return Ptr (ref, &cell);
|
||||
|
||||
if (MWWorld::LiveCellRef<ESM::Repair> *ref = cell.mRepairs.find (name))
|
||||
ptr = Ptr (ref, &cell);
|
||||
return Ptr (ref, &cell);
|
||||
|
||||
if (MWWorld::LiveCellRef<ESM::Static> *ref = cell.mStatics.find (name))
|
||||
ptr = Ptr (ref, &cell);
|
||||
return Ptr (ref, &cell);
|
||||
|
||||
if (MWWorld::LiveCellRef<ESM::Weapon> *ref = cell.mWeapons.find (name))
|
||||
ptr = Ptr (ref, &cell);
|
||||
return Ptr (ref, &cell);
|
||||
|
||||
if (searchInContainers)
|
||||
return cell.searchInContainer (name);
|
||||
|
||||
if (!ptr.isEmpty() && ptr.getRefData().getCount() > 0) {
|
||||
return ptr;
|
||||
}
|
||||
return Ptr();
|
||||
}
|
||||
|
||||
|
|
|
@ -45,7 +45,8 @@ namespace MWWorld
|
|||
|
||||
CellStore *getInterior (const std::string& name);
|
||||
|
||||
Ptr getPtr (const std::string& name, CellStore& cellStore);
|
||||
Ptr getPtr (const std::string& name, CellStore& cellStore, bool searchInContainers = false);
|
||||
///< \param searchInContainers Only affect loaded cells.
|
||||
|
||||
Ptr getPtr (const std::string& name);
|
||||
};
|
||||
|
|
|
@ -7,6 +7,29 @@
|
|||
|
||||
#include "ptr.hpp"
|
||||
#include "esmstore.hpp"
|
||||
#include "class.hpp"
|
||||
#include "containerstore.hpp"
|
||||
|
||||
namespace
|
||||
{
|
||||
template<typename T>
|
||||
MWWorld::Ptr searchInContainerList (MWWorld::CellRefList<T>& containerList, const std::string& id)
|
||||
{
|
||||
for (typename MWWorld::CellRefList<T>::List::iterator iter (containerList.mList.begin());
|
||||
iter!=containerList.mList.end(); ++iter)
|
||||
{
|
||||
MWWorld::Ptr container (&*iter, 0);
|
||||
|
||||
MWWorld::Ptr ptr =
|
||||
MWWorld::Class::get (container).getContainerStore (container).search (id);
|
||||
|
||||
if (!ptr.isEmpty())
|
||||
return ptr;
|
||||
}
|
||||
|
||||
return MWWorld::Ptr();
|
||||
}
|
||||
}
|
||||
|
||||
namespace MWWorld
|
||||
{
|
||||
|
@ -16,14 +39,14 @@ namespace MWWorld
|
|||
{
|
||||
// Get existing reference, in case we need to overwrite it.
|
||||
typename std::list<LiveRef>::iterator iter = std::find(mList.begin(), mList.end(), ref.mRefnum);
|
||||
|
||||
|
||||
// Skip this when reference was deleted.
|
||||
// TODO: Support respawning references, in this case, we need to track it somehow.
|
||||
if (ref.mDeleted) {
|
||||
mList.erase(iter);
|
||||
return;
|
||||
}
|
||||
|
||||
|
||||
// for throwing exception on unhandled record type
|
||||
const MWWorld::Store<X> &store = esmStore.get<X>();
|
||||
const X *ptr = store.search(ref.mRefID);
|
||||
|
@ -39,7 +62,7 @@ namespace MWWorld
|
|||
mList.push_back(LiveRef(ref, ptr));
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
template<typename X> bool operator==(const LiveCellRef<X>& ref, int pRefnum)
|
||||
{
|
||||
return (ref.mRef.mRefnum == pRefnum);
|
||||
|
@ -133,7 +156,7 @@ namespace MWWorld
|
|||
ESM::MovedCellRefTracker::const_iterator iter = std::find(mCell->mMovedRefs.begin(), mCell->mMovedRefs.end(), ref.mRefnum);
|
||||
if (iter != mCell->mMovedRefs.end()) {
|
||||
continue;
|
||||
}
|
||||
}
|
||||
int rec = store.find(ref.mRefID);
|
||||
|
||||
ref.mRefID = lowerCase;
|
||||
|
@ -186,7 +209,7 @@ namespace MWWorld
|
|||
(int(*)(int)) std::tolower);
|
||||
|
||||
int rec = store.find(ref.mRefID);
|
||||
|
||||
|
||||
ref.mRefID = lowerCase;
|
||||
|
||||
/* We can optimize this further by storing the pointer to the
|
||||
|
@ -221,7 +244,33 @@ namespace MWWorld
|
|||
default:
|
||||
std::cout << "WARNING: Ignoring reference '" << ref.mRefID << "' of unhandled type\n";
|
||||
}
|
||||
|
||||
|
||||
}
|
||||
}
|
||||
|
||||
Ptr CellStore::searchInContainer (const std::string& id)
|
||||
{
|
||||
{
|
||||
Ptr ptr = searchInContainerList (mContainers, id);
|
||||
|
||||
if (!ptr.isEmpty())
|
||||
return ptr;
|
||||
}
|
||||
|
||||
{
|
||||
Ptr ptr = searchInContainerList (mCreatures, id);
|
||||
|
||||
if (!ptr.isEmpty())
|
||||
return ptr;
|
||||
}
|
||||
|
||||
{
|
||||
Ptr ptr = searchInContainerList (mNpcs, id);
|
||||
|
||||
if (!ptr.isEmpty())
|
||||
return ptr;
|
||||
}
|
||||
|
||||
return Ptr();
|
||||
}
|
||||
}
|
||||
|
|
|
@ -131,6 +131,8 @@ namespace MWWorld
|
|||
return mCell->isExterior();
|
||||
}
|
||||
|
||||
Ptr searchInContainer (const std::string& id);
|
||||
|
||||
private:
|
||||
|
||||
template<class Functor, class List>
|
||||
|
@ -148,6 +150,7 @@ namespace MWWorld
|
|||
void listRefs(const MWWorld::ESMStore &store, std::vector<ESM::ESMReader> &esm);
|
||||
|
||||
void loadRefs(const MWWorld::ESMStore &store, std::vector<ESM::ESMReader> &esm);
|
||||
|
||||
};
|
||||
}
|
||||
|
||||
|
|
|
@ -9,6 +9,7 @@
|
|||
|
||||
#include <components/esm/loadcont.hpp>
|
||||
#include <components/compiler/locals.hpp>
|
||||
#include <components/misc/stringops.hpp>
|
||||
|
||||
#include "../mwbase/environment.hpp"
|
||||
#include "../mwbase/world.hpp"
|
||||
|
@ -85,12 +86,12 @@ MWWorld::ContainerStoreIterator MWWorld::ContainerStore::add (const Ptr& itemPtr
|
|||
CellStore *cell;
|
||||
|
||||
Ptr player = MWBase::Environment::get().getWorld ()->getPlayer().getPlayer();
|
||||
|
||||
|
||||
if(&(MWWorld::Class::get (player).getContainerStore (player)) == this)
|
||||
{
|
||||
cell = 0; // Items in player's inventory have cell set to 0, so their scripts will never be removed
|
||||
|
||||
// Set OnPCAdd special variable, if it is declared
|
||||
|
||||
// Set OnPCAdd special variable, if it is declared
|
||||
item.getRefData().getLocals().setVarByInt(script, "onpcadd", 1);
|
||||
}
|
||||
else
|
||||
|
@ -347,6 +348,25 @@ int MWWorld::ContainerStore::getType (const Ptr& ptr)
|
|||
"Object of type " + ptr.getTypeName() + " can not be placed into a container");
|
||||
}
|
||||
|
||||
MWWorld::Ptr MWWorld::ContainerStore::search (const std::string& id)
|
||||
{
|
||||
/// \todo Since we have direct access to the CellRefList here, the performance of this function
|
||||
/// could be improved notably by iterating directly over the CellRefLists instead of using
|
||||
/// a ContainerStoreIterator.
|
||||
|
||||
std::string id2 = Misc::StringUtils::lowerCase (id);
|
||||
|
||||
for (ContainerStoreIterator iter (this); iter!=end(); ++iter)
|
||||
{
|
||||
Ptr ptr = *iter;
|
||||
|
||||
if (Misc::StringUtils::lowerCase (Class::get (ptr).getId (ptr))==id2)
|
||||
return ptr;
|
||||
}
|
||||
|
||||
return Ptr();
|
||||
}
|
||||
|
||||
|
||||
MWWorld::ContainerStoreIterator::ContainerStoreIterator (ContainerStore *container)
|
||||
: mType (-1), mMask (0), mContainer (container)
|
||||
|
|
|
@ -106,6 +106,8 @@ namespace MWWorld
|
|||
///< This function throws an exception, if ptr does not point to an object, that can be
|
||||
/// put into a container.
|
||||
|
||||
Ptr search (const std::string& id);
|
||||
|
||||
friend class ContainerStoreIterator;
|
||||
};
|
||||
|
||||
|
|
Loading…
Reference in a new issue