Laserlicht пре 1 година
родитељ
комит
e505aab29a

+ 58 - 14
client/lobby/CSelectionBase.cpp

@@ -403,25 +403,35 @@ PvPBox::PvPBox(const Rect & rect)
 	backgroundTexture->playerColored(PlayerColor(1));
 	backgroundBorder = std::make_shared<TransparentFilledRectangle>(Rect(0, 0, rect.w, rect.h), ColorRGBA(0, 0, 0, 64), ColorRGBA(96, 96, 96, 255), 1);
 
-	factionselector = std::make_shared<FactionSelector>(Point(5, 3));
+	factionSelector = std::make_shared<FactionSelector>(Point(5, 3));
 
-	buttonFlipCoin = std::make_shared<CButton>(Point(203, 6), AnimationPath::builtin("GSPBUT2.DEF"), CButton::tooltip("flip coin"), [](){
+	auto getBannedTowns = [this](){
+		std::vector<FactionID> bannedTowns;
+		for(auto & town : factionSelector->townsEnabled)
+			if(!town.second)
+				bannedTowns.push_back(town.first);
+		return bannedTowns;
+	};
+
+	buttonFlipCoin = std::make_shared<CButton>(Point(190, 6), AnimationPath::builtin("GSPBUT2.DEF"), CButton::tooltip("flip coin"), [](){
 		LobbyPvPAction lpa;
 		lpa.action = LobbyPvPAction::COIN;
 		CSH->sendLobbyPack(lpa);
 	}, EShortcut::NONE);
 	buttonFlipCoin->setTextOverlay("Flip coin2", EFonts::FONT_SMALL, Colors::WHITE);
 
-	buttonRandomTown = std::make_shared<CButton>(Point(203, 31), AnimationPath::builtin("GSPBUT2.DEF"), CButton::tooltip("random town"), [](){
+	buttonRandomTown = std::make_shared<CButton>(Point(190, 31), AnimationPath::builtin("GSPBUT2.DEF"), CButton::tooltip("random town"), [getBannedTowns](){
 		LobbyPvPAction lpa;
 		lpa.action = LobbyPvPAction::RANDOM_TOWN;
+		lpa.bannedTowns = getBannedTowns();
 		CSH->sendLobbyPack(lpa);
 	}, EShortcut::NONE);
 	buttonRandomTown->setTextOverlay("random town", EFonts::FONT_SMALL, Colors::WHITE);
 
-	buttonRandomTownVs = std::make_shared<CButton>(Point(203, 56), AnimationPath::builtin("GSPBUT2.DEF"), CButton::tooltip("random town vs"), [](){
+	buttonRandomTownVs = std::make_shared<CButton>(Point(190, 56), AnimationPath::builtin("GSPBUT2.DEF"), CButton::tooltip("random town vs"), [getBannedTowns](){
 		LobbyPvPAction lpa;
 		lpa.action = LobbyPvPAction::RANDOM_TOWN_VS;
+		lpa.bannedTowns = getBannedTowns();
 		CSH->sendLobbyPack(lpa);
 	}, EShortcut::NONE);
 	buttonRandomTownVs->setTextOverlay("random town vs", EFonts::FONT_SMALL, Colors::WHITE);
@@ -433,20 +443,46 @@ FactionSelector::FactionSelector(const Point & loc)
 	pos += loc;
 	setRedrawParent(true);
 
+	int count = 0;
+	CGI->factions()->forEach([this, &count](const Faction *entity, bool &stop){
+		if(!entity->hasTown())
+			return;
+		townsEnabled[entity->getFaction()] = true;
+		count++;
+	});
+
+	auto divisionRoundUp = [](int x, int y){ return (x + (y - 1)) / y; };
+	slider = std::make_shared<CSlider>(Point(144, 0), 96, std::bind(&FactionSelector::sliderMove, this, _1), 3, divisionRoundUp(count, 3), 0, Orientation::VERTICAL, CSlider::BLUE);
+	slider->setPanningStep(24);
+	slider->setScrollBounds(Rect(-144, 0, slider->pos.x - pos.x + slider->pos.w, slider->pos.h));
+
+	updateListItems();
+}
+
+void FactionSelector::updateListItems()
+{
+	OBJ_CONSTRUCTION;
+	int line = slider->getValue();
+	
+	towns.clear();
+	townsArea.clear();
+
 	int x = 0, y = 0;
-	CGI->factions()->forEach([this, &x, &y](const Faction *entity, bool &stop){
+	CGI->factions()->forEach([this, &x, &y, line](const Faction *entity, bool &stop){
 		if(!entity->hasTown())
 			return;
 
-		FactionID factionID = entity->getFaction();
-		auto getImageIndex = [](FactionID factionID, bool enabled){ return (*CGI->townh)[factionID]->town->clientInfo.icons[true][!enabled] + 2; }; 
-		towns[factionID] = std::make_shared<CAnimImage>(AnimationPath::builtin("ITPA"), getImageIndex(factionID, true), 0, 48 * x, 32 * y);
-		townsArea[factionID] = std::make_shared<LRClickableArea>(Rect(48 * x, 32 * y, 48, 32), [this, getImageIndex, factionID](){
-			townsEnabled[factionID] = !townsEnabled[factionID];
-			towns[factionID]->setFrame(getImageIndex(factionID, townsEnabled[factionID]));
-			redraw();
-		});
-		townsEnabled[factionID] = true;
+		if(y >= line && (y - line) < 3)
+			{
+			FactionID factionID = entity->getFaction();
+			auto getImageIndex = [](FactionID factionID, bool enabled){ return (*CGI->townh)[factionID]->town->clientInfo.icons[true][!enabled] + 2; }; 
+			towns[factionID] = std::make_shared<CAnimImage>(AnimationPath::builtin("ITPA"), getImageIndex(factionID, townsEnabled[factionID]), 0, 48 * x, 32 * (y - line));
+			townsArea[factionID] = std::make_shared<LRClickableArea>(Rect(48 * x, 32 * (y - line), 48, 32), [this, getImageIndex, factionID](){
+				townsEnabled[factionID] = !townsEnabled[factionID];
+				towns[factionID]->setFrame(getImageIndex(factionID, townsEnabled[factionID]));
+				redraw();
+			});
+		}
 
 		if (x < 2)
 			x++;
@@ -458,6 +494,14 @@ FactionSelector::FactionSelector(const Point & loc)
 	});
 }
 
+void FactionSelector::sliderMove(int slidPos)
+{
+	if(!slider)
+		return; // ignore spurious call when slider is being created
+	updateListItems();
+	redraw();
+}
+
 CFlagBox::CFlagBox(const Rect & rect)
 	: CIntObject(SHOW_POPUP)
 {

+ 6 - 2
client/lobby/CSelectionBase.h

@@ -148,7 +148,7 @@ class PvPBox : public CIntObject
 	std::shared_ptr<FilledTexturePlayerColored> backgroundTexture;
 	std::shared_ptr<TransparentFilledRectangle> backgroundBorder;
 	
-	std::shared_ptr<FactionSelector> factionselector;
+	std::shared_ptr<FactionSelector> factionSelector;
 
 	std::shared_ptr<CButton> buttonFlipCoin;
 	std::shared_ptr<CButton> buttonRandomTown;
@@ -161,10 +161,14 @@ class FactionSelector : public CIntObject
 {
 	std::map<FactionID, std::shared_ptr<CAnimImage>> towns;
 	std::map<FactionID, std::shared_ptr<LRClickableArea>> townsArea;
-	std::map<FactionID, bool> townsEnabled;
 	std::shared_ptr<CSlider> slider;
 
+	void sliderMove(int slidPos);
+	void updateListItems();
+
 public:
+	std::map<FactionID, bool> townsEnabled;
+
 	FactionSelector(const Point & loc);
 };
 

+ 2 - 0
lib/networkPacks/PacksForLobby.h

@@ -348,6 +348,7 @@ struct DLL_LINKAGE LobbyPvPAction : public CLobbyPackToServer
 	enum EAction : ui8 {
 		NONE, COIN, RANDOM_TOWN, RANDOM_TOWN_VS
 	} action = NONE;
+	std::vector<FactionID> bannedTowns;
 
 
 	void visitTyped(ICPackVisitor & visitor) override;
@@ -355,6 +356,7 @@ struct DLL_LINKAGE LobbyPvPAction : public CLobbyPackToServer
 	template <typename Handler> void serialize(Handler &h)
 	{
 		h & action;
+		h & bannedTowns;
 	}
 };
 

+ 17 - 10
server/NetPacksLobbyServer.cpp

@@ -372,25 +372,32 @@ void ApplyOnServerNetPackVisitor::visitLobbyForceSetPlayer(LobbyForceSetPlayer &
 
 void ApplyOnServerNetPackVisitor::visitLobbyPvPAction(LobbyPvPAction & pack)
 {
-	std::set<FactionID> allowedFactions;
-	for(auto & player : srv.mi->mapHeader->players)
-	{
-		std::set<FactionID> tmpAllowedFactions = player.allowedFactions;
-		std::set_union(std::begin(tmpAllowedFactions), std::end(tmpAllowedFactions), std::begin(allowedFactions), std::end(allowedFactions), std::inserter(allowedFactions, std::begin(allowedFactions)));
-	}
+	std::vector<FactionID> allowedFactions;
+
+	VLC->townh->forEach([pack, &allowedFactions](const Faction *entity, bool &stop){
+		if(!entity->hasTown())
+			return;
+		if(std::find(pack.bannedTowns.begin(), pack.bannedTowns.end(), entity->getId()) == pack.bannedTowns.end()) {
+			allowedFactions.push_back(entity->getId());
+		}
+	});
 
-	std::vector<FactionID> randomFactions;
-	std::sample(allowedFactions.begin(), allowedFactions.end(), std::back_inserter(randomFactions), 2, std::mt19937{std::random_device{}()});
+	std::vector<FactionID> randomFaction1;
+	std::sample(allowedFactions.begin(), allowedFactions.end(), std::back_inserter(randomFaction1), 1, std::mt19937{std::random_device{}()});
+	std::vector<FactionID> randomFaction2;
+	std::sample(allowedFactions.begin(), allowedFactions.end(), std::back_inserter(randomFaction2), 1, std::mt19937{std::random_device{}()});
 
 	switch(pack.action) {
 		case LobbyPvPAction::COIN:
 			srv.announceTxt("Coin - " + std::to_string(std::rand()%2));
 			break;
 		case LobbyPvPAction::RANDOM_TOWN:
-			srv.announceTxt("Faction - " + VLC->townh->getById(randomFactions[0])->getNameTranslated());
+			if(allowedFactions.size())
+				srv.announceTxt("Faction - " + VLC->townh->getById(randomFaction1[0])->getNameTranslated());
 			break;
 		case LobbyPvPAction::RANDOM_TOWN_VS:
-			srv.announceTxt("Factions - " + VLC->townh->getById(randomFactions[0])->getNameTranslated() + " vs. " + VLC->townh->getById(randomFactions[randomFactions.size() > 1 ? 1 : 0])->getNameTranslated());
+			if(allowedFactions.size())
+				srv.announceTxt("Factions - " + VLC->townh->getById(randomFaction1[0])->getNameTranslated() + " vs. " + VLC->townh->getById(randomFaction2[0])->getNameTranslated());
 			break;
 	}
 	result = true;