Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Extract some player attributes to data files #6608

Merged
merged 2 commits into from
Sep 17, 2023
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
6 changes: 6 additions & 0 deletions CMake/Assets.cmake
Original file line number Diff line number Diff line change
Expand Up @@ -142,6 +142,12 @@ set(devilutionx_assets
nlevels/l5data/cornerstone.dun
nlevels/l5data/uberroom.dun
txtdata/Experience.tsv
txtdata/classes/barbarian/attributes.tsv
txtdata/classes/bard/attributes.tsv
txtdata/classes/monk/attributes.tsv
txtdata/classes/rogue/attributes.tsv
txtdata/classes/sorcerer/attributes.tsv
txtdata/classes/warrior/attributes.tsv
ui_art/diablo.pal
ui_art/hellfire.pal
ui_art/creditsw.clx
Expand Down
25 changes: 25 additions & 0 deletions Packaging/resources/assets/txtdata/classes/README.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,25 @@
# Player class data

There is one folder per class.

### attributes.tsv

Attribute | Description
-------------:|--------------------------------------
`baseStr` | Class Starting Strength Stat, uint8_t
`baseMag` | Class Starting Magic Stat, uint8_t
`baseDex` | Class Starting Dexterity Stat, uint8_t
`baseVit` | Class Starting Vitality Stat, uint8_t
`maxStr` | Class Maximum Strength Stat, uint8_t
`maxMag` | Class Maximum Magic Stat, uint8_t
`maxDex` | Class Maximum Dexterity Stat, uint8_t
`maxVit` | Class Maximum Vitality Stat, uint8_t
`blockBonus` | Class Block Bonus, %
`adjLife` | Class Life Adjustment, decimal
`adjMana` | Class Mana Adjustment, decimal
`lvlLife` | Life gained on level up, decimal
`lvlMana` | Mana gained on level up, decimal
`chrLife` | Life from base Vitality, decimal
`chrMana` | Mana from base Magic, decimal
`itmLife` | Life from item bonus Vitality, decimal
`itmMana` | Mana from item bonus Magic, decimal
Original file line number Diff line number Diff line change
@@ -0,0 +1,18 @@
Attribute Value
baseStr 40
baseMag 0
baseDex 20
baseVit 25
maxStr 255
maxMag 0
maxDex 55
maxVit 150
blockBonus 30
adjLife 18
adjMana 0
lvlLife 2
lvlMana 0
chrLife 2
chrMana 1
itmLife 2.5
itmMana 1
18 changes: 18 additions & 0 deletions Packaging/resources/assets/txtdata/classes/bard/attributes.tsv
Original file line number Diff line number Diff line change
@@ -0,0 +1,18 @@
Attribute Value
baseStr 20
baseMag 20
baseDex 25
baseVit 20
maxStr 120
maxMag 120
maxDex 120
maxVit 100
blockBonus 25
adjLife 23
adjMana 3
lvlLife 2
lvlMana 2
chrLife 1
chrMana 1.5
itmLife 1.5
itmMana 1.75
18 changes: 18 additions & 0 deletions Packaging/resources/assets/txtdata/classes/monk/attributes.tsv
Original file line number Diff line number Diff line change
@@ -0,0 +1,18 @@
Attribute Value
baseStr 25
baseMag 15
baseDex 25
baseVit 20
maxStr 150
maxMag 80
maxDex 150
maxVit 80
blockBonus 25
adjLife 23
adjMana 5.5
lvlLife 2
lvlMana 2
chrLife 1
chrMana 1
itmLife 1.5
itmMana 1.5
18 changes: 18 additions & 0 deletions Packaging/resources/assets/txtdata/classes/rogue/attributes.tsv
Original file line number Diff line number Diff line change
@@ -0,0 +1,18 @@
Attribute Value
baseStr 20
baseMag 15
baseDex 30
baseVit 20
maxStr 55
maxMag 70
maxDex 250
maxVit 80
blockBonus 20
adjLife 23
adjMana 5.5
lvlLife 2
lvlMana 2
chrLife 1
chrMana 1
itmLife 1.5
itmMana 1.5
18 changes: 18 additions & 0 deletions Packaging/resources/assets/txtdata/classes/sorcerer/attributes.tsv
Original file line number Diff line number Diff line change
@@ -0,0 +1,18 @@
Attribute Value
baseStr 15
baseMag 35
baseDex 15
baseVit 20
maxStr 45
maxMag 250
maxDex 85
maxVit 80
blockBonus 10
adjLife 9
adjMana -2
lvlLife 1
lvlMana 2
chrLife 1
chrMana 2
itmLife 1
itmMana 2
18 changes: 18 additions & 0 deletions Packaging/resources/assets/txtdata/classes/warrior/attributes.tsv
Original file line number Diff line number Diff line change
@@ -0,0 +1,18 @@
Attribute Value
baseStr 30
baseMag 10
baseDex 20
baseVit 25
maxStr 250
maxMag 50
maxDex 60
maxVit 100
blockBonus 30
adjLife 18
adjMana -1
lvlLife 2
lvlMana 1
chrLife 2
chrMana 1
itmLife 2
itmMana 1
12 changes: 12 additions & 0 deletions Source/data/file.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -115,4 +115,16 @@ tl::expected<void, DataFile::Error> DataFile::parseHeader(ColumnDefinition *begi
}
return {};
}

tl::expected<void, DataFile::Error> DataFile::skipHeader()
{
RecordIterator it { data(), data() + size(), false };
++it;
if (it == this->end()) {
return tl::unexpected { Error::NoContent };
}
body_ = it.data();
return {};
}

} // namespace devilution
2 changes: 2 additions & 0 deletions Source/data/file.hpp
Original file line number Diff line number Diff line change
Expand Up @@ -107,6 +107,8 @@ class DataFile {
return parseHeader(begin, end, [typedMapper](std::string_view label) { return typedMapper(label).transform([](T value) { return static_cast<uint8_t>(value); }); });
}

[[nodiscard]] tl::expected<void, DataFile::Error> skipHeader();

[[nodiscard]] RecordIterator begin() const
{
return { body_, data() + size(), body_ != data() };
Expand Down
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
4 changes: 2 additions & 2 deletions Source/items.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -2747,10 +2747,10 @@ void CalcPlrItemVals(Player &player, bool loadgfx)
player._pFireResist = std::clamp(fr, 0, MaxResistance);
player._pLghtResist = std::clamp(lr, 0, MaxResistance);

vadd = (vadd * PlayersData[static_cast<size_t>(player._pClass)].itmLife) >> 6;
vadd = (vadd * GetClassAttributes(player._pClass).itmLife) >> 6;
ihp += (vadd << 6); // BUGFIX: blood boil can cause negative shifts here (see line 757)

madd = (madd * PlayersData[static_cast<size_t>(player._pClass)].itmMana) >> 6;
madd = (madd * GetClassAttributes(player._pClass).itmMana) >> 6;
imana += (madd << 6);

player._pMaxHP = ihp + player._pMaxHPBase;
Expand Down
2 changes: 1 addition & 1 deletion Source/loadsave.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -414,7 +414,7 @@ void LoadPlayer(LoadHelper &file, Player &player)
player._pDamageMod = file.NextLE<int32_t>();
player._pBaseToBlk = file.NextLE<int32_t>();
if (player._pBaseToBlk == 0)
player._pBaseToBlk = PlayersData[static_cast<std::size_t>(player._pClass)].blockBonus;
player._pBaseToBlk = GetClassAttributes(player._pClass).blockBonus;
player._pHPBase = file.NextLE<int32_t>();
player._pMaxHPBase = file.NextLE<int32_t>();
player._pHitPoints = file.NextLE<int32_t>();
Expand Down
4 changes: 2 additions & 2 deletions Source/pack.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -453,7 +453,7 @@ void UnPackPlayer(const PlayerPack &packed, Player &player)

player._pExperience = SDL_SwapLE32(packed.pExperience);
player._pGold = SDL_SwapLE32(packed.pGold);
player._pBaseToBlk = PlayersData[static_cast<std::size_t>(player._pClass)].blockBonus;
player._pBaseToBlk = GetClassAttributes(player._pClass).blockBonus;
if ((int)(player._pHPBase & 0xFFFFFFC0) < 64)
player._pHPBase = 64;

Expand Down Expand Up @@ -542,7 +542,7 @@ bool UnPackNetPlayer(const PlayerNetPack &packed, Player &player)
player._pStatPts = packed.pStatPts;

player._pExperience = SDL_SwapLE32(packed.pExperience);
player._pBaseToBlk = PlayersData[static_cast<std::size_t>(player._pClass)].blockBonus;
player._pBaseToBlk = GetClassAttributes(player._pClass).blockBonus;
player._pMaxManaBase = baseManaMax;
player._pManaBase = baseMana;
player._pMemSpells = SDL_SwapLE64(packed.pMemSpells);
Expand Down
9 changes: 5 additions & 4 deletions Source/pfile.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -678,10 +678,11 @@ bool pfile_ui_set_hero_infos(bool (*uiAddHeroInfo)(_uiheroinfo *))

void pfile_ui_set_class_stats(unsigned int playerClass, _uidefaultstats *classStats)
{
classStats->strength = PlayersData[playerClass].baseStr;
classStats->magic = PlayersData[playerClass].baseMag;
classStats->dexterity = PlayersData[playerClass].baseDex;
classStats->vitality = PlayersData[playerClass].baseVit;
const ClassAttributes &classAttributes = GetClassAttributes(static_cast<HeroClass>(playerClass));
classStats->strength = classAttributes.baseStr;
classStats->magic = classAttributes.baseMag;
classStats->dexterity = classAttributes.baseDex;
classStats->vitality = classAttributes.baseVit;
}

uint32_t pfile_ui_get_first_unused_save_num()
Expand Down
44 changes: 22 additions & 22 deletions Source/player.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -1703,16 +1703,16 @@ int Player::GetCurrentAttributeValue(CharacterAttribute attribute) const

int Player::GetMaximumAttributeValue(CharacterAttribute attribute) const
{
PlayerData plrData = PlayersData[static_cast<std::size_t>(_pClass)];
const ClassAttributes &attr = GetClassAttributes(_pClass);
switch (attribute) {
case CharacterAttribute::Strength:
return plrData.maxStr;
return attr.maxStr;
case CharacterAttribute::Magic:
return plrData.maxMag;
return attr.maxMag;
case CharacterAttribute::Dexterity:
return plrData.maxDex;
return attr.maxDex;
case CharacterAttribute::Vitality:
return plrData.maxVit;
return attr.maxVit;
}
app_fatal("Unsupported attribute");
}
Expand Down Expand Up @@ -2062,14 +2062,14 @@ uint32_t Player::getNextExperienceThreshold() const

int32_t Player::calculateBaseLife() const
{
const PlayerData &playerData = PlayersData[static_cast<size_t>(_pClass)];
return playerData.adjLife + (playerData.lvlLife * getCharacterLevel()) + (playerData.chrLife * _pBaseVit);
const ClassAttributes &attr = GetClassAttributes(_pClass);
return attr.adjLife + (attr.lvlLife * getCharacterLevel()) + (attr.chrLife * _pBaseVit);
}

int32_t Player::calculateBaseMana() const
{
const PlayerData &playerData = PlayersData[static_cast<size_t>(_pClass)];
return playerData.adjMana + (playerData.lvlMana * getCharacterLevel()) + (playerData.chrMana * _pBaseMag);
const ClassAttributes &attr = GetClassAttributes(_pClass);
return attr.adjMana + (attr.lvlMana * getCharacterLevel()) + (attr.chrMana * _pBaseMag);
}

Player *PlayerAtPosition(Point position)
Expand Down Expand Up @@ -2279,24 +2279,24 @@ void CreatePlayer(Player &player, HeroClass c)
player = {};
SetRndSeed(SDL_GetTicks());

const PlayerData &playerData = PlayersData[static_cast<size_t>(c)];
const ClassAttributes &attr = GetClassAttributes(c);

player.setCharacterLevel(1);
player._pClass = c;

player._pBaseStr = playerData.baseStr;
player._pBaseStr = attr.baseStr;
player._pStrength = player._pBaseStr;

player._pBaseMag = playerData.baseMag;
player._pBaseMag = attr.baseMag;
player._pMagic = player._pBaseMag;

player._pBaseDex = playerData.baseDex;
player._pBaseDex = attr.baseDex;
player._pDexterity = player._pBaseDex;

player._pBaseVit = playerData.baseVit;
player._pBaseVit = attr.baseVit;
player._pVitality = player._pBaseVit;

player._pBaseToBlk = playerData.blockBonus;
player._pBaseToBlk = attr.blockBonus;

player._pHitPoints = player.calculateBaseLife();
player._pMaxHP = player._pHitPoints;
Expand All @@ -2314,7 +2314,7 @@ void CreatePlayer(Player &player, HeroClass c)
player._pInfraFlag = false;

player._pRSplType = SpellType::Skill;
SpellID s = playerData.skill;
SpellID s = PlayersData[static_cast<size_t>(c)].skill;
player._pAblSpells = GetSpellBitmask(s);
player._pRSpell = s;

Expand Down Expand Up @@ -2397,7 +2397,7 @@ void NextPlrLevel(Player &player)
} else {
player._pStatPts += 5;
}
int hp = PlayersData[static_cast<size_t>(player._pClass)].lvlLife;
int hp = GetClassAttributes(player._pClass).lvlLife;

player._pMaxHP += hp;
player._pHitPoints = player._pMaxHP;
Expand All @@ -2408,7 +2408,7 @@ void NextPlrLevel(Player &player)
RedrawComponent(PanelDrawComponent::Health);
}

int mana = PlayersData[static_cast<size_t>(player._pClass)].lvlMana;
int mana = GetClassAttributes(player._pClass).lvlMana;

player._pMaxMana += mana;
player._pMaxManaBase += mana;
Expand Down Expand Up @@ -3329,7 +3329,7 @@ void ModifyPlrMag(Player &player, int l)
player._pBaseMag += l;

int ms = l;
ms *= PlayersData[static_cast<size_t>(player._pClass)].chrMana;
ms *= GetClassAttributes(player._pClass).chrMana;

player._pMaxManaBase += ms;
player._pMaxMana += ms;
Expand Down Expand Up @@ -3366,7 +3366,7 @@ void ModifyPlrVit(Player &player, int l)
player._pBaseVit += l;

int ms = l;
ms *= PlayersData[static_cast<size_t>(player._pClass)].chrLife;
ms *= GetClassAttributes(player._pClass).chrLife;

player._pHPBase += ms;
player._pMaxHPBase += ms;
Expand Down Expand Up @@ -3401,7 +3401,7 @@ void SetPlrMag(Player &player, int v)
player._pBaseMag = v;

int m = v;
m *= PlayersData[static_cast<size_t>(player._pClass)].chrMana;
m *= GetClassAttributes(player._pClass).chrMana;

player._pMaxManaBase = m;
player._pMaxMana = m;
Expand All @@ -3419,7 +3419,7 @@ void SetPlrVit(Player &player, int v)
player._pBaseVit = v;

int hp = v;
hp *= PlayersData[static_cast<size_t>(player._pClass)].chrLife;
hp *= GetClassAttributes(player._pClass).chrLife;

player._pHPBase = hp;
player._pMaxHPBase = hp;
Expand Down
Loading
Loading