hedgewars/uGearsUtils.pas
changeset 12742 d08afea02908
parent 12740 83d62800d215
child 12748 f45ffb4cf1e1
--- a/hedgewars/uGearsUtils.pas	Sun Oct 22 00:48:38 2017 +0200
+++ b/hedgewars/uGearsUtils.pas	Sun Oct 22 02:25:27 2017 +0200
@@ -57,6 +57,7 @@
 function  GetUtility(Hedgehog: PHedgehog): TAmmoType;
 
 function WorldWrap(var Gear: PGear): boolean;
+function HomingWrap(var Gear: PGear): boolean;
 
 function IsHogLocal(HH: PHedgehog): boolean;
 
@@ -1628,6 +1629,47 @@
     end;
 end;
 
+(*
+Applies wrap-around logic for the target of homing gears.
+
+In wrap-around world edge, the shortest way may to the target might
+be across the border, so the X value of the target would lead the
+gear to the wrong direction across the whole map. This procedure
+changes the target X in this case.
+This function must be called in the gear set-up routine and whenever
+the gear passed through the wrap-around world edge.
+
+No-op for other world edges.
+
+Returns true if target has been changed.
+*)
+function HomingWrap(var Gear: PGear): boolean;
+var dist_center, dist_right, dist_left: hwFloat;
+begin
+    if WorldEdge = weWrap then
+        begin
+        HomingWrap:= false;
+        // We just need check the same target 3 times:
+        // 1) in current section (no change)
+        // 2) clone in the right section
+        // 3) clone in the left section
+        // The gear will go for the target with the shortest distance to the gear
+        dist_center:= Distance(Gear^.X - int2hwFloat(Gear^.Target.X), Gear^.Y - int2hwFloat(Gear^.Target.Y));
+        dist_right:= Distance(Gear^.X - int2hwFloat(Gear^.Target.X + (RightX-LeftX)), Gear^.Y - int2hwFloat(Gear^.Target.Y));
+        dist_left:= Distance(Gear^.X - int2hwFloat(Gear^.Target.X - (RightX-LeftX)), Gear^.Y - int2hwFloat(Gear^.Target.Y));
+        if (dist_left < dist_right) and (dist_left < dist_center) then
+            begin
+            dec(Gear^.Target.X, RightX-LeftX);
+            HomingWrap:= true;
+            end
+        else if (dist_right < dist_left) and (dist_right < dist_center) then
+            begin
+            inc(Gear^.Target.X, RightX-LeftX);
+            HomingWrap:= true;
+            end;
+        end;
+end;
+
 procedure AddBounceEffectForGear(Gear: PGear);
 var boing: PVisualGear;
 begin