Browse Source

Fix for choosing most specific templates. Also seems to fix the Prisons.

Tomasz Zieliński 1 year ago
parent
commit
e22f6dd07e

+ 20 - 0
lib/mapObjectConstructors/AObjectTypeHandler.cpp

@@ -207,6 +207,26 @@ std::vector<std::shared_ptr<const ObjectTemplate>>AObjectTypeHandler::getTemplat
 		return filtered;
 }
 
+std::vector<std::shared_ptr<const ObjectTemplate>>AObjectTypeHandler::getMostSpecificTemplates(TerrainId terrainType) const
+{
+	auto templates = getTemplates(terrainType);
+	if (!templates.empty())
+	{
+		//Get terrain-specific template if possible
+		int leastTerrains = (*boost::min_element(templates, [](const std::shared_ptr<const ObjectTemplate> & tmp1, const std::shared_ptr<const ObjectTemplate> & tmp2)
+		{
+			return tmp1->getAllowedTerrains().size() < tmp2->getAllowedTerrains().size();
+		}))->getAllowedTerrains().size();
+
+		vstd::erase_if(templates, [leastTerrains](const std::shared_ptr<const ObjectTemplate> & tmp)
+		{
+			return tmp->getAllowedTerrains().size() > leastTerrains;
+		});
+	}
+
+	return templates;
+}
+
 std::shared_ptr<const ObjectTemplate> AObjectTypeHandler::getOverride(TerrainId terrainType, const CGObjectInstance * object) const
 {
 	std::vector<std::shared_ptr<const ObjectTemplate>> ret = getTemplates(terrainType);

+ 1 - 0
lib/mapObjectConstructors/AObjectTypeHandler.h

@@ -78,6 +78,7 @@ public:
 	/// returns all templates matching parameters
 	std::vector<std::shared_ptr<const ObjectTemplate>> getTemplates() const;
 	std::vector<std::shared_ptr<const ObjectTemplate>> getTemplates(const TerrainId terrainType) const;
+	std::vector<std::shared_ptr<const ObjectTemplate>> getMostSpecificTemplates(TerrainId terrainType) const;
 
 	/// returns preferred template for this object, if present (e.g. one of 3 possible templates for town - village, fort and castle)
 	/// note that appearance will not be changed - this must be done separately (either by assignment or via pack from server)

+ 4 - 1
lib/mapObjectConstructors/CObjectClassesHandler.cpp

@@ -315,7 +315,10 @@ TObjectTypeHandler CObjectClassesHandler::getHandlerFor(MapObjectID type, MapObj
 		if (objects.at(type.getNum()) == nullptr)
 			return objects.front()->objects.front();
 
-		auto result = objects.at(type.getNum())->objects.at(subtype.getNum());
+		auto subID = subtype.getNum();
+		if (type == Obj::PRISON)
+			subID = 0;
+		auto result = objects.at(type.getNum())->objects.at(subID);
 
 		if (result != nullptr)
 			return result;

+ 3 - 11
lib/rmg/RmgObject.cpp

@@ -69,6 +69,7 @@ const rmg::Area & Object::Instance::getAccessibleArea() const
 	if(dAccessibleAreaCache.empty())
 	{
 		auto neighbours = rmg::Area({getVisitablePosition()}).getBorderOutside();
+		// FIXME: Blocked area of removable object is also accessible area for neighbors
 		rmg::Area visitable = rmg::Area(neighbours) - getBlockedArea();
 		// TODO: Add in one operation to avoid multiple invalidation
 		for(const auto & from : visitable.getTilesVector())
@@ -122,22 +123,13 @@ void Object::Instance::setAnyTemplate(CRandomGenerator & rng)
 
 void Object::Instance::setTemplate(TerrainId terrain, CRandomGenerator & rng)
 {
-	auto templates = dObject.getObjectHandler()->getTemplates(terrain);
+	auto templates = dObject.getObjectHandler()->getMostSpecificTemplates(terrain);
+
 	if (templates.empty())
 	{
 		auto terrainName = VLC->terrainTypeHandler->getById(terrain)->getNameTranslated();
 		throw rmgException(boost::str(boost::format("Did not find graphics for object (%d,%d) at %s") % dObject.ID % dObject.getObjTypeIndex() % terrainName));
 	}
-	//Get terrain-specific template if possible
-	int leastTerrains = (*boost::min_element(templates, [](const std::shared_ptr<const ObjectTemplate> & tmp1, const std::shared_ptr<const ObjectTemplate> & tmp2)
-	{
-		return tmp1->getAllowedTerrains().size() < tmp2->getAllowedTerrains().size();
-	}))->getAllowedTerrains().size();
-
-	vstd::erase_if(templates, [leastTerrains](const std::shared_ptr<const ObjectTemplate> & tmp)
-	{
-		return tmp->getAllowedTerrains().size() > leastTerrains;
-	});
 	
 	dObject.appearance = *RandomGeneratorUtil::nextItem(templates, rng);
 	dAccessibleAreaCache.clear();

+ 8 - 1
lib/rmg/modificators/TreasurePlacer.cpp

@@ -641,7 +641,14 @@ rmg::Object TreasurePlacer::constructTreasurePile(const std::vector<ObjectInfo*>
 		if(oi->templates.empty())
 			continue;
 		
-		object->appearance = *RandomGeneratorUtil::nextItem(oi->templates, zone.getRand());
+		auto templates = object->getObjectHandler()->getMostSpecificTemplates(zone.getTerrainType());
+
+		if (templates.empty())
+		{
+			throw rmgException(boost::str(boost::format("Did not find template for object (%d,%d) at %s") % object->ID % object->subID % zone.getTerrainType().encode(zone.getTerrainType())));
+		}
+
+		object->appearance = *RandomGeneratorUtil::nextItem(templates, zone.getRand());
 
 		auto blockingIssue = object->isBlockedVisitable() && !object->isRemovable();
 		if (blockingIssue)