DEADSOFTWARE

Game: Split bubbles effect code into a distinct function
[d2df-sdl.git] / src / game / g_weapons.pas
index 4f91b9fc7acc5c5e16e6a9138ac777793a97b471..86a9de5e15a45b072a8da158d9d981e84cc77dac 100644 (file)
@@ -51,19 +51,19 @@ function g_Weapon_Hit(obj: PObj; d: Integer; SpawnerUID: Word; t: Byte; HitCorps
 function g_Weapon_HitUID(UID: Word; d: Integer; SpawnerUID: Word; t: Byte): Boolean;
 function g_Weapon_CreateShot(I: Integer; ShotType: Byte; Spawner, TargetUID: Word; X, Y, XV, YV: Integer): LongWord;
 
-procedure g_Weapon_gun(const x, y, xd, yd, v, dmg: Integer; SpawnerUID: Word; CheckTrigger: Boolean);
+procedure g_Weapon_gun(const x, y, xd, yd, v, indmg: Integer; SpawnerUID: Word; CheckTrigger: Boolean);
 procedure g_Weapon_punch(x, y: Integer; d, SpawnerUID: Word);
 function g_Weapon_chainsaw(x, y: Integer; d, SpawnerUID: Word): Integer;
-procedure g_Weapon_rocket(x, y, xd, yd: Integer; SpawnerUID: Word; WID: Integer = -1; Silent: Boolean = False);
+procedure g_Weapon_rocket(x, y, xd, yd: Integer; SpawnerUID: Word; WID: Integer = -1; Silent: Boolean = False; compat: Boolean = true);
 procedure g_Weapon_revf(x, y, xd, yd: Integer; SpawnerUID, TargetUID: Word; WID: Integer = -1; Silent: Boolean = False);
-procedure g_Weapon_flame(x, y, xd, yd: Integer; SpawnerUID: Word; WID: Integer = -1; Silent: Boolean = False);
-procedure g_Weapon_plasma(x, y, xd, yd: Integer; SpawnerUID: Word; WID: Integer = -1; Silent: Boolean = False);
-procedure g_Weapon_ball1(x, y, xd, yd: Integer; SpawnerUID: Word; WID: Integer = -1; Silent: Boolean = False);
-procedure g_Weapon_ball2(x, y, xd, yd: Integer; SpawnerUID: Word; WID: Integer = -1; Silent: Boolean = False);
-procedure g_Weapon_ball7(x, y, xd, yd: Integer; SpawnerUID: Word; WID: Integer = -1; Silent: Boolean = False);
-procedure g_Weapon_aplasma(x, y, xd, yd: Integer; SpawnerUID: Word; WID: Integer = -1; Silent: Boolean = False);
-procedure g_Weapon_manfire(x, y, xd, yd: Integer; SpawnerUID: Word; WID: Integer = -1; Silent: Boolean = False);
-procedure g_Weapon_bfgshot(x, y, xd, yd: Integer; SpawnerUID: Word; WID: Integer = -1; Silent: Boolean = False);
+procedure g_Weapon_flame(x, y, xd, yd: Integer; SpawnerUID: Word; WID: Integer = -1; Silent: Boolean = False; compat: Boolean = true);
+procedure g_Weapon_plasma(x, y, xd, yd: Integer; SpawnerUID: Word; WID: Integer = -1; Silent: Boolean = False; compat: Boolean = true);
+procedure g_Weapon_ball1(x, y, xd, yd: Integer; SpawnerUID: Word; WID: Integer = -1; Silent: Boolean = False; compat: Boolean = true);
+procedure g_Weapon_ball2(x, y, xd, yd: Integer; SpawnerUID: Word; WID: Integer = -1; Silent: Boolean = False; compat: Boolean = true);
+procedure g_Weapon_ball7(x, y, xd, yd: Integer; SpawnerUID: Word; WID: Integer = -1; Silent: Boolean = False; compat: Boolean = true);
+procedure g_Weapon_aplasma(x, y, xd, yd: Integer; SpawnerUID: Word; WID: Integer = -1; Silent: Boolean = False; compat: Boolean = true);
+procedure g_Weapon_manfire(x, y, xd, yd: Integer; SpawnerUID: Word; WID: Integer = -1; Silent: Boolean = False; compat: Boolean = true);
+procedure g_Weapon_bfgshot(x, y, xd, yd: Integer; SpawnerUID: Word; WID: Integer = -1; Silent: Boolean = False; compat: Boolean = true);
 procedure g_Weapon_bfghit(x, y: Integer);
 procedure g_Weapon_pistol(x, y, xd, yd: Integer; SpawnerUID: Word; Silent: Boolean = False);
 procedure g_Weapon_mgun(x, y, xd, yd: Integer; SpawnerUID: Word; Silent: Boolean = False);
@@ -694,7 +694,7 @@ begin
       begin
         g_Obj_Init(@Obj);
 
-        Obj.Rect.Width := 32;
+        Obj.Rect.Width := 16;
         Obj.Rect.Height := 16;
 
         Triggers := nil;
@@ -1398,13 +1398,14 @@ end;
 
 
 //!!!FIXME!!!
-procedure g_Weapon_gun (const x, y, xd, yd, v, dmg: Integer; SpawnerUID: Word; CheckTrigger: Boolean);
+procedure g_Weapon_gun (const x, y, xd, yd, v, indmg: Integer; SpawnerUID: Word; CheckTrigger: Boolean);
 var
   x0, y0: Integer;
   x2, y2: Integer;
   xi, yi: Integer;
   wallDistSq: Integer = $3fffffff;
   spawnerPlr: TPlayer = nil;
+  dmg: Integer;
 
   function doPlayerHit (idx: Integer; hx, hy: Integer): Boolean;
   begin
@@ -1415,7 +1416,11 @@ var
     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
+      begin
+        if (spawnerPlr <> gPlayers[idx]) and ((gGameSettings.Options and GAME_OPTION_TEAMABSORBDAMAGE) = 0) then
+          dmg := Max(1, dmg div 2);
         exit;
+      end;
     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));
@@ -1512,6 +1517,8 @@ begin
   if (g_GetUIDType(SpawnerUID) = UID_PLAYER) then
     spawnerPlr := g_Player_Get(SpawnerUID);
 
+  dmg := indmg;
+
   //wgunMonHash.reset(); //FIXME: clear hash on level change
   wgunHitHeap.clear();
   wgunHitTimeUsed := 0;
@@ -1652,7 +1659,7 @@ begin
 end;
 
 procedure g_Weapon_rocket(x, y, xd, yd: Integer; SpawnerUID: Word; WID: Integer = -1;
-  Silent: Boolean = False);
+  Silent: Boolean = False; compat: Boolean = true);
 var
   find_id: DWORD;
   dx, dy: Integer;
@@ -1673,7 +1680,10 @@ begin
     Obj.Rect.Width := SHOT_ROCKETLAUNCHER_WIDTH;
     Obj.Rect.Height := SHOT_ROCKETLAUNCHER_HEIGHT;
 
-    dx := IfThen(xd > x, -Obj.Rect.Width, 0);
+    if compat then
+      dx := IfThen(xd > x, -Obj.Rect.Width, 0)
+    else
+      dx := -(Obj.Rect.Width div 2);
     dy := -(Obj.Rect.Height div 2);
 
     ShotType := WEAPON_ROCKETLAUNCHER;
@@ -1731,7 +1741,7 @@ begin
 end;
 
 procedure g_Weapon_plasma(x, y, xd, yd: Integer; SpawnerUID: Word; WID: Integer = -1;
-  Silent: Boolean = False);
+  Silent: Boolean = False; compat: Boolean = true);
 var
   find_id, FramesID: DWORD;
   dx, dy: Integer;
@@ -1752,7 +1762,10 @@ begin
     Obj.Rect.Width := SHOT_PLASMA_WIDTH;
     Obj.Rect.Height := SHOT_PLASMA_HEIGHT;
 
-    dx := IfThen(xd>x, -Obj.Rect.Width, 0);
+    if compat then
+      dx := IfThen(xd > x, -Obj.Rect.Width, 0)
+    else
+      dx := -(Obj.Rect.Width div 2);
     dy := -(Obj.Rect.Height div 2);
 
     ShotType := WEAPON_PLASMA;
@@ -1770,7 +1783,7 @@ begin
 end;
 
 procedure g_Weapon_flame(x, y, xd, yd: Integer; SpawnerUID: Word; WID: Integer = -1;
-  Silent: Boolean = False);
+  Silent: Boolean = False; compat: Boolean = true);
 var
   find_id: DWORD;
   dx, dy: Integer;
@@ -1791,7 +1804,10 @@ begin
     Obj.Rect.Width := SHOT_FLAME_WIDTH;
     Obj.Rect.Height := SHOT_FLAME_HEIGHT;
 
-    dx := IfThen(xd>x, -Obj.Rect.Width, 0);
+    if compat then
+      dx := IfThen(xd > x, -Obj.Rect.Width, 0)
+    else
+      dx := -(Obj.Rect.Width div 2);
     dy := -(Obj.Rect.Height div 2);
 
     ShotType := WEAPON_FLAMETHROWER;
@@ -1810,7 +1826,7 @@ begin
 end;
 
 procedure g_Weapon_ball1(x, y, xd, yd: Integer; SpawnerUID: Word; WID: Integer = -1;
-  Silent: Boolean = False);
+  Silent: Boolean = False; compat: Boolean = true);
 var
   find_id, FramesID: DWORD;
   dx, dy: Integer;
@@ -1831,7 +1847,10 @@ begin
     Obj.Rect.Width := 16;
     Obj.Rect.Height := 16;
 
-    dx := IfThen(xd>x, -Obj.Rect.Width, 0);
+    if compat then
+      dx := IfThen(xd > x, -Obj.Rect.Width, 0)
+    else
+      dx := -(Obj.Rect.Width div 2);
     dy := -(Obj.Rect.Height div 2);
 
     ShotType := WEAPON_IMP_FIRE;
@@ -1849,7 +1868,7 @@ begin
 end;
 
 procedure g_Weapon_ball2(x, y, xd, yd: Integer; SpawnerUID: Word; WID: Integer = -1;
-  Silent: Boolean = False);
+  Silent: Boolean = False; compat: Boolean = true);
 var
   find_id, FramesID: DWORD;
   dx, dy: Integer;
@@ -1870,7 +1889,10 @@ begin
     Obj.Rect.Width := 16;
     Obj.Rect.Height := 16;
 
-    dx := IfThen(xd>x, -Obj.Rect.Width, 0);
+    if compat then
+      dx := IfThen(xd > x, -Obj.Rect.Width, 0)
+    else
+      dx := -(Obj.Rect.Width div 2);
     dy := -(Obj.Rect.Height div 2);
 
     ShotType := WEAPON_CACO_FIRE;
@@ -1888,7 +1910,7 @@ begin
 end;
 
 procedure g_Weapon_ball7(x, y, xd, yd: Integer; SpawnerUID: Word; WID: Integer = -1;
-  Silent: Boolean = False);
+  Silent: Boolean = False; compat: Boolean = true);
 var
   find_id, FramesID: DWORD;
   dx, dy: Integer;
@@ -1906,10 +1928,13 @@ begin
   begin
     g_Obj_Init(@Obj);
 
-    Obj.Rect.Width := 32;
+    Obj.Rect.Width := 16;
     Obj.Rect.Height := 16;
 
-    dx := IfThen(xd>x, -Obj.Rect.Width, 0);
+    if compat then
+      dx := IfThen(xd > x, -Obj.Rect.Width, 0)
+    else
+      dx := -(Obj.Rect.Width div 2);
     dy := -(Obj.Rect.Height div 2);
 
     ShotType := WEAPON_BARON_FIRE;
@@ -1927,7 +1952,7 @@ begin
 end;
 
 procedure g_Weapon_aplasma(x, y, xd, yd: Integer; SpawnerUID: Word; WID: Integer = -1;
-  Silent: Boolean = False);
+  Silent: Boolean = False; compat: Boolean = true);
 var
   find_id, FramesID: DWORD;
   dx, dy: Integer;
@@ -1948,7 +1973,10 @@ begin
     Obj.Rect.Width := 16;
     Obj.Rect.Height := 16;
 
-    dx := IfThen(xd>x, -Obj.Rect.Width, 0);
+    if compat then
+      dx := IfThen(xd > x, -Obj.Rect.Width, 0)
+    else
+      dx := -(Obj.Rect.Width div 2);
     dy := -(Obj.Rect.Height div 2);
 
     ShotType := WEAPON_BSP_FIRE;
@@ -1967,7 +1995,7 @@ begin
 end;
 
 procedure g_Weapon_manfire(x, y, xd, yd: Integer; SpawnerUID: Word; WID: Integer = -1;
-  Silent: Boolean = False);
+  Silent: Boolean = False; compat: Boolean = true);
 var
   find_id, FramesID: DWORD;
   dx, dy: Integer;
@@ -1988,7 +2016,10 @@ begin
     Obj.Rect.Width := 32;
     Obj.Rect.Height := 32;
 
-    dx := IfThen(xd>x, -Obj.Rect.Width, 0);
+    if compat then
+      dx := IfThen(xd > x, -Obj.Rect.Width, 0)
+    else
+      dx := -(Obj.Rect.Width div 2);
     dy := -(Obj.Rect.Height div 2);
 
     ShotType := WEAPON_MANCUB_FIRE;
@@ -2007,7 +2038,7 @@ begin
 end;
 
 procedure g_Weapon_bfgshot(x, y, xd, yd: Integer; SpawnerUID: Word; WID: Integer = -1;
-  Silent: Boolean = False);
+  Silent: Boolean = False; compat: Boolean = true);
 var
   find_id, FramesID: DWORD;
   dx, dy: Integer;
@@ -2028,7 +2059,10 @@ begin
     Obj.Rect.Width := SHOT_BFG_WIDTH;
     Obj.Rect.Height := SHOT_BFG_HEIGHT;
 
-    dx := IfThen(xd>x, -Obj.Rect.Width, 0);
+    if compat then
+      dx := IfThen(xd > x, -Obj.Rect.Width, 0)
+    else
+      dx := -(Obj.Rect.Width div 2);
     dy := -(Obj.Rect.Height div 2);
 
     ShotType := WEAPON_BFG;
@@ -2067,8 +2101,16 @@ begin
   g_Weapon_gun(x, y, xd, yd, 1, 3, SpawnerUID, True);
   if gGameSettings.GameMode in [GM_DM, GM_TDM, GM_CTF] then
   begin
-    g_Weapon_gun(x, y+1, xd, yd+1, 1, 3, SpawnerUID, False);
-    g_Weapon_gun(x, y-1, xd, yd-1, 1, 2, SpawnerUID, False);
+    if ABS(x-xd) >= ABS(y-yd) then
+    begin
+      g_Weapon_gun(x, y+1, xd, yd+1, 1, 3, SpawnerUID, False);
+      g_Weapon_gun(x, y-1, xd, yd-1, 1, 2, SpawnerUID, False);
+    end
+    else
+    begin
+      g_Weapon_gun(x+1, y, xd+1, yd, 1, 3, SpawnerUID, False);
+      g_Weapon_gun(x-1, y, xd-1, yd, 1, 2, SpawnerUID, False);
+    end;
   end;
 end;
 
@@ -2082,30 +2124,39 @@ begin
   if (gGameSettings.GameMode in [GM_DM, GM_TDM, GM_CTF]) and
      (g_GetUIDType(SpawnerUID) = UID_PLAYER) then
   begin
-    g_Weapon_gun(x, y+1, xd, yd+1, 1, 2, SpawnerUID, False);
-    g_Weapon_gun(x, y-1, xd, yd-1, 1, 2, SpawnerUID, False);
+    if ABS(x-xd) >= ABS(y-yd) then
+    begin
+      g_Weapon_gun(x, y+1, xd, yd+1, 1, 2, SpawnerUID, False);
+      g_Weapon_gun(x, y-1, xd, yd-1, 1, 2, SpawnerUID, False);
+    end
+    else
+    begin
+      g_Weapon_gun(x+1, y, xd+1, yd, 1, 2, SpawnerUID, False);
+      g_Weapon_gun(x-1, y, xd-1, yd, 1, 2, SpawnerUID, False);
+    end;
   end;
 end;
 
 procedure g_Weapon_shotgun(x, y, xd, yd: Integer; SpawnerUID: Word;
   Silent: Boolean = False);
 var
-  i, j: Integer;
+  i, j, k: Integer;
 begin
   if not Silent then
     if gSoundEffectsDF then g_Sound_PlayExAt('SOUND_WEAPON_FIRESHOTGUN', x, y);
 
   for i := 0 to 9 do
   begin
-    j := Random(17)-8; // -8 .. 8
-    g_Weapon_gun(x, y+j, xd, yd+j, IfThen(i mod 2 <> 0, 1, 0), 3, SpawnerUID, i=0);
+    j := 0; k := 0;
+    if ABS(x-xd) >= ABS(y-yd) then j := Random(17) - 8 else k := Random(17) - 8; // -8 .. 8
+    g_Weapon_gun(x+k, y+j, xd+k, yd+j, IfThen(i mod 2 <> 0, 1, 0), 3, SpawnerUID, i=0);
   end;
 end;
 
 procedure g_Weapon_dshotgun(x, y, xd, yd: Integer; SpawnerUID: Word;
   Silent: Boolean = False);
 var
-  a, i, j: Integer;
+  a, i, j, k: Integer;
 begin
   if not Silent then
     g_Sound_PlayExAt('SOUND_WEAPON_FIRESHOTGUN2', x, y);
@@ -2113,8 +2164,9 @@ begin
   if gGameSettings.GameMode in [GM_DM, GM_TDM, GM_CTF] then a := 25 else a := 20;
   for i := 0 to a do
   begin
-    j := Random(41)-20; // -20 .. 20
-    g_Weapon_gun(x, y+j, xd, yd+j, IfThen(i mod 3 <> 0, 0, 1), 3, SpawnerUID, i=0);
+    j := 0; k := 0;
+    if ABS(x-xd) >= ABS(y-yd) then j := Random(41) - 20 else k := Random(41) - 20; // -20 .. 20
+    g_Weapon_gun(x+k, y+j, xd+k, yd+j, IfThen(i mod 3 <> 0, 0, 1), 3, SpawnerUID, i=0);
   end;
 end;
 
@@ -2225,19 +2277,17 @@ begin
 
           // Â âîäå øëåéô - ïóçûðè, â âîçäóõå øëåéô - äûì:
             if WordBool(st and MOVE_INWATER) then
-              g_GFX_Bubbles(Obj.X+(Obj.Rect.Width div 2),
-                            Obj.Y+(Obj.Rect.Height div 2),
-                            1+Random(3), 16, 16)
-            else
-              if g_Frames_Get(_id, 'FRAMES_SMOKE') then
-              begin
-                Anim := TAnimation.Create(_id, False, 3);
-                Anim.Alpha := 150;
-                g_GFX_OnceAnim(Obj.X-14+Random(9),
-                               Obj.Y+(Obj.Rect.Height div 2)-20+Random(9),
-                               Anim, ONCEANIM_SMOKE);
-                Anim.Free();
-              end;
+            begin
+              g_Game_Effect_Bubbles(cx, cy, 1+Random(3), 16, 16);
+            end
+            else if g_Frames_Get(_id, 'FRAMES_SMOKE') then
+            begin
+              Anim := TAnimation.Create(_id, False, 3);
+              Anim.Alpha := 150;
+              g_GFX_OnceAnim(Obj.X-14+Random(9), cy-20+Random(9),
+                             Anim, ONCEANIM_SMOKE);
+              Anim.Free();
+            end;
 
           // Ïîïàëè â êîãî-òî èëè â ñòåíó:
             if WordBool(st and (MOVE_HITWALL or MOVE_HITLAND or MOVE_HITCEIL)) or
@@ -2360,7 +2410,8 @@ begin
                 end;
               end
               else
-                g_GFX_Bubbles(cx, cy, 1+Random(3), 16, 16);
+                g_Game_Effect_Bubbles(cx, cy, 1+Random(3), 16, 16);
+
               ShotType := 0;
               Continue;
             end;
@@ -2562,6 +2613,12 @@ begin
         p.X := Obj.Rect.Width div 2;
         p.Y := Obj.Rect.Height div 2;
 
+        if Shots[i].ShotType = WEAPON_BFG then
+        begin
+          DEC(fX, 6);
+          DEC(fY, 7);
+        end;
+
         if Animation <> nil then
           begin
             if (Shots[i].ShotType = WEAPON_BARON_FIRE) or