1 /***************************************************************************
2              userconfiguration.cpp  -  Manages game preferences
3                              -------------------
4     begin                : Sat Feb 14 2004
5     copyright            : (C) 2004 by Daroth-U
6     email                : daroth-u@ifrance.com
7  ***************************************************************************/
8 
9 /***************************************************************************
10  *                                                                         *
11  *   This program is free software; you can redistribute it and/or modify  *
12  *   it under the terms of the GNU General Public License as published by  *
13  *   the Free Software Foundation; either version 2 of the License, or     *
14  *   (at your option) any later version.                                   *
15  *                                                                         *
16  ***************************************************************************/
17 
18 #include "common/constants.h"
19 #include "userconfiguration.h"
20 
21 using namespace std;
22 
23 #ifndef WIN32
24 #include <sys/stat.h>
25 #include <unistd.h>
26 #endif
27 
28 #include "gui/guitheme.h"
29 
30 // ###### MS Visual C++ specific ######
31 #if defined(_MSC_VER) && defined(_DEBUG)
32 # define new DEBUG_NEW
33 # undef THIS_FILE
34 static char THIS_FILE[] = __FILE__;
35 #endif
36 
37 
38 // TODO : - warn if there is an unknown parameter in the config file ?
39 //        - manage doubled keynames -> must be impossible in optionsmenu
40 //        - make an array for variables too (they are all hard coded for now)
41 //        - default config if config file not there ??
42 
43 const char UserConfiguration::default_key[][40] = {
44 
45 	/*
46 	SET_MOVE_DOWN = 0,
47 	SET_MOVE_RIGHT,
48 	SET_MOVE_UP,
49 	SET_MOVE_LEFT,
50 	*/
51 
52 
53 	"down",
54 	"right",
55 	"up",
56 	"left",
57 
58 	/*    SET_PLAYER_0,
59 	    SET_PLAYER_1,
60 	    SET_PLAYER_2,
61 	    SET_PLAYER_3,
62 	    SET_PLAYER_ONLY,
63 	*/
64 
65 	"1",
66 	"2",
67 	"3",
68 	"4",
69 	"0",
70 
71 	/*    SHOW_BACKPACK,
72 	    SHOW_OPTIONS_MENU,
73 	    SET_NEXT_FORMATION,
74 	*/
75 
76 	"i",
77 	"o",
78 	"f",
79 
80 	/*
81 	    TOGGLE_MINIMAP,
82 	*/
83 
84 	"[+]",
85 
86 	/*
87 	    SET_ZOOM_IN,
88 	    SET_ZOOM_OUT,
89 	*/
90 
91 	"8",
92 	"9",
93 
94 	/*
95 	    TOGGLE_MAP_CENTER,
96 	    INCREASE_GAME_SPEED,
97 	    DECREASE_GAME_SPEED,
98 	*/
99 
100 	"m",
101 	"k",
102 	"l",
103 
104 //    START_ROUND,
105 
106 	"space",
107 
108 	/*
109 	  LAYOUT_1,
110 	  LAYOUT_2,
111 	  LAYOUT_4,
112 	*/
113 
114 	"g",
115 	"h",
116 	"j",
117 
118 	/*
119 	    SWITCH_COMBAT,
120 	*/
121 
122 	"c",
123 
124 	/*
125 	  NEXT_WEAPON,
126 	*/
127 	"]",
128 
129 	/*
130 	    QUICK_SPELL_1,
131 	    QUICK_SPELL_2,
132 	    QUICK_SPELL_3,
133 	    QUICK_SPELL_4,
134 	    QUICK_SPELL_5,
135 	    QUICK_SPELL_6,
136 	    QUICK_SPELL_7,
137 	    QUICK_SPELL_8,
138 	    QUICK_SPELL_9,
139 	    QUICK_SPELL_10,
140 	    QUICK_SPELL_11,
141 	    QUICK_SPELL_12
142 	*/
143 
144 	"f1",
145 	"f2",
146 	"f3",
147 	"f4",
148 	"f5",
149 	"f6",
150 	"f7",
151 	"f8",
152 	"f9",
153 	"f10",
154 	"f11",
155 	"f12",
156 
157 	/*
158 	  QUICK_SAVE,
159 	  QUICK_LOAD,
160 	  AUTO_LOAD,
161 	*/
162 	"q",
163 	"w",
164 	"a"
165 };
166 
167 // Must be exact copy of enums defined in userconfiguration.h
168 // (except for ENGINE_ACTION_COUNT)
169 const char * UserConfiguration::ENGINE_ACTION_NAMES[] = {
170 
171 	"SET_MOVE_DOWN",
172 	"SET_MOVE_RIGHT",
173 	"SET_MOVE_UP",
174 	"SET_MOVE_LEFT",
175 
176 	"SET_PLAYER_0",
177 	"SET_PLAYER_1",
178 	"SET_PLAYER_2",
179 	"SET_PLAYER_3",
180 	"SET_PLAYER_ONLY",
181 
182 	"SHOW_BACKPACK",
183 	"SHOW_OPTIONS_MENU",
184 	"SET_NEXT_FORMATION",
185 
186 	"TOGGLE_MINIMAP",
187 
188 	"SET_ZOOM_IN",
189 	"SET_ZOOM_OUT",
190 
191 	"TOGGLE_MAP_CENTER",
192 	"INCREASE_GAME_SPEED",
193 	"DECREASE_GAME_SPEED",
194 
195 	"START_ROUND",
196 
197 	"LAYOUT_1",
198 	"LAYOUT_2",
199 	"LAYOUT_4",
200 
201 	"SWITCH_COMBAT",
202 
203 	"NEXT_WEAPON",
204 
205 	"QUICK_SPELL_1",
206 	"QUICK_SPELL_2",
207 	"QUICK_SPELL_3",
208 	"QUICK_SPELL_4",
209 	"QUICK_SPELL_5",
210 	"QUICK_SPELL_6",
211 	"QUICK_SPELL_7",
212 	"QUICK_SPELL_8",
213 	"QUICK_SPELL_9",
214 	"QUICK_SPELL_10",
215 	"QUICK_SPELL_11",
216 	"QUICK_SPELL_12",
217 
218 	"QUICK_SAVE",
219 	"QUICK_LOAD",
220 	"AUTO_LOAD"
221 };
222 
223 
224 // Must be exact copy of enums defined in userconfiguration.h
225 // (without the "_STOP" and except for ENGINE_ACTION_UP_COUNT)
226 const char * UserConfiguration :: ENGINE_ACTION_UP_NAMES[] = {
227 
228 	"SET_MOVE_DOWN",
229 	"SET_MOVE_RIGHT",
230 	"SET_MOVE_UP",
231 	"SET_MOVE_LEFT",
232 	"SET_Y_ROT_PLUS",
233 	"SET_Y_ROT_MINUS",
234 	"SET_Z_ROT_PLUS",
235 	"SET_Z_ROT_MINUS",
236 	"SET_ZOOM_IN",
237 	"SET_ZOOM_OUT",
238 	"SET_NEXT_FORMATION"
239 
240 };
241 
242 
243 
244 const char * UserConfiguration::ENGINE_ACTION_DESCRIPTION[] = {
245 
246 	_( "Scroll map south" ),
247 	_( "Scroll map north" ),
248 	_( "Scroll map east" ),
249 	_( "Scroll map west" ),
250 
251 	_( "Select player 0" ),
252 	_( "Select player 1" ),
253 	_( "Select player 2" ),
254 	_( "Select player 3" ),
255 	_( "Toggle group mode" ),
256 
257 	_( "Show backpack" ),
258 	_( "Show options" ),
259 	_( "Choose next formation" ),
260 
261 	_( "Toggle minimap" ),
262 
263 	_( "Zoom in map" ),
264 	_( "Zoom out map" ),
265 
266 	_( "Always center map" ),
267 	_( "Increase game speed" ),
268 	_( "Decrease game speed" ),
269 
270 	_( "Start next round" ),
271 
272 	_( "Floating UI layout" ),
273 	_( "Bottom UI layout" ),
274 	_( "Inventory UI layout" ),
275 
276 	_( "Switch combat mode" ),
277 
278 	_( "Switch to next weapon" ),
279 
280 	_( "Quick Spell 1" ),
281 	_( "Quick Spell 2" ),
282 	_( "Quick Spell 3" ),
283 	_( "Quick Spell 4" ),
284 	_( "Quick Spell 5" ),
285 	_( "Quick Spell 6" ),
286 	_( "Quick Spell 7" ),
287 	_( "Quick Spell 8" ),
288 	_( "Quick Spell 9" ),
289 	_( "Quick Spell 10" ),
290 	_( "Quick Spell 11" ),
291 	_( "Quick Spell 12" ),
292 
293 	_( "Quick save" ),
294 	_( "Quick load" ),
295 	_( "Load autosave" )
296 };
297 
298 
UserConfiguration()299 UserConfiguration::UserConfiguration()
300 		: Preferences()
301 		, configurationChanged( false )
302 		, keyDownBindings()
303 		, keyUpBindings()
304 		, mouseDownBindings()
305 		, mouseUpBindings()
306 		, engineActionUpNumber()
307 		, engineActionNumber()
308 		, keyForEngineAction()
309 		, engineActionName()
310 		// default settings for video mode (are overridden by command line)
311 		, fullscreen( true )
312 		, doublebuf( true )
313 		, hwpal( true )
314 		, resizeable( true )
315 		, force_hwsurf( false )
316 		, force_swsurf( false )
317 		, hwaccel( true )
318 		, test( false )
319 		, multitexturing( true )
320 		, stencilbuf( true )
321 		, bpp( -1 )
322 		, w( 800 )
323 		, h( 600 )
324 		, shadows( 0 )
325 		, alwaysShowPath( true )
326 		, tooltipEnabled( true )
327 		, enableScreenshots( true )
328 		, tooltipInterval( 50 )
329 		, aniso_filter( false )
330 		// game settings
331 		, gamespeed( 1 )  // fast speed
332 		, centermap( true )
333 		, keepMapSize( true )
334 		, frameOnFullScreen( true )
335 		, turnBasedBattle( true )
336 		, ovalCutoutShown( true )
337 		, outlineInteractiveItems( true )
338 		, combatInfoDetail( 0 )
339 		, hideInventoriesOnMove( true )
340 		, logLevel( 3 )
341 		, pathFindingQuality( 0 )
342 		, maxPathNodes( 500 )
343 		// audio settings
344 		, soundEnabled( true )
345 		, soundFreq( 5 )
346 		, musicVolume( 64 )
347 		, effectsVolume( 128 )
348 		// others
349 		, standAloneMode( NONE )
350 		, host()
351 		, userName()
352 		, port( 0 )
353 		, monsterToughness( 0 )
354 		, debugTheme( false )
355 		, flaky( false ) {
356 	// Build (string engineAction -> int engineAction ) lookup table
357 	// and   (int ea -> string ea) lookup table
358 	for ( int i = 0; i < ENGINE_ACTION_COUNT ; i++ ) {
359 		string temp( ENGINE_ACTION_NAMES[i] );
360 		for ( size_t j = 0; j < temp.length(); j++ ) {
361 			temp[j] = tolower( temp[j] );
362 		}
363 		//engineActionNumber.insert( std::pair<string,int>( temp, i ) );
364 		//engineActionName.insert( std::pair<int,string>( i, temp ) );
365 
366 		engineActionNumber[temp] = i;
367 		engineActionName[i] = temp;
368 	}
369 
370 	// Build (string engineActionUp -> int engineActionUp ) lookup table
371 	for ( int i = SET_MOVE_DOWN_STOP; i < ENGINE_ACTION_UP_COUNT ; i++ ) {
372 		string temp = ENGINE_ACTION_UP_NAMES[i - SET_MOVE_DOWN_STOP];
373 		for ( size_t j = 0; j < temp.length(); j++ ) {
374 			temp[j] = tolower( temp[j] );
375 		}
376 		engineActionUpNumber[temp] = i;
377 	}
378 
379 	if ( DEBUG_USER_CONFIG ) {
380 		map<string, int>::iterator p = engineActionUpNumber.begin();
381 		cout << "Engine Action Up list : " << endl;
382 		while ( p != engineActionUpNumber.end() ) {
383 			cout << " '" << p->first << "' associated to  '" << p->second << "'" << endl;
384 			p++;
385 		}
386 
387 		cout << endl << endl;
388 		p = engineActionNumber.begin();
389 		cout << "Engine Action list : " << endl;
390 		while ( p != engineActionNumber.end() ) {
391 			cout << " '" << p->first << "' associated to  '" << p->second << "'" << endl;
392 			p++;
393 		}
394 	}
395 }
396 
loadConfiguration()397 void UserConfiguration::loadConfiguration() {
398 	ifstream *configFile;
399 	string sLine;
400 	string sInstruction, sFirstParam, sSecondParam;
401 	char textLine[255];
402 	int pos, firstChar, endWord, foo;
403 	int lineNumber;
404 	unsigned int i;
405 	bool isCurrentVersion = false;
406 
407 	//    strcpy(path, rootDir);
408 	//    strcat(path, CONFIG_FILE_NAME);
409 	string path = get_config_file_name();
410 	configFile = new ifstream( path.c_str() );
411 	if ( !configFile->is_open() ) {
412 		cerr << "Can't open configuration file: " << path << endl;
413 		cerr << "Will create a default config file at the above location." << endl;
414 		createDefaultConfigFile();
415 
416 		// try to open it again
417 		delete configFile;
418 		configFile = new ifstream( path.c_str() );
419 		if ( !configFile->is_open() ) {
420 			cout << "Error: Can't open configuration file: " << path << endl;
421 			exit( 1 );
422 		}
423 	}
424 
425 	// loop through the whole configuration file
426 	lineNumber = 0;
427 	while ( !configFile->eof() ) {
428 		configFile -> getline( textLine, 255 );
429 		sLine = textLine;
430 		if ( !sInstruction.empty() ) sInstruction.clear();
431 		if ( !sFirstParam.empty() ) sFirstParam.clear();
432 		if ( !sSecondParam.empty() ) sSecondParam.clear();
433 
434 		for ( i = 0; i < sLine.length(); i++ ) {
435 			sLine[i] = tolower( sLine[i] );
436 		}
437 
438 		// search for keywords, ignore lines not begining with keyword or spaces
439 		endWord = -1;
440 		foo = -1;
441 		firstChar = sLine.find_first_not_of( ' ', 0 );
442 		pos = sLine.find( "bind", 0 );
443 		if ( pos < 0 ) {
444 			pos = sLine.find( "set", 0 );
445 			if ( pos < 0 ) {
446 				pos = sLine.find( "version", 0 );
447 				if ( pos >= 0 && pos <= firstChar ) {
448 					sInstruction = "version";
449 					sFirstParam = getNextWord( sLine, pos + 7, endWord );
450 					// hack
451 					foo = 2;
452 				}
453 			} else if ( pos <= firstChar ) {
454 				sInstruction = "set";
455 				sFirstParam = getNextWord( sLine, pos + 3, endWord );
456 				sSecondParam = getNextWord( sLine, endWord, foo );
457 			}
458 		} else if ( pos <= firstChar ) {
459 			sInstruction = "bind";
460 			sFirstParam = getNextWord( sLine, pos + 4, endWord );
461 			sSecondParam = getNextWord( sLine, endWord, foo );
462 		}
463 
464 		if ( sFirstParam.empty() || ( sInstruction != "version" && sSecondParam.empty() ) || foo == endWord ) {
465 			if ( pos >= 0 && sInstruction.length() != 0 ) {
466 				cerr  << "Warning : in file " << path
467 				<< " missing parameter at line " << lineNumber
468 				<< ", ignoring line." << endl;
469 			}
470 		} else {
471 			if ( sInstruction == "bind" ) {
472 				bind( sFirstParam, sSecondParam, lineNumber );
473 			} else if ( sInstruction == "version" ) {
474 				isCurrentVersion = ( sFirstParam == SCOURGE_VERSION );
475 			} else {
476 				set( sFirstParam, sSecondParam, lineNumber );
477 			}
478 		}
479 
480 		lineNumber++;
481 	}
482 	configurationChanged = true;
483 
484 	delete configFile;
485 
486 	// set default bindings for unbound actions
487 	if ( !isCurrentVersion ) {
488 		keyForEngineAction.clear();
489 		keyDownBindings.clear();
490 		keyUpBindings.clear();
491 	}
492 	for ( int i = 0; i < ENGINE_ACTION_COUNT; i++ ) {
493 		// if no bindings
494 		if ( keyForEngineAction.find( i ) == keyForEngineAction.end() ) {
495 			string keyName = default_key[ i ];
496 			bind( keyName, engineActionName[ i ], 1 );
497 		}
498 	}
499 
500 	// merge old and new settings
501 	if ( !isCurrentVersion ) {
502 		saveConfiguration();
503 	}
504 }
505 
saveConfiguration()506 void UserConfiguration::saveConfiguration() {
507 	ofstream *configFile;
508 	string sLine;
509 	int i;
510 
511 	string path = get_config_file_name();
512 	configFile = new ofstream( path.c_str() );
513 	if ( !configFile->is_open() ) {
514 		cout << "Error while saving " << path << endl;
515 		return;
516 	}
517 	enum { TXT_SIZE = 255 };
518 	char textLine[ TXT_SIZE ];
519 	snprintf( textLine, TXT_SIZE, "Generated by Scourge version %s\n", SCOURGE_VERSION );
520 	writeFile( configFile, textLine );
521 	writeFile( configFile, "Modify at your own risks.\n" );
522 	writeFile( configFile, "-------------------------------------------------\n" );
523 	writeFile( configFile, "- A line not beginning with BIND or SET is ignored (spaces excepted)\n" );
524 	writeFile( configFile, "- Only one instruction per line will be processed\n" );
525 	writeFile( configFile, "- No upper/lower case distinction\n" );
526 	writeFile( configFile, "- A space is a parameter separator so replace spaces by '_' if needed in your parameters.\n" );
527 	writeFile( configFile, "    Example : for 'left bracket' put 'left_bracket'\n" );
528 	writeFile( configFile, "- No specific order needed between BIND/SET commands\n\n" );
529 	writeFile( configFile, "Syntax : \n" );
530 	writeFile( configFile, "- BIND  sdl_key_name  engineAction\n" );
531 	writeFile( configFile, "- SET   variable   value\n" );
532 	writeFile( configFile, "without the '-' at the beginning\n" );
533 	writeFile( configFile, "sdl_key_names are defined in SDL.h\n" );
534 	writeFile( configFile, "engineActions and variables are defined in userconfiguration.h\n" );
535 	writeFile( configFile, "-------------------------------------------------\n\n" );
536 
537 	// print the version
538 	snprintf( textLine, TXT_SIZE, "version %s\n", SCOURGE_VERSION );
539 	writeFile( configFile, textLine );
540 
541 	writeFile( configFile, "// Bindings\n" );
542 
543 	// save bindings
544 	for ( i = 0; i < ENGINE_ACTION_COUNT ; i++ ) {
545 		if ( keyForEngineAction.find( i ) != keyForEngineAction.end() ) {
546 			sLine = "bind " + keyForEngineAction[i];
547 			if ( engineActionName.find( i ) != engineActionName.end() ) {
548 				sLine = sLine + " " + engineActionName[i] + "\n";
549 				writeFile( configFile, ( char * ) sLine.c_str() );
550 			}
551 		}
552 	}
553 
554 	// save video variables
555 	writeFile( configFile, "\n// Video settings\n" );
556 	snprintf( textLine, TXT_SIZE, "set fullscreen %s\n", fullscreen ? "true" : "false" );
557 	writeFile( configFile, textLine );
558 	snprintf( textLine, TXT_SIZE, "set doublebuf %s\n", doublebuf ? "true" : "false" );
559 	writeFile( configFile, textLine );
560 	snprintf( textLine, TXT_SIZE, "set stencilbuf %s\n", stencilbuf ? "true" : "false" );
561 	writeFile( configFile, textLine );
562 	snprintf( textLine, TXT_SIZE, "set hwpal %s\n", hwpal ? "true" : "false" );
563 	writeFile( configFile, textLine );
564 	snprintf( textLine, TXT_SIZE, "set resizeable %s\n", resizeable ? "true" : "false" );
565 	writeFile( configFile, textLine );
566 	snprintf( textLine, TXT_SIZE, "set force_hwsurf %s\n", force_hwsurf ? "true" : "false" );
567 	writeFile( configFile, textLine );
568 	snprintf( textLine, TXT_SIZE, "set force_swsurf %s\n", force_swsurf ? "true" : "false" );
569 	writeFile( configFile, textLine );
570 	snprintf( textLine, TXT_SIZE, "set multitexturing %s\n", Constants::multitexture ? "true" : "false" );
571 	writeFile( configFile, textLine );
572 	snprintf( textLine, TXT_SIZE, "set hwaccel %s\n", hwaccel ? "true" : "false" );
573 	writeFile( configFile, textLine );
574 	snprintf( textLine, TXT_SIZE, "set shadows %d  // 0 : no shadows, 2 : best shadows\n", shadows );
575 	writeFile( configFile, textLine );
576 	snprintf( textLine, TXT_SIZE, "set w %d\n", w );
577 	writeFile( configFile, textLine );
578 	snprintf( textLine, TXT_SIZE, "set h %d\n", h );
579 	writeFile( configFile, textLine );
580 	snprintf( textLine, TXT_SIZE, "set bpp %d\n", bpp );
581 	writeFile( configFile, textLine );
582 	snprintf( textLine, TXT_SIZE, "set aniso_filter %s\n", aniso_filter ? "true" : "false" );
583 	writeFile( configFile, textLine );
584 	snprintf( textLine, TXT_SIZE, "\n// Game settings\n" );
585 	writeFile( configFile, textLine );
586 	snprintf( textLine, TXT_SIZE, "set gamespeed %d  // 0 : fastest, 4 : slowest\n", gamespeed );
587 	writeFile( configFile, textLine );
588 	snprintf( textLine, TXT_SIZE, "set monstertoughness %d  // 0 : easy, 2 : toughest\n", monsterToughness );
589 	writeFile( configFile, textLine );
590 	snprintf( textLine, TXT_SIZE, "set centermap %s\n", centermap ? "true" : "false" );
591 	writeFile( configFile, textLine );
592 	snprintf( textLine, TXT_SIZE, "set keepmapsize %s\n", keepMapSize ? "true" : "false" );
593 	writeFile( configFile, textLine );
594 	snprintf( textLine, TXT_SIZE, "set frameonfullscreen %s\n", frameOnFullScreen ? "true" : "false" );
595 	writeFile( configFile, textLine );
596 	snprintf( textLine, TXT_SIZE, "set ovalcutoutshown %s\n", ovalCutoutShown ? "true" : "false" );
597 	writeFile( configFile, textLine );
598 	snprintf( textLine, TXT_SIZE, "set outlineinteractiveitems %s\n", outlineInteractiveItems ? "true" : "false" );
599 	writeFile( configFile, textLine );
600 	snprintf( textLine, TXT_SIZE, "set hideinventoriesonmove %s\n", hideInventoriesOnMove ? "true" : "false" );
601 	writeFile( configFile, textLine );
602 	snprintf( textLine, TXT_SIZE, "set combatinfodetail %d\n", combatInfoDetail );
603 	writeFile( configFile, textLine );
604 	snprintf( textLine, TXT_SIZE, "set turnbasedbattle %s\n", turnBasedBattle ? "true" : "false" );
605 	writeFile( configFile, textLine );
606 	snprintf( textLine, TXT_SIZE, "set alwaysshowpath %s\n", alwaysShowPath ? "true" : "false" );
607 	writeFile( configFile, textLine );
608 	snprintf( textLine, TXT_SIZE, "set tooltipenabled %s\n", tooltipEnabled ? "true" : "false" );
609 	writeFile( configFile, textLine );
610 	snprintf( textLine, TXT_SIZE, "set enablescreenshots %s\n", enableScreenshots ? "true" : "false" );
611 	writeFile( configFile, textLine );
612 	snprintf( textLine, TXT_SIZE, "set tooltipinterval %d\n", tooltipInterval );
613 	writeFile( configFile, textLine );
614 	snprintf( textLine, TXT_SIZE, "set loglevel %d  // 0 : minimal, 3 : full\n", logLevel );
615 	writeFile( configFile, textLine );
616 	snprintf( textLine, TXT_SIZE, "set pathfindingquality %d  // 0 : basic, 2 : excellent\n", pathFindingQuality );
617 	writeFile( configFile, textLine );
618 	snprintf( textLine, TXT_SIZE, "\n// Audio settings\n" );
619 	writeFile( configFile, textLine );
620 	snprintf( textLine, TXT_SIZE, "set soundenabled %s\n", soundEnabled ? "true" : "false" );
621 	writeFile( configFile, textLine );
622 	snprintf( textLine, TXT_SIZE, "set soundfreq %d\n", soundFreq );
623 	writeFile( configFile, textLine );
624 	snprintf( textLine, TXT_SIZE, "set musicvolume %d\n", musicVolume );
625 	writeFile( configFile, textLine );
626 	snprintf( textLine, TXT_SIZE, "set effectsvolume %d\n", effectsVolume );
627 	writeFile( configFile, textLine );
628 
629 	delete configFile;
630 }
631 
setKeyForEngineAction(string keyName,int ea)632 void UserConfiguration::setKeyForEngineAction( string keyName, int ea ) {
633 
634 	string oldKeyName;
635 	string eas;
636 
637 	if ( keyForEngineAction.find( ea ) != keyForEngineAction.end() ) {
638 		oldKeyName = keyForEngineAction[ea];
639 		if ( keyDownBindings.find( oldKeyName ) != keyDownBindings.end() ) {
640 			keyDownBindings.erase( oldKeyName );
641 			if ( keyUpBindings.find( oldKeyName ) != keyUpBindings.end() ) {
642 				keyUpBindings.erase( oldKeyName );
643 			}
644 		}
645 		keyForEngineAction[ea] = keyName;
646 		keyDownBindings[keyName] = ea;
647 
648 		if ( engineActionName.find( ea ) != engineActionName.end() ) {
649 			eas = engineActionName[ea];
650 			if ( engineActionUpNumber.find( eas ) != engineActionUpNumber.end() ) {
651 				keyUpBindings[eas] = engineActionUpNumber[eas];
652 			}
653 		}
654 	}
655 }
656 
657 //    Bind   sdl_name_of_key    engineAction
658 // OR Bind   sdl_mouse_button   engineAction
bind(string s1,string s2,int lineNumber)659 void UserConfiguration::bind( string s1, string s2, int lineNumber ) {
660 	//int i;
661 
662 	if ( DEBUG_USER_CONFIG ) {
663 		cout << "line : " << lineNumber << " ";
664 		cout << "bind '" << s1 << "' '" << s2 << "'" << endl;
665 	}
666 
667 	// for now, we trust what is written in configuration file
668 	if ( engineActionNumber.find( s2 ) != engineActionNumber.end() ) {
669 		// Ignore debug ea
670 		keyDownBindings[s1] = engineActionNumber[s2];
671 		keyForEngineAction[engineActionNumber[s2]] = s1;
672 		if ( engineActionUpNumber.find( s2 ) != engineActionUpNumber.end() ) {
673 			keyUpBindings[s1] = engineActionUpNumber[s2];
674 		}
675 	}
676 }
677 
set(string s1,string s2,int lineNumber)678 void UserConfiguration::set( string s1, string s2, int lineNumber ) {
679 	bool paramValue = false;
680 
681 	if ( DEBUG_USER_CONFIG ) {
682 		cout << "line : " << lineNumber << " ";
683 		cout << "set '" << s1 << "' '" << s2 << "'" << endl;
684 	}
685 
686 	// Check if s1 is a valid variable to set (engineVariable?)
687 	// Check if s2 is a valid value
688 
689 	if ( s1 == "fullscreen" || s1 == "doublebuf" || s1 == "hwpal" || s1 == "resizeable" ||
690 	        s1 == "force_hwsurf" || s1 == "force_swsurf" || s1 == "hwaccel" ||
691 	        s1 == "multitexturing" || s1 == "stencilbuf" || s1 == "centermap" ||
692 	        s1 == "keepmapsize" || s1 == "frameonfullscreen" || s1 == "turnbasedbattle" ||
693 	        s1 == "ovalcutoutshown" || s1 == "outlineinteractiveitems" ||
694 	        s1 == "hideinventoriesonmove" ||
695 	        s1 == "soundenabled" || s1 == "alwaysshowpath" || s1 == "tooltipenabled" ||
696 	        s1 == "enablescreenshots" || s1 == "aniso_filter" ) {
697 		if ( s2 == "true" ) {
698 			paramValue = true;
699 		} else if ( s2 == "false" ) {
700 			paramValue = false;
701 		} else {
702 			cerr << "Warning : in file " << CONFIG_FILE // _NAME
703 			<< " invalid parameter at line " << lineNumber
704 			<< ", valid parameter are 'true' or 'false'. Ignoring line" << endl;
705 			return;
706 		}
707 	}
708 
709 	if ( s1 == "fullscreen" ) {
710 		fullscreen = paramValue;
711 	} else if ( s1 == "doublebuf" ) {
712 		doublebuf = paramValue;
713 	} else if ( s1 == "hwpal" ) {
714 		hwpal = paramValue;
715 	} else if ( s1 == "resizeable" ) {
716 		resizeable = paramValue;
717 	} else if ( s1 == "force_hwsurf" ) {
718 		force_hwsurf = paramValue;
719 	} else if ( s1 == "force_swsurf" ) {
720 		force_swsurf = paramValue;
721 	} else if ( s1 == "hwaccel" ) {
722 		hwaccel = paramValue;
723 	} else if ( s1 == "test" ) {
724 		test = paramValue;
725 	} else if ( s1 == "bpp" ) {
726 		bpp = atoi( s2.c_str() );
727 		if ( !( bpp == 8 || bpp == 15 || bpp == 16 || bpp == 24 || bpp == 32 ) ) {
728 			cerr << "Warning : in file " << CONFIG_FILE //_NAME
729 			<< " invalid bpp value at line " << lineNumber
730 			<< ", valid values are 8, 15, 16, 24 or 32 . Ignoring line" << endl;
731 			bpp = -1; // To autodetect best bpp value
732 		}
733 	} else if ( s1 == "aniso_filter" ) {
734 		aniso_filter = paramValue;
735 	} else if ( s1 == "soundfreq" ) {
736 		soundFreq = atoi( s2.c_str() );
737 	} else if ( s1 == "musicvolume" ) {
738 		musicVolume = atoi( s2.c_str() );
739 	} else if ( s1 == "effectsvolume" ) {
740 		effectsVolume = atoi( s2.c_str() );
741 	} else if ( s1 == "tooltipinterval" ) {
742 		tooltipInterval = atoi( s2.c_str() );
743 	} else if ( s1 == "w" ) {
744 		w = atoi( s2.c_str() );
745 	} else if ( s1 == "h" ) {
746 		h = atoi( s2.c_str() );
747 	} else if ( s1 == "combatinfodetail" ) {
748 		combatInfoDetail = atoi( s2.c_str() );
749 	} else if ( s1 == "shadows" ) {
750 		shadows = atoi( s2.c_str() );
751 		if ( !( shadows == 0 ||
752 		        shadows == 1 ||
753 		        shadows == 2 ) ) {
754 			cerr << "Warning : in file " << CONFIG_FILE //_NAME
755 			<< " invalid shadow mode at line " << lineNumber
756 			<< ", valid modes 0, 1, 2 . Ignoring line" << endl;
757 			shadows = 2; // Default value
758 		}
759 	} else if ( s1 == "stencilbuf" ) {
760 		stencilbuf = paramValue;
761 	} else if ( s1 == "multitexturing" ) {
762 		Constants::multitexture = paramValue;
763 	} else if ( s1 == "centermap" ) {
764 		centermap = paramValue;
765 	} else if ( s1 == "keepmapsize" ) {
766 		keepMapSize = paramValue;
767 	} else if ( s1 == "frameonfullscreen" ) {
768 		frameOnFullScreen = paramValue;
769 	} else if ( s1 == "turnbasedbattle" ) {
770 		turnBasedBattle = paramValue;
771 	} else if ( s1 == "ovalcutoutshown" ) {
772 		ovalCutoutShown = paramValue;
773 	} else if ( s1 == "outlineinteractiveitems" ) {
774 		outlineInteractiveItems = paramValue;
775 	} else if ( s1 == "hideinventoriesonmove" ) {
776 		hideInventoriesOnMove = paramValue;
777 	} else if ( s1 == "soundenabled" ) {
778 		soundEnabled = paramValue;
779 	} else if ( s1 == "alwaysshowpath" ) {
780 		alwaysShowPath = paramValue;
781 	} else if ( s1 == "tooltipenabled" ) {
782 		tooltipEnabled = paramValue;
783 	} else if ( s1 == "loglevel" ) {
784 		logLevel = atoi( s2.c_str() );
785 		if ( logLevel < 0 || logLevel > 3 ) {
786 			cerr << "Warning : in file " << CONFIG_FILE //_NAME
787 			<< " invalid loglevel at line " << lineNumber
788 			<< ", valid values are 0, 1, 2 and 3 . Ignoring line" << endl;
789 			logLevel = 3; // Default value
790 		}
791 	} else if ( s1 == "pathfindingquality" ) {
792 		pathFindingQuality = atoi( s2.c_str() );
793 		if ( pathFindingQuality < 0 || pathFindingQuality > 2 ) {
794 			cerr << "Warning : in file " << CONFIG_FILE //_NAME
795 			<< " invalid pathfindingquality at line " << lineNumber
796 			<< ", valid values are 0, 1 and 2 . Ignoring line" << endl;
797 			pathFindingQuality = 0; // Default value
798 		}
799 		maxPathNodes =  pow( 10., pathFindingQuality ) * 500;
800 	} else if ( s1 == "enablescreenshots" ) {
801 		enableScreenshots = paramValue;
802 	} else if ( s1 == "monstertoughness" ) {
803 		monsterToughness = atoi( s2.c_str() );
804 		if ( monsterToughness < 0 ) monsterToughness = 0;
805 		if ( monsterToughness > 2 ) monsterToughness = 2;
806 	} else if ( s1 == "gamespeed" ) {
807 		gamespeed = atoi( s2.c_str() );
808 		if ( gamespeed < 0 || gamespeed > 4 ) {
809 			cerr << "Warning : in file " << CONFIG_FILE //_NAME
810 			<< " invalid gamespeed level at line " << lineNumber
811 			<< ", valid values are 0, 1, 2, 3 and 4 . Ignoring line" << endl;
812 			gamespeed = 1; // Default value
813 		}
814 	}
815 }
816 
817 
getGameSpeedTicks()818 int UserConfiguration::getGameSpeedTicks() {
819 	return gamespeed * 50;
820 }
821 
822 
parseCommandLine(int argc,char * argv[])823 void UserConfiguration::parseCommandLine( int argc, char *argv[] ) {
824 	bool printusage;
825 
826 	printusage = false;
827 
828 
829 	// interpret command line args
830 	for ( int i = 1; i < argc; i++ ) {
831 		if ( strstr( argv[i], "--bpp" ) == argv[i] ) {
832 			bpp = atoi( argv[i] + 5 );
833 			if ( !( bpp == 8 || bpp == 15 || bpp == 16 || bpp == 24 || bpp == 32 ) ) {
834 				printf( "Error: bad bpp=%d\n", bpp );
835 				printusage = true;
836 			}
837 		} else if ( strstr( argv[i], "--width" ) == argv[i] ) {
838 			w = atoi( argv[i] + 7 );
839 			if ( !w ) {
840 				printf( "Error: bad width=%s\n", argv[i] + 7 );
841 				printusage = true;
842 			}
843 		} else if ( strstr( argv[i], "--height" ) == argv[i] ) {
844 			h = atoi( argv[i] + 8 );
845 			if ( !h ) {
846 				printf( "Error: bad height=%s\n", argv[i] + 8 );
847 				printusage = true;
848 			}
849 		} else if ( strstr( argv[i], "--shadow" ) == argv[i] ) {
850 			shadows = atoi( argv[i] + 8 );
851 			if ( !( shadows == 0 || shadows == 1 || shadows == 2 ) ) {
852 				printf( "Error: bad shadow mode: %d\n", shadows );
853 				printusage = true;
854 			}
855 		} else if ( strstr( argv[i], "--theme" ) == argv[i] ) {
856 			strcpy( GuiTheme::DEFAULT_THEME, argv[i] + 7 );
857 			cerr << "Using gui theme: " << GuiTheme::DEFAULT_THEME << endl;
858 		} else if ( !strcmp( argv[i], "--version" ) ) {
859 			printf( "Scourge, version %s\n", SCOURGE_VERSION );
860 			exit( 0 );
861 #ifdef HAVE_SDL_NET
862 		} else if ( !strncmp( argv[i], "--server", 8 ) ) {
863 			standAloneMode = SERVER;
864 			port = atoi( argv[i] + 8 );
865 		} else if ( !strncmp( argv[i], "--client", 8 ) ) {
866 			string s( argv[i] + 8 );
867 			size_t colonPos = s.find( ':' );
868 			host = s.substr( 0, colonPos );
869 			size_t commaPos = s.find( ',', colonPos );
870 			port = atoi( s.substr(colonPos+1, commaPos ).c_str() );
871 			userName = s.substr( commaPos+1 );
872 			standAloneMode = CLIENT;
873 #endif
874 		} else if ( !strcmp( argv[i], "--test" ) ) {
875 			test = true;
876 		} else if ( !strcmp( argv[i], "--nosound" ) ) {
877 			soundEnabled = false;
878 		} else if ( argv[i][0] == '-' && argv[i][1] != '-' ) {
879 			for ( int t = 1; t < static_cast<int>( strlen( argv[i] ) ); t++ ) {
880 				switch ( argv[i][t] ) {
881 				case 'h':
882 				case '?': printusage = true; break;
883 				case 'f': fullscreen = false; break;
884 				case 'd': doublebuf = false; break;
885 				case 'p': hwpal = false; break;
886 				case 'r': resizeable = false; break;
887 				case 'H': force_hwsurf = true; break;
888 				case 'S': force_swsurf = true; break;
889 				case 'a': hwaccel = false; break;
890 				case 's': stencilbuf = false; break;
891 				case 'm': Constants::multitexture = false; break;
892 				}
893 			}
894 		} else if ( !strcmp( argv[i], "--flaky" ) ) {
895 			// disable some gfx effects for flaky GPU-s
896 			flaky = true;
897 		} else if ( !strcmp( argv[i], "--run-tests" ) ) {
898 			// this is ok
899 			standAloneMode = TEST;
900 		} else if ( !strcmp( argv[ i ], "--debugtheme" ) ) {
901 			debugTheme = true;
902 		} else {
903 			printusage = true;
904 		}
905 	}
906 
907 	if ( printusage ) {
908 		printf( _( "S.C.O.U.R.G.E.: Heroes of Lesser Renown\n" ) );
909 		printf( _( "A 3D, roguelike game of not quite epic proportions.\n\n" ) );
910 		printf( _( "Usage:\n" ) );
911 		printf( _( "scourge [-fdprHSa?hsm] [--test] [--bppXX] [--help] [--version] [--shadowX]\n" ) );
912 		printf( _( "version: %s\n" ), SCOURGE_VERSION );
913 #ifdef HAVE_SDL_NET
914 		printf( _( "[Multiplayer support]\n" ) );
915 #endif
916 #ifdef HAVE_SDL_MIXER
917 		printf( _( "[Sound support]\n" ) );
918 #endif
919 		printf( _( "\nOptions:\n" ) );
920 		printf( _( "\tf - disable fullscreen mode\n" ) );
921 		printf( _( "\td - disable double buffering\n" ) );
922 		printf( _( "\tp - disable hardware palette\n" ) );
923 		printf( _( "\tr - disable resizable window\n" ) );
924 		printf( _( "\tH - force hardware surface\n" ) );
925 		printf( _( "\tS - force software surface\n" ) );
926 		printf( _( "\ta - disable hardware acceleration\n" ) );
927 		printf( _( "\th,?,--help - show this info\n" ) );
928 		printf( _( "\ts - disable stencil buffer\n" ) );
929 		printf( _( "\tm - disable multitexturing\n" ) );
930 		printf( _( "\t--test - list card's supported video modes\n" ) );
931 		printf( _( "\t--test-config - print out the file configuration and exit\n" ) );
932 		printf( _( "\t--run-tests [path] - run internal tests of the rpg engine and save the result in html"
933 		           " in the $path dir\n" )
934 		      );
935 		printf( _( "\t--version - print the build version\n" ) );
936 		printf( _( "\t--bppXX - use XX bits per pixel (8,15,16,24,32)\n" ) );
937 		printf( _( "\t--widthXX - use XX pixels for the screen width\n" ) );
938 		printf( _( "\t--heightXX - use XX pixels for the screen height\n" ) );
939 		printf( _( "\t--shadowX - shadow's cast by: 0-nothing, 1-objects and creatures, 2-everything\n" ) );
940 		printf( _( "\t--themeXYZ - use gui theme XYZ to draw the ui.\n" ) );
941 		printf( _( "\t--debugtheme - use the debug theme only to for wall textures.\n" ) );
942 		printf( _( "\t--flaky - disable some graphic effects for flaky video cards.\n" ) );
943 		printf( _( "\nBy default (with no options):\n\tbpp is the highest possible value\n\t"
944 		           "fullscreen mode is on\n\tdouble buffering is on\n\thwpal is used if available\n\t"
945 		           "resizeable is on (no effect in fullscreen mode)\n\thardware surface is used if available\n\t"
946 		           "hardware acceleration is used if available\n\tstencil buffer is used if available\n\t"
947 		           "multitexturing is used if available\n\tshadows are cast by everything.\n\n" )
948 		      );
949 #ifdef HAVE_SDL_NET
950 		printf( _( "Multiplayer options:\n" ) );
951 		printf( _( "\t--serverPORT - run a standalone server w/o a ui on PORT\n" ) );
952 		printf( _( "\t--clientHOST:PORT,USERNAME - run a standalone admin client w/o a ui."
953 		           " Connect to server HOST:PORT as USERNAME.\n" )
954 		      );
955 #endif
956 #ifdef HAVE_SDL_MIXER
957 		printf( _( "Sound options:\n" ) );
958 		printf( _( "\t--nosound - run without sound\n" ) );
959 #endif
960 		exit( 0 );
961 	}
962 }
963 
964 
writeFile(ofstream * fileOut,char * text)965 void UserConfiguration::writeFile( ofstream *fileOut, char *text ) {
966 	string s;
967 	s = text;
968 	fileOut->write( s.c_str(), s.length() );
969 }
970 
971 // returns the action to do for this event
getEngineAction(SDL_Event * event)972 int UserConfiguration::getEngineAction( SDL_Event *event ) {
973 	string s;
974 	int res;
975 
976 	if ( !s.empty() ) s.clear();
977 	res = -1;
978 	if ( event->type == SDL_KEYDOWN ) {
979 		s = SDL_GetKeyName( event->key.keysym.sym );
980 		//replaceSpaces(s);
981 		if ( keyDownBindings.find( s ) != keyDownBindings.end() ) {
982 			res = keyDownBindings[s];
983 		}
984 	} else if ( event->type == SDL_KEYUP ) {
985 		s = SDL_GetKeyName( event->key.keysym.sym );
986 		//replaceSpaces(s);
987 		if ( keyUpBindings.find( s ) != keyUpBindings.end() ) {
988 			res = keyUpBindings[s];
989 		}
990 	} else if ( event->type == SDL_MOUSEBUTTONDOWN ) {
991 		if ( mouseDownBindings.find( event->button.button ) != mouseDownBindings.end() ) {
992 			res = mouseDownBindings[event->button.button];
993 		}
994 	} else if ( event->type == SDL_MOUSEBUTTONUP ) {
995 		if ( mouseUpBindings.find( event->button.button ) != mouseUpBindings.end() ) {
996 			res = mouseUpBindings[event->button.button];
997 		}
998 	}
999 
1000 	if ( DEBUG_USER_CONFIG ) {
1001 		cout << "engine action returned : " << res << endl;
1002 	}
1003 	return res;
1004 
1005 
1006 	/* case SDL_MOUSEBUTTONUP:
1007 	   if(event->button.button) {
1008 	       int region = gui->testActiveRegions(event->button.x, event->button.y);
1009 	       if(region == Constants::SHOW_BACKPACK) {
1010 	           backpack->show();
1011 	       } else if(region == Constants::SHOW_OPTIONS) {
1012 	           // do something
1013 	       } else if(region == Constants::ESCAPE) {
1014 	           return true;
1015 	 } else if(region >= Constants::DIAMOND_FORMATION && region <= Constants::CROSS_FORMATION) {
1016 	   setFormation(region - Constants::DIAMOND_FORMATION);
1017 	 } else if(region >= Constants::PLAYER_1 && region <= Constants::PLAYER_4) {
1018 	   setPlayer(region - Constants::PLAYER_1);
1019 	 } else if(region == Constants::PLAYER_ONLY) {
1020 	   player_only = (player_only ? false : true);
1021 	       } else {
1022 	           processGameMouseClick(event->button.x, event->button.y, event->button.button);
1023 	       }
1024 	   }
1025 	   break;*/
1026 
1027 }
1028 
1029 
getEngineActionDescription(int i)1030 const char * UserConfiguration::getEngineActionDescription( int i ) {
1031 	if ( ! ( i < 0 || i > ENGINE_ACTION_COUNT ) ) {
1032 		return _( ENGINE_ACTION_DESCRIPTION[i] );
1033 	} else {
1034 		return "";
1035 	}
1036 }
1037 
1038 
getEngineActionKeyName(int i)1039 const char * UserConfiguration::getEngineActionKeyName( int i ) {
1040 	if ( keyForEngineAction.find( i ) != keyForEngineAction.end() ) {
1041 		return ( keyForEngineAction[i].c_str() );
1042 	} else {
1043 		return "";
1044 	}
1045 }
1046 
1047 // Returns next word from the given position. If there is not a space at the given
1048 // position, the function suppose it is the first letter of the word wanted.
getNextWord(const string theInput,int fromPos,int & endWord)1049 string UserConfiguration::getNextWord( const string theInput, int fromPos, int &endWord ) {
1050 	int firstChar, lastStringChar;
1051 	string sub;
1052 	if ( !sub.empty() ) sub.clear();
1053 
1054 	if ( theInput.empty() || fromPos == -1 ) {
1055 		return sub;
1056 	}
1057 
1058 	lastStringChar = theInput.find_last_not_of( ' ' );
1059 	if ( theInput[fromPos] == ' ' ) {
1060 		firstChar = theInput.find_first_not_of( ' ', fromPos );
1061 	} else {
1062 		firstChar = fromPos;
1063 	}
1064 	endWord = theInput.find_first_of( ' ', firstChar );
1065 	// cout << "line :" << theInput << endl;
1066 	// cout << "\t\tpos = " << fromPos << " firstChar = " << firstChar << " endWord = " << endWord << " lastStringChar =" << lastStringChar << endl;
1067 	if ( endWord == -1 ) {
1068 		if ( ( lastStringChar >= firstChar ) && ( firstChar != -1 ) ) {
1069 			sub = theInput.substr( firstChar, lastStringChar - firstChar + 1 );
1070 		}
1071 	} else {
1072 		sub = theInput.substr( firstChar, endWord - firstChar );
1073 	}
1074 	return sub;
1075 
1076 }
1077 
replaceSpaces(string & s)1078 void UserConfiguration::replaceSpaces( string& s ) {
1079 	s.replace( s.begin(), s.end(), ' ', '_' );
1080 }
1081 
~UserConfiguration()1082 UserConfiguration::~UserConfiguration() {
1083 
1084 }
1085 
createConfigDir()1086 void UserConfiguration::createConfigDir() {
1087 #ifndef WIN32
1088 	// first create the directory
1089 	// no need on windows, this file is saved in the current dir
1090 	string path = get_config_dir_name();
1091 	FILE *fp = fopen( path.c_str(), "r" );
1092 	if ( !fp ) {
1093 		int err = mkdir( path.c_str(), S_IRWXU | S_IRGRP | S_IXGRP );
1094 		if ( err ) {
1095 			cerr << "Error creating config directory: " << path << endl;
1096 			cerr << "Error: " << err << endl;
1097 			perror( "UserConfiguration::createDefaultConfigFile: " );
1098 			exit( 1 );
1099 		}
1100 	} else {
1101 		fclose( fp );
1102 	}
1103 #endif
1104 }
1105 
createDefaultConfigFile()1106 void UserConfiguration::createDefaultConfigFile() {
1107 	createConfigDir();
1108 
1109 	// now create the file
1110 	string path = get_config_file_name();
1111 	ofstream configFile ( path.c_str() );
1112 	if ( !configFile.is_open() ) {
1113 		cerr << "Can't open configuration file: " << path << endl;
1114 		exit( 1 );
1115 	}
1116 
1117 	configFile << "Generated by Scourge version " << SCOURGE_VERSION << endl;
1118 	configFile << "Modify at your own risks." << endl;
1119 	configFile << "-------------------------------------------------" << endl;
1120 	configFile << "- A line not beginning with BIND or SET is ignored (spaces excepted)" << endl;
1121 	configFile << "- Only one instruction per line will be processed" << endl;
1122 	configFile << "- No upper/lower case distinction" << endl;
1123 	configFile << "- A space is a parameter separator so replace spaces by '_' if needed in your parameters." << endl;
1124 	configFile << "    Example : for 'left bracket' put 'left_bracket'" << endl;
1125 	configFile << "- No specific order needed between BIND/SET commands" << endl;
1126 	configFile << "" << endl;
1127 	configFile << "Syntax : " << endl;
1128 	configFile << "- BIND  sdl_key_name  engineAction" << endl;
1129 	configFile << "- SET   variable   value" << endl;
1130 	configFile << "without the '-' at the beginning" << endl;
1131 	configFile << "sdl_key_names are defined in SDL.h" << endl;
1132 	configFile << "engineActions and variables are defined in userconfiguration.h" << endl;
1133 	configFile << "-------------------------------------------------" << endl;
1134 	configFile << "" << endl;
1135 	configFile << "version " << SCOURGE_VERSION << endl;
1136 	configFile << "" << endl;
1137 	configFile << "// Bindings" << endl;
1138 	configFile << "bind down set_move_down" << endl;
1139 	configFile << "bind right set_move_right" << endl;
1140 	configFile << "bind up set_move_up" << endl;
1141 	configFile << "bind left set_move_left" << endl;
1142 	configFile << "bind 1 set_player_0" << endl;
1143 	configFile << "bind 2 set_player_1" << endl;
1144 	configFile << "bind 3 set_player_2" << endl;
1145 	configFile << "bind 4 set_player_3" << endl;
1146 	configFile << "bind 0 set_player_only" << endl;
1147 	configFile << "bind i show_backpack" << endl;
1148 	configFile << "bind o show_options_menu" << endl;
1149 	configFile << "bind u use_item" << endl;
1150 	configFile << "bind f set_next_formation" << endl;
1151 	configFile << "bind [+] toggle_minimap" << endl;
1152 	configFile << "bind 8 set_zoom_in" << endl;
1153 	configFile << "bind 9 set_zoom_out" << endl;
1154 	configFile << "bind m toggle_map_center" << endl;
1155 	configFile << "bind k increase_game_speed" << endl;
1156 	configFile << "bind l decrease_game_speed" << endl;
1157 	configFile << "bind space start_round" << endl;
1158 	configFile << "bind g layout_1" << endl;
1159 	configFile << "bind h layout_2" << endl;
1160 	configFile << "bind j layout_4" << endl;
1161 	configFile << "bind c switch_combat" << endl;
1162 	configFile << "bind ] next_weapon" << endl;
1163 	configFile << "bind f1 quick_spell_1" << endl;
1164 	configFile << "bind f2 quick_spell_2" << endl;
1165 	configFile << "bind f3 quick_spell_3" << endl;
1166 	configFile << "bind f4 quick_spell_4" << endl;
1167 	configFile << "bind f5 quick_spell_5" << endl;
1168 	configFile << "bind f6 quick_spell_6" << endl;
1169 	configFile << "bind f7 quick_spell_7" << endl;
1170 	configFile << "bind f8 quick_spell_8" << endl;
1171 	configFile << "bind f9 quick_spell_9" << endl;
1172 	configFile << "bind f10 quick_spell_10" << endl;
1173 	configFile << "bind f11 quick_spell_11" << endl;
1174 	configFile << "bind f12 quick_spell_12" << endl;
1175 	configFile << "bind q quick_save" << endl;
1176 	configFile << "bind w quick_load" << endl;
1177 	configFile << "bind a auto_load" << endl;
1178 	configFile << "" << endl;
1179 	configFile << "// Video settings" << endl;
1180 	configFile << "set fullscreen true" << endl;
1181 	configFile << "set doublebuf true" << endl;
1182 	configFile << "set stencilbuf true" << endl;
1183 	configFile << "set hwpal true" << endl;
1184 	configFile << "set resizeable false" << endl;
1185 	configFile << "set force_hwsurf true" << endl;
1186 	configFile << "set force_swsurf false" << endl;
1187 	configFile << "set multitexturing true" << endl;
1188 	configFile << "set hwaccel true" << endl;
1189 	configFile << "set shadows 2  // 0 : no shadows, 2 : best shadows" << endl;
1190 	configFile << "set w 1024" << endl;
1191 	configFile << "set h 768" << endl;
1192 	configFile << "set bpp 32" << endl;
1193 	configFile << "set enablescreenshots true" << endl;
1194 	configFile << "set aniso_filter false" << endl;
1195 	configFile << "" << endl;
1196 	configFile << "// Game settings" << endl;
1197 	configFile << "set gamespeed 2  // 0 : fastest, 4 : slowest" << endl;
1198 	configFile << "set monstertoughness 0  // 0 : easy, 2 : toughest" << endl;
1199 	configFile << "set centermap false" << endl;
1200 	configFile << "set keepmapsize true" << endl;
1201 	configFile << "set frameonfullscreen true" << endl;
1202 	configFile << "set turnbasedbattle true" << endl;
1203 	configFile << "set ovalcutoutshown true" << endl;
1204 	configFile << "set outlineinteractiveitems true" << endl;
1205 	configFile << "set hideinventoriesonmove true" << endl;
1206 	configFile << "set combatinfodetail 0" << endl;
1207 	configFile << "set alwaysshowpath false" << endl;
1208 	configFile << "set tooltipenabled true" << endl;
1209 	configFile << "set tooltipinterval 50" << endl;
1210 	configFile << "set loglevel 3" << endl;
1211 	configFile << "set pathfindingquality 0" << endl;
1212 	configFile << "" << endl;
1213 	configFile << "// Audio settings" << endl;
1214 	configFile << "set soundenabled true" << endl;
1215 	configFile << "set musicvolume 64 // 0-silent, 128-loudest" << endl;
1216 	configFile << "set effectsvolume 128 // 0-silent, 128-loudest" << endl;
1217 	configFile << "set soundfreq 5  // 0: most frequent, 10: least frequent" << endl;
1218 	configFile << "" << endl;
1219 
1220 	configFile.close();
1221 }
1222