forked from mirror/openmw-tes3mp
store content of containers in saved game files
This commit is contained in:
parent
900532a6ca
commit
dd674566a2
14 changed files with 288 additions and 9 deletions
|
@ -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
|
||||
|
|
16
components/esm/containerstate.cpp
Normal file
16
components/esm/containerstate.cpp
Normal file
|
@ -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);
|
||||
}
|
20
components/esm/containerstate.hpp
Normal file
20
components/esm/containerstate.hpp
Normal file
|
@ -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
|
60
components/esm/inventorystate.cpp
Normal file
60
components/esm/inventorystate.cpp
Normal file
|
@ -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);
|
||||
}
|
28
components/esm/inventorystate.hpp
Normal file
28
components/esm/inventorystate.hpp
Normal file
|
@ -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…
Reference in a new issue