Rewrote the Ammomenu:
authorXeli
Sat, 04 Feb 2012 16:22:46 +0100
changeset 6622 01889d5bc79b
parent 6621 cc94940fe438
child 6623 6bf169f1e97c
Rewrote the Ammomenu: Added landscape ammomenu At the moment MOBILE indicates landscape, but we could just as easily make a variable out of it Draw to texture once uVariables.AmmoMenuInvalidated indicates a new ammo menu needs to be drawn, see uTeams and uAmmos Slot/Cellsize is dependent on uConsts.AMSlotSize this should make it easier to scale the ammo menu on smaller screens AmmoRect AmmoRect indicates where and how big the ammo menu is, this makes positioning a bit easier imo, because you only need to change the position at one single point needs testing on the iphone (and other systems as well ofcourse..)
hedgewars/uAmmos.pas
hedgewars/uConsts.pas
hedgewars/uTeams.pas
hedgewars/uVariables.pas
hedgewars/uWorld.pas
--- a/hedgewars/uAmmos.pas	Sat Feb 04 16:17:31 2012 +0100
+++ b/hedgewars/uAmmos.pas	Sat Feb 04 16:22:46 2012 +0100
@@ -380,6 +380,7 @@
             end;
         end
     end;
+AmmoMenuInvalidated:= true;
 end;
 
 procedure SwitchNotHeldAmmo(var Hedgehog: THedgehog);
--- a/hedgewars/uConsts.pas	Sat Feb 04 16:17:31 2012 +0100
+++ b/hedgewars/uConsts.pas	Sat Feb 04 16:22:46 2012 +0100
@@ -289,8 +289,13 @@
     htHealth      = $04;
     htTransparent = $08;
 
+{$IFDEF MOBILE}
+    AMSlotSize = 48;
+    AMTITLE = 30;
+{$ELSE}
     AMSlotSize = 33;
-
+{$ENDIF}
+    AMSlotPadding = (AMSlotSize - 32) shr 1;
 implementation
 
 end.
--- a/hedgewars/uTeams.pas	Sat Feb 04 16:17:31 2012 +0100
+++ b/hedgewars/uTeams.pas	Sat Feb 04 16:22:46 2012 +0100
@@ -183,6 +183,8 @@
 until (CurrentTeam^.Hedgehogs[CurrentTeam^.CurrHedgehog].Gear <> nil);
 
 CurrentHedgehog:= @(CurrentTeam^.Hedgehogs[CurrentTeam^.CurrHedgehog]);
+
+AmmoMenuInvalidated:= true;
 end;
 
 procedure AfterSwitchHedgehog;
--- a/hedgewars/uVariables.pas	Sat Feb 04 16:17:31 2012 +0100
+++ b/hedgewars/uVariables.pas	Sat Feb 04 16:22:46 2012 +0100
@@ -153,8 +153,11 @@
     cVampiric       : boolean;
     cArtillery      : boolean;
     WeaponTooltipTex: PTexture;
+    AmmoMenuTex     : PTexture;
+    AmmoMenuInvalidated: boolean;
     HHTexture       : PTexture;
 
+
     flagMakeCapture : boolean;
 
     InitStepsFlags  : Longword;
@@ -332,15 +335,15 @@
             (FileName:       'SkyR'; Path: ptCurrTheme;AltPath: ptNone; Texture: nil; Surface: nil;
             Width:   0; Height:  0; imageWidth: 0; imageHeight: 0; saveSurf: false; priority: tpHigh; getDimensions: true; getImageDimensions: true),// sprSky
             (FileName:  'BorderHorizontal'; Path: ptAmmoMenu; AltPath: ptNone; Texture: nil; Surface: nil;
-            Width: AMSlotSize; Height:  2; imageWidth: 0; imageHeight: 0; saveSurf: true; priority: tpLow; getDimensions: false; getImageDimensions: true),// sprAMBorderHorizontal
+            Width: 32; Height:  2; imageWidth: 0; imageHeight: 0; saveSurf: true; priority: tpLow; getDimensions: false; getImageDimensions: true),// sprAMBorderHorizontal
             (FileName:  'BorderVertical'; Path: ptAmmoMenu; AltPath: ptNone; Texture: nil; Surface: nil;
-            Width: 2; Height: AMSlotSize; imageWidth: 0; imageHeight: 0; saveSurf: true; priority: tpLow; getDimensions: false; getImageDimensions: true),// sprAMBorderVertical
+            Width: 2; Height: 32; imageWidth: 0; imageHeight: 0; saveSurf: true; priority: tpLow; getDimensions: false; getImageDimensions: true),// sprAMBorderVertical
             (FileName:   'Slot'; Path: ptAmmoMenu; AltPath: ptNone; Texture: nil; Surface: nil;
-            Width: AMSlotSize; Height: AMSlotSize; imageWidth: 0; imageHeight: 0; saveSurf: true; priority: tpMedium; getDimensions: false; getImageDimensions: true),// sprAMSlot
+            Width: 32; Height: 32; imageWidth: 0; imageHeight: 0; saveSurf: true; priority: tpMedium; getDimensions: false; getImageDimensions: true),// sprAMSlot
             (FileName:      'Ammos'; Path: ptAmmoMenu; AltPath: ptNone; Texture: nil; Surface: nil;
             Width:  32; Height: 32; imageWidth: 0; imageHeight: 0; saveSurf: true; priority: tpMedium; getDimensions: false; getImageDimensions: true),// sprAMAmmos
             (FileName:   'Ammos_bw'; Path: ptAmmoMenu; AltPath: ptNone; Texture: nil; Surface: nil;
-            Width:  32; Height: 32; imageWidth: 0; imageHeight: 0; saveSurf: false; priority: tpHigh; getDimensions: false; getImageDimensions: true),// sprAMAmmosBW
+            Width:  32; Height: 32; imageWidth: 0; imageHeight: 0; saveSurf: true; priority: tpHigh; getDimensions: false; getImageDimensions: true),// sprAMAmmosBW
             (FileName:   'SlotKeys'; Path: ptAmmoMenu; AltPath: ptNone; Texture: nil; Surface: nil;
             Width:  32; Height: 32; imageWidth: 0; imageHeight: 0; saveSurf: false; priority: tpMedium; getDimensions: false; getImageDimensions: true),// sprAMSlotKeys
             (FileName:  'Corners'; Path: ptAmmoMenu; AltPath: ptNone; Texture: nil; Surface: nil;
@@ -408,7 +411,7 @@
             (FileName:     'Mortar'; Path: ptGraphics; AltPath: ptNone; Texture: nil; Surface: nil;
             Width:  16; Height: 16; imageWidth: 0; imageHeight: 0; saveSurf: false; priority: tpMedium; getDimensions: false; getImageDimensions: true),// sprMortar
             (FileName:  'TurnsLeft'; Path: ptAmmoMenu; AltPath: ptNone; Texture: nil; Surface: nil;
-            Width:  16; Height: 16; imageWidth: 0; imageHeight: 0; saveSurf: false; priority: tpMedium; getDimensions: false; getImageDimensions: true),// sprTurnsLeft
+            Width:  16; Height: 16; imageWidth: 0; imageHeight: 0; saveSurf: true; priority: tpMedium; getDimensions: false; getImageDimensions: true),// sprTurnsLeft
             (FileName: 'amKamikaze'; Path: ptHedgehog; AltPath: ptNone; Texture: nil; Surface: nil;
             Width: 128; Height: 32; imageWidth: 0; imageHeight: 0; saveSurf: false; priority: tpMedium; getDimensions: false; getImageDimensions: true),// sprKamikaze
             (FileName:     'amWhip'; Path: ptHedgehog; AltPath: ptNone; Texture: nil; Surface: nil;
--- a/hedgewars/uWorld.pas	Sat Feb 04 16:17:31 2012 +0100
+++ b/hedgewars/uWorld.pas	Sat Feb 04 16:22:46 2012 +0100
@@ -21,7 +21,7 @@
 
 unit uWorld;
 interface
-uses SDLh, uGears, uConsts, uFloat, uRandom, uTypes;
+uses SDLh, uGears, uConsts, uFloat, uRandom, uTypes, uRenderUtils;
 
 procedure initModule;
 procedure freeModule;
@@ -61,10 +61,12 @@
     ;
 
 var cWaveWidth, cWaveHeight: LongInt;
-    AMxOffset, AMyOffset, AMShiftTarget, AMShift, SlotsNum: LongInt;
+    AMShiftTargetX, AMShiftTargetY, AMShiftX, AMShiftY, SlotsNum: LongInt;
     tmpSurface: PSDL_Surface;
     fpsTexture: PTexture;
     timeTexture: PTexture;
+    AmmoRect: TSDL_Rect;
+    MenuSpeedX, MenuSpeedY: LongInt;
     FPS: Longword;
     CountTicks: Longword;
     SoundTimerTicks: Longword;
@@ -196,20 +198,6 @@
 SkyOffset:= 0;
 HorizontOffset:= 0;
 
-{$IFDEF MOBILE}
-AMxOffset:= 0;
-if isPhone() then
-    AMyOffset:= AMSlotSize
-else
-    AMyOffset:= AMSlotSize * 2;
-AMShiftTarget:= (cMaxSlotAmmoIndex + 2) * AMSlotSize + AMyOffset;
-{$ELSE}
-AMxOffset:= 10;
-AMyOffset:= 60;
-AMShiftTarget:= (cMaxSlotAmmoIndex + 2) * AMSlotSize + AMxOffset;
-{$ENDIF}
-
-AMShift:= AMShiftTarget;
 end;
 
 procedure InitCameraBorders;
@@ -228,202 +216,270 @@
     missionTex:= nil;
 end;
 
-procedure ShowAmmoMenu;
-const MENUSPEED = 15;
+function GetAmmoMenuTexture(Ammo: PHHAmmo): PTexture;
 const BORDERSIZE = 2;
-var x, y, i, t, g: LongInt;
-    Slot, Pos, STurns: LongInt;
-    Ammo: PHHAmmo;
+var x, y, i, t, SlotsNumY, SlotsNumX, AMFrame: LongInt;
+    STurns: LongInt;
+    amSurface: PSDL_Surface;
+    AMRect: TSDL_Rect;
 begin
-    if (TurnTimeLeft = 0) or (not CurrentTeam^.ExtDriven and (((CurAmmoGear = nil)
-    or ((Ammoz[CurAmmoGear^.AmmoType].Ammo.Propz and ammoprop_AltAttack) = 0)) and hideAmmoMenu)) then
-        bShowAmmoMenu:= false;
-
-    if bShowAmmoMenu then
-    // show ammo menu
-        begin
-        FollowGear:= nil;
-        if AMShift = AMShiftTarget then
-{$IFDEF MOBILE}
-            prevPoint.Y:= 0;
-{$ELSE}
-            prevPoint.X:= 0;
-{$ENDIF}
-        if (cReducedQuality and rqSlowMenu) <> 0 then
-            AMShift:= 0
-        else
-            if AMShift > MENUSPEED then
-                dec(AMShift, MENUSPEED)
-            else
-                AMShift:= 0;
-        end
-    else
-    // hide ammo menu
-        begin
-        if AMShift = 0 then
-            begin
-            CursorPoint.X:= cScreenWidth shr 1;
-            CursorPoint.Y:= cScreenHeight shr 1;
-            prevPoint:= CursorPoint;
-            end;
-        if (cReducedQuality and rqSlowMenu) <> 0 then
-            AMShift:= AMShiftTarget+2
-        else
-            if AMShift < (AMShiftTarget - MENUSPEED) then
-                inc(AMShift, MENUSPEED)
-            else
-                AMShift:= AMShiftTarget;
-        end;
-
-    // give the assigned ammo to hedgehog
-    Ammo:= nil;
-    if (CurrentTeam <> nil) and (CurrentHedgehog <> nil)
-    and (not CurrentTeam^.ExtDriven) and (CurrentHedgehog^.BotLevel = 0) then
-        Ammo:= CurrentHedgehog^.Ammo
-    else if (LocalAmmo <> -1) then
-        Ammo:= GetAmmoByNum(LocalAmmo);
-    Pos:= -1;
-    if Ammo = nil then
-        begin
-        bShowAmmoMenu:= false;
-        exit
-        end;
     SlotsNum:= 0;
-
-{$IFDEF MOBILE}
-    Slot:= cMaxSlotIndex;
-
     for i:= 0 to cMaxSlotIndex do
         if((i = 0) and (Ammo^[i,1].Count > 0)) or ((i <> 0) and (Ammo^[i,0].Count > 0)) then
             inc(SlotsNum);
+{$IFDEF MOBILE}
+    SlotsNumX:= SlotsNum;
+    SlotsNumY:= cMaxSlotAmmoIndex + 2;
+{$ELSE}
+    SlotsNumX:= cMaxSlotAmmoIndex + 1;
+    SlotsNumY:= SlotsNum + 1;
+{$ENDIF}
 
-    x:= AMxOffset - ((SlotsNum * AMSlotSize) shr 1);
-    y:= cScreenHeight - AMShiftTarget + AMShift;
-    dec(x, BORDERSIZE);
-    DrawSprite(sprAMCorners, x, y - BORDERSIZE, 0);//top left corner
-    for i:= 0 to cMaxSlotAmmoIndex +1 do
-        DrawSprite(sprAMBorderVertical, x, y + i * AMSlotSize, 0);
-    DrawSprite(sprAMCorners, x, y + ((cMaxSlotAmmoIndex+2) * AMSlotSize) , 2);//bottom left corner
-    inc(x, BORDERSIZE);
+    ammoRect.w:= (BORDERSIZE*2) + (SlotsNumX * AMSlotSize) + (SlotsNumX-1);
+    ammoRect.h:= (BORDERSIZE*2) + (SlotsNumY * AMSlotSize) + (SlotsNumY-1);
+    amSurface := SDL_CreateRGBSurface(SDL_SWSURFACE, ammoRect.w, ammoRect.h, 32, RMask, GMask, BMask, AMask);
+    
+    AMRect.x:= BORDERSIZE;
+    AMRect.y:= BORDERSIZE;
+    AMRect.w:= ammoRect.w - (BORDERSIZE*2);
+    AMRect.h:= ammoRect.h - (BORDERSIZE*2);
 
-    for i:= 0 to SlotsNum -2 do
-        DrawSprite(sprAMSlot, x + i * AMSlotSize, y, 2);
-    DrawSprite(sprAMSlot, x + (SlotsNum-1) * AMSlotSize, y, 1);
+    SDL_FillRect(amSurface, @AMRect, SDL_MapRGB(amSurface^.format, 0,0,0));
 
-    inc(y, AMSlotSize);
+    
+    x:= 0;
+    y:= 0;
     for i:= 0 to cMaxSlotIndex do
         if ((i = 0) and (Ammo^[i, 1].Count > 0)) or ((i <> 0) and (Ammo^[i, 0].Count > 0)) then
             begin
-            if (CursorPoint.X >= x) and (CursorPoint.X <= x + AMSlotSize) then
-                Slot:= i;
-            DrawSprite(sprAMBorderHorizontal, x, y - BORDERSIZE - AMSlotSize, 0);
-            g:= 0;
-            
+{$IFDEF MOBILE}
+            y:= 0;
+{$ELSE}
+            x:= 0;
+{$ENDIF}
             for t:=0 to cMaxSlotAmmoIndex do
                 begin
-                DrawSprite(sprAMSlot, x, y + t * AMSlotSize, 1);
-                if (Ammo^[i, t].Count > 0) then
+                if (Ammo^[i, t].Count > 0)  and (Ammo^[i, t].AmmoType <> amNothing) then
                     begin
-                    if (Ammo^[i, t].AmmoType <> amNothing) then
+                    STurns:= Ammoz[Ammo^[i, t].AmmoType].SkipTurns - CurrentTeam^.Clan^.TurnNumber;
+                    AMFrame:= LongInt(Ammo^[i,t].AmmoType) - 1;
+                    if STurns >= 0 then //weapon not usable yet, draw grayed out with turns remaining
                         begin
-                        STurns:= Ammoz[Ammo^[i, t].AmmoType].SkipTurns - CurrentTeam^.Clan^.TurnNumber;
-
-                        if STurns >= 0 then //weapon not usable yet, draw grayed out with turns remaining
-                            begin
-                            DrawSprite(sprAMAmmosBW, x, y + (g * AMSlotSize) + 1, LongInt(Ammo^[i, t].AmmoType)-1);
-                            if STurns < 100 then
-                                DrawSprite(sprTurnsLeft, x + AMSlotSize-16, y + (g + 1) * AMSlotSize-16, STurns);
-                            end
-                        else //draw colored version
-                            DrawSprite(sprAMAmmos, x, y + (g * AMSlotSize) + 1, LongInt(Ammo^[i, t].AmmoType)-1);
-                        if (Slot = i) and (CursorPoint.Y <= (cScreenHeight - y) - (g * AMSlotSize)) and
-                           (CursorPoint.Y >= (cScreenHeight - y) - ((g+1) * AMSlotSize)) then
-                            begin
-                            if (STurns < 0) then
-                                DrawSprite(sprAMSlot, x, y + (g * AMSlotSize), 0);
-                            Pos:= t;
-                            end;
-                        inc(g);
+                        DrawSprite2Surf(sprAMAmmosBW, amSurface, x + AMSlotPadding, 
+                                                                 y + AMSlotPadding + 1, AMFrame);
+                        if STurns < 100 then
+                            DrawSprite2Surf(sprTurnsLeft, amSurface, 
+			    	    x + AMSlotSize-16, 
+				    y + AMSlotSize + 1 - 16, STurns);
+                        end
+                    else //draw colored version
+                        begin
+                            DrawSprite2Surf(sprAMAmmos, amSurface, x + AMSlotPadding, 
+       						       y + AMSlotPadding + 1, AMFrame);
                         end;
-                    end;
-                end;
-            DrawSprite(sprAMBorderHorizontal, x, y + ((cMaxSlotAmmoIndex+1) * AMSlotSize), 1);
-            inc(x, AMSlotSize);
-            end;
-
-    DrawSprite(sprAMCorners, x, y + ((cMaxSlotAmmoIndex+1) * AMSlotSize), 3); //bottom right corner
-    DrawSprite(sprAMCorners, x - BORDERSIZE, y + (AMSlotSize * cMaxSlotAmmoIndex), 1);//top right  corner
-
-    dec(y, AMSlotSize);
-    for i:= 0 to cMaxSlotAmmoIndex + 1 do
-        DrawSprite(sprAMBorderVertical, x,y + i * AMSlotSize, 1);
-    inc(y, AMSlotSize);
+{$IFDEF MOBILE}
+	    inc(y, AMSlotSize + 1); //the plus one is for the border
+{$ELSE}
+	    inc(x, AMSlotSize + 1);
+{$ENDIF}
+	    end;
+	end;
+{$IFDEF MOBILE}
+    inc(x, AMSlotSize + 1);
 {$ELSE}
-    Slot:= 0;
-    x:= (cScreenWidth shr 1) - AMShiftTarget + AMShift;
-    y:= cScreenHeight - AMyOffset;
-    DrawSprite(sprAMCorners, x - BORDERSIZE, y, 2);
-    for i:= 0 to cMaxSlotAmmoIndex + 1 do
-        DrawSprite(sprAMBorderHorizontal, x + i * AMSlotSize, y, 1);
-    DrawSprite(sprAMCorners, x + AMShiftTarget - AMxOffset, y, 3);
-    dec(y, AMSlotSize);
-    DrawSprite(sprAMBorderVertical, x - BORDERSIZE, y, 0);
-    for i:= 0 to cMaxSlotAmmoIndex do
-        DrawSprite(sprAMSlot, x + i * AMSlotSize, y, 2);
-    DrawSprite(sprAMSlot, x + (cMaxSlotAmmoIndex + 1) * AMSlotSize, y, 1);
-    DrawSprite(sprAMBorderVertical, x + AMShiftTarget - AMxOffset, y, 1);
+    inc(y, AMSlotSize + 1);
+{$ENDIF}
+    end;
+
+for i:= 1 to SlotsNumX -1 do
+DrawLine2Surf(amSurface, i * (AMSlotSize+1), BORDERSIZE, i * (AMSlotSize+1), AMRect.h + BORDERSIZE - AMSlotSize - 2,160,160,160);            
+for i:= 1 to SlotsNumY -1 do
+DrawLine2Surf(amSurface, BORDERSIZE, i * (AMSlotSize+1), AMRect.w + BORDERSIZE, i * (AMSlotSize+1),160,160,160);
+
+//draw outer border
+DrawSprite2Surf(sprAMCorners, amSurface, 0                    , 0                    , 0);
+DrawSprite2Surf(sprAMCorners, amSurface, AMRect.w + BORDERSIZE, AMRect.y             , 1);
+DrawSprite2Surf(sprAMCorners, amSurface, AMRect.x             , AMRect.h + BORDERSIZE, 2);
+DrawSprite2Surf(sprAMCorners, amSurface, AMRect.w + BORDERSIZE, AMRect.h + BORDERSIZE, 3);
+
+for i:=0 to BORDERSIZE-1 do
+begin
+DrawLine2Surf(amSurface, BORDERSIZE, i, AMRect.w + BORDERSIZE, i,160,160,160);//top
+DrawLine2Surf(amSurface, BORDERSIZE, AMRect.h+BORDERSIZE+i, AMRect.w + BORDERSIZE, AMRect.h+BORDERSIZE+i,160,160,160);//bottom
+DrawLine2Surf(amSurface, i, BORDERSIZE, i, AMRect.h + BORDERSIZE,160,160,160);//left
+DrawLine2Surf(amSurface, AMRect.w+BORDERSIZE+i, BORDERSIZE, AMRect.w + BORDERSIZE+i, AMRect.h + BORDERSIZE, 160,160,160);//right
+end;
+
+  
+GetAmmoMenuTexture:= Surface2Tex(amSurface, false);
+if amSurface <> nil then SDL_FreeSurface(amSurface);
+end;
+
+procedure ShowAmmoMenu;
+const BORDERSIZE = 2;
+      MENUSPEED = 15;
+var Slot, Pos: LongInt;
+    Ammo: PHHAmmo;
+    i,g,t,CursorXtmp, CursorYtmp,STurns: LongInt;
+begin
+if (TurnTimeLeft = 0) or (not CurrentTeam^.ExtDriven and (((CurAmmoGear = nil)
+or ((Ammoz[CurAmmoGear^.AmmoType].Ammo.Propz and ammoprop_AltAttack) = 0)) and hideAmmoMenu)) then
+bShowAmmoMenu:= false;
+
+
+// give the assigned ammo to hedgehog
+Ammo:= nil;
+if (CurrentTeam <> nil) and (CurrentHedgehog <> nil)
+and (not CurrentTeam^.ExtDriven) and (CurrentHedgehog^.BotLevel = 0) then
+Ammo:= CurrentHedgehog^.Ammo
+else if (LocalAmmo <> -1) then
+Ammo:= GetAmmoByNum(LocalAmmo);
+Pos:= -1;
+if Ammo = nil then
+begin
+bShowAmmoMenu:= false;
+exit
+end;
+
+//Init the menu 
+if(AmmoMenuInvalidated) then 
+    begin
+    AmmoMenuInvalidated:= false;
+    FreeTexture(AmmoMenuTex);
+    AmmoMenuTex:= GetAmmoMenuTexture(Ammo);
 
-    for i:= cMaxSlotIndex downto 0 do
+{$IFDEF MOBILE}
+    if isPhone() then
+        begin
+        AmmoRect.x:= -(AmmoRect.w shr 1);
+        AmmoRect.y:= (cScreenHeight shr 1) - (AmmoRect.h shr 1);
+        end
+    else
+        begin
+        AmmoRect.x:= -(AmmoRect.w shr 1);
+        AmmoRect.y:= cScreenHeight - (AmmoRect.h + AMSlotSize);
+        end;
+{$ELSE}
+        AmmoRect.x:= (cScreenWidth shr 1) - AmmoRect.w - AMSlotSize;
+        AmmoRect.y:= cScreenHeight - (AmmoRect.h + AMSlotSize);
+{$ENDIF}
+    AMShiftTargetX:= (cScreenWidth shr 1) - AmmoRect.x;
+    AMShiftTargetY:= cScreenHeight - AmmoRect.y;
+    AMShiftX:= AMShiftTargetX;
+    AMShiftY:= AMShiftTargetY;
+
+    if (AMShiftTargetX div MENUSPEED) <  (AMShiftTargetY div MENUSPEED) then
+        begin
+        MenuSpeedX:= MENUSPEED;
+        MenuSpeedY:= AMShiftTargetY div (AMShiftTargetX div MENUSPEED);
+        end
+    else
+        begin
+        MenuSpeedX:= AMShiftTargetX div (AMShiftTargetY div MENUSPEED);
+        MenuSpeedY:= MENUSPEED;
+        end;
+end;
+
+if bShowAmmoMenu then // show ammo menu
+    begin
+    FollowGear:= nil;
+    if (AMShiftX = 0) and (AMShiftY = 0) then
+{$IFDEF MOBILE}
+        prevPoint.Y:= 0;
+{$ELSE}
+        prevPoint.X:= 0;
+{$ENDIF}
+    if (cReducedQuality and rqSlowMenu) <> 0 then
+        begin
+        AMShiftX:= 0;
+        AMShiftY:= 0;
+        end
+    else
+        if (AMShiftX <> 0) or (AMShiftY <> 0) then
+            begin
+            dec(AMShiftX, MenuSpeedX);
+            if AMShiftX < 0 then AMShiftX:= 0;
+            dec(AMShiftY, MenuSpeedY);
+            if AMShiftY < 0 then AMShiftY:= 0;
+            end
+    end
+else  // hide ammo menu
+    begin
+    if (AMShiftX = AMShiftTargetX) and (AMShiftY = AMShiftTargetY) then
+        begin
+        prevPoint:= CursorPoint;
+        end;
+    if (cReducedQuality and rqSlowMenu) <> 0 then
+        begin
+        AMShiftX:= AMShiftTargetX;
+        AMShiftY:= AMShiftTargetY;
+        end
+    else
+        if (AMShiftX <> AMShiftTargetX) or (AMShiftY <> AMShiftTargetY) then
+            begin
+            inc(AMShiftX, MenuSpeedX);
+            if AMShiftX > AMShiftTargetX then AMShiftX:= AMShiftTargetX;
+            inc(AMShiftY, MenuSpeedY);
+            if AMShiftY> AMShiftTargetY then AMShiftY:= AMShiftTargetY;
+            end
+    end;
+
+    DrawTexture(AmmoRect.x + AMShiftX, AmmoRect.y + AMShiftY, AmmoMenuTex);
+
+    Pos:= -1;
+    Slot:= -1;
+{$IFDEF MOBILE}
+    for i:= 0 to cMaxSlotIndex do
         if ((i = 0) and (Ammo^[i, 1].Count > 0)) or ((i <> 0) and (Ammo^[i, 0].Count > 0)) then
             begin
-            if (cScreenHeight - CursorPoint.Y >= y - AMSlotSize) and (cScreenHeight - CursorPoint.Y <= y) then
-                Slot:= i;
-            dec(y, AMSlotSize);
-            inc(SlotsNum);
-            DrawSprite(sprAMBorderVertical, x - BORDERSIZE, y, 0);
-            DrawSprite(sprAMSlot, x, y, 1);
-            DrawSprite(sprAMSlotKeys, x, y + 1, i);
-            t:= 0;
-            g:= 1;
-            while (t <= cMaxSlotAmmoIndex) and (Ammo^[i, t].Count > 0) do
-                begin
-                DrawSprite(sprAMSlot, x + g * AMSlotSize, y, 1);
-                if (Ammo^[i, t].AmmoType <> amNothing) then
+            g:= 0;
+            for t:=0 to cMaxSlotAmmoIndex do
+                if (Ammo^[i, t].Count > 0) and (Ammo^[i, t].AmmoType <> amNothing) then
                     begin
-                    STurns:= Ammoz[Ammo^[i, t].AmmoType].SkipTurns - CurrentTeam^.Clan^.TurnNumber;
-
-                    if STurns >= 0 then
+                    if (CursorPoint.Y <= (cScreenHeight - AmmoRect.y) - ( g    * (AMSlotSize+1))) and
+                       (CursorPoint.Y >= (cScreenHeight - AmmoRect.y) - ((g+1) * (AMSlotSize+1))) and
+                       (CursorPoint.X >= AmmoRect.x                   + ( i    * (AMSlotSize+1))) and 
+                       (CursorPoint.X <= AmmoRect.x                   + ((i+1) * (AMSlotSize+1))) then
                         begin
-                        DrawSprite(sprAMAmmosBW, x + g * AMSlotSize, y + 1, LongInt(Ammo^[i, t].AmmoType)-1);
-                        if STurns < 100 then
-                            DrawSprite(sprTurnsLeft, x + (g + 1) * AMSlotSize - 16, y + AMSlotSize - 16, STurns);
-                        end else
-                        DrawSprite(sprAMAmmos, x + g * AMSlotSize, y + 1, LongInt(Ammo^[i, t].AmmoType)-1);
-                    if (Slot = i) and (CursorPoint.X >= x + g * AMSlotSize) and
-                       (CursorPoint.X <= x + (g + 1) * AMSlotSize) then
-                        begin
-                        if (STurns < 0) then
-                            DrawSprite(sprAMSlot, x + g * AMSlotSize, y, 0);
+                        Slot:= i;
                         Pos:= t;
+                        STurns:= Ammoz[Ammo^[i, t].AmmoType].SkipTurns - CurrentTeam^.Clan^.TurnNumber;
+                        if (STurns < 0) and (AMShiftX = 0) and (AMShiftY = 0) then
+                            DrawSprite(sprAMSlot, 
+                                       AmmoRect.x + BORDERSIZE + (Slot * (AMSlotSize+1)) + AMSlotPadding -1, 
+                                       AmmoRect.y + BORDERSIZE + (g  * (AMSlotSize+1)) + AMSlotPadding -1, 0);
                         end;
-                    inc(g)
-                    end;
-                    inc(t)
-                end;
-            for g:= g to cMaxSlotAmmoIndex + 1 do
-                DrawSprite(sprAMSlot, x + g * AMSlotSize, y, 1);
-            DrawSprite(sprAMBorderVertical, x + AMShiftTarget - AMxOffset, y, 1);
+                        inc(g);
+                   end;
             end;
-
-    dec(y, BORDERSIZE);
-    DrawSprite(sprAMCorners, x - BORDERSIZE, y, 0);
-    for i:= 0 to cMaxSlotAmmoIndex + 1 do
-        DrawSprite(sprAMBorderHorizontal, x + i * AMSlotSize, y, 0);
-    DrawSprite(sprAMCorners, x + AMShiftTarget - AMxOffset, y, 1);
+{$ELSE}
+    for i:= 0 to cMaxSlotIndex do
+        if ((i = 0) and (Ammo^[i, 1].Count > 0)) or ((i <> 0) and (Ammo^[i, 0].Count > 0)) then
+            begin
+            g:= 0;
+            for t:=0 to cMaxSlotAmmoIndex do
+                if (Ammo^[i, t].Count > 0) and (Ammo^[i, t].AmmoType <> amNothing) then
+                    begin
+                    if (CursorPoint.Y <= (cScreenHeight - AmmoRect.y) - ( i    * (AMSlotSize+1))) and
+                       (CursorPoint.Y >= (cScreenHeight - AmmoRect.y) - ((i+1) * (AMSlotSize+1))) and
+                       (CursorPoint.X >= AmmoRect.x                   + ( g    * (AMSlotSize+1))) and 
+                       (CursorPoint.X <= AmmoRect.x                   + ((g+1) * (AMSlotSize+1))) then
+                        begin
+                        Slot:= i;
+                        Pos:= t;
+                        STurns:= Ammoz[Ammo^[i, t].AmmoType].SkipTurns - CurrentTeam^.Clan^.TurnNumber;
+                        if (STurns < 0) and (AMShiftX = 0) and (AMShiftY = 0) then
+                            DrawSprite(sprAMSlot, 
+                                       AmmoRect.x + BORDERSIZE + (g * (AMSlotSize+1)) + AMSlotPadding -1, 
+                                       AmmoRect.y + BORDERSIZE + (Slot  * (AMSlotSize+1)) + AMSlotPadding -1, 0);
+                        end;
+                        inc(g);
+                   end;
+            end;
 {$ENDIF}
-
-    if (Pos >= 0) then
+    if (Pos >= 0) and (Pos <= cMaxSlotAmmoIndex) and (Slot >= 0) and (Slot <= cMaxSlotIndex)then
         begin
+        if (AMShiftX = 0) and (AMShiftY = 0) then
         if (Ammo^[Slot, Pos].Count > 0) and (Ammo^[Slot, Pos].AmmoType <> amNothing) then
             begin
             if (amSel <> Ammo^[Slot, Pos].AmmoType) or (WeaponTooltipTex = nil) then
@@ -432,19 +488,13 @@
                 RenderWeaponTooltip(amSel)
                 end;
 
-{$IFDEF MOBILE}
-            DrawTexture(AMxOffset - ((SlotsNum * AMSlotSize) shr 1) + (AMSlotSize shr 1),
-                        cScreenHeight - AMShiftTarget + AMShift + (Ammoz[Ammo^[Slot, Pos].AmmoType].NameTex^.h shr 1),
+            DrawTexture(AmmoRect.x + (AMSlotSize shr 1),
+                        AmmoRect.y + AmmoRect.h - BORDERSIZE - (AMSlotSize shr 1) - (Ammoz[Ammo^[Slot, Pos].AmmoType].NameTex^.h shr 1),
                         Ammoz[Ammo^[Slot, Pos].AmmoType].NameTex);
             if Ammo^[Slot, Pos].Count < AMMO_INFINITE then
-                DrawTexture(AMxOffset + ((SlotsNum * AMSlotSize) shr 1) - Round(Ammoz[Ammo^[Slot, Pos].AmmoType].NameTex^.h * 1.5),
-                            cScreenHeight - AMShiftTarget + AMShift + (Ammoz[Ammo^[Slot, Pos].AmmoType].NameTex^.h shr 1),
+                DrawTexture(AmmoRect.x + AmmoRect.w - 20 - (CountTexz[Ammo^[Slot, Pos].Count]^.w),
+                            AmmoRect.y + AmmoRect.h - BORDERSIZE - (AMslotSize shr 1) - (CountTexz[Ammo^[Slot, Pos].Count]^.w shr 1),
                             CountTexz[Ammo^[Slot, Pos].Count]);
-{$ELSE}
-            DrawTexture(cScreenWidth div 2 - (AMShiftTarget - 10) + AMShift, cScreenHeight - AMyOffset - 25, Ammoz[Ammo^[Slot, Pos].AmmoType].NameTex);
-            if Ammo^[Slot, Pos].Count < AMMO_INFINITE then
-                DrawTexture(cScreenWidth div 2 + AMxOffset - 45, cScreenHeight - AMyOffset - 25, CountTexz[Ammo^[Slot, Pos].Count]);
-{$ENDIF}
 
             if bSelected and (Ammoz[Ammo^[Slot, Pos].AmmoType].SkipTurns - CurrentTeam^.Clan^.TurnNumber < 0) then
                 begin
@@ -459,16 +509,17 @@
     else
         FreeWeaponTooltip;
 
-    if (WeaponTooltipTex <> nil) and (AMShift = 0) then
+    if (WeaponTooltipTex <> nil) and (AMShiftX = 0) and (AMShiftY = 0) then
 {$IFDEF MOBILE}
-        ShowWeaponTooltip(-WeaponTooltipTex^.w div 2, cScreenHeight - (AMShiftTarget + AMSlotSize + WeaponTooltipTex^.h));
+        if not isPhone() then
+            ShowWeaponTooltip(-WeaponTooltipTex^.w div 2, AmmoRect.y - WeaponTooltipTex^.h - AMSlotSize);
 {$ELSE}
-        ShowWeaponTooltip(x - WeaponTooltipTex^.w - 3, Min(y + 1, cScreenHeight - WeaponTooltipTex^.h - 40));
+        ShowWeaponTooltip(AmmoRect.x - WeaponTooltipTex^.w - 3, Min(AmmoRect.y + 1, cScreenHeight - WeaponTooltipTex^.h - 40));
 {$ENDIF}
 
     bSelected:= false;
-    if AMShift = 0 then
-        DrawSprite(sprArrow, CursorPoint.X, cScreenHeight - CursorPoint.Y, (RealTicks shr 6) mod 8)
+    if (AMShiftX = 0) and (AMShiftY = 0) then
+        DrawSprite(sprArrow, CursorPoint.X, cScreenHeight - CursorPoint.Y, (RealTicks shr 6) mod 8);
 end;
 
 procedure DrawWater(Alpha: byte; OffsetY: LongInt);
@@ -1110,7 +1161,7 @@
         end;
 
 // AmmoMenu
-if (AMShift < AMShiftTarget) or bShowAmmoMenu then
+if bShowAmmoMenu or ((AMShiftX <> AMShiftTargetX) or (AMShiftY <> AMShiftTargetY)) then
     ShowAmmoMenu;
 
 // Cursor
@@ -1307,27 +1358,16 @@
 if ((CursorPoint.X = prevPoint.X) and (CursorPoint.Y = prevpoint.Y)) then
     exit;
 
-if AMShift < AMShiftTarget then
+if (AMShiftX <> AMShiftTargetX) and (AMShiftY <> AMShiftTargetY) then
 begin
-{$IFDEF MOBILE}
-    if CursorPoint.X < AMxOffset - ((SlotsNum * AMSlotSize) shr 1) then//check left 
-        CursorPoint.X:= AMxOffset - ((SlotsNum* AMSlotSize) shr 1);
-    if CursorPoint.X > (AMxOffset + (SlotsNum * AMSlotSize) shr 1) then//check right
-        CursorPoint.X:= (AMxOffset + (SlotsNum * AMSlotSize) shr 1);
-    if CursorPoint.Y > (AMShiftTarget + AMShift - AMSlotSize) then//check top
-        CursorPoint.Y:= AMShiftTarget + AMShift - AMSlotSize;
-    if CursorPoint.Y < (AMShiftTarget + AMShift) - ((cMaxSlotAmmoIndex+2) * AMSlotSize) then//check bottom
-        CursorPoint.Y:= (AMShiftTarget + AMShift) - ((cMaxSlotAmmoIndex+2) * AMSlotSize);
-{$ELSE}
-    if CursorPoint.X < cScreenWidth div 2 + AMShift - AMShiftTarget + AMSlotSize then
-        CursorPoint.X:= cScreenWidth div 2 + AMShift - AMShiftTarget + AMSlotSize;
-    if CursorPoint.X > cScreenWidth div 2 + AMShift - AMxOffset then
-        CursorPoint.X:= cScreenWidth div 2 + AMShift - AMxOffset;
-    if CursorPoint.Y > AMyOffset + (SlotsNum + 1) * AMSlotSize then
-        CursorPoint.Y:= AMyOffset + (SlotsNum + 1) * AMSlotSize;
-    if CursorPoint.Y < AMyOffset + AMSlotSize then
-        CursorPoint.Y:= AMyOffset + AMSlotSize;
-{$ENDIF}
+    if CursorPoint.X < AmmoRect.x then//check left 
+        CursorPoint.X:= AmmoRect.x;
+    if CursorPoint.X > AmmoRect.x + AmmoRect.w then//check right
+        CursorPoint.X:= AmmoRect.x + AmmoRect.w;
+    if CursorPoint.Y > cScreenHeight - AmmoRect.y then//check top
+        CursorPoint.Y:= cScreenHeight - AmmoRect.y;
+    if CursorPoint.Y < cScreenHeight - (AmmoRect.y + AmmoRect.h - AMSlotSize - 2) then//check bottom
+        CursorPoint.Y:= cScreenHeight - (AmmoRect.y + AmmoRect.h - AMSlotSize - 2);
     prevPoint:= CursorPoint;
     //if cHasFocus then SDL_WarpMouse(CursorPoint.X + cScreenWidth div 2, cScreenHeight - CursorPoint.Y);
     exit