Skip to content

Commit

Permalink
LoadClassAttributes: Mandate field order
Browse files Browse the repository at this point in the history
Makes parsing simpler.

Additional columns and rows are ignored.
  • Loading branch information
glebm committed Sep 17, 2023
1 parent 345cd3e commit da49487
Show file tree
Hide file tree
Showing 8 changed files with 90 additions and 97 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -8,11 +8,11 @@ maxMag 0
maxDex 55
maxVit 150
blockBonus 30
adjLife 1152
adjLife 18
adjMana 0
lvlLife 128
lvlLife 2
lvlMana 0
chrLife 128
chrMana 64
itmLife 160
itmMana 64
chrLife 2
chrMana 1
itmLife 2.5
itmMana 1
16 changes: 8 additions & 8 deletions Packaging/resources/assets/txtdata/classes/bard/attributes.tsv
Original file line number Diff line number Diff line change
Expand Up @@ -8,11 +8,11 @@ maxMag 120
maxDex 120
maxVit 100
blockBonus 25
adjLife 1472
adjMana 192
lvlLife 128
lvlMana 128
chrLife 64
chrMana 96
itmLife 96
itmMana 112
adjLife 23
adjMana 3
lvlLife 2
lvlMana 2
chrLife 1
chrMana 1.5
itmLife 1.5
itmMana 1.75
16 changes: 8 additions & 8 deletions Packaging/resources/assets/txtdata/classes/monk/attributes.tsv
Original file line number Diff line number Diff line change
Expand Up @@ -8,11 +8,11 @@ maxMag 80
maxDex 150
maxVit 80
blockBonus 25
adjLife 1472
adjMana 352
lvlLife 128
lvlMana 128
chrLife 64
chrMana 64
itmLife 96
itmMana 96
adjLife 23
adjMana 5.5
lvlLife 2
lvlMana 2
chrLife 1
chrMana 1
itmLife 1.5
itmMana 1.5
16 changes: 8 additions & 8 deletions Packaging/resources/assets/txtdata/classes/rogue/attributes.tsv
Original file line number Diff line number Diff line change
Expand Up @@ -8,11 +8,11 @@ maxMag 70
maxDex 250
maxVit 80
blockBonus 20
adjLife 1472
adjMana 352
lvlLife 128
lvlMana 128
chrLife 64
chrMana 64
itmLife 96
itmMana 96
adjLife 23
adjMana 5.5
lvlLife 2
lvlMana 2
chrLife 1
chrMana 1
itmLife 1.5
itmMana 1.5
Original file line number Diff line number Diff line change
Expand Up @@ -8,11 +8,11 @@ maxMag 250
maxDex 85
maxVit 80
blockBonus 10
adjLife 576
adjMana -128
lvlLife 64
lvlMana 128
chrLife 64
chrMana 128
itmLife 64
itmMana 128
adjLife 9
adjMana -2
lvlLife 1
lvlMana 2
chrLife 1
chrMana 2
itmLife 1
itmMana 2
Original file line number Diff line number Diff line change
Expand Up @@ -8,11 +8,11 @@ maxMag 50
maxDex 60
maxVit 100
blockBonus 30
adjLife 1152
adjMana -64
lvlLife 128
lvlMana 64
chrLife 128
chrMana 64
itmLife 128
itmMana 64
adjLife 18
adjMana -1
lvlLife 2
lvlMana 1
chrLife 2
chrMana 1
itmLife 2
itmMana 1
4 changes: 2 additions & 2 deletions Source/data/iterators.hpp
Original file line number Diff line number Diff line change
Expand Up @@ -25,9 +25,9 @@ class DataFileField {

static tl::expected<void, Error> mapError(std::errc ec)
{
switch (ec) {
case std::errc():
if (ec == std::errc())
return {};
switch (ec) {
case std::errc::result_out_of_range:
return tl::unexpected { Error::OutOfRange };
case std::errc::invalid_argument:
Expand Down
91 changes: 42 additions & 49 deletions Source/playerdat.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -11,8 +11,6 @@
#include <bitset>
#include <charconv>
#include <cstdint>
#include <unordered_map>
#include <variant>
#include <vector>

#include <expected.hpp>
Expand Down Expand Up @@ -169,65 +167,60 @@ void LoadClassAttributes(std::string_view classPath, ClassAttributes &out)
DataFile::reportFatalError(result.error(), filename);
}

struct KeyInfo {
std::variant<uint8_t *, int16_t *> out;
bool found = false;
};
std::unordered_map<std::string_view, KeyInfo> keyToField {
{ "baseStr", KeyInfo { &out.baseStr } },
{ "baseMag", KeyInfo { &out.baseMag } },
{ "baseDex", KeyInfo { &out.baseDex } },
{ "baseVit", KeyInfo { &out.baseVit } },
{ "maxStr", KeyInfo { &out.maxStr } },
{ "maxMag", KeyInfo { &out.maxMag } },
{ "maxDex", KeyInfo { &out.maxDex } },
{ "maxVit", KeyInfo { &out.maxVit } },
{ "blockBonus", KeyInfo { &out.blockBonus } },
{ "adjLife", KeyInfo { &out.adjLife } },
{ "adjMana", KeyInfo { &out.adjMana } },
{ "lvlLife", KeyInfo { &out.lvlLife } },
{ "lvlMana", KeyInfo { &out.lvlMana } },
{ "chrLife", KeyInfo { &out.chrLife } },
{ "chrMana", KeyInfo { &out.chrMana } },
{ "itmLife", KeyInfo { &out.itmLife } },
{ "itmMana", KeyInfo { &out.itmMana } },
};
for (DataFileRecord record : dataFile) {
auto recordIt = dataFile.begin();
const auto recordEnd = dataFile.end();

const auto getValueField = [&](std::string_view expectedKey) {
if (recordIt == recordEnd) {
app_fatal(fmt::format("Missing field {} in {}", expectedKey, filename));
}
DataFileRecord record = *recordIt;
FieldIterator fieldIt = record.begin();
const FieldIterator endField = record.end();

const std::string_view key = (*fieldIt).value();
if (key != expectedKey) {
app_fatal(fmt::format("Unexpected field in {}: got {}, expected {}", filename, key, expectedKey));
}

++fieldIt;
if (fieldIt == endField) {
DataFile::reportFatalError(DataFile::Error::NotEnoughColumns, filename);
}
DataFileField valueField = *fieldIt;
return *fieldIt;
};

auto mappingIt = keyToField.find(key);
if (mappingIt == keyToField.end()) {
app_fatal(fmt::format("Unknown field {} in {}", key, filename));
const auto readRecord = [&](std::string_view expectedKey, auto &outValue) {
DataFileField valueField = getValueField(expectedKey);
tl::expected<void, devilution::DataFileField::Error> parseIntResult;
if constexpr (std::is_same_v<std::remove_cvref_t<decltype(outValue)>, int16_t>) {
parseIntResult = valueField.parseFixed6(outValue);
} else {
parseIntResult = valueField.parseInt(outValue);
}
KeyInfo &keyInfo = mappingIt->second;
if (keyInfo.found) {
app_fatal(fmt::format("Duplicate field {} in {}", key, filename));
if (!parseIntResult.has_value()) {
DataFile::reportFatalFieldError(parseIntResult.error(), filename, "Value", valueField);
}
std::visit([&](auto *outField) {
auto parseIntResult = valueField.parseInt(*outField);
if (parseIntResult != std::errc()) {
DataFile::reportFatalFieldError(parseIntResult, filename, "Value", valueField);
}
},
keyInfo.out);
keyInfo.found = true;

++fieldIt;
}
++recordIt;
};

for (const auto &[key, keyInfo] : keyToField) {
if (!keyInfo.found) {
app_fatal(fmt::format("Missing field {} in {}", key, filename));
}
}
readRecord("baseStr", out.baseStr);
readRecord("baseMag", out.baseMag);
readRecord("baseDex", out.baseDex);
readRecord("baseVit", out.baseVit);
readRecord("maxStr", out.maxStr);
readRecord("maxMag", out.maxMag);
readRecord("maxDex", out.maxDex);
readRecord("maxVit", out.maxVit);
readRecord("blockBonus", out.blockBonus);
readRecord("adjLife", out.adjLife);
readRecord("adjMana", out.adjMana);
readRecord("lvlLife", out.lvlLife);
readRecord("lvlMana", out.lvlMana);
readRecord("chrLife", out.chrLife);
readRecord("chrMana", out.chrMana);
readRecord("itmLife", out.itmLife);
readRecord("itmMana", out.itmMana);
}

std::vector<ClassAttributes> ClassAttributesPerClass;
Expand Down

0 comments on commit da49487

Please sign in to comment.