DEADSOFTWARE

added optional framebuffer and resolution scaling
[d2df-sdl.git] / src / game / g_menu.pas
index 53a1cbc6bae3cca965e73a2c6dfdd3ea144ccca3..fe650785d11a8b34baa3b623089b0788e1b37349 100644 (file)
@@ -38,6 +38,7 @@ var
   PromptIP: string;
   PromptPort: Word;
   TempScale: Integer = -1;
+  TempResScale: Integer = -1;
 
 implementation
 
@@ -375,7 +376,7 @@ begin
 
   if g_Game_IsClient then MC_SEND_PlayerSettings;
 
-  s := e_GetDir(ConfigDirs);
+  s := e_GetWriteableDir(ConfigDirs);
   if s <> '' then
     g_Options_Write(s + '/' + CONFIG_FILENAME);
   g_Console_WriteGameConfig;
@@ -667,12 +668,18 @@ begin
     gcMaxLives := StrToIntDef(TGUIEdit(GetControl('edMaxLives')).Text, 0);
 
     gcTeamDamage := TGUISwitch(GetControl('swTeamDamage')).ItemIndex = 0;
+    gcRespawnItems := TGUISwitch(GetControl('swRespawnItems')).ItemIndex = 0;
+    gcDeathmatchKeys := TGUISwitch(GetControl('swDeathmatchKeys')).ItemIndex = 0;
     gcAllowExit := TGUISwitch(GetControl('swEnableExits')).ItemIndex = 0;
     gcWeaponStay := TGUISwitch(GetControl('swWeaponStay')).ItemIndex = 0;
     gcMonsters := TGUISwitch(GetControl('swMonsters')).ItemIndex = 0;
     Options := 0;
     if gcTeamDamage then
       Options := Options or GAME_OPTION_TEAMDAMAGE;
+    if gcRespawnItems then
+      Options := Options or GAME_OPTION_RESPAWNITEMS;
+    if gcDeathmatchKeys then
+      Options := Options or GAME_OPTION_DMKEYS;
     if gcAllowExit then
       Options := Options or GAME_OPTION_ALLOWEXIT;
     if gcWeaponStay then
@@ -699,7 +706,7 @@ begin
     gcMap := Map;
   end;
 
-  s := e_GetDir(ConfigDirs);
+  s := e_GetWriteableDir(ConfigDirs);
   if s <> '' then
     g_Options_Write_Gameplay_Custom(s + '/' + CONFIG_FILENAME);
 
@@ -731,12 +738,18 @@ begin
     NetPort := StrToIntDef(TGUIEdit(GetControl('edPort')).Text, 0);
 
     gnTeamDamage := TGUISwitch(GetControl('swTeamDamage')).ItemIndex = 0;
+    gnRespawnItems := TGUISwitch(GetControl('swRespawnItems')).ItemIndex = 0;
+    gnDeathmatchKeys := TGUISwitch(GetControl('swDeathmatchKeys')).ItemIndex = 0;
     gnAllowExit := TGUISwitch(GetControl('swEnableExits')).ItemIndex = 0;
     gnWeaponStay := TGUISwitch(GetControl('swWeaponStay')).ItemIndex = 0;
     gnMonsters := TGUISwitch(GetControl('swMonsters')).ItemIndex = 0;
     Options := 0;
     if gnTeamDamage then
       Options := Options or GAME_OPTION_TEAMDAMAGE;
+    if gnRespawnItems then
+      Options := Options or GAME_OPTION_RESPAWNITEMS;
+    if gnDeathmatchKeys then
+      Options := Options or GAME_OPTION_DMKEYS;
     if gnAllowExit then
       Options := Options or GAME_OPTION_ALLOWEXIT;
     if gnWeaponStay then
@@ -768,7 +781,7 @@ begin
     NetUseMaster := TGUISwitch(GetControl('swUseMaster')).ItemIndex = 0;
   end;
 
-  s := e_GetDir(ConfigDirs);
+  s := e_GetWriteableDir(ConfigDirs);
   if s <> '' then
   begin
     g_Options_Write_Net_Server(s + '/' + CONFIG_FILENAME);
@@ -791,7 +804,7 @@ begin
     PW := TGUIEdit(GetControl('edPW')).Text;
   end;
 
-  s := e_GetDir(ConfigDirs);
+  s := e_GetWriteableDir(ConfigDirs);
   if s <> '' then
     g_Options_Write_Net_Client(s + '/' + CONFIG_FILENAME);
   g_Game_StartClient(NetClientIP, NetClientPort, PW);
@@ -809,7 +822,7 @@ begin
     PW := TGUIEdit(GetControl('edPW')).Text;
   end;
 
-  s := e_GetDir(ConfigDirs);
+  s := e_GetWriteableDir(ConfigDirs);
   if s <> '' then
     g_Options_Write_Net_Client(s + '/' + CONFIG_FILENAME);
   g_Game_StartClient(NetClientIP, NetClientPort, PW);
@@ -860,6 +873,7 @@ begin
     WAD := TGUIFileListBox(GetControl('lsWAD')).SelectedItem();
     TwoPlayers := TGUISwitch(GetControl('swPlayers')).ItemIndex = 1;
   end;
+  WAD := e_FindWadRel(MegawadDirs, WAD);
 
   if TwoPlayers then
     n := 2
@@ -1280,13 +1294,14 @@ end;
 procedure ProcSinglePlayer (n: Integer);
   var wad, map: AnsiString;
 begin
+  assert(n >= 1);
   wad := g_ExtractWadName(gDefaultMegawadStart);
   map := g_ExtractFilePathName(gDefaultMegawadStart);
   if e_FindResource(AllMapDirs, wad) then
   begin
     wad := ExpandFileName(wad);
-    g_Game_StartSingle(wad + ':\' + map, False, n);
-  end;
+    g_Game_StartSingle(wad + ':\' + map, n > 1, n)
+  end
 end;
 
 procedure ProcSingle1Player;
@@ -1357,6 +1372,8 @@ begin
   if (wad = '') or (map = '') then
     Exit;
 
+  wad := e_FindWadRel(MapDirs, WAD);
+
   res := wad+':\'+map;
 
   TGUILabel(TGUIMenu(g_GUI_GetWindow('CustomGameMenu').GetControl('mCustomGameMenu')).GetControl('lbMap')).Text := res;
@@ -1653,37 +1670,23 @@ begin
 end;
 
 procedure ProcSetRussianLanguage;
-  var s: AnsiString;
 begin
   if gLanguage <> LANGUAGE_RUSSIAN then
   begin
     gLanguage := LANGUAGE_RUSSIAN;
     gLanguageChange := True;
     gAskLanguage := False;
-
-    s := e_GetDir(ConfigDirs);
-    if s <> '' then
-      g_Options_Write_Language(s + '/' + CONFIG_FILENAME);
-
-  // Ñîõðàíÿåì èçìåíåíèÿ âñåõ íàñòðîåê:
     ProcApplyOptions();
   end;
 end;
 
 procedure ProcSetEnglishLanguage;
-  var s: AnsiString;
 begin
   if gLanguage <> LANGUAGE_ENGLISH then
   begin
     gLanguage := LANGUAGE_ENGLISH;
     gLanguageChange := True;
     gAskLanguage := False;
-
-    s := e_GetDir(ConfigDirs);
-    if s <> '' then
-      g_Options_Write_Language(s + '/' + CONFIG_FILENAME);
-
-  // Ñîõðàíÿåì èçìåíåíèÿ âñåõ íàñòðîåê:
     ProcApplyOptions();
   end;
 end;
@@ -1701,6 +1704,11 @@ begin
         ItemIndex := 0
       else
         ItemIndex := 1;
+    with TGUISwitch(menu.GetControl('swDeathmatchKeys')) do
+      if LongBool(Options and GAME_OPTION_DMKEYS) then
+        ItemIndex := 0
+      else
+        ItemIndex := 1;
 
     TGUIEdit(menu.GetControl('edTimeLimit')).Text := IntToStr(TimeLimit);
     TGUIEdit(menu.GetControl('edGoalLimit')).Text := IntToStr(GoalLimit);
@@ -1719,6 +1727,7 @@ begin
     if GameType in [GT_CUSTOM, GT_SERVER] then
       begin
         TGUISwitch(menu.GetControl('swTeamDamage')).Enabled := True;
+        TGUISwitch(menu.GetControl('swDeathmatchKeys')).Enabled := (GameMode in [GM_DM, GM_TDM, GM_CTF]);
         TGUIEdit(menu.GetControl('edTimeLimit')).Enabled := True;
         TGUILabel(menu.GetControlsText('edTimeLimit')).Color := MENU_ITEMSTEXT_COLOR;
         TGUIEdit(menu.GetControl('edGoalLimit')).Enabled := True;
@@ -1730,6 +1739,7 @@ begin
     else
       begin
         TGUISwitch(menu.GetControl('swTeamDamage')).Enabled := True;
+        TGUISwitch(menu.GetControl('swDeathmatchKeys')).Enabled := False;
         with TGUIEdit(menu.GetControl('edTimeLimit')) do
         begin
           Enabled := False;
@@ -1773,6 +1783,14 @@ begin
         Options := Options and (not GAME_OPTION_TEAMDAMAGE);
     end;
 
+    if TGUISwitch(menu.GetControl('swDeathmatchKeys')).Enabled then
+    begin
+      if TGUISwitch(menu.GetControl('swDeathmatchKeys')).ItemIndex = 0 then
+        Options := Options or GAME_OPTION_DMKEYS
+      else
+        Options := Options and (not GAME_OPTION_DMKEYS);
+    end;
+
     if TGUIEdit(menu.GetControl('edTimeLimit')).Enabled then
     begin
       n := StrToIntDef(TGUIEdit(menu.GetControl('edTimeLimit')).Text, TimeLimit);
@@ -1864,13 +1882,13 @@ begin
   menu := TGUIMenu(g_GUI_GetWindow('OptionsVideoResMenu').GetControl('mOptionsVideoResMenu'));
 
   TGUILabel(menu.GetControl('lbCurrentRes')).Text :=
-    IntToStr(gScreenWidth) +
-    ' x ' + IntToStr(gScreenHeight) +
+    IntToStr(gWinSizeX) +
+    ' x ' + IntToStr(gWinSizeY) +
     ', ' + IntToStr(gBPP) + ' bpp';
 
   with TGUIListBox(menu.GetControl('lsResolution')) do
   begin
-    list := sys_GetDispalyModes(gBPP);
+    list := sys_GetDisplayModes(gBPP);
     if list <> nil then
     begin
       Items := list;
@@ -1887,6 +1905,9 @@ begin
       ItemIndex := 0
     else
       ItemIndex := 1;
+
+  TempResScale := Round(r_pixel_scale - 1);
+  TGUIScroll(menu.GetControl('scResFactor')).Value := TempResScale;
 end;
 
 procedure ProcApplyVideoOptions();
@@ -1894,18 +1915,34 @@ var
   menu: TGUIMenu;
   Fullscreen: Boolean;
   SWidth, SHeight: Integer;
+  ScaleChanged: Boolean;
   str: String;
 begin
   menu := TGUIMenu(g_GUI_GetWindow('OptionsVideoResMenu').GetControl('mOptionsVideoResMenu'));
 
   str := TGUIListBox(menu.GetControl('lsResolution')).SelectedItem;
-  SScanf(str, '%dx%d', [@SWidth, @SHeight]);
+  if str <> '' then
+    SScanf(str, '%dx%d', [@SWidth, @SHeight])
+  else
+  begin
+    SWidth := gWinSizeX;
+    SHeight := gWinSizeY;
+  end;
 
   Fullscreen := TGUISwitch(menu.GetControl('swFullScreen')).ItemIndex = 0;
 
-  if (SWidth <> gScreenWidth) or
-     (SHeight <> gScreenHeight) or
-     (Fullscreen <> gFullscreen) then
+  ScaleChanged := False;
+  if TGUIScroll(menu.GetControl('scResFactor')).Value <> TempResScale then
+  begin
+    TempResScale := TGUIScroll(menu.GetControl('scResFactor')).Value;
+    r_pixel_scale := TempResScale + 1;
+    ScaleChanged := True;
+  end;
+
+  if (SWidth <> gWinSizeX) or
+     (SHeight <> gWinSizeY) or
+     (Fullscreen <> gFullscreen) or
+     ScaleChanged then
   begin
     gResolutionChange := True;
     gRC_Width := SWidth;
@@ -1919,27 +1956,17 @@ begin
 end;
 
 procedure ProcSetFirstRussianLanguage;
-  var s: AnsiString;
 begin
   gLanguage := LANGUAGE_RUSSIAN;
   gLanguageChange := True;
   gAskLanguage := False;
-
-  s := e_GetDir(ConfigDirs);
-  if s <> '' then
-    g_Options_Write_Language(s + '/' + CONFIG_FILENAME)
 end;
 
 procedure ProcSetFirstEnglishLanguage;
-  var s: AnsiString;
 begin
   gLanguage := LANGUAGE_ENGLISH;
   gLanguageChange := True;
   gAskLanguage := False;
-
-  s := e_GetDir(ConfigDirs);
-  if s <> '' then
-    g_Options_Write_Language(s + '/' + CONFIG_FILENAME)
 end;
 
 procedure ProcRecallAddress();
@@ -2208,6 +2235,26 @@ begin
       else
         ItemIndex := 1;
     end;
+    with AddSwitch(_lc[I_MENU_RESPAWN_ITEMS]) do
+    begin
+      Name := 'swRespawnItems';
+      AddItem(_lc[I_MENU_YES]);
+      AddItem(_lc[I_MENU_NO]);
+      if gnRespawnItems then
+        ItemIndex := 0
+      else
+        ItemIndex := 1;
+    end;
+    with AddSwitch(_lc[I_MENU_DEATHMATCH_KEYS]) do
+    begin
+      Name := 'swDeathmatchKeys';
+      AddItem(_lc[I_MENU_YES]);
+      AddItem(_lc[I_MENU_NO]);
+      if gnDeathmatchKeys then
+        ItemIndex := 0
+      else
+        ItemIndex := 1;
+    end;
     with AddSwitch(_lc[I_MENU_ENABLE_EXITS]) do
     begin
       Name := 'swEnableExits';
@@ -2408,6 +2455,26 @@ begin
       else
         ItemIndex := 1;
     end;
+    with AddSwitch(_lc[I_MENU_RESPAWN_ITEMS]) do
+    begin
+      Name := 'swRespawnItems';
+      AddItem(_lc[I_MENU_YES]);
+      AddItem(_lc[I_MENU_NO]);
+      if gcRespawnItems then
+        ItemIndex := 0
+      else
+        ItemIndex := 1;
+    end;
+    with AddSwitch(_lc[I_MENU_DEATHMATCH_KEYS]) do
+    begin
+      Name := 'swDeathmatchKeys';
+      AddItem(_lc[I_MENU_YES]);
+      AddItem(_lc[I_MENU_NO]);
+      if gcDeathmatchKeys then
+        ItemIndex := 0
+      else
+        ItemIndex := 1;
+    end;
     with AddSwitch(_lc[I_MENU_ENABLE_EXITS]) do
     begin
       Name := 'swEnableExits';
@@ -2668,6 +2735,11 @@ begin
       AddItem(_lc[I_MENU_YES]);
       AddItem(_lc[I_MENU_NO]);
     end;
+    with AddScroll(_lc[I_MENU_GAME_SCALE_FACTOR]) do
+    begin
+      Name := 'scResFactor';
+      Max := 10;
+    end;
     AddSpace();
     AddButton(@ProcApplyVideoOptions, _lc[I_MENU_RESOLUTION_APPLY]);
     UpdateIndex();
@@ -3268,6 +3340,13 @@ begin
       AddItem(_lc[I_MENU_NO]);
       ItemIndex := 1;
     end;
+    with AddSwitch(_lc[I_MENU_DEATHMATCH_KEYS]) do
+    begin
+      Name := 'swDeathmatchKeys';
+      AddItem(_lc[I_MENU_YES]);
+      AddItem(_lc[I_MENU_NO]);
+      ItemIndex := 1;
+    end;
     with AddEdit(_lc[I_MENU_TIME_LIMIT]) do
     begin
       Name := 'edTimeLimit';