Fix bee homing incorrectly when target is across wrap world edge
authorWuzzy <Wuzzy2@mail.ru>
Sun, 22 Oct 2017 02:25:27 +0200 (2017-10-22)
changeset 12737 d08afea02908
parent 12736 7cbb0241d31c
child 12738 49c45424a333
Fix bee homing incorrectly when target is across wrap world edge
ChangeLog.txt
hedgewars/uGearsHandlersMess.pas
hedgewars/uGearsUtils.pas
--- a/ChangeLog.txt	Sun Oct 22 00:48:38 2017 +0200
+++ b/ChangeLog.txt	Sun Oct 22 02:25:27 2017 +0200
@@ -37,6 +37,7 @@
  * Fixed screenshots being too bright if taken in quick succession
  * Video recording functionality is restored
  * Fixed bee not being affected by wrap world edge while still being thrown
+ * Fixed bee homing incorrectly when target is across wrap world edge
  * Rope is now destroyed when attempting to shoot it through wrap or bouncy world edge
  * Fixed turn not ending when sticky mine was trapped on rubberband
  * Fixed molotov cocktails bouncing off vertically off rubber
--- a/hedgewars/uGearsHandlersMess.pas	Sun Oct 22 00:48:38 2017 +0200
+++ b/hedgewars/uGearsHandlersMess.pas	Sun Oct 22 02:25:27 2017 +0200
@@ -994,11 +994,14 @@
 var
     t: hwFloat;
     gX,gY,i: LongInt;
-    uw, nuw: boolean;
+    uw, nuw, wrapped: boolean;
     flower: PVisualGear;
 
 begin
-    WorldWrap(Gear);
+    wrapped:= WorldWrap(Gear);
+    if wrapped then
+        HomingWrap(Gear);
+
     AllInactive := false;
     gX := hwRound(Gear^.X);
     gY := hwRound(Gear^.Y);
@@ -1116,6 +1119,9 @@
 
         Gear^.SoundChannel := LoopSound(sndBee);
         Gear^.Timer := 5000;
+
+        HomingWrap(Gear);
+
         // save initial speed in otherwise unused Friction variable
         Gear^.Friction := Distance(Gear^.dX, Gear^.dY);
         Gear^.doStep := @doStepBeeWork
--- 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