diff -r 2093cf51eea1 -r f2507005be87 hedgewars/uGearsHandlersMess.pas --- a/hedgewars/uGearsHandlersMess.pas Thu Dec 11 21:00:42 2014 +0900 +++ b/hedgewars/uGearsHandlersMess.pas Thu Dec 11 13:35:35 2014 +0100 @@ -4574,7 +4574,7 @@ var x, y, rX, rY, t, tmp, initHealth: LongInt; oX, oY, ldX, ldY, sdX, sdY, sine, lx, ly, amp: hwFloat; - justCollided: boolean; + justCollided, justBounced: boolean; begin AllInactive := false; initHealth := Gear^.Health; @@ -4597,6 +4597,8 @@ // used for a work-around detection of area that is within land array, but outside borders justCollided := false; + // this variable is just to ensure we don't run in infinite loop due to precision errors + justBounced:= false; repeat lX := lX + ldX; @@ -4609,7 +4611,6 @@ amp := _128 * (_1 - hwSqr(int2hwFloat(Gear^.Health)/initHealth)); sine := amp * AngleSin(tmp mod 2048); sine.isNegative := (tmp < 2048); - inc(t,Gear^.Health div 313); Gear^.X := lX + (sine * sdX); Gear^.Y := ly + (sine * sdY); Gear^.dX := Gear^.X - oX; @@ -4630,8 +4631,28 @@ inc(x, playWidth); inc(rx, playWidth); until x >= LongInt(leftX); + end + else if (WorldEdge = weBounce) then + begin + if (not justBounced) and ((x > LongInt(rightX)) or (x < LongInt(leftX))) then + begin + // reflect + lX:= lX - ldX + ((oX - lX) * 2); + lY:= lY - ldY; + Gear^.X:= oX; + Gear^.Y:= oY; + ldX.isNegative:= (not ldX.isNegative); + sdX.isNegative:= (not sdX.isNegative); + justBounced:= true; + continue; + end + else + justBounced:= false; end; + + inc(t,Gear^.Health div 313); + // if borders are on, stop outside land array if hasBorder and (((x and LAND_WIDTH_MASK) <> 0) or ((y and LAND_HEIGHT_MASK) <> 0)) then begin