DEADSOFTWARE

game: add flag dropping
authorfgsfds <pvt.fgsfds@gmail.com>
Fri, 14 Jan 2022 18:46:50 +0000 (21:46 +0300)
committerfgsfds <pvt.fgsfds@gmail.com>
Fri, 14 Jan 2022 18:46:50 +0000 (21:46 +0300)
use p1_dropflag/p2_dropflag/dropflag, g_allow_dropflag and g_throw_flag for adjustment

src/engine/e_input_sdl2.inc
src/game/g_console.pas
src/game/g_game.pas
src/game/g_language.pas
src/game/g_menu.pas
src/game/g_netmsg.pas
src/game/g_options.pas
src/game/g_player.pas

index d619c517456199c6232dc1a8ba50bb8ae5cfcd06..56416e60a7f506d180fd887ea37758c8e71b63c5 100644 (file)
@@ -120,6 +120,7 @@ const
   IK_S       = SDL_SCANCODE_S;
   IK_D       = SDL_SCANCODE_D;
   IK_Q       = SDL_SCANCODE_Q;
+  IK_R       = SDL_SCANCODE_R;
   IK_E       = SDL_SCANCODE_E;
   IK_H       = SDL_SCANCODE_H;
   IK_J       = SDL_SCANCODE_J;
index 3dd754c56b0e24a2860d1bc4ecb3d494eb904b27..12849af9cb8a94047db132e97234246af1b6500b 100644 (file)
@@ -1046,6 +1046,8 @@ begin
   AddCommand('g_allow_exit', GameCVars);
   AddCommand('g_dm_keys', GameCVars);
   AddCommand('g_allow_monsters', GameCVars);
+  AddCommand('g_allow_dropflag', GameCVars);
+  AddCommand('g_throw_flag', GameCVars);
   AddCommand('g_bot_vsmonsters', GameCVars);
   AddCommand('g_bot_vsplayers', GameCVars);
   AddCommand('g_scorelimit', GameCVars);
@@ -1110,12 +1112,15 @@ begin
   AddCommand('weapnext', GameCommands);
   AddCommand('weapprev', GameCommands);
   AddCommand('weapon', GameCommands);
+  AddCommand('dropflag', GameCommands);
   AddCommand('p1_weapnext', GameCommands);
   AddCommand('p1_weapprev', GameCommands);
   AddCommand('p1_weapon', GameCommands);
+  AddCommand('p1_dropflag', GameCommands);
   AddCommand('p2_weapnext', GameCommands);
   AddCommand('p2_weapprev', GameCommands);
   AddCommand('p2_weapon', GameCommands);
+  AddCommand('p2_dropflag', GameCommands);
 
   AddCommand('god', GameCheats);
   AddCommand('notarget', GameCheats);
@@ -1990,6 +1995,7 @@ begin
   g_Console_BindKey(IK_ALT, '+p1_strafe', '-p1_strafe');
   g_Console_BindKey(IK_E, 'p1_weapnext', '', True);
   g_Console_BindKey(IK_Q, 'p1_weapprev', '', True);
+  g_Console_BindKey(IK_R, 'p1_dropflag', '');
   g_Console_BindKey(IK_1, 'p1_weapon 1');
   g_Console_BindKey(IK_2, 'p1_weapon 2');
   g_Console_BindKey(IK_3, 'p1_weapon 3');
@@ -2154,6 +2160,8 @@ begin
   WriteFlag('g_friendly_hit_projectile ', GAME_OPTION_TEAMHITPROJECTILE);
   WriteFlag('g_allow_exit ', GAME_OPTION_ALLOWEXIT);
   WriteFlag('g_allow_monsters ', GAME_OPTION_MONSTERS);
+  WriteFlag('g_allow_dropflag ', GAME_OPTION_ALLOWDROPFLAG);
+  WriteFlag('g_throw_flag ', GAME_OPTION_THROWFLAG);
   WriteFlag('g_dm_keys ', GAME_OPTION_DMKEYS);
   WriteFlag('g_weaponstay ', GAME_OPTION_WEAPONSTAY);
   WriteFlag('g_bot_vsmonsters ', GAME_OPTION_BOTVSMONSTER);
index 256a564513e88b9c3b08e82e3a2b26209cee7296..add8be44def44354fd817f129e847a4e9c914944 100644 (file)
@@ -186,7 +186,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;
@@ -5541,6 +5543,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);
@@ -7234,6 +7244,27 @@ begin
         gSelectWeapon[b, a] := True
     end
   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
index d79c48c46743721c92b12a3d013b28e5a21f3c25..a7791c6fe7b93a7fffb66a5432207d749f8cfd49 100644 (file)
@@ -177,6 +177,8 @@ type
     I_MENU_BOTS_VS_PLAYERS,
     I_MENU_BOTS_VS_MONSTERS,
     I_MENU_BOTS_VS_ALL,
+    I_MENU_FLAG_DROP,
+    I_MENU_FLAG_THROW,
 
     I_MENU_MAP_WAD,
     I_MENU_MAP_RESOURCE,
@@ -234,6 +236,7 @@ type
     I_MENU_CONTROL_NEXT_WEAPON,
     I_MENU_CONTROL_PREV_WEAPON,
     I_MENU_CONTROL_STRAFE,
+    I_MENU_CONTROL_DROPFLAG,
 
     I_MENU_COUNT_NONE,
     I_MENU_COUNT_SMALL,
@@ -586,6 +589,10 @@ type
     I_MSG_ALLOWEXIT_OFF,
     I_MSG_ALLOWMON_ON,
     I_MSG_ALLOWMON_OFF,
+    I_MSG_ALLOWDROPFLAG_ON,
+    I_MSG_ALLOWDROPFLAG_OFF,
+    I_MSG_THROWFLAG_ON,
+    I_MSG_THROWFLAG_OFF,
     I_MSG_DMKEYS_ON,
     I_MSG_DMKEYS_OFF,
     I_MSG_BOTSVSPLAYERS_ON,
@@ -966,6 +973,10 @@ const
                                        'Ìîíñòðîâ'),
     ('MENU BOTS VS ALL',               'Everybody',
                                        'Âñåõ'),
+    ('MENU FLAG DROP',                 'Flag dropping',
+                                       'Âûáðàñûâàíèå ôëàãà'),
+    ('MENU FLAG THROW',                'Yes, with force',
+                                       'Äà, ñ óñêîðåíèåì'),
 
     ('MENU MAP WAD',                   'Select WAD:',
                                        'Âûáîð WAD''à:'),
@@ -1075,6 +1086,8 @@ const
                                        'Ïðåä. îðóæèå:'),
     ('MENU CONTROL STRAFE',            'Strafe:',
                                        'Ëóííàÿ ïîõîäêà:'),
+    ('MENU CONTROL DROPFLAG',          'Drop flag:',
+                                       'Âûáðîñèòü ôëàã:'),
 
     ('MENU COUNT NONE',                'None',
                                        'Íåò'),
@@ -1745,6 +1758,14 @@ const
                                        'Ìîíñòðû â DM âêëþ÷åíû*'),
     ('MSG ALLOWMON OFF',               'Monsters in DM disabled*',
                                        'Ìîíñòðû â DM âûêëþ÷åíû*'),
+    ('MSG ALLOWDROPFLAG ON',           'dropflag command enabled',
+                                       'Âûáðàñûâàíèå ôëàãà ïî êîìàíäå dropflag âêëþ÷åíî'),
+    ('MSG ALLOWDROPFLAG OFF',          'dropflag command disabled',
+                                       'Âûáðàñûâàíèå ôëàãà ïî êîìàíäå dropflag âûêëþ÷åíî'),
+    ('MSG THROWFLAG ON',               'Dropped flags inherit player momentum',
+                                       'Ôëàã âûáðàñûâàåòñÿ ñ óñêîðåíèåì'),
+    ('MSG THROWFLAG OFF',              'Dropped flags fall straight down',
+                                       'Ôëàã âûáðàñûâàåòñÿ ñòðîãî âíèç'),
     ('MSG DMKEYS ON',                  'Spawning with all keys in DM enabled',
                                        'Ðåñïàâí ñî âñåìè êëþ÷àìè â DM âêëþ÷åí'),
     ('MSG DMKEYS OFF',                 'Spawning with all keys in DM disabled',
index 95a0da30f122c1634ea69c381f02d372d8097e8e..04ffd90df4089a2ff64649478ad1ba764fbfebbc 100644 (file)
@@ -196,6 +196,7 @@ begin
     g_Console_BindKey(g_Console_FindBind(1, '+p1_jump', '-p1_jump'), '');
     g_Console_BindKey(g_Console_FindBind(1, '+p1_activate', '-p1_activate'), '');
     g_Console_BindKey(g_Console_FindBind(1, '+p1_strafe', '-p1_strafe'), '');
+    g_Console_BindKey(g_Console_FindBind(1, 'p1_dropflag', ''), '');
     g_Console_BindKey(g_Console_FindBind(1, 'p1_weapnext', ''), '');
     g_Console_BindKey(g_Console_FindBind(1, 'p1_weapprev', ''), '');
     g_Console_BindKey(TGUIKeyRead2(GetControl(_lc[I_MENU_CONTROL_RIGHT])).Key0, '+p1_moveright', '-p1_moveright');
@@ -206,6 +207,7 @@ begin
     g_Console_BindKey(TGUIKeyRead2(GetControl(_lc[I_MENU_CONTROL_JUMP])).Key0, '+p1_jump', '-p1_jump');
     g_Console_BindKey(TGUIKeyRead2(GetControl(_lc[I_MENU_CONTROL_USE])).Key0, '+p1_activate', '-p1_activate');
     g_Console_BindKey(TGUIKeyRead2(GetControl(_lc[I_MENU_CONTROL_STRAFE])).Key0, '+p1_strafe', '-p1_strafe');
+    g_Console_BindKey(TGUIKeyRead2(GetControl(_lc[I_MENU_CONTROL_DROPFLAG])).Key0, 'p1_dropflag', '');
     g_Console_BindKey(TGUIKeyRead2(GetControl(_lc[I_MENU_CONTROL_NEXT_WEAPON])).Key0, 'p1_weapnext', '', True);
     g_Console_BindKey(TGUIKeyRead2(GetControl(_lc[I_MENU_CONTROL_PREV_WEAPON])).Key0, 'p1_weapprev', '', True);
     // second set
@@ -217,6 +219,7 @@ begin
     g_Console_BindKey(g_Console_FindBind(2, '+p1_jump', '-p1_jump'), '');
     g_Console_BindKey(g_Console_FindBind(2, '+p1_activate', '-p1_activate'), '');
     g_Console_BindKey(g_Console_FindBind(2, '+p1_strafe', '-p1_strafe'), '');
+    g_Console_BindKey(g_Console_FindBind(2, 'p1_dropflag', ''), '');
     g_Console_BindKey(g_Console_FindBind(2, 'p1_weapnext', ''), '');
     g_Console_BindKey(g_Console_FindBind(2, 'p1_weapprev', ''), '');
     g_Console_BindKey(TGUIKeyRead2(GetControl(_lc[I_MENU_CONTROL_RIGHT])).Key1, '+p1_moveright', '-p1_moveright');
@@ -227,6 +230,7 @@ begin
     g_Console_BindKey(TGUIKeyRead2(GetControl(_lc[I_MENU_CONTROL_JUMP])).Key1, '+p1_jump', '-p1_jump');
     g_Console_BindKey(TGUIKeyRead2(GetControl(_lc[I_MENU_CONTROL_USE])).Key1, '+p1_activate', '-p1_activate');
     g_Console_BindKey(TGUIKeyRead2(GetControl(_lc[I_MENU_CONTROL_STRAFE])).Key1, '+p1_strafe', '-p1_strafe');
+    g_Console_BindKey(TGUIKeyRead2(GetControl(_lc[I_MENU_CONTROL_DROPFLAG])).Key1, 'p1_dropflag', '');
     g_Console_BindKey(TGUIKeyRead2(GetControl(_lc[I_MENU_CONTROL_NEXT_WEAPON])).Key1, 'p1_weapnext', '', True);
     g_Console_BindKey(TGUIKeyRead2(GetControl(_lc[I_MENU_CONTROL_PREV_WEAPON])).Key1, 'p1_weapprev', '', True);
   end;
@@ -254,6 +258,7 @@ begin
     g_Console_BindKey(g_Console_FindBind(1, '+p2_jump', '-p2_jump'), '');
     g_Console_BindKey(g_Console_FindBind(1, '+p2_activate', '-p2_activate'), '');
     g_Console_BindKey(g_Console_FindBind(1, '+p2_strafe', '-p2_strafe'), '');
+    g_Console_BindKey(g_Console_FindBind(1, 'p2_dropflag', ''), '');
     g_Console_BindKey(g_Console_FindBind(1, 'p2_weapnext', ''), '');
     g_Console_BindKey(g_Console_FindBind(1, 'p2_weapprev', ''), '');
     g_Console_BindKey(TGUIKeyRead2(GetControl(_lc[I_MENU_CONTROL_RIGHT])).Key0, '+p2_moveright', '-p2_moveright');
@@ -264,6 +269,7 @@ begin
     g_Console_BindKey(TGUIKeyRead2(GetControl(_lc[I_MENU_CONTROL_JUMP])).Key0, '+p2_jump', '-p2_jump');
     g_Console_BindKey(TGUIKeyRead2(GetControl(_lc[I_MENU_CONTROL_USE])).Key0, '+p2_activate', '-p2_activate');
     g_Console_BindKey(TGUIKeyRead2(GetControl(_lc[I_MENU_CONTROL_STRAFE])).Key0, '+p2_strafe', '-p2_strafe');
+    g_Console_BindKey(TGUIKeyRead2(GetControl(_lc[I_MENU_CONTROL_DROPFLAG])).Key0, 'p2_dropflag', '');
     g_Console_BindKey(TGUIKeyRead2(GetControl(_lc[I_MENU_CONTROL_NEXT_WEAPON])).Key0, 'p2_weapnext', '', True);
     g_Console_BindKey(TGUIKeyRead2(GetControl(_lc[I_MENU_CONTROL_PREV_WEAPON])).Key0, 'p2_weapprev', '', True);
     // second set
@@ -275,6 +281,7 @@ begin
     g_Console_BindKey(g_Console_FindBind(2, '+p2_jump', '-p2_jump'), '');
     g_Console_BindKey(g_Console_FindBind(2, '+p2_activate', '-p2_activate'), '');
     g_Console_BindKey(g_Console_FindBind(2, '+p2_strafe', '-p2_strafe'), '');
+    g_Console_BindKey(g_Console_FindBind(2, 'p2_dropflag', ''), '');
     g_Console_BindKey(g_Console_FindBind(2, 'p2_weapnext', ''), '');
     g_Console_BindKey(g_Console_FindBind(2, 'p2_weapprev', ''), '');
     g_Console_BindKey(TGUIKeyRead2(GetControl(_lc[I_MENU_CONTROL_RIGHT])).Key1, '+p2_moveright', '-p2_moveright');
@@ -285,6 +292,7 @@ begin
     g_Console_BindKey(TGUIKeyRead2(GetControl(_lc[I_MENU_CONTROL_JUMP])).Key1, '+p2_jump', '-p2_jump');
     g_Console_BindKey(TGUIKeyRead2(GetControl(_lc[I_MENU_CONTROL_USE])).Key1, '+p2_activate', '-p2_activate');
     g_Console_BindKey(TGUIKeyRead2(GetControl(_lc[I_MENU_CONTROL_STRAFE])).Key1, '+p2_strafe', '-p2_strafe');
+    g_Console_BindKey(TGUIKeyRead2(GetControl(_lc[I_MENU_CONTROL_DROPFLAG])).Key1, 'p2_dropflag', '');
     g_Console_BindKey(TGUIKeyRead2(GetControl(_lc[I_MENU_CONTROL_NEXT_WEAPON])).Key1, 'p2_weapnext', '', True);
     g_Console_BindKey(TGUIKeyRead2(GetControl(_lc[I_MENU_CONTROL_PREV_WEAPON])).Key1, 'p2_weapprev', '', True);
   end;
@@ -441,6 +449,7 @@ begin
     TGUIKeyRead2(GetControl(_lc[I_MENU_CONTROL_JUMP])).Key0 := g_Console_FindBind(1, '+p1_jump', '-p1_jump');
     TGUIKeyRead2(GetControl(_lc[I_MENU_CONTROL_USE])).Key0 := g_Console_FindBind(1, '+p1_activate', '-p1_activate');
     TGUIKeyRead2(GetControl(_lc[I_MENU_CONTROL_STRAFE])).Key0 := g_Console_FindBind(1, '+p1_strafe', '-p1_strafe');
+    TGUIKeyRead2(GetControl(_lc[I_MENU_CONTROL_DROPFLAG])).Key0 := g_Console_FindBind(1, 'p1_dropflag', '');
     TGUIKeyRead2(GetControl(_lc[I_MENU_CONTROL_NEXT_WEAPON])).Key0 := g_Console_FindBind(1, 'p1_weapnext', '');
     TGUIKeyRead2(GetControl(_lc[I_MENU_CONTROL_PREV_WEAPON])).Key0 := g_Console_FindBind(1, 'p1_weapprev', '');
     // second set
@@ -452,6 +461,7 @@ begin
     TGUIKeyRead2(GetControl(_lc[I_MENU_CONTROL_JUMP])).Key1 := g_Console_FindBind(2, '+p1_jump', '-p1_jump');
     TGUIKeyRead2(GetControl(_lc[I_MENU_CONTROL_USE])).Key1 := g_Console_FindBind(2, '+p1_activate', '-p1_activate');
     TGUIKeyRead2(GetControl(_lc[I_MENU_CONTROL_STRAFE])).Key1 := g_Console_FindBind(2, '+p1_strafe', '-p1_strafe');
+    TGUIKeyRead2(GetControl(_lc[I_MENU_CONTROL_DROPFLAG])).Key1 := g_Console_FindBind(2, 'p1_dropflag', '');
     TGUIKeyRead2(GetControl(_lc[I_MENU_CONTROL_NEXT_WEAPON])).Key1 := g_Console_FindBind(2, 'p1_weapnext', '');
     TGUIKeyRead2(GetControl(_lc[I_MENU_CONTROL_PREV_WEAPON])).Key1 := g_Console_FindBind(2, 'p1_weapprev', '');
   end;
@@ -477,6 +487,7 @@ begin
     TGUIKeyRead2(GetControl(_lc[I_MENU_CONTROL_JUMP])).Key0 := g_Console_FindBind(1, '+p2_jump', '-p2_jump');
     TGUIKeyRead2(GetControl(_lc[I_MENU_CONTROL_USE])).Key0 := g_Console_FindBind(1, '+p2_activate', '-p2_activate');
     TGUIKeyRead2(GetControl(_lc[I_MENU_CONTROL_STRAFE])).Key0 := g_Console_FindBind(1, '+p2_strafe', '-p2_strafe');
+    TGUIKeyRead2(GetControl(_lc[I_MENU_CONTROL_DROPFLAG])).Key0 := g_Console_FindBind(1, 'p2_dropflag', '');
     TGUIKeyRead2(GetControl(_lc[I_MENU_CONTROL_NEXT_WEAPON])).Key0 := g_Console_FindBind(1, 'p2_weapnext', '');
     TGUIKeyRead2(GetControl(_lc[I_MENU_CONTROL_PREV_WEAPON])).Key0 := g_Console_FindBind(1, 'p2_weapprev', '');
     // second set
@@ -488,6 +499,7 @@ begin
     TGUIKeyRead2(GetControl(_lc[I_MENU_CONTROL_JUMP])).Key1 := g_Console_FindBind(2, '+p2_jump', '-p2_jump');
     TGUIKeyRead2(GetControl(_lc[I_MENU_CONTROL_USE])).Key1 := g_Console_FindBind(2, '+p2_activate', '-p2_activate');
     TGUIKeyRead2(GetControl(_lc[I_MENU_CONTROL_STRAFE])).Key1 := g_Console_FindBind(2, '+p2_strafe', '-p2_strafe');
+    TGUIKeyRead2(GetControl(_lc[I_MENU_CONTROL_DROPFLAG])).Key1 := g_Console_FindBind(2, 'p2_dropflag', '');
     TGUIKeyRead2(GetControl(_lc[I_MENU_CONTROL_NEXT_WEAPON])).Key1 := g_Console_FindBind(2, 'p2_weapnext', '');
     TGUIKeyRead2(GetControl(_lc[I_MENU_CONTROL_PREV_WEAPON])).Key1 := g_Console_FindBind(2, 'p2_weapprev', '');
   end;
@@ -693,6 +705,12 @@ begin
       else gsGameFlags := gsGameFlags or GAME_OPTION_BOTVSPLAYER;
     end;
 
+    case TGUISwitch(GetControl('swFlagDrop')).ItemIndex of
+      0: gsGameFlags := gsGameFlags or GAME_OPTION_ALLOWDROPFLAG or GAME_OPTION_THROWFLAG;
+      1: gsGameFlags := gsGameFlags or GAME_OPTION_ALLOWDROPFLAG;
+      else gsGameFlags := gsGameFlags and not (GAME_OPTION_ALLOWDROPFLAG or GAME_OPTION_THROWFLAG);
+    end;
+
     // TODO: get this crap out of here
     gGameSettings.ItemRespawnTime := gsItemRespawnTime;
     gGameSettings.WarmupTime := gsWarmupTime;
@@ -1655,6 +1673,13 @@ begin
         ItemIndex := 0
       else
         ItemIndex := 1;
+    with TGUISwitch(menu.GetControl('swFlagDrop')) do
+      if LongBool(Options and GAME_OPTION_ALLOWDROPFLAG) and LongBool(Options and GAME_OPTION_THROWFLAG) then
+        ItemIndex := 0
+      else if LongBool(Options and GAME_OPTION_ALLOWDROPFLAG) then
+        ItemIndex := 1
+      else
+        ItemIndex := 2;
 
     TGUIEdit(menu.GetControl('edTimeLimit')).Text := IntToStr(TimeLimit);
     TGUIEdit(menu.GetControl('edGoalLimit')).Text := IntToStr(GoalLimit);
@@ -1691,6 +1716,7 @@ begin
         TGUIEdit(menu.GetControl('edMaxLives')).Enabled := True;
         TGUILabel(menu.GetControlsText('edMaxLives')).Color := MENU_ITEMSTEXT_COLOR;
         TGUISwitch(menu.GetControl('swBotsVS')).Enabled := True;
+        TGUISwitch(menu.GetControl('swFlagDrop')).Enabled := True;
       end
     else
       begin
@@ -1717,6 +1743,7 @@ begin
         end;
         TGUILabel(menu.GetControlsText('edMaxLives')).Color := MENU_UNACTIVEITEMS_COLOR;
         TGUISwitch(menu.GetControl('swBotsVS')).Enabled := True;
+        TGUISwitch(menu.GetControl('swFlagDrop')).Enabled := False;
       end;
   end;
 end;
@@ -1838,6 +1865,15 @@ begin
       end;
     end;
 
+    if TGUISwitch(menu.GetControl('swFlagDrop')).Enabled then
+    begin
+      case TGUISwitch(menu.GetControl('swFlagDrop')).ItemIndex of
+        0: Options := Options or GAME_OPTION_ALLOWDROPFLAG or GAME_OPTION_THROWFLAG;
+        1: Options := Options or GAME_OPTION_ALLOWDROPFLAG;
+        else Options := Options and not (GAME_OPTION_ALLOWDROPFLAG or GAME_OPTION_THROWFLAG);
+      end;
+    end;
+
     // don't forget to latch this shit
     gsGameFlags := Options;
     gsMaxLives := MaxLives;
@@ -2288,6 +2324,19 @@ begin
       if not LongBool(gsGameFlags and GAME_OPTION_BOTVSPLAYER) then
         ItemIndex := 1;
     end;
+    with AddSwitch(_lc[I_MENU_FLAG_DROP]) do
+    begin
+      Name := 'swFlagDrop';
+      AddItem(_lc[I_MENU_FLAG_THROW]);
+      AddItem(_lc[I_MENU_YES]);
+      AddItem(_lc[I_MENU_NO]);
+      if (gsGameFlags and (GAME_OPTION_ALLOWDROPFLAG or GAME_OPTION_THROWFLAG)) = (GAME_OPTION_ALLOWDROPFLAG or GAME_OPTION_THROWFLAG) then
+        ItemIndex := 0
+      else if LongBool(gsGameFlags and GAME_OPTION_ALLOWDROPFLAG) then
+        ItemIndex := 1
+      else
+        ItemIndex := 2;
+    end;
     AddSpace();
     AddButton(@ProcStartNetGame, _lc[I_MENU_START_GAME]);
 
@@ -2523,6 +2572,19 @@ begin
       if not LongBool(gsGameFlags and GAME_OPTION_BOTVSPLAYER) then
         ItemIndex := 1;
     end;
+    with AddSwitch(_lc[I_MENU_FLAG_DROP]) do
+    begin
+      Name := 'swFlagDrop';
+      AddItem(_lc[I_MENU_FLAG_THROW]);
+      AddItem(_lc[I_MENU_YES]);
+      AddItem(_lc[I_MENU_NO]);
+      if (gsGameFlags and (GAME_OPTION_ALLOWDROPFLAG or GAME_OPTION_THROWFLAG)) = (GAME_OPTION_ALLOWDROPFLAG or GAME_OPTION_THROWFLAG) then
+        ItemIndex := 0
+      else if LongBool(gsGameFlags and GAME_OPTION_ALLOWDROPFLAG) then
+        ItemIndex := 1
+      else
+        ItemIndex := 2;
+    end;
     AddSpace();
     AddButton(@ProcStartCustomGame, _lc[I_MENU_START_GAME]);
 
@@ -2977,6 +3039,7 @@ begin
     AddKeyRead2(_lc[I_MENU_CONTROL_NEXT_WEAPON]).Name := _lc[I_MENU_CONTROL_NEXT_WEAPON];
     AddKeyRead2(_lc[I_MENU_CONTROL_PREV_WEAPON]).Name := _lc[I_MENU_CONTROL_PREV_WEAPON];
     AddKeyRead2(_lc[I_MENU_CONTROL_STRAFE]).Name := _lc[I_MENU_CONTROL_STRAFE];
+    AddKeyRead2(_lc[I_MENU_CONTROL_DROPFLAG]).Name := _lc[I_MENU_CONTROL_DROPFLAG];
   end;
   Menu.DefControl := 'mOptionsControlsP1Menu';
   g_GUI_AddWindow(Menu);
@@ -3006,6 +3069,7 @@ begin
     AddKeyRead2(_lc[I_MENU_CONTROL_NEXT_WEAPON]).Name := _lc[I_MENU_CONTROL_NEXT_WEAPON];
     AddKeyRead2(_lc[I_MENU_CONTROL_PREV_WEAPON]).Name := _lc[I_MENU_CONTROL_PREV_WEAPON];
     AddKeyRead2(_lc[I_MENU_CONTROL_STRAFE]).Name := _lc[I_MENU_CONTROL_STRAFE];
+    AddKeyRead2(_lc[I_MENU_CONTROL_DROPFLAG]).Name := _lc[I_MENU_CONTROL_DROPFLAG];
   end;
   Menu.DefControl := 'mOptionsControlsP2Menu';
   g_GUI_AddWindow(Menu);
@@ -3399,6 +3463,14 @@ begin
       AddItem(_lc[I_MENU_BOTS_VS_ALL]);
       ItemIndex := 2;
     end;
+    with AddSwitch(_lc[I_MENU_FLAG_DROP]) do
+    begin
+      Name := 'swFlagDrop';
+      AddItem(_lc[I_MENU_FLAG_THROW]);
+      AddItem(_lc[I_MENU_YES]);
+      AddItem(_lc[I_MENU_NO]);
+      ItemIndex := 2;
+    end;
 
     ReAlign();
   end;
index 6d004e814fcb61fcb5aea62b26126a5cc3138778..0a4facfdbdc7a0fe1c91cd362962b5fc7e3dadc1 100644 (file)
@@ -129,6 +129,7 @@ const
   NET_CHEAT_SUICIDE  = 1;
   NET_CHEAT_SPECTATE = 2;
   NET_CHEAT_READY    = 3;
+  NET_CHEAT_DROPFLAG = 4;
 
   NET_MAX_DIFFTIME = 5000 div 36;
 
@@ -625,6 +626,8 @@ begin
         Dec(gInterReadyCount);
       end;
     end;
+    NET_CHEAT_DROPFLAG:
+      Pl.TryDropFlag();
   end;
 end;
 
index 59028f5534bb6772957420c8071eacb21605d3be..853c612964cda47af0fe40d2d824ec27216a77dc 100644 (file)
@@ -271,7 +271,8 @@ begin
   gsItemRespawnTime := 60;
   gsGameFlags := GAME_OPTION_ALLOWEXIT or GAME_OPTION_DMKEYS or
     GAME_OPTION_BOTVSPLAYER or GAME_OPTION_BOTVSMONSTER or
-    GAME_OPTION_TEAMHITTRACE or GAME_OPTION_TEAMHITPROJECTILE;
+    GAME_OPTION_TEAMHITTRACE or GAME_OPTION_TEAMHITPROJECTILE or
+    GAME_OPTION_ALLOWDROPFLAG;
   gsPlayers := 1;
 
   if not gGameOn then
index 3025ea549a1fe28480c9588c30c2094a1eee4f39..759450b25be60295da39a099a2a12d68e6ac2bdf 100644 (file)
@@ -310,7 +310,8 @@ type
     procedure   BFGHit();
     function    GetFlag(Flag: Byte): Boolean;
     procedure   SetFlag(Flag: Byte);
-    function    DropFlag(Silent: Boolean = True): Boolean;
+    function    DropFlag(Silent: Boolean = True; DoThrow: Boolean = False): Boolean;
+    function    TryDropFlag(): Boolean;
     procedure   AllRulez(Health: Boolean);
     procedure   RestoreHealthArmor();
     procedure   FragCombo();
@@ -5763,10 +5764,19 @@ begin
     FModel.SetFlag(FFlag);
 end;
 
-function TPlayer.DropFlag(Silent: Boolean = True): Boolean;
+function TPlayer.TryDropFlag(): Boolean;
+begin
+  if LongBool(gGameSettings.Options and GAME_OPTION_ALLOWDROPFLAG) then
+    Result := DropFlag(False, LongBool(gGameSettings.Options and GAME_OPTION_THROWFLAG))
+  else
+    Result := False;
+end;
+
+function TPlayer.DropFlag(Silent: Boolean = True; DoThrow: Boolean = False): Boolean;
 var
   s: String;
   a: Byte;
+  xv, yv: Integer;
 begin
   Result := False;
   if (not g_Game_IsServer) or (FFlag = FLAG_NONE) then
@@ -5779,8 +5789,18 @@ begin
     Direction := FDirection;
     State := FLAG_STATE_DROPPED;
     Count := FLAG_TIME;
-    g_Obj_Push(@Obj, (FObj.Vel.X div 2)-2+Random(5),
-                     (FObj.Vel.Y div 2)-2+Random(5));
+    if DoThrow then
+    begin
+      xv := FObj.Vel.X + IfThen(Direction = TDirection.D_RIGHT, 10, -10);
+      yv := FObj.Vel.Y - 2;
+    end
+    else
+    begin
+      xv := (FObj.Vel.X div 2);
+      yv := (FObj.Vel.Y div 2) - 2;
+    end;
+    g_Obj_Push(@Obj, xv, yv);
+
     positionChanged(); // this updates spatial accelerators
 
     if FFlag = FLAG_RED then