Browse Source

Seerhut works as rewardable object

nordsoft 2 years ago
parent
commit
06f01c3b82

+ 11 - 0
lib/MetaString.cpp

@@ -19,6 +19,7 @@
 #include "VCMI_Lib.h"
 #include "mapObjectConstructors/CObjectClassesHandler.h"
 #include "spells/CSpellHandler.h"
+#include "serializer/JsonSerializeFormat.h"
 
 VCMI_LIB_NAMESPACE_BEGIN
 
@@ -385,4 +386,14 @@ void MetaString::jsonDeserialize(const JsonNode & source)
 		numbers.push_back(entry.Integer());
 }
 
+void MetaString::serializeJson(JsonSerializeFormat & handler)
+{
+	JsonNode attr;
+	if(handler.saving)
+		jsonSerialize(attr);
+	handler.serializeRaw("attributes", attr, std::nullopt);
+	if(!handler.saving)
+		jsonDeserialize(attr);
+}
+
 VCMI_LIB_NAMESPACE_END

+ 3 - 0
lib/MetaString.h

@@ -14,6 +14,7 @@ VCMI_LIB_NAMESPACE_BEGIN
 class JsonNode;
 class CreatureID;
 class CStackBasicDescriptor;
+class JsonSerializeFormat;
 using TQuantity = si32;
 
 /// Strings classes that can be used as replacement in MetaString
@@ -113,6 +114,8 @@ public:
 
 	void jsonSerialize(JsonNode & dest) const;
 	void jsonDeserialize(const JsonNode & dest);
+	
+	void serializeJson(JsonSerializeFormat & handler);
 
 	template <typename Handler> void serialize(Handler & h, const int version)
 	{

+ 12 - 19
lib/mapObjects/CQuest.cpp

@@ -802,35 +802,28 @@ void CGSeerHut::serializeJsonOptions(JsonSerializeFormat & handler)
 	}
 	else
 	{
+		if(handler.getCurrent()["reward"].isNull() || handler.getCurrent()["reward"].Struct().empty())
+		{
+			CRewardableObject::serializeJsonOptions(handler);
+			return;
+		}
+		
+		//backward compatibility
 		auto s = handler.enterStruct("reward");
+		const JsonNode & rewardsJson = handler.getCurrent();
+		
 		std::string fullIdentifier;
 		std::string metaTypeName;
 		std::string scope;
 		std::string identifier;
-		
-		const JsonNode & rewardsJson = handler.getCurrent();
 
-		fullIdentifier.clear();
-
-		if(rewardsJson.Struct().empty())
-		{
-			CRewardableObject::serializeJsonOptions(handler);
-			return;
-		}
-		else
-		{
-			auto iter = rewardsJson.Struct().begin();
-			fullIdentifier = iter->first;
-		}
+		auto iter = rewardsJson.Struct().begin();
+		fullIdentifier = iter->first;
 
 		ModUtility::parseIdentifier(fullIdentifier, scope, metaTypeName, identifier);
 		if(!std::set<std::string>{"resource", "primarySkill", "secondarySkill", "artifact", "spell", "creature", "experience", "mana", "morale", "luck"}.count(metaTypeName))
-		{
-			CRewardableObject::serializeJsonOptions(handler);
 			return;
-		}
-		
-		//backward compatibility
+
 		int val = 0;
 		handler.serializeInt(fullIdentifier, val);
 		

+ 3 - 1
lib/mapObjects/CRewardableObject.cpp

@@ -17,6 +17,7 @@
 #include "../NetPacks.h"
 #include "../mapObjectConstructors/AObjectTypeHandler.h"
 #include "../mapObjectConstructors/CObjectClassesHandler.h"
+#include "../serializer/JsonSerializeFormat.h"
 
 VCMI_LIB_NAMESPACE_BEGIN
 
@@ -278,7 +279,8 @@ CRewardableObject::CRewardableObject()
 
 void CRewardableObject::serializeJsonOptions(JsonSerializeFormat & handler)
 {
-	
+	CArmedInstance::serializeJsonOptions(handler);
+	handler.serializeStruct("rewardable", static_cast<Rewardable::Interface&>(*this));
 }
 
 VCMI_LIB_NAMESPACE_END

+ 27 - 0
lib/rewardable/Configuration.cpp

@@ -10,6 +10,7 @@
 
 #include "StdInc.h"
 #include "Configuration.h"
+#include "../serializer/JsonSerializeFormat.h"
 
 VCMI_LIB_NAMESPACE_BEGIN
 
@@ -23,4 +24,30 @@ ui16 Rewardable::Configuration::getResetDuration() const
 	return resetParameters.period;
 }
 
+void Rewardable::ResetInfo::serializeJson(JsonSerializeFormat & handler)
+{
+	handler.serializeInt("period", period);
+	handler.serializeBool("visitors", visitors);
+	handler.serializeBool("rewards", rewards);
+}
+
+void Rewardable::VisitInfo::serializeJson(JsonSerializeFormat & handler)
+{
+	handler.serializeStruct("limiter", limiter);
+	handler.serializeStruct("reward", reward);
+	handler.serializeStruct("message", message);
+	handler.serializeInt("visitType", visitType);
+}
+
+void Rewardable::Configuration::serializeJson(JsonSerializeFormat & handler)
+{
+	handler.serializeStruct("onSelect", onSelect);
+	handler.enterArray("info").serializeStruct(info);
+	handler.serializeEnum("selectMode", selectMode, std::vector<std::string>{SelectModeString.begin(), SelectModeString.end()});
+	handler.serializeEnum("visitMode", visitMode, std::vector<std::string>{VisitModeString.begin(), VisitModeString.end()});
+	handler.serializeStruct("resetParameters", resetParameters);
+	handler.serializeBool("canRefuse", canRefuse);
+	handler.serializeInt("infoWindowType", infoWindowType);
+}
+
 VCMI_LIB_NAMESPACE_END

+ 7 - 1
lib/rewardable/Configuration.h

@@ -65,7 +65,9 @@ struct DLL_LINKAGE ResetInfo
 
 	/// if true - re-randomize rewards on a new week
 	bool rewards;
-
+	
+	void serializeJson(JsonSerializeFormat & handler);
+	
 	template <typename Handler> void serialize(Handler &h, const int version)
 	{
 		h & period;
@@ -84,6 +86,8 @@ struct DLL_LINKAGE VisitInfo
 
 	/// Event to which this reward is assigned
 	EEventType visitType;
+	
+	void serializeJson(JsonSerializeFormat & handler);
 
 	template <typename Handler> void serialize(Handler &h, const int version)
 	{
@@ -121,6 +125,8 @@ struct DLL_LINKAGE Configuration
 	EVisitMode getVisitMode() const;
 	ui16 getResetDuration() const;
 	
+	void serializeJson(JsonSerializeFormat & handler);
+	
 	template <typename Handler> void serialize(Handler &h, const int version)
 	{
 		h & info;

+ 5 - 0
lib/rewardable/Interface.cpp

@@ -147,4 +147,9 @@ void Rewardable::Interface::grantRewardAfterLevelup(IGameCallback * cb, const Re
 			cb->removeAfterVisit(instance);
 }
 
+void Rewardable::Interface::serializeJson(JsonSerializeFormat & handler)
+{
+	configuration.serializeJson(handler);
+}
+
 VCMI_LIB_NAMESPACE_END

+ 2 - 0
lib/rewardable/Interface.h

@@ -44,6 +44,8 @@ public:
 	
 	Rewardable::Configuration configuration;
 	
+	void serializeJson(JsonSerializeFormat & handler);
+	
 	template <typename Handler> void serialize(Handler &h, const int version)
 	{
 		h & configuration;

+ 6 - 0
lib/rewardable/Limiter.cpp

@@ -14,6 +14,7 @@
 #include "../IGameCallback.h"
 #include "../CPlayerState.h"
 #include "../mapObjects/CGHeroInstance.h"
+#include "../serializer/JsonSerializeFormat.h"
 
 VCMI_LIB_NAMESPACE_BEGIN
 
@@ -119,4 +120,9 @@ bool Rewardable::Limiter::heroAllowed(const CGHeroInstance * hero) const
 	return false;
 }
 
+void Rewardable::Limiter::serializeJson(JsonSerializeFormat & handler)
+{
+	
+}
+
 VCMI_LIB_NAMESPACE_END

+ 2 - 0
lib/rewardable/Limiter.h

@@ -92,6 +92,8 @@ struct DLL_LINKAGE Limiter
 		h & anyOf;
 		h & noneOf;
 	}
+	
+	void serializeJson(JsonSerializeFormat & handler);
 };
 
 }

+ 96 - 0
lib/rewardable/Reward.cpp

@@ -12,6 +12,9 @@
 #include "Reward.h"
 
 #include "../mapObjects/CGHeroInstance.h"
+#include "../serializer/JsonSerializeFormat.h"
+#include "../constants/StringConstants.h"
+#include "../CSkillHandler.h"
 
 VCMI_LIB_NAMESPACE_BEGIN
 
@@ -94,4 +97,97 @@ void Rewardable::Reward::loadComponents(std::vector<Component> & comps,
 	}
 }
 
+void Rewardable::Reward::serializeJson(JsonSerializeFormat & handler)
+{
+	resources.serializeJson(handler, "resources");
+	handler.serializeBool("removeObject", removeObject);
+	handler.serializeInt("manaPercentage", manaPercentage);
+	handler.serializeInt("movePercentage", movePercentage);
+	handler.serializeInt("heroExperience", heroExperience);
+	handler.serializeInt("heroLevel", heroLevel);
+	handler.serializeInt("manaDiff", manaDiff);
+	handler.serializeInt("manaOverflowFactor", manaOverflowFactor);
+	handler.serializeInt("movePoints", movePoints);
+	handler.serializeIdArray("artifacts", artifacts);
+	handler.serializeIdArray("spells", spells);
+	handler.enterArray("creatures").serializeStruct(creatures);
+	{
+		auto a = handler.enterArray("primary");
+		a.syncSize(primary);
+		for(int i = 0; i < primary.size(); ++i)
+			a.serializeInt(i, primary[i]);
+	}
+	
+	{
+		auto a = handler.enterArray("secondary");
+		std::vector<std::pair<std::string, std::string>> fieldValue;
+		if(handler.saving)
+		{
+			for(auto & i : secondary)
+			{
+				auto key = VLC->skillh->encodeSkill(i.first);
+				auto value = NSecondarySkill::levels.at(i.second);
+				fieldValue.emplace_back(key, value);
+			}
+		}
+		a.syncSize(fieldValue);
+		for(int i = 0; i < fieldValue.size(); ++i)
+		{
+			auto e = a.enterStruct(i);
+			e->serializeString("skill", fieldValue[i].first);
+			e->serializeString("level", fieldValue[i].second);
+		}
+		if(!handler.saving)
+		{
+			for(auto & i : fieldValue)
+			{
+				const int skillId = VLC->skillh->decodeSkill(i.first);
+				if(skillId < 0)
+				{
+					logGlobal->error("Invalid secondary skill %s", i.first);
+					continue;
+				}
+				
+				const int level = vstd::find_pos(NSecondarySkill::levels, i.second);
+				if(level < 0)
+				{
+					logGlobal->error("Invalid secondary skill level%s", i.second);
+					continue;
+				}
+				
+				secondary[SecondarySkill(skillId)] = level;
+			}
+				
+		}
+	}
+	
+	{
+		auto a = handler.enterArray("creaturesChange");
+		std::vector<std::pair<CreatureID, CreatureID>> fieldValue;
+		if(handler.saving)
+		{
+			for(auto & i : creaturesChange)
+				fieldValue.push_back(i);
+		}
+		a.syncSize(fieldValue);
+		for(int i = 0; i < fieldValue.size(); ++i)
+		{
+			auto e = a.enterStruct(i);
+			e->serializeId("creature", fieldValue[i].first, CreatureID{});
+			e->serializeId("amount", fieldValue[i].second, CreatureID{});
+		}
+		if(!handler.saving)
+		{
+			for(auto & i : fieldValue)
+				creaturesChange[i.first] = i.second;
+		}
+	}
+	
+	{
+		auto a = handler.enterStruct("spellCast");
+		a->serializeId("spell", spellCast.first, SpellID{});
+		a->serializeInt("level", spellCast.second);
+	}
+}
+
 VCMI_LIB_NAMESPACE_END

+ 2 - 0
lib/rewardable/Reward.h

@@ -110,6 +110,8 @@ struct DLL_LINKAGE Reward
 		if(version >= 821)
 			h & spellCast;
 	}
+	
+	void serializeJson(JsonSerializeFormat & handler);
 };
 }
 

+ 3 - 1
mapeditor/inspector/rewardswidget.cpp

@@ -293,7 +293,9 @@ bool RewardsWidget::commitChanges()
 		seerhut->configuration.info.clear();
 		for(int row = 0; row < rewards; ++row)
 		{
-			Rewardable::Reward reward;
+			seerhut->configuration.info.emplace_back();
+			seerhut->configuration.info.back().visitType = Rewardable::EEventType::EVENT_FIRST_VISIT;
+			Rewardable::Reward & reward = seerhut->configuration.info.back().reward;
 			haveRewards = true;
 			int typeId = ui->rewardsTable->item(row, 0)->data(Qt::UserRole).toInt();
 			int listId = ui->rewardsTable->item(row, 1) ? ui->rewardsTable->item(row, 1)->data(Qt::UserRole).toInt() : 0;