Merge branch 'stringrefidskills' into 'master'

Assign StringRefIds to skills

See merge request OpenMW/openmw!3146
This commit is contained in:
psi29a 2023-07-20 07:15:49 +00:00
commit 03dbe1c9f3
21 changed files with 444 additions and 325 deletions

View file

@ -5,46 +5,37 @@
#include <components/misc/strings/algorithm.hpp>
#include <cstdint>
namespace ESM
{
const std::string Skill::sSkillNames[Length] = {
"Block",
"Armorer",
"Mediumarmor",
"Heavyarmor",
"Bluntweapon",
"Longblade",
"Axe",
"Spear",
"Athletics",
"Enchant",
"Destruction",
"Alteration",
"Illusion",
"Conjuration",
"Mysticism",
"Restoration",
"Alchemy",
"Unarmored",
"Security",
"Sneak",
"Acrobatics",
"Lightarmor",
"Shortblade",
"Marksman",
"Mercantile",
"Speechcraft",
"Handtohand",
};
int Skill::stringToSkillId(std::string_view skill)
{
for (int id = 0; id < Skill::Length; ++id)
if (Misc::StringUtils::ciEqual(sSkillNames[id], skill))
return id;
throw std::logic_error("No such skill: " + std::string(skill));
}
const SkillId Skill::Block("Block");
const SkillId Skill::Armorer("Armorer");
const SkillId Skill::MediumArmor("MediumArmor");
const SkillId Skill::HeavyArmor("HeavyArmor");
const SkillId Skill::BluntWeapon("BluntWeapon");
const SkillId Skill::LongBlade("LongBlade");
const SkillId Skill::Axe("Axe");
const SkillId Skill::Spear("Spear");
const SkillId Skill::Athletics("Athletics");
const SkillId Skill::Enchant("Enchant");
const SkillId Skill::Destruction("Destruction");
const SkillId Skill::Alteration("Alteration");
const SkillId Skill::Illusion("Illusion");
const SkillId Skill::Conjuration("Conjuration");
const SkillId Skill::Mysticism("Mysticism");
const SkillId Skill::Restoration("Restoration");
const SkillId Skill::Alchemy("Alchemy");
const SkillId Skill::Unarmored("Unarmored");
const SkillId Skill::Security("Security");
const SkillId Skill::Sneak("Sneak");
const SkillId Skill::Acrobatics("Acrobatics");
const SkillId Skill::LightArmor("LightArmor");
const SkillId Skill::ShortBlade("ShortBlade");
const SkillId Skill::Marksman("Marksman");
const SkillId Skill::Mercantile("Mercantile");
const SkillId Skill::Speechcraft("Speechcraft");
const SkillId Skill::HandToHand("HandToHand");
void Skill::load(ESMReader& esm, bool& isDeleted)
{
@ -53,13 +44,14 @@ namespace ESM
bool hasIndex = false;
bool hasData = false;
int32_t index = -1;
while (esm.hasMoreSubs())
{
esm.getSubName();
switch (esm.retSubName().toInt())
{
case fourCC("INDX"):
esm.getHT(mIndex);
esm.getHT(index);
hasIndex = true;
break;
case fourCC("SKDT"):
@ -75,19 +67,17 @@ namespace ESM
}
if (!hasIndex)
esm.fail("Missing INDX");
else if (mIndex < 0 || mIndex >= Length)
else if (index < 0 || index >= Length)
esm.fail("Invalid INDX");
if (!hasData)
esm.fail("Missing SKDT");
// create an ID from the index and the name (only used in the editor and likely to change in the
// future)
mId = indexToRefId(mIndex);
mId = *indexToRefId(index).getIf<SkillId>();
}
void Skill::save(ESMWriter& esm, bool /*isDeleted*/) const
{
esm.writeHNT("INDX", mIndex);
esm.writeHNT("INDX", refIdToIndex(mId));
esm.writeHNT("SKDT", mData, 24);
esm.writeHNOString("DESC", mDescription);
}
@ -101,11 +91,51 @@ namespace ESM
mDescription.clear();
}
static const RefId sSkills[Skill::Length] = {
Skill::Block,
Skill::Armorer,
Skill::MediumArmor,
Skill::HeavyArmor,
Skill::BluntWeapon,
Skill::LongBlade,
Skill::Axe,
Skill::Spear,
Skill::Athletics,
Skill::Enchant,
Skill::Destruction,
Skill::Alteration,
Skill::Illusion,
Skill::Conjuration,
Skill::Mysticism,
Skill::Restoration,
Skill::Alchemy,
Skill::Unarmored,
Skill::Security,
Skill::Sneak,
Skill::Acrobatics,
Skill::LightArmor,
Skill::ShortBlade,
Skill::Marksman,
Skill::Mercantile,
Skill::Speechcraft,
Skill::HandToHand,
};
RefId Skill::indexToRefId(int index)
{
if (index < 0 || index >= Length)
return RefId();
return RefId::index(sRecordId, static_cast<std::uint32_t>(index));
return sSkills[index];
}
int Skill::refIdToIndex(RefId id)
{
for (int i = 0; i < Length; ++i)
{
if (sSkills[i] == id)
return i;
}
return -1;
}
const std::array<RefId, MagicSchool::Length> sMagicSchools = {

View file

@ -14,6 +14,8 @@ namespace ESM
class ESMReader;
class ESMWriter;
using SkillId = StringRefId;
struct MagicSchool
{
ESM::RefId mAreaSound;
@ -43,7 +45,7 @@ namespace ESM
static std::string_view getRecordType() { return "Skill"; }
unsigned int mRecordFlags;
RefId mId;
SkillId mId;
struct SKDTstruct
{
@ -55,48 +57,40 @@ namespace ESM
}; // Total size: 24 bytes
SKDTstruct mData;
// Skill index. Skils don't have an id ("NAME") like most records,
// they only have a numerical index that matches one of the
// hard-coded skills in the game.
int mIndex{ -1 };
std::string mDescription;
std::string mName;
std::string mIcon;
float mWerewolfValue{};
std::optional<MagicSchool> mSchool;
static constexpr IndexRefId Block{ sRecordId, 0 };
static constexpr IndexRefId Armorer{ sRecordId, 1 };
static constexpr IndexRefId MediumArmor{ sRecordId, 2 };
static constexpr IndexRefId HeavyArmor{ sRecordId, 3 };
static constexpr IndexRefId BluntWeapon{ sRecordId, 4 };
static constexpr IndexRefId LongBlade{ sRecordId, 5 };
static constexpr IndexRefId Axe{ sRecordId, 6 };
static constexpr IndexRefId Spear{ sRecordId, 7 };
static constexpr IndexRefId Athletics{ sRecordId, 8 };
static constexpr IndexRefId Enchant{ sRecordId, 9 };
static constexpr IndexRefId Destruction{ sRecordId, 10 };
static constexpr IndexRefId Alteration{ sRecordId, 11 };
static constexpr IndexRefId Illusion{ sRecordId, 12 };
static constexpr IndexRefId Conjuration{ sRecordId, 13 };
static constexpr IndexRefId Mysticism{ sRecordId, 14 };
static constexpr IndexRefId Restoration{ sRecordId, 15 };
static constexpr IndexRefId Alchemy{ sRecordId, 16 };
static constexpr IndexRefId Unarmored{ sRecordId, 17 };
static constexpr IndexRefId Security{ sRecordId, 18 };
static constexpr IndexRefId Sneak{ sRecordId, 19 };
static constexpr IndexRefId Acrobatics{ sRecordId, 20 };
static constexpr IndexRefId LightArmor{ sRecordId, 21 };
static constexpr IndexRefId ShortBlade{ sRecordId, 22 };
static constexpr IndexRefId Marksman{ sRecordId, 23 };
static constexpr IndexRefId Mercantile{ sRecordId, 24 };
static constexpr IndexRefId Speechcraft{ sRecordId, 25 };
static constexpr IndexRefId HandToHand{ sRecordId, 26 };
static const SkillId Block;
static const SkillId Armorer;
static const SkillId MediumArmor;
static const SkillId HeavyArmor;
static const SkillId BluntWeapon;
static const SkillId LongBlade;
static const SkillId Axe;
static const SkillId Spear;
static const SkillId Athletics;
static const SkillId Enchant;
static const SkillId Destruction;
static const SkillId Alteration;
static const SkillId Illusion;
static const SkillId Conjuration;
static const SkillId Mysticism;
static const SkillId Restoration;
static const SkillId Alchemy;
static const SkillId Unarmored;
static const SkillId Security;
static const SkillId Sneak;
static const SkillId Acrobatics;
static const SkillId LightArmor;
static const SkillId ShortBlade;
static const SkillId Marksman;
static const SkillId Mercantile;
static const SkillId Speechcraft;
static const SkillId HandToHand;
static constexpr int Length = 27;
static const std::string sSkillNames[Length];
static int stringToSkillId(std::string_view skill);
void load(ESMReader& esm, bool& isDeleted);
void save(ESMWriter& esm, bool isDeleted = false) const;
@ -105,6 +99,7 @@ namespace ESM
///< Set record to default state (does not touch the ID/index).
static RefId indexToRefId(int index);
static int refIdToIndex(RefId id);
};
}
#endif

View file

@ -49,7 +49,7 @@ namespace ESM
mWerewolfDeprecatedData = true;
std::vector<StatState<float>> skills(mSkills.begin(), mSkills.end());
for (int i = 0; i < ESM::Skill::Length; ++i)
for (size_t i = 0; i < std::size(mSkills); ++i)
{
StatState<float> skill;
skill.load(esm, intFallback);

View file

@ -54,7 +54,7 @@ namespace ESM
= esm.getFormatVersion() <= MaxClearModifiersFormatVersion && !mObject.mNpcStats.mIsWerewolf;
if (esm.hasMoreSubs())
{
for (int i = 0; i < Attribute::Length; ++i)
for (size_t i = 0; i < std::size(mSaveAttributes); ++i)
{
StatState<float> attribute;
attribute.load(esm, intFallback);
@ -64,7 +64,7 @@ namespace ESM
if (mObject.mNpcStats.mIsWerewolf)
mObject.mCreatureStats.mAttributes[i] = attribute;
}
for (int i = 0; i < Skill::Length; ++i)
for (size_t i = 0; i < std::size(mSaveSkills); ++i)
{
StatState<float> skill;
skill.load(esm, intFallback);