Browse Source

Fix rmg generation if player list is not continuous

Ivan Savenko 1 year ago
parent
commit
2d0bd94135

+ 11 - 5
lib/rmg/CMapGenOptions.cpp

@@ -284,9 +284,12 @@ void CMapGenOptions::resetPlayersMap()
 
 	while (players.size() > realPlayersCnt)
 	{
-		while (eraseLastPlayer(EPlayerType::AI));
-		while (eraseLastPlayer(EPlayerType::COMP_ONLY));
-		while (eraseLastPlayer(EPlayerType::HUMAN));
+		if (eraseLastPlayer(EPlayerType::AI))
+			continue;
+		if (eraseLastPlayer(EPlayerType::COMP_ONLY))
+			continue;
+		if (eraseLastPlayer(EPlayerType::HUMAN))
+			continue;
 	}
 
 	//First colors from the list are assigned to human players, then to CPU players
@@ -503,8 +506,9 @@ void CMapGenOptions::finalize(CRandomGenerator & rand)
 	if (getHumanOrCpuPlayerCount() == RANDOM_SIZE)
 	{
 		auto possiblePlayers = mapTemplate->getPlayers().getNumbers();
+		int requiredPlayers = countHumanPlayers() + countCompOnlyPlayers();
 		//ignore all non-randomized players, make sure these players will not be missing after roll
-		possiblePlayers.erase(possiblePlayers.begin(), possiblePlayers.lower_bound(countHumanPlayers() + countCompOnlyPlayers()));
+		possiblePlayers.erase(possiblePlayers.begin(), possiblePlayers.lower_bound(requiredPlayers));
 
 		vstd::erase_if(possiblePlayers, [maxPlayers](int i)
 		{
@@ -598,7 +602,9 @@ void CMapGenOptions::updatePlayers()
 	{
 		auto it = itrev;
 		--it;
-		if (players.size() == getHumanOrCpuPlayerCount()) break;
+		if (players.size() == getHumanOrCpuPlayerCount())
+			break;
+
 		if(it->second.getPlayerType() != EPlayerType::HUMAN)
 		{
 			players.erase(it);

+ 2 - 2
lib/rmg/CZonePlacer.cpp

@@ -454,9 +454,9 @@ void CZonePlacer::prepareZones(TZoneMap &zones, TZoneVector &zonesVector, const
 				auto player = PlayerColor(*owner - 1);
 				auto playerSettings = map.getMapGenOptions().getPlayersSettings();
 				FactionID faction = FactionID::RANDOM;
-				if (vstd::contains(playerSettings, player))
+				if (playerSettings.size() > player)
 				{
-					faction = playerSettings[player].getStartingTown();
+					faction = std::next(playerSettings.begin(), player)->second.getStartingTown();
 				}
 				else
 				{

+ 9 - 6
lib/rmg/modificators/TownPlacer.cpp

@@ -54,12 +54,14 @@ void TownPlacer::placeTowns(ObjectManager & manager)
 		//set zone types to player faction, generate main town
 		logGlobal->info("Preparing playing zone");
 		int player_id = *zone.getOwner() - 1;
-		auto& playerInfo = map.getPlayer(player_id);
-		PlayerColor player(player_id);
-		if(playerInfo.canAnyonePlay())
+		const auto & playerSettings = map.getMapGenOptions().getPlayersSettings();
+		PlayerColor player;
+
+		if (playerSettings.size() > player_id)
 		{
-			player = PlayerColor(player_id);
-			zone.setTownType(map.getMapGenOptions().getPlayersSettings().find(player)->second.getStartingTown());
+			const auto & currentPlayerSettings = std::next(playerSettings.begin(), player_id);
+			player = currentPlayerSettings->first;
+			zone.setTownType(currentPlayerSettings->second.getStartingTown());
 			
 			if(zone.getTownType() == FactionID::RANDOM)
 				zone.setTownType(getRandomTownType(true));
@@ -89,11 +91,12 @@ void TownPlacer::placeTowns(ObjectManager & manager)
 		//register MAIN town of zone only
 		map.registerZone(town->getFaction());
 		
-		if(playerInfo.canAnyonePlay()) //configure info for owning player
+		if(player.isValidPlayer()) //configure info for owning player
 		{
 			logGlobal->trace("Fill player info %d", player_id);
 			
 			// Update player info
+			auto & playerInfo = map.getPlayer(player.getNum());
 			playerInfo.allowedFactions.clear();
 			playerInfo.allowedFactions.insert(zone.getTownType());
 			playerInfo.hasMainTown = true;

+ 4 - 0
server/CVCMIServer.cpp

@@ -662,6 +662,10 @@ void CVCMIServer::updateAndPropagateLobbyState()
 			{
 				si->mapGenOptions->setPlayerTypeForStandardPlayer(pset.color, EPlayerType::HUMAN);
 			}
+			else
+			{
+				si->mapGenOptions->setPlayerTypeForStandardPlayer(pset.color, EPlayerType::AI);
+			}
 		}
 	}