store content of containers in saved game files

actorid
Marc Zinnschlag 11 years ago
parent 900532a6ca
commit dd674566a2

@ -2,6 +2,7 @@
#include "container.hpp"
#include <components/esm/loadcont.hpp>
#include <components/esm/containerstate.hpp>
#include "../mwbase/environment.hpp"
#include "../mwbase/world.hpp"
@ -258,4 +259,26 @@ namespace MWClass
return MWWorld::Ptr(&cell.mContainers.insert(*ref), &cell);
}
void Container::readAdditionalState (const MWWorld::Ptr& ptr, const ESM::ObjectState& state)
const
{
const ESM::ContainerState& state2 = dynamic_cast<const ESM::ContainerState&> (state);
ensureCustomData (ptr);
dynamic_cast<CustomData&> (*ptr.getRefData().getCustomData()).mContainerStore.
readState (state2.mInventory);
}
void Container::writeAdditionalState (const MWWorld::Ptr& ptr, ESM::ObjectState& state)
const
{
ESM::ContainerState& state2 = dynamic_cast<ESM::ContainerState&> (state);
ensureCustomData (ptr);
dynamic_cast<CustomData&> (*ptr.getRefData().getCustomData()).mContainerStore.
writeState (state2.mInventory);
}
}

@ -54,6 +54,14 @@ namespace MWClass
virtual void unlock (const MWWorld::Ptr& ptr) const;
///< Unlock object
virtual void readAdditionalState (const MWWorld::Ptr& ptr, const ESM::ObjectState& state)
const;
///< Read additional state from \a state into \a ptr.
virtual void writeAdditionalState (const MWWorld::Ptr& ptr, ESM::ObjectState& state)
const;
///< Write additional state from \a ptr into \a state.
static void registerSelf();
virtual std::string getModel(const MWWorld::Ptr &ptr) const;

@ -7,6 +7,7 @@
#include <components/esm/esmwriter.hpp>
#include <components/esm/objectstate.hpp>
#include <components/esm/lightstate.hpp>
#include <components/esm/containerstate.hpp>
#include "../mwbase/environment.hpp"
#include "../mwbase/world.hpp"
@ -326,7 +327,7 @@ namespace MWWorld
writeReferenceCollection<ESM::ObjectState> (writer, mArmors);
writeReferenceCollection<ESM::ObjectState> (writer, mBooks);
writeReferenceCollection<ESM::ObjectState> (writer, mClothes);
writeReferenceCollection<ESM::ObjectState> (writer, mContainers);
writeReferenceCollection<ESM::ContainerState> (writer, mContainers);
writeReferenceCollection<ESM::ObjectState> (writer, mCreatures);
writeReferenceCollection<ESM::ObjectState> (writer, mDoors);
writeReferenceCollection<ESM::ObjectState> (writer, mIngreds);
@ -384,7 +385,7 @@ namespace MWWorld
case ESM::REC_CONT:
readReferenceCollection<ESM::ObjectState> (reader, mContainers, contentFileMap);
readReferenceCollection<ESM::ContainerState> (reader, mContainers, contentFileMap);
break;
case ESM::REC_CREA:

@ -5,6 +5,8 @@
#include <typeinfo>
#include <stdexcept>
#include <components/esm/inventorystate.hpp>
#include "../mwbase/environment.hpp"
#include "../mwbase/world.hpp"
@ -55,6 +57,43 @@ namespace
return MWWorld::Ptr();
}
template<typename T>
void getState (MWWorld::CellRefList<T>& collection, const ESM::ObjectState& state)
{
if (!MWWorld::LiveCellRef<T>::checkState (state))
return; // not valid anymore with current content files -> skip
const T *record = MWBase::Environment::get().getWorld()->getStore().
get<T>().search (state.mRef.mRefID);
if (!record)
return;
MWWorld::LiveCellRef<T> ref (record);
ref.load (state);
ref.mRef.mRefNum.mContentFile = -1;
collection.mList.push_back (ref);
}
template<typename T>
void storeState (const MWWorld::LiveCellRef<T>& ref, ESM::ObjectState& state)
{
ref.save (state);
}
template<typename T>
void storeStates (const MWWorld::CellRefList<T>& collection,
std::vector<std::pair<ESM::ObjectState, std::pair<unsigned int, int> > >& states)
{
for (typename MWWorld::CellRefList<T>::List::const_iterator iter (collection.mList.begin());
iter!=collection.mList.end(); ++iter)
{
ESM::ObjectState state;
storeState (*iter, state);
states.push_back (std::make_pair (state, std::make_pair (T::sRecordId, -1)));
}
}
}
const std::string MWWorld::ContainerStore::sGoldId = "gold_001";
@ -495,6 +534,67 @@ MWWorld::Ptr MWWorld::ContainerStore::search (const std::string& id)
return Ptr();
}
void MWWorld::ContainerStore::writeState (ESM::InventoryState& state) const
{
state.mItems.clear();
storeStates (potions, state.mItems);
storeStates (appas, state.mItems);
storeStates (armors, state.mItems);
storeStates (books, state.mItems);
storeStates (clothes, state.mItems);
storeStates (ingreds, state.mItems);
storeStates (lockpicks, state.mItems);
storeStates (miscItems, state.mItems);
storeStates (probes, state.mItems);
storeStates (repairs, state.mItems);
storeStates (weapons, state.mItems);
state.mLights.clear();
for (MWWorld::CellRefList<ESM::Light>::List::const_iterator iter (lights.mList.begin());
iter!=lights.mList.end(); ++iter)
{
ESM::LightState objectState;
storeState (*iter, objectState);
state.mLights.push_back (std::make_pair (objectState, -1));
}
}
void MWWorld::ContainerStore::readState (const ESM::InventoryState& state)
{
clear();
for (std::vector<std::pair<ESM::ObjectState, std::pair<unsigned int, int> > >::const_iterator
iter (state.mItems.begin()); iter!=state.mItems.end(); ++iter)
{
switch (iter->second.first)
{
case ESM::REC_ALCH: getState (potions, iter->first); break;
case ESM::REC_APPA: getState (appas, iter->first); break;
case ESM::REC_ARMO: getState (armors, iter->first); break;
case ESM::REC_BOOK: getState (books, iter->first); break;
case ESM::REC_CLOT: getState (clothes, iter->first); break;
case ESM::REC_INGR: getState (ingreds, iter->first); break;
case ESM::REC_LOCK: getState (lockpicks, iter->first); break;
case ESM::REC_MISC: getState (miscItems, iter->first); break;
case ESM::REC_PROB: getState (probes, iter->first); break;
case ESM::REC_REPA: getState (repairs, iter->first); break;
case ESM::REC_WEAP: getState (weapons, iter->first); break;
default:
std::cerr << "invalid item type in inventory state" << std::endl;
}
}
for (std::vector<std::pair<ESM::LightState, int> >::const_iterator iter (state.mLights.begin());
iter!=state.mLights.end(); ++iter)
{
getState (lights, iter->first);
}
}
MWWorld::ContainerStoreIterator::ContainerStoreIterator (ContainerStore *container)
: mType (-1), mMask (0), mContainer (container)

@ -8,6 +8,7 @@
namespace ESM
{
struct InventoryList;
struct InventoryState;
}
namespace MWWorld
@ -123,6 +124,10 @@ namespace MWWorld
Ptr search (const std::string& id);
void writeState (ESM::InventoryState& state) const;
void readState (const ESM::InventoryState& state);
friend class ContainerStoreIterator;
};
@ -172,7 +177,7 @@ namespace MWWorld
ContainerStoreIterator (ContainerStore *container, MWWorld::CellRefList<ESM::Repair>::List::iterator);
ContainerStoreIterator (ContainerStore *container, MWWorld::CellRefList<ESM::Weapon>::List::iterator);
void copy (const ContainerStoreIterator& src);
void copy (const ContainerStoreIterator& src);
void incType();
@ -200,7 +205,7 @@ namespace MWWorld
ContainerStoreIterator operator++ (int);
ContainerStoreIterator& operator= (const ContainerStoreIterator& rhs);
ContainerStoreIterator& operator= (const ContainerStoreIterator& rhs);
bool isEqual (const ContainerStoreIterator& iter) const;

@ -35,6 +35,14 @@ namespace MWWorld
/* Need this for the class to be recognized as polymorphic */
virtual ~LiveCellRefBase() { }
virtual void load (const ESM::ObjectState& state) = 0;
///< Load state into a LiveCellRef, that has already been initialised with base and class.
///
/// \attention Must not be called with an invalid \a state.
virtual void save (ESM::ObjectState& state) const = 0;
///< Save LiveCellRef state into \a state.
protected:
void loadImp (const ESM::ObjectState& state);
@ -79,12 +87,12 @@ namespace MWWorld
// The object that this instance is based on.
const X* mBase;
void load (const ESM::ObjectState& state);
virtual void load (const ESM::ObjectState& state);
///< Load state into a LiveCellRef, that has already been initialised with base and class.
///
/// \attention Must not be called with an invalid \a state.
void save (ESM::ObjectState& state) const;
virtual void save (ESM::ObjectState& state) const;
///< Save LiveCellRef state into \a state.
static bool checkState (const ESM::ObjectState& state);

@ -21,6 +21,14 @@ const std::string& MWWorld::Ptr::getTypeName() const
throw std::runtime_error("Can't get type name from an empty object.");
}
MWWorld::LiveCellRefBase *MWWorld::Ptr::getBase() const
{
if (!mRef)
throw std::runtime_error ("Can't access cell ref pointed to by null Ptr");
return mRef;
}
ESM::CellRef& MWWorld::Ptr::getCellRef() const
{
assert(mRef);

@ -52,6 +52,8 @@ namespace MWWorld
throw std::runtime_error(str.str());
}
MWWorld::LiveCellRefBase *getBase() const;
ESM::CellRef& getCellRef() const;
RefData& getRefData() const;

@ -40,7 +40,7 @@ add_component_dir (esm
loadinfo loadingr loadland loadlevlist loadligh loadlock loadprob loadrepa loadltex loadmgef loadmisc loadnpcc
loadnpc loadpgrd loadrace loadregn loadscpt loadskil loadsndg loadsoun loadspel loadsscr loadstat
loadweap records aipackage effectlist spelllist variant variantimp loadtes3 cellref filter
savedgame journalentry queststate locals globalscript player objectstate cellid cellstate globalmap lightstate
savedgame journalentry queststate locals globalscript player objectstate cellid cellstate globalmap lightstate inventorystate containerstate
)
add_component_dir (misc

@ -0,0 +1,16 @@
#include "containerstate.hpp"
void ESM::ContainerState::load (ESMReader &esm)
{
ObjectState::load (esm);
mInventory.load (esm);
}
void ESM::ContainerState::save (ESMWriter &esm, bool inInventory) const
{
ObjectState::save (esm, inInventory);
mInventory.save (esm);
}

@ -0,0 +1,20 @@
#ifndef OPENMW_ESM_CONTAINERSTATE_H
#define OPENMW_ESM_CONTAINERSTATE_H
#include "objectstate.hpp"
#include "inventorystate.hpp"
namespace ESM
{
// format 0, saved games only
struct ContainerState : public ObjectState
{
InventoryState mInventory;
virtual void load (ESMReader &esm);
virtual void save (ESMWriter &esm, bool inInventory = false) const;
};
}
#endif

@ -0,0 +1,60 @@
#include "inventorystate.hpp"
#include "esmreader.hpp"
#include "esmwriter.hpp"
namespace
{
void read (ESM::ESMReader &esm, ESM::ObjectState& state, int& slot)
{
slot = -1;
esm.getHNOT (slot, "SLOT");
state.load (esm);
}
void write (ESM::ESMWriter &esm, const ESM::ObjectState& state, unsigned int type, int slot)
{
esm.writeHNT ("IOBJ", type);
if (slot!=-1)
esm.writeHNT ("SLOT", slot);
state.save (esm, true);
}
}
void ESM::InventoryState::load (ESMReader &esm)
{
while (esm.isNextSub ("IOBJ"))
{
unsigned int id = 0;
esm.getHT (id);
if (id==ESM::REC_LIGH)
{
LightState state;
int slot;
read (esm, state, slot);
mLights.push_back (std::make_pair (state, slot));
}
else
{
ObjectState state;
int slot;
read (esm, state, slot);
mItems.push_back (std::make_pair (state, std::make_pair (id, slot)));
}
}
}
void ESM::InventoryState::save (ESMWriter &esm) const
{
for (std::vector<std::pair<ObjectState, std::pair<unsigned int, int> > >::const_iterator iter (mItems.begin()); iter!=mItems.end(); ++iter)
write (esm, iter->first, iter->second.first, iter->second.second);
for (std::vector<std::pair<LightState, int> >::const_iterator iter (mLights.begin());
iter!=mLights.end(); ++iter)
write (esm, iter->first, ESM::REC_LIGH, iter->second);
}

@ -0,0 +1,28 @@
#ifndef OPENMW_ESM_INVENTORYSTATE_H
#define OPENMW_ESM_INVENTORYSTATE_H
#include "objectstate.hpp"
#include "lightstate.hpp"
namespace ESM
{
class ESMReader;
class ESMWriter;
// format 0, saved games only
/// \brief State for inventories and containers
struct InventoryState
{
// anything but lights (type, slot)
std::vector<std::pair<ObjectState, std::pair<unsigned int, int> > > mItems;
// lights (slot)
std::vector<std::pair<LightState, int> > mLights;
virtual void load (ESMReader &esm);
virtual void save (ESMWriter &esm) const;
};
}
#endif

@ -20,9 +20,9 @@ void ESM::ObjectState::load (ESMReader &esm)
mCount = 1;
esm.getHNOT (mCount, "COUN");
esm.getHNT (mPosition, "POS_", 24);
esm.getHNOT (mPosition, "POS_", 24);
esm.getHNT (mLocalRotation, "LROT", 12);
esm.getHNOT (mLocalRotation, "LROT", 12);
}
void ESM::ObjectState::save (ESMWriter &esm, bool inInventory) const

Loading…
Cancel
Save