DEADSOFTWARE

game: add g_max_bots
[d2df-sdl.git] / src / game / g_game.pas
index 2c8ae0fb8dcdc8507c2184aaccc0ca4a660b3183..5822952a5e8383595a747ebfd831ac19bdc4e06c 100644 (file)
@@ -62,6 +62,11 @@ type
     Model: String;
     Color: TRGB;
     Team: Byte;
+    // ones below are sent only to the server
+    WeaponSwitch: Byte;
+    WeaponPreferences: Array[WP_FIRST..WP_LAST+1] of Byte;
+    SwitchToEmpty: Byte;
+    SkipFist: Byte;
   end;
 
   TMegaWADInfo = record
@@ -186,7 +191,9 @@ const
   GAME_OPTION_DMKEYS            = 128;
   GAME_OPTION_TEAMHITTRACE      = 256;
   GAME_OPTION_TEAMHITPROJECTILE = 512;
-  GAME_OPTION_TEAMABSORBDAMAGE = 1024;
+  GAME_OPTION_TEAMABSORBDAMAGE  = 1024;
+  GAME_OPTION_ALLOWDROPFLAG     = 2048;
+  GAME_OPTION_THROWFLAG         = 4096;
 
   STATE_NONE        = 0;
   STATE_MENU        = 1;
@@ -340,8 +347,10 @@ var
   gDelayedEvents: Array of TDelayedEvent;
   gUseChatSounds: Boolean = True;
   gChatSounds: Array of TChatSound;
+  gWeaponAction: Array [0..1, WP_FACT..WP_LACT] of Boolean; // [player, weapon_action]
   gSelectWeapon: Array [0..1, WP_FIRST..WP_LAST] of Boolean; // [player, weapon]
   gInterReadyCount: Integer = 0;
+  gMaxBots: Integer = 127;
 
   g_dbg_ignore_bounds: Boolean = false;
   r_smallmap_h: Integer = 0; // 0: left; 1: center; 2: right
@@ -1690,12 +1699,16 @@ begin
   if gPlayerAction[p, ACTION_LOOKUP] then plr.PressKey(KEY_UP, time);
   if gPlayerAction[p, ACTION_LOOKDOWN] then plr.PressKey(KEY_DOWN, time);
   if gPlayerAction[p, ACTION_ATTACK] then plr.PressKey(KEY_FIRE);
-  if gPlayerAction[p, ACTION_WEAPNEXT] then plr.PressKey(KEY_NEXTWEAPON);
-  if gPlayerAction[p, ACTION_WEAPPREV] then plr.PressKey(KEY_PREVWEAPON);
   if gPlayerAction[p, ACTION_ACTIVATE] then plr.PressKey(KEY_OPEN);
 
-  gPlayerAction[p, ACTION_WEAPNEXT] := False; // HACK, remove after readyweaon&pendinweapon implementation
-  gPlayerAction[p, ACTION_WEAPPREV] := False; // HACK, remove after readyweaon&pendinweapon implementation
+  for i := WP_FACT to WP_LACT do
+  begin
+    if gWeaponAction[p, i] then
+    begin
+      plr.ProcessWeaponAction(i);
+      gWeaponAction[p, i] := False
+    end
+  end;
 
   for i := WP_FIRST to WP_LAST do
   begin
@@ -1774,6 +1787,16 @@ var
     if mon.gncNeedSend then MH_SEND_MonsterPos(mon.UID);
   end;
 
+  function sendItemPos (it: PItem): Boolean;
+  begin
+    result := false; // don't stop
+    if it.needSend then
+    begin
+      MH_SEND_ItemPos(it.myId);
+      it.needSend := False;
+    end;
+  end;
+
 var
   reliableUpdate: Boolean;
 begin
@@ -1901,6 +1924,7 @@ begin
           // Çàêîí÷èëñÿ óðîâåíü â Ñâîåé èãðå:
             if gGameSettings.GameType in [GT_CUSTOM, GT_SERVER, GT_CLIENT] then
               begin
+                gState := STATE_INTERCUSTOM;
                 InterReadyTime := -1;
                 if gLastMap and (gGameSettings.GameMode = GM_COOP) then
                 begin
@@ -1910,9 +1934,7 @@ begin
                 end
                 else
                   gMusic.SetByName('MUSIC_ROUNDMUS');
-
                 gMusic.Play();
-                gState := STATE_INTERCUSTOM;
                 e_UnpressAllKeys();
               end
             else // Çàêîí÷èëàñü ïîñëåäíÿÿ êàðòà â Îäèíî÷íîé èãðå
@@ -2056,17 +2078,17 @@ begin
             gSpectY := Max(gSpectY - gSpectStep, 0);
           if gPlayerAction[0, ACTION_LOOKDOWN] then
             gSpectY := Min(gSpectY + gSpectStep, gMapInfo.Height - gScreenHeight);
-          if gPlayerAction[0, ACTION_WEAPPREV] then
+          if gWeaponAction[0, WP_PREV] then
           begin
             // decrease step
             if gSpectStep > 4 then gSpectStep := gSpectStep shr 1;
-            gSpectKeyPress := True;
+            gWeaponAction[0, WP_PREV] := False;
           end;
-          if gPlayerAction[0, ACTION_WEAPNEXT] then
+          if gWeaponAction[0, WP_NEXT] then
           begin
             // increase step
             if gSpectStep < 64 then gSpectStep := gSpectStep shl 1;
-            gSpectKeyPress := True;
+            gWeaponAction[0, WP_NEXT] := False;
           end;
         end;
         if (gSpectMode = SPECT_PLAYERS)
@@ -2096,17 +2118,17 @@ begin
             gSpectPID1 := GetActivePlayerID_Next(gSpectPID1);
             gSpectKeyPress := True;
           end;
-          if gPlayerAction[0, ACTION_WEAPPREV] then
+          if gWeaponAction[0, WP_PREV] then
           begin
             // prev player (view 2)
             gSpectPID2 := GetActivePlayerID_Prev(gSpectPID2);
-            gSpectKeyPress := True;
+            gWeaponAction[0, WP_PREV] := False;
           end;
-          if gPlayerAction[0, ACTION_WEAPNEXT] then
+          if gWeaponAction[0, WP_NEXT] then
           begin
             // next player (view 2)
             gSpectPID2 := GetActivePlayerID_Next(gSpectPID2);
-            gSpectKeyPress := True;
+            gWeaponAction[0, WP_NEXT] := False;
           end;
         end;
         if gPlayerAction[0, ACTION_ATTACK] then
@@ -2133,9 +2155,7 @@ begin
            (not gPlayerAction[0, ACTION_MOVELEFT]) and
            (not gPlayerAction[0, ACTION_MOVERIGHT]) and
            (not gPlayerAction[0, ACTION_LOOKUP]) and
-           (not gPlayerAction[0, ACTION_LOOKDOWN]) and
-           (not gPlayerAction[0, ACTION_WEAPPREV]) and
-           (not gPlayerAction[0, ACTION_WEAPNEXT]) then
+           (not gPlayerAction[0, ACTION_LOOKDOWN]) then
           gSpectKeyPress := False;
 
       if gSpectAuto then
@@ -2235,6 +2255,18 @@ begin
 
         g_Mons_ForEach(sendMonsPos);
 
+        // update flags that aren't stationary
+        if gGameSettings.GameMode = GM_CTF then
+          for I := FLAG_RED to FLAG_BLUE do
+            if gFlags[I].NeedSend then
+            begin
+              gFlags[I].NeedSend := False;
+              MH_SEND_FlagPos(I);
+            end;
+
+        // update items that aren't stationary
+        g_Items_ForEachAlive(sendItemPos);
+
         if reliableUpdate then
         begin
           NetTimeToReliable := 0;
@@ -4320,6 +4352,10 @@ begin
     else
     begin
       gPlayer1.Name := gPlayer1Settings.Name;
+      gPlayer1.WeapSwitchMode := gPlayer1Settings.WeaponSwitch;
+      gPlayer1.setWeaponPrefs(gPlayer1Settings.WeaponPreferences);
+      gPlayer1.SwitchToEmpty := gPlayer1Settings.SwitchToEmpty;
+      gPlayer1.SkipFist := gPlayer1Settings.SkipFist;
       g_Console_Add(Format(_lc[I_PLAYER_JOIN], [gPlayer1.Name]), True);
       if g_Game_IsServer and g_Game_IsNet then
         MH_SEND_PlayerCreate(gPlayer1.UID);
@@ -4350,6 +4386,10 @@ begin
     else
     begin
       gPlayer2.Name := gPlayer2Settings.Name;
+      gPlayer2.WeapSwitchMode := gPlayer2Settings.WeaponSwitch;
+      gPlayer2.setWeaponPrefs(gPlayer2Settings.WeaponPreferences);
+      gPlayer2.SwitchToEmpty := gPlayer2Settings.SwitchToEmpty;
+      gPlayer2.SkipFist := gPlayer2Settings.SkipFist;
       g_Console_Add(Format(_lc[I_PLAYER_JOIN], [gPlayer2.Name]), True);
       if g_Game_IsServer and g_Game_IsNet then
         MH_SEND_PlayerCreate(gPlayer2.UID);
@@ -4465,6 +4505,10 @@ begin
   end;
 
   gPlayer1.Name := gPlayer1Settings.Name;
+  gPlayer1.WeapSwitchMode := gPlayer1Settings.WeaponSwitch;
+  gPlayer1.setWeaponPrefs(gPlayer1Settings.WeaponPreferences);
+  gPlayer1.SwitchToEmpty := gPlayer1Settings.SwitchToEmpty;
+  gPlayer1.SkipFist := gPlayer1Settings.SkipFist;
   nPl := 1;
 
 // Ñîçäàíèå âòîðîãî èãðîêà, åñëè åñòü:
@@ -4480,6 +4524,10 @@ begin
     end;
 
     gPlayer2.Name := gPlayer2Settings.Name;
+    gPlayer2.WeapSwitchMode := gPlayer2Settings.WeaponSwitch;
+    gPlayer2.setWeaponPrefs(gPlayer2Settings.WeaponPreferences);
+    gPlayer2.SwitchToEmpty := gPlayer2Settings.SwitchToEmpty;
+    gPlayer2.SkipFist := gPlayer2Settings.SkipFist;
     Inc(nPl);
   end;
 
@@ -4559,6 +4607,10 @@ begin
     end;
 
     gPlayer1.Name := gPlayer1Settings.Name;
+    gPlayer1.WeapSwitchMode := gPlayer1Settings.WeaponSwitch;
+    gPlayer1.setWeaponPrefs(gPlayer1Settings.WeaponPreferences);
+    gPlayer1.SwitchToEmpty := gPlayer1Settings.SwitchToEmpty;
+    gPlayer1.SkipFist := gPlayer1Settings.SkipFist;
     Inc(nPl);
   end;
 
@@ -4575,6 +4627,10 @@ begin
     end;
 
     gPlayer2.Name := gPlayer2Settings.Name;
+    gPlayer2.WeapSwitchMode := gPlayer2Settings.WeaponSwitch;
+    gPlayer2.setWeaponPrefs(gPlayer2Settings.WeaponPreferences);
+    gPlayer2.SwitchToEmpty := gPlayer2Settings.SwitchToEmpty;
+    gPlayer2.SkipFist := gPlayer2Settings.SkipFist;
     Inc(nPl);
   end;
 
@@ -4662,6 +4718,10 @@ begin
     end;
 
     gPlayer1.Name := gPlayer1Settings.Name;
+    gPlayer1.WeapSwitchMode := gPlayer1Settings.WeaponSwitch;
+    gPlayer1.setWeaponPrefs(gPlayer1Settings.WeaponPreferences);
+    gPlayer1.SwitchToEmpty := gPlayer1Settings.SwitchToEmpty;
+    gPlayer1.SkipFist := gPlayer1Settings.SkipFist;
   end;
 
   if nPlayers >= 2 then
@@ -4677,6 +4737,10 @@ begin
     end;
 
     gPlayer2.Name := gPlayer2Settings.Name;
+    gPlayer2.WeapSwitchMode := gPlayer2Settings.WeaponSwitch;
+    gPlayer2.setWeaponPrefs(gPlayer2Settings.WeaponPreferences);
+    gPlayer2.SwitchToEmpty := gPlayer2Settings.SwitchToEmpty;
+    gPlayer2.SkipFist := gPlayer2Settings.SkipFist;
   end;
 
   g_Game_SetLoadingText(_lc[I_LOAD_HOST], 0, False);
@@ -4855,6 +4919,10 @@ begin
           end;
 
           gPlayer1.Name := gPlayer1Settings.Name;
+          gPlayer1.WeapSwitchMode := gPlayer1Settings.WeaponSwitch;
+          gPlayer1.setWeaponPrefs(gPlayer1Settings.WeaponPreferences);
+          gPlayer1.SwitchToEmpty := gPlayer1Settings.SwitchToEmpty;
+          gPlayer1.SkipFist := gPlayer1Settings.SkipFist;
           gPlayer1.UID := NetPlrUID1;
           gPlayer1.Reset(True);
 
@@ -5539,6 +5607,14 @@ begin
   begin
     ParseGameFlag(GAME_OPTION_MONSTERS, I_MSG_ALLOWMON_OFF, I_MSG_ALLOWMON_ON, True);
   end
+  else if cmd = 'g_allow_dropflag' then
+  begin
+    ParseGameFlag(GAME_OPTION_ALLOWDROPFLAG, I_MSG_ALLOWDROPFLAG_OFF, I_MSG_ALLOWDROPFLAG_ON);
+  end
+  else if cmd = 'g_throw_flag' then
+  begin
+    ParseGameFlag(GAME_OPTION_THROWFLAG, I_MSG_THROWFLAG_OFF, I_MSG_THROWFLAG_ON);
+  end
   else if cmd = 'g_bot_vsplayers' then
   begin
     ParseGameFlag(GAME_OPTION_BOTVSPLAYER, I_MSG_BOTSVSPLAYERS_OFF, I_MSG_BOTSVSPLAYERS_ON);
@@ -5626,7 +5702,7 @@ begin
   begin
     if Length(p) = 2 then
     begin
-      a := Max(0, StrToInt(p[1]));
+      a := Max(0, StrToIntDef(p[1], 0));
       g_GFX_SetMax(a)
     end
     else if Length(p) = 1 then
@@ -5642,7 +5718,7 @@ begin
   begin
     if Length(p) = 2 then
     begin
-      a := Max(0, StrToInt(p[1]));
+      a := Max(0, StrToIntDef(p[1], 0));
       g_Shells_SetMax(a)
     end
     else if Length(p) = 1 then
@@ -5658,7 +5734,7 @@ begin
   begin
     if Length(p) = 2 then
     begin
-      a := Max(0, StrToInt(p[1]));
+      a := Max(0, StrToIntDef(p[1], 0));
       g_Gibs_SetMax(a)
     end
     else if Length(p) = 1 then
@@ -5674,7 +5750,7 @@ begin
   begin
     if Length(p) = 2 then
     begin
-      a := Max(0, StrToInt(p[1]));
+      a := Max(0, StrToIntDef(p[1], 0));
       g_Corpses_SetMax(a)
     end
     else if Length(p) = 1 then
@@ -5732,6 +5808,12 @@ begin
                          (gsTimeLimit div 60) mod 60,
                           gsTimeLimit mod 60]));
   end
+  else if cmd = 'g_max_bots' then
+  begin
+    if Length(P) > 1 then
+      gMaxBots := nclamp(StrToIntDef(P[1], gMaxBots), 0, 127);
+    g_Console_Add('g_max_bots = ' + IntToStr(gMaxBots));
+  end
   else if cmd = 'g_maxlives' then
   begin
     if Length(P) > 1 then
@@ -5883,6 +5965,156 @@ begin
             g_Console_Add(_lc[I_MSG_ONMAPCHANGE]);
         end;
       end;
+    'p1_autoswitch':
+      begin
+        if (Length(P) = 2) then
+          gPlayer1Settings.WeaponSwitch := EnsureRange(StrTointDef(P[1], 0), 0, 2);
+        end;
+    'p2_autoswitch':
+      begin
+        if (Length(P) = 2) then
+          gPlayer2Settings.WeaponSwitch := EnsureRange(StrTointDef(P[1], 0), 0, 2);
+        end;
+    'p1_switch_empty':
+      begin
+        if (Length(P) = 2) then
+          gPlayer1Settings.SwitchToEmpty := EnsureRange(StrTointDef(P[1], 0), 0, 1);
+        end;
+    'p2_switch_empty':
+      begin
+        if (Length(P) = 2) then
+          gPlayer2Settings.SwitchToEmpty := EnsureRange(StrTointDef(P[1], 0), 0, 1);
+        end;
+    'p1_skip_fist':
+      begin
+        if (Length(P) = 2) then
+          gPlayer1Settings.SkipFist := EnsureRange(StrTointDef(P[1], 0), 0, 1);
+        end;
+    'p2_skip_fist':
+      begin
+        if (Length(P) = 2) then
+          gPlayer2Settings.SkipFist := EnsureRange(StrTointDef(P[1], 0), 0, 1);
+        end;
+    'p1_priority_kastet':
+      begin
+        if (Length(P) = 2) then
+          gPlayer1Settings.WeaponPreferences[WEAPON_KASTET] := EnsureRange(StrToIntDef(P[1], WP_FIRST), WP_FIRST, WP_LAST+1); 
+        end;
+    'p2_priority_kastet':
+      begin
+        if (Length(P) = 2) then
+          gPlayer2Settings.WeaponPreferences[WEAPON_KASTET] := EnsureRange(StrToIntDef(P[1], WP_FIRST), WP_FIRST, WP_LAST+1); 
+      end;        
+    'p1_priority_saw':
+      begin
+        if (Length(P) = 2) then
+          gPlayer1Settings.WeaponPreferences[WEAPON_SAW] := EnsureRange(StrToIntDef(P[1], WP_FIRST), WP_FIRST, WP_LAST+1);
+        end;
+    'p2_priority_saw':
+      begin
+        if (Length(P) = 2) then
+          gPlayer2Settings.WeaponPreferences[WEAPON_SAW] := EnsureRange(StrToIntDef(P[1], WP_FIRST), WP_FIRST, WP_LAST+1);
+      end;
+    'p1_priority_pistol':
+      begin
+        if (Length(P) = 2) then
+          gPlayer1Settings.WeaponPreferences[WEAPON_KASTET] := EnsureRange(StrToIntDef(P[1], WP_FIRST), WP_FIRST, WP_LAST+1); 
+        end;
+    'p2_priority_pistol':
+      begin
+        if (Length(P) = 2) then
+          gPlayer2Settings.WeaponPreferences[WEAPON_KASTET] := EnsureRange(StrToIntDef(P[1], WP_FIRST), WP_FIRST, WP_LAST+1); 
+      end;         
+    'p1_priority_shotgun1':
+      begin
+        if (Length(P) = 2) then
+          gPlayer1Settings.WeaponPreferences[WEAPON_SHOTGUN1] := EnsureRange(StrToIntDef(P[1], WP_FIRST), WP_FIRST, WP_LAST+1);
+      end;
+    'p2_priority_shotgun1':
+      begin
+        if (Length(P) = 2) then
+          gPlayer2Settings.WeaponPreferences[WEAPON_SHOTGUN1] := EnsureRange(StrToIntDef(P[1], WP_FIRST), WP_FIRST, WP_LAST+1);
+      end;
+    'p1_priority_shotgun2':
+      begin
+        if (Length(P) = 2) then
+          gPlayer1Settings.WeaponPreferences[WEAPON_SHOTGUN2] := EnsureRange(StrToIntDef(P[1], WP_FIRST), WP_FIRST, WP_LAST+1);
+      end;
+    'p2_priority_shotgun2':
+      begin
+        if (Length(P) = 2) then
+          gPlayer2Settings.WeaponPreferences[WEAPON_SHOTGUN2] := EnsureRange(StrToIntDef(P[1], WP_FIRST), WP_FIRST, WP_LAST+1);
+      end;
+    'p1_priority_chaingun':
+      begin
+        if (Length(P) = 2) then
+          gPlayer1Settings.WeaponPreferences[WEAPON_CHAINGUN] := EnsureRange(StrToIntDef(P[1], WP_FIRST), WP_FIRST, WP_LAST+1);
+      end;
+    'p2_priority_chaingun':
+      begin
+        if (Length(P) = 2) then
+          gPlayer2Settings.WeaponPreferences[WEAPON_CHAINGUN] := EnsureRange(StrToIntDef(P[1], WP_FIRST), WP_FIRST, WP_LAST+1);
+      end;
+    'p1_priority_rocketlauncher':
+      begin
+        if (Length(P) = 2) then
+          gPlayer1Settings.WeaponPreferences[WEAPON_ROCKETLAUNCHER] := EnsureRange(StrToIntDef(P[1], WP_FIRST), WP_FIRST, WP_LAST+1);
+      end;
+    'p2_priority_rocketlauncher':
+      begin
+        if (Length(P) = 2) then
+          gPlayer2Settings.WeaponPreferences[WEAPON_ROCKETLAUNCHER] := EnsureRange(StrToIntDef(P[1], WP_FIRST), WP_FIRST, WP_LAST+1);
+      end;
+    'p1_priority_plasma':
+      begin
+        if (Length(P) = 2) then
+          gPlayer1Settings.WeaponPreferences[WEAPON_PLASMA] := EnsureRange(StrToIntDef(P[1], WP_FIRST), WP_FIRST, WP_LAST+1);
+      end;
+    'p2_priority_plasma':
+      begin
+        if (Length(P) = 2) then
+          gPlayer2Settings.WeaponPreferences[WEAPON_PLASMA] := EnsureRange(StrToIntDef(P[1], WP_FIRST), WP_FIRST, WP_LAST+1);
+      end;
+    'p1_priority_bfg':
+      begin
+        if (Length(P) = 2) then
+          gPlayer1Settings.WeaponPreferences[WEAPON_BFG] := EnsureRange(StrToIntDef(P[1], WP_FIRST), WP_FIRST, WP_LAST+1);
+      end;
+    'p2_priority_bfg':
+      begin
+        if (Length(P) = 2) then
+          gPlayer2Settings.WeaponPreferences[WEAPON_BFG] := EnsureRange(StrToIntDef(P[1], WP_FIRST), WP_FIRST, WP_LAST+1);
+      end;
+    'p1_priority_super':
+      begin
+        if (Length(P) = 2) then
+          gPlayer1Settings.WeaponPreferences[WEAPON_SUPERPULEMET] := EnsureRange(StrToIntDef(P[1], WP_FIRST), WP_FIRST, WP_LAST+1);
+      end;
+    'p2_priority_super':
+      begin
+        if (Length(P) = 2) then
+          gPlayer2Settings.WeaponPreferences[WEAPON_SUPERPULEMET] := EnsureRange(StrToIntDef(P[1], WP_FIRST), WP_FIRST, WP_LAST+1);
+      end;
+    'p1_priority_flamethrower':
+      begin
+        if (Length(P) = 2) then
+          gPlayer1Settings.WeaponPreferences[WEAPON_FLAMETHROWER] := EnsureRange(StrToIntDef(P[1], WP_FIRST), WP_FIRST, WP_LAST+1);
+      end;
+    'p2_priority_flamethrower':
+      begin
+        if (Length(P) = 2) then
+          gPlayer2Settings.WeaponPreferences[WEAPON_FLAMETHROWER] := EnsureRange(StrToIntDef(P[1], WP_FIRST), WP_FIRST, WP_LAST+1);
+      end;      
+    'p1_priority_berserk':
+      begin
+        if (Length(P) = 2) then
+          gPlayer1Settings.WeaponPreferences[WP_LAST+1] := EnsureRange(StrToIntDef(P[1], WP_FIRST), WP_FIRST, WP_LAST+1); 
+        end;
+    'p2_priority_berserk':
+      begin
+        if (Length(P) = 2) then
+          gPlayer2Settings.WeaponPreferences[WP_LAST+1] := EnsureRange(StrToIntDef(P[1], WP_FIRST), WP_FIRST, WP_LAST+1); 
+      end;                                                                                  
   end;
 end;
 
@@ -6751,6 +6983,34 @@ begin
     end else
       g_Console_Add(_lc[I_MSG_GM_UNAVAIL]);
   end
+  else if (cmd = 'an') or (cmd = 'announce') then
+  begin
+    if g_Game_IsNet then
+    begin
+      if Length(P) > 1 then
+      begin
+        for a := 1 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('announce <text>');
+          Exit;
+        end;
+
+        chstr := 'centerprint 100 ' + b_Text_Format(chstr);
+        if g_Game_IsClient then
+          MC_SEND_RCONCommand(chstr)
+        else
+          g_Console_Process(chstr, True);
+      end
+      else
+        g_Console_Add('announce <text>');
+    end else
+      g_Console_Add(_lc[I_MSG_GM_UNAVAIL]);
+  end
   else if cmd = 'game' then
   begin
     if gGameSettings.GameType <> GT_NONE then
@@ -7195,25 +7455,72 @@ begin
   begin
     g_TakeScreenShot()
   end
+  else if (cmd = 'weapnext') or (cmd = 'weapprev') then
+  begin
+    a := 1 - (ord(cmd[5]) - ord('n'));
+    if a = -1 then
+      gWeaponAction[0, WP_PREV] := True;
+    if a = 1 then
+      gWeaponAction[0, WP_NEXT] := True;
+  end
   else if cmd = 'weapon' then
   begin
     if Length(p) = 2 then
     begin
-      a := WP_FIRST + StrToInt(p[1]) - 1;
+      a := WP_FIRST + StrToIntDef(p[1], 0) - 1;
       if (a >= WP_FIRST) and (a <= WP_LAST) then
         gSelectWeapon[0, a] := True
     end
   end
+  else if (cmd = 'p1_weapnext') or (cmd = 'p1_weapprev')
+       or (cmd = 'p2_weapnext') or (cmd = 'p2_weapprev') then
+  begin
+    a := 1 - (ord(cmd[8]) - ord('n'));
+    b := ord(cmd[2]) - ord('1');
+    if a = -1 then
+      gWeaponAction[b, WP_PREV] := True;
+    if a = 1 then
+      gWeaponAction[b, WP_NEXT] := True;
+  end
   else if (cmd = 'p1_weapon') or (cmd = 'p2_weapon') then
   begin
     if Length(p) = 2 then
     begin
-      a := WP_FIRST + StrToInt(p[1]) - 1;
+      a := WP_FIRST + StrToIntDef(p[1], 0) - 1;
       b := ord(cmd[2]) - ord('1');
       if (a >= WP_FIRST) and (a <= WP_LAST) then
         gSelectWeapon[b, a] := True
     end
   end
+  else if (cmd = 'p1_weapbest') or (cmd = 'p2_weapbest') then
+  begin
+    b := ord(cmd[2]) - ord('1');
+    if b = 0 then
+      gSelectWeapon[b, gPlayer1.GetMorePrefered()] := True
+    else
+      gSelectWeapon[b, gPlayer2.GetMorePrefered()] := True;
+  end
+  else if (cmd = 'dropflag') then
+  begin
+    if g_Game_IsServer then
+    begin
+      if gPlayer2 <> nil then gPlayer2.TryDropFlag();
+      if gPlayer1 <> nil then gPlayer1.TryDropFlag();
+    end
+    else
+      MC_SEND_CheatRequest(NET_CHEAT_DROPFLAG);
+  end
+  else if (cmd = 'p1_dropflag') or (cmd = 'p2_dropflag') then
+  begin
+    b := ord(cmd[2]) - ord('1');
+    if g_Game_IsServer then
+    begin
+      if (b = 1) and (gPlayer2 <> nil) then gPlayer2.TryDropFlag()
+      else if (b = 0) and (gPlayer1 <> nil) then gPlayer1.TryDropFlag();
+    end
+    else
+      MC_SEND_CheatRequest(NET_CHEAT_DROPFLAG);
+  end
 // Êîìàíäû Ñâîåé èãðû:
   else if gGameSettings.GameType in [GT_CUSTOM, GT_SERVER, GT_CLIENT] then
   begin
@@ -7503,7 +7810,7 @@ begin
     name := e_CatPath(dir, Filename + '.png');
     s := createDiskFile(name);
     try
-      e_MakeScreenshot(s, gScreenWidth, gScreenHeight);
+      e_MakeScreenshot(s, gWinSizeX, gWinSizeX);
       s.Free;
       g_Console_Add(Format(_lc[I_CONSOLE_SCREENSHOT], [name]))
     except
@@ -8048,9 +8355,9 @@ begin
   while i <= ParamCount do
   begin
     s := ParamStr(i);
-    if (s[1] = '-') and (Length(s) > 1) then
+    if (Length(s) > 1) and (s[1] = '-') then
     begin
-      if (s[2] = '-') and (Length(s) > 2) then
+      if (Length(s) > 2) and (s[2] = '-') then
         begin // Îäèíî÷íûé ïàðàìåòð
           SetLength(pars, Length(pars) + 1);
           with pars[High(pars)] do