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 "agg.h"
24 #include "agg_image.h"
25 #include "audio.h"
26 #include "cursor.h"
27 #include "dialog.h"
28 #include "dialog_game_settings.h"
29 #include "dialog_language_selection.h"
30 #include "dialog_resolution.h"
31 #include "game.h"
32 #include "game_delays.h"
33 #include "game_interface.h"
34 #include "game_mainmenu_ui.h"
35 #include "icn.h"
36 #include "image.h"
37 #include "localevent.h"
38 #include "mus.h"
39 #include "settings.h"
40 #include "text.h"
41 #include "translations.h"
42 #include "ui_button.h"
43 #include "ui_dialog.h"
44 #include "ui_text.h"
45
46 namespace
47 {
48 struct ButtonInfo
49 {
50 u32 frame;
51 fheroes2::Button & button;
52 bool isOver;
53 bool wasOver;
54 };
55
56 enum
57 {
58 NEWGAME_DEFAULT = 1,
59 LOADGAME_DEFAULT = 5,
60 HIGHSCORES_DEFAULT = 9,
61 CREDITS_DEFAULT = 13,
62 QUIT_DEFAULT = 17
63 };
64 }
65
mainGameLoop(bool isFirstGameRun)66 void Game::mainGameLoop( bool isFirstGameRun )
67 {
68 fheroes2::GameMode result = fheroes2::GameMode::MAIN_MENU;
69
70 while ( result != fheroes2::GameMode::QUIT_GAME ) {
71 switch ( result ) {
72 case fheroes2::GameMode::MAIN_MENU:
73 result = Game::MainMenu( isFirstGameRun );
74 isFirstGameRun = false;
75 break;
76 case fheroes2::GameMode::NEW_GAME:
77 result = Game::NewGame();
78 break;
79 case fheroes2::GameMode::LOAD_GAME:
80 result = Game::LoadGame();
81 break;
82 case fheroes2::GameMode::HIGHSCORES:
83 result = Game::HighScores();
84 break;
85 case fheroes2::GameMode::CREDITS:
86 result = Game::Credits();
87 break;
88 case fheroes2::GameMode::NEW_STANDARD:
89 result = Game::NewStandard();
90 break;
91 case fheroes2::GameMode::NEW_CAMPAIGN_SELECTION:
92 result = Game::CampaignSelection();
93 break;
94 case fheroes2::GameMode::NEW_SUCCESSION_WARS_CAMPAIGN:
95 result = Game::NewSuccessionWarsCampaign();
96 break;
97 case fheroes2::GameMode::NEW_PRICE_OF_LOYALTY_CAMPAIGN:
98 result = Game::NewPriceOfLoyaltyCampaign();
99 break;
100 case fheroes2::GameMode::NEW_MULTI:
101 result = Game::NewMulti();
102 break;
103 case fheroes2::GameMode::NEW_HOT_SEAT:
104 result = Game::NewHotSeat();
105 break;
106 case fheroes2::GameMode::NEW_BATTLE_ONLY:
107 result = Game::NewBattleOnly();
108 break;
109 case fheroes2::GameMode::LOAD_STANDARD:
110 result = Game::LoadStandard();
111 break;
112 case fheroes2::GameMode::LOAD_CAMPAIN:
113 result = Game::LoadCampaign();
114 break;
115 case fheroes2::GameMode::LOAD_MULTI:
116 result = Game::LoadMulti();
117 break;
118 case fheroes2::GameMode::LOAD_HOT_SEAT:
119 result = Game::LoadHotseat();
120 break;
121 case fheroes2::GameMode::SCENARIO_INFO:
122 result = Game::ScenarioInfo();
123 break;
124 case fheroes2::GameMode::SELECT_SCENARIO:
125 result = Game::SelectScenario();
126 break;
127 case fheroes2::GameMode::START_GAME:
128 result = Game::StartGame();
129 break;
130 case fheroes2::GameMode::SELECT_CAMPAIGN_SCENARIO:
131 result = Game::SelectCampaignScenario( fheroes2::GameMode::MAIN_MENU, false );
132 break;
133 case fheroes2::GameMode::COMPLETE_CAMPAIGN_SCENARIO:
134 result = Game::CompleteCampaignScenario( false );
135 break;
136 case fheroes2::GameMode::COMPLETE_CAMPAIGN_SCENARIO_FROM_LOAD_FILE:
137 result = Game::CompleteCampaignScenario( true );
138 if ( result == fheroes2::GameMode::SELECT_CAMPAIGN_SCENARIO ) {
139 result = Game::SelectCampaignScenario( fheroes2::GameMode::LOAD_CAMPAIN, false );
140 }
141 break;
142
143 default:
144 break;
145 }
146 }
147 }
148
MainMenu(bool isFirstGameRun)149 fheroes2::GameMode Game::MainMenu( bool isFirstGameRun )
150 {
151 Mixer::Pause();
152 AGG::PlayMusic( MUS::MAINMENU, true, true );
153
154 Settings & conf = Settings::Get();
155
156 conf.SetGameType( TYPE_MENU );
157
158 // setup cursor
159 const CursorRestorer cursorRestorer( true, Cursor::POINTER );
160
161 fheroes2::Display & display = fheroes2::Display::instance();
162
163 // image background
164 fheroes2::drawMainMenuScreen();
165 if ( isFirstGameRun ) {
166 fheroes2::SupportedLanguage currentLanguage = fheroes2::getLanguageFromAbbreviation( conf.getGameLanguage() );
167 const std::vector<fheroes2::SupportedLanguage> supportedLanguages = fheroes2::getSupportedLanguages();
168
169 if ( supportedLanguages.size() > 1 ) {
170 currentLanguage = fheroes2::selectLanguage( supportedLanguages, currentLanguage );
171 conf.setGameLanguage( fheroes2::getLanguageAbbreviation( currentLanguage ) );
172 }
173
174 Dialog::Message( _( "Greetings!" ), _( "Welcome to Free Heroes of Might and Magic II! Before starting the game please choose game resolution." ), Font::BIG,
175 Dialog::OK );
176
177 bool isResolutionChanged = Dialog::SelectResolution();
178 if ( isResolutionChanged ) {
179 fheroes2::drawMainMenuScreen();
180 }
181
182 fheroes2::Text header( _( "Please Remember" ), { fheroes2::FontSize::NORMAL, fheroes2::FontColor::YELLOW } );
183
184 fheroes2::MultiFontText body;
185 body.add( { _( "You can always change game resolution by clicking on the " ), { fheroes2::FontSize::NORMAL, fheroes2::FontColor::WHITE } } );
186 body.add( { _( "door" ), { fheroes2::FontSize::NORMAL, fheroes2::FontColor::YELLOW } } );
187 body.add( { _( " on the left side of main menu.\n\nTo switch between windowed and full screen modes\npress " ),
188 { fheroes2::FontSize::NORMAL, fheroes2::FontColor::WHITE } } );
189 body.add( { _( "F4" ), { fheroes2::FontSize::NORMAL, fheroes2::FontColor::YELLOW } } );
190 body.add( { _( " key on the keyboard.\n\nEnjoy the game!" ), { fheroes2::FontSize::NORMAL, fheroes2::FontColor::WHITE } } );
191
192 fheroes2::showMessage( header, body, Dialog::OK );
193
194 conf.resetFirstGameRun();
195 conf.Save( "fheroes2.cfg" );
196 }
197
198 LocalEvent & le = LocalEvent::Get();
199
200 fheroes2::Button buttonNewGame( 0, 0, ICN::BTNSHNGL, NEWGAME_DEFAULT, NEWGAME_DEFAULT + 2 );
201 fheroes2::Button buttonLoadGame( 0, 0, ICN::BTNSHNGL, LOADGAME_DEFAULT, LOADGAME_DEFAULT + 2 );
202 fheroes2::Button buttonHighScores( 0, 0, ICN::BTNSHNGL, HIGHSCORES_DEFAULT, HIGHSCORES_DEFAULT + 2 );
203 fheroes2::Button buttonCredits( 0, 0, ICN::BTNSHNGL, CREDITS_DEFAULT, CREDITS_DEFAULT + 2 );
204 fheroes2::Button buttonQuit( 0, 0, ICN::BTNSHNGL, QUIT_DEFAULT, QUIT_DEFAULT + 2 );
205
206 const fheroes2::Sprite & lantern10 = fheroes2::AGG::GetICN( ICN::SHNGANIM, 0 );
207 fheroes2::Blit( lantern10, display, lantern10.x(), lantern10.y() );
208
209 const fheroes2::Sprite & lantern11 = fheroes2::AGG::GetICN( ICN::SHNGANIM, ICN::AnimationFrame( ICN::SHNGANIM, 0, 0 ) );
210 fheroes2::Blit( lantern11, display, lantern11.x(), lantern11.y() );
211
212 buttonNewGame.draw();
213 buttonLoadGame.draw();
214 buttonHighScores.draw();
215 buttonCredits.draw();
216 buttonQuit.draw();
217
218 display.render();
219
220 const double scaleX = static_cast<double>( display.width() ) / fheroes2::Display::DEFAULT_WIDTH;
221 const double scaleY = static_cast<double>( display.height() ) / fheroes2::Display::DEFAULT_HEIGHT;
222 const fheroes2::Rect settingsArea( static_cast<int32_t>( 63 * scaleX ), static_cast<int32_t>( 202 * scaleY ), static_cast<int32_t>( 90 * scaleX ),
223 static_cast<int32_t>( 160 * scaleY ) );
224
225 u32 lantern_frame = 0;
226
227 std::vector<ButtonInfo> buttons{ { NEWGAME_DEFAULT, buttonNewGame, false, false },
228 { LOADGAME_DEFAULT, buttonLoadGame, false, false },
229 { HIGHSCORES_DEFAULT, buttonHighScores, false, false },
230 { CREDITS_DEFAULT, buttonCredits, false, false },
231 { QUIT_DEFAULT, buttonQuit, false, false } };
232
233 for ( size_t i = 0; le.MouseMotion() && i < buttons.size(); ++i ) {
234 const fheroes2::Sprite & sprite = fheroes2::AGG::GetICN( ICN::BTNSHNGL, buttons[i].frame );
235 fheroes2::Blit( sprite, display, sprite.x(), sprite.y() );
236 }
237
238 fheroes2::Sprite highlightDoor = fheroes2::AGG::GetICN( ICN::SHNGANIM, 18 );
239 fheroes2::ApplyPalette( highlightDoor, 8 );
240
241 // mainmenu loop
242 while ( true ) {
243 if ( !le.HandleEvents( true, true ) ) {
244 if ( Interface::Basic::EventExit() == fheroes2::GameMode::QUIT_GAME ) {
245 // if ( conf.ExtGameUseFade() )
246 // display.Fade();
247 break;
248 }
249 else {
250 continue;
251 }
252 }
253
254 bool redrawScreen = false;
255
256 for ( size_t i = 0; i < buttons.size(); ++i ) {
257 buttons[i].wasOver = buttons[i].isOver;
258
259 if ( le.MousePressLeft( buttons[i].button.area() ) ) {
260 buttons[i].button.drawOnPress();
261 }
262 else {
263 buttons[i].button.drawOnRelease();
264 }
265
266 buttons[i].isOver = le.MouseCursor( buttons[i].button.area() );
267
268 if ( buttons[i].isOver != buttons[i].wasOver ) {
269 u32 frame = buttons[i].frame;
270
271 if ( buttons[i].isOver && !buttons[i].wasOver )
272 ++frame;
273
274 if ( !redrawScreen ) {
275 redrawScreen = true;
276 }
277 const fheroes2::Sprite & sprite = fheroes2::AGG::GetICN( ICN::BTNSHNGL, frame );
278 fheroes2::Blit( sprite, display, sprite.x(), sprite.y() );
279 }
280 }
281
282 if ( redrawScreen ) {
283 display.render();
284 }
285
286 if ( HotKeyPressEvent( EVENT_BUTTON_NEWGAME ) || le.MouseClickLeft( buttonNewGame.area() ) )
287 return fheroes2::GameMode::NEW_GAME;
288 else if ( HotKeyPressEvent( EVENT_BUTTON_LOADGAME ) || le.MouseClickLeft( buttonLoadGame.area() ) )
289 return fheroes2::GameMode::LOAD_GAME;
290 else if ( HotKeyPressEvent( EVENT_BUTTON_HIGHSCORES ) || le.MouseClickLeft( buttonHighScores.area() ) )
291 return fheroes2::GameMode::HIGHSCORES;
292 else if ( HotKeyPressEvent( EVENT_BUTTON_CREDITS ) || le.MouseClickLeft( buttonCredits.area() ) )
293 return fheroes2::GameMode::CREDITS;
294 else if ( HotKeyPressEvent( EVENT_DEFAULT_EXIT ) || le.MouseClickLeft( buttonQuit.area() ) ) {
295 if ( Interface::Basic::EventExit() == fheroes2::GameMode::QUIT_GAME ) {
296 // if ( conf.ExtGameUseFade() )
297 // display.Fade();
298 return fheroes2::GameMode::QUIT_GAME;
299 }
300 }
301 else if ( HotKeyPressEvent( EVENT_BUTTON_SETTINGS ) || le.MouseClickLeft( settingsArea ) ) {
302 fheroes2::openGameSettings();
303
304 // force interface to reset area and positions
305 Interface::Basic::Get().Reset();
306 return fheroes2::GameMode::MAIN_MENU;
307 }
308
309 // right info
310 if ( le.MousePressRight( buttonQuit.area() ) )
311 Dialog::Message( _( "Quit" ), _( "Quit Heroes of Might and Magic and return to the operating system." ), Font::BIG );
312 else if ( le.MousePressRight( buttonLoadGame.area() ) )
313 Dialog::Message( _( "Load Game" ), _( "Load a previously saved game." ), Font::BIG );
314 else if ( le.MousePressRight( buttonCredits.area() ) )
315 Dialog::Message( _( "Credits" ), _( "View the credits screen." ), Font::BIG );
316 else if ( le.MousePressRight( buttonHighScores.area() ) )
317 Dialog::Message( _( "High Scores" ), _( "View the high scores screen." ), Font::BIG );
318 else if ( le.MousePressRight( buttonNewGame.area() ) )
319 Dialog::Message( _( "New Game" ), _( "Start a single or multi-player game." ), Font::BIG );
320 else if ( le.MousePressRight( settingsArea ) )
321 Dialog::Message( _( "Game Settings" ), _( "Change language, resolution and settings of the game." ), Font::BIG );
322
323 if ( validateAnimationDelay( MAIN_MENU_DELAY ) ) {
324 const fheroes2::Sprite & lantern12 = fheroes2::AGG::GetICN( ICN::SHNGANIM, ICN::AnimationFrame( ICN::SHNGANIM, 0, lantern_frame ) );
325 ++lantern_frame;
326 fheroes2::Blit( lantern12, display, lantern12.x(), lantern12.y() );
327 if ( le.MouseCursor( settingsArea ) ) {
328 const int32_t offsetY = static_cast<int32_t>( 55 * scaleY );
329 fheroes2::Blit( highlightDoor, 0, offsetY, display, highlightDoor.x(), highlightDoor.y() + offsetY, highlightDoor.width(), highlightDoor.height() );
330 }
331
332 display.render();
333 }
334 }
335
336 return fheroes2::GameMode::QUIT_GAME;
337 }
338