From ba7709da50c57998f1988e9fe37e1ff1743b254f Mon Sep 17 00:00:00 2001 From: Henning Koehler Date: Fri, 15 Sep 2017 09:25:43 +1200 Subject: [PATCH] middle-aged specialty format is converted properly and logged --- config/heroes/special.json | 38 +++++++++++++++- lib/CHeroHandler.cpp | 93 ++++++++++++++++++++++++++++++-------- lib/HeroBonus.h | 2 +- 3 files changed, 112 insertions(+), 21 deletions(-) diff --git a/config/heroes/special.json b/config/heroes/special.json index 841260f44..1f2976f1f 100644 --- a/config/heroes/special.json +++ b/config/heroes/special.json @@ -194,9 +194,43 @@ { "skill" : "tactics", "level": "basic" }, { "skill" : "offence", "level": "basic" } ], - "specialties": + "specialty" : [ - { "type":1, "val": 0, "subtype": 0, "info": 90 } + { + "growsWithLevel" : true, + "bonuses" : [ + { + "limiters" : [ + { + "parameters" : [ "ogre", true ], + "type" : "CREATURE_TYPE_LIMITER" + } + ], + "subtype" : "primSkill.attack", + "type" : "PRIMARY_SKILL", + }, + { + "limiters" : [ + { + "parameters" : [ "ogre", true ], + "type" : "CREATURE_TYPE_LIMITER" + } + ], + "subtype" : "primSkill.defence", + "type" : "PRIMARY_SKILL", + }, + { + "limiters" : [ + { + "parameters" : [ "ogre", true ], + "type" : "CREATURE_TYPE_LIMITER" + } + ], + "type" : "STACKS_SPEED", + "val" : 1 + } + ] + } ], "army" : [ diff --git a/lib/CHeroHandler.cpp b/lib/CHeroHandler.cpp index 2ac313964..b4549de37 100644 --- a/lib/CHeroHandler.cpp +++ b/lib/CHeroHandler.cpp @@ -533,6 +533,51 @@ std::vector> SpecialtyInfoToBonuses(const SSpecialtyInfo return result; } +// convert deprecated format +std::vector> SpecialtyBonusToBonuses(const SSpecialtyBonus & spec) +{ + std::vector> result; + for(std::shared_ptr oldBonus : spec.bonuses) + { + if(spec.growsWithLevel) + { + std::shared_ptr newBonus = std::make_shared(*oldBonus); + switch(newBonus->type) + { + case Bonus::SECONDARY_SKILL_PREMY: + break; // ignore - used to be overwritten based on SPECIAL_SECONDARY_SKILL + case Bonus::SPECIAL_SECONDARY_SKILL: + newBonus->type = Bonus::SECONDARY_SKILL_PREMY; + newBonus->updater = std::make_shared(newBonus->val * 20); + newBonus->val = 0; // for json printing + result.push_back(newBonus); + break; + case Bonus::PRIMARY_SKILL: + if((newBonus->subtype == PrimarySkill::ATTACK || newBonus->subtype == PrimarySkill::DEFENSE) && newBonus->limiter) + { + const std::shared_ptr creatureLimiter = std::dynamic_pointer_cast(newBonus->limiter); + if(creatureLimiter) + { + const CCreature * cre = creatureLimiter->creature; + int creStat = newBonus->subtype == PrimarySkill::ATTACK ? cre->Attack() : cre->Defense(); + int creLevel = cre->level ? cre->level : 5; + newBonus->updater = std::make_shared(creStat, creLevel); + } + result.push_back(newBonus); + } + break; + default: + result.push_back(newBonus); + } + } + else + { + result.push_back(oldBonus); + } + } + return result; +} + void CHeroHandler::beforeValidate(JsonNode & object) { //handle "base" specialty info @@ -583,8 +628,11 @@ void CHeroHandler::loadHeroSpecialty(CHero * hero, const JsonNode & node) //deprecated middle-aged format for(const JsonNode & specialty : node["specialty"].Vector()) { + SSpecialtyBonus hs; + hs.growsWithLevel = specialty["growsWithLevel"].Bool(); for (const JsonNode & bonus : specialty["bonuses"].Vector()) - hero->specialty.push_back(prepSpec(JsonUtils::parseBonus(bonus))); + hs.bonuses.push_back(prepSpec(JsonUtils::parseBonus(bonus))); + hero->specialtyDeprecated.push_back(hs); } } else if(specialtyNode.getType() == JsonNode::JsonType::DATA_STRUCT) @@ -753,28 +801,37 @@ void CHeroHandler::afterLoadFinalization() { for(ConstTransitivePtr hero : heroes) { - if(hero->specDeprecated.size() > 0) + if(hero->specDeprecated.size() > 0 || hero->specialtyDeprecated.size() > 0) { - logMod->debug("Converting specialties format for hero %s(%s)", hero->identifier, VLC->townh->encodeFaction(hero->heroClass->faction)); - std::vector specVec; - std::vector specNames; + logMod->debug("Converting specialty format for hero %s(%s)", hero->identifier, VLC->townh->encodeFaction(hero->heroClass->faction)); + std::vector> convertedBonuses; for(const SSpecialtyInfo & spec : hero->specDeprecated) { - for(std::shared_ptr bonus : SpecialtyInfoToBonuses(spec, hero->ID.getNum())) + for(std::shared_ptr b : SpecialtyInfoToBonuses(spec, hero->ID.getNum())) + convertedBonuses.push_back(b); + } + for(const SSpecialtyBonus & spec : hero->specialtyDeprecated) + { + for(std::shared_ptr b : SpecialtyBonusToBonuses(spec)) + convertedBonuses.push_back(b); + } + // store and create json for logging + std::vector specVec; + std::vector specNames; + for(std::shared_ptr bonus : convertedBonuses) + { + hero->specialty.push_back(bonus); + specVec.push_back(bonus->toJsonNode()); + // find fitting & unique bonus name + std::string bonusName = nameForBonus(*bonus); + if(vstd::contains(specNames, bonusName)) { - hero->specialty.push_back(bonus); - specVec.push_back(bonus->toJsonNode()); - // find fitting & unique bonus name - std::string bonusName = nameForBonus(*bonus); - if(vstd::contains(specNames, bonusName)) - { - int i = 2; - while(vstd::contains(specNames, bonusName + std::to_string(i))) - i++; - bonusName += std::to_string(i); - } - specNames.push_back(bonusName); + int suffix = 2; + while(vstd::contains(specNames, bonusName + std::to_string(suffix))) + suffix++; + bonusName += std::to_string(suffix); } + specNames.push_back(bonusName); } hero->specDeprecated.clear(); // log new format for easy copy-and-paste diff --git a/lib/HeroBonus.h b/lib/HeroBonus.h index e3e3e1a67..664441c20 100644 --- a/lib/HeroBonus.h +++ b/lib/HeroBonus.h @@ -207,7 +207,7 @@ private: BONUS_NAME(NO_LUCK) /*eg. when fighting on cursed ground*/ \ BONUS_NAME(NO_MORALE) /*eg. when fighting on cursed ground*/ \ BONUS_NAME(DARKNESS) /*val = radius */ \ - BONUS_NAME(SPECIAL_SECONDARY_SKILL) /*val = id, additionalInfo = value per level in percent*/ \ + BONUS_NAME(SPECIAL_SECONDARY_SKILL) /*subtype = id, val = value per level in percent*/ \ BONUS_NAME(SPECIAL_SPELL_LEV) /*val = id, additionalInfo = value per level in percent*/\ BONUS_NAME(SPELL_DAMAGE) /*val = value*/\ BONUS_NAME(SPECIFIC_SPELL_DAMAGE) /*subtype = id of spell, val = value*/\