merge from default flibqtfrontend
authorunc0rr
Tue, 04 Dec 2012 09:15:55 +0400
branchflibqtfrontend
changeset 8208 171da01bd04d
parent 8141 6482875b0d97 (current diff)
parent 8206 1633a6510834 (diff)
child 8210 ad178654142a
merge from default
QTfrontend/CMakeLists.txt
QTfrontend/hwconsts.h
QTfrontend/net/newnetclient.cpp
hedgewars/uMobile.pas
misc/physfs/CMakeLists.txt
project_files/hedgewars.pro
share/hedgewars/Data/Graphics/AmmoMenu/Ammos@2x.png
share/hedgewars/Data/Graphics/AmmoMenu/Ammos_bw@2x.png
share/hedgewars/Data/Graphics/AmmoMenu/BorderHorizontal.png
share/hedgewars/Data/Graphics/AmmoMenu/BorderVertical.png
--- a/CMakeLists.txt	Fri Nov 30 18:19:52 2012 +0400
+++ b/CMakeLists.txt	Tue Dec 04 09:15:55 2012 +0400
@@ -2,11 +2,11 @@
 
 #initialise cmake environment
 cmake_minimum_required(VERSION 2.6.0)
-FOREACH(hwpolicy CMP0003 CMP0012 CMP0017)
-    IF(POLICY ${hwpolicy})
-        CMAKE_POLICY(SET ${hwpolicy} NEW)
-    ENDIF()
-ENDFOREACH()
+foreach(hwpolicy CMP0003 CMP0012 CMP0017)
+    if(POLICY ${hwpolicy})
+        cmake_policy(SET ${hwpolicy} NEW)
+    endif()
+endforeach()
 #use available modules, fallback to ours if not present (CMP0017 helps)
 set(CMAKE_MODULE_PATH "${CMAKE_ROOT}/Modules" "${CMAKE_CURRENT_SOURCE_DIR}/cmake_modules")
 
@@ -27,34 +27,34 @@
 
 
 #detect Mercurial revision (if present)
-IF(NOT NOREVISION)
+if(NOT NOREVISION)
     set(default_build_type "DEBUG")
     set(version_suffix "-development_version")
     set(HW_DEV true)
-    FIND_PROGRAM(HGCOMMAND hg)
-    IF(HGCOMMAND AND (EXISTS ${CMAKE_SOURCE_DIR}/.hg))
+    find_program(HGCOMMAND hg)
+    if(HGCOMMAND AND (EXISTS ${CMAKE_SOURCE_DIR}/.hg))
         execute_process(COMMAND ${HGCOMMAND} identify -in
                         WORKING_DIRECTORY ${CMAKE_SOURCE_DIR}
                         OUTPUT_VARIABLE internal_version
                         ERROR_QUIET
                     )
         #check local repo status
-        STRING(REGEX REPLACE "[^+]" "" HGCHANGED ${internal_version})
+        string(REGEX REPLACE "[^+]" "" HGCHANGED ${internal_version})
 
-        STRING(REGEX REPLACE "[0-9a-zA-Z]+(.*) ([0-9]+)(.*)" "\\2" revision_number ${internal_version})
-        STRING(REGEX REPLACE "([0-9a-zA-Z]+)(.*) [0-9]+(.*)" "\\1" revision_hash ${internal_version})
+        string(REGEX REPLACE "[0-9a-zA-Z]+(.*) ([0-9]+)(.*)" "\\2" revision_number ${internal_version})
+        string(REGEX REPLACE "([0-9a-zA-Z]+)(.*) [0-9]+(.*)" "\\1" revision_hash ${internal_version})
 
-        MESSAGE(STATUS "Building revision ${revision_number} from hash ${revision_hash} ${HGCHANGED}")
-        IF(HGCHANGED)
+        message(STATUS "Building revision ${revision_number} from hash ${revision_hash} ${HGCHANGED}")
+        if(HGCHANGED)
             MESSAGE(WARNING "Notice: you have uncommitted changes in your repository")
-        ENDIF()
+        endif()
         set(version_suffix "-${revision_number}${HGCHANGED}")
-    ENDIF()
-ELSE(NOT NOREVISION)
+    endif()
+else(NOT NOREVISION)
     set(default_build_type "RELEASE")
     set(HWDEV false)
-    MESSAGE(STATUS "Building distributable version")
-ENDIF(NOT NOREVISION)
+    message(STATUS "Building distributable version")
+endif(NOT NOREVISION)
 
 
 #versioning
--- a/INSTALL	Fri Nov 30 18:19:52 2012 +0400
+++ b/INSTALL	Tue Dec 04 09:15:55 2012 +0400
@@ -8,7 +8,7 @@
  - SDL_image >= 1.2
  - SDL_ttf >= 2.0
  - Lua >= 5.1.0
- - Physfs >= 2.0
+ - Physfs >= 2.1
 For server:
  - Glasgow Haskell Compiler >= 6.10
  - bytestring-show package
@@ -20,7 +20,7 @@
 For compressed screenshots:
  - libpng
 
-Lua and Physfs will be automatically built if not found.
+Lua will be automatically built if not found.
 
 
 1. Configure:
--- a/QTfrontend/CMakeLists.txt	Fri Nov 30 18:19:52 2012 +0400
+++ b/QTfrontend/CMakeLists.txt	Tue Dec 04 09:15:55 2012 +0400
@@ -20,6 +20,9 @@
 find_package(SDL_net REQUIRED)   #network frontlib
 if(NOT NOVIDEOREC)
     find_package(FFMPEG)
+    if(${FFMPEG_FOUND})
+        add_definitions(-DVIDEOREC -D__STDC_CONSTANT_MACROS)
+    endif()
 endif()
 
 include_directories(.)
@@ -66,10 +69,6 @@
 file(GLOB_RECURSE UIcpp ui/*.cpp)
 file(GLOB UtilCpp util/*.cpp)
 
-if(${FFMPEG_FOUND})
-    add_definitions(-DVIDEOREC -D__STDC_CONSTANT_MACROS)
-endif()
-
 set(hwfr_src
     ${ModelCpp}
     ${NetCpp}
--- a/QTfrontend/binds.cpp	Fri Nov 30 18:19:52 2012 +0400
+++ b/QTfrontend/binds.cpp	Tue Dec 04 09:15:55 2012 +0400
@@ -66,5 +66,7 @@
     {"fullscr",   "f12",        QT_TRANSLATE_NOOP("binds", "change mode"),     NULL, QT_TRANSLATE_NOOP("binds (descriptions)", "Toggle fullscreen mode:")},
     {"capture",   "c",          QT_TRANSLATE_NOOP("binds", "capture"),         NULL, QT_TRANSLATE_NOOP("binds (descriptions)", "Take a screenshot:")},
     {"rotmask",   "delete",     QT_TRANSLATE_NOOP("binds", "hedgehogs\ninfo"), NULL, QT_TRANSLATE_NOOP("binds (descriptions)", "Toggle labels above hedgehogs:")},
+#ifdef VIDEOREC
     {"record",    "r",          QT_TRANSLATE_NOOP("binds", "record"),          NULL, QT_TRANSLATE_NOOP("binds (descriptions)", "Record video:")}
+#endif
 };
--- a/QTfrontend/binds.h	Fri Nov 30 18:19:52 2012 +0400
+++ b/QTfrontend/binds.h	Tue Dec 04 09:15:55 2012 +0400
@@ -21,7 +21,11 @@
 
 #include <QString>
 
+#ifdef VIDEOREC
 #define BINDS_NUMBER 46
+#else
+#define BINDS_NUMBER 45
+#endif
 
 struct BindAction
 {
--- a/QTfrontend/gameuiconfig.cpp	Fri Nov 30 18:19:52 2012 +0400
+++ b/QTfrontend/gameuiconfig.cpp	Tue Dec 04 09:15:55 2012 +0400
@@ -94,11 +94,13 @@
     Form->ui.pageOptions->editNetPassword->installEventFilter(this);
 
     int passLength = value("net/passwordlength", 0).toInt();
-    setNetPasswordLength(passLength);
-    if (savePwd == false) {
-        Form->ui.pageOptions->editNetPassword->setEnabled(savePwd);
+    if (!savePwd) {
+        Form->ui.pageOptions->editNetPassword->setEnabled(false);
         Form->ui.pageOptions->editNetPassword->setText("");
         setNetPasswordLength(0);
+    } else
+    {
+        setNetPasswordLength(passLength);
     }
 
     delete netHost;
@@ -139,26 +141,34 @@
 
 void GameUIConfig::reloadVideosValues(void)
 {
-    Form->ui.pageVideos->framerateBox->setValue(value("videorec/fps",25).toUInt());
-    Form->ui.pageVideos->bitrateBox->setValue(value("videorec/bitrate",400).toUInt());
-    bool useGameRes = value("videorec/usegameres",true).toBool();
+    // one pass with default values
+    Form->ui.pageOptions->setDefaultOptions();
+
+    // then load user configuration
+    Form->ui.pageOptions->framerateBox->setCurrentIndex(
+            Form->ui.pageOptions->framerateBox->findData(
+                        value("videorec/framerate", rec_Framerate()).toString() + " fps",
+                    Qt::MatchExactly) );
+    Form->ui.pageOptions->bitrateBox->setValue(value("videorec/bitrate", rec_Bitrate()).toUInt());
+    bool useGameRes = value("videorec/usegameres",Form->ui.pageOptions->checkUseGameRes->isChecked()).toBool();
     if (useGameRes)
     {
         QRect res = vid_Resolution();
-        Form->ui.pageVideos->widthEdit->setText(QString::number(res.width()));
-        Form->ui.pageVideos->heightEdit->setText(QString::number(res.height()));
+        Form->ui.pageOptions->widthEdit->setText(QString::number(res.width()));
+        Form->ui.pageOptions->heightEdit->setText(QString::number(res.height()));
     }
     else
     {
-        Form->ui.pageVideos->widthEdit->setText(value("videorec/width","800").toString());
-        Form->ui.pageVideos->heightEdit->setText(value("videorec/height","600").toString());
+        Form->ui.pageOptions->widthEdit->setText(value("videorec/width","800").toString());
+        Form->ui.pageOptions->heightEdit->setText(value("videorec/height","600").toString());
     }
-    Form->ui.pageVideos->checkUseGameRes->setChecked(useGameRes);
-    Form->ui.pageVideos->checkRecordAudio->setChecked(value("videorec/audio",true).toBool());
-    if (!Form->ui.pageVideos->tryCodecs(value("videorec/format","no").toString(),
+    Form->ui.pageOptions->checkUseGameRes->setChecked(useGameRes);
+    Form->ui.pageOptions->checkRecordAudio->setChecked(
+            value("videorec/audio",Form->ui.pageOptions->checkRecordAudio->isChecked()).toBool() );
+    if (!Form->ui.pageOptions->tryCodecs(value("videorec/format","no").toString(),
                                         value("videorec/videocodec","no").toString(),
                                         value("videorec/audiocodec","no").toString()))
-        Form->ui.pageVideos->setDefaultCodecs();
+        Form->ui.pageOptions->setDefaultCodecs();
 }
 
 QStringList GameUIConfig::GetTeamsList()
@@ -177,7 +187,16 @@
 
 void GameUIConfig::resizeToConfigValues()
 {
-    Form->resize(value("frontend/width", 800).toUInt(), value("frontend/height", 600).toUInt());
+    // fill 2/3 of the screen desktop
+    const QRect deskSize = QApplication::desktop()->screenGeometry(-1);
+    Form->resize(value("frontend/width", deskSize.width()*2/3).toUInt(),
+                 value("frontend/height", deskSize.height()*2/3).toUInt());
+
+    // move the window to the center of the screen
+    QPoint center = QApplication::desktop()->availableGeometry(-1).center();
+    center.setX(center.x() - (Form->width()/2));
+    center.setY(center.y() - (Form->height()/2));
+    Form->move(center);
 }
 
 void GameUIConfig::SaveOptions()
@@ -270,7 +289,7 @@
             setValue(QString("colors/color%1").arg(i), model->item(i)->data());
     }
 
-    Form->gameSettings->sync();
+    sync();
 }
 
 void GameUIConfig::SaveVideosOptions()
@@ -279,14 +298,19 @@
     setValue("videorec/format", AVFormat());
     setValue("videorec/videocodec", videoCodec());
     setValue("videorec/audiocodec", audioCodec());
-    setValue("videorec/fps", rec_Framerate());
+    setValue("videorec/framerate", rec_Framerate());
     setValue("videorec/bitrate", rec_Bitrate());
     setValue("videorec/width", res.width());
     setValue("videorec/height", res.height());
-    setValue("videorec/usegameres", Form->ui.pageVideos->checkUseGameRes->isChecked());
+    setValue("videorec/usegameres", Form->ui.pageOptions->checkUseGameRes->isChecked());
     setValue("videorec/audio", recordAudio());
 
-    Form->gameSettings->sync();
+    sync();
+}
+
+void GameUIConfig::setValue(const QString &key, const QVariant &value)
+{
+    QSettings::setValue(key, value);
 }
 
 QString GameUIConfig::language()
@@ -447,7 +471,7 @@
 
 bool GameUIConfig::netPasswordIsValid()
 {
-    return (netPasswordLength() == 0 || Form->ui.pageOptions->editNetPassword->text() != QString(netPasswordLength(), '\0'));
+    return (netPasswordLength() == 0 || Form->ui.pageOptions->editNetPassword->text() != QString(netPasswordLength(), '*'));
 }
 
 // When hedgewars launches, the password field is set with null characters. If the user tries to edit the field and there are such characters, then clear the field
@@ -472,7 +496,7 @@
 {
     if (passwordLength > 0)
     {
-        Form->ui.pageOptions->editNetPassword->setText(QString(passwordLength, '\0'));
+        Form->ui.pageOptions->editNetPassword->setText(QString(passwordLength, '*'));
     }
     else
     {
@@ -487,40 +511,43 @@
 
 QString GameUIConfig::AVFormat()
 {
-    return Form->ui.pageVideos->format();
+    return Form->ui.pageOptions->format();
 }
 
 QString GameUIConfig::videoCodec()
 {
-    return Form->ui.pageVideos->videoCodec();
+    return Form->ui.pageOptions->videoCodec();
 }
 
 QString GameUIConfig::audioCodec()
 {
-    return Form->ui.pageVideos->audioCodec();
+    return Form->ui.pageOptions->audioCodec();
 }
 
 QRect GameUIConfig::rec_Resolution()
 {
-    if (Form->ui.pageVideos->checkUseGameRes->isChecked())
+    if (Form->ui.pageOptions->checkUseGameRes->isChecked())
         return vid_Resolution();
     QRect res(0,0,0,0);
-    res.setWidth(Form->ui.pageVideos->widthEdit->text().toUInt());
-    res.setHeight(Form->ui.pageVideos->heightEdit->text().toUInt());
+    res.setWidth(Form->ui.pageOptions->widthEdit->text().toUInt());
+    res.setHeight(Form->ui.pageOptions->heightEdit->text().toUInt());
     return res;
 }
 
 int GameUIConfig::rec_Framerate()
 {
-    return Form->ui.pageVideos->framerateBox->value();
+    // remove the "fps" label
+    QString fpsText = Form->ui.pageOptions->framerateBox->currentText();
+    QStringList fpsList = fpsText.split(" ");
+    return fpsList.first().toInt();
 }
 
 int GameUIConfig::rec_Bitrate()
 {
-    return Form->ui.pageVideos->bitrateBox->value();
+    return Form->ui.pageOptions->bitrateBox->value();
 }
 
 bool GameUIConfig::recordAudio()
 {
-    return Form->ui.pageVideos->checkRecordAudio->isChecked();
+    return Form->ui.pageOptions->checkRecordAudio->isChecked();
 }
--- a/QTfrontend/gameuiconfig.h	Fri Nov 30 18:19:52 2012 +0400
+++ b/QTfrontend/gameuiconfig.h	Tue Dec 04 09:15:55 2012 +0400
@@ -58,6 +58,7 @@
         bool isFrontendFullscreen() const;
         void resizeToConfigValues();
         quint32 stereoMode() const;
+        void setValue(const QString & key, const QVariant & value);
 
         QString AVFormat();
         QString videoCodec();
--- a/QTfrontend/hwconsts.h	Fri Nov 30 18:19:52 2012 +0400
+++ b/QTfrontend/hwconsts.h	Tue Dec 04 09:15:55 2012 +0400
@@ -63,40 +63,40 @@
 
 #define HEDGEHOGS_PER_TEAM           8
 
-#define AMMOLINE_DEFAULT_QT     "93919294221991210322351110012010000002111101010111110101"
-#define AMMOLINE_DEFAULT_PROB   "04050405416006555465544647765766666661555101011154110101"
-#define AMMOLINE_DEFAULT_DELAY  "00000000000002055000000400070040000000002200000006000000"
-#define AMMOLINE_DEFAULT_CRATE  "13111103121111111231141111111111111112111111011111110101"
+#define AMMOLINE_DEFAULT_QT     "9391929422199121032235111001201000000211110101011111101"
+#define AMMOLINE_DEFAULT_PROB   "0405040541600655546554464776576666666155510101115411101"
+#define AMMOLINE_DEFAULT_DELAY  "0000000000000205500000040007004000000000220000000600000"
+#define AMMOLINE_DEFAULT_CRATE  "1311110312111111123114111111111111111211111101111111101"
 
-#define AMMOLINE_CRAZY_QT       "99999999999999999929999999999999992999999999099999920909"
-#define AMMOLINE_CRAZY_PROB     "11111101111111111111111111111111111111111111011111110101"
-#define AMMOLINE_CRAZY_DELAY    "00000000000000000000000000000000000000000000000000000000"
-#define AMMOLINE_CRAZY_CRATE    "13111103121111111231141111111111111112111101011111110101"
+#define AMMOLINE_CRAZY_QT       "9999999999999999992999999999999999299999999909999992909"
+#define AMMOLINE_CRAZY_PROB     "1111110111111111111111111111111111111111111101111111101"
+#define AMMOLINE_CRAZY_DELAY    "0000000000000000000000000000000000000000000000000000000"
+#define AMMOLINE_CRAZY_CRATE    "1311110312111111123114111111111111111211110101111111101"
 
-#define AMMOLINE_PROMODE_QT     "90900090000000000000090000000000000000000000000000000000"
-#define AMMOLINE_PROMODE_PROB   "00000000000000000000000000000000000000000000000000000000"
-#define AMMOLINE_PROMODE_DELAY  "00000000000002055000000400070040000000002000000000000002"
-#define AMMOLINE_PROMODE_CRATE  "11111111111111111111111111111111111111111001011111110101"
+#define AMMOLINE_PROMODE_QT     "9090009000000000000009000000000000000000000000000000000"
+#define AMMOLINE_PROMODE_PROB   "0000000000000000000000000000000000000000000000000000000"
+#define AMMOLINE_PROMODE_DELAY  "0000000000000205500000040007004000000000200000000000002"
+#define AMMOLINE_PROMODE_CRATE  "1111111111111111111111111111111111111111100101111111101"
 
-#define AMMOLINE_SHOPPA_QT      "00000099000000000000000000000000000000000000000000000000"
-#define AMMOLINE_SHOPPA_PROB    "44444100442444022101121212224220000000020004000100110001"
-#define AMMOLINE_SHOPPA_DELAY   "00000000000000000000000000000000000000000000000000000000"
-#define AMMOLINE_SHOPPA_CRATE   "11111111111111111111111111111111111111111011011111110001"
+#define AMMOLINE_SHOPPA_QT      "0000009900000000000000000000000000000000000000000000000"
+#define AMMOLINE_SHOPPA_PROB    "4444410044244402210112121222422000000002000400010011001"
+#define AMMOLINE_SHOPPA_DELAY   "0000000000000000000000000000000000000000000000000000000"
+#define AMMOLINE_SHOPPA_CRATE   "1111111111111111111111111111111111111111101101111111001"
 
-#define AMMOLINE_CLEAN_QT       "10100090000100000110000000000000000000000000000010000000"
-#define AMMOLINE_CLEAN_PROB     "04050405416006555465544647765766666661555101011154110101"
-#define AMMOLINE_CLEAN_DELAY    "00000000000000000000000000000000000000000000000000000000"
-#define AMMOLINE_CLEAN_CRATE    "13111103121111111231141111111111111112111111011111110101"
+#define AMMOLINE_CLEAN_QT       "1010009000010000011000000000000000000000000000001000000"
+#define AMMOLINE_CLEAN_PROB     "0405040541600655546554464776576666666155510101115411101"
+#define AMMOLINE_CLEAN_DELAY    "0000000000000000000000000000000000000000000000000000000"
+#define AMMOLINE_CLEAN_CRATE    "1311110312111111123114111111111111111211111101111111101"
 
-#define AMMOLINE_MINES_QT       "00000099000900000003000000000000000000000000000000000000"
-#define AMMOLINE_MINES_PROB     "00000000000000000000000000000000000000000000000000000000"
-#define AMMOLINE_MINES_DELAY    "00000000000002055000000400070040000000002000000006000000"
-#define AMMOLINE_MINES_CRATE    "11111111111111111111111111111111111111111111011111110101"
+#define AMMOLINE_MINES_QT       "0000009900090000000300000000000000000000000000000000000"
+#define AMMOLINE_MINES_PROB     "0000000000000000000000000000000000000000000000000000000"
+#define AMMOLINE_MINES_DELAY    "0000000000000205500000040007004000000000200000000600000"
+#define AMMOLINE_MINES_CRATE    "1111111111111111111111111111111111111111111101111111101"
 
-#define AMMOLINE_PORTALS_QT     "90000090020000000021000000000000001100000900000000000000"
-#define AMMOLINE_PORTALS_PROB   "04050405416006555465544647765766666661555101011154110101"
-#define AMMOLINE_PORTALS_DELAY  "00000000000002055000000400070040000000002000000006000000"
-#define AMMOLINE_PORTALS_CRATE  "13111103121111111231141111111111111112111111011111110101"
+#define AMMOLINE_PORTALS_QT     "9000009002000000002100000000000000110000090000000000000"
+#define AMMOLINE_PORTALS_PROB   "0405040541600655546554464776576666666155510101115411101"
+#define AMMOLINE_PORTALS_DELAY  "0000000000000205500000040007004000000000200000000600000"
+#define AMMOLINE_PORTALS_CRATE  "1311110312111111123114111111111111111211111101111111101"
 
 //Different seasons; assigned to season (int)
 #define SEASON_NONE 0
--- a/QTfrontend/hwform.cpp	Fri Nov 30 18:19:52 2012 +0400
+++ b/QTfrontend/hwform.cpp	Tue Dec 04 09:15:55 2012 +0400
@@ -111,7 +111,6 @@
 QString playerHash;
 
 GameUIConfig* HWForm::config = NULL;
-QSettings* HWForm::gameSettings = NULL;
 
 HWForm::HWForm(QWidget *parent, QString styleSheet)
     : QMainWindow(parent)
@@ -127,10 +126,6 @@
 #ifdef USE_XFIRE
     xfire_init();
 #endif
-    gameSettings = new QSettings("physfs://hedgewars.ini", QSettings::IniFormat);
-    frontendEffects = gameSettings->value("frontend/effects", true).toBool();
-    playerHash = QString(QCryptographicHash::hash(gameSettings->value("net/nick","").toString().toUtf8(), QCryptographicHash::Md5).toHex());
-
     this->setStyleSheet(styleSheet);
     ui.setupUi(this);
     setMinimumSize(760, 580);
@@ -140,8 +135,16 @@
     ui.pageOptions->CBResolution->addItems(SDLInteraction::instance().getResolutions());
 
     config = new GameUIConfig(this, "physfs://hedgewars.ini");
+    frontendEffects = config->value("frontend/effects", true).toBool();
+    playerHash = QString(QCryptographicHash::hash(config->value("net/nick","").toString().toUtf8(), QCryptographicHash::Md5).toHex());
 
+    ui.pageRoomsList->setSettings(config);
+    ui.pageNetGame->chatWidget->setSettings(config);
+    ui.pageRoomsList->chatWidget->setSettings(config);
+#ifdef VIDEOREC
     ui.pageVideos->init(config);
+    ui.pageOptions->setConfig(config);
+#endif
 
 #ifdef __APPLE__
     panel = new M3Panel;
@@ -439,23 +442,27 @@
     }
 }
 
-void HWForm::UpdateTeamsLists(const QStringList* editable_teams)
+void HWForm::UpdateTeamsLists()
 {
-    QStringList teamslist;
-    if(editable_teams)
-    {
-        teamslist =* editable_teams;
-    }
-    else
-    {
-        teamslist = config->GetTeamsList();
-    }
+    QStringList teamslist = config->GetTeamsList();
 
     if(teamslist.empty())
     {
-        HWTeam defaultTeam(tr("DefaultTeam"));
+        QString currentNickName = config->value("net/nick","").toString().toUtf8();
+        QString teamName;
+
+        if (currentNickName.isEmpty())
+        {
+            teamName = tr("DefaultTeam");
+        }
+        else
+        {
+            teamName = tr("%1's Team").arg(currentNickName);
+        }
+
+        HWTeam defaultTeam(teamName);
         defaultTeam.saveToFile();
-        teamslist.push_back(tr("DefaultTeam"));
+        teamslist.push_back(teamName);
     }
 
     ui.pageOptions->CBTeamName->clear();
@@ -531,6 +538,69 @@
 #ifdef USE_XFIRE
     updateXfire();
 #endif
+    
+    QString openPrefix = "Debug:   (PAGE_OPENED: ";
+    QString openSuffix = ")";
+    QString closePrefix = "Debug:   (PAGE_LEFT: ";
+    QString closeSuffix = ")";
+    
+    switch (lastid) { //Print the id of the page we're leaving      
+      case ID_PAGE_SETUP_TEAM :	qDebug("%sPAGE_SETUP_TEAM%s", qPrintable(closePrefix), qPrintable(closeSuffix)); 	break;      
+      case ID_PAGE_SETUP :		qDebug("%sPAGE_SETUP%s", qPrintable(closePrefix), qPrintable(closeSuffix));		break;      
+      case ID_PAGE_MULTIPLAYER :	qDebug("%sPAGE_MULTIPLAYER%s", qPrintable(closePrefix), qPrintable(closeSuffix));	break;      
+      case ID_PAGE_DEMOS :		qDebug("%sPAGE_DEMOS%s", qPrintable(closePrefix), qPrintable(closeSuffix));		break;      
+      case ID_PAGE_NET :		qDebug("%sPAGE_NET%s", qPrintable(closePrefix), qPrintable(closeSuffix));		break;      
+      case ID_PAGE_NETGAME :		qDebug("%sPAGE_NETGAME%s", qPrintable(closePrefix), qPrintable(closeSuffix));		break;      
+      case ID_PAGE_INFO :		qDebug("%sPAGE_INFO%s", qPrintable(closePrefix), qPrintable(closeSuffix));		break;      
+      case ID_PAGE_MAIN :		qDebug("%sPAGE_MAIN%s", qPrintable(closePrefix), qPrintable(closeSuffix));		break;      
+      case ID_PAGE_GAMESTATS :		qDebug("%sPAGE_GAMESTATS%s", qPrintable(closePrefix), qPrintable(closeSuffix));		break;      
+      case ID_PAGE_SINGLEPLAYER :	qDebug("%sPAGE_SINGLEPLAYER%s", qPrintable(closePrefix), qPrintable(closeSuffix));	break;      
+      case ID_PAGE_TRAINING :		qDebug("%sPAGE_TRAINING%s", qPrintable(closePrefix), qPrintable(closeSuffix));		break;      
+      case ID_PAGE_SELECTWEAPON :	qDebug("%sPAGE_SELECTWEAPON%s", qPrintable(closePrefix), qPrintable(closeSuffix));	break;      
+      case ID_PAGE_NETSERVER :		qDebug("%sPAGE_NETSERVER%s", qPrintable(closePrefix), qPrintable(closeSuffix));		break;      
+      case ID_PAGE_INGAME :		qDebug("%sPAGE_INGAME%s", qPrintable(closePrefix), qPrintable(closeSuffix));		break;      
+      case ID_PAGE_ROOMSLIST :		qDebug("%sPAGE_ROOMSLIST%s", qPrintable(closePrefix), qPrintable(closeSuffix));		break;      
+      case ID_PAGE_CONNECTING :	qDebug("%sPAGE_CONNECTING%s", qPrintable(closePrefix), qPrintable(closeSuffix));	break;      
+      case ID_PAGE_SCHEME :		qDebug("%sPAGE_SCHEME%s", qPrintable(closePrefix), qPrintable(closeSuffix));		break;      
+      case ID_PAGE_ADMIN :		qDebug("%sPAGE_ADMIN%s", qPrintable(closePrefix), qPrintable(closeSuffix));		break;      
+      case ID_PAGE_NETTYPE :		qDebug("%sPAGE_NETTYPE%s", qPrintable(closePrefix), qPrintable(closeSuffix));		break;      
+      case ID_PAGE_CAMPAIGN :		qDebug("%sPAGE_CAMPAIGN%s", qPrintable(closePrefix), qPrintable(closeSuffix));		break;      
+      case ID_PAGE_DRAWMAP :		qDebug("%sPAGE_DRAWMAP%s", qPrintable(closePrefix), qPrintable(closeSuffix));		break;      
+      case ID_PAGE_DATADOWNLOAD :	qDebug("%sPAGE_DATADOWNLOAD%s", qPrintable(closePrefix), qPrintable(closeSuffix));	break;      
+      case ID_PAGE_FEEDBACK :		qDebug("%sPAGE_FEEDBACK%s", qPrintable(closePrefix), qPrintable(closeSuffix));		break;      
+      case ID_PAGE_VIDEOS :		qDebug("%sPAGE_VIDEOS%s", qPrintable(closePrefix), qPrintable(closeSuffix));		break;
+      case MAX_PAGE :			qDebug("%sMAX_PAGE%s", qPrintable(closePrefix), qPrintable(closeSuffix));		break; 
+      default :			qDebug("%sUNKNOWN PAGE%s", qPrintable(closePrefix), qPrintable(closeSuffix));		break;
+    } //end switch(lastid)
+    switch (id) { //Print the id of the opened page
+      case ID_PAGE_SETUP_TEAM :	qDebug("%sPAGE_SETUP_TEAM%s", qPrintable(openPrefix), qPrintable(openSuffix)); 		break;      
+      case ID_PAGE_SETUP :		qDebug("%sPAGE_SETUP%s", qPrintable(openPrefix), qPrintable(openSuffix));		break;      
+      case ID_PAGE_MULTIPLAYER :	qDebug("%sPAGE_MULTIPLAYER%s", qPrintable(openPrefix), qPrintable(openSuffix));		break;      
+      case ID_PAGE_DEMOS :		qDebug("%sPAGE_DEMOS%s", qPrintable(openPrefix), qPrintable(openSuffix));		break;      
+      case ID_PAGE_NET :		qDebug("%sPAGE_NET%s", qPrintable(openPrefix), qPrintable(openSuffix));			break;      
+      case ID_PAGE_NETGAME :		qDebug("%sPAGE_NETGAME%s", qPrintable(openPrefix), qPrintable(openSuffix));		break;      
+      case ID_PAGE_INFO :		qDebug("%sPAGE_INFO%s", qPrintable(openPrefix), qPrintable(openSuffix));		break;      
+      case ID_PAGE_MAIN :		qDebug("%sPAGE_MAIN%s", qPrintable(openPrefix), qPrintable(openSuffix));		break;      
+      case ID_PAGE_GAMESTATS :		qDebug("%sPAGE_GAMESTATS%s", qPrintable(openPrefix), qPrintable(openSuffix));		break;      
+      case ID_PAGE_SINGLEPLAYER :	qDebug("%sPAGE_SINGLEPLAYER%s", qPrintable(openPrefix), qPrintable(openSuffix));	break;      
+      case ID_PAGE_TRAINING :		qDebug("%sPAGE_TRAINING%s", qPrintable(openPrefix), qPrintable(openSuffix));		break;      
+      case ID_PAGE_SELECTWEAPON :	qDebug("%sPAGE_SELECTWEAPON%s", qPrintable(openPrefix), qPrintable(openSuffix));	break;      
+      case ID_PAGE_NETSERVER :		qDebug("%sPAGE_NETSERVER%s", qPrintable(openPrefix), qPrintable(openSuffix));		break;      
+      case ID_PAGE_INGAME :		qDebug("%sPAGE_INGAME%s", qPrintable(openPrefix), qPrintable(openSuffix));		break;      
+      case ID_PAGE_ROOMSLIST :		qDebug("%sPAGE_ROOMSLIST%s", qPrintable(openPrefix), qPrintable(openSuffix));		break;      
+      case ID_PAGE_CONNECTING :	qDebug("%sPAGE_CONNECTING%s", qPrintable(openPrefix), qPrintable(openSuffix));		break;      
+      case ID_PAGE_SCHEME :		qDebug("%sPAGE_SCHEME%s", qPrintable(openPrefix), qPrintable(openSuffix));		break;      
+      case ID_PAGE_ADMIN :		qDebug("%sPAGE_ADMIN%s", qPrintable(openPrefix), qPrintable(openSuffix));		break;      
+      case ID_PAGE_NETTYPE :		qDebug("%sPAGE_NETTYPE%s", qPrintable(openPrefix), qPrintable(openSuffix));		break;      
+      case ID_PAGE_CAMPAIGN :		qDebug("%sPAGE_CAMPAIGN%s", qPrintable(openPrefix), qPrintable(openSuffix));		break;      
+      case ID_PAGE_DRAWMAP :		qDebug("%sPAGE_DRAWMAP%s", qPrintable(openPrefix), qPrintable(openSuffix));		break;      
+      case ID_PAGE_DATADOWNLOAD :	qDebug("%sPAGE_DATADOWNLOAD%s", qPrintable(openPrefix), qPrintable(openSuffix));	break;      
+      case ID_PAGE_FEEDBACK :		qDebug("%sPAGE_FEEDBACK%s", qPrintable(openPrefix), qPrintable(openSuffix));		break;      
+      case ID_PAGE_VIDEOS :		qDebug("%sPAGE_VIDEOS%s", qPrintable(openPrefix), qPrintable(openSuffix));		break;
+      case MAX_PAGE :			qDebug("%sMAX_PAGE%s", qPrintable(openPrefix), qPrintable(openSuffix));			break; 
+      default :			qDebug("%sUNKNOWN PAGE%s", qPrintable(openPrefix), qPrintable(openSuffix));		break;
+    } //end switch(id)
+    
     if (id == ID_PAGE_DATADOWNLOAD)
     {
         ui.pageDataDownload->fetchList();
@@ -611,16 +681,6 @@
     {
         ui.pageOptions->setTeamOptionsEnabled(true);
     }
-
-    if (id == ID_PAGE_SETUP)
-    {
-        config->reloadValues();
-    }
-
-    if (id == ID_PAGE_VIDEOS )
-    {
-        config->reloadVideosValues();
-    }
 }
 
 void HWForm::GoToPage(int id)
@@ -965,37 +1025,26 @@
 
 void HWForm::NetPassword(const QString & nick)
 {
-    int passLength = config->value("net/passwordlength", 0).toInt();
-    QString hash = config->value("net/passwordhash", "").toString();
+    //Get hashes
+    QString hash =  config->value("net/passwordhash", "").toString();
+    QString temphash =  config->value("net/temppasswordhash", "").toString();
+
+    //Check them
 
-    // If the password is blank, ask the user to enter one in
-    if (passLength == 0)
-    {
-        HWPasswordDialog * hpd = new HWPasswordDialog(this, tr("Your nickname %1 is\nregistered on Hedgewars.org\nPlease provide your password below\nor pick another nickname in game config:").arg(nick));
-        hpd->cbSave->setChecked(config->value("net/savepassword", true).toBool());
-        if (hpd->exec() != QDialog::Accepted)
-        {
-            ForcedDisconnect(tr("No password supplied."));
-            delete hpd;
-            return;
-        }
-
-        QString password = hpd->lePassword->text();
-        hash = QCryptographicHash::hash(password.toUtf8(), QCryptographicHash::Md5).toHex();
-
-        bool save = hpd->cbSave->isChecked();
-        config->setValue("net/savepassword", save);
-        if (save) // user wants to save password
-        {
-            config->setValue("net/passwordhash", hash);
-            config->setValue("net/passwordlength", password.size());
-            config->setNetPasswordLength(password.size());
-        }
-
-        delete hpd;
+    if (temphash.isEmpty() && hash.isEmpty()) { //If the user enters a registered nick with no password, sends a bogus hash
+        hwnet->SendPasswordHash("THISISNOHASH");
+    }
+    else if (temphash.isEmpty()) { //Send saved hash as default
+        hwnet->SendPasswordHash(hash);
+    }
+    else { //Send the hash
+        hwnet->SendPasswordHash(temphash);
     }
 
-    hwnet->SendPasswordHash(hash);
+    //Remove temporary hash from config
+    QString key = "net/temppasswordhash";
+    config->setValue(key, "");
+    config->remove(key);
 }
 
 void HWForm::NetNickTaken(const QString & nick)
@@ -1080,7 +1129,7 @@
     //connect(ui.pageNetGame->BtnBack, SIGNAL(clicked()), hwnet, SLOT(partRoom()));
 
     ui.pageRoomsList->chatWidget->setUsersModel(hwnet->lobbyPlayersModel());
-    ui.pageNetGame->pChatWidget->setUsersModel(hwnet->roomPlayersModel());
+    ui.pageNetGame->chatWidget->setUsersModel(hwnet->roomPlayersModel());
 
 // rooms list page stuff
     ui.pageRoomsList->setModel(hwnet->roomsListModel());
@@ -1109,26 +1158,26 @@
 
 // net page stuff
     connect(hwnet, SIGNAL(chatStringFromNet(const QString&)),
-            ui.pageNetGame->pChatWidget, SLOT(onChatString(const QString&)), Qt::QueuedConnection);
+            ui.pageNetGame->chatWidget, SLOT(onChatString(const QString&)), Qt::QueuedConnection);
 
     connect(hwnet, SIGNAL(chatStringFromMe(const QString&)),
-            ui.pageNetGame->pChatWidget, SLOT(onChatString(const QString&)), Qt::QueuedConnection);
+            ui.pageNetGame->chatWidget, SLOT(onChatString(const QString&)), Qt::QueuedConnection);
     connect(hwnet, SIGNAL(roomMaster(bool)),
-            ui.pageNetGame->pChatWidget, SLOT(adminAccess(bool)), Qt::QueuedConnection);
-    connect(ui.pageNetGame->pChatWidget, SIGNAL(chatLine(const QString&)),
+            ui.pageNetGame->chatWidget, SLOT(adminAccess(bool)), Qt::QueuedConnection);
+    connect(ui.pageNetGame->chatWidget, SIGNAL(chatLine(const QString&)),
             hwnet, SLOT(chatLineToNet(const QString&)));
     connect(ui.pageNetGame->BtnGo, SIGNAL(clicked()), hwnet, SLOT(ToggleReady()));
     connect(hwnet, SIGNAL(setMyReadyStatus(bool)),
             ui.pageNetGame, SLOT(setReadyStatus(bool)), Qt::QueuedConnection);
 
 // chat widget actions
-    connect(ui.pageNetGame->pChatWidget, SIGNAL(kick(const QString&)),
+    connect(ui.pageNetGame->chatWidget, SIGNAL(kick(const QString&)),
             hwnet, SLOT(kickPlayer(const QString&)));
-    connect(ui.pageNetGame->pChatWidget, SIGNAL(ban(const QString&)),
+    connect(ui.pageNetGame->chatWidget, SIGNAL(ban(const QString&)),
             hwnet, SLOT(banPlayer(const QString&)));
-    connect(ui.pageNetGame->pChatWidget, SIGNAL(info(const QString&)),
+    connect(ui.pageNetGame->chatWidget, SIGNAL(info(const QString&)),
             hwnet, SLOT(infoPlayer(const QString&)));
-    connect(ui.pageNetGame->pChatWidget, SIGNAL(follow(const QString&)),
+    connect(ui.pageNetGame->chatWidget, SIGNAL(follow(const QString&)),
             hwnet, SLOT(followPlayer(const QString&)));
     connect(ui.pageRoomsList->chatWidget, SIGNAL(kick(const QString&)),
             hwnet, SLOT(kickPlayer(const QString&)));
@@ -1151,9 +1200,9 @@
 
 // nick list stuff
     connect(hwnet, SIGNAL(nickAdded(const QString&, bool)),
-            ui.pageNetGame->pChatWidget, SLOT(nickAdded(const QString&, bool)), Qt::QueuedConnection);
+            ui.pageNetGame->chatWidget, SLOT(nickAdded(const QString&, bool)), Qt::QueuedConnection);
     connect(hwnet, SIGNAL(nickRemoved(const QString&)),
-            ui.pageNetGame->pChatWidget, SLOT(nickRemoved(const QString&)), Qt::QueuedConnection);
+            ui.pageNetGame->chatWidget, SLOT(nickRemoved(const QString&)), Qt::QueuedConnection);
     connect(hwnet, SIGNAL(nickAddedLobby(const QString&, bool)),
             ui.pageRoomsList->chatWidget, SLOT(nickAdded(const QString&, bool)), Qt::QueuedConnection);
     connect(hwnet, SIGNAL(nickRemovedLobby(const QString&)),
@@ -1176,11 +1225,16 @@
     connect(hwnet, SIGNAL(serverMessageNew(const QString&)), ui.pageAdmin, SLOT(serverMessageNew(const QString &)));
     connect(hwnet, SIGNAL(serverMessageOld(const QString&)), ui.pageAdmin, SLOT(serverMessageOld(const QString &)));
     connect(hwnet, SIGNAL(latestProtocolVar(int)), ui.pageAdmin, SLOT(protocol(int)));
+    connect(hwnet, SIGNAL(bansList(const QStringList &)), ui.pageAdmin, SLOT(setBansList(const QStringList &)));
     connect(ui.pageAdmin, SIGNAL(setServerMessageNew(const QString&)), hwnet, SLOT(setServerMessageNew(const QString &)));
     connect(ui.pageAdmin, SIGNAL(setServerMessageOld(const QString&)), hwnet, SLOT(setServerMessageOld(const QString &)));
     connect(ui.pageAdmin, SIGNAL(setProtocol(int)), hwnet, SLOT(setLatestProtocolVar(int)));
     connect(ui.pageAdmin, SIGNAL(askServerVars()), hwnet, SLOT(askServerVars()));
     connect(ui.pageAdmin, SIGNAL(clearAccountsCache()), hwnet, SLOT(clearAccountsCache()));
+    connect(ui.pageAdmin, SIGNAL(bansListRequest()), hwnet, SLOT(getBanList()));
+    connect(ui.pageAdmin, SIGNAL(removeBan(QString)), hwnet, SLOT(removeBan(QString)));
+    connect(ui.pageAdmin, SIGNAL(banIP(QString,QString,int)), hwnet, SLOT(banIP(QString,QString,int)));
+    connect(ui.pageAdmin, SIGNAL(banNick(QString,QString,int)), hwnet, SLOT(banNick(QString,QString,int)));
 
 // disconnect
     connect(hwnet, SIGNAL(disconnected(const QString&)), this, SLOT(ForcedDisconnect(const QString&)), Qt::QueuedConnection);
@@ -1189,24 +1243,88 @@
     connect(hwnet, SIGNAL(paramChanged(const QString &, const QStringList &)), ui.pageNetGame->pGameCFG, SLOT(setParam(const QString &, const QStringList &)));
     connect(ui.pageNetGame->pGameCFG, SIGNAL(paramChanged(const QString &, const QStringList &)), hwnet, SLOT(onParamChanged(const QString &, const QStringList &)));
     connect(hwnet, SIGNAL(configAsked()), ui.pageNetGame->pGameCFG, SLOT(fullNetConfig()));
-
-    while (nick.isEmpty())
+   
+//nick and pass stuff
+    
+    //remove temppasswordhash just in case
+    config->value("net/temppasswordhash", "");
+    config->remove("net/temppasswordhash");
+    
+    //initialize
+    QString hash = config->value("net/passwordhash", "").toString();
+    QString temphash = config->value("net/temppasswordhash", "").toString();
+    QString nickname = config->value("net/nick", "").toString();
+    QString password;
+    
+    if (nickname.isEmpty() || hash.isEmpty()) { //if something from login is missing, start dialog loop
+    
+    while (nickname.isEmpty() || (hash.isEmpty() && temphash.isEmpty())) //while a nickname, or both hashes are missing
     {
-        nick = QInputDialog::getText(this,
-                                     QObject::tr("Nickname"),
-                                     QObject::tr("Please enter your nickname"),
-                                     QLineEdit::Normal,
-                                     QDir::home().dirName());
-        config->setValue("net/nick",nick);
+	//open dialog
+        HWPasswordDialog * hpd = new HWPasswordDialog(this);
+        hpd->cbSave->setChecked(config->value("net/savepassword", true).toBool());
+
+	//if nickname is present, put it into the field
+	if (!nickname.isEmpty()) {
+	    hpd->leNickname->setText(nickname);
+	    hpd->lePassword->setFocus();
+	}
+
+	//if dialog close, create an error message
+        if (hpd->exec() != QDialog::Accepted)
+        {
+            ForcedDisconnect(tr("Login info not supplied."));
+            delete hpd;
+            return;
+        }
+
+	//set nick and pass from the dialog
+	nickname = hpd->leNickname->text();
+        password = hpd->lePassword->text();
+
+	//calculate temphash and set it into config
+	temphash = QCryptographicHash::hash(password.toUtf8(), QCryptographicHash::Md5).toHex();
+	config->setValue("net/temppasswordhash", temphash);
+
+	//if user wants to save password
+        bool save = hpd->cbSave->isChecked();
+        config->setValue("net/savepassword", save);
+        if (save) // user wants to save password
+        {
+            config->setValue("net/passwordhash", temphash);
+            config->setValue("net/passwordlength", password.size());
+            config->setNetPasswordLength(password.size());
+        }
+
+        delete hpd;
+
+
+	//update nickname
+        config->setValue("net/nick", nickname);
         config->updNetNick();
+	
+	//and all the variables
+	hash = config->value("net/passwordhash", "").toString();
+	temphash = config->value("net/temppasswordhash", "").toString();
+	nickname = config->value("net/nick", "").toString();
+    }
+    
+    
+	//if pass is none (hash is generated anyway), remove the hash
+	if (password.size() <= 0) {
+	    config->setValue("net/temppasswordhash", "");
+	    config->remove("net/temppasswordhash");
+	}
     }
 
-    ui.pageRoomsList->setUser(nick);
-    ui.pageNetGame->setUser(nick);
+    ui.pageRoomsList->setUser(nickname);
+    ui.pageNetGame->setUser(nickname);
 
-    hwnet->Connect(hostName, port, nick);
+    hwnet->Connect(hostName, port, nickname);
 }
 
+
+
 void HWForm::NetConnect()
 {
     HWHostPortDialog * hpd = new HWHostPortDialog(this);
@@ -1294,7 +1412,7 @@
 
 void HWForm::NetGameEnter()
 {
-    ui.pageNetGame->pChatWidget->clear();
+    ui.pageNetGame->chatWidget->clear();
     GoToPage(ID_PAGE_NETGAME);
 }
 
--- a/QTfrontend/hwform.h	Fri Nov 30 18:19:52 2012 +0400
+++ b/QTfrontend/hwform.h	Tue Dec 04 09:15:55 2012 +0400
@@ -61,7 +61,6 @@
         HWForm(QWidget *parent = 0, QString styleSheet = "");
         Ui_HWForm ui;
         static GameUIConfig * config;
-        static QSettings * gameSettings; // Same file GameUIConfig points to but without the baggage.  Needs sync() calls if you want to get GameUIConfig changes though
         void updateXfire();
         void PlayDemoQuick(const QString & demofilename);
         void exit();
@@ -146,7 +145,7 @@
 
     private:
         void _NetConnect(const QString & hostName, quint16 port, QString nick);
-        void UpdateTeamsLists(const QStringList* editable_teams=0);
+        void UpdateTeamsLists();
         void CreateGame(GameCFGWidget * gamecfg, TeamSelWidget* pTeamSelWidget, QString ammo);
         void closeEvent(QCloseEvent *event);
         void CustomizePalettes();
@@ -178,8 +177,8 @@
             ID_PAGE_DRAWMAP        ,
             ID_PAGE_DATADOWNLOAD   ,
             ID_PAGE_FEEDBACK	   ,
-            ID_PAGE_VIDEOS,
-	    MAX_PAGE
+            ID_PAGE_VIDEOS	   ,
+            MAX_PAGE
         };
         QPointer<HWGame> game;
         QPointer<HWNetServer> pnetserver;
--- a/QTfrontend/main.cpp	Fri Nov 30 18:19:52 2012 +0400
+++ b/QTfrontend/main.cpp	Tue Dec 04 09:15:55 2012 +0400
@@ -90,9 +90,9 @@
 
 bool checkForDir(const QString & dir)
 {
-    QDir tmpdir;
-    if (!tmpdir.exists(dir))
-        if (!tmpdir.mkdir(dir))
+    QDir tmpdir(dir);
+    if (!tmpdir.exists())
+        if (!tmpdir.mkpath(dir))
         {
             QMessageBox directoryMsg(QApplication::activeWindow());
             directoryMsg.setIcon(QMessageBox::Warning);
@@ -105,8 +105,37 @@
     return true;
 }
 
+bool checkForFile(const QString & file)
+{
+    QFile tmpfile(file);
+    if (!tmpfile.exists())
+        return tmpfile.open(QFile::WriteOnly);
+    else
+        return true;
+}
+
+#ifdef __APPLE__
+static CocoaInitializer *cocoaInit = NULL;
+// Function to be called at end of program's termination on OS X to release
+// the NSAutoReleasePool contained within the CocoaInitializer.
+void releaseCocoaPool(void)
+{
+    if (cocoaInit != NULL)
+    {
+        delete cocoaInit;
+        cocoaInit = NULL;
+    }
+}
+#endif
+
 int main(int argc, char *argv[])
 {
+#ifdef __APPLE__
+    // This creates the autoreleasepool that prevents leaking, and destroys it only on exit
+    cocoaInit = new CocoaInitializer();
+    atexit(releaseCocoaPool);
+#endif
+
     HWApplication app(argc, argv);
 
     FileEngineHandler engine(argv[0]);
@@ -232,6 +261,8 @@
     engine.setWriteDir(cfgdir->absolutePath());
     engine.mountPacks();
 
+    checkForFile("physfs://hedgewars.ini");
+
     QTranslator Translator;
     {
         QSettings settings("physfs://hedgewars.ini", QSettings::IniFormat);
@@ -254,10 +285,6 @@
         registry_hklm.setValue("Software/Hedgewars/Path", bindir->absolutePath().replace("/", "\\"));
     }
 #endif
-#ifdef __APPLE__
-    // this creates the autoreleasepool that prevents leaking
-    CocoaInitializer initializer;
-#endif
 
     QString style = "";
     QString fname;
--- a/QTfrontend/net/newnetclient.cpp	Fri Nov 30 18:19:52 2012 +0400
+++ b/QTfrontend/net/newnetclient.cpp	Tue Dec 04 09:15:55 2012 +0400
@@ -364,6 +364,14 @@
         return;
     }
 
+    if (lst[0] == "BANLIST")
+    {
+        QStringList tmp = lst;
+        tmp.removeFirst();
+        emit bansList(tmp);
+        return;
+    }
+
     if (lst[0] == "CLIENT_FLAGS")
     {
         if(lst.size() < 3 || lst[1].size() < 2)
@@ -863,6 +871,26 @@
     RawSendNet(QString("BAN%1%2").arg(delimeter).arg(nick));
 }
 
+void HWNewNet::banIP(const QString & ip, const QString & reason, int seconds)
+{
+    RawSendNet(QString("BANIP%1%2%1%3%1%4").arg(delimeter).arg(ip).arg(reason).arg(seconds));
+}
+
+void HWNewNet::banNick(const QString & nick, const QString & reason, int seconds)
+{
+    RawSendNet(QString("BANNICK%1%2%1%3%1%4").arg(delimeter).arg(nick).arg(reason).arg(seconds));
+}
+
+void HWNewNet::getBanList()
+{
+    RawSendNet(QByteArray("BANLIST"));
+}
+
+void HWNewNet::removeBan(const QString & b)
+{
+    RawSendNet(QString("UNBAN%1%2").arg(delimeter).arg(b));
+}
+
 void HWNewNet::kickPlayer(const QString & nick)
 {
     RawSendNet(QString("KICK%1%2").arg(delimeter).arg(nick));
--- a/QTfrontend/net/newnetclient.h	Fri Nov 30 18:19:52 2012 +0400
+++ b/QTfrontend/net/newnetclient.h	Tue Dec 04 09:15:55 2012 +0400
@@ -123,6 +123,7 @@
         void serverMessageNew(const QString &);
         void serverMessageOld(const QString &);
         void latestProtocolVar(int);
+        void bansList(const QStringList &);
 
         void setMyReadyStatus(bool isReady);
 
@@ -156,7 +157,11 @@
         void toggleRestrictJoins();
         void toggleRestrictTeamAdds();
         void partRoom();
-        void clearAccountsCache();
+        void clearAccountsCache();        
+        void getBanList();
+        void removeBan(const QString &);
+        void banIP(const QString & ip, const QString & reason, int seconds);
+        void banNick(const QString & nick, const QString & reason, int seconds);
 
     private slots:
         void ClientRead();
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/QTfrontend/ui/dialog/bandialog.cpp	Tue Dec 04 09:15:55 2012 +0400
@@ -0,0 +1,87 @@
+#include <QFormLayout>
+#include <QComboBox>
+#include <QRadioButton>
+#include <QLineEdit>
+#include <QLabel>
+#include <QPushButton>
+#include <QHBoxLayout>
+#include <QMessageBox>
+
+#include "bandialog.h"
+
+BanDialog::BanDialog(QWidget *parent) :
+    QDialog(parent)
+{
+    QFormLayout * formLayout = new QFormLayout(this);
+
+    rbIP = new QRadioButton(this);
+    rbIP->setChecked(true);
+    rbNick = new QRadioButton(this);
+    leId = new QLineEdit(this);
+    leReason = new QLineEdit(this);
+    cbTime = new QComboBox(this);
+
+    cbTime->addItem(tr("10 minutes"), 5 * 60);
+    cbTime->addItem(tr("30 minutes"), 10 * 60);
+    cbTime->addItem(tr("1 hour"), 60 * 60);
+    cbTime->addItem(tr("3 hours"), 3 * 60 * 60);
+    cbTime->addItem(tr("5 hours"), 5 * 60 * 60);
+    cbTime->addItem(tr("24 hours"), 24 * 60 * 60);
+    cbTime->addItem(tr("3 days"), 72 * 60 * 60);
+    cbTime->addItem(tr("7 days"), 168 * 60 * 60);
+    cbTime->addItem(tr("14 days"), 336 * 60 * 60);
+    cbTime->addItem(tr("permanent"), 3650 * 24 * 60 * 60);
+    cbTime->setCurrentIndex(0);
+
+    formLayout->addRow(tr("IP"), rbIP);
+    formLayout->addRow(tr("Nick"), rbNick);
+    formLayout->addRow(tr("IP/Nick"), leId);
+    formLayout->addRow(tr("Reason"), leReason);
+    formLayout->addRow(tr("Duration"), cbTime);
+
+    formLayout->setLabelAlignment(Qt::AlignRight);
+
+    QHBoxLayout * hbox = new QHBoxLayout();
+    formLayout->addRow(hbox);
+    QPushButton * btnOk = new QPushButton(tr("Ok"), this);
+    QPushButton * btnCancel = new QPushButton(tr("Cancel"), this);
+    hbox->addStretch();
+    hbox->addWidget(btnOk);
+    hbox->addWidget(btnCancel);
+
+    connect(btnOk, SIGNAL(clicked()), this, SLOT(okClicked()));
+    connect(btnCancel, SIGNAL(clicked()), this, SLOT(reject()));
+
+    this->setWindowModality(Qt::WindowModal);
+}
+
+bool BanDialog::byIP()
+{
+    return rbIP->isChecked();
+}
+
+int BanDialog::duration()
+{
+    return cbTime->itemData(cbTime->currentIndex()).toInt();
+}
+
+QString BanDialog::banId()
+{
+    return leId->text();
+}
+
+QString BanDialog::reason()
+{
+    return leReason->text().isEmpty() ? tr("you know why") : leReason->text();
+}
+
+void BanDialog::okClicked()
+{
+    if(leId->text().isEmpty())
+    {
+        QMessageBox::warning(this, tr("Warning"), tr("Please, specify %1").arg(byIP() ? tr("IP") : tr("nickname")));
+        return;
+    }
+
+    accept();
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/QTfrontend/ui/dialog/bandialog.h	Tue Dec 04 09:15:55 2012 +0400
@@ -0,0 +1,32 @@
+#ifndef BANDIALOG_H
+#define BANDIALOG_H
+
+#include <QDialog>
+
+class QComboBox;
+class QRadioButton;
+class QLineEdit;
+
+class BanDialog : public QDialog
+{
+    Q_OBJECT
+public:
+    explicit BanDialog(QWidget *parent = 0);    
+
+    bool byIP();
+    int duration();
+    QString banId();
+    QString reason();
+
+private:
+    QRadioButton * rbIP;
+    QRadioButton * rbNick;
+    QLineEdit * leId;
+    QLineEdit * leReason;
+    QComboBox * cbTime;
+
+private slots:
+    void okClicked();
+};
+
+#endif // BANDIALOG_H
--- a/QTfrontend/ui/dialog/input_password.cpp	Fri Nov 30 18:19:52 2012 +0400
+++ b/QTfrontend/ui/dialog/input_password.cpp	Tue Dec 04 09:15:55 2012 +0400
@@ -25,28 +25,44 @@
 
 #include "input_password.h"
 
-HWPasswordDialog::HWPasswordDialog(QWidget* parent, const QString & label) : QDialog(parent)
+HWPasswordDialog::HWPasswordDialog(QWidget* parent) : QDialog(parent)
 {
-    setWindowTitle(tr("Password"));
+    setWindowTitle(tr("Login"));
+    
+    QString titleLabelText = "To connect to the server, please log in.\n\nIf you don't have an account on www.hedgewars.org,\njust enter your nickname.";
+    QString nickLabelText = "Nickname:";
+    QString passLabelText = "Password:";
 
     QGridLayout * layout = new QGridLayout(this);
 
-    QLabel * lbLabel = new QLabel(this);
-    lbLabel->setText(label);
-    layout->addWidget(lbLabel, 0, 0);
+    QLabel * titleLabel = new QLabel(this);
+    titleLabel->setText(titleLabelText);
+    layout->addWidget(titleLabel, 0, 0);
+    
+    QLabel * nickLabel = new QLabel(this);
+    nickLabel->setText(nickLabelText);
+    layout->addWidget(nickLabel, 1, 0);
+    
+    leNickname = new QLineEdit(this);
+    leNickname->setEchoMode(QLineEdit::Normal);
+    layout->addWidget(leNickname, 2, 0);
+    
+    QLabel * passLabel = new QLabel(this);
+    passLabel->setText(passLabelText);
+    layout->addWidget(passLabel, 3, 0);
 
     lePassword = new QLineEdit(this);
     lePassword->setEchoMode(QLineEdit::Password);
-    layout->addWidget(lePassword, 1, 0);
+    layout->addWidget(lePassword, 4, 0);
 
     cbSave = new QCheckBox(this);
     cbSave->setText(QCheckBox::tr("Save password"));
-    layout->addWidget(cbSave, 2, 0);
+    layout->addWidget(cbSave, 5, 0);
 
     QDialogButtonBox* dbbButtons = new QDialogButtonBox(this);
     QPushButton * pbOK = dbbButtons->addButton(QDialogButtonBox::Ok);
     QPushButton * pbCancel = dbbButtons->addButton(QDialogButtonBox::Cancel);
-    layout->addWidget(dbbButtons, 3, 0);
+    layout->addWidget(dbbButtons, 6, 0);
 
     connect(pbOK, SIGNAL(clicked()), this, SLOT(accept()));
     connect(pbCancel, SIGNAL(clicked()), this, SLOT(reject()));
--- a/QTfrontend/ui/dialog/input_password.h	Fri Nov 30 18:19:52 2012 +0400
+++ b/QTfrontend/ui/dialog/input_password.h	Tue Dec 04 09:15:55 2012 +0400
@@ -28,9 +28,10 @@
 {
         Q_OBJECT
     public:
-        HWPasswordDialog(QWidget* parent, const QString & label);
+        HWPasswordDialog(QWidget* parent);
 
         QLineEdit* lePassword;
+        QLineEdit* leNickname;
         QCheckBox* cbSave;
 };
 
--- a/QTfrontend/ui/page/AbstractPage.cpp	Fri Nov 30 18:19:52 2012 +0400
+++ b/QTfrontend/ui/page/AbstractPage.cpp	Tue Dec 04 09:15:55 2012 +0400
@@ -41,8 +41,9 @@
     QGridLayout * pageLayout = new QGridLayout(this);
 
     // stretch grid space for body and footer
-    pageLayout->setColumnStretch(0,0);
-    pageLayout->setColumnStretch(1,1);
+    pageLayout->setColumnStretch(0,1);
+    pageLayout->setColumnStretch(1,2);
+    pageLayout->setColumnStretch(2,1);
     pageLayout->setRowStretch(0,1);
     pageLayout->setRowStretch(1,0);
 
--- a/QTfrontend/ui/page/pageadmin.cpp	Fri Nov 30 18:19:52 2012 +0400
+++ b/QTfrontend/ui/page/pageadmin.cpp	Tue Dec 04 09:15:55 2012 +0400
@@ -22,56 +22,98 @@
 #include <QSpinBox>
 #include <QPushButton>
 #include <QTextBrowser>
+#include <QTableWidget>
+#include <QHeaderView>
 
 #include "pageadmin.h"
 #include "chatwidget.h"
+#include "bandialog.h"
 
 QLayout * PageAdmin::bodyLayoutDefinition()
 {
-    QGridLayout * pageLayout = new QGridLayout();
-
-    // 0
-    pbAsk = addButton(tr("Fetch data"), pageLayout, 0, 0, 1, 3);
+    QVBoxLayout * pageLayout = new QVBoxLayout();
 
-    // 1
-    QLabel * lblSMN = new QLabel(this);
-    lblSMN->setText(tr("Server message for latest version:"));
-    pageLayout->addWidget(lblSMN, 1, 0);
+    QTabWidget * tabs = new QTabWidget(this);
+    pageLayout->addWidget(tabs);
+    QWidget * page1 = new QWidget(this);
+    QWidget * page2 = new QWidget(this);
+    tabs->addTab(page1, tr("General"));
+    tabs->addTab(page2, tr("Bans"));
+
+    // page 1
+    {
+        QGridLayout * tab1Layout = new QGridLayout(page1);
+
+        // 0
+        pbAsk = addButton(tr("Fetch data"), tab1Layout, 0, 0, 1, 3);
 
-    leServerMessageNew = new QLineEdit(this);
-    pageLayout->addWidget(leServerMessageNew, 1, 1);
+        // 1
+        QLabel * lblSMN = new QLabel(this);
+        lblSMN->setText(tr("Server message for latest version:"));
+        tab1Layout->addWidget(lblSMN, 1, 0);
+
+        leServerMessageNew = new QLineEdit(this);
+        tab1Layout->addWidget(leServerMessageNew, 1, 1);
 
-    // 2
-    QLabel * lblSMO = new QLabel(this);
-    lblSMO->setText(tr("Server message for previous versions:"));
-    pageLayout->addWidget(lblSMO, 2, 0);
+        // 2
+        QLabel * lblSMO = new QLabel(this);
+        lblSMO->setText(tr("Server message for previous versions:"));
+        tab1Layout->addWidget(lblSMO, 2, 0);
+
+        leServerMessageOld = new QLineEdit(this);
+        tab1Layout->addWidget(leServerMessageOld, 2, 1);
 
-    leServerMessageOld = new QLineEdit(this);
-    pageLayout->addWidget(leServerMessageOld, 2, 1);
+        // 3
+        QLabel * lblP = new QLabel(this);
+        lblP->setText(tr("Latest version protocol number:"));
+        tab1Layout->addWidget(lblP, 3, 0);
+
+        sbProtocol = new QSpinBox(this);
+        tab1Layout->addWidget(sbProtocol, 3, 1);
 
-    // 3
-    QLabel * lblP = new QLabel(this);
-    lblP->setText(tr("Latest version protocol number:"));
-    pageLayout->addWidget(lblP, 3, 0);
+        // 4
+        QLabel * lblPreview = new QLabel(this);
+        lblPreview->setText(tr("MOTD preview:"));
+        tab1Layout->addWidget(lblPreview, 4, 0);
 
-    sbProtocol = new QSpinBox(this);
-    pageLayout->addWidget(sbProtocol, 3, 1);
+        tb = new QTextBrowser(this);
+        tb->setOpenExternalLinks(true);
+        tb->document()->setDefaultStyleSheet(HWChatWidget::styleSheet());
+        tab1Layout->addWidget(tb, 4, 1, 1, 2);
+
+        // 5
+        pbClearAccountsCache = addButton(tr("Clear Accounts Cache"), tab1Layout, 5, 0);
+
+        // 6
+        pbSetSM = addButton(tr("Set data"), tab1Layout, 6, 0, 1, 3);
+    }
 
-    // 4
-    QLabel * lblPreview = new QLabel(this);
-    lblPreview->setText(tr("MOTD preview:"));
-    pageLayout->addWidget(lblPreview, 4, 0);
+    // page 2
+    {
+        QGridLayout * tab2Layout = new QGridLayout(page2);
+        twBans = new QTableWidget(this);
+        twBans->setColumnCount(3);
+        twBans->setHorizontalHeaderLabels(QStringList()
+                              << tr("IP/Nick")
+                              << tr("Expiration")
+                              << tr("Reason")
+                    );
+        twBans->horizontalHeader()->setResizeMode(2, QHeaderView::Stretch);
+        twBans->setEditTriggers(QAbstractItemView::NoEditTriggers);
+        twBans->setSelectionBehavior(QAbstractItemView::SelectRows);
+        twBans->setSelectionMode(QAbstractItemView::SingleSelection);
+        twBans->setAlternatingRowColors(true);
+        tab2Layout->addWidget(twBans, 0, 1, 4, 1);
 
-    tb = new QTextBrowser(this);
-    tb->setOpenExternalLinks(true);
-    tb->document()->setDefaultStyleSheet(HWChatWidget::styleSheet());
-    pageLayout->addWidget(tb, 4, 1, 1, 2);
+        QPushButton * btnRefresh = addButton(tr("Refresh"), tab2Layout, 0, 0);
+        QPushButton * btnAdd = addButton(tr("Add"), tab2Layout, 1, 0);
+        QPushButton * btnRemove = addButton(tr("Remove"), tab2Layout, 2, 0);
 
-    // 5
-    pbClearAccountsCache = addButton(tr("Clear Accounts Cache"), pageLayout, 5, 0);
-
-    // 6
-    pbSetSM = addButton(tr("Set data"), pageLayout, 6, 0, 1, 3);
+        connect(btnRefresh, SIGNAL(clicked()), this, SIGNAL(bansListRequest()));
+        connect(btnRefresh, SIGNAL(clicked()), this, SLOT(onRefreshClicked()));
+        connect(btnAdd, SIGNAL(clicked()), this, SLOT(onAddClicked()));
+        connect(btnRemove, SIGNAL(clicked()), this, SLOT(onRemoveClicked()));
+    }
 
     return pageLayout;
 }
@@ -106,7 +148,64 @@
 {
     leServerMessageOld->setText(str);
 }
+
 void PageAdmin::protocol(int proto)
 {
     sbProtocol->setValue(proto);
 }
+
+void PageAdmin::onAddClicked()
+{
+    BanDialog dialog(this);
+
+    if(dialog.exec())
+    {
+        if(dialog.byIP())
+        {
+            emit banIP(dialog.banId(), dialog.reason(), dialog.duration());
+        } else
+        {
+            emit banNick(dialog.banId(), dialog.reason(), dialog.duration());
+        }
+
+        emit bansListRequest();
+    }
+}
+
+void PageAdmin::onRemoveClicked()
+{
+    QList<QTableWidgetItem *> sel = twBans->selectedItems();
+
+    if(sel.size())
+    {
+        emit removeBan(twBans->item(sel[0]->row(), 0)->data(Qt::DisplayRole).toString());
+        emit bansListRequest();
+    }
+}
+
+void PageAdmin::setBansList(const QStringList & bans)
+{
+    if(bans.size() % 4)
+        return;
+
+    twBans->setRowCount(bans.size() / 4);
+
+    for(int i = 0; i < bans.size(); i += 4)
+    {
+        if(!twBans->item(i / 4, 0))
+        {
+            twBans->setItem(i / 4, 0, new QTableWidgetItem());
+            twBans->setItem(i / 4, 1, new QTableWidgetItem());
+            twBans->setItem(i / 4, 2, new QTableWidgetItem());
+        }
+
+        twBans->item(i / 4, 0)->setData(Qt::DisplayRole, bans[i + 1]);
+        twBans->item(i / 4, 1)->setData(Qt::DisplayRole, bans[i + 3]);
+        twBans->item(i / 4, 2)->setData(Qt::DisplayRole, bans[i + 2]);
+    }
+}
+
+void PageAdmin::onRefreshClicked()
+{
+    twBans->setRowCount(0);
+}
--- a/QTfrontend/ui/page/pageadmin.h	Fri Nov 30 18:19:52 2012 +0400
+++ b/QTfrontend/ui/page/pageadmin.h	Tue Dec 04 09:15:55 2012 +0400
@@ -21,6 +21,8 @@
 
 #include "AbstractPage.h"
 
+class QTableWidget;
+
 class PageAdmin : public AbstractPage
 {
         Q_OBJECT
@@ -32,6 +34,7 @@
         void serverMessageNew(const QString & str);
         void serverMessageOld(const QString & str);
         void protocol(int proto);
+        void setBansList(const QStringList & bans);
 
     signals:
         void setServerMessageNew(const QString & str);
@@ -39,6 +42,10 @@
         void setProtocol(int proto);
         void askServerVars();
         void clearAccountsCache();
+        void bansListRequest();
+        void removeBan(const QString &);
+        void banIP(const QString & ip, const QString & reason, int seconds);
+        void banNick(const QString & nick, const QString & reason, int seconds);
 
     protected:
         QLayout * bodyLayoutDefinition();
@@ -52,9 +59,13 @@
         QSpinBox * sbProtocol;
         QTextBrowser * tb;
         QPushButton * pbClearAccountsCache;
+        QTableWidget * twBans;
 
     private slots:
         void smChanged();
+        void onAddClicked();
+        void onRemoveClicked();
+        void onRefreshClicked();
 };
 
 #endif
--- a/QTfrontend/ui/page/pagemain.cpp	Fri Nov 30 18:19:52 2012 +0400
+++ b/QTfrontend/ui/page/pagemain.cpp	Tue Dec 04 09:15:55 2012 +0400
@@ -115,7 +115,7 @@
     }
     else
     {
-        setDefautDescription(QLabel::tr("This development build is 'work in progress' and may not be compatible with other versions of the game. Some features might be broken or incomplete. Use at your own risk!"));
+        setDefautDescription(QLabel::tr("This development build is 'work in progress' and may not be compatible with other versions of the game, while some features might be broken or incomplete!"));
     }
 
 }
--- a/QTfrontend/ui/page/pagenetgame.cpp	Fri Nov 30 18:19:52 2012 +0400
+++ b/QTfrontend/ui/page/pagenetgame.cpp	Tue Dec 04 09:15:55 2012 +0400
@@ -37,10 +37,10 @@
     pageLayout->setColumnStretch(1, 50);
 
     // chatwidget
-    pChatWidget = new HWChatWidget(this, m_gameSettings, true);
-    pChatWidget->setShowFollow(false); // don't show follow in nicks' context menus
-    pChatWidget->setIgnoreListKick(true); // kick ignored players automatically
-    pageLayout->addWidget(pChatWidget, 2, 0, 1, 2);
+    chatWidget = new HWChatWidget(this, true);
+    chatWidget->setShowFollow(false); // don't show follow in nicks' context menus
+    chatWidget->setIgnoreListKick(true); // kick ignored players automatically
+    pageLayout->addWidget(chatWidget, 2, 0, 1, 2);
     pageLayout->setRowStretch(1, 100);
     pageLayout->setRowStretch(2, 100);
 
@@ -96,10 +96,8 @@
     connect(BtnUpdate, SIGNAL(clicked()), this, SLOT(onUpdateClick()));
 }
 
-PageNetGame::PageNetGame(QWidget* parent, QSettings * gameSettings) : AbstractPage(parent)
+PageNetGame::PageNetGame(QWidget* parent) : AbstractPage(parent)
 {
-    m_gameSettings = gameSettings;
-
     initPage();
 
     QMenu * menu = new QMenu(BtnMaster);
@@ -113,24 +111,23 @@
     menu->addAction(restrictTeamAdds);
 
     BtnMaster->setMenu(menu);
-
 }
 
 
 void PageNetGame::displayError(const QString & message)
 {
-    pChatWidget->displayError(message);
+    chatWidget->displayError(message);
 }
 
 
 void PageNetGame::displayNotice(const QString & message)
 {
-    pChatWidget->displayNotice(message);
+    chatWidget->displayNotice(message);
 }
 
 void PageNetGame::displayWarning(const QString & message)
 {
-    pChatWidget->displayWarning(message);
+    chatWidget->displayWarning(message);
 }
 
 
@@ -178,5 +175,5 @@
 
 void PageNetGame::setUser(const QString & nickname)
 {
-    pChatWidget->setUser(nickname);
+    chatWidget->setUser(nickname);
 }
--- a/QTfrontend/ui/page/pagenetgame.h	Fri Nov 30 18:19:52 2012 +0400
+++ b/QTfrontend/ui/page/pagenetgame.h	Tue Dec 04 09:15:55 2012 +0400
@@ -32,7 +32,7 @@
         Q_OBJECT
 
     public:
-        PageNetGame(QWidget* parent, QSettings * gameSettings);
+        PageNetGame(QWidget* parent);
 
         /**
          * Sets the room name to display.
@@ -52,7 +52,7 @@
         QAction * restrictJoins;
         QAction * restrictTeamAdds;
 
-        HWChatWidget* pChatWidget;
+        HWChatWidget* chatWidget;
 
         TeamSelWidget* pNetTeamsWidget;
         GameCFGWidget* pGameCFG;
@@ -72,8 +72,6 @@
         QLayout * footerLayoutDefinition();
         void connectSignals();
 
-        QSettings * m_gameSettings;
-
         HistoryLineEdit * leRoomName;
         QPushButton * btnSetup;
 };
--- a/QTfrontend/ui/page/pageoptions.cpp	Fri Nov 30 18:19:52 2012 +0400
+++ b/QTfrontend/ui/page/pageoptions.cpp	Tue Dec 04 09:15:55 2012 +0400
@@ -33,10 +33,12 @@
 #include <QStandardItemModel>
 
 #include "pageoptions.h"
+#include "gameuiconfig.h"
 #include "hwconsts.h"
 #include "fpsedit.h"
 #include "igbox.h"
 #include "DataManager.h"
+#include "LibavInteraction.h"
 
 // TODO cleanup
 QLayout * PageOptions::bodyLayoutDefinition()
@@ -50,6 +52,11 @@
     tabs->addTab(page1, tr("General"));
     tabs->addTab(page2, tr("Advanced"));
 
+#ifdef VIDEOREC
+    QWidget * page3 = new QWidget(this);
+    tabs->addTab(page3, tr("Video Recording"));
+#endif
+
     { // page 1
         QGridLayout * page1Layout = new QGridLayout(page1);
         //gbTBLayout->setMargin(0);
@@ -477,6 +484,121 @@
 
         page2Layout->addWidget(new QWidget(this), 2, 0);
     }
+#ifdef VIDEOREC
+    { // page 3
+        QGridLayout * page3Layout = new QGridLayout(page3);
+
+        IconedGroupBox* pOptionsGroup = new IconedGroupBox(this);
+        pOptionsGroup->setIcon(QIcon(":/res/Settings.png")); // FIXME
+        pOptionsGroup->setSizePolicy(QSizePolicy::Fixed, QSizePolicy::Fixed);
+        pOptionsGroup->setTitle(QGroupBox::tr("Video recording options"));
+        QGridLayout * pOptLayout = new QGridLayout(pOptionsGroup);
+
+        // label for format
+        QLabel *labelFormat = new QLabel(pOptionsGroup);
+        labelFormat->setText(QLabel::tr("Format"));
+        pOptLayout->addWidget(labelFormat, 0, 0);
+
+        // list of supported formats
+        comboAVFormats = new QComboBox(pOptionsGroup);
+        pOptLayout->addWidget(comboAVFormats, 0, 1, 1, 4);
+        LibavInteraction::instance().fillFormats(comboAVFormats);
+
+        // separator
+        QFrame * hr = new QFrame(pOptionsGroup);
+        hr->setFrameStyle(QFrame::HLine);
+        hr->setLineWidth(3);
+        hr->setFixedHeight(10);
+        pOptLayout->addWidget(hr, 1, 0, 1, 5);
+
+        // label for audio codec
+        QLabel *labelACodec = new QLabel(pOptionsGroup);
+        labelACodec->setText(QLabel::tr("Audio codec"));
+        pOptLayout->addWidget(labelACodec, 2, 0);
+
+        // list of supported audio codecs
+        comboAudioCodecs = new QComboBox(pOptionsGroup);
+        pOptLayout->addWidget(comboAudioCodecs, 2, 1, 1, 3);
+
+        // checkbox 'record audio'
+        checkRecordAudio = new QCheckBox(pOptionsGroup);
+        checkRecordAudio->setText(QCheckBox::tr("Record audio"));
+        pOptLayout->addWidget(checkRecordAudio, 2, 4);
+
+        // separator
+        hr = new QFrame(pOptionsGroup);
+        hr->setFrameStyle(QFrame::HLine);
+        hr->setLineWidth(3);
+        hr->setFixedHeight(10);
+        pOptLayout->addWidget(hr, 3, 0, 1, 5);
+
+        // label for video codec
+        QLabel *labelVCodec = new QLabel(pOptionsGroup);
+        labelVCodec->setText(QLabel::tr("Video codec"));
+        pOptLayout->addWidget(labelVCodec, 4, 0);
+
+        // list of supported video codecs
+        comboVideoCodecs = new QComboBox(pOptionsGroup);
+        pOptLayout->addWidget(comboVideoCodecs, 4, 1, 1, 4);
+
+        // label for resolution
+        QLabel *labelRes = new QLabel(pOptionsGroup);
+        labelRes->setText(QLabel::tr("Resolution"));
+        pOptLayout->addWidget(labelRes, 5, 0);
+
+        // width
+        widthEdit = new QLineEdit(pOptionsGroup);
+        widthEdit->setValidator(new QIntValidator(this));
+        pOptLayout->addWidget(widthEdit, 5, 1);
+
+        // x
+        QLabel *labelX = new QLabel(pOptionsGroup);
+        labelX->setText("X");
+        pOptLayout->addWidget(labelX, 5, 2);
+
+        // height
+        heightEdit = new QLineEdit(pOptionsGroup);
+        heightEdit->setValidator(new QIntValidator(pOptionsGroup));
+        pOptLayout->addWidget(heightEdit, 5, 3);
+
+        // checkbox 'use game resolution'
+        checkUseGameRes = new QCheckBox(pOptionsGroup);
+        checkUseGameRes->setText(QCheckBox::tr("Use game resolution"));
+        pOptLayout->addWidget(checkUseGameRes, 5, 4);
+
+        // label for framerate
+        QLabel *labelFramerate = new QLabel(pOptionsGroup);
+        labelFramerate->setText(QLabel::tr("Framerate"));
+        pOptLayout->addWidget(labelFramerate, 6, 0);
+
+        framerateBox = new QComboBox(pOptionsGroup);
+        framerateBox->addItem("24 fps", 24);
+        framerateBox->addItem("25 fps", 25);
+        framerateBox->addItem("30 fps", 30);
+        framerateBox->addItem("50 fps", 50);
+        framerateBox->addItem("60 fps", 60);
+        pOptLayout->addWidget(framerateBox, 6, 1);
+
+        // label for Bitrate
+        QLabel *labelBitrate = new QLabel(pOptionsGroup);
+        labelBitrate->setText(QLabel::tr("Bitrate (Kbps)"));
+        pOptLayout->addWidget(labelBitrate, 6, 2);
+
+        // bitrate
+        bitrateBox = new QSpinBox(pOptionsGroup);
+        bitrateBox->setRange(100, 5000);
+        bitrateBox->setSingleStep(100);
+        pOptLayout->addWidget(bitrateBox, 6, 3);
+
+        // button 'set default options'
+        btnDefaults = new QPushButton(pOptionsGroup);
+        btnDefaults->setText(QPushButton::tr("Set default options"));
+        btnDefaults->setWhatsThis(QPushButton::tr("Restore default coding parameters"));
+        pOptLayout->addWidget(btnDefaults, 7, 0, 1, 5);
+
+        page3Layout->addWidget(pOptionsGroup, 1, 0);
+    }
+#endif
 
     previousQuality = this->SLQuality->value();
     previousResolutionIndex = this->CBResolution->currentIndex();
@@ -492,6 +614,13 @@
 
 void PageOptions::connectSignals()
 {
+#ifdef VIDEOREC
+    connect(checkUseGameRes, SIGNAL(stateChanged(int)), this, SLOT(changeUseGameRes(int)));
+    connect(checkRecordAudio, SIGNAL(stateChanged(int)), this, SLOT(changeRecordAudio(int)));
+    connect(comboAVFormats, SIGNAL(currentIndexChanged(int)), this, SLOT(changeAVFormat(int)));
+    connect(btnDefaults, SIGNAL(clicked()), this, SLOT(setDefaultOptions()));
+#endif
+
     connect(SLQuality, SIGNAL(valueChanged(int)), this, SLOT(setQuality(int)));
     connect(CBResolution, SIGNAL(currentIndexChanged(int)), this, SLOT(setResolution(int)));
     connect(CBFullscreen, SIGNAL(stateChanged(int)), this, SLOT(setFullscreen(int)));
@@ -500,7 +629,7 @@
     connect(CBSavePassword, SIGNAL(stateChanged(int)), this, SLOT(savePwdChanged(int)));
 }
 
-PageOptions::PageOptions(QWidget* parent) : AbstractPage(parent)
+PageOptions::PageOptions(QWidget* parent) : AbstractPage(parent), config(0)
 {
     initPage();
 }
@@ -619,3 +748,128 @@
     leProxyLogin->setEnabled(b);
     leProxyPassword->setEnabled(b);
 }
+
+// Video Recording
+
+void PageOptions::setConfig(GameUIConfig * config)
+{
+    this->config = config;
+}
+
+// user changed file format, we need to update list of codecs
+void PageOptions::changeAVFormat(int index)
+{
+    // remember selected codecs
+    QString prevVCodec = videoCodec();
+    QString prevACodec = audioCodec();
+
+    // clear lists of codecs
+    comboVideoCodecs->clear();
+    comboAudioCodecs->clear();
+
+    // get list of codecs for specified format
+    LibavInteraction::instance().fillCodecs(comboAVFormats->itemData(index).toString(), comboVideoCodecs, comboAudioCodecs);
+
+    // disable audio if there is no audio codec
+    if (comboAudioCodecs->count() == 0)
+    {
+        checkRecordAudio->setChecked(false);
+        checkRecordAudio->setEnabled(false);
+    }
+    else
+        checkRecordAudio->setEnabled(true);
+
+    // restore selected codecs if possible
+    int iVCodec = comboVideoCodecs->findData(prevVCodec);
+    if (iVCodec != -1)
+        comboVideoCodecs->setCurrentIndex(iVCodec);
+    int iACodec = comboAudioCodecs->findData(prevACodec);
+    if (iACodec != -1)
+        comboAudioCodecs->setCurrentIndex(iACodec);
+}
+
+// user switched checkbox 'use game resolution'
+void PageOptions::changeUseGameRes(int state)
+{
+    if (state && config)
+    {
+        // set resolution to game resolution
+        QRect resolution = config->vid_Resolution();
+        widthEdit->setText(QString::number(resolution.width()));
+        heightEdit->setText(QString::number(resolution.height()));
+    }
+    widthEdit->setEnabled(!state);
+    heightEdit->setEnabled(!state);
+}
+
+// user switched checkbox 'record audio'
+void PageOptions::changeRecordAudio(int state)
+{
+    comboAudioCodecs->setEnabled(!!state);
+}
+
+void PageOptions::setDefaultCodecs()
+{
+    // VLC should be able to handle any of these configurations
+    // Quicktime X only opens the first one
+    // Windows Media Player TODO
+    if (tryCodecs("mp4", "libx264", "aac"))
+        return;
+    if (tryCodecs("mp4", "libx264", "libfaac"))
+        return;
+    if (tryCodecs("mp4", "libx264", "libmp3lame"))
+        return;
+    if (tryCodecs("mp4", "libx264", "mp2"))
+        return;
+    if (tryCodecs("avi", "libxvid", "libmp3lame"))
+        return;
+    if (tryCodecs("avi", "libxvid", "ac3_fixed"))
+        return;
+    if (tryCodecs("avi", "libxvid", "mp2"))
+        return;
+    if (tryCodecs("avi", "mpeg4", "libmp3lame"))
+        return;
+    if (tryCodecs("avi", "mpeg4", "ac3_fixed"))
+        return;
+    if (tryCodecs("avi", "mpeg4", "mp2"))
+        return;
+
+    // this shouldn't happen, just in case
+    if (tryCodecs("ogg", "libtheora", "libvorbis"))
+        return;
+    tryCodecs("ogg", "libtheora", "flac");
+}
+
+void PageOptions::setDefaultOptions()
+{
+    framerateBox->setCurrentIndex(2);
+    bitrateBox->setValue(1000);
+    checkRecordAudio->setChecked(true);
+    checkUseGameRes->setChecked(true);
+    setDefaultCodecs();
+}
+
+bool PageOptions::tryCodecs(const QString & format, const QString & vcodec, const QString & acodec)
+{
+    // first we should change format
+    int iFormat = comboAVFormats->findData(format);
+    if (iFormat == -1)
+        return false;
+    comboAVFormats->setCurrentIndex(iFormat);
+    // format was changed, so lists of codecs were automatically updated to codecs supported by this format
+
+    // try to find video codec
+    int iVCodec = comboVideoCodecs->findData(vcodec);
+    if (iVCodec == -1)
+        return false;
+    comboVideoCodecs->setCurrentIndex(iVCodec);
+
+    // try to find audio codec
+    int iACodec = comboAudioCodecs->findData(acodec);
+    if (iACodec == -1 && checkRecordAudio->isChecked())
+        return false;
+    if (iACodec != -1)
+        comboAudioCodecs->setCurrentIndex(iACodec);
+
+    return true;
+}
--- a/QTfrontend/ui/page/pageoptions.h	Fri Nov 30 18:19:52 2012 +0400
+++ b/QTfrontend/ui/page/pageoptions.h	Tue Dec 04 09:15:55 2012 +0400
@@ -21,6 +21,7 @@
 
 #include "AbstractPage.h"
 
+class GameUIConfig;
 class FPSEdit;
 class IconedGroupBox;
 class QSignalMapper;
@@ -84,6 +85,28 @@
         QLineEdit * leProxyLogin;
         QLineEdit * leProxyPassword;
 
+#ifdef VIDEOREC
+        QComboBox  *framerateBox;
+        QSpinBox  *bitrateBox;
+        QLineEdit *widthEdit;
+        QLineEdit *heightEdit;
+        QCheckBox *checkUseGameRes;
+        QCheckBox *checkRecordAudio;
+
+        QString format()
+        { return comboAVFormats->itemData(comboAVFormats->currentIndex()).toString(); }
+
+        QString videoCodec()
+        { return comboVideoCodecs->itemData(comboVideoCodecs->currentIndex()).toString(); }
+
+        QString audioCodec()
+        { return comboAudioCodecs->itemData(comboAudioCodecs->currentIndex()).toString(); }
+
+        void setDefaultCodecs();
+        bool tryCodecs(const QString & format, const QString & vcodec, const QString & acodec);
+        void setConfig(GameUIConfig * config);
+#endif
+
         void setTeamOptionsEnabled(bool enabled);
 
     signals:
@@ -106,6 +129,14 @@
         QPushButton *BtnDeleteTeam;
         QList<QPushButton *> m_colorButtons;
 
+#ifdef VIDEOREC
+        QComboBox *comboAVFormats;
+        QComboBox *comboVideoCodecs;
+        QComboBox *comboAudioCodecs;
+        QPushButton *btnDefaults;
+        GameUIConfig * config;
+#endif
+
     private slots:
         void forceFullscreen(int index);
         void setFullscreen(int state);
@@ -118,6 +149,14 @@
         void colorButtonClicked(int i);
         void onColorModelDataChanged(const QModelIndex & topLeft, const QModelIndex & bottomRight);
         void onProxyTypeChanged();
+#ifdef VIDEOREC
+        void changeAVFormat(int index);
+        void changeUseGameRes(int state);
+        void changeRecordAudio(int state);
+
+    public slots:
+        void setDefaultOptions();
+#endif
 };
 
 #endif
--- a/QTfrontend/ui/page/pageroomslist.cpp	Fri Nov 30 18:19:52 2012 +0400
+++ b/QTfrontend/ui/page/pageroomslist.cpp	Tue Dec 04 09:15:55 2012 +0400
@@ -95,7 +95,7 @@
 
     pageLayout->addLayout(filterLayout, 4, 0, 1, 2);
 
-    chatWidget = new HWChatWidget(this, m_gameSettings, false);
+    chatWidget = new HWChatWidget(this, false);
     pageLayout->addWidget(chatWidget, 5, 0, 1, 3);
     pageLayout->setRowStretch(5, 350);
 
@@ -156,11 +156,9 @@
 }
 
 
-PageRoomsList::PageRoomsList(QWidget* parent, QSettings * gameSettings) :
+PageRoomsList::PageRoomsList(QWidget* parent) :
     AbstractPage(parent)
 {
-    m_gameSettings = gameSettings;
-
     roomsModel = NULL;
     stateFilteredModel = NULL;
     schemeFilteredModel = NULL;
@@ -612,13 +610,17 @@
             QString("*%1*").arg(CBWeapons->currentText()));
 }
 
+void PageRoomsList::setSettings(QSettings *settings)
+{
+    m_gameSettings = settings;
+}
 
 bool PageRoomsList::restoreHeaderState()
 {
     if (!m_gameSettings->contains("frontend/roomslist_header"))
         return false;
     return roomsList->horizontalHeader()->restoreState(QByteArray::fromBase64(
-        (m_gameSettings->value("frontend/roomslist_header").toString().toAscii())));
+        (m_gameSettings->value("frontend/roomslist_header").toByteArray())));
 }
 
 void PageRoomsList::saveHeaderState()
--- a/QTfrontend/ui/page/pageroomslist.h	Fri Nov 30 18:19:52 2012 +0400
+++ b/QTfrontend/ui/page/pageroomslist.h	Tue Dec 04 09:15:55 2012 +0400
@@ -32,10 +32,11 @@
         Q_OBJECT
 
     public:
-        PageRoomsList(QWidget* parent, QSettings * config);
+        PageRoomsList(QWidget* parent);
         void displayError(const QString & message);
         void displayNotice(const QString & message);
         void displayWarning(const QString & message);
+        void setSettings(QSettings * settings);
 
         QLineEdit * roomName;
         QLineEdit * searchText;
--- a/QTfrontend/ui/page/pagevideos.cpp	Fri Nov 30 18:19:52 2012 +0400
+++ b/QTfrontend/ui/page/pagevideos.cpp	Tue Dec 04 09:15:55 2012 +0400
@@ -109,119 +109,6 @@
     QGridLayout * pPageLayout = new QGridLayout();
     pPageLayout->setColumnStretch(0, 1);
     pPageLayout->setColumnStretch(1, 2);
-    pPageLayout->setRowStretch(0, 1);
-    pPageLayout->setRowStretch(1, 1);
-
-    // options
-    {
-        IconedGroupBox* pOptionsGroup = new IconedGroupBox(this);
-        pOptionsGroup->setIcon(QIcon(":/res/Settings.png")); // FIXME
-        pOptionsGroup->setSizePolicy(QSizePolicy::Expanding, QSizePolicy::Expanding);
-        pOptionsGroup->setTitle(QGroupBox::tr("Video recording options"));
-        QGridLayout * pOptLayout = new QGridLayout(pOptionsGroup);
-
-        // label for format
-        QLabel *labelFormat = new QLabel(pOptionsGroup);
-        labelFormat->setText(QLabel::tr("Format"));
-        pOptLayout->addWidget(labelFormat, 0, 0);
-
-        // list of supported formats
-        comboAVFormats = new QComboBox(pOptionsGroup);
-        pOptLayout->addWidget(comboAVFormats, 0, 1, 1, 4);
-        LibavInteraction::instance().fillFormats(comboAVFormats);
-
-        // separator
-        QFrame * hr = new QFrame(pOptionsGroup);
-        hr->setFrameStyle(QFrame::HLine);
-        hr->setLineWidth(3);
-        hr->setFixedHeight(10);
-        pOptLayout->addWidget(hr, 1, 0, 1, 5);
-
-        // label for audio codec
-        QLabel *labelACodec = new QLabel(pOptionsGroup);
-        labelACodec->setText(QLabel::tr("Audio codec"));
-        pOptLayout->addWidget(labelACodec, 2, 0);
-
-        // list of supported audio codecs
-        comboAudioCodecs = new QComboBox(pOptionsGroup);
-        pOptLayout->addWidget(comboAudioCodecs, 2, 1, 1, 3);
-
-        // checkbox 'record audio'
-        checkRecordAudio = new QCheckBox(pOptionsGroup);
-        checkRecordAudio->setText(QCheckBox::tr("Record audio"));
-        pOptLayout->addWidget(checkRecordAudio, 2, 4);
-
-        // separator
-        hr = new QFrame(pOptionsGroup);
-        hr->setFrameStyle(QFrame::HLine);
-        hr->setLineWidth(3);
-        hr->setFixedHeight(10);
-        pOptLayout->addWidget(hr, 3, 0, 1, 5);
-
-        // label for video codec
-        QLabel *labelVCodec = new QLabel(pOptionsGroup);
-        labelVCodec->setText(QLabel::tr("Video codec"));
-        pOptLayout->addWidget(labelVCodec, 4, 0);
-
-        // list of supported video codecs
-        comboVideoCodecs = new QComboBox(pOptionsGroup);
-        pOptLayout->addWidget(comboVideoCodecs, 4, 1, 1, 4);
-
-        // label for resolution
-        QLabel *labelRes = new QLabel(pOptionsGroup);
-        labelRes->setText(QLabel::tr("Resolution"));
-        pOptLayout->addWidget(labelRes, 5, 0);
-
-        // width
-        widthEdit = new QLineEdit(pOptionsGroup);
-        widthEdit->setValidator(new QIntValidator(this));
-        pOptLayout->addWidget(widthEdit, 5, 1);
-
-        // x
-        QLabel *labelX = new QLabel(pOptionsGroup);
-        labelX->setText("X");
-        pOptLayout->addWidget(labelX, 5, 2);
-
-        // height
-        heightEdit = new QLineEdit(pOptionsGroup);
-        heightEdit->setValidator(new QIntValidator(pOptionsGroup));
-        pOptLayout->addWidget(heightEdit, 5, 3);
-
-        // checkbox 'use game resolution'
-        checkUseGameRes = new QCheckBox(pOptionsGroup);
-        checkUseGameRes->setText(QCheckBox::tr("Use game resolution"));
-        pOptLayout->addWidget(checkUseGameRes, 5, 4);
-
-        // label for framerate
-        QLabel *labelFramerate = new QLabel(pOptionsGroup);
-        labelFramerate->setText(QLabel::tr("Framerate"));
-        pOptLayout->addWidget(labelFramerate, 6, 0);
-
-        // framerate
-        framerateBox = new QSpinBox(pOptionsGroup);
-        framerateBox->setRange(1, 200);
-        framerateBox->setSingleStep(1);
-        pOptLayout->addWidget(framerateBox, 6, 1);
-
-        // label for Bitrate
-        QLabel *labelBitrate = new QLabel(pOptionsGroup);
-        labelBitrate->setText(QLabel::tr("Bitrate (Kbps)"));
-        pOptLayout->addWidget(labelBitrate, 6, 2);
-
-        // bitrate
-        bitrateBox = new QSpinBox(pOptionsGroup);
-        bitrateBox->setRange(100, 5000);
-        bitrateBox->setSingleStep(100);
-        pOptLayout->addWidget(bitrateBox, 6, 3);
-
-        // button 'set default options'
-        btnDefaults = new QPushButton(pOptionsGroup);
-        btnDefaults->setText(QPushButton::tr("Set default options"));
-        btnDefaults->setWhatsThis(QPushButton::tr("Restore default coding parameters"));
-        pOptLayout->addWidget(btnDefaults, 7, 0, 1, 5);
-
-        pPageLayout->addWidget(pOptionsGroup, 1, 0);
-    }
 
     // list of videos
     {
@@ -257,7 +144,7 @@
         box->addWidget(filesTable);
         box->addWidget(btnOpenDir);
 
-        pPageLayout->addWidget(pTableGroup, 0, 1, 2, 1);
+        pPageLayout->addWidget(pTableGroup, 0, 1);
     }
 
     // description
@@ -267,7 +154,6 @@
         pDescGroup->setTitle(QGroupBox::tr("Description"));
 
         QVBoxLayout* pDescLayout = new QVBoxLayout(pDescGroup);
-        QHBoxLayout* pTopDescLayout = new QHBoxLayout(0);    // picture and text
         QHBoxLayout* pBottomDescLayout = new QHBoxLayout(0); // buttons
 
         // label with thumbnail picture
@@ -282,7 +168,6 @@
                     "border-radius: 4px;"
                     "}" );
         clearThumbnail();
-        pTopDescLayout->addWidget(labelThumbnail, 2);
 
         // label with file description
         labelDesc = new QLabel(pDescGroup);
@@ -293,7 +178,8 @@
                                            Qt::LinksAccessibleByKeyboard);
         labelDesc->setTextFormat(Qt::RichText);
         labelDesc->setOpenExternalLinks(true);
-        pTopDescLayout->addWidget(labelDesc, 1);
+        labelDesc->setMinimumSize(ThumbnailSize);
+        //pTopDescLayout->addWidget(labelDesc, 1);
 
         // buttons: play and delete
         btnPlay = new QPushButton(QPushButton::tr("Play"), pDescGroup);
@@ -310,7 +196,9 @@
         pBottomDescLayout->addWidget(btnToYouTube);
 
         pDescLayout->addStretch(1);
-        pDescLayout->addLayout(pTopDescLayout, 0);
+        pDescLayout->addWidget(labelThumbnail, 0);
+        pDescLayout->addStretch(1);
+        pDescLayout->addWidget(labelDesc, 0);
         pDescLayout->addStretch(1);
         pDescLayout->addLayout(pBottomDescLayout, 0);
 
@@ -327,10 +215,6 @@
 
 void PageVideos::connectSignals()
 {
-    connect(checkUseGameRes, SIGNAL(stateChanged(int)), this, SLOT(changeUseGameRes(int)));
-    connect(checkRecordAudio, SIGNAL(stateChanged(int)), this, SLOT(changeRecordAudio(int)));
-    connect(comboAVFormats, SIGNAL(currentIndexChanged(int)), this, SLOT(changeAVFormat(int)));
-    connect(btnDefaults, SIGNAL(clicked()), this, SLOT(setDefaultOptions()));
     connect(filesTable, SIGNAL(cellDoubleClicked(int, int)), this, SLOT(cellDoubleClicked(int, int)));
     connect(filesTable, SIGNAL(cellChanged(int,int)), this, SLOT(cellChanged(int, int)));
     connect(filesTable, SIGNAL(currentCellChanged(int,int,int,int)), this, SLOT(currentCellChanged()));
@@ -362,124 +246,6 @@
     startEncoding(); // this is for videos recorded from demos which were executed directly (without frontend)
 }
 
-// user changed file format, we need to update list of codecs
-void PageVideos::changeAVFormat(int index)
-{
-    // remember selected codecs
-    QString prevVCodec = videoCodec();
-    QString prevACodec = audioCodec();
-
-    // clear lists of codecs
-    comboVideoCodecs->clear();
-    comboAudioCodecs->clear();
-
-    // get list of codecs for specified format
-    LibavInteraction::instance().fillCodecs(comboAVFormats->itemData(index).toString(), comboVideoCodecs, comboAudioCodecs);
-
-    // disable audio if there is no audio codec
-    if (comboAudioCodecs->count() == 0)
-    {
-        checkRecordAudio->setChecked(false);
-        checkRecordAudio->setEnabled(false);
-    }
-    else
-        checkRecordAudio->setEnabled(true);
-
-    // restore selected codecs if possible
-    int iVCodec = comboVideoCodecs->findData(prevVCodec);
-    if (iVCodec != -1)
-        comboVideoCodecs->setCurrentIndex(iVCodec);
-    int iACodec = comboAudioCodecs->findData(prevACodec);
-    if (iACodec != -1)
-        comboAudioCodecs->setCurrentIndex(iACodec);
-}
-
-// user switched checkbox 'use game resolution'
-void PageVideos::changeUseGameRes(int state)
-{
-    if (state && config)
-    {
-        // set resolution to game resolution
-        QRect resolution = config->vid_Resolution();
-        widthEdit->setText(QString::number(resolution.width()));
-        heightEdit->setText(QString::number(resolution.height()));
-    }
-    widthEdit->setEnabled(!state);
-    heightEdit->setEnabled(!state);
-}
-
-// user switched checkbox 'record audio'
-void PageVideos::changeRecordAudio(int state)
-{
-    comboAudioCodecs->setEnabled(!!state);
-}
-
-void PageVideos::setDefaultCodecs()
-{
-    // VLC should be able to handle any of these configurations
-    // Quicktime X only opens the first one
-    // Windows Media Player TODO
-    if (tryCodecs("mp4", "libx264", "aac"))
-        return;
-    if (tryCodecs("mp4", "libx264", "libfaac"))
-        return;
-    if (tryCodecs("mp4", "libx264", "libmp3lame"))
-        return;
-    if (tryCodecs("mp4", "libx264", "mp2"))
-        return;
-    if (tryCodecs("avi", "libxvid", "libmp3lame"))
-        return;
-    if (tryCodecs("avi", "libxvid", "ac3_fixed"))
-        return;
-    if (tryCodecs("avi", "libxvid", "mp2"))
-        return;
-    if (tryCodecs("avi", "mpeg4", "libmp3lame"))
-        return;
-    if (tryCodecs("avi", "mpeg4", "ac3_fixed"))
-        return;
-    if (tryCodecs("avi", "mpeg4", "mp2"))
-        return;
-
-    // this shouldn't happen, just in case
-    if (tryCodecs("ogg", "libtheora", "libvorbis"))
-        return;
-    tryCodecs("ogg", "libtheora", "flac");
-}
-
-void PageVideos::setDefaultOptions()
-{
-    framerateBox->setValue(30);
-    bitrateBox->setValue(1000);
-    checkRecordAudio->setChecked(true);
-    checkUseGameRes->setChecked(true);
-    setDefaultCodecs();
-}
-
-bool PageVideos::tryCodecs(const QString & format, const QString & vcodec, const QString & acodec)
-{
-    // first we should change format
-    int iFormat = comboAVFormats->findData(format);
-    if (iFormat == -1)
-        return false;
-    comboAVFormats->setCurrentIndex(iFormat);
-    // format was changed, so lists of codecs were automatically updated to codecs supported by this format
-
-    // try to find video codec
-    int iVCodec = comboVideoCodecs->findData(vcodec);
-    if (iVCodec == -1)
-        return false;
-    comboVideoCodecs->setCurrentIndex(iVCodec);
-
-    // try to find audio codec
-    int iACodec = comboAudioCodecs->findData(acodec);
-    if (iACodec == -1 && checkRecordAudio->isChecked())
-        return false;
-    if (iACodec != -1)
-        comboAudioCodecs->setCurrentIndex(iACodec);
-
-    return true;
-}
-
 // get file size as string
 static QString FileSizeStr(const QString & path)
 {
--- a/QTfrontend/ui/page/pagevideos.h	Fri Nov 30 18:19:52 2012 +0400
+++ b/QTfrontend/ui/page/pagevideos.h	Tue Dec 04 09:15:55 2012 +0400
@@ -36,24 +36,6 @@
     public:
         PageVideos(QWidget* parent = 0);
 
-        QSpinBox  *framerateBox;
-        QSpinBox  *bitrateBox;
-        QLineEdit *widthEdit;
-        QLineEdit *heightEdit;
-        QCheckBox *checkUseGameRes;
-        QCheckBox *checkRecordAudio;
-
-        QString format()
-        { return comboAVFormats->itemData(comboAVFormats->currentIndex()).toString(); }
-
-        QString videoCodec()
-        { return comboVideoCodecs->itemData(comboVideoCodecs->currentIndex()).toString(); }
-
-        QString audioCodec()
-        { return comboAudioCodecs->itemData(comboAudioCodecs->currentIndex()).toString(); }
-
-        void setDefaultCodecs();
-        bool tryCodecs(const QString & format, const QString & vcodec, const QString & acodec);
         void addRecorder(HWRecorder* pRecorder);
         bool tryQuit(HWForm *form);
         QString getVideosInProgress(); // get multi-line string with list of videos in progress
@@ -83,12 +65,6 @@
         GameUIConfig * config;
         QNetworkAccessManager* netManager;
 
-        // options group
-        QComboBox *comboAVFormats;
-        QComboBox *comboVideoCodecs;
-        QComboBox *comboAudioCodecs;
-        QPushButton *btnDefaults;
-
         // file list group
         QTableWidget *filesTable;
         QPushButton *btnOpenDir;
@@ -105,10 +81,6 @@
         int numRecorders, numUploads;
 
     private slots:
-        void changeAVFormat(int index);
-        void changeUseGameRes(int state);
-        void changeRecordAudio(int state);
-        void setDefaultOptions();
         void encodingFinished(bool success);
         void updateProgress(float value);
         void cellDoubleClicked(int row, int column);
--- a/QTfrontend/ui/widget/chatwidget.cpp	Fri Nov 30 18:19:52 2012 +0400
+++ b/QTfrontend/ui/widget/chatwidget.cpp	Tue Dec 04 09:15:55 2012 +0400
@@ -177,7 +177,7 @@
 }
 
 
-HWChatWidget::HWChatWidget(QWidget* parent, QSettings * gameSettings, bool notify) :
+HWChatWidget::HWChatWidget(QWidget* parent, bool notify) :
     QWidget(parent),
     mainLayout(this)
 {
@@ -187,7 +187,6 @@
     m_isAdmin = false;
     m_autoKickEnabled = false;
 
-    if(gameSettings->value("frontend/sound", true).toBool())
     {
         QStringList vpList =
              QStringList() << "Classic" << "Default" << "Mobster" << "Russian";
@@ -281,6 +280,10 @@
     clear();
 }
 
+void HWChatWidget::setSettings(QSettings * settings)
+{
+    gameSettings = settings;
+}
 
 void HWChatWidget::linkClicked(const QUrl & link)
 {
--- a/QTfrontend/ui/widget/chatwidget.h	Fri Nov 30 18:19:52 2012 +0400
+++ b/QTfrontend/ui/widget/chatwidget.h	Tue Dec 04 09:15:55 2012 +0400
@@ -54,7 +54,7 @@
         Q_OBJECT
 
     public:
-        HWChatWidget(QWidget* parent, QSettings * gameSettings, bool notify);
+        HWChatWidget(QWidget* parent, bool notify);
         void setIgnoreListKick(bool enabled); ///< automatically kick people on ignore list (if possible)
         void setShowFollow(bool enabled);
         static const QString & styleSheet();
@@ -63,6 +63,7 @@
         void displayWarning(const QString & message);
         void setUser(const QString & nickname);
         void setUsersModel(QAbstractItemModel * model);
+        void setSettings(QSettings * settings);
 
     protected:
         virtual void dragEnterEvent(QDragEnterEvent * event);
--- a/QTfrontend/ui/widget/teamselect.cpp	Fri Nov 30 18:19:52 2012 +0400
+++ b/QTfrontend/ui/widget/teamselect.cpp	Tue Dec 04 09:15:55 2012 +0400
@@ -59,6 +59,7 @@
                     this, SLOT(changeTeamStatus(HWTeam)));
         }
     }
+
     emit setEnabledGameStart(curPlayingTeams.size()>1);
 }
 
@@ -168,6 +169,12 @@
         m_curNotPlayingTeams.push_back(*itPlay);
         emit teamNotPlaying(*itPlay);
         curPlayingTeams.erase(itPlay);
+
+        // Show team notice if less than two teams.
+        if (curPlayingTeams.size() < 2)
+        {
+            numTeamNotice->show();
+        }
     }
     else
     {
@@ -179,6 +186,12 @@
         curPlayingTeams.push_back(*itDontPlay);
         if(!m_acceptOuter) emit teamWillPlay(*itDontPlay);
         m_curNotPlayingTeams.erase(itDontPlay);
+
+        // Hide team notice if at least two teams.
+        if (curPlayingTeams.size() >= 2)
+        {
+            numTeamNotice->hide();
+        }
     }
 
     FrameTeams* pRemoveTeams;
@@ -254,6 +267,10 @@
     framePlaying = new FrameTeams();
     frameDontPlaying = new FrameTeams();
 
+    // Add notice about number of required teams.
+    numTeamNotice = new QLabel("Two teams are required to play!");
+    mainLayout.addWidget(numTeamNotice);
+
     QPalette p;
     p.setColor(QPalette::Window, QColor(0x00, 0x00, 0x00));
     addScrArea(framePlaying, p.color(QPalette::Window).light(105), 250);
--- a/QTfrontend/ui/widget/teamselect.h	Fri Nov 30 18:19:52 2012 +0400
+++ b/QTfrontend/ui/widget/teamselect.h	Tue Dec 04 09:15:55 2012 +0400
@@ -20,6 +20,7 @@
 #ifndef _TEAM_SELECT_INCLUDED
 #define _TEAM_SELECT_INCLUDED
 
+#include <QLabel>
 #include <QGroupBox>
 #include <QVBoxLayout>
 #include <QColor>
@@ -74,6 +75,7 @@
         FrameTeams* framePlaying;
 
         QVBoxLayout mainLayout;
+        QLabel *numTeamNotice;
         bool m_acceptOuter;
 
         QList<HWTeam> curPlayingTeams;
--- a/QTfrontend/ui_hwform.cpp	Fri Nov 30 18:19:52 2012 +0400
+++ b/QTfrontend/ui_hwform.cpp	Tue Dec 04 09:15:55 2012 +0400
@@ -60,7 +60,7 @@
     centralWidget = new QWidget(HWForm);
     centralWidget->setObjectName(QString::fromUtf8("centralWidget"));
 
-    SetupPages(centralWidget, HWForm);
+    SetupPages(centralWidget);
 
     HWForm->setCentralWidget(centralWidget);
 
@@ -74,7 +74,7 @@
     font14 = new QFont("MS Shell Dlg", 14);
 }
 
-void Ui_HWForm::SetupPages(QWidget *Parent, HWForm *HWForm)
+void Ui_HWForm::SetupPages(QWidget *Parent)
 {
     Pages = new QStackedLayout(Parent);
 
@@ -93,7 +93,7 @@
     pageNet = new PageNet();
     Pages->addWidget(pageNet);
 
-    pageNetGame = new PageNetGame(Parent, HWForm->gameSettings);
+    pageNetGame = new PageNetGame(Parent);
     Pages->addWidget(pageNetGame);
 
     pageInfo = new PageInfo();
@@ -120,7 +120,7 @@
     pageInGame = new PageInGame();
     Pages->addWidget(pageInGame);
 
-    pageRoomsList = new PageRoomsList(Parent, HWForm->gameSettings);
+    pageRoomsList = new PageRoomsList(Parent);
     Pages->addWidget(pageRoomsList);
 
     pageConnecting = new PageConnecting();
--- a/QTfrontend/ui_hwform.h	Fri Nov 30 18:19:52 2012 +0400
+++ b/QTfrontend/ui_hwform.h	Tue Dec 04 09:15:55 2012 +0400
@@ -86,7 +86,7 @@
 
         void setupUi(HWForm *HWForm);
         void SetupFonts();
-        void SetupPages(QWidget *Parent, HWForm *HWForm);
+        void SetupPages(QWidget *Parent);
 };
 
 #endif // UI_HWFORM_H
--- a/QTfrontend/util/FileEngine.cpp	Fri Nov 30 18:19:52 2012 +0400
+++ b/QTfrontend/util/FileEngine.cpp	Tue Dec 04 09:15:55 2012 +0400
@@ -10,8 +10,10 @@
 
 FileEngine::FileEngine(const QString& filename)
     : m_handle(NULL)
+    , m_size(0)
     , m_flags(0)
     , m_bufferSet(false)
+    , m_readWrite(false)
 {
     setFileName(filename);
 }
@@ -25,7 +27,16 @@
 {
     close();
 
-    if (openMode & QIODevice::WriteOnly) {
+    if ((openMode & QIODevice::ReadWrite) == QIODevice::ReadWrite) {
+        m_handle = PHYSFS_openAppend(m_fileName.toUtf8().constData());
+        if(m_handle)
+        {
+            m_readWrite = true;
+            seek(0);
+        }
+    }
+
+    else if (openMode & QIODevice::WriteOnly) {
         m_handle = PHYSFS_openWrite(m_fileName.toUtf8().constData());
         m_flags = QAbstractFileEngine::WriteOwnerPerm | QAbstractFileEngine::WriteUserPerm | QAbstractFileEngine::FileType;
     }
@@ -76,9 +87,22 @@
     return PHYSFS_tell(m_handle);
 }
 
+bool FileEngine::setSize(qint64 size)
+{
+    if(size == 0)
+    {
+        m_size = 0;
+        return open(QIODevice::WriteOnly);
+    }
+    else
+        return false;
+}
+
 bool FileEngine::seek(qint64 pos)
 {
-    return PHYSFS_seek(m_handle, pos) != 0;
+    bool ok = PHYSFS_seek(m_handle, pos) != 0;
+
+    return ok;
 }
 
 bool FileEngine::isSequential() const
@@ -94,12 +118,14 @@
 bool FileEngine::mkdir(const QString &dirName, bool createParentDirectories) const
 {
     Q_UNUSED(createParentDirectories);
+
     return PHYSFS_mkdir(dirName.toUtf8().constData()) != 0;
 }
 
 bool FileEngine::rmdir(const QString &dirName, bool recurseParentDirectories) const
 {
     Q_UNUSED(recurseParentDirectories);
+
     return PHYSFS_delete(dirName.toUtf8().constData()) != 0;
 }
 
@@ -110,7 +136,7 @@
 
 bool FileEngine::isRelativePath() const
 {
-    return true;
+    return false;
 }
 
 QAbstractFileEngineIterator * FileEngine::beginEntryList(QDir::Filters filters, const QStringList &filterNames)
@@ -171,7 +197,6 @@
 
 QDateTime FileEngine::fileTime(FileTime time) const
 {
-
     switch (time)
     {
         case QAbstractFileEngine::ModificationTime:
@@ -187,21 +212,21 @@
         m_fileName = file.mid(FileEngineHandler::scheme.size());
     else
         m_fileName = file;
-
     PHYSFS_Stat stat;
-    if (PHYSFS_stat(m_fileName.toUtf8().constData(), &stat) != 0) {
+    if (PHYSFS_stat(m_fileName.toUtf8().constData(), &stat) != 0) {        
         m_size = stat.filesize;
         m_date = QDateTime::fromTime_t(stat.modtime);
-//        _flags |= QAbstractFileEngine::WriteUserPerm;
+//        m_flags |= QAbstractFileEngine::WriteOwnerPerm;
+        m_flags |= QAbstractFileEngine::ReadOwnerPerm;
         m_flags |= QAbstractFileEngine::ReadUserPerm;
         m_flags |= QAbstractFileEngine::ExistsFlag;
+        m_flags |= QAbstractFileEngine::LocalDiskFlag;
 
         switch (stat.filetype)
         {
             case PHYSFS_FILETYPE_REGULAR:
                 m_flags |= QAbstractFileEngine::FileType;
                 break;
-
             case PHYSFS_FILETYPE_DIRECTORY:
                 m_flags |= QAbstractFileEngine::DirectoryType;
                 break;
@@ -220,7 +245,16 @@
 
 qint64 FileEngine::read(char *data, qint64 maxlen)
 {
-    return PHYSFS_readBytes(m_handle, data, maxlen);
+    if(m_readWrite)
+    {
+        if(pos() == 0)
+            open(QIODevice::ReadOnly);
+        else
+            return -1;
+    }
+
+    qint64 len = PHYSFS_readBytes(m_handle, data, maxlen);
+    return len;
 }
 
 qint64 FileEngine::readLine(char *data, qint64 maxlen)
@@ -286,7 +320,7 @@
 QAbstractFileEngine* FileEngineHandler::create(const QString &filename) const
 {
     if (filename.startsWith(scheme))
-        return new FileEngine(filename.mid(scheme.size()));
+        return new FileEngine(filename);
     else
         return NULL;
 }
--- a/QTfrontend/util/FileEngine.h	Fri Nov 30 18:19:52 2012 +0400
+++ b/QTfrontend/util/FileEngine.h	Tue Dec 04 09:15:55 2012 +0400
@@ -22,6 +22,7 @@
         virtual bool flush();
         virtual qint64 size() const;
         virtual qint64 pos() const;
+        virtual bool setSize(qint64 size);
         virtual bool seek(qint64 pos);
         virtual bool isSequential() const;
         virtual bool remove();
@@ -55,6 +56,7 @@
         QString m_fileName;
         QDateTime m_date;
         bool m_bufferSet;
+        bool m_readWrite;
 };
 
 class FileEngineHandler : public QAbstractFileEngineHandler
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/cmake_modules/FindFreepascal.cmake	Tue Dec 04 09:15:55 2012 +0400
@@ -0,0 +1,36 @@
+# Load Freepascal
+if (FPC)
+    set(FPC_EXECUTABLE ${FPC})
+else()
+    find_program(FPC_EXECUTABLE
+        NAMES fpc
+        PATHS /opt/local/bin /usr/local/bin /usr/bin)
+endif()
+
+# Check Freepascal version
+if (FPC_EXECUTABLE)
+    exec_program(${FPC_EXECUTABLE} ARGS "-v" OUTPUT_VARIABLE FPC_VERSION_FULL)
+
+    string(REGEX MATCH "[0-9]+\\.[0-9]+" FPC_VERSION_LONG "${FPC_VERSION_FULL}")
+    string(REGEX REPLACE "([0-9]+\\.[0-9]+)" "\\1" FPC_VERSION "${FPC_VERSION_LONG}")
+    message(STATUS "Found Freepascal: ${FPC_EXECUTABLE} (version ${FPC_VERSION}")
+else()
+    message(FATAL_ERROR "Could NOT find Freepascal")
+endif()
+
+# Check for noexecstack flag support
+set(NOEXECSTACK_FLAGS "-k-z" "-knoexecstack")
+file(WRITE ${EXECUTABLE_OUTPUT_PATH}/checkstack.pas "begin end.")
+
+execute_process(COMMAND ${FPC_EXECUTABLE} ${NOEXECSTACK_FLAGS} checkstack.pas
+    WORKING_DIRECTORY ${EXECUTABLE_OUTPUT_PATH}
+    RESULT_VARIABLE TEST_NOEXECSTACK
+    OUTPUT_QUIET ERROR_QUIET)
+
+if (TEST_NOEXECSTACK)
+    set(NOEXECSTACK_FLAGS "")
+    message(STATUS "Checking whether linker needs explicit noexecstack -- no")
+else(TEST_NOEXECSTACK)
+    message(STATUS "Checking whether linker needs explicit noexecstack -- yes")
+endif(TEST_NOEXECSTACK)
+
--- a/gameServer/Actions.hs	Fri Nov 30 18:19:52 2012 +0400
+++ b/gameServer/Actions.hs	Tue Dec 04 09:15:55 2012 +0400
@@ -52,6 +52,7 @@
     | KickRoomClient ClientIndex
     | BanClient NominalDiffTime B.ByteString ClientIndex
     | BanIP B.ByteString NominalDiffTime B.ByteString
+    | BanNick B.ByteString NominalDiffTime B.ByteString
     | BanList
     | Unban B.ByteString
     | ChangeMaster
@@ -154,7 +155,7 @@
 
     when loggedIn $ processAction $ AnswerClients clientsChans ["LOBBY:LEFT", clNick, msg]
 
-    mapM processAction
+    mapM_ processAction
         [
         AnswerClients [chan] ["BYE", msg]
         , ModifyClient (\c -> c{nick = "", logonPassed = False}) -- this will effectively hide client from others while he isn't deleted from list
@@ -440,17 +441,25 @@
     return ()
 
 
-processAction (ProcessAccountInfo info) =
+processAction (ProcessAccountInfo info) = do
     case info of
         HasAccount passwd isAdmin -> do
-            chan <- client's sendChan
-            mapM_ processAction [AnswerClients [chan] ["ASKPASSWORD"], ModifyClient (\c -> c{webPassword = passwd, isAdministrator = isAdmin})]
-        Guest ->
-            processAction JoinLobby
+            b <- isBanned
+            when (not b) $ do
+                chan <- client's sendChan
+                mapM_ processAction [AnswerClients [chan] ["ASKPASSWORD"], ModifyClient (\c -> c{webPassword = passwd, isAdministrator = isAdmin})]
+        Guest -> do
+            b <- isBanned
+            when (not b) $
+                processAction JoinLobby
         Admin -> do
             mapM_ processAction [ModifyClient (\cl -> cl{isAdministrator = True}), JoinLobby]
             chan <- client's sendChan
             processAction $ AnswerClients [chan] ["ADMIN_ACCESS"]
+    where
+    isBanned = do
+        processAction CheckBanned
+        liftM B.null $ client's nick
 
 
 processAction JoinLobby = do
@@ -500,14 +509,28 @@
     processAction $
         AddIP2Bans ip msg (addUTCTime seconds currentTime)
 
+processAction (BanNick n seconds reason) = do
+    currentTime <- io getCurrentTime
+    let msg = 
+            if seconds > 60 * 60 * 24 * 365 then
+                B.concat ["Permanent ban (", reason, ")"]
+                else
+                B.concat ["Ban for ", B.pack . show $ seconds, " (", reason, ")"]
+    processAction $
+        AddNick2Bans n msg (addUTCTime seconds currentTime)
+
 processAction BanList = do
+    time <- io $ getCurrentTime
     ch <- client's sendChan
-    b <- gets (B.pack . unlines . map show . bans . serverInfo)
+    b <- gets (B.intercalate "\n" . concatMap (ban2Str time) . bans . serverInfo)
     processAction $
         AnswerClients [ch] ["BANLIST", b]
+    where
+        ban2Str time (BanByIP b r t) = ["I", b, r, B.pack . show $ t `diffUTCTime` time]
+        ban2Str time (BanByNick b r t) = ["N", b, r, B.pack . show $ t `diffUTCTime` time]
 
 processAction (Unban entry) = do
-    processAction $ ModifyServerInfo (\s -> s{bans = filter f $ bans s})
+    processAction $ ModifyServerInfo (\s -> s{bans = filter (not . f) $ bans s})
     where
         f (BanByIP bip _ _) = bip == entry
         f (BanByNick bn _ _) = bn == entry
@@ -561,7 +584,7 @@
         checkNotExpired testTime (BanByIP _ _ time) = testTime `diffUTCTime` time <= 0
         checkNotExpired testTime (BanByNick _ _ time) = testTime `diffUTCTime` time <= 0
         checkBan ip _ (BanByIP bip _ _) = bip `B.isPrefixOf` ip
-        checkBan _ n (BanByNick bn _ _) = bn == n
+        checkBan _ n (BanByNick bn _ _) = caseInsensitiveCompare bn n
         getBanReason (BanByIP _ msg _) = msg
         getBanReason (BanByNick _ msg _) = msg
 
--- a/gameServer/HWProtoInRoomState.hs	Fri Nov 30 18:19:52 2012 +0400
+++ b/gameServer/HWProtoInRoomState.hs	Tue Dec 04 09:15:55 2012 +0400
@@ -308,8 +308,8 @@
     let sameRoom = clientRoom rnc thisClientId == clientRoom rnc banId
     if master && isJust maybeClientId && (banId /= thisClientId) && sameRoom then
         return [
-                ModifyRoom (\r -> r{roomBansList = let h = host $ rnc `client` banId in h `deepseq` h : roomBansList r})
-              , KickRoomClient banId
+--                ModifyRoom (\r -> r{roomBansList = let h = host $ rnc `client` banId in h `deepseq` h : roomBansList r})
+                KickRoomClient banId
             ]
         else
         return []
--- a/gameServer/HWProtoLobbyState.hs	Fri Nov 30 18:19:52 2012 +0400
+++ b/gameServer/HWProtoLobbyState.hs	Tue Dec 04 09:15:55 2012 +0400
@@ -150,16 +150,20 @@
     return [KickClient $ fromJust kickId | isAdministrator cl && isJust kickId && fromJust kickId /= ci]
 
 
-handleCmd_lobby ["BAN", banNick, reason] = do
+handleCmd_lobby ["BAN", banNick, reason, duration] = do
     (ci, _) <- ask
     cl <- thisClient
     banId <- clientByNick banNick
-    return [BanClient 60 reason (fromJust banId) | isAdministrator cl && isJust banId && fromJust banId /= ci]
+    return [BanClient (readInt_ duration) reason (fromJust banId) | isAdministrator cl && isJust banId && fromJust banId /= ci]
 
 handleCmd_lobby ["BANIP", ip, reason, duration] = do
     cl <- thisClient
     return [BanIP ip (readInt_ duration) reason | isAdministrator cl]
 
+handleCmd_lobby ["BANNICK", n, reason, duration] = do
+    cl <- thisClient
+    return [BanNick n (readInt_ duration) reason | isAdministrator cl]
+
 handleCmd_lobby ["BANLIST"] = do
     cl <- thisClient
     return [BanList | isAdministrator cl]
--- a/hedgewars/ArgParsers.inc	Fri Nov 30 18:19:52 2012 +0400
+++ b/hedgewars/ArgParsers.inc	Tue Dec 04 09:15:55 2012 +0400
@@ -64,97 +64,150 @@
 end;
 {$ENDIF}
 
-procedure setVideo(screenWidth: LongInt; screenHeight: LongInt; bitsStr: LongInt);
+procedure DisplayUsage;
 begin
-    cScreenWidth:= screenWidth;
-    cScreenHeight:= screenHeight;
-    cBits:= bitsStr
-end;
-
-procedure setVideoWithParameters(screenWidthParam: string; screenHeightParam: string; bitsParam: string);
-var screenWidthAsInt, screenHeightAsInt, bitsStrAsInt, c: LongInt;
-begin
-    val(screenWidthParam, screenWidthAsInt, c);
-    val(screenHeightParam, screenHeightAsInt, c);
-    val(bitsParam, bitsStrAsInt, c);
-    setVideo(screenWidthAsInt,screenHeightAsInt,bitsStrAsInt)
+    WriteLn(stdout, 'Usage:');
+    WriteLn(stdout, '');
+    WriteLn(stdout, '  hwengine <path to user hedgewars folder> <path to global data folder> <path to replay file> [options]');
+    WriteLn(stdout, '');
+    WriteLn(stdout, 'where [options] are any of the following:');
+    WriteLn(stdout, ' --locale [path to language file]');
+    WriteLn(stdout, ' --width  [screen width in pixels]');
+    WriteLn(stdout, ' --height [screen height in pixels]');
+    WriteLn(stdout, ' --depth  [color depth]');
+    WriteLn(stdout, ' --volume [sound level]');
+    WriteLn(stdout, ' --time   [number of seconds]');
+    WriteLn(stdout, ' --nomusic');
+    WriteLn(stdout, ' --nosound');
+    WriteLn(stdout, ' --fullscreen');
+    WriteLn(stdout, ' --showfps');
+    WriteLn(stdout, ' --altdmg');
+    WriteLn(stdout, ' --lowquality');
+    WriteLn(stdout, ' --stats-only');
+    WriteLn(stdout, ' --help');
+    WriteLn(stdout, '');
+    WriteLn(stdout, 'Deprecated options:');
+    WriteLn(stdout, ' --set-video [screen width] [screen height] [color dept]');
+    WriteLn(stdout, ' --set-audio [volume] [enable music] [enable sounds]');
+    WriteLn(stdout, ' --set-other [language file] [full screen] [show FPS]');
+    WriteLn(stdout, ' --set-multimedia [screen width] [screen height] [color dept] [volume] [enable music] [enable sounds] [language file] [full screen]');
+    WriteLn(stdout, ' --set-everything [screen width] [screen height] [color dept] [volume] [enable music] [enable sounds] [language file] [full screen] [show FPS] [alternate damage] [timer value] [reduced quality]');
+    WriteLn(stdout, '');
+    WriteLn(stdout, 'For a more detailed help and examples go to:');
+    WriteLn(stdout, 'http://code.google.com/p/hedgewars/wiki/CommandLineOptions');
 end;
 
-procedure setOtherOptions(languageFile: string; fullScreen: boolean);
+function getLongIntParameter(str:String; var paramIndex:LongInt; var wrongParameter:Boolean): LongInt;
+var tmpInt, c: LongInt;
 begin
-    cLocaleFName:= languageFile;
-    cFullScreen:= fullScreen
-end;
-
-procedure setShowFPS(showFPS: boolean);
-begin
-    cShowFPS:= showFPS
+    paramIndex:= paramIndex + 1;
+    val(str, tmpInt, c);
+    wrongParameter:= c <> 0;
+    if wrongParameter then
+        WriteLn(stderr, 'ERROR: '+ParamStr(paramIndex-1)+' expects a number, you passed "'+str+'"');
+    getLongIntParameter:= tmpInt;
 end;
 
-procedure setOtherOptionsWithParameters(languageFileParam: string; fullScreenParam: string; showFPSParam: string);
-var fullScreen, showFPS: boolean;
+function getStringParameter(str:String; var paramIndex:LongInt): String;
 begin
-    fullScreen:= fullScreenParam = '1';
-    showFPS:= showFPSParam = '1';
-    setOtherOptions(languageFileParam,fullScreen);
-    setShowFPS(showFPS)
-end;
-
-procedure setAudio(initialVolume: LongInt; musicEnabled: boolean; soundEnabled: boolean);
-begin
-    SetVolume(initialVolume);
-    SetMusic(musicEnabled);
-    SetSound(soundEnabled);
+    paramIndex:= paramIndex + 1;
+    getStringParameter:= str;
 end;
 
-procedure setAudioWithParameters(initialVolumeParam: string; musicEnabledParam: string; soundEnabledParam: string);
-var initialVolumeAsInt, c: LongInt;
-    musicEnabled, soundEnabled: boolean;
+procedure parseClassicParameter(cmdArray: Array of String; size:LongInt; var paramIndex:LongInt); Forward;
+
+function parseParameter(cmd:String; arg:String; var paramIndex:LongInt): Boolean;
+const videoArray: Array [1..3] of String = ('--width','--height','--depth');
+const audioArray: Array [1..3] of String = ('--volume','--nomusic','--nosound');
+const otherArray: Array [1..3] of String = ('--locale','--fullscreen','--showfps');
+const mediaArray: Array [1..8] of String = ('--width','--height','--depth','--volume','--nomusic','--nosound','--locale','--fullscreen');
+const allArray: Array [1..12] of String = ('--width','--height','--depth','--volume','--nomusic','--nosound','--locale','--fullscreen','--showfps','--altdmg','--time','--lowquality');
+const reallyAll: array[0..19] of shortstring = (
+            '--locale', '--width', '--height', '--depth', '--time'
+            , '--volume', '--nomusic', '--nosound', '--fullscreen', '--showfps'
+            , '--altdmg', '--lowquality', '--set-video', '--set-audio', '--set-other'
+            , '--set-multimedia', '--set-everything', '--stats-only', '--gci', '--help');
+var cmdIndex: byte;
 begin
-    val(initialVolumeParam, initialVolumeAsInt, c);
-    musicEnabled:= musicEnabledParam = '1';
-    soundEnabled:= soundEnabledParam = '1';
-    setAudio(initialVolumeAsInt,musicEnabled, soundEnabled)
-end;
-
-procedure setMultimediaOptionsWithParameters(screenWidthParam, screenHeightParam, bitsParam: string;
-                                             initialVolumeParam, musicEnabledParam, soundEnabledParam: string;
-                                             languageFileParam, fullScreenParam: string);
-begin
-    setVideoWithParameters(screenWidthParam,screenHeightParam, bitsParam);
-    setAudioWithParameters(initialVolumeParam,musicEnabledParam,soundEnabledParam);
-    setOtherOptions(languageFileParam,fullScreenParam = '1')
+    parseParameter:= false;
+    cmdIndex:= 0;
+    while (cmdIndex <= High(reallyAll)) and (cmd <> reallyAll[cmdIndex]) do inc(cmdIndex);
+    case cmdIndex of
+        {--locale}   0 : cLocaleFName   := getStringParameter (arg, paramIndex);
+        {--width}    1 : cScreenWidth   := getLongIntParameter(arg, paramIndex, parseParameter);
+        {--height}   2 : cScreenHeight  := getLongIntParameter(arg, paramIndex, parseParameter);
+        {--depth}    3 : cBits          := getLongIntParameter(arg, paramIndex, parseParameter);
+        {--time}     4 : cTimerInterval := getLongIntParameter(arg, paramIndex, parseParameter);
+        {--volume}   5 : SetVolume       ( getLongIntParameter(arg, paramIndex, parseParameter) );
+        {--nomusic}  6 : SetMusic        ( false );
+        {--nosound}  7 : SetSound        ( false );
+        {--fullscreen}   8 : cFullScreen    := true;
+        {--showfps}      9 : cShowFPS       := true;
+        {--altdmg}      10 : cAltDamage     := true;
+        {--lowquality}  11 : cReducedQuality:= ($FFFFFFFF * getLongIntParameter(arg, paramIndex, parseParameter)) xor rqLowRes; //HACK!
+        {--set-video}   12 : parseClassicParameter(videoArray,3,paramIndex);
+        {--set-audio}   13 : parseClassicParameter(audioArray,3,paramIndex);
+        {--set-other}   14 : parseClassicParameter(otherArray,3,paramIndex);
+        {--set-multimedia}  15 : parseClassicParameter(mediaArray,8,paramIndex);
+        {--set-everything}  16 : parseClassicParameter(allArray,12,paramIndex);
+        {--stats-only}  17 : begin
+                             cOnlyStats:= true;
+                             SetSound(false);
+                             SetMusic(false);
+                             cReducedQuality:= $FFFFFFFF xor rqLowRes;
+                             end;
+        {--gci}  18 : begin            //     We had to make up all this saved space some how...     \\
+                      WriteLn(stdout, '                                                                ');
+                      WriteLn(stdout, '      /\\\\\\\\\\\\        /\\\\\\\\\  /\\\\\\\\\\\             ');
+                      WriteLn(stdout, '     /\\\//////////      /\\\////////  \/////\\\///             ');
+                      WriteLn(stdout, '     /\\\               /\\\/               \/\\\               ');
+                      WriteLn(stdout, '     \/\\\    /\\\\\\\  /\\\                 \/\\\              ');
+                      WriteLn(stdout, '      \/\\\   \/////\\\ \/\\\                 \/\\\             ');
+                      WriteLn(stdout, '       \/\\\       \/\\\ \//\\\                \/\\\            ');
+                      WriteLn(stdout, '        \/\\\       \/\\\  \///\\\              \/\\\           ');
+                      WriteLn(stdout, '         \//\\\\\\\\\\\\/     \////\\\\\\\\\  /\\\\\\\\\\\      ');
+                      WriteLn(stdout, '          \////////////           \/////////  \///////////      ');
+                      WriteLn(stdout, '                                                                ');
+                      WriteLn(stdout, ' Command Line Parser Implementation by a Google Code-In Student ');
+                      WriteLn(stdout, '             ASCII Art easter egg idea by @sheepluva            ');
+                      WriteLn(stdout, '                                                                ');
+                      end;
+        {--help}  19 : begin
+                       DisplayUsage();
+                       GameType:= gmtSyntax;
+                       end;
+    else
+        begin
+        WriteLn(stderr, 'ERROR: '+cmd+' is not a valid argument');
+        parseParameter:= true;
+        end
+    end;
 end;
 
-procedure setAltDamageTimerValueAndQuality(altDamage: boolean; timeIterval: LongInt; reducedQuality: boolean);
+procedure parseClassicParameter(cmdArray: Array of String; size:LongInt; var paramIndex:LongInt);
+var index, tmpInt: LongInt;
+    isBool: Boolean;
 begin
-    cAltDamage:= altDamage;
-    cTimerInterval:= timeIterval;
-    if (reducedQuality) then        //HACK
-        cReducedQuality:= $FFFFFFFF xor rqLowRes
-end;
-
-procedure setAllOptionsWithParameters(screenWidthParam:string; screenHeightParam:string; bitsParam:string;
-                                      initialVolumeParam:string; musicEnabledParam:string; soundEnabledParam:string;
-                                      languageFileParam:string; fullScreenParam:string; showFPSParam:string;
-                                      altDamageParam:string; timeItervalParam:string; reducedQualityParam: string);
-var showFPS, altDamage, reducedQuality: boolean;
-    timeIterval, c: LongInt;
-begin
-    setMultimediaOptionsWithParameters(screenWidthParam,screenHeightParam, bitsParam,
-                                       initialVolumeParam,musicEnabledParam,soundEnabledParam,
-                                       languageFileParam,fullScreenParam);
-    showFPS := showFPSParam = '1';
-    setShowFPS(showFPS);
-
-    altDamage:= altDamageParam = '1';
-    val(timeItervalParam, timeIterval, c);
-    reducedQuality:= reducedQualityParam = '1';
-    setAltDamageTimerValueAndQuality(altDamage,timeIterval,reducedQuality);
+    index:= 0;
+    tmpInt:= 1;
+    while (index < size) do
+        begin
+        paramIndex:= paramIndex+1;
+        // check if the parameter is a boolean one
+        isBool:= (cmdArray[index] = '--nomusic')
+            or (cmdArray[index] = '--nosound')
+            or (cmdArray[index] = '--fullscreen')
+            or (cmdArray[index] = '--showfps')
+            or (cmdArray[index] = '--altdmg')
+            or (cmdArray[index] = '--lowquality');
+        if (not isBool) or ((ParamStr(paramIndex)='1') and (cmdArray[index]<>'--nomusic') and (cmdArray[index]<>'--nosound')) then
+            parseParameter(cmdArray[index], ParamStr(paramIndex), tmpInt);
+        index:= index+1;
+        end;
 end;
 
 procedure playReplayFileWithParameters();
-var paramIndex: LongInt;
+var paramIndex, tmpInt: LongInt;
     wrongParameter: boolean;
 begin
     UserPathPrefix:= ParamStr(1);
@@ -162,86 +215,15 @@
     recordFileName:= ParamStr(3);
     paramIndex:= 4;
     wrongParameter:= false;
-    while (paramIndex <= ParamCount) and (not wrongParameter) do
+    while (paramIndex <= ParamCount) do
         begin
-        if ParamStr(paramIndex) = '--set-video'  then
-//--set-video [screen width] [screen height] [color dept]
-            begin
-            if(ParamCount-paramIndex < 3) then
-                begin
-                wrongParameter:= true;
-                GameType:= gmtSyntax
-                end;
-            setVideoWithParameters(ParamStr(paramIndex+1), ParamStr(paramIndex+2), ParamStr(paramIndex+3));
-            paramIndex:= paramIndex + 4
-            end
-        else
-//--set-audio [volume] [enable music] [enable sounds]
-            if ParamStr(paramIndex) = '--set-audio'  then
-                begin
-                if(ParamCount-paramIndex < 3) then
-                    begin
-                    wrongParameter := true;
-                    GameType:= gmtSyntax
-                    end;
-                setAudioWithParameters(ParamStr(paramIndex+1),ParamStr(paramIndex+2), ParamStr(paramIndex+3));
-                paramIndex:= paramIndex + 4
-                end
-            else
-// --set-other [language file] [full screen] [show FPS]
-                if ParamStr(paramIndex) = '--set-other'  then
-                    begin
-                    if(ParamCount-paramIndex < 3) then
-                        begin
-                        wrongParameter:= true;
-                        GameType:= gmtSyntax
-                        end;
-                    setOtherOptionsWithParameters(ParamStr(paramIndex+1),ParamStr(paramIndex+2), ParamStr(paramIndex+3));
-                    paramIndex:= paramIndex + 4
-                    end
-                else
-//--set-multimedia [screen width] [screen height] [color dept] [volume] [enable music] [enable sounds] [language file] [full screen]
-                    if ParamStr(paramIndex) = '--set-multimedia'  then
-                        begin
-                        if ParamCount-paramIndex < 8  then
-                            begin
-                            wrongParameter:= true;
-                            GameType:= gmtSyntax
-                            end;
-                        setMultimediaOptionsWithParameters(ParamStr(paramIndex+1),ParamStr(paramIndex+2),ParamStr(paramIndex+3),
-                                                           ParamStr(paramIndex+4),ParamStr(paramIndex+5),ParamStr(paramIndex+6),
-                                                           ParamStr(paramIndex+7),ParamStr(paramIndex+8));
-                        paramIndex:= paramIndex + 9
-                        end
-                    else
-//--set-everything [screen width] [screen height] [color dept] [volume] [enable music] [enable sounds] [language file] [full screen] [show FPS] [alternate damage] [timer value] [reduced quality]
-                        if ParamStr(paramIndex) = '--set-everything'  then
-                            begin
-                            if ParamCount-paramIndex < 12  then
-                                begin
-                                wrongParameter:= true;
-                                GameType:= gmtSyntax
-                                end;
-                            setAllOptionsWithParameters(ParamStr(paramIndex+1),ParamStr(paramIndex+2),ParamStr(paramIndex+3),
-                                                        ParamStr(paramIndex+4),ParamStr(paramIndex+5),ParamStr(paramIndex+6),
-                                                        ParamStr(paramIndex+7),ParamStr(paramIndex+8),ParamStr(paramIndex+9),
-                                                        ParamStr(paramIndex+10),ParamStr(paramIndex+11),ParamStr(paramIndex+12));
-                            paramIndex:= paramIndex + 13
-                            end
-                        else
-                            if ParamStr(paramIndex) = '--stats-only'  then
-                                begin
-                                cOnlyStats:= true;
-                                SetSound(false);
-                                SetMusic(false);
-                                cReducedQuality:= $FFFFFFFF xor rqLowRes; // HACK
-                                paramIndex:= paramIndex + 1
-                                end
-                            else
-                                begin
-                                wrongParameter:= true;
-                                GameType:= gmtSyntax
-                                end
-    end
+        if parseParameter( ParamStr(paramIndex), ParamStr(paramIndex+1), paramIndex) then
+            wrongParameter:= true;
+        paramIndex:= paramIndex+1;
+        end;
+    if wrongParameter = true then
+        begin
+        WriteLn(stderr, 'Please use --help to see possible arguments and their usage');
+        GameType:= gmtSyntax;
+        end
 end;
-
--- a/hedgewars/CMakeLists.txt	Fri Nov 30 18:19:52 2012 +0400
+++ b/hedgewars/CMakeLists.txt	Tue Dec 04 09:15:55 2012 +0400
@@ -12,6 +12,12 @@
 set(hwengine_project ${hedgewars_SOURCE_DIR}/hedgewars/hwengine.pas)
 set(engine_output_name "hwengine")
 
+if (APPLE)
+    set(required_fpc_version 2.6)
+else()
+    set(required_fpc_version 2.2)
+endif()
+
 set(engine_sources
     ${hwengine_project}
     LuaPas.pas
@@ -53,7 +59,6 @@
     uLandTexture.pas
     uLocale.pas
     uMisc.pas
-    uMobile.pas
     uPhysFSLayer.pas
     uRandom.pas
     uRender.pas
@@ -101,54 +106,13 @@
 endif(BUILD_ENGINE_LIBRARY)
 
 
-#PASCAL DETECTION SECTION
-IF(FPC)
-    set(fpc_executable ${FPC})
-ELSE()
-    find_program(fpc_executable fpc)
-ENDIF()
-
-message(STATUS "Check for working FPC compiler: ${fpc_executable}")
-execute_process(COMMAND ${fpc_executable} -iV OUTPUT_VARIABLE fpc_output ERROR_VARIABLE fpc_error)
-if(fpc_error)
-    message(STATUS "Check for working FPC compiler: ${fpc_executable} -- broken")
-else(fpc_error)
-    message(STATUS "Check for working FPC compiler: ${fpc_executable} -- works")
-endif(fpc_error)
+# Check Freepascal version
+find_package(Freepascal)
 
-string(REGEX MATCH "[0-9]+\\.[0-9]+\\.[0-9]+" fpc_version "${fpc_output}")
-if(fpc_version)
-    string(REGEX REPLACE "([0-9]+)\\.[0-9]+\\.[0-9]+" "\\1" fpc_vers_major "${fpc_version}")
-    string(REGEX REPLACE "[0-9]+\\.([0-9]+)\\.[0-9]+" "\\1" fpc_vers_minor "${fpc_version}")
-    string(REGEX REPLACE "[0-9]+\\.[0-9]+\\.([0-9]+)" "\\1" fpc_vers_patch "${fpc_version}")
-    message(STATUS "Found Freepascal: ${fpc_executable} (version ${fpc_vers_major}.${fpc_vers_minor})")
-    math(EXPR fpc_version "${fpc_vers_major}*10000 + ${fpc_vers_minor}*100 + ${fpc_vers_patch}")
-
-    if(fpc_version LESS "020200")
-        message(FATAL_ERROR "Minimum required version of FreePascal is 2.2.0")
-    elseif(APPLE AND (fpc_version LESS "020600"))
-        message(FATAL_ERROR "Minimum required version of FreePascal is 2.6.0 on Mac OS X")
-    endif()
-else()
-    message(FATAL_ERROR "No FreePascal compiler found!")
+if (FPC_VERSION VERSION_LESS required_fpc_version)
+    message(FATAL_ERROR "Freepascal is too old, minimum version required is ${required_fpc_version}")
 endif()
 
-message(STATUS "Checking whether linker supports noexecstack flag")
-set(noexecstack_flags "-k-z" "-knoexecstack")
-file(WRITE ${EXECUTABLE_OUTPUT_PATH}/checkstack.pas "begin end.")
-
-execute_process(COMMAND ${fpc_executable} ${noexecstack_flags} checkstack.pas
-    WORKING_DIRECTORY ${EXECUTABLE_OUTPUT_PATH}
-    RESULT_VARIABLE testnoexecstack
-    OUTPUT_QUIET ERROR_QUIET
-    )
-
-if(${testnoexecstack})
-    set (noexecstack_flags "")
-    message(STATUS "Checking whether linker supports noexecstack flag -- no")
-else(${testnoexecstack})
-    message(STATUS "Checking whether linker supports noexecstack flag -- yes")
-endif(${testnoexecstack})
 
 #DEPENDECIES AND EXECUTABLES SECTION
 if(APPLE)
@@ -198,9 +162,8 @@
 
 
 #this command is a workaround to some inlining issues present in older FreePascal versions and fixed in 2.6
-if(fpc_version LESS "020600")
+if(FPC_VERSION VERSION_LESS "2.6")
     #under some configurations CMAKE_BUILD_TOOL fails to pass on the jobserver, breaking parallel compilation
-    #TODO: check if this is needed on windows too
     if(UNIX)
         set(SAFE_BUILD_TOOL $(MAKE))
     else()
@@ -239,22 +202,22 @@
 
 set(pascal_flags "-Fl${LIBRARY_OUTPUT_PATH}" ${pascal_flags})
 
-set(fpc_flags ${noexecstack_flags} ${pascal_flags} ${hwengine_project})
+set(fpc_flags ${NOEXECSTACK_FLAGS} ${pascal_flags} ${hwengine_project})
 
-IF(NOT APPLE)
+if(NOT APPLE)
     #here is the command for standard executables or for shared library
     add_custom_command(OUTPUT "${EXECUTABLE_OUTPUT_PATH}/${engine_output_name}${CMAKE_EXECUTABLE_SUFFIX}"
-        COMMAND "${fpc_executable}"
+        COMMAND "${FPC_EXECUTABLE}"
         ARGS ${fpc_flags}
         MAIN_DEPENDENCY ${hwengine_project}
         DEPENDS ${engine_sources}
         )
-ELSE()
+else()
     #these are the dependencies for building a universal binary on Mac OS X
     foreach (build_arch ${powerpc_build} ${i386_build} ${x86_64_build})
         set(lipo_args_list "${EXECUTABLE_OUTPUT_PATH}/hwengine.${build_arch}" ${lipo_args_list})
         add_custom_command(OUTPUT "${EXECUTABLE_OUTPUT_PATH}/hwengine.${build_arch}"
-            COMMAND "${fpc_executable}"
+            COMMAND "${FPC_EXECUTABLE}"
             ARGS ${fpc_flags} -ohwengine.${build_arch} -P${build_arch}
             MAIN_DEPENDENCY ${hwengine_project}
             DEPENDS ${engine_sources}
@@ -267,7 +230,7 @@
         ARGS ${lipo_args_list} -create -output ${EXECUTABLE_OUTPUT_PATH}/${engine_output_name}
         DEPENDS ${lipo_args_list}
         )
-ENDIF()
+endif()
 
 
 add_custom_target(${engine_output_name} ALL DEPENDS "${EXECUTABLE_OUTPUT_PATH}/${engine_output_name}${CMAKE_EXECUTABLE_SUFFIX}")
@@ -287,7 +250,7 @@
 endif()
 
 #this command is a workaround to some inlining issues present in older FreePascal versions and fixed in 2.6
-if((fpc_version LESS "020600") AND (NOVIDEOREC OR NOT ${FFMPEG_FOUND}))
+if((FPC_VERSION VERSION_LESS "2.6") AND (NOVIDEOREC OR NOT ${FFMPEG_FOUND}))
     add_dependencies(${engine_output_name} ENGINECLEAN)
 endif()
 
--- a/hedgewars/GSHandlers.inc	Fri Nov 30 18:19:52 2012 +0400
+++ b/hedgewars/GSHandlers.inc	Tue Dec 04 09:15:55 2012 +0400
@@ -2223,7 +2223,9 @@
         begin
         doMakeExplosion(hwRound(Gear^.X), hwRound(Gear^.Y), 30, Gear^.Hedgehog, EXPLAutoSound);
         DeleteGear(Gear);
-        performRumble();
+        with mobileRecord do
+            if (performRumble <> nil) and (not fastUntilLag) then
+                performRumble(kSystemSoundID_Vibrate);
         exit
         end;
     if (GameTicks and $3F) = 0 then
@@ -4308,7 +4310,9 @@
     Gear^.dY.isNegative := not Gear^.dY.isNegative;
 
     Gear^.doStep := @doStepSineGunShotWork;
-    performRumble();
+    with mobileRecord do
+        if (performRumble <> nil) and (not fastUntilLag) then
+            performRumble(kSystemSoundID_Vibrate);
 end;
 
 ////////////////////////////////////////////////////////////////////////////////
--- a/hedgewars/VGSHandlers.inc	Fri Nov 30 18:19:52 2012 +0400
+++ b/hedgewars/VGSHandlers.inc	Tue Dec 04 09:15:55 2012 +0400
@@ -697,7 +697,9 @@
 Gear^.doStep:= @doStepBigExplosionWork;
 if Steps > 1 then
     Gear^.doStep(Gear, Steps-1);
-performRumble();
+with mobileRecord do
+    if (performRumble <> nil) and (not fastUntilLag) then
+        performRumble(kSystemSoundID_Vibrate);
 end;
 
 procedure doStepChunk(Gear: PVisualGear; Steps: Longword);
--- a/hedgewars/hwengine.pas	Fri Nov 30 18:19:52 2012 +0400
+++ b/hedgewars/hwengine.pas	Tue Dec 04 09:15:55 2012 +0400
@@ -536,39 +536,18 @@
 end;
 
 {$IFNDEF HWLIBRARY}
-///////////////////////////////////////////////////////////////////////////////
-procedure DisplayUsage;
-var i: LongInt;
-begin
-    WriteLn(stdout, 'Wrong argument format: correct configurations is');
-    WriteLn(stdout, '');
-    WriteLn(stdout, '  hwengine <path to user hedgewars folder> <path to global data folder> <path to replay file> [options]');
-    WriteLn(stdout, '');
-    WriteLn(stdout, 'where [options] must be specified either as:');
-    WriteLn(stdout, ' --set-video [screen width] [screen height] [color dept]');
-    WriteLn(stdout, ' --set-audio [volume] [enable music] [enable sounds]');
-    WriteLn(stdout, ' --set-other [language file] [full screen] [show FPS]');
-    WriteLn(stdout, ' --set-multimedia [screen width] [screen height] [color dept] [volume] [enable music] [enable sounds] [language file] [full screen]');
-    WriteLn(stdout, ' --set-everything [screen width] [screen height] [color dept] [volume] [enable music] [enable sounds] [language file] [full screen] [show FPS] [alternate damage] [timer value] [reduced quality]');
-    WriteLn(stdout, ' --stats-only');
-    WriteLn(stdout, '');
-    WriteLn(stdout, 'Read documentation online at http://code.google.com/p/hedgewars/wiki/CommandLineOptions for more information');
-    WriteLn(stdout, '');
-    Write(stdout, 'PARSED COMMAND: ');
-    
-    for i:=0 to ParamCount do
-        Write(stdout, ParamStr(i) + ' ');
-        
-    WriteLn(stdout, '');
-end;
 
 ///////////////////////////////////////////////////////////////////////////////
 {$INCLUDE "ArgParsers.inc"}
 
 procedure GetParams;
+var tmpInt: LongInt;
 begin
     if (ParamCount < 3) then
-        GameType:= gmtSyntax
+        begin
+        DisplayUsage();
+        GameType:= gmtSyntax;
+        end
     else
         if (ParamCount = 3) and (ParamStr(3) = 'landpreview') then
             begin
@@ -601,7 +580,7 @@
     if GameType = gmtLandPreview then
         GenLandPreview()
     else if GameType = gmtSyntax then
-        DisplayUsage()
+        //Exit cleanly
     else Game();
 
     // return 1 when engine is not called correctly
--- a/hedgewars/options.inc	Fri Nov 30 18:19:52 2012 +0400
+++ b/hedgewars/options.inc	Tue Dec 04 09:15:55 2012 +0400
@@ -43,12 +43,12 @@
 
 {$IFDEF MOBILE}
     {$DEFINE HWLIBRARY}
-    {$DEFINE S3D_DISABLED}
     {$DEFINE GLunit:=gles11}
     {$DEFINE USE_LANDSCAPE_AMMOMENU}
     {$DEFINE USE_TOUCH_INTERFACE}
 {$ELSE}
     {$DEFINE USE_AM_NUMCOLUMN}
+    {$DEFINE USE_S3D_RENDERING}
 {$ENDIF}
 
 
--- a/hedgewars/uAIAmmoTests.pas	Fri Nov 30 18:19:52 2012 +0400
+++ b/hedgewars/uAIAmmoTests.pas	Tue Dec 04 09:15:55 2012 +0400
@@ -116,7 +116,7 @@
             (proc: nil;              flags: 0), // amDrillStrike
             (proc: nil;              flags: 0), // amSnowball
             (proc: nil;              flags: 0), // amTardis
-            (proc: nil;              flags: 0), // amStructure
+            //(proc: nil;              flags: 0), // amStructure
             (proc: nil;              flags: 0), // amLandGun
             (proc: nil;              flags: 0), // amIceGun
             (proc: nil;              flags: 0)  // amKnife
--- a/hedgewars/uChat.pas	Fri Nov 30 18:19:52 2012 +0400
+++ b/hedgewars/uChat.pas	Tue Dec 04 09:15:55 2012 +0400
@@ -41,6 +41,7 @@
     Width: LongInt;
     s: shortstring;
     end;
+    TChatCmd = (quit, pause, finish, fullscreen);
 
 var Strs: array[0 .. MaxStrIndex] of TChatLine;
     MStrs: array[0 .. MaxStrIndex] of shortstring;
@@ -52,15 +53,25 @@
     ChatReady: boolean;
     showAll: boolean;
 
-const colors: array[#0..#6] of TSDL_Color = (
-    (r:$FF; g:$FF; b:$FF; unused:$FF), // unused, feel free to take it for anything
-    (r:$FF; g:$FF; b:$FF; unused:$FF), // chat message [White]
-    (r:$FF; g:$00; b:$FF; unused:$FF), // action message [Purple]
-    (r:$90; g:$FF; b:$90; unused:$FF), // join/leave message [Lime]
-    (r:$FF; g:$FF; b:$A0; unused:$FF), // team message [Light Yellow]
-    (r:$FF; g:$00; b:$00; unused:$FF), // error messages [Red]
-    (r:$00; g:$FF; b:$FF; unused:$FF)  // input line [Light Blue]
-    );
+const
+    colors: array[#0..#6] of TSDL_Color = (
+            (r:$FF; g:$FF; b:$FF; unused:$FF), // unused, feel free to take it for anything
+            (r:$FF; g:$FF; b:$FF; unused:$FF), // chat message [White]
+            (r:$FF; g:$00; b:$FF; unused:$FF), // action message [Purple]
+            (r:$90; g:$FF; b:$90; unused:$FF), // join/leave message [Lime]
+            (r:$FF; g:$FF; b:$A0; unused:$FF), // team message [Light Yellow]
+            (r:$FF; g:$00; b:$00; unused:$FF), // error messages [Red]
+            (r:$00; g:$FF; b:$FF; unused:$FF)  // input line [Light Blue]
+            );
+    ChatCommandz: array [TChatCmd] of record
+            ChatCmd: string[31];
+            ProcedureCallChatCmd: string[31];
+            end = (
+            (ChatCmd: '/quit'; ProcedureCallChatCmd: 'halt'),
+            (ChatCmd: '/pause'; ProcedureCallChatCmd: 'pause'),
+            (ChatCmd: '/finish'; ProcedureCallChatCmd: 'finish'),
+            (ChatCmd: '/fullscreen'; ProcedureCallChatCmd: 'fullscr')
+            );
 
 procedure SetLine(var cl: TChatLine; str: shortstring; isInput: boolean);
 var strSurface, resSurface: PSDL_Surface;
@@ -197,6 +208,7 @@
 
 procedure AcceptChatString(s: shortstring);
 var i: TWave;
+    j: TChatCmd;
     c, t: LongInt;
     x: byte;
 begin
@@ -267,6 +279,13 @@
             ParseCommand('/taunt ' + char(i), true);
             exit
             end;
+
+	for j:= Low(TChatCmd) to High(TChatCmd) do
+        if (s = ChatCommandz[j].ChatCmd) then
+            begin
+            ParseCommand(ChatCommandz[j].ProcedureCallChatCmd, true);
+            exit
+            end;
     end
     else
         ParseCommand('/say ' + s, true);
--- a/hedgewars/uCommandHandlers.pas	Fri Nov 30 18:19:52 2012 +0400
+++ b/hedgewars/uCommandHandlers.pas	Tue Dec 04 09:15:55 2012 +0400
@@ -30,6 +30,8 @@
      {$IFDEF USE_VIDEO_RECORDING}, uVideoRec {$ENDIF};
 
 var prevGState: TGameState = gsConfirm;
+    cTagsMasks : array[0..15] of byte = (7, 0, 0, 0, 15, 6, 4, 5, 0, 0, 0, 0, 0, 14, 12, 13);
+    cTagsMasksNoHealth: array[0..15] of byte = (3, 2, 11, 1, 0, 0, 0, 0, 0, 10, 0, 9, 0, 0, 0, 0);
 
 procedure chGenCmd(var s: shortstring);
 begin
--- a/hedgewars/uConsts.pas	Fri Nov 30 18:19:52 2012 +0400
+++ b/hedgewars/uConsts.pas	Tue Dec 04 09:15:55 2012 +0400
@@ -112,9 +112,7 @@
     GL_TEXTURE_PRIORITY = $8066;
     {$ENDIF}
 
-    cSendCursorPosTime  : LongWord = 50;
     cVisibleWater       : LongInt = 128;
-    cCursorEdgesDist    : LongInt = 100;
     cTeamHealthWidth    : LongInt = 128;
 
     cifRandomize = $00000001;
@@ -122,8 +120,6 @@
     cifMap       = $00000002; // either theme or map (or map+theme)
     cifAllInited = cifRandomize or cifTheme or cifMap;
 
-    cTransparentColor: Longword = $00000000;
-
     RGB_LUMINANCE_RED    = 0.212671;
     RGB_LUMINANCE_GREEN  = 0.715160;
     RGB_LUMINANCE_BLUE   = 0.072169;
@@ -131,18 +127,14 @@
     cMaxTeams        = 8;
     cMaxHHIndex      = 7;
     cMaxHHs          = 48;
-    cMaxSpawnPoints  = 1024;
 
     cMaxEdgePoints = 16384;
 
     cHHRadius = 9;
     cHHStepTicks = 29;
 
-    cUsualZ = 500;
-    cSmokeZ = 499;
     cHHZ = 1000;
     cCurrHHZ = Succ(cHHZ);
-    cOnHHZ = 2000;
 
     cBarrelHealth = 60;
     cShotgunRadius = 22;
@@ -152,18 +144,11 @@
     cKeyMaxIndex = 1023;
     cKbdMaxIndex = 65536;//need more room for the modifier keys
 
-    cHHFileName = 'Hedgehog';
-    cCHFileName = 'Crosshair';
-    cThemeCFGFilename = 'theme.cfg';
-
     cFontBorder = 2;
 
     // do not change this value
     cDefaultZoomLevel = 2.0;
 
-    cSendEmptyPacketTime = 1000;
-    trigTurns = $80000001;
-
     // game flags
     gfAny                = $FFFFFFFF;
     gfOneClanMode        = $00000001;           // used in trainings
@@ -290,40 +275,8 @@
     NoPointX = Low(LongInt);
     cTargetPointRef : TPoint = (X: NoPointX; Y: 0);
 
-    // hog tag mask
-    htNone        = $00;
-    htTeamName    = $01;
-    htName        = $02;
-    htHealth      = $04;
-    htTransparent = $08;
-
-    AMAnimDuration = 200;
-    AMHidden    = 0;//AMState values
-    AMShowingUp = 1;
-    AMShowing   = 2;
-    AMHiding    = 3;
+    kSystemSoundID_Vibrate = $00000FFF;
 
-    AMTypeMaskX     = $00000001;
-    AMTypeMaskY     = $00000002;
-    AMTypeMaskAlpha = $00000004;
-    AMTypeMaskSlide = $00000008;
-
-{$IFDEF MOBILE}
-    AMSlotSize = 48;
-    AMTITLE = 30;
-{$ELSE}
-    AMSlotSize = 32;
-{$ENDIF}
-    AMSlotPadding = (AMSlotSize - 32) shr 1;
-
-{$IFDEF USE_TOUCH_INTERFACE}
-    FADE_ANIM_TIME = 500;
-    MOVE_ANIM_TIME = 500;
-{$ENDIF}
-
-    cTagsMasks : array[0..15] of byte = (7, 0, 0, 0, 15, 6, 4, 5, 0, 0, 0, 0, 0, 14, 12, 13);
-    cTagsMasksNoHealth: array[0..15] of byte = (3, 2, 11, 1, 0, 0, 0, 0, 0, 10, 0, 9, 0, 0, 0, 0);
-       
 implementation
 
 end.
--- a/hedgewars/uGame.pas	Fri Nov 30 18:19:52 2012 +0400
+++ b/hedgewars/uGame.pas	Tue Dec 04 09:15:55 2012 +0400
@@ -26,7 +26,7 @@
 ////////////////////
     implementation
 ////////////////////
-uses uInputHandler, uTeams, uIO, uAI, uGears, uSound, uMobile, 
+uses uInputHandler, uTeams, uIO, uAI, uGears, uSound, 
     uVisualGears, uTypes, uVariables, uCommands, uConsts
     {$IFDEF USE_TOUCH_INTERFACE}, uTouch{$ENDIF};
 
@@ -96,7 +96,9 @@
                         AddVisualGear(0, 0, vgtTeamHealthSorter);
                         AddVisualGear(0, 0, vgtSmoothWindBar);
                         {$IFDEF IPHONEOS}InitIPC;{$ENDIF}
-                        uMobile.SaveLoadingEnded();
+                        with mobileRecord do
+                            if SaveLoadingEnded <> nil then
+                                SaveLoadingEnded();
                         end;
                 end
         else ProcessGears
--- a/hedgewars/uGears.pas	Fri Nov 30 18:19:52 2012 +0400
+++ b/hedgewars/uGears.pas	Tue Dec 04 09:15:55 2012 +0400
@@ -57,7 +57,7 @@
 
 implementation
 uses uStore, uSound, uTeams, uRandom, uCollisions, uIO, uLandGraphics,
-    uLocale, uAI, uAmmos, uStats, uVisualGears, uScript, GLunit, uMobile, uVariables,
+    uLocale, uAI, uAmmos, uStats, uVisualGears, uScript, GLunit, uVariables,
     uCommands, uUtils, uTextures, uRenderUtils, uGearsRender, uCaptions, uDebug, uLandTexture,
     uGearsHedgehog, uGearsUtils, uGearsList, uGearsHandlers, uGearsHandlersRope;
 
@@ -677,8 +677,8 @@
             gtKnife,
             gtCase,
             gtTarget,
-            gtExplosives,
-            gtStructure: begin
+            gtExplosives: begin//,
+//            gtStructure: begin
 //addFileLog('ShotgunShot radius: ' + inttostr(Gear^.Radius) + ', t^.Radius = ' + inttostr(t^.Radius) + ', distance = ' + inttostr(dist) + ', dmg = ' + inttostr(dmg));
                     dmg:= 0;
                     r:= Gear^.Radius + t^.Radius;
@@ -777,8 +777,8 @@
             gtKnife,
             gtTarget,
             gtCase,
-            gtExplosives,
-            gtStructure:
+            gtExplosives: //,
+            //gtStructure:
             begin
             if (Ammo^.Kind = gtDrill) then
                 begin
@@ -906,10 +906,6 @@
                     inc(Count)
                     end;
         end;
-    // unC0Rr, while it is true user can watch value on map screen, IMO this (and check above) should be enforced in UI
-    // - is there a good place to put values for the different widgets to check?  Right now they are kind of disconnected.
-    //it would be nice if divide teams, forts mode and hh per map could all be checked by the team widget, or maybe disable start button
-    TryDo(Count <= MaxHedgehogs, 'Too many hedgehogs for this map! (max # is ' + inttostr(MaxHedgehogs) + ')', true);
     while (Count > 0) do
         begin
         i:= GetRandom(Count);
@@ -1367,7 +1363,7 @@
             @doStepNapalmBomb,
             @doStepSnowball,
             @doStepSnowflake,
-            @doStepStructure,
+            //@doStepStructure,
             @doStepLandGun,
             @doStepTardis,
             @doStepIceGun,
--- a/hedgewars/uGearsHedgehog.pas	Fri Nov 30 18:19:52 2012 +0400
+++ b/hedgewars/uGearsHedgehog.pas	Tue Dec 04 09:15:55 2012 +0400
@@ -374,7 +374,7 @@
                                  newGear:= AddGear(hwRound(lx), hwRound(ly), gtResurrector, 0, _0, _0, 0);
                                  newGear^.SoundChannel := LoopSound(sndResurrector);
                                  end;
-                    amStructure: newGear:= AddGear(hwRound(lx) + hwSign(dX) * 7, hwRound(ly), gtStructure, gstWait, SignAs(_0_02, dX), _0, 3000);
+                    //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;
@@ -404,7 +404,7 @@
                     amSeduction, amBallgun,
                       amJetpack, amBirdy,
                  amFlamethrower, amLandGun,
-                  amResurrector, amStructure,
+                  amResurrector, //amStructure,
                        amTardis, amPiano,
                        amIceGun: CurAmmoGear:= newGear;
              end;
--- a/hedgewars/uGearsList.pas	Fri Nov 30 18:19:52 2012 +0400
+++ b/hedgewars/uGearsList.pas	Tue Dec 04 09:15:55 2012 +0400
@@ -35,8 +35,83 @@
     uTextures, uScript, uRenderUtils, uAI, uCollisions,
     uGearsRender, uGearsUtils, uDebug;
 
+const
+    GearKindAmmoTypeMap : array [TGearType] of TAmmoType = (    
+(*          gtFlame *)   amNothing
+(*       gtHedgehog *) , amNothing
+(*           gtMine *) , amMine
+(*           gtCase *) , amNothing
+(*     gtExplosives *) , amNothing
+(*        gtGrenade *) , amGrenade
+(*          gtShell *) , amBazooka
+(*          gtGrave *) , amNothing
+(*            gtBee *) , amBee
+(*    gtShotgunShot *) , amShotgun
+(*     gtPickHammer *) , amPickHammer
+(*           gtRope *) , amRope
+(*     gtDEagleShot *) , amDEagle
+(*       gtDynamite *) , amDynamite
+(*    gtClusterBomb *) , amClusterBomb
+(*        gtCluster *) , amClusterBomb
+(*         gtShover *) , amBaseballBat  // Shover is only used for baseball bat right now
+(*      gtFirePunch *) , amFirePunch
+(*    gtATStartGame *) , amNothing
+(*   gtATFinishGame *) , amNothing
+(*      gtParachute *) , amParachute
+(*      gtAirAttack *) , amAirAttack
+(*        gtAirBomb *) , amAirAttack
+(*      gtBlowTorch *) , amBlowTorch
+(*         gtGirder *) , amGirder
+(*       gtTeleport *) , amTeleport
+(*       gtSwitcher *) , amSwitch
+(*         gtTarget *) , amNothing
+(*         gtMortar *) , amMortar
+(*           gtWhip *) , amWhip
+(*       gtKamikaze *) , amKamikaze
+(*           gtCake *) , amCake
+(*      gtSeduction *) , amSeduction
+(*     gtWatermelon *) , amWatermelon
+(*     gtMelonPiece *) , amWatermelon
+(*    gtHellishBomb *) , amHellishBomb
+(*        gtWaterUp *) , amNothing
+(*          gtDrill *) , amDrill
+(*        gtBallGun *) , amBallgun
+(*           gtBall *) , amBallgun
+(*        gtRCPlane *) , amRCPlane
+(*gtSniperRifleShot *) , amSniperRifle
+(*        gtJetpack *) , amJetpack
+(*        gtMolotov *) , amMolotov
+(*          gtBirdy *) , amBirdy
+(*            gtEgg *) , amBirdy
+(*         gtPortal *) , amPortalGun
+(*          gtPiano *) , amPiano
+(*        gtGasBomb *) , amGasBomb
+(*    gtSineGunShot *) , amSineGun
+(*   gtFlamethrower *) , amFlamethrower
+(*          gtSMine *) , amSMine
+(*    gtPoisonCloud *) , amNothing
+(*         gtHammer *) , amHammer
+(*      gtHammerHit *) , amHammer
+(*    gtResurrector *) , amResurrector
+(*    gtPoisonCloud *) , amNothing
+(*       gtSnowball *) , amSnowball
+(*          gtFlake *) , amNothing
+//(*      gtStructure *) , amStructure  // TODO - This will undoubtedly change once there is more than one structure
+(*        gtLandGun *) , amLandGun
+(*         gtTardis *) , amTardis
+(*         gtIceGun *) , amIceGun
+(*        gtAddAmmo *) , amNothing
+(*  gtGenericFaller *) , amNothing
+(*          gtKnife *) , amKnife
+    );
+
+
 var GCounter: LongWord = 0; // this does not get re-initialized, but should be harmless
 
+const
+    cUsualZ = 500;
+    cOnHHZ = 2000;
+
 procedure InsertGearToList(Gear: PGear);
 var tmp, ptmp: PGear;
 begin
@@ -461,6 +536,7 @@
                 gear^.Radius:= 5;
                 gear^.Density:= _1_5;
                 end;
+{
    gtStructure: begin
                 gear^.Elasticity:= _0_55;
                 gear^.Friction:= _0_995;
@@ -471,6 +547,7 @@
                 gear^.Tag:= TotalRounds + 3;
                 gear^.Pos:= 1;
                 end;
+}
       gtIceGun: gear^.Health:= 1000;
 gtGenericFaller:begin
                 gear^.AdvBounce:= 1;
--- a/hedgewars/uGearsRender.pas	Fri Nov 30 18:19:52 2012 +0400
+++ b/hedgewars/uGearsRender.pas	Tue Dec 04 09:15:55 2012 +0400
@@ -39,6 +39,14 @@
 implementation
 uses uRender, uUtils, uVariables, uAmmos, Math, uVisualGears;
 
+const
+    // hog tag mask
+    htNone        = $00;
+    htTeamName    = $01;
+    htName        = $02;
+    htHealth      = $04;
+    htTransparent = $08;
+
 procedure DrawRopeLinesRQ(Gear: PGear);
 begin
 with RopePoints do
@@ -1178,7 +1186,7 @@
                         if Gear^.FlightTime > 0 then
                             Tint($FF, $FF, $FF, $FF);
                         end;
-       gtStructure: DrawSprite(sprTarget, x - 16, y - 16, 0);
+       //gtStructure: DrawSprite(sprTarget, x - 16, y - 16, 0);
           gtTardis: if Gear^.Pos <> 4 then
                         begin
                         if Gear^.Pos = 2 then
--- a/hedgewars/uGearsUtils.pas	Fri Nov 30 18:19:52 2012 +0400
+++ b/hedgewars/uGearsUtils.pas	Tue Dec 04 09:15:55 2012 +0400
@@ -106,8 +106,8 @@
                 gtTarget,
                 gtFlame,
                 gtKnife,
-                gtExplosives,
-                gtStructure: begin
+                gtExplosives: begin //,
+                //gtStructure: begin
 // Run the calcs only once we know we have a type that will need damage
                         tdX:= Gear^.X-fX;
                         tdY:= Gear^.Y-fY;
@@ -243,8 +243,8 @@
             end;
         uStats.HedgehogDamaged(Gear, AttackerHog, Damage, false);    
         end;
-    end
-    else if Gear^.Kind <> gtStructure then // not gtHedgehog nor gtStructure
+    end else
+    //else if Gear^.Kind <> gtStructure then // not gtHedgehog nor gtStructure
         Gear^.Hedgehog:= AttackerHog;
     inc(Gear^.Damage, Damage);
     
--- a/hedgewars/uIO.pas	Fri Nov 30 18:19:52 2012 +0400
+++ b/hedgewars/uIO.pas	Tue Dec 04 09:15:55 2012 +0400
@@ -41,6 +41,9 @@
 implementation
 uses uConsole, uConsts, uVariables, uCommands, uUtils, uDebug;
 
+const
+    cSendEmptyPacketTime = 1000;
+
 type PCmd = ^TCmd;
      TCmd = packed record
             Next: PCmd;
--- a/hedgewars/uInputHandler.pas	Fri Nov 30 18:19:52 2012 +0400
+++ b/hedgewars/uInputHandler.pas	Tue Dec 04 09:15:55 2012 +0400
@@ -60,6 +60,16 @@
     quitKeyCode, closeKeyCode: Byte;
     KeyNames: array [0..cKeyMaxIndex] of string[15];
     CurrentBinds: TBinds;
+    ControllerNumControllers: Integer;
+    ControllerEnabled: Integer;
+    ControllerNumAxes: array[0..5] of Integer;
+    //ControllerNumBalls: array[0..5] of Integer;
+    ControllerNumHats: array[0..5] of Integer;
+    ControllerNumButtons: array[0..5] of Integer;
+    ControllerAxes: array[0..5] of array[0..19] of Integer;
+    //ControllerBalls: array[0..5] of array[0..19] of array[0..1] of Integer;
+    ControllerHats: array[0..5] of array[0..19] of Byte;
+    ControllerButtons: array[0..5] of array[0..19] of Byte;
 
 function  KeyNameToCode(name: shortstring): LongInt; inline;
 begin
--- a/hedgewars/uLand.pas	Fri Nov 30 18:19:52 2012 +0400
+++ b/hedgewars/uLand.pas	Tue Dec 04 09:15:55 2012 +0400
@@ -596,7 +596,7 @@
             begin
             map:= cPathz[ptMapCurrent] + '/map.png';
             mask:= cPathz[ptMapCurrent] + '/mask.png';
-            if (not(FileExists(map)) and FileExists(mask)) then
+            if (not(pfsExists(map)) and pfsExists(mask)) then
                 begin
                 maskOnly:= true;
                 LoadMask;
--- a/hedgewars/uLandObjects.pas	Fri Nov 30 18:19:52 2012 +0400
+++ b/hedgewars/uLandObjects.pas	Tue Dec 04 09:15:55 2012 +0400
@@ -37,6 +37,7 @@
 const MaxRects = 512;
       MAXOBJECTRECTS = 16;
       MAXTHEMEOBJECTS = 32;
+      cThemeCFGFilename = 'theme.cfg';
 
 type TRectsArray = array[0..MaxRects] of TSDL_Rect;
      PRectArray = ^TRectsArray;
--- a/hedgewars/uLandOutline.pas	Fri Nov 30 18:19:52 2012 +0400
+++ b/hedgewars/uLandOutline.pas	Tue Dec 04 09:15:55 2012 +0400
@@ -27,6 +27,9 @@
                                      end
            end;
 
+const
+    cMaxEdgePoints = 16384;
+
 procedure Push(_xl, _xr, _y, _dir: LongInt);
 begin
     TryDo(Stack.Count <= 8192, 'FillLand: stack overflow', true);
--- a/hedgewars/uMobile.pas	Fri Nov 30 18:19:52 2012 +0400
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,110 +0,0 @@
-(*
- * Hedgewars, a free turn based strategy game
- * Copyright (c) 2004-2012 Andrey Korotaev <unC0Rr@gmail.com>
- *
- * This program is free software; you can redistribute it and/or modify
- * it under the terms of the GNU General Public License as published by
- * the Free Software Foundation; version 2 of the License
- *
- * This program is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
- * GNU General Public License for more details.
- *
- * You should have received a copy of the GNU General Public License
- * along with this program; if not, write to the Free Software
- * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA
- *)
-
-{$INCLUDE "options.inc"}
-
-(*
- * This unit contains a lot of useful functions when hw is running on mobile
- * Unlike HwLibrary when you declare functions that you will call from your code,
- * here you need to provide functions that Pascall code will call.
- *)
-
-unit uMobile;
-interface
-
-function  isPhone: Boolean; inline;
-function  getScreenDPI: Double; inline;
-procedure performRumble; inline;
-
-procedure GameLoading; inline;
-procedure GameLoaded; inline;
-procedure SaveLoadingEnded; inline;
-
-implementation
-uses uVariables, uConsole, SDLh;
-
-// add here any external call that you need
-{$IFDEF IPHONEOS}
-(*  iOS calls written in ObjcExports.m  *)
-procedure startLoadingIndicator; cdecl; external;
-procedure stopLoadingIndicator; cdecl; external;
-procedure saveFinishedSynching; cdecl; external;
-function  isApplePhone: Boolean; cdecl; external;
-procedure AudioServicesPlaySystemSound(num: LongInt); cdecl; external;
-{$ENDIF}
-
-// this function is just to determine whether we are running on a limited screen device
-function isPhone: Boolean; inline;
-begin
-    isPhone:= false;
-{$IFDEF IPHONEOS}
-    isPhone:= isApplePhone();
-{$ENDIF}
-{$IFDEF ANDROID}
-    //nasty nasty hack. TODO: implement callback to java to have a unified way of determining if it is a tablet
-    if (cScreenWidth < 1000) and (cScreenHeight < 500) then
-        isPhone:= true;
-{$ENDIF}
-end;
-
-function getScreenDPI: Double; inline;
-begin
-{$IFDEF ANDROID}
-//    getScreenDPI:= Android_JNI_getDensity();
-    getScreenDPI:= 1;
-{$ELSE}
-    getScreenDPI:= 1;
-{$ENDIF}
-end;
-
-// this function should make the device vibrate in some way
-procedure PerformRumble; inline;
-{$IFDEF IPHONEOS}const kSystemSoundID_Vibrate = $00000FFF;{$ENDIF}
-begin
-    // do not vibrate while synchronising a demo/save
-    if not fastUntilLag then
-    begin
-{$IFDEF IPHONEOS}
-        AudioServicesPlaySystemSound(kSystemSoundID_Vibrate);
-{$ENDIF}
-    end;
-end;
-
-procedure GameLoading; inline;
-begin
-{$IFDEF IPHONEOS}
-    startLoadingIndicator();
-{$ENDIF}
-end;
-
-procedure GameLoaded; inline;
-begin
-{$IFDEF IPHONEOS}
-    stopLoadingIndicator();
-{$ENDIF}
-end;
-
-procedure SaveLoadingEnded; inline;
-begin
-{$IFDEF IPHONEOS}
-    saveFinishedSynching();
-{$ENDIF}
-end;
-
-
-end.
--- a/hedgewars/uPhysFSLayer.pas	Fri Nov 30 18:19:52 2012 +0400
+++ b/hedgewars/uPhysFSLayer.pas	Tue Dec 04 09:15:55 2012 +0400
@@ -15,6 +15,7 @@
 {$IFDEF WIN32}
     PhysfsLibName = 'libphysfs';
 {$ELSE}
+    {$LINKLIB ../bin/libphysfs.a}
     PhysfsLibName = 'physfs';
 {$ENDIF}
 
--- a/hedgewars/uRender.pas	Fri Nov 30 18:19:52 2012 +0400
+++ b/hedgewars/uRender.pas	Tue Dec 04 09:15:55 2012 +0400
@@ -55,6 +55,12 @@
 implementation
 uses uVariables;
 
+{$IFDEF USE_TOUCH_INTERFACE}
+const
+    FADE_ANIM_TIME = 500;
+    MOVE_ANIM_TIME = 500;
+{$ENDIF}
+
 var LastTint: LongWord = 0;
 
 procedure DrawSpriteFromRect(Sprite: TSprite; r: TSDL_Rect; X, Y, Height, Position: LongInt);
--- a/hedgewars/uScript.pas	Fri Nov 30 18:19:52 2012 +0400
+++ b/hedgewars/uScript.pas	Tue Dec 04 09:15:55 2012 +0400
@@ -2319,6 +2319,7 @@
 ScriptSetInteger('gstHHGone'         ,$00100000);
 ScriptSetInteger('gstInvisible'      ,$00200000);
 
+// ai hints
 ScriptSetInteger('aihUsualProcessing' ,$00000000);
 ScriptSetInteger('aihDoesntMatter'    ,$00000001);
 
--- a/hedgewars/uSound.pas	Fri Nov 30 18:19:52 2012 +0400
+++ b/hedgewars/uSound.pas	Tue Dec 04 09:15:55 2012 +0400
@@ -120,6 +120,136 @@
     isMusicEnabled: boolean;
     isSoundEnabled: boolean;
     isSEBackup: boolean;
+    VoiceList : array[0..7] of TVoice =  (
+                    ( snd: sndNone; voicepack: nil),
+                    ( snd: sndNone; voicepack: nil),
+                    ( snd: sndNone; voicepack: nil),
+                    ( snd: sndNone; voicepack: nil),
+                    ( snd: sndNone; voicepack: nil),
+                    ( snd: sndNone; voicepack: nil),
+                    ( snd: sndNone; voicepack: nil),
+                    ( snd: sndNone; voicepack: nil));
+    Soundz: array[TSound] of record
+            FileName: string[31];
+            Path    : TPathType;
+            end = (
+            (FileName:                         ''; Path: ptNone  ),// sndNone
+            (FileName:        'grenadeimpact.ogg'; Path: ptSounds),// sndGrenadeImpact
+            (FileName:            'explosion.ogg'; Path: ptSounds),// sndExplosion
+            (FileName:         'throwpowerup.ogg'; Path: ptSounds),// sndThrowPowerUp
+            (FileName:         'throwrelease.ogg'; Path: ptSounds),// sndThrowRelease
+            (FileName:               'splash.ogg'; Path: ptSounds),// sndSplash
+            (FileName:        'shotgunreload.ogg'; Path: ptSounds),// sndShotgunReload
+            (FileName:          'shotgunfire.ogg'; Path: ptSounds),// sndShotgunFire
+            (FileName:          'graveimpact.ogg'; Path: ptSounds),// sndGraveImpact
+            (FileName:           'mineimpact.ogg'; Path: ptSounds),// sndMineImpact
+            (FileName:             'minetick.ogg'; Path: ptSounds),// sndMineTicks
+            (FileName:             'Droplet1.ogg'; Path: ptSounds),// sndMudballImpact
+            (FileName:           'pickhammer.ogg'; Path: ptSounds),// sndPickhammer
+            (FileName:                  'gun.ogg'; Path: ptSounds),// sndGun
+            (FileName:                  'bee.ogg'; Path: ptSounds),// sndBee
+            (FileName:                'Jump1.ogg'; Path: ptVoices),// sndJump1
+            (FileName:                'Jump2.ogg'; Path: ptVoices),// sndJump2
+            (FileName:                'Jump3.ogg'; Path: ptVoices),// sndJump3
+            (FileName:               'Yessir.ogg'; Path: ptVoices),// sndYesSir
+            (FileName:                'Laugh.ogg'; Path: ptVoices),// sndLaugh
+            (FileName:            'Illgetyou.ogg'; Path: ptVoices),// sndIllGetYou
+            (FileName:          'JustYouWait.ogg'; Path: ptVoices),// sndJustYouWait
+            (FileName:             'Incoming.ogg'; Path: ptVoices),// sndIncoming
+            (FileName:               'Missed.ogg'; Path: ptVoices),// sndMissed
+            (FileName:               'Stupid.ogg'; Path: ptVoices),// sndStupid
+            (FileName:           'Firstblood.ogg'; Path: ptVoices),// sndFirstBlood
+            (FileName:               'Boring.ogg'; Path: ptVoices),// sndBoring
+            (FileName:               'Byebye.ogg'; Path: ptVoices),// sndByeBye
+            (FileName:             'Sameteam.ogg'; Path: ptVoices),// sndSameTeam
+            (FileName:               'Nutter.ogg'; Path: ptVoices),// sndNutter
+            (FileName:       'Reinforcements.ogg'; Path: ptVoices),// sndReinforce
+            (FileName:              'Traitor.ogg'; Path: ptVoices),// sndTraitor
+            (FileName:      'Youllregretthat.ogg'; Path: ptVoices),// sndRegret
+            (FileName:            'Enemydown.ogg'; Path: ptVoices),// sndEnemyDown
+            (FileName:               'Coward.ogg'; Path: ptVoices),// sndCoward
+            (FileName:                'Hurry.ogg'; Path: ptVoices),// sndHurry
+            (FileName:              'Watchit.ogg'; Path: ptVoices),// sndWatchIt
+            (FileName:             'Kamikaze.ogg'; Path: ptVoices),// sndKamikaze
+            (FileName:                'cake2.ogg'; Path: ptSounds),// sndCake
+            (FileName:                  'Ow1.ogg'; Path: ptVoices),// sndOw1
+            (FileName:                  'Ow2.ogg'; Path: ptVoices),// sndOw2
+            (FileName:                  'Ow3.ogg'; Path: ptVoices),// sndOw3
+            (FileName:                  'Ow4.ogg'; Path: ptVoices),// sndOw4
+            (FileName:           'Firepunch1.ogg'; Path: ptVoices),// sndFirepunch1
+            (FileName:           'Firepunch2.ogg'; Path: ptVoices),// sndFirepunch2
+            (FileName:           'Firepunch3.ogg'; Path: ptVoices),// sndFirepunch3
+            (FileName:           'Firepunch4.ogg'; Path: ptVoices),// sndFirepunch4
+            (FileName:           'Firepunch5.ogg'; Path: ptVoices),// sndFirepunch5
+            (FileName:           'Firepunch6.ogg'; Path: ptVoices),// sndFirepunch6
+            (FileName:                'Melon.ogg'; Path: ptVoices),// sndMelon
+            (FileName:              'Hellish.ogg'; Path: ptSounds),// sndHellish
+            (FileName:               'Yoohoo.ogg'; Path: ptSounds),// sndYoohoo
+            (FileName:              'rcplane.ogg'; Path: ptSounds),// sndRCPlane
+            (FileName:            'whipcrack.ogg'; Path: ptSounds),// sndWhipCrack
+            (FileName:'ride_of_the_valkyries.ogg'; Path: ptSounds),// sndRideOfTheValkyries
+            (FileName:               'denied.ogg'; Path: ptSounds),// sndDenied
+            (FileName:               'placed.ogg'; Path: ptSounds),// sndPlaced
+            (FileName:          'baseballbat.ogg'; Path: ptSounds),// sndBaseballBat
+            (FileName:                'steam.ogg'; Path: ptSounds),// sndVaporize
+            (FileName:                 'warp.ogg'; Path: ptSounds),// sndWarp
+            (FileName:          'suddendeath.ogg'; Path: ptSounds),// sndSuddenDeath
+            (FileName:               'mortar.ogg'; Path: ptSounds),// sndMortar
+            (FileName:         'shutterclick.ogg'; Path: ptSounds),// sndShutter
+            (FileName:              'homerun.ogg'; Path: ptSounds),// sndHomerun
+            (FileName:              'molotov.ogg'; Path: ptSounds),// sndMolotov
+            (FileName:            'Takecover.ogg'; Path: ptVoices),// sndCover
+            (FileName:                'Uh-oh.ogg'; Path: ptVoices),// sndUhOh
+            (FileName:                 'Oops.ogg'; Path: ptVoices),// sndOops
+            (FileName:                 'Nooo.ogg'; Path: ptVoices),// sndNooo
+            (FileName:                'Hello.ogg'; Path: ptVoices),// sndHello
+            (FileName:             'ropeshot.ogg'; Path: ptSounds),// sndRopeShot
+            (FileName:           'ropeattach.ogg'; Path: ptSounds),// sndRopeAttach
+            (FileName:          'roperelease.ogg'; Path: ptSounds),// sndRopeRelease
+            (FileName:            'switchhog.ogg'; Path: ptSounds),// sndSwitchHog
+            (FileName:              'Victory.ogg'; Path: ptVoices),// sndVictory
+            (FileName:             'Flawless.ogg'; Path: ptVoices),// sndFlawless
+            (FileName:         'sniperreload.ogg'; Path: ptSounds),// sndSniperReload
+            (FileName:                'steps.ogg'; Path: ptSounds),// sndSteps
+            (FileName:           'lowgravity.ogg'; Path: ptSounds),// sndLowGravity
+            (FileName:           'hell_growl.ogg'; Path: ptSounds),// sndHellishImpact1
+            (FileName:            'hell_ooff.ogg'; Path: ptSounds),// sndHellishImpact2
+            (FileName:              'hell_ow.ogg'; Path: ptSounds),// sndHellishImpact3
+            (FileName:             'hell_ugh.ogg'; Path: ptSounds),// sndHellishImpact4
+            (FileName:          'melonimpact.ogg'; Path: ptSounds),// sndMelonImpact
+            (FileName:             'Droplet1.ogg'; Path: ptSounds),// sndDroplet1
+            (FileName:             'Droplet2.ogg'; Path: ptSounds),// sndDroplet2
+            (FileName:             'Droplet3.ogg'; Path: ptSounds),// sndDroplet3
+            (FileName:                  'egg.ogg'; Path: ptSounds),// sndEggBreak
+            (FileName:             'drillgun.ogg'; Path: ptSounds),// sndDrillRocket
+            (FileName:          'PoisonCough.ogg'; Path: ptVoices),// sndPoisonCough
+            (FileName:           'PoisonMoan.ogg'; Path: ptVoices),// sndPoisonMoan
+            (FileName:             'BirdyLay.ogg'; Path: ptSounds),// sndBirdyLay
+            (FileName:              'Whistle.ogg'; Path: ptSounds),// sndWhistle
+            (FileName:             'beewater.ogg'; Path: ptSounds),// sndBeeWater
+            (FileName:                   '1C.ogg'; Path: ptSounds),// sndPiano0
+            (FileName:                   '2D.ogg'; Path: ptSounds),// sndPiano1
+            (FileName:                   '3E.ogg'; Path: ptSounds),// sndPiano2
+            (FileName:                   '4F.ogg'; Path: ptSounds),// sndPiano3
+            (FileName:                   '5G.ogg'; Path: ptSounds),// sndPiano4
+            (FileName:                   '6A.ogg'; Path: ptSounds),// sndPiano5
+            (FileName:                   '7B.ogg'; Path: ptSounds),// sndPiano6
+            (FileName:                   '8C.ogg'; Path: ptSounds),// sndPiano7
+            (FileName:                   '9D.ogg'; Path: ptSounds),// sndPiano8
+            (FileName:                 'skip.ogg'; Path: ptSounds),// sndSkip
+            (FileName:              'sinegun.ogg'; Path: ptSounds),// sndSineGun
+            (FileName:                'Ooff1.ogg'; Path: ptVoices),// sndOoff1
+            (FileName:                'Ooff2.ogg'; Path: ptVoices),// sndOoff2
+            (FileName:                'Ooff3.ogg'; Path: ptVoices),// sndOoff3
+            (FileName:               'hammer.ogg'; Path: ptSounds),// sndWhack
+            (FileName:           'Comeonthen.ogg'; Path: ptVoices),// sndComeonthen
+            (FileName:            'parachute.ogg'; Path: ptSounds),// sndParachute
+            (FileName:                 'bump.ogg'; Path: ptSounds),// sndBump
+            (FileName:            'hogchant3.ogg'; Path: ptSounds),// sndResurrector
+            (FileName:                'plane.ogg'; Path: ptSounds),// sndPlane
+            (FileName:               'TARDIS.ogg'; Path: ptSounds) // sndTardis
+            );
+
 
 
 function  AskForVoicepack(name: shortstring): Pointer;
@@ -256,7 +386,7 @@
         if (voicepack^.chunks[snd] = nil) and (Soundz[snd].Path = ptVoices) and (Soundz[snd].FileName <> '') then
             begin
             s:= cPathz[Soundz[snd].Path] + '/' + voicepack^.name + '/' + Soundz[snd].FileName;
-            if (not FileExists(s)) and (snd in [sndFirePunch2, sndFirePunch3, sndFirePunch4, sndFirePunch5, sndFirePunch6]) then
+            if (not pfsExists(s)) and (snd in [sndFirePunch2, sndFirePunch3, sndFirePunch4, sndFirePunch5, sndFirePunch6]) then
                 s:= cPathz[Soundz[sndFirePunch1].Path] + '/' + voicepack^.name + '/' + Soundz[snd].FileName;
             WriteToConsole(msgLoading + s + ' ');
             voicepack^.chunks[snd]:= Mix_LoadWAV_RW(rwopsOpenRead(s), 1);
@@ -289,7 +419,7 @@
     if (snd = sndVictory) or (snd = sndFlawless) then
         begin
         Mix_FadeOutChannel(-1, 800);
-        for i:= 0 to 7 do
+        for i:= 0 to High(VoiceList) do
             VoiceList[i].snd:= sndNone;
         LastVoice.snd:= sndNone;
         end;
@@ -311,7 +441,7 @@
     if (not isSoundEnabled) or fastUntilLag or ((LastVoice.snd <> sndNone) and (lastChan[LastVoice.snd] <> -1) and (Mix_Playing(lastChan[LastVoice.snd]) <> 0)) then
         exit;
     i:= 0;
-    while (i<8) and (VoiceList[i].snd = sndNone) do
+    while (i<High(VoiceList)) and (VoiceList[i].snd = sndNone) do
         inc(i);
     
     if (VoiceList[i].snd <> sndNone) then
@@ -589,7 +719,7 @@
                 voicepacks[t].chunks[i]:= nil;
 
     (* on MOBILE SDL_mixer has to be compiled against Tremor (USE_OGG_TREMOR)
-       or sound files bigger than 32k will lockup the game *)
+       or sound files bigger than 32k will lockup the game on slow cpu *)
     for i:= Low(TSound) to High(TSound) do
         defVoicepack^.chunks[i]:= nil;
 
--- a/hedgewars/uStore.pas	Fri Nov 30 18:19:52 2012 +0400
+++ b/hedgewars/uStore.pas	Tue Dec 04 09:15:55 2012 +0400
@@ -33,7 +33,7 @@
 procedure FinishProgress;
 function  LoadImage(const filename: shortstring; imageFlags: LongInt): PSDL_Surface;
 
-// loads an image from the game's data files
+// loads an image from the games data files
 function  LoadDataImage(const path: TPathType; const filename: shortstring; imageFlags: LongInt): PSDL_Surface;
 // like LoadDataImage but uses altPath as fallback-path if file not found/loadable in path
 function  LoadDataImageAltPath(const path, altPath: TPathType; const filename: shortstring; imageFlags: LongInt): PSDL_Surface;
@@ -56,7 +56,7 @@
 procedure SwapBuffers; {$IFDEF USE_VIDEO_RECORDING}cdecl{$ELSE}inline{$ENDIF};
 
 implementation
-uses uMisc, uConsole, uMobile, uVariables, uUtils, uTextures, uRender, uRenderUtils, uCommands
+uses uMisc, uConsole, uVariables, uUtils, uTextures, uRender, uRenderUtils, uCommands
     , uPhysFSLayer
     , uDebug
     {$IFDEF USE_CONTEXT_RESTORE}, uWorld{$ENDIF}
@@ -71,6 +71,13 @@
 {$ELSE}
     SDLPrimSurface: PSDL_Surface;
 {$ENDIF}
+    squaresize : LongInt;
+    numsquares : LongInt;
+    ProgrTex: PTexture;
+
+const 
+    cHHFileName = 'Hedgehog';
+    cCHFileName = 'Crosshair';
 
 function WriteInRect(Surface: PSDL_Surface; X, Y: LongInt; Color: LongWord; Font: THWFont; s: ansistring): TSDL_Rect;
 var w, h: LongInt;
@@ -437,7 +444,7 @@
 IMG_Quit();
 end;
 
-{$IF NOT DEFINED(S3D_DISABLED) OR DEFINED(USE_VIDEO_RECORDING)}
+{$IF DEFINED(USE_S3D_RENDERING) OR DEFINED(USE_VIDEO_RECORDING)}
 procedure CreateFramebuffer(var frame, depth, tex: GLuint);
 begin
     glGenFramebuffersEXT(1, @frame);
@@ -539,7 +546,7 @@
     if defaultFrame <> 0 then
         DeleteFramebuffer(defaultFrame, depthv, texv);
 {$ENDIF}
-{$IFNDEF S3D_DISABLED}
+{$IFDEF USE_S3D_RENDERING}
     if (cStereoMode = smHorizontal) or (cStereoMode = smVertical) or (cStereoMode = smAFR) then
         begin
         DeleteFramebuffer(framel, depthl, texl);
@@ -805,7 +812,7 @@
     end;
 {$ENDIF}
 
-{$IFNDEF S3D_DISABLED}
+{$IFDEF USE_S3D_RENDERING}
     if (cStereoMode = smHorizontal) or (cStereoMode = smVertical) or (cStereoMode = smAFR) then
     begin
         // prepare left and right frame buffers and associated textures
@@ -879,8 +886,10 @@
         squaresize:= texsurf^.w shr 1;
         numsquares:= texsurf^.h div squaresize;
         SDL_FreeSurface(texsurf);
-
-        uMobile.GameLoading();
+        with mobileRecord do
+            if GameLoading <> nil then
+                GameLoading();
+        
         end;
 
     TryDo(ProgrTex <> nil, 'Error - Progress Texure is nil!', true);
@@ -903,7 +912,9 @@
 
 procedure FinishProgress;
 begin
-    uMobile.GameLoaded();
+    with mobileRecord do
+        if GameLoaded <> nil then
+            GameLoaded();
     WriteLnToConsole('Freeing progress surface... ');
     FreeTexture(ProgrTex);
     ProgrTex:= nil;
--- a/hedgewars/uTeams.pas	Fri Nov 30 18:19:52 2012 +0400
+++ b/hedgewars/uTeams.pas	Tue Dec 04 09:15:55 2012 +0400
@@ -46,6 +46,7 @@
 
 var MaxTeamHealth: LongInt;
     GameOver: boolean;
+    NextClan: boolean;
 
 function CheckForWin: boolean;
 var AliveClan: PClan;
--- a/hedgewars/uTouch.pas	Fri Nov 30 18:19:52 2012 +0400
+++ b/hedgewars/uTouch.pas	Tue Dec 04 09:15:55 2012 +0400
@@ -22,7 +22,7 @@
 
 interface
 
-uses SysUtils, uConsole, uVariables, SDLh, uFloat, uConsts, uCommands, GLUnit, uTypes, uCaptions, uAmmos, uWorld, uMobile;
+uses SysUtils, uConsole, uVariables, SDLh, uFloat, uConsts, uCommands, GLUnit, uTypes, uCaptions, uAmmos, uWorld;
 
 
 procedure initModule;
@@ -558,7 +558,7 @@
     isOnCrosshair:= isOnRect((x-HalfRectSize), (y-HalfRectSize), RectSize, RectSize, finger);
     printFinger(finger);
     WriteLnToConsole(inttostr(finger.x) + '   ' + inttostr(x));
-    WriteLnToConsole(inttostr(x) + '  ' + inttostr(y) + '   ' + inttostr(round(uMobile.getScreenDPI * 10)));
+    WriteLnToConsole(inttostr(x) + '  ' + inttostr(y) + '   ' + inttostr(round(mobileRecord.getScreenDPI() * 10)));
 end;
 
 function isOnCurrentHog(finger: TTouch_Data): boolean;
@@ -640,7 +640,7 @@
     for index := 0 to High(fingers) do 
         fingers[index].id := nilFingerId;
 
-    rectSize:= round(baseRectSize * uMobile.getScreenDPI);
+    rectSize:= round(baseRectSize * mobileRecord.getScreenDPI());
     halfRectSize:= rectSize shl 1;
 end;
 
--- a/hedgewars/uTypes.pas	Fri Nov 30 18:19:52 2012 +0400
+++ b/hedgewars/uTypes.pas	Tue Dec 04 09:15:55 2012 +0400
@@ -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, // 61
             gtIceGun, gtAddAmmo, gtGenericFaller, gtKnife); // 65
 
     // Gears that are _only_ of visual nature (e.g. background stuff, visual effects, speechbubbles, etc.)
@@ -151,7 +151,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, amIceGun, amKnife); // 54
+            amResurrector, amDrillStrike, amSnowball, amTardis, {amStructure,} amLandGun, amIceGun, amKnife); // 54
 
     // Different kind of crates that e.g. hedgehogs can pick up
     TCrateType = (HealthCrate, AmmoCrate, UtilityCrate);
@@ -399,6 +399,18 @@
             Flawless: boolean;
             end;
 
+     cdeclPtr = procedure; cdecl;
+     cdeclIntPtr = procedure(num: LongInt); cdecl;
+     functionDoublePtr = function: Double;
+
+     TMobileRecord = record
+                     getScreenDPI: functionDoublePtr;
+                     PerformRumble: cdeclIntPtr;
+                     GameLoading: cdeclPtr;
+                     GameLoaded: cdeclPtr;
+                     SaveLoadingEnded: cdeclPtr;
+                     end;
+
      TAmmoStrId = (sidGrenade, sidClusterBomb, sidBazooka, sidBee, sidShotgun,
             sidPickHammer, sidSkip, sidRope, sidMine, sidDEagle,
             sidDynamite, sidBaseballBat, sidFirePunch, sidSeconds,
@@ -411,7 +423,7 @@
             sidMolotov, sidBirdy, sidPortalGun, sidPiano, sidGasBomb,
             sidSineGun, sidFlamethrower,sidSMine, sidHammer, sidResurrector,
             sidDrillStrike, sidSnowball, sidNothing, sidTardis,
-            sidStructure, sidLandGun, sidIceGun, sidKnife);
+            {sidStructure,} sidLandGun, sidIceGun, sidKnife);
 
     TMsgStrId = (sidStartFight, sidDraw, sidWinner, sidVolume, sidPaused,
             sidConfirm, sidSuddenDeath, sidRemaining, sidFuel, sidSync,
--- a/hedgewars/uUtils.pas	Fri Nov 30 18:19:52 2012 +0400
+++ b/hedgewars/uUtils.pas	Tue Dec 04 09:15:55 2012 +0400
@@ -73,6 +73,17 @@
 procedure WriteLn(var f: textfile; s: shortstring);
 {$ENDIF}
 
+function  isPhone: Boolean; inline;
+function  getScreenDPI: Double; inline; //cdecl; external;
+
+{$IFDEF IPHONEOS}
+procedure startLoadingIndicator; cdecl; external;
+procedure stopLoadingIndicator; cdecl; external;
+procedure saveFinishedSynching; cdecl; external;
+function  isApplePhone: Boolean; cdecl; external;
+procedure AudioServicesPlaySystemSound(num: LongInt); cdecl; external;
+{$ENDIF}
+
 procedure initModule(isNotPreview: boolean);
 procedure freeModule;
 
@@ -401,6 +412,31 @@
 end;
 {$ENDIF}
 
+// this function is just to determine whether we are running on a limited screen device
+function isPhone: Boolean; inline;
+begin
+    isPhone:= false;
+{$IFDEF IPHONEOS}
+    isPhone:= isApplePhone();
+{$ENDIF}
+{$IFDEF ANDROID}
+    //nasty nasty hack. TODO: implement callback to java to have a unified way of determining if it is a tablet
+    if (cScreenWidth < 1000) and (cScreenHeight < 500) then
+        isPhone:= true;
+{$ENDIF}
+end;
+
+//This dummy function should be reimplemented (externally).
+function getScreenDPI: Double; inline;
+begin
+{$IFDEF ANDROID}
+//    getScreenDPI:= Android_JNI_getDensity();
+    getScreenDPI:= 1;
+{$ELSE}
+    getScreenDPI:= 1;
+{$ENDIF}
+end;
+
 procedure initModule(isNotPreview: boolean);
 {$IFDEF DEBUGFILE}
 var logfileBase: shortstring;
--- a/hedgewars/uVariables.pas	Fri Nov 30 18:19:52 2012 +0400
+++ b/hedgewars/uVariables.pas	Tue Dec 04 09:15:55 2012 +0400
@@ -21,7 +21,7 @@
 unit uVariables;
 interface
 
-uses SDLh, uTypes, uFloat, GLunit, uConsts, Math, uMobile, uUtils;
+uses SDLh, uTypes, uFloat, GLunit, uConsts, Math, uUtils;
 
 var
 /////// init flags ///////
@@ -157,7 +157,6 @@
     cVampiric       : boolean;
     cArtillery      : boolean;
     WeaponTooltipTex: PTexture;
-    AmmoMenuTex     : PTexture;
     AmmoMenuInvalidated: boolean;
     AmmoRect		: TSDL_Rect;
     HHTexture       : PTexture;
@@ -196,17 +195,10 @@
 
     LuaTemplateNumber : LongWord;
 
-    VoiceList : array[0..7] of TVoice =  (
-                    ( snd: sndNone; voicepack: nil),
-                    ( snd: sndNone; voicepack: nil),
-                    ( snd: sndNone; voicepack: nil),
-                    ( snd: sndNone; voicepack: nil),
-                    ( snd: sndNone; voicepack: nil),
-                    ( snd: sndNone; voicepack: nil),
-                    ( snd: sndNone; voicepack: nil),
-                    ( snd: sndNone; voicepack: nil));
     LastVoice : TVoice = ( snd: sndNone; voicepack: nil );
 
+    mobileRecord: TMobileRecord;
+
 /////////////////////////////////////
 //Buttons
 {$IFDEF USE_TOUCH_INTERFACE}
@@ -690,126 +682,6 @@
             (Sprite:   sprJuggle; FramesCount: 49; Interval:  38; cmd: '/juggle'; Voice: sndNone; VoiceDelay: 0)
             );
 
-    Soundz: array[TSound] of record
-            FileName: string[31];
-            Path    : TPathType;
-            end = (
-            (FileName:                         ''; Path: ptNone  ),// sndNone
-            (FileName:        'grenadeimpact.ogg'; Path: ptSounds),// sndGrenadeImpact
-            (FileName:            'explosion.ogg'; Path: ptSounds),// sndExplosion
-            (FileName:         'throwpowerup.ogg'; Path: ptSounds),// sndThrowPowerUp
-            (FileName:         'throwrelease.ogg'; Path: ptSounds),// sndThrowRelease
-            (FileName:               'splash.ogg'; Path: ptSounds),// sndSplash
-            (FileName:        'shotgunreload.ogg'; Path: ptSounds),// sndShotgunReload
-            (FileName:          'shotgunfire.ogg'; Path: ptSounds),// sndShotgunFire
-            (FileName:          'graveimpact.ogg'; Path: ptSounds),// sndGraveImpact
-            (FileName:           'mineimpact.ogg'; Path: ptSounds),// sndMineImpact
-            (FileName:             'minetick.ogg'; Path: ptSounds),// sndMineTicks
-            (FileName:             'Droplet1.ogg'; Path: ptSounds),// sndMudballImpact
-            (FileName:           'pickhammer.ogg'; Path: ptSounds),// sndPickhammer
-            (FileName:                  'gun.ogg'; Path: ptSounds),// sndGun
-            (FileName:                  'bee.ogg'; Path: ptSounds),// sndBee
-            (FileName:                'Jump1.ogg'; Path: ptVoices),// sndJump1
-            (FileName:                'Jump2.ogg'; Path: ptVoices),// sndJump2
-            (FileName:                'Jump3.ogg'; Path: ptVoices),// sndJump3
-            (FileName:               'Yessir.ogg'; Path: ptVoices),// sndYesSir
-            (FileName:                'Laugh.ogg'; Path: ptVoices),// sndLaugh
-            (FileName:            'Illgetyou.ogg'; Path: ptVoices),// sndIllGetYou
-            (FileName:          'JustYouWait.ogg'; Path: ptVoices),// sndJustYouWait
-            (FileName:             'Incoming.ogg'; Path: ptVoices),// sndIncoming
-            (FileName:               'Missed.ogg'; Path: ptVoices),// sndMissed
-            (FileName:               'Stupid.ogg'; Path: ptVoices),// sndStupid
-            (FileName:           'Firstblood.ogg'; Path: ptVoices),// sndFirstBlood
-            (FileName:               'Boring.ogg'; Path: ptVoices),// sndBoring
-            (FileName:               'Byebye.ogg'; Path: ptVoices),// sndByeBye
-            (FileName:             'Sameteam.ogg'; Path: ptVoices),// sndSameTeam
-            (FileName:               'Nutter.ogg'; Path: ptVoices),// sndNutter
-            (FileName:       'Reinforcements.ogg'; Path: ptVoices),// sndReinforce
-            (FileName:              'Traitor.ogg'; Path: ptVoices),// sndTraitor
-            (FileName:      'Youllregretthat.ogg'; Path: ptVoices),// sndRegret
-            (FileName:            'Enemydown.ogg'; Path: ptVoices),// sndEnemyDown
-            (FileName:               'Coward.ogg'; Path: ptVoices),// sndCoward
-            (FileName:                'Hurry.ogg'; Path: ptVoices),// sndHurry
-            (FileName:              'Watchit.ogg'; Path: ptVoices),// sndWatchIt
-            (FileName:             'Kamikaze.ogg'; Path: ptVoices),// sndKamikaze
-            (FileName:                'cake2.ogg'; Path: ptSounds),// sndCake
-            (FileName:                  'Ow1.ogg'; Path: ptVoices),// sndOw1
-            (FileName:                  'Ow2.ogg'; Path: ptVoices),// sndOw2
-            (FileName:                  'Ow3.ogg'; Path: ptVoices),// sndOw3
-            (FileName:                  'Ow4.ogg'; Path: ptVoices),// sndOw4
-            (FileName:           'Firepunch1.ogg'; Path: ptVoices),// sndFirepunch1
-            (FileName:           'Firepunch2.ogg'; Path: ptVoices),// sndFirepunch2
-            (FileName:           'Firepunch3.ogg'; Path: ptVoices),// sndFirepunch3
-            (FileName:           'Firepunch4.ogg'; Path: ptVoices),// sndFirepunch4
-            (FileName:           'Firepunch5.ogg'; Path: ptVoices),// sndFirepunch5
-            (FileName:           'Firepunch6.ogg'; Path: ptVoices),// sndFirepunch6
-            (FileName:                'Melon.ogg'; Path: ptVoices),// sndMelon
-            (FileName:              'Hellish.ogg'; Path: ptSounds),// sndHellish
-            (FileName:               'Yoohoo.ogg'; Path: ptSounds),// sndYoohoo
-            (FileName:              'rcplane.ogg'; Path: ptSounds),// sndRCPlane
-            (FileName:            'whipcrack.ogg'; Path: ptSounds),// sndWhipCrack
-            (FileName:'ride_of_the_valkyries.ogg'; Path: ptSounds),// sndRideOfTheValkyries
-            (FileName:               'denied.ogg'; Path: ptSounds),// sndDenied
-            (FileName:               'placed.ogg'; Path: ptSounds),// sndPlaced
-            (FileName:          'baseballbat.ogg'; Path: ptSounds),// sndBaseballBat
-            (FileName:                'steam.ogg'; Path: ptSounds),// sndVaporize
-            (FileName:                 'warp.ogg'; Path: ptSounds),// sndWarp
-            (FileName:          'suddendeath.ogg'; Path: ptSounds),// sndSuddenDeath
-            (FileName:               'mortar.ogg'; Path: ptSounds),// sndMortar
-            (FileName:         'shutterclick.ogg'; Path: ptSounds),// sndShutter
-            (FileName:              'homerun.ogg'; Path: ptSounds),// sndHomerun
-            (FileName:              'molotov.ogg'; Path: ptSounds),// sndMolotov
-            (FileName:            'Takecover.ogg'; Path: ptVoices),// sndCover
-            (FileName:                'Uh-oh.ogg'; Path: ptVoices),// sndUhOh
-            (FileName:                 'Oops.ogg'; Path: ptVoices),// sndOops
-            (FileName:                 'Nooo.ogg'; Path: ptVoices),// sndNooo
-            (FileName:                'Hello.ogg'; Path: ptVoices),// sndHello
-            (FileName:             'ropeshot.ogg'; Path: ptSounds),// sndRopeShot
-            (FileName:           'ropeattach.ogg'; Path: ptSounds),// sndRopeAttach
-            (FileName:          'roperelease.ogg'; Path: ptSounds),// sndRopeRelease
-            (FileName:            'switchhog.ogg'; Path: ptSounds),// sndSwitchHog
-            (FileName:              'Victory.ogg'; Path: ptVoices),// sndVictory
-            (FileName:             'Flawless.ogg'; Path: ptVoices),// sndFlawless
-            (FileName:         'sniperreload.ogg'; Path: ptSounds),// sndSniperReload
-            (FileName:                'steps.ogg'; Path: ptSounds),// sndSteps
-            (FileName:           'lowgravity.ogg'; Path: ptSounds),// sndLowGravity
-            (FileName:           'hell_growl.ogg'; Path: ptSounds),// sndHellishImpact1
-            (FileName:            'hell_ooff.ogg'; Path: ptSounds),// sndHellishImpact2
-            (FileName:              'hell_ow.ogg'; Path: ptSounds),// sndHellishImpact3
-            (FileName:             'hell_ugh.ogg'; Path: ptSounds),// sndHellishImpact4
-            (FileName:          'melonimpact.ogg'; Path: ptSounds),// sndMelonImpact
-            (FileName:             'Droplet1.ogg'; Path: ptSounds),// sndDroplet1
-            (FileName:             'Droplet2.ogg'; Path: ptSounds),// sndDroplet2
-            (FileName:             'Droplet3.ogg'; Path: ptSounds),// sndDroplet3
-            (FileName:                  'egg.ogg'; Path: ptSounds),// sndEggBreak
-            (FileName:             'drillgun.ogg'; Path: ptSounds),// sndDrillRocket
-            (FileName:          'PoisonCough.ogg'; Path: ptVoices),// sndPoisonCough
-            (FileName:           'PoisonMoan.ogg'; Path: ptVoices),// sndPoisonMoan
-            (FileName:             'BirdyLay.ogg'; Path: ptSounds),// sndBirdyLay
-            (FileName:              'Whistle.ogg'; Path: ptSounds),// sndWhistle
-            (FileName:             'beewater.ogg'; Path: ptSounds),// sndBeeWater
-            (FileName:                   '1C.ogg'; Path: ptSounds),// sndPiano0
-            (FileName:                   '2D.ogg'; Path: ptSounds),// sndPiano1
-            (FileName:                   '3E.ogg'; Path: ptSounds),// sndPiano2
-            (FileName:                   '4F.ogg'; Path: ptSounds),// sndPiano3
-            (FileName:                   '5G.ogg'; Path: ptSounds),// sndPiano4
-            (FileName:                   '6A.ogg'; Path: ptSounds),// sndPiano5
-            (FileName:                   '7B.ogg'; Path: ptSounds),// sndPiano6
-            (FileName:                   '8C.ogg'; Path: ptSounds),// sndPiano7
-            (FileName:                   '9D.ogg'; Path: ptSounds),// sndPiano8
-            (FileName:                 'skip.ogg'; Path: ptSounds),// sndSkip
-            (FileName:              'sinegun.ogg'; Path: ptSounds),// sndSineGun
-            (FileName:                'Ooff1.ogg'; Path: ptVoices),// sndOoff1
-            (FileName:                'Ooff2.ogg'; Path: ptVoices),// sndOoff2
-            (FileName:                'Ooff3.ogg'; Path: ptVoices),// sndOoff3
-            (FileName:               'hammer.ogg'; Path: ptSounds),// sndWhack
-            (FileName:           'Comeonthen.ogg'; Path: ptVoices),// sndComeonthen
-            (FileName:            'parachute.ogg'; Path: ptSounds),// sndParachute
-            (FileName:                 'bump.ogg'; Path: ptSounds),// sndBump
-            (FileName:            'hogchant3.ogg'; Path: ptSounds),// sndResurrector
-            (FileName:                'plane.ogg'; Path: ptSounds),// sndPlane
-            (FileName:               'TARDIS.ogg'; Path: ptSounds) // sndTardis
-            );
 var
     Ammoz: array [TAmmoType] of record
             NameId: TAmmoStrId;
@@ -2257,6 +2129,7 @@
             ejectY: 0),
 
 // Structure      
+{
             (NameId: sidStructure;
             NameTex: nil;
             Probability: 0;
@@ -2282,6 +2155,7 @@
             PosSprite: sprWater;
             ejectX: 0;
             ejectY: 0),
+}
             
 // Land Gun
             (NameId: sidLandGun;
@@ -2359,76 +2233,6 @@
             ejectY: 0)
         );
 
-const
-    GearKindAmmoTypeMap : array [TGearType] of TAmmoType = (    
-(*          gtFlame *)   amNothing
-(*       gtHedgehog *) , amNothing
-(*           gtMine *) , amMine
-(*           gtCase *) , amNothing
-(*     gtExplosives *) , amNothing
-(*        gtGrenade *) , amGrenade
-(*          gtShell *) , amBazooka
-(*          gtGrave *) , amNothing
-(*            gtBee *) , amBee
-(*    gtShotgunShot *) , amShotgun
-(*     gtPickHammer *) , amPickHammer
-(*           gtRope *) , amRope
-(*     gtDEagleShot *) , amDEagle
-(*       gtDynamite *) , amDynamite
-(*    gtClusterBomb *) , amClusterBomb
-(*        gtCluster *) , amClusterBomb
-(*         gtShover *) , amBaseballBat  // Shover is only used for baseball bat right now
-(*      gtFirePunch *) , amFirePunch
-(*    gtATStartGame *) , amNothing
-(*   gtATFinishGame *) , amNothing
-(*      gtParachute *) , amParachute
-(*      gtAirAttack *) , amAirAttack
-(*        gtAirBomb *) , amAirAttack
-(*      gtBlowTorch *) , amBlowTorch
-(*         gtGirder *) , amGirder
-(*       gtTeleport *) , amTeleport
-(*       gtSwitcher *) , amSwitch
-(*         gtTarget *) , amNothing
-(*         gtMortar *) , amMortar
-(*           gtWhip *) , amWhip
-(*       gtKamikaze *) , amKamikaze
-(*           gtCake *) , amCake
-(*      gtSeduction *) , amSeduction
-(*     gtWatermelon *) , amWatermelon
-(*     gtMelonPiece *) , amWatermelon
-(*    gtHellishBomb *) , amHellishBomb
-(*        gtWaterUp *) , amNothing
-(*          gtDrill *) , amDrill
-(*        gtBallGun *) , amBallgun
-(*           gtBall *) , amBallgun
-(*        gtRCPlane *) , amRCPlane
-(*gtSniperRifleShot *) , amSniperRifle
-(*        gtJetpack *) , amJetpack
-(*        gtMolotov *) , amMolotov
-(*          gtBirdy *) , amBirdy
-(*            gtEgg *) , amBirdy
-(*         gtPortal *) , amPortalGun
-(*          gtPiano *) , amPiano
-(*        gtGasBomb *) , amGasBomb
-(*    gtSineGunShot *) , amSineGun
-(*   gtFlamethrower *) , amFlamethrower
-(*          gtSMine *) , amSMine
-(*    gtPoisonCloud *) , amNothing
-(*         gtHammer *) , amHammer
-(*      gtHammerHit *) , amHammer
-(*    gtResurrector *) , amResurrector
-(*    gtPoisonCloud *) , amNothing
-(*       gtSnowball *) , amSnowball
-(*          gtFlake *) , amNothing
-(*      gtStructure *) , amStructure  // TODO - This will undoubtedly change once there is more than one structure
-(*        gtLandGun *) , amLandGun
-(*         gtTardis *) , amTardis
-(*         gtIceGun *) , amIceGun
-(*        gtAddAmmo *) , amNothing
-(*  gtGenericFaller *) , amNothing
-(*          gtKnife *) , amKnife
-    );
-
 var
     Land: TCollisionArray;
     LandPixels: TLandArray;
@@ -2462,7 +2266,6 @@
     LocalTeam: LongInt;  // last non-bot, non-extdriven clan first team
     LocalAmmo: LongInt;  // last non-bot, non-extdriven clan's first team's ammo index, updated to next upcoming hog for per-hog-ammo
     CurMinAngle, CurMaxAngle: Longword;
-    NextClan: boolean;
 
     FollowGear: PGear;
     WindBarWidth: LongInt;
@@ -2473,13 +2276,9 @@
     WaterColor, DeepWaterColor: TSDL_Color;
     SkyColor, RQSkyColor, SDSkyColor: TSDL_Color;
     SkyOffset: LongInt;
-    HorizontOffset: LongInt;
 {$IFDEF COUNTTICKS}
     cntTicks: LongWord;
 {$ENDIF}
-    cOffsetY: LongInt;
-    AFRToggle: Boolean;
-    bAFRRight: Boolean;
 
 
     PauseTexture,
@@ -2488,9 +2287,6 @@
     cScaleFactor: GLfloat;
     SupportNPOTT: Boolean;
     Step: LongInt;
-    squaresize : LongInt;
-    numsquares : LongInt;
-    ProgrTex: PTexture;
     MissionIcons: PSDL_Surface;
     ropeIconTex: PTexture;
 
@@ -2502,24 +2298,12 @@
     defaultFrame, depthv: GLuint;
     texv: GLuint;
 
-    VisualGearLayers: array[0..6] of PVisualGear;
     lastVisualGearByUID: PVisualGear;
     vobFrameTicks, vobFramesCount, vobCount: Longword;
     vobVelocity, vobFallSpeed: LongInt;
     vobSDFrameTicks, vobSDFramesCount, vobSDCount: Longword;
     vobSDVelocity, vobSDFallSpeed: LongInt;
 
-    ControllerNumControllers: Integer;
-    ControllerEnabled: Integer;
-    ControllerNumAxes: array[0..5] of Integer;
-    //ControllerNumBalls: array[0..5] of Integer;
-    ControllerNumHats: array[0..5] of Integer;
-    ControllerNumButtons: array[0..5] of Integer;
-    ControllerAxes: array[0..5] of array[0..19] of Integer;
-    //ControllerBalls: array[0..5] of array[0..19] of array[0..1] of Integer;
-    ControllerHats: array[0..5] of array[0..19] of Byte;
-    ControllerButtons: array[0..5] of array[0..19] of Byte;
-
     DefaultBinds : TBinds;
 
     lastTurnChecksum : Longword;
@@ -2737,6 +2521,19 @@
     cMapName:= '';
 
     LuaTemplateNumber:= 0;
+
+    mobileRecord.getScreenDPI:= @getScreenDPI; //TODO: define external function.
+    {$IFDEF IPHONEOS}
+    mobileRecord.PerformRumble:= @AudioServicesPlaySystemSound;
+    mobileRecord.GameLoading:= @startLoadingIndicator;
+    mobileRecord.GameLoaded:= @stopLoadingIndicator;
+    mobileRecord.SaveLoadingEnded:= @saveFinishedSynching;
+    {$ELSE}
+    mobileRecord.PerformRumble:= nil;
+    mobileRecord.GameLoading:= nil;
+    mobileRecord.GameLoaded:= nil;
+    mobileRecord.SaveLoadingEnded:= nil;
+    {$ENDIF}
 end;
 
 procedure freeModule;
--- a/hedgewars/uVisualGears.pas	Fri Nov 30 18:19:52 2012 +0400
+++ b/hedgewars/uVisualGears.pas	Tue Dec 04 09:15:55 2012 +0400
@@ -53,10 +53,13 @@
 procedure KickFlakes(Radius, X, Y: LongInt);
 
 implementation
-uses uSound, uMobile, uVariables, uTextures, uRender, Math, uRenderUtils, uStore, uUtils;
+uses uSound, uVariables, uTextures, uRender, Math, uRenderUtils, uStore, uUtils;
 
-const cExplFrameTicks = 110;
+const 
+    cExplFrameTicks = 110;
+    cSmokeZ = 499;
 var VGCounter: LongWord;
+    VisualGearLayers: array[0..6] of PVisualGear;
 
 // For better maintainability the step handlers of visual gears are stored
 // in a separate file.
--- a/hedgewars/uWorld.pas	Fri Nov 30 18:19:52 2012 +0400
+++ b/hedgewars/uWorld.pas	Tue Dec 04 09:15:55 2012 +0400
@@ -60,7 +60,6 @@
     , uCaptions
     , uCursor
     , uCommands
-    , uMobile
 {$IFDEF USE_VIDEO_RECORDING}    
     , uVideoRec
 {$ENDIF}    
@@ -84,6 +83,10 @@
     isFirstFrame: boolean;
     AMAnimType: LongInt;
     recTexture: PTexture;
+    AmmoMenuTex     : PTexture;
+    HorizontOffset: LongInt;
+    cOffsetY: LongInt;
+    AFRToggle: Boolean;
 
 const cStereo_Sky           = 0.0500;
       cStereo_Horizon       = 0.0250;
@@ -93,6 +96,28 @@
       cStereo_Water_near    = 0.0025;
       cStereo_Outside       = -0.0400;
 
+      AMAnimDuration = 200;
+      AMHidden    = 0;//AMState values
+      AMShowingUp = 1;
+      AMShowing   = 2;
+      AMHiding    = 3;
+
+      AMTypeMaskX     = $00000001;
+      AMTypeMaskY     = $00000002;
+      AMTypeMaskAlpha = $00000004;
+      AMTypeMaskSlide = $00000008;
+
+{$IFDEF MOBILE}
+      AMSlotSize = 48;
+      AMTITLE    = 30;
+{$ELSE}
+      AMSlotSize = 32;
+{$ENDIF}
+      AMSlotPadding = (AMSlotSize - 32) shr 1;
+
+      cSendCursorPosTime = 50;
+      cCursorEdgesDist   = 100;
+
 // helper functions to create the goal/game mode string
 function AddGoal(s: ansistring; gf: longword; si: TGoalStrId; i: LongInt): ansistring;
 var t: ansistring;
@@ -220,7 +245,7 @@
 {$IFDEF USE_TOUCH_INTERFACE}
 
 //positioning of the buttons
-buttonScale:= uMobile.getScreenDPI/cDefaultZoomLevel;
+buttonScale:= mobileRecord.getScreenDPI()/cDefaultZoomLevel;
 
 
 with JumpWidget do
@@ -961,7 +986,7 @@
         glClear(GL_COLOR_BUFFER_BIT);
         DrawWorldStereo(Lag, rmDefault)
         end
-{$IFNDEF S3D_DISABLED}
+{$IFDEF USE_S3D_RENDERING}
     else if (cStereoMode = smAFR) then
         begin
         AFRToggle:= not AFRToggle;
@@ -1074,7 +1099,7 @@
 
 procedure ChangeDepth(rm: TRenderMode; d: GLfloat);
 begin
-{$IFDEF S3D_DISABLED}
+{$IFNDEF USE_S3D_RENDERING}
     rm:= rm; d:= d; // avoid hint
     exit;
 {$ELSE}
@@ -1092,7 +1117,7 @@
  
 procedure ResetDepth(rm: TRenderMode);
 begin
-{$IFDEF S3D_DISABLED}
+{$IFNDEF USE_S3D_RENDERING}
     rm:= rm; // avoid hint
     exit;
 {$ELSE}
--- a/misc/libopenalbridge/CMakeLists.txt	Fri Nov 30 18:19:52 2012 +0400
+++ b/misc/libopenalbridge/CMakeLists.txt	Tue Dec 04 09:15:55 2012 +0400
@@ -30,7 +30,7 @@
 
 if(WIN32)
 if(MSVC)
-	SET_TARGET_PROPERTIES(openalbridge PROPERTIES LINK_FLAGS /DEF:openalbridge.def)
+	set_target_properties(openalbridge PROPERTIES LINK_FLAGS /DEF:openalbridge.def)
 endif(MSVC)
 #install it in the executable directory
 	install(TARGETS openalbridge DESTINATION bin)
--- a/misc/physfs/CMakeLists.txt	Fri Nov 30 18:19:52 2012 +0400
+++ b/misc/physfs/CMakeLists.txt	Tue Dec 04 09:15:55 2012 +0400
@@ -6,59 +6,59 @@
 #lines overridden by Hedgewars configuration
 #CMAKE_MINIMUM_REQUIRED(VERSION 2.4)
 #PROJECT(PhysicsFS)
-SET(PHYSFS_VERSION 2.1.0)
+set(PHYSFS_VERSION 2.1.0)
 
 # Increment this if/when we break backwards compatibility.
-SET(PHYSFS_SOVERSION 1)
+set(PHYSFS_SOVERSION 1)
 
 # I hate that they define "WIN32" ... we're about to move to Win64...I hope!
-IF(WIN32 AND NOT WINDOWS)
-    SET(WINDOWS TRUE)
-ENDIF(WIN32 AND NOT WINDOWS)
+if(WIN32 AND NOT WINDOWS)
+    set(WINDOWS true)
+endif(WIN32 AND NOT WINDOWS)
 
 # Bleh, let's do it for "APPLE" too.
-IF(APPLE AND NOT MACOSX)
-    SET(MACOSX TRUE)
-ENDIF(APPLE AND NOT MACOSX)
+if(APPLE AND NOT MACOSX)
+    set(MACOSX true)
+endif(APPLE AND NOT MACOSX)
 
 # For now, Haiku and BeOS are the same, as far as the build system cares.
-IF(HAIKU AND NOT BEOS)
-    SET(BEOS TRUE)
-ENDIF(HAIKU AND NOT BEOS)
+if(HAIKU AND NOT BEOS)
+    set(BEOS true)
+endif(HAIKU AND NOT BEOS)
 
-IF(CMAKE_SYSTEM_NAME STREQUAL "SunOS")
-    SET(SOLARIS TRUE)
-ENDIF(CMAKE_SYSTEM_NAME STREQUAL "SunOS")
+if(CMAKE_SYSTEM_NAME STREQUAL "SunOS")
+    set(SOLARIS true)
+endif(CMAKE_SYSTEM_NAME STREQUAL "SunOS")
 
-INCLUDE(CheckIncludeFile)
-INCLUDE(CheckLibraryExists)
-INCLUDE(CheckCSourceCompiles)
+include(CheckIncludeFile)
+include(CheckLibraryExists)
+include(CheckCSourceCompiles)
 
 include_directories(${CMAKE_CURRENT_SOURCE_DIR}/src)
 include_directories(${SDL_INCLUDE_DIR}) #hw
 include_directories(${LUA_INCLUDE_DIR}) #hw
 
-IF(MACOSX)
+if(MACOSX)
     # Fallback to older OS X on PowerPC to support wider range of systems...
-    IF(CMAKE_OSX_ARCHITECTURES MATCHES ppc)
-        ADD_DEFINITIONS(-DMAC_OS_X_VERSION_MIN_REQUIRED=1020)
-        SET(OTHER_LDFLAGS ${OTHER_LDFLAGS} " -mmacosx-version-min=10.2")
-    ENDIF(CMAKE_OSX_ARCHITECTURES MATCHES ppc)
+    if(CMAKE_OSX_ARCHITECTURES MATCHES ppc)
+        add_definitions(-DMAC_OS_X_VERSION_MIN_REQUIRED=1020)
+        set(OTHER_LDFLAGS ${OTHER_LDFLAGS} " -mmacosx-version-min=10.2")
+    endif(CMAKE_OSX_ARCHITECTURES MATCHES ppc)
 
     # Need these everywhere...
-    ADD_DEFINITIONS(-fno-common)
-    SET(OTHER_LDFLAGS ${OTHER_LDFLAGS} "-framework IOKit")
-ENDIF(MACOSX)
+    add_definitions(-fno-common)
+    set(OTHER_LDFLAGS ${OTHER_LDFLAGS} "-framework IOKit")
+endif(MACOSX)
 
 # Add some gcc-specific command lines.
-IF(CMAKE_COMPILER_IS_GNUCC)
+if(CMAKE_COMPILER_IS_GNUCC)
     # Always build with debug symbols...you can strip it later.
-    ADD_DEFINITIONS(-g -pipe -Werror -fsigned-char)
+    add_definitions(-g -pipe -Werror -fsigned-char)
 
     # Stupid BeOS generates warnings in the system headers.
-    IF(NOT BEOS)
-        ADD_DEFINITIONS(-Wall)
-    ENDIF(NOT BEOS)
+    if(NOT BEOS)
+        add_definitions(-Wall)
+    endif(NOT BEOS)
 
     CHECK_C_SOURCE_COMPILES("
         #if ((defined(__GNUC__)) && (__GNUC__ >= 4))
@@ -68,31 +68,31 @@
         #endif
     " PHYSFS_IS_GCC4)
 
-    IF(PHYSFS_IS_GCC4)
+    if(PHYSFS_IS_GCC4)
         # Not supported on several operating systems at this time.
-        IF(NOT SOLARIS AND NOT WINDOWS)
-            ADD_DEFINITIONS(-fvisibility=hidden)
-        ENDIF(NOT SOLARIS AND NOT WINDOWS)
-    ENDIF(PHYSFS_IS_GCC4)
+        if(NOT SOLARIS AND NOT WINDOWS)
+            add_definitions(-fvisibility=hidden)
+        endif(NOT SOLARIS AND NOT WINDOWS)
+    endif(PHYSFS_IS_GCC4)
 
     # Don't use -rpath.
-    SET(CMAKE_SKIP_RPATH ON CACHE BOOL "Skip RPATH" FORCE)
-ENDIF(CMAKE_COMPILER_IS_GNUCC)
+    set(CMAKE_SKIP_RPATH ON CACHE BOOL "Skip RPATH" FORCE)
+endif(CMAKE_COMPILER_IS_GNUCC)
 
-IF(CMAKE_C_COMPILER_ID STREQUAL "SunPro")
-    ADD_DEFINITIONS(-erroff=E_EMPTY_TRANSLATION_UNIT)
-    ADD_DEFINITIONS(-xldscope=hidden)
-ENDIF(CMAKE_C_COMPILER_ID STREQUAL "SunPro")
+if(CMAKE_C_COMPILER_ID STREQUAL "SunPro")
+    add_definitions(-erroff=E_EMPTY_TRANSLATION_UNIT)
+    add_definitions(-xldscope=hidden)
+endif(CMAKE_C_COMPILER_ID STREQUAL "SunPro")
 
-IF(MSVC)
+if(MSVC)
     # VS.NET 8.0 got really really anal about strcpy, etc, which even if we
     #  cleaned up our code, zlib, etc still use...so disable the warning.
-    ADD_DEFINITIONS(-D_CRT_SECURE_NO_WARNINGS=1)
-ENDIF(MSVC)
+    add_definitions(-D_CRT_SECURE_NO_WARNINGS=1)
+endif(MSVC)
 
 # Basic chunks of source code ...
 
-SET(LZMA_SRCS
+set(LZMA_SRCS
     src/lzma/C/7zCrc.c
     src/lzma/C/Archive/7z/7zBuffer.c
     src/lzma/C/Archive/7z/7zDecode.c
@@ -106,20 +106,20 @@
     src/lzma/C/Compress/Lzma/LzmaDecode.c
 )
 
-IF(BEOS)
+if(BEOS)
     # We add this explicitly, since we don't want CMake to think this
     #  is a C++ project unless we're on BeOS.
-    SET(PHYSFS_BEOS_SRCS src/platform_beos.cpp)
-    FIND_LIBRARY(BE_LIBRARY be)
-    FIND_LIBRARY(ROOT_LIBRARY root)
-    SET(OPTIONAL_LIBRARY_LIBS ${OPTIONAL_LIBRARY_LIBS} ${BE_LIBRARY} ${ROOT_LIBRARY})
-ENDIF(BEOS)
+    set(PHYSFS_BEOS_SRCS src/platform_beos.cpp)
+    find_library(BE_LIBRARY be)
+    find_library(ROOT_LIBRARY root)
+    set(OPTIONAL_LIBRARY_LIBS ${OPTIONAL_LIBRARY_LIBS} ${BE_LIBRARY} ${ROOT_LIBRARY})
+endif(BEOS)
 
 # Almost everything is "compiled" here, but things that don't apply to the
 #  build are #ifdef'd out. This is to make it easy to embed PhysicsFS into
 #  another project or bring up a new build system: just compile all the source
 #  code and #define the things you want.
-SET(PHYSFS_SRCS
+set(PHYSFS_SRCS
     src/physfs.c
     src/physfs_byteorder.c
     src/physfs_unicode.c
@@ -148,23 +148,23 @@
 
 # platform layers ...
 
-IF(UNIX)
-    IF(BEOS)
-        SET(PHYSFS_HAVE_CDROM_SUPPORT TRUE)
-        SET(PHYSFS_HAVE_THREAD_SUPPORT TRUE)
-        SET(HAVE_PTHREAD_H TRUE)
-    ELSE(BEOS)
+if(UNIX)
+    if(BEOS)
+        set(PHYSFS_HAVE_CDROM_SUPPORT true)
+        set(PHYSFS_HAVE_THREAD_SUPPORT true)
+        set(HAVE_PTHREAD_H true)
+    else(BEOS)
         CHECK_INCLUDE_FILE(sys/ucred.h HAVE_UCRED_H)
-        IF(HAVE_UCRED_H)
-            ADD_DEFINITIONS(-DPHYSFS_HAVE_SYS_UCRED_H=1)
-            SET(PHYSFS_HAVE_CDROM_SUPPORT TRUE)
-        ENDIF(HAVE_UCRED_H)
+        if(HAVE_UCRED_H)
+            add_definitions(-DPHYSFS_HAVE_SYS_UCRED_H=1)
+            set(PHYSFS_HAVE_CDROM_SUPPORT false)
+        endif(HAVE_UCRED_H)
 
         CHECK_INCLUDE_FILE(mntent.h HAVE_MNTENT_H)
-        IF(HAVE_MNTENT_H)
-            ADD_DEFINITIONS(-DPHYSFS_HAVE_MNTENT_H=1)
-            SET(PHYSFS_HAVE_CDROM_SUPPORT TRUE)
-        ENDIF(HAVE_MNTENT_H)
+        if(HAVE_MNTENT_H)
+            add_definitions(-DPHYSFS_HAVE_MNTENT_H=1)
+            set(PHYSFS_HAVE_CDROM_SUPPORT false)
+        endif(HAVE_MNTENT_H)
 
         # !!! FIXME: Solaris fails this, because mnttab.h implicitly
         # !!! FIXME:  depends on other system headers.  :(
@@ -175,150 +175,150 @@
             int main(int argc, char **argv) { return 0; }
         " HAVE_SYS_MNTTAB_H)
 
-        IF(HAVE_SYS_MNTTAB_H)
-            ADD_DEFINITIONS(-DPHYSFS_HAVE_SYS_MNTTAB_H=1)
-            SET(PHYSFS_HAVE_CDROM_SUPPORT TRUE)
-        ENDIF(HAVE_SYS_MNTTAB_H)
+        if(HAVE_SYS_MNTTAB_H)
+            add_definitions(-DPHYSFS_HAVE_SYS_MNTTAB_H=1)
+            set(PHYSFS_HAVE_CDROM_SUPPORT false)
+        endif(HAVE_SYS_MNTTAB_H)
 
         CHECK_INCLUDE_FILE(pthread.h HAVE_PTHREAD_H)
-        IF(HAVE_PTHREAD_H)
-            SET(PHYSFS_HAVE_THREAD_SUPPORT TRUE)
-        ENDIF(HAVE_PTHREAD_H)
-    ENDIF(BEOS)
-ENDIF(UNIX)
+        if(HAVE_PTHREAD_H)
+            set(PHYSFS_HAVE_THREAD_SUPPORT false)
+        endif(HAVE_PTHREAD_H)
+    endif(BEOS)
+endif(UNIX)
 
-IF(WINDOWS)
-    SET(PHYSFS_HAVE_CDROM_SUPPORT TRUE)
-    SET(PHYSFS_HAVE_THREAD_SUPPORT TRUE)
-ENDIF(WINDOWS)
+if(WINDOWS)
+    set(PHYSFS_HAVE_CDROM_SUPPORT true)
+    set(PHYSFS_HAVE_THREAD_SUPPORT true)
+endif(WINDOWS)
 
-IF(NOT PHYSFS_HAVE_CDROM_SUPPORT)
-    ADD_DEFINITIONS(-DPHYSFS_NO_CDROM_SUPPORT=1)
-    MESSAGE(WARNING " ***")
-    MESSAGE(WARNING " *** There is no CD-ROM support in this build!")
-    MESSAGE(WARNING " *** PhysicsFS will just pretend there are no discs.")
-    MESSAGE(WARNING " *** This may be fine, depending on how PhysicsFS is used,")
-    MESSAGE(WARNING " ***   but is this what you REALLY wanted?")
-    MESSAGE(WARNING " *** (Maybe fix CMakeLists.txt, or write a platform driver?)")
-    MESSAGE(WARNING " ***")
-ENDIF(NOT PHYSFS_HAVE_CDROM_SUPPORT)
+if(NOT PHYSFS_HAVE_CDROM_SUPPORT)
+    add_definitions(-DPHYSFS_NO_CDROM_SUPPORT=1)
+    message(WARNING " ***")
+    message(WARNING " *** There is no CD-ROM support in this build!")
+    message(WARNING " *** PhysicsFS will just pretend there are no discs.")
+    message(WARNING " *** This may be fine, depending on how PhysicsFS is used,")
+    message(WARNING " ***   but is this what you REALLY wanted?")
+    message(WARNING " *** (Maybe fix CMakeLists.txt, or write a platform driver?)")
+    message(WARNING " ***")
+endif(NOT PHYSFS_HAVE_CDROM_SUPPORT)
 
-IF(PHYSFS_HAVE_THREAD_SUPPORT)
-    ADD_DEFINITIONS(-D_REENTRANT -D_THREAD_SAFE)
-ELSE(PHYSFS_HAVE_THREAD_SUPPORT)
-    ADD_DEFINITIONS(-DPHYSFS_NO_THREAD_SUPPORT=1)
-    MESSAGE(WARNING " ***")
-    MESSAGE(WARNING " *** There is no thread support in this build!")
-    MESSAGE(WARNING " *** PhysicsFS will NOT be reentrant!")
-    MESSAGE(WARNING " *** This may be fine, depending on how PhysicsFS is used,")
-    MESSAGE(WARNING " ***   but is this what you REALLY wanted?")
-    MESSAGE(WARNING " *** (Maybe fix CMakeLists.txt, or write a platform driver?)")
-    MESSAGE(WARNING " ***")
-ENDIF(PHYSFS_HAVE_THREAD_SUPPORT)
+if(PHYSFS_HAVE_THREAD_SUPPORT)
+    add_definitions(-D_REENTRANT -D_THREAD_SAFE)
+else(PHYSFS_HAVE_THREAD_SUPPORT)
+    add_definitions(-DPHYSFS_NO_THREAD_SUPPORT=1)
+    message(WARNING " ***")
+    message(WARNING " *** There is no thread support in this build!")
+    message(WARNING " *** PhysicsFS will NOT be reentrant!")
+    message(WARNING " *** This may be fine, depending on how PhysicsFS is used,")
+    message(WARNING " ***   but is this what you REALLY wanted?")
+    message(WARNING " *** (Maybe fix CMakeLists.txt, or write a platform driver?)")
+    message(WARNING " ***")
+endif(PHYSFS_HAVE_THREAD_SUPPORT)
 
 
 # Archivers ...
 
-OPTION(PHYSFS_ARCHIVE_ZIP "Enable ZIP support" TRUE)
-IF(PHYSFS_ARCHIVE_ZIP)
-    ADD_DEFINITIONS(-DPHYSFS_SUPPORTS_ZIP=1)
-ENDIF(PHYSFS_ARCHIVE_ZIP)
+option(PHYSFS_ARCHIVE_ZIP "Enable ZIP support" true)
+if(PHYSFS_ARCHIVE_ZIP)
+    add_definitions(-DPHYSFS_SUPPORTS_ZIP=1)
+endif(PHYSFS_ARCHIVE_ZIP)
 
-OPTION(PHYSFS_ARCHIVE_7Z "Enable 7zip support" FALSE)
-IF(PHYSFS_ARCHIVE_7Z)
-    ADD_DEFINITIONS(-DPHYSFS_SUPPORTS_7Z=1)
+option(PHYSFS_ARCHIVE_7Z "Enable 7zip support" false)
+if(PHYSFS_ARCHIVE_7Z)
+    add_definitions(-DPHYSFS_SUPPORTS_7Z=1)
     # !!! FIXME: rename to 7z.c?
-    SET(PHYSFS_SRCS ${PHYSFS_SRCS} ${LZMA_SRCS})
-ENDIF(PHYSFS_ARCHIVE_7Z)
+    set(PHYSFS_SRCS ${PHYSFS_SRCS} ${LZMA_SRCS})
+endif(PHYSFS_ARCHIVE_7Z)
 
-OPTION(PHYSFS_ARCHIVE_GRP "Enable Build Engine GRP support" TRUE)
-IF(PHYSFS_ARCHIVE_GRP)
-    ADD_DEFINITIONS(-DPHYSFS_SUPPORTS_GRP=1)
-ENDIF(PHYSFS_ARCHIVE_GRP)
+option(PHYSFS_ARCHIVE_GRP "Enable Build Engine GRP support" true)
+if(PHYSFS_ARCHIVE_GRP)
+    add_definitions(-DPHYSFS_SUPPORTS_GRP=1)
+endif(PHYSFS_ARCHIVE_GRP)
 
-OPTION(PHYSFS_ARCHIVE_WAD "Enable Doom WAD support" TRUE)
-IF(PHYSFS_ARCHIVE_WAD)
-    ADD_DEFINITIONS(-DPHYSFS_SUPPORTS_WAD=1)
-ENDIF(PHYSFS_ARCHIVE_WAD)
+option(PHYSFS_ARCHIVE_WAD "Enable Doom WAD support" true)
+if(PHYSFS_ARCHIVE_WAD)
+    add_definitions(-DPHYSFS_SUPPORTS_WAD=1)
+endif(PHYSFS_ARCHIVE_WAD)
 
-OPTION(PHYSFS_ARCHIVE_HOG "Enable Descent I/II HOG support" TRUE)
-IF(PHYSFS_ARCHIVE_HOG)
-    ADD_DEFINITIONS(-DPHYSFS_SUPPORTS_HOG=1)
-ENDIF(PHYSFS_ARCHIVE_HOG)
+option(PHYSFS_ARCHIVE_HOG "Enable Descent I/II HOG support" true)
+if(PHYSFS_ARCHIVE_HOG)
+    add_definitions(-DPHYSFS_SUPPORTS_HOG=1)
+endif(PHYSFS_ARCHIVE_HOG)
 
-OPTION(PHYSFS_ARCHIVE_MVL "Enable Descent I/II MVL support" TRUE)
-IF(PHYSFS_ARCHIVE_MVL)
-    ADD_DEFINITIONS(-DPHYSFS_SUPPORTS_MVL=1)
-ENDIF(PHYSFS_ARCHIVE_MVL)
+option(PHYSFS_ARCHIVE_MVL "Enable Descent I/II MVL support" true)
+if(PHYSFS_ARCHIVE_MVL)
+    add_definitions(-DPHYSFS_SUPPORTS_MVL=1)
+endif(PHYSFS_ARCHIVE_MVL)
 
-OPTION(PHYSFS_ARCHIVE_QPAK "Enable Quake I/II QPAK support" TRUE)
-IF(PHYSFS_ARCHIVE_QPAK)
-    ADD_DEFINITIONS(-DPHYSFS_SUPPORTS_QPAK=1)
-ENDIF(PHYSFS_ARCHIVE_QPAK)
+option(PHYSFS_ARCHIVE_QPAK "Enable Quake I/II QPAK support" true)
+if(PHYSFS_ARCHIVE_QPAK)
+    add_definitions(-DPHYSFS_SUPPORTS_QPAK=1)
+endif(PHYSFS_ARCHIVE_QPAK)
 
-OPTION(PHYSFS_ARCHIVE_ISO9660 "Enable ISO9660 support" TRUE)
-IF(PHYSFS_ARCHIVE_ISO9660)
-    ADD_DEFINITIONS(-DPHYSFS_SUPPORTS_ISO9660=1)
-ENDIF(PHYSFS_ARCHIVE_ISO9660)
+option(PHYSFS_ARCHIVE_ISO9660 "Enable ISO9660 support" true)
+if(PHYSFS_ARCHIVE_ISO9660)
+    add_definitions(-DPHYSFS_SUPPORTS_ISO9660=1)
+endif(PHYSFS_ARCHIVE_ISO9660)
 
 #as needed by Hedgewars configuration
-IF(WINDOWS)
-    OPTION(PHYSFS_BUILD_STATIC "Build static library" FALSE)
-    OPTION(PHYSFS_BUILD_SHARED "Build shared library" TRUE)
-    SET(OTHER_LDFLAGS ${OTHER_LDFLAGS} ${SDL_LIBRARY})
-ELSE(WINDOWS)
-    OPTION(PHYSFS_BUILD_STATIC "Build static library" TRUE)
-    OPTION(PHYSFS_BUILD_SHARED "Build shared library" FALSE)
-ENDIF(WINDOWS)
+if(WINDOWS)
+    option(PHYSFS_BUILD_STATIC "Build static library" false)
+    option(PHYSFS_BUILD_SHARED "Build shared library" true)
+    set(OTHER_LDFLAGS ${OTHER_LDFLAGS} ${SDL_LIBRARY})
+else(WINDOWS)
+    option(PHYSFS_BUILD_STATIC "Build static library" true)
+    option(PHYSFS_BUILD_SHARED "Build shared library" false)
+endif(WINDOWS)
 
-IF(PHYSFS_BUILD_STATIC)
-    ADD_LIBRARY(physfs STATIC ${PHYSFS_SRCS})
-    SET_TARGET_PROPERTIES(physfs PROPERTIES OUTPUT_NAME "physfs")
-    SET(PHYSFS_LIB_TARGET physfs)
-    SET(PHYSFS_INSTALL_TARGETS ${PHYSFS_INSTALL_TARGETS} ";physfs")
-ENDIF(PHYSFS_BUILD_STATIC)
+if(PHYSFS_BUILD_STATIC)
+    add_library(physfs STATIC ${PHYSFS_SRCS})
+    set_target_properties(physfs PROPERTIES OUTPUT_NAME "physfs")
+    set(PHYSFS_LIB_TARGET physfs)
+    set(PHYSFS_INSTALL_TARGETS ${PHYSFS_INSTALL_TARGETS} ";physfs")
+endif(PHYSFS_BUILD_STATIC)
 
-IF(PHYSFS_BUILD_SHARED)
+if(PHYSFS_BUILD_SHARED)
     find_package(SDL REQUIRED)
-    ADD_LIBRARY(physfs SHARED ${PHYSFS_SRCS})
-    SET_TARGET_PROPERTIES(physfs PROPERTIES VERSION ${PHYSFS_VERSION})
-    SET_TARGET_PROPERTIES(physfs PROPERTIES SOVERSION ${PHYSFS_SOVERSION})
-    TARGET_LINK_LIBRARIES(physfs ${OPTIONAL_LIBRARY_LIBS} ${OTHER_LDFLAGS})
-    SET(PHYSFS_LIB_TARGET physfs)
-    SET(PHYSFS_INSTALL_TARGETS ${PHYSFS_INSTALL_TARGETS} ";physfs")
-    INSTALL(TARGETS ${PHYSFS_INSTALL_TARGETS}
+    add_library(physfs SHARED ${PHYSFS_SRCS})
+    set_target_properties(physfs PROPERTIES VERSION ${PHYSFS_VERSION})
+    set_target_properties(physfs PROPERTIES SOVERSION ${PHYSFS_SOVERSION})
+    target_link_libraries(physfs ${OPTIONAL_LIBRARY_LIBS} ${OTHER_LDFLAGS})
+    set(PHYSFS_LIB_TARGET physfs)
+    set(PHYSFS_INSTALL_TARGETS ${PHYSFS_INSTALL_TARGETS} ";physfs")
+    install(TARGETS ${PHYSFS_INSTALL_TARGETS}
             RUNTIME DESTINATION bin)
-ENDIF(PHYSFS_BUILD_SHARED)
+endif(PHYSFS_BUILD_SHARED)
 
-IF(NOT PHYSFS_BUILD_SHARED AND NOT PHYSFS_BUILD_STATIC)
-    MESSAGE(FATAL "Both shared and static libraries are disabled!")
-ENDIF(NOT PHYSFS_BUILD_SHARED AND NOT PHYSFS_BUILD_STATIC)
+if(NOT PHYSFS_BUILD_SHARED AND NOT PHYSFS_BUILD_STATIC)
+    message(FATAL "Both shared and static libraries are disabled!")
+endif(NOT PHYSFS_BUILD_SHARED AND NOT PHYSFS_BUILD_STATIC)
 
 # CMake FAQ says I need this...
-IF(PHYSFS_BUILD_SHARED AND PHYSFS_BUILD_STATIC)
-    SET_TARGET_PROPERTIES(physfs PROPERTIES CLEAN_DIRECT_OUTPUT 1)
-ENDIF(PHYSFS_BUILD_SHARED AND PHYSFS_BUILD_STATIC)
+if(PHYSFS_BUILD_SHARED AND PHYSFS_BUILD_STATIC)
+    set_target_properties(physfs PROPERTIES CLEAN_DIRECT_OUTPUT 1)
+endif(PHYSFS_BUILD_SHARED AND PHYSFS_BUILD_STATIC)
 
-OPTION(PHYSFS_BUILD_TEST "Build stdio test program." FALSE)
-MARK_AS_ADVANCED(PHYSFS_BUILD_TEST)
-IF(PHYSFS_BUILD_TEST)
-    FIND_PATH(READLINE_H readline/readline.h)
-    FIND_PATH(HISTORY_H readline/history.h)
-    IF(READLINE_H AND HISTORY_H)
-        FIND_LIBRARY(CURSES_LIBRARY NAMES curses ncurses)
-        SET(CMAKE_REQUIRED_LIBRARIES ${CURSES_LIBRARY})
-        FIND_LIBRARY(READLINE_LIBRARY readline)
-        IF(READLINE_LIBRARY)
-            SET(HAVE_SYSTEM_READLINE TRUE)
-            SET(TEST_PHYSFS_LIBS ${TEST_PHYSFS_LIBS} ${READLINE_LIBRARY} ${CURSES_LIBRARY})
-            INCLUDE_DIRECTORIES(${READLINE_H} ${HISTORY_H})
-            ADD_DEFINITIONS(-DPHYSFS_HAVE_READLINE=1)
-        ENDIF(READLINE_LIBRARY)
-    ENDIF(READLINE_H AND HISTORY_H)
-    ADD_EXECUTABLE(test_physfs test/test_physfs.c)
-    TARGET_LINK_LIBRARIES(test_physfs ${PHYSFS_LIB_TARGET} ${TEST_PHYSFS_LIBS} ${OTHER_LDFLAGS})
-    SET(PHYSFS_INSTALL_TARGETS ${PHYSFS_INSTALL_TARGETS} ";test_physfs")
-ENDIF(PHYSFS_BUILD_TEST)
+option(PHYSFS_BUILD_TEST "Build stdio test program." false)
+mark_as_advanced(PHYSFS_BUILD_TEST)
+if(PHYSFS_BUILD_TEST)
+    find_path(READLINE_H readline/readline.h)
+    find_path(HISTORY_H readline/history.h)
+    if(READLINE_H AND HISTORY_H)
+        find_library(CURSES_LIBRARY NAMES curses ncurses)
+        set(CMAKE_REQUIRED_LIBRARIES ${CURSES_LIBRARY})
+        find_library(READLINE_LIBRARY readline)
+        if(READLINE_LIBRARY)
+            set(HAVE_SYSTEM_READLINE true)
+            set(TEST_PHYSFS_LIBS ${TEST_PHYSFS_LIBS} ${READLINE_LIBRARY} ${CURSES_LIBRARY})
+            include_directories(${READLINE_H} ${HISTORY_H})
+            add_definitions(-DPHYSFS_HAVE_READLINE=1)
+        endif(READLINE_LIBRARY)
+    endif(READLINE_H AND HISTORY_H)
+    add_executable(test_physfs test/test_physfs.c)
+    target_link_libraries(test_physfs ${PHYSFS_LIB_TARGET} ${TEST_PHYSFS_LIBS} ${OTHER_LDFLAGS})
+    set(PHYSFS_INSTALL_TARGETS ${PHYSFS_INSTALL_TARGETS} ";test_physfs")
+endif(PHYSFS_BUILD_TEST)
 
 
 # Scripting language bindings...
@@ -326,38 +326,38 @@
 #CMake's SWIG support is basically useless.
 #FIND_PACKAGE(SWIG)
 
-OPTION(PHYSFS_BUILD_SWIG "Build ${_LANG} bindings." FALSE)
-MARK_AS_ADVANCED(PHYSFS_BUILD_SWIG)
+option(PHYSFS_BUILD_SWIG "Build ${_LANG} bindings." false)
+mark_as_advanced(PHYSFS_BUILD_SWIG)
 
-FIND_PROGRAM(SWIG swig DOC "Path to swig command line app: http://swig.org/")
-IF(NOT SWIG)
-    MESSAGE(STATUS "SWIG not found. You won't be able to build scripting language bindings.")
-ELSE(NOT SWIG)
-    MARK_AS_ADVANCED(SWIG)
-    IF(DEFINED CMAKE_BUILD_TYPE)
-        IF((NOT CMAKE_BUILD_TYPE STREQUAL "") AND (NOT CMAKE_BUILD_TYPE STREQUAL "Debug"))
-            IF(CMAKE_BUILD_TYPE STREQUAL "MinSizeRel")
-                SET(SWIG_OPT_CFLAGS "-small")
-            ELSE(CMAKE_BUILD_TYPE STREQUAL "MinSizeRel")
-                SET(SWIG_OPT_CFLAGS "-O")
-            ENDIF(CMAKE_BUILD_TYPE STREQUAL "MinSizeRel")
-        ENDIF((NOT CMAKE_BUILD_TYPE STREQUAL "") AND (NOT CMAKE_BUILD_TYPE STREQUAL "Debug"))
-    ENDIF(DEFINED CMAKE_BUILD_TYPE)
+find_program(SWIG swig DOC "Path to swig command line app: http://swig.org/")
+if(NOT SWIG)
+    message(STATUS "SWIG not found. You won't be able to build scripting language bindings.")
+else(NOT SWIG)
+    mark_as_advanced(SWIG)
+    if(DEFINED CMAKE_BUILD_TYPE)
+        if((NOT CMAKE_BUILD_TYPE STREQUAL "") AND (NOT CMAKE_BUILD_TYPE STREQUAL "Debug"))
+            if(CMAKE_BUILD_TYPE STREQUAL "MinSizeRel")
+                set(SWIG_OPT_CFLAGS "-small")
+            else(CMAKE_BUILD_TYPE STREQUAL "MinSizeRel")
+                set(SWIG_OPT_CFLAGS "-O")
+            endif(CMAKE_BUILD_TYPE STREQUAL "MinSizeRel")
+        endif((NOT CMAKE_BUILD_TYPE STREQUAL "") AND (NOT CMAKE_BUILD_TYPE STREQUAL "Debug"))
+    endif(DEFINED CMAKE_BUILD_TYPE)
 
-    SET(SWIG_OUTPUT_DIR "${CMAKE_CURRENT_BINARY_DIR}/physfs-swig-bindings")
+    set(SWIG_OUTPUT_DIR "${CMAKE_CURRENT_BINARY_DIR}/physfs-swig-bindings")
 
-    MACRO(CONFIGURE_SWIG_BINDING _LANG _INSTALLPATH _EXTRAOUTPUTS _EXTRACFLAGS _EXTRALDFLAGS)
-        STRING(TOUPPER "${_LANG}" _UPPERLANG)
-        STRING(TOLOWER "${_LANG}" _LOWERLANG)
-        SET(_TARGET "physfs-${_LOWERLANG}")
-        SET(_TARGETDIR "${SWIG_OUTPUT_DIR}/${_LOWERLANG}")
+    macro(CONFIGURE_SWIG_BINDING _LANG _INSTALLPATH _EXTRAOUTPUTS _EXTRACFLAGS _EXTRALDFLAGS)
+        string(TOUPPER "${_LANG}" _UPPERLANG)
+        string(TOLOWER "${_LANG}" _LOWERLANG)
+        set(_TARGET "physfs-${_LOWERLANG}")
+        set(_TARGETDIR "${SWIG_OUTPUT_DIR}/${_LOWERLANG}")
 
-        IF(NOT EXISTS "${_TARGETDIR}")
-            FILE(MAKE_DIRECTORY "${_TARGETDIR}")
-        ENDIF(NOT EXISTS "${_TARGETDIR}")
+        if(NOT EXISTS "${_TARGETDIR}")
+            file(MAKE_DIRECTORY "${_TARGETDIR}")
+        endif(NOT EXISTS "${_TARGETDIR}")
 
-        IF(PHYSFS_BUILD_${_UPPERLANG})
-            ADD_CUSTOM_COMMAND(
+        if(PHYSFS_BUILD_${_UPPERLANG})
+            add_custom_command(
                 OUTPUT "${_TARGETDIR}/${_TARGET}.c" ${_EXTRAOUTPUTS}
                 MAIN_DEPENDENCY "${CMAKE_CURRENT_SOURCE_DIR}/extras/physfs-swig.i"
                 COMMAND "${SWIG}"
@@ -365,66 +365,66 @@
                 COMMENT "Generating ${_LANG} bindings..."
             )
 
-            ADD_LIBRARY(${_TARGET} SHARED "${_TARGETDIR}/${_TARGET}.c")
-            TARGET_LINK_LIBRARIES(${_TARGET} ${PHYSFS_LIB_TARGET})
-            SET_TARGET_PROPERTIES(${_TARGET} PROPERTIES
+            add_library(${_TARGET} SHARED "${_TARGETDIR}/${_TARGET}.c")
+            target_link_libraries(${_TARGET} ${PHYSFS_LIB_TARGET})
+            set_target_properties(${_TARGET} PROPERTIES
                 COMPILE_FLAGS "${_EXTRACFLAGS}"
                 LINK_FLAGS "${_EXTRALDFLAGS}"
                 LIBRARY_OUTPUT_NAME "physfs"
                 LIBRARY_OUTPUT_DIRECTORY "${_TARGETDIR}"
                 CLEAN_DIRECT_OUTPUT 1
             )
-            INSTALL(TARGETS ${_TARGET} LIBRARY DESTINATION "${_INSTALLPATH}")
-            MESSAGE(STATUS "${_LANG} bindings configured!")
-        ELSE(PHYSFS_BUILD_${_UPPERLANG})
-            MESSAGE(STATUS "Couldn't figure out ${_LANG} configuration. Skipping ${_LANG} bindings.")
-        ENDIF(PHYSFS_BUILD_${_UPPERLANG})
-    ENDMACRO(CONFIGURE_SWIG_BINDING)
+            install(TARGETS ${_TARGET} LIBRARY DESTINATION "${_INSTALLPATH}")
+            message(STATUS "${_LANG} bindings configured!")
+        else(PHYSFS_BUILD_${_UPPERLANG})
+            message(STATUS "Couldn't figure out ${_LANG} configuration. Skipping ${_LANG} bindings.")
+        endif(PHYSFS_BUILD_${_UPPERLANG})
+    endmacro(CONFIGURE_SWIG_BINDING)
 
-    MACRO(ADD_SCRIPT_BINDING_OPTION _VAR _LANG _DEFVAL)
-        SET(BUILDSWIGVAL ${_DEFVAL})
-        IF(NOT PHYSFS_BUILD_SWIG)
-            SET(BUILDSWIGVAL FALSE)
-        ENDIF(NOT PHYSFS_BUILD_SWIG)
-        OPTION(${_VAR} "Build ${_LANG} bindings." ${BUILDSWIGVAL})
-        MARK_AS_ADVANCED(${_VAR})
-    ENDMACRO(ADD_SCRIPT_BINDING_OPTION)
+    macro(ADD_SCRIPT_BINDING_OPTION _VAR _LANG _DEFVAL)
+        set(BUILDSWIGVAL ${_DEFVAL})
+        if(NOT PHYSFS_BUILD_SWIG)
+            set(BUILDSWIGVAL false)
+        endif(NOT PHYSFS_BUILD_SWIG)
+        option(${_VAR} "Build ${_LANG} bindings." ${BUILDSWIGVAL})
+        mark_as_advanced(${_VAR})
+    endmacro(ADD_SCRIPT_BINDING_OPTION)
 
-    ADD_SCRIPT_BINDING_OPTION(PHYSFS_BUILD_PERL "Perl" TRUE)
-    ADD_SCRIPT_BINDING_OPTION(PHYSFS_BUILD_RUBY "Ruby" TRUE)
-ENDIF(NOT SWIG)
+    ADD_SCRIPT_BINDING_OPTION(PHYSFS_BUILD_PERL "Perl" true)
+    ADD_SCRIPT_BINDING_OPTION(PHYSFS_BUILD_RUBY "Ruby" true)
+endif(NOT SWIG)
 
-IF(PHYSFS_BUILD_PERL)
-    MESSAGE(STATUS "Configuring Perl bindings...")
-    FIND_PROGRAM(PERL perl DOC "Path to perl command line app: http://perl.org/")
-    IF(NOT PERL)
-        MESSAGE(STATUS "Perl not found. You won't be able to build perl bindings.")
-        SET(PHYSFS_BUILD_PERL FALSE)
-    ENDIF(NOT PERL)
-    MARK_AS_ADVANCED(PERL)
+if(PHYSFS_BUILD_PERL)
+    message(STATUS "Configuring Perl bindings...")
+    find_program(PERL perl DOC "Path to perl command line app: http://perl.org/")
+    if(NOT PERL)
+        message(STATUS "Perl not found. You won't be able to build perl bindings.")
+        set(PHYSFS_BUILD_PERL false)
+    endif(NOT PERL)
+    mark_as_advanced(PERL)
 
-    MACRO(GET_PERL_CONFIG _KEY _VALUE)
-        IF(PHYSFS_BUILD_PERL)
-            MESSAGE(STATUS "Figuring out perl config value '${_KEY}' ...")
-            EXECUTE_PROCESS(
+    macro(GET_PERL_CONFIG _KEY _VALUE)
+        if(PHYSFS_BUILD_PERL)
+            message(STATUS "Figuring out perl config value '${_KEY}' ...")
+            execute_process(
                 COMMAND ${PERL} -w -e "use Config; print \$Config{${_KEY}};"
                 RESULT_VARIABLE GET_PERL_CONFIG_RC
                 OUTPUT_VARIABLE ${_VALUE}
             )
-            IF(NOT GET_PERL_CONFIG_RC EQUAL 0)
-                MESSAGE(STATUS "Perl executable ('${PERL}') reported failure: ${GET_PERL_CONFIG_RC}")
-                SET(PHYSFS_BUILD_PERL FALSE)
-            ENDIF(NOT GET_PERL_CONFIG_RC EQUAL 0)
-            IF(NOT ${_VALUE})
-                MESSAGE(STATUS "Perl executable ('${PERL}') didn't have a value for '${_KEY}'")
-                SET(PHYSFS_BUILD_PERL FALSE)
-            ENDIF(NOT ${_VALUE})
+            if(NOT GET_PERL_CONFIG_RC EQUAL 0)
+                message(STATUS "Perl executable ('${PERL}') reported failure: ${GET_PERL_CONFIG_RC}")
+                set(PHYSFS_BUILD_PERL false)
+            endif(NOT GET_PERL_CONFIG_RC EQUAL 0)
+            if(NOT ${_VALUE})
+                message(STATUS "Perl executable ('${PERL}') didn't have a value for '${_KEY}'")
+                set(PHYSFS_BUILD_PERL false)
+            endif(NOT ${_VALUE})
 
-            IF(PHYSFS_BUILD_PERL)
-                MESSAGE(STATUS "Perl says: '${${_VALUE}}'.")
-            ENDIF(PHYSFS_BUILD_PERL)
-        ENDIF(PHYSFS_BUILD_PERL)
-    ENDMACRO(GET_PERL_CONFIG)
+            if(PHYSFS_BUILD_PERL)
+                message(STATUS "Perl says: '${${_VALUE}}'.")
+            endif(PHYSFS_BUILD_PERL)
+        endif(PHYSFS_BUILD_PERL)
+    endmacro(GET_PERL_CONFIG)
 
     # !!! FIXME: installsitearch might be the wrong location.
     GET_PERL_CONFIG("archlibexp" PERL_INCLUDE_PATH)
@@ -433,63 +433,63 @@
     GET_PERL_CONFIG("installsitearch" PERL_INSTALL_PATH)
 
     # !!! FIXME: this test for Mac OS X is wrong.
-    IF(MACOSX)
+    if(MACOSX)
         GET_PERL_CONFIG("libperl" PERL_LIBPERL)
-        SET(TMPLIBPERL "${PERL_LIBPERL}")
-        STRING(REGEX REPLACE "^lib" "" TMPLIBPERL "${TMPLIBPERL}")
-        STRING(REGEX REPLACE "\\.so$" "" TMPLIBPERL "${TMPLIBPERL}")
-        STRING(REGEX REPLACE "\\.dylib$" "" TMPLIBPERL "${TMPLIBPERL}")
-        STRING(REGEX REPLACE "\\.dll$" "" TMPLIBPERL "${TMPLIBPERL}")
-        IF(NOT "${TMPLIBPERL}" STREQUAL "${PERL_LIBPERL}")
-            MESSAGE(STATUS "Stripped '${PERL_LIBPERL}' down to '${TMPLIBPERL}'.")
-            SET(PERL_LIBPERL "${TMPLIBPERL}")
-        ENDIF(NOT "${TMPLIBPERL}" STREQUAL "${PERL_LIBPERL}")
-        SET(PERL_LIBPERL "-l${PERL_LIBPERL}")
-    ENDIF(MACOSX)
+        set(TMPLIBPERL "${PERL_LIBPERL}")
+        string(REGEX REPLACE "^lib" "" TMPLIBPERL "${TMPLIBPERL}")
+        string(REGEX REPLACE "\\.so$" "" TMPLIBPERL "${TMPLIBPERL}")
+        string(REGEX REPLACE "\\.dylib$" "" TMPLIBPERL "${TMPLIBPERL}")
+        string(REGEX REPLACE "\\.dll$" "" TMPLIBPERL "${TMPLIBPERL}")
+        if(NOT "${TMPLIBPERL}" STREQUAL "${PERL_LIBPERL}")
+            message(STATUS "Stripped '${PERL_LIBPERL}' down to '${TMPLIBPERL}'.")
+            set(PERL_LIBPERL "${TMPLIBPERL}")
+        endif(NOT "${TMPLIBPERL}" STREQUAL "${PERL_LIBPERL}")
+        set(PERL_LIBPERL "-l${PERL_LIBPERL}")
+    endif(MACOSX)
 
     CONFIGURE_SWIG_BINDING(Perl "${PERL_INSTALL_PATH}" "${SWIG_OUTPUT_DIR}/perl/physfs.pm" "\"-I${PERL_INCLUDE_PATH}/CORE\" ${PERL_CCFLAGS} -w" "\"-L${PERL_INCLUDE_PATH}/CORE\" ${PERL_LIBPERL} ${PERL_LDFLAGS}")
-    INSTALL(FILES "${SWIG_OUTPUT_DIR}/perl/physfs.pm" DESTINATION "${PERL_INSTALL_PATH}")
-    INSTALL(
+    install(FILES "${SWIG_OUTPUT_DIR}/perl/physfs.pm" DESTINATION "${PERL_INSTALL_PATH}")
+    install(
         FILES test/test_physfs.pl
         DESTINATION bin
         PERMISSIONS OWNER_READ OWNER_WRITE OWNER_EXECUTE
                     GROUP_READ GROUP_EXECUTE WORLD_READ WORLD_EXECUTE
     )
-ENDIF(PHYSFS_BUILD_PERL)
+endif(PHYSFS_BUILD_PERL)
 
 # !!! FIXME: lots of cut-and-paste from perl bindings.
-IF(PHYSFS_BUILD_RUBY)
-    MESSAGE(STATUS "Configuring Ruby bindings...")
-    FIND_PROGRAM(RUBY ruby DOC "Path to ruby command line app: http://ruby-lang.org/")
-    IF(NOT RUBY)
-        MESSAGE(STATUS "Ruby not found. You won't be able to build ruby bindings.")
-        SET(PHYSFS_BUILD_RUBY FALSE)
-    ENDIF(NOT RUBY)
-    MARK_AS_ADVANCED(RUBY)
+if(PHYSFS_BUILD_RUBY)
+    message(STATUS "Configuring Ruby bindings...")
+    find_program(RUBY ruby DOC "Path to ruby command line app: http://ruby-lang.org/")
+    if(NOT RUBY)
+        message(STATUS "Ruby not found. You won't be able to build ruby bindings.")
+        set(PHYSFS_BUILD_RUBY FALSE)
+    endif(NOT RUBY)
+    mark_as_advanced(RUBY)
 
-    MACRO(GET_RUBY_CONFIG _KEY _VALUE)
-        IF(PHYSFS_BUILD_RUBY)
-            MESSAGE(STATUS "Figuring out ruby config value '${_KEY}' ...")
-            EXECUTE_PROCESS(
+    macro(GET_RUBY_CONFIG _KEY _VALUE)
+        if(PHYSFS_BUILD_RUBY)
+            message(STATUS "Figuring out ruby config value '${_KEY}' ...")
+            execute_process(
                 COMMAND ${RUBY} -e "require 'rbconfig'; puts RbConfig::CONFIG['${_KEY}'];"
                 RESULT_VARIABLE GET_RUBY_CONFIG_RC
                 OUTPUT_VARIABLE ${_VALUE}
                 OUTPUT_STRIP_TRAILING_WHITESPACE
             )
-            IF(NOT GET_RUBY_CONFIG_RC EQUAL 0)
-                MESSAGE(STATUS "Ruby executable ('${RUBY}') reported failure: ${GET_RUBY_CONFIG_RC}")
-                SET(PHYSFS_BUILD_RUBY FALSE)
-            ENDIF(NOT GET_RUBY_CONFIG_RC EQUAL 0)
-            IF(NOT ${_VALUE})
-                MESSAGE(STATUS "Ruby executable ('${RUBY}') didn't have a value for '${_KEY}'")
-                SET(PHYSFS_BUILD_RUBY FALSE)
-            ENDIF(NOT ${_VALUE})
+            if(NOT GET_RUBY_CONFIG_RC EQUAL 0)
+                message(STATUS "Ruby executable ('${RUBY}') reported failure: ${GET_RUBY_CONFIG_RC}")
+                set(PHYSFS_BUILD_RUBY FALSE)
+            endif(NOT GET_RUBY_CONFIG_RC EQUAL 0)
+            if(NOT ${_VALUE})
+                message(STATUS "Ruby executable ('${RUBY}') didn't have a value for '${_KEY}'")
+                set(PHYSFS_BUILD_RUBY FALSE)
+            endif(NOT ${_VALUE})
 
-            IF(PHYSFS_BUILD_RUBY)
-                MESSAGE(STATUS "Ruby says: '${${_VALUE}}'.")
-            ENDIF(PHYSFS_BUILD_RUBY)
-        ENDIF(PHYSFS_BUILD_RUBY)
-    ENDMACRO(GET_RUBY_CONFIG)
+            if(PHYSFS_BUILD_RUBY)
+                message(STATUS "Ruby says: '${${_VALUE}}'.")
+            endif(PHYSFS_BUILD_RUBY)
+        endif(PHYSFS_BUILD_RUBY)
+    endmacro(GET_RUBY_CONFIG)
 
     GET_RUBY_CONFIG("archdir" RUBY_INCLUDE_PATH)
     GET_RUBY_CONFIG("CFLAGS" RUBY_CCFLAGS)
@@ -499,14 +499,14 @@
     GET_RUBY_CONFIG("libdir" RUBY_LIBDIR)
 
     CONFIGURE_SWIG_BINDING(Ruby "${RUBY_INSTALL_PATH}" "" "\"-I${RUBY_INCLUDE_PATH}\" ${RUBY_CCFLAGS} -w" "\"-L${RUBY_LIBDIR}\" ${RUBY_LIBRUBY} ${RUBY_LDFLAGS}")
-    SET_TARGET_PROPERTIES(physfs-ruby PROPERTIES PREFIX "")
-    INSTALL(
+    set_target_properties(physfs-ruby PROPERTIES PREFIX "")
+    install(
         FILES test/test_physfs.rb
         DESTINATION bin
         PERMISSIONS OWNER_READ OWNER_WRITE OWNER_EXECUTE
                     GROUP_READ GROUP_EXECUTE WORLD_READ WORLD_EXECUTE
     )
-ENDIF(PHYSFS_BUILD_RUBY)
+endif(PHYSFS_BUILD_RUBY)
 
 
 #INSTALL(TARGETS ${PHYSFS_INSTALL_TARGETS}
@@ -515,9 +515,9 @@
 #        ARCHIVE DESTINATION lib${LIB_SUFFIX})
 #INSTALL(FILES src/physfs.h DESTINATION include)
 
-IF(UNIX)
-    SET(PHYSFS_TARBALL "${CMAKE_CURRENT_SOURCE_DIR}/../physfs-${PHYSFS_VERSION}.tar.gz")
-    ADD_CUSTOM_TARGET(
+if(UNIX)
+    set(PHYSFS_TARBALL "${CMAKE_CURRENT_SOURCE_DIR}/../physfs-${PHYSFS_VERSION}.tar.gz")
+    add_custom_target(
         dist
         hg archive -t tgz "${PHYSFS_TARBALL}"
         WORKING_DIRECTORY "${CMAKE_CURRENT_SOURCE_DIR}"
@@ -529,17 +529,17 @@
 #        WORKING_DIRECTORY "${CMAKE_CURRENT_BINARY_DIR}"
 #        COMMENT "Uninstall the project..."
 #    )
-ENDIF(UNIX)
+endif(UNIX)
 
-MACRO(MESSAGE_BOOL_OPTION _NAME _VALUE)
-    IF(${_VALUE})
-        MESSAGE(STATUS "  ${_NAME}: enabled")
-    ELSE(${_VALUE})
-        MESSAGE(STATUS "  ${_NAME}: disabled")
-    ENDIF(${_VALUE})
-ENDMACRO(MESSAGE_BOOL_OPTION)
+macro(MESSAGE_BOOL_OPTION _NAME _VALUE)
+    if(${_VALUE})
+        message(STATUS "  ${_NAME}: enabled")
+    else(${_VALUE})
+        message(STATUS "  ${_NAME}: disabled")
+    endif(${_VALUE})
+endmacro(MESSAGE_BOOL_OPTION)
 
-MESSAGE(STATUS "PhysicsFS will build with the following options:")
+message(STATUS "PhysicsFS will build with the following options:")
 MESSAGE_BOOL_OPTION("ZIP support" PHYSFS_ARCHIVE_ZIP)
 MESSAGE_BOOL_OPTION("7zip support" PHYSFS_ARCHIVE_7Z)
 MESSAGE_BOOL_OPTION("GRP support" PHYSFS_ARCHIVE_GRP)
@@ -554,9 +554,9 @@
 MESSAGE_BOOL_OPTION("Build Perl bindings" PHYSFS_BUILD_PERL)
 MESSAGE_BOOL_OPTION("Build Ruby bindings" PHYSFS_BUILD_RUBY)
 MESSAGE_BOOL_OPTION("Build stdio test program" PHYSFS_BUILD_TEST)
-IF(PHYSFS_BUILD_TEST)
+if(PHYSFS_BUILD_TEST)
     MESSAGE_BOOL_OPTION("  Use readline in test program" HAVE_SYSTEM_READLINE)
-ENDIF(PHYSFS_BUILD_TEST)
+endif(PHYSFS_BUILD_TEST)
 
 # end of CMakeLists.txt ...
 
--- a/project_files/Android-build/CMakeLists.txt	Fri Nov 30 18:19:52 2012 +0400
+++ b/project_files/Android-build/CMakeLists.txt	Tue Dec 04 09:15:55 2012 +0400
@@ -18,7 +18,7 @@
 
 find_program(ANT ant DOC "Path to the java package creator: ant")
 if(NOT EXISTS ${ANT})
-    MESSAGE(FATAL_ERROR "Couldn't detect the Ant build tool")
+    message(FATAL_ERROR "Couldn't detect the Ant build tool")
 endif()
 
 if(NOT ANDROID_NDK)
@@ -26,9 +26,9 @@
 endif()
 
 if(IS_DIRECTORY "${ANDROID_NDK}")
-    MESSAGE(STATUS "Detected the android NDK directory at: " ${ANDROID_NDK}) 
+    message(STATUS "Detected the android NDK directory at: " ${ANDROID_NDK}) 
 else ()
-    MESSAGE(FATAL_ERROR "Couldn't detect the Android NDK directory")
+    message(FATAL_ERROR "Couldn't detect the Android NDK directory")
 endif()
 
 if(NOT ANDROID_NDK_TOOLCHAINDIR)
@@ -39,9 +39,9 @@
 endif()
 
 if(IS_DIRECTORY "${ANDROID_NDK_TOOLCHAINDIR}")
-    MESSAGE(STATUS "Detected the Android NDK toolchain at: ${ANDROID_NDK_TOOLCHAINDIR}") 
+    message(STATUS "Detected the Android NDK toolchain at: ${ANDROID_NDK_TOOLCHAINDIR}") 
 else ()
-    MESSAGE(FATAL_ERROR "Couldn't detect the Android NDK toolchain directory: ${ANDROID_NDK_TOOLCHAINDIR}")
+    message(FATAL_ERROR "Couldn't detect the Android NDK toolchain directory: ${ANDROID_NDK_TOOLCHAINDIR}")
 endif()
 
 if(NOT ANDROID_SDK)#Check if its defined at the cmdline
@@ -52,9 +52,9 @@
 endif()
 
 if( IS_DIRECTORY "${ANDROID_SDK}")
-    MESSAGE(STATUS "Detected the android SDK directory at: " ${ANDROID_SDK}) 
+    message(STATUS "Detected the android SDK directory at: " ${ANDROID_SDK}) 
 else ()
-    MESSAGE(FATAL_ERROR "Couldn't detect the Android SDK directory")
+    message(FATAL_ERROR "Couldn't detect the Android SDK directory")
 endif()
 
 if( NOT FPC_DIR)
@@ -66,9 +66,9 @@
 endif()
 
 if( IS_DIRECTORY "${FPC_DIR}")
-    MESSAGE(STATUS "Detected the FreePascal directory at: " "${FPC_DIR}") 
+    message(STATUS "Detected the FreePascal directory at: " "${FPC_DIR}") 
 else ()
-    MESSAGE(FATAL_ERROR "Couldn't detect the FreePascal directory")
+    message(FATAL_ERROR "Couldn't detect the FreePascal directory")
 endif()
 
 set(SDL_DIR /home/richard/Downloads/android-project)
@@ -77,7 +77,7 @@
 set(ANDROID_SDK_API_LVL 16)
 set(ANDROID_NDK_API_LVL 5)
 
-MESSAGE(STATUS "Creating Makefile.android...")
+message(STATUS "Creating Makefile.android...")
 
 configure_file(Templates/Makefile.android .)
 
@@ -89,9 +89,9 @@
                  "--target android-${ANDROID_SDK_API_LVL}"
                  OUTPUT_VARIABLE androidoutput
                 )
-    MESSAGE(STATUS "Updating android project config...\n" ${androidoutput})
+    message(STATUS "Updating android project config...\n" ${androidoutput})
 else()
-    MESSAGE(FATAL_ERROR "Couldn't find the android executable in ${ANDROID_SDK}/platform-tools or ${ANDROID_SDK}/tools.")
+    message(FATAL_ERROR "Couldn't find the android executable in ${ANDROID_SDK}/platform-tools or ${ANDROID_SDK}/tools.")
 endif()
 
 exec_program(${HGCOMMAND}
--- a/project_files/HedgewarsMobile/Hedgewars.xcodeproj/project.pbxproj	Fri Nov 30 18:19:52 2012 +0400
+++ b/project_files/HedgewarsMobile/Hedgewars.xcodeproj/project.pbxproj	Tue Dec 04 09:15:55 2012 +0400
@@ -261,70 +261,70 @@
 			isa = PBXContainerItemProxy;
 			containerPortal = 619599BA1364E65900B429B6 /* Freetype.xcodeproj */;
 			proxyType = 1;
-			remoteGlobalIDString = D2AAC07D0554694100DB518D /* libFreetype */;
+			remoteGlobalIDString = D2AAC07D0554694100DB518D;
 			remoteInfo = libFreetype;
 		};
 		610FB7E316613980002FB2A7 /* PBXContainerItemProxy */ = {
 			isa = PBXContainerItemProxy;
 			containerPortal = 61A19BF414D20D83004B1E6D /* SDL_net.xcodeproj */;
 			proxyType = 1;
-			remoteGlobalIDString = BE48FF6507AFA9A800BB41DA /* Static Library */;
+			remoteGlobalIDString = BE48FF6507AFA9A800BB41DA;
 			remoteInfo = "Static Library";
 		};
 		610FB7E516613980002FB2A7 /* PBXContainerItemProxy */ = {
 			isa = PBXContainerItemProxy;
 			containerPortal = 6195993F1364C82B00B429B6 /* Lua.xcodeproj */;
 			proxyType = 1;
-			remoteGlobalIDString = D2AAC07D0554694100DB518D /* libLua */;
+			remoteGlobalIDString = D2AAC07D0554694100DB518D;
 			remoteInfo = libLua;
 		};
 		610FB7E716613980002FB2A7 /* PBXContainerItemProxy */ = {
 			isa = PBXContainerItemProxy;
 			containerPortal = 61A19AE314D2010A004B1E6D /* SDL.xcodeproj */;
 			proxyType = 1;
-			remoteGlobalIDString = FD6526620DE8FCCB002AD96B /* libSDL */;
+			remoteGlobalIDString = FD6526620DE8FCCB002AD96B;
 			remoteInfo = libSDL;
 		};
 		610FB7E916613980002FB2A7 /* PBXContainerItemProxy */ = {
 			isa = PBXContainerItemProxy;
 			containerPortal = 61A19C1E14D20F51004B1E6D /* SDL_mixer.xcodeproj */;
 			proxyType = 1;
-			remoteGlobalIDString = BE1FA90707AF96B2004B6283 /* Static Library */;
+			remoteGlobalIDString = BE1FA90707AF96B2004B6283;
 			remoteInfo = "Static Library";
 		};
 		610FB7EB16613980002FB2A7 /* PBXContainerItemProxy */ = {
 			isa = PBXContainerItemProxy;
 			containerPortal = 61A19BC114D20CDA004B1E6D /* SDL_ttf.xcodeproj */;
 			proxyType = 1;
-			remoteGlobalIDString = BE48FD6807AFA17000BB41DA /* Static Library */;
+			remoteGlobalIDString = BE48FD6807AFA17000BB41DA;
 			remoteInfo = "Static Library";
 		};
 		610FB7ED16613980002FB2A7 /* PBXContainerItemProxy */ = {
 			isa = PBXContainerItemProxy;
 			containerPortal = 619598181364BCD200B429B6 /* Tremor.xcodeproj */;
 			proxyType = 1;
-			remoteGlobalIDString = D2AAC07D0554694100DB518D /* libTremor */;
+			remoteGlobalIDString = D2AAC07D0554694100DB518D;
 			remoteInfo = libTremor;
 		};
 		610FB7EF16613980002FB2A7 /* PBXContainerItemProxy */ = {
 			isa = PBXContainerItemProxy;
 			containerPortal = 61A19B6114D20B6C004B1E6D /* SDL_image.xcodeproj */;
 			proxyType = 1;
-			remoteGlobalIDString = BE1FA72F07AF4C45004B6283 /* libSDL_image */;
+			remoteGlobalIDString = BE1FA72F07AF4C45004B6283;
 			remoteInfo = libSDL_image;
 		};
 		610FB7F7166139A4002FB2A7 /* PBXContainerItemProxy */ = {
 			isa = PBXContainerItemProxy;
 			containerPortal = 610FB7F3166139A4002FB2A7 /* Physfs.xcodeproj */;
 			proxyType = 2;
-			remoteGlobalIDString = D2AAC07E0554694100DB518D /* libPhysfs.a */;
+			remoteGlobalIDString = D2AAC07E0554694100DB518D;
 			remoteInfo = Physfs;
 		};
 		610FB81B166139EC002FB2A7 /* PBXContainerItemProxy */ = {
 			isa = PBXContainerItemProxy;
 			containerPortal = 610FB7F3166139A4002FB2A7 /* Physfs.xcodeproj */;
 			proxyType = 1;
-			remoteGlobalIDString = D2AAC07D0554694100DB518D /* Physfs */;
+			remoteGlobalIDString = D2AAC07D0554694100DB518D;
 			remoteInfo = Physfs;
 		};
 		6162456614E6159C00CC97FB /* PBXContainerItemProxy */ = {
--- a/project_files/hedgewars.pro	Fri Nov 30 18:19:52 2012 +0400
+++ b/project_files/hedgewars.pro	Tue Dec 04 09:15:55 2012 +0400
@@ -109,7 +109,8 @@
     ../QTfrontend/model/playerslistmodel.h \
     ../QTfrontend/util/LibavInteraction.h \
     ../QTfrontend/util/FileEngine.h \
-    ../QTfrontend/util/frontlibpoller.h
+    ../QTfrontend/util/frontlibpoller.h \
+    ../QTfrontend/ui/dialog/bandialog.h
 
 
 SOURCES += ../QTfrontend/model/ammoSchemeModel.cpp \
@@ -201,7 +202,8 @@
     ../QTfrontend/model/playerslistmodel.cpp \
     ../QTfrontend/util/LibavInteraction.cpp \
     ../QTfrontend/util/FileEngine.cpp \
-    ../QTfrontend/util/frontlibpoller.cpp
+    ../QTfrontend/util/frontlibpoller.cpp \
+    ../QTfrontend/ui/dialog/bandialog.cpp
 
 
 TRANSLATIONS += ../share/hedgewars/Data/Locale/hedgewars_ar.ts \
--- a/share/CMakeLists.txt	Fri Nov 30 18:19:52 2012 +0400
+++ b/share/CMakeLists.txt	Tue Dec 04 09:15:55 2012 +0400
@@ -1,13 +1,13 @@
 add_subdirectory(hedgewars)
 
-IF(APPLE OR CROSSAPPLE)
+if(APPLE OR CROSSAPPLE)
     #needed for CFBundleVersion and CFBundleShortVersionString
         #should reuse the variables set in main CMakeLists.txt
-    IF(HGCOMMAND AND (EXISTS ${CMAKE_SOURCE_DIR}/.hg))
+    if(HGCOMMAND AND (EXISTS ${CMAKE_SOURCE_DIR}/.hg))
         set(HEDGEWARS_REVISION ${revision_number})
-    ELSE()
+    else()
         set(HEDGEWARS_REVISION ${HEDGEWARS_VERSION})
-    ENDIF()
+    endif()
 
     configure_file(${hedgewars_SOURCE_DIR}/share/Info.plist.in
                    ${CMAKE_CURRENT_BINARY_DIR}/Info.plist)
@@ -20,4 +20,4 @@
             DESTINATION ../Resources/)
     install(PROGRAMS "${hedgewars_SOURCE_DIR}/share/dsa_pub.pem"
             DESTINATION ../Resources/)
-ENDIF(APPLE OR CROSSAPPLE)
+endif(APPLE OR CROSSAPPLE)
Binary file share/hedgewars/Data/Graphics/AmmoMenu/Ammos.png has changed
Binary file share/hedgewars/Data/Graphics/AmmoMenu/Ammos@2x.png has changed
Binary file share/hedgewars/Data/Graphics/AmmoMenu/Ammos_bw.png has changed
Binary file share/hedgewars/Data/Graphics/AmmoMenu/Ammos_bw@2x.png has changed
Binary file share/hedgewars/Data/Graphics/AmmoMenu/BorderHorizontal.png has changed
Binary file share/hedgewars/Data/Graphics/AmmoMenu/BorderVertical.png has changed
--- a/share/hedgewars/Data/Graphics/AmmoMenu/CMakeLists.txt	Fri Nov 30 18:19:52 2012 +0400
+++ b/share/hedgewars/Data/Graphics/AmmoMenu/CMakeLists.txt	Tue Dec 04 09:15:55 2012 +0400
@@ -1,5 +1,4 @@
 file(GLOB AmmoMenuSprites *.png)
-list(REMOVE_ITEM AmmoMenuSprites *@2x.png Border*.png)
 
 install(FILES
 	${AmmoMenuSprites}
--- a/share/hedgewars/Data/Locale/hedgewars_sk.ts	Fri Nov 30 18:19:52 2012 +0400
+++ b/share/hedgewars/Data/Locale/hedgewars_sk.ts	Tue Dec 04 09:15:55 2012 +0400
@@ -5,7 +5,7 @@
     <name>AbstractPage</name>
     <message>
         <source>Go back</source>
-        <translation type="unfinished"></translation>
+        <translation>Krok späť</translation>
     </message>
 </context>
 <context>
@@ -57,7 +57,7 @@
     <name>HWAskQuitDialog</name>
     <message>
         <source>Do you really want to quit?</source>
-        <translation type="unfinished"></translation>
+        <translation>Naozaj chcete odísť?</translation>
     </message>
 </context>
 <context>
@@ -166,7 +166,7 @@
     <message>
         <source>Someone already uses your nickname %1 on the server.
 Please pick another nickname:</source>
-        <translation type="unfinished"></translation>
+        <translation>Prezývku %1 už niekto na serveri používa. Prosím, zvoľte si inú prezývku:</translation>
     </message>
 </context>
 <context>
@@ -314,29 +314,29 @@
     </message>
     <message>
         <source>Remote host has closed connection</source>
-        <translation type="unfinished"></translation>
+        <translation>Vzdialený hostiteľ ukončiť spojenie</translation>
     </message>
     <message>
         <source>The server is too old. Disconnecting now.</source>
-        <translation type="unfinished"></translation>
+        <translation>Server je príliš zastaraný. Odpojím sa.</translation>
     </message>
 </context>
 <context>
     <name>HWPasswordDialog</name>
     <message>
         <source>Password</source>
-        <translation type="unfinished">Heslo</translation>
+        <translation>Heslo</translation>
     </message>
 </context>
 <context>
     <name>HWUploadVideoDialog</name>
     <message>
         <source>Upload video</source>
-        <translation type="unfinished"></translation>
+        <translation>Upload videa</translation>
     </message>
     <message>
         <source>Upload</source>
-        <translation type="unfinished"></translation>
+        <translation>Upload</translation>
     </message>
 </context>
 <context>
@@ -351,19 +351,19 @@
     <message>
         <source>Duration: %1m %2s
 </source>
-        <translation type="unfinished"></translation>
+        <translation>Trvanie: %1m %2s</translation>
     </message>
     <message>
         <source>Video: %1x%2, </source>
-        <translation type="unfinished"></translation>
+        <translation>Video: %1x%2, </translation>
     </message>
     <message>
         <source>%1 fps, </source>
-        <translation type="unfinished"></translation>
+        <translation>%1 fps, </translation>
     </message>
     <message>
         <source>Audio: </source>
-        <translation type="unfinished"></translation>
+        <translation>Zvuk: </translation>
     </message>
 </context>
 <context>
@@ -440,7 +440,7 @@
     </message>
     <message>
         <source>Eraser</source>
-        <translation type="unfinished"></translation>
+        <translation>Guma</translation>
     </message>
 </context>
 <context>
@@ -532,7 +532,7 @@
     <name>PageInfo</name>
     <message>
         <source>Open the snapshot folder</source>
-        <translation type="unfinished"></translation>
+        <translation>Otvoriť priečinok so snímkami</translation>
     </message>
 </context>
 <context>
@@ -788,43 +788,43 @@
     </message>
     <message>
         <source>Local Game</source>
-        <translation type="unfinished"></translation>
+        <translation>Miestna hra</translation>
     </message>
     <message>
         <source>Play a game on a single computer</source>
-        <translation type="unfinished"></translation>
+        <translation>Hrať hru na tomto počítači</translation>
     </message>
     <message>
         <source>Network Game</source>
-        <translation type="unfinished"></translation>
+        <translation>Hra na sieti</translation>
     </message>
     <message>
         <source>Play a game across a network</source>
-        <translation type="unfinished"></translation>
+        <translation>Hra cez sieť</translation>
     </message>
     <message>
         <source>Read about who is behind the Hedgewars Project</source>
-        <translation type="unfinished"></translation>
+        <translation>Prečítajte si, kto stojí za projektom Hedgewars</translation>
     </message>
     <message>
         <source>Leave a feedback here reporting issues, suggesting features or just saying how you like Hedgewars</source>
-        <translation type="unfinished"></translation>
+        <translation>Dajte nám späťnú väzbu formou hlásenia chýb, navrhovania nových vlastností alebo nám len napíšte, čo sa vám na Hedgewars páči</translation>
     </message>
     <message>
         <source>Access the user created content downloadable from our website</source>
-        <translation type="unfinished"></translation>
+        <translation>Stiahnuť obsah vytvorený inými užívateľmi z našej stránky </translation>
     </message>
     <message>
         <source>Exit game</source>
-        <translation type="unfinished"></translation>
+        <translation>Ukončiť hru</translation>
     </message>
     <message>
         <source>Manage videos recorded from game</source>
-        <translation type="unfinished"></translation>
+        <translation>Spravovať videá nahrané počas hrania</translation>
     </message>
     <message>
         <source>Edit game preferences</source>
-        <translation type="unfinished"></translation>
+        <translation>Upraviť nastavenia hry</translation>
     </message>
 </context>
 <context>
@@ -857,11 +857,11 @@
     </message>
     <message>
         <source>Join hundreds of players online!</source>
-        <translation type="unfinished"></translation>
+        <translation>Pripojte sa ku stovkám hráčov online!</translation>
     </message>
     <message>
         <source>Join or host your own game server in a Local Area Network.</source>
-        <translation type="unfinished"></translation>
+        <translation>Pripojiť sa k existujúcej hre alebo vytvoriť vlastnú hru na miestnej sieti.</translation>
     </message>
 </context>
 <context>
@@ -908,47 +908,47 @@
     </message>
     <message>
         <source>General</source>
-        <translation type="unfinished">Všeobecné</translation>
+        <translation>Všeobecné</translation>
     </message>
     <message>
         <source>Advanced</source>
-        <translation type="unfinished">Pokročilé</translation>
+        <translation>Pokročilé</translation>
     </message>
     <message>
         <source>Reset to default colors</source>
-        <translation type="unfinished"></translation>
+        <translation>Nastaviť východzie farby</translation>
     </message>
     <message>
         <source>Proxy host</source>
-        <translation type="unfinished"></translation>
+        <translation>Hostiteľ proxy</translation>
     </message>
     <message>
         <source>Proxy port</source>
-        <translation type="unfinished"></translation>
+        <translation>Port proxy</translation>
     </message>
     <message>
         <source>Proxy login</source>
-        <translation type="unfinished"></translation>
+        <translation>Login pre proxy</translation>
     </message>
     <message>
         <source>Proxy password</source>
-        <translation type="unfinished"></translation>
+        <translation>Heslo pre proxy</translation>
     </message>
     <message>
         <source>No proxy</source>
-        <translation type="unfinished"></translation>
+        <translation>Bez proxy</translation>
     </message>
     <message>
         <source>Socks5 proxy</source>
-        <translation type="unfinished"></translation>
+        <translation>Socks5 proxy</translation>
     </message>
     <message>
         <source>HTTP proxy</source>
-        <translation type="unfinished"></translation>
+        <translation>HTTP proxy</translation>
     </message>
     <message>
         <source>System proxy settings</source>
-        <translation type="unfinished"></translation>
+        <translation>Systémové nastavenia proxy</translation>
     </message>
 </context>
 <context>
@@ -1151,47 +1151,47 @@
     <name>PageSinglePlayer</name>
     <message>
         <source>Simple Game</source>
-        <translation type="unfinished"></translation>
+        <translation>Jednoduchá hra</translation>
     </message>
     <message>
         <source>Play a quick game against the computer with random settings</source>
-        <translation type="unfinished"></translation>
+        <translation>Zahrajte si rýchlu hru proti počítaču s náhodnými nastaveniami</translation>
     </message>
     <message>
         <source>Multiplayer</source>
-        <translation type="unfinished"></translation>
+        <translation>Hra viacerých hráčov</translation>
     </message>
     <message>
         <source>Play a hotseat game against your friends, or AI teams</source>
-        <translation type="unfinished"></translation>
+        <translation>Zahrajte si hru za týmto počítačom proti kamarátom alebo počítačovým protivníkom</translation>
     </message>
     <message>
         <source>Campaign Mode</source>
-        <translation type="unfinished"></translation>
+        <translation>Režim kampane</translation>
     </message>
     <message>
         <source>Training Mode</source>
-        <translation type="unfinished"></translation>
+        <translation>Tréningový režim</translation>
     </message>
     <message>
         <source>Practice your skills in a range of training missions</source>
-        <translation type="unfinished"></translation>
+        <translation>Cibrite si svoje schopnosti v rade tréningových misií</translation>
     </message>
     <message>
         <source>Demos</source>
-        <translation type="unfinished"></translation>
+        <translation>Demá</translation>
     </message>
     <message>
         <source>Watch recorded demos</source>
-        <translation type="unfinished"></translation>
+        <translation>Prezerať nahrané demá</translation>
     </message>
     <message>
         <source>Load</source>
-        <translation type="unfinished">Načítať</translation>
+        <translation>Načítať</translation>
     </message>
     <message>
         <source>Load a previously saved game</source>
-        <translation type="unfinished"></translation>
+        <translation>Načítať uloženú hru</translation>
     </message>
 </context>
 <context>
@@ -1206,50 +1206,50 @@
     </message>
     <message>
         <source>Pick the mission or training to play</source>
-        <translation type="unfinished"></translation>
+        <translation>Vyberte si misiu alebo tréning</translation>
     </message>
     <message>
         <source>Start fighting</source>
-        <translation type="unfinished"></translation>
+        <translation>Začať boj</translation>
     </message>
 </context>
 <context>
     <name>PageVideos</name>
     <message>
         <source>Name</source>
-        <translation type="unfinished">Meno</translation>
+        <translation>Meno</translation>
     </message>
     <message>
         <source>Size</source>
-        <translation type="unfinished"></translation>
+        <translation>Veľkosť</translation>
     </message>
     <message numerus="yes">
         <source>%1 bytes</source>
-        <translation type="unfinished">
-            <numerusform></numerusform>
+        <translation>
+            <numerusform>%1 bajtov</numerusform>
             <numerusform></numerusform>
             <numerusform></numerusform>
         </translation>
     </message>
     <message>
         <source>(in progress...)</source>
-        <translation type="unfinished"></translation>
+        <translation>(prebieha...)</translation>
     </message>
     <message>
         <source>Date: </source>
-        <translation type="unfinished"></translation>
+        <translation>Dátum: </translation>
     </message>
     <message>
         <source>Size: </source>
-        <translation type="unfinished"></translation>
+        <translation>Veľkosť: </translation>
     </message>
     <message>
         <source>encoding</source>
-        <translation type="unfinished"></translation>
+        <translation>kódovanie</translation>
     </message>
     <message>
         <source>uploading</source>
-        <translation type="unfinished"></translation>
+        <translation>uploadujem</translation>
     </message>
 </context>
 <context>
@@ -1355,23 +1355,23 @@
     </message>
     <message>
         <source>Save password</source>
-        <translation type="unfinished"></translation>
+        <translation>Uložiť heslo</translation>
     </message>
     <message>
         <source>Save account name and password</source>
-        <translation type="unfinished"></translation>
+        <translation>Uložiť meno účtu a heslo</translation>
     </message>
     <message>
         <source>Video is private</source>
-        <translation type="unfinished"></translation>
+        <translation>Video je súkromné</translation>
     </message>
     <message>
         <source>Record audio</source>
-        <translation type="unfinished"></translation>
+        <translation>Nahrať audio</translation>
     </message>
     <message>
         <source>Use game resolution</source>
-        <translation type="unfinished"></translation>
+        <translation>Použiť rozlíšenie hry</translation>
     </message>
 </context>
 <context>
@@ -1537,27 +1537,27 @@
     </message>
     <message>
         <source>Custom colors</source>
-        <translation type="unfinished"></translation>
+        <translation>Vlastné farby</translation>
     </message>
     <message>
         <source>Miscellaneous</source>
-        <translation type="unfinished"></translation>
+        <translation>Rozličné</translation>
     </message>
     <message>
         <source>Video recording options</source>
-        <translation type="unfinished"></translation>
+        <translation>Voľby nahrávania videa</translation>
     </message>
     <message>
         <source>Videos</source>
-        <translation type="unfinished"></translation>
+        <translation>Videá</translation>
     </message>
     <message>
         <source>Description</source>
-        <translation type="unfinished"></translation>
+        <translation>Popis</translation>
     </message>
     <message>
         <source>Proxy settings</source>
-        <translation type="unfinished"></translation>
+        <translation>Nastavenia proxy</translation>
     </message>
 </context>
 <context>
@@ -1743,63 +1743,63 @@
         <source>There are videos that are currently being processed.
 Exiting now will abort them.
 Do you really want to quit?</source>
-        <translation type="unfinished"></translation>
+        <translation>Momentálne sa niektoré videá spracovávajú. Ukončením zrušíte spracovávanie. Naozaj chcete ukončiť program?</translation>
     </message>
     <message>
         <source>Please provide either the YouTube account name or the email address associated with the Google Account.</source>
-        <translation type="unfinished"></translation>
+        <translation>Prosím zadajte buď názov YouTube účtu alebo e-mailovú adresu prepojenú s Google účtom.</translation>
     </message>
     <message>
         <source>Account name (or email): </source>
-        <translation type="unfinished"></translation>
+        <translation>Názov účtu (alebo e-mail): </translation>
     </message>
     <message>
         <source>Password: </source>
-        <translation type="unfinished"></translation>
+        <translation>Heslo:</translation>
     </message>
     <message>
         <source>Video title: </source>
-        <translation type="unfinished"></translation>
+        <translation>Názov videa: </translation>
     </message>
     <message>
         <source>Video description: </source>
-        <translation type="unfinished"></translation>
+        <translation>Popis videa: </translation>
     </message>
     <message>
         <source>Tags (comma separated): </source>
-        <translation type="unfinished"></translation>
+        <translation>Značky (oddelené čiarkou): </translation>
     </message>
     <message>
         <source>Summary   </source>
-        <translation type="unfinished"></translation>
+        <translation>Sumár </translation>
     </message>
     <message>
         <source>Description</source>
-        <translation type="unfinished"></translation>
+        <translation>Popis</translation>
     </message>
     <message>
         <source>Nickname</source>
-        <translation type="unfinished">Prezývka</translation>
+        <translation>Prezývka</translation>
     </message>
     <message>
         <source>Format</source>
-        <translation type="unfinished"></translation>
+        <translation>Formát</translation>
     </message>
     <message>
         <source>Audio codec</source>
-        <translation type="unfinished"></translation>
+        <translation>Audio kodek</translation>
     </message>
     <message>
         <source>Video codec</source>
-        <translation type="unfinished"></translation>
+        <translation>Video kodek</translation>
     </message>
     <message>
         <source>Framerate</source>
-        <translation type="unfinished"></translation>
+        <translation>Snímkovanie</translation>
     </message>
     <message>
         <source>Bitrate (Kbps)</source>
-        <translation type="unfinished"></translation>
+        <translation>Bitový tok (Kbps)</translation>
     </message>
 </context>
 <context>
@@ -1814,7 +1814,7 @@
     </message>
     <message>
         <source>anonymous</source>
-        <translation type="unfinished"></translation>
+        <translation>anonymný</translation>
     </message>
 </context>
 <context>
@@ -1840,214 +1840,217 @@
     </message>
     <message>
         <source>Please fill out all fields</source>
-        <translation type="unfinished"></translation>
+        <translation>Prosím, vyplňte všetky polia</translation>
     </message>
     <message>
         <source>Error while authenticating at google.com:
 </source>
-        <translation type="unfinished"></translation>
+        <translation>Chyba pri autentizácii voči google.com:</translation>
     </message>
     <message>
         <source>Login or password is incorrect</source>
-        <translation type="unfinished"></translation>
+        <translation>Prihlasovacie meno alebo heslo je nesprávne</translation>
     </message>
     <message>
         <source>Error while sending metadata to youtube.com:
 </source>
-        <translation type="unfinished"></translation>
+        <translation>Chyba pri posielaní metadát na youtube.com:</translation>
     </message>
     <message>
         <source>Teams - Are you sure?</source>
-        <translation type="unfinished"></translation>
+        <translation>Tímy - Ste si istý?</translation>
     </message>
     <message>
         <source>Do you really want to delete the team &apos;%1&apos;?</source>
-        <translation type="unfinished"></translation>
+        <translation>Naozaj chcete vymazať tím &apos;%1&apos;?</translation>
     </message>
     <message>
         <source>Cannot delete default scheme &apos;%1&apos;!</source>
-        <translation type="unfinished"></translation>
+        <translation>Nemôžem vymazať východziu schému &apos;%1&apos;!</translation>
     </message>
     <message>
         <source>Please select a record from the list</source>
-        <translation type="unfinished"></translation>
+        <translation>Prosím, vyberte nahrávku zo zoznamu</translation>
     </message>
     <message>
         <source>Unable to start server</source>
-        <translation type="unfinished"></translation>
+        <translation>Nepodarilo sa spustiť server</translation>
     </message>
     <message>
         <source>Hedgewars - Error</source>
-        <translation type="unfinished"></translation>
+        <translation>Hedgewars - Chyba</translation>
     </message>
     <message>
         <source>Hedgewars - Success</source>
-        <translation type="unfinished"></translation>
+        <translation>Hedgewars - Úspech</translation>
     </message>
     <message>
         <source>All file associations have been set</source>
-        <translation type="unfinished"></translation>
+        <translation>Všeky súborové asociácie boli nastavené</translation>
     </message>
     <message>
         <source>Successfully posted the issue on hedgewars.googlecode.com</source>
-        <translation type="unfinished"></translation>
+        <translation>Popis problému bol úspešne odoslaný na hedgewars.google.com</translation>
     </message>
     <message>
         <source>Error during authentication at google.com</source>
-        <translation type="unfinished"></translation>
+        <translation>Chyba počas autentizácie voči google.com</translation>
     </message>
     <message>
         <source>Error reporting the issue, please try again later (or visit hedgewars.googlecode.com directly)</source>
-        <translation type="unfinished"></translation>
+        <translation>Chyba pri hlásení problému, skúste to prosím neskôr (alebo navštívte priamo hedgewars.googlecode.com)</translation>
     </message>
     <message>
         <source>Main - Error</source>
-        <translation type="unfinished"></translation>
+        <translation>Hlavné okno - Chyba</translation>
     </message>
     <message>
         <source>Cannot create directory %1</source>
-        <translation type="unfinished">Nepodarilo sa vytvoriť adresár %1</translation>
+        <translation>Nepodarilo sa vytvoriť adresár %1</translation>
     </message>
     <message>
         <source>Failed to open data directory:
 %1
 
 Please check your installation!</source>
-        <translation type="unfinished"></translation>
+        <translation>Chyba pri otváraní adresára s dátami:
+%1
+
+Skontrolujte, prosím, inštaláciu!</translation>
     </message>
     <message>
         <source>TCP - Error</source>
-        <translation type="unfinished"></translation>
+        <translation>TCP - Chyba</translation>
     </message>
     <message>
         <source>Unable to start the server: %1.</source>
-        <translation type="unfinished">Nie je možné spustiť server: %1.</translation>
+        <translation>Nepodarilo sa spustiť server: %1.</translation>
     </message>
     <message>
         <source>Unable to run engine at </source>
-        <translation type="unfinished"></translation>
+        <translation>Nepodarilo sa spustiť enginu na </translation>
     </message>
     <message>
         <source>Error code: %1</source>
-        <translation type="unfinished"></translation>
+        <translation>Kód chyby: %1</translation>
     </message>
     <message>
         <source>Video upload - Error</source>
-        <translation type="unfinished"></translation>
+        <translation>Upload videa - Chyba</translation>
     </message>
     <message>
         <source>Netgame - Error</source>
-        <translation type="unfinished"></translation>
+        <translation>Sieťová hra - Chyba</translation>
     </message>
     <message>
         <source>Please select a server from the list</source>
-        <translation type="unfinished"></translation>
+        <translation>Prosím, vyberte server zo zoznamu</translation>
     </message>
     <message>
         <source>Please enter room name</source>
-        <translation type="unfinished">Prosím zadajte názov miestnosti</translation>
+        <translation>Prosím, zadajte názov miestnosti</translation>
     </message>
     <message>
         <source>Record Play - Error</source>
-        <translation type="unfinished"></translation>
+        <translation>Prehrávanie záznamu - Chyba</translation>
     </message>
     <message>
         <source>Please select record from the list</source>
-        <translation type="unfinished">Prosím vyberte záznam zo zoznamu</translation>
+        <translation>Prosím, vyberte záznam zo zoznamu</translation>
     </message>
     <message>
         <source>Cannot rename to </source>
-        <translation type="unfinished"></translation>
+        <translation>Nepodarilo sa premenovať na</translation>
     </message>
     <message>
         <source>Cannot delete file </source>
-        <translation type="unfinished"></translation>
+        <translation>Nepodarilo sa vymazať súbor</translation>
     </message>
     <message>
         <source>Room Name - Error</source>
-        <translation type="unfinished"></translation>
+        <translation>Názov miestnosti - Chyba</translation>
     </message>
     <message>
         <source>Please select room from the list</source>
-        <translation type="unfinished">Prosím vyberte miestnosť zo zoznamu</translation>
+        <translation>Prosím, vyberte miestnosť zo zoznamu</translation>
     </message>
     <message>
         <source>Room Name - Are you sure?</source>
-        <translation type="unfinished"></translation>
+        <translation>Názov miestnosti - Ste si istý?</translation>
     </message>
     <message>
         <source>The game you are trying to join has started.
 Do you still want to join the room?</source>
-        <translation type="unfinished">Hra, ku ktorej sa snažíte pripojiť, už začala.
+        <translation>Hra, ku ktorej sa snažíte pripojiť, už začala.
 Aj napriek tomu chcete vojsť do miestnosti?</translation>
     </message>
     <message>
         <source>Schemes - Warning</source>
-        <translation type="unfinished"></translation>
+        <translation>Schémy - Varovanie</translation>
     </message>
     <message>
         <source>Schemes - Are you sure?</source>
-        <translation type="unfinished"></translation>
+        <translation>Schémy - Ste si istý?</translation>
     </message>
     <message>
         <source>Do you really want to delete the game scheme &apos;%1&apos;?</source>
-        <translation type="unfinished"></translation>
+        <translation>Naozaj chcete vymazať hernú schému &apos;%1&apos;?</translation>
     </message>
     <message>
         <source>Videos - Are you sure?</source>
-        <translation type="unfinished"></translation>
+        <translation>Videa - Ste si istý?</translation>
     </message>
     <message>
         <source>Do you really want to delete the video &apos;%1&apos;?</source>
-        <translation type="unfinished"></translation>
+        <translation>Naozaj chcete vymazať video &apos;%1&apos;?</translation>
     </message>
     <message numerus="yes">
         <source>Do you really want to remove %1 file(s)?</source>
-        <translation type="unfinished">
-            <numerusform></numerusform>
+        <translation>
+            <numerusform>Naozaj chcete vymazať %1 súbor(y)?</numerusform>
             <numerusform></numerusform>
             <numerusform></numerusform>
         </translation>
     </message>
     <message>
         <source>Do you really want to cancel uploading %1?</source>
-        <translation type="unfinished"></translation>
+        <translation>Naozaj chcete zrušiť uploadovanie %1?</translation>
     </message>
     <message>
         <source>File error</source>
-        <translation type="unfinished">Chyba v súbore</translation>
+        <translation>Chyba v súbore</translation>
     </message>
     <message>
         <source>Cannot open &apos;%1&apos; for writing</source>
-        <translation type="unfinished"></translation>
+        <translation>Nepodarilo sa otvoriť &apos;%1&apos; pre zápis</translation>
     </message>
     <message>
         <source>Cannot open &apos;%1&apos; for reading</source>
-        <translation type="unfinished"></translation>
+        <translation>Nepodarilo sa otvoriť &apos;%1&apos; pre čítanie</translation>
     </message>
     <message>
         <source>Cannot use the ammo &apos;%1&apos;!</source>
-        <translation type="unfinished"></translation>
+        <translation>Nemôžem použiť muníciu &apos;%1&apos;!</translation>
     </message>
     <message>
         <source>Weapons - Warning</source>
-        <translation type="unfinished"></translation>
+        <translation>Zbrane - Varovanie</translation>
     </message>
     <message>
         <source>Cannot overwrite default weapon set &apos;%1&apos;!</source>
-        <translation type="unfinished"></translation>
+        <translation>Nemôžete prepísať východziu sadu zbraní &apos;%1&apos;!</translation>
     </message>
     <message>
         <source>Cannot delete default weapon set &apos;%1&apos;!</source>
-        <translation type="unfinished"></translation>
+        <translation>Nemôžete vymazať východziu sadu zbraní &apos;%1&apos;!</translation>
     </message>
     <message>
         <source>Weapons - Are you sure?</source>
-        <translation type="unfinished"></translation>
+        <translation>Zbrane - Ste si istý?</translation>
     </message>
     <message>
         <source>Do you really want to delete the weapon set &apos;%1&apos;?</source>
-        <translation type="unfinished"></translation>
+        <translation>Naozaj chcete vymazať sadu zbraní &apos;%1&apos;?</translation>
     </message>
 </context>
 <context>
@@ -2137,94 +2140,94 @@
     </message>
     <message>
         <source>More info</source>
-        <translation type="unfinished"></translation>
+        <translation>Viac informácii</translation>
     </message>
     <message>
         <source>Set default options</source>
-        <translation type="unfinished"></translation>
+        <translation>Nastaviť východzie</translation>
     </message>
     <message>
         <source>Open videos directory</source>
-        <translation type="unfinished"></translation>
+        <translation>Otvoriť adresár s videami</translation>
     </message>
     <message>
         <source>Play</source>
-        <translation type="unfinished"></translation>
+        <translation>Prehrať</translation>
     </message>
     <message>
         <source>Upload to YouTube</source>
-        <translation type="unfinished"></translation>
+        <translation>Uploadovať na YouTube</translation>
     </message>
     <message>
         <source>Cancel uploading</source>
-        <translation type="unfinished"></translation>
+        <translation>Zrušiť upload</translation>
     </message>
     <message>
         <source>Restore default coding parameters</source>
-        <translation type="unfinished"></translation>
+        <translation>Obnoviť pôvodné parametre pre kódovanie</translation>
     </message>
     <message>
         <source>Open the video directory in your system</source>
-        <translation type="unfinished"></translation>
+        <translation>Otvoriť adresár s videami vo vašom systéme</translation>
     </message>
     <message>
         <source>Play this video</source>
-        <translation type="unfinished"></translation>
+        <translation>Prehrať toto videa</translation>
     </message>
     <message>
         <source>Delete this video</source>
-        <translation type="unfinished"></translation>
+        <translation>Vymazať toto video</translation>
     </message>
     <message>
         <source>Upload this video to your Youtube account</source>
-        <translation type="unfinished"></translation>
+        <translation>Uploadovať video na váš účet YouTube</translation>
     </message>
 </context>
 <context>
     <name>RoomsListModel</name>
     <message>
         <source>In progress</source>
-        <translation type="unfinished">Prebieha</translation>
+        <translation>Prebieha</translation>
     </message>
     <message>
         <source>Room Name</source>
-        <translation type="unfinished">Názov miestnosti</translation>
+        <translation>Názov miestnosti</translation>
     </message>
     <message>
         <source>C</source>
-        <translation type="unfinished">C</translation>
+        <translation>C</translation>
     </message>
     <message>
         <source>T</source>
-        <translation type="unfinished">T</translation>
+        <translation>T</translation>
     </message>
     <message>
         <source>Owner</source>
-        <translation type="unfinished">Majiteľ</translation>
+        <translation>Majiteľ</translation>
     </message>
     <message>
         <source>Map</source>
-        <translation type="unfinished">Mapa</translation>
+        <translation>Mapa</translation>
     </message>
     <message>
         <source>Rules</source>
-        <translation type="unfinished">Pravidlá</translation>
+        <translation>Pravidlá</translation>
     </message>
     <message>
         <source>Weapons</source>
-        <translation type="unfinished">Výzbroj</translation>
+        <translation>Výzbroj</translation>
     </message>
     <message>
         <source>Random Map</source>
-        <translation type="unfinished">Náhodná mapa</translation>
+        <translation>Náhodná mapa</translation>
     </message>
     <message>
         <source>Random Maze</source>
-        <translation type="unfinished">Náhodné bludisko</translation>
+        <translation>Náhodné bludisko</translation>
     </message>
     <message>
         <source>Hand-drawn</source>
-        <translation type="unfinished"></translation>
+        <translation>Ručne kreslená</translation>
     </message>
 </context>
 <context>
@@ -2523,11 +2526,11 @@
     </message>
     <message>
         <source>mute audio</source>
-        <translation type="unfinished"></translation>
+        <translation>stlmiť zvuk</translation>
     </message>
     <message>
         <source>record</source>
-        <translation type="unfinished"></translation>
+        <translation>nahrať</translation>
     </message>
 </context>
 <context>
@@ -2617,7 +2620,7 @@
     </message>
     <message>
         <source>Record video:</source>
-        <translation type="unfinished"></translation>
+        <translation>Nahrať video:</translation>
     </message>
 </context>
 <context>
--- a/share/hedgewars/Data/Locale/sk.txt	Fri Nov 30 18:19:52 2012 +0400
+++ b/share/hedgewars/Data/Locale/sk.txt	Tue Dec 04 09:15:55 2012 +0400
@@ -56,6 +56,8 @@
 00:53=TARDIS
 00:54=Budova
 00:55=Postrek zeme
+00:56=Zmrazovač
+00:57=Sekáčik
 
 01:00=Do boja!
 01:01=Remíza
@@ -78,6 +80,7 @@
 01:18=Vysoký
 01:19=Extrémny
 01:20=%1 odskok
+01:21=Vypnutý zvuk
 
 ; Správy o udalostiach
 ; Ježko (%1) zomrel
--- a/tools/PascalPreprocessor.hs	Fri Nov 30 18:19:52 2012 +0400
+++ b/tools/PascalPreprocessor.hs	Tue Dec 04 09:15:55 2012 +0400
@@ -19,7 +19,6 @@
     ("FPC", "")
     , ("PAS2C", "")
     , ("ENDIAN_LITTLE", "")
-    , ("S3D_DISABLED", "")
     ]
 
 preprocess :: String -> IO String