pull icegun into default. it has a few issues, but, pretty close. that way more people will play with it.
authornemo
Tue, 26 Feb 2013 20:39:18 -0500
changeset 8590 c64b758e0412
parent 8577 7445ce865e04 (current diff)
parent 8589 3bb505fc707e (diff)
child 8591 9afb44f030b6
child 8592 bb724ef609db
pull icegun into default. it has a few issues, but, pretty close. that way more people will play with it.
--- a/hedgewars/GSHandlers.inc	Mon Feb 25 11:37:48 2013 +0400
+++ b/hedgewars/GSHandlers.inc	Tue Feb 26 20:39:18 2013 -0500
@@ -1783,7 +1783,7 @@
         Gear^.Y := Gear^.Y + Gear^.dY;
 
         if (not Gear^.dY.isNegative) and (Gear^.dY > _0_001) then
-            SetAllHHToActive;
+            SetAllHHToActive(false);
 
         if (not Gear^.dY.isNegative) and (TestCollisionYwithGear(Gear, 1) <> 0) then
             begin
@@ -2382,7 +2382,9 @@
 
         repeat
             CurrentTeam^.CurrHedgehog := Succ(CurrentTeam^.CurrHedgehog) mod (CurrentTeam^.HedgehogsNumber);
-        until (CurrentTeam^.Hedgehogs[CurrentTeam^.CurrHedgehog].Gear <> nil) and (CurrentTeam^.Hedgehogs[CurrentTeam^.CurrHedgehog].Gear^.Damage = 0);
+        until (CurrentTeam^.Hedgehogs[CurrentTeam^.CurrHedgehog].Gear <> nil) and 
+              (CurrentTeam^.Hedgehogs[CurrentTeam^.CurrHedgehog].Gear^.Damage = 0) and 
+              (CurrentTeam^.Hedgehogs[CurrentTeam^.CurrHedgehog].Effects[heFrozen]=0);
 
         SwitchCurrentHedgehog(@CurrentTeam^.Hedgehogs[CurrentTeam^.CurrHedgehog]);
         AmmoMenuInvalidated:= true; 
@@ -5044,7 +5046,138 @@
 A frozen hog will animate differently.  To be decided, but possibly in a similar fashion to a grave when it comes to explosions.  The hog might (possibly) not be damaged by explosions.  This might make freezing potentially useful for friendlies in a bad position.  It might be better to allow damage though.
 A frozen hog stays frozen for a certain number of turns. Each turn the frozen overlay becomes fainter, until it fades and the hog animates normally again.
 *)
+
+
+procedure updateFuel(Gear: PGear);
+var 
+  t:LongInt;
+begin
+    t:= Gear^.Health div 10;
+    if (t <> Gear^.Damage) and ((GameTicks and $3F) = 0) then
+    begin
+    Gear^.Damage:= t;
+    FreeTexture(Gear^.Tex);
+    Gear^.Tex := RenderStringTex(trmsg[sidFuel] + ': ' + inttostr(t) +
+              '%', cWhiteColor, fntSmall)
+    end;
+    if GameTicks mod 10 = 0 then dec(Gear^.Health);
+end;
+
+
+procedure updateTarget(Gear:PGear; newX, newY:HWFloat);
+    var
+    iter:PGear;    
+begin
+  with Gear^ do
+  begin
+    dX:= newX;
+    dY:= newY;
+    Pos:= 0;
+    Target.X:= NoPointX;
+    LastDamage:= nil;
+    X:= Hedgehog^.Gear^.X;
+    Y:= Hedgehog^.Gear^.Y;
+    //unfreeze all semifrozen hogs - make this generic hog cleanup
+(*
+    iter := GearsList;
+    while iter <> nil do
+        begin
+        if (iter^.Kind = gtHedgehog) and 
+        (iter^.Hedgehog^.Effects[heFrozen] and $FF = 0) then 
+        iter^.Hedgehog^.Effects[heFrozen]:= 0;
+        iter:= iter^.NextGear
+        end 
+*)
+  end;
+end;
+
+
+function isLandscapeEdge(weight:Longint):boolean;
+begin
+    result := (weight < 8) and (weight >= 2);
+end;
+
+function isLandscape(weight:Longint):boolean;
+begin
+    result := weight < 2;
+end;
+
+function isEmptySpace(weight:Longint):boolean;
+begin
+    result := not isLandscape(weight) and not isLandscapeEdge(weight);
+end;
+
+
+function getPixelWeight(x, y:Longint): Longint;
+var
+    i, j:Longint;
+begin    
+    result := 0;
+    for i := x - 1 to x + 1 do
+        for j := y - 1 to y + 1 do 
+        begin
+        if (i < 0) or 
+           (i > LAND_WIDTH - 1) or 
+           (j < 0) or 
+           (j > LAND_HEIGHT -1) or 
+           ((Land[j, i] and $FF00) = 0) then
+           begin
+           result := result + 1;
+           end;
+        end;
+end;
+
+
+procedure drawIcePixel(x, y:Longint);
+var 
+    iceSurface: PSDL_Surface;
+    icePixels: PLongwordArray;
+    pictureX, pictureY: LongInt;
+    w, c: LongWord;
+begin
+    if Land[y, x] and lfIce <> 0 then exit;
+// So. 3 parameters here. Ice colour, Ice opacity, and a bias on the greyscaled pixel towards lightness
+    iceSurface:= SpritesData[sprIceTexture].Surface;
+    pictureX := x mod iceSurface^.w;
+    pictureY := y mod iceSurface^.h;
+    icePixels := iceSurface^.pixels;
+    w:= LandPixels[y, x];
+    w:= round(((w shr RShift and $FF) * RGB_LUMINANCE_RED +
+          (w shr BShift and $FF) * RGB_LUMINANCE_GREEN +
+          (w shr GShift and $FF) * RGB_LUMINANCE_BLUE));
+    if w < 128 then w:= w+128;
+    if w > 255 then w:= 255;
+    w:= (w shl RShift) or (w shl BShift) or (w shl GShift) or (LandPixels[y,x] and AMask);
+    //LandPixels[y, x]:= w;
+    LandPixels[y, x]:= addBgColor(w, IceColor);
+    LandPixels[y, x]:= addBgColor(LandPixels[y, x], icePixels^[iceSurface^.w * (y mod iceSurface^.h) + (x mod iceSurface^.w)]);
+
+    Land[y, x] := Land[y, x] or lfIce;
+end;
+
+procedure DrawIce(x, y: Longint); 
+    const iceRadius :Longint = 32;
+var
+    i, j: Longint;
+    weight: Longint;
+    landRect : TSDL_RECT;
+begin
+    FillRoundInLandWithIce(x, y, iceRadius);
+    SetAllHHToActive; 
+    landRect.x := min(max(x - iceRadius, 0), LAND_WIDTH - 1);
+    landRect.y := min(max(y - iceRadius, 0), LAND_HEIGHT - 1);
+    landRect.w := min(2*iceRadius, LAND_WIDTH - landRect.x - 1);
+    landRect.h := min(2*iceRadius, LAND_HEIGHT - landRect.y - 1);
+    UpdateLandTexture(landRect.x, landRect.w, landRect.y, landRect.h, true);
+end;
+
+
 procedure doStepIceGun(Gear: PGear);
+const iceWaitCollision:Longint = 0;
+const iceCollideWithGround:Longint = 1;
+const iceWaitNextTarget:Longint = 2;
+const iceCollideWithHog:Longint = 4;
+const groundFreezingTime:Longint = 1000;
 var
     HHGear: PGear;
     ndX, ndY: hwFloat;
@@ -5052,7 +5185,7 @@
     hogs: PGearArrayS;
 begin
     HHGear := Gear^.Hedgehog^.Gear;
-    if (Gear^.Health = 0) or (HHGear = nil) or (HHGear^.Damage <> 0) then
+    if (Gear^.Message and gmAttack <> 0) or (Gear^.Health = 0) or (HHGear = nil) or (HHGear^.Damage <> 0) then
         begin
         DeleteGear(Gear);
         AfterAttack;
@@ -5060,16 +5193,9 @@
         end
     else
         begin
-        t:= Gear^.Health div 10;
-        if (t <> Gear^.Damage) and ((GameTicks and $3F) = 0) then
-            begin
-            Gear^.Damage:= t;
-            FreeTexture(Gear^.Tex);
-            Gear^.Tex := RenderStringTex(trmsg[sidFuel] + ': ' + inttostr(t) +
-                         '%', cWhiteColor, fntSmall)
-            end
+        updateFuel(Gear);
         end;
-    if GameTicks mod 10 = 0 then dec(Gear^.Health);
+
     with Gear^ do
         begin
         HedgehogChAngle(HHGear);
@@ -5079,65 +5205,76 @@
            ((Target.X <> NoPointX) and (Target.X and LAND_WIDTH_MASK = 0) and 
              (Target.Y and LAND_HEIGHT_MASK = 0) and ((Land[Target.Y, Target.X] = 0))) then
             begin
-            dX:= ndX;
-            dY:= ndY;
-            Pos:= 0;
-            Target.X:= NoPointX;
-            LastDamage:= nil;
-            X:= HHGear^.X;
-            Y:= HHGear^.Y;
-(* unfreeze all semifrozen hogs - make this generic hog cleanup
-            iter := GearsList;
-            while iter <> nil do
-                begin
-                if (iter^.Kind = gtHedgehog) and 
-                   (iter^.Hedgehog^.Effects[heFrozen] < 0) then 
-                    iter^.Hedgehog^.Effects[heFrozen]:= 0;
-                iter:= iter^.NextGear
-                end *)
+                updateTarget(Gear, ndX, ndY);
+                IceState := iceWaitCollision;
             end
         else
             begin
             X:= X + dX;
             Y:= Y + dY;
             gX:= hwRound(X);
-            gY:= hwRound(Y);
-            if Target.X = NoPointX then t:= hwRound(hwSqr(X-HHGear^.X)+hwSqr(Y-HHGear^.Y));
+            gY:= hwRound(Y);    
+            if Target.X = NoPointX then 
+            begin
+                t:= hwRound(hwSqr(X-HHGear^.X)+hwSqr(Y-HHGear^.Y));
+            end;
+
             if Target.X <> NoPointX then
-                begin
+            begin
+                CheckCollisionWithLand(Gear);
+                if (State and gstCollision) <> 0 then
+                begin        
+                    if IceState = iceWaitCollision then
+                    begin
+                        IceState := iceCollideWithGround;
+                        IceTime := GameTicks;                    
+                    end;
+                end;
+
                 if (abs(gX-Target.X) < 2) and (abs(gY-Target.Y) < 2) then
-                    begin
+                begin
                     X:= HHGear^.X;
                     Y:= HHGear^.Y
-                    end;
+                end;
+
+                if (IceState = iceCollideWithGround) and ((GameTicks - IceTime) > groundFreezingTime) then
+                begin 
+                    DrawIce(Target.X, Target.Y);                                        
+                    IceState := iceWaitNextTarget;
+                end;
+
 // freeze nearby hogs
-                if GameTicks mod 10 = 0 then dec(Gear^.Health);
-                hogs := GearsNear(Gear^.X, Gear^.Y, gtHedgehog, Gear^.Radius);
+                hogs := GearsNear(int2hwFloat(Target.X), int2hwFloat(Target.Y), gtHedgehog, Gear^.Radius*2);
                 if hogs.size > 0 then
                     for i:= 0 to hogs.size - 1 do
                         if hogs.ar^[i] <> HHGear then
-                            begin
-                            //if Gear^.Hedgehog^.Effects[heFrozen]:= 0;
-                            end;
+                            if GameTicks mod 5 = 0 then 
+                                begin
+                                hogs.ar^[i]^.Active:= true;
+                                if hogs.ar^[i]^.Hedgehog^.Effects[heFrozen] < 256 then
+                                    hogs.ar^[i]^.Hedgehog^.Effects[heFrozen] := hogs.ar^[i]^.Hedgehog^.Effects[heFrozen] + 1
+                                else if hogs.ar^[i]^.Hedgehog^.Effects[heFrozen] = 256 then
+                                    hogs.ar^[i]^.Hedgehog^.Effects[heFrozen]:= 100000
+                                end;
                 inc(Pos)
-                end
+            end
             else if (t > 400) and ((gY > cWaterLine) or
                     (((gX and LAND_WIDTH_MASK = 0) and (gY and LAND_HEIGHT_MASK = 0))
                         and (Land[gY, gX] <> 0))) then
-                begin
+            begin
                 Target.X:= gX;
                 Target.Y:= gY;
                 X:= HHGear^.X;
                 Y:= HHGear^.Y
-                end;
-            if (gX > max(LAND_WIDTH,4096)*2) or
+            end;
+            {if (gX > max(LAND_WIDTH,4096)*2) or
                     (gX < -max(LAND_WIDTH,4096)) or
                     (gY < -max(LAND_HEIGHT,4096)) or
                     (gY > max(LAND_HEIGHT,4096)+512) then
-                begin
+            begin
                 X:= HHGear^.X;
                 Y:= HHGear^.Y
-                end
+            end}
         end
     end;
 end;
--- a/hedgewars/uGears.pas	Mon Feb 25 11:37:48 2013 +0400
+++ b/hedgewars/uGears.pas	Tue Feb 26 20:39:18 2013 -0500
@@ -46,7 +46,8 @@
 procedure ProcessGears;
 procedure EndTurnCleanup;
 procedure SetAllToActive;
-procedure SetAllHHToActive;
+procedure SetAllHHToActive; inline;
+procedure SetAllHHToActive(Ice: boolean);
 procedure DrawGears;
 procedure FreeGearsList;
 procedure AddMiscGears;
@@ -562,7 +563,12 @@
     end
 end;
 
-procedure SetAllHHToActive;
+procedure SetAllHHToActive; inline;
+begin
+SetAllHHToActive(true)
+end;
+
+procedure SetAllHHToActive(Ice: boolean);
 var t: PGear;
 begin
 AllInactive:= false;
@@ -570,12 +576,14 @@
 while t <> nil do
     begin
     if (t^.Kind = gtHedgehog) or (t^.Kind = gtExplosives) then
-        t^.Active:= true;
+        begin
+        if (t^.Kind = gtHedgehog) and Ice then CheckIce(t);
+        t^.Active:= true
+        end;
     t:= t^.NextGear
     end
 end;
 
-
 procedure DrawGears;
 var Gear: PGear;
     x, y: LongInt;
@@ -766,6 +774,8 @@
     begin
     dec(i);
     Gear:= t^.ar[i];
+    if (Ammo^.Kind = gtFlame) and (Gear^.Kind = gtHedgehog) and (Gear^.Hedgehog^.Effects[heFrozen] > 255) then
+        Gear^.Hedgehog^.Effects[heFrozen]:= max(255,Gear^.Hedgehog^.Effects[heFrozen]-10000);
     tmpDmg:= ModifyDamage(Damage, Gear);
     if (Gear^.State and gstNoDamage) = 0 then
         begin
@@ -780,6 +790,7 @@
         if (Gear^.Kind = gtHedgehog) and (Ammo^.State and gsttmpFlag <> 0) and (Ammo^.Kind = gtShover) then
             Gear^.FlightTime:= 1;
 
+
         case Gear^.Kind of
             gtHedgehog,
             gtMine,
--- a/hedgewars/uGearsHedgehog.pas	Mon Feb 25 11:37:48 2013 +0400
+++ b/hedgewars/uGearsHedgehog.pas	Tue Feb 26 20:39:18 2013 -0500
@@ -29,6 +29,7 @@
 procedure HedgehogChAngle(HHGear: PGear); 
 procedure PickUp(HH, Gear: PGear);
 procedure AddPickup(HH: THedgehog; ammo: TAmmoType; cnt, X, Y: LongWord);
+procedure CheckIce(Gear: PGear); inline;
 
 implementation
 uses uConsts, uVariables, uFloat, uAmmos, uSound, uCaptions, 
@@ -377,7 +378,10 @@
                                  end;
                     //amStructure: newGear:= AddGear(hwRound(lx) + hwSign(dX) * 7, hwRound(ly), gtStructure, gstWait, SignAs(_0_02, dX), _0, 3000);
                        amTardis: newGear:= AddGear(hwRound(X), hwRound(Y), gtTardis, 0, _0, _0, 5000);
-                       amIceGun: newGear:= AddGear(hwRound(X), hwRound(Y), gtIceGun, 0, _0, _0, 0);
+                       amIceGun: begin
+                       newGear:= AddGear(hwRound(X), hwRound(Y), gtIceGun, 0, _0, _0, 0);
+                       newGear^.radius := 8;
+                       end;
             end;
             if altUse and (newGear <> nil) then
                begin
@@ -778,7 +782,7 @@
     if (not cArtillery) and ((Gear^.Message and gmPrecise) = 0) then
         MakeHedgehogsStep(Gear);
 
-    SetAllHHToActive;
+    SetAllHHToActive(false);
     AddGearCI(Gear)
     end
 end;
@@ -1196,7 +1200,7 @@
     if Gear^.Timer = 0 then
         begin
         Gear^.State:= Gear^.State and (not (gstWait or gstLoser or gstWinner or gstAttacked or gstNotKickable or gstHHChooseTarget));
-        Gear^.Active:= false;
+        if Gear^.Hedgehog^.Effects[heFrozen] = 0 then Gear^.Active:= false;
         AddGearCI(Gear);
         exit
         end
@@ -1206,40 +1210,24 @@
 AllInactive:= false
 end;
 
-////////////////////////////////////////////////////////////////////////////////
-procedure doStepHedgehog(Gear: PGear);
+procedure CheckIce(Gear: PGear); inline;
 (*
 var x,y,tx,ty: LongInt;
     tdX, tdY, slope: hwFloat; 
     land: Word; *)
 var slope: hwFloat; 
 begin
-CheckSum:= CheckSum xor Gear^.Hedgehog^.BotLevel;
-if (Gear^.Message and gmDestroy) <> 0 then
-    begin
-    DeleteGear(Gear);
-    exit
-    end;
-
-if (Gear^.State and gstHHDriven) = 0 then
-    doStepHedgehogFree(Gear)
-else
-    begin
-    with Gear^.Hedgehog^ do
-        if Team^.hasGone then
-            TeamGoneEffect(Team^)
-        else
-            doStepHedgehogDriven(Gear)
-    end;
-if (Gear^.Message and (gmAllStoppable or gmLJump or gmHJump) = 0)
-and (Gear^.State and (gstHHJumping or gstHHHJump or gstAttacking) = 0)
-and (not Gear^.dY.isNegative) and (GameTicks mod (100*LongWOrd(hwRound(cMaxWindSpeed*2/cGravity))) = 0)
-and (TestCollisionYwithGear(Gear, 1) and lfIce <> 0) then
-    begin
-    slope:= CalcSlopeBelowGear(Gear);
-    Gear^.dX:=Gear^.dX+slope*_0_07;
-    if slope.QWordValue <> 0 then
-        Gear^.State:= Gear^.State or gstMoving;
+    if (Gear^.Message and (gmAllStoppable or gmLJump or gmHJump) = 0)
+    and (Gear^.State and (gstHHJumping or gstHHHJump or gstAttacking) = 0)
+    and (not Gear^.dY.isNegative) and (TestCollisionYwithGear(Gear, 1) and lfIce <> 0) then
+        begin
+        slope:= CalcSlopeBelowGear(Gear);
+        if slope.QWordValue > 730144440 then // ignore mild slopes
+            begin
+            Gear^.dX:=Gear^.dX+slope*cGravity*_256;
+            Gear^.State:= Gear^.State or gstMoving
+            end
+        end;
 (*
     x:= hwRound(Gear^.X);
     y:= hwRound(Gear^.Y);
@@ -1254,7 +1242,35 @@
     AddVisualGear(x + hwRound(_40 * slope), y - hwRound(_40 * slope), vgtSmokeTrace);
     AddVisualGear(x - hwRound(_50 * slope), y + hwRound(_50 * slope), vgtSmokeTrace);
     AddVisualGear(x + hwRound(_50 * slope), y - hwRound(_50 * slope), vgtSmokeTrace); *)
-    end
+end;
+
+////////////////////////////////////////////////////////////////////////////////
+procedure doStepHedgehog(Gear: PGear);
+begin
+CheckSum:= CheckSum xor Gear^.Hedgehog^.BotLevel;
+if (Gear^.Message and gmDestroy) <> 0 then
+    begin
+    DeleteGear(Gear);
+    exit
+    end;
+if GameTicks mod 100 = 0 then CheckIce(Gear);
+if Gear^.Hedgehog^.Effects[heFrozen] > 0 then 
+    begin
+    if Gear^.Hedgehog^.Effects[heFrozen] > 256 then
+        dec(Gear^.Hedgehog^.Effects[heFrozen])
+    else if GameTicks mod 10 = 0 then
+        dec(Gear^.Hedgehog^.Effects[heFrozen])
+    end;
+if (Gear^.State and gstHHDriven) = 0 then
+    doStepHedgehogFree(Gear)
+else
+    begin
+    with Gear^.Hedgehog^ do
+        if Team^.hasGone then
+            TeamGoneEffect(Team^)
+        else
+            doStepHedgehogDriven(Gear)
+    end;
 end;
 
 end.
--- a/hedgewars/uGearsRender.pas	Mon Feb 25 11:37:48 2013 +0400
+++ b/hedgewars/uGearsRender.pas	Tue Feb 26 20:39:18 2013 -0500
@@ -211,6 +211,8 @@
     defaultPos, HatVisible: boolean;
     HH: PHedgehog;
     CurWeapon: PAmmo;
+    iceOffset:Longint;
+    r:TSDL_Rect;
 begin
     HH:= Gear^.Hedgehog;
     if HH^.Unplaced then
@@ -239,6 +241,29 @@
     defaultPos:= true;
     HatVisible:= false;
 
+    if HH^.Effects[heFrozen] > 0 then
+        if HH^.Effects[heFrozen] < 256 then
+            begin
+            DrawHedgehog(sx, sy,
+                    sign,
+                    0,
+                    0,
+                    0);
+            defaultPos:= false;
+            HatVisible:= true
+            end
+        else 
+            begin
+            DrawHedgehog(sx, sy,
+                    sign,
+                    2,
+                    4,
+                    0);
+            defaultPos:= false;
+            HatVisible:= false;
+            exit
+            end;
+
 
     if HH^.Effects[hePoisoned] <> 0 then
         begin
@@ -247,6 +272,7 @@
         Tint($FF, $FF, $FF, $FF)
         end;
 
+
     if ((Gear^.State and gstWinner) <> 0) and
     ((CurAmmoGear = nil) or (CurAmmoGear^.Kind <> gtPickHammer)) then
         begin
@@ -538,7 +564,7 @@
                         DrawTextureCentered(sx, sy - 40, CurAmmoGear^.Tex)
                     end;
                 gtIceGun:
-                    begin DrawSpriteRotated(sprHandBallgun, hx, hy, sign, aangle);
+                    begin DrawSpriteRotated(sprIceGun, hx, hy, sign, aangle);
                     if CurAmmoGear^.Tex <> nil then
                         DrawTextureCentered(sx, sy - 40, CurAmmoGear^.Tex)
                     end;
@@ -669,7 +695,7 @@
                 amBee: DrawSpriteRotatedF(sprHandBee, hx, hy, (RealTicks div 125) mod 4, sign, aangle);
                 amFlamethrower: DrawSpriteRotatedF(sprHandFlamethrower, hx, hy, (RealTicks div 125) mod 4, sign, aangle);
                 amLandGun: DrawSpriteRotated(sprHandBallgun, hx, hy, sign, aangle);
-                amIceGun: DrawSpriteRotated(sprHandBallgun, hx, hy, sign, aangle);
+                amIceGun: DrawSpriteRotated(sprIceGun, hx, hy, sign, aangle);
                 amResurrector: DrawCircle(ox, oy, 98, 4, $F5, $DB, $35, $AA); // I'd rather not like to hardcode 100 here
             end;
 
@@ -917,6 +943,23 @@
         Tint($FF, $FF, $FF, max($40, round($FF * abs(1 - ((RealTicks div 2 + Gear^.uid * 491) mod 1500) / 750))));
         DrawSprite(sprInvulnerable, sx - 24, sy - 24, 0);
         end;
+
+    if HH^.Effects[heFrozen] = HH^.Effects[heFrozen] and $FF then
+        begin
+       /// Tint($00, $FF, $40, $40);  (HH^.Effects[heFrozen] and $FF)
+        iceOffset:= trunc(HH^.Effects[heFrozen] / 256 * 64);
+        Tint($FF, $FF, $FF, $FF);        
+        r.x := 128;
+        r.y := 128 - iceOffset;
+        r.w := 64;
+        r.h := iceOffset;
+        //DrawTextureFromRect(sx-32, sy-iceoffset+32, @r, SpritesData[sprFrozenHog].texture);
+        DrawTextureFromRectDir(sx-16+sign*2, sy+48-iceoffset, r.w, r.h, @r, HHTexture, sign);
+
+        Tint($FF, $FF, $FF, $FF);
+        end;
+
+
     if cVampiric and
     (CurrentHedgehog^.Gear <> nil) and
     (CurrentHedgehog^.Gear = Gear) then
--- a/hedgewars/uGearsUtils.pas	Mon Feb 25 11:37:48 2013 +0400
+++ b/hedgewars/uGearsUtils.pas	Tue Feb 26 20:39:18 2013 -0500
@@ -182,6 +182,7 @@
 i:= _1;
 if (CurrentHedgehog <> nil) and CurrentHedgehog^.King then
     i:= _1_5;
+if (Gear^.Hedgehog <> nil) and (Gear^.Hedgehog^.Effects[heFrozen] > 0) then i:=i*_0_2;
 if (Gear^.Hedgehog <> nil) and (Gear^.Hedgehog^.King) then
     ModifyDamage:= hwRound(_0_01 * cDamageModifier * dmg * i * cDamagePercent * _0_5)
 else
--- a/hedgewars/uLandGraphics.pas	Mon Feb 25 11:37:48 2013 +0400
+++ b/hedgewars/uLandGraphics.pas	Tue Feb 26 20:39:18 2013 -0500
@@ -36,6 +36,7 @@
 procedure DrawHLinesExplosions(ar: PRangeArray; Radius: LongInt; y, dY: LongInt; Count: Byte);
 procedure DrawTunnel(X, Y, dX, dY: hwFloat; ticks, HalfWidth: LongInt);
 procedure FillRoundInLand(X, Y, Radius: LongInt; Value: Longword);
+procedure FillRoundInLandWithIce(X, Y, Radius: LongInt);
 procedure ChangeRoundInLand(X, Y, Radius: LongInt; doSet, isCurrent: boolean);
 function  LandBackPixel(x, y: LongInt): LongWord;
 procedure DrawLine(X1, Y1, X2, Y2: LongInt; Color: Longword);
@@ -158,6 +159,8 @@
     end
 end;
 
+
+
 procedure FillRoundInLand(X, Y, Radius: LongInt; Value: Longword);
 var dx, dy, d: LongInt;
 begin
@@ -243,6 +246,130 @@
 
 end;
 
+
+function isLandscapeEdge(weight:Longint):boolean;
+begin
+    result := (weight < 8) and (weight >= 2);
+end;
+
+function isLandscape(weight:Longint):boolean;
+begin
+    result := weight < 2;
+end;
+
+function isEmptySpace(weight:Longint):boolean;
+begin
+    result := not isLandscape(weight) and not isLandscapeEdge(weight);
+end;
+
+function getPixelWeight(x, y:Longint): Longint;
+var
+    i, j:Longint;
+begin
+    result := 0;
+    for i := x - 1 to x + 1 do
+        for j := y - 1 to y + 1 do
+        begin
+        if (i < 0) or
+           (i > LAND_WIDTH - 1) or
+           (j < 0) or
+           (j > LAND_HEIGHT -1) or
+           ((Land[j, i] and $FF00) = 0) then
+           begin
+           result := result + 1;
+           end;
+        end;
+end;
+
+procedure drawIcePixel(y, x:Longint);
+var
+    iceSurface: PSDL_Surface;
+    icePixels: PLongwordArray;
+    pictureX, pictureY: LongInt;
+    w, c: LongWord;
+    weight: Longint;
+begin
+    weight := getPixelWeight(x, y);
+    if isLandscape(weight) then
+        begin
+        // So. 3 parameters here. Ice colour, Ice opacity, and a bias on the greyscaled pixel towards lightness
+        iceSurface:= SpritesData[sprIceTexture].Surface;
+        pictureX := x mod iceSurface^.w;
+        pictureY := y mod iceSurface^.h;
+        icePixels := iceSurface^.pixels;
+        w:= LandPixels[y, x];
+        w:= round(((w shr RShift and $FF) * RGB_LUMINANCE_RED +
+              (w shr BShift and $FF) * RGB_LUMINANCE_GREEN +
+              (w shr GShift and $FF) * RGB_LUMINANCE_BLUE));
+        if w < 128 then w:= w+128;
+        if w > 255 then w:= 255;
+        w:= (w shl RShift) or (w shl BShift) or (w shl GShift) or (LandPixels[y,x] and AMask);
+        //LandPixels[y, x]:= w;
+        LandPixels[y, x]:= addBgColor(w, IceColor);
+        LandPixels[y, x]:= addBgColor(LandPixels[y, x], icePixels^[iceSurface^.w * (y mod iceSurface^.h) + (x mod iceSurface^.w)]);
+        Land[y, x] := land[y, x] or lfIce;
+        end
+    else if (isLandscapeEdge(weight)) then
+        begin
+        LandPixels[y, x] := $FFB2AF8A;
+        if Land[y, x] > 255 then Land[y, x] := Land[y, x] or lfIce;
+        end;
+
+end;
+
+function getIncrementInquarter(dx, dy, quarter: Longint): Longint;
+const directionX : array [0..3] of Longint = (0, 0, 1, -1);
+const directionY : array [0..3] of Longint = (1, -1, 0, 0);
+begin
+    getIncrementInquarter := directionX[quarter] * dx + directionY[quarter] * dy;
+end;
+
+function getIncrementInquarter2(dx, dy, quarter: Longint): Longint;
+const directionY : array [0..3] of Longint = (0, 0, 1, 1);
+const directionX : array [0..3] of Longint = (1, 1, 0, 0);
+begin
+    getIncrementInquarter2 := directionX[quarter] * dx + directionY[quarter] * dy;
+end;
+
+procedure FillLandCircleLinesIce(x, y, dx, dy: LongInt);
+var q, i, t: LongInt;
+begin
+for q := 0 to 3 do
+    begin
+        t:= y + getIncrementInquarter(dx, dy, q);
+        if (t and LAND_HEIGHT_MASK) = 0 then
+            for i:= Max(x - getIncrementInquarter2(dx, dy, q), 0) to Min(x + getIncrementInquarter2(dx, dy, q), LAND_WIDTH - 1) do
+                if (Land[t, i] and (lfIndestructible or lfIce) = 0) and (not disableLandBack or (Land[t, i] > 255))  then
+                    if (cReducedQuality and rqBlurryLand) = 0 then
+                       drawIcePixel(t, i)
+                    else
+                       drawIcePixel(t div 2, i div 2) ;
+    end;
+end;
+
+procedure FillRoundInLandWithIce(X, Y, Radius: LongInt);
+var dx, dy, d: LongInt;
+begin
+dx:= 0;
+dy:= Radius;
+d:= 3 - 2 * Radius;
+    while (dx < dy) do
+        begin
+        FillLandCircleLinesIce(x, y, dx, dy);
+        if (d < 0) then
+            d:= d + 4 * dx + 6
+        else
+            begin
+            d:= d + 4 * (dx - dy) + 10;
+            dec(dy)
+            end;
+        inc(dx)
+        end;
+    if (dx = dy) then
+        FillLandCircleLinesIce(x, y, dx, dy);
+end;
+
+
 function FillLandCircleLinesBG(x, y, dx, dy: LongInt): Longword;
 var i, t, by, bx: LongInt;
     cnt: Longword;
@@ -350,7 +477,7 @@
             else
                 LandPixels[t div 2, i div 2]:= ExplosionBorderColor;
 
-            Land[t, i]:= Land[t, i] or lfDamaged;
+            Land[t, i]:= (Land[t, i] or lfDamaged) and not lfIce;
             //Despeckle(i, t);
             LandDirty[t div 32, i div 32]:= 1;
             end;
@@ -364,7 +491,7 @@
                 LandPixels[t, i]:= ExplosionBorderColor
             else
                 LandPixels[t div 2, i div 2]:= ExplosionBorderColor;
-            Land[t, i]:= Land[t, i] or lfDamaged;
+            Land[t, i]:= (Land[t, i] or lfDamaged) and not lfIce;
             //Despeckle(i, t);
             LandDirty[t div 32, i div 32]:= 1;
             end;
@@ -379,7 +506,7 @@
             else
                LandPixels[t div 2, i div 2]:= ExplosionBorderColor;
 
-            Land[t, i]:= Land[t, i] or lfDamaged;
+            Land[t, i]:= (Land[t, i] or lfDamaged) and not lfIce;
             //Despeckle(i, t);
             LandDirty[t div 32, i div 32]:= 1;
             end;
@@ -394,7 +521,7 @@
             else
                 LandPixels[t div 2, i div 2]:= ExplosionBorderColor;
 
-            Land[t, i]:= Land[t, i] or lfDamaged;
+            Land[t, i]:= (Land[t, i] or lfDamaged) and not lfIce;
             //Despeckle(i, y - dy);
             LandDirty[t div 32, i div 32]:= 1;
             end;
@@ -525,7 +652,7 @@
                 else
                     LandPixels[ty div 2, tx div 2]:= ExplosionBorderColor;
 
-                Land[ty, tx]:= Land[ty, tx] or lfDamaged;
+                Land[ty, tx]:= (Land[ty, tx] or lfDamaged) and not lfIce;
                 LandDirty[ty div 32, tx div 32]:= 1;
                 end;
     inc(y, dY)
@@ -567,6 +694,7 @@
     and ((tx and LAND_WIDTH_MASK) = 0)
     and (((Land[ty, tx] and lfBasic) <> 0) or ((Land[ty, tx] and lfObject) <> 0)) then
         begin
+        Land[ty, tx]:= Land[ty, tx] and not lfIce;
         if despeckle then
             begin
             Land[ty, tx]:= Land[ty, tx] or lfDamaged;
@@ -595,7 +723,7 @@
         if ((ty and LAND_HEIGHT_MASK) = 0) and ((tx and LAND_WIDTH_MASK) = 0) and (((Land[ty, tx] and lfBasic) <> 0)
         or ((Land[ty, tx] and lfObject) <> 0)) then
             begin
-            Land[ty, tx]:= Land[ty, tx] or lfDamaged;
+            Land[ty, tx]:= (Land[ty, tx] or lfDamaged) and not lfIce;
             if despeckle then
                 LandDirty[ty div 32, tx div 32]:= 1;
             if (cReducedQuality and rqBlurryLand) = 0 then
@@ -638,7 +766,7 @@
     if ((ty and LAND_HEIGHT_MASK) = 0) and ((tx and LAND_WIDTH_MASK) = 0) and (((Land[ty, tx] and lfBasic) <> 0)
     or ((Land[ty, tx] and lfObject) <> 0)) then
         begin
-        Land[ty, tx]:= Land[ty, tx] or lfDamaged;
+        Land[ty, tx]:=( Land[ty, tx] or lfDamaged) and not lfIce;
         if despeckle then
             LandDirty[ty div 32, tx div 32]:= 1;
         if (cReducedQuality and rqBlurryLand) = 0 then
@@ -664,7 +792,7 @@
     if ((ty and LAND_HEIGHT_MASK) = 0) and ((tx and LAND_WIDTH_MASK) = 0) and (((Land[ty, tx] and lfBasic) <> 0)
     or ((Land[ty, tx] and lfObject) <> 0)) then
         begin
-        Land[ty, tx]:= Land[ty, tx] or lfDamaged;
+        Land[ty, tx]:= (Land[ty, tx] or lfDamaged) and not lfIce;
         if despeckle then
             LandDirty[ty div 32, tx div 32]:= 1;
         if (cReducedQuality and rqBlurryLand) = 0 then
--- a/hedgewars/uRender.pas	Mon Feb 25 11:37:48 2013 +0400
+++ b/hedgewars/uRender.pas	Tue Feb 26 20:39:18 2013 -0500
@@ -26,15 +26,16 @@
 
 procedure DrawSprite            (Sprite: TSprite; X, Y, Frame: LongInt);
 procedure DrawSprite            (Sprite: TSprite; X, Y, FrameX, FrameY: LongInt);
-procedure DrawSpriteFromRect    (Sprite: TSprite; r: TSDL_Rect; X, Y, Height, Position: LongInt);
+procedure DrawSpriteFromRect    (Sprite: TSprite; r: TSDL_Rect; X, Y, Height, Position: LongInt); inline;
 procedure DrawSpriteClipped     (Sprite: TSprite; X, Y, TopY, RightX, BottomY, LeftX: LongInt);
 procedure DrawSpriteRotated     (Sprite: TSprite; X, Y, Dir: LongInt; Angle: real);
 procedure DrawSpriteRotatedF    (Sprite: TSprite; X, Y, Frame, Dir: LongInt; Angle: real);
 
 procedure DrawTexture           (X, Y: LongInt; Texture: PTexture); inline;
 procedure DrawTexture           (X, Y: LongInt; Texture: PTexture; Scale: GLfloat);
-procedure DrawTextureFromRect   (X, Y: LongInt; r: PSDL_Rect; SourceTexture: PTexture);
-procedure DrawTextureFromRect   (X, Y, W, H: LongInt; r: PSDL_Rect; SourceTexture: PTexture);
+procedure DrawTextureFromRect   (X, Y: LongInt; r: PSDL_Rect; SourceTexture: PTexture); inline;
+procedure DrawTextureFromRect   (X, Y, W, H: LongInt; r: PSDL_Rect; SourceTexture: PTexture); inline;
+procedure DrawTextureFromRectDir(X, Y, W, H: LongInt; r: PSDL_Rect; SourceTexture: PTexture; Dir: LongInt);
 procedure DrawTextureCentered   (X, Top: LongInt; Source: PTexture);
 procedure DrawTextureF          (Texture: PTexture; Scale: GLfloat; X, Y, Frame, Dir, w, h: LongInt);
 procedure DrawTextureRotated    (Texture: PTexture; hw, hh, X, Y, Dir: LongInt; Angle: real);
@@ -63,19 +64,23 @@
 
 var LastTint: LongWord = 0;
 
-procedure DrawSpriteFromRect(Sprite: TSprite; r: TSDL_Rect; X, Y, Height, Position: LongInt);
+procedure DrawSpriteFromRect(Sprite: TSprite; r: TSDL_Rect; X, Y, Height, Position: LongInt); inline;
 begin
 r.y:= r.y + Height * Position;
 r.h:= Height;
 DrawTextureFromRect(X, Y, @r, SpritesData[Sprite].Texture)
 end;
 
-procedure DrawTextureFromRect(X, Y: LongInt; r: PSDL_Rect; SourceTexture: PTexture);
+procedure DrawTextureFromRect(X, Y: LongInt; r: PSDL_Rect; SourceTexture: PTexture); inline;
 begin
-DrawTextureFromRect(X, Y, r^.w, r^.h, r, SourceTexture)
+DrawTextureFromRectDir(X, Y, r^.w, r^.h, r, SourceTexture, 1)
+end;
+procedure DrawTextureFromRect(X, Y, W, H: LongInt; r: PSDL_Rect; SourceTexture: PTexture); inline;
+begin
+DrawTextureFromRectDir(X, Y, W, H, r, SourceTexture, 1)
 end;
 
-procedure DrawTextureFromRect(X, Y, W, H: LongInt; r: PSDL_Rect; SourceTexture: PTexture);
+procedure DrawTextureFromRectDir(X, Y, W, H: LongInt; r: PSDL_Rect; SourceTexture: PTexture; Dir: LongInt);
 var rr: TSDL_Rect;
     _l, _r, _t, _b: real;
     VertexBuffer, TextureBuffer: array [0..3] of TVertex2f;
@@ -101,14 +106,28 @@
 
 glBindTexture(GL_TEXTURE_2D, SourceTexture^.id);
 
-VertexBuffer[0].X:= X;
-VertexBuffer[0].Y:= Y;
-VertexBuffer[1].X:= rr.w + X;
-VertexBuffer[1].Y:= Y;
-VertexBuffer[2].X:= rr.w + X;
-VertexBuffer[2].Y:= rr.h + Y;
-VertexBuffer[3].X:= X;
-VertexBuffer[3].Y:= rr.h + Y;
+if Dir < 0 then
+    begin
+    VertexBuffer[0].X:= X + rr.w/2;
+    VertexBuffer[0].Y:= Y;
+    VertexBuffer[1].X:= X - rr.w/2;
+    VertexBuffer[1].Y:= Y;
+    VertexBuffer[2].X:= X - rr.w/2;
+    VertexBuffer[2].Y:= rr.h + Y;
+    VertexBuffer[3].X:= X + rr.w/2;
+    VertexBuffer[3].Y:= rr.h + Y;
+    end
+else
+    begin
+    VertexBuffer[0].X:= X;
+    VertexBuffer[0].Y:= Y;
+    VertexBuffer[1].X:= rr.w + X;
+    VertexBuffer[1].Y:= Y;
+    VertexBuffer[2].X:= rr.w + X;
+    VertexBuffer[2].Y:= rr.h + Y;
+    VertexBuffer[3].X:= X;
+    VertexBuffer[3].Y:= rr.h + Y;
+    end;
 
 TextureBuffer[0].X:= _l;
 TextureBuffer[0].Y:= _t;
--- a/hedgewars/uTeams.pas	Mon Feb 25 11:37:48 2013 +0400
+++ b/hedgewars/uTeams.pas	Tue Feb 26 20:39:18 2013 -0500
@@ -188,11 +188,11 @@
                 PrevHH:= CurrHedgehog mod HedgehogsNumber; // prevent infinite loop when CurrHedgehog = 7, but HedgehogsNumber < 8 (team is destroyed before its first turn)
                 repeat
                     CurrHedgehog:= Succ(CurrHedgehog) mod HedgehogsNumber;
-                until (Hedgehogs[CurrHedgehog].Gear <> nil) or (CurrHedgehog = PrevHH)
+                until ((Hedgehogs[CurrHedgehog].Gear <> nil) and (Hedgehogs[CurrHedgehog].Effects[heFrozen] = 0)) or (CurrHedgehog = PrevHH)
                 end
         until (CurrentTeam^.Hedgehogs[CurrentTeam^.CurrHedgehog].Gear <> nil) or (PrevTeam = CurrTeam) or ((CurrTeam = TagTeamIndex) and ((GameFlags and gfTagTeam) <> 0));
         end
-until (CurrentTeam^.Hedgehogs[CurrentTeam^.CurrHedgehog].Gear <> nil);
+until (CurrentTeam^.Hedgehogs[CurrentTeam^.CurrHedgehog].Gear <> nil) and (CurrentTeam^.Hedgehogs[CurrentTeam^.CurrHedgehog].Effects[heFrozen] = 0);
 
 SwitchCurrentHedgehog(@(CurrentTeam^.Hedgehogs[CurrentTeam^.CurrHedgehog]));
 {$IFDEF USE_TOUCH_INTERFACE}
--- a/hedgewars/uTypes.pas	Mon Feb 25 11:37:48 2013 +0400
+++ b/hedgewars/uTypes.pas	Tue Feb 26 20:39:18 2013 -0500
@@ -86,7 +86,7 @@
             sprHandResurrector, sprCross, sprAirDrill, sprNapalmBomb,
             sprBulletHit, sprSnowball, sprHandSnowball, sprSnow,
             sprSDFlake, sprSDWater, sprSDCloud, sprSDSplash, sprSDDroplet, sprTardis,
-            sprSlider, sprBotlevels, sprHandKnife, sprKnife, sprStar
+            sprSlider, sprBotlevels, sprHandKnife, sprKnife, sprStar, sprIceTexture, sprIceGun, sprFrozenHog
             );
 
     // Gears that interact with other Gears and/or Land
@@ -259,6 +259,8 @@
             SoundChannel: LongInt;
             PortalCounter: LongWord;  // Hopefully temporary, but avoids infinite portal loops in a guaranteed fashion.
             AIHints: LongWord; // hints for ai. haha ^^^^^^ temporary, sure
+            IceTime: Longint; //time of ice beam with object some interaction  temporary
+            IceState: Longint; //state of ice gun temporary
             LastDamage: PHedgehog;
             end;
     TPGearArray = array of PGear;
--- a/hedgewars/uVariables.pas	Mon Feb 25 11:37:48 2013 +0400
+++ b/hedgewars/uVariables.pas	Tue Feb 26 20:39:18 2013 -0500
@@ -115,6 +115,7 @@
 
     // originally typed consts
     ExplosionBorderColor: LongWord;
+    IceColor            : LongWord;
     WaterOpacity: byte;
     SDWaterOpacity: byte;
     GrayScale: Boolean;
@@ -654,16 +655,18 @@
             Width: 3; Height: 17; imageWidth: 3; imageHeight: 17; saveSurf: false; priority: tpLow; getDimensions: false; getImageDimensions: false), // sprSlider
             (FileName:  'botlevels'; Path: ptGraphics; AltPath: ptNone; Texture: nil; Surface: nil;
             Width: 22; Height: 15; imageWidth: 22; imageHeight: 15; saveSurf: true; priority: tpLow; getDimensions: false; getImageDimensions: false), // sprBotlevels
-         (*   (FileName:  'amKnife'; Path: ptHedgehog; AltPath: ptNone; Texture: nil; Surface: nil;
-            Width:  64; Height: 64; imageWidth: 0; imageHeight: 0; saveSurf: false; priority: tpMedium; getDimensions: false; getImageDimensions: true),// sprHandKnife*)
             (FileName:  'amCleaver'; Path: ptHedgehog; AltPath: ptNone; Texture: nil; Surface: nil;
             Width:  64; Height: 64; imageWidth: 64; imageHeight: 64; saveSurf: false; priority: tpMedium; getDimensions: false; getImageDimensions: false),// sprHandKnife
-            (*(FileName:  'knife'; Path: ptGraphics; AltPath: ptNone; Texture: nil; Surface: nil;
-            Width: 29; Height: 14; imageWidth: 64; imageHeight: 64; saveSurf: true; priority: tpLow; getDimensions: false; getImageDimensions: false) // sprKnife*)
             (FileName:  'cleaver'; Path: ptGraphics; AltPath: ptNone; Texture: nil; Surface: nil;
             Width: 64; Height: 64; imageWidth: 64; imageHeight: 128; saveSurf: false; priority: tpLow; getDimensions: false; getImageDimensions: false), // sprKnife
             (FileName:  'star'; Path: ptGraphics; AltPath: ptNone; Texture: nil; Surface: nil;
-            Width: 12; Height: 12; imageWidth: 12; imageHeight: 12; saveSurf: false; priority: tpLow; getDimensions: false; getImageDimensions: false) // sprStar
+            Width: 12; Height: 12; imageWidth: 12; imageHeight: 12; saveSurf: false; priority: tpLow; getDimensions: false; getImageDimensions: false), // sprStar
+            (FileName:  'icetexture'; Path: ptGraphics; AltPath: ptNone; Texture: nil; Surface: nil;
+            Width: 128; Height: 128; imageWidth: 128; imageHeight: 128; saveSurf: true; priority: tpLow; getDimensions: false; getImageDimensions: true), // sprIceTexture
+            (FileName:  'amIceGun'; Path: ptHedgehog; AltPath: ptNone; Texture: nil; Surface: nil;
+            Width: 32; Height: 32; imageWidth: 32; imageHeight: 32; saveSurf: false; priority: tpLow; getDimensions: false; getImageDimensions: false), // sprIceGun
+            (FileName:  'amFrozenHog'; Path: ptHedgehog; AltPath: ptNone; Texture: nil; Surface: nil;
+            Width: 64; Height: 64; imageWidth: 64; imageHeight: 64; saveSurf: false; priority: tpLow; getDimensions: false; getImageDimensions: false) // sprFrozenHog
             );
 
 const
@@ -2407,6 +2410,7 @@
     SDWaterOpacity:= $80;
     SDTint:= $80;
     ExplosionBorderColor:= $FF808080;
+    IceColor:= ($44 shl RShift) or ($97 shl GShift) or ($A9 shl BShift) or ($A0 shl AShift);
     WaterOpacity:= $80;
 
     cDrownSpeed.QWordValue  := 257698038;       // 0.06
Binary file share/hedgewars/Data/Graphics/Hedgehog.png has changed
Binary file share/hedgewars/Data/Graphics/Hedgehog/amFrozenHog.png has changed
Binary file share/hedgewars/Data/Graphics/Hedgehog/amIceGun.png has changed
Binary file share/hedgewars/Data/Graphics/icetexture.png has changed