|  | @@ -138,8 +138,7 @@ CRmgTemplateZone::CRmgTemplateZone() :
 | 
	
		
			
				|  |  |  	matchTerrainToTown(true),
 | 
	
		
			
				|  |  |  	townType(ETownType::NEUTRAL),
 | 
	
		
			
				|  |  |  	terrainType (ETerrainType::GRASS),
 | 
	
		
			
				|  |  | -	zoneMonsterStrength(EMonsterStrength::ZONE_NORMAL),
 | 
	
		
			
				|  |  | -	totalDensity(0)
 | 
	
		
			
				|  |  | +	zoneMonsterStrength(EMonsterStrength::ZONE_NORMAL)
 | 
	
		
			
				|  |  |  {
 | 
	
		
			
				|  |  |  	terrainTypes = getDefaultTerrainTypes();
 | 
	
		
			
				|  |  |  }
 | 
	
	
		
			
				|  | @@ -303,16 +302,6 @@ void CRmgTemplateZone::setMonsterStrength (EMonsterStrength::EMonsterStrength va
 | 
	
		
			
				|  |  |  	zoneMonsterStrength = val;
 | 
	
		
			
				|  |  |  }
 | 
	
		
			
				|  |  |  
 | 
	
		
			
				|  |  | -void CRmgTemplateZone::setTotalDensity (ui16 val)
 | 
	
		
			
				|  |  | -{
 | 
	
		
			
				|  |  | -	totalDensity = val;
 | 
	
		
			
				|  |  | -}
 | 
	
		
			
				|  |  | -
 | 
	
		
			
				|  |  | -ui16 CRmgTemplateZone::getTotalDensity () const
 | 
	
		
			
				|  |  | -{
 | 
	
		
			
				|  |  | -	return totalDensity;
 | 
	
		
			
				|  |  | -}
 | 
	
		
			
				|  |  | -
 | 
	
		
			
				|  |  |  void CRmgTemplateZone::addTreasureInfo(CTreasureInfo & info)
 | 
	
		
			
				|  |  |  {
 | 
	
		
			
				|  |  |  	treasureInfo.push_back(info);
 | 
	
	
		
			
				|  | @@ -420,7 +409,11 @@ void CRmgTemplateZone::fractalize(CMapGenerator* gen)
 | 
	
		
			
				|  |  |  	std::set<int3> tilesToIgnore; //will be erased in this iteration
 | 
	
		
			
				|  |  |  
 | 
	
		
			
				|  |  |  	//the more treasure density, the greater distance between paths. Scaling is experimental.
 | 
	
		
			
				|  |  | +	int totalDensity = 0;
 | 
	
		
			
				|  |  | +	for (auto ti : treasureInfo)
 | 
	
		
			
				|  |  | +		totalDensity =+ ti.density;
 | 
	
		
			
				|  |  |  	const float minDistance = std::sqrt(totalDensity * 3);
 | 
	
		
			
				|  |  | +
 | 
	
		
			
				|  |  |  	for (auto tile : tileinfo)
 | 
	
		
			
				|  |  |  	{
 | 
	
		
			
				|  |  |  		if (gen->isFree(tile))
 | 
	
	
		
			
				|  | @@ -686,7 +679,7 @@ bool CRmgTemplateZone::addMonster(CMapGenerator* gen, int3 &pos, si32 strength,
 | 
	
		
			
				|  |  |  	return true;
 | 
	
		
			
				|  |  |  }
 | 
	
		
			
				|  |  |  
 | 
	
		
			
				|  |  | -bool CRmgTemplateZone::createTreasurePile (CMapGenerator* gen, int3 &pos, float minDistance)
 | 
	
		
			
				|  |  | +bool CRmgTemplateZone::createTreasurePile(CMapGenerator* gen, int3 &pos, float minDistance, const CTreasureInfo& treasureInfo)
 | 
	
		
			
				|  |  |  {
 | 
	
		
			
				|  |  |  	CTreasurePileInfo info;
 | 
	
		
			
				|  |  |  
 | 
	
	
		
			
				|  | @@ -695,25 +688,9 @@ bool CRmgTemplateZone::createTreasurePile (CMapGenerator* gen, int3 &pos, float
 | 
	
		
			
				|  |  |  	int3 guardPos (-1,-1,-1);
 | 
	
		
			
				|  |  |  	info.nextTreasurePos = pos;
 | 
	
		
			
				|  |  |  
 | 
	
		
			
				|  |  | -	//default values
 | 
	
		
			
				|  |  | -	int maxValue = 5000;
 | 
	
		
			
				|  |  | -	int minValue = 1500;
 | 
	
		
			
				|  |  | -
 | 
	
		
			
				|  |  | -	if (treasureInfo.size())
 | 
	
		
			
				|  |  | -	{
 | 
	
		
			
				|  |  | -		//roulette wheel
 | 
	
		
			
				|  |  | -		int r = gen->rand.nextInt (1, totalDensity);
 | 
	
		
			
				|  |  | +	int maxValue = treasureInfo.max;
 | 
	
		
			
				|  |  | +	int minValue = treasureInfo.min;
 | 
	
		
			
				|  |  |  
 | 
	
		
			
				|  |  | -		for (auto t : treasureInfo)
 | 
	
		
			
				|  |  | -		{
 | 
	
		
			
				|  |  | -			if (r <= t.threshold)
 | 
	
		
			
				|  |  | -			{
 | 
	
		
			
				|  |  | -				maxValue = t.max;
 | 
	
		
			
				|  |  | -				minValue = t.min;
 | 
	
		
			
				|  |  | -				break;
 | 
	
		
			
				|  |  | -			}
 | 
	
		
			
				|  |  | -		}
 | 
	
		
			
				|  |  | -	}
 | 
	
		
			
				|  |  |  	ui32 desiredValue = gen->rand.nextInt(minValue, maxValue);
 | 
	
		
			
				|  |  |  	//quantize value to let objects with value equal to max spawn too
 | 
	
		
			
				|  |  |  
 | 
	
	
		
			
				|  | @@ -1194,30 +1171,43 @@ bool CRmgTemplateZone::createRequiredObjects(CMapGenerator* gen)
 | 
	
		
			
				|  |  |  
 | 
	
		
			
				|  |  |  void CRmgTemplateZone::createTreasures(CMapGenerator* gen)
 | 
	
		
			
				|  |  |  {
 | 
	
		
			
				|  |  | -	//treasure density is proportional to map siz,e but must be scaled bakc to map size
 | 
	
		
			
				|  |  | -	//also, normalize it to zone count - higher count means relative smaller zones
 | 
	
		
			
				|  |  | +	auto valueComparator = [](const CTreasureInfo & lhs, const CTreasureInfo & rhs) -> bool
 | 
	
		
			
				|  |  | +	{
 | 
	
		
			
				|  |  | +		return lhs.max > rhs.max;
 | 
	
		
			
				|  |  | +	};
 | 
	
		
			
				|  |  |  
 | 
	
		
			
				|  |  | -	//this is squared distance for optimization purposes
 | 
	
		
			
				|  |  | -	const double minDistance = std::max<float>((600.f * size * size * gen->getZones().size()) /
 | 
	
		
			
				|  |  | -		(gen->mapGenOptions->getWidth() * gen->mapGenOptions->getHeight() * totalDensity * (gen->map->twoLevel ? 2 : 1)), 2);
 | 
	
		
			
				|  |  | -	//distance lower than 2 causes objects to overlap and crash
 | 
	
		
			
				|  |  | +	//place biggest treasures first at large distance, place smaller ones inbetween
 | 
	
		
			
				|  |  | +	boost::sort(treasureInfo, valueComparator);
 | 
	
		
			
				|  |  |  
 | 
	
		
			
				|  |  | -	do {
 | 
	
		
			
				|  |  | -		
 | 
	
		
			
				|  |  | -		//optimization - don't check tiles which are not allowed
 | 
	
		
			
				|  |  | -		vstd::erase_if (possibleTiles, [gen](const int3 &tile) -> bool
 | 
	
		
			
				|  |  | -		{
 | 
	
		
			
				|  |  | -			return !gen->isPossible(tile);
 | 
	
		
			
				|  |  | -		});
 | 
	
		
			
				|  |  | +	int totalDensity = 0;
 | 
	
		
			
				|  |  | +	for (auto t : treasureInfo)
 | 
	
		
			
				|  |  | +	{
 | 
	
		
			
				|  |  | +		totalDensity += t.density;
 | 
	
		
			
				|  |  |  
 | 
	
		
			
				|  |  | -		int3 pos;
 | 
	
		
			
				|  |  | -		if ( ! findPlaceForTreasurePile(gen, minDistance, pos))		
 | 
	
		
			
				|  |  | -		{
 | 
	
		
			
				|  |  | -			break;
 | 
	
		
			
				|  |  | -		}
 | 
	
		
			
				|  |  | -		createTreasurePile (gen, pos, minDistance);
 | 
	
		
			
				|  |  | +		//treasure density is inversely proportional to zone size but must be scaled back to map size
 | 
	
		
			
				|  |  | +		//also, normalize it to zone count - higher count means relatively smaller zones
 | 
	
		
			
				|  |  | +
 | 
	
		
			
				|  |  | +		//this is squared distance for optimization purposes
 | 
	
		
			
				|  |  | +		const double minDistance = std::max<float>((600.f * size * size * gen->getZones().size()) /
 | 
	
		
			
				|  |  | +			(gen->mapGenOptions->getWidth() * gen->mapGenOptions->getHeight() * totalDensity * (gen->map->twoLevel ? 2 : 1)), 2);
 | 
	
		
			
				|  |  | +		//distance lower than 2 causes objects to overlap and crash
 | 
	
		
			
				|  |  |  
 | 
	
		
			
				|  |  | -	} while(true);
 | 
	
		
			
				|  |  | +		do {
 | 
	
		
			
				|  |  | +			//optimization - don't check tiles which are not allowed
 | 
	
		
			
				|  |  | +			vstd::erase_if(possibleTiles, [gen](const int3 &tile) -> bool
 | 
	
		
			
				|  |  | +			{
 | 
	
		
			
				|  |  | +				return !gen->isPossible(tile);
 | 
	
		
			
				|  |  | +			});
 | 
	
		
			
				|  |  | +
 | 
	
		
			
				|  |  | +			int3 pos;
 | 
	
		
			
				|  |  | +			if (!findPlaceForTreasurePile(gen, minDistance, pos))
 | 
	
		
			
				|  |  | +			{
 | 
	
		
			
				|  |  | +				break;
 | 
	
		
			
				|  |  | +			}
 | 
	
		
			
				|  |  | +			createTreasurePile(gen, pos, minDistance, t);
 | 
	
		
			
				|  |  | +
 | 
	
		
			
				|  |  | +		} while (true);
 | 
	
		
			
				|  |  | +	}
 | 
	
		
			
				|  |  |  }
 | 
	
		
			
				|  |  |  
 | 
	
		
			
				|  |  |  void CRmgTemplateZone::createObstacles(CMapGenerator* gen)
 |