DEADSOFTWARE

Game: Weapon autoswitch by travi$
[d2df-sdl.git] / src / game / g_player.pas
index 3025ea549a1fe28480c9588c30c2094a1eee4f39..80ab62efd2f1318a793c5d971f765d08bc91088c 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();
@@ -3876,6 +3877,7 @@ function TPlayer.PickItem(ItemType: Byte; arespawn: Boolean; var remove: Boolean
 
 var
   a: Boolean;
+  hadWeapon: Boolean;
 begin
   Result := False;
   if g_Game_IsClient then Exit;
@@ -3949,7 +3951,18 @@ begin
     ITEM_WEAPON_SAW:
       if (not FWeapon[WEAPON_SAW]) or ((not arespawn) and (gGameSettings.GameMode in [GM_DM, GM_TDM, GM_CTF])) then
       begin
-        FWeapon[WEAPON_SAW] := True;
+        if ( (gWeaponAutoswitch = True) and ((g_Game_IsNet = False or (NetMode = NET_SERVER)) and ((Self = gPlayer1) or (Self = gPlayer2)))) then
+        begin
+          hadWeapon := FWeapon[WEAPON_SAW];
+          FWeapon[WEAPON_SAW] := True;
+          if (hadWeapon = False) then
+          begin
+            FCurrWeap := WEAPON_SAW;
+            resetWeaponQueue();
+            FModel.SetWeapon(WEAPON_SAW);
+          end;
+        end
+        else FWeapon[WEAPON_SAW] := True;
         Result := True;
         if gFlash = 2 then Inc(FPickup, 5);
         if a and g_Game_IsNet then MH_SEND_Sound(GameX, GameY, 'SOUND_ITEM_GETWEAPON');
@@ -3960,9 +3973,19 @@ begin
       begin
         // Íóæíî, ÷òîáû íå âçÿòü âñå ïóëè ñðàçó:
         if a and FWeapon[WEAPON_SHOTGUN1] then Exit;
-
         IncMax(FAmmo[A_SHELLS], 4, FMaxAmmo[A_SHELLS]);
-        FWeapon[WEAPON_SHOTGUN1] := True;
+        if ( (gWeaponAutoswitch = True) and ((g_Game_IsNet = False or (NetMode = NET_SERVER)) and ((Self = gPlayer1) or (Self = gPlayer2)))) then
+        begin
+          hadWeapon := FWeapon[WEAPON_SHOTGUN1];
+          FWeapon[WEAPON_SHOTGUN1] := True;
+          if (hadWeapon = False) then
+          begin
+            FCurrWeap := WEAPON_SHOTGUN1;
+            resetWeaponQueue();
+            FModel.SetWeapon(WEAPON_SHOTGUN1);
+          end;
+        end
+        else FWeapon[WEAPON_SHOTGUN1] := True;
         Result := True;
         if gFlash = 2 then Inc(FPickup, 5);
         if a and g_Game_IsNet then MH_SEND_Sound(GameX, GameY, 'SOUND_ITEM_GETWEAPON');
@@ -3972,9 +3995,19 @@ begin
       if (FAmmo[A_SHELLS] < FMaxAmmo[A_SHELLS]) or not FWeapon[WEAPON_SHOTGUN2] then
       begin
         if a and FWeapon[WEAPON_SHOTGUN2] then Exit;
-
+        if ( (gWeaponAutoswitch = True) and ((g_Game_IsNet = False or (NetMode = NET_SERVER)) and ((Self = gPlayer1) or (Self = gPlayer2)))) then
+        begin
+          hadWeapon := FWeapon[WEAPON_SHOTGUN2];
+          FWeapon[WEAPON_SHOTGUN2] := True;
+          if (hadWeapon = False) then
+          begin
+            FCurrWeap := WEAPON_SHOTGUN2;
+            resetWeaponQueue();
+            FModel.SetWeapon(WEAPON_SHOTGUN2);
+          end;
+        end
+        else FWeapon[WEAPON_SHOTGUN2] := True;
         IncMax(FAmmo[A_SHELLS], 4, FMaxAmmo[A_SHELLS]);
-        FWeapon[WEAPON_SHOTGUN2] := True;
         Result := True;
         if gFlash = 2 then Inc(FPickup, 5);
         if a and g_Game_IsNet then MH_SEND_Sound(GameX, GameY, 'SOUND_ITEM_GETWEAPON');
@@ -3984,9 +4017,19 @@ begin
       if (FAmmo[A_BULLETS] < FMaxAmmo[A_BULLETS]) or not FWeapon[WEAPON_CHAINGUN] then
       begin
         if a and FWeapon[WEAPON_CHAINGUN] then Exit;
-
+        if ( (gWeaponAutoswitch = True) and ((g_Game_IsNet = False or (NetMode = NET_SERVER)) and ((Self = gPlayer1) or (Self = gPlayer2)))) then
+        begin
+          hadWeapon := FWeapon[WEAPON_CHAINGUN];
+          FWeapon[WEAPON_CHAINGUN] := True;
+          if (hadWeapon = False) then
+          begin
+            FCurrWeap := WEAPON_CHAINGUN;
+            resetWeaponQueue();
+            FModel.SetWeapon(WEAPON_CHAINGUN);
+          end;
+        end
+        else FWeapon[WEAPON_CHAINGUN] := True;
         IncMax(FAmmo[A_BULLETS], 50, FMaxAmmo[A_BULLETS]);
-        FWeapon[WEAPON_CHAINGUN] := True;
         Result := True;
         if gFlash = 2 then Inc(FPickup, 5);
         if a and g_Game_IsNet then MH_SEND_Sound(GameX, GameY, 'SOUND_ITEM_GETWEAPON');
@@ -3996,9 +4039,19 @@ begin
       if (FAmmo[A_ROCKETS] < FMaxAmmo[A_ROCKETS]) or not FWeapon[WEAPON_ROCKETLAUNCHER] then
       begin
         if a and FWeapon[WEAPON_ROCKETLAUNCHER] then Exit;
-
+        if ( (gWeaponAutoswitch = True) and ((g_Game_IsNet = False or (NetMode = NET_SERVER)) and ((Self = gPlayer1) or (Self = gPlayer2)))) then
+        begin
+          hadWeapon := FWeapon[WEAPON_ROCKETLAUNCHER];
+          FWeapon[WEAPON_ROCKETLAUNCHER] := True;
+          if (hadWeapon = False) then
+          begin
+            FCurrWeap := WEAPON_ROCKETLAUNCHER;
+            resetWeaponQueue();
+            FModel.SetWeapon(WEAPON_ROCKETLAUNCHER);
+          end;
+        end
+        else FWeapon[WEAPON_ROCKETLAUNCHER] := True;
         IncMax(FAmmo[A_ROCKETS], 2, FMaxAmmo[A_ROCKETS]);
-        FWeapon[WEAPON_ROCKETLAUNCHER] := True;
         Result := True;
         if gFlash = 2 then Inc(FPickup, 5);
         if a and g_Game_IsNet then MH_SEND_Sound(GameX, GameY, 'SOUND_ITEM_GETWEAPON');
@@ -4008,9 +4061,19 @@ begin
       if (FAmmo[A_CELLS] < FMaxAmmo[A_CELLS]) or not FWeapon[WEAPON_PLASMA] then
       begin
         if a and FWeapon[WEAPON_PLASMA] then Exit;
-
+        if ( (gWeaponAutoswitch = True) and ((g_Game_IsNet = False or (NetMode = NET_SERVER)) and ((Self = gPlayer1) or (Self = gPlayer2)))) then
+        begin
+          hadWeapon := FWeapon[WEAPON_PLASMA];
+          FWeapon[WEAPON_PLASMA] := True;
+          if (hadWeapon = False) then
+          begin
+            FCurrWeap := WEAPON_PLASMA;
+            resetWeaponQueue();
+            FModel.SetWeapon(WEAPON_PLASMA);
+          end;
+        end
+        else FWeapon[WEAPON_PLASMA] := True;
         IncMax(FAmmo[A_CELLS], 40, FMaxAmmo[A_CELLS]);
-        FWeapon[WEAPON_PLASMA] := True;
         Result := True;
         if gFlash = 2 then Inc(FPickup, 5);
         if a and g_Game_IsNet then MH_SEND_Sound(GameX, GameY, 'SOUND_ITEM_GETWEAPON');
@@ -4020,9 +4083,19 @@ begin
       if (FAmmo[A_CELLS] < FMaxAmmo[A_CELLS]) or not FWeapon[WEAPON_BFG] then
       begin
         if a and FWeapon[WEAPON_BFG] then Exit;
-
+        if ( (gWeaponAutoswitch = True) and ((g_Game_IsNet = False or (NetMode = NET_SERVER)) and ((Self = gPlayer1) or (Self = gPlayer2)))) then
+        begin
+          hadWeapon := FWeapon[WEAPON_BFG];
+          FWeapon[WEAPON_BFG] := True;
+          if (hadWeapon = False) then
+          begin
+            FCurrWeap := WEAPON_BFG;
+            resetWeaponQueue();
+            FModel.SetWeapon(WEAPON_BFG);
+          end;
+        end
+        else FWeapon[WEAPON_BFG] := True;
         IncMax(FAmmo[A_CELLS], 40, FMaxAmmo[A_CELLS]);
-        FWeapon[WEAPON_BFG] := True;
         Result := True;
         if gFlash = 2 then Inc(FPickup, 5);
         if a and g_Game_IsNet then MH_SEND_Sound(GameX, GameY, 'SOUND_ITEM_GETWEAPON');
@@ -4032,9 +4105,19 @@ begin
       if (FAmmo[A_SHELLS] < FMaxAmmo[A_SHELLS]) or not FWeapon[WEAPON_SUPERPULEMET] then
       begin
         if a and FWeapon[WEAPON_SUPERPULEMET] then Exit;
-
+        if ( (gWeaponAutoswitch = True) and ((g_Game_IsNet = False or (NetMode = NET_SERVER)) and ((Self = gPlayer1) or (Self = gPlayer2)))) then
+        begin
+          hadWeapon := FWeapon[WEAPON_SUPERPULEMET];
+          FWeapon[WEAPON_SUPERPULEMET] := True;
+          if (hadWeapon = False) then
+          begin
+            FCurrWeap := WEAPON_SUPERPULEMET;
+            resetWeaponQueue();
+            FModel.SetWeapon(WEAPON_SUPERPULEMET);
+          end;
+        end
+        else FWeapon[WEAPON_SUPERPULEMET] := True;
         IncMax(FAmmo[A_SHELLS], 4, FMaxAmmo[A_SHELLS]);
-        FWeapon[WEAPON_SUPERPULEMET] := True;
         Result := True;
         if gFlash = 2 then Inc(FPickup, 5);
         if a and g_Game_IsNet then MH_SEND_Sound(GameX, GameY, 'SOUND_ITEM_GETWEAPON');
@@ -4044,9 +4127,19 @@ begin
       if (FAmmo[A_FUEL] < FMaxAmmo[A_FUEL]) or not FWeapon[WEAPON_FLAMETHROWER] then
       begin
         if a and FWeapon[WEAPON_FLAMETHROWER] then Exit;
-
+        if ( (gWeaponAutoswitch = True) and ((g_Game_IsNet = False or (NetMode = NET_SERVER)) and ((Self = gPlayer1) or (Self = gPlayer2)))) then
+        begin
+          hadWeapon := FWeapon[WEAPON_FLAMETHROWER];
+          FWeapon[WEAPON_FLAMETHROWER] := True;
+          if (hadWeapon = False) then
+          begin
+            FCurrWeap := WEAPON_FLAMETHROWER;
+            resetWeaponQueue();
+            FModel.SetWeapon(WEAPON_FLAMETHROWER);
+          end;
+        end
+        else FWeapon[WEAPON_FLAMETHROWER] := True;
         IncMax(FAmmo[A_FUEL], 100, FMaxAmmo[A_FUEL]);
-        FWeapon[WEAPON_FLAMETHROWER] := True;
         Result := True;
         if gFlash = 2 then Inc(FPickup, 5);
         if a and g_Game_IsNet then MH_SEND_Sound(GameX, GameY, 'SOUND_ITEM_GETWEAPON');
@@ -4926,7 +5019,7 @@ begin
       DoLerp(4);
 
   if NetServer then
-    if FClientID >= 0 then
+    if (FClientID >= 0) and (NetClients[FClientID].Peer <> nil) then
     begin
       FPing := NetClients[FClientID].Peer^.lastRoundTripTime;
       if NetClients[FClientID].Peer^.packetsSent > 0 then
@@ -5763,10 +5856,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 +5881,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
@@ -7900,4 +8012,5 @@ begin
   conRegVar('cheat_berserk_autoswitch', @gBerserkAutoswitch, 'autoswitch to fist when berserk pack taken', '',  true, true);
   conRegVar('player_indicator', @gPlayerIndicator, 'Draw indicator only for current player, also for teammates, or not at all', 'Draw indicator only for current player, also for teammates, or not at all');
   conRegVar('player_indicator_style', @gPlayerIndicatorStyle, 'Visual appearance of indicator', 'Visual appearance of indicator');
+  conRegVar('weapon_autoswitch', @gWeaponAutoswitch, 'Automatically switch to a first time picked up weapon', '');
 end.