diff --git a/apps/components_tests/esm3/testsaveload.cpp b/apps/components_tests/esm3/testsaveload.cpp index 9d9a549ef3..909072a929 100644 --- a/apps/components_tests/esm3/testsaveload.cpp +++ b/apps/components_tests/esm3/testsaveload.cpp @@ -576,8 +576,8 @@ namespace ESM EffectList record; record.mList.emplace_back(IndexedENAMstruct{ { .mEffectID = ESM::MagicEffect::SwiftSwim, - .mSkill = 2, - .mAttribute = 3, + .mSkill = ESM::Skill::MediumArmor, + .mAttribute = ESM::Attribute::Agility, .mRange = 4, .mArea = 5, .mDuration = 6, diff --git a/apps/esmtool/record.cpp b/apps/esmtool/record.cpp index 5832339dd8..611d6fd247 100644 --- a/apps/esmtool/record.cpp +++ b/apps/esmtool/record.cpp @@ -154,15 +154,16 @@ namespace for (const ESM::IndexedENAMstruct& effect : effects.mList) { int effectIdx = ESM::MagicEffect::refIdToIndex(effect.mData.mEffectID); + int skillIdx = ESM::Skill::refIdToIndex(effect.mData.mSkill); + int attributeIdx = ESM::Attribute::refIdToIndex(effect.mData.mAttribute); if (effectIdx != -1) std::cout << " Effect[" << i << "]: " << magicEffectLabel(effectIdx) << " (" << effectIdx << ")" << std::endl; - if (effect.mData.mSkill != -1) - std::cout << " Skill: " << skillLabel(effect.mData.mSkill) << " (" << (int)effect.mData.mSkill << ")" + if (skillIdx != -1) + std::cout << " Skill: " << skillLabel(skillIdx) << " (" << skillIdx << ")" << std::endl; + if (attributeIdx != -1) + std::cout << " Attribute: " << attributeLabel(attributeIdx) << " (" << attributeIdx << ")" << std::endl; - if (effect.mData.mAttribute != -1) - std::cout << " Attribute: " << attributeLabel(effect.mData.mAttribute) << " (" - << (int)effect.mData.mAttribute << ")" << std::endl; std::cout << " Range: " << rangeTypeLabel(effect.mData.mRange) << " (" << effect.mData.mRange << ")" << std::endl; // Area is always zero if range type is "Self" diff --git a/apps/opencs/model/tools/effectlistcheck.cpp b/apps/opencs/model/tools/effectlistcheck.cpp index 461950e457..4ad8d908d0 100644 --- a/apps/opencs/model/tools/effectlistcheck.cpp +++ b/apps/opencs/model/tools/effectlistcheck.cpp @@ -27,11 +27,13 @@ namespace CSMTools // At the time of writing this effects, attributes and skills are mostly hardcoded int effectIndex = ESM::MagicEffect::refIdToIndex(effect.mData.mEffectID); + int skillIndex = ESM::Skill::refIdToIndex(effect.mData.mSkill); + int attributeIndex = ESM::Attribute::refIdToIndex(effect.mData.mAttribute); if (effectIndex < -1 || effectIndex >= ESM::MagicEffect::Length) messages.add(id, "Effect #" + number + ": invalid effect ID", "", CSMDoc::Message::Severity_Error); - if (effect.mData.mSkill < -1 || effect.mData.mSkill >= ESM::Skill::Length) + if (skillIndex < -1 || skillIndex >= ESM::Skill::Length) messages.add(id, "Effect #" + number + ": invalid skill", "", CSMDoc::Message::Severity_Error); - if (effect.mData.mAttribute < -1 || effect.mData.mAttribute >= ESM::Attribute::Length) + if (attributeIndex < -1 || attributeIndex >= ESM::Attribute::Length) messages.add(id, "Effect #" + number + ": invalid attribute", "", CSMDoc::Message::Severity_Error); if (effect.mData.mRange < ESM::RT_Self || effect.mData.mRange > ESM::RT_Target) diff --git a/apps/opencs/model/world/nestedcoladapterimp.hpp b/apps/opencs/model/world/nestedcoladapterimp.hpp index 2d5247f106..276ea48d5d 100644 --- a/apps/opencs/model/world/nestedcoladapterimp.hpp +++ b/apps/opencs/model/world/nestedcoladapterimp.hpp @@ -9,8 +9,10 @@ #include #include +#include #include #include // for converting magic effect id to string & back +#include #include "idcollection.hpp" #include "nestedcolumnadapter.hpp" @@ -267,8 +269,8 @@ namespace CSMWorld ESM::IndexedENAMstruct effect; effect.mIndex = position; effect.mData.mEffectID = ESM::MagicEffect::WaterBreathing; - effect.mData.mSkill = -1; - effect.mData.mAttribute = -1; + effect.mData.mSkill = ESM::RefId(); + effect.mData.mAttribute = ESM::RefId(); effect.mData.mRange = 0; effect.mData.mArea = 0; effect.mData.mDuration = 0; @@ -339,14 +341,14 @@ namespace CSMWorld case 1: { if (targetSkill) - return effect.mSkill; + return ESM::Skill::refIdToIndex(effect.mSkill); else return QVariant(); } case 2: { if (targetAttribute) - return effect.mAttribute; + return ESM::Attribute::refIdToIndex(effect.mAttribute); else return QVariant(); } @@ -389,19 +391,19 @@ namespace CSMWorld targetAttribute = mgef.mData.mFlags & ESM::MagicEffect::TargetAttribute; } if (!targetSkill) - effect.mSkill = -1; + effect.mSkill = ESM::RefId(); if (!targetAttribute) - effect.mAttribute = -1; + effect.mAttribute = ESM::RefId(); break; } case 1: { - effect.mSkill = static_cast(value.toInt()); + effect.mSkill = ESM::Skill::indexToRefId(value.toInt()); break; } case 2: { - effect.mAttribute = static_cast(value.toInt()); + effect.mAttribute = ESM::Attribute::indexToRefId(value.toInt()); break; } case 3: diff --git a/apps/openmw/mwgui/spellcreationdialog.cpp b/apps/openmw/mwgui/spellcreationdialog.cpp index 5795b87e83..17d4c35456 100644 --- a/apps/openmw/mwgui/spellcreationdialog.cpp +++ b/apps/openmw/mwgui/spellcreationdialog.cpp @@ -48,8 +48,8 @@ namespace effect.mMagnMax = 0; effect.mMagnMin = 0; effect.mRange = 0; - effect.mSkill = -1; - effect.mAttribute = -1; + effect.mSkill = ESM::RefId(); + effect.mAttribute = ESM::RefId(); } } @@ -143,8 +143,8 @@ namespace MWGui mEffect.mMagnMax = 1; mEffect.mDuration = 1; mEffect.mArea = 0; - mEffect.mSkill = -1; - mEffect.mAttribute = -1; + mEffect.mSkill = ESM::RefId(); + mEffect.mAttribute = ESM::RefId(); eventEffectAdded(mEffect); onRangeButtonClicked(mRangeButton); @@ -331,13 +331,13 @@ namespace MWGui void EditEffectDialog::setSkill(ESM::RefId skill) { - mEffect.mSkill = static_cast(ESM::Skill::refIdToIndex(skill)); + mEffect.mSkill = skill; eventEffectModified(mEffect); } void EditEffectDialog::setAttribute(ESM::RefId attribute) { - mEffect.mAttribute = static_cast(ESM::Attribute::refIdToIndex(attribute)); + mEffect.mAttribute = attribute; eventEffectModified(mEffect); } @@ -961,8 +961,8 @@ namespace MWGui { Widgets::SpellEffectParams params; params.mEffectID = effectInfo.mEffectID; - params.mSkill = ESM::Skill::indexToRefId(effectInfo.mSkill); - params.mAttribute = ESM::Attribute::indexToRefId(effectInfo.mAttribute); + params.mSkill = effectInfo.mSkill; + params.mAttribute = effectInfo.mAttribute; params.mDuration = effectInfo.mDuration; params.mMagnMin = effectInfo.mMagnMin; params.mMagnMax = effectInfo.mMagnMax; diff --git a/apps/openmw/mwgui/spellmodel.cpp b/apps/openmw/mwgui/spellmodel.cpp index f390e7ff50..78c460c090 100644 --- a/apps/openmw/mwgui/spellmodel.cpp +++ b/apps/openmw/mwgui/spellmodel.cpp @@ -53,9 +53,8 @@ namespace MWGui if (!effectId.empty()) { const ESM::MagicEffect* magicEffect = store.get().find(effectId); - const ESM::Attribute* attribute - = store.get().search(ESM::Attribute::indexToRefId(effect.mData.mAttribute)); - const ESM::Skill* skill = store.get().search(ESM::Skill::indexToRefId(effect.mData.mSkill)); + const ESM::Attribute* attribute = store.get().search(effect.mData.mAttribute); + const ESM::Skill* skill = store.get().search(effect.mData.mSkill); std::string fullEffectName = MWMechanics::getMagicEffectString(*magicEffect, attribute, skill); std::string convert = Utf8Stream::lowerCaseUtf8(fullEffectName); diff --git a/apps/openmw/mwgui/tooltips.cpp b/apps/openmw/mwgui/tooltips.cpp index 5ab408f533..4803fe1c60 100644 --- a/apps/openmw/mwgui/tooltips.cpp +++ b/apps/openmw/mwgui/tooltips.cpp @@ -228,8 +228,8 @@ namespace MWGui { Widgets::SpellEffectParams params; params.mEffectID = spellEffect.mData.mEffectID; - params.mSkill = ESM::Skill::indexToRefId(spellEffect.mData.mSkill); - params.mAttribute = ESM::Attribute::indexToRefId(spellEffect.mData.mAttribute); + params.mSkill = spellEffect.mData.mSkill; + params.mAttribute = spellEffect.mData.mAttribute; params.mDuration = spellEffect.mData.mDuration; params.mMagnMin = spellEffect.mData.mMagnMin; params.mMagnMax = spellEffect.mData.mMagnMax; diff --git a/apps/openmw/mwgui/widgets.cpp b/apps/openmw/mwgui/widgets.cpp index a4ca75d21d..0c4793e50f 100644 --- a/apps/openmw/mwgui/widgets.cpp +++ b/apps/openmw/mwgui/widgets.cpp @@ -216,8 +216,8 @@ namespace MWGui::Widgets = creator->createWidget("MW_EffectImage", coord, MyGUI::Align::Default); SpellEffectParams params; params.mEffectID = effectInfo.mData.mEffectID; - params.mSkill = ESM::Skill::indexToRefId(effectInfo.mData.mSkill); - params.mAttribute = ESM::Attribute::indexToRefId(effectInfo.mData.mAttribute); + params.mSkill = effectInfo.mData.mSkill; + params.mAttribute = effectInfo.mData.mAttribute; params.mDuration = effectInfo.mData.mDuration; params.mMagnMin = effectInfo.mData.mMagnMin; params.mMagnMax = effectInfo.mData.mMagnMax; @@ -333,8 +333,8 @@ namespace MWGui::Widgets { SpellEffectParams params; params.mEffectID = effectInfo.mData.mEffectID; - params.mSkill = ESM::Skill::indexToRefId(effectInfo.mData.mSkill); - params.mAttribute = ESM::Attribute::indexToRefId(effectInfo.mData.mAttribute); + params.mSkill = effectInfo.mData.mSkill; + params.mAttribute = effectInfo.mData.mAttribute; params.mDuration = effectInfo.mData.mDuration; params.mMagnMin = effectInfo.mData.mMagnMin; params.mMagnMax = effectInfo.mData.mMagnMax; diff --git a/apps/openmw/mwlua/magicbindings.cpp b/apps/openmw/mwlua/magicbindings.cpp index 264ae2fca1..1d8c92854f 100644 --- a/apps/openmw/mwlua/magicbindings.cpp +++ b/apps/openmw/mwlua/magicbindings.cpp @@ -323,16 +323,14 @@ namespace MWLua [](const ESM::IndexedENAMstruct& params) -> ESM::RefId { return params.mData.mEffectID; }); effectParamsT["affectedSkill"] = sol::readonly_property([](const ESM::IndexedENAMstruct& params) -> sol::optional { - ESM::RefId id = ESM::Skill::indexToRefId(params.mData.mSkill); - if (!id.empty()) - return id.serializeText(); + if (!params.mData.mSkill.empty()) + return params.mData.mSkill.serializeText(); return sol::nullopt; }); effectParamsT["affectedAttribute"] = sol::readonly_property([](const ESM::IndexedENAMstruct& params) -> sol::optional { - ESM::RefId id = ESM::Attribute::indexToRefId(params.mData.mAttribute); - if (!id.empty()) - return id.serializeText(); + if (!params.mData.mAttribute.empty()) + return params.mData.mAttribute.serializeText(); return sol::nullopt; }); effectParamsT["range"] diff --git a/apps/openmw/mwlua/types/ingredient.cpp b/apps/openmw/mwlua/types/ingredient.cpp index 0089ce2457..ec9cbf693c 100644 --- a/apps/openmw/mwlua/types/ingredient.cpp +++ b/apps/openmw/mwlua/types/ingredient.cpp @@ -50,8 +50,8 @@ namespace MWLua continue; ESM::IndexedENAMstruct effect; effect.mData.mEffectID = rec.mData.mEffectID[i]; - effect.mData.mSkill = static_cast(rec.mData.mSkills[i]); - effect.mData.mAttribute = static_cast(rec.mData.mAttributes[i]); + effect.mData.mSkill = ESM::Skill::indexToRefId(rec.mData.mSkills[i]); + effect.mData.mAttribute = ESM::Attribute::indexToRefId(rec.mData.mAttributes[i]); effect.mData.mRange = ESM::RT_Self; effect.mData.mArea = 0; effect.mData.mDuration = 0; diff --git a/apps/openmw/mwmechanics/alchemy.cpp b/apps/openmw/mwmechanics/alchemy.cpp index f748988e42..eeb4a60bfb 100644 --- a/apps/openmw/mwmechanics/alchemy.cpp +++ b/apps/openmw/mwmechanics/alchemy.cpp @@ -220,13 +220,13 @@ void MWMechanics::Alchemy::updateEffects() ESM::ENAMstruct effect; effect.mEffectID = effectKey.mId; - effect.mAttribute = -1; - effect.mSkill = -1; + effect.mAttribute = ESM::RefId(); + effect.mSkill = ESM::RefId(); if (magicEffect->mData.mFlags & ESM::MagicEffect::TargetSkill) - effect.mSkill = static_cast(ESM::Skill::refIdToIndex(effectKey.mArg)); + effect.mSkill = effectKey.mArg; else if (magicEffect->mData.mFlags & ESM::MagicEffect::TargetAttribute) - effect.mAttribute = static_cast(ESM::Attribute::refIdToIndex(effectKey.mArg)); + effect.mAttribute = effectKey.mArg; effect.mRange = 0; effect.mArea = 0; diff --git a/apps/openmw/mwmechanics/autocalcspell.cpp b/apps/openmw/mwmechanics/autocalcspell.cpp index dcd3ec7dcb..626e5593cc 100644 --- a/apps/openmw/mwmechanics/autocalcspell.cpp +++ b/apps/openmw/mwmechanics/autocalcspell.cpp @@ -230,16 +230,14 @@ namespace MWMechanics if ((magicEffect->mData.mFlags & ESM::MagicEffect::TargetSkill)) { - ESM::RefId skill = ESM::Skill::indexToRefId(spellEffect.mData.mSkill); - auto found = actorSkills.find(skill); + auto found = actorSkills.find(spellEffect.mData.mSkill); if (found == actorSkills.end() || found->second.getBase() < iAutoSpellAttSkillMin) return false; } if ((magicEffect->mData.mFlags & ESM::MagicEffect::TargetAttribute)) { - ESM::RefId attribute = ESM::Attribute::indexToRefId(spellEffect.mData.mAttribute); - auto found = actorAttributes.find(attribute); + auto found = actorAttributes.find(spellEffect.mData.mAttribute); if (found == actorAttributes.end() || found->second.getBase() < iAutoSpellAttSkillMin) return false; } diff --git a/apps/openmw/mwmechanics/magiceffects.cpp b/apps/openmw/mwmechanics/magiceffects.cpp index 05d50ced0f..4d1c27eb2f 100644 --- a/apps/openmw/mwmechanics/magiceffects.cpp +++ b/apps/openmw/mwmechanics/magiceffects.cpp @@ -33,15 +33,14 @@ namespace MWMechanics EffectKey::EffectKey(const ESM::ENAMstruct& effect) { mId = effect.mEffectID; - mArg = ESM::Skill::indexToRefId(effect.mSkill); + mArg = effect.mSkill; - ESM::RefId attribute = ESM::Attribute::indexToRefId(effect.mAttribute); - if (!attribute.empty()) + if (!effect.mAttribute.empty()) { if (!mArg.empty()) throw std::runtime_error("magic effect can't have both a skill and an attribute argument"); - mArg = attribute; + mArg = effect.mAttribute; } } diff --git a/apps/openmw/mwmechanics/spellpriority.cpp b/apps/openmw/mwmechanics/spellpriority.cpp index e93fb6f217..912857a70c 100644 --- a/apps/openmw/mwmechanics/spellpriority.cpp +++ b/apps/openmw/mwmechanics/spellpriority.cpp @@ -541,14 +541,11 @@ namespace MWMechanics || effect.mEffectID == ESM::MagicEffect::DrainAttribute) { if (!enemy.isEmpty() - && enemy.getClass() - .getCreatureStats(enemy) - .getAttribute(ESM::Attribute::indexToRefId(effect.mAttribute)) - .getModified() - <= 0) + && enemy.getClass().getCreatureStats(enemy).getAttribute(effect.mAttribute).getModified() <= 0) return 0.f; { - if (effect.mAttribute >= 0 && effect.mAttribute < ESM::Attribute::Length) + int attributeIdx = ESM::Attribute::refIdToIndex(effect.mAttribute); + if (attributeIdx >= 0 && attributeIdx < ESM::Attribute::Length) { const float attributePriorities[ESM::Attribute::Length] = { 1.0f, // Strength @@ -560,7 +557,7 @@ namespace MWMechanics 0.7f, // Personality 0.3f // Luck }; - rating *= attributePriorities[effect.mAttribute]; + rating *= attributePriorities[attributeIdx]; } } } @@ -569,7 +566,7 @@ namespace MWMechanics { if (enemy.isEmpty() || !enemy.getClass().isNpc()) return 0.f; - if (enemy.getClass().getSkill(enemy, ESM::Skill::indexToRefId(effect.mSkill)) <= 0) + if (enemy.getClass().getSkill(enemy, effect.mSkill) <= 0) return 0.f; } diff --git a/apps/openmw/mwmechanics/spellutil.cpp b/apps/openmw/mwmechanics/spellutil.cpp index 67e9084b29..27d2a9e9c9 100644 --- a/apps/openmw/mwmechanics/spellutil.cpp +++ b/apps/openmw/mwmechanics/spellutil.cpp @@ -167,8 +167,8 @@ namespace MWMechanics ESM::ENAMstruct effect; effect.mEffectID = ingredient->mData.mEffectID[index]; - effect.mSkill = static_cast(ingredient->mData.mSkills[index]); - effect.mAttribute = static_cast(ingredient->mData.mAttributes[index]); + effect.mSkill = ESM::Skill::indexToRefId(ingredient->mData.mSkills[index]); + effect.mAttribute = ESM::Attribute::indexToRefId(ingredient->mData.mAttributes[index]); effect.mRange = ESM::RT_Self; effect.mArea = 0; diff --git a/apps/openmw/mwworld/esmstore.cpp b/apps/openmw/mwworld/esmstore.cpp index 869ba86f48..e0cf1ae8e5 100644 --- a/apps/openmw/mwworld/esmstore.cpp +++ b/apps/openmw/mwworld/esmstore.cpp @@ -181,18 +181,18 @@ namespace continue; } - if (!(mgef->mData.mFlags & ESM::MagicEffect::TargetAttribute) && iter->mData.mAttribute != -1) + if (!(mgef->mData.mFlags & ESM::MagicEffect::TargetAttribute) && !iter->mData.mAttribute.empty()) { - iter->mData.mAttribute = -1; + iter->mData.mAttribute = ESM::RefId(); Log(Debug::Verbose) << RecordType::getRecordType() << " " << spell.mId << ": dropping unexpected attribute argument of " << iter->mData.mEffectID << " effect"; changed = true; } - if (!(mgef->mData.mFlags & ESM::MagicEffect::TargetSkill) && iter->mData.mSkill != -1) + if (!(mgef->mData.mFlags & ESM::MagicEffect::TargetSkill) && !iter->mData.mSkill.empty()) { - iter->mData.mSkill = -1; + iter->mData.mSkill = ESM::RefId(); Log(Debug::Verbose) << RecordType::getRecordType() << " " << spell.mId << ": dropping unexpected skill argument of " << iter->mData.mEffectID << " effect"; diff --git a/apps/openmw/mwworld/magiceffects.cpp b/apps/openmw/mwworld/magiceffects.cpp index ff38d909ae..4ea076c156 100644 --- a/apps/openmw/mwworld/magiceffects.cpp +++ b/apps/openmw/mwworld/magiceffects.cpp @@ -48,7 +48,7 @@ namespace MWWorld for (auto& effect : spell->mEffects.mList) { if (effect.mData.mEffectID == ESM::MagicEffect::DrainAttribute) - stats.mWorsenings[effect.mData.mAttribute] = oldStats.mWorsenings; + stats.mWorsenings[ESM::Attribute::refIdToIndex(effect.mData.mAttribute)] = oldStats.mWorsenings; } creatureStats.mCorprusSpells[id] = stats; } diff --git a/components/esm3/effectlist.cpp b/components/esm3/effectlist.cpp index 2cfa279eb8..7a7841d9ed 100644 --- a/components/esm3/effectlist.cpp +++ b/components/esm3/effectlist.cpp @@ -34,8 +34,8 @@ namespace ESM if (index < 0 || index >= ESM::MagicEffect::Length) throw std::runtime_error(std::format("Cannot serialize effect {}", src.mEffectID.toDebugString())); dst.mEffectID = index; - dst.mSkill = src.mSkill; - dst.mAttribute = src.mAttribute; + dst.mSkill = static_cast(ESM::Skill::refIdToIndex(src.mSkill)); + dst.mAttribute = static_cast(ESM::Attribute::refIdToIndex(src.mAttribute)); dst.mRange = src.mRange; dst.mArea = src.mArea; dst.mDuration = src.mDuration; @@ -49,8 +49,8 @@ namespace ESM if (index < 0 || index >= ESM::MagicEffect::Length) throw std::runtime_error(std::format("Cannot deserialize effect into ENAM with index {}.", index)); dst.mEffectID = ESM::MagicEffect::indexToRefId(index); - dst.mSkill = src.mSkill; - dst.mAttribute = src.mAttribute; + dst.mSkill = ESM::Skill::indexToRefId(src.mSkill); + dst.mAttribute = ESM::Attribute::indexToRefId(src.mAttribute); dst.mRange = src.mRange; dst.mArea = src.mArea; dst.mDuration = src.mDuration; @@ -118,8 +118,8 @@ namespace ESM esm.getSubComposite(p); setEffectParams(p, s); s.mEffectID = esm.getHNRefId("ENID"); - s.mSkill = static_cast(ESM::Skill::refIdToIndex(esm.getHNORefId("ENSK"))); - s.mAttribute = static_cast(ESM::Attribute::refIdToIndex(esm.getHNORefId("ENAT"))); + s.mSkill = esm.getHNORefId("ENSK"); + s.mAttribute = esm.getHNORefId("ENAT"); } mList.push_back({ s, static_cast(mList.size()) }); } @@ -142,8 +142,8 @@ namespace ESM setEffectParams(enam.mData, p); esm.writeNamedComposite("ENAM", p); esm.writeHNRefId("ENID", enam.mData.mEffectID); - esm.writeHNORefId("ENSK", ESM::Skill::indexToRefId(enam.mData.mSkill)); - esm.writeHNORefId("ENAT", ESM::Attribute::indexToRefId(enam.mData.mAttribute)); + esm.writeHNORefId("ENSK", enam.mData.mSkill); + esm.writeHNORefId("ENAT", enam.mData.mAttribute); } } } diff --git a/components/esm3/effectlist.hpp b/components/esm3/effectlist.hpp index f7350f40fc..3a93589412 100644 --- a/components/esm3/effectlist.hpp +++ b/components/esm3/effectlist.hpp @@ -21,7 +21,7 @@ namespace ESM // Which skills/attributes are affected (for restore/drain spells // etc.) - signed char mSkill, mAttribute; // -1 if N/A + ESM::RefId mSkill, mAttribute; // EmptyRefId if N/A // Other spell parameters int32_t mRange; // 0 - self, 1 - touch, 2 - target (RangeType enum)