--- 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