Explorar o código

Load obstacle sets from json in mods

Tomasz Zieliński hai 1 ano
pai
achega
305e2bdf2f

+ 3 - 0
config/schemas/objectType.json

@@ -16,6 +16,9 @@
 			"additionalProperties" : true, // Not validated on its own - instead data copied to main object and validated as part of it
 			"type" : "object"
 		},
+		"biome" : {
+			"type" : "object"
+		},
 		"rmg" : {
 			"additionalProperties" : false,
 			"type" : "object",

+ 39 - 0
lib/mapObjectConstructors/CommonConstructors.cpp

@@ -36,6 +36,45 @@ bool CObstacleConstructor::isStaticObject()
 	return true;
 }
 
+void CObstacleConstructor::initTypeData(const JsonNode & input)
+{
+	if (!input["biome"].isNull())
+	{
+		obstacleType = ObstacleSet::typeFromString(input["biome"]["objectType"].String());
+	}
+	else
+	{
+		obstacleType = ObstacleSet::EObstacleType::INVALID;
+	}
+}
+
+void CObstacleConstructor::afterLoadFinalization()
+{
+	if (obstacleType == ObstacleSet::EObstacleType::INVALID)
+		return;
+
+	auto templates = getTemplates();
+	logGlobal->info("Loaded %d templates for %s", templates.size(), getJsonKey());
+	if (!templates.empty())
+	{
+		auto terrains = templates.front()->getAllowedTerrains();
+
+		// FIXME: 0 terrains
+		logGlobal->info("Found %d terrains for %s", terrains.size(), getJsonKey());
+		// For now assume that all templates are from the same biome
+		for (auto terrain : terrains)
+		{
+			ObstacleSet os(obstacleType, terrain);
+			for (auto tmpl : templates)
+			{
+				os.addObstacle(tmpl);
+			}
+			VLC->biomeHandler->addObstacleSet(os);
+			logGlobal->info("Loaded obstacle set from mod %s, terrain: %s", getJsonKey(), terrain.encode(terrain.getNum()));
+		}
+	}
+}
+
 bool CreatureInstanceConstructor::hasNameTextID() const
 {
 	return true;

+ 7 - 0
lib/mapObjectConstructors/CommonConstructors.h

@@ -14,6 +14,7 @@
 
 #include "../mapObjects/MiscObjects.h"
 #include "../mapObjects/CGCreature.h"
+#include "../mapObjects/ObstacleSetHandler.h"
 
 VCMI_LIB_NAMESPACE_BEGIN
 
@@ -28,11 +29,17 @@ class CBank;
 class CGBoat;
 class CFaction;
 class CStackBasicDescriptor;
+class ObstacleSet;
 
 class CObstacleConstructor : public CDefaultObjectTypeHandler<CGObjectInstance>
 {
 public:
 	bool isStaticObject() override;
+	void initTypeData(const JsonNode & input) override;
+	void afterLoadFinalization() override;
+
+protected:
+	ObstacleSet::EObstacleType obstacleType;
 };
 
 class CreatureInstanceConstructor : public CDefaultObjectTypeHandler<CGCreature>

+ 44 - 1
lib/mapObjects/ObstacleSetHandler.cpp

@@ -66,7 +66,6 @@ ObstacleSet::EObstacleType ObstacleSetHandler::convertObstacleClass(MapObjectID
 	switch (id)
 	{
 		case Obj::MOUNTAIN:
-		case Obj::SAND_DUNE:
 		case Obj::VOLCANIC_VENT:
 		case Obj::VOLCANO:
 		case Obj::REEF:
@@ -94,6 +93,7 @@ ObstacleSet::EObstacleType ObstacleSetHandler::convertObstacleClass(MapObjectID
 		case Obj::MOUND:
 		case Obj::OUTCROPPING:
 		case Obj::ROCK:
+		case Obj::SAND_DUNE:
 		case Obj::STALAGMITE:
 			return ObstacleSet::ROCKS;
 		case Obj::BUSH:
@@ -115,6 +115,30 @@ ObstacleSet::EObstacleType ObstacleSetHandler::convertObstacleClass(MapObjectID
 	}
 }
 
+ObstacleSet::EObstacleType ObstacleSet::typeFromString(const std::string &str)
+{
+	static const std::map<std::string, EObstacleType> OBSTACLE_TYPE_NAMES =
+	{
+		{"mountain", MOUNTAINS},
+		{"tree", TREES},
+		{"lake", LAKES},
+		{"crater", CRATERS},
+		{"rock", ROCKS},
+		{"plant", PLANTS},
+		{"structure", STRUCTURES},
+		{"animal", ANIMALS},
+		{"other", OTHER}
+	};
+
+	if (OBSTACLE_TYPE_NAMES.find(str) != OBSTACLE_TYPE_NAMES.end())
+	{
+		return OBSTACLE_TYPE_NAMES.at(str);
+	}
+
+	// TODO: How to handle that?
+	throw std::runtime_error("Invalid obstacle type: " + str);
+}
+
 std::vector<ObstacleSet::EObstacleType> ObstacleSetFilter::getAllowedTypes() const
 {
 	return allowedTypes;
@@ -149,5 +173,24 @@ TObstacleTypes ObstacleSetHandler::getObstacles( const ObstacleSetFilter &filter
 	return result;
 }
 
+/*
+ObstacleSet ObstacleSetHandler::loadObject(std::string scope, std::string name, const JsonNode & data)
+{
+	// TODO: Merge by name with existing obstacle sets?
+
+
+	const JsonNode & biome = json["biome"];
+	auto objectType = ObstacleSet::typeFromString(biome["objectType"].String());
+
+	for (const JsonNode & type : data["types"])
+	{
+		for (const JsonNode & obstacle : type["templates"])
+		{
+			// TODO: Reuse templates (pointers) parsed by CObjectClassesHandler
+		}
+	}
+}
+*/
+
 VCMI_LIB_NAMESPACE_END
 

+ 4 - 2
lib/mapObjects/ObstacleSetHandler.h

@@ -26,7 +26,8 @@ public:
 
 	enum EObstacleType
 	{
-		MOUNTAINS,
+		INVALID = -1,
+		MOUNTAINS = 0,
 		TREES,
 		LAKES, // Inluding dry or lava lakes
 		CRATERS, // Chasms, Canyons, etc.
@@ -36,7 +37,6 @@ public:
 		ANIMALS, // Living, or bones
 		OTHER // Crystals, shipwrecks, barrels, etc.
 	};
-
 	explicit ObstacleSet(EObstacleType type, TerrainId terrain);
 
 	void addObstacle(std::shared_ptr<const ObjectTemplate> obstacle);
@@ -45,6 +45,8 @@ public:
 	EObstacleType getType() const;
 	TerrainId getTerrain() const;
 
+	static EObstacleType typeFromString(const std::string &str);
+
 private:
 	EObstacleType type;
 	TerrainId terrain;

+ 5 - 2
lib/mapping/ObstacleProxy.cpp

@@ -177,7 +177,10 @@ bool ObstacleProxy::prepareBiome(TerrainId terrain, CRandomGenerator & rand)
 
 	// Copy this set to our possible obstacles
 	
-	if (selectedSets >= MINIMUM_SETS)
+	//	if (selectedSets >= MINIMUM_SETS)
+
+	if (selectedSets >= MINIMUM_SETS ||
+		(terrain == TerrainId::WATER && selectedSets > 0))
 	{
 		obstaclesBySize.clear();
 		for (const auto & os : obstacleSets)
@@ -200,7 +203,7 @@ bool ObstacleProxy::prepareBiome(TerrainId terrain, CRandomGenerator & rand)
 		{
 			return p1.first > p2.first; //bigger obstacles first
 		});
-		
+
 		return true;
 	}
 	else