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