mirror of
https://gitlab.com/OpenMW/openmw.git
synced 2025-03-12 04:14:05 +00:00
accessing references via their ID now also works for references in containers in active cells
This commit is contained in:
parent
aee0336780
commit
e94fcce622
@ -48,7 +48,7 @@ MWWorld::Ptr MWWorld::Cells::getPtrAndCache (const std::string& name, Ptr::CellS
|
|||||||
{
|
{
|
||||||
Ptr ptr = getPtr (name, cellStore);
|
Ptr ptr = getPtr (name, cellStore);
|
||||||
|
|
||||||
if (!ptr.isEmpty())
|
if (!ptr.isEmpty() && ptr.isInCell())
|
||||||
{
|
{
|
||||||
mIdCache[mIdCacheIndex].first = name;
|
mIdCache[mIdCacheIndex].first = name;
|
||||||
mIdCache[mIdCacheIndex].second = &cellStore;
|
mIdCache[mIdCacheIndex].second = &cellStore;
|
||||||
@ -121,7 +121,8 @@ MWWorld::Ptr::CellStore *MWWorld::Cells::getInterior (const std::string& name)
|
|||||||
return &result->second;
|
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)
|
if (cell.mState==Ptr::CellStore::State_Unloaded)
|
||||||
cell.preload (mStore, mReader);
|
cell.preload (mStore, mReader);
|
||||||
@ -138,71 +139,69 @@ MWWorld::Ptr MWWorld::Cells::getPtr (const std::string& name, Ptr::CellStore& ce
|
|||||||
return Ptr();
|
return Ptr();
|
||||||
}
|
}
|
||||||
|
|
||||||
MWWorld::Ptr ptr;
|
|
||||||
|
|
||||||
if (MWWorld::LiveCellRef<ESM::Activator> *ref = cell.mActivators.find (name))
|
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))
|
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))
|
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))
|
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))
|
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))
|
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))
|
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))
|
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))
|
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))
|
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))
|
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))
|
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))
|
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))
|
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))
|
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))
|
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))
|
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))
|
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))
|
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))
|
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();
|
return Ptr();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -45,7 +45,8 @@ namespace MWWorld
|
|||||||
|
|
||||||
CellStore *getInterior (const std::string& name);
|
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);
|
Ptr getPtr (const std::string& name);
|
||||||
};
|
};
|
||||||
|
@ -7,6 +7,29 @@
|
|||||||
|
|
||||||
#include "ptr.hpp"
|
#include "ptr.hpp"
|
||||||
#include "esmstore.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
|
namespace MWWorld
|
||||||
{
|
{
|
||||||
@ -16,14 +39,14 @@ namespace MWWorld
|
|||||||
{
|
{
|
||||||
// Get existing reference, in case we need to overwrite it.
|
// Get existing reference, in case we need to overwrite it.
|
||||||
typename std::list<LiveRef>::iterator iter = std::find(mList.begin(), mList.end(), ref.mRefnum);
|
typename std::list<LiveRef>::iterator iter = std::find(mList.begin(), mList.end(), ref.mRefnum);
|
||||||
|
|
||||||
// Skip this when reference was deleted.
|
// Skip this when reference was deleted.
|
||||||
// TODO: Support respawning references, in this case, we need to track it somehow.
|
// TODO: Support respawning references, in this case, we need to track it somehow.
|
||||||
if (ref.mDeleted) {
|
if (ref.mDeleted) {
|
||||||
mList.erase(iter);
|
mList.erase(iter);
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
// for throwing exception on unhandled record type
|
// for throwing exception on unhandled record type
|
||||||
const MWWorld::Store<X> &store = esmStore.get<X>();
|
const MWWorld::Store<X> &store = esmStore.get<X>();
|
||||||
const X *ptr = store.search(ref.mRefID);
|
const X *ptr = store.search(ref.mRefID);
|
||||||
@ -39,7 +62,7 @@ namespace MWWorld
|
|||||||
mList.push_back(LiveRef(ref, ptr));
|
mList.push_back(LiveRef(ref, ptr));
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
template<typename X> bool operator==(const LiveCellRef<X>& ref, int pRefnum)
|
template<typename X> bool operator==(const LiveCellRef<X>& ref, int pRefnum)
|
||||||
{
|
{
|
||||||
return (ref.mRef.mRefnum == 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);
|
ESM::MovedCellRefTracker::const_iterator iter = std::find(mCell->mMovedRefs.begin(), mCell->mMovedRefs.end(), ref.mRefnum);
|
||||||
if (iter != mCell->mMovedRefs.end()) {
|
if (iter != mCell->mMovedRefs.end()) {
|
||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
int rec = store.find(ref.mRefID);
|
int rec = store.find(ref.mRefID);
|
||||||
|
|
||||||
ref.mRefID = lowerCase;
|
ref.mRefID = lowerCase;
|
||||||
@ -186,7 +209,7 @@ namespace MWWorld
|
|||||||
(int(*)(int)) std::tolower);
|
(int(*)(int)) std::tolower);
|
||||||
|
|
||||||
int rec = store.find(ref.mRefID);
|
int rec = store.find(ref.mRefID);
|
||||||
|
|
||||||
ref.mRefID = lowerCase;
|
ref.mRefID = lowerCase;
|
||||||
|
|
||||||
/* We can optimize this further by storing the pointer to the
|
/* We can optimize this further by storing the pointer to the
|
||||||
@ -221,7 +244,33 @@ namespace MWWorld
|
|||||||
default:
|
default:
|
||||||
std::cout << "WARNING: Ignoring reference '" << ref.mRefID << "' of unhandled type\n";
|
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();
|
return mCell->isExterior();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
Ptr searchInContainer (const std::string& id);
|
||||||
|
|
||||||
private:
|
private:
|
||||||
|
|
||||||
template<class Functor, class List>
|
template<class Functor, class List>
|
||||||
@ -148,6 +150,7 @@ namespace MWWorld
|
|||||||
void listRefs(const MWWorld::ESMStore &store, std::vector<ESM::ESMReader> &esm);
|
void listRefs(const MWWorld::ESMStore &store, std::vector<ESM::ESMReader> &esm);
|
||||||
|
|
||||||
void loadRefs(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/esm/loadcont.hpp>
|
||||||
#include <components/compiler/locals.hpp>
|
#include <components/compiler/locals.hpp>
|
||||||
|
#include <components/misc/stringops.hpp>
|
||||||
|
|
||||||
#include "../mwbase/environment.hpp"
|
#include "../mwbase/environment.hpp"
|
||||||
#include "../mwbase/world.hpp"
|
#include "../mwbase/world.hpp"
|
||||||
@ -85,12 +86,12 @@ MWWorld::ContainerStoreIterator MWWorld::ContainerStore::add (const Ptr& itemPtr
|
|||||||
CellStore *cell;
|
CellStore *cell;
|
||||||
|
|
||||||
Ptr player = MWBase::Environment::get().getWorld ()->getPlayer().getPlayer();
|
Ptr player = MWBase::Environment::get().getWorld ()->getPlayer().getPlayer();
|
||||||
|
|
||||||
if(&(MWWorld::Class::get (player).getContainerStore (player)) == this)
|
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
|
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.mRefData->getLocals().setVarByInt(script, "onpcadd", 1);
|
item.mRefData->getLocals().setVarByInt(script, "onpcadd", 1);
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
@ -347,6 +348,25 @@ int MWWorld::ContainerStore::getType (const Ptr& ptr)
|
|||||||
"Object of type " + ptr.getTypeName() + " can not be placed into a container");
|
"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)
|
MWWorld::ContainerStoreIterator::ContainerStoreIterator (ContainerStore *container)
|
||||||
: mType (-1), mMask (0), mContainer (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
|
///< This function throws an exception, if ptr does not point to an object, that can be
|
||||||
/// put into a container.
|
/// put into a container.
|
||||||
|
|
||||||
|
Ptr search (const std::string& id);
|
||||||
|
|
||||||
friend class ContainerStoreIterator;
|
friend class ContainerStoreIterator;
|
||||||
};
|
};
|
||||||
|
|
||||||
|
Loading…
x
Reference in New Issue
Block a user