1
0
Fork 0
mirror of https://github.com/OpenMW/openmw.git synced 2026-01-20 22:00:54 +00:00
openmw/components/esm3/loadingr.cpp
Telvanni 4Life 9159788c9b Address reviewer feedback and ran clang-format on modified files:
- Changed reverse lookup map constructor for gmsts, names, and ESM::MagicEffectIds to be more generic.
- Changed refIdToIndex to use map instead of array traversal.
- Removed redundant check from refIdToGmstString.
- Removed sMagicEffectNames and associated map. Removed dead code from loadmgef.cpp/hpp.
- Changed return types of magic effect bindings to RefId.
- Reverted ESMStore search to find.
- Changed std::map to std::unordered_map for faster lookups in resistance and weakness functions.
- Changed loadmgef To methods to pass RefId by value.
- Removed StringRefId alias MagicEffectId.
- Changed all effectId arguments in PR to pass-by-value.
- Removed ESM::MagicEffect::refIdToName function.
- Changed effect key type from long to ESM::RefId in OpGetEffect of mwscript.
- Removed superfluous MWWorld::Store<ESM::GameSettings> argument to MagicEffect store's setUp method.
- Removed transformation code from decompose for ENAM and IRDT structs.
- Changed resistance and weakness maps to initialization to use initialization instead of assignment.
- Changed sGmstEffectIds to constexpr array since all parameters are known at compile time.
- Changed getBoundItemsMap to use an unordered_map and have string_view values.
- MagicEffect store definition removed (uses standard template class TypedDynamicStore).
- Fixed bug in calculating sun damage that would have made vampires daywalkers in Mournhold.
- Removed polymorphic EffectKey constructor and added overload to getOrDefault.
- Placed ESM spec IRDT and ENAM structs in anonymous namespace.
- Added exception if attempting to serialize ENAM subrecords with out of bounds index.
- Added include format statements to satisfy Ubuntu CI linker.
2026-01-08 07:44:06 -05:00

160 lines
4.9 KiB
C++

#include "loadingr.hpp"
#include "esmreader.hpp"
#include "esmwriter.hpp"
#include <components/esm3/loadmgef.hpp>
#include <components/misc/concepts.hpp>
namespace ESM
{
namespace
{
// IRDT format defined by Morrowind.esm
struct EsmIRDTstruct
{
float mWeight;
int32_t mValue, mEffectID[4], mSkills[4], mAttributes[4];
};
void toBinary(const Ingredient::IRDTstruct& src, EsmIRDTstruct& dst)
{
dst.mWeight = src.mWeight;
dst.mValue = src.mValue;
for (int i = 0; i < 4; ++i)
{
dst.mEffectID[i] = ESM::MagicEffect::refIdToIndex(src.mEffectID[i]);
dst.mSkills[i] = src.mSkills[i];
dst.mAttributes[i] = src.mAttributes[i];
}
}
void fromBinary(const EsmIRDTstruct& src, Ingredient::IRDTstruct& dst)
{
dst.mWeight = src.mWeight;
dst.mValue = src.mValue;
for (int i = 0; i < 4; ++i)
{
dst.mEffectID[i] = ESM::MagicEffect::indexToRefId(src.mEffectID[i]);
dst.mSkills[i] = src.mSkills[i];
dst.mAttributes[i] = src.mAttributes[i];
}
}
}
template <Misc::SameAsWithoutCvref<EsmIRDTstruct> T>
void decompose(T&& v, const auto& f)
{
f(v.mWeight, v.mValue, v.mEffectID, v.mSkills, v.mAttributes);
}
void Ingredient::load(ESMReader& esm, bool& isDeleted)
{
isDeleted = false;
mRecordFlags = esm.getRecordFlags();
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("MODL"):
mModel = esm.getHString();
break;
case fourCC("FNAM"):
mName = esm.getHString();
break;
case fourCC("IRDT"):
EsmIRDTstruct bin;
esm.getSubComposite(bin);
fromBinary(bin, mData);
hasData = true;
break;
case fourCC("SCRI"):
mScript = esm.getRefId();
break;
case fourCC("ITEX"):
mIcon = esm.getHString();
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 IRDT subrecord");
// horrible hack to fix broken data in records
for (int i = 0; i < 4; ++i)
{
if (mData.mEffectID[i] != ESM::MagicEffect::AbsorbAttribute
&& mData.mEffectID[i] != ESM::MagicEffect::DamageAttribute
&& mData.mEffectID[i] != ESM::MagicEffect::DrainAttribute
&& mData.mEffectID[i] != ESM::MagicEffect::FortifyAttribute
&& mData.mEffectID[i] != ESM::MagicEffect::RestoreAttribute)
{
mData.mAttributes[i] = -1;
}
// is this relevant in cycle from 0 to 4?
if (mData.mEffectID[i] != ESM::MagicEffect::AbsorbSkill
&& mData.mEffectID[i] != ESM::MagicEffect::DamageSkill
&& mData.mEffectID[i] != ESM::MagicEffect::DrainSkill
&& mData.mEffectID[i] != ESM::MagicEffect::FortifySkill
&& mData.mEffectID[i] != ESM::MagicEffect::RestoreSkill)
{
mData.mSkills[i] = -1;
}
}
}
void Ingredient::save(ESMWriter& esm, bool isDeleted) const
{
esm.writeHNCRefId("NAME", mId);
if (isDeleted)
{
esm.writeHNString("DELE", "", 3);
return;
}
esm.writeHNCString("MODL", mModel);
esm.writeHNOCString("FNAM", mName);
EsmIRDTstruct bin;
toBinary(mData, bin);
esm.writeNamedComposite("IRDT", bin);
esm.writeHNOCRefId("SCRI", mScript);
esm.writeHNOCString("ITEX", mIcon);
}
void Ingredient::blank()
{
mRecordFlags = 0;
mData.mWeight = 0;
mData.mValue = 0;
for (int i = 0; i < 4; ++i)
{
mData.mEffectID[i] = ESM::MagicEffect::WaterBreathing;
mData.mSkills[i] = 0;
mData.mAttributes[i] = 0;
}
mName.clear();
mModel.clear();
mIcon.clear();
mScript = ESM::RefId();
}
}