Merge branch 'clickbait' into 'master'

Use std::array in various ESM structs

See merge request OpenMW/openmw!3103
macos_ci
psi29a 11 months ago
commit 25c1e6abee

@ -622,18 +622,15 @@ namespace EsmTool
std::cout << " Description: " << mData.mDescription << std::endl;
std::cout << " Playable: " << mData.mData.mIsPlayable << std::endl;
std::cout << " AI Services: " << Misc::StringUtils::format("0x%08X", mData.mData.mServices) << std::endl;
std::cout << " Attribute1: " << attributeLabel(mData.mData.mAttribute[0]) << " (" << mData.mData.mAttribute[0]
<< ")" << std::endl;
std::cout << " Attribute2: " << attributeLabel(mData.mData.mAttribute[1]) << " (" << mData.mData.mAttribute[1]
<< ")" << std::endl;
for (size_t i = 0; i < mData.mData.mAttribute.size(); ++i)
std::cout << " Attribute" << (i + 1) << ": " << attributeLabel(mData.mData.mAttribute[i]) << " ("
<< mData.mData.mAttribute[i] << ")" << std::endl;
std::cout << " Specialization: " << specializationLabel(mData.mData.mSpecialization) << " ("
<< mData.mData.mSpecialization << ")" << std::endl;
for (int i = 0; i != 5; i++)
std::cout << " Minor Skill: " << skillLabel(mData.mData.mSkills[i][0]) << " (" << mData.mData.mSkills[i][0]
<< ")" << std::endl;
for (int i = 0; i != 5; i++)
std::cout << " Major Skill: " << skillLabel(mData.mData.mSkills[i][1]) << " (" << mData.mData.mSkills[i][1]
<< ")" << std::endl;
for (const auto& skills : mData.mData.mSkills)
std::cout << " Minor Skill: " << skillLabel(skills[0]) << " (" << skills[0] << ")" << std::endl;
for (const auto& skills : mData.mData.mSkills)
std::cout << " Major Skill: " << skillLabel(skills[1]) << " (" << skills[1] << ")" << std::endl;
std::cout << " Deleted: " << mIsDeleted << std::endl;
}
@ -778,14 +775,13 @@ namespace EsmTool
{
std::cout << " Name: " << mData.mName << std::endl;
std::cout << " Hidden: " << mData.mData.mIsHidden << std::endl;
std::cout << " Attribute1: " << attributeLabel(mData.mData.mAttribute[0]) << " (" << mData.mData.mAttribute[0]
<< ")" << std::endl;
std::cout << " Attribute2: " << attributeLabel(mData.mData.mAttribute[1]) << " (" << mData.mData.mAttribute[1]
<< ")" << std::endl;
for (size_t i = 0; i < mData.mData.mAttribute.size(); ++i)
std::cout << " Attribute" << (i + 1) << ": " << attributeLabel(mData.mData.mAttribute[i]) << " ("
<< mData.mData.mAttribute[i] << ")" << std::endl;
for (int skill : mData.mData.mSkills)
if (skill != -1)
std::cout << " Skill: " << skillLabel(skill) << " (" << skill << ")" << std::endl;
for (int i = 0; i != 10; i++)
for (size_t i = 0; i != mData.mData.mRankData.size(); i++)
if (!mData.mRanks[i].empty())
{
std::cout << " Rank: " << mData.mRanks[i] << std::endl;
@ -1104,8 +1100,8 @@ namespace EsmTool
std::cout << " Luck: " << (int)mData.mNpdt.mLuck << std::endl;
std::cout << " Skills:" << std::endl;
for (int i = 0; i != ESM::Skill::Length; i++)
std::cout << " " << skillLabel(i) << ": " << (int)(mData.mNpdt.mSkills[i]) << std::endl;
for (size_t i = 0; i != mData.mNpdt.mSkills.size(); i++)
std::cout << " " << skillLabel(i) << ": " << int(mData.mNpdt.mSkills[i]) << std::endl;
std::cout << " Health: " << mData.mNpdt.mHealth << std::endl;
std::cout << " Magicka: " << mData.mNpdt.mMana << std::endl;
@ -1188,7 +1184,7 @@ namespace EsmTool
std::cout << (male ? " Male:" : " Female:") << std::endl;
for (int j = 0; j < 8; ++j)
for (int j = 0; j < ESM::Attribute::Length; ++j)
std::cout << " " << sAttributeNames[j] << ": " << mData.mData.mAttributeValues[j].getValue(male)
<< std::endl;
@ -1196,11 +1192,11 @@ namespace EsmTool
std::cout << " Weight: " << mData.mData.mWeight.getValue(male) << std::endl;
}
for (int i = 0; i != 7; i++)
for (const auto& bonus : mData.mData.mBonus)
// Not all races have 7 skills.
if (mData.mData.mBonus[i].mSkill != -1)
std::cout << " Skill: " << skillLabel(mData.mData.mBonus[i].mSkill) << " ("
<< mData.mData.mBonus[i].mSkill << ") = " << mData.mData.mBonus[i].mBonus << std::endl;
if (bonus.mSkill != -1)
std::cout << " Skill: " << skillLabel(bonus.mSkill) << " (" << bonus.mSkill << ") = " << bonus.mBonus
<< std::endl;
for (const auto& power : mData.mPowers.mList)
std::cout << " Power: " << power << std::endl;

@ -249,7 +249,7 @@ namespace ESSImport
{
ESM::InventoryState& invState = mContext->mPlayer.mObject.mInventory;
for (unsigned int i = 0; i < invState.mItems.size(); ++i)
for (size_t i = 0; i < invState.mItems.size(); ++i)
{
// FIXME: in case of conflict (multiple items with this refID) use the already equipped one?
if (invState.mItems[i].mRef.mRefID == ESM::RefId::stringRefId(refr.mActorData.mSelectedEnchantItem))

@ -25,11 +25,11 @@ namespace ESSImport
faction.mReputation = essFaction.mReputation;
out.mObject.mNpcStats.mFactions[ESM::RefId::stringRefId(essFaction.mFactionName.toString())] = faction;
}
for (int i = 0; i < 3; ++i)
for (size_t i = 0; i < out.mObject.mNpcStats.mSpecIncreases.size(); ++i)
out.mObject.mNpcStats.mSpecIncreases[i] = pcdt.mPNAM.mSpecIncreases[i];
for (int i = 0; i < 8; ++i)
for (size_t i = 0; i < out.mObject.mNpcStats.mSkillIncrease.size(); ++i)
out.mObject.mNpcStats.mSkillIncrease[i] = pcdt.mPNAM.mSkillIncreases[i];
for (int i = 0; i < 27; ++i)
for (size_t i = 0; i < out.mObject.mNpcStats.mSkills.size(); ++i)
out.mObject.mNpcStats.mSkills[i].mProgress = pcdt.mPNAM.mSkillProgress[i];
out.mObject.mNpcStats.mLevelProgress = pcdt.mPNAM.mLevelProgress;

@ -162,7 +162,7 @@ namespace ESSImport
read(mOutFile, file2); // todo rename variable
// FIXME: use max(size1, size2)
for (unsigned int i = 0; i < file1.mRecords.size(); ++i)
for (size_t i = 0; i < file1.mRecords.size(); ++i)
{
File::Record rec = file1.mRecords[i];
@ -185,7 +185,7 @@ namespace ESSImport
}
// FIXME: use max(size1, size2)
for (unsigned int j = 0; j < rec.mSubrecords.size(); ++j)
for (size_t j = 0; j < rec.mSubrecords.size(); ++j)
{
File::Subrecord sub = rec.mSubrecords[j];
@ -221,7 +221,7 @@ namespace ESSImport
<< std::hex << sub.mFileOffset << " (2) 0x" << sub2.mFileOffset << std::endl;
std::cout << "Data 1:" << std::endl;
for (unsigned int k = 0; k < sub.mData.size(); ++k)
for (size_t k = 0; k < sub.mData.size(); ++k)
{
bool different = false;
if (k >= sub2.mData.size() || sub2.mData[k] != sub.mData[k])
@ -236,7 +236,7 @@ namespace ESSImport
std::cout << std::endl;
std::cout << "Data 2:" << std::endl;
for (unsigned int k = 0; k < sub2.mData.size(); ++k)
for (size_t k = 0; k < sub2.mData.size(); ++k)
{
bool different = false;
if (k >= sub.mData.size() || sub.mData[k] != sub2.mData[k])

@ -82,9 +82,9 @@ std::pair<QWidget*, QWidget*> CSMPrefs::EnumSetting::makeWidgets(QWidget* parent
mWidget = new QComboBox(parent);
int index = 0;
size_t index = 0;
for (int i = 0; i < static_cast<int>(mValues.mValues.size()); ++i)
for (size_t i = 0; i < mValues.mValues.size(); ++i)
{
if (mDefault.mValue == mValues.mValues[i].mValue)
index = i;
@ -95,7 +95,7 @@ std::pair<QWidget*, QWidget*> CSMPrefs::EnumSetting::makeWidgets(QWidget* parent
mWidget->setItemData(i, QString::fromUtf8(mValues.mValues[i].mTooltip.c_str()), Qt::ToolTipRole);
}
mWidget->setCurrentIndex(index);
mWidget->setCurrentIndex(static_cast<int>(index));
if (!mTooltip.empty())
{

@ -50,23 +50,32 @@ void CSMTools::ClassCheckStage::perform(int stage, CSMDoc::Messages& messages)
messages.add(id, "Description of a playable class is missing", "", CSMDoc::Message::Severity_Warning);
// test for invalid attributes
for (int i = 0; i < 2; ++i)
if (class_.mData.mAttribute[i] == -1)
std::map<int, int> attributeCount;
for (size_t i = 0; i < class_.mData.mAttribute.size(); ++i)
{
int attribute = class_.mData.mAttribute[i];
if (attribute == -1)
messages.add(id, "Attribute #" + std::to_string(i) + " is not set", {}, CSMDoc::Message::Severity_Error);
else
{
messages.add(id, "Attribute #" + std::to_string(i) + " is not set", "", CSMDoc::Message::Severity_Error);
auto it = attributeCount.find(attribute);
if (it == attributeCount.end())
attributeCount.emplace(attribute, 1);
else
{
if (it->second == 1)
messages.add(id, "Same attribute is listed twice", {}, CSMDoc::Message::Severity_Error);
++it->second;
}
}
if (class_.mData.mAttribute[0] == class_.mData.mAttribute[1] && class_.mData.mAttribute[0] != -1)
{
messages.add(id, "Same attribute is listed twice", "", CSMDoc::Message::Severity_Error);
}
// test for non-unique skill
std::map<int, int> skills; // ID, number of occurrences
for (int i = 0; i < 5; ++i)
for (int i2 = 0; i2 < 2; ++i2)
++skills[class_.mData.mSkills[i][i2]];
for (const auto& s : class_.mData.mSkills)
for (int skill : s)
++skills[skill];
for (auto& skill : skills)
if (skill.second > 1)

@ -46,17 +46,30 @@ void CSMTools::FactionCheckStage::perform(int stage, CSMDoc::Messages& messages)
messages.add(id, "Name is missing", "", CSMDoc::Message::Severity_Error);
// test for invalid attributes
if (faction.mData.mAttribute[0] == faction.mData.mAttribute[1] && faction.mData.mAttribute[0] != -1)
std::map<int, int> attributeCount;
for (size_t i = 0; i < faction.mData.mAttribute.size(); ++i)
{
messages.add(id, "Same attribute is listed twice", "", CSMDoc::Message::Severity_Error);
int attribute = faction.mData.mAttribute[i];
if (attribute != -1)
{
auto it = attributeCount.find(attribute);
if (it == attributeCount.end())
attributeCount.emplace(attribute, 1);
else
{
if (it->second == 1)
messages.add(id, "Same attribute is listed twice", {}, CSMDoc::Message::Severity_Error);
++it->second;
}
}
}
// test for non-unique skill
std::map<int, int> skills; // ID, number of occurrences
for (int i = 0; i < 7; ++i)
if (faction.mData.mSkills[i] != -1)
++skills[faction.mData.mSkills[i]];
for (int skill : faction.mData.mSkills)
if (skill != -1)
++skills[skill];
for (auto& skill : skills)
if (skill.second > 1)

@ -1039,14 +1039,14 @@ void CSMTools::ReferenceableCheckStage::listCheck(
someID, "Chance that no object is used is over 100 percent", "", CSMDoc::Message::Severity_Warning);
}
for (unsigned i = 0; i < someList.mList.size(); ++i)
for (const auto& element : someList.mList)
{
if (mReferencables.searchId(someList.mList[i].mId).first == -1)
messages.add(someID, "Object '" + someList.mList[i].mId.getRefIdString() + "' does not exist", "",
if (mReferencables.searchId(element.mId).first == -1)
messages.add(someID, "Object '" + element.mId.getRefIdString() + "' does not exist", "",
CSMDoc::Message::Severity_Error);
if (someList.mList[i].mLevel < 1)
messages.add(someID, "Level of item '" + someList.mList[i].mId.getRefIdString() + "' is non-positive", "",
if (element.mLevel < 1)
messages.add(someID, "Level of item '" + element.mId.getRefIdString() + "' is non-positive", "",
CSMDoc::Message::Severity_Error);
}
}

@ -134,9 +134,9 @@ CSMWorld::NestableColumn::NestableColumn(int columnId, CSMWorld::ColumnBase::Dis
CSMWorld::NestableColumn::~NestableColumn()
{
for (unsigned int i = 0; i < mNestedColumns.size(); ++i)
for (auto* col : mNestedColumns)
{
delete mNestedColumns[i];
delete col;
}
}

@ -1026,12 +1026,12 @@ int CSMWorld::Data::getTotalRecords(const std::vector<std::filesystem::path>& fi
std::unique_ptr<ESM::ESMReader> reader = std::make_unique<ESM::ESMReader>();
for (unsigned int i = 0; i < files.size(); ++i)
for (const auto& file : files)
{
if (!std::filesystem::exists(files[i]))
if (!std::filesystem::exists(file))
continue;
reader->open(files[i]);
reader->open(file);
records += reader->getRecordCount();
reader->close();
}

@ -825,8 +825,7 @@ namespace CSMWorld
{
ESM::Race race = record.get();
if (subRowIndex < 0
|| subRowIndex >= static_cast<int>(sizeof(race.mData.mBonus) / sizeof(race.mData.mBonus[0])))
if (subRowIndex < 0 || static_cast<size_t>(subRowIndex) >= race.mData.mBonus.size())
throw std::runtime_error("index out of range");
switch (subColIndex)
@ -845,8 +844,7 @@ namespace CSMWorld
{
ESM::Race race = record.get();
if (subRowIndex < 0
|| subRowIndex >= static_cast<int>(sizeof(race.mData.mBonus) / sizeof(race.mData.mBonus[0])))
if (subRowIndex < 0 || static_cast<size_t>(subRowIndex) >= race.mData.mBonus.size())
throw std::runtime_error("index out of range");
switch (subColIndex)
@ -871,8 +869,7 @@ namespace CSMWorld
int RaceSkillsBonusAdapter::getRowsCount(const Record<ESM::Race>& record) const
{
// there are 7 skill bonuses
return static_cast<int>(sizeof(record.get().mData.mBonus) / sizeof(record.get().mData.mBonus[0]));
return record.get().mData.mBonus.size();
}
void CellListAdapter::addRow(Record<CSMWorld::Cell>& record, int position) const
@ -1189,13 +1186,9 @@ namespace CSMWorld
QVariant FactionRanksAdapter::getData(const Record<ESM::Faction>& record, int subRowIndex, int subColIndex) const
{
ESM::Faction faction = record.get();
if (subRowIndex < 0
|| subRowIndex >= static_cast<int>(sizeof(faction.mData.mRankData) / sizeof(faction.mData.mRankData[0])))
throw std::runtime_error("index out of range");
const ESM::Faction& faction = record.get();
auto& rankData = faction.mData.mRankData[subRowIndex];
const auto& rankData = faction.mData.mRankData.at(subRowIndex);
switch (subColIndex)
{
@ -1221,11 +1214,7 @@ namespace CSMWorld
{
ESM::Faction faction = record.get();
if (subRowIndex < 0
|| subRowIndex >= static_cast<int>(sizeof(faction.mData.mRankData) / sizeof(faction.mData.mRankData[0])))
throw std::runtime_error("index out of range");
auto& rankData = faction.mData.mRankData[subRowIndex];
auto& rankData = faction.mData.mRankData.at(subRowIndex);
switch (subColIndex)
{

@ -45,21 +45,21 @@ std::string CSMWorld::TableMimeData::getIcon() const
std::string tmpIcon;
bool firstIteration = true;
for (unsigned i = 0; i < mUniversalId.size(); ++i)
for (const auto& id : mUniversalId)
{
if (firstIteration)
{
firstIteration = false;
tmpIcon = mUniversalId[i].getIcon();
tmpIcon = id.getIcon();
continue;
}
if (tmpIcon != mUniversalId[i].getIcon())
if (tmpIcon != id.getIcon())
{
return ":/multitype.png"; // icon stolen from gnome TODO: get new icon
}
tmpIcon = mUniversalId[i].getIcon();
tmpIcon = id.getIcon();
}
return mUniversalId.begin()->getIcon(); // All objects are of the same type;

@ -698,9 +698,9 @@ bool CSVRender::PagedWorldspaceWidget::handleDrop(
return false;
bool selectionChanged = false;
for (unsigned i = 0; i < universalIdData.size(); ++i)
for (const auto& id : universalIdData)
{
std::pair<int, int> coordinates(getCoordinatesFromId(universalIdData[i].getId()));
std::pair<int, int> coordinates(getCoordinatesFromId(id.getId()));
if (mSelection.add(CSMWorld::CellCoordinates(coordinates.first, coordinates.second)))
{
selectionChanged = true;

@ -347,10 +347,10 @@ namespace CSVRender
QModelIndex parent = model->index(recordIndex, parentColumn);
for (size_t i = 0; i < mSelected.size(); ++i)
for (const auto& selected : mSelected)
{
const CSMWorld::Pathgrid::Point& point = source->mPoints[mSelected[i]];
int row = static_cast<int>(mSelected[i]);
const CSMWorld::Pathgrid::Point& point = source->mPoints[selected];
int row = static_cast<int>(selected);
commands.push(new CSMWorld::ModifyCommand(
*model, model->index(row, posXColumn, parent), clampToCell(point.mX + offsetX)));
@ -378,9 +378,9 @@ namespace CSVRender
const CSMWorld::Pathgrid* source = getPathgridSource();
if (source)
{
for (size_t i = 0; i < mSelected.size(); ++i)
for (const auto& selected : mSelected)
{
addEdge(commands, *source, node, mSelected[i]);
addEdge(commands, *source, node, selected);
}
}
}

@ -227,11 +227,11 @@ void CSVWorld::DialogueDelegateDispatcher::setEditorData(QWidget* editor, const
delegateIt->second->setEditorData(editor, index, true);
}
for (unsigned i = 0; i < mProxys.size(); ++i)
for (const auto& proxy : mProxys)
{
if (mProxys[i]->getEditor() == editor)
if (proxy->getEditor() == editor)
{
mProxys[i]->setIndex(index);
proxy->setIndex(index);
}
}
}
@ -341,9 +341,9 @@ QWidget* CSVWorld::DialogueDelegateDispatcher::makeEditor(
CSVWorld::DialogueDelegateDispatcher::~DialogueDelegateDispatcher()
{
for (unsigned i = 0; i < mProxys.size(); ++i)
for (auto* proxy : mProxys)
{
delete mProxys[i]; // unique_ptr could be handy
delete proxy; // unique_ptr could be handy
}
}
@ -477,8 +477,8 @@ void CSVWorld::EditWidget::createEditorContextMenu(
CSVWorld::EditWidget::~EditWidget()
{
for (unsigned i = 0; i < mNestedModels.size(); ++i)
delete mNestedModels[i];
for (auto* model : mNestedModels)
delete model;
if (mDispatcher)
delete mDispatcher;
@ -511,8 +511,8 @@ void CSVWorld::EditWidget::remake(int row)
}
mMainWidget = new QWidget(this);
for (unsigned i = 0; i < mNestedModels.size(); ++i)
delete mNestedModels[i];
for (auto* model : mNestedModels)
delete model;
mNestedModels.clear();

@ -611,7 +611,7 @@ void CSVWorld::Table::moveRecords(QDropEvent* event)
std::vector<int> newOrder(highestDifference + 1);
for (long unsigned int i = 0; i < newOrder.size(); ++i)
for (int i = 0; i <= highestDifference; ++i)
{
newOrder[i] = i;
}

@ -98,10 +98,9 @@ namespace
// class bonus
const ESM::Class* class_ = MWBase::Environment::get().getESMStore()->get<ESM::Class>().find(npc->mClass);
for (int i = 0; i < 2; ++i)
for (int attribute : class_->mData.mAttribute)
{
int attribute = class_->mData.mAttribute[i];
if (attribute >= 0 && attribute < 8)
if (attribute >= 0 && attribute < ESM::Attribute::Length)
{
creatureStats.setAttribute(attribute, creatureStats.getAttribute(attribute).getBase() + 10);
}
@ -121,14 +120,11 @@ namespace
// is this a minor or major skill?
float add = 0.2f;
for (int k = 0; k < 5; ++k)
for (const auto& skills : class_->mData.mSkills)
{
if (class_->mData.mSkills[k][0] == j)
if (skills[0] == j)
add = 0.5;
}
for (int k = 0; k < 5; ++k)
{
if (class_->mData.mSkills[k][1] == j)
if (skills[1] == j)
add = 1.0;
}
modifierSum += add;
@ -149,8 +145,8 @@ namespace
else if (class_->mData.mSpecialization == ESM::Class::Stealth)
multiplier += 1;
if (class_->mData.mAttribute[0] == ESM::Attribute::Endurance
|| class_->mData.mAttribute[1] == ESM::Attribute::Endurance)
if (std::find(class_->mData.mAttribute.begin(), class_->mData.mAttribute.end(), ESM::Attribute::Endurance)
!= class_->mData.mAttribute.end())
multiplier += 1;
creatureStats.setHealth(floor(0.5f * (strength + endurance)) + multiplier * (creatureStats.getLevel() - 1));
@ -183,9 +179,9 @@ namespace
{
int bonus = (i == 0) ? 10 : 25;
for (int i2 = 0; i2 < 5; ++i2)
for (const auto& skills : class_->mData.mSkills)
{
int index = class_->mData.mSkills[i2][i];
int index = skills[i];
if (index >= 0 && index < ESM::Skill::Length)
{
npcStats.getSkill(index).setBase(npcStats.getSkill(index).getBase() + bonus);
@ -201,19 +197,15 @@ namespace
int raceBonus = 0;
int specBonus = 0;
for (int raceSkillIndex = 0; raceSkillIndex < 7; ++raceSkillIndex)
{
if (race->mData.mBonus[raceSkillIndex].mSkill == skillIndex)
{
raceBonus = race->mData.mBonus[raceSkillIndex].mBonus;
break;
}
}
auto bonusIt = std::find_if(race->mData.mBonus.begin(), race->mData.mBonus.end(),
[skillIndex](const auto& bonus) { return bonus.mSkill == skillIndex; });
if (bonusIt != race->mData.mBonus.end())
raceBonus = bonusIt->mBonus;
for (int k = 0; k < 5; ++k)
for (const auto& skills : class_->mData.mSkills)
{
// is this a minor or major skill?
if ((class_->mData.mSkills[k][0] == skillIndex) || (class_->mData.mSkills[k][1] == skillIndex))
if (std::find(skills.begin(), skills.end(), skillIndex) != skills.end())
{
majorMultiplier = 1.0f;
break;
@ -322,7 +314,7 @@ namespace MWClass
{
gold = ref->mBase->mNpdt.mGold;
for (unsigned int i = 0; i < ESM::Skill::Length; ++i)
for (size_t i = 0; i < ref->mBase->mNpdt.mSkills.size(); ++i)
data->mNpcStats.getSkill(i).setBase(ref->mBase->mNpdt.mSkills[i]);
data->mNpcStats.setAttribute(ESM::Attribute::Strength, ref->mBase->mNpdt.mStrength);

@ -108,7 +108,7 @@ namespace MWClass
// hide effects the player doesn't know about
MWWorld::Ptr player = MWBase::Environment::get().getWorld()->getPlayerPtr();
for (unsigned int i = 0; i < info.effects.size(); ++i)
for (size_t i = 0; i < info.effects.size(); ++i)
info.effects[i].mKnown = MWMechanics::Alchemy::knownEffect(i, player);
info.isPotion = true;

@ -644,9 +644,6 @@ int MWDialogue::Filter::getFactionRank(const MWWorld::Ptr& actor, const ESM::Ref
bool MWDialogue::Filter::hasFactionRankSkillRequirements(
const MWWorld::Ptr& actor, const ESM::RefId& factionId, int rank) const
{
if (rank < 0 || rank >= 10)
throw std::runtime_error("rank index out of range");
if (!actor.getClass().getNpcStats(actor).hasSkillsForRank(factionId, rank))
return false;
@ -661,14 +658,11 @@ bool MWDialogue::Filter::hasFactionRankSkillRequirements(
bool MWDialogue::Filter::hasFactionRankReputationRequirements(
const MWWorld::Ptr& actor, const ESM::RefId& factionId, int rank) const
{
if (rank < 0 || rank >= 10)
throw std::runtime_error("rank index out of range");
MWMechanics::NpcStats& stats = actor.getClass().getNpcStats(actor);
const ESM::Faction& faction = *MWBase::Environment::get().getESMStore()->get<ESM::Faction>().find(factionId);
return stats.getFactionReputation(factionId) >= faction.mData.mRankData[rank].mFactReaction;
return stats.getFactionReputation(factionId) >= faction.mData.mRankData.at(rank).mFactReaction;
}
MWDialogue::Filter::Filter(const MWWorld::Ptr& actor, int choice, bool talkedToPlayer)

@ -473,15 +473,14 @@ namespace MWGui
klass.mRecordFlags = 0;
std::vector<int> attributes = mCreateClassDialog->getFavoriteAttributes();
assert(attributes.size() == 2);
klass.mData.mAttribute[0] = attributes[0];
klass.mData.mAttribute[1] = attributes[1];
assert(attributes.size() == klass.mData.mAttribute.size());
std::copy(attributes.begin(), attributes.end(), klass.mData.mAttribute.begin());
std::vector<ESM::Skill::SkillEnum> majorSkills = mCreateClassDialog->getMajorSkills();
std::vector<ESM::Skill::SkillEnum> minorSkills = mCreateClassDialog->getMinorSkills();
assert(majorSkills.size() >= sizeof(klass.mData.mSkills) / sizeof(klass.mData.mSkills[0]));
assert(minorSkills.size() >= sizeof(klass.mData.mSkills) / sizeof(klass.mData.mSkills[0]));
for (size_t i = 0; i < sizeof(klass.mData.mSkills) / sizeof(klass.mData.mSkills[0]); ++i)
assert(majorSkills.size() >= klass.mData.mSkills.size());
assert(minorSkills.size() >= klass.mData.mSkills.size());
for (size_t i = 0; i < klass.mData.mSkills.size(); ++i)
{
klass.mData.mSkills[i][1] = majorSkills[i];
klass.mData.mSkills[i][0] = minorSkills[i];

@ -264,7 +264,7 @@ namespace MWGui
ToolTips::createAttributeToolTip(mFavoriteAttribute[0], mFavoriteAttribute[0]->getAttributeId());
ToolTips::createAttributeToolTip(mFavoriteAttribute[1], mFavoriteAttribute[1]->getAttributeId());
for (int i = 0; i < 5; ++i)
for (size_t i = 0; i < klass->mData.mSkills.size(); ++i)
{
mMinorSkill[i]->setSkillNumber(klass->mData.mSkills[i][0]);
mMajorSkill[i]->setSkillNumber(klass->mData.mSkills[i][1]);

@ -462,7 +462,7 @@ namespace MWGui::Formatting
mPaginator.setIgnoreLeadingEmptyLines(true);
const MyGUI::VectorLineInfo& lines = mEditBox->getSubWidgetText()->castType<MyGUI::EditText>()->getLineInfo();
for (unsigned int i = lastLine; i < lines.size(); ++i)
for (size_t i = lastLine; i < lines.size(); ++i)
{
if (lines[i].width == 0)
ret += lineHeight;

@ -163,13 +163,13 @@ namespace MWGui
setGender(proto.isMale() ? GM_Male : GM_Female);
recountParts();
for (unsigned int i = 0; i < mAvailableHeads.size(); ++i)
for (size_t i = 0; i < mAvailableHeads.size(); ++i)
{
if (mAvailableHeads[i] == proto.mHead)
mFaceIndex = i;
}
for (unsigned int i = 0; i < mAvailableHairs.size(); ++i)
for (size_t i = 0; i < mAvailableHairs.size(); ++i)
{
if (mAvailableHairs[i] == proto.mHair)
mHairIndex = i;
@ -412,20 +412,15 @@ namespace MWGui
const MWWorld::ESMStore& store = *MWBase::Environment::get().getESMStore();
const ESM::Race* race = store.get<ESM::Race>().find(mCurrentRaceId);
int count = sizeof(race->mData.mBonus)
/ sizeof(race->mData.mBonus[0]); // TODO: Find a portable macro for this ARRAYSIZE?
for (int i = 0; i < count; ++i)
for (const auto& bonus : race->mData.mBonus)
{
int skillId = race->mData.mBonus[i].mSkill;
if (skillId < 0 || skillId > ESM::Skill::Length) // Skip unknown skill indexes
if (bonus.mSkill < 0 || bonus.mSkill >= ESM::Skill::Length) // Skip unknown skill indexes
continue;
skillWidget = mSkillList->createWidget<Widgets::MWSkill>(
"MW_StatNameValue", coord1, MyGUI::Align::Default, std::string("Skill") + MyGUI::utility::toString(i));
skillWidget->setSkillNumber(skillId);
skillWidget->setSkillValue(
Widgets::MWSkill::SkillValue(static_cast<float>(race->mData.mBonus[i].mBonus), 0.f));
ToolTips::createSkillToolTip(skillWidget, skillId);
skillWidget = mSkillList->createWidget<Widgets::MWSkill>("MW_StatNameValue", coord1, MyGUI::Align::Default);
skillWidget->setSkillId(ESM::Skill::SkillEnum(bonus.mSkill));
skillWidget->setSkillValue(Widgets::MWSkill::SkillValue(static_cast<float>(bonus.mBonus), 0.f));
ToolTips::createSkillToolTip(skillWidget, bonus.mSkill);
mSkillItems.push_back(skillWidget);

@ -124,10 +124,11 @@ namespace MWGui
= MWBase::Environment::get().getESMStore()->get<ESM::Class>().find(watchedRecord->mClass);
setValue("class", cls->mName);
MWBase::WindowManager::SkillList majorSkills(5);
MWBase::WindowManager::SkillList minorSkills(5);
size_t size = cls->mData.mSkills.size();
MWBase::WindowManager::SkillList majorSkills(size);
MWBase::WindowManager::SkillList minorSkills(size);
for (int i = 0; i < 5; ++i)
for (size_t i = 0; i < size; ++i)
{
minorSkills[i] = cls->mData.mSkills[i][0];
majorSkills[i] = cls->mData.mSkills[i][1];

@ -626,7 +626,7 @@ namespace MWGui
// player doesn't have max rank yet
text += std::string("\n\n#{fontcolourhtml=header}#{sNextRank} ") + faction->mRanks[rank + 1];
ESM::RankData rankData = faction->mData.mRankData[rank + 1];
const ESM::RankData& rankData = faction->mData.mRankData[rank + 1];
const ESM::Attribute* attr1 = store.get<ESM::Attribute>().find(faction->mData.mAttribute[0]);
const ESM::Attribute* attr2 = store.get<ESM::Attribute>().find(faction->mData.mAttribute[1]);
@ -638,15 +638,15 @@ namespace MWGui
text += "\n\n#{fontcolourhtml=header}#{sFavoriteSkills}";
text += "\n#{fontcolourhtml=normal}";
bool firstSkill = true;
for (int i = 0; i < 7; ++i)
for (int id : faction->mData.mSkills)
{
if (faction->mData.mSkills[i] != -1)
if (id != -1)
{
if (!firstSkill)
text += ", ";
firstSkill = false;
const ESM::Skill* skill = store.get<ESM::Skill>().find(faction->mData.mSkills[i]);
const ESM::Skill* skill = store.get<ESM::Skill>().find(id);
text += MyGUI::TextIterator::toTagsString(skill->mName);
}
}

@ -121,19 +121,19 @@ namespace MWGui
else if (mPtr.getType() == ESM::Creature::sRecordId)
transport = mPtr.get<ESM::Creature>()->mBase->getTransport();
for (unsigned int i = 0; i < transport.size(); i++)
for (const auto& dest : transport)
{
std::string_view cellname = transport[i].mCellName;
std::string_view cellname = dest.mCellName;
bool interior = true;
const ESM::ExteriorCellLocation cellIndex
= ESM::positionToExteriorCellLocation(transport[i].mPos.pos[0], transport[i].mPos.pos[1]);
= ESM::positionToExteriorCellLocation(dest.mPos.pos[0], dest.mPos.pos[1]);
if (cellname.empty())
{
MWWorld::CellStore& cell = MWBase::Environment::get().getWorldModel()->getExterior(cellIndex);
cellname = MWBase::Environment::get().getWorld()->getCellName(&cell);
interior = false;
}
addDestination(ESM::RefId::stringRefId(cellname), transport[i].mPos, interior);
addDestination(ESM::RefId::stringRefId(cellname), dest.mPos, interior);
}
updateLabels();

@ -128,7 +128,7 @@ namespace MWMechanics
creatureStats.getSpells().clear(true);
creatureStats.getActiveSpells().clear(ptr);
for (int i = 0; i < 27; ++i)
for (size_t i = 0; i < player->mNpdt.mSkills.size(); ++i)
npcStats.getSkill(i).setBase(player->mNpdt.mSkills[i]);
creatureStats.setAttribute(ESM::Attribute::Strength, player->mNpdt.mStrength);
@ -148,7 +148,7 @@ namespace MWMechanics
bool male = (player->mFlags & ESM::NPC::Female) == 0;
for (int i = 0; i < 8; ++i)
for (int i = 0; i < ESM::Attribute::Length; ++i)
{
const ESM::Race::MaleFemale& attribute = race->mData.mAttributeValues[i];
@ -159,12 +159,10 @@ namespace MWMechanics
{
int bonus = 0;
for (int i2 = 0; i2 < 7; ++i2)
if (race->mData.mBonus[i2].mSkill == i)
{
bonus = race->mData.mBonus[i2].mBonus;
break;
}
auto bonusIt = std::find_if(race->mData.mBonus.begin(), race->mData.mBonus.end(),
[i](const auto& bonus) { return bonus.mSkill == i; });
if (bonusIt != race->mData.mBonus.end())
bonus = bonusIt->mBonus;
npcStats.getSkill(i).setBase(5 + bonus);
}
@ -193,10 +191,9 @@ namespace MWMechanics
{
const ESM::Class* class_ = esmStore.get<ESM::Class>().find(player->mClass);
for (int i = 0; i < 2; ++i)
for (int attribute : class_->mData.mAttribute)
{
int attribute = class_->mData.mAttribute[i];
if (attribute >= 0 && attribute < 8)
if (attribute >= 0 && attribute < ESM::Attribute::Length)
{
creatureStats.setAttribute(attribute, creatureStats.getAttribute(attribute).getBase() + 10);
}
@ -206,11 +203,11 @@ namespace MWMechanics
{
int bonus = i == 0 ? 10 : 25;
for (int i2 = 0; i2 < 5; ++i2)
for (const auto& skills : class_->mData.mSkills)
{
int index = class_->mData.mSkills[i2][i];
int index = skills[i];
if (index >= 0 && index < 27)
if (index >= 0 && index < ESM::Skill::Length)
{
npcStats.getSkill(index).setBase(npcStats.getSkill(index).getBase() + bonus);
}

@ -162,14 +162,14 @@ float MWMechanics::NpcStats::getSkillProgressRequirement(int skillIndex, const E
float typeFactor = gmst.find("fMiscSkillBonus")->mValue.getFloat();
for (int i = 0; i < 5; ++i)
for (const auto& skills : class_.mData.mSkills)
{
if (class_.mData.mSkills[i][0] == skillIndex)
if (skills[0] == skillIndex)
{
typeFactor = gmst.find("fMinorSkillBonus")->mValue.getFloat();
break;
}
else if (class_.mData.mSkills[i][1] == skillIndex)
else if (skills[1] == skillIndex)
{
typeFactor = gmst.find("fMajorSkillBonus")->mValue.getFloat();
break;
@ -235,15 +235,15 @@ void MWMechanics::NpcStats::increaseSkill(
// is this a minor or major skill?
int increase = gmst.find("iLevelupMiscMultAttriubte")->mValue.getInteger(); // Note: GMST has a typo
for (int k = 0; k < 5; ++k)
for (const auto& skills : class_.mData.mSkills)
{
if (class_.mData.mSkills[k][0] == skillIndex)
if (skills[0] == skillIndex)
{
mLevelProgress += gmst.find("iLevelUpMinorMult")->mValue.getInteger();
increase = gmst.find("iLevelUpMinorMultAttribute")->mValue.getInteger();
break;
}
else if (class_.mData.mSkills[k][1] == skillIndex)
else if (skills[1] == skillIndex)
{
mLevelProgress += gmst.find("iLevelUpMajorMult")->mValue.getInteger();
increase = gmst.find("iLevelUpMajorMultAttribute")->mValue.getInteger();
@ -382,17 +382,16 @@ void MWMechanics::NpcStats::setCrimeId(int id)
bool MWMechanics::NpcStats::hasSkillsForRank(const ESM::RefId& factionId, int rank) const
{
if (rank < 0 || rank >= 10)
throw std::runtime_error("rank index out of range");
const ESM::Faction& faction = *MWBase::Environment::get().getESMStore()->get<ESM::Faction>().find(factionId);
const ESM::RankData& rankData = faction.mData.mRankData.at(rank);
std::vector<int> skills;
for (int i = 0; i < 7; ++i)
for (int id : faction.mData.mSkills)
{
if (faction.mData.mSkills[i] != -1)
skills.push_back(static_cast<int>(getSkill(faction.mData.mSkills[i]).getBase()));
if (id != -1)
skills.push_back(static_cast<int>(getSkill(id).getBase()));
}
if (skills.empty())
@ -402,8 +401,6 @@ bool MWMechanics::NpcStats::hasSkillsForRank(const ESM::RefId& factionId, int ra
std::vector<int>::const_reverse_iterator iter = skills.rbegin();
const ESM::RankData& rankData = faction.mData.mRankData[rank];
if (*iter < rankData.mPrimarySkill)
return false;
@ -473,7 +470,7 @@ void MWMechanics::NpcStats::writeState(ESM::NpcStats& state) const
state.mDisposition = mDisposition;
for (int i = 0; i < ESM::Skill::Length; ++i)
for (size_t i = 0; i < state.mSkills.size(); ++i)
mSkill[i].writeState(state.mSkills[i]);
state.mIsWerewolf = mIsWerewolf;
@ -492,10 +489,10 @@ void MWMechanics::NpcStats::writeState(ESM::NpcStats& state) const
state.mWerewolfKills = mWerewolfKills;
state.mLevelProgress = mLevelProgress;
for (int i = 0; i < ESM::Attribute::Length; ++i)
for (size_t i = 0; i < state.mSkillIncrease.size(); ++i)
state.mSkillIncrease[i] = mSkillIncreases[i];
for (int i = 0; i < 3; ++i)
for (size_t i = 0; i < state.mSpecIncreases.size(); ++i)
state.mSpecIncreases[i] = mSpecIncreases[i];
std::copy(mUsedIds.begin(), mUsedIds.end(), std::back_inserter(state.mUsedIds));
@ -526,7 +523,7 @@ void MWMechanics::NpcStats::readState(const ESM::NpcStats& state)
mDisposition = state.mDisposition;
for (int i = 0; i < ESM::Skill::Length; ++i)
for (size_t i = 0; i < state.mSkills.size(); ++i)
mSkill[i].readState(state.mSkills[i]);
mIsWerewolf = state.mIsWerewolf;
@ -537,10 +534,10 @@ void MWMechanics::NpcStats::readState(const ESM::NpcStats& state)
mWerewolfKills = state.mWerewolfKills;
mLevelProgress = state.mLevelProgress;
for (int i = 0; i < ESM::Attribute::Length; ++i)
for (size_t i = 0; i < state.mSkillIncrease.size(); ++i)
mSkillIncreases[i] = state.mSkillIncrease[i];
for (int i = 0; i < 3; ++i)
for (size_t i = 0; i < state.mSpecIncreases.size(); ++i)
mSpecIncreases[i] = state.mSpecIncreases[i];
for (auto iter(state.mUsedIds.begin()); iter != state.mUsedIds.end(); ++iter)

@ -13,18 +13,12 @@ namespace ESM
int& Class::CLDTstruct::getSkill(int index, bool major)
{
if (index < 0 || index >= 5)
throw std::logic_error("skill index out of range");
return mSkills[index][major ? 1 : 0];
return mSkills.at(index)[major ? 1 : 0];
}
int Class::CLDTstruct::getSkill(int index, bool major) const
{
if (index < 0 || index >= 5)
throw std::logic_error("skill index out of range");
return mSkills[index][major ? 1 : 0];
return mSkills.at(index)[major ? 1 : 0];
}
void Class::load(ESMReader& esm, bool& isDeleted)
@ -91,13 +85,12 @@ namespace ESM
mName.clear();
mDescription.clear();
mData.mAttribute[0] = mData.mAttribute[1] = 0;
mData.mAttribute.fill(0);
mData.mSpecialization = 0;
mData.mIsPlayable = 0;
mData.mServices = 0;
for (int i = 0; i < 5; ++i)
for (int i2 = 0; i2 < 2; ++i2)
mData.mSkills[i][i2] = 0;
for (auto& skills : mData.mSkills)
skills.fill(0);
}
}

@ -1,6 +1,7 @@
#ifndef OPENMW_ESM_CLAS_H
#define OPENMW_ESM_CLAS_H
#include <array>
#include <string>
#include "components/esm/defs.hpp"
@ -33,9 +34,9 @@ namespace ESM
struct CLDTstruct
{
int mAttribute[2]; // Attributes that get class bonus
std::array<int, 2> mAttribute; // Attributes that get class bonus
int mSpecialization; // 0 = Combat, 1 = Magic, 2 = Stealth
int mSkills[5][2]; // Minor and major skills.
std::array<std::array<int, 2>, 5> mSkills; // Minor and major skills.
int mIsPlayable; // 0x0001 - Playable class
int mServices;

@ -7,20 +7,14 @@
namespace ESM
{
int& Faction::FADTstruct::getSkill(int index, bool ignored)
int& Faction::FADTstruct::getSkill(int index, bool)
{
if (index < 0 || index >= 7)
throw std::logic_error("skill index out of range");
return mSkills[index];
return mSkills.at(index);
}
int Faction::FADTstruct::getSkill(int index, bool ignored) const
int Faction::FADTstruct::getSkill(int index, bool) const
{
if (index < 0 || index >= 7)
throw std::logic_error("skill index out of range");
return mSkills[index];
return mSkills.at(index);
}
void Faction::load(ESMReader& esm, bool& isDeleted)
@ -115,10 +109,10 @@ namespace ESM
{
mRecordFlags = 0;
mName.clear();
mData.mAttribute[0] = mData.mAttribute[1] = 0;
mData.mAttribute.fill(0);
mData.mIsHidden = 0;
for (int i = 0; i < 10; ++i)
for (size_t i = 0; i < mData.mRankData.size(); ++i)
{
mData.mRankData[i].mAttribute1 = mData.mRankData[i].mAttribute2 = 0;
mData.mRankData[i].mPrimarySkill = mData.mRankData[i].mFavouredSkill = 0;
@ -127,8 +121,7 @@ namespace ESM
mRanks[i].clear();
}
for (int i = 0; i < 7; ++i)
mData.mSkills[i] = 0;
mData.mSkills.fill(0);
mReactions.clear();
}

@ -1,6 +1,7 @@
#ifndef OPENMW_ESM_FACT_H
#define OPENMW_ESM_FACT_H
#include <array>
#include <map>
#include <string>
@ -45,12 +46,12 @@ namespace ESM
struct FADTstruct
{
// Which attributes we like
int mAttribute[2];
std::array<int, 2> mAttribute;
RankData mRankData[10];
std::array<RankData, 10> mRankData;
int mSkills[7]; // IDs of skills this faction require
// Each element will either contain an Skill index, or -1.
std::array<int, 7> mSkills; // IDs of skills this faction require
// Each element will either contain an Skill index, or -1.
int mIsHidden; // 1 - hidden from player

@ -215,8 +215,7 @@ namespace ESM
mNpdt.mLevel = 0;
mNpdt.mStrength = mNpdt.mIntelligence = mNpdt.mWillpower = mNpdt.mAgility = mNpdt.mSpeed = mNpdt.mEndurance
= mNpdt.mPersonality = mNpdt.mLuck = 0;
for (int i = 0; i < Skill::Length; ++i)
mNpdt.mSkills[i] = 0;
mNpdt.mSkills.fill(0);
mNpdt.mReputation = 0;
mNpdt.mHealth = mNpdt.mMana = mNpdt.mFatigue = 0;
mNpdt.mDisposition = 0;

@ -1,6 +1,7 @@
#ifndef OPENMW_ESM_NPC_H
#define OPENMW_ESM_NPC_H
#include <array>
#include <string>
#include <vector>
@ -82,7 +83,7 @@ namespace ESM
unsigned char mStrength, mIntelligence, mWillpower, mAgility, mSpeed, mEndurance, mPersonality, mLuck;
// mSkill can grow up to 200, it must be unsigned
unsigned char mSkills[Skill::Length];
std::array<unsigned char, Skill::Length> mSkills;
char mUnknown1;
unsigned short mHealth, mMana, mFatigue;

@ -84,14 +84,14 @@ namespace ESM
mPowers.mList.clear();
for (int i = 0; i < 7; ++i)
for (auto& bonus : mData.mBonus)
{
mData.mBonus[i].mSkill = -1;
mData.mBonus[i].mBonus = 0;
bonus.mSkill = -1;
bonus.mBonus = 0;
}
for (int i = 0; i < 8; ++i)
mData.mAttributeValues[i].mMale = mData.mAttributeValues[i].mFemale = 1;
for (auto& attribute : mData.mAttributeValues)
attribute.mMale = attribute.mFemale = 1;
mData.mHeight.mMale = mData.mHeight.mFemale = 1;
mData.mWeight.mMale = mData.mWeight.mFemale = 1;

@ -1,6 +1,7 @@
#ifndef OPENMW_ESM_RACE_H
#define OPENMW_ESM_RACE_H
#include <array>
#include <string>
#include "components/esm/defs.hpp"
@ -53,10 +54,10 @@ namespace ESM
struct RADTstruct
{
// List of skills that get a bonus
SkillBonus mBonus[7];
std::array<SkillBonus, 7> mBonus;
// Attribute values for male/female
MaleFemale mAttributeValues[8];
std::array<MaleFemale, 8> mAttributeValues;
// The actual eye level height (in game units) is (probably) given
// as 'height' times 128. This has not been tested yet.

@ -31,15 +31,15 @@ namespace ESM
esm.getHNOT(faction.mReputation, "FARE");
mFactions.insert(std::make_pair(id, faction));
mFactions.emplace(id, faction);
}
mDisposition = 0;
esm.getHNOT(mDisposition, "DISP");
const bool intFallback = esm.getFormatVersion() <= MaxIntFallbackFormatVersion;
for (int i = 0; i < 27; ++i)
mSkills[i].load(esm, intFallback);
for (auto& skill : mSkills)
skill.load(esm, intFallback);
mWerewolfDeprecatedData = false;
if (esm.getFormatVersion() <= MaxWerewolfDeprecatedDataFormatVersion && esm.peekNextSub("STBA"))
@ -47,9 +47,9 @@ namespace ESM
// we have deprecated werewolf skills, stored interleaved
// Load into one big vector, then remove every 2nd value
mWerewolfDeprecatedData = true;
std::vector<StatState<float>> skills(mSkills, mSkills + sizeof(mSkills) / sizeof(mSkills[0]));
std::vector<StatState<float>> skills(mSkills.begin(), mSkills.end());
for (int i = 0; i < 27; ++i)
for (int i = 0; i < ESM::Skill::Length; ++i)
{
StatState<float> skill;
skill.load(esm, intFallback);
@ -67,7 +67,7 @@ namespace ESM
if (skills.size() != std::size(mSkills))
throw std::runtime_error(
"Invalid number of skill for werewolf deprecated data: " + std::to_string(skills.size()));
std::copy(skills.begin(), skills.end(), mSkills);
std::copy(skills.begin(), skills.end(), mSkills.begin());
}
// No longer used
@ -76,7 +76,7 @@ namespace ESM
if (hasWerewolfAttributes)
{
StatState<int> dummy;
for (int i = 0; i < 8; ++i)
for (int i = 0; i < ESM::Attribute::Length; ++i)
dummy.load(esm, intFallback);
mWerewolfDeprecatedData = true;
}
@ -104,12 +104,10 @@ namespace ESM
mLevelProgress = 0;
esm.getHNOT(mLevelProgress, "LPRO");
for (int i = 0; i < 8; ++i)
mSkillIncrease[i] = 0;
mSkillIncrease.fill(0);
esm.getHNOT(mSkillIncrease, "INCR");
for (int i = 0; i < 3; ++i)
mSpecIncreases[i] = 0;
mSpecIncreases.fill(0);
esm.getHNOT(mSpecIncreases, "SPEC");
while (esm.isNextSub("USED"))
@ -152,8 +150,8 @@ namespace ESM
if (mDisposition)
esm.writeHNT("DISP", mDisposition);
for (int i = 0; i < 27; ++i)
mSkills[i].save(esm);
for (const auto& skill : mSkills)
skill.save(esm);
if (mIsWerewolf)
esm.writeHNT("WOLF", mIsWerewolf);
@ -171,9 +169,9 @@ namespace ESM
esm.writeHNT("LPRO", mLevelProgress);
bool saveSkillIncreases = false;
for (int i = 0; i < 8; ++i)
for (int increase : mSkillIncrease)
{
if (mSkillIncrease[i] != 0)
if (increase != 0)
{
saveSkillIncreases = true;
break;
@ -204,10 +202,8 @@ namespace ESM
mReputation = 0;
mWerewolfKills = 0;
mLevelProgress = 0;
for (int i = 0; i < 8; ++i)
mSkillIncrease[i] = 0;
for (int i = 0; i < 3; ++i)
mSpecIncreases[i] = 0;
mSkillIncrease.fill(0);
mSpecIncreases.fill(0);
mTimeToStartDrowning = 20;
mCrimeId = -1;
}

@ -1,8 +1,12 @@
#ifndef OPENMW_ESM_NPCSTATS_H
#define OPENMW_ESM_NPCSTATS_H
#include "loadskil.hpp"
#include "statstate.hpp"
#include <components/esm/attr.hpp>
#include <components/esm/refid.hpp>
#include <array>
#include <map>
#include <string>
#include <vector>
@ -31,13 +35,13 @@ namespace ESM
std::map<ESM::RefId, Faction> mFactions; // lower case IDs
int mDisposition;
StatState<float> mSkills[27];
std::array<StatState<float>, ESM::Skill::Length> mSkills;
int mBounty;
int mReputation;
int mWerewolfKills;
int mLevelProgress;
int mSkillIncrease[8];
int mSpecIncreases[3];
std::array<int, ESM::Attribute::Length> mSkillIncrease;
std::array<int, 3> mSpecIncreases;
std::vector<ESM::RefId> mUsedIds; // lower case IDs
float mTimeToStartDrowning;
int mCrimeId;

Loading…
Cancel
Save