hedgewars/GSHandlers.inc
changeset 5841 ef0a76e154cb
parent 5839 7ea0745912f7
child 5866 9017a0ff4201
--- a/hedgewars/GSHandlers.inc	Sat Sep 10 11:40:37 2011 -0400
+++ b/hedgewars/GSHandlers.inc	Sun Sep 11 00:36:47 2011 +0200
@@ -959,6 +959,44 @@
 end;
 
 ////////////////////////////////////////////////////////////////////////////////
+procedure spawnBulletTrail(Bullet: PGear);
+var oX, oY: hwFloat;
+    VGear: PVisualGear;
+begin
+    if Bullet^.PortalCounter = 0 then
+        begin
+        ox:= CurrentHedgehog^.Gear^.X + Int2hwFloat(GetLaunchX(CurrentHedgehog^.CurAmmoType, hwSign(CurrentHedgehog^.Gear^.dX), CurrentHedgehog^.Gear^.Angle));
+        oy:= CurrentHedgehog^.Gear^.Y + Int2hwFloat(GetLaunchY(CurrentHedgehog^.CurAmmoType, CurrentHedgehog^.Gear^.Angle));
+        end
+    else
+        begin
+        ox:= Bullet^.Elasticity;
+        oy:= Bullet^.Friction;
+        end;
+
+        // Bullet trail
+        VGear := AddVisualGear(hwRound(ox), hwRound(oy), vgtLineTrail);
+        if VGear <> nil then
+            begin
+            VGear^.X:= hwFloat2Float(ox);
+            VGear^.Y:= hwFloat2Float(oy);
+            VGear^.dX:= hwFloat2Float(Bullet^.X);
+            VGear^.dY:= hwFloat2Float(Bullet^.Y);
+
+            // reached edge of land. assume infinite beam. Extend it way out past camera
+            if (hwRound(Bullet^.X) and LAND_WIDTH_MASK <> 0)
+                or (hwRound(Bullet^.Y) and LAND_HEIGHT_MASK <> 0) then
+                    // only extend if not under water
+                    if hwRound(Bullet^.Y) < cWaterLine then
+                        begin
+                        VGear^.dX := VGear^.dX + LAND_WIDTH * (VGear^.dX - VGear^.X);
+                        VGear^.dY := VGear^.dY + LAND_WIDTH * (VGear^.dY - VGear^.Y);
+                        end;
+
+            VGear^.Timer := 200;
+            end;
+end;
+
 procedure doStepBulletWork(Gear: PGear);
 var 
     i, x, y: LongWord;
@@ -977,6 +1015,19 @@
         y := hwRound(Gear^.Y);
         if ((y and LAND_HEIGHT_MASK) = 0) and ((x and LAND_WIDTH_MASK) = 0)
            and (Land[y, x] <> 0) then inc(Gear^.Damage);
+        // let's interrupt before a collision to give portals a chance to catch the bullet
+        if (Gear^.Damage = 1) and (Gear^.Tag = 0) and (Land[y, x] > 255) then
+        begin
+            Gear^.Tag := 1;
+            Gear^.Damage := 0;
+            Gear^.X := Gear^.X - Gear^.dX;
+            Gear^.Y := Gear^.Y - Gear^.dY;
+            CheckGearDrowning(Gear);
+            break;
+        end
+        else
+            Gear^.Tag := 0;
+
         if Gear^.Damage > 5 then
             if Gear^.AmmoType = amDEagle then
                 AmmoShove(Gear, 7, 20)
@@ -1022,36 +1073,7 @@
             end;
         end;
        
-        if Gear^.PortalCounter = 0 then
-            begin 
-            // Bullet trail
-            VGear := AddVisualGear(
-                hwround(CurrentHedgehog^.Gear^.X) + GetLaunchX(CurrentHedgehog^.CurAmmoType, hwSign(CurrentHedgehog^.Gear^.dX), CurrentHedgehog^.Gear^.Angle), 
-                hwround(CurrentHedgehog^.Gear^.Y) + GetLaunchY(CurrentHedgehog^.CurAmmoType, CurrentHedgehog^.Gear^.Angle),
-                vgtLineTrail
-            );
-            if VGear <> nil then
-                begin
-                // http://mantis.freepascal.org/view.php?id=17714 hits again
-                VGear^.dX := Gear^.X.QWordValue / SignAs(_1,_1).QWordValue;
-                VGear^.dY := Gear^.Y.QWordValue / SignAs(_1,_1).QWordValue;
-
-                if (Gear^.X.isNegative) then VGear^.dX:= -VGear^.dX;
-                if (Gear^.Y.isNegative) then VGear^.dY:= -VGear^.dY;
-                
-                // reached edge of land. assume infinite beam. Extend it way out past camera
-                if (hwRound(Gear^.X) and LAND_WIDTH_MASK <> 0) 
-                    or (hwRound(Gear^.Y) and LAND_HEIGHT_MASK <> 0) then
-                        // only extend if not under water
-                        if hwRound(Gear^.Y) < cWaterLine then
-                            begin
-                            VGear^.dX := VGear^.dX + LAND_WIDTH * (VGear^.dX - VGear^.X);
-                            VGear^.dY := VGear^.dY + LAND_WIDTH * (VGear^.dY - VGear^.Y);
-                            end;
-                
-                VGear^.Timer := 200;
-                end
-            end;
+        spawnBulletTrail(Gear);
         Gear^.doStep := @doStepShotIdle
     end;
 end;
@@ -3931,12 +3953,20 @@
                 continue;
         end;
 
+        // draw bullet trail
+        if isbullet then
+            spawnBulletTrail(iterator);
+
         // calc gear offset in portal vector direction
         ox := (iterator^.X - Gear^.X);
         oy := (iterator^.Y - Gear^.Y);
         poffs:= (Gear^.dX * ox + Gear^.dY * oy);
 
-        if poffs < _0 then
+        if not isBullet and poffs.isNegative then
+            continue;
+
+        // only port bullets close to the portal
+        if isBullet and not (hwAbs(poffs) < _3) then
             continue;
 
         //
@@ -3964,8 +3994,11 @@
         // calc gear offset in portal normal vector direction
         noffs:= (nx * ox + ny * oy);
 
+        if isBullet and (hwRound(hwAbs(noffs)) >= Gear^.Radius) then
+            continue;
+
         // avoid gravity related loops of not really moving gear
-        if not iscake and (Gear^.dY.isNegative) and (conPortal^.dY.isNegative)
+        if not (iscake or isbullet) and (Gear^.dY.isNegative) and (conPortal^.dY.isNegative)
             and ((iterator^.dX.QWordValue + iterator^.dY.QWordValue) < _0_08.QWordValue)
             and (iterator^.PortalCounter > 0) then
              continue;
@@ -4080,6 +4113,13 @@
         if not isbullet and (iterator^.Kind <> gtFlake) then
             FollowGear := iterator;
 
+        // store X/Y values of exit for net bullet trail
+        if isbullet then
+        begin
+            iterator^.Elasticity:= iterator^.X;
+            iterator^.Friction  := iterator^.Y;
+        end;
+
         // This jiggles gears, to ensure a portal connection just placed under a gear takes effect.
         iterator:= GearsList;
         while iterator <> nil do