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