1 /***************************************************************************
2 * Copyright (C) 2009 by Andrey Afletdinov <fheroes2@gmail.com> *
3 * *
4 * Part of the Free Heroes2 Engine: *
5 * http://sourceforge.net/projects/fheroes2 *
6 * *
7 * This program is free software; you can redistribute it and/or modify *
8 * it under the terms of the GNU General Public License as published by *
9 * the Free Software Foundation; either version 2 of the License, or *
10 * (at your option) any later version. *
11 * *
12 * This program is distributed in the hope that it will be useful, *
13 * but WITHOUT ANY WARRANTY; without even the implied warranty of *
14 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the *
15 * GNU General Public License for more details. *
16 * *
17 * You should have received a copy of the GNU General Public License *
18 * along with this program; if not, write to the *
19 * Free Software Foundation, Inc., *
20 * 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. *
21 ***************************************************************************/
22
23 #include "game.h"
24 #include "agg.h"
25 #include "agg_image.h"
26 #include "audio.h"
27 #include "campaign_savedata.h"
28 #include "cursor.h"
29 #include "dialog.h"
30 #include "dialog_game_settings.h"
31 #include "game_delays.h"
32 #include "game_mainmenu_ui.h"
33 #include "game_video.h"
34 #include "icn.h"
35 #include "mus.h"
36 #include "settings.h"
37 #include "smk_decoder.h"
38 #include "text.h"
39 #include "translations.h"
40 #include "ui_button.h"
41 #include "ui_tool.h"
42 #include "world.h"
43
44 #include <array>
45 #include <cmath>
46
47 namespace
48 {
49 const int32_t buttonYStep = 66;
50
51 // Draw button panel and return the position for a button.
drawButtonPanel()52 fheroes2::Point drawButtonPanel()
53 {
54 const fheroes2::Sprite & back = fheroes2::AGG::GetICN( ICN::HEROES, 0 );
55 const fheroes2::Sprite & panel = fheroes2::AGG::GetICN( ICN::REDBACK, 0 );
56
57 const uint32_t panelOffset = fheroes2::Display::DEFAULT_HEIGHT - panel.height();
58 const uint32_t panelXPos = back.width() - ( panel.width() + panelOffset );
59 fheroes2::Blit( panel, fheroes2::Display::instance(), panelXPos, panelOffset );
60
61 const int32_t buttonMiddlePos = panelXPos + SHADOWWIDTH + ( panel.width() - SHADOWWIDTH ) / 2;
62
63 const fheroes2::Sprite & buttonSample = fheroes2::AGG::GetICN( ICN::BTNNEWGM, 0 );
64 const int32_t buttonWidth = buttonSample.width();
65 const int32_t buttonXPos = buttonMiddlePos - buttonWidth / 2 - 3; // 3 is button shadow
66 const int32_t buttonYPos = 46;
67
68 return fheroes2::Point( buttonXPos, buttonYPos );
69 }
70
getVideo(const std::string & fileName)71 std::unique_ptr<SMKVideoSequence> getVideo( const std::string & fileName )
72 {
73 std::string videoPath;
74 if ( !Video::isVideoFile( fileName, videoPath ) ) {
75 return nullptr;
76 }
77
78 std::unique_ptr<SMKVideoSequence> video( new SMKVideoSequence( videoPath ) );
79 if ( video->frameCount() < 1 ) {
80 return nullptr;
81 }
82
83 return video;
84 }
85 }
86
NewStandard()87 fheroes2::GameMode Game::NewStandard()
88 {
89 Settings & conf = Settings::Get();
90 if ( conf.isCampaignGameType() )
91 conf.SetCurrentFileInfo( Maps::FileInfo() );
92 conf.SetGameType( Game::TYPE_STANDARD );
93 conf.SetPreferablyCountPlayers( 0 );
94 return fheroes2::GameMode::SELECT_SCENARIO;
95 }
96
NewBattleOnly()97 fheroes2::GameMode Game::NewBattleOnly()
98 {
99 Settings & conf = Settings::Get();
100 conf.SetGameType( Game::TYPE_BATTLEONLY );
101
102 return fheroes2::GameMode::NEW_MULTI;
103 }
104
NewHotSeat()105 fheroes2::GameMode Game::NewHotSeat()
106 {
107 Settings & conf = Settings::Get();
108 if ( conf.isCampaignGameType() )
109 conf.SetCurrentFileInfo( Maps::FileInfo() );
110
111 if ( conf.IsGameType( Game::TYPE_BATTLEONLY ) ) {
112 conf.SetPreferablyCountPlayers( 2 );
113 world.NewMaps( 10, 10 );
114 return StartBattleOnly();
115 }
116 else {
117 conf.SetGameType( Game::TYPE_HOTSEAT );
118 const u32 select = SelectCountPlayers();
119 if ( select ) {
120 conf.SetPreferablyCountPlayers( select );
121 return fheroes2::GameMode::SELECT_SCENARIO;
122 }
123 }
124 return fheroes2::GameMode::MAIN_MENU;
125 }
126
CampaignSelection()127 fheroes2::GameMode Game::CampaignSelection()
128 {
129 if ( !isPriceOfLoyaltyCampaignPresent() ) {
130 return fheroes2::GameMode::NEW_SUCCESSION_WARS_CAMPAIGN;
131 }
132
133 fheroes2::drawMainMenuScreen();
134 const fheroes2::Point buttonPos = drawButtonPanel();
135
136 fheroes2::Button buttonSuccessionWars( buttonPos.x, buttonPos.y, ICN::X_LOADCM, 0, 1 );
137 fheroes2::Button buttonPriceOfLoyalty( buttonPos.x, buttonPos.y + buttonYStep * 1, ICN::X_LOADCM, 2, 3 );
138 fheroes2::Button buttonCancelGame( buttonPos.x, buttonPos.y + buttonYStep * 5, ICN::BTNMP, 8, 9 );
139
140 buttonSuccessionWars.draw();
141 buttonPriceOfLoyalty.draw();
142 buttonCancelGame.draw();
143
144 fheroes2::Display::instance().render();
145
146 LocalEvent & le = LocalEvent::Get();
147 while ( le.HandleEvents() ) {
148 le.MousePressLeft( buttonSuccessionWars.area() ) ? buttonSuccessionWars.drawOnPress() : buttonSuccessionWars.drawOnRelease();
149 le.MousePressLeft( buttonPriceOfLoyalty.area() ) ? buttonPriceOfLoyalty.drawOnPress() : buttonPriceOfLoyalty.drawOnRelease();
150 le.MousePressLeft( buttonCancelGame.area() ) ? buttonCancelGame.drawOnPress() : buttonCancelGame.drawOnRelease();
151
152 if ( le.MouseClickLeft( buttonSuccessionWars.area() ) || le.KeyPress( KEY_o ) )
153 return fheroes2::GameMode::NEW_SUCCESSION_WARS_CAMPAIGN;
154 if ( le.MouseClickLeft( buttonPriceOfLoyalty.area() ) || le.KeyPress( KEY_e ) )
155 return fheroes2::GameMode::NEW_PRICE_OF_LOYALTY_CAMPAIGN;
156 if ( HotKeyPressEvent( EVENT_DEFAULT_EXIT ) || le.MouseClickLeft( buttonCancelGame.area() ) )
157 return fheroes2::GameMode::MAIN_MENU;
158
159 if ( le.MousePressRight( buttonSuccessionWars.area() ) ) {
160 Dialog::Message( _( "Original Campaign" ), _( "Either Roland's or Archibald's campaign from the original Heroes of Might and Magic II." ), Font::BIG );
161 }
162 if ( le.MousePressRight( buttonPriceOfLoyalty.area() ) ) {
163 Dialog::Message( _( "Expansion Campaign" ), _( "One of the four new campaigns from the Price of Loyalty expansion set." ), Font::BIG );
164 }
165 if ( le.MousePressRight( buttonCancelGame.area() ) ) {
166 Dialog::Message( _( "Cancel" ), _( "Cancel back to the main menu." ), Font::BIG );
167 }
168 }
169
170 return fheroes2::GameMode::QUIT_GAME;
171 }
172
NewSuccessionWarsCampaign()173 fheroes2::GameMode Game::NewSuccessionWarsCampaign()
174 {
175 Settings::Get().SetGameType( Game::TYPE_CAMPAIGN );
176
177 Mixer::Pause();
178 Music::Pause();
179
180 fheroes2::Display & display = fheroes2::Display::instance();
181 const fheroes2::Point roiOffset( ( display.width() - display.DEFAULT_WIDTH ) / 2, ( display.height() - display.DEFAULT_HEIGHT ) / 2 );
182
183 display.fill( 0 );
184
185 const Text loadingScreen( "Loading video. Please wait...", Font::BIG );
186 loadingScreen.Blit( display.width() / 2 - loadingScreen.w() / 2, display.height() / 2 - loadingScreen.h() / 2 );
187 display.render();
188
189 std::vector<fheroes2::Rect> campaignRoi;
190 campaignRoi.emplace_back( 382 + roiOffset.x, 58 + roiOffset.y, 222, 298 );
191 campaignRoi.emplace_back( 30 + roiOffset.x, 59 + roiOffset.y, 224, 297 );
192
193 // Reset all sound and music before playing videos
194 AGG::ResetMixer();
195
196 const CursorRestorer cursorRestorer( false, Cursor::POINTER );
197
198 Video::ShowVideo( "INTRO.SMK", Video::VideoAction::PLAY_TILL_VIDEO_END );
199
200 AGG::ResetMixer();
201 Video::ShowVideo( "CHOOSEW.SMK", Video::VideoAction::IGNORE_VIDEO );
202 const int chosenCampaign = Video::ShowVideo( "CHOOSE.SMK", Video::VideoAction::LOOP_VIDEO, campaignRoi );
203
204 Campaign::CampaignSaveData & campaignSaveData = Campaign::CampaignSaveData::Get();
205 campaignSaveData.reset();
206 campaignSaveData.setCampaignID( chosenCampaign );
207 campaignSaveData.setCurrentScenarioID( 0 );
208
209 AGG::PlayMusic( MUS::VICTORY, true, true );
210
211 return fheroes2::GameMode::SELECT_CAMPAIGN_SCENARIO;
212 }
213
NewPriceOfLoyaltyCampaign()214 fheroes2::GameMode Game::NewPriceOfLoyaltyCampaign()
215 {
216 // TODO: Properly choose the campaign instead of this hackish way
217 Campaign::CampaignSaveData & campaignSaveData = Campaign::CampaignSaveData::Get();
218 campaignSaveData.reset();
219 campaignSaveData.setCampaignID( Campaign::PRICE_OF_LOYALTY_CAMPAIGN );
220 campaignSaveData.setCurrentScenarioID( 0 );
221
222 std::array<std::unique_ptr<SMKVideoSequence>, 4> videos{ getVideo( "IVYPOL.SMK" ), getVideo( "IVYVOY.SMK" ), getVideo( "IVYWIZ.SMK" ), getVideo( "IVYDES.SMK" ) };
223
224 if ( !videos[0] ) {
225 // File doesn't exist. Fallback to PoL campaign.
226 return fheroes2::GameMode::SELECT_CAMPAIGN_SCENARIO;
227 }
228
229 const fheroes2::ScreenPaletteRestorer screenRestorer;
230
231 const CursorRestorer cursorRestorer( true, Cursor::POINTER );
232
233 std::vector<uint8_t> palette = videos[0]->getCurrentPalette();
234 screenRestorer.changePalette( palette.data() );
235
236 Cursor::Get().setVideoPlaybackCursor();
237
238 fheroes2::Display & display = fheroes2::Display::instance();
239 const fheroes2::Point roiOffset( ( display.width() - display.DEFAULT_WIDTH ) / 2, ( display.height() - display.DEFAULT_HEIGHT ) / 2 );
240
241 display.fill( 0 );
242
243 const fheroes2::Sprite & background = fheroes2::AGG::GetICN( ICN::X_IVY, 1 );
244 fheroes2::Blit( background, 0, 0, display, roiOffset.x, roiOffset.y, background.width(), background.height() );
245
246 const fheroes2::Sprite & campaignChoice = fheroes2::AGG::GetICN( ICN::X_IVY, 0 );
247 fheroes2::Blit( campaignChoice, 0, 0, display, roiOffset.x + campaignChoice.x(), roiOffset.y + campaignChoice.y(), campaignChoice.width(), campaignChoice.height() );
248
249 display.render();
250
251 const std::array<fheroes2::Rect, 4> activeCampaignArea{ fheroes2::Rect( roiOffset.x + 192, roiOffset.y + 23, 248, 163 ),
252 fheroes2::Rect( roiOffset.x + 19, roiOffset.y + 120, 166, 193 ),
253 fheroes2::Rect( roiOffset.x + 450, roiOffset.y + 120, 166, 193 ),
254 fheroes2::Rect( roiOffset.x + 192, roiOffset.y + 240, 248, 163 ) };
255
256 const std::array<fheroes2::Rect, 4> renderCampaignArea{ fheroes2::Rect( roiOffset.x + 214, roiOffset.y + 47, 248, 163 ),
257 fheroes2::Rect( roiOffset.x + 41, roiOffset.y + 140, 166, 193 ),
258 fheroes2::Rect( roiOffset.x + 472, roiOffset.y + 131, 166, 193 ),
259 fheroes2::Rect( roiOffset.x + 214, roiOffset.y + 273, 248, 163 ) };
260
261 size_t highlightCampaignId = videos.size();
262
263 fheroes2::GameMode gameChoice = fheroes2::GameMode::NEW_CAMPAIGN_SELECTION;
264 uint64_t customDelay = 0;
265
266 LocalEvent & le = LocalEvent::Get();
267 while ( le.HandleEvents( highlightCampaignId < videos.size() ? Game::isCustomDelayNeeded( customDelay ) : true ) ) {
268 if ( le.MouseClickLeft( activeCampaignArea[0] ) ) {
269 campaignSaveData.setCampaignID( Campaign::PRICE_OF_LOYALTY_CAMPAIGN );
270 gameChoice = fheroes2::GameMode::SELECT_CAMPAIGN_SCENARIO;
271 break;
272 }
273 if ( le.MouseClickLeft( activeCampaignArea[1] ) ) {
274 campaignSaveData.setCampaignID( Campaign::VOYAGE_HOME_CAMPAIGN );
275 gameChoice = fheroes2::GameMode::SELECT_CAMPAIGN_SCENARIO;
276 break;
277 }
278 if ( le.MouseClickLeft( activeCampaignArea[2] ) ) {
279 campaignSaveData.setCampaignID( Campaign::WIZARDS_ISLE_CAMPAIGN );
280 gameChoice = fheroes2::GameMode::SELECT_CAMPAIGN_SCENARIO;
281 break;
282 }
283 if ( le.MouseClickLeft( activeCampaignArea[3] ) ) {
284 campaignSaveData.setCampaignID( Campaign::DESCENDANTS_CAMPAIGN );
285 gameChoice = fheroes2::GameMode::SELECT_CAMPAIGN_SCENARIO;
286 break;
287 }
288
289 const size_t beforeCampaignId = highlightCampaignId;
290
291 highlightCampaignId = videos.size();
292
293 for ( size_t i = 0; i < activeCampaignArea.size(); ++i ) {
294 if ( le.MouseCursor( activeCampaignArea[i] ) && videos[i] ) {
295 highlightCampaignId = i;
296 customDelay = static_cast<uint64_t>( std::lround( 1000.0 / videos[highlightCampaignId]->fps() ) );
297 break;
298 }
299 }
300
301 if ( highlightCampaignId != beforeCampaignId ) {
302 fheroes2::Blit( background, 0, 0, display, roiOffset.x, roiOffset.y, background.width(), background.height() );
303 fheroes2::Blit( campaignChoice, 0, 0, display, roiOffset.x + campaignChoice.x(), roiOffset.y + campaignChoice.y(), campaignChoice.width(),
304 campaignChoice.height() );
305 if ( highlightCampaignId >= videos.size() ) {
306 display.render();
307 }
308 }
309
310 if ( highlightCampaignId < videos.size() && Game::validateCustomAnimationDelay( customDelay ) ) {
311 fheroes2::Rect frameRoi( renderCampaignArea[highlightCampaignId].x, renderCampaignArea[highlightCampaignId].y, 0, 0 );
312 videos[highlightCampaignId]->getNextFrame( display, frameRoi.x, frameRoi.y, frameRoi.width, frameRoi.height, palette );
313
314 fheroes2::Blit( background, frameRoi.x - roiOffset.x, frameRoi.y - roiOffset.y, display, frameRoi.x, frameRoi.y, frameRoi.width, frameRoi.height );
315
316 display.render( frameRoi );
317
318 if ( videos[highlightCampaignId]->frameCount() <= videos[highlightCampaignId]->getCurrentFrame() ) {
319 videos[highlightCampaignId]->resetFrame();
320 }
321 }
322 }
323
324 display.fill( 0 );
325
326 return gameChoice;
327 }
328
NewNetwork()329 fheroes2::GameMode Game::NewNetwork()
330 {
331 Settings & conf = Settings::Get();
332 conf.SetGameType( conf.GameType() | Game::TYPE_NETWORK );
333
334 // setup cursor
335 const CursorRestorer cursorRestorer( true, Cursor::POINTER );
336
337 fheroes2::drawMainMenuScreen();
338 const fheroes2::Point buttonPos = drawButtonPanel();
339
340 fheroes2::Button buttonHost( buttonPos.x, buttonPos.y, ICN::BTNNET, 0, 1 );
341 fheroes2::Button buttonGuest( buttonPos.x, buttonPos.y + buttonYStep, ICN::BTNNET, 2, 3 );
342 fheroes2::Button buttonCancelGame( buttonPos.x, buttonPos.y + buttonYStep * 2, ICN::BTNMP, 8, 9 );
343
344 buttonHost.draw();
345 buttonGuest.draw();
346 buttonCancelGame.draw();
347
348 fheroes2::Display::instance().render();
349
350 LocalEvent & le = LocalEvent::Get();
351 while ( le.HandleEvents() ) {
352 le.MousePressLeft( buttonHost.area() ) ? buttonHost.drawOnPress() : buttonHost.drawOnRelease();
353 le.MousePressLeft( buttonGuest.area() ) ? buttonGuest.drawOnPress() : buttonGuest.drawOnRelease();
354 le.MousePressLeft( buttonCancelGame.area() ) ? buttonCancelGame.drawOnPress() : buttonCancelGame.drawOnRelease();
355
356 if ( HotKeyPressEvent( EVENT_DEFAULT_EXIT ) || le.MouseClickLeft( buttonCancelGame.area() ) )
357 return fheroes2::GameMode::MAIN_MENU;
358
359 // right info
360 if ( le.MousePressRight( buttonHost.area() ) )
361 Dialog::Message( _( "Host" ), _( "The host sets up the game options. There can only be one host per network game." ), Font::BIG );
362 if ( le.MousePressRight( buttonGuest.area() ) )
363 Dialog::Message( _( "Guest" ),
364 _( "The guest waits for the host to set up the game, then is automatically added in. There can be multiple guests for TCP/IP games." ),
365 Font::BIG );
366 if ( le.MousePressRight( buttonCancelGame.area() ) )
367 Dialog::Message( _( "Cancel" ), _( "Cancel back to the main menu." ), Font::BIG );
368 }
369
370 return fheroes2::GameMode::MAIN_MENU;
371 }
372
NewGame()373 fheroes2::GameMode Game::NewGame()
374 {
375 Mixer::Pause();
376 AGG::PlayMusic( MUS::MAINMENU, true, true );
377 Settings & conf = Settings::Get();
378
379 // reset last save name
380 Game::SetLastSavename( "" );
381
382 // setup cursor
383 const CursorRestorer cursorRestorer( true, Cursor::POINTER );
384
385 fheroes2::Display & display = fheroes2::Display::instance();
386
387 // load game settings
388 conf.BinaryLoad();
389
390 fheroes2::drawMainMenuScreen();
391 const fheroes2::Point buttonPos = drawButtonPanel();
392
393 fheroes2::Button buttonStandartGame( buttonPos.x, buttonPos.y, ICN::BTNNEWGM, 0, 1 );
394 fheroes2::ButtonSprite buttonCampainGame( buttonPos.x, buttonPos.y + buttonYStep * 1, fheroes2::AGG::GetICN( ICN::BTNNEWGM, 2 ),
395 fheroes2::AGG::GetICN( ICN::BTNNEWGM, 3 ), fheroes2::AGG::GetICN( ICN::NEW_CAMPAIGN_DISABLED_BUTTON, 0 ) );
396 fheroes2::Button buttonMultiGame( buttonPos.x, buttonPos.y + buttonYStep * 2, ICN::BTNNEWGM, 4, 5 );
397 fheroes2::Button buttonBattleGame( buttonPos.x, buttonPos.y + buttonYStep * 3, ICN::BTNBATTLEONLY, 0, 1 );
398 fheroes2::Button buttonSettings( buttonPos.x, buttonPos.y + buttonYStep * 4, ICN::BTNDCCFG, 4, 5 );
399 fheroes2::Button buttonCancelGame( buttonPos.x, buttonPos.y + buttonYStep * 5, ICN::BTNNEWGM, 6, 7 );
400
401 if ( !isSuccessionWarsCampaignPresent() ) {
402 buttonCampainGame.disable();
403 }
404
405 buttonStandartGame.draw();
406 buttonCampainGame.draw();
407 buttonMultiGame.draw();
408 buttonBattleGame.draw();
409 buttonSettings.draw();
410 buttonCancelGame.draw();
411
412 display.render();
413
414 LocalEvent & le = LocalEvent::Get();
415
416 while ( le.HandleEvents() ) {
417 le.MousePressLeft( buttonStandartGame.area() ) ? buttonStandartGame.drawOnPress() : buttonStandartGame.drawOnRelease();
418
419 if ( buttonCampainGame.isEnabled() ) {
420 le.MousePressLeft( buttonCampainGame.area() ) ? buttonCampainGame.drawOnPress() : buttonCampainGame.drawOnRelease();
421 }
422 le.MousePressLeft( buttonMultiGame.area() ) ? buttonMultiGame.drawOnPress() : buttonMultiGame.drawOnRelease();
423 le.MousePressLeft( buttonBattleGame.area() ) ? buttonBattleGame.drawOnPress() : buttonBattleGame.drawOnRelease();
424 le.MousePressLeft( buttonSettings.area() ) ? buttonSettings.drawOnPress() : buttonSettings.drawOnRelease();
425 le.MousePressLeft( buttonCancelGame.area() ) ? buttonCancelGame.drawOnPress() : buttonCancelGame.drawOnRelease();
426
427 if ( HotKeyPressEvent( EVENT_BUTTON_STANDARD ) || le.MouseClickLeft( buttonStandartGame.area() ) )
428 return fheroes2::GameMode::NEW_STANDARD;
429 if ( buttonCampainGame.isEnabled() && ( HotKeyPressEvent( EVENT_BUTTON_CAMPAIGN ) || le.MouseClickLeft( buttonCampainGame.area() ) ) )
430 return fheroes2::GameMode::NEW_CAMPAIGN_SELECTION;
431 if ( HotKeyPressEvent( EVENT_BUTTON_MULTI ) || le.MouseClickLeft( buttonMultiGame.area() ) )
432 return fheroes2::GameMode::NEW_MULTI;
433 if ( HotKeyPressEvent( EVENT_BUTTON_SETTINGS ) || le.MouseClickLeft( buttonSettings.area() ) ) {
434 fheroes2::openGameSettings();
435 return fheroes2::GameMode::MAIN_MENU;
436 }
437 if ( HotKeyPressEvent( EVENT_DEFAULT_EXIT ) || le.MouseClickLeft( buttonCancelGame.area() ) )
438 return fheroes2::GameMode::MAIN_MENU;
439
440 if ( HotKeyPressEvent( EVENT_BUTTON_BATTLEONLY ) || le.MouseClickLeft( buttonBattleGame.area() ) )
441 return fheroes2::GameMode::NEW_BATTLE_ONLY;
442
443 if ( le.MousePressRight( buttonStandartGame.area() ) )
444 Dialog::Message( _( "Standard Game" ), _( "A single player game playing out a single map." ), Font::BIG );
445 else if ( le.MousePressRight( buttonCampainGame.area() ) )
446 Dialog::Message( _( "Campaign Game" ), _( "A single player game playing through a series of maps." ), Font::BIG );
447 else if ( le.MousePressRight( buttonMultiGame.area() ) )
448 Dialog::Message( _( "Multi-Player Game" ), _( "A multi-player game, with several human players completing against each other on a single map." ), Font::BIG );
449 else if ( le.MousePressRight( buttonBattleGame.area() ) )
450 Dialog::Message( _( "Battle Only" ), _( "Setup and play a battle without loading any map." ), Font::BIG );
451 else if ( le.MousePressRight( buttonSettings.area() ) )
452 Dialog::Message( _( "Game Settings" ), _( "Change language, resolution and settings of the game." ), Font::BIG );
453 else if ( le.MousePressRight( buttonCancelGame.area() ) )
454 Dialog::Message( _( "Cancel" ), _( "Cancel back to the main menu." ), Font::BIG );
455 }
456
457 return fheroes2::GameMode::QUIT_GAME;
458 }
459
NewMulti()460 fheroes2::GameMode Game::NewMulti()
461 {
462 Settings & conf = Settings::Get();
463
464 if ( !( conf.IsGameType( Game::TYPE_BATTLEONLY ) ) )
465 conf.SetGameType( Game::TYPE_STANDARD );
466
467 // setup cursor
468 const CursorRestorer cursorRestorer( true, Cursor::POINTER );
469
470 fheroes2::drawMainMenuScreen();
471 const fheroes2::Point buttonPos = drawButtonPanel();
472
473 fheroes2::Button buttonHotSeat( buttonPos.x, buttonPos.y, ICN::BTNMP, 0, 1 );
474 fheroes2::Button buttonNetwork( buttonPos.x, buttonPos.y + buttonYStep * 1, ICN::BTNMP, 2, 3 );
475 fheroes2::Button buttonCancelGame( buttonPos.x, buttonPos.y + buttonYStep * 5, ICN::BTNMP, 8, 9 );
476
477 buttonHotSeat.draw();
478 buttonCancelGame.draw();
479 buttonNetwork.disable();
480
481 fheroes2::Display::instance().render();
482
483 LocalEvent & le = LocalEvent::Get();
484 // newgame loop
485 while ( le.HandleEvents() ) {
486 le.MousePressLeft( buttonHotSeat.area() ) ? buttonHotSeat.drawOnPress() : buttonHotSeat.drawOnRelease();
487 le.MousePressLeft( buttonCancelGame.area() ) ? buttonCancelGame.drawOnPress() : buttonCancelGame.drawOnRelease();
488
489 if ( le.MouseClickLeft( buttonHotSeat.area() ) || HotKeyPressEvent( EVENT_BUTTON_HOTSEAT ) )
490 return fheroes2::GameMode::NEW_HOT_SEAT;
491 if ( HotKeyPressEvent( EVENT_DEFAULT_EXIT ) || le.MouseClickLeft( buttonCancelGame.area() ) )
492 return fheroes2::GameMode::MAIN_MENU;
493
494 // right info
495 if ( le.MousePressRight( buttonHotSeat.area() ) )
496 Dialog::Message( _( "Hot Seat" ),
497 _( "Play a Hot Seat game, where 2 to 4 players play around the same computer, switching into the 'Hot Seat' when it is their turn." ),
498 Font::BIG );
499 if ( le.MousePressRight( buttonCancelGame.area() ) )
500 Dialog::Message( _( "Cancel" ), _( "Cancel back to the main menu." ), Font::BIG );
501 }
502
503 return fheroes2::GameMode::QUIT_GAME;
504 }
505
SelectCountPlayers(void)506 u32 Game::SelectCountPlayers( void )
507 {
508 // setup cursor
509 const CursorRestorer cursorRestorer( true, Cursor::POINTER );
510
511 fheroes2::drawMainMenuScreen();
512 const fheroes2::Point buttonPos = drawButtonPanel();
513
514 fheroes2::Button button2Players( buttonPos.x, buttonPos.y, ICN::BTNHOTST, 0, 1 );
515 fheroes2::Button button3Players( buttonPos.x, buttonPos.y + buttonYStep * 1, ICN::BTNHOTST, 2, 3 );
516 fheroes2::Button button4Players( buttonPos.x, buttonPos.y + buttonYStep * 2, ICN::BTNHOTST, 4, 5 );
517 fheroes2::Button button5Players( buttonPos.x, buttonPos.y + buttonYStep * 3, ICN::BTNHOTST, 6, 7 );
518 fheroes2::Button button6Players( buttonPos.x, buttonPos.y + buttonYStep * 4, ICN::BTNHOTST, 8, 9 );
519 fheroes2::Button buttonCancel( buttonPos.x, buttonPos.y + buttonYStep * 5, ICN::BTNNEWGM, 6, 7 );
520
521 button2Players.draw();
522 button3Players.draw();
523 button4Players.draw();
524 button5Players.draw();
525 button6Players.draw();
526 buttonCancel.draw();
527
528 fheroes2::Display::instance().render();
529
530 LocalEvent & le = LocalEvent::Get();
531 while ( le.HandleEvents() ) {
532 le.MousePressLeft( button2Players.area() ) ? button2Players.drawOnPress() : button2Players.drawOnRelease();
533 le.MousePressLeft( button3Players.area() ) ? button3Players.drawOnPress() : button3Players.drawOnRelease();
534 le.MousePressLeft( button4Players.area() ) ? button4Players.drawOnPress() : button4Players.drawOnRelease();
535 le.MousePressLeft( button5Players.area() ) ? button5Players.drawOnPress() : button5Players.drawOnRelease();
536 le.MousePressLeft( button6Players.area() ) ? button6Players.drawOnPress() : button6Players.drawOnRelease();
537
538 le.MousePressLeft( buttonCancel.area() ) ? buttonCancel.drawOnPress() : buttonCancel.drawOnRelease();
539
540 if ( le.MouseClickLeft( button2Players.area() ) || le.KeyPress( KEY_2 ) )
541 return 2;
542 if ( le.MouseClickLeft( button3Players.area() ) || le.KeyPress( KEY_3 ) )
543 return 3;
544 if ( le.MouseClickLeft( button4Players.area() ) || le.KeyPress( KEY_4 ) )
545 return 4;
546 if ( le.MouseClickLeft( button5Players.area() ) || le.KeyPress( KEY_5 ) )
547 return 5;
548 if ( le.MouseClickLeft( button6Players.area() ) || le.KeyPress( KEY_6 ) )
549 return 6;
550
551 if ( HotKeyPressEvent( Game::EVENT_DEFAULT_EXIT ) || le.MouseClickLeft( buttonCancel.area() ) )
552 return 0;
553
554 // right info
555 if ( le.MousePressRight( button2Players.area() ) )
556 Dialog::Message( _( "2 Players" ), _( "Play with 2 human players, and optionally, up to 4 additional computer players." ), Font::BIG );
557 if ( le.MousePressRight( button3Players.area() ) )
558 Dialog::Message( _( "3 Players" ), _( "Play with 3 human players, and optionally, up to 3 additional computer players." ), Font::BIG );
559 if ( le.MousePressRight( button4Players.area() ) )
560 Dialog::Message( _( "4 Players" ), _( "Play with 4 human players, and optionally, up to 2 additional computer players." ), Font::BIG );
561 if ( le.MousePressRight( button5Players.area() ) )
562 Dialog::Message( _( "5 Players" ), _( "Play with 5 human players, and optionally, up to 1 additional computer player." ), Font::BIG );
563 if ( le.MousePressRight( button6Players.area() ) )
564 Dialog::Message( _( "6 Players" ), _( "Play with 6 human players." ), Font::BIG );
565 if ( le.MousePressRight( buttonCancel.area() ) )
566 Dialog::Message( _( "Cancel" ), _( "Cancel back to the main menu." ), Font::BIG );
567 }
568
569 return 0;
570 }
571