Pārlūkot izejas kodu

updated json loading and schema to fit new specialty format

Henning Koehler 8 gadi atpakaļ
vecāks
revīzija
a002df399e
4 mainītis faili ar 93 papildinājumiem un 70 dzēšanām
  1. 39 47
      config/heroes/castle.json
  2. 24 12
      config/schemas/hero.json
  3. 29 11
      lib/CHeroHandler.cpp
  4. 1 0
      lib/CHeroHandler.h

+ 39 - 47
config/heroes/castle.json

@@ -9,17 +9,19 @@
 			{ "skill" : "leadership", "level": "basic" },
 			{ "skill" : "archery", "level": "basic" }
 		],
-		"specialty" : [
-			{
-				"type" : "SECONDARY_SKILL_PREMY",
-				"subtype" : "skill.archery",
-				"valueType" : "PERCENT_TO_BASE",
-				"updater" : {
-					"type" : "GROWS_WITH_LEVEL",
-					"parameters" : [100]
+		"specialty" : {
+			"bonuses" : {
+				"archery" : {
+					"type" : "SECONDARY_SKILL_PREMY",
+					"subtype" : "skill.archery",
+					"valueType" : "PERCENT_TO_BASE",
+					"updater" : {
+						"type" : "GROWS_WITH_LEVEL",
+						"parameters" : [100]
+					}
 				}
 			}
-		]
+		}
 	},
 	"valeska":
 	{
@@ -31,55 +33,45 @@
 			{ "skill" : "leadership", "level": "basic" },
 			{ "skill" : "archery", "level": "basic" }
 		],
-		"specialty" : [
-			{
+		"specialty" : {
+			"base" : {
 				"limiter" : {
 					"parameters" : [
 						"archer",
 						true
 					],
 					"type" : "CREATURE_TYPE_LIMITER"
-				},
-				"type" : "STACKS_SPEED",
-				"val" : 1
-			},
-			{
-				"limiter" : {
-					"parameters" : [
-						"archer",
-						true
-					],
-					"type" : "CREATURE_TYPE_LIMITER"
-				},
-				"subtype" : "primSkill.attack",
-				"type" : "PRIMARY_SKILL",
-				"updater" : {
-					"parameters" : [
-						6,
-						2
-					],
-					"type" : "GROWS_WITH_LEVEL"
 				}
 			},
-			{
-				"limiter" : {
-					"parameters" : [
-						"archer",
-						true
-					],
-					"type" : "CREATURE_TYPE_LIMITER"
+			"bonuses" : {
+				"attack" : {
+					"subtype" : "primSkill.attack",
+					"type" : "PRIMARY_SKILL",
+					"updater" : {
+						"parameters" : [
+							6,
+							2
+						],
+						"type" : "GROWS_WITH_LEVEL"
+					}
 				},
-				"subtype" : "primSkill.defence",
-				"type" : "PRIMARY_SKILL",
-				"updater" : {
-					"parameters" : [
-						3,
-						2
-					],
-					"type" : "GROWS_WITH_LEVEL"
+				"defence" : {
+					"subtype" : "primSkill.defence",
+					"type" : "PRIMARY_SKILL",
+					"updater" : {
+						"parameters" : [
+							3,
+							2
+						],
+						"type" : "GROWS_WITH_LEVEL"
+					}
+				},
+				"speed" : {
+					"type" : "STACKS_SPEED",
+					"val" : 1
 				}
 			}
-		]
+		}
 	},
 	"edric":
 	{

+ 24 - 12
config/schemas/hero.json

@@ -115,11 +115,11 @@
 			"additionalItems" : true
 		},
 		"specialty": {
-			"type":"array",
-			"description": "Description of hero specialty using bonus system",	
-			"items": {
-				"oneOf" : [
-					{
+			"oneOf" : [
+				{
+					"type":"array",
+					"description": "Description of hero specialty using bonus system (deprecated)",
+					"items": {
 						"type" : "object",
 						"additionalProperties" : false,
 						"required" : [ "bonuses" ],
@@ -134,14 +134,26 @@
 								"items" : { "$ref" : "vcmi:bonus" }
 							}
 						}
-					},
-					{
-						"type" : "object",
-						"description" : "List of bonuses",
-						"items" : { "$ref" : "vcmi:bonus" }
 					}
-				]
-			}
+				},
+				{
+					"type" : "object",
+					"description": "Description of hero specialty using bonus system",
+					"additionalProperties" : false,
+					"required" : [ "bonuses" ],
+					"properties" : { 
+						"base" : {
+							"type" : "object",
+							"description" : "Will be merged with all bonuses."
+						},
+						"bonuses" : {
+							"type" : "object",
+							"description" : "Set of bonuses",
+							"additionalProperties" : { "$ref" : "vcmi:bonus" }
+						}
+					}
+				}
+			]
 		},
 		"spellbook": {
 			"type":"array",

+ 29 - 11
lib/CHeroHandler.cpp

@@ -533,6 +533,21 @@ std::vector<std::shared_ptr<Bonus>> SpecialtyInfoToBonuses(const SSpecialtyInfo
 	return result;
 }
 
+void CHeroHandler::beforeValidate(JsonNode & object)
+{
+	//handle "base" specialty info
+	const JsonNode & specialtyNode = object["specialty"];
+	if(specialtyNode.getType() == JsonNode::DATA_STRUCT)
+	{
+		const JsonNode & base = specialtyNode["base"];
+		if(!base.isNull())
+		{
+			for(auto keyValue : specialtyNode["bonuses"].Struct())
+				JsonUtils::inherit(keyValue.second, base);
+		}
+	}
+}
+
 void CHeroHandler::loadHeroSpecialty(CHero * hero, const JsonNode & node)
 {
 	int sid = hero->ID.getNum();
@@ -545,11 +560,11 @@ void CHeroHandler::loadHeroSpecialty(CHero * hero, const JsonNode & node)
 	};
 
 	//deprecated, used only for original specialties
-	const JsonNode & specialties = node["specialties"];
-	if (!specialties.isNull())
+	const JsonNode & specialtiesNode = node["specialties"];
+	if (!specialtiesNode.isNull())
 	{
 		logMod->warn("Hero %s has deprecated specialties format.", hero->identifier);
-		for(const JsonNode &specialty : node["specialties"].Vector())
+		for(const JsonNode &specialty : specialtiesNode.Vector())
 		{
 			SSpecialtyInfo spec;
 			spec.type = specialty["type"].Float();
@@ -560,19 +575,22 @@ void CHeroHandler::loadHeroSpecialty(CHero * hero, const JsonNode & node)
 			hero->specDeprecated.push_back(spec);
 		}
 	}
-	//new format, using bonus system
-	for(const JsonNode & specialty : node["specialty"].Vector())
+	//new(er) format, using bonus system
+	const JsonNode & specialtyNode = node["specialty"];
+	if(specialtyNode.getType() == JsonNode::DATA_VECTOR)
 	{
-		//deprecated new format
-		if(!specialty["bonuses"].isNull())
+		//deprecated middle-aged format
+		for(const JsonNode & specialty : node["specialty"].Vector())
 		{
 			for (const JsonNode & bonus : specialty["bonuses"].Vector())
 				hero->specialty.push_back(prepSpec(JsonUtils::parseBonus(bonus)));
 		}
-		else //proper new format
-		{
-			hero->specialty.push_back(prepSpec(JsonUtils::parseBonus(specialty)));
-		}
+	}
+	else if(specialtyNode.getType() == JsonNode::DATA_STRUCT)
+	{
+		//proper new format
+		for(auto keyValue : specialtyNode["bonuses"].Struct())
+			hero->specialty.push_back(prepSpec(JsonUtils::parseBonus(keyValue.second)));
 	}
 }
 

+ 1 - 0
lib/CHeroHandler.h

@@ -300,6 +300,7 @@ public:
 
 	std::vector<JsonNode> loadLegacyData(size_t dataSize) override;
 
+	void beforeValidate(JsonNode & object);
 	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;