浏览代码

- Duplicate Monolith templates to ensure at least 100 are available to RMG
- Do not use Monoliths which can't be placed at any land

Tomasz Zieliński 2 年之前
父节点
当前提交
5b267f9cbd

+ 34 - 3
lib/mapObjects/CObjectClassesHandler.cpp

@@ -393,12 +393,43 @@ void CObjectClassesHandler::afterLoadFinalization()
 		}
 	}
 
+	generateExtraMonolithsForRMG();
+}
+
+void CObjectClassesHandler::generateExtraMonolithsForRMG()
+{
 	//duplicate existing two-way portals to make reserve for RMG
 	auto& portalVec = objects[Obj::MONOLITH_TWO_WAY]->objects;
-	size_t portalCount = portalVec.size();
+	//FIXME: Monoliths  in this vector can be already not useful for every terrain
+	const size_t portalCount = portalVec.size();
+
+	//Invalid portals will be skipped and portalVec size stays unchanged
+	for (size_t i = portalCount; portalVec.size() < 100; ++i)
+	{
+		auto index = static_cast<si32>(i % portalCount);
+		auto portal = portalVec[index];
+		auto templates = portal->getTemplates();
+		if (templates.empty() || !templates[0]->canBePlacedAtAnyTerrain())
+		{
+			continue; //Do not clone HoTA water-only portals or any others we can't use
+		}
 
-	for (size_t i = portalCount; i < 100; ++i)
-		portalVec.push_back(portalVec[static_cast<si32>(i % portalCount)]);
+		//deep copy of noncopyable object :?
+		auto newPortal = std::make_shared<CDefaultObjectTypeHandler<CGMonolith>>();
+		newPortal->rmgInfo = portal->getRMGInfo();
+		newPortal->base = portal->base; //not needed?
+		newPortal->templates = portal->getTemplates();
+		newPortal->sounds = portal->getSounds();
+		newPortal->aiValue = portal->getAiValue();
+		newPortal->battlefield = portal->battlefield; //getter is not initialized at this point
+		newPortal->modScope = portal->modScope; //private
+		newPortal->typeName = portal->getTypeName(); 
+		newPortal->subTypeName = std::string("monolith") + std::to_string(portalVec.size());
+		newPortal->type = portal->getIndex();
+
+		newPortal->subtype = portalVec.size(); //indexes must be unique, they are returned as a set
+		portalVec.push_back(newPortal);
+	}
 }
 
 std::string CObjectClassesHandler::getObjectName(si32 type, si32 subtype) const

+ 2 - 0
lib/mapObjects/CObjectClassesHandler.h

@@ -291,6 +291,8 @@ class DLL_LINKAGE CObjectClassesHandler : public IHandlerBase
 
 	ObjectClass * loadFromJson(const std::string & scope, const JsonNode & json, const std::string & name, size_t index);
 
+	void generateExtraMonolithsForRMG();
+
 public:
 	CObjectClassesHandler();
 	~CObjectClassesHandler();

+ 5 - 0
lib/mapObjects/ObjectTemplate.h

@@ -102,6 +102,11 @@ public:
 		return visitDir & 2;
 	};
 
+	inline bool canBePlacedAtAnyTerrain() const
+	{
+		return anyTerrain;
+	}; 
+
 	// Checks if object can be placed on specific terrain
 	bool canBePlacedAt(TerrainId terrain) const;
 

+ 18 - 4
lib/rmg/CMapGenerator.cpp

@@ -367,10 +367,24 @@ void CMapGenerator::addHeaderInfo()
 
 int CMapGenerator::getNextMonlithIndex()
 {
-	if (monolithIndex >= VLC->objtypeh->knownSubObjects(Obj::MONOLITH_TWO_WAY).size())
-		throw rmgException(boost::to_string(boost::format("There is no Monolith Two Way with index %d available!") % monolithIndex));
-	else
-		return monolithIndex++;
+	while (true)
+	{
+		if (monolithIndex >= VLC->objtypeh->knownSubObjects(Obj::MONOLITH_TWO_WAY).size())
+			throw rmgException(boost::to_string(boost::format("There is no Monolith Two Way with index %d available!") % monolithIndex));
+		else
+		{
+			//Skip modded Monoliths which can't beplaced on every terrain
+			auto templates = VLC->objtypeh->getHandlerFor(Obj::MONOLITH_TWO_WAY, monolithIndex)->getTemplates();
+			if (templates.empty() || !templates[0]->canBePlacedAtAnyTerrain())
+			{
+				monolithIndex++;
+			}
+			else
+			{
+				return monolithIndex++;
+			}
+		}
+	}
 }
 
 int CMapGenerator::getPrisonsRemaning() const