mirror of
https://github.com/TES3MP/openmw-tes3mp.git
synced 2025-01-16 18:19:55 +00:00
Don't require the object type id for reading references from savegames
This is redundant, since we can look it up from the RefID.
This commit is contained in:
parent
8e1eeccbe1
commit
9014dc48ee
13 changed files with 123 additions and 39 deletions
|
@ -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);
|
||||
|
||||
switch (id)
|
||||
// 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 (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…
Reference in a new issue