hedgewars/uGearsHandlersMess.pas
changeset 13412 06792533ef91
parent 13411 6a3f94fe2636
child 13413 419c5eab88eb
--- a/hedgewars/uGearsHandlersMess.pas	Sun May 27 20:32:06 2018 -0400
+++ b/hedgewars/uGearsHandlersMess.pas	Mon May 28 19:50:15 2018 -0400
@@ -1160,9 +1160,33 @@
     end;
 end;
 
+function ShotgunLineHitHelp(Gear: PGear; oX, oY, tX, tY: hwFloat): Boolean;
+var i: LongInt;
+    Collisions: PGearArray;
+begin
+    ShotgunLineHitHelp := false;
+    Collisions := CheckAllGearsLineCollision(Gear, oX, oY, tX, tY);
+    i := Collisions^.Count;
+    while i > 0 do
+        begin
+        dec(i);
+        if Collisions^.ar[i]^.Kind in
+            [gtMine, gtSMine, gtAirMine, gtKnife, gtCase, gtTarget, gtExplosives] then
+            begin
+            Gear^.X := Collisions^.ar[i]^.X;
+            Gear^.Y := Collisions^.ar[i]^.Y;
+            ShotgunShot(Gear);
+            Gear^.doStep := @doStepShotIdle;
+            ShotgunLineHitHelp := true;
+            exit;
+            end;
+        end;
+end;
+
 procedure doStepShotgunShot(Gear: PGear);
 var
     i: LongWord;
+    oX, oY, tmpX, tmpY: hwFloat;
 begin
     AllInactive := false;
 
@@ -1186,29 +1210,60 @@
     else
         inc(Gear^.Timer);
 
-        i := 200;
+    i := 100;
+    oX := Gear^.X;
+    oY := Gear^.Y;
     repeat
-        Gear^.X := Gear^.X + Gear^.dX;
-        Gear^.Y := Gear^.Y + Gear^.dY;
-        WorldWrap(Gear);
+        if Gear^.Tag = 0 then
+            begin
+            Gear^.X := Gear^.X + Gear^.dX;
+            Gear^.Y := Gear^.Y + Gear^.dY;
+            end;
+
+        tmpX := Gear^.X;
+        tmpY := Gear^.Y;
+        if (Gear^.PortalCounter < 30) and WorldWrap(Gear) then
+            begin
+            inc(Gear^.PortalCounter);
+            if ShotgunLineHitHelp(Gear, oX, oY, tmpX, tmpY) then
+                exit;
+            oX := Gear^.X;
+            oY := Gear^.Y;
+            end;
         CheckCollision(Gear);
-        if (Gear^.State and gstCollision) <> 0 then
-            begin
-            Gear^.X := Gear^.X + Gear^.dX * 8;
-            Gear^.Y := Gear^.Y + Gear^.dY * 8;
-            ShotgunShot(Gear);
-            Gear^.doStep := @doStepShotIdle;
-            exit
-            end;
+
+        if ((Gear^.State and gstCollision) <> 0) then
+            begin
+            if Gear^.Tag = 0 then
+                begin
+                    //Try to align the shot with the land to give portals a chance to catch it
+                    Gear^.X := Gear^.X + Gear^.dX * 2;
+                    Gear^.Y := Gear^.Y + Gear^.dY * 2;
+                    Gear^.Tag := 1
+                end
+                else
+                begin
+                    Gear^.X := Gear^.X + Gear^.dX * 6;
+                    Gear^.Y := Gear^.Y + Gear^.dY * 6;
+                    ShotgunShot(Gear);
+                    Gear^.doStep := @doStepShotIdle;
+                end;
+                exit
+            end
+        else
+            Gear^.Tag := 0;
 
         CheckGearDrowning(Gear);
         if (Gear^.State and gstDrowning) <> 0 then
             begin
             Gear^.doStep := @doStepShotIdle;
-            exit
+            break;
             end;
         dec(i)
     until i = 0;
+
+    ShotgunLineHitHelp(Gear, oX, oY, Gear^.X, Gear^.Y);
+
     if (hwRound(Gear^.X) and LAND_WIDTH_MASK <> 0) or (hwRound(Gear^.Y) and LAND_HEIGHT_MASK <> 0) then
         Gear^.doStep := @doStepShotIdle
 end;