Add getCompositeSize and handle NPC data

fix-osga-rotate-wildly
Evil Eye 10 months ago
parent cef59e8928
commit 1499dd2654

@ -5,6 +5,13 @@ namespace ESM
{ {
template <class T> template <class T>
void decompose(T&& value, const auto& apply) = delete; void decompose(T&& value, const auto& apply) = delete;
std::size_t getCompositeSize(const auto& value)
{
std::size_t result = 0;
decompose(value, [&](const auto&... args) { result = (0 + ... + sizeof(args)); });
return result;
}
} }
#endif #endif

@ -3,8 +3,34 @@
#include "esmreader.hpp" #include "esmreader.hpp"
#include "esmwriter.hpp" #include "esmwriter.hpp"
#include <components/misc/concepts.hpp>
namespace ESM namespace ESM
{ {
namespace
{
struct NPDTstruct12
{
NPC::NPDTstruct52& mStruct;
};
}
template <Misc::SameAsWithoutCvref<NPC::NPDTstruct52> T>
void decompose(T&& v, const auto& f)
{
char padding1 = 0;
char padding2 = 0;
f(v.mLevel, v.mAttributes, v.mSkills, padding1, v.mHealth, v.mMana, v.mFatigue, v.mDisposition, v.mReputation,
v.mRank, padding2, v.mGold);
}
template <Misc::SameAsWithoutCvref<NPDTstruct12> T>
void decompose(T&& v, const auto& f)
{
char padding[] = { 0, 0, 0 };
f(v.mStruct.mLevel, v.mStruct.mDisposition, v.mStruct.mReputation, v.mStruct.mRank, padding, v.mStruct.mGold);
}
void NPC::load(ESMReader& esm, bool& isDeleted) void NPC::load(ESMReader& esm, bool& isDeleted)
{ {
isDeleted = false; isDeleted = false;
@ -56,37 +82,25 @@ namespace ESM
case fourCC("NPDT"): case fourCC("NPDT"):
hasNpdt = true; hasNpdt = true;
esm.getSubHeader(); esm.getSubHeader();
if (esm.getSubSize() == 52) if (esm.getSubSize() == getCompositeSize(mNpdt))
{ {
mNpdtType = NPC_DEFAULT; mNpdtType = NPC_DEFAULT;
esm.getT(mNpdt.mLevel); esm.getComposite(mNpdt);
esm.getT(mNpdt.mAttributes);
esm.getT(mNpdt.mSkills);
esm.getT(mNpdt.mUnknown1);
esm.getT(mNpdt.mHealth);
esm.getT(mNpdt.mMana);
esm.getT(mNpdt.mFatigue);
esm.getT(mNpdt.mDisposition);
esm.getT(mNpdt.mReputation);
esm.getT(mNpdt.mRank);
esm.getT(mNpdt.mUnknown2);
esm.getT(mNpdt.mGold);
} }
else if (esm.getSubSize() == 12) else
{ {
mNpdtType = NPC_WITH_AUTOCALCULATED_STATS; NPDTstruct12 data{ mNpdt };
if (esm.getSubSize() == getCompositeSize(data))
// Clearing the mNdpt struct to initialize all values {
blankNpdt(); mNpdtType = NPC_WITH_AUTOCALCULATED_STATS;
esm.getT(mNpdt.mLevel);
esm.getT(mNpdt.mDisposition); // Clearing the mNdpt struct to initialize all values
esm.getT(mNpdt.mReputation); blankNpdt();
esm.getT(mNpdt.mRank); esm.getComposite(data);
esm.skip(3); }
esm.getT(mNpdt.mGold); else
esm.fail("NPC_NPDT must be 12 or 52 bytes long");
} }
else
esm.fail("NPC_NPDT must be 12 or 52 bytes long");
break; break;
case fourCC("FLAG"): case fourCC("FLAG"):
hasFlags = true; hasFlags = true;
@ -154,32 +168,11 @@ namespace ESM
if (mNpdtType == NPC_DEFAULT) if (mNpdtType == NPC_DEFAULT)
{ {
esm.startSubRecord("NPDT"); esm.writeNamedComposite("NPDT", mNpdt);
esm.writeT(mNpdt.mLevel);
esm.writeT(mNpdt.mAttributes);
esm.writeT(mNpdt.mSkills);
esm.writeT(mNpdt.mUnknown1);
esm.writeT(mNpdt.mHealth);
esm.writeT(mNpdt.mMana);
esm.writeT(mNpdt.mFatigue);
esm.writeT(mNpdt.mDisposition);
esm.writeT(mNpdt.mReputation);
esm.writeT(mNpdt.mRank);
esm.writeT(mNpdt.mUnknown2);
esm.writeT(mNpdt.mGold);
esm.endRecord("NPDT");
} }
else if (mNpdtType == NPC_WITH_AUTOCALCULATED_STATS) else if (mNpdtType == NPC_WITH_AUTOCALCULATED_STATS)
{ {
esm.startSubRecord("NPDT"); esm.writeNamedComposite("NPDT", NPDTstruct12{ const_cast<NPDTstruct52&>(mNpdt) });
esm.writeT(mNpdt.mLevel);
esm.writeT(mNpdt.mDisposition);
esm.writeT(mNpdt.mReputation);
esm.writeT(mNpdt.mRank);
constexpr char padding[] = { 0, 0, 0 };
esm.writeT(padding);
esm.writeT(mNpdt.mGold);
esm.endRecord("NPDT");
} }
esm.writeHNT("FLAG", ((mBloodType << 10) + mFlags)); esm.writeHNT("FLAG", ((mBloodType << 10) + mFlags));
@ -238,9 +231,7 @@ namespace ESM
mNpdt.mReputation = 0; mNpdt.mReputation = 0;
mNpdt.mHealth = mNpdt.mMana = mNpdt.mFatigue = 0; mNpdt.mHealth = mNpdt.mMana = mNpdt.mFatigue = 0;
mNpdt.mDisposition = 0; mNpdt.mDisposition = 0;
mNpdt.mUnknown1 = 0;
mNpdt.mRank = 0; mNpdt.mRank = 0;
mNpdt.mUnknown2 = 0;
mNpdt.mGold = 0; mNpdt.mGold = 0;
} }

@ -83,10 +83,8 @@ namespace ESM
// mSkill can grow up to 200, it must be unsigned // mSkill can grow up to 200, it must be unsigned
std::array<unsigned char, Skill::Length> mSkills; std::array<unsigned char, Skill::Length> mSkills;
char mUnknown1;
uint16_t mHealth, mMana, mFatigue; uint16_t mHealth, mMana, mFatigue;
unsigned char mDisposition, mReputation, mRank; unsigned char mDisposition, mReputation, mRank;
char mUnknown2;
int32_t mGold; int32_t mGold;
}; // 52 bytes }; // 52 bytes

@ -73,7 +73,7 @@ namespace ESM
{ {
esm.getSubHeader(); esm.getSubHeader();
uint32_t size = esm.getSubSize(); uint32_t size = esm.getSubSize();
if (size != 16u * mData.mPoints) if (size != getCompositeSize(Point{}) * mData.mPoints)
esm.fail("Path point subrecord size mismatch"); esm.fail("Path point subrecord size mismatch");
else else
{ {

Loading…
Cancel
Save