Browse Source

Select random object template instead of first

nordsoft 2 years ago
parent
commit
ce62ab3e66

+ 11 - 10
lib/rmg/RmgObject.cpp

@@ -111,18 +111,18 @@ void Object::Instance::setPositionRaw(const int3 & position)
 	dObject.pos = dPosition + dParent.getPosition();
 }
 
-void Object::Instance::setAnyTemplate()
+void Object::Instance::setAnyTemplate(CRandomGenerator & rng)
 {
 	auto templates = VLC->objtypeh->getHandlerFor(dObject.ID, dObject.subID)->getTemplates();
 	if(templates.empty())
 		throw rmgException(boost::str(boost::format("Did not find any graphics for object (%d,%d)") % dObject.ID % dObject.subID));
 
-	dObject.appearance = templates.front();
+	dObject.appearance = *RandomGeneratorUtil::nextItem(templates, rng);
 	dAccessibleAreaCache.clear();
 	setPosition(getPosition(false));
 }
 
-void Object::Instance::setTemplate(TerrainId terrain)
+void Object::Instance::setTemplate(TerrainId terrain, CRandomGenerator & rng)
 {
 	auto templates = VLC->objtypeh->getHandlerFor(dObject.ID, dObject.subID)->getTemplates(terrain);
 	if (templates.empty())
@@ -130,7 +130,8 @@ void Object::Instance::setTemplate(TerrainId terrain)
 		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.subID % terrainName));
 	}
-	dObject.appearance = templates.front();
+	
+	dObject.appearance = *RandomGeneratorUtil::nextItem(templates, rng);
 	dAccessibleAreaCache.clear();
 	setPosition(getPosition(false));
 }
@@ -280,10 +281,10 @@ void Object::setPosition(const int3 & position)
 		i.setPositionRaw(i.getPosition());
 }
 
-void Object::setTemplate(const TerrainId & terrain)
+void Object::setTemplate(const TerrainId & terrain, CRandomGenerator & rng)
 {
 	for(auto& i : dInstances)
-		i.setTemplate(terrain);
+		i.setTemplate(terrain, rng);
 }
 
 const Area & Object::getArea() const
@@ -325,7 +326,7 @@ void rmg::Object::setGuardedIfMonster(const Instance& object)
 	}
 }
 
-void Object::Instance::finalize(RmgMap & map)
+void Object::Instance::finalize(RmgMap & map, CRandomGenerator & rng)
 {
 	if(!map.isOnMap(getPosition(true)))
 		throw rmgException(boost::str(boost::format("Position of object %d at %s is outside the map") % dObject.id % getPosition(true).toString()));
@@ -341,7 +342,7 @@ void Object::Instance::finalize(RmgMap & map)
 		}
 		else
 		{
-			setTemplate(terrainType->getId());
+			setTemplate(terrainType->getId(), rng);
 		}
 	}
 
@@ -362,14 +363,14 @@ void Object::Instance::finalize(RmgMap & map)
 	map.getMapProxy()->insertObject(&dObject);
 }
 
-void Object::finalize(RmgMap & map)
+void Object::finalize(RmgMap & map, CRandomGenerator & rng)
 {
 	if(dInstances.empty())
 		throw rmgException("Cannot finalize object without instances");
 
 	for(auto & dInstance : dInstances)
 	{
-		dInstance.finalize(map);
+		dInstance.finalize(map, rng);
 	}
 }
 

+ 6 - 5
lib/rmg/RmgObject.h

@@ -17,6 +17,7 @@
 VCMI_LIB_NAMESPACE_BEGIN
 
 class CGObjectInstance;
+class CRandomGenerator;
 class RmgMap;
 
 namespace rmg {
@@ -35,8 +36,8 @@ public:
 		int3 getVisitablePosition() const;
 		bool isVisitableFrom(const int3 & tile) const;
 		const Area & getAccessibleArea() const;
-		void setTemplate(TerrainId terrain); //cache invalidation
-		void setAnyTemplate(); //cache invalidation
+		void setTemplate(TerrainId terrain, CRandomGenerator &); //cache invalidation
+		void setAnyTemplate(CRandomGenerator &); //cache invalidation
 		
 		int3 getTopTile() const;
 		int3 getPosition(bool isAbsolute = false) const;
@@ -45,7 +46,7 @@ public:
 		const CGObjectInstance & object() const;
 		CGObjectInstance & object();
 		
-		void finalize(RmgMap & map); //cache invalidation
+		void finalize(RmgMap & map, CRandomGenerator &); //cache invalidation
 		void clear();
 		
 	private:
@@ -73,7 +74,7 @@ public:
 	
 	const int3 & getPosition() const;
 	void setPosition(const int3 & position);
-	void setTemplate(const TerrainId & terrain);
+	void setTemplate(const TerrainId & terrain, CRandomGenerator &);
 	
 	const Area & getArea() const;  //lazy cache invalidation
 	const int3 getVisibleTop() const;
@@ -81,7 +82,7 @@ public:
 	bool isGuarded() const;
 	void setGuardedIfMonster(const Instance & object);
 	
-	void finalize(RmgMap & map);
+	void finalize(RmgMap & map, CRandomGenerator &);
 	void clear();
 	
 private:

+ 2 - 2
lib/rmg/modificators/ConnectionsPlacer.cpp

@@ -316,8 +316,8 @@ void ConnectionsPlacer::selfSideIndirectConnection(const rmg::ZoneConnection & c
 			auto * gate2 = factory->create();
 			rmg::Object rmgGate1(*gate1);
 			rmg::Object rmgGate2(*gate2);
-			rmgGate1.setTemplate(zone.getTerrainType());
-			rmgGate2.setTemplate(otherZone->getTerrainType());
+			rmgGate1.setTemplate(zone.getTerrainType(), zone.getRand());
+			rmgGate2.setTemplate(otherZone->getTerrainType(), zone.getRand());
 			bool guarded1 = manager.addGuard(rmgGate1, connection.getGuardStrength(), true);
 			bool guarded2 = managerOther.addGuard(rmgGate2, connection.getGuardStrength(), true);
 			int minDist = 3;

+ 5 - 5
lib/rmg/modificators/ObjectManager.cpp

@@ -354,7 +354,7 @@ bool ObjectManager::createRequiredObjects()
 	for(const auto & objInfo : requiredObjects)
 	{
 		rmg::Object rmgObject(*objInfo.obj);
-		rmgObject.setTemplate(zone.getTerrainType());
+		rmgObject.setTemplate(zone.getTerrainType(), zone.getRand());
 		bool guarded = addGuard(rmgObject, objInfo.guardStrength, (objInfo.obj->ID == Obj::MONOLITH_TWO_WAY));
 
 		Zone::Lock lock(zone.areaMutex);
@@ -394,7 +394,7 @@ bool ObjectManager::createRequiredObjects()
 		auto possibleArea = zone.areaPossible();
 
 		rmg::Object rmgObject(*objInfo.obj);
-		rmgObject.setTemplate(zone.getTerrainType());
+		rmgObject.setTemplate(zone.getTerrainType(), zone.getRand());
 		bool guarded = addGuard(rmgObject, objInfo.guardStrength, (objInfo.obj->ID == Obj::MONOLITH_TWO_WAY));
 		auto path = placeAndConnectObject(zone.areaPossible(), rmgObject,
 										  [this, &rmgObject](const int3 & tile)
@@ -480,7 +480,7 @@ void ObjectManager::placeObject(rmg::Object & object, bool guarded, bool updateD
 		if (!monster->object().appearance)
 		{
 			//Needed to determine visitable offset
-			monster->setAnyTemplate();
+			monster->setAnyTemplate(zone.getRand());
 		}
 		object.getPosition();
 		auto visitableOffset = monster->object().getVisitableOffset();
@@ -492,7 +492,7 @@ void ObjectManager::placeObject(rmg::Object & object, bool guarded, bool updateD
 		int3 parentOffset = monster->getPosition(true) - monster->getPosition(false);
 		monster->setPosition(fixedPos - parentOffset);
 	}
-	object.finalize(map);
+	object.finalize(map, zone.getRand());
 
 	Zone::Lock lock(zone.areaMutex);
 	zone.areaPossible().subtract(object.getArea());
@@ -689,7 +689,7 @@ bool ObjectManager::addGuard(rmg::Object & object, si32 strength, bool zoneGuard
 	});
 	
 	auto & instance = object.addInstance(*guard);
-	instance.setAnyTemplate(); //terrain is irrelevant for monsters, but monsters need some template now
+	instance.setAnyTemplate(zone.getRand()); //terrain is irrelevant for monsters, but monsters need some template now
 
 	//Fix HoTA monsters with offset template
 	auto visitableOffset = instance.object().getVisitableOffset();

+ 1 - 1
lib/rmg/modificators/RiverPlacer.cpp

@@ -397,7 +397,7 @@ void RiverPlacer::connectRiver(const int3 & tile)
 				{
 					auto * obj = handler->create(templ);
 					rmg::Object deltaObj(*obj, deltaPositions[pos]);
-					deltaObj.finalize(map);
+					deltaObj.finalize(map, zone.getRand());
 				}
 			}
 		}

+ 1 - 1
lib/rmg/modificators/TownPlacer.cpp

@@ -140,7 +140,7 @@ int3 TownPlacer::placeMainTown(ObjectManager & manager, CGTownInstance & town)
 {
 	//towns are big objects and should be centered around visitable position
 	rmg::Object rmgObject(town);
-	rmgObject.setTemplate(zone.getTerrainType());
+	rmgObject.setTemplate(zone.getTerrainType(), zone.getRand());
 
 	int3 position(-1, -1, -1);
 	{

+ 2 - 2
lib/rmg/modificators/WaterProxy.cpp

@@ -254,7 +254,7 @@ bool WaterProxy::placeBoat(Zone & land, const Lake & lake, bool createRoad, Rout
 	auto * boat = dynamic_cast<CGBoat *>(VLC->objtypeh->getHandlerFor(Obj::BOAT, *RandomGeneratorUtil::nextItem(sailingBoatTypes, zone.getRand()))->create());
 
 	rmg::Object rmgObject(*boat);
-	rmgObject.setTemplate(zone.getTerrainType());
+	rmgObject.setTemplate(zone.getTerrainType(), zone.getRand());
 
 	auto waterAvailable = zone.areaPossible() + zone.freePaths();
 	rmg::Area coast = lake.neighbourZones.at(land.getId()); //having land tiles
@@ -319,7 +319,7 @@ bool WaterProxy::placeShipyard(Zone & land, const Lake & lake, si32 guard, bool
 	shipyard->tempOwner = PlayerColor::NEUTRAL;
 	
 	rmg::Object rmgObject(*shipyard);
-	rmgObject.setTemplate(land.getTerrainType());
+	rmgObject.setTemplate(land.getTerrainType(), zone.getRand());
 	bool guarded = manager->addGuard(rmgObject, guard);
 	
 	auto waterAvailable = zone.areaPossible() + zone.freePaths();