mirror of
https://github.com/OpenMW/openmw.git
synced 2025-06-19 22:11:34 +00:00
Merge branch 'clickbait' into 'master'
Mostly dehardcode attributes See merge request OpenMW/openmw!3164
This commit is contained in:
commit
dd0d66513d
43 changed files with 378 additions and 638 deletions
|
@ -1171,7 +1171,7 @@ namespace EsmTool
|
||||||
template <>
|
template <>
|
||||||
void Record<ESM::Race>::print()
|
void Record<ESM::Race>::print()
|
||||||
{
|
{
|
||||||
static const char* sAttributeNames[8]
|
static const char* sAttributeNames[ESM::Attribute::Length]
|
||||||
= { "Strength", "Intelligence", "Willpower", "Agility", "Speed", "Endurance", "Personality", "Luck" };
|
= { "Strength", "Intelligence", "Willpower", "Agility", "Speed", "Endurance", "Personality", "Luck" };
|
||||||
|
|
||||||
std::cout << " Name: " << mData.mName << std::endl;
|
std::cout << " Name: " << mData.mName << std::endl;
|
||||||
|
|
|
@ -7,6 +7,7 @@
|
||||||
#include <apps/opencs/model/world/refiddata.hpp>
|
#include <apps/opencs/model/world/refiddata.hpp>
|
||||||
#include <apps/opencs/model/world/universalid.hpp>
|
#include <apps/opencs/model/world/universalid.hpp>
|
||||||
|
|
||||||
|
#include <components/esm/attr.hpp>
|
||||||
#include <components/esm3/loadcont.hpp>
|
#include <components/esm3/loadcont.hpp>
|
||||||
#include <components/esm3/loadmgef.hpp>
|
#include <components/esm3/loadmgef.hpp>
|
||||||
#include <components/esm3/loadskil.hpp>
|
#include <components/esm3/loadskil.hpp>
|
||||||
|
@ -1007,8 +1008,7 @@ int CSMWorld::NpcAttributesRefIdAdapter::getNestedColumnsCount(const RefIdColumn
|
||||||
int CSMWorld::NpcAttributesRefIdAdapter::getNestedRowsCount(
|
int CSMWorld::NpcAttributesRefIdAdapter::getNestedRowsCount(
|
||||||
const RefIdColumn* column, const RefIdData& data, int index) const
|
const RefIdColumn* column, const RefIdData& data, int index) const
|
||||||
{
|
{
|
||||||
// There are 8 attributes
|
return ESM::Attribute::Length;
|
||||||
return 8;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
void CSMWorld::NpcSkillsRefIdAdapter::addNestedRow(
|
void CSMWorld::NpcSkillsRefIdAdapter::addNestedRow(
|
||||||
|
@ -1385,8 +1385,7 @@ int CSMWorld::CreatureAttributesRefIdAdapter::getNestedColumnsCount(
|
||||||
int CSMWorld::CreatureAttributesRefIdAdapter::getNestedRowsCount(
|
int CSMWorld::CreatureAttributesRefIdAdapter::getNestedRowsCount(
|
||||||
const RefIdColumn* column, const RefIdData& data, int index) const
|
const RefIdColumn* column, const RefIdData& data, int index) const
|
||||||
{
|
{
|
||||||
// There are 8 attributes
|
return ESM::Attribute::Length;
|
||||||
return 8;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
void CSMWorld::CreatureAttackRefIdAdapter::addNestedRow(
|
void CSMWorld::CreatureAttackRefIdAdapter::addNestedRow(
|
||||||
|
|
|
@ -123,7 +123,7 @@ namespace MWClass
|
||||||
const MWWorld::LiveCellRef<ESM::Clothing>* ref = ptr.get<ESM::Clothing>();
|
const MWWorld::LiveCellRef<ESM::Clothing>* ref = ptr.get<ESM::Clothing>();
|
||||||
static const ESM::RefId ringUp = ESM::RefId::stringRefId("Item Ring Up");
|
static const ESM::RefId ringUp = ESM::RefId::stringRefId("Item Ring Up");
|
||||||
static const ESM::RefId clothsUp = ESM::RefId::stringRefId("Item Clothes Up");
|
static const ESM::RefId clothsUp = ESM::RefId::stringRefId("Item Clothes Up");
|
||||||
if (ref->mBase->mData.mType == 8)
|
if (ref->mBase->mData.mType == ESM::Clothing::Ring)
|
||||||
{
|
{
|
||||||
return ringUp;
|
return ringUp;
|
||||||
}
|
}
|
||||||
|
@ -135,7 +135,7 @@ namespace MWClass
|
||||||
const MWWorld::LiveCellRef<ESM::Clothing>* ref = ptr.get<ESM::Clothing>();
|
const MWWorld::LiveCellRef<ESM::Clothing>* ref = ptr.get<ESM::Clothing>();
|
||||||
static const ESM::RefId ringDown = ESM::RefId::stringRefId("Item Ring Down");
|
static const ESM::RefId ringDown = ESM::RefId::stringRefId("Item Ring Down");
|
||||||
static const ESM::RefId clothsDown = ESM::RefId::stringRefId("Item Clothes Down");
|
static const ESM::RefId clothsDown = ESM::RefId::stringRefId("Item Clothes Down");
|
||||||
if (ref->mBase->mData.mType == 8)
|
if (ref->mBase->mData.mType == ESM::Clothing::Ring)
|
||||||
{
|
{
|
||||||
return ringDown;
|
return ringDown;
|
||||||
}
|
}
|
||||||
|
|
|
@ -88,11 +88,12 @@ namespace
|
||||||
|
|
||||||
bool male = (npc->mFlags & ESM::NPC::Female) == 0;
|
bool male = (npc->mFlags & ESM::NPC::Female) == 0;
|
||||||
|
|
||||||
|
const auto& attributes = MWBase::Environment::get().getESMStore()->get<ESM::Attribute>();
|
||||||
int level = creatureStats.getLevel();
|
int level = creatureStats.getLevel();
|
||||||
for (int i = 0; i < ESM::Attribute::Length; ++i)
|
for (const ESM::Attribute& attribute : attributes)
|
||||||
{
|
{
|
||||||
const ESM::Race::MaleFemale& attribute = race->mData.mAttributeValues[i];
|
const ESM::Race::MaleFemale& value = race->mData.mAttributeValues[attribute.mId];
|
||||||
creatureStats.setAttribute(i, male ? attribute.mMale : attribute.mFemale);
|
creatureStats.setAttribute(attribute.mId, male ? value.mMale : value.mFemale);
|
||||||
}
|
}
|
||||||
|
|
||||||
// class bonus
|
// class bonus
|
||||||
|
@ -102,18 +103,19 @@ namespace
|
||||||
{
|
{
|
||||||
if (attribute >= 0 && attribute < ESM::Attribute::Length)
|
if (attribute >= 0 && attribute < ESM::Attribute::Length)
|
||||||
{
|
{
|
||||||
creatureStats.setAttribute(attribute, creatureStats.getAttribute(attribute).getBase() + 10);
|
auto id = static_cast<ESM::Attribute::AttributeID>(attribute);
|
||||||
|
creatureStats.setAttribute(id, creatureStats.getAttribute(id).getBase() + 10);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// skill bonus
|
// skill bonus
|
||||||
for (int attribute = 0; attribute < ESM::Attribute::Length; ++attribute)
|
for (const ESM::Attribute& attribute : attributes)
|
||||||
{
|
{
|
||||||
float modifierSum = 0;
|
float modifierSum = 0;
|
||||||
|
|
||||||
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)
|
if (skill.mData.mAttribute != attribute.mId)
|
||||||
continue;
|
continue;
|
||||||
|
|
||||||
// is this a minor or major skill?
|
// is this a minor or major skill?
|
||||||
|
@ -127,9 +129,10 @@ namespace
|
||||||
}
|
}
|
||||||
modifierSum += add;
|
modifierSum += add;
|
||||||
}
|
}
|
||||||
creatureStats.setAttribute(attribute,
|
creatureStats.setAttribute(attribute.mId,
|
||||||
std::min(
|
std::min(
|
||||||
round_ieee_754(creatureStats.getAttribute(attribute).getBase() + (level - 1) * modifierSum), 100));
|
round_ieee_754(creatureStats.getAttribute(attribute.mId).getBase() + (level - 1) * modifierSum),
|
||||||
|
100));
|
||||||
}
|
}
|
||||||
|
|
||||||
// initial health
|
// initial health
|
||||||
|
@ -223,13 +226,10 @@ namespace
|
||||||
100)); // Must gracefully handle level 0
|
100)); // Must gracefully handle level 0
|
||||||
}
|
}
|
||||||
|
|
||||||
int attributes[ESM::Attribute::Length];
|
|
||||||
for (int i = 0; i < ESM::Attribute::Length; ++i)
|
|
||||||
attributes[i] = npcStats.getAttribute(i).getBase();
|
|
||||||
|
|
||||||
if (!spellsInitialised)
|
if (!spellsInitialised)
|
||||||
{
|
{
|
||||||
std::vector<ESM::RefId> spells = MWMechanics::autoCalcNpcSpells(npcStats.getSkills(), attributes, race);
|
std::vector<ESM::RefId> spells
|
||||||
|
= MWMechanics::autoCalcNpcSpells(npcStats.getSkills(), npcStats.getAttributes(), race);
|
||||||
npcStats.getSpells().addAllToInstance(spells);
|
npcStats.getSpells().addAllToInstance(spells);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -382,9 +382,10 @@ int MWDialogue::Filter::getSelectStructInteger(const SelectWrapper& select) cons
|
||||||
.getModified(false);
|
.getModified(false);
|
||||||
|
|
||||||
case SelectWrapper::Function_PcAttribute:
|
case SelectWrapper::Function_PcAttribute:
|
||||||
|
{
|
||||||
return player.getClass().getCreatureStats(player).getAttribute(select.getArgument()).getModified();
|
auto attribute = static_cast<ESM::Attribute::AttributeID>(select.getArgument());
|
||||||
|
return player.getClass().getCreatureStats(player).getAttribute(attribute).getModified();
|
||||||
|
}
|
||||||
case SelectWrapper::Function_PcSkill:
|
case SelectWrapper::Function_PcSkill:
|
||||||
{
|
{
|
||||||
ESM::RefId skill = ESM::Skill::indexToRefId(select.getArgument());
|
ESM::RefId skill = ESM::Skill::indexToRefId(select.getArgument());
|
||||||
|
@ -653,8 +654,10 @@ bool MWDialogue::Filter::hasFactionRankSkillRequirements(
|
||||||
|
|
||||||
MWMechanics::CreatureStats& stats = actor.getClass().getCreatureStats(actor);
|
MWMechanics::CreatureStats& stats = actor.getClass().getCreatureStats(actor);
|
||||||
|
|
||||||
return stats.getAttribute(faction.mData.mAttribute[0]).getBase() >= faction.mData.mRankData[rank].mAttribute1
|
return stats.getAttribute(ESM::Attribute::AttributeID(faction.mData.mAttribute[0])).getBase()
|
||||||
&& stats.getAttribute(faction.mData.mAttribute[1]).getBase() >= faction.mData.mRankData[rank].mAttribute2;
|
>= faction.mData.mRankData[rank].mAttribute1
|
||||||
|
&& stats.getAttribute(ESM::Attribute::AttributeID(faction.mData.mAttribute[1])).getBase()
|
||||||
|
>= faction.mData.mRankData[rank].mAttribute2;
|
||||||
}
|
}
|
||||||
|
|
||||||
bool MWDialogue::Filter::hasFactionRankReputationRequirements(
|
bool MWDialogue::Filter::hasFactionRankReputationRequirements(
|
||||||
|
|
|
@ -102,21 +102,11 @@ namespace MWGui
|
||||||
mPlayerSkillValues.emplace(skill.mId, MWMechanics::SkillValue());
|
mPlayerSkillValues.emplace(skill.mId, MWMechanics::SkillValue());
|
||||||
}
|
}
|
||||||
|
|
||||||
void CharacterCreation::setValue(std::string_view id, const MWMechanics::AttributeValue& value)
|
void CharacterCreation::setValue(ESM::Attribute::AttributeID id, const MWMechanics::AttributeValue& value)
|
||||||
{
|
{
|
||||||
std::string_view prefix = "AttribVal";
|
mPlayerAttributes[id] = value;
|
||||||
if (id.starts_with(prefix) && id.size() == prefix.size() + 1)
|
if (mReviewDialog)
|
||||||
{
|
mReviewDialog->setAttribute(id, value);
|
||||||
char index = id[prefix.size()];
|
|
||||||
if (index >= '1' && index <= '8')
|
|
||||||
{
|
|
||||||
// Match [AttribVal1-AttribVal8] to the corresponding AttributeID values [0-7]
|
|
||||||
auto attribute = static_cast<ESM::Attribute::AttributeID>(index - '0' - 1);
|
|
||||||
mPlayerAttributes[attribute] = value;
|
|
||||||
if (mReviewDialog)
|
|
||||||
mReviewDialog->setAttribute(attribute, value);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
void CharacterCreation::setValue(std::string_view id, const MWMechanics::DynamicStat<float>& value)
|
void CharacterCreation::setValue(std::string_view id, const MWMechanics::DynamicStat<float>& value)
|
||||||
|
|
|
@ -44,7 +44,7 @@ namespace MWGui
|
||||||
// Show a dialog
|
// Show a dialog
|
||||||
void spawnDialog(const char id);
|
void spawnDialog(const char id);
|
||||||
|
|
||||||
void setValue(std::string_view id, const MWMechanics::AttributeValue& value) override;
|
void setValue(ESM::Attribute::AttributeID 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;
|
||||||
|
|
|
@ -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(klass->mData.mAttribute[0]);
|
mFavoriteAttribute[0]->setAttributeId(static_cast<ESM::Attribute::AttributeID>(klass->mData.mAttribute[0]));
|
||||||
mFavoriteAttribute[1]->setAttributeId(klass->mData.mAttribute[1]);
|
mFavoriteAttribute[1]->setAttributeId(static_cast<ESM::Attribute::AttributeID>(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());
|
||||||
|
|
||||||
|
@ -749,30 +749,34 @@ namespace MWGui
|
||||||
center();
|
center();
|
||||||
|
|
||||||
const auto& store = MWBase::Environment::get().getWorld()->getStore().get<ESM::Attribute>();
|
const auto& store = MWBase::Environment::get().getWorld()->getStore().get<ESM::Attribute>();
|
||||||
|
MyGUI::ScrollView* attributes;
|
||||||
|
getWidget(attributes, "Attributes");
|
||||||
|
MyGUI::IntCoord coord{ 0, 0, attributes->getWidth(), 18 };
|
||||||
for (const ESM::Attribute& attribute : store)
|
for (const ESM::Attribute& attribute : store)
|
||||||
{
|
{
|
||||||
Widgets::MWAttributePtr widget;
|
auto* widget
|
||||||
char theIndex = '0' + attribute.mId;
|
= attributes->createWidget<Widgets::MWAttribute>("MW_StatNameButtonC", coord, MyGUI::Align::Default);
|
||||||
|
coord.top += coord.height;
|
||||||
getWidget(widget, std::string("Attribute").append(1, theIndex));
|
|
||||||
widget->setAttributeId(attribute.mId);
|
widget->setAttributeId(attribute.mId);
|
||||||
widget->eventClicked += MyGUI::newDelegate(this, &SelectAttributeDialog::onAttributeClicked);
|
widget->eventClicked += MyGUI::newDelegate(this, &SelectAttributeDialog::onAttributeClicked);
|
||||||
ToolTips::createAttributeToolTip(widget, widget->getAttributeId());
|
ToolTips::createAttributeToolTip(widget, attribute.mId);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
attributes->setVisibleVScroll(false);
|
||||||
|
attributes->setCanvasSize(MyGUI::IntSize(attributes->getWidth(), std::max(attributes->getHeight(), coord.top)));
|
||||||
|
attributes->setVisibleVScroll(true);
|
||||||
|
attributes->setViewOffset(MyGUI::IntPoint());
|
||||||
|
|
||||||
MyGUI::Button* cancelButton;
|
MyGUI::Button* cancelButton;
|
||||||
getWidget(cancelButton, "CancelButton");
|
getWidget(cancelButton, "CancelButton");
|
||||||
cancelButton->eventMouseButtonClick += MyGUI::newDelegate(this, &SelectAttributeDialog::onCancelClicked);
|
cancelButton->eventMouseButtonClick += MyGUI::newDelegate(this, &SelectAttributeDialog::onCancelClicked);
|
||||||
}
|
}
|
||||||
|
|
||||||
SelectAttributeDialog::~SelectAttributeDialog() {}
|
|
||||||
|
|
||||||
// widget controls
|
// widget controls
|
||||||
|
|
||||||
void SelectAttributeDialog::onAttributeClicked(Widgets::MWAttributePtr _sender)
|
void SelectAttributeDialog::onAttributeClicked(Widgets::MWAttributePtr _sender)
|
||||||
{
|
{
|
||||||
// TODO: Change MWAttribute to set and get AttributeID enum instead of int
|
mAttributeId = _sender->getAttributeId();
|
||||||
mAttributeId = static_cast<ESM::Attribute::AttributeID>(_sender->getAttributeId());
|
|
||||||
eventItemSelected();
|
eventItemSelected();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -184,7 +184,7 @@ namespace MWGui
|
||||||
{
|
{
|
||||||
public:
|
public:
|
||||||
SelectAttributeDialog();
|
SelectAttributeDialog();
|
||||||
~SelectAttributeDialog();
|
~SelectAttributeDialog() override = default;
|
||||||
|
|
||||||
bool exit() override;
|
bool exit() override;
|
||||||
|
|
||||||
|
|
|
@ -3,8 +3,11 @@
|
||||||
#include <MyGUI_Button.h>
|
#include <MyGUI_Button.h>
|
||||||
#include <MyGUI_EditBox.h>
|
#include <MyGUI_EditBox.h>
|
||||||
#include <MyGUI_ImageBox.h>
|
#include <MyGUI_ImageBox.h>
|
||||||
|
#include <MyGUI_ScrollView.h>
|
||||||
|
#include <MyGUI_TextBox.h>
|
||||||
|
|
||||||
#include <components/fallback/fallback.hpp>
|
#include <components/fallback/fallback.hpp>
|
||||||
|
#include <components/widgets/box.hpp>
|
||||||
|
|
||||||
#include "../mwbase/environment.hpp"
|
#include "../mwbase/environment.hpp"
|
||||||
#include "../mwbase/soundmanager.hpp"
|
#include "../mwbase/soundmanager.hpp"
|
||||||
|
@ -12,6 +15,7 @@
|
||||||
#include "../mwbase/world.hpp"
|
#include "../mwbase/world.hpp"
|
||||||
|
|
||||||
#include "../mwworld/class.hpp"
|
#include "../mwworld/class.hpp"
|
||||||
|
#include "../mwworld/esmstore.hpp"
|
||||||
|
|
||||||
#include "../mwmechanics/actorutil.hpp"
|
#include "../mwmechanics/actorutil.hpp"
|
||||||
#include "../mwmechanics/creaturestats.hpp"
|
#include "../mwmechanics/creaturestats.hpp"
|
||||||
|
@ -20,9 +24,13 @@
|
||||||
#include "class.hpp"
|
#include "class.hpp"
|
||||||
#include "ustring.hpp"
|
#include "ustring.hpp"
|
||||||
|
|
||||||
|
namespace
|
||||||
|
{
|
||||||
|
constexpr unsigned int sMaxCoins = 3;
|
||||||
|
constexpr int sColumnOffsets[] = { 32, 218 };
|
||||||
|
}
|
||||||
namespace MWGui
|
namespace MWGui
|
||||||
{
|
{
|
||||||
const unsigned int LevelupDialog::sMaxCoins = 3;
|
|
||||||
LevelupDialog::LevelupDialog()
|
LevelupDialog::LevelupDialog()
|
||||||
: WindowBase("openmw_levelup_dialog.layout")
|
: WindowBase("openmw_levelup_dialog.layout")
|
||||||
, mCoinCount(sMaxCoins)
|
, mCoinCount(sMaxCoins)
|
||||||
|
@ -36,23 +44,43 @@ namespace MWGui
|
||||||
|
|
||||||
mOkButton->eventMouseButtonClick += MyGUI::newDelegate(this, &LevelupDialog::onOkButtonClicked);
|
mOkButton->eventMouseButtonClick += MyGUI::newDelegate(this, &LevelupDialog::onOkButtonClicked);
|
||||||
|
|
||||||
for (int i = 1; i < 9; ++i)
|
|
||||||
{
|
{
|
||||||
MyGUI::TextBox* t;
|
const auto& store = MWBase::Environment::get().getESMStore()->get<ESM::Attribute>();
|
||||||
getWidget(t, "AttribVal" + MyGUI::utility::toString(i));
|
const size_t perCol
|
||||||
mAttributeValues.push_back(t);
|
= static_cast<size_t>(std::ceil(store.getSize() / static_cast<float>(std::size(sColumnOffsets))));
|
||||||
|
size_t i = 0;
|
||||||
|
for (const ESM::Attribute& attribute : store)
|
||||||
|
{
|
||||||
|
const int offset = sColumnOffsets[i / perCol];
|
||||||
|
const int row = static_cast<int>(i % perCol);
|
||||||
|
Widgets widgets;
|
||||||
|
widgets.mMultiplier = mAssignWidget->createWidget<MyGUI::TextBox>(
|
||||||
|
"SandTextVCenter", { offset, 20 * row, 100, 20 }, MyGUI::Align::Default);
|
||||||
|
auto* hbox = mAssignWidget->createWidget<Gui::HBox>(
|
||||||
|
{}, { offset + 20, 20 * row, 200, 20 }, MyGUI::Align::Default);
|
||||||
|
widgets.mButton = hbox->createWidget<Gui::AutoSizedButton>("SandTextButton", {}, MyGUI::Align::Default);
|
||||||
|
widgets.mButton->setUserData(attribute.mId);
|
||||||
|
widgets.mButton->eventMouseButtonClick += MyGUI::newDelegate(this, &LevelupDialog::onAttributeClicked);
|
||||||
|
widgets.mButton->setUserString("TextPadding", "0 0");
|
||||||
|
widgets.mButton->setUserString("ToolTipType", "Layout");
|
||||||
|
widgets.mButton->setUserString("ToolTipLayout", "AttributeToolTip");
|
||||||
|
widgets.mButton->setUserString("Caption_AttributeName", attribute.mName);
|
||||||
|
widgets.mButton->setUserString("Caption_AttributeDescription", attribute.mDescription);
|
||||||
|
widgets.mButton->setUserString("ImageTexture_AttributeImage", attribute.mIcon);
|
||||||
|
widgets.mButton->setCaption(attribute.mName);
|
||||||
|
widgets.mValue = hbox->createWidget<Gui::AutoSizedTextBox>("SandText", {}, MyGUI::Align::Default);
|
||||||
|
mAttributeWidgets.emplace(attribute.mId, widgets);
|
||||||
|
++i;
|
||||||
|
}
|
||||||
|
|
||||||
MyGUI::Button* b;
|
mAssignWidget->setVisibleVScroll(false);
|
||||||
getWidget(b, "Attrib" + MyGUI::utility::toString(i));
|
mAssignWidget->setCanvasSize(MyGUI::IntSize(
|
||||||
b->setUserData(i - 1);
|
mAssignWidget->getWidth(), std::max(mAssignWidget->getHeight(), static_cast<int>(20 * perCol))));
|
||||||
b->eventMouseButtonClick += MyGUI::newDelegate(this, &LevelupDialog::onAttributeClicked);
|
mAssignWidget->setVisibleVScroll(true);
|
||||||
mAttributes.push_back(b);
|
mAssignWidget->setViewOffset(MyGUI::IntPoint());
|
||||||
|
|
||||||
getWidget(t, "AttribMultiplier" + MyGUI::utility::toString(i));
|
|
||||||
mAttributeMultipliers.push_back(t);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
for (unsigned int i = 0; i < mCoinCount; ++i)
|
for (unsigned int i = 0; i < sMaxCoins; ++i)
|
||||||
{
|
{
|
||||||
MyGUI::ImageBox* image = mCoinBox->createWidget<MyGUI::ImageBox>(
|
MyGUI::ImageBox* image = mCoinBox->createWidget<MyGUI::ImageBox>(
|
||||||
"ImageBox", MyGUI::IntCoord(0, 0, 16, 16), MyGUI::Align::Default);
|
"ImageBox", MyGUI::IntCoord(0, 0, 16, 16), MyGUI::Align::Default);
|
||||||
|
@ -69,24 +97,24 @@ namespace MWGui
|
||||||
MWMechanics::CreatureStats& creatureStats = player.getClass().getCreatureStats(player);
|
MWMechanics::CreatureStats& creatureStats = player.getClass().getCreatureStats(player);
|
||||||
MWMechanics::NpcStats& pcStats = player.getClass().getNpcStats(player);
|
MWMechanics::NpcStats& pcStats = player.getClass().getNpcStats(player);
|
||||||
|
|
||||||
for (int i = 0; i < 8; ++i)
|
for (const ESM::Attribute& attribute : MWBase::Environment::get().getESMStore()->get<ESM::Attribute>())
|
||||||
{
|
{
|
||||||
int val = creatureStats.getAttribute(i).getBase();
|
int val = creatureStats.getAttribute(attribute.mId).getBase();
|
||||||
if (std::find(mSpentAttributes.begin(), mSpentAttributes.end(), i) != mSpentAttributes.end())
|
if (std::find(mSpentAttributes.begin(), mSpentAttributes.end(), attribute.mId) != mSpentAttributes.end())
|
||||||
{
|
{
|
||||||
val += pcStats.getLevelupAttributeMultiplier(i);
|
val += pcStats.getLevelupAttributeMultiplier(attribute.mId);
|
||||||
}
|
}
|
||||||
|
|
||||||
if (val >= 100)
|
if (val >= 100)
|
||||||
val = 100;
|
val = 100;
|
||||||
|
|
||||||
mAttributeValues[i]->setCaption(MyGUI::utility::toString(val));
|
mAttributeWidgets[attribute.mId].mValue->setCaption(MyGUI::utility::toString(val));
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
void LevelupDialog::resetCoins()
|
void LevelupDialog::resetCoins()
|
||||||
{
|
{
|
||||||
const int coinSpacing = 33;
|
constexpr int coinSpacing = 33;
|
||||||
int curX = mCoinBox->getWidth() / 2 - (coinSpacing * (mCoinCount - 1) + 16 * mCoinCount) / 2;
|
int curX = mCoinBox->getWidth() / 2 - (coinSpacing * (mCoinCount - 1) + 16 * mCoinCount) / 2;
|
||||||
for (unsigned int i = 0; i < sMaxCoins; ++i)
|
for (unsigned int i = 0; i < sMaxCoins; ++i)
|
||||||
{
|
{
|
||||||
|
@ -113,13 +141,15 @@ namespace MWGui
|
||||||
image->detachFromWidget();
|
image->detachFromWidget();
|
||||||
image->attachToWidget(mAssignWidget);
|
image->attachToWidget(mAssignWidget);
|
||||||
|
|
||||||
int attribute = mSpentAttributes[i];
|
const auto& attribute = mSpentAttributes[i];
|
||||||
|
const auto& widgets = mAttributeWidgets[attribute];
|
||||||
|
|
||||||
int xdiff = mAttributeMultipliers[attribute]->getCaption().empty() ? 0 : 20;
|
const int xdiff = widgets.mMultiplier->getCaption().empty() ? 0 : 20;
|
||||||
|
const auto* hbox = widgets.mButton->getParent();
|
||||||
|
|
||||||
MyGUI::IntPoint pos = mAttributes[attribute]->getAbsolutePosition() - mAssignWidget->getAbsolutePosition()
|
MyGUI::IntPoint pos = hbox->getPosition();
|
||||||
- MyGUI::IntPoint(22 + xdiff, 0);
|
pos.left -= 22 + xdiff;
|
||||||
pos.top += (mAttributes[attribute]->getHeight() - image->getHeight()) / 2;
|
pos.top += (hbox->getHeight() - image->getHeight()) / 2;
|
||||||
image->setPosition(pos);
|
image->setPosition(pos);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -130,8 +160,8 @@ namespace MWGui
|
||||||
{
|
{
|
||||||
MWBase::World* world = MWBase::Environment::get().getWorld();
|
MWBase::World* world = MWBase::Environment::get().getWorld();
|
||||||
MWWorld::Ptr player = world->getPlayerPtr();
|
MWWorld::Ptr player = world->getPlayerPtr();
|
||||||
MWMechanics::CreatureStats& creatureStats = player.getClass().getCreatureStats(player);
|
const MWMechanics::CreatureStats& creatureStats = player.getClass().getCreatureStats(player);
|
||||||
MWMechanics::NpcStats& pcStats = player.getClass().getNpcStats(player);
|
const MWMechanics::NpcStats& pcStats = player.getClass().getNpcStats(player);
|
||||||
|
|
||||||
setClassImage(mClassImage,
|
setClassImage(mClassImage,
|
||||||
ESM::RefId::stringRefId(getLevelupClassImage(pcStats.getSkillIncreasesForSpecialization(0),
|
ESM::RefId::stringRefId(getLevelupClassImage(pcStats.getSkillIncreasesForSpecialization(0),
|
||||||
|
@ -149,28 +179,28 @@ namespace MWGui
|
||||||
mLevelDescription->setCaption(toUString(levelupdescription));
|
mLevelDescription->setCaption(toUString(levelupdescription));
|
||||||
|
|
||||||
unsigned int availableAttributes = 0;
|
unsigned int availableAttributes = 0;
|
||||||
for (int i = 0; i < 8; ++i)
|
for (const ESM::Attribute& attribute : MWBase::Environment::get().getESMStore()->get<ESM::Attribute>())
|
||||||
{
|
{
|
||||||
MyGUI::TextBox* text = mAttributeMultipliers[i];
|
const auto& widgets = mAttributeWidgets[attribute.mId];
|
||||||
if (pcStats.getAttribute(i).getBase() < 100)
|
if (pcStats.getAttribute(attribute.mId).getBase() < 100)
|
||||||
{
|
{
|
||||||
mAttributes[i]->setEnabled(true);
|
widgets.mButton->setEnabled(true);
|
||||||
mAttributeValues[i]->setEnabled(true);
|
widgets.mValue->setEnabled(true);
|
||||||
availableAttributes++;
|
availableAttributes++;
|
||||||
|
|
||||||
float mult = pcStats.getLevelupAttributeMultiplier(i);
|
float mult = pcStats.getLevelupAttributeMultiplier(attribute.mId);
|
||||||
mult = std::min(mult, 100 - pcStats.getAttribute(i).getBase());
|
mult = std::min(mult, 100 - pcStats.getAttribute(attribute.mId).getBase());
|
||||||
if (mult <= 1)
|
if (mult <= 1)
|
||||||
text->setCaption({});
|
widgets.mMultiplier->setCaption({});
|
||||||
else
|
else
|
||||||
text->setCaption("x" + MyGUI::utility::toString(mult));
|
widgets.mMultiplier->setCaption("x" + MyGUI::utility::toString(mult));
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
mAttributes[i]->setEnabled(false);
|
widgets.mButton->setEnabled(false);
|
||||||
mAttributeValues[i]->setEnabled(false);
|
widgets.mValue->setEnabled(false);
|
||||||
|
|
||||||
text->setCaption({});
|
widgets.mMultiplier->setCaption({});
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -215,9 +245,9 @@ namespace MWGui
|
||||||
|
|
||||||
void LevelupDialog::onAttributeClicked(MyGUI::Widget* sender)
|
void LevelupDialog::onAttributeClicked(MyGUI::Widget* sender)
|
||||||
{
|
{
|
||||||
int attribute = *sender->getUserData<int>();
|
auto attribute = *sender->getUserData<ESM::Attribute::AttributeID>();
|
||||||
|
|
||||||
std::vector<int>::iterator found = std::find(mSpentAttributes.begin(), mSpentAttributes.end(), attribute);
|
auto found = std::find(mSpentAttributes.begin(), mSpentAttributes.end(), attribute);
|
||||||
if (found != mSpentAttributes.end())
|
if (found != mSpentAttributes.end())
|
||||||
mSpentAttributes.erase(found);
|
mSpentAttributes.erase(found);
|
||||||
else
|
else
|
||||||
|
|
|
@ -1,6 +1,8 @@
|
||||||
#ifndef MWGUI_LEVELUPDIALOG_H
|
#ifndef MWGUI_LEVELUPDIALOG_H
|
||||||
#define MWGUI_LEVELUPDIALOG_H
|
#define MWGUI_LEVELUPDIALOG_H
|
||||||
|
|
||||||
|
#include <components/esm/attr.hpp>
|
||||||
|
|
||||||
#include "windowbase.hpp"
|
#include "windowbase.hpp"
|
||||||
|
|
||||||
namespace MWGui
|
namespace MWGui
|
||||||
|
@ -14,23 +16,26 @@ namespace MWGui
|
||||||
void onOpen() override;
|
void onOpen() override;
|
||||||
|
|
||||||
private:
|
private:
|
||||||
|
struct Widgets
|
||||||
|
{
|
||||||
|
MyGUI::Button* mButton;
|
||||||
|
MyGUI::TextBox* mValue;
|
||||||
|
MyGUI::TextBox* mMultiplier;
|
||||||
|
};
|
||||||
MyGUI::Button* mOkButton;
|
MyGUI::Button* mOkButton;
|
||||||
MyGUI::ImageBox* mClassImage;
|
MyGUI::ImageBox* mClassImage;
|
||||||
MyGUI::TextBox* mLevelText;
|
MyGUI::TextBox* mLevelText;
|
||||||
MyGUI::EditBox* mLevelDescription;
|
MyGUI::EditBox* mLevelDescription;
|
||||||
|
|
||||||
MyGUI::Widget* mCoinBox;
|
MyGUI::Widget* mCoinBox;
|
||||||
MyGUI::Widget* mAssignWidget;
|
MyGUI::ScrollView* mAssignWidget;
|
||||||
|
|
||||||
std::vector<MyGUI::Button*> mAttributes;
|
std::map<ESM::Attribute::AttributeID, Widgets> mAttributeWidgets;
|
||||||
std::vector<MyGUI::TextBox*> mAttributeValues;
|
|
||||||
std::vector<MyGUI::TextBox*> mAttributeMultipliers;
|
|
||||||
std::vector<MyGUI::ImageBox*> mCoins;
|
std::vector<MyGUI::ImageBox*> mCoins;
|
||||||
|
|
||||||
std::vector<int> mSpentAttributes;
|
std::vector<ESM::Attribute::AttributeID> mSpentAttributes;
|
||||||
|
|
||||||
unsigned int mCoinCount;
|
unsigned int mCoinCount;
|
||||||
static const unsigned int sMaxCoins;
|
|
||||||
|
|
||||||
void onOkButtonClicked(MyGUI::Widget* sender);
|
void onOkButtonClicked(MyGUI::Widget* sender);
|
||||||
void onAttributeClicked(MyGUI::Widget* sender);
|
void onAttributeClicked(MyGUI::Widget* sender);
|
||||||
|
|
|
@ -76,14 +76,22 @@ namespace MWGui
|
||||||
|
|
||||||
// Setup attributes
|
// Setup attributes
|
||||||
|
|
||||||
Widgets::MWAttributePtr widget;
|
MyGUI::Widget* attributes = getWidget("Attributes");
|
||||||
const auto& store = MWBase::Environment::get().getWorld()->getStore().get<ESM::Attribute>();
|
const auto& store = MWBase::Environment::get().getWorld()->getStore().get<ESM::Attribute>();
|
||||||
|
MyGUI::IntCoord coord{ 8, 4, 250, 18 };
|
||||||
for (const ESM::Attribute& attribute : store)
|
for (const ESM::Attribute& attribute : store)
|
||||||
{
|
{
|
||||||
getWidget(widget, std::string("Attribute").append(1, '0' + attribute.mId));
|
auto* widget
|
||||||
|
= attributes->createWidget<Widgets::MWAttribute>("MW_StatNameValue", coord, MyGUI::Align::Default);
|
||||||
mAttributeWidgets.emplace(attribute.mId, widget);
|
mAttributeWidgets.emplace(attribute.mId, widget);
|
||||||
|
widget->setUserString("ToolTipType", "Layout");
|
||||||
|
widget->setUserString("ToolTipLayout", "AttributeToolTip");
|
||||||
|
widget->setUserString("Caption_AttributeName", attribute.mName);
|
||||||
|
widget->setUserString("Caption_AttributeDescription", attribute.mDescription);
|
||||||
|
widget->setUserString("ImageTexture_AttributeImage", attribute.mIcon);
|
||||||
widget->setAttributeId(attribute.mId);
|
widget->setAttributeId(attribute.mId);
|
||||||
widget->setAttributeValue(Widgets::MWAttribute::AttributeValue());
|
widget->setAttributeValue(Widgets::MWAttribute::AttributeValue());
|
||||||
|
coord.top += coord.height;
|
||||||
}
|
}
|
||||||
|
|
||||||
// Setup skills
|
// Setup skills
|
||||||
|
@ -193,7 +201,7 @@ namespace MWGui
|
||||||
|
|
||||||
void ReviewDialog::setAttribute(ESM::Attribute::AttributeID attributeId, const MWMechanics::AttributeValue& value)
|
void ReviewDialog::setAttribute(ESM::Attribute::AttributeID attributeId, const MWMechanics::AttributeValue& value)
|
||||||
{
|
{
|
||||||
std::map<int, Widgets::MWAttributePtr>::iterator attr = mAttributeWidgets.find(static_cast<int>(attributeId));
|
auto attr = mAttributeWidgets.find(attributeId);
|
||||||
if (attr == mAttributeWidgets.end())
|
if (attr == mAttributeWidgets.end())
|
||||||
return;
|
return;
|
||||||
|
|
||||||
|
@ -394,9 +402,9 @@ 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);
|
||||||
|
|
||||||
int attributes[ESM::Attribute::Length];
|
std::map<ESM::Attribute::AttributeID, MWMechanics::AttributeValue> attributes;
|
||||||
for (int i = 0; i < ESM::Attribute::Length; ++i)
|
for (const auto& [key, value] : mAttributeWidgets)
|
||||||
attributes[i] = mAttributeWidgets[i]->getAttributeValue().getBase();
|
attributes[key] = value->getAttributeValue();
|
||||||
|
|
||||||
std::vector<ESM::RefId> selectedSpells = MWMechanics::autoCalcPlayerSpells(mSkillValues, attributes, race);
|
std::vector<ESM::RefId> selectedSpells = MWMechanics::autoCalcPlayerSpells(mSkillValues, attributes, race);
|
||||||
for (ESM::RefId& spellId : selectedSpells)
|
for (ESM::RefId& spellId : selectedSpells)
|
||||||
|
|
|
@ -90,7 +90,7 @@ namespace MWGui
|
||||||
|
|
||||||
Widgets::MWDynamicStatPtr mHealth, mMagicka, mFatigue;
|
Widgets::MWDynamicStatPtr mHealth, mMagicka, mFatigue;
|
||||||
|
|
||||||
std::map<int, Widgets::MWAttributePtr> mAttributeWidgets;
|
std::map<ESM::Attribute::AttributeID, 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;
|
||||||
|
|
|
@ -35,14 +35,16 @@ namespace MWGui
|
||||||
if (mWatched.isEmpty())
|
if (mWatched.isEmpty())
|
||||||
return;
|
return;
|
||||||
|
|
||||||
|
const auto& store = MWBase::Environment::get().getESMStore();
|
||||||
MWBase::WindowManager* winMgr = MWBase::Environment::get().getWindowManager();
|
MWBase::WindowManager* winMgr = MWBase::Environment::get().getWindowManager();
|
||||||
const MWMechanics::NpcStats& stats = mWatched.getClass().getNpcStats(mWatched);
|
const MWMechanics::NpcStats& stats = mWatched.getClass().getNpcStats(mWatched);
|
||||||
for (int i = 0; i < ESM::Attribute::Length; ++i)
|
for (const ESM::Attribute& attribute : store->get<ESM::Attribute>())
|
||||||
{
|
{
|
||||||
if (stats.getAttribute(i) != mWatchedAttributes[i] || mWatchedStatsEmpty)
|
const auto& value = stats.getAttribute(attribute.mId);
|
||||||
|
if (value != mWatchedAttributes[attribute.mId] || mWatchedStatsEmpty)
|
||||||
{
|
{
|
||||||
mWatchedAttributes[i] = stats.getAttribute(i);
|
mWatchedAttributes[attribute.mId] = value;
|
||||||
setValue("AttribVal" + std::to_string(i + 1), stats.getAttribute(i));
|
setValue(attribute.mId, value);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -83,7 +85,7 @@ namespace MWGui
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
for (const ESM::Skill& skill : MWBase::Environment::get().getESMStore()->get<ESM::Skill>())
|
for (const ESM::Skill& skill : store->get<ESM::Skill>())
|
||||||
{
|
{
|
||||||
const auto& value = stats.getSkill(skill.mId);
|
const auto& value = stats.getSkill(skill.mId);
|
||||||
if (value != mWatchedSkills[skill.mId] || mWatchedStatsEmpty)
|
if (value != mWatchedSkills[skill.mId] || mWatchedStatsEmpty)
|
||||||
|
@ -112,16 +114,14 @@ namespace MWGui
|
||||||
if (watchedRecord->mRace != mWatchedRace || mWatchedStatsEmpty)
|
if (watchedRecord->mRace != mWatchedRace || mWatchedStatsEmpty)
|
||||||
{
|
{
|
||||||
mWatchedRace = watchedRecord->mRace;
|
mWatchedRace = watchedRecord->mRace;
|
||||||
const ESM::Race* race
|
const ESM::Race* race = store->get<ESM::Race>().find(watchedRecord->mRace);
|
||||||
= MWBase::Environment::get().getESMStore()->get<ESM::Race>().find(watchedRecord->mRace);
|
|
||||||
setValue("race", race->mName);
|
setValue("race", race->mName);
|
||||||
}
|
}
|
||||||
|
|
||||||
if (watchedRecord->mClass != mWatchedClass || mWatchedStatsEmpty)
|
if (watchedRecord->mClass != mWatchedClass || mWatchedStatsEmpty)
|
||||||
{
|
{
|
||||||
mWatchedClass = watchedRecord->mClass;
|
mWatchedClass = watchedRecord->mClass;
|
||||||
const ESM::Class* cls
|
const ESM::Class* cls = store->get<ESM::Class>().find(watchedRecord->mClass);
|
||||||
= MWBase::Environment::get().getESMStore()->get<ESM::Class>().find(watchedRecord->mClass);
|
|
||||||
setValue("class", cls->mName);
|
setValue("class", cls->mName);
|
||||||
|
|
||||||
size_t size = cls->mData.mSkills.size();
|
size_t size = cls->mData.mSkills.size();
|
||||||
|
@ -151,7 +151,7 @@ namespace MWGui
|
||||||
mListeners.erase(listener);
|
mListeners.erase(listener);
|
||||||
}
|
}
|
||||||
|
|
||||||
void StatsWatcher::setValue(std::string_view id, const MWMechanics::AttributeValue& value)
|
void StatsWatcher::setValue(ESM::Attribute::AttributeID id, const MWMechanics::AttributeValue& value)
|
||||||
{
|
{
|
||||||
for (StatsListener* listener : mListeners)
|
for (StatsListener* listener : mListeners)
|
||||||
listener->setValue(id, value);
|
listener->setValue(id, 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(std::string_view id, const MWMechanics::AttributeValue& value) {}
|
virtual void setValue(ESM::Attribute::AttributeID 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;
|
||||||
|
|
||||||
MWMechanics::AttributeValue mWatchedAttributes[ESM::Attribute::Length];
|
std::map<ESM::Attribute::AttributeID, 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(std::string_view id, const MWMechanics::AttributeValue& value);
|
void setValue(ESM::Attribute::AttributeID 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);
|
||||||
|
|
|
@ -1,5 +1,6 @@
|
||||||
#include "statswindow.hpp"
|
#include "statswindow.hpp"
|
||||||
|
|
||||||
|
#include <MyGUI_Button.h>
|
||||||
#include <MyGUI_Gui.h>
|
#include <MyGUI_Gui.h>
|
||||||
#include <MyGUI_ImageBox.h>
|
#include <MyGUI_ImageBox.h>
|
||||||
#include <MyGUI_InputManager.h>
|
#include <MyGUI_InputManager.h>
|
||||||
|
@ -43,15 +44,26 @@ namespace MWGui
|
||||||
, mMinFullWidth(mMainWidget->getSize().width)
|
, mMinFullWidth(mMainWidget->getSize().width)
|
||||||
{
|
{
|
||||||
|
|
||||||
const char* names[][2] = { { "Attrib1", "sAttributeStrength" }, { "Attrib2", "sAttributeIntelligence" },
|
|
||||||
{ "Attrib3", "sAttributeWillpower" }, { "Attrib4", "sAttributeAgility" }, { "Attrib5", "sAttributeSpeed" },
|
|
||||||
{ "Attrib6", "sAttributeEndurance" }, { "Attrib7", "sAttributePersonality" },
|
|
||||||
{ "Attrib8", "sAttributeLuck" }, { 0, 0 } };
|
|
||||||
|
|
||||||
const MWWorld::ESMStore& store = *MWBase::Environment::get().getESMStore();
|
const MWWorld::ESMStore& store = *MWBase::Environment::get().getESMStore();
|
||||||
for (int i = 0; names[i][0]; ++i)
|
MyGUI::Widget* attributeView = getWidget("AttributeView");
|
||||||
|
MyGUI::IntCoord coord{ 0, 0, 204, 18 };
|
||||||
|
const MyGUI::Align alignment = MyGUI::Align::Left | MyGUI::Align::Top | MyGUI::Align::HStretch;
|
||||||
|
for (const ESM::Attribute& attribute : store.get<ESM::Attribute>())
|
||||||
{
|
{
|
||||||
setText(names[i][0], store.get<ESM::GameSetting>().find(names[i][1])->mValue.getString());
|
auto* box = attributeView->createWidget<MyGUI::Button>({}, coord, alignment);
|
||||||
|
box->setUserString("ToolTipType", "Layout");
|
||||||
|
box->setUserString("ToolTipLayout", "AttributeToolTip");
|
||||||
|
box->setUserString("Caption_AttributeName", attribute.mName);
|
||||||
|
box->setUserString("Caption_AttributeDescription", attribute.mDescription);
|
||||||
|
box->setUserString("ImageTexture_AttributeImage", attribute.mIcon);
|
||||||
|
coord.top += coord.height;
|
||||||
|
auto* name = box->createWidget<MyGUI::TextBox>("SandText", { 0, 0, 160, 18 }, alignment);
|
||||||
|
name->setNeedMouseFocus(false);
|
||||||
|
name->setCaption(attribute.mName);
|
||||||
|
auto* value = box->createWidget<MyGUI::TextBox>(
|
||||||
|
"SandTextRight", { 160, 0, 44, 18 }, MyGUI::Align::Right | MyGUI::Align::Top);
|
||||||
|
value->setNeedMouseFocus(false);
|
||||||
|
mAttributeWidgets.emplace(attribute.mId, value);
|
||||||
}
|
}
|
||||||
|
|
||||||
getWidget(mSkillView, "SkillView");
|
getWidget(mSkillView, "SkillView");
|
||||||
|
@ -143,37 +155,20 @@ namespace MWGui
|
||||||
mMainWidget->castType<MyGUI::Window>()->setCaption(playerName);
|
mMainWidget->castType<MyGUI::Window>()->setCaption(playerName);
|
||||||
}
|
}
|
||||||
|
|
||||||
void StatsWindow::setValue(std::string_view id, const MWMechanics::AttributeValue& value)
|
void StatsWindow::setValue(ESM::Attribute::AttributeID id, const MWMechanics::AttributeValue& value)
|
||||||
{
|
{
|
||||||
static const char* ids[] = {
|
auto it = mAttributeWidgets.find(id);
|
||||||
"AttribVal1",
|
if (it != mAttributeWidgets.end())
|
||||||
"AttribVal2",
|
{
|
||||||
"AttribVal3",
|
MyGUI::TextBox* box = it->second;
|
||||||
"AttribVal4",
|
box->setCaption(std::to_string(static_cast<int>(value.getModified())));
|
||||||
"AttribVal5",
|
if (value.getModified() > value.getBase())
|
||||||
"AttribVal6",
|
box->_setWidgetState("increased");
|
||||||
"AttribVal7",
|
else if (value.getModified() < value.getBase())
|
||||||
"AttribVal8",
|
box->_setWidgetState("decreased");
|
||||||
nullptr,
|
else
|
||||||
};
|
box->_setWidgetState("normal");
|
||||||
|
}
|
||||||
for (int i = 0; ids[i]; ++i)
|
|
||||||
if (ids[i] == id)
|
|
||||||
{
|
|
||||||
setText(id, std::to_string(static_cast<int>(value.getModified())));
|
|
||||||
|
|
||||||
MyGUI::TextBox* box;
|
|
||||||
getWidget(box, id);
|
|
||||||
|
|
||||||
if (value.getModified() > value.getBase())
|
|
||||||
box->_setWidgetState("increased");
|
|
||||||
else if (value.getModified() < value.getBase())
|
|
||||||
box->_setWidgetState("decreased");
|
|
||||||
else
|
|
||||||
box->_setWidgetState("normal");
|
|
||||||
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
void StatsWindow::setValue(std::string_view id, const MWMechanics::DynamicStat<float>& value)
|
void StatsWindow::setValue(std::string_view id, const MWMechanics::DynamicStat<float>& value)
|
||||||
|
|
|
@ -3,6 +3,7 @@
|
||||||
|
|
||||||
#include "statswatcher.hpp"
|
#include "statswatcher.hpp"
|
||||||
#include "windowpinnablebase.hpp"
|
#include "windowpinnablebase.hpp"
|
||||||
|
#include <components/esm/attr.hpp>
|
||||||
#include <components/esm/refid.hpp>
|
#include <components/esm/refid.hpp>
|
||||||
|
|
||||||
namespace MWGui
|
namespace MWGui
|
||||||
|
@ -21,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(std::string_view id, const MWMechanics::AttributeValue& value) override;
|
void setValue(ESM::Attribute::AttributeID 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;
|
||||||
|
@ -67,6 +68,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, 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
|
||||||
|
|
|
@ -823,7 +823,7 @@ namespace MWGui
|
||||||
widget->setUserString("ImageTexture_SkillNoProgressImage", skill->mIcon);
|
widget->setUserString("ImageTexture_SkillNoProgressImage", skill->mIcon);
|
||||||
}
|
}
|
||||||
|
|
||||||
void ToolTips::createAttributeToolTip(MyGUI::Widget* widget, int attributeId)
|
void ToolTips::createAttributeToolTip(MyGUI::Widget* widget, ESM::Attribute::AttributeID 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);
|
||||||
|
|
|
@ -94,7 +94,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, int attributeId);
|
static void createAttributeToolTip(MyGUI::Widget* widget, ESM::Attribute::AttributeID 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);
|
||||||
|
|
|
@ -150,7 +150,8 @@ 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() >= pcStats.getAttribute(skill->mData.mAttribute).getBase())
|
if (pcStats.getSkill(skill->mId).getBase()
|
||||||
|
>= pcStats.getAttribute(ESM::Attribute::AttributeID(skill->mData.mAttribute)).getBase())
|
||||||
{
|
{
|
||||||
MWBase::Environment::get().getWindowManager()->messageBox("#{sNotifyMessage17}");
|
MWBase::Environment::get().getWindowManager()->messageBox("#{sNotifyMessage17}");
|
||||||
return;
|
return;
|
||||||
|
|
|
@ -102,13 +102,13 @@ namespace MWGui::Widgets
|
||||||
/* MWAttribute */
|
/* MWAttribute */
|
||||||
|
|
||||||
MWAttribute::MWAttribute()
|
MWAttribute::MWAttribute()
|
||||||
: mId(-1)
|
: mId(ESM::Attribute::Length)
|
||||||
, mAttributeNameWidget(nullptr)
|
, mAttributeNameWidget(nullptr)
|
||||||
, mAttributeValueWidget(nullptr)
|
, mAttributeValueWidget(nullptr)
|
||||||
{
|
{
|
||||||
}
|
}
|
||||||
|
|
||||||
void MWAttribute::setAttributeId(int attributeId)
|
void MWAttribute::setAttributeId(ESM::Attribute::AttributeID attributeId)
|
||||||
{
|
{
|
||||||
mId = attributeId;
|
mId = attributeId;
|
||||||
updateWidgets();
|
updateWidgets();
|
||||||
|
@ -129,17 +129,15 @@ namespace MWGui::Widgets
|
||||||
{
|
{
|
||||||
if (mAttributeNameWidget)
|
if (mAttributeNameWidget)
|
||||||
{
|
{
|
||||||
if (mId < 0 || mId >= 8)
|
const ESM::Attribute* attribute
|
||||||
|
= MWBase::Environment::get().getESMStore()->get<ESM::Attribute>().search(mId);
|
||||||
|
if (!attribute)
|
||||||
{
|
{
|
||||||
mAttributeNameWidget->setCaption({});
|
mAttributeNameWidget->setCaption({});
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
static const std::string_view attributes[8]
|
MyGUI::UString name = toUString(attribute->mName);
|
||||||
= { "sAttributeStrength", "sAttributeIntelligence", "sAttributeWillpower", "sAttributeAgility",
|
|
||||||
"sAttributeSpeed", "sAttributeEndurance", "sAttributePersonality", "sAttributeLuck" };
|
|
||||||
MyGUI::UString name = toUString(
|
|
||||||
MWBase::Environment::get().getWindowManager()->getGameSettingString(attributes[mId], {}));
|
|
||||||
mAttributeNameWidget->setCaption(name);
|
mAttributeNameWidget->setCaption(name);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -156,8 +154,6 @@ namespace MWGui::Widgets
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
MWAttribute::~MWAttribute() {}
|
|
||||||
|
|
||||||
void MWAttribute::initialiseOverride()
|
void MWAttribute::initialiseOverride()
|
||||||
{
|
{
|
||||||
Base::initialiseOverride();
|
Base::initialiseOverride();
|
||||||
|
|
|
@ -7,6 +7,7 @@
|
||||||
#include <MyGUI_TextBox.h>
|
#include <MyGUI_TextBox.h>
|
||||||
#include <MyGUI_Widget.h>
|
#include <MyGUI_Widget.h>
|
||||||
|
|
||||||
|
#include <components/esm/attr.hpp>
|
||||||
#include <components/esm/refid.hpp>
|
#include <components/esm/refid.hpp>
|
||||||
#include <components/esm3/effectlist.hpp>
|
#include <components/esm3/effectlist.hpp>
|
||||||
#include <components/esm3/loadskil.hpp>
|
#include <components/esm3/loadskil.hpp>
|
||||||
|
@ -32,8 +33,6 @@ namespace MWGui
|
||||||
{
|
{
|
||||||
class MWEffectList;
|
class MWEffectList;
|
||||||
|
|
||||||
void fixTexturePath(std::string& path);
|
|
||||||
|
|
||||||
struct SpellEffectParams
|
struct SpellEffectParams
|
||||||
{
|
{
|
||||||
SpellEffectParams()
|
SpellEffectParams()
|
||||||
|
@ -139,10 +138,10 @@ namespace MWGui
|
||||||
|
|
||||||
typedef MWMechanics::AttributeValue AttributeValue;
|
typedef MWMechanics::AttributeValue AttributeValue;
|
||||||
|
|
||||||
void setAttributeId(int attributeId);
|
void setAttributeId(ESM::Attribute::AttributeID attributeId);
|
||||||
void setAttributeValue(const AttributeValue& value);
|
void setAttributeValue(const AttributeValue& value);
|
||||||
|
|
||||||
int getAttributeId() const { return mId; }
|
ESM::Attribute::AttributeID getAttributeId() const { return mId; }
|
||||||
const AttributeValue& getAttributeValue() const { return mValue; }
|
const AttributeValue& getAttributeValue() const { return mValue; }
|
||||||
|
|
||||||
// Events
|
// Events
|
||||||
|
@ -154,7 +153,7 @@ namespace MWGui
|
||||||
EventHandle_AttributeVoid eventClicked;
|
EventHandle_AttributeVoid eventClicked;
|
||||||
|
|
||||||
protected:
|
protected:
|
||||||
virtual ~MWAttribute();
|
~MWAttribute() override = default;
|
||||||
|
|
||||||
void initialiseOverride() override;
|
void initialiseOverride() override;
|
||||||
|
|
||||||
|
@ -163,7 +162,7 @@ namespace MWGui
|
||||||
private:
|
private:
|
||||||
void updateWidgets();
|
void updateWidgets();
|
||||||
|
|
||||||
int mId;
|
ESM::Attribute::AttributeID mId;
|
||||||
AttributeValue mValue;
|
AttributeValue mValue;
|
||||||
MyGUI::TextBox* mAttributeNameWidget;
|
MyGUI::TextBox* mAttributeNameWidget;
|
||||||
MyGUI::TextBox* mAttributeValueWidget;
|
MyGUI::TextBox* mAttributeValueWidget;
|
||||||
|
|
|
@ -182,9 +182,10 @@ 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, [this, getter](const MWWorld::Ptr& ptr) {
|
context, mObject, &AttributeStat::setValue, mIndex, prop, [id, getter](const MWWorld::Ptr& ptr) {
|
||||||
return (ptr.getClass().getCreatureStats(ptr).getAttribute(mIndex).*getter)();
|
return (ptr.getClass().getCreatureStats(ptr).getAttribute(id).*getter)();
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -213,9 +214,9 @@ namespace MWLua
|
||||||
|
|
||||||
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)
|
||||||
{
|
{
|
||||||
int index = std::get<int>(i);
|
auto id = static_cast<ESM::Attribute::AttributeID>(std::get<int>(i));
|
||||||
auto& stats = ptr.getClass().getCreatureStats(ptr);
|
auto& stats = ptr.getClass().getCreatureStats(ptr);
|
||||||
auto stat = stats.getAttribute(index);
|
auto stat = stats.getAttribute(id);
|
||||||
float floatValue = LuaUtil::cast<float>(value);
|
float floatValue = LuaUtil::cast<float>(value);
|
||||||
if (prop == "base")
|
if (prop == "base")
|
||||||
stat.setBase(floatValue);
|
stat.setBase(floatValue);
|
||||||
|
@ -226,7 +227,7 @@ namespace MWLua
|
||||||
}
|
}
|
||||||
else if (prop == "modifier")
|
else if (prop == "modifier")
|
||||||
stat.setModifier(floatValue);
|
stat.setModifier(floatValue);
|
||||||
stats.setAttribute(index, stat);
|
stats.setAttribute(id, stat);
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|
|
@ -27,13 +27,13 @@ namespace MWMechanics
|
||||||
ESM::RefId mWeakestSpell;
|
ESM::RefId mWeakestSpell;
|
||||||
};
|
};
|
||||||
|
|
||||||
std::vector<ESM::RefId> autoCalcNpcSpells(
|
std::vector<ESM::RefId> autoCalcNpcSpells(const std::map<ESM::RefId, SkillValue>& actorSkills,
|
||||||
const std::map<ESM::RefId, SkillValue>& actorSkills, const int* actorAttributes, const ESM::Race* race)
|
const std::map<ESM::Attribute::AttributeID, 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>();
|
||||||
static const float fNPCbaseMagickaMult = gmst.find("fNPCbaseMagickaMult")->mValue.getFloat();
|
static const float fNPCbaseMagickaMult = gmst.find("fNPCbaseMagickaMult")->mValue.getFloat();
|
||||||
float baseMagicka = fNPCbaseMagickaMult * actorAttributes[ESM::Attribute::Intelligence];
|
float baseMagicka = fNPCbaseMagickaMult * actorAttributes.at(ESM::Attribute::Intelligence).getBase();
|
||||||
|
|
||||||
static const std::string schools[]
|
static const std::string schools[]
|
||||||
= { "alteration", "conjuration", "destruction", "illusion", "mysticism", "restoration" };
|
= { "alteration", "conjuration", "destruction", "illusion", "mysticism", "restoration" };
|
||||||
|
@ -148,15 +148,15 @@ namespace MWMechanics
|
||||||
return selectedSpells;
|
return selectedSpells;
|
||||||
}
|
}
|
||||||
|
|
||||||
std::vector<ESM::RefId> autoCalcPlayerSpells(
|
std::vector<ESM::RefId> autoCalcPlayerSpells(const std::map<ESM::RefId, SkillValue>& actorSkills,
|
||||||
const std::map<ESM::RefId, SkillValue>& actorSkills, const int* actorAttributes, const ESM::Race* race)
|
const std::map<ESM::Attribute::AttributeID, AttributeValue>& actorAttributes, const ESM::Race* race)
|
||||||
{
|
{
|
||||||
const MWWorld::ESMStore& esmStore = *MWBase::Environment::get().getESMStore();
|
const MWWorld::ESMStore& esmStore = *MWBase::Environment::get().getESMStore();
|
||||||
|
|
||||||
static const float fPCbaseMagickaMult
|
static const float fPCbaseMagickaMult
|
||||||
= esmStore.get<ESM::GameSetting>().find("fPCbaseMagickaMult")->mValue.getFloat();
|
= esmStore.get<ESM::GameSetting>().find("fPCbaseMagickaMult")->mValue.getFloat();
|
||||||
|
|
||||||
float baseMagicka = fPCbaseMagickaMult * actorAttributes[ESM::Attribute::Intelligence];
|
float baseMagicka = fPCbaseMagickaMult * actorAttributes.at(ESM::Attribute::Intelligence).getBase();
|
||||||
bool reachedLimit = false;
|
bool reachedLimit = false;
|
||||||
const ESM::Spell* weakestSpell = nullptr;
|
const ESM::Spell* weakestSpell = nullptr;
|
||||||
int minCost = std::numeric_limits<int>::max();
|
int minCost = std::numeric_limits<int>::max();
|
||||||
|
@ -227,8 +227,8 @@ namespace MWMechanics
|
||||||
return selectedSpells;
|
return selectedSpells;
|
||||||
}
|
}
|
||||||
|
|
||||||
bool attrSkillCheck(
|
bool attrSkillCheck(const ESM::Spell* spell, const std::map<ESM::RefId, SkillValue>& actorSkills,
|
||||||
const ESM::Spell* spell, const std::map<ESM::RefId, SkillValue>& actorSkills, const int* actorAttributes)
|
const std::map<ESM::Attribute::AttributeID, AttributeValue>& actorAttributes)
|
||||||
{
|
{
|
||||||
for (const auto& spellEffect : spell->mEffects.mList)
|
for (const auto& spellEffect : spell->mEffects.mList)
|
||||||
{
|
{
|
||||||
|
@ -250,8 +250,8 @@ namespace MWMechanics
|
||||||
|
|
||||||
if ((magicEffect->mData.mFlags & ESM::MagicEffect::TargetAttribute))
|
if ((magicEffect->mData.mFlags & ESM::MagicEffect::TargetAttribute))
|
||||||
{
|
{
|
||||||
assert(spellEffect.mAttribute >= 0 && spellEffect.mAttribute < ESM::Attribute::Length);
|
auto found = actorAttributes.find(ESM::Attribute::AttributeID(spellEffect.mAttribute));
|
||||||
if (actorAttributes[spellEffect.mAttribute] < iAutoSpellAttSkillMin)
|
if (found == actorAttributes.end() || found->second.getBase() < iAutoSpellAttSkillMin)
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -313,7 +313,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 int* actorAttributes, int effectiveSchool)
|
const std::map<ESM::Attribute::AttributeID, AttributeValue>& actorAttributes, int effectiveSchool)
|
||||||
{
|
{
|
||||||
if (spell->mData.mType != ESM::Spell::ST_Spell)
|
if (spell->mData.mType != ESM::Spell::ST_Spell)
|
||||||
return 100.f;
|
return 100.f;
|
||||||
|
@ -334,7 +334,8 @@ namespace MWMechanics
|
||||||
spell, actorSkills, effectiveSchool, skillTerm); // Note effectiveSchool is unused after this
|
spell, actorSkills, effectiveSchool, skillTerm); // Note effectiveSchool is unused after this
|
||||||
|
|
||||||
float castChance = skillTerm - MWMechanics::calcSpellCost(*spell)
|
float castChance = skillTerm - MWMechanics::calcSpellCost(*spell)
|
||||||
+ 0.2f * actorAttributes[ESM::Attribute::Willpower] + 0.1f * actorAttributes[ESM::Attribute::Luck];
|
+ 0.2f * actorAttributes.at(ESM::Attribute::Willpower).getBase()
|
||||||
|
+ 0.1f * actorAttributes.at(ESM::Attribute::Luck).getBase();
|
||||||
return castChance;
|
return castChance;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -19,22 +19,22 @@ namespace MWMechanics
|
||||||
/// Contains algorithm for calculating an NPC's spells based on stats
|
/// Contains algorithm for calculating an NPC's spells based on stats
|
||||||
/// @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(
|
std::vector<ESM::RefId> autoCalcNpcSpells(const std::map<ESM::RefId, SkillValue>& actorSkills,
|
||||||
const std::map<ESM::RefId, SkillValue>& actorSkills, const int* actorAttributes, const ESM::Race* race);
|
const std::map<ESM::Attribute::AttributeID, AttributeValue>& actorAttributes, const ESM::Race* race);
|
||||||
|
|
||||||
std::vector<ESM::RefId> autoCalcPlayerSpells(
|
std::vector<ESM::RefId> autoCalcPlayerSpells(const std::map<ESM::RefId, SkillValue>& actorSkills,
|
||||||
const std::map<ESM::RefId, SkillValue>& actorSkills, const int* actorAttributes, const ESM::Race* race);
|
const std::map<ESM::Attribute::AttributeID, AttributeValue>& actorAttributes, const ESM::Race* race);
|
||||||
|
|
||||||
// Helpers
|
// Helpers
|
||||||
|
|
||||||
bool attrSkillCheck(
|
bool attrSkillCheck(const ESM::Spell* spell, const std::map<ESM::RefId, SkillValue>& actorSkills,
|
||||||
const ESM::Spell* spell, const std::map<ESM::RefId, SkillValue>& actorSkills, const int* actorAttributes);
|
const std::map<ESM::Attribute::AttributeID, 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,
|
||||||
int& effectiveSchool, float& skillTerm);
|
int& 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 int* actorAttributes, int effectiveSchool);
|
const std::map<ESM::Attribute::AttributeID, AttributeValue>& actorAttributes, int effectiveSchool);
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -46,6 +46,10 @@ namespace MWMechanics
|
||||||
, mLevel(0)
|
, mLevel(0)
|
||||||
, mAttackingOrSpell(false)
|
, mAttackingOrSpell(false)
|
||||||
{
|
{
|
||||||
|
for (const ESM::Attribute& attribute : MWBase::Environment::get().getESMStore()->get<ESM::Attribute>())
|
||||||
|
{
|
||||||
|
mAttributes.emplace(attribute.mId, AttributeValue{});
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
const AiSequence& CreatureStats::getAiSequence() const
|
const AiSequence& CreatureStats::getAiSequence() const
|
||||||
|
@ -74,13 +78,9 @@ namespace MWMechanics
|
||||||
return fFatigueBase - fFatigueMult * (1 - normalised);
|
return fFatigueBase - fFatigueMult * (1 - normalised);
|
||||||
}
|
}
|
||||||
|
|
||||||
const AttributeValue& CreatureStats::getAttribute(int index) const
|
const AttributeValue& CreatureStats::getAttribute(ESM::Attribute::AttributeID id) const
|
||||||
{
|
{
|
||||||
if (index < 0 || index > 7)
|
return mAttributes.at(id);
|
||||||
{
|
|
||||||
throw std::runtime_error("attribute index is out of range");
|
|
||||||
}
|
|
||||||
return mAttributes[index];
|
|
||||||
}
|
}
|
||||||
|
|
||||||
const DynamicStat<float>& CreatureStats::getHealth() const
|
const DynamicStat<float>& CreatureStats::getHealth() const
|
||||||
|
@ -147,30 +147,25 @@ namespace MWMechanics
|
||||||
return mMagicEffects;
|
return mMagicEffects;
|
||||||
}
|
}
|
||||||
|
|
||||||
void CreatureStats::setAttribute(int index, float base)
|
void CreatureStats::setAttribute(ESM::Attribute::AttributeID id, float base)
|
||||||
{
|
{
|
||||||
AttributeValue current = getAttribute(index);
|
AttributeValue current = getAttribute(id);
|
||||||
current.setBase(base);
|
current.setBase(base);
|
||||||
setAttribute(index, current);
|
setAttribute(id, current);
|
||||||
}
|
}
|
||||||
|
|
||||||
void CreatureStats::setAttribute(int index, const AttributeValue& value)
|
void CreatureStats::setAttribute(ESM::Attribute::AttributeID id, const AttributeValue& value)
|
||||||
{
|
{
|
||||||
if (index < 0 || index > 7)
|
const AttributeValue& currentValue = mAttributes.at(id);
|
||||||
{
|
|
||||||
throw std::runtime_error("attribute index is out of range");
|
|
||||||
}
|
|
||||||
|
|
||||||
const AttributeValue& currentValue = mAttributes[index];
|
|
||||||
|
|
||||||
if (value != currentValue)
|
if (value != currentValue)
|
||||||
{
|
{
|
||||||
mAttributes[index] = value;
|
mAttributes[id] = value;
|
||||||
|
|
||||||
if (index == ESM::Attribute::Intelligence)
|
if (id == ESM::Attribute::Intelligence)
|
||||||
recalculateMagicka();
|
recalculateMagicka();
|
||||||
else if (index == ESM::Attribute::Strength || index == ESM::Attribute::Willpower
|
else if (id == ESM::Attribute::Strength || id == ESM::Attribute::Willpower || id == ESM::Attribute::Agility
|
||||||
|| index == ESM::Attribute::Agility || index == ESM::Attribute::Endurance)
|
|| id == ESM::Attribute::Endurance)
|
||||||
{
|
{
|
||||||
float strength = getAttribute(ESM::Attribute::Strength).getModified();
|
float strength = getAttribute(ESM::Attribute::Strength).getModified();
|
||||||
float willpower = getAttribute(ESM::Attribute::Willpower).getModified();
|
float willpower = getAttribute(ESM::Attribute::Willpower).getModified();
|
||||||
|
@ -535,10 +530,10 @@ namespace MWMechanics
|
||||||
|
|
||||||
void CreatureStats::writeState(ESM::CreatureStats& state) const
|
void CreatureStats::writeState(ESM::CreatureStats& state) const
|
||||||
{
|
{
|
||||||
for (int i = 0; i < ESM::Attribute::Length; ++i)
|
for (size_t i = 0; i < state.mAttributes.size(); ++i)
|
||||||
mAttributes[i].writeState(state.mAttributes[i]);
|
getAttribute(static_cast<ESM::Attribute::AttributeID>(i)).writeState(state.mAttributes[i]);
|
||||||
|
|
||||||
for (int i = 0; i < 3; ++i)
|
for (size_t i = 0; i < state.mDynamic.size(); ++i)
|
||||||
mDynamic[i].writeState(state.mDynamic[i]);
|
mDynamic[i].writeState(state.mDynamic[i]);
|
||||||
|
|
||||||
state.mTradeTime = mLastRestock.toEsm();
|
state.mTradeTime = mLastRestock.toEsm();
|
||||||
|
@ -582,7 +577,7 @@ namespace MWMechanics
|
||||||
state.mSummonGraveyard = mSummonGraveyard;
|
state.mSummonGraveyard = mSummonGraveyard;
|
||||||
|
|
||||||
state.mHasAiSettings = true;
|
state.mHasAiSettings = true;
|
||||||
for (int i = 0; i < 4; ++i)
|
for (size_t i = 0; i < state.mAiSettings.size(); ++i)
|
||||||
mAiSettings[i].writeState(state.mAiSettings[i]);
|
mAiSettings[i].writeState(state.mAiSettings[i]);
|
||||||
|
|
||||||
state.mMissingACDT = false;
|
state.mMissingACDT = false;
|
||||||
|
@ -592,10 +587,10 @@ namespace MWMechanics
|
||||||
{
|
{
|
||||||
if (!state.mMissingACDT)
|
if (!state.mMissingACDT)
|
||||||
{
|
{
|
||||||
for (int i = 0; i < ESM::Attribute::Length; ++i)
|
for (size_t i = 0; i < state.mAttributes.size(); ++i)
|
||||||
mAttributes[i].readState(state.mAttributes[i]);
|
mAttributes[static_cast<ESM::Attribute::AttributeID>(i)].readState(state.mAttributes[i]);
|
||||||
|
|
||||||
for (int i = 0; i < 3; ++i)
|
for (size_t i = 0; i < state.mDynamic.size(); ++i)
|
||||||
mDynamic[i].readState(state.mDynamic[i]);
|
mDynamic[i].readState(state.mDynamic[i]);
|
||||||
|
|
||||||
mGoldPool = state.mGoldPool;
|
mGoldPool = state.mGoldPool;
|
||||||
|
@ -636,7 +631,7 @@ namespace MWMechanics
|
||||||
mSummonGraveyard = state.mSummonGraveyard;
|
mSummonGraveyard = state.mSummonGraveyard;
|
||||||
|
|
||||||
if (state.mHasAiSettings)
|
if (state.mHasAiSettings)
|
||||||
for (int i = 0; i < 4; ++i)
|
for (size_t i = 0; i < state.mAiSettings.size(); ++i)
|
||||||
mAiSettings[i].readState(state.mAiSettings[i]);
|
mAiSettings[i].readState(state.mAiSettings[i]);
|
||||||
if (state.mRecalcDynamicStats)
|
if (state.mRecalcDynamicStats)
|
||||||
recalculateMagicka();
|
recalculateMagicka();
|
||||||
|
|
|
@ -40,7 +40,7 @@ namespace MWMechanics
|
||||||
{
|
{
|
||||||
static int sActorId;
|
static int sActorId;
|
||||||
DrawState mDrawState;
|
DrawState mDrawState;
|
||||||
AttributeValue mAttributes[ESM::Attribute::Length];
|
std::map<ESM::Attribute::AttributeID, 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(int index) const;
|
const AttributeValue& getAttribute(ESM::Attribute::AttributeID id) const;
|
||||||
|
|
||||||
const DynamicStat<float>& getHealth() const;
|
const DynamicStat<float>& getHealth() const;
|
||||||
|
|
||||||
|
@ -139,9 +139,9 @@ namespace MWMechanics
|
||||||
|
|
||||||
MagicEffects& getMagicEffects();
|
MagicEffects& getMagicEffects();
|
||||||
|
|
||||||
void setAttribute(int index, const AttributeValue& value);
|
void setAttribute(ESM::Attribute::AttributeID id, const AttributeValue& value);
|
||||||
// Shortcut to set only the base
|
// Shortcut to set only the base
|
||||||
void setAttribute(int index, float base);
|
void setAttribute(ESM::Attribute::AttributeID id, float base);
|
||||||
|
|
||||||
void setHealth(const DynamicStat<float>& value);
|
void setHealth(const DynamicStat<float>& value);
|
||||||
|
|
||||||
|
@ -293,6 +293,8 @@ 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; }
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -148,11 +148,11 @@ namespace MWMechanics
|
||||||
|
|
||||||
bool male = (player->mFlags & ESM::NPC::Female) == 0;
|
bool male = (player->mFlags & ESM::NPC::Female) == 0;
|
||||||
|
|
||||||
for (int i = 0; i < ESM::Attribute::Length; ++i)
|
for (const ESM::Attribute& attribute : esmStore.get<ESM::Attribute>())
|
||||||
{
|
{
|
||||||
const ESM::Race::MaleFemale& attribute = race->mData.mAttributeValues[i];
|
const ESM::Race::MaleFemale& value = race->mData.mAttributeValues[attribute.mId];
|
||||||
|
|
||||||
creatureStats.setAttribute(i, male ? attribute.mMale : attribute.mFemale);
|
creatureStats.setAttribute(attribute.mId, male ? value.mMale : value.mFemale);
|
||||||
}
|
}
|
||||||
|
|
||||||
for (const ESM::Skill& skill : esmStore.get<ESM::Skill>())
|
for (const ESM::Skill& skill : esmStore.get<ESM::Skill>())
|
||||||
|
@ -195,7 +195,8 @@ namespace MWMechanics
|
||||||
{
|
{
|
||||||
if (attribute >= 0 && attribute < ESM::Attribute::Length)
|
if (attribute >= 0 && attribute < ESM::Attribute::Length)
|
||||||
{
|
{
|
||||||
creatureStats.setAttribute(attribute, creatureStats.getAttribute(attribute).getBase() + 10);
|
auto id = static_cast<ESM::Attribute::AttributeID>(attribute);
|
||||||
|
creatureStats.setAttribute(id, creatureStats.getAttribute(id).getBase() + 10);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -223,12 +224,10 @@ namespace MWMechanics
|
||||||
if (mRaceSelected)
|
if (mRaceSelected)
|
||||||
race = esmStore.get<ESM::Race>().find(player->mRace);
|
race = esmStore.get<ESM::Race>().find(player->mRace);
|
||||||
|
|
||||||
int attributes[ESM::Attribute::Length];
|
|
||||||
for (int i = 0; i < ESM::Attribute::Length; ++i)
|
|
||||||
attributes[i] = npcStats.getAttribute(i).getBase();
|
|
||||||
npcStats.updateHealth();
|
npcStats.updateHealth();
|
||||||
|
|
||||||
std::vector<ESM::RefId> selectedSpells = autoCalcPlayerSpells(npcStats.getSkills(), attributes, race);
|
std::vector<ESM::RefId> selectedSpells
|
||||||
|
= autoCalcPlayerSpells(npcStats.getSkills(), npcStats.getAttributes(), race);
|
||||||
|
|
||||||
for (const ESM::RefId& spell : selectedSpells)
|
for (const ESM::RefId& spell : selectedSpells)
|
||||||
creatureStats.getSpells().add(spell);
|
creatureStats.getSpells().add(spell);
|
||||||
|
|
|
@ -28,7 +28,6 @@ MWMechanics::NpcStats::NpcStats()
|
||||||
, mTimeToStartDrowning(-1.0) // set breath to special value, it will be replaced during actor update
|
, mTimeToStartDrowning(-1.0) // set breath to special value, it will be replaced during actor update
|
||||||
, mIsWerewolf(false)
|
, mIsWerewolf(false)
|
||||||
{
|
{
|
||||||
mSkillIncreases.resize(ESM::Attribute::Length, 0);
|
|
||||||
mSpecIncreases.resize(3, 0);
|
mSpecIncreases.resize(3, 0);
|
||||||
for (const ESM::Skill& skill : MWBase::Environment::get().getESMStore()->get<ESM::Skill>())
|
for (const ESM::Skill& skill : MWBase::Environment::get().getESMStore()->get<ESM::Skill>())
|
||||||
mSkills.emplace(skill.mId, SkillValue{});
|
mSkills.emplace(skill.mId, SkillValue{});
|
||||||
|
@ -246,7 +245,7 @@ void MWMechanics::NpcStats::increaseSkill(ESM::RefId id, const ESM::Class& class
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
mSkillIncreases[skill->mData.mAttribute] += increase;
|
mSkillIncreases[ESM::Attribute::AttributeID(skill->mData.mAttribute)] += increase;
|
||||||
|
|
||||||
mSpecIncreases[skill->mData.mSpecialization] += gmst.find("iLevelupSpecialization")->mValue.getInteger();
|
mSpecIncreases[skill->mData.mSpecialization] += gmst.find("iLevelupSpecialization")->mValue.getInteger();
|
||||||
|
|
||||||
|
@ -286,8 +285,7 @@ void MWMechanics::NpcStats::levelUp()
|
||||||
mLevelProgress -= gmst.find("iLevelUpTotal")->mValue.getInteger();
|
mLevelProgress -= gmst.find("iLevelUpTotal")->mValue.getInteger();
|
||||||
mLevelProgress = std::max(0, mLevelProgress); // might be necessary when levelup was invoked via console
|
mLevelProgress = std::max(0, mLevelProgress); // might be necessary when levelup was invoked via console
|
||||||
|
|
||||||
for (int i = 0; i < ESM::Attribute::Length; ++i)
|
mSkillIncreases.clear();
|
||||||
mSkillIncreases[i] = 0;
|
|
||||||
|
|
||||||
const float endurance = getAttribute(ESM::Attribute::Endurance).getBase();
|
const float endurance = getAttribute(ESM::Attribute::Endurance).getBase();
|
||||||
|
|
||||||
|
@ -312,14 +310,12 @@ void MWMechanics::NpcStats::updateHealth()
|
||||||
setHealth(floor(0.5f * (strength + endurance)));
|
setHealth(floor(0.5f * (strength + endurance)));
|
||||||
}
|
}
|
||||||
|
|
||||||
int MWMechanics::NpcStats::getLevelupAttributeMultiplier(int attribute) const
|
int MWMechanics::NpcStats::getLevelupAttributeMultiplier(ESM::Attribute::AttributeID attribute) const
|
||||||
{
|
{
|
||||||
int num = mSkillIncreases[attribute];
|
auto it = mSkillIncreases.find(attribute);
|
||||||
|
if (it == mSkillIncreases.end() || it->second == 0)
|
||||||
if (num == 0)
|
|
||||||
return 1;
|
return 1;
|
||||||
|
int num = std::min(10, it->second);
|
||||||
num = std::min(10, num);
|
|
||||||
|
|
||||||
// iLevelUp01Mult - iLevelUp10Mult
|
// iLevelUp01Mult - iLevelUp10Mult
|
||||||
std::stringstream gmst;
|
std::stringstream gmst;
|
||||||
|
@ -488,8 +484,9 @@ void MWMechanics::NpcStats::writeState(ESM::NpcStats& state) const
|
||||||
state.mWerewolfKills = mWerewolfKills;
|
state.mWerewolfKills = mWerewolfKills;
|
||||||
state.mLevelProgress = mLevelProgress;
|
state.mLevelProgress = mLevelProgress;
|
||||||
|
|
||||||
for (size_t i = 0; i < state.mSkillIncrease.size(); ++i)
|
state.mSkillIncrease.fill(0);
|
||||||
state.mSkillIncrease[i] = mSkillIncreases[i];
|
for (const auto& [key, value] : mSkillIncreases)
|
||||||
|
state.mSkillIncrease[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 +535,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[i] = state.mSkillIncrease[i];
|
mSkillIncreases[static_cast<ESM::Attribute::AttributeID>(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,8 @@ 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::vector<int> mSkillIncreases; // number of skill increases for each attribute (resets after leveling up)
|
std::map<ESM::Attribute::AttributeID, int>
|
||||||
|
mSkillIncreases; // number of skill increases for each attribute (resets after leveling up)
|
||||||
std::vector<int> mSpecIncreases; // number of skill increases for each specialization (accumulates throughout
|
std::vector<int> mSpecIncreases; // number of skill increases for each specialization (accumulates throughout
|
||||||
// the entire game)
|
// the entire game)
|
||||||
std::set<ESM::RefId> mUsedIds;
|
std::set<ESM::RefId> mUsedIds;
|
||||||
|
@ -87,7 +88,7 @@ namespace MWMechanics
|
||||||
|
|
||||||
int getLevelProgress() const;
|
int getLevelProgress() const;
|
||||||
|
|
||||||
int getLevelupAttributeMultiplier(int attribute) const;
|
int getLevelupAttributeMultiplier(ESM::Attribute::AttributeID attribute) const;
|
||||||
|
|
||||||
int getSkillIncreasesForSpecialization(int spec) const;
|
int getSkillIncreasesForSpecialization(int spec) const;
|
||||||
|
|
||||||
|
|
|
@ -79,27 +79,30 @@ 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 attr = creatureStats.getAttribute(effect.mArg);
|
auto attribute = static_cast<ESM::Attribute::AttributeID>(effect.mArg);
|
||||||
|
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);
|
||||||
attr.damage(magnitude);
|
attr.damage(magnitude);
|
||||||
creatureStats.setAttribute(effect.mArg, attr);
|
creatureStats.setAttribute(attribute, attr);
|
||||||
}
|
}
|
||||||
|
|
||||||
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 attr = creatureStats.getAttribute(effect.mArg);
|
auto attribute = static_cast<ESM::Attribute::AttributeID>(effect.mArg);
|
||||||
|
auto attr = creatureStats.getAttribute(attribute);
|
||||||
attr.restore(magnitude);
|
attr.restore(magnitude);
|
||||||
creatureStats.setAttribute(effect.mArg, attr);
|
creatureStats.setAttribute(attribute, attr);
|
||||||
}
|
}
|
||||||
|
|
||||||
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 attr = creatureStats.getAttribute(effect.mArg);
|
auto attribute = static_cast<ESM::Attribute::AttributeID>(effect.mArg);
|
||||||
|
auto attr = creatureStats.getAttribute(attribute);
|
||||||
attr.setModifier(attr.getModifier() + magnitude);
|
attr.setModifier(attr.getModifier() + magnitude);
|
||||||
creatureStats.setAttribute(effect.mArg, attr);
|
creatureStats.setAttribute(attribute, attr);
|
||||||
}
|
}
|
||||||
|
|
||||||
void damageSkill(const MWWorld::Ptr& target, const ESM::ActiveEffect& effect, float magnitude)
|
void damageSkill(const MWWorld::Ptr& target, const ESM::ActiveEffect& effect, float magnitude)
|
||||||
|
@ -739,9 +742,10 @@ 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);
|
||||||
AttributeValue attr = creatureStats.getAttribute(effect.mArg);
|
auto attribute = static_cast<ESM::Attribute::AttributeID>(effect.mArg);
|
||||||
|
AttributeValue attr = creatureStats.getAttribute(attribute);
|
||||||
attr.setBase(attr.getBase() + effect.mMagnitude);
|
attr.setBase(attr.getBase() + effect.mMagnitude);
|
||||||
creatureStats.setAttribute(effect.mArg, attr);
|
creatureStats.setAttribute(attribute, attr);
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
fortifyAttribute(target, effect, effect.mMagnitude);
|
fortifyAttribute(target, effect, effect.mMagnitude);
|
||||||
|
@ -1202,9 +1206,10 @@ 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);
|
||||||
AttributeValue attr = creatureStats.getAttribute(effect.mArg);
|
auto attribute = static_cast<ESM::Attribute::AttributeID>(effect.mArg);
|
||||||
|
AttributeValue attr = creatureStats.getAttribute(attribute);
|
||||||
attr.setBase(attr.getBase() - effect.mMagnitude);
|
attr.setBase(attr.getBase() - effect.mMagnitude);
|
||||||
creatureStats.setAttribute(effect.mArg, attr);
|
creatureStats.setAttribute(attribute, attr);
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
fortifyAttribute(target, effect, -effect.mMagnitude);
|
fortifyAttribute(target, effect, -effect.mMagnitude);
|
||||||
|
|
|
@ -540,7 +540,11 @@ namespace MWMechanics
|
||||||
case ESM::MagicEffect::DamageAttribute:
|
case ESM::MagicEffect::DamageAttribute:
|
||||||
case ESM::MagicEffect::DrainAttribute:
|
case ESM::MagicEffect::DrainAttribute:
|
||||||
if (!enemy.isEmpty()
|
if (!enemy.isEmpty()
|
||||||
&& enemy.getClass().getCreatureStats(enemy).getAttribute(effect.mAttribute).getModified() <= 0)
|
&& enemy.getClass()
|
||||||
|
.getCreatureStats(enemy)
|
||||||
|
.getAttribute(ESM::Attribute::AttributeID(effect.mAttribute))
|
||||||
|
.getModified()
|
||||||
|
<= 0)
|
||||||
return 0.f;
|
return 0.f;
|
||||||
{
|
{
|
||||||
if (effect.mAttribute >= 0 && effect.mAttribute < ESM::Attribute::Length)
|
if (effect.mAttribute >= 0 && effect.mAttribute < ESM::Attribute::Length)
|
||||||
|
|
|
@ -247,23 +247,24 @@ namespace MWMechanics
|
||||||
return;
|
return;
|
||||||
|
|
||||||
// Note: if target actor has the Restore attribute effects, stats will be restored.
|
// Note: if target actor has the Restore attribute effects, stats will be restored.
|
||||||
for (std::vector<ESM::SpellState::PermanentSpellEffectInfo>::const_iterator effectIt = it->second.begin();
|
for (const ESM::SpellState::PermanentSpellEffectInfo& info : it->second)
|
||||||
effectIt != it->second.end(); ++effectIt)
|
|
||||||
{
|
{
|
||||||
// Applied corprus effects are already in loaded stats modifiers
|
// Applied corprus effects are already in loaded stats modifiers
|
||||||
if (effectIt->mId == ESM::MagicEffect::FortifyAttribute)
|
if (info.mId == ESM::MagicEffect::FortifyAttribute)
|
||||||
{
|
{
|
||||||
AttributeValue attr = creatureStats->getAttribute(effectIt->mArg);
|
auto id = static_cast<ESM::Attribute::AttributeID>(info.mArg);
|
||||||
attr.setModifier(attr.getModifier() - effectIt->mMagnitude);
|
AttributeValue attr = creatureStats->getAttribute(id);
|
||||||
attr.damage(-effectIt->mMagnitude);
|
attr.setModifier(attr.getModifier() - info.mMagnitude);
|
||||||
creatureStats->setAttribute(effectIt->mArg, attr);
|
attr.damage(-info.mMagnitude);
|
||||||
|
creatureStats->setAttribute(id, attr);
|
||||||
}
|
}
|
||||||
else if (effectIt->mId == ESM::MagicEffect::DrainAttribute)
|
else if (info.mId == ESM::MagicEffect::DrainAttribute)
|
||||||
{
|
{
|
||||||
AttributeValue attr = creatureStats->getAttribute(effectIt->mArg);
|
auto id = static_cast<ESM::Attribute::AttributeID>(info.mArg);
|
||||||
attr.setModifier(attr.getModifier() + effectIt->mMagnitude);
|
AttributeValue attr = creatureStats->getAttribute(id);
|
||||||
attr.damage(effectIt->mMagnitude);
|
attr.setModifier(attr.getModifier() + info.mMagnitude);
|
||||||
creatureStats->setAttribute(effectIt->mArg, attr);
|
attr.damage(info.mMagnitude);
|
||||||
|
creatureStats->setAttribute(id, attr);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -109,10 +109,10 @@ namespace MWScript
|
||||||
template <class R>
|
template <class R>
|
||||||
class OpGetAttribute : public Interpreter::Opcode0
|
class OpGetAttribute : public Interpreter::Opcode0
|
||||||
{
|
{
|
||||||
int mIndex;
|
ESM::Attribute::AttributeID mIndex;
|
||||||
|
|
||||||
public:
|
public:
|
||||||
OpGetAttribute(int index)
|
OpGetAttribute(ESM::Attribute::AttributeID 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
|
||||||
{
|
{
|
||||||
int mIndex;
|
ESM::Attribute::AttributeID mIndex;
|
||||||
|
|
||||||
public:
|
public:
|
||||||
OpSetAttribute(int index)
|
OpSetAttribute(ESM::Attribute::AttributeID 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
|
||||||
{
|
{
|
||||||
int mIndex;
|
ESM::Attribute::AttributeID mIndex;
|
||||||
|
|
||||||
public:
|
public:
|
||||||
OpModAttribute(int index)
|
OpModAttribute(ESM::Attribute::AttributeID index)
|
||||||
: mIndex(index)
|
: mIndex(index)
|
||||||
{
|
{
|
||||||
}
|
}
|
||||||
|
@ -1322,17 +1322,18 @@ namespace MWScript
|
||||||
{
|
{
|
||||||
for (int i = 0; i < Compiler::Stats::numberOfAttributes; ++i)
|
for (int i = 0; i < Compiler::Stats::numberOfAttributes; ++i)
|
||||||
{
|
{
|
||||||
interpreter.installSegment5<OpGetAttribute<ImplicitRef>>(Compiler::Stats::opcodeGetAttribute + i, i);
|
auto id = static_cast<ESM::Attribute::AttributeID>(i);
|
||||||
|
interpreter.installSegment5<OpGetAttribute<ImplicitRef>>(Compiler::Stats::opcodeGetAttribute + i, id);
|
||||||
interpreter.installSegment5<OpGetAttribute<ExplicitRef>>(
|
interpreter.installSegment5<OpGetAttribute<ExplicitRef>>(
|
||||||
Compiler::Stats::opcodeGetAttributeExplicit + i, i);
|
Compiler::Stats::opcodeGetAttributeExplicit + i, id);
|
||||||
|
|
||||||
interpreter.installSegment5<OpSetAttribute<ImplicitRef>>(Compiler::Stats::opcodeSetAttribute + i, i);
|
interpreter.installSegment5<OpSetAttribute<ImplicitRef>>(Compiler::Stats::opcodeSetAttribute + i, id);
|
||||||
interpreter.installSegment5<OpSetAttribute<ExplicitRef>>(
|
interpreter.installSegment5<OpSetAttribute<ExplicitRef>>(
|
||||||
Compiler::Stats::opcodeSetAttributeExplicit + i, i);
|
Compiler::Stats::opcodeSetAttributeExplicit + i, id);
|
||||||
|
|
||||||
interpreter.installSegment5<OpModAttribute<ImplicitRef>>(Compiler::Stats::opcodeModAttribute + i, i);
|
interpreter.installSegment5<OpModAttribute<ImplicitRef>>(Compiler::Stats::opcodeModAttribute + i, id);
|
||||||
interpreter.installSegment5<OpModAttribute<ExplicitRef>>(
|
interpreter.installSegment5<OpModAttribute<ExplicitRef>>(
|
||||||
Compiler::Stats::opcodeModAttributeExplicit + i, i);
|
Compiler::Stats::opcodeModAttributeExplicit + i, id);
|
||||||
}
|
}
|
||||||
|
|
||||||
for (int i = 0; i < Compiler::Stats::numberOfDynamics; ++i)
|
for (int i = 0; i < Compiler::Stats::numberOfDynamics; ++i)
|
||||||
|
|
|
@ -43,8 +43,7 @@ namespace MWWorld
|
||||||
|
|
||||||
ESM::CreatureStats::CorprusStats stats;
|
ESM::CreatureStats::CorprusStats stats;
|
||||||
stats.mNextWorsening = oldStats.mNextWorsening;
|
stats.mNextWorsening = oldStats.mNextWorsening;
|
||||||
for (int i = 0; i < ESM::Attribute::Length; ++i)
|
stats.mWorsenings.fill(0);
|
||||||
stats.mWorsenings[i] = 0;
|
|
||||||
|
|
||||||
for (auto& effect : spell->mEffects.mList)
|
for (auto& effect : spell->mEffects.mList)
|
||||||
{
|
{
|
||||||
|
@ -179,8 +178,8 @@ namespace MWWorld
|
||||||
{
|
{
|
||||||
it->mNextWorsening = spell.second.mNextWorsening;
|
it->mNextWorsening = spell.second.mNextWorsening;
|
||||||
int worsenings = 0;
|
int worsenings = 0;
|
||||||
for (int i = 0; i < ESM::Attribute::Length; ++i)
|
for (const auto& worsening : spell.second.mWorsenings)
|
||||||
worsenings = std::max(spell.second.mWorsenings[i], worsenings);
|
worsenings = std::max(worsening, worsenings);
|
||||||
it->mWorsenings = worsenings;
|
it->mWorsenings = worsenings;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -209,20 +208,19 @@ namespace MWWorld
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
// Reset modifiers that were previously recalculated each frame
|
// Reset modifiers that were previously recalculated each frame
|
||||||
for (std::size_t i = 0; i < ESM::Attribute::Length; ++i)
|
for (auto& attribute : creatureStats.mAttributes)
|
||||||
creatureStats.mAttributes[i].mMod = 0.f;
|
attribute.mMod = 0.f;
|
||||||
for (std::size_t i = 0; i < 3; ++i)
|
for (auto& dynamic : creatureStats.mDynamic)
|
||||||
{
|
{
|
||||||
auto& dynamic = creatureStats.mDynamic[i];
|
|
||||||
dynamic.mCurrent -= dynamic.mMod - dynamic.mBase;
|
dynamic.mCurrent -= dynamic.mMod - dynamic.mBase;
|
||||||
dynamic.mMod = 0.f;
|
dynamic.mMod = 0.f;
|
||||||
}
|
}
|
||||||
for (std::size_t i = 0; i < 4; ++i)
|
for (auto& setting : creatureStats.mAiSettings)
|
||||||
creatureStats.mAiSettings[i].mMod = 0.f;
|
setting.mMod = 0.f;
|
||||||
if (npcStats)
|
if (npcStats)
|
||||||
{
|
{
|
||||||
for (std::size_t i = 0; i < npcStats->mSkills.size(); ++i)
|
for (auto& skill : npcStats->mSkills)
|
||||||
npcStats->mSkills[i].mMod = 0.f;
|
skill.mMod = 0.f;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -230,9 +228,9 @@ namespace MWWorld
|
||||||
// version or not
|
// version or not
|
||||||
void convertStats(ESM::CreatureStats& creatureStats)
|
void convertStats(ESM::CreatureStats& creatureStats)
|
||||||
{
|
{
|
||||||
for (std::size_t i = 0; i < 3; ++i)
|
for (auto& dynamic : creatureStats.mDynamic)
|
||||||
creatureStats.mDynamic[i].mMod = 0.f;
|
dynamic.mMod = 0.f;
|
||||||
for (std::size_t i = 0; i < 4; ++i)
|
for (auto& setting : creatureStats.mAiSettings)
|
||||||
creatureStats.mAiSettings[i].mMod = 0.f;
|
setting.mMod = 0.f;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -61,8 +61,8 @@ 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 (int i = 0; i < ESM::Attribute::Length; ++i)
|
for (size_t i = 0; i < mSaveAttributes.size(); ++i)
|
||||||
mSaveAttributes[i] = stats.getAttribute(i).getModified();
|
mSaveAttributes[i] = stats.getAttribute(static_cast<ESM::Attribute::AttributeID>(i)).getModified();
|
||||||
}
|
}
|
||||||
|
|
||||||
void Player::restoreStats()
|
void Player::restoreStats()
|
||||||
|
@ -79,12 +79,13 @@ namespace MWWorld
|
||||||
skill.restore(skill.getDamage());
|
skill.restore(skill.getDamage());
|
||||||
skill.setModifier(mSaveSkills[i] - skill.getBase());
|
skill.setModifier(mSaveSkills[i] - skill.getBase());
|
||||||
}
|
}
|
||||||
for (int i = 0; i < ESM::Attribute::Length; ++i)
|
for (size_t i = 0; i < mSaveAttributes.size(); ++i)
|
||||||
{
|
{
|
||||||
auto attribute = npcStats.getAttribute(i);
|
auto id = static_cast<ESM::Attribute::AttributeID>(i);
|
||||||
|
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());
|
||||||
npcStats.setAttribute(i, attribute);
|
npcStats.setAttribute(id, attribute);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -252,11 +253,7 @@ namespace MWWorld
|
||||||
mLastKnownExteriorPosition = osg::Vec3f(0, 0, 0);
|
mLastKnownExteriorPosition = osg::Vec3f(0, 0, 0);
|
||||||
|
|
||||||
mSaveSkills.fill(0.f);
|
mSaveSkills.fill(0.f);
|
||||||
|
mSaveAttributes.fill(0.f);
|
||||||
for (int i = 0; i < ESM::Attribute::Length; ++i)
|
|
||||||
{
|
|
||||||
mSaveAttributes[i] = 0.f;
|
|
||||||
}
|
|
||||||
|
|
||||||
mMarkedPosition.pos[0] = 0;
|
mMarkedPosition.pos[0] = 0;
|
||||||
mMarkedPosition.pos[1] = 0;
|
mMarkedPosition.pos[1] = 0;
|
||||||
|
@ -291,7 +288,7 @@ namespace MWWorld
|
||||||
else
|
else
|
||||||
player.mHasMark = false;
|
player.mHasMark = false;
|
||||||
|
|
||||||
for (int i = 0; i < ESM::Attribute::Length; ++i)
|
for (size_t i = 0; i < mSaveAttributes.size(); ++i)
|
||||||
player.mSaveAttributes[i] = mSaveAttributes[i];
|
player.mSaveAttributes[i] = mSaveAttributes[i];
|
||||||
for (size_t i = 0; i < mSaveSkills.size(); ++i)
|
for (size_t i = 0; i < mSaveSkills.size(); ++i)
|
||||||
player.mSaveSkills[i] = mSaveSkills[i];
|
player.mSaveSkills[i] = mSaveSkills[i];
|
||||||
|
@ -329,7 +326,7 @@ namespace MWWorld
|
||||||
|
|
||||||
mPlayer.load(player.mObject);
|
mPlayer.load(player.mObject);
|
||||||
|
|
||||||
for (int i = 0; i < ESM::Attribute::Length; ++i)
|
for (size_t i = 0; i < mSaveAttributes.size(); ++i)
|
||||||
mSaveAttributes[i] = player.mSaveAttributes[i];
|
mSaveAttributes[i] = player.mSaveAttributes[i];
|
||||||
for (size_t i = 0; i < mSaveSkills.size(); ++i)
|
for (size_t i = 0; i < mSaveSkills.size(); ++i)
|
||||||
mSaveSkills[i] = player.mSaveSkills[i];
|
mSaveSkills[i] = player.mSaveSkills[i];
|
||||||
|
|
|
@ -52,7 +52,7 @@ namespace MWWorld
|
||||||
|
|
||||||
// Saved stats prior to becoming a werewolf
|
// Saved stats prior to becoming a werewolf
|
||||||
std::array<float, ESM::Skill::Length> mSaveSkills;
|
std::array<float, ESM::Skill::Length> mSaveSkills;
|
||||||
float mSaveAttributes[ESM::Attribute::Length];
|
std::array<float, ESM::Attribute::Length> mSaveAttributes;
|
||||||
|
|
||||||
bool mJumping;
|
bool mJumping;
|
||||||
|
|
||||||
|
|
|
@ -10,11 +10,11 @@ namespace ESM
|
||||||
void CreatureStats::load(ESMReader& esm)
|
void CreatureStats::load(ESMReader& esm)
|
||||||
{
|
{
|
||||||
const bool intFallback = esm.getFormatVersion() <= MaxIntFallbackFormatVersion;
|
const bool intFallback = esm.getFormatVersion() <= MaxIntFallbackFormatVersion;
|
||||||
for (int i = 0; i < 8; ++i)
|
for (auto& attribute : mAttributes)
|
||||||
mAttributes[i].load(esm, intFallback);
|
attribute.load(esm, intFallback);
|
||||||
|
|
||||||
for (int i = 0; i < 3; ++i)
|
for (auto& dynamic : mDynamic)
|
||||||
mDynamic[i].load(esm);
|
dynamic.load(esm);
|
||||||
|
|
||||||
mGoldPool = 0;
|
mGoldPool = 0;
|
||||||
esm.getHNOT(mGoldPool, "GOLD");
|
esm.getHNOT(mGoldPool, "GOLD");
|
||||||
|
@ -154,8 +154,8 @@ namespace ESM
|
||||||
|
|
||||||
if (mHasAiSettings)
|
if (mHasAiSettings)
|
||||||
{
|
{
|
||||||
for (int i = 0; i < 4; ++i)
|
for (auto& setting : mAiSettings)
|
||||||
mAiSettings[i].load(esm);
|
setting.load(esm);
|
||||||
}
|
}
|
||||||
|
|
||||||
while (esm.isNextSub("CORP"))
|
while (esm.isNextSub("CORP"))
|
||||||
|
@ -179,11 +179,11 @@ namespace ESM
|
||||||
|
|
||||||
void CreatureStats::save(ESMWriter& esm) const
|
void CreatureStats::save(ESMWriter& esm) const
|
||||||
{
|
{
|
||||||
for (int i = 0; i < 8; ++i)
|
for (const auto& attribute : mAttributes)
|
||||||
mAttributes[i].save(esm);
|
attribute.save(esm);
|
||||||
|
|
||||||
for (int i = 0; i < 3; ++i)
|
for (const auto& dynamic : mDynamic)
|
||||||
mDynamic[i].save(esm);
|
dynamic.save(esm);
|
||||||
|
|
||||||
if (mGoldPool)
|
if (mGoldPool)
|
||||||
esm.writeHNT("GOLD", mGoldPool);
|
esm.writeHNT("GOLD", mGoldPool);
|
||||||
|
@ -268,8 +268,8 @@ namespace ESM
|
||||||
esm.writeHNT("AISE", mHasAiSettings);
|
esm.writeHNT("AISE", mHasAiSettings);
|
||||||
if (mHasAiSettings)
|
if (mHasAiSettings)
|
||||||
{
|
{
|
||||||
for (int i = 0; i < 4; ++i)
|
for (const auto& setting : mAiSettings)
|
||||||
mAiSettings[i].save(esm);
|
setting.save(esm);
|
||||||
}
|
}
|
||||||
if (mMissingACDT)
|
if (mMissingACDT)
|
||||||
esm.writeHNT("NOAC", mMissingACDT);
|
esm.writeHNT("NOAC", mMissingACDT);
|
||||||
|
|
|
@ -1,6 +1,7 @@
|
||||||
#ifndef OPENMW_ESM_CREATURESTATS_H
|
#ifndef OPENMW_ESM_CREATURESTATS_H
|
||||||
#define OPENMW_ESM_CREATURESTATS_H
|
#define OPENMW_ESM_CREATURESTATS_H
|
||||||
|
|
||||||
|
#include <array>
|
||||||
#include <map>
|
#include <map>
|
||||||
#include <string>
|
#include <string>
|
||||||
#include <vector>
|
#include <vector>
|
||||||
|
@ -26,19 +27,19 @@ namespace ESM
|
||||||
{
|
{
|
||||||
struct CorprusStats
|
struct CorprusStats
|
||||||
{
|
{
|
||||||
int mWorsenings[Attribute::Length];
|
std::array<int, Attribute::Length> mWorsenings;
|
||||||
TimeStamp mNextWorsening;
|
TimeStamp mNextWorsening;
|
||||||
};
|
};
|
||||||
|
|
||||||
StatState<float> mAttributes[Attribute::Length];
|
std::array<StatState<float>, Attribute::Length> mAttributes;
|
||||||
StatState<float> mDynamic[3];
|
std::array<StatState<float>, 3> mDynamic;
|
||||||
|
|
||||||
MagicEffects mMagicEffects;
|
MagicEffects mMagicEffects;
|
||||||
|
|
||||||
AiSequence::AiSequence mAiSequence;
|
AiSequence::AiSequence mAiSequence;
|
||||||
|
|
||||||
bool mHasAiSettings;
|
bool mHasAiSettings;
|
||||||
StatState<int> mAiSettings[4];
|
std::array<StatState<int>, 4> mAiSettings;
|
||||||
|
|
||||||
std::map<SummonKey, int> mSummonedCreatureMap;
|
std::map<SummonKey, int> mSummonedCreatureMap;
|
||||||
std::multimap<int, int> mSummonedCreatures;
|
std::multimap<int, int> mSummonedCreatures;
|
||||||
|
|
|
@ -46,64 +46,7 @@
|
||||||
</Widget>
|
</Widget>
|
||||||
|
|
||||||
<!-- Player attributes -->
|
<!-- Player attributes -->
|
||||||
<Widget type="Widget" skin="MW_Box" position="8 224 265 156">
|
<Widget type="Widget" skin="MW_Box" position="8 224 265 156" name="Attributes" />
|
||||||
<Widget type="MWAttribute" skin="MW_StatNameValue" position="8 4 250 18" name="Attribute0">
|
|
||||||
<UserString key="ToolTipType" value="Layout"/>
|
|
||||||
<UserString key="ToolTipLayout" value="AttributeToolTip"/>
|
|
||||||
<UserString key="Caption_AttributeName" value="#{sAttributeStrength}"/>
|
|
||||||
<UserString key="Caption_AttributeDescription" value="#{sStrDesc}"/>
|
|
||||||
<UserString key="ImageTexture_AttributeImage" value="icons\k\attribute_strength.dds"/>
|
|
||||||
</Widget>
|
|
||||||
<Widget type="MWAttribute" skin="MW_StatNameValue" position="8 22 250 18" name="Attribute1">
|
|
||||||
<UserString key="ToolTipType" value="Layout"/>
|
|
||||||
<UserString key="ToolTipLayout" value="AttributeToolTip"/>
|
|
||||||
<UserString key="Caption_AttributeName" value="#{sAttributeIntelligence}"/>
|
|
||||||
<UserString key="Caption_AttributeDescription" value="#{sIntDesc}"/>
|
|
||||||
<UserString key="ImageTexture_AttributeImage" value="icons\k\attribute_int.dds"/>
|
|
||||||
</Widget>
|
|
||||||
<Widget type="MWAttribute" skin="MW_StatNameValue" position="8 40 250 18" name="Attribute2">
|
|
||||||
<UserString key="ToolTipType" value="Layout"/>
|
|
||||||
<UserString key="ToolTipLayout" value="AttributeToolTip"/>
|
|
||||||
<UserString key="Caption_AttributeName" value="#{sAttributeWillpower}"/>
|
|
||||||
<UserString key="Caption_AttributeDescription" value="#{sWilDesc}"/>
|
|
||||||
<UserString key="ImageTexture_AttributeImage" value="icons\k\attribute_wilpower.dds"/>
|
|
||||||
</Widget>
|
|
||||||
<Widget type="MWAttribute" skin="MW_StatNameValue" position="8 58 250 18" name="Attribute3">
|
|
||||||
<UserString key="ToolTipType" value="Layout"/>
|
|
||||||
<UserString key="ToolTipLayout" value="AttributeToolTip"/>
|
|
||||||
<UserString key="Caption_AttributeName" value="#{sAttributeAgility}"/>
|
|
||||||
<UserString key="Caption_AttributeDescription" value="#{sAgiDesc}"/>
|
|
||||||
<UserString key="ImageTexture_AttributeImage" value="icons\k\attribute_agility.dds"/>
|
|
||||||
</Widget>
|
|
||||||
<Widget type="MWAttribute" skin="MW_StatNameValue" position="8 76 250 18" name="Attribute4">
|
|
||||||
<UserString key="ToolTipType" value="Layout"/>
|
|
||||||
<UserString key="ToolTipLayout" value="AttributeToolTip"/>
|
|
||||||
<UserString key="Caption_AttributeName" value="#{sAttributeSpeed}"/>
|
|
||||||
<UserString key="Caption_AttributeDescription" value="#{sSpdDesc}"/>
|
|
||||||
<UserString key="ImageTexture_AttributeImage" value="icons\k\attribute_speed.dds"/>
|
|
||||||
</Widget>
|
|
||||||
<Widget type="MWAttribute" skin="MW_StatNameValue" position="8 94 250 18" name="Attribute5">
|
|
||||||
<UserString key="ToolTipType" value="Layout"/>
|
|
||||||
<UserString key="ToolTipLayout" value="AttributeToolTip"/>
|
|
||||||
<UserString key="Caption_AttributeName" value="#{sAttributeEndurance}"/>
|
|
||||||
<UserString key="Caption_AttributeDescription" value="#{sEndDesc}"/>
|
|
||||||
<UserString key="ImageTexture_AttributeImage" value="icons\k\attribute_endurance.dds"/>
|
|
||||||
</Widget>
|
|
||||||
<Widget type="MWAttribute" skin="MW_StatNameValue" position="8 112 250 18" name="Attribute6">
|
|
||||||
<UserString key="ToolTipType" value="Layout"/>
|
|
||||||
<UserString key="ToolTipLayout" value="AttributeToolTip"/>
|
|
||||||
<UserString key="Caption_AttributeName" value="#{sAttributePersonality}"/>
|
|
||||||
<UserString key="Caption_AttributeDescription" value="#{sPerDesc}"/>
|
|
||||||
<UserString key="ImageTexture_AttributeImage" value="icons\k\attribute_personality.dds"/>
|
|
||||||
</Widget>
|
|
||||||
<Widget type="MWAttribute" skin="MW_StatNameValue" position="8 130 250 18" name="Attribute7">
|
|
||||||
<UserString key="ToolTipType" value="Layout"/>
|
|
||||||
<UserString key="ToolTipLayout" value="AttributeToolTip"/>
|
|
||||||
<UserString key="Caption_AttributeName" value="#{sAttributeLuck}"/>
|
|
||||||
<UserString key="Caption_AttributeDescription" value="#{sLucDesc}"/>
|
|
||||||
<UserString key="ImageTexture_AttributeImage" value="icons\k\attribute_luck.dds"/>
|
|
||||||
</Widget>
|
|
||||||
</Widget>
|
|
||||||
|
|
||||||
<!-- Player Skills -->
|
<!-- Player Skills -->
|
||||||
<Widget type="Widget" skin="MW_Box" position="281 7 244 372" align="Left VStretch" name="Skills">
|
<Widget type="Widget" skin="MW_Box" position="281 7 244 372" align="Left VStretch" name="Skills">
|
||||||
|
|
|
@ -10,14 +10,9 @@
|
||||||
</Widget>
|
</Widget>
|
||||||
|
|
||||||
<!-- Attribute list -->
|
<!-- Attribute list -->
|
||||||
<Widget type="MWAttribute" skin="MW_StatNameButtonC" position="0 28 216 18" name="Attribute0" align="Left Top"/>
|
<Widget type="ScrollView" skin="MW_ScrollView" position="0 28 216 144" name="Attributes" align="Left Top">
|
||||||
<Widget type="MWAttribute" skin="MW_StatNameButtonC" position="0 46 216 18" name="Attribute1" align="Left Top"/>
|
<Property key="CanvasAlign" value="Left"/>
|
||||||
<Widget type="MWAttribute" skin="MW_StatNameButtonC" position="0 64 216 18" name="Attribute2" align="Left Top"/>
|
</Widget>
|
||||||
<Widget type="MWAttribute" skin="MW_StatNameButtonC" position="0 82 216 18" name="Attribute3" align="Left Top"/>
|
|
||||||
<Widget type="MWAttribute" skin="MW_StatNameButtonC" position="0 100 216 18" name="Attribute4" align="Left Top"/>
|
|
||||||
<Widget type="MWAttribute" skin="MW_StatNameButtonC" position="0 118 216 18" name="Attribute5" align="Left Top"/>
|
|
||||||
<Widget type="MWAttribute" skin="MW_StatNameButtonC" position="0 136 216 18" name="Attribute6" align="Left Top"/>
|
|
||||||
<Widget type="MWAttribute" skin="MW_StatNameButtonC" position="0 154 216 18" name="Attribute7" align="Left Top"/>
|
|
||||||
|
|
||||||
<!-- Dialog buttons -->
|
<!-- Dialog buttons -->
|
||||||
<Widget type="HBox" position="0 175 216 28">
|
<Widget type="HBox" position="0 175 216 28">
|
||||||
|
|
|
@ -27,131 +27,10 @@
|
||||||
<UserString key="VStretch" value="false"/>
|
<UserString key="VStretch" value="false"/>
|
||||||
</Widget>
|
</Widget>
|
||||||
|
|
||||||
<Widget type="Widget" skin="" position="0 280 420 84" name="AssignWidget">
|
<Widget type="ScrollView" skin="MW_ScrollView" position="0 280 420 84" name="AssignWidget">
|
||||||
<UserString key="HStretch" value="false"/>
|
<UserString key="HStretch" value="false"/>
|
||||||
<UserString key="VStretch" value="false"/>
|
<UserString key="VStretch" value="false"/>
|
||||||
|
<Property key="CanvasAlign" value="Left"/>
|
||||||
<Widget type="TextBox" skin="SandTextVCenter" position="32 0 100 20" name="AttribMultiplier1"/>
|
|
||||||
<Widget type="TextBox" skin="SandTextVCenter" position="32 20 100 20" name="AttribMultiplier2"/>
|
|
||||||
<Widget type="TextBox" skin="SandTextVCenter" position="32 40 100 20" name="AttribMultiplier3"/>
|
|
||||||
<Widget type="TextBox" skin="SandTextVCenter" position="32 60 100 20" name="AttribMultiplier4"/>
|
|
||||||
<Widget type="TextBox" skin="SandTextVCenter" position="218 0 100 20" name="AttribMultiplier5"/>
|
|
||||||
<Widget type="TextBox" skin="SandTextVCenter" position="218 20 100 20" name="AttribMultiplier6"/>
|
|
||||||
<Widget type="TextBox" skin="SandTextVCenter" position="218 40 100 20" name="AttribMultiplier7"/>
|
|
||||||
<Widget type="TextBox" skin="SandTextVCenter" position="218 60 100 20" name="AttribMultiplier8"/>
|
|
||||||
|
|
||||||
<Widget type="HBox" position="52 0 200 20">
|
|
||||||
<Widget type="AutoSizedButton" skin="SandTextButton" name="Attrib1">
|
|
||||||
<UserString key="TextPadding" value="0 0"/>
|
|
||||||
<UserString key="ToolTipType" value="Layout"/>
|
|
||||||
<UserString key="ToolTipLayout" value="AttributeToolTip"/>
|
|
||||||
<UserString key="Caption_AttributeName" value="#{sAttributeStrength}"/>
|
|
||||||
<UserString key="Caption_AttributeDescription" value="#{sStrDesc}"/>
|
|
||||||
<UserString key="ImageTexture_AttributeImage" value="icons\k\attribute_strength.dds"/>
|
|
||||||
<Property key="Caption" value="#{sAttributeStrength}"/>
|
|
||||||
</Widget>
|
|
||||||
<Widget type="AutoSizedTextBox" skin="SandText" name="AttribVal1">
|
|
||||||
</Widget>
|
|
||||||
</Widget>
|
|
||||||
|
|
||||||
<Widget type="HBox" position="52 20 200 20">
|
|
||||||
<Widget type="AutoSizedButton" skin="SandTextButton" name="Attrib2">
|
|
||||||
<UserString key="TextPadding" value="0 0"/>
|
|
||||||
<UserString key="ToolTipType" value="Layout"/>
|
|
||||||
<UserString key="ToolTipLayout" value="AttributeToolTip"/>
|
|
||||||
<UserString key="Caption_AttributeName" value="#{sAttributeIntelligence}"/>
|
|
||||||
<UserString key="Caption_AttributeDescription" value="#{sIntDesc}"/>
|
|
||||||
<UserString key="ImageTexture_AttributeImage" value="icons\k\attribute_int.dds"/>
|
|
||||||
<Property key="Caption" value="#{sAttributeIntelligence}"/>
|
|
||||||
</Widget>
|
|
||||||
<Widget type="AutoSizedTextBox" skin="SandText" name="AttribVal2">
|
|
||||||
</Widget>
|
|
||||||
</Widget>
|
|
||||||
|
|
||||||
<Widget type="HBox" position="52 40 200 20">
|
|
||||||
<Widget type="AutoSizedButton" skin="SandTextButton" name="Attrib3">
|
|
||||||
<UserString key="TextPadding" value="0 0"/>
|
|
||||||
<UserString key="ToolTipType" value="Layout"/>
|
|
||||||
<UserString key="ToolTipLayout" value="AttributeToolTip"/>
|
|
||||||
<UserString key="Caption_AttributeName" value="#{sAttributeWillpower}"/>
|
|
||||||
<UserString key="Caption_AttributeDescription" value="#{sWilDesc}"/>
|
|
||||||
<UserString key="ImageTexture_AttributeImage" value="icons\k\attribute_wilpower.dds"/>
|
|
||||||
<Property key="Caption" value="#{sAttributeWillpower}"/>
|
|
||||||
</Widget>
|
|
||||||
<Widget type="AutoSizedTextBox" skin="SandText" name="AttribVal3">
|
|
||||||
</Widget>
|
|
||||||
</Widget>
|
|
||||||
|
|
||||||
<Widget type="HBox" position="52 60 200 20">
|
|
||||||
<Widget type="AutoSizedButton" skin="SandTextButton" name="Attrib4">
|
|
||||||
<UserString key="TextPadding" value="0 0"/>
|
|
||||||
<UserString key="ToolTipType" value="Layout"/>
|
|
||||||
<UserString key="ToolTipLayout" value="AttributeToolTip"/>
|
|
||||||
<UserString key="Caption_AttributeName" value="#{sAttributeAgility}"/>
|
|
||||||
<UserString key="Caption_AttributeDescription" value="#{sAgiDesc}"/>
|
|
||||||
<UserString key="ImageTexture_AttributeImage" value="icons\k\attribute_agility.dds"/>
|
|
||||||
<Property key="Caption" value="#{sAttributeAgility}"/>
|
|
||||||
</Widget>
|
|
||||||
<Widget type="AutoSizedTextBox" skin="SandText" name="AttribVal4">
|
|
||||||
</Widget>
|
|
||||||
</Widget>
|
|
||||||
|
|
||||||
|
|
||||||
<Widget type="HBox" position="238 0 200 20">
|
|
||||||
<Widget type="AutoSizedButton" skin="SandTextButton" name="Attrib5">
|
|
||||||
<UserString key="TextPadding" value="0 0"/>
|
|
||||||
<UserString key="ToolTipType" value="Layout"/>
|
|
||||||
<UserString key="ToolTipLayout" value="AttributeToolTip"/>
|
|
||||||
<UserString key="Caption_AttributeName" value="#{sAttributeSpeed}"/>
|
|
||||||
<UserString key="Caption_AttributeDescription" value="#{sSpdDesc}"/>
|
|
||||||
<UserString key="ImageTexture_AttributeImage" value="icons\k\attribute_speed.dds"/>
|
|
||||||
<Property key="Caption" value="#{sAttributeSpeed}"/>
|
|
||||||
</Widget>
|
|
||||||
<Widget type="AutoSizedTextBox" skin="SandText" name="AttribVal5">
|
|
||||||
</Widget>
|
|
||||||
</Widget>
|
|
||||||
|
|
||||||
<Widget type="HBox" position="238 20 200 20">
|
|
||||||
<Widget type="AutoSizedButton" skin="SandTextButton" name="Attrib6">
|
|
||||||
<UserString key="TextPadding" value="0 0"/>
|
|
||||||
<UserString key="ToolTipType" value="Layout"/>
|
|
||||||
<UserString key="ToolTipLayout" value="AttributeToolTip"/>
|
|
||||||
<UserString key="Caption_AttributeName" value="#{sAttributeEndurance}"/>
|
|
||||||
<UserString key="Caption_AttributeDescription" value="#{sEndDesc}"/>
|
|
||||||
<UserString key="ImageTexture_AttributeImage" value="icons\k\attribute_endurance.dds"/>
|
|
||||||
<Property key="Caption" value="#{sAttributeEndurance}"/>
|
|
||||||
</Widget>
|
|
||||||
<Widget type="AutoSizedTextBox" skin="SandText" name="AttribVal6">
|
|
||||||
</Widget>
|
|
||||||
</Widget>
|
|
||||||
|
|
||||||
<Widget type="HBox" position="238 40 200 20">
|
|
||||||
<Widget type="AutoSizedButton" skin="SandTextButton" name="Attrib7">
|
|
||||||
<UserString key="TextPadding" value="0 0"/>
|
|
||||||
<UserString key="ToolTipType" value="Layout"/>
|
|
||||||
<UserString key="ToolTipLayout" value="AttributeToolTip"/>
|
|
||||||
<UserString key="Caption_AttributeName" value="#{sAttributePersonality}"/>
|
|
||||||
<UserString key="Caption_AttributeDescription" value="#{sPerDesc}"/>
|
|
||||||
<UserString key="ImageTexture_AttributeImage" value="icons\k\attribute_personality.dds"/>
|
|
||||||
<Property key="Caption" value="#{sAttributePersonality}"/>
|
|
||||||
</Widget>
|
|
||||||
<Widget type="AutoSizedTextBox" skin="SandText" name="AttribVal7">
|
|
||||||
</Widget>
|
|
||||||
</Widget>
|
|
||||||
|
|
||||||
<Widget type="HBox" position="238 60 200 20">
|
|
||||||
<Widget type="AutoSizedButton" skin="SandTextButton" name="Attrib8">
|
|
||||||
<UserString key="TextPadding" value="0 0"/>
|
|
||||||
<UserString key="ToolTipType" value="Layout"/>
|
|
||||||
<UserString key="ToolTipLayout" value="AttributeToolTip"/>
|
|
||||||
<UserString key="Caption_AttributeName" value="#{sAttributeLuck}"/>
|
|
||||||
<UserString key="Caption_AttributeDescription" value="#{sLucDesc}"/>
|
|
||||||
<UserString key="ImageTexture_AttributeImage" value="icons\k\attribute_luck.dds"/>
|
|
||||||
<Property key="Caption" value="#{sAttributeLuck}"/>
|
|
||||||
</Widget>
|
|
||||||
<Widget type="AutoSizedTextBox" skin="SandText" name="AttribVal8">
|
|
||||||
</Widget>
|
|
||||||
</Widget>
|
|
||||||
</Widget>
|
</Widget>
|
||||||
|
|
||||||
<Widget type="HBox" skin="" position="0 0 330 24">
|
<Widget type="HBox" skin="" position="0 0 330 24">
|
||||||
|
|
|
@ -113,120 +113,8 @@
|
||||||
</Widget>
|
</Widget>
|
||||||
|
|
||||||
<Widget type="Widget" skin="MW_Box" position="8 148 212 152" align="Left Top Stretch">
|
<Widget type="Widget" skin="MW_Box" position="8 148 212 152" align="Left Top Stretch">
|
||||||
<!-- TODO: this should be a scroll view -->
|
<!-- TODO: this should be a scroll view -->
|
||||||
<Widget type="Widget" skin="" position="4 4 204 144" align="Left Top Stretch">
|
<Widget type="Widget" skin="" position="4 4 204 144" align="Left Top Stretch" name="AttributeView" />
|
||||||
<Widget type="Button" skin="" position="0 0 204 18" name="Attrib1Box" align="Left Top HStretch">
|
|
||||||
<UserString key="ToolTipType" value="Layout"/>
|
|
||||||
<UserString key="ToolTipLayout" value="AttributeToolTip"/>
|
|
||||||
<UserString key="Caption_AttributeName" value="#{sAttributeStrength}"/>
|
|
||||||
<UserString key="Caption_AttributeDescription" value="#{sStrDesc}"/>
|
|
||||||
<UserString key="ImageTexture_AttributeImage" value="icons\k\attribute_strength.dds"/>
|
|
||||||
<Widget type="TextBox" skin="SandText" position="0 0 160 18" name="Attrib1" align="Left Top HStretch">
|
|
||||||
<Property key="NeedMouse" value="false"/>
|
|
||||||
</Widget>
|
|
||||||
<Widget type="TextBox" skin="SandTextRight" position="160 0 44 18" name="AttribVal1" align="Right Top">
|
|
||||||
<Property key="NeedMouse" value="false"/>
|
|
||||||
</Widget>
|
|
||||||
</Widget>
|
|
||||||
|
|
||||||
<Widget type="Button" skin="" position="0 18 204 18" name="Attrib2Box" align="Left Top HStretch">
|
|
||||||
<UserString key="ToolTipType" value="Layout"/>
|
|
||||||
<UserString key="ToolTipLayout" value="AttributeToolTip"/>
|
|
||||||
<UserString key="Caption_AttributeName" value="#{sAttributeIntelligence}"/>
|
|
||||||
<UserString key="Caption_AttributeDescription" value="#{sIntDesc}"/>
|
|
||||||
<UserString key="ImageTexture_AttributeImage" value="icons\k\attribute_int.dds"/>
|
|
||||||
<Widget type="TextBox" skin="SandText" position="0 0 160 18" name="Attrib2" align="Left Top HStretch">
|
|
||||||
<Property key="NeedMouse" value="false"/>
|
|
||||||
</Widget>
|
|
||||||
<Widget type="TextBox" skin="SandTextRight" position="160 0 44 18" name="AttribVal2" align="Right Top">
|
|
||||||
<Property key="NeedMouse" value="false"/>
|
|
||||||
</Widget>
|
|
||||||
</Widget>
|
|
||||||
|
|
||||||
<Widget type="Button" skin="" position="0 36 204 18" name="Attrib3Box" align="Left Top HStretch">
|
|
||||||
<UserString key="ToolTipType" value="Layout"/>
|
|
||||||
<UserString key="ToolTipLayout" value="AttributeToolTip"/>
|
|
||||||
<UserString key="Caption_AttributeName" value="#{sAttributeWillpower}"/>
|
|
||||||
<UserString key="Caption_AttributeDescription" value="#{sWilDesc}"/>
|
|
||||||
<UserString key="ImageTexture_AttributeImage" value="icons\k\attribute_wilpower.dds"/>
|
|
||||||
<Widget type="TextBox" skin="SandText" position="0 0 160 18" name="Attrib3" align="Left Top HStretch">
|
|
||||||
<Property key="NeedMouse" value="false"/>
|
|
||||||
</Widget>
|
|
||||||
<Widget type="TextBox" skin="SandTextRight" position="160 0 44 18" name="AttribVal3" align="Right Top">
|
|
||||||
<Property key="NeedMouse" value="false"/>
|
|
||||||
</Widget>
|
|
||||||
</Widget>
|
|
||||||
|
|
||||||
<Widget type="Button" skin="" position="0 54 204 18" name="Attrib4Box" align="Left Top HStretch">
|
|
||||||
<UserString key="ToolTipType" value="Layout"/>
|
|
||||||
<UserString key="ToolTipLayout" value="AttributeToolTip"/>
|
|
||||||
<UserString key="Caption_AttributeName" value="#{sAttributeAgility}"/>
|
|
||||||
<UserString key="Caption_AttributeDescription" value="#{sAgiDesc}"/>
|
|
||||||
<UserString key="ImageTexture_AttributeImage" value="icons\k\attribute_agility.dds"/>
|
|
||||||
<Widget type="TextBox" skin="SandText" position="0 0 160 18" name="Attrib4" align="Left Top HStretch">
|
|
||||||
<Property key="NeedMouse" value="false"/>
|
|
||||||
</Widget>
|
|
||||||
<Widget type="TextBox" skin="SandTextRight" position="160 0 44 18" name="AttribVal4" align="Right Top">
|
|
||||||
<Property key="NeedMouse" value="false"/>
|
|
||||||
</Widget>
|
|
||||||
</Widget>
|
|
||||||
|
|
||||||
<Widget type="Button" skin="" position="0 72 204 18" name="Attrib5Box" align="Left Top HStretch">
|
|
||||||
<UserString key="ToolTipType" value="Layout"/>
|
|
||||||
<UserString key="ToolTipLayout" value="AttributeToolTip"/>
|
|
||||||
<UserString key="Caption_AttributeName" value="#{sAttributeSpeed}"/>
|
|
||||||
<UserString key="Caption_AttributeDescription" value="#{sSpdDesc}"/>
|
|
||||||
<UserString key="ImageTexture_AttributeImage" value="icons\k\attribute_speed.dds"/>
|
|
||||||
<Widget type="TextBox" skin="SandText" position="0 0 160 18" name="Attrib5" align="Left Top HStretch">
|
|
||||||
<Property key="NeedMouse" value="false"/>
|
|
||||||
</Widget>
|
|
||||||
<Widget type="TextBox" skin="SandTextRight" position="160 0 44 18" name="AttribVal5" align="Right Top">
|
|
||||||
<Property key="NeedMouse" value="false"/>
|
|
||||||
</Widget>
|
|
||||||
</Widget>
|
|
||||||
|
|
||||||
<Widget type="Button" skin="" position="0 90 204 18" name="Attrib6Box" align="Left Top HStretch">
|
|
||||||
<UserString key="ToolTipType" value="Layout"/>
|
|
||||||
<UserString key="ToolTipLayout" value="AttributeToolTip"/>
|
|
||||||
<UserString key="Caption_AttributeName" value="#{sAttributeEndurance}"/>
|
|
||||||
<UserString key="Caption_AttributeDescription" value="#{sEndDesc}"/>
|
|
||||||
<UserString key="ImageTexture_AttributeImage" value="icons\k\attribute_endurance.dds"/>
|
|
||||||
<Widget type="TextBox" skin="SandText" position="0 0 160 18" name="Attrib6" align="Left Top HStretch">
|
|
||||||
<Property key="NeedMouse" value="false"/>
|
|
||||||
</Widget>
|
|
||||||
<Widget type="TextBox" skin="SandTextRight" position="160 0 44 18" name="AttribVal6" align="Right Top">
|
|
||||||
<Property key="NeedMouse" value="false"/>
|
|
||||||
</Widget>
|
|
||||||
</Widget>
|
|
||||||
|
|
||||||
<Widget type="Button" skin="" position="0 108 204 18" name="Attrib7Box" align="Left Top HStretch">
|
|
||||||
<UserString key="ToolTipType" value="Layout"/>
|
|
||||||
<UserString key="ToolTipLayout" value="AttributeToolTip"/>
|
|
||||||
<UserString key="Caption_AttributeName" value="#{sAttributePersonality}"/>
|
|
||||||
<UserString key="Caption_AttributeDescription" value="#{sPerDesc}"/>
|
|
||||||
<UserString key="ImageTexture_AttributeImage" value="icons\k\attribute_personality.dds"/>
|
|
||||||
<Widget type="TextBox" skin="SandText" position="0 0 160 18" name="Attrib7" align="Left Top HStretch">
|
|
||||||
<Property key="NeedMouse" value="false"/>
|
|
||||||
</Widget>
|
|
||||||
<Widget type="TextBox" skin="SandTextRight" position="160 0 44 18" name="AttribVal7" align="Right Top">
|
|
||||||
<Property key="NeedMouse" value="false"/>
|
|
||||||
</Widget>
|
|
||||||
</Widget>
|
|
||||||
|
|
||||||
<Widget type="Button" skin="" position="0 126 204 18" name="Attrib8Box" align="Left Top HStretch">
|
|
||||||
<UserString key="ToolTipType" value="Layout"/>
|
|
||||||
<UserString key="ToolTipLayout" value="AttributeToolTip"/>
|
|
||||||
<UserString key="Caption_AttributeName" value="#{sAttributeLuck}"/>
|
|
||||||
<UserString key="Caption_AttributeDescription" value="#{sLucDesc}"/>
|
|
||||||
<UserString key="ImageTexture_AttributeImage" value="icons\k\attribute_luck.dds"/>
|
|
||||||
<Widget type="TextBox" skin="SandText" position="0 0 160 18" name="Attrib8" align="Left Top HStretch">
|
|
||||||
<Property key="NeedMouse" value="false"/>
|
|
||||||
</Widget>
|
|
||||||
<Widget type="TextBox" skin="SandTextRight" position="160 0 44 18" name="AttribVal8" align="Right Top">
|
|
||||||
<Property key="NeedMouse" value="false"/>
|
|
||||||
</Widget>
|
|
||||||
</Widget>
|
|
||||||
</Widget>
|
|
||||||
</Widget>
|
</Widget>
|
||||||
|
|
||||||
</Widget>
|
</Widget>
|
||||||
|
|
Loading…
Reference in a new issue