DEADSOFTWARE

sfs and wad code refactoring: part 1
[d2df-sdl.git] / src / game / g_main.pas
1 unit g_main;
3 interface
5 procedure Main();
6 procedure Init();
7 procedure Release();
8 procedure Update();
9 procedure Draw();
10 procedure KeyPress(K: Word);
11 procedure CharPress(C: Char);
13 var
14 GameDir: string;
15 DataDir: string;
16 MapsDir: string;
17 ModelsDir: string;
18 GameWAD: string;
20 implementation
22 uses
23 SDL2, GL, GLExt, wadreader, e_log, g_window,
24 e_graphics, e_input, g_game, g_console, g_gui,
25 e_sound, g_options, g_sound, g_player,
26 g_weapons, SysUtils, g_triggers, MAPDEF, g_map,
27 MAPSTRUCT, g_menu, g_language, g_net, utils;
29 var
30 charbuff: Array [0..15] of Char;
32 procedure Main();
33 var
34 sdlflags: LongWord;
35 begin
36 GetDir(0, GameDir);
37 MapsDir := GameDir + '/maps/';
38 DataDir := GameDir + '/data/';
39 ModelsDir := DataDir + 'models/';
40 GameWAD := DataDir + 'Game.wad';
42 e_InitLog(GameDir + '/' + LOG_FILENAME, WM_NEWFILE);
44 e_WriteLog('Read config file', MSG_NOTIFY);
45 g_Options_Read(GameDir + '/' + CONFIG_FILENAME);
47 e_WriteToStdOut := {$IFDEF HEADLESS}True;{$ELSE}False;{$ENDIF}
49 //GetSystemDefaultLCID()
51 //e_WriteLog('Read language file', MSG_NOTIFY);
52 //g_Language_Load(DataDir + gLanguage + '.txt');
53 e_WriteLog(gLanguage, MSG_NOTIFY);
54 g_Language_Set(gLanguage);
56 {$IFDEF HEADLESS}
57 sdlflags := SDL_INIT_TIMER or $00004000;
58 {$ELSE}
59 {$IFDEF USE_SDLMIXER}
60 sdlflags := SDL_INIT_EVERYTHING;
61 {$ELSE}
62 sdlflags := SDL_INIT_JOYSTICK or SDL_INIT_TIMER or SDL_INIT_VIDEO;
63 {$ENDIF}
64 {$ENDIF}
65 if SDL_Init(sdlflags) < 0 then
66 raise Exception.Create('SDL: Init failed: ' + SDL_GetError());
68 {$IFDEF HEADLESS}
69 SDL_StartTextInput();
70 {$ENDIF}
72 e_WriteLog('Entering SDLMain', MSG_NOTIFY);
74 {$WARNINGS OFF}
75 SDLMain();
76 {$WARNINGS ON}
78 {$IFDEF HEADLESS}
79 SDL_StopTextInput();
80 {$ENDIF}
82 e_WriteLog('Releasing SDL', MSG_NOTIFY);
83 SDL_Quit();
84 end;
86 procedure Init();
87 var
88 a: Integer;
89 begin
90 Randomize;
92 e_WriteLog('Init Input', MSG_NOTIFY);
93 e_InitInput();
95 if (e_JoysticksAvailable > 0) then
96 e_WriteLog('Input: Joysticks available.', MSG_NOTIFY)
97 else
98 e_WriteLog('Input: No Joysticks.', MSG_NOTIFY);
100 if (not gNoSound) then
101 begin
102 e_WriteLog('Initializing sound system', MSG_NOTIFY);
103 e_InitSoundSystem({$IFDEF HEADLESS}True{$ELSE}False{$ENDIF});
104 end;
106 e_WriteLog('Init game', MSG_NOTIFY);
107 g_Game_Init();
109 for a := 0 to 15 do charbuff[a] := ' ';
110 end;
112 procedure Release();
113 begin
114 e_WriteLog('Releasing engine', MSG_NOTIFY);
115 e_ReleaseEngine();
117 e_WriteLog('Releasing Input', MSG_NOTIFY);
118 e_ReleaseInput();
120 if not gNoSound then
121 begin
122 e_WriteLog('Releasing FMOD', MSG_NOTIFY);
123 e_ReleaseSoundSystem();
124 end;
125 end;
127 procedure Update();
128 begin
129 g_Game_Update();
130 end;
132 procedure Draw();
133 begin
134 g_Game_Draw();
135 end;
137 function Translit(S: String): String;
138 var
139 i: Integer;
140 begin
141 Result := S;
142 for i := 1 to Length(Result) do
143 case Result[i] of
144 'É': Result[i] := 'Q';
145 'Ö': Result[i] := 'W';
146 'Ó': Result[i] := 'E';
147 'Ê': Result[i] := 'R';
148 'Å': Result[i] := 'T';
149 'Í': Result[i] := 'Y';
150 'Ã': Result[i] := 'U';
151 'Ø': Result[i] := 'I';
152 'Ù': Result[i] := 'O';
153 'Ç': Result[i] := 'P';
154 'Õ': Result[i] := '['; //Chr(219);
155 'Ú': Result[i] := ']'; //Chr(221);
156 'Ô': Result[i] := 'A';
157 'Û': Result[i] := 'S';
158 'Â': Result[i] := 'D';
159 'À': Result[i] := 'F';
160 'Ï': Result[i] := 'G';
161 'Ð': Result[i] := 'H';
162 'Î': Result[i] := 'J';
163 'Ë': Result[i] := 'K';
164 'Ä': Result[i] := 'L';
165 'Æ': Result[i] := ';'; //Chr(186);
166 'Ý': Result[i] := #39; //Chr(222);
167 'ß': Result[i] := 'Z';
168 '×': Result[i] := 'X';
169 'Ñ': Result[i] := 'C';
170 'Ì': Result[i] := 'V';
171 'È': Result[i] := 'B';
172 'Ò': Result[i] := 'N';
173 'Ü': Result[i] := 'M';
174 'Á': Result[i] := ','; //Chr(188);
175 'Þ': Result[i] := '.'; //Chr(190);
176 end;
177 end;
180 function CheckCheat (ct: TStrings_Locale; eofs: Integer=0): Boolean;
181 var
182 ls1, ls2: string;
183 begin
184 ls1 := CheatEng[ct];
185 ls2 := Translit(CheatRus[ct]);
186 if length(ls1) = 0 then ls1 := '~';
187 if length(ls2) = 0 then ls2 := '~';
188 result :=
189 (Copy(charbuff, 17-Length(ls1)-eofs, Length(ls1)) = ls1) or
190 (Translit(Copy(charbuff, 17-Length(ls1)-eofs, Length(ls1))) = ls1) or
191 (Copy(charbuff, 17-Length(ls2)-eofs, Length(ls2)) = ls2) or
192 (Translit(Copy(charbuff, 17-Length(ls2)-eofs, Length(ls2))) = ls2);
194 if ct = I_GAME_CHEAT_JETPACK then
195 begin
196 e_WriteLog('ls1: ['+ls1+']', MSG_NOTIFY);
197 e_WriteLog('ls2: ['+ls2+']', MSG_NOTIFY);
198 e_WriteLog('bf0: ['+Copy(charbuff, 17-Length(ls1)-eofs, Length(ls1))+']', MSG_NOTIFY);
199 e_WriteLog('bf1: ['+Translit(Copy(charbuff, 17-Length(ls1)-eofs, Length(ls1)))+']', MSG_NOTIFY);
200 e_WriteLog('bf2: ['+Copy(charbuff, 17-Length(ls2)-eofs, Length(ls2))+']', MSG_NOTIFY);
201 e_WriteLog('bf3: ['+Translit(Copy(charbuff, 17-Length(ls2)-eofs, Length(ls2)))+']', MSG_NOTIFY);
202 end;
204 end;
207 procedure Cheat();
208 const
209 CHEAT_DAMAGE = 500;
210 label
211 Cheated;
212 var
213 s, s2: string;
214 c: Char16;
215 a: Integer;
216 begin
217 if (not gGameOn) or (not gCheats) or ((gGameSettings.GameType <> GT_SINGLE) and
218 (gGameSettings.GameMode <> GM_COOP) and (not gDebugMode))
219 or g_Game_IsNet then Exit;
221 s := 'SOUND_GAME_RADIO';
223 //
224 if CheckCheat(I_GAME_CHEAT_GODMODE) then
225 begin
226 if gPlayer1 <> nil then gPlayer1.GodMode := not gPlayer1.GodMode;
227 if gPlayer2 <> nil then gPlayer2.GodMode := not gPlayer2.GodMode;
228 goto Cheated;
229 end;
230 // RAMBO
231 if CheckCheat(I_GAME_CHEAT_WEAPONS) then
232 begin
233 if gPlayer1 <> nil then gPlayer1.AllRulez(False);
234 if gPlayer2 <> nil then gPlayer2.AllRulez(False);
235 goto Cheated;
236 end;
237 // TANK
238 if CheckCheat(I_GAME_CHEAT_HEALTH) then
239 begin
240 if gPlayer1 <> nil then gPlayer1.AllRulez(True);
241 if gPlayer2 <> nil then gPlayer2.AllRulez(True);
242 goto Cheated;
243 end;
244 // IDDQD
245 if CheckCheat(I_GAME_CHEAT_DEATH) then
246 begin
247 if gPlayer1 <> nil then gPlayer1.Damage(CHEAT_DAMAGE, 0, 0, 0, HIT_TRAP);
248 if gPlayer2 <> nil then gPlayer2.Damage(CHEAT_DAMAGE, 0, 0, 0, HIT_TRAP);
249 s := 'SOUND_MONSTER_HAHA';
250 goto Cheated;
251 end;
252 //
253 if CheckCheat(I_GAME_CHEAT_DOORS) then
254 begin
255 g_Triggers_OpenAll();
256 goto Cheated;
257 end;
258 // GOODBYE
259 if CheckCheat(I_GAME_CHEAT_NEXTMAP) then
260 begin
261 if gTriggers <> nil then
262 for a := 0 to High(gTriggers) do
263 if gTriggers[a].TriggerType = TRIGGER_EXIT then
264 begin
265 gExitByTrigger := True;
266 g_Game_ExitLevel(gTriggers[a].Data.MapName);
267 Break;
268 end;
269 goto Cheated;
270 end;
271 //
272 s2 := Copy(charbuff, 15, 2);
273 if CheckCheat(I_GAME_CHEAT_CHANGEMAP, 2) and (s2[1] >= '0') and (s2[1] <= '9') and (s2[2] >= '0') and (s2[2] <= '9') then
274 begin
275 if g_Map_Exist(MapsDir+gGameSettings.WAD+':\MAP'+s2) then
276 begin
277 c := 'MAP00';
278 c[3] := s2[1];
279 c[4] := s2[2];
280 g_Game_ExitLevel(c);
281 end;
282 goto Cheated;
283 end;
284 //
285 if CheckCheat(I_GAME_CHEAT_FLY) then
286 begin
287 gFly := not gFly;
288 goto Cheated;
289 end;
290 // BULLFROG
291 if CheckCheat(I_GAME_CHEAT_JUMPS) then
292 begin
293 VEL_JUMP := 30-VEL_JUMP;
294 goto Cheated;
295 end;
296 // FORMULA1
297 if CheckCheat(I_GAME_CHEAT_SPEED) then
298 begin
299 MAX_RUNVEL := 32-MAX_RUNVEL;
300 goto Cheated;
301 end;
302 // CONDOM
303 if CheckCheat(I_GAME_CHEAT_SUIT) then
304 begin
305 if gPlayer1 <> nil then gPlayer1.GiveItem(ITEM_SUIT);
306 if gPlayer2 <> nil then gPlayer2.GiveItem(ITEM_SUIT);
307 goto Cheated;
308 end;
309 //
310 if CheckCheat(I_GAME_CHEAT_AIR) then
311 begin
312 if gPlayer1 <> nil then gPlayer1.GiveItem(ITEM_OXYGEN);
313 if gPlayer2 <> nil then gPlayer2.GiveItem(ITEM_OXYGEN);
314 goto Cheated;
315 end;
316 // PURELOVE
317 if CheckCheat(I_GAME_CHEAT_BERSERK) then
318 begin
319 if gPlayer1 <> nil then gPlayer1.GiveItem(ITEM_MEDKIT_BLACK);
320 if gPlayer2 <> nil then gPlayer2.GiveItem(ITEM_MEDKIT_BLACK);
321 goto Cheated;
322 end;
323 //
324 if CheckCheat(I_GAME_CHEAT_JETPACK) then
325 begin
326 if gPlayer1 <> nil then gPlayer1.GiveItem(ITEM_JETPACK);
327 if gPlayer2 <> nil then gPlayer2.GiveItem(ITEM_JETPACK);
328 goto Cheated;
329 end;
330 // CASPER
331 if CheckCheat(I_GAME_CHEAT_NOCLIP) then
332 begin
333 if gPlayer1 <> nil then gPlayer1.SwitchNoClip;
334 if gPlayer2 <> nil then gPlayer2.SwitchNoClip;
335 goto Cheated;
336 end;
337 //
338 if CheckCheat(I_GAME_CHEAT_NOTARGET) then
339 begin
340 if gPlayer1 <> nil then gPlayer1.NoTarget := not gPlayer1.NoTarget;
341 if gPlayer2 <> nil then gPlayer2.NoTarget := not gPlayer2.NoTarget;
342 goto Cheated;
343 end;
344 // INFERNO
345 if CheckCheat(I_GAME_CHEAT_NORELOAD) then
346 begin
347 if gPlayer1 <> nil then gPlayer1.NoReload := not gPlayer1.NoReload;
348 if gPlayer2 <> nil then gPlayer2.NoReload := not gPlayer2.NoReload;
349 goto Cheated;
350 end;
351 if CheckCheat(I_GAME_CHEAT_AIMLINE) then
352 begin
353 gAimLine := not gAimLine;
354 goto Cheated;
355 end;
356 if CheckCheat(I_GAME_CHEAT_AUTOMAP) then
357 begin
358 gShowMap := not gShowMap;
359 goto Cheated;
360 end;
361 Exit;
363 Cheated:
364 g_Sound_PlayEx(s);
365 end;
367 procedure KeyPress(K: Word);
368 var
369 Msg: g_gui.TMessage;
370 begin
371 case K of
372 IK_PAUSE: // <Pause/Break>:
373 begin
374 if (g_ActiveWindow = nil) then
375 g_Game_Pause(not gPause);
376 end;
378 IK_BACKQUOTE: // <`/~/¨/¸>:
379 begin
380 g_Console_Switch();
381 end;
383 IK_ESCAPE: // <Esc>:
384 begin
385 if gChatShow then
386 begin
387 g_Console_Chat_Switch();
388 Exit;
389 end;
391 if gConsoleShow then
392 g_Console_Switch()
393 else
394 if g_ActiveWindow <> nil then
395 begin
396 Msg.Msg := WM_KEYDOWN;
397 Msg.WParam := IK_ESCAPE;
398 g_ActiveWindow.OnMessage(Msg);
399 end
400 else
401 if gState <> STATE_FOLD then
402 if gGameOn
403 or (gState = STATE_INTERSINGLE)
404 or (gState = STATE_INTERCUSTOM)
405 then
406 g_Game_InGameMenu(True)
407 else
408 if (gExit = 0) and (gState <> STATE_SLIST) then
409 begin
410 if gState <> STATE_MENU then
411 if NetMode <> NET_NONE then
412 begin
413 g_Game_StopAllSounds(True);
414 g_Game_Free;
415 gState := STATE_MENU;
416 Exit;
417 end;
419 g_GUI_ShowWindow('MainMenu');
420 g_Sound_PlayEx('MENU_OPEN');
421 end;
422 end;
424 IK_F2, IK_F3, IK_F4, IK_F5, IK_F6, IK_F7, IK_F10:
425 begin // <F2> .. <F6> � <F12>
426 if gGameOn and (not gConsoleShow) and (not gChatShow) then
427 begin
428 while g_ActiveWindow <> nil do
429 g_GUI_HideWindow(False);
431 if (not g_Game_IsNet) then
432 g_Game_Pause(True);
434 case K of
435 IK_F2:
436 g_Menu_Show_SaveMenu();
437 IK_F3:
438 g_Menu_Show_LoadMenu();
439 IK_F4:
440 g_Menu_Show_GameSetGame();
441 IK_F5:
442 g_Menu_Show_OptionsVideo();
443 IK_F6:
444 g_Menu_Show_OptionsSound();
445 IK_F7:
446 g_Menu_Show_EndGameMenu();
447 IK_F10:
448 g_Menu_Show_QuitGameMenu();
449 end;
450 end;
451 end;
453 else
454 begin
455 gJustChatted := False;
456 if gConsoleShow or gChatShow then
457 g_Console_Control(K)
458 else
459 if g_ActiveWindow <> nil then
460 begin
461 Msg.Msg := WM_KEYDOWN;
462 Msg.WParam := K;
463 g_ActiveWindow.OnMessage(Msg);
464 end
465 else
466 begin
467 if (gState = STATE_MENU) then
468 begin
469 g_GUI_ShowWindow('MainMenu');
470 g_Sound_PlayEx('MENU_OPEN');
471 end;
472 end;
473 end;
474 end;
475 end;
477 procedure CharPress(C: Char);
478 var
479 Msg: g_gui.TMessage;
480 a: Integer;
481 begin
482 if (not gChatShow) and ((C = '`') or (C = '~') or (C = '¸') or (C = '¨')) then
483 Exit;
485 if gConsoleShow or gChatShow then
486 g_Console_Char(C)
487 else
488 if g_ActiveWindow <> nil then
489 begin
490 Msg.Msg := WM_CHAR;
491 Msg.WParam := Ord(C);
492 g_ActiveWindow.OnMessage(Msg);
493 end
494 else
495 begin
496 for a := 0 to 14 do charbuff[a] := charbuff[a+1];
497 charbuff[15] := UpCase1251(C);
498 Cheat();
499 end;
500 end;
502 end.