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 <algorithm>
24 #include <cstdlib>
25 #include <fstream>
26 
27 #include "difficulty.h"
28 #include "game.h"
29 #include "logging.h"
30 #include "save_format_version.h"
31 #include "screen.h"
32 #include "serialize.h"
33 #include "settings.h"
34 #include "system.h"
35 #include "tinyconfig.h"
36 #include "tools.h"
37 #include "translations.h"
38 #include "ui_language.h"
39 #include "version.h"
40 
41 #define STRINGIFY( DEF ) #DEF
42 #define EXPANDDEF( DEF ) STRINGIFY( DEF )
43 
44 namespace
45 {
46     enum
47     {
48         GLOBAL_FIRST_RUN = 0x00000001,
49         GLOBAL_SHOW_INTRO = 0x00000002,
50         GLOBAL_PRICELOYALTY = 0x00000004,
51 
52         GLOBAL_RENDER_VSYNC = 0x00000008,
53         // UNUSED = 0x00000010,
54         // UNUSED = 0x00000020,
55 
56         GLOBAL_SHOWCPANEL = 0x00000040,
57         GLOBAL_SHOWRADAR = 0x00000080,
58         GLOBAL_SHOWICONS = 0x00000100,
59         GLOBAL_SHOWBUTTONS = 0x00000200,
60         GLOBAL_SHOWSTATUS = 0x00000400,
61 
62         GLOBAL_FULLSCREEN = 0x00008000,
63         // UNUSED = 0x00010000,
64 
65         GLOBAL_MUSIC_EXT = 0x00020000,
66         GLOBAL_MUSIC_MIDI = 0x00040000,
67         GLOBAL_MUSIC = GLOBAL_MUSIC_EXT | GLOBAL_MUSIC_MIDI,
68 
69         // UNUSED = 0x00080000,
70         // UNUSED = 0x00100000,
71         // UNUSED = 0x00200000,
72         // UNUSED = 0x00400000,
73 
74         GLOBAL_BATTLE_SHOW_GRID = 0x00800000,
75         GLOBAL_BATTLE_SHOW_MOUSE_SHADOW = 0x01000000,
76         GLOBAL_BATTLE_SHOW_MOVE_SHADOW = 0x02000000,
77         GLOBAL_BATTLE_AUTO_RESOLVE = 0x04000000,
78         GLOBAL_BATTLE_AUTO_SPELLCAST = 0x08000000
79     };
80 }
81 
GetVersion()82 std::string Settings::GetVersion()
83 {
84     return std::to_string( MAJOR_VERSION ) + '.' + std::to_string( MINOR_VERSION ) + '.' + std::to_string( INTERMEDIATE_VERSION );
85 }
86 
Settings()87 Settings::Settings()
88     : debug( 0 )
89     , video_mode( fheroes2::Size( fheroes2::Display::DEFAULT_WIDTH, fheroes2::Display::DEFAULT_HEIGHT ) )
90     , game_difficulty( Difficulty::NORMAL )
91     , sound_volume( 6 )
92     , music_volume( 6 )
93     , _musicType( MUSIC_EXTERNAL )
94     , _controllerPointerSpeed( 10 )
95     , heroes_speed( DEFAULT_SPEED_DELAY )
96     , ai_speed( DEFAULT_SPEED_DELAY )
97     , scroll_speed( SCROLL_NORMAL )
98     , battle_speed( DEFAULT_BATTLE_SPEED )
99     , game_type( 0 )
100     , preferably_count_players( 0 )
101 {
102     ExtSetModes( GAME_AUTOSAVE_ON );
103 
104     opt_global.SetModes( GLOBAL_FIRST_RUN );
105     opt_global.SetModes( GLOBAL_SHOW_INTRO );
106     opt_global.SetModes( GLOBAL_SHOWRADAR );
107     opt_global.SetModes( GLOBAL_SHOWICONS );
108     opt_global.SetModes( GLOBAL_SHOWBUTTONS );
109     opt_global.SetModes( GLOBAL_SHOWSTATUS );
110     opt_global.SetModes( GLOBAL_MUSIC_EXT );
111 
112     opt_global.SetModes( GLOBAL_BATTLE_SHOW_GRID );
113     opt_global.SetModes( GLOBAL_BATTLE_SHOW_MOUSE_SHADOW );
114     opt_global.SetModes( GLOBAL_BATTLE_SHOW_MOVE_SHADOW );
115     opt_global.SetModes( GLOBAL_BATTLE_AUTO_SPELLCAST );
116 
117     // The Price of Loyalty is not supported by default.
118     EnablePriceOfLoyaltySupport( false );
119 }
120 
~Settings()121 Settings::~Settings()
122 {
123     if ( !LoadedGameVersion() )
124         BinarySave();
125 }
126 
Get()127 Settings & Settings::Get()
128 {
129     static Settings conf;
130 
131     return conf;
132 }
133 
Read(const std::string & filename)134 bool Settings::Read( const std::string & filename )
135 {
136     TinyConfig config( '=', '#' );
137 
138     std::string sval;
139     int ival;
140 
141     if ( !config.Load( filename ) )
142         return false;
143 
144     // debug
145     ival = config.IntParams( "debug" );
146 
147     switch ( ival ) {
148     case 0:
149         debug = DBG_ALL_WARN;
150         break;
151     case 1:
152         debug = DBG_ALL_INFO;
153         break;
154     case 2:
155         debug = DBG_ALL_TRACE;
156         break;
157     case 3:
158         debug = DBG_ENGINE_TRACE;
159         break;
160     case 4:
161         debug = DBG_GAME_INFO | DBG_BATTLE_INFO | DBG_AI_INFO;
162         break;
163     case 5:
164         debug = DBG_GAME_TRACE | DBG_AI_INFO | DBG_BATTLE_INFO;
165         break;
166     case 6:
167         debug = DBG_AI_TRACE | DBG_BATTLE_INFO | DBG_GAME_INFO;
168         break;
169     case 7:
170         debug = DBG_BATTLE_TRACE | DBG_AI_INFO | DBG_GAME_INFO;
171         break;
172     case 8:
173         debug = DBG_DEVEL | DBG_GAME_TRACE;
174         break;
175     case 9:
176         debug = DBG_DEVEL | DBG_AI_INFO | DBG_BATTLE_INFO | DBG_GAME_INFO;
177         break;
178     case 10:
179         debug = DBG_DEVEL | DBG_AI_TRACE | DBG_BATTLE_INFO | DBG_GAME_INFO;
180         break;
181     case 11:
182         debug = DBG_DEVEL | DBG_AI_TRACE | DBG_BATTLE_TRACE | DBG_GAME_INFO;
183         break;
184     default:
185         debug = ival;
186         break;
187     }
188 
189 #ifndef WITH_DEBUG
190     // reset devel
191     debug &= ~( DBG_DEVEL );
192 #endif
193 
194     Logging::SetDebugLevel( debug );
195 
196     // game language
197     sval = config.StrParams( "lang" );
198     if ( !sval.empty() ) {
199         _gameLanguage = sval;
200     }
201 
202     // music source
203     _musicType = MUSIC_EXTERNAL;
204     sval = config.StrParams( "music" );
205 
206     if ( !sval.empty() ) {
207         if ( sval == "original" ) {
208             opt_global.ResetModes( GLOBAL_MUSIC );
209             opt_global.SetModes( GLOBAL_MUSIC_MIDI );
210             _musicType = MUSIC_MIDI_ORIGINAL;
211         }
212         else if ( sval == "expansion" ) {
213             opt_global.ResetModes( GLOBAL_MUSIC );
214             opt_global.SetModes( GLOBAL_MUSIC_MIDI );
215             _musicType = MUSIC_MIDI_EXPANSION;
216         }
217         else if ( sval == "external" ) {
218             opt_global.ResetModes( GLOBAL_MUSIC );
219             opt_global.SetModes( GLOBAL_MUSIC_EXT );
220             _musicType = MUSIC_EXTERNAL;
221         }
222     }
223 
224     // sound volume
225     if ( config.Exists( "sound volume" ) ) {
226         SetSoundVolume( config.IntParams( "sound volume" ) );
227     }
228 
229     // music volume
230     if ( config.Exists( "music volume" ) ) {
231         SetMusicVolume( config.IntParams( "music volume" ) );
232     }
233 
234     // move speed
235     if ( config.Exists( "ai speed" ) ) {
236         SetAIMoveSpeed( config.IntParams( "ai speed" ) );
237     }
238 
239     if ( config.Exists( "heroes speed" ) ) {
240         SetHeroesMoveSpeed( config.IntParams( "heroes speed" ) );
241     }
242 
243     // scroll speed
244     SetScrollSpeed( config.IntParams( "scroll speed" ) );
245 
246     if ( config.Exists( "battle speed" ) ) {
247         SetBattleSpeed( config.IntParams( "battle speed" ) );
248     }
249 
250     if ( config.Exists( "battle grid" ) ) {
251         SetBattleGrid( config.StrParams( "battle grid" ) == "on" );
252     }
253 
254     if ( config.Exists( "battle shadow movement" ) ) {
255         SetBattleMovementShaded( config.StrParams( "battle shadow movement" ) == "on" );
256     }
257 
258     if ( config.Exists( "battle shadow cursor" ) ) {
259         SetBattleMouseShaded( config.StrParams( "battle shadow cursor" ) == "on" );
260     }
261 
262     if ( config.Exists( "auto resolve battles" ) ) {
263         setBattleAutoResolve( config.StrParams( "auto resolve battles" ) == "on" );
264     }
265 
266     if ( config.Exists( "auto spell casting" ) ) {
267         setBattleAutoSpellcast( config.StrParams( "auto spell casting" ) == "on" );
268     }
269 
270     // videomode
271     sval = config.StrParams( "videomode" );
272     if ( !sval.empty() ) {
273         // default
274         video_mode.width = fheroes2::Display::DEFAULT_WIDTH;
275         video_mode.height = fheroes2::Display::DEFAULT_HEIGHT;
276 
277         std::string value = StringLower( sval );
278         const size_t pos = value.find( 'x' );
279 
280         if ( std::string::npos != pos ) {
281             std::string width( value.substr( 0, pos ) );
282             std::string height( value.substr( pos + 1, value.length() - pos - 1 ) );
283 
284             video_mode.width = GetInt( width );
285             video_mode.height = GetInt( height );
286         }
287         else {
288             DEBUG_LOG( DBG_ENGINE, DBG_WARN, "unknown video mode: " << value );
289         }
290     }
291 
292     // full screen
293     if ( config.Exists( "fullscreen" ) ) {
294         setFullScreen( config.StrParams( "fullscreen" ) == "on" );
295     }
296 
297     if ( config.Exists( "controller pointer speed" ) ) {
298         _controllerPointerSpeed = clamp( config.IntParams( "controller pointer speed" ), 0, 100 );
299     }
300 
301     if ( config.Exists( "first time game run" ) && config.StrParams( "first time game run" ) == "off" ) {
302         resetFirstGameRun();
303     }
304 
305     if ( config.Exists( "show game intro" ) ) {
306         if ( config.StrParams( "show game intro" ) == "on" ) {
307             opt_global.SetModes( GLOBAL_SHOW_INTRO );
308         }
309         else {
310             opt_global.ResetModes( GLOBAL_SHOW_INTRO );
311         }
312     }
313 
314     if ( config.Exists( "v-sync" ) ) {
315         if ( config.StrParams( "v-sync" ) == "on" ) {
316             opt_global.SetModes( GLOBAL_RENDER_VSYNC );
317         }
318         else {
319             opt_global.ResetModes( GLOBAL_RENDER_VSYNC );
320         }
321     }
322 
323     BinaryLoad();
324 
325     if ( video_mode.width > 0 && video_mode.height > 0 ) {
326         PostLoad();
327     }
328 
329     return true;
330 }
331 
PostLoad()332 void Settings::PostLoad()
333 {
334     if ( ExtModes( GAME_HIDE_INTERFACE ) ) {
335         opt_global.SetModes( GLOBAL_SHOWCPANEL );
336         opt_global.ResetModes( GLOBAL_SHOWRADAR );
337         opt_global.ResetModes( GLOBAL_SHOWICONS );
338         opt_global.ResetModes( GLOBAL_SHOWBUTTONS );
339         opt_global.ResetModes( GLOBAL_SHOWSTATUS );
340     }
341 }
342 
Save(const std::string & filename) const343 bool Settings::Save( const std::string & filename ) const
344 {
345     if ( filename.empty() )
346         return false;
347 
348     std::fstream file;
349 #if defined( FHEROES2_VITA )
350     const std::string vitaFilename = "ux0:data/fheroes2/" + filename;
351     file.open( vitaFilename.data(), std::fstream::out | std::fstream::trunc );
352 #else
353     const std::string cfgFilename = System::ConcatePath( System::GetConfigDirectory( "fheroes2" ), filename );
354     file.open( cfgFilename.data(), std::fstream::out | std::fstream::trunc );
355 #endif
356     if ( !file )
357         return false;
358 
359     const std::string & data = String();
360     file.write( data.data(), data.size() );
361 
362     return true;
363 }
364 
String() const365 std::string Settings::String() const
366 {
367     std::ostringstream os;
368 
369     std::string musicType;
370     if ( MusicType() == MUSIC_EXTERNAL ) {
371         musicType = "external";
372     }
373     else if ( MusicType() == MUSIC_MIDI_EXPANSION ) {
374         musicType = "expansion";
375     }
376     else {
377         musicType = "original";
378     }
379 
380     os << "# fheroes2 configuration file (saved by version " << GetVersion() << ")" << std::endl;
381 
382     os << std::endl << "# video mode (game resolution)" << std::endl;
383     os << "videomode = " << fheroes2::Display::instance().width() << "x" << fheroes2::Display::instance().height() << std::endl;
384 
385     os << std::endl << "# music: original, expansion, external" << std::endl;
386     os << "music = " << musicType << std::endl;
387 
388     os << std::endl << "# sound volume: 0 - 10" << std::endl;
389     os << "sound volume = " << sound_volume << std::endl;
390 
391     os << std::endl << "# music volume: 0 - 10" << std::endl;
392     os << "music volume = " << music_volume << std::endl;
393 
394     os << std::endl << "# run in fullscreen mode: on/off (use F4 key to switch between modes)" << std::endl;
395     os << "fullscreen = " << ( opt_global.Modes( GLOBAL_FULLSCREEN ) ? "on" : "off" ) << std::endl;
396 
397     os << std::endl << "# print debug messages (only for development, see src/engine/logging.h for possible values)" << std::endl;
398     os << "debug = " << debug << std::endl;
399 
400     os << std::endl << "# heroes movement speed: 1 - 10" << std::endl;
401     os << "heroes speed = " << heroes_speed << std::endl;
402 
403     os << std::endl << "# AI movement speed: 0 - 10" << std::endl;
404     os << "ai speed = " << ai_speed << std::endl;
405 
406     os << std::endl << "# battle speed: 1 - 10" << std::endl;
407     os << "battle speed = " << battle_speed << std::endl;
408 
409     os << std::endl << "# scroll speed: 1 - 4" << std::endl;
410     os << "scroll speed = " << scroll_speed << std::endl;
411 
412     os << std::endl << "# show battle grid: on/off" << std::endl;
413     os << "battle grid = " << ( opt_global.Modes( GLOBAL_BATTLE_SHOW_GRID ) ? "on" : "off" ) << std::endl;
414 
415     os << std::endl << "# show battle shadow movement: on/off" << std::endl;
416     os << "battle shadow movement = " << ( opt_global.Modes( GLOBAL_BATTLE_SHOW_MOVE_SHADOW ) ? "on" : "off" ) << std::endl;
417 
418     os << std::endl << "# show battle shadow cursor: on/off" << std::endl;
419     os << "battle shadow cursor = " << ( opt_global.Modes( GLOBAL_BATTLE_SHOW_MOUSE_SHADOW ) ? "on" : "off" ) << std::endl;
420 
421     os << std::endl << "# auto resolve battles: on/off" << std::endl;
422     os << "auto resolve battles = " << ( opt_global.Modes( GLOBAL_BATTLE_AUTO_RESOLVE ) ? "on" : "off" ) << std::endl;
423 
424     os << std::endl << "# auto combat spell casting: on/off" << std::endl;
425     os << "auto spell casting = " << ( opt_global.Modes( GLOBAL_BATTLE_AUTO_SPELLCAST ) ? "on" : "off" ) << std::endl;
426 
427     os << std::endl << "# game language (an empty value means English)" << std::endl;
428     os << "lang = " << _gameLanguage << std::endl;
429 
430     os << std::endl << "# controller pointer speed: 0 - 100" << std::endl;
431     os << "controller pointer speed = " << _controllerPointerSpeed << std::endl;
432 
433     os << std::endl << "# first time game run (show additional hints): on/off" << std::endl;
434     os << "first time game run = " << ( opt_global.Modes( GLOBAL_FIRST_RUN ) ? "on" : "off" ) << std::endl;
435 
436     os << std::endl << "# show game intro (splash screen and video): on/off" << std::endl;
437     os << "show game intro = " << ( opt_global.Modes( GLOBAL_SHOW_INTRO ) ? "on" : "off" ) << std::endl;
438 
439     os << std::endl << "# enable V-Sync (Vertical Synchronization) for rendering" << std::endl;
440     os << "v-sync = " << ( opt_global.Modes( GLOBAL_RENDER_VSYNC ) ? "on" : "off" ) << std::endl;
441 
442     return os.str();
443 }
444 
445 /* read maps info */
SetCurrentFileInfo(const Maps::FileInfo & fi)446 void Settings::SetCurrentFileInfo( const Maps::FileInfo & fi )
447 {
448     current_maps_file = fi;
449 
450     players.Init( current_maps_file );
451 
452     preferably_count_players = 0;
453 }
454 
CurrentFileInfo() const455 const Maps::FileInfo & Settings::CurrentFileInfo() const
456 {
457     return current_maps_file;
458 }
459 
isCurrentMapPriceOfLoyalty() const460 bool Settings::isCurrentMapPriceOfLoyalty() const
461 {
462     return current_maps_file._version == GameVersion::PRICE_OF_LOYALTY;
463 }
464 
465 /* return debug */
Debug() const466 int Settings::Debug() const
467 {
468     return debug;
469 }
470 
471 /* return game difficulty */
GameDifficulty() const472 int Settings::GameDifficulty() const
473 {
474     return game_difficulty;
475 }
476 
CurrentColor() const477 int Settings::CurrentColor() const
478 {
479     return players.current_color;
480 }
481 
getGameLanguage() const482 const std::string & Settings::getGameLanguage() const
483 {
484     return _gameLanguage;
485 }
486 
setGameLanguage(const std::string & language)487 bool Settings::setGameLanguage( const std::string & language )
488 {
489     fheroes2::updateAlphabet( language );
490 
491     Translation::setStripContext( '|' );
492 
493     _gameLanguage = language;
494 
495     if ( _gameLanguage.empty() ) {
496         Translation::reset();
497         return true;
498     }
499 
500     const std::string fileName = std::string( _gameLanguage ).append( ".mo" );
501     const ListFiles translations = Settings::FindFiles( System::ConcatePath( "files", "lang" ), fileName, false );
502 
503     if ( !translations.empty() ) {
504         return Translation::bindDomain( language.c_str(), translations.back().c_str() ) && Translation::setDomain( language.c_str() );
505     }
506 
507     ERROR_LOG( "Translation file " << fileName << " is not found." )
508     return false;
509 }
510 
loadedFileLanguage() const511 const std::string & Settings::loadedFileLanguage() const
512 {
513     return _loadedFileLanguage;
514 }
515 
SetMapsFile(const std::string & file)516 void Settings::SetMapsFile( const std::string & file )
517 {
518     current_maps_file.file = file;
519 }
520 
SetProgramPath(const char * argv0)521 void Settings::SetProgramPath( const char * argv0 )
522 {
523     if ( argv0 )
524         path_program = argv0;
525 }
526 
GetRootDirs()527 ListDirs Settings::GetRootDirs()
528 {
529     ListDirs dirs;
530 
531     // from build
532 #ifdef CONFIGURE_FHEROES2_DATA
533     dirs.push_back( EXPANDDEF( CONFIGURE_FHEROES2_DATA ) );
534 #endif
535 
536     // from env
537     if ( getenv( "FHEROES2_DATA" ) )
538         dirs.push_back( getenv( "FHEROES2_DATA" ) );
539 
540     // from app path
541     dirs.push_back( System::GetDirname( Settings::Get().path_program ) );
542 
543     // os-specific directories
544     dirs.splice( dirs.end(), System::GetOSSpecificDirectories() );
545 
546     // user config directory
547     const std::string & config = System::GetConfigDirectory( "fheroes2" );
548     if ( !config.empty() )
549         dirs.push_back( config );
550 
551     // user data directory (may be the same as user config directory, so check this to avoid unnecessary work)
552     const std::string & data = System::GetDataDirectory( "fheroes2" );
553     if ( !data.empty() && ( std::find( dirs.cbegin(), dirs.cend(), data ) == dirs.cend() ) )
554         dirs.push_back( data );
555 
556     return dirs;
557 }
558 
FindFiles(const std::string & prefixDir,const std::string & fileNameFilter,const bool exactMatch)559 ListFiles Settings::FindFiles( const std::string & prefixDir, const std::string & fileNameFilter, const bool exactMatch )
560 {
561     ListFiles res;
562 
563     for ( const std::string & dir : GetRootDirs() ) {
564         const std::string path = !prefixDir.empty() ? System::ConcatePath( dir, prefixDir ) : dir;
565 
566         if ( System::IsDirectory( path ) ) {
567             if ( exactMatch ) {
568                 res.FindFileInDir( path, fileNameFilter, false );
569             }
570             else {
571                 res.ReadDir( path, fileNameFilter, false );
572             }
573         }
574     }
575 
576     return res;
577 }
578 
GetLastFile(const std::string & prefix,const std::string & name)579 std::string Settings::GetLastFile( const std::string & prefix, const std::string & name )
580 {
581     const ListFiles & files = FindFiles( prefix, name, true );
582     return files.empty() ? name : files.back();
583 }
584 
MusicMIDI() const585 bool Settings::MusicMIDI() const
586 {
587     return opt_global.Modes( GLOBAL_MUSIC_MIDI );
588 }
589 
590 /* return move speed */
HeroesMoveSpeed() const591 int Settings::HeroesMoveSpeed() const
592 {
593     return heroes_speed;
594 }
AIMoveSpeed() const595 int Settings::AIMoveSpeed() const
596 {
597     return ai_speed;
598 }
BattleSpeed() const599 int Settings::BattleSpeed() const
600 {
601     return battle_speed;
602 }
603 
604 /* return scroll speed */
ScrollSpeed() const605 int Settings::ScrollSpeed() const
606 {
607     return scroll_speed;
608 }
609 
610 /* set ai speed: 0 (don't show) - 10 */
SetAIMoveSpeed(int speed)611 void Settings::SetAIMoveSpeed( int speed )
612 {
613     ai_speed = clamp( speed, 0, 10 );
614 }
615 
616 /* set hero speed: 1 - 10 */
SetHeroesMoveSpeed(int speed)617 void Settings::SetHeroesMoveSpeed( int speed )
618 {
619     heroes_speed = clamp( speed, 1, 10 );
620 }
621 
622 /* set battle speed: 1 - 10 */
SetBattleSpeed(int speed)623 void Settings::SetBattleSpeed( int speed )
624 {
625     battle_speed = clamp( speed, 1, 10 );
626 }
627 
setBattleAutoResolve(bool enable)628 void Settings::setBattleAutoResolve( bool enable )
629 {
630     if ( enable ) {
631         opt_global.SetModes( GLOBAL_BATTLE_AUTO_RESOLVE );
632     }
633     else {
634         opt_global.ResetModes( GLOBAL_BATTLE_AUTO_RESOLVE );
635     }
636 }
637 
setBattleAutoSpellcast(bool enable)638 void Settings::setBattleAutoSpellcast( bool enable )
639 {
640     if ( enable ) {
641         opt_global.SetModes( GLOBAL_BATTLE_AUTO_SPELLCAST );
642     }
643     else {
644         opt_global.ResetModes( GLOBAL_BATTLE_AUTO_SPELLCAST );
645     }
646 }
647 
setFullScreen(const bool enable)648 void Settings::setFullScreen( const bool enable )
649 {
650     if ( enable ) {
651         opt_global.SetModes( GLOBAL_FULLSCREEN );
652     }
653     else {
654         opt_global.ResetModes( GLOBAL_FULLSCREEN );
655     }
656 }
657 
658 /* set scroll speed: 1 - 4 */
SetScrollSpeed(int speed)659 void Settings::SetScrollSpeed( int speed )
660 {
661     scroll_speed = clamp( speed, static_cast<int>( SCROLL_SLOW ), static_cast<int>( SCROLL_FAST2 ) );
662 }
663 
isPriceOfLoyaltySupported() const664 bool Settings::isPriceOfLoyaltySupported() const
665 {
666     return opt_global.Modes( GLOBAL_PRICELOYALTY );
667 }
668 
LoadedGameVersion() const669 bool Settings::LoadedGameVersion() const
670 {
671     // 0x80 value should be same as in Game::TYPE_LOADFILE enumeration value
672     // This constant not used here, to not drag dependency on the game.h and game.cpp in compilation target.
673     return ( game_type & 0x80 ) != 0;
674 }
675 
ShowControlPanel() const676 bool Settings::ShowControlPanel() const
677 {
678     return opt_global.Modes( GLOBAL_SHOWCPANEL );
679 }
680 
ShowRadar() const681 bool Settings::ShowRadar() const
682 {
683     return opt_global.Modes( GLOBAL_SHOWRADAR );
684 }
685 
ShowIcons() const686 bool Settings::ShowIcons() const
687 {
688     return opt_global.Modes( GLOBAL_SHOWICONS );
689 }
690 
ShowButtons() const691 bool Settings::ShowButtons() const
692 {
693     return opt_global.Modes( GLOBAL_SHOWBUTTONS );
694 }
695 
ShowStatus() const696 bool Settings::ShowStatus() const
697 {
698     return opt_global.Modes( GLOBAL_SHOWSTATUS );
699 }
700 
BattleShowGrid() const701 bool Settings::BattleShowGrid() const
702 {
703     return opt_global.Modes( GLOBAL_BATTLE_SHOW_GRID );
704 }
705 
BattleShowMouseShadow() const706 bool Settings::BattleShowMouseShadow() const
707 {
708     return opt_global.Modes( GLOBAL_BATTLE_SHOW_MOUSE_SHADOW );
709 }
710 
BattleShowMoveShadow() const711 bool Settings::BattleShowMoveShadow() const
712 {
713     return opt_global.Modes( GLOBAL_BATTLE_SHOW_MOVE_SHADOW );
714 }
715 
BattleAutoResolve() const716 bool Settings::BattleAutoResolve() const
717 {
718     return opt_global.Modes( GLOBAL_BATTLE_AUTO_RESOLVE );
719 }
720 
BattleAutoSpellcast() const721 bool Settings::BattleAutoSpellcast() const
722 {
723     return opt_global.Modes( GLOBAL_BATTLE_AUTO_SPELLCAST );
724 }
725 
VideoMode() const726 const fheroes2::Size & Settings::VideoMode() const
727 {
728     return video_mode;
729 }
730 
731 /* set level debug */
SetDebug(int d)732 void Settings::SetDebug( int d )
733 {
734     debug = d;
735     Logging::SetDebugLevel( debug );
736 }
737 
SetGameDifficulty(int d)738 void Settings::SetGameDifficulty( int d )
739 {
740     game_difficulty = d;
741 }
742 
SetCurrentColor(int color)743 void Settings::SetCurrentColor( int color )
744 {
745     players.current_color = color;
746 }
747 
SoundVolume() const748 int Settings::SoundVolume() const
749 {
750     return sound_volume;
751 }
MusicVolume() const752 int Settings::MusicVolume() const
753 {
754     return music_volume;
755 }
MusicType() const756 MusicSource Settings::MusicType() const
757 {
758     return _musicType;
759 }
760 
761 /* sound volume: 0 - 10 */
SetSoundVolume(int v)762 void Settings::SetSoundVolume( int v )
763 {
764     sound_volume = clamp( v, 0, 10 );
765 }
766 
767 /* music volume: 0 - 10 */
SetMusicVolume(int v)768 void Settings::SetMusicVolume( int v )
769 {
770     music_volume = clamp( v, 0, 10 );
771 }
772 
773 /* Set music type: check MusicSource enum */
SetMusicType(int v)774 void Settings::SetMusicType( int v )
775 {
776     _musicType = MUSIC_EXTERNAL <= v ? MUSIC_EXTERNAL : static_cast<MusicSource>( v );
777 }
778 
779 /* check game type */
IsGameType(int f) const780 bool Settings::IsGameType( int f ) const
781 {
782     return ( game_type & f ) != 0;
783 }
784 
GameType() const785 int Settings::GameType() const
786 {
787     return game_type;
788 }
789 
790 /* set game type */
SetGameType(int type)791 void Settings::SetGameType( int type )
792 {
793     game_type = type;
794 }
795 
isCampaignGameType() const796 bool Settings::isCampaignGameType() const
797 {
798     return ( game_type & Game::TYPE_CAMPAIGN ) != 0;
799 }
800 
GetPlayers() const801 const Players & Settings::GetPlayers() const
802 {
803     return players;
804 }
805 
GetPlayers()806 Players & Settings::GetPlayers()
807 {
808     return players;
809 }
810 
SetPreferablyCountPlayers(int c)811 void Settings::SetPreferablyCountPlayers( int c )
812 {
813     preferably_count_players = std::min( c, 6 );
814 }
815 
PreferablyCountPlayers() const816 int Settings::PreferablyCountPlayers() const
817 {
818     return preferably_count_players;
819 }
820 
MapsFile() const821 const std::string & Settings::MapsFile() const
822 {
823     return current_maps_file.file;
824 }
825 
MapsName() const826 const std::string & Settings::MapsName() const
827 {
828     return current_maps_file.name;
829 }
830 
MapsDescription() const831 const std::string & Settings::MapsDescription() const
832 {
833     return current_maps_file.description;
834 }
835 
MapsDifficulty() const836 int Settings::MapsDifficulty() const
837 {
838     return current_maps_file.difficulty;
839 }
840 
MapsSize() const841 fheroes2::Size Settings::MapsSize() const
842 {
843     return fheroes2::Size( current_maps_file.size_w, current_maps_file.size_h );
844 }
845 
AllowChangeRace(int f) const846 bool Settings::AllowChangeRace( int f ) const
847 {
848     return ( current_maps_file.rnd_races & f ) != 0;
849 }
850 
GameStartWithHeroes() const851 bool Settings::GameStartWithHeroes() const
852 {
853     return current_maps_file.startWithHeroInEachCastle;
854 }
855 
ConditionWins() const856 uint32_t Settings::ConditionWins() const
857 {
858     return current_maps_file.ConditionWins();
859 }
860 
ConditionLoss() const861 uint32_t Settings::ConditionLoss() const
862 {
863     return current_maps_file.ConditionLoss();
864 }
865 
WinsCompAlsoWins() const866 bool Settings::WinsCompAlsoWins() const
867 {
868     return current_maps_file.WinsCompAlsoWins();
869 }
870 
WinsFindArtifactID() const871 int Settings::WinsFindArtifactID() const
872 {
873     return current_maps_file.WinsFindArtifactID();
874 }
875 
WinsFindUltimateArtifact() const876 bool Settings::WinsFindUltimateArtifact() const
877 {
878     return current_maps_file.WinsFindUltimateArtifact();
879 }
880 
WinsAccumulateGold() const881 u32 Settings::WinsAccumulateGold() const
882 {
883     return current_maps_file.WinsAccumulateGold();
884 }
885 
WinsMapsPositionObject() const886 fheroes2::Point Settings::WinsMapsPositionObject() const
887 {
888     return current_maps_file.WinsMapsPositionObject();
889 }
890 
LossMapsPositionObject() const891 fheroes2::Point Settings::LossMapsPositionObject() const
892 {
893     return current_maps_file.LossMapsPositionObject();
894 }
895 
LossCountDays() const896 u32 Settings::LossCountDays() const
897 {
898     return current_maps_file.LossCountDays();
899 }
900 
controllerPointerSpeed() const901 int Settings::controllerPointerSpeed() const
902 {
903     return _controllerPointerSpeed;
904 }
905 
EnablePriceOfLoyaltySupport(const bool set)906 void Settings::EnablePriceOfLoyaltySupport( const bool set )
907 {
908     if ( set ) {
909         opt_global.SetModes( GLOBAL_PRICELOYALTY );
910     }
911     else {
912         opt_global.ResetModes( GLOBAL_PRICELOYALTY );
913         if ( _musicType == MUSIC_MIDI_EXPANSION )
914             _musicType = MUSIC_MIDI_ORIGINAL;
915     }
916 }
917 
SetEvilInterface(bool f)918 void Settings::SetEvilInterface( bool f )
919 {
920     f ? ExtSetModes( GAME_EVIL_INTERFACE ) : ExtResetModes( GAME_EVIL_INTERFACE );
921 }
922 
SetHideInterface(bool f)923 void Settings::SetHideInterface( bool f )
924 {
925     f ? ExtSetModes( GAME_HIDE_INTERFACE ) : ExtResetModes( GAME_HIDE_INTERFACE );
926 }
927 
SetBattleGrid(bool f)928 void Settings::SetBattleGrid( bool f )
929 {
930     f ? opt_global.SetModes( GLOBAL_BATTLE_SHOW_GRID ) : opt_global.ResetModes( GLOBAL_BATTLE_SHOW_GRID );
931 }
932 
SetBattleMovementShaded(bool f)933 void Settings::SetBattleMovementShaded( bool f )
934 {
935     f ? opt_global.SetModes( GLOBAL_BATTLE_SHOW_MOVE_SHADOW ) : opt_global.ResetModes( GLOBAL_BATTLE_SHOW_MOVE_SHADOW );
936 }
937 
SetBattleMouseShaded(bool f)938 void Settings::SetBattleMouseShaded( bool f )
939 {
940     f ? opt_global.SetModes( GLOBAL_BATTLE_SHOW_MOUSE_SHADOW ) : opt_global.ResetModes( GLOBAL_BATTLE_SHOW_MOUSE_SHADOW );
941 }
942 
SetShowPanel(bool f)943 void Settings::SetShowPanel( bool f )
944 {
945     f ? opt_global.SetModes( GLOBAL_SHOWCPANEL ) : opt_global.ResetModes( GLOBAL_SHOWCPANEL );
946 }
947 
SetShowRadar(bool f)948 void Settings::SetShowRadar( bool f )
949 {
950     f ? opt_global.SetModes( GLOBAL_SHOWRADAR ) : opt_global.ResetModes( GLOBAL_SHOWRADAR );
951 }
952 
SetShowIcons(bool f)953 void Settings::SetShowIcons( bool f )
954 {
955     f ? opt_global.SetModes( GLOBAL_SHOWICONS ) : opt_global.ResetModes( GLOBAL_SHOWICONS );
956 }
957 
SetShowButtons(bool f)958 void Settings::SetShowButtons( bool f )
959 {
960     f ? opt_global.SetModes( GLOBAL_SHOWBUTTONS ) : opt_global.ResetModes( GLOBAL_SHOWBUTTONS );
961 }
962 
SetShowStatus(bool f)963 void Settings::SetShowStatus( bool f )
964 {
965     f ? opt_global.SetModes( GLOBAL_SHOWSTATUS ) : opt_global.ResetModes( GLOBAL_SHOWSTATUS );
966 }
967 
CanChangeInGame(u32 f) const968 bool Settings::CanChangeInGame( u32 f ) const
969 {
970     return ( f >> 28 ) == 0x01; // GAME_ and POCKETPC_
971 }
972 
ExtModes(u32 f) const973 bool Settings::ExtModes( u32 f ) const
974 {
975     const u32 mask = 0x0FFFFFFF;
976     switch ( f >> 28 ) {
977     case 0x01:
978         return opt_game.Modes( f & mask );
979     case 0x02:
980         return opt_world.Modes( f & mask );
981     case 0x03:
982         return opt_addons.Modes( f & mask );
983     case 0x04:
984         return opt_battle.Modes( f & mask );
985     default:
986         break;
987     }
988     return false;
989 }
990 
ExtName(const uint32_t settingId)991 std::string Settings::ExtName( const uint32_t settingId )
992 {
993     switch ( settingId ) {
994     case Settings::GAME_SAVE_REWRITE_CONFIRM:
995         return _( "game: always confirm for rewrite savefile" );
996     case Settings::GAME_REMEMBER_LAST_FOCUS:
997         return _( "game: remember last focus" );
998     case Settings::GAME_BATTLE_SHOW_DAMAGE:
999         return _( "battle: show damage info" );
1000     case Settings::WORLD_SHOW_TERRAIN_PENALTY:
1001         return _( "world: show terrain penalty" );
1002     case Settings::WORLD_SCOUTING_EXTENDED:
1003         return _( "world: scouting skill show extended content info" );
1004     case Settings::WORLD_ALLOW_SET_GUARDIAN:
1005         return _( "world: allow set guardian to objects" );
1006     case Settings::WORLD_EYE_EAGLE_AS_SCHOLAR:
1007         return _( "world: Eagle Eye also works like Scholar in H3." );
1008     case Settings::WORLD_ARTIFACT_CRYSTAL_BALL:
1009         return _( "world: Crystal Ball also added Identify Hero and Visions spells" );
1010     case Settings::WORLD_SCALE_NEUTRAL_ARMIES:
1011         return _( "world: Neutral armies scale with game difficulty" );
1012     case Settings::WORLD_USE_UNIQUE_ARTIFACTS_RS:
1013         return _( "world: use unique artifacts for resource affecting" );
1014     case Settings::WORLD_USE_UNIQUE_ARTIFACTS_PS:
1015         return _( "world: use unique artifacts for primary skills" );
1016     case Settings::WORLD_USE_UNIQUE_ARTIFACTS_SS:
1017         return _( "world: use unique artifacts for secondary skills" );
1018     case Settings::WORLD_EXT_OBJECTS_CAPTURED:
1019         return _( "world: Wind/Water Mills and Magic Garden can be captured" );
1020     case Settings::WORLD_DISABLE_BARROW_MOUNDS:
1021         return _( "world: disable Barrow Mounds" );
1022     case Settings::CASTLE_ALLOW_GUARDIANS:
1023         return _( "castle: allow guardians" );
1024     case Settings::CASTLE_MAGEGUILD_POINTS_TURN:
1025         return _( "castle: higher mage guilds regenerate more spell points/turn (20/40/60/80/100%)" );
1026     case Settings::HEROES_BUY_BOOK_FROM_SHRINES:
1027         return _( "heroes: allow buy a spellbook from Shrines" );
1028     case Settings::HEROES_COST_DEPENDED_FROM_LEVEL:
1029         return _( "heroes: recruit cost to be dependent on hero level" );
1030     case Settings::HEROES_REMEMBER_POINTS_RETREAT:
1031         return _( "heroes: remember move points for retreat/surrender result" );
1032     case Settings::HEROES_TRANSCRIBING_SCROLLS:
1033         return _( "heroes: allow transcribing scrolls (needs: Eye Eagle skill)" );
1034     case Settings::HEROES_ARENA_ANY_SKILLS:
1035         return _( "heroes: in Arena can choose any of primary skills" );
1036     case Settings::BATTLE_SHOW_ARMY_ORDER:
1037         return _( "battle: show army order" );
1038     case Settings::BATTLE_SOFT_WAITING:
1039         return _( "battle: soft wait troop" );
1040     case Settings::BATTLE_REVERSE_WAIT_ORDER:
1041         return _( "battle: reverse wait order (fast, average, slow)" );
1042     case Settings::BATTLE_DETERMINISTIC_RESULT:
1043         return _( "battle: deterministic events" );
1044     case Settings::GAME_SHOW_SYSTEM_INFO:
1045         return _( "game: show system info" );
1046     case Settings::GAME_AUTOSAVE_ON:
1047         return _( "game: autosave on" );
1048     case Settings::GAME_AUTOSAVE_BEGIN_DAY:
1049         return _( "game: autosave will be made at the beginning of the day" );
1050     case Settings::GAME_USE_FADE:
1051         return _( "game: use fade" );
1052     case Settings::GAME_EVIL_INTERFACE:
1053         return _( "game: use evil interface" );
1054     case Settings::GAME_HIDE_INTERFACE:
1055         return _( "game: hide interface" );
1056     case Settings::GAME_CONTINUE_AFTER_VICTORY:
1057         return _( "game: offer to continue the game afer victory condition" );
1058     default:
1059         break;
1060     }
1061 
1062     return std::string();
1063 }
1064 
ExtSetModes(u32 f)1065 void Settings::ExtSetModes( u32 f )
1066 {
1067     const u32 mask = 0x0FFFFFFF;
1068     switch ( f >> 28 ) {
1069     case 0x01:
1070         opt_game.SetModes( f & mask );
1071         break;
1072     case 0x02:
1073         opt_world.SetModes( f & mask );
1074         break;
1075     case 0x03:
1076         opt_addons.SetModes( f & mask );
1077         break;
1078     case 0x04:
1079         opt_battle.SetModes( f & mask );
1080         break;
1081     default:
1082         break;
1083     }
1084 }
1085 
ExtResetModes(u32 f)1086 void Settings::ExtResetModes( u32 f )
1087 {
1088     const u32 mask = 0x0FFFFFFF;
1089     switch ( f >> 28 ) {
1090     case 0x01:
1091         opt_game.ResetModes( f & mask );
1092         break;
1093     case 0x02:
1094         opt_world.ResetModes( f & mask );
1095         break;
1096     case 0x03:
1097         opt_addons.ResetModes( f & mask );
1098         break;
1099     case 0x04:
1100         opt_battle.ResetModes( f & mask );
1101         break;
1102     default:
1103         break;
1104     }
1105 }
1106 
ExtCastleGuildRestorePointsTurn() const1107 bool Settings::ExtCastleGuildRestorePointsTurn() const
1108 {
1109     return ExtModes( CASTLE_MAGEGUILD_POINTS_TURN );
1110 }
1111 
ExtCastleAllowGuardians() const1112 bool Settings::ExtCastleAllowGuardians() const
1113 {
1114     return ExtModes( CASTLE_ALLOW_GUARDIANS );
1115 }
1116 
ExtWorldShowTerrainPenalty() const1117 bool Settings::ExtWorldShowTerrainPenalty() const
1118 {
1119     return ExtModes( WORLD_SHOW_TERRAIN_PENALTY );
1120 }
1121 
ExtWorldScouteExtended() const1122 bool Settings::ExtWorldScouteExtended() const
1123 {
1124     return ExtModes( WORLD_SCOUTING_EXTENDED );
1125 }
1126 
ExtGameRememberLastFocus() const1127 bool Settings::ExtGameRememberLastFocus() const
1128 {
1129     return ExtModes( GAME_REMEMBER_LAST_FOCUS );
1130 }
1131 
ExtWorldAllowSetGuardian() const1132 bool Settings::ExtWorldAllowSetGuardian() const
1133 {
1134     return ExtModes( WORLD_ALLOW_SET_GUARDIAN );
1135 }
1136 
ExtWorldArtifactCrystalBall() const1137 bool Settings::ExtWorldArtifactCrystalBall() const
1138 {
1139     return ExtModes( WORLD_ARTIFACT_CRYSTAL_BALL );
1140 }
1141 
ExtWorldEyeEagleAsScholar() const1142 bool Settings::ExtWorldEyeEagleAsScholar() const
1143 {
1144     return ExtModes( WORLD_EYE_EAGLE_AS_SCHOLAR );
1145 }
1146 
ExtHeroBuySpellBookFromShrine() const1147 bool Settings::ExtHeroBuySpellBookFromShrine() const
1148 {
1149     return ExtModes( HEROES_BUY_BOOK_FROM_SHRINES );
1150 }
1151 
ExtHeroRecruitCostDependedFromLevel() const1152 bool Settings::ExtHeroRecruitCostDependedFromLevel() const
1153 {
1154     return ExtModes( HEROES_COST_DEPENDED_FROM_LEVEL );
1155 }
1156 
ExtHeroRememberPointsForRetreating() const1157 bool Settings::ExtHeroRememberPointsForRetreating() const
1158 {
1159     return ExtModes( HEROES_REMEMBER_POINTS_RETREAT );
1160 }
1161 
ExtBattleShowDamage() const1162 bool Settings::ExtBattleShowDamage() const
1163 {
1164     return ExtModes( GAME_BATTLE_SHOW_DAMAGE );
1165 }
1166 
ExtHeroAllowTranscribingScroll() const1167 bool Settings::ExtHeroAllowTranscribingScroll() const
1168 {
1169     return ExtModes( HEROES_TRANSCRIBING_SCROLLS );
1170 }
1171 
ExtBattleShowBattleOrder() const1172 bool Settings::ExtBattleShowBattleOrder() const
1173 {
1174     return ExtModes( BATTLE_SHOW_ARMY_ORDER );
1175 }
1176 
ExtBattleSoftWait() const1177 bool Settings::ExtBattleSoftWait() const
1178 {
1179     return ExtModes( BATTLE_SOFT_WAITING );
1180 }
1181 
ExtBattleDeterministicResult() const1182 bool Settings::ExtBattleDeterministicResult() const
1183 {
1184     return ExtModes( BATTLE_DETERMINISTIC_RESULT );
1185 }
1186 
ExtGameRewriteConfirm() const1187 bool Settings::ExtGameRewriteConfirm() const
1188 {
1189     return ExtModes( GAME_SAVE_REWRITE_CONFIRM );
1190 }
1191 
ExtGameShowSystemInfo() const1192 bool Settings::ExtGameShowSystemInfo() const
1193 {
1194     return ExtModes( GAME_SHOW_SYSTEM_INFO );
1195 }
1196 
ExtGameAutosaveBeginOfDay() const1197 bool Settings::ExtGameAutosaveBeginOfDay() const
1198 {
1199     return ExtModes( GAME_AUTOSAVE_BEGIN_DAY );
1200 }
1201 
ExtGameAutosaveOn() const1202 bool Settings::ExtGameAutosaveOn() const
1203 {
1204     return ExtModes( GAME_AUTOSAVE_ON );
1205 }
1206 
ExtGameUseFade() const1207 bool Settings::ExtGameUseFade() const
1208 {
1209     return video_mode == fheroes2::Size( fheroes2::Display::DEFAULT_WIDTH, fheroes2::Display::DEFAULT_HEIGHT ) && ExtModes( GAME_USE_FADE );
1210 }
1211 
ExtGameEvilInterface() const1212 bool Settings::ExtGameEvilInterface() const
1213 {
1214     return ExtModes( GAME_EVIL_INTERFACE );
1215 }
1216 
ExtGameHideInterface() const1217 bool Settings::ExtGameHideInterface() const
1218 {
1219     return ExtModes( GAME_HIDE_INTERFACE );
1220 }
1221 
ExtBattleReverseWaitOrder() const1222 bool Settings::ExtBattleReverseWaitOrder() const
1223 {
1224     return ExtModes( BATTLE_REVERSE_WAIT_ORDER );
1225 }
1226 
ExtWorldNeutralArmyDifficultyScaling() const1227 bool Settings::ExtWorldNeutralArmyDifficultyScaling() const
1228 {
1229     return ExtModes( WORLD_SCALE_NEUTRAL_ARMIES );
1230 }
1231 
ExtWorldUseUniqueArtifactsRS() const1232 bool Settings::ExtWorldUseUniqueArtifactsRS() const
1233 {
1234     return ExtModes( WORLD_USE_UNIQUE_ARTIFACTS_RS );
1235 }
1236 
ExtWorldUseUniqueArtifactsPS() const1237 bool Settings::ExtWorldUseUniqueArtifactsPS() const
1238 {
1239     return ExtModes( WORLD_USE_UNIQUE_ARTIFACTS_PS );
1240 }
1241 
ExtWorldUseUniqueArtifactsSS() const1242 bool Settings::ExtWorldUseUniqueArtifactsSS() const
1243 {
1244     return ExtModes( WORLD_USE_UNIQUE_ARTIFACTS_SS );
1245 }
1246 
ExtHeroArenaCanChoiseAnySkills() const1247 bool Settings::ExtHeroArenaCanChoiseAnySkills() const
1248 {
1249     return ExtModes( HEROES_ARENA_ANY_SKILLS );
1250 }
1251 
ExtWorldExtObjectsCaptured() const1252 bool Settings::ExtWorldExtObjectsCaptured() const
1253 {
1254     return ExtModes( WORLD_EXT_OBJECTS_CAPTURED );
1255 }
1256 
ExtWorldDisableBarrowMounds() const1257 bool Settings::ExtWorldDisableBarrowMounds() const
1258 {
1259     return ExtModes( WORLD_DISABLE_BARROW_MOUNDS );
1260 }
1261 
ExtGameContinueAfterVictory() const1262 bool Settings::ExtGameContinueAfterVictory() const
1263 {
1264     return ExtModes( GAME_CONTINUE_AFTER_VICTORY );
1265 }
1266 
PosRadar() const1267 const fheroes2::Point & Settings::PosRadar() const
1268 {
1269     return pos_radr;
1270 }
1271 
PosButtons() const1272 const fheroes2::Point & Settings::PosButtons() const
1273 {
1274     return pos_bttn;
1275 }
1276 
PosIcons() const1277 const fheroes2::Point & Settings::PosIcons() const
1278 {
1279     return pos_icon;
1280 }
1281 
PosStatus() const1282 const fheroes2::Point & Settings::PosStatus() const
1283 {
1284     return pos_stat;
1285 }
1286 
SetPosRadar(const fheroes2::Point & pt)1287 void Settings::SetPosRadar( const fheroes2::Point & pt )
1288 {
1289     pos_radr = pt;
1290 }
1291 
SetPosButtons(const fheroes2::Point & pt)1292 void Settings::SetPosButtons( const fheroes2::Point & pt )
1293 {
1294     pos_bttn = pt;
1295 }
1296 
SetPosIcons(const fheroes2::Point & pt)1297 void Settings::SetPosIcons( const fheroes2::Point & pt )
1298 {
1299     pos_icon = pt;
1300 }
1301 
SetPosStatus(const fheroes2::Point & pt)1302 void Settings::SetPosStatus( const fheroes2::Point & pt )
1303 {
1304     pos_stat = pt;
1305 }
1306 
BinarySave() const1307 void Settings::BinarySave() const
1308 {
1309     const std::string fname = System::ConcatePath( System::GetConfigDirectory( "fheroes2" ), "fheroes2.bin" );
1310 
1311     StreamFile fs;
1312     fs.setbigendian( true );
1313 
1314     if ( fs.open( fname, "wb" ) ) {
1315         fs << static_cast<u16>( CURRENT_FORMAT_VERSION ) << opt_game << opt_world << opt_battle << opt_addons << pos_radr << pos_bttn << pos_icon << pos_stat;
1316     }
1317 }
1318 
BinaryLoad()1319 void Settings::BinaryLoad()
1320 {
1321     std::string fname = System::ConcatePath( System::GetConfigDirectory( "fheroes2" ), "fheroes2.bin" );
1322 
1323     if ( !System::IsFile( fname ) )
1324         fname = GetLastFile( "", "fheroes2.bin" );
1325 
1326     StreamFile fs;
1327     fs.setbigendian( true );
1328 
1329     if ( fs.open( fname, "rb" ) ) {
1330         u16 version = 0;
1331 
1332         fs >> version >> opt_game >> opt_world >> opt_battle >> opt_addons >> pos_radr >> pos_bttn >> pos_icon >> pos_stat;
1333     }
1334 }
1335 
FullScreen() const1336 bool Settings::FullScreen() const
1337 {
1338     return System::isEmbededDevice() || opt_global.Modes( GLOBAL_FULLSCREEN );
1339 }
1340 
isVSyncEnabled() const1341 bool Settings::isVSyncEnabled() const
1342 {
1343     return opt_global.Modes( GLOBAL_RENDER_VSYNC );
1344 }
1345 
isFirstGameRun() const1346 bool Settings::isFirstGameRun() const
1347 {
1348     return opt_global.Modes( GLOBAL_FIRST_RUN );
1349 }
1350 
isShowIntro() const1351 bool Settings::isShowIntro() const
1352 {
1353     return opt_global.Modes( GLOBAL_SHOW_INTRO );
1354 }
1355 
resetFirstGameRun()1356 void Settings::resetFirstGameRun()
1357 {
1358     opt_global.ResetModes( GLOBAL_FIRST_RUN );
1359 }
1360 
operator <<(StreamBase & msg,const Settings & conf)1361 StreamBase & operator<<( StreamBase & msg, const Settings & conf )
1362 {
1363     msg << conf._gameLanguage << conf.current_maps_file << conf.game_difficulty << conf.game_type << conf.preferably_count_players << conf.debug << conf.opt_game
1364         << conf.opt_world << conf.opt_battle << conf.opt_addons << conf.players;
1365 
1366     return msg;
1367 }
1368 
operator >>(StreamBase & msg,Settings & conf)1369 StreamBase & operator>>( StreamBase & msg, Settings & conf )
1370 {
1371     msg >> conf._loadedFileLanguage;
1372 
1373     int debug;
1374     u32 opt_game = 0; // skip: settings
1375 
1376     // map file
1377     msg >> conf.current_maps_file >> conf.game_difficulty >> conf.game_type >> conf.preferably_count_players >> debug >> opt_game >> conf.opt_world >> conf.opt_battle
1378         >> conf.opt_addons >> conf.players;
1379 
1380 #ifndef WITH_DEBUG
1381     conf.debug = debug;
1382 #endif
1383 
1384     return msg;
1385 }
1386