1
0
mirror of https://github.com/vcmi/vcmi.git synced 2025-11-29 23:07:48 +02:00

Implement shortcut for hero skill specialties

Should make changes to secondary skill bonuses less mod-breaking, and
reduce chances of incorrectly defined specialties in mods
This commit is contained in:
Ivan Savenko
2025-06-03 17:32:15 +03:00
parent 4fda657296
commit eb9a5bb71b
17 changed files with 170 additions and 382 deletions

View File

@@ -21,6 +21,7 @@
#include "../../json/JsonBonus.h"
#include "../../json/JsonUtils.h"
#include "../../modding/IdentifierStorage.h"
#include "../../CSkillHandler.h"
#include "../../texts/CGeneralTextHandler.h"
#include "../../texts/CLegacyConfigParser.h"
@@ -140,7 +141,7 @@ void CHeroHandler::loadHeroSkills(CHero * hero, const JsonNode & node) const
}
/// creates standard H3 hero specialty for creatures
static std::vector<std::shared_ptr<Bonus>> createCreatureSpecialty(CreatureID cid)
std::vector<std::shared_ptr<Bonus>> CHeroHandler::createCreatureSpecialty(CreatureID cid) const
{
std::vector<std::shared_ptr<Bonus>> result;
@@ -174,6 +175,19 @@ static std::vector<std::shared_ptr<Bonus>> createCreatureSpecialty(CreatureID ci
bonus->updater.reset(new GrowsWithLevelUpdater(specCreature.getDefense(false), stepSize));
result.push_back(bonus);
}
return result;
}
std::vector<std::shared_ptr<Bonus>> CHeroHandler::createSecondarySkillSpecialty(SecondarySkill skillID) const
{
std::vector<std::shared_ptr<Bonus>> result;
const auto & skillPtr = LIBRARY->skillh->objects[skillID.getNum()];
if (skillPtr->specialtyTargetBonuses.empty())
logMod->warn("Skill '%s' does not supports generic specialties!", skillPtr->getJsonKey());
for (const auto & bonus : skillPtr->specialtyTargetBonuses)
result.push_back(std::make_shared<Bonus>(*bonus));
return result;
}
@@ -201,15 +215,7 @@ void CHeroHandler::beforeValidate(JsonNode & object)
}
}
void CHeroHandler::afterLoadFinalization()
{
for(const auto & functor : callAfterLoadFinalization)
functor();
callAfterLoadFinalization.clear();
}
void CHeroHandler::loadHeroSpecialty(CHero * hero, const JsonNode & node)
void CHeroHandler::loadHeroSpecialty(CHero * hero, const JsonNode & node) const
{
auto prepSpec = [=](std::shared_ptr<Bonus> bonus)
{
@@ -230,18 +236,21 @@ void CHeroHandler::loadHeroSpecialty(CHero * hero, const JsonNode & node)
//creature specialty - alias for simplicity
if(!specialtyNode["creature"].isNull())
{
JsonNode creatureNode = specialtyNode["creature"];
std::function<void()> specialtyLoader = [creatureNode, hero, prepSpec]
LIBRARY->identifiers()->requestIdentifier("creature", specialtyNode["creature"], [this, hero, prepSpec](si32 creature)
{
LIBRARY->identifiers()->requestIdentifier("creature", creatureNode, [hero, prepSpec](si32 creature)
{
for (const auto & bonus : createCreatureSpecialty(CreatureID(creature)))
hero->specialty.push_back(prepSpec(bonus));
});
};
for (const auto & bonus : createCreatureSpecialty(CreatureID(creature)))
hero->specialty.push_back(prepSpec(bonus));
});
}
callAfterLoadFinalization.push_back(specialtyLoader);
//secondary skill specialty - alias for simplicity
if(!specialtyNode["secondary"].isNull())
{
LIBRARY->identifiers()->requestIdentifier("secondarySkill", specialtyNode["secondary"], [this, hero, prepSpec](si32 creature)
{
for (const auto & bonus : createSecondarySkillSpecialty(SecondarySkill(creature)))
hero->specialty.push_back(prepSpec(bonus));
});
}
for(const auto & keyValue : specialtyNode["bonuses"].Struct())

View File

@@ -28,11 +28,12 @@ class DLL_LINKAGE CHeroHandler : public CHandlerBase<HeroTypeID, HeroType, CHero
/// helpers for loading to avoid huge load functions
void loadHeroArmy(CHero * hero, const JsonNode & node) const;
void loadHeroSkills(CHero * hero, const JsonNode & node) const;
void loadHeroSpecialty(CHero * hero, const JsonNode & node);
void loadHeroSpecialty(CHero * hero, const JsonNode & node) const;
void loadExperience();
std::vector<std::function<void()>> callAfterLoadFinalization;
std::vector<std::shared_ptr<Bonus>> createCreatureSpecialty(CreatureID cid) const;
std::vector<std::shared_ptr<Bonus>> createSecondarySkillSpecialty(SecondarySkill skillID) const;
public:
ui32 level(TExpType experience) const; //calculates level corresponding to given experience amount
@@ -44,7 +45,6 @@ public:
void beforeValidate(JsonNode & object) override;
void loadObject(std::string scope, std::string name, const JsonNode & data) override;
void loadObject(std::string scope, std::string name, const JsonNode & data, size_t index) override;
void afterLoadFinalization() override;
CHeroHandler();
~CHeroHandler();