1
0
mirror of https://github.com/vcmi/vcmi.git synced 2025-09-16 09:26:28 +02:00

Fix handling of bonuses with negative values

This commit is contained in:
Ivan Savenko
2025-06-26 15:45:04 +03:00
parent 31786c8135
commit d1f9c497a3
4 changed files with 19 additions and 6 deletions

View File

@@ -712,13 +712,16 @@ namespace vstd
return a + (b - a) * f; return a + (b - a) * f;
} }
/// Divides dividend by divisor and rounds result up /// Divides dividend by divisor and rounds result away from zero
/// For use with integer-only arithmetic /// For use with integer-only arithmetic
template<typename Integer1, typename Integer2> template<typename Integer1, typename Integer2>
Integer1 divideAndCeil(const Integer1 & dividend, const Integer2 & divisor) Integer1 divideAndCeil(const Integer1 & dividend, const Integer2 & divisor)
{ {
static_assert(std::is_integral_v<Integer1> && std::is_integral_v<Integer2>, "This function should only be used with integral types"); static_assert(std::is_integral_v<Integer1> && std::is_integral_v<Integer2>, "This function should only be used with integral types");
return (dividend + divisor - 1) / divisor; if (dividend >= 0)
return (dividend + divisor - 1) / divisor;
else
return (dividend - divisor + 1) / divisor;
} }
/// Divides dividend by divisor and rounds result to nearest /// Divides dividend by divisor and rounds result to nearest
@@ -727,10 +730,13 @@ namespace vstd
Integer1 divideAndRound(const Integer1 & dividend, const Integer2 & divisor) Integer1 divideAndRound(const Integer1 & dividend, const Integer2 & divisor)
{ {
static_assert(std::is_integral_v<Integer1> && std::is_integral_v<Integer2>, "This function should only be used with integral types"); static_assert(std::is_integral_v<Integer1> && std::is_integral_v<Integer2>, "This function should only be used with integral types");
return (dividend + divisor / 2 - 1) / divisor; if (dividend >= 0)
return (dividend + divisor / 2 - 1) / divisor;
else
return (dividend - divisor / 2 + 1) / divisor;
} }
/// Divides dividend by divisor and rounds result down /// Divides dividend by divisor and rounds result towards zero
/// For use with integer-only arithmetic /// For use with integer-only arithmetic
template<typename Integer1, typename Integer2> template<typename Integer1, typename Integer2>
Integer1 divideAndFloor(const Integer1 & dividend, const Integer2 & divisor) Integer1 divideAndFloor(const Integer1 & dividend, const Integer2 & divisor)

View File

@@ -112,8 +112,9 @@ Example of long form with custom parameters:
Effect: Updates val to `val = clamp(val * floor(stackSize / stepSize), minimum, maximum)`, where stackSize is total number of creatures in hero army that fulful filter Effect: Updates val to `val = clamp(val * floor(stackSize / stepSize), minimum, maximum)`, where stackSize is total number of creatures in hero army that fulful filter
Parameters: Parameters:
- `minimum`: minimum possible value of the bonus value. Unlimited by default - `minimum`: minimum possible value of the bonus value. Unlimited by default
- `minimum`: maximum possible value of the bonus value. Unlimited by default - `maximum`: maximum possible value of the bonus value. Unlimited by default
- `stepSize`: number of units needed to increase updater multiplier by 1 - `stepSize`: number of units needed to increase updater multiplier by 1
- `filteredCreature`: identifier of specific unit to filter - `filteredCreature`: identifier of specific unit to filter
- `filteredLevel`: level of units that need to be counted. Redundant if `filteredCreature` is used - `filteredLevel`: level of units that need to be counted. Redundant if `filteredCreature` is used

View File

@@ -70,7 +70,10 @@ int BonusList::totalValue(int baseValue) const
}; };
auto applyPercentageRoundUp = [](int base, int percent) -> int { auto applyPercentageRoundUp = [](int base, int percent) -> int {
return (static_cast<int64_t>(base) * (100 + percent) + 99) / 100; if (base >= 0)
return (static_cast<int64_t>(base) * (100 + percent) + 99) / 100;
else
return (static_cast<int64_t>(base) * (100 + percent) - 99) / 100;
}; };
auto applyPercentageRoundDown = [](int base, int percent) -> int { auto applyPercentageRoundDown = [](int base, int percent) -> int {

View File

@@ -134,6 +134,9 @@ public:
h & minimum; h & minimum;
h & maximum; h & maximum;
h & stepSize; h & stepSize;
h & filteredLevel;
h & filteredCreature;
h & filteredFaction;
} }
}; };