DEADSOFTWARE

game: remove d_player (unused command)
[d2df-sdl.git] / src / game / g_game.pas
index b78667168645fcef361ce6ca231569c3a4f911b3..854938698fc7b37b254f7b58c4541d5a9bb3f39f 100644 (file)
@@ -17,12 +17,15 @@ unit g_game;
 
 interface
 
-uses
-  SysUtils, Classes,
-  MAPDEF,
-  g_base, g_basic, g_player, r_graphics, g_res_downloader,
-  g_sound, g_gui, utils, md5, mempool, xprofiler,
-  g_touch, g_weapons;
+  uses
+    {$IFDEF ENABLE_MENU}
+      g_gui,
+    {$ENDIF}
+    SysUtils, Classes, MAPDEF,
+    g_base, g_basic, g_player, g_res_downloader,
+    g_sound, utils, md5, mempool, xprofiler,
+    g_weapons
+  ;
 
 type
   TGameSettings = record
@@ -91,7 +94,6 @@ procedure g_Game_FreeData();
 procedure g_Game_Update();
 procedure g_Game_PreUpdate();
 procedure g_Game_Quit();
-procedure g_Game_SetupScreenSize();
 function  g_Game_ModeToText(Mode: Byte): string;
 function  g_Game_TextToMode(Mode: string): Byte;
 procedure g_Game_ExecuteEvent(Name: String);
@@ -116,7 +118,6 @@ function  g_Game_GetNextMap(): String;
 procedure g_Game_NextLevel();
 procedure g_Game_Pause(Enable: Boolean);
 procedure g_Game_HolmesPause(Enable: Boolean);
-procedure g_Game_InGameMenu(Show: Boolean);
 function  g_Game_IsWatchedPlayer(UID: Word): Boolean;
 function  g_Game_IsWatchedTeam(Team: Byte): Boolean;
 procedure g_Game_Message(Msg: String; Time: Word);
@@ -131,7 +132,6 @@ procedure g_Game_Announce_KillCombo(Param: Integer);
 procedure g_Game_Announce_BodyKill(SpawnerUID: Word);
 procedure g_Game_StartVote(Command, Initiator: string);
 procedure g_Game_CheckVote;
-procedure g_TakeScreenShot(Filename: string = '');
 procedure g_FatalError(Text: String);
 procedure g_SimpleError(Text: String);
 function  g_Game_IsTestMap(): Boolean;
@@ -143,26 +143,27 @@ procedure GameCommands(P: SSArray);
 procedure GameCheats(P: SSArray);
 procedure DebugCommands(P: SSArray);
 procedure g_Game_Process_Params;
-procedure g_Game_SetLoadingText(Text: String; Max: Integer; reWrite: Boolean);
-procedure g_Game_StepLoading(Value: Integer = -1);
-procedure g_Game_ClearLoading();
 procedure g_Game_SetDebugMode();
 
 function IsActivePlayer(p: TPlayer): Boolean;
 function GetActivePlayerID_Next(Skip: Integer = -1): Integer;
 procedure SortGameStat(var stat: TPlayerStatArray);
 
-procedure KeyPress (K: Word);
-procedure CharPress (C: AnsiChar);
+
+{$IFDEF ENABLE_MENU}
+  procedure g_Game_InGameMenu(Show: Boolean);
+{$ENDIF}
+{$IFDEF ENABLE_SYSTEM}
+  procedure CharPress (C: AnsiChar);
+{$ENDIF}
+
+  procedure KeyPress (K: Word);
 
 { procedure SetWinPause(Enable: Boolean); }
 
 const
   GAME_TICK = 28;
 
-  LOADING_SHOW_STEP = 100;
-  LOADING_INTERLINE = 20;
-
   GT_NONE   = 0;
   GT_SINGLE = 1;
   GT_CUSTOM = 2;
@@ -176,8 +177,6 @@ const
   GM_COOP = 4;
   GM_SINGLE = 5;
 
-  MESSAGE_DIKEY = WM_USER + 1;
-
   EXIT_QUIT            = 1;
   EXIT_SIMPLE          = 2;
   EXIT_RESTART         = 3;
@@ -242,21 +241,18 @@ const
   STATFILE_VERSION = $03;
 
 var
-  gStdFont: DWORD;
   gGameSettings: TGameSettings;
   gPlayer1Settings: TPlayerSettings;
   gPlayer2Settings: TPlayerSettings;
   gGameOn: Boolean;
   gPlayerScreenSize: TDFPoint;
-  gPlayer1ScreenCoord: TDFPoint;
-  gPlayer2ScreenCoord: TDFPoint;
   gPlayer1: TPlayer = nil;
   gPlayer2: TPlayer = nil;
-  gPlayerDrawn: TPlayer = nil;
   gTime: LongWord;
   gLerpFactor: Single = 1.0;
   gSwitchGameMode: Byte = GM_DM;
   gHearPoint1, gHearPoint2: THearPoint;
+  gMaxDist: Integer = 1; // for sound
   gSoundEffectsDF: Boolean = False;
   gSoundTriggerTime: Word = 0;
   gAnnouncer: Integer = ANNOUNCE_NONE;
@@ -316,13 +312,8 @@ var
   gRC_FullScreen, gRC_Maximized: Boolean;
   gLanguageChange: Boolean = False;
   gDebugMode: Boolean = False;
-  g_debug_Sounds: Boolean = False;
-  g_debug_Frames: Boolean = False;
-  g_debug_WinMsgs: Boolean = False;
   g_debug_MonsterOff: Boolean = False;
   g_debug_BotAIOff: Byte = 0;
-  g_debug_HealthBar: Boolean = False;
-  g_Debug_Player: Boolean = False;
   gCoopMonstersKilled: Word = 0;
   gCoopSecretsFound: Word = 0;
   gCoopTotalMonstersKilled: Word = 0;
@@ -411,15 +402,6 @@ function gPause (): Boolean; inline;
       TotalSecrets: Integer;
     end;
 
-    TLoadingStat = record
-      CurValue: Integer;
-      MaxValue: Integer;
-      ShowCount: Integer;
-      Msgs: Array of String;
-      NextMsg: Word;
-      PBarWasHere: Boolean; // did we draw a progress bar for this message?
-    end;
-
     TDynLight = record
       x, y, radius: Integer;
       r, g, b, a: Single;
@@ -432,8 +414,6 @@ function gPause (): Boolean; inline;
     StatShotDone: Boolean;
     StatFilename: string = ''; // used by stat screenshot to save with the same name as the csv
     SingleStat: TEndSingleGameStat;
-    hasPBarGfx: Boolean;
-    LoadingStat: TLoadingStat;
     MessageText: String;
     IsDrawStat: Boolean;
     EndingGameCounter: Byte;
@@ -441,20 +421,42 @@ function gPause (): Boolean; inline;
     g_playerLight: Boolean;
     g_dynLights: array of TDynLight = nil;
     g_dynLightCount: Integer = 0;
+    EndPicPath: AnsiString; // full path, used by render
 
 implementation
 
 uses
-{$IFDEF ENABLE_HOLMES}
-  g_holmes,
-{$ENDIF}
-  e_res, g_window, g_menu, r_render, r_textures, r_animations, r_gfx, r_map,
-  e_input, e_log, g_console, r_console, g_items, g_map, g_panel,
-  g_playermodel, g_gfx, g_options, Math,
+  {$IFDEF ENABLE_HOLMES}
+    g_holmes,
+  {$ENDIF}
+  {$IFDEF ENABLE_MENU}
+    g_menu,
+  {$ENDIF}
+  {$IFDEF ENABLE_GFX}
+    g_gfx,
+  {$ENDIF}
+  {$IFDEF ENABLE_GIBS}
+    g_gibs,
+  {$ENDIF}
+  {$IFDEF ENABLE_SHELLS}
+    g_shells,
+  {$ENDIF}
+  {$IFDEF ENABLE_CORPSES}
+    g_corpses,
+  {$ENDIF}
+  {$IFDEF ENABLE_RENDER}
+    r_render,
+  {$ENDIF}
+  {$IFDEF ENABLE_SYSTEM}
+    g_system,
+  {$ENDIF}
+  e_res, g_window,
+  e_input, e_log, g_console, g_items, g_map, g_panel,
+  g_playermodel, g_options, Math,
   g_triggers, g_monsters, e_sound, CONFIG,
   g_language, g_net, g_phys,
   ENet, e_msg, g_netmsg, g_netmaster,
-  sfs, wadreader, g_system, r_playermodel;
+  sfs, wadreader;
 
   var
     charbuff: packed array [0..15] of AnsiChar = (
@@ -696,13 +698,10 @@ Cheated:
 end;
 
 
+{$IFDEF ENABLE_MENU}
 procedure KeyPress (K: Word);
-{$IFNDEF HEADLESS}
-var
-  Msg: g_gui.TMessage;
-{$ENDIF}
+  var Msg: g_gui.TMessage;
 begin
-{$IFNDEF HEADLESS}
   case K of
     VK_ESCAPE: // <Esc>:
       begin
@@ -775,31 +774,48 @@ begin
         end;
       end;
   end;
-{$ENDIF}
 end;
-
-procedure CharPress (C: AnsiChar);
-var
-  Msg: g_gui.TMessage;
-  a: Integer;
-begin
-  if gConsoleShow or gChatShow then
-  begin
-    g_Console_Char(C)
-  end
-  else if (g_ActiveWindow <> nil) then
+{$ELSE}
+  procedure KeyPress (K: Word);
   begin
-    Msg.Msg := WM_CHAR;
-    Msg.WParam := Ord(C);
-    g_ActiveWindow.OnMessage(Msg);
-  end
-  else
+    gJustChatted := False;
+    if gConsoleShow or gChatShow then
+    begin
+      g_Console_Control(K);
+    end
+  end;
+{$ENDIF}
+
+{$IFDEF ENABLE_SYSTEM}
+  procedure CharPress (C: AnsiChar);
+    {$IFDEF ENABLE_MENU}
+      var Msg: g_gui.TMessage;
+    {$ENDIF}
+    var a: Integer;
   begin
-    for a := 0 to 14 do charbuff[a] := charbuff[a+1];
-    charbuff[15] := upcase1251(C);
-    Cheat();
+    if gConsoleShow or gChatShow then
+    begin
+      g_Console_Char(C);
+    end
+    {$IFDEF ENABLE_MENU}
+      else if g_ActiveWindow <> nil then
+      begin
+        Msg.Msg := WM_CHAR;
+        Msg.WParam := Ord(C);
+        g_ActiveWindow.OnMessage(Msg);
+      end
+    {$ENDIF}
+    else
+    begin
+      for a := 0 to 14 do
+      begin
+        charbuff[a] := charbuff[a + 1];
+      end;
+      charbuff[15] := upcase1251(C);
+      Cheat;
+    end;
   end;
-end;
+{$ENDIF}
 
 
 // ////////////////////////////////////////////////////////////////////////// //
@@ -898,7 +914,6 @@ var
   UPSTime: LongWord;
   DataLoaded: Boolean = False;
   MessageTime: Word;
-  MessageLineLength: Integer = 80;
   MapList: SSArray = nil;
   MapIndex: Integer = -1;
   InterReadyTime: Integer = -1;
@@ -907,22 +922,7 @@ var
     info: TMegaWADInfo;
     endpic: String;
     endmus: String;
-    res: record
-      text: Array of ShortString;
-      anim: Array of ShortString;
-      pic: Array of ShortString;
-      mus: Array of ShortString;
-    end;
-    triggers: Array of record
-      event: ShortString;
-      actions: Array of record
-        action, p1, p2: Integer;
-      end;
-    end;
-    cur_trigger: Integer;
-    cur_action: Integer;
   end;
-  //InterPic: String;
   InterText: record
     lines: SSArray;
     img: String;
@@ -1026,13 +1026,8 @@ end;
 
 procedure ClearDebugCvars();
 begin
-  g_debug_Sounds := False;
-  g_debug_Frames := False;
-  g_debug_WinMsgs := False;
   g_debug_MonsterOff := False;
   g_debug_BotAIOff := 0;
-  g_debug_HealthBar := False;
-  g_Debug_Player := False;
 end;
 
 function g_Game_ModeToText(Mode: Byte): string;
@@ -1123,37 +1118,20 @@ begin
   FreeMem(p);
 end;
 
-procedure g_Game_FreeWAD();
-var
-  a: Integer;
-begin
-  for a := 0 to High(MegaWAD.res.pic) do
-    if MegaWAD.res.pic[a] <> '' then
-      g_Texture_Delete(MegaWAD.res.pic[a]);
-
-  for a := 0 to High(MegaWAD.res.mus) do
-    if MegaWAD.res.mus[a] <> '' then
-      g_Sound_Delete(MegaWAD.res.mus[a]);
-
-  MegaWAD.res.pic := nil;
-  MegaWAD.res.text := nil;
-  MegaWAD.res.anim := nil;
-  MegaWAD.res.mus := nil;
-  MegaWAD.triggers := nil;
-
-  g_Texture_Delete('TEXTURE_endpic');
-  g_Sound_Delete('MUSIC_endmus');
-
-  ZeroMemory(@MegaWAD, SizeOf(MegaWAD));
-  gGameSettings.WAD := '';
-end;
+  procedure g_Game_FreeWAD;
+  begin
+    EndPicPath := '';
+    g_Sound_Delete('MUSIC_endmus');
+    ZeroMemory(@MegaWAD, SizeOf(MegaWAD));
+    gGameSettings.WAD := '';
+  end;
 
 procedure g_Game_LoadWAD(WAD: string);
 var
   w: TWADFile;
   cfg: TConfig;
   p: Pointer;
-  {b, }len: Integer;
+  len: Integer;
   s: AnsiString;
 begin
   g_Game_FreeWAD();
@@ -1174,38 +1152,11 @@ begin
 
   cfg := TConfig.CreateMem(p, len);
 
- {b := 1;
- while True do
- begin
-  s := cfg.ReadStr('pic', 'pic'+IntToStr(b), '');
-  if s = '' then Break;
-  b := b+1;
-
-  SetLength(MegaWAD.res.pic, Length(MegaWAD.res.pic)+1);
-  MegaWAD.res.pic[High(MegaWAD.res.pic)] := s;
-
-  g_Texture_CreateWADEx(s, s);
- end;
-
- b := 1;
- while True do
- begin
-  s := cfg.ReadStr('mus', 'mus'+IntToStr(b), '');
-  if s = '' then Break;
-  b := b+1;
-
-  SetLength(MegaWAD.res.mus, Length(MegaWAD.res.mus)+1);
-  MegaWAD.res.mus[High(MegaWAD.res.mus)] := s;
-
-  g_Music_CreateWADEx(s, s);
- end;}
-
+  EndPicPath := '';
   MegaWAD.endpic := cfg.ReadStr('megawad', 'endpic', '');
   if MegaWAD.endpic <> '' then
-  begin
-    s := e_GetResourcePath(WadDirs, MegaWAD.endpic, WAD);
-    g_Texture_CreateWADEx('TEXTURE_endpic', s, gTextureFilter);
-  end;
+    EndPicPath := e_GetResourcePath(WadDirs, MegaWAD.endpic, WAD);
+
   MegaWAD.endmus := cfg.ReadStr('megawad', 'endmus', 'Standart.wad:D2DMUS\КОНЕЦ');
   if MegaWAD.endmus <> '' then
   begin
@@ -1308,7 +1259,10 @@ begin
   MessageText := '';
 
   EndingGameCounter := 0;
+
+{$IFDEF ENABLE_MENU}
   g_ActiveWindow := nil;
+{$ENDIF}
 
   gLMSRespawn := LMS_RESPAWN_NONE;
   gLMSRespawnTime := 0;
@@ -1317,20 +1271,23 @@ begin
     EXIT_SIMPLE: // Выход через меню или конец теста
       begin
         g_Game_Free();
-
         if gMapOnce  then
-          begin // Это был тест
-            g_Game_Quit();
-          end
+        begin // Это был тест
+          g_Game_Quit();
+        end
         else
-          begin // Выход в главное меню
+        begin // Выход в главное меню
+          {$IFDEF DISABLE_MENU}
+            gState := STATE_MENU; // ???
+          {$ELSE}
             gMusic.SetByName('MUSIC_MENU');
             gMusic.Play();
             if gState <> STATE_SLIST then
             begin
               g_GUI_ShowWindow('MainMenu');
               gState := STATE_MENU;
-            end else
+            end
+            else
             begin
               // Обновляем список серверов
               slReturnPressed := True;
@@ -1343,9 +1300,9 @@ begin
                 slWaitStr := _lc[I_NET_SLIST_ERROR];
               g_Serverlist_GenerateTable(slCurrent, slTable);
             end;
-
-            g_Game_ExecuteEvent('ongameend');
-          end;
+          {$ENDIF}
+          g_Game_ExecuteEvent('ongameend');
+        end;
       end;
 
     EXIT_RESTART: // Начать уровень сначала
@@ -1468,21 +1425,6 @@ begin
   sfsGCDisable(); // temporary disable removing of temporary volumes
 
   try
-    g_Texture_CreateWADEx('MENU_BACKGROUND', GameWAD+':TEXTURES\TITLE', gTextureFilter);
-    g_Texture_CreateWADEx('INTER', GameWAD+':TEXTURES\INTER', gTextureFilter);
-    g_Texture_CreateWADEx('ENDGAME_EN', GameWAD+':TEXTURES\ENDGAME_EN', gTextureFilter);
-    g_Texture_CreateWADEx('ENDGAME_RU', GameWAD+':TEXTURES\ENDGAME_RU', gTextureFilter);
-
-    LoadStdFont('STDTXT', 'STDFONT', gStdFont);
-    LoadFont('MENUTXT', 'MENUFONT', gMenuFont);
-    LoadFont('SMALLTXT', 'SMALLFONT', gMenuSmallFont);
-
-    g_Game_ClearLoading();
-    g_Game_SetLoadingText(Format('Doom 2D: Forever %s', [GAME_VERSION]), 0, False);
-    g_Game_SetLoadingText('', 0, False);
-
-//    g_Game_SetLoadingText(_lc[I_LOAD_MODELS], 0, False);
-
     gGameOn := false;
     gPauseMain := false;
     gPauseHolmes := false;
@@ -1490,7 +1432,6 @@ begin
 
     {e_MouseInfo.Accel := 1.0;}
 
-    g_Game_SetLoadingText(_lc[I_LOAD_GAME_DATA], 0, False);
     g_Game_LoadData();
 
     g_Game_SetLoadingText(_lc[I_LOAD_MUSIC], 0, False);
@@ -1526,7 +1467,16 @@ begin
 
   g_Map_Free(freeTextures);
   g_Player_Free();
-  g_Player_RemoveAllCorpses();
+
+  {$IFDEF ENABLE_GIBS}
+    g_Gibs_RemoveAll;
+  {$ENDIF}
+  {$IFDEF ENABLE_SHELLS}
+    g_Shells_RemoveAll;
+  {$ENDIF}
+  {$IFDEF ENABLE_CORPSES}
+    g_Corpses_RemoveAll;
+  {$ENDIF}
 
   gGameSettings.GameType := GT_NONE;
   if gGameSettings.GameMode = GM_SINGLE then
@@ -1728,6 +1678,7 @@ begin
     end
   end;
 
+{$IFDEF ENABLE_MENU}
   // HACK: add dynlight here
   if gwin_k8_enable_light_experiments then
   begin
@@ -1742,6 +1693,7 @@ begin
   end;
 
   if gwin_has_stencil and g_playerLight then g_AddDynLight(plr.GameX+32, plr.GameY+40, 128, 1, 1, 0, 0.6);
+{$ENDIF}
 end;
 
 // HACK: don't have a "key was pressed" function
@@ -1763,13 +1715,69 @@ begin
   g_Weapon_PreUpdate();
 end;
 
+  procedure g_Game_SetupHearPoints;
+    var p1, p2: TPlayer; a, b: Integer;
+  begin
+    p1 := nil;
+    p2 := nil;
+    gHearPoint1.Active := false;
+    gHearPoint2.Active := false;
+    if gSpectMode = SPECT_MAPVIEW then
+    begin
+      // TODO something better (render dependency)
+      gHearPoint1.Active := true;
+      gHearPoint1.Coords.X := gSpectX + gScreenWidth div 2;
+      gHearPoint1.Coords.Y := gSpectY + gScreenHeight div 2;
+    end
+    else if gSpectMode = SPECT_PLAYERS then
+    begin
+      p1 := g_Player_Get(gSpectPID1);
+      if gSpectViewTwo then
+        p2 := g_Player_Get(gSpectPID2);
+    end
+    else if gSpectMode = SPECT_NONE then
+    begin
+      p1 := gPlayer1;
+      p2 := gPlayer2;
+    end;
+    if p1 <> nil then
+    begin
+      gHearPoint1.Active := true;
+      gHearPoint1.Coords.X := p1.obj.x + p1.obj.rect.width div 2;
+      gHearPoint1.Coords.Y := p1.obj.y + p1.obj.rect.height div 2;
+    end;
+    if (p2 <> nil) and (p1 <> p2) then
+    begin
+      gHearPoint2.Active := true;
+      gHearPoint2.Coords.X := p2.obj.x + p2.obj.rect.width div 2;
+      gHearPoint2.Coords.Y := p2.obj.y + p2.obj.rect.height div 2;
+    end;
+    // TODO something better (render dependency)
+    if (p1 <> nil) and (p2 <> nil) then
+    begin
+      gPlayerScreenSize.X := gScreenWidth - 196;
+      gPlayerScreenSize.Y := gScreenHeight div 2;
+    end
+    else
+    begin
+      gPlayerScreenSize.X := gScreenWidth - 196;
+      gPlayerScreenSize.Y := gScreenHeight;
+    end;
+    // sound distance
+    if gMapInfo.Height > gPlayerScreenSize.Y then a := gMapInfo.Height - gPlayerScreenSize.Y else a := gMapInfo.Height;
+    if gMapInfo.Width > gPlayerScreenSize.X then b := gMapInfo.Width - gPlayerScreenSize.X else b := gMapInfo.Width;
+    gMaxDist := Trunc(Hypot(a, b));
+  end;
+
 procedure g_Game_Update();
-var
-  Msg: g_gui.TMessage;
-  Time: Int64;
-  a: Byte;
-  w: Word;
-  i, b: Integer;
+  var
+    {$IFDEF ENABLE_MENU}
+      Msg: g_gui.TMessage;
+      w: Word;
+    {$ENDIF}
+    Time: Int64;
+    a: Byte;
+    i, b: Integer;
 
   function sendMonsPos (mon: TMonster): Boolean;
   begin
@@ -1808,6 +1816,8 @@ var
 
 var
   reliableUpdate: Boolean;
+  rSpectX0, rSpectY0: Integer;
+  rSpectX1, rSpectY1: Integer;
 begin
   g_ResetDynlights();
   framePool.reset();
@@ -1827,7 +1837,6 @@ begin
   // no need to, as we'll do it in event handler
 
 // Обновляем консоль (движение и сообщения):
-  r_Console_Update;
   g_Console_Update();
 
   if (NetMode = NET_NONE) and (g_Game_IsNet) and (gGameOn or (gState in [STATE_FOLD, STATE_INTERCUSTOM])) then
@@ -1867,7 +1876,9 @@ begin
               e_KeyPressed(JOY2_ATTACK) or e_KeyPressed(JOY3_ATTACK)
             )
             and (not gJustChatted) and (not gConsoleShow) and (not gChatShow)
+{$IFDEF ENABLE_MENU}
             and (g_ActiveWindow = nil)
+{$ENDIF}
           )
           or (g_Game_IsNet and ((gInterTime > gInterEndTime) or ((gInterReadyCount >= NetClientCount) and (NetClientCount > 0))))
         )
@@ -1886,9 +1897,11 @@ begin
               begin
               // Выход в главное меню:
                 g_Game_Free;
+{$IFDEF ENABLE_MENU}
                 g_GUI_ShowWindow('MainMenu');
                 gMusic.SetByName('MUSIC_MENU');
                 gMusic.Play();
+{$ENDIF}
                 gState := STATE_MENU;
               end else
               begin
@@ -1914,7 +1927,9 @@ begin
             e_KeyPressed(JOY2_ATTACK) or e_KeyPressed(JOY3_ATTACK)
           )
           and (not gJustChatted) and (not gConsoleShow) and (not gChatShow)
+{$IFDEF ENABLE_MENU}
           and (g_ActiveWindow = nil)
+{$ENDIF}
         )
         then
         begin
@@ -1975,7 +1990,22 @@ begin
 
 // Статистика по Tab:
   if gGameOn then
+  begin
     IsDrawStat := (not gConsoleShow) and (not gChatShow) and (gGameSettings.GameType <> GT_SINGLE) and g_Console_Action(ACTION_SCORES);
+  end
+  else
+  begin
+    if g_Console_Action(ACTION_SCORES) then
+    begin
+      if not gStatsPressed then
+      begin
+        gStatsOff := not gStatsOff;
+        gStatsPressed := True;
+      end;
+    end
+    else
+      gStatsPressed := False;
+  end;
 
 // Игра идет:
   if gGameOn and not gPause and (gState <> STATE_FOLD) then
@@ -2048,7 +2078,11 @@ begin
     // Обрабатываем клавиши игроков:
       if gPlayer1 <> nil then gPlayer1.ReleaseKeys();
       if gPlayer2 <> nil then gPlayer2.ReleaseKeys();
+{$IFDEF DISABLE_MENU}
+      if (not gConsoleShow) and (not gChatShow) then
+{$ELSE}
       if (not gConsoleShow) and (not gChatShow) and (g_ActiveWindow = nil) then
+{$ENDIF}
       begin
         ProcessPlayerControls(gPlayer1, 0, P1MoveButton);
         ProcessPlayerControls(gPlayer2, 1, P2MoveButton);
@@ -2060,9 +2094,21 @@ begin
       // process weapon switch queue
     end; // if server
 
-  // Наблюдатель
-    if (gPlayer1 = nil) and (gPlayer2 = nil) and
-       (not gConsoleShow) and (not gChatShow) and (g_ActiveWindow = nil) then
+  // Spectator
+
+    {$IFDEF ENABLE_RENDER}
+      r_Render_GetSpectatorLimits(rSpectX0, rSpectY0, rSpectX1, rSpectY1);
+    {$ELSE}
+      rSpectX0 := 0; rSpectY0 := 0;
+      rSpectX1 := gMapInfo.Width - 1; rSpectY1 := gMapInfo.Height - 1;
+    {$ENDIF}
+
+    if (gPlayer1 = nil) and (gPlayer2 = nil)
+      and (not gConsoleShow) and (not gChatShow)
+{$IFDEF ENABLE_MENU}
+      and (g_ActiveWindow = nil)
+{$ENDIF}
+    then
     begin
       if not gSpectKeyPress then
       begin
@@ -2080,14 +2126,10 @@ begin
         if (gSpectMode = SPECT_MAPVIEW)
            and (not gSpectAuto) then
         begin
-          if gPlayerAction[0, ACTION_MOVELEFT] then
-            gSpectX := Max(gSpectX - gSpectStep, 0);
-          if gPlayerAction[0, ACTION_MOVERIGHT] then
-            gSpectX := Min(gSpectX + gSpectStep, gMapInfo.Width - gScreenWidth);
-          if gPlayerAction[0, ACTION_LOOKUP] then
-            gSpectY := Max(gSpectY - gSpectStep, 0);
-          if gPlayerAction[0, ACTION_LOOKDOWN] then
-            gSpectY := Min(gSpectY + gSpectStep, gMapInfo.Height - gScreenHeight);
+          if gPlayerAction[0, ACTION_MOVELEFT]  then gSpectX := gSpectX - gSpectStep;
+          if gPlayerAction[0, ACTION_MOVERIGHT] then gSpectX := gSpectX + gSpectStep;
+          if gPlayerAction[0, ACTION_LOOKUP]    then gSpectY := gSpectY - gSpectStep;
+          if gPlayerAction[0, ACTION_LOOKDOWN]  then gSpectY := gSpectY + gSpectStep;
           if gWeaponAction[0, WP_PREV] then
           begin
             // decrease step
@@ -2172,12 +2214,12 @@ begin
       begin
         if gSpectMode = SPECT_MAPVIEW then
         begin
-          i := Min(Max(gSpectX + gSpectAutoStepX, 0), gMapInfo.Width - gScreenWidth);
+          i := Min(Max(gSpectX + gSpectAutoStepX, rSpectX0), rSpectX1);
           if i = gSpectX then
             gSpectAutoNext := gTime
           else
             gSpectX := i;
-          i := Min(Max(gSpectY + gSpectAutoStepY, 0), gMapInfo.Height - gScreenHeight);
+          i := Min(Max(gSpectY + gSpectAutoStepY, rSpectY0), rSpectY1);
           if i = gSpectY then
             gSpectAutoNext := gTime
           else
@@ -2191,15 +2233,15 @@ begin
             case gSpectMode of
               SPECT_MAPVIEW:
               begin
-                gSpectX := Random(gMapInfo.Width - gScreenWidth);
-                gSpectY := Random(gMapInfo.Height - gScreenHeight);
+                gSpectX := rSpectX0 + Random(rSpectX1 - rSpectX0);
+                gSpectY := rSpectY0 + Random(rSpectY1 - rSpectY0);
                 gSpectAutoStepX := Random(9) - 4;
                 gSpectAutoStepY := Random(9) - 4;
-                if ((gSpectX < 800) and (gSpectAutoStepX < 0)) or
-                   ((gSpectX > gMapInfo.Width - gScreenWidth - 800) and (gSpectAutoStepX > 0)) then
+                if ((gSpectX < rSpectX0) and (gSpectAutoStepX < 0)) or
+                   ((gSpectX > rSpectX1) and (gSpectAutoStepX > 0)) then
                   gSpectAutoStepX := gSpectAutoStepX * -1;
-                if ((gSpectY < 800) and (gSpectAutoStepY < 0)) or
-                   ((gSpectY > gMapInfo.Height - gScreenHeight - 800) and (gSpectAutoStepY > 0)) then
+                if ((gSpectY < rSpectY0) and (gSpectAutoStepY < 0)) or
+                   ((gSpectY > rSpectY1) and (gSpectAutoStepY > 0)) then
                   gSpectAutoStepY := gSpectAutoStepY * -1;
               end;
               SPECT_PLAYERS:
@@ -2215,18 +2257,56 @@ begin
           end;
         end;
       end;
+
+      if gSpectMode = SPECT_MAPVIEW then
+      begin
+        gSpectX := Max(gSpectX, rSpectX0);
+        gSpectX := Min(gSpectX, rSpectX1);
+        gSpectY := Max(gSpectY, rSpectY0);
+        gSpectY := Min(gSpectY, rSpectY1);
+      end;
     end;
 
+    (* spectator state check from render *)
+
+    if (gPlayer1 = nil) and (gPlayer2 = nil) then
+    begin
+      (* no local players -> automatically enable to spectator mode *)
+      if gSpectMode = SPECT_NONE then gSpectMode := SPECT_STATS;
+    end
+    else
+    begin
+      (* at least one local player -> automatically disable spectator mode *)
+      gSpectMode := SPECT_NONE;
+    end;
+
+    if IsActivePlayer(g_Player_Get(gSpectPID1)) = false then
+      gSpectPID1 := GetActivePlayerID_Next();
+
+    if IsActivePlayer(g_Player_Get(gSpectPID2)) = false then
+      gSpectPID2 := GetActivePlayerID_Next();
+
+    g_Game_SetupHearPoints;
+
   // Обновляем все остальное:
     g_Map_Update();
     g_Items_Update();
     g_Triggers_Update();
     g_Weapon_Update();
     g_Monsters_Update();
-    g_GFX_Update();
-    r_GFX_Update;
+    {$IFDEF ENABLE_GFX}
+      g_GFX_Update;
+    {$ENDIF}
     g_Player_UpdateAll();
-    g_Player_UpdatePhysicalObjects();
+    {$IFDEF ENABLE_GIBS}
+      g_Gibs_Update;
+    {$ENDIF}
+    {$IFDEF ENABLE_CORPSES}
+      g_Corpses_Update;
+    {$ENDIF}
+    {$IFDEF ENABLE_SHELLS}
+      g_Shells_Update;
+    {$ENDIF}
 
     // server: send newly spawned monsters unconditionally
     if (gGameSettings.GameType = GT_SERVER) then
@@ -2317,6 +2397,7 @@ begin
   end; // if gameOn ...
 
 // Активно окно интерфейса - передаем клавиши ему:
+{$IFDEF ENABLE_MENU}
   if g_ActiveWindow <> nil then
   begin
     w := e_GetFirstKeyPressed();
@@ -2335,8 +2416,10 @@ begin
   // Нужно сменить разрешение:
     if gResolutionChange then
     begin
-      e_WriteLog('Changing resolution', TMsgType.Notify);
-      r_Render_Apply;
+      {$IFDEF ENABLE_RENDER}
+        e_WriteLog('Changing resolution', TMsgType.Notify);
+        r_Render_Apply;
+      {$ENDIF}
       gResolutionChange := False;
       g_ActiveWindow := nil;
     end;
@@ -2347,9 +2430,7 @@ begin
       //e_WriteLog('Read language file', MSG_NOTIFY);
       //g_Language_Load(DataDir + gLanguage + '.txt');
       g_Language_Set(gLanguage);
-{$IFNDEF HEADLESS}
       g_Menu_Reset();
-{$ENDIF}
       gLanguageChange := False;
     end;
   end;
@@ -2362,6 +2443,7 @@ begin
   begin
     KeyPress(IK_F10);
   end;
+{$ENDIF}
 
   Time := GetTickCount64() {div 1000};
 
@@ -2468,60 +2550,12 @@ begin
 end;
 
 procedure g_Game_LoadData();
-var
-  wl, hl: Integer;
-  wr, hr: Integer;
-  wb, hb: Integer;
-  wm, hm: Integer;
 begin
   if DataLoaded then Exit;
 
   e_WriteLog('Loading game data...', TMsgType.Notify);
+  g_Game_SetLoadingText(_lc[I_LOAD_GAME_DATA], 0, False);
 
-  g_Texture_CreateWADEx('NOTEXTURE', GameWAD+':TEXTURES\NOTEXTURE');
-  g_Texture_CreateWADEx('TEXTURE_PLAYER_HUD', GameWAD+':TEXTURES\HUD');
-  g_Texture_CreateWADEx('TEXTURE_PLAYER_HUDAIR', GameWAD+':TEXTURES\AIRBAR');
-  g_Texture_CreateWADEx('TEXTURE_PLAYER_HUDJET', GameWAD+':TEXTURES\JETBAR');
-  g_Texture_CreateWADEx('TEXTURE_PLAYER_HUDBG', GameWAD+':TEXTURES\HUDBG');
-  g_Texture_CreateWADEx('TEXTURE_PLAYER_ARMORHUD', GameWAD+':TEXTURES\ARMORHUD');
-  g_Texture_CreateWADEx('TEXTURE_PLAYER_REDFLAG', GameWAD+':TEXTURES\FLAGHUD_R_BASE');
-  g_Texture_CreateWADEx('TEXTURE_PLAYER_REDFLAG_S', GameWAD+':TEXTURES\FLAGHUD_R_STOLEN');
-  g_Texture_CreateWADEx('TEXTURE_PLAYER_REDFLAG_D', GameWAD+':TEXTURES\FLAGHUD_R_DROP');
-  g_Texture_CreateWADEx('TEXTURE_PLAYER_BLUEFLAG', GameWAD+':TEXTURES\FLAGHUD_B_BASE');
-  g_Texture_CreateWADEx('TEXTURE_PLAYER_BLUEFLAG_S', GameWAD+':TEXTURES\FLAGHUD_B_STOLEN');
-  g_Texture_CreateWADEx('TEXTURE_PLAYER_BLUEFLAG_D', GameWAD+':TEXTURES\FLAGHUD_B_DROP');
-  g_Texture_CreateWADEx('TEXTURE_PLAYER_TALKBUBBLE', GameWAD+':TEXTURES\TALKBUBBLE');
-  g_Texture_CreateWADEx('TEXTURE_PLAYER_INVULPENTA', GameWAD+':TEXTURES\PENTA');
-  g_Texture_CreateWADEx('TEXTURE_PLAYER_INDICATOR', GameWAD+':TEXTURES\PLRIND');
-
-  hasPBarGfx := true;
-  if not g_Texture_CreateWADEx('UI_GFX_PBAR_LEFT', GameWAD+':TEXTURES\LLEFT') then hasPBarGfx := false;
-  if not g_Texture_CreateWADEx('UI_GFX_PBAR_MARKER', GameWAD+':TEXTURES\LMARKER') then hasPBarGfx := false;
-  if not g_Texture_CreateWADEx('UI_GFX_PBAR_MIDDLE', GameWAD+':TEXTURES\LMIDDLE') then hasPBarGfx := false;
-  if not g_Texture_CreateWADEx('UI_GFX_PBAR_RIGHT', GameWAD+':TEXTURES\LRIGHT') then hasPBarGfx := false;
-
-  if hasPBarGfx then
-  begin
-    g_Texture_GetSize('UI_GFX_PBAR_LEFT', wl, hl);
-    g_Texture_GetSize('UI_GFX_PBAR_RIGHT', wr, hr);
-    g_Texture_GetSize('UI_GFX_PBAR_MIDDLE', wb, hb);
-    g_Texture_GetSize('UI_GFX_PBAR_MARKER', wm, hm);
-    if (wl > 0) and (hl > 0) and (wr > 0) and (hr = hl) and (wb > 0) and (hb = hl) and (wm > 0) and (hm > 0) and (hm <= hl) then
-    begin
-      // yay!
-    end
-    else
-    begin
-      hasPBarGfx := false;
-    end;
-  end;
-
-  g_Frames_CreateWAD(nil, 'FRAMES_PUNCH', GameWAD+':WEAPONS\PUNCH', 64, 64, 4, False);
-  g_Frames_CreateWAD(nil, 'FRAMES_PUNCH_UP', GameWAD+':WEAPONS\PUNCH_UP', 64, 64, 4, False);
-  g_Frames_CreateWAD(nil, 'FRAMES_PUNCH_DN', GameWAD+':WEAPONS\PUNCH_DN', 64, 64, 4, False);
-  g_Frames_CreateWAD(nil, 'FRAMES_PUNCH_BERSERK', GameWAD+':WEAPONS\PUNCHB', 64, 64, 4, False);
-  g_Frames_CreateWAD(nil, 'FRAMES_PUNCH_BERSERK_UP', GameWAD+':WEAPONS\PUNCHB_UP', 64, 64, 4, False);
-  g_Frames_CreateWAD(nil, 'FRAMES_PUNCH_BERSERK_DN', GameWAD+':WEAPONS\PUNCHB_DN', 64, 64, 4, False);
   g_Sound_CreateWADEx('SOUND_GAME_TELEPORT', GameWAD+':SOUNDS\TELEPORT');
   g_Sound_CreateWADEx('SOUND_GAME_NOTELEPORT', GameWAD+':SOUNDS\NOTELEPORT');
   g_Sound_CreateWADEx('SOUND_GAME_SECRET', GameWAD+':SOUNDS\SECRET');
@@ -2603,10 +2637,8 @@ begin
 
   g_Game_LoadChatSounds(GameWAD+':CHATSND\SNDCFG');
 
-  g_Game_SetLoadingText(_lc[I_LOAD_ITEMS_DATA], 0, False);
   g_Items_LoadData();
 
-  g_Game_SetLoadingText(_lc[I_LOAD_WEAPONS_DATA], 0, False);
   g_Weapon_LoadData();
 
   g_Monsters_LoadData();
@@ -2620,11 +2652,9 @@ begin
   gMusic.Free();
   g_Game_FreeData();
   g_PlayerModel_FreeData();
-  g_Texture_DeleteAll();
-  g_Frames_DeleteAll();
-{$IFNDEF HEADLESS}
-  //g_Menu_Free(); //k8: this segfaults after resolution change; who cares?
-{$ENDIF}
+  {$IFDEF ENABLE_MENU}
+    // g_Menu_Free(); //k8: this segfaults after resolution change; who cares?
+  {$ENDIF}
 
   if NetInitDone then g_Net_Free;
 
@@ -2633,7 +2663,10 @@ begin
     g_Game_DeleteTestMap();
 
   gExit := EXIT_QUIT;
-  sys_RequestQuit;
+
+  {$IFDEF ENABLE_SYSTEM}
+    sys_RequestQuit;
+  {$ENDIF}
 end;
 
 procedure g_Game_FreeData();
@@ -2646,24 +2679,6 @@ begin
 
   e_WriteLog('Releasing game data...', TMsgType.Notify);
 
-  g_Texture_Delete('NOTEXTURE');
-  g_Texture_Delete('TEXTURE_PLAYER_HUD');
-  g_Texture_Delete('TEXTURE_PLAYER_HUDBG');
-  g_Texture_Delete('TEXTURE_PLAYER_ARMORHUD');
-  g_Texture_Delete('TEXTURE_PLAYER_REDFLAG');
-  g_Texture_Delete('TEXTURE_PLAYER_REDFLAG_S');
-  g_Texture_Delete('TEXTURE_PLAYER_REDFLAG_D');
-  g_Texture_Delete('TEXTURE_PLAYER_BLUEFLAG');
-  g_Texture_Delete('TEXTURE_PLAYER_BLUEFLAG_S');
-  g_Texture_Delete('TEXTURE_PLAYER_BLUEFLAG_D');
-  g_Texture_Delete('TEXTURE_PLAYER_TALKBUBBLE');
-  g_Texture_Delete('TEXTURE_PLAYER_INVULPENTA');
-  g_Frames_DeleteByName('FRAMES_PUNCH');
-  g_Frames_DeleteByName('FRAMES_PUNCH_UP');
-  g_Frames_DeleteByName('FRAMES_PUNCH_DN');
-  g_Frames_DeleteByName('FRAMES_PUNCH_BERSERK');
-  g_Frames_DeleteByName('FRAMES_PUNCH_BERSERK_UP');
-  g_Frames_DeleteByName('FRAMES_PUNCH_BERSERK_DN');
   g_Sound_Delete('SOUND_GAME_TELEPORT');
   g_Sound_Delete('SOUND_GAME_NOTELEPORT');
   g_Sound_Delete('SOUND_GAME_SECRET');
@@ -2743,45 +2758,6 @@ begin
   e_WriteLog(Format(_lc[I_SIMPLE_ERROR], [Text]), TMsgType.Warning);
 end;
 
-procedure g_Game_SetupScreenSize();
-const
-  RES_FACTOR = 4.0 / 3.0;
-var
-  s: Single;
-  rf: Single;
-  bw, bh: Word;
-begin
-// Размер экранов игроков:
-  gPlayerScreenSize.X := gScreenWidth-196;
-  if (gPlayer1 <> nil) and (gPlayer2 <> nil) then
-    gPlayerScreenSize.Y := gScreenHeight div 2
-  else
-    gPlayerScreenSize.Y := gScreenHeight;
-
-// Размер заднего плана:
-  if BackID <> DWORD(-1) then
-  begin
-    s := SKY_STRETCH;
-    if (gScreenWidth*s > gMapInfo.Width) or
-       (gScreenHeight*s > gMapInfo.Height) then
-    begin
-      gBackSize.X := gScreenWidth;
-      gBackSize.Y := gScreenHeight;
-    end
-    else
-    begin
-      e_GetTextureSize(BackID, @bw, @bh);
-      rf := Single(bw) / Single(bh);
-      if (rf > RES_FACTOR) then bw := Round(Single(bh) * RES_FACTOR)
-      else if (rf < RES_FACTOR) then bh := Round(Single(bw) / RES_FACTOR);
-      s := Max(gScreenWidth / bw, gScreenHeight / bh);
-      if (s < 1.0) then s := 1.0;
-      gBackSize.X := Round(bw*s);
-      gBackSize.Y := Round(bh*s);
-    end;
-  end;
-end;
-
 procedure g_Game_AddPlayer(Team: Byte = TEAM_NONE);
 begin
   if ((not gGameOn) and (gState <> STATE_INTERCUSTOM))
@@ -2951,9 +2927,6 @@ begin
 
   g_Game_ExecuteEvent('ongamestart');
 
-// Установка размеров окон игроков:
-  g_Game_SetupScreenSize();
-
 // Создание первого игрока:
   gPlayer1 := g_Player_Get(g_Player_Create(gPlayer1Settings.Model,
                                            gPlayer1Settings.Color,
@@ -3043,9 +3016,6 @@ begin
 
   g_Game_ExecuteEvent('ongamestart');
 
-// Установка размеров окон игроков:
-  g_Game_SetupScreenSize();
-
 // Режим наблюдателя:
   if nPlayers = 0 then
   begin
@@ -3157,9 +3127,6 @@ begin
 
   g_Game_ExecuteEvent('ongamestart');
 
-// Установка размеров окна игрока
-  g_Game_SetupScreenSize();
-
 // Режим наблюдателя:
   if nPlayers = 0 then
   begin
@@ -3281,9 +3248,6 @@ begin
 
   g_Game_ExecuteEvent('ongamestart');
 
-// Установка размеров окон игроков:
-  g_Game_SetupScreenSize();
-
   NetState := NET_STATE_AUTH;
 
   g_Game_SetLoadingText(_lc[I_LOAD_CONNECT], 0, False);
@@ -3480,7 +3444,16 @@ var
   nws: AnsiString;
 begin
   g_Map_Free((Map <> gCurrentMapFileName) and (oldMapPath <> gCurrentMapFileName));
-  g_Player_RemoveAllCorpses();
+
+  {$IFDEF ENABLE_GIBS}
+    g_Gibs_RemoveAll;
+  {$ENDIF}
+  {$IFDEF ENABLE_SHELLS}
+    g_Shells_RemoveAll;
+  {$ENDIF}
+  {$IFDEF ENABLE_CORPSES}
+    g_Corpses_RemoveAll;
+  {$ENDIF}
 
   if (not g_Game_IsClient) and
      (gSwitchGameMode <> gGameSettings.GameMode) and
@@ -3549,14 +3522,19 @@ begin
   begin
     //result := g_Map_Load(gGameSettings.WAD + ':\' + ResName);
     result := g_Map_Load(NewWAD+':\'+ResName);
-    r_Map_LoadTextures;
   end;
   if Result then
     begin
+      {$IFDEF ENABLE_RENDER}
+        r_Render_LoadTextures;
+        r_Render_Reset;
+      {$ENDIF}
       g_Player_ResetAll(Force or gLastMap, gGameSettings.GameType = GT_SINGLE);
 
       gState := STATE_NONE;
-      g_ActiveWindow := nil;
+      {$IFDEF ENABLE_MENU}
+        g_ActiveWindow := nil;
+      {$ENDIF}
       gGameOn := True;
 
       DisableCheats();
@@ -3806,7 +3784,16 @@ begin
     Exit;
   end;
 
-  g_Player_RemoveAllCorpses;
+  {$IFDEF ENABLE_GIBS}
+    g_Gibs_RemoveAll;
+  {$ENDIF}
+  {$IFDEF ENABLE_SHELLS}
+    g_Shells_RemoveAll;
+  {$ENDIF}
+  {$IFDEF ENABLE_CORPSES}
+    g_Corpses_RemoveAll;
+  {$ENDIF}
+
   g_Game_Message(_lc[I_MESSAGE_LMS_START], 144);
   if g_Game_IsNet then
     MH_SEND_GameEvent(NET_EV_LMS_START);
@@ -4165,12 +4152,18 @@ begin
   begin
     if Length(p) = 2 then
     begin
-      a := Max(0, StrToIntDef(p[1], 0));
-      g_GFX_SetMax(a)
+      {$IFDEF ENABLE_GFX}
+        a := Max(0, StrToIntDef(p[1], 0));
+        g_GFX_SetMax(a)
+      {$ENDIF}
     end
     else if Length(p) = 1 then
     begin
-      e_LogWritefln('%s', [g_GFX_GetMax()])
+      {$IFDEF ENABLE_GFX}
+        e_LogWritefln('%s', [g_GFX_GetMax()])
+      {$ELSE}
+        e_LogWritefln('%s', [0])
+      {$ENDIF}
     end
     else
     begin
@@ -4181,12 +4174,18 @@ begin
   begin
     if Length(p) = 2 then
     begin
-      a := Max(0, StrToIntDef(p[1], 0));
-      g_Shells_SetMax(a)
+      {$IFDEF ENABLE_SHELLS}
+        a := Max(0, StrToIntDef(p[1], 0));
+        g_Shells_SetMax(a)
+      {$ENDIF}
     end
     else if Length(p) = 1 then
     begin
-      e_LogWritefln('%s', [g_Shells_GetMax()])
+      {$IFDEF ENABLE_SHELLS}
+        e_LogWritefln('%s', [g_Shells_GetMax()])
+      {$ELSE}
+        e_LogWritefln('%s', [0])
+      {$ENDIF}
     end
     else
     begin
@@ -4197,12 +4196,18 @@ begin
   begin
     if Length(p) = 2 then
     begin
-      a := Max(0, StrToIntDef(p[1], 0));
-      g_Gibs_SetMax(a)
+      {$IFDEF ENABLE_GIBS}
+        a := Max(0, StrToIntDef(p[1], 0));
+        g_Gibs_SetMax(a)
+      {$ENDIF}
     end
     else if Length(p) = 1 then
     begin
-      e_LogWritefln('%s', [g_Gibs_GetMax()])
+      {$IFDEF ENABLE_GIBS}
+        e_LogWritefln('%s', [g_Gibs_GetMax()])
+      {$ELSE}
+        e_LogWritefln('%s', [0])
+      {$ENDIF}
     end
     else
     begin
@@ -4213,12 +4218,18 @@ begin
   begin
     if Length(p) = 2 then
     begin
-      a := Max(0, StrToIntDef(p[1], 0));
-      g_Corpses_SetMax(a)
+      {$IFDEF ENABLE_CORPSES}
+        a := Max(0, StrToIntDef(p[1], 0));
+        g_Corpses_SetMax(a)
+      {$ENDIF}
     end
     else if Length(p) = 1 then
     begin
-      e_LogWritefln('%s', [g_Corpses_GetMax()])
+      {$IFDEF ENABLE_CORPSES}
+        e_LogWritefln('%s', [g_Corpses_GetMax()])
+      {$ELSE}
+        e_LogWritefln('%s', [0])
+      {$ENDIF}
     end
     else
     begin
@@ -4669,30 +4680,6 @@ begin
       g_Console_Add(Format('gScreenWidth = %d, gScreenHeight = %d', [gScreenWidth, gScreenHeight]));
       g_Console_Add(Format('gScreenWidth = %d, gScreenHeight = %d', [gScreenWidth, gScreenHeight]));
     end
-    else if cmd = 'd_sounds' then
-    begin
-      if (Length(P) > 1) and
-         ((P[1] = '1') or (P[1] = '0')) then
-        g_Debug_Sounds := (P[1][1] = '1');
-
-      g_Console_Add(Format('d_sounds is %d', [Byte(g_Debug_Sounds)]));
-    end
-    else if cmd = 'd_frames' then
-    begin
-      if (Length(P) > 1) and
-         ((P[1] = '1') or (P[1] = '0')) then
-        g_Debug_Frames := (P[1][1] = '1');
-
-      g_Console_Add(Format('d_frames is %d', [Byte(g_Debug_Frames)]));
-    end
-    else if cmd = 'd_winmsg' then
-    begin
-      if (Length(P) > 1) and
-         ((P[1] = '1') or (P[1] = '0')) then
-        g_Debug_WinMsgs := (P[1][1] = '1');
-
-      g_Console_Add(Format('d_winmsg is %d', [Byte(g_Debug_WinMsgs)]));
-    end
     else if (cmd = 'd_monoff') and not g_Game_IsNet then
     begin
       if (Length(P) > 1) and
@@ -4755,22 +4742,6 @@ begin
             end;
         end;
     end
-    else if (cmd = 'd_health') then
-    begin
-      if (Length(P) > 1) and
-         ((P[1] = '1') or (P[1] = '0')) then
-        g_debug_HealthBar := (P[1][1] = '1');
-
-      g_Console_Add(Format('d_health is %d', [Byte(g_debug_HealthBar)]));
-    end
-    else if (cmd = 'd_player') then
-    begin
-      if (Length(P) > 1) and
-         ((P[1] = '1') or (P[1] = '0')) then
-        g_debug_Player := (P[1][1] = '1');
-
-      g_Console_Add(Format(cmd + ' is %d', [Byte(g_Debug_Player)]));
-    end
     else if (cmd = 'd_mem') then
     begin
       PrintHeapStats();
@@ -5014,8 +4985,12 @@ begin
   chstr := '';
   if cmd = 'pause' then
   begin
-    if (g_ActiveWindow = nil) then
+    {$IFDEF ENABLE_MENU}
+      if (g_ActiveWindow = nil) then
+        g_Game_Pause(not gPauseMain);
+    {$ELSE}
       g_Game_Pause(not gPauseMain);
+    {$ENDIF}
   end
   else if cmd = 'endgame' then
     gExit := EXIT_SIMPLE
@@ -5974,7 +5949,9 @@ begin
   end
   else if cmd = 'screenshot' then
   begin
-    g_TakeScreenShot()
+    {$IFDEF ENABLE_RENDER}
+      r_Render_RequestScreenShot;
+    {$ENDIF}
   end
   else if (cmd = 'weapnext') or (cmd = 'weapprev') then
   begin
@@ -6258,8 +6235,10 @@ begin
         g_Game_Free();
         g_Game_Quit();
       end;
+{$IFDEF ENABLE_RENDER}
     'r_reset':
-       r_Render_Apply;
+         r_Render_Apply;
+{$ENDIF}
     'r_maxfps':
       begin
         if Length(p) = 2 then
@@ -6305,36 +6284,7 @@ begin
   end;
 end;
 
-procedure g_TakeScreenShot(Filename: string = '');
-  var s: TStream; t: TDateTime; dir, date, name: String;
-begin
-  if e_NoGraphics then Exit;
-  try
-    dir := e_GetWriteableDir(ScreenshotDirs);
-
-    if Filename = '' then
-    begin
-      t := Now;
-      DateTimeToString(date, 'yyyy-mm-dd-hh-nn-ss', t);
-      Filename := 'screenshot-' + date;
-    end;
-    
-    name := e_CatPath(dir, Filename + '.png');
-    s := createDiskFile(name);
-    try
-      e_MakeScreenshot(s, gWinSizeX, gWinSizeY);
-      s.Free;
-      g_Console_Add(Format(_lc[I_CONSOLE_SCREENSHOT], [name]))
-    except
-      g_Console_Add(Format(_lc[I_CONSOLE_ERROR_WRITE], [name]));
-      s.Free;
-      DeleteFile(name)
-    end
-  except
-    g_Console_Add('oh shit, i can''t create screenshot!')
-  end
-end;
-
+{$IFDEF ENABLE_MENU}
 procedure g_Game_InGameMenu(Show: Boolean);
 begin
   if (g_ActiveWindow = nil) and Show then
@@ -6365,6 +6315,7 @@ begin
         g_Game_Pause(False);
     end;
 end;
+{$ENDIF}
 
 procedure g_Game_Pause (Enable: Boolean);
 var
@@ -6508,12 +6459,11 @@ begin
   end;
 end;
 
-procedure g_Game_Message(Msg: string; Time: Word);
-begin
-  MessageLineLength := (gScreenWidth - 204) div e_CharFont_GetMaxWidth(gMenuFont);
-  MessageText := b_Text_Wrap(b_Text_Format(Msg), MessageLineLength);
-  MessageTime := Time;
-end;
+  procedure g_Game_Message (Msg: string; Time: Word);
+  begin
+    MessageText := Msg;
+    MessageTime := Time;
+  end;
 
 procedure g_Game_ChatSound(Text: String; Taunt: Boolean = True);
 const
@@ -6785,78 +6735,6 @@ begin
   gCheats := True;
 end;
 
-procedure g_Game_SetLoadingText(Text: String; Max: Integer; reWrite: Boolean);
-var
-  i: Word;
-begin
-  if Length(LoadingStat.Msgs) = 0 then
-    Exit;
-
-  with LoadingStat do
-  begin
-    if not reWrite then
-    begin // Переходим на следующую строку или скроллируем:
-      if NextMsg = Length(Msgs) then
-        begin // scroll
-          for i := 0 to High(Msgs)-1 do
-            Msgs[i] := Msgs[i+1];
-        end
-      else
-        Inc(NextMsg);
-    end else
-      if NextMsg = 0 then
-        Inc(NextMsg);
-
-    Msgs[NextMsg-1] := Text;
-    CurValue := 0;
-    MaxValue := Max;
-    ShowCount := 0;
-    PBarWasHere := false;
-  end;
-
-  g_ActiveWindow := nil;
-  ProcessLoading(True);
-end;
-
-procedure g_Game_StepLoading(Value: Integer = -1);
-begin
-  with LoadingStat do
-  begin
-    if Value = -1 then
-    begin
-      Inc(CurValue);
-      Inc(ShowCount);
-    end
-    else
-      CurValue := Value;
-
-    if (ShowCount > LOADING_SHOW_STEP) or (Value > -1) then
-    begin
-      ShowCount := 0;
-      ProcessLoading(False);
-    end;
-  end;
-end;
-
-procedure g_Game_ClearLoading();
-var
-  len: Word;
-begin
-  with LoadingStat do
-  begin
-    CurValue := 0;
-    MaxValue := 0;
-    ShowCount := 0;
-    len := ((gScreenHeight div 3)*2 - 50) div LOADING_INTERLINE;
-    if len < 1 then len := 1;
-    SetLength(Msgs, len);
-    for len := Low(Msgs) to High(Msgs) do
-      Msgs[len] := '';
-    NextMsg := 0;
-    PBarWasHere := false;
-  end;
-end;
-
 procedure Parse_Params(var pars: TParamStrValues);
 var
   i: Integer;
@@ -7091,13 +6969,14 @@ begin
   conRegVar('pf_coldet', @g_profile_collision, 'draw collision detection profiles', 'coldet profiles');
   conRegVar('pf_los', @g_profile_los, 'draw monster LOS profiles', 'monster LOS profiles');
 
-  conRegVar('r_sq_draw', @gdbg_map_use_accel_render, 'accelerated spatial queries in rendering', 'accelerated rendering');
   conRegVar('cd_sq_enabled', @gdbg_map_use_accel_coldet, 'accelerated spatial queries in map coldet', 'accelerated map coldet');
   conRegVar('mon_sq_enabled', @gmon_debug_use_sqaccel, 'accelerated spatial queries for monsters', 'accelerated monster coldet');
   conRegVar('wtrace_sq_enabled', @gwep_debug_fast_trace, 'accelerated spatial queries for weapon hitscan trace', 'accelerated weapon hitscan');
 
+{$IFDEF ENABLE_GFX}
   conRegVar('pr_enabled', @gpart_dbg_enabled, 'enable/disable particles', 'particles');
   conRegVar('pr_phys_enabled', @gpart_dbg_phys_enabled, 'enable/disable particle physics', 'particle physics');
+{$ENDIF}
 
   conRegVar('los_enabled', @gmon_dbg_los_enabled, 'enable/disable monster LOS calculations', 'monster LOS', true);
   conRegVar('mon_think', @gmon_debug_think, 'enable/disable monster thinking', 'monster thinking', true);