DEADSOFTWARE

86761de063a688abc621149e2b2adc531c906755
[d2df-sdl.git] / src / game / g_options.pas
1 (* Copyright (C) Doom 2D: Forever Developers
2 *
3 * This program is free software: you can redistribute it and/or modify
4 * it under the terms of the GNU General Public License as published by
5 * the Free Software Foundation, either version 3 of the License, or
6 * (at your option) any later version.
7 *
8 * This program is distributed in the hope that it will be useful,
9 * but WITHOUT ANY WARRANTY; without even the implied warranty of
10 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
11 * GNU General Public License for more details.
12 *
13 * You should have received a copy of the GNU General Public License
14 * along with this program. If not, see <http://www.gnu.org/licenses/>.
15 *)
16 {$INCLUDE ../shared/a_modes.inc}
17 unit g_options;
19 interface
21 uses
22 g_language, g_weapons;
24 type
25 TPlayerControl = record
26 KeyRight: Word;
27 KeyLeft: Word;
28 KeyUp: Word;
29 KeyDown: Word;
30 KeyFire: Word;
31 KeyJump: Word;
32 KeyNextWeapon: Word;
33 KeyPrevWeapon: Word;
34 KeyOpen: Word;
35 KeyStrafe: Word;
36 KeyWeapon: array [WP_FIRST..WP_LAST] of Word;
38 KeyRight2: Word;
39 KeyLeft2: Word;
40 KeyUp2: Word;
41 KeyDown2: Word;
42 KeyFire2: Word;
43 KeyJump2: Word;
44 KeyNextWeapon2: Word;
45 KeyPrevWeapon2: Word;
46 KeyOpen2: Word;
47 KeyStrafe2: Word;
48 KeyWeapon2: array [WP_FIRST..WP_LAST] of Word;
49 end;
51 TGameControls = record
52 TakeScreenshot: Word;
53 Stat: Word;
54 Chat: Word;
55 TeamChat: Word;
56 end;
58 TControls = record
59 GameControls: TGameControls;
60 P1Control: TPlayerControl;
61 P2Control: TPlayerControl;
62 end;
64 procedure g_Options_SetDefault();
65 procedure g_Options_Read(FileName: String);
66 procedure g_Options_Write(FileName: String);
67 procedure g_Options_Write_Language(FileName: String);
68 procedure g_Options_Write_Video(FileName: String);
69 procedure g_Options_Write_Gameplay_Custom(FileName: String);
70 procedure g_Options_Write_Gameplay_Net(FileName: String);
71 procedure g_Options_Write_Net_Server(FileName: String);
72 procedure g_Options_Write_Net_Client(FileName: String);
74 const DF_Default_Megawad_Start = 'megawads/DOOM2D.WAD:\MAP01';
76 var
77 gGameControls: TControls;
78 gScreenWidth: Word;
79 gScreenHeight: Word;
80 gWinRealPosX: Integer;
81 gWinRealPosY: Integer;
82 gBPP: Byte;
83 gFreq: Byte;
84 gFullscreen: Boolean;
85 gWinMaximized: Boolean;
86 gVSync: Boolean;
87 glLegacyNPOT: Boolean;
88 gTextureFilter: Boolean;
89 gNoSound: Boolean;
90 gSoundLevel: Byte;
91 gMusicLevel: Byte;
92 gMaxSimSounds: Byte;
93 gMuteWhenInactive: Boolean;
94 gAdvCorpses: Boolean;
95 gAdvBlood: Boolean;
96 gAdvGibs: Boolean;
97 gGibsCount: Integer;
98 gBloodCount: Byte;
99 gFlash: Byte;
100 gDrawBackGround: Boolean;
101 gShowMessages: Boolean;
102 gRevertPlayers: Boolean;
103 gLanguage: String;
104 gAskLanguage: Boolean;
105 gcMap: String;
106 gcGameMode: String;
107 gcTimeLimit: Word;
108 gcGoalLimit: Word;
109 gcMaxLives: Byte;
110 gcPlayers: Byte;
111 gcTeamDamage: Boolean;
112 gcAllowExit: Boolean;
113 gcWeaponStay: Boolean;
114 gcMonsters: Boolean;
115 gcBotsVS: String;
116 gnMap: String;
117 gnGameMode: String;
118 gnTimeLimit: Word;
119 gnGoalLimit: Word;
120 gnMaxLives: Byte;
121 gnPlayers: Byte;
122 gnTeamDamage: Boolean;
123 gnAllowExit: Boolean;
124 gnWeaponStay: Boolean;
125 gnMonsters: Boolean;
126 gnBotsVS: String;
127 gsSDLSampleRate: Integer;
128 gsSDLBufferSize: Integer;
129 gSFSDebug: Boolean;
130 gSFSFastMode: Boolean;
131 gDefaultMegawadStart: AnsiString;
132 gBerserkAutoswitch: Boolean;
134 implementation
136 uses
137 {$INCLUDE ../nogl/noGLuses.inc}
138 e_log, e_input, g_window, g_sound, g_gfx, g_player, Math,
139 g_map, g_net, g_netmaster, SysUtils, CONFIG, g_game, g_main, e_texture,
140 g_items, wadreader, e_graphics, g_touch, SDL2;
142 procedure g_Options_SetDefaultVideo;
143 var
144 target, closest, display: TSDL_DisplayMode;
145 percentage: Integer;
146 begin
147 (* Display 0 = Primary display *)
148 SDL_GetDesktopDisplayMode(0, @display);
149 {$IF DEFINED(ANDROID)}
150 gScreenWidth := display.w;
151 gScreenHeight := display.h;
152 //gBPP := SDL_BITSPERPIXEL(dispaly.format);
153 gBPP := 32;
154 gFullScreen := True; (* rotation not allowed? *)
155 {$ELSE}
156 (* Window must be smaller than display *)
157 closest.w := display.w;
158 closest.h := display.h;
159 percentage := 75;
160 while (display.w - closest.w < 48) or (display.h - closest.h < 48) do
161 begin
162 if percentage < 25 then
163 begin
164 closest.w := display.w * 75 div 100;
165 closest.h := display.h * 75 div 100;
166 break;
167 end;
168 target.w := display.w * percentage div 100;
169 target.h := display.h * percentage div 100;
170 target.format := 0; (* didn't care *)
171 target.refresh_rate := 0; (* didn't care *)
172 target.driverdata := nil; (* init *)
173 SDL_GetClosestDisplayMode(0, @target, @closest);
174 Dec(percentage);
175 end;
176 gScreenWidth := closest.w;
177 gScreenHeight := closest.h;
178 //gBPP := SDL_BITSPERPIXEL(closest.format); (* Resolution list didn't work for some reason *)
179 gBPP := 32;
180 gFullScreen := False;
181 {$ENDIF}
182 (* Must be positioned on primary display *)
183 gWinRealPosX := SDL_WINDOWPOS_CENTERED;
184 gWinRealPosY := SDL_WINDOWPOS_CENTERED;
185 gWinMaximized := False;
186 gVSync := True;
187 gTextureFilter := True;
188 glLegacyNPOT := False;
189 e_LogWriteLn('g_Options_SetDefaultVideo: w = ' + IntToStr(gScreenWidth) + ' h = ' + IntToStr(gScreenHeight));
190 end;
192 procedure g_Options_SetDefault();
193 var
194 i: Integer;
195 begin
196 (* section Sound *)
197 gNoSound := False;
198 gSoundLevel := 75;
199 gMusicLevel := 65;
200 gMaxSimSounds := 8;
201 gMuteWhenInactive := False;
202 gAnnouncer := ANNOUNCE_MEPLUS;
203 gSoundEffectsDF := True;
204 gUseChatSounds := True;
205 gsSDLSampleRate := 44100;
206 gsSDLBufferSize := 2048;
208 g_Sound_SetupAllVolumes(gSoundLevel, gMusicLevel);
210 (* section GameControls *)
211 with gGameControls.GameControls do
212 begin
213 TakeScreenshot := SDL_SCANCODE_F12;
214 Stat := SDL_SCANCODE_TAB;
215 Chat := SDL_SCANCODE_T;
216 TeamChat := SDL_SCANCODE_Y;
217 end;
219 (* section Player1 *)
220 with gGameControls.P1Control do
221 begin
222 KeyRight := SDL_SCANCODE_KP_6;
223 KeyLeft := SDL_SCANCODE_KP_4;
224 KeyUp := SDL_SCANCODE_KP_8;
225 KeyDown := SDL_SCANCODE_KP_5;
226 KeyFire := SDL_SCANCODE_SLASH;
227 KeyJump := SDL_SCANCODE_RCTRL;
228 KeyNextWeapon := SDL_SCANCODE_KP_9;
229 KeyPrevWeapon := SDL_SCANCODE_KP_7;
230 KeyOpen := SDL_SCANCODE_RSHIFT;
231 KeyStrafe := SDL_SCANCODE_PERIOD;
233 for i := 0 to 9 do
234 begin
235 KeyWeapon[i] := SDL_SCANCODE_1 + i (* 1, ..., 9, 0 *)
236 end;
237 KeyWeapon[10] := SDL_SCANCODE_MINUS;
238 for i := 11 to High(KeyWeapon) do
239 begin
240 KeyWeapon[i] := 0
241 end;
243 KeyRight2 := VK_RIGHT;
244 KeyLeft2 := VK_LEFT;
245 KeyUp2 := VK_UP;
246 KeyDown2 := VK_DOWN;
247 KeyFire2 := VK_FIRE;
248 KeyJump2 := VK_JUMP;
249 KeyNextWeapon2 := VK_NEXT;
250 KeyPrevWeapon2 := VK_PREV;
251 KeyOpen2 := VK_OPEN;
252 KeyStrafe2 := VK_STRAFE;
254 for i := 0 to High(KeyWeapon2) do
255 begin
256 KeyWeapon2[i] := VK_0 + i
257 end;
258 end;
260 with gPlayer1Settings do
261 begin
262 Name := 'Player1';
263 Model := STD_PLAYER_MODEL;
264 Color.R := PLAYER1_DEF_COLOR.R;
265 Color.G := PLAYER1_DEF_COLOR.G;
266 Color.B := PLAYER1_DEF_COLOR.B;
267 Team := TEAM_RED;
268 end;
270 (* section Player2 *)
271 with gGameControls.P2Control do
272 begin
273 KeyRight := SDL_SCANCODE_D;
274 KeyLeft := SDL_SCANCODE_A;
275 KeyUp := SDL_SCANCODE_W;
276 KeyDown := SDL_SCANCODE_S;
277 KeyFire := SDL_SCANCODE_G;
278 KeyJump := SDL_SCANCODE_SPACE;
279 KeyNextWeapon := SDL_SCANCODE_E;
280 KeyPrevWeapon := SDL_SCANCODE_Q;
281 KeyOpen := SDL_SCANCODE_F;
282 KeyStrafe := SDL_SCANCODE_LSHIFT;
283 for i := 0 to High(KeyWeapon) do
284 begin
285 KeyWeapon[i] := 0
286 end;
288 KeyRight2 := 0;
289 KeyLeft2 := 0;
290 KeyUp2 := 0;
291 KeyDown2 := 0;
292 KeyFire2 := 0;
293 KeyJump2 := 0;
294 KeyNextWeapon2 := 0;
295 KeyPrevWeapon2 := 0;
296 KeyOpen2 := 0;
297 KeyStrafe2 := 0;
299 for i := 0 to High(KeyWeapon2) do
300 begin
301 KeyWeapon2[i] := 0;
302 end
303 end;
305 with gPlayer2Settings do
306 begin
307 Name := 'Player2';
308 Model := STD_PLAYER_MODEL;
309 Color.R := PLAYER2_DEF_COLOR.R;
310 Color.G := PLAYER2_DEF_COLOR.G;
311 Color.B := PLAYER2_DEF_COLOR.B;
312 Team := TEAM_BLUE;
313 end;
315 (* section Joysticks *)
316 for i := 0 to e_MaxJoys - 1 do
317 begin
318 e_JoystickDeadzones[i] := 8192
319 end;
321 (* section Touch *)
322 g_touch_size := 1.0;
323 g_touch_fire := True;
324 g_touch_offset := 50;
325 g_touch_alt := False;
327 (* section Game *)
328 g_GFX_SetMax(2000);
329 g_Shells_SetMax(300);
330 g_Gibs_SetMax(150);
331 g_Corpses_SetMax(20);
332 gGibsCount := 32;
333 ITEM_RESPAWNTIME := 60 * 36;
334 gBloodCount := 4;
335 gAdvBlood := True;
336 gAdvCorpses := True;
337 gAdvGibs := True;
338 gFlash := 1;
339 gDrawBackGround := True;
340 gShowMessages := True;
341 gRevertPlayers := False;
342 gChatBubble := 4;
343 gSFSDebug := False;
344 gSFSFastMode := False;
345 e_FastScreenshots := True;
346 gDefaultMegawadStart := DF_Default_Megawad_Start;
347 gBerserkAutoswitch := True;
348 g_dbg_scale := 1.0;
350 gAskLanguage := True;
351 gLanguage := LANGUAGE_ENGLISH;
353 (* section GameplayCustom *)
354 gcMap := '';
355 gcGameMode := _lc[I_MENU_GAME_TYPE_DM];
356 gcTimeLimit := 0;
357 gcGoalLimit := 0;
358 gcMaxLives := 0;
359 gcPlayers := 1;
360 gcTeamDamage := False;
361 gcAllowExit := True;
362 gcWeaponStay := False;
363 gcMonsters := False;
364 gcBotsVS := 'Everybody';
366 (* section GameplayNetwork *)
367 gnMap := '';
368 gnGameMode := _lc[I_MENU_GAME_TYPE_DM];
369 gnTimeLimit := 0;
370 gnGoalLimit := 0;
371 gnMaxLives := 0;
372 gnPlayers := 1;
373 gnTeamDamage := False;
374 gnAllowExit := True;
375 gnWeaponStay := False;
376 gnMonsters := False;
377 gnBotsVS := 'Everybody';
379 (* section MasterServer *)
380 NetSlistIP := 'mpms.doom2d.org';
381 NetSlistPort := 25665;
382 g_Net_Slist_Set(NetSlistIP, NetSlistPort);
384 (* section Server *)
385 NetServerName := 'Unnamed Server';
386 NetPassword := '';
387 NetPort := 25666;
388 NetMaxClients := 16;
389 NetAllowRCON := False;
390 NetRCONPassword := 'default';
391 NetUseMaster := True;
392 NetUpdateRate := 0;
393 NetRelupdRate := 18;
394 NetMasterRate := 60000;
395 NetForwardPorts := False;
397 (* section Client *)
398 NetInterpLevel := 2;
399 NetForcePlayerUpdate := False;
400 NetPredictSelf := True;
401 NetClientIP := '127.0.0.1';
402 NetClientPort := NetPort;
403 end;
405 procedure g_Options_Read(FileName: String);
406 var
407 i: Integer;
408 config: TConfig;
409 section: String;
411 procedure ReadInteger (VAR v: Integer; param: String; minv: Integer = Low(Integer); maxv: Integer = High(Integer));
412 begin
413 v := Max(Min(config.ReadInt(section, param, v), maxv), minv)
414 end;
416 procedure ReadInteger (VAR v: LongWord; param: String; minv: LongWord = Low(LongWord); maxv: LongWord = High(LongWord)); overload;
417 begin
418 v := Max(Min(config.ReadInt(section, param, v), maxv), minv)
419 end;
421 procedure ReadInteger (VAR v: Word; param: String; minv: Word = Low(Word); maxv: Word = High(Word)); overload;
422 begin
423 v := Max(Min(config.ReadInt(section, param, v), maxv), minv)
424 end;
426 procedure ReadInteger (VAR v: Byte; param: String; minv: Byte = Low(Byte); maxv: Byte = High(Byte)); overload;
427 begin
428 v := Max(Min(config.ReadInt(section, param, v), maxv), minv)
429 end;
431 procedure ReadBoolean (VAR v: Boolean; param: String);
432 begin
433 v := config.ReadBool(section, param, v)
434 end;
436 procedure ReadString (VAR v: String; param: String);
437 begin
438 v := config.ReadStr(section, param, v)
439 end;
441 begin
442 gAskLanguage := True;
443 e_WriteLog('Reading config', TMsgType.Notify);
444 g_Options_SetDefault;
446 if FileExists(FileName) = False then
447 begin
448 e_WriteLog('Config file '+FileName+' not found', TMsgType.Warning);
449 g_Options_SetDefaultVideo;
450 Exit
451 end;
453 config := TConfig.CreateFile(FileName);
455 section := 'Video';
456 ReadInteger(gScreenWidth, 'ScreenWidth', 0);
457 ReadInteger(gScreenHeight, 'ScreenHeight', 0);
458 ReadInteger(gWinRealPosX, 'WinPosX', 60);
459 ReadInteger(gWinRealPosY, 'WinPosY', 60);
460 ReadBoolean(gFullScreen, 'Fullscreen');
461 ReadBoolean(gWinMaximized, 'Maximized');
462 ReadInteger(gBPP, 'BPP', 0);
463 ReadInteger(gFreq, 'Freq', 0);
464 ReadBoolean(gVSync, 'VSync');
465 ReadBoolean(gTextureFilter, 'TextureFilter');
466 ReadBoolean(glLegacyNPOT, 'LegacyCompatible');
468 section := 'Sound';
469 ReadBoolean(gNoSound, 'NoSound');
470 ReadInteger(gSoundLevel, 'SoundLevel', 0, 255);
471 ReadInteger(gMusicLevel, 'MusicLevel', 0, 255);
472 ReadInteger(gMaxSimSounds, 'MaxSimSounds', 2, 66);
473 ReadBoolean(gMuteWhenInactive, 'MuteInactive');
474 ReadInteger(gAnnouncer, 'Announcer', ANNOUNCE_NONE, ANNOUNCE_ALL);
475 ReadBoolean(gSoundEffectsDF, 'SoundEffectsDF');
476 ReadBoolean(gUseChatSounds, 'ChatSounds');
477 ReadInteger(gsSDLSampleRate, 'SDLSampleRate', 11025, 96000);
478 ReadInteger(gsSDLBufferSize, 'SDLBufferSize', 64, 16384);
480 section := 'GameControls';
481 with gGameControls.GameControls do
482 begin
483 ReadInteger(TakeScreenshot, 'TakeScreenshot');
484 ReadInteger(Stat, 'Stat');
485 ReadInteger(Chat, 'Chat');
486 ReadInteger(TeamChat, 'TeamChat');
487 end;
489 section := 'Player1';
490 with gGameControls.P1Control do
491 begin
492 ReadInteger(KeyRight, 'KeyRight');
493 ReadInteger(KeyLeft, 'KeyLeft');
494 ReadInteger(KeyUp, 'KeyUp');
495 ReadInteger(KeyDown, 'KeyDown');
496 ReadInteger(KeyFire, 'KeyFire');
497 ReadInteger(KeyJump, 'KeyJump');
498 ReadInteger(KeyNextWeapon, 'KeyNextWeapon');
499 ReadInteger(KeyPrevWeapon, 'KeyPrevWeapon');
500 ReadInteger(KeyOpen, 'KeyOpen');
501 ReadInteger(KeyStrafe, 'KeyStrafe');
503 for i := 0 to High(KeyWeapon) do
504 begin
505 ReadInteger(KeyWeapon[i], 'KeyWeapon' + IntToStr(i))
506 end;
508 ReadInteger(KeyRight2, 'KeyRight2');
509 ReadInteger(KeyLeft2, 'KeyLeft2');
510 ReadInteger(KeyUp2, 'KeyUp2');
511 ReadInteger(KeyDown2, 'KeyDown2');
512 ReadInteger(KeyFire2, 'KeyFire2');
513 ReadInteger(KeyJump2, 'KeyJump2');
514 ReadInteger(KeyNextWeapon2, 'KeyNextWeapon2');
515 ReadInteger(KeyPrevWeapon2, 'KeyPrevWeapon2');
516 ReadInteger(KeyOpen2, 'KeyOpen2');
517 ReadInteger(KeyStrafe2, 'KeyStrafe2');
519 for i := 0 to High(KeyWeapon2) do
520 begin
521 ReadInteger(KeyWeapon2[i], 'KeyWeapon2' + IntToStr(i))
522 end;
523 end;
525 section := 'Player1';
526 with gPlayer1Settings do
527 begin
528 ReadString(Name, 'name');
529 ReadString(Model, 'model');
530 ReadInteger(Color.R, 'red', 0, 255);
531 ReadInteger(Color.G, 'green', 0, 255);
532 ReadInteger(Color.B, 'blue', 0, 255);
533 ReadInteger(Team, 'team');
534 if (Team < TEAM_RED) or (Team > TEAM_BLUE) then
535 Team := TEAM_RED;
536 end;
538 section := 'Player2';
539 with gGameControls.P2Control do
540 begin
541 ReadInteger(KeyRight, 'KeyRight');
542 ReadInteger(KeyLeft, 'KeyLeft');
543 ReadInteger(KeyUp, 'KeyUp');
544 ReadInteger(KeyDown, 'KeyDown');
545 ReadInteger(KeyFire, 'KeyFire');
546 ReadInteger(KeyJump, 'KeyJump');
547 ReadInteger(KeyNextWeapon, 'KeyNextWeapon');
548 ReadInteger(KeyPrevWeapon, 'KeyPrevWeapon');
549 ReadInteger(KeyOpen, 'KeyOpen');
550 ReadInteger(KeyStrafe, 'KeyStrafe');
552 for i := 0 to High(KeyWeapon) do
553 begin
554 ReadInteger(KeyWeapon[i], 'KeyWeapon' + IntToStr(i))
555 end;
557 ReadInteger(KeyRight2, 'KeyRight2');
558 ReadInteger(KeyLeft2, 'KeyLeft2');
559 ReadInteger(KeyUp2, 'KeyUp2');
560 ReadInteger(KeyDown2, 'KeyDown2');
561 ReadInteger(KeyFire2, 'KeyFire2');
562 ReadInteger(KeyJump2, 'KeyJump2');
563 ReadInteger(KeyNextWeapon2, 'KeyNextWeapon2');
564 ReadInteger(KeyPrevWeapon2, 'KeyPrevWeapon2');
565 ReadInteger(KeyOpen2, 'KeyOpen2');
566 ReadInteger(KeyStrafe2, 'KeyStrafe2');
568 for i := 0 to High(KeyWeapon2) do
569 begin
570 ReadInteger(KeyWeapon2[i], 'KeyWeapon2' + IntToStr(i))
571 end;
572 end;
574 section := 'Player2';
575 with gPlayer2Settings do
576 begin
577 ReadString(Name, 'name');
578 ReadString(Model, 'model');
579 ReadInteger(Color.R, 'red', 0, 255);
580 ReadInteger(Color.G, 'green', 0, 255);
581 ReadInteger(Color.B, 'blue', 0, 255);
582 ReadInteger(Team, 'team');
583 if (Team < TEAM_RED) or (Team > TEAM_BLUE) then
584 Team := TEAM_RED;
585 end;
587 section := 'Joysticks';
588 for i := 0 to e_MaxJoys - 1 do
589 begin
590 ReadInteger(e_JoystickDeadzones[i], 'Deadzone' + IntToStr(i))
591 end;
593 section := 'Touch';
594 i := Trunc(g_touch_size * 10); ReadInteger(i, 'Size', 0); g_touch_size := i / 10;
595 ReadBoolean(g_touch_fire, 'Fire');
596 i := Round(g_touch_offset); ReadInteger(i, 'Offset', 0, 100); g_touch_offset := i;
597 ReadBoolean(g_touch_alt, 'Alt');
599 section := 'Game';
600 ReadInteger(i, 'MaxParticles', 1000, 50000); g_GFX_SetMax(i);
601 ReadInteger(i, 'MaxShells', 300, 600); g_Shells_SetMax(i);
602 ReadInteger(i, 'MaxGibs', 150, 500); g_Gibs_SetMax(i);
603 ReadInteger(i, 'MaxCorpses', 20, 100); g_Corpses_SetMax(i);
604 ReadInteger(i, 'GibsCount');
605 case i of
606 0: gGibsCount := 0;
607 1: gGibsCount := 8;
608 2: gGibsCount := 16;
609 3: gGibsCount := 32;
610 else gGibsCount := 48;
611 end;
612 i := ITEM_RESPAWNTIME div 36; ReadInteger(i, 'ItemRespawnTime', 0); ITEM_RESPAWNTIME := i * 36;
613 ReadInteger(gBloodCount, 'BloodCount', 0, 4);
614 ReadBoolean(gAdvBlood, 'AdvancesBlood');
615 ReadBoolean(gAdvCorpses, 'AdvancesCorpses');
616 ReadBoolean(gAdvGibs, 'AdvancesGibs');
617 ReadInteger(gFlash, 'Flash', 0, 2);
618 ReadBoolean(gDrawBackGround, 'BackGround');
619 ReadBoolean(gShowMessages, 'Messages');
620 ReadBoolean(gRevertPlayers, 'RevertPlayers');
621 ReadInteger(gChatBubble, 'ChatBubble', 0, 4);
622 ReadBoolean(gSFSDebug, 'SFSDebug'); wadoptDebug := gSFSDebug;
623 ReadBoolean(gSFSFastMode, 'SFSFastMode'); wadoptFast := gSFSFastMode;
624 ReadBoolean(e_FastScreenshots, 'FastScreenshots');
625 ReadString(gDefaultMegawadStart, 'DefaultMegawadStart');
626 ReadBoolean(gBerserkAutoswitch, 'BerserkAutoswitching');
627 i := Trunc(g_dbg_scale * 100); ReadInteger(i, 'Scale', 100); g_dbg_scale := i / 100;
628 ReadString(gLanguage, 'Language');
629 if (gLanguage = LANGUAGE_RUSSIAN) or (gLanguage = LANGUAGE_ENGLISH) then
630 gAskLanguage := False
631 else
632 gLanguage := LANGUAGE_ENGLISH;
634 section := 'GameplayCustom';
635 ReadString(gcMap, 'Map');
636 ReadString(gcGameMode, 'GameMode');
637 ReadInteger(gcTimeLimit, 'TimeLimit', 0, 65535);
638 ReadInteger(gcGoalLimit, 'GoalLimit', 0, 65535);
639 ReadInteger(gcMaxLives, 'MaxLives', 0, 255);
640 ReadInteger(gcPlayers, 'Players', 0, 2);
641 ReadBoolean(gcTeamDamage, 'TeamDamage');
642 ReadBoolean(gcAllowExit, 'AllowExit');
643 ReadBoolean(gcWeaponStay, 'WeaponStay');
644 ReadBoolean(gcMonsters, 'Monsters');
645 ReadString(gcBotsVS, 'BotsVS');
647 with gGameSettings do
648 begin
649 GameMode := g_Game_TextToMode(gcGameMode);
650 if GameMode = GM_NONE then
651 GameMode := GM_DM;
652 if GameMode = GM_SINGLE then
653 GameMode := GM_COOP;
654 TimeLimit := gcTimeLimit;
655 GoalLimit := gcGoalLimit;
656 MaxLives := gcMaxLives;
658 Options := 0;
659 if gcTeamDamage then
660 Options := Options or GAME_OPTION_TEAMDAMAGE;
661 if gcAllowExit then
662 Options := Options or GAME_OPTION_ALLOWEXIT;
663 if gcWeaponStay then
664 Options := Options or GAME_OPTION_WEAPONSTAY;
665 if gcMonsters then
666 Options := Options or GAME_OPTION_MONSTERS;
667 if gcBotsVS = 'Everybody' then
668 Options := Options or GAME_OPTION_BOTVSPLAYER or GAME_OPTION_BOTVSMONSTER;
669 if gcBotsVS = 'Players' then
670 Options := Options or GAME_OPTION_BOTVSPLAYER;
671 if gcBotsVS = 'Monsters' then
672 Options := Options or GAME_OPTION_BOTVSMONSTER;
673 end;
675 section := 'GameplayNetwork';
676 ReadString(gnMap, 'Map');
677 ReadString(gnGameMode, 'GameMode');
678 ReadInteger(gnTimeLimit, 'TimeLimit', 0, 65535);
679 ReadInteger(gnGoalLimit, 'GoalLimit', 0, 65535);
680 ReadInteger(gnMaxLives, 'MaxLives', 0, 255);
681 ReadInteger(gnPlayers, 'Players', 0, 2);
682 ReadBoolean(gnTeamDamage, 'TeamDamage');
683 ReadBoolean(gnAllowExit, 'AllowExit');
684 ReadBoolean(gnWeaponStay, 'WeaponStay');
685 ReadBoolean(gnMonsters, 'Monsters');
686 ReadString(gnBotsVS, 'BotsVS');
688 section := 'MasterServer';
689 ReadString(NetSlistIP, 'IP');
690 ReadInteger(NetSlistPort, 'Port', 0, 65535);
691 g_Net_Slist_Set(NetSlistIP, NetSlistPort);
693 section := 'Server';
694 ReadString(NetServerName, 'Name');
695 ReadString(NetPassword, 'Password');
696 ReadInteger(NetPort, 'Port', 0, 65535);
697 ReadInteger(NetMaxClients, 'MaxClients', 0, NET_MAXCLIENTS);
698 ReadBoolean(NetAllowRCON, 'RCON');
699 ReadString(NetRCONPassword, 'RCONPassword');
700 ReadBoolean(NetUseMaster, 'SyncWithMaster');
701 ReadInteger(NetUpdateRate, 'UpdateInterval', 0);
702 ReadInteger(NetRelupdRate, 'ReliableUpdateInterval', 0);
703 ReadInteger(NetMasterRate, 'MasterSyncInterval', 1);
704 ReadBoolean(NetForwardPorts, 'ForwardPorts');
706 section := 'Client';
707 ReadInteger(NetInterpLevel, 'InterpolationSteps', 0);
708 ReadBoolean(NetForcePlayerUpdate, 'ForcePlayerUpdate');
709 ReadBoolean(NetPredictSelf, 'PredictSelf');
710 ReadString(NetClientIP, 'LastIP');
711 ReadInteger(NetClientPort, 'LastPort', 0, 65535);
713 config.Free();
715 //if gTextureFilter then TEXTUREFILTER := GL_LINEAR else TEXTUREFILTER := GL_NEAREST;
716 end;
718 procedure g_Options_Write(FileName: String);
719 var
720 config: TConfig;
721 i: Integer;
722 begin
723 e_WriteLog('Writing config', TMsgType.Notify);
725 config := TConfig.CreateFile(FileName);
727 config.WriteInt('Video', 'ScreenWidth', gScreenWidth);
728 config.WriteInt('Video', 'ScreenHeight', gScreenHeight);
729 config.WriteInt('Video', 'WinPosX', gWinRealPosX);
730 config.WriteInt('Video', 'WinPosY', gWinRealPosY);
731 config.WriteBool('Video', 'Fullscreen', gFullScreen);
732 config.WriteBool('Video', 'Maximized', gWinMaximized);
733 config.WriteInt('Video', 'BPP', gBPP);
734 config.WriteBool('Video', 'VSync', gVSync);
735 config.WriteBool('Video', 'TextureFilter', gTextureFilter);
736 config.WriteBool('Video', 'LegacyCompatible', glLegacyNPOT);
738 config.WriteBool('Sound', 'NoSound', gNoSound);
739 config.WriteInt('Sound', 'SoundLevel', gSoundLevel);
740 config.WriteInt('Sound', 'MusicLevel', gMusicLevel);
741 config.WriteInt('Sound', 'MaxSimSounds', gMaxSimSounds);
742 config.WriteBool('Sound', 'MuteInactive', gMuteWhenInactive);
743 config.WriteInt('Sound', 'Announcer', gAnnouncer);
744 config.WriteBool('Sound', 'SoundEffectsDF', gSoundEffectsDF);
745 config.WriteBool('Sound', 'ChatSounds', gUseChatSounds);
746 config.WriteInt('Sound', 'SDLSampleRate', gsSDLSampleRate);
747 config.WriteInt('Sound', 'SDLBufferSize', gsSDLBufferSize);
749 with config, gGameControls.GameControls do
750 begin
751 WriteInt('GameControls', 'TakeScreenshot', TakeScreenshot);
752 WriteInt('GameControls', 'Stat', Stat);
753 WriteInt('GameControls', 'Chat', Chat);
754 WriteInt('GameControls', 'TeamChat', TeamChat);
755 end;
757 with config, gGameControls.P1Control, gPlayer1Settings do
758 begin
759 WriteInt('Player1', 'KeyRight', KeyRight);
760 WriteInt('Player1', 'KeyLeft', KeyLeft);
761 WriteInt('Player1', 'KeyUp', KeyUp);
762 WriteInt('Player1', 'KeyDown', KeyDown);
763 WriteInt('Player1', 'KeyFire', KeyFire);
764 WriteInt('Player1', 'KeyJump', KeyJump);
765 WriteInt('Player1', 'KeyNextWeapon', KeyNextWeapon);
766 WriteInt('Player1', 'KeyPrevWeapon', KeyPrevWeapon);
767 WriteInt('Player1', 'KeyOpen', KeyOpen);
768 WriteInt('Player1', 'KeyStrafe', KeyStrafe);
769 for i := 0 to High(KeyWeapon) do
770 WriteInt('Player1', 'KeyWeapon' + IntToStr(i), KeyWeapon[i]);
772 WriteInt('Player1', 'KeyRight2', KeyRight2);
773 WriteInt('Player1', 'KeyLeft2', KeyLeft2);
774 WriteInt('Player1', 'KeyUp2', KeyUp2);
775 WriteInt('Player1', 'KeyDown2', KeyDown2);
776 WriteInt('Player1', 'KeyFire2', KeyFire2);
777 WriteInt('Player1', 'KeyJump2', KeyJump2);
778 WriteInt('Player1', 'KeyNextWeapon2', KeyNextWeapon2);
779 WriteInt('Player1', 'KeyPrevWeapon2', KeyPrevWeapon2);
780 WriteInt('Player1', 'KeyOpen2', KeyOpen2);
781 WriteInt('Player1', 'KeyStrafe2', KeyStrafe2);
782 for i := 0 to High(KeyWeapon2) do
783 WriteInt('Player1', 'KeyWeapon2' + IntToStr(i), KeyWeapon2[i]);
785 WriteStr('Player1', 'Name', Name);
786 WriteStr('Player1', 'model', Model);
787 WriteInt('Player1', 'red', Color.R);
788 WriteInt('Player1', 'green', Color.G);
789 WriteInt('Player1', 'blue', Color.B);
790 WriteInt('Player1', 'team', Team);
791 end;
793 with config, gGameControls.P2Control, gPlayer2Settings do
794 begin
795 WriteInt('Player2', 'KeyRight', KeyRight);
796 WriteInt('Player2', 'KeyLeft', KeyLeft);
797 WriteInt('Player2', 'KeyUp', KeyUp);
798 WriteInt('Player2', 'KeyDown', KeyDown);
799 WriteInt('Player2', 'KeyFire', KeyFire);
800 WriteInt('Player2', 'KeyJump', KeyJump);
801 WriteInt('Player2', 'KeyNextWeapon', KeyNextWeapon);
802 WriteInt('Player2', 'KeyPrevWeapon', KeyPrevWeapon);
803 WriteInt('Player2', 'KeyOpen', KeyOpen);
804 WriteInt('Player2', 'KeyStrafe', KeyStrafe);
805 for i := 0 to High(KeyWeapon) do
806 WriteInt('Player2', 'KeyWeapon' + IntToStr(i), KeyWeapon[i]);
808 WriteInt('Player2', 'KeyRight2', KeyRight2);
809 WriteInt('Player2', 'KeyLeft2', KeyLeft2);
810 WriteInt('Player2', 'KeyUp2', KeyUp2);
811 WriteInt('Player2', 'KeyDown2', KeyDown2);
812 WriteInt('Player2', 'KeyFire2', KeyFire2);
813 WriteInt('Player2', 'KeyJump2', KeyJump2);
814 WriteInt('Player2', 'KeyNextWeapon2', KeyNextWeapon2);
815 WriteInt('Player2', 'KeyPrevWeapon2', KeyPrevWeapon2);
816 WriteInt('Player2', 'KeyOpen2', KeyOpen2);
817 WriteInt('Player2', 'KeyStrafe2', KeyStrafe2);
818 for i := 0 to High(KeyWeapon2) do
819 WriteInt('Player2', 'KeyWeapon2' + IntToStr(i), KeyWeapon2[i]);
821 WriteStr('Player2', 'Name', Name);
822 WriteStr('Player2', 'model', Model);
823 WriteInt('Player2', 'red', Color.R);
824 WriteInt('Player2', 'green', Color.G);
825 WriteInt('Player2', 'blue', Color.B);
826 WriteInt('Player2', 'team', Team);
827 end;
829 for i := 0 to e_MaxJoys-1 do
830 config.WriteInt('Joysticks', 'Deadzone' + IntToStr(i), e_JoystickDeadzones[i]);
832 config.WriteInt('Touch', 'Size', Round(g_touch_size * 10));
833 config.WriteBool('Touch', 'Fire', g_touch_fire);
834 config.WriteInt('Touch', 'Offset', Round(g_touch_offset));
835 config.WriteBool('Touch', 'Alt', g_touch_alt);
837 with config do
838 case gGibsCount of
839 0: config.WriteInt('Game', 'GibsCount', 0);
840 8: config.WriteInt('Game', 'GibsCount', 1);
841 16: config.WriteInt('Game', 'GibsCount', 2);
842 32: config.WriteInt('Game', 'GibsCount', 3);
843 else config.WriteInt('Game', 'GibsCount', 4);
844 end;
846 config.WriteInt('Game', 'ItemRespawnTime', ITEM_RESPAWNTIME div 36);
847 config.WriteInt('Game', 'MaxParticles', g_GFX_GetMax());
848 config.WriteInt('Game', 'MaxShells', g_Shells_GetMax());
849 config.WriteInt('Game', 'MaxGibs', g_Gibs_GetMax());
850 config.WriteInt('Game', 'MaxCorpses', g_Corpses_GetMax());
851 config.WriteInt('Game', 'BloodCount', gBloodCount);
852 config.WriteBool('Game', 'AdvancesBlood', gAdvBlood);
853 config.WriteBool('Game', 'AdvancesCorpses', gAdvCorpses);
854 config.WriteBool('Game', 'AdvancesGibs', gAdvGibs);
855 config.WriteInt('Game', 'Flash', gFlash);
856 config.WriteBool('Game', 'BackGround', gDrawBackGround);
857 config.WriteBool('Game', 'Messages', gShowMessages);
858 config.WriteBool('Game', 'RevertPlayers', gRevertPlayers);
859 config.WriteInt('Game', 'ChatBubble', gChatBubble);
860 config.WriteBool('Game', 'SFSDebug', gSFSDebug);
861 config.WriteBool('Game', 'SFSFastMode', gSFSFastMode);
862 config.WriteBool('Game', 'FastScreenshots', e_FastScreenshots);
863 config.WriteStr('Game', 'DefaultMegawadStart', gDefaultMegawadStart);
864 config.WriteBool('Game', 'BerserkAutoswitching', gBerserkAutoswitch);
865 config.WriteInt('Game', 'Scale', Round(g_dbg_scale * 100));
867 config.WriteStr ('GameplayCustom', 'Map', gcMap);
868 config.WriteStr ('GameplayCustom', 'GameMode', gcGameMode);
869 config.WriteInt ('GameplayCustom', 'TimeLimit', gcTimeLimit);
870 config.WriteInt ('GameplayCustom', 'GoalLimit', gcGoalLimit);
871 config.WriteInt ('GameplayCustom', 'MaxLives', gcMaxLives);
872 config.WriteInt ('GameplayCustom', 'Players', gcPlayers);
873 config.WriteBool('GameplayCustom', 'TeamDamage', gcTeamDamage);
874 config.WriteBool('GameplayCustom', 'AllowExit', gcAllowExit);
875 config.WriteBool('GameplayCustom', 'WeaponStay', gcWeaponStay);
876 config.WriteBool('GameplayCustom', 'Monsters', gcMonsters);
877 config.WriteStr ('GameplayCustom', 'BotsVS', gcBotsVS);
879 config.WriteStr ('GameplayNetwork', 'Map', gnMap);
880 config.WriteStr ('GameplayNetwork', 'GameMode', gnGameMode);
881 config.WriteInt ('GameplayNetwork', 'TimeLimit', gnTimeLimit);
882 config.WriteInt ('GameplayNetwork', 'GoalLimit', gnGoalLimit);
883 config.WriteInt ('GameplayNetwork', 'MaxLives', gnMaxLives);
884 config.WriteInt ('GameplayNetwork', 'Players', gnPlayers);
885 config.WriteBool('GameplayNetwork', 'TeamDamage', gnTeamDamage);
886 config.WriteBool('GameplayNetwork', 'AllowExit', gnAllowExit);
887 config.WriteBool('GameplayNetwork', 'WeaponStay', gnWeaponStay);
888 config.WriteBool('GameplayNetwork', 'Monsters', gnMonsters);
889 config.WriteStr ('GameplayNetwork', 'BotsVS', gnBotsVS);
891 config.WriteStr('MasterServer', 'IP', NetSlistIP);
892 config.WriteInt('MasterServer', 'Port', NetSlistPort);
894 config.WriteStr ('Server', 'Name', NetServerName);
895 config.WriteStr ('Server', 'Password', NetPassword);
896 config.WriteInt ('Server', 'Port', NetPort);
897 config.WriteInt ('Server', 'MaxClients', NetMaxClients);
898 config.WriteBool('Server', 'RCON', NetAllowRCON);
899 config.WriteStr ('Server', 'RCONPassword', NetRCONPassword);
900 config.WriteBool('Server', 'SyncWithMaster', NetUseMaster);
901 config.WriteBool('Server', 'ForwardPorts', NetForwardPorts);
902 config.WriteInt ('Server', 'UpdateInterval', NetUpdateRate);
903 config.WriteInt ('Server', 'ReliableUpdateInterval', NetRelupdRate);
904 config.WriteInt ('Server', 'MasterSyncInterval', NetMasterRate);
906 config.WriteInt ('Client', 'InterpolationSteps', NetInterpLevel);
907 config.WriteBool ('Client', 'ForcePlayerUpdate', NetForcePlayerUpdate);
908 config.WriteBool ('Client', 'PredictSelf', NetPredictSelf);
909 config.WriteStr ('Client', 'LastIP', NetClientIP);
910 config.WriteInt ('Client', 'LastPort', NetClientPort);
912 config.SaveFile(FileName);
913 config.Free();
914 end;
916 procedure g_Options_Write_Language(FileName: String);
917 var
918 config: TConfig;
919 begin
920 e_WriteLog('Writing language config', TMsgType.Notify);
922 config := TConfig.CreateFile(FileName);
923 config.WriteStr('Game', 'Language', gLanguage);
924 config.SaveFile(FileName);
925 config.Free();
926 end;
928 procedure g_Options_Write_Video(FileName: String);
929 var
930 config: TConfig;
931 sW, sH: Integer;
932 begin
933 e_WriteLog('Writing resolution to config', TMsgType.Notify);
935 config := TConfig.CreateFile(FileName);
937 if gWinMaximized and (not gFullscreen) then
938 begin
939 sW := gWinSizeX;
940 sH := gWinSizeY;
941 end
942 else
943 begin
944 sW := gScreenWidth;
945 sH := gScreenHeight;
946 end;
947 e_LogWritefln(' (ws=%dx%d) (ss=%dx%d)', [gWinSizeX, gWinSizeY, gScreenWidth, gScreenHeight]);
949 config.WriteInt('Video', 'ScreenWidth', sW);
950 config.WriteInt('Video', 'ScreenHeight', sH);
951 config.WriteInt('Video', 'WinPosX', gWinRealPosX);
952 config.WriteInt('Video', 'WinPosY', gWinRealPosY);
953 config.WriteBool('Video', 'Fullscreen', gFullscreen);
954 config.WriteBool('Video', 'Maximized', gWinMaximized);
956 config.SaveFile(FileName);
957 config.Free();
958 end;
960 procedure g_Options_Write_Gameplay_Custom(FileName: String);
961 var
962 config: TConfig;
963 begin
964 e_WriteLog('Writing custom gameplay config', TMsgType.Notify);
966 config := TConfig.CreateFile(FileName);
968 config.WriteStr ('GameplayCustom', 'Map', gcMap);
969 config.WriteStr ('GameplayCustom', 'GameMode', gcGameMode);
970 config.WriteInt ('GameplayCustom', 'TimeLimit', gcTimeLimit);
971 config.WriteInt ('GameplayCustom', 'GoalLimit', gcGoalLimit);
972 config.WriteInt ('GameplayCustom', 'MaxLives', gcMaxLives);
973 config.WriteInt ('GameplayCustom', 'Players', gcPlayers);
974 config.WriteBool('GameplayCustom', 'TeamDamage', gcTeamDamage);
975 config.WriteBool('GameplayCustom', 'AllowExit', gcAllowExit);
976 config.WriteBool('GameplayCustom', 'WeaponStay', gcWeaponStay);
977 config.WriteBool('GameplayCustom', 'Monsters', gcMonsters);
978 config.WriteStr ('GameplayCustom', 'BotsVS', gcBotsVS);
980 config.SaveFile(FileName);
981 config.Free();
982 end;
984 procedure g_Options_Write_Gameplay_Net(FileName: String);
985 var
986 config: TConfig;
987 begin
988 e_WriteLog('Writing network gameplay config', TMsgType.Notify);
990 config := TConfig.CreateFile(FileName);
992 config.WriteStr ('GameplayNetwork', 'Map', gnMap);
993 config.WriteStr ('GameplayNetwork', 'GameMode', gnGameMode);
994 config.WriteInt ('GameplayNetwork', 'TimeLimit', gnTimeLimit);
995 config.WriteInt ('GameplayNetwork', 'GoalLimit', gnGoalLimit);
996 config.WriteInt ('GameplayNetwork', 'MaxLives', gnMaxLives);
997 config.WriteInt ('GameplayNetwork', 'Players', gnPlayers);
998 config.WriteBool('GameplayNetwork', 'TeamDamage', gnTeamDamage);
999 config.WriteBool('GameplayNetwork', 'AllowExit', gnAllowExit);
1000 config.WriteBool('GameplayNetwork', 'WeaponStay', gnWeaponStay);
1001 config.WriteBool('GameplayNetwork', 'Monsters', gnMonsters);
1002 config.WriteStr ('GameplayNetwork', 'BotsVS', gnBotsVS);
1004 config.SaveFile(FileName);
1005 config.Free();
1006 end;
1008 procedure g_Options_Write_Net_Server(FileName: String);
1009 var
1010 config: TConfig;
1011 begin
1012 e_WriteLog('Writing server config', TMsgType.Notify);
1014 config := TConfig.CreateFile(FileName);
1016 config.WriteStr ('Server', 'Name', NetServerName);
1017 config.WriteStr ('Server', 'Password', NetPassword);
1018 config.WriteInt ('Server', 'Port', NetPort);
1019 config.WriteInt ('Server', 'MaxClients', NetMaxClients);
1020 config.WriteBool('Server', 'SyncWithMaster', NetUseMaster);
1021 config.WriteBool('Server', 'ForwardPorts', NetForwardPorts);
1023 config.SaveFile(FileName);
1024 config.Free();
1025 end;
1027 procedure g_Options_Write_Net_Client(FileName: String);
1028 var
1029 config: TConfig;
1030 begin
1031 e_WriteLog('Writing client config', TMsgType.Notify);
1033 config := TConfig.CreateFile(FileName);
1035 config.WriteStr('Client', 'LastIP', NetClientIP);
1036 config.WriteInt('Client', 'LastPort', NetClientPort);
1038 config.SaveFile(FileName);
1039 config.Free();
1040 end;
1042 end.