mirror of
https://github.com/OpenMW/openmw.git
synced 2025-02-28 12:39:41 +00:00
Assign StringRefIds to attributes
This commit is contained in:
parent
11ae1a1fcb
commit
e660a9ca16
53 changed files with 415 additions and 306 deletions
|
@ -1171,9 +1171,6 @@ namespace EsmTool
|
|||
template <>
|
||||
void Record<ESM::Race>::print()
|
||||
{
|
||||
static const char* sAttributeNames[ESM::Attribute::Length]
|
||||
= { "Strength", "Intelligence", "Willpower", "Agility", "Speed", "Endurance", "Personality", "Luck" };
|
||||
|
||||
std::cout << " Name: " << mData.mName << std::endl;
|
||||
std::cout << " Description: " << mData.mDescription << std::endl;
|
||||
std::cout << " Flags: " << raceFlags(mData.mData.mFlags) << std::endl;
|
||||
|
@ -1185,8 +1182,8 @@ namespace EsmTool
|
|||
std::cout << (male ? " Male:" : " Female:") << std::endl;
|
||||
|
||||
for (int j = 0; j < ESM::Attribute::Length; ++j)
|
||||
std::cout << " " << sAttributeNames[j] << ": " << mData.mData.mAttributeValues[j].getValue(male)
|
||||
<< std::endl;
|
||||
std::cout << " " << ESM::Attribute::indexToRefId(j) << ": "
|
||||
<< mData.mData.mAttributeValues[j].getValue(male) << std::endl;
|
||||
|
||||
std::cout << " Height: " << mData.mData.mHeight.getValue(male) << std::endl;
|
||||
std::cout << " Weight: " << mData.mData.mWeight.getValue(male) << std::endl;
|
||||
|
|
|
@ -138,12 +138,9 @@ namespace MWClass
|
|||
continue;
|
||||
MWGui::Widgets::SpellEffectParams params;
|
||||
params.mEffectID = ref->mBase->mData.mEffectID[i];
|
||||
params.mAttribute = ref->mBase->mData.mAttributes[i];
|
||||
params.mSkill = ref->mBase->mData.mSkills[i];
|
||||
|
||||
params.mKnown = ((i == 0 && alchemySkill >= fWortChanceValue)
|
||||
|| (i == 1 && alchemySkill >= fWortChanceValue * 2) || (i == 2 && alchemySkill >= fWortChanceValue * 3)
|
||||
|| (i == 3 && alchemySkill >= fWortChanceValue * 4));
|
||||
params.mAttribute = ESM::Attribute::indexToRefId(ref->mBase->mData.mAttributes[i]);
|
||||
params.mSkill = ESM::Skill::indexToRefId(ref->mBase->mData.mSkills[i]);
|
||||
params.mKnown = alchemySkill >= fWortChanceValue * (i + 1);
|
||||
|
||||
list.push_back(params);
|
||||
}
|
||||
|
|
|
@ -93,7 +93,8 @@ namespace
|
|||
int level = creatureStats.getLevel();
|
||||
for (const ESM::Attribute& attribute : attributes)
|
||||
{
|
||||
const ESM::Race::MaleFemale& value = race->mData.mAttributeValues[attribute.mId];
|
||||
const ESM::Race::MaleFemale& value
|
||||
= race->mData.mAttributeValues[ESM::Attribute::refIdToIndex(attribute.mId)];
|
||||
creatureStats.setAttribute(attribute.mId, male ? value.mMale : value.mFemale);
|
||||
}
|
||||
|
||||
|
@ -104,7 +105,7 @@ namespace
|
|||
{
|
||||
if (attribute >= 0 && attribute < ESM::Attribute::Length)
|
||||
{
|
||||
auto id = static_cast<ESM::Attribute::AttributeID>(attribute);
|
||||
auto id = ESM::Attribute::indexToRefId(attribute);
|
||||
creatureStats.setAttribute(id, creatureStats.getAttribute(id).getBase() + 10);
|
||||
}
|
||||
}
|
||||
|
@ -113,10 +114,11 @@ namespace
|
|||
for (const ESM::Attribute& attribute : attributes)
|
||||
{
|
||||
float modifierSum = 0;
|
||||
int attributeIndex = ESM::Attribute::refIdToIndex(attribute.mId);
|
||||
|
||||
for (const ESM::Skill& skill : MWBase::Environment::get().getESMStore()->get<ESM::Skill>())
|
||||
{
|
||||
if (skill.mData.mAttribute != attribute.mId)
|
||||
if (skill.mData.mAttribute != attributeIndex)
|
||||
continue;
|
||||
|
||||
// is this a minor or major skill?
|
||||
|
@ -148,7 +150,8 @@ namespace
|
|||
else if (class_->mData.mSpecialization == ESM::Class::Stealth)
|
||||
multiplier += 1;
|
||||
|
||||
if (std::find(class_->mData.mAttribute.begin(), class_->mData.mAttribute.end(), ESM::Attribute::Endurance)
|
||||
if (std::find(class_->mData.mAttribute.begin(), class_->mData.mAttribute.end(),
|
||||
ESM::Attribute::refIdToIndex(ESM::Attribute::Endurance))
|
||||
!= class_->mData.mAttribute.end())
|
||||
multiplier += 1;
|
||||
|
||||
|
|
|
@ -383,7 +383,7 @@ int MWDialogue::Filter::getSelectStructInteger(const SelectWrapper& select) cons
|
|||
|
||||
case SelectWrapper::Function_PcAttribute:
|
||||
{
|
||||
auto attribute = static_cast<ESM::Attribute::AttributeID>(select.getArgument());
|
||||
ESM::RefId attribute = ESM::Attribute::indexToRefId(select.getArgument());
|
||||
return player.getClass().getCreatureStats(player).getAttribute(attribute).getModified();
|
||||
}
|
||||
case SelectWrapper::Function_PcSkill:
|
||||
|
@ -654,9 +654,9 @@ bool MWDialogue::Filter::hasFactionRankSkillRequirements(
|
|||
|
||||
MWMechanics::CreatureStats& stats = actor.getClass().getCreatureStats(actor);
|
||||
|
||||
return stats.getAttribute(ESM::Attribute::AttributeID(faction.mData.mAttribute[0])).getBase()
|
||||
return stats.getAttribute(ESM::Attribute::indexToRefId(faction.mData.mAttribute[0])).getBase()
|
||||
>= faction.mData.mRankData[rank].mAttribute1
|
||||
&& stats.getAttribute(ESM::Attribute::AttributeID(faction.mData.mAttribute[1])).getBase()
|
||||
&& stats.getAttribute(ESM::Attribute::indexToRefId(faction.mData.mAttribute[1])).getBase()
|
||||
>= faction.mData.mRankData[rank].mAttribute2;
|
||||
}
|
||||
|
||||
|
|
|
@ -103,7 +103,7 @@ namespace MWGui
|
|||
mPlayerSkillValues.emplace(skill.mId, MWMechanics::SkillValue());
|
||||
}
|
||||
|
||||
void CharacterCreation::setValue(ESM::Attribute::AttributeID id, const MWMechanics::AttributeValue& value)
|
||||
void CharacterCreation::setAttribute(ESM::RefId id, const MWMechanics::AttributeValue& value)
|
||||
{
|
||||
mPlayerAttributes[id] = value;
|
||||
if (mReviewDialog)
|
||||
|
@ -263,8 +263,7 @@ namespace MWGui
|
|||
mReviewDialog->setFatigue(stats.getFatigue());
|
||||
for (auto& attributePair : mPlayerAttributes)
|
||||
{
|
||||
mReviewDialog->setAttribute(
|
||||
static_cast<ESM::Attribute::AttributeID>(attributePair.first), attributePair.second);
|
||||
mReviewDialog->setAttribute(attributePair.first, attributePair.second);
|
||||
}
|
||||
for (const auto& [skill, value] : mPlayerSkillValues)
|
||||
{
|
||||
|
@ -462,9 +461,10 @@ namespace MWGui
|
|||
klass.mData.mIsPlayable = 0x1;
|
||||
klass.mRecordFlags = 0;
|
||||
|
||||
std::vector<int> attributes = mCreateClassDialog->getFavoriteAttributes();
|
||||
assert(attributes.size() == klass.mData.mAttribute.size());
|
||||
std::copy(attributes.begin(), attributes.end(), klass.mData.mAttribute.begin());
|
||||
std::vector<ESM::RefId> attributes = mCreateClassDialog->getFavoriteAttributes();
|
||||
assert(attributes.size() >= klass.mData.mAttribute.size());
|
||||
for (size_t i = 0; i < klass.mData.mAttribute.size(); ++i)
|
||||
klass.mData.mAttribute[i] = ESM::Attribute::refIdToIndex(attributes[i]);
|
||||
|
||||
std::vector<ESM::RefId> majorSkills = mCreateClassDialog->getMajorSkills();
|
||||
std::vector<ESM::RefId> minorSkills = mCreateClassDialog->getMinorSkills();
|
||||
|
|
|
@ -44,7 +44,7 @@ namespace MWGui
|
|||
// Show a dialog
|
||||
void spawnDialog(const char id);
|
||||
|
||||
void setValue(ESM::Attribute::AttributeID id, const MWMechanics::AttributeValue& value) override;
|
||||
void setAttribute(ESM::RefId id, const MWMechanics::AttributeValue& value) override;
|
||||
void setValue(std::string_view id, const MWMechanics::DynamicStat<float>& value) override;
|
||||
void setValue(ESM::RefId id, const MWMechanics::SkillValue& value) override;
|
||||
void configureSkills(const std::vector<ESM::RefId>& major, const std::vector<ESM::RefId>& minor) override;
|
||||
|
@ -56,7 +56,7 @@ namespace MWGui
|
|||
Resource::ResourceSystem* mResourceSystem;
|
||||
|
||||
std::vector<ESM::RefId> mPlayerMajorSkills, mPlayerMinorSkills;
|
||||
std::map<int, MWMechanics::AttributeValue> mPlayerAttributes;
|
||||
std::map<ESM::RefId, MWMechanics::AttributeValue> mPlayerAttributes;
|
||||
std::map<ESM::RefId, MWMechanics::SkillValue> mPlayerSkillValues;
|
||||
|
||||
// Dialogs
|
||||
|
|
|
@ -260,8 +260,8 @@ namespace MWGui
|
|||
mSpecializationName->setCaption(specName);
|
||||
ToolTips::createSpecializationToolTip(mSpecializationName, specName, specialization);
|
||||
|
||||
mFavoriteAttribute[0]->setAttributeId(static_cast<ESM::Attribute::AttributeID>(klass->mData.mAttribute[0]));
|
||||
mFavoriteAttribute[1]->setAttributeId(static_cast<ESM::Attribute::AttributeID>(klass->mData.mAttribute[1]));
|
||||
mFavoriteAttribute[0]->setAttributeId(ESM::Attribute::indexToRefId(klass->mData.mAttribute[0]));
|
||||
mFavoriteAttribute[1]->setAttributeId(ESM::Attribute::indexToRefId(klass->mData.mAttribute[1]));
|
||||
ToolTips::createAttributeToolTip(mFavoriteAttribute[0], mFavoriteAttribute[0]->getAttributeId());
|
||||
ToolTips::createAttributeToolTip(mFavoriteAttribute[1], mFavoriteAttribute[1]->getAttributeId());
|
||||
|
||||
|
@ -509,9 +509,9 @@ namespace MWGui
|
|||
return mSpecializationId;
|
||||
}
|
||||
|
||||
std::vector<int> CreateClassDialog::getFavoriteAttributes() const
|
||||
std::vector<ESM::RefId> CreateClassDialog::getFavoriteAttributes() const
|
||||
{
|
||||
std::vector<int> v;
|
||||
std::vector<ESM::RefId> v;
|
||||
v.push_back(mFavoriteAttribute0->getAttributeId());
|
||||
v.push_back(mFavoriteAttribute1->getAttributeId());
|
||||
return v;
|
||||
|
@ -599,7 +599,7 @@ namespace MWGui
|
|||
|
||||
void CreateClassDialog::onAttributeSelected()
|
||||
{
|
||||
ESM::Attribute::AttributeID id = mAttribDialog->getAttributeId();
|
||||
ESM::RefId id = mAttribDialog->getAttributeId();
|
||||
if (mAffectedAttribute == mFavoriteAttribute0)
|
||||
{
|
||||
if (mFavoriteAttribute1->getAttributeId() == id)
|
||||
|
|
|
@ -188,7 +188,7 @@ namespace MWGui
|
|||
|
||||
bool exit() override;
|
||||
|
||||
ESM::Attribute::AttributeID getAttributeId() const { return mAttributeId; }
|
||||
ESM::RefId getAttributeId() const { return mAttributeId; }
|
||||
|
||||
// Events
|
||||
typedef MyGUI::delegates::MultiDelegate<> EventHandle_Void;
|
||||
|
@ -208,7 +208,7 @@ namespace MWGui
|
|||
void onCancelClicked(MyGUI::Widget* _sender);
|
||||
|
||||
private:
|
||||
ESM::Attribute::AttributeID mAttributeId;
|
||||
ESM::RefId mAttributeId;
|
||||
};
|
||||
|
||||
class SelectSkillDialog : public WindowModal
|
||||
|
@ -274,7 +274,7 @@ namespace MWGui
|
|||
std::string getName() const;
|
||||
std::string getDescription() const;
|
||||
ESM::Class::Specialization getSpecializationId() const;
|
||||
std::vector<int> getFavoriteAttributes() const;
|
||||
std::vector<ESM::RefId> getFavoriteAttributes() const;
|
||||
std::vector<ESM::RefId> getMajorSkills() const;
|
||||
std::vector<ESM::RefId> getMinorSkills() const;
|
||||
|
||||
|
|
|
@ -200,7 +200,7 @@ namespace MWGui
|
|||
mFatigue->setUserString("Caption_HealthDescription", "#{sFatDesc}\n" + valStr);
|
||||
}
|
||||
|
||||
void ReviewDialog::setAttribute(ESM::Attribute::AttributeID attributeId, const MWMechanics::AttributeValue& value)
|
||||
void ReviewDialog::setAttribute(ESM::RefId attributeId, const MWMechanics::AttributeValue& value)
|
||||
{
|
||||
auto attr = mAttributeWidgets.find(attributeId);
|
||||
if (attr == mAttributeWidgets.end())
|
||||
|
@ -412,7 +412,7 @@ namespace MWGui
|
|||
if (!mRaceId.empty())
|
||||
race = MWBase::Environment::get().getESMStore()->get<ESM::Race>().find(mRaceId);
|
||||
|
||||
std::map<ESM::Attribute::AttributeID, MWMechanics::AttributeValue> attributes;
|
||||
std::map<ESM::RefId, MWMechanics::AttributeValue> attributes;
|
||||
for (const auto& [key, value] : mAttributeWidgets)
|
||||
attributes[key] = value->getAttributeValue();
|
||||
|
||||
|
|
|
@ -3,7 +3,6 @@
|
|||
|
||||
#include "widgets.hpp"
|
||||
#include "windowbase.hpp"
|
||||
#include <components/esm/attr.hpp>
|
||||
#include <components/esm/refid.hpp>
|
||||
#include <components/esm3/loadclas.hpp>
|
||||
|
||||
|
@ -38,7 +37,7 @@ namespace MWGui
|
|||
void setMagicka(const MWMechanics::DynamicStat<float>& value);
|
||||
void setFatigue(const MWMechanics::DynamicStat<float>& value);
|
||||
|
||||
void setAttribute(ESM::Attribute::AttributeID attributeId, const MWMechanics::AttributeValue& value);
|
||||
void setAttribute(ESM::RefId attributeId, const MWMechanics::AttributeValue& value);
|
||||
|
||||
void configureSkills(const std::vector<ESM::RefId>& major, const std::vector<ESM::RefId>& minor);
|
||||
void setSkillValue(ESM::RefId id, const MWMechanics::SkillValue& value);
|
||||
|
@ -90,7 +89,7 @@ namespace MWGui
|
|||
|
||||
Widgets::MWDynamicStatPtr mHealth, mMagicka, mFatigue;
|
||||
|
||||
std::map<ESM::Attribute::AttributeID, Widgets::MWAttributePtr> mAttributeWidgets;
|
||||
std::map<ESM::RefId, Widgets::MWAttributePtr> mAttributeWidgets;
|
||||
|
||||
std::vector<ESM::RefId> mMajorSkills, mMinorSkills, mMiscSkills;
|
||||
std::map<ESM::RefId, MWMechanics::SkillValue> mSkillValues;
|
||||
|
|
|
@ -291,9 +291,9 @@ namespace MWGui
|
|||
eventEffectModified(mEffect);
|
||||
}
|
||||
|
||||
void EditEffectDialog::setAttribute(int attribute)
|
||||
void EditEffectDialog::setAttribute(ESM::RefId attribute)
|
||||
{
|
||||
mEffect.mAttribute = attribute;
|
||||
mEffect.mAttribute = ESM::Attribute::refIdToIndex(attribute);
|
||||
eventEffectModified(mEffect);
|
||||
}
|
||||
|
||||
|
@ -689,8 +689,8 @@ namespace MWGui
|
|||
{
|
||||
Widgets::SpellEffectParams params;
|
||||
params.mEffectID = effectInfo.mEffectID;
|
||||
params.mSkill = effectInfo.mSkill;
|
||||
params.mAttribute = effectInfo.mAttribute;
|
||||
params.mSkill = ESM::Skill::indexToRefId(effectInfo.mSkill);
|
||||
params.mAttribute = ESM::Attribute::indexToRefId(effectInfo.mAttribute);
|
||||
params.mDuration = effectInfo.mDuration;
|
||||
params.mMagnMin = effectInfo.mMagnMin;
|
||||
params.mMagnMax = effectInfo.mMagnMax;
|
||||
|
|
|
@ -31,7 +31,7 @@ namespace MWGui
|
|||
void setConstantEffect(bool constant);
|
||||
|
||||
void setSkill(ESM::RefId skill);
|
||||
void setAttribute(int attribute);
|
||||
void setAttribute(ESM::RefId attribute);
|
||||
|
||||
void newEffect(const ESM::MagicEffect* effect);
|
||||
void editEffect(ESM::ENAMstruct effect);
|
||||
|
|
|
@ -36,7 +36,7 @@ namespace MWGui
|
|||
if (!(effect.mFlags & ESM::ActiveEffect::Flag_Applied))
|
||||
continue;
|
||||
MagicEffectInfo newEffectSource;
|
||||
newEffectSource.mKey = MWMechanics::EffectKey(effect.mEffectId, effect.mArg);
|
||||
newEffectSource.mKey = MWMechanics::EffectKey(effect.mEffectId, effect.getSkillOrAttribute());
|
||||
newEffectSource.mMagnitude = static_cast<int>(effect.mMagnitude);
|
||||
newEffectSource.mPermanent = effect.mDuration == -1.f;
|
||||
newEffectSource.mRemainingTime = effect.mTimeLeft;
|
||||
|
@ -82,8 +82,7 @@ namespace MWGui
|
|||
|
||||
if (effect->mData.mFlags & ESM::MagicEffect::TargetSkill)
|
||||
{
|
||||
const ESM::Skill* skill
|
||||
= store->get<ESM::Skill>().find(ESM::Skill::indexToRefId(effectInfo.mKey.mArg));
|
||||
const ESM::Skill* skill = store->get<ESM::Skill>().find(effectInfo.mKey.mArg);
|
||||
sourcesDescription += " (" + skill->mName + ')';
|
||||
}
|
||||
if (effect->mData.mFlags & ESM::MagicEffect::TargetAttribute)
|
||||
|
|
|
@ -53,7 +53,8 @@ namespace MWGui
|
|||
if (effectId != -1)
|
||||
{
|
||||
const ESM::MagicEffect* magicEffect = store.get<ESM::MagicEffect>().find(effectId);
|
||||
const ESM::Attribute* attribute = store.get<ESM::Attribute>().search(effect.mAttribute);
|
||||
const ESM::Attribute* attribute
|
||||
= store.get<ESM::Attribute>().search(ESM::Attribute::indexToRefId(effect.mAttribute));
|
||||
const ESM::Skill* skill = store.get<ESM::Skill>().search(ESM::Skill::indexToRefId(effect.mSkill));
|
||||
|
||||
std::string fullEffectName = MWMechanics::getMagicEffectString(*magicEffect, attribute, skill);
|
||||
|
|
|
@ -43,7 +43,7 @@ namespace MWGui
|
|||
if (value != mWatchedAttributes[attribute.mId] || mWatchedStatsEmpty)
|
||||
{
|
||||
mWatchedAttributes[attribute.mId] = value;
|
||||
setValue(attribute.mId, value);
|
||||
setAttribute(attribute.mId, value);
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -150,10 +150,10 @@ namespace MWGui
|
|||
mListeners.erase(listener);
|
||||
}
|
||||
|
||||
void StatsWatcher::setValue(ESM::Attribute::AttributeID id, const MWMechanics::AttributeValue& value)
|
||||
void StatsWatcher::setAttribute(ESM::RefId id, const MWMechanics::AttributeValue& value)
|
||||
{
|
||||
for (StatsListener* listener : mListeners)
|
||||
listener->setValue(id, value);
|
||||
listener->setAttribute(id, value);
|
||||
}
|
||||
|
||||
void StatsWatcher::setValue(ESM::RefId id, const MWMechanics::SkillValue& value)
|
||||
|
|
|
@ -19,7 +19,7 @@ namespace MWGui
|
|||
virtual ~StatsListener() = default;
|
||||
|
||||
/// Set value for the given ID.
|
||||
virtual void setValue(ESM::Attribute::AttributeID id, const MWMechanics::AttributeValue& value) {}
|
||||
virtual void setAttribute(ESM::RefId id, const MWMechanics::AttributeValue& value) {}
|
||||
virtual void setValue(std::string_view id, const MWMechanics::DynamicStat<float>& value) {}
|
||||
virtual void setValue(std::string_view, const std::string& value) {}
|
||||
virtual void setValue(std::string_view, int value) {}
|
||||
|
@ -31,7 +31,7 @@ namespace MWGui
|
|||
{
|
||||
MWWorld::Ptr mWatched;
|
||||
|
||||
std::map<ESM::Attribute::AttributeID, MWMechanics::AttributeValue> mWatchedAttributes;
|
||||
std::map<ESM::RefId, MWMechanics::AttributeValue> mWatchedAttributes;
|
||||
std::map<ESM::RefId, MWMechanics::SkillValue> mWatchedSkills;
|
||||
|
||||
MWMechanics::DynamicStat<float> mWatchedHealth;
|
||||
|
@ -50,7 +50,7 @@ namespace MWGui
|
|||
|
||||
std::set<StatsListener*> mListeners;
|
||||
|
||||
void setValue(ESM::Attribute::AttributeID id, const MWMechanics::AttributeValue& value);
|
||||
void setAttribute(ESM::RefId id, const MWMechanics::AttributeValue& value);
|
||||
void setValue(std::string_view id, const MWMechanics::DynamicStat<float>& value);
|
||||
void setValue(std::string_view id, const std::string& value);
|
||||
void setValue(std::string_view id, int value);
|
||||
|
|
|
@ -157,7 +157,7 @@ namespace MWGui
|
|||
mMainWidget->castType<MyGUI::Window>()->setCaption(playerName);
|
||||
}
|
||||
|
||||
void StatsWindow::setValue(ESM::Attribute::AttributeID id, const MWMechanics::AttributeValue& value)
|
||||
void StatsWindow::setAttribute(ESM::RefId id, const MWMechanics::AttributeValue& value)
|
||||
{
|
||||
auto it = mAttributeWidgets.find(id);
|
||||
if (it != mAttributeWidgets.end())
|
||||
|
@ -505,7 +505,8 @@ namespace MWGui
|
|||
continue;
|
||||
}
|
||||
|
||||
const ESM::Attribute* attr = esmStore.get<ESM::Attribute>().find(skill->mData.mAttribute);
|
||||
const ESM::Attribute* attr
|
||||
= esmStore.get<ESM::Attribute>().find(ESM::Attribute::indexToRefId(skill->mData.mAttribute));
|
||||
|
||||
std::pair<MyGUI::TextBox*, MyGUI::TextBox*> widgets
|
||||
= addValueItem(skill->mName, {}, "normal", coord1, coord2);
|
||||
|
@ -620,8 +621,10 @@ namespace MWGui
|
|||
text += std::string("\n\n#{fontcolourhtml=header}#{sNextRank} ") + faction->mRanks[rank + 1];
|
||||
|
||||
const ESM::RankData& rankData = faction->mData.mRankData[rank + 1];
|
||||
const ESM::Attribute* attr1 = store.get<ESM::Attribute>().find(faction->mData.mAttribute[0]);
|
||||
const ESM::Attribute* attr2 = store.get<ESM::Attribute>().find(faction->mData.mAttribute[1]);
|
||||
const ESM::Attribute* attr1 = store.get<ESM::Attribute>().find(
|
||||
ESM::Attribute::indexToRefId(faction->mData.mAttribute[0]));
|
||||
const ESM::Attribute* attr2 = store.get<ESM::Attribute>().find(
|
||||
ESM::Attribute::indexToRefId(faction->mData.mAttribute[1]));
|
||||
|
||||
text += "\n#{fontcolourhtml=normal}" + MyGUI::TextIterator::toTagsString(attr1->mName) + ": "
|
||||
+ MyGUI::utility::toString(rankData.mAttribute1) + ", "
|
||||
|
|
|
@ -22,7 +22,7 @@ namespace MWGui
|
|||
void setPlayerName(const std::string& playerName);
|
||||
|
||||
/// Set value for the given ID.
|
||||
void setValue(ESM::Attribute::AttributeID id, const MWMechanics::AttributeValue& value) override;
|
||||
void setAttribute(ESM::RefId id, const MWMechanics::AttributeValue& value) override;
|
||||
void setValue(std::string_view id, const MWMechanics::DynamicStat<float>& value) override;
|
||||
void setValue(std::string_view id, const std::string& value) override;
|
||||
void setValue(std::string_view id, int value) override;
|
||||
|
@ -68,7 +68,7 @@ namespace MWGui
|
|||
|
||||
std::vector<ESM::RefId> mMajorSkills, mMinorSkills, mMiscSkills;
|
||||
std::map<ESM::RefId, MWMechanics::SkillValue> mSkillValues;
|
||||
std::map<ESM::Attribute::AttributeID, MyGUI::TextBox*> mAttributeWidgets;
|
||||
std::map<ESM::RefId, MyGUI::TextBox*> mAttributeWidgets;
|
||||
std::map<ESM::RefId, std::pair<MyGUI::TextBox*, MyGUI::TextBox*>> mSkillWidgetMap;
|
||||
std::map<std::string, MyGUI::Widget*> mFactionWidgetMap;
|
||||
FactionList mFactions; ///< Stores a list of factions and the current rank
|
||||
|
|
|
@ -225,8 +225,8 @@ namespace MWGui
|
|||
{
|
||||
Widgets::SpellEffectParams params;
|
||||
params.mEffectID = spellEffect.mEffectID;
|
||||
params.mSkill = spellEffect.mSkill;
|
||||
params.mAttribute = spellEffect.mAttribute;
|
||||
params.mSkill = ESM::Skill::indexToRefId(spellEffect.mSkill);
|
||||
params.mAttribute = ESM::Attribute::indexToRefId(spellEffect.mAttribute);
|
||||
params.mDuration = spellEffect.mDuration;
|
||||
params.mMagnMin = spellEffect.mMagnMin;
|
||||
params.mMagnMax = spellEffect.mMagnMax;
|
||||
|
@ -804,7 +804,8 @@ namespace MWGui
|
|||
|
||||
const MWWorld::ESMStore& store = *MWBase::Environment::get().getESMStore();
|
||||
const ESM::Skill* skill = store.get<ESM::Skill>().find(skillId);
|
||||
const ESM::Attribute* attr = store.get<ESM::Attribute>().find(skill->mData.mAttribute);
|
||||
const ESM::Attribute* attr
|
||||
= store.get<ESM::Attribute>().find(ESM::Attribute::indexToRefId(skill->mData.mAttribute));
|
||||
|
||||
widget->setUserString("ToolTipType", "Layout");
|
||||
widget->setUserString("ToolTipLayout", "SkillNoProgressToolTip");
|
||||
|
@ -815,7 +816,7 @@ namespace MWGui
|
|||
widget->setUserString("ImageTexture_SkillNoProgressImage", skill->mIcon);
|
||||
}
|
||||
|
||||
void ToolTips::createAttributeToolTip(MyGUI::Widget* widget, ESM::Attribute::AttributeID attributeId)
|
||||
void ToolTips::createAttributeToolTip(MyGUI::Widget* widget, ESM::RefId attributeId)
|
||||
{
|
||||
const ESM::Attribute* attribute
|
||||
= MWBase::Environment::get().getESMStore()->get<ESM::Attribute>().search(attributeId);
|
||||
|
|
|
@ -92,7 +92,7 @@ namespace MWGui
|
|||
// these do not create an actual tooltip, but they fill in the data that is required so the tooltip
|
||||
// system knows what to show in case this widget is hovered
|
||||
static void createSkillToolTip(MyGUI::Widget* widget, ESM::RefId skillId);
|
||||
static void createAttributeToolTip(MyGUI::Widget* widget, ESM::Attribute::AttributeID attributeId);
|
||||
static void createAttributeToolTip(MyGUI::Widget* widget, ESM::RefId attributeId);
|
||||
static void createSpecializationToolTip(MyGUI::Widget* widget, const std::string& name, int specId);
|
||||
static void createBirthsignToolTip(MyGUI::Widget* widget, const ESM::RefId& birthsignId);
|
||||
static void createRaceToolTip(MyGUI::Widget* widget, const ESM::Race* playerRace);
|
||||
|
|
|
@ -165,7 +165,7 @@ namespace MWGui
|
|||
|
||||
// You can not train a skill above its governing attribute
|
||||
if (pcStats.getSkill(skill->mId).getBase()
|
||||
>= pcStats.getAttribute(ESM::Attribute::AttributeID(skill->mData.mAttribute)).getBase())
|
||||
>= pcStats.getAttribute(ESM::Attribute::indexToRefId(skill->mData.mAttribute)).getBase())
|
||||
{
|
||||
MWBase::Environment::get().getWindowManager()->messageBox("#{sNotifyMessage17}");
|
||||
return;
|
||||
|
|
|
@ -101,13 +101,12 @@ namespace MWGui::Widgets
|
|||
/* MWAttribute */
|
||||
|
||||
MWAttribute::MWAttribute()
|
||||
: mId(ESM::Attribute::Length)
|
||||
, mAttributeNameWidget(nullptr)
|
||||
: mAttributeNameWidget(nullptr)
|
||||
, mAttributeValueWidget(nullptr)
|
||||
{
|
||||
}
|
||||
|
||||
void MWAttribute::setAttributeId(ESM::Attribute::AttributeID attributeId)
|
||||
void MWAttribute::setAttributeId(ESM::RefId attributeId)
|
||||
{
|
||||
mId = attributeId;
|
||||
updateWidgets();
|
||||
|
@ -204,8 +203,8 @@ namespace MWGui::Widgets
|
|||
= creator->createWidget<MWSpellEffect>("MW_EffectImage", coord, MyGUI::Align::Default);
|
||||
SpellEffectParams params;
|
||||
params.mEffectID = effectInfo.mEffectID;
|
||||
params.mSkill = effectInfo.mSkill;
|
||||
params.mAttribute = effectInfo.mAttribute;
|
||||
params.mSkill = ESM::Skill::indexToRefId(effectInfo.mSkill);
|
||||
params.mAttribute = ESM::Attribute::indexToRefId(effectInfo.mAttribute);
|
||||
params.mDuration = effectInfo.mDuration;
|
||||
params.mMagnMin = effectInfo.mMagnMin;
|
||||
params.mMagnMax = effectInfo.mMagnMax;
|
||||
|
@ -315,8 +314,8 @@ namespace MWGui::Widgets
|
|||
{
|
||||
SpellEffectParams params;
|
||||
params.mEffectID = effectInfo.mEffectID;
|
||||
params.mSkill = effectInfo.mSkill;
|
||||
params.mAttribute = effectInfo.mAttribute;
|
||||
params.mSkill = ESM::Skill::indexToRefId(effectInfo.mSkill);
|
||||
params.mAttribute = ESM::Attribute::indexToRefId(effectInfo.mAttribute);
|
||||
params.mDuration = effectInfo.mDuration;
|
||||
params.mMagnMin = effectInfo.mMagnMin;
|
||||
params.mMagnMax = effectInfo.mMagnMax;
|
||||
|
@ -358,7 +357,7 @@ namespace MWGui::Widgets
|
|||
|
||||
const ESM::MagicEffect* magicEffect = store.get<ESM::MagicEffect>().search(mEffectParams.mEffectID);
|
||||
const ESM::Attribute* attribute = store.get<ESM::Attribute>().search(mEffectParams.mAttribute);
|
||||
const ESM::Skill* skill = store.get<ESM::Skill>().search(ESM::Skill::indexToRefId(mEffectParams.mSkill));
|
||||
const ESM::Skill* skill = store.get<ESM::Skill>().search(mEffectParams.mSkill);
|
||||
|
||||
assert(magicEffect);
|
||||
|
||||
|
|
|
@ -41,8 +41,6 @@ namespace MWGui
|
|||
, mNoMagnitude(false)
|
||||
, mKnown(true)
|
||||
, mEffectID(-1)
|
||||
, mSkill(-1)
|
||||
, mAttribute(-1)
|
||||
, mMagnMin(-1)
|
||||
, mMagnMax(-1)
|
||||
, mRange(-1)
|
||||
|
@ -60,8 +58,7 @@ namespace MWGui
|
|||
// value of -1 here means the effect is unknown to the player
|
||||
short mEffectID;
|
||||
|
||||
// value of -1 here means there is no skill/attribute
|
||||
signed char mSkill, mAttribute;
|
||||
ESM::RefId mSkill, mAttribute;
|
||||
|
||||
// value of -1 here means the value is unavailable
|
||||
int mMagnMin, mMagnMax, mRange, mDuration;
|
||||
|
@ -138,10 +135,10 @@ namespace MWGui
|
|||
|
||||
typedef MWMechanics::AttributeValue AttributeValue;
|
||||
|
||||
void setAttributeId(ESM::Attribute::AttributeID attributeId);
|
||||
void setAttributeId(ESM::RefId attributeId);
|
||||
void setAttributeValue(const AttributeValue& value);
|
||||
|
||||
ESM::Attribute::AttributeID getAttributeId() const { return mId; }
|
||||
ESM::RefId getAttributeId() const { return mId; }
|
||||
const AttributeValue& getAttributeValue() const { return mValue; }
|
||||
|
||||
// Events
|
||||
|
@ -162,7 +159,7 @@ namespace MWGui
|
|||
private:
|
||||
void updateWidgets();
|
||||
|
||||
ESM::Attribute::AttributeID mId;
|
||||
ESM::RefId mId;
|
||||
AttributeValue mValue;
|
||||
MyGUI::TextBox* mAttributeNameWidget;
|
||||
MyGUI::TextBox* mAttributeValueWidget;
|
||||
|
|
|
@ -179,11 +179,18 @@ namespace MWLua
|
|||
skills[key] = id;
|
||||
}
|
||||
|
||||
sol::table attribute(context.mLua->sol(), sol::create);
|
||||
api["ATTRIBUTE"] = LuaUtil::makeStrictReadOnly(attribute);
|
||||
for (int id = 0; id < ESM::Attribute::Length; ++id)
|
||||
attribute[ESM::Attribute::sAttributeNames[id]]
|
||||
= Misc::StringUtils::lowerCase(ESM::Attribute::sAttributeNames[id]);
|
||||
// TODO: deprecate this and provide access to the store instead
|
||||
sol::table attributes(context.mLua->sol(), sol::create);
|
||||
api["ATTRIBUTE"] = LuaUtil::makeStrictReadOnly(attributes);
|
||||
for (int i = 0; i < ESM::Attribute::Length; ++i)
|
||||
{
|
||||
ESM::RefId attribute = ESM::Attribute::indexToRefId(i);
|
||||
std::string id = attribute.serializeText();
|
||||
std::string key = Misc::StringUtils::lowerCase(attribute.getRefIdString());
|
||||
// force first character to uppercase for backwards compatability
|
||||
key[0] += 'A' - 'a';
|
||||
attributes[key] = id;
|
||||
}
|
||||
|
||||
return LuaUtil::makeReadOnly(api);
|
||||
}
|
||||
|
|
|
@ -358,10 +358,10 @@ namespace MWLua
|
|||
});
|
||||
effectParamsT["affectedAttribute"]
|
||||
= sol::readonly_property([](const ESM::ENAMstruct& params) -> sol::optional<std::string> {
|
||||
if (params.mAttribute >= 0 && params.mAttribute < ESM::Attribute::Length)
|
||||
return Misc::StringUtils::lowerCase(ESM::Attribute::sAttributeNames[params.mAttribute]);
|
||||
else
|
||||
return sol::nullopt;
|
||||
ESM::RefId id = ESM::Attribute::indexToRefId(params.mAttribute);
|
||||
if (!id.empty())
|
||||
return id.serializeText();
|
||||
return sol::nullopt;
|
||||
});
|
||||
effectParamsT["range"]
|
||||
= sol::readonly_property([](const ESM::ENAMstruct& params) -> int { return params.mRange; });
|
||||
|
@ -419,23 +419,21 @@ namespace MWLua
|
|||
return Misc::StringUtils::lowerCase(name);
|
||||
});
|
||||
activeSpellEffectT["name"] = sol::readonly_property([](const ESM::ActiveEffect& effect) -> std::string {
|
||||
return MWMechanics::EffectKey(effect.mEffectId, effect.mArg).toString();
|
||||
return MWMechanics::EffectKey(effect.mEffectId, effect.getSkillOrAttribute()).toString();
|
||||
});
|
||||
activeSpellEffectT["affectedSkill"]
|
||||
= sol::readonly_property([magicEffectStore](const ESM::ActiveEffect& effect) -> sol::optional<std::string> {
|
||||
auto* rec = magicEffectStore->find(effect.mEffectId);
|
||||
if ((rec->mData.mFlags & ESM::MagicEffect::TargetSkill) && effect.mArg >= 0
|
||||
&& effect.mArg < ESM::Skill::Length)
|
||||
return ESM::Skill::indexToRefId(effect.mArg).serializeText();
|
||||
if (rec->mData.mFlags & ESM::MagicEffect::TargetSkill)
|
||||
return effect.getSkillOrAttribute().serializeText();
|
||||
else
|
||||
return sol::nullopt;
|
||||
});
|
||||
activeSpellEffectT["affectedAttribute"]
|
||||
= sol::readonly_property([magicEffectStore](const ESM::ActiveEffect& effect) -> sol::optional<std::string> {
|
||||
auto* rec = magicEffectStore->find(effect.mEffectId);
|
||||
if ((rec->mData.mFlags & ESM::MagicEffect::TargetAttribute) && effect.mArg >= 0
|
||||
&& effect.mArg < ESM::Attribute::Length)
|
||||
return Misc::StringUtils::lowerCase(ESM::Attribute::sAttributeNames[effect.mArg]);
|
||||
if (rec->mData.mFlags & ESM::MagicEffect::TargetAttribute)
|
||||
return effect.getSkillOrAttribute().serializeText();
|
||||
else
|
||||
return sol::nullopt;
|
||||
});
|
||||
|
@ -542,20 +540,15 @@ namespace MWLua
|
|||
= sol::readonly_property([magicEffectStore](const ActiveEffect& effect) -> sol::optional<std::string> {
|
||||
auto* rec = magicEffectStore->find(effect.key.mId);
|
||||
if (rec->mData.mFlags & ESM::MagicEffect::TargetSkill)
|
||||
{
|
||||
ESM::RefId id = ESM::Skill::indexToRefId(effect.key.mArg);
|
||||
return id.serializeText();
|
||||
}
|
||||
return effect.key.mArg.serializeText();
|
||||
return sol::nullopt;
|
||||
});
|
||||
activeEffectT["affectedAttribute"]
|
||||
= sol::readonly_property([magicEffectStore](const ActiveEffect& effect) -> sol::optional<std::string> {
|
||||
auto* rec = magicEffectStore->find(effect.key.mId);
|
||||
if ((rec->mData.mFlags & ESM::MagicEffect::TargetAttribute) && effect.key.mArg >= 0
|
||||
&& effect.key.mArg < ESM::Attribute::Length)
|
||||
return Misc::StringUtils::lowerCase(ESM::Attribute::sAttributeNames[effect.key.mArg]);
|
||||
else
|
||||
return sol::nullopt;
|
||||
if (rec->mData.mFlags & ESM::MagicEffect::TargetAttribute)
|
||||
return effect.key.mArg.serializeText();
|
||||
return sol::nullopt;
|
||||
});
|
||||
|
||||
activeEffectT["magnitude"]
|
||||
|
@ -777,12 +770,15 @@ namespace MWLua
|
|||
{
|
||||
// MWLua exposes attributes and skills as strings, so we have to convert them back to IDs here
|
||||
if (rec->mData.mFlags & ESM::MagicEffect::TargetAttribute)
|
||||
key = MWMechanics::EffectKey(id, ESM::Attribute::stringToAttributeId(argStr.value()));
|
||||
{
|
||||
ESM::RefId attribute = ESM::RefId::deserializeText(argStr.value());
|
||||
key = MWMechanics::EffectKey(id, attribute);
|
||||
}
|
||||
|
||||
if (rec->mData.mFlags & ESM::MagicEffect::TargetSkill)
|
||||
{
|
||||
ESM::RefId skill = ESM::RefId::deserializeText(argStr.value());
|
||||
key = MWMechanics::EffectKey(id, ESM::Skill::refIdToIndex(skill));
|
||||
key = MWMechanics::EffectKey(id, skill);
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
@ -171,11 +171,11 @@ namespace MWLua
|
|||
class AttributeStat
|
||||
{
|
||||
ObjectVariant mObject;
|
||||
int mIndex;
|
||||
ESM::RefId mId;
|
||||
|
||||
AttributeStat(ObjectVariant object, int index)
|
||||
AttributeStat(ObjectVariant object, ESM::RefId id)
|
||||
: mObject(std::move(object))
|
||||
, mIndex(index)
|
||||
, mId(id)
|
||||
{
|
||||
}
|
||||
|
||||
|
@ -183,10 +183,9 @@ namespace MWLua
|
|||
template <class G>
|
||||
sol::object get(const Context& context, std::string_view prop, G getter) const
|
||||
{
|
||||
auto id = static_cast<ESM::Attribute::AttributeID>(mIndex);
|
||||
return getValue(
|
||||
context, mObject, &AttributeStat::setValue, mIndex, prop, [id, getter](const MWWorld::Ptr& ptr) {
|
||||
return (ptr.getClass().getCreatureStats(ptr).getAttribute(id).*getter)();
|
||||
context, mObject, &AttributeStat::setValue, mId, prop, [this, getter](const MWWorld::Ptr& ptr) {
|
||||
return (ptr.getClass().getCreatureStats(ptr).getAttribute(mId).*getter)();
|
||||
});
|
||||
}
|
||||
|
||||
|
@ -202,20 +201,20 @@ namespace MWLua
|
|||
{
|
||||
if (!object.ptr().getClass().isActor())
|
||||
return {};
|
||||
int index = std::get<int>(i);
|
||||
return AttributeStat{ std::move(object), index };
|
||||
ESM::RefId id = std::get<ESM::RefId>(i);
|
||||
return AttributeStat{ std::move(object), id };
|
||||
}
|
||||
|
||||
void cache(const Context& context, std::string_view prop, const sol::object& value) const
|
||||
{
|
||||
SelfObject* obj = mObject.asSelfObject();
|
||||
addStatUpdateAction(context.mLuaManager, *obj);
|
||||
obj->mStatsCache[SelfObject::CachedStat{ &AttributeStat::setValue, mIndex, prop }] = value;
|
||||
obj->mStatsCache[SelfObject::CachedStat{ &AttributeStat::setValue, mId, prop }] = value;
|
||||
}
|
||||
|
||||
static void setValue(Index i, std::string_view prop, const MWWorld::Ptr& ptr, const sol::object& value)
|
||||
{
|
||||
auto id = static_cast<ESM::Attribute::AttributeID>(std::get<int>(i));
|
||||
ESM::RefId id = std::get<ESM::RefId>(i);
|
||||
auto& stats = ptr.getClass().getCreatureStats(ptr);
|
||||
auto stat = stats.getAttribute(id);
|
||||
float floatValue = LuaUtil::cast<float>(value);
|
||||
|
@ -370,9 +369,8 @@ namespace MWLua
|
|||
addProp(context, attributeStatT, "modifier", &MWMechanics::AttributeValue::getModifier);
|
||||
sol::table attributes(context.mLua->sol(), sol::create);
|
||||
stats["attributes"] = LuaUtil::makeReadOnly(attributes);
|
||||
for (int id = ESM::Attribute::Strength; id < ESM::Attribute::Length; ++id)
|
||||
attributes[Misc::StringUtils::lowerCase(ESM::Attribute::sAttributeNames[id])]
|
||||
= addIndexedAccessor<AttributeStat>(id);
|
||||
for (const ESM::Attribute& attribute : MWBase::Environment::get().getESMStore()->get<ESM::Attribute>())
|
||||
attributes[ESM::RefId(attribute.mId).serializeText()] = addIndexedAccessor<AttributeStat>(attribute.mId);
|
||||
}
|
||||
|
||||
void addNpcStatsBindings(sol::table& npc, const Context& context)
|
||||
|
|
|
@ -548,14 +548,13 @@ namespace MWMechanics
|
|||
purge([=](const ActiveSpellParams& params) { return params.mId == id; }, ptr);
|
||||
}
|
||||
|
||||
void ActiveSpells::purgeEffect(const MWWorld::Ptr& ptr, int effectId, int effectArg)
|
||||
void ActiveSpells::purgeEffect(const MWWorld::Ptr& ptr, int effectId, ESM::RefId effectArg)
|
||||
{
|
||||
purge(
|
||||
[=](const ActiveSpellParams&, const ESM::ActiveEffect& effect) {
|
||||
if (effectArg < 0)
|
||||
if (effectArg.empty())
|
||||
return effect.mEffectId == effectId;
|
||||
else
|
||||
return effect.mEffectId == effectId && effect.mArg == effectArg;
|
||||
return effect.mEffectId == effectId && effect.getSkillOrAttribute() == effectArg;
|
||||
},
|
||||
ptr);
|
||||
}
|
||||
|
|
|
@ -134,7 +134,7 @@ namespace MWMechanics
|
|||
void removeEffects(const MWWorld::Ptr& ptr, const ESM::RefId& id);
|
||||
|
||||
/// Remove all active effects with this effect id
|
||||
void purgeEffect(const MWWorld::Ptr& ptr, int effectId, int effectArg = -1);
|
||||
void purgeEffect(const MWWorld::Ptr& ptr, int effectId, ESM::RefId effectArg = {});
|
||||
|
||||
void purge(EffectPredicate predicate, const MWWorld::Ptr& ptr);
|
||||
void purge(ParamsPredicate predicate, const MWWorld::Ptr& ptr);
|
||||
|
|
|
@ -45,9 +45,10 @@ std::set<MWMechanics::EffectKey> MWMechanics::Alchemy::listEffects() const
|
|||
for (int i = 0; i < 4; ++i)
|
||||
if (ingredient->mBase->mData.mEffectID[i] != -1)
|
||||
{
|
||||
EffectKey key(ingredient->mBase->mData.mEffectID[i],
|
||||
ingredient->mBase->mData.mSkills[i] != -1 ? ingredient->mBase->mData.mSkills[i]
|
||||
: ingredient->mBase->mData.mAttributes[i]);
|
||||
ESM::RefId arg = ESM::Skill::indexToRefId(ingredient->mBase->mData.mSkills[i]);
|
||||
if (arg.empty())
|
||||
arg = ESM::Attribute::indexToRefId(ingredient->mBase->mData.mAttributes[i]);
|
||||
EffectKey key(ingredient->mBase->mData.mEffectID[i], arg);
|
||||
|
||||
if (seenEffects.insert(key).second)
|
||||
++effects[key];
|
||||
|
@ -203,9 +204,9 @@ void MWMechanics::Alchemy::updateEffects()
|
|||
effect.mSkill = -1;
|
||||
|
||||
if (magicEffect->mData.mFlags & ESM::MagicEffect::TargetSkill)
|
||||
effect.mSkill = iter->mArg;
|
||||
effect.mSkill = ESM::Skill::refIdToIndex(iter->mArg);
|
||||
else if (magicEffect->mData.mFlags & ESM::MagicEffect::TargetAttribute)
|
||||
effect.mAttribute = iter->mArg;
|
||||
effect.mAttribute = ESM::Attribute::refIdToIndex(iter->mArg);
|
||||
|
||||
effect.mRange = 0;
|
||||
effect.mArea = 0;
|
||||
|
@ -576,7 +577,8 @@ std::vector<std::string> MWMechanics::Alchemy::effectsDescription(const MWWorld:
|
|||
|
||||
if (effectID != -1)
|
||||
{
|
||||
const ESM::Attribute* attribute = store->get<ESM::Attribute>().search(data.mAttributes[i]);
|
||||
const ESM::Attribute* attribute
|
||||
= store->get<ESM::Attribute>().search(ESM::Attribute::indexToRefId(data.mAttributes[i]));
|
||||
const ESM::Skill* skill = store->get<ESM::Skill>().search(ESM::Skill::indexToRefId(data.mSkills[i]));
|
||||
std::string effect = getMagicEffectString(*mgef.find(effectID), attribute, skill);
|
||||
|
||||
|
|
|
@ -27,7 +27,7 @@ namespace MWMechanics
|
|||
};
|
||||
|
||||
std::vector<ESM::RefId> autoCalcNpcSpells(const std::map<ESM::RefId, SkillValue>& actorSkills,
|
||||
const std::map<ESM::Attribute::AttributeID, AttributeValue>& actorAttributes, const ESM::Race* race)
|
||||
const std::map<ESM::RefId, AttributeValue>& actorAttributes, const ESM::Race* race)
|
||||
{
|
||||
const MWWorld::Store<ESM::GameSetting>& gmst
|
||||
= MWBase::Environment::get().getESMStore()->get<ESM::GameSetting>();
|
||||
|
@ -136,7 +136,7 @@ namespace MWMechanics
|
|||
}
|
||||
|
||||
std::vector<ESM::RefId> autoCalcPlayerSpells(const std::map<ESM::RefId, SkillValue>& actorSkills,
|
||||
const std::map<ESM::Attribute::AttributeID, AttributeValue>& actorAttributes, const ESM::Race* race)
|
||||
const std::map<ESM::RefId, AttributeValue>& actorAttributes, const ESM::Race* race)
|
||||
{
|
||||
const MWWorld::ESMStore& esmStore = *MWBase::Environment::get().getESMStore();
|
||||
|
||||
|
@ -215,7 +215,7 @@ namespace MWMechanics
|
|||
}
|
||||
|
||||
bool attrSkillCheck(const ESM::Spell* spell, const std::map<ESM::RefId, SkillValue>& actorSkills,
|
||||
const std::map<ESM::Attribute::AttributeID, AttributeValue>& actorAttributes)
|
||||
const std::map<ESM::RefId, AttributeValue>& actorAttributes)
|
||||
{
|
||||
for (const auto& spellEffect : spell->mEffects.mList)
|
||||
{
|
||||
|
@ -237,7 +237,8 @@ namespace MWMechanics
|
|||
|
||||
if ((magicEffect->mData.mFlags & ESM::MagicEffect::TargetAttribute))
|
||||
{
|
||||
auto found = actorAttributes.find(ESM::Attribute::AttributeID(spellEffect.mAttribute));
|
||||
ESM::RefId attribute = ESM::Attribute::indexToRefId(spellEffect.mAttribute);
|
||||
auto found = actorAttributes.find(attribute);
|
||||
if (found == actorAttributes.end() || found->second.getBase() < iAutoSpellAttSkillMin)
|
||||
return false;
|
||||
}
|
||||
|
@ -299,7 +300,7 @@ namespace MWMechanics
|
|||
}
|
||||
|
||||
float calcAutoCastChance(const ESM::Spell* spell, const std::map<ESM::RefId, SkillValue>& actorSkills,
|
||||
const std::map<ESM::Attribute::AttributeID, AttributeValue>& actorAttributes, ESM::RefId effectiveSchool)
|
||||
const std::map<ESM::RefId, AttributeValue>& actorAttributes, ESM::RefId effectiveSchool)
|
||||
{
|
||||
if (spell->mData.mType != ESM::Spell::ST_Spell)
|
||||
return 100.f;
|
||||
|
|
|
@ -20,21 +20,21 @@ namespace MWMechanics
|
|||
/// @note We might want to move this code to a component later, so the editor can use it for preview purposes
|
||||
|
||||
std::vector<ESM::RefId> autoCalcNpcSpells(const std::map<ESM::RefId, SkillValue>& actorSkills,
|
||||
const std::map<ESM::Attribute::AttributeID, AttributeValue>& actorAttributes, const ESM::Race* race);
|
||||
const std::map<ESM::RefId, AttributeValue>& actorAttributes, const ESM::Race* race);
|
||||
|
||||
std::vector<ESM::RefId> autoCalcPlayerSpells(const std::map<ESM::RefId, SkillValue>& actorSkills,
|
||||
const std::map<ESM::Attribute::AttributeID, AttributeValue>& actorAttributes, const ESM::Race* race);
|
||||
const std::map<ESM::RefId, AttributeValue>& actorAttributes, const ESM::Race* race);
|
||||
|
||||
// Helpers
|
||||
|
||||
bool attrSkillCheck(const ESM::Spell* spell, const std::map<ESM::RefId, SkillValue>& actorSkills,
|
||||
const std::map<ESM::Attribute::AttributeID, AttributeValue>& actorAttributes);
|
||||
const std::map<ESM::RefId, AttributeValue>& actorAttributes);
|
||||
|
||||
void calcWeakestSchool(const ESM::Spell* spell, const std::map<ESM::RefId, SkillValue>& actorSkills,
|
||||
ESM::RefId& effectiveSchool, float& skillTerm);
|
||||
|
||||
float calcAutoCastChance(const ESM::Spell* spell, const std::map<ESM::RefId, SkillValue>& actorSkills,
|
||||
const std::map<ESM::Attribute::AttributeID, AttributeValue>& actorAttributes, ESM::RefId effectiveSchool);
|
||||
const std::map<ESM::RefId, AttributeValue>& actorAttributes, ESM::RefId effectiveSchool);
|
||||
|
||||
}
|
||||
|
||||
|
|
|
@ -78,7 +78,7 @@ namespace MWMechanics
|
|||
return fFatigueBase - fFatigueMult * (1 - normalised);
|
||||
}
|
||||
|
||||
const AttributeValue& CreatureStats::getAttribute(ESM::Attribute::AttributeID id) const
|
||||
const AttributeValue& CreatureStats::getAttribute(ESM::RefId id) const
|
||||
{
|
||||
return mAttributes.at(id);
|
||||
}
|
||||
|
@ -147,14 +147,14 @@ namespace MWMechanics
|
|||
return mMagicEffects;
|
||||
}
|
||||
|
||||
void CreatureStats::setAttribute(ESM::Attribute::AttributeID id, float base)
|
||||
void CreatureStats::setAttribute(ESM::RefId id, float base)
|
||||
{
|
||||
AttributeValue current = getAttribute(id);
|
||||
current.setBase(base);
|
||||
setAttribute(id, current);
|
||||
}
|
||||
|
||||
void CreatureStats::setAttribute(ESM::Attribute::AttributeID id, const AttributeValue& value)
|
||||
void CreatureStats::setAttribute(ESM::RefId id, const AttributeValue& value)
|
||||
{
|
||||
const AttributeValue& currentValue = mAttributes.at(id);
|
||||
|
||||
|
@ -531,7 +531,7 @@ namespace MWMechanics
|
|||
void CreatureStats::writeState(ESM::CreatureStats& state) const
|
||||
{
|
||||
for (size_t i = 0; i < state.mAttributes.size(); ++i)
|
||||
getAttribute(static_cast<ESM::Attribute::AttributeID>(i)).writeState(state.mAttributes[i]);
|
||||
getAttribute(ESM::Attribute::indexToRefId(i)).writeState(state.mAttributes[i]);
|
||||
|
||||
for (size_t i = 0; i < state.mDynamic.size(); ++i)
|
||||
mDynamic[i].writeState(state.mDynamic[i]);
|
||||
|
@ -588,7 +588,7 @@ namespace MWMechanics
|
|||
if (!state.mMissingACDT)
|
||||
{
|
||||
for (size_t i = 0; i < state.mAttributes.size(); ++i)
|
||||
mAttributes[static_cast<ESM::Attribute::AttributeID>(i)].readState(state.mAttributes[i]);
|
||||
mAttributes[ESM::Attribute::indexToRefId(i)].readState(state.mAttributes[i]);
|
||||
|
||||
for (size_t i = 0; i < state.mDynamic.size(); ++i)
|
||||
mDynamic[i].readState(state.mDynamic[i]);
|
||||
|
|
|
@ -40,7 +40,7 @@ namespace MWMechanics
|
|||
{
|
||||
static int sActorId;
|
||||
DrawState mDrawState;
|
||||
std::map<ESM::Attribute::AttributeID, AttributeValue> mAttributes;
|
||||
std::map<ESM::RefId, AttributeValue> mAttributes;
|
||||
DynamicStat<float> mDynamic[3]; // health, magicka, fatigue
|
||||
Spells mSpells;
|
||||
ActiveSpells mActiveSpells;
|
||||
|
@ -113,7 +113,7 @@ namespace MWMechanics
|
|||
/// @return total fall height
|
||||
float land(bool isPlayer = false);
|
||||
|
||||
const AttributeValue& getAttribute(ESM::Attribute::AttributeID id) const;
|
||||
const AttributeValue& getAttribute(ESM::RefId id) const;
|
||||
|
||||
const DynamicStat<float>& getHealth() const;
|
||||
|
||||
|
@ -139,9 +139,9 @@ namespace MWMechanics
|
|||
|
||||
MagicEffects& getMagicEffects();
|
||||
|
||||
void setAttribute(ESM::Attribute::AttributeID id, const AttributeValue& value);
|
||||
void setAttribute(ESM::RefId id, const AttributeValue& value);
|
||||
// Shortcut to set only the base
|
||||
void setAttribute(ESM::Attribute::AttributeID id, float base);
|
||||
void setAttribute(ESM::RefId id, float base);
|
||||
|
||||
void setHealth(const DynamicStat<float>& value);
|
||||
|
||||
|
@ -294,7 +294,7 @@ namespace MWMechanics
|
|||
bool wasTeleported() const { return mTeleported; }
|
||||
void setTeleported(bool v) { mTeleported = v; }
|
||||
|
||||
const std::map<ESM::Attribute::AttributeID, AttributeValue> getAttributes() const { return mAttributes; }
|
||||
const std::map<ESM::RefId, AttributeValue> getAttributes() const { return mAttributes; }
|
||||
};
|
||||
}
|
||||
|
||||
|
|
|
@ -27,24 +27,21 @@ namespace MWMechanics
|
|||
{
|
||||
EffectKey::EffectKey()
|
||||
: mId(0)
|
||||
, mArg(-1)
|
||||
{
|
||||
}
|
||||
|
||||
EffectKey::EffectKey(const ESM::ENAMstruct& effect)
|
||||
{
|
||||
mId = effect.mEffectID;
|
||||
mArg = -1;
|
||||
mArg = ESM::Skill::indexToRefId(effect.mSkill);
|
||||
|
||||
if (effect.mSkill != -1)
|
||||
mArg = effect.mSkill;
|
||||
|
||||
if (effect.mAttribute != -1)
|
||||
ESM::RefId attribute = ESM::Attribute::indexToRefId(effect.mAttribute);
|
||||
if (!attribute.empty())
|
||||
{
|
||||
if (mArg != -1)
|
||||
if (!mArg.empty())
|
||||
throw std::runtime_error("magic effect can't have both a skill and an attribute argument");
|
||||
|
||||
mArg = effect.mAttribute;
|
||||
mArg = attribute;
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -52,8 +49,8 @@ namespace MWMechanics
|
|||
{
|
||||
const auto& store = MWBase::Environment::get().getESMStore();
|
||||
const ESM::MagicEffect* magicEffect = store->get<ESM::MagicEffect>().search(mId);
|
||||
return getMagicEffectString(*magicEffect, store->get<ESM::Attribute>().search(mArg),
|
||||
store->get<ESM::Skill>().search(ESM::Skill::indexToRefId(mArg)));
|
||||
return getMagicEffectString(
|
||||
*magicEffect, store->get<ESM::Attribute>().search(mArg), store->get<ESM::Skill>().search(mArg));
|
||||
}
|
||||
|
||||
bool operator<(const EffectKey& left, const EffectKey& right)
|
||||
|
|
|
@ -5,6 +5,8 @@
|
|||
#include <optional>
|
||||
#include <string>
|
||||
|
||||
#include <components/esm/refid.hpp>
|
||||
|
||||
namespace ESM
|
||||
{
|
||||
struct Attribute;
|
||||
|
@ -20,11 +22,11 @@ namespace MWMechanics
|
|||
struct EffectKey
|
||||
{
|
||||
int mId;
|
||||
int mArg; // skill or ability
|
||||
ESM::RefId mArg; // skill or ability
|
||||
|
||||
EffectKey();
|
||||
|
||||
EffectKey(int id, int arg = -1)
|
||||
EffectKey(int id, ESM::RefId arg = {})
|
||||
: mId(id)
|
||||
, mArg(arg)
|
||||
{
|
||||
|
|
|
@ -150,7 +150,8 @@ namespace MWMechanics
|
|||
|
||||
for (const ESM::Attribute& attribute : esmStore.get<ESM::Attribute>())
|
||||
{
|
||||
const ESM::Race::MaleFemale& value = race->mData.mAttributeValues[attribute.mId];
|
||||
const ESM::Race::MaleFemale& value
|
||||
= race->mData.mAttributeValues[ESM::Attribute::refIdToIndex(attribute.mId)];
|
||||
|
||||
creatureStats.setAttribute(attribute.mId, male ? value.mMale : value.mFemale);
|
||||
}
|
||||
|
@ -193,11 +194,9 @@ namespace MWMechanics
|
|||
|
||||
for (int attribute : class_->mData.mAttribute)
|
||||
{
|
||||
if (attribute >= 0 && attribute < ESM::Attribute::Length)
|
||||
{
|
||||
auto id = static_cast<ESM::Attribute::AttributeID>(attribute);
|
||||
ESM::RefId id = ESM::Attribute::indexToRefId(attribute);
|
||||
if (!id.empty())
|
||||
creatureStats.setAttribute(id, creatureStats.getAttribute(id).getBase() + 10);
|
||||
}
|
||||
}
|
||||
|
||||
for (int i = 0; i < 2; ++i)
|
||||
|
|
|
@ -246,7 +246,7 @@ void MWMechanics::NpcStats::increaseSkill(ESM::RefId id, const ESM::Class& class
|
|||
}
|
||||
}
|
||||
|
||||
mSkillIncreases[ESM::Attribute::AttributeID(skill->mData.mAttribute)] += increase;
|
||||
mSkillIncreases[ESM::Attribute::indexToRefId(skill->mData.mAttribute)] += increase;
|
||||
|
||||
mSpecIncreases[skill->mData.mSpecialization] += gmst.find("iLevelupSpecialization")->mValue.getInteger();
|
||||
|
||||
|
@ -488,7 +488,7 @@ void MWMechanics::NpcStats::writeState(ESM::NpcStats& state) const
|
|||
|
||||
state.mSkillIncrease.fill(0);
|
||||
for (const auto& [key, value] : mSkillIncreases)
|
||||
state.mSkillIncrease[key] = value;
|
||||
state.mSkillIncrease[ESM::Attribute::refIdToIndex(key)] = value;
|
||||
|
||||
for (size_t i = 0; i < state.mSpecIncreases.size(); ++i)
|
||||
state.mSpecIncreases[i] = mSpecIncreases[i];
|
||||
|
@ -538,7 +538,7 @@ void MWMechanics::NpcStats::readState(const ESM::NpcStats& state)
|
|||
mLevelProgress = state.mLevelProgress;
|
||||
|
||||
for (size_t i = 0; i < state.mSkillIncrease.size(); ++i)
|
||||
mSkillIncreases[static_cast<ESM::Attribute::AttributeID>(i)] = state.mSkillIncrease[i];
|
||||
mSkillIncreases[ESM::Attribute::indexToRefId(i)] = state.mSkillIncrease[i];
|
||||
|
||||
for (size_t i = 0; i < state.mSpecIncreases.size(); ++i)
|
||||
mSpecIncreases[i] = state.mSpecIncreases[i];
|
||||
|
|
|
@ -36,7 +36,7 @@ namespace MWMechanics
|
|||
std::set<ESM::RefId> mExpelled;
|
||||
std::map<ESM::RefId, int> mFactionReputation;
|
||||
int mLevelProgress; // 0-10
|
||||
std::map<ESM::Attribute::AttributeID, int>
|
||||
std::map<ESM::RefId, int>
|
||||
mSkillIncreases; // number of skill increases for each attribute (resets after leveling up)
|
||||
std::vector<int> mSpecIncreases; // number of skill increases for each specialization (accumulates throughout
|
||||
// the entire game)
|
||||
|
|
|
@ -80,7 +80,7 @@ namespace
|
|||
void damageAttribute(const MWWorld::Ptr& target, const ESM::ActiveEffect& effect, float magnitude)
|
||||
{
|
||||
auto& creatureStats = target.getClass().getCreatureStats(target);
|
||||
auto attribute = static_cast<ESM::Attribute::AttributeID>(effect.mArg);
|
||||
auto attribute = effect.getSkillOrAttribute();
|
||||
auto attr = creatureStats.getAttribute(attribute);
|
||||
if (effect.mEffectId == ESM::MagicEffect::DamageAttribute)
|
||||
magnitude = std::min(attr.getModified(), magnitude);
|
||||
|
@ -91,7 +91,7 @@ namespace
|
|||
void restoreAttribute(const MWWorld::Ptr& target, const ESM::ActiveEffect& effect, float magnitude)
|
||||
{
|
||||
auto& creatureStats = target.getClass().getCreatureStats(target);
|
||||
auto attribute = static_cast<ESM::Attribute::AttributeID>(effect.mArg);
|
||||
auto attribute = effect.getSkillOrAttribute();
|
||||
auto attr = creatureStats.getAttribute(attribute);
|
||||
attr.restore(magnitude);
|
||||
creatureStats.setAttribute(attribute, attr);
|
||||
|
@ -100,7 +100,7 @@ namespace
|
|||
void fortifyAttribute(const MWWorld::Ptr& target, const ESM::ActiveEffect& effect, float magnitude)
|
||||
{
|
||||
auto& creatureStats = target.getClass().getCreatureStats(target);
|
||||
auto attribute = static_cast<ESM::Attribute::AttributeID>(effect.mArg);
|
||||
auto attribute = effect.getSkillOrAttribute();
|
||||
auto attr = creatureStats.getAttribute(attribute);
|
||||
attr.setModifier(attr.getModifier() + magnitude);
|
||||
creatureStats.setAttribute(attribute, attr);
|
||||
|
@ -109,7 +109,7 @@ namespace
|
|||
void damageSkill(const MWWorld::Ptr& target, const ESM::ActiveEffect& effect, float magnitude)
|
||||
{
|
||||
auto& npcStats = target.getClass().getNpcStats(target);
|
||||
auto& skill = npcStats.getSkill(ESM::Skill::indexToRefId(effect.mArg));
|
||||
auto& skill = npcStats.getSkill(effect.getSkillOrAttribute());
|
||||
if (effect.mEffectId == ESM::MagicEffect::DamageSkill)
|
||||
magnitude = std::min(skill.getModified(), magnitude);
|
||||
skill.damage(magnitude);
|
||||
|
@ -118,14 +118,14 @@ namespace
|
|||
void restoreSkill(const MWWorld::Ptr& target, const ESM::ActiveEffect& effect, float magnitude)
|
||||
{
|
||||
auto& npcStats = target.getClass().getNpcStats(target);
|
||||
auto& skill = npcStats.getSkill(ESM::Skill::indexToRefId(effect.mArg));
|
||||
auto& skill = npcStats.getSkill(effect.getSkillOrAttribute());
|
||||
skill.restore(magnitude);
|
||||
}
|
||||
|
||||
void fortifySkill(const MWWorld::Ptr& target, const ESM::ActiveEffect& effect, float magnitude)
|
||||
{
|
||||
auto& npcStats = target.getClass().getNpcStats(target);
|
||||
auto& skill = npcStats.getSkill(ESM::Skill::indexToRefId(effect.mArg));
|
||||
auto& skill = npcStats.getSkill(effect.getSkillOrAttribute());
|
||||
skill.setModifier(skill.getModifier() + magnitude);
|
||||
}
|
||||
|
||||
|
@ -670,7 +670,7 @@ namespace MWMechanics
|
|||
if (spellParams.getType() == ESM::ActiveSpells::Type_Ability)
|
||||
{
|
||||
auto& npcStats = target.getClass().getNpcStats(target);
|
||||
SkillValue& skill = npcStats.getSkill(ESM::Skill::indexToRefId(effect.mArg));
|
||||
SkillValue& skill = npcStats.getSkill(effect.getSkillOrAttribute());
|
||||
// Damage Skill abilities reduce base skill :todd:
|
||||
skill.setBase(std::max(skill.getBase() - effect.mMagnitude, 0.f));
|
||||
}
|
||||
|
@ -741,7 +741,7 @@ namespace MWMechanics
|
|||
if (spellParams.getType() == ESM::ActiveSpells::Type_Ability)
|
||||
{
|
||||
auto& creatureStats = target.getClass().getCreatureStats(target);
|
||||
auto attribute = static_cast<ESM::Attribute::AttributeID>(effect.mArg);
|
||||
auto attribute = effect.getSkillOrAttribute();
|
||||
AttributeValue attr = creatureStats.getAttribute(attribute);
|
||||
attr.setBase(attr.getBase() + effect.mMagnitude);
|
||||
creatureStats.setAttribute(attribute, attr);
|
||||
|
@ -762,7 +762,7 @@ namespace MWMechanics
|
|||
{
|
||||
// Abilities affect base stats, but not for drain
|
||||
auto& npcStats = target.getClass().getNpcStats(target);
|
||||
auto& skill = npcStats.getSkill(ESM::Skill::indexToRefId(effect.mArg));
|
||||
auto& skill = npcStats.getSkill(effect.getSkillOrAttribute());
|
||||
skill.setBase(skill.getBase() + effect.mMagnitude);
|
||||
}
|
||||
else
|
||||
|
@ -1033,7 +1033,8 @@ namespace MWMechanics
|
|||
applyMagicEffect(target, caster, spellParams, effect, invalid, receivedMagicDamage, affectedHealth,
|
||||
recalculateMagicka);
|
||||
effect.mMagnitude = magnitude;
|
||||
magnitudes.add(EffectKey(effect.mEffectId, effect.mArg), EffectParam(effect.mMagnitude - oldMagnitude));
|
||||
magnitudes.add(EffectKey(effect.mEffectId, effect.getSkillOrAttribute()),
|
||||
EffectParam(effect.mMagnitude - oldMagnitude));
|
||||
}
|
||||
effect.mTimeLeft -= dt;
|
||||
if (invalid)
|
||||
|
@ -1145,13 +1146,14 @@ namespace MWMechanics
|
|||
case ESM::MagicEffect::SummonCreature04:
|
||||
case ESM::MagicEffect::SummonCreature05:
|
||||
{
|
||||
if (effect.mArg != -1)
|
||||
MWBase::Environment::get().getMechanicsManager()->cleanupSummonedCreature(target, effect.mArg);
|
||||
int actorId = effect.getActorId();
|
||||
if (actorId != -1)
|
||||
MWBase::Environment::get().getMechanicsManager()->cleanupSummonedCreature(target, actorId);
|
||||
auto& summons = target.getClass().getCreatureStats(target).getSummonedCreatureMap();
|
||||
auto [begin, end] = summons.equal_range(effect.mEffectId);
|
||||
for (auto it = begin; it != end; ++it)
|
||||
{
|
||||
if (it->second == effect.mArg)
|
||||
if (it->second == actorId)
|
||||
{
|
||||
summons.erase(it);
|
||||
break;
|
||||
|
@ -1205,7 +1207,7 @@ namespace MWMechanics
|
|||
if (spellParams.getType() == ESM::ActiveSpells::Type_Ability)
|
||||
{
|
||||
auto& creatureStats = target.getClass().getCreatureStats(target);
|
||||
auto attribute = static_cast<ESM::Attribute::AttributeID>(effect.mArg);
|
||||
auto attribute = effect.getSkillOrAttribute();
|
||||
AttributeValue attr = creatureStats.getAttribute(attribute);
|
||||
attr.setBase(attr.getBase() - effect.mMagnitude);
|
||||
creatureStats.setAttribute(attribute, attr);
|
||||
|
@ -1221,7 +1223,7 @@ namespace MWMechanics
|
|||
if (spellParams.getType() == ESM::ActiveSpells::Type_Ability)
|
||||
{
|
||||
auto& npcStats = target.getClass().getNpcStats(target);
|
||||
auto& skill = npcStats.getSkill(ESM::Skill::indexToRefId(effect.mArg));
|
||||
auto& skill = npcStats.getSkill(effect.getSkillOrAttribute());
|
||||
skill.setBase(skill.getBase() - effect.mMagnitude);
|
||||
}
|
||||
else
|
||||
|
@ -1277,7 +1279,7 @@ namespace MWMechanics
|
|||
if (!(effect.mFlags & ESM::ActiveEffect::Flag_Applied))
|
||||
return;
|
||||
auto& magnitudes = target.getClass().getCreatureStats(target).getMagicEffects();
|
||||
magnitudes.add(EffectKey(effect.mEffectId, effect.mArg), EffectParam(-effect.mMagnitude));
|
||||
magnitudes.add(EffectKey(effect.mEffectId, effect.getSkillOrAttribute()), EffectParam(-effect.mMagnitude));
|
||||
removeMagicEffect(target, spellParams, effect);
|
||||
if (magnitudes.getOrDefault(effect.mEffectId).getMagnitude() <= 0.f)
|
||||
{
|
||||
|
|
|
@ -573,7 +573,7 @@ namespace MWMechanics
|
|||
if (!enemy.isEmpty()
|
||||
&& enemy.getClass()
|
||||
.getCreatureStats(enemy)
|
||||
.getAttribute(ESM::Attribute::AttributeID(effect.mAttribute))
|
||||
.getAttribute(ESM::Attribute::indexToRefId(effect.mAttribute))
|
||||
.getModified()
|
||||
<= 0)
|
||||
return 0.f;
|
||||
|
|
|
@ -252,7 +252,7 @@ namespace MWMechanics
|
|||
// Applied corprus effects are already in loaded stats modifiers
|
||||
if (info.mId == ESM::MagicEffect::FortifyAttribute)
|
||||
{
|
||||
auto id = static_cast<ESM::Attribute::AttributeID>(info.mArg);
|
||||
auto id = ESM::Attribute::indexToRefId(info.mArg);
|
||||
AttributeValue attr = creatureStats->getAttribute(id);
|
||||
attr.setModifier(attr.getModifier() - info.mMagnitude);
|
||||
attr.damage(-info.mMagnitude);
|
||||
|
@ -260,7 +260,7 @@ namespace MWMechanics
|
|||
}
|
||||
else if (info.mId == ESM::MagicEffect::DrainAttribute)
|
||||
{
|
||||
auto id = static_cast<ESM::Attribute::AttributeID>(info.mArg);
|
||||
auto id = ESM::Attribute::indexToRefId(info.mArg);
|
||||
AttributeValue attr = creatureStats->getAttribute(id);
|
||||
attr.setModifier(attr.getModifier() + info.mMagnitude);
|
||||
attr.damage(info.mMagnitude);
|
||||
|
|
|
@ -166,7 +166,7 @@ namespace MWMechanics
|
|||
auto& creatureStats = summoner.getClass().getCreatureStats(summoner);
|
||||
creatureStats.getActiveSpells().purge(
|
||||
[summon](const auto& spell, const auto& effect) {
|
||||
return effect.mEffectId == summon.first && effect.mArg == summon.second;
|
||||
return effect.mEffectId == summon.first && effect.getActorId() == summon.second;
|
||||
},
|
||||
summoner);
|
||||
|
||||
|
|
|
@ -109,10 +109,10 @@ namespace MWScript
|
|||
template <class R>
|
||||
class OpGetAttribute : public Interpreter::Opcode0
|
||||
{
|
||||
ESM::Attribute::AttributeID mIndex;
|
||||
ESM::RefId mIndex;
|
||||
|
||||
public:
|
||||
OpGetAttribute(ESM::Attribute::AttributeID index)
|
||||
OpGetAttribute(ESM::RefId index)
|
||||
: mIndex(index)
|
||||
{
|
||||
}
|
||||
|
@ -130,10 +130,10 @@ namespace MWScript
|
|||
template <class R>
|
||||
class OpSetAttribute : public Interpreter::Opcode0
|
||||
{
|
||||
ESM::Attribute::AttributeID mIndex;
|
||||
ESM::RefId mIndex;
|
||||
|
||||
public:
|
||||
OpSetAttribute(ESM::Attribute::AttributeID index)
|
||||
OpSetAttribute(ESM::RefId index)
|
||||
: mIndex(index)
|
||||
{
|
||||
}
|
||||
|
@ -154,10 +154,10 @@ namespace MWScript
|
|||
template <class R>
|
||||
class OpModAttribute : public Interpreter::Opcode0
|
||||
{
|
||||
ESM::Attribute::AttributeID mIndex;
|
||||
ESM::RefId mIndex;
|
||||
|
||||
public:
|
||||
OpModAttribute(ESM::Attribute::AttributeID index)
|
||||
OpModAttribute(ESM::RefId index)
|
||||
: mIndex(index)
|
||||
{
|
||||
}
|
||||
|
@ -1322,7 +1322,7 @@ namespace MWScript
|
|||
{
|
||||
for (int i = 0; i < Compiler::Stats::numberOfAttributes; ++i)
|
||||
{
|
||||
auto id = static_cast<ESM::Attribute::AttributeID>(i);
|
||||
ESM::RefId id = ESM::Attribute::indexToRefId(i);
|
||||
interpreter.installSegment5<OpGetAttribute<ImplicitRef>>(Compiler::Stats::opcodeGetAttribute + i, id);
|
||||
interpreter.installSegment5<OpGetAttribute<ExplicitRef>>(
|
||||
Compiler::Stats::opcodeGetAttributeExplicit + i, id);
|
||||
|
|
|
@ -184,7 +184,7 @@ namespace MWWorld
|
|||
}
|
||||
for (const auto& [key, actorId] : creatureStats.mSummonedCreatureMap)
|
||||
{
|
||||
if (actorId == -1)
|
||||
if (actorId < 0)
|
||||
continue;
|
||||
for (auto& params : creatureStats.mActiveSpells.mSpells)
|
||||
{
|
||||
|
@ -195,7 +195,7 @@ namespace MWWorld
|
|||
{
|
||||
if (effect.mEffectId == key.mEffectId && effect.mEffectIndex == key.mEffectIndex)
|
||||
{
|
||||
effect.mArg = actorId;
|
||||
effect.mArg = ESM::RefId::generated(static_cast<uint64_t>(actorId));
|
||||
effect.mFlags |= ESM::ActiveEffect::Flag_Applied | ESM::ActiveEffect::Flag_Remove;
|
||||
found = true;
|
||||
break;
|
||||
|
|
|
@ -63,7 +63,7 @@ namespace MWWorld
|
|||
for (size_t i = 0; i < mSaveSkills.size(); ++i)
|
||||
mSaveSkills[i] = stats.getSkill(ESM::Skill::indexToRefId(i)).getModified();
|
||||
for (size_t i = 0; i < mSaveAttributes.size(); ++i)
|
||||
mSaveAttributes[i] = stats.getAttribute(static_cast<ESM::Attribute::AttributeID>(i)).getModified();
|
||||
mSaveAttributes[i] = stats.getAttribute(ESM::Attribute::indexToRefId(i)).getModified();
|
||||
}
|
||||
|
||||
void Player::restoreStats()
|
||||
|
@ -82,7 +82,7 @@ namespace MWWorld
|
|||
}
|
||||
for (size_t i = 0; i < mSaveAttributes.size(); ++i)
|
||||
{
|
||||
auto id = static_cast<ESM::Attribute::AttributeID>(i);
|
||||
auto id = ESM::Attribute::indexToRefId(i);
|
||||
auto attribute = npcStats.getAttribute(id);
|
||||
attribute.restore(attribute.getDamage());
|
||||
attribute.setModifier(mSaveAttributes[i] - attribute.getBase());
|
||||
|
|
|
@ -1041,87 +1041,50 @@ namespace MWWorld
|
|||
// Attribute
|
||||
//=========================================================================
|
||||
|
||||
Store<ESM::Attribute>::Store()
|
||||
{
|
||||
mStatic.reserve(ESM::Attribute::Length);
|
||||
}
|
||||
const ESM::Attribute* Store<ESM::Attribute>::search(size_t index) const
|
||||
{
|
||||
if (index >= mStatic.size())
|
||||
{
|
||||
return nullptr;
|
||||
}
|
||||
return &mStatic[index];
|
||||
}
|
||||
|
||||
const ESM::Attribute* Store<ESM::Attribute>::find(size_t index) const
|
||||
{
|
||||
const ESM::Attribute* ptr = search(index);
|
||||
if (ptr == nullptr)
|
||||
{
|
||||
const std::string msg = "Attribute with index " + std::to_string(index) + " not found";
|
||||
throw std::runtime_error(msg);
|
||||
}
|
||||
return ptr;
|
||||
}
|
||||
void Store<ESM::Attribute>::setUp(const MWWorld::Store<ESM::GameSetting>& settings)
|
||||
{
|
||||
// TODO remove after !3084 gets merged
|
||||
mStatic.clear();
|
||||
mStatic.push_back({ .mId = ESM::Attribute::Strength,
|
||||
insertStatic({ .mId = ESM::Attribute::Strength,
|
||||
.mName = std::string{ getGMSTString(settings, "sAttributeStrength") },
|
||||
.mDescription = std::string{ getGMSTString(settings, "sStrDesc") },
|
||||
.mIcon = "icons\\k\\attribute_strength.dds",
|
||||
.mWerewolfValue = getGMSTFloat(settings, "fWerewolfStrength") });
|
||||
mStatic.push_back({ .mId = ESM::Attribute::Intelligence,
|
||||
insertStatic({ .mId = ESM::Attribute::Intelligence,
|
||||
.mName = std::string{ getGMSTString(settings, "sAttributeIntelligence") },
|
||||
.mDescription = std::string{ getGMSTString(settings, "sIntDesc") },
|
||||
.mIcon = "icons\\k\\attribute_int.dds",
|
||||
// Oh, Bethesda. It's "Intelligence".
|
||||
.mWerewolfValue = getGMSTFloat(settings, "fWerewolfIntellegence") });
|
||||
mStatic.push_back({ .mId = ESM::Attribute::Willpower,
|
||||
insertStatic({ .mId = ESM::Attribute::Willpower,
|
||||
.mName = std::string{ getGMSTString(settings, "sAttributeWillpower") },
|
||||
.mDescription = std::string{ getGMSTString(settings, "sWilDesc") },
|
||||
.mIcon = "icons\\k\\attribute_wilpower.dds",
|
||||
.mWerewolfValue = getGMSTFloat(settings, "fWerewolfWillpower") });
|
||||
mStatic.push_back({ .mId = ESM::Attribute::Agility,
|
||||
insertStatic({ .mId = ESM::Attribute::Agility,
|
||||
.mName = std::string{ getGMSTString(settings, "sAttributeAgility") },
|
||||
.mDescription = std::string{ getGMSTString(settings, "sAgiDesc") },
|
||||
.mIcon = "icons\\k\\attribute_agility.dds",
|
||||
.mWerewolfValue = getGMSTFloat(settings, "fWerewolfAgility") });
|
||||
mStatic.push_back({ .mId = ESM::Attribute::Speed,
|
||||
insertStatic({ .mId = ESM::Attribute::Speed,
|
||||
.mName = std::string{ getGMSTString(settings, "sAttributeSpeed") },
|
||||
.mDescription = std::string{ getGMSTString(settings, "sSpdDesc") },
|
||||
.mIcon = "icons\\k\\attribute_speed.dds",
|
||||
.mWerewolfValue = getGMSTFloat(settings, "fWerewolfSpeed") });
|
||||
mStatic.push_back({ .mId = ESM::Attribute::Endurance,
|
||||
insertStatic({ .mId = ESM::Attribute::Endurance,
|
||||
.mName = std::string{ getGMSTString(settings, "sAttributeEndurance") },
|
||||
.mDescription = std::string{ getGMSTString(settings, "sEndDesc") },
|
||||
.mIcon = "icons\\k\\attribute_endurance.dds",
|
||||
.mWerewolfValue = getGMSTFloat(settings, "fWerewolfEndurance") });
|
||||
mStatic.push_back({ .mId = ESM::Attribute::Personality,
|
||||
insertStatic({ .mId = ESM::Attribute::Personality,
|
||||
.mName = std::string{ getGMSTString(settings, "sAttributePersonality") },
|
||||
.mDescription = std::string{ getGMSTString(settings, "sPerDesc") },
|
||||
.mIcon = "icons\\k\\attribute_personality.dds",
|
||||
.mWerewolfValue = getGMSTFloat(settings, "fWerewolfPersonality") });
|
||||
mStatic.push_back({ .mId = ESM::Attribute::Luck,
|
||||
insertStatic({ .mId = ESM::Attribute::Luck,
|
||||
.mName = std::string{ getGMSTString(settings, "sAttributeLuck") },
|
||||
.mDescription = std::string{ getGMSTString(settings, "sLucDesc") },
|
||||
.mIcon = "icons\\k\\attribute_luck.dds",
|
||||
.mWerewolfValue = getGMSTFloat(settings, "fWerewolfLuck") });
|
||||
}
|
||||
size_t Store<ESM::Attribute>::getSize() const
|
||||
{
|
||||
return mStatic.size();
|
||||
}
|
||||
Store<ESM::Attribute>::iterator Store<ESM::Attribute>::begin() const
|
||||
{
|
||||
return mStatic.begin();
|
||||
}
|
||||
Store<ESM::Attribute>::iterator Store<ESM::Attribute>::end() const
|
||||
{
|
||||
return mStatic.end();
|
||||
}
|
||||
|
||||
// Dialogue
|
||||
//=========================================================================
|
||||
|
@ -1339,7 +1302,7 @@ namespace MWWorld
|
|||
template class MWWorld::TypedDynamicStore<ESM::Activator>;
|
||||
template class MWWorld::TypedDynamicStore<ESM::Apparatus>;
|
||||
template class MWWorld::TypedDynamicStore<ESM::Armor>;
|
||||
// template class MWWorld::Store<ESM::Attribute>;
|
||||
template class MWWorld::TypedDynamicStore<ESM::Attribute>;
|
||||
template class MWWorld::TypedDynamicStore<ESM::BirthSign>;
|
||||
template class MWWorld::TypedDynamicStore<ESM::BodyPart>;
|
||||
template class MWWorld::TypedDynamicStore<ESM::Book>;
|
||||
|
|
|
@ -9,6 +9,7 @@
|
|||
#include <unordered_map>
|
||||
#include <vector>
|
||||
|
||||
#include <components/esm/attr.hpp>
|
||||
#include <components/esm/refid.hpp>
|
||||
#include <components/esm/util.hpp>
|
||||
#include <components/esm3/loadcell.hpp>
|
||||
|
@ -29,7 +30,6 @@
|
|||
|
||||
namespace ESM
|
||||
{
|
||||
struct Attribute;
|
||||
struct LandTexture;
|
||||
struct MagicEffect;
|
||||
struct WeaponType;
|
||||
|
@ -492,25 +492,14 @@ namespace MWWorld
|
|||
};
|
||||
|
||||
template <>
|
||||
class Store<ESM::Attribute> : public IndexedStore<ESM::Attribute>
|
||||
class Store<ESM::Attribute> : public TypedDynamicStore<ESM::Attribute>
|
||||
{
|
||||
std::vector<ESM::Attribute> mStatic;
|
||||
using TypedDynamicStore<ESM::Attribute>::setUp;
|
||||
|
||||
public:
|
||||
typedef std::vector<ESM::Attribute>::const_iterator iterator;
|
||||
|
||||
Store();
|
||||
|
||||
const ESM::Attribute* search(size_t index) const;
|
||||
|
||||
// calls `search` and throws an exception if not found
|
||||
const ESM::Attribute* find(size_t index) const;
|
||||
Store() = default;
|
||||
|
||||
void setUp(const MWWorld::Store<ESM::GameSetting>& settings);
|
||||
|
||||
size_t getSize() const;
|
||||
iterator begin() const;
|
||||
iterator end() const;
|
||||
};
|
||||
|
||||
template <>
|
||||
|
|
|
@ -456,6 +456,8 @@ namespace
|
|||
{
|
||||
refId = ESM::RefId::esm3ExteriorCell(0, 0);
|
||||
}
|
||||
else if constexpr (std::is_same_v<RecordType, ESM::Attribute>)
|
||||
refId = ESM::Attribute::Strength;
|
||||
else if constexpr (std::is_same_v<RecordType, ESM::Skill>)
|
||||
refId = ESM::Skill::Block;
|
||||
else
|
||||
|
@ -485,6 +487,12 @@ namespace
|
|||
ESM::Dialogue* dialogue = nullptr;
|
||||
MWWorld::ESMStore esmStore;
|
||||
|
||||
if constexpr (std::is_same_v<RecordType, ESM::Attribute>)
|
||||
{
|
||||
ASSERT_ANY_THROW(getEsmFile(record, false, formatVersion));
|
||||
continue;
|
||||
}
|
||||
|
||||
reader.open(getEsmFile(record, false, formatVersion), "filename");
|
||||
ASSERT_NO_THROW(esmStore.load(reader, &dummyListener, dialogue));
|
||||
esmStore.setUp();
|
||||
|
@ -575,7 +583,7 @@ namespace
|
|||
|
||||
REGISTER_TYPED_TEST_SUITE_P(StoreSaveLoadTest, shouldNotChangeRefId);
|
||||
|
||||
static_assert(std::tuple_size_v<RecordTypesWithSave> == 39);
|
||||
static_assert(std::tuple_size_v<RecordTypesWithSave> == 40);
|
||||
|
||||
INSTANTIATE_TYPED_TEST_SUITE_P(
|
||||
RecordTypesTest, StoreSaveLoadTest, typename AsTestingTypes<RecordTypesWithSave>::Type);
|
||||
|
|
|
@ -1,25 +1,56 @@
|
|||
#include "attr.hpp"
|
||||
#include <components/misc/strings/algorithm.hpp>
|
||||
|
||||
#include <components/esm3/esmreader.hpp>
|
||||
#include <components/esm3/esmwriter.hpp>
|
||||
|
||||
#include <stdexcept>
|
||||
|
||||
using namespace ESM;
|
||||
|
||||
const std::string Attribute::sAttributeNames[Attribute::Length] = {
|
||||
"Strength",
|
||||
"Intelligence",
|
||||
"Willpower",
|
||||
"Agility",
|
||||
"Speed",
|
||||
"Endurance",
|
||||
"Personality",
|
||||
"Luck",
|
||||
};
|
||||
|
||||
Attribute::AttributeID Attribute::stringToAttributeId(std::string_view attribute)
|
||||
namespace ESM
|
||||
{
|
||||
for (int id = 0; id < Attribute::Length; ++id)
|
||||
if (Misc::StringUtils::ciEqual(sAttributeNames[id], attribute))
|
||||
return Attribute::AttributeID(id);
|
||||
const Attribute::AttributeID Attribute::Strength("Strength");
|
||||
const Attribute::AttributeID Attribute::Intelligence("Intelligence");
|
||||
const Attribute::AttributeID Attribute::Willpower("Willpower");
|
||||
const Attribute::AttributeID Attribute::Agility("Agility");
|
||||
const Attribute::AttributeID Attribute::Speed("Speed");
|
||||
const Attribute::AttributeID Attribute::Endurance("Endurance");
|
||||
const Attribute::AttributeID Attribute::Personality("Personality");
|
||||
const Attribute::AttributeID Attribute::Luck("Luck");
|
||||
|
||||
throw std::logic_error("No such attribute: " + std::string(attribute));
|
||||
static const RefId sAttributes[Attribute::Length] = {
|
||||
Attribute::Strength,
|
||||
Attribute::Intelligence,
|
||||
Attribute::Willpower,
|
||||
Attribute::Agility,
|
||||
Attribute::Speed,
|
||||
Attribute::Endurance,
|
||||
Attribute::Personality,
|
||||
Attribute::Luck,
|
||||
};
|
||||
|
||||
RefId Attribute::indexToRefId(int index)
|
||||
{
|
||||
if (index < 0 || index >= Length)
|
||||
return RefId();
|
||||
return sAttributes[index];
|
||||
}
|
||||
|
||||
int Attribute::refIdToIndex(RefId id)
|
||||
{
|
||||
for (int i = 0; i < Length; ++i)
|
||||
{
|
||||
if (sAttributes[i] == id)
|
||||
return i;
|
||||
}
|
||||
return -1;
|
||||
}
|
||||
|
||||
void Attribute::load(ESMReader& esm, bool& isDeleted)
|
||||
{
|
||||
throw std::runtime_error("Attribute loading not yet implemented");
|
||||
}
|
||||
|
||||
void Attribute::save(ESMWriter& esm, bool isDeleted) const
|
||||
{
|
||||
throw std::runtime_error("Attribute saving not yet implemented");
|
||||
}
|
||||
}
|
||||
|
|
|
@ -2,9 +2,15 @@
|
|||
#define OPENMW_ESM_ATTR_H
|
||||
|
||||
#include <string>
|
||||
#include <string_view>
|
||||
|
||||
#include "defs.hpp"
|
||||
#include "refid.hpp"
|
||||
|
||||
namespace ESM
|
||||
{
|
||||
class ESMReader;
|
||||
class ESMWriter;
|
||||
|
||||
/*
|
||||
* Attribute definitions
|
||||
|
@ -12,26 +18,30 @@ namespace ESM
|
|||
|
||||
struct Attribute
|
||||
{
|
||||
enum AttributeID
|
||||
{
|
||||
Strength = 0,
|
||||
Intelligence = 1,
|
||||
Willpower = 2,
|
||||
Agility = 3,
|
||||
Speed = 4,
|
||||
Endurance = 5,
|
||||
Personality = 6,
|
||||
Luck = 7,
|
||||
Length = 8
|
||||
};
|
||||
constexpr static RecNameInts sRecordId = REC_ATTR;
|
||||
/// Return a string descriptor for this record type. Currently used for debugging / error logs only.
|
||||
static std::string_view getRecordType() { return "Attribute"; }
|
||||
|
||||
using AttributeID = StringRefId;
|
||||
static const AttributeID Strength;
|
||||
static const AttributeID Intelligence;
|
||||
static const AttributeID Willpower;
|
||||
static const AttributeID Agility;
|
||||
static const AttributeID Speed;
|
||||
static const AttributeID Endurance;
|
||||
static const AttributeID Personality;
|
||||
static const AttributeID Luck;
|
||||
static constexpr int Length = 8;
|
||||
|
||||
AttributeID mId;
|
||||
std::string mName, mDescription, mIcon;
|
||||
float mWerewolfValue{};
|
||||
|
||||
static const std::string sAttributeNames[Length];
|
||||
void load(ESMReader& esm, bool& isDeleted);
|
||||
void save(ESMWriter& esm, bool isDeleted = false) const;
|
||||
|
||||
static AttributeID stringToAttributeId(std::string_view attribute);
|
||||
static RefId indexToRefId(int index);
|
||||
static int refIdToIndex(RefId id);
|
||||
};
|
||||
}
|
||||
#endif
|
||||
|
|
|
@ -180,6 +180,8 @@ namespace ESM
|
|||
// format 21 - Random state in saved games.
|
||||
REC_RAND = esm3Recname("RAND"), // Random state.
|
||||
|
||||
REC_ATTR = esm3Recname("ATTR"), // Attribute
|
||||
|
||||
REC_AACT4 = esm4Recname(ESM4::REC_AACT), // Action
|
||||
REC_ACHR4 = esm4Recname(ESM4::REC_ACHR), // Actor Reference
|
||||
REC_ACTI4 = esm4Recname(ESM4::REC_ACTI), // Activator
|
||||
|
|
|
@ -2,11 +2,93 @@
|
|||
|
||||
#include "esmreader.hpp"
|
||||
#include "esmwriter.hpp"
|
||||
#include "loadmgef.hpp"
|
||||
#include "loadskil.hpp"
|
||||
|
||||
#include <components/esm/attr.hpp>
|
||||
|
||||
#include <cstdint>
|
||||
|
||||
namespace ESM
|
||||
{
|
||||
namespace
|
||||
{
|
||||
bool isSummon(int effectId)
|
||||
{
|
||||
switch (effectId)
|
||||
{
|
||||
case MagicEffect::SummonScamp:
|
||||
case MagicEffect::SummonClannfear:
|
||||
case MagicEffect::SummonDaedroth:
|
||||
case MagicEffect::SummonDremora:
|
||||
case MagicEffect::SummonAncestralGhost:
|
||||
case MagicEffect::SummonSkeletalMinion:
|
||||
case MagicEffect::SummonBonewalker:
|
||||
case MagicEffect::SummonGreaterBonewalker:
|
||||
case MagicEffect::SummonBonelord:
|
||||
case MagicEffect::SummonWingedTwilight:
|
||||
case MagicEffect::SummonHunger:
|
||||
case MagicEffect::SummonGoldenSaint:
|
||||
case MagicEffect::SummonFlameAtronach:
|
||||
case MagicEffect::SummonFrostAtronach:
|
||||
case MagicEffect::SummonStormAtronach:
|
||||
case MagicEffect::SummonCenturionSphere:
|
||||
case MagicEffect::SummonFabricant:
|
||||
case MagicEffect::SummonWolf:
|
||||
case MagicEffect::SummonBear:
|
||||
case MagicEffect::SummonBonewolf:
|
||||
case MagicEffect::SummonCreature04:
|
||||
case MagicEffect::SummonCreature05:
|
||||
return true;
|
||||
}
|
||||
return false;
|
||||
}
|
||||
bool affectsAttribute(int effectId)
|
||||
{
|
||||
switch (effectId)
|
||||
{
|
||||
case MagicEffect::DrainAttribute:
|
||||
case MagicEffect::DamageAttribute:
|
||||
case MagicEffect::RestoreAttribute:
|
||||
case MagicEffect::FortifyAttribute:
|
||||
case MagicEffect::AbsorbAttribute:
|
||||
return true;
|
||||
}
|
||||
return false;
|
||||
}
|
||||
bool affectsSkill(int effectId)
|
||||
{
|
||||
switch (effectId)
|
||||
{
|
||||
case MagicEffect::DrainSkill:
|
||||
case MagicEffect::DamageSkill:
|
||||
case MagicEffect::RestoreSkill:
|
||||
case MagicEffect::FortifySkill:
|
||||
case MagicEffect::AbsorbSkill:
|
||||
return true;
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
struct ToInt
|
||||
{
|
||||
int effectId;
|
||||
|
||||
int operator()(const ESM::RefId& id) const
|
||||
{
|
||||
if (!id.empty())
|
||||
{
|
||||
if (affectsAttribute(effectId))
|
||||
return ESM::Attribute::refIdToIndex(id);
|
||||
else if (affectsSkill(effectId))
|
||||
return ESM::Skill::refIdToIndex(id);
|
||||
}
|
||||
return -1;
|
||||
}
|
||||
|
||||
int operator()(int actor) const { return actor; }
|
||||
};
|
||||
|
||||
void saveImpl(ESMWriter& esm, const std::vector<ActiveSpells::ActiveSpellParams>& spells, NAME tag)
|
||||
{
|
||||
for (const auto& params : spells)
|
||||
|
@ -27,8 +109,9 @@ namespace ESM
|
|||
for (auto& effect : params.mEffects)
|
||||
{
|
||||
esm.writeHNT("MGEF", effect.mEffectId);
|
||||
if (effect.mArg != -1)
|
||||
esm.writeHNT("ARG_", effect.mArg);
|
||||
int arg = std::visit(ToInt{ effect.mEffectId }, effect.mArg);
|
||||
if (arg != -1)
|
||||
esm.writeHNT("ARG_", arg);
|
||||
esm.writeHNT("MAGN", effect.mMagnitude);
|
||||
esm.writeHNT("MAGN", effect.mMinMagnitude);
|
||||
esm.writeHNT("MAGN", effect.mMaxMagnitude);
|
||||
|
@ -81,8 +164,17 @@ namespace ESM
|
|||
{
|
||||
ActiveEffect effect;
|
||||
esm.getHT(effect.mEffectId);
|
||||
effect.mArg = -1;
|
||||
esm.getHNOT(effect.mArg, "ARG_");
|
||||
int32_t arg = -1;
|
||||
esm.getHNOT(arg, "ARG_");
|
||||
if (arg >= 0)
|
||||
{
|
||||
if (isSummon(effect.mEffectId))
|
||||
effect.mArg = arg;
|
||||
else if (affectsAttribute(effect.mEffectId))
|
||||
effect.mArg = ESM::Attribute::indexToRefId(arg);
|
||||
else if (affectsSkill(effect.mEffectId))
|
||||
effect.mArg = ESM::Skill::indexToRefId(arg);
|
||||
}
|
||||
esm.getHNT(effect.mMagnitude, "MAGN");
|
||||
if (format <= MaxClearModifiersFormatVersion)
|
||||
{
|
||||
|
@ -112,10 +204,7 @@ namespace ESM
|
|||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
namespace ESM
|
||||
{
|
||||
void ActiveSpells::save(ESMWriter& esm) const
|
||||
{
|
||||
saveImpl(esm, mSpells, "ID__");
|
||||
|
@ -127,4 +216,18 @@ namespace ESM
|
|||
loadImpl(esm, mSpells, "ID__");
|
||||
loadImpl(esm, mQueue, "QID_");
|
||||
}
|
||||
|
||||
RefId ActiveEffect::getSkillOrAttribute() const
|
||||
{
|
||||
if (const auto* id = std::get_if<ESM::RefId>(&mArg))
|
||||
return *id;
|
||||
return {};
|
||||
}
|
||||
|
||||
int ActiveEffect::getActorId() const
|
||||
{
|
||||
if (const auto* id = std::get_if<int>(&mArg))
|
||||
return *id;
|
||||
return -1;
|
||||
}
|
||||
}
|
||||
|
|
|
@ -7,6 +7,7 @@
|
|||
#include "timestamp.hpp"
|
||||
|
||||
#include <string>
|
||||
#include <variant>
|
||||
#include <vector>
|
||||
|
||||
namespace ESM
|
||||
|
@ -32,11 +33,14 @@ namespace ESM
|
|||
float mMagnitude;
|
||||
float mMinMagnitude;
|
||||
float mMaxMagnitude;
|
||||
int32_t mArg; // skill or attribute
|
||||
std::variant<RefId, int> mArg; // skill, attribute, or summon
|
||||
float mDuration;
|
||||
float mTimeLeft;
|
||||
int32_t mEffectIndex;
|
||||
int32_t mFlags;
|
||||
|
||||
RefId getSkillOrAttribute() const;
|
||||
int getActorId() const;
|
||||
};
|
||||
|
||||
// format 0, saved games only
|
||||
|
|
Loading…
Reference in a new issue