Merge branch 'clickbait' into 'master'

Use std::array in various ESM structs

See merge request OpenMW/openmw!3103
macos_ci
psi29a 2 years ago
commit 25c1e6abee

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

@ -249,7 +249,7 @@ namespace ESSImport
{ {
ESM::InventoryState& invState = mContext->mPlayer.mObject.mInventory; 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? // 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)) if (invState.mItems[i].mRef.mRefID == ESM::RefId::stringRefId(refr.mActorData.mSelectedEnchantItem))

@ -25,11 +25,11 @@ namespace ESSImport
faction.mReputation = essFaction.mReputation; faction.mReputation = essFaction.mReputation;
out.mObject.mNpcStats.mFactions[ESM::RefId::stringRefId(essFaction.mFactionName.toString())] = faction; 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]; 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]; 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.mSkills[i].mProgress = pcdt.mPNAM.mSkillProgress[i];
out.mObject.mNpcStats.mLevelProgress = pcdt.mPNAM.mLevelProgress; out.mObject.mNpcStats.mLevelProgress = pcdt.mPNAM.mLevelProgress;

@ -162,7 +162,7 @@ namespace ESSImport
read(mOutFile, file2); // todo rename variable read(mOutFile, file2); // todo rename variable
// FIXME: use max(size1, size2) // 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]; File::Record rec = file1.mRecords[i];
@ -185,7 +185,7 @@ namespace ESSImport
} }
// FIXME: use max(size1, size2) // 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]; File::Subrecord sub = rec.mSubrecords[j];
@ -221,7 +221,7 @@ namespace ESSImport
<< std::hex << sub.mFileOffset << " (2) 0x" << sub2.mFileOffset << std::endl; << std::hex << sub.mFileOffset << " (2) 0x" << sub2.mFileOffset << std::endl;
std::cout << "Data 1:" << 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; bool different = false;
if (k >= sub2.mData.size() || sub2.mData[k] != sub.mData[k]) if (k >= sub2.mData.size() || sub2.mData[k] != sub.mData[k])
@ -236,7 +236,7 @@ namespace ESSImport
std::cout << std::endl; std::cout << std::endl;
std::cout << "Data 2:" << 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; bool different = false;
if (k >= sub.mData.size() || sub.mData[k] != sub2.mData[k]) 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); 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) if (mDefault.mValue == mValues.mValues[i].mValue)
index = i; 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->setItemData(i, QString::fromUtf8(mValues.mValues[i].mTooltip.c_str()), Qt::ToolTipRole);
} }
mWidget->setCurrentIndex(index); mWidget->setCurrentIndex(static_cast<int>(index));
if (!mTooltip.empty()) 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); messages.add(id, "Description of a playable class is missing", "", CSMDoc::Message::Severity_Warning);
// test for invalid attributes // test for invalid attributes
for (int i = 0; i < 2; ++i) std::map<int, int> attributeCount;
if (class_.mData.mAttribute[i] == -1) 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 // test for non-unique skill
std::map<int, int> skills; // ID, number of occurrences std::map<int, int> skills; // ID, number of occurrences
for (int i = 0; i < 5; ++i) for (const auto& s : class_.mData.mSkills)
for (int i2 = 0; i2 < 2; ++i2) for (int skill : s)
++skills[class_.mData.mSkills[i][i2]]; ++skills[skill];
for (auto& skill : skills) for (auto& skill : skills)
if (skill.second > 1) 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); messages.add(id, "Name is missing", "", CSMDoc::Message::Severity_Error);
// test for invalid attributes // 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 // test for non-unique skill
std::map<int, int> skills; // ID, number of occurrences std::map<int, int> skills; // ID, number of occurrences
for (int i = 0; i < 7; ++i) for (int skill : faction.mData.mSkills)
if (faction.mData.mSkills[i] != -1) if (skill != -1)
++skills[faction.mData.mSkills[i]]; ++skills[skill];
for (auto& skill : skills) for (auto& skill : skills)
if (skill.second > 1) 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); 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) if (mReferencables.searchId(element.mId).first == -1)
messages.add(someID, "Object '" + someList.mList[i].mId.getRefIdString() + "' does not exist", "", messages.add(someID, "Object '" + element.mId.getRefIdString() + "' does not exist", "",
CSMDoc::Message::Severity_Error); CSMDoc::Message::Severity_Error);
if (someList.mList[i].mLevel < 1) if (element.mLevel < 1)
messages.add(someID, "Level of item '" + someList.mList[i].mId.getRefIdString() + "' is non-positive", "", messages.add(someID, "Level of item '" + element.mId.getRefIdString() + "' is non-positive", "",
CSMDoc::Message::Severity_Error); CSMDoc::Message::Severity_Error);
} }
} }

@ -134,9 +134,9 @@ CSMWorld::NestableColumn::NestableColumn(int columnId, CSMWorld::ColumnBase::Dis
CSMWorld::NestableColumn::~NestableColumn() 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>(); 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; continue;
reader->open(files[i]); reader->open(file);
records += reader->getRecordCount(); records += reader->getRecordCount();
reader->close(); reader->close();
} }

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

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

@ -698,9 +698,9 @@ bool CSVRender::PagedWorldspaceWidget::handleDrop(
return false; return false;
bool selectionChanged = 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))) if (mSelection.add(CSMWorld::CellCoordinates(coordinates.first, coordinates.second)))
{ {
selectionChanged = true; selectionChanged = true;

@ -347,10 +347,10 @@ namespace CSVRender
QModelIndex parent = model->index(recordIndex, parentColumn); 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]]; const CSMWorld::Pathgrid::Point& point = source->mPoints[selected];
int row = static_cast<int>(mSelected[i]); int row = static_cast<int>(selected);
commands.push(new CSMWorld::ModifyCommand( commands.push(new CSMWorld::ModifyCommand(
*model, model->index(row, posXColumn, parent), clampToCell(point.mX + offsetX))); *model, model->index(row, posXColumn, parent), clampToCell(point.mX + offsetX)));
@ -378,9 +378,9 @@ namespace CSVRender
const CSMWorld::Pathgrid* source = getPathgridSource(); const CSMWorld::Pathgrid* source = getPathgridSource();
if (source) 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); 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() 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() CSVWorld::EditWidget::~EditWidget()
{ {
for (unsigned i = 0; i < mNestedModels.size(); ++i) for (auto* model : mNestedModels)
delete mNestedModels[i]; delete model;
if (mDispatcher) if (mDispatcher)
delete mDispatcher; delete mDispatcher;
@ -511,8 +511,8 @@ void CSVWorld::EditWidget::remake(int row)
} }
mMainWidget = new QWidget(this); mMainWidget = new QWidget(this);
for (unsigned i = 0; i < mNestedModels.size(); ++i) for (auto* model : mNestedModels)
delete mNestedModels[i]; delete model;
mNestedModels.clear(); mNestedModels.clear();

@ -611,7 +611,7 @@ void CSVWorld::Table::moveRecords(QDropEvent* event)
std::vector<int> newOrder(highestDifference + 1); 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; newOrder[i] = i;
} }

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

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

@ -644,9 +644,6 @@ int MWDialogue::Filter::getFactionRank(const MWWorld::Ptr& actor, const ESM::Ref
bool MWDialogue::Filter::hasFactionRankSkillRequirements( bool MWDialogue::Filter::hasFactionRankSkillRequirements(
const MWWorld::Ptr& actor, const ESM::RefId& factionId, int rank) const 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)) if (!actor.getClass().getNpcStats(actor).hasSkillsForRank(factionId, rank))
return false; return false;
@ -661,14 +658,11 @@ bool MWDialogue::Filter::hasFactionRankSkillRequirements(
bool MWDialogue::Filter::hasFactionRankReputationRequirements( bool MWDialogue::Filter::hasFactionRankReputationRequirements(
const MWWorld::Ptr& actor, const ESM::RefId& factionId, int rank) const 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); MWMechanics::NpcStats& stats = actor.getClass().getNpcStats(actor);
const ESM::Faction& faction = *MWBase::Environment::get().getESMStore()->get<ESM::Faction>().find(factionId); 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) MWDialogue::Filter::Filter(const MWWorld::Ptr& actor, int choice, bool talkedToPlayer)

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

@ -264,7 +264,7 @@ namespace MWGui
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());
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]); mMinorSkill[i]->setSkillNumber(klass->mData.mSkills[i][0]);
mMajorSkill[i]->setSkillNumber(klass->mData.mSkills[i][1]); mMajorSkill[i]->setSkillNumber(klass->mData.mSkills[i][1]);

@ -462,7 +462,7 @@ namespace MWGui::Formatting
mPaginator.setIgnoreLeadingEmptyLines(true); mPaginator.setIgnoreLeadingEmptyLines(true);
const MyGUI::VectorLineInfo& lines = mEditBox->getSubWidgetText()->castType<MyGUI::EditText>()->getLineInfo(); 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) if (lines[i].width == 0)
ret += lineHeight; ret += lineHeight;

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

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

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

@ -121,19 +121,19 @@ namespace MWGui
else if (mPtr.getType() == ESM::Creature::sRecordId) else if (mPtr.getType() == ESM::Creature::sRecordId)
transport = mPtr.get<ESM::Creature>()->mBase->getTransport(); 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; bool interior = true;
const ESM::ExteriorCellLocation cellIndex 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()) if (cellname.empty())
{ {
MWWorld::CellStore& cell = MWBase::Environment::get().getWorldModel()->getExterior(cellIndex); MWWorld::CellStore& cell = MWBase::Environment::get().getWorldModel()->getExterior(cellIndex);
cellname = MWBase::Environment::get().getWorld()->getCellName(&cell); cellname = MWBase::Environment::get().getWorld()->getCellName(&cell);
interior = false; interior = false;
} }
addDestination(ESM::RefId::stringRefId(cellname), transport[i].mPos, interior); addDestination(ESM::RefId::stringRefId(cellname), dest.mPos, interior);
} }
updateLabels(); updateLabels();

@ -128,7 +128,7 @@ namespace MWMechanics
creatureStats.getSpells().clear(true); creatureStats.getSpells().clear(true);
creatureStats.getActiveSpells().clear(ptr); 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]); npcStats.getSkill(i).setBase(player->mNpdt.mSkills[i]);
creatureStats.setAttribute(ESM::Attribute::Strength, player->mNpdt.mStrength); creatureStats.setAttribute(ESM::Attribute::Strength, player->mNpdt.mStrength);
@ -148,7 +148,7 @@ namespace MWMechanics
bool male = (player->mFlags & ESM::NPC::Female) == 0; 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]; const ESM::Race::MaleFemale& attribute = race->mData.mAttributeValues[i];
@ -159,12 +159,10 @@ namespace MWMechanics
{ {
int bonus = 0; int bonus = 0;
for (int i2 = 0; i2 < 7; ++i2) auto bonusIt = std::find_if(race->mData.mBonus.begin(), race->mData.mBonus.end(),
if (race->mData.mBonus[i2].mSkill == i) [i](const auto& bonus) { return bonus.mSkill == i; });
{ if (bonusIt != race->mData.mBonus.end())
bonus = race->mData.mBonus[i2].mBonus; bonus = bonusIt->mBonus;
break;
}
npcStats.getSkill(i).setBase(5 + bonus); npcStats.getSkill(i).setBase(5 + bonus);
} }
@ -193,10 +191,9 @@ namespace MWMechanics
{ {
const ESM::Class* class_ = esmStore.get<ESM::Class>().find(player->mClass); 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 < ESM::Attribute::Length)
if (attribute >= 0 && attribute < 8)
{ {
creatureStats.setAttribute(attribute, creatureStats.getAttribute(attribute).getBase() + 10); creatureStats.setAttribute(attribute, creatureStats.getAttribute(attribute).getBase() + 10);
} }
@ -206,11 +203,11 @@ namespace MWMechanics
{ {
int bonus = i == 0 ? 10 : 25; 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); 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(); 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(); typeFactor = gmst.find("fMinorSkillBonus")->mValue.getFloat();
break; break;
} }
else if (class_.mData.mSkills[i][1] == skillIndex) else if (skills[1] == skillIndex)
{ {
typeFactor = gmst.find("fMajorSkillBonus")->mValue.getFloat(); typeFactor = gmst.find("fMajorSkillBonus")->mValue.getFloat();
break; break;
@ -235,15 +235,15 @@ void MWMechanics::NpcStats::increaseSkill(
// is this a minor or major skill? // is this a minor or major skill?
int increase = gmst.find("iLevelupMiscMultAttriubte")->mValue.getInteger(); // Note: GMST has a typo 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(); mLevelProgress += gmst.find("iLevelUpMinorMult")->mValue.getInteger();
increase = gmst.find("iLevelUpMinorMultAttribute")->mValue.getInteger(); increase = gmst.find("iLevelUpMinorMultAttribute")->mValue.getInteger();
break; break;
} }
else if (class_.mData.mSkills[k][1] == skillIndex) else if (skills[1] == skillIndex)
{ {
mLevelProgress += gmst.find("iLevelUpMajorMult")->mValue.getInteger(); mLevelProgress += gmst.find("iLevelUpMajorMult")->mValue.getInteger();
increase = gmst.find("iLevelUpMajorMultAttribute")->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 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::Faction& faction = *MWBase::Environment::get().getESMStore()->get<ESM::Faction>().find(factionId);
const ESM::RankData& rankData = faction.mData.mRankData.at(rank);
std::vector<int> skills; std::vector<int> skills;
for (int i = 0; i < 7; ++i) for (int id : faction.mData.mSkills)
{ {
if (faction.mData.mSkills[i] != -1) if (id != -1)
skills.push_back(static_cast<int>(getSkill(faction.mData.mSkills[i]).getBase())); skills.push_back(static_cast<int>(getSkill(id).getBase()));
} }
if (skills.empty()) 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(); std::vector<int>::const_reverse_iterator iter = skills.rbegin();
const ESM::RankData& rankData = faction.mData.mRankData[rank];
if (*iter < rankData.mPrimarySkill) if (*iter < rankData.mPrimarySkill)
return false; return false;
@ -473,7 +470,7 @@ void MWMechanics::NpcStats::writeState(ESM::NpcStats& state) const
state.mDisposition = mDisposition; 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]); mSkill[i].writeState(state.mSkills[i]);
state.mIsWerewolf = mIsWerewolf; state.mIsWerewolf = mIsWerewolf;
@ -492,10 +489,10 @@ void MWMechanics::NpcStats::writeState(ESM::NpcStats& state) const
state.mWerewolfKills = mWerewolfKills; state.mWerewolfKills = mWerewolfKills;
state.mLevelProgress = mLevelProgress; 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]; 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]; state.mSpecIncreases[i] = mSpecIncreases[i];
std::copy(mUsedIds.begin(), mUsedIds.end(), std::back_inserter(state.mUsedIds)); 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; 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]); mSkill[i].readState(state.mSkills[i]);
mIsWerewolf = state.mIsWerewolf; mIsWerewolf = state.mIsWerewolf;
@ -537,10 +534,10 @@ void MWMechanics::NpcStats::readState(const ESM::NpcStats& state)
mWerewolfKills = state.mWerewolfKills; mWerewolfKills = state.mWerewolfKills;
mLevelProgress = state.mLevelProgress; 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]; 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]; mSpecIncreases[i] = state.mSpecIncreases[i];
for (auto iter(state.mUsedIds.begin()); iter != state.mUsedIds.end(); ++iter) 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) int& Class::CLDTstruct::getSkill(int index, bool major)
{ {
if (index < 0 || index >= 5) return mSkills.at(index)[major ? 1 : 0];
throw std::logic_error("skill index out of range");
return mSkills[index][major ? 1 : 0];
} }
int Class::CLDTstruct::getSkill(int index, bool major) const int Class::CLDTstruct::getSkill(int index, bool major) const
{ {
if (index < 0 || index >= 5) return mSkills.at(index)[major ? 1 : 0];
throw std::logic_error("skill index out of range");
return mSkills[index][major ? 1 : 0];
} }
void Class::load(ESMReader& esm, bool& isDeleted) void Class::load(ESMReader& esm, bool& isDeleted)
@ -91,13 +85,12 @@ namespace ESM
mName.clear(); mName.clear();
mDescription.clear(); mDescription.clear();
mData.mAttribute[0] = mData.mAttribute[1] = 0; mData.mAttribute.fill(0);
mData.mSpecialization = 0; mData.mSpecialization = 0;
mData.mIsPlayable = 0; mData.mIsPlayable = 0;
mData.mServices = 0; mData.mServices = 0;
for (int i = 0; i < 5; ++i) for (auto& skills : mData.mSkills)
for (int i2 = 0; i2 < 2; ++i2) skills.fill(0);
mData.mSkills[i][i2] = 0;
} }
} }

@ -1,6 +1,7 @@
#ifndef OPENMW_ESM_CLAS_H #ifndef OPENMW_ESM_CLAS_H
#define OPENMW_ESM_CLAS_H #define OPENMW_ESM_CLAS_H
#include <array>
#include <string> #include <string>
#include "components/esm/defs.hpp" #include "components/esm/defs.hpp"
@ -33,9 +34,9 @@ namespace ESM
struct CLDTstruct 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 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 mIsPlayable; // 0x0001 - Playable class
int mServices; int mServices;

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

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

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

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

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

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

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

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

Loading…
Cancel
Save