Skip to content

Commit a95543f

Browse files
committed
Merge branch 'Serialize-magic-effect-RefId-directly' into 'master'
Serialize active magic effects and dynamic ENAM-based record RefIds directly See merge request OpenMW/openmw!5141
2 parents 6226836 + ce5e38a commit a95543f

File tree

5 files changed

+90
-21
lines changed

5 files changed

+90
-21
lines changed

components/esm3/activespells.cpp

Lines changed: 9 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -86,7 +86,7 @@ namespace ESM
8686

8787
for (auto& effect : params.mEffects)
8888
{
89-
esm.writeHNT("MGEF", ESM::MagicEffect::refIdToIndex(effect.mEffectId));
89+
esm.writeHNRefId("MGEF", effect.mEffectId);
9090
if (const ESM::RefId* id = std::get_if<ESM::RefId>(&effect.mArg))
9191
{
9292
if (!id->empty())
@@ -171,10 +171,15 @@ namespace ESM
171171

172172
while (esm.isNextSub("MGEF"))
173173
{
174-
int32_t effectId;
175174
ActiveEffect effect;
176-
esm.getHT(effectId);
177-
effect.mEffectId = ESM::MagicEffect::indexToRefId(effectId);
175+
if (format <= MaxSerializeEffectRefIdFormatVersion)
176+
{
177+
int32_t effectId;
178+
esm.getHT(effectId);
179+
effect.mEffectId = ESM::MagicEffect::indexToRefId(effectId);
180+
}
181+
else
182+
effect.mEffectId = esm.getRefId();
178183
if (format <= MaxActorIdSaveGameFormatVersion)
179184
{
180185
int32_t arg = -1;

components/esm3/creaturestats.cpp

Lines changed: 11 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -129,14 +129,21 @@ namespace ESM
129129
{
130130
while (esm.isNextSub("SUMM"))
131131
{
132-
int32_t magicEffect;
133-
esm.getHT(magicEffect);
132+
RefId effectId;
133+
if (esm.getFormatVersion() <= MaxSerializeEffectRefIdFormatVersion)
134+
{
135+
int32_t magicEffect;
136+
esm.getHT(magicEffect);
137+
effectId = ESM::MagicEffect::indexToRefId(magicEffect);
138+
}
139+
else
140+
effectId = esm.getRefId();
134141
RefNum actor;
135142
if (esm.getFormatVersion() <= MaxActorIdSaveGameFormatVersion)
136143
esm.getHNT(actor.mIndex, "ACID");
137144
else
138145
actor = esm.getFormId(true, "ACID");
139-
mSummonedCreatures.emplace(ESM::MagicEffect::indexToRefId(magicEffect), actor);
146+
mSummonedCreatures.emplace(effectId, actor);
140147
}
141148
}
142149

@@ -251,7 +258,7 @@ namespace ESM
251258

252259
for (const auto& [effectId, actor] : mSummonedCreatures)
253260
{
254-
esm.writeHNT("SUMM", ESM::MagicEffect::refIdToIndex(effectId));
261+
esm.writeHNRefId("SUMM", effectId);
255262
esm.writeFormId(actor, true, "ACID");
256263
}
257264

components/esm3/effectlist.cpp

Lines changed: 57 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -5,7 +5,9 @@
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

1113
namespace 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

components/esm3/formatversion.hpp

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -29,7 +29,8 @@ namespace ESM
2929
inline constexpr FormatVersion MaxActiveSpellTypeVersion = 31;
3030
inline constexpr FormatVersion MaxPlayerBeforeCellDataFormatVersion = 32;
3131
inline constexpr FormatVersion MaxActorIdSaveGameFormatVersion = 34;
32-
inline constexpr FormatVersion CurrentSaveGameFormatVersion = 35;
32+
inline constexpr FormatVersion MaxSerializeEffectRefIdFormatVersion = 35;
33+
inline constexpr FormatVersion CurrentSaveGameFormatVersion = 36;
3334

3435
inline constexpr FormatVersion MinSupportedSaveGameFormatVersion = 5;
3536
inline constexpr FormatVersion OpenMW0_49MinSaveGameFormatVersion = 5;

components/esm3/magiceffects.cpp

Lines changed: 11 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -12,7 +12,7 @@ namespace ESM
1212
{
1313
for (const auto& [key, params] : mEffects)
1414
{
15-
esm.writeHNT("EFID", ESM::MagicEffect::refIdToIndex(key));
15+
esm.writeHNRefId("EFID", key);
1616
esm.writeHNT("BASE", params.first);
1717
esm.writeHNT("MODI", params.second);
1818
}
@@ -22,15 +22,22 @@ namespace ESM
2222
{
2323
while (esm.isNextSub("EFID"))
2424
{
25-
int32_t id;
25+
RefId effectId;
26+
if (esm.getFormatVersion() <= MaxSerializeEffectRefIdFormatVersion)
27+
{
28+
int32_t id;
29+
esm.getHT(id);
30+
effectId = ESM::MagicEffect::indexToRefId(id);
31+
}
32+
else
33+
effectId = esm.getRefId();
2634
std::pair<int32_t, float> params;
27-
esm.getHT(id);
2835
esm.getHNT(params.first, "BASE");
2936
if (esm.getFormatVersion() <= MaxClearModifiersFormatVersion)
3037
params.second = 0.f;
3138
else
3239
esm.getHNT(params.second, "MODI");
33-
mEffects.emplace(ESM::MagicEffect::indexToRefId(id), params);
40+
mEffects.emplace(effectId, params);
3441
}
3542
}
3643

0 commit comments

Comments
 (0)