Basic test implementation of an ice flag. Allows for slick parts of terrain. Intended for ice gun, or "ice" mask on portions of land objects.
authornemo
Sun, 02 Oct 2011 10:36:43 -0400
changeset 6081 537bbd5c1a62
parent 6080 ce02ddfe8aa1
child 6082 16ca7a7a6aa6
Basic test implementation of an ice flag. Allows for slick parts of terrain. Intended for ice gun, or "ice" mask on portions of land objects. In this test variant it is triggered on girders/objects/bridges of the snow/christmas theme, or on a map that uses blue as a mask colour. Probably needs sheepluva's slope detection to make slopes more slippery to climb.
hedgewars/GSHandlers.inc
hedgewars/HHHandlers.inc
hedgewars/uAIMisc.pas
hedgewars/uCollisions.pas
hedgewars/uConsts.pas
hedgewars/uGears.pas
hedgewars/uLand.pas
hedgewars/uLandGraphics.pas
hedgewars/uLandObjects.pas
--- a/hedgewars/GSHandlers.inc	Sun Oct 02 03:45:09 2011 +0200
+++ b/hedgewars/GSHandlers.inc	Sun Oct 02 10:36:43 2011 -0400
@@ -219,8 +219,7 @@
 
 procedure CheckCollision(Gear: PGear); inline;
 begin
-    if TestCollisionXwithGear(Gear, hwSign(Gear^.dX)) or TestCollisionYwithGear(Gear, hwSign(Gear^.dY)
-       )
+    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;
@@ -303,6 +302,7 @@
     //tmp: QWord;
     tdX, tdY: hwFloat;
     collV, collH: LongInt;
+    land: word;
 begin
     // clip velocity at 1.9 - over 1 per pixel, but really shouldn't cause many actual problems.
     if Gear^.dX.QWordValue > 8160437862 then Gear^.dX.QWordValue:= 8160437862;
@@ -320,28 +320,37 @@
     if Gear^.dY.isNegative then
         begin
         isFalling := true;
-        if TestCollisionYwithGear(Gear, -1) then
+        land:= TestCollisionYwithGear(Gear, -1);
+        if land <> 0 then
             begin
             collV := -1;
-            Gear^.dX :=   Gear^.dX * Gear^.Friction;
+            if land and lfIce <> 0 then Gear^.dX := Gear^.dX * (_1 - (_1 - Gear^.Friction) / _10)
+            else Gear^.dX := Gear^.dX * Gear^.Friction;
+
             Gear^.dY := - Gear^.dY * Gear^.Elasticity;
             Gear^.State := Gear^.State or gstCollision
             end
-        else if (Gear^.AdvBounce=1) and TestCollisionYwithGear(Gear, 1) then collV := 1;
+        else if (Gear^.AdvBounce=1) and (TestCollisionYwithGear(Gear, 1) <> 0) then collV := 1;
         end
-    else if TestCollisionYwithGear(Gear, 1) then
+    else 
         begin
-        collV := 1;
-        isFalling := false;
-        Gear^.dX :=   Gear^.dX * Gear^.Friction;
-        Gear^.dY := - Gear^.dY * Gear^.Elasticity;
-        Gear^.State := Gear^.State or gstCollision
-        end
-    else
-        begin
-        isFalling := true;
-        if (Gear^.AdvBounce=1) and not Gear^.dY.isNegative and TestCollisionYwithGear(Gear, -1) then
-            collV := -1;
+        land:= TestCollisionYwithGear(Gear, 1);
+        if land <> 0 then
+            begin
+            collV := 1;
+            isFalling := false;
+            if land and lfIce <> 0 then Gear^.dX := Gear^.dX * (_1 - (_1 - Gear^.Friction) / _10)
+            else Gear^.dX := Gear^.dX * Gear^.Friction;
+
+            Gear^.dY := - Gear^.dY * Gear^.Elasticity;
+            Gear^.State := Gear^.State or gstCollision
+            end
+        else
+            begin
+            isFalling := true;
+            if (Gear^.AdvBounce=1) and not Gear^.dY.isNegative and (TestCollisionYwithGear(Gear, -1) <> 0) then
+                collV := -1
+            end
         end;
 
 
@@ -1260,7 +1269,7 @@
             end;
         SetAllHHToActive;
         end;
-    if TestCollisionYwithGear(Gear, 1) then
+    if TestCollisionYwithGear(Gear, 1) <> 0 then
         begin
         Gear^.dY := _0;
         SetLittle(HHGear^.dX);
@@ -1429,7 +1438,7 @@
     HHGear := Gear^.Hedgehog^.Gear;
     if ((HHGear^.State and gstHHDriven) = 0)
        or (CheckGearDrowning(HHGear))
-       or TestCollisionYwithGear(HHGear, 1) then
+       or (TestCollisionYwithGear(HHGear, 1) <> 0) then
     begin
         DeleteGear(Gear);
         isCursorVisible := false;
@@ -1441,7 +1450,7 @@
 
     if TestCollisionXwithGear(HHGear, hwSign(HHGear^.dX)) then SetLittle(HHGear^.dX);
 
-    if HHGear^.dY.isNegative and TestCollisionYwithGear(HHGear, -1) then HHGear^.dY := _0;
+    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;
@@ -1514,7 +1523,7 @@
     ropeDx := HHGear^.X - Gear^.X;
     ropeDy := HHGear^.Y - Gear^.Y;
 
-    if not TestCollisionYwithGear(HHGear, 1) then
+    if TestCollisionYwithGear(HHGear, 1) = 0 then
         begin
 
         // depending on the rope vector we know which X-side to check for collision
@@ -1551,12 +1560,12 @@
 
     if ((Gear^.Message and gmDown) <> 0) and (Gear^.Elasticity < Gear^.Friction) then
         if not (TestCollisionXwithGear(HHGear, hwSign(ropeDx))
-           or TestCollisionYwithGear(HHGear, hwSign(ropeDy))) then
+           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))) then
+           or (TestCollisionYwithGear(HHGear, -hwSign(ropeDy)) <> 0)) then
             Gear^.Elasticity := Gear^.Elasticity - _0_3;
 
     HHGear^.X := Gear^.X + mdX * Gear^.Elasticity;
@@ -1648,7 +1657,7 @@
         HHGear^.dX := -_0_6 * HHGear^.dX;
         haveCollision := true
         end;
-    if TestCollisionYwithGear(HHGear, hwSign(HHGear^.dY)) then
+    if TestCollisionYwithGear(HHGear, hwSign(HHGear^.dY)) <> 0 then
         begin
         HHGear^.dY := -_0_6 * HHGear^.dY;
         haveCollision := true
@@ -1750,12 +1759,12 @@
     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) then HHGear^.dY := _0;
+        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) then
+        if TestCollisionYwithGear(HHGear, 1) <> 0 then
             begin
             CheckHHDamage(HHGear);
             HHGear^.dY := _0
@@ -1863,11 +1872,11 @@
             doStepFallingGear(Gear);
     if (Gear^.Health = 0) then
         begin
-            if not Gear^.dY.isNegative and (Gear^.dY > _0_2) and TestCollisionYwithGear(Gear, 1) then
+            if not Gear^.dY.isNegative and (Gear^.dY > _0_2) and (TestCollisionYwithGear(Gear, 1) <> 0) then
                 inc(Gear^.Damage, hwRound(Gear^.dY * _70))
             else if not Gear^.dX.isNegative and (Gear^.dX > _0_2) and TestCollisionXwithGear(Gear, 1) then
                  inc(Gear^.Damage, hwRound(Gear^.dX * _70))
-            else if Gear^.dY.isNegative and (Gear^.dY < -_0_2) and TestCollisionYwithGear(Gear, -1) then
+            else if Gear^.dY.isNegative and (Gear^.dY < -_0_2) and (TestCollisionYwithGear(Gear, -1) <> 0) then
                  inc(Gear^.Damage, hwRound(Gear^.dY * -_70))
             else if Gear^.dX.isNegative and (Gear^.dX < -_0_2) and TestCollisionXwithGear(Gear, -1) then
                  inc(Gear^.Damage, hwRound(Gear^.dX * -_70));
@@ -1927,7 +1936,7 @@
 procedure doStepSMine(Gear: PGear);
 begin
     // TODO: do real calculation?
-    if TestCollisionXwithGear(Gear, 2) or TestCollisionYwithGear(Gear, -2) or TestCollisionXwithGear(Gear, -2) or TestCollisionYwithGear(Gear, 2) then
+    if TestCollisionXwithGear(Gear, 2) or (TestCollisionYwithGear(Gear, -2) <> 0) or TestCollisionXwithGear(Gear, -2) or (TestCollisionYwithGear(Gear, 2) <> 0) then
     begin
         if (hwAbs(Gear^.dX) > _0) or (hwAbs(Gear^.dY) > _0) then
         begin
@@ -1999,13 +2008,13 @@
     i: LongInt;
     particle: PVisualGear;
 begin
-    if (Gear^.dY.QWordValue = 0) and (Gear^.dY.QWordValue = 0) and not TestCollisionYwithGear(Gear, 1) then SetLittle(Gear^.dY);
+    if (Gear^.dY.QWordValue = 0) and (Gear^.dY.QWordValue = 0) and (TestCollisionYwithGear(Gear, 1) = 0) then SetLittle(Gear^.dY);
     Gear^.State := Gear^.State or gstAnimation;
     if ((Gear^.dX.QWordValue <> 0) or (Gear^.dY.QWordValue <> 0))  then
     begin
         DeleteCI(Gear);
         AllInactive := false;
-        if not Gear^.dY.isNegative and (Gear^.dY > _0_2) and TestCollisionYwithGear(Gear, 1) then
+        if not Gear^.dY.isNegative and (Gear^.dY > _0_2) and (TestCollisionYwithGear(Gear, 1) <> 0) then
         begin
             Gear^.State := Gear^.State or gsttmpFlag;
             inc(Gear^.Damage, hwRound(Gear^.dY * _70));
@@ -2019,7 +2028,7 @@
         else if not Gear^.dX.isNegative and (Gear^.dX > _0_2) and TestCollisionXwithGear(Gear, 1)
                  then
                  inc(Gear^.Damage, hwRound(Gear^.dX * _70))
-        else if Gear^.dY.isNegative and (Gear^.dY < -_0_2) and TestCollisionYwithGear(Gear, -1)
+        else if Gear^.dY.isNegative and (Gear^.dY < -_0_2) and (TestCollisionYwithGear(Gear, -1) <> 0)
                  then
                  inc(Gear^.Damage, hwRound(Gear^.dY * -_70))
         else if Gear^.dX.isNegative and (Gear^.dX < -_0_2) and TestCollisionXwithGear(Gear, -1)
@@ -2052,7 +2061,7 @@
     if Gear^.dX.QWordValue = 0 then AddGearCI(Gear)
     end; *)
 
-    if not Gear^.dY.isNegative and (Gear^.dY < _0_001) and TestCollisionYwithGear(Gear, 1) then Gear
+    if not Gear^.dY.isNegative and (Gear^.dY < _0_001) and (TestCollisionYwithGear(Gear, 1) <> 0) then Gear
         ^.dY := _0;
     if hwAbs(Gear^.dX) < _0_001 then Gear^.dX := _0;
 
@@ -2136,14 +2145,14 @@
         exit
     end;
 
-    if (Gear^.dY.QWordValue <> 0) or (not TestCollisionYwithGear(Gear, 1)) then
+    if (Gear^.dY.QWordValue <> 0) or (TestCollisionYwithGear(Gear, 1) = 0) then
     begin
         AllInactive := false;
         Gear^.dY := Gear^.dY + cGravity;
         Gear^.Y := Gear^.Y + Gear^.dY;
         if (not Gear^.dY.isNegative) and (Gear^.dY > _0_001) then SetAllHHToActive;
-        if (Gear^.dY.isNegative) and TestCollisionYwithGear(Gear, -1) then Gear^.dY := _0;
-        if (not Gear^.dY.isNegative) and TestCollisionYwithGear(Gear, 1) then
+        if (Gear^.dY.isNegative) and (TestCollisionYwithGear(Gear, -1) <> 0) then Gear^.dY := _0;
+        if (not Gear^.dY.isNegative) and (TestCollisionYwithGear(Gear, 1) <> 0) then
         begin
             if (Gear^.dY > _0_2) and (k = gtExplosives) then
                 inc(Gear^.Damage, hwRound(Gear^.dY * _70));
@@ -2249,7 +2258,7 @@
     sticky:= (Gear^.State and gsttmpFlag) <> 0;
     if not sticky then AllInactive := false;
 
-    if not TestCollisionYwithGear(Gear, 1) then
+    if TestCollisionYwithGear(Gear, 1) = 0 then
     begin
         AllInactive := false;
 
@@ -2447,7 +2456,7 @@
 
     inc(Gear^.Timer);
 
-    if TestCollisionYwithGear(HHGear, 1)
+    if (TestCollisionYwithGear(HHGear, 1) <> 0)
        or ((HHGear^.State and gstHHDriven) = 0)
        or CheckGearDrowning(HHGear)
        or ((Gear^.Message and gmAttack) <> 0) then
@@ -2633,7 +2642,7 @@
     HHGear^.X := HHGear^.X + HHGear^.dX;
     // hedgehog falling to collect cases
     HHGear^.dY := HHGear^.dY + cGravity;
-    if TestCollisionYwithGear(HHGear, 1)
+    if (TestCollisionYwithGear(HHGear, 1) <> 0)
        or CheckGearDrowning(HHGear) then
     begin
         DeleteGear(Gear);
@@ -3006,7 +3015,7 @@
     yyn := dirs[(LongInt(Gear^.Angle) + 4 + dA) mod 4].y;
 
     if (xx = 0) then
-        if TestCollisionYwithGear(Gear, yy) then
+        if TestCollisionYwithGear(Gear, yy) <> 0 then
             PrevAngle
     else
     begin
@@ -3083,13 +3092,12 @@
     AllInactive := false;
 
     Gear^.dY := Gear^.dY + cGravity;
-    if TestCollisionYwithGear(Gear, 1) then
-        Gear^.doStep := @doStepCakeUp
+    if TestCollisionYwithGear(Gear, 1) <> 0 then Gear^.doStep := @doStepCakeUp
     else
-    begin
+        begin
         Gear^.Y := Gear^.Y + Gear^.dY;
         if CheckGearDrowning(Gear) then AfterAttack
-    end
+        end
 end;
 
 procedure doStepCake(Gear: PGear);
@@ -3254,11 +3262,10 @@
 
     t := CheckGearsCollision(Gear);
     //fixes drill not exploding when touching HH bug
-    if (Gear^.Timer = 0)
-       or (t^.Count <> 0)
-       or (not TestCollisionYWithGear(Gear, hwSign(Gear^.dY))
-       and not TestCollisionXWithGear(Gear, hwSign(Gear^.dX))
-       and ((Gear^.State and gsttmpFlag) = 0)) 
+    if (Gear^.Timer = 0) or (t^.Count <> 0) or 
+       ( ((Gear^.State and gsttmpFlag) = 0) and
+         (TestCollisionYWithGear(Gear, hwSign(Gear^.dY)) = 0)
+         and not TestCollisionXWithGear(Gear, hwSign(Gear^.dX)))
 // CheckLandValue returns true if the type isn't matched
        or not CheckLandValue(hwRound(Gear^.X), hwRound(Gear^.Y), lfIndestructible) then
         begin
@@ -3271,7 +3278,7 @@
         DeleteGear(Gear);
         exit
         end
-    else if not TestCollisionYWithGear(Gear, hwSign(Gear^.dY)) and not TestCollisionXWithGear(Gear, hwSign(Gear^.dX)) then
+    else if (TestCollisionYWithGear(Gear, hwSign(Gear^.dY)) = 0) and not TestCollisionXWithGear(Gear, hwSign(Gear^.dX)) then
         begin
         StopSound(Gear^.SoundChannel);
         Gear^.Tag := 1;
@@ -3625,8 +3632,7 @@
         or (cWaterLine + 512 < hwRound(HHGear^.Y))
         or (TurnTimeLeft = 0)
         // allow brief ground touches - to be fair on this, might need another counter
-        or (((GameTicks and $1FF) = 0) and (not HHGear^.dY.isNegative) and TestCollisionYwithGear(
-        HHGear, 1))
+        or (((GameTicks and $1FF) = 0) and (not HHGear^.dY.isNegative) and (TestCollisionYwithGear(HHGear, 1) <> 0))
         or ((Gear^.Message and gmAttack) <> 0) then
         begin
         with HHGear^ do
@@ -3750,8 +3756,7 @@
        or CheckGearDrowning(HHGear)
        or (TurnTimeLeft = 0)
        // allow brief ground touches - to be fair on this, might need another counter
-       or (((GameTicks and $1FF) = 0) and (not HHGear^.dY.isNegative) and TestCollisionYwithGear(
-       HHGear, 1))
+       or (((GameTicks and $1FF) = 0) and (not HHGear^.dY.isNegative) and (TestCollisionYwithGear(HHGear, 1) <> 0))
        or ((Gear^.Message and gmAttack) <> 0) then
         begin
         with HHGear^ do
@@ -4824,7 +4829,7 @@
             Gear^.Y := Gear^.Y + _1_9;
             end;
         end;
-    if TestCollisionYwithGear(Gear, 1) then
+    if TestCollisionYwithGear(Gear, 1) <> 0 then
         begin
         Gear^.dY := _0;
         SetLittle(HitGear^.dX);
@@ -4899,7 +4904,7 @@
     if Gear^.Power < 45 then 
         begin
         inc(Gear^.Power);
-        if not TestCollisionYwithGear(hh^.Gear, -1) then hh^.Gear^.Y := hh^.Gear^.Y - _1;
+        if TestCollisionYwithGear(hh^.Gear, -1) = 0 then hh^.Gear^.Y := hh^.Gear^.Y - _1;
         end;
 
     graves := GearsNear(Gear^.X, Gear^.Y, gtGrave, Gear^.Radius);
--- a/hedgewars/HHHandlers.inc	Sun Oct 02 03:45:09 2011 +0200
+++ b/hedgewars/HHHandlers.inc	Sun Oct 02 10:36:43 2011 -0400
@@ -638,11 +638,11 @@
       begin
       Gear^.Message:= Gear^.Message and not gmLJump;
       DeleteCI(Gear);
-      if not TestCollisionYwithGear(Gear, -1) then
+      if TestCollisionYwithGear(Gear, -1) = 0 then
          if not TestCollisionXwithXYShift(Gear, _0, -2, hwSign(Gear^.dX)) then Gear^.Y:= Gear^.Y - _2 else
          if not TestCollisionXwithXYShift(Gear, _0, -1, hwSign(Gear^.dX)) then Gear^.Y:= Gear^.Y - _1;
       if not (TestCollisionXwithGear(Gear, hwSign(Gear^.dX))
-         or   TestCollisionYwithGear(Gear, -1)) then
+         or   (TestCollisionYwithGear(Gear, -1) <> 0)) then
          begin
          Gear^.dY:= -_0_15;
          if not cArtillery then Gear^.dX:= SignAs(_0_15, Gear^.dX);
@@ -685,17 +685,17 @@
    if TestCollisionXwithGear(Gear, hwSign(Gear^.dX)) then
       begin
       if not (TestCollisionXwithXYShift(Gear, _0, -6, hwSign(Gear^.dX))
-         or TestCollisionYwithGear(Gear, -1)) then Gear^.Y:= Gear^.Y - _1;
+         or (TestCollisionYwithGear(Gear, -1) <> 0)) then Gear^.Y:= Gear^.Y - _1;
       if not (TestCollisionXwithXYShift(Gear, _0, -5, hwSign(Gear^.dX))
-         or TestCollisionYwithGear(Gear, -1)) then Gear^.Y:= Gear^.Y - _1;
+         or (TestCollisionYwithGear(Gear, -1) <> 0)) then Gear^.Y:= Gear^.Y - _1;
       if not (TestCollisionXwithXYShift(Gear, _0, -4, hwSign(Gear^.dX))
-         or TestCollisionYwithGear(Gear, -1)) then Gear^.Y:= Gear^.Y - _1;
+         or (TestCollisionYwithGear(Gear, -1) <> 0)) then Gear^.Y:= Gear^.Y - _1;
       if not (TestCollisionXwithXYShift(Gear, _0, -3, hwSign(Gear^.dX))
-         or TestCollisionYwithGear(Gear, -1)) then Gear^.Y:= Gear^.Y - _1;
+         or (TestCollisionYwithGear(Gear, -1) <> 0)) then Gear^.Y:= Gear^.Y - _1;
       if not (TestCollisionXwithXYShift(Gear, _0, -2, hwSign(Gear^.dX))
-         or TestCollisionYwithGear(Gear, -1)) then Gear^.Y:= Gear^.Y - _1;
+         or (TestCollisionYwithGear(Gear, -1) <> 0)) then Gear^.Y:= Gear^.Y - _1;
       if not (TestCollisionXwithXYShift(Gear, _0, -1, hwSign(Gear^.dX))
-         or TestCollisionYwithGear(Gear, -1)) then Gear^.Y:= Gear^.Y - _1;
+         or (TestCollisionYwithGear(Gear, -1) <> 0)) then Gear^.Y:= Gear^.Y - _1;
       end;
 
    if (not cArtillery) and ((Gear^.Message and gmPrecise) = 0) and (not TestCollisionXwithGear(Gear, hwSign(Gear^.dX))) then
@@ -703,25 +703,25 @@
 
    SetAllHHToActive;
 
-   if not TestCollisionYwithGear(Gear, 1) then
+   if TestCollisionYwithGear(Gear, 1) = 0 then
    begin
    Gear^.Y:= Gear^.Y + _1;
-   if not TestCollisionYwithGear(Gear, 1) then
+   if TestCollisionYwithGear(Gear, 1) = 0 then
    begin
    Gear^.Y:= Gear^.Y + _1;
-   if not TestCollisionYwithGear(Gear, 1) then
+   if TestCollisionYwithGear(Gear, 1) = 0 then
    begin
    Gear^.Y:= Gear^.Y + _1;
-   if not TestCollisionYwithGear(Gear, 1) then
+   if TestCollisionYwithGear(Gear, 1) = 0 then
    begin
    Gear^.Y:= Gear^.Y + _1;
-   if not TestCollisionYwithGear(Gear, 1) then
+   if TestCollisionYwithGear(Gear, 1) = 0 then
    begin
    Gear^.Y:= Gear^.Y + _1;
-   if not TestCollisionYwithGear(Gear, 1) then
+   if TestCollisionYwithGear(Gear, 1) = 0 then
    begin
    Gear^.Y:= Gear^.Y + _1;
-   if not TestCollisionYwithGear(Gear, 1) then
+   if TestCollisionYwithGear(Gear, 1) = 0 then
       begin
       Gear^.Y:= Gear^.Y - _6;
       Gear^.dY:= _0;
@@ -758,7 +758,9 @@
 ////////////////////////////////////////////////////////////////////////////////
 procedure doStepHedgehogMoving(Gear: PGear);
 var isFalling, isUnderwater: boolean;
+    land: Word;
 begin
+land:= 0;
 isUnderwater:= cWaterLine < hwRound(Gear^.Y) + Gear^.Radius;
 if Gear^.dX.QWordValue > 8160437862 then Gear^.dX.QWordValue:= 8160437862;
 if Gear^.dY.QWordValue > 8160437862 then Gear^.dY.QWordValue:= 8160437862;
@@ -796,7 +798,8 @@
    end 
 else
    begin
-   if ((Gear^.dX.QWordValue + Gear^.dY.QWordValue) < _0_55.QWordValue)
+   land:= TestCollisionYwithGear(Gear, 1);
+   if ((Gear^.dX.QWordValue + Gear^.dY.QWordValue) < _0_55.QWordValue) and ((land and lfIce) = 0)
       and ((Gear^.State and gstHHJumping) <> 0) then SetLittle(Gear^.dX);
 
    if not Gear^.dY.isNegative then
@@ -810,7 +813,11 @@
       Gear^.dY:= _0;
       end else Gear^.dY:= Gear^.dY + cGravity;
 
-   if ((Gear^.State and gstMoving) <> 0) then Gear^.dX:= Gear^.dX * Gear^.Friction
+   if ((Gear^.State and gstMoving) <> 0) then
+       begin
+       if land and lfIce <> 0 then Gear^.dX:= Gear^.dX * (_1 - (_1 - Gear^.Friction) / _2)
+       else Gear^.dX:= Gear^.dX * Gear^.Friction;
+       end
    end;
 
 if (Gear^.State <> 0) then DeleteCI(Gear);
--- a/hedgewars/uAIMisc.pas	Sun Oct 02 03:45:09 2011 +0200
+++ b/hedgewars/uAIMisc.pas	Sun Oct 02 10:36:43 2011 -0400
@@ -332,18 +332,18 @@
 bY:= hwRound(Gear^.Y);
 case JumpType of
      jmpNone: exit(bRes);
-    jmpHJump: if not TestCollisionYwithGear(Gear, -1) then
+    jmpHJump: if TestCollisionYwithGear(Gear, -1) = 0 then
                  begin
                  Gear^.dY:= -_0_2;
                  SetLittle(Gear^.dX);
                  Gear^.State:= Gear^.State or gstMoving or gstHHJumping;
                  end else exit(bRes);
     jmpLJump: begin
-              if not TestCollisionYwithGear(Gear, -1) then
+              if TestCollisionYwithGear(Gear, -1) <> 0 then
                  if not TestCollisionXwithXYShift(Gear, _0, -2, hwSign(Gear^.dX)) then Gear^.Y:= Gear^.Y - int2hwFloat(2) else
                  if not TestCollisionXwithXYShift(Gear, _0, -1, hwSign(Gear^.dX)) then Gear^.Y:= Gear^.Y - _1;
               if not (TestCollisionXwithGear(Gear, hwSign(Gear^.dX))
-                 or   TestCollisionYwithGear(Gear, -1)) then
+                 or   (TestCollisionYwithGear(Gear, -1) <> 0)) then
                  begin
                  Gear^.dY:= -_0_15;
                  Gear^.dX:= SignAs(_0_15, Gear^.dX);
@@ -367,9 +367,9 @@
    inc(GoInfo.Ticks);
    Gear^.dY:= Gear^.dY + cGravity;
    if Gear^.dY > _0_4 then exit(bRes);
-   if (Gear^.dY.isNegative)and TestCollisionYwithGear(Gear, -1) then Gear^.dY:= _0;
+   if (Gear^.dY.isNegative)and (TestCollisionYwithGear(Gear, -1) <> 0) then Gear^.dY:= _0;
    Gear^.Y:= Gear^.Y + Gear^.dY;
-   if (not Gear^.dY.isNegative)and TestCollisionYwithGear(Gear, 1) then
+   if (not Gear^.dY.isNegative)and (TestCollisionYwithGear(Gear, 1) <> 0) then
       begin
       Gear^.State:= Gear^.State and not (gstMoving or gstHHJumping);
       Gear^.dY:= _0;
@@ -417,7 +417,7 @@
       end;
    Gear^.Y:= Gear^.Y + Gear^.dY;
    if hwRound(Gear^.Y) > pY then inc(GoInfo.FallPix);
-   if TestCollisionYwithGear(Gear, 1) then
+   if TestCollisionYwithGear(Gear, 1) <> 0 then
       begin
       inc(GoInfo.Ticks, 410);
       Gear^.State:= Gear^.State and not (gstMoving or gstHHJumping);
@@ -432,17 +432,17 @@
    if TestCollisionXwithGear(Gear, hwSign(Gear^.dX)) then
       begin
       if not (TestCollisionXwithXYShift(Gear, _0, -6, hwSign(Gear^.dX))
-         or TestCollisionYwithGear(Gear, -1)) then Gear^.Y:= Gear^.Y - _1;
+         or (TestCollisionYwithGear(Gear, -1) <> 0)) then Gear^.Y:= Gear^.Y - _1;
       if not (TestCollisionXwithXYShift(Gear, _0, -5, hwSign(Gear^.dX))
-         or TestCollisionYwithGear(Gear, -1)) then Gear^.Y:= Gear^.Y - _1;
+         or (TestCollisionYwithGear(Gear, -1) <> 0)) then Gear^.Y:= Gear^.Y - _1;
       if not (TestCollisionXwithXYShift(Gear, _0, -4, hwSign(Gear^.dX))
-         or TestCollisionYwithGear(Gear, -1)) then Gear^.Y:= Gear^.Y - _1;
+         or (TestCollisionYwithGear(Gear, -1) <> 0)) then Gear^.Y:= Gear^.Y - _1;
       if not (TestCollisionXwithXYShift(Gear, _0, -3, hwSign(Gear^.dX))
-         or TestCollisionYwithGear(Gear, -1)) then Gear^.Y:= Gear^.Y - _1;
+         or (TestCollisionYwithGear(Gear, -1) <> 0)) then Gear^.Y:= Gear^.Y - _1;
       if not (TestCollisionXwithXYShift(Gear, _0, -2, hwSign(Gear^.dX))
-         or TestCollisionYwithGear(Gear, -1)) then Gear^.Y:= Gear^.Y - _1;
+         or (TestCollisionYwithGear(Gear, -1) <> 0)) then Gear^.Y:= Gear^.Y - _1;
       if not (TestCollisionXwithXYShift(Gear, _0, -1, hwSign(Gear^.dX))
-         or TestCollisionYwithGear(Gear, -1)) then Gear^.Y:= Gear^.Y - _1;
+         or (TestCollisionYwithGear(Gear, -1) <> 0)) then Gear^.Y:= Gear^.Y - _1;
       end;
 
    if not TestCollisionXwithGear(Gear, hwSign(Gear^.dX)) then
@@ -450,25 +450,25 @@
       Gear^.X:= Gear^.X + int2hwFloat(hwSign(Gear^.dX));
       inc(GoInfo.Ticks, cHHStepTicks)
       end;
-   if not TestCollisionYwithGear(Gear, 1) then
+   if TestCollisionYwithGear(Gear, 1) = 0 then
    begin
    Gear^.Y:= Gear^.Y + _1;
-   if not TestCollisionYwithGear(Gear, 1) then
+   if TestCollisionYwithGear(Gear, 1) = 0 then
    begin
    Gear^.Y:= Gear^.Y + _1;
-   if not TestCollisionYwithGear(Gear, 1) then
+   if TestCollisionYwithGear(Gear, 1) = 0 then
    begin
    Gear^.Y:= Gear^.Y + _1;
-   if not TestCollisionYwithGear(Gear, 1) then
+   if TestCollisionYwithGear(Gear, 1) = 0 then
    begin
    Gear^.Y:= Gear^.Y + _1;
-   if not TestCollisionYwithGear(Gear, 1) then
+   if TestCollisionYwithGear(Gear, 1) = 0 then
    begin
    Gear^.Y:= Gear^.Y + _1;
-   if not TestCollisionYwithGear(Gear, 1) then
+   if TestCollisionYwithGear(Gear, 1) = 0 then
    begin
    Gear^.Y:= Gear^.Y + _1;
-   if not TestCollisionYwithGear(Gear, 1) then
+   if TestCollisionYwithGear(Gear, 1) = 0 then
       begin
       Gear^.Y:= Gear^.Y - _6;
       Gear^.dY:= _0;
--- a/hedgewars/uCollisions.pas	Sun Oct 02 03:45:09 2011 +0200
+++ b/hedgewars/uCollisions.pas	Sun Oct 02 10:36:43 2011 -0400
@@ -39,7 +39,7 @@
 function  CheckGearsCollision(Gear: PGear): PGearArray;
 
 function  TestCollisionXwithGear(Gear: PGear; Dir: LongInt): boolean;
-function  TestCollisionYwithGear(Gear: PGear; Dir: LongInt): boolean;
+function  TestCollisionYwithGear(Gear: PGear; Dir: LongInt): Word;
 
 function  TestCollisionXKick(Gear: PGear; Dir: LongInt): boolean;
 function  TestCollisionYKick(Gear: PGear; Dir: LongInt): boolean;
@@ -157,7 +157,7 @@
 TestCollisionXwithGear:= false
 end;
 
-function TestCollisionYwithGear(Gear: PGear; Dir: LongInt): boolean;
+function TestCollisionYwithGear(Gear: PGear; Dir: LongInt): Word;
 var x, y, i: LongInt;
     TestWord: LongWord;
 begin
@@ -181,11 +181,11 @@
    i:= x + Gear^.Radius * 2 - 2;
    repeat
      if (x and LAND_WIDTH_MASK) = 0 then
-        if Land[y, x] > TestWord then exit(true);
+        if Land[y, x] > TestWord then exit(Land[y, x]);
      inc(x)
    until (x > i);
    end;
-TestCollisionYwithGear:= false
+TestCollisionYwithGear:= 0
 end;
 
 function TestCollisionXKick(Gear: PGear; Dir: LongInt): boolean;
@@ -344,7 +344,7 @@
 begin
 Gear^.X:= Gear^.X + int2hwFloat(ShiftX);
 Gear^.Y:= Gear^.Y + int2hwFloat(ShiftY);
-if withGear then TestCollisionYwithXYShift:= TestCollisionYwithGear(Gear, Dir)
+if withGear then TestCollisionYwithXYShift:= TestCollisionYwithGear(Gear, Dir) <> 0
 else TestCollisionYwithXYShift:= TestCollisionY(Gear, Dir);
 Gear^.X:= Gear^.X - int2hwFloat(ShiftX);
 Gear^.Y:= Gear^.Y - int2hwFloat(ShiftY)
--- a/hedgewars/uConsts.pas	Sun Oct 02 03:45:09 2011 +0200
+++ b/hedgewars/uConsts.pas	Sun Oct 02 10:36:43 2011 -0400
@@ -89,10 +89,12 @@
 
 // To allow these to layer, going to treat them as masks. The bottom byte is reserved for objects
 // TODO - set lfBasic for all solid land, ensure all uses of the flags can handle multiple flag bits
+// lfObject and lfBasic are only to be different *graphically*  in all other ways they should be treated the same
     lfBasic          = $8000;  // white
     lfIndestructible = $4000;  // red
-    lfObject         = $2000;  // no idea - lfObject and lfBasic are only to be different *graphically*  in all other ways they should be treated the same
-    lfDamaged        = $1000;  // no idea
+    lfObject         = $2000;  
+    lfDamaged        = $1000;  //
+    lfIce            = $0800;  // blue
 
     cMaxPower     = 1500;
     cMaxAngle     = 2048;
--- a/hedgewars/uGears.pas	Sun Oct 02 03:45:09 2011 +0200
+++ b/hedgewars/uGears.pas	Sun Oct 02 10:36:43 2011 -0400
@@ -1490,11 +1490,11 @@
                     if TestCollisionXwithGear(Gear, hwSign(Gear^.dX)) then
                         begin
                         if not (TestCollisionXwithXYShift(Gear, _0, -3, hwSign(Gear^.dX))
-                            or TestCollisionYwithGear(Gear, -1)) then Gear^.Y:= Gear^.Y - _1;
+                            or (TestCollisionYwithGear(Gear, -1) <> 0)) then Gear^.Y:= Gear^.Y - _1;
                         if not (TestCollisionXwithXYShift(Gear, _0, -2, hwSign(Gear^.dX))
-                            or TestCollisionYwithGear(Gear, -1)) then Gear^.Y:= Gear^.Y - _1;
+                            or (TestCollisionYwithGear(Gear, -1) <> 0)) then Gear^.Y:= Gear^.Y - _1;
                         if not (TestCollisionXwithXYShift(Gear, _0, -1, hwSign(Gear^.dX))
-                            or TestCollisionYwithGear(Gear, -1)) then Gear^.Y:= Gear^.Y - _1;
+                            or (TestCollisionYwithGear(Gear, -1) <> 0)) then Gear^.Y:= Gear^.Y - _1;
                         end;
 
                     if (Ammo^.Kind <> gtFlame) or ((Ammo^.State and gsttmpFlag) = 0) then FollowGear:= Gear
--- a/hedgewars/uLand.pas	Sun Oct 02 03:45:09 2011 +0200
+++ b/hedgewars/uLand.pas	Sun Oct 02 10:36:43 2011 -0400
@@ -1158,6 +1158,8 @@
                         Land[cpY + y, cpX + x]:= 0
                     else if p^[x] = (AMask or RMask) then
                         Land[cpY + y, cpX + x]:= lfIndestructible
+                    else if p^[x] = (AMask or BMask) then
+                        Land[cpY + y, cpX + x]:= lfIce
                     else if p^[x] = $FFFFFFFF then
                         Land[cpY + y, cpX + x]:= lfBasic;
                 end;
--- a/hedgewars/uLandGraphics.pas	Sun Oct 02 03:45:09 2011 +0200
+++ b/hedgewars/uLandGraphics.pas	Sun Oct 02 10:36:43 2011 -0400
@@ -718,6 +718,8 @@
                        Land[cpY + y, cpX + x]:= lfBasic
                    else
                        Land[cpY + y, cpX + x]:= lfObject;
+                   // For testing only. Intent is to flag this on objects with masks, or use it for an ice ray gun
+                   if (Theme = 'Snow') or (Theme = 'Christmas') then Land[cpY + y, cpX + x]:= Land[cpY + y, cpX + x] or lfIce;
                    LandPixels[gY, gX]:= PLongword(@(p^[x * 4]))^
                    end;
             p:= @(p^[Image^.pitch]);
--- a/hedgewars/uLandObjects.pas	Sun Oct 02 03:45:09 2011 +0200
+++ b/hedgewars/uLandObjects.pas	Sun Oct 02 10:36:43 2011 -0400
@@ -97,7 +97,11 @@
                     LandPixels[(cpY + y) div 2, (cpX + x) div 2]:= p^[x];
 
         if ((Land[cpY + y, cpX + x] and $FF00) = 0) and ((p^[x] and AMask) <> 0) then
-            Land[cpY + y, cpX + x]:= lfObject
+            begin
+            Land[cpY + y, cpX + x]:= lfObject;
+            // For testing only. Intent is to flag this on objects with masks, or use it for an ice ray gun
+            if (Theme = 'Snow') or (Theme = 'Christmas') then Land[cpY + y, cpX + x]:= Land[cpY + y, cpX + x] or lfIce
+            end;
         end;
     p:= @(p^[Image^.pitch shr 2])
     end;