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;
}
/// Divides dividend by divisor and rounds result up
/// Divides dividend by divisor and rounds result away from zero
/// For use with integer-only arithmetic
template<typename Integer1, typename Integer2>
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");
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
@@ -727,10 +730,13 @@ namespace vstd
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");
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
template<typename Integer1, typename Integer2>
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
Parameters:
- `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
- `filteredCreature`: identifier of specific unit to filter
- `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 {
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 {

View File

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