DEADSOFTWARE

added optional framebuffer and resolution scaling
[d2df-sdl.git] / src / game / g_game.pas
index ef256d18c597441246b1fd81e115d67b259a1c77..8d784c2a2be634127f934150244bae03af5e5cb2 100644 (file)
@@ -31,6 +31,7 @@ type
     TimeLimit: Word;
     GoalLimit: Word;
     WarmupTime: Word;
+    SpawnInvul: Word;
     MaxLives: Byte;
     Options: LongWord;
     WAD: String;
@@ -178,6 +179,8 @@ const
   GAME_OPTION_MONSTERS     = 16;
   GAME_OPTION_BOTVSPLAYER  = 32;
   GAME_OPTION_BOTVSMONSTER = 64;
+  GAME_OPTION_DMKEYS       = 128;
+  GAME_OPTION_RESPAWNITEMS = 256;
 
   STATE_NONE        = 0;
   STATE_MENU        = 1;
@@ -288,7 +291,8 @@ var
   gMapToDelete: String;
   gTempDelete: Boolean = False;
   gLastMap: Boolean = False;
-  gWinSizeX, gWinSizeY: Integer;
+  gScreenWidth: Word;
+  gScreenHeight: Word;
   gResolutionChange: Boolean = False;
   gRC_Width, gRC_Height: Integer;
   gRC_FullScreen, gRC_Maximized: Boolean;
@@ -1062,14 +1066,15 @@ begin
 
           SortGameStat(CustomStat.PlayerStat);
 
-          if gSaveStats or gScreenshotStats then
+          if (gSaveStats or gScreenshotStats) and (Length(CustomStat.PlayerStat) > 1) then
           begin
             t := Now;
             if g_Game_IsNet then StatFilename := NetServerName else StatFilename := 'local';
             StatDate := FormatDateTime('yymmdd_hhnnss', t);
             StatFilename := StatFilename + '_' + CustomStat.Map + '_' + g_Game_ModeToText(CustomStat.GameMode);
             StatFilename := sanitizeFilename(StatFilename) + '_' + StatDate;
-            if gSaveStats then SaveGameStat(CustomStat, FormatDateTime('yyyy"/"mm"/"dd', t));
+            if gSaveStats then
+              SaveGameStat(CustomStat, FormatDateTime('yyyy"/"mm"/"dd', t));
           end;
 
           StatShotDone := False;
@@ -2872,7 +2877,7 @@ begin
   end;
 
   // HACK: take stats screenshot immediately after the first frame of the stats showing
-  if gScreenshotStats and not StatShotDone then
+  if gScreenshotStats and (not StatShotDone) and (Length(CustomStat.PlayerStat) > 1) then
   begin
     g_TakeScreenShot('stats/' + StatFilename);
     StatShotDone := True;
@@ -3414,7 +3419,7 @@ begin
     end
     else
     begin
-      glScissor(0, 0, gWinSizeX, gWinSizeY);
+      glScissor(0, 0, gScreenWidth, gScreenHeight);
     end;
     // no need to clear stencil buffer, light blitting will do it for us... but only for normal scale
     if (g_dbg_scale <> 1.0) then glClear(GL_STENCIL_BUFFER_BIT);
@@ -3664,67 +3669,45 @@ begin
     b := -py+(gPlayerScreenSize.Y div 2);
   end;
 
-  if p.IncCam <> 0 then
-  begin
-    if py > gMapInfo.Height-(gPlayerScreenSize.Y div 2) then
-    begin
-      if p.IncCam > 120-(py-(gMapInfo.Height-(gPlayerScreenSize.Y div 2))) then
-      begin
-        p.IncCam := 120-(py-(gMapInfo.Height-(gPlayerScreenSize.Y div 2)));
-      end;
-    end;
-
-    if py < gPlayerScreenSize.Y div 2 then
-    begin
-      if p.IncCam < -120+((gPlayerScreenSize.Y div 2)-py) then
-      begin
-        p.IncCam := -120+((gPlayerScreenSize.Y div 2)-py);
-      end;
-    end;
-
-    if p.IncCam < 0 then
-    begin
-      while (py+(gPlayerScreenSize.Y div 2)-p.IncCam > gMapInfo.Height) and (p.IncCam < 0) do p.IncCam := p.IncCam+1; //Inc(p.IncCam);
-    end;
-
-    if p.IncCam > 0 then
-    begin
-      while (py-(gPlayerScreenSize.Y div 2)-p.IncCam < 0) and (p.IncCam > 0) do p.IncCam := p.IncCam-1; //Dec(p.IncCam);
-    end;
-  end;
-
-       if (px < gPlayerScreenSize.X div 2) or (gMapInfo.Width-gPlayerScreenSize.X <= 256) then c := 0
-  else if (px > gMapInfo.Width-(gPlayerScreenSize.X div 2)) then c := gBackSize.X-gPlayerScreenSize.X
-  else c := round((px-(gPlayerScreenSize.X div 2))/(gMapInfo.Width-gPlayerScreenSize.X)*(gBackSize.X-gPlayerScreenSize.X));
-
-       if (py-p.IncCam <= gPlayerScreenSize.Y div 2) or (gMapInfo.Height-gPlayerScreenSize.Y <= 256) then d := 0
-  else if (py-p.IncCam >= gMapInfo.Height-(gPlayerScreenSize.Y div 2)) then d := gBackSize.Y-gPlayerScreenSize.Y
-  else d := round((py-p.IncCam-(gPlayerScreenSize.Y div 2))/(gMapInfo.Height-gPlayerScreenSize.Y)*(gBackSize.Y-gPlayerScreenSize.Y));
-
   sX := -a;
-  sY := -(b+p.IncCam);
+  sY := -b;
   sWidth := gPlayerScreenSize.X;
   sHeight := gPlayerScreenSize.Y;
+  fixViewportForScale();
 
-  //glTranslatef(a, b+p.IncCam, 0);
-
-  //if (p = gPlayer1) and (g_dbg_scale >= 1.0) then g_Holmes_plrViewSize(sWidth, sHeight);
+  i := py - (sY + sHeight div 2);
+  if (p.IncCam > 0) then
+  begin
+    // clamp to level bounds
+    if (sY - p.IncCam < 0) then
+      p.IncCam := nclamp(sY, 0, 120);
+    // clamp around player position
+    if (i > 0) then
+      p.IncCam := nclamp(p.IncCam, 0, max(0, 120 - i));
+  end
+  else if (p.IncCam < 0) then
+  begin
+    // clamp to level bounds
+    if (sY + sHeight - p.IncCam > gMapInfo.Height) then
+      p.IncCam := nclamp(sY + sHeight - gMapInfo.Height, -120, 0);
+    // clamp around player position
+    if (i < 0) then
+      p.IncCam := nclamp(p.IncCam, min(0, -120 - i), 0);
+  end;
 
-  //conwritefln('OLD: (%s,%s)-(%s,%s)', [sX, sY, sWidth, sHeight]);
-  fixViewportForScale();
-  //conwritefln('     (%s,%s)-(%s,%s)', [sX, sY, sWidth, sHeight]);
+  sY := sY - p.IncCam;
 
-  if (g_dbg_scale <> 1.0) and (not g_dbg_ignore_bounds) then
+  if (not g_dbg_ignore_bounds) then
   begin
     if (sX+sWidth > gMapInfo.Width) then sX := gMapInfo.Width-sWidth;
     if (sY+sHeight > gMapInfo.Height) then sY := gMapInfo.Height-sHeight;
     if (sX < 0) then sX := 0;
     if (sY < 0) then sY := 0;
-
-    if (gBackSize.X <= gPlayerScreenSize.X) or (gMapInfo.Width <= sWidth) then c := 0 else c := trunc((gBackSize.X-gPlayerScreenSize.X)*sX/(gMapInfo.Width-sWidth));
-    if (gBackSize.Y <= gPlayerScreenSize.Y) or (gMapInfo.Height <= sHeight) then d := 0 else d := trunc((gBackSize.Y-gPlayerScreenSize.Y)*sY/(gMapInfo.Height-sHeight));
   end;
 
+  if (gBackSize.X <= gPlayerScreenSize.X) or (gMapInfo.Width <= sWidth) then c := 0 else c := trunc((gBackSize.X-gPlayerScreenSize.X)*sX/(gMapInfo.Width-sWidth));
+  if (gBackSize.Y <= gPlayerScreenSize.Y) or (gMapInfo.Height <= sHeight) then d := 0 else d := trunc((gBackSize.Y-gPlayerScreenSize.Y)*sY/(gMapInfo.Height-sHeight));
+
   //r_smallmap_h: 0: left; 1: center; 2: right
   //r_smallmap_v: 0: top; 1: center; 2: bottom
   // horiz small map?
@@ -4638,7 +4621,7 @@ begin
 // Ñòàðòóåì ñåðâåð
   if not g_Net_Host(IPAddr, Port, NetMaxClients) then
   begin
-    g_FatalError(_lc[I_NET_MSG] + _lc[I_NET_ERR_HOST]);
+    g_FatalError(_lc[I_NET_MSG] + Format(_lc[I_NET_ERR_HOST], [Port]));
     Exit;
   end;
 
@@ -5552,6 +5535,48 @@ begin
       if g_Game_IsNet then MH_SEND_GameSettings;
     end;
   end
+  else if (cmd = 'g_dm_keys') and not g_Game_IsClient then
+  begin
+    with gGameSettings do
+    begin
+      if (Length(P) > 1) and
+         ((P[1] = '1') or (P[1] = '0')) then
+      begin
+        if (P[1][1] = '1') then
+          Options := Options or GAME_OPTION_DMKEYS
+        else
+          Options := Options and (not GAME_OPTION_DMKEYS);
+      end;
+
+      if (LongBool(Options and GAME_OPTION_DMKEYS)) then
+        g_Console_Add(_lc[I_MSG_DMKEYS_ON])
+      else
+        g_Console_Add(_lc[I_MSG_DMKEYS_OFF]);
+
+      if g_Game_IsNet then MH_SEND_GameSettings;
+    end;
+  end
+  else if (cmd = 'g_respawn_items') and not g_Game_IsClient then
+  begin
+    with gGameSettings do
+    begin
+      if (Length(P) > 1) and
+         ((P[1] = '1') or (P[1] = '0')) then
+      begin
+        if (P[1][1] = '1') then
+          Options := Options or GAME_OPTION_RESPAWNITEMS
+        else
+          Options := Options and (not GAME_OPTION_RESPAWNITEMS);
+      end;
+
+      if (LongBool(Options and GAME_OPTION_RESPAWNITEMS)) then
+        g_Console_Add(_lc[I_MSG_RESPAWNITEMS_ON])
+      else
+        g_Console_Add(_lc[I_MSG_RESPAWNITEMS_OFF]);
+
+      if g_Game_IsNet then MH_SEND_GameSettings;
+    end;
+  end
   else if (cmd = 'g_warmuptime') and not g_Game_IsClient then
   begin
     if Length(P) > 1 then
@@ -5566,6 +5591,20 @@ begin
                  [gGameSettings.WarmupTime]));
     g_Console_Add(_lc[I_MSG_ONMAPCHANGE]);
   end
+  else if (cmd = 'g_spawn_invul') and not g_Game_IsClient then
+  begin
+    if Length(P) > 1 then
+    begin
+      if StrToIntDef(P[1], gGameSettings.SpawnInvul) = 0 then
+        gGameSettings.SpawnInvul := 0
+      else
+        gGameSettings.SpawnInvul := StrToIntDef(P[1], gGameSettings.SpawnInvul);
+    end;
+
+    g_Console_Add(Format(_lc[I_MSG_SPAWNINVUL],
+                 [gGameSettings.SpawnInvul]));
+    g_Console_Add(_lc[I_MSG_ONMAPCHANGE]);
+  end
   else if cmd = 'net_interp' then
   begin
     if (Length(P) > 1) then
@@ -5934,7 +5973,7 @@ begin
     if cmd = 'd_window' then
     begin
       g_Console_Add(Format('gScreenWidth = %d, gScreenHeight = %d', [gScreenWidth, gScreenHeight]));
-      g_Console_Add(Format('gWinSizeX = %d, gWinSizeY = %d', [gWinSizeX, gWinSizeY]));
+      g_Console_Add(Format('gScreenWidth = %d, gScreenHeight = %d', [gScreenWidth, gScreenHeight]));
     end
     else if cmd = 'd_sounds' then
     begin
@@ -7207,6 +7246,30 @@ begin
       end else
         g_Console_Add(_lc[I_MSG_SERVERONLY]);
     end
+    else if cmd = 'centerprint' then
+    begin
+      if (Length(P) > 2) and (P[1] <> '') then
+      begin
+        chstr := '';
+        for a := 2 to High(P) do
+          chstr := chstr + P[a] + ' ';
+
+        if Length(chstr) > 200 then SetLength(chstr, 200);
+
+        if Length(chstr) < 1 then
+        begin
+          g_Console_Add('centerprint <timeout> <text>');
+          Exit;
+        end;
+
+        a := StrToIntDef(P[1], 100);
+        chstr := b_Text_Format(chstr);
+        g_Game_Message(chstr, a);
+        if g_Game_IsNet and g_Game_IsServer then
+          MH_SEND_GameEvent(NET_EV_BIGTEXT, a, chstr);
+      end
+      else g_Console_Add('centerprint <timeout> <text>');
+    end
     else if (cmd = 'overtime') and not g_Game_IsClient then
     begin
       if (Length(P) = 1) or (StrToIntDef(P[1], -1) <= 0) then
@@ -8119,6 +8182,7 @@ begin
   conRegVar('dbg_ignore_level_bounds', @g_dbg_ignore_bounds, 'ignore level bounds', '',  false);
 
   conRegVar('r_scale', @g_dbg_scale, 0.01, 100.0, 'render scale', '',  false);
+  conRegVar('r_resolution_scale', @r_pixel_scale, 0.01, 100.0, 'upscale factor', '', false);
 
   conRegVar('light_enabled', @gwin_k8_enable_light_experiments, 'enable/disable dynamic lighting', 'lighting');
   conRegVar('light_player_halo', @g_playerLight, 'enable/disable player halo', 'player light halo');