Don't require the object type id for reading references from savegames

This is redundant, since we can look it up from the RefID.
openmw-35
scrawl 10 years ago
parent 8e1eeccbe1
commit 9014dc48ee

@ -816,6 +816,9 @@ namespace MWClass
void Creature::readAdditionalState (const MWWorld::Ptr& ptr, const ESM::ObjectState& state)
const
{
if (!state.mHasCustomState)
return;
const ESM::CreatureState& state2 = dynamic_cast<const ESM::CreatureState&> (state);
ensureCustomData(ptr);
@ -844,7 +847,6 @@ namespace MWClass
customData.mContainerStore->readState (state2.mInventory);
customData.mCreatureStats.readState (state2.mCreatureStats);
}
void Creature::writeAdditionalState (const MWWorld::Ptr& ptr, ESM::ObjectState& state)
@ -852,6 +854,12 @@ namespace MWClass
{
ESM::CreatureState& state2 = dynamic_cast<ESM::CreatureState&> (state);
if (!ptr.getRefData().getCustomData())
{
state.mHasCustomState = false;
return;
}
ensureCustomData (ptr);
CreatureCustomData& customData = dynamic_cast<CreatureCustomData&> (*ptr.getRefData().getCustomData());

@ -1275,6 +1275,9 @@ namespace MWClass
void Npc::readAdditionalState (const MWWorld::Ptr& ptr, const ESM::ObjectState& state)
const
{
if (!state.mHasCustomState)
return;
const ESM::NpcState& state2 = dynamic_cast<const ESM::NpcState&> (state);
ensureCustomData(ptr);
@ -1302,6 +1305,12 @@ namespace MWClass
{
ESM::NpcState& state2 = dynamic_cast<ESM::NpcState&> (state);
if (!ptr.getRefData().getCustomData())
{
state.mHasCustomState = false;
return;
}
ensureCustomData (ptr);
NpcCustomData& customData = dynamic_cast<NpcCustomData&> (*ptr.getRefData().getCustomData());

@ -85,7 +85,9 @@ namespace
RecordType state;
iter->save (state);
// recordId currently unused
writer.writeHNT ("OBJE", collection.mList.front().mBase->sRecordId);
state.save (writer);
}
}
@ -93,12 +95,13 @@ namespace
template<typename RecordType, typename T>
void readReferenceCollection (ESM::ESMReader& reader,
MWWorld::CellRefList<T>& collection, const std::map<int, int>& contentFileMap)
MWWorld::CellRefList<T>& collection, const ESM::CellRef& cref, const std::map<int, int>& contentFileMap)
{
const MWWorld::ESMStore& esmStore = MWBase::Environment::get().getWorld()->getStore();
RecordType state;
state.load (reader);
state.mRef = cref;
state.load(reader);
// If the reference came from a content file, make sure this content file is loaded
if (state.mRef.mRefNum.hasContentFile())
@ -640,109 +643,121 @@ namespace MWWorld
while (reader.isNextSub ("OBJE"))
{
unsigned int id = 0;
reader.getHT (id);
unsigned int unused;
reader.getHT (unused);
// load the RefID first so we know what type of object it is
ESM::CellRef cref;
cref.loadId(reader, true);
int type = MWBase::Environment::get().getWorld()->getStore().find(cref.mRefID);
if (type == 0)
{
std::cerr << "Dropping reference to '" << cref.mRefID << "' (object no longer exists)" << std::endl;
reader.skipHSubUntil("OBJE");
continue;
}
switch (id)
switch (type)
{
case ESM::REC_ACTI:
readReferenceCollection<ESM::ObjectState> (reader, mActivators, contentFileMap);
readReferenceCollection<ESM::ObjectState> (reader, mActivators, cref, contentFileMap);
break;
case ESM::REC_ALCH:
readReferenceCollection<ESM::ObjectState> (reader, mPotions, contentFileMap);
readReferenceCollection<ESM::ObjectState> (reader, mPotions, cref, contentFileMap);
break;
case ESM::REC_APPA:
readReferenceCollection<ESM::ObjectState> (reader, mAppas, contentFileMap);
readReferenceCollection<ESM::ObjectState> (reader, mAppas, cref, contentFileMap);
break;
case ESM::REC_ARMO:
readReferenceCollection<ESM::ObjectState> (reader, mArmors, contentFileMap);
readReferenceCollection<ESM::ObjectState> (reader, mArmors, cref, contentFileMap);
break;
case ESM::REC_BOOK:
readReferenceCollection<ESM::ObjectState> (reader, mBooks, contentFileMap);
readReferenceCollection<ESM::ObjectState> (reader, mBooks, cref, contentFileMap);
break;
case ESM::REC_CLOT:
readReferenceCollection<ESM::ObjectState> (reader, mClothes, contentFileMap);
readReferenceCollection<ESM::ObjectState> (reader, mClothes, cref, contentFileMap);
break;
case ESM::REC_CONT:
readReferenceCollection<ESM::ContainerState> (reader, mContainers, contentFileMap);
readReferenceCollection<ESM::ContainerState> (reader, mContainers, cref, contentFileMap);
break;
case ESM::REC_CREA:
readReferenceCollection<ESM::CreatureState> (reader, mCreatures, contentFileMap);
readReferenceCollection<ESM::CreatureState> (reader, mCreatures, cref, contentFileMap);
break;
case ESM::REC_DOOR:
readReferenceCollection<ESM::DoorState> (reader, mDoors, contentFileMap);
readReferenceCollection<ESM::DoorState> (reader, mDoors, cref, contentFileMap);
break;
case ESM::REC_INGR:
readReferenceCollection<ESM::ObjectState> (reader, mIngreds, contentFileMap);
readReferenceCollection<ESM::ObjectState> (reader, mIngreds, cref, contentFileMap);
break;
case ESM::REC_LEVC:
readReferenceCollection<ESM::CreatureLevListState> (reader, mCreatureLists, contentFileMap);
readReferenceCollection<ESM::CreatureLevListState> (reader, mCreatureLists, cref, contentFileMap);
break;
case ESM::REC_LEVI:
readReferenceCollection<ESM::ObjectState> (reader, mItemLists, contentFileMap);
readReferenceCollection<ESM::ObjectState> (reader, mItemLists, cref, contentFileMap);
break;
case ESM::REC_LIGH:
readReferenceCollection<ESM::ObjectState> (reader, mLights, contentFileMap);
readReferenceCollection<ESM::ObjectState> (reader, mLights, cref, contentFileMap);
break;
case ESM::REC_LOCK:
readReferenceCollection<ESM::ObjectState> (reader, mLockpicks, contentFileMap);
readReferenceCollection<ESM::ObjectState> (reader, mLockpicks, cref, contentFileMap);
break;
case ESM::REC_MISC:
readReferenceCollection<ESM::ObjectState> (reader, mMiscItems, contentFileMap);
readReferenceCollection<ESM::ObjectState> (reader, mMiscItems, cref, contentFileMap);
break;
case ESM::REC_NPC_:
readReferenceCollection<ESM::NpcState> (reader, mNpcs, contentFileMap);
readReferenceCollection<ESM::NpcState> (reader, mNpcs, cref, contentFileMap);
break;
case ESM::REC_PROB:
readReferenceCollection<ESM::ObjectState> (reader, mProbes, contentFileMap);
readReferenceCollection<ESM::ObjectState> (reader, mProbes, cref, contentFileMap);
break;
case ESM::REC_REPA:
readReferenceCollection<ESM::ObjectState> (reader, mRepairs, contentFileMap);
readReferenceCollection<ESM::ObjectState> (reader, mRepairs, cref, contentFileMap);
break;
case ESM::REC_STAT:
readReferenceCollection<ESM::ObjectState> (reader, mStatics, contentFileMap);
readReferenceCollection<ESM::ObjectState> (reader, mStatics, cref, contentFileMap);
break;
case ESM::REC_WEAP:
readReferenceCollection<ESM::ObjectState> (reader, mWeapons, contentFileMap);
readReferenceCollection<ESM::ObjectState> (reader, mWeapons, cref, contentFileMap);
break;
default:

@ -5,6 +5,12 @@
#include "esmwriter.hpp"
void ESM::CellRef::load (ESMReader& esm, bool wideRefNum)
{
loadId(esm, wideRefNum);
loadData(esm);
}
void ESM::CellRef::loadId(ESMReader &esm, bool wideRefNum)
{
// According to Hrnchamd, this does not belong to the actual ref. Instead, it is a marker indicating that
// the following refs are part of a "temp refs" section. A temp ref is not being tracked by the moved references system.
@ -19,8 +25,6 @@ void ESM::CellRef::load (ESMReader& esm, bool wideRefNum)
esm.getHNT (mRefNum.mIndex, "FRMR");
mRefID = esm.getHNString ("NAME");
loadData(esm);
}
void ESM::CellRef::loadData(ESMReader &esm)

@ -89,8 +89,11 @@ namespace ESM
// Position and rotation of this object within the cell
Position mPos;
/// Calls loadId and loadData
void load (ESMReader& esm, bool wideRefNum = false);
void loadId (ESMReader& esm, bool wideRefNum = false);
/// Implicitly called by load
void loadData (ESMReader& esm);

@ -5,18 +5,24 @@ void ESM::CreatureState::load (ESMReader &esm)
{
ObjectState::load (esm);
mInventory.load (esm);
if (mHasCustomState)
{
mInventory.load (esm);
mCreatureStats.load (esm);
mCreatureStats.load (esm);
}
}
void ESM::CreatureState::save (ESMWriter &esm, bool inInventory) const
{
ObjectState::save (esm, inInventory);
mInventory.save (esm);
if (mHasCustomState)
{
mInventory.save (esm);
mCreatureStats.save (esm);
mCreatureStats.save (esm);
}
}
void ESM::CreatureState::blank()

@ -210,6 +210,17 @@ void ESMReader::skipHSubSize(int size)
fail("skipHSubSize() mismatch");
}
void ESMReader::skipHSubUntil(const char *name)
{
while (hasMoreSubs() && !isNextSub(name))
{
mCtx.subCached = false;
skipHSub();
}
if (hasMoreSubs())
mCtx.subCached = true;
}
void ESMReader::getSubHeader()
{
if (mCtx.leftRec < 4)

@ -195,6 +195,9 @@ public:
// Skip sub record and check its size
void skipHSubSize(int size);
// Skip all subrecords until the given subrecord or no more subrecords remaining
void skipHSubUntil(const char* name);
/* Sub-record header. This updates leftRec beyond the current
sub-record as well. leftSub contains size of current sub-record.
*/

@ -11,6 +11,7 @@ namespace
slot = -1;
esm.getHNOT (slot, "SLOT");
state.mRef.loadId(esm, true);
state.load (esm);
}

@ -5,22 +5,28 @@ void ESM::NpcState::load (ESMReader &esm)
{
ObjectState::load (esm);
mInventory.load (esm);
if (mHasCustomState)
{
mInventory.load (esm);
mNpcStats.load (esm);
mNpcStats.load (esm);
mCreatureStats.load (esm);
mCreatureStats.load (esm);
}
}
void ESM::NpcState::save (ESMWriter &esm, bool inInventory) const
{
ObjectState::save (esm, inInventory);
mInventory.save (esm);
if (mHasCustomState)
{
mInventory.save (esm);
mNpcStats.save (esm);
mNpcStats.save (esm);
mCreatureStats.save (esm);
mCreatureStats.save (esm);
}
}
void ESM::NpcState::blank()
@ -28,4 +34,5 @@ void ESM::NpcState::blank()
ObjectState::blank();
mNpcStats.blank();
mCreatureStats.blank();
mHasCustomState = true;
}

@ -6,7 +6,7 @@
void ESM::ObjectState::load (ESMReader &esm)
{
mRef.load (esm, true);
mRef.loadData(esm);
mHasLocals = 0;
esm.getHNOT (mHasLocals, "HLOC");
@ -27,6 +27,10 @@ void ESM::ObjectState::load (ESMReader &esm)
// used for lights only
mTime = 0;
esm.getHNOT (mTime, "LTIM");
// FIXME: assuming "false" as default would make more sense, but also break compatibility with older save files
mHasCustomState = true;
esm.getHNOT (mHasCustomState, "HCUS");
}
void ESM::ObjectState::save (ESMWriter &esm, bool inInventory) const
@ -53,6 +57,9 @@ void ESM::ObjectState::save (ESMWriter &esm, bool inInventory) const
if (mTime)
esm.writeHNT ("LTIM", mTime);
if (!mHasCustomState)
esm.writeHNT ("HCUS", false);
}
void ESM::ObjectState::blank()
@ -68,6 +75,7 @@ void ESM::ObjectState::blank()
mLocalRotation[i] = 0;
}
mTime = 0;
mHasCustomState = true;
}
ESM::ObjectState::~ObjectState() {}

@ -28,7 +28,15 @@ namespace ESM
float mTime; // Used for lights only. Overhead should not be so awful, besides CellRef isn't OO either
// Is there any class-specific state following the ObjectState
bool mHasCustomState;
ObjectState() : mHasCustomState(true)
{}
/// @note Does not load the CellRef ID, it should already be loaded before calling this method
virtual void load (ESMReader &esm);
virtual void save (ESMWriter &esm, bool inInventory = false) const;
/// Initialize to default state

@ -6,6 +6,7 @@
void ESM::Player::load (ESMReader &esm)
{
mObject.mRef.loadId(esm, true);
mObject.load (esm);
mCellId.load (esm);

Loading…
Cancel
Save