diff --git a/lib/CTownHandler.cpp b/lib/CTownHandler.cpp index d2a03480b..466031c7d 100644 --- a/lib/CTownHandler.cpp +++ b/lib/CTownHandler.cpp @@ -63,14 +63,19 @@ std::string CBuilding::getDescriptionTranslated() const return VLC->generaltexth->translate(getDescriptionTextID()); } +std::string CBuilding::getBaseTextID() const +{ + return TextIdentifier("building", modScope, town->faction->identifier, identifier).get(); +} + std::string CBuilding::getNameTextID() const { - return TextIdentifier("building", modScope, town->faction->identifier, identifier, "name").get(); + return TextIdentifier(getBaseTextID(), "name").get(); } std::string CBuilding::getDescriptionTextID() const { - return TextIdentifier("building", modScope, town->faction->identifier, identifier, "description").get(); + return TextIdentifier(getBaseTextID(), "description").get(); } BuildingID CBuilding::getBase() const @@ -639,7 +644,7 @@ void CTownHandler::loadBuilding(CTown * town, const std::string & stringID, cons if(source["type"].String() == "configurable" && ret->subId == BuildingSubID::NONE) { ret->subId = BuildingSubID::CUSTOM_VISITING_REWARD; - ret->rewardableObjectInfo.init(source); + ret->rewardableObjectInfo.init(source, ret->getBaseTextID()); } } //MODS COMPATIBILITY FOR 0.96 diff --git a/lib/CTownHandler.h b/lib/CTownHandler.h index 49cdc0c97..3acbf9a70 100644 --- a/lib/CTownHandler.h +++ b/lib/CTownHandler.h @@ -88,6 +88,7 @@ public: std::string getNameTranslated() const; std::string getDescriptionTranslated() const; + std::string getBaseTextID() const; std::string getNameTextID() const; std::string getDescriptionTextID() const; diff --git a/lib/JsonNode.cpp b/lib/JsonNode.cpp index 758c5c0bb..41edb62ab 100644 --- a/lib/JsonNode.cpp +++ b/lib/JsonNode.cpp @@ -460,6 +460,21 @@ const JsonNode & JsonNode::operator[](const std::string & child) const return nullNode; } +JsonNode & JsonNode::operator[](size_t child) +{ + if (child >= Vector().size() ) + Vector().resize(child + 1); + return Vector()[child]; +} + +const JsonNode & JsonNode::operator[](size_t child) const +{ + if (child < Vector().size() ) + return Vector()[child]; + + return nullNode; +} + const JsonNode & JsonNode::resolvePointer(const std::string &jsonPointer) const { return ::resolvePointer(*this, jsonPointer); diff --git a/lib/JsonNode.h b/lib/JsonNode.h index d15ea509b..c1d39991e 100644 --- a/lib/JsonNode.h +++ b/lib/JsonNode.h @@ -129,6 +129,9 @@ public: JsonNode & operator[](const std::string & child); const JsonNode & operator[](const std::string & child) const; + JsonNode & operator[](size_t child); + const JsonNode & operator[](size_t child) const; + std::string toJson(bool compact = false) const; template void serialize(Handler &h, const int version) diff --git a/lib/mapObjectConstructors/AObjectTypeHandler.cpp b/lib/mapObjectConstructors/AObjectTypeHandler.cpp index 424825aef..1c93a6fd7 100644 --- a/lib/mapObjectConstructors/AObjectTypeHandler.cpp +++ b/lib/mapObjectConstructors/AObjectTypeHandler.cpp @@ -133,9 +133,14 @@ bool AObjectTypeHandler::hasNameTextID() const return false; } +std::string AObjectTypeHandler::getBaseTextID() const +{ + return TextIdentifier("mapObject", modScope, typeName, subTypeName).get(); +} + std::string AObjectTypeHandler::getNameTextID() const { - return TextIdentifier("mapObject", modScope, typeName, subTypeName, "name").get(); + return TextIdentifier(getBaseTextID(), "name").get(); } std::string AObjectTypeHandler::getNameTranslated() const diff --git a/lib/mapObjectConstructors/AObjectTypeHandler.h b/lib/mapObjectConstructors/AObjectTypeHandler.h index fae3ad6a7..f6776b0ac 100644 --- a/lib/mapObjectConstructors/AObjectTypeHandler.h +++ b/lib/mapObjectConstructors/AObjectTypeHandler.h @@ -89,6 +89,9 @@ public: /// returns true if this class provides custom text ID's instead of generic per-object name virtual bool hasNameTextID() const; + /// returns base prefix for all translatable strings of this object + std::string getBaseTextID() const; + /// returns object's name in form of translatable text ID virtual std::string getNameTextID() const; diff --git a/lib/mapObjectConstructors/CRewardableConstructor.cpp b/lib/mapObjectConstructors/CRewardableConstructor.cpp index d0fe29ada..8d3bec191 100644 --- a/lib/mapObjectConstructors/CRewardableConstructor.cpp +++ b/lib/mapObjectConstructors/CRewardableConstructor.cpp @@ -18,7 +18,7 @@ VCMI_LIB_NAMESPACE_BEGIN void CRewardableConstructor::initTypeData(const JsonNode & config) { - objectInfo.init(config); + objectInfo.init(config, getBaseTextID()); blockVisit = config["blockedVisitable"].Bool(); if (!config["name"].isNull()) diff --git a/lib/mapObjects/CGTownBuilding.cpp b/lib/mapObjects/CGTownBuilding.cpp index 5da61d7f4..0cccdc62e 100644 --- a/lib/mapObjects/CGTownBuilding.cpp +++ b/lib/mapObjects/CGTownBuilding.cpp @@ -297,7 +297,10 @@ CTownRewardableBuilding::CTownRewardableBuilding(const BuildingID & index, Build void CTownRewardableBuilding::initObj(CRandomGenerator & rand) { assert(town && town->town); - town->town->buildings.at(bID)->rewardableObjectInfo.configureObject(configuration, rand); + + auto building = town->town->buildings.at(bID); + + building->rewardableObjectInfo.configureObject(configuration, rand); for(auto & rewardInfo : configuration.info) { for (auto & bonus : rewardInfo.reward.bonuses) diff --git a/lib/rewardable/Info.cpp b/lib/rewardable/Info.cpp index 8b8b937e6..e68e44ba3 100644 --- a/lib/rewardable/Info.cpp +++ b/lib/rewardable/Info.cpp @@ -10,33 +10,33 @@ #include "StdInc.h" #include "Info.h" + +#include "Configuration.h" #include "Limiter.h" #include "Reward.h" -#include "Configuration.h" -#include "../CCreatureSet.h" -#include "../CRandomGenerator.h" -#include "../StringConstants.h" -#include "../CCreatureHandler.h" -#include "../CModHandler.h" -#include "../NetPacksBase.h" -#include "../JsonRandom.h" -#include "../IGameCallback.h" #include "../CGeneralTextHandler.h" -#include "../JsonNode.h" +#include "../CModHandler.h" #include "../IGameCallback.h" +#include "../JsonRandom.h" #include "../mapObjects/IObjectInterface.h" VCMI_LIB_NAMESPACE_BEGIN namespace { - MetaString loadMessage(const JsonNode & value) + MetaString loadMessage(const JsonNode & value, const TextIdentifier & textIdentifier ) { MetaString ret; if (value.isNumber()) + { ret.appendLocalString(EMetaText::ADVOB_TXT, static_cast(value.Float())); - else - ret.appendRawString(value.String()); + return ret; + } + + if (value.String().empty()) + return ret; + + ret.appendTextID(textIdentifier.get()); return ret; } @@ -51,9 +51,38 @@ namespace { } } -void Rewardable::Info::init(const JsonNode & objectConfig) +void Rewardable::Info::init(const JsonNode & objectConfig, const std::string & objectName) { + objectTextID = objectName; + + auto loadString = [&](const JsonNode & entry, const TextIdentifier & textID){ + if (entry.isString() && !entry.String().empty()) + VLC->generaltexth->registerString(entry.meta, textID, entry.String()); + }; + parameters = objectConfig; + + for(size_t i = 0; i < parameters["rewards"].Vector().size(); ++i) + { + const JsonNode message = parameters["rewards"][i]["message"]; + loadString(message, TextIdentifier(objectName, "rewards", i)); + } + + for(size_t i = 0; i < parameters["onVisited"].Vector().size(); ++i) + { + const JsonNode message = parameters["onVisited"][i]["message"]; + loadString(message, TextIdentifier(objectName, "onVisited", i)); + } + + for(size_t i = 0; i < parameters["onEmpty"].Vector().size(); ++i) + { + const JsonNode message = parameters["onEmpty"][i]["message"]; + loadString(message, TextIdentifier(objectName, "onEmpty", i)); + } + + loadString(parameters["onSelectMessage"], TextIdentifier(objectName, "onSelect")); + loadString(parameters["onVisitedMessage"], TextIdentifier(objectName, "onVisited")); + loadString(parameters["onEmptyMessage"], TextIdentifier(objectName, "onEmpty")); } Rewardable::LimitersList Rewardable::Info::configureSublimiters(Rewardable::Configuration & object, CRandomGenerator & rng, const JsonNode & source) const @@ -157,10 +186,13 @@ void Rewardable::Info::configureRewards( CRandomGenerator & rng, const JsonNode & source, std::map & thrownDice, - Rewardable::EEventType event ) const + Rewardable::EEventType event, + const std::string & modeName) const { - for (const JsonNode & reward : source.Vector()) + for(size_t i = 0; i < source.Vector().size(); ++i) { + const JsonNode reward = source.Vector()[i]; + if (!reward["appearChance"].isNull()) { JsonNode chance = reward["appearChance"]; @@ -188,7 +220,7 @@ void Rewardable::Info::configureRewards( configureReward(object, rng, info.reward, reward); info.visitType = event; - info.message = loadMessage(reward["message"]); + info.message = loadMessage(reward["message"], TextIdentifier(objectTextID, modeName, i)); for (const auto & artifact : info.reward.artifacts ) info.message.replaceLocalString(EMetaText::ART_NAMES, artifact.getNum()); @@ -206,17 +238,17 @@ void Rewardable::Info::configureObject(Rewardable::Configuration & object, CRand std::map thrownDice; - configureRewards(object, rng, parameters["rewards"], thrownDice, Rewardable::EEventType::EVENT_FIRST_VISIT); - configureRewards(object, rng, parameters["onVisited"], thrownDice, Rewardable::EEventType::EVENT_ALREADY_VISITED); - configureRewards(object, rng, parameters["onEmpty"], thrownDice, Rewardable::EEventType::EVENT_NOT_AVAILABLE); + configureRewards(object, rng, parameters["rewards"], thrownDice, Rewardable::EEventType::EVENT_FIRST_VISIT, "rewards"); + configureRewards(object, rng, parameters["onVisited"], thrownDice, Rewardable::EEventType::EVENT_ALREADY_VISITED, "onVisited"); + configureRewards(object, rng, parameters["onEmpty"], thrownDice, Rewardable::EEventType::EVENT_NOT_AVAILABLE, "onEmpty"); - object.onSelect = loadMessage(parameters["onSelectMessage"]); + object.onSelect = loadMessage(parameters["onSelectMessage"], TextIdentifier(objectTextID, "onSelect")); if (!parameters["onVisitedMessage"].isNull()) { Rewardable::VisitInfo onVisited; onVisited.visitType = Rewardable::EEventType::EVENT_ALREADY_VISITED; - onVisited.message = loadMessage(parameters["onVisitedMessage"]); + onVisited.message = loadMessage(parameters["onVisitedMessage"], TextIdentifier(objectTextID, "onVisited")); object.info.push_back(onVisited); } @@ -224,7 +256,7 @@ void Rewardable::Info::configureObject(Rewardable::Configuration & object, CRand { Rewardable::VisitInfo onEmpty; onEmpty.visitType = Rewardable::EEventType::EVENT_NOT_AVAILABLE; - onEmpty.message = loadMessage(parameters["onEmptyMessage"]); + onEmpty.message = loadMessage(parameters["onEmptyMessage"], TextIdentifier(objectTextID, "onEmpty")); object.info.push_back(onEmpty); } diff --git a/lib/rewardable/Info.h b/lib/rewardable/Info.h index ff0d7fea5..c9c826fae 100644 --- a/lib/rewardable/Info.h +++ b/lib/rewardable/Info.h @@ -30,8 +30,9 @@ enum class EEventType; class DLL_LINKAGE Info : public IObjectInfo { JsonNode parameters; + std::string objectTextID; - void configureRewards(Rewardable::Configuration & object, CRandomGenerator & rng, const JsonNode & source, std::map & thrownDice, Rewardable::EEventType mode) const; + void configureRewards(Rewardable::Configuration & object, CRandomGenerator & rng, const JsonNode & source, std::map & thrownDice, Rewardable::EEventType mode, const std::string & textPrefix) const; void configureLimiter(Rewardable::Configuration & object, CRandomGenerator & rng, Rewardable::Limiter & limiter, const JsonNode & source) const; Rewardable::LimitersList configureSublimiters(Rewardable::Configuration & object, CRandomGenerator & rng, const JsonNode & source) const; @@ -58,7 +59,7 @@ public: void configureObject(Rewardable::Configuration & object, CRandomGenerator & rng) const; - void init(const JsonNode & objectConfig); + void init(const JsonNode & objectConfig, const std::string & objectTextID); template void serialize(Handler &h, const int version) {