Browse Source

Move ObjectConfig to ObjectInfo.cpp. Preliminary version of banning object categories.

Tomasz Zieliński 1 year ago
parent
commit
64fc2e5ed0

+ 3 - 0
config/schemas/template.json

@@ -49,6 +49,9 @@
 						},
 						"additionalProperties" : false
 					}
+				},
+				"customObjects" : {
+					"type" : "object"
 				}
 			}
 		},

+ 1 - 4
lib/mapObjectConstructors/CObjectClassesHandler.cpp

@@ -411,11 +411,8 @@ CompoundMapObjectID CObjectClassesHandler::getCompoundIdentifier(const std::stri
 CompoundMapObjectID CObjectClassesHandler::getCompoundIdentifier(const std::string & objectName) const
 {
 	// FIXME: Crash with no further log
-	//"core:object.creatureBank.experimentalShop",
-	//"core:object.creatureBank.wolfRiderPicket",
-	//"core:object.creatureBank.demonDomain"
 
-		// TODO: Use existing utilities for parsing id?	
+	// TODO: Use existing utilities for parsing id?	
 	JsonNode node(objectName);
 	auto modScope = node.getModScope();
 

+ 5 - 73
lib/rmg/CRmgTemplate.cpp

@@ -11,9 +11,9 @@
 #include "StdInc.h"
 #include <vstd/ContainerUtils.h>
 #include <boost/bimap.hpp>
+
 #include "CRmgTemplate.h"
 #include "Functions.h"
-
 #include "../TerrainHandler.h"
 #include "../VCMI_Lib.h"
 #include "../constants/StringConstants.h"
@@ -909,87 +909,19 @@ void CRmgTemplate::serializePlayers(JsonSerializeFormat & handler, CPlayerCountR
 		value.fromString(encodedValue);
 }
 
-void ZoneOptions::ObjectConfig::addBannedObject(const CompoundMapObjectID & objid)
-{
-	// FIXME: We do not need to store the object info, just the id
-
-	bannedObjects.push_back(objid);
-
-	logGlobal->info("Banned object of type %d.%d", objid.primaryID, objid.secondaryID);
-}
-
-void ZoneOptions::ObjectConfig::serializeJson(JsonSerializeFormat & handler)
-{
-	// TODO: Implement'
-	
-	auto bannedObjectData = handler.enterArray("bannedObjects");	
-	if (handler.saving)
-	{
-
-		// FIXME: Do we even need to serialize / store banned objects?
-		/*
-		for (const auto & object : bannedObjects)
-		{
-			// TODO: Translate id back to string?
-
-
-			JsonNode node;
-			node.String() = VLC->objtypeh->getHandlerFor(object.primaryID, object.secondaryID);
-			// TODO: Check if AI-generated code is right
-
-
-		}
-		// handler.serializeRaw("bannedObjects", node, std::nullopt);
-
-		*/
-	}
-	else
-	{
-		/*
-			auto zonesData = handler.enterStruct("zones");
-			for(const auto & idAndZone : zonesData->getCurrent().Struct())
-			{
-				auto guard = handler.enterStruct(idAndZone.first);
-				auto zone = std::make_shared<ZoneOptions>();
-				zone->setId(decodeZoneId(idAndZone.first));
-				zone->serializeJson(handler);
-				zones[zone->getId()] = zone;
-			}
-		*/
-		std::vector<std::string> objectNames;
-		bannedObjectData.serializeArray(objectNames);
-
-		for (const auto & objectName : objectNames)
-		{
-			VLC->objtypeh->resolveObjectCompoundId(objectName,
-				[this](CompoundMapObjectID objid)
-				{
-					addBannedObject(objid);
-				}
-			);
-			
-		}
-	}
-}
-
 const std::vector<CompoundMapObjectID> & ZoneOptions::getBannedObjects() const
 {
 	return objectConfig.getBannedObjects();
 }
 
-const std::vector<ObjectInfo> & ZoneOptions::getCustomObjects() const
-{
-	return objectConfig.getCustomObjects();
-}
-
-const std::vector<CompoundMapObjectID> & ZoneOptions::ObjectConfig::getBannedObjects() const
+const std::vector<ObjectConfig::EObjectCategory> & ZoneOptions::getBannedObjectCategories() const
 {
-	return bannedObjects;
+	return objectConfig.getBannedObjectCategories();
 }
 
-const std::vector<ObjectInfo> & ZoneOptions::ObjectConfig::getCustomObjects() const
+const std::vector<ObjectInfo> & ZoneOptions::getCustomObjects() const
 {
-	return customObjects;
+	return objectConfig.getCustomObjects();
 }
 
 VCMI_LIB_NAMESPACE_END

+ 1 - 26
lib/rmg/CRmgTemplate.h

@@ -139,32 +139,6 @@ public:
 		TRmgTemplateZoneId sourceZone = NO_ZONE;
 	};
 
-	// TODO: Store config for custom objects to spawn in this zone
-	// TODO: Read custom object config from zone file
-	class DLL_LINKAGE ObjectConfig
-	{
-	public:
-		//ObjectConfig() = default;
-
-		void addBannedObject(const CompoundMapObjectID & objid);
-		void addCustomObject(const ObjectInfo & object);
-		void clearBannedObjects();
-		void clearCustomObjects();
-		const std::vector<CompoundMapObjectID> & getBannedObjects() const;
-		const std::vector<ObjectInfo> & getCustomObjects() const;
-
-		// TODO: Separate serializer
-		void serializeJson(JsonSerializeFormat & handler);
-	private:
-		// TODO: Add convenience method for banning objects by name
-		std::vector<CompoundMapObjectID> bannedObjects;
-
-		// TODO: In what format should I store custom objects?
-		// Need to convert map serialization format to ObjectInfo
-		std::vector<ObjectInfo> customObjects;
-	};
-	// TODO: Allow to copy all custom objects config from another zone
-
 	ZoneOptions();
 
 	TRmgTemplateZoneId getId() const;
@@ -215,6 +189,7 @@ public:
 	bool isMatchTerrainToTown() const;
 
 	const std::vector<CompoundMapObjectID> & getBannedObjects() const;
+	const std::vector<ObjectConfig::EObjectCategory> & getBannedObjectCategories() const;
 	const std::vector<ObjectInfo> & getCustomObjects() const;
 
 protected:

+ 115 - 7
lib/rmg/ObjectInfo.cpp

@@ -9,11 +9,14 @@
  */
 
 #include "StdInc.h"
+#include <boost/bimap.hpp>
+#include <boost/assign.hpp>
 #include "ObjectInfo.h"
 
 #include "../VCMI_Lib.h"
 #include "../mapObjectConstructors/CObjectClassesHandler.h"
 #include "../mapObjectConstructors/AObjectTypeHandler.h"
+#include "../serializer/JsonSerializeFormat.h"
 
 VCMI_LIB_NAMESPACE_BEGIN
 
@@ -56,16 +59,121 @@ void ObjectInfo::setTemplates(MapObjectID type, MapObjectSubID subtype, TerrainI
 	templates = templHandler->getTemplates(terrainType);
 }
 
-/*
-bool ObjectInfo::matchesId(const CompoundMapObjectID & id) const
+void ObjectConfig::addBannedObject(const CompoundMapObjectID & objid)
+{
+	// FIXME: We do not need to store the object info, just the id
+
+	bannedObjects.push_back(objid);
+
+	logGlobal->info("Banned object of type %d.%d", objid.primaryID, objid.secondaryID);
+}
+
+void ObjectConfig::serializeJson(JsonSerializeFormat & handler)
 {
-	for (const auto & templ : templates)
+	// TODO: We need serializer utility for list of enum values
+
+	static const boost::bimap<EObjectCategory, std::string> OBJECT_CATEGORY_STRINGS = boost::assign::list_of<boost::bimap<EObjectCategory, std::string>::relation>
+		(EObjectCategory::OTHER, "other")
+		(EObjectCategory::ALL, "all")
+		(EObjectCategory::NONE, "none")
+		(EObjectCategory::CREATURE_BANK, "creatureBank")
+		(EObjectCategory::PERMANENT_BONUS, "permanentBonus")
+		(EObjectCategory::NEXT_BATTLE_BONUS, "nextBattleBonus")
+		(EObjectCategory::DWELLING, "dwelling")
+		(EObjectCategory::RESOURCE, "resource")
+		(EObjectCategory::RESOURCE_GENERATOR, "resourceGenerator")
+		(EObjectCategory::SPELL_SCROLL, "spellScroll")
+		(EObjectCategory::RANDOM_ARTIFACT, "randomArtifact")
+		(EObjectCategory::PANDORAS_BOX, "pandorasBox")
+		(EObjectCategory::QUEST_ARTIFACT, "questArtifact");
+
+	auto categories = handler.enterArray("bannedCategories");
+	if (handler.saving)
+	{
+		for (const auto& category : bannedObjectCategories)
+		{
+			auto str = OBJECT_CATEGORY_STRINGS.left.at(category);
+			categories.serializeString(categories.size(), str);
+		}
+	}
+	else
+	{
+		std::vector<std::string> categoryNames;
+		categories.serializeArray(categoryNames);
+
+		for (const auto & categoryName : categoryNames)
+		{
+			auto it = OBJECT_CATEGORY_STRINGS.right.find(categoryName);
+			if (it != OBJECT_CATEGORY_STRINGS.right.end())
+			{
+				bannedObjectCategories.push_back(it->second);
+			}
+		}
+	}
+	
+	auto bannedObjectData = handler.enterArray("bannedObjects");	
+	if (handler.saving)
+	{
+
+		// FIXME: Do we even need to serialize / store banned objects?
+		/*
+		for (const auto & object : bannedObjects)
+		{
+			// TODO: Translate id back to string?
+
+
+			JsonNode node;
+			node.String() = VLC->objtypeh->getHandlerFor(object.primaryID, object.secondaryID);
+			// TODO: Check if AI-generated code is right
+
+
+		}
+		// handler.serializeRaw("bannedObjects", node, std::nullopt);
+
+		*/
+	}
+	else
 	{
-		if (id.primaryID == templ->id && id.secondaryID == templ->subid)
-			return true;
+		/*
+			auto zonesData = handler.enterStruct("zones");
+			for(const auto & idAndZone : zonesData->getCurrent().Struct())
+			{
+				auto guard = handler.enterStruct(idAndZone.first);
+				auto zone = std::make_shared<ZoneOptions>();
+				zone->setId(decodeZoneId(idAndZone.first));
+				zone->serializeJson(handler);
+				zones[zone->getId()] = zone;
+			}
+		*/
+		std::vector<std::string> objectNames;
+		bannedObjectData.serializeArray(objectNames);
+
+		for (const auto & objectName : objectNames)
+		{
+			VLC->objtypeh->resolveObjectCompoundId(objectName,
+				[this](CompoundMapObjectID objid)
+				{
+					addBannedObject(objid);
+				}
+			);
+			
+		}
 	}
-	return false;
 }
-*/
+
+const std::vector<ObjectInfo> & ObjectConfig::getCustomObjects() const
+{
+	return customObjects;
+}
+
+const std::vector<CompoundMapObjectID> & ObjectConfig::getBannedObjects() const
+{
+	return bannedObjects;
+}
+
+const std::vector<ObjectConfig::EObjectCategory> & ObjectConfig::getBannedObjectCategories() const
+{
+	return bannedObjectCategories;
+}
 
 VCMI_LIB_NAMESPACE_END

+ 45 - 0
lib/rmg/ObjectInfo.h

@@ -37,4 +37,49 @@ struct DLL_LINKAGE ObjectInfo
 	//bool matchesId(const CompoundMapObjectID & id) const;
 };
 
+// TODO: Store config for custom objects to spawn in this zone
+// TODO: Read custom object config from zone file
+class DLL_LINKAGE ObjectConfig
+{
+public:
+
+	enum class EObjectCategory
+	{
+		OTHER = -2,
+		ALL = -1,
+		NONE = 0,
+		CREATURE_BANK = 1,
+		PERMANENT_BONUS,
+		NEXT_BATTLE_BONUS,
+		DWELLING,
+		RESOURCE,
+		RESOURCE_GENERATOR,
+		SPELL_SCROLL,
+		RANDOM_ARTIFACT,
+		PANDORAS_BOX,
+		QUEST_ARTIFACT
+		// TODO: Seer huts?
+	};
+
+	void addBannedObject(const CompoundMapObjectID & objid);
+	void addCustomObject(const ObjectInfo & object);
+	void clearBannedObjects();
+	void clearCustomObjects();
+	const std::vector<CompoundMapObjectID> & getBannedObjects() const;
+	const std::vector<EObjectCategory> & getBannedObjectCategories() const;
+	const std::vector<ObjectInfo> & getCustomObjects() const;
+
+	// TODO: Separate serializer
+	void serializeJson(JsonSerializeFormat & handler);
+private:
+	// TODO: Add convenience method for banning objects by name
+	std::vector<CompoundMapObjectID> bannedObjects;
+	std::vector<EObjectCategory> bannedObjectCategories;
+
+	// TODO: In what format should I store custom objects?
+	// Need to convert map serialization format to ObjectInfo
+	std::vector<ObjectInfo> customObjects;
+};
+// TODO: Allow to copy all custom objects config from another zone
+
 VCMI_LIB_NAMESPACE_END

+ 74 - 0
lib/rmg/modificators/TreasurePlacer.cpp

@@ -10,6 +10,7 @@
 
 #include "StdInc.h"
 #include "TreasurePlacer.h"
+#include "../CRmgTemplate.h"
 #include "../CMapGenerator.h"
 #include "../Functions.h"
 #include "ObjectManager.h"
@@ -1133,6 +1134,19 @@ void TreasurePlacer::ObjectPool::patchWithZoneConfig(const Zone & zone)
 		}
 	}
 	*/
+	auto bannedObjectCategories = zone.getBannedObjectCategories();
+	auto categoriesSet = std::unordered_set<ObjectConfig::EObjectCategory>(bannedObjectCategories.begin(), bannedObjectCategories.end());
+
+	vstd::erase_if(possibleObjects, [this, &categoriesSet](const ObjectInfo & oi) -> bool
+	{
+		auto category = getObjectCategory(oi.templates.front()->id);
+		if (categoriesSet.count(category))
+		{
+			logGlobal->info("Removing object %s from possible objects", oi.templates.front()->stringID);
+			return true;
+		}
+		return false;
+	});
 
 	vstd::erase_if(possibleObjects, [&zone](const ObjectInfo & object)
 	{
@@ -1180,4 +1194,64 @@ void TreasurePlacer::ObjectPool::discardObjectsAboveValue(ui32 value)
 	});
 }
 
+ObjectConfig::EObjectCategory TreasurePlacer::ObjectPool::getObjectCategory(MapObjectID id)
+{
+	auto name = VLC->objtypeh->getObjectHandlerName(id);
+
+	if (name == "configurable")
+	{
+		// TODO: Need to check configuration here.
+		// Possible otions: PERMANENT_BONUS, NEXT_BATTLE_BONUS, RESOURCE
+		return ObjectConfig::EObjectCategory::RESOURCE;
+	}
+	else if (name == "dwelling" || name == "randomDwelling")
+	{
+		// TODO: Special handling for different tiers
+		return ObjectConfig::EObjectCategory::DWELLING;
+	}
+	else if (name == "bank")
+		return ObjectConfig::EObjectCategory::CREATURE_BANK;
+	else if (name == "market")
+		return ObjectConfig::EObjectCategory::OTHER;
+	else if (name == "hillFort")
+		return ObjectConfig::EObjectCategory::OTHER;
+	else if (name == "resource" || name == "randomResource")
+		return ObjectConfig::EObjectCategory::RESOURCE;
+	else if (name == "randomArtifact") //"artifact"
+		return ObjectConfig::EObjectCategory::RANDOM_ARTIFACT;
+	else if (name == "denOfThieves")
+		return ObjectConfig::EObjectCategory::OTHER;
+	else if (name == "lighthouse")
+	{
+		// TODO: So far Lighthouse is not generated
+		// Also, it gives global bonus as long as owned
+		return ObjectConfig::EObjectCategory::PERMANENT_BONUS;
+	}
+	else if (name == "magi")
+		return ObjectConfig::EObjectCategory::OTHER;
+	else if (name == "mine")
+		return ObjectConfig::EObjectCategory::RESOURCE_GENERATOR;
+	else if (name == "pandora")
+		return ObjectConfig::EObjectCategory::PANDORAS_BOX;
+	else if (name == "prison")
+	{
+		// TODO: Prisons are configurable
+		return ObjectConfig::EObjectCategory::OTHER;
+	}
+	else if (name == "seerHut")
+	{
+		// quest artifacts are configurable, but what about seer huts?
+		return ObjectConfig::EObjectCategory::QUEST_ARTIFACT;
+	}
+	else if (name == "siren")
+		return ObjectConfig::EObjectCategory::NEXT_BATTLE_BONUS;
+	else if (name == "obelisk")
+		return ObjectConfig::EObjectCategory::OTHER;
+
+	// TODO: ObjectConfig::EObjectCategory::SPELL_SCROLL
+
+	// Not interesting for us
+	return ObjectConfig::EObjectCategory::NONE;
+}
+
 VCMI_LIB_NAMESPACE_END

+ 3 - 0
lib/rmg/modificators/TreasurePlacer.h

@@ -20,6 +20,7 @@ class CGObjectInstance;
 class ObjectManager;
 class RmgMap;
 class CMapGenerator;
+class ObjectConfig;
 struct CompoundMapObjectID;
 
 class TreasurePlacer: public Modificator
@@ -72,6 +73,8 @@ protected:
 		void sortPossibleObjects();
 		void discardObjectsAboveValue(ui32 value);
 
+		ObjectConfig::EObjectCategory getObjectCategory(MapObjectID id);
+
 	private:
 
 		std::vector<ObjectInfo> possibleObjects;