diff --git a/components/esm/cellref.cpp b/components/esm/cellref.cpp index e43a37b66..c6fb899b3 100644 --- a/components/esm/cellref.cpp +++ b/components/esm/cellref.cpp @@ -3,7 +3,6 @@ #include "esmreader.hpp" #include "esmwriter.hpp" -#include "util.hpp" ESM::CellRef::CellRef() : mScale(1.0f), @@ -38,7 +37,6 @@ void ESM::RefNum::save (ESMWriter &esm, bool wide, const std::string& tag) const void ESM::CellRef::load (ESMReader& esm, bool wideRefNum) { - mIsDeleted = false; loadId(esm, wideRefNum); loadData(esm); } @@ -55,62 +53,90 @@ void ESM::CellRef::loadId (ESMReader& esm, bool wideRefNum) mRefNum.load (esm, wideRefNum); mRefID = esm.getHNString ("NAME"); + mIsDeleted = false; } void ESM::CellRef::loadData(ESMReader &esm) { - // Again, UNAM sometimes appears after NAME and sometimes later. - // Or perhaps this UNAM means something different? - mReferenceBlocked = -1; - esm.getHNOT (mReferenceBlocked, "UNAM"); - - mScale = 1.0; - esm.getHNOT (mScale, "XSCL"); - - mOwner = esm.getHNOString ("ANAM"); - mGlobalVariable = esm.getHNOString ("BNAM"); - mSoul = esm.getHNOString ("XSOL"); - - mFaction = esm.getHNOString ("CNAM"); + mScale = 1.0f; mFactionRank = -2; - esm.getHNOT (mFactionRank, "INDX"); - - mGoldValue = 1; mChargeInt = -1; mEnchantmentCharge = -1; + mGoldValue = 1; + mLockLevel = 0; + mReferenceBlocked = -1; + mTeleport = false; + mIsDeleted = false; - esm.getHNOT (mEnchantmentCharge, "XCHG"); - - esm.getHNOT (mChargeInt, "INTV"); - - esm.getHNOT (mGoldValue, "NAM9"); - - // Present for doors that teleport you to another cell. - if (esm.isNextSub ("DODT")) + bool isLoaded = false; + while (!isLoaded && esm.hasMoreSubs()) { - mTeleport = true; - esm.getHT (mDoorDest); - mDestCell = esm.getHNOString ("DNAM"); + esm.getSubName(); + uint32_t name = esm.retSubName().val; + switch (name) + { + case ESM::FourCC<'U','N','A','M'>::value: + esm.getHT(mReferenceBlocked); + break; + case ESM::FourCC<'X','S','C','L'>::value: + esm.getHT(mScale); + break; + case ESM::FourCC<'A','N','A','M'>::value: + mOwner = esm.getHString(); + break; + case ESM::FourCC<'B','N','A','M'>::value: + mGlobalVariable = esm.getHString(); + break; + case ESM::FourCC<'X','S','O','L'>::value: + mSoul = esm.getHString(); + break; + case ESM::FourCC<'C','N','A','M'>::value: + mFaction = esm.getHString(); + break; + case ESM::FourCC<'I','N','D','X'>::value: + esm.getHT(mFactionRank); + break; + case ESM::FourCC<'X','C','H','G'>::value: + esm.getHT(mEnchantmentCharge); + break; + case ESM::FourCC<'I','N','T','V'>::value: + esm.getHT(mChargeInt); + break; + case ESM::FourCC<'N','A','M','9'>::value: + esm.getHT(mGoldValue); + break; + case ESM::FourCC<'D','O','D','T'>::value: + esm.getHT(mDoorDest); + mTeleport = true; + break; + case ESM::FourCC<'D','N','A','M'>::value: + mDestCell = esm.getHString(); + break; + case ESM::FourCC<'F','L','T','V'>::value: + esm.getHT(mLockLevel); + break; + case ESM::FourCC<'K','N','A','M'>::value: + mKey = esm.getHString(); + break; + case ESM::FourCC<'T','N','A','M'>::value: + mTrap = esm.getHString(); + break; + case ESM::FourCC<'D','A','T','A'>::value: + esm.getHT(mPos, 24); + break; + case ESM::FourCC<'N','A','M','0'>::value: + esm.skipHSub(); + break; + case ESM::FourCC<'D','E','L','E'>::value: + esm.skipHSub(); + mIsDeleted = true; + break; + default: + esm.cacheSubName(); + isLoaded = true; + break; + } } - else - mTeleport = false; - - mLockLevel = 0; //Set to 0 to indicate no lock - esm.getHNOT (mLockLevel, "FLTV"); - - mKey = esm.getHNOString ("KNAM"); - mTrap = esm.getHNOString ("TNAM"); - - esm.getHNOT (mReferenceBlocked, "UNAM"); - if (esm.isNextSub("FLTV")) // no longer used - esm.skipHSub(); - - esm.getHNOT(mPos, "DATA", 24); - - if (esm.isNextSub("NAM0")) - esm.skipHSub(); - - mIsDeleted = readDeleSubRecord (esm); } void ESM::CellRef::save (ESMWriter &esm, bool wideRefNum, bool inInventory) const @@ -149,7 +175,7 @@ void ESM::CellRef::save (ESMWriter &esm, bool wideRefNum, bool inInventory) cons } if (!inInventory && mLockLevel != 0) { - esm.writeHNT("FLTV", mLockLevel); + esm.writeHNT("FLTV", mLockLevel); } if (!inInventory) @@ -166,7 +192,7 @@ void ESM::CellRef::save (ESMWriter &esm, bool wideRefNum, bool inInventory) cons if (mIsDeleted) { - writeDeleSubRecord(esm); + esm.writeHNCString("DELE", ""); } } diff --git a/components/esm/esmreader.cpp b/components/esm/esmreader.cpp index 4be334970..1bf176842 100644 --- a/components/esm/esmreader.cpp +++ b/components/esm/esmreader.cpp @@ -187,6 +187,11 @@ bool ESMReader::peekNextSub(const char *name) return mCtx.subName == name; } +void ESMReader::cacheSubName() +{ + mCtx.subCached = true; +} + // Read subrecord name. This gets called a LOT, so I've optimized it // slightly. void ESMReader::getSubName() diff --git a/components/esm/esmreader.hpp b/components/esm/esmreader.hpp index c3e6bbbd3..4772aeb6f 100644 --- a/components/esm/esmreader.hpp +++ b/components/esm/esmreader.hpp @@ -185,6 +185,9 @@ public: bool peekNextSub(const char* name); + // Store the current subrecord name for the next call of getSubName() + void cacheSubName(); + // Read subrecord name. This gets called a LOT, so I've optimized it // slightly. void getSubName(); diff --git a/components/esm/loadacti.cpp b/components/esm/loadacti.cpp index 14a3abe54..c32cea1a6 100644 --- a/components/esm/loadacti.cpp +++ b/components/esm/loadacti.cpp @@ -3,7 +3,6 @@ #include "esmreader.hpp" #include "esmwriter.hpp" #include "defs.hpp" -#include "util.hpp" namespace ESM { @@ -15,18 +14,23 @@ namespace ESM void Activator::load(ESMReader &esm) { - mId = esm.getHNString("NAME"); - if (mIsDeleted = readDeleSubRecord(esm)) - { - return; - } + mIsDeleted = false; + bool hasName = false; while (esm.hasMoreSubs()) { esm.getSubName(); uint32_t name = esm.retSubName().val; switch (name) { + case ESM::FourCC<'N','A','M','E'>::value: + mId = esm.getHString(); + hasName = true; + break; + case ESM::FourCC<'D','E','L','E'>::value: + esm.skipHSub(); + mIsDeleted = true; + break; case ESM::FourCC<'M','O','D','L'>::value: mModel = esm.getHString(); break; @@ -38,15 +42,20 @@ namespace ESM break; default: esm.fail("Unknown subrecord"); + break; } } + + if (!hasName) + esm.fail("Missing NAME subrecord"); } void Activator::save(ESMWriter &esm) const { esm.writeHNCString("NAME", mId); + if (mIsDeleted) { - writeDeleSubRecord(esm); + esm.writeHNCString("DELE", ""); return; } diff --git a/components/esm/loadalch.cpp b/components/esm/loadalch.cpp index 5faeb99e1..c1213583d 100644 --- a/components/esm/loadalch.cpp +++ b/components/esm/loadalch.cpp @@ -3,7 +3,6 @@ #include "esmreader.hpp" #include "esmwriter.hpp" #include "defs.hpp" -#include "util.hpp" namespace ESM { @@ -16,13 +15,9 @@ namespace ESM void Potion::load(ESMReader &esm) { mEffects.mList.clear(); + mIsDeleted = false; - mId = esm.getHNString("NAME"); - if (mIsDeleted = readDeleSubRecord(esm)) - { - return; - } - + bool hasName = false; bool hasData = false; while (esm.hasMoreSubs()) { @@ -30,6 +25,14 @@ namespace ESM uint32_t name = esm.retSubName().val; switch (name) { + case ESM::FourCC<'N','A','M','E'>::value: + mId = esm.getHString(); + hasName = true; + break; + case ESM::FourCC<'D','E','L','E'>::value: + esm.skipHSub(); + mIsDeleted = true; + break; case ESM::FourCC<'M','O','D','L'>::value: mModel = esm.getHString(); break; @@ -51,17 +54,22 @@ namespace ESM break; default: esm.fail("Unknown subrecord"); + break; } } - if (!hasData) - esm.fail("Missing ALDT"); + + if (!hasName) + esm.fail("Missing NAME subrecord"); + if (!hasData && !mIsDeleted) + esm.fail("Missing ALDT subrecord"); } void Potion::save(ESMWriter &esm) const { esm.writeHNCString("NAME", mId); + if (mIsDeleted) { - writeDeleSubRecord(esm); + esm.writeHNCString("DELE", ""); return; } diff --git a/components/esm/loadappa.cpp b/components/esm/loadappa.cpp index ea375aa7f..edf1f473b 100644 --- a/components/esm/loadappa.cpp +++ b/components/esm/loadappa.cpp @@ -3,7 +3,6 @@ #include "esmreader.hpp" #include "esmwriter.hpp" #include "defs.hpp" -#include "util.hpp" namespace ESM { @@ -15,12 +14,9 @@ namespace ESM void Apparatus::load(ESMReader &esm) { - mId = esm.getHNString("NAME"); - if (mIsDeleted = readDeleSubRecord(esm)) - { - return; - } + mIsDeleted = false; + bool hasName = false; bool hasData = false; while (esm.hasMoreSubs()) { @@ -28,6 +24,14 @@ namespace ESM uint32_t name = esm.retSubName().val; switch (name) { + case ESM::FourCC<'N','A','M','E'>::value: + mId = esm.getHString(); + hasName = true; + break; + case ESM::FourCC<'D','E','L','E'>::value: + esm.skipHSub(); + mIsDeleted = true; + break; case ESM::FourCC<'M','O','D','L'>::value: mModel = esm.getHString(); break; @@ -46,18 +50,23 @@ namespace ESM break; default: esm.fail("Unknown subrecord"); + break; } } - if (!hasData) - esm.fail("Missing AADT"); + + if (!hasName) + esm.fail("Missing NAME subrecord"); + if (!hasData && !mIsDeleted) + esm.fail("Missing AADT subrecord"); } void Apparatus::save(ESMWriter &esm) const { esm.writeHNCString("NAME", mId); + if (mIsDeleted) { - writeDeleSubRecord(esm); + esm.writeHNCString("DELE", ""); return; } diff --git a/components/esm/loadarmo.cpp b/components/esm/loadarmo.cpp index d23a71cac..d5b9fdd44 100644 --- a/components/esm/loadarmo.cpp +++ b/components/esm/loadarmo.cpp @@ -3,7 +3,6 @@ #include "esmreader.hpp" #include "esmwriter.hpp" #include "defs.hpp" -#include "util.hpp" namespace ESM { @@ -46,13 +45,9 @@ namespace ESM void Armor::load(ESMReader &esm) { mParts.mParts.clear(); + mIsDeleted = false; - mId = esm.getHNString("NAME"); - if (mIsDeleted = readDeleSubRecord(esm)) - { - return; - } - + bool hasName = false; bool hasData = false; while (esm.hasMoreSubs()) { @@ -60,6 +55,14 @@ namespace ESM uint32_t name = esm.retSubName().val; switch (name) { + case ESM::FourCC<'N','A','M','E'>::value: + mId = esm.getHString(); + hasName = true; + break; + case ESM::FourCC<'D','E','L','E'>::value: + esm.skipHSub(); + mIsDeleted = true; + break; case ESM::FourCC<'M','O','D','L'>::value: mModel = esm.getHString(); break; @@ -84,18 +87,23 @@ namespace ESM break; default: esm.fail("Unknown subrecord"); + break; } } - if (!hasData) + + if (!hasName) + esm.fail("Missing NAME subrecord"); + if (!hasData && !mIsDeleted) esm.fail("Missing CTDT subrecord"); } void Armor::save(ESMWriter &esm) const { esm.writeHNCString("NAME", mId); + if (mIsDeleted) { - writeDeleSubRecord(esm); + esm.writeHNCString("DELE", ""); return; } diff --git a/components/esm/loadbody.cpp b/components/esm/loadbody.cpp index e0ebfd539..e2c6ad7b2 100644 --- a/components/esm/loadbody.cpp +++ b/components/esm/loadbody.cpp @@ -3,7 +3,6 @@ #include "esmreader.hpp" #include "esmwriter.hpp" #include "defs.hpp" -#include "util.hpp" namespace ESM { @@ -15,12 +14,9 @@ namespace ESM void BodyPart::load(ESMReader &esm) { - mId = esm.getHNString("NAME"); - if (mIsDeleted = readDeleSubRecord(esm)) - { - return; - } + mIsDeleted = false; + bool hasName = false; bool hasData = false; while (esm.hasMoreSubs()) { @@ -28,6 +24,14 @@ namespace ESM uint32_t name = esm.retSubName().val; switch (name) { + case ESM::FourCC<'N','A','M','E'>::value: + mId = esm.getHString(); + hasName = true; + break; + case ESM::FourCC<'D','E','L','E'>::value: + esm.skipHSub(); + mIsDeleted = true; + break; case ESM::FourCC<'M','O','D','L'>::value: mModel = esm.getHString(); break; @@ -40,19 +44,23 @@ namespace ESM break; default: esm.fail("Unknown subrecord"); + break; } } - if (!hasData) + if (!hasName) + esm.fail("Missing NAME subrecord"); + if (!hasData && !mIsDeleted) esm.fail("Missing BYDT subrecord"); } void BodyPart::save(ESMWriter &esm) const { esm.writeHNCString("NAME", mId); + if (mIsDeleted) { - writeDeleSubRecord(esm); + esm.writeHNCString("DELE", ""); return; } diff --git a/components/esm/loadbook.cpp b/components/esm/loadbook.cpp index 2824b6200..2d0d3ce75 100644 --- a/components/esm/loadbook.cpp +++ b/components/esm/loadbook.cpp @@ -3,7 +3,6 @@ #include "esmreader.hpp" #include "esmwriter.hpp" #include "defs.hpp" -#include "util.hpp" namespace ESM { @@ -15,12 +14,9 @@ namespace ESM void Book::load(ESMReader &esm) { - mId = esm.getHNString("NAME"); - if (mIsDeleted = readDeleSubRecord(esm)) - { - return; - } + mIsDeleted = false; + bool hasName = false; bool hasData = false; while (esm.hasMoreSubs()) { @@ -28,6 +24,14 @@ namespace ESM uint32_t name = esm.retSubName().val; switch (name) { + case ESM::FourCC<'N','A','M','E'>::value: + mId = esm.getHString(); + hasName = true; + break; + case ESM::FourCC<'D','E','L','E'>::value: + esm.skipHSub(); + mIsDeleted = true; + break; case ESM::FourCC<'M','O','D','L'>::value: mModel = esm.getHString(); break; @@ -52,17 +56,22 @@ namespace ESM break; default: esm.fail("Unknown subrecord"); + break; } } - if (!hasData) + + if (!hasName) + esm.fail("Missing NAME subrecord"); + if (!hasData && !mIsDeleted) esm.fail("Missing BKDT subrecord"); } void Book::save(ESMWriter &esm) const { esm.writeHNCString("NAME", mId); + if (mIsDeleted) { - writeDeleSubRecord(esm); + esm.writeHNCString("DELE", ""); return; } diff --git a/components/esm/loadbsgn.cpp b/components/esm/loadbsgn.cpp index 8cdeed3f6..9f5cd7270 100644 --- a/components/esm/loadbsgn.cpp +++ b/components/esm/loadbsgn.cpp @@ -16,16 +16,23 @@ namespace ESM void BirthSign::load(ESMReader &esm) { mPowers.mList.clear(); + mIsDeleted = false; - mIsDeleted = readDeleSubRecord(esm); - mId = esm.getHNString("NAME"); - + bool hasName = false; while (esm.hasMoreSubs()) { esm.getSubName(); uint32_t name = esm.retSubName().val; switch (name) { + case ESM::FourCC<'N','A','M','E'>::value: + mId = esm.getHString(); + hasName = true; + break; + case ESM::FourCC<'D','E','L','E'>::value: + esm.skipHSub(); + mIsDeleted = true; + break; case ESM::FourCC<'F','N','A','M'>::value: mName = esm.getHString(); break; @@ -40,16 +47,21 @@ namespace ESM break; default: esm.fail("Unknown subrecord"); + break; } } + + if (!hasName) + esm.fail("Missing NAME subrecord"); } void BirthSign::save(ESMWriter &esm) const { if (mIsDeleted) { - writeDeleSubRecord(esm); + esm.writeHNCString("DELE", ""); } + esm.writeHNCString("NAME", mId); esm.writeHNOCString("FNAM", mName); esm.writeHNOCString("TNAM", mTexture); diff --git a/components/esm/loadclas.cpp b/components/esm/loadclas.cpp index 1384a6280..b58c35d90 100644 --- a/components/esm/loadclas.cpp +++ b/components/esm/loadclas.cpp @@ -5,7 +5,6 @@ #include "esmreader.hpp" #include "esmwriter.hpp" #include "defs.hpp" -#include "util.hpp" namespace ESM { @@ -45,12 +44,9 @@ namespace ESM void Class::load(ESMReader &esm) { - mId = esm.getHNString("NAME"); - if (mIsDeleted = readDeleSubRecord(esm)) - { - return; - } + mIsDeleted = false; + bool hasName = false; bool hasData = false; while (esm.hasMoreSubs()) { @@ -58,6 +54,14 @@ namespace ESM uint32_t name = esm.retSubName().val; switch (name) { + case ESM::FourCC<'N','A','M','E'>::value: + mId = esm.getHString(); + hasName = true; + break; + case ESM::FourCC<'D','E','L','E'>::value: + esm.skipHSub(); + mIsDeleted = true; + break; case ESM::FourCC<'F','N','A','M'>::value: mName = esm.getHString(); break; @@ -72,17 +76,22 @@ namespace ESM break; default: esm.fail("Unknown subrecord"); + break; } } - if (!hasData) + + if (!hasName) + esm.fail("Missing NAME subrecord"); + if (!hasData && !mIsDeleted) esm.fail("Missing CLDT subrecord"); } void Class::save(ESMWriter &esm) const { esm.writeHNCString("NAME", mId); + if (mIsDeleted) { - writeDeleSubRecord(esm); + esm.writeHNCString("DELE", ""); return; } diff --git a/components/esm/loadclot.cpp b/components/esm/loadclot.cpp index 88f2e5715..18f7cd44f 100644 --- a/components/esm/loadclot.cpp +++ b/components/esm/loadclot.cpp @@ -3,7 +3,6 @@ #include "esmreader.hpp" #include "esmwriter.hpp" #include "defs.hpp" -#include "util.hpp" namespace ESM { @@ -16,13 +15,9 @@ namespace ESM void Clothing::load(ESMReader &esm) { mParts.mParts.clear(); + mIsDeleted = false; - mId = esm.getHNString("NAME"); - if (mIsDeleted = readDeleSubRecord(esm)) - { - return; - } - + bool hasName = false; bool hasData = false; while (esm.hasMoreSubs()) { @@ -30,6 +25,14 @@ namespace ESM uint32_t name = esm.retSubName().val; switch (name) { + case ESM::FourCC<'N','A','M','E'>::value: + mId = esm.getHString(); + hasName = true; + break; + case ESM::FourCC<'D','E','L','E'>::value: + esm.skipHSub(); + mIsDeleted = true; + break; case ESM::FourCC<'M','O','D','L'>::value: mModel = esm.getHString(); break; @@ -54,18 +57,23 @@ namespace ESM break; default: esm.fail("Unknown subrecord"); + break; } } - if (!hasData) + + if (!hasName) + esm.fail("Missing NAME subrecord"); + if (!hasData && !mIsDeleted) esm.fail("Missing CTDT subrecord"); } void Clothing::save(ESMWriter &esm) const { esm.writeHNCString("NAME", mId); + if (mIsDeleted) { - writeDeleSubRecord(esm); + esm.writeHNCString("DELE", ""); return; } diff --git a/components/esm/loadcont.cpp b/components/esm/loadcont.cpp index 3d3d7fced..fadfe5f0f 100644 --- a/components/esm/loadcont.cpp +++ b/components/esm/loadcont.cpp @@ -3,7 +3,6 @@ #include "esmreader.hpp" #include "esmwriter.hpp" #include "defs.hpp" -#include "util.hpp" namespace ESM { @@ -26,19 +25,17 @@ namespace ESM unsigned int Container::sRecordId = REC_CONT; Container::Container() - : mIsDeleted(false) + : mWeight(0), + mFlags(0x8), + mIsDeleted(false) {} void Container::load(ESMReader &esm) { mInventory.mList.clear(); + mIsDeleted = false; - mId = esm.getHNString("NAME"); - if (mIsDeleted = readDeleSubRecord(esm)) - { - return; - } - + bool hasName = false; bool hasWeight = false; bool hasFlags = false; while (esm.hasMoreSubs()) @@ -47,6 +44,14 @@ namespace ESM uint32_t name = esm.retSubName().val; switch (name) { + case ESM::FourCC<'N','A','M','E'>::value: + mId = esm.getHString(); + hasName = true; + break; + case ESM::FourCC<'D','E','L','E'>::value: + esm.skipHSub(); + mIsDeleted = true; + break; case ESM::FourCC<'M','O','D','L'>::value: mModel = esm.getHString(); break; @@ -73,20 +78,25 @@ namespace ESM break; default: esm.fail("Unknown subrecord"); + break; } } - if (!hasWeight) + + if (!hasName) + esm.fail("Missing NAME subrecord"); + if (!hasWeight && !mIsDeleted) esm.fail("Missing CNDT subrecord"); - if (!hasFlags) + if (!hasFlags && !mIsDeleted) esm.fail("Missing FLAG subrecord"); } void Container::save(ESMWriter &esm) const { esm.writeHNCString("NAME", mId); + if (mIsDeleted) { - writeDeleSubRecord(esm); + esm.writeHNCString("DELE", ""); return; } diff --git a/components/esm/loadcrea.cpp b/components/esm/loadcrea.cpp index 57e911e70..f360c8748 100644 --- a/components/esm/loadcrea.cpp +++ b/components/esm/loadcrea.cpp @@ -3,14 +3,15 @@ #include "esmreader.hpp" #include "esmwriter.hpp" #include "defs.hpp" -#include "util.hpp" namespace ESM { unsigned int Creature::sRecordId = REC_CREA; Creature::Creature() - : mIsDeleted(false) + : mFlags(0), + mScale(0.0f), + mIsDeleted(false) {} void Creature::load(ESMReader &esm) @@ -22,14 +23,11 @@ namespace ESM { mSpells.mList.clear(); mTransport.mList.clear(); - mId = esm.getHNString("NAME"); - if (mIsDeleted = readDeleSubRecord(esm)) - { - return; - } - mScale = 1.f; mHasAI = false; + mIsDeleted = false; + + bool hasName = false; bool hasNpdt = false; bool hasFlags = false; while (esm.hasMoreSubs()) @@ -38,6 +36,14 @@ namespace ESM { uint32_t name = esm.retSubName().val; switch (name) { + case ESM::FourCC<'N','A','M','E'>::value: + mId = esm.getHString(); + hasName = true; + break; + case ESM::FourCC<'D','E','L','E'>::value: + esm.skipHSub(); + mIsDeleted = true; + break; case ESM::FourCC<'M','O','D','L'>::value: mModel = esm.getHString(); break; @@ -85,20 +91,25 @@ namespace ESM { break; default: esm.fail("Unknown subrecord"); + break; } } - if (!hasNpdt) + + if (!hasName) + esm.fail("Missing NAME subrecord"); + if (!hasNpdt && !mIsDeleted) esm.fail("Missing NPDT subrecord"); - if (!hasFlags) + if (!hasFlags && !mIsDeleted) esm.fail("Missing FLAG subrecord"); } void Creature::save(ESMWriter &esm) const { esm.writeHNCString("NAME", mId); + if (mIsDeleted) { - writeDeleSubRecord(esm); + esm.writeHNCString("DELE", ""); return; } diff --git a/components/esm/loaddial.cpp b/components/esm/loaddial.cpp index fcdb57c8d..c517dc722 100644 --- a/components/esm/loaddial.cpp +++ b/components/esm/loaddial.cpp @@ -7,7 +7,6 @@ #include "esmreader.hpp" #include "esmwriter.hpp" #include "defs.hpp" -#include "util.hpp" namespace ESM { @@ -31,20 +30,36 @@ namespace ESM void Dialogue::loadData(ESMReader &esm) { - esm.getSubNameIs("DATA"); - esm.getSubHeader(); - int si = esm.getSubSize(); - if (si == 1) - esm.getT(mType); - else if (si == 4) // The dialogue is deleted + while (esm.hasMoreSubs()) { - int32_t empty; - esm.getT(empty); // Skip an empty DATA - mIsDeleted = readDeleSubRecord(esm); - mType = Unknown; + esm.getSubName(); + uint32_t name = esm.retSubName().val; + switch (name) + { + case ESM::FourCC<'D','A','T','A'>::value: + { + esm.getSubHeader(); + int size = esm.getSubSize(); + if (size == 1) + { + esm.getT(mType); + } + else + { + esm.skip(size); + } + break; + } + case ESM::FourCC<'D','E','L','E'>::value: + esm.skipHSub(); + mType = Unknown; + mIsDeleted = true; + break; + default: + esm.fail("Unknown subrecord"); + break; + } } - else - esm.fail("Unknown sub record size"); } void Dialogue::save(ESMWriter &esm) const @@ -52,8 +67,7 @@ namespace ESM esm.writeHNCString("NAME", mId); if (mIsDeleted) { - esm.writeHNT("DATA", static_cast(0)); - writeDeleSubRecord(esm); + esm.writeHNCString("DELE", ""); } else { @@ -138,7 +152,7 @@ namespace ESM { for (InfoContainer::iterator it = mInfo.begin(); it != mInfo.end(); ) { - if (it->mIsDeleted || it->mQuestStatus == DialInfo::QS_Deleted) + if (it->mIsDeleted) it = mInfo.erase(it); else ++it; diff --git a/components/esm/loaddoor.cpp b/components/esm/loaddoor.cpp index 87382fa7b..4f58a4261 100644 --- a/components/esm/loaddoor.cpp +++ b/components/esm/loaddoor.cpp @@ -3,7 +3,6 @@ #include "esmreader.hpp" #include "esmwriter.hpp" #include "defs.hpp" -#include "util.hpp" namespace ESM { @@ -15,18 +14,23 @@ namespace ESM void Door::load(ESMReader &esm) { - mId = esm.getHNString("NAME"); - if (mIsDeleted = readDeleSubRecord(esm)) - { - return; - } + mIsDeleted = false; + bool hasName = false; while (esm.hasMoreSubs()) { esm.getSubName(); uint32_t name = esm.retSubName().val; switch (name) { + case ESM::FourCC<'N','A','M','E'>::value: + mId = esm.getHString(); + hasName = true; + break; + case ESM::FourCC<'D','E','L','E'>::value: + esm.skipHSub(); + mIsDeleted = true; + break; case ESM::FourCC<'M','O','D','L'>::value: mModel = esm.getHString(); break; @@ -44,16 +48,21 @@ namespace ESM break; default: esm.fail("Unknown subrecord"); + break; } } + + if (!hasName) + esm.fail("Missing NAME subrecord"); } void Door::save(ESMWriter &esm) const { esm.writeHNCString("NAME", mId); + if (mIsDeleted) { - writeDeleSubRecord(esm); + esm.writeHNCString("DELE", ""); return; } diff --git a/components/esm/loadench.cpp b/components/esm/loadench.cpp index 1518e0385..0e480c379 100644 --- a/components/esm/loadench.cpp +++ b/components/esm/loadench.cpp @@ -3,7 +3,6 @@ #include "esmreader.hpp" #include "esmwriter.hpp" #include "defs.hpp" -#include "util.hpp" namespace ESM { @@ -16,13 +15,9 @@ namespace ESM void Enchantment::load(ESMReader &esm) { mEffects.mList.clear(); + mIsDeleted = false; - mId = esm.getHNString("NAME"); - if (mIsDeleted = readDeleSubRecord(esm)) - { - return; - } - + bool hasName = false; bool hasData = false; while (esm.hasMoreSubs()) { @@ -30,6 +25,14 @@ namespace ESM uint32_t name = esm.retSubName().val; switch (name) { + case ESM::FourCC<'N','A','M','E'>::value: + mId = esm.getHString(); + hasName = true; + break; + case ESM::FourCC<'D','E','L','E'>::value: + esm.skipHSub(); + mIsDeleted = true; + break; case ESM::FourCC<'E','N','D','T'>::value: esm.getHT(mData, 16); hasData = true; @@ -42,16 +45,20 @@ namespace ESM break; } } - if (!hasData) + + if (!hasName) + esm.fail("Missing NAME subrecord"); + if (!hasData && !mIsDeleted) esm.fail("Missing ENDT subrecord"); } void Enchantment::save(ESMWriter &esm) const { esm.writeHNCString("NAME", mId); + if (mIsDeleted) { - writeDeleSubRecord(esm); + esm.writeHNCString("DELE", ""); return; } diff --git a/components/esm/loadfact.cpp b/components/esm/loadfact.cpp index 53f3aa5a6..8538b0b95 100644 --- a/components/esm/loadfact.cpp +++ b/components/esm/loadfact.cpp @@ -5,7 +5,6 @@ #include "esmreader.hpp" #include "esmwriter.hpp" #include "defs.hpp" -#include "util.hpp" namespace ESM { @@ -33,17 +32,13 @@ namespace ESM void Faction::load(ESMReader &esm) { + mIsDeleted = false; mReactions.clear(); for (int i=0;i<10;++i) mRanks[i].clear(); - mId = esm.getHNString("NAME"); - if (mIsDeleted = readDeleSubRecord(esm)) - { - return; - } - - int rankCounter=0; + int rankCounter = 0; + bool hasName = false; bool hasData = false; while (esm.hasMoreSubs()) { @@ -51,6 +46,14 @@ namespace ESM uint32_t name = esm.retSubName().val; switch (name) { + case ESM::FourCC<'N','A','M','E'>::value: + mId = esm.getHString(); + hasName = true; + break; + case ESM::FourCC<'D','E','L','E'>::value: + esm.skipHSub(); + mIsDeleted = true; + break; case ESM::FourCC<'F','N','A','M'>::value: mName = esm.getHString(); break; @@ -75,18 +78,23 @@ namespace ESM } default: esm.fail("Unknown subrecord"); + break; } } - if (!hasData) + + if (!hasName) + esm.fail("Missing NAME subrecord"); + if (!hasData && !mIsDeleted) esm.fail("Missing FADT subrecord"); } void Faction::save(ESMWriter &esm) const { esm.writeHNCString("NAME", mId); + if (mIsDeleted) { - writeDeleSubRecord(esm); + esm.writeHNCString("DELE", ""); return; } diff --git a/components/esm/loadglob.cpp b/components/esm/loadglob.cpp index 392df02b5..5f96aff1f 100644 --- a/components/esm/loadglob.cpp +++ b/components/esm/loadglob.cpp @@ -3,7 +3,6 @@ #include "esmreader.hpp" #include "esmwriter.hpp" #include "defs.hpp" -#include "util.hpp" namespace ESM { @@ -15,30 +14,38 @@ namespace ESM void Global::load (ESMReader &esm) { - mId = esm.getHNString("NAME"); - if (mIsDeleted = readDeleSubRecord(esm)) + mIsDeleted = false; + mId = esm.getHNString ("NAME"); + + if (esm.isNextSub ("DELE")) { - return; + esm.skipHSub(); + mIsDeleted = true; + } + else + { + mValue.read (esm, ESM::Variant::Format_Global); } - - mValue.read (esm, ESM::Variant::Format_Global); } void Global::save (ESMWriter &esm) const { - esm.writeHNCString("NAME", mId); + esm.writeHNCString ("NAME", mId); + if (mIsDeleted) { - writeDeleSubRecord(esm); - return; + esm.writeHNCString ("DELE", ""); + } + else + { + mValue.write (esm, ESM::Variant::Format_Global); } - - mValue.write (esm, ESM::Variant::Format_Global); } void Global::blank() { mValue.setType (ESM::VT_None); + mIsDeleted = false; } bool operator== (const Global& left, const Global& right) diff --git a/components/esm/loadinfo.cpp b/components/esm/loadinfo.cpp index 8f5f0f28b..89fd4e0cd 100644 --- a/components/esm/loadinfo.cpp +++ b/components/esm/loadinfo.cpp @@ -3,14 +3,15 @@ #include "esmreader.hpp" #include "esmwriter.hpp" #include "defs.hpp" -#include "util.hpp" namespace ESM { unsigned int DialInfo::sRecordId = REC_INFO; DialInfo::DialInfo() - : mIsDeleted(false) + : mFactionLess(false), + mQuestStatus(QS_None), + mIsDeleted(false) {} void DialInfo::load(ESMReader &esm) @@ -29,6 +30,7 @@ namespace ESM { mQuestStatus = QS_None; mFactionLess = false; + mIsDeleted = false; mPrev = esm.getHNString("PNAM"); mNext = esm.getHNString("NNAM"); @@ -36,118 +38,77 @@ namespace ESM // Since there's no way to mark selects as "deleted", we have to clear the SelectStructs from all previous loadings mSelects.clear(); - // If the info is deleted, NAME and DELE sub-records are followed after NNAM - if (esm.isNextSub("NAME")) - { - mResponse = esm.getHString(); - mIsDeleted = readDeleSubRecord(esm); - return; - } - - esm.getSubNameIs("DATA"); - esm.getHT(mData, 12); - - if (!esm.hasMoreSubs()) - return; - - // What follows is somewhat spaghetti-ish, but it's worth if for - // an extra speedup. INFO is by far the most common record type. - - // subName is a reference to the original, so it changes whenever - // a new sub name is read. esm.isEmptyOrGetName() will get the - // next name for us, or return true if there are no more records. - esm.getSubName(); - const NAME &subName = esm.retSubName(); - - if (subName.val == REC_ONAM) - { - mActor = esm.getHString(); - if (esm.isEmptyOrGetName()) - return; - } - if (subName.val == REC_RNAM) - { - mRace = esm.getHString(); - if (esm.isEmptyOrGetName()) - return; - } - if (subName.val == REC_CNAM) - { - mClass = esm.getHString(); - if (esm.isEmptyOrGetName()) - return; - } - - if (subName.val == REC_FNAM) - { - mFaction = esm.getHString(); - if (mFaction == "FFFF") - mFactionLess = true; - if (esm.isEmptyOrGetName()) - return; - } - if (subName.val == REC_ANAM) - { - mCell = esm.getHString(); - if (esm.isEmptyOrGetName()) - return; - } - if (subName.val == REC_DNAM) - { - mPcFaction = esm.getHString(); - if (esm.isEmptyOrGetName()) - return; - } - if (subName.val == REC_SNAM) - { - mSound = esm.getHString(); - if (esm.isEmptyOrGetName()) - return; - } - if (subName.val == REC_NAME) - { - mResponse = esm.getHString(); - if (esm.isEmptyOrGetName()) - return; - } - - while (subName.val == REC_SCVR) + while (esm.hasMoreSubs()) { - SelectStruct ss; - - ss.mSelectRule = esm.getHString(); - - ss.mValue.read (esm, Variant::Format_Info); - - mSelects.push_back(ss); - - if (esm.isEmptyOrGetName()) - return; + esm.getSubName(); + uint32_t name = 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: + esm.getHT(mData, 12); + break; + case ESM::FourCC<'O','N','A','M'>::value: + mActor = esm.getHString(); + break; + case ESM::FourCC<'R','N','A','M'>::value: + mRace = esm.getHString(); + break; + case ESM::FourCC<'C','N','A','M'>::value: + mClass = esm.getHString(); + break; + case ESM::FourCC<'F','N','A','M'>::value: + { + mFaction = esm.getHString(); + if (mFaction == "FFFF") + { + mFactionLess = true; + } + break; + } + case ESM::FourCC<'A','N','A','M'>::value: + mCell = esm.getHString(); + break; + case ESM::FourCC<'D','N','A','M'>::value: + mPcFaction = esm.getHString(); + break; + case ESM::FourCC<'S','N','A','M'>::value: + mSound = esm.getHString(); + break; + case ESM::FourCC<'N','A','M','E'>::value: + mResponse = esm.getHString(); + break; + case ESM::FourCC<'S','C','V','R'>::value: + { + SelectStruct ss; + ss.mSelectRule = esm.getHString(); + ss.mValue.read(esm, Variant::Format_Info); + mSelects.push_back(ss); + break; + } + case ESM::FourCC<'B','N','A','M'>::value: + mResultScript = esm.getHString(); + break; + case ESM::FourCC<'Q','S','T','N'>::value: + mQuestStatus = QS_Name; + esm.skipRecord(); + break; + case ESM::FourCC<'Q','S','T','F'>::value: + mQuestStatus = QS_Finished; + esm.skipRecord(); + break; + case ESM::FourCC<'Q','S','T','R'>::value: + mQuestStatus = QS_Restart; + esm.skipRecord(); + break; + default: + esm.fail("Unknown subrecord"); + break; + } } - - if (subName.val == REC_BNAM) - { - mResultScript = esm.getHString(); - if (esm.isEmptyOrGetName()) - return; - } - - if (subName.val == REC_QSTN) - mQuestStatus = QS_Name; - else if (subName.val == REC_QSTF) - mQuestStatus = QS_Finished; - else if (subName.val == REC_QSTR) - mQuestStatus = QS_Restart; - else if (subName.val == REC_DELE) - mQuestStatus = QS_Deleted; - else - esm.fail( - "Don't know what to do with " + subName.toString() - + " in INFO " + mId); - - if (mQuestStatus != QS_None) - // Skip rest of record - esm.skipRecord(); } void DialInfo::save(ESMWriter &esm) const @@ -158,8 +119,7 @@ namespace ESM if (mIsDeleted) { - esm.writeHNCString("NAME", mResponse); - writeDeleSubRecord(esm); + esm.writeHNCString("DELE", ""); return; } @@ -186,7 +146,6 @@ namespace ESM case QS_Name: esm.writeHNT("QSTN",'\1'); break; case QS_Finished: esm.writeHNT("QSTF", '\1'); break; case QS_Restart: esm.writeHNT("QSTR", '\1'); break; - case QS_Deleted: esm.writeHNT("DELE", '\1'); break; default: break; } } diff --git a/components/esm/loadinfo.hpp b/components/esm/loadinfo.hpp index c243cd50e..65363d1be 100644 --- a/components/esm/loadinfo.hpp +++ b/components/esm/loadinfo.hpp @@ -59,8 +59,7 @@ struct DialInfo QS_None = 0, QS_Name = 1, QS_Finished = 2, - QS_Restart = 3, - QS_Deleted + QS_Restart = 3 }; // Rules for when to include this item in the final list of options diff --git a/components/esm/loadingr.cpp b/components/esm/loadingr.cpp index a7018b36d..51a1f4805 100644 --- a/components/esm/loadingr.cpp +++ b/components/esm/loadingr.cpp @@ -3,7 +3,6 @@ #include "esmreader.hpp" #include "esmwriter.hpp" #include "defs.hpp" -#include "util.hpp" namespace ESM { @@ -15,12 +14,9 @@ namespace ESM void Ingredient::load(ESMReader &esm) { - mId = esm.getHNString("NAME"); - if (mIsDeleted = readDeleSubRecord(esm)) - { - return; - } + mIsDeleted = false; + bool hasName = false; bool hasData = false; while (esm.hasMoreSubs()) { @@ -28,6 +24,14 @@ namespace ESM uint32_t name = esm.retSubName().val; switch (name) { + case ESM::FourCC<'N','A','M','E'>::value: + mId = esm.getHString(); + hasName = true; + break; + case ESM::FourCC<'D','E','L','E'>::value: + esm.skipHSub(); + mIsDeleted = true; + break; case ESM::FourCC<'M','O','D','L'>::value: mModel = esm.getHString(); break; @@ -46,10 +50,13 @@ namespace ESM break; default: esm.fail("Unknown subrecord"); + break; } } - if (!hasData) + if (!hasName) + esm.fail("Missing NAME subrecord"); + if (!hasData && !mIsDeleted) esm.fail("Missing IRDT subrecord"); // horrible hack to fix broken data in records @@ -79,9 +86,10 @@ namespace ESM void Ingredient::save(ESMWriter &esm) const { esm.writeHNCString("NAME", mId); + if (mIsDeleted) { - writeDeleSubRecord(esm); + esm.writeHNCString("DELE", ""); return; } diff --git a/components/esm/loadlevlist.cpp b/components/esm/loadlevlist.cpp index 1e07086bc..9c34ef657 100644 --- a/components/esm/loadlevlist.cpp +++ b/components/esm/loadlevlist.cpp @@ -3,7 +3,6 @@ #include "esmreader.hpp" #include "esmwriter.hpp" #include "defs.hpp" -#include "util.hpp" namespace ESM { @@ -13,49 +12,67 @@ namespace ESM void LevelledListBase::load(ESMReader &esm) { - mId = esm.getHNString("NAME"); - if (mIsDeleted = readDeleSubRecord(esm)) - { - return; - } - - esm.getHNT(mFlags, "DATA"); - esm.getHNT(mChanceNone, "NNAM"); + mIsDeleted = false; - if (esm.isNextSub("INDX")) - { - int len; - esm.getHT(len); - mList.resize(len); - } - else + bool hasName = false; + while (esm.hasMoreSubs()) { - // Original engine ignores rest of the record, even if there are items following - mList.clear(); - esm.skipRecord(); - return; - } + esm.getSubName(); + uint32_t name = esm.retSubName().val; + switch (name) + { + case ESM::FourCC<'N','A','M','E'>::value: + mId = esm.getHString(); + hasName = true; + break; + case ESM::FourCC<'D','E','L','E'>::value: + esm.skipHSub(); + mIsDeleted = true; + break; + case ESM::FourCC<'D','A','T','A'>::value: + esm.getHT(mFlags); + break; + case ESM::FourCC<'N','N','A','M'>::value: + esm.getHT(mChanceNone); + break; + case ESM::FourCC<'I','N','D','X'>::value: + { + int length = 0; + esm.getHT(length); + mList.resize(length); - // If this levelled list was already loaded by a previous content file, - // we overwrite the list. Merging lists should probably be left to external tools, - // with the limited amount of information there is in the records, all merging methods - // will be flawed in some way. For a proper fix the ESM format would have to be changed - // to actually track list changes instead of including the whole list for every file - // that does something with that list. - - for (size_t i = 0; i < mList.size(); i++) - { - LevelItem &li = mList[i]; - li.mId = esm.getHNString(mRecName); - esm.getHNT(li.mLevel, "INTV"); + // If this levelled list was already loaded by a previous content file, + // we overwrite the list. Merging lists should probably be left to external tools, + // with the limited amount of information there is in the records, all merging methods + // will be flawed in some way. For a proper fix the ESM format would have to be changed + // to actually track list changes instead of including the whole list for every file + // that does something with that list. + for (size_t i = 0; i < mList.size(); i++) + { + LevelItem &li = mList[i]; + li.mId = esm.getHNString(mRecName); + esm.getHNT(li.mLevel, "INTV"); + } + break; + } + default: + mList.clear(); + esm.skipRecord(); + break; + } } + + if (!hasName) + esm.fail("Missing NAME subrecord"); } + void LevelledListBase::save(ESMWriter &esm) const { esm.writeHNCString("NAME", mId); + if (mIsDeleted) { - writeDeleSubRecord(esm); + esm.writeHNCString("DELE", ""); return; } diff --git a/components/esm/loadligh.cpp b/components/esm/loadligh.cpp index a153d500a..441e96d0a 100644 --- a/components/esm/loadligh.cpp +++ b/components/esm/loadligh.cpp @@ -3,7 +3,6 @@ #include "esmreader.hpp" #include "esmwriter.hpp" #include "defs.hpp" -#include "util.hpp" namespace ESM { @@ -15,12 +14,9 @@ namespace ESM void Light::load(ESMReader &esm) { - mId = esm.getHNString("NAME"); - if (mIsDeleted = readDeleSubRecord(esm)) - { - return; - } + mIsDeleted = false; + bool hasName = false; bool hasData = false; while (esm.hasMoreSubs()) { @@ -28,6 +24,14 @@ namespace ESM uint32_t name = esm.retSubName().val; switch (name) { + case ESM::FourCC<'N','A','M','E'>::value: + mId = esm.getHString(); + hasName = true; + break; + case ESM::FourCC<'D','E','L','E'>::value: + esm.skipHSub(); + mIsDeleted = true; + break; case ESM::FourCC<'M','O','D','L'>::value: mModel = esm.getHString(); break; @@ -49,17 +53,22 @@ namespace ESM break; default: esm.fail("Unknown subrecord"); + break; } } - if (!hasData) + + if (!hasName) + esm.fail("Missing NAME subrecord"); + if (!hasData && !mIsDeleted) esm.fail("Missing LHDT subrecord"); } void Light::save(ESMWriter &esm) const { esm.writeHNCString("NAME", mId); + if (mIsDeleted) { - writeDeleSubRecord(esm); + esm.writeHNCString("DELE", ""); return; } diff --git a/components/esm/loadlock.cpp b/components/esm/loadlock.cpp index 3b169af33..5ee041dab 100644 --- a/components/esm/loadlock.cpp +++ b/components/esm/loadlock.cpp @@ -3,7 +3,6 @@ #include "esmreader.hpp" #include "esmwriter.hpp" #include "defs.hpp" -#include "util.hpp" namespace ESM { @@ -15,19 +14,23 @@ namespace ESM void Lockpick::load(ESMReader &esm) { - mId = esm.getHNString("NAME"); - if (mIsDeleted = readDeleSubRecord(esm)) - { - return; - } + mIsDeleted = false; - bool hasData = true; + bool hasName = false; + bool hasData = false; while (esm.hasMoreSubs()) { esm.getSubName(); uint32_t name = esm.retSubName().val; switch (name) { + case ESM::FourCC<'N','A','M','E'>::value: + mId = esm.getHString(); + break; + case ESM::FourCC<'D','E','L','E'>::value: + esm.skipHSub(); + mIsDeleted = true; + break; case ESM::FourCC<'M','O','D','L'>::value: mModel = esm.getHString(); break; @@ -46,18 +49,23 @@ namespace ESM break; default: esm.fail("Unknown subrecord"); + break; } } - if (!hasData) + + if (!hasName) + esm.fail("Missing NAME subrecord"); + if (!hasData && !mIsDeleted) esm.fail("Missing LKDT subrecord"); } void Lockpick::save(ESMWriter &esm) const { esm.writeHNCString("NAME", mId); + if (mIsDeleted) { - writeDeleSubRecord(esm); + esm.writeHNCString("DELE", ""); return; } diff --git a/components/esm/loadltex.cpp b/components/esm/loadltex.cpp index 13315e684..7c14536ed 100644 --- a/components/esm/loadltex.cpp +++ b/components/esm/loadltex.cpp @@ -3,7 +3,6 @@ #include "esmreader.hpp" #include "esmwriter.hpp" #include "defs.hpp" -#include "util.hpp" namespace ESM { @@ -15,17 +14,49 @@ namespace ESM void LandTexture::load(ESMReader &esm) { - mIsDeleted = readDeleSubRecord(esm); - mId = esm.getHNString("NAME"); - esm.getHNT(mIndex, "INTV"); - mTexture = esm.getHNString("DATA"); + mIsDeleted = false; + + bool hasName = false; + bool hasIndex = false; + while (esm.hasMoreSubs()) + { + esm.getSubName(); + uint32_t name = esm.retSubName().val; + switch (name) + { + case ESM::FourCC<'N','A','M','E'>::value: + mId = esm.getHString(); + hasName = false; + break; + case ESM::FourCC<'D','E','L','E'>::value: + esm.skipHSub(); + mIsDeleted = true; + break; + case ESM::FourCC<'I','N','T','V'>::value: + esm.getHT(mIndex); + hasIndex = true; + break; + case ESM::FourCC<'D','A','T','A'>::value: + mTexture = esm.getHString(); + break; + default: + esm.fail("Unknown subrecord"); + break; + } + } + + if (!hasName) + esm.fail("Missing NAME subrecord"); + if (!hasIndex) + esm.fail("Missing INTV subrecord"); } void LandTexture::save(ESMWriter &esm) const { if (mIsDeleted) { - writeDeleSubRecord(esm); + esm.writeHNCString("DELE", ""); } + esm.writeHNCString("NAME", mId); esm.writeHNT("INTV", mIndex); esm.writeHNCString("DATA", mTexture); diff --git a/components/esm/loadmisc.cpp b/components/esm/loadmisc.cpp index 08cbcf741..de9ccdd6a 100644 --- a/components/esm/loadmisc.cpp +++ b/components/esm/loadmisc.cpp @@ -3,7 +3,6 @@ #include "esmreader.hpp" #include "esmwriter.hpp" #include "defs.hpp" -#include "util.hpp" namespace ESM { @@ -15,12 +14,9 @@ namespace ESM void Miscellaneous::load(ESMReader &esm) { - mId = esm.getHNString("NAME"); - if (mIsDeleted = readDeleSubRecord(esm)) - { - return; - } + mIsDeleted = false; + bool hasName = false; bool hasData = false; while (esm.hasMoreSubs()) { @@ -28,6 +24,14 @@ namespace ESM uint32_t name = esm.retSubName().val; switch (name) { + case ESM::FourCC<'N','A','M','E'>::value: + mId = esm.getHString(); + hasName = true; + break; + case ESM::FourCC<'D','E','L','E'>::value: + esm.skipHSub(); + mIsDeleted = true; + break; case ESM::FourCC<'M','O','D','L'>::value: mModel = esm.getHString(); break; @@ -44,18 +48,25 @@ namespace ESM case ESM::FourCC<'I','T','E','X'>::value: mIcon = esm.getHString(); break; + default: + esm.fail("Unknown subrecord"); + break; } } - if (!hasData) + + if (!hasName) + esm.fail("Missing NAME subrecord"); + if (!hasData && !mIsDeleted) esm.fail("Missing MCDT subrecord"); } void Miscellaneous::save(ESMWriter &esm) const { esm.writeHNCString("NAME", mId); + if (mIsDeleted) { - writeDeleSubRecord(esm); + esm.writeHNCString("DELE", ""); return; } diff --git a/components/esm/loadnpc.cpp b/components/esm/loadnpc.cpp index eadf23a21..ff3213ee9 100644 --- a/components/esm/loadnpc.cpp +++ b/components/esm/loadnpc.cpp @@ -3,40 +3,45 @@ #include "esmreader.hpp" #include "esmwriter.hpp" #include "defs.hpp" -#include "util.hpp" namespace ESM { unsigned int NPC::sRecordId = REC_NPC_; NPC::NPC() - : mIsDeleted(false) + : mFlags(0), + mHasAI(false), + mIsDeleted(false) {} void NPC::load(ESMReader &esm) { + mIsDeleted = false; mPersistent = (esm.getRecordFlags() & 0x0400) != 0; mSpells.mList.clear(); mInventory.mList.clear(); mTransport.mList.clear(); mAiPackage.mList.clear(); + mHasAI = false; - mId = esm.getHNString("NAME"); - if (mIsDeleted = readDeleSubRecord(esm)) - { - return; - } - + bool hasName = false; bool hasNpdt = false; bool hasFlags = false; - mHasAI = false; while (esm.hasMoreSubs()) { esm.getSubName(); uint32_t name = esm.retSubName().val; switch (name) { + case ESM::FourCC<'N','A','M','E'>::value: + mId = esm.getHString(); + hasName = true; + break; + case ESM::FourCC<'D','E','L','E'>::value: + esm.skipHSub(); + mIsDeleted = true; + break; case ESM::FourCC<'M','O','D','L'>::value: mModel = esm.getHString(); break; @@ -105,19 +110,24 @@ namespace ESM break; default: esm.fail("Unknown subrecord"); + break; } } - if (!hasNpdt) + + if (!hasName) + esm.fail("Missing NAME subrecord"); + if (!hasNpdt && !mIsDeleted) esm.fail("Missing NPDT subrecord"); - if (!hasFlags) + if (!hasFlags && !mIsDeleted) esm.fail("Missing FLAG subrecord"); } void NPC::save(ESMWriter &esm) const { esm.writeHNCString("NAME", mId); + if (mIsDeleted) { - writeDeleSubRecord(esm); + esm.writeHNCString("DELE", ""); return; } diff --git a/components/esm/loadprob.cpp b/components/esm/loadprob.cpp index f5287f986..4ce9b9d9c 100644 --- a/components/esm/loadprob.cpp +++ b/components/esm/loadprob.cpp @@ -3,7 +3,6 @@ #include "esmreader.hpp" #include "esmwriter.hpp" #include "defs.hpp" -#include "util.hpp" namespace ESM { @@ -15,19 +14,24 @@ namespace ESM void Probe::load(ESMReader &esm) { - mId = esm.getHNString("NAME"); - if (mIsDeleted = readDeleSubRecord(esm)) - { - return; - } + mIsDeleted = false; - bool hasData = true; + bool hasName = false; + bool hasData = false; while (esm.hasMoreSubs()) { esm.getSubName(); uint32_t name = esm.retSubName().val; switch (name) { + case ESM::FourCC<'N','A','M','E'>::value: + mId = esm.getHString(); + hasName = true; + break; + case ESM::FourCC<'D','E','L','E'>::value: + esm.skipHSub(); + mIsDeleted = true; + break; case ESM::FourCC<'M','O','D','L'>::value: mModel = esm.getHString(); break; @@ -46,18 +50,23 @@ namespace ESM break; default: esm.fail("Unknown subrecord"); + break; } } - if (!hasData) + + if (!hasName) + esm.fail("Missing NAME subrecord"); + if (!hasData && !mIsDeleted) esm.fail("Missing PBDT subrecord"); } void Probe::save(ESMWriter &esm) const { esm.writeHNCString("NAME", mId); + if (mIsDeleted) { - writeDeleSubRecord(esm); + esm.writeHNCString("DELE", ""); return; } diff --git a/components/esm/loadregn.cpp b/components/esm/loadregn.cpp index 2d99947b0..b48ffa4b7 100644 --- a/components/esm/loadregn.cpp +++ b/components/esm/loadregn.cpp @@ -3,64 +3,95 @@ #include "esmreader.hpp" #include "esmwriter.hpp" #include "defs.hpp" -#include "util.hpp" namespace ESM { unsigned int Region::sRecordId = REC_REGN; Region::Region() - : mIsDeleted(false) + : mMapColor(0), + mIsDeleted(false) {} void Region::load(ESMReader &esm) { - mIsDeleted = readDeleSubRecord(esm); - mId = esm.getHNString("NAME"); - mName = esm.getHNOString("FNAM"); + mIsDeleted = false; - esm.getSubNameIs("WEAT"); - esm.getSubHeader(); - if (esm.getVer() == VER_12) - { - mData.mA = 0; - mData.mB = 0; - esm.getExact(&mData, sizeof(mData) - 2); - } - else if (esm.getVer() == VER_13) + bool hasName = false; + while (esm.hasMoreSubs()) { - // May include the additional two bytes (but not necessarily) - if (esm.getSubSize() == sizeof(mData)) - esm.getExact(&mData, sizeof(mData)); - else + esm.getSubName(); + uint32_t name = esm.retSubName().val; + switch (name) { - mData.mA = 0; - mData.mB = 0; - esm.getExact(&mData, sizeof(mData)-2); + case ESM::FourCC<'N','A','M','E'>::value: + mId = esm.getHString(); + hasName = true; + break; + case ESM::FourCC<'D','E','L','E'>::value: + esm.skipHSub(); + mIsDeleted = true; + break; + case ESM::FourCC<'F','N','A','M'>::value: + mName = esm.getHString(); + break; + case ESM::FourCC<'W','E','A','T'>::value: + { + esm.getSubHeader(); + if (esm.getVer() == VER_12) + { + mData.mA = 0; + mData.mB = 0; + esm.getExact(&mData, sizeof(mData) - 2); + } + else if (esm.getVer() == VER_13) + { + // May include the additional two bytes (but not necessarily) + if (esm.getSubSize() == sizeof(mData)) + { + esm.getExact(&mData, sizeof(mData)); + } + else + { + mData.mA = 0; + mData.mB = 0; + esm.getExact(&mData, sizeof(mData)-2); + } + } + else + { + esm.fail("Don't know what to do in this version"); + } + break; + } + case ESM::FourCC<'B','N','A','M'>::value: + mSleepList = esm.getHString(); + break; + case ESM::FourCC<'C','N','A','M'>::value: + esm.getHT(mMapColor); + break; + case ESM::FourCC<'S','N','A','M'>::value: + SoundRef sr; + esm.getHT(sr, 33); + mSoundList.push_back(sr); + break; + default: + esm.fail("Unknown subrecord"); + break; } } - else - esm.fail("Don't know what to do in this version"); - - mSleepList = esm.getHNOString("BNAM"); - esm.getHNT(mMapColor, "CNAM"); - - mSoundList.clear(); - while (esm.hasMoreSubs()) - { - SoundRef sr; - esm.getHNT(sr, "SNAM", 33); - mSoundList.push_back(sr); - } + if (!hasName) + esm.fail("Missing NAME subrecord"); } void Region::save(ESMWriter &esm) const { if (mIsDeleted) { - writeDeleSubRecord(esm); + esm.writeHNCString("DELE", ""); } + esm.writeHNString("NAME", mId); esm.writeHNOCString("FNAM", mName); diff --git a/components/esm/loadrepa.cpp b/components/esm/loadrepa.cpp index fb213efd8..74e682d63 100644 --- a/components/esm/loadrepa.cpp +++ b/components/esm/loadrepa.cpp @@ -3,7 +3,6 @@ #include "esmreader.hpp" #include "esmwriter.hpp" #include "defs.hpp" -#include "util.hpp" namespace ESM { @@ -15,19 +14,24 @@ namespace ESM void Repair::load(ESMReader &esm) { - mId = esm.getHNString("NAME"); - if (mIsDeleted = readDeleSubRecord(esm)) - { - return; - } + mIsDeleted = false; - bool hasData = true; + bool hasName = false; + bool hasData = false; while (esm.hasMoreSubs()) { esm.getSubName(); uint32_t name = esm.retSubName().val; switch (name) { + case ESM::FourCC<'N','A','M','E'>::value: + mId = esm.getHString(); + hasName = true; + break; + case ESM::FourCC<'D','E','L','E'>::value: + esm.skipHSub(); + mIsDeleted = true; + break; case ESM::FourCC<'M','O','D','L'>::value: mModel = esm.getHString(); break; @@ -46,18 +50,23 @@ namespace ESM break; default: esm.fail("Unknown subrecord"); + break; } } - if (!hasData) + + if (!hasName) + esm.fail("Missing NAME subrecord"); + if (!hasData && !mIsDeleted) esm.fail("Missing RIDT subrecord"); } void Repair::save(ESMWriter &esm) const { esm.writeHNCString("NAME", mId); + if (mIsDeleted) { - writeDeleSubRecord(esm); + esm.writeHNCString("DELE", ""); return; } diff --git a/components/esm/loadscpt.cpp b/components/esm/loadscpt.cpp index 529f0a66d..333389ba4 100644 --- a/components/esm/loadscpt.cpp +++ b/components/esm/loadscpt.cpp @@ -3,7 +3,6 @@ #include "esmreader.hpp" #include "esmwriter.hpp" #include "defs.hpp" -#include "util.hpp" #include @@ -64,23 +63,27 @@ namespace ESM void Script::load(ESMReader &esm) { - SCHD data; - esm.getHNT(data, "SCHD", 52); - mData = data.mData; - mId = data.mName.toString(); - - // In scripts DELE sub-record appears after a header. - // The script data is following after DELE in this case. - mIsDeleted = readDeleSubRecord(esm); - mVarNames.clear(); + mIsDeleted = false; + bool hasHeader = false; while (esm.hasMoreSubs()) { esm.getSubName(); uint32_t name = esm.retSubName().val; switch (name) { + case ESM::FourCC<'S','C','H','D'>::value: + SCHD data; + esm.getHT(data, 52); + mData = data.mData; + mId = data.mName.toString(); + hasHeader = true; + break; + case ESM::FourCC<'D','E','L','E'>::value: + esm.skipHSub(); + mIsDeleted = true; + break; case ESM::FourCC<'S','C','V','R'>::value: // list of local variables loadSCVR(esm); @@ -95,8 +98,12 @@ namespace ESM break; default: esm.fail("Unknown subrecord"); + break; } } + + if (!hasHeader) + esm.fail("Missing SCHD subrecord"); } void Script::save(ESMWriter &esm) const @@ -116,7 +123,7 @@ namespace ESM if (mIsDeleted) { - writeDeleSubRecord(esm); + esm.writeHNCString("DELE", ""); } if (!mVarNames.empty()) diff --git a/components/esm/loadsndg.cpp b/components/esm/loadsndg.cpp index 261087be0..a20e6ee51 100644 --- a/components/esm/loadsndg.cpp +++ b/components/esm/loadsndg.cpp @@ -3,24 +3,21 @@ #include "esmreader.hpp" #include "esmwriter.hpp" #include "defs.hpp" -#include "util.hpp" namespace ESM { unsigned int SoundGenerator::sRecordId = REC_SNDG; SoundGenerator::SoundGenerator() - : mIsDeleted(false) + : mType(LeftFoot), + mIsDeleted(false) {} void SoundGenerator::load(ESMReader &esm) { - mId = esm.getHNString("NAME"); - if (mIsDeleted = readDeleSubRecord(esm)) - { - return; - } + mIsDeleted = false; + bool hasName = false; bool hasData = false; while (esm.hasMoreSubs()) { @@ -28,6 +25,14 @@ namespace ESM uint32_t name = esm.retSubName().val; switch (name) { + case ESM::FourCC<'N','A','M','E'>::value: + mId = esm.getHString(); + hasName = true; + break; + case ESM::FourCC<'D','E','L','E'>::value: + esm.skipHSub(); + mIsDeleted = true; + break; case ESM::FourCC<'D','A','T','A'>::value: esm.getHT(mType, 4); hasData = true; @@ -40,23 +45,26 @@ namespace ESM break; default: esm.fail("Unknown subrecord"); + break; } } - if (!hasData) - esm.fail("Missing DATA"); + + if (!hasName) + esm.fail("Missing NAME subrecord"); + if (!hasData && !mIsDeleted) + esm.fail("Missing DATA subrecord"); } void SoundGenerator::save(ESMWriter &esm) const { esm.writeHNCString("NAME", mId); - if (mIsDeleted) - { - writeDeleSubRecord(esm); - return; - } - esm.writeHNT("DATA", mType, 4); esm.writeHNOCString("CNAM", mCreature); esm.writeHNOCString("SNAM", mSound); + + if (mIsDeleted) + { + esm.writeHNCString("DELE", ""); + } } void SoundGenerator::blank() diff --git a/components/esm/loadsoun.cpp b/components/esm/loadsoun.cpp index 9a1a52b1e..55fe69292 100644 --- a/components/esm/loadsoun.cpp +++ b/components/esm/loadsoun.cpp @@ -3,7 +3,6 @@ #include "esmreader.hpp" #include "esmwriter.hpp" #include "defs.hpp" -#include "util.hpp" namespace ESM { @@ -15,12 +14,9 @@ namespace ESM void Sound::load(ESMReader &esm) { - mId = esm.getHNString("NAME"); - if (mIsDeleted = readDeleSubRecord(esm)) - { - return; - } + mIsDeleted = false; + bool hasName = false; bool hasData = false; while (esm.hasMoreSubs()) { @@ -28,6 +24,14 @@ namespace ESM uint32_t name = esm.retSubName().val; switch (name) { + case ESM::FourCC<'N','A','M','E'>::value: + mId = esm.getHString(); + hasName = true; + break; + case ESM::FourCC<'D','E','L','E'>::value: + esm.skipHSub(); + mIsDeleted = true; + break; case ESM::FourCC<'F','N','A','M'>::value: mSound = esm.getHString(); break; @@ -37,18 +41,23 @@ namespace ESM break; default: esm.fail("Unknown subrecord"); + break; } } - if (!hasData) - esm.fail("Missing DATA"); + + if (!hasName) + esm.fail("Missing NAME subrecord"); + if (!hasData && !mIsDeleted) + esm.fail("Missing DATA subrecord"); } void Sound::save(ESMWriter &esm) const { esm.writeHNCString("NAME", mId); + if (mIsDeleted) { - writeDeleSubRecord(esm); + esm.writeHNCString("DELE", ""); return; } diff --git a/components/esm/loadspel.cpp b/components/esm/loadspel.cpp index d2d8c7d6d..28feffd20 100644 --- a/components/esm/loadspel.cpp +++ b/components/esm/loadspel.cpp @@ -3,7 +3,6 @@ #include "esmreader.hpp" #include "esmwriter.hpp" #include "defs.hpp" -#include "util.hpp" namespace ESM { @@ -16,13 +15,9 @@ namespace ESM void Spell::load(ESMReader &esm) { mEffects.mList.clear(); + mIsDeleted = false; - mId = esm.getHNString("NAME"); - if (mIsDeleted = readDeleSubRecord(esm)) - { - return; - } - + bool hasName = false; bool hasData = false; while (esm.hasMoreSubs()) { @@ -31,6 +26,14 @@ namespace ESM switch (val) { + case ESM::FourCC<'N','A','M','E'>::value: + mId = esm.getHString(); + hasName = true; + break; + case ESM::FourCC<'D','E','L','E'>::value: + esm.skipHSub(); + mIsDeleted = true; + break; case ESM::FourCC<'F','N','A','M'>::value: mName = esm.getHString(); break; @@ -43,18 +46,25 @@ namespace ESM esm.getHT(s, 24); mEffects.mList.push_back(s); break; + default: + esm.fail("Unknown subrecord"); + break; } } - if (!hasData) + + if (!hasName) + esm.fail("Missing NAME subrecord"); + if (!hasData && !mIsDeleted) esm.fail("Missing SPDT subrecord"); } void Spell::save(ESMWriter &esm) const { esm.writeHNCString("NAME", mId); + if (mIsDeleted) { - writeDeleSubRecord(esm); + esm.writeHNCString("DELE", ""); return; } @@ -70,9 +80,7 @@ namespace ESM mData.mFlags = 0; mName.clear(); - mEffects.mList.clear(); - mIsDeleted = false; } } diff --git a/components/esm/loadstat.cpp b/components/esm/loadstat.cpp index 2fde46bd2..9a146a370 100644 --- a/components/esm/loadstat.cpp +++ b/components/esm/loadstat.cpp @@ -3,7 +3,6 @@ #include "esmreader.hpp" #include "esmwriter.hpp" #include "defs.hpp" -#include "util.hpp" namespace ESM { @@ -15,24 +14,46 @@ namespace ESM void Static::load(ESMReader &esm) { - mId = esm.getHNString("NAME"); - if (mIsDeleted = readDeleSubRecord(esm)) + mIsDeleted = false; + + bool hasName = false; + while (esm.hasMoreSubs()) { - return; + esm.getSubName(); + uint32_t name = esm.retSubName().val; + switch (name) + { + case ESM::FourCC<'N','A','M','E'>::value: + mId = esm.getHString(); + hasName = true; + break; + case ESM::FourCC<'D','E','L','E'>::value: + esm.skipHSub(); + mIsDeleted = true; + break; + case ESM::FourCC<'M','O','D','L'>::value: + mModel = esm.getHString(); + break; + default: + esm.fail("Unknown subrecord"); + break; + } } - mModel = esm.getHNString("MODL"); + if (!hasName) + esm.fail("Missing NAME subrecord"); } void Static::save(ESMWriter &esm) const { esm.writeHNCString("NAME", mId); if (mIsDeleted) { - writeDeleSubRecord(esm); - return; + esm.writeHNCString("DELE", ""); + } + else + { + esm.writeHNCString("MODL", mModel); } - - esm.writeHNCString("MODL", mModel); } void Static::blank() diff --git a/components/esm/loadweap.cpp b/components/esm/loadweap.cpp index 38fb94adb..98302c13d 100644 --- a/components/esm/loadweap.cpp +++ b/components/esm/loadweap.cpp @@ -3,7 +3,6 @@ #include "esmreader.hpp" #include "esmwriter.hpp" #include "defs.hpp" -#include "util.hpp" namespace ESM { @@ -15,12 +14,9 @@ namespace ESM void Weapon::load(ESMReader &esm) { - mId = esm.getHNString("NAME"); - if (mIsDeleted = readDeleSubRecord(esm)) - { - return; - } + mIsDeleted = false; + bool hasName = false; bool hasData = false; while (esm.hasMoreSubs()) { @@ -28,6 +24,14 @@ namespace ESM uint32_t name = esm.retSubName().val; switch (name) { + case ESM::FourCC<'N','A','M','E'>::value: + mId = esm.getHString(); + hasName = true; + break; + case ESM::FourCC<'D','E','L','E'>::value: + esm.skipHSub(); + mIsDeleted = true; + break; case ESM::FourCC<'M','O','D','L'>::value: mModel = esm.getHString(); break; @@ -51,15 +55,19 @@ namespace ESM esm.fail("Unknown subrecord"); } } - if (!hasData) + + if (!hasName) + esm.fail("Missing NAME subrecord"); + if (!hasData && !mIsDeleted) esm.fail("Missing WPDT subrecord"); } void Weapon::save(ESMWriter &esm) const { esm.writeHNCString("NAME", mId); + if (mIsDeleted) { - writeDeleSubRecord(esm); + esm.writeHNCString("DELE", ""); return; }