Snowball weapon
authornemo
Sun, 19 Dec 2010 21:06:34 -0500
changeset 4578 f3cf226fad16
parent 4576 d85062310790
child 4580 bd43d9ac6e04
Snowball weapon
QTfrontend/hwconsts.cpp.in
hedgewars/GSHandlers.inc
hedgewars/HHHandlers.inc
hedgewars/uAIAmmoTests.pas
hedgewars/uGears.pas
hedgewars/uGearsRender.pas
hedgewars/uMisc.pas
hedgewars/uTypes.pas
hedgewars/uVariables.pas
share/hedgewars/Data/Graphics/AmmoMenu/Ammos.png
share/hedgewars/Data/Graphics/AmmoMenu/Ammos_bw.png
share/hedgewars/Data/Graphics/Hedgehog/amSnowball.png
share/hedgewars/Data/Graphics/Snowball.png
share/hedgewars/Data/Locale/en.txt
share/hedgewars/Data/Themes/Compost/Snowball.png
share/hedgewars/Data/Themes/Compost/amSnowball.png
share/hedgewars/Data/Themes/Underwater/Snowball.png
share/hedgewars/Data/Themes/Underwater/amSnowball.png
--- a/QTfrontend/hwconsts.cpp.in	Mon Dec 20 02:00:22 2010 +0100
+++ b/QTfrontend/hwconsts.cpp.in	Sun Dec 19 21:06:34 2010 -0500
@@ -37,10 +37,10 @@
 int cMaxTeams = 6;
 
 QString * cDefaultAmmoStore = new QString(
-        "93919294221991210322351110012010000002111101010111"
-        "04050405416006555465544647765766666661555101011154"
-        "00000000000002055000000400070040000000002000000006"
-        "13111103121111111231141111111111111112111111011111"
+        "939192942219912103223511100120100000021111010101112"
+        "040504054160065554655446477657666666615551010111541"
+        "000000000000020550000004000700400000000020000000060"
+        "131111031211111112311411111111111111121111110111112"
         );
 int cAmmoNumber = cDefaultAmmoStore->size() / 4;
 
@@ -49,40 +49,40 @@
         << qMakePair(QString("Default"), *cDefaultAmmoStore)
         << qMakePair(QString("Crazy"),     QString(
         // TODO: Remove Piano's unlimited uses!
-        "99999999999999999929999999999999992999999999099999"
-        "11111101111111111111111111111111111111111111011111"
-        "00000000000000000000000000000000000000000000000000"
-        "13111103121111111231141111111111111112111101011111"
+        "999999999999999999299999999999999929999999990999999"
+        "111111011111111111111111111111111111111111110111111"
+        "000000000000000000000000000000000000000000000000000"
+        "131111031211111112311411111111111111121111010111111"
         ))
         << qMakePair(QString("Pro Mode"),  QString(
-        "90900090000000000000090000000000000000000000000000"
-        "00000000000000000000000000000000000000000000000000"
-        "00000000000002055000000400070040000000002000000000"
-        "11111111111111111111111111111111111111111001011111"
+        "909000900000000000000900000000000000000000000000000"
+        "000000000000000000000000000000000000000000000000000"
+        "000000000000020550000004000700400000000020000000000"
+        "111111111111111111111111111111111111111110010111111"
         ))
         << qMakePair(QString("Shoppa"),    QString(
-        "00000099000000000000000000000000000000000000000000"
-        "44444100442444022101121212224220000000020004000100"
-        "00000000000000000000000000000000000000000000000000"
-        "11111111111111111111111111111111111111111011011111"
+        "000000990000000000000000000000000000000000000000000"
+        "444441004424440221011212122242200000000200040001001"
+        "000000000000000000000000000000000000000000000000000"
+        "111111111111111111111111111111111111111110110111111"
         ))
         << qMakePair(QString("Clean Slate"),QString(
-        "10100090000100000110000000000000000000000000000010"
-        "04050405416006555465544647765766666661555101011154"
-        "00000000000000000000000000000000000000000000000000"
-        "13111103121111111231141111111111111112111111011111"
+        "101000900001000001100000000000000000000000000000100"
+        "040504054160065554655446477657666666615551010111541"
+        "000000000000000000000000000000000000000000000000000"
+        "131111031211111112311411111111111111121111110111111"
         ))
         << qMakePair(QString("Minefield"), QString(
-        "00000099000900000003000000000000000000000000000000"
-        "00000000000000000000000000000000000000000000000000"
-        "00000000000002055000000400070040000000002000000006"
-        "11111111111111111111111111111111111111111111011111"
+        "000000990009000000030000000000000000000000000000000"
+        "000000000000000000000000000000000000000000000000000"
+        "000000000000020550000004000700400000000020000000060"
+        "111111111111111111111111111111111111111111110111111"
         ))
         << qMakePair(QString("Thinking with Portals"), QString(
-        "90000090020000000021000000000000001100000900000000"
-        "04050405416006555465544647765766666661555101011154"
-        "00000000000002055000000400070040000000002000000006"
-        "13111103121111111231141111111111111112111111011111"
+        "900000900200000000210000000000000011000009000000000"
+        "040504054160065554655446477657666666615551010111541"
+        "000000000000020550000004000700400000000020000000060"
+        "131111031211111112311411111111111111121111110111111"
         ));
 
 QColor *colors[] = {
--- a/hedgewars/GSHandlers.inc	Mon Dec 20 02:00:22 2010 +0100
+++ b/hedgewars/GSHandlers.inc	Sun Dec 19 21:06:34 2010 -0500
@@ -28,32 +28,32 @@
 
     // Gear is still on the same Pixel it was before
     if steps < 1 then
-    begin
+        begin
         if onlyCheckIfChanged then
-        begin
+            begin
             Gear^.X := Gear^.X + dX;
             Gear^.Y := Gear^.Y + dY;
             EXIT;
-        end
+            end
         else
             steps := 1;
-    end;
+        end;
 
     if steps > 1 then
-    begin
+        begin
         sX:= dX / steps;
         sY:= dY / steps;
-    end
+        end
     else
-    begin
+        begin
         sX:= dX;
         sY:= dY;
-    end;
+        end;
 
     caller:= Gear^.doStep;
 
     for i:= 1 to steps do
-    begin
+        begin
         Gear^.X := Gear^.X + sX;
         Gear^.Y := Gear^.Y + sY;
         step(Gear);
@@ -61,7 +61,7 @@
         or ((Gear^.State and gstCollision) <> 0)
         or ((Gear^.State and gstMoving) = 0) then
             break;
-    end;
+        end;
 end;
 
 procedure makeHogsWorry(x, y: hwFloat; r: LongInt);
@@ -71,27 +71,27 @@
 begin
     gi := GearsList;
     while gi <> nil do
-    begin
+        begin
         if (gi^.Kind = gtHedgehog) then
-        begin
+            begin
             d := r - hwRound(Distance(gi^.X - x, gi^.Y - y));
             if (d > 1) and not gi^.Invulnerable and (GetRandom(2) = 0) then
-            begin
+                begin
                 if (CurrentHedgehog^.Gear = gi) then
                     PlaySound(sndOops, gi^.Hedgehog^.Team^.voicepack)
                 else
-                begin
+                    begin
                     if (gi^.State and gstMoving) = 0 then
                         gi^.State := gi^.State or gstLoser;
                     if d > r div 2 then
                         PlaySound(sndNooo, gi^.Hedgehog^.Team^.voicepack)
                     else
                         PlaySound(sndUhOh, gi^.Hedgehog^.Team^.voicepack);
+                    end;
                 end;
             end;
+        gi := gi^.NextGear
         end;
-        gi := gi^.NextGear
-    end;
 end;
 ////////////////////////////////////////////////////////////////////////////////
 procedure doStepDrowningGear(Gear: PGear);
@@ -107,28 +107,29 @@
     isSubmersible:= (Gear = CurrentHedgehog^.Gear) and (CurAmmoGear <> nil) and (CurAmmoGear^.AmmoType = amJetpack);
     // probably needs tweaking. might need to be in a case statement based upon gear type
     if cWaterLine < hwRound(Gear^.Y) + Gear^.Radius then
-    begin
+        begin
         skipSpeed := _0_25;
         skipAngle := _1_9;
         skipDecay := _0_87;
         // this could perhaps be a tiny bit higher.
         if  (hwSqr(Gear^.dX) + hwSqr(Gear^.dY) > skipSpeed) and
            (hwAbs(Gear^.dX) > skipAngle * hwAbs(Gear^.dY)) then
-        begin
+            begin
             Gear^.dY.isNegative := true;
             Gear^.dY := Gear^.dY * skipDecay;
             Gear^.dX := Gear^.dX * skipDecay;
             CheckGearDrowning := false;
             PlaySound(sndSkip)
-        end
+            end
         else
-        begin
+            begin
             if not isSubmersible then
-            begin
+                begin
                 CheckGearDrowning := true;
                 Gear^.State := gstDrowning;
                 Gear^.RenderTimer := false;
-                if (Gear^.Kind <> gtSniperRifleShot) and (Gear^.Kind <> gtShotgunShot) and (Gear^.Kind <> gtDEagleShot) and (Gear^.Kind <> gtSineGunShot) then
+                if (Gear^.Kind <> gtSniperRifleShot) and (Gear^.Kind <> gtShotgunShot) and 
+                   (Gear^.Kind <> gtDEagleShot) and (Gear^.Kind <> gtSineGunShot) then
                     if Gear^.Kind = gtHedgehog then 
                         begin
                         if Gear^.Hedgehog^.Effects[heResurrectable] then
@@ -152,21 +153,21 @@
         if ((cReducedQuality and rqPlainSplash) = 0) and 
            (((not isSubmersible) and (hwRound(Gear^.Y) < cWaterLine + 64 + Gear^.Radius)) or
              (isSubmersible and (hwRound(Gear^.Y) < cWaterLine + 2 + Gear^.Radius) and ((CurAmmoGear^.Pos = 0) and (CurAmmoGear^.dY < _0_01)))) then
-        begin
+            begin
             AddVisualGear(hwRound(Gear^.X), cWaterLine, vgtSplash);
 
             maxDrops := (Gear^.Radius div 2) + hwRound(Gear^.dX * Gear^.Radius * 2) + hwRound(Gear^.
                         dY * Gear^.Radius * 2);
             for i:= max(maxDrops div 3, min(32, Random(maxDrops))) downto 0 do
-            begin
+                begin
                 particle := AddVisualGear(hwRound(Gear^.X) - 3 + Random(6), cWaterLine, vgtDroplet);
                 if particle <> nil then
-                begin
+                    begin
                     particle^.dX := particle^.dX - (Gear^.dX.QWordValue / 42949672960);
                     particle^.dY := particle^.dY - (Gear^.dY.QWordValue / 21474836480)
+                    end
                 end
-            end
-        end;
+            end;
         if isSubmersible and (CurAmmoGear^.Pos = 0) then CurAmmoGear^.Pos := 1000
     end
     else
@@ -188,17 +189,16 @@
     particle: PVisualGear;
 begin
     if _0_4 < Gear^.dY then
-    begin
+        begin
         dmg := ModifyDamage(1 + hwRound((hwAbs(Gear^.dY) - _0_4) * 70), Gear);
         PlaySound(sndBump);
         if dmg < 1 then exit;
 
         for i:= min(12, (3 + dmg div 10)) downto 0 do
-        begin
-            particle := AddVisualGear(hwRound(Gear^.X) - 5 + Random(10), hwRound(Gear^.Y) + 12,
-                        vgtDust);
+            begin
+            particle := AddVisualGear(hwRound(Gear^.X) - 5 + Random(10), hwRound(Gear^.Y) + 12, vgtDust);
             if particle <> nil then particle^.dX := particle^.dX + (Gear^.dX.QWordValue / 21474836480);
-        end;
+            end;
 
         if (Gear^.Invulnerable) then exit;
 
@@ -267,53 +267,53 @@
     if (hwRound(Gear^.X) < LAND_WIDTH div -2) or (hwRound(Gear^.X) > LAND_WIDTH * 3 div 2) then Gear^.State := Gear^.State or gstCollision;
 
     if Gear^.dY.isNegative then
-    begin
+        begin
         isFalling := true;
         if TestCollisionYwithGear(Gear, -1) then
-        begin
+            begin
             collV := -1;
             Gear^.dX :=   Gear^.dX * Gear^.Friction;
             Gear^.dY := - Gear^.dY * Gear^.Elasticity;
             Gear^.State := Gear^.State or gstCollision
-        end
+            end
         else if (Gear^.AdvBounce=1) and TestCollisionYwithGear(Gear, 1) then collV := 1;
-    end
+        end
     else if TestCollisionYwithGear(Gear, 1) then
         begin
-            collV := 1;
-            isFalling := false;
-            Gear^.dX :=   Gear^.dX * Gear^.Friction;
-            Gear^.dY := - Gear^.dY * Gear^.Elasticity;
-            Gear^.State := Gear^.State or gstCollision
+        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
+        begin
         isFalling := true;
         if (Gear^.AdvBounce=1) and not Gear^.dY.isNegative and TestCollisionYwithGear(Gear, -1) then
             collV := -1;
-    end;
+        end;
 
 
     if TestCollisionXwithGear(Gear, hwSign(Gear^.dX)) then
-    begin
+        begin
         collH := hwSign(Gear^.dX);
         Gear^.dX := - Gear^.dX * Gear^.Elasticity;
         Gear^.dY :=   Gear^.dY * Gear^.Elasticity;
         Gear^.State := Gear^.State or gstCollision
-    end
+        end
     else if (Gear^.AdvBounce=1) and TestCollisionXwithGear(Gear, -hwSign(Gear^.dX)) then 
         collH := -hwSign(Gear^.dX); 
     //if Gear^.AdvBounce and (collV <>0) and (collH <> 0) and (hwSqr(tdX) + hwSqr(tdY) > _0_08) then
     if (Gear^.AdvBounce=1) and (collV <>0) and (collH <> 0) and ((collV=-1) or ((tdX.QWordValue +
        tdY.QWordValue) > _0_2.QWordValue)) then
-    begin
+        begin
         Gear^.dX := tdY*Gear^.Elasticity*Gear^.Friction;
         Gear^.dY := tdX*Gear^.Elasticity;
         //*Gear^.Friction;
         Gear^.dY.isNegative := not tdY.isNegative;
         isFalling := false;
         Gear^.AdvBounce := 10;
-    end;
+        end;
 
     if Gear^.AdvBounce > 1 then dec(Gear^.AdvBounce);
 
@@ -519,16 +519,46 @@
     if (GameFlags and gfMoreWind) = 0 then Gear^.dX := Gear^.dX + cWindSpeed;
     doStepFallingGear(Gear);
     if (Gear^.State and gstCollision) <> 0 then
-    begin
+        begin
         doMakeExplosion(hwRound(Gear^.X), hwRound(Gear^.Y), 50, EXPLAutoSound);
         DeleteGear(Gear);
         exit
-    end;
+        end;
     if (GameTicks and $3F) = 0 then
         AddVisualGear(hwRound(Gear^.X), hwRound(Gear^.Y), vgtSmokeTrace);
 end;
 
 ////////////////////////////////////////////////////////////////////////////////
+procedure doStepSnowball(Gear: PGear);
+var kick, i: LongInt;
+    particle: PVisualGear;
+begin
+    AllInactive := false;
+    if (GameFlags and gfMoreWind) = 0 then Gear^.dX := Gear^.dX + cWindSpeed;
+    doStepFallingGear(Gear);
+    CalcRotationDirAngle(Gear);
+    if (Gear^.State and gstCollision) <> 0 then
+        begin
+        kick:= hwRound((hwAbs(Gear^.dX)+hwAbs(Gear^.dY)) * _20);
+        Gear^.dY.isNegative:= not Gear^.dY.isNegative;
+        Gear^.dX.isNegative:= not Gear^.dX.isNegative;
+        AmmoShove(Gear, 1, kick);
+        for i:= 15 + kick div 10 downto 0 do
+            begin
+            particle := AddVisualGear(hwRound(Gear^.X) + Random(25), hwRound(Gear^.Y) + Random(25), vgtDust);
+            if particle <> nil then particle^.dX := particle^.dX + (Gear^.dX.QWordValue / 21474836480)
+            end;
+        DeleteGear(Gear);
+        exit
+        end;
+    if ((GameTicks and $1F) = 0) and (Random(3) = 0) then
+        begin
+        AddVisualGear(hwRound(Gear^.X), hwRound(Gear^.Y), vgtDust);
+        if particle <> nil then particle^.dX := particle^.dX + (Gear^.dX.QWordValue / 21474836480)
+        end
+end;
+
+////////////////////////////////////////////////////////////////////////////////
 procedure doStepGrave(Gear: PGear);
 begin
     AllInactive := false;
@@ -895,7 +925,7 @@
 ////////////////////////////////////////////////////////////////////////////////
 procedure doStepPickHammerWork(Gear: PGear);
 var 
-    i, ei: LongInt;
+    i, ei, x, y: LongInt;
     HHGear: PGear;
 begin
     AllInactive := false;
@@ -903,53 +933,58 @@
     dec(Gear^.Timer);
     if (Gear^.Timer = 0)or((Gear^.Message and gmDestroy) <> 0)or((HHGear^.State and gstHHDriven) =
        0) then
-    begin
+        begin
         StopSound(Gear^.SoundChannel);
         DeleteGear(Gear);
         AfterAttack;
         doStepHedgehogMoving(HHGear);  // for gfInfAttack
         exit
-    end;
-
+        end;
+
+    x:= hwRound(Gear^.X);
+    y:= hwRound(Gear^.Y);
     if (Gear^.Timer mod 33) = 0 then
-    begin
+        begin
         HHGear^.State := HHGear^.State or gstNoDamage;
-        doMakeExplosion(hwRound(Gear^.X), hwRound(Gear^.Y) + 7, 6, EXPLDontDraw);
+        doMakeExplosion(x, y + 7, 6, EXPLDontDraw);
         HHGear^.State := HHGear^.State and not gstNoDamage
-    end;
+        end;
 
     if (Gear^.Timer mod 47) = 0 then
-    begin
-        for i:= 0 to 1 do
-            AddVisualGear(hwRound(Gear^.X) - 5 + Random(10), hwRound(Gear^.Y) + 12, vgtDust);
-        i := hwRound(Gear^.X) - Gear^.Radius - LongInt(GetRandom(2));
-        ei := hwRound(Gear^.X) + Gear^.Radius + LongInt(GetRandom(2));
+        begin
+        // ok. this was an attempt to turn off dust if not actually drilling land.  I have no idea why it isn't working as expected
+        //if ((y + 12 and LAND_HEIGHT_MASK) = 0) and ((x and LAND_WIDTH_MASK) = 0) and (Land[y + 12, x] > 255) then 
+            for i:= 0 to 1 do
+                AddVisualGear(x - 5 + Random(10), y + 12, vgtDust);
+
+        i := x - Gear^.Radius - LongInt(GetRandom(2));
+        ei := x + Gear^.Radius + LongInt(GetRandom(2));
         while i <= ei do
-        begin
-            DrawExplosion(i, hwRound(Gear^.Y) + 3, 3);
+            begin
+            DrawExplosion(i, y + 3, 3);
             inc(i, 1)
-        end;
+            end;
 
         if CheckLandValue(hwRound(Gear^.X + Gear^.dX + SignAs(_6,Gear^.dX)), hwRound(Gear^.Y + _1_9)
            , lfIndestructible) then
-        begin
+            begin
             Gear^.X := Gear^.X + Gear^.dX;
             Gear^.Y := Gear^.Y + _1_9;
-        end;
+            end;
         SetAllHHToActive;
-    end;
+        end;
     if TestCollisionYwithGear(Gear, 1) then
-    begin
+        begin
         Gear^.dY := _0;
         SetLittle(HHGear^.dX);
         HHGear^.dY := _0;
-    end
+        end
     else
-    begin
+        begin
         Gear^.dY := Gear^.dY + cGravity;
         Gear^.Y := Gear^.Y + Gear^.dY;
         if hwRound(Gear^.Y) > cWaterLine then Gear^.Timer := 1
-    end;
+        end;
 
     Gear^.X := Gear^.X + HHGear^.dX;
     HHGear^.X := Gear^.X;
@@ -1858,10 +1893,10 @@
     DeleteCI(HHGear);
 
     for i:= 0 to 3 do
-    begin
+        begin
         AmmoShove(Gear, 30, 25);
         Gear^.X := Gear^.X + Gear^.dX * 5
-    end;
+        end;
 
     HHGear^.State := (HHGear^.State and (not gstNoDamage)) or gstMoving;
 
@@ -2688,7 +2723,7 @@
 
     if ((y and LAND_HEIGHT_MASK) = 0) and ((x and LAND_WIDTH_MASK) = 0) then
         if (Land[y, x] <> 0) then
-        begin
+            begin
             Gear^.dX.isNegative := not Gear^.dX.isNegative;
             Gear^.dY.isNegative := not Gear^.dY.isNegative;
             Gear^.dX := Gear^.dX * _1_5;
@@ -2696,13 +2731,13 @@
             AmmoShove(Gear, 0, 40);
             AfterAttack;
             DeleteGear(Gear)
-        end
+            end
+        else
     else
-    else
-    begin
+        begin
         AfterAttack;
         DeleteGear(Gear)
-    end
+        end
 end;
 
 procedure doStepSeductionWear(Gear: PGear);
--- a/hedgewars/HHHandlers.inc	Mon Dec 20 02:00:22 2010 +0100
+++ b/hedgewars/HHHandlers.inc	Sun Dec 19 21:06:34 2010 -0500
@@ -207,6 +207,7 @@
                   amClusterBomb: FollowGear:= AddGear(hwRound(lx), hwRound(ly), gtClusterBomb,  0, newDx, newDy, CurWeapon^.Timer);
                       amGasBomb: FollowGear:= AddGear(hwRound(lx), hwRound(ly), gtGasBomb,      0, newDx, newDy, CurWeapon^.Timer);
                       amBazooka: FollowGear:= AddGear(hwRound(lx), hwRound(ly), gtShell,        0, newDx, newDy, 0);
+                     amSnowball: FollowGear:= AddGear(hwRound(lx), hwRound(ly), gtSnowball,     0, newDx, newDy, 0);
                           amBee: FollowGear:= AddGear(hwRound(lx), hwRound(ly), gtBee,          0, newDx, newDy, 0);
                       amShotgun: begin
                                  PlaySound(sndShotgunReload);
--- a/hedgewars/uAIAmmoTests.pas	Mon Dec 20 02:00:22 2010 +0100
+++ b/hedgewars/uAIAmmoTests.pas	Sun Dec 19 21:06:34 2010 -0500
@@ -102,7 +102,8 @@
             (proc: @TestGrenade;     flags: 0), // amSMine
             (proc: @TestFirePunch;   flags: 0), // amHammer
             (proc: nil;              flags: 0), // amResurrector
-            (proc: nil;              flags: 0) // amDrillStrike
+            (proc: nil;              flags: 0),// amDrillStrike
+            (proc: nil;              flags: 0) // amSnowball
             );
 
 const BadTurn = Low(LongInt) div 4;
--- a/hedgewars/uGears.pas	Mon Dec 20 02:00:22 2010 +0100
+++ b/hedgewars/uGears.pas	Sun Dec 19 21:06:34 2010 -0500
@@ -127,7 +127,8 @@
             @doStepHammer,
             @doStepHammerHit,
             @doStepResurrector,
-            @doStepNapalmBomb
+            @doStepNapalmBomb,
+            @doStepSnowball
             );
 
 procedure InsertGearToList(Gear: PGear);
@@ -246,6 +247,11 @@
        gtShell: begin
                 gear^.Radius:= 4;
                 end;
+       gtSnowball: begin
+                gear^.Radius:= 4;
+                gear^.Elasticity:= _1;
+                gear^.Friction:= _1;
+                end;
        gtGrave: begin
                 gear^.ImpactSound:= sndGraveImpact;
                 gear^.nImpactSounds:= 1;
@@ -1245,13 +1251,10 @@
         begin
         
         if (Ammo^.Kind = gtDEagleShot) or (Ammo^.Kind = gtSniperRifleShot) then 
-        begin
+            begin
             VGear := AddVisualGear(hwround(Ammo^.X), hwround(Ammo^.Y), vgtBulletHit);
-            if VGear <> nil then
-            begin
-                VGear^.Angle := DxDy2Angle(-Ammo^.dX, Ammo^.dY);
+            if VGear <> nil then VGear^.Angle := DxDy2Angle(-Ammo^.dX, Ammo^.dY);
             end;
-        end;
         
         if (Gear^.Kind = gtHedgehog) and (Ammo^.State and gsttmpFlag <> 0) and (Ammo^.Kind = gtShover) then Gear^.FlightTime:= 1;
 
--- a/hedgewars/uGearsRender.pas	Mon Dec 20 02:00:22 2010 +0100
+++ b/hedgewars/uGearsRender.pas	Sun Dec 19 21:06:34 2010 -0500
@@ -543,6 +543,7 @@
             CurWeapon:= GetAmmoEntry(HH^);
             case amt of
                 amBazooka: DrawRotated(sprHandBazooka, hx, hy, sign, aangle);
+                amSnowball: DrawRotated(sprHandSnowball, hx, hy, sign, aangle);
                 amMortar: DrawRotated(sprHandMortar, hx, hy, sign, aangle);
                 amMolotov: DrawRotated(sprHandMolotov, hx, hy, sign, aangle);
                 amBallgun: DrawRotated(sprHandBallgun, hx, hy, sign, aangle);
@@ -845,6 +846,7 @@
 begin
     case Gear^.Kind of
           gtBomb: DrawRotated(sprBomb, x, y, 0, Gear^.DirAngle);
+      gtSnowball: DrawRotated(sprSnowball, x, y, 0, Gear^.DirAngle);
        gtGasBomb: DrawRotated(sprCheese, x, y, 0, Gear^.DirAngle);
        gtMolotov: DrawRotated(sprMolotov, x, y, 0, Gear^.DirAngle);
 
--- a/hedgewars/uMisc.pas	Mon Dec 20 02:00:22 2010 +0100
+++ b/hedgewars/uMisc.pas	Sun Dec 19 21:06:34 2010 -0500
@@ -122,11 +122,11 @@
 var convertedSurf: PSDL_Surface = nil;
 begin
     if (tmpsurf^.format^.bitsperpixel = 24) or ((tmpsurf^.format^.bitsperpixel = 32) and (tmpsurf^.format^.rshift > tmpsurf^.format^.bshift)) then
-    begin
+        begin
         convertedSurf:= SDL_ConvertSurface(tmpsurf, @conversionFormat, SDL_SWSURFACE);
         SDL_FreeSurface(tmpsurf);
         exit(convertedSurf);
-    end;
+        end;
 
     exit(tmpsurf);
 end;
--- a/hedgewars/uTypes.pas	Mon Dec 20 02:00:22 2010 +0100
+++ b/hedgewars/uTypes.pas	Sun Dec 19 21:06:34 2010 -0500
@@ -52,7 +52,7 @@
             sprCheese, sprHandCheese, sprHandFlamethrower, sprChunk, sprNote,
             sprSMineOff, sprSMineOn, sprHandSMine, sprHammer,
             sprHandResurrector, sprCross, sprAirDrill, sprNapalmBomb,
-            sprBulletHit
+            sprBulletHit, sprSnowball, sprHandSnowball
             );
 
     // Gears that interact with other Gears and/or Land
@@ -67,7 +67,7 @@
             gtSniperRifleShot, gtJetpack, gtMolotov, gtExplosives, gtBirdy, // 45
             gtEgg, gtPortal, gtPiano, gtGasBomb, gtSineGunShot, gtFlamethrower, // 51
             gtSMine, gtPoisonCloud, gtHammer, gtHammerHit, gtResurrector, // 56
-            gtNapalmBomb); // 57
+            gtNapalmBomb, gtSnowball); // 58
 
     // Gears that are _only_ of visual nature (e.g. background stuff, visual effects, speechbubbles, etc.)
     TVisualGearType = (vgtFlake, vgtCloud, vgtExplPart, vgtExplPart2, vgtFire,
@@ -112,7 +112,7 @@
             amRCPlane, amLowGravity, amExtraDamage, amInvulnerable, amExtraTime, // 35
             amLaserSight, amVampiric, amSniperRifle, amJetpack, amMolotov, amBirdy, amPortalGun, // 42
             amPiano, amGasBomb, amSineGun, amFlamethrower, amSMine, amHammer, // 48
-            amResurrector, amDrillStrike);
+            amResurrector, amDrillStrike, amSnowball);
 
     TCrateType = (HealthCrate, AmmoCrate, UtilityCrate);
 
@@ -342,7 +342,7 @@
             sidLowGravity, sidExtraDamage, sidInvulnerable, sidExtraTime,
             sidLaserSight, sidVampiric, sidSniperRifle, sidJetpack,
             sidMolotov, sidBirdy, sidPortalGun, sidPiano, sidGasBomb, sidSineGun, sidFlamethrower,
-            sidSMine, sidHammer, sidResurrector, sidDrillStrike);
+            sidSMine, sidHammer, sidResurrector, sidDrillStrike, sidSnowball);
 
     TMsgStrId = (sidStartFight, sidDraw, sidWinner, sidVolume, sidPaused,
             sidConfirm, sidSuddenDeath, sidRemaining, sidFuel, sidSync,
--- a/hedgewars/uVariables.pas	Mon Dec 20 02:00:22 2010 +0100
+++ b/hedgewars/uVariables.pas	Sun Dec 19 21:06:34 2010 -0500
@@ -548,8 +548,12 @@
             (FileName:  'BulletHit'; Path: ptGraphics; AltPath: ptNone;
                 Texture: nil; Surface: nil; Width:  32; Height: 32;
                 imageWidth: 0; imageHeight: 0; saveSurf: false; priority:
-                tpMedium; getDimensions: false; getImageDimensions: true)
+                tpMedium; getDimensions: false; getImageDimensions: true),
             // sprNapalmBomb
+            (FileName:  'Snowball'; Path: ptCurrTheme; AltPath: ptGraphics; Texture: nil; Surface: nil;
+            Width:  16; Height: 16; imageWidth: 0; imageHeight: 0; saveSurf: false; priority: tpMedium; getDimensions: false; getImageDimensions: true),// sprSnowball
+            (FileName:  'amSnowball'; Path: ptCurrTheme; AltPath: ptHedgehog; Texture: nil; Surface: nil;
+            Width:  64; Height: 64; imageWidth: 0; imageHeight: 0; saveSurf: false; priority: tpMedium; getDimensions: false; getImageDimensions: true) // sprHandSnowball
             );
 
 
@@ -1957,11 +1961,32 @@
             PosCount: 2;
             PosSprite: sprAmAirplane;
             ejectX: 0;
+            ejectY: 0),
+// Snowball
+            (NameId: sidSnowball;
+            NameTex: nil;
+            Probability: 0;
+            NumberInCase: 1;
+            Ammo: (Propz: ammoprop_Power or ammoprop_AltUse;
+                Count: 2;
+                NumPerTurn: 0;
+                Timer: 0;
+                Pos: 0;
+                AmmoType: amSnowball;
+                AttackVoice: sndNone);
+            Slot: 0;
+            TimeAfterTurn: 3000;
+            minAngle: 0;
+            maxAngle: 0;
+            isDamaging: true;
+            SkipTurns: 0;
+            PosCount: 1;
+            PosSprite: sprWater;
+            ejectX: 0; 
             ejectY: 0)
         );
 
 
-
     conversionFormat: TSDL_PixelFormat = (
         palette: nil;
         BitsPerPixel : 32;
Binary file share/hedgewars/Data/Graphics/AmmoMenu/Ammos.png has changed
Binary file share/hedgewars/Data/Graphics/AmmoMenu/Ammos_bw.png has changed
Binary file share/hedgewars/Data/Graphics/Hedgehog/amSnowball.png has changed
Binary file share/hedgewars/Data/Graphics/Snowball.png has changed
--- a/share/hedgewars/Data/Locale/en.txt	Mon Dec 20 02:00:22 2010 +0100
+++ b/share/hedgewars/Data/Locale/en.txt	Sun Dec 19 21:06:34 2010 -0500
@@ -51,6 +51,7 @@
 00:48=Hammer
 00:49=Resurrector
 00:50=Drill Strike
+00:51=Snowball
 
 01:00=Let's fight!
 01:01=Round draw
Binary file share/hedgewars/Data/Themes/Compost/Snowball.png has changed
Binary file share/hedgewars/Data/Themes/Compost/amSnowball.png has changed
Binary file share/hedgewars/Data/Themes/Underwater/Snowball.png has changed
Binary file share/hedgewars/Data/Themes/Underwater/amSnowball.png has changed