Merge Stepik-777's video recording gsoc project
authorunc0rr
Tue, 28 Aug 2012 20:30:57 +0400
changeset 7615 b39beffcf05e
parent 7614 3ae60c8a15f2 (diff)
parent 7565 00568d3054d0 (current diff)
child 7616 dcda1c2b77e4
Merge Stepik-777's video recording gsoc project
QTfrontend/net/tcpBase.cpp
hedgewars/CMakeLists.txt
hedgewars/hwengine.pas
hedgewars/uGearsHedgehog.pas
hedgewars/uTypes.pas
hedgewars/uVariables.pas
hedgewars/uVisualGears.pas
--- a/QTfrontend/net/tcpBase.cpp	Sun Aug 19 22:13:41 2012 +0400
+++ b/QTfrontend/net/tcpBase.cpp	Tue Aug 28 20:30:57 2012 +0400
@@ -112,6 +112,8 @@
     QMessageBox::critical(0, tr("Error"),
                           tr("Unable to run engine: %1 (")
                           .arg(error) + bindir->absolutePath() + "/hwengine)");
+
+    ClientDisconnect();
 }
 
 void TCPBase::tcpServerReady()
--- a/gameServer/Actions.hs	Sun Aug 19 22:13:41 2012 +0400
+++ b/gameServer/Actions.hs	Tue Aug 28 20:30:57 2012 +0400
@@ -541,8 +541,8 @@
             when (pq > 0) $ do
                 withStateT (\as -> as{clientIndex = Just ci}) $
                     processAction (ByeClient "Ping timeout")
-                when (pq > 1) $
-                    processAction $ DeleteClient ci -- smth went wrong with client io threads, issue DeleteClient here
+--                when (pq > 1) $
+--                    processAction $ DeleteClient ci -- smth went wrong with client io threads, issue DeleteClient here
 
 
 processAction StatsAction = do
--- a/hedgewars/CMakeLists.txt	Sun Aug 19 22:13:41 2012 +0400
+++ b/hedgewars/CMakeLists.txt	Tue Aug 28 20:30:57 2012 +0400
@@ -34,7 +34,9 @@
     uGame.pas
     uGears.pas
     uGearsHandlers.pas
+    uGearsHandlersRope.pas
     uGearsRender.pas
+    uGearsUtils.pas
     uIO.pas
     uInputHandler.pas
     uLand.pas
--- a/hedgewars/GSHandlers.inc	Sun Aug 19 22:13:41 2012 +0400
+++ b/hedgewars/GSHandlers.inc	Tue Aug 28 20:30:57 2012 +0400
@@ -140,28 +140,6 @@
     ScriptCall('onHogRestore', HH^.Gear^.Uid)
 end;
 
-////////////////////////////////////////////////////////////////////////////////
-procedure CheckCollision(Gear: PGear); inline;
-begin
-    if TestCollisionXwithGear(Gear, hwSign(Gear^.dX))
-    or (TestCollisionYwithGear(Gear, hwSign(Gear^.dY)) <> 0) then
-        Gear^.State := Gear^.State or gstCollision
-    else
-        Gear^.State := Gear^.State and (not gstCollision)
-end;
-
-procedure CheckCollisionWithLand(Gear: PGear); inline;
-begin
-    if TestCollisionX(Gear, hwSign(Gear^.dX))
-    or TestCollisionY(Gear, hwSign(Gear^.dY)) then
-        Gear^.State := Gear^.State or gstCollision
-    else 
-        Gear^.State := Gear^.State and (not gstCollision)
-end;
-
-
-////////////////////////////////////////////////////////////////////////////////
-
 
 ////////////////////////////////////////////////////////////////////////////////
 procedure doStepDrowningGear(Gear: PGear);
@@ -923,7 +901,13 @@
             Gear^.State := Gear^.State or gstAnimation
             end;
             exit
-        end
+        end else
+        if(Gear^.Hedgehog^.Gear = nil) or ((Gear^.Hedgehog^.Gear^.State and gstMoving) <> 0) then
+            begin
+            DeleteGear(Gear);
+            AfterAttack;
+            exit
+            end
     else
         inc(Gear^.Timer);
 
@@ -1400,436 +1384,6 @@
 end;
 
 ////////////////////////////////////////////////////////////////////////////////
-
-procedure doStepRope(Gear: PGear);
-forward;
-
-procedure doStepRopeAfterAttack(Gear: PGear);
-var 
-    HHGear: PGear;
-begin
-    HHGear := Gear^.Hedgehog^.Gear;
-    if ((HHGear^.State and gstHHDriven) = 0)
-    or (CheckGearDrowning(HHGear))
-    or (TestCollisionYwithGear(HHGear, 1) <> 0) then
-        begin
-        DeleteGear(Gear);
-        isCursorVisible := false;
-        ApplyAmmoChanges(HHGear^.Hedgehog^);
-        exit
-        end;
-
-    HedgehogChAngle(HHGear);
-
-    if TestCollisionXwithGear(HHGear, hwSign(HHGear^.dX)) then
-        SetLittle(HHGear^.dX);
-
-    if HHGear^.dY.isNegative and (TestCollisionYwithGear(HHGear, -1) <> 0) then
-        HHGear^.dY := _0;
-    HHGear^.X := HHGear^.X + HHGear^.dX;
-    HHGear^.Y := HHGear^.Y + HHGear^.dY;
-    HHGear^.dY := HHGear^.dY + cGravity;
-    
-    if (GameFlags and gfMoreWind) <> 0 then
-        HHGear^.dX := HHGear^.dX + cWindSpeed / HHGear^.Density;
-
-    if (Gear^.Message and gmAttack) <> 0 then
-        begin
-        Gear^.X := HHGear^.X;
-        Gear^.Y := HHGear^.Y;
-
-        ApplyAngleBounds(Gear^.Hedgehog^, amRope);
-
-        Gear^.dX := SignAs(AngleSin(HHGear^.Angle), HHGear^.dX);
-        Gear^.dY := -AngleCos(HHGear^.Angle);
-        Gear^.Friction := _4_5 * cRopePercent;
-        Gear^.Elasticity := _0;
-        Gear^.State := Gear^.State and (not gsttmpflag);
-        Gear^.doStep := @doStepRope;
-        end
-end;
-
-procedure RopeDeleteMe(Gear, HHGear: PGear);
-begin
-    with HHGear^ do
-        begin
-        Message := Message and (not gmAttack);
-        State := (State or gstMoving) and (not gstWinner);
-        end;
-    DeleteGear(Gear)
-end;
-
-procedure RopeWaitCollision(Gear, HHGear: PGear);
-begin
-    with HHGear^ do
-        begin
-        Message := Message and (not gmAttack);
-        State := State or gstMoving;
-        end;
-    RopePoints.Count := 0;
-    Gear^.Elasticity := _0;
-    Gear^.doStep := @doStepRopeAfterAttack
-end;
-
-procedure doStepRopeWork(Gear: PGear);
-var 
-    HHGear: PGear;
-    len, tx, ty, nx, ny, ropeDx, ropeDy, mdX, mdY: hwFloat;
-    lx, ly, cd: LongInt;
-    haveCollision,
-    haveDivided: boolean;
-
-begin
-    HHGear := Gear^.Hedgehog^.Gear;
-
-    if ((HHGear^.State and gstHHDriven) = 0)
-       or (CheckGearDrowning(HHGear)) or (Gear^.PortalCounter <> 0) then
-        begin
-        PlaySound(sndRopeRelease);
-        RopeDeleteMe(Gear, HHGear);
-        exit
-        end;
-
-    if (Gear^.Message and gmLeft  <> 0) and (not TestCollisionXwithGear(HHGear, -1)) then
-        HHGear^.dX := HHGear^.dX - _0_0002;
-
-    if (Gear^.Message and gmRight <> 0) and (not TestCollisionXwithGear(HHGear,  1)) then
-        HHGear^.dX := HHGear^.dX + _0_0002;
-
-    // vector between hedgehog and rope attaching point
-    ropeDx := HHGear^.X - Gear^.X;
-    ropeDy := HHGear^.Y - Gear^.Y;
-
-    if TestCollisionYwithGear(HHGear, 1) = 0 then
-        begin
-
-        // depending on the rope vector we know which X-side to check for collision
-        // in order to find out if the hog can still be moved by gravity
-        if ropeDx.isNegative = RopeDy.IsNegative then
-            cd:= -1
-        else
-            cd:= 1;
-
-        // apply gravity if there is no obstacle
-        if not TestCollisionXwithGear(HHGear, cd) then
-            HHGear^.dY := HHGear^.dY + cGravity;
-
-        if (GameFlags and gfMoreWind) <> 0 then
-            // apply wind if there's no obstacle
-            if not TestCollisionXwithGear(HHGear, hwSign(cWindSpeed)) then
-                HHGear^.dX := HHGear^.dX + cWindSpeed / HHGear^.Density;
-        end;
-
-    mdX := ropeDx + HHGear^.dX;
-    mdY := ropeDy + HHGear^.dY;
-    len := _1 / Distance(mdX, mdY);
-    // rope vector plus hedgehog direction vector normalized
-    mdX := mdX * len;
-    mdY := mdY * len;
-
-    // for visual purposes only
-    Gear^.dX := mdX;
-    Gear^.dY := mdY;
-
-    /////
-    tx := HHGear^.X;
-    ty := HHGear^.Y;
-
-    if ((Gear^.Message and gmDown) <> 0) and (Gear^.Elasticity < Gear^.Friction) then
-        if not (TestCollisionXwithGear(HHGear, hwSign(ropeDx))
-        or (TestCollisionYwithGear(HHGear, hwSign(ropeDy)) <> 0)) then
-            Gear^.Elasticity := Gear^.Elasticity + _0_3;
-
-    if ((Gear^.Message and gmUp) <> 0) and (Gear^.Elasticity > _30) then
-        if not (TestCollisionXwithGear(HHGear, -hwSign(ropeDx))
-        or (TestCollisionYwithGear(HHGear, -hwSign(ropeDy)) <> 0)) then
-            Gear^.Elasticity := Gear^.Elasticity - _0_3;
-
-    HHGear^.X := Gear^.X + mdX * Gear^.Elasticity;
-    HHGear^.Y := Gear^.Y + mdY * Gear^.Elasticity;
-
-    HHGear^.dX := HHGear^.X - tx;
-    HHGear^.dY := HHGear^.Y - ty;
-    ////
-
-
-    haveDivided := false;
-    // check whether rope needs dividing
-
-    len := Gear^.Elasticity - _5;
-    nx := Gear^.X + mdX * len;
-    ny := Gear^.Y + mdY * len;
-    tx := mdX * _0_3; // should be the same as increase step
-    ty := mdY * _0_3;
-
-    while len > _3 do
-        begin
-        lx := hwRound(nx);
-        ly := hwRound(ny);
-        if ((ly and LAND_HEIGHT_MASK) = 0) and ((lx and LAND_WIDTH_MASK) = 0) and ((Land[ly, lx] and $FF00) <> 0) then
-            begin
-            ny := _1 / Distance(ropeDx, ropeDy);
-            // old rope pos
-            nx := ropeDx * ny;
-            ny := ropeDy * ny;
-
-            with RopePoints.ar[RopePoints.Count] do
-                begin
-                X := Gear^.X;
-                Y := Gear^.Y;
-                if RopePoints.Count = 0 then
-                    RopePoints.HookAngle := DxDy2Angle(Gear^.dY, Gear^.dX);
-                b := (nx * HHGear^.dY) > (ny * HHGear^.dX);
-                dLen := len
-                end;
-                
-            with RopePoints.rounded[RopePoints.Count] do
-                begin
-                X := hwRound(Gear^.X);
-                Y := hwRound(Gear^.Y);
-                end;
-
-            Gear^.X := Gear^.X + nx * len;
-            Gear^.Y := Gear^.Y + ny * len;
-            inc(RopePoints.Count);
-            TryDo(RopePoints.Count <= MAXROPEPOINTS, 'Rope points overflow', true);
-            Gear^.Elasticity := Gear^.Elasticity - len;
-            Gear^.Friction := Gear^.Friction - len;
-            haveDivided := true;
-            break
-            end;
-        nx := nx - tx;
-        ny := ny - ty;
-
-        // len := len - _0_3 // should be the same as increase step
-        len.QWordValue := len.QWordValue - _0_3.QWordValue;
-        end;
-
-    if not haveDivided then
-        if RopePoints.Count > 0 then // check whether the last dividing point could be removed
-            begin
-            tx := RopePoints.ar[Pred(RopePoints.Count)].X;
-            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
-                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;
-
-                // 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;
-
-    haveCollision := false;
-    if TestCollisionXwithGear(HHGear, hwSign(HHGear^.dX)) then
-        begin
-        HHGear^.dX := -_0_6 * HHGear^.dX;
-        haveCollision := true
-        end;
-    if TestCollisionYwithGear(HHGear, hwSign(HHGear^.dY)) <> 0 then
-        begin
-        HHGear^.dY := -_0_6 * HHGear^.dY;
-        haveCollision := true
-        end;
-
-    if haveCollision and (Gear^.Message and (gmLeft or gmRight) <> 0) and (Gear^.Message and (gmUp or gmDown) <> 0) then
-        begin
-        HHGear^.dX := SignAs(hwAbs(HHGear^.dX) + _0_2, HHGear^.dX);
-        HHGear^.dY := SignAs(hwAbs(HHGear^.dY) + _0_2, HHGear^.dY)
-        end;
-
-    len := hwSqr(HHGear^.dX) + hwSqr(HHGear^.dY);
-    if len > _0_64 then
-        begin
-        len := _0_8 / hwSqrt(len);
-        HHGear^.dX := HHGear^.dX * len;
-        HHGear^.dY := HHGear^.dY * len;
-        end;
-
-    haveCollision:= ((hwRound(Gear^.Y) and LAND_HEIGHT_MASK) = 0) and ((hwRound(Gear^.X) and LAND_WIDTH_MASK) = 0) and ((Land[hwRound(Gear^.Y), hwRound(Gear^.X)]) <> 0);
-
-    if not haveCollision then
-        begin
-        // backup gear location
-        tx:= Gear^.X;
-        ty:= Gear^.Y;
-
-        if RopePoints.Count > 0 then
-            begin
-            // set gear location to the remote end of the rope, the attachment point
-            Gear^.X:= RopePoints.ar[0].X;
-            Gear^.Y:= RopePoints.ar[0].Y;
-            end;
-
-        CheckCollision(Gear);
-        // if we haven't found any collision yet then check the other side too
-        if (Gear^.State and gstCollision) = 0 then
-            begin
-            Gear^.dX.isNegative:= not Gear^.dX.isNegative;
-            Gear^.dY.isNegative:= not Gear^.dY.isNegative;
-            CheckCollision(Gear);
-            Gear^.dX.isNegative:= not Gear^.dX.isNegative;
-            Gear^.dY.isNegative:= not Gear^.dY.isNegative;
-            end;
-
-        haveCollision:= (Gear^.State and gstCollision) <> 0;
-
-        // restore gear location
-        Gear^.X:= tx;
-        Gear^.Y:= ty;
-        end;
-
-    // if the attack key is pressed, lose rope contact as well
-    if (Gear^.Message and gmAttack) <> 0 then
-        haveCollision:= false;
-
-    if not haveCollision then
-        begin
-        if (Gear^.State and gsttmpFlag) <> 0 then
-            begin
-            PlaySound(sndRopeRelease);
-            if Gear^.Hedgehog^.CurAmmoType <> amParachute then
-                RopeWaitCollision(Gear, HHGear)
-            else
-                RopeDeleteMe(Gear, HHGear)
-            end
-        end
-    else
-        if (Gear^.State and gsttmpFlag) = 0 then
-            Gear^.State := Gear^.State or gsttmpFlag;
-end;
-
-procedure RopeRemoveFromAmmo(Gear, HHGear: PGear);
-begin
-    if (Gear^.State and gstAttacked) = 0 then
-        begin
-        OnUsedAmmo(HHGear^.Hedgehog^);
-        Gear^.State := Gear^.State or gstAttacked
-        end;
-    ApplyAmmoChanges(HHGear^.Hedgehog^)
-end;
-
-procedure doStepRopeAttach(Gear: PGear);
-var 
-    HHGear: PGear;
-    tx, ty, tt: hwFloat;
-begin
-    Gear^.X := Gear^.X - Gear^.dX;
-    Gear^.Y := Gear^.Y - Gear^.dY;
-    Gear^.Elasticity := Gear^.Elasticity + _1;
-
-    HHGear := Gear^.Hedgehog^.Gear;
-    DeleteCI(HHGear);
-
-    if (HHGear^.State and gstMoving) <> 0 then
-        begin
-        if TestCollisionXwithGear(HHGear, hwSign(HHGear^.dX)) then
-            SetLittle(HHGear^.dX);
-        if HHGear^.dY.isNegative and (TestCollisionYwithGear(HHGear, -1) <> 0) then
-            HHGear^.dY := _0;
-
-        HHGear^.X := HHGear^.X + HHGear^.dX;
-        Gear^.X := Gear^.X + HHGear^.dX;
-
-        if TestCollisionYwithGear(HHGear, 1) <> 0 then
-            begin
-            CheckHHDamage(HHGear);
-            HHGear^.dY := _0
-            //HHGear^.State:= HHGear^.State and (not (gstHHJumping or gstHHHJump));
-            end
-        else
-            begin
-            HHGear^.Y := HHGear^.Y + HHGear^.dY;
-            Gear^.Y := Gear^.Y + HHGear^.dY;
-            HHGear^.dY := HHGear^.dY + cGravity;
-            if (GameFlags and gfMoreWind) <> 0 then
-                HHGear^.dX := HHGear^.dX + cWindSpeed / HHGear^.Density
-            end;
-
-        tt := Gear^.Elasticity;
-        tx := _0;
-        ty := _0;
-        while tt > _20 do
-            begin
-            if ((hwRound(Gear^.Y+ty) and LAND_HEIGHT_MASK) = 0) and ((hwRound(Gear^.X+tx) and LAND_WIDTH_MASK) = 0) and ((Land[hwRound(Gear^.Y+ty), hwRound(Gear^.X+tx)] and $FF00) <> 0) then
-                begin
-                Gear^.X := Gear^.X + tx;
-                Gear^.Y := Gear^.Y + ty;
-                Gear^.Elasticity := tt;
-                Gear^.doStep := @doStepRopeWork;
-                PlaySound(sndRopeAttach);
-                with HHGear^ do
-                    begin
-                    State := State and (not (gstAttacking or gstHHJumping or gstHHHJump));
-                    Message := Message and (not gmAttack)
-                    end;
-
-                RopeRemoveFromAmmo(Gear, HHGear);
-
-                tt := _0;
-                exit
-                end;
-            tx := tx + Gear^.dX + Gear^.dX;
-            ty := ty + Gear^.dY + Gear^.dY;
-            tt := tt - _2;
-            end;
-        end;
-
-    CheckCollision(Gear);
-
-    if (Gear^.State and gstCollision) <> 0 then
-        if Gear^.Elasticity < _10 then
-            Gear^.Elasticity := _10000
-    else
-        begin
-        Gear^.doStep := @doStepRopeWork;
-        PlaySound(sndRopeAttach);
-        with HHGear^ do
-            begin
-            State := State and (not (gstAttacking or gstHHJumping or gstHHHJump));
-            Message := Message and (not gmAttack)
-            end;
-
-        RopeRemoveFromAmmo(Gear, HHGear);
-
-        exit
-        end;
-
-    if (Gear^.Elasticity > Gear^.Friction)
-        or ((Gear^.Message and gmAttack) = 0)
-        or ((HHGear^.State and gstHHDriven) = 0)
-        or (HHGear^.Damage > 0) then
-            begin
-            with Gear^.Hedgehog^.Gear^ do
-                begin
-                State := State and (not gstAttacking);
-                Message := Message and (not gmAttack)
-                end;
-        DeleteGear(Gear);
-        exit;
-        end;
-    if CheckGearDrowning(HHGear) then DeleteGear(Gear)
-end;
-
-procedure doStepRope(Gear: PGear);
-begin
-    Gear^.dX := - Gear^.dX;
-    Gear^.dY := - Gear^.dY;
-    Gear^.doStep := @doStepRopeAttach;
-    PlaySound(sndRopeShot)
-end;
-
-////////////////////////////////////////////////////////////////////////////////
 procedure doStepMine(Gear: PGear);
 var vg: PVisualGear;
 begin
@@ -4035,7 +3589,7 @@
             break;
 
         // don't port portals or other gear that wouldn't make sense
-        if (iterator^.Kind in [gtPortal, gtRope])
+        if (iterator^.Kind in [gtPortal, gtRope, gtAirAttack])
         or (iterator^.PortalCounter > 32) then
             continue;
 
@@ -4317,23 +3871,6 @@
             iterator^.Friction  := iterator^.Y;
             end;
 
-        // This jiggles gears, to ensure a portal connection just placed under a gear takes effect.
-        iterator:= GearsList;
-        while iterator <> nil do
-            begin
-            if (iterator^.Kind <> gtPortal) and ((iterator^.Hedgehog <> CurrentHedgehog)
-            or ((iterator^.Message and gmAllStoppable) = 0)) then
-                    begin
-                    iterator^.Active:= true;
-                    if iterator^.dY.QWordValue = _0.QWordValue then
-                        iterator^.dY.isNegative:= false;
-                    iterator^.State:= iterator^.State or gstMoving;
-                    DeleteCI(iterator);
-                //inc(iterator^.dY.QWordValue,10);
-                    end;
-            iterator:= iterator^.NextGear
-            end;
-
         if Gear^.Health > 1 then
             dec(Gear^.Health);
     end;
@@ -4462,7 +3999,7 @@
 
             iterator := GearsList;
             while iterator <> nil do
-            begin
+                begin
                 if (iterator^.Kind = gtPortal) then
                     if (iterator <> newPortal) and (iterator^.Timer > 0) and (iterator^.Hedgehog = CurrentHedgehog) then
                         begin
@@ -4480,7 +4017,27 @@
                         end;
                 iterator^.PortalCounter:= 0;
                 iterator := iterator^.NextGear
-            end;
+                end;
+
+            if newPortal^.LinkedGear <> nil then
+                begin
+                // This jiggles gears, to ensure a portal connection just placed under a gear takes effect.
+                iterator:= GearsList;
+                while iterator <> nil do
+                    begin
+                    if not (iterator^.Kind in [gtPortal, gtAirAttack]) and ((iterator^.Hedgehog <> CurrentHedgehog)
+                    or ((iterator^.Message and gmAllStoppable) = 0)) then
+                            begin
+                            iterator^.Active:= true;
+                            if iterator^.dY.QWordValue = _0.QWordValue then
+                                iterator^.dY.isNegative:= false;
+                            iterator^.State:= iterator^.State or gstMoving;
+                            DeleteCI(iterator);
+                        //inc(iterator^.dY.QWordValue,10);
+                            end;
+                    iterator:= iterator^.NextGear
+                    end
+                end
             end;
     newPortal^.State := newPortal^.State and (not gstCollision);
     newPortal^.State := newPortal^.State or gstMoving;
--- a/hedgewars/hwengine.pas	Sun Aug 19 22:13:41 2012 +0400
+++ b/hedgewars/hwengine.pas	Tue Aug 28 20:30:57 2012 +0400
@@ -30,7 +30,7 @@
 {$ENDIF}
 
 uses SDLh, uMisc, uConsole, uGame, uConsts, uLand, uAmmos, uVisualGears, uGears, uStore, uWorld, uInputHandler, uSound,
-     uScript, uTeams, uStats, uIO, uLocale, uChat, uAI, uAIMisc, uRandom, uLandTexture, uCollisions,
+     uScript, uTeams, uStats, uIO, uLocale, uChat, uAI, uAIMisc, uLandTexture, uCollisions,
      SysUtils, uTypes, uVariables, uCommands, uUtils, uCaptions, uDebug, uCommandHandlers, uLandPainted
      {$IFDEF USE_VIDEO_RECORDING}, uVideoRec {$ENDIF}
      {$IFDEF SDL13}, uTouch{$ENDIF}{$IFDEF ANDROID}, GLUnit{$ENDIF}, uAILandMarks;
@@ -477,7 +477,6 @@
         //uLandObjects does not need initialization
         //uLandTemplates does not need initialization
         //uLocale does not need initialization
-        uRandom.initModule;
         uScript.initModule;
         uSound.initModule;
         uStats.initModule;
@@ -505,7 +504,7 @@
         uStats.freeModule;          //stub
         uSound.freeModule;
         uScript.freeModule;
-        uRandom.freeModule;         //stub
+        //uRandom does not need to be freed
         //uLocale does not need to be freed
         //uLandTemplates does not need to be freed
         uLandTexture.freeModule;
--- a/hedgewars/uFloat.pas	Sun Aug 19 22:13:41 2012 +0400
+++ b/hedgewars/uFloat.pas	Tue Aug 28 20:30:57 2012 +0400
@@ -119,6 +119,7 @@
           _0_005: hwFloat = (isNegative: false; QWordValue:    21474836);
           _0_008: hwFloat = (isNegative: false; QWordValue:    34359738);
            _0_01: hwFloat = (isNegative: false; QWordValue:    42949673);
+         _0_0128: hwFloat = (isNegative: false; QWordValue:    54975581);
            _0_02: hwFloat = (isNegative: false; QWordValue:    85899345);
            _0_03: hwFloat = (isNegative: false; QWordValue:   128849018);
            _0_07: hwFloat = (isNegative: false; QWordValue:   300647710);
@@ -149,14 +150,18 @@
               _0: hwFloat = (isNegative: false; QWordValue:           0);
               _1: hwFloat = (isNegative: false; QWordValue:  4294967296);
             _1_5: hwFloat = (isNegative: false; QWordValue:  4294967296 * 3 div 2);
+            _1_6: hwFloat = (isNegative: false; QWordValue:  4294967296 * 8 div 5);
             _1_9: hwFloat = (isNegative: false; QWordValue:  8160437862);
               _2: hwFloat = (isNegative: false; QWordValue:  4294967296 * 2);
+            _2_4: hwFloat = (isNegative: false; QWordValue:  4294967296 * 12 div 5);
               _3: hwFloat = (isNegative: false; QWordValue:  4294967296 * 3);
              _PI: hwFloat = (isNegative: false; QWordValue: 13493037704);
               _4: hwFloat = (isNegative: false; QWordValue:  4294967296 * 4);
             _4_5: hwFloat = (isNegative: false; QWordValue:  4294967296 * 9 div 2);
               _5: hwFloat = (isNegative: false; QWordValue:  4294967296 * 5);
               _6: hwFloat = (isNegative: false; QWordValue:  4294967296 * 6);
+            _6_4: hwFloat = (isNegative: false; QWordValue:  3435973837 * 8);
+              _7: hwFloat = (isNegative: false; QWordValue:  4294967296 * 7);
              _10: hwFloat = (isNegative: false; QWordValue:  4294967296 * 10);
              _12: hwFloat = (isNegative: false; QWordValue:  4294967296 * 12);
              _16: hwFloat = (isNegative: false; QWordValue:  4294967296 * 16);
@@ -165,6 +170,8 @@
              _25: hwFloat = (isNegative: false; QWordValue:  4294967296 * 25);
              _30: hwFloat = (isNegative: false; QWordValue:  4294967296 * 30);
              _40: hwFloat = (isNegative: false; QWordValue:  4294967296 * 40);
+             _41: hwFloat = (isNegative: false; QWordValue:  4294967296 * 41);
+             _49: hwFloat = (isNegative: false; QWordValue:  4294967296 * 49);
              _50: hwFloat = (isNegative: false; QWordValue:  4294967296 * 50);
              _70: hwFloat = (isNegative: false; QWordValue:  4294967296 * 70);
              _90: hwFloat = (isNegative: false; QWordValue:  4294967296 * 90);
@@ -205,11 +212,12 @@
 
 function hwFloat2Float (const i: hwFloat) : extended;
 begin
-hwFloat2Float:= i.QWordValue / $100000000;
+hwFloat2Float:= i.Frac / $100000000 + i.Round;
 if i.isNegative then
     hwFloat2Float:= -hwFloat2Float;
 end;
 
+{$IFNDEF WEB}
 operator = (const z1, z2: hwFloat) z : boolean; inline;
 begin
     z:= (z1.isNegative = z2.isNegative) and (z1.QWordValue = z2.QWordValue);
@@ -261,6 +269,81 @@
     z.QWordValue:= z1.QWordValue + z2.QWordValue
     end
 end;
+{$ENDIF}
+{$IFDEF WEB}
+(*
+    Mostly to be kind to JS as of 2012-08-27 where there is no int64/uint64.  This may change though.
+*)
+operator = (const z1, z2: hwFloat) z : boolean; inline;
+begin
+    z:= (z1.isNegative = z2.isNegative) and (z1.Frac = z2.Frac) and (z1.Round = z2.Round);
+end;
+
+operator <> (const z1, z2: hwFloat) z : boolean; inline;
+begin
+    z:= (z1.isNegative <> z2.isNegative) or (z1.Frac <> z2.Frac) or (z1.Round <> z2.Round);
+end;
+
+operator + (const z1, z2: hwFloat) z : hwFloat;
+begin
+if z1.isNegative = z2.isNegative then
+    begin
+//  z.QWordValue:= z1.QWordValue + z2.QWordValue
+    z:= z1;
+    z.Frac:= z.Frac + z2.Frac;
+    z.Round:= z.Round + z2.Round;
+    if z.Frac<z1.Frac then inc(z.Round)
+    end
+else
+//  if z1.QWordValue > z2.QWordValue then
+    if (z1.Round > z2.Round) or ((z1.Round = z2.Round) and (z1.Frac > z2.Frac)) then
+        begin
+        z.isNegative:= z1.isNegative;
+//      z.QWordValue:= z1.QWordValue - z2.QWordValue
+        z.Round:= z1.Round - z2.Round;
+        z.Frac:= z1.Frac - z2.Frac;
+        if z2.Frac > z1.Frac then dec(z.Round)
+        end
+    else
+        begin
+        z.isNegative:= z2.isNegative;
+//      z.QWordValue:= z2.QWordValue - z1.QWordValue
+        z.Round:= z2.Round - z1.Round;
+        z.Frac:= z2.Frac-z1.Frac;
+        if z2.Frac < z1.Frac then dec(z.Round)
+        end
+end;
+
+operator - (const z1, z2: hwFloat) z : hwFloat;
+begin
+if z1.isNegative = z2.isNegative then
+//  if z1.QWordValue > z2.QWordValue then
+    if (z1.Round > z2.Round) or ((z1.Round = z2.Round) and (z1.Frac > z2.Frac)) then
+        begin
+        z.isNegative:= z1.isNegative;
+//      z.QWordValue:= z1.QWordValue - z2.QWordValue
+        z.Round:= z1.Round - z2.Round;
+        z.Frac:= z1.Frac-z2.Frac;
+        if z2.Frac > z1.Frac then dec(z.Round)
+        end
+    else
+        begin
+        z.isNegative:= not z2.isNegative;
+//      z.QWordValue:= z2.QWordValue - z1.QWordValue
+        z.Round:= z2.Round - z1.Round;
+        z.Frac:= z2.Frac-z1.Frac;
+        if z2.Frac < z1.Frac then dec(z.Round)
+        end
+else
+    begin
+//  z.QWordValue:= z1.QWordValue + z2.QWordValue
+    z:= z1;
+    z.Frac:= z.Frac + z2.Frac;
+    z.Round:= z.Round + z2.Round;
+    if z.Frac<z1.Frac then inc(z.Round)
+    end
+end;
+{$ENDIF}
 
 operator - (const z1: hwFloat) z : hwFloat;
 begin
--- a/hedgewars/uGears.pas	Sun Aug 19 22:13:41 2012 +0400
+++ b/hedgewars/uGears.pas	Tue Aug 28 20:30:57 2012 +0400
@@ -59,7 +59,7 @@
 uses uStore, uSound, uTeams, uRandom, uCollisions, uIO, uLandGraphics,
     uLocale, uAI, uAmmos, uStats, uVisualGears, uScript, GLunit, uMobile, uVariables,
     uCommands, uUtils, uTextures, uRenderUtils, uGearsRender, uCaptions, uDebug, uLandTexture,
-    uGearsHedgehog, uGearsUtils, uGearsList, uGearsHandlers;
+    uGearsHedgehog, uGearsUtils, uGearsList, uGearsHandlers, uGearsHandlersRope;
 
 var skipFlag: boolean;
 
@@ -641,7 +641,8 @@
 if (GameFlags and gfArtillery) <> 0 then
     cArtillery:= true;
 for i:= GetRandom(10)+30 downto 0 do
-    begin                                                                                                                                       rx:= GetRandom(rightX-leftX)+leftX;
+    begin
+    rx:= GetRandom(rightX-leftX)+leftX;
     ry:= GetRandom(LAND_HEIGHT-topY)+topY;
     rdx:= _90-(GetRandomf*_360);
     rdy:= _90-(GetRandomf*_360);
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/hedgewars/uGearsHandlersRope.pas	Tue Aug 28 20:30:57 2012 +0400
@@ -0,0 +1,589 @@
+(*
+ * Hedgewars, a free turn based strategy game
+ * Copyright (c) 2004-2012 Andrey Korotaev <unC0Rr@gmail.com>
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; version 2 of the License
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA
+ *)
+
+{$INCLUDE "options.inc"}
+unit uGearsHandlersRope;
+interface
+
+uses uTypes;
+
+procedure doStepRope(Gear: PGear);
+
+implementation
+uses uConsts, uFloat, uCollisions, uVariables, uGearsList, uSound, uGearsUtils,
+    uAmmos, uDebug, uUtils, uGearsHedgehog, uGearsRender;
+
+procedure doStepRopeAfterAttack(Gear: PGear);
+var 
+    HHGear: PGear;
+begin
+    HHGear := Gear^.Hedgehog^.Gear;
+    if ((HHGear^.State and gstHHDriven) = 0)
+    or (CheckGearDrowning(HHGear))
+    or (TestCollisionYwithGear(HHGear, 1) <> 0) then
+        begin
+        DeleteGear(Gear);
+        isCursorVisible := false;
+        ApplyAmmoChanges(HHGear^.Hedgehog^);
+        exit
+        end;
+
+    HedgehogChAngle(HHGear);
+
+    if TestCollisionXwithGear(HHGear, hwSign(HHGear^.dX)) then
+        SetLittle(HHGear^.dX);
+
+    if HHGear^.dY.isNegative and (TestCollisionYwithGear(HHGear, -1) <> 0) then
+        HHGear^.dY := _0;
+    HHGear^.X := HHGear^.X + HHGear^.dX;
+    HHGear^.Y := HHGear^.Y + HHGear^.dY;
+    HHGear^.dY := HHGear^.dY + cGravity;
+    
+    if (GameFlags and gfMoreWind) <> 0 then
+        HHGear^.dX := HHGear^.dX + cWindSpeed / HHGear^.Density;
+
+    if (Gear^.Message and gmAttack) <> 0 then
+        begin
+        Gear^.X := HHGear^.X;
+        Gear^.Y := HHGear^.Y;
+
+        ApplyAngleBounds(Gear^.Hedgehog^, amRope);
+
+        Gear^.dX := SignAs(AngleSin(HHGear^.Angle), HHGear^.dX);
+        Gear^.dY := -AngleCos(HHGear^.Angle);
+        Gear^.Friction := _4_5 * cRopePercent;
+        Gear^.Elasticity := _0;
+        Gear^.State := Gear^.State and (not gsttmpflag);
+        Gear^.doStep := @doStepRope;
+        end
+end;
+
+procedure unstickHog(Gear, HHGear: PGear);
+var i: LongInt;
+    stuck: Boolean;
+begin
+    if (TestCollisionYwithGear(HHGear, 1) <> 0) and (TestCollisionYwithGear(HHGear, -1) = 0) then
+        begin
+        i:= 1;
+        repeat
+            begin
+            inc(i);
+            stuck:= TestCollisionYwithGear(HHGear, 1) <> 0;
+            if stuck then HHGear^.Y:= HHGear^.Y-_1
+            end
+        until (i = 8) or (not stuck);
+        HHGear^.Y:= HHGear^.Y+_1;
+        // experiment in simulating something the shoppa players apparently expect
+        if Gear^.Message and gmDown <> 0 then
+            begin
+            //HHGear^.dY:= HHGear^.dY / 16;
+            //HHGear^.dY.QWordValue:= 0;
+            HHGear^.dY:= -_0_1;
+            HHGear^.dX:= HHGear^.dX * _1_5;
+            end;
+        if Gear^.Message and gmRight <> 0 then
+            HHGear^.dX.isNegative:= false
+        else if Gear^.Message and gmLeft <> 0 then
+            HHGear^.dX.isNegative:= true
+        end
+    else if (TestCollisionYwithGear(HHGear, -1) <> 0) and (TestCollisionYwithGear(HHGear, 1) = 0) then
+        begin
+        i:= 1;
+        repeat
+            begin
+            inc(i);
+            stuck:= TestCollisionYwithGear(HHGear, -1) <> 0;
+            if stuck then HHGear^.Y:= HHGear^.Y+_1
+            end
+        until (i = 8) or (not stuck);
+        HHGear^.Y:= HHGear^.Y-_1;
+        if Gear^.Message and gmDown <> 0 then
+            begin
+            //HHGear^.dY:= HHGear^.dY / 16;
+            //HHGear^.dY.QWordValue:= 0;
+            HHGear^.dY:= _0_1;
+            HHGear^.dX:= HHGear^.dX * _1_5;
+            end;
+        if Gear^.Message and gmRight <> 0 then
+            HHGear^.dX.isNegative:= true
+        else if Gear^.Message and gmLeft <> 0 then
+            HHGear^.dX.isNegative:= false
+        end;
+    if TestCollisionXwithGear(HHGear, 1) and (not TestCollisionXwithGear(HHGear, -1)) then
+        begin
+        i:= 1;
+        repeat
+            begin
+            inc(i);
+            stuck:= TestCollisionXwithGear(HHGear, 1);
+            if stuck then HHGear^.X:= HHGear^.X-_1
+            end
+        until (i = 8) or (not stuck);
+        HHGear^.X:= HHGear^.X+_1;
+        if Gear^.Message and gmDown <> 0 then
+            begin
+            //HHGear^.dX:= HHGear^.dX / 16;
+            //HHGear^.dX.QWordValue:= 0;
+            HHGear^.dX:= -_0_1;
+            HHGear^.dY:= HHGear^.dY * _1_5;
+            end;
+        if Gear^.Message and gmRight <> 0 then
+            HHGear^.dY.isNegative:= true
+        else if Gear^.Message and gmLeft <> 0 then
+            HHGear^.dY.isNegative:= false
+        end
+    else if TestCollisionXwithGear(HHGear, -1) and (not TestCollisionXwithGear(HHGear, 1)) then
+        begin
+        i:= 1;
+        repeat
+            begin
+            inc(i);
+            stuck:= TestCollisionXwithGear(HHGear, -1);
+            if stuck then HHGear^.X:= HHGear^.X+_1
+            end
+        until (i = 8) or (not stuck);
+        HHGear^.X:= HHGear^.X-_1;
+        if Gear^.Message and gmDown <> 0 then
+            begin
+            //HHGear^.dX:= HHGear^.dX / 16;
+            //HHGear^.dX.QWordValue:= 0;
+            HHGear^.dX:= _0_1;
+            HHGear^.dY:= HHGear^.dY * _1_5;
+            end;
+        if Gear^.Message and gmRight <> 0 then
+            HHGear^.dY.isNegative:= false
+        else if Gear^.Message and gmLeft <> 0 then
+            HHGear^.dY.isNegative:= true
+        end
+end;
+
+procedure RopeDeleteMe(Gear, HHGear: PGear);
+begin
+    PlaySound(sndRopeRelease);
+    HHGear^.dX.QWordValue:= HHGear^.dX.QWordValue div Gear^.stepFreq;
+    HHGear^.dY.QWordValue:= HHGear^.dY.QWordValue div Gear^.stepFreq;
+    with HHGear^ do
+        begin
+        Message := Message and (not gmAttack);
+        State := (State or gstMoving) and (not gstWinner);
+        end;
+    unstickHog(Gear, HHGear);
+    DeleteGear(Gear)
+end;
+
+procedure RopeWaitCollision(Gear, HHGear: PGear);
+begin
+    PlaySound(sndRopeRelease);
+    with HHGear^ do
+        begin
+        Message := Message and (not gmAttack);
+        State := State or gstMoving;
+        end;
+    unstickHog(Gear, HHGear);
+    RopePoints.Count := 0;
+    Gear^.Elasticity := _0;
+    Gear^.doStep := @doStepRopeAfterAttack;
+    HHGear^.dX.QWordValue:= HHGear^.dX.QWordValue div Gear^.stepFreq;
+    HHGear^.dY.QWordValue:= HHGear^.dY.QWordValue div Gear^.stepFreq;
+    Gear^.stepFreq := 1
+end;
+
+procedure doStepRopeWork(Gear: PGear);
+var 
+    HHGear: PGear;
+    len, tx, ty, nx, ny, ropeDx, ropeDy, mdX, mdY, t: hwFloat;
+    lx, ly, cd, i: LongInt;
+    haveCollision,
+    haveDivided: boolean;
+
+begin
+    if GameTicks mod 8 <> 0 then exit;
+
+    HHGear := Gear^.Hedgehog^.Gear;
+    haveCollision:= false;
+    if (Gear^.Message and gmLeft  <> 0) and (not TestCollisionXwithGear(HHGear, -1)) then
+        HHGear^.dX := HHGear^.dX - _0_0128
+    else haveCollision:= true;
+
+    if (Gear^.Message and gmRight <> 0) and (not TestCollisionXwithGear(HHGear,  1)) then
+        HHGear^.dX := HHGear^.dX + _0_0128
+    else haveCollision:= true;
+
+
+    if ((HHGear^.State and gstHHDriven) = 0)
+       or (CheckGearDrowning(HHGear)) or (Gear^.PortalCounter <> 0) then
+        begin
+        RopeDeleteMe(Gear, HHGear);
+        exit
+        end;
+
+    // vector between hedgehog and rope attaching point
+    ropeDx := HHGear^.X - Gear^.X;
+    ropeDy := HHGear^.Y - Gear^.Y;
+
+    if TestCollisionYwithGear(HHGear, 1) = 0 then
+        begin
+
+        // depending on the rope vector we know which X-side to check for collision
+        // in order to find out if the hog can still be moved by gravity
+        if ropeDx.isNegative = RopeDy.IsNegative then
+            cd:= -1
+        else
+            cd:= 1;
+
+        // apply gravity if there is no obstacle
+        if not TestCollisionXwithGear(HHGear, cd) then
+            HHGear^.dY := HHGear^.dY + cGravity * 64;
+
+        if (GameFlags and gfMoreWind) <> 0 then
+            // apply wind if there's no obstacle
+            if not TestCollisionXwithGear(HHGear, hwSign(cWindSpeed)) then
+                HHGear^.dX := HHGear^.dX + cWindSpeed * 64 / HHGear^.Density;
+        end
+    else haveCollision:= true;
+
+    if ((Gear^.Message and gmDown) <> 0) and (Gear^.Elasticity < Gear^.Friction) then
+        if not (TestCollisionXwithGear(HHGear, hwSign(ropeDx))
+        or (TestCollisionYwithGear(HHGear, hwSign(ropeDy)) <> 0)) then
+            Gear^.Elasticity := Gear^.Elasticity + _2_4
+    else haveCollision:= true;
+
+    if ((Gear^.Message and gmUp) <> 0) and (Gear^.Elasticity > _30) then
+        if not (TestCollisionXwithGear(HHGear, -hwSign(ropeDx))
+        or (TestCollisionYwithGear(HHGear, -hwSign(ropeDy)) <> 0)) then
+            Gear^.Elasticity := Gear^.Elasticity - _2_4
+    else haveCollision:= true;
+
+(*
+I am not so sure this is useful. Disabling
+    if haveCollision then
+        begin
+        if TestCollisionXwithGear(HHGear, hwSign(HHGear^.dX)) and not TestCollisionXwithGear(HHGear, hwSign(HHGear^.dX)) then
+            HHGear^.dX.isNegative:= not HHGear^.dX.isNegative;
+        if (TestCollisionYwithGear(HHGear, hwSign(HHGear^.dY)) <> 0) and (TestCollisionYwithGear(HHGear, -hwSign(HHGear^.dY)) = 0) then
+            HHGear^.dY.isNegative:= not HHGear^.dY.isNegative;
+        end;
+*)
+
+    mdX := ropeDx + HHGear^.dX;
+    mdY := ropeDy + HHGear^.dY;
+    len := _1 / Distance(mdX, mdY);
+    // rope vector plus hedgehog direction vector normalized
+    mdX := mdX * len;
+    mdY := mdY * len;
+
+    // for visual purposes only
+    Gear^.dX := mdX;
+    Gear^.dY := mdY;
+
+    /////
+    tx := HHGear^.X;
+    ty := HHGear^.Y;
+
+    HHGear^.X := Gear^.X + mdX * Gear^.Elasticity;
+    HHGear^.Y := Gear^.Y + mdY * Gear^.Elasticity;
+
+    HHGear^.dX := HHGear^.X - tx;
+    HHGear^.dY := HHGear^.Y - ty;
+    ////
+
+
+    haveDivided := false;
+    // check whether rope needs dividing
+
+    len := Gear^.Elasticity - _5;
+    nx := Gear^.X + mdX * len;
+    ny := Gear^.Y + mdY * len;
+    tx := mdX * _2_4; // should be the same as increase step
+    ty := mdY * _2_4;
+
+    while len > _3 do
+        begin
+        lx := hwRound(nx);
+        ly := hwRound(ny);
+        if ((ly and LAND_HEIGHT_MASK) = 0) and ((lx and LAND_WIDTH_MASK) = 0) and ((Land[ly, lx] and $FF00) <> 0) then
+            begin
+            ny := _1 / Distance(ropeDx, ropeDy);
+            // old rope pos
+            nx := ropeDx * ny;
+            ny := ropeDy * ny;
+
+            with RopePoints.ar[RopePoints.Count] do
+                begin
+                X := Gear^.X;
+                Y := Gear^.Y;
+                if RopePoints.Count = 0 then
+                    RopePoints.HookAngle := DxDy2Angle(Gear^.dY, Gear^.dX);
+                b := (nx * HHGear^.dY) > (ny * HHGear^.dX);
+                dLen := len
+                end;
+                
+            with RopePoints.rounded[RopePoints.Count] do
+                begin
+                X := hwRound(Gear^.X);
+                Y := hwRound(Gear^.Y);
+                end;
+
+            Gear^.X := Gear^.X + nx * len;
+            Gear^.Y := Gear^.Y + ny * len;
+            inc(RopePoints.Count);
+            TryDo(RopePoints.Count <= MAXROPEPOINTS, 'Rope points overflow', true);
+            Gear^.Elasticity := Gear^.Elasticity - len;
+            Gear^.Friction := Gear^.Friction - len;
+            haveDivided := true;
+            break
+            end;
+        nx := nx - tx;
+        ny := ny - ty;
+
+        // len := len - _2_4 // should be the same as increase step
+        len.QWordValue := len.QWordValue - _2_4.QWordValue;
+        end;
+
+    if not haveDivided then
+        if RopePoints.Count > 0 then // check whether the last dividing point could be removed
+            begin
+            tx := RopePoints.ar[Pred(RopePoints.Count)].X;
+            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
+                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;
+
+                // 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;
+
+    haveCollision := false;
+    if TestCollisionXwithGear(HHGear, hwSign(HHGear^.dX)) then
+        begin
+        HHGear^.dX := -_0_6 * HHGear^.dX;
+        haveCollision := true
+        end;
+    if TestCollisionYwithGear(HHGear, hwSign(HHGear^.dY)) <> 0 then
+        begin
+        HHGear^.dY := -_0_6 * HHGear^.dY;
+        haveCollision := true
+        end;
+
+    if haveCollision and (Gear^.Message and (gmLeft or gmRight) <> 0) and (Gear^.Message and (gmUp or gmDown) <> 0) then
+        begin
+        HHGear^.dX := SignAs(hwAbs(HHGear^.dX) + _1_6, HHGear^.dX);
+        HHGear^.dY := SignAs(hwAbs(HHGear^.dY) + _1_6, HHGear^.dY)
+        end;
+
+    len := hwSqr(HHGear^.dX) + hwSqr(HHGear^.dY);
+    if len > _49 then
+        begin
+        len := _7 / hwSqrt(len);
+        HHGear^.dX := HHGear^.dX * len;
+        HHGear^.dY := HHGear^.dY * len;
+        end;
+
+    haveCollision:= ((hwRound(Gear^.Y) and LAND_HEIGHT_MASK) = 0) and ((hwRound(Gear^.X) and LAND_WIDTH_MASK) = 0) and ((Land[hwRound(Gear^.Y), hwRound(Gear^.X)]) <> 0);
+
+    if not haveCollision then
+        begin
+        // backup gear location
+        tx:= Gear^.X;
+        ty:= Gear^.Y;
+
+        if RopePoints.Count > 0 then
+            begin
+            // set gear location to the remote end of the rope, the attachment point
+            Gear^.X:= RopePoints.ar[0].X;
+            Gear^.Y:= RopePoints.ar[0].Y;
+            end;
+
+        CheckCollision(Gear);
+        // if we haven't found any collision yet then check the other side too
+        if (Gear^.State and gstCollision) = 0 then
+            begin
+            Gear^.dX.isNegative:= not Gear^.dX.isNegative;
+            Gear^.dY.isNegative:= not Gear^.dY.isNegative;
+            CheckCollision(Gear);
+            Gear^.dX.isNegative:= not Gear^.dX.isNegative;
+            Gear^.dY.isNegative:= not Gear^.dY.isNegative;
+            end;
+
+        haveCollision:= (Gear^.State and gstCollision) <> 0;
+
+        // restore gear location
+        Gear^.X:= tx;
+        Gear^.Y:= ty;
+        end;
+
+    // if the attack key is pressed, lose rope contact as well
+    if (Gear^.Message and gmAttack) <> 0 then
+        haveCollision:= false;
+
+    if not haveCollision then
+        begin
+        if (Gear^.State and gsttmpFlag) <> 0 then
+            begin
+            if Gear^.Hedgehog^.CurAmmoType <> amParachute then
+                RopeWaitCollision(Gear, HHGear)
+            else
+                RopeDeleteMe(Gear, HHGear)
+            end
+        end
+    else
+        if (Gear^.State and gsttmpFlag) = 0 then
+            Gear^.State := Gear^.State or gsttmpFlag;
+end;
+
+procedure RopeRemoveFromAmmo(Gear, HHGear: PGear);
+begin
+    if (Gear^.State and gstAttacked) = 0 then
+        begin
+        OnUsedAmmo(HHGear^.Hedgehog^);
+        Gear^.State := Gear^.State or gstAttacked
+        end;
+    ApplyAmmoChanges(HHGear^.Hedgehog^)
+end;
+
+procedure doStepRopeAttach(Gear: PGear);
+var 
+    HHGear: PGear;
+    tx, ty, tt: hwFloat;
+begin
+    Gear^.X := Gear^.X - Gear^.dX;
+    Gear^.Y := Gear^.Y - Gear^.dY;
+    Gear^.Elasticity := Gear^.Elasticity + _1;
+
+    HHGear := Gear^.Hedgehog^.Gear;
+    DeleteCI(HHGear);
+
+    if (HHGear^.State and gstMoving) <> 0 then
+        begin
+        if TestCollisionXwithGear(HHGear, hwSign(HHGear^.dX)) then
+            SetLittle(HHGear^.dX);
+        if HHGear^.dY.isNegative and (TestCollisionYwithGear(HHGear, -1) <> 0) then
+            HHGear^.dY := _0;
+
+        HHGear^.X := HHGear^.X + HHGear^.dX;
+        Gear^.X := Gear^.X + HHGear^.dX;
+
+        if TestCollisionYwithGear(HHGear, 1) <> 0 then
+            begin
+            CheckHHDamage(HHGear);
+            HHGear^.dY := _0
+            //HHGear^.State:= HHGear^.State and (not (gstHHJumping or gstHHHJump));
+            end
+        else
+            begin
+            HHGear^.Y := HHGear^.Y + HHGear^.dY;
+            Gear^.Y := Gear^.Y + HHGear^.dY;
+            HHGear^.dY := HHGear^.dY + cGravity;
+            if (GameFlags and gfMoreWind) <> 0 then
+                HHGear^.dX := HHGear^.dX + cWindSpeed / HHGear^.Density
+            end;
+
+        tt := Gear^.Elasticity;
+        tx := _0;
+        ty := _0;
+        while tt > _20 do
+            begin
+            if ((hwRound(Gear^.Y+ty) and LAND_HEIGHT_MASK) = 0) and ((hwRound(Gear^.X+tx) and LAND_WIDTH_MASK) = 0) and ((Land[hwRound(Gear^.Y+ty), hwRound(Gear^.X+tx)] and $FF00) <> 0) then
+                begin
+                Gear^.X := Gear^.X + tx;
+                Gear^.Y := Gear^.Y + ty;
+                Gear^.Elasticity := tt;
+                Gear^.doStep := @doStepRopeWork;
+                Gear^.stepFreq:= 8;
+                PlaySound(sndRopeAttach);
+                with HHGear^ do
+                    begin
+                    dX.QWordValue:= dX.QWordValue shl 3;
+                    dY.QWordValue:= dY.QWordValue shl 3;
+                    State := State and (not (gstAttacking or gstHHJumping or gstHHHJump));
+                    Message := Message and (not gmAttack)
+                    end;
+
+                RopeRemoveFromAmmo(Gear, HHGear);
+
+                tt := _0;
+                exit
+                end;
+            tx := tx + Gear^.dX + Gear^.dX;
+            ty := ty + Gear^.dY + Gear^.dY;
+            tt := tt - _2;
+            end;
+        end;
+
+    if Gear^.Elasticity < _20 then Gear^.CollisionMask:= $FF00
+    else Gear^.CollisionMask:= $FF7F;
+    CheckCollision(Gear);
+
+    if (Gear^.State and gstCollision) <> 0 then
+        if Gear^.Elasticity < _10 then
+            Gear^.Elasticity := _10000
+    else
+        begin
+        Gear^.doStep := @doStepRopeWork;
+        Gear^.stepFreq:= 8;
+        PlaySound(sndRopeAttach);
+        with HHGear^ do
+            begin
+            dX.QWordValue:= dX.QWordValue shl 3;
+            dY.QWordValue:= dY.QWordValue shl 3;
+            State := State and (not (gstAttacking or gstHHJumping or gstHHHJump));
+            Message := Message and (not gmAttack)
+            end;
+
+        RopeRemoveFromAmmo(Gear, HHGear);
+
+        exit
+        end;
+
+    if (Gear^.Elasticity > Gear^.Friction)
+        or ((Gear^.Message and gmAttack) = 0)
+        or ((HHGear^.State and gstHHDriven) = 0)
+        or (HHGear^.Damage > 0) then
+            begin
+            with Gear^.Hedgehog^.Gear^ do
+                begin
+                State := State and (not gstAttacking);
+                Message := Message and (not gmAttack)
+                end;
+        DeleteGear(Gear);
+        exit;
+        end;
+    if CheckGearDrowning(HHGear) then DeleteGear(Gear)
+end;
+
+procedure doStepRope(Gear: PGear);
+begin
+    Gear^.dX := - Gear^.dX;
+    Gear^.dY := - Gear^.dY;
+    Gear^.doStep := @doStepRopeAttach;
+    PlaySound(sndRopeShot)
+end;
+
+end.
--- a/hedgewars/uGearsHedgehog.pas	Sun Aug 19 22:13:41 2012 +0400
+++ b/hedgewars/uGearsHedgehog.pas	Tue Aug 28 20:30:57 2012 +0400
@@ -234,9 +234,9 @@
         and ((Gear^.Message and gmLJump) <> 0)
         and ((Ammoz[CurAmmoType].Ammo.Propz and ammoprop_AltUse) <> 0) then
             begin
-            newDx:= dX / _2; 
-            newDy:= dY / _2;
-            altUse:= true;
+            newDx:= dX / CurAmmoGear^.stepFreq; 
+            newDy:= dY / CurAmmoGear^.stepFreq;
+            altUse:= true
             end
         else
             begin
@@ -260,10 +260,7 @@
                    amPickHammer: newGear:= AddGear(hwRound(lx), hwRound(ly) + cHHRadius, gtPickHammer, 0, _0, _0, 0);
                          amSkip: ParseCommand('/skip', true);
                          amRope: newGear:= AddGear(hwRound(lx), hwRound(ly), gtRope, 0, xx, yy, 0);
-                         amMine: if altUse then
-                                     newGear:= AddGear(hwRound(lx) + hwSign(dX) * 7, hwRound(ly), gtMine, gstWait, newDx, newDy, 3000)
-                                 else
-                                     newGear:= AddGear(hwRound(lx) + hwSign(dX) * 7, hwRound(ly), gtMine, gstWait, SignAs(_0_02, dX), _0, 3000);
+                         amMine: newGear:= AddGear(hwRound(lx) + hwSign(dX) * 7, hwRound(ly), gtMine, gstWait, SignAs(_0_02, dX), _0, 3000);
                         amSMine: newGear:= AddGear(hwRound(lx), hwRound(ly), gtSMine,    0, xx*Power/cPowerDivisor, yy*Power/cPowerDivisor, 0);
                        amDEagle: newGear:= AddGear(hwRound(lx + xx * cHHRadius), hwRound(ly + yy * cHHRadius), gtDEagleShot, 0, xx * _0_5, yy * _0_5, 0);
                       amSineGun: newGear:= AddGear(hwRound(lx + xx * cHHRadius), hwRound(ly + yy * cHHRadius), gtSineGunShot, 0, xx * _0_5, yy * _0_5, 0);
@@ -360,6 +357,11 @@
                        amTardis: newGear:= AddGear(hwRound(X), hwRound(Y), gtTardis, 0, _0, _0, 5000);
                        amIceGun: newGear:= AddGear(hwRound(X), hwRound(Y), gtIceGun, 0, _0, _0, 0);
              end;
+             if altUse then
+                begin
+                newGear^.dX:= newDx / newGear^.Density;
+                newGear^.dY:= newDY / newGear^.Density
+                end;
              
              case CurAmmoType of
                       amGrenade, amMolotov, 
@@ -572,7 +574,6 @@
 var s: shortstring;
     vga: PVisualGear;
 begin
-    PlaySound(sndShotgunReload);
     if cnt <> 0 then AddAmmo(HH, ammo, cnt)
     else AddAmmo(HH, ammo);
 
@@ -614,6 +615,7 @@
 case Gear^.Pos of
        posCaseUtility,
        posCaseAmmo: begin
+                    PlaySound(sndShotgunReload);
                     if Gear^.AmmoType <> amNothing then 
                         begin
                         AddPickup(HH^.Hedgehog^, Gear^.AmmoType, Gear^.Power, hwRound(Gear^.X), hwRound(Gear^.Y));
@@ -636,7 +638,7 @@
                                 end;
                             gi := gi^.NextGear
                             end;
-                        ag:= AddGear(hwRound(Gear^.X), hwRound(Gear^.Y), gtAddAmmo, gstInvisible, _0, _0, GetRandom(200)+100);
+                        ag:= AddGear(hwRound(Gear^.X), hwRound(Gear^.Y), gtAddAmmo, gstInvisible, _0, _0, GetRandom(125)+25);
                         ag^.Pos:= Gear^.Pos;
                         ag^.Power:= Gear^.Power
                         end;
--- a/hedgewars/uGearsList.pas	Sun Aug 19 22:13:41 2012 +0400
+++ b/hedgewars/uGearsList.pas	Tue Aug 28 20:30:57 2012 +0400
@@ -105,6 +105,7 @@
 // Define ammo association, if any.
 gear^.AmmoType:= GearKindAmmoTypeMap[Kind];
 gear^.CollisionMask:= $FFFF;
+gear^.stepFreq:= 1;
 
 if CurrentHedgehog <> nil then gear^.Hedgehog:= CurrentHedgehog;
 
@@ -230,7 +231,7 @@
                 gear^.Radius:= 2;
                 gear^.Elasticity:= _0_55;
                 gear^.Friction:= _0_995;
-                gear^.Density:= _0_9;
+                gear^.Density:= _1;
                 if cMinesTime < 0 then
                     gear^.Timer:= getrandom(51)*100
                 else
@@ -242,7 +243,7 @@
                 gear^.Radius:= 2;
                 gear^.Elasticity:= _0_55;
                 gear^.Friction:= _0_995;
-                gear^.Density:= _0_9;
+                gear^.Density:= _1_6;
                 gear^.Timer:= 500;
                 end;
         gtCase: begin
--- a/hedgewars/uGearsUtils.pas	Sun Aug 19 22:13:41 2012 +0400
+++ b/hedgewars/uGearsUtils.pas	Tue Aug 28 20:30:57 2012 +0400
@@ -38,6 +38,8 @@
 
 function  CheckGearNear(Gear: PGear; Kind: TGearType; rX, rY: LongInt): PGear;
 function  CheckGearDrowning(Gear: PGear): boolean;
+procedure CheckCollision(Gear: PGear); inline;
+procedure CheckCollisionWithLand(Gear: PGear); inline;
 
 var doStepHandlers: array[TGearType] of TGearStepProcedure;
 
@@ -319,7 +321,8 @@
 var 
     dAngle: real;
 begin
-    dAngle := (Gear^.dX.QWordValue + Gear^.dY.QWordValue) / $80000000;
+// Frac/Round to be kind to JS as of 2012-08-27 where there is yet no int64/uint64
+    dAngle := (Gear^.dX.Round + Gear^.dY.Round) / 2 + (Gear^.dX.Frac+Gear^.dY.Frac) / $80000000;
     if not Gear^.dX.isNegative then
         Gear^.DirAngle := Gear^.DirAngle + dAngle
     else
@@ -603,7 +606,7 @@
                     inc(cnt)
                     end;
 
-                inc(y, 45)
+                inc(y, 10)
                 end;
 
             if cnt > 0 then
@@ -663,4 +666,22 @@
 CheckGearNear:= nil
 end;
 
+procedure CheckCollision(Gear: PGear); inline;
+begin
+    if TestCollisionXwithGear(Gear, hwSign(Gear^.dX))
+    or (TestCollisionYwithGear(Gear, hwSign(Gear^.dY)) <> 0) then
+        Gear^.State := Gear^.State or gstCollision
+    else
+        Gear^.State := Gear^.State and (not gstCollision)
+end;
+
+procedure CheckCollisionWithLand(Gear: PGear); inline;
+begin
+    if TestCollisionX(Gear, hwSign(Gear^.dX))
+    or TestCollisionY(Gear, hwSign(Gear^.dY)) then
+        Gear^.State := Gear^.State or gstCollision
+    else 
+        Gear^.State := Gear^.State and (not gstCollision)
+end;
+
 end.
--- a/hedgewars/uLand.pas	Sun Aug 19 22:13:41 2012 +0400
+++ b/hedgewars/uLand.pas	Tue Aug 28 20:30:57 2012 +0400
@@ -284,6 +284,11 @@
         3: SelectTemplate:= LargeTemplates[getrandom(Succ(High(LargeTemplates)))];
         4: SelectTemplate:= CavernTemplates[getrandom(Succ(High(CavernTemplates)))];
         5: SelectTemplate:= WackyTemplates[getrandom(Succ(High(WackyTemplates)))];
+// For lua only!
+        6: begin
+           SelectTemplate:= min(LuaTemplateNumber,High(EdgeTemplates));
+           GetRandom(2) // burn 1
+           end;
     end;
 
     WriteLnToConsole('Selected template #'+inttostr(SelectTemplate)+' using filter #'+inttostr(cTemplateFilter));
@@ -608,7 +613,7 @@
             if Land[y, x] <> 0 then
                 begin
                 inc(c);
-                if c > 200 then // avoid accidental triggering
+                if c > 1000 then // avoid accidental triggering
                     begin
                     hasBorder:= true;
                     break;
--- a/hedgewars/uLandPainted.pas	Sun Aug 19 22:13:41 2012 +0400
+++ b/hedgewars/uLandPainted.pas	Tue Aug 28 20:30:57 2012 +0400
@@ -58,9 +58,9 @@
         rec.X:= SDLNet_Read16(@rec.X);
         rec.Y:= SDLNet_Read16(@rec.Y);
         if rec.X < -318 then rec.X:= -318;
-        if rec.X > LAND_WIDTH+318 then rec.X:= LAND_WIDTH+318;
+        if rec.X > 4096+318 then rec.X:= 4096+318;
         if rec.Y < -318 then rec.Y:= -318;
-        if rec.Y > LAND_HEIGHT+318 then rec.Y:= LAND_HEIGHT+318;
+        if rec.Y > 2048+318 then rec.Y:= 2048+318;
 
         new(pe);
         if pointsListLast = nil then
--- a/hedgewars/uLandTemplates.pas	Sun Aug 19 22:13:41 2012 +0400
+++ b/hedgewars/uLandTemplates.pas	Tue Aug 28 20:30:57 2012 +0400
@@ -1457,92 +1457,92 @@
 // Many islands
 const Template41Points: array[0..86] of TSDL_Rect =
       (
-       (x:   95; y: 500; w:   1; h:   1),
-       (x:  100; y: 275; w:  25; h: 100),
-       (x:  325; y: 275; w:  25; h: 100),
-       (x:  330; y: 500; w:   1; h:   1),
+       (x:   95; y: 500; w:  26; h:  26),
+       (x:  100; y: 275; w:  50; h: 125),
+       (x:  325; y: 275; w:  50; h: 125),
+       (x:  330; y: 500; w:  26; h:  26),
        (x: NTPX; y:   0; w:   1; h:   1),
-       (x:  725; y: 125; w:   1; h:   1),
-       (x:  725; y:  25; w:   5; h:  25),
-       (x:  825; y:  35; w:   5; h:  10),
-       (x:  825; y: 135; w:   1; h:   1),
+       (x:  725; y: 125; w:  26; h:  26),
+       (x:  725; y:  25; w:  30; h:  50),
+       (x:  825; y:  35; w:  30; h:  35),
+       (x:  825; y: 135; w:  26; h:  26),
        (x: NTPX; y:   0; w:   1; h:   1),
-       (x: 1150; y: 550; w:  25; h:  50),
-       (x: 1250; y: 300; w:  25; h:  50),
-       (x: 1350; y: 300; w:  25; h:  50),
-       (x: 1400; y: 575; w:  25; h:  50),
+       (x: 1150; y: 550; w:  50; h:  75),
+       (x: 1250; y: 300; w:  50; h:  75),
+       (x: 1350; y: 300; w:  50; h:  75),
+       (x: 1400; y: 575; w:  50; h:  75),
        (x: NTPX; y:   0; w:   1; h:   1),
-       (x:  525; y:1050; w:  50; h:  50),
-       (x:  700; y: 800; w: 100; h: 150),
-       (x:  950; y: 900; w: 100; h: 150),
-       (x: 1100; y:1100; w:  50; h:  50),
+       (x:  525; y:1050; w:  75; h:  75),
+       (x:  700; y: 800; w: 125; h: 175),
+       (x:  950; y: 900; w: 125; h: 175),
+       (x: 1100; y:1100; w:  75; h:  75),
        (x: NTPX; y:   0; w:   1; h:   1),
-       (x:  175; y:1500; w:   1; h:   1),
-       (x:  210; y:1400; w:   5; h:  25),
-       (x:  240; y:1400; w:   5; h:  25),
-       (x:  275; y:1510; w:   1; h:   1),
+       (x:  175; y:1500; w:  26; h:  26),
+       (x:  210; y:1400; w:  30; h:  50),
+       (x:  240; y:1400; w:  30; h:  50),
+       (x:  275; y:1510; w:  26; h:  26),
        (x: NTPX; y:   0; w:   1; h:   1),
-       (x:  450; y:1800; w: 100; h: 100),
-       (x:  600; y:1750; w: 100; h: 100),
-       (x:  750; y:1750; w: 100; h: 100),
-       (x:  950; y:1850; w: 100; h: 100),
+       (x:  450; y:1800; w: 125; h: 125),
+       (x:  600; y:1750; w: 125; h: 125),
+       (x:  750; y:1750; w: 125; h: 125),
+       (x:  950; y:1850; w: 125; h: 125),
        (x: NTPX; y:   0; w:   1; h:   1),
-       (x: 1075; y:1450; w:   1; h:   1),
-       (x: 1110; y:1300; w:   5; h:  25),
-       (x: 1140; y:1300; w:   5; h:  25),
-       (x: 1175; y:1430; w:   1; h:   1),
+       (x: 1075; y:1450; w:  26; h:  26),
+       (x: 1110; y:1300; w:  30; h:  50),
+       (x: 1140; y:1300; w:  30; h:  50),
+       (x: 1175; y:1430; w:  26; h:  26),
        (x: NTPX; y:   0; w:   1; h:   1),
-       (x: 1600; y:1250; w:  25; h: 100),
-       (x: 1700; y:1150; w:  25; h: 100),
-       (x: 1850; y: 500; w:  50; h: 100),
-       (x: 1950; y: 550; w:  50; h: 150),
-       (x: 2250; y:1150; w:  25; h: 100),
-       (x: 2350; y:1250; w:  25; h: 100),
+       (x: 1600; y:1250; w:  50; h: 125),
+       (x: 1700; y:1150; w:  50; h: 125),
+       (x: 1850; y: 500; w:  75; h: 125),
+       (x: 1950; y: 550; w:  75; h: 175),
+       (x: 2250; y:1150; w:  50; h: 125),
+       (x: 2350; y:1250; w:  50; h: 125),
        (x: NTPX; y:   0; w:   1; h:   1),
-       (x: 1750; y:2010; w:   1; h:   1),
-       (x: 1900; y:1870; w:  50; h:  50),
-       (x: 2050; y:1870; w:  50; h:  50),
-       (x: 2175; y:2010; w:   1; h:   1),
+       (x: 1750; y:2010; w:  26; h:  26),
+       (x: 1900; y:1870; w:  75; h:  75),
+       (x: 2050; y:1870; w:  75; h:  75),
+       (x: 2175; y:2010; w:  26; h:  26),
        (x: NTPX; y:   0; w:   1; h:   1),
-       (x: 2500; y:1700; w:   1; h:   1),
-       (x: 2575; y:1500; w:  10; h:  50),
-       (x: 2650; y:1500; w:  10; h:  50),
-       (x: 2700; y:1690; w:   1; h:   1),
+       (x: 2500; y:1700; w:  26; h:  26),
+       (x: 2575; y:1500; w:  35; h:  75),
+       (x: 2650; y:1500; w:  35; h:  75),
+       (x: 2700; y:1690; w:  26; h:  26),
        (x: NTPX; y:   0; w:   1; h:   1),
-       (x: 2000; y: 125; w:   1; h:   1),
-       (x: 2050; y:  50; w:  25; h:  25),
-       (x: 2100; y:  50; w:  25; h:  25),
-       (x: 2150; y: 150; w:   1; h:   1),
+       (x: 2000; y: 125; w:  26; h:  26),
+       (x: 2050; y:  50; w:  50; h:  50),
+       (x: 2100; y:  50; w:  50; h:  50),
+       (x: 2150; y: 150; w:  26; h:  26),
        (x: NTPX; y:   0; w:   1; h:   1),
-       (x: 2600; y: 250; w:  25; h: 100),
-       (x: 2750; y: 400; w:  50; h:  50),
-       (x: 2900; y: 525; w:  50; h:  50),
-       (x: 3150; y: 550; w:  50; h: 100),
+       (x: 2600; y: 250; w:  50; h: 125),
+       (x: 2750; y: 400; w:  75; h:  75),
+       (x: 2900; y: 525; w:  75; h:  75),
+       (x: 3150; y: 550; w:  75; h: 125),
        (x: NTPX; y:   0; w:   1; h:   1),
-       (x: 2800; y:1150; w:   1; h:   1),
-       (x: 2840; y: 950; w:  25; h:  25),
-       (x: 2880; y: 950; w:  25; h:  25),
-       (x: 2900; y:1150; w:   1; h:   1),
+       (x: 2800; y:1150; w:  26; h:  26),
+       (x: 2840; y: 950; w:  50; h:  50),
+       (x: 2880; y: 950; w:  50; h:  50),
+       (x: 2900; y:1150; w:  26; h:  26),
        (x: NTPX; y:   0; w:   1; h:   1),
-       (x: 3075; y:1985; w:   1; h:   1),
-       (x: 3325; y:1700; w:  50; h: 100),
-       (x: 3475; y:1700; w:  50; h: 100),
-       (x: 3625; y:1985; w:   1; h:   1),
+       (x: 3075; y:1985; w:  26; h:  26),
+       (x: 3325; y:1700; w:  75; h: 125),
+       (x: 3475; y:1700; w:  75; h: 125),
+       (x: 3625; y:1985; w:  26; h:  26),
        (x: NTPX; y:   0; w:   1; h:   1),
-       (x: 3200; y:1450; w:   1; h:   1),
-       (x: 3240; y:1350; w:  25; h:  25),
-       (x: 3280; y:1350; w:  25; h:  25),
-       (x: 3300; y:1450; w:   1; h:   1),
+       (x: 3200; y:1450; w:  26; h:  26),
+       (x: 3240; y:1350; w:  50; h:  50),
+       (x: 3280; y:1350; w:  50; h:  50),
+       (x: 3300; y:1450; w:  26; h:  26),
        (x: NTPX; y:   0; w:   1; h:   1),
-       (x: 3500; y:1050; w:  25; h:  50),
-       (x: 3650; y: 600; w:  50; h: 100),
-       (x: 3800; y: 600; w:  50; h: 100),
-       (x: 3900; y:1000; w:  25; h:  50),
+       (x: 3500; y:1050; w:  50; h:  75),
+       (x: 3650; y: 600; w:  75; h: 125),
+       (x: 3800; y: 600; w:  75; h: 125),
+       (x: 3900; y:1000; w:  50; h:  75),
        (x: NTPX; y:   0; w:   1; h:   1),
-       (x: 3800; y: 200; w:  25; h:  50),
-       (x: 3875; y: 100; w:  50; h:  50),
-       (x: 3925; y:  50; w:  50; h:  25),
-       (x: 4050; y: 125; w:  25; h:  50),
+       (x: 3800; y: 200; w:  50; h:  75),
+       (x: 3875; y: 100; w:  75; h:  75),
+       (x: 3925; y:  50; w:  75; h:  50),
+       (x: 4050; y: 125; w:  50; h:  75),
        (x: NTPX; y:   0; w:   1; h:   1)
       );
       Template41FPoints: array[0..0] of TPoint =
@@ -1574,179 +1574,179 @@
 // Many islands
 const Template43Points: array[0..173] of TSDL_Rect =
       (
-       (x:   95; y: 500; w:   1; h:   1),
-       (x:  100; y: 275; w:  25; h: 100),
-       (x:  325; y: 275; w:  25; h: 100),
-       (x:  330; y: 500; w:   1; h:   1),
+       (x:   95; y: 500; w:  26; h:  26),
+       (x:  100; y: 275; w:  50; h: 125),
+       (x:  325; y: 275; w:  50; h: 125),
+       (x:  330; y: 500; w:  26; h:  26),
        (x: NTPX; y:   0; w:   1; h:   1),
-       (x:  725; y: 125; w:   1; h:   1),
-       (x:  725; y:  25; w:   5; h:  25),
-       (x:  825; y:  35; w:   5; h:  10),
-       (x:  825; y: 135; w:   1; h:   1),
+       (x:  725; y: 125; w:  26; h:  26),
+       (x:  725; y:  25; w:  30; h:  50),
+       (x:  825; y:  35; w:  30; h:  35),
+       (x:  825; y: 135; w:  26; h:  26),
        (x: NTPX; y:   0; w:   1; h:   1),
-       (x: 1150; y: 550; w:  25; h:  50),
-       (x: 1250; y: 300; w:  25; h:  50),
-       (x: 1350; y: 300; w:  25; h:  50),
-       (x: 1400; y: 575; w:  25; h:  50),
+       (x: 1150; y: 550; w:  50; h:  75),
+       (x: 1250; y: 300; w:  50; h:  75),
+       (x: 1350; y: 300; w:  50; h:  75),
+       (x: 1400; y: 575; w:  50; h:  75),
        (x: NTPX; y:   0; w:   1; h:   1),
-       (x:  525; y:1050; w:  50; h:  50),
-       (x:  700; y: 800; w: 100; h: 150),
-       (x:  950; y: 900; w: 100; h: 150),
-       (x: 1100; y:1100; w:  50; h:  50),
+       (x:  525; y:1050; w:  75; h:  75),
+       (x:  700; y: 800; w: 125; h: 175),
+       (x:  950; y: 900; w: 125; h: 175),
+       (x: 1100; y:1100; w:  75; h:  75),
        (x: NTPX; y:   0; w:   1; h:   1),
-       (x:  175; y:1500; w:   1; h:   1),
-       (x:  210; y:1400; w:   5; h:  25),
-       (x:  240; y:1400; w:   5; h:  25),
-       (x:  275; y:1510; w:   1; h:   1),
+       (x:  175; y:1500; w:  26; h:  26),
+       (x:  210; y:1400; w:  30; h:  50),
+       (x:  240; y:1400; w:  30; h:  50),
+       (x:  275; y:1510; w:  26; h:  26),
        (x: NTPX; y:   0; w:   1; h:   1),
-       (x:  450; y:1800; w: 100; h: 100),
-       (x:  600; y:1750; w: 100; h: 100),
-       (x:  750; y:1750; w: 100; h: 100),
-       (x:  950; y:1850; w: 100; h: 100),
+       (x:  450; y:1800; w: 125; h: 125),
+       (x:  600; y:1750; w: 125; h: 125),
+       (x:  750; y:1750; w: 125; h: 125),
+       (x:  950; y:1850; w: 125; h: 125),
        (x: NTPX; y:   0; w:   1; h:   1),
-       (x: 1075; y:1450; w:   1; h:   1),
-       (x: 1110; y:1300; w:   5; h:  25),
-       (x: 1140; y:1300; w:   5; h:  25),
-       (x: 1175; y:1430; w:   1; h:   1),
+       (x: 1075; y:1450; w:  26; h:  26),
+       (x: 1110; y:1300; w:  30; h:  50),
+       (x: 1140; y:1300; w:  30; h:  50),
+       (x: 1175; y:1430; w:  26; h:  26),
        (x: NTPX; y:   0; w:   1; h:   1),
-       (x: 1600; y:1250; w:  25; h: 100),
-       (x: 1700; y:1150; w:  25; h: 100),
-       (x: 1850; y: 500; w:  50; h: 100),
-       (x: 1950; y: 550; w:  50; h: 150),
-       (x: 2250; y:1150; w:  25; h: 100),
-       (x: 2350; y:1250; w:  25; h: 100),
+       (x: 1600; y:1250; w:  50; h: 125),
+       (x: 1700; y:1150; w:  50; h: 125),
+       (x: 1850; y: 500; w:  75; h: 125),
+       (x: 1950; y: 550; w:  75; h: 175),
+       (x: 2250; y:1150; w:  50; h: 125),
+       (x: 2350; y:1250; w:  50; h: 125),
        (x: NTPX; y:   0; w:   1; h:   1),
-       (x: 1750; y:2010; w:   1; h:   1),
-       (x: 1900; y:1870; w:  50; h:  50),
-       (x: 2050; y:1870; w:  50; h:  50),
-       (x: 2175; y:2010; w:   1; h:   1),
+       (x: 1750; y:2010; w:  26; h:  26),
+       (x: 1900; y:1870; w:  75; h:  75),
+       (x: 2050; y:1870; w:  75; h:  75),
+       (x: 2175; y:2010; w:  26; h:  26),
        (x: NTPX; y:   0; w:   1; h:   1),
-       (x: 2500; y:1700; w:   1; h:   1),
-       (x: 2575; y:1500; w:  10; h:  50),
-       (x: 2650; y:1500; w:  10; h:  50),
-       (x: 2700; y:1690; w:   1; h:   1),
+       (x: 2500; y:1700; w:  26; h:  26),
+       (x: 2575; y:1500; w:  35; h:  75),
+       (x: 2650; y:1500; w:  35; h:  75),
+       (x: 2700; y:1690; w:  26; h:  26),
        (x: NTPX; y:   0; w:   1; h:   1),
-       (x: 2000; y: 125; w:   1; h:   1),
-       (x: 2050; y:  50; w:  25; h:  25),
-       (x: 2100; y:  50; w:  25; h:  25),
-       (x: 2150; y: 150; w:   1; h:   1),
+       (x: 2000; y: 125; w:  26; h:  26),
+       (x: 2050; y:  50; w:  50; h:  50),
+       (x: 2100; y:  50; w:  50; h:  50),
+       (x: 2150; y: 150; w:  26; h:  26),
        (x: NTPX; y:   0; w:   1; h:   1),
-       (x: 2600; y: 250; w:  25; h: 100),
-       (x: 2750; y: 400; w:  50; h:  50),
-       (x: 2900; y: 525; w:  50; h:  50),
-       (x: 3150; y: 550; w:  50; h: 100),
+       (x: 2600; y: 250; w:  50; h: 125),
+       (x: 2750; y: 400; w:  75; h:  75),
+       (x: 2900; y: 525; w:  75; h:  75),
+       (x: 3150; y: 550; w:  75; h: 125),
        (x: NTPX; y:   0; w:   1; h:   1),
-       (x: 2800; y:1150; w:   1; h:   1),
-       (x: 2840; y: 950; w:  25; h:  25),
-       (x: 2880; y: 950; w:  25; h:  25),
-       (x: 2900; y:1150; w:   1; h:   1),
+       (x: 2800; y:1150; w:  26; h:  26),
+       (x: 2840; y: 950; w:  50; h:  50),
+       (x: 2880; y: 950; w:  50; h:  50),
+       (x: 2900; y:1150; w:  26; h:  26),
        (x: NTPX; y:   0; w:   1; h:   1),
-       (x: 3075; y:1985; w:   1; h:   1),
-       (x: 3325; y:1700; w:  50; h: 100),
-       (x: 3475; y:1700; w:  50; h: 100),
-       (x: 3625; y:1985; w:   1; h:   1),
+       (x: 3075; y:1985; w:  26; h:  26),
+       (x: 3325; y:1700; w:  75; h: 125),
+       (x: 3475; y:1700; w:  75; h: 125),
+       (x: 3625; y:1985; w:  26; h:  26),
        (x: NTPX; y:   0; w:   1; h:   1),
-       (x: 3200; y:1450; w:   1; h:   1),
-       (x: 3240; y:1350; w:  25; h:  25),
-       (x: 3280; y:1350; w:  25; h:  25),
-       (x: 3300; y:1450; w:   1; h:   1),
+       (x: 3200; y:1450; w:  26; h:  26),
+       (x: 3240; y:1350; w:  50; h:  50),
+       (x: 3280; y:1350; w:  50; h:  50),
+       (x: 3300; y:1450; w:  26; h:  26),
        (x: NTPX; y:   0; w:   1; h:   1),
-       (x: 3500; y:1050; w:  25; h:  50),
-       (x: 3650; y: 600; w:  50; h: 100),
-       (x: 3800; y: 600; w:  50; h: 100),
-       (x: 3900; y:1000; w:  25; h:  50),
+       (x: 3500; y:1050; w:  50; h:  75),
+       (x: 3650; y: 600; w:  75; h: 125),
+       (x: 3800; y: 600; w:  75; h: 125),
+       (x: 3900; y:1000; w:  50; h:  75),
        (x: NTPX; y:   0; w:   1; h:   1),
-       (x: 3800; y: 200; w:  25; h:  50),
-       (x: 3875; y: 100; w:  50; h:  50),
-       (x: 3925; y:  50; w:  50; h:  25),
-       (x: 4050; y: 125; w:  25; h:  50),
+       (x: 3800; y: 200; w:  50; h:  75),
+       (x: 3875; y: 100; w:  75; h:  75),
+       (x: 3925; y:  50; w:  75; h:  50),
+       (x: 4050; y: 125; w:  50; h:  75),
        (x: NTPX; y:   0; w:   1; h:   1),
-       (x:   95; y:2548; w:   1; h:   1),
-       (x:  100; y:2323; w:  25; h: 100),
-       (x:  325; y:2323; w:  25; h: 100),
-       (x:  330; y:2548; w:   1; h:   1),
+       (x:   95; y:2548; w:  26; h:  26),
+       (x:  100; y:2323; w:  50; h: 125),
+       (x:  325; y:2323; w:  50; h: 125),
+       (x:  330; y:2548; w:  26; h:  26),
        (x: NTPX; y:2048; w:   1; h:   1),
-       (x:  725; y:2173; w:   1; h:   1),
-       (x:  725; y:2073; w:   5; h:  25),
-       (x:  825; y:2083; w:   5; h:  10),
-       (x:  825; y:2183; w:   1; h:   1),
+       (x:  725; y:2173; w:  26; h:  26),
+       (x:  725; y:2073; w:  30; h:  50),
+       (x:  825; y:2083; w:  30; h:  35),
+       (x:  825; y:2183; w:  26; h:  26),
        (x: NTPX; y:2048; w:   1; h:   1),
-       (x: 1150; y:2598; w:  25; h:  50),
-       (x: 1250; y:2348; w:  25; h:  50),
-       (x: 1350; y:2348; w:  25; h:  50),
-       (x: 1400; y:2623; w:  25; h:  50),
+       (x: 1150; y:2598; w:  50; h:  75),
+       (x: 1250; y:2348; w:  50; h:  75),
+       (x: 1350; y:2348; w:  50; h:  75),
+       (x: 1400; y:2623; w:  50; h:  75),
        (x: NTPX; y:2048; w:   1; h:   1),
-       (x:  525; y:3098; w:  50; h:  50),
-       (x:  700; y:2848; w: 100; h: 150),
-       (x:  950; y:2948; w: 100; h: 150),
-       (x: 1100; y:3148; w:  50; h:  50),
+       (x:  525; y:3098; w:  75; h:  75),
+       (x:  700; y:2848; w: 125; h: 175),
+       (x:  950; y:2948; w: 125; h: 175),
+       (x: 1100; y:3148; w:  75; h:  75),
        (x: NTPX; y:2048; w:   1; h:   1),
-       (x:  175; y:3548; w:   1; h:   1),
-       (x:  210; y:3448; w:   5; h:  25),
-       (x:  240; y:3448; w:   5; h:  25),
-       (x:  275; y:3558; w:   1; h:   1),
+       (x:  175; y:3548; w:  26; h:  26),
+       (x:  210; y:3448; w:  30; h:  50),
+       (x:  240; y:3448; w:  30; h:  50),
+       (x:  275; y:3558; w:  26; h:  26),
        (x: NTPX; y:2048; w:   1; h:   1),
-       (x:  450; y:3848; w: 100; h: 100),
-       (x:  600; y:3798; w: 100; h: 100),
-       (x:  750; y:3798; w: 100; h: 100),
-       (x:  950; y:3898; w: 100; h: 100),
+       (x:  450; y:3848; w: 125; h: 125),
+       (x:  600; y:3798; w: 125; h: 125),
+       (x:  750; y:3798; w: 125; h: 125),
+       (x:  950; y:3898; w: 125; h: 125),
        (x: NTPX; y:2048; w:   1; h:   1),
-       (x: 1075; y:3498; w:   1; h:   1),
-       (x: 1110; y:3348; w:   5; h:  25),
-       (x: 1140; y:3348; w:   5; h:  25),
-       (x: 1175; y:3478; w:   1; h:   1),
+       (x: 1075; y:3498; w:  26; h:  26),
+       (x: 1110; y:3348; w:  30; h:  50),
+       (x: 1140; y:3348; w:  30; h:  50),
+       (x: 1175; y:3478; w:  26; h:  26),
        (x: NTPX; y:2048; w:   1; h:   1),
-       (x: 1600; y:3298; w:  25; h: 100),
-       (x: 1700; y:3198; w:  25; h: 100),
-       (x: 1850; y:2548; w:  50; h: 100),
-       (x: 1950; y:2598; w:  50; h: 150),
-       (x: 2250; y:3198; w:  25; h: 100),
-       (x: 2350; y:3298; w:  25; h: 100),
+       (x: 1600; y:3298; w:  50; h: 125),
+       (x: 1700; y:3198; w:  50; h: 125),
+       (x: 1850; y:2548; w:  75; h: 125),
+       (x: 1950; y:2598; w:  75; h: 175),
+       (x: 2250; y:3198; w:  50; h: 125),
+       (x: 2350; y:3298; w:  50; h: 125),
        (x: NTPX; y:2048; w:   1; h:   1),
-       (x: 1750; y:4058; w:   1; h:   1),
-       (x: 1900; y:3918; w:  50; h:  50),
-       (x: 2050; y:3918; w:  50; h:  50),
-       (x: 2175; y:4058; w:   1; h:   1),
+       (x: 1750; y:4058; w:  26; h:  26),
+       (x: 1900; y:3918; w:  75; h:  75),
+       (x: 2050; y:3918; w:  75; h:  75),
+       (x: 2175; y:4058; w:  26; h:  26),
        (x: NTPX; y:2048; w:   1; h:   1),
-       (x: 2500; y:3748; w:   1; h:   1),
-       (x: 2575; y:3548; w:  10; h:  50),
-       (x: 2650; y:3548; w:  10; h:  50),
-       (x: 2700; y:3738; w:   1; h:   1),
+       (x: 2500; y:3748; w:  26; h:  26),
+       (x: 2575; y:3548; w:  35; h:  75),
+       (x: 2650; y:3548; w:  35; h:  75),
+       (x: 2700; y:3738; w:  26; h:  26),
        (x: NTPX; y:2048; w:   1; h:   1),
-       (x: 2000; y:2173; w:   1; h:   1),
-       (x: 2050; y:2098; w:  25; h:  25),
-       (x: 2100; y:2098; w:  25; h:  25),
-       (x: 2150; y:2198; w:   1; h:   1),
+       (x: 2000; y:2173; w:  26; h:  26),
+       (x: 2050; y:2098; w:  50; h:  50),
+       (x: 2100; y:2098; w:  50; h:  50),
+       (x: 2150; y:2198; w:  26; h:  26),
        (x: NTPX; y:2048; w:   1; h:   1),
-       (x: 2600; y:2298; w:  25; h: 100),
-       (x: 2750; y:2448; w:  50; h:  50),
-       (x: 2900; y:2573; w:  50; h:  50),
-       (x: 3150; y:2598; w:  50; h: 100),
+       (x: 2600; y:2298; w:  50; h: 125),
+       (x: 2750; y:2448; w:  75; h:  75),
+       (x: 2900; y:2573; w:  75; h:  75),
+       (x: 3150; y:2598; w:  75; h: 125),
        (x: NTPX; y:2048; w:   1; h:   1),
-       (x: 2800; y:3198; w:   1; h:   1),
-       (x: 2840; y:2998; w:  25; h:  25),
-       (x: 2880; y:2998; w:  25; h:  25),
-       (x: 2900; y:3198; w:   1; h:   1),
+       (x: 2800; y:3198; w:  26; h:  26),
+       (x: 2840; y:2998; w:  50; h:  50),
+       (x: 2880; y:2998; w:  50; h:  50),
+       (x: 2900; y:3198; w:  26; h:  26),
        (x: NTPX; y:2048; w:   1; h:   1),
-       (x: 3075; y:4033; w:   1; h:   1),
-       (x: 3325; y:3748; w:  50; h: 100),
-       (x: 3475; y:3748; w:  50; h: 100),
-       (x: 3625; y:4033; w:   1; h:   1),
+       (x: 3075; y:4033; w:  26; h:  26),
+       (x: 3325; y:3748; w:  75; h: 125),
+       (x: 3475; y:3748; w:  75; h: 125),
+       (x: 3625; y:4033; w:  26; h:  26),
        (x: NTPX; y:2048; w:   1; h:   1),
-       (x: 3200; y:3498; w:   1; h:   1),
-       (x: 3240; y:3398; w:  25; h:  25),
-       (x: 3280; y:3398; w:  25; h:  25),
-       (x: 3300; y:3498; w:   1; h:   1),
+       (x: 3200; y:3498; w:  26; h:  26),
+       (x: 3240; y:3398; w:  50; h:  50),
+       (x: 3280; y:3398; w:  50; h:  50),
+       (x: 3300; y:3498; w:  26; h:  26),
        (x: NTPX; y:2048; w:   1; h:   1),
-       (x: 3500; y:3098; w:  25; h:  50),
-       (x: 3650; y:2648; w:  50; h: 100),
-       (x: 3800; y:2648; w:  50; h: 100),
-       (x: 3900; y:3048; w:  25; h:  50),
+       (x: 3500; y:3098; w:  50; h:  75),
+       (x: 3650; y:2648; w:  75; h: 125),
+       (x: 3800; y:2648; w:  75; h: 125),
+       (x: 3900; y:3048; w:  50; h:  75),
        (x: NTPX; y:2048; w:   1; h:   1),
-       (x: 3800; y:2248; w:  25; h:  50),
-       (x: 3875; y:2148; w:  50; h:  50),
-       (x: 3925; y:2098; w:  50; h:  25),
-       (x: 4050; y:2173; w:  25; h:  50),
+       (x: 3800; y:2248; w:  50; h:  75),
+       (x: 3875; y:2148; w:  75; h:  75),
+       (x: 3925; y:2098; w:  75; h:  50),
+       (x: 4050; y:2173; w:  50; h:  75),
        (x: NTPX; y:2048; w:   1; h:   1)
       );
       Template43FPoints: array[0..0] of TPoint =
@@ -2212,8 +2212,8 @@
         BasePointsCount: Succ(High(Template41Points));
         FillPoints: @Template41FPoints;
         FillPointsCount: Succ(High(Template41FPoints));
-        BezierizeCount: 3;
-        RandPassesCount: 5;
+        BezierizeCount: 2;
+        RandPassesCount: 9;
         TemplateHeight: 2048; TemplateWidth: 4096;
         canMirror: true; canFlip: true; isNegative: false; canInvert: false;
         hasGirders: true;
@@ -2234,8 +2234,8 @@
         BasePointsCount: Succ(High(Template43Points));
         FillPoints: @Template43FPoints;
         FillPointsCount: Succ(High(Template43FPoints));
-        BezierizeCount: 3;
-        RandPassesCount: 5;
+        BezierizeCount: 2;
+        RandPassesCount: 9;
         TemplateHeight: 4096; TemplateWidth: 4096;
         canMirror: true; canFlip: true; isNegative: false; canInvert: false;
         hasGirders: true;
--- a/hedgewars/uRandom.pas	Sun Aug 19 22:13:41 2012 +0400
+++ b/hedgewars/uRandom.pas	Tue Aug 28 20:30:57 2012 +0400
@@ -30,9 +30,6 @@
 interface
 uses uFloat;
 
-procedure initModule;
-procedure freeModule;
-
 procedure SetRandomSeed(Seed: shortstring); // Sets the seed that should be used for generating pseudo-random values.
 function  GetRandomf: hwFloat; overload; // Returns a pseudo-random hwFloat.
 function  GetRandom(m: LongWord): LongWord; overload; inline; // Returns a positive pseudo-random integer smaller than m.
@@ -99,15 +96,4 @@
 rndSign:= num
 end;
 
-procedure initModule;
-begin
-    n:= 54;
-    FillChar(cirbuf, 64*sizeof(Longword), 0);
-end;
-
-procedure freeModule;
-begin
-
-end;
-
 end.
--- a/hedgewars/uScript.pas	Sun Aug 19 22:13:41 2012 +0400
+++ b/hedgewars/uScript.pas	Tue Aug 28 20:30:57 2012 +0400
@@ -980,10 +980,13 @@
         if (gear <> nil) and (gear^.Kind = gtHedgehog) and (gear^.Hedgehog <> nil) and (CurrentHedgehog <> nil) then
             begin
             prevgear := CurrentHedgehog^.Gear;
-            prevgear^.Active := false;
-            prevgear^.State:= prevgear^.State and (not gstHHDriven);
-            prevgear^.Z := cHHZ;
-            prevgear^.Message:= prevgear^.Message or gmRemoveFromList or gmAddToList;
+            if prevgear <> nil then
+                begin
+                prevgear^.Active := false;
+                prevgear^.State:= prevgear^.State and (not gstHHDriven);
+                prevgear^.Z := cHHZ;
+                prevgear^.Message:= prevgear^.Message or gmRemoveFromList or gmAddToList;
+                end;
             
             SwitchCurrentHedgehog(gear^.Hedgehog);
             CurrentTeam:= CurrentHedgehog^.Team;
@@ -1745,6 +1748,7 @@
 ScriptSetInteger('GameFlags', GameFlags);
 ScriptSetString('Seed', cSeed);
 ScriptSetInteger('TemplateFilter', cTemplateFilter);
+ScriptSetInteger('TemplateNumber', LuaTemplateNumber);
 ScriptSetInteger('MapGen', cMapGen);
 ScriptSetInteger('ScreenHeight', cScreenHeight);
 ScriptSetInteger('ScreenWidth', cScreenWidth);
@@ -1773,6 +1777,7 @@
 // pop game variables
 ParseCommand('seed ' + ScriptGetString('Seed'), true);
 cTemplateFilter  := ScriptGetInteger('TemplateFilter');
+LuaTemplateNumber:= ScriptGetInteger('TemplateNumber');
 cMapGen          := ScriptGetInteger('MapGen');
 GameFlags        := ScriptGetInteger('GameFlags');
 cHedgehogTurnTime:= ScriptGetInteger('TurnTime');
--- a/hedgewars/uTypes.pas	Sun Aug 19 22:13:41 2012 +0400
+++ b/hedgewars/uTypes.pas	Tue Aug 28 20:30:57 2012 +0400
@@ -235,6 +235,7 @@
             Kind: TGearType;
             Pos: Longword;
             doStep: TGearStepProcedure;
+            stepFreq: Longword;
             Radius: LongInt;
             Angle, Power : Longword;
             DirAngle: real;
--- a/hedgewars/uVariables.pas	Sun Aug 19 22:13:41 2012 +0400
+++ b/hedgewars/uVariables.pas	Tue Aug 28 20:30:57 2012 +0400
@@ -193,6 +193,8 @@
 
     LuaGoals        : shortstring;
 
+    LuaTemplateNumber : LongWord;
+
     VoiceList : array[0..7] of TVoice =  (
                     ( snd: sndNone; voicepack: nil),
                     ( snd: sndNone; voicepack: nil),
@@ -2638,6 +2640,8 @@
     SDWaterOpacity:= $80;
 
     LuaGoals:= '';
+
+    LuaTemplateNumber:= 0;
 end;
 
 procedure freeModule;
--- a/hedgewars/uVisualGears.pas	Sun Aug 19 22:13:41 2012 +0400
+++ b/hedgewars/uVisualGears.pas	Tue Aug 28 20:30:57 2012 +0400
@@ -284,8 +284,9 @@
                 begin
                 dx:= 0.005 * (random(15) + 10);
                 dy:= 0.001 * (random(40) + 20);
-                if random(2) = 0 then
-                    dx := -dx;
+                if random(2) = 0 then dx := -dx;
+                if random(2) = 0 then Tag:= 1
+                else Tag:= -1;
                 Frame:= 7 - random(2);
                 FrameTicks:= random(20) + 15;
                 end;
@@ -642,9 +643,9 @@
                   vgtSmoke: DrawTextureF(SpritesData[sprSmoke].Texture, Gear^.scale, round(Gear^.X) + WorldDx, round(Gear^.Y) + WorldDy, 7 - Gear^.Frame, 1, SpritesData[sprSmoke].Width, SpritesData[sprSmoke].Height);
                   vgtSmokeWhite: DrawSprite(sprSmokeWhite, round(Gear^.X) + WorldDx - 11, round(Gear^.Y) + WorldDy - 11, 7 - Gear^.Frame);
                   vgtDust: if Gear^.State = 1 then
-                               DrawSpriteRotatedF(sprSnowDust, round(Gear^.X) + WorldDx - 11, round(Gear^.Y) + WorldDy - 11, 7 - Gear^.Frame, 1, Gear^.Angle)
+                               DrawSpriteRotatedF(sprSnowDust, round(Gear^.X) + WorldDx - 11, round(Gear^.Y) + WorldDy - 11, 7 - Gear^.Frame, Gear^.Tag, Gear^.Angle)
                            else
-                               DrawSprite(sprDust, round(Gear^.X) + WorldDx - 11, round(Gear^.Y) + WorldDy - 11, 7 - Gear^.Frame);
+                               DrawSpriteRotatedF(sprDust, round(Gear^.X) + WorldDx - 11, round(Gear^.Y) + WorldDy - 11, 7 - Gear^.Frame, Gear^.Tag, Gear^.Angle);
                   vgtFire: if (Gear^.State and gstTmpFlag) = 0 then
                                DrawSprite(sprFlame, round(Gear^.X) + WorldDx - 8, round(Gear^.Y) + WorldDy, (RealTicks shr 6 + Gear^.Frame) mod 8)
                            else