Переглянути джерело

middle-aged specialty format is converted properly and logged

Henning Koehler 8 роки тому
батько
коміт
ba7709da50
3 змінених файлів з 111 додано та 20 видалено
  1. 36 2
      config/heroes/special.json
  2. 74 17
      lib/CHeroHandler.cpp
  3. 1 1
      lib/HeroBonus.h

+ 36 - 2
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" :
 		[

+ 74 - 17
lib/CHeroHandler.cpp

@@ -533,6 +533,51 @@ std::vector<std::shared_ptr<Bonus>> SpecialtyInfoToBonuses(const SSpecialtyInfo
 	return result;
 }
 
+// convert deprecated format
+std::vector<std::shared_ptr<Bonus>> SpecialtyBonusToBonuses(const SSpecialtyBonus & spec)
+{
+	std::vector<std::shared_ptr<Bonus>> result;
+	for(std::shared_ptr<Bonus> oldBonus : spec.bonuses)
+	{
+		if(spec.growsWithLevel)
+		{
+			std::shared_ptr<Bonus> newBonus = std::make_shared<Bonus>(*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<ScalingUpdater>(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<CCreatureTypeLimiter> creatureLimiter = std::dynamic_pointer_cast<CCreatureTypeLimiter>(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<ScalingUpdater>(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<CHero> 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));
+			logMod->debug("Converting specialty format for hero %s(%s)", hero->identifier, VLC->townh->encodeFaction(hero->heroClass->faction));
+			std::vector<std::shared_ptr<Bonus>> convertedBonuses;
+			for(const SSpecialtyInfo & spec : hero->specDeprecated)
+			{
+				for(std::shared_ptr<Bonus> b : SpecialtyInfoToBonuses(spec, hero->ID.getNum()))
+					convertedBonuses.push_back(b);
+			}
+			for(const SSpecialtyBonus & spec : hero->specialtyDeprecated)
+			{
+				for(std::shared_ptr<Bonus> b : SpecialtyBonusToBonuses(spec))
+					convertedBonuses.push_back(b);
+			}
+			// store and create json for logging
 			std::vector<JsonNode> specVec;
 			std::vector<std::string> specNames;
-			for(const SSpecialtyInfo & spec : hero->specDeprecated)
+			for(std::shared_ptr<Bonus> bonus : convertedBonuses)
 			{
-				for(std::shared_ptr<Bonus> bonus : SpecialtyInfoToBonuses(spec, hero->ID.getNum()))
+				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

+ 1 - 1
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*/\