Handle getdistance on objects inside a container (Fixes #2046)

loadfix
MiroslavR 10 years ago
parent fa746b8e54
commit ed3a3f717f

@ -199,6 +199,10 @@ namespace MWBase
virtual MWWorld::Ptr searchPtrViaActorId (int actorId) = 0;
///< Search is limited to the active cells.
virtual MWWorld::Ptr findContainer (const MWWorld::Ptr& ptr) = 0;
///< Return a pointer to a liveCellRef which contains \a ptr.
/// \note Search is limited to the active cells.
/// \todo enable reference in the OGRE scene
virtual void enable (const MWWorld::Ptr& ptr) = 0;

@ -21,6 +21,7 @@
#include "../mwworld/class.hpp"
#include "../mwworld/cellstore.hpp"
#include "../mwworld/containerstore.hpp"
#include "../mwmechanics/npcstats.hpp"
@ -434,6 +435,16 @@ namespace MWScript
else
ref2 = MWBase::Environment::get().getWorld()->getPtr(id, false);
if (ref2.getContainerStore()) // is the object contained?
{
MWWorld::Ptr container = MWBase::Environment::get().getWorld()->findContainer(ref2);
if (!container.isEmpty())
ref2 = container;
else
throw std::runtime_error("failed to find container ptr");
}
const MWWorld::Ptr ref = MWBase::Environment::get().getWorld()->getPtr(name, false);
// If the objects are in different worldspaces, return a large value (just like vanilla)

@ -149,6 +149,17 @@ namespace MWWorld
forEachImp (functor, mCreatureLists);
}
template<class Functor>
bool forEachContainer (Functor& functor)
{
mHasState = true;
return
forEachImp (functor, mContainers) &&
forEachImp (functor, mCreatures) &&
forEachImp (functor, mNpcs);
}
bool isExterior() const;
Ptr searchInContainer (const std::string& id);

@ -272,7 +272,7 @@ MWWorld::ContainerStoreIterator MWWorld::ContainerStore::add (const Ptr& itemPtr
item.mCell = actorPtr.getCell();
}
item.mContainerStore = 0;
item.mContainerStore = this;
MWBase::Environment::get().getWorld()->getLocalScripts().add(script, item);

@ -657,6 +657,47 @@ namespace MWWorld
return mWorldScene->searchPtrViaActorId (actorId);
}
struct FindContainerFunctor
{
Ptr mContainedPtr;
Ptr mResult;
FindContainerFunctor(const Ptr& containedPtr) : mContainedPtr(containedPtr) {}
bool operator() (Ptr ptr)
{
if (mContainedPtr.getContainerStore() == &ptr.getClass().getContainerStore(ptr))
{
mResult = ptr;
return false;
}
return true;
}
};
Ptr World::findContainer(const Ptr& ptr)
{
if (ptr.isInCell())
return Ptr();
Ptr player = getPlayerPtr();
if (ptr.getContainerStore() == &player.getClass().getContainerStore(player))
return player;
const Scene::CellStoreCollection& collection = mWorldScene->getActiveCells();
for (Scene::CellStoreCollection::const_iterator cellIt = collection.begin(); cellIt != collection.end(); ++cellIt)
{
FindContainerFunctor functor(ptr);
(*cellIt)->forEachContainer(functor);
if (!functor.mResult.isEmpty())
return functor.mResult;
}
return Ptr();
}
void World::addContainerScripts(const Ptr& reference, CellStore * cell)
{
if( reference.getTypeName()==typeid (ESM::Container).name() ||

@ -260,6 +260,10 @@ namespace MWWorld
virtual Ptr searchPtrViaActorId (int actorId);
///< Search is limited to the active cells.
virtual MWWorld::Ptr findContainer (const MWWorld::Ptr& ptr);
///< Return a pointer to a liveCellRef which contains \a ptr.
/// \note Search is limited to the active cells.
virtual void adjustPosition (const Ptr& ptr, bool force);
///< Adjust position after load to be on ground. Must be called after model load.
/// @param force do this even if the ptr is flying

Loading…
Cancel
Save