diff --git a/client/lobby/CBonusSelection.cpp b/client/lobby/CBonusSelection.cpp index 9ca0716c6..525fd73ee 100644 --- a/client/lobby/CBonusSelection.cpp +++ b/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(); - 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(); - 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(); - 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(); + 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: diff --git a/config/schemas/artifact.json b/config/schemas/artifact.json index 7818ac074..af82cf778 100644 --- a/config/schemas/artifact.json +++ b/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" : { diff --git a/config/schemas/skill.json b/config/schemas/skill.json index 6e98987f0..5c29e85ce 100644 --- a/config/schemas/skill.json +++ b/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" } } }, diff --git a/config/schemas/spell.json b/config/schemas/spell.json index f91c1cf35..c1ddadf74 100644 --- a/config/schemas/spell.json +++ b/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", diff --git a/docs/modders/Entities_Format/Artifact_Format.md b/docs/modders/Entities_Format/Artifact_Format.md index 46e12622b..f11b914dd 100644 --- a/docs/modders/Entities_Format/Artifact_Format.md +++ b/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" diff --git a/docs/modders/Entities_Format/Secondary_Skill_Format.md b/docs/modders/Entities_Format/Secondary_Skill_Format.md index 54da74461..eb9dc38db 100644 --- a/docs/modders/Entities_Format/Secondary_Skill_Format.md +++ b/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" : "" } } ``` diff --git a/lib/CSkillHandler.cpp b/lib/CSkillHandler.cpp index f2a962a2b..4eddd9b3e 100644 --- a/lib/CSkillHandler.cpp +++ b/lib/CSkillHandler.cpp @@ -249,6 +249,10 @@ std::shared_ptr 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()) diff --git a/lib/CSkillHandler.h b/lib/CSkillHandler.h index 5096e526d..0979a4a90 100644 --- a/lib/CSkillHandler.h +++ b/lib/CSkillHandler.h @@ -28,6 +28,7 @@ public: std::string iconSmall; std::string iconMedium; std::string iconLarge; + std::string scenarioBonus; std::vector> effects; }; diff --git a/lib/entities/artifact/CArtHandler.cpp b/lib/entities/artifact/CArtHandler.cpp index 8fbaf924d..7b893edd5 100644 --- a/lib/entities/artifact/CArtHandler.cpp +++ b/lib/entities/artifact/CArtHandler.cpp @@ -166,10 +166,10 @@ std::shared_ptr 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(); diff --git a/lib/entities/artifact/CArtifact.cpp b/lib/entities/artifact/CArtifact.cpp index 465480a1b..e63bde2e0 100644 --- a/lib/entities/artifact/CArtifact.cpp +++ b/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; } diff --git a/lib/entities/artifact/CArtifact.h b/lib/entities/artifact/CArtifact.h index 374272e1d..877797f95 100644 --- a/lib/entities/artifact/CArtifact.h +++ b/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> instanceBonuses; + std::string scenarioBonus; + EArtifactClass aClass = EArtifactClass::ART_SPECIAL; bool onlyOnWaterMap;