diff -r 57c10f640b60 -r b6002f1956d5 hedgewars/uGearsHandlersRope.pas --- a/hedgewars/uGearsHandlersRope.pas Fri Mar 15 11:55:41 2013 -0400 +++ b/hedgewars/uGearsHandlersRope.pas Sun Mar 17 00:18:38 2013 +0400 @@ -110,7 +110,7 @@ lx, ly, cd: LongInt; haveCollision, haveDivided: boolean; - + wrongSide: boolean; begin if GameTicks mod 4 <> 0 then exit; @@ -216,6 +216,9 @@ if RopePoints.Count = 0 then RopePoints.HookAngle := DxDy2Angle(Gear^.dY, Gear^.dX); b := (nx * HHGear^.dY) > (ny * HHGear^.dX); + sx:= Gear^.dX.isNegative; + sy:= Gear^.dY.isNegative; + sb:= Gear^.dX.QWordValue < Gear^.dY.QWordValue; dLen := len end; @@ -248,21 +251,45 @@ ty := RopePoints.ar[Pred(RopePoints.Count)].Y; mdX := tx - Gear^.X; mdY := ty - Gear^.Y; - if RopePoints.ar[Pred(RopePoints.Count)].b xor (mdX * (ty - HHGear^.Y) > (tx - HHGear^.X) * mdY) then + ropeDx:= tx - HHGear^.X; + ropeDy:= ty - HHGear^.Y; + if RopePoints.ar[Pred(RopePoints.Count)].b xor (mdX * ropeDy > ropeDx * mdY) then begin dec(RopePoints.Count); - Gear^.X := RopePoints.ar[RopePoints.Count].X; - Gear^.Y := RopePoints.ar[RopePoints.Count].Y; - Gear^.Elasticity := Gear^.Elasticity + RopePoints.ar[RopePoints.Count].dLen; - Gear^.Friction := Gear^.Friction + RopePoints.ar[RopePoints.Count].dLen; + Gear^.X := tx; + Gear^.Y := ty; + + // oops, opposite quadrant, don't restore hog position in such case, just remove the point + wrongSide:= (ropeDx.isNegative = RopePoints.ar[RopePoints.Count].sx) + and (ropeDy.isNegative = RopePoints.ar[RopePoints.Count].sy); + + // previous check could be inaccurate in vertical/horizontal rope positions, + // so perform this check also, even though odds are 1 to 415927 to hit this + if (not wrongSide) + and ((ropeDx.isNegative = RopePoints.ar[RopePoints.Count].sx) + <> (ropeDy.isNegative = RopePoints.ar[RopePoints.Count].sy)) then + if RopePoints.ar[RopePoints.Count].sb then + wrongSide:= ropeDy.isNegative = RopePoints.ar[RopePoints.Count].sy + else + wrongSide:= ropeDx.isNegative = RopePoints.ar[RopePoints.Count].sx; - // restore hog position - len := _1 / Distance(mdX, mdY); - mdX := mdX * len; - mdY := mdY * len; + if wrongSide then + begin + Gear^.Elasticity := Gear^.Elasticity - RopePoints.ar[RopePoints.Count].dLen; + Gear^.Friction := Gear^.Friction - RopePoints.ar[RopePoints.Count].dLen; + end else + begin + Gear^.Elasticity := Gear^.Elasticity + RopePoints.ar[RopePoints.Count].dLen; + Gear^.Friction := Gear^.Friction + RopePoints.ar[RopePoints.Count].dLen; - HHGear^.X := Gear^.X - mdX * Gear^.Elasticity; - HHGear^.Y := Gear^.Y - mdY * Gear^.Elasticity; + // restore hog position + len := _1 / Distance(mdX, mdY); + mdX := mdX * len; + mdY := mdY * len; + + HHGear^.X := Gear^.X - mdX * Gear^.Elasticity; + HHGear^.Y := Gear^.Y - mdY * Gear^.Elasticity; + end; end end;