mirror of
https://github.com/vcmi/vcmi.git
synced 2025-11-29 23:07:48 +02:00
Replace bonus string description with metastring that can properly
handle translations
This commit is contained in:
@@ -208,8 +208,7 @@ void StackWithBonuses::removeUnitBonus(const std::vector<Bonus> & bonus)
|
|||||||
&& one.sid == b->sid
|
&& one.sid == b->sid
|
||||||
&& one.valType == b->valType
|
&& one.valType == b->valType
|
||||||
&& one.additionalInfo == b->additionalInfo
|
&& one.additionalInfo == b->additionalInfo
|
||||||
&& one.effectRange == b->effectRange
|
&& one.effectRange == b->effectRange;
|
||||||
&& one.description == b->description;
|
|
||||||
});
|
});
|
||||||
|
|
||||||
removeUnitBonus(selector);
|
removeUnitBonus(selector);
|
||||||
|
|||||||
@@ -79,14 +79,14 @@
|
|||||||
"type" : "MORALE",
|
"type" : "MORALE",
|
||||||
"val" : 1,
|
"val" : 1,
|
||||||
"valueType" : "BASE_NUMBER",
|
"valueType" : "BASE_NUMBER",
|
||||||
"description" : "Creatures of good town alignment on Holly Ground",
|
"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" : "Creatures of evil town alignment on Holly Ground",
|
"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" : "Creatures of neutral town alignment on Clover Field",
|
"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" : "Creatures of good town alignment on Evil Fog",
|
"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" : "Creatures of evil town alignment on Evil Fog",
|
"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" : "Creatures on Cursed Ground"
|
"description" : "core.arraytxt.112"
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
"type" : "NO_LUCK",
|
"type" : "NO_LUCK",
|
||||||
"val" : 0,
|
"val" : 0,
|
||||||
"valueType" : "INDEPENDENT_MIN",
|
"valueType" : "INDEPENDENT_MIN",
|
||||||
"description" : "Creatures on Cursed Ground"
|
"description" : "core.arraytxt.81"
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
"type" : "BLOCK_MAGIC_ABOVE",
|
"type" : "BLOCK_MAGIC_ABOVE",
|
||||||
|
|||||||
@@ -294,7 +294,7 @@ 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 = getNameTranslated();
|
b->description.appendName(id);
|
||||||
CBonusSystemNode::addNewBonus(b);
|
CBonusSystemNode::addNewBonus(b);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -94,7 +94,7 @@ 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 = getNameTranslated();
|
b->description.appendTextID(getNameTextID());
|
||||||
levels[level-1].effects.push_back(b);
|
levels[level-1].effects.push_back(b);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -575,20 +575,9 @@ std::shared_ptr<Bonus> CTownHandler::createBonus(CBuilding * build, BonusType ty
|
|||||||
|
|
||||||
std::shared_ptr<Bonus> CTownHandler::createBonus(CBuilding * build, BonusType type, int val, BonusSubtypeID subtype, const TPropagatorPtr & prop) const
|
std::shared_ptr<Bonus> CTownHandler::createBonus(CBuilding * build, BonusType type, int val, BonusSubtypeID subtype, const TPropagatorPtr & prop) const
|
||||||
{
|
{
|
||||||
std::ostringstream descr;
|
auto b = std::make_shared<Bonus>(BonusDuration::PERMANENT, type, BonusSource::TOWN_STRUCTURE, val, build->getUniqueTypeID(), subtype);
|
||||||
descr << build->getNameTranslated();
|
|
||||||
return createBonusImpl(build->bid, build->town->faction->getId(), type, val, prop, descr.str(), subtype);
|
|
||||||
}
|
|
||||||
|
|
||||||
std::shared_ptr<Bonus> CTownHandler::createBonusImpl(const BuildingID & building,
|
b->description.appendTextID(build->getNameTextID());
|
||||||
const FactionID & faction,
|
|
||||||
BonusType type,
|
|
||||||
int val,
|
|
||||||
const TPropagatorPtr & prop,
|
|
||||||
const std::string & description,
|
|
||||||
BonusSubtypeID subtype) const
|
|
||||||
{
|
|
||||||
auto b = std::make_shared<Bonus>(BonusDuration::PERMANENT, type, BonusSource::TOWN_STRUCTURE, val, BuildingTypeUniqueID(faction, building), subtype, description);
|
|
||||||
|
|
||||||
if(prop)
|
if(prop)
|
||||||
b->addPropagator(prop);
|
b->addPropagator(prop);
|
||||||
@@ -600,12 +589,13 @@ void CTownHandler::loadSpecialBuildingBonuses(const JsonNode & source, BonusList
|
|||||||
{
|
{
|
||||||
for(const auto & b : source.Vector())
|
for(const auto & b : source.Vector())
|
||||||
{
|
{
|
||||||
auto bonus = JsonUtils::parseBuildingBonus(b, building->town->faction->getId(), building->bid, building->getNameTranslated());
|
auto bonus = std::make_shared<Bonus>(BonusDuration::PERMANENT, BonusType::NONE, BonusSource::TOWN_STRUCTURE, 0, BonusSourceID(building->getUniqueTypeID()));
|
||||||
|
|
||||||
if(bonus == nullptr)
|
if(!JsonUtils::parseBonus(b, bonus.get()))
|
||||||
continue;
|
continue;
|
||||||
|
|
||||||
bonus->sid = BonusSourceID(building->getUniqueTypeID());
|
bonus->description.appendTextID(building->getNameTextID());
|
||||||
|
|
||||||
//JsonUtils::parseBuildingBonus produces UNKNOWN type propagator instead of empty.
|
//JsonUtils::parseBuildingBonus produces UNKNOWN type propagator instead of empty.
|
||||||
if(bonus->propagator != nullptr
|
if(bonus->propagator != nullptr
|
||||||
&& bonus->propagator->getPropagatorType() == CBonusSystemNode::ENodeTypes::UNKNOWN)
|
&& bonus->propagator->getPropagatorType() == CBonusSystemNode::ENodeTypes::UNKNOWN)
|
||||||
|
|||||||
@@ -303,13 +303,6 @@ class DLL_LINKAGE CTownHandler : public CHandlerBase<FactionID, Faction, CFactio
|
|||||||
std::shared_ptr<Bonus> createBonus(CBuilding * build, BonusType type, int val) const;
|
std::shared_ptr<Bonus> createBonus(CBuilding * build, BonusType type, int val) const;
|
||||||
std::shared_ptr<Bonus> createBonus(CBuilding * build, BonusType type, int val, BonusSubtypeID subtype) const;
|
std::shared_ptr<Bonus> createBonus(CBuilding * build, BonusType type, int val, BonusSubtypeID subtype) const;
|
||||||
std::shared_ptr<Bonus> createBonus(CBuilding * build, BonusType type, int val, BonusSubtypeID subtype, const TPropagatorPtr & prop) const;
|
std::shared_ptr<Bonus> createBonus(CBuilding * build, BonusType type, int val, BonusSubtypeID subtype, const TPropagatorPtr & prop) const;
|
||||||
std::shared_ptr<Bonus> createBonusImpl(const BuildingID & building,
|
|
||||||
const FactionID & faction,
|
|
||||||
BonusType type,
|
|
||||||
int val,
|
|
||||||
const TPropagatorPtr & prop,
|
|
||||||
const std::string & description,
|
|
||||||
BonusSubtypeID subtype) const;
|
|
||||||
|
|
||||||
/// loads CStructure's into town
|
/// loads CStructure's into town
|
||||||
void loadStructure(CTown & town, const std::string & stringID, const JsonNode & source) const;
|
void loadStructure(CTown & town, const std::string & stringID, const JsonNode & source) const;
|
||||||
|
|||||||
@@ -917,8 +917,7 @@ void BattleInfo::removeUnitBonus(uint32_t id, const std::vector<Bonus> & bonus)
|
|||||||
&& one.sid == b->sid
|
&& one.sid == b->sid
|
||||||
&& one.valType == b->valType
|
&& one.valType == b->valType
|
||||||
&& one.additionalInfo == b->additionalInfo
|
&& one.additionalInfo == b->additionalInfo
|
||||||
&& one.effectRange == b->effectRange
|
&& one.effectRange == b->effectRange;
|
||||||
&& one.description == b->description;
|
|
||||||
};
|
};
|
||||||
sta->removeBonusesRecursive(selector);
|
sta->removeBonusesRecursive(selector);
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -90,7 +90,7 @@ JsonNode CAddInfo::toJsonNode() const
|
|||||||
}
|
}
|
||||||
std::string Bonus::Description(std::optional<si32> customValue) const
|
std::string Bonus::Description(std::optional<si32> customValue) const
|
||||||
{
|
{
|
||||||
std::string str;
|
MetaString descriptionHelper;
|
||||||
|
|
||||||
if(description.empty())
|
if(description.empty())
|
||||||
{
|
{
|
||||||
@@ -99,42 +99,43 @@ std::string Bonus::Description(std::optional<si32> customValue) const
|
|||||||
switch(source)
|
switch(source)
|
||||||
{
|
{
|
||||||
case BonusSource::ARTIFACT:
|
case BonusSource::ARTIFACT:
|
||||||
str = sid.as<ArtifactID>().toEntity(VLC)->getNameTranslated();
|
descriptionHelper.appendName(sid.as<ArtifactID>());
|
||||||
break;
|
break;
|
||||||
case BonusSource::SPELL_EFFECT:
|
case BonusSource::SPELL_EFFECT:
|
||||||
str = sid.as<SpellID>().toEntity(VLC)->getNameTranslated();
|
descriptionHelper.appendName(sid.as<SpellID>());
|
||||||
break;
|
break;
|
||||||
case BonusSource::CREATURE_ABILITY:
|
case BonusSource::CREATURE_ABILITY:
|
||||||
str = sid.as<CreatureID>().toEntity(VLC)->getNamePluralTranslated();
|
descriptionHelper.appendNamePlural(sid.as<CreatureID>());
|
||||||
break;
|
break;
|
||||||
case BonusSource::SECONDARY_SKILL:
|
case BonusSource::SECONDARY_SKILL:
|
||||||
str = VLC->skills()->getById(sid.as<SecondarySkill>())->getNameTranslated();
|
descriptionHelper.appendTextID(sid.as<SecondarySkill>().toEntity(VLC)->getNameTextID());
|
||||||
break;
|
break;
|
||||||
case BonusSource::HERO_SPECIAL:
|
case BonusSource::HERO_SPECIAL:
|
||||||
str = VLC->heroTypes()->getById(sid.as<HeroTypeID>())->getNameTranslated();
|
descriptionHelper.appendTextID(sid.as<HeroTypeID>().toEntity(VLC)->getNameTextID());
|
||||||
break;
|
break;
|
||||||
default:
|
default:
|
||||||
//todo: handle all possible sources
|
//todo: handle all possible sources
|
||||||
str = "Unknown";
|
descriptionHelper.appendRawString("Unknown");
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
str = stacking;
|
descriptionHelper = MetaString::createFromRawString(stacking);
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
str = description;
|
descriptionHelper = description;
|
||||||
}
|
}
|
||||||
|
|
||||||
if(auto value = customValue.value_or(val)) {
|
auto valueToShow = customValue.value_or(val);
|
||||||
//arraytxt already contains +-value
|
|
||||||
std::string valueString = boost::str(boost::format(" %+d") % value);
|
if(valueToShow != 0)
|
||||||
if(!boost::algorithm::ends_with(str, valueString))
|
{
|
||||||
str += valueString;
|
descriptionHelper.replaceNumber(valueToShow);
|
||||||
|
descriptionHelper.replacePositiveNumber(valueToShow);
|
||||||
}
|
}
|
||||||
|
|
||||||
return str;
|
return descriptionHelper.toString();
|
||||||
}
|
}
|
||||||
|
|
||||||
static JsonNode additionalInfoToJson(BonusType type, CAddInfo addInfo)
|
static JsonNode additionalInfoToJson(BonusType type, CAddInfo addInfo)
|
||||||
@@ -170,7 +171,7 @@ JsonNode Bonus::toJsonNode() const
|
|||||||
if(!stacking.empty())
|
if(!stacking.empty())
|
||||||
root["stacking"].String() = stacking;
|
root["stacking"].String() = stacking;
|
||||||
if(!description.empty())
|
if(!description.empty())
|
||||||
root["description"].String() = description;
|
root["description"].String() = description.toString();
|
||||||
if(effectRange != BonusLimitEffect::NO_LIMIT)
|
if(effectRange != BonusLimitEffect::NO_LIMIT)
|
||||||
root["effectRange"].String() = vstd::findKey(bonusLimitEffect, effectRange);
|
root["effectRange"].String() = vstd::findKey(bonusLimitEffect, effectRange);
|
||||||
if(duration != BonusDuration::PERMANENT)
|
if(duration != BonusDuration::PERMANENT)
|
||||||
@@ -187,27 +188,17 @@ JsonNode Bonus::toJsonNode() const
|
|||||||
}
|
}
|
||||||
|
|
||||||
Bonus::Bonus(BonusDuration::Type Duration, BonusType Type, BonusSource Src, si32 Val, BonusSourceID ID)
|
Bonus::Bonus(BonusDuration::Type Duration, BonusType Type, BonusSource Src, si32 Val, BonusSourceID ID)
|
||||||
: Bonus(Duration, Type, Src, Val, ID, BonusSubtypeID(), std::string())
|
: Bonus(Duration, Type, Src, Val, ID, BonusSubtypeID())
|
||||||
{}
|
{}
|
||||||
|
|
||||||
Bonus::Bonus(BonusDuration::Type Duration, BonusType Type, BonusSource Src, si32 Val, BonusSourceID ID, std::string Desc)
|
Bonus::Bonus(BonusDuration::Type Duration, BonusType Type, BonusSource Src, si32 Val, BonusSourceID ID, BonusSubtypeID Subtype):
|
||||||
: Bonus(Duration, Type, Src, Val, ID, BonusSubtypeID(), Desc)
|
|
||||||
{}
|
|
||||||
|
|
||||||
Bonus::Bonus(BonusDuration::Type Duration, BonusType Type, BonusSource Src, si32 Val, BonusSourceID ID, BonusSubtypeID Subtype)
|
|
||||||
: Bonus(Duration, Type, Src, Val, ID, Subtype, std::string())
|
|
||||||
{}
|
|
||||||
|
|
||||||
Bonus::Bonus(BonusDuration::Type Duration, BonusType Type, BonusSource Src, si32 Val, BonusSourceID ID, BonusSubtypeID Subtype, std::string Desc):
|
|
||||||
duration(Duration),
|
duration(Duration),
|
||||||
type(Type),
|
type(Type),
|
||||||
subtype(Subtype),
|
subtype(Subtype),
|
||||||
source(Src),
|
source(Src),
|
||||||
val(Val),
|
val(Val),
|
||||||
sid(ID),
|
sid(ID)
|
||||||
description(std::move(Desc))
|
|
||||||
{
|
{
|
||||||
boost::algorithm::trim(description);
|
|
||||||
targetSourceType = BonusSource::OTHER;
|
targetSourceType = BonusSource::OTHER;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -13,6 +13,7 @@
|
|||||||
#include "BonusCustomTypes.h"
|
#include "BonusCustomTypes.h"
|
||||||
#include "../constants/VariantIdentifier.h"
|
#include "../constants/VariantIdentifier.h"
|
||||||
#include "../constants/EntityIdentifiers.h"
|
#include "../constants/EntityIdentifiers.h"
|
||||||
|
#include "../MetaString.h"
|
||||||
|
|
||||||
VCMI_LIB_NAMESPACE_BEGIN
|
VCMI_LIB_NAMESPACE_BEGIN
|
||||||
|
|
||||||
@@ -77,15 +78,15 @@ struct DLL_LINKAGE Bonus : public std::enable_shared_from_this<Bonus>
|
|||||||
TUpdaterPtr updater;
|
TUpdaterPtr updater;
|
||||||
TUpdaterPtr propagationUpdater;
|
TUpdaterPtr propagationUpdater;
|
||||||
|
|
||||||
std::string 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);
|
||||||
Bonus(BonusDuration::Type Duration, BonusType Type, BonusSource Src, si32 Val, BonusSourceID sourceID, std::string Desc);
|
|
||||||
Bonus(BonusDuration::Type Duration, BonusType Type, BonusSource Src, si32 Val, BonusSourceID sourceID, BonusSubtypeID subtype);
|
Bonus(BonusDuration::Type Duration, BonusType Type, BonusSource Src, si32 Val, BonusSourceID sourceID, BonusSubtypeID subtype);
|
||||||
Bonus(BonusDuration::Type Duration, BonusType Type, BonusSource Src, si32 Val, BonusSourceID sourceID, BonusSubtypeID subtype, std::string Desc);
|
|
||||||
Bonus(BonusDuration::Type Duration, BonusType Type, BonusSource Src, si32 Val, BonusSourceID sourceID, BonusSubtypeID subtype, BonusValueType ValType);
|
Bonus(BonusDuration::Type Duration, BonusType Type, BonusSource Src, si32 Val, BonusSourceID sourceID, BonusSubtypeID subtype, BonusValueType ValType);
|
||||||
Bonus() = default;
|
Bonus() = default;
|
||||||
|
|
||||||
|
public:
|
||||||
|
|
||||||
template <typename Handler> void serialize(Handler &h)
|
template <typename Handler> void serialize(Handler &h)
|
||||||
{
|
{
|
||||||
h & duration;
|
h & duration;
|
||||||
|
|||||||
@@ -625,19 +625,6 @@ std::shared_ptr<Bonus> JsonUtils::parseBonus(const JsonNode &ability)
|
|||||||
return b;
|
return b;
|
||||||
}
|
}
|
||||||
|
|
||||||
std::shared_ptr<Bonus> JsonUtils::parseBuildingBonus(const JsonNode & ability, const FactionID & faction, const BuildingID & building, const std::string & description)
|
|
||||||
{
|
|
||||||
/* duration = BonusDuration::PERMANENT
|
|
||||||
source = BonusSource::TOWN_STRUCTURE
|
|
||||||
bonusType, val, subtype - get from json
|
|
||||||
*/
|
|
||||||
auto b = std::make_shared<Bonus>(BonusDuration::PERMANENT, BonusType::NONE, BonusSource::TOWN_STRUCTURE, 0, BuildingTypeUniqueID(faction, building), description);
|
|
||||||
|
|
||||||
if(!parseBonus(ability, b.get()))
|
|
||||||
return nullptr;
|
|
||||||
return b;
|
|
||||||
}
|
|
||||||
|
|
||||||
bool JsonUtils::parseBonus(const JsonNode &ability, Bonus *b)
|
bool JsonUtils::parseBonus(const JsonNode &ability, Bonus *b)
|
||||||
{
|
{
|
||||||
const JsonNode * value = nullptr;
|
const JsonNode * value = nullptr;
|
||||||
@@ -682,9 +669,9 @@ bool JsonUtils::parseBonus(const JsonNode &ability, Bonus *b)
|
|||||||
if(!ability["description"].isNull())
|
if(!ability["description"].isNull())
|
||||||
{
|
{
|
||||||
if (ability["description"].isString())
|
if (ability["description"].isString())
|
||||||
b->description = ability["description"].String();
|
b->description.appendTextID(ability["description"].String());
|
||||||
if (ability["description"].isNumber())
|
if (ability["description"].isNumber())
|
||||||
b->description = VLC->generaltexth->translate("core.arraytxt", ability["description"].Integer());
|
b->description.appendTextID("core.arraytxt." + std::to_string(ability["description"].Integer()));
|
||||||
}
|
}
|
||||||
|
|
||||||
value = &ability["effectRange"];
|
value = &ability["effectRange"];
|
||||||
|
|||||||
@@ -23,7 +23,6 @@ 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);
|
||||||
std::shared_ptr<Bonus> parseBuildingBonus(const JsonNode & ability, const FactionID & faction, const BuildingID & building, const std::string & description);
|
|
||||||
bool parseBonus(const JsonNode & ability, Bonus * placement);
|
bool parseBonus(const JsonNode & ability, Bonus * placement);
|
||||||
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);
|
||||||
|
|||||||
@@ -101,28 +101,22 @@ void CArmedInstance::updateMoraleBonusFromArmy()
|
|||||||
factionsInArmy -= mixableFactions - 1;
|
factionsInArmy -= mixableFactions - 1;
|
||||||
}
|
}
|
||||||
|
|
||||||
std::string description;
|
MetaString bonusDescription;
|
||||||
|
|
||||||
if(factionsInArmy == 1)
|
if(factionsInArmy == 1)
|
||||||
{
|
{
|
||||||
b->val = +1;
|
b->val = +1;
|
||||||
description = VLC->generaltexth->arraytxt[115]; //All troops of one alignment +1
|
bonusDescription.appendTextID("core.arraytxt.115"); //All troops of one alignment +1
|
||||||
description = description.substr(0, description.size()-3);//trim "+1"
|
|
||||||
}
|
}
|
||||||
else if (!factions.empty()) // no bonus from empty garrison
|
else if (!factions.empty()) // no bonus from empty garrison
|
||||||
{
|
{
|
||||||
b->val = 2 - static_cast<si32>(factionsInArmy);
|
b->val = 2 - static_cast<si32>(factionsInArmy);
|
||||||
MetaString formatter;
|
bonusDescription.appendTextID("core.arraytxt.114"); //Troops of %d alignments %d
|
||||||
formatter.appendTextID("core.arraytxt.114"); //Troops of %d alignments %d
|
bonusDescription.replaceNumber(factionsInArmy);
|
||||||
formatter.replaceNumber(factionsInArmy);
|
bonusDescription.replaceNumber(b->val);
|
||||||
formatter.replaceNumber(b->val);
|
|
||||||
|
|
||||||
description = formatter.toString();
|
|
||||||
description = description.substr(0, description.size()-3);//trim value
|
|
||||||
}
|
}
|
||||||
|
|
||||||
boost::algorithm::trim(description);
|
b->description = bonusDescription;
|
||||||
b->description = description;
|
|
||||||
|
|
||||||
CBonusSystemNode::treeHasChanged();
|
CBonusSystemNode::treeHasChanged();
|
||||||
|
|
||||||
@@ -132,8 +126,8 @@ void CArmedInstance::updateMoraleBonusFromArmy()
|
|||||||
{
|
{
|
||||||
if(!undeadModifier)
|
if(!undeadModifier)
|
||||||
{
|
{
|
||||||
undeadModifier = std::make_shared<Bonus>(BonusDuration::PERMANENT, BonusType::MORALE, BonusSource::ARMY, -1, BonusCustomSource::undeadMoraleDebuff, VLC->generaltexth->arraytxt[116]);
|
undeadModifier = std::make_shared<Bonus>(BonusDuration::PERMANENT, BonusType::MORALE, BonusSource::ARMY, -1, BonusCustomSource::undeadMoraleDebuff);
|
||||||
undeadModifier->description = undeadModifier->description.substr(0, undeadModifier->description.size()-2);//trim value
|
undeadModifier->description.appendTextID("core.arraytxt.116");
|
||||||
addNewBonus(undeadModifier);
|
addNewBonus(undeadModifier);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -225,15 +225,15 @@ void CBank::doVisit(const CGHeroInstance * hero) const
|
|||||||
{
|
{
|
||||||
case Obj::SHIPWRECK:
|
case Obj::SHIPWRECK:
|
||||||
textID = 123;
|
textID = 123;
|
||||||
gbonus.bdescr.appendRawString(VLC->generaltexth->arraytxt[99]);
|
gbonus.bonus.description.appendRawString(VLC->generaltexth->arraytxt[99]);
|
||||||
break;
|
break;
|
||||||
case Obj::DERELICT_SHIP:
|
case Obj::DERELICT_SHIP:
|
||||||
textID = 42;
|
textID = 42;
|
||||||
gbonus.bdescr.appendRawString(VLC->generaltexth->arraytxt[101]);
|
gbonus.bonus.description.appendRawString(VLC->generaltexth->arraytxt[101]);
|
||||||
break;
|
break;
|
||||||
case Obj::CRYPT:
|
case Obj::CRYPT:
|
||||||
textID = 120;
|
textID = 120;
|
||||||
gbonus.bdescr.appendRawString(VLC->generaltexth->arraytxt[98]);
|
gbonus.bonus.description.appendRawString(VLC->generaltexth->arraytxt[98]);
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
cb->giveHeroBonus(&gbonus);
|
cb->giveHeroBonus(&gbonus);
|
||||||
@@ -244,7 +244,8 @@ void CBank::doVisit(const CGHeroInstance * hero) const
|
|||||||
case Obj::PYRAMID:
|
case Obj::PYRAMID:
|
||||||
{
|
{
|
||||||
GiveBonus gb;
|
GiveBonus gb;
|
||||||
gb.bonus = Bonus(BonusDuration::ONE_BATTLE, BonusType::LUCK, BonusSource::OBJECT_INSTANCE, -2, BonusSourceID(id), VLC->generaltexth->arraytxt[70]);
|
gb.bonus = Bonus(BonusDuration::ONE_BATTLE, BonusType::LUCK, BonusSource::OBJECT_INSTANCE, -2, BonusSourceID(id));
|
||||||
|
gb.bonus.description.appendTextID("core.arraytxt.70");
|
||||||
gb.id = hero->id;
|
gb.id = hero->id;
|
||||||
cb->giveHeroBonus(&gb);
|
cb->giveHeroBonus(&gb);
|
||||||
textID = 107;
|
textID = 107;
|
||||||
|
|||||||
@@ -98,27 +98,33 @@ std::string CGTownBuilding::getCustomBonusGreeting(const Bonus & bonus) const
|
|||||||
{
|
{
|
||||||
if(bonus.type == BonusType::TOWN_MAGIC_WELL)
|
if(bonus.type == BonusType::TOWN_MAGIC_WELL)
|
||||||
{
|
{
|
||||||
auto bonusGreeting = std::string(VLC->generaltexth->translate("vcmi.townHall.greetingInTownMagicWell"));
|
MetaString wellGreeting = MetaString::createFromTextID("vcmi.townHall.greetingInTownMagicWell");
|
||||||
auto buildingName = town->getTown()->getSpecialBuilding(bType)->getNameTranslated();
|
|
||||||
boost::algorithm::replace_first(bonusGreeting, "%s", buildingName);
|
wellGreeting.replaceTextID(town->getTown()->getSpecialBuilding(bType)->getNameTextID());
|
||||||
return bonusGreeting;
|
return wellGreeting.toString();
|
||||||
}
|
}
|
||||||
auto bonusGreeting = std::string(VLC->generaltexth->translate("vcmi.townHall.greetingCustomBonus")); //"%s gives you +%d %s%s"
|
|
||||||
std::string param;
|
MetaString greeting = MetaString::createFromTextID("vcmi.townHall.greetingCustomBonus");
|
||||||
|
|
||||||
|
std::string paramTextID;
|
||||||
std::string until;
|
std::string until;
|
||||||
|
|
||||||
if(bonus.type == BonusType::MORALE)
|
if(bonus.type == BonusType::MORALE)
|
||||||
param = VLC->generaltexth->allTexts[384];
|
paramTextID = "core.genrltxt.384"; // Morale
|
||||||
else if(bonus.type == BonusType::LUCK)
|
|
||||||
param = VLC->generaltexth->allTexts[385];
|
|
||||||
|
|
||||||
until = bonus.duration == BonusDuration::ONE_BATTLE
|
if(bonus.type == BonusType::LUCK)
|
||||||
? VLC->generaltexth->translate("vcmi.townHall.greetingCustomUntil")
|
paramTextID = "core.genrltxt.385"; // Luck
|
||||||
: ".";
|
|
||||||
|
|
||||||
boost::format fmt = boost::format(bonusGreeting) % bonus.description % bonus.val % param % until;
|
// greeting.replaceTextID(bonus.descriptionTextID);
|
||||||
std::string greeting = fmt.str();
|
greeting.replaceNumber(bonus.val);
|
||||||
return greeting;
|
greeting.replaceTextID(paramTextID);
|
||||||
|
|
||||||
|
if (bonus.duration == BonusDuration::ONE_BATTLE)
|
||||||
|
greeting.replaceTextID("vcmi.townHall.greetingCustomUntil");
|
||||||
|
else
|
||||||
|
greeting.replaceRawString(".");
|
||||||
|
|
||||||
|
return greeting.toString();
|
||||||
}
|
}
|
||||||
|
|
||||||
COPWBonus::COPWBonus(IGameCallback *cb)
|
COPWBonus::COPWBonus(IGameCallback *cb)
|
||||||
@@ -160,7 +166,7 @@ void COPWBonus::onHeroVisit (const CGHeroInstance * h) const
|
|||||||
if(!h->hasBonusFrom(BonusSource::OBJECT_TYPE, BonusSourceID(Obj(Obj::STABLES)))) //does not stack with advMap Stables
|
if(!h->hasBonusFrom(BonusSource::OBJECT_TYPE, BonusSourceID(Obj(Obj::STABLES)))) //does not stack with advMap Stables
|
||||||
{
|
{
|
||||||
GiveBonus gb;
|
GiveBonus gb;
|
||||||
gb.bonus = Bonus(BonusDuration::ONE_WEEK, BonusType::MOVEMENT, BonusSource::OBJECT_TYPE, 600, BonusSourceID(Obj(Obj::STABLES)), BonusCustomSubtype::heroMovementLand, VLC->generaltexth->arraytxt[100]);
|
gb.bonus = Bonus(BonusDuration::ONE_WEEK, BonusType::MOVEMENT, BonusSource::OBJECT_TYPE, 600, BonusSourceID(Obj(Obj::STABLES)), BonusCustomSubtype::heroMovementLand);
|
||||||
gb.id = heroID;
|
gb.id = heroID;
|
||||||
cb->giveHeroBonus(&gb);
|
cb->giveHeroBonus(&gb);
|
||||||
|
|
||||||
|
|||||||
@@ -1005,30 +1005,26 @@ void GiveBonus::applyGs(CGameState *gs)
|
|||||||
auto b = std::make_shared<Bonus>(bonus);
|
auto b = std::make_shared<Bonus>(bonus);
|
||||||
cbsn->addNewBonus(b);
|
cbsn->addNewBonus(b);
|
||||||
|
|
||||||
std::string &descr = b->description;
|
|
||||||
|
|
||||||
if(!bdescr.empty())
|
if(b->description.empty())
|
||||||
{
|
{
|
||||||
descr = bdescr.toString();
|
if((bonus.type == BonusType::LUCK || bonus.type == BonusType::MORALE)
|
||||||
}
|
|
||||||
else if(!descr.empty())
|
|
||||||
{
|
|
||||||
//use preseet description
|
|
||||||
}
|
|
||||||
else if((bonus.type == BonusType::LUCK || bonus.type == BonusType::MORALE)
|
|
||||||
&& (bonus.source == BonusSource::OBJECT_TYPE || bonus.source == BonusSource::OBJECT_INSTANCE))
|
&& (bonus.source == BonusSource::OBJECT_TYPE || bonus.source == BonusSource::OBJECT_INSTANCE))
|
||||||
{
|
{
|
||||||
//no description, use generic
|
|
||||||
//?could use allways when Type == BonusDuration::Type::ONE_BATTLE
|
//?could use allways when Type == BonusDuration::Type::ONE_BATTLE
|
||||||
descr = VLC->generaltexth->arraytxt[bonus.val > 0 ? 110 : 109]; //+/-%d Temporary until next battle"
|
if (bonus.val > 0)
|
||||||
|
b->description.appendTextID("core.arraytxt.110"); //+%d Temporary until next battle"
|
||||||
|
else
|
||||||
|
b->description.appendTextID("core.arraytxt.109"); //-%d Temporary until next battle"
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
logGlobal->debug("Empty bonus decription. Type=%d", (int) bonus.type);
|
logGlobal->debug("Empty bonus decription. Type=%d", (int) bonus.type);
|
||||||
}
|
}
|
||||||
|
}
|
||||||
// Some of(?) versions of H3 use " %s" here instead of %d. Try to replace both of them
|
// Some of(?) versions of H3 use " %s" here instead of %d. Try to replace both of them
|
||||||
boost::replace_first(descr, "%d", std::to_string(std::abs(bonus.val))); // " +/-%d Temporary until next battle
|
//boost::replace_first(descr, "%d", std::to_string(std::abs(bonus.val))); // " +/-%d Temporary until next battle
|
||||||
boost::replace_first(descr, " %s", boost::str(boost::format(" %+d") % bonus.val)); // " %s" in arraytxt.69, fountian of fortune
|
//boost::replace_first(descr, " %s", boost::str(boost::format(" %+d") % bonus.val)); // " %s" in arraytxt.69, fountian of fortune
|
||||||
}
|
}
|
||||||
|
|
||||||
void ChangeObjPos::applyGs(CGameState *gs)
|
void ChangeObjPos::applyGs(CGameState *gs)
|
||||||
|
|||||||
@@ -382,7 +382,6 @@ struct DLL_LINKAGE GiveBonus : public CPackForClient
|
|||||||
ETarget who = ETarget::OBJECT;
|
ETarget who = ETarget::OBJECT;
|
||||||
VariantIdentifier<ObjectInstanceID, PlayerColor, BattleID> id;
|
VariantIdentifier<ObjectInstanceID, PlayerColor, BattleID> id;
|
||||||
Bonus bonus;
|
Bonus bonus;
|
||||||
MetaString bdescr;
|
|
||||||
|
|
||||||
void visitTyped(ICPackVisitor & visitor) override;
|
void visitTyped(ICPackVisitor & visitor) override;
|
||||||
|
|
||||||
@@ -390,7 +389,6 @@ struct DLL_LINKAGE GiveBonus : public CPackForClient
|
|||||||
{
|
{
|
||||||
h & bonus;
|
h & bonus;
|
||||||
h & id;
|
h & id;
|
||||||
h & bdescr;
|
|
||||||
h & who;
|
h & who;
|
||||||
assert(id.getNum() != -1);
|
assert(id.getNum() != -1);
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -207,8 +207,7 @@ void JsonUpdater::serializeBonuses(const std::string & fieldName, CBonusSystemNo
|
|||||||
&& mask->sid == b->sid
|
&& mask->sid == b->sid
|
||||||
&& mask->valType == b->valType
|
&& mask->valType == b->valType
|
||||||
&& mask->additionalInfo == b->additionalInfo
|
&& mask->additionalInfo == b->additionalInfo
|
||||||
&& mask->effectRange == b->effectRange
|
&& mask->effectRange == b->effectRange;
|
||||||
&& mask->description == b->description;
|
|
||||||
};
|
};
|
||||||
|
|
||||||
value->removeBonuses(selector);
|
value->removeBonuses(selector);
|
||||||
|
|||||||
@@ -32,9 +32,9 @@ BonusCaster::~BonusCaster() = default;
|
|||||||
|
|
||||||
void BonusCaster::getCasterName(MetaString & text) const
|
void BonusCaster::getCasterName(MetaString & text) const
|
||||||
{
|
{
|
||||||
if(!bonus->description.empty())
|
// if(!bonus->descriptionTextID.empty())
|
||||||
text.replaceRawString(bonus->description);
|
// text.replaceTextID(bonus->descriptionTextID);
|
||||||
else
|
// else
|
||||||
actualCaster->getCasterName(text);
|
actualCaster->getCasterName(text);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -33,8 +33,7 @@ bool operator==(const Bonus & b1, const Bonus & b2)
|
|||||||
&& b1.sid == b2.sid
|
&& b1.sid == b2.sid
|
||||||
&& b1.valType == b2.valType
|
&& b1.valType == b2.valType
|
||||||
&& b1.additionalInfo == b2.additionalInfo
|
&& b1.additionalInfo == b2.additionalInfo
|
||||||
&& b1.effectRange == b2.effectRange
|
&& b1.effectRange == b2.effectRange;
|
||||||
&& b1.description == b2.description;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
namespace test
|
namespace test
|
||||||
|
|||||||
Reference in New Issue
Block a user