diff --git a/src/game/Unit.cpp b/src/game/Unit.cpp index b2603c4feb..613c9089ed 100644 --- a/src/game/Unit.cpp +++ b/src/game/Unit.cpp @@ -83,35 +83,42 @@ static inline SpellPartialResistDistribution InitSpellPartialResistDistribution( { const uint8 arg = (column > SPELL_PARTIAL_RESIST_PCT_80) ? (100 - percentage) : percentage; if (!(column % SPELL_PARTIAL_RESIST_PCT_100)) - values[column] = uint16(std::roundf((100.0f - (arg * 7.5f)) * 100)); + values[column] = uint16(std::round((100.0f - (arg * 7.5f)) * 100)); else values[column] = uint16(arg * 5 * 100); } else - values[column] = uint16(std::roundf(std::max(0.5f - (2.5f * std::abs((float(column) * 10 / 100) - (float(percentage) / 100))), 0.0f) * 10000)); + values[column] = uint16(std::round(std::max(0.5f - (2.5f * std::abs((float(column) * 10 / 100) - (float(percentage) / 100))), 0.0f) * 10000)); } precalculated.push_back(values); } - // Inflate up to two decimal places of chance %: add intermediate values - SpellPartialResistDistribution inflated; - for (size_t index = 0; index < precalculated.size(); ++index) + // Inflate up to two decimal places of chance %: add all intermediate values and 100% value (100*100 + 1) + SpellPartialResistDistribution inflated(10001, {{}}); + for (size_t row = 0; row < precalculated.size(); ++row) { - for (uint8 intermediate = 0; intermediate < 100; ++intermediate) + const size_t next = (row + 1); + const size_t shift = (row * 100); + const auto &source = precalculated.at(row); + // Check if this is the last one first + if (next == precalculated.size()) { - // Check if this is the last one first - if ((index + 1) == precalculated.size()) - { - inflated.push_back(precalculated[index]); - break; - } - SpellPartialResistChanceEntry values; + for (uint8 column = SPELL_PARTIAL_RESIST_NONE; column < NUM_SPELL_PARTIAL_RESISTS; ++column) + inflated[shift][column] = source.at(column); + break; + } + const auto &ahead = precalculated.at(next); + for (size_t intermediate = 0; intermediate < 100; ++intermediate) + { + const size_t index = (shift + intermediate); + auto &values = inflated[index]; for (uint8 column = SPELL_PARTIAL_RESIST_NONE; column < NUM_SPELL_PARTIAL_RESISTS; ++column) { - const uint32 base = precalculated.at(index).at(column); - const uint32 next = precalculated.at(index + 1).at(column); - values[column] = base + ((next - base) * intermediate / 100); + const uint32 base = source.at(column); + const uint32 upcoming = ahead.at(column); + const int64 diff = (int64(upcoming) - base); + // Use bigger types signed math to avoid potential erratic behavior on some compilers... + values[column] = uint32(std::max(0.0, (base + std::round(diff * (intermediate / double(100.0)))))); } - inflated.push_back(values); } } return inflated;