1
0
mirror of https://gitlab.com/OpenMW/openmw.git synced 2024-12-29 03:19:44 +00:00

Add getCompositeSize and handle NPC data

This commit is contained in:
Evil Eye 2024-03-06 18:16:55 +01:00
parent cef59e8928
commit 1499dd2654
4 changed files with 51 additions and 55 deletions

View File

@ -5,6 +5,13 @@ namespace ESM
{
template <class T>
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

View File

@ -3,8 +3,34 @@
#include "esmreader.hpp"
#include "esmwriter.hpp"
#include <components/misc/concepts.hpp>
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)
{
isDeleted = false;
@ -56,37 +82,25 @@ namespace ESM
case fourCC("NPDT"):
hasNpdt = true;
esm.getSubHeader();
if (esm.getSubSize() == 52)
if (esm.getSubSize() == getCompositeSize(mNpdt))
{
mNpdtType = NPC_DEFAULT;
esm.getT(mNpdt.mLevel);
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)
{
mNpdtType = NPC_WITH_AUTOCALCULATED_STATS;
// Clearing the mNdpt struct to initialize all values
blankNpdt();
esm.getT(mNpdt.mLevel);
esm.getT(mNpdt.mDisposition);
esm.getT(mNpdt.mReputation);
esm.getT(mNpdt.mRank);
esm.skip(3);
esm.getT(mNpdt.mGold);
esm.getComposite(mNpdt);
}
else
esm.fail("NPC_NPDT must be 12 or 52 bytes long");
{
NPDTstruct12 data{ mNpdt };
if (esm.getSubSize() == getCompositeSize(data))
{
mNpdtType = NPC_WITH_AUTOCALCULATED_STATS;
// Clearing the mNdpt struct to initialize all values
blankNpdt();
esm.getComposite(data);
}
else
esm.fail("NPC_NPDT must be 12 or 52 bytes long");
}
break;
case fourCC("FLAG"):
hasFlags = true;
@ -154,32 +168,11 @@ namespace ESM
if (mNpdtType == NPC_DEFAULT)
{
esm.startSubRecord("NPDT");
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");
esm.writeNamedComposite("NPDT", mNpdt);
}
else if (mNpdtType == NPC_WITH_AUTOCALCULATED_STATS)
{
esm.startSubRecord("NPDT");
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.writeNamedComposite("NPDT", NPDTstruct12{ const_cast<NPDTstruct52&>(mNpdt) });
}
esm.writeHNT("FLAG", ((mBloodType << 10) + mFlags));
@ -238,9 +231,7 @@ namespace ESM
mNpdt.mReputation = 0;
mNpdt.mHealth = mNpdt.mMana = mNpdt.mFatigue = 0;
mNpdt.mDisposition = 0;
mNpdt.mUnknown1 = 0;
mNpdt.mRank = 0;
mNpdt.mUnknown2 = 0;
mNpdt.mGold = 0;
}

View File

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

View File

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