mirror of
https://github.com/vcmi/vcmi.git
synced 2025-07-03 00:46:55 +02:00
Add support for custom icons & descriptions for bonuses
This commit is contained in:
@ -258,8 +258,8 @@ CStackWindow::BonusLineSection::BonusLineSection(CStackWindow * owner, size_t li
|
|||||||
|
|
||||||
static const std::array<Point, 2> offset =
|
static const std::array<Point, 2> offset =
|
||||||
{
|
{
|
||||||
Point(6, 4),
|
Point(6, 2),
|
||||||
Point(214, 4)
|
Point(214, 2)
|
||||||
};
|
};
|
||||||
|
|
||||||
auto drawBonusSource = [this](int leftRight, Point p, BonusInfo & bi)
|
auto drawBonusSource = [this](int leftRight, Point p, BonusInfo & bi)
|
||||||
@ -313,8 +313,14 @@ CStackWindow::BonusLineSection::BonusLineSection(CStackWindow * owner, size_t li
|
|||||||
BonusInfo & bi = parent->activeBonuses[bonusIndex];
|
BonusInfo & bi = parent->activeBonuses[bonusIndex];
|
||||||
if (!bi.imagePath.empty())
|
if (!bi.imagePath.empty())
|
||||||
icon[leftRight] = std::make_shared<CPicture>(bi.imagePath, position.x, position.y);
|
icon[leftRight] = std::make_shared<CPicture>(bi.imagePath, position.x, position.y);
|
||||||
name[leftRight] = std::make_shared<CLabel>(position.x + 60, position.y + 2, FONT_TINY, ETextAlignment::TOPLEFT, Colors::WHITE, bi.name, 137);
|
|
||||||
description[leftRight] = std::make_shared<CMultiLineLabel>(Rect(position.x + 60, position.y + 20, 137, 26), FONT_TINY, ETextAlignment::TOPLEFT, Colors::WHITE, bi.description);
|
if (!bi.name.empty())
|
||||||
|
{
|
||||||
|
name[leftRight] = std::make_shared<CLabel>(position.x + 60, position.y + 2, FONT_TINY, ETextAlignment::TOPLEFT, Colors::YELLOW, bi.name, 137);
|
||||||
|
description[leftRight] = std::make_shared<CMultiLineLabel>(Rect(position.x + 60, position.y + 20, 137, 26), FONT_TINY, ETextAlignment::TOPLEFT, Colors::WHITE, bi.description);
|
||||||
|
}
|
||||||
|
else
|
||||||
|
description[leftRight] = std::make_shared<CMultiLineLabel>(Rect(position.x + 60, position.y + 2, 137, 50), FONT_TINY, ETextAlignment::TOPLEFT, Colors::WHITE, bi.description);
|
||||||
drawBonusSource(leftRight, Point(position.x - 1, position.y - 1), bi);
|
drawBonusSource(leftRight, Point(position.x - 1, position.y - 1), bi);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -846,12 +852,9 @@ void CStackWindow::init()
|
|||||||
|
|
||||||
void CStackWindow::initBonusesList()
|
void CStackWindow::initBonusesList()
|
||||||
{
|
{
|
||||||
auto inputPtr = info->stackNode->getBonuses(CSelector(Bonus::Permanent), Selector::all);
|
BonusList receivedBonuses = *info->stackNode->getBonuses(CSelector(Bonus::Permanent), Selector::all);
|
||||||
|
|
||||||
BonusList output;
|
std::sort(receivedBonuses.begin(), receivedBonuses.end(), [this](std::shared_ptr<Bonus> v1, std::shared_ptr<Bonus> & v2){
|
||||||
BonusList input = *inputPtr;
|
|
||||||
|
|
||||||
std::sort(input.begin(), input.end(), [this](std::shared_ptr<Bonus> v1, std::shared_ptr<Bonus> & v2){
|
|
||||||
if (v1->source != v2->source)
|
if (v1->source != v2->source)
|
||||||
{
|
{
|
||||||
int priorityV1 = v1->source == BonusSource::CREATURE_ABILITY ? -1 : static_cast<int>(v1->source);
|
int priorityV1 = v1->source == BonusSource::CREATURE_ABILITY ? -1 : static_cast<int>(v1->source);
|
||||||
@ -862,25 +865,24 @@ void CStackWindow::initBonusesList()
|
|||||||
return info->stackNode->bonusToString(v1, false) < info->stackNode->bonusToString(v2, false);
|
return info->stackNode->bonusToString(v1, false) < info->stackNode->bonusToString(v2, false);
|
||||||
});
|
});
|
||||||
|
|
||||||
while(!input.empty())
|
BonusList visibleBonuses;
|
||||||
{
|
|
||||||
auto b = input.front();
|
for (const auto & bonus : info->stackNode->getExportedBonusList())
|
||||||
output.push_back(std::make_shared<Bonus>(*b));
|
visibleBonuses.push_back(bonus);
|
||||||
output.back()->val = input.valOfBonuses(Selector::typeSubtype(b->type, b->subtype)); //merge multiple bonuses into one
|
for (const auto & bonus : info->creature->getExportedBonusList())
|
||||||
input.remove_if (Selector::typeSubtype(b->type, b->subtype)); //remove used bonuses
|
visibleBonuses.push_back(bonus);
|
||||||
}
|
for (const auto & bonus : receivedBonuses)
|
||||||
|
if (bonus->sid.as<CreatureID>() != info->stackNode->getId())
|
||||||
|
visibleBonuses.push_back(bonus);
|
||||||
|
|
||||||
BonusInfo bonusInfo;
|
BonusInfo bonusInfo;
|
||||||
for(auto b : output)
|
for(auto b : visibleBonuses)
|
||||||
{
|
{
|
||||||
bonusInfo.name = info->stackNode->bonusToString(b, false);
|
bonusInfo.name = info->stackNode->bonusToString(b, false);
|
||||||
bonusInfo.description = info->stackNode->bonusToString(b, true);
|
bonusInfo.description = info->stackNode->bonusToString(b, true);
|
||||||
bonusInfo.imagePath = info->stackNode->bonusToGraphics(b);
|
bonusInfo.imagePath = info->stackNode->bonusToGraphics(b);
|
||||||
bonusInfo.bonusSource = b->source;
|
bonusInfo.bonusSource = b->source;
|
||||||
|
|
||||||
if(b->sid.as<CreatureID>() != info->stackNode->getId() && b->propagator && b->propagator->getPropagatorType() == CBonusSystemNode::HERO) // Shows bonus with "propagator":"HERO" only at creature with bonus
|
|
||||||
continue;
|
|
||||||
|
|
||||||
//if it's possible to give any description or image for this kind of bonus
|
//if it's possible to give any description or image for this kind of bonus
|
||||||
//TODO: figure out why half of bonuses don't have proper description
|
//TODO: figure out why half of bonuses don't have proper description
|
||||||
if(!bonusInfo.name.empty() || !bonusInfo.imagePath.empty())
|
if(!bonusInfo.name.empty() || !bonusInfo.imagePath.empty())
|
||||||
|
@ -79,14 +79,14 @@
|
|||||||
"type" : "MORALE",
|
"type" : "MORALE",
|
||||||
"val" : 1,
|
"val" : 1,
|
||||||
"valueType" : "BASE_NUMBER",
|
"valueType" : "BASE_NUMBER",
|
||||||
"description" : "core.arraytxt.123",
|
"description" : "@core.arraytxt.123",
|
||||||
"limiters": [{ "type" : "CREATURE_ALIGNMENT_LIMITER", "parameters" : ["good"] }]
|
"limiters": [{ "type" : "CREATURE_ALIGNMENT_LIMITER", "parameters" : ["good"] }]
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
"type" : "MORALE",
|
"type" : "MORALE",
|
||||||
"val" : -1,
|
"val" : -1,
|
||||||
"valueType" : "BASE_NUMBER",
|
"valueType" : "BASE_NUMBER",
|
||||||
"description" : "core.arraytxt.124",
|
"description" : "@core.arraytxt.124",
|
||||||
"limiters": [{ "type" : "CREATURE_ALIGNMENT_LIMITER", "parameters" : ["evil"] }]
|
"limiters": [{ "type" : "CREATURE_ALIGNMENT_LIMITER", "parameters" : ["evil"] }]
|
||||||
}
|
}
|
||||||
]
|
]
|
||||||
@ -99,7 +99,7 @@
|
|||||||
"type" : "LUCK",
|
"type" : "LUCK",
|
||||||
"val" : 2,
|
"val" : 2,
|
||||||
"valueType" : "BASE_NUMBER",
|
"valueType" : "BASE_NUMBER",
|
||||||
"description" : "core.arraytxt.83",
|
"description" : "@core.arraytxt.83",
|
||||||
"limiters": [{ "type" : "CREATURE_ALIGNMENT_LIMITER", "parameters" : ["neutral"] }]
|
"limiters": [{ "type" : "CREATURE_ALIGNMENT_LIMITER", "parameters" : ["neutral"] }]
|
||||||
}
|
}
|
||||||
]
|
]
|
||||||
@ -112,14 +112,14 @@
|
|||||||
"type" : "MORALE",
|
"type" : "MORALE",
|
||||||
"val" : -1,
|
"val" : -1,
|
||||||
"valueType" : "BASE_NUMBER",
|
"valueType" : "BASE_NUMBER",
|
||||||
"description" : "core.arraytxt.126",
|
"description" : "@core.arraytxt.126",
|
||||||
"limiters": [{ "type" : "CREATURE_ALIGNMENT_LIMITER", "parameters" : ["good"] }]
|
"limiters": [{ "type" : "CREATURE_ALIGNMENT_LIMITER", "parameters" : ["good"] }]
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
"type" : "MORALE",
|
"type" : "MORALE",
|
||||||
"val" : 1,
|
"val" : 1,
|
||||||
"valueType" : "BASE_NUMBER",
|
"valueType" : "BASE_NUMBER",
|
||||||
"description" : "core.arraytxt.125",
|
"description" : "@core.arraytxt.125",
|
||||||
"limiters": [{ "type" : "CREATURE_ALIGNMENT_LIMITER", "parameters" : ["evil"] }]
|
"limiters": [{ "type" : "CREATURE_ALIGNMENT_LIMITER", "parameters" : ["evil"] }]
|
||||||
}
|
}
|
||||||
]
|
]
|
||||||
@ -132,13 +132,13 @@
|
|||||||
"type" : "NO_MORALE",
|
"type" : "NO_MORALE",
|
||||||
"val" : 0,
|
"val" : 0,
|
||||||
"valueType" : "INDEPENDENT_MIN",
|
"valueType" : "INDEPENDENT_MIN",
|
||||||
"description" : "core.arraytxt.112"
|
"description" : "@core.arraytxt.112"
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
"type" : "NO_LUCK",
|
"type" : "NO_LUCK",
|
||||||
"val" : 0,
|
"val" : 0,
|
||||||
"valueType" : "INDEPENDENT_MIN",
|
"valueType" : "INDEPENDENT_MIN",
|
||||||
"description" : "core.arraytxt.81"
|
"description" : "@core.arraytxt.81"
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
"type" : "BLOCK_MAGIC_ABOVE",
|
"type" : "BLOCK_MAGIC_ABOVE",
|
||||||
|
@ -238,6 +238,7 @@
|
|||||||
{
|
{
|
||||||
"type" : "SPELL_AFTER_ATTACK",
|
"type" : "SPELL_AFTER_ATTACK",
|
||||||
"subtype" : "spell.stoneGaze",
|
"subtype" : "spell.stoneGaze",
|
||||||
|
"description" : "Medusa are able to turn anyone who looked at them to stone",
|
||||||
"val" : 20,
|
"val" : 20,
|
||||||
"addInfo" : [0,2]
|
"addInfo" : [0,2]
|
||||||
}
|
}
|
||||||
@ -282,6 +283,8 @@
|
|||||||
{
|
{
|
||||||
"type" : "SPELL_AFTER_ATTACK",
|
"type" : "SPELL_AFTER_ATTACK",
|
||||||
"subtype" : "spell.stoneGaze",
|
"subtype" : "spell.stoneGaze",
|
||||||
|
"description" : "{Eyes of Petrification}\nMedusa Queens have a 40% chance of turning anyone they look at to stone",
|
||||||
|
"icon" : "zvs/Lib1.res/unused/stone",
|
||||||
"val" : 20,
|
"val" : 20,
|
||||||
"addInfo" : [0,2]
|
"addInfo" : [0,2]
|
||||||
}
|
}
|
||||||
|
@ -438,6 +438,8 @@
|
|||||||
"stacking" : "Undead Dragons",
|
"stacking" : "Undead Dragons",
|
||||||
"propagator": "BATTLE_WIDE",
|
"propagator": "BATTLE_WIDE",
|
||||||
"propagationUpdater" : "BONUS_OWNER_UPDATER",
|
"propagationUpdater" : "BONUS_OWNER_UPDATER",
|
||||||
|
"icon" : "zvs/Lib1.res/unused/negativemorale"
|
||||||
|
"description" : "{Intimidating Presence}\Bone Dragons reduce morale of all enemy units by 1",
|
||||||
"limiters" : [ "OPPOSITE_SIDE" ]
|
"limiters" : [ "OPPOSITE_SIDE" ]
|
||||||
},
|
},
|
||||||
"KING_1" : // Will be affected by Slayer with no expertise
|
"KING_1" : // Will be affected by Slayer with no expertise
|
||||||
@ -493,6 +495,7 @@
|
|||||||
"stacking" : "Undead Dragons",
|
"stacking" : "Undead Dragons",
|
||||||
"propagator": "BATTLE_WIDE",
|
"propagator": "BATTLE_WIDE",
|
||||||
"propagationUpdater" : "BONUS_OWNER_UPDATER",
|
"propagationUpdater" : "BONUS_OWNER_UPDATER",
|
||||||
|
"description" : "{Intimidating Presence}\nReduces morale of all enemy units by 1",
|
||||||
"limiters" : [ "OPPOSITE_SIDE" ]
|
"limiters" : [ "OPPOSITE_SIDE" ]
|
||||||
},
|
},
|
||||||
"KING_1" : // Will be affected by Slayer with no expertise
|
"KING_1" : // Will be affected by Slayer with no expertise
|
||||||
|
@ -228,6 +228,11 @@ std::string CCreature::getDescriptionTextID() const
|
|||||||
return TextIdentifier("creatures", modScope, identifier, "description").get();
|
return TextIdentifier("creatures", modScope, identifier, "description").get();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
std::string CCreature::getBonusTextID(const std::string & bonusID) const
|
||||||
|
{
|
||||||
|
return TextIdentifier("creatures", modScope, identifier, "bonus", bonusID).get();
|
||||||
|
}
|
||||||
|
|
||||||
CCreature::CreatureQuantityId CCreature::getQuantityID(const int & quantity)
|
CCreature::CreatureQuantityId CCreature::getQuantityID(const int & quantity)
|
||||||
{
|
{
|
||||||
if (quantity<5)
|
if (quantity<5)
|
||||||
@ -904,7 +909,7 @@ void CCreatureHandler::loadCreatureJson(CCreature * creature, const JsonNode & c
|
|||||||
{
|
{
|
||||||
if (!ability.second.isNull())
|
if (!ability.second.isNull())
|
||||||
{
|
{
|
||||||
auto b = JsonUtils::parseBonus(ability.second);
|
auto b = JsonUtils::parseBonus(ability.second, creature->getBonusTextID(ability.first));
|
||||||
b->source = BonusSource::CREATURE_ABILITY;
|
b->source = BonusSource::CREATURE_ABILITY;
|
||||||
b->sid = BonusSourceID(creature->getId());
|
b->sid = BonusSourceID(creature->getId());
|
||||||
b->duration = BonusDuration::PERMANENT;
|
b->duration = BonusDuration::PERMANENT;
|
||||||
|
@ -56,6 +56,7 @@ class DLL_LINKAGE CCreature : public Creature, public CBonusSystemNode
|
|||||||
public:
|
public:
|
||||||
std::string getDescriptionTranslated() const;
|
std::string getDescriptionTranslated() const;
|
||||||
std::string getDescriptionTextID() const;
|
std::string getDescriptionTextID() const;
|
||||||
|
std::string getBonusTextID(const std::string & bonusID) const;
|
||||||
|
|
||||||
ui32 ammMin; // initial size of stack of these creatures on adventure map (if not set in editor)
|
ui32 ammMin; // initial size of stack of these creatures on adventure map (if not set in editor)
|
||||||
ui32 ammMax;
|
ui32 ammMax;
|
||||||
|
@ -837,11 +837,20 @@ void CStackInstance::setCount(TQuantity newCount)
|
|||||||
|
|
||||||
std::string CStackInstance::bonusToString(const std::shared_ptr<Bonus>& bonus, bool description) const
|
std::string CStackInstance::bonusToString(const std::shared_ptr<Bonus>& bonus, bool description) const
|
||||||
{
|
{
|
||||||
|
if (!bonus->description.empty())
|
||||||
|
{
|
||||||
|
if (description)
|
||||||
|
return bonus->description.toString();
|
||||||
|
else
|
||||||
|
return {};
|
||||||
|
}
|
||||||
return LIBRARY->getBth()->bonusToString(bonus, this, description);
|
return LIBRARY->getBth()->bonusToString(bonus, this, description);
|
||||||
}
|
}
|
||||||
|
|
||||||
ImagePath CStackInstance::bonusToGraphics(const std::shared_ptr<Bonus> & bonus) const
|
ImagePath CStackInstance::bonusToGraphics(const std::shared_ptr<Bonus> & bonus) const
|
||||||
{
|
{
|
||||||
|
if (!bonus->customIconPath.empty())
|
||||||
|
return bonus->customIconPath;
|
||||||
return LIBRARY->getBth()->bonusToGraphics(bonus);
|
return LIBRARY->getBth()->bonusToGraphics(bonus);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -109,8 +109,11 @@ void CSkill::addNewBonus(const std::shared_ptr<Bonus> & b, int level)
|
|||||||
b->source = BonusSource::SECONDARY_SKILL;
|
b->source = BonusSource::SECONDARY_SKILL;
|
||||||
b->sid = BonusSourceID(id);
|
b->sid = BonusSourceID(id);
|
||||||
b->duration = BonusDuration::PERMANENT;
|
b->duration = BonusDuration::PERMANENT;
|
||||||
b->description.appendTextID(getNameTextID());
|
if (b->description.empty() && (b->type == BonusType::LUCK || b->type == BonusType::MORALE))
|
||||||
b->description.appendRawString(" %+d");
|
{
|
||||||
|
b->description.appendTextID(getNameTextID());
|
||||||
|
b->description.appendRawString(" %+d");
|
||||||
|
}
|
||||||
levels[level-1].effects.push_back(b);
|
levels[level-1].effects.push_back(b);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -15,6 +15,7 @@
|
|||||||
#include "../constants/EntityIdentifiers.h"
|
#include "../constants/EntityIdentifiers.h"
|
||||||
#include "../serializer/Serializeable.h"
|
#include "../serializer/Serializeable.h"
|
||||||
#include "../texts/MetaString.h"
|
#include "../texts/MetaString.h"
|
||||||
|
#include "../filesystem/ResourcePath.h"
|
||||||
|
|
||||||
VCMI_LIB_NAMESPACE_BEGIN
|
VCMI_LIB_NAMESPACE_BEGIN
|
||||||
|
|
||||||
@ -79,6 +80,7 @@ struct DLL_LINKAGE Bonus : public std::enable_shared_from_this<Bonus>, public Se
|
|||||||
TUpdaterPtr updater;
|
TUpdaterPtr updater;
|
||||||
TUpdaterPtr propagationUpdater;
|
TUpdaterPtr propagationUpdater;
|
||||||
|
|
||||||
|
ImagePath customIconPath;
|
||||||
MetaString description;
|
MetaString description;
|
||||||
|
|
||||||
Bonus(BonusDuration::Type Duration, BonusType Type, BonusSource Src, si32 Val, BonusSourceID sourceID);
|
Bonus(BonusDuration::Type Duration, BonusType Type, BonusSource Src, si32 Val, BonusSourceID sourceID);
|
||||||
@ -95,6 +97,8 @@ struct DLL_LINKAGE Bonus : public std::enable_shared_from_this<Bonus>, public Se
|
|||||||
h & val;
|
h & val;
|
||||||
h & sid;
|
h & sid;
|
||||||
h & description;
|
h & description;
|
||||||
|
if (h.hasFeature(Handler::Version::CUSTOM_BONUS_ICONS))
|
||||||
|
h & customIconPath;
|
||||||
h & additionalInfo;
|
h & additionalInfo;
|
||||||
h & turnsRemain;
|
h & turnsRemain;
|
||||||
h & valType;
|
h & valType;
|
||||||
|
@ -80,8 +80,6 @@ public:
|
|||||||
std::copy(newList.begin(), newList.end(), bonuses.begin());
|
std::copy(newList.begin(), newList.end(), bonuses.begin());
|
||||||
}
|
}
|
||||||
|
|
||||||
template <class InputIterator>
|
|
||||||
void insert(const int position, InputIterator first, InputIterator last);
|
|
||||||
void insert(TInternalContainer::iterator position, TInternalContainer::size_type n, const std::shared_ptr<Bonus> & x);
|
void insert(TInternalContainer::iterator position, TInternalContainer::size_type n, const std::shared_ptr<Bonus> & x);
|
||||||
|
|
||||||
template <typename Handler>
|
template <typename Handler>
|
||||||
|
@ -332,8 +332,11 @@ void CArtifact::addNewBonus(const std::shared_ptr<Bonus>& b)
|
|||||||
{
|
{
|
||||||
b->source = BonusSource::ARTIFACT;
|
b->source = BonusSource::ARTIFACT;
|
||||||
b->duration = BonusDuration::PERMANENT;
|
b->duration = BonusDuration::PERMANENT;
|
||||||
b->description.appendTextID(getNameTextID());
|
if (b->description.empty() && (b->type == BonusType::LUCK || b->type == BonusType::MORALE))
|
||||||
b->description.appendRawString(" %+d");
|
{
|
||||||
|
b->description.appendTextID(getNameTextID());
|
||||||
|
b->description.appendRawString(" %+d");
|
||||||
|
}
|
||||||
CBonusSystemNode::addNewBonus(b);
|
CBonusSystemNode::addNewBonus(b);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -615,10 +615,10 @@ std::shared_ptr<ILimiter> JsonUtils::parseLimiter(const JsonNode & limiter)
|
|||||||
return nullptr;
|
return nullptr;
|
||||||
}
|
}
|
||||||
|
|
||||||
std::shared_ptr<Bonus> JsonUtils::parseBonus(const JsonNode &ability)
|
std::shared_ptr<Bonus> JsonUtils::parseBonus(const JsonNode &ability, const TextIdentifier & descriptionID)
|
||||||
{
|
{
|
||||||
auto b = std::make_shared<Bonus>();
|
auto b = std::make_shared<Bonus>();
|
||||||
if (!parseBonus(ability, b.get()))
|
if (!parseBonus(ability, b.get(), descriptionID))
|
||||||
{
|
{
|
||||||
// caller code can not handle this case and presumes that returned bonus is always valid
|
// caller code can not handle this case and presumes that returned bonus is always valid
|
||||||
logGlobal->error("Failed to parse bonus! Json config was %S ", ability.toString());
|
logGlobal->error("Failed to parse bonus! Json config was %S ", ability.toString());
|
||||||
@ -628,7 +628,7 @@ std::shared_ptr<Bonus> JsonUtils::parseBonus(const JsonNode &ability)
|
|||||||
return b;
|
return b;
|
||||||
}
|
}
|
||||||
|
|
||||||
bool JsonUtils::parseBonus(const JsonNode &ability, Bonus *b)
|
bool JsonUtils::parseBonus(const JsonNode &ability, Bonus *b, const TextIdentifier & descriptionID)
|
||||||
{
|
{
|
||||||
const JsonNode * value = nullptr;
|
const JsonNode * value = nullptr;
|
||||||
|
|
||||||
@ -671,12 +671,23 @@ bool JsonUtils::parseBonus(const JsonNode &ability, Bonus *b)
|
|||||||
|
|
||||||
if(!ability["description"].isNull())
|
if(!ability["description"].isNull())
|
||||||
{
|
{
|
||||||
if (ability["description"].isString())
|
if (ability["description"].isString() && !ability["description"].String().empty())
|
||||||
b->description.appendTextID(ability["description"].String());
|
{
|
||||||
|
if (ability["description"].String()[0] == '@')
|
||||||
|
b->description.appendTextID(ability["description"].String());
|
||||||
|
else if (!descriptionID.get().empty())
|
||||||
|
{
|
||||||
|
LIBRARY->generaltexth->registerString(ability.getModScope(), descriptionID, ability["description"]);
|
||||||
|
b->description.appendTextID(descriptionID.get());
|
||||||
|
}
|
||||||
|
}
|
||||||
if (ability["description"].isNumber())
|
if (ability["description"].isNumber())
|
||||||
b->description.appendTextID("core.arraytxt." + std::to_string(ability["description"].Integer()));
|
b->description.appendTextID("core.arraytxt." + std::to_string(ability["description"].Integer()));
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if(!ability["icon"].isNull())
|
||||||
|
b->customIconPath = ImagePath::fromJson(ability["icon"]);
|
||||||
|
|
||||||
value = &ability["effectRange"];
|
value = &ability["effectRange"];
|
||||||
if (!value->isNull())
|
if (!value->isNull())
|
||||||
b->effectRange = static_cast<BonusLimitEffect>(parseByMapN(bonusLimitEffect, value, "effect range "));
|
b->effectRange = static_cast<BonusLimitEffect>(parseByMapN(bonusLimitEffect, value, "effect range "));
|
||||||
|
@ -11,6 +11,7 @@
|
|||||||
|
|
||||||
#include "JsonNode.h"
|
#include "JsonNode.h"
|
||||||
#include "../GameConstants.h"
|
#include "../GameConstants.h"
|
||||||
|
#include "../texts/TextIdentifier.h"
|
||||||
|
|
||||||
VCMI_LIB_NAMESPACE_BEGIN
|
VCMI_LIB_NAMESPACE_BEGIN
|
||||||
|
|
||||||
@ -18,12 +19,11 @@ struct Bonus;
|
|||||||
class ILimiter;
|
class ILimiter;
|
||||||
class CSelector;
|
class CSelector;
|
||||||
class CAddInfo;
|
class CAddInfo;
|
||||||
|
|
||||||
namespace JsonUtils
|
namespace JsonUtils
|
||||||
{
|
{
|
||||||
std::shared_ptr<Bonus> parseBonus(const JsonVector & ability_vec);
|
std::shared_ptr<Bonus> parseBonus(const JsonVector & ability_vec);
|
||||||
std::shared_ptr<Bonus> parseBonus(const JsonNode & ability);
|
std::shared_ptr<Bonus> parseBonus(const JsonNode & ability, const TextIdentifier & descriptionID = "");
|
||||||
bool parseBonus(const JsonNode & ability, Bonus * placement);
|
bool parseBonus(const JsonNode & ability, Bonus * placement, const TextIdentifier & descriptionID = "");
|
||||||
std::shared_ptr<ILimiter> parseLimiter(const JsonNode & limiter);
|
std::shared_ptr<ILimiter> parseLimiter(const JsonNode & limiter);
|
||||||
CSelector parseSelector(const JsonNode &ability);
|
CSelector parseSelector(const JsonNode &ability);
|
||||||
void resolveAddInfo(CAddInfo & var, const JsonNode & node);
|
void resolveAddInfo(CAddInfo & var, const JsonNode & node);
|
||||||
|
@ -42,8 +42,9 @@ enum class ESerializationVersion : int32_t
|
|||||||
REWARDABLE_EXTENSIONS, // new functionality for rewardable objects
|
REWARDABLE_EXTENSIONS, // new functionality for rewardable objects
|
||||||
FLAGGABLE_BONUS_SYSTEM_NODE, // flaggable objects now contain bonus system node
|
FLAGGABLE_BONUS_SYSTEM_NODE, // flaggable objects now contain bonus system node
|
||||||
RANDOMIZATION_REWORK, // random rolls logic has been moved to server
|
RANDOMIZATION_REWORK, // random rolls logic has been moved to server
|
||||||
|
CUSTOM_BONUS_ICONS, // support for custom icons in bonuses
|
||||||
|
|
||||||
CURRENT = RANDOMIZATION_REWORK,
|
CURRENT = CUSTOM_BONUS_ICONS,
|
||||||
};
|
};
|
||||||
|
|
||||||
static_assert(ESerializationVersion::MINIMAL <= ESerializationVersion::CURRENT, "Invalid serialization version definition!");
|
static_assert(ESerializationVersion::MINIMAL <= ESerializationVersion::CURRENT, "Invalid serialization version definition!");
|
||||||
|
Reference in New Issue
Block a user