Browse Source

Also allow filtering biomes by faction(s)

Tomasz Zieliński 1 year ago
parent
commit
4fa7f0e93d

+ 43 - 14
config/biomes.json

@@ -174,7 +174,7 @@
 		},
 		"templates" : ["AVXrk0", "AVXrk1", "AVXrk2", "AVXrk3", "AVXrk4", "AVXrk5", "AVXrk6", "AVXrk7"]
 	},
-	"templateSet29":{
+	"cactus":{
 		"biome":{
 			"terrain" : "sand",
 			"objectType" : "plant"
@@ -209,12 +209,19 @@
 		},
 		"templates" : ["AVLskul0"]
 	},
-	"templateSet37":{
+	"sandPalms":{
 		"biome":{
 			"terrain" : "sand",
 			"objectType" : "tree"
 		},
-		"templates" : ["AVLplm10", "AVLplm20", "AVLplm30", "AVLplm40", "AVLplm50", "AVLyuc10", "AVLyuc20", "AVLyuc30"]
+		"templates" : ["AVLplm10", "AVLplm20", "AVLplm30", "AVLplm40", "AVLplm50"]
+	},
+	"sandYucca":{
+		"biome":{
+			"terrain" : "sand",
+			"objectType" : "plant"
+		},
+		"templates" : ["AVLyuc10", "AVLyuc20", "AVLyuc30"]
 	},
 	"templateSet38":{
 		"biome":{
@@ -405,9 +412,10 @@
 		},
 		"templates" : ["AvLStm1", "AvLStm2", "AvLStm3"]
 	},
-	"templateSet64":{
+	"swampTreesOnGrass":{
 		"biome":{
 			"terrain" : "grass",
+			"faction" : "fortress",
 			"objectType" : "tree"
 		},
 		"templates" : ["AVLswmp0", "AVLswmp1", "AVLswmp2", "AVLswmp3", "AVLswmp4", "AVLswmp5", "AVLswmp6", "AVLswmp7", "AVLtr1d0", "AVLtr2d0", "AVLtr3d0", "AVLwlw10", "AVLwlw20", "AVLwlw30"]
@@ -650,7 +658,7 @@
 		},
 		"templates" : ["AVLmtsw1", "AVLmtsw2", "AVLmtsw3", "AVLmtsw4", "AVLmtsw5", "AVLmtsw6"]
 	},
-	"templateSet106":{
+	"swampTrees":{
 		"biome":{
 			"terrain" : "swamp",
 			"objectType" : "tree"
@@ -671,19 +679,33 @@
 		},
 		"templates" : ["AVLs01s0", "AVLs02s0", "AVLs03s0", "AVLs04s0", "AVLs05s0", "AVLs06s0", "AVLs07s0", "AVLs08s0", "AVLs09s0", "AVLs10s0", "AVLs11s0", "AVLswp10", "AVLswp20", "AVLswp30", "AVLswp40"]
 	},
-	"templateSet110":{
+	"floodedPalms":{
 		"biome":{
 			"terrain" : "swamp",
 			"objectType" : "tree"
 		},
-		"templates" : ["AVLswmp0", "AVLswmp1", "AVLswmp2", "AVLswmp3", "AVLswmp4", "AVLswmp5", "AVLswmp6", "AVLswmp7", "AVLtr1d0", "AVLtr2d0", "AVLtr3d0", "AVLwlw10", "AVLwlw20", "AVLwlw30"]
+		"templates" : ["AVLswmp0", "AVLswmp1", "AVLswmp2", "AVLswmp3", "AVLswmp4", "AVLswmp5", "AVLswmp6", "AVLswmp7"]
 	},
-	"templateSet111":{
+	"swampTrees2":{
 		"biome":{
 			"terrain" : "swamp",
-			"objectType" : "other"
+			"objectType" : "tree"
+		},
+		"templates" : ["AVLtr1d0", "AVLtr2d0", "AVLtr3d0", "AVLwlw10", "AVLwlw20", "AVLwlw30"]
+	},
+	"swampPalms":{
+		"biome":{
+			"terrain" : "swamp",
+			"objectType" : "tree"
 		},
-		"templates" : ["avlswtr0", "avlswtr1", "avlswtr2", "avlswtr3", "avlswtr4", "avlswtr5", "avlswtr6", "avlswtr7", "avlswtr8", "avlswtr9", "avlswt00", "avlswt01", "avlswt02", "avlswt03", "avlswt04", "avlswt05", "avlswt06", "avlswt07", "avlswt08", "avlswt09", "avlswt10", "avlswt11", "avlswt12", "avlswt13", "avlswt14", "avlswt15", "avlswt16", "avlswt17", "avlswt18", "avlswt19"]
+		"templates" : ["avlswtr0", "avlswtr1", "avlswtr2", "avlswtr3", "avlswtr4", "avlswtr5", "avlswtr6", "avlswtr7", "avlswtr8", "avlswtr9"]
+	},
+	"swampSinglePalms":{
+		"biome":{
+			"terrain" : "swamp",
+			"objectType" : "plant"
+		},
+		"templates" : ["avlswt00", "avlswt01", "avlswt02", "avlswt03", "avlswt04", "avlswt05", "avlswt06", "avlswt07", "avlswt08", "avlswt09", "avlswt10", "avlswt11", "avlswt12", "avlswt13", "avlswt14", "avlswt15", "avlswt16", "avlswt17", "avlswt18", "avlswt19"]
 	},
 	"templateSet112":{
 		"biome":{
@@ -818,12 +840,19 @@
 		},
 		"templates" : ["AvLdlog", "AvLStm1", "AvLStm2", "AvLStm3"]
 	},
-	"templateSet137":{
+	"roughSmallTree":{
 		"biome":{
 			"terrain" : "rough",
-			"objectType" : "tree"
+			"objectType" : "plant"
+		},
+		"templates" : ["AVLroug0", "AVLroug1", "AVLroug2"]
+	},
+	"roughYucca":{
+		"biome":{
+			"terrain" : "rough",
+			"objectType" : "plant"
 		},
-		"templates" : ["AVLroug0", "AVLroug1", "AVLroug2", "AVLyuc10", "AVLyuc20", "AVLyuc30"]
+		"templates" : ["AVLyuc10", "AVLyuc20", "AVLyuc30"]
 	},
 	"roughLake":{
 		"biome":{
@@ -1070,7 +1099,7 @@
 		},
 		"templates" : ["AVLmtvo1", "AVLmtvo2", "AVLmtvo3", "AVLmtvo4", "AVLmtvo5", "AVLmtvo6"]
 	},
-	"templateSet182":{
+	"volcanos":{
 		"biome":{
 			"terrain" : "lava",
 			"objectType" : "mountain"

+ 13 - 0
config/schemas/biome.json

@@ -28,6 +28,19 @@
 					]
 					
 				},
+				"faction" : {
+					"anyOf": [
+						{
+							"type" : "string",
+							"description" : "Faction of the zone"
+						},
+						{
+							"type" : "array",
+							"items" : { "type" : "string" },
+							"description" : "Factions of the zone"
+						}
+					]
+				},
 				"alignment" : {
 					"anyOf": [
 						{

+ 5 - 0
config/schemas/mod.json

@@ -255,6 +255,11 @@
 			"description" : "List of configuration files for objects",
 			"items" : { "type" : "string", "format" : "textFile" }
 		},
+		"biomes" : {
+			"type" : "array",
+			"description" : "List of configuration files for biomes",
+			"items" : { "type" : "string", "format" : "textFile" }
+		},
 		"bonuses" : {
 			"type" : "array",
 			"description" : "List of configuration files for bonuses",

+ 45 - 2
lib/mapObjects/ObstacleSetHandler.cpp

@@ -33,16 +33,18 @@ void ObstacleSet::addObstacle(std::shared_ptr<const ObjectTemplate> obstacle)
 	obstacles.push_back(obstacle);
 }
 
-ObstacleSetFilter::ObstacleSetFilter(std::vector<ObstacleSet::EObstacleType> allowedTypes, TerrainId terrain = TerrainId::ANY_TERRAIN, EAlignment alignment = EAlignment::ANY):
+ObstacleSetFilter::ObstacleSetFilter(std::vector<ObstacleSet::EObstacleType> allowedTypes, TerrainId terrain = TerrainId::ANY_TERRAIN, FactionID faction = FactionID::ANY, EAlignment alignment = EAlignment::ANY):
 	allowedTypes(allowedTypes),
 	terrain(terrain),
+	faction(faction),
 	alignment(alignment)
 {
 }
 
-ObstacleSetFilter::ObstacleSetFilter(ObstacleSet::EObstacleType allowedType, TerrainId terrain = TerrainId::ANY_TERRAIN, EAlignment alignment = EAlignment::ANY):
+ObstacleSetFilter::ObstacleSetFilter(ObstacleSet::EObstacleType allowedType, TerrainId terrain = TerrainId::ANY_TERRAIN, FactionID faction = FactionID::ANY, EAlignment alignment = EAlignment::ANY):
 	allowedTypes({allowedType}),
 	terrain(terrain),
+	faction(faction),
 	alignment(alignment)
 {
 }
@@ -54,6 +56,15 @@ bool ObstacleSetFilter::filter(const ObstacleSet &set) const
 		return false;
 	}
 
+	if (faction != FactionID::ANY)
+	{
+		auto factions = set.getFactions();
+		if (!factions.empty() && !vstd::contains(factions, faction))
+		{
+			return false;
+		}
+	}
+
 	// TODO: Also check specific factions
 	if (alignment != EAlignment::ANY)
 	{
@@ -92,6 +103,16 @@ void ObstacleSet::addTerrain(TerrainId terrain)
 	this->allowedTerrains.insert(terrain);
 }
 
+std::set<FactionID> ObstacleSet::getFactions() const
+{
+	return allowedFactions;
+}
+
+void ObstacleSet::addFaction(FactionID faction)
+{
+	this->allowedFactions.insert(faction);
+}
+
 void ObstacleSet::addAlignment(EAlignment alignment)
 {
 	this->allowedAlignments.insert(alignment);
@@ -295,6 +316,28 @@ std::shared_ptr<ObstacleSet> ObstacleSetHandler::loadFromJson(const std::string
 		}
 	}
 
+	auto parseFaction = [os, scope](const std::string & str) -> FactionID
+	{
+		VLC->identifiers()->requestIdentifier(scope, "faction", str, [os](si32 id)
+		{
+			os->addFaction(FactionID(id));
+		});
+	};
+
+	if (biome["faction"].isString())
+	{
+		auto factionName = biome["faction"].String();
+		parseFaction(factionName);
+	}
+	else if (biome["faction"].isVector())
+	{
+		auto factions = biome["faction"].Vector();
+		for (const auto & node : factions)
+		{
+			parseFaction(node.String());
+		}
+	}
+
 	// TODO: Move this parser to some utils
 	auto parseAlignment = [](const std::string & str) ->EAlignment
 	{

+ 6 - 2
lib/mapObjects/ObstacleSetHandler.h

@@ -52,6 +52,8 @@ public:
 	void addTerrain(TerrainId terrain);
 	std::set<EAlignment> getAlignments() const;
 	void addAlignment(EAlignment alignment);
+	std::set<FactionID> getFactions() const;
+	void addFaction(FactionID faction);
 
 	static EObstacleType typeFromString(const std::string &str);
 	std::string toString() const;
@@ -61,6 +63,7 @@ public:
 private:
 	EObstacleType type;
 	std::set<TerrainId> allowedTerrains;
+	std::set<FactionID> allowedFactions;
 	std::set<EAlignment> allowedAlignments; // Empty means all
 	std::vector<std::shared_ptr<const ObjectTemplate>> obstacles;
 };
@@ -70,8 +73,8 @@ typedef std::vector<std::shared_ptr<ObstacleSet>> TObstacleTypes;
 class DLL_LINKAGE ObstacleSetFilter
 {
 public:
-	ObstacleSetFilter(ObstacleSet::EObstacleType allowedType, TerrainId terrain , EAlignment alignment);
-	ObstacleSetFilter(std::vector<ObstacleSet::EObstacleType> allowedTypes, TerrainId terrain, EAlignment alignment);
+	ObstacleSetFilter(ObstacleSet::EObstacleType allowedType, TerrainId terrain, FactionID faction, EAlignment alignment);
+	ObstacleSetFilter(std::vector<ObstacleSet::EObstacleType> allowedTypes, TerrainId terrain, FactionID faction, EAlignment alignment);
 
 	bool filter(const ObstacleSet &set) const;
 
@@ -84,6 +87,7 @@ public:
 
 private:
 	std::vector<ObstacleSet::EObstacleType> allowedTypes;
+	FactionID faction;
 	EAlignment alignment;
 // TODO: Filter by faction,  surface/underground, etc.
 	const TerrainId terrain;

+ 0 - 4
lib/mapping/ObstacleProxy.cpp

@@ -54,12 +54,8 @@ void ObstacleProxy::sortObstacles()
 
 bool ObstacleProxy::prepareBiome(const ObstacleSetFilter & filter, CRandomGenerator & rand)
 {
-	// FIXME: All the mountains have same ID and mostly same subID, how to differentiate them?
-
 	possibleObstacles.clear();
 
-	// TODO: Move this logic to ObstacleSetHandler
-
 	std::vector<std::shared_ptr<ObstacleSet>> obstacleSets;
 
 	size_t selectedSets = 0;

+ 3 - 1
lib/rmg/modificators/ObstaclePlacer.cpp

@@ -36,7 +36,9 @@ void ObstaclePlacer::process()
 	if(!manager)
 		return;
 
-	ObstacleSetFilter filter(ObstacleSet::EObstacleType::INVALID, zone.getTerrainType(), zone.getTownType().toFaction()->alignment);
+	auto faction = zone.getTownType().toFaction();
+
+	ObstacleSetFilter filter(ObstacleSet::EObstacleType::INVALID, zone.getTerrainType(), faction->getId(), faction->alignment);
 
 	if (!prepareBiome(filter, zone.getRand()))
 	{