mirror of
https://github.com/vcmi/vcmi.git
synced 2025-07-13 01:20:34 +02:00
Support for objects from mods as campaign scenario bonuses
This commit is contained in:
@ -46,12 +46,14 @@
|
|||||||
#include "../../lib/GameLibrary.h"
|
#include "../../lib/GameLibrary.h"
|
||||||
#include "../../lib/StartInfo.h"
|
#include "../../lib/StartInfo.h"
|
||||||
#include "../../lib/campaign/CampaignState.h"
|
#include "../../lib/campaign/CampaignState.h"
|
||||||
|
#include "../../lib/entities/artifact/CArtifact.h"
|
||||||
#include "../../lib/entities/building/CBuilding.h"
|
#include "../../lib/entities/building/CBuilding.h"
|
||||||
#include "../../lib/entities/building/CBuildingHandler.h"
|
#include "../../lib/entities/building/CBuildingHandler.h"
|
||||||
#include "../../lib/entities/faction/CFaction.h"
|
#include "../../lib/entities/faction/CFaction.h"
|
||||||
#include "../../lib/entities/faction/CTown.h"
|
#include "../../lib/entities/faction/CTown.h"
|
||||||
#include "../../lib/entities/faction/CTownHandler.h"
|
#include "../../lib/entities/faction/CTownHandler.h"
|
||||||
#include "../../lib/entities/hero/CHeroHandler.h"
|
#include "../../lib/entities/hero/CHeroHandler.h"
|
||||||
|
#include "../../lib/spells/CSpellHandler.h"
|
||||||
#include "../../lib/filesystem/Filesystem.h"
|
#include "../../lib/filesystem/Filesystem.h"
|
||||||
#include "../../lib/mapObjects/CGHeroInstance.h"
|
#include "../../lib/mapObjects/CGHeroInstance.h"
|
||||||
#include "../../lib/mapping/CMapHeader.h"
|
#include "../../lib/mapping/CMapHeader.h"
|
||||||
@ -184,7 +186,12 @@ void CBonusSelection::createBonusesIcons()
|
|||||||
case CampaignBonusType::SPELL:
|
case CampaignBonusType::SPELL:
|
||||||
{
|
{
|
||||||
const auto & bonusValue = bonus.getValue<CampaignBonusSpell>();
|
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.appendLocalString(EMetaText::GENERAL_TXT, 715);
|
||||||
desc.replaceName(bonusValue.spell);
|
desc.replaceName(bonusValue.spell);
|
||||||
break;
|
break;
|
||||||
@ -227,7 +234,11 @@ void CBonusSelection::createBonusesIcons()
|
|||||||
case CampaignBonusType::ARTIFACT:
|
case CampaignBonusType::ARTIFACT:
|
||||||
{
|
{
|
||||||
const auto & bonusValue = bonus.getValue<CampaignBonusArtifact>();
|
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.appendLocalString(EMetaText::GENERAL_TXT, 715);
|
||||||
desc.replaceName(bonusValue.artifact);
|
desc.replaceName(bonusValue.artifact);
|
||||||
break;
|
break;
|
||||||
@ -235,7 +246,12 @@ void CBonusSelection::createBonusesIcons()
|
|||||||
case CampaignBonusType::SPELL_SCROLL:
|
case CampaignBonusType::SPELL_SCROLL:
|
||||||
{
|
{
|
||||||
const auto & bonusValue = bonus.getValue<CampaignBonusSpellScroll>();
|
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.appendLocalString(EMetaText::GENERAL_TXT, 716);
|
||||||
desc.replaceName(bonusValue.spell);
|
desc.replaceName(bonusValue.spell);
|
||||||
break;
|
break;
|
||||||
@ -276,11 +292,14 @@ void CBonusSelection::createBonusesIcons()
|
|||||||
case CampaignBonusType::SECONDARY_SKILL:
|
case CampaignBonusType::SECONDARY_SKILL:
|
||||||
{
|
{
|
||||||
const auto & bonusValue = bonus.getValue<CampaignBonusSecondarySkill>();
|
const auto & bonusValue = bonus.getValue<CampaignBonusSecondarySkill>();
|
||||||
|
const auto * skill = bonusValue.skill.toSkill();
|
||||||
desc.appendLocalString(EMetaText::GENERAL_TXT, 718);
|
desc.appendLocalString(EMetaText::GENERAL_TXT, 718);
|
||||||
desc.replaceTextID(TextIdentifier("core", "skilllev", bonusValue.mastery - 1).get());
|
desc.replaceTextID(TextIdentifier("core", "skilllev", bonusValue.mastery - 1).get());
|
||||||
desc.replaceName(bonusValue.skill);
|
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;
|
break;
|
||||||
}
|
}
|
||||||
case CampaignBonusType::RESOURCE:
|
case CampaignBonusType::RESOURCE:
|
||||||
|
@ -91,16 +91,16 @@
|
|||||||
"type" : "object",
|
"type" : "object",
|
||||||
"additionalProperties" : false,
|
"additionalProperties" : false,
|
||||||
"description" : "Graphical files associated with the artifact",
|
"description" : "Graphical files associated with the artifact",
|
||||||
"required" : [ "image", "map" ],
|
"required" : [ "image", "map", "scenarioBonus" ],
|
||||||
"properties" : {
|
"properties" : {
|
||||||
"image" : {
|
"image" : {
|
||||||
"type" : "string",
|
"type" : "string",
|
||||||
"description" : "Base image for this artifact, used for example in hero screen",
|
"description" : "Base image for this artifact, used for example in hero screen",
|
||||||
"format" : "imageFile"
|
"format" : "imageFile"
|
||||||
},
|
},
|
||||||
"large" : {
|
"scenarioBonus" : {
|
||||||
"type" : "string",
|
"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"
|
"format" : "imageFile"
|
||||||
},
|
},
|
||||||
"map" : {
|
"map" : {
|
||||||
|
@ -16,6 +16,7 @@
|
|||||||
"images" : {
|
"images" : {
|
||||||
"type" : "object",
|
"type" : "object",
|
||||||
"description" : "Skill icons of varying size",
|
"description" : "Skill icons of varying size",
|
||||||
|
"required" : [ "small", "medium", "large", "scenarioBonus"],
|
||||||
"properties" : {
|
"properties" : {
|
||||||
"small" : {
|
"small" : {
|
||||||
"type" : "string",
|
"type" : "string",
|
||||||
@ -31,6 +32,11 @@
|
|||||||
"type" : "string",
|
"type" : "string",
|
||||||
"description" : "82x93 skill icon",
|
"description" : "82x93 skill icon",
|
||||||
"format" : "imageFile"
|
"format" : "imageFile"
|
||||||
|
},
|
||||||
|
"scenarioBonus" : {
|
||||||
|
"type" : "string",
|
||||||
|
"description" : "58x64 skill icon for use as campaign scenario bonus",
|
||||||
|
"format" : "imageFile"
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
|
@ -119,8 +119,67 @@
|
|||||||
"additionalProperties" : false
|
"additionalProperties" : false
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
"required" : ["type", "name", "school", "level", "power","gainChance","flags","levels"],
|
"required" : ["type", "name", "school", "level", "power", "flags", "levels"],
|
||||||
"additionalProperties" : false,
|
"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" : {
|
"properties" : {
|
||||||
"index" : {
|
"index" : {
|
||||||
"type" : "number",
|
"type" : "number",
|
||||||
@ -265,7 +324,7 @@
|
|||||||
},
|
},
|
||||||
"iconEffect" : {
|
"iconEffect" : {
|
||||||
"type" : "string",
|
"type" : "string",
|
||||||
"description" : "Resourse path of icon for spell effects during battle" ,
|
"description" : "Resourse path of icon for spell effects during battle",
|
||||||
"format" : "imageFile"
|
"format" : "imageFile"
|
||||||
},
|
},
|
||||||
"iconImmune" : {
|
"iconImmune" : {
|
||||||
@ -275,7 +334,7 @@
|
|||||||
},
|
},
|
||||||
"iconScenarioBonus" : {
|
"iconScenarioBonus" : {
|
||||||
"type" : "string",
|
"type" : "string",
|
||||||
"description" : "Resourse path of icon for scenario bonus" ,
|
"description" : "Resourse path of 58x64 icon for scenario bonus",
|
||||||
"format" : "imageFile"
|
"format" : "imageFile"
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -293,7 +352,6 @@
|
|||||||
"levels" : {
|
"levels" : {
|
||||||
"type" : "object",
|
"type" : "object",
|
||||||
"additionalProperties" : false,
|
"additionalProperties" : false,
|
||||||
"required" : ["none", "basic", "advanced", "expert"],
|
|
||||||
"properties" : {
|
"properties" : {
|
||||||
"base" : {
|
"base" : {
|
||||||
"type" : "object",
|
"type" : "object",
|
||||||
|
@ -46,8 +46,8 @@ In order to make functional artifact you also need:
|
|||||||
// Base image for this artifact, used for example in hero screen
|
// Base image for this artifact, used for example in hero screen
|
||||||
"image": "BigSword.png",
|
"image": "BigSword.png",
|
||||||
|
|
||||||
// Large image, used for drag-and-drop and popup messages
|
// Large 58x64 image, used for campaign scenario bonus selection
|
||||||
"large": "BigSword_large.png",
|
"scenarioBonus": "BigSword_large.png",
|
||||||
|
|
||||||
//def file for adventure map
|
//def file for adventure map
|
||||||
"map": "BigSword.def"
|
"map": "BigSword.def"
|
||||||
|
@ -83,6 +83,8 @@ level fields become optional if they equal "base" configuration.
|
|||||||
"medium" : "",
|
"medium" : "",
|
||||||
// 82x93 skill icon
|
// 82x93 skill icon
|
||||||
"large" : "",
|
"large" : "",
|
||||||
|
// 58x64 skill icon for campaign scenario bonus
|
||||||
|
"scenarioBonus" : ""
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
```
|
```
|
||||||
|
@ -249,6 +249,10 @@ std::shared_ptr<CSkill> CSkillHandler::loadFromJson(const std::string & scope, c
|
|||||||
skillAtLevel.iconSmall = levelNode["images"]["small"].String();
|
skillAtLevel.iconSmall = levelNode["images"]["small"].String();
|
||||||
skillAtLevel.iconMedium = levelNode["images"]["medium"].String();
|
skillAtLevel.iconMedium = levelNode["images"]["medium"].String();
|
||||||
skillAtLevel.iconLarge = levelNode["images"]["large"].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())
|
for(const auto & b : json["specialty"].Vector())
|
||||||
|
@ -28,6 +28,7 @@ public:
|
|||||||
std::string iconSmall;
|
std::string iconSmall;
|
||||||
std::string iconMedium;
|
std::string iconMedium;
|
||||||
std::string iconLarge;
|
std::string iconLarge;
|
||||||
|
std::string scenarioBonus;
|
||||||
std::vector<std::shared_ptr<Bonus>> effects;
|
std::vector<std::shared_ptr<Bonus>> effects;
|
||||||
};
|
};
|
||||||
|
|
||||||
|
@ -166,10 +166,10 @@ std::shared_ptr<CArtifact> CArtHandler::loadFromJson(const std::string & scope,
|
|||||||
const JsonNode & graphics = node["graphics"];
|
const JsonNode & graphics = node["graphics"];
|
||||||
art->image = graphics["image"].String();
|
art->image = graphics["image"].String();
|
||||||
|
|
||||||
if(!graphics["large"].isNull())
|
if(!graphics["scenarioBonus"].isNull())
|
||||||
art->large = graphics["large"].String();
|
art->scenarioBonus = graphics["scenarioBonus"].String();
|
||||||
else
|
else
|
||||||
art->large = art->image;
|
art->scenarioBonus = art->image; // MOD COMPATIBILITY fallback for pre-1.7 mods
|
||||||
|
|
||||||
art->advMapDef = graphics["map"].String();
|
art->advMapDef = graphics["map"].String();
|
||||||
|
|
||||||
|
@ -102,7 +102,6 @@ std::string CArtifact::getModScope() const
|
|||||||
void CArtifact::registerIcons(const IconRegistar & cb) const
|
void CArtifact::registerIcons(const IconRegistar & cb) const
|
||||||
{
|
{
|
||||||
cb(getIconIndex(), 0, "ARTIFACT", image);
|
cb(getIconIndex(), 0, "ARTIFACT", image);
|
||||||
cb(getIconIndex(), 0, "ARTIFACTLARGE", large);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
ArtifactID CArtifact::getId() const
|
ArtifactID CArtifact::getId() const
|
||||||
@ -359,7 +358,7 @@ void CArtifact::setImage(int32_t newIconIndex, const std::string & newImage, con
|
|||||||
{
|
{
|
||||||
iconIndex = newIconIndex;
|
iconIndex = newIconIndex;
|
||||||
image = newImage;
|
image = newImage;
|
||||||
large = newLargeImage;
|
scenarioBonus = newLargeImage;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
@ -91,7 +91,6 @@ class DLL_LINKAGE CArtifact final : public Artifact, public CBonusSystemNode,
|
|||||||
{
|
{
|
||||||
ArtifactID id;
|
ArtifactID id;
|
||||||
std::string image;
|
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 advMapDef; // used for adventure map object
|
||||||
std::string modScope;
|
std::string modScope;
|
||||||
std::string identifier;
|
std::string identifier;
|
||||||
@ -105,6 +104,8 @@ public:
|
|||||||
/// Bonuses that are created for each instance of artifact
|
/// Bonuses that are created for each instance of artifact
|
||||||
std::vector<std::shared_ptr<Bonus>> instanceBonuses;
|
std::vector<std::shared_ptr<Bonus>> instanceBonuses;
|
||||||
|
|
||||||
|
std::string scenarioBonus;
|
||||||
|
|
||||||
EArtifactClass aClass = EArtifactClass::ART_SPECIAL;
|
EArtifactClass aClass = EArtifactClass::ART_SPECIAL;
|
||||||
bool onlyOnWaterMap;
|
bool onlyOnWaterMap;
|
||||||
|
|
||||||
|
Reference in New Issue
Block a user