Change save format to store relative equipment index

Store the index for the allowedSlots vector instead of the absolute slot index. This will more gracefully handle edge cases like the available slots for an item having changed when loading the game, or the "allows stacking" property having changed. However the main reason this was done is to ease work on the essimporter.
openmw-35
scrawl 10 years ago
parent 142a138b75
commit 89d9649b50

@ -466,7 +466,7 @@ namespace MWWorld
// List moved references, from separately tracked list.
for (ESM::CellRefTracker::const_iterator it = mCell->mLeasedRefs.begin(); it != mCell->mLeasedRefs.end(); ++it)
{
ESM::CellRef &ref = const_cast<ESM::CellRef&>(*it);
const ESM::CellRef &ref = *it;
mIds.push_back(Misc::StringUtils::lowerCase(ref.mRefID));
}

@ -85,28 +85,29 @@ void MWWorld::ContainerStore::storeState (const LiveCellRef<T>& ref, ESM::Object
ref.save (state);
}
/// \todo make this method const once const-correct ContainerStoreIterators are available
template<typename T>
void MWWorld::ContainerStore::storeStates (const CellRefList<T>& collection,
std::vector<std::pair<ESM::ObjectState, int> >& states, bool equipable) const
void MWWorld::ContainerStore::storeStates (CellRefList<T>& collection,
std::vector<std::pair<ESM::ObjectState, int> >& states, bool equipable)
{
for (typename CellRefList<T>::List::const_iterator iter (collection.mList.begin());
for (typename CellRefList<T>::List::iterator iter (collection.mList.begin());
iter!=collection.mList.end(); ++iter)
{
if (iter->mData.getCount() == 0)
continue;
ESM::ObjectState state;
storeState (*iter, state);
int slot = equipable ? getSlot (*iter) : -1;
int slot = equipable ? getRelativeSlot (MWWorld::ContainerStoreIterator(this, iter)) : -1;
states.push_back (std::make_pair (state, slot));
}
}
int MWWorld::ContainerStore::getSlot (const MWWorld::LiveCellRefBase& ref) const
int MWWorld::ContainerStore::getRelativeSlot (const MWWorld::ContainerStoreIterator& iter) const
{
return -1;
}
void MWWorld::ContainerStore::setSlot (const MWWorld::ContainerStoreIterator& iter, int slot) {}
void MWWorld::ContainerStore::setRelativeSlot (const MWWorld::ContainerStoreIterator& iter, int slot) {}
const std::string MWWorld::ContainerStore::sGoldId = "gold_001";
@ -641,7 +642,7 @@ MWWorld::Ptr MWWorld::ContainerStore::search (const std::string& id)
return Ptr();
}
void MWWorld::ContainerStore::writeState (ESM::InventoryState& state) const
void MWWorld::ContainerStore::writeState (ESM::InventoryState& state)
{
state.mItems.clear();
@ -678,16 +679,16 @@ void MWWorld::ContainerStore::readState (const ESM::InventoryState& state)
{
case ESM::REC_ALCH: getState (potions, iter->first); break;
case ESM::REC_APPA: getState (appas, iter->first); break;
case ESM::REC_ARMO: setSlot (getState (armors, iter->first), slot); break;
case ESM::REC_ARMO: setRelativeSlot (getState (armors, iter->first), slot); break;
case ESM::REC_BOOK: getState (books, iter->first); break;
case ESM::REC_CLOT: setSlot (getState (clothes, iter->first), slot); break;
case ESM::REC_CLOT: setRelativeSlot (getState (clothes, iter->first), slot); break;
case ESM::REC_INGR: getState (ingreds, iter->first); break;
case ESM::REC_LOCK: setSlot (getState (lockpicks, iter->first), slot); break;
case ESM::REC_LOCK: setRelativeSlot (getState (lockpicks, iter->first), slot); break;
case ESM::REC_MISC: getState (miscItems, iter->first); break;
case ESM::REC_PROB: setSlot (getState (probes, iter->first), slot); break;
case ESM::REC_PROB: setRelativeSlot (getState (probes, iter->first), slot); break;
case ESM::REC_REPA: getState (repairs, iter->first); break;
case ESM::REC_WEAP: setSlot (getState (weapons, iter->first), slot); break;
case ESM::REC_LIGH: setSlot (getState (lights, iter->first), slot); break;
case ESM::REC_WEAP: setRelativeSlot (getState (weapons, iter->first), slot); break;
case ESM::REC_LIGH: setRelativeSlot (getState (lights, iter->first), slot); break;
default:
std::cerr << "invalid item type in inventory state, refid " << state.mRef.mRefID << std::endl;

@ -84,15 +84,16 @@ namespace MWWorld
template<typename T>
void storeState (const LiveCellRef<T>& ref, ESM::ObjectState& state) const;
/// \todo make this method const once const-correct ContainerStoreIterators are available
template<typename T>
void storeStates (const CellRefList<T>& collection,
void storeStates (CellRefList<T>& collection,
std::vector<std::pair<ESM::ObjectState, int> >& states,
bool equipable = false) const;
bool equipable = false);
virtual int getSlot (const MWWorld::LiveCellRefBase& ref) const;
virtual int getRelativeSlot (const MWWorld::ContainerStoreIterator& iter) const;
///< Return inventory slot that \a ref is in or -1 (if \a ref is not in a slot).
virtual void setSlot (const MWWorld::ContainerStoreIterator& iter, int slot);
virtual void setRelativeSlot (const MWWorld::ContainerStoreIterator& iter, int slot);
///< Set slot for \a iter. Ignored if \a iter is an end iterator or if slot==-1.
public:
@ -171,7 +172,8 @@ namespace MWWorld
Ptr search (const std::string& id);
virtual void writeState (ESM::InventoryState& state) const;
/// \todo make this method const once const-correct ContainerStoreIterators are available
virtual void writeState (ESM::InventoryState& state);
virtual void readState (const ESM::InventoryState& state);

@ -49,19 +49,40 @@ void MWWorld::InventoryStore::initSlots (TSlots& slots_)
slots_.push_back (end());
}
int MWWorld::InventoryStore::getSlot (const MWWorld::LiveCellRefBase& ref) const
int MWWorld::InventoryStore::getRelativeSlot (const MWWorld::ContainerStoreIterator& iter)
{
for (int i = 0; i<static_cast<int> (mSlots.size()); ++i)
if (mSlots[i].getType()!=-1 && mSlots[i]->getBase()==&ref)
return i;
if (mSlots[i].getType()!=-1 && mSlots[i] == iter)
{
// linear complexity, but allowedSlots is most of the time just 1 anyway
std::vector<int> allowedSlots = iter->getClass().getEquipmentSlots(*iter).first;
std::vector<int>::iterator found = std::find(allowedSlots.begin(),allowedSlots.end(),i);
if (found == allowedSlots.end())
return -1;
else
return std::distance(allowedSlots.begin(), found);
}
return -1;
}
void MWWorld::InventoryStore::setSlot (const MWWorld::ContainerStoreIterator& iter, int slot)
void MWWorld::InventoryStore::setRelativeSlot (const MWWorld::ContainerStoreIterator& iter, int relativeSlot)
{
if (iter!=end() && slot>=0 && slot<Slots)
mSlots[slot] = iter;
if (relativeSlot < 0 || iter == end())
return;
std::pair<std::vector<int>, bool> allowedSlots = iter->getClass().getEquipmentSlots(*iter);
relativeSlot = std::min(int(allowedSlots.first.size()-1), relativeSlot);
// unstack if required
if (!allowedSlots.second && iter->getRefData().getCount() > 1)
{
MWWorld::ContainerStoreIterator newIter = addNewStack(*iter, 1);
iter->getRefData().setCount(iter->getRefData().getCount()-1);
mSlots[allowedSlots.first[relativeSlot]] = newIter;
}
else
mSlots[allowedSlots.first[relativeSlot]] = iter;
}
MWWorld::InventoryStore::InventoryStore()
@ -703,7 +724,7 @@ bool MWWorld::InventoryStore::isEquipped(const MWWorld::Ptr &item)
return false;
}
void MWWorld::InventoryStore::writeState(ESM::InventoryState &state) const
void MWWorld::InventoryStore::writeState(ESM::InventoryState &state)
{
MWWorld::ContainerStore::writeState(state);

@ -113,10 +113,10 @@ namespace MWWorld
void fireEquipmentChangedEvent();
virtual int getSlot (const MWWorld::LiveCellRefBase& ref) const;
virtual int getRelativeSlot (const MWWorld::ContainerStoreIterator& iter);
///< Return inventory slot that \a ref is in or -1 (if \a ref is not in a slot).
virtual void setSlot (const MWWorld::ContainerStoreIterator& iter, int slot);
virtual void setRelativeSlot (const MWWorld::ContainerStoreIterator& iter, int relativeSlot);
///< Set slot for \a iter. Ignored if \a iter is an end iterator or if slot==-1.
public:
@ -209,7 +209,7 @@ namespace MWWorld
virtual void clear();
///< Empty container.
virtual void writeState (ESM::InventoryState& state) const;
virtual void writeState (ESM::InventoryState& state);
virtual void readState (const ESM::InventoryState& state);
};

@ -2031,7 +2031,7 @@ namespace MWWorld
bool World::isOnGround(const MWWorld::Ptr &ptr) const
{
RefData &refdata = ptr.getRefData();
const OEngine::Physic::PhysicActor *physactor = mPhysEngine->getCharacter(refdata.getHandle());
OEngine::Physic::PhysicActor *physactor = mPhysEngine->getCharacter(refdata.getHandle());
if(!physactor)
return false;
@ -2049,7 +2049,7 @@ namespace MWWorld
mPhysEngine);
if(tracer.mFraction < 1.0f) // collision, must be close to something below
{
const_cast<OEngine::Physic::PhysicActor *> (physactor)->setOnGround(true);
physactor->setOnGround(true);
return true;
}
else

@ -15,6 +15,7 @@ namespace ESM
/// \brief State for inventories and containers
struct InventoryState
{
/// <ObjectState, relative equipment slot>
std::vector<std::pair<ObjectState, int> > mItems;
std::map<std::string, int> mLevelledItemMap;

Loading…
Cancel
Save