55
66#include < format>
77
8+ #include < components/esm/attr.hpp>
89#include < components/esm3/loadmgef.hpp>
10+ #include < components/esm3/loadskil.hpp>
911#include < components/misc/concepts.hpp>
1012
1113namespace ESM
@@ -20,6 +22,12 @@ namespace ESM
2022 int32_t mRange , mArea , mDuration , mMagnMin , mMagnMax ;
2123 };
2224
25+ // Struct with residual binary fields from ENAM
26+ struct EffectParams
27+ {
28+ int32_t mRange , mArea , mDuration , mMagnMin , mMagnMax ;
29+ };
30+
2331 void toBinary (const ENAMstruct& src, EsmENAMstruct& dst)
2432 {
2533 int16_t index = static_cast <int16_t >(ESM::MagicEffect::refIdToIndex (src.mEffectID ));
@@ -39,7 +47,7 @@ namespace ESM
3947 {
4048 int16_t index = src.mEffectID ;
4149 if (index < 0 || index >= ESM::MagicEffect::Length)
42- throw std::runtime_error (std::format (" Cannot deserialize effect with index {}" , index));
50+ throw std::runtime_error (std::format (" Cannot deserialize effect into ENAM with index {}. " , index));
4351 dst.mEffectID = ESM::MagicEffect::indexToRefId (index);
4452 dst.mSkill = src.mSkill ;
4553 dst.mAttribute = src.mAttribute ;
@@ -49,6 +57,16 @@ namespace ESM
4957 dst.mMagnMin = src.mMagnMin ;
5058 dst.mMagnMax = src.mMagnMax ;
5159 }
60+
61+ template <typename T, typename U>
62+ void setEffectParams (const T& src, U& dst)
63+ {
64+ dst.mRange = src.mRange ;
65+ dst.mArea = src.mArea ;
66+ dst.mDuration = src.mDuration ;
67+ dst.mMagnMin = src.mMagnMin ;
68+ dst.mMagnMax = src.mMagnMax ;
69+ }
5270 }
5371
5472 template <Misc::SameAsWithoutCvref<EsmENAMstruct> T>
@@ -57,6 +75,12 @@ namespace ESM
5775 f (v.mEffectID , v.mSkill , v.mAttribute , v.mRange , v.mArea , v.mDuration , v.mMagnMin , v.mMagnMax );
5876 }
5977
78+ template <Misc::SameAsWithoutCvref<EffectParams> T>
79+ void decompose (T&& v, const auto & f)
80+ {
81+ f (v.mRange , v.mArea , v.mDuration , v.mMagnMin , v.mMagnMax );
82+ }
83+
6084 void EffectList::load (ESMReader& esm)
6185 {
6286 mList .clear ();
@@ -81,21 +105,46 @@ namespace ESM
81105
82106 void EffectList::add (ESMReader& esm)
83107 {
84- EsmENAMstruct bin;
85- esm.getSubComposite (bin);
86-
87108 ENAMstruct s;
88- fromBinary (bin, s);
109+ if (esm.getFormatVersion () <= MaxSerializeEffectRefIdFormatVersion)
110+ {
111+ EsmENAMstruct bin;
112+ esm.getSubComposite (bin);
113+ fromBinary (bin, s);
114+ }
115+ else
116+ {
117+ EffectParams p;
118+ esm.getSubComposite (p);
119+ setEffectParams (p, s);
120+ s.mEffectID = esm.getHNRefId (" ENID" );
121+ s.mSkill = static_cast <signed char >(ESM::Skill::refIdToIndex (esm.getHNORefId (" ENSK" )));
122+ s.mAttribute = static_cast <signed char >(ESM::Attribute::refIdToIndex (esm.getHNORefId (" ENAT" )));
123+ }
89124 mList .push_back ({ s, static_cast <uint32_t >(mList .size ()) });
90125 }
91126
92127 void EffectList::save (ESMWriter& esm) const
93128 {
94129 for (const IndexedENAMstruct& enam : mList )
95130 {
96- EsmENAMstruct bin;
97- toBinary (enam.mData , bin);
98- esm.writeNamedComposite (" ENAM" , bin);
131+ if (esm.getFormatVersion () <= MaxSerializeEffectRefIdFormatVersion)
132+ {
133+ EsmENAMstruct bin;
134+ toBinary (enam.mData , bin);
135+ esm.writeNamedComposite (" ENAM" , bin);
136+ }
137+ else
138+ {
139+ if (enam.mData .mEffectID .empty ())
140+ throw std::runtime_error (" Cannot serialize empty effect into ENAM." );
141+ EffectParams p;
142+ setEffectParams (enam.mData , p);
143+ esm.writeNamedComposite (" ENAM" , p);
144+ esm.writeHNRefId (" ENID" , enam.mData .mEffectID );
145+ esm.writeHNORefId (" ENSK" , ESM::Skill::indexToRefId (enam.mData .mSkill ));
146+ esm.writeHNORefId (" ENAT" , ESM::Attribute::indexToRefId (enam.mData .mAttribute ));
147+ }
99148 }
100149 }
101150
0 commit comments