DEADSOFTWARE

game: add option to disable hits on friendly players
authorfgsfds <pvt.fgsfds@gmail.com>
Thu, 6 May 2021 14:18:48 +0000 (17:18 +0300)
committerfgsfds <pvt.fgsfds@gmail.com>
Thu, 6 May 2021 14:18:57 +0000 (17:18 +0300)
src/game/g_console.pas
src/game/g_game.pas
src/game/g_language.pas
src/game/g_menu.pas
src/game/g_weapons.pas

index bbbd1c2024df8a367eff8f7beb22a575c427ba83..8eaad1226f490e9620fcce2e42fed3a1029f9fc5 100644 (file)
@@ -1039,6 +1039,8 @@ begin
   AddCommand('g_max_corpses', GameCVars);
   AddCommand('g_gamemode', GameCVars);
   AddCommand('g_friendlyfire', GameCVars);
+  AddCommand('g_friendly_hit_trace', GameCVars);
+  AddCommand('g_friendly_hit_projectile', GameCVars);
   AddCommand('g_weaponstay', GameCVars);
   AddCommand('g_allow_exit', GameCVars);
   AddCommand('g_dm_keys', GameCVars);
@@ -1154,6 +1156,8 @@ begin
 
   WhitelistCommand('g_gamemode');
   WhitelistCommand('g_friendlyfire');
+  WhitelistCommand('g_friendly_hit_trace');
+  WhitelistCommand('g_friendly_hit_projectile');
   WhitelistCommand('g_weaponstay');
   WhitelistCommand('g_allow_exit');
   WhitelistCommand('g_dm_keys');
@@ -2132,6 +2136,8 @@ begin
   WriteLn(f, 'g_warmup_time ', gsWarmupTime);
 
   WriteFlag('g_friendlyfire ', GAME_OPTION_TEAMDAMAGE);
+  WriteFlag('g_friendly_hit_trace ', GAME_OPTION_TEAMHITTRACE);
+  WriteFlag('g_friendly_hit_projectile ', GAME_OPTION_TEAMHITPROJECTILE);
   WriteFlag('g_allow_exit ', GAME_OPTION_ALLOWEXIT);
   WriteFlag('g_allow_monsters ', GAME_OPTION_MONSTERS);
   WriteFlag('g_dm_keys ', GAME_OPTION_DMKEYS);
index 2fd8408553a14a0c8efa24b8a4653d9972d44c34..2cf72c1bcc17dc8ceb2cb1b7f2ef140a2500a803 100644 (file)
@@ -176,14 +176,16 @@ const
   EXIT_ENDLEVELSINGLE  = 4;
   EXIT_ENDLEVELCUSTOM  = 5;
 
-  GAME_OPTION_RESERVED     = 1;
-  GAME_OPTION_TEAMDAMAGE   = 2;
-  GAME_OPTION_ALLOWEXIT    = 4;
-  GAME_OPTION_WEAPONSTAY   = 8;
-  GAME_OPTION_MONSTERS     = 16;
-  GAME_OPTION_BOTVSPLAYER  = 32;
-  GAME_OPTION_BOTVSMONSTER = 64;
-  GAME_OPTION_DMKEYS       = 128;
+  GAME_OPTION_RESERVED          = 1;
+  GAME_OPTION_TEAMDAMAGE        = 2;
+  GAME_OPTION_ALLOWEXIT         = 4;
+  GAME_OPTION_WEAPONSTAY        = 8;
+  GAME_OPTION_MONSTERS          = 16;
+  GAME_OPTION_BOTVSPLAYER       = 32;
+  GAME_OPTION_BOTVSMONSTER      = 64;
+  GAME_OPTION_DMKEYS            = 128;
+  GAME_OPTION_TEAMHITTRACE      = 256;
+  GAME_OPTION_TEAMHITPROJECTILE = 512;
 
   STATE_NONE        = 0;
   STATE_MENU        = 1;
@@ -5510,6 +5512,14 @@ begin
   begin
     ParseGameFlag(GAME_OPTION_TEAMDAMAGE, I_MSG_FRIENDLY_FIRE_OFF, I_MSG_FRIENDLY_FIRE_ON);
   end
+  else if cmd = 'g_friendly_hit_trace' then
+  begin
+    ParseGameFlag(GAME_OPTION_TEAMHITTRACE, I_MSG_FRIENDLY_FIRE_OFF, I_MSG_FRIENDLY_FIRE_ON);
+  end
+  else if cmd = 'g_friendly_hit_projectile' then
+  begin
+    ParseGameFlag(GAME_OPTION_TEAMHITPROJECTILE, I_MSG_FRIENDLY_FIRE_OFF, I_MSG_FRIENDLY_FIRE_ON);
+  end
   else if cmd = 'g_weaponstay' then
   begin
     ParseGameFlag(GAME_OPTION_WEAPONSTAY, I_MSG_WEAPONSTAY_OFF, I_MSG_WEAPONSTAY_ON);
index dc216c9a8306238f9c31ce4831e0962c30df63a3..8e821af1c1404b3f37c2944033a23b211de28fda 100644 (file)
@@ -163,6 +163,11 @@ type
     I_MENU_GOAL_LIMIT,
     I_MENU_MAX_LIVES,
     I_MENU_TEAM_DAMAGE,
+    I_MENU_TEAM_HIT,
+    I_MENU_TEAM_HIT_BOTH,
+    I_MENU_TEAM_HIT_TRACE,
+    I_MENU_TEAM_HIT_PROJECTILE,
+    I_MENU_TEAM_HIT_NOTHING,
     I_MENU_ITEM_RESPAWN_TIME,
     I_MENU_DEATHMATCH_KEYS,
     I_MENU_ENABLE_EXITS,
@@ -927,6 +932,16 @@ const
                                        'Æèçíè:'),
     ('MENU TEAM DAMAGE',               'Friendly Fire:',
                                        'Óðîí ñâîèõ:'),
+    ('MENU TEAM HIT',                  'Hit friendlies with:',
+                                       'Ïîïàäàíèÿ ïî ñâîèì:'),
+    ('MENU TEAM HIT BOTH',             'Everything',
+                                       'Ïóëÿìè è ñíàðÿäàìè'),
+    ('MENU TEAM HIT TRACE',            'Hitscan only',
+                                       'Òîëüêî ïóëÿìè'),
+    ('MENU TEAM HIT PROJECTILE',       'Projectiles only',
+                                       'Òîëüêî ñíàðÿäàìè'),
+    ('MENU TEAM HIT NONE',             'Nothing',
+                                       'Íè÷åì'),
     ('MENU ITEM RESPAWN TIME',         'Item respawn time:',
                                        'Âðåìÿ ðåñïàâíà ïðåäìåòîâ:'),
     ('MENU DEATHMATCH KEYS',           'Give all keys in DM:',
index 484b513c208e50a63f9175c540fbd6c53fb45fb3..bd213148c20374d88faf9ef963fd0605124eac46 100644 (file)
@@ -681,6 +681,12 @@ begin
     if TGUISwitch(GetControl('swMonsters')).ItemIndex = 0 then
       gsGameFlags := gsGameFlags or GAME_OPTION_MONSTERS;
 
+    case TGUISwitch(GetControl('swTeamHit')).ItemIndex of
+      1: gsGameFlags := gsGameFlags or GAME_OPTION_TEAMHITTRACE;
+      2: gsGameFlags := gsGameFlags or GAME_OPTION_TEAMHITPROJECTILE;
+      0: gsGameFlags := gsGameFlags or GAME_OPTION_TEAMHITTRACE or GAME_OPTION_TEAMHITPROJECTILE;
+    end;
+
     case TGUISwitch(GetControl('swBotsVS')).ItemIndex of
       1: gsGameFlags := gsGameFlags or GAME_OPTION_BOTVSMONSTER;
       2: gsGameFlags := gsGameFlags or GAME_OPTION_BOTVSPLAYER or GAME_OPTION_BOTVSMONSTER;
@@ -1635,6 +1641,15 @@ begin
         ItemIndex := 0
       else
         ItemIndex := 1;
+    with TGUISwitch(menu.GetControl('swTeamHit')) do
+      if (Options and (GAME_OPTION_TEAMHITTRACE or GAME_OPTION_TEAMHITPROJECTILE)) = (GAME_OPTION_TEAMHITTRACE or GAME_OPTION_TEAMHITPROJECTILE) then
+        ItemIndex := 0
+      else if LongBool(Options and GAME_OPTION_TEAMHITTRACE) then
+        ItemIndex := 1
+      else if LongBool(Options and GAME_OPTION_TEAMHITPROJECTILE) then
+        ItemIndex := 2
+      else
+        ItemIndex := 3;
     with TGUISwitch(menu.GetControl('swDeathmatchKeys')) do
       if LongBool(Options and GAME_OPTION_DMKEYS) then
         ItemIndex := 0
@@ -1658,6 +1673,7 @@ begin
     if GameType in [GT_CUSTOM, GT_SERVER] then
       begin
         TGUISwitch(menu.GetControl('swTeamDamage')).Enabled := True;
+        TGUISwitch(menu.GetControl('swTeamHit')).Enabled := True;
         if (GameMode in [GM_DM, GM_TDM, GM_CTF]) then
         begin
           TGUISwitch(menu.GetControl('swDeathmatchKeys')).Enabled := True;
@@ -1679,6 +1695,7 @@ begin
     else
       begin
         TGUISwitch(menu.GetControl('swTeamDamage')).Enabled := True;
+        TGUISwitch(menu.GetControl('swTeamHit')).Enabled := True;
         TGUISwitch(menu.GetControl('swDeathmatchKeys')).Enabled := False;
         TGUILabel(menu.GetControlsText('swDeathmatchKeys')).Color := MENU_UNACTIVEITEMS_COLOR;
         with TGUIEdit(menu.GetControl('edTimeLimit')) do
@@ -1724,6 +1741,16 @@ begin
         Options := Options and (not GAME_OPTION_TEAMDAMAGE);
     end;
 
+    if TGUISwitch(menu.GetControl('swTeamHit')).Enabled then
+    begin
+      Options := Options and not (GAME_OPTION_TEAMHITTRACE or GAME_OPTION_TEAMHITPROJECTILE);
+      case TGUISwitch(menu.GetControl('swTeamHit')).ItemIndex of
+        1: Options := Options or GAME_OPTION_TEAMHITTRACE;
+        2: Options := Options or GAME_OPTION_TEAMHITPROJECTILE;
+        0: Options := Options or GAME_OPTION_TEAMHITTRACE or GAME_OPTION_TEAMHITPROJECTILE;
+      end;
+    end;
+
     if TGUISwitch(menu.GetControl('swDeathmatchKeys')).Enabled then
     begin
       if TGUISwitch(menu.GetControl('swDeathmatchKeys')).ItemIndex = 0 then
@@ -2193,6 +2220,22 @@ begin
       else
         ItemIndex := 1;
     end;
+    with AddSwitch(_lc[I_MENU_TEAM_HIT]) do
+    begin
+      Name := 'swTeamHit';
+      AddItem(_lc[I_MENU_TEAM_HIT_BOTH]);
+      AddItem(_lc[I_MENU_TEAM_HIT_TRACE]);
+      AddItem(_lc[I_MENU_TEAM_HIT_PROJECTILE]);
+      AddItem(_lc[I_MENU_TEAM_HIT_NOTHING]);
+      if (gsGameFlags and (GAME_OPTION_TEAMHITTRACE or GAME_OPTION_TEAMHITPROJECTILE)) = (GAME_OPTION_TEAMHITTRACE or GAME_OPTION_TEAMHITPROJECTILE) then
+        ItemIndex := 0
+      else if LongBool(gsGameFlags and GAME_OPTION_TEAMHITTRACE) then
+        ItemIndex := 1
+      else if LongBool(gsGameFlags and GAME_OPTION_TEAMHITPROJECTILE) then
+        ItemIndex := 2
+      else
+        ItemIndex := 3;
+    end;
     with AddSwitch(_lc[I_MENU_DEATHMATCH_KEYS]) do
     begin
       Name := 'swDeathmatchKeys';
@@ -2412,6 +2455,22 @@ begin
       else
         ItemIndex := 1;
     end;
+    with AddSwitch(_lc[I_MENU_TEAM_HIT]) do
+    begin
+      Name := 'swTeamHit';
+      AddItem(_lc[I_MENU_TEAM_HIT_BOTH]);
+      AddItem(_lc[I_MENU_TEAM_HIT_TRACE]);
+      AddItem(_lc[I_MENU_TEAM_HIT_PROJECTILE]);
+      AddItem(_lc[I_MENU_TEAM_HIT_NOTHING]);
+      if (gsGameFlags and (GAME_OPTION_TEAMHITTRACE or GAME_OPTION_TEAMHITPROJECTILE)) = (GAME_OPTION_TEAMHITTRACE or GAME_OPTION_TEAMHITPROJECTILE) then
+        ItemIndex := 0
+      else if LongBool(gsGameFlags and GAME_OPTION_TEAMHITTRACE) then
+        ItemIndex := 1
+      else if LongBool(gsGameFlags and GAME_OPTION_TEAMHITPROJECTILE) then
+        ItemIndex := 2
+      else
+        ItemIndex := 3;
+    end;
     with AddSwitch(_lc[I_MENU_DEATHMATCH_KEYS]) do
     begin
       Name := 'swDeathmatchKeys';
@@ -3295,6 +3354,15 @@ begin
       AddItem(_lc[I_MENU_NO]);
       ItemIndex := 1;
     end;
+    with AddSwitch(_lc[I_MENU_TEAM_HIT]) do
+    begin
+      Name := 'swTeamHit';
+      AddItem(_lc[I_MENU_TEAM_HIT_BOTH]);
+      AddItem(_lc[I_MENU_TEAM_HIT_TRACE]);
+      AddItem(_lc[I_MENU_TEAM_HIT_PROJECTILE]);
+      AddItem(_lc[I_MENU_TEAM_HIT_NOTHING]);
+      ItemIndex := 0
+    end;
     with AddSwitch(_lc[I_MENU_DEATHMATCH_KEYS]) do
     begin
       Name := 'swDeathmatchKeys';
index 79f6f2566ae93038ec519b1f4e2726f1c8036de3..a64d9872abf86eef5e60a7239d21f41a51308321 100644 (file)
@@ -893,10 +893,15 @@ begin
         Exit;
       end;
 
-      if PlayerHit() then
+      // È â êîíöå èãðîêîâ, íî òîëüêî åñëè ïîëîæåíî
+      // (èëè friendlyfire, èëè friendly_hit_projectile)
+      if LongBool(gGameSettings.Options and (GAME_OPTION_TEAMDAMAGE or GAME_OPTION_TEAMHITPROJECTILE)) then
       begin
-        Result := 1;
-        Exit;
+        if PlayerHit() then
+        begin
+          Result := 1;
+          Exit;
+        end;
       end;
     end;
 
@@ -934,11 +939,15 @@ begin
         Exit;
       end;
 
-      // È â êîíöå ñâîèõ èãðîêîâ
-      if PlayerHit(1) then
+      // È â êîíöå ñâîèõ èãðîêîâ, íî òîëüêî åñëè ïîëîæåíî
+      // (èëè friendlyfire, èëè friendly_hit_projectile)
+      if LongBool(gGameSettings.Options and (GAME_OPTION_TEAMDAMAGE or GAME_OPTION_TEAMHITPROJECTILE)) then
       begin
-        Result := 1;
-        Exit;
+        if PlayerHit(1) then
+        begin
+          Result := 1;
+          Exit;
+        end;
       end;
     end;
 
@@ -1394,12 +1403,19 @@ var
   x2, y2: Integer;
   xi, yi: Integer;
   wallDistSq: Integer = $3fffffff;
+  spawnerPlr: TPlayer = nil;
 
   function doPlayerHit (idx: Integer; hx, hy: Integer): Boolean;
   begin
     result := false;
     if (idx < 0) or (idx > High(gPlayers)) then exit;
     if (gPlayers[idx] = nil) or not gPlayers[idx].alive then exit;
+    if (spawnerPlr <> nil) then
+    begin
+      if ((gGameSettings.Options and (GAME_OPTION_TEAMHITTRACE or GAME_OPTION_TEAMDAMAGE)) = 0) and
+         (spawnerPlr.Team <> TEAM_NONE) and (spawnerPlr.Team = gPlayers[idx].Team) then
+        exit;
+    end;
     result := HitPlayer(gPlayers[idx], dmg, (xi*v)*10, (yi*v)*10-3, SpawnerUID, HIT_SOME);
     if result and (v <> 0) then gPlayers[idx].Push((xi*v), (yi*v));
     {$IF DEFINED(D2F_DEBUG)}
@@ -1492,6 +1508,9 @@ begin
 
   if (xd = 0) and (yd = 0) then exit;
 
+  if (g_GetUIDType(SpawnerUID) = UID_PLAYER) then
+    spawnerPlr := g_Player_Get(SpawnerUID);
+
   //wgunMonHash.reset(); //FIXME: clear hash on level change
   wgunHitHeap.clear();
   wgunHitTimeUsed := 0;