#include "loadfact.hpp" #include #include "esmreader.hpp" #include "esmwriter.hpp" #include #include namespace ESM { ESM::RefId& Faction::FADTstruct::getSkill(size_t index, bool) { return mSkills.at(index); } ESM::RefId Faction::FADTstruct::getSkill(size_t index, bool) const { return mSkills.at(index); } void RankData::load(ESMReader& esm) { esm.getT(mAttribute1); esm.getT(mAttribute2); esm.getT(mPrimarySkill); esm.getT(mFavouredSkill); esm.getT(mFactReputation); } void RankData::save(ESMWriter& esm) const { esm.writeT(mAttribute1); esm.writeT(mAttribute2); esm.writeT(mPrimarySkill); esm.writeT(mFavouredSkill); esm.writeT(mFactReputation); } void Faction::FADTstruct::load(ESMReader& esm) { esm.getSubHeader(); if (esm.getFormatVersion() <= MaxFixedStatsFormatVersion) { int32_t attributes[2]; esm.getT(attributes); mAttribute[0] = ESM::Attribute::indexToRefId(attributes[0]); mAttribute[1] = ESM::Attribute::indexToRefId(attributes[1]); for (auto& rank : mRankData) rank.load(esm); int32_t skills[7]; esm.getT(skills); for (std::size_t i = 0; i < std::size(skills); ++i) mSkills[i] = ESM::Skill::indexToRefId(skills[i]); esm.getT(mFlags); } else { for (auto& rank : mRankData) rank.load(esm); esm.getT(mFlags); for (size_t i = 0; i < mAttribute.size() && esm.isNextSub("ATTR"); ++i) mAttribute[i] = esm.getRefId(); for (size_t i = 0; i < mSkills.size() && esm.isNextSub("SKIL"); ++i) mSkills[i] = esm.getRefId(); } } void Faction::FADTstruct::save(ESMWriter& esm) const { if (esm.getFormatVersion() <= MaxFixedStatsFormatVersion) { esm.startSubRecord("FADT"); esm.writeT(ESM::Attribute::refIdToIndex(mAttribute[0])); esm.writeT(ESM::Attribute::refIdToIndex(mAttribute[1])); for (const auto& rank : mRankData) rank.save(esm); for (const ESM::RefId& id : mSkills) { int32_t skill = ESM::Skill::refIdToIndex(id); esm.writeT(skill); } esm.writeT(mFlags); esm.endRecord("FADT"); } else { esm.startSubRecord("FADT"); for (const auto& rank : mRankData) rank.save(esm); esm.writeT(mFlags); esm.endRecord("FADT"); for (const ESM::RefId& id : mAttribute) esm.writeHNOCRefId("ATTR", id); for (const ESM::RefId& id : mSkills) esm.writeHNOCRefId("SKIL", id); } } void Faction::load(ESMReader& esm, bool& isDeleted) { isDeleted = false; mRecordFlags = esm.getRecordFlags(); mReactions.clear(); for (auto& rank : mRanks) rank.clear(); size_t rankCounter = 0; bool hasName = false; bool hasData = false; while (esm.hasMoreSubs()) { esm.getSubName(); switch (esm.retSubName().toInt()) { case SREC_NAME: mId = esm.getRefId(); hasName = true; break; case fourCC("FNAM"): mName = esm.getHString(); break; case fourCC("RNAM"): if (rankCounter >= mRanks.size()) esm.fail("Rank out of range"); mRanks[rankCounter++] = esm.getHString(); break; case fourCC("FADT"): mData.load(esm); hasData = true; break; case fourCC("ANAM"): { ESM::RefId faction = esm.getRefId(); int32_t reaction; esm.getHNT(reaction, "INTV"); // Prefer the lowest reaction in case a faction is listed multiple times auto it = mReactions.find(faction); if (it == mReactions.end()) mReactions.emplace(faction, reaction); else if (it->second > reaction) it->second = reaction; break; } case SREC_DELE: esm.skipHSub(); isDeleted = true; break; default: esm.fail("Unknown subrecord"); break; } } if (!hasName) esm.fail("Missing NAME subrecord"); if (!hasData && !isDeleted) esm.fail("Missing FADT subrecord"); } void Faction::save(ESMWriter& esm, bool isDeleted) const { esm.writeHNCRefId("NAME", mId); if (isDeleted) { esm.writeHNString("DELE", "", 3); return; } esm.writeHNOCString("FNAM", mName); for (const auto& rank : mRanks) { if (rank.empty()) break; esm.writeHNString("RNAM", rank, 32); } mData.save(esm); for (auto it = mReactions.begin(); it != mReactions.end(); ++it) { esm.writeHNRefId("ANAM", it->first); esm.writeHNT("INTV", it->second); } } void Faction::blank() { mRecordFlags = 0; mName.clear(); mData.mAttribute.fill({}); mData.mFlags = 0; for (size_t i = 0; i < mData.mRankData.size(); ++i) { mData.mRankData[i].blank(); mRanks[i].clear(); } mData.mSkills.fill({}); mReactions.clear(); } void RankData::blank() { mAttribute1 = 0; mAttribute2 = 0; mPrimarySkill = 0; mFavouredSkill = 0; mFactReputation = 0; } }