mirror of
https://github.com/OpenMW/openmw.git
synced 2025-01-30 09:45:36 +00:00
- For pull request: remove all instances of maps used to track refnumbers.
- new file: apps/openmw/mwworld/store.cpp, had to move reference merging method out of the header file to prevent three-way recursion/unresolved forward references in custom compare operators.
This commit is contained in:
parent
3e43db5f76
commit
eefbdde6de
13 changed files with 233 additions and 225 deletions
|
@ -213,8 +213,10 @@ bool parseOptions (int argc, char** argv, OMW::Engine& engine, Files::Configurat
|
|||
|
||||
StringsVector plugin = variables["plugin"].as<StringsVector>();
|
||||
// Removed check for 255 files, which would be the hard-coded limit in Morrowind.
|
||||
// I'll keep the following variable in, maybe we can use it for somethng different.
|
||||
int cnt = master.size() + plugin.size();
|
||||
// I'll keep the following variable in, maybe we can use it for something different.
|
||||
// Say, a feedback like "loading file x/cnt".
|
||||
// Commenting this out for now to silence compiler warning.
|
||||
//int cnt = master.size() + plugin.size();
|
||||
|
||||
// Prepare loading master/plugin files (i.e. send filenames to engine)
|
||||
for (std::vector<std::string>::size_type i = 0; i < master.size(); i++)
|
||||
|
|
|
@ -42,30 +42,30 @@ void MWWorld::Cells::fillContainers (Ptr::CellStore& cellStore)
|
|||
cellStore.mContainers.mList.begin());
|
||||
iter!=cellStore.mContainers.mList.end(); ++iter)
|
||||
{
|
||||
Ptr container (&iter->second, &cellStore);
|
||||
Ptr container (&*iter, &cellStore);
|
||||
|
||||
Class::get (container).getContainerStore (container).fill (
|
||||
iter->second.mBase->mInventory, mStore);
|
||||
iter->mBase->mInventory, mStore);
|
||||
}
|
||||
|
||||
for (CellRefList<ESM::Creature>::List::iterator iter (
|
||||
cellStore.mCreatures.mList.begin());
|
||||
iter!=cellStore.mCreatures.mList.end(); ++iter)
|
||||
{
|
||||
Ptr container (&iter->second, &cellStore);
|
||||
Ptr container (&*iter, &cellStore);
|
||||
|
||||
Class::get (container).getContainerStore (container).fill (
|
||||
iter->second.mBase->mInventory, mStore);
|
||||
iter->mBase->mInventory, mStore);
|
||||
}
|
||||
|
||||
for (CellRefList<ESM::NPC>::List::iterator iter (
|
||||
cellStore.mNpcs.mList.begin());
|
||||
iter!=cellStore.mNpcs.mList.end(); ++iter)
|
||||
{
|
||||
Ptr container (&iter->second, &cellStore);
|
||||
Ptr container (&*iter, &cellStore);
|
||||
|
||||
Class::get (container).getContainerStore (container).fill (
|
||||
iter->second.mBase->mInventory, mStore);
|
||||
iter->mBase->mInventory, mStore);
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
@ -10,6 +10,41 @@
|
|||
|
||||
namespace MWWorld
|
||||
{
|
||||
|
||||
template <typename X>
|
||||
void CellRefList<X>::load(ESM::CellRef &ref, const MWWorld::ESMStore &esmStore)
|
||||
{
|
||||
// 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);
|
||||
|
||||
/// \note no longer redundant - changed to Store<X>::search(), don't throw
|
||||
/// an exception on miss, try to continue (that's how MW does it, anyway)
|
||||
if (ptr == NULL) {
|
||||
std::cout << "Warning: could not resolve cell reference " << ref.mRefID << ", trying to continue anyway" << std::endl;
|
||||
} else {
|
||||
if (iter != mList.end())
|
||||
*iter = LiveRef(ref, ptr);
|
||||
else
|
||||
mList.push_back(LiveRef(ref, ptr));
|
||||
}
|
||||
}
|
||||
|
||||
template<typename X> bool operator==(const LiveCellRef<X>& ref, int pRefnum)
|
||||
{
|
||||
return (ref.mRef.mRefnum == pRefnum);
|
||||
}
|
||||
|
||||
CellStore::CellStore (const ESM::Cell *cell)
|
||||
: mCell (cell), mState (State_Unloaded)
|
||||
{
|
||||
|
@ -95,7 +130,8 @@ namespace MWWorld
|
|||
{
|
||||
// Don't load reference if it was moved to a different cell.
|
||||
std::string lowerCase = Misc::StringUtils::lowerCase(ref.mRefID);
|
||||
if (mCell->mMovedRefs.find(ref.mRefnum) != mCell->mMovedRefs.end()) {
|
||||
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);
|
||||
|
@ -141,8 +177,8 @@ namespace MWWorld
|
|||
for (ESM::CellRefTracker::const_iterator it = mCell->mLeasedRefs.begin(); it != mCell->mLeasedRefs.end(); it++)
|
||||
{
|
||||
// Doesn't seem to work in one line... huh? Too sleepy to check...
|
||||
//const ESM::CellRef &ref0 = it->second;
|
||||
ESM::CellRef &ref = const_cast<ESM::CellRef&>(it->second);
|
||||
ESM::CellRef &ref = const_cast<ESM::CellRef&>(*it);
|
||||
//ESM::CellRef &ref = const_cast<ESM::CellRef&>(it->second);
|
||||
|
||||
std::string lowerCase;
|
||||
|
||||
|
|
|
@ -9,11 +9,12 @@
|
|||
#include "refdata.hpp"
|
||||
#include "esmstore.hpp"
|
||||
|
||||
struct C;
|
||||
namespace MWWorld
|
||||
{
|
||||
class Ptr;
|
||||
class ESMStore;
|
||||
|
||||
|
||||
/// A reference to one object (of any type) in a cell.
|
||||
///
|
||||
/// Constructing this with a CellRef instance in the constructor means that
|
||||
|
@ -42,88 +43,25 @@ namespace MWWorld
|
|||
/// runtime-data
|
||||
RefData mData;
|
||||
};
|
||||
|
||||
template<typename X> bool operator==(const LiveCellRef<X>& ref, int pRefnum);
|
||||
|
||||
/// A list of cell references
|
||||
template <typename X>
|
||||
struct CellRefList
|
||||
{
|
||||
typedef LiveCellRef<X> LiveRef;
|
||||
typedef std::map<int,LiveRef> List;
|
||||
typedef std::list<LiveRef> List;
|
||||
List mList;
|
||||
|
||||
// Search for the given reference in the given reclist from
|
||||
// ESMStore. Insert the reference into the list if a match is
|
||||
// found. If not, throw an exception.
|
||||
/// Searches for reference of appropriate type in given ESMStore.
|
||||
/// If reference exists, loads it into container, throws an exception
|
||||
/// on miss
|
||||
void load(ESM::CellRef &ref, const MWWorld::ESMStore &esmStore)
|
||||
{
|
||||
// Skip this when reference was deleted.
|
||||
// TODO: Support respawning references, in this case, we need to track it somehow.
|
||||
if (ref.mDeleted) {
|
||||
mList.erase(ref.mRefnum);
|
||||
return;
|
||||
}
|
||||
|
||||
// for throwing exception on unhandled record type
|
||||
const MWWorld::Store<X> &store = esmStore.get<X>();
|
||||
const X *ptr = store.search(ref.mRefID);
|
||||
|
||||
/// \note no longer redundant - changed to Store<X>::search(), don't throw
|
||||
/// an exception on miss, try to continue (that's how MW does it, anyway)
|
||||
if (ptr == NULL) {
|
||||
std::cout << "Warning: could not resolve cell reference " << ref.mRefID << ", trying to continue anyway" << std::endl;
|
||||
} else
|
||||
mList[ref.mRefnum] = LiveRef(ref, ptr);
|
||||
}
|
||||
|
||||
LiveRef *find (const std::string& name)
|
||||
{
|
||||
for (typename std::map<int,LiveRef>::iterator iter (mList.begin()); iter!=mList.end(); ++iter)
|
||||
{
|
||||
if (iter->second.mData.getCount() > 0 && iter->second.mRef.mRefID == name)
|
||||
return &iter->second;
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
LiveRef &insert(const LiveRef &item) {
|
||||
mList[item.mRef.mRefnum] = item;
|
||||
return mList[item.mRef.mRefnum];
|
||||
}
|
||||
};
|
||||
|
||||
/// A list of container references. These references do not track their mRefnumber.
|
||||
/// Otherwise, taking 1 of 20 instances of an object would produce multiple objects
|
||||
/// with the same reference.
|
||||
/// Unfortunately, this also means that we need a different STL container.
|
||||
/// (cells use CellRefList, where refs can be located according to their refnumner,
|
||||
/// which uses a map; container items do not make use of the refnumber, so we
|
||||
/// can't use a map with refnumber keys.)
|
||||
template <typename X>
|
||||
struct ContainerRefList
|
||||
{
|
||||
typedef LiveCellRef<X> LiveRef;
|
||||
typedef std::list<LiveRef> List;
|
||||
List mList;
|
||||
|
||||
/// Searches for reference of appropriate type in given ESMStore.
|
||||
/// If reference exists, loads it into container, throws an exception
|
||||
/// on miss
|
||||
void load(ESM::CellRef &ref, const MWWorld::ESMStore &esmStore)
|
||||
{
|
||||
// for throwing exception on unhandled record type
|
||||
const MWWorld::Store<X> &store = esmStore.get<X>();
|
||||
const X *ptr = store.find(ref.mRefID);
|
||||
|
||||
/// \note redundant because Store<X>::find() throws exception on miss
|
||||
if (ptr == NULL) {
|
||||
throw std::runtime_error("Error resolving cell reference " + ref.mRefID);
|
||||
}
|
||||
mList.push_back(LiveRef(ref, ptr));
|
||||
}
|
||||
// Moved to cpp file, as we require a custom compare operator for it,
|
||||
// and the build will fail with an ugly three-way cyclic header dependence
|
||||
// so we need to pass the instantiation of the method to the lnker, when
|
||||
// all methods are known.
|
||||
void load(ESM::CellRef &ref, const MWWorld::ESMStore &esmStore);
|
||||
|
||||
LiveRef *find (const std::string& name)
|
||||
{
|
||||
|
@ -236,7 +174,7 @@ namespace MWWorld
|
|||
{
|
||||
for (typename List::List::iterator iter (list.mList.begin()); iter!=list.mList.end();
|
||||
++iter)
|
||||
if (!functor (iter->second.mRef, iter->second.mData))
|
||||
if (!functor (iter->mRef, iter->mData))
|
||||
return false;
|
||||
|
||||
return true;
|
||||
|
|
|
@ -21,11 +21,11 @@
|
|||
namespace
|
||||
{
|
||||
template<typename T>
|
||||
float getTotalWeight (const MWWorld::ContainerRefList<T>& cellRefList)
|
||||
float getTotalWeight (const MWWorld::CellRefList<T>& cellRefList)
|
||||
{
|
||||
float sum = 0;
|
||||
|
||||
for (typename MWWorld::ContainerRefList<T>::List::const_iterator iter (
|
||||
for (typename MWWorld::CellRefList<T>::List::const_iterator iter (
|
||||
cellRefList.mList.begin());
|
||||
iter!=cellRefList.mList.end();
|
||||
++iter)
|
||||
|
@ -300,29 +300,29 @@ MWWorld::ContainerStoreIterator::ContainerStoreIterator (int mask, ContainerStor
|
|||
++*this;
|
||||
}
|
||||
|
||||
MWWorld::ContainerStoreIterator::ContainerStoreIterator (ContainerStore *container, MWWorld::ContainerRefList<ESM::Potion>::List::iterator iterator)
|
||||
MWWorld::ContainerStoreIterator::ContainerStoreIterator (ContainerStore *container, MWWorld::CellRefList<ESM::Potion>::List::iterator iterator)
|
||||
: mType(MWWorld::ContainerStore::Type_Potion), mMask(MWWorld::ContainerStore::Type_All), mContainer(container), mPotion(iterator){}
|
||||
MWWorld::ContainerStoreIterator::ContainerStoreIterator (ContainerStore *container, MWWorld::ContainerRefList<ESM::Apparatus>::List::iterator iterator)
|
||||
MWWorld::ContainerStoreIterator::ContainerStoreIterator (ContainerStore *container, MWWorld::CellRefList<ESM::Apparatus>::List::iterator iterator)
|
||||
: mType(MWWorld::ContainerStore::Type_Apparatus), mMask(MWWorld::ContainerStore::Type_All), mContainer(container), mApparatus(iterator){}
|
||||
MWWorld::ContainerStoreIterator::ContainerStoreIterator (ContainerStore *container, MWWorld::ContainerRefList<ESM::Armor>::List::iterator iterator)
|
||||
MWWorld::ContainerStoreIterator::ContainerStoreIterator (ContainerStore *container, MWWorld::CellRefList<ESM::Armor>::List::iterator iterator)
|
||||
: mType(MWWorld::ContainerStore::Type_Armor), mMask(MWWorld::ContainerStore::Type_All), mContainer(container), mArmor(iterator){}
|
||||
MWWorld::ContainerStoreIterator::ContainerStoreIterator (ContainerStore *container, MWWorld::ContainerRefList<ESM::Book>::List::iterator iterator)
|
||||
MWWorld::ContainerStoreIterator::ContainerStoreIterator (ContainerStore *container, MWWorld::CellRefList<ESM::Book>::List::iterator iterator)
|
||||
: mType(MWWorld::ContainerStore::Type_Book), mMask(MWWorld::ContainerStore::Type_All), mContainer(container), mBook(iterator){}
|
||||
MWWorld::ContainerStoreIterator::ContainerStoreIterator (ContainerStore *container, MWWorld::ContainerRefList<ESM::Clothing>::List::iterator iterator)
|
||||
MWWorld::ContainerStoreIterator::ContainerStoreIterator (ContainerStore *container, MWWorld::CellRefList<ESM::Clothing>::List::iterator iterator)
|
||||
: mType(MWWorld::ContainerStore::Type_Clothing), mMask(MWWorld::ContainerStore::Type_All), mContainer(container), mClothing(iterator){}
|
||||
MWWorld::ContainerStoreIterator::ContainerStoreIterator (ContainerStore *container, MWWorld::ContainerRefList<ESM::Ingredient>::List::iterator iterator)
|
||||
MWWorld::ContainerStoreIterator::ContainerStoreIterator (ContainerStore *container, MWWorld::CellRefList<ESM::Ingredient>::List::iterator iterator)
|
||||
: mType(MWWorld::ContainerStore::Type_Ingredient), mMask(MWWorld::ContainerStore::Type_All), mContainer(container), mIngredient(iterator){}
|
||||
MWWorld::ContainerStoreIterator::ContainerStoreIterator (ContainerStore *container, MWWorld::ContainerRefList<ESM::Light>::List::iterator iterator)
|
||||
MWWorld::ContainerStoreIterator::ContainerStoreIterator (ContainerStore *container, MWWorld::CellRefList<ESM::Light>::List::iterator iterator)
|
||||
: mType(MWWorld::ContainerStore::Type_Light), mMask(MWWorld::ContainerStore::Type_All), mContainer(container), mLight(iterator){}
|
||||
MWWorld::ContainerStoreIterator::ContainerStoreIterator (ContainerStore *container, MWWorld::ContainerRefList<ESM::Tool>::List::iterator iterator)
|
||||
MWWorld::ContainerStoreIterator::ContainerStoreIterator (ContainerStore *container, MWWorld::CellRefList<ESM::Tool>::List::iterator iterator)
|
||||
: mType(MWWorld::ContainerStore::Type_Lockpick), mMask(MWWorld::ContainerStore::Type_All), mContainer(container), mLockpick(iterator){}
|
||||
MWWorld::ContainerStoreIterator::ContainerStoreIterator (ContainerStore *container, MWWorld::ContainerRefList<ESM::Miscellaneous>::List::iterator iterator)
|
||||
MWWorld::ContainerStoreIterator::ContainerStoreIterator (ContainerStore *container, MWWorld::CellRefList<ESM::Miscellaneous>::List::iterator iterator)
|
||||
: mType(MWWorld::ContainerStore::Type_Miscellaneous), mMask(MWWorld::ContainerStore::Type_All), mContainer(container), mMiscellaneous(iterator){}
|
||||
MWWorld::ContainerStoreIterator::ContainerStoreIterator (ContainerStore *container, MWWorld::ContainerRefList<ESM::Probe>::List::iterator iterator)
|
||||
MWWorld::ContainerStoreIterator::ContainerStoreIterator (ContainerStore *container, MWWorld::CellRefList<ESM::Probe>::List::iterator iterator)
|
||||
: mType(MWWorld::ContainerStore::Type_Probe), mMask(MWWorld::ContainerStore::Type_All), mContainer(container), mProbe(iterator){}
|
||||
MWWorld::ContainerStoreIterator::ContainerStoreIterator (ContainerStore *container, MWWorld::ContainerRefList<ESM::Repair>::List::iterator iterator)
|
||||
MWWorld::ContainerStoreIterator::ContainerStoreIterator (ContainerStore *container, MWWorld::CellRefList<ESM::Repair>::List::iterator iterator)
|
||||
: mType(MWWorld::ContainerStore::Type_Repair), mMask(MWWorld::ContainerStore::Type_All), mContainer(container), mRepair(iterator){}
|
||||
MWWorld::ContainerStoreIterator::ContainerStoreIterator (ContainerStore *container, MWWorld::ContainerRefList<ESM::Weapon>::List::iterator iterator)
|
||||
MWWorld::ContainerStoreIterator::ContainerStoreIterator (ContainerStore *container, MWWorld::CellRefList<ESM::Weapon>::List::iterator iterator)
|
||||
: mType(MWWorld::ContainerStore::Type_Weapon), mMask(MWWorld::ContainerStore::Type_All), mContainer(container), mWeapon(iterator){}
|
||||
|
||||
void MWWorld::ContainerStoreIterator::incType()
|
||||
|
|
|
@ -37,18 +37,18 @@ namespace MWWorld
|
|||
|
||||
private:
|
||||
|
||||
MWWorld::ContainerRefList<ESM::Potion> potions;
|
||||
MWWorld::ContainerRefList<ESM::Apparatus> appas;
|
||||
MWWorld::ContainerRefList<ESM::Armor> armors;
|
||||
MWWorld::ContainerRefList<ESM::Book> books;
|
||||
MWWorld::ContainerRefList<ESM::Clothing> clothes;
|
||||
MWWorld::ContainerRefList<ESM::Ingredient> ingreds;
|
||||
MWWorld::ContainerRefList<ESM::Light> lights;
|
||||
MWWorld::ContainerRefList<ESM::Tool> lockpicks;
|
||||
MWWorld::ContainerRefList<ESM::Miscellaneous> miscItems;
|
||||
MWWorld::ContainerRefList<ESM::Probe> probes;
|
||||
MWWorld::ContainerRefList<ESM::Repair> repairs;
|
||||
MWWorld::ContainerRefList<ESM::Weapon> weapons;
|
||||
MWWorld::CellRefList<ESM::Potion> potions;
|
||||
MWWorld::CellRefList<ESM::Apparatus> appas;
|
||||
MWWorld::CellRefList<ESM::Armor> armors;
|
||||
MWWorld::CellRefList<ESM::Book> books;
|
||||
MWWorld::CellRefList<ESM::Clothing> clothes;
|
||||
MWWorld::CellRefList<ESM::Ingredient> ingreds;
|
||||
MWWorld::CellRefList<ESM::Light> lights;
|
||||
MWWorld::CellRefList<ESM::Tool> lockpicks;
|
||||
MWWorld::CellRefList<ESM::Miscellaneous> miscItems;
|
||||
MWWorld::CellRefList<ESM::Probe> probes;
|
||||
MWWorld::CellRefList<ESM::Repair> repairs;
|
||||
MWWorld::CellRefList<ESM::Weapon> weapons;
|
||||
int mStateId;
|
||||
mutable float mCachedWeight;
|
||||
mutable bool mWeightUpToDate;
|
||||
|
@ -120,18 +120,18 @@ namespace MWWorld
|
|||
ContainerStore *mContainer;
|
||||
mutable Ptr mPtr;
|
||||
|
||||
MWWorld::ContainerRefList<ESM::Potion>::List::iterator mPotion;
|
||||
MWWorld::ContainerRefList<ESM::Apparatus>::List::iterator mApparatus;
|
||||
MWWorld::ContainerRefList<ESM::Armor>::List::iterator mArmor;
|
||||
MWWorld::ContainerRefList<ESM::Book>::List::iterator mBook;
|
||||
MWWorld::ContainerRefList<ESM::Clothing>::List::iterator mClothing;
|
||||
MWWorld::ContainerRefList<ESM::Ingredient>::List::iterator mIngredient;
|
||||
MWWorld::ContainerRefList<ESM::Light>::List::iterator mLight;
|
||||
MWWorld::ContainerRefList<ESM::Tool>::List::iterator mLockpick;
|
||||
MWWorld::ContainerRefList<ESM::Miscellaneous>::List::iterator mMiscellaneous;
|
||||
MWWorld::ContainerRefList<ESM::Probe>::List::iterator mProbe;
|
||||
MWWorld::ContainerRefList<ESM::Repair>::List::iterator mRepair;
|
||||
MWWorld::ContainerRefList<ESM::Weapon>::List::iterator mWeapon;
|
||||
MWWorld::CellRefList<ESM::Potion>::List::iterator mPotion;
|
||||
MWWorld::CellRefList<ESM::Apparatus>::List::iterator mApparatus;
|
||||
MWWorld::CellRefList<ESM::Armor>::List::iterator mArmor;
|
||||
MWWorld::CellRefList<ESM::Book>::List::iterator mBook;
|
||||
MWWorld::CellRefList<ESM::Clothing>::List::iterator mClothing;
|
||||
MWWorld::CellRefList<ESM::Ingredient>::List::iterator mIngredient;
|
||||
MWWorld::CellRefList<ESM::Light>::List::iterator mLight;
|
||||
MWWorld::CellRefList<ESM::Tool>::List::iterator mLockpick;
|
||||
MWWorld::CellRefList<ESM::Miscellaneous>::List::iterator mMiscellaneous;
|
||||
MWWorld::CellRefList<ESM::Probe>::List::iterator mProbe;
|
||||
MWWorld::CellRefList<ESM::Repair>::List::iterator mRepair;
|
||||
MWWorld::CellRefList<ESM::Weapon>::List::iterator mWeapon;
|
||||
|
||||
private:
|
||||
|
||||
|
@ -142,18 +142,18 @@ namespace MWWorld
|
|||
///< Begin-iterator
|
||||
|
||||
// construct iterator using a CellRefList iterator
|
||||
ContainerStoreIterator (ContainerStore *container, MWWorld::ContainerRefList<ESM::Potion>::List::iterator);
|
||||
ContainerStoreIterator (ContainerStore *container, MWWorld::ContainerRefList<ESM::Apparatus>::List::iterator);
|
||||
ContainerStoreIterator (ContainerStore *container, MWWorld::ContainerRefList<ESM::Armor>::List::iterator);
|
||||
ContainerStoreIterator (ContainerStore *container, MWWorld::ContainerRefList<ESM::Book>::List::iterator);
|
||||
ContainerStoreIterator (ContainerStore *container, MWWorld::ContainerRefList<ESM::Clothing>::List::iterator);
|
||||
ContainerStoreIterator (ContainerStore *container, MWWorld::ContainerRefList<ESM::Ingredient>::List::iterator);
|
||||
ContainerStoreIterator (ContainerStore *container, MWWorld::ContainerRefList<ESM::Light>::List::iterator);
|
||||
ContainerStoreIterator (ContainerStore *container, MWWorld::ContainerRefList<ESM::Tool>::List::iterator);
|
||||
ContainerStoreIterator (ContainerStore *container, MWWorld::ContainerRefList<ESM::Miscellaneous>::List::iterator);
|
||||
ContainerStoreIterator (ContainerStore *container, MWWorld::ContainerRefList<ESM::Probe>::List::iterator);
|
||||
ContainerStoreIterator (ContainerStore *container, MWWorld::ContainerRefList<ESM::Repair>::List::iterator);
|
||||
ContainerStoreIterator (ContainerStore *container, MWWorld::ContainerRefList<ESM::Weapon>::List::iterator);
|
||||
ContainerStoreIterator (ContainerStore *container, MWWorld::CellRefList<ESM::Potion>::List::iterator);
|
||||
ContainerStoreIterator (ContainerStore *container, MWWorld::CellRefList<ESM::Apparatus>::List::iterator);
|
||||
ContainerStoreIterator (ContainerStore *container, MWWorld::CellRefList<ESM::Armor>::List::iterator);
|
||||
ContainerStoreIterator (ContainerStore *container, MWWorld::CellRefList<ESM::Book>::List::iterator);
|
||||
ContainerStoreIterator (ContainerStore *container, MWWorld::CellRefList<ESM::Clothing>::List::iterator);
|
||||
ContainerStoreIterator (ContainerStore *container, MWWorld::CellRefList<ESM::Ingredient>::List::iterator);
|
||||
ContainerStoreIterator (ContainerStore *container, MWWorld::CellRefList<ESM::Light>::List::iterator);
|
||||
ContainerStoreIterator (ContainerStore *container, MWWorld::CellRefList<ESM::Tool>::List::iterator);
|
||||
ContainerStoreIterator (ContainerStore *container, MWWorld::CellRefList<ESM::Miscellaneous>::List::iterator);
|
||||
ContainerStoreIterator (ContainerStore *container, MWWorld::CellRefList<ESM::Probe>::List::iterator);
|
||||
ContainerStoreIterator (ContainerStore *container, MWWorld::CellRefList<ESM::Repair>::List::iterator);
|
||||
ContainerStoreIterator (ContainerStore *container, MWWorld::CellRefList<ESM::Weapon>::List::iterator);
|
||||
|
||||
void incType();
|
||||
|
||||
|
|
|
@ -17,9 +17,9 @@ namespace
|
|||
cellRefList.mList.begin());
|
||||
iter!=cellRefList.mList.end(); ++iter)
|
||||
{
|
||||
if (!iter->second.mBase->mScript.empty() && iter->second.mData.getCount())
|
||||
if (!iter->mBase->mScript.empty() && iter->mData.getCount())
|
||||
{
|
||||
localScripts.add (iter->second.mBase->mScript, MWWorld::Ptr (&iter->second, cell));
|
||||
localScripts.add (iter->mBase->mScript, MWWorld::Ptr (&*iter, cell));
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -34,7 +34,7 @@ namespace
|
|||
iter!=cellRefList.mList.end(); ++iter)
|
||||
{
|
||||
|
||||
MWWorld::Ptr containerPtr (&iter->second, cell);
|
||||
MWWorld::Ptr containerPtr (&*iter, cell);
|
||||
|
||||
MWWorld::ContainerStore& container = MWWorld::Class::get(containerPtr).getContainerStore(containerPtr);
|
||||
for(MWWorld::ContainerStoreIterator it3 = container.begin(); it3 != container.end(); ++it3)
|
||||
|
|
|
@ -23,7 +23,7 @@ namespace
|
|||
if (!cellRefList.mList.empty())
|
||||
{
|
||||
const MWWorld::Class& class_ =
|
||||
MWWorld::Class::get (MWWorld::Ptr (&cellRefList.mList.begin()->second, &cell));
|
||||
MWWorld::Class::get (MWWorld::Ptr (&*cellRefList.mList.begin(), &cell));
|
||||
|
||||
int numRefs = cellRefList.mList.size();
|
||||
int current = 0;
|
||||
|
@ -33,9 +33,9 @@ namespace
|
|||
MWBase::Environment::get().getWindowManager ()->setLoadingProgress ("Loading cells", 1, current, numRefs);
|
||||
++current;
|
||||
|
||||
if (it->second.mData.getCount() || it->second.mData.isEnabled())
|
||||
if (it->mData.getCount() || it->mData.isEnabled())
|
||||
{
|
||||
MWWorld::Ptr ptr (&it->second, &cell);
|
||||
MWWorld::Ptr ptr (&*it, &cell);
|
||||
|
||||
try
|
||||
{
|
||||
|
|
65
apps/openmw/mwworld/store.cpp
Normal file
65
apps/openmw/mwworld/store.cpp
Normal file
|
@ -0,0 +1,65 @@
|
|||
#include "store.hpp"
|
||||
|
||||
namespace MWWorld {
|
||||
|
||||
|
||||
void Store<ESM::Cell>::load(ESM::ESMReader &esm, const std::string &id)
|
||||
{
|
||||
// Don't automatically assume that a new cell must be spawned. Multiple plugins write to the same cell,
|
||||
// and we merge all this data into one Cell object. However, we can't simply search for the cell id,
|
||||
// as many exterior cells do not have a name. Instead, we need to search by (x,y) coordinates - and they
|
||||
// are not available until both cells have been loaded! So first, proceed as usual.
|
||||
|
||||
// All cells have a name record, even nameless exterior cells.
|
||||
std::string idLower = Misc::StringUtils::lowerCase(id);
|
||||
ESM::Cell *cell = new ESM::Cell;
|
||||
cell->mName = id;
|
||||
|
||||
// The cell itself takes care of some of the hairy details
|
||||
cell->load(esm, *mEsmStore);
|
||||
|
||||
if(cell->mData.mFlags & ESM::Cell::Interior)
|
||||
{
|
||||
// Store interior cell by name, try to merge with existing parent data.
|
||||
ESM::Cell *oldcell = const_cast<ESM::Cell*>(search(idLower));
|
||||
if (oldcell) {
|
||||
// push the new references on the list of references to manage
|
||||
oldcell->mContextList.push_back(cell->mContextList.at(0));
|
||||
// copy list into new cell
|
||||
cell->mContextList = oldcell->mContextList;
|
||||
// have new cell replace old cell
|
||||
*oldcell = *cell;
|
||||
} else
|
||||
mInt[idLower] = *cell;
|
||||
}
|
||||
else
|
||||
{
|
||||
// Store exterior cells by grid position, try to merge with existing parent data.
|
||||
ESM::Cell *oldcell = const_cast<ESM::Cell*>(search(cell->getGridX(), cell->getGridY()));
|
||||
if (oldcell) {
|
||||
// push the new references on the list of references to manage
|
||||
oldcell->mContextList.push_back(cell->mContextList.at(0));
|
||||
// copy list into new cell
|
||||
cell->mContextList = oldcell->mContextList;
|
||||
// merge lists of leased references, use newer data in case of conflict
|
||||
for (ESM::MovedCellRefTracker::const_iterator it = cell->mMovedRefs.begin(); it != cell->mMovedRefs.end(); it++) {
|
||||
// remove reference from current leased ref tracker and add it to new cell
|
||||
ESM::MovedCellRefTracker::iterator itold = std::find(oldcell->mMovedRefs.begin(), oldcell->mMovedRefs.end(), it->mRefnum);
|
||||
if (itold != oldcell->mMovedRefs.end()) {
|
||||
ESM::MovedCellRef target0 = *itold;
|
||||
ESM::Cell *wipecell = const_cast<ESM::Cell*>(search(target0.mTarget[0], target0.mTarget[1]));
|
||||
ESM::CellRefTracker::iterator it_lease = std::find(wipecell->mLeasedRefs.begin(), wipecell->mLeasedRefs.end(), it->mRefnum);
|
||||
wipecell->mLeasedRefs.erase(it_lease);
|
||||
*itold = *it;
|
||||
}
|
||||
}
|
||||
cell->mMovedRefs = oldcell->mMovedRefs;
|
||||
// have new cell replace old cell
|
||||
*oldcell = *cell;
|
||||
} else
|
||||
mExt[std::make_pair(cell->mData.mX, cell->mData.mY)] = *cell;
|
||||
}
|
||||
delete cell;
|
||||
}
|
||||
|
||||
}
|
|
@ -187,7 +187,7 @@ namespace MWWorld
|
|||
T item;
|
||||
item.mId = Misc::StringUtils::lowerCase(id);
|
||||
|
||||
typename std::map<std::string, T>::const_iterator it = mStatic.find(item.mId);
|
||||
typename std::map<std::string, T>::iterator it = mStatic.find(item.mId);
|
||||
|
||||
if (it != mStatic.end() && Misc::StringUtils::ciEqual(it->second.mId, id)) {
|
||||
mStatic.erase(it);
|
||||
|
@ -523,62 +523,12 @@ namespace MWWorld
|
|||
}
|
||||
}
|
||||
|
||||
void load(ESM::ESMReader &esm, const std::string &id) {
|
||||
// Don't automatically assume that a new cell must be spawned. Multiple plugins write to the same cell,
|
||||
// and we merge all this data into one Cell object. However, we can't simply search for the cell id,
|
||||
// as many exterior cells do not have a name. Instead, we need to search by (x,y) coordinates - and they
|
||||
// are not available until both cells have been loaded! So first, proceed as usual.
|
||||
|
||||
// All cells have a name record, even nameless exterior cells.
|
||||
std::string idLower = Misc::StringUtils::lowerCase(id);
|
||||
ESM::Cell *cell = new ESM::Cell;
|
||||
cell->mName = id;
|
||||
|
||||
// The cell itself takes care of all the hairy details
|
||||
cell->load(esm, *mEsmStore);
|
||||
|
||||
if(cell->mData.mFlags & ESM::Cell::Interior)
|
||||
{
|
||||
// Store interior cell by name, try to merge with existing parent data.
|
||||
ESM::Cell *oldcell = const_cast<ESM::Cell*>(search(idLower));
|
||||
if (oldcell) {
|
||||
// push the new references on the list of references to manage
|
||||
oldcell->mContextList.push_back(cell->mContextList.at(0));
|
||||
// copy list into new cell
|
||||
cell->mContextList = oldcell->mContextList;
|
||||
// have new cell replace old cell
|
||||
*oldcell = *cell;
|
||||
} else
|
||||
mInt[idLower] = *cell;
|
||||
}
|
||||
else
|
||||
{
|
||||
// Store exterior cells by grid position, try to merge with existing parent data.
|
||||
ESM::Cell *oldcell = const_cast<ESM::Cell*>(search(cell->getGridX(), cell->getGridY()));
|
||||
if (oldcell) {
|
||||
// push the new references on the list of references to manage
|
||||
oldcell->mContextList.push_back(cell->mContextList.at(0));
|
||||
// copy list into new cell
|
||||
cell->mContextList = oldcell->mContextList;
|
||||
// merge lists of leased references, use newer data in case of conflict
|
||||
for (ESM::MovedCellRefTracker::const_iterator it = cell->mMovedRefs.begin(); it != cell->mMovedRefs.end(); it++) {
|
||||
// remove reference from current leased ref tracker and add it to new cell
|
||||
if (oldcell->mMovedRefs.find(it->second.mRefnum) != oldcell->mMovedRefs.end()) {
|
||||
ESM::MovedCellRef target0 = oldcell->mMovedRefs[it->second.mRefnum];
|
||||
ESM::Cell *wipecell = const_cast<ESM::Cell*>(search(target0.mTarget[0], target0.mTarget[1]));
|
||||
wipecell->mLeasedRefs.erase(it->second.mRefnum);
|
||||
}
|
||||
oldcell->mMovedRefs[it->second.mRefnum] = it->second;
|
||||
}
|
||||
cell->mMovedRefs = oldcell->mMovedRefs;
|
||||
// have new cell replace old cell
|
||||
*oldcell = *cell;
|
||||
} else
|
||||
mExt[std::make_pair(cell->mData.mX, cell->mData.mY)] = *cell;
|
||||
}
|
||||
delete cell;
|
||||
}
|
||||
|
||||
// HACK: Method implementation had to be moved to a separate cpp file, as we would otherwise get
|
||||
// errors related to the compare operator used in std::find for ESM::MovedCellRefTracker::find.
|
||||
// There some nasty three-way cyclic header dependency involved, which I could only fix by moving
|
||||
// this method.
|
||||
void load(ESM::ESMReader &esm, const std::string &id);
|
||||
|
||||
iterator intBegin() const {
|
||||
return iterator(mSharedInt.begin());
|
||||
}
|
||||
|
|
|
@ -33,13 +33,13 @@ namespace
|
|||
cellRefList.mList.begin());
|
||||
iter!=cellRefList.mList.end(); ++iter)
|
||||
{
|
||||
if (!iter->second.mBase->mScript.empty() && iter->second.mData.getCount())
|
||||
if (!iter->mBase->mScript.empty() && iter->mData.getCount())
|
||||
{
|
||||
if (const ESM::Script *script = store.get<ESM::Script>().find (iter->second.mBase->mScript))
|
||||
if (const ESM::Script *script = store.get<ESM::Script>().find (iter->mBase->mScript))
|
||||
{
|
||||
iter->mData.setLocals (*script);
|
||||
|
||||
localScripts.add (iter->second.mBase->mScript, MWWorld::Ptr (&iter->second, cell));
|
||||
localScripts.add (iter->mBase->mScript, MWWorld::Ptr (&*iter, cell));
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -53,10 +53,10 @@ namespace
|
|||
|
||||
for (iterator iter (refList.mList.begin()); iter!=refList.mList.end(); ++iter)
|
||||
{
|
||||
if (iter->second.mData.getCount() > 0 && iter->second.mData.getBaseNode()){
|
||||
if (iter->second.mData.getHandle()==handle)
|
||||
if (iter->mData.getCount() > 0 && iter->mData.getBaseNode()){
|
||||
if (iter->mData.getHandle()==handle)
|
||||
{
|
||||
return &iter->second;
|
||||
return &*iter;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -1261,7 +1261,7 @@ namespace MWWorld
|
|||
CellRefList<ESM::Door>::List& refList = doors.mList;
|
||||
for (CellRefList<ESM::Door>::List::iterator it = refList.begin(); it != refList.end(); ++it)
|
||||
{
|
||||
MWWorld::LiveCellRef<ESM::Door>& ref = it->second;
|
||||
MWWorld::LiveCellRef<ESM::Door>& ref = *it;
|
||||
|
||||
if (ref.mRef.mTeleport)
|
||||
{
|
||||
|
|
|
@ -14,6 +14,17 @@
|
|||
namespace ESM
|
||||
{
|
||||
|
||||
/// Some overloaded copare operators.
|
||||
bool operator==(const MovedCellRef& ref, int pRefnum)
|
||||
{
|
||||
return (ref.mRefnum == pRefnum);
|
||||
}
|
||||
|
||||
bool operator==(const CellRef& ref, int pRefnum)
|
||||
{
|
||||
return (ref.mRefnum == pRefnum);
|
||||
}
|
||||
|
||||
void CellRef::save(ESMWriter &esm)
|
||||
{
|
||||
esm.writeHNT("FRMR", mRefnum);
|
||||
|
@ -134,13 +145,14 @@ void Cell::load(ESMReader &esm, MWWorld::ESMStore &store)
|
|||
(int(*)(int)) std::tolower);
|
||||
|
||||
// Add data required to make reference appear in the correct cell.
|
||||
/*
|
||||
std::cout << "Moving refnumber! First cell: " << mData.mX << " " << mData.mY << std::endl;
|
||||
std::cout << " New cell: " << cMRef.mTarget[0] << " " << cMRef.mTarget[0] << std::endl;
|
||||
std::cout << "Refnumber (MVRF): " << cMRef.mRefnum << " (FRMR) " << ref.mRefnum << std::endl;
|
||||
*/
|
||||
mMovedRefs[cMRef.mRefnum] = cMRef;
|
||||
cellAlt->mLeasedRefs[ref.mRefnum] = ref;
|
||||
// We should not need to test for duplicates, as this part of the code is pre-cell merge.
|
||||
mMovedRefs.push_back(cMRef);
|
||||
// But there may be duplicates here!
|
||||
ESM::CellRefTracker::iterator iter = std::find(cellAlt->mLeasedRefs.begin(), cellAlt->mLeasedRefs.end(), ref.mRefnum);
|
||||
if (iter == cellAlt->mLeasedRefs.end())
|
||||
cellAlt->mLeasedRefs.push_back(ref);
|
||||
else
|
||||
*iter = ref;
|
||||
}
|
||||
|
||||
// Save position of the cell references and move on
|
||||
|
|
|
@ -6,7 +6,7 @@
|
|||
|
||||
#include "esmcommon.hpp"
|
||||
#include "defs.hpp"
|
||||
#include <apps/openmw/mwbase/world.hpp>
|
||||
#include "apps/openmw/mwbase/world.hpp"
|
||||
|
||||
/*
|
||||
namespace MWWorld {
|
||||
|
@ -95,24 +95,29 @@ public:
|
|||
};
|
||||
|
||||
/* Moved cell reference tracking object. This mainly stores the target cell
|
||||
of the reference, so we can easily know where it has been moved when another
|
||||
plugin tries to move it independently.
|
||||
*/
|
||||
of the reference, so we can easily know where it has been moved when another
|
||||
plugin tries to move it independently.
|
||||
Unfortunately, we need to implement this here.
|
||||
*/
|
||||
class MovedCellRef
|
||||
{
|
||||
public:
|
||||
int mRefnum;
|
||||
|
||||
// Target cell (if exterior)
|
||||
int mTarget[2];
|
||||
|
||||
// TODO: Support moving references between exterior and interior cells!
|
||||
// This may happen in saves, when an NPC follows the player. Tribunal
|
||||
// introduces a henchman (which no one uses), so we may need this as well.
|
||||
int mRefnum;
|
||||
|
||||
// Target cell (if exterior)
|
||||
int mTarget[2];
|
||||
|
||||
// TODO: Support moving references between exterior and interior cells!
|
||||
// This may happen in saves, when an NPC follows the player. Tribunal
|
||||
// introduces a henchman (which no one uses), so we may need this as well.
|
||||
};
|
||||
|
||||
typedef std::map<int, MovedCellRef> MovedCellRefTracker;
|
||||
typedef std::map<int, CellRef> CellRefTracker;
|
||||
/// Overloaded copare operator used to search inside a list of cell refs.
|
||||
bool operator==(const MovedCellRef& ref, int pRefnum);
|
||||
bool operator==(const CellRef& ref, int pRefnum);
|
||||
|
||||
typedef std::list<MovedCellRef> MovedCellRefTracker;
|
||||
typedef std::list<CellRef> CellRefTracker;
|
||||
|
||||
/* Cells hold data about objects, creatures, statics (rocks, walls,
|
||||
buildings) and landscape (for exterior cells). Cells frequently
|
||||
|
|
Loading…
Reference in a new issue