1 /*
2 * This file is part of Dune Legacy.
3 *
4 * Dune Legacy is free software: you can redistribute it and/or modify
5 * it under the terms of the GNU General Public License as published by
6 * the Free Software Foundation, either version 2 of the License, or
7 * (at your option) any later version.
8 *
9 * Dune Legacy is distributed in the hope that it will be useful,
10 * but WITHOUT ANY WARRANTY; without even the implied warranty of
11 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
12 * GNU General Public License for more details.
13 *
14 * You should have received a copy of the GNU General Public License
15 * along with Dune Legacy. If not, see <http://www.gnu.org/licenses/>.
16 */
17
18 #include <Menu/CustomGamePlayers.h>
19
20 #include <FileClasses/GFXManager.h>
21 #include <FileClasses/TextManager.h>
22 #include <FileClasses/INIFile.h>
23
24 #include <Network/NetworkManager.h>
25
26 #include <GUI/Spacer.h>
27 #include <GUI/GUIStyle.h>
28 #include <GUI/MsgBox.h>
29 #include <GUI/dune/DuneStyle.h>
30
31 #include <players/PlayerFactory.h>
32
33 #include <misc/fnkdat.h>
34 #include <misc/FileSystem.h>
35 #include <misc/draw_util.h>
36 #include <misc/string_util.h>
37 #include <misc/IMemoryStream.h>
38
39 #include <INIMap/INIMapPreviewCreator.h>
40
41 #include <sand.h>
42 #include <globals.h>
43
44
45 #define PLAYER_HUMAN 0
46 #define PLAYER_OPEN -1
47 #define PLAYER_CLOSED -2
48
49
CustomGamePlayers(const GameInitSettings & newGameInitSettings,bool server,bool LANServer)50 CustomGamePlayers::CustomGamePlayers(const GameInitSettings& newGameInitSettings, bool server, bool LANServer)
51 : MenuBase(), gameInitSettings(newGameInitSettings), bServer(server), bLANServer(LANServer), startGameTime(0), brainEqHumanSlot(-1) {
52
53 // set up window
54 SDL_Texture *pBackground = pGFXManager->getUIGraphic(UI_MenuBackground);
55 setBackground(pBackground, false);
56 resize(getTextureSize(pBackground));
57
58 setWindowWidget(&windowWidget);
59
60 windowWidget.addWidget(&mainVBox, Point(24,23), Point(getRendererWidth() - 48, getRendererHeight() - 32));
61
62 captionLabel.setText(getBasename(gameInitSettings.getFilename(), true));
63 captionLabel.setAlignment(Alignment_HCenter);
64 mainVBox.addWidget(&captionLabel, 24);
65 mainVBox.addWidget(VSpacer::create(24));
66
67 mainVBox.addWidget(Spacer::create(), 0.04);
68
69 mainVBox.addWidget(&mainHBox, 0.6);
70
71 mainHBox.addWidget(Spacer::create(), 0.05);
72 leftVBox.addWidget(Spacer::create(), 0.1);
73 leftVBox.addWidget(&playerListHBox);
74 playerListHBox.addWidget(Spacer::create(), 0.4);
75 playerListHBox.addWidget(&playerListVBox, 0.2);
76 playerListHBox.addWidget(Spacer::create(), 0.4);
77 mainHBox.addWidget(&leftVBox, 0.8);
78
79 mainHBox.addWidget(Spacer::create(), 0.05);
80
81 mainHBox.addWidget(HSpacer::create(8));
82
83 mainHBox.addWidget(&rightVBox, 180);
84 mainHBox.addWidget(Spacer::create(), 0.05);
85 minimap.setSurface( GUIStyle::getInstance().createButtonSurface(130,130,_("Choose map"), true, false), true);
86 rightVBox.addWidget(&minimap);
87
88 if(gameInitSettings.getGameType() == GameType::CustomGame || gameInitSettings.getGameType() == GameType::CustomMultiplayer) {
89 SDL_RWops* RWops = SDL_RWFromConstMem(gameInitSettings.getFiledata().c_str(), gameInitSettings.getFiledata().size());
90
91 std::shared_ptr<INIFile> map(new INIFile(RWops));
92 extractMapInfo(map);
93
94 SDL_RWclose(RWops);
95 } else if(gameInitSettings.getGameType() == GameType::LoadMultiplayer) {
96 IMemoryStream memStream(gameInitSettings.getFiledata().c_str(), gameInitSettings.getFiledata().size());
97
98 Uint32 magicNum = memStream.readUint32();
99 if(magicNum != SAVEMAGIC) {
100 SDL_Log("CustomGamePlayers: No valid savegame! Expected magic number %.8X, but got %.8X!", SAVEMAGIC, magicNum);
101 }
102
103 Uint32 savegameVersion = memStream.readUint32();
104 if (savegameVersion != SAVEGAMEVERSION) {
105 SDL_Log("CustomGamePlayers: No valid savegame! Expected savegame version %d, but got %d!", SAVEGAMEVERSION, savegameVersion);
106 }
107
108 memStream.readString(); // dune legacy version
109
110 // read gameInitSettings
111 GameInitSettings tmpGameInitSettings(memStream);
112
113 Uint32 numHouseInfo = memStream.readUint32();
114 for(Uint32 i=0;i<numHouseInfo;i++) {
115 houseInfoListSetup.push_back(GameInitSettings::HouseInfo(memStream));
116 }
117
118 SDL_RWops* RWops = SDL_RWFromConstMem(tmpGameInitSettings.getFiledata().c_str(), tmpGameInitSettings.getFiledata().size());
119
120 std::shared_ptr<INIFile> map(new INIFile(RWops));
121 extractMapInfo(map);
122
123 SDL_RWclose(RWops);
124
125 // adjust multiple players per house as this was not known before actually loading the saved game
126 gameInitSettings.setMultiplePlayersPerHouse(tmpGameInitSettings.isMultiplePlayersPerHouse());
127
128 // adjust numHouses to the actually used houses (which might be smaller than the houses on the map)
129 numHouses = houseInfoListSetup.size();
130 } else {
131 std::shared_ptr<INIFile> map(new INIFile(gameInitSettings.getFilename()));
132 extractMapInfo(map);
133 }
134
135 rightVBox.addWidget(VSpacer::create(10));
136 rightVBox.addWidget(&mapPropertiesHBox, 0.01);
137 mapPropertiesHBox.addWidget(&mapPropertyNamesVBox, 75);
138 mapPropertiesHBox.addWidget(&mapPropertyValuesVBox, 105);
139 mapPropertyNamesVBox.addWidget(Label::create(_("Size") + ":"));
140 mapPropertyValuesVBox.addWidget(&mapPropertySize);
141 mapPropertyNamesVBox.addWidget(Label::create(_("Players") + ":"));
142 mapPropertyValuesVBox.addWidget(&mapPropertyPlayers);
143 mapPropertyNamesVBox.addWidget(Label::create(_("Author") + ":"));
144 mapPropertyValuesVBox.addWidget(&mapPropertyAuthors);
145 mapPropertyNamesVBox.addWidget(Label::create(_("License") + ":"));
146 mapPropertyValuesVBox.addWidget(&mapPropertyLicense);
147 rightVBox.addWidget(Spacer::create());
148
149 mainVBox.addWidget(Spacer::create(), 0.04);
150
151 mainVBox.addWidget(&buttonHBox, 0.32);
152
153 buttonHBox.addWidget(HSpacer::create(70));
154
155 backButtonVBox.addWidget(Spacer::create());
156 backButton.setText(_("Back"));
157 backButton.setOnClick(std::bind(&CustomGamePlayers::onCancel, this));
158 backButtonVBox.addWidget(&backButton, 24);
159 backButtonVBox.addWidget(VSpacer::create(14));
160 buttonHBox.addWidget(&backButtonVBox, 0.1);
161
162 buttonHBox.addWidget(Spacer::create(), 0.0625);
163
164 chatTextView.setTextFont(FONT_STD10);
165 chatVBox.addWidget(&chatTextView, 0.77);
166 if(getRendererHeight() <= 600) {
167 chatTextBox.setTextFont(FONT_STD10);
168 }
169 chatTextBox.setOnReturn(std::bind(&CustomGamePlayers::onSendChatMessage, this));
170 chatVBox.addWidget(&chatTextBox, 0.2);
171 chatVBox.addWidget(Spacer::create(), 0.03);
172 buttonHBox.addWidget(&chatVBox, 0.675);
173
174 if(gameInitSettings.getGameType() != GameType::CustomMultiplayer && gameInitSettings.getGameType() != GameType::LoadMultiplayer) {
175 chatVBox.setVisible(false);
176 chatVBox.setEnabled(false);
177 }
178
179 bool bLoadMultiplayer = (gameInitSettings.getGameType() == GameType::LoadMultiplayer);
180
181 buttonHBox.addWidget(Spacer::create(), 0.0625);
182
183 nextButtonVBox.addWidget(Spacer::create());
184 nextButton.setText(_("Next"));
185 nextButton.setOnClick(std::bind(&CustomGamePlayers::onNext, this));
186 nextButtonVBox.addWidget(&nextButton, 24);
187 nextButtonVBox.addWidget(VSpacer::create(14));
188 if(bServer == false) {
189 nextButton.setEnabled(false);
190 nextButton.setVisible(false);
191 }
192 buttonHBox.addWidget(&nextButtonVBox, 0.1);
193
194 buttonHBox.addWidget(HSpacer::create(90));
195
196 std::list<HOUSETYPE> tmpBoundHousesOnMap = boundHousesOnMap;
197
198 bool thisPlayerPlaced = false;
199
200 for(int i=0;i<NUM_HOUSES;i++) {
201 HouseInfo& curHouseInfo = houseInfo[i];
202
203 // set up header row with Label "House", DropDown for house selection and DropDown for team selection
204 curHouseInfo.houseLabel.setText(_("House"));
205 curHouseInfo.houseHBox.addWidget(&curHouseInfo.houseLabel, 60);
206
207 if(bLoadMultiplayer) {
208 if(i < (int) houseInfoListSetup.size()) {
209 GameInitSettings::HouseInfo gisHouseInfo = houseInfoListSetup.at(i);
210
211 if(gisHouseInfo.houseID == HOUSE_INVALID) {
212 addToHouseDropDown(curHouseInfo.houseDropDown, HOUSE_INVALID, true);
213 } else {
214 addToHouseDropDown(curHouseInfo.houseDropDown, gisHouseInfo.houseID, true);
215 }
216 }
217
218 curHouseInfo.houseDropDown.setEnabled(false);
219 } else if(tmpBoundHousesOnMap.empty() == false) {
220 HOUSETYPE housetype = tmpBoundHousesOnMap.front();
221 tmpBoundHousesOnMap.pop_front();
222
223 addToHouseDropDown(curHouseInfo.houseDropDown, housetype, true);
224 curHouseInfo.houseDropDown.setEnabled(bServer);
225 } else {
226 addToHouseDropDown(curHouseInfo.houseDropDown, HOUSE_INVALID, true);
227 curHouseInfo.houseDropDown.setEnabled(bServer);
228 }
229 curHouseInfo.houseDropDown.setOnSelectionChange(std::bind(&CustomGamePlayers::onChangeHousesDropDownBoxes, this, std::placeholders::_1, i));
230 curHouseInfo.houseHBox.addWidget(&curHouseInfo.houseDropDown, 95);
231
232 if(bLoadMultiplayer) {
233 if(i < (int) houseInfoListSetup.size()) {
234 GameInitSettings::HouseInfo gisHouseInfo = houseInfoListSetup.at(i);
235
236 curHouseInfo.teamDropDown.addEntry(_("Team") + " " + stringify(gisHouseInfo.team), gisHouseInfo.team);
237 curHouseInfo.teamDropDown.setSelectedItem(0);
238 }
239 curHouseInfo.teamDropDown.setEnabled(false);
240 curHouseInfo.teamDropDown.setOnClickEnabled(false);
241 } else {
242 for(int team = 0 ; team<numHouses ; team++) {
243 curHouseInfo.teamDropDown.addEntry(_("Team") + " " + stringify(team+1), team+1);
244 }
245 curHouseInfo.teamDropDown.setSelectedItem(slotToTeam[i]);
246 curHouseInfo.teamDropDown.setEnabled(bServer);
247 }
248 curHouseInfo.teamDropDown.setOnSelectionChange(std::bind(&CustomGamePlayers::onChangeTeamDropDownBoxes, this, std::placeholders::_1, i));
249 curHouseInfo.houseHBox.addWidget(HSpacer::create(10));
250 curHouseInfo.houseHBox.addWidget(&curHouseInfo.teamDropDown, 85);
251
252 curHouseInfo.houseInfoVBox.addWidget(&curHouseInfo.houseHBox);
253
254 // add 1. player
255 curHouseInfo.player1ArrowLabel.setTexture(pGFXManager->getUIGraphic(UI_CustomGamePlayersArrowNeutral), false);
256 curHouseInfo.playerHBox.addWidget(&curHouseInfo.player1ArrowLabel);
257 curHouseInfo.player1Label.setText(_("Player") + (gameInitSettings.isMultiplePlayersPerHouse() ? " 1" : ""));
258 curHouseInfo.player1Label.setTextFont(FONT_STD10);
259 curHouseInfo.playerHBox.addWidget(&curHouseInfo.player1Label, 68);
260
261 if(bLoadMultiplayer) {
262 if(i < (int) houseInfoListSetup.size()) {
263 GameInitSettings::HouseInfo gisHouseInfo = houseInfoListSetup.at(i);
264
265 if(gisHouseInfo.houseID == HOUSE_UNUSED) {
266 curHouseInfo.player1DropDown.addEntry(_("closed"), PLAYER_CLOSED);
267 } else if(gisHouseInfo.playerInfoList.empty() == false) {
268 GameInitSettings::PlayerInfo playerInfo = gisHouseInfo.playerInfoList.front();
269 if(playerInfo.playerClass == HUMANPLAYERCLASS) {
270 if(thisPlayerPlaced == false) {
271 curHouseInfo.player1DropDown.addEntry(settings.general.playerName, PLAYER_HUMAN);
272 curHouseInfo.player1DropDown.setSelectedItem(0);
273 thisPlayerPlaced = true;
274 } else {
275 curHouseInfo.player1DropDown.addEntry(_("open"), PLAYER_OPEN);
276 curHouseInfo.player1DropDown.setSelectedItem(0);
277 }
278 } else {
279 const PlayerFactory::PlayerData* pPlayerData = PlayerFactory::getByPlayerClass(playerInfo.playerClass);
280 int index = PlayerFactory::getIndexByPlayerClass(playerInfo.playerClass);
281
282 if(pPlayerData != nullptr) {
283 curHouseInfo.player1DropDown.addEntry(pPlayerData->getName(), -(index+2));
284 curHouseInfo.player1DropDown.setSelectedItem(0);
285 curHouseInfo.player1DropDown.setEnabled(false);
286 curHouseInfo.player1DropDown.setOnClickEnabled(false);
287 }
288 }
289 }
290
291 }
292
293 } else if(bServer && (thisPlayerPlaced == false)) {
294 curHouseInfo.player1DropDown.addEntry(settings.general.playerName, PLAYER_HUMAN);
295 curHouseInfo.player1DropDown.setSelectedItem(0);
296 curHouseInfo.player1DropDown.setEnabled(bServer);
297 thisPlayerPlaced = true;
298 } else {
299 curHouseInfo.player1DropDown.addEntry(_("open"), PLAYER_OPEN);
300 curHouseInfo.player1DropDown.setSelectedItem(0);
301 curHouseInfo.player1DropDown.addEntry(_("closed"), PLAYER_CLOSED);
302 for(unsigned int k = 1; k < PlayerFactory::getList().size(); k++) {
303 curHouseInfo.player1DropDown.addEntry(PlayerFactory::getByIndex(k)->getName(), k);
304 }
305 curHouseInfo.player1DropDown.setEnabled(bServer);
306 }
307 curHouseInfo.player1DropDown.setOnSelectionChange(std::bind(&CustomGamePlayers::onChangePlayerDropDownBoxes, this, std::placeholders::_1, 2*i));
308 curHouseInfo.player1DropDown.setOnClick(std::bind(&CustomGamePlayers::onClickPlayerDropDownBox, this, 2*i));
309 curHouseInfo.playerHBox.addWidget(&curHouseInfo.player1DropDown, 100);
310
311 curHouseInfo.playerHBox.addWidget(HSpacer::create(10));
312
313 // add 2. player
314 curHouseInfo.player2Label.setText(_("Player") + " 2");
315 curHouseInfo.player2Label.setTextFont(FONT_STD10);
316 curHouseInfo.playerHBox.addWidget(&curHouseInfo.player2Label, 68);
317
318 if(bLoadMultiplayer) {
319 if(i < (int) houseInfoListSetup.size()) {
320 GameInitSettings::HouseInfo gisHouseInfo = houseInfoListSetup.at(i);
321
322 if(gisHouseInfo.houseID == HOUSE_UNUSED) {
323 curHouseInfo.player2DropDown.addEntry(_("closed"), PLAYER_CLOSED);
324 } else if(gisHouseInfo.playerInfoList.size() >= 2) {
325 GameInitSettings::PlayerInfo playerInfo = *(++gisHouseInfo.playerInfoList.begin());
326 if(playerInfo.playerClass == HUMANPLAYERCLASS) {
327 if(thisPlayerPlaced == false) {
328 curHouseInfo.player2DropDown.addEntry(settings.general.playerName, PLAYER_HUMAN);
329 curHouseInfo.player2DropDown.setSelectedItem(0);
330 thisPlayerPlaced = true;
331 } else {
332 curHouseInfo.player2DropDown.addEntry(_("open"), PLAYER_OPEN);
333 curHouseInfo.player2DropDown.setSelectedItem(0);
334 }
335 } else {
336 const PlayerFactory::PlayerData* pPlayerData = PlayerFactory::getByPlayerClass(playerInfo.playerClass);
337 int index = PlayerFactory::getIndexByPlayerClass(playerInfo.playerClass);
338
339 if(pPlayerData != nullptr) {
340 curHouseInfo.player1DropDown.addEntry(pPlayerData->getName(), -(index+2));
341 curHouseInfo.player1DropDown.setSelectedItem(0);
342 curHouseInfo.player1DropDown.setEnabled(false);
343 curHouseInfo.player1DropDown.setOnClickEnabled(false);
344 }
345 }
346 }
347 }
348 } else if(bServer && (thisPlayerPlaced == false)) {
349 curHouseInfo.player2DropDown.addEntry(settings.general.playerName, PLAYER_HUMAN);
350 curHouseInfo.player2DropDown.setSelectedItem(0);
351 curHouseInfo.player2DropDown.setEnabled(bServer);
352 thisPlayerPlaced = true;
353 } else {
354 curHouseInfo.player2DropDown.addEntry(_("open"), PLAYER_OPEN);
355 curHouseInfo.player2DropDown.setSelectedItem(0);
356 curHouseInfo.player2DropDown.addEntry(_("closed"), PLAYER_CLOSED);
357 for(unsigned int k = 1; k < PlayerFactory::getList().size(); k++) {
358 curHouseInfo.player2DropDown.addEntry(PlayerFactory::getByIndex(k)->getName(), k);
359 }
360 curHouseInfo.player2DropDown.setEnabled(bServer);
361 }
362 curHouseInfo.player2DropDown.setOnSelectionChange(std::bind(&CustomGamePlayers::onChangePlayerDropDownBoxes, this, std::placeholders::_1, 2*i + 1));
363 curHouseInfo.player2DropDown.setOnClick(std::bind(&CustomGamePlayers::onClickPlayerDropDownBox, this, 2*i + 1));
364 curHouseInfo.playerHBox.addWidget(&curHouseInfo.player2DropDown, 100);
365
366 curHouseInfo.houseInfoVBox.addWidget(&curHouseInfo.playerHBox);
367
368 playerListVBox.addWidget(&curHouseInfo.houseInfoVBox, 0.01);
369
370 playerListVBox.addWidget(VSpacer::create(4), 0.0);
371 playerListVBox.addWidget(Spacer::create(), 0.07);
372
373 if(i >= numHouses) {
374 curHouseInfo.houseInfoVBox.setEnabled(false);
375 curHouseInfo.houseInfoVBox.setVisible(false);
376 }
377 }
378
379 onChangeHousesDropDownBoxes(false);
380
381 checkPlayerBoxes();
382
383 leftVBox.addWidget(Spacer::create(), 0.3);
384
385 // maybe there is a better fitting slot if we are loading a map in the old format with Brain=CPU and Brain=Human
386 if(brainEqHumanSlot >= 0) {
387 DropDownBox& dropDownBox1 = houseInfo[brainEqHumanSlot].player1DropDown;
388 DropDownBox& dropDownBox2 = houseInfo[brainEqHumanSlot].player2DropDown;
389
390 if(dropDownBox1.getSelectedEntry() != settings.general.playerName && dropDownBox2.getSelectedEntry() != settings.general.playerName) {
391 if(dropDownBox1.getSelectedEntryIntData() == PLAYER_OPEN) {
392 setPlayer2Slot(settings.general.playerName, brainEqHumanSlot*2);
393 } else if((dropDownBox2.getSelectedEntryIntData() == PLAYER_OPEN) && gameInitSettings.isMultiplePlayersPerHouse()) {
394 setPlayer2Slot(settings.general.playerName, brainEqHumanSlot*2+1);
395 }
396 }
397 }
398
399 if(pNetworkManager != nullptr) {
400 if(bServer) {
401 pNetworkManager->startServer(bLANServer, gameInitSettings.getServername(), settings.general.playerName, &gameInitSettings, 1, gameInitSettings.isMultiplePlayersPerHouse() ? numHouses*2 : numHouses);
402 }
403
404 pNetworkManager->setOnPeerDisconnected(std::bind(&CustomGamePlayers::onPeerDisconnected, this, std::placeholders::_1, std::placeholders::_2, std::placeholders::_3));
405 pNetworkManager->setOnReceiveChangeEventList(std::bind(&CustomGamePlayers::onReceiveChangeEventList, this, std::placeholders::_1));
406 pNetworkManager->setOnReceiveChatMessage(std::bind(&CustomGamePlayers::onReceiveChatMessage, this, std::placeholders::_1, std::placeholders::_2));
407
408 if(bServer) {
409 pNetworkManager->setGetChangeEventListForNewPlayerCallback(std::bind(&CustomGamePlayers::getChangeEventListForNewPlayer, this, std::placeholders::_1));
410 } else {
411 pNetworkManager->setOnStartGame(std::bind(&CustomGamePlayers::onStartGame, this, std::placeholders::_1));
412 }
413 }
414 }
415
~CustomGamePlayers()416 CustomGamePlayers::~CustomGamePlayers()
417 {
418 if(pNetworkManager != nullptr) {
419 pNetworkManager->disconnect();
420
421 pNetworkManager->setOnPeerDisconnected(std::function<void (const std::string&, bool, int)>());
422 pNetworkManager->setGetChangeEventListForNewPlayerCallback(std::function<ChangeEventList (const std::string&)>());
423 pNetworkManager->setOnReceiveChangeEventList(std::function<void (const ChangeEventList&)>());
424 pNetworkManager->setOnReceiveChatMessage(std::function<void (const std::string&, const std::string&)>());
425 pNetworkManager->setOnStartGame(std::function<void (unsigned int)>());
426
427 if(bServer) {
428 pNetworkManager->stopServer();
429 }
430 }
431 }
432
update()433 void CustomGamePlayers::update() {
434 if(startGameTime > 0) {
435 if(SDL_GetTicks() >= startGameTime) {
436 startGameTime = 0;
437
438 pNetworkManager->setOnPeerDisconnected(std::function<void (const std::string&, bool, int)>());
439 pNetworkManager->setGetChangeEventListForNewPlayerCallback(std::function<ChangeEventList (const std::string&)>());
440 pNetworkManager->setOnReceiveChangeEventList(std::function<void (const ChangeEventList&)>());
441 pNetworkManager->setOnReceiveChatMessage(std::function<void (const std::string&, const std::string&)>());
442 pNetworkManager->setOnStartGame(std::function<void (unsigned int)>());
443
444 if(bServer) {
445 pNetworkManager->stopServer();
446 }
447
448 addAllPlayersToGameInitSettings();
449 startMultiPlayerGame(gameInitSettings);
450
451 quit(MENU_QUIT_GAME_FINISHED);
452 } else {
453 static Uint32 lastSecondLeft = 0;
454 Uint32 secondsLeft = ((startGameTime - SDL_GetTicks())/1000) + 1;
455 if(lastSecondLeft != secondsLeft) {
456 lastSecondLeft = secondsLeft;
457 addInfoMessage("Starting game in " + stringify(secondsLeft) + "...");
458 }
459 }
460 }
461 }
462
onReceiveChangeEventList(const ChangeEventList & changeEventList)463 void CustomGamePlayers::onReceiveChangeEventList(const ChangeEventList& changeEventList)
464 {
465 for(const ChangeEventList::ChangeEvent& changeEvent : changeEventList.changeEventList) {
466
467 switch(changeEvent.eventType) {
468 case ChangeEventList::ChangeEvent::EventType::ChangeHouse: {
469 HOUSETYPE houseType = (HOUSETYPE) changeEvent.newValue;
470
471 HouseInfo& curHouseInfo = houseInfo[changeEvent.slot];
472
473 for(int i=0;i<curHouseInfo.houseDropDown.getNumEntries();i++) {
474 if(curHouseInfo.houseDropDown.getEntryIntData(i) == houseType) {
475 curHouseInfo.houseDropDown.setSelectedItem(i);
476 break;
477 }
478 }
479 } break;
480
481 case ChangeEventList::ChangeEvent::EventType::ChangeTeam: {
482 int newTeam = (int) changeEvent.newValue;
483
484 HouseInfo& curHouseInfo = houseInfo[changeEvent.slot];
485
486 for(int i=0;i<curHouseInfo.teamDropDown.getNumEntries();i++) {
487 if(curHouseInfo.teamDropDown.getEntryIntData(i) == newTeam) {
488 curHouseInfo.teamDropDown.setSelectedItem(i);
489 break;
490 }
491 }
492 } break;
493
494 case ChangeEventList::ChangeEvent::EventType::ChangePlayer: {
495 int newPlayer = (int) changeEvent.newValue;
496
497 HouseInfo& curHouseInfo = houseInfo[changeEvent.slot/2];
498
499 if(changeEvent.slot % 2 == 0) {
500 for(int i=0;i<curHouseInfo.player1DropDown.getNumEntries();i++) {
501 if(curHouseInfo.player1DropDown.getEntryIntData(i) == newPlayer) {
502 curHouseInfo.player1DropDown.setSelectedItem(i);
503 break;
504 }
505 }
506 } else {
507 for(int i=0;i<curHouseInfo.player2DropDown.getNumEntries();i++) {
508 if(curHouseInfo.player2DropDown.getEntryIntData(i) == newPlayer) {
509 curHouseInfo.player2DropDown.setSelectedItem(i);
510 break;
511 }
512 }
513 }
514
515 checkPlayerBoxes();
516 } break;
517
518 case ChangeEventList::ChangeEvent::EventType::SetHumanPlayer: {
519 const std::string& name = changeEvent.newStringValue;
520 int slot = changeEvent.slot;
521
522 setPlayer2Slot(name, slot);
523
524 checkPlayerBoxes();
525 } break;
526
527 default: {
528 } break;
529 }
530 }
531
532 if((pNetworkManager != nullptr) && bServer) {
533 ChangeEventList changeEventList2 = getChangeEventList();
534
535 pNetworkManager->sendChangeEventList(changeEventList2);
536 }
537 }
538
getChangeEventList()539 ChangeEventList CustomGamePlayers::getChangeEventList()
540 {
541 ChangeEventList changeEventList;
542
543 for(int i=0;i<NUM_HOUSES;i++) {
544 HouseInfo& curHouseInfo = houseInfo[i];
545
546 int houseID = curHouseInfo.houseDropDown.getSelectedEntryIntData();
547 int team = curHouseInfo.teamDropDown.getSelectedEntryIntData();
548 int player1 = curHouseInfo.player1DropDown.getSelectedEntryIntData();
549 int player2 = curHouseInfo.player2DropDown.getSelectedEntryIntData();
550
551 changeEventList.changeEventList.push_back(ChangeEventList::ChangeEvent(ChangeEventList::ChangeEvent::EventType::ChangeHouse, i, houseID));
552 changeEventList.changeEventList.push_back(ChangeEventList::ChangeEvent(ChangeEventList::ChangeEvent::EventType::ChangeTeam, i, team));
553
554 if(player1 == PLAYER_HUMAN) {
555 std::string playername = curHouseInfo.player1DropDown.getSelectedEntry();
556 changeEventList.changeEventList.push_back(ChangeEventList::ChangeEvent(2*i, playername));
557 } else {
558 changeEventList.changeEventList.push_back(ChangeEventList::ChangeEvent(ChangeEventList::ChangeEvent::EventType::ChangePlayer, 2*i, player1));
559 }
560
561 if(player2 == PLAYER_HUMAN) {
562 std::string playername = curHouseInfo.player2DropDown.getSelectedEntry();
563 changeEventList.changeEventList.push_back(ChangeEventList::ChangeEvent(2*i+1, playername));
564 } else {
565 changeEventList.changeEventList.push_back(ChangeEventList::ChangeEvent(ChangeEventList::ChangeEvent::EventType::ChangePlayer, 2*i+1, player2));
566 }
567 }
568
569 return changeEventList;
570 }
571
getChangeEventListForNewPlayer(const std::string & newPlayerName)572 ChangeEventList CustomGamePlayers::getChangeEventListForNewPlayer(const std::string& newPlayerName)
573 {
574 ChangeEventList changeEventList = getChangeEventList();
575
576 // find a place for the new player
577
578 int newPlayerSlot = INVALID;
579
580 // look for an open left slot
581 for(int i=0;i<numHouses;i++) {
582 HouseInfo& curHouseInfo = houseInfo[i];
583 int player1 = curHouseInfo.player1DropDown.getSelectedEntryIntData();
584
585 if(player1 == PLAYER_OPEN) {
586 newPlayerSlot = 2*i;
587 break;
588 }
589 }
590
591 // if multiple players per house look for an open right slot
592 if((newPlayerSlot == INVALID) && gameInitSettings.isMultiplePlayersPerHouse()) {
593 for(int i=0;i<numHouses;i++) {
594 HouseInfo& curHouseInfo = houseInfo[i];
595 int player2 = curHouseInfo.player2DropDown.getSelectedEntryIntData();
596
597 if(player2 == PLAYER_OPEN) {
598 newPlayerSlot = 2*i + 1;
599 break;
600 }
601 }
602 }
603
604 // as a fallback look for any non-human slot
605 if(newPlayerSlot == INVALID) {
606 for(int i=0;i<numHouses;i++) {
607 HouseInfo& curHouseInfo = houseInfo[i];
608 int player1 = curHouseInfo.player1DropDown.getSelectedEntryIntData();
609 int player2 = curHouseInfo.player2DropDown.getSelectedEntryIntData();
610
611 if(player1 != PLAYER_HUMAN) {
612 newPlayerSlot = 2*i;
613 break;
614 } else if(gameInitSettings.isMultiplePlayersPerHouse() && (player2 != PLAYER_HUMAN)) {
615 newPlayerSlot = 2*i + 1;
616 break;
617 }
618 }
619 }
620
621 if(newPlayerSlot != INVALID) {
622 setPlayer2Slot(newPlayerName, newPlayerSlot);
623
624 ChangeEventList::ChangeEvent changeEvent(newPlayerSlot, newPlayerName);
625
626 // add changeEvent to changeEventList for the new player
627 changeEventList.changeEventList.push_back(changeEvent);
628
629 // send it to all other connected peers
630 ChangeEventList changeEventList2;
631 changeEventList2.changeEventList.push_back(changeEvent);
632
633 pNetworkManager->sendChangeEventList(changeEventList2);
634 }
635
636 return changeEventList;
637 }
638
onReceiveChatMessage(const std::string & name,const std::string & message)639 void CustomGamePlayers::onReceiveChatMessage(const std::string& name, const std::string& message) {
640 addChatMessage(name, message);
641 }
642
onNext()643 void CustomGamePlayers::onNext()
644 {
645 // check if we have at least two houses on the map and if we have more than one team
646 int numUsedHouses = 0;
647 int numTeams = 0;
648 for(int i=0;i<NUM_HOUSES;i++) {
649 HouseInfo& curHouseInfo = houseInfo[i];
650
651 int currentPlayer1 = curHouseInfo.player1DropDown.getSelectedEntryIntData();
652 int currentPlayer2 = curHouseInfo.player2DropDown.getSelectedEntryIntData();
653
654 if((currentPlayer1 != PLAYER_OPEN && currentPlayer1 != PLAYER_CLOSED) || (currentPlayer2 != PLAYER_OPEN && currentPlayer2 != PLAYER_CLOSED)) {
655 numUsedHouses++;
656
657 int currentTeam = curHouseInfo.teamDropDown.getSelectedEntryIntData();
658 bool bTeamFound = false;
659 for(int j=0;j<i;j++) {
660 int player1 = houseInfo[j].player1DropDown.getSelectedEntryIntData();
661 int player2 = houseInfo[j].player2DropDown.getSelectedEntryIntData();
662
663 if((player1 != PLAYER_OPEN && player1 != PLAYER_CLOSED) || (player2 != PLAYER_OPEN && player2 != PLAYER_CLOSED)) {
664
665 int team = houseInfo[j].teamDropDown.getSelectedEntryIntData();
666 if(currentTeam == team) {
667 bTeamFound = true;
668 }
669 }
670 }
671
672 if(bTeamFound == false) {
673 numTeams++;
674 }
675 }
676 }
677
678 if(numUsedHouses < 2) {
679 // No game possible with only 1 house
680 openWindow(MsgBox::create(_("At least 2 houses must be controlled\nby a human player or an AI player!")));
681 } else if(numTeams < 2) {
682 // No game possible with only 1 team
683 openWindow(MsgBox::create(_("There must be at least two different teams!")));
684 } else {
685 // start game
686
687 addAllPlayersToGameInitSettings();
688
689 if(pNetworkManager != nullptr) {
690 unsigned int timeLeft = 5000;
691 startGameTime = SDL_GetTicks() + timeLeft;
692 pNetworkManager->sendStartGame(timeLeft);
693
694 disableAllDropDownBoxes();
695 } else {
696 startSinglePlayerGame(gameInitSettings);
697
698 quit(MENU_QUIT_GAME_FINISHED);
699 }
700 }
701 }
702
addAllPlayersToGameInitSettings()703 void CustomGamePlayers::addAllPlayersToGameInitSettings()
704 {
705 gameInitSettings.clearHouseInfo();
706
707 for(int i=0;i<NUM_HOUSES;i++) {
708 HouseInfo& curHouseInfo = houseInfo[i];
709
710 int houseID = curHouseInfo.houseDropDown.getSelectedEntryIntData();
711 int team = curHouseInfo.teamDropDown.getSelectedEntryIntData();
712 int player1 = curHouseInfo.player1DropDown.getSelectedEntryIntData();
713 std::string player1name = curHouseInfo.player1DropDown.getSelectedEntry();
714 int player2 = curHouseInfo.player2DropDown.getSelectedEntryIntData();
715 std::string player2name = curHouseInfo.player2DropDown.getSelectedEntry();
716
717 GameInitSettings::HouseInfo newHouseInfo((HOUSETYPE) houseID, team);
718
719 bool bAdded = false;
720 bAdded |= addPlayerToHouseInfo(newHouseInfo, player1, player1name);
721 bAdded |= addPlayerToHouseInfo(newHouseInfo, player2, player2name);
722
723 if(bAdded == true) {
724 gameInitSettings.addHouseInfo(newHouseInfo);
725 }
726 }
727 }
728
addPlayerToHouseInfo(GameInitSettings::HouseInfo & newHouseInfo,int player,const std::string & playername)729 bool CustomGamePlayers::addPlayerToHouseInfo(GameInitSettings::HouseInfo& newHouseInfo, int player, const std::string& playername)
730 {
731 std::string playerName;
732 std::string playerClass;
733
734 HOUSETYPE houseID = newHouseInfo.houseID;
735
736 switch(player) {
737 case PLAYER_HUMAN: {
738 playerName = playername;
739 playerClass = HUMANPLAYERCLASS;
740 } break;
741
742 case PLAYER_OPEN:
743 case PLAYER_CLOSED: {
744 return false;
745 } break;
746
747
748 default: {
749 // AI player
750 const PlayerFactory::PlayerData* pPlayerData = PlayerFactory::getByIndex(player);
751 if(pPlayerData == nullptr) {
752 return false;
753 }
754
755 playerName = (houseID == HOUSE_INVALID) ? pPlayerData->getName() : getHouseNameByNumber(houseID);
756 playerClass = pPlayerData->getPlayerClass();
757
758 } break;
759 }
760
761 newHouseInfo.addPlayerInfo(GameInitSettings::PlayerInfo(playerName, playerClass));
762 return true;
763 }
764
onCancel()765 void CustomGamePlayers::onCancel()
766 {
767 quit();
768 }
769
onSendChatMessage()770 void CustomGamePlayers::onSendChatMessage()
771 {
772 std::string message = chatTextBox.getText();
773 addChatMessage(settings.general.playerName, message);
774 chatTextBox.setText("");
775
776 pNetworkManager->sendChatMessage(message);
777
778 }
779
addInfoMessage(const std::string & message)780 void CustomGamePlayers::addInfoMessage(const std::string& message) {
781 std::string text = chatTextView.getText();
782 if(text.length() > 0) {
783 text += "\n";
784 }
785 text += "* " + message;
786 chatTextView.setText(text);
787 chatTextView.scrollToEnd();
788 }
789
addChatMessage(const std::string & name,const std::string & message)790 void CustomGamePlayers::addChatMessage(const std::string& name, const std::string& message)
791 {
792 std::string text = chatTextView.getText();
793 if(text.length() > 0) {
794 text += "\n";
795 }
796 text += name + ": " + message;
797 chatTextView.setText(text);
798 chatTextView.scrollToEnd();
799 }
800
extractMapInfo(std::shared_ptr<INIFile> & pMap)801 void CustomGamePlayers::extractMapInfo(std::shared_ptr<INIFile>& pMap)
802 {
803 int sizeX = 0;
804 int sizeY = 0;
805
806 if(pMap->hasKey("MAP","Seed")) {
807 // old map format with seed value
808 int mapscale = pMap->getIntValue("BASIC", "MapScale", -1);
809
810 switch(mapscale) {
811 case 0: {
812 sizeX = 62;
813 sizeY = 62;
814 } break;
815
816 case 1: {
817 sizeX = 32;
818 sizeY = 32;
819 } break;
820
821 case 2: {
822 sizeX = 21;
823 sizeY = 21;
824 } break;
825
826 default: {
827 sizeX = 64;
828 sizeY = 64;
829 }
830 }
831 } else {
832 // new map format with saved map
833 sizeX = pMap->getIntValue("MAP","SizeX", 0);
834 sizeY = pMap->getIntValue("MAP","SizeY", 0);
835 }
836
837 mapPropertySize.setText(stringify(sizeX) + " x " + stringify(sizeY));
838
839 SDL_Surface* pMapSurface = nullptr;
840 try {
841 INIMapPreviewCreator mapPreviewCreator(pMap);
842 pMapSurface = mapPreviewCreator.createMinimapImageOfMap(1, DuneStyle::buttonBorderColor);
843 } catch(...) {
844 pMapSurface = GUIStyle::getInstance().createButtonSurface(130, 130, "Error", true, false);
845 nextButton.setEnabled(false);
846 }
847 minimap.setSurface(pMapSurface, true);
848
849
850 boundHousesOnMap.clear();
851 if(pMap->hasSection("Harkonnen")) boundHousesOnMap.push_back(HOUSE_HARKONNEN);
852 if(pMap->hasSection("Atreides")) boundHousesOnMap.push_back(HOUSE_ATREIDES);
853 if(pMap->hasSection("Ordos")) boundHousesOnMap.push_back(HOUSE_ORDOS);
854 if(pMap->hasSection("Fremen")) boundHousesOnMap.push_back(HOUSE_FREMEN);
855 if(pMap->hasSection("Sardaukar")) boundHousesOnMap.push_back(HOUSE_SARDAUKAR);
856 if(pMap->hasSection("Mercenary")) boundHousesOnMap.push_back(HOUSE_MERCENARY);
857
858 numHouses = boundHousesOnMap.size();
859 if(pMap->hasSection("Player1")) numHouses++;
860 if(pMap->hasSection("Player2")) numHouses++;
861 if(pMap->hasSection("Player3")) numHouses++;
862 if(pMap->hasSection("Player4")) numHouses++;
863 if(pMap->hasSection("Player5")) numHouses++;
864 if(pMap->hasSection("Player6")) numHouses++;
865
866 mapPropertyPlayers.setText(stringify(numHouses));
867
868 std::string authors = pMap->getStringValue("BASIC","Author", "-");
869 if(authors.size() > 11) {
870 authors = authors.substr(0,9) + "...";
871 }
872 mapPropertyAuthors.setText(authors);
873
874
875 mapPropertyLicense.setText(pMap->getStringValue("BASIC","License", "-"));
876
877 // find Brain=Human
878 int currentIndex = 0;
879 for(const HOUSETYPE& houseType : boundHousesOnMap) {
880 if(strToUpper(pMap->getStringValue(getHouseNameByNumber(houseType),"Brain","")) == "HUMAN") {
881 brainEqHumanSlot = currentIndex;
882 }
883 currentIndex++;
884 }
885
886 currentIndex = 0;
887 int currentTeam = 0;
888 std::vector<std::string> teamNames;
889 for(const HOUSETYPE& houseType : boundHousesOnMap) {
890 std::string teamName = strToUpper(pMap->getStringValue(getHouseNameByNumber(houseType),"Brain","Team " + stringify(currentIndex+1)));
891 teamNames.push_back(teamName);
892 slotToTeam[currentIndex] = currentTeam;
893 currentTeam++;
894
895 // let's see if we can reuse an old team number
896 for(unsigned int i = 0; i < teamNames.size()-1; i++) {
897 if(teamNames[i] == teamName) {
898 slotToTeam[currentIndex] = slotToTeam[i];
899 currentTeam--;
900 break;
901 }
902 }
903
904 currentIndex++;
905 }
906
907 for(int p = 0; (p < NUM_HOUSES) && (currentIndex < NUM_HOUSES); p++) {
908 if(pMap->hasSection("Player" + stringify(p+1))) {
909 std::string teamName = strToUpper(pMap->getStringValue("Player" + stringify(p+1),"Brain","Team " + stringify(currentIndex+p+1)));
910 teamNames.push_back(teamName);
911 slotToTeam[currentIndex] = currentTeam;
912 currentTeam++;
913
914 // let's see if we can reuse an old team number
915 for(unsigned int i = 0; i < teamNames.size()-1; i++) {
916 if(teamNames[i] == teamName) {
917 slotToTeam[currentIndex] = slotToTeam[i];
918 currentTeam--;
919 break;
920 }
921 }
922
923 currentIndex++;
924 }
925 }
926
927 for(;currentIndex < NUM_HOUSES; currentIndex++) {
928 slotToTeam[currentIndex] = -1;
929 }
930 }
931
onChangeHousesDropDownBoxes(bool bInteractive,int houseInfoNum)932 void CustomGamePlayers::onChangeHousesDropDownBoxes(bool bInteractive, int houseInfoNum) {
933 if(bInteractive && houseInfoNum >= 0 && pNetworkManager != nullptr) {
934 int selectedHouseID = houseInfo[houseInfoNum].houseDropDown.getSelectedEntryIntData();
935
936 ChangeEventList changeEventList;
937 changeEventList.changeEventList.push_back(ChangeEventList::ChangeEvent(ChangeEventList::ChangeEvent::EventType::ChangeHouse, houseInfoNum, selectedHouseID));
938
939 pNetworkManager->sendChangeEventList(changeEventList);
940 }
941
942 int numBoundHouses = boundHousesOnMap.size();
943 int numUsedBoundHouses = 0;
944 int numUsedRandomHouses = 0;
945 for(int i=0;i<numHouses;i++) {
946 int selectedHouseID = houseInfo[i].houseDropDown.getSelectedEntryIntData();
947
948 if(selectedHouseID == HOUSE_INVALID) {
949 numUsedRandomHouses++;
950 } else {
951 if(isBoundedHouseOnMap((HOUSETYPE) selectedHouseID)) {
952 numUsedBoundHouses++;
953 }
954 }
955 }
956
957
958 for(int i=0;i<numHouses;i++) {
959 HouseInfo& curHouseInfo = houseInfo[i];
960
961 int house = curHouseInfo.houseDropDown.getSelectedEntryIntData();
962
963 if(houseInfoNum == -1 || houseInfoNum == i) {
964
965 Uint32 color = (house == HOUSE_INVALID) ? COLOR_RGB(20,20,40) : SDL2RGB(palette[houseToPaletteIndex[house] + 3]);
966 curHouseInfo.houseLabel.setTextColor(color);
967 curHouseInfo.houseDropDown.setColor(color);
968 curHouseInfo.teamDropDown.setColor(color);
969 curHouseInfo.player1Label.setTextColor(color);
970 curHouseInfo.player1DropDown.setColor(color);
971 curHouseInfo.player2Label.setTextColor(color);
972 curHouseInfo.player2DropDown.setColor(color);
973
974 if(house == HOUSE_INVALID) {
975 curHouseInfo.player1ArrowLabel.setTexture(pGFXManager->getUIGraphic(UI_CustomGamePlayersArrowNeutral), false);
976 } else {
977 curHouseInfo.player1ArrowLabel.setTexture(pGFXManager->getUIGraphic(UI_CustomGamePlayersArrow, house), false);
978 }
979 }
980
981 if(gameInitSettings.getGameType() == GameType::LoadMultiplayer) {
982 // no house changes possible
983 continue;
984 }
985
986 addToHouseDropDown(curHouseInfo.houseDropDown, HOUSE_INVALID);
987
988 for(int h=0;h<NUM_HOUSES;h++) {
989 bool bAddHouse;
990
991 bool bCheck;
992
993 if((house == HOUSE_INVALID) || (isBoundedHouseOnMap((HOUSETYPE) house))) {
994 if(numUsedBoundHouses + numUsedRandomHouses - 1 >= numBoundHouses) {
995 bCheck = true;
996 } else {
997 bCheck = false;
998 }
999 } else {
1000 if(numUsedBoundHouses + numUsedRandomHouses >= numBoundHouses) {
1001 bCheck = true;
1002 } else {
1003 bCheck = false;
1004 }
1005 }
1006
1007 if(bCheck == true) {
1008 bAddHouse = true;
1009 for(int j = 0; j < numHouses; j++) {
1010 if(i != j) {
1011 DropDownBox& tmpDropDown = houseInfo[j].houseDropDown;
1012 if(tmpDropDown.getSelectedEntryIntData() == h) {
1013 bAddHouse = false;
1014 break;
1015 }
1016 }
1017 }
1018 } else {
1019 bAddHouse = (h == house);
1020
1021 if(((house == HOUSE_INVALID) || (isBoundedHouseOnMap((HOUSETYPE) house))) && isBoundedHouseOnMap((HOUSETYPE) h)) {
1022 // check if this entry is random or a bounded house but is needed for a bounded house
1023 bAddHouse = true;
1024 for(int j = 0; j < numHouses; j++) {
1025 if(i != j) {
1026 DropDownBox& tmpDropDown = houseInfo[j].houseDropDown;
1027 if(tmpDropDown.getSelectedEntryIntData() == h) {
1028 bAddHouse = false;
1029 break;
1030 }
1031 }
1032 }
1033 }
1034 }
1035
1036 if(bAddHouse == true) {
1037 addToHouseDropDown(curHouseInfo.houseDropDown, h);
1038 } else {
1039 removeFromHouseDropDown(curHouseInfo.houseDropDown, h);
1040 }
1041 }
1042 }
1043 }
1044
onChangeTeamDropDownBoxes(bool bInteractive,int houseInfoNum)1045 void CustomGamePlayers::onChangeTeamDropDownBoxes(bool bInteractive, int houseInfoNum) {
1046
1047 if(bInteractive && houseInfoNum >= 0 && pNetworkManager != nullptr) {
1048 int selectedTeam = houseInfo[houseInfoNum].teamDropDown.getSelectedEntryIntData();
1049
1050 ChangeEventList changeEventList;
1051 changeEventList.changeEventList.push_back(ChangeEventList::ChangeEvent(ChangeEventList::ChangeEvent::EventType::ChangeTeam, houseInfoNum, selectedTeam));
1052
1053 pNetworkManager->sendChangeEventList(changeEventList);
1054 }
1055 }
1056
onChangePlayerDropDownBoxes(bool bInteractive,int boxnum)1057 void CustomGamePlayers::onChangePlayerDropDownBoxes(bool bInteractive, int boxnum) {
1058 if(bInteractive && boxnum >= 0 && pNetworkManager != nullptr) {
1059 DropDownBox& dropDownBox = (boxnum % 2 == 0) ? houseInfo[boxnum / 2].player1DropDown : houseInfo[boxnum / 2].player2DropDown;
1060
1061 int selectedPlayer = dropDownBox.getSelectedEntryIntData();
1062
1063 ChangeEventList changeEventList;
1064 changeEventList.changeEventList.push_back(ChangeEventList::ChangeEvent(ChangeEventList::ChangeEvent::EventType::ChangePlayer, boxnum, selectedPlayer));
1065
1066 pNetworkManager->sendChangeEventList(changeEventList);
1067 }
1068
1069 checkPlayerBoxes();
1070 }
1071
onClickPlayerDropDownBox(int boxnum)1072 void CustomGamePlayers::onClickPlayerDropDownBox(int boxnum) {
1073 DropDownBox& dropDownBox = (boxnum % 2 == 0) ? houseInfo[boxnum / 2].player1DropDown : houseInfo[boxnum / 2].player2DropDown;
1074
1075 if(dropDownBox.getSelectedEntryIntData() == PLAYER_CLOSED) {
1076 return;
1077 }
1078
1079 setPlayer2Slot(settings.general.playerName, boxnum);
1080
1081 if(boxnum >= 0 && pNetworkManager != nullptr) {
1082 ChangeEventList changeEventList;
1083 changeEventList.changeEventList.push_back(ChangeEventList::ChangeEvent(boxnum, settings.general.playerName));
1084
1085 pNetworkManager->sendChangeEventList(changeEventList);
1086 }
1087 }
1088
onPeerDisconnected(const std::string & playername,bool bHost,int cause)1089 void CustomGamePlayers::onPeerDisconnected(const std::string& playername, bool bHost, int cause) {
1090 if(bHost) {
1091 quit(cause);
1092 } else {
1093 for(int i=0;i<numHouses*2;i++) {
1094 DropDownBox& curDropDownBox = (i % 2 == 0) ? houseInfo[i / 2].player1DropDown : houseInfo[i / 2].player2DropDown;
1095
1096 if(curDropDownBox.getSelectedEntryIntData() == PLAYER_HUMAN && curDropDownBox.getSelectedEntry() == playername) {
1097
1098 curDropDownBox.clearAllEntries();
1099 curDropDownBox.addEntry(_("open"), PLAYER_OPEN);
1100 curDropDownBox.setSelectedItem(0);
1101
1102 if(gameInitSettings.getGameType() != GameType::LoadMultiplayer) {
1103 curDropDownBox.addEntry(_("closed"), PLAYER_CLOSED);
1104 for(unsigned int k = 1; k < PlayerFactory::getList().size(); k++) {
1105 curDropDownBox.addEntry(PlayerFactory::getByIndex(k)->getName(), k);
1106 }
1107 }
1108
1109 break;
1110 }
1111 }
1112
1113 if(bServer == false) {
1114 for(int i=0;i<numHouses;i++) {
1115 bool bIsThisPlayer = false;
1116 if(houseInfo[i].player1DropDown.getSelectedEntryIntData() == PLAYER_HUMAN) {
1117 if(houseInfo[i].player1DropDown.getSelectedEntry() == settings.general.playerName) {
1118 bIsThisPlayer = true;
1119 }
1120 }
1121
1122 if(houseInfo[i].player2DropDown.getSelectedEntryIntData() == PLAYER_HUMAN) {
1123 if(houseInfo[i].player2DropDown.getSelectedEntry() == settings.general.playerName) {
1124 bIsThisPlayer = true;
1125 }
1126 }
1127
1128 houseInfo[i].player1DropDown.setEnabled(bIsThisPlayer);
1129 houseInfo[i].player2DropDown.setEnabled(bIsThisPlayer);
1130 houseInfo[i].houseDropDown.setEnabled(bIsThisPlayer);
1131 houseInfo[i].teamDropDown.setEnabled(bIsThisPlayer);
1132 }
1133 }
1134
1135 checkPlayerBoxes();
1136
1137 addInfoMessage(playername + " disconnected!");
1138 }
1139 }
1140
onStartGame(unsigned int timeLeft)1141 void CustomGamePlayers::onStartGame(unsigned int timeLeft) {
1142 startGameTime = SDL_GetTicks() + timeLeft;
1143 disableAllDropDownBoxes();
1144 }
1145
setPlayer2Slot(const std::string & playername,int slot)1146 void CustomGamePlayers::setPlayer2Slot(const std::string& playername, int slot) {
1147 DropDownBox& dropDownBox = (slot % 2 == 0) ? houseInfo[slot / 2].player1DropDown : houseInfo[slot / 2].player2DropDown;
1148
1149 std::string oldPlayerName = "";
1150 int oldPlayerType = dropDownBox.getSelectedEntryIntData();
1151 if(oldPlayerType == PLAYER_HUMAN) {
1152 oldPlayerName = dropDownBox.getSelectedEntry();
1153 }
1154
1155 for(int i=0;i<numHouses*2;i++) {
1156 DropDownBox& curDropDownBox = (i % 2 == 0) ? houseInfo[i / 2].player1DropDown : houseInfo[i / 2].player2DropDown;
1157
1158 if(curDropDownBox.getSelectedEntryIntData() == PLAYER_HUMAN && curDropDownBox.getSelectedEntry() == playername) {
1159
1160 if(oldPlayerType == PLAYER_HUMAN) {
1161 curDropDownBox.clearAllEntries();
1162 curDropDownBox.addEntry(oldPlayerName, PLAYER_HUMAN);
1163 curDropDownBox.setSelectedItem(0);
1164 } else {
1165 curDropDownBox.clearAllEntries();
1166 curDropDownBox.addEntry(_("open"), PLAYER_OPEN);
1167
1168 if(gameInitSettings.getGameType() != GameType::LoadMultiplayer) {
1169 curDropDownBox.addEntry(_("closed"), PLAYER_CLOSED);
1170 for(unsigned int k = 1; k < PlayerFactory::getList().size(); k++) {
1171 curDropDownBox.addEntry(PlayerFactory::getByIndex(k)->getName(), k);
1172 }
1173 }
1174
1175 for(int j = 0; j < curDropDownBox.getNumEntries(); j++) {
1176 if(curDropDownBox.getEntryIntData(j) == oldPlayerType) {
1177 curDropDownBox.setSelectedItem(j);
1178 break;
1179 }
1180 }
1181 }
1182
1183 break;
1184 }
1185 }
1186
1187 dropDownBox.clearAllEntries();
1188 dropDownBox.addEntry(playername, PLAYER_HUMAN);
1189 dropDownBox.setSelectedItem(0);
1190
1191 if(bServer == false) {
1192 for(int i=0;i<numHouses;i++) {
1193 bool bIsThisPlayer = false;
1194
1195 if(gameInitSettings.getGameType() != GameType::LoadMultiplayer) {
1196 if(houseInfo[i].player1DropDown.getSelectedEntryIntData() == PLAYER_HUMAN) {
1197 if(houseInfo[i].player1DropDown.getSelectedEntry() == settings.general.playerName) {
1198 bIsThisPlayer = true;
1199 }
1200 }
1201
1202 if(houseInfo[i].player2DropDown.getSelectedEntryIntData() == PLAYER_HUMAN) {
1203 if(houseInfo[i].player2DropDown.getSelectedEntry() == settings.general.playerName) {
1204 bIsThisPlayer = true;
1205 }
1206 }
1207 }
1208
1209 houseInfo[i].player1DropDown.setEnabled(bIsThisPlayer);
1210 houseInfo[i].player2DropDown.setEnabled(bIsThisPlayer);
1211 houseInfo[i].houseDropDown.setEnabled(bIsThisPlayer);
1212 houseInfo[i].teamDropDown.setEnabled(bIsThisPlayer);
1213 }
1214 }
1215
1216 checkPlayerBoxes();
1217 }
1218
checkPlayerBoxes()1219 void CustomGamePlayers::checkPlayerBoxes() {
1220 int numPlayers = 0;
1221
1222 for(int i=0;i<numHouses;i++) {
1223 HouseInfo& curHouseInfo = houseInfo[i];
1224
1225 int player1 = curHouseInfo.player1DropDown.getSelectedEntryIntData();
1226 int player2 = curHouseInfo.player2DropDown.getSelectedEntryIntData();
1227
1228 if(player1 != PLAYER_OPEN) {
1229 numPlayers++;
1230 }
1231
1232 if(gameInitSettings.isMultiplePlayersPerHouse() && player2 != PLAYER_OPEN) {
1233 numPlayers++;
1234 }
1235
1236 if((gameInitSettings.isMultiplePlayersPerHouse() == false) || (player1 == PLAYER_OPEN && player2 == PLAYER_OPEN) || (curHouseInfo.player2DropDown.getNumEntries() == 0)) {
1237 curHouseInfo.player2DropDown.setVisible(false);
1238 curHouseInfo.player2DropDown.setEnabled(false);
1239 curHouseInfo.player2Label.setVisible(false);
1240 } else {
1241 curHouseInfo.player2DropDown.setVisible(true);
1242
1243 bool bEnableDropDown2 = bServer;
1244 if(bServer == false) {
1245 if(player1 == PLAYER_HUMAN) {
1246 if(curHouseInfo.player1DropDown.getSelectedEntry() == settings.general.playerName) {
1247 bEnableDropDown2 = true;
1248 }
1249 }
1250
1251 if(player2 == PLAYER_HUMAN) {
1252 if(curHouseInfo.player2DropDown.getSelectedEntry() == settings.general.playerName) {
1253 bEnableDropDown2 = true;
1254 }
1255 }
1256 }
1257
1258 if((gameInitSettings.getGameType() == GameType::LoadMultiplayer) && (player2 != PLAYER_OPEN) && (player2 != PLAYER_HUMAN)) {
1259 curHouseInfo.player2DropDown.setEnabled(false);
1260 } else {
1261 curHouseInfo.player2DropDown.setEnabled(bEnableDropDown2);
1262 }
1263 curHouseInfo.player2Label.setVisible(true);
1264 }
1265 }
1266
1267 if(pNetworkManager != nullptr) {
1268 if(bServer) {
1269 pNetworkManager->updateServer(numPlayers);
1270 }
1271 }
1272 }
1273
1274
addToHouseDropDown(DropDownBox & houseDropDownBox,int house,bool bSelect)1275 void CustomGamePlayers::addToHouseDropDown(DropDownBox& houseDropDownBox, int house, bool bSelect) {
1276
1277 if(houseDropDownBox.getNumEntries() == 0) {
1278 if(house == HOUSE_INVALID) {
1279 houseDropDownBox.addEntry(_("Random"), HOUSE_INVALID);
1280 } else {
1281 houseDropDownBox.addEntry(getHouseNameByNumber((HOUSETYPE) house), house);
1282 }
1283
1284 if(bSelect) {
1285 houseDropDownBox.setSelectedItem(0);
1286 }
1287 } else {
1288
1289 if(house == HOUSE_INVALID) {
1290 if(houseDropDownBox.getEntryIntData(0) != HOUSE_INVALID) {
1291 houseDropDownBox.insertEntry(0, _("Random"), HOUSE_INVALID);
1292 }
1293
1294 if(bSelect) {
1295 houseDropDownBox.setSelectedItem(houseDropDownBox.getNumEntries()-1);
1296 }
1297 } else {
1298
1299 int currentItemIndex = (houseDropDownBox.getEntryIntData(0) == HOUSE_INVALID) ? 1 : 0;
1300
1301 for(int h = 0; h < NUM_HOUSES; h++) {
1302 if(currentItemIndex < houseDropDownBox.getNumEntries() && houseDropDownBox.getEntryIntData(currentItemIndex) == h) {
1303 if(h == house) {
1304 if(bSelect) {
1305 houseDropDownBox.setSelectedItem(currentItemIndex);
1306 }
1307 break;
1308 }
1309
1310 currentItemIndex++;
1311 } else {
1312 if(h == house) {
1313 houseDropDownBox.insertEntry(currentItemIndex, getHouseNameByNumber((HOUSETYPE) h), h);
1314
1315 if(bSelect) {
1316 houseDropDownBox.setSelectedItem(currentItemIndex);
1317 }
1318 break;
1319 }
1320 }
1321
1322
1323 }
1324 }
1325 }
1326 }
1327
removeFromHouseDropDown(DropDownBox & houseDropDownBox,int house)1328 void CustomGamePlayers::removeFromHouseDropDown(DropDownBox& houseDropDownBox, int house) {
1329
1330 for(int i=0;i<houseDropDownBox.getNumEntries(); i++) {
1331 if(houseDropDownBox.getEntryIntData(i) == house) {
1332 houseDropDownBox.removeEntry(i);
1333 break;
1334 }
1335 }
1336 }
1337
isBoundedHouseOnMap(HOUSETYPE houseID)1338 bool CustomGamePlayers::isBoundedHouseOnMap(HOUSETYPE houseID) {
1339 return (std::find(boundHousesOnMap.begin(), boundHousesOnMap.end(), houseID) != boundHousesOnMap.end());
1340 }
1341
disableAllDropDownBoxes()1342 void CustomGamePlayers::disableAllDropDownBoxes() {
1343 for(int i=0;i<NUM_HOUSES;i++) {
1344 HouseInfo& curHouseInfo = houseInfo[i];
1345
1346 curHouseInfo.houseDropDown.setEnabled(false);
1347 curHouseInfo.houseDropDown.setOnClickEnabled(false);
1348 curHouseInfo.teamDropDown.setEnabled(false);
1349 curHouseInfo.teamDropDown.setOnClickEnabled(false);
1350 curHouseInfo.player1DropDown.setEnabled(false);
1351 curHouseInfo.player1DropDown.setOnClickEnabled(false);
1352 curHouseInfo.player2DropDown.setEnabled(false);
1353 curHouseInfo.player2DropDown.setOnClickEnabled(false);
1354 }
1355
1356 backButton.setEnabled(false);
1357 nextButton.setEnabled(false);
1358 }
1359