Pārlūkot izejas kodu

Preparation for user-defined bonus types

Ivan Savenko 4 mēneši atpakaļ
vecāks
revīzija
51832c4fb9

+ 35 - 14
lib/CBonusTypeHandler.cpp

@@ -45,14 +45,19 @@ CBonusTypeHandler::CBonusTypeHandler()
 {
 	//register predefined bonus types
 
-	#define BONUS_NAME(x) \
+#define BONUS_NAME(x) { #x },
+	bonusNames = {
+		BONUS_LIST
+	};
+#undef BONUS_NAME
+
+#define BONUS_NAME(x) \
 	do { \
 		bonusTypes.push_back(CBonusType()); \
 	} while(0);
 
-
 	BONUS_LIST;
-	#undef BONUS_NAME
+#undef BONUS_NAME
 }
 
 CBonusTypeHandler::~CBonusTypeHandler() = default;
@@ -117,19 +122,12 @@ std::vector<JsonNode> CBonusTypeHandler::loadLegacyData()
 
 void CBonusTypeHandler::loadObject(std::string scope, std::string name, const JsonNode & data)
 {
-	auto it = bonusNameMap.find(name);
+	BonusType bonus = stringToBonus(name);
 
-	if(it == bonusNameMap.end())
-	{
-		logBonus->warn("Unrecognized bonus name! (%s)", name);
-	}
-	else
-	{
-		CBonusType & bt = bonusTypes[vstd::to_underlying(it->second)];
+	CBonusType & bt = bonusTypes[vstd::to_underlying(bonus)];
 
-		loadItem(data, bt, name);
-		logBonus->trace("Loaded bonus type %s", name);
-	}
+	loadItem(data, bt, name);
+	logBonus->trace("Loaded bonus type %s", name);
 }
 
 void CBonusTypeHandler::loadObject(std::string scope, std::string name, const JsonNode & data, size_t index)
@@ -185,4 +183,27 @@ void CBonusTypeHandler::loadItem(const JsonNode & source, CBonusType & dest, con
 	}
 }
 
+BonusType CBonusTypeHandler::stringToBonus(const std::string & name) const
+{
+	auto it	= boost::range::find(bonusNames, name);
+
+	if (it != bonusNames.end())
+		return static_cast<BonusType>(it - bonusNames.begin());
+	return BonusType::NONE;
+}
+
+const std::string CBonusTypeHandler::bonusToString(BonusType bonus) const
+{
+	return bonusNames.at(static_cast<int>(bonus));
+}
+
+std::vector<BonusType> CBonusTypeHandler::getAllObjets() const
+{
+	std::vector<BonusType> ret;
+	for (int i = 0; i < bonusNames.size(); ++i)
+		ret.push_back(static_cast<BonusType>(i));
+
+	return ret;
+}
+
 VCMI_LIB_NAMESPACE_END

+ 5 - 0
lib/CBonusTypeHandler.h

@@ -41,6 +41,7 @@ private:
 
 class DLL_LINKAGE CBonusTypeHandler : public IBonusTypeHandler
 {
+	std::vector<std::string> bonusNames;
 public:
 	CBonusTypeHandler();
 	virtual ~CBonusTypeHandler();
@@ -52,6 +53,10 @@ public:
 	void loadObject(std::string scope, std::string name, const JsonNode & data) override;
 	void loadObject(std::string scope, std::string name, const JsonNode & data, size_t index) override;
 
+	BonusType stringToBonus(const std::string & name) const;
+	const std::string bonusToString(BonusType bonus) const;
+
+	std::vector<BonusType> getAllObjets() const;
 private:
 	void loadItem(const JsonNode & source, CBonusType & dest, const std::string & name) const;
 

+ 3 - 4
lib/bonuses/Bonus.cpp

@@ -14,6 +14,7 @@
 #include "Updaters.h"
 #include "Propagators.h"
 
+#include "../CBonusTypeHandler.h"
 #include "../CCreatureHandler.h"
 #include "../CCreatureSet.h"
 #include "../CSkillHandler.h"
@@ -172,7 +173,7 @@ JsonNode Bonus::toJsonNode() const
 {
 	JsonNode root;
 	// only add values that might reasonably be found in config files
-	root["type"].String() = vstd::findKey(bonusNameMap, type);
+	root["type"].String() = LIBRARY->bth->bonusToString(type);
 	if(subtype != BonusSubtypeID())
 		root["subtype"].String() = subtype.toString();
 	if(additionalInfo != CAddInfo::NONE)
@@ -243,9 +244,7 @@ std::shared_ptr<Bonus> Bonus::addPropagator(const TPropagatorPtr & Propagator)
 
 DLL_LINKAGE std::ostream & operator<<(std::ostream &out, const Bonus &bonus)
 {
-	for(const auto & i : bonusNameMap)
-	if(i.second == bonus.type)
-		out << "\tType: " << i.first << " \t";
+	out << "\tType: " << LIBRARY->bth->bonusToString(bonus.type) << " \t";
 
 #define printField(field) out << "\t" #field ": " << (int)bonus.field << "\n"
 	printField(val);

+ 1 - 2
lib/bonuses/Bonus.h

@@ -65,9 +65,8 @@ struct DLL_LINKAGE Bonus : public std::enable_shared_from_this<Bonus>, public Se
 	BonusValueType valType = BonusValueType::ADDITIVE_VALUE; // 1 byte
 	BonusSource source = BonusSource::OTHER; //source type" uses BonusSource values - what gave that bonus - 1 byte
 	BonusSource targetSourceType = BonusSource::OTHER;//Bonuses of what origin this amplifies, uses BonusSource values. Needed for PERCENT_TO_TARGET_TYPE. - 1 byte
-	BonusType type = BonusType::NONE; //uses BonusType values - says to what is this bonus - 1 byte
 	BonusLimitEffect effectRange = BonusLimitEffect::NO_LIMIT; // 1 byte
-	// 1 bytes padding
+	BonusType type = BonusType::NONE; //uses BonusType values - says to what is this bonus - 2 bytes
 
 	BonusSubtypeID subtype;
 	BonusSourceID sid; //source id: id of object/artifact/spell

+ 0 - 6
lib/bonuses/BonusEnum.cpp

@@ -14,12 +14,6 @@
 
 VCMI_LIB_NAMESPACE_BEGIN
 
-#define BONUS_NAME(x) { #x, BonusType::x },
-	const std::map<std::string, BonusType> bonusNameMap = {
-		BONUS_LIST
-	};
-#undef BONUS_NAME
-
 #define BONUS_VALUE(x) { #x, BonusValueType::x },
 	const std::map<std::string, BonusValueType> bonusValueMap = { BONUS_VALUE_LIST };
 #undef BONUS_VALUE

+ 2 - 2
lib/bonuses/BonusEnum.h

@@ -224,11 +224,12 @@ class JsonNode;
 	BONUS_VALUE(INDEPENDENT_MIN) //used for SECONDARY_SKILL_PREMY bonus
 
 
-enum class BonusType : uint8_t
+enum class BonusType : uint16_t
 {
 #define BONUS_NAME(x) x,
     BONUS_LIST
 #undef BONUS_NAME
+    BUILTIN_BONUSES_COUNT
 };
 namespace BonusDuration  //when bonus is automatically removed
 {
@@ -273,7 +274,6 @@ enum class BonusValueType : uint8_t
 #undef BONUS_VALUE
 };
 
-extern DLL_LINKAGE const std::map<std::string, BonusType> bonusNameMap;
 extern DLL_LINKAGE const std::map<std::string, BonusValueType> bonusValueMap;
 extern DLL_LINKAGE const std::map<std::string, BonusSource> bonusSourceMap;
 extern DLL_LINKAGE const std::map<std::string, BonusDuration::Type> bonusDurationMap;

+ 3 - 2
lib/bonuses/Limiters.cpp

@@ -12,6 +12,7 @@
 #include "Limiters.h"
 #include "Updaters.h"
 
+#include "../CBonusTypeHandler.h"
 #include "../GameLibrary.h"
 #include "../entities/faction/CFaction.h"
 #include "../entities/faction/CTownHandler.h"
@@ -189,7 +190,7 @@ ILimiter::EDecision HasAnotherBonusLimiter::limit(const BonusLimitationContext &
 
 std::string HasAnotherBonusLimiter::toString() const
 {
-	std::string typeName = vstd::findKey(bonusNameMap, type);
+	std::string typeName = LIBRARY->bth->bonusToString(type);
 	if(isSubtypeRelevant)
 	{
 		boost::format fmt("HasAnotherBonusLimiter(type=%s, subtype=%s)");
@@ -207,7 +208,7 @@ std::string HasAnotherBonusLimiter::toString() const
 JsonNode HasAnotherBonusLimiter::toJsonNode() const
 {
 	JsonNode root;
-	std::string typeName = vstd::findKey(bonusNameMap, type);
+	std::string typeName = LIBRARY->bth->bonusToString(type);
 	auto sourceTypeName = vstd::findKey(bonusSourceMap, source);
 
 	root["type"].String() = "HAS_ANOTHER_BONUS_LIMITER";

+ 2 - 15
lib/bonuses/Updaters.h

@@ -78,12 +78,8 @@ public:
 class DLL_LINKAGE TimesStackLevelUpdater : public IUpdater
 {
 	std::shared_ptr<Bonus> apply(const std::shared_ptr<Bonus> & b, int level) const;
-public:
-	template <typename Handler> void serialize(Handler & h)
-	{
-		h & static_cast<IUpdater &>(*this);
-	}
 
+public:
 	std::shared_ptr<Bonus> createUpdatedBonus(const std::shared_ptr<Bonus> & b, const CBonusSystemNode & context) const override;
 	std::string toString() const override;
 	JsonNode toJsonNode() const override;
@@ -92,12 +88,8 @@ public:
 class DLL_LINKAGE DivideStackLevelUpdater : public IUpdater
 {
 	std::shared_ptr<Bonus> apply(const std::shared_ptr<Bonus> & b, int level) const;
-public:
-	template <typename Handler> void serialize(Handler & h)
-	{
-		h & static_cast<IUpdater &>(*this);
-	}
 
+public:
 	std::shared_ptr<Bonus> createUpdatedBonus(const std::shared_ptr<Bonus> & b, const CBonusSystemNode & context) const override;
 	std::string toString() const override;
 	JsonNode toJsonNode() const override;
@@ -125,11 +117,6 @@ public:
 class DLL_LINKAGE OwnerUpdater : public IUpdater
 {
 public:
-	template <typename Handler> void serialize(Handler& h)
-	{
-		h & static_cast<IUpdater &>(*this);
-	}
-
 	std::shared_ptr<Bonus> createUpdatedBonus(const std::shared_ptr<Bonus>& b, const CBonusSystemNode& context) const override;
 	std::string toString() const override;
 	JsonNode toJsonNode() const override;

+ 9 - 38
lib/json/JsonBonus.cpp

@@ -9,6 +9,7 @@
  */
 
 #include "StdInc.h"
+#include "CBonusTypeHandler.h"
 #include "JsonBonus.h"
 
 #include "JsonValidator.h"
@@ -184,10 +185,10 @@ static void loadBonusSubtype(BonusSubtypeID & subtype, BonusType type, const Jso
 			break;
 		}
 		default:
-			for(const auto & i : bonusNameMap)
-				if(i.second == type)
-					logMod->warn("Bonus type %s does not supports subtypes!", i.first );
+		{
+			logMod->warn("Bonus type %s does not supports subtypes!", LIBRARY->bth->bonusToString(type));
 			subtype =  BonusSubtypeID();
+		}
 	}
 }
 
@@ -258,10 +259,7 @@ static void loadBonusAddInfo(CAddInfo & var, BonusType type, const JsonNode & no
 			}
 			break;
 		default:
-			for(const auto & i : bonusNameMap)
-				if(i.second == type)
-					logMod->warn("Bonus type %s does not supports addInfo!", i.first );
-
+			logMod->warn("Bonus type %s does not supports addInfo!", LIBRARY->bth->bonusToString(type) );
 	}
 }
 
@@ -414,14 +412,8 @@ std::shared_ptr<Bonus> JsonUtils::parseBonus(const JsonVector & ability_vec)
 {
 	auto b = std::make_shared<Bonus>();
 	std::string type = ability_vec[0].String();
-	auto it = bonusNameMap.find(type);
-	if (it == bonusNameMap.end())
-	{
-		logMod->error("Error: invalid ability type %s.", type);
-		return b;
-	}
-	b->type = it->second;
 
+	b->type = LIBRARY->bth->stringToBonus(type);
 	b->val = static_cast<si32>(ability_vec[1].Float());
 	loadBonusSubtype(b->subtype, b->type, ability_vec[2]);
 	b->additionalInfo = static_cast<si32>(ability_vec[3].Float());
@@ -505,15 +497,7 @@ std::shared_ptr<const ILimiter> JsonUtils::parseLimiter(const JsonNode & limiter
 				if (!parameters[0].isNull())
 				{
 					std::string anotherBonusType = parameters[0].String();
-					auto it = bonusNameMap.find(anotherBonusType);
-					if(it != bonusNameMap.end())
-					{
-						bonusLimiter->type = it->second;
-					}
-					else
-					{
-						logMod->error("Error: invalid ability type %s.", anotherBonusType);
-					}
+					bonusLimiter->type = LIBRARY->bth->stringToBonus(anotherBonusType);
 				}
 
 				auto findSource = [&](const JsonNode & parameter)
@@ -627,15 +611,7 @@ bool JsonUtils::parseBonus(const JsonNode &ability, Bonus *b, const TextIdentifi
 {
 	const JsonNode * value = nullptr;
 
-	std::string type = ability["type"].String();
-	auto it = bonusNameMap.find(type);
-	if (it == bonusNameMap.end())
-	{
-		logMod->error("Error: invalid ability type %s.", type);
-		return false;
-	}
-	else
-		b->type = it->second;
+	b->type = LIBRARY->bth->stringToBonus(ability["type"].String());
 
 	loadBonusSubtype(b->subtype, b->type, ability["subtype"]);
 
@@ -771,12 +747,7 @@ CSelector JsonUtils::parseSelector(const JsonNode & ability)
 	value = &ability["type"];
 	if(value->isString())
 	{
-		auto it = bonusNameMap.find(value->String());
-		if(it != bonusNameMap.end())
-		{
-			type = it->second;
-			ret = ret.And(Selector::type()(it->second));
-		}
+		ret = ret.And(Selector::type()(LIBRARY->bth->stringToBonus(value->String())));
 	}
 	value = &ability["subtype"];
 	if(!value->isNull() && type != BonusType::NONE)

+ 4 - 28
lib/spells/CSpellHandler.cpp

@@ -12,6 +12,7 @@
 
 #include <cctype>
 
+#include "CBonusTypeHandler.h"
 #include "CSpellHandler.h"
 #include "Problem.h"
 
@@ -473,26 +474,14 @@ JsonNode CSpell::convertTargetCondition(const BTVector & immunity, const BTVecto
 	static const std::string CONDITION_NORMAL = "normal";
 	static const std::string CONDITION_ABSOLUTE = "absolute";
 
-#define BONUS_NAME(x) { BonusType::x, #x },
-	static const std::map<BonusType, std::string> bonusNameRMap = { BONUS_LIST };
-#undef BONUS_NAME
-
 	JsonNode res;
 
 	auto convertVector = [&](const std::string & targetName, const BTVector & source, const std::string & value)
 	{
 		for(auto bonusType : source)
 		{
-			auto iter = bonusNameRMap.find(bonusType);
-			if(iter != bonusNameRMap.end())
-			{
-				auto fullId = ModUtility::makeFullIdentifier("", "bonus", iter->second);
-				res[targetName][fullId].String() = value;
-			}
-			else
-			{
-				logGlobal->error("Invalid bonus type %d", static_cast<int32_t>(bonusType));
-			}
+			std::string bonusName = LIBRARY->bth->bonusToString(bonusType);
+			res[targetName][bonusName].String() = value;
 		}
 	};
 
@@ -886,19 +875,6 @@ std::shared_ptr<CSpell> CSpellHandler::loadFromJson(const std::string & scope, c
 
 	spell->onlyOnWaterMap = json["onlyOnWaterMap"].Bool();
 
-	auto findBonus = [&](const std::string & name, std::vector<BonusType> & vec)
-	{
-		auto it = bonusNameMap.find(name);
-		if(it == bonusNameMap.end())
-		{
-			logMod->error("Spell %s: invalid bonus name %s", spell->getNameTranslated(), name);
-		}
-		else
-		{
-			vec.push_back(static_cast<BonusType>(it->second));
-		}
-	};
-
 	auto readBonusStruct = [&](const std::string & name, std::vector<BonusType> & vec)
 	{
 		for(auto bonusData: json[name].Struct())
@@ -907,7 +883,7 @@ std::shared_ptr<CSpell> CSpellHandler::loadFromJson(const std::string & scope, c
 			const bool flag = bonusData.second.Bool();
 
 			if(flag)
-				findBonus(bonusId, vec);
+				vec.push_back(LIBRARY->bth->stringToBonus(bonusId));
 		}
 	};
 

+ 1 - 6
lib/spells/TargetCondition.cpp

@@ -355,12 +355,7 @@ public:
 	{
 		if(type == "bonus")
 		{
-			//TODO: support custom bonus types
-			auto it = bonusNameMap.find(identifier);
-			if(it != bonusNameMap.end())
-				return std::make_shared<SelectorCondition>(Selector::type()(it->second));
-
-			logMod->error("Invalid bonus type %s in spell target condition.", identifier);
+			return std::make_shared<SelectorCondition>(Selector::type()(LIBRARY->bth->stringToBonus(identifier)));
 		}
 		else if(type == "creature")
 		{

+ 7 - 5
mapeditor/inspector/rewardswidget.cpp

@@ -8,6 +8,7 @@
  *
  */
 #include "StdInc.h"
+#include "CBonusTypeHandler.h"
 #include "rewardswidget.h"
 #include "ui_rewardswidget.h"
 #include "../lib/GameLibrary.h"
@@ -183,8 +184,8 @@ RewardsWidget::RewardsWidget(CMap & m, CRewardableObject & p, QWidget *parent) :
 	//fill bonuses
 	for(auto & s : bonusDurationMap)
 		ui->bonusDuration->addItem(QString::fromStdString(s.first));
-	for(auto & s : bonusNameMap)
-		ui->bonusType->addItem(QString::fromStdString(s.first));
+	for(auto & s : LIBRARY->bth->getAllObjets())
+		ui->bonusType->addItem(QString::fromStdString(LIBRARY->bth->bonusToString(s)));
 	
 	//set default values
 	if(dynamic_cast<CGPandoraBox*>(&object))
@@ -340,7 +341,7 @@ void RewardsWidget::saveCurrentVisitInfo(int index)
 	for(int i = 0; i < ui->bonuses->rowCount(); ++i)
 	{
 		auto dur = bonusDurationMap.at(ui->bonuses->item(i, 0)->text().toStdString());
-		auto typ = bonusNameMap.at(ui->bonuses->item(i, 1)->text().toStdString());
+		auto typ = LIBRARY->bth->stringToBonus(ui->bonuses->item(i, 1)->text().toStdString());
 		auto val = ui->bonuses->item(i, 2)->data(Qt::UserRole).toInt();
 		vinfo.reward.heroBonuses.emplace_back(dur, typ, BonusSource::OBJECT_INSTANCE, val, BonusSourceID(object.id));
 	}
@@ -490,7 +491,7 @@ void RewardsWidget::loadCurrentVisitInfo(int index)
 			}
 		}
 		
-		auto typ = vstd::findKey(bonusNameMap, i.type);
+		std::string typ = LIBRARY->bth->bonusToString(i.type);
 		for(int i = 0; i < ui->bonusType->count(); ++i)
 		{
 			if(ui->bonusType->itemText(i) == QString::fromStdString(typ))
@@ -816,7 +817,8 @@ void RewardsDelegate::updateModelData(QAbstractItemModel * model, const QModelIn
 		QStringList bonusesList;
 		for (auto & bonus : vinfo.reward.heroBonuses)
 		{
-			bonusesList += QString("%1 %2 (%3)").arg(QString::fromStdString(vstd::findKey(bonusDurationMap, bonus.duration))).arg(QString::fromStdString(vstd::findKey(bonusNameMap, bonus.type))).arg(bonus.val);
+			std::string bonusName = LIBRARY->bth->bonusToString(bonus.type);
+			bonusesList += QString("%1 %2 (%3)").arg(QString::fromStdString(vstd::findKey(bonusDurationMap, bonus.duration))).arg(QString::fromStdString(bonusName)).arg(bonus.val);
 		}
 		textList += QObject::tr("Bonuses: %1").arg(bonusesList.join(", "));
 	}

+ 0 - 1
scripting/lua/api/BonusSystem.cpp

@@ -187,7 +187,6 @@ static void publishMap(lua_State * L, const std::map<T , std::bitset<N>> & map)
 
 void BonusProxy::adjustStaticTable(lua_State * L) const
 {
-	publishMap(L, bonusNameMap);
 	publishMap(L, bonusValueMap);
 	publishMap(L, bonusSourceMap);
 	publishMap(L, bonusDurationMap);