From e65ff723ce6e71da7d00e68820250682512418c1 Mon Sep 17 00:00:00 2001 From: Stanislav Bas Date: Thu, 16 Jul 2015 22:17:49 +0300 Subject: [PATCH] More ESM records have DELE handling. Changed records: Race, Land, Pathgrid, StartScript, DebugProfile, Filter --- components/esm/debugprofile.cpp | 45 +++- components/esm/debugprofile.hpp | 4 + components/esm/filter.cpp | 41 +++- components/esm/filter.hpp | 4 + components/esm/loadland.cpp | 393 +++++++++++++++++--------------- components/esm/loadland.hpp | 4 +- components/esm/loadpgrd.cpp | 194 +++++++++------- components/esm/loadpgrd.hpp | 4 + components/esm/loadrace.cpp | 96 +++++--- components/esm/loadrace.hpp | 4 + components/esm/loadsscr.cpp | 18 ++ components/esm/loadsscr.hpp | 4 + 12 files changed, 504 insertions(+), 307 deletions(-) diff --git a/components/esm/debugprofile.cpp b/components/esm/debugprofile.cpp index 9c8164d29..d1e27debc 100644 --- a/components/esm/debugprofile.cpp +++ b/components/esm/debugprofile.cpp @@ -7,17 +7,53 @@ unsigned int ESM::DebugProfile::sRecordId = REC_DBGP; +ESM::DebugProfile::DebugProfile() + : mIsDeleted(false) +{} + void ESM::DebugProfile::load (ESMReader& esm) { - mId = esm.getHNString ("NAME"); - mDescription = esm.getHNString ("DESC"); - mScriptText = esm.getHNString ("SCRP"); - esm.getHNT (mFlags, "FLAG"); + mIsDeleted = 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<'D','E','S','C'>::value: + mDescription = esm.getHString(); + break; + case ESM::FourCC<'S','C','R','P'>::value: + mScriptText = esm.getHString(); + break; + case ESM::FourCC<'F','L','A','G'>::value: + esm.getHT(mFlags); + break; + default: + esm.fail("Unknown subrecord"); + break; + } + } } void ESM::DebugProfile::save (ESMWriter& esm) const { esm.writeHNCString ("NAME", mId); + + if (mIsDeleted) + { + esm.writeHNCString("DELE", ""); + return; + } + esm.writeHNCString ("DESC", mDescription); esm.writeHNCString ("SCRP", mScriptText); esm.writeHNT ("FLAG", mFlags); @@ -28,4 +64,5 @@ void ESM::DebugProfile::blank() mDescription.clear(); mScriptText.clear(); mFlags = 0; + mIsDeleted = false; } diff --git a/components/esm/debugprofile.hpp b/components/esm/debugprofile.hpp index b54e8ff5f..1709136f5 100644 --- a/components/esm/debugprofile.hpp +++ b/components/esm/debugprofile.hpp @@ -27,6 +27,10 @@ namespace ESM unsigned int mFlags; + bool mIsDeleted; + + DebugProfile(); + void load (ESMReader& esm); void save (ESMWriter& esm) const; diff --git a/components/esm/filter.cpp b/components/esm/filter.cpp index ee2c67869..57cb59454 100644 --- a/components/esm/filter.cpp +++ b/components/esm/filter.cpp @@ -7,16 +7,50 @@ unsigned int ESM::Filter::sRecordId = REC_FILT; +ESM::Filter::Filter() + : mIsDeleted(false) +{} + void ESM::Filter::load (ESMReader& esm) { - mId = esm.getHNString ("NAME"); - mFilter = esm.getHNString ("FILT"); - mDescription = esm.getHNString ("DESC"); + mIsDeleted = 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<'F','I','L','T'>::value: + mFilter = esm.getHString(); + break; + case ESM::FourCC<'D','E','S','C'>::value: + mDescription = esm.getHString(); + break; + default: + esm.fail("Unknown subrecord"); + break; + } + } } void ESM::Filter::save (ESMWriter& esm) const { esm.writeHNCString ("NAME", mId); + + if (mIsDeleted) + { + esm.writeHNCString("DELE", ""); + return; + } + esm.writeHNCString ("FILT", mFilter); esm.writeHNCString ("DESC", mDescription); } @@ -25,4 +59,5 @@ void ESM::Filter::blank() { mFilter.clear(); mDescription.clear(); + mIsDeleted = false; } diff --git a/components/esm/filter.hpp b/components/esm/filter.hpp index bc3dd7bdc..1a8af9229 100644 --- a/components/esm/filter.hpp +++ b/components/esm/filter.hpp @@ -18,6 +18,10 @@ namespace ESM std::string mFilter; + bool mIsDeleted; + + Filter(); + void load (ESMReader& esm); void save (ESMWriter& esm) const; diff --git a/components/esm/loadland.cpp b/components/esm/loadland.cpp index b0897ec67..6acaa6e6a 100644 --- a/components/esm/loadland.cpp +++ b/components/esm/loadland.cpp @@ -8,211 +8,234 @@ namespace ESM { unsigned int Land::sRecordId = REC_LAND; -void Land::LandData::save(ESMWriter &esm) -{ - if (mDataTypes & Land::DATA_VNML) { - esm.writeHNT("VNML", mNormals, sizeof(mNormals)); - } - if (mDataTypes & Land::DATA_VHGT) { - VHGT offsets; - offsets.mHeightOffset = mHeights[0] / HEIGHT_SCALE; - offsets.mUnk1 = mUnk1; - offsets.mUnk2 = mUnk2; + void Land::LandData::save(ESMWriter &esm) + { + if (mDataTypes & Land::DATA_VNML) { + esm.writeHNT("VNML", mNormals, sizeof(mNormals)); + } + if (mDataTypes & Land::DATA_VHGT) { + VHGT offsets; + offsets.mHeightOffset = mHeights[0] / HEIGHT_SCALE; + offsets.mUnk1 = mUnk1; + offsets.mUnk2 = mUnk2; - float prevY = mHeights[0]; - int number = 0; // avoid multiplication - for (int i = 0; i < LAND_SIZE; ++i) { - float diff = (mHeights[number] - prevY) / HEIGHT_SCALE; - offsets.mHeightData[number] = - (diff >= 0) ? (int8_t) (diff + 0.5) : (int8_t) (diff - 0.5); - - float prevX = prevY = mHeights[number]; - ++number; - - for (int j = 1; j < LAND_SIZE; ++j) { - diff = (mHeights[number] - prevX) / HEIGHT_SCALE; + float prevY = mHeights[0]; + int number = 0; // avoid multiplication + for (int i = 0; i < LAND_SIZE; ++i) { + float diff = (mHeights[number] - prevY) / HEIGHT_SCALE; offsets.mHeightData[number] = (diff >= 0) ? (int8_t) (diff + 0.5) : (int8_t) (diff - 0.5); - prevX = mHeights[number]; + float prevX = prevY = mHeights[number]; ++number; - } - } - esm.writeHNT("VHGT", offsets, sizeof(VHGT)); - } - if (mDataTypes & Land::DATA_WNAM) { - esm.writeHNT("WNAM", mWnam, 81); - } - if (mDataTypes & Land::DATA_VCLR) { - esm.writeHNT("VCLR", mColours, 3*LAND_NUM_VERTS); - } - if (mDataTypes & Land::DATA_VTEX) { - static uint16_t vtex[LAND_NUM_TEXTURES]; - transposeTextureData(mTextures, vtex); - esm.writeHNT("VTEX", vtex, sizeof(vtex)); - } -} -void Land::LandData::transposeTextureData(uint16_t *in, uint16_t *out) -{ - int readPos = 0; //bit ugly, but it works - for ( int y1 = 0; y1 < 4; y1++ ) - for ( int x1 = 0; x1 < 4; x1++ ) - for ( int y2 = 0; y2 < 4; y2++) - for ( int x2 = 0; x2 < 4; x2++ ) - out[(y1*4+y2)*16+(x1*4+x2)] = in[readPos++]; -} + for (int j = 1; j < LAND_SIZE; ++j) { + diff = (mHeights[number] - prevX) / HEIGHT_SCALE; + offsets.mHeightData[number] = + (diff >= 0) ? (int8_t) (diff + 0.5) : (int8_t) (diff - 0.5); -Land::Land() - : mFlags(0) - , mX(0) - , mY(0) - , mPlugin(0) - , mEsm(NULL) - , mDataTypes(0) - , mDataLoaded(false) - , mLandData(NULL) -{ -} - -Land::~Land() -{ - delete mLandData; -} - -void Land::load(ESMReader &esm) -{ - mEsm = &esm; - mPlugin = mEsm->getIndex(); - - // Get the grid location - esm.getSubNameIs("INTV"); - esm.getSubHeaderIs(8); - esm.getT(mX); - esm.getT(mY); - - esm.getHNT(mFlags, "DATA"); - - // Store the file position - mContext = esm.getContext(); - - // Skip these here. Load the actual data when the cell is loaded. - if (esm.isNextSub("VNML")) - { - esm.skipHSubSize(12675); - mDataTypes |= DATA_VNML; - } - if (esm.isNextSub("VHGT")) - { - esm.skipHSubSize(4232); - mDataTypes |= DATA_VHGT; - } - if (esm.isNextSub("WNAM")) - { - esm.skipHSubSize(81); - mDataTypes |= DATA_WNAM; - } - if (esm.isNextSub("VCLR")) - { - esm.skipHSubSize(12675); - mDataTypes |= DATA_VCLR; - } - if (esm.isNextSub("VTEX")) - { - esm.skipHSubSize(512); - mDataTypes |= DATA_VTEX; - } - - mDataLoaded = 0; - mLandData = NULL; -} - -void Land::save(ESMWriter &esm) const -{ - esm.startSubRecord("INTV"); - esm.writeT(mX); - esm.writeT(mY); - esm.endRecord("INTV"); - - esm.writeHNT("DATA", mFlags); -} - -void Land::loadData(int flags) -{ - // Try to load only available data - flags = flags & mDataTypes; - // Return if all required data is loaded - if ((mDataLoaded & flags) == flags) { - return; - } - // Create storage if nothing is loaded - if (mLandData == NULL) { - mLandData = new LandData; - mLandData->mDataTypes = mDataTypes; - } - mEsm->restoreContext(mContext); - - if (mEsm->isNextSub("VNML")) { - condLoad(flags, DATA_VNML, mLandData->mNormals, sizeof(mLandData->mNormals)); - } - - if (mEsm->isNextSub("VHGT")) { - static VHGT vhgt; - if (condLoad(flags, DATA_VHGT, &vhgt, sizeof(vhgt))) { - float rowOffset = vhgt.mHeightOffset; - for (int y = 0; y < LAND_SIZE; y++) { - rowOffset += vhgt.mHeightData[y * LAND_SIZE]; - - mLandData->mHeights[y * LAND_SIZE] = rowOffset * HEIGHT_SCALE; - - float colOffset = rowOffset; - for (int x = 1; x < LAND_SIZE; x++) { - colOffset += vhgt.mHeightData[y * LAND_SIZE + x]; - mLandData->mHeights[x + y * LAND_SIZE] = colOffset * HEIGHT_SCALE; + prevX = mHeights[number]; + ++number; } } - mLandData->mUnk1 = vhgt.mUnk1; - mLandData->mUnk2 = vhgt.mUnk2; + esm.writeHNT("VHGT", offsets, sizeof(VHGT)); + } + if (mDataTypes & Land::DATA_WNAM) { + esm.writeHNT("WNAM", mWnam, 81); + } + if (mDataTypes & Land::DATA_VCLR) { + esm.writeHNT("VCLR", mColours, 3*LAND_NUM_VERTS); + } + if (mDataTypes & Land::DATA_VTEX) { + static uint16_t vtex[LAND_NUM_TEXTURES]; + transposeTextureData(mTextures, vtex); + esm.writeHNT("VTEX", vtex, sizeof(vtex)); } } - if (mEsm->isNextSub("WNAM")) { - condLoad(flags, DATA_WNAM, mLandData->mWnam, 81); + void Land::LandData::transposeTextureData(uint16_t *in, uint16_t *out) + { + int readPos = 0; //bit ugly, but it works + for ( int y1 = 0; y1 < 4; y1++ ) + for ( int x1 = 0; x1 < 4; x1++ ) + for ( int y2 = 0; y2 < 4; y2++) + for ( int x2 = 0; x2 < 4; x2++ ) + out[(y1*4+y2)*16+(x1*4+x2)] = in[readPos++]; } - if (mEsm->isNextSub("VCLR")) - condLoad(flags, DATA_VCLR, mLandData->mColours, 3 * LAND_NUM_VERTS); - if (mEsm->isNextSub("VTEX")) { - static uint16_t vtex[LAND_NUM_TEXTURES]; - if (condLoad(flags, DATA_VTEX, vtex, sizeof(vtex))) { - LandData::transposeTextureData(vtex, mLandData->mTextures); - } - } -} -void Land::unloadData() -{ - if (mDataLoaded) + Land::Land() + : mFlags(0) + , mX(0) + , mY(0) + , mPlugin(0) + , mEsm(NULL) + , mDataTypes(0) + , mDataLoaded(false) + , mLandData(NULL) + , mIsDeleted(false) + { + } + + Land::~Land() { delete mLandData; - mLandData = NULL; + } + + void Land::load(ESMReader &esm) + { + mEsm = &esm; + mPlugin = mEsm->getIndex(); + mIsDeleted = false; + + // Get the grid location + esm.getSubNameIs("INTV"); + esm.getSubHeaderIs(8); + esm.getT(mX); + esm.getT(mY); + + esm.getHNT(mFlags, "DATA"); + + if (esm.isNextSub("DELE")) + { + esm.skipHSub(); + mIsDeleted = true; + } + + // Store the file position + mContext = esm.getContext(); + + // Skip these here. Load the actual data when the cell is loaded. + if (esm.isNextSub("VNML")) + { + esm.skipHSubSize(12675); + mDataTypes |= DATA_VNML; + } + if (esm.isNextSub("VHGT")) + { + esm.skipHSubSize(4232); + mDataTypes |= DATA_VHGT; + } + if (esm.isNextSub("WNAM")) + { + esm.skipHSubSize(81); + mDataTypes |= DATA_WNAM; + } + if (esm.isNextSub("VCLR")) + { + esm.skipHSubSize(12675); + mDataTypes |= DATA_VCLR; + } + if (esm.isNextSub("VTEX")) + { + esm.skipHSubSize(512); + mDataTypes |= DATA_VTEX; + } + mDataLoaded = 0; + mLandData = NULL; } -} -bool Land::condLoad(int flags, int dataFlag, void *ptr, unsigned int size) -{ - if ((mDataLoaded & dataFlag) == 0 && (flags & dataFlag) != 0) { - mEsm->getHExact(ptr, size); - mDataLoaded |= dataFlag; - return true; + void Land::save(ESMWriter &esm) const + { + esm.startSubRecord("INTV"); + esm.writeT(mX); + esm.writeT(mY); + esm.endRecord("INTV"); + + esm.writeHNT("DATA", mFlags); + + if (mIsDeleted) + { + esm.writeHNCString("DELE", ""); + } + + if (mLandData != NULL) + { + mLandData->save(esm); + } } - mEsm->skipHSubSize(size); - return false; -} -bool Land::isDataLoaded(int flags) const -{ - return (mDataLoaded & flags) == (flags & mDataTypes); -} + void Land::blank() + { + mIsDeleted = false; + } + + void Land::loadData(int flags) + { + // Try to load only available data + flags = flags & mDataTypes; + // Return if all required data is loaded + if ((mDataLoaded & flags) == flags) { + return; + } + // Create storage if nothing is loaded + if (mLandData == NULL) { + mLandData = new LandData; + mLandData->mDataTypes = mDataTypes; + } + mEsm->restoreContext(mContext); + + if (mEsm->isNextSub("VNML")) { + condLoad(flags, DATA_VNML, mLandData->mNormals, sizeof(mLandData->mNormals)); + } + + if (mEsm->isNextSub("VHGT")) { + static VHGT vhgt; + if (condLoad(flags, DATA_VHGT, &vhgt, sizeof(vhgt))) { + float rowOffset = vhgt.mHeightOffset; + for (int y = 0; y < LAND_SIZE; y++) { + rowOffset += vhgt.mHeightData[y * LAND_SIZE]; + + mLandData->mHeights[y * LAND_SIZE] = rowOffset * HEIGHT_SCALE; + + float colOffset = rowOffset; + for (int x = 1; x < LAND_SIZE; x++) { + colOffset += vhgt.mHeightData[y * LAND_SIZE + x]; + mLandData->mHeights[x + y * LAND_SIZE] = colOffset * HEIGHT_SCALE; + } + } + mLandData->mUnk1 = vhgt.mUnk1; + mLandData->mUnk2 = vhgt.mUnk2; + } + } + + if (mEsm->isNextSub("WNAM")) { + condLoad(flags, DATA_WNAM, mLandData->mWnam, 81); + } + if (mEsm->isNextSub("VCLR")) + condLoad(flags, DATA_VCLR, mLandData->mColours, 3 * LAND_NUM_VERTS); + if (mEsm->isNextSub("VTEX")) { + static uint16_t vtex[LAND_NUM_TEXTURES]; + if (condLoad(flags, DATA_VTEX, vtex, sizeof(vtex))) { + LandData::transposeTextureData(vtex, mLandData->mTextures); + } + } + } + + void Land::unloadData() + { + if (mDataLoaded) + { + delete mLandData; + mLandData = NULL; + mDataLoaded = 0; + } + } + + bool Land::condLoad(int flags, int dataFlag, void *ptr, unsigned int size) + { + if ((mDataLoaded & dataFlag) == 0 && (flags & dataFlag) != 0) { + mEsm->getHExact(ptr, size); + mDataLoaded |= dataFlag; + return true; + } + mEsm->skipHSubSize(size); + return false; + } + + bool Land::isDataLoaded(int flags) const + { + return (mDataLoaded & flags) == (flags & mDataTypes); + } } diff --git a/components/esm/loadland.hpp b/components/esm/loadland.hpp index 61ce4855e..d9ee0015a 100644 --- a/components/esm/loadland.hpp +++ b/components/esm/loadland.hpp @@ -97,10 +97,12 @@ struct Land LandData *mLandData; + bool mIsDeleted; + void load(ESMReader &esm); void save(ESMWriter &esm) const; - void blank() {} + void blank(); /** * Actually loads data diff --git a/components/esm/loadpgrd.cpp b/components/esm/loadpgrd.cpp index fc0974c9d..5e8de9d57 100644 --- a/components/esm/loadpgrd.cpp +++ b/components/esm/loadpgrd.cpp @@ -32,98 +32,137 @@ namespace ESM { } -void Pathgrid::load(ESMReader &esm) -{ - esm.getHNT(mData, "DATA", 12); - mCell = esm.getHNString("NAME"); + Pathgrid::Pathgrid() + : mIsDeleted(false) + {} - mPoints.clear(); - mEdges.clear(); - - // keep track of total connections so we can reserve edge vector size - int edgeCount = 0; - - if (esm.isNextSub("PGRP")) + void Pathgrid::load(ESMReader &esm) { - esm.getSubHeader(); - int size = esm.getSubSize(); - // Check that the sizes match up. Size = 16 * s2 (path points) - if (size != static_cast (sizeof(Point) * mData.mS2)) - esm.fail("Path point subrecord size mismatch"); - else - { - int pointCount = mData.mS2; - mPoints.reserve(pointCount); - for (int i = 0; i < pointCount; ++i) - { - Point p; - esm.getExact(&p, sizeof(Point)); - mPoints.push_back(p); - edgeCount += p.mConnectionNum; - } - } - } + mPoints.clear(); + mEdges.clear(); - if (esm.isNextSub("PGRC")) - { - esm.getSubHeader(); - int size = esm.getSubSize(); - if (size % sizeof(int) != 0) - esm.fail("PGRC size not a multiple of 4"); - else - { - int rawConnNum = size / sizeof(int); - std::vector rawConnections; - rawConnections.reserve(rawConnNum); - for (int i = 0; i < rawConnNum; ++i) - { - int currentValue; - esm.getT(currentValue); - rawConnections.push_back(currentValue); - } + // keep track of total connections so we can reserve edge vector size + int edgeCount = 0; - std::vector::const_iterator rawIt = rawConnections.begin(); - int pointIndex = 0; - mEdges.reserve(edgeCount); - for(PointList::const_iterator it = mPoints.begin(); it != mPoints.end(); ++it, ++pointIndex) + bool hasData = false; + bool hasName = false; + while (esm.hasMoreSubs()) + { + esm.getSubName(); + uint32_t name = esm.retSubName().val; + switch (name) { - unsigned char connectionNum = (*it).mConnectionNum; - for (int i = 0; i < connectionNum; ++i) { - Edge edge; - edge.mV0 = pointIndex; - edge.mV1 = *rawIt; - ++rawIt; - mEdges.push_back(edge); + case ESM::FourCC<'D','A','T','A'>::value: + esm.getHT(mData, 12); + hasData = true; + break; + case ESM::FourCC<'N','A','M','E'>::value: + mCell = esm.getHString(); + hasName = true; + break; + case ESM::FourCC<'P','G','R','P'>::value: + { + esm.getSubHeader(); + int size = esm.getSubSize(); + // Check that the sizes match up. Size = 16 * s2 (path points) + if (size != static_cast (sizeof(Point) * mData.mS2)) + esm.fail("Path point subrecord size mismatch"); + else + { + int pointCount = mData.mS2; + mPoints.reserve(pointCount); + for (int i = 0; i < pointCount; ++i) + { + Point p; + esm.getExact(&p, sizeof(Point)); + mPoints.push_back(p); + edgeCount += p.mConnectionNum; + } + } + break; } + case ESM::FourCC<'P','G','R','C'>::value: + { + esm.getSubHeader(); + int size = esm.getSubSize(); + if (size % sizeof(int) != 0) + esm.fail("PGRC size not a multiple of 4"); + else + { + int rawConnNum = size / sizeof(int); + std::vector rawConnections; + rawConnections.reserve(rawConnNum); + for (int i = 0; i < rawConnNum; ++i) + { + int currentValue; + esm.getT(currentValue); + rawConnections.push_back(currentValue); + } + + std::vector::const_iterator rawIt = rawConnections.begin(); + int pointIndex = 0; + mEdges.reserve(edgeCount); + for(PointList::const_iterator it = mPoints.begin(); it != mPoints.end(); ++it, ++pointIndex) + { + unsigned char connectionNum = (*it).mConnectionNum; + for (int i = 0; i < connectionNum; ++i) { + Edge edge; + edge.mV0 = pointIndex; + edge.mV1 = *rawIt; + ++rawIt; + mEdges.push_back(edge); + } + } + } + break; + } + case ESM::FourCC<'D','E','L','E'>::value: + esm.skipHSub(); + mIsDeleted = true; + break; + default: + esm.fail("Unknown subrecord"); + break; } } - } -} -void Pathgrid::save(ESMWriter &esm) const -{ - esm.writeHNT("DATA", mData, 12); - esm.writeHNCString("NAME", mCell); - if (!mPoints.empty()) - { - esm.startSubRecord("PGRP"); - for (PointList::const_iterator it = mPoints.begin(); it != mPoints.end(); ++it) - { - esm.writeT(*it); - } - esm.endRecord("PGRP"); + if (!hasData) + esm.fail("Missing DATA subrecord"); + if (!hasName) + esm.fail("Missing NAME subrecord"); } - if (!mEdges.empty()) + void Pathgrid::save(ESMWriter &esm) const { - esm.startSubRecord("PGRC"); - for (std::vector::const_iterator it = mEdges.begin(); it != mEdges.end(); ++it) + esm.writeHNT("DATA", mData, 12); + esm.writeHNCString("NAME", mCell); + + if (mIsDeleted) { - esm.writeT(it->mV1); + esm.writeHNCString("DELE", ""); + return; + } + + if (!mPoints.empty()) + { + esm.startSubRecord("PGRP"); + for (PointList::const_iterator it = mPoints.begin(); it != mPoints.end(); ++it) + { + esm.writeT(*it); + } + esm.endRecord("PGRP"); + } + + if (!mEdges.empty()) + { + esm.startSubRecord("PGRC"); + for (std::vector::const_iterator it = mEdges.begin(); it != mEdges.end(); ++it) + { + esm.writeT(it->mV1); + } + esm.endRecord("PGRC"); } - esm.endRecord("PGRC"); } -} void Pathgrid::blank() { @@ -134,5 +173,6 @@ void Pathgrid::save(ESMWriter &esm) const mData.mS2 = 0; mPoints.clear(); mEdges.clear(); + mIsDeleted = false; } } diff --git a/components/esm/loadpgrd.hpp b/components/esm/loadpgrd.hpp index f33ccbedf..4b82d9571 100644 --- a/components/esm/loadpgrd.hpp +++ b/components/esm/loadpgrd.hpp @@ -53,6 +53,10 @@ struct Pathgrid typedef std::vector EdgeList; EdgeList mEdges; + bool mIsDeleted; + + Pathgrid(); + void load(ESMReader &esm); void save(ESMWriter &esm) const; diff --git a/components/esm/loadrace.cpp b/components/esm/loadrace.cpp index 3feb06c92..12762bda3 100644 --- a/components/esm/loadrace.cpp +++ b/components/esm/loadrace.cpp @@ -8,6 +8,10 @@ namespace ESM { unsigned int Race::sRecordId = REC_RACE; + Race::Race() + : mIsDeleted(false) + {} + int Race::MaleFemale::getValue (bool male) const { return male ? mMale : mFemale; @@ -18,47 +22,65 @@ namespace ESM return static_cast(male ? mMale : mFemale); } -void Race::load(ESMReader &esm) -{ - mPowers.mList.clear(); - - mId = esm.getHNString("NAME"); - - bool hasData = false; - while (esm.hasMoreSubs()) + void Race::load(ESMReader &esm) { - esm.getSubName(); - uint32_t name = esm.retSubName().val; - switch (name) + mPowers.mList.clear(); + mIsDeleted = false; + + bool hasName = false; + bool hasData = false; + while (esm.hasMoreSubs()) { - case ESM::FourCC<'F','N','A','M'>::value: - mName = esm.getHString(); - break; - case ESM::FourCC<'R','A','D','T'>::value: - esm.getHT(mData, 140); - hasData = true; - break; - case ESM::FourCC<'D','E','S','C'>::value: - mDescription = esm.getHString(); - break; - case ESM::FourCC<'N','P','C','S'>::value: - mPowers.add(esm); - break; - default: - esm.fail("Unknown subrecord"); + 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; + case ESM::FourCC<'R','A','D','T'>::value: + esm.getHT(mData, 140); + hasData = true; + break; + case ESM::FourCC<'D','E','S','C'>::value: + mDescription = esm.getHString(); + break; + case ESM::FourCC<'N','P','C','S'>::value: + mPowers.add(esm); + break; + default: + esm.fail("Unknown subrecord"); + } } + + if (!hasName) + esm.fail("Missing NAME subrecord"); + if (!hasData && !mIsDeleted) + esm.fail("Missing RADT subrecord"); + } + void Race::save(ESMWriter &esm) const + { + esm.writeHNCString("NAME", mId); + + if (mIsDeleted) + { + esm.writeHNCString("DELE", ""); + return; + } + + esm.writeHNOCString("FNAM", mName); + esm.writeHNT("RADT", mData, 140); + mPowers.save(esm); + esm.writeHNOString("DESC", mDescription); } - if (!hasData) - esm.fail("Missing RADT subrecord"); -} -void Race::save(ESMWriter &esm) const -{ - esm.writeHNCString("NAME", mId); - esm.writeHNOCString("FNAM", mName); - esm.writeHNT("RADT", mData, 140); - mPowers.save(esm); - esm.writeHNOString("DESC", mDescription); -} void Race::blank() { diff --git a/components/esm/loadrace.hpp b/components/esm/loadrace.hpp index 553d2e68b..e8e9a442b 100644 --- a/components/esm/loadrace.hpp +++ b/components/esm/loadrace.hpp @@ -68,6 +68,10 @@ struct Race std::string mId, mName, mDescription; SpellList mPowers; + bool mIsDeleted; + + Race(); + void load(ESMReader &esm); void save(ESMWriter &esm) const; diff --git a/components/esm/loadsscr.cpp b/components/esm/loadsscr.cpp index 7380dd0a7..076f73742 100644 --- a/components/esm/loadsscr.cpp +++ b/components/esm/loadsscr.cpp @@ -8,8 +8,14 @@ namespace ESM { unsigned int StartScript::sRecordId = REC_SSCR; + StartScript::StartScript() + : mIsDeleted(false) + {} + void StartScript::load(ESMReader &esm) { + mIsDeleted = false; + bool hasData = false; bool hasName = false; while (esm.hasMoreSubs()) @@ -26,10 +32,16 @@ namespace ESM mId = esm.getHString(); hasName = true; break; + case ESM::FourCC<'D','E','L','E'>::value: + esm.skipHSub(); + mIsDeleted = true; + break; default: esm.fail("Unknown subrecord"); + break; } } + if (!hasData) esm.fail("Missing DATA"); if (!hasName) @@ -39,10 +51,16 @@ namespace ESM { esm.writeHNString("DATA", mData); esm.writeHNString("NAME", mId); + + if (mIsDeleted) + { + esm.writeHNCString("DELE", ""); + } } void StartScript::blank() { mData.clear(); + mIsDeleted = false; } } diff --git a/components/esm/loadsscr.hpp b/components/esm/loadsscr.hpp index dc7ad6a42..e475abd86 100644 --- a/components/esm/loadsscr.hpp +++ b/components/esm/loadsscr.hpp @@ -26,6 +26,10 @@ struct StartScript std::string mData; std::string mId; + bool mIsDeleted; + + StartScript(); + // Load a record and add it to the list void load(ESMReader &esm); void save(ESMWriter &esm) const;