diff --git a/apps/esmtool/record.cpp b/apps/esmtool/record.cpp index 0c22114749b..55a850cf7e0 100644 --- a/apps/esmtool/record.cpp +++ b/apps/esmtool/record.cpp @@ -690,14 +690,8 @@ namespace EsmTool std::cout << " Level: " << mData.mData.mLevel << std::endl; std::cout << " Attributes:" << std::endl; - std::cout << " Strength: " << mData.mData.mStrength << std::endl; - std::cout << " Intelligence: " << mData.mData.mIntelligence << std::endl; - std::cout << " Willpower: " << mData.mData.mWillpower << std::endl; - std::cout << " Agility: " << mData.mData.mAgility << std::endl; - std::cout << " Speed: " << mData.mData.mSpeed << std::endl; - std::cout << " Endurance: " << mData.mData.mEndurance << std::endl; - std::cout << " Personality: " << mData.mData.mPersonality << std::endl; - std::cout << " Luck: " << mData.mData.mLuck << std::endl; + for (size_t i = 0; i < mData.mData.mAttributes.size(); ++i) + std::cout << " " << ESM::Attribute::indexToRefId(i) << ": " << mData.mData.mAttributes[i] << std::endl; std::cout << " Health: " << mData.mData.mHealth << std::endl; std::cout << " Magicka: " << mData.mData.mMana << std::endl; diff --git a/apps/opencs/model/tools/referenceablecheck.cpp b/apps/opencs/model/tools/referenceablecheck.cpp index 6effa2cbf65..e2e178f90af 100644 --- a/apps/opencs/model/tools/referenceablecheck.cpp +++ b/apps/opencs/model/tools/referenceablecheck.cpp @@ -456,22 +456,12 @@ void CSMTools::ReferenceableCheckStage::creatureCheck( if (creature.mData.mLevel <= 0) messages.add(id, "Level is non-positive", "", CSMDoc::Message::Severity_Warning); - if (creature.mData.mStrength < 0) - messages.add(id, "Strength is negative", "", CSMDoc::Message::Severity_Warning); - if (creature.mData.mIntelligence < 0) - messages.add(id, "Intelligence is negative", "", CSMDoc::Message::Severity_Warning); - if (creature.mData.mWillpower < 0) - messages.add(id, "Willpower is negative", "", CSMDoc::Message::Severity_Warning); - if (creature.mData.mAgility < 0) - messages.add(id, "Agility is negative", "", CSMDoc::Message::Severity_Warning); - if (creature.mData.mSpeed < 0) - messages.add(id, "Speed is negative", "", CSMDoc::Message::Severity_Warning); - if (creature.mData.mEndurance < 0) - messages.add(id, "Endurance is negative", "", CSMDoc::Message::Severity_Warning); - if (creature.mData.mPersonality < 0) - messages.add(id, "Personality is negative", "", CSMDoc::Message::Severity_Warning); - if (creature.mData.mLuck < 0) - messages.add(id, "Luck is negative", "", CSMDoc::Message::Severity_Warning); + for (size_t i = 0; i < creature.mData.mAttributes.size(); ++i) + { + if (creature.mData.mAttributes[i] < 0) + messages.add(id, ESM::Attribute::indexToRefId(i).toDebugString() + " is negative", {}, + CSMDoc::Message::Severity_Warning); + } if (creature.mData.mCombat < 0) messages.add(id, "Combat is negative", "", CSMDoc::Message::Severity_Warning); diff --git a/apps/opencs/model/world/refidadapterimp.cpp b/apps/opencs/model/world/refidadapterimp.cpp index ba9c6d65a76..0ddfbbb0512 100644 --- a/apps/opencs/model/world/refidadapterimp.cpp +++ b/apps/opencs/model/world/refidadapterimp.cpp @@ -1315,30 +1315,9 @@ QVariant CSMWorld::CreatureAttributesRefIdAdapter::getNestedData( if (subColIndex == 0) return subRowIndex; - else if (subColIndex == 1) - switch (subRowIndex) - { - case 0: - return creature.mData.mStrength; - case 1: - return creature.mData.mIntelligence; - case 2: - return creature.mData.mWillpower; - case 3: - return creature.mData.mAgility; - case 4: - return creature.mData.mSpeed; - case 5: - return creature.mData.mEndurance; - case 6: - return creature.mData.mPersonality; - case 7: - return creature.mData.mLuck; - default: - return QVariant(); // throw an exception here? - } - else - return QVariant(); // throw an exception here? + else if (subColIndex == 1 && subRowIndex > 0 && subRowIndex < ESM::Attribute::Length) + return creature.mData.mAttributes[subRowIndex]; + return QVariant(); // throw an exception here? } void CSMWorld::CreatureAttributesRefIdAdapter::setNestedData( @@ -1346,42 +1325,14 @@ void CSMWorld::CreatureAttributesRefIdAdapter::setNestedData( { Record& record = static_cast&>(data.getRecord(RefIdData::LocalIndex(row, UniversalId::Type_Creature))); - ESM::Creature creature = record.get(); - if (subColIndex == 1) - switch (subRowIndex) - { - case 0: - creature.mData.mStrength = value.toInt(); - break; - case 1: - creature.mData.mIntelligence = value.toInt(); - break; - case 2: - creature.mData.mWillpower = value.toInt(); - break; - case 3: - creature.mData.mAgility = value.toInt(); - break; - case 4: - creature.mData.mSpeed = value.toInt(); - break; - case 5: - creature.mData.mEndurance = value.toInt(); - break; - case 6: - creature.mData.mPersonality = value.toInt(); - break; - case 7: - creature.mData.mLuck = value.toInt(); - break; - default: - return; // throw an exception here? - } - else - return; // throw an exception here? - - record.setModified(creature); + if (subColIndex == 1 && subRowIndex > 0 && subRowIndex < ESM::Attribute::Length) + { + ESM::Creature creature = record.get(); + creature.mData.mAttributes[subRowIndex] = value.toInt(); + record.setModified(creature); + } + // throw an exception here? } int CSMWorld::CreatureAttributesRefIdAdapter::getNestedColumnsCount( diff --git a/apps/openmw/mwclass/creature.cpp b/apps/openmw/mwclass/creature.cpp index 62dd48deb62..df1ada96f4b 100644 --- a/apps/openmw/mwclass/creature.cpp +++ b/apps/openmw/mwclass/creature.cpp @@ -127,14 +127,8 @@ namespace MWClass MWWorld::LiveCellRef* ref = ptr.get(); // creature stats - data->mCreatureStats.setAttribute(ESM::Attribute::Strength, ref->mBase->mData.mStrength); - data->mCreatureStats.setAttribute(ESM::Attribute::Intelligence, ref->mBase->mData.mIntelligence); - data->mCreatureStats.setAttribute(ESM::Attribute::Willpower, ref->mBase->mData.mWillpower); - data->mCreatureStats.setAttribute(ESM::Attribute::Agility, ref->mBase->mData.mAgility); - data->mCreatureStats.setAttribute(ESM::Attribute::Speed, ref->mBase->mData.mSpeed); - data->mCreatureStats.setAttribute(ESM::Attribute::Endurance, ref->mBase->mData.mEndurance); - data->mCreatureStats.setAttribute(ESM::Attribute::Personality, ref->mBase->mData.mPersonality); - data->mCreatureStats.setAttribute(ESM::Attribute::Luck, ref->mBase->mData.mLuck); + for (size_t i = 0; i < ref->mBase->mData.mAttributes.size(); ++i) + data->mCreatureStats.setAttribute(ESM::Attribute::indexToRefId(i), ref->mBase->mData.mAttributes[i]); data->mCreatureStats.setHealth(static_cast(ref->mBase->mData.mHealth)); data->mCreatureStats.setMagicka(static_cast(ref->mBase->mData.mMana)); data->mCreatureStats.setFatigue(static_cast(ref->mBase->mData.mFatigue)); diff --git a/components/esm3/loadcell.cpp b/components/esm3/loadcell.cpp index 25a98786586..b966338ae59 100644 --- a/components/esm3/loadcell.cpp +++ b/components/esm3/loadcell.cpp @@ -93,7 +93,7 @@ namespace ESM mName = esm.getHString(); break; case fourCC("DATA"): - esm.getHTSized<12>(mData); + esm.getHT(mData.mFlags, mData.mX, mData.mY); hasData = true; break; case SREC_DELE: @@ -144,7 +144,7 @@ namespace ESM mWater = waterLevel; break; case fourCC("AMBI"): - esm.getHTSized<16>(mAmbi); + esm.getHT(mAmbi.mAmbient, mAmbi.mSunlight, mAmbi.mFog, mAmbi.mFogDensity); mHasAmbi = true; break; case fourCC("RGNN"): diff --git a/components/esm3/loadcell.hpp b/components/esm3/loadcell.hpp index b7cf6bf2ebf..0ba0777e7ce 100644 --- a/components/esm3/loadcell.hpp +++ b/components/esm3/loadcell.hpp @@ -96,8 +96,8 @@ namespace ESM struct DATAstruct { - int mFlags{ 0 }; - int mX{ 0 }, mY{ 0 }; + int32_t mFlags{ 0 }; + int32_t mX{ 0 }, mY{ 0 }; }; struct AMBIstruct @@ -132,11 +132,11 @@ namespace ESM float mWater; // Water level bool mWaterInt; - int mMapColor; + int32_t mMapColor; // Counter for RefNums. This is only used during content file editing and has no impact on gameplay. // It prevents overwriting previous refNums, even if they were deleted. // as that would collide with refs when a content file is upgraded. - int mRefNumCounter; + int32_t mRefNumCounter; // References "leased" from another cell (i.e. a different cell // introduced this ref, and it has been moved here by a plugin) diff --git a/components/esm3/loadcrea.cpp b/components/esm3/loadcrea.cpp index 27cc98c1f23..0c0bad2e7c0 100644 --- a/components/esm3/loadcrea.cpp +++ b/components/esm3/loadcrea.cpp @@ -48,7 +48,8 @@ namespace ESM mScript = esm.getRefId(); break; case fourCC("NPDT"): - esm.getHTSized<96>(mData); + esm.getHT(mData.mType, mData.mLevel, mData.mAttributes, mData.mHealth, mData.mMana, mData.mFatigue, + mData.mSoul, mData.mCombat, mData.mMagic, mData.mStealth, mData.mAttack, mData.mGold); hasNpdt = true; break; case fourCC("FLAG"): @@ -139,8 +140,7 @@ namespace ESM mRecordFlags = 0; mData.mType = 0; mData.mLevel = 0; - mData.mStrength = mData.mIntelligence = mData.mWillpower = mData.mAgility = mData.mSpeed = mData.mEndurance - = mData.mPersonality = mData.mLuck = 0; + mData.mAttributes.fill(0); mData.mHealth = mData.mMana = mData.mFatigue = 0; mData.mSoul = 0; mData.mCombat = mData.mMagic = mData.mStealth = 0; diff --git a/components/esm3/loadcrea.hpp b/components/esm3/loadcrea.hpp index 42e50073281..ff4e698fa89 100644 --- a/components/esm3/loadcrea.hpp +++ b/components/esm3/loadcrea.hpp @@ -1,6 +1,7 @@ #ifndef OPENMW_ESM_CREA_H #define OPENMW_ESM_CREA_H +#include #include #include "aipackage.hpp" @@ -8,6 +9,7 @@ #include "spelllist.hpp" #include "transport.hpp" +#include "components/esm/attr.hpp" #include "components/esm/defs.hpp" #include "components/esm/refid.hpp" @@ -52,30 +54,30 @@ namespace ESM struct NPDTstruct { - int mType; + int32_t mType; // For creatures we obviously have to use ints, not shorts and // bytes like we use for NPCs.... this file format just makes so // much sense! (Still, _much_ easier to decode than the NIFs.) - int mLevel; - int mStrength, mIntelligence, mWillpower, mAgility, mSpeed, mEndurance, mPersonality, mLuck; + int32_t mLevel; + std::array mAttributes; - int mHealth, mMana, mFatigue; // Stats - int mSoul; // The creatures soul value (used with soul gems.) + int32_t mHealth, mMana, mFatigue; // Stats + int32_t mSoul; // The creatures soul value (used with soul gems.) // Creatures have generalized combat, magic and stealth stats which substitute for // the specific skills (in the same way as specializations). - int mCombat, mMagic, mStealth; - int mAttack[6]; // AttackMin1, AttackMax1, ditto2, ditto3 - int mGold; + int32_t mCombat, mMagic, mStealth; + int32_t mAttack[6]; // AttackMin1, AttackMax1, ditto2, ditto3 + int32_t mGold; }; // 96 byte NPDTstruct mData; - int mBloodType; + int32_t mBloodType; unsigned char mFlags; float mScale; - unsigned int mRecordFlags; + uint32_t mRecordFlags; RefId mId, mScript; std::string mModel; std::string mName; diff --git a/components/esm3/loadfact.cpp b/components/esm3/loadfact.cpp index 768de4f5130..9d4b832f97a 100644 --- a/components/esm3/loadfact.cpp +++ b/components/esm3/loadfact.cpp @@ -7,12 +7,12 @@ namespace ESM { - int& Faction::FADTstruct::getSkill(int index, bool) + int32_t& Faction::FADTstruct::getSkill(size_t index, bool) { return mSkills.at(index); } - int Faction::FADTstruct::getSkill(int index, bool) const + int32_t Faction::FADTstruct::getSkill(size_t index, bool) const { return mSkills.at(index); } @@ -23,10 +23,10 @@ namespace ESM mRecordFlags = esm.getRecordFlags(); mReactions.clear(); - for (int i = 0; i < 10; ++i) - mRanks[i].clear(); + for (auto& rank : mRanks) + rank.clear(); - int rankCounter = 0; + size_t rankCounter = 0; bool hasName = false; bool hasData = false; while (esm.hasMoreSubs()) @@ -42,7 +42,7 @@ namespace ESM mName = esm.getHString(); break; case fourCC("RNAM"): - if (rankCounter >= 10) + if (rankCounter >= mRanks.size()) esm.fail("Rank out of range"); mRanks[rankCounter++] = esm.getHString(); break; @@ -55,7 +55,7 @@ namespace ESM case fourCC("ANAM"): { ESM::RefId faction = esm.getRefId(); - int reaction; + int32_t reaction; esm.getHNT(reaction, "INTV"); // Prefer the lowest reaction in case a faction is listed multiple times auto it = mReactions.find(faction); @@ -93,12 +93,12 @@ namespace ESM esm.writeHNOCString("FNAM", mName); - for (int i = 0; i < 10; i++) + for (const auto& rank : mRanks) { - if (mRanks[i].empty()) + if (rank.empty()) break; - esm.writeHNString("RNAM", mRanks[i], 32); + esm.writeHNString("RNAM", rank, 32); } esm.writeHNT("FADT", mData, 240); diff --git a/components/esm3/loadfact.hpp b/components/esm3/loadfact.hpp index 4cbf6c1d239..2359d276a27 100644 --- a/components/esm3/loadfact.hpp +++ b/components/esm3/loadfact.hpp @@ -21,15 +21,15 @@ namespace ESM // Requirements for each rank struct RankData { - int mAttribute1, mAttribute2; // Attribute level + int32_t mAttribute1, mAttribute2; // Attribute level // Skill level (faction skills given in // skillID below.) You need one skill at // level 'mPrimarySkill' and two skills at level // 'mFavouredSkill' to advance to this rank. - int mPrimarySkill, mFavouredSkill; + int32_t mPrimarySkill, mFavouredSkill; - int mFactReaction; // Reaction from faction members + int32_t mFactReaction; // Reaction from faction members }; struct Faction @@ -39,33 +39,33 @@ namespace ESM /// Return a string descriptor for this record type. Currently used for debugging / error logs only. static std::string_view getRecordType() { return "Faction"; } - unsigned int mRecordFlags; + uint32_t mRecordFlags; std::string mName; RefId mId; struct FADTstruct { // Which attributes we like - std::array mAttribute; + std::array mAttribute; std::array mRankData; - std::array mSkills; // IDs of skills this faction require - // Each element will either contain an Skill index, or -1. + std::array mSkills; // IDs of skills this faction require + // Each element will either contain an Skill index, or -1. - int mIsHidden; // 1 - hidden from player + int32_t mIsHidden; // 1 - hidden from player - int& getSkill(int index, bool ignored = false); + int32_t& getSkill(size_t index, bool ignored = false); ///< Throws an exception for invalid values of \a index. - int getSkill(int index, bool ignored = false) const; + int32_t getSkill(size_t index, bool ignored = false) const; ///< Throws an exception for invalid values of \a index. }; // 240 bytes FADTstruct mData; // - std::map mReactions; + std::map mReactions; // Name of faction ranks (may be empty for NPC factions) std::array mRanks; diff --git a/components/esm3/loadinfo.cpp b/components/esm3/loadinfo.cpp index 8807f7b03f9..9cff21da3ef 100644 --- a/components/esm3/loadinfo.cpp +++ b/components/esm3/loadinfo.cpp @@ -23,7 +23,8 @@ namespace ESM switch (esm.retSubName().toInt()) { case fourCC("DATA"): - esm.getHTSized<12>(mData); + esm.getHT(mData.mUnknown1, mData.mDisposition, mData.mRank, mData.mGender, mData.mPCrank, + mData.mUnknown2); break; case fourCC("ONAM"): mActor = esm.getRefId(); diff --git a/components/esm3/loadinfo.hpp b/components/esm3/loadinfo.hpp index 84db0d4f851..518e2eaa54c 100644 --- a/components/esm3/loadinfo.hpp +++ b/components/esm3/loadinfo.hpp @@ -35,11 +35,11 @@ namespace ESM struct DATAstruct { - int mUnknown1 = 0; + int32_t mUnknown1 = 0; union { - int mDisposition = 0; // Used for dialogue responses - int mJournalIndex; // Used for journal entries + int32_t mDisposition = 0; // Used for dialogue responses + int32_t mJournalIndex; // Used for journal entries }; signed char mRank = -1; // Rank of NPC signed char mGender = Gender::NA; // See Gender enum diff --git a/components/esm3/loadingr.cpp b/components/esm3/loadingr.cpp index fef7a93feb2..4e409ab63d3 100644 --- a/components/esm3/loadingr.cpp +++ b/components/esm3/loadingr.cpp @@ -28,7 +28,7 @@ namespace ESM mName = esm.getHString(); break; case fourCC("IRDT"): - esm.getHTSized<56>(mData); + esm.getHT(mData.mWeight, mData.mValue, mData.mEffectID, mData.mSkills, mData.mAttributes); hasData = true; break; case fourCC("SCRI"): diff --git a/components/esm3/loadingr.hpp b/components/esm3/loadingr.hpp index 02b237f386a..2a8748e067b 100644 --- a/components/esm3/loadingr.hpp +++ b/components/esm3/loadingr.hpp @@ -26,14 +26,14 @@ namespace ESM struct IRDTstruct { float mWeight; - int mValue; - int mEffectID[4]; // Effect, -1 means none - int mSkills[4]; // SkillEnum related to effect - int mAttributes[4]; // Attribute related to effect + int32_t mValue; + int32_t mEffectID[4]; // Effect, -1 means none + int32_t mSkills[4]; // SkillEnum related to effect + int32_t mAttributes[4]; // Attribute related to effect }; IRDTstruct mData; - unsigned int mRecordFlags; + uint32_t mRecordFlags; RefId mId, mScript; std::string mName, mModel, mIcon; diff --git a/components/esm3/loadligh.cpp b/components/esm3/loadligh.cpp index 150baccec09..e22f6110c21 100644 --- a/components/esm3/loadligh.cpp +++ b/components/esm3/loadligh.cpp @@ -31,7 +31,7 @@ namespace ESM mIcon = esm.getHString(); break; case fourCC("LHDT"): - esm.getHTSized<24>(mData); + esm.getHT(mData.mWeight, mData.mValue, mData.mTime, mData.mRadius, mData.mColor, mData.mFlags); hasData = true; break; case fourCC("SCRI"): diff --git a/components/esm3/loadligh.hpp b/components/esm3/loadligh.hpp index 7ee24d26fc3..67c171b0bc2 100644 --- a/components/esm3/loadligh.hpp +++ b/components/esm3/loadligh.hpp @@ -41,16 +41,16 @@ namespace ESM struct LHDTstruct { float mWeight; - int mValue; - int mTime; // Duration - int mRadius; - unsigned int mColor; // 4-byte rgba value - int mFlags; + int32_t mValue; + int32_t mTime; // Duration + int32_t mRadius; + uint32_t mColor; // 4-byte rgba value + int32_t mFlags; }; // Size = 24 bytes LHDTstruct mData; - unsigned int mRecordFlags; + uint32_t mRecordFlags; std::string mModel, mIcon, mName; ESM::RefId mId, mSound, mScript; diff --git a/components/esm3/loadlock.cpp b/components/esm3/loadlock.cpp index 0e87558871f..578a8a36a70 100644 --- a/components/esm3/loadlock.cpp +++ b/components/esm3/loadlock.cpp @@ -28,7 +28,7 @@ namespace ESM mName = esm.getHString(); break; case fourCC("LKDT"): - esm.getHTSized<16>(mData); + esm.getHT(mData.mWeight, mData.mValue, mData.mQuality, mData.mUses); hasData = true; break; case fourCC("SCRI"): diff --git a/components/esm3/loadlock.hpp b/components/esm3/loadlock.hpp index 1b94fd61bb2..ae08243d699 100644 --- a/components/esm3/loadlock.hpp +++ b/components/esm3/loadlock.hpp @@ -22,14 +22,14 @@ namespace ESM struct Data { float mWeight; - int mValue; + int32_t mValue; float mQuality; - int mUses; + int32_t mUses; }; // Size = 16 Data mData; - unsigned int mRecordFlags; + uint32_t mRecordFlags; RefId mId, mScript; std::string mName, mModel, mIcon;