mirror of
https://gitlab.com/OpenMW/openmw.git
synced 2025-01-15 22:49:48 +00:00
Use decompose to handle AI packages and data
This commit is contained in:
parent
3301ebb2cb
commit
75d0b6e355
@ -722,9 +722,6 @@ namespace EsmTool
|
||||
std::cout << " AI Fight:" << (int)mData.mAiData.mFight << std::endl;
|
||||
std::cout << " AI Flee:" << (int)mData.mAiData.mFlee << std::endl;
|
||||
std::cout << " AI Alarm:" << (int)mData.mAiData.mAlarm << std::endl;
|
||||
std::cout << " AI U1:" << (int)mData.mAiData.mU1 << std::endl;
|
||||
std::cout << " AI U2:" << (int)mData.mAiData.mU2 << std::endl;
|
||||
std::cout << " AI U3:" << (int)mData.mAiData.mU3 << std::endl;
|
||||
std::cout << " AI Services:" << Misc::StringUtils::format("0x%08X", mData.mAiData.mServices) << std::endl;
|
||||
|
||||
for (const ESM::AIPackage& package : mData.mAiPackage.mList)
|
||||
@ -1115,9 +1112,6 @@ namespace EsmTool
|
||||
std::cout << " AI Fight:" << (int)mData.mAiData.mFight << std::endl;
|
||||
std::cout << " AI Flee:" << (int)mData.mAiData.mFlee << std::endl;
|
||||
std::cout << " AI Alarm:" << (int)mData.mAiData.mAlarm << std::endl;
|
||||
std::cout << " AI U1:" << (int)mData.mAiData.mU1 << std::endl;
|
||||
std::cout << " AI U2:" << (int)mData.mAiData.mU2 << std::endl;
|
||||
std::cout << " AI U3:" << (int)mData.mAiData.mU3 << std::endl;
|
||||
std::cout << " AI Services:" << Misc::StringUtils::format("0x%08X", mData.mAiData.mServices) << std::endl;
|
||||
|
||||
for (const ESM::AIPackage& package : mData.mAiPackage.mList)
|
||||
|
@ -1,4 +1,5 @@
|
||||
#include <components/esm/fourcc.hpp>
|
||||
#include <components/esm3/aipackage.hpp>
|
||||
#include <components/esm3/aisequence.hpp>
|
||||
#include <components/esm3/esmreader.hpp>
|
||||
#include <components/esm3/esmwriter.hpp>
|
||||
@ -89,8 +90,18 @@ namespace ESM
|
||||
|
||||
constexpr std::uint32_t fakeRecordId = fourCC("FAKE");
|
||||
|
||||
template <class T, class = std::void_t<>>
|
||||
struct HasSave : std::false_type
|
||||
{
|
||||
};
|
||||
|
||||
template <class T>
|
||||
void save(const T& record, ESMWriter& writer)
|
||||
struct HasSave<T, std::void_t<decltype(std::declval<T>().save(std::declval<ESMWriter&>()))>> : std::true_type
|
||||
{
|
||||
};
|
||||
|
||||
template <class T>
|
||||
auto save(const T& record, ESMWriter& writer) -> std::enable_if_t<HasSave<std::decay_t<T>>::value>
|
||||
{
|
||||
record.save(writer);
|
||||
}
|
||||
@ -100,6 +111,12 @@ namespace ESM
|
||||
record.save(writer, true);
|
||||
}
|
||||
|
||||
template <class T>
|
||||
auto save(const T& record, ESMWriter& writer) -> std::enable_if_t<!HasSave<std::decay_t<T>>::value>
|
||||
{
|
||||
writer.writeComposite(record);
|
||||
}
|
||||
|
||||
template <typename T>
|
||||
std::unique_ptr<std::istream> makeEsmStream(const T& record, FormatVersion formatVersion)
|
||||
{
|
||||
@ -154,6 +171,12 @@ namespace ESM
|
||||
record.load(reader, deleted, true);
|
||||
}
|
||||
|
||||
template <class T>
|
||||
auto load(ESMReader& reader, T& record) -> std::enable_if_t<!HasSave<std::decay_t<T>>::value>
|
||||
{
|
||||
reader.getComposite(record);
|
||||
}
|
||||
|
||||
template <typename T>
|
||||
void saveAndLoadRecord(const T& record, FormatVersion formatVersion, T& result)
|
||||
{
|
||||
@ -490,6 +513,25 @@ namespace ESM
|
||||
EXPECT_EQ(result.mRepeat, record.mRepeat);
|
||||
}
|
||||
|
||||
TEST_P(Esm3SaveLoadRecordTest, aiDataShouldNotChange)
|
||||
{
|
||||
AIData record;
|
||||
record.mHello = 1;
|
||||
record.mFight = 2;
|
||||
record.mFlee = 3;
|
||||
record.mAlarm = 4;
|
||||
record.mServices = 5;
|
||||
|
||||
AIData result;
|
||||
saveAndLoadRecord(record, GetParam(), result);
|
||||
|
||||
EXPECT_EQ(result.mHello, record.mHello);
|
||||
EXPECT_EQ(result.mFight, record.mFight);
|
||||
EXPECT_EQ(result.mFlee, record.mFlee);
|
||||
EXPECT_EQ(result.mAlarm, record.mAlarm);
|
||||
EXPECT_EQ(result.mServices, record.mServices);
|
||||
}
|
||||
|
||||
INSTANTIATE_TEST_SUITE_P(FormatVersions, Esm3SaveLoadRecordTest, ValuesIn(getFormats()));
|
||||
}
|
||||
}
|
||||
|
@ -5,9 +5,35 @@
|
||||
|
||||
namespace ESM
|
||||
{
|
||||
template <Misc::SameAsWithoutCvref<AIWander> T>
|
||||
void decompose(T&& v, const auto& f)
|
||||
{
|
||||
f(v.mDistance, v.mDuration, v.mTimeOfDay, v.mIdle, v.mShouldRepeat);
|
||||
}
|
||||
|
||||
template <Misc::SameAsWithoutCvref<AITravel> T>
|
||||
void decompose(T&& v, const auto& f)
|
||||
{
|
||||
char padding[3] = { 0, 0, 0 };
|
||||
f(v.mX, v.mY, v.mZ, v.mShouldRepeat, padding);
|
||||
}
|
||||
|
||||
template <Misc::SameAsWithoutCvref<AITarget> T>
|
||||
void decompose(T&& v, const auto& f)
|
||||
{
|
||||
char padding = 0;
|
||||
f(v.mX, v.mY, v.mZ, v.mDuration, v.mId.mData, v.mShouldRepeat, padding);
|
||||
}
|
||||
|
||||
template <Misc::SameAsWithoutCvref<AIActivate> T>
|
||||
void decompose(T&& v, const auto& f)
|
||||
{
|
||||
f(v.mName.mData, v.mShouldRepeat);
|
||||
}
|
||||
|
||||
void AIData::blank()
|
||||
{
|
||||
mHello = mFight = mFlee = mAlarm = mU1 = mU2 = mU3 = 0;
|
||||
mHello = mFight = mFlee = mAlarm = 0;
|
||||
mServices = 0;
|
||||
}
|
||||
|
||||
@ -28,58 +54,57 @@ namespace ESM
|
||||
else if (esm.retSubName() == AI_Wander)
|
||||
{
|
||||
pack.mType = AI_Wander;
|
||||
esm.getHExact(&pack.mWander, 14);
|
||||
esm.getSubHeader();
|
||||
esm.getComposite(pack.mWander);
|
||||
mList.push_back(pack);
|
||||
}
|
||||
else if (esm.retSubName() == AI_Travel)
|
||||
{
|
||||
pack.mType = AI_Travel;
|
||||
esm.getHExact(&pack.mTravel, 16);
|
||||
esm.getSubHeader();
|
||||
esm.getComposite(pack.mTravel);
|
||||
mList.push_back(pack);
|
||||
}
|
||||
else if (esm.retSubName() == AI_Escort || esm.retSubName() == AI_Follow)
|
||||
{
|
||||
pack.mType = (esm.retSubName() == AI_Escort) ? AI_Escort : AI_Follow;
|
||||
esm.getHExact(&pack.mTarget, 48);
|
||||
esm.getSubHeader();
|
||||
esm.getComposite(pack.mTarget);
|
||||
mList.push_back(pack);
|
||||
}
|
||||
else if (esm.retSubName() == AI_Activate)
|
||||
{
|
||||
pack.mType = AI_Activate;
|
||||
esm.getHExact(&pack.mActivate, 33);
|
||||
esm.getSubHeader();
|
||||
esm.getComposite(pack.mActivate);
|
||||
mList.push_back(pack);
|
||||
}
|
||||
else
|
||||
{ // not AI package related data, so leave
|
||||
return;
|
||||
}
|
||||
}
|
||||
|
||||
void AIPackageList::save(ESMWriter& esm) const
|
||||
{
|
||||
typedef std::vector<AIPackage>::const_iterator PackageIter;
|
||||
for (PackageIter it = mList.begin(); it != mList.end(); ++it)
|
||||
for (const AIPackage& package : mList)
|
||||
{
|
||||
switch (it->mType)
|
||||
switch (package.mType)
|
||||
{
|
||||
case AI_Wander:
|
||||
esm.writeHNT("AI_W", it->mWander, sizeof(it->mWander));
|
||||
esm.writeNamedComposite("AI_W", package.mWander);
|
||||
break;
|
||||
|
||||
case AI_Travel:
|
||||
esm.writeHNT("AI_T", it->mTravel, sizeof(it->mTravel));
|
||||
esm.writeNamedComposite("AI_T", package.mTravel);
|
||||
break;
|
||||
|
||||
case AI_Activate:
|
||||
esm.writeHNT("AI_A", it->mActivate, sizeof(it->mActivate));
|
||||
esm.writeNamedComposite("AI_A", package.mActivate);
|
||||
break;
|
||||
|
||||
case AI_Escort:
|
||||
case AI_Follow:
|
||||
{
|
||||
const NAME name = (it->mType == AI_Escort) ? NAME("AI_E") : NAME("AI_F");
|
||||
esm.writeHNT(name, it->mTarget, sizeof(it->mTarget));
|
||||
esm.writeHNOCString("CNDT", it->mCellName);
|
||||
const NAME name = (package.mType == AI_Escort) ? NAME("AI_E") : NAME("AI_F");
|
||||
esm.writeNamedComposite(name, package.mTarget);
|
||||
esm.writeHNOCString("CNDT", package.mCellName);
|
||||
break;
|
||||
}
|
||||
|
||||
|
@ -5,20 +5,17 @@
|
||||
#include <vector>
|
||||
|
||||
#include "components/esm/esmcommon.hpp"
|
||||
#include "components/misc/concepts.hpp"
|
||||
|
||||
namespace ESM
|
||||
{
|
||||
class ESMReader;
|
||||
class ESMWriter;
|
||||
|
||||
#pragma pack(push)
|
||||
#pragma pack(1)
|
||||
|
||||
struct AIData
|
||||
{
|
||||
uint16_t mHello; // This is the base value for greeting distance [0, 65535]
|
||||
unsigned char mFight, mFlee, mAlarm; // These are probabilities [0, 100]
|
||||
char mU1, mU2, mU3; // Unknown values
|
||||
int32_t mServices; // See the Services enum
|
||||
|
||||
void blank();
|
||||
@ -38,7 +35,6 @@ namespace ESM
|
||||
{
|
||||
float mX, mY, mZ;
|
||||
unsigned char mShouldRepeat;
|
||||
unsigned char mPadding[3];
|
||||
};
|
||||
|
||||
struct AITarget
|
||||
@ -47,7 +43,6 @@ namespace ESM
|
||||
int16_t mDuration;
|
||||
NAME32 mId;
|
||||
unsigned char mShouldRepeat;
|
||||
unsigned char mPadding;
|
||||
};
|
||||
|
||||
struct AIActivate
|
||||
@ -56,8 +51,6 @@ namespace ESM
|
||||
unsigned char mShouldRepeat;
|
||||
};
|
||||
|
||||
#pragma pack(pop)
|
||||
|
||||
enum AiPackageType : std::uint32_t
|
||||
{
|
||||
AI_Wander = 0x575f4941,
|
||||
@ -98,6 +91,13 @@ namespace ESM
|
||||
|
||||
void save(ESMWriter& esm) const;
|
||||
};
|
||||
|
||||
template <Misc::SameAsWithoutCvref<AIData> T>
|
||||
void decompose(T&& v, const auto& f)
|
||||
{
|
||||
char padding[3] = { 0, 0, 0 };
|
||||
f(v.mHello, v.mFight, v.mFlee, v.mAlarm, padding, v.mServices);
|
||||
}
|
||||
}
|
||||
|
||||
#endif
|
||||
|
@ -69,7 +69,8 @@ namespace ESM
|
||||
mSpells.add(esm);
|
||||
break;
|
||||
case fourCC("AIDT"):
|
||||
esm.getHExact(&mAiData, sizeof(mAiData));
|
||||
esm.getSubHeader();
|
||||
esm.getComposite(mAiData);
|
||||
break;
|
||||
case fourCC("DODT"):
|
||||
case fourCC("DNAM"):
|
||||
@ -130,7 +131,7 @@ namespace ESM
|
||||
|
||||
mInventory.save(esm);
|
||||
mSpells.save(esm);
|
||||
esm.writeHNT("AIDT", mAiData, sizeof(mAiData));
|
||||
esm.writeNamedComposite("AIDT", mAiData);
|
||||
mTransport.save(esm);
|
||||
mAiPackage.save(esm);
|
||||
}
|
||||
|
@ -102,7 +102,8 @@ namespace ESM
|
||||
mInventory.add(esm);
|
||||
break;
|
||||
case fourCC("AIDT"):
|
||||
esm.getHExact(&mAiData, sizeof(mAiData));
|
||||
esm.getSubHeader();
|
||||
esm.getComposite(mAiData);
|
||||
break;
|
||||
case fourCC("DODT"):
|
||||
case fourCC("DNAM"):
|
||||
@ -186,7 +187,7 @@ namespace ESM
|
||||
|
||||
mInventory.save(esm);
|
||||
mSpells.save(esm);
|
||||
esm.writeHNT("AIDT", mAiData, sizeof(mAiData));
|
||||
esm.writeNamedComposite("AIDT", mAiData);
|
||||
|
||||
mTransport.save(esm);
|
||||
|
||||
|
Loading…
Reference in New Issue
Block a user