Merge
authorMedo <smaxein@googlemail.com>
Thu, 03 May 2012 22:48:02 +0200
changeset 7020 846cea23aea2
parent 7009 23131a8b4c3a (current diff)
parent 7018 6a1f46c026bf (diff)
child 7110 c91d33837b0d
Merge
--- a/CMakeLists.txt	Thu May 03 15:34:26 2012 +0200
+++ b/CMakeLists.txt	Thu May 03 22:48:02 2012 +0200
@@ -162,7 +162,7 @@
 	set(pascal_compiler_flags_cmn "-Os" "-Ooregvar" "-Xs" "-Si" ${pascal_compiler_flags_cmn})
 	set(haskell_compiler_flags_cmn "-w" "-fno-warn-unused-do-bind" ${haskell_compiler_flags_cmn})
 else(Optz)
-	set(pascal_compiler_flags_cmn "-O-" "-g" "-gl" "-gv" "-dDEBUGFILE" ${pascal_compiler_flags_cmn})
+	set(pascal_compiler_flags_cmn "-O-" "-g" "-gl" "-gv" "-Ct" "-dDEBUGFILE" ${pascal_compiler_flags_cmn})
 	set(haskell_compiler_flags_cmn "-Wall" "-debug" "-dcore-lint" "-fno-warn-unused-do-bind" ${haskell_compiler_flags_cmn})
 endif(Optz)
 
--- a/QTfrontend/hwconsts.h	Thu May 03 15:34:26 2012 +0200
+++ b/QTfrontend/hwconsts.h	Thu May 03 22:48:02 2012 +0200
@@ -63,40 +63,40 @@
 
 #define HEDGEHOGS_PER_TEAM           8
 
-#define AMMOLINE_DEFAULT_QT     "939192942219912103223511100120100000021111010101111101"
-#define AMMOLINE_DEFAULT_PROB   "040504054160065554655446477657666666615551010111541101"
-#define AMMOLINE_DEFAULT_DELAY  "000000000000020550000004000700400000000022000000060000"
-#define AMMOLINE_DEFAULT_CRATE  "131111031211111112311411111111111111121111110111111101"
+#define AMMOLINE_DEFAULT_QT     "9391929422199121032235111001201000000211110101011111011"
+#define AMMOLINE_DEFAULT_PROB   "0405040541600655546554464776576666666155510101115411011"
+#define AMMOLINE_DEFAULT_DELAY  "0000000000000205500000040007004000000000220000000600000"
+#define AMMOLINE_DEFAULT_CRATE  "1311110312111111123114111111111111111211111101111111010"
 
-#define AMMOLINE_CRAZY_QT       "999999999999999999299999999999999929999999990999999209"
-#define AMMOLINE_CRAZY_PROB     "111111011111111111111111111111111111111111110111111101"
-#define AMMOLINE_CRAZY_DELAY    "000000000000000000000000000000000000000000000000000000"
-#define AMMOLINE_CRAZY_CRATE    "131111031211111112311411111111111111121111010111111101"
+#define AMMOLINE_CRAZY_QT       "9999999999999999992999999999999999299999999909999992099"
+#define AMMOLINE_CRAZY_PROB     "1111110111111111111111111111111111111111111101111111011"
+#define AMMOLINE_CRAZY_DELAY    "0000000000000000000000000000000000000000000000000000000"
+#define AMMOLINE_CRAZY_CRATE    "1311110312111111123114111111111111111211110101111111011"
 
-#define AMMOLINE_PROMODE_QT     "909000900000000000000900000000000000000000000000000000"
-#define AMMOLINE_PROMODE_PROB   "000000000000000000000000000000000000000000000000000000"
-#define AMMOLINE_PROMODE_DELAY  "000000000000020550000004000700400000000020000000000000"
-#define AMMOLINE_PROMODE_CRATE  "111111111111111111111111111111111111111110010111111101"
+#define AMMOLINE_PROMODE_QT     "9090009000000000000009000000000000000000000000000000000"
+#define AMMOLINE_PROMODE_PROB   "0000000000000000000000000000000000000000000000000000000"
+#define AMMOLINE_PROMODE_DELAY  "0000000000000205500000040007004000000000200000000000000"
+#define AMMOLINE_PROMODE_CRATE  "1111111111111111111111111111111111111111100101111111011"
 
-#define AMMOLINE_SHOPPA_QT      "000000990000000000000000000000000000000000000000000000"
-#define AMMOLINE_SHOPPA_PROB    "444441004424440221011212122242200000000200040001001100"
-#define AMMOLINE_SHOPPA_DELAY   "000000000000000000000000000000000000000000000000000000"
-#define AMMOLINE_SHOPPA_CRATE   "111111111111111111111111111111111111111110110111111100"
+#define AMMOLINE_SHOPPA_QT      "0000009900000000000000000000000000000000000000000000000"
+#define AMMOLINE_SHOPPA_PROB    "4444410044244402210112121222422000000002000400010011000"
+#define AMMOLINE_SHOPPA_DELAY   "0000000000000000000000000000000000000000000000000000000"
+#define AMMOLINE_SHOPPA_CRATE   "1111111111111111111111111111111111111111101101111111001"
 
-#define AMMOLINE_CLEAN_QT       "101000900001000001100000000000000000000000000000100000"
-#define AMMOLINE_CLEAN_PROB     "040504054160065554655446477657666666615551010111541101"
-#define AMMOLINE_CLEAN_DELAY    "000000000000000000000000000000000000000000000000000000"
-#define AMMOLINE_CLEAN_CRATE    "131111031211111112311411111111111111121111110111111101"
+#define AMMOLINE_CLEAN_QT       "1010009000010000011000000000000000000000000000001000000"
+#define AMMOLINE_CLEAN_PROB     "0405040541600655546554464776576666666155510101115411011"
+#define AMMOLINE_CLEAN_DELAY    "0000000000000000000000000000000000000000000000000000000"
+#define AMMOLINE_CLEAN_CRATE    "1311110312111111123114111111111111111211111101111111011"
 
-#define AMMOLINE_MINES_QT       "000000990009000000030000000000000000000000000000000000"
-#define AMMOLINE_MINES_PROB     "000000000000000000000000000000000000000000000000000000"
-#define AMMOLINE_MINES_DELAY    "000000000000020550000004000700400000000020000000060000"
-#define AMMOLINE_MINES_CRATE    "111111111111111111111111111111111111111111110111111101"
+#define AMMOLINE_MINES_QT       "0000009900090000000300000000000000000000000000000000000"
+#define AMMOLINE_MINES_PROB     "0000000000000000000000000000000000000000000000000000000"
+#define AMMOLINE_MINES_DELAY    "0000000000000205500000040007004000000000200000000600000"
+#define AMMOLINE_MINES_CRATE    "1111111111111111111111111111111111111111111101111111011"
 
-#define AMMOLINE_PORTALS_QT     "900000900200000000210000000000000011000009000000000000"
-#define AMMOLINE_PORTALS_PROB   "040504054160065554655446477657666666615551010111541101"
-#define AMMOLINE_PORTALS_DELAY  "000000000000020550000004000700400000000020000000060000"
-#define AMMOLINE_PORTALS_CRATE  "131111031211111112311411111111111111121111110111111101"
+#define AMMOLINE_PORTALS_QT     "9000009002000000002100000000000000110000090000000000000"
+#define AMMOLINE_PORTALS_PROB   "0405040541600655546554464776576666666155510101115411011"
+#define AMMOLINE_PORTALS_DELAY  "0000000000000205500000040007004000000000200000000600000"
+#define AMMOLINE_PORTALS_CRATE  "1311110312111111123114111111111111111211111101111111011"
 
 //Different seasons; assigned to season (int)
 #define SEASON_NONE 0
--- a/QTfrontend/hwform.cpp	Thu May 03 15:34:26 2012 +0200
+++ b/QTfrontend/hwform.cpp	Thu May 03 22:48:02 2012 +0200
@@ -195,6 +195,9 @@
     connect(ui.pageMain->BtnDataDownload, SIGNAL(clicked()), pageSwitchMapper, SLOT(map()));
     pageSwitchMapper->setMapping(ui.pageMain->BtnDataDownload, ID_PAGE_DATADOWNLOAD);
 
+    connect(ui.pageNetGame, SIGNAL(DLCClicked()), pageSwitchMapper, SLOT(map()));
+    pageSwitchMapper->setMapping(ui.pageNetGame, ID_PAGE_DATADOWNLOAD);
+
     //connect(ui.pageMain->BtnExit, SIGNAL(pressed()), this, SLOT(btnExitPressed()));
     //connect(ui.pageMain->BtnExit, SIGNAL(clicked()), this, SLOT(btnExitClicked()));
 
@@ -624,8 +627,12 @@
     OnPageShown(id, lastid);
     ui.Pages->setCurrentIndex(id);
 
-    if (id == ID_PAGE_DRAWMAP || id == ID_PAGE_GAMESTATS)
+
+   /* if (id == ID_PAGE_DRAWMAP || id == ID_PAGE_GAMESTATS)
         stopAnim = true;
+	This were disabled due to broken flake animations.  I believe the more general problems w/ opacity that forced its disable makes blocking these
+	unnecessary.
+   */
 
 #if (QT_VERSION >= 0x040600)
     if (!stopAnim)
@@ -646,7 +653,7 @@
         //New page animation
         animationNewSlide = new QPropertyAnimation(ui.Pages->widget(id), "pos");
         animationNewSlide->setDuration(duration);
-        animationNewSlide->setStartValue(QPoint(this->width()*1.5/coeff, 0));
+        animationNewSlide->setStartValue(QPoint(width()/coeff, 0));
         animationNewSlide->setEndValue(QPoint(0, 0));
         animationNewSlide->setEasingCurve(QEasingCurve::OutExpo);
 
@@ -664,7 +671,7 @@
         animationOldSlide = new QPropertyAnimation(ui.Pages->widget(lastid), "pos");
         animationOldSlide->setDuration(duration);
         animationOldSlide->setStartValue(QPoint(0, 0));
-        animationOldSlide->setEndValue(QPoint(this->width()*1.5/coeff, 0));
+        animationOldSlide->setEndValue(QPoint(-width()/coeff, 0));
         animationOldSlide->setEasingCurve(QEasingCurve::OutExpo);
 
 #ifdef false
@@ -685,6 +692,8 @@
         group->start();
 
         connect(animationOldSlide, SIGNAL(finished()), ui.Pages->widget(lastid), SLOT(hide()));
+    	/* this is for the situation when the animation below is interrupted by a new animation.  For some reason, finished is not being fired */ 	
+    	for(int i=0;i<MAX_PAGE;i++) if (i!=id && i!=lastid) ui.Pages->widget(i)->hide();
     }
 #endif
 }
@@ -718,8 +727,8 @@
         stopAnim = true;
         GoBack();
     }
-    if (curid == ID_PAGE_DRAWMAP)
-        stopAnim = true;
+    /*if (curid == ID_PAGE_DRAWMAP)
+        stopAnim = true; */
 
     if ((!hwnet) || (!hwnet->isInRoom()))
         if (id == ID_PAGE_NETGAME || id == ID_PAGE_NETGAME)
--- a/QTfrontend/hwform.h	Thu May 03 15:34:26 2012 +0200
+++ b/QTfrontend/hwform.h	Thu May 03 22:48:02 2012 +0200
@@ -152,29 +152,30 @@
 
         enum PageIDs
         {
-            ID_PAGE_SETUP_TEAM      =  0,
-            ID_PAGE_SETUP           =  1,
-            ID_PAGE_MULTIPLAYER     =  2,
-            ID_PAGE_DEMOS           =  3,
-            ID_PAGE_NET             =  4,
-            ID_PAGE_NETGAME         =  5,
-            ID_PAGE_INFO            =  6,
-            ID_PAGE_MAIN            =  7,
-            ID_PAGE_GAMESTATS       =  8,
-            ID_PAGE_SINGLEPLAYER    =  9,
-            ID_PAGE_TRAINING        = 10,
-            ID_PAGE_SELECTWEAPON    = 11,
-            ID_PAGE_NETSERVER       = 12,
-            ID_PAGE_INGAME          = 13,
-            ID_PAGE_ROOMSLIST       = 14,
-            ID_PAGE_CONNECTING      = 15,
-            ID_PAGE_SCHEME          = 16,
-            ID_PAGE_ADMIN           = 17,
-            ID_PAGE_NETTYPE         = 18,
-            ID_PAGE_CAMPAIGN        = 19,
-            ID_PAGE_DRAWMAP         = 20,
-            ID_PAGE_DATADOWNLOAD    = 21,
-            ID_PAGE_FEEDBACK        = 22
+            ID_PAGE_SETUP_TEAM     ,
+            ID_PAGE_SETUP          ,
+            ID_PAGE_MULTIPLAYER    ,
+            ID_PAGE_DEMOS          ,
+            ID_PAGE_NET            ,
+            ID_PAGE_NETGAME        ,
+            ID_PAGE_INFO           ,
+            ID_PAGE_MAIN           ,
+            ID_PAGE_GAMESTATS      ,
+            ID_PAGE_SINGLEPLAYER   ,
+            ID_PAGE_TRAINING       ,
+            ID_PAGE_SELECTWEAPON   ,
+            ID_PAGE_NETSERVER      ,
+            ID_PAGE_INGAME         ,
+            ID_PAGE_ROOMSLIST      ,
+            ID_PAGE_CONNECTING     ,
+            ID_PAGE_SCHEME         ,
+            ID_PAGE_ADMIN          ,
+            ID_PAGE_NETTYPE        ,
+            ID_PAGE_CAMPAIGN       ,
+            ID_PAGE_DRAWMAP        ,
+            ID_PAGE_DATADOWNLOAD   ,
+            ID_PAGE_FEEDBACK	   ,
+	    MAX_PAGE
         };
         QPointer<HWGame> game;
         QPointer<HWNetServer> pnetserver;
--- a/QTfrontend/ui/page/pagedata.cpp	Thu May 03 15:34:26 2012 +0200
+++ b/QTfrontend/ui/page/pagedata.cpp	Thu May 03 22:48:02 2012 +0200
@@ -222,7 +222,10 @@
                 return false;
             }
 
-            m_contentDownloaded = true;
+            if (this->isVisible())
+                m_contentDownloaded = true;
+            else
+                DataManager::instance().reload();
         }
 
         file.close();
--- a/QTfrontend/ui/page/pagenetgame.cpp	Thu May 03 15:34:26 2012 +0200
+++ b/QTfrontend/ui/page/pagenetgame.cpp	Thu May 03 22:48:02 2012 +0200
@@ -63,6 +63,9 @@
 {
     QHBoxLayout * bottomLayout = new QHBoxLayout;
 
+    btnDLC = addButton(tr("DLC"), bottomLayout, 0);
+    btnDLC->setWhatsThis(tr("Downloadable Content"));
+
     leRoomName = new HistoryLineEdit(this,10);
     leRoomName->setMaxLength(60);
     leRoomName->setMinimumWidth(200);
@@ -77,21 +80,23 @@
     BtnGo->setMinimumHeight(50);
 
     bottomLayout->addWidget(leRoomName);
-    BtnUpdate = addButton(QAction::tr("Update"), bottomLayout, 1);
+    BtnUpdate = addButton(QAction::tr("Update"), bottomLayout, 2);
 
     bottomLayout->addStretch();
     bottomLayout->addWidget(BtnGo);
 
-    BtnMaster = addButton(tr("Control"), bottomLayout, 3);
+    BtnMaster = addButton(tr("Control"), bottomLayout, 4);
     bottomLayout->insertStretch(3, 100);
 
-    BtnStart = addButton(QAction::tr("Start"), bottomLayout, 3);
+    BtnStart = addButton(QAction::tr("Start"), bottomLayout, 4);
 
     return bottomLayout;
 }
 
 void PageNetGame::connectSignals()
 {
+    connect(btnDLC, SIGNAL(clicked()), this, SIGNAL(DLCClicked()));
+
     connect(btnSetup, SIGNAL(clicked()), this, SIGNAL(SetupClicked()));
 
     connect(BtnUpdate, SIGNAL(clicked()), this, SLOT(onUpdateClick()));
--- a/QTfrontend/ui/page/pagenetgame.h	Thu May 03 15:34:26 2012 +0200
+++ b/QTfrontend/ui/page/pagenetgame.h	Thu May 03 22:48:02 2012 +0200
@@ -65,6 +65,7 @@
 
     signals:
         void SetupClicked();
+        void DLCClicked();
         void askForUpdateRoomName(const QString &);
 
     private:
@@ -76,6 +77,7 @@
 
         HistoryLineEdit * leRoomName;
         QPushButton * btnSetup;
+        QPushButton * btnDLC;
 };
 
 #endif
--- a/QTfrontend/ui/page/pageroomslist.cpp	Thu May 03 15:34:26 2012 +0200
+++ b/QTfrontend/ui/page/pageroomslist.cpp	Thu May 03 22:48:02 2012 +0200
@@ -152,12 +152,6 @@
     connect(searchText, SIGNAL(textChanged (const QString &)), this, SLOT(onFilterChanged()));
     connect(this, SIGNAL(askJoinConfirmation (const QString &)), this, SLOT(onJoinConfirmation(const QString &)), Qt::QueuedConnection);
 
-    // save header state on change
-    connect(roomsList->horizontalHeader(), SIGNAL(sortIndicatorChanged(int, Qt::SortOrder)),
-            this, SLOT(saveHeaderState()));
-    connect(roomsList->horizontalHeader(), SIGNAL(sectionResized),
-            this, SLOT(saveHeaderState()));
-
     // sorting
     connect(roomsList->horizontalHeader(), SIGNAL(sortIndicatorChanged(int, Qt::SortOrder)),
             this, SLOT(onSortIndicatorChanged(int, Qt::SortOrder)));
@@ -538,6 +532,10 @@
 
     QHeaderView * h = roomsList->horizontalHeader();
 
+    h->setSortIndicatorShown(true);
+    h->setSortIndicator(RoomsListModel::StateColumn, Qt::AscendingOrder);
+    h->setResizeMode(RoomsListModel::NameColumn, QHeaderView::Stretch);
+
     if (!restoreHeaderState())
     {
         h->resizeSection(RoomsListModel::PlayerCountColumn, 32);
@@ -548,8 +546,12 @@
         h->resizeSection(RoomsListModel::WeaponsColumn, 100);
     }
 
-    h->setSortIndicatorShown(true);
-    h->setResizeMode(RoomsListModel::NameColumn, QHeaderView::Stretch);
+
+    // save header state on change
+    connect(roomsList->horizontalHeader(), SIGNAL(sortIndicatorChanged(int, Qt::SortOrder)),
+            this, SLOT(saveHeaderState()));
+    connect(roomsList->horizontalHeader(), SIGNAL(sectionResized(int, int, int)),
+            this, SLOT(saveHeaderState()));
 }
 
 
@@ -558,6 +560,12 @@
     if (roomsModel == NULL)
         return;
 
+    if (logicalIndex == 0)
+    {
+        roomsModel->sort(0, Qt::AscendingOrder);
+        return;
+    }
+
     // three state sorting: asc -> dsc -> default (by room state)
     if ((order == Qt::AscendingOrder) && (logicalIndex == roomsModel->sortColumn()))
         roomsList->horizontalHeader()->setSortIndicator(
@@ -600,12 +608,12 @@
 {
     if (!m_gameSettings->contains("frontend/roomslist_header"))
         return false;
-    return roomsList->horizontalHeader()->restoreState(QByteArray::fromHex(
-        (m_gameSettings->value("frontend/roomslist_header").toByteArray())));
+    return roomsList->horizontalHeader()->restoreState(QByteArray::fromBase64(
+        (m_gameSettings->value("frontend/roomslist_header").toString().toAscii())));
 }
 
 void PageRoomsList::saveHeaderState()
 {
     m_gameSettings->setValue("frontend/roomslist_header",
-        roomsList->horizontalHeader()->saveState().toHex());
+        QString(roomsList->horizontalHeader()->saveState().toBase64()));
 }
--- a/QTfrontend/ui/widget/frameTeam.cpp	Thu May 03 15:34:26 2012 +0200
+++ b/QTfrontend/ui/widget/frameTeam.cpp	Thu May 03 22:48:02 2012 +0200
@@ -41,6 +41,7 @@
         availableColors.push_back(QColor(colors[i++]));
 
     resetColors();
+    this->setSizePolicy(QSizePolicy::Maximum, QSizePolicy::Fixed);
 }
 
 void FrameTeams::setInteractivity(bool interactive)
@@ -89,6 +90,8 @@
     mainLayout.removeWidget(it.value());
     it.value()->deleteLater();
     teamToWidget.erase(it);
+    QResizeEvent* pevent=new QResizeEvent(parentWidget()->size(), parentWidget()->size());
+    QCoreApplication::postEvent(parentWidget(), pevent);
 }
 
 void FrameTeams::resetTeams()
@@ -99,6 +102,8 @@
         it.value()->deleteLater();
         teamToWidget.erase(it++);
     }
+    QResizeEvent* pevent=new QResizeEvent(parentWidget()->size(), parentWidget()->size());
+    QCoreApplication::postEvent(parentWidget(), pevent);
 }
 
 void FrameTeams::setHHNum(const HWTeam& team)
@@ -132,3 +137,8 @@
 {
     emit teamColorChanged(team);
 }
+
+QSize FrameTeams::sizeHint() const
+{
+    return QSize(-1, teamToWidget.size() * 39 + 9);
+}
--- a/QTfrontend/ui/widget/frameTeam.h	Thu May 03 15:34:26 2012 +0200
+++ b/QTfrontend/ui/widget/frameTeam.h	Thu May 03 22:48:02 2012 +0200
@@ -43,6 +43,7 @@
         void setTeamColor(const HWTeam& team);
         void setInteractivity(bool interactive);
         QColor getNextColor() const;
+        QSize sizeHint() const;
 
     signals:
         void teamColorChanged(const HWTeam&);
--- a/QTfrontend/ui/widget/mapContainer.cpp	Thu May 03 15:34:26 2012 +0200
+++ b/QTfrontend/ui/widget/mapContainer.cpp	Thu May 03 22:48:02 2012 +0200
@@ -41,12 +41,17 @@
     QWidget(parent),
     mainLayout(this),
     pMap(0),
-    mapgen(MAPGEN_REGULAR)
+    mapgen(MAPGEN_REGULAR),
+    m_previewSize(256, 128)
 {
     hhSmall.load(":/res/hh_small.png");
     hhLimit = 18;
     templateFilter = 0;
 
+    linearGrad = QLinearGradient(QPoint(128, 0), QPoint(128, 128));
+    linearGrad.setColorAt(1, QColor(0, 0, 192));
+    linearGrad.setColorAt(0, QColor(66, 115, 225));
+
     mainLayout.setContentsMargins(HWApplication::style()->pixelMetric(QStyle::PM_LayoutLeftMargin),
                                   1,
                                   HWApplication::style()->pixelMetric(QStyle::PM_LayoutRightMargin),
@@ -72,9 +77,6 @@
     chooseMap->setEditable(false);
     chooseMap->setModel(m_mapModel);
 
-    // update model views after model changes (to e.g. re-adjust separators)
-    connect(&DataManager::instance(), SIGNAL(updated()), this, SLOT(updateModelViews()));
-
     mapLayout->addWidget(chooseMap, 1, 1);
 
     QLabel * lblMap = new QLabel(tr("Map"), mapWidget);
@@ -178,25 +180,25 @@
 
     chooseMap->setCurrentIndex(0);
     mapChanged(0);
-    connect(chooseMap, SIGNAL(currentIndexChanged(int)), this, SLOT(mapChanged(int)));
+    // use signal "activated" rather than currentIndexChanged
+    // because index is somtimes changed a few times in a row programmatically
+    connect(chooseMap, SIGNAL(activated(int)), this, SLOT(mapChanged(int)));
 
-    updateModelViews();
+    // update model views after model changes (to e.g. re-adjust separators)
+    connect(&DataManager::instance(), SIGNAL(updated()), this, SLOT(updateModelViews()));
 }
 
 void HWMapContainer::setImage(const QImage newImage)
 {
-    QPixmap px(256, 128);
-    QPixmap pxres(256, 128);
+    QPixmap px(m_previewSize);
+    QPixmap pxres(px.size());
     QPainter p(&pxres);
 
     px.fill(Qt::yellow);
     QBitmap bm = QBitmap::fromImage(newImage);
     px.setMask(bm);
 
-    QLinearGradient linearGrad(QPoint(128, 0), QPoint(128, 128));
-    linearGrad.setColorAt(1, QColor(0, 0, 192));
-    linearGrad.setColorAt(0, QColor(66, 115, 225));
-    p.fillRect(QRect(0, 0, 256, 128), linearGrad);
+    p.fillRect(pxres.rect(), linearGrad);
     p.drawPixmap(QPoint(0, 0), px);
 
     addInfoToPreview(pxres);
@@ -211,15 +213,24 @@
 
 void HWMapContainer::mapChanged(int index)
 {
+    if (chooseMap->currentIndex() != index)
+        chooseMap->setCurrentIndex(index);
+
+    if (index < 0)
+    {
+        m_mapInfo.type = MapModel::Invalid;
+        updatePreview();
+        return;
+    }
+
     Q_ASSERT(chooseMap->itemData(index, Qt::UserRole + 1).canConvert<MapModel::MapInfo>());
     m_mapInfo = chooseMap->itemData(index, Qt::UserRole + 1).value<MapModel::MapInfo>();
-    m_curMap = chooseMap->currentText();
+    m_curMap = m_mapInfo.name;
 
     switch(m_mapInfo.type)
     {
         case MapModel::GeneratedMap:
             mapgen = MAPGEN_REGULAR;
-            updatePreview();
             gbThemes->show();
             lblFilter->show();
             cbTemplateFilter->show();
@@ -228,7 +239,6 @@
             break;
         case MapModel::GeneratedMaze:
             mapgen = MAPGEN_MAZE;
-            updatePreview();
             gbThemes->show();
             lblFilter->hide();
             cbTemplateFilter->hide();
@@ -237,7 +247,6 @@
             break;
         case MapModel::HandDrawnMap:
             mapgen = MAPGEN_DRAWN;
-            updatePreview();
             gbThemes->show();
             lblFilter->hide();
             cbTemplateFilter->hide();
@@ -246,7 +255,6 @@
             break;
         default:
             mapgen = MAPGEN_MAP;
-            updatePreview();
             gbThemes->hide();
             lblFilter->hide();
             cbTemplateFilter->hide();
@@ -261,7 +269,9 @@
         m_theme = lvThemes->currentIndex().data().toString();
         emit themeChanged(m_theme);
     }
-    emit mapChanged(m_mapInfo.name);
+
+    updatePreview();
+    emit mapChanged(m_curMap);
     emit mapgenChanged(mapgen);
 }
 
@@ -278,7 +288,8 @@
     p.setBrush(QColor(0, 0, 0));
     p.drawRect(image.rect().width() - hhSmall.rect().width() - 28, 3, 40, 20);
     p.setFont(QFont("MS Shell Dlg", 10));
-    p.drawText(image.rect().width() - hhSmall.rect().width() - 14 - (hhLimit > 9 ? 10 : 0), 18, QString::number(hhLimit));
+    QString text = (hhLimit > 0) ? QString::number(hhLimit) : "?";
+    p.drawText(image.rect().width() - hhSmall.rect().width() - 14 - (hhLimit > 9 ? 10 : 0), 18, text);
     p.drawPixmap(image.rect().width() - hhSmall.rect().width() - 5, 5, hhSmall.rect().width(), hhSmall.rect().height(), hhSmall);
 
     imageButt->setIcon(finalImage);
@@ -287,22 +298,30 @@
 
 void HWMapContainer::askForGeneratedPreview()
 {
-    if (pMap)
-    {
-        disconnect(pMap, 0, this, SLOT(setImage(const QImage)));
-        disconnect(pMap, 0, this, SLOT(setHHLimit(int)));
-        pMap = 0;
-    }
-
     pMap = new HWMap();
     connect(pMap, SIGNAL(ImageReceived(const QImage)), this, SLOT(setImage(const QImage)));
     connect(pMap, SIGNAL(HHLimitReceived(int)), this, SLOT(setHHLimit(int)));
+    connect(pMap, SIGNAL(destroyed(QObject *)), this, SLOT(onPreviewMapDestroyed(QObject *)));
     pMap->getImage(m_seed,
                    getTemplateFilter(),
                    get_mapgen(),
                    getMazeSize(),
                    getDrawnMapData()
                   );
+
+    setHHLimit(0);
+
+    const QPixmap waitIcon(":/res/iconTime.png");
+
+    QPixmap waitImage(m_previewSize);
+    QPainter p(&waitImage);
+
+    p.fillRect(waitImage.rect(), linearGrad);
+    int x = (waitImage.width() - waitIcon.width()) / 2;
+    int y = (waitImage.height() - waitIcon.height()) / 2;
+    p.drawPixmap(QPoint(x, y), waitIcon);
+
+    addInfoToPreview(waitImage);
 }
 
 void HWMapContainer::themeSelected(const QModelIndex & current, const QModelIndex &)
@@ -321,7 +340,7 @@
 QString HWMapContainer::getCurrentMap() const
 {
     if(chooseMap->currentIndex() < MAPGEN_MAP) return QString();
-    return(m_mapInfo.name);
+    return(m_curMap);
 }
 
 QString HWMapContainer::getCurrentTheme() const
@@ -376,24 +395,17 @@
 
 void HWMapContainer::intSetMap(const QString & map)
 {
+    m_curMap = map;
+
     int id = m_mapModel->indexOf(map);
 
-    if(id >= 0)
-    {
-        if (pMap)
-        {
-            disconnect(pMap, 0, this, SLOT(setImage(const QImage)));
-            disconnect(pMap, 0, this, SLOT(setHHLimit(int)));
-            pMap = 0;
-        }
-        chooseMap->setCurrentIndex(id);
-    }
+    mapChanged(id);
 }
 
-void HWMapContainer::setMap(const QString &map)
+void HWMapContainer::setMap(const QString & map)
 {
-    intSetMap(map);
-    updatePreview();
+    if ((m_mapInfo.type == MapModel::Invalid) || (map != m_mapInfo.name))
+        intSetMap(map);
 }
 
 void HWMapContainer::setTheme(const QString & theme)
@@ -422,10 +434,10 @@
         case MapModel::StaticMap:
             // get random map of same type
             idx = m_mapModel->randomMap(m_mapInfo.type);
-            chooseMap->setCurrentIndex(idx);
+            mapChanged(idx);
             break;
         case MapModel::Invalid:
-            Q_ASSERT(false);
+            mapChanged(0);
     }
 }
 
@@ -452,7 +464,8 @@
 void HWMapContainer::setTemplateFilter(int filter)
 {
     intSetTemplateFilter(filter);
-    updatePreview();
+    if (m_mapInfo.type == MapModel::GeneratedMap)
+        updatePreview();
 }
 
 MapGenerator HWMapContainer::get_mapgen(void) const
@@ -474,23 +487,52 @@
 void HWMapContainer::setMazeSize(int size)
 {
     intSetMazeSize(size);
-    updatePreview();
+    if (m_mapInfo.type == MapModel::GeneratedMaze)
+        updatePreview();
 }
 
 void HWMapContainer::intSetMapgen(MapGenerator m)
 {
-    mapgen = m;
+    if (mapgen != m)
+    {
+        mapgen = m;
 
-    if(m != MAPGEN_MAP)
-        chooseMap->setCurrentIndex(m);
+        switch (m)
+        {
+            case MAPGEN_REGULAR:
+                m_mapInfo.type = MapModel::GeneratedMap;
+                break;
+            case MAPGEN_MAZE:
+                m_mapInfo.type = MapModel::GeneratedMaze;
+                break;
+            case MAPGEN_DRAWN:
+                m_mapInfo.type = MapModel::HandDrawnMap;
+                break;
+            case MAPGEN_MAP:
+                switch (m_mapInfo.type)
+                {
+                    case MapModel::GeneratedMap:
+                    case MapModel::GeneratedMaze:
+                    case MapModel::HandDrawnMap:
+                        m_mapInfo.type = MapModel::Invalid;
+                    default:
+                        break;
+                }
+                break;
+        }
 
-    emit mapgenChanged(m);
+        if(m != MAPGEN_MAP)
+            chooseMap->setCurrentIndex(m);
+
+        emit mapgenChanged(m);
+    }
 }
 
 void HWMapContainer::setMapgen(MapGenerator m)
 {
     intSetMapgen(m);
-    updatePreview();
+    if(m != MAPGEN_MAP)
+        updatePreview();
 }
 
 void HWMapContainer::setDrawnMapData(const QByteArray & ar)
@@ -537,8 +579,22 @@
 
 void HWMapContainer::updatePreview()
 {
+    if (pMap)
+    {
+        disconnect(pMap, 0, this, SLOT(setImage(const QImage)));
+        disconnect(pMap, 0, this, SLOT(setHHLimit(int)));
+        pMap = 0;
+    }
+
+    QPixmap failIcon;
+
     switch(m_mapInfo.type)
     {
+        case MapModel::Invalid:
+            failIcon = QPixmap(":/res/btnDisabled.png");
+            imageButt->setIcon(failIcon);
+            imageButt->setIconSize(failIcon.size());
+            break;
         case MapModel::GeneratedMap:
             askForGeneratedPreview();
             break;
@@ -568,13 +624,12 @@
 
 void HWMapContainer::setAllMapParameters(const QString &map, MapGenerator m, int mazesize, const QString &seed, int tmpl)
 {
-    intSetMap(map);
     intSetMapgen(m);
     intSetMazeSize(mazesize);
     intSetSeed(seed);
     intSetTemplateFilter(tmpl);
-
-    updatePreview();
+    // this one last because it will refresh the preview
+    intSetMap(map);
 }
 
 
@@ -592,13 +647,15 @@
     }
 
     // restore map selection
-    if (!m_curMap.isEmpty())
-    {
-        int idx = chooseMap->findText(m_curMap);
-        if (idx >= 0)
-            chooseMap->setCurrentIndex(idx);
-        else
-            chooseMap->setCurrentIndex(0);
-    }
+    if ((!m_curMap.isEmpty()) && (chooseMap->currentIndex() < 0))
+        intSetMap(m_curMap);
+    else
+        updatePreview();
+}
 
+
+void HWMapContainer::onPreviewMapDestroyed(QObject * map)
+{
+    if (map == pMap)
+        pMap = 0;
 }
--- a/QTfrontend/ui/widget/mapContainer.h	Thu May 03 15:34:26 2012 +0200
+++ b/QTfrontend/ui/widget/mapContainer.h	Thu May 03 22:48:02 2012 +0200
@@ -73,6 +73,7 @@
         void setDrawnMapData(const QByteArray & ar);
         void setAllMapParameters(const QString & map, MapGenerator m, int mazesize, const QString & seed, int tmpl);
         void updateModelViews();
+        void onPreviewMapDestroyed(QObject * map);
 
     signals:
         void seedChanged(const QString & seed);
@@ -130,6 +131,9 @@
         MapModel::MapInfo m_mapInfo;
         QString m_theme;
         QString m_curMap;
+
+        QLinearGradient linearGrad; ///< for preview background
+        QSize m_previewSize;
 };
 
 #endif // _HWMAP_CONTAINER_INCLUDED
--- a/hedgewars/GSHandlers.inc	Thu May 03 15:34:26 2012 +0200
+++ b/hedgewars/GSHandlers.inc	Thu May 03 22:48:02 2012 +0200
@@ -5089,7 +5089,7 @@
                 DeleteGear(graves[i]);
                 RenderHealth(resgear^.Hedgehog^);
                 RecountTeamHealth(resgear^.Hedgehog^.Team);
-                resgear^.Hedgehog^.Effects[heResurrected]:= true;
+                resgear^.Hedgehog^.Effects[heResurrected]:= 1;
                 // only make hat-less hedgehogs look like zombies, preserve existing hats
                 
                 if resgear^.Hedgehog^.Hat = 'NoHat' then
@@ -5418,3 +5418,66 @@
 
 ////////////////////////////////////////////////////////////////////////////////
 
+(*
+WIP. The ice gun will have the following effects.  It has been proposed by sheepluva that it take the appearance of a large freezer
+spewing ice cubes.  The cubes will be visual gears only.  The scatter from them and the impact snow dust should help hide imprecisions in things like the GearsNear effect.
+For now we assume a "ray" like a deagle projected out from the gun.
+All these effects assume the ray's angle is not changed and that the target type was unchanged over a number of ticks.  This is a simplifying assumption for "gun was applying freezing effect to the same target".  
+  * When fired at water a layer of ice textured land is added above the water.
+  * When fired at non-ice land (land and $FF00 and not lfIce) the land is overlaid with a thin layer of ice textured land around that point (say, 1 or 2px into land, 1px above). For attractiveness, a slope would probably be needed.
+  * When fired at a hog (land and $00FF <> 0), while the hog is targetted, the hog's state is set to frozen.  As long as the gun is on the hog, a frozen hog sprite creeps up from the feet to the head.  If the effect is interrupted before reaching the top, the freezing state is cleared.
+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 doStepIceGun(Gear: PGear);
+var 
+    HHGear, iter: PGear;
+    ndX, ndY: hwFloat;
+    gX, gY: LongInt;
+begin
+    with Gear^ do
+        begin
+        HHGear := Hedgehog^.Gear;
+        HedgehogChAngle(HHGear);
+        ndX:= SignAs(AngleSin(HHGear^.Angle), HHGear^.dX);
+        ndY:= -AngleCos(HHGear^.Angle);
+        if (ndX <> dX) or (ndY <> dY) then
+            begin
+            Pos:= 0;
+            Target.X:= NoPointX;
+            LastDamage:= nil;
+            X:= HHGear^.X;
+            Y:= HHGear^.Y;
+// unfreeze all semifrozen hogs
+            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;
+            end
+        else
+            begin
+            gX:= hwRound(X);
+            gY:= hwRound(Y);
+            X:= X + dX;
+            Y:= Y + dY;
+            if Target.X <> NoPointX then
+                inc(Pos)
+            else if (gY > cWaterLine) or 
+                    (((gX and LAND_WIDTH_MASK = 0) and (gY and LAND_HEIGHT_MASK = 0))
+                        and ((Land[gY, gX] and $FF00 and not lfIce <> 0) or
+                             (Land[gY, gX] and $00FF <> 0))) then
+                begin
+                Target.X:= gX;
+                Target.Y:= gY;
+                if Land[gY, gX] and $00FF <> 0 then // locate and tag hogs
+                    begin
+                //GearsNear(X, Y, gtHedgehog, Radius);
+                    end;
+                end
+        end
+    end;
+end;
--- a/hedgewars/SDLh.pas	Thu May 03 15:34:26 2012 +0200
+++ b/hedgewars/SDLh.pas	Thu May 03 22:48:02 2012 +0200
@@ -944,7 +944,7 @@
 function  SDL_UnlockMutex(mutex: PSDL_mutex): LongInt; cdecl; external SDLLibName name 'SDL_mutexV';
 
 function  SDL_GL_SetAttribute(attr: TSDL_GLattr; value: LongInt): LongInt; cdecl; external SDLLibName;
-procedure SDL_GL_SwapBuffers(); cdecl; external SDLLibName;
+procedure SDL_GL_SwapBuffers; cdecl; external SDLLibName;
 
 function  SDL_NumJoysticks: LongInt; cdecl; external SDLLibName;
 function  SDL_JoystickName(idx: LongInt): PChar; cdecl; external SDLLibName;
--- a/hedgewars/options.inc	Thu May 03 15:34:26 2012 +0200
+++ b/hedgewars/options.inc	Thu May 03 22:48:02 2012 +0200
@@ -17,14 +17,15 @@
  *)
 
 {$IFDEF FPC}
-    {$WRITEABLECONST OFF} 
+    {$WRITEABLECONST OFF}
+    {$IMPLICITEXCEPTIONS OFF}
+    {$VARSTRINGCHECKS ON}
     {$MODE OBJFPC}
 {$ELSE}
     {$ERROR Only Free Pascal supported!}
 {$ENDIF}
 
 {$MACRO ON}
-
 {$DEFINE GLunit:=GL}
 
 {$IFDEF ANDROID}
--- a/hedgewars/uAIAmmoTests.pas	Thu May 03 15:34:26 2012 +0200
+++ b/hedgewars/uAIAmmoTests.pas	Thu May 03 22:48:02 2012 +0200
@@ -109,7 +109,8 @@
             (proc: @TestSnowball;    flags: 0), // amSnowball
             (proc: nil;              flags: 0), // amTardis
             (proc: nil;              flags: 0), // amStructure
-            (proc: nil;              flags: 0) // amLandGun
+            (proc: nil;              flags: 0), // amLandGun
+            (proc: nil;              flags: 0)  // amIceGun
             );
 
 const BadTurn = Low(LongInt) div 4;
--- a/hedgewars/uGears.pas	Thu May 03 15:34:26 2012 +0200
+++ b/hedgewars/uGears.pas	Thu May 03 22:48:02 2012 +0200
@@ -110,7 +110,7 @@
                 dec(Gear^.Health, dmg);
 
             if (Gear^.Hedgehog^.Team = CurrentTeam) and (Gear^.Damage <> Gear^.Karma)
-            and (not Gear^.Hedgehog^.King) and (not Gear^.Hedgehog^.Effects[hePoisoned]) and (not SuddenDeathDmg) then
+            and (not Gear^.Hedgehog^.King) and (Gear^.Hedgehog^.Effects[hePoisoned] = 0) and (not SuddenDeathDmg) then
                 Gear^.State:= Gear^.State or gstLoser;
 
             spawnHealthTagForHH(Gear, dmg);
@@ -141,7 +141,7 @@
         if Gear^.Kind = gtHedgehog then
             begin
             tmp:= 0;
-            if Gear^.Hedgehog^.Effects[hePoisoned] then
+            if Gear^.Hedgehog^.Effects[hePoisoned] <> 0 then
                 begin
                 inc(tmp, ModifyDamage(5, Gear));
                 if (GameFlags and gfResetHealth) <> 0 then
@@ -1302,7 +1302,8 @@
             @doStepSnowflake,
             @doStepStructure,
             @doStepLandGun,
-            @doStepTardis);
+            @doStepTardis,
+            @doStepIceGun);
 begin
     doStepHandlers:= handlers;
 
--- a/hedgewars/uGearsHedgehog.pas	Thu May 03 15:34:26 2012 +0200
+++ b/hedgewars/uGearsHedgehog.pas	Thu May 03 22:48:02 2012 +0200
@@ -356,6 +356,7 @@
                                  //amMelonStrike: AddGear(CurWeapon^.Pos, 0, gtAirAttack, 4, _0, _0, 0);
                     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);
              end;
              
              case CurAmmoType of
@@ -379,7 +380,8 @@
                       amJetpack, amBirdy,
                  amFlamethrower, amLandGun,
                   amResurrector, amStructure,
-                       amTardis, amPiano: CurAmmoGear:= newGear;
+                       amTardis, amPiano,
+                       amIceGun: CurAmmoGear:= newGear;
              end;
              
             if ((CurAmmoType = amMine) or (CurAmmoType = amSMine)) and (GameFlags and gfInfAttack <> 0) then
@@ -611,7 +613,7 @@
                     end;
      posCaseHealth: begin
                     inc(HH^.Health, Gear^.Health);
-                    HH^.Hedgehog^.Effects[hePoisoned] := false;
+                    HH^.Hedgehog^.Effects[hePoisoned] := 0;
                     str(Gear^.Health, s);
                     s:= '+' + s;
                     AddCaption(s, HH^.Hedgehog^.Team^.Clan^.Color, capgrpAmmoinfo);
@@ -1157,8 +1159,8 @@
 
         if (Gear^.State and gstHHGone) = 0 then
             begin
-            Gear^.Hedgehog^.Effects[hePoisoned] := false;
-            if Gear^.Hedgehog^.Effects[heResurrectable] then
+            Gear^.Hedgehog^.Effects[hePoisoned] := 0;
+            if Gear^.Hedgehog^.Effects[heResurrectable] <> 0 then
                 begin
                 ResurrectHedgehog(Gear);
                 end
--- a/hedgewars/uGearsList.pas	Thu May 03 15:34:26 2012 +0200
+++ b/hedgewars/uGearsList.pas	Thu May 03 22:48:02 2012 +0200
@@ -148,7 +148,7 @@
                 gear^.Z:= cHHZ;
                 if (GameFlags and gfAISurvival) <> 0 then
                     if gear^.Hedgehog^.BotLevel > 0 then
-                        gear^.Hedgehog^.Effects[heResurrectable] := true;
+                        gear^.Hedgehog^.Effects[heResurrectable] := 0;
                 end;
        gtShell: begin
                 gear^.Radius:= 4;
@@ -541,8 +541,8 @@
 
         inc(KilledHHs);
         RecountTeamHealth(team);
-        if (CurrentHedgehog <> nil) and CurrentHedgehog^.Effects[heResurrectable] and
-        (not Gear^.Hedgehog^.Effects[heResurrectable]) then
+        if (CurrentHedgehog <> nil) and (CurrentHedgehog^.Effects[heResurrectable] <> 0)  and
+        (Gear^.Hedgehog^.Effects[heResurrectable] = 0) then
             with CurrentHedgehog^ do 
                 begin
                 inc(Team^.stats.AIKills);
--- a/hedgewars/uGearsRender.pas	Thu May 03 15:34:26 2012 +0200
+++ b/hedgewars/uGearsRender.pas	Thu May 03 22:48:02 2012 +0200
@@ -232,7 +232,7 @@
     HatVisible:= false;
 
 
-    if HH^.Effects[hePoisoned] then
+    if HH^.Effects[hePoisoned] <> 0 then
         begin
         Tint($00, $FF, $40, $40);
         DrawTextureRotatedF(SpritesData[sprSmokeWhite].texture, 2, 0, 0, sx, sy, 0, 1, 22, 22, (RealTicks shr 36) mod 360);
@@ -877,12 +877,12 @@
             end
         end;
 
-    if HH^.Effects[hePoisoned] then
+    if HH^.Effects[hePoisoned] <> 0 then
         begin
         Tint($00, $FF, $40, $80);
         DrawTextureRotatedF(SpritesData[sprSmokeWhite].texture, 1.5, 0, 0, sx, sy, 0, 1, 22, 22, 360 - (RealTicks shr 37) mod 360);
         end;
-    if HH^.Effects[heResurrected] then
+    if HH^.Effects[heResurrected] <> 0 then
         begin
         Tint($f5, $db, $35, $20);
         DrawSprite(sprVampiric, sx - 24, sy - 24, 0);
@@ -914,8 +914,10 @@
     if Gear^.Target.X <> NoPointX then
         if Gear^.AmmoType = amBee then
             DrawSpriteRotatedF(sprTargetBee, Gear^.Target.X + WorldDx, Gear^.Target.Y + WorldDy, 0, 0, (RealTicks shr 3) mod 360)
-        else
-            DrawSpriteRotatedF(sprTargetP, Gear^.Target.X + WorldDx, Gear^.Target.Y + WorldDy, 0, 0, (RealTicks shr 3) mod 360);
+	else if Gear^.AmmoType = amIceGun then
+	    DrawSprite(sprSnowDust, Gear^.Target.X + WorldDx, Gear^.Target.Y + WorldDy, (RealTicks shr 3) mod 360)
+    else
+        DrawSpriteRotatedF(sprTargetP, Gear^.Target.X + WorldDx, Gear^.Target.Y + WorldDy, 0, 0, (RealTicks shr 3) mod 360);
 
     case Gear^.Kind of
           gtGrenade: DrawSpriteRotated(sprBomb, x, y, 0, Gear^.DirAngle);
--- a/hedgewars/uGearsUtils.pas	Thu May 03 15:34:26 2012 +0200
+++ b/hedgewars/uGearsUtils.pas	Thu May 03 22:48:02 2012 +0200
@@ -132,7 +132,7 @@
                                 if Gear^.Kind <> gtFlame then FollowGear:= Gear
                                 end;
                             if ((Mask and EXPLPoisoned) <> 0) and (Gear^.Kind = gtHedgehog) and (not Gear^.Invulnerable) then
-                                Gear^.Hedgehog^.Effects[hePoisoned] := true;
+                                Gear^.Hedgehog^.Effects[hePoisoned] := 1;
                             end;
 
                         end;
@@ -371,7 +371,7 @@
                 and (Gear^.Kind <> gtDEagleShot) and (Gear^.Kind <> gtSineGunShot) then
                     if Gear^.Kind = gtHedgehog then
                         begin
-                        if Gear^.Hedgehog^.Effects[heResurrectable] then
+                        if Gear^.Hedgehog^.Effects[heResurrectable] <> 0 then
                             ResurrectHedgehog(Gear)
                         else
                             begin
@@ -449,8 +449,8 @@
     gear^.dY := _0;
     gear^.Damage := 0;
     gear^.Health := gear^.Hedgehog^.InitialHealth;
-    gear^.Hedgehog^.Effects[hePoisoned] := false;
-    if not CurrentHedgehog^.Effects[heResurrectable] then
+    gear^.Hedgehog^.Effects[hePoisoned] := 0;
+    if CurrentHedgehog^.Effects[heResurrectable] = 0 then
         with CurrentHedgehog^ do 
             begin
             inc(Team^.stats.AIKills);
@@ -593,7 +593,7 @@
     begin
     OutError('Can''t find place for Gear', false);
     if Gear^.Kind = gtHedgehog then
-        Gear^.Hedgehog^.Effects[heResurrectable] := false;
+        Gear^.Hedgehog^.Effects[heResurrectable] := 0;
     DeleteGear(Gear);
     Gear:= nil
     end
--- a/hedgewars/uRenderUtils.pas	Thu May 03 15:34:26 2012 +0200
+++ b/hedgewars/uRenderUtils.pas	Thu May 03 22:48:02 2012 +0200
@@ -27,15 +27,15 @@
 
 procedure copyRotatedSurface(src, dest: PSDL_Surface); // this is necessary since width/height are read only in SDL
 procedure copyToXY(src, dest: PSDL_Surface; destX, destY: LongInt); inline;
-procedure copyToXY(src, dest: PSDL_Surface; srcX, srcY, srcW, srcH, destX, destY: LongInt);
+procedure copyToXYFromRect(src, dest: PSDL_Surface; srcX, srcY, srcW, srcH, destX, destY: LongInt);
 
 procedure DrawSprite2Surf(sprite: TSprite; dest: PSDL_Surface; x,y: LongInt); inline;
-procedure DrawSprite2Surf(sprite: TSprite; dest: PSDL_Surface; x,y: LongInt; frame: LongInt);
+procedure DrawSpriteFrame2Surf(sprite: TSprite; dest: PSDL_Surface; x,y: LongInt; frame: LongInt);
 procedure DrawLine2Surf(dest: PSDL_Surface; x0,y0,x1,y1:LongInt; r,g,b: byte);
 procedure DrawRoundRect(rect: PSDL_Rect; BorderColor, FillColor: Longword; Surface: PSDL_Surface; Clear: boolean);
 
 function  RenderStringTex(s: ansistring; Color: Longword; font: THWFont): PTexture;
-function  RenderStringTex(s: ansistring; Color: Longword; font: THWFont; maxLength: LongWord): PTexture;
+function  RenderStringTexLim(s: ansistring; Color: Longword; font: THWFont; maxLength: LongWord): PTexture;
 function  RenderSpeechBubbleTex(s: ansistring; SpeechType: Longword; font: THWFont): PTexture;
 
 implementation
@@ -140,10 +140,10 @@
 
 procedure copyToXY(src, dest: PSDL_Surface; destX, destY: LongInt); inline;
 begin
-    copyToXY(src, dest, 0, 0, src^.w, src^.h, destX, destY);
+    copyToXYFromRect(src, dest, 0, 0, src^.w, src^.h, destX, destY);
 end;
 
-procedure copyToXY(src, dest: PSDL_Surface; srcX, srcY, srcW, srcH, destX, destY: LongInt);
+procedure copyToXYFromRect(src, dest: PSDL_Surface; srcX, srcY, srcW, srcH, destX, destY: LongInt);
 var i, j, maxDest, maxSrc, iX, iY: LongInt;
     srcPixels, destPixels: PLongWordArray;
     r0, g0, b0, a0, r1, g1, b1, a1: Byte;
@@ -173,17 +173,17 @@
 
 procedure DrawSprite2Surf(sprite: TSprite; dest: PSDL_Surface; x,y: LongInt); inline;
 begin
-    DrawSprite2Surf(sprite, dest, x, y, 0);
+    DrawSpriteFrame2Surf(sprite, dest, x, y, 0);
 end;
 
-procedure DrawSprite2Surf(sprite: TSprite; dest: PSDL_Surface; x,y,frame: LongInt);
+procedure DrawSpriteFrame2Surf(sprite: TSprite; dest: PSDL_Surface; x,y,frame: LongInt);
 var numFramesFirstCol, row, col: LongInt;
 begin
     numFramesFirstCol:= SpritesData[sprite].imageHeight div SpritesData[sprite].Height;
     row:= Frame mod numFramesFirstCol;
     col:= Frame div numFramesFirstCol;
     
-    copyToXY(SpritesData[sprite].Surface, dest, 
+    copyToXYFromRect(SpritesData[sprite].Surface, dest, 
              col*SpritesData[sprite].Width, 
              row*SpritesData[sprite].Height, 
              SpritesData[sprite].Width, 
@@ -250,10 +250,10 @@
 
 function RenderStringTex(s: ansistring; Color: Longword; font: THWFont): PTexture;
 begin
-    RenderStringTex:= RenderStringTex(s, Color, font, 0);
+    RenderStringTex:= RenderStringTexLim(s, Color, font, 0);
 end;
 
-function RenderStringTex(s: ansistring; Color: Longword; font: THWFont; maxLength: LongWord): PTexture;
+function RenderStringTexLim(s: ansistring; Color: Longword; font: THWFont; maxLength: LongWord): PTexture;
 var w, h: LongInt;
     finalSurface: PSDL_Surface;
 begin
@@ -272,7 +272,7 @@
 
     TryDo(SDL_SetColorKey(finalSurface, SDL_SRCCOLORKEY, 0) = 0, errmsgTransparentSet, true);
 
-    RenderStringTex:= Surface2Tex(finalSurface, false);
+    RenderStringTexLim:= Surface2Tex(finalSurface, false);
 
     SDL_FreeSurface(finalSurface);
 end;
--- a/hedgewars/uScript.pas	Thu May 03 15:34:26 2012 +0200
+++ b/hedgewars/uScript.pas	Thu May 03 22:48:02 2012 +0200
@@ -1103,7 +1103,7 @@
     else begin
         gear := GearByUID(lua_tointeger(L, 1));
         if (gear <> nil) and (gear^.Hedgehog <> nil) then
-            gear^.Hedgehog^.Effects[THogEffect(lua_tointeger(L, 2))]:= lua_toboolean(L, 3);
+            gear^.Hedgehog^.Effects[THogEffect(lua_tointeger(L, 2))]:= lua_tointeger(L, 3);
     end;
     lc_seteffect := 0;
 end;
@@ -1118,9 +1118,9 @@
         begin
         gear:= GearByUID(lua_tointeger(L, 1));
         if (gear <> nil) and (gear^.Hedgehog <> nil) then
-            lua_pushboolean(L, gear^.Hedgehog^.Effects[THogEffect(lua_tointeger(L, 2))])
+            lua_pushinteger(L, gear^.Hedgehog^.Effects[THogEffect(lua_tointeger(L, 2))])
         else
-            lua_pushboolean(L, false)
+            lua_pushinteger(L, 0)
         end;
     lc_geteffect:= 1
 end;
--- a/hedgewars/uStore.pas	Thu May 03 15:34:26 2012 +0200
+++ b/hedgewars/uStore.pas	Thu May 03 22:48:02 2012 +0200
@@ -133,7 +133,7 @@
 for t:= 0 to Pred(TeamsCount) do
     with TeamsArray[t]^ do
         begin
-        NameTagTex:= RenderStringTex(TeamName, Clan^.Color, Font, cTeamHealthWidth);
+        NameTagTex:= RenderStringTexLim(TeamName, Clan^.Color, Font, cTeamHealthWidth);
 
         r.w:= cTeamHealthWidth + 5;
         r.h:= NameTagTex^.h;
@@ -199,7 +199,7 @@
             with Hedgehogs[i] do
                 if Gear <> nil then
                     begin
-                    NameTagTex:= RenderStringTex(Name, Clan^.Color, fnt16, cTeamHealthWidth);
+                    NameTagTex:= RenderStringTexLim(Name, Clan^.Color, fnt16, cTeamHealthWidth);
                     if Hat <> 'NoHat' then
                         begin
                         if (Length(Hat) > 39) and (Copy(Hat,1,8) = 'Reserved') and (Copy(Hat,9,32) = PlayerHash) then
--- a/hedgewars/uTeams.pas	Thu May 03 15:34:26 2012 +0200
+++ b/hedgewars/uTeams.pas	Thu May 03 22:48:02 2012 +0200
@@ -384,7 +384,7 @@
             begin
             Hedgehogs[0].King:= true;
             Hedgehogs[0].Hat:= 'crown';
-            Hedgehogs[0].Effects[hePoisoned] := false;
+            Hedgehogs[0].Effects[hePoisoned] := 0;
             h:= Hedgehogs[0].Gear^.Health;
             Hedgehogs[0].Gear^.Health:= hwRound(int2hwFloat(th)*_0_375);
             if Hedgehogs[0].Gear^.Health > h then
--- a/hedgewars/uTypes.pas	Thu May 03 15:34:26 2012 +0200
+++ b/hedgewars/uTypes.pas	Thu May 03 22:48:02 2012 +0200
@@ -102,7 +102,7 @@
             gtSniperRifleShot, gtJetpack, gtMolotov, gtBirdy, // 44
             gtEgg, gtPortal, gtPiano, gtGasBomb, gtSineGunShot, gtFlamethrower, // 50
             gtSMine, gtPoisonCloud, gtHammer, gtHammerHit, gtResurrector, // 55
-            gtNapalmBomb, gtSnowball, gtFlake, gtStructure, gtLandGun, gtTardis); // 61
+            gtNapalmBomb, gtSnowball, gtFlake, gtStructure, gtLandGun, gtTardis, gtIceGun); // 62
 
     // Gears that are _only_ of visual nature (e.g. background stuff, visual effects, speechbubbles, etc.)
     TVisualGearType = (vgtFlake, vgtCloud, vgtExplPart, vgtExplPart2, vgtFire,
@@ -150,7 +150,7 @@
             amRCPlane, amLowGravity, amExtraDamage, amInvulnerable, amExtraTime, // 35
             amLaserSight, amVampiric, amSniperRifle, amJetpack, amMolotov, amBirdy, amPortalGun, // 42
             amPiano, amGasBomb, amSineGun, amFlamethrower, amSMine, amHammer, // 48
-            amResurrector, amDrillStrike, amSnowball, amTardis, amStructure, amLandGun); // 54
+            amResurrector, amDrillStrike, amSnowball, amTardis, amStructure, amLandGun, amIceGun); // 54
 
     // Different kind of crates that e.g. hedgehogs can pick up
     TCrateType = (HealthCrate, AmmoCrate, UtilityCrate);
@@ -209,7 +209,7 @@
             PrevTexture, NextTexture: PTexture;
             end;
 
-    THogEffect = (heInvulnerable, heResurrectable, hePoisoned, heResurrected);
+    THogEffect = (heInvulnerable, heResurrectable, hePoisoned, heResurrected, heFrozen);
 
     TScreenFade = (sfNone, sfInit, sfToBlack, sfFromBlack, sfToWhite, sfFromWhite);
 
@@ -326,7 +326,7 @@
     THHAmmo = array[0..cMaxSlotIndex, 0..cMaxSlotAmmoIndex] of TAmmo;
 
     THedgehog = record
-            Name: string[192];
+            Name: shortstring;
             Gear: PGear;
             GearHidden: PGear;
             SpeechGear: PVisualGear;
@@ -347,12 +347,12 @@
             King: boolean;  // Flag for a bunch of hedgehog attributes
             Unplaced: boolean;  // Flag for hog placing mode
             Timer: Longword;
-            Effects: array[THogEffect] of boolean;
+            Effects: array[THogEffect] of LongInt;
             end;
 
     TTeam = record
             Clan: PClan;
-            TeamName: string[192];
+            TeamName: shortstring;
             ExtDriven: boolean;
             Binds: TBinds;
             Hedgehogs: array[0..cMaxHHIndex] of THedgehog;
@@ -400,7 +400,8 @@
             sidLowGravity, sidExtraDamage, sidInvulnerable, sidExtraTime,
             sidLaserSight, sidVampiric, sidSniperRifle, sidJetpack,
             sidMolotov, sidBirdy, sidPortalGun, sidPiano, sidGasBomb, sidSineGun, sidFlamethrower,
-            sidSMine, sidHammer, sidResurrector, sidDrillStrike, sidSnowball, sidNothing, sidTardis, sidStructure, sidLandGun);
+            sidSMine, sidHammer, sidResurrector, sidDrillStrike, sidSnowball, sidNothing, sidTardis, 
+	    sidStructure, sidLandGun, sidIceGun);
 
     TMsgStrId = (sidStartFight, sidDraw, sidWinner, sidVolume, sidPaused,
             sidConfirm, sidSuddenDeath, sidRemaining, sidFuel, sidSync,
--- a/hedgewars/uVariables.pas	Thu May 03 15:34:26 2012 +0200
+++ b/hedgewars/uVariables.pas	Thu May 03 22:48:02 2012 +0200
@@ -2305,6 +2305,31 @@
             PosCount: 1;
             PosSprite: sprWater;
             ejectX: 0; //20;
+            ejectY: -3),
+// Freezer
+            (NameId: sidIceGun;
+            NameTex: nil;
+            Probability: 20;
+            NumberInCase: 1;
+            Ammo: (Propz: ammoprop_ForwMsgs or 
+                          ammoprop_NeedUpDown or
+                          ammoprop_DontHold;
+                Count: 1;
+                NumPerTurn: 0;
+                Timer: 5001;
+                Pos: 0;
+                AmmoType: amFlamethrower;
+                AttackVoice: sndNone;
+                Bounciness: 1000);
+            Slot: 2;
+            TimeAfterTurn: 0;
+            minAngle: 0;
+            maxAngle: 0;
+            isDamaging: true;
+            SkipTurns: 0;
+            PosCount: 1;
+            PosSprite: sprWater;
+            ejectX: 0; //20;
             ejectY: -3)
         );
 
@@ -2372,6 +2397,7 @@
 (*      gtStructure *) , amStructure  // TODO - This will undoubtedly change once there is more than one structure
 (*        gtLandGun *) , amLandGun
 (*         gtTardis *) , amTardis
+(*         gtIceGun *) , amIceGun
     );
 
 var
--- a/hedgewars/uWorld.pas	Thu May 03 15:34:26 2012 +0200
+++ b/hedgewars/uWorld.pas	Thu May 03 22:48:02 2012 +0200
@@ -447,16 +447,16 @@
                     AMFrame:= LongInt(Ammo^[i,t].AmmoType) - 1;
                     if STurns >= 0 then //weapon not usable yet, draw grayed out with turns remaining
                         begin
-                        DrawSprite2Surf(sprAMAmmosBW, amSurface, x + AMSlotPadding, 
+                        DrawSpriteFrame2Surf(sprAMAmmosBW, amSurface, x + AMSlotPadding, 
                                                                  y + AMSlotPadding, AMFrame);
                         if STurns < 100 then
-                            DrawSprite2Surf(sprTurnsLeft, amSurface, 
-			    	    x + AMSlotSize-16, 
-				    y + AMSlotSize + 1 - 16, STurns);
+                            DrawSpriteFrame2Surf(sprTurnsLeft, amSurface, 
+                                x + AMSlotSize-16, 
+                                y + AMSlotSize + 1 - 16, STurns);
                         end
                     else //draw colored version
                         begin
-                        DrawSprite2Surf(sprAMAmmos, amSurface, x + AMSlotPadding, 
+                        DrawSpriteFrame2Surf(sprAMAmmos, amSurface, x + AMSlotPadding, 
                                                                y + AMSlotPadding, AMFrame);
                         end;
 {$IFDEF USE_LANDSCAPE_AMMOMENU}
@@ -479,10 +479,10 @@
 DrawLine2Surf(amSurface, BORDERSIZE, i * (AMSlotSize+1)+1, AMRect.w + BORDERSIZE, i * (AMSlotSize+1)+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);
+DrawSpriteFrame2Surf(sprAMCorners, amSurface, 0                    , 0                    , 0);
+DrawSpriteFrame2Surf(sprAMCorners, amSurface, AMRect.w + BORDERSIZE, AMRect.y             , 1);
+DrawSpriteFrame2Surf(sprAMCorners, amSurface, AMRect.x             , AMRect.h + BORDERSIZE, 2);
+DrawSpriteFrame2Surf(sprAMCorners, amSurface, AMRect.w + BORDERSIZE, AMRect.h + BORDERSIZE, 3);
 
 for i:=0 to BORDERSIZE-1 do
 begin
@@ -1107,7 +1107,7 @@
 var i, t, h: LongInt;
     r: TSDL_Rect;
     tdx, tdy: Double;
-    s: string[15];
+    s: shortstring;
     highlight: Boolean;
     smallScreenOffset, offsetX, offsetY, screenBottom: LongInt;
     VertexBuffer: array [0..3] of TVertex2f;
@@ -1464,7 +1464,7 @@
         inc(CountTicks, Lag);
     if (GameType = gmtDemo) and (CountTicks >= 1000) then
         begin
-        i:=GameTicks div 1000;
+        i:= GameTicks div 1000;
         t:= i mod 60;
         s:= inttostr(t);
         if t < 10 then
--- a/share/hedgewars/Data/Locale/en.txt	Thu May 03 15:34:26 2012 +0200
+++ b/share/hedgewars/Data/Locale/en.txt	Thu May 03 22:48:02 2012 +0200
@@ -56,6 +56,7 @@
 00:53=TimeBox
 00:54=Structure
 00:55=Land Spray
+00:56=Freezer
 
 01:00=Let's fight!
 01:01=Round draw