1
0
mirror of https://github.com/vcmi/vcmi.git synced 2025-11-23 22:37:55 +02:00

Added TIMES_ARMY_SIZE updater

This commit is contained in:
Ivan Savenko
2025-06-26 15:10:55 +03:00
parent dec4826b54
commit 135768e763
5 changed files with 141 additions and 0 deletions

View File

@@ -107,6 +107,54 @@ Example of long form with custom parameters:
} }
``` ```
## TIMES_ARMY_SIZE
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
- `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
- `filteredFaction`: faction of units that need to be counted. Redundant if `filteredCreature` is used
Filtering for specific unit:
```json
"updater" : {
"type" : "TIMES_ARMY_SIZE",
"filteredCreature" : "pikeman",
// Optional, by default - unlimited
"minimum" : 0,
// Optional, by default - unlimited
"maximum" : 100,
// Optional, by default - 1
"stepSize" : 2
}
```
Filtering for specific faction:
```json
"updater" : {
"type" : "TIMES_STACK_SIZE",
"filteredFaction" : "castle"
}
```
Filtering for specific unit level:
```json
"updater" : {
"type" : "TIMES_STACK_SIZE",
"filteredLevel" : 2
}
```
## BONUS_OWNER_UPDATER ## BONUS_OWNER_UPDATER
Helper updater for proper functionality of `OPPOSITE_SIDE` limiter Helper updater for proper functionality of `OPPOSITE_SIDE` limiter

View File

@@ -148,6 +148,44 @@ JsonNode TimesStackSizeUpdater::toJsonNode() const
return JsonNode("TIMES_STACK_SIZE"); return JsonNode("TIMES_STACK_SIZE");
} }
std::shared_ptr<Bonus> TimesArmySizeUpdater::createUpdatedBonus(const std::shared_ptr<Bonus> & b, const CBonusSystemNode & context) const
{
if(context.getNodeType() == BonusNodeType::ARMY || context.getNodeType() == BonusNodeType::HERO || context.getNodeType() == BonusNodeType::TOWN)
{
const auto & army = dynamic_cast<const CArmedInstance &>(context);
int totalSize = 0;
for (const auto & unit : army.Slots())
{
if (filteredCreature.hasValue() && filteredCreature != unit.second->getCreatureID())
continue;
if (filteredFaction.hasValue() && filteredFaction != unit.second->getFactionID())
continue;
if (filteredLevel != -1 && filteredLevel != unit.second->getLevel())
continue;
totalSize += unit.second->getCount();
}
auto newBonus = std::make_shared<Bonus>(*b);
newBonus->val *= std::clamp(totalSize / stepSize, minimum, maximum);
return newBonus;
}
return b;
}
std::string TimesArmySizeUpdater::toString() const
{
return "TimesArmySizeUpdater";
}
JsonNode TimesArmySizeUpdater::toJsonNode() const
{
return JsonNode("TIMES_ARMY_SIZE");
}
std::shared_ptr<Bonus> TimesStackLevelUpdater::apply(const std::shared_ptr<Bonus> & b, int level) const std::shared_ptr<Bonus> TimesStackLevelUpdater::apply(const std::shared_ptr<Bonus> & b, int level) const
{ {
auto newBonus = std::make_shared<Bonus>(*b); auto newBonus = std::make_shared<Bonus>(*b);

View File

@@ -113,6 +113,30 @@ public:
} }
}; };
class DLL_LINKAGE TimesArmySizeUpdater : public IUpdater
{
public:
int minimum = std::numeric_limits<int>::min();
int maximum = std::numeric_limits<int>::max();
int stepSize = 1;
int filteredLevel = -1;
CreatureID filteredCreature;
FactionID filteredFaction;
TimesArmySizeUpdater() = default;
std::shared_ptr<Bonus> createUpdatedBonus(const std::shared_ptr<Bonus> & b, const CBonusSystemNode & context) const override;
std::string toString() const override;
JsonNode toJsonNode() const override;
template <typename Handler> void serialize(Handler & h)
{
h & static_cast<IUpdater &>(*this);
h & minimum;
h & maximum;
h & stepSize;
}
};
class DLL_LINKAGE TimesStackLevelUpdater : public IUpdater class DLL_LINKAGE TimesStackLevelUpdater : public IUpdater
{ {
std::shared_ptr<Bonus> apply(const std::shared_ptr<Bonus> & b, int level) const; std::shared_ptr<Bonus> apply(const std::shared_ptr<Bonus> & b, int level) const;

View File

@@ -428,6 +428,35 @@ static TUpdaterPtr parseUpdater(const JsonNode & updaterJson)
} }
return std::make_shared<TimesStackSizeUpdater>(minimum, maximum, std::max(1, stepSize)); return std::make_shared<TimesStackSizeUpdater>(minimum, maximum, std::max(1, stepSize));
} }
if(updaterJson["type"].String() == "TIMES_ARMY_SIZE")
{
auto result = std::make_shared<TimesArmySizeUpdater>();
result->minimum = updaterJson["minimum"].isNull() ? std::numeric_limits<int>::min() : updaterJson["minimum"].Integer();
result->maximum = updaterJson["maximum"].isNull() ? std::numeric_limits<int>::max() : updaterJson["maximum"].Integer();
result->stepSize = updaterJson["stepSize"].isNull() ? 1 : updaterJson["stepSize"].Integer();
result->filteredLevel = updaterJson["filteredLevel"].isNull() ? -1 : updaterJson["filteredLevel"].Integer();
if (result->minimum > result->maximum)
{
logMod->warn("TIMES_ARMY_SIZE updater: minimum value (%d) is above maximum value(%d)!", result->minimum, result->maximum);
std::swap(result->minimum, result->maximum);
}
if (!updaterJson["filteredFaction"].isNull())
{
LIBRARY->identifiers()->requestIdentifier( "faction", updaterJson["filteredFaction"], [result](int32_t identifier)
{
result->filteredFaction = FactionID(identifier);
});
}
if (!updaterJson["filteredCreature"].isNull())
{
LIBRARY->identifiers()->requestIdentifier( "creature", updaterJson["filteredCreature"], [result](int32_t identifier)
{
result->filteredCreature = CreatureID(identifier);
});
}
return result;
}
else else
logMod->warn("Unknown updater type \"%s\"", updaterJson["type"].String()); logMod->warn("Unknown updater type \"%s\"", updaterJson["type"].String());
break; break;

View File

@@ -298,6 +298,8 @@ void registerTypes(Serializer &s)
s.template registerType<DivideStackLevelUpdater>(246); s.template registerType<DivideStackLevelUpdater>(246);
s.template registerType<SetHeroExperience>(247); s.template registerType<SetHeroExperience>(247);
s.template registerType<GiveStackExperience>(248); s.template registerType<GiveStackExperience>(248);
s.template registerType<TimesStackSizeUpdater>(249);
s.template registerType<TimesArmySizeUpdater>(250);
} }
VCMI_LIB_NAMESPACE_END VCMI_LIB_NAMESPACE_END