1 /*
2  *
3  *  Iter Vehemens ad Necem (IVAN)
4  *  Copyright (C) Timo Kiviluoto
5  *  Released under the GNU General
6  *  Public License
7  *
8  *  See LICENSING which should be included
9  *  along with this file for more details
10  *
11  */
12 
13 #include "area.h"
14 #include "audio.h"
15 #include "bitmap.h"
16 #include "feio.h"
17 #include "felist.h"
18 #include "game.h"
19 #include "graphics.h"
20 #include "iconf.h"
21 #include "igraph.h"
22 #include "save.h"
23 #include "stack.h"
24 #include "whandler.h"
25 #include "bugworkaround.h"
26 #include "sfx.h"
27 
28 stringoption ivanconfig::DefaultName(     "DefaultName",
29                                           "Player's default name",
30                                           "Pick a character name for all your future games. When left empty, the game will generate a random name if a random name generator pattern is configured, or otherwise ask you to pick a name whenever you start a new game.",
31                                           "",
32                                           &configsystem::NormalStringDisplayer,
33                                           &DefaultNameChangeInterface);
34 stringoption ivanconfig::FantasyNamePattern("FantasyNamePattern",
35                                           "Random name generator pattern",
36                                           "Set a pattern for the random fantasy name generator. See MANUAL for further information and pattern examples.", // TODO: this above
37                                           "!ss !sV",
38                                           &configsystem::NormalStringDisplayer,
39                                           &FantasyNameChangeInterface);
40 stringoption ivanconfig::DefaultPetName(  "DefaultPetName",
41                                           "Starting pet's default name",
42                                           "Choose a name for your puppy.",
43                                           CONST_S("Kenny"),
44                                           &configsystem::NormalStringDisplayer,
45                                           &DefaultPetNameChangeInterface);
46 stringoption ivanconfig::SelectedBkgColor("SelectedBkgColor",
47                                           "Highlight color of selected entry",
48                                           "Choose the RGB code of a color used to highlight the selected entry in a menu.",
49                                           "8,8,8",
50                                           &configsystem::NormalStringDisplayer,
51                                           &SelectedBkgColorChangeInterface,
52                                           &SelectedBkgColorChanger);
53 stringoption ivanconfig::AutoPickUpMatching("AutoPickUpMatching",
54                                           "Auto pick up regex",
55                                           "Automatically pick up items according to a regular expression. To disable something, you can invalidate it with '_' without removing it from the expression (eg. '_dagger'). To disable everything at once, begin this config option with '!'. Due to current constraints on length of options, editing is easier to do externally for now.",  //TODO if multiline text editing is implemented, remove the last help statement.
56                                           "!((book|can|dagger|grenade|horn of|kiwi|key|ring|scroll|wand|whistle)|^(?:(?!(broken|empty)).)*(bottle|vial)|sol stone)",
57                                           &configsystem::NormalStringDisplayer,
58                                           &AutoPickUpMatchingChangeInterface,
59                                           &AutoPickUpMatchingChanger);
60 numberoption ivanconfig::AutoSaveInterval("AutoSaveInterval",
61                                           "Autosave interval",
62                                           "Automatically backs up your game in case of a crash.",
63                                           100,
64                                           &AutoSaveIntervalDisplayer,
65                                           &AutoSaveIntervalChangeInterface,
66                                           &AutoSaveIntervalChanger);
67 scrollbaroption ivanconfig::Contrast(     "Contrast",
68                                           "Contrast",
69                                           "",
70                                           100,
71                                           &ContrastDisplayer,
72                                           &ContrastChangeInterface,
73                                           &ContrastChanger,
74                                           &ContrastHandler);
75 cycleoption ivanconfig::HitIndicator(     "HitIndicator",
76                                           "Show successful hit",
77                                           "",
78                                           0, 5,
79                                           &HitIndicatorDisplayer);
80 cycleoption ivanconfig::HoldPosMaxDist(   "HoldPosMaxDist",
81                                           "Pets stay put when not following",
82                                           "If pets are set not to follow the player, they will move around from their spot no further than the maximum specified distance. If a pet set to be following loses track of the player, it will stay near the last position where it was still able to follow the player.",
83                                           0, 7,
84                                           &HoldPosMaxDistDisplayer);
85 cycleoption ivanconfig::ShowItemsAtPlayerSquare("ShowItemsAtPlayerSquare",
86                                           "Show items at player's square",
87                                           "",
88                                           0, 12,
89                                           &ShowItemsAtPlayerSquareDisplayer,
90                                           &configsystem::NormalCycleChangeInterface,
91                                           &ShowItemsAtPlayerSquareChanger);
92 cycleoption ivanconfig::ShowMap(          "ShowMap",
93                                           "Map preferences",
94                                           "",
95                                           0, 5,
96                                           &ShowMapDisplayer);
97 cycleoption ivanconfig::RotateTimesPerSquare("RotateTimesPerSquare",
98                                           "Thrown weapons rotate",
99                                           "Select how many times per square should the animation rotate a thrown weapon.",
100                                           0, 6,
101                                           &RotateTimesPerSquareDisplayer);
102 numberoption ivanconfig::WindowWidth(     "WindowWidth",
103                                           "* Window width in pixels",
104                                           "Choose the width of the game window, with a minimum of 640 pixels. Requires restarting the game to take effect.",
105                                           800, //default will be vanilla, but mininum still can be 640
106                                           &WindowWidthDisplayer,
107                                           &WindowWidthChangeInterface,
108                                           &WindowWidthChanger);
109 numberoption ivanconfig::WindowHeight(    "WindowHeight",
110                                           "* Window height in pixels",
111                                           "Choose the height of the game window, with a minimum of 480 pixels. Requires restarting the game to take effect.",
112                                           600, //default will be vanilla, but mininum still can be 480
113                                           &WindowHeightDisplayer,
114                                           &WindowHeightChangeInterface,
115                                           &WindowHeightChanger);
116 numberoption ivanconfig::StackListPageLength("StackListPageLength",
117                                           "Page length in entries for non-selectable menus",
118                                           "Choose how many entries will be displayed per page for non-selectable menus, such as when viewing your inventory. Note that selecting too many entries for the height of your screen may result in the menu being drawn partially off-screen.",
119                                           stack::GetDefaultPageLength(),
120                                           &StackListPageLengthDisplayer,
121                                           &StackListPageLengthChangeInterface,
122                                           &StackListPageLengthChanger);
123 cycleoption ivanconfig::GoOnStopMode(     "GoOnStopMode",
124                                           "Fastwalk stop mode",
125                                           "",
126                                           0, 4,
127                                           &GoOnStopModeDisplayer);
128 numberoption ivanconfig::FrameSkip(       "FrameSkip",
129                                           "Frame skip (assures responsiveness)",
130                                           "",
131                                           0,
132                                           &FrameSkipDisplayer,
133                                           &FrameSkipChangeInterface,
134                                           &FrameSkipChanger);
135 truthoption ivanconfig::AllowMouseOnFelist("AllowMouseOnFelist",
136                                           "Enable mouse cursor on lists",
137                                           "",
138                                           false,
139                                           &configsystem::NormalTruthDisplayer,
140                                           &configsystem::NormalTruthChangeInterface,
141                                           &AllowMouseOnFelistChanger);
142 truthoption ivanconfig::ShowMapAtDetectMaterial("ShowMapAtDetectMaterial",
143                                           "Show map while detecting material",
144                                           "",
145                                           false);
146 truthoption ivanconfig::AutoPickupThrownItems("AutoPickupThrownItems",
147                                           "Auto pick up thrown weapons",
148                                           "Automatically annotate any thrown weapon and pick it up without loosing a turn when you step on its square.",
149                                           true);
150 truthoption ivanconfig::TransparentMapLM( "TransparentMapLM",
151                                           "Show transparent map in look mode",
152                                           "Show transparent map of the whole level when in look mode.",
153                                           true);
154 truthoption ivanconfig::AllowImportOldSavegame("AllowImportOldSavegame",
155                                           "Import old savegames (v131 up, experimental)",
156                                           "",
157                                           false);
158 truthoption ivanconfig::WaitNeutralsMoveAway("WaitNeutralsMoveAway",
159                                           "Wait until neutral NPCs move from your path",
160                                           "When you try to move in a direction that is blocked by a neutral NPC, skip turns until the path is clear. Will not skip turns if the NPC doesn't move from their square, or if there are hostiles nearby.",
161                                           false);
162 truthoption ivanconfig::AllWeightIsRelevant("AllWeightIsRelevant",
163                                           "Only pile items with equal weight on lists", //clutter are useful now for crafting so their weight matters...
164                                           "",
165                                           false);
166 truthoption ivanconfig::ShowVolume(       "ShowVolume",
167                                           "Show item volume in cm3",
168                                           "",
169                                           false);
170 truthoption ivanconfig::EnhancedLights(   "EnhancedLights",
171                                           "Allow distant lights to be seen",
172                                           "",
173                                           true);
174 truthoption ivanconfig::HideWeirdHitAnimationsThatLookLikeMiss("HideWeirdHitAnimationsThatLookLikeMiss",
175                                           "Hide hit animations that look like miss",
176                                           "",
177                                           true);
178 truthoption ivanconfig::UseLightEmiterBasedOnVolume("UseLightEmiterBasedOnVolume",
179                                           "Small light sources emit less light",
180                                           "This experimental feature still has bugs that happen when splitting rocks etc. Most are fixed after restarting the game.",
181                                           false);
182 truthoption ivanconfig::ShowFullDungeonName("ShowFullDungeonName",
183                                           "Show full name of current dungeon",
184                                           "",
185                                           false);
186 truthoption ivanconfig::ShowGodInfo(      "ShowGodInfo",
187                                           "Show extra info about gods when praying",
188                                           "Remember the last response to a prayer for each god.",
189                                           false);
190 truthoption ivanconfig::CenterOnPlayerAfterLook("CenterOnPlayerAfterLook",
191                                           "Center camera on player after exiting look mode",
192                                           "Always center the displayed region of the dungeon back on player after exiting look mode.",
193                                           false);
194 truthoption ivanconfig::WarnAboutDanger(  "WarnAboutVeryDangerousMonsters",
195                                           "Warn about very dangerous monsters",
196                                           "Display a warning prompt when you encounter an unusually dangerous monster.",
197                                           true);
198 truthoption ivanconfig::AutoDropLeftOvers("AutoDropLeftOvers",
199                                           "Drop food leftovers automatically",
200                                           "",
201                                           true);
202 truthoption ivanconfig::LookZoom(         "LookZoom",
203                                           "Zoom in look mode",
204                                           "",
205                                           false);
206 truthoption ivanconfig::AltAdentureInfo(  "AltAdentureInfo",
207                                           "Enhanced message review mode after death",
208                                           "",
209                                           false);
210 truthoption ivanconfig::DescriptiveHP(    "DescriptiveHP",
211                                           "Use health level descriptions",
212                                           "Display description of your relative health rather than numeric value of your hit points.",
213                                           false);
214 truthoption ivanconfig::StartWithNoPet(   "StartWithNoPet",
215                                           "Start with no pet",
216                                           "Do not start the game with a puppy.",
217                                           false);
218 cycleoption ivanconfig::MemorizeEquipmentMode("MemorizeEquipmentMode",
219                                           "NPCs restore equipped items after polymorph",
220                                           "",
221                                           2, 3,
222                                           &MemorizeEquipmentModeDisplayer);
223 truthoption ivanconfig::XBRZScale(        "XBRZScale",
224                                           "Use xBRZScale to stretch graphics",
225                                           "",
226                                           false,
227                                           &configsystem::NormalTruthDisplayer,
228                                           &configsystem::NormalTruthChangeInterface,
229                                           &XBRZScaleChanger);
230 numberoption ivanconfig::XBRZSquaresAroundPlayer("XBRZSquaresAroundPlayer",
231                                           "Stretch squares around player with xBRZ",
232                                           "",
233                                           3,
234                                           &XBRZSquaresAroundPlayerDisplayer,
235                                           &XBRZSquaresAroundPlayerChangeInterface,
236                                           &XBRZSquaresAroundPlayerChanger);
237 cycleoption ivanconfig::DungeonGfxScale(  "DungeonGfxScale",
238                                           "* Select graphics scaling factor",
239                                           "",
240                                           1, 6, //from 1 to 6 (max xbrz) where 1 is no scale
241                                           &DungeonGfxScaleDisplayer,
242                                           &DungeonGfxScaleChangeInterface,
243                                           &DungeonGfxScaleChanger);
244 cycleoption ivanconfig::FontGfx(          "FontGfx",
245                                           "* Select font",
246                                           "Select your favorite from the available fonts.",
247                                           1, 3, //from 1 to 3 (three options available)
248                                           &FontGfxDisplayer,
249                                           &FontGfxChangeInterface,
250                                           &FontGfxChanger);
251 cycleoption ivanconfig::DistLimitMagicMushrooms("DistLimitMagicMushrooms",
252                                           "Breeders' active range",
253                                           "Select the maximum distance where breeding monsters will spawn more of their own. This option can be used to prevent lag from high number of creatures on slow computers, but may impact the intended game balance negatively.",
254                                           0, 5,
255                                           &DistLimitMagicMushroomsDisplayer);
256 cycleoption ivanconfig::SaveGameSortMode( "SaveGameSortMode",
257                                           "Sort savegame files by dungeon IDs",
258                                           "Savegame selection menu will be sorted according to the chosen criterion.",
259                                           0, 4,
260                                           &SaveGameSortModeDisplayer,
261                                           &configsystem::NormalCycleChangeInterface,
262                                           &SaveGameSortModeChanger);
263 cycleoption ivanconfig::SilhouetteScale(  "SilhouetteScale",
264                                           "Silhouette scaling factor",
265                                           "Select scaling factor for silhouette, 1x to disable (no scaling).",
266                                           1, 6, //from 1 to 6 (max xbrz) where 1 is no scale
267                                           &SilhouetteScaleDisplayer,
268                                           &SilhouetteScaleChangeInterface,
269                                           &SilhouetteScaleChanger);
270 cycleoption ivanconfig::AltSilhouette(    "AltSilhouette",
271                                           "Alternative silhouette mode",
272                                           "",
273                                           0, 7,
274                                           &AltSilhouetteDisplayer);
275 cycleoption ivanconfig::AltSilhouettePreventColorGlitch("AltSilhouettePreventColorGlitch",
276                                           "Alternative silhouette background",
277                                           "",
278                                           2, 3,
279                                           &AltSilhouettePreventColorGlitchDisplayer);
280 cycleoption ivanconfig::DirectionKeyMap(  "DirectionKeyMap",
281                                           "Movement control scheme",
282                                           "Select a pre-defined keybinding scheme for the movement of your character. Normal scheme uses NumPad, or arrow keys along with Home, End, PgUp and PgDn for diagonal directions. Alternative scheme is better suited for laptops and uses number and letter keys on the main keyboard. NetHack scheme uses vi keys. After you select a movement control scheme, you may also check the in game keybindings help to see the currently active movement keys. Any other command keys may be auto changed also to not conflict with this movement keys choice.",
283                                           DIR_NORM, 3, // {default value, number of options to cycle through}
284                                           &DirectionKeyMapDisplayer);
285 truthoption ivanconfig::SetupCustomKeys(  "SetupCustomKeys",
286                                           "Custom command and movement", //TODO all keys one day, and let it work on main menu
287                                           "Lets you assign any command to any key binding of your preference. The default keys here will be from the control scheme option above. Only changed keybindings will be saved at the new config file. This global configuration won't work at main menu, load/start some game.",
288                                           false,
289                                           &configsystem::NormalTruthDisplayer,
290                                           &configsystem::NormalTruthChangeInterface,
291                                           &SetupCustomKeysChanger);
292 truthoption ivanconfig::SmartOpenCloseApply("SmartOpenCloseApply",
293                                           "Smart open/close/apply behavior",
294                                           "Automatically try to open doors when you walk into them, and don't ask for the target of close/apply actions when only one viable target is present.",
295                                           true);
296 truthoption ivanconfig::BeNice(           "BeNice",
297                                           "Be nice to pets",
298                                           "Don't let your sadistic tendencies hurt your pets.",
299                                           true);
300 cycleoption ivanconfig::AltListItemPos(   "AltListItemPos",
301                                           "Use alternative position of stretched lists",
302                                           "",
303                                           0, 3,
304                                           &AltListItemPosDisplayer);
305 numberoption ivanconfig::AltListItemWidth("AltListItemWidth",
306                                           "List width for alternative stretched lists",
307                                           "",
308                                           game::getDefaultItemsListWidth(),
309                                           &AltListItemWidthDisplayer,
310                                           &AltListItemWidthChangeInterface,
311                                           &AltListItemWidthChanger);
312 scrollbaroption ivanconfig::Volume(       "Volume",
313                                           "Music Volume",
314                                           "Select volume for game MIDI music",
315                                           127,
316                                           &VolumeDisplayer,
317                                           &VolumeChangeInterface,
318                                           &VolumeChanger,
319                                           &VolumeHandler);
320 scrollbaroption ivanconfig::SfxVolume(    "SfxVolume",
321                                           "Soud Effects (SFX) Volume",
322                                           "Select volume for sound effects",
323                                           127,
324                                           &SfxVolumeDisplayer,
325                                           &SfxVolumeChangeInterface,
326                                           &SfxVolumeChanger,
327                                           &SfxVolumeHandler);
328 
329 cycleoption ivanconfig::MIDIOutputDevice( "MIDIOutputDevice",
330                                           "Use MIDI soundtrack",
331                                           "Select an output device for the game music, or disable soundtrack.",
332                                           0, 0, // {default value, number of options to cycle through}
333                                           &MIDIOutputDeviceDisplayer);
334 cycleoption ivanconfig::LandTypeConfig("LandTypeConfig",
335                                           "What land shapes to generate",
336                                           "Choose whether to generate continents or pangea. If Pangea is selected, the generator will make all locations reachable from the same landmass.",
337                                           0, 2,
338                                           &LandTypeConfigDisplayer);
339 cycleoption ivanconfig::WorldSizeConfig("WorldSizeConfig",
340                                           "Size of the world map",
341                                           "Select a world size.",
342                                           2, 7,
343                                           &WorldSizeConfigDisplayer);
344 cycleoption ivanconfig::WorldShapeConfig("WorldShapeConfig",
345                                           "Shape of the world",
346                                           "This affects the player's movement around the world. Pancake worlds are flat, and the player cannot cross the edges of the world map. Brandy snap worlds are like a cylinder, the world map wraps around the horizontal axis. Doughnut worlds are shaped like a torus, the player can wrap around the horizontal and vertical axes.",
347                                           0, 3,
348                                           &WorldShapeConfigDisplayer);
349 numberoption ivanconfig::WorldSeedConfig("WorldSeedConfig",
350                                           "Select a world seed",
351                                           "0 gives a random world seed, else select a new one at your own risk. If a world cannot be generated with the given seed after a finite number of attempts, you will get a message saying the world generator encountered a bad seed, what that seed was, and a new world will be generated from a random seed instead of the one specified here.",
352                                           0,
353                                           &WorldSeedConfigDisplayer,
354                                           &WorldSeedConfigChangeInterface,
355                                           &WorldSeedConfigChanger);
356 
357 #ifndef __DJGPP__
358 cycleoption ivanconfig::GraphicsScale(    "GraphicsScale",
359                                           "Select window scaling factor",
360                                           "",
361                                           1, 2,
362                                           &GraphicsScaleDisplayer,
363                                           &GraphicsScaleChangeInterface,
364                                           &GraphicsScaleChanger);
365 truthoption ivanconfig::FullScreenMode(   "FullScreenMode",
366                                           "Full screen mode",
367                                           "Display the game in full screen mode.",
368                                           false,
369                                           &configsystem::NormalTruthDisplayer,
370                                           &configsystem::NormalTruthChangeInterface,
371                                           &FullScreenModeChanger);
372 cycleoption ivanconfig::ScalingQuality(   "ScalingQuality",
373                                           "* Scaling quality",
374                                           "",
375                                           0, 2,
376                                           &ScalingQualityDisplayer);
377 truthoption ivanconfig::UseExtraMenuGraphics("UseExtraMenuGraphics",
378                                           "Use extra main menu graphics",
379                                           "Add changing graphics and sounds to the main menu.",
380                                           false,
381                                           &configsystem::NormalTruthDisplayer,
382                                           &configsystem::NormalTruthChangeInterface,
383                                           &UseExtraMenuGraphicsChanger);
384 #endif
385 col24 ivanconfig::ContrastLuminance = NORMAL_LUMINANCE;
386 truthoption ivanconfig::PlaySounds(       "PlaySounds",
387                                           "Use sound effects",
388                                           "Use sound effects for combat, explosions and more.",
389                                           true);
390 truthoption ivanconfig::ShowTurn(         "ShowTurn",
391                                           "Show game turn on message log",
392                                           "Add a game turn number to each action described in the message log.",
393                                           false);
394 truthoption ivanconfig::OutlinedGfx(      "OutlinedGfx",
395                                           "* Use outlined graphics",
396                                           "The game graphics will be outlined in black for better differentiation.",
397                                           false);
398 
GetQuestionPos()399 v2 ivanconfig::GetQuestionPos() { return game::IsRunning() ? v2(16, 6) : v2(30, 30); }
BackGroundDrawer()400 void ivanconfig::BackGroundDrawer() { game::DrawEverythingNoBlit(); }
401 
XBRZSquaresAroundPlayerDisplayer(const numberoption * O,festring & Entry)402 void ivanconfig::XBRZSquaresAroundPlayerDisplayer(const numberoption* O, festring& Entry)
403 {
404   Entry << O->Value << " squares";
405 }
406 
AltListItemWidthDisplayer(const numberoption * O,festring & Entry)407 void ivanconfig::AltListItemWidthDisplayer(const numberoption* O, festring& Entry)
408 {
409   Entry << O->Value << " pixels";
410 }
411 
FrameSkipDisplayer(const numberoption * O,festring & Entry)412 void ivanconfig::FrameSkipDisplayer(const numberoption* O, festring& Entry)
413 {
414   Entry << O->Value;
415   if(O->Value==-2)Entry  << " = wait"  ;
416   if(O->Value==-1)Entry  << " = auto"  ;
417   if(O->Value>= 0)Entry  <<   " frames";
418 }
419 
DistLimitMagicMushroomsDisplayer(const cycleoption * O,festring & Entry)420 void ivanconfig::DistLimitMagicMushroomsDisplayer(const cycleoption* O, festring& Entry)
421 {
422   if(O->Value == 0)
423     Entry << "everywhere";
424   else if(O->Value == 1)
425     Entry << "close";
426   else if(O->Value == 2)
427     Entry << "near";
428   else if(O->Value == 3)
429     Entry << "medium";
430   else if(O->Value == 4)
431     Entry << "far";
432   else
433     Entry << O->Value;
434 }
435 
StackListPageLengthDisplayer(const numberoption * O,festring & Entry)436 void ivanconfig::StackListPageLengthDisplayer(const numberoption* O, festring& Entry)
437 {
438   Entry << O->Value << " entries";
439 }
440 
WindowHeightDisplayer(const numberoption * O,festring & Entry)441 void ivanconfig::WindowHeightDisplayer(const numberoption* O, festring& Entry)
442 {
443   Entry << O->Value << " pixels";
444 }
445 
AltSilhouettePreventColorGlitchDisplayer(const cycleoption * O,festring & Entry)446 void ivanconfig::AltSilhouettePreventColorGlitchDisplayer(const cycleoption* O, festring& Entry)
447 {
448   switch(O->Value){
449   case 0: Entry << "transparent";break;
450   case 1: Entry << "dark";break;
451   case 2: Entry << "alignment";break;
452   }
453 }
454 
RotateTimesPerSquareDisplayer(const cycleoption * O,festring & Entry)455 void ivanconfig::RotateTimesPerSquareDisplayer(const cycleoption* O, festring& Entry)
456 {
457   switch(O->Value){
458   case 0: Entry << "disabled";break;
459   case 1: Entry << "x1";break;
460   case 2: Entry << "x2";break;
461   case 3: Entry << "x3";break;
462   case 4: Entry << "x4";break;
463   case 5: Entry << "dynamic";break;
464   }
465 }
466 
HoldPosMaxDistDisplayer(const cycleoption * O,festring & Entry)467 void ivanconfig::HoldPosMaxDistDisplayer(const cycleoption* O, festring& Entry)
468 {
469   if(O->Value>0)
470     Entry << O->Value << " squares";
471   else
472     Entry << "disabled";
473 }
474 
HitIndicatorDisplayer(const cycleoption * O,festring & Entry)475 void ivanconfig::HitIndicatorDisplayer(const cycleoption* O, festring& Entry)
476 {
477   switch(O->Value){
478   case 0: Entry << "disabled";break;
479   case 1: Entry << "immersive";break;
480   case 2: Entry << "indicator";break;
481   case 3: Entry << "indicator + color";break;
482   case 4: Entry << "dynamic";break;
483   }
484 }
485 
GoOnStopModeDisplayer(const cycleoption * O,festring & Entry)486 void ivanconfig::GoOnStopModeDisplayer(const cycleoption* O, festring& Entry)
487 {
488   switch(O->Value){
489     case 0:Entry << "everything";break;
490     case 1:Entry << "ignore useless";break;
491     case 2:Entry << "ignore cheap";break;
492     case 3:Entry << "ignore encumbering";break;
493   }
494 }
495 
ShowMapDisplayer(const cycleoption * O,festring & Entry)496 void ivanconfig::ShowMapDisplayer(const cycleoption* O, festring& Entry)
497 {
498   switch(O->Value){
499     case 0:Entry << "vanilla";break; //mmm... just not using xBRZ
500     case 1:Entry << "xBRZ";break;
501     case 2:Entry << "immersive 1";break;
502     case 3:Entry << "immersive 2";break;
503     case 4:Entry << "immersive 3";break;
504   }
505 }
506 
ShowItemsAtPlayerSquareDisplayer(const cycleoption * O,festring & Entry)507 void ivanconfig::ShowItemsAtPlayerSquareDisplayer(const cycleoption* O, festring& Entry)
508 {
509   if(O->Value>=10){
510     Entry << "Use corners if NPC";
511     if(O->Value==11)Entry << "+Items";
512     Entry << " above";
513     return;
514   }
515 
516   int iCode = game::ItemUnderCode(O->Value);
517 
518   if(iCode==0){
519     Entry << "disabled";
520   }else
521   if(iCode==1){
522     Entry << "above head";
523   }else{
524     switch(game::ItemUnderCorner(iCode)){
525       case 0:Entry << "upper left";break;
526       case 1:Entry << "upper right";break;
527       case 2:Entry << "lower left";break;
528       case 3:Entry << "lower right";break;
529     }
530 
531 //    Entry << ",";
532 //    Entry << "x" << game::ItemUnderZoom(O->Value);
533 
534     Entry << ", ";
535     Entry << (game::ItemUnderHV(iCode) ? "horizontal" : "vertical");
536   }
537 }
538 
WindowWidthDisplayer(const numberoption * O,festring & Entry)539 void ivanconfig::WindowWidthDisplayer(const numberoption* O, festring& Entry)
540 {
541   Entry << O->Value << " pixels";
542 }
543 
AutoSaveIntervalDisplayer(const numberoption * O,festring & Entry)544 void ivanconfig::AutoSaveIntervalDisplayer(const numberoption* O, festring& Entry)
545 {
546   if(O->Value)
547   {
548     Entry << O->Value << " turn";
549 
550     if(O->Value != 1)
551       Entry << 's';
552   }
553   else
554     Entry << "disabled";
555 }
556 
ContrastDisplayer(const numberoption * O,festring & Entry)557 void ivanconfig::ContrastDisplayer(const numberoption* O, festring& Entry)
558 {
559   Entry << O->Value << "/100";
560 }
561 
VolumeDisplayer(const numberoption * O,festring & Entry)562 void ivanconfig::VolumeDisplayer(const numberoption* O, festring& Entry)
563 {
564   Entry << O->Value << "/127";
565 }
SfxVolumeDisplayer(const numberoption * O,festring & Entry)566 void ivanconfig::SfxVolumeDisplayer(const numberoption* O, festring& Entry)
567 {
568   Entry << O->Value << "/127";
569 }
570 
AltSilhouetteDisplayer(const cycleoption * O,festring & Entry)571 void ivanconfig::AltSilhouetteDisplayer(const cycleoption* O, festring& Entry)
572 {
573   switch(O->Value){
574     case 0: Entry << "no"        ; break;
575     case 1: Entry << "short"     ; break;
576     case 2: Entry << "tall"      ; break;
577     case 3: Entry << "breathing" ; break;
578     case 4: Entry << "breathSlower"; break;
579     case 5: Entry << "breathSlower+"; break;
580     case 6: Entry << "breathSlower++"; break;
581   }
582 }
583 
DirectionKeyMapDisplayer(const cycleoption * O,festring & Entry)584 void ivanconfig::DirectionKeyMapDisplayer(const cycleoption* O, festring& Entry)
585 {
586   switch(O->Value)
587   {
588     case DIR_NORM:
589       Entry << CONST_S("Normal");
590       break;
591     case DIR_ALT:
592       Entry << CONST_S("Alternative");
593       break;
594     case DIR_HACK:
595       Entry << CONST_S("NetHack");
596       break;
597   }
598 }
599 
MIDIOutputDeviceDisplayer(const cycleoption * O,festring & Entry)600 void ivanconfig::MIDIOutputDeviceDisplayer(const cycleoption* O, festring& Entry)
601 {
602   std::vector<std::string> devicenames;
603   int NumDevices = audio::GetMIDIOutputDevices(devicenames);
604   MIDIOutputDevice.CycleCount = NumDevices+1;
605 
606   if(O->Value && O->Value <= devicenames.size())
607   {
608      const char *cstr = devicenames[O->Value - 1].c_str();
609      Entry << cstr;
610 
611      audio::ChangeMIDIOutputDevice(O->Value);
612      VolumeChanger(&Volume, GetVolume());
613   }
614   else
615   {
616      audio::ChangeMIDIOutputDevice(0);
617      Entry << CONST_S("no");
618   }
619 }
620 
clearToBackgroundAfterChangeInterface()621 void clearToBackgroundAfterChangeInterface(){
622   if(game::IsRunning())
623     igraph::BlitBackGround(
624       v2(16,6),
625       v2(game::GetMaxScreenXSize() << 4, 23)
626     );
627 }
628 
GraphicsScaleChangeInterface(cycleoption * O)629 truth ivanconfig::GraphicsScaleChangeInterface(cycleoption* O)
630 {
631   O->ChangeValue(O->Value % O->CycleCount + 1);
632   clearToBackgroundAfterChangeInterface();
633   return true;
634 }
635 
SilhouetteScaleChangeInterface(cycleoption * O)636 truth ivanconfig::SilhouetteScaleChangeInterface(cycleoption* O)
637 {
638   O->ChangeValue(O->Value % O->CycleCount + 1);
639   clearToBackgroundAfterChangeInterface();
640   return true;
641 }
642 
DungeonGfxScaleChangeInterface(cycleoption * O)643 truth ivanconfig::DungeonGfxScaleChangeInterface(cycleoption* O)
644 {
645   O->ChangeValue(O->Value % O->CycleCount + 1);
646   clearToBackgroundAfterChangeInterface();
647   return true;
648 }
649 
FontGfxChangeInterface(cycleoption * O)650 truth ivanconfig::FontGfxChangeInterface(cycleoption* O)
651 {
652   O->ChangeValue(O->Value % O->CycleCount + 1);
653   clearToBackgroundAfterChangeInterface();
654   return true;
655 }
656 
657 
FantasyNameChangeInterface(stringoption * O)658 truth ivanconfig::FantasyNameChangeInterface(stringoption* O)
659 {
660   festring String;
661   if(O)String<<O->Value;
662 
663   if(iosystem::StringQuestion(String, CONST_S("Set name generator pattern (recommended \"!ss !sV\"):"),
664                               GetQuestionPos(), WHITE, 0, 20, !game::IsRunning(), true) == NORMAL_EXIT)
665     O->ChangeValue(String);
666 
667   clearToBackgroundAfterChangeInterface();
668 
669   return false;
670 }
671 
DefaultNameChangeInterface(stringoption * O)672 truth ivanconfig::DefaultNameChangeInterface(stringoption* O)
673 {
674   festring String;
675   if(O)String<<O->Value;
676 
677   if(iosystem::StringQuestion(String, CONST_S("Set new default name (1-20 letters):"),
678                               GetQuestionPos(), WHITE, 0, 20, !game::IsRunning(), true) == NORMAL_EXIT)
679     O->ChangeValue(String);
680 
681   clearToBackgroundAfterChangeInterface();
682 
683   return false;
684 }
685 
SelectedBkgColorChangeInterface(stringoption * O)686 truth ivanconfig::SelectedBkgColorChangeInterface(stringoption* O)
687 {
688   festring String;
689   if(O)String<<O->Value;
690 
691   if(iosystem::StringQuestion(String, CONST_S("Set new RGB color (8 to 200 for each value, default \"8,8,8\"), or leave empty to disable:"),
692                               GetQuestionPos(), WHITE, 0, 20, !game::IsRunning(), true) == NORMAL_EXIT)
693     O->ChangeValue(String);
694 
695   clearToBackgroundAfterChangeInterface();
696 
697   return false;
698 }
699 
AutoPickUpMatchingChangeInterface(stringoption * O)700 truth ivanconfig::AutoPickUpMatchingChangeInterface(stringoption* O)
701 {
702   festring String;
703   if(O)String<<O->Value;
704 
705   if(iosystem::StringQuestion(String, CONST_S("What items do you want to automatically pick up?"),
706                               GetQuestionPos(), WHITE, 0, 200, !game::IsRunning(), true) == NORMAL_EXIT) //TODO should have no limit? but crashes if going beyond screen limit...
707     O->ChangeValue(String);
708 
709   clearToBackgroundAfterChangeInterface();
710 
711   return false;
712 }
713 
DefaultPetNameChangeInterface(stringoption * O)714 truth ivanconfig::DefaultPetNameChangeInterface(stringoption* O)
715 {
716   festring String;
717   if(O)String<<O->Value;
718 
719   if(iosystem::StringQuestion(String, CONST_S("Set new default name for the starting pet (1-20 letters):"),
720                               GetQuestionPos(), WHITE, 0, 20, !game::IsRunning(), true) == NORMAL_EXIT)
721     O->ChangeValue(String);
722 
723   clearToBackgroundAfterChangeInterface();
724 
725   return false;
726 }
727 
XBRZSquaresAroundPlayerChangeInterface(numberoption * O)728 truth ivanconfig::XBRZSquaresAroundPlayerChangeInterface(numberoption* O)
729 {
730   O->ChangeValue(iosystem::NumberQuestion(CONST_S("Set how many squares around player to use xBRZ at (0 for whole dungeon):"),
731                                           GetQuestionPos(), WHITE, !game::IsRunning()));
732   clearToBackgroundAfterChangeInterface();
733   return false;
734 }
735 
AltListItemWidthChangeInterface(numberoption * O)736 truth ivanconfig::AltListItemWidthChangeInterface(numberoption* O)
737 {
738   O->ChangeValue(iosystem::NumberQuestion(CONST_S("Set new item list width:"),
739                                           GetQuestionPos(), WHITE, !game::IsRunning()));
740   clearToBackgroundAfterChangeInterface();
741   return false;
742 }
743 
FrameSkipChangeInterface(numberoption * O)744 truth ivanconfig::FrameSkipChangeInterface(numberoption* O)
745 {
746   O->ChangeValue(iosystem::NumberQuestion(CONST_S("Set frame skip (-2 = wait, -1 = auto, or 0 to 100):"),
747                                           GetQuestionPos(), WHITE, !game::IsRunning()));
748   clearToBackgroundAfterChangeInterface();
749   return false;
750 }
751 
StackListPageLengthChangeInterface(numberoption * O)752 truth ivanconfig::StackListPageLengthChangeInterface(numberoption* O)
753 {
754   O->ChangeValue(iosystem::NumberQuestion(CONST_S("Set new length of list pages (in entries):"),
755                                           GetQuestionPos(), WHITE, !game::IsRunning()));
756   clearToBackgroundAfterChangeInterface();
757   return false;
758 }
759 
WindowHeightChangeInterface(numberoption * O)760 truth ivanconfig::WindowHeightChangeInterface(numberoption* O)
761 {
762   O->ChangeValue(iosystem::NumberQuestion(CONST_S("Set new window height (from 480 to your monitor screen max height):"),
763                                           GetQuestionPos(), WHITE, !game::IsRunning()));
764   clearToBackgroundAfterChangeInterface();
765   return false;
766 }
767 
WindowWidthChangeInterface(numberoption * O)768 truth ivanconfig::WindowWidthChangeInterface(numberoption* O)
769 {
770   O->ChangeValue(iosystem::NumberQuestion(CONST_S("Set new window width (from 640 to your monitor screen max width):"),
771                                           GetQuestionPos(), WHITE, !game::IsRunning()));
772   clearToBackgroundAfterChangeInterface();
773   return false;
774 }
775 
AutoSaveIntervalChangeInterface(numberoption * O)776 truth ivanconfig::AutoSaveIntervalChangeInterface(numberoption* O)
777 {
778   O->ChangeValue(iosystem::NumberQuestion(CONST_S("Set new autosave interval (1-50000 turns, 0 for never):"),
779                                           GetQuestionPos(), WHITE, !game::IsRunning()));
780 
781   clearToBackgroundAfterChangeInterface();
782 
783   return false;
784 }
785 
ContrastChangeInterface(numberoption * O)786 truth ivanconfig::ContrastChangeInterface(numberoption* O)
787 {
788   iosystem::ScrollBarQuestion(CONST_S("Set new contrast value (0-200, '<' and '>' move the slider):"),
789                               GetQuestionPos(), O->Value, 5, 0, 200, O->Value, WHITE, LIGHT_GRAY, DARK_GRAY,
790                               game::GetMoveCommandKey(KEY_LEFT_INDEX), game::GetMoveCommandKey(KEY_RIGHT_INDEX),
791                               !game::IsRunning(), static_cast<scrollbaroption*>(O)->BarHandler);
792 
793   clearToBackgroundAfterChangeInterface();
794 
795   return false;
796 }
797 
VolumeChangeInterface(numberoption * O)798 truth ivanconfig::VolumeChangeInterface(numberoption* O)
799 {
800   iosystem::ScrollBarQuestion(CONST_S("Set new volume value (0-127, '<' and '>' move the slider):"),
801                               GetQuestionPos(), O->Value, 5, 0, 127, O->Value, WHITE, LIGHT_GRAY, DARK_GRAY,
802                               game::GetMoveCommandKey(KEY_LEFT_INDEX), game::GetMoveCommandKey(KEY_RIGHT_INDEX),
803                               !game::IsRunning(), static_cast<scrollbaroption*>(O)->BarHandler);
804 
805   clearToBackgroundAfterChangeInterface();
806 
807   return false;
808 }
SfxVolumeChangeInterface(numberoption * O)809 truth ivanconfig::SfxVolumeChangeInterface(numberoption* O)
810 {
811   iosystem::ScrollBarQuestion(CONST_S("Set new SFX volume value (0-127, '<' and '>' move the slider):"),
812                               GetQuestionPos(), O->Value, 5, 0, 127, O->Value, WHITE, LIGHT_GRAY, DARK_GRAY,
813                               game::GetMoveCommandKey(KEY_LEFT_INDEX), game::GetMoveCommandKey(KEY_RIGHT_INDEX),
814                               !game::IsRunning(), static_cast<scrollbaroption*>(O)->BarHandler);
815 
816   clearToBackgroundAfterChangeInterface();
817 
818   return false;
819 }
820 
XBRZSquaresAroundPlayerChanger(numberoption * O,long What)821 void ivanconfig::XBRZSquaresAroundPlayerChanger(numberoption* O, long What)
822 {
823   if(What < 0) What = 0;
824   O->Value = What;
825 }
826 
AltListItemWidthChanger(numberoption * O,long What)827 void ivanconfig::AltListItemWidthChanger(numberoption* O, long What)
828 {
829   if(What < 400) What = 400; //TODO find the best quality minimum value
830   O->Value = What;
831 }
832 
FrameSkipChanger(numberoption * O,long What)833 void ivanconfig::FrameSkipChanger(numberoption* O, long What)
834 {
835   if(What <  -2) What =  -2;
836   if(What > 100) What = 100;
837 
838   if(O!=NULL)O->Value = What;
839 
840   globalwindowhandler::SetAddFrameSkip(What);
841 }
842 
StackListPageLengthChanger(numberoption * O,long What)843 void ivanconfig::StackListPageLengthChanger(numberoption* O, long What)
844 {
845   if(What < stack::GetDefaultPageLength()) What = stack::GetDefaultPageLength();
846   if(O!=NULL)O->Value = What;
847 
848   stack::SetStandardPageLength(What);
849 }
850 
WindowHeightChanger(numberoption * O,long What)851 void ivanconfig::WindowHeightChanger(numberoption* O, long What)
852 {
853   if(What < 480) What = 480;
854   O->Value = What;
855 }
856 
ShowItemsAtPlayerSquareChanger(cycleoption * O,long What)857 void ivanconfig::ShowItemsAtPlayerSquareChanger(cycleoption* O, long What)
858 {
859 //  if(What==1 && GetStartingDungeonGfxScale()<3){ //above head asked
860 //    What=2; //upgrade to 1st corner
861 //  }
862 
863   O->Value = What;
864 }
865 
WindowWidthChanger(numberoption * O,long What)866 void ivanconfig::WindowWidthChanger(numberoption* O, long What)
867 {
868   if(What < 640) What = 640;
869   O->Value = What;
870 }
871 
SelectedBkgColorChanger(stringoption * O,cfestring & What)872 void ivanconfig::SelectedBkgColorChanger(stringoption* O, cfestring& What)
873 {
874   if(!What.IsEmpty()){
875     int RGB[3]={1,1,1}, j=0;
876     std::string sC;
877     for(int i=0;i<What.GetSize();i++){
878       if(j==3)return; //wrong usage detected
879 
880       if(What[i]>=0x30 && What[i]<=0x39) //0-9
881         sC+=What[i];
882       else{
883         if(What[i]!=',') //wrong usage detected
884           return;
885       }
886 
887       if(What[i]==',' || i==What.GetSize()-1){
888         RGB[j]=std::stol(sC);
889         if(RGB[j]<8)return; //0,0,0 makes xBRZ not work well. 8,8,8 is min to have col16 not 0,0,0 (it is less bits than col24 per component)
890         if(RGB[j]>200)return; //if all too high will prevent reading white text
891         j++;
892         sC="";
893       }
894     }
895 
896     if(j!=3)return; //wrong usage detected
897 
898     felist::SetSelectedBkgColor(MakeRGB16(RGB[0],RGB[1],RGB[2]));
899   }else{
900     felist::SetSelectedBkgColor(TRANSPARENT_COLOR);
901   }
902 
903   if(O!=NULL){
904     O->Value.Empty();
905     O->Value<<What;
906   }
907 }
908 
AutoPickUpMatchingChanger(stringoption * O,cfestring & What)909 void ivanconfig::AutoPickUpMatchingChanger(stringoption* O, cfestring& What)
910 {
911   if(O!=NULL){
912     O->Value.Empty();
913     O->Value<<What;
914     game::UpdateAutoPickUpMatching();
915   }
916 }
917 
AutoSaveIntervalChanger(numberoption * O,long What)918 void ivanconfig::AutoSaveIntervalChanger(numberoption* O, long What)
919 {
920   if(What < 0) What = 0;
921   if(What > 50000) What = 50000;
922   O->Value = What;
923 }
924 
ContrastChanger(numberoption * O,long What)925 void ivanconfig::ContrastChanger(numberoption* O, long What)
926 {
927   if(What < 0) What = 0;
928   if(What > 200) What = 200;
929   O->Value = What;
930 
931   CalculateContrastLuminance();
932 }
933 
VolumeChanger(numberoption * O,long What)934 void ivanconfig::VolumeChanger(numberoption* O, long What)
935 {
936   if(What < 0) What = 0;
937   if(What > 127) What = 127;
938   O->Value = What;
939 
940   audio::SetVolumeLevel(What);
941 }
942 
SfxVolumeChanger(numberoption * O,long What)943 void ivanconfig::SfxVolumeChanger(numberoption* O, long What)
944 {
945   if(What < 0) What = 0;
946   if(What > 127) What = 127;
947   O->Value = What;
948 }
949 
WorldSizeConfigDisplayer(const cycleoption * O,festring & Entry)950 void ivanconfig::WorldSizeConfigDisplayer(const cycleoption* O, festring& Entry)
951 {
952   if(O->Value == 0)
953     Entry << "Huge (128x128)";
954   else if(O->Value == 1)
955     Entry << "Large (96x96)";
956   else if(O->Value == 2)
957     Entry << "Medium (64x64)";
958   else if(O->Value == 3)
959     Entry << "Small (49x49)";
960   else if(O->Value == 4)
961     Entry << "Tiny (32x32)";
962   else if(O->Value == 5)
963     Entry << "One screen (42x26)";
964   else if(O->Value == 6)
965     Entry << "Four screens (84x52)";
966   else
967     Entry << O->Value;
968 }
969 
LandTypeConfigDisplayer(const cycleoption * O,festring & Entry)970 void ivanconfig::LandTypeConfigDisplayer(const cycleoption* O, festring& Entry)
971 {
972   if(O->Value == 0)
973     Entry << "Pangea";
974   else if(O->Value == 1)
975     Entry << "Continents";
976   else
977     Entry << O->Value;
978 }
979 
WorldShapeConfigDisplayer(const cycleoption * O,festring & Entry)980 void ivanconfig::WorldShapeConfigDisplayer(const cycleoption* O, festring& Entry)
981 {
982   if(O->Value == 0)
983     Entry << "Pancake (flat)";
984   else if(O->Value == 1)
985     Entry << "Brandy snap (cylinder)";
986   else if(O->Value == 2)
987     Entry << "Doughnut (torus)";
988   else
989     Entry << O->Value;
990 }
991 
GetWorldSizeConfig()992 v2 ivanconfig::GetWorldSizeConfig()
993 {
994   v2 WorldSize = v2(49, 49);
995 
996   if(WorldSizeConfig.Value == HUGE_WORLD)
997     WorldSize = v2(128, 128);
998   else if(WorldSizeConfig.Value == LARGE_WORLD)
999     WorldSize = v2(96, 96);
1000   else if(WorldSizeConfig.Value == SMALL_WORLD)
1001     WorldSize = v2(49, 49);
1002   else if(WorldSizeConfig.Value == TINY_WORLD)
1003     WorldSize = v2(32, 32);
1004   else if(WorldSizeConfig.Value == ONE_SCREEN_WORLD)
1005     WorldSize = v2(42, 26);
1006   else if(WorldSizeConfig.Value == FOUR_SCREEN_WORLD)
1007     WorldSize = v2(84, 52);
1008   else
1009     WorldSize = v2(49, 49); //SMALL_WORLD
1010 
1011   return WorldSize;
1012 }
1013 
WorldSeedConfigDisplayer(const numberoption * O,festring & Entry)1014 void ivanconfig::WorldSeedConfigDisplayer(const numberoption* O, festring& Entry)
1015 {
1016   Entry << O->Value << "/2147483647";
1017 }
1018 
WorldSeedConfigChangeInterface(numberoption * O)1019 truth ivanconfig::WorldSeedConfigChangeInterface(numberoption* O)
1020 {
1021   O->ChangeValue(iosystem::NumberQuestion(CONST_S("0 gives random world seed, else select new one at your own risk."), GetQuestionPos(), WHITE, !game::IsRunning()));
1022   clearToBackgroundAfterChangeInterface();
1023   return false;
1024 }
1025 
WorldSeedConfigChanger(numberoption * O,long What)1026 void ivanconfig::WorldSeedConfigChanger(numberoption* O, long What)
1027 {
1028   if(What < -1)
1029     What = 0;
1030 
1031   O->Value = What;
1032 }
1033 
1034 #ifndef __DJGPP__
1035 
GraphicsScaleDisplayer(const cycleoption * O,festring & Entry)1036 void ivanconfig::GraphicsScaleDisplayer(const cycleoption* O, festring& Entry)
1037 {
1038   Entry << O->Value << 'x';
1039 }
1040 
GraphicsScaleChanger(cycleoption * O,long What)1041 void ivanconfig::GraphicsScaleChanger(cycleoption* O, long What)
1042 {
1043   O->Value = What;
1044   graphics::SetScale(What);
1045 }
1046 
SilhouetteScaleDisplayer(const cycleoption * O,festring & Entry)1047 void ivanconfig::SilhouetteScaleDisplayer(const cycleoption* O, festring& Entry)
1048 {
1049   Entry << O->Value << 'x';
1050 }
1051 
AltListItemPosDisplayer(const cycleoption * O,festring & Entry)1052 void ivanconfig::AltListItemPosDisplayer(const cycleoption* O, festring& Entry)
1053 {
1054   switch(O->Value){
1055   case 0:Entry << "disabled";break; //do not show
1056   case 1:Entry << "no";break; //default pos
1057   case 2:Entry << "yes";break; //alt pos
1058   }
1059 }
1060 
SaveGameSortModeDisplayer(const cycleoption * O,festring & Entry)1061 void ivanconfig::SaveGameSortModeDisplayer(const cycleoption* O, festring& Entry)
1062 {
1063   switch(O->Value){
1064   case 0: Entry << "newest first";break;
1065   case 1: Entry << "newest first + progress";break;
1066   case 2: Entry << "alphanumeric";break;
1067   case 3: Entry << "alphanumeric + progress";break;
1068   }
1069 }
1070 
MemorizeEquipmentModeDisplayer(const cycleoption * O,festring & Entry)1071 void ivanconfig::MemorizeEquipmentModeDisplayer(const cycleoption* O, festring& Entry)
1072 {
1073   switch(O->Value){
1074   case 0:Entry << "disabled";break; //do not show
1075   case 1:Entry << "only pet";break; //default pos
1076   case 2:Entry << "everyone";break; //alt pos
1077   }
1078 }
1079 
DungeonGfxScaleDisplayer(const cycleoption * O,festring & Entry)1080 void ivanconfig::DungeonGfxScaleDisplayer(const cycleoption* O, festring& Entry)
1081 {
1082   Entry << O->Value << 'x';
1083 }
1084 
FontGfxDisplayer(const cycleoption * O,festring & Entry)1085 void ivanconfig::FontGfxDisplayer(const cycleoption* O, festring& Entry)
1086 {
1087   Entry << O->Value;
1088 }
1089 
SilhouetteScaleChanger(cycleoption * O,long What)1090 void ivanconfig::SilhouetteScaleChanger(cycleoption* O, long What)
1091 {
1092   O->Value = What;
1093 }
1094 
SaveGameSortModeChanger(cycleoption * O,long What)1095 void ivanconfig::SaveGameSortModeChanger(cycleoption* O, long What)
1096 {
1097   if(O!=NULL)O->Value = What;
1098 
1099   iosystem::SetSaveGameSortMode(What);
1100 }
1101 
DungeonGfxScaleChanger(cycleoption * O,long What)1102 void ivanconfig::DungeonGfxScaleChanger(cycleoption* O, long What)
1103 {
1104   O->Value = What;
1105 }
1106 
FontGfxChanger(cycleoption * O,long What)1107 void ivanconfig::FontGfxChanger(cycleoption* O, long What)
1108 {
1109   O->Value = What;
1110 }
1111 
SetupCustomKeysChanger(truthoption * O,truth What)1112 void ivanconfig::SetupCustomKeysChanger(truthoption* O, truth What)
1113 {
1114   if(game::IsRunning() || !What){
1115     O->Value = What;
1116     if(O->Value)
1117       game::ConfigureCustomKeys();
1118   }
1119 }
1120 
XBRZScaleChanger(truthoption * O,truth What)1121 void ivanconfig::XBRZScaleChanger(truthoption* O, truth What)
1122 {
1123   O->Value = What;
1124 
1125   game::UpdateSRegionsXBRZ();
1126 }
1127 
AllowMouseOnFelistChanger(truthoption * O,truth What)1128 void ivanconfig::AllowMouseOnFelistChanger(truthoption* O, truth What)
1129 {
1130   if(O!=NULL)O->Value = What;
1131   felist::SetAllowMouse(What);
1132   graphics::SetAllowMouseInFullScreen(What);
1133 }
1134 
UseExtraMenuGraphicsChanger(truthoption * O,truth What)1135 void ivanconfig::UseExtraMenuGraphicsChanger(truthoption* O, truth What)
1136 {
1137   if(O!=NULL)O->Value = What;
1138   felist::SetAllowMouse(What);
1139   graphics::SetAllowMouseInFullScreen(What);
1140 }
1141 
FullScreenModeChanger(truthoption *,truth)1142 void ivanconfig::FullScreenModeChanger(truthoption*, truth)
1143 {
1144   graphics::SwitchMode();
1145 }
1146 
ScalingQualityDisplayer(const cycleoption * O,festring & Entry)1147 void ivanconfig::ScalingQualityDisplayer(const cycleoption* O, festring& Entry)
1148 {
1149   switch(O->Value){
1150   case 0: Entry << "pixelated"; break;
1151   case 1: Entry << "smooth"; break;
1152   }
1153 }
1154 
1155 #endif
1156 
Show()1157 void ivanconfig::Show()
1158 {
1159   game::SRegionAroundDeny();
1160   configsystem::Show(&BackGroundDrawer, &game::SetStandardListAttributes, game::IsRunning());
1161   game::SRegionAroundAllow();
1162 }
1163 
ContrastHandler(long Value)1164 void ivanconfig::ContrastHandler(long Value)
1165 {
1166   ContrastChanger(&Contrast, Value);
1167 
1168   if(game::IsRunning())
1169   {
1170     game::GetCurrentArea()->SendNewDrawRequest();
1171     game::DrawEverythingNoBlit();
1172   }
1173 }
1174 
VolumeHandler(long Value)1175 void ivanconfig::VolumeHandler(long Value)
1176 {
1177   VolumeChanger(&Volume, Value);
1178 
1179   if(game::IsRunning())
1180   {
1181     game::GetCurrentArea()->SendNewDrawRequest();
1182     game::DrawEverythingNoBlit();
1183   }
1184 }
SfxVolumeHandler(long Value)1185 void ivanconfig::SfxVolumeHandler(long Value)
1186 {
1187   SfxVolumeChanger(&SfxVolume, Value);
1188 
1189   soundeffects::SetSfxVolume(SfxVolume.Value);
1190 
1191   if(game::IsRunning())
1192   {
1193     game::GetCurrentArea()->SendNewDrawRequest();
1194     game::DrawEverythingNoBlit();
1195   }
1196 }
1197 
1198 #ifndef __DJGPP__
1199 
SwitchModeHandler()1200 void ivanconfig::SwitchModeHandler()
1201 {
1202   FullScreenMode.Value = !FullScreenMode.Value;
1203   Save();
1204 }
1205 
1206 #endif
1207 
CalculateContrastLuminance()1208 void ivanconfig::CalculateContrastLuminance()
1209 {
1210   int Element = Min<long>((GetContrast() << 7) / 100, 255);
1211   ContrastLuminance = MakeRGB24(Element, Element, Element);
1212 }
1213 
1214 // TODO keep initializing with invalid values (where possible) so if they are used before cfg file loading it will show errors clearly?
1215 int  ivanconfig::iStartingWindowWidth=-1;
1216 int  ivanconfig::iStartingWindowHeight=-1;
1217 int  ivanconfig::iStartingDungeonGfxScale=-1;
1218 int  ivanconfig::iStartingFontGfx=-1;
1219 bool ivanconfig::bStartingOutlinedGfx=false;
Initialize()1220 void ivanconfig::Initialize()
1221 {
1222   festring fsCategory;
1223 
1224   fsCategory="General Setup";
1225   configsystem::AddOption(fsCategory,&DefaultName);
1226   configsystem::AddOption(fsCategory,&FantasyNamePattern);
1227   configsystem::AddOption(fsCategory,&DefaultPetName);
1228   configsystem::AddOption(fsCategory,&StartWithNoPet);
1229   configsystem::AddOption(fsCategory,&AutoSaveInterval);
1230   configsystem::AddOption(fsCategory,&AltAdentureInfo);
1231 
1232   fsCategory="Gameplay Options";
1233   configsystem::AddOption(fsCategory,&BeNice);
1234   configsystem::AddOption(fsCategory,&HoldPosMaxDist);
1235   //configsystem::AddOption(fsCategory,&MemorizeEquipmentMode); // Let everyone retore equipped items on unpolymorph.
1236   configsystem::AddOption(fsCategory,&WarnAboutDanger);
1237   configsystem::AddOption(fsCategory,&AutoDropLeftOvers);
1238   configsystem::AddOption(fsCategory,&SmartOpenCloseApply);
1239   configsystem::AddOption(fsCategory,&CenterOnPlayerAfterLook);
1240   configsystem::AddOption(fsCategory,&DescriptiveHP);
1241   configsystem::AddOption(fsCategory,&ShowGodInfo); //gameplay change in a sense that, to remember what each god is about may be a challenge on itself :)
1242   configsystem::AddOption(fsCategory,&ShowMapAtDetectMaterial);
1243   configsystem::AddOption(fsCategory,&GoOnStopMode);
1244   configsystem::AddOption(fsCategory,&WaitNeutralsMoveAway);
1245   configsystem::AddOption(fsCategory,&AllWeightIsRelevant);
1246   configsystem::AddOption(fsCategory,&ShowVolume);
1247   configsystem::AddOption(fsCategory,&EnhancedLights);
1248   configsystem::AddOption(fsCategory,&DistLimitMagicMushrooms);
1249   configsystem::AddOption(fsCategory,&AutoPickupThrownItems);
1250   configsystem::AddOption(fsCategory,&AutoPickUpMatching);
1251 
1252   fsCategory="Game Window";
1253   configsystem::AddOption(fsCategory,&Contrast);
1254   configsystem::AddOption(fsCategory,&WindowWidth);
1255   configsystem::AddOption(fsCategory,&WindowHeight);
1256 #ifndef __DJGPP__
1257   configsystem::AddOption(fsCategory,&GraphicsScale);
1258   configsystem::AddOption(fsCategory,&FullScreenMode);
1259 #endif
1260 
1261   fsCategory="Graphics";
1262 #ifndef __DJGPP__
1263   configsystem::AddOption(fsCategory,&ScalingQuality);
1264 #endif
1265   configsystem::AddOption(fsCategory,&LookZoom);
1266   configsystem::AddOption(fsCategory,&XBRZScale);
1267   configsystem::AddOption(fsCategory,&XBRZSquaresAroundPlayer);
1268   configsystem::AddOption(fsCategory,&SilhouetteScale);
1269   configsystem::AddOption(fsCategory,&AltSilhouette);
1270   configsystem::AddOption(fsCategory,&AltSilhouettePreventColorGlitch);
1271   configsystem::AddOption(fsCategory,&AltListItemPos);
1272   configsystem::AddOption(fsCategory,&AltListItemWidth);
1273   configsystem::AddOption(fsCategory,&StackListPageLength);
1274   configsystem::AddOption(fsCategory,&DungeonGfxScale);
1275   configsystem::AddOption(fsCategory,&FontGfx);
1276   configsystem::AddOption(fsCategory,&OutlinedGfx);
1277   configsystem::AddOption(fsCategory,&FrameSkip);
1278   configsystem::AddOption(fsCategory,&ShowItemsAtPlayerSquare);
1279   configsystem::AddOption(fsCategory,&RotateTimesPerSquare);
1280   configsystem::AddOption(fsCategory,&HitIndicator);
1281   configsystem::AddOption(fsCategory,&ShowMap);
1282   configsystem::AddOption(fsCategory,&TransparentMapLM);
1283   configsystem::AddOption(fsCategory,&UseExtraMenuGraphics);
1284 
1285   fsCategory="Sounds";
1286   configsystem::AddOption(fsCategory,&PlaySounds);
1287 
1288   std::vector<std::string> DeviceNames;
1289   int NumDevices = audio::GetMIDIOutputDevices(DeviceNames);
1290   MIDIOutputDevice.Value = 0;
1291   if( NumDevices )
1292   {
1293      MIDIOutputDevice.Value = 1;
1294   }
1295   MIDIOutputDevice.CycleCount = NumDevices+1;
1296 
1297   configsystem::AddOption(fsCategory,&MIDIOutputDevice);
1298   configsystem::AddOption(fsCategory,&Volume);
1299   configsystem::AddOption(fsCategory,&SfxVolume);
1300 
1301   fsCategory="Input and Interface";
1302   configsystem::AddOption(fsCategory,&DirectionKeyMap);
1303   configsystem::AddOption(fsCategory,&SetupCustomKeys);
1304   configsystem::AddOption(fsCategory,&SaveGameSortMode);
1305   configsystem::AddOption(fsCategory,&ShowTurn);
1306   configsystem::AddOption(fsCategory,&ShowFullDungeonName);
1307   configsystem::AddOption(fsCategory,&SelectedBkgColor);
1308   configsystem::AddOption(fsCategory,&AllowMouseOnFelist);
1309 
1310   fsCategory="Advanced Options";
1311   configsystem::AddOption(fsCategory,&AllowImportOldSavegame);
1312   configsystem::AddOption(fsCategory,&HideWeirdHitAnimationsThatLookLikeMiss);
1313   configsystem::AddOption(fsCategory,&UseLightEmiterBasedOnVolume);
1314 
1315   fsCategory="World Generation";
1316   configsystem::AddOption(fsCategory, &WorldSizeConfig);
1317   configsystem::AddOption(fsCategory, &LandTypeConfig);
1318   configsystem::AddOption(fsCategory, &WorldShapeConfig);
1319   configsystem::AddOption(fsCategory, &WorldSeedConfig);
1320 
1321   //World shape: Flat, [Horizontal Wrap (cylinder)]
1322   //  Alt names for world shape: pancake (flat), doughnut (torus), brandy snap (cylinder).
1323 
1324   /********************************
1325    * LOAD AND APPLY some SETTINGS *
1326    ********************************/
1327 #if defined(WIN32) || defined(__DJGPP__)
1328   configsystem::SetConfigFileName(GetUserDataDir() + "ivan.cfg");
1329 #else
1330   configsystem::SetConfigFileName(GetUserDataDir() + "ivan.conf");
1331 #endif
1332 
1333   configsystem::Load();
1334 
1335   iStartingWindowWidth = WindowWidth.Value;
1336   iStartingWindowHeight = WindowHeight.Value;
1337   iStartingDungeonGfxScale = DungeonGfxScale.Value;
1338   iStartingFontGfx = FontGfx.Value;
1339   bStartingOutlinedGfx = OutlinedGfx.Value;
1340 
1341   CalculateContrastLuminance();
1342   audio::ChangeMIDIOutputDevice(MIDIOutputDevice.Value);
1343   audio::SetVolumeLevel(Volume.Value);
1344 
1345   if(ivanconfig::IsSetupCustomKeys())
1346     game::LoadCustomCommandKeys();
1347 
1348   //TODO re-use changer methods for above configs too to avoid duplicating the algo?
1349   FrameSkipChanger(NULL,FrameSkip.Value);
1350   StackListPageLengthChanger(NULL, StackListPageLength.Value);
1351   SaveGameSortModeChanger(NULL, SaveGameSortMode.Value);
1352   SelectedBkgColorChanger(NULL, SelectedBkgColor.Value);
1353   AutoPickUpMatchingChanger(NULL, AutoPickUpMatching.Value);
1354   AllowMouseOnFelistChanger(NULL, AllowMouseOnFelist.Value);
1355   UseExtraMenuGraphicsChanger(NULL, UseExtraMenuGraphics.Value);
1356 
1357 #ifndef NOSOUND
1358   soundeffects::SetEnableSfx(PlaySounds.Value);
1359   soundeffects::SetSfxVolume(SfxVolume.Value);
1360   soundeffects::SetDataDir(game::GetDataDir());
1361 #endif
1362 }
1363