Sfoglia il codice sorgente

Support for objects from mods as campaign scenario bonuses

Ivan Savenko 4 mesi fa
parent
commit
2bf951a4cf

+ 24 - 5
client/lobby/CBonusSelection.cpp

@@ -46,12 +46,14 @@
 #include "../../lib/GameLibrary.h"
 #include "../../lib/StartInfo.h"
 #include "../../lib/campaign/CampaignState.h"
+#include "../../lib/entities/artifact/CArtifact.h"
 #include "../../lib/entities/building/CBuilding.h"
 #include "../../lib/entities/building/CBuildingHandler.h"
 #include "../../lib/entities/faction/CFaction.h"
 #include "../../lib/entities/faction/CTown.h"
 #include "../../lib/entities/faction/CTownHandler.h"
 #include "../../lib/entities/hero/CHeroHandler.h"
+#include "../../lib/spells/CSpellHandler.h"
 #include "../../lib/filesystem/Filesystem.h"
 #include "../../lib/mapObjects/CGHeroInstance.h"
 #include "../../lib/mapping/CMapHeader.h"
@@ -184,7 +186,12 @@ void CBonusSelection::createBonusesIcons()
 			case CampaignBonusType::SPELL:
 			{
 				const auto & bonusValue = bonus.getValue<CampaignBonusSpell>();
-				picNumber = bonusValue.spell.getNum();
+				const auto * spell = bonusValue.spell.toSpell();
+				if (!spell->getIconScenarioBonus().empty())
+					picName = spell->getIconScenarioBonus();
+				else
+					picNumber = bonusValue.spell.getNum();
+
 				desc.appendLocalString(EMetaText::GENERAL_TXT, 715);
 				desc.replaceName(bonusValue.spell);
 				break;
@@ -227,7 +234,11 @@ void CBonusSelection::createBonusesIcons()
 			case CampaignBonusType::ARTIFACT:
 			{
 				const auto & bonusValue = bonus.getValue<CampaignBonusArtifact>();
-				picNumber = bonusValue.artifact;
+				const auto * artifact = bonusValue.artifact.toArtifact();
+				if (!artifact->scenarioBonus.empty())
+					picName = artifact->scenarioBonus;
+				else
+					picNumber = bonusValue.artifact.getNum();
 				desc.appendLocalString(EMetaText::GENERAL_TXT, 715);
 				desc.replaceName(bonusValue.artifact);
 				break;
@@ -235,7 +246,12 @@ void CBonusSelection::createBonusesIcons()
 			case CampaignBonusType::SPELL_SCROLL:
 			{
 				const auto & bonusValue = bonus.getValue<CampaignBonusSpellScroll>();
-				picNumber = bonusValue.spell;
+				const auto * spell = bonusValue.spell.toSpell();
+				if (!spell->getIconScenarioBonus().empty())
+					picName = spell->getIconScenarioBonus();
+				else
+					picNumber = bonusValue.spell.getNum();
+
 				desc.appendLocalString(EMetaText::GENERAL_TXT, 716);
 				desc.replaceName(bonusValue.spell);
 				break;
@@ -276,11 +292,14 @@ void CBonusSelection::createBonusesIcons()
 			case CampaignBonusType::SECONDARY_SKILL:
 			{
 				const auto & bonusValue = bonus.getValue<CampaignBonusSecondarySkill>();
+				const auto * skill = bonusValue.skill.toSkill();
 				desc.appendLocalString(EMetaText::GENERAL_TXT, 718);
 				desc.replaceTextID(TextIdentifier("core", "skilllev", bonusValue.mastery - 1).get());
 				desc.replaceName(bonusValue.skill);
-				picNumber = bonusValue.skill.getNum() * 3 + bonusValue.mastery - 1;
-
+				if (!skill->at(bonusValue.mastery).scenarioBonus.empty())
+					picName = skill->at(bonusValue.mastery).scenarioBonus.empty();
+				else
+					picNumber = bonusValue.skill.getNum() * 3 + bonusValue.mastery - 1;
 				break;
 			}
 			case CampaignBonusType::RESOURCE:

+ 3 - 3
config/schemas/artifact.json

@@ -91,16 +91,16 @@
 			"type" : "object",
 			"additionalProperties" : false,
 			"description" : "Graphical files associated with the artifact",
-			"required" : [ "image", "map" ],
+			"required" : [ "image", "map", "scenarioBonus" ],
 			"properties" : {
 				"image" : {
 					"type" : "string",
 					"description" : "Base image for this artifact, used for example in hero screen",
 					"format" : "imageFile"
 				},
-				"large" : {
+				"scenarioBonus" : {
 					"type" : "string",
-					"description" : "Large image, used for drag-and-drop and popup messages",
+					"description" : "Image 58x64 in size, for use as campaign scenario starting bonus selection",
 					"format" : "imageFile"
 				},
 				"map" : {

+ 6 - 0
config/schemas/skill.json

@@ -16,6 +16,7 @@
 				"images" : {
 					"type" : "object",
 					"description" : "Skill icons of varying size",
+					"required" : [ "small", "medium", "large", "scenarioBonus"],
 					"properties" : {
 						"small" : {
 							"type" : "string",
@@ -31,6 +32,11 @@
 							"type" : "string",
 							"description" : "82x93 skill icon",
 							"format" : "imageFile"
+						},
+						"scenarioBonus" : {
+							"type" : "string",
+							"description" : "58x64 skill icon for use as campaign scenario bonus",
+							"format" : "imageFile"
 						}
 					}
 				},

+ 62 - 4
config/schemas/spell.json

@@ -119,8 +119,67 @@
 			"additionalProperties" : false
 		}
 	},
-	"required" : ["type", "name", "school", "level", "power","gainChance","flags","levels"],
+	"required" : ["type", "name", "school", "level", "power", "flags", "levels"],
 	"additionalProperties" : false,
+	
+	"allOf": [
+		{
+			"if": {
+				"not" : {
+					"properties": {
+						"index" : {
+							"type" : "number"
+						}
+					}
+				},
+				"properties": {
+					"type": {
+						"enum" : ["adventure", "combat"],
+					},
+					
+				}
+			},
+			"then": {
+				"required" : ["school", "gainChance" ],
+				"properties": {
+					"levels": {
+						"required" : ["none", "basic", "advanced", "expert"]
+					},
+					"graphics" : {
+						"required" : ["iconBook", "iconScroll", "iconEffect", "iconImmune", "iconScenarioBonus"]
+					},
+				}
+			}
+		},
+		{
+			"if": {
+				"not" : {
+					"properties": {
+						"index" : {
+							"type" : "number"
+						}
+					}
+				},
+				"properties": {
+					"type": {
+						"const" : "ability"
+					}
+				}
+			},
+			"then": {
+				"required" : ["school", "gainChance" ],
+				"properties": {
+					"levels": {
+						"required" : ["none"]
+					},
+					"graphics" : {
+						"required" : ["iconEffect", "iconImmune"]
+					},
+				}
+			}
+		}
+	],
+	
 	"properties" : {
 		"index" : {
 			"type" : "number",
@@ -265,7 +324,7 @@
 				},
 				"iconEffect" : {
 					"type" : "string",
-					"description" : "Resourse path of icon for spell effects during battle" ,
+					"description" : "Resourse path of icon for spell effects during battle",
 					"format" : "imageFile"
 				},
 				"iconImmune" : {
@@ -275,7 +334,7 @@
 				},
 				"iconScenarioBonus" : {
 					"type" : "string",
-					"description" : "Resourse path of icon for scenario bonus" ,
+					"description" : "Resourse path of 58x64 icon for scenario bonus",
 					"format" : "imageFile"
 				}
 			}
@@ -293,7 +352,6 @@
 		"levels" : {
 			 "type" : "object",
 			 "additionalProperties" : false,
-			 "required" : ["none", "basic", "advanced", "expert"],
 			 "properties" : {
 				"base" : {
 					"type" : "object",

+ 2 - 2
docs/modders/Entities_Format/Artifact_Format.md

@@ -46,8 +46,8 @@ In order to make functional artifact you also need:
 		// Base image for this artifact, used for example in hero screen
 		"image": "BigSword.png",
 
-		// Large image, used for drag-and-drop and popup messages
-		"large": "BigSword_large.png",
+		// Large 58x64 image, used for campaign scenario bonus selection
+		"scenarioBonus": "BigSword_large.png",
 
 		//def file for adventure map
 		"map": "BigSword.def"

+ 2 - 0
docs/modders/Entities_Format/Secondary_Skill_Format.md

@@ -83,6 +83,8 @@ level fields become optional if they equal "base" configuration.
 		"medium" : "",
 		// 82x93 skill icon
 		"large" : "",
+		// 58x64 skill icon for campaign scenario bonus
+		"scenarioBonus" : ""
 	}
 }
 ```

+ 4 - 0
lib/CSkillHandler.cpp

@@ -249,6 +249,10 @@ std::shared_ptr<CSkill> CSkillHandler::loadFromJson(const std::string & scope, c
 		skillAtLevel.iconSmall = levelNode["images"]["small"].String();
 		skillAtLevel.iconMedium = levelNode["images"]["medium"].String();
 		skillAtLevel.iconLarge = levelNode["images"]["large"].String();
+		if (!levelNode["images"]["scenarioBonus"].isNull())
+			skillAtLevel.scenarioBonus = levelNode["images"]["scenarioBonus"].String();
+		else
+			skillAtLevel.scenarioBonus = skillAtLevel.iconMedium; // MOD COMPATIBILITY fallback for pre-1.7 mods
 	}
 
 	for(const auto & b : json["specialty"].Vector())

+ 1 - 0
lib/CSkillHandler.h

@@ -28,6 +28,7 @@ public:
 		std::string iconSmall;
 		std::string iconMedium;
 		std::string iconLarge;
+		std::string scenarioBonus;
 		std::vector<std::shared_ptr<Bonus>> effects;
 	};
 

+ 3 - 3
lib/entities/artifact/CArtHandler.cpp

@@ -166,10 +166,10 @@ std::shared_ptr<CArtifact> CArtHandler::loadFromJson(const std::string & scope,
 	const JsonNode & graphics = node["graphics"];
 	art->image = graphics["image"].String();
 
-	if(!graphics["large"].isNull())
-		art->large = graphics["large"].String();
+	if(!graphics["scenarioBonus"].isNull())
+		art->scenarioBonus = graphics["scenarioBonus"].String();
 	else
-		art->large = art->image;
+		art->scenarioBonus = art->image; // MOD COMPATIBILITY fallback for pre-1.7 mods
 
 	art->advMapDef = graphics["map"].String();
 

+ 1 - 2
lib/entities/artifact/CArtifact.cpp

@@ -102,7 +102,6 @@ std::string CArtifact::getModScope() const
 void CArtifact::registerIcons(const IconRegistar & cb) const
 {
 	cb(getIconIndex(), 0, "ARTIFACT", image);
-	cb(getIconIndex(), 0, "ARTIFACTLARGE", large);
 }
 
 ArtifactID CArtifact::getId() const
@@ -359,7 +358,7 @@ void CArtifact::setImage(int32_t newIconIndex, const std::string & newImage, con
 {
 	iconIndex = newIconIndex;
 	image = newImage;
-	large = newLargeImage;
+	scenarioBonus = newLargeImage;
 }
 
 

+ 2 - 1
lib/entities/artifact/CArtifact.h

@@ -91,7 +91,6 @@ class DLL_LINKAGE CArtifact final : public Artifact, public CBonusSystemNode,
 {
 	ArtifactID id;
 	std::string image;
-	std::string large; // big image for custom artifacts, used in drag & drop
 	std::string advMapDef; // used for adventure map object
 	std::string modScope;
 	std::string identifier;
@@ -105,6 +104,8 @@ public:
 	/// Bonuses that are created for each instance of artifact
 	std::vector<std::shared_ptr<Bonus>> instanceBonuses;
 
+	std::string scenarioBonus;
+
 	EArtifactClass aClass = EArtifactClass::ART_SPECIAL;
 	bool onlyOnWaterMap;