|
@@ -452,73 +452,74 @@ void BonusList::stackBonuses()
|
|
|
|
|
|
int BonusList::totalValue() const
|
|
|
{
|
|
|
- std::array <std::pair<int, int>, Bonus::BonusSource::NUM_BONUS_SOURCE> sources = {};
|
|
|
- int base = 0;
|
|
|
- int percentToBase = 0;
|
|
|
- int percentToAll = 0;
|
|
|
- int additive = 0;
|
|
|
- int indepMax = 0;
|
|
|
+ struct BonusCollection
|
|
|
+ {
|
|
|
+ int base = 0;
|
|
|
+ int percentToBase = 0;
|
|
|
+ int percentToAll = 0;
|
|
|
+ int additive = 0;
|
|
|
+ int percentToSource;
|
|
|
+ int indepMin = std::numeric_limits<int>::max();
|
|
|
+ int indepMax = std::numeric_limits<int>::min();
|
|
|
+ };
|
|
|
+
|
|
|
+ auto percent = [](int base, int percent) -> int {return (base * (100 + percent)) / 100; };
|
|
|
+ std::array <BonusCollection, Bonus::BonusSource::NUM_BONUS_SOURCE> sources = {};
|
|
|
+ BonusCollection any;
|
|
|
bool hasIndepMax = false;
|
|
|
- int indepMin = 0;
|
|
|
bool hasIndepMin = false;
|
|
|
- int modifiedBase = 0;
|
|
|
|
|
|
for(std::shared_ptr<Bonus> b : bonuses)
|
|
|
{
|
|
|
switch(b->valType)
|
|
|
{
|
|
|
case Bonus::BASE_NUMBER:
|
|
|
- sources[b->source].first += b->val;
|
|
|
+ sources[b->source].base += b->val;
|
|
|
break;
|
|
|
case Bonus::PERCENT_TO_ALL:
|
|
|
- percentToAll += b->val;
|
|
|
+ sources[b->source].percentToAll += b->val;
|
|
|
break;
|
|
|
case Bonus::PERCENT_TO_BASE:
|
|
|
- percentToBase += b->val;
|
|
|
+ sources[b->source].percentToBase += b->val;
|
|
|
break;
|
|
|
case Bonus::PERCENT_TO_SOURCE:
|
|
|
- sources[b->source].second += b->val;
|
|
|
+ sources[b->source].percentToSource += b->val;
|
|
|
+ break;
|
|
|
+ case Bonus::PERCENT_TO_TARGET_TYPE:
|
|
|
+ sources[b->targetSourceType].percentToSource += b->val;
|
|
|
break;
|
|
|
case Bonus::ADDITIVE_VALUE:
|
|
|
- additive += b->val;
|
|
|
+ sources[b->source].additive += b->val;
|
|
|
break;
|
|
|
case Bonus::INDEPENDENT_MAX:
|
|
|
- if (!hasIndepMax)
|
|
|
- {
|
|
|
- indepMax = b->val;
|
|
|
- hasIndepMax = true;
|
|
|
- }
|
|
|
- else
|
|
|
- {
|
|
|
- vstd::amax(indepMax, b->val);
|
|
|
- }
|
|
|
+ hasIndepMax = true;
|
|
|
+ vstd::amax(sources[b->source].indepMax, b->val);
|
|
|
break;
|
|
|
case Bonus::INDEPENDENT_MIN:
|
|
|
- if (!hasIndepMin)
|
|
|
- {
|
|
|
- indepMin = b->val;
|
|
|
- hasIndepMin = true;
|
|
|
- }
|
|
|
- else
|
|
|
- {
|
|
|
- vstd::amin(indepMin, b->val);
|
|
|
- }
|
|
|
+ hasIndepMin = true;
|
|
|
+ vstd::amin(sources[b->source].indepMin, b->val);
|
|
|
break;
|
|
|
}
|
|
|
}
|
|
|
for(auto src : sources)
|
|
|
{
|
|
|
- base += src.first;
|
|
|
- modifiedBase += src.first + (src.first * src.second) / 100;
|
|
|
+ any.base += percent(src.base ,src.percentToSource);
|
|
|
+ any.percentToBase += percent(src.percentToBase, src.percentToSource);
|
|
|
+ any.percentToAll += percent(src.percentToAll, src.percentToSource);
|
|
|
+ any.additive += percent(src.additive, src.percentToSource);
|
|
|
+ if(hasIndepMin)
|
|
|
+ vstd::amin(any.indepMin, percent(src.indepMin, src.percentToSource));
|
|
|
+ if(hasIndepMax)
|
|
|
+ vstd::amax(any.indepMax, percent(src.indepMin, src.percentToSource));
|
|
|
}
|
|
|
- modifiedBase += (base * percentToBase) / 100;
|
|
|
- modifiedBase += additive;
|
|
|
- int valFirst = (modifiedBase * (100 + percentToAll)) / 100;
|
|
|
+ any.base = percent(any.base, any.percentToBase);
|
|
|
+ any.base += any.additive;
|
|
|
+ auto valFirst = percent(any.base ,any.percentToAll);
|
|
|
|
|
|
if(hasIndepMin && hasIndepMax)
|
|
|
- assert(indepMin < indepMax);
|
|
|
+ assert(any.indepMin < any.indepMax);
|
|
|
|
|
|
- const int notIndepBonuses = (int)boost::count_if(bonuses, [](const std::shared_ptr<Bonus>& b)
|
|
|
+ const int notIndepBonuses = (int)std::count_if(bonuses.cbegin(), bonuses.cend(), [](const std::shared_ptr<Bonus>& b)
|
|
|
{
|
|
|
return b->valType != Bonus::INDEPENDENT_MAX && b->valType != Bonus::INDEPENDENT_MIN;
|
|
|
});
|
|
@@ -526,16 +527,16 @@ int BonusList::totalValue() const
|
|
|
if (hasIndepMax)
|
|
|
{
|
|
|
if(notIndepBonuses)
|
|
|
- vstd::amax(valFirst, indepMax);
|
|
|
+ vstd::amax(valFirst, any.indepMax);
|
|
|
else
|
|
|
- valFirst = indepMax;
|
|
|
+ valFirst = any.indepMax;
|
|
|
}
|
|
|
if (hasIndepMin)
|
|
|
{
|
|
|
if(notIndepBonuses)
|
|
|
- vstd::amin(valFirst, indepMin);
|
|
|
+ vstd::amin(valFirst, any.indepMin);
|
|
|
else
|
|
|
- valFirst = indepMin;
|
|
|
+ valFirst = any.indepMin;
|
|
|
}
|
|
|
|
|
|
return valFirst;
|
|
@@ -1719,6 +1720,8 @@ JsonNode Bonus::toJsonNode() const
|
|
|
root["turns"].Integer() = turnsRemain;
|
|
|
if(source != OTHER)
|
|
|
root["sourceType"].String() = vstd::findKey(bonusSourceMap, source);
|
|
|
+ if(targetSourceType != OTHER)
|
|
|
+ root["targetSourceType"].String() = vstd::findKey(bonusSourceMap, targetSourceType);
|
|
|
if(sid != 0)
|
|
|
root["sourceID"].Integer() = sid;
|
|
|
if(val != 0)
|
|
@@ -1778,6 +1781,7 @@ Bonus::Bonus(Bonus::BonusDuration Duration, BonusType Type, BonusSource Src, si3
|
|
|
valType = ADDITIVE_VALUE;
|
|
|
effectRange = NO_LIMIT;
|
|
|
boost::algorithm::trim(description);
|
|
|
+ targetSourceType = OTHER;
|
|
|
}
|
|
|
|
|
|
Bonus::Bonus(Bonus::BonusDuration Duration, BonusType Type, BonusSource Src, si32 Val, ui32 ID, si32 Subtype, ValueType ValType)
|
|
@@ -1785,6 +1789,7 @@ Bonus::Bonus(Bonus::BonusDuration Duration, BonusType Type, BonusSource Src, si3
|
|
|
{
|
|
|
turnsRemain = 0;
|
|
|
effectRange = NO_LIMIT;
|
|
|
+ targetSourceType = OTHER;
|
|
|
}
|
|
|
|
|
|
Bonus::Bonus()
|
|
@@ -1799,6 +1804,7 @@ Bonus::Bonus()
|
|
|
val = 0;
|
|
|
source = OTHER;
|
|
|
sid = 0;
|
|
|
+ targetSourceType = OTHER;
|
|
|
}
|
|
|
|
|
|
std::shared_ptr<Bonus> Bonus::addPropagator(TPropagatorPtr Propagator)
|
|
@@ -1833,6 +1839,12 @@ namespace Selector
|
|
|
return ssourceType;
|
|
|
}
|
|
|
|
|
|
+ DLL_LINKAGE CSelectFieldEqual<Bonus::BonusSource> & targetSourceType()
|
|
|
+ {
|
|
|
+ static CSelectFieldEqual<Bonus::BonusSource> ssourceType(&Bonus::targetSourceType);
|
|
|
+ return ssourceType;
|
|
|
+ }
|
|
|
+
|
|
|
DLL_LINKAGE CSelectFieldEqual<Bonus::LimitEffect> & effectRange()
|
|
|
{
|
|
|
static CSelectFieldEqual<Bonus::LimitEffect> seffectRange(&Bonus::effectRange);
|