Browse Source

Fixed: Advanced options window issues

Dmitry Orlov 4 years ago
parent
commit
a65feb29f5

+ 2 - 1
client/lobby/CLobbyScreen.cpp

@@ -139,11 +139,12 @@ void CLobbyScreen::startScenario(bool allowOnlyAI)
 	{
 		(void)e;	// unused
 		// You must position yourself prior to starting the game.
-		CInfoWindow::showYesNoDialog(std::ref(CGI->generaltexth->allTexts[530]), CInfoWindow::TCompsInfo(), 0, std::bind(&CLobbyScreen::startScenario, this, true), PlayerColor(1));
+		CInfoWindow::showInfoDialog(std::ref(CGI->generaltexth->allTexts[530]), CInfoWindow::TCompsInfo(), PlayerColor(1));
 	}
 	catch(ExceptionNoTemplate & e)
 	{
 		(void)e; // unused
+		// Could not create a random map that fits current choices.
 		CInfoWindow::showInfoDialog(std::ref(CGI->generaltexth->allTexts[751]), CInfoWindow::TCompsInfo(), PlayerColor(1));
 	}
 	catch(...)

+ 20 - 5
client/lobby/OptionsTab.cpp

@@ -33,7 +33,7 @@
 #include "../../lib/mapping/CMap.h"
 #include "../../lib/mapping/CMapInfo.h"
 
-OptionsTab::OptionsTab()
+OptionsTab::OptionsTab() : humanPlayers(0)
 {
 	recActions = 0;
 	OBJ_CONSTRUCTION;
@@ -57,11 +57,15 @@ OptionsTab::OptionsTab()
 void OptionsTab::recreate()
 {
 	entries.clear();
+	humanPlayers = 0;
 
 	OBJ_CONSTRUCTION_CAPTURING_ALL_NO_DISPOSE;
 	for(auto & pInfo : SEL->getStartInfo()->playerInfos)
 	{
-		entries.insert(std::make_pair(pInfo.first, std::make_shared<PlayerOptionsEntry>(pInfo.second)));
+		if(pInfo.second.isControlledByHuman())
+			humanPlayers++;
+
+		entries.insert(std::make_pair(pInfo.first, std::make_shared<PlayerOptionsEntry>(pInfo.second, * this)));
 	}
 
 	if(sliderTurnDuration)
@@ -437,8 +441,8 @@ void OptionsTab::SelectedBox::clickRight(tribool down, bool previousState)
 	}
 }
 
-OptionsTab::PlayerOptionsEntry::PlayerOptionsEntry(const PlayerSettings & S)
-	: pi(SEL->getPlayerInfo(S.color.getNum())), s(S)
+OptionsTab::PlayerOptionsEntry::PlayerOptionsEntry(const PlayerSettings & S, const OptionsTab & parent)
+	: pi(SEL->getPlayerInfo(S.color.getNum())), s(S), parentTab(parent)
 {
 	OBJ_CONSTRUCTION;
 	defActions |= SHARE_POS;
@@ -493,7 +497,12 @@ OptionsTab::PlayerOptionsEntry::PlayerOptionsEntry(const PlayerSettings & S)
 
 	if(SEL->screenType != ESelectionScreen::scenarioInfo && SEL->getPlayerInfo(s.color.getNum()).canHumanPlay)
 	{
-		flag = std::make_shared<CButton>(Point(-43, 2), flags[s.color.getNum()], CGI->generaltexth->zelp[180], std::bind(&IServerAPI::setPlayer, CSH, s.color));
+		flag = std::make_shared<CButton>(
+			Point(-43, 2),
+			flags[s.color.getNum()],
+			CGI->generaltexth->zelp[180],
+			std::bind(&OptionsTab::onSetPlayerClicked, &parentTab, s)
+		);
 		flag->hoverable = true;
 		flag->block(CSH->isGuest());
 	}
@@ -505,6 +514,12 @@ OptionsTab::PlayerOptionsEntry::PlayerOptionsEntry(const PlayerSettings & S)
 	bonus = std::make_shared<SelectedBox>(Point(271, 2), s, BONUS);
 }
 
+void OptionsTab::onSetPlayerClicked(const PlayerSettings & ps) const
+{
+	if(ps.isControlledByAI() || humanPlayers > 1)
+		CSH->setPlayer(ps.color);
+}
+
 void OptionsTab::PlayerOptionsEntry::hideUnavailableButtons()
 {
 	if(!buttonTownLeft)

+ 6 - 1
client/lobby/OptionsTab.h

@@ -31,6 +31,7 @@ class OptionsTab : public CIntObject
 
 	std::shared_ptr<CLabel> labelPlayerTurnDuration;
 	std::shared_ptr<CLabel> labelTurnDurationValue;
+	ui8 humanPlayers;
 
 public:
 	enum SelType
@@ -115,8 +116,11 @@ public:
 		std::shared_ptr<SelectedBox> bonus;
 		enum {HUMAN_OR_CPU, HUMAN, CPU} whoCanPlay;
 
-		PlayerOptionsEntry(const PlayerSettings & S);
+		PlayerOptionsEntry(const PlayerSettings & S, const OptionsTab & parentTab);
 		void hideUnavailableButtons();
+
+	private:
+		const OptionsTab & parentTab;
 	};
 
 	std::shared_ptr<CSlider> sliderTurnDuration;
@@ -124,4 +128,5 @@ public:
 
 	OptionsTab();
 	void recreate();
+	void onSetPlayerClicked(const PlayerSettings & ps) const;
 };

+ 13 - 4
lib/mapping/MapFormatH3M.cpp

@@ -220,15 +220,24 @@ void CMapLoaderH3M::readPlayerInfo()
 		else
 			totalFactions--; //exclude conflux for ROE
 
-		for(int fact = 0; fact < totalFactions; ++fact)
+		const bool isFactionRandom = mapHeader->players[i].isFactionRandom = reader.readBool();
+		const ui16 allFactionsMask = (mapHeader->version == EMapFormat::ROE)
+			? 0b1111111
+			: 0b11111111;
+		const bool allFactionsAllowed = mapHeader->version == EMapFormat::VCMI
+			|| (isFactionRandom && ((allowedFactions & allFactionsMask) == allFactionsMask));
+
+		if(!allFactionsAllowed)
 		{
-			if(!(allowedFactions & (1 << fact)))
+			mapHeader->players[i].allowedFactions.clear();
+
+			for(int fact = 0; fact < totalFactions; ++fact)
 			{
-				mapHeader->players[i].allowedFactions.erase(fact);
+				if(allowedFactions & (1 << fact))
+					mapHeader->players[i].allowedFactions.insert(fact);
 			}
 		}
 
-		mapHeader->players[i].isFactionRandom = reader.readBool();
 		mapHeader->players[i].hasMainTown = reader.readBool();
 		if(mapHeader->players[i].hasMainTown)
 		{