Skip to content

Commit

Permalink
Fix up tooltip display when min and max damage are both present.
Browse files Browse the repository at this point in the history
Simplify chained attributes logic
  • Loading branch information
WalterCouto committed Oct 2, 2022
1 parent ca07884 commit 91c89ec
Show file tree
Hide file tree
Showing 13 changed files with 483 additions and 234 deletions.
37 changes: 18 additions & 19 deletions source/d2ce/DataTypes.h
Original file line number Diff line number Diff line change
Expand Up @@ -1193,25 +1193,24 @@ namespace d2ce
//---------------------------------------------------------------------------
struct ItemStat
{
std::uint16_t id = 0; // internal ID
std::string name; // An Id pointer used in other *.txt files (Properties.txt, Skills.txt, States.txt and also within ItemStatCost.txt) to refer to this stat, this field must be unique, otherwise you're looking into a world of glitches and bugs.
std::uint16_t charSaveBits = 0; // How many bits of data are allocated to the value of this stat within the *.d2s file stat section when the stat is saved
std::uint8_t encode = 0; // This field tells the game whenever to encode the stat (and in this case in what way to encode it) when it is saved to conserve space
std::uint16_t saveBits = 0; // These fields control how many bits of data are allocated to the value of this stat within the *.d2s fil
std::int16_t saveAdd = 0;
std::uint16_t saveParamBits = 0; // This field controls how many bits of data are allocated to the parameter of this stat when it is saved on items
OpAttributes opAttribs; // These fields control special forms of stat assignment used for example for stats that add a bonus depending on cLvl
std::uint8_t descPriority = 0; // The higher this value is the further up in the item description this stat will be listed
std::uint8_t descFunc = 0; // The function used for generating the description for this stat, this works like the descfuncs in SkillDesc.txt pretty much
std::uint8_t descVal = 0; // Controls whenever and if so in what way the stat value is shown, 0 = doesn't show the value of the stat, 1 = shows the value of the stat infront of the description, 2 = shows the value of the stat after the description.
std::string desc; // base description string
std::string descNeg; // The string used for the description when the stat value is negative.
std::string descGrp; // When all stats in this group are present on the same item and they all have the same value, replace their description with the associated group description.
std::string descGrpNeg; // The string used for the description when the stat value is negative for the group
std::string descRange; // The description used for range stats (i.e. fire damage)
std::string descNoRange; // The description used for ragne stats when the min/max value is the same
std::uint16_t nextInChain = 0; // stat that follows this one (i.e. firemaxdam follows firemindam)
bool isRootInChain = false; // is this the root of the chain?
std::uint16_t id = 0; // internal ID
std::string name; // An Id pointer used in other *.txt files (Properties.txt, Skills.txt, States.txt and also within ItemStatCost.txt) to refer to this stat, this field must be unique, otherwise you're looking into a world of glitches and bugs.
std::uint16_t charSaveBits = 0; // How many bits of data are allocated to the value of this stat within the *.d2s file stat section when the stat is saved
std::uint8_t encode = 0; // This field tells the game whenever to encode the stat (and in this case in what way to encode it) when it is saved to conserve space
std::uint16_t saveBits = 0; // These fields control how many bits of data are allocated to the value of this stat within the *.d2s fil
std::int16_t saveAdd = 0;
std::uint16_t saveParamBits = 0; // This field controls how many bits of data are allocated to the parameter of this stat when it is saved on items
OpAttributes opAttribs; // These fields control special forms of stat assignment used for example for stats that add a bonus depending on cLvl
std::uint8_t descPriority = 0; // The higher this value is the further up in the item description this stat will be listed
std::uint8_t descFunc = 0; // The function used for generating the description for this stat, this works like the descfuncs in SkillDesc.txt pretty much
std::uint8_t descVal = 0; // Controls whenever and if so in what way the stat value is shown, 0 = doesn't show the value of the stat, 1 = shows the value of the stat infront of the description, 2 = shows the value of the stat after the description.
std::string desc; // base description string
std::string descNeg; // The string used for the description when the stat value is negative.
std::string descGrp; // When all stats in this group are present on the same item and they all have the same value, replace their description with the associated group description.
std::string descGrpNeg; // The string used for the description when the stat value is negative for the group
std::string descRange; // The description used for range stats (i.e. fire damage)
std::string descNoRange; // The description used for ragne stats when the min/max value is the same
std::vector<std::uint16_t> nextInChain; // stats that follows this one (i.e. firemaxdam follows firemindam)
};

//---------------------------------------------------------------------------
Expand Down
41 changes: 24 additions & 17 deletions source/d2ce/Item.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -16347,10 +16347,12 @@ bool d2ce::Item::parsePropertyList(std::FILE* charfile, size_t& current_bit_offs
numParms = 1;
}

nextInChain = stat.isRootInChain ? stat.nextInChain : 0;
while (nextInChain && numParms < 4)
auto nextInChainIter = stat.nextInChain.begin();
auto nextInChainIterEnd = stat.nextInChain.end();
for (; nextInChainIter != nextInChainIterEnd && numParms < 4; ++nextInChainIter)
{
const auto& statNext = ItemHelpers::getItemStat(getVersion(), nextInChain);
nextInChain = *nextInChainIter;
const auto& statNext = ItemHelpers::getItemStat(getVersion(), *nextInChainIter);
if (statNext.id != nextInChain)
{
// corrupt file
Expand All @@ -16368,7 +16370,6 @@ bool d2ce::Item::parsePropertyList(std::FILE* charfile, size_t& current_bit_offs
// corrupt file
return false;
}
nextInChain = statNext.nextInChain;
++numParms;
}

Expand Down Expand Up @@ -16479,9 +16480,12 @@ bool d2ce::Item::parsePropertyList(const Json::Value& propListRoot, bool bSerial
node = iter->operator[]("Value");
values.push_back(SafeGetNodeValue(node));

nextInChain = stat.isRootInChain ? stat.nextInChain : 0;
while (nextInChain && values.size() < 4)
auto nextInChainIter = stat.nextInChain.begin();
auto nextInChainIterEnd = stat.nextInChain.end();
for (; nextInChainIter != nextInChainIterEnd && values.size() < 4; ++nextInChainIter)
{
nextInChain = *nextInChainIter;

++iter;
if (iter == iter_end)
{
Expand Down Expand Up @@ -16518,7 +16522,6 @@ bool d2ce::Item::parsePropertyList(const Json::Value& propListRoot, bool bSerial

node = iter->operator[]("Value");
values.push_back(SafeGetNodeValue(node));
nextInChain = statNext.nextInChain;
}
}
}
Expand Down Expand Up @@ -16766,9 +16769,12 @@ bool d2ce::Item::parsePropertyList(const Json::Value& propListRoot, bool bSerial
}
}

nextInChain = stat.isRootInChain ? stat.nextInChain : 0;
while (nextInChain && valueIdx < 4)
auto nextInChainIter = stat.nextInChain.begin();
auto nextInChainIterEnd = stat.nextInChain.end();
for (; nextInChainIter != nextInChainIterEnd && valueIdx < 4; ++nextInChainIter)
{
nextInChain = *nextInChainIter;

const auto& statNext = ItemHelpers::getItemStat(getVersion(), nextInChain);
if (statNext.id != nextInChain)
{
Expand All @@ -16793,7 +16799,6 @@ bool d2ce::Item::parsePropertyList(const Json::Value& propListRoot, bool bSerial
{
return false;
}
nextInChain = statNext.nextInChain;
}
}

Expand Down Expand Up @@ -16841,7 +16846,7 @@ bool d2ce::Item::readPropertyList(size_t& current_bit_offset, std::vector<Magica

magicalAttrib.Id = stat.id;
magicalAttrib.Name = stat.name;
magicalAttrib.Desc = stat.nextInChain != 0 && stat.isRootInChain ? stat.descRange : stat.desc;
magicalAttrib.Desc = stat.nextInChain.empty() ? stat.desc : stat.descRange;
magicalAttrib.Version = itemVersion;
magicalAttrib.GameVersion = gameVersion;
magicalAttrib.DescPriority = stat.descPriority;
Expand Down Expand Up @@ -16938,9 +16943,11 @@ bool d2ce::Item::readPropertyList(size_t& current_bit_offset, std::vector<Magica
current_bit_offset += stat.saveBits;
}

nextInChain = stat.isRootInChain ? stat.nextInChain : 0;
while (nextInChain && magicalAttrib.Values.size() < 4)
auto nextInChainIter = stat.nextInChain.begin();
auto nextInChainIterEnd = stat.nextInChain.end();
for (; nextInChainIter != nextInChainIterEnd && magicalAttrib.Values.size() < 4; ++nextInChainIter)
{
nextInChain = *nextInChainIter;
const auto& statNext = ItemHelpers::getItemStat(itemVersion, nextInChain);
if (statNext.id != nextInChain)
{
Expand All @@ -16956,7 +16963,6 @@ bool d2ce::Item::readPropertyList(size_t& current_bit_offset, std::vector<Magica

magicalAttrib.Values.push_back(readBits64(current_bit_offset, statNext.saveBits) - statNext.saveAdd);
current_bit_offset += statNext.saveBits;
nextInChain = statNext.nextInChain;
}

attrib.push_back(magicalAttrib);
Expand Down Expand Up @@ -17249,9 +17255,11 @@ bool d2ce::Item::updatePropertyList(size_t& current_bit_offset, const std::vecto
std::advance(iterValue, 1);
}

nextInChain = stat.isRootInChain ? stat.nextInChain : 0;
while (nextInChain)
auto nextInChainIter = stat.nextInChain.begin();
auto nextInChainIterEnd = stat.nextInChain.end();
for (; nextInChainIter != nextInChainIterEnd; ++nextInChainIter)
{
nextInChain = *nextInChainIter;
if (iterValue == iterValueEnd)
{
return false;
Expand All @@ -17276,7 +17284,6 @@ bool d2ce::Item::updatePropertyList(size_t& current_bit_offset, const std::vecto
return false;
}

nextInChain = statNext.nextInChain;
std::advance(iterValue, 1);
}

Expand Down
Loading

0 comments on commit 91c89ec

Please sign in to comment.