浏览代码

added one-line option for standard creature specialty; also fixes bug for creatures where upgrades have different attack/defense

Henning Koehler 7 年之前
父节点
当前提交
6442842731
共有 3 个文件被更改,包括 70 次插入60 次删除
  1. 1 30
      config/heroes/castle.json
  2. 4 1
      config/schemas/hero.json
  3. 65 29
      lib/CHeroHandler.cpp

+ 1 - 30
config/heroes/castle.json

@@ -75,36 +75,7 @@
 			{ "skill" : "armorer", "level": "basic" }
 			{ "skill" : "armorer", "level": "basic" }
 		],
 		],
 		"specialty" : {
 		"specialty" : {
-			"base" : {
-				"limiters" : [
-					{
-						"parameters" : [ "griffin", true ],
-						"type" : "CREATURE_TYPE_LIMITER"
-					}
-				]
-			},
-			"bonuses" : {
-				"attack" : {
-					"subtype" : "primSkill.attack",
-					"type" : "PRIMARY_SKILL",
-					"updater" : {
-						"parameters" : [ 8, 3 ],
-						"type" : "GROWS_WITH_LEVEL"
-					}
-				},
-				"defence" : {
-					"subtype" : "primSkill.defence",
-					"type" : "PRIMARY_SKILL",
-					"updater" : {
-						"parameters" : [ 8, 3 ],
-						"type" : "GROWS_WITH_LEVEL"
-					}
-				},
-				"speed" : {
-					"type" : "STACKS_SPEED",
-					"val" : 1
-				}
-			}
+			"creature" : "griffin"
 		}
 		}
 	},
 	},
 	"sylvia":
 	"sylvia":

+ 4 - 1
config/schemas/hero.json

@@ -140,7 +140,6 @@
 					"type" : "object",
 					"type" : "object",
 					"description": "Description of hero specialty using bonus system",
 					"description": "Description of hero specialty using bonus system",
 					"additionalProperties" : false,
 					"additionalProperties" : false,
-					"required" : [ "bonuses" ],
 					"properties" : { 
 					"properties" : { 
 						"base" : {
 						"base" : {
 							"type" : "object",
 							"type" : "object",
@@ -150,6 +149,10 @@
 							"type" : "object",
 							"type" : "object",
 							"description" : "Set of bonuses",
 							"description" : "Set of bonuses",
 							"additionalProperties" : { "$ref" : "vcmi:bonus" }
 							"additionalProperties" : { "$ref" : "vcmi:bonus" }
+						},
+						"creature" : {
+							"type" : "string",
+							"description" : "Name of base creature to grant standard specialty to."
 						}
 						}
 					}
 					}
 				}
 				}

+ 65 - 29
lib/CHeroHandler.cpp

@@ -379,6 +379,43 @@ void CHeroHandler::loadHeroSkills(CHero * hero, const JsonNode & node)
 	}
 	}
 }
 }
 
 
+// add standard creature specialty to result
+void AddSpecialtyForCreature(int creatureID, std::shared_ptr<Bonus> bonus, std::vector<std::shared_ptr<Bonus>> &result)
+{
+	const CCreature &specBaseCreature = *VLC->creh->creatures[creatureID]; //base creature in which we have specialty
+
+	bonus->limiter.reset(new CCreatureTypeLimiter(specBaseCreature, true));
+	bonus->type = Bonus::STACKS_SPEED;
+	bonus->valType = Bonus::ADDITIVE_VALUE;
+	bonus->val = 1;
+	result.push_back(bonus);
+
+	// attack and defense may differ for upgraded creatures => separate bonuses
+	std::vector<int> specTargets;
+	specTargets.push_back(creatureID);
+	specTargets.insert(specTargets.end(), specBaseCreature.upgrades.begin(), specBaseCreature.upgrades.end());
+
+	for(int cid : specTargets)
+	{
+		const CCreature &specCreature = *VLC->creh->creatures[cid];
+		bonus = std::make_shared<Bonus>(*bonus);
+		bonus->limiter.reset(new CCreatureTypeLimiter(specCreature, false));
+		bonus->type = Bonus::PRIMARY_SKILL;
+		bonus->val = 0;
+
+		int stepSize = specCreature.level ? specCreature.level : 5;
+
+		bonus->subtype = PrimarySkill::ATTACK;
+		bonus->updater.reset(new GrowsWithLevelUpdater(specCreature.getAttack(false), stepSize));
+		result.push_back(bonus);
+
+		bonus = std::make_shared<Bonus>(*bonus);
+		bonus->subtype = PrimarySkill::DEFENSE;
+		bonus->updater.reset(new GrowsWithLevelUpdater(specCreature.getDefence(false), stepSize));
+		result.push_back(bonus);
+	}
+}
+
 // convert deprecated format
 // convert deprecated format
 std::vector<std::shared_ptr<Bonus>> SpecialtyInfoToBonuses(const SSpecialtyInfo & spec, int sid)
 std::vector<std::shared_ptr<Bonus>> SpecialtyInfoToBonuses(const SSpecialtyInfo & spec, int sid)
 {
 {
@@ -393,29 +430,7 @@ std::vector<std::shared_ptr<Bonus>> SpecialtyInfoToBonuses(const SSpecialtyInfo
 	switch (spec.type)
 	switch (spec.type)
 	{
 	{
 	case 1: //creature specialty
 	case 1: //creature specialty
-		{
-			const CCreature &specCreature = *VLC->creh->creatures[spec.additionalinfo]; //creature in which we have specialty
-			bonus->limiter.reset(new CCreatureTypeLimiter(specCreature, true));
-
-			bonus->type = Bonus::STACKS_SPEED;
-			bonus->valType = Bonus::ADDITIVE_VALUE;
-			bonus->val = 1;
-			result.push_back(bonus);
-
-			bonus = std::make_shared<Bonus>(*bonus);
-			bonus->type = Bonus::PRIMARY_SKILL;
-			bonus->val = 0;
-			int stepSize = specCreature.level ? specCreature.level : 5;
-
-			bonus->subtype = PrimarySkill::ATTACK;
-			bonus->updater.reset(new GrowsWithLevelUpdater(specCreature.getAttack(false), stepSize));
-			result.push_back(bonus);
-
-			bonus = std::make_shared<Bonus>(*bonus);
-			bonus->subtype = PrimarySkill::DEFENSE;
-			bonus->updater.reset(new GrowsWithLevelUpdater(specCreature.getDefence(false), stepSize));
-			result.push_back(bonus);
-		}
+		AddSpecialtyForCreature(spec.additionalinfo, bonus, result);
 		break;
 		break;
 	case 2: //secondary skill
 	case 2: //secondary skill
 		bonus->type = Bonus::SECONDARY_SKILL_PREMY;
 		bonus->type = Bonus::SECONDARY_SKILL_PREMY;
@@ -585,9 +600,16 @@ void CHeroHandler::beforeValidate(JsonNode & object)
 		const JsonNode & base = specialtyNode["base"];
 		const JsonNode & base = specialtyNode["base"];
 		if(!base.isNull())
 		if(!base.isNull())
 		{
 		{
-			JsonMap & bonuses = specialtyNode["bonuses"].Struct();
-			for(std::pair<std::string, JsonNode> keyValue : bonuses)
-				JsonUtils::inherit(bonuses[keyValue.first], base);
+			if(specialtyNode["bonuses"].isNull())
+			{
+				logMod->warn("specialty has base without bonuses");
+			}
+			else
+			{
+				JsonMap & bonuses = specialtyNode["bonuses"].Struct();
+				for(std::pair<std::string, JsonNode> keyValue : bonuses)
+					JsonUtils::inherit(bonuses[keyValue.first], base);
+			}
 		}
 		}
 	}
 	}
 }
 }
@@ -635,9 +657,23 @@ void CHeroHandler::loadHeroSpecialty(CHero * hero, const JsonNode & node)
 	}
 	}
 	else if(specialtyNode.getType() == JsonNode::JsonType::DATA_STRUCT)
 	else if(specialtyNode.getType() == JsonNode::JsonType::DATA_STRUCT)
 	{
 	{
-		//proper new format
-		for(auto keyValue : specialtyNode["bonuses"].Struct())
-			hero->specialty.push_back(prepSpec(JsonUtils::parseBonus(keyValue.second)));
+		//creature specialty - alias for simplicity
+		if(!specialtyNode["creature"].isNull())
+		{
+			VLC->modh->identifiers.requestIdentifier("creature", specialtyNode["creature"], [hero](si32 creature) {
+				// use legacy format for delayed conversion (must have all creature data loaded, also for upgrades)
+				SSpecialtyInfo spec;
+				spec.type = 1;
+				spec.additionalinfo = creature;
+				hero->specDeprecated.push_back(spec);
+			});
+		}
+		if(!specialtyNode["bonuses"].isNull())
+		{
+			//proper new format
+			for(auto keyValue : specialtyNode["bonuses"].Struct())
+				hero->specialty.push_back(prepSpec(JsonUtils::parseBonus(keyValue.second)));
+		}
 	}
 	}
 }
 }