Make deleted flag a parameter of load/save methods (instead of a record member) in ESM records

openmw-38
Stanislav Bas 10 years ago
parent 1e8182220a
commit 4a16eba716

@ -4,18 +4,6 @@
#include "esmreader.hpp" #include "esmreader.hpp"
#include "esmwriter.hpp" #include "esmwriter.hpp"
ESM::CellRef::CellRef()
: mScale(1.0f),
mFactionRank(-2),
mChargeInt(-1),
mEnchantmentCharge(-1.0f),
mGoldValue(1),
mTeleport(false),
mLockLevel(0),
mReferenceBlocked(-1),
mIsDeleted(false)
{}
void ESM::RefNum::load (ESMReader& esm, bool wide) void ESM::RefNum::load (ESMReader& esm, bool wide)
{ {
if (wide) if (wide)
@ -37,10 +25,37 @@ void ESM::RefNum::save (ESMWriter &esm, bool wide, const std::string& tag) const
} }
void ESM::CellRef::load (ESMReader& esm, bool wideRefNum) void ESM::CellRef::clearData()
{
mScale = 1;
mOwner.clear();
mGlobalVariable.clear();
mSoul.clear();
mFaction.clear();
mFactionRank = -2;
mChargeInt = -1;
mEnchantmentCharge = -1;
mGoldValue = 0;
mDestCell.clear();
mLockLevel = 0;
mKey.clear();
mTrap.clear();
mReferenceBlocked = -1;
mTeleport = false;
for (int i=0; i<3; ++i)
{
mDoorDest.pos[i] = 0;
mDoorDest.rot[i] = 0;
mPos.pos[i] = 0;
mPos.rot[i] = 0;
}
}
void ESM::CellRef::load (ESMReader& esm, bool &isDeleted, bool wideRefNum)
{ {
loadId(esm, wideRefNum); loadId(esm, wideRefNum);
loadData(esm); loadData(esm, isDeleted);
} }
void ESM::CellRef::loadId (ESMReader& esm, bool wideRefNum) void ESM::CellRef::loadId (ESMReader& esm, bool wideRefNum)
@ -55,27 +70,19 @@ void ESM::CellRef::loadId (ESMReader& esm, bool wideRefNum)
mRefNum.load (esm, wideRefNum); mRefNum.load (esm, wideRefNum);
mRefID = esm.getHNString ("NAME"); mRefID = esm.getHNString ("NAME");
mIsDeleted = false;
} }
void ESM::CellRef::loadData(ESMReader &esm) void ESM::CellRef::loadData(ESMReader &esm, bool &isDeleted)
{ {
mScale = 1.0f; isDeleted = false;
mFactionRank = -2;
mChargeInt = -1; clearData();
mEnchantmentCharge = -1;
mGoldValue = 1;
mLockLevel = 0;
mReferenceBlocked = -1;
mTeleport = false;
mIsDeleted = false;
bool isLoaded = false; bool isLoaded = false;
while (!isLoaded && esm.hasMoreSubs()) while (!isLoaded && esm.hasMoreSubs())
{ {
esm.getSubName(); esm.getSubName();
uint32_t name = esm.retSubName().val; switch (esm.retSubName().val)
switch (name)
{ {
case ESM::FourCC<'U','N','A','M'>::value: case ESM::FourCC<'U','N','A','M'>::value:
esm.getHT(mReferenceBlocked); esm.getHT(mReferenceBlocked);
@ -131,7 +138,7 @@ void ESM::CellRef::loadData(ESMReader &esm)
break; break;
case ESM::FourCC<'D','E','L','E'>::value: case ESM::FourCC<'D','E','L','E'>::value:
esm.skipHSub(); esm.skipHSub();
mIsDeleted = true; isDeleted = true;
break; break;
default: default:
esm.cacheSubName(); esm.cacheSubName();
@ -141,7 +148,7 @@ void ESM::CellRef::loadData(ESMReader &esm)
} }
} }
void ESM::CellRef::save (ESMWriter &esm, bool wideRefNum, bool inInventory) const void ESM::CellRef::save (ESMWriter &esm, bool wideRefNum, bool inInventory, bool isDeleted) const
{ {
mRefNum.save (esm, wideRefNum); mRefNum.save (esm, wideRefNum);
@ -192,7 +199,7 @@ void ESM::CellRef::save (ESMWriter &esm, bool wideRefNum, bool inInventory) cons
if (!inInventory) if (!inInventory)
esm.writeHNT("DATA", mPos, 24); esm.writeHNT("DATA", mPos, 24);
if (mIsDeleted) if (isDeleted)
{ {
esm.writeHNCString("DELE", ""); esm.writeHNCString("DELE", "");
} }
@ -202,31 +209,7 @@ void ESM::CellRef::blank()
{ {
mRefNum.unset(); mRefNum.unset();
mRefID.clear(); mRefID.clear();
mScale = 1; clearData();
mOwner.clear();
mGlobalVariable.clear();
mSoul.clear();
mFaction.clear();
mFactionRank = -2;
mChargeInt = -1;
mEnchantmentCharge = -1;
mGoldValue = 0;
mDestCell.clear();
mLockLevel = 0;
mKey.clear();
mTrap.clear();
mReferenceBlocked = -1;
mTeleport = false;
for (int i=0; i<3; ++i)
{
mDoorDest.pos[i] = 0;
mDoorDest.rot[i] = 0;
mPos.pos[i] = 0;
mPos.rot[i] = 0;
}
mIsDeleted = false;
} }
bool ESM::operator== (const RefNum& left, const RefNum& right) bool ESM::operator== (const RefNum& left, const RefNum& right)

@ -33,6 +33,8 @@ namespace ESM
class CellRef class CellRef
{ {
void clearData();
public: public:
// Reference number // Reference number
@ -99,19 +101,15 @@ namespace ESM
// Position and rotation of this object within the cell // Position and rotation of this object within the cell
Position mPos; Position mPos;
bool mIsDeleted;
CellRef();
/// Calls loadId and loadData /// Calls loadId and loadData
void load (ESMReader& esm, bool wideRefNum = false); void load (ESMReader& esm, bool &isDeleted, bool wideRefNum = false);
void loadId (ESMReader& esm, bool wideRefNum = false); void loadId (ESMReader& esm, bool wideRefNum = false);
/// Implicitly called by load /// Implicitly called by load
void loadData (ESMReader& esm); void loadData (ESMReader& esm, bool &isDeleted);
void save (ESMWriter &esm, bool wideRefNum = false, bool inInventory = false) const; void save (ESMWriter &esm, bool wideRefNum = false, bool inInventory = false, bool isDeleted = false) const;
void blank(); void blank();
}; };

@ -7,27 +7,18 @@
unsigned int ESM::DebugProfile::sRecordId = REC_DBGP; unsigned int ESM::DebugProfile::sRecordId = REC_DBGP;
ESM::DebugProfile::DebugProfile() void ESM::DebugProfile::load (ESMReader& esm, bool &isDeleted)
: mIsDeleted(false)
{}
void ESM::DebugProfile::load (ESMReader& esm)
{ {
mIsDeleted = false; isDeleted = false;
while (esm.hasMoreSubs()) while (esm.hasMoreSubs())
{ {
esm.getSubName(); esm.getSubName();
uint32_t name = esm.retSubName().val; switch (esm.retSubName().val)
switch (name)
{ {
case ESM::FourCC<'N','A','M','E'>::value: case ESM::FourCC<'N','A','M','E'>::value:
mId = esm.getHString(); mId = esm.getHString();
break; break;
case ESM::FourCC<'D','E','L','E'>::value:
esm.skipHSub();
mIsDeleted = true;
break;
case ESM::FourCC<'D','E','S','C'>::value: case ESM::FourCC<'D','E','S','C'>::value:
mDescription = esm.getHString(); mDescription = esm.getHString();
break; break;
@ -37,6 +28,10 @@ void ESM::DebugProfile::load (ESMReader& esm)
case ESM::FourCC<'F','L','A','G'>::value: case ESM::FourCC<'F','L','A','G'>::value:
esm.getHT(mFlags); esm.getHT(mFlags);
break; break;
case ESM::FourCC<'D','E','L','E'>::value:
esm.skipHSub();
isDeleted = true;
break;
default: default:
esm.fail("Unknown subrecord"); esm.fail("Unknown subrecord");
break; break;
@ -44,11 +39,11 @@ void ESM::DebugProfile::load (ESMReader& esm)
} }
} }
void ESM::DebugProfile::save (ESMWriter& esm) const void ESM::DebugProfile::save (ESMWriter& esm, bool isDeleted) const
{ {
esm.writeHNCString ("NAME", mId); esm.writeHNCString ("NAME", mId);
if (mIsDeleted) if (isDeleted)
{ {
esm.writeHNCString("DELE", ""); esm.writeHNCString("DELE", "");
return; return;
@ -64,5 +59,4 @@ void ESM::DebugProfile::blank()
mDescription.clear(); mDescription.clear();
mScriptText.clear(); mScriptText.clear();
mFlags = 0; mFlags = 0;
mIsDeleted = false;
} }

@ -27,12 +27,8 @@ namespace ESM
unsigned int mFlags; unsigned int mFlags;
bool mIsDeleted; void load (ESMReader& esm, bool &isDeleted);
void save (ESMWriter& esm, bool isDeleted = false) const;
DebugProfile();
void load (ESMReader& esm);
void save (ESMWriter& esm) const;
/// Set record to default state (does not touch the ID). /// Set record to default state (does not touch the ID).
void blank(); void blank();

@ -281,6 +281,7 @@ void ESMReader::skipRecord()
{ {
skip(mCtx.leftRec); skip(mCtx.leftRec);
mCtx.leftRec = 0; mCtx.leftRec = 0;
mCtx.subCached = false;
} }
void ESMReader::getRecHeader(uint32_t &flags) void ESMReader::getRecHeader(uint32_t &flags)

@ -7,13 +7,9 @@
unsigned int ESM::Filter::sRecordId = REC_FILT; unsigned int ESM::Filter::sRecordId = REC_FILT;
ESM::Filter::Filter() void ESM::Filter::load (ESMReader& esm, bool &isDeleted)
: mIsDeleted(false)
{}
void ESM::Filter::load (ESMReader& esm)
{ {
mIsDeleted = false; isDeleted = false;
while (esm.hasMoreSubs()) while (esm.hasMoreSubs())
{ {
@ -24,16 +20,16 @@ void ESM::Filter::load (ESMReader& esm)
case ESM::FourCC<'N','A','M','E'>::value: case ESM::FourCC<'N','A','M','E'>::value:
mId = esm.getHString(); mId = esm.getHString();
break; break;
case ESM::FourCC<'D','E','L','E'>::value:
esm.skipHSub();
mIsDeleted = true;
break;
case ESM::FourCC<'F','I','L','T'>::value: case ESM::FourCC<'F','I','L','T'>::value:
mFilter = esm.getHString(); mFilter = esm.getHString();
break; break;
case ESM::FourCC<'D','E','S','C'>::value: case ESM::FourCC<'D','E','S','C'>::value:
mDescription = esm.getHString(); mDescription = esm.getHString();
break; break;
case ESM::FourCC<'D','E','L','E'>::value:
esm.skipHSub();
isDeleted = true;
break;
default: default:
esm.fail("Unknown subrecord"); esm.fail("Unknown subrecord");
break; break;
@ -41,11 +37,11 @@ void ESM::Filter::load (ESMReader& esm)
} }
} }
void ESM::Filter::save (ESMWriter& esm) const void ESM::Filter::save (ESMWriter& esm, bool isDeleted) const
{ {
esm.writeHNCString ("NAME", mId); esm.writeHNCString ("NAME", mId);
if (mIsDeleted) if (isDeleted)
{ {
esm.writeHNCString("DELE", ""); esm.writeHNCString("DELE", "");
return; return;
@ -59,5 +55,4 @@ void ESM::Filter::blank()
{ {
mFilter.clear(); mFilter.clear();
mDescription.clear(); mDescription.clear();
mIsDeleted = false;
} }

@ -18,12 +18,8 @@ namespace ESM
std::string mFilter; std::string mFilter;
bool mIsDeleted; void load (ESMReader& esm, bool &isDeleted);
void save (ESMWriter& esm, bool isDeleted = false) const;
Filter();
void load (ESMReader& esm);
void save (ESMWriter& esm) const;
void blank(); void blank();
///< Set record to default state (does not touch the ID). ///< Set record to default state (does not touch the ID).

@ -8,29 +8,20 @@ namespace ESM
{ {
unsigned int Activator::sRecordId = REC_ACTI; unsigned int Activator::sRecordId = REC_ACTI;
Activator::Activator() void Activator::load(ESMReader &esm, bool &isDeleted)
: mIsDeleted(false)
{}
void Activator::load(ESMReader &esm)
{ {
mIsDeleted = false; isDeleted = false;
bool hasName = false; bool hasName = false;
while (esm.hasMoreSubs()) while (esm.hasMoreSubs())
{ {
esm.getSubName(); esm.getSubName();
uint32_t name = esm.retSubName().val; switch (esm.retSubName().val)
switch (name)
{ {
case ESM::FourCC<'N','A','M','E'>::value: case ESM::FourCC<'N','A','M','E'>::value:
mId = esm.getHString(); mId = esm.getHString();
hasName = true; hasName = true;
break; break;
case ESM::FourCC<'D','E','L','E'>::value:
esm.skipHSub();
mIsDeleted = true;
break;
case ESM::FourCC<'M','O','D','L'>::value: case ESM::FourCC<'M','O','D','L'>::value:
mModel = esm.getHString(); mModel = esm.getHString();
break; break;
@ -40,6 +31,10 @@ namespace ESM
case ESM::FourCC<'S','C','R','I'>::value: case ESM::FourCC<'S','C','R','I'>::value:
mScript = esm.getHString(); mScript = esm.getHString();
break; break;
case ESM::FourCC<'D','E','L','E'>::value:
esm.skipHSub();
isDeleted = true;
break;
default: default:
esm.fail("Unknown subrecord"); esm.fail("Unknown subrecord");
break; break;
@ -49,11 +44,11 @@ namespace ESM
if (!hasName) if (!hasName)
esm.fail("Missing NAME subrecord"); esm.fail("Missing NAME subrecord");
} }
void Activator::save(ESMWriter &esm) const void Activator::save(ESMWriter &esm, bool isDeleted) const
{ {
esm.writeHNCString("NAME", mId); esm.writeHNCString("NAME", mId);
if (mIsDeleted) if (isDeleted)
{ {
esm.writeHNCString("DELE", ""); esm.writeHNCString("DELE", "");
return; return;
@ -69,6 +64,5 @@ namespace ESM
mName.clear(); mName.clear();
mScript.clear(); mScript.clear();
mModel.clear(); mModel.clear();
mIsDeleted = false;
} }
} }

@ -17,12 +17,8 @@ struct Activator
std::string mId, mName, mScript, mModel; std::string mId, mName, mScript, mModel;
bool mIsDeleted; void load(ESMReader &esm, bool &isDeleted);
void save(ESMWriter &esm, bool isDeleted = false) const;
Activator();
void load(ESMReader &esm);
void save(ESMWriter &esm) const;
void blank(); void blank();
///< Set record to default state (does not touch the ID). ///< Set record to default state (does not touch the ID).

@ -8,31 +8,23 @@ namespace ESM
{ {
unsigned int Potion::sRecordId = REC_ALCH; unsigned int Potion::sRecordId = REC_ALCH;
Potion::Potion() void Potion::load(ESMReader &esm, bool &isDeleted)
: mIsDeleted(false)
{}
void Potion::load(ESMReader &esm)
{ {
isDeleted = false;
mEffects.mList.clear(); mEffects.mList.clear();
mIsDeleted = false;
bool hasName = false; bool hasName = false;
bool hasData = false; bool hasData = false;
while (esm.hasMoreSubs()) while (esm.hasMoreSubs())
{ {
esm.getSubName(); esm.getSubName();
uint32_t name = esm.retSubName().val; switch (esm.retSubName().val)
switch (name)
{ {
case ESM::FourCC<'N','A','M','E'>::value: case ESM::FourCC<'N','A','M','E'>::value:
mId = esm.getHString(); mId = esm.getHString();
hasName = true; hasName = true;
break; break;
case ESM::FourCC<'D','E','L','E'>::value:
esm.skipHSub();
mIsDeleted = true;
break;
case ESM::FourCC<'M','O','D','L'>::value: case ESM::FourCC<'M','O','D','L'>::value:
mModel = esm.getHString(); mModel = esm.getHString();
break; break;
@ -52,6 +44,10 @@ namespace ESM
case ESM::FourCC<'E','N','A','M'>::value: case ESM::FourCC<'E','N','A','M'>::value:
mEffects.add(esm); mEffects.add(esm);
break; break;
case ESM::FourCC<'D','E','L','E'>::value:
esm.skipHSub();
isDeleted = true;
break;
default: default:
esm.fail("Unknown subrecord"); esm.fail("Unknown subrecord");
break; break;
@ -60,14 +56,14 @@ namespace ESM
if (!hasName) if (!hasName)
esm.fail("Missing NAME subrecord"); esm.fail("Missing NAME subrecord");
if (!hasData && !mIsDeleted) if (!hasData && !isDeleted)
esm.fail("Missing ALDT subrecord"); esm.fail("Missing ALDT subrecord");
} }
void Potion::save(ESMWriter &esm) const void Potion::save(ESMWriter &esm, bool isDeleted) const
{ {
esm.writeHNCString("NAME", mId); esm.writeHNCString("NAME", mId);
if (mIsDeleted) if (isDeleted)
{ {
esm.writeHNCString("DELE", ""); esm.writeHNCString("DELE", "");
return; return;
@ -91,6 +87,5 @@ namespace ESM
mIcon.clear(); mIcon.clear();
mScript.clear(); mScript.clear();
mEffects.mList.clear(); mEffects.mList.clear();
mIsDeleted = false;
} }
} }

@ -33,12 +33,8 @@ struct Potion
std::string mId, mName, mModel, mIcon, mScript; std::string mId, mName, mModel, mIcon, mScript;
EffectList mEffects; EffectList mEffects;
bool mIsDeleted; void load(ESMReader &esm, bool &isDeleted);
void save(ESMWriter &esm, bool isDeleted = false) const;
Potion();
void load(ESMReader &esm);
void save(ESMWriter &esm) const;
void blank(); void blank();
///< Set record to default state (does not touch the ID). ///< Set record to default state (does not touch the ID).

@ -8,30 +8,21 @@ namespace ESM
{ {
unsigned int Apparatus::sRecordId = REC_APPA; unsigned int Apparatus::sRecordId = REC_APPA;
Apparatus::Apparatus() void Apparatus::load(ESMReader &esm, bool &isDeleted)
: mIsDeleted(false)
{}
void Apparatus::load(ESMReader &esm)
{ {
mIsDeleted = false; isDeleted = false;
bool hasName = false; bool hasName = false;
bool hasData = false; bool hasData = false;
while (esm.hasMoreSubs()) while (esm.hasMoreSubs())
{ {
esm.getSubName(); esm.getSubName();
uint32_t name = esm.retSubName().val; switch (esm.retSubName().val)
switch (name)
{ {
case ESM::FourCC<'N','A','M','E'>::value: case ESM::FourCC<'N','A','M','E'>::value:
mId = esm.getHString(); mId = esm.getHString();
hasName = true; hasName = true;
break; break;
case ESM::FourCC<'D','E','L','E'>::value:
esm.skipHSub();
mIsDeleted = true;
break;
case ESM::FourCC<'M','O','D','L'>::value: case ESM::FourCC<'M','O','D','L'>::value:
mModel = esm.getHString(); mModel = esm.getHString();
break; break;
@ -48,6 +39,10 @@ namespace ESM
case ESM::FourCC<'I','T','E','X'>::value: case ESM::FourCC<'I','T','E','X'>::value:
mIcon = esm.getHString(); mIcon = esm.getHString();
break; break;
case ESM::FourCC<'D','E','L','E'>::value:
esm.skipHSub();
isDeleted = true;
break;
default: default:
esm.fail("Unknown subrecord"); esm.fail("Unknown subrecord");
break; break;
@ -56,15 +51,15 @@ namespace ESM
if (!hasName) if (!hasName)
esm.fail("Missing NAME subrecord"); esm.fail("Missing NAME subrecord");
if (!hasData && !mIsDeleted) if (!hasData && !isDeleted)
esm.fail("Missing AADT subrecord"); esm.fail("Missing AADT subrecord");
} }
void Apparatus::save(ESMWriter &esm) const void Apparatus::save(ESMWriter &esm, bool isDeleted) const
{ {
esm.writeHNCString("NAME", mId); esm.writeHNCString("NAME", mId);
if (mIsDeleted) if (isDeleted)
{ {
esm.writeHNCString("DELE", ""); esm.writeHNCString("DELE", "");
return; return;
@ -87,6 +82,5 @@ namespace ESM
mIcon.clear(); mIcon.clear();
mScript.clear(); mScript.clear();
mName.clear(); mName.clear();
mIsDeleted = false;
} }
} }

@ -38,12 +38,8 @@ struct Apparatus
AADTstruct mData; AADTstruct mData;
std::string mId, mModel, mIcon, mScript, mName; std::string mId, mModel, mIcon, mScript, mName;
bool mIsDeleted; void load(ESMReader &esm, bool &isDeleted);
void save(ESMWriter &esm, bool isDeleted = false) const;
Apparatus();
void load(ESMReader &esm);
void save(ESMWriter &esm) const;
void blank(); void blank();
///< Set record to default state (does not touch the ID). ///< Set record to default state (does not touch the ID).

@ -38,31 +38,23 @@ namespace ESM
unsigned int Armor::sRecordId = REC_ARMO; unsigned int Armor::sRecordId = REC_ARMO;
Armor::Armor() void Armor::load(ESMReader &esm, bool &isDeleted)
: mIsDeleted(false)
{}
void Armor::load(ESMReader &esm)
{ {
isDeleted = false;
mParts.mParts.clear(); mParts.mParts.clear();
mIsDeleted = false;
bool hasName = false; bool hasName = false;
bool hasData = false; bool hasData = false;
while (esm.hasMoreSubs()) while (esm.hasMoreSubs())
{ {
esm.getSubName(); esm.getSubName();
uint32_t name = esm.retSubName().val; switch (esm.retSubName().val)
switch (name)
{ {
case ESM::FourCC<'N','A','M','E'>::value: case ESM::FourCC<'N','A','M','E'>::value:
mId = esm.getHString(); mId = esm.getHString();
hasName = true; hasName = true;
break; break;
case ESM::FourCC<'D','E','L','E'>::value:
esm.skipHSub();
mIsDeleted = true;
break;
case ESM::FourCC<'M','O','D','L'>::value: case ESM::FourCC<'M','O','D','L'>::value:
mModel = esm.getHString(); mModel = esm.getHString();
break; break;
@ -85,6 +77,10 @@ namespace ESM
case ESM::FourCC<'I','N','D','X'>::value: case ESM::FourCC<'I','N','D','X'>::value:
mParts.add(esm); mParts.add(esm);
break; break;
case ESM::FourCC<'D','E','L','E'>::value:
esm.skipHSub();
isDeleted = true;
break;
default: default:
esm.fail("Unknown subrecord"); esm.fail("Unknown subrecord");
break; break;
@ -93,15 +89,15 @@ namespace ESM
if (!hasName) if (!hasName)
esm.fail("Missing NAME subrecord"); esm.fail("Missing NAME subrecord");
if (!hasData && !mIsDeleted) if (!hasData && !isDeleted)
esm.fail("Missing CTDT subrecord"); esm.fail("Missing CTDT subrecord");
} }
void Armor::save(ESMWriter &esm) const void Armor::save(ESMWriter &esm, bool isDeleted) const
{ {
esm.writeHNCString("NAME", mId); esm.writeHNCString("NAME", mId);
if (mIsDeleted) if (isDeleted)
{ {
esm.writeHNCString("DELE", ""); esm.writeHNCString("DELE", "");
return; return;
@ -130,6 +126,5 @@ namespace ESM
mIcon.clear(); mIcon.clear();
mScript.clear(); mScript.clear();
mEnchant.clear(); mEnchant.clear();
mIsDeleted = false;
} }
} }

@ -96,12 +96,8 @@ struct Armor
std::string mId, mName, mModel, mIcon, mScript, mEnchant; std::string mId, mName, mModel, mIcon, mScript, mEnchant;
bool mIsDeleted; void load(ESMReader &esm, bool &isDeleted);
void save(ESMWriter &esm, bool isDeleted = false) const;
Armor();
void load(ESMReader &esm);
void save(ESMWriter &esm) const;
void blank(); void blank();
///< Set record to default state (does not touch the ID). ///< Set record to default state (does not touch the ID).

@ -8,30 +8,21 @@ namespace ESM
{ {
unsigned int BodyPart::sRecordId = REC_BODY; unsigned int BodyPart::sRecordId = REC_BODY;
BodyPart::BodyPart() void BodyPart::load(ESMReader &esm, bool &isDeleted)
: mIsDeleted(false)
{}
void BodyPart::load(ESMReader &esm)
{ {
mIsDeleted = false; isDeleted = false;
bool hasName = false; bool hasName = false;
bool hasData = false; bool hasData = false;
while (esm.hasMoreSubs()) while (esm.hasMoreSubs())
{ {
esm.getSubName(); esm.getSubName();
uint32_t name = esm.retSubName().val; switch (esm.retSubName().val)
switch (name)
{ {
case ESM::FourCC<'N','A','M','E'>::value: case ESM::FourCC<'N','A','M','E'>::value:
mId = esm.getHString(); mId = esm.getHString();
hasName = true; hasName = true;
break; break;
case ESM::FourCC<'D','E','L','E'>::value:
esm.skipHSub();
mIsDeleted = true;
break;
case ESM::FourCC<'M','O','D','L'>::value: case ESM::FourCC<'M','O','D','L'>::value:
mModel = esm.getHString(); mModel = esm.getHString();
break; break;
@ -42,6 +33,10 @@ namespace ESM
esm.getHT(mData, 4); esm.getHT(mData, 4);
hasData = true; hasData = true;
break; break;
case ESM::FourCC<'D','E','L','E'>::value:
esm.skipHSub();
isDeleted = true;
break;
default: default:
esm.fail("Unknown subrecord"); esm.fail("Unknown subrecord");
break; break;
@ -50,15 +45,15 @@ namespace ESM
if (!hasName) if (!hasName)
esm.fail("Missing NAME subrecord"); esm.fail("Missing NAME subrecord");
if (!hasData && !mIsDeleted) if (!hasData && !isDeleted)
esm.fail("Missing BYDT subrecord"); esm.fail("Missing BYDT subrecord");
} }
void BodyPart::save(ESMWriter &esm) const void BodyPart::save(ESMWriter &esm, bool isDeleted) const
{ {
esm.writeHNCString("NAME", mId); esm.writeHNCString("NAME", mId);
if (mIsDeleted) if (isDeleted)
{ {
esm.writeHNCString("DELE", ""); esm.writeHNCString("DELE", "");
return; return;
@ -78,7 +73,5 @@ namespace ESM
mModel.clear(); mModel.clear();
mRace.clear(); mRace.clear();
mIsDeleted = false;
} }
} }

@ -60,12 +60,8 @@ struct BodyPart
BYDTstruct mData; BYDTstruct mData;
std::string mId, mModel, mRace; std::string mId, mModel, mRace;
bool mIsDeleted; void load(ESMReader &esm, bool &isDeleted);
void save(ESMWriter &esm, bool isDeleted = false) const;
BodyPart();
void load(ESMReader &esm);
void save(ESMWriter &esm) const;
void blank(); void blank();
///< Set record to default state (does not touch the ID). ///< Set record to default state (does not touch the ID).

@ -8,30 +8,21 @@ namespace ESM
{ {
unsigned int Book::sRecordId = REC_BOOK; unsigned int Book::sRecordId = REC_BOOK;
Book::Book() void Book::load(ESMReader &esm, bool &isDeleted)
: mIsDeleted(false)
{}
void Book::load(ESMReader &esm)
{ {
mIsDeleted = false; isDeleted = false;
bool hasName = false; bool hasName = false;
bool hasData = false; bool hasData = false;
while (esm.hasMoreSubs()) while (esm.hasMoreSubs())
{ {
esm.getSubName(); esm.getSubName();
uint32_t name = esm.retSubName().val; switch (esm.retSubName().val)
switch (name)
{ {
case ESM::FourCC<'N','A','M','E'>::value: case ESM::FourCC<'N','A','M','E'>::value:
mId = esm.getHString(); mId = esm.getHString();
hasName = true; hasName = true;
break; break;
case ESM::FourCC<'D','E','L','E'>::value:
esm.skipHSub();
mIsDeleted = true;
break;
case ESM::FourCC<'M','O','D','L'>::value: case ESM::FourCC<'M','O','D','L'>::value:
mModel = esm.getHString(); mModel = esm.getHString();
break; break;
@ -54,6 +45,10 @@ namespace ESM
case ESM::FourCC<'T','E','X','T'>::value: case ESM::FourCC<'T','E','X','T'>::value:
mText = esm.getHString(); mText = esm.getHString();
break; break;
case ESM::FourCC<'D','E','L','E'>::value:
esm.skipHSub();
isDeleted = true;
break;
default: default:
esm.fail("Unknown subrecord"); esm.fail("Unknown subrecord");
break; break;
@ -62,14 +57,14 @@ namespace ESM
if (!hasName) if (!hasName)
esm.fail("Missing NAME subrecord"); esm.fail("Missing NAME subrecord");
if (!hasData && !mIsDeleted) if (!hasData && !isDeleted)
esm.fail("Missing BKDT subrecord"); esm.fail("Missing BKDT subrecord");
} }
void Book::save(ESMWriter &esm) const void Book::save(ESMWriter &esm, bool isDeleted) const
{ {
esm.writeHNCString("NAME", mId); esm.writeHNCString("NAME", mId);
if (mIsDeleted) if (isDeleted)
{ {
esm.writeHNCString("DELE", ""); esm.writeHNCString("DELE", "");
return; return;
@ -97,6 +92,5 @@ namespace ESM
mScript.clear(); mScript.clear();
mEnchant.clear(); mEnchant.clear();
mText.clear(); mText.clear();
mIsDeleted = false;
} }
} }

@ -28,12 +28,8 @@ struct Book
std::string mName, mModel, mIcon, mScript, mEnchant, mText; std::string mName, mModel, mIcon, mScript, mEnchant, mText;
std::string mId; std::string mId;
bool mIsDeleted; void load(ESMReader &esm, bool &isDeleted);
void save(ESMWriter &esm, bool isDeleted = false) const;
Book();
void load(ESMReader &esm);
void save(ESMWriter &esm) const;
void blank(); void blank();
///< Set record to default state (does not touch the ID). ///< Set record to default state (does not touch the ID).

@ -8,30 +8,22 @@ namespace ESM
{ {
unsigned int BirthSign::sRecordId = REC_BSGN; unsigned int BirthSign::sRecordId = REC_BSGN;
BirthSign::BirthSign() void BirthSign::load(ESMReader &esm, bool &isDeleted)
: mIsDeleted(false)
{}
void BirthSign::load(ESMReader &esm)
{ {
isDeleted = false;
mPowers.mList.clear(); mPowers.mList.clear();
mIsDeleted = false;
bool hasName = false; bool hasName = false;
while (esm.hasMoreSubs()) while (esm.hasMoreSubs())
{ {
esm.getSubName(); esm.getSubName();
uint32_t name = esm.retSubName().val; switch (esm.retSubName().val)
switch (name)
{ {
case ESM::FourCC<'N','A','M','E'>::value: case ESM::FourCC<'N','A','M','E'>::value:
mId = esm.getHString(); mId = esm.getHString();
hasName = true; hasName = true;
break; break;
case ESM::FourCC<'D','E','L','E'>::value:
esm.skipHSub();
mIsDeleted = true;
break;
case ESM::FourCC<'F','N','A','M'>::value: case ESM::FourCC<'F','N','A','M'>::value:
mName = esm.getHString(); mName = esm.getHString();
break; break;
@ -44,6 +36,10 @@ namespace ESM
case ESM::FourCC<'N','P','C','S'>::value: case ESM::FourCC<'N','P','C','S'>::value:
mPowers.add(esm); mPowers.add(esm);
break; break;
case ESM::FourCC<'D','E','L','E'>::value:
esm.skipHSub();
isDeleted = true;
break;
default: default:
esm.fail("Unknown subrecord"); esm.fail("Unknown subrecord");
break; break;
@ -54,9 +50,9 @@ namespace ESM
esm.fail("Missing NAME subrecord"); esm.fail("Missing NAME subrecord");
} }
void BirthSign::save(ESMWriter &esm) const void BirthSign::save(ESMWriter &esm, bool isDeleted) const
{ {
if (mIsDeleted) if (isDeleted)
{ {
esm.writeHNCString("DELE", ""); esm.writeHNCString("DELE", "");
} }
@ -75,7 +71,6 @@ namespace ESM
mDescription.clear(); mDescription.clear();
mTexture.clear(); mTexture.clear();
mPowers.mList.clear(); mPowers.mList.clear();
mIsDeleted = false;
} }
} }

@ -22,12 +22,8 @@ struct BirthSign
// List of powers and abilities that come with this birth sign. // List of powers and abilities that come with this birth sign.
SpellList mPowers; SpellList mPowers;
bool mIsDeleted; void load(ESMReader &esm, bool &isDeleted);
void save(ESMWriter &esm, bool isDeleted = false) const;
BirthSign();
void load(ESMReader &esm);
void save(ESMWriter &esm) const;
void blank(); void blank();
///< Set record to default state (does not touch the ID/index). ///< Set record to default state (does not touch the ID/index).

@ -52,75 +52,98 @@ namespace ESM
return ref.mRefNum == refNum; return ref.mRefNum == refNum;
} }
void Cell::load(ESMReader &esm, bool saveContext) void Cell::load(ESMReader &esm, bool &isDeleted, bool saveContext)
{ {
loadName(esm); loadNameAndData(esm, isDeleted);
loadData(esm);
loadCell(esm, saveContext); loadCell(esm, saveContext);
} }
void Cell::loadName(ESMReader &esm) void Cell::loadNameAndData(ESMReader &esm, bool &isDeleted)
{ {
mName = esm.getHNString("NAME"); isDeleted = false;
mIsDeleted = false; bool hasName = false;
if (esm.isNextSub("DELE")) bool hasData = false;
bool isLoaded = false;
while (!isLoaded && esm.hasMoreSubs())
{ {
esm.skipHSub(); esm.getSubName();
mIsDeleted = true; switch (esm.retSubName().val)
{
case ESM::FourCC<'N','A','M','E'>::value:
mName = esm.getHString();
hasName = true;
break;
case ESM::FourCC<'D','A','T','A'>::value:
esm.getHT(mData, 12);
hasData = true;
break;
case ESM::FourCC<'D','E','L','E'>::value:
esm.skipHSub();
isDeleted = true;
break;
default:
esm.cacheSubName();
isLoaded = true;
break;
}
} }
if (!hasName)
esm.fail("Missing NAME subrecord");
if (!hasData)
esm.fail("Missing DATA subrecord");
} }
void Cell::loadCell(ESMReader &esm, bool saveContext) void Cell::loadCell(ESMReader &esm, bool saveContext)
{ {
mWater = 0.0f;
mWaterInt = false;
mMapColor = 0;
mRegion.clear();
mRefNumCounter = 0; mRefNumCounter = 0;
if (mData.mFlags & Interior) bool isLoaded = false;
while (!isLoaded && esm.hasMoreSubs())
{ {
// Interior cells esm.getSubName();
if (esm.isNextSub("INTV")) switch (esm.retSubName().val)
{ {
int waterl; case ESM::FourCC<'I','N','T','V'>::value:
esm.getHT(waterl); int waterl;
mWater = (float) waterl; esm.getHT(waterl);
mWaterInt = true; mWater = static_cast<float>(waterl);
mWaterInt = true;
break;
case ESM::FourCC<'W','H','G','T'>::value:
esm.getHT(mWater);
break;
case ESM::FourCC<'A','M','B','I'>::value:
esm.getHT(mAmbi);
break;
case ESM::FourCC<'R','G','N','N'>::value:
mRegion = esm.getHString();
break;
case ESM::FourCC<'N','A','M','5'>::value:
esm.getHT(mMapColor);
break;
case ESM::FourCC<'N','A','M','0'>::value:
esm.getHT(mRefNumCounter);
break;
default:
esm.cacheSubName();
isLoaded = true;
break;
} }
else if (esm.isNextSub("WHGT"))
{
esm.getHT(mWater);
}
// Quasi-exterior cells have a region (which determines the
// weather), pure interior cells have ambient lighting
// instead.
if (mData.mFlags & QuasiEx)
mRegion = esm.getHNOString("RGNN");
else if (esm.isNextSub("AMBI"))
esm.getHT(mAmbi);
}
else
{
// Exterior cells
mRegion = esm.getHNOString("RGNN");
mMapColor = 0;
esm.getHNOT(mMapColor, "NAM5");
}
if (esm.isNextSub("NAM0")) {
esm.getHT(mRefNumCounter);
} }
if (saveContext) { if (saveContext)
{
mContextList.push_back(esm.getContext()); mContextList.push_back(esm.getContext());
esm.skipRecord(); esm.skipRecord();
} }
} }
void Cell::loadData(ESMReader &esm)
{
esm.getHNT(mData, "DATA", 12);
}
void Cell::postLoad(ESMReader &esm) void Cell::postLoad(ESMReader &esm)
{ {
// Save position of the cell references and move on // Save position of the cell references and move on
@ -128,11 +151,11 @@ namespace ESM
esm.skipRecord(); esm.skipRecord();
} }
void Cell::save(ESMWriter &esm) const void Cell::save(ESMWriter &esm, bool isDeleted) const
{ {
esm.writeHNCString("NAME", mName); esm.writeHNCString("NAME", mName);
if (mIsDeleted) if (isDeleted)
{ {
esm.writeHNCString("DELE", ""); esm.writeHNCString("DELE", "");
} }
@ -183,8 +206,10 @@ namespace ESM
} }
} }
bool Cell::getNextRef(ESMReader &esm, CellRef &ref, bool ignoreMoves, MovedCellRef *mref) bool Cell::getNextRef(ESMReader &esm, CellRef &ref, bool &isDeleted, bool ignoreMoves, MovedCellRef *mref)
{ {
isDeleted = false;
// TODO: Try and document reference numbering, I don't think this has been done anywhere else. // TODO: Try and document reference numbering, I don't think this has been done anywhere else.
if (!esm.hasMoreSubs()) if (!esm.hasMoreSubs())
return false; return false;
@ -207,12 +232,15 @@ namespace ESM
} }
} }
ref.load (esm); if (esm.peekNextSub("FRMR"))
{
// Identify references belonging to a parent file and adapt the ID accordingly. ref.load (esm, isDeleted);
adjustRefNum (ref.mRefNum, esm);
return true; // Identify references belonging to a parent file and adapt the ID accordingly.
adjustRefNum (ref.mRefNum, esm);
return true;
}
return false;
} }
bool Cell::getNextMVRF(ESMReader &esm, MovedCellRef &mref) bool Cell::getNextMVRF(ESMReader &esm, MovedCellRef &mref)
@ -242,8 +270,6 @@ namespace ESM
mAmbi.mSunlight = 0; mAmbi.mSunlight = 0;
mAmbi.mFog = 0; mAmbi.mFog = 0;
mAmbi.mFogDensity = 0; mAmbi.mFogDensity = 0;
mIsDeleted = false;
} }
CellId Cell::getCellId() const CellId Cell::getCellId() const

@ -85,8 +85,7 @@ struct Cell
mWater(0), mWater(0),
mWaterInt(false), mWaterInt(false),
mMapColor(0), mMapColor(0),
mRefNumCounter(0), mRefNumCounter(0)
mIsDeleted(false)
{} {}
// Interior cells are indexed by this (it's the 'id'), for exterior // Interior cells are indexed by this (it's the 'id'), for exterior
@ -113,18 +112,15 @@ struct Cell
CellRefTracker mLeasedRefs; CellRefTracker mLeasedRefs;
MovedCellRefTracker mMovedRefs; MovedCellRefTracker mMovedRefs;
bool mIsDeleted;
void postLoad(ESMReader &esm); void postLoad(ESMReader &esm);
// This method is left in for compatibility with esmtool. Parsing moved references currently requires // This method is left in for compatibility with esmtool. Parsing moved references currently requires
// passing ESMStore, bit it does not know about this parameter, so we do it this way. // passing ESMStore, bit it does not know about this parameter, so we do it this way.
void load(ESMReader &esm, bool saveContext = true); // Load everything (except references) void load(ESMReader &esm, bool &isDeleted, bool saveContext = true); // Load everything (except references)
void loadName(ESMReader &esm); // Load NAME and checks for DELE void loadNameAndData(ESMReader &esm, bool &isDeleted); // Load NAME and DATAstruct
void loadData(ESMReader &esm); // Load DATAstruct only void loadCell(ESMReader &esm, bool saveContext = true); // Load everything, except NAME, DATAstruct and references
void loadCell(ESMReader &esm, bool saveContext = true); // Load everything, except DATAstruct and references
void save(ESMWriter &esm) const; void save(ESMWriter &esm, bool isDeleted = false) const;
bool isExterior() const bool isExterior() const
{ {
@ -163,7 +159,11 @@ struct Cell
reuse one memory location without blanking it between calls. reuse one memory location without blanking it between calls.
*/ */
/// \param ignoreMoves ignore MVRF record and read reference like a regular CellRef. /// \param ignoreMoves ignore MVRF record and read reference like a regular CellRef.
static bool getNextRef(ESMReader &esm, CellRef &ref, bool ignoreMoves = false, MovedCellRef *mref = 0); static bool getNextRef(ESMReader &esm,
CellRef &ref,
bool &isDeleted,
bool ignoreMoves = false,
MovedCellRef *mref = 0);
/* This fetches an MVRF record, which is used to track moved references. /* This fetches an MVRF record, which is used to track moved references.
* Since they are comparably rare, we use a separate method for this. * Since they are comparably rare, we use a separate method for this.

@ -22,10 +22,6 @@ namespace ESM
"sSpecializationStealth" "sSpecializationStealth"
}; };
Class::Class()
: mIsDeleted(false)
{}
int& Class::CLDTstruct::getSkill (int index, bool major) int& Class::CLDTstruct::getSkill (int index, bool major)
{ {
if (index<0 || index>=5) if (index<0 || index>=5)
@ -42,26 +38,21 @@ namespace ESM
return mSkills[index][major ? 1 : 0]; return mSkills[index][major ? 1 : 0];
} }
void Class::load(ESMReader &esm) void Class::load(ESMReader &esm, bool &isDeleted)
{ {
mIsDeleted = false; isDeleted = false;
bool hasName = false; bool hasName = false;
bool hasData = false; bool hasData = false;
while (esm.hasMoreSubs()) while (esm.hasMoreSubs())
{ {
esm.getSubName(); esm.getSubName();
uint32_t name = esm.retSubName().val; switch (esm.retSubName().val)
switch (name)
{ {
case ESM::FourCC<'N','A','M','E'>::value: case ESM::FourCC<'N','A','M','E'>::value:
mId = esm.getHString(); mId = esm.getHString();
hasName = true; hasName = true;
break; break;
case ESM::FourCC<'D','E','L','E'>::value:
esm.skipHSub();
mIsDeleted = true;
break;
case ESM::FourCC<'F','N','A','M'>::value: case ESM::FourCC<'F','N','A','M'>::value:
mName = esm.getHString(); mName = esm.getHString();
break; break;
@ -74,6 +65,10 @@ namespace ESM
case ESM::FourCC<'D','E','S','C'>::value: case ESM::FourCC<'D','E','S','C'>::value:
mDescription = esm.getHString(); mDescription = esm.getHString();
break; break;
case ESM::FourCC<'D','E','L','E'>::value:
esm.skipHSub();
isDeleted = true;
break;
default: default:
esm.fail("Unknown subrecord"); esm.fail("Unknown subrecord");
break; break;
@ -82,14 +77,14 @@ namespace ESM
if (!hasName) if (!hasName)
esm.fail("Missing NAME subrecord"); esm.fail("Missing NAME subrecord");
if (!hasData && !mIsDeleted) if (!hasData && !isDeleted)
esm.fail("Missing CLDT subrecord"); esm.fail("Missing CLDT subrecord");
} }
void Class::save(ESMWriter &esm) const void Class::save(ESMWriter &esm, bool isDeleted) const
{ {
esm.writeHNCString("NAME", mId); esm.writeHNCString("NAME", mId);
if (mIsDeleted) if (isDeleted)
{ {
esm.writeHNCString("DELE", ""); esm.writeHNCString("DELE", "");
return; return;
@ -113,7 +108,5 @@ namespace ESM
for (int i=0; i<5; ++i) for (int i=0; i<5; ++i)
for (int i2=0; i2<2; ++i2) for (int i2=0; i2<2; ++i2)
mData.mSkills[i][i2] = 0; mData.mSkills[i][i2] = 0;
mIsDeleted = false;
} }
} }

@ -73,12 +73,8 @@ struct Class
std::string mId, mName, mDescription; std::string mId, mName, mDescription;
CLDTstruct mData; CLDTstruct mData;
bool mIsDeleted; void load(ESMReader &esm, bool &isDeleted);
void save(ESMWriter &esm, bool isDeleted = false) const;
Class();
void load(ESMReader &esm);
void save(ESMWriter &esm) const;
void blank(); void blank();
///< Set record to default state (does not touch the ID/index). ///< Set record to default state (does not touch the ID/index).

@ -8,31 +8,23 @@ namespace ESM
{ {
unsigned int Clothing::sRecordId = REC_CLOT; unsigned int Clothing::sRecordId = REC_CLOT;
Clothing::Clothing() void Clothing::load(ESMReader &esm, bool &isDeleted)
: mIsDeleted(false)
{}
void Clothing::load(ESMReader &esm)
{ {
isDeleted = false;
mParts.mParts.clear(); mParts.mParts.clear();
mIsDeleted = false;
bool hasName = false; bool hasName = false;
bool hasData = false; bool hasData = false;
while (esm.hasMoreSubs()) while (esm.hasMoreSubs())
{ {
esm.getSubName(); esm.getSubName();
uint32_t name = esm.retSubName().val; switch (esm.retSubName().val)
switch (name)
{ {
case ESM::FourCC<'N','A','M','E'>::value: case ESM::FourCC<'N','A','M','E'>::value:
mId = esm.getHString(); mId = esm.getHString();
hasName = true; hasName = true;
break; break;
case ESM::FourCC<'D','E','L','E'>::value:
esm.skipHSub();
mIsDeleted = true;
break;
case ESM::FourCC<'M','O','D','L'>::value: case ESM::FourCC<'M','O','D','L'>::value:
mModel = esm.getHString(); mModel = esm.getHString();
break; break;
@ -55,6 +47,10 @@ namespace ESM
case ESM::FourCC<'I','N','D','X'>::value: case ESM::FourCC<'I','N','D','X'>::value:
mParts.add(esm); mParts.add(esm);
break; break;
case ESM::FourCC<'D','E','L','E'>::value:
esm.skipHSub();
isDeleted = true;
break;
default: default:
esm.fail("Unknown subrecord"); esm.fail("Unknown subrecord");
break; break;
@ -63,15 +59,15 @@ namespace ESM
if (!hasName) if (!hasName)
esm.fail("Missing NAME subrecord"); esm.fail("Missing NAME subrecord");
if (!hasData && !mIsDeleted) if (!hasData && !isDeleted)
esm.fail("Missing CTDT subrecord"); esm.fail("Missing CTDT subrecord");
} }
void Clothing::save(ESMWriter &esm) const void Clothing::save(ESMWriter &esm, bool isDeleted) const
{ {
esm.writeHNCString("NAME", mId); esm.writeHNCString("NAME", mId);
if (mIsDeleted) if (isDeleted)
{ {
esm.writeHNCString("DELE", ""); esm.writeHNCString("DELE", "");
return; return;
@ -101,6 +97,5 @@ namespace ESM
mIcon.clear(); mIcon.clear();
mEnchant.clear(); mEnchant.clear();
mScript.clear(); mScript.clear();
mIsDeleted = false;
} }
} }

@ -48,12 +48,8 @@ struct Clothing
std::string mId, mName, mModel, mIcon, mEnchant, mScript; std::string mId, mName, mModel, mIcon, mEnchant, mScript;
bool mIsDeleted; void load(ESMReader &esm, bool &isDeleted);
void save(ESMWriter &esm, bool isDeleted = false) const;
Clothing();
void load(ESMReader &esm);
void save(ESMWriter &esm) const;
void blank(); void blank();
///< Set record to default state (does not touch the ID). ///< Set record to default state (does not touch the ID).

@ -24,16 +24,11 @@ namespace ESM
unsigned int Container::sRecordId = REC_CONT; unsigned int Container::sRecordId = REC_CONT;
Container::Container() void Container::load(ESMReader &esm, bool &isDeleted)
: mWeight(0),
mFlags(0x8),
mIsDeleted(false)
{}
void Container::load(ESMReader &esm)
{ {
isDeleted = false;
mInventory.mList.clear(); mInventory.mList.clear();
mIsDeleted = false;
bool hasName = false; bool hasName = false;
bool hasWeight = false; bool hasWeight = false;
@ -41,17 +36,12 @@ namespace ESM
while (esm.hasMoreSubs()) while (esm.hasMoreSubs())
{ {
esm.getSubName(); esm.getSubName();
uint32_t name = esm.retSubName().val; switch (esm.retSubName().val)
switch (name)
{ {
case ESM::FourCC<'N','A','M','E'>::value: case ESM::FourCC<'N','A','M','E'>::value:
mId = esm.getHString(); mId = esm.getHString();
hasName = true; hasName = true;
break; break;
case ESM::FourCC<'D','E','L','E'>::value:
esm.skipHSub();
mIsDeleted = true;
break;
case ESM::FourCC<'M','O','D','L'>::value: case ESM::FourCC<'M','O','D','L'>::value:
mModel = esm.getHString(); mModel = esm.getHString();
break; break;
@ -76,6 +66,10 @@ namespace ESM
case ESM::FourCC<'N','P','C','O'>::value: case ESM::FourCC<'N','P','C','O'>::value:
mInventory.add(esm); mInventory.add(esm);
break; break;
case ESM::FourCC<'D','E','L','E'>::value:
esm.skipHSub();
isDeleted = true;
break;
default: default:
esm.fail("Unknown subrecord"); esm.fail("Unknown subrecord");
break; break;
@ -84,17 +78,17 @@ namespace ESM
if (!hasName) if (!hasName)
esm.fail("Missing NAME subrecord"); esm.fail("Missing NAME subrecord");
if (!hasWeight && !mIsDeleted) if (!hasWeight && !isDeleted)
esm.fail("Missing CNDT subrecord"); esm.fail("Missing CNDT subrecord");
if (!hasFlags && !mIsDeleted) if (!hasFlags && !isDeleted)
esm.fail("Missing FLAG subrecord"); esm.fail("Missing FLAG subrecord");
} }
void Container::save(ESMWriter &esm) const void Container::save(ESMWriter &esm, bool isDeleted) const
{ {
esm.writeHNCString("NAME", mId); esm.writeHNCString("NAME", mId);
if (mIsDeleted) if (isDeleted)
{ {
esm.writeHNCString("DELE", ""); esm.writeHNCString("DELE", "");
return; return;
@ -118,6 +112,5 @@ namespace ESM
mWeight = 0; mWeight = 0;
mFlags = 0x8; // set default flag value mFlags = 0x8; // set default flag value
mInventory.mList.clear(); mInventory.mList.clear();
mIsDeleted = false;
} }
} }

@ -52,12 +52,8 @@ struct Container
int mFlags; int mFlags;
InventoryList mInventory; InventoryList mInventory;
bool mIsDeleted; void load(ESMReader &esm, bool &isDeleted);
void save(ESMWriter &esm, bool isDeleted = false) const;
Container();
void load(ESMReader &esm);
void save(ESMWriter &esm) const;
void blank(); void blank();
///< Set record to default state (does not touch the ID). ///< Set record to default state (does not touch the ID).

@ -8,14 +8,10 @@ namespace ESM {
unsigned int Creature::sRecordId = REC_CREA; unsigned int Creature::sRecordId = REC_CREA;
Creature::Creature() void Creature::load(ESMReader &esm, bool &isDeleted)
: mFlags(0),
mScale(0.0f),
mIsDeleted(false)
{}
void Creature::load(ESMReader &esm)
{ {
isDeleted = false;
mPersistent = (esm.getRecordFlags() & 0x0400) != 0; mPersistent = (esm.getRecordFlags() & 0x0400) != 0;
mAiPackage.mList.clear(); mAiPackage.mList.clear();
@ -25,7 +21,6 @@ namespace ESM {
mScale = 1.f; mScale = 1.f;
mHasAI = false; mHasAI = false;
mIsDeleted = false;
bool hasName = false; bool hasName = false;
bool hasNpdt = false; bool hasNpdt = false;
@ -33,17 +28,12 @@ namespace ESM {
while (esm.hasMoreSubs()) while (esm.hasMoreSubs())
{ {
esm.getSubName(); esm.getSubName();
uint32_t name = esm.retSubName().val; switch (esm.retSubName().val)
switch (name)
{ {
case ESM::FourCC<'N','A','M','E'>::value: case ESM::FourCC<'N','A','M','E'>::value:
mId = esm.getHString(); mId = esm.getHString();
hasName = true; hasName = true;
break; break;
case ESM::FourCC<'D','E','L','E'>::value:
esm.skipHSub();
mIsDeleted = true;
break;
case ESM::FourCC<'M','O','D','L'>::value: case ESM::FourCC<'M','O','D','L'>::value:
mModel = esm.getHString(); mModel = esm.getHString();
break; break;
@ -89,6 +79,10 @@ namespace ESM {
case AI_CNDT: case AI_CNDT:
mAiPackage.add(esm); mAiPackage.add(esm);
break; break;
case ESM::FourCC<'D','E','L','E'>::value:
esm.skipHSub();
isDeleted = true;
break;
default: default:
esm.fail("Unknown subrecord"); esm.fail("Unknown subrecord");
break; break;
@ -97,17 +91,17 @@ namespace ESM {
if (!hasName) if (!hasName)
esm.fail("Missing NAME subrecord"); esm.fail("Missing NAME subrecord");
if (!hasNpdt && !mIsDeleted) if (!hasNpdt && !isDeleted)
esm.fail("Missing NPDT subrecord"); esm.fail("Missing NPDT subrecord");
if (!hasFlags && !mIsDeleted) if (!hasFlags && !isDeleted)
esm.fail("Missing FLAG subrecord"); esm.fail("Missing FLAG subrecord");
} }
void Creature::save(ESMWriter &esm) const void Creature::save(ESMWriter &esm, bool isDeleted) const
{ {
esm.writeHNCString("NAME", mId); esm.writeHNCString("NAME", mId);
if (mIsDeleted) if (isDeleted)
{ {
esm.writeHNCString("DELE", ""); esm.writeHNCString("DELE", "");
return; return;
@ -156,7 +150,6 @@ namespace ESM {
mAiData.mServices = 0; mAiData.mServices = 0;
mAiPackage.mList.clear(); mAiPackage.mList.clear();
mTransport.mList.clear(); mTransport.mList.clear();
mIsDeleted = false;
} }
const std::vector<Transport::Dest>& Creature::getTransport() const const std::vector<Transport::Dest>& Creature::getTransport() const

@ -96,14 +96,10 @@ struct Creature
AIPackageList mAiPackage; AIPackageList mAiPackage;
Transport mTransport; Transport mTransport;
bool mIsDeleted;
Creature();
const std::vector<Transport::Dest>& getTransport() const; const std::vector<Transport::Dest>& getTransport() const;
void load(ESMReader &esm); void load(ESMReader &esm, bool &isDeleted);
void save(ESMWriter &esm) const; void save(ESMWriter &esm, bool isDeleted = false) const;
void blank(); void blank();
///< Set record to default state (does not touch the ID). ///< Set record to default state (does not touch the ID).

@ -10,29 +10,25 @@ namespace ESM
{ {
unsigned int Dialogue::sRecordId = REC_DIAL; unsigned int Dialogue::sRecordId = REC_DIAL;
Dialogue::Dialogue() void Dialogue::load(ESMReader &esm, bool &isDeleted)
: mIsDeleted(false)
{}
void Dialogue::load(ESMReader &esm)
{ {
loadId(esm); loadId(esm);
loadData(esm); loadData(esm, isDeleted);
} }
void Dialogue::loadId(ESMReader &esm) void Dialogue::loadId(ESMReader &esm)
{ {
mIsDeleted = false;
mId = esm.getHNString("NAME"); mId = esm.getHNString("NAME");
} }
void Dialogue::loadData(ESMReader &esm) void Dialogue::loadData(ESMReader &esm, bool &isDeleted)
{ {
isDeleted = false;
while (esm.hasMoreSubs()) while (esm.hasMoreSubs())
{ {
esm.getSubName(); esm.getSubName();
uint32_t name = esm.retSubName().val; switch (esm.retSubName().val)
switch (name)
{ {
case ESM::FourCC<'D','A','T','A'>::value: case ESM::FourCC<'D','A','T','A'>::value:
{ {
@ -51,7 +47,7 @@ namespace ESM
case ESM::FourCC<'D','E','L','E'>::value: case ESM::FourCC<'D','E','L','E'>::value:
esm.skipHSub(); esm.skipHSub();
mType = Unknown; mType = Unknown;
mIsDeleted = true; isDeleted = true;
break; break;
default: default:
esm.fail("Unknown subrecord"); esm.fail("Unknown subrecord");
@ -60,10 +56,10 @@ namespace ESM
} }
} }
void Dialogue::save(ESMWriter &esm) const void Dialogue::save(ESMWriter &esm, bool isDeleted) const
{ {
esm.writeHNCString("NAME", mId); esm.writeHNCString("NAME", mId);
if (mIsDeleted) if (isDeleted)
{ {
esm.writeHNCString("DELE", ""); esm.writeHNCString("DELE", "");
} }
@ -76,7 +72,6 @@ namespace ESM
void Dialogue::blank() void Dialogue::blank()
{ {
mInfo.clear(); mInfo.clear();
mIsDeleted = false;
} }
void Dialogue::readInfo(ESMReader &esm, bool merge) void Dialogue::readInfo(ESMReader &esm, bool merge)
@ -84,25 +79,27 @@ namespace ESM
ESM::DialInfo info; ESM::DialInfo info;
info.loadId(esm); info.loadId(esm);
bool isDeleted = false;
if (!merge || mInfo.empty()) if (!merge || mInfo.empty())
{ {
info.loadInfo(esm); info.loadData(esm, isDeleted);
mLookup[info.mId] = mInfo.insert(mInfo.end(), info); mLookup[info.mId] = std::make_pair(mInfo.insert(mInfo.end(), info), isDeleted);
return; return;
} }
ESM::Dialogue::InfoContainer::iterator it = mInfo.end(); InfoContainer::iterator it = mInfo.end();
std::map<std::string, ESM::Dialogue::InfoContainer::iterator>::iterator lookup; LookupMap::iterator lookup;
lookup = mLookup.find(info.mId); lookup = mLookup.find(info.mId);
if (lookup != mLookup.end()) if (lookup != mLookup.end())
{ {
it = lookup->second; it = lookup->second.first;
// Merge with existing record. Only the subrecords that are present in // Merge with existing record. Only the subrecords that are present in
// the new record will be overwritten. // the new record will be overwritten.
it->loadInfo(esm); it->loadData(esm, isDeleted);
info = *it; info = *it;
// Since the record merging may have changed the next/prev linked list connection, we need to re-insert the record // Since the record merging may have changed the next/prev linked list connection, we need to re-insert the record
@ -111,35 +108,35 @@ namespace ESM
} }
else else
{ {
info.loadInfo(esm); info.loadData(esm, isDeleted);
} }
if (info.mNext.empty()) if (info.mNext.empty())
{ {
mLookup[info.mId] = mInfo.insert(mInfo.end(), info); mLookup[info.mId] = std::make_pair(mInfo.insert(mInfo.end(), info), isDeleted);
return; return;
} }
if (info.mPrev.empty()) if (info.mPrev.empty())
{ {
mLookup[info.mId] = mInfo.insert(mInfo.begin(), info); mLookup[info.mId] = std::make_pair(mInfo.insert(mInfo.begin(), info), isDeleted);
return; return;
} }
lookup = mLookup.find(info.mPrev); lookup = mLookup.find(info.mPrev);
if (lookup != mLookup.end()) if (lookup != mLookup.end())
{ {
it = lookup->second; it = lookup->second.first;
mLookup[info.mId] = mInfo.insert(++it, info); mLookup[info.mId] = std::make_pair(mInfo.insert(++it, info), isDeleted);
return; return;
} }
lookup = mLookup.find(info.mNext); lookup = mLookup.find(info.mNext);
if (lookup != mLookup.end()) if (lookup != mLookup.end())
{ {
it = lookup->second; it = lookup->second.first;
mLookup[info.mId] = mInfo.insert(it, info); mLookup[info.mId] = std::make_pair(mInfo.insert(it, info), isDeleted);
return; return;
} }
@ -148,12 +145,15 @@ namespace ESM
void Dialogue::clearDeletedInfos() void Dialogue::clearDeletedInfos()
{ {
for (InfoContainer::iterator it = mInfo.begin(); it != mInfo.end(); ) LookupMap::const_iterator current = mLookup.begin();
LookupMap::const_iterator end = mLookup.end();
for (; current != end; ++current)
{ {
if (it->mIsDeleted) if (current->second.second)
it = mInfo.erase(it); {
else mInfo.erase(current->second.first);
++it; }
} }
mLookup.clear();
} }
} }

@ -4,6 +4,7 @@
#include <string> #include <string>
#include <list> #include <list>
#include <map> #include <map>
#include <set>
#include "loadinfo.hpp" #include "loadinfo.hpp"
@ -39,27 +40,24 @@ struct Dialogue
typedef std::list<DialInfo> InfoContainer; typedef std::list<DialInfo> InfoContainer;
typedef std::map<std::string, InfoContainer::iterator> LookupMap; // Parameters: Info ID, (Info iterator, Deleted flag)
typedef std::map<std::string, std::pair<InfoContainer::iterator, bool> > LookupMap;
InfoContainer mInfo; InfoContainer mInfo;
// This is only used during the loading phase to speed up DialInfo merging. // This is only used during the loading phase to speed up DialInfo merging.
LookupMap mLookup; LookupMap mLookup;
bool mIsDeleted; void load(ESMReader &esm, bool &isDeleted);
Dialogue();
void load(ESMReader &esm);
///< Loads all sub-records of Dialogue record ///< Loads all sub-records of Dialogue record
void loadId(ESMReader &esm); void loadId(ESMReader &esm);
///< Loads NAME sub-record of Dialogue record ///< Loads NAME sub-record of Dialogue record
void loadData(ESMReader &esm); void loadData(ESMReader &esm, bool &isDeleted);
///< Loads all sub-records of Dialogue record, except NAME sub-record ///< Loads all sub-records of Dialogue record, except NAME sub-record
void save(ESMWriter &esm) const; void save(ESMWriter &esm, bool isDeleted = false) const;
/// Remove all INFOs that are deleted or marked as QS_Deleted from mInfos. /// Remove all INFOs that are deleted
void clearDeletedInfos(); void clearDeletedInfos();
/// Read the next info record /// Read the next info record

@ -8,29 +8,20 @@ namespace ESM
{ {
unsigned int Door::sRecordId = REC_DOOR; unsigned int Door::sRecordId = REC_DOOR;
Door::Door() void Door::load(ESMReader &esm, bool &isDeleted)
: mIsDeleted(false)
{}
void Door::load(ESMReader &esm)
{ {
mIsDeleted = false; isDeleted = false;
bool hasName = false; bool hasName = false;
while (esm.hasMoreSubs()) while (esm.hasMoreSubs())
{ {
esm.getSubName(); esm.getSubName();
uint32_t name = esm.retSubName().val; switch (esm.retSubName().val)
switch (name)
{ {
case ESM::FourCC<'N','A','M','E'>::value: case ESM::FourCC<'N','A','M','E'>::value:
mId = esm.getHString(); mId = esm.getHString();
hasName = true; hasName = true;
break; break;
case ESM::FourCC<'D','E','L','E'>::value:
esm.skipHSub();
mIsDeleted = true;
break;
case ESM::FourCC<'M','O','D','L'>::value: case ESM::FourCC<'M','O','D','L'>::value:
mModel = esm.getHString(); mModel = esm.getHString();
break; break;
@ -46,6 +37,10 @@ namespace ESM
case ESM::FourCC<'A','N','A','M'>::value: case ESM::FourCC<'A','N','A','M'>::value:
mCloseSound = esm.getHString(); mCloseSound = esm.getHString();
break; break;
case ESM::FourCC<'D','E','L','E'>::value:
esm.skipHSub();
isDeleted = true;
break;
default: default:
esm.fail("Unknown subrecord"); esm.fail("Unknown subrecord");
break; break;
@ -56,11 +51,11 @@ namespace ESM
esm.fail("Missing NAME subrecord"); esm.fail("Missing NAME subrecord");
} }
void Door::save(ESMWriter &esm) const void Door::save(ESMWriter &esm, bool isDeleted) const
{ {
esm.writeHNCString("NAME", mId); esm.writeHNCString("NAME", mId);
if (mIsDeleted) if (isDeleted)
{ {
esm.writeHNCString("DELE", ""); esm.writeHNCString("DELE", "");
return; return;
@ -80,6 +75,5 @@ namespace ESM
mScript.clear(); mScript.clear();
mOpenSound.clear(); mOpenSound.clear();
mCloseSound.clear(); mCloseSound.clear();
mIsDeleted = false;
} }
} }

@ -17,12 +17,8 @@ struct Door
std::string mId, mName, mModel, mScript, mOpenSound, mCloseSound; std::string mId, mName, mModel, mScript, mOpenSound, mCloseSound;
bool mIsDeleted; void load(ESMReader &esm, bool &isDeleted);
void save(ESMWriter &esm, bool isDeleted = false) const;
Door();
void load(ESMReader &esm);
void save(ESMWriter &esm) const;
void blank(); void blank();
///< Set record to default state (does not touch the ID). ///< Set record to default state (does not touch the ID).

@ -8,31 +8,22 @@ namespace ESM
{ {
unsigned int Enchantment::sRecordId = REC_ENCH; unsigned int Enchantment::sRecordId = REC_ENCH;
Enchantment::Enchantment() void Enchantment::load(ESMReader &esm, bool &isDeleted)
: mIsDeleted(false)
{}
void Enchantment::load(ESMReader &esm)
{ {
isDeleted = false;
mEffects.mList.clear(); mEffects.mList.clear();
mIsDeleted = false;
bool hasName = false; bool hasName = false;
bool hasData = false; bool hasData = false;
while (esm.hasMoreSubs()) while (esm.hasMoreSubs())
{ {
esm.getSubName(); esm.getSubName();
uint32_t name = esm.retSubName().val; switch (esm.retSubName().val)
switch (name)
{ {
case ESM::FourCC<'N','A','M','E'>::value: case ESM::FourCC<'N','A','M','E'>::value:
mId = esm.getHString(); mId = esm.getHString();
hasName = true; hasName = true;
break; break;
case ESM::FourCC<'D','E','L','E'>::value:
esm.skipHSub();
mIsDeleted = true;
break;
case ESM::FourCC<'E','N','D','T'>::value: case ESM::FourCC<'E','N','D','T'>::value:
esm.getHT(mData, 16); esm.getHT(mData, 16);
hasData = true; hasData = true;
@ -40,6 +31,10 @@ namespace ESM
case ESM::FourCC<'E','N','A','M'>::value: case ESM::FourCC<'E','N','A','M'>::value:
mEffects.add(esm); mEffects.add(esm);
break; break;
case ESM::FourCC<'D','E','L','E'>::value:
esm.skipHSub();
isDeleted = true;
break;
default: default:
esm.fail("Unknown subrecord"); esm.fail("Unknown subrecord");
break; break;
@ -48,15 +43,15 @@ namespace ESM
if (!hasName) if (!hasName)
esm.fail("Missing NAME subrecord"); esm.fail("Missing NAME subrecord");
if (!hasData && !mIsDeleted) if (!hasData && !isDeleted)
esm.fail("Missing ENDT subrecord"); esm.fail("Missing ENDT subrecord");
} }
void Enchantment::save(ESMWriter &esm) const void Enchantment::save(ESMWriter &esm, bool isDeleted) const
{ {
esm.writeHNCString("NAME", mId); esm.writeHNCString("NAME", mId);
if (mIsDeleted) if (isDeleted)
{ {
esm.writeHNCString("DELE", ""); esm.writeHNCString("DELE", "");
return; return;
@ -74,7 +69,5 @@ namespace ESM
mData.mAutocalc = 0; mData.mAutocalc = 0;
mEffects.mList.clear(); mEffects.mList.clear();
mIsDeleted = false;
} }
} }

@ -42,12 +42,8 @@ struct Enchantment
ENDTstruct mData; ENDTstruct mData;
EffectList mEffects; EffectList mEffects;
bool mIsDeleted; void load(ESMReader &esm, bool &isDeleted);
void save(ESMWriter &esm, bool isDeleted = false) const;
Enchantment();
void load(ESMReader &esm);
void save(ESMWriter &esm) const;
void blank(); void blank();
///< Set record to default state (does not touch the ID). ///< Set record to default state (does not touch the ID).

@ -10,10 +10,6 @@ namespace ESM
{ {
unsigned int Faction::sRecordId = REC_FACT; unsigned int Faction::sRecordId = REC_FACT;
Faction::Faction()
: mIsDeleted(false)
{}
int& Faction::FADTstruct::getSkill (int index, bool ignored) int& Faction::FADTstruct::getSkill (int index, bool ignored)
{ {
if (index<0 || index>=7) if (index<0 || index>=7)
@ -30,9 +26,10 @@ namespace ESM
return mSkills[index]; return mSkills[index];
} }
void Faction::load(ESMReader &esm) void Faction::load(ESMReader &esm, bool &isDeleted)
{ {
mIsDeleted = false; isDeleted = false;
mReactions.clear(); mReactions.clear();
for (int i=0;i<10;++i) for (int i=0;i<10;++i)
mRanks[i].clear(); mRanks[i].clear();
@ -43,17 +40,12 @@ namespace ESM
while (esm.hasMoreSubs()) while (esm.hasMoreSubs())
{ {
esm.getSubName(); esm.getSubName();
uint32_t name = esm.retSubName().val; switch (esm.retSubName().val)
switch (name)
{ {
case ESM::FourCC<'N','A','M','E'>::value: case ESM::FourCC<'N','A','M','E'>::value:
mId = esm.getHString(); mId = esm.getHString();
hasName = true; hasName = true;
break; break;
case ESM::FourCC<'D','E','L','E'>::value:
esm.skipHSub();
mIsDeleted = true;
break;
case ESM::FourCC<'F','N','A','M'>::value: case ESM::FourCC<'F','N','A','M'>::value:
mName = esm.getHString(); mName = esm.getHString();
break; break;
@ -76,6 +68,10 @@ namespace ESM
mReactions[faction] = reaction; mReactions[faction] = reaction;
break; break;
} }
case ESM::FourCC<'D','E','L','E'>::value:
esm.skipHSub();
isDeleted = true;
break;
default: default:
esm.fail("Unknown subrecord"); esm.fail("Unknown subrecord");
break; break;
@ -84,15 +80,15 @@ namespace ESM
if (!hasName) if (!hasName)
esm.fail("Missing NAME subrecord"); esm.fail("Missing NAME subrecord");
if (!hasData && !mIsDeleted) if (!hasData && !isDeleted)
esm.fail("Missing FADT subrecord"); esm.fail("Missing FADT subrecord");
} }
void Faction::save(ESMWriter &esm) const void Faction::save(ESMWriter &esm, bool isDeleted) const
{ {
esm.writeHNCString("NAME", mId); esm.writeHNCString("NAME", mId);
if (mIsDeleted) if (isDeleted)
{ {
esm.writeHNCString("DELE", ""); esm.writeHNCString("DELE", "");
return; return;
@ -136,7 +132,5 @@ namespace ESM
mData.mSkills[i] = 0; mData.mSkills[i] = 0;
mReactions.clear(); mReactions.clear();
mIsDeleted = false;
} }
} }

@ -62,12 +62,8 @@ struct Faction
// Name of faction ranks (may be empty for NPC factions) // Name of faction ranks (may be empty for NPC factions)
std::string mRanks[10]; std::string mRanks[10];
bool mIsDeleted; void load(ESMReader &esm, bool &isDeleted);
void save(ESMWriter &esm, bool isDeleted = false) const;
Faction();
void load(ESMReader &esm);
void save(ESMWriter &esm) const;
void blank(); void blank();
///< Set record to default state (does not touch the ID/index). ///< Set record to default state (does not touch the ID/index).

@ -8,19 +8,16 @@ namespace ESM
{ {
unsigned int Global::sRecordId = REC_GLOB; unsigned int Global::sRecordId = REC_GLOB;
Global::Global() void Global::load (ESMReader &esm, bool &isDeleted)
: mIsDeleted(false)
{}
void Global::load (ESMReader &esm)
{ {
mIsDeleted = false; isDeleted = false;
mId = esm.getHNString ("NAME"); mId = esm.getHNString ("NAME");
if (esm.isNextSub ("DELE")) if (esm.isNextSub ("DELE"))
{ {
esm.skipHSub(); esm.skipHSub();
mIsDeleted = true; isDeleted = true;
} }
else else
{ {
@ -28,11 +25,11 @@ namespace ESM
} }
} }
void Global::save (ESMWriter &esm) const void Global::save (ESMWriter &esm, bool isDeleted) const
{ {
esm.writeHNCString ("NAME", mId); esm.writeHNCString ("NAME", mId);
if (mIsDeleted) if (isDeleted)
{ {
esm.writeHNCString ("DELE", ""); esm.writeHNCString ("DELE", "");
} }
@ -45,7 +42,6 @@ namespace ESM
void Global::blank() void Global::blank()
{ {
mValue.setType (ESM::VT_None); mValue.setType (ESM::VT_None);
mIsDeleted = false;
} }
bool operator== (const Global& left, const Global& right) bool operator== (const Global& left, const Global& right)

@ -24,12 +24,8 @@ struct Global
std::string mId; std::string mId;
Variant mValue; Variant mValue;
bool mIsDeleted; void load(ESMReader &esm, bool &isDeleted);
void save(ESMWriter &esm, bool isDeleted = false) const;
Global();
void load(ESMReader &esm);
void save(ESMWriter &esm) const;
void blank(); void blank();
///< Set record to default state (does not touch the ID). ///< Set record to default state (does not touch the ID).

@ -8,13 +8,15 @@ namespace ESM
{ {
unsigned int GameSetting::sRecordId = REC_GMST; unsigned int GameSetting::sRecordId = REC_GMST;
void GameSetting::load (ESMReader &esm) void GameSetting::load (ESMReader &esm, bool &isDeleted)
{ {
isDeleted = false; // GameSetting record can't be deleted now (may be changed in the future)
mId = esm.getHNString("NAME"); mId = esm.getHNString("NAME");
mValue.read (esm, ESM::Variant::Format_Gmst); mValue.read (esm, ESM::Variant::Format_Gmst);
} }
void GameSetting::save (ESMWriter &esm) const void GameSetting::save (ESMWriter &esm, bool /*isDeleted*/) const
{ {
esm.writeHNCString("NAME", mId); esm.writeHNCString("NAME", mId);
mValue.write (esm, ESM::Variant::Format_Gmst); mValue.write (esm, ESM::Variant::Format_Gmst);

@ -26,7 +26,7 @@ struct GameSetting
Variant mValue; Variant mValue;
void load(ESMReader &esm); void load(ESMReader &esm, bool &isDeleted);
/// \todo remove the get* functions (redundant, since mValue has equivalent functions now). /// \todo remove the get* functions (redundant, since mValue has equivalent functions now).
@ -39,7 +39,7 @@ struct GameSetting
std::string getString() const; std::string getString() const;
///< Throwns an exception if GMST is not of type string. ///< Throwns an exception if GMST is not of type string.
void save(ESMWriter &esm) const; void save(ESMWriter &esm, bool isDeleted = false) const;
void blank(); void blank();
///< Set record to default state (does not touch the ID). ///< Set record to default state (does not touch the ID).

@ -8,29 +8,23 @@ namespace ESM
{ {
unsigned int DialInfo::sRecordId = REC_INFO; unsigned int DialInfo::sRecordId = REC_INFO;
DialInfo::DialInfo() void DialInfo::load(ESMReader &esm, bool &isDeleted)
: mFactionLess(false),
mQuestStatus(QS_None),
mIsDeleted(false)
{}
void DialInfo::load(ESMReader &esm)
{ {
loadId(esm); loadId(esm);
loadInfo(esm); loadData(esm, isDeleted);
} }
void DialInfo::loadId(ESMReader &esm) void DialInfo::loadId(ESMReader &esm)
{ {
mIsDeleted = false;
mId = esm.getHNString("INAM"); mId = esm.getHNString("INAM");
} }
void DialInfo::loadInfo(ESMReader &esm) void DialInfo::loadData(ESMReader &esm, bool &isDeleted)
{ {
isDeleted = false;
mQuestStatus = QS_None; mQuestStatus = QS_None;
mFactionLess = false; mFactionLess = false;
mIsDeleted = false;
mPrev = esm.getHNString("PNAM"); mPrev = esm.getHNString("PNAM");
mNext = esm.getHNString("NNAM"); mNext = esm.getHNString("NNAM");
@ -41,13 +35,8 @@ namespace ESM
while (esm.hasMoreSubs()) while (esm.hasMoreSubs())
{ {
esm.getSubName(); esm.getSubName();
uint32_t name = esm.retSubName().val; switch (esm.retSubName().val)
switch (name)
{ {
case ESM::FourCC<'D','E','L','E'>::value:
esm.skipHSub();
mIsDeleted = true;
break;
case ESM::FourCC<'D','A','T','A'>::value: case ESM::FourCC<'D','A','T','A'>::value:
esm.getHT(mData, 12); esm.getHT(mData, 12);
break; break;
@ -104,6 +93,10 @@ namespace ESM
mQuestStatus = QS_Restart; mQuestStatus = QS_Restart;
esm.skipRecord(); esm.skipRecord();
break; break;
case ESM::FourCC<'D','E','L','E'>::value:
esm.skipHSub();
isDeleted = true;
break;
default: default:
esm.fail("Unknown subrecord"); esm.fail("Unknown subrecord");
break; break;
@ -111,13 +104,13 @@ namespace ESM
} }
} }
void DialInfo::save(ESMWriter &esm) const void DialInfo::save(ESMWriter &esm, bool isDeleted) const
{ {
esm.writeHNCString("INAM", mId); esm.writeHNCString("INAM", mId);
esm.writeHNCString("PNAM", mPrev); esm.writeHNCString("PNAM", mPrev);
esm.writeHNCString("NNAM", mNext); esm.writeHNCString("NNAM", mNext);
if (mIsDeleted) if (isDeleted)
{ {
esm.writeHNCString("DELE", ""); esm.writeHNCString("DELE", "");
return; return;
@ -173,6 +166,5 @@ namespace ESM
mResultScript.clear(); mResultScript.clear();
mFactionLess = false; mFactionLess = false;
mQuestStatus = QS_None; mQuestStatus = QS_None;
mIsDeleted = false;
} }
} }

@ -105,18 +105,14 @@ struct DialInfo
REC_DELE = 0x454c4544 REC_DELE = 0x454c4544
}; };
bool mIsDeleted; void load(ESMReader &esm, bool &isDeleted);
DialInfo();
void load(ESMReader &esm);
///< Loads all sub-records of Info record ///< Loads all sub-records of Info record
void loadId(ESMReader &esm); void loadId(ESMReader &esm);
///< Loads only Id of Info record (INAM sub-record) ///< Loads only Id of Info record (INAM sub-record)
void loadInfo(ESMReader &esm); void loadData(ESMReader &esm, bool &isDeleted);
///< Loads all sub-records of Info record, except INAM sub-record ///< Loads all sub-records of Info record, except INAM sub-record
void save(ESMWriter &esm) const; void save(ESMWriter &esm, bool isDeleted = false) const;
void blank(); void blank();
///< Set record to default state (does not touch the ID). ///< Set record to default state (does not touch the ID).

@ -8,30 +8,21 @@ namespace ESM
{ {
unsigned int Ingredient::sRecordId = REC_INGR; unsigned int Ingredient::sRecordId = REC_INGR;
Ingredient::Ingredient() void Ingredient::load(ESMReader &esm, bool &isDeleted)
: mIsDeleted(false)
{}
void Ingredient::load(ESMReader &esm)
{ {
mIsDeleted = false; isDeleted = false;
bool hasName = false; bool hasName = false;
bool hasData = false; bool hasData = false;
while (esm.hasMoreSubs()) while (esm.hasMoreSubs())
{ {
esm.getSubName(); esm.getSubName();
uint32_t name = esm.retSubName().val; switch (esm.retSubName().val)
switch (name)
{ {
case ESM::FourCC<'N','A','M','E'>::value: case ESM::FourCC<'N','A','M','E'>::value:
mId = esm.getHString(); mId = esm.getHString();
hasName = true; hasName = true;
break; break;
case ESM::FourCC<'D','E','L','E'>::value:
esm.skipHSub();
mIsDeleted = true;
break;
case ESM::FourCC<'M','O','D','L'>::value: case ESM::FourCC<'M','O','D','L'>::value:
mModel = esm.getHString(); mModel = esm.getHString();
break; break;
@ -48,6 +39,10 @@ namespace ESM
case ESM::FourCC<'I','T','E','X'>::value: case ESM::FourCC<'I','T','E','X'>::value:
mIcon = esm.getHString(); mIcon = esm.getHString();
break; break;
case ESM::FourCC<'D','E','L','E'>::value:
esm.skipHSub();
isDeleted = true;
break;
default: default:
esm.fail("Unknown subrecord"); esm.fail("Unknown subrecord");
break; break;
@ -56,7 +51,7 @@ namespace ESM
if (!hasName) if (!hasName)
esm.fail("Missing NAME subrecord"); esm.fail("Missing NAME subrecord");
if (!hasData && !mIsDeleted) if (!hasData && !isDeleted)
esm.fail("Missing IRDT subrecord"); esm.fail("Missing IRDT subrecord");
// horrible hack to fix broken data in records // horrible hack to fix broken data in records
@ -83,11 +78,11 @@ namespace ESM
} }
} }
void Ingredient::save(ESMWriter &esm) const void Ingredient::save(ESMWriter &esm, bool isDeleted) const
{ {
esm.writeHNCString("NAME", mId); esm.writeHNCString("NAME", mId);
if (mIsDeleted) if (isDeleted)
{ {
esm.writeHNCString("DELE", ""); esm.writeHNCString("DELE", "");
return; return;
@ -115,7 +110,5 @@ namespace ESM
mModel.clear(); mModel.clear();
mIcon.clear(); mIcon.clear();
mScript.clear(); mScript.clear();
mIsDeleted = false;
} }
} }

@ -31,12 +31,8 @@ struct Ingredient
IRDTstruct mData; IRDTstruct mData;
std::string mId, mName, mModel, mIcon, mScript; std::string mId, mName, mModel, mIcon, mScript;
bool mIsDeleted; void load(ESMReader &esm, bool &isDeleted);
void save(ESMWriter &esm, bool isDeleted = false) const;
Ingredient();
void load(ESMReader &esm);
void save(ESMWriter &esm) const;
void blank(); void blank();
///< Set record to default state (does not touch the ID). ///< Set record to default state (does not touch the ID).

@ -72,7 +72,6 @@ namespace ESM
, mDataTypes(0) , mDataTypes(0)
, mDataLoaded(false) , mDataLoaded(false)
, mLandData(NULL) , mLandData(NULL)
, mIsDeleted(false)
{ {
} }
@ -81,61 +80,82 @@ namespace ESM
delete mLandData; delete mLandData;
} }
void Land::load(ESMReader &esm) void Land::load(ESMReader &esm, bool &isDeleted)
{ {
isDeleted = false;
mEsm = &esm; mEsm = &esm;
mPlugin = mEsm->getIndex(); mPlugin = mEsm->getIndex();
mIsDeleted = false;
// Get the grid location
esm.getSubNameIs("INTV");
esm.getSubHeaderIs(8);
esm.getT<int>(mX);
esm.getT<int>(mY);
esm.getHNT(mFlags, "DATA");
if (esm.isNextSub("DELE")) bool hasLocation = false;
bool isLoaded = false;
while (!isLoaded && esm.hasMoreSubs())
{ {
esm.skipHSub(); esm.getSubName();
mIsDeleted = true; switch (esm.retSubName().val)
{
case ESM::FourCC<'I','N','T','V'>::value:
esm.getSubHeaderIs(8);
esm.getT<int>(mX);
esm.getT<int>(mY);
hasLocation = true;
break;
case ESM::FourCC<'D','A','T','A'>::value:
esm.getHT(mFlags);
break;
case ESM::FourCC<'D','E','L','E'>::value:
esm.skipHSub();
isDeleted = true;
break;
default:
esm.cacheSubName();
isLoaded = true;
break;
}
} }
// Store the file position if (!hasLocation)
esm.fail("Missing INTV subrecord");
mContext = esm.getContext(); mContext = esm.getContext();
// Skip these here. Load the actual data when the cell is loaded. // Skip the land data here. Load it when the cell is loaded.
if (esm.isNextSub("VNML")) while (esm.hasMoreSubs())
{
esm.skipHSubSize(12675);
mDataTypes |= DATA_VNML;
}
if (esm.isNextSub("VHGT"))
{
esm.skipHSubSize(4232);
mDataTypes |= DATA_VHGT;
}
if (esm.isNextSub("WNAM"))
{ {
esm.skipHSubSize(81); esm.getSubName();
mDataTypes |= DATA_WNAM; switch (esm.retSubName().val)
} {
if (esm.isNextSub("VCLR")) case ESM::FourCC<'V','N','M','L'>::value:
{ esm.skipHSub();
esm.skipHSubSize(12675); mDataTypes |= DATA_VNML;
mDataTypes |= DATA_VCLR; break;
} case ESM::FourCC<'V','H','G','T'>::value:
if (esm.isNextSub("VTEX")) esm.skipHSub();
{ mDataTypes |= DATA_VHGT;
esm.skipHSubSize(512); break;
mDataTypes |= DATA_VTEX; case ESM::FourCC<'W','N','A','M'>::value:
esm.skipHSub();
mDataTypes |= DATA_WNAM;
break;
case ESM::FourCC<'V','C','L','R'>::value:
esm.skipHSub();
mDataTypes |= DATA_VCLR;
break;
case ESM::FourCC<'V','T','E','X'>::value:
esm.skipHSub();
mDataTypes |= DATA_VTEX;
break;
default:
esm.fail("Unknown subrecord");
break;
}
} }
mDataLoaded = 0; mDataLoaded = 0;
mLandData = NULL; mLandData = NULL;
} }
void Land::save(ESMWriter &esm) const void Land::save(ESMWriter &esm, bool isDeleted) const
{ {
esm.startSubRecord("INTV"); esm.startSubRecord("INTV");
esm.writeT(mX); esm.writeT(mX);
@ -144,22 +164,17 @@ namespace ESM
esm.writeHNT("DATA", mFlags); esm.writeHNT("DATA", mFlags);
if (mIsDeleted) if (isDeleted)
{ {
esm.writeHNCString("DELE", ""); esm.writeHNCString("DELE", "");
} }
if (mLandData != NULL) if (mLandData)
{ {
mLandData->save(esm); mLandData->save(esm);
} }
} }
void Land::blank()
{
mIsDeleted = false;
}
void Land::loadData(int flags) void Land::loadData(int flags)
{ {
// Try to load only available data // Try to load only available data

@ -97,12 +97,10 @@ struct Land
LandData *mLandData; LandData *mLandData;
bool mIsDeleted; void load(ESMReader &esm, bool &isDeleted);
void save(ESMWriter &esm, bool isDeleted = false) const;
void load(ESMReader &esm); void blank() {}
void save(ESMWriter &esm) const;
void blank();
/** /**
* Actually loads data * Actually loads data

@ -6,29 +6,21 @@
namespace ESM namespace ESM
{ {
LevelledListBase::LevelledListBase() void LevelledListBase::load(ESMReader &esm, bool &isDeleted)
: mIsDeleted(false)
{}
void LevelledListBase::load(ESMReader &esm)
{ {
mIsDeleted = false; isDeleted = false;
bool hasName = false; bool hasName = false;
bool hasList = false;
while (esm.hasMoreSubs()) while (esm.hasMoreSubs())
{ {
esm.getSubName(); esm.getSubName();
uint32_t name = esm.retSubName().val; switch (esm.retSubName().val)
switch (name)
{ {
case ESM::FourCC<'N','A','M','E'>::value: case ESM::FourCC<'N','A','M','E'>::value:
mId = esm.getHString(); mId = esm.getHString();
hasName = true; hasName = true;
break; break;
case ESM::FourCC<'D','E','L','E'>::value:
esm.skipHSub();
mIsDeleted = true;
break;
case ESM::FourCC<'D','A','T','A'>::value: case ESM::FourCC<'D','A','T','A'>::value:
esm.getHT(mFlags); esm.getHT(mFlags);
break; break;
@ -53,12 +45,28 @@ namespace ESM
li.mId = esm.getHNString(mRecName); li.mId = esm.getHNString(mRecName);
esm.getHNT(li.mLevel, "INTV"); esm.getHNT(li.mLevel, "INTV");
} }
hasList = true;
break; break;
} }
case ESM::FourCC<'D','E','L','E'>::value:
esm.skipHSub();
isDeleted = true;
break;
default: default:
mList.clear(); {
esm.skipRecord(); if (!hasList)
{
// Original engine ignores rest of the record, even if there are items following
mList.clear();
esm.skipRecord();
}
else
{
esm.fail("Unknown subrecord");
}
break; break;
}
} }
} }
@ -66,11 +74,11 @@ namespace ESM
esm.fail("Missing NAME subrecord"); esm.fail("Missing NAME subrecord");
} }
void LevelledListBase::save(ESMWriter &esm) const void LevelledListBase::save(ESMWriter &esm, bool isDeleted) const
{ {
esm.writeHNCString("NAME", mId); esm.writeHNCString("NAME", mId);
if (mIsDeleted) if (isDeleted)
{ {
esm.writeHNCString("DELE", ""); esm.writeHNCString("DELE", "");
return; return;
@ -92,7 +100,6 @@ namespace ESM
mFlags = 0; mFlags = 0;
mChanceNone = 0; mChanceNone = 0;
mList.clear(); mList.clear();
mIsDeleted = false;
} }
unsigned int CreatureLevList::sRecordId = REC_LEVC; unsigned int CreatureLevList::sRecordId = REC_LEVC;

@ -36,12 +36,8 @@ struct LevelledListBase
std::vector<LevelItem> mList; std::vector<LevelItem> mList;
bool mIsDeleted; void load(ESMReader &esm, bool &isDeleted);
void save(ESMWriter &esm, bool isDeleted = false) const;
LevelledListBase();
void load(ESMReader &esm);
void save(ESMWriter &esm) const;
void blank(); void blank();
///< Set record to default state (does not touch the ID). ///< Set record to default state (does not touch the ID).

@ -8,30 +8,21 @@ namespace ESM
{ {
unsigned int Light::sRecordId = REC_LIGH; unsigned int Light::sRecordId = REC_LIGH;
Light::Light() void Light::load(ESMReader &esm, bool &isDeleted)
: mIsDeleted(false)
{}
void Light::load(ESMReader &esm)
{ {
mIsDeleted = false; isDeleted = false;
bool hasName = false; bool hasName = false;
bool hasData = false; bool hasData = false;
while (esm.hasMoreSubs()) while (esm.hasMoreSubs())
{ {
esm.getSubName(); esm.getSubName();
uint32_t name = esm.retSubName().val; switch (esm.retSubName().val)
switch (name)
{ {
case ESM::FourCC<'N','A','M','E'>::value: case ESM::FourCC<'N','A','M','E'>::value:
mId = esm.getHString(); mId = esm.getHString();
hasName = true; hasName = true;
break; break;
case ESM::FourCC<'D','E','L','E'>::value:
esm.skipHSub();
mIsDeleted = true;
break;
case ESM::FourCC<'M','O','D','L'>::value: case ESM::FourCC<'M','O','D','L'>::value:
mModel = esm.getHString(); mModel = esm.getHString();
break; break;
@ -51,6 +42,10 @@ namespace ESM
case ESM::FourCC<'S','N','A','M'>::value: case ESM::FourCC<'S','N','A','M'>::value:
mSound = esm.getHString(); mSound = esm.getHString();
break; break;
case ESM::FourCC<'D','E','L','E'>::value:
esm.skipHSub();
isDeleted = true;
break;
default: default:
esm.fail("Unknown subrecord"); esm.fail("Unknown subrecord");
break; break;
@ -59,14 +54,14 @@ namespace ESM
if (!hasName) if (!hasName)
esm.fail("Missing NAME subrecord"); esm.fail("Missing NAME subrecord");
if (!hasData && !mIsDeleted) if (!hasData && !isDeleted)
esm.fail("Missing LHDT subrecord"); esm.fail("Missing LHDT subrecord");
} }
void Light::save(ESMWriter &esm) const void Light::save(ESMWriter &esm, bool isDeleted) const
{ {
esm.writeHNCString("NAME", mId); esm.writeHNCString("NAME", mId);
if (mIsDeleted) if (isDeleted)
{ {
esm.writeHNCString("DELE", ""); esm.writeHNCString("DELE", "");
return; return;
@ -93,6 +88,5 @@ namespace ESM
mModel.clear(); mModel.clear();
mIcon.clear(); mIcon.clear();
mName.clear(); mName.clear();
mIsDeleted = false;
} }
} }

@ -47,12 +47,8 @@ struct Light
std::string mSound, mScript, mModel, mIcon, mName, mId; std::string mSound, mScript, mModel, mIcon, mName, mId;
bool mIsDeleted; void load(ESMReader &esm, bool &isDeleted);
void save(ESMWriter &esm, bool isDeleted = false) const;
Light();
void load(ESMReader &esm);
void save(ESMWriter &esm) const;
void blank(); void blank();
///< Set record to default state (does not touch the ID). ///< Set record to default state (does not touch the ID).

@ -8,30 +8,21 @@ namespace ESM
{ {
unsigned int Lockpick::sRecordId = REC_LOCK; unsigned int Lockpick::sRecordId = REC_LOCK;
Lockpick::Lockpick() void Lockpick::load(ESMReader &esm, bool &isDeleted)
: mIsDeleted(false)
{}
void Lockpick::load(ESMReader &esm)
{ {
mIsDeleted = false; isDeleted = false;
bool hasName = false; bool hasName = false;
bool hasData = false; bool hasData = false;
while (esm.hasMoreSubs()) while (esm.hasMoreSubs())
{ {
esm.getSubName(); esm.getSubName();
uint32_t name = esm.retSubName().val; switch (esm.retSubName().val)
switch (name)
{ {
case ESM::FourCC<'N','A','M','E'>::value: case ESM::FourCC<'N','A','M','E'>::value:
mId = esm.getHString(); mId = esm.getHString();
hasName = true; hasName = true;
break; break;
case ESM::FourCC<'D','E','L','E'>::value:
esm.skipHSub();
mIsDeleted = true;
break;
case ESM::FourCC<'M','O','D','L'>::value: case ESM::FourCC<'M','O','D','L'>::value:
mModel = esm.getHString(); mModel = esm.getHString();
break; break;
@ -48,6 +39,10 @@ namespace ESM
case ESM::FourCC<'I','T','E','X'>::value: case ESM::FourCC<'I','T','E','X'>::value:
mIcon = esm.getHString(); mIcon = esm.getHString();
break; break;
case ESM::FourCC<'D','E','L','E'>::value:
esm.skipHSub();
isDeleted = true;
break;
default: default:
esm.fail("Unknown subrecord"); esm.fail("Unknown subrecord");
break; break;
@ -56,15 +51,15 @@ namespace ESM
if (!hasName) if (!hasName)
esm.fail("Missing NAME subrecord"); esm.fail("Missing NAME subrecord");
if (!hasData && !mIsDeleted) if (!hasData && !isDeleted)
esm.fail("Missing LKDT subrecord"); esm.fail("Missing LKDT subrecord");
} }
void Lockpick::save(ESMWriter &esm) const void Lockpick::save(ESMWriter &esm, bool isDeleted) const
{ {
esm.writeHNCString("NAME", mId); esm.writeHNCString("NAME", mId);
if (mIsDeleted) if (isDeleted)
{ {
esm.writeHNCString("DELE", ""); esm.writeHNCString("DELE", "");
return; return;
@ -88,6 +83,5 @@ namespace ESM
mModel.clear(); mModel.clear();
mIcon.clear(); mIcon.clear();
mScript.clear(); mScript.clear();
mIsDeleted = false;
} }
} }

@ -27,12 +27,8 @@ struct Lockpick
Data mData; Data mData;
std::string mId, mName, mModel, mIcon, mScript; std::string mId, mName, mModel, mIcon, mScript;
bool mIsDeleted; void load(ESMReader &esm, bool &isDeleted);
void save(ESMWriter &esm, bool isDeleted = false) const;
Lockpick();
void load(ESMReader &esm);
void save(ESMWriter &esm) const;
void blank(); void blank();
///< Set record to default state (does not touch the ID). ///< Set record to default state (does not touch the ID).

@ -8,30 +8,21 @@ namespace ESM
{ {
unsigned int LandTexture::sRecordId = REC_LTEX; unsigned int LandTexture::sRecordId = REC_LTEX;
LandTexture::LandTexture() void LandTexture::load(ESMReader &esm, bool &isDeleted)
: mIsDeleted(false)
{}
void LandTexture::load(ESMReader &esm)
{ {
mIsDeleted = false; isDeleted = false;
bool hasName = false; bool hasName = false;
bool hasIndex = false; bool hasIndex = false;
while (esm.hasMoreSubs()) while (esm.hasMoreSubs())
{ {
esm.getSubName(); esm.getSubName();
uint32_t name = esm.retSubName().val; switch (esm.retSubName().val)
switch (name)
{ {
case ESM::FourCC<'N','A','M','E'>::value: case ESM::FourCC<'N','A','M','E'>::value:
mId = esm.getHString(); mId = esm.getHString();
hasName = true; hasName = true;
break; break;
case ESM::FourCC<'D','E','L','E'>::value:
esm.skipHSub();
mIsDeleted = true;
break;
case ESM::FourCC<'I','N','T','V'>::value: case ESM::FourCC<'I','N','T','V'>::value:
esm.getHT(mIndex); esm.getHT(mIndex);
hasIndex = true; hasIndex = true;
@ -39,6 +30,10 @@ namespace ESM
case ESM::FourCC<'D','A','T','A'>::value: case ESM::FourCC<'D','A','T','A'>::value:
mTexture = esm.getHString(); mTexture = esm.getHString();
break; break;
case ESM::FourCC<'D','E','L','E'>::value:
esm.skipHSub();
isDeleted = true;
break;
default: default:
esm.fail("Unknown subrecord"); esm.fail("Unknown subrecord");
break; break;
@ -50,9 +45,9 @@ namespace ESM
if (!hasIndex) if (!hasIndex)
esm.fail("Missing INTV subrecord"); esm.fail("Missing INTV subrecord");
} }
void LandTexture::save(ESMWriter &esm) const void LandTexture::save(ESMWriter &esm, bool isDeleted) const
{ {
if (mIsDeleted) if (isDeleted)
{ {
esm.writeHNCString("DELE", ""); esm.writeHNCString("DELE", "");
} }
@ -66,6 +61,5 @@ namespace ESM
{ {
mTexture.clear(); mTexture.clear();
mIndex = -1; mIndex = -1;
mIsDeleted = false;
} }
} }

@ -34,12 +34,8 @@ struct LandTexture
std::string mId, mTexture; std::string mId, mTexture;
int mIndex; int mIndex;
bool mIsDeleted; void load(ESMReader &esm, bool &isDeleted);
void save(ESMWriter &esm, bool isDeleted = false) const;
LandTexture();
void load(ESMReader &esm);
void save(ESMWriter &esm) const;
void blank(); void blank();
///< Set record to default state (does not touch the ID). ///< Set record to default state (does not touch the ID).

@ -189,8 +189,10 @@ namespace ESM
{ {
unsigned int MagicEffect::sRecordId = REC_MGEF; unsigned int MagicEffect::sRecordId = REC_MGEF;
void MagicEffect::load(ESMReader &esm) void MagicEffect::load(ESMReader &esm, bool &isDeleted)
{ {
isDeleted = false; // MagicEffect record can't be deleted now (may be changed in the future)
esm.getHNT(mIndex, "INDX"); esm.getHNT(mIndex, "INDX");
mId = indexToId (mIndex); mId = indexToId (mIndex);
@ -209,8 +211,7 @@ void MagicEffect::load(ESMReader &esm)
while (esm.hasMoreSubs()) while (esm.hasMoreSubs())
{ {
esm.getSubName(); esm.getSubName();
uint32_t name = esm.retSubName().val; switch (esm.retSubName().val)
switch (name)
{ {
case ESM::FourCC<'I','T','E','X'>::value: case ESM::FourCC<'I','T','E','X'>::value:
mIcon = esm.getHString(); mIcon = esm.getHString();
@ -250,7 +251,7 @@ void MagicEffect::load(ESMReader &esm)
} }
} }
} }
void MagicEffect::save(ESMWriter &esm) const void MagicEffect::save(ESMWriter &esm, bool /*isDeleted*/) const
{ {
esm.writeHNT("INDX", mIndex); esm.writeHNT("INDX", mIndex);

@ -96,8 +96,8 @@ struct MagicEffect
// sMagicCreature04ID/05ID. // sMagicCreature04ID/05ID.
int mIndex; int mIndex;
void load(ESMReader &esm); void load(ESMReader &esm, bool &isDeleted);
void save(ESMWriter &esm) const; void save(ESMWriter &esm, bool isDeleted = false) const;
/// Set record to default state (does not touch the ID/index). /// Set record to default state (does not touch the ID/index).
void blank(); void blank();

@ -8,30 +8,21 @@ namespace ESM
{ {
unsigned int Miscellaneous::sRecordId = REC_MISC; unsigned int Miscellaneous::sRecordId = REC_MISC;
Miscellaneous::Miscellaneous() void Miscellaneous::load(ESMReader &esm, bool &isDeleted)
: mIsDeleted(false)
{}
void Miscellaneous::load(ESMReader &esm)
{ {
mIsDeleted = false; isDeleted = false;
bool hasName = false; bool hasName = false;
bool hasData = false; bool hasData = false;
while (esm.hasMoreSubs()) while (esm.hasMoreSubs())
{ {
esm.getSubName(); esm.getSubName();
uint32_t name = esm.retSubName().val; switch (esm.retSubName().val)
switch (name)
{ {
case ESM::FourCC<'N','A','M','E'>::value: case ESM::FourCC<'N','A','M','E'>::value:
mId = esm.getHString(); mId = esm.getHString();
hasName = true; hasName = true;
break; break;
case ESM::FourCC<'D','E','L','E'>::value:
esm.skipHSub();
mIsDeleted = true;
break;
case ESM::FourCC<'M','O','D','L'>::value: case ESM::FourCC<'M','O','D','L'>::value:
mModel = esm.getHString(); mModel = esm.getHString();
break; break;
@ -48,6 +39,10 @@ namespace ESM
case ESM::FourCC<'I','T','E','X'>::value: case ESM::FourCC<'I','T','E','X'>::value:
mIcon = esm.getHString(); mIcon = esm.getHString();
break; break;
case ESM::FourCC<'D','E','L','E'>::value:
esm.skipHSub();
isDeleted = true;
break;
default: default:
esm.fail("Unknown subrecord"); esm.fail("Unknown subrecord");
break; break;
@ -56,15 +51,15 @@ namespace ESM
if (!hasName) if (!hasName)
esm.fail("Missing NAME subrecord"); esm.fail("Missing NAME subrecord");
if (!hasData && !mIsDeleted) if (!hasData && !isDeleted)
esm.fail("Missing MCDT subrecord"); esm.fail("Missing MCDT subrecord");
} }
void Miscellaneous::save(ESMWriter &esm) const void Miscellaneous::save(ESMWriter &esm, bool isDeleted) const
{ {
esm.writeHNCString("NAME", mId); esm.writeHNCString("NAME", mId);
if (mIsDeleted) if (isDeleted)
{ {
esm.writeHNCString("DELE", ""); esm.writeHNCString("DELE", "");
return; return;
@ -86,6 +81,5 @@ namespace ESM
mModel.clear(); mModel.clear();
mIcon.clear(); mIcon.clear();
mScript.clear(); mScript.clear();
mIsDeleted = false;
} }
} }

@ -32,12 +32,8 @@ struct Miscellaneous
std::string mId, mName, mModel, mIcon, mScript; std::string mId, mName, mModel, mIcon, mScript;
bool mIsDeleted; void load(ESMReader &esm, bool &isDeleted);
void save(ESMWriter &esm, bool isDeleted = false) const;
Miscellaneous();
void load(ESMReader &esm);
void save(ESMWriter &esm) const;
void blank(); void blank();
///< Set record to default state (does not touch the ID). ///< Set record to default state (does not touch the ID).

@ -8,15 +8,10 @@ namespace ESM
{ {
unsigned int NPC::sRecordId = REC_NPC_; unsigned int NPC::sRecordId = REC_NPC_;
NPC::NPC() void NPC::load(ESMReader &esm, bool &isDeleted)
: mFlags(0),
mHasAI(false),
mIsDeleted(false)
{}
void NPC::load(ESMReader &esm)
{ {
mIsDeleted = false; isDeleted = false;
mPersistent = (esm.getRecordFlags() & 0x0400) != 0; mPersistent = (esm.getRecordFlags() & 0x0400) != 0;
mSpells.mList.clear(); mSpells.mList.clear();
@ -31,17 +26,12 @@ namespace ESM
while (esm.hasMoreSubs()) while (esm.hasMoreSubs())
{ {
esm.getSubName(); esm.getSubName();
uint32_t name = esm.retSubName().val; switch (esm.retSubName().val)
switch (name)
{ {
case ESM::FourCC<'N','A','M','E'>::value: case ESM::FourCC<'N','A','M','E'>::value:
mId = esm.getHString(); mId = esm.getHString();
hasName = true; hasName = true;
break; break;
case ESM::FourCC<'D','E','L','E'>::value:
esm.skipHSub();
mIsDeleted = true;
break;
case ESM::FourCC<'M','O','D','L'>::value: case ESM::FourCC<'M','O','D','L'>::value:
mModel = esm.getHString(); mModel = esm.getHString();
break; break;
@ -108,6 +98,10 @@ namespace ESM
case AI_CNDT: case AI_CNDT:
mAiPackage.add(esm); mAiPackage.add(esm);
break; break;
case ESM::FourCC<'D','E','L','E'>::value:
esm.skipHSub();
isDeleted = true;
break;
default: default:
esm.fail("Unknown subrecord"); esm.fail("Unknown subrecord");
break; break;
@ -116,16 +110,16 @@ namespace ESM
if (!hasName) if (!hasName)
esm.fail("Missing NAME subrecord"); esm.fail("Missing NAME subrecord");
if (!hasNpdt && !mIsDeleted) if (!hasNpdt && !isDeleted)
esm.fail("Missing NPDT subrecord"); esm.fail("Missing NPDT subrecord");
if (!hasFlags && !mIsDeleted) if (!hasFlags && !isDeleted)
esm.fail("Missing FLAG subrecord"); esm.fail("Missing FLAG subrecord");
} }
void NPC::save(ESMWriter &esm) const void NPC::save(ESMWriter &esm, bool isDeleted) const
{ {
esm.writeHNCString("NAME", mId); esm.writeHNCString("NAME", mId);
if (mIsDeleted) if (isDeleted)
{ {
esm.writeHNCString("DELE", ""); esm.writeHNCString("DELE", "");
return; return;
@ -206,7 +200,6 @@ namespace ESM
mScript.clear(); mScript.clear();
mHair.clear(); mHair.clear();
mHead.clear(); mHead.clear();
mIsDeleted = false;
} }
int NPC::getFactionRank() const int NPC::getFactionRank() const

@ -130,12 +130,8 @@ struct NPC
// body parts // body parts
std::string mHair, mHead; std::string mHair, mHead;
bool mIsDeleted; void load(ESMReader &esm, bool &isDeleted);
void save(ESMWriter &esm, bool isDeleted = false) const;
NPC();
void load(ESMReader &esm);
void save(ESMWriter &esm) const;
bool isMale() const; bool isMale() const;

@ -32,12 +32,10 @@ namespace ESM
{ {
} }
Pathgrid::Pathgrid() void Pathgrid::load(ESMReader &esm, bool &isDeleted)
: mIsDeleted(false)
{}
void Pathgrid::load(ESMReader &esm)
{ {
isDeleted = false;
mPoints.clear(); mPoints.clear();
mEdges.clear(); mEdges.clear();
@ -49,8 +47,7 @@ namespace ESM
while (esm.hasMoreSubs()) while (esm.hasMoreSubs())
{ {
esm.getSubName(); esm.getSubName();
uint32_t name = esm.retSubName().val; switch (esm.retSubName().val)
switch (name)
{ {
case ESM::FourCC<'D','A','T','A'>::value: case ESM::FourCC<'D','A','T','A'>::value:
esm.getHT(mData, 12); esm.getHT(mData, 12);
@ -118,7 +115,7 @@ namespace ESM
} }
case ESM::FourCC<'D','E','L','E'>::value: case ESM::FourCC<'D','E','L','E'>::value:
esm.skipHSub(); esm.skipHSub();
mIsDeleted = true; isDeleted = true;
break; break;
default: default:
esm.fail("Unknown subrecord"); esm.fail("Unknown subrecord");
@ -132,12 +129,12 @@ namespace ESM
esm.fail("Missing NAME subrecord"); esm.fail("Missing NAME subrecord");
} }
void Pathgrid::save(ESMWriter &esm) const void Pathgrid::save(ESMWriter &esm, bool isDeleted) const
{ {
esm.writeHNT("DATA", mData, 12); esm.writeHNT("DATA", mData, 12);
esm.writeHNCString("NAME", mCell); esm.writeHNCString("NAME", mCell);
if (mIsDeleted) if (isDeleted)
{ {
esm.writeHNCString("DELE", ""); esm.writeHNCString("DELE", "");
return; return;
@ -173,6 +170,5 @@ namespace ESM
mData.mS2 = 0; mData.mS2 = 0;
mPoints.clear(); mPoints.clear();
mEdges.clear(); mEdges.clear();
mIsDeleted = false;
} }
} }

@ -53,12 +53,8 @@ struct Pathgrid
typedef std::vector<Edge> EdgeList; typedef std::vector<Edge> EdgeList;
EdgeList mEdges; EdgeList mEdges;
bool mIsDeleted; void load(ESMReader &esm, bool &isDeleted);
void save(ESMWriter &esm, bool isDeleted = false) const;
Pathgrid();
void load(ESMReader &esm);
void save(ESMWriter &esm) const;
void blank(); void blank();
}; };

@ -8,30 +8,21 @@ namespace ESM
{ {
unsigned int Probe::sRecordId = REC_PROB; unsigned int Probe::sRecordId = REC_PROB;
Probe::Probe() void Probe::load(ESMReader &esm, bool &isDeleted)
: mIsDeleted(false)
{}
void Probe::load(ESMReader &esm)
{ {
mIsDeleted = false; isDeleted = false;
bool hasName = false; bool hasName = false;
bool hasData = false; bool hasData = false;
while (esm.hasMoreSubs()) while (esm.hasMoreSubs())
{ {
esm.getSubName(); esm.getSubName();
uint32_t name = esm.retSubName().val; switch (esm.retSubName().val)
switch (name)
{ {
case ESM::FourCC<'N','A','M','E'>::value: case ESM::FourCC<'N','A','M','E'>::value:
mId = esm.getHString(); mId = esm.getHString();
hasName = true; hasName = true;
break; break;
case ESM::FourCC<'D','E','L','E'>::value:
esm.skipHSub();
mIsDeleted = true;
break;
case ESM::FourCC<'M','O','D','L'>::value: case ESM::FourCC<'M','O','D','L'>::value:
mModel = esm.getHString(); mModel = esm.getHString();
break; break;
@ -48,6 +39,10 @@ namespace ESM
case ESM::FourCC<'I','T','E','X'>::value: case ESM::FourCC<'I','T','E','X'>::value:
mIcon = esm.getHString(); mIcon = esm.getHString();
break; break;
case ESM::FourCC<'D','E','L','E'>::value:
esm.skipHSub();
isDeleted = true;
break;
default: default:
esm.fail("Unknown subrecord"); esm.fail("Unknown subrecord");
break; break;
@ -56,15 +51,15 @@ namespace ESM
if (!hasName) if (!hasName)
esm.fail("Missing NAME subrecord"); esm.fail("Missing NAME subrecord");
if (!hasData && !mIsDeleted) if (!hasData && !isDeleted)
esm.fail("Missing PBDT subrecord"); esm.fail("Missing PBDT subrecord");
} }
void Probe::save(ESMWriter &esm) const void Probe::save(ESMWriter &esm, bool isDeleted) const
{ {
esm.writeHNCString("NAME", mId); esm.writeHNCString("NAME", mId);
if (mIsDeleted) if (isDeleted)
{ {
esm.writeHNCString("DELE", ""); esm.writeHNCString("DELE", "");
return; return;
@ -88,6 +83,5 @@ namespace ESM
mModel.clear(); mModel.clear();
mIcon.clear(); mIcon.clear();
mScript.clear(); mScript.clear();
mIsDeleted = false;
} }
} }

@ -27,12 +27,8 @@ struct Probe
Data mData; Data mData;
std::string mId, mName, mModel, mIcon, mScript; std::string mId, mName, mModel, mIcon, mScript;
bool mIsDeleted; void load(ESMReader &esm, bool &isDeleted);
void save(ESMWriter &esm, bool isDeleted = false) const;
Probe();
void load(ESMReader &esm);
void save(ESMWriter &esm) const;
void blank(); void blank();
///< Set record to default state (does not touch the ID). ///< Set record to default state (does not touch the ID).

@ -8,10 +8,6 @@ namespace ESM
{ {
unsigned int Race::sRecordId = REC_RACE; unsigned int Race::sRecordId = REC_RACE;
Race::Race()
: mIsDeleted(false)
{}
int Race::MaleFemale::getValue (bool male) const int Race::MaleFemale::getValue (bool male) const
{ {
return male ? mMale : mFemale; return male ? mMale : mFemale;
@ -22,27 +18,23 @@ namespace ESM
return static_cast<int>(male ? mMale : mFemale); return static_cast<int>(male ? mMale : mFemale);
} }
void Race::load(ESMReader &esm) void Race::load(ESMReader &esm, bool &isDeleted)
{ {
isDeleted = false;
mPowers.mList.clear(); mPowers.mList.clear();
mIsDeleted = false;
bool hasName = false; bool hasName = false;
bool hasData = false; bool hasData = false;
while (esm.hasMoreSubs()) while (esm.hasMoreSubs())
{ {
esm.getSubName(); esm.getSubName();
uint32_t name = esm.retSubName().val; switch (esm.retSubName().val)
switch (name)
{ {
case ESM::FourCC<'N','A','M','E'>::value: case ESM::FourCC<'N','A','M','E'>::value:
mId = esm.getHString(); mId = esm.getHString();
hasName = true; hasName = true;
break; break;
case ESM::FourCC<'D','E','L','E'>::value:
esm.skipHSub();
mIsDeleted = true;
break;
case ESM::FourCC<'F','N','A','M'>::value: case ESM::FourCC<'F','N','A','M'>::value:
mName = esm.getHString(); mName = esm.getHString();
break; break;
@ -56,6 +48,10 @@ namespace ESM
case ESM::FourCC<'N','P','C','S'>::value: case ESM::FourCC<'N','P','C','S'>::value:
mPowers.add(esm); mPowers.add(esm);
break; break;
case ESM::FourCC<'D','E','L','E'>::value:
esm.skipHSub();
isDeleted = true;
break;
default: default:
esm.fail("Unknown subrecord"); esm.fail("Unknown subrecord");
} }
@ -63,14 +59,14 @@ namespace ESM
if (!hasName) if (!hasName)
esm.fail("Missing NAME subrecord"); esm.fail("Missing NAME subrecord");
if (!hasData && !mIsDeleted) if (!hasData && !isDeleted)
esm.fail("Missing RADT subrecord"); esm.fail("Missing RADT subrecord");
} }
void Race::save(ESMWriter &esm) const void Race::save(ESMWriter &esm, bool isDeleted) const
{ {
esm.writeHNCString("NAME", mId); esm.writeHNCString("NAME", mId);
if (mIsDeleted) if (isDeleted)
{ {
esm.writeHNCString("DELE", ""); esm.writeHNCString("DELE", "");
return; return;

@ -68,12 +68,8 @@ struct Race
std::string mId, mName, mDescription; std::string mId, mName, mDescription;
SpellList mPowers; SpellList mPowers;
bool mIsDeleted; void load(ESMReader &esm, bool &isDeleted);
void save(ESMWriter &esm, bool isDeleted = false) const;
Race();
void load(ESMReader &esm);
void save(ESMWriter &esm) const;
void blank(); void blank();
///< Set record to default state (does not touch the ID/index). ///< Set record to default state (does not touch the ID/index).

@ -8,29 +8,20 @@ namespace ESM
{ {
unsigned int Region::sRecordId = REC_REGN; unsigned int Region::sRecordId = REC_REGN;
Region::Region() void Region::load(ESMReader &esm, bool &isDeleted)
: mMapColor(0),
mIsDeleted(false)
{}
void Region::load(ESMReader &esm)
{ {
mIsDeleted = false; isDeleted = false;
bool hasName = false; bool hasName = false;
while (esm.hasMoreSubs()) while (esm.hasMoreSubs())
{ {
esm.getSubName(); esm.getSubName();
uint32_t name = esm.retSubName().val; switch (esm.retSubName().val)
switch (name)
{ {
case ESM::FourCC<'N','A','M','E'>::value: case ESM::FourCC<'N','A','M','E'>::value:
mId = esm.getHString(); mId = esm.getHString();
hasName = true; hasName = true;
break; break;
case ESM::FourCC<'D','E','L','E'>::value:
esm.skipHSub();
mIsDeleted = true;
break; break;
case ESM::FourCC<'F','N','A','M'>::value: case ESM::FourCC<'F','N','A','M'>::value:
mName = esm.getHString(); mName = esm.getHString();
@ -75,6 +66,9 @@ namespace ESM
esm.getHT(sr, 33); esm.getHT(sr, 33);
mSoundList.push_back(sr); mSoundList.push_back(sr);
break; break;
case ESM::FourCC<'D','E','L','E'>::value:
esm.skipHSub();
isDeleted = true;
default: default:
esm.fail("Unknown subrecord"); esm.fail("Unknown subrecord");
break; break;
@ -85,9 +79,9 @@ namespace ESM
esm.fail("Missing NAME subrecord"); esm.fail("Missing NAME subrecord");
} }
void Region::save(ESMWriter &esm) const void Region::save(ESMWriter &esm, bool isDeleted) const
{ {
if (mIsDeleted) if (isDeleted)
{ {
esm.writeHNCString("DELE", ""); esm.writeHNCString("DELE", "");
} }
@ -121,7 +115,5 @@ namespace ESM
mName.clear(); mName.clear();
mSleepList.clear(); mSleepList.clear();
mSoundList.clear(); mSoundList.clear();
mIsDeleted = false;
} }
} }

@ -51,12 +51,8 @@ struct Region
std::vector<SoundRef> mSoundList; std::vector<SoundRef> mSoundList;
bool mIsDeleted; void load(ESMReader &esm, bool &isDeleted);
void save(ESMWriter &esm, bool isDeleted = false) const;
Region();
void load(ESMReader &esm);
void save(ESMWriter &esm) const;
void blank(); void blank();
///< Set record to default state (does not touch the ID/index). ///< Set record to default state (does not touch the ID/index).

@ -8,30 +8,21 @@ namespace ESM
{ {
unsigned int Repair::sRecordId = REC_REPA; unsigned int Repair::sRecordId = REC_REPA;
Repair::Repair() void Repair::load(ESMReader &esm, bool &isDeleted)
: mIsDeleted(false)
{}
void Repair::load(ESMReader &esm)
{ {
mIsDeleted = false; isDeleted = false;
bool hasName = false; bool hasName = false;
bool hasData = false; bool hasData = false;
while (esm.hasMoreSubs()) while (esm.hasMoreSubs())
{ {
esm.getSubName(); esm.getSubName();
uint32_t name = esm.retSubName().val; switch (esm.retSubName().val)
switch (name)
{ {
case ESM::FourCC<'N','A','M','E'>::value: case ESM::FourCC<'N','A','M','E'>::value:
mId = esm.getHString(); mId = esm.getHString();
hasName = true; hasName = true;
break; break;
case ESM::FourCC<'D','E','L','E'>::value:
esm.skipHSub();
mIsDeleted = true;
break;
case ESM::FourCC<'M','O','D','L'>::value: case ESM::FourCC<'M','O','D','L'>::value:
mModel = esm.getHString(); mModel = esm.getHString();
break; break;
@ -48,6 +39,10 @@ namespace ESM
case ESM::FourCC<'I','T','E','X'>::value: case ESM::FourCC<'I','T','E','X'>::value:
mIcon = esm.getHString(); mIcon = esm.getHString();
break; break;
case ESM::FourCC<'D','E','L','E'>::value:
esm.skipHSub();
isDeleted = true;
break;
default: default:
esm.fail("Unknown subrecord"); esm.fail("Unknown subrecord");
break; break;
@ -56,15 +51,15 @@ namespace ESM
if (!hasName) if (!hasName)
esm.fail("Missing NAME subrecord"); esm.fail("Missing NAME subrecord");
if (!hasData && !mIsDeleted) if (!hasData && !isDeleted)
esm.fail("Missing RIDT subrecord"); esm.fail("Missing RIDT subrecord");
} }
void Repair::save(ESMWriter &esm) const void Repair::save(ESMWriter &esm, bool isDeleted) const
{ {
esm.writeHNCString("NAME", mId); esm.writeHNCString("NAME", mId);
if (mIsDeleted) if (isDeleted)
{ {
esm.writeHNCString("DELE", ""); esm.writeHNCString("DELE", "");
return; return;
@ -88,6 +83,5 @@ namespace ESM
mModel.clear(); mModel.clear();
mIcon.clear(); mIcon.clear();
mScript.clear(); mScript.clear();
mIsDeleted = false;
} }
} }

@ -27,12 +27,8 @@ struct Repair
Data mData; Data mData;
std::string mId, mName, mModel, mIcon, mScript; std::string mId, mName, mModel, mIcon, mScript;
bool mIsDeleted; void load(ESMReader &esm, bool &isDeleted);
void save(ESMWriter &esm, bool isDeleted = false) const;
Repair();
void load(ESMReader &esm);
void save(ESMWriter &esm) const;
void blank(); void blank();
///< Set record to default state (does not touch the ID). ///< Set record to default state (does not touch the ID).

@ -10,10 +10,6 @@ namespace ESM
{ {
unsigned int Script::sRecordId = REC_SCPT; unsigned int Script::sRecordId = REC_SCPT;
Script::Script()
: mIsDeleted(false)
{}
void Script::loadSCVR(ESMReader &esm) void Script::loadSCVR(ESMReader &esm)
{ {
int s = mData.mStringTableSize; int s = mData.mStringTableSize;
@ -61,17 +57,17 @@ namespace ESM
} }
} }
void Script::load(ESMReader &esm) void Script::load(ESMReader &esm, bool &isDeleted)
{ {
isDeleted = false;
mVarNames.clear(); mVarNames.clear();
mIsDeleted = false;
bool hasHeader = false; bool hasHeader = false;
while (esm.hasMoreSubs()) while (esm.hasMoreSubs())
{ {
esm.getSubName(); esm.getSubName();
uint32_t name = esm.retSubName().val; switch (esm.retSubName().val)
switch (name)
{ {
case ESM::FourCC<'S','C','H','D'>::value: case ESM::FourCC<'S','C','H','D'>::value:
SCHD data; SCHD data;
@ -80,10 +76,6 @@ namespace ESM
mId = data.mName.toString(); mId = data.mName.toString();
hasHeader = true; hasHeader = true;
break; break;
case ESM::FourCC<'D','E','L','E'>::value:
esm.skipHSub();
mIsDeleted = true;
break;
case ESM::FourCC<'S','C','V','R'>::value: case ESM::FourCC<'S','C','V','R'>::value:
// list of local variables // list of local variables
loadSCVR(esm); loadSCVR(esm);
@ -96,6 +88,10 @@ namespace ESM
case ESM::FourCC<'S','C','T','X'>::value: case ESM::FourCC<'S','C','T','X'>::value:
mScriptText = esm.getHString(); mScriptText = esm.getHString();
break; break;
case ESM::FourCC<'D','E','L','E'>::value:
esm.skipHSub();
isDeleted = true;
break;
default: default:
esm.fail("Unknown subrecord"); esm.fail("Unknown subrecord");
break; break;
@ -106,7 +102,7 @@ namespace ESM
esm.fail("Missing SCHD subrecord"); esm.fail("Missing SCHD subrecord");
} }
void Script::save(ESMWriter &esm) const void Script::save(ESMWriter &esm, bool isDeleted) const
{ {
std::string varNameString; std::string varNameString;
if (!mVarNames.empty()) if (!mVarNames.empty())
@ -121,7 +117,7 @@ namespace ESM
esm.writeHNT("SCHD", data, 52); esm.writeHNT("SCHD", data, 52);
if (mIsDeleted) if (isDeleted)
{ {
esm.writeHNCString("DELE", ""); esm.writeHNCString("DELE", "");
} }
@ -156,8 +152,6 @@ namespace ESM
mScriptText = "Begin \"" + mId + "\"\n\nEnd " + mId + "\n"; mScriptText = "Begin \"" + mId + "\"\n\nEnd " + mId + "\n";
else else
mScriptText = "Begin " + mId + "\n\nEnd " + mId + "\n"; mScriptText = "Begin " + mId + "\n\nEnd " + mId + "\n";
mIsDeleted = false;
} }
} }

@ -50,12 +50,8 @@ public:
/// Script source code /// Script source code
std::string mScriptText; std::string mScriptText;
bool mIsDeleted; void load(ESMReader &esm, bool &isDeleted);
void save(ESMWriter &esm, bool isDeleted = false) const;
Script();
void load(ESMReader &esm);
void save(ESMWriter &esm) const;
void blank(); void blank();
///< Set record to default state (does not touch the ID/index). ///< Set record to default state (does not touch the ID/index).

@ -129,15 +129,16 @@ namespace ESM
unsigned int Skill::sRecordId = REC_SKIL; unsigned int Skill::sRecordId = REC_SKIL;
void Skill::load(ESMReader &esm) void Skill::load(ESMReader &esm, bool &isDeleted)
{ {
isDeleted = false; // Skill record can't be deleted now (may be changed in the future)
bool hasIndex = false; bool hasIndex = false;
bool hasData = false; bool hasData = false;
while (esm.hasMoreSubs()) while (esm.hasMoreSubs())
{ {
esm.getSubName(); esm.getSubName();
uint32_t name = esm.retSubName().val; switch (esm.retSubName().val)
switch (name)
{ {
case ESM::FourCC<'I','N','D','X'>::value: case ESM::FourCC<'I','N','D','X'>::value:
esm.getHT(mIndex); esm.getHT(mIndex);
@ -164,7 +165,7 @@ namespace ESM
mId = indexToId (mIndex); mId = indexToId (mIndex);
} }
void Skill::save(ESMWriter &esm) const void Skill::save(ESMWriter &esm, bool /*isDeleted*/) const
{ {
esm.writeHNT("INDX", mIndex); esm.writeHNT("INDX", mIndex);
esm.writeHNT("SKDT", mData, 24); esm.writeHNT("SKDT", mData, 24);

@ -78,8 +78,8 @@ struct Skill
static const std::string sIconNames[Length]; static const std::string sIconNames[Length];
static const boost::array<SkillEnum, Length> sSkillIds; static const boost::array<SkillEnum, Length> sSkillIds;
void load(ESMReader &esm); void load(ESMReader &esm, bool &isDeleted);
void save(ESMWriter &esm) const; void save(ESMWriter &esm, bool isDeleted = false) const;
void blank(); void blank();
///< Set record to default state (does not touch the ID/index). ///< Set record to default state (does not touch the ID/index).

@ -8,31 +8,21 @@ namespace ESM
{ {
unsigned int SoundGenerator::sRecordId = REC_SNDG; unsigned int SoundGenerator::sRecordId = REC_SNDG;
SoundGenerator::SoundGenerator() void SoundGenerator::load(ESMReader &esm, bool &isDeleted)
: mType(LeftFoot),
mIsDeleted(false)
{}
void SoundGenerator::load(ESMReader &esm)
{ {
mIsDeleted = false; isDeleted = false;
bool hasName = false; bool hasName = false;
bool hasData = false; bool hasData = false;
while (esm.hasMoreSubs()) while (esm.hasMoreSubs())
{ {
esm.getSubName(); esm.getSubName();
uint32_t name = esm.retSubName().val; switch (esm.retSubName().val)
switch (name)
{ {
case ESM::FourCC<'N','A','M','E'>::value: case ESM::FourCC<'N','A','M','E'>::value:
mId = esm.getHString(); mId = esm.getHString();
hasName = true; hasName = true;
break; break;
case ESM::FourCC<'D','E','L','E'>::value:
esm.skipHSub();
mIsDeleted = true;
break;
case ESM::FourCC<'D','A','T','A'>::value: case ESM::FourCC<'D','A','T','A'>::value:
esm.getHT(mType, 4); esm.getHT(mType, 4);
hasData = true; hasData = true;
@ -43,6 +33,10 @@ namespace ESM
case ESM::FourCC<'S','N','A','M'>::value: case ESM::FourCC<'S','N','A','M'>::value:
mSound = esm.getHString(); mSound = esm.getHString();
break; break;
case ESM::FourCC<'D','E','L','E'>::value:
esm.skipHSub();
isDeleted = true;
break;
default: default:
esm.fail("Unknown subrecord"); esm.fail("Unknown subrecord");
break; break;
@ -51,17 +45,17 @@ namespace ESM
if (!hasName) if (!hasName)
esm.fail("Missing NAME subrecord"); esm.fail("Missing NAME subrecord");
if (!hasData && !mIsDeleted) if (!hasData && !isDeleted)
esm.fail("Missing DATA subrecord"); esm.fail("Missing DATA subrecord");
} }
void SoundGenerator::save(ESMWriter &esm) const void SoundGenerator::save(ESMWriter &esm, bool isDeleted) const
{ {
esm.writeHNCString("NAME", mId); esm.writeHNCString("NAME", mId);
esm.writeHNT("DATA", mType, 4); esm.writeHNT("DATA", mType, 4);
esm.writeHNOCString("CNAM", mCreature); esm.writeHNOCString("CNAM", mCreature);
esm.writeHNOCString("SNAM", mSound); esm.writeHNOCString("SNAM", mSound);
if (mIsDeleted) if (isDeleted)
{ {
esm.writeHNCString("DELE", ""); esm.writeHNCString("DELE", "");
} }
@ -72,6 +66,5 @@ namespace ESM
mType = LeftFoot; mType = LeftFoot;
mCreature.clear(); mCreature.clear();
mSound.clear(); mSound.clear();
mIsDeleted = false;
} }
} }

@ -36,12 +36,8 @@ struct SoundGenerator
std::string mId, mCreature, mSound; std::string mId, mCreature, mSound;
bool mIsDeleted; void load(ESMReader &esm, bool &isDeleted);
void save(ESMWriter &esm, bool isDeleted = false) const;
SoundGenerator();
void load(ESMReader &esm);
void save(ESMWriter &esm) const;
void blank(); void blank();
}; };

@ -8,30 +8,21 @@ namespace ESM
{ {
unsigned int Sound::sRecordId = REC_SOUN; unsigned int Sound::sRecordId = REC_SOUN;
Sound::Sound() void Sound::load(ESMReader &esm, bool &isDeleted)
: mIsDeleted(false)
{}
void Sound::load(ESMReader &esm)
{ {
mIsDeleted = false; isDeleted = false;
bool hasName = false; bool hasName = false;
bool hasData = false; bool hasData = false;
while (esm.hasMoreSubs()) while (esm.hasMoreSubs())
{ {
esm.getSubName(); esm.getSubName();
uint32_t name = esm.retSubName().val; switch (esm.retSubName().val)
switch (name)
{ {
case ESM::FourCC<'N','A','M','E'>::value: case ESM::FourCC<'N','A','M','E'>::value:
mId = esm.getHString(); mId = esm.getHString();
hasName = true; hasName = true;
break; break;
case ESM::FourCC<'D','E','L','E'>::value:
esm.skipHSub();
mIsDeleted = true;
break;
case ESM::FourCC<'F','N','A','M'>::value: case ESM::FourCC<'F','N','A','M'>::value:
mSound = esm.getHString(); mSound = esm.getHString();
break; break;
@ -39,6 +30,10 @@ namespace ESM
esm.getHT(mData, 3); esm.getHT(mData, 3);
hasData = true; hasData = true;
break; break;
case ESM::FourCC<'D','E','L','E'>::value:
esm.skipHSub();
isDeleted = true;
break;
default: default:
esm.fail("Unknown subrecord"); esm.fail("Unknown subrecord");
break; break;
@ -47,15 +42,15 @@ namespace ESM
if (!hasName) if (!hasName)
esm.fail("Missing NAME subrecord"); esm.fail("Missing NAME subrecord");
if (!hasData && !mIsDeleted) if (!hasData && !isDeleted)
esm.fail("Missing DATA subrecord"); esm.fail("Missing DATA subrecord");
} }
void Sound::save(ESMWriter &esm) const void Sound::save(ESMWriter &esm, bool isDeleted) const
{ {
esm.writeHNCString("NAME", mId); esm.writeHNCString("NAME", mId);
if (mIsDeleted) if (isDeleted)
{ {
esm.writeHNCString("DELE", ""); esm.writeHNCString("DELE", "");
return; return;
@ -72,7 +67,5 @@ namespace ESM
mData.mVolume = 128; mData.mVolume = 128;
mData.mMinRange = 0; mData.mMinRange = 0;
mData.mMaxRange = 255; mData.mMaxRange = 255;
mIsDeleted = false;
} }
} }

@ -23,12 +23,8 @@ struct Sound
SOUNstruct mData; SOUNstruct mData;
std::string mId, mSound; std::string mId, mSound;
bool mIsDeleted; void load(ESMReader &esm, bool &isDeleted);
void save(ESMWriter &esm, bool isDeleted = false) const;
Sound();
void load(ESMReader &esm);
void save(ESMWriter &esm) const;
void blank(); void blank();
///< Set record to default state (does not touch the ID/index). ///< Set record to default state (does not touch the ID/index).

@ -8,32 +8,23 @@ namespace ESM
{ {
unsigned int Spell::sRecordId = REC_SPEL; unsigned int Spell::sRecordId = REC_SPEL;
Spell::Spell() void Spell::load(ESMReader &esm, bool &isDeleted)
: mIsDeleted(false)
{}
void Spell::load(ESMReader &esm)
{ {
isDeleted = false;
mEffects.mList.clear(); mEffects.mList.clear();
mIsDeleted = false;
bool hasName = false; bool hasName = false;
bool hasData = false; bool hasData = false;
while (esm.hasMoreSubs()) while (esm.hasMoreSubs())
{ {
esm.getSubName(); esm.getSubName();
uint32_t val = esm.retSubName().val; switch (esm.retSubName().val)
switch (val)
{ {
case ESM::FourCC<'N','A','M','E'>::value: case ESM::FourCC<'N','A','M','E'>::value:
mId = esm.getHString(); mId = esm.getHString();
hasName = true; hasName = true;
break; break;
case ESM::FourCC<'D','E','L','E'>::value:
esm.skipHSub();
mIsDeleted = true;
break;
case ESM::FourCC<'F','N','A','M'>::value: case ESM::FourCC<'F','N','A','M'>::value:
mName = esm.getHString(); mName = esm.getHString();
break; break;
@ -46,6 +37,10 @@ namespace ESM
esm.getHT(s, 24); esm.getHT(s, 24);
mEffects.mList.push_back(s); mEffects.mList.push_back(s);
break; break;
case ESM::FourCC<'D','E','L','E'>::value:
esm.skipHSub();
isDeleted = true;
break;
default: default:
esm.fail("Unknown subrecord"); esm.fail("Unknown subrecord");
break; break;
@ -54,15 +49,15 @@ namespace ESM
if (!hasName) if (!hasName)
esm.fail("Missing NAME subrecord"); esm.fail("Missing NAME subrecord");
if (!hasData && !mIsDeleted) if (!hasData && !isDeleted)
esm.fail("Missing SPDT subrecord"); esm.fail("Missing SPDT subrecord");
} }
void Spell::save(ESMWriter &esm) const void Spell::save(ESMWriter &esm, bool isDeleted) const
{ {
esm.writeHNCString("NAME", mId); esm.writeHNCString("NAME", mId);
if (mIsDeleted) if (isDeleted)
{ {
esm.writeHNCString("DELE", ""); esm.writeHNCString("DELE", "");
return; return;
@ -81,6 +76,5 @@ namespace ESM
mName.clear(); mName.clear();
mEffects.mList.clear(); mEffects.mList.clear();
mIsDeleted = false;
} }
} }

@ -45,12 +45,8 @@ struct Spell
std::string mId, mName; std::string mId, mName;
EffectList mEffects; EffectList mEffects;
bool mIsDeleted; void load(ESMReader &esm, bool &isDeleted);
void save(ESMWriter &esm, bool isDeleted = false) const;
Spell();
void load(ESMReader &esm);
void save(ESMWriter &esm) const;
void blank(); void blank();
///< Set record to default state (does not touch the ID/index). ///< Set record to default state (does not touch the ID/index).

@ -8,21 +8,16 @@ namespace ESM
{ {
unsigned int StartScript::sRecordId = REC_SSCR; unsigned int StartScript::sRecordId = REC_SSCR;
StartScript::StartScript() void StartScript::load(ESMReader &esm, bool &isDeleted)
: mIsDeleted(false)
{}
void StartScript::load(ESMReader &esm)
{ {
mIsDeleted = false; isDeleted = false;
bool hasData = false; bool hasData = false;
bool hasName = false; bool hasName = false;
while (esm.hasMoreSubs()) while (esm.hasMoreSubs())
{ {
esm.getSubName(); esm.getSubName();
uint32_t name = esm.retSubName().val; switch (esm.retSubName().val)
switch (name)
{ {
case ESM::FourCC<'D','A','T','A'>::value: case ESM::FourCC<'D','A','T','A'>::value:
mData = esm.getHString(); mData = esm.getHString();
@ -34,7 +29,7 @@ namespace ESM
break; break;
case ESM::FourCC<'D','E','L','E'>::value: case ESM::FourCC<'D','E','L','E'>::value:
esm.skipHSub(); esm.skipHSub();
mIsDeleted = true; isDeleted = true;
break; break;
default: default:
esm.fail("Unknown subrecord"); esm.fail("Unknown subrecord");
@ -47,12 +42,12 @@ namespace ESM
if (!hasName) if (!hasName)
esm.fail("Missing NAME"); esm.fail("Missing NAME");
} }
void StartScript::save(ESMWriter &esm) const void StartScript::save(ESMWriter &esm, bool isDeleted) const
{ {
esm.writeHNString("DATA", mData); esm.writeHNString("DATA", mData);
esm.writeHNString("NAME", mId); esm.writeHNString("NAME", mId);
if (mIsDeleted) if (isDeleted)
{ {
esm.writeHNCString("DELE", ""); esm.writeHNCString("DELE", "");
} }
@ -61,6 +56,5 @@ namespace ESM
void StartScript::blank() void StartScript::blank()
{ {
mData.clear(); mData.clear();
mIsDeleted = false;
} }
} }

@ -26,13 +26,9 @@ struct StartScript
std::string mData; std::string mData;
std::string mId; std::string mId;
bool mIsDeleted;
StartScript();
// Load a record and add it to the list // Load a record and add it to the list
void load(ESMReader &esm); void load(ESMReader &esm, bool &isDeleted);
void save(ESMWriter &esm) const; void save(ESMWriter &esm, bool isDeleted = false) const;
void blank(); void blank();
}; };

@ -8,32 +8,27 @@ namespace ESM
{ {
unsigned int Static::sRecordId = REC_STAT; unsigned int Static::sRecordId = REC_STAT;
Static::Static() void Static::load(ESMReader &esm, bool &isDeleted)
: mIsDeleted(false)
{}
void Static::load(ESMReader &esm)
{ {
mIsDeleted = false; isDeleted = false;
bool hasName = false; bool hasName = false;
while (esm.hasMoreSubs()) while (esm.hasMoreSubs())
{ {
esm.getSubName(); esm.getSubName();
uint32_t name = esm.retSubName().val; switch (esm.retSubName().val)
switch (name)
{ {
case ESM::FourCC<'N','A','M','E'>::value: case ESM::FourCC<'N','A','M','E'>::value:
mId = esm.getHString(); mId = esm.getHString();
hasName = true; hasName = true;
break; break;
case ESM::FourCC<'D','E','L','E'>::value:
esm.skipHSub();
mIsDeleted = true;
break;
case ESM::FourCC<'M','O','D','L'>::value: case ESM::FourCC<'M','O','D','L'>::value:
mModel = esm.getHString(); mModel = esm.getHString();
break; break;
case ESM::FourCC<'D','E','L','E'>::value:
esm.skipHSub();
isDeleted = true;
break;
default: default:
esm.fail("Unknown subrecord"); esm.fail("Unknown subrecord");
break; break;
@ -43,10 +38,10 @@ namespace ESM
if (!hasName) if (!hasName)
esm.fail("Missing NAME subrecord"); esm.fail("Missing NAME subrecord");
} }
void Static::save(ESMWriter &esm) const void Static::save(ESMWriter &esm, bool isDeleted) const
{ {
esm.writeHNCString("NAME", mId); esm.writeHNCString("NAME", mId);
if (mIsDeleted) if (isDeleted)
{ {
esm.writeHNCString("DELE", ""); esm.writeHNCString("DELE", "");
} }
@ -59,6 +54,5 @@ namespace ESM
void Static::blank() void Static::blank()
{ {
mModel.clear(); mModel.clear();
mIsDeleted = false;
} }
} }

@ -28,12 +28,8 @@ struct Static
std::string mId, mModel; std::string mId, mModel;
bool mIsDeleted; void load(ESMReader &esm, bool &isDeleted);
void save(ESMWriter &esm, bool isDeleted = false) const;
Static();
void load(ESMReader &esm);
void save(ESMWriter &esm) const;
void blank(); void blank();
///< Set record to default state (does not touch the ID). ///< Set record to default state (does not touch the ID).

@ -8,30 +8,21 @@ namespace ESM
{ {
unsigned int Weapon::sRecordId = REC_WEAP; unsigned int Weapon::sRecordId = REC_WEAP;
Weapon::Weapon() void Weapon::load(ESMReader &esm, bool &isDeleted)
: mIsDeleted(false)
{}
void Weapon::load(ESMReader &esm)
{ {
mIsDeleted = false; isDeleted = false;
bool hasName = false; bool hasName = false;
bool hasData = false; bool hasData = false;
while (esm.hasMoreSubs()) while (esm.hasMoreSubs())
{ {
esm.getSubName(); esm.getSubName();
uint32_t name = esm.retSubName().val; switch (esm.retSubName().val)
switch (name)
{ {
case ESM::FourCC<'N','A','M','E'>::value: case ESM::FourCC<'N','A','M','E'>::value:
mId = esm.getHString(); mId = esm.getHString();
hasName = true; hasName = true;
break; break;
case ESM::FourCC<'D','E','L','E'>::value:
esm.skipHSub();
mIsDeleted = true;
break;
case ESM::FourCC<'M','O','D','L'>::value: case ESM::FourCC<'M','O','D','L'>::value:
mModel = esm.getHString(); mModel = esm.getHString();
break; break;
@ -51,6 +42,10 @@ namespace ESM
case ESM::FourCC<'E','N','A','M'>::value: case ESM::FourCC<'E','N','A','M'>::value:
mEnchant = esm.getHString(); mEnchant = esm.getHString();
break; break;
case ESM::FourCC<'D','E','L','E'>::value:
esm.skipHSub();
isDeleted = true;
break;
default: default:
esm.fail("Unknown subrecord"); esm.fail("Unknown subrecord");
} }
@ -58,14 +53,14 @@ namespace ESM
if (!hasName) if (!hasName)
esm.fail("Missing NAME subrecord"); esm.fail("Missing NAME subrecord");
if (!hasData && !mIsDeleted) if (!hasData && !isDeleted)
esm.fail("Missing WPDT subrecord"); esm.fail("Missing WPDT subrecord");
} }
void Weapon::save(ESMWriter &esm) const void Weapon::save(ESMWriter &esm, bool isDeleted) const
{ {
esm.writeHNCString("NAME", mId); esm.writeHNCString("NAME", mId);
if (mIsDeleted) if (isDeleted)
{ {
esm.writeHNCString("DELE", ""); esm.writeHNCString("DELE", "");
return; return;
@ -98,7 +93,5 @@ namespace ESM
mIcon.clear(); mIcon.clear();
mEnchant.clear(); mEnchant.clear();
mScript.clear(); mScript.clear();
mIsDeleted = false;
} }
} }

@ -69,12 +69,8 @@ struct Weapon
std::string mId, mName, mModel, mIcon, mEnchant, mScript; std::string mId, mName, mModel, mIcon, mEnchant, mScript;
bool mIsDeleted; void load(ESMReader &esm, bool &isDeleted);
void save(ESMWriter &esm, bool isDeleted = false) const;
Weapon();
void load(ESMReader &esm);
void save(ESMWriter &esm) const;
void blank(); void blank();
///< Set record to default state (does not touch the ID). ///< Set record to default state (does not touch the ID).

@ -8,7 +8,8 @@ void ESM::ObjectState::load (ESMReader &esm)
{ {
mVersion = esm.getFormat(); mVersion = esm.getFormat();
mRef.loadData(esm); bool isDeleted;
mRef.loadData(esm, isDeleted);
mHasLocals = 0; mHasLocals = 0;
esm.getHNOT (mHasLocals, "HLOC"); esm.getHNOT (mHasLocals, "HLOC");

Loading…
Cancel
Save