2011-09-08 09:02:55 +00:00
|
|
|
#include "cells.hpp"
|
|
|
|
|
2012-07-03 10:30:50 +00:00
|
|
|
#include "../mwbase/environment.hpp"
|
|
|
|
#include "../mwbase/world.hpp"
|
|
|
|
|
2012-03-10 11:36:29 +00:00
|
|
|
#include "class.hpp"
|
2012-10-01 15:17:04 +00:00
|
|
|
#include "esmstore.hpp"
|
2012-03-10 11:36:29 +00:00
|
|
|
#include "containerstore.hpp"
|
2011-09-27 08:08:07 +00:00
|
|
|
|
2011-09-22 10:44:17 +00:00
|
|
|
MWWorld::Ptr::CellStore *MWWorld::Cells::getCellStore (const ESM::Cell *cell)
|
|
|
|
{
|
2012-09-17 07:37:50 +00:00
|
|
|
if (cell->mData.mFlags & ESM::Cell::Interior)
|
2011-09-22 10:44:17 +00:00
|
|
|
{
|
2012-09-17 07:37:50 +00:00
|
|
|
std::map<std::string, Ptr::CellStore>::iterator result = mInteriors.find (cell->mName);
|
2011-09-22 10:44:17 +00:00
|
|
|
|
|
|
|
if (result==mInteriors.end())
|
|
|
|
{
|
2012-09-17 07:37:50 +00:00
|
|
|
result = mInteriors.insert (std::make_pair (cell->mName, Ptr::CellStore (cell))).first;
|
2011-09-22 10:44:17 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
return &result->second;
|
|
|
|
}
|
|
|
|
else
|
|
|
|
{
|
|
|
|
std::map<std::pair<int, int>, Ptr::CellStore>::iterator result =
|
2012-11-05 12:07:59 +00:00
|
|
|
mExteriors.find (std::make_pair (cell->getGridX(), cell->getGridY()));
|
2011-09-22 10:44:17 +00:00
|
|
|
|
|
|
|
if (result==mExteriors.end())
|
|
|
|
{
|
|
|
|
result = mExteriors.insert (std::make_pair (
|
2012-11-05 12:07:59 +00:00
|
|
|
std::make_pair (cell->getGridX(), cell->getGridY()), Ptr::CellStore (cell))).first;
|
2011-09-22 10:44:17 +00:00
|
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
return &result->second;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2012-03-10 11:36:29 +00:00
|
|
|
void MWWorld::Cells::fillContainers (Ptr::CellStore& cellStore)
|
|
|
|
{
|
2012-06-29 16:54:23 +00:00
|
|
|
for (CellRefList<ESM::Container>::List::iterator iter (
|
2012-11-05 12:07:59 +00:00
|
|
|
cellStore.mContainers.mList.begin());
|
|
|
|
iter!=cellStore.mContainers.mList.end(); ++iter)
|
2012-03-10 11:36:29 +00:00
|
|
|
{
|
2013-02-09 12:00:57 +00:00
|
|
|
Ptr container (&*iter, &cellStore);
|
2012-03-10 11:36:29 +00:00
|
|
|
|
|
|
|
Class::get (container).getContainerStore (container).fill (
|
2013-02-09 12:00:57 +00:00
|
|
|
iter->mBase->mInventory, mStore);
|
2012-03-10 11:36:29 +00:00
|
|
|
}
|
|
|
|
|
2012-06-29 16:54:23 +00:00
|
|
|
for (CellRefList<ESM::Creature>::List::iterator iter (
|
2012-11-05 12:07:59 +00:00
|
|
|
cellStore.mCreatures.mList.begin());
|
|
|
|
iter!=cellStore.mCreatures.mList.end(); ++iter)
|
2012-03-10 11:36:29 +00:00
|
|
|
{
|
2013-02-09 12:00:57 +00:00
|
|
|
Ptr container (&*iter, &cellStore);
|
2012-03-10 11:36:29 +00:00
|
|
|
|
|
|
|
Class::get (container).getContainerStore (container).fill (
|
2013-02-09 12:00:57 +00:00
|
|
|
iter->mBase->mInventory, mStore);
|
2012-03-10 11:36:29 +00:00
|
|
|
}
|
|
|
|
|
2012-06-29 16:54:23 +00:00
|
|
|
for (CellRefList<ESM::NPC>::List::iterator iter (
|
2012-11-05 12:07:59 +00:00
|
|
|
cellStore.mNpcs.mList.begin());
|
|
|
|
iter!=cellStore.mNpcs.mList.end(); ++iter)
|
2012-03-10 11:36:29 +00:00
|
|
|
{
|
2013-02-09 12:00:57 +00:00
|
|
|
Ptr container (&*iter, &cellStore);
|
2012-03-10 11:36:29 +00:00
|
|
|
|
|
|
|
Class::get (container).getContainerStore (container).fill (
|
2013-02-09 12:00:57 +00:00
|
|
|
iter->mBase->mInventory, mStore);
|
2012-03-10 11:36:29 +00:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2012-06-21 09:43:18 +00:00
|
|
|
MWWorld::Ptr MWWorld::Cells::getPtrAndCache (const std::string& name, Ptr::CellStore& cellStore)
|
|
|
|
{
|
|
|
|
Ptr ptr = getPtr (name, cellStore);
|
|
|
|
|
|
|
|
if (!ptr.isEmpty())
|
|
|
|
{
|
|
|
|
mIdCache[mIdCacheIndex].first = name;
|
|
|
|
mIdCache[mIdCacheIndex].second = &cellStore;
|
|
|
|
if (++mIdCacheIndex>=mIdCache.size())
|
|
|
|
mIdCacheIndex = 0;
|
|
|
|
}
|
|
|
|
|
|
|
|
return ptr;
|
|
|
|
}
|
|
|
|
|
2012-11-25 13:12:44 +00:00
|
|
|
MWWorld::Cells::Cells (const MWWorld::ESMStore& store, std::vector<ESM::ESMReader>& reader)
|
2012-07-03 10:30:50 +00:00
|
|
|
: mStore (store), mReader (reader),
|
2013-02-25 15:43:56 +00:00
|
|
|
mIdCache (40, std::pair<std::string, Ptr::CellStore *> ("", (Ptr::CellStore*)0)), /// \todo make cache size configurable
|
2012-06-21 09:43:18 +00:00
|
|
|
mIdCacheIndex (0)
|
|
|
|
{}
|
2011-09-08 09:02:55 +00:00
|
|
|
|
|
|
|
MWWorld::Ptr::CellStore *MWWorld::Cells::getExterior (int x, int y)
|
|
|
|
{
|
|
|
|
std::map<std::pair<int, int>, Ptr::CellStore>::iterator result =
|
|
|
|
mExteriors.find (std::make_pair (x, y));
|
|
|
|
|
|
|
|
if (result==mExteriors.end())
|
|
|
|
{
|
2012-11-06 08:36:21 +00:00
|
|
|
const ESM::Cell *cell = mStore.get<ESM::Cell>().search(x, y);
|
2011-09-27 08:08:07 +00:00
|
|
|
|
|
|
|
if (!cell)
|
|
|
|
{
|
|
|
|
// Cell isn't predefined. Make one on the fly.
|
|
|
|
ESM::Cell record;
|
|
|
|
|
2012-09-17 07:37:50 +00:00
|
|
|
record.mData.mFlags = 0;
|
|
|
|
record.mData.mX = x;
|
|
|
|
record.mData.mY = y;
|
|
|
|
record.mWater = 0;
|
|
|
|
record.mMapColor = 0;
|
2011-09-27 08:08:07 +00:00
|
|
|
|
2012-07-03 10:30:50 +00:00
|
|
|
cell = MWBase::Environment::get().getWorld()->createRecord (record);
|
2011-09-27 08:08:07 +00:00
|
|
|
}
|
2011-09-08 09:02:55 +00:00
|
|
|
|
2011-09-10 09:22:32 +00:00
|
|
|
result = mExteriors.insert (std::make_pair (
|
2012-07-03 10:30:50 +00:00
|
|
|
std::make_pair (x, y), CellStore (cell))).first;
|
2012-02-12 11:35:29 +00:00
|
|
|
}
|
2011-09-10 09:22:32 +00:00
|
|
|
|
2012-02-12 11:35:29 +00:00
|
|
|
if (result->second.mState!=Ptr::CellStore::State_Loaded)
|
2012-05-25 15:55:00 +00:00
|
|
|
{
|
2012-11-10 20:43:41 +00:00
|
|
|
// Multiple plugin support for landscape data is much easier than for references. The last plugin wins.
|
2011-09-10 09:22:32 +00:00
|
|
|
result->second.load (mStore, mReader);
|
2012-03-10 11:36:29 +00:00
|
|
|
fillContainers (result->second);
|
2012-05-25 15:55:00 +00:00
|
|
|
}
|
2012-03-10 11:36:29 +00:00
|
|
|
|
2011-09-08 09:02:55 +00:00
|
|
|
return &result->second;
|
|
|
|
}
|
|
|
|
|
|
|
|
MWWorld::Ptr::CellStore *MWWorld::Cells::getInterior (const std::string& name)
|
|
|
|
{
|
2013-03-07 19:15:01 +00:00
|
|
|
std::string lowerName = Misc::StringUtils::lowerCase(name);
|
|
|
|
std::map<std::string, Ptr::CellStore>::iterator result = mInteriors.find (lowerName);
|
2011-09-08 09:02:55 +00:00
|
|
|
|
|
|
|
if (result==mInteriors.end())
|
|
|
|
{
|
2013-03-07 19:15:01 +00:00
|
|
|
const ESM::Cell *cell = mStore.get<ESM::Cell>().find(lowerName);
|
2011-09-10 09:22:32 +00:00
|
|
|
|
2013-03-07 19:15:01 +00:00
|
|
|
result = mInteriors.insert (std::make_pair (lowerName, Ptr::CellStore (cell))).first;
|
2012-02-12 11:35:29 +00:00
|
|
|
}
|
2011-09-08 09:02:55 +00:00
|
|
|
|
2012-02-12 11:35:29 +00:00
|
|
|
if (result->second.mState!=Ptr::CellStore::State_Loaded)
|
2012-05-25 15:55:00 +00:00
|
|
|
{
|
2011-09-10 09:22:32 +00:00
|
|
|
result->second.load (mStore, mReader);
|
2012-03-10 11:36:29 +00:00
|
|
|
fillContainers (result->second);
|
2012-05-25 15:55:00 +00:00
|
|
|
}
|
2012-03-10 11:36:29 +00:00
|
|
|
|
2011-09-08 09:02:55 +00:00
|
|
|
return &result->second;
|
|
|
|
}
|
2011-09-22 09:54:08 +00:00
|
|
|
|
|
|
|
MWWorld::Ptr MWWorld::Cells::getPtr (const std::string& name, Ptr::CellStore& cell)
|
|
|
|
{
|
2011-09-24 09:45:59 +00:00
|
|
|
if (cell.mState==Ptr::CellStore::State_Unloaded)
|
|
|
|
cell.preload (mStore, mReader);
|
|
|
|
|
|
|
|
if (cell.mState==Ptr::CellStore::State_Preloaded)
|
|
|
|
{
|
2013-01-09 19:51:52 +00:00
|
|
|
std::string lowerCase = Misc::StringUtils::lowerCase(name);
|
2011-09-24 09:45:59 +00:00
|
|
|
|
|
|
|
if (std::binary_search (cell.mIds.begin(), cell.mIds.end(), lowerCase))
|
2012-06-19 14:42:10 +00:00
|
|
|
{
|
2011-09-24 09:45:59 +00:00
|
|
|
cell.load (mStore, mReader);
|
2012-06-19 14:42:10 +00:00
|
|
|
fillContainers (cell);
|
|
|
|
}
|
2011-09-24 09:45:59 +00:00
|
|
|
else
|
|
|
|
return Ptr();
|
|
|
|
}
|
2012-08-06 14:20:48 +00:00
|
|
|
MWWorld::Ptr ptr;
|
2011-09-22 09:54:08 +00:00
|
|
|
|
2012-11-05 12:07:59 +00:00
|
|
|
if (MWWorld::LiveCellRef<ESM::Activator> *ref = cell.mActivators.find (name))
|
2012-08-06 14:20:48 +00:00
|
|
|
ptr = Ptr (ref, &cell);
|
2011-09-22 09:54:08 +00:00
|
|
|
|
2012-11-05 12:07:59 +00:00
|
|
|
if (MWWorld::LiveCellRef<ESM::Potion> *ref = cell.mPotions.find (name))
|
2012-08-06 14:20:48 +00:00
|
|
|
ptr = Ptr (ref, &cell);
|
2011-09-22 09:54:08 +00:00
|
|
|
|
2012-11-05 12:07:59 +00:00
|
|
|
if (MWWorld::LiveCellRef<ESM::Apparatus> *ref = cell.mAppas.find (name))
|
2012-08-06 14:20:48 +00:00
|
|
|
ptr = Ptr (ref, &cell);
|
2011-09-22 09:54:08 +00:00
|
|
|
|
2012-11-05 12:07:59 +00:00
|
|
|
if (MWWorld::LiveCellRef<ESM::Armor> *ref = cell.mArmors.find (name))
|
2012-08-06 14:20:48 +00:00
|
|
|
ptr = Ptr (ref, &cell);
|
2011-09-22 09:54:08 +00:00
|
|
|
|
2012-11-05 12:07:59 +00:00
|
|
|
if (MWWorld::LiveCellRef<ESM::Book> *ref = cell.mBooks.find (name))
|
2012-08-06 14:20:48 +00:00
|
|
|
ptr = Ptr (ref, &cell);
|
2011-09-22 09:54:08 +00:00
|
|
|
|
2012-11-05 12:07:59 +00:00
|
|
|
if (MWWorld::LiveCellRef<ESM::Clothing> *ref = cell.mClothes.find (name))
|
2012-08-06 14:20:48 +00:00
|
|
|
ptr = Ptr (ref, &cell);
|
2011-09-22 09:54:08 +00:00
|
|
|
|
2012-11-05 12:07:59 +00:00
|
|
|
if (MWWorld::LiveCellRef<ESM::Container> *ref = cell.mContainers.find (name))
|
2012-08-06 14:20:48 +00:00
|
|
|
ptr = Ptr (ref, &cell);
|
2011-09-22 09:54:08 +00:00
|
|
|
|
2012-11-05 12:07:59 +00:00
|
|
|
if (MWWorld::LiveCellRef<ESM::Creature> *ref = cell.mCreatures.find (name))
|
2012-08-06 14:20:48 +00:00
|
|
|
ptr = Ptr (ref, &cell);
|
2011-09-22 09:54:08 +00:00
|
|
|
|
2012-11-05 12:07:59 +00:00
|
|
|
if (MWWorld::LiveCellRef<ESM::Door> *ref = cell.mDoors.find (name))
|
2012-08-06 14:20:48 +00:00
|
|
|
ptr = Ptr (ref, &cell);
|
2011-09-22 09:54:08 +00:00
|
|
|
|
2012-11-05 12:07:59 +00:00
|
|
|
if (MWWorld::LiveCellRef<ESM::Ingredient> *ref = cell.mIngreds.find (name))
|
2012-08-06 14:20:48 +00:00
|
|
|
ptr = Ptr (ref, &cell);
|
2011-09-22 09:54:08 +00:00
|
|
|
|
2012-11-05 12:07:59 +00:00
|
|
|
if (MWWorld::LiveCellRef<ESM::CreatureLevList> *ref = cell.mCreatureLists.find (name))
|
2012-08-06 14:20:48 +00:00
|
|
|
ptr = Ptr (ref, &cell);
|
2011-09-22 09:54:08 +00:00
|
|
|
|
2012-11-05 12:07:59 +00:00
|
|
|
if (MWWorld::LiveCellRef<ESM::ItemLevList> *ref = cell.mItemLists.find (name))
|
2012-08-06 14:20:48 +00:00
|
|
|
ptr = Ptr (ref, &cell);
|
2011-09-22 09:54:08 +00:00
|
|
|
|
2012-11-05 12:07:59 +00:00
|
|
|
if (MWWorld::LiveCellRef<ESM::Light> *ref = cell.mLights.find (name))
|
2012-08-06 14:20:48 +00:00
|
|
|
ptr = Ptr (ref, &cell);
|
2011-09-22 09:54:08 +00:00
|
|
|
|
2012-11-05 12:07:59 +00:00
|
|
|
if (MWWorld::LiveCellRef<ESM::Tool> *ref = cell.mLockpicks.find (name))
|
2012-08-06 14:20:48 +00:00
|
|
|
ptr = Ptr (ref, &cell);
|
2011-09-22 09:54:08 +00:00
|
|
|
|
2012-11-05 12:07:59 +00:00
|
|
|
if (MWWorld::LiveCellRef<ESM::Miscellaneous> *ref = cell.mMiscItems.find (name))
|
2012-08-06 14:20:48 +00:00
|
|
|
ptr = Ptr (ref, &cell);
|
2011-09-22 09:54:08 +00:00
|
|
|
|
2012-11-05 12:07:59 +00:00
|
|
|
if (MWWorld::LiveCellRef<ESM::NPC> *ref = cell.mNpcs.find (name))
|
2012-08-06 14:20:48 +00:00
|
|
|
ptr = Ptr (ref, &cell);
|
2011-09-22 09:54:08 +00:00
|
|
|
|
2012-11-05 12:07:59 +00:00
|
|
|
if (MWWorld::LiveCellRef<ESM::Probe> *ref = cell.mProbes.find (name))
|
2012-08-06 14:20:48 +00:00
|
|
|
ptr = Ptr (ref, &cell);
|
2011-09-22 09:54:08 +00:00
|
|
|
|
2012-11-05 12:07:59 +00:00
|
|
|
if (MWWorld::LiveCellRef<ESM::Repair> *ref = cell.mRepairs.find (name))
|
2012-08-06 14:20:48 +00:00
|
|
|
ptr = Ptr (ref, &cell);
|
2011-09-22 09:54:08 +00:00
|
|
|
|
2012-11-05 12:07:59 +00:00
|
|
|
if (MWWorld::LiveCellRef<ESM::Static> *ref = cell.mStatics.find (name))
|
2012-08-06 14:20:48 +00:00
|
|
|
ptr = Ptr (ref, &cell);
|
2011-09-22 09:54:08 +00:00
|
|
|
|
2012-11-05 12:07:59 +00:00
|
|
|
if (MWWorld::LiveCellRef<ESM::Weapon> *ref = cell.mWeapons.find (name))
|
2012-08-06 14:20:48 +00:00
|
|
|
ptr = Ptr (ref, &cell);
|
2011-09-22 09:54:08 +00:00
|
|
|
|
2012-08-06 14:20:48 +00:00
|
|
|
if (!ptr.isEmpty() && ptr.getRefData().getCount() > 0) {
|
|
|
|
return ptr;
|
|
|
|
}
|
2011-09-22 09:54:08 +00:00
|
|
|
return Ptr();
|
|
|
|
}
|
2011-09-22 10:44:17 +00:00
|
|
|
|
|
|
|
MWWorld::Ptr MWWorld::Cells::getPtr (const std::string& name)
|
|
|
|
{
|
2012-06-21 09:43:18 +00:00
|
|
|
// First check the cache
|
|
|
|
for (std::vector<std::pair<std::string, Ptr::CellStore *> >::iterator iter (mIdCache.begin());
|
|
|
|
iter!=mIdCache.end(); ++iter)
|
|
|
|
if (iter->first==name && iter->second)
|
|
|
|
{
|
|
|
|
Ptr ptr = getPtr (name, *iter->second);
|
|
|
|
if (!ptr.isEmpty())
|
|
|
|
return ptr;
|
|
|
|
}
|
|
|
|
|
|
|
|
// Then check cells that are already listed
|
2011-09-22 10:44:17 +00:00
|
|
|
for (std::map<std::string, Ptr::CellStore>::iterator iter = mInteriors.begin();
|
|
|
|
iter!=mInteriors.end(); ++iter)
|
|
|
|
{
|
2012-06-21 09:43:18 +00:00
|
|
|
Ptr ptr = getPtrAndCache (name, iter->second);
|
2011-09-22 10:44:17 +00:00
|
|
|
if (!ptr.isEmpty())
|
2012-06-21 09:43:18 +00:00
|
|
|
return ptr;
|
2011-09-22 10:44:17 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
for (std::map<std::pair<int, int>, Ptr::CellStore>::iterator iter = mExteriors.begin();
|
|
|
|
iter!=mExteriors.end(); ++iter)
|
|
|
|
{
|
2012-06-21 09:43:18 +00:00
|
|
|
Ptr ptr = getPtrAndCache (name, iter->second);
|
2011-09-22 10:44:17 +00:00
|
|
|
if (!ptr.isEmpty())
|
|
|
|
return ptr;
|
|
|
|
}
|
|
|
|
|
|
|
|
// Now try the other cells
|
2012-11-06 08:36:21 +00:00
|
|
|
const MWWorld::Store<ESM::Cell> &cells = mStore.get<ESM::Cell>();
|
|
|
|
MWWorld::Store<ESM::Cell>::iterator iter;
|
|
|
|
|
|
|
|
for (iter = cells.intBegin(); iter != cells.intEnd(); ++iter)
|
2011-09-22 10:44:17 +00:00
|
|
|
{
|
2012-11-06 10:03:36 +00:00
|
|
|
Ptr::CellStore *cellStore = getCellStore (&(*iter));
|
2011-09-22 10:44:17 +00:00
|
|
|
|
2012-06-21 09:43:18 +00:00
|
|
|
Ptr ptr = getPtrAndCache (name, *cellStore);
|
2011-09-22 10:44:17 +00:00
|
|
|
|
|
|
|
if (!ptr.isEmpty())
|
|
|
|
return ptr;
|
|
|
|
}
|
|
|
|
|
2012-11-06 10:03:36 +00:00
|
|
|
for (iter = cells.extBegin(); iter != cells.extEnd(); ++iter)
|
2011-09-22 10:44:17 +00:00
|
|
|
{
|
2012-11-06 10:03:36 +00:00
|
|
|
Ptr::CellStore *cellStore = getCellStore (&(*iter));
|
2011-09-22 10:44:17 +00:00
|
|
|
|
2012-06-21 09:43:18 +00:00
|
|
|
Ptr ptr = getPtrAndCache (name, *cellStore);
|
2011-09-22 10:44:17 +00:00
|
|
|
|
|
|
|
if (!ptr.isEmpty())
|
|
|
|
return ptr;
|
|
|
|
}
|
|
|
|
|
|
|
|
// giving up
|
|
|
|
return Ptr();
|
|
|
|
}
|