update branch webgl
authorkoda
Tue, 04 Jun 2013 22:28:12 +0200
branchwebgl
changeset 9127 e350500c4edb
parent 8860 bde641cf53c8 (current diff)
parent 9125 c542f6e3a133 (diff)
child 9130 4f4b71da3559
update branch
.hgignore
CMakeLists.txt
QTfrontend/KB.h
QTfrontend/game.cpp
QTfrontend/gameuiconfig.cpp
QTfrontend/gameuiconfig.h
QTfrontend/hwform.cpp
QTfrontend/hwform.h
QTfrontend/net/newnetclient.cpp
QTfrontend/net/newnetclient.h
QTfrontend/ui/dialog/input_password.cpp
QTfrontend/ui/page/pagemain.cpp
QTfrontend/ui/page/pagevideos.cpp
QTfrontend/ui/widget/about.cpp
cmake_modules/CPackConfig.cmake
gameServer/Actions.hs
gameServer/HWProtoInRoomState.hs
gameServer/hedgewars-server.cabal
hedgewars/ArgParsers.inc
hedgewars/CMakeLists.txt
hedgewars/GSHandlers.inc
hedgewars/SDLh.pas
hedgewars/VGSHandlers.inc
hedgewars/hwengine.pas
hedgewars/options.inc
hedgewars/uAI.pas
hedgewars/uAIAmmoTests.pas
hedgewars/uAIMisc.pas
hedgewars/uAmmos.pas
hedgewars/uCaptions.pas
hedgewars/uChat.pas
hedgewars/uCommandHandlers.pas
hedgewars/uConsts.pas
hedgewars/uFloat.pas
hedgewars/uGame.pas
hedgewars/uGears.pas
hedgewars/uGearsHedgehog.pas
hedgewars/uGearsList.pas
hedgewars/uGearsRender.pas
hedgewars/uGearsUtils.pas
hedgewars/uIO.pas
hedgewars/uInputHandler.pas
hedgewars/uLand.pas
hedgewars/uLandGenMaze.pas
hedgewars/uLandGraphics.pas
hedgewars/uLandObjects.pas
hedgewars/uLandTemplates.pas
hedgewars/uLandTexture.pas
hedgewars/uLocale.pas
hedgewars/uMisc.pas
hedgewars/uPhysFSLayer.pas
hedgewars/uRandom.pas
hedgewars/uRender.pas
hedgewars/uRenderUtils.pas
hedgewars/uScript.pas
hedgewars/uSound.pas
hedgewars/uStats.pas
hedgewars/uStore.pas
hedgewars/uTeams.pas
hedgewars/uTypes.pas
hedgewars/uUtils.pas
hedgewars/uVariables.pas
hedgewars/uVisualGears.pas
hedgewars/uWorld.pas
hedgewars/videorec/avwrapper.c
misc/libphysfs/CMakeLists.txt
project_files/frontlib/hwconsts.h
share/hedgewars/Data/Sounds/voices/Default_uk/JustYouwait.ogg
--- a/.hgignore	Thu Apr 04 14:37:19 2013 +0200
+++ b/.hgignore	Tue Jun 04 22:28:12 2013 +0200
@@ -3,6 +3,7 @@
 glob:moc_*.cxx
 glob:qrc_*.cxx
 glob:*.o
+glob:*.a
 glob:*.qm
 glob:Makefile
 glob:bin
@@ -56,8 +57,8 @@
 glob:project_files/Android-build/SDL-android-project/.*
 glob:project_files/Android-build/out
 glob:project_files/Android-build/Makefile.android
-glob:hedgewars-build-desktop-Qt_4_7_4_for_Desktop_-_MinGW_4_4__Qt_SDK__Debug
-glob:hedgewars-build-desktop-Qt_4_7_4_for_Desktop_-_MinGW_4_4__Qt_SDK__Release
+glob:hedgewars-build-desktop-Qt*
+glob:hedgewars-build-desktop-Qt*
 glob:*.depends
 glob:tools/build_windows_koda.bat
 glob:share/hedgewars/Data/misc/hwengine.desktop
@@ -65,3 +66,5 @@
 glob:_CPack_Packages/
 glob:version_info.txt
 glob:*.tar.*
+glob:*.or
+glob:*.res
\ No newline at end of file
--- a/.hgtags	Thu Apr 04 14:37:19 2013 +0200
+++ b/.hgtags	Tue Jun 04 22:28:12 2013 +0200
@@ -59,3 +59,4 @@
 0000000000000000000000000000000000000000 0.9.18-release
 0000000000000000000000000000000000000000 0.9.18-release
 2fc02902c7cbf3c29bfe08a50e5f37983582b251 0.9.18-release
+1617149e01a4fa25637e2ab655d0287ef9c21b7c 0.9.19-release
--- a/CMakeLists.txt	Thu Apr 04 14:37:19 2013 +0200
+++ b/CMakeLists.txt	Tue Jun 04 22:28:12 2013 +0200
@@ -24,7 +24,7 @@
 option(NOVIDEOREC "Disable video recording (off)" OFF)
 
 #set this to ON when 2.1.0 becomes more widespread (and only for linux)
-option(SYSTEM_PHYSFS "Use system physfs (off)" OFF)
+option(PHYSFS_SYSTEM "Use system physfs (off)" OFF)
 
 option(LIBENGINE "Enable hwengine library (off)" OFF)
 option(ANDROID "Enable Android build (off)" OFF)
@@ -88,7 +88,7 @@
 set(CPACK_PACKAGE_VERSION_MAJOR 0)
 set(CPACK_PACKAGE_VERSION_MINOR 9)
 set(CPACK_PACKAGE_VERSION_PATCH 19)
-set(HEDGEWARS_PROTO_VER 44)
+set(HEDGEWARS_PROTO_VER 45)
 set(HEDGEWARS_VERSION "${CPACK_PACKAGE_VERSION_MAJOR}.${CPACK_PACKAGE_VERSION_MINOR}.${CPACK_PACKAGE_VERSION_PATCH}")
 set(required_clang_version 3.0)
 
@@ -198,8 +198,8 @@
     if(NOT ${minimum_macosx_version} VERSION_EQUAL ${current_macosx_version})
         if(minimum_macosx_version VERSION_EQUAL "10.4")
             set(CMAKE_OSX_SYSROOT "/Developer/SDKs/MacOSX10.4u.sdk/")
-            set(CMAKE_C_COMPILER "gcc-4.0")
-            set(CMAKE_CXX_COMPILER "g++-4.0")
+            set(CMAKE_C_COMPILER "/Developer/usr/bin/gcc-4.0")
+            set(CMAKE_CXX_COMPILER "/Developer/usr/bin/g++-4.0")
         else()
             string(REGEX REPLACE "([0-9]+.[0-9]+).[0-9]+" "\\1" sdk_version ${minimum_macosx_version})
             set(CMAKE_OSX_SYSROOT "/Developer/SDKs/MacOSX${sdk_version}.sdk/")
@@ -227,6 +227,10 @@
 
 #set default flags values for all projects (unless MINIMAL_FLAGS is true)
 if(NOT ${MINIMAL_FLAGS})
+    if(WINDOWS)
+        #this flags prevents a few dll hell problems
+        set(CMAKE_C_FLAGS "-static-libgcc ${CMAKE_C_FLAGS}")
+    endif(WINDOWS)
     set(CMAKE_C_FLAGS "-pipe ${CMAKE_C_FLAGS}")
     set(CMAKE_C_FLAGS_RELEASE "-w -Os -fomit-frame-pointer ${CMAKE_C_FLAGS_RELEASE}")
     set(CMAKE_C_FLAGS_DEBUG "-Wall -O0 -g -DDEBUG ${CMAKE_C_FLAGS_DEBUG}")
@@ -241,25 +245,36 @@
     set(CMAKE_CXX_FLAGS_DEBUG "-Wall -DDEBUG")
 endif()
 
-#TODO: find out why we need this...
+
+#TESTING TIME
 include(CheckCCompilerFlag)
+
+#check for noexecstack on ELF, should be set on Gentoo and similar
 set(CMAKE_REQUIRED_FLAGS "-Wl,-z -Wl,noexecstack")
 check_c_compiler_flag("" HAVE_NOEXECSTACK) #empty because we are testing a linker flag
 if(HAVE_NOEXECSTACK)
     list(APPEND pascal_flags "-k-z" "-knoexecstack")
-    if(NOT ${MINIMAL_FLAGS})
-        set(CMAKE_C_FLAGS "${CMAKE_C_FLAGS} ${CMAKE_REQUIRED_FLAGS}")
-    endif()
+    set(CMAKE_C_FLAGS "${CMAKE_C_FLAGS} ${CMAKE_REQUIRED_FLAGS}")
+endif()
+unset(CMAKE_REQUIRED_FLAGS)
+
+#check for ASLR and DEP security features on Windows
+#both supported in binutils >= 2.20, available since Vista and XP SP2 respectively
+set(CMAKE_REQUIRED_FLAGS "-Wl,--nxcompat -Wl,--dynamicbase")
+check_c_compiler_flag("" HAVE_WINASLRDEP) #empty because we are testing a linker flag
+if(HAVE_WINASLRDEP)
+    list(APPEND pascal_flags "-k--nxcompat" "-k--dynamicbase")
+    set(CMAKE_C_FLAGS "${CMAKE_C_FLAGS} ${CMAKE_REQUIRED_FLAGS}")
 endif()
 unset(CMAKE_REQUIRED_FLAGS)
 
 #parse additional parameters
 if(FPFLAGS OR GHFLAGS)
     if(${allow_parse_args})
-        message(${WARNING} "FPFLAGS and GHFLAGS are available only when using CMake >= 2.8")
-    else()
         separate_arguments(fpflags_parsed UNIX_COMMAND ${FPFLAGS})
         separate_arguments(ghflags_parsed UNIX_COMMAND ${GHFLAGS})
+    else()
+        message(${WARNING} "FPFLAGS and GHFLAGS are available only when using CMake >= 2.8")
     endif()
 endif()
 
@@ -344,7 +359,7 @@
 
 
 #physfs discovery
-if (${SYSTEM_PHYSFS})
+if (${PHYSFS_SYSTEM})
     if (NOT PHYSFS_LIBRARY OR NOT PHYSFS_INCLUDE_DIR)
         find_package(PhysFS)
     endif()
@@ -410,5 +425,5 @@
     endif(ANDROID)
 endif(WEBGL)
 
-include(${CMAKE_MODULE_PATH}/CPackConfig.cmake)
+include(${CMAKE_MODULE_PATH}/cpackvars.cmake)
 
--- a/ChangeLog.txt	Thu Apr 04 14:37:19 2013 +0200
+++ b/ChangeLog.txt	Tue Jun 04 22:28:12 2013 +0200
@@ -1,10 +1,45 @@
 + features
 * bugfixes
 
+0.9.18 -> 0.9.19:
+ + New Freezer weapon - freezes terrain, water, hedgehogs, mines, cases, explosives
+ + Saucer can aim weapons and fire underwater
+ + Main graphical user interface overhaul
+ + Splashscreen on Windows *_*
+ + Up and down keys navigate in chat history
+ + Several commands from chat available
+ + Support hwplay:// scheme syntax
+ + Supply full revision and hash information in version tag
+ + Better set of options for driving engine
+ + Downloadable content can now be stored in packages for easy uninstall
+ + Lua scripts can load a sidecar overlay package of game resources
+ + Math improvements for better performance/reliability
+ + Smarter AI - now uses drill rocket accurately and is aware of barrels and dud mines.  More aggressive in infinite attack, lua can tell to target specific hogs, such as in Mutant
+ + New fort, Steel Tower
+ + New theme, Fruit
+ + New hats - some national ones, Portal, harlequin, more animals...
+ + New maps based on StarBound. SB_Bones, SB_Crystal, SB_Grassy, SB_Grove, SB_Haunty, SB_Oaks, SB_Shrooms, SB_Tentacles
+ + Translation updates - Turkish, French, German, Japanese, Portuguese, Italian, Russian - Campaign french should work correctly now
+ + Theme object masks
+ + Easier weapon selection in shoppa. F1 will select from F5 if there are no weps in F1-F4
+ + Cleaver radius shrunk to improve usability on horizontal throws
+ + Map hog limit is now just a suggestion, not enforced
+ + Static map theme is now just the default, can be changed
+ + Themeable static maps (provide a mask.png without a map.png)
+ + Split seed with '|' to keep the land shape but change the hog placement
+ * You can now move out of the way when throwing a sticky mine or cleaver straight up
+ * Rope sliding should behave more like pre-0.9.18 again
+ * Forbid kicking on 1v1 matches
+ * Desync fixes
+ * Fixed fort mode
+ * Making very large maps now works properly with targeted weapons
+ * ParseCommand should be safe to use in Lua now, at any time
+ * Fixes to many weapons. Mudball, blowtorch, explosives, cluster bomb spread, portal.
+
 0.9.17 -> 0.9.18:
 
  + 'A Classic Fairytale' Campaign
- + Video recorder (requires ffmpeg)
+ + Video recorder (requires ffmpeg/libav)
  + Cleaver weapon
  + AI is now aware of drowning and fall damage
  + AI learned how to use Sniper Rifle and Cake
--- a/QTfrontend/KB.h	Thu Apr 04 14:37:19 2013 +0200
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,34 +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
- */
-
-#ifndef KB_H
-#define KB_H
-
-#include <QString>
-
-const ulong KBmsgsCount = 1;
-
-const QString KBMessages[KBmsgsCount] =
-{
-    QT_TRANSLATE_NOOP("KB", "SDL_ttf returned error while rendering text, "
-    "most propably it is related to the bug "
-    "in freetype2. It's recommended to update your "
-    "freetype lib.")
-};
-
-#endif // KB_H
--- a/QTfrontend/achievements.cpp	Thu Apr 04 14:37:19 2013 +0200
+++ b/QTfrontend/achievements.cpp	Tue Jun 04 22:28:12 2013 +0200
@@ -1,6 +1,6 @@
 /*
  * Hedgewars, a free turn based strategy game
- * Copyright (c) 2004-2012 Andrey Korotaev <unC0Rr@gmail.com>
+ * Copyright (c) 2004-2013 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
--- a/QTfrontend/achievements.h	Thu Apr 04 14:37:19 2013 +0200
+++ b/QTfrontend/achievements.h	Tue Jun 04 22:28:12 2013 +0200
@@ -1,6 +1,6 @@
 /*
  * Hedgewars, a free turn based strategy game
- * Copyright (c) 2004-2012 Andrey Korotaev <unC0Rr@gmail.com>
+ * Copyright (c) 2004-2013 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
--- a/QTfrontend/binds.cpp	Thu Apr 04 14:37:19 2013 +0200
+++ b/QTfrontend/binds.cpp	Tue Jun 04 22:28:12 2013 +0200
@@ -1,6 +1,6 @@
 /*
  * Hedgewars, a free turn based strategy game
- * Copyright (c) 2004-2012 Andrey Korotaev <unC0Rr@gmail.com>
+ * Copyright (c) 2004-2013 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
--- a/QTfrontend/binds.h	Thu Apr 04 14:37:19 2013 +0200
+++ b/QTfrontend/binds.h	Tue Jun 04 22:28:12 2013 +0200
@@ -1,6 +1,6 @@
 /*
  * Hedgewars, a free turn based strategy game
- * Copyright (c) 2004-2012 Andrey Korotaev <unC0Rr@gmail.com>
+ * Copyright (c) 2004-2013 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
--- a/QTfrontend/campaign.cpp	Thu Apr 04 14:37:19 2013 +0200
+++ b/QTfrontend/campaign.cpp	Tue Jun 04 22:28:12 2013 +0200
@@ -1,6 +1,6 @@
 /*
  * Hedgewars, a free turn based strategy game
- * Copyright (c) 2004-2012 Andrey Korotaev <unC0Rr@gmail.com>
+ * Copyright (c) 2004-2013 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
@@ -16,43 +16,12 @@
  * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA
  */
 
-#include <QDir>
-#include <QFile>
-#include <QTextStream>
-#include <QPushButton>
-#include <QListWidget>
-#include <QStackedLayout>
-#include <QLineEdit>
-#include <QLabel>
-#include <QRadioButton>
-#include <QSpinBox>
-#include <QCloseEvent>
-#include <QCheckBox>
-#include <QTextBrowser>
-#include <QAction>
-#include <QTimer>
-#include <QScrollBar>
-#include <QDataWidgetMapper>
-#include <QTableView>
-#include <QCryptographicHash>
-#include <QSignalMapper>
-#include <QShortcut>
-#include <QDesktopServices>
-#include <QInputDialog>
-#include <QPropertyAnimation>
+#include "campaign.h"
+
+#include "hwconsts.h"
+
 #include <QSettings>
 
-#include "campaign.h"
-#include "gameuiconfig.h"
-#include "hwconsts.h"
-#include "gamecfgwidget.h"
-#include "bgwidget.h"
-#include "mouseoverfilter.h"
-#include "tcpBase.h"
-
-#include "DataManager.h"
-
-extern QString campaign, campaignTeam;
 
 QStringList getCampMissionList(QString & campaign)
 {
--- a/QTfrontend/campaign.h	Thu Apr 04 14:37:19 2013 +0200
+++ b/QTfrontend/campaign.h	Tue Jun 04 22:28:12 2013 +0200
@@ -1,6 +1,6 @@
 /*
  * Hedgewars, a free turn based strategy game
- * Copyright (c) 2004-2012 Andrey Korotaev <unC0Rr@gmail.com>
+ * Copyright (c) 2004-2013 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
@@ -19,21 +19,8 @@
 #ifndef CAMPAIGN_H
 #define CAMPAIGN_H
 
-#include <QMainWindow>
-#include <QStack>
-#include <QTime>
-#include <QPointer>
-#include <QPropertyAnimation>
-#include <QUrl>
-#include <QNetworkReply>
-#include <QNetworkRequest>
-#include <QNetworkAccessManager>
-
-#include "netserver.h"
-#include "game.h"
-#include "ui_hwform.h"
-#include "SDLInteraction.h"
-#include "bgwidget.h"
+#include <QString>
+#include <QStringList>
 
 QStringList getCampMissionList(QString & campaign);
 unsigned int getCampProgress(QString & teamName, QString & campName);
--- a/QTfrontend/drawmapscene.cpp	Thu Apr 04 14:37:19 2013 +0200
+++ b/QTfrontend/drawmapscene.cpp	Tue Jun 04 22:28:12 2013 +0200
@@ -1,6 +1,6 @@
 /*
  * Hedgewars, a free turn based strategy game
- * Copyright (c) 2004-2012 Andrey Korotaev <unC0Rr@gmail.com>
+ * Copyright (c) 2004-2013 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
--- a/QTfrontend/drawmapscene.h	Thu Apr 04 14:37:19 2013 +0200
+++ b/QTfrontend/drawmapscene.h	Tue Jun 04 22:28:12 2013 +0200
@@ -1,6 +1,6 @@
 /*
  * Hedgewars, a free turn based strategy game
- * Copyright (c) 2004-2012 Andrey Korotaev <unC0Rr@gmail.com>
+ * Copyright (c) 2004-2013 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
--- a/QTfrontend/game.cpp	Thu Apr 04 14:37:19 2013 +0200
+++ b/QTfrontend/game.cpp	Tue Jun 04 22:28:12 2013 +0200
@@ -1,6 +1,6 @@
 /*
  * Hedgewars, a free turn based strategy game
- * Copyright (c) 2004-2012 Andrey Korotaev <unC0Rr@gmail.com>
+ * Copyright (c) 2004-2013 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
@@ -38,6 +38,13 @@
 #include <QTextStream>
 #include "ThemeModel.h"
 
+// last game info
+QList<QVariant> lastGameStartArgs = QList<QVariant>();
+GameType lastGameType = gtNone;
+GameCFGWidget * lastGameCfg = NULL;
+QString lastGameAmmo = NULL;
+TeamSelWidget * lastGameTeamSel = NULL;
+
 QString training, campaign, campaignScript, campaignTeam; // TODO: Cleaner solution?
 
 HWGame::HWGame(GameUIConfig * config, GameCFGWidget * gamecfg, QString ammo, TeamSelWidget* pTeamSelWidget) :
@@ -48,6 +55,10 @@
     this->config = config;
     this->gamecfg = gamecfg;
     netSuspend = false;
+
+    lastGameCfg = gamecfg;
+    lastGameAmmo = ammo;
+    lastGameTeamSel = pTeamSelWidget;
 }
 
 HWGame::~HWGame()
@@ -228,6 +239,7 @@
                     SendQuickConfig();
                     break;
                 }
+                case gtNone:
                 case gtSave:
                 case gtDemo:
                     break;
@@ -306,8 +318,8 @@
             int size = msg.size();
             QString newResolution = QString().append(msg.mid(2)).left(size - 4);
             QStringList wh = newResolution.split('x');
-            config->Form->ui.pageOptions->windowWidthEdit->setText(wh[0]);
-            config->Form->ui.pageOptions->windowHeightEdit->setText(wh[1]);
+            config->Form->ui.pageOptions->windowWidthEdit->setValue(wh[0].toInt());
+            config->Form->ui.pageOptions->windowHeightEdit->setValue(wh[1].toInt());
             break;
         }
         default:
@@ -343,7 +355,7 @@
         readbuffer.remove(0, msglen + 1);
         ParseMessage(msg);
     }
-    
+
     flushNetBuffer();
 }
 
@@ -352,7 +364,7 @@
     if(m_netSendBuffer.size())
     {
         emit SendNet(m_netSendBuffer);
-        
+
         m_netSendBuffer.clear();
     }
 }
@@ -435,6 +447,9 @@
 
 void HWGame::StartLocal()
 {
+    lastGameStartArgs.clear();
+    lastGameType = gtLocal;
+
     gameType = gtLocal;
     demo.clear();
     Start(false);
@@ -443,6 +458,9 @@
 
 void HWGame::StartQuick()
 {
+    lastGameStartArgs.clear();
+    lastGameType = gtQLocal;
+
     gameType = gtQLocal;
     demo.clear();
     Start(false);
@@ -451,6 +469,10 @@
 
 void HWGame::StartTraining(const QString & file)
 {
+    lastGameStartArgs.clear();
+    lastGameStartArgs.append(file);
+    lastGameType = gtTraining;
+
     gameType = gtTraining;
     training = "Missions/Training/" + file + ".lua";
     demo.clear();
@@ -460,6 +482,12 @@
 
 void HWGame::StartCampaign(const QString & camp, const QString & campScript, const QString & campTeam)
 {
+    lastGameStartArgs.clear();
+    lastGameStartArgs.append(camp);
+    lastGameStartArgs.append(campScript);
+    lastGameStartArgs.append(campTeam);
+    lastGameType = gtCampaign;
+
     gameType = gtCampaign;
     campaign = camp;
     campaignScript = "Missions/Campaign/" + camp + "/" + campScript;
--- a/QTfrontend/game.h	Thu Apr 04 14:37:19 2013 +0200
+++ b/QTfrontend/game.h	Tue Jun 04 22:28:12 2013 +0200
@@ -1,6 +1,6 @@
 /*
  * Hedgewars, a free turn based strategy game
- * Copyright (c) 2004-2012 Andrey Korotaev <unC0Rr@gmail.com>
+ * Copyright (c) 2004-2013 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
@@ -29,6 +29,18 @@
 class GameCFGWidget;
 class TeamSelWidget;
 
+enum GameType
+{
+    gtNone     = 0,
+    gtLocal    = 1,
+    gtQLocal   = 2,
+    gtDemo     = 3,
+    gtNet      = 4,
+    gtTraining = 5,
+    gtCampaign = 6,
+    gtSave     = 7,
+};
+
 enum GameState
 {
     gsNotStarted = 0,
@@ -49,6 +61,13 @@
 
 bool checkForDir(const QString & dir);
 
+// last game info
+extern QList<QVariant> lastGameStartArgs;
+extern GameType lastGameType;
+extern GameCFGWidget * lastGameCfg;
+extern QString lastGameAmmo;
+extern TeamSelWidget * lastGameTeamSel;
+
 class HWGame : public TCPBase
 {
         Q_OBJECT
@@ -86,16 +105,6 @@
         void FromNetChat(const QString & msg);
 
     private:
-        enum GameType
-        {
-            gtLocal    = 1,
-            gtQLocal   = 2,
-            gtDemo     = 3,
-            gtNet      = 4,
-            gtTraining = 5,
-            gtCampaign = 6,
-            gtSave     = 7,
-        };
         char msgbuf[MAXMSGCHARS];
         QString ammostr;
         GameUIConfig * config;
--- a/QTfrontend/gameuiconfig.cpp	Thu Apr 04 14:37:19 2013 +0200
+++ b/QTfrontend/gameuiconfig.cpp	Tue Jun 04 22:28:12 2013 +0200
@@ -1,6 +1,6 @@
 /*
  * Hedgewars, a free turn based strategy game
- * Copyright (c) 2004-2012 Andrey Korotaev <unC0Rr@gmail.com>
+ * Copyright (c) 2004-2013 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
@@ -25,6 +25,7 @@
 #include <QNetworkProxy>
 #include <QNetworkProxyFactory>
 #include <utility>
+#include <QVariant>
 
 #include "gameuiconfig.h"
 #include "hwform.h"
@@ -94,8 +95,8 @@
     // If left blank reset the resolution to the default
     wWidth = (wWidth == "" ? widthStr : wWidth);
     wHeight = (wHeight == "" ? heightStr : wHeight);
-    Form->ui.pageOptions->windowWidthEdit->setText(wWidth);
-    Form->ui.pageOptions->windowHeightEdit->setText(wHeight);
+    Form->ui.pageOptions->windowWidthEdit->setValue(wWidth.toInt());
+    Form->ui.pageOptions->windowHeightEdit->setValue(wHeight.toInt());
 
     Form->ui.pageOptions->CBResolution->setCurrentIndex((t < 0) ? 1 : t);
     Form->ui.pageOptions->CBFullscreen->setChecked(value("video/fullscreen", false).toBool());
@@ -111,7 +112,7 @@
     Form->ui.pageOptions->CBFrontendMusic->setChecked(value("frontend/music", true).toBool());
     Form->ui.pageOptions->SLVolume->setValue(value("audio/volume", 100).toUInt());
 
-    QString netNick = value("net/nick", "").toString();
+    QString netNick = value("net/nick", tr("Guest")+QString("%1").arg(rand())).toString();
     Form->ui.pageOptions->editNetNick->setText(netNick);
     bool savePwd = value("net/savepassword",true).toBool();
     Form->ui.pageOptions->CBSavePassword->setChecked(savePwd);
@@ -156,7 +157,7 @@
     { // load colors
         QStandardItemModel * model = DataManager::instance().colorsModel();
         for(int i = model->rowCount() - 1; i >= 0; --i)
-            model->item(i)->setData(value(QString("colors/color%1").arg(i), model->item(i)->data()));
+            model->item(i)->setData(QColor(value(QString("colors/color%1").arg(i), model->item(i)->data()).toString()));
     }
 
     { // load binds
@@ -319,7 +320,7 @@
     { // save colors
         QStandardItemModel * model = DataManager::instance().colorsModel();
         for(int i = model->rowCount() - 1; i >= 0; --i)
-            setValue(QString("colors/color%1").arg(i), model->item(i)->data());
+            setValue(QString("colors/color%1").arg(i), model->item(i)->data().value<QColor>().name());
     }
 
     sync();
@@ -520,14 +521,28 @@
     setValue("net/passwordhash", QString());
     setValue("net/passwordlength", 0);
     setValue("net/savepassword", false); //changes the savepassword value to false in order to not let the user save an empty password in PAGE_SETUP
-    reloadValues(); //reloads the values of PAGE_SETUP
+    Form->ui.pageOptions->editNetPassword->setEnabled(false);
+    Form->ui.pageOptions->editNetPassword->setText("");
 }
 
 void GameUIConfig::setPasswordHash(const QString & passwordhash)
 {
     setValue("net/passwordhash", passwordhash);
-    setValue("net/passwordlength", passwordhash.size()/4);
-    setNetPasswordLength(passwordhash.size()/4);  //the hash.size() is divided by 4 let PAGE_SETUP use a reasonable number of stars to display the PW
+    if (passwordhash!=NULL && passwordhash.size() > 0)
+    {
+    // WTF - the whole point of "password length" was to have the dots match what they typed.  This is totally pointless, and all hashes are the same length for a given hash so might as well hardcode it.
+    // setValue("net/passwordlength", passwordhash.size()/4);
+        setValue("net/passwordlength", 8);
+
+    // More WTF
+    //setNetPasswordLength(passwordhash.size()/4);  //the hash.size() is divided by 4 let PAGE_SETUP use a reasonable number of stars to display the PW
+        setNetPasswordLength(8);
+    }
+    else
+    {
+        setValue("net/passwordlength", 0);
+        setNetPasswordLength(0);
+    }
 }
 
 QString GameUIConfig::passwordHash()
--- a/QTfrontend/gameuiconfig.h	Thu Apr 04 14:37:19 2013 +0200
+++ b/QTfrontend/gameuiconfig.h	Tue Jun 04 22:28:12 2013 +0200
@@ -1,6 +1,6 @@
 /*
  * Hedgewars, a free turn based strategy game
- * Copyright (c) 2004-2012 Andrey Korotaev <unC0Rr@gmail.com>
+ * Copyright (c) 2004-2013 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
--- a/QTfrontend/hwconsts.cpp.in	Thu Apr 04 14:37:19 2013 +0200
+++ b/QTfrontend/hwconsts.cpp.in	Tue Jun 04 22:28:12 2013 +0200
@@ -1,6 +1,6 @@
 /*
  * Hedgewars, a free turn based strategy game
- * Copyright (c) 2004-2012 Andrey Korotaev <unC0Rr@gmail.com>
+ * Copyright (c) 2004-2013 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
--- a/QTfrontend/hwconsts.h	Thu Apr 04 14:37:19 2013 +0200
+++ b/QTfrontend/hwconsts.h	Tue Jun 04 22:28:12 2013 +0200
@@ -1,6 +1,6 @@
 /*
  * Hedgewars, a free turn based strategy game
- * Copyright (c) 2004-2012 Andrey Korotaev <unC0Rr@gmail.com>
+ * Copyright (c) 2004-2013 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
--- a/QTfrontend/hwform.cpp	Thu Apr 04 14:37:19 2013 +0200
+++ b/QTfrontend/hwform.cpp	Tue Jun 04 22:28:12 2013 +0200
@@ -1,6 +1,6 @@
 /*
  * Hedgewars, a free turn based strategy game
- * Copyright (c) 2004-2012 Andrey Korotaev <unC0Rr@gmail.com>
+ * Copyright (c) 2004-2013 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
@@ -45,6 +45,7 @@
 #include <QInputDialog>
 #include <QPropertyAnimation>
 #include <QSettings>
+#include <QSortFilterProxyModel>
 
 #if (QT_VERSION >= 0x040600)
 #include <QGraphicsEffect>
@@ -150,9 +151,9 @@
 
     ui.pageOptions->CBResolution->addItems(SDLInteraction::instance().getResolutions());
 
-    config = new GameUIConfig(this, "physfs://hedgewars.ini");
+    config = new GameUIConfig(this, DataManager::instance().settingsFileName());
     frontendEffects = config->value("frontend/effects", true).toBool();
-    playerHash = QString(QCryptographicHash::hash(config->value("net/nick","").toString().toUtf8(), QCryptographicHash::Md5).toHex());
+    playerHash = QString(QCryptographicHash::hash(config->value("net/nick",tr("Guest")+QString("%1").arg(rand())).toString().toUtf8(), QCryptographicHash::Md5).toHex());
 
     ui.pageRoomsList->setSettings(config);
     ui.pageNetGame->setSettings(config);
@@ -285,6 +286,7 @@
     connect(ui.pageInfo->BtnSnapshots, SIGNAL(clicked()), this, SLOT(OpenSnapshotFolder()));
 
     connect(ui.pageGameStats, SIGNAL(saveDemoRequested()), this, SLOT(saveDemoWithCustomName()));
+    connect(ui.pageGameStats, SIGNAL(restartGameRequested()), this, SLOT(restartGame()));
 
     connect(ui.pageSinglePlayer->BtnSimpleGamePage, SIGNAL(clicked()), this, SLOT(SimpleGame()));
     connect(ui.pageSinglePlayer->BtnTrainPage, SIGNAL(clicked()), pageSwitchMapper, SLOT(map()));
@@ -317,8 +319,6 @@
     connect(ui.pageMain->BtnNetLocal, SIGNAL(clicked()), this, SLOT(GoToNet()));
     connect(ui.pageMain->BtnNetOfficial, SIGNAL(clicked()), this, SLOT(NetConnectOfficialServer()));
 
-    connect(ui.pageConnecting, SIGNAL(cancelConnection()), this, SLOT(GoBack()));
-
     connect(ui.pageVideos, SIGNAL(goBack()), config, SLOT(SaveVideosOptions()));
 
     ammoSchemeModel = new AmmoSchemeModel(this, cfgdir->absolutePath() + "/schemes.ini");
@@ -470,7 +470,7 @@
 
     if(teamslist.empty())
     {
-        QString currentNickName = config->value("net/nick","").toString().toUtf8();
+        QString currentNickName = config->value("net/nick",tr("Guest")+QString("%1").arg(rand())).toString().toUtf8();
         QString teamName;
 
         if (currentNickName.isEmpty())
@@ -596,6 +596,10 @@
 #endif
 
     qDebug("Leaving %s, entering %s", qPrintable(stringifyPageId(lastid)), qPrintable(stringifyPageId(id)));
+    if (lastid == ID_PAGE_MAIN)
+    {
+        ui.pageMain->resetNetworkChoice();
+    }
 
     // pageEnter and pageLeave events
     ((AbstractPage*)ui.Pages->widget(lastid))->triggerPageLeave();
@@ -673,6 +677,21 @@
         }
     }
 
+    if (id == ID_PAGE_GAMESTATS)
+    {
+        switch(lastGameType) {
+        case gtLocal:
+        case gtQLocal:
+        case gtTraining:
+        case gtCampaign:
+            ui.pageGameStats->restartBtnVisible(true);
+            break;
+        default:
+            ui.pageGameStats->restartBtnVisible(false);
+            break;
+        }
+    }
+
     if (id == ID_PAGE_MAIN)
     {
         ui.pageOptions->setTeamOptionsEnabled(true);
@@ -1246,20 +1265,20 @@
 
 // room status stuff
     connect(hwnet, SIGNAL(roomMaster(bool)),
-            this, SLOT(NetGameChangeStatus(bool)), Qt::QueuedConnection);
+            this, SLOT(NetGameChangeStatus(bool)));
 
 // net page stuff
     connect(hwnet, SIGNAL(roomNameUpdated(const QString &)),
             ui.pageNetGame, SLOT(setRoomName(const QString &)), Qt::QueuedConnection);
-    connect(hwnet, SIGNAL(chatStringFromNet(const QString&)),
-            ui.pageNetGame->chatWidget, SLOT(onChatString(const QString&)), Qt::QueuedConnection);
+    connect(hwnet, SIGNAL(roomChatAction(const QString&, const QString&)),
+            ui.pageNetGame->chatWidget, SLOT(onChatAction(const QString&, const QString&)), Qt::QueuedConnection);
+    connect(hwnet, SIGNAL(roomChatMessage(const QString&, const QString&)),
+            ui.pageNetGame->chatWidget, SLOT(onChatMessage(const QString&, const QString&)), Qt::QueuedConnection);
 
-    connect(hwnet, SIGNAL(chatStringFromMe(const QString&)),
-            ui.pageNetGame->chatWidget, SLOT(onChatString(const QString&)), Qt::QueuedConnection);
     connect(hwnet, SIGNAL(roomMaster(bool)),
             ui.pageNetGame->chatWidget, SLOT(adminAccess(bool)), Qt::QueuedConnection);
     connect(ui.pageNetGame->chatWidget, SIGNAL(chatLine(const QString&)),
-            hwnet, SLOT(chatLineToNet(const QString&)));
+            hwnet, SLOT(chatLineToNetWithEcho(const QString&)));
     connect(ui.pageNetGame->BtnGo, SIGNAL(clicked()), hwnet, SLOT(ToggleReady()));
     connect(hwnet, SIGNAL(setMyReadyStatus(bool)),
             ui.pageNetGame, SLOT(setReadyStatus(bool)), Qt::QueuedConnection);
@@ -1286,25 +1305,38 @@
     connect(ui.pageRoomsList->chatWidget, SIGNAL(consoleCommand(const QString&)),
             hwnet, SLOT(consoleCommand(const QString&)));
 
+// player info
+    connect(hwnet, SIGNAL(playerInfo(const QString&, const QString&, const QString&, const QString&)),
+            ui.pageRoomsList->chatWidget, SLOT(onPlayerInfo(const QString&, const QString&, const QString&, const QString&)), Qt::QueuedConnection);
+    connect(hwnet, SIGNAL(playerInfo(const QString&, const QString&, const QString&, const QString&)),
+            ui.pageNetGame->chatWidget, SLOT(onPlayerInfo(const QString&, const QString&, const QString&, const QString&)), Qt::QueuedConnection);
+
 // chatting
     connect(ui.pageRoomsList->chatWidget, SIGNAL(chatLine(const QString&)),
             hwnet, SLOT(chatLineToLobby(const QString&)));
-    connect(hwnet, SIGNAL(chatStringLobby(const QString&)),
-            ui.pageRoomsList->chatWidget, SLOT(onChatString(const QString&)), Qt::QueuedConnection);
-    connect(hwnet, SIGNAL(chatStringLobby(const QString&, const QString&)),
-            ui.pageRoomsList->chatWidget, SLOT(onChatString(const QString&, const QString&)), Qt::QueuedConnection);
-    connect(hwnet, SIGNAL(chatStringFromMeLobby(const QString&)),
-            ui.pageRoomsList->chatWidget, SLOT(onChatString(const QString&)), Qt::QueuedConnection);
+    connect(hwnet, SIGNAL(lobbyChatAction(const QString&,const QString&)),
+            ui.pageRoomsList->chatWidget, SLOT(onChatAction(const QString&,const QString&)), Qt::QueuedConnection);
+    connect(hwnet, SIGNAL(lobbyChatMessage(const QString&, const QString&)),
+            ui.pageRoomsList->chatWidget, SLOT(onChatMessage(const QString&, const QString&)), Qt::QueuedConnection);
 
 // nick list stuff
-    connect(hwnet, SIGNAL(nickAdded(const QString&, bool)),
-            ui.pageNetGame->chatWidget, SLOT(nickAdded(const QString&, bool)), Qt::QueuedConnection);
-    connect(hwnet, SIGNAL(nickRemoved(const QString&)),
-            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&)),
-            ui.pageRoomsList->chatWidget, SLOT(nickRemoved(const QString&)), Qt::QueuedConnection);
+    {
+        QSortFilterProxyModel * playersSortFilterModel = qobject_cast<QSortFilterProxyModel *>(hwnet->lobbyPlayersModel());
+        if(playersSortFilterModel)
+        {
+            PlayersListModel * players = qobject_cast<PlayersListModel *>(playersSortFilterModel->sourceModel());
+            connect(players, SIGNAL(nickAdded(const QString&, bool)),
+                    ui.pageNetGame->chatWidget, SLOT(nickAdded(const QString&, bool)));
+            connect(players, SIGNAL(nickRemoved(const QString&)),
+                    ui.pageNetGame->chatWidget, SLOT(nickRemoved(const QString&)));
+            connect(players, SIGNAL(nickAddedLobby(const QString&, bool)),
+                    ui.pageRoomsList->chatWidget, SLOT(nickAdded(const QString&, bool)));
+            connect(players, SIGNAL(nickRemovedLobby(const QString&)),
+                    ui.pageRoomsList->chatWidget, SLOT(nickRemoved(const QString&)));
+            connect(players, SIGNAL(nickRemovedLobby(const QString&, const QString&)),
+                    ui.pageRoomsList->chatWidget, SLOT(nickRemoved(const QString&, const QString&)));
+        }
+    }
 
 // teams selecting stuff
     connect(ui.pageNetGame->pNetTeamsWidget, SIGNAL(hhogsNumChanged(const HWTeam&)),
@@ -1342,14 +1374,15 @@
     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()));
 
+    // using proxy slot to prevent loss of game messages when they're sent to not yet connected slot of game object
+    connect(hwnet, SIGNAL(FromNet(const QByteArray &)), this, SLOT(FromNetProxySlot(const QByteArray &)), Qt::QueuedConnection);
+
     //nick and pass stuff
-    QString nickname = config->value("net/nick", "").toString();
-
     hwnet->m_private_game = !(hostName == NETGAME_DEFAULT_SERVER && port == NETGAME_DEFAULT_PORT);
-    if (hwnet->m_private_game == false)
-        if (AskForNickAndPwd() != 0)
-            return;
+    if (hwnet->m_private_game == false && AskForNickAndPwd() != 0)
+        return;
 
+    QString nickname = config->value("net/nick",tr("Guest")+QString("%1").arg(rand())).toString();
     ui.pageRoomsList->setUser(nickname);
     ui.pageNetGame->setUser(nickname);
 
@@ -1362,16 +1395,18 @@
     config->clearTempHash();
 
     //initialize
-    QString hash = config->passwordHash();
-    QString temphash = config->tempHash();
-    QString nickname = config->value("net/nick", "").toString();
+    QString hash;
+    QString temphash;
+    QString nickname;
     QString password;
 
-    //if something from login is missing, start dialog loop
-    if (nickname.isEmpty() || hash.isEmpty())
-    {
-        while (nickname.isEmpty() || (hash.isEmpty() && temphash.isEmpty())) //while a nickname, or both hashes are missing
-        {
+    do {
+        nickname = config->value("net/nick",tr("Guest")+QString("%1").arg(rand())).toString();
+        hash = config->passwordHash();
+        temphash = config->tempHash();
+
+        //if something from login is missing, start dialog loop
+        if (nickname.isEmpty() || hash.isEmpty()) {
             //open dialog
             HWPasswordDialog * pwDialog = new HWPasswordDialog(this);
             // make the "new account" button dialog open a browser with the registration page
@@ -1388,62 +1423,54 @@
             if (pwDialog->exec() != QDialog::Accepted) {
                 delete pwDialog;
                 GoBack();
-                return -1;
+                break;
             }
 
             //set nick and pass from the dialog
             nickname = pwDialog->leNickname->text();
             password = pwDialog->lePassword->text();
+            bool save = pwDialog->cbSave->isChecked();
+            //clean up
+            delete pwDialog;
 
             //check the nickname variable
             if (nickname.isEmpty()) {
                 int retry = RetryDialog(tr("Hedgewars - Empty nickname"), tr("No nickname supplied."));
                 GoBack();
-                delete pwDialog;
                 if (retry) {
                     if (hwnet->m_private_game) {
                         QStringList list = hwnet->getHost().split(":");
                         NetConnectServer(list.at(0), list.at(1).toShort());
                     } else
                         NetConnectOfficialServer();
-                    }
-                return -1;
+                }
+                break; //loop restart
+            } else {
+                //update nickname if it's fine
+                config->setValue("net/nick", nickname);
+                config->updNetNick();
             }
 
-            if (!password.isEmpty()) {
+            //check the password variable
+            if (password.isEmpty()) {
+                config->clearPasswordHash();
+                break;
+            }  else {
                 //calculate temphash and set it into config
                 temphash = QCryptographicHash::hash(password.toUtf8(), QCryptographicHash::Md5).toHex();
                 config->setTempHash(temphash);
 
                 //if user wants to save password
-                bool save = pwDialog->cbSave->isChecked();
                 config->setValue("net/savepassword", save);
-                if (save) // user wants to save password
-                {
+                if (save) {
+                    // user wants to save password
                     ui.pageOptions->CBSavePassword->setChecked(true);
                     config->setPasswordHash(temphash);
                 }
             }
-            else {
-                delete pwDialog;
-                config->setValue("net/nick", nickname);
-                config->updNetNick();
-                config->clearPasswordHash();
-                break;
-            }
-
-            delete pwDialog;
+        }
+    } while (nickname.isEmpty() || (hash.isEmpty() && temphash.isEmpty())); //while a nickname, or both hashes are missing
 
-            //update nickname
-            config->setValue("net/nick", nickname);
-            config->updNetNick();
-
-            //and all the variables
-            hash = config->passwordHash();
-            temphash = config->tempHash();
-            nickname = config->value("net/nick", "").toString();
-        }
-    }
     return 0;
 }
 
@@ -1516,7 +1543,7 @@
         if (retry) {
             if (hwnet->m_private_game) {
                 QStringList list = hwnet->getHost().split(":");
-                NetConnectServer(list.at(0), list.at(1).toShort());
+                NetConnectServer(list.at(0), list.at(1).toUInt());
             } else
                 NetConnectOfficialServer();
         }
@@ -1702,6 +1729,11 @@
 
 void HWForm::CreateNetGame()
 {
+    // go back in pages to prevent user from being stuck on certain pages
+    if(ui.Pages->currentIndex() == ID_PAGE_GAMESTATS ||
+       ui.Pages->currentIndex() == ID_PAGE_INGAME)
+        GoBack();
+
     QString ammo;
     ammo = ui.pageNetGame->pGameCFG->WeaponsName->itemData(
                ui.pageNetGame->pGameCFG->WeaponsName->currentIndex()
@@ -1712,7 +1744,6 @@
     connect(game, SIGNAL(SendNet(const QByteArray &)), hwnet, SLOT(SendNet(const QByteArray &)));
     connect(game, SIGNAL(SendChat(const QString &)), hwnet, SLOT(chatLineToNet(const QString &)));
     connect(game, SIGNAL(SendTeamMessage(const QString &)), hwnet, SLOT(SendTeamMessage(const QString &)));
-    connect(hwnet, SIGNAL(FromNet(const QByteArray &)), game, SLOT(FromNet(const QByteArray &)), Qt::QueuedConnection);
     connect(hwnet, SIGNAL(chatStringFromNet(const QString &)), game, SLOT(FromNetChat(const QString &)), Qt::QueuedConnection);
 
     game->StartNet();
@@ -1740,9 +1771,6 @@
 
 void HWForm::NetGameChangeStatus(bool isMaster)
 {
-    ui.pageNetGame->pGameCFG->setMaster(isMaster);
-    ui.pageNetGame->pNetTeamsWidget->setInteractivity(isMaster);
-
     if (isMaster)
         NetGameMaster();
     else
@@ -1794,6 +1822,7 @@
     {
         NetAmmoSchemeModel * netAmmo = new NetAmmoSchemeModel(hwnet);
         connect(hwnet, SIGNAL(netSchemeConfig(QStringList &)), netAmmo, SLOT(setNetSchemeConfig(QStringList &)));
+
         ui.pageNetGame->pGameCFG->GameSchemes->setModel(netAmmo);
 
         ui.pageNetGame->setRoomName(hwnet->getRoom());
@@ -1806,6 +1835,13 @@
     ui.pageNetGame->setMasterMode(false);
 }
 
+void HWForm::FromNetProxySlot(const QByteArray & msg)
+{
+    if(game)
+        game->FromNet(msg);
+
+}
+
 void HWForm::selectFirstNetScheme()
 {
     ui.pageNetGame->pGameCFG->GameSchemes->setCurrentIndex(0);
@@ -2002,6 +2038,31 @@
     }
 }
 
+void HWForm::restartGame()
+{
+    // get rid off old game stats page
+    if(ui.Pages->currentIndex() == ID_PAGE_GAMESTATS)
+        GoBack();
+
+    CreateGame(lastGameCfg, lastGameTeamSel, lastGameAmmo);
+
+    switch(lastGameType) {
+    case gtTraining:
+        game->StartTraining(lastGameStartArgs.at(0).toString());
+        break;
+    case gtQLocal:
+        game->StartQuick();
+        break;
+    case gtCampaign:
+        game->StartCampaign(lastGameStartArgs.at(0).toString(), lastGameStartArgs.at(1).toString(), lastGameStartArgs.at(2).toString());
+        break;
+    case gtLocal:
+        game->StartLocal();
+        break;
+    default:
+        break;
+    }
+}
 
 void HWForm::ShowErrorMessage(const QString & msg)
 {
@@ -2010,8 +2071,22 @@
 
 void HWForm::showFeedbackDialog()
 {
-    FeedbackDialog dialog(this);
-    dialog.exec();
+    QNetworkRequest newRequest(QUrl("http://www.hedgewars.org"));
+
+    QNetworkAccessManager *manager = new QNetworkAccessManager(this);
+    QNetworkReply *reply = manager->get(newRequest);
+    connect(reply, SIGNAL(finished()), this, SLOT(showFeedbackDialogNetChecked()));
+}
+
+void HWForm::showFeedbackDialogNetChecked()
+{
+    QNetworkReply *reply = qobject_cast<QNetworkReply *>(sender());
+
+    if (reply && (reply->error() == QNetworkReply::NoError)) {
+        FeedbackDialog dialog(this);
+        dialog.exec();
+    } else
+        MessageDialog::ShowErrorMessage(tr("This page requires an internet connection."), this);
 }
 
 void HWForm::startGame()
--- a/QTfrontend/hwform.h	Thu Apr 04 14:37:19 2013 +0200
+++ b/QTfrontend/hwform.h	Tue Jun 04 22:28:12 2013 +0200
@@ -1,6 +1,6 @@
 /*
  * Hedgewars, a free turn based strategy game
- * Copyright (c) 2004-2012 Andrey Korotaev <unC0Rr@gmail.com>
+ * Copyright (c) 2004-2013 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
@@ -129,6 +129,7 @@
         void UpdateCampaignPageProgress(int index);
         void InitCampaignPage();
         void showFeedbackDialog();
+        void showFeedbackDialogNetChecked();
 
         void NetGameChangeStatus(bool isMaster);
         void NetGameMaster();
@@ -142,6 +143,9 @@
         void openRegistrationPage();
 
         void startGame();
+        void restartGame();
+
+        void FromNetProxySlot(const QByteArray &);
 
     private:
         void _NetConnect(const QString & hostName, quint16 port, QString nick);
--- a/QTfrontend/main.cpp	Thu Apr 04 14:37:19 2013 +0200
+++ b/QTfrontend/main.cpp	Tue Jun 04 22:28:12 2013 +0200
@@ -1,6 +1,6 @@
 /*
  * Hedgewars, a free turn based strategy game
- * Copyright (c) 2004-2012 Andrey Korotaev <unC0Rr@gmail.com>
+ * Copyright (c) 2004-2013 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
@@ -261,18 +261,24 @@
     engine->setWriteDir(cfgdir->absolutePath());
     engine->mountPacks();
 
-    DataManager::ensureFileExists("physfs://hedgewars.ini");
-
     QTranslator Translator;
     {
-        QSettings settings("physfs://hedgewars.ini", QSettings::IniFormat);
+        QSettings settings(DataManager::instance().settingsFileName(), QSettings::IniFormat);
+        settings.setIniCodec("UTF-8");
+
         QString cc = settings.value("misc/locale", QString()).toString();
-        if(cc.isEmpty())
+        if (cc.isEmpty())
+        {
             cc = QLocale::system().name();
 
+            // Fallback to current input locale if "C" locale is returned
+            if(cc == "C")
+                cc = HWApplication::keyboardInputLocale().name();
+        }
+
         // load locale file into translator
-        if(!Translator.load(QString("physfs://Locale/hedgewars_%1").arg(cc)))
-            qWarning("Failed to install translation");
+        if (!Translator.load(QString("physfs://Locale/hedgewars_%1").arg(cc)))
+            qWarning("Failed to install translation (%s)", qPrintable(cc));
         app.installTranslator(&Translator);
     }
 
--- a/QTfrontend/model/GameStyleModel.cpp	Thu Apr 04 14:37:19 2013 +0200
+++ b/QTfrontend/model/GameStyleModel.cpp	Tue Jun 04 22:28:12 2013 +0200
@@ -1,6 +1,6 @@
 /*
  * Hedgewars, a free turn based strategy game
- * Copyright (c) 2004-2012 Andrey Korotaev <unC0Rr@gmail.com>
+ * Copyright (c) 2004-2013 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
--- a/QTfrontend/model/GameStyleModel.h	Thu Apr 04 14:37:19 2013 +0200
+++ b/QTfrontend/model/GameStyleModel.h	Tue Jun 04 22:28:12 2013 +0200
@@ -1,6 +1,6 @@
 /*
  * Hedgewars, a free turn based strategy game
- * Copyright (c) 2004-2012 Andrey Korotaev <unC0Rr@gmail.com>
+ * Copyright (c) 2004-2013 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
--- a/QTfrontend/model/HatModel.cpp	Thu Apr 04 14:37:19 2013 +0200
+++ b/QTfrontend/model/HatModel.cpp	Tue Jun 04 22:28:12 2013 +0200
@@ -1,6 +1,6 @@
 /*
  * Hedgewars, a free turn based strategy game
- * Copyright (c) 2004-2012 Andrey Korotaev <unC0Rr@gmail.com>
+ * Copyright (c) 2004-2013 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
--- a/QTfrontend/model/HatModel.h	Thu Apr 04 14:37:19 2013 +0200
+++ b/QTfrontend/model/HatModel.h	Tue Jun 04 22:28:12 2013 +0200
@@ -1,6 +1,6 @@
 /*
  * Hedgewars, a free turn based strategy game
- * Copyright (c) 2004-2012 Andrey Korotaev <unC0Rr@gmail.com>
+ * Copyright (c) 2004-2013 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
--- a/QTfrontend/model/MapModel.cpp	Thu Apr 04 14:37:19 2013 +0200
+++ b/QTfrontend/model/MapModel.cpp	Tue Jun 04 22:28:12 2013 +0200
@@ -1,6 +1,6 @@
 /*
  * Hedgewars, a free turn based strategy game
- * Copyright (c) 2004-2012 Andrey Korotaev <unC0Rr@gmail.com>
+ * Copyright (c) 2004-2013 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
--- a/QTfrontend/model/MapModel.h	Thu Apr 04 14:37:19 2013 +0200
+++ b/QTfrontend/model/MapModel.h	Tue Jun 04 22:28:12 2013 +0200
@@ -1,6 +1,6 @@
 /*
  * Hedgewars, a free turn based strategy game
- * Copyright (c) 2004-2012 Andrey Korotaev <unC0Rr@gmail.com>
+ * Copyright (c) 2004-2013 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
--- a/QTfrontend/model/ThemeModel.cpp	Thu Apr 04 14:37:19 2013 +0200
+++ b/QTfrontend/model/ThemeModel.cpp	Tue Jun 04 22:28:12 2013 +0200
@@ -1,6 +1,6 @@
 /*
  * Hedgewars, a free turn based strategy game
- * Copyright (c) 2004-2012 Andrey Korotaev <unC0Rr@gmail.com>
+ * Copyright (c) 2004-2013 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
--- a/QTfrontend/model/ThemeModel.h	Thu Apr 04 14:37:19 2013 +0200
+++ b/QTfrontend/model/ThemeModel.h	Tue Jun 04 22:28:12 2013 +0200
@@ -1,6 +1,6 @@
 /*
  * Hedgewars, a free turn based strategy game
- * Copyright (c) 2004-2012 Andrey Korotaev <unC0Rr@gmail.com>
+ * Copyright (c) 2004-2013 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
--- a/QTfrontend/model/ammoSchemeModel.cpp	Thu Apr 04 14:37:19 2013 +0200
+++ b/QTfrontend/model/ammoSchemeModel.cpp	Tue Jun 04 22:28:12 2013 +0200
@@ -1,6 +1,6 @@
 /*
  * Hedgewars, a free turn based strategy game
- * Copyright (c) 2004-2012 Andrey Korotaev <unC0Rr@gmail.com>
+ * Copyright (c) 2004-2013 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
@@ -194,7 +194,7 @@
             << QVariant(false)         // place hog      14
             << QVariant(true)          // shared ammo    15
             << QVariant(true)          // disable girders 16
-            << QVariant(false)         // disable land objects 17
+            << QVariant(true)         // disable land objects 17
             << QVariant(false)         // AI survival    18
             << QVariant(false)         // inf. attack    19
             << QVariant(true)          // reset weps     20
@@ -407,7 +407,7 @@
             << QVariant(true)          // team divide    2
             << QVariant(false)         // solid land     3
             << QVariant(false)         // border         4
-            << QVariant(true)          // low gravity    5
+            << QVariant(false)         // low gravity    5
             << QVariant(false)         // laser sight    6
             << QVariant(false)         // invulnerable   7
             << QVariant(false)         // reset health   8
--- a/QTfrontend/model/ammoSchemeModel.h	Thu Apr 04 14:37:19 2013 +0200
+++ b/QTfrontend/model/ammoSchemeModel.h	Tue Jun 04 22:28:12 2013 +0200
@@ -1,6 +1,6 @@
 /*
  * Hedgewars, a free turn based strategy game
- * Copyright (c) 2004-2012 Andrey Korotaev <unC0Rr@gmail.com>
+ * Copyright (c) 2004-2013 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
--- a/QTfrontend/model/netserverslist.cpp	Thu Apr 04 14:37:19 2013 +0200
+++ b/QTfrontend/model/netserverslist.cpp	Tue Jun 04 22:28:12 2013 +0200
@@ -1,6 +1,6 @@
 /*
  * Hedgewars, a free turn based strategy game
- * Copyright (c) 2004-2012 Andrey Korotaev <unC0Rr@gmail.com>
+ * Copyright (c) 2004-2013 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
--- a/QTfrontend/model/netserverslist.h	Thu Apr 04 14:37:19 2013 +0200
+++ b/QTfrontend/model/netserverslist.h	Tue Jun 04 22:28:12 2013 +0200
@@ -1,6 +1,6 @@
 /*
  * Hedgewars, a free turn based strategy game
- * Copyright (c) 2004-2012 Andrey Korotaev <unC0Rr@gmail.com>
+ * Copyright (c) 2004-2013 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
--- a/QTfrontend/model/playerslistmodel.cpp	Thu Apr 04 14:37:19 2013 +0200
+++ b/QTfrontend/model/playerslistmodel.cpp	Tue Jun 04 22:28:12 2013 +0200
@@ -84,7 +84,7 @@
 }
 
 
-void PlayersListModel::addPlayer(const QString & nickname)
+void PlayersListModel::addPlayer(const QString & nickname, bool notify)
 {
     insertRow(rowCount());
 
@@ -92,11 +92,18 @@
     setData(mi, nickname);
 
     checkFriendIgnore(mi);
+
+    emit nickAddedLobby(nickname, notify);
 }
 
 
-void PlayersListModel::removePlayer(const QString & nickname)
+void PlayersListModel::removePlayer(const QString & nickname, const QString &msg)
 {
+    if(msg.isEmpty())
+        emit nickRemovedLobby(nickname);
+    else
+        emit nickRemovedLobby(nickname, msg);
+
     QModelIndexList mil = match(index(0), Qt::DisplayRole, nickname, 1, Qt::MatchExactly);
 
     if(mil.size())
@@ -104,7 +111,7 @@
 }
 
 
-void PlayersListModel::playerJoinedRoom(const QString & nickname)
+void PlayersListModel::playerJoinedRoom(const QString & nickname, bool notify)
 {
     QModelIndexList mil = match(index(0), Qt::DisplayRole, nickname, 1, Qt::MatchExactly);
 
@@ -114,11 +121,15 @@
         updateIcon(mil[0]);
         updateSortData(mil[0]);
     }
+
+    emit nickAdded(nickname, notify);
 }
 
 
 void PlayersListModel::playerLeftRoom(const QString & nickname)
 {
+    emit nickRemoved(nickname);
+
     QModelIndexList mil = match(index(0), Qt::DisplayRole, nickname, 1, Qt::MatchExactly);
 
     if(mil.size())
--- a/QTfrontend/model/playerslistmodel.h	Thu Apr 04 14:37:19 2013 +0200
+++ b/QTfrontend/model/playerslistmodel.h	Tue Jun 04 22:28:12 2013 +0200
@@ -41,13 +41,20 @@
     bool removeRows(int row, int count, const QModelIndex &parent = QModelIndex());
 
 public slots:
-    void addPlayer(const QString & nickname);
-    void removePlayer(const QString & nickname);
-    void playerJoinedRoom(const QString & nickname);
+    void addPlayer(const QString & nickname, bool notify);
+    void removePlayer(const QString & nickname, const QString & msg = QString());
+    void playerJoinedRoom(const QString & nickname, bool notify);
     void playerLeftRoom(const QString & nickname);
     void resetRoomFlags();
     void setNickname(const QString & nickname);
 
+signals:
+    void nickAdded(const QString& nick, bool notifyNick);
+    void nickRemoved(const QString& nick);
+    void nickAddedLobby(const QString& nick, bool notifyNick);
+    void nickRemovedLobby(const QString& nick);
+    void nickRemovedLobby(const QString& nick, const QString& message);
+
 private:
     QHash<quint32, QIcon> & m_icons();
     typedef QHash<int, QVariant> DataEntry;
--- a/QTfrontend/model/roomslistmodel.cpp	Thu Apr 04 14:37:19 2013 +0200
+++ b/QTfrontend/model/roomslistmodel.cpp	Tue Jun 04 22:28:12 2013 +0200
@@ -1,6 +1,6 @@
 /*
  * Hedgewars, a free turn based strategy game
- * Copyright (c) 2004-2012 Andrey Korotaev <unC0Rr@gmail.com>
+ * Copyright (c) 2004-2013 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
--- a/QTfrontend/model/roomslistmodel.h	Thu Apr 04 14:37:19 2013 +0200
+++ b/QTfrontend/model/roomslistmodel.h	Tue Jun 04 22:28:12 2013 +0200
@@ -1,6 +1,6 @@
 /*
  * Hedgewars, a free turn based strategy game
- * Copyright (c) 2004-2012 Andrey Korotaev <unC0Rr@gmail.com>
+ * Copyright (c) 2004-2013 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
--- a/QTfrontend/net/hwmap.cpp	Thu Apr 04 14:37:19 2013 +0200
+++ b/QTfrontend/net/hwmap.cpp	Tue Jun 04 22:28:12 2013 +0200
@@ -1,7 +1,7 @@
 /*
  * Hedgewars, a free turn based strategy game
  * Copyright (c) 2006-2007 Ulyanov Igor <iulyanov@gmail.com>
- * Copyright (c) 2004-2012 Andrey Korotaev <unC0Rr@gmail.com>
+ * Copyright (c) 2004-2013 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
--- a/QTfrontend/net/hwmap.h	Thu Apr 04 14:37:19 2013 +0200
+++ b/QTfrontend/net/hwmap.h	Tue Jun 04 22:28:12 2013 +0200
@@ -1,7 +1,7 @@
 /*
  * Hedgewars, a free turn based strategy game
  * Copyright (c) 2006 Igor Ulyanov <iulyanov@gmail.com>
- * Copyright (c) 2004-2012 Andrey Korotaev <unC0Rr@gmail.com>
+ * Copyright (c) 2004-2013 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
--- a/QTfrontend/net/netregister.cpp	Thu Apr 04 14:37:19 2013 +0200
+++ b/QTfrontend/net/netregister.cpp	Tue Jun 04 22:28:12 2013 +0200
@@ -1,6 +1,6 @@
 /*
  * Hedgewars, a free turn based strategy game
- * Copyright (c) 2004-2012 Andrey Korotaev <unC0Rr@gmail.com>
+ * Copyright (c) 2004-2013 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
--- a/QTfrontend/net/netregister.h	Thu Apr 04 14:37:19 2013 +0200
+++ b/QTfrontend/net/netregister.h	Tue Jun 04 22:28:12 2013 +0200
@@ -1,6 +1,6 @@
 /*
  * Hedgewars, a free turn based strategy game
- * Copyright (c) 2004-2012 Andrey Korotaev <unC0Rr@gmail.com>
+ * Copyright (c) 2004-2013 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
--- a/QTfrontend/net/netserver.cpp	Thu Apr 04 14:37:19 2013 +0200
+++ b/QTfrontend/net/netserver.cpp	Tue Jun 04 22:28:12 2013 +0200
@@ -1,7 +1,7 @@
 /*
  * Hedgewars, a free turn based strategy game
  * Copyright (c) 2006-2008 Igor Ulyanov <iulyanov@gmail.com>
- * Copyright (c) 2004-2012 Andrey Korotaev <unC0Rr@gmail.com>
+ * Copyright (c) 2004-2013 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
--- a/QTfrontend/net/netserver.h	Thu Apr 04 14:37:19 2013 +0200
+++ b/QTfrontend/net/netserver.h	Tue Jun 04 22:28:12 2013 +0200
@@ -1,7 +1,7 @@
 /*
  * Hedgewars, a free turn based strategy game
  * Copyright (c) 2006-2008 Igor Ulyanov <iulyanov@gmail.com>
- * Copyright (c) 2004-2012 Andrey Korotaev <unC0Rr@gmail.com>
+ * Copyright (c) 2004-2013 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
--- a/QTfrontend/net/netudpserver.cpp	Thu Apr 04 14:37:19 2013 +0200
+++ b/QTfrontend/net/netudpserver.cpp	Tue Jun 04 22:28:12 2013 +0200
@@ -1,7 +1,7 @@
 /*
  * Hedgewars, a free turn based strategy game
  * Copyright (c) 2007-2008 Igor Ulyanov <iulyanov@gmail.com>
- * Copyright (c) 2004-2012 Andrey Korotaev <unC0Rr@gmail.com>
+ * Copyright (c) 2004-2013 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
--- a/QTfrontend/net/netudpserver.h	Thu Apr 04 14:37:19 2013 +0200
+++ b/QTfrontend/net/netudpserver.h	Tue Jun 04 22:28:12 2013 +0200
@@ -1,7 +1,7 @@
 /*
  * Hedgewars, a free turn based strategy game
  * Copyright (c) 2007-2008 Igor Ulyanov <iulyanov@gmail.com>
- * Copyright (c) 2004-2012 Andrey Korotaev <unC0Rr@gmail.com>
+ * Copyright (c) 2004-2013 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
--- a/QTfrontend/net/netudpwidget.cpp	Thu Apr 04 14:37:19 2013 +0200
+++ b/QTfrontend/net/netudpwidget.cpp	Tue Jun 04 22:28:12 2013 +0200
@@ -1,7 +1,7 @@
 /*
  * Hedgewars, a free turn based strategy game
  * Copyright (c) 2007 Igor Ulyanov <iulyanov@gmail.com>
- * Copyright (c) 2004-2012 Andrey Korotaev <unC0Rr@gmail.com>
+ * Copyright (c) 2004-2013 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
--- a/QTfrontend/net/netudpwidget.h	Thu Apr 04 14:37:19 2013 +0200
+++ b/QTfrontend/net/netudpwidget.h	Tue Jun 04 22:28:12 2013 +0200
@@ -1,7 +1,7 @@
 /*
  * Hedgewars, a free turn based strategy game
  * Copyright (c) 2007 Igor Ulyanov <iulyanov@gmail.com>
- * Copyright (c) 2004-2012 Andrey Korotaev <unC0Rr@gmail.com>
+ * Copyright (c) 2004-2013 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
--- a/QTfrontend/net/newnetclient.cpp	Thu Apr 04 14:37:19 2013 +0200
+++ b/QTfrontend/net/newnetclient.cpp	Tue Jun 04 22:28:12 2013 +0200
@@ -1,7 +1,7 @@
 /*
  * Hedgewars, a free turn based strategy game
  * Copyright (c) 2006-2008 Igor Ulyanov <iulyanov@gmail.com>
- * Copyright (c) 2004-2012 Andrey Korotaev <unC0Rr@gmail.com>
+ * Copyright (c) 2004-2013 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
@@ -336,10 +336,24 @@
             qWarning("Net: Empty CHAT message");
             return;
         }
+
+        QString action = HWProto::chatStringToAction(lst[2]);
+
         if (netClientState == InLobby)
-            emit chatStringLobby(lst[1], HWProto::formatChatMsgForFrontend(lst[2]));
+        {
+            if (action != NULL)
+                emit lobbyChatAction(lst[1], action);
+            else
+                emit lobbyChatMessage(lst[1], lst[2]);
+        }
         else
+        {
             emit chatStringFromNet(HWProto::formatChatMsg(lst[1], lst[2]));
+            if (action != NULL)
+                emit roomChatAction(lst[1], action);
+            else
+                emit roomChatMessage(lst[1], lst[2]);
+        }
         return;
     }
 
@@ -350,12 +364,13 @@
             qWarning("Net: Malformed INFO message");
             return;
         }
-        QStringList tmp = lst;
-        tmp.removeFirst();
-        if (netClientState == InLobby)
-            emit chatStringLobby(tmp.join("\n").prepend('\x01'));
-        else
-            emit chatStringFromNet(tmp.join("\n").prepend('\x01'));
+        emit playerInfo(lst[1], lst[2], lst[3], lst[4]);
+        if (netClientState != InLobby)
+        {
+            QStringList tmp = lst;
+            tmp.removeFirst();
+            emit chatStringFromNet(tmp.join(" ").prepend('\x01'));
+        }
         return;
     }
 
@@ -410,8 +425,7 @@
                         {
                             if (nick == mynick)
                             {
-                                if (isChief && !setFlag) ToggleReady();
-                                else emit setMyReadyStatus(setFlag);
+                                emit setMyReadyStatus(setFlag);
                             }
                             m_playersModel->setFlag(nick, PlayersListModel::Ready, setFlag);
                         }
@@ -490,9 +504,7 @@
                 emit connected();
             }
 
-            m_playersModel->addPlayer(lst[i]);
-            emit nickAddedLobby(lst[i], false);
-            emit chatStringLobby(lst[i], tr("%1 *** %2 has joined").arg('\x03').arg("|nick|"));
+            m_playersModel->addPlayer(lst[i], false);
         }
         return;
     }
@@ -539,13 +551,11 @@
             qWarning("Net: Bad LOBBY:LEFT message");
             return;
         }
-        emit nickRemovedLobby(lst[1]);
+
         if (lst.size() < 3)
-            emit chatStringLobby(tr("%1 *** %2 has left").arg('\x03').arg(lst[1]));
+            m_playersModel->removePlayer(lst[1]);
         else
-            emit chatStringLobby(lst[1], tr("%1 *** %2 has left (%3)").arg('\x03').arg("|nick|", lst[2]));
-
-        m_playersModel->removePlayer(lst[1]);
+            m_playersModel->removePlayer(lst[1], lst[2]);
 
         return;
     }
@@ -636,8 +646,8 @@
                     emit configAsked();
             }
 
-            m_playersModel->playerJoinedRoom(lst[i]);
-            emit nickAdded(lst[i], isChief && (lst[i] != mynick));
+            m_playersModel->playerJoinedRoom(lst[i], isChief && (lst[i] != mynick));
+
             emit chatStringFromNet(tr("%1 *** %2 has joined the room").arg('\x03').arg(lst[i]));
         }
         return;
@@ -769,9 +779,8 @@
 
             for(int i = 1; i < lst.size(); ++i)
             {
-                emit nickAdded(lst[i], isChief && (lst[i] != mynick));
                 emit chatStringFromNet(tr("%1 *** %2 has joined the room").arg('\x03').arg(lst[i]));
-                m_playersModel->playerJoinedRoom(lst[i]);
+                m_playersModel->playerJoinedRoom(lst[i], isChief && (lst[i] != mynick));
             }
             return;
         }
@@ -783,7 +792,7 @@
                 qWarning("Net: Bad LEFT message");
                 return;
             }
-            emit nickRemoved(lst[1]);
+
             if (lst.size() < 3)
                 emit chatStringFromNet(tr("%1 *** %2 has left").arg('\x03').arg(lst[1]));
             else
@@ -836,12 +845,25 @@
         );
 }
 
+void HWNewNet::chatLineToNetWithEcho(const QString& str)
+{
+    if(str != "")
+    {
+        emit chatStringFromNet(HWProto::formatChatMsg(mynick, str));
+        chatLineToNet(str);
+    }
+}
+
 void HWNewNet::chatLineToNet(const QString& str)
 {
     if(str != "")
     {
         RawSendNet(QString("CHAT") + delimeter + str);
-        emit(chatStringFromMe(HWProto::formatChatMsg(mynick, str)));
+        QString action = HWProto::chatStringToAction(str);
+        if (action != NULL)
+            emit(roomChatAction(mynick, action));
+        else
+            emit(roomChatMessage(mynick, str));
     }
 }
 
@@ -850,7 +872,11 @@
     if(str != "")
     {
         RawSendNet(QString("CHAT") + delimeter + str);
-        emit chatStringLobby(mynick, HWProto::formatChatMsgForFrontend(str));
+        QString action = HWProto::chatStringToAction(str);
+        if (action != NULL)
+            emit(lobbyChatAction(mynick, action));
+        else
+            emit(lobbyChatMessage(mynick, str));
     }
 }
 
--- a/QTfrontend/net/newnetclient.h	Thu Apr 04 14:37:19 2013 +0200
+++ b/QTfrontend/net/newnetclient.h	Tue Jun 04 22:28:12 2013 +0200
@@ -1,7 +1,7 @@
 /*
  * Hedgewars, a free turn based strategy game
  * Copyright (c) 2006-2008 Igor Ulyanov <iulyanov@gmail.com>
- * Copyright (c) 2004-2012 Andrey Korotaev <unC0Rr@gmail.com>
+ * Copyright (c) 2004-2013 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
@@ -99,10 +99,6 @@
         void AuthFailed();
         void EnteredGame();
         void LeftRoom(const QString & reason);
-        void nickAdded(const QString& nick, bool notifyNick);
-        void nickRemoved(const QString& nick);
-        void nickAddedLobby(const QString& nick, bool notifyNick);
-        void nickRemovedLobby(const QString& nick);
         void FromNet(const QByteArray & buf);
         void adminAccess(bool);
         void roomMaster(bool);
@@ -117,11 +113,16 @@
         void RemoveNetTeam(const HWTeam&);
         void hhnumChanged(const HWTeam&);
         void teamColorChanged(const HWTeam&);
-        void chatStringLobby(const QString&);
-        void chatStringLobby(const QString&, const QString&);
+        void playerInfo(
+            const QString & nick,
+            const QString & ip,
+            const QString & version,
+            const QString & roomInfo);
+        void lobbyChatMessage(const QString & nick, const QString & message);
+        void lobbyChatAction(const QString & nick, const QString & action);
+        void roomChatMessage(const QString & nick, const QString & message);
+        void roomChatAction(const QString & nick, const QString & action);
         void chatStringFromNet(const QString&);
-        void chatStringFromMe(const QString&);
-        void chatStringFromMeLobby(const QString&);
 
         void roomsList(const QStringList&);
         void serverMessage(const QString &);
@@ -137,6 +138,7 @@
     public slots:
         void ToggleReady();
         void chatLineToNet(const QString& str);
+        void chatLineToNetWithEcho(const QString&);
         void chatLineToLobby(const QString& str);
         void SendTeamMessage(const QString& str);
         void SendNet(const QByteArray & buf);
--- a/QTfrontend/net/proto.cpp	Thu Apr 04 14:37:19 2013 +0200
+++ b/QTfrontend/net/proto.cpp	Tue Jun 04 22:28:12 2013 +0200
@@ -1,6 +1,6 @@
 /*
  * Hedgewars, a free turn based strategy game
- * Copyright (c) 2004-2012 Andrey Korotaev <unC0Rr@gmail.com>
+ * Copyright (c) 2004-2013 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
@@ -45,11 +45,6 @@
     return buf;
 }
 
-QString HWProto::formatChatMsgForFrontend(const QString & msg)
-{
-    return formatChatMsg("|nick|", msg);
-}
-
 QString HWProto::formatChatMsg(const QString & nick, const QString & msg)
 {
     if(msg.left(4) == "/me ")
@@ -57,3 +52,11 @@
     else
         return QString("\x01%1: %2").arg(nick).arg(msg);
 }
+
+QString HWProto::chatStringToAction(const QString & string)
+{
+    if(string.left(4) == "/me ")
+        return string.mid(4);
+    else
+        return NULL;
+}
--- a/QTfrontend/net/proto.h	Thu Apr 04 14:37:19 2013 +0200
+++ b/QTfrontend/net/proto.h	Tue Jun 04 22:28:12 2013 +0200
@@ -1,6 +1,6 @@
 /*
  * Hedgewars, a free turn based strategy game
- * Copyright (c) 2004-2012 Andrey Korotaev <unC0Rr@gmail.com>
+ * Copyright (c) 2004-2013 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
@@ -35,6 +35,12 @@
         static QByteArray & addStringListToBuffer(QByteArray & buf, const QStringList & strList);
         static QString formatChatMsg(const QString & nick, const QString & msg);
         static QString formatChatMsgForFrontend(const QString & msg);
+        /**
+         * @brief Determines if a chat string represents a chat action and returns the action.
+         * @param string chat string
+         * @return the action-message or NULL if message is no action
+         */
+        static QString chatStringToAction(const QString & string);
 };
 
 #endif // _PROTO_H
--- a/QTfrontend/net/recorder.cpp	Thu Apr 04 14:37:19 2013 +0200
+++ b/QTfrontend/net/recorder.cpp	Tue Jun 04 22:28:12 2013 +0200
@@ -1,6 +1,6 @@
 /*
  * Hedgewars, a free turn based strategy game
- * Copyright (c) 2004-2012 Andrey Korotaev <unC0Rr@gmail.com>
+ * Copyright (c) 2004-2013 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
--- a/QTfrontend/net/recorder.h	Thu Apr 04 14:37:19 2013 +0200
+++ b/QTfrontend/net/recorder.h	Tue Jun 04 22:28:12 2013 +0200
@@ -1,6 +1,6 @@
 /*
  * Hedgewars, a free turn based strategy game
- * Copyright (c) 2004-2012 Andrey Korotaev <unC0Rr@gmail.com>
+ * Copyright (c) 2004-2013 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
--- a/QTfrontend/net/tcpBase.cpp	Thu Apr 04 14:37:19 2013 +0200
+++ b/QTfrontend/net/tcpBase.cpp	Tue Jun 04 22:28:12 2013 +0200
@@ -1,7 +1,7 @@
 /*
  * Hedgewars, a free turn based strategy game
  * Copyright (c) 2006-2007 Igor Ulyanov <iulyanov@gmail.com>
- * Copyright (c) 2004-2012 Andrey Korotaev <unC0Rr@gmail.com>
+ * Copyright (c) 2004-2013 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
--- a/QTfrontend/net/tcpBase.h	Thu Apr 04 14:37:19 2013 +0200
+++ b/QTfrontend/net/tcpBase.h	Tue Jun 04 22:28:12 2013 +0200
@@ -1,7 +1,7 @@
 /*
  * Hedgewars, a free turn based strategy game
  * Copyright (c) 2006-2007 Igor Ulyanov <iulyanov@gmail.com>
- * Copyright (c) 2004-2012 Andrey Korotaev <unC0Rr@gmail.com>
+ * Copyright (c) 2004-2013 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
--- a/QTfrontend/res/css/chat.css	Thu Apr 04 14:37:19 2013 +0200
+++ b/QTfrontend/res/css/chat.css	Tue Jun 04 22:28:12 2013 +0200
@@ -61,15 +61,20 @@
 .msg_FriendChat .nick { color: #30ff30; }
 .msg_UserJoin { color: #c0c0c0; }
 .msg_UserJoin .nick { color: #d0d0d0; }
+.msg_UserLeave { color: #b8b8b8; }
+.msg_UserLeave .nick { color: #c8c8c8; }
 .msg_FriendJoin { font-weight: bold; color: #c0f0c0; }
 .msg_FriendJoin .nick { color: #d8f0d8; }
+.msg_FriendLeave { font-weight: bold; color: #ffe090; }
+.msg_FriendLeave .nick { color: #f8e878; }
 .msg_UserAction { color: #ff80ff; }
 .msg_UserAction .nick { color: #ffa0ff;}
 .msg_FriendAction { color: #ff00ff; }
 .msg_FriendAction .nick { color: #ff30ff; }
 
-/* uncomment next line to disable join and leave messages of non-friends */
+/* uncomment next lines to disable join and leave messages of non-friends */
 /* .msg_UserJoin { display:none; } */
+/* .msg_UserLeave { display:none; } */
 
 /* timestamps */
 .timestamp {
--- a/QTfrontend/res/css/qt.css	Thu Apr 04 14:37:19 2013 +0200
+++ b/QTfrontend/res/css/qt.css	Tue Jun 04 22:28:12 2013 +0200
@@ -179,6 +179,7 @@
 QComboBox {
 border-radius: 10px;
 padding: 3px;
+height: 18px;
 }
 QComboBox:pressed{
 border-color: white;
@@ -326,4 +327,8 @@
 
 TeamSelWidget, #gameStackContainer, #GBoxOptions {
 border-radius: 10px;
-}
\ No newline at end of file
+}
+
+PageMultiplayer TeamSelWidget {
+min-height: 500px;
+}
--- a/QTfrontend/res/html/about.html	Thu Apr 04 14:37:19 2013 +0200
+++ b/QTfrontend/res/html/about.html	Tue Jun 04 22:28:12 2013 +0200
@@ -73,11 +73,11 @@
             Chinese: Jie Luo &lt;<a href="mailto:lililjlj@gmail.com">lililjlj@gmail.com</a>&gt;<br>
             English: Andrey Korotaev &lt;<a href="mailto:unC0Rr@gmail.com">unC0Rr@gmail.com</a>&gt;<br>
             Finnish: Nina Kuisma &lt;<a href="mailto:ninnnu@gmail.com">ninnnu@gmail.com</a>&gt;<br>
-            French: Antoine Turmel &lt;<a href="mailto:geekshadow@gmail.com">geekshadow@gmail.com</a>&gt;, Clement Woitrain &lt;<a href="mailto:sphrixclement@gmail.com">sphrixclement@gmail.com</a>&gt;<br>
+            French: Antoine Turmel &lt;<a href="mailto:geekshadow@gmail.com">geekshadow@gmail.com</a>&gt;, Clement Woitrain &lt;<a href="mailto:sphrixclement@gmail.com">sphrixclement@gmail.com</a>&gt;, Matisumi<br>
             German: Peter Hüwe &lt;<a href="mailto:PeterHuewe@gmx.de">PeterHuewe@gmx.de</a>&gt;, Mario Liebisch &lt;<a href="mailto:mario.liebisch@gmail.com">mario.liebisch@gmail.com</a>&gt;, Richard Karolyi &lt;<a href="mailto:sheepluva@ercatec.net">sheepluva@ercatec.net</a>&gt;<br>
             Greek: &lt;<a href="mailto:talos_kriti@yahoo.gr">talos_kriti@yahoo.gr</a>&gt;<br>
-            Italian: Luca Bonora &lt;<a href="mailto:bonora.luca@gmail.com">bonora.luca@gmail.com</a>&gt;, Marco Bresciani<br>
-            Japanese: ADAM Etienne &lt;<a href="mailto:etienne.adam@gmail.com">etienne.adam@gmail.com</a>&gt;<br>
+            Italian: Luca Bonora &lt;<a href="mailto:bonora.luca@gmail.com">bonora.luca@gmail.com</a>&gt;, Marco Bresciani &lt;<a href="mailto:m.bresciani@email.it">m.bresciani@email.it</a>&gt;<br>
+            Japanese: ADAM Etienne &lt;<a href="mailto:etienne.adam@gmail.com">etienne.adam@gmail.com</a>&gt;, Marco Bresciani &lt;<a href="mailto:m.bresciani@email.it">m.bresciani@email.it</a>&gt;, 梅津洋恵<br>
             Korean: Anthony Bellew &lt;<a href="mailto:anthonyreflected@gmail.com">anthonyreflected@gmail.com</a>&gt;<br>
             Lithuanian: Lukas Urbonas &lt;<a href="mailto:lukasu08@gmail.com">lukasu08@gmail.com</a>&gt;<br>
             Polish: Maciej Mroziński &lt;<a href="mailto:mynick2@o2.pl">mynick2@o2.pl</a>&gt;, Wojciech Latkowski &lt;<a href="mailto:magik17l@gmail.com">magik17l@gmail.com</a>&gt;, Piotr Mitana, Maciej Górny<br>
--- a/QTfrontend/res/xml/tips.xml	Thu Apr 04 14:37:19 2013 +0200
+++ b/QTfrontend/res/xml/tips.xml	Tue Jun 04 22:28:12 2013 +0200
@@ -46,6 +46,7 @@
     <tip>Like Hedgewars? Become a fan on <a href="http://www.facebook.com/Hedgewars">Facebook</a> or follow us on <a href="http://twitter.com/hedgewars">Twitter</a></tip>
     <tip>Feel free to draw your own graves, hats, flags or even maps and themes! But note that you'll have to share them somewhere to use them online.</tip>
     <tip>Keep your video card drivers up to date to avoid issues playing the game.</tip>
+    <tip>Heads or tails? Type '/rnd' in lobby and you'll find out. Also '/rnd rock paper scissors' works!</tip>
     <tip>You're able to associate Hedgewars related files (savegames and demo recordings) with the game to launch them right from your favorite file or internet browser.</tip>
     <windows-only>
 	    <tip>The version of Hedgewars supports <a href="http://www.xfire.com">Xfire</a>. Make sure to add Hedgewars to its game list so your friends can see you playing.</tip>
--- a/QTfrontend/sdlkeys.h	Thu Apr 04 14:37:19 2013 +0200
+++ b/QTfrontend/sdlkeys.h	Tue Jun 04 22:28:12 2013 +0200
@@ -1,6 +1,6 @@
 /*
  * Hedgewars, a free turn based strategy game
- * Copyright (c) 2004-2012 Andrey Korotaev <unC0Rr@gmail.com>
+ * Copyright (c) 2004-2013 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
--- a/QTfrontend/team.cpp	Thu Apr 04 14:37:19 2013 +0200
+++ b/QTfrontend/team.cpp	Tue Jun 04 22:28:12 2013 +0200
@@ -1,6 +1,6 @@
 /*
  * Hedgewars, a free turn based strategy game
- * Copyright (c) 2004-2012 Andrey Korotaev <unC0Rr@gmail.com>
+ * Copyright (c) 2004-2013 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
--- a/QTfrontend/team.h	Thu Apr 04 14:37:19 2013 +0200
+++ b/QTfrontend/team.h	Tue Jun 04 22:28:12 2013 +0200
@@ -1,6 +1,6 @@
 /*
  * Hedgewars, a free turn based strategy game
- * Copyright (c) 2004-2012 Andrey Korotaev <unC0Rr@gmail.com>
+ * Copyright (c) 2004-2013 Andrey Korotaev <unC0Rr@gmail.com>
  * Copyright (c) 2007 Igor Ulyanov <iulyanov@gmail.com>
  *
  * This program is free software; you can redistribute it and/or modify
--- a/QTfrontend/ui/dialog/ask_quit.cpp	Thu Apr 04 14:37:19 2013 +0200
+++ b/QTfrontend/ui/dialog/ask_quit.cpp	Tue Jun 04 22:28:12 2013 +0200
@@ -1,6 +1,6 @@
 /*
  * Hedgewars, a free turn based strategy game
- * Copyright (c) 2004-2012 Andrey Korotaev <unC0Rr@gmail.com>
+ * Copyright (c) 2004-2013 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
--- a/QTfrontend/ui/dialog/ask_quit.h	Thu Apr 04 14:37:19 2013 +0200
+++ b/QTfrontend/ui/dialog/ask_quit.h	Tue Jun 04 22:28:12 2013 +0200
@@ -1,6 +1,6 @@
 /*
  * Hedgewars, a free turn based strategy game
- * Copyright (c) 2004-2012 Andrey Korotaev <unC0Rr@gmail.com>
+ * Copyright (c) 2004-2013 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
--- a/QTfrontend/ui/dialog/input_ip.cpp	Thu Apr 04 14:37:19 2013 +0200
+++ b/QTfrontend/ui/dialog/input_ip.cpp	Tue Jun 04 22:28:12 2013 +0200
@@ -1,6 +1,6 @@
 /*
  * Hedgewars, a free turn based strategy game
- * Copyright (c) 2004-2012 Andrey Korotaev <unC0Rr@gmail.com>
+ * Copyright (c) 2004-2013 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
--- a/QTfrontend/ui/dialog/input_ip.h	Thu Apr 04 14:37:19 2013 +0200
+++ b/QTfrontend/ui/dialog/input_ip.h	Tue Jun 04 22:28:12 2013 +0200
@@ -1,6 +1,6 @@
 /*
  * Hedgewars, a free turn based strategy game
- * Copyright (c) 2004-2012 Andrey Korotaev <unC0Rr@gmail.com>
+ * Copyright (c) 2004-2013 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
--- a/QTfrontend/ui/dialog/input_password.cpp	Thu Apr 04 14:37:19 2013 +0200
+++ b/QTfrontend/ui/dialog/input_password.cpp	Tue Jun 04 22:28:12 2013 +0200
@@ -1,6 +1,6 @@
 /*
  * Hedgewars, a free turn based strategy game
- * Copyright (c) 2004-2012 Andrey Korotaev <unC0Rr@gmail.com>
+ * Copyright (c) 2004-2013 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
--- a/QTfrontend/ui/dialog/input_password.h	Thu Apr 04 14:37:19 2013 +0200
+++ b/QTfrontend/ui/dialog/input_password.h	Tue Jun 04 22:28:12 2013 +0200
@@ -1,6 +1,6 @@
 /*
  * Hedgewars, a free turn based strategy game
- * Copyright (c) 2004-2012 Andrey Korotaev <unC0Rr@gmail.com>
+ * Copyright (c) 2004-2013 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
--- a/QTfrontend/ui/dialog/upload_video.cpp	Thu Apr 04 14:37:19 2013 +0200
+++ b/QTfrontend/ui/dialog/upload_video.cpp	Tue Jun 04 22:28:12 2013 +0200
@@ -1,6 +1,6 @@
 /*
  * Hedgewars, a free turn based strategy game
- * Copyright (c) 2004-2012 Andrey Korotaev <unC0Rr@gmail.com>
+ * Copyright (c) 2004-2013 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
--- a/QTfrontend/ui/dialog/upload_video.h	Thu Apr 04 14:37:19 2013 +0200
+++ b/QTfrontend/ui/dialog/upload_video.h	Tue Jun 04 22:28:12 2013 +0200
@@ -1,6 +1,6 @@
 /*
  * Hedgewars, a free turn based strategy game
- * Copyright (c) 2004-2012 Andrey Korotaev <unC0Rr@gmail.com>
+ * Copyright (c) 2004-2013 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
--- a/QTfrontend/ui/page/AbstractPage.cpp	Thu Apr 04 14:37:19 2013 +0200
+++ b/QTfrontend/ui/page/AbstractPage.cpp	Tue Jun 04 22:28:12 2013 +0200
@@ -1,6 +1,6 @@
 /*
  * Hedgewars, a free turn based strategy game
- * Copyright (c) 2004-2012 Andrey Korotaev <unC0Rr@gmail.com>
+ * Copyright (c) 2004-2013 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
--- a/QTfrontend/ui/page/AbstractPage.h	Thu Apr 04 14:37:19 2013 +0200
+++ b/QTfrontend/ui/page/AbstractPage.h	Tue Jun 04 22:28:12 2013 +0200
@@ -1,6 +1,6 @@
 /*
  * Hedgewars, a free turn based strategy game
- * Copyright (c) 2004-2012 Andrey Korotaev <unC0Rr@gmail.com>
+ * Copyright (c) 2004-2013 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
--- a/QTfrontend/ui/page/pageadmin.cpp	Thu Apr 04 14:37:19 2013 +0200
+++ b/QTfrontend/ui/page/pageadmin.cpp	Tue Jun 04 22:28:12 2013 +0200
@@ -1,6 +1,6 @@
 /*
  * Hedgewars, a free turn based strategy game
- * Copyright (c) 2004-2012 Andrey Korotaev <unC0Rr@gmail.com>
+ * Copyright (c) 2004-2013 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
--- a/QTfrontend/ui/page/pageadmin.h	Thu Apr 04 14:37:19 2013 +0200
+++ b/QTfrontend/ui/page/pageadmin.h	Tue Jun 04 22:28:12 2013 +0200
@@ -1,6 +1,6 @@
 /*
  * Hedgewars, a free turn based strategy game
- * Copyright (c) 2004-2012 Andrey Korotaev <unC0Rr@gmail.com>
+ * Copyright (c) 2004-2013 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
--- a/QTfrontend/ui/page/pagecampaign.cpp	Thu Apr 04 14:37:19 2013 +0200
+++ b/QTfrontend/ui/page/pagecampaign.cpp	Tue Jun 04 22:28:12 2013 +0200
@@ -1,6 +1,6 @@
 /*
  * Hedgewars, a free turn based strategy game
- * Copyright (c) 2004-2012 Andrey Korotaev <unC0Rr@gmail.com>
+ * Copyright (c) 2004-2013 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
--- a/QTfrontend/ui/page/pagecampaign.h	Thu Apr 04 14:37:19 2013 +0200
+++ b/QTfrontend/ui/page/pagecampaign.h	Tue Jun 04 22:28:12 2013 +0200
@@ -1,6 +1,6 @@
 /*
  * Hedgewars, a free turn based strategy game
- * Copyright (c) 2004-2012 Andrey Korotaev <unC0Rr@gmail.com>
+ * Copyright (c) 2004-2013 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
--- a/QTfrontend/ui/page/pageconnecting.cpp	Thu Apr 04 14:37:19 2013 +0200
+++ b/QTfrontend/ui/page/pageconnecting.cpp	Tue Jun 04 22:28:12 2013 +0200
@@ -1,6 +1,6 @@
 /*
  * Hedgewars, a free turn based strategy game
- * Copyright (c) 2004-2012 Andrey Korotaev <unC0Rr@gmail.com>
+ * Copyright (c) 2004-2013 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
--- a/QTfrontend/ui/page/pageconnecting.h	Thu Apr 04 14:37:19 2013 +0200
+++ b/QTfrontend/ui/page/pageconnecting.h	Tue Jun 04 22:28:12 2013 +0200
@@ -1,6 +1,6 @@
 /*
  * Hedgewars, a free turn based strategy game
- * Copyright (c) 2004-2012 Andrey Korotaev <unC0Rr@gmail.com>
+ * Copyright (c) 2004-2013 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
--- a/QTfrontend/ui/page/pagedata.cpp	Thu Apr 04 14:37:19 2013 +0200
+++ b/QTfrontend/ui/page/pagedata.cpp	Tue Jun 04 22:28:12 2013 +0200
@@ -1,6 +1,6 @@
 /*
  * Hedgewars, a free turn based strategy game
- * Copyright (c) 2004-2012 Andrey Korotaev <unC0Rr@gmail.com>
+ * Copyright (c) 2004-2013 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
@@ -60,7 +60,10 @@
 
     web->setOpenLinks(false);
 //    fetchList();
-
+    web->setHtml(QString(
+        "<center><h2>Hedgewars Downloadable Content</h2><br><br>"
+        "<i>%1</i></center>")
+        .arg(tr("Loading, please wait.")));
     m_contentDownloaded = false;
 }
 
@@ -106,8 +109,7 @@
 {
     QNetworkReply * reply = qobject_cast<QNetworkReply *>(sender());
 
-    if(reply)
-    {
+    if (reply && (reply->error() == QNetworkReply::NoError)) {
         QString html = QString::fromUtf8(reply->readAll());
         int begin = html.indexOf("<!-- BEGIN -->");
         int end = html.indexOf("<!-- END -->");
@@ -117,7 +119,11 @@
             html.remove(0, begin);
         }
         web->setHtml(html);
-    }
+    } else
+        web->setHtml(QString(
+            "<center><h2>Hedgewars Downloadable Content</h2><br><br>"
+            "<p><i><h4>%1</i></h4></p></center>")
+            .arg(tr("This page requires an internet connection.")));
 }
 
 void PageDataDownload::fileDownloaded()
--- a/QTfrontend/ui/page/pagedata.h	Thu Apr 04 14:37:19 2013 +0200
+++ b/QTfrontend/ui/page/pagedata.h	Tue Jun 04 22:28:12 2013 +0200
@@ -1,6 +1,6 @@
 /*
  * Hedgewars, a free turn based strategy game
- * Copyright (c) 2004-2012 Andrey Korotaev <unC0Rr@gmail.com>
+ * Copyright (c) 2004-2013 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
--- a/QTfrontend/ui/page/pagedrawmap.cpp	Thu Apr 04 14:37:19 2013 +0200
+++ b/QTfrontend/ui/page/pagedrawmap.cpp	Tue Jun 04 22:28:12 2013 +0200
@@ -1,6 +1,6 @@
 /*
  * Hedgewars, a free turn based strategy game
- * Copyright (c) 2004-2012 Andrey Korotaev <unC0Rr@gmail.com>
+ * Copyright (c) 2004-2013 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
--- a/QTfrontend/ui/page/pagedrawmap.h	Thu Apr 04 14:37:19 2013 +0200
+++ b/QTfrontend/ui/page/pagedrawmap.h	Tue Jun 04 22:28:12 2013 +0200
@@ -1,6 +1,6 @@
 /*
  * Hedgewars, a free turn based strategy game
- * Copyright (c) 2004-2012 Andrey Korotaev <unC0Rr@gmail.com>
+ * Copyright (c) 2004-2013 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
--- a/QTfrontend/ui/page/pageeditteam.cpp	Thu Apr 04 14:37:19 2013 +0200
+++ b/QTfrontend/ui/page/pageeditteam.cpp	Tue Jun 04 22:28:12 2013 +0200
@@ -1,6 +1,6 @@
 /*
  * Hedgewars, a free turn based strategy game
- * Copyright (c) 2004-2012 Andrey Korotaev <unC0Rr@gmail.com>
+ * Copyright (c) 2004-2013 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
@@ -320,7 +320,7 @@
                        );
 
     if (!list.isEmpty())
-        SDLInteraction::instance().playSoundFile("physfs://" + voiceDir + "/" +
+        SDLInteraction::instance().playSoundFile("/" + voiceDir + "/" +
                                     list[rand() % list.size()]);
 }
 
--- a/QTfrontend/ui/page/pageeditteam.h	Thu Apr 04 14:37:19 2013 +0200
+++ b/QTfrontend/ui/page/pageeditteam.h	Tue Jun 04 22:28:12 2013 +0200
@@ -1,6 +1,6 @@
 /*
  * Hedgewars, a free turn based strategy game
- * Copyright (c) 2004-2012 Andrey Korotaev <unC0Rr@gmail.com>
+ * Copyright (c) 2004-2013 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
--- a/QTfrontend/ui/page/pagegamestats.cpp	Thu Apr 04 14:37:19 2013 +0200
+++ b/QTfrontend/ui/page/pagegamestats.cpp	Tue Jun 04 22:28:12 2013 +0200
@@ -1,6 +1,6 @@
 /*
  * Hedgewars, a free turn based strategy game
- * Copyright (c) 2004-2012 Andrey Korotaev <unC0Rr@gmail.com>
+ * Copyright (c) 2004-2013 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
@@ -97,13 +97,26 @@
     return pageLayout;
 }
 
+//TODO button placement, image etc
 QLayout * PageGameStats::footerLayoutDefinition()
 {
     QHBoxLayout * bottomLayout = new QHBoxLayout();
+    
+    mainNote = new QLabel(this);
+    mainNote->setAlignment(Qt::AlignHCenter | Qt::AlignVCenter);
+    mainNote->setWordWrap(true);
+    
+    bottomLayout->addWidget(mainNote, 0);
+    bottomLayout->setStretch(0,1);
 
-    btnSave = addButton(":/res/Save.png", bottomLayout, 0, true);
+    btnRestart = addButton(":/res/Start.png", bottomLayout, 1, true);
+    btnRestart->setWhatsThis(tr("Play again"));
+    btnRestart->setFixedWidth(58);
+    btnRestart->setFixedHeight(81);
+    btnRestart->setStyleSheet("QPushButton{margin-top:24px}");
+    btnSave = addButton(":/res/Save.png", bottomLayout, 2, true);
+    btnSave->setWhatsThis(tr("Save"));
     btnSave->setStyleSheet("QPushButton{margin: 24px 0 0 0;}");
-    bottomLayout->setAlignment(btnSave, Qt::AlignRight | Qt::AlignBottom);
 
     return bottomLayout;
 }
@@ -112,6 +125,7 @@
 {
     connect(this, SIGNAL(pageEnter()), this, SLOT(renderStats()));
     connect(btnSave, SIGNAL(clicked()), this, SIGNAL(saveDemoRequested()));
+    connect(btnRestart, SIGNAL(clicked()), this, SIGNAL(restartGameRequested()));
 }
 
 PageGameStats::PageGameStats(QWidget* parent) : AbstractPage(parent)
@@ -133,6 +147,11 @@
     lastColor = 0;
 }
 
+void PageGameStats::restartBtnVisible(bool visible)
+{
+    btnRestart->setVisible(visible);
+}
+
 void PageGameStats::renderStats()
 {
     QGraphicsScene * scene = new QGraphicsScene();
--- a/QTfrontend/ui/page/pagegamestats.h	Thu Apr 04 14:37:19 2013 +0200
+++ b/QTfrontend/ui/page/pagegamestats.h	Tue Jun 04 22:28:12 2013 +0200
@@ -1,6 +1,6 @@
 /*
  * Hedgewars, a free turn based strategy game
- * Copyright (c) 2004-2012 Andrey Korotaev <unC0Rr@gmail.com>
+ * Copyright (c) 2004-2013 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
@@ -44,6 +44,8 @@
         PageGameStats(QWidget* parent = 0);
 
         QPushButton *btnSave;
+        QPushButton *btnRestart;
+        QLabel *mainNote;
         QLabel *labelGameStats;
         QLabel *labelGameWin;
         QLabel *labelGameRank;
@@ -53,9 +55,11 @@
         void GameStats(char type, const QString & info);
         void clear();
         void renderStats();
+        void restartBtnVisible(bool visible);
 
     signals:
         void saveDemoRequested();
+        void restartGameRequested();
 
     private:
         void AddStatText(const QString & msg);
--- a/QTfrontend/ui/page/pageinfo.cpp	Thu Apr 04 14:37:19 2013 +0200
+++ b/QTfrontend/ui/page/pageinfo.cpp	Tue Jun 04 22:28:12 2013 +0200
@@ -1,6 +1,6 @@
 /*
  * Hedgewars, a free turn based strategy game
- * Copyright (c) 2004-2012 Andrey Korotaev <unC0Rr@gmail.com>
+ * Copyright (c) 2004-2013 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
--- a/QTfrontend/ui/page/pageinfo.h	Thu Apr 04 14:37:19 2013 +0200
+++ b/QTfrontend/ui/page/pageinfo.h	Tue Jun 04 22:28:12 2013 +0200
@@ -1,6 +1,6 @@
 /*
  * Hedgewars, a free turn based strategy game
- * Copyright (c) 2004-2012 Andrey Korotaev <unC0Rr@gmail.com>
+ * Copyright (c) 2004-2013 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
--- a/QTfrontend/ui/page/pageingame.cpp	Thu Apr 04 14:37:19 2013 +0200
+++ b/QTfrontend/ui/page/pageingame.cpp	Tue Jun 04 22:28:12 2013 +0200
@@ -1,6 +1,6 @@
 /*
  * Hedgewars, a free turn based strategy game
- * Copyright (c) 2004-2012 Andrey Korotaev <unC0Rr@gmail.com>
+ * Copyright (c) 2004-2013 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
--- a/QTfrontend/ui/page/pageingame.h	Thu Apr 04 14:37:19 2013 +0200
+++ b/QTfrontend/ui/page/pageingame.h	Tue Jun 04 22:28:12 2013 +0200
@@ -1,6 +1,6 @@
 /*
  * Hedgewars, a free turn based strategy game
- * Copyright (c) 2004-2012 Andrey Korotaev <unC0Rr@gmail.com>
+ * Copyright (c) 2004-2013 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
--- a/QTfrontend/ui/page/pagemain.cpp	Thu Apr 04 14:37:19 2013 +0200
+++ b/QTfrontend/ui/page/pagemain.cpp	Tue Jun 04 22:28:12 2013 +0200
@@ -1,6 +1,6 @@
 /*
  * Hedgewars, a free turn based strategy game
- * Copyright (c) 2004-2012 Andrey Korotaev <unC0Rr@gmail.com>
+ * Copyright (c) 2004-2013 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
@@ -120,8 +120,8 @@
 void PageMain::connectSignals()
 {
     connect(BtnNet, SIGNAL(clicked()), this, SLOT(toggleNetworkChoice()));
-    connect(BtnNetLocal, SIGNAL(clicked()), this, SLOT(toggleNetworkChoice()));
-    connect(BtnNetOfficial, SIGNAL(clicked()), this, SLOT(toggleNetworkChoice()));
+    //connect(BtnNetLocal, SIGNAL(clicked()), this, SLOT(toggleNetworkChoice()));
+    //connect(BtnNetOfficial, SIGNAL(clicked()), this, SLOT(toggleNetworkChoice()));
     // TODO: add signal-forwarding required by (currently missing) encapsulation
 }
 
@@ -136,7 +136,7 @@
 #ifdef DEBUG
     setDefaultDescription(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!"));
 #else
-    setDefaultDescription(QLabel::tr("Tip: ") + randomTip());
+    setDefaultDescription(QLabel::tr("Tip: %1").arg(randomTip()));
 #endif
 
 }
@@ -189,3 +189,10 @@
     if (visible)    BtnNet->setIcon(originalNetworkIcon);
     else            BtnNet->setIcon(disabledNetworkIcon);
 }
+
+void PageMain::resetNetworkChoice()
+{
+    BtnNetLocal->setVisible(false);
+    BtnNetOfficial->setVisible(false);
+    BtnNet->setIcon(originalNetworkIcon);
+}
--- a/QTfrontend/ui/page/pagemain.h	Thu Apr 04 14:37:19 2013 +0200
+++ b/QTfrontend/ui/page/pagemain.h	Tue Jun 04 22:28:12 2013 +0200
@@ -1,6 +1,6 @@
 /*
  * Hedgewars, a free turn based strategy game
- * Copyright (c) 2004-2012 Andrey Korotaev <unC0Rr@gmail.com>
+ * Copyright (c) 2004-2013 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
@@ -29,6 +29,7 @@
 
     public:
         PageMain(QWidget * parent = 0);
+        void resetNetworkChoice();
 
         QPushButton * BtnSinglePlayer;
         QPushButton * BtnNet;
--- a/QTfrontend/ui/page/pagemultiplayer.cpp	Thu Apr 04 14:37:19 2013 +0200
+++ b/QTfrontend/ui/page/pagemultiplayer.cpp	Tue Jun 04 22:28:12 2013 +0200
@@ -1,6 +1,6 @@
 /*
  * Hedgewars, a free turn based strategy game
- * Copyright (c) 2004-2012 Andrey Korotaev <unC0Rr@gmail.com>
+ * Copyright (c) 2004-2013 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
@@ -31,15 +31,13 @@
 
 QLayout * PageMultiplayer::bodyLayoutDefinition()
 {
-    QGridLayout * pageLayout = new QGridLayout();
+    QHBoxLayout * pageLayout = new QHBoxLayout();
 
     gameCFG = new GameCFGWidget(this);
-    pageLayout->addWidget(gameCFG, 0, 0, 1, 2);
-
-    pageLayout->setRowStretch(2, 1);
+    pageLayout->addWidget(gameCFG, 3, Qt::AlignTop);
 
     teamsSelect = new TeamSelWidget(this);
-    pageLayout->addWidget(teamsSelect, 0, 2, 3, 2);
+    pageLayout->addWidget(teamsSelect, 2, Qt::AlignTop);
 
     return pageLayout;
 }
--- a/QTfrontend/ui/page/pagemultiplayer.h	Thu Apr 04 14:37:19 2013 +0200
+++ b/QTfrontend/ui/page/pagemultiplayer.h	Tue Jun 04 22:28:12 2013 +0200
@@ -1,6 +1,6 @@
 /*
  * Hedgewars, a free turn based strategy game
- * Copyright (c) 2004-2012 Andrey Korotaev <unC0Rr@gmail.com>
+ * Copyright (c) 2004-2013 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
--- a/QTfrontend/ui/page/pagenet.cpp	Thu Apr 04 14:37:19 2013 +0200
+++ b/QTfrontend/ui/page/pagenet.cpp	Tue Jun 04 22:28:12 2013 +0200
@@ -1,6 +1,6 @@
 /*
  * Hedgewars, a free turn based strategy game
- * Copyright (c) 2004-2012 Andrey Korotaev <unC0Rr@gmail.com>
+ * Copyright (c) 2004-2013 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
--- a/QTfrontend/ui/page/pagenet.h	Thu Apr 04 14:37:19 2013 +0200
+++ b/QTfrontend/ui/page/pagenet.h	Tue Jun 04 22:28:12 2013 +0200
@@ -1,6 +1,6 @@
 /*
  * Hedgewars, a free turn based strategy game
- * Copyright (c) 2004-2012 Andrey Korotaev <unC0Rr@gmail.com>
+ * Copyright (c) 2004-2013 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
--- a/QTfrontend/ui/page/pagenetgame.cpp	Thu Apr 04 14:37:19 2013 +0200
+++ b/QTfrontend/ui/page/pagenetgame.cpp	Tue Jun 04 22:28:12 2013 +0200
@@ -1,6 +1,6 @@
 /*
  * Hedgewars, a free turn based strategy game
- * Copyright (c) 2004-2012 Andrey Korotaev <unC0Rr@gmail.com>
+ * Copyright (c) 2004-2013 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
--- a/QTfrontend/ui/page/pagenetgame.h	Thu Apr 04 14:37:19 2013 +0200
+++ b/QTfrontend/ui/page/pagenetgame.h	Tue Jun 04 22:28:12 2013 +0200
@@ -1,6 +1,6 @@
 /*
  * Hedgewars, a free turn based strategy game
- * Copyright (c) 2004-2012 Andrey Korotaev <unC0Rr@gmail.com>
+ * Copyright (c) 2004-2013 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
--- a/QTfrontend/ui/page/pagenetserver.cpp	Thu Apr 04 14:37:19 2013 +0200
+++ b/QTfrontend/ui/page/pagenetserver.cpp	Tue Jun 04 22:28:12 2013 +0200
@@ -1,6 +1,6 @@
 /*
  * Hedgewars, a free turn based strategy game
- * Copyright (c) 2004-2012 Andrey Korotaev <unC0Rr@gmail.com>
+ * Copyright (c) 2004-2013 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
@@ -79,6 +79,16 @@
     BtnShare->setWhatsThis(QPushButton::tr("Click to copy your unique server URL in your clipboard. Send this link to your friends ands and they will be able to join you."));
     gbLayout->addWidget(BtnShare, 2, 1);
 
+    labelURL = new QLabel(gb);
+    labelURL->setText(
+              "<style type=\"text/css\"> a { color: #ffcc00; } </style>"
+              "<div align=\"center\">"
+              "<a href=\"https://code.google.com/p/hedgewars/wiki/HWPlaySchemeSyntax\">" +
+              tr("Click here for details") +
+              "</a></div>");
+    labelURL->setOpenExternalLinks(true);
+    gbLayout->addWidget(labelURL, 3, 1);
+
     return pageLayout;
 }
 
--- a/QTfrontend/ui/page/pagenetserver.h	Thu Apr 04 14:37:19 2013 +0200
+++ b/QTfrontend/ui/page/pagenetserver.h	Tue Jun 04 22:28:12 2013 +0200
@@ -1,6 +1,6 @@
 /*
  * Hedgewars, a free turn based strategy game
- * Copyright (c) 2004-2012 Andrey Korotaev <unC0Rr@gmail.com>
+ * Copyright (c) 2004-2013 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
@@ -32,8 +32,9 @@
         QPushButton *BtnDefault;
         QPushButton *BtnShare;
         QLabel *labelSD;
+        QLabel *labelPort;
+        QLabel *labelURL;
         QLineEdit *leServerDescr;
-        QLabel *labelPort;
         QSpinBox *sbPort;
 
     protected:
--- a/QTfrontend/ui/page/pageoptions.cpp	Thu Apr 04 14:37:19 2013 +0200
+++ b/QTfrontend/ui/page/pageoptions.cpp	Tue Jun 04 22:28:12 2013 +0200
@@ -1,6 +1,6 @@
 /*
  * Hedgewars, a free turn based strategy game
- * Copyright (c) 2004-2012 Andrey Korotaev <unC0Rr@gmail.com>
+ * Copyright (c) 2004-2013 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
@@ -275,11 +275,13 @@
             winLabelX->setFixedWidth(40);
             winLabelX->setAlignment(Qt::AlignCenter);
 
-            windowWidthEdit = new QLineEdit(groupGame);
-            windowWidthEdit->setValidator(new QIntValidator(this));
+            // TODO: less random max. also:
+            // make some min/max-consts, shared with engine?
+            windowWidthEdit = new QSpinBox(groupGame);
+            windowWidthEdit->setRange(640, 102400);
             windowWidthEdit->setFixedSize(55, CBResolution->height());
-            windowHeightEdit = new QLineEdit(groupGame);
-            windowHeightEdit->setValidator(new QIntValidator(this));
+            windowHeightEdit = new QSpinBox(groupGame);
+            windowHeightEdit->setRange(480, 102400);
             windowHeightEdit->setFixedSize(55, CBResolution->height());
 
             winResLayout->addWidget(windowWidthEdit, 0);
@@ -585,13 +587,19 @@
             CBLanguage = new QComboBox(groupMisc);
             groupMisc->layout()->addWidget(CBLanguage, 0, 1);
             QStringList locs = DataManager::instance().entryList("Locale", QDir::Files, QStringList("hedgewars_*.qm"));
-            CBLanguage->addItem(QComboBox::tr("(System default)"), QString(""));
+            CBLanguage->addItem(QComboBox::tr("(System default)"), QString());
             for(int i = 0; i < locs.count(); i++)
             {
-                QLocale loc(locs[i].replace(QRegExp("hedgewars_(.*)\\.qm"), "\\1"));
-                CBLanguage->addItem(QLocale::languageToString(loc.language()) + " (" + QLocale::countryToString(loc.country()) + ")", loc.name());
+                QString lname = locs[i].replace(QRegExp("hedgewars_(.*)\\.qm"), "\\1");
+                QLocale loc(lname);
+                CBLanguage->addItem(QLocale::languageToString(loc.language()) + " (" + QLocale::countryToString(loc.country()) + ")", lname);
             }
 
+            QLabel *restartNoticeLabel = new QLabel(groupMisc);
+            restartNoticeLabel->setText(QLabel::tr("This setting will be effective at next restart."));
+            groupMisc->layout()->addWidget(restartNoticeLabel, 1, 1);
+
+
             // Divider
 
             groupMisc->addDivider(); // row 1
@@ -600,14 +608,14 @@
 
             CBNameWithDate = new QCheckBox(groupMisc);
             CBNameWithDate->setText(QCheckBox::tr("Append date and time to record file name"));
-            groupMisc->layout()->addWidget(CBNameWithDate, 2, 0, 1, 2);
+            groupMisc->layout()->addWidget(CBNameWithDate, 3, 0, 1, 2);
 
             // Associate file extensions
 
             BtnAssociateFiles = new QPushButton(groupMisc);
             BtnAssociateFiles->setText(QPushButton::tr("Associate file extensions"));
             BtnAssociateFiles->setVisible(!custom_data && !custom_config);
-            groupMisc->layout()->addWidget(BtnAssociateFiles, 3, 0, 1, 2);
+            groupMisc->layout()->addWidget(BtnAssociateFiles, 4, 0, 1, 2);
         }
 
 #ifdef __APPLE__
--- a/QTfrontend/ui/page/pageoptions.h	Thu Apr 04 14:37:19 2013 +0200
+++ b/QTfrontend/ui/page/pageoptions.h	Tue Jun 04 22:28:12 2013 +0200
@@ -1,6 +1,6 @@
 /*
  * Hedgewars, a free turn based strategy game
- * Copyright (c) 2004-2012 Andrey Korotaev <unC0Rr@gmail.com>
+ * Copyright (c) 2004-2013 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
@@ -77,8 +77,8 @@
         QComboBox *CBTeamName;
         IconedGroupBox *AGGroupBox;
         QComboBox *CBResolution;
-        QLineEdit *windowWidthEdit;
-        QLineEdit *windowHeightEdit;
+        QSpinBox *windowWidthEdit;
+        QSpinBox *windowHeightEdit;
         QComboBox *CBStereoMode;
         QCheckBox *CBFrontendSound;
         QCheckBox *CBFrontendMusic;
--- a/QTfrontend/ui/page/pageplayrecord.cpp	Thu Apr 04 14:37:19 2013 +0200
+++ b/QTfrontend/ui/page/pageplayrecord.cpp	Tue Jun 04 22:28:12 2013 +0200
@@ -1,6 +1,6 @@
 /*
  * Hedgewars, a free turn based strategy game
- * Copyright (c) 2004-2012 Andrey Korotaev <unC0Rr@gmail.com>
+ * Copyright (c) 2004-2013 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
--- a/QTfrontend/ui/page/pageplayrecord.h	Thu Apr 04 14:37:19 2013 +0200
+++ b/QTfrontend/ui/page/pageplayrecord.h	Tue Jun 04 22:28:12 2013 +0200
@@ -1,6 +1,6 @@
 /*
  * Hedgewars, a free turn based strategy game
- * Copyright (c) 2004-2012 Andrey Korotaev <unC0Rr@gmail.com>
+ * Copyright (c) 2004-2013 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
--- a/QTfrontend/ui/page/pageroomslist.cpp	Thu Apr 04 14:37:19 2013 +0200
+++ b/QTfrontend/ui/page/pageroomslist.cpp	Tue Jun 04 22:28:12 2013 +0200
@@ -1,6 +1,6 @@
 /*
  * Hedgewars, a free turn based strategy game
- * Copyright (c) 2004-2012 Andrey Korotaev <unC0Rr@gmail.com>
+ * Copyright (c) 2004-2013 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
@@ -28,6 +28,7 @@
 #include <QGroupBox>
 #include <QMenu>
 #include <QDebug>
+#include <QSplitter>
 
 #include <QSortFilterProxyModel>
 
@@ -107,7 +108,18 @@
     topLayout->setRowStretch(1, 0);
     topLayout->setColumnStretch(3, 1);
 
+    // Rooms list and chat with splitter
+    m_splitter = new QSplitter();
+    m_splitter->setChildrenCollapsible(false);
+    pageLayout->addWidget(m_splitter, 100);
+
     // Room list
+    QWidget * roomsListWidget = new QWidget(this);
+    m_splitter->setOrientation(Qt::Vertical);
+    m_splitter->addWidget(roomsListWidget);
+
+    QVBoxLayout * roomsLayout = new QVBoxLayout(roomsListWidget);
+    roomsLayout->setMargin(0);
 
     roomsList = new RoomTableView(this);
     roomsList->setSelectionBehavior(QAbstractItemView::SelectRows);
@@ -118,7 +130,7 @@
     roomsList->setSelectionMode(QAbstractItemView::SingleSelection);
     roomsList->setStyleSheet("QTableView { border-top-left-radius: 0px; }");
     roomsList->setFocusPolicy(Qt::NoFocus);
-    pageLayout->addWidget(roomsList, 200);
+    roomsLayout->addWidget(roomsList, 200);
 
     // Room filters container
 
@@ -126,9 +138,9 @@
     filtersContainer->setMaximumWidth(800);
     filtersContainer->setSizePolicy(QSizePolicy::Expanding, QSizePolicy::Fixed);
 
-    pageLayout->addSpacing(7);
-    pageLayout->addWidget(filtersContainer, 0, Qt::AlignHCenter);
-    pageLayout->addSpacing(7);
+    roomsLayout->addSpacing(7);
+    roomsLayout->addWidget(filtersContainer, 0, Qt::AlignHCenter);
+    roomsLayout->addSpacing(7);
     
     QHBoxLayout * filterLayout = new QHBoxLayout(filtersContainer);
     filterLayout->setSpacing(0);
@@ -194,7 +206,7 @@
     // Lobby chat
 
     chatWidget = new HWChatWidget(this, false);
-    pageLayout->addWidget(chatWidget, 350);
+    m_splitter->addWidget(chatWidget);
 
     CBRules->addItem(QComboBox::tr("Any"));
 
@@ -251,6 +263,8 @@
 
 void PageRoomsList::roomSelectionChanged(const QModelIndex & current, const QModelIndex & previous)
 {
+    Q_UNUSED(previous);
+
     BtnJoin->setEnabled(current.isValid());
 }
 
@@ -732,14 +746,24 @@
 
 bool PageRoomsList::restoreHeaderState()
 {
-    if (!m_gameSettings->contains("frontend/roomslist_header"))
-        return false;
-    return roomsList->horizontalHeader()->restoreState(QByteArray::fromBase64(
-        (m_gameSettings->value("frontend/roomslist_header").toByteArray())));
+    if (m_gameSettings->contains("frontend/roomslist_splitter"))
+    {
+        m_splitter->restoreState(QByteArray::fromBase64(
+            (m_gameSettings->value("frontend/roomslist_splitter").toByteArray())));
+    }
+
+    if (m_gameSettings->contains("frontend/roomslist_header"))
+    {
+        return roomsList->horizontalHeader()->restoreState(QByteArray::fromBase64(
+            (m_gameSettings->value("frontend/roomslist_header").toByteArray())));
+    } else return false;
 }
 
 void PageRoomsList::saveHeaderState()
 {
     m_gameSettings->setValue("frontend/roomslist_header",
         QString(roomsList->horizontalHeader()->saveState().toBase64()));
+
+    m_gameSettings->setValue("frontend/roomslist_splitter",
+        QString(m_splitter->saveState().toBase64()));
 }
--- a/QTfrontend/ui/page/pageroomslist.h	Thu Apr 04 14:37:19 2013 +0200
+++ b/QTfrontend/ui/page/pageroomslist.h	Tue Jun 04 22:28:12 2013 +0200
@@ -1,6 +1,6 @@
 /*
  * Hedgewars, a free turn based strategy game
- * Copyright (c) 2004-2012 Andrey Korotaev <unC0Rr@gmail.com>
+ * Copyright (c) 2004-2013 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
@@ -27,6 +27,7 @@
 class QTableView;
 class RoomsListModel;
 class QSortFilterProxyModel;
+class QSplitter;
 
 class RoomTableView : public QTableView
 {
@@ -101,6 +102,7 @@
         QSortFilterProxyModel * weaponsFilteredModel;
         QAction * showGamesInLobby;
         QAction * showGamesInProgress;
+        QSplitter * m_splitter;
 
         AmmoSchemeModel * ammoSchemeModel;
 
--- a/QTfrontend/ui/page/pagescheme.cpp	Thu Apr 04 14:37:19 2013 +0200
+++ b/QTfrontend/ui/page/pagescheme.cpp	Tue Jun 04 22:28:12 2013 +0200
@@ -1,6 +1,6 @@
 /*
  * Hedgewars, a free turn based strategy game
- * Copyright (c) 2004-2012 Andrey Korotaev <unC0Rr@gmail.com>
+ * Copyright (c) 2004-2013 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
--- a/QTfrontend/ui/page/pagescheme.h	Thu Apr 04 14:37:19 2013 +0200
+++ b/QTfrontend/ui/page/pagescheme.h	Tue Jun 04 22:28:12 2013 +0200
@@ -1,6 +1,6 @@
 /*
  * Hedgewars, a free turn based strategy game
- * Copyright (c) 2004-2012 Andrey Korotaev <unC0Rr@gmail.com>
+ * Copyright (c) 2004-2013 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
--- a/QTfrontend/ui/page/pageselectweapon.cpp	Thu Apr 04 14:37:19 2013 +0200
+++ b/QTfrontend/ui/page/pageselectweapon.cpp	Tue Jun 04 22:28:12 2013 +0200
@@ -1,6 +1,6 @@
 /*
  * Hedgewars, a free turn based strategy game
- * Copyright (c) 2004-2012 Andrey Korotaev <unC0Rr@gmail.com>
+ * Copyright (c) 2004-2013 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
--- a/QTfrontend/ui/page/pageselectweapon.h	Thu Apr 04 14:37:19 2013 +0200
+++ b/QTfrontend/ui/page/pageselectweapon.h	Tue Jun 04 22:28:12 2013 +0200
@@ -1,6 +1,6 @@
 /*
  * Hedgewars, a free turn based strategy game
- * Copyright (c) 2004-2012 Andrey Korotaev <unC0Rr@gmail.com>
+ * Copyright (c) 2004-2013 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
--- a/QTfrontend/ui/page/pagesingleplayer.cpp	Thu Apr 04 14:37:19 2013 +0200
+++ b/QTfrontend/ui/page/pagesingleplayer.cpp	Tue Jun 04 22:28:12 2013 +0200
@@ -1,6 +1,6 @@
 /*
  * Hedgewars, a free turn based strategy game
- * Copyright (c) 2004-2012 Andrey Korotaev <unC0Rr@gmail.com>
+ * Copyright (c) 2004-2013 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
--- a/QTfrontend/ui/page/pagesingleplayer.h	Thu Apr 04 14:37:19 2013 +0200
+++ b/QTfrontend/ui/page/pagesingleplayer.h	Tue Jun 04 22:28:12 2013 +0200
@@ -1,6 +1,6 @@
 /*
  * Hedgewars, a free turn based strategy game
- * Copyright (c) 2004-2012 Andrey Korotaev <unC0Rr@gmail.com>
+ * Copyright (c) 2004-2013 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
--- a/QTfrontend/ui/page/pagetraining.cpp	Thu Apr 04 14:37:19 2013 +0200
+++ b/QTfrontend/ui/page/pagetraining.cpp	Tue Jun 04 22:28:12 2013 +0200
@@ -1,6 +1,6 @@
 /*
  * Hedgewars, a free turn based strategy game
- * Copyright (c) 2004-2012 Andrey Korotaev <unC0Rr@gmail.com>
+ * Copyright (c) 2004-2013 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
@@ -118,7 +118,7 @@
     DataManager & dataMgr = DataManager::instance();
 
     // get locale
-    QSettings settings("physfs://hedgewars.ini",
+    QSettings settings(dataMgr.settingsFileName(),
                        QSettings::IniFormat);
 
     QString loc = settings.value("misc/locale", "").toString();
--- a/QTfrontend/ui/page/pagetraining.h	Thu Apr 04 14:37:19 2013 +0200
+++ b/QTfrontend/ui/page/pagetraining.h	Tue Jun 04 22:28:12 2013 +0200
@@ -1,6 +1,6 @@
 /*
  * Hedgewars, a free turn based strategy game
- * Copyright (c) 2004-2012 Andrey Korotaev <unC0Rr@gmail.com>
+ * Copyright (c) 2004-2013 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
--- a/QTfrontend/ui/page/pagevideos.cpp	Thu Apr 04 14:37:19 2013 +0200
+++ b/QTfrontend/ui/page/pagevideos.cpp	Tue Jun 04 22:28:12 2013 +0200
@@ -1,6 +1,6 @@
 /*
  * Hedgewars, a free turn based strategy game
- * Copyright (c) 2004-2012 Andrey Korotaev <unC0Rr@gmail.com>
+ * Copyright (c) 2004-2013 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
--- a/QTfrontend/ui/page/pagevideos.h	Thu Apr 04 14:37:19 2013 +0200
+++ b/QTfrontend/ui/page/pagevideos.h	Tue Jun 04 22:28:12 2013 +0200
@@ -1,6 +1,6 @@
 /*
  * Hedgewars, a free turn based strategy game
- * Copyright (c) 2004-2012 Andrey Korotaev <unC0Rr@gmail.com>
+ * Copyright (c) 2004-2013 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
--- a/QTfrontend/ui/widget/FreqSpinBox.cpp	Thu Apr 04 14:37:19 2013 +0200
+++ b/QTfrontend/ui/widget/FreqSpinBox.cpp	Tue Jun 04 22:28:12 2013 +0200
@@ -1,6 +1,6 @@
 /*
  * Hedgewars, a free turn based strategy game
- * Copyright (c) 2004-2012 Andrey Korotaev <unC0Rr@gmail.com>
+ * Copyright (c) 2004-2013 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
--- a/QTfrontend/ui/widget/FreqSpinBox.h	Thu Apr 04 14:37:19 2013 +0200
+++ b/QTfrontend/ui/widget/FreqSpinBox.h	Tue Jun 04 22:28:12 2013 +0200
@@ -1,6 +1,6 @@
 /*
  * Hedgewars, a free turn based strategy game
- * Copyright (c) 2004-2012 Andrey Korotaev <unC0Rr@gmail.com>
+ * Copyright (c) 2004-2013 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
--- a/QTfrontend/ui/widget/HistoryLineEdit.cpp	Thu Apr 04 14:37:19 2013 +0200
+++ b/QTfrontend/ui/widget/HistoryLineEdit.cpp	Tue Jun 04 22:28:12 2013 +0200
@@ -1,7 +1,7 @@
 /*
  * Hedgewars, a free turn based strategy game
  * Copyright (c) 2006-2007 Igor Ulyanov <iulyanov@gmail.com>
- * Copyright (c) 2004-2012 Andrey Korotaev <unC0Rr@gmail.com>
+ * Copyright (c) 2004-2013 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
--- a/QTfrontend/ui/widget/HistoryLineEdit.h	Thu Apr 04 14:37:19 2013 +0200
+++ b/QTfrontend/ui/widget/HistoryLineEdit.h	Tue Jun 04 22:28:12 2013 +0200
@@ -1,7 +1,7 @@
 /*
  * Hedgewars, a free turn based strategy game
  * Copyright (c) 2006-2007 Igor Ulyanov <iulyanov@gmail.com>
- * Copyright (c) 2004-2012 Andrey Korotaev <unC0Rr@gmail.com>
+ * Copyright (c) 2004-2013 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
--- a/QTfrontend/ui/widget/SmartLineEdit.cpp	Thu Apr 04 14:37:19 2013 +0200
+++ b/QTfrontend/ui/widget/SmartLineEdit.cpp	Tue Jun 04 22:28:12 2013 +0200
@@ -1,7 +1,7 @@
 /*
  * Hedgewars, a free turn based strategy game
  * Copyright (c) 2006-2007 Igor Ulyanov <iulyanov@gmail.com>
- * Copyright (c) 2004-2012 Andrey Korotaev <unC0Rr@gmail.com>
+ * Copyright (c) 2004-2013 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
--- a/QTfrontend/ui/widget/SmartLineEdit.h	Thu Apr 04 14:37:19 2013 +0200
+++ b/QTfrontend/ui/widget/SmartLineEdit.h	Tue Jun 04 22:28:12 2013 +0200
@@ -1,7 +1,7 @@
 /*
  * Hedgewars, a free turn based strategy game
  * Copyright (c) 2006-2007 Igor Ulyanov <iulyanov@gmail.com>
- * Copyright (c) 2004-2012 Andrey Korotaev <unC0Rr@gmail.com>
+ * Copyright (c) 2004-2013 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
--- a/QTfrontend/ui/widget/SquareLabel.cpp	Thu Apr 04 14:37:19 2013 +0200
+++ b/QTfrontend/ui/widget/SquareLabel.cpp	Tue Jun 04 22:28:12 2013 +0200
@@ -1,6 +1,6 @@
 /*
  * Hedgewars, a free turn based strategy game
- * Copyright (c) 2004-2012 Andrey Korotaev <unC0Rr@gmail.com>
+ * Copyright (c) 2004-2013 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
--- a/QTfrontend/ui/widget/SquareLabel.h	Thu Apr 04 14:37:19 2013 +0200
+++ b/QTfrontend/ui/widget/SquareLabel.h	Tue Jun 04 22:28:12 2013 +0200
@@ -1,6 +1,6 @@
 /*
  * Hedgewars, a free turn based strategy game
- * Copyright (c) 2004-2012 Andrey Korotaev <unC0Rr@gmail.com>
+ * Copyright (c) 2004-2013 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
--- a/QTfrontend/ui/widget/about.cpp	Thu Apr 04 14:37:19 2013 +0200
+++ b/QTfrontend/ui/widget/about.cpp	Tue Jun 04 22:28:12 2013 +0200
@@ -1,6 +1,6 @@
 /*
  * Hedgewars, a free turn based strategy game
- * Copyright (c) 2004-2012 Andrey Korotaev <unC0Rr@gmail.com>
+ * Copyright (c) 2004-2013 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
--- a/QTfrontend/ui/widget/about.h	Thu Apr 04 14:37:19 2013 +0200
+++ b/QTfrontend/ui/widget/about.h	Tue Jun 04 22:28:12 2013 +0200
@@ -1,6 +1,6 @@
 /*
  * Hedgewars, a free turn based strategy game
- * Copyright (c) 2004-2012 Andrey Korotaev <unC0Rr@gmail.com>
+ * Copyright (c) 2004-2013 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
--- a/QTfrontend/ui/widget/bgwidget.cpp	Thu Apr 04 14:37:19 2013 +0200
+++ b/QTfrontend/ui/widget/bgwidget.cpp	Tue Jun 04 22:28:12 2013 +0200
@@ -1,7 +1,7 @@
 /*
  * Hedgewars, a free turn based strategy game
  * Copyright (c) 2009 Kristian Lehmann <email@thexception.net>
- * Copyright (c) 2004-2012 Andrey Korotaev <unC0Rr@gmail.com>
+ * Copyright (c) 2004-2013 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
--- a/QTfrontend/ui/widget/bgwidget.h	Thu Apr 04 14:37:19 2013 +0200
+++ b/QTfrontend/ui/widget/bgwidget.h	Tue Jun 04 22:28:12 2013 +0200
@@ -1,7 +1,7 @@
 /*
  * Hedgewars, a free turn based strategy game
  * Copyright (c) 2009 Kristian Lehmann <email@thexception.net>
- * Copyright (c) 2004-2012 Andrey Korotaev <unC0Rr@gmail.com>
+ * Copyright (c) 2004-2013 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
--- a/QTfrontend/ui/widget/chatwidget.cpp	Thu Apr 04 14:37:19 2013 +0200
+++ b/QTfrontend/ui/widget/chatwidget.cpp	Tue Jun 04 22:28:12 2013 +0200
@@ -1,7 +1,7 @@
 /*
  * Hedgewars, a free turn based strategy game
  * Copyright (c) 2007 Igor Ulyanov <iulyanov@gmail.com>
- * Copyright (c) 2004-2012 Andrey Korotaev <unC0Rr@gmail.com>
+ * Copyright (c) 2004-2013 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
@@ -295,9 +295,9 @@
 
 void HWChatWidget::linkClicked(const QUrl & link)
 {
-    if (link.scheme() == "http")
+    if ((link.scheme() == "http") or (link.scheme() == "https"))
         QDesktopServices::openUrl(link);
-    if (link.scheme() == "hwnick")
+    else if (link.scheme() == "hwnick")
     {
         // decode nick
         QString nick = QString::fromUtf8(QByteArray::fromBase64(link.encodedQuery()));
@@ -368,15 +368,43 @@
     return QString("<span class=\"nick\">%1</span>").arg(Qt::escape(nickname));
 }
 
+const QRegExp HWChatWidget::URLREGEXP = QRegExp("(http(s)?://)?(www\\.)?((hedgewars\\.org|code\\.google\\.com|googlecode\\.com|hh\\.unit22\\.org)(/[^ ]*)?)");
 
-void HWChatWidget::onChatString(const QString& str)
+bool HWChatWidget::containsHighlight(const QString & sender, const QString & message)
 {
-    onChatString("", str);
+    if ((sender != m_userNick) && (!m_userNick.isEmpty()))
+    {
+        QString lcStr = message.toLower();
+
+        foreach (const QRegExp & hl, m_highlights)
+        {
+            if (lcStr.contains(hl))
+                return true;
+        }
+    }
+    return false;
 }
 
-const QRegExp HWChatWidget::URLREGEXP = QRegExp("(http://)?(www\\.)?(hedgewars\\.org(/[^ ]*)?)");
+QString HWChatWidget::messageToHTML(const QString & message)
+{
+    QString formattedStr = Qt::escape(message);
+    // link some urls
+    formattedStr = formattedStr.replace(URLREGEXP, "<a href=\"http\\2://\\4\">\\4</a>");
+    return formattedStr;
+}
 
-void HWChatWidget::onChatString(const QString& nick, const QString& str)
+void HWChatWidget::onChatAction(const QString & nick, const QString & action)
+{
+    printChatString(nick, "* " + linkedNick(nick) + " " + messageToHTML(action), "Action", containsHighlight(nick, action));
+}
+
+void HWChatWidget::onChatMessage(const QString & nick, const QString & message)
+{
+    printChatString(nick, linkedNick(nick) + ": " + messageToHTML(message), "Chat", containsHighlight(nick, message));
+}
+
+void HWChatWidget::printChatString(
+    const QString & nick, const QString & str, const QString & cssClassPart, bool highlight)
 {
     QSortFilterProxyModel * playersSortFilterModel = qobject_cast<QSortFilterProxyModel *>(chatNicks->model());
     if(!playersSortFilterModel)
@@ -387,58 +415,15 @@
     if(!players)
         return;
 
-    if (!nick.isEmpty())
-    {
-        // don't show chat lines that are from ignored nicks
-        if (players->isFlagSet(nick, PlayersListModel::Ignore))
-            return;
-    }
+    // don't show chat lines that are from ignored nicks
+    if (players->isFlagSet(nick, PlayersListModel::Ignore))
+        return;
 
     bool isFriend = (!nick.isEmpty()) && players->isFlagSet(nick, PlayersListModel::Friend);
 
-    QString formattedStr = Qt::escape(str.mid(1));
-    // make hedgewars.org urls actual links
-    formattedStr = formattedStr.replace(URLREGEXP, "<a href=\"http://\\3\">\\3</a>");
-
-    // link the nick
-    if(!nick.isEmpty())
-        formattedStr.replace("|nick|", linkedNick(nick));
-
-    QString cssClass("msg_UserChat");
+    QString cssClass = (isFriend ? "msg_Friend" : "msg_User") + cssClassPart;
 
-    // check first character for color code and set color properly
-    char c = str[0].toAscii();
-    switch (c)
-    {
-        case 3:
-            cssClass = (isFriend ? "msg_FriendJoin" : "msg_UserJoin");
-            break;
-        case 2:
-            cssClass = (isFriend ? "msg_FriendAction" : "msg_UserAction");
-            break;
-        default:
-            if (isFriend)
-                cssClass = "msg_FriendChat";
-    }
-
-    bool isHL = false;
-
-    if ((c != 3) && (!nick.isEmpty()) &&
-            (nick != m_userNick) && (!m_userNick.isEmpty()))
-    {
-        QString lcStr = str.toLower();
-
-        foreach (const QRegExp & hl, m_highlights)
-        {
-            if (lcStr.contains(hl))
-            {
-                isHL = true;
-                break;
-            }
-        }
-    }
-
-    addLine(cssClass, formattedStr, isHL);
+    addLine(cssClass, str, highlight);
 }
 
 void HWChatWidget::addLine(const QString & cssClass, QString line, bool isHighlight)
@@ -513,6 +498,9 @@
 
     emit nickCountUpdate(chatNicks->model()->rowCount());
 
+    if (!isIgnored)
+        printChatString(nick, QString("*** ") + tr("%1 has joined").arg(linkedNick(nick)), "Join", false);
+
     if (notifyNick && notify && (m_helloSounds.size() > 0))
     {
         SDLInteraction::instance().playSoundFile(
@@ -522,9 +510,19 @@
 
 void HWChatWidget::nickRemoved(const QString& nick)
 {
+    nickRemoved(nick, "");
+}
+
+void HWChatWidget::nickRemoved(const QString& nick, const QString & message)
+{
     chatEditLine->removeNickname(nick);
 
     emit nickCountUpdate(chatNicks->model()->rowCount());
+
+    if (message.isEmpty())
+        printChatString(nick, QString("*** ") + tr("%1 has left").arg(linkedNick(nick)), "Leave", false);
+    else
+        printChatString(nick, QString("*** ") + tr("%1 has left (%2)").arg(linkedNick(nick)).arg(messageToHTML(message)), "Leave", false);
 }
 
 void HWChatWidget::clear()
@@ -583,6 +581,19 @@
     }
 }
 
+void HWChatWidget::onPlayerInfo(
+            const QString & nick,
+            const QString & ip,
+            const QString & version,
+            const QString & roomInfo)
+{
+    addLine("msg_PlayerInfo", QString(" >>> %1 - <span class=\"ipaddress\">%2</span> <span class=\"version\">%3</span> <span class=\"location\">%4</span>")
+        .arg(linkedNick(nick))
+        .arg(ip)
+        .arg(version)
+        .arg(roomInfo));
+}
+
 void HWChatWidget::onKick()
 {
     QModelIndexList mil = chatNicks->selectionModel()->selectedRows();
--- a/QTfrontend/ui/widget/chatwidget.h	Thu Apr 04 14:37:19 2013 +0200
+++ b/QTfrontend/ui/widget/chatwidget.h	Tue Jun 04 22:28:12 2013 +0200
@@ -1,7 +1,7 @@
 /*
  * Hedgewars, a free turn based strategy game
  * Copyright (c) 2007 Igor Ulyanov <iulyanov@gmail.com>
- * Copyright (c) 2004-2012 Andrey Korotaev <unC0Rr@gmail.com>
+ * Copyright (c) 2004-2013 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
@@ -86,14 +86,39 @@
         void beforeContentAdd();
         void afterContentAdd();
 
+        /**
+         * @brief Checks whether the message contains a highlight.
+         * @param sender the sender of the message
+         * @param message the message
+         * @return true if the sender is somebody else and the message contains a highlight, otherwise false
+         */
+        bool containsHighlight(const QString & sender, const QString & message);
+        /**
+         * @brief Escapes HTML chars in the message and converts URls to HTML links.
+         * @param message the message to be converted to HTML
+         * @return the HTML message
+         */
+        QString messageToHTML(const QString & message);
+        void printChatString(
+            const QString & nick,
+            const QString & str,
+            const QString & cssClassPart,
+            bool highlight);
+
     public slots:
-        void onChatString(const QString& str);
-        void onChatString(const QString& nick, const QString& str);
+        void onChatAction(const QString & nick, const QString & str);
+        void onChatMessage(const QString & nick, const QString & str);
         void onServerMessage(const QString& str);
         void nickAdded(const QString& nick, bool notifyNick);
         void nickRemoved(const QString& nick);
+        void nickRemoved(const QString& nick, const QString& message);
         void clear();
         void adminAccess(bool);
+        void onPlayerInfo(
+            const QString & nick,
+            const QString & ip,
+            const QString & version,
+            const QString & roomInfo);
 
     signals:
         void chatLine(const QString& str);
--- a/QTfrontend/ui/widget/databrowser.cpp	Thu Apr 04 14:37:19 2013 +0200
+++ b/QTfrontend/ui/widget/databrowser.cpp	Tue Jun 04 22:28:12 2013 +0200
@@ -1,6 +1,6 @@
 /*
  * Hedgewars, a free turn based strategy game
- * Copyright (c) 2004-2012 Andrey Korotaev <unC0Rr@gmail.com>
+ * Copyright (c) 2004-2013 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
--- a/QTfrontend/ui/widget/databrowser.h	Thu Apr 04 14:37:19 2013 +0200
+++ b/QTfrontend/ui/widget/databrowser.h	Tue Jun 04 22:28:12 2013 +0200
@@ -1,6 +1,6 @@
 /*
  * Hedgewars, a free turn based strategy game
- * Copyright (c) 2004-2012 Andrey Korotaev <unC0Rr@gmail.com>
+ * Copyright (c) 2004-2013 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
--- a/QTfrontend/ui/widget/drawmapwidget.cpp	Thu Apr 04 14:37:19 2013 +0200
+++ b/QTfrontend/ui/widget/drawmapwidget.cpp	Tue Jun 04 22:28:12 2013 +0200
@@ -1,6 +1,6 @@
 /*
  * Hedgewars, a free turn based strategy game
- * Copyright (c) 2004-2012 Andrey Korotaev <unC0Rr@gmail.com>
+ * Copyright (c) 2004-2013 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
--- a/QTfrontend/ui/widget/drawmapwidget.h	Thu Apr 04 14:37:19 2013 +0200
+++ b/QTfrontend/ui/widget/drawmapwidget.h	Tue Jun 04 22:28:12 2013 +0200
@@ -1,6 +1,6 @@
 /*
  * Hedgewars, a free turn based strategy game
- * Copyright (c) 2004-2012 Andrey Korotaev <unC0Rr@gmail.com>
+ * Copyright (c) 2004-2013 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
--- a/QTfrontend/ui/widget/feedbackdialog.cpp	Thu Apr 04 14:37:19 2013 +0200
+++ b/QTfrontend/ui/widget/feedbackdialog.cpp	Tue Jun 04 22:28:12 2013 +0200
@@ -1,6 +1,6 @@
 /*
  * Hedgewars, a free turn based strategy game
- * Copyright (c) 2004-2012 Andrey Korotaev <unC0Rr@gmail.com>
+ * Copyright (c) 2004-2013 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
@@ -44,6 +44,9 @@
 
 #ifdef Q_WS_MAC
 #include <sys/sysctl.h>
+#ifndef _SC_NPROCESSORS_ONLN
+#define _SC_NPROCESSORS_ONLN 58
+#endif
 #endif
 
 #include <stdint.h>
@@ -84,10 +87,10 @@
         "<h4>%3 <a href=\"http://code.google.com/p/hedgewars/wiki/KnownBugs\">known bugs</a><h4>"
         "<h4>%4<h4>"
         "</div>")
-        .arg(tr("Please give us feedback!"))
+        .arg(tr("Send us feedback!"))
         .arg(tr("We are always happy about suggestions, ideas, or bug reports."))
-        .arg(tr("If you found a bug, you can see if it's already known here (english): "))
-        .arg(tr("Your email address is optional, but we may want to contact you."))
+        .arg(tr("If you found a bug, you can see if it's already been reported here: "))
+        .arg(tr("Your email address is optional, but necessary if you want us to get back at you."))
     );
     info->setOpenExternalLinks(true);
     pageLayout->addWidget(info);
@@ -244,12 +247,14 @@
     MEMORYSTATUSEX status;
     status.dwLength = sizeof(status);
     GlobalMemoryStatusEx(&status);
-    total_ram += QString::number(status.ullTotalPhys) + "\n";
+    total_ram += QString::number(status.ullTotalPhys/1024/1024) + " MB\n";
 
-    switch(QSysInfo::WinVersion())
+    switch(QSysInfo::windowsVersion())
     {
+        case QSysInfo::WV_NT: os_version += "Windows NT\n"; break;
         case QSysInfo::WV_2000: os_version += "Windows 2000\n"; break;
         case QSysInfo::WV_XP: os_version += "Windows XP\n"; break;
+        case QSysInfo::WV_2003: os_version += "Windows Server 2003\n"; break;
         case QSysInfo::WV_VISTA: os_version += "Windows Vista\n"; break;
         case QSysInfo::WV_WINDOWS7: os_version += "Windows 7\n"; break;
         //case QSysInfo::WV_WINDOWS8: os_version += "Windows 8\n"; break; //QT 5+
@@ -266,8 +271,8 @@
 #else
          available_pages = 0,
 #endif*/
-         page_size = sysconf(_SC_PAGE_SIZE);
-    total_ram += QString::number(pages * page_size) + "\n";
+    page_size = sysconf(_SC_PAGE_SIZE);
+    total_ram += QString::number(pages*page_size/1024/1024) + " MB\n";
     os_version += "GNU/Linux or BSD\n";
 #endif
 
@@ -281,7 +286,7 @@
     delete process;
 #endif
 
-#if defined(__i386__) || defined(__x86_64__)
+#if (!defined(Q_WS_MACX) && defined(__i386__)) || defined(__x86_64__)
     // cpu info
     quint32 registers[4];
     quint32 i;
@@ -456,7 +461,7 @@
     QString email = this->email->text();
     QString captchaCode = this->captcha_code->text();
     QString captchaID = QString::number(this->captchaID);
-    QString version = "HedgewarsFoundation-Hedgewars-v" + *cVersionString + "_r" + 
+    QString version = "HedgewarsFoundation-Hedgewars-v" + *cVersionString + "_r" +
                        *cRevisionString + "|" + *cHashString;
 
     if (summary.isEmpty() || description.isEmpty())
--- a/QTfrontend/ui/widget/feedbackdialog.h	Thu Apr 04 14:37:19 2013 +0200
+++ b/QTfrontend/ui/widget/feedbackdialog.h	Tue Jun 04 22:28:12 2013 +0200
@@ -1,6 +1,6 @@
 /*
  * Hedgewars, a free turn based strategy game
- * Copyright (c) 2004-2012 Andrey Korotaev <unC0Rr@gmail.com>
+ * Copyright (c) 2004-2013 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
--- a/QTfrontend/ui/widget/fpsedit.cpp	Thu Apr 04 14:37:19 2013 +0200
+++ b/QTfrontend/ui/widget/fpsedit.cpp	Tue Jun 04 22:28:12 2013 +0200
@@ -1,6 +1,6 @@
 /*
  * Hedgewars, a free turn based strategy game
- * Copyright (c) 2004-2012 Andrey Korotaev <unC0Rr@gmail.com>
+ * Copyright (c) 2004-2013 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
--- a/QTfrontend/ui/widget/fpsedit.h	Thu Apr 04 14:37:19 2013 +0200
+++ b/QTfrontend/ui/widget/fpsedit.h	Tue Jun 04 22:28:12 2013 +0200
@@ -1,6 +1,6 @@
 /*
  * Hedgewars, a free turn based strategy game
- * Copyright (c) 2004-2012 Andrey Korotaev <unC0Rr@gmail.com>
+ * Copyright (c) 2004-2013 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
--- a/QTfrontend/ui/widget/frameTeam.cpp	Thu Apr 04 14:37:19 2013 +0200
+++ b/QTfrontend/ui/widget/frameTeam.cpp	Tue Jun 04 22:28:12 2013 +0200
@@ -1,7 +1,7 @@
 /*
  * Hedgewars, a free turn based strategy game
  * Copyright (c) 2006-2007 Igor Ulyanov <iulyanov@gmail.com>
- * Copyright (c) 2004-2012 Andrey Korotaev <unC0Rr@gmail.com>
+ * Copyright (c) 2004-2013 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
--- a/QTfrontend/ui/widget/frameTeam.h	Thu Apr 04 14:37:19 2013 +0200
+++ b/QTfrontend/ui/widget/frameTeam.h	Tue Jun 04 22:28:12 2013 +0200
@@ -1,7 +1,7 @@
 /*
  * Hedgewars, a free turn based strategy game
  * Copyright (c) 2006-2007 Igor Ulyanov <iulyanov@gmail.com>
- * Copyright (c) 2004-2012 Andrey Korotaev <unC0Rr@gmail.com>
+ * Copyright (c) 2004-2013 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
--- a/QTfrontend/ui/widget/gamecfgwidget.cpp	Thu Apr 04 14:37:19 2013 +0200
+++ b/QTfrontend/ui/widget/gamecfgwidget.cpp	Tue Jun 04 22:28:12 2013 +0200
@@ -1,6 +1,6 @@
 /*
  * Hedgewars, a free turn based strategy game
- * Copyright (c) 2004-2012 Andrey Korotaev <unC0Rr@gmail.com>
+ * Copyright (c) 2004-2013 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
@@ -599,7 +599,7 @@
             GameSchemes->setEnabled(false);
             GameSchemes->setCurrentIndex(GameSchemes->findText("Default"));
         }
-        else
+        else if (m_master)
         {
             GameSchemes->setEnabled(true);
             int num = GameSchemes->findText(scheme);
@@ -614,7 +614,7 @@
             WeaponsName->setEnabled(false);
             WeaponsName->setCurrentIndex(WeaponsName->findText("Default"));
         }
-        else
+        else if (m_master)
         {
             WeaponsName->setEnabled(true);
             int num = WeaponsName->findText(weapons);
--- a/QTfrontend/ui/widget/gamecfgwidget.h	Thu Apr 04 14:37:19 2013 +0200
+++ b/QTfrontend/ui/widget/gamecfgwidget.h	Tue Jun 04 22:28:12 2013 +0200
@@ -1,6 +1,6 @@
 /*
  * Hedgewars, a free turn based strategy game
- * Copyright (c) 2004-2012 Andrey Korotaev <unC0Rr@gmail.com>
+ * Copyright (c) 2004-2013 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
--- a/QTfrontend/ui/widget/hatbutton.cpp	Thu Apr 04 14:37:19 2013 +0200
+++ b/QTfrontend/ui/widget/hatbutton.cpp	Tue Jun 04 22:28:12 2013 +0200
@@ -1,6 +1,6 @@
 /*
  * Hedgewars, a free turn based strategy game
- * Copyright (c) 2004-2012 Andrey Korotaev <unC0Rr@gmail.com>
+ * Copyright (c) 2004-2013 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
--- a/QTfrontend/ui/widget/hatbutton.h	Thu Apr 04 14:37:19 2013 +0200
+++ b/QTfrontend/ui/widget/hatbutton.h	Tue Jun 04 22:28:12 2013 +0200
@@ -1,6 +1,6 @@
 /*
  * Hedgewars, a free turn based strategy game
- * Copyright (c) 2004-2012 Andrey Korotaev <unC0Rr@gmail.com>
+ * Copyright (c) 2004-2013 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
--- a/QTfrontend/ui/widget/hatprompt.cpp	Thu Apr 04 14:37:19 2013 +0200
+++ b/QTfrontend/ui/widget/hatprompt.cpp	Tue Jun 04 22:28:12 2013 +0200
@@ -1,6 +1,6 @@
 /*
  * Hedgewars, a free turn based strategy game
- * Copyright (c) 2004-2012 Andrey Korotaev <unC0Rr@gmail.com>
+ * Copyright (c) 2004-2013 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
--- a/QTfrontend/ui/widget/hatprompt.h	Thu Apr 04 14:37:19 2013 +0200
+++ b/QTfrontend/ui/widget/hatprompt.h	Tue Jun 04 22:28:12 2013 +0200
@@ -1,6 +1,6 @@
 /*
  * Hedgewars, a free turn based strategy game
- * Copyright (c) 2004-2012 Andrey Korotaev <unC0Rr@gmail.com>
+ * Copyright (c) 2004-2013 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
--- a/QTfrontend/ui/widget/hedgehogerWidget.cpp	Thu Apr 04 14:37:19 2013 +0200
+++ b/QTfrontend/ui/widget/hedgehogerWidget.cpp	Tue Jun 04 22:28:12 2013 +0200
@@ -1,7 +1,7 @@
 /*
  * Hedgewars, a free turn based strategy game
  * Copyright (c) 2006-2008 Ulyanov Igor <iulyanov@gmail.com>
- * Copyright (c) 2004-2012 Andrey Korotaev <unC0Rr@gmail.com>
+ * Copyright (c) 2004-2013 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
--- a/QTfrontend/ui/widget/hedgehogerWidget.h	Thu Apr 04 14:37:19 2013 +0200
+++ b/QTfrontend/ui/widget/hedgehogerWidget.h	Tue Jun 04 22:28:12 2013 +0200
@@ -1,7 +1,7 @@
 /*
  * Hedgewars, a free turn based strategy game
  * Copyright (c) 2006-2007 Ulyanov Igor <iulyanov@gmail.com>
- * Copyright (c) 2004-2012 Andrey Korotaev <unC0Rr@gmail.com>
+ * Copyright (c) 2004-2013 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
--- a/QTfrontend/ui/widget/igbox.cpp	Thu Apr 04 14:37:19 2013 +0200
+++ b/QTfrontend/ui/widget/igbox.cpp	Tue Jun 04 22:28:12 2013 +0200
@@ -1,6 +1,6 @@
 /*
  * Hedgewars, a free turn based strategy game
- * Copyright (c) 2004-2012 Andrey Korotaev <unC0Rr@gmail.com>
+ * Copyright (c) 2004-2013 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
--- a/QTfrontend/ui/widget/igbox.h	Thu Apr 04 14:37:19 2013 +0200
+++ b/QTfrontend/ui/widget/igbox.h	Tue Jun 04 22:28:12 2013 +0200
@@ -1,6 +1,6 @@
 /*
  * Hedgewars, a free turn based strategy game
- * Copyright (c) 2004-2012 Andrey Korotaev <unC0Rr@gmail.com>
+ * Copyright (c) 2004-2013 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
--- a/QTfrontend/ui/widget/keybinder.cpp	Thu Apr 04 14:37:19 2013 +0200
+++ b/QTfrontend/ui/widget/keybinder.cpp	Tue Jun 04 22:28:12 2013 +0200
@@ -1,6 +1,6 @@
 /*
  * Hedgewars, a free turn based strategy game
- * Copyright (c) 2004-2012 Andrey Korotaev <unC0Rr@gmail.com>
+ * Copyright (c) 2004-2013 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
--- a/QTfrontend/ui/widget/keybinder.h	Thu Apr 04 14:37:19 2013 +0200
+++ b/QTfrontend/ui/widget/keybinder.h	Tue Jun 04 22:28:12 2013 +0200
@@ -1,6 +1,6 @@
 /*
  * Hedgewars, a free turn based strategy game
- * Copyright (c) 2004-2012 Andrey Korotaev <unC0Rr@gmail.com>
+ * Copyright (c) 2004-2013 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
--- a/QTfrontend/ui/widget/lineeditcursor.cpp	Thu Apr 04 14:37:19 2013 +0200
+++ b/QTfrontend/ui/widget/lineeditcursor.cpp	Tue Jun 04 22:28:12 2013 +0200
@@ -1,6 +1,6 @@
 /*
  * Hedgewars, a free turn based strategy game
- * Copyright (c) 2004-2012 Andrey Korotaev <unC0Rr@gmail.com>
+ * Copyright (c) 2004-2013 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
--- a/QTfrontend/ui/widget/lineeditcursor.h	Thu Apr 04 14:37:19 2013 +0200
+++ b/QTfrontend/ui/widget/lineeditcursor.h	Tue Jun 04 22:28:12 2013 +0200
@@ -1,6 +1,6 @@
 /*
  * Hedgewars, a free turn based strategy game
- * Copyright (c) 2004-2012 Andrey Korotaev <unC0Rr@gmail.com>
+ * Copyright (c) 2004-2013 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
--- a/QTfrontend/ui/widget/mapContainer.cpp	Thu Apr 04 14:37:19 2013 +0200
+++ b/QTfrontend/ui/widget/mapContainer.cpp	Tue Jun 04 22:28:12 2013 +0200
@@ -75,8 +75,11 @@
 
     /* Layouts */
 
-    QHBoxLayout * typeLayout = new QHBoxLayout();
-    QHBoxLayout * seedLayout = new QHBoxLayout();
+    QWidget * topWidget = new QWidget();
+    QHBoxLayout * topLayout = new QHBoxLayout(topWidget);
+    topWidget->setContentsMargins(0, 0, 0, 0);
+    topLayout->setContentsMargins(0, 0, 0, 0);
+
     QHBoxLayout * twoColumnLayout = new QHBoxLayout();
     QVBoxLayout * leftLayout = new QVBoxLayout();
     QVBoxLayout * rightLayout = new QVBoxLayout();
@@ -84,15 +87,13 @@
     twoColumnLayout->addStretch(1);
     twoColumnLayout->addLayout(rightLayout, 0);
     QVBoxLayout * drawnControls = new QVBoxLayout();
-    leftLayout->addLayout(typeLayout, 0);
-    rightLayout->addLayout(seedLayout, 0);
 
     /* Map type combobox */
 
-    typeLayout->setSpacing(10);
-    typeLayout->addWidget(new QLabel(tr("Map type:")), 0);
+    topLayout->setSpacing(10);
+    topLayout->addWidget(new QLabel(tr("Map type:")), 0);
     cType = new QComboBox(this);
-    typeLayout->addWidget(cType, 1);
+    topLayout->addWidget(cType, 1);
     cType->insertItem(0, tr("Image map"), MapModel::StaticMap);
     cType->insertItem(1, tr("Mission map"), MapModel::MissionMap);
     cType->insertItem(2, tr("Hand-drawn"), MapModel::HandDrawnMap);
@@ -103,7 +104,7 @@
 
     /* Randomize button */
 
-    seedLayout->addStretch(1);
+    topLayout->addStretch(1);
     const QIcon& lp = QIcon(":/res/dice.png");
     QSize sz = lp.actualSize(QSize(65535, 65535));
     btnRandomize = new QPushButton();
@@ -117,15 +118,16 @@
     m_childWidgets << btnRandomize;
     btnRandomize->setStyleSheet("padding: 5px;");
     btnRandomize->setFixedHeight(cType->height());
-    seedLayout->addWidget(btnRandomize, 1);
+    topLayout->addWidget(btnRandomize, 1);
 
     /* Seed button */
+
     btnSeed = new QPushButton(parentWidget()->parentWidget());
     btnSeed->setText(tr("Seed"));
     btnSeed->setStyleSheet("padding: 5px;");
     btnSeed->setFixedHeight(cType->height());
     connect(btnSeed, SIGNAL(clicked()), this, SLOT(showSeedPrompt()));
-    seedLayout->addWidget(btnSeed, 0);
+    topLayout->addWidget(btnSeed, 0);
 
     /* Map preview label */
 
@@ -137,6 +139,7 @@
 
     mapPreview = new QPushButton(this);
     mapPreview->setObjectName("mapPreview");
+    mapPreview->setFlat(true);
     mapPreview->setFixedSize(256, 128);
     mapPreview->setContentsMargins(0, 0, 0, 0);
     leftLayout->addWidget(mapPreview, 0);
@@ -240,13 +243,15 @@
     /* Theme chooser */
 
     btnTheme = new QPushButton();
+    btnTheme->setFlat(true);
     connect(btnTheme, SIGNAL(clicked()), this, SLOT(showThemePrompt()));
     m_childWidgets << btnTheme;
     bottomLeftLayout->addWidget(btnTheme, 0);
 
     /* Add everything to main layout */
 
-    mainLayout.addLayout(twoColumnLayout, 0);
+    mainLayout.addWidget(topWidget, 0);
+    mainLayout.addLayout(twoColumnLayout, 1);
 
     /* Set defaults */
 
@@ -463,7 +468,7 @@
 void HWMapContainer::setRandomMap()
 {
     if (!m_master) return;
-    
+
     setRandomSeed();
     switch(m_mapInfo.type)
     {
@@ -796,7 +801,7 @@
     btnTheme->setFixedHeight(64);
     btnTheme->setIconSize(iconSize);
     btnTheme->setIcon(icon);
-    btnTheme->setText(tr("Theme: ") + current.data(Qt::DisplayRole).toString());
+    btnTheme->setText(tr("Theme: %1").arg(current.data(Qt::DisplayRole).toString()));
     updateThemeButtonSize();
 }
 
@@ -927,5 +932,5 @@
 
     m_theme = name;
     btnTheme->setIcon(QIcon());
-    btnTheme->setText(tr("Theme: ") + name);
+    btnTheme->setText(tr("Theme: %1").arg(name));
 }
--- a/QTfrontend/ui/widget/mapContainer.h	Thu Apr 04 14:37:19 2013 +0200
+++ b/QTfrontend/ui/widget/mapContainer.h	Tue Jun 04 22:28:12 2013 +0200
@@ -1,7 +1,7 @@
 /*
  * Hedgewars, a free turn based strategy game
  * Copyright (c) 2006-2007 Igor Ulyanov <iulyanov@gmail.com>
- * Copyright (c) 2004-2012 Andrey Korotaev <unC0Rr@gmail.com>
+ * Copyright (c) 2004-2013 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
--- a/QTfrontend/ui/widget/qpushbuttonwithsound.cpp	Thu Apr 04 14:37:19 2013 +0200
+++ b/QTfrontend/ui/widget/qpushbuttonwithsound.cpp	Tue Jun 04 22:28:12 2013 +0200
@@ -1,6 +1,6 @@
 /*
  * Hedgewars, a free turn based strategy game
- * Copyright (c) 2004-2012 Andrey Korotaev <unC0Rr@gmail.com>
+ * Copyright (c) 2004-2013 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
--- a/QTfrontend/ui/widget/qpushbuttonwithsound.h	Thu Apr 04 14:37:19 2013 +0200
+++ b/QTfrontend/ui/widget/qpushbuttonwithsound.h	Tue Jun 04 22:28:12 2013 +0200
@@ -1,6 +1,6 @@
 /*
  * Hedgewars, a free turn based strategy game
- * Copyright (c) 2004-2012 Andrey Korotaev <unC0Rr@gmail.com>
+ * Copyright (c) 2004-2013 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
--- a/QTfrontend/ui/widget/roomnameprompt.cpp	Thu Apr 04 14:37:19 2013 +0200
+++ b/QTfrontend/ui/widget/roomnameprompt.cpp	Tue Jun 04 22:28:12 2013 +0200
@@ -1,6 +1,6 @@
 /*
  * Hedgewars, a free turn based strategy game
- * Copyright (c) 2004-2012 Andrey Korotaev <unC0Rr@gmail.com>
+ * Copyright (c) 2004-2013 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
--- a/QTfrontend/ui/widget/roomnameprompt.h	Thu Apr 04 14:37:19 2013 +0200
+++ b/QTfrontend/ui/widget/roomnameprompt.h	Tue Jun 04 22:28:12 2013 +0200
@@ -1,6 +1,6 @@
 /*
  * Hedgewars, a free turn based strategy game
- * Copyright (c) 2004-2012 Andrey Korotaev <unC0Rr@gmail.com>
+ * Copyright (c) 2004-2013 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
--- a/QTfrontend/ui/widget/seedprompt.cpp	Thu Apr 04 14:37:19 2013 +0200
+++ b/QTfrontend/ui/widget/seedprompt.cpp	Tue Jun 04 22:28:12 2013 +0200
@@ -1,6 +1,6 @@
 /*
  * Hedgewars, a free turn based strategy game
- * Copyright (c) 2004-2012 Andrey Korotaev <unC0Rr@gmail.com>
+ * Copyright (c) 2004-2013 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
--- a/QTfrontend/ui/widget/seedprompt.h	Thu Apr 04 14:37:19 2013 +0200
+++ b/QTfrontend/ui/widget/seedprompt.h	Tue Jun 04 22:28:12 2013 +0200
@@ -1,6 +1,6 @@
 /*
  * Hedgewars, a free turn based strategy game
- * Copyright (c) 2004-2012 Andrey Korotaev <unC0Rr@gmail.com>
+ * Copyright (c) 2004-2013 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
--- a/QTfrontend/ui/widget/selectWeapon.cpp	Thu Apr 04 14:37:19 2013 +0200
+++ b/QTfrontend/ui/widget/selectWeapon.cpp	Tue Jun 04 22:28:12 2013 +0200
@@ -1,7 +1,7 @@
 /*
  * Hedgewars, a free turn based strategy game
  * Copyright (c) 2006-2008 Igor Ulyanov <iulyanov@gmail.com>
- * Copyright (c) 2004-2012 Andrey Korotaev <unC0Rr@gmail.com>
+ * Copyright (c) 2004-2013 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
--- a/QTfrontend/ui/widget/selectWeapon.h	Thu Apr 04 14:37:19 2013 +0200
+++ b/QTfrontend/ui/widget/selectWeapon.h	Tue Jun 04 22:28:12 2013 +0200
@@ -1,7 +1,7 @@
 /*
  * Hedgewars, a free turn based strategy game
  * Copyright (c) 2006-2008 Igor Ulyanov <iulyanov@gmail.com>
- * Copyright (c) 2004-2012 Andrey Korotaev <unC0Rr@gmail.com>
+ * Copyright (c) 2004-2013 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
--- a/QTfrontend/ui/widget/teamselect.cpp	Thu Apr 04 14:37:19 2013 +0200
+++ b/QTfrontend/ui/widget/teamselect.cpp	Tue Jun 04 22:28:12 2013 +0200
@@ -1,7 +1,7 @@
 /*
  * Hedgewars, a free turn based strategy game
  * Copyright (c) 2006-2007 Igor Ulyanov <iulyanov@gmail.com>
- * Copyright (c) 2004-2012 Andrey Korotaev <unC0Rr@gmail.com>
+ * Copyright (c) 2004-2013 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
@@ -38,7 +38,9 @@
         curPlayingTeams.push_back(team);
         connect(framePlaying->getTeamWidget(team), SIGNAL(hhNmChanged(const HWTeam&)),
                 this, SLOT(hhNumChanged(const HWTeam&)));
+        blockSignals(true);
         dynamic_cast<TeamShowWidget*>(framePlaying->getTeamWidget(team))->hhNumChanged();
+        blockSignals(false);
         connect(framePlaying->getTeamWidget(team), SIGNAL(teamColorChanged(const HWTeam&)),
                 this, SLOT(proxyTeamColorChanged(const HWTeam&)));
     }
@@ -210,7 +212,9 @@
     {
         connect(framePlaying->getTeamWidget(team), SIGNAL(hhNmChanged(const HWTeam&)),
                 this, SLOT(hhNumChanged(const HWTeam&)));
+        blockSignals(true);
         dynamic_cast<TeamShowWidget*>(framePlaying->getTeamWidget(team))->hhNumChanged();
+        blockSignals(false);
         connect(framePlaying->getTeamWidget(team), SIGNAL(teamColorChanged(const HWTeam&)),
                 this, SLOT(proxyTeamColorChanged(const HWTeam&)));
         emit teamColorChanged(((TeamShowWidget*)framePlaying->getTeamWidget(team))->getTeam());
@@ -258,12 +262,16 @@
 
     // Add notice about number of required teams.
     numTeamNotice = new QLabel(tr("At least two teams are required to play!"));
+    numTeamNotice->setWordWrap(true);
     mainLayout.addWidget(numTeamNotice);
 
     QPalette p;
     p.setColor(QPalette::Window, QColor(0x00, 0x00, 0x00));
     addScrArea(framePlaying, p.color(QPalette::Window).light(105), 150);
     addScrArea(frameDontPlaying, p.color(QPalette::Window).dark(105), 0);
+
+    this->setSizePolicy(QSizePolicy::Preferred, QSizePolicy::Expanding);
+    this->setMinimumWidth(200);
 }
 
 void TeamSelWidget::setAcceptOuter(bool acceptOuter)
--- a/QTfrontend/ui/widget/teamselect.h	Thu Apr 04 14:37:19 2013 +0200
+++ b/QTfrontend/ui/widget/teamselect.h	Tue Jun 04 22:28:12 2013 +0200
@@ -1,7 +1,7 @@
 /*
  * Hedgewars, a free turn based strategy game
  * Copyright (c) 2006-2007 Igor Ulyanov <iulyanov@gmail.com>
- * Copyright (c) 2004-2012 Andrey Korotaev <unC0Rr@gmail.com>
+ * Copyright (c) 2004-2013 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
--- a/QTfrontend/ui/widget/teamselhelper.cpp	Thu Apr 04 14:37:19 2013 +0200
+++ b/QTfrontend/ui/widget/teamselhelper.cpp	Tue Jun 04 22:28:12 2013 +0200
@@ -1,7 +1,7 @@
 /*
  * Hedgewars, a free turn based strategy game
  * Copyright (c) 2006-2007 Igor Ulyanov <iulyanov@gmail.com>
- * Copyright (c) 2004-2012 Andrey Korotaev <unC0Rr@gmail.com>
+ * Copyright (c) 2004-2013 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
--- a/QTfrontend/ui/widget/teamselhelper.h	Thu Apr 04 14:37:19 2013 +0200
+++ b/QTfrontend/ui/widget/teamselhelper.h	Tue Jun 04 22:28:12 2013 +0200
@@ -1,7 +1,7 @@
 /*
  * Hedgewars, a free turn based strategy game
  * Copyright (c) 2006-2007 Igor Ulyanov <iulyanov@gmail.com>
- * Copyright (c) 2004-2012 Andrey Korotaev <unC0Rr@gmail.com>
+ * Copyright (c) 2004-2013 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
--- a/QTfrontend/ui/widget/themeprompt.cpp	Thu Apr 04 14:37:19 2013 +0200
+++ b/QTfrontend/ui/widget/themeprompt.cpp	Tue Jun 04 22:28:12 2013 +0200
@@ -1,6 +1,6 @@
 /*
  * Hedgewars, a free turn based strategy game
- * Copyright (c) 2004-2012 Andrey Korotaev <unC0Rr@gmail.com>
+ * Copyright (c) 2004-2013 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
--- a/QTfrontend/ui/widget/themeprompt.h	Thu Apr 04 14:37:19 2013 +0200
+++ b/QTfrontend/ui/widget/themeprompt.h	Tue Jun 04 22:28:12 2013 +0200
@@ -1,6 +1,6 @@
 /*
  * Hedgewars, a free turn based strategy game
- * Copyright (c) 2004-2012 Andrey Korotaev <unC0Rr@gmail.com>
+ * Copyright (c) 2004-2013 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
--- a/QTfrontend/ui/widget/togglebutton.cpp	Thu Apr 04 14:37:19 2013 +0200
+++ b/QTfrontend/ui/widget/togglebutton.cpp	Tue Jun 04 22:28:12 2013 +0200
@@ -1,7 +1,7 @@
 /*
  * Hedgewars, a free turn based strategy game
  * Copyright (c) 2009 Kristian Lehmann <email@thexception.net>
- * Copyright (c) 2004-2012 Andrey Korotaev <unC0Rr@gmail.com>
+ * Copyright (c) 2004-2013 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
--- a/QTfrontend/ui/widget/togglebutton.h	Thu Apr 04 14:37:19 2013 +0200
+++ b/QTfrontend/ui/widget/togglebutton.h	Tue Jun 04 22:28:12 2013 +0200
@@ -1,7 +1,7 @@
 /*
  * Hedgewars, a free turn based strategy game
  * Copyright (c) 2009 Kristian Lehmann <email@thexception.net>
- * Copyright (c) 2004-2012 Andrey Korotaev <unC0Rr@gmail.com>
+ * Copyright (c) 2004-2013 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
--- a/QTfrontend/ui/widget/vertScrollArea.cpp	Thu Apr 04 14:37:19 2013 +0200
+++ b/QTfrontend/ui/widget/vertScrollArea.cpp	Tue Jun 04 22:28:12 2013 +0200
@@ -1,7 +1,7 @@
 /*
  * Hedgewars, a free turn based strategy game
  * Copyright (c) 2006 Igor Ulyanov <iulyanov@gmail.com>
- * Copyright (c) 2004-2012 Andrey Korotaev <unC0Rr@gmail.com>
+ * Copyright (c) 2004-2013 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
--- a/QTfrontend/ui/widget/vertScrollArea.h	Thu Apr 04 14:37:19 2013 +0200
+++ b/QTfrontend/ui/widget/vertScrollArea.h	Tue Jun 04 22:28:12 2013 +0200
@@ -1,7 +1,7 @@
 /*
  * Hedgewars, a free turn based strategy game
  * Copyright (c) 2006 Igor Ulyanov <iulyanov@gmail.com>
- * Copyright (c) 2004-2012 Andrey Korotaev <unC0Rr@gmail.com>
+ * Copyright (c) 2004-2013 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
--- a/QTfrontend/ui/widget/weaponItem.cpp	Thu Apr 04 14:37:19 2013 +0200
+++ b/QTfrontend/ui/widget/weaponItem.cpp	Tue Jun 04 22:28:12 2013 +0200
@@ -1,7 +1,7 @@
 /*
  * Hedgewars, a free turn based strategy game
  * Copyright (c) 2006-2008 Igor Ulyanov <iulyanov@gmail.com>
- * Copyright (c) 2004-2012 Andrey Korotaev <unC0Rr@gmail.com>
+ * Copyright (c) 2004-2013 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
--- a/QTfrontend/ui/widget/weaponItem.h	Thu Apr 04 14:37:19 2013 +0200
+++ b/QTfrontend/ui/widget/weaponItem.h	Tue Jun 04 22:28:12 2013 +0200
@@ -1,7 +1,7 @@
 /*
  * Hedgewars, a free turn based strategy game
  * Copyright (c) 2006-2008 Igor Ulyanov <iulyanov@gmail.com>
- * Copyright (c) 2004-2012 Andrey Korotaev <unC0Rr@gmail.com>
+ * Copyright (c) 2004-2013 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
--- a/QTfrontend/ui_hwform.cpp	Thu Apr 04 14:37:19 2013 +0200
+++ b/QTfrontend/ui_hwform.cpp	Tue Jun 04 22:28:12 2013 +0200
@@ -1,6 +1,6 @@
 /*
  * Hedgewars, a free turn based strategy game
- * Copyright (c) 2004-2012 Andrey Korotaev <unC0Rr@gmail.com>
+ * Copyright (c) 2004-2013 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
@@ -56,7 +56,7 @@
     HWForm->setMinimumSize(QSize(720, 450));
     QString title = QMainWindow::tr("Hedgewars %1").arg(*cVersionString);
 #ifdef DEBUG
-    title += QMainWindow::tr("-r%1 (%2)").arg(*cRevisionString, *cHashString);
+    title += QString("-r%1 (%2)").arg(*cRevisionString, *cHashString);
 #endif
     HWForm->setWindowTitle(title);
     centralWidget = new QWidget(HWForm);
--- a/QTfrontend/ui_hwform.h	Thu Apr 04 14:37:19 2013 +0200
+++ b/QTfrontend/ui_hwform.h	Tue Jun 04 22:28:12 2013 +0200
@@ -1,6 +1,6 @@
 /*
  * Hedgewars, a free turn based strategy game
- * Copyright (c) 2004-2012 Andrey Korotaev <unC0Rr@gmail.com>
+ * Copyright (c) 2004-2013 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
--- a/QTfrontend/util/DataManager.cpp	Thu Apr 04 14:37:19 2013 +0200
+++ b/QTfrontend/util/DataManager.cpp	Tue Jun 04 22:28:12 2013 +0200
@@ -1,6 +1,6 @@
 /*
  * Hedgewars, a free turn based strategy game
- * Copyright (c) 2004-2012 Andrey Korotaev <unC0Rr@gmail.com>
+ * Copyright (c) 2004-2013 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
@@ -25,6 +25,8 @@
 #include <QStringList>
 #include <QStandardItemModel>
 #include <QFileInfo>
+#include <QSettings>
+#include <QColor>
 
 #include "hwconsts.h"
 #include "HWApplication.h"
@@ -162,6 +164,41 @@
     return m_bindsModel;
 }
 
+QString DataManager::settingsFileName()
+{
+    if(m_settingsFileName.isEmpty())
+    {
+        QFile settingsFile("physfs://settings.ini");
+
+        if(!settingsFile.exists())
+        {
+            QFile oldSettingsFile("physfs://hedgewars.ini");
+
+            settingsFile.open(QFile::WriteOnly);
+            settingsFile.close();
+
+            if(oldSettingsFile.exists())
+            {
+                QSettings sOld(oldSettingsFile.fileName(), QSettings::IniFormat);
+                QSettings sNew(settingsFile.fileName(), QSettings::IniFormat);
+                sNew.setIniCodec("UTF-8");
+
+                foreach(const QString & key, sOld.allKeys())
+                {
+                    if(key.startsWith("colors/color"))
+                        sNew.setValue(key, sOld.value(key).value<QColor>().name());
+                    else
+                        sNew.setValue(key, sOld.value(key));
+                }
+            }
+        }
+
+        m_settingsFileName = settingsFile.fileName();
+    }
+
+    return m_settingsFileName;
+}
+
 void DataManager::reload()
 {
     // removed for now (also code was a bit unclean, could lead to segfault if
--- a/QTfrontend/util/DataManager.h	Thu Apr 04 14:37:19 2013 +0200
+++ b/QTfrontend/util/DataManager.h	Tue Jun 04 22:28:12 2013 +0200
@@ -1,6 +1,6 @@
 /*
  * Hedgewars, a free turn based strategy game
- * Copyright (c) 2004-2012 Andrey Korotaev <unC0Rr@gmail.com>
+ * Copyright (c) 2004-2013 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
@@ -117,6 +117,8 @@
         QStandardItemModel * colorsModel();
         QStandardItemModel * bindsModel();
 
+        QString settingsFileName();
+
         static bool ensureFileExists(const QString & fileName);
 
     public slots:
@@ -148,6 +150,7 @@
         ThemeModel * m_themeModel; ///< theme model instance
         QStandardItemModel * m_colorsModel;
         QStandardItemModel * m_bindsModel;
+        QString m_settingsFileName;
 };
 
 #endif // HEDGEWARS_DATAMANAGER_H
--- a/QTfrontend/util/LibavInteraction.cpp	Thu Apr 04 14:37:19 2013 +0200
+++ b/QTfrontend/util/LibavInteraction.cpp	Tue Jun 04 22:28:12 2013 +0200
@@ -1,6 +1,6 @@
 /*
  * Hedgewars, a free turn based strategy game
- * Copyright (c) 2004-2012 Andrey Korotaev <unC0Rr@gmail.com>
+ * Copyright (c) 2004-2013 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
--- a/QTfrontend/util/LibavInteraction.h	Thu Apr 04 14:37:19 2013 +0200
+++ b/QTfrontend/util/LibavInteraction.h	Tue Jun 04 22:28:12 2013 +0200
@@ -1,6 +1,6 @@
 /*
  * Hedgewars, a free turn based strategy game
- * Copyright (c) 2004-2012 Andrey Korotaev <unC0Rr@gmail.com>
+ * Copyright (c) 2004-2013 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
--- a/QTfrontend/util/MessageDialog.cpp	Thu Apr 04 14:37:19 2013 +0200
+++ b/QTfrontend/util/MessageDialog.cpp	Tue Jun 04 22:28:12 2013 +0200
@@ -1,6 +1,6 @@
 /*
  * Hedgewars, a free turn based strategy game
- * Copyright (c) 2004-2012 Andrey Korotaev <unC0Rr@gmail.com>
+ * Copyright (c) 2004-2013 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
--- a/QTfrontend/util/MessageDialog.h	Thu Apr 04 14:37:19 2013 +0200
+++ b/QTfrontend/util/MessageDialog.h	Tue Jun 04 22:28:12 2013 +0200
@@ -1,6 +1,6 @@
 /*
  * Hedgewars, a free turn based strategy game
- * Copyright (c) 2004-2012 Andrey Korotaev <unC0Rr@gmail.com>
+ * Copyright (c) 2004-2013 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
--- a/QTfrontend/util/SDLInteraction.cpp	Thu Apr 04 14:37:19 2013 +0200
+++ b/QTfrontend/util/SDLInteraction.cpp	Tue Jun 04 22:28:12 2013 +0200
@@ -1,6 +1,6 @@
 /*
  * Hedgewars, a free turn based strategy game
- * Copyright (c) 2004-2012 Andrey Korotaev <unC0Rr@gmail.com>
+ * Copyright (c) 2004-2013 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
--- a/QTfrontend/util/SDLInteraction.h	Thu Apr 04 14:37:19 2013 +0200
+++ b/QTfrontend/util/SDLInteraction.h	Tue Jun 04 22:28:12 2013 +0200
@@ -1,6 +1,6 @@
 /*
  * Hedgewars, a free turn based strategy game
- * Copyright (c) 2004-2012 Andrey Korotaev <unC0Rr@gmail.com>
+ * Copyright (c) 2004-2013 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
--- a/QTfrontend/util/namegen.cpp	Thu Apr 04 14:37:19 2013 +0200
+++ b/QTfrontend/util/namegen.cpp	Tue Jun 04 22:28:12 2013 +0200
@@ -1,7 +1,7 @@
 /*
  * Hedgewars, a free turn based strategy game
  * Copyright (c) 2009 Martin Minarik <ttsmj@pokec.sk>
- * Copyright (c) 2004-2012 Andrey Korotaev <unC0Rr@gmail.com>
+ * Copyright (c) 2004-2013 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
--- a/QTfrontend/util/namegen.h	Thu Apr 04 14:37:19 2013 +0200
+++ b/QTfrontend/util/namegen.h	Tue Jun 04 22:28:12 2013 +0200
@@ -1,7 +1,7 @@
 /*
  * Hedgewars, a free turn based strategy game
  * Copyright (c) 2009 Martin Minarik <ttsmj@pokec.sk>
- * Copyright (c) 2004-2012 Andrey Korotaev <unC0Rr@gmail.com>
+ * Copyright (c) 2004-2013 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
--- a/QTfrontend/util/platform/CocoaInitializer.h	Thu Apr 04 14:37:19 2013 +0200
+++ b/QTfrontend/util/platform/CocoaInitializer.h	Tue Jun 04 22:28:12 2013 +0200
@@ -1,6 +1,6 @@
 /*
  * Hedgewars, a free turn based strategy game
- * Copyright (c) 2004-2012 Andrey Korotaev <unC0Rr@gmail.com>
+ * Copyright (c) 2004-2013 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
--- a/QTfrontend/util/platform/CocoaInitializer.mm	Thu Apr 04 14:37:19 2013 +0200
+++ b/QTfrontend/util/platform/CocoaInitializer.mm	Tue Jun 04 22:28:12 2013 +0200
@@ -1,6 +1,6 @@
 /*
  * Hedgewars, a free turn based strategy game
- * Copyright (c) 2004-2012 Andrey Korotaev <unC0Rr@gmail.com>
+ * Copyright (c) 2004-2013 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
--- a/QTfrontend/util/platform/InstallController.cpp	Thu Apr 04 14:37:19 2013 +0200
+++ b/QTfrontend/util/platform/InstallController.cpp	Tue Jun 04 22:28:12 2013 +0200
@@ -1,6 +1,6 @@
 /*
  * Hedgewars, a free turn based strategy game
- * Copyright (c) 2004-2012 Andrey Korotaev <unC0Rr@gmail.com>
+ * Copyright (c) 2004-2013 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
--- a/QTfrontend/util/platform/InstallController.h	Thu Apr 04 14:37:19 2013 +0200
+++ b/QTfrontend/util/platform/InstallController.h	Tue Jun 04 22:28:12 2013 +0200
@@ -1,6 +1,6 @@
 /*
  * Hedgewars, a free turn based strategy game
- * Copyright (c) 2004-2012 Andrey Korotaev <unC0Rr@gmail.com>
+ * Copyright (c) 2004-2013 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
--- a/QTfrontend/util/platform/M3InstallController.m	Thu Apr 04 14:37:19 2013 +0200
+++ b/QTfrontend/util/platform/M3InstallController.m	Tue Jun 04 22:28:12 2013 +0200
@@ -35,8 +35,8 @@
 
 @implementation M3InstallController
 
-- (id) init {
-        if ((self = [super init])) {
+-(id) init {
+    if ((self = [super init])) {
         NSString *appName = [[NSBundle mainBundle] objectForInfoDictionaryKey:@"CFBundleName"];
         NSString *title = [NSString stringWithFormat:NSLocalizedString(@"%@ is currently running from a disk image", @"AppName is currently running from a disk image"), appName];
         NSString *body = [NSString stringWithFormat:NSLocalizedString(@"Would you like to install %@ in your applications folder before quitting?", @"Would you like to install App Name in your applications folder before quitting?"), appName];
@@ -50,70 +50,91 @@
     return self;
 }
 
-- (void)displayInstaller {
+-(void) displayInstaller {
     NSString *imageFilePath = [[[NSWorkspace sharedWorkspace] propertiesForPath:[[NSBundle mainBundle] bundlePath]] objectForKey:NSWorkspace_RBimagefilepath];
     if (imageFilePath && ![imageFilePath isEqualToString:[NSString stringWithFormat:@"/Users/.%@/%@.sparseimage", NSUserName(), NSUserName()]] && ![[NSUserDefaults standardUserDefaults] boolForKey:@"M3DontAskInstallAgain"]) {
         NSInteger returnValue = [alert runModal];
         if (returnValue == NSAlertDefaultReturn) {
             [self installApp];
         }
-        if ([[alert suppressionButton] state] == NSOnState) {
-            [[NSUserDefaults standardUserDefaults] setBool:YES forKey:@"M3DontAskInstallAgain"];
+        if ([NSAlert instancesRespondToSelector:@selector(suppressionButton)])
+            if ([[alert performSelector:@selector(suppressionButton)] state] == NSOnState)
+                [[NSUserDefaults standardUserDefaults] setBool:YES forKey:@"M3DontAskInstallAgain"];
         }
-    }
 }
 
-- (void)installApp {
+-(void) installApp {
     NSString *appsPath = [[NSString stringWithString:@"/Applications"] stringByAppendingPathComponent:[[[NSBundle mainBundle] bundlePath] lastPathComponent]];
     NSString *userAppsPath = [[[NSString stringWithString:@"~/Applications"] stringByAppendingPathComponent:[[[NSBundle mainBundle] bundlePath] lastPathComponent]] stringByExpandingTildeInPath];
     NSString *appName = [[NSBundle mainBundle] objectForInfoDictionaryKey:@"CFBundleName"];
+    NSString *currentPath = [[NSBundle mainBundle] bundlePath];
+    NSString *finalPath;
+    NSError *error = nil;
+    BOOL success;
 
-    //Delete the app that is installed
+    // Prepare the remove invocation
+    SEL removeSelector;
+    if ([NSFileManager instancesRespondToSelector:@selector(removeItemAtPath:error:)])
+        removeSelector = @selector(removeItemAtPath:error:);
+    else
+        removeSelector = @selector(removeFileAtPath:handler:);
+
+    NSMethodSignature *removeSignature = [NSFileManager instanceMethodSignatureForSelector:removeSelector];
+    NSInvocation *removeInvocation = [NSInvocation invocationWithMethodSignature:removeSignature];
+    [removeInvocation setTarget:[NSFileManager defaultManager]];
+    [removeInvocation setSelector:removeSelector];
+
+    // Delete the app if already installed
     if ([[NSFileManager defaultManager] fileExistsAtPath:appsPath]) {
-        if ([NSFileManager instancesRespondToSelector:@selector(removeItemAtPath:error:)])
-            [[NSFileManager defaultManager] removeItemAtPath:appsPath error:nil];
-        else
-            //casting hides the deprecation warning
-            [(id)[NSFileManager defaultManager] removeFileAtPath:appsPath handler:nil];
+        [removeInvocation setArgument:&appsPath atIndex:2];
+        [removeInvocation setArgument:&error atIndex:3];
+        [removeInvocation invoke];
     }
-    //Delete the app that is installed
-    BOOL success = NO;
+
+    // Prepare the copy invocation
+    SEL copySelector;
     if ([NSFileManager instancesRespondToSelector:@selector(copyItemAtPath:toPath:error:)])
-        success = [[NSFileManager defaultManager] copyItemAtPath:[[NSBundle mainBundle] bundlePath]
-                                                          toPath:appsPath
-                                                           error:nil];
+        copySelector = @selector(copyItemAtPath:toPath:error:);
     else
-        success = [(id)[NSFileManager defaultManager] copyPath:[[NSBundle mainBundle] bundlePath]
-                                                        toPath:appsPath
-                                                       handler:nil];
-    if (success) {
-        NSRunAlertPanel([NSString stringWithFormat:NSLocalizedString(@"%@ installed successfully", @"App Name installed successfully"), appName],
-                        [NSString stringWithFormat:NSLocalizedString(@"%@ was installed in /Applications", @"App Name was installed in /Applications"), appName],
-                        NSLocalizedString(@"Quit", @"Quit"), nil, nil);
-    } else {
+        copySelector = @selector(copyPath:toPath:handler:);
+
+    NSMethodSignature *copySignature = [NSFileManager instanceMethodSignatureForSelector:copySelector];
+    NSInvocation *copyInvocation = [NSInvocation invocationWithMethodSignature:copySignature];
+
+    [copyInvocation setTarget:[NSFileManager defaultManager]];
+    [copyInvocation setSelector:copySelector];
+
+    // Copy the app in /Applications
+    [copyInvocation setArgument:&currentPath atIndex:2];
+    [copyInvocation setArgument:&appsPath atIndex:3];
+    [copyInvocation setArgument:&error atIndex:4];
+    [copyInvocation invoke];
+    [copyInvocation getReturnValue:&success];
+    finalPath = @"/Applications";
+
+    // In case something went wrong, let's try again somewhere else
+    if (success == NO) {
+        // Delete the app if already installed
         if ([[NSFileManager defaultManager] fileExistsAtPath:userAppsPath]) {
-            if ([NSFileManager instancesRespondToSelector:@selector(removeItemAtPath:error:)])
-                [[NSFileManager defaultManager] removeItemAtPath:userAppsPath error:nil];
-            else
-                [(id)[NSFileManager defaultManager] removeFileAtPath:userAppsPath handler:nil];
+            [removeInvocation setArgument:&userAppsPath atIndex:2];
+            [removeInvocation invoke];
         }
-        if ([NSFileManager instancesRespondToSelector:@selector(copyItemAtPath:toPath:error:)])
-            success = [[NSFileManager defaultManager] copyItemAtPath:[[NSBundle mainBundle] bundlePath]
-                                                              toPath:userAppsPath
-                                                               error:nil];
-        else
-            success = [(id)[NSFileManager defaultManager] copyPath:[[NSBundle mainBundle] bundlePath]
-                                                            toPath:userAppsPath
-                                                           handler:nil];
-        if (success) {
-            NSRunAlertPanel([NSString stringWithFormat:NSLocalizedString(@"%@ installed successfully", @"AppName installed successfully"), appName],
-                [NSString stringWithFormat:NSLocalizedString(@"%@ was installed in %@", @"App Name was installed in %@"), appName, [[NSString stringWithString:@"~/Applications"] stringByExpandingTildeInPath]],
-                        NSLocalizedString(@"Quit", @"Quit"), nil, nil);
-        } else {
-            NSRunAlertPanel([NSString stringWithFormat:NSLocalizedString(@"Could not install %@", @"Could not install App Name"), appName],
-                            NSLocalizedString(@"An error occurred when installing", @"An error occurred when installing"), NSLocalizedString(@"Quit", @"Quit"), nil, nil);
-        }
+
+        // Copy the app in ~/Applications
+        [copyInvocation setArgument:&userAppsPath atIndex:3];
+        [copyInvocation invoke];
+        [copyInvocation getReturnValue:&success];
+        finalPath = [[NSString stringWithString:@"~/Applications"] stringByExpandingTildeInPath];
     }
+
+    if (success)
+        NSRunAlertPanel([NSString stringWithFormat:NSLocalizedString(@"%@ installed successfully", @"successful installation title"), appName],
+              [NSString stringWithFormat:NSLocalizedString(@"%@ was installed in %@", @"successfull installation text"), appName, finalPath],
+              NSLocalizedString(@"Ok", @"ok message"), nil, nil);
+    else
+        NSRunAlertPanel([NSString stringWithFormat:NSLocalizedString(@"Could not install %@", @"installation failure title"), appName],
+              NSLocalizedString(@"An error occurred when installing", @"installation failure text"),
+              NSLocalizedString(@"Quit", @"exit message"), nil, nil);
 }
 
 @end
--- a/QTfrontend/util/platform/M3Panel.h	Thu Apr 04 14:37:19 2013 +0200
+++ b/QTfrontend/util/platform/M3Panel.h	Tue Jun 04 22:28:12 2013 +0200
@@ -1,6 +1,6 @@
 /*
  * Hedgewars, a free turn based strategy game
- * Copyright (c) 2004-2012 Andrey Korotaev <unC0Rr@gmail.com>
+ * Copyright (c) 2004-2013 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
--- a/QTfrontend/util/platform/M3Panel.mm	Thu Apr 04 14:37:19 2013 +0200
+++ b/QTfrontend/util/platform/M3Panel.mm	Tue Jun 04 22:28:12 2013 +0200
@@ -1,6 +1,6 @@
 /*
  * Hedgewars, a free turn based strategy game
- * Copyright (c) 2004-2012 Andrey Korotaev <unC0Rr@gmail.com>
+ * Copyright (c) 2004-2013 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
--- a/QTfrontend/util/platform/SparkleAutoUpdater.mm	Thu Apr 04 14:37:19 2013 +0200
+++ b/QTfrontend/util/platform/SparkleAutoUpdater.mm	Tue Jun 04 22:28:12 2013 +0200
@@ -1,6 +1,6 @@
 /*
  * Hedgewars, a free turn based strategy game
- * Copyright (c) 2004-2012 Andrey Korotaev <unC0Rr@gmail.com>
+ * Copyright (c) 2004-2013 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
--- a/QTfrontend/util/platform/xfire.cpp	Thu Apr 04 14:37:19 2013 +0200
+++ b/QTfrontend/util/platform/xfire.cpp	Tue Jun 04 22:28:12 2013 +0200
@@ -1,6 +1,6 @@
 /*
  * Hedgewars, a free turn based strategy game
- * Copyright (c) 2004-2012 Andrey Korotaev <unC0Rr@gmail.com>
+ * Copyright (c) 2004-2013 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
--- a/QTfrontend/util/platform/xfire.h	Thu Apr 04 14:37:19 2013 +0200
+++ b/QTfrontend/util/platform/xfire.h	Tue Jun 04 22:28:12 2013 +0200
@@ -1,6 +1,6 @@
 /*
  * Hedgewars, a free turn based strategy game
- * Copyright (c) 2004-2012 Andrey Korotaev <unC0Rr@gmail.com>
+ * Copyright (c) 2004-2013 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
--- a/QTfrontend/weapons.h	Thu Apr 04 14:37:19 2013 +0200
+++ b/QTfrontend/weapons.h	Tue Jun 04 22:28:12 2013 +0200
@@ -58,9 +58,9 @@
 
 #define AMMOLINE_ONEEVERY_QT    "1111119111111111111111111111111111111111111111111111111"
 #define AMMOLINE_ONEEVERY_PROB  "1111110111111111111111111111111111111111111111111111111"
-#define AMMOLINE_ONEEVERY_DELAY "0000000000000205500000040007004000000000220000000600020"
+#define AMMOLINE_ONEEVERY_DELAY "0000000000000000000000000000000000000000000000000000000"
 #define AMMOLINE_ONEEVERY_CRATE "1111110111111111111111111111111111111111111111111111111"
 
-//When adding new weapons also inster one element in cDefaultAmmos list (hwconsts.cpp.in)
+//When adding new weapons also insert one element in cDefaultAmmos list (hwconsts.cpp.in)
 
 
--- a/README	Thu Apr 04 14:37:19 2013 +0200
+++ b/README	Tue Jun 04 22:28:12 2013 +0200
@@ -3,7 +3,7 @@
 Images and sounds are distributed under the terms of the GNU FDL licence.
 
 Source:
-Copyright 2004-2011 Andrey Korotaev <unC0Rr@gmail.com>
+Copyright 2004-2013 Andrey Korotaev <unC0Rr@gmail.com>
 Portions copyright 2006-2008 Igor Ulyanov aka Displacer <iulyanov@gmail.com>
 
 Instructions:
--- a/cmake_modules/CPackConfig.cmake	Thu Apr 04 14:37:19 2013 +0200
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,99 +0,0 @@
-
-# revision information in cpack-generated names
-if(CMAKE_BUILD_TYPE MATCHES DEBUG)
-    set(full_suffix "${HEDGEWARS_VERSION}-r${HEDGEWARS_REVISION}")
-else()
-    set(full_suffix "${HEDGEWARS_VERSION}")
-endif()
-
-# CPack variables
-set(CPACK_PACKAGE_DESCRIPTION_SUMMARY "Hedgewars, a free turn-based strategy game")
-set(CPACK_PACKAGE_VENDOR "Hedgewars Project")
-set(CPACK_PACKAGE_FILE_NAME "Hedgewars-${full_suffix}")
-set(CPACK_SOURCE_PACKAGE_FILE_NAME "hedgewars-src-${full_suffix}")
-set(CPACK_SOURCE_GENERATOR "TBZ2")
-set(CPACK_PACKAGE_EXECUTABLES "hedgewars" "Hedgewars")
-set(CPACK_RESOURCE_FILE_LICENSE "${CMAKE_SOURCE_DIR}/COPYING")
-set(CPACK_PACKAGE_INSTALL_DIRECTORY "Hedgewars ${full_suffix}")
-set(CPACK_STRIP_FILES true)
-
-if(WIN32 AND NOT UNIX)
-    set(CPACK_NSIS_DISPLAY_NAME "Hedgewars")
-    set(CPACK_NSIS_HELP_LINK "http://www.hedgewars.org/")
-    set(CPACK_NSIS_URL_INFO_ABOUT "http://www.hedgewars.org/")
-    set(CPACK_NSIS_CONTACT "unC0Rr@gmail.com")
-    set(CPACK_NSIS_MODIFY_PATH OFF)
-    set(CPACK_NSIS_EXECUTABLES_DIRECTORY "${target_binary_install_dir}")
-    set(CPACK_NSIS_MUI_FINISHPAGE_RUN "hedgewars${CMAKE_EXECUTABLE_SUFFIX}")
-    set(CPACK_GENERATOR "ZIP;NSIS")
-    set(CPACK_PACKAGE_INSTALL_REGISTRY_KEY "hedgewars")
-endif(WIN32 AND NOT UNIX)
-
-set(CPACK_SOURCE_IGNORE_FILES
-    #temporary files
-    "~"
-    ".swp"
-    #version control
-    "\\\\.hg"
-    #output binary/library
-    "\\\\.exe$"
-    "\\\\.a$"
-    "\\\\.so$"
-    "\\\\.dylib$"
-    "\\\\.dll$"
-    "\\\\.ppu$"
-    "\\\\.o$"
-    "\\\\.cxx$"
-    #graphics
-    "\\\\.xcf$"
-    "\\\\.svg$"
-    "\\\\.svgz$"
-    "\\\\.psd$"
-    "\\\\.sifz$"
-    #misc
-    "\\\\.core$"
-    "\\\\.sh$"
-    "\\\\.orig$"
-    "\\\\.layout$"
-    "\\\\.db$"
-    "\\\\.dof$"
-    #archives
-    "\\\\.zip$"
-    "\\\\.gz$"
-    "\\\\.bz2$"
-    "\\\\.tmp$"
-    #cmake-configured files
-    "hwconsts\\\\.cpp$"
-    "config\\\\.inc$"
-    "hwengine\\\\.desktop$"
-    "Info\\\\.plist$"
-    #other cmake generated files
-    "Makefile"
-    "Doxyfile"
-    "CMakeFiles"
-    "[dD]ebug$"
-    "[rR]elease$"
-    "CPack"
-    "cmake_install\\\\.cmake$"
-    "CMakeCache\\\\.txt$"
-#    "^${CMAKE_CURRENT_SOURCE_DIR}/misc/libtremor"
-#    "^${CMAKE_CURRENT_SOURCE_DIR}/misc/libfreetype"
-#    "^${CMAKE_CURRENT_SOURCE_DIR}/misc/liblua"
-    "^${CMAKE_CURRENT_SOURCE_DIR}/misc/libopenalbridge"
-    "^${CMAKE_CURRENT_SOURCE_DIR}/project_files/frontlib"
-    "^${CMAKE_CURRENT_SOURCE_DIR}/project_files/promotional_art"
-    "^${CMAKE_CURRENT_SOURCE_DIR}/project_files/cmdlineClient"
-    "^${CMAKE_CURRENT_SOURCE_DIR}/tools/templates"
-    "^${CMAKE_CURRENT_SOURCE_DIR}/bin/checkstack*"
-    "^${CMAKE_CURRENT_SOURCE_DIR}/doc"
-    "^${CMAKE_CURRENT_SOURCE_DIR}/templates"
-    "^${CMAKE_CURRENT_SOURCE_DIR}/tmp"
-    "^${CMAKE_CURRENT_SOURCE_DIR}/utils"
-    "^${CMAKE_CURRENT_SOURCE_DIR}/share/hedgewars/Data/Maps/test"
-    "^${CMAKE_CURRENT_SOURCE_DIR}/install_manifest.txt"
-    "^${CMAKE_CURRENT_SOURCE_DIR}/CMakeCache.txt"
-    "^${CMAKE_CURRENT_SOURCE_DIR}/hedgewars\\\\."
-)
-
-include(CPack)
-
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/cmake_modules/cpackvars.cmake	Tue Jun 04 22:28:12 2013 +0200
@@ -0,0 +1,105 @@
+
+# revision information in cpack-generated names
+if(CMAKE_BUILD_TYPE MATCHES DEBUG)
+    set(full_suffix "${HEDGEWARS_VERSION}-r${HEDGEWARS_REVISION}")
+else()
+    set(full_suffix "${HEDGEWARS_VERSION}")
+endif()
+
+# CPack variables
+set(CPACK_PACKAGE_DESCRIPTION_SUMMARY "Hedgewars, a free turn-based strategy game")
+set(CPACK_PACKAGE_VENDOR "Hedgewars Project")
+set(CPACK_PACKAGE_FILE_NAME "Hedgewars-${full_suffix}")
+set(CPACK_SOURCE_PACKAGE_FILE_NAME "hedgewars-src-${full_suffix}")
+set(CPACK_SOURCE_GENERATOR "TBZ2")
+set(CPACK_PACKAGE_EXECUTABLES "hedgewars" "Hedgewars")
+set(CPACK_RESOURCE_FILE_LICENSE "${CMAKE_SOURCE_DIR}/COPYING")
+set(CPACK_PACKAGE_INSTALL_DIRECTORY "Hedgewars ${full_suffix}")
+set(CPACK_STRIP_FILES true)
+
+if(WIN32 AND NOT UNIX)
+    set(CPACK_NSIS_DISPLAY_NAME "Hedgewars")
+    set(CPACK_NSIS_HELP_LINK "http://www.hedgewars.org/")
+    set(CPACK_NSIS_URL_INFO_ABOUT "http://www.hedgewars.org/")
+    set(CPACK_NSIS_CONTACT "unC0Rr@gmail.com")
+    set(CPACK_NSIS_MODIFY_PATH OFF)
+    set(CPACK_NSIS_EXECUTABLES_DIRECTORY ".")
+    set(CPACK_NSIS_MUI_FINISHPAGE_RUN "hedgewars${CMAKE_EXECUTABLE_SUFFIX}")
+    set(CPACK_NSIS_CREATE_ICONS "CreateShortCut '$SMPROGRAMS\\\\$STARTMENU_FOLDER\\\\Hedgewars.lnk' '$INSTDIR\\\\hedgewars.exe'")
+    set(CPACK_PACKAGE_INSTALL_REGISTRY_KEY "hedgewars")
+endif(WIN32 AND NOT UNIX)
+
+set(CPACK_SOURCE_IGNORE_FILES
+    #temporary files
+    "~"
+    ".swp"
+    #version control
+    "\\\\.hg"
+    "\\\\.orig$"
+    #output binary/library
+    "\\\\.exe$"
+    "\\\\.a$"
+    "\\\\.so$"
+    "\\\\.dylib$"
+    "\\\\.dll$"
+    "\\\\.ppu$"
+    "\\\\.o$"
+    "\\\\.cxx$"
+    "\\\\.hi$"
+    #graphics
+    "\\\\.xcf$"
+    "\\\\.svg$"
+    "\\\\.svgz$"
+    "\\\\.psd$"
+    "\\\\.sifz$"
+    #misc
+    "\\\\.core$"
+    "\\\\.layout$"
+    "\\\\.db$"
+    "\\\\.dof$"
+    "\\\\.or$"
+    #archives
+    "\\\\.zip$"
+    "\\\\.gz$"
+    "\\\\.bz2$"
+    "\\\\.tmp$"
+    #cmake-configured files
+    "hwconsts\\\\.cpp$"
+    "config\\\\.inc$"
+    "hwengine\\\\.desktop$"
+    "Info\\\\.plist$"
+    #qt extra files
+    "moc_.*\\\\.cxx_parameters"
+    "\\\\.qrc.depends$"
+    "\\\\.qm$"
+    #other cmake generated files
+    "Makefile$"
+    "Doxyfile"
+    "CMakeFiles"
+    "[dD]ebug$"
+    "[rR]elease$"
+    "CPack"
+    "cmake_install\\\\.cmake$"
+    "cmake_uninstall\\\\.cmake$"
+    "CMakeCache\\\\.txt$"
+    "build_windows_.*\\\\.bat$"
+#    "^${CMAKE_CURRENT_SOURCE_DIR}/misc/libtremor"
+#    "^${CMAKE_CURRENT_SOURCE_DIR}/misc/libfreetype"
+#    "^${CMAKE_CURRENT_SOURCE_DIR}/misc/liblua"
+#    "^${CMAKE_CURRENT_SOURCE_DIR}/project_files/frontlib"
+#    "^${CMAKE_CURRENT_SOURCE_DIR}/project_files/cmdlineClient"
+    "^${CMAKE_CURRENT_SOURCE_DIR}/misc/libopenalbridge"
+    "^${CMAKE_CURRENT_SOURCE_DIR}/misc/winutils/bin"
+    "^${CMAKE_CURRENT_SOURCE_DIR}/project_files/promotional_art"
+    "^${CMAKE_CURRENT_SOURCE_DIR}/tools/templates"
+    "^${CMAKE_CURRENT_SOURCE_DIR}/tools/drawMapTest"
+    "^${CMAKE_CURRENT_SOURCE_DIR}/doc"
+    "^${CMAKE_CURRENT_SOURCE_DIR}/tmp"
+    "^${CMAKE_CURRENT_SOURCE_DIR}/utils"
+    "^${CMAKE_CURRENT_SOURCE_DIR}/share/hedgewars/Data/Maps/test"
+    "^${CMAKE_CURRENT_SOURCE_DIR}/install_manifest.txt"
+    "^${CMAKE_CURRENT_SOURCE_DIR}/CMakeCache.txt"
+    "^${CMAKE_CURRENT_SOURCE_DIR}/hedgewars\\\\."
+)
+
+include(CPack)
--- a/gameServer/Actions.hs	Thu Apr 04 14:37:19 2013 +0200
+++ b/gameServer/Actions.hs	Tue Jun 04 22:28:12 2013 +0200
@@ -20,6 +20,7 @@
 import Control.Exception
 import System.Process
 import Network.Socket
+import System.Random
 -----------------------------
 #if defined(OFFICIAL_SERVER)
 import OfficialServer.GameReplayStore
@@ -206,8 +207,9 @@
     rnc <- gets roomsClients
     newMasterId <- liftM (\ids -> fromMaybe (last . filter (/= ci) $ ids) delegateId) . io $ roomClientsIndicesM rnc ri
     newMaster <- io $ client'sM rnc id newMasterId
+    oldMasterId <- io $ room'sM rnc masterID ri
+    oldMaster <- io $ client'sM rnc id oldMasterId
     oldRoomName <- io $ room'sM rnc name ri
-    oldMaster <- client's nick
     kicked <- client's isKickedFromServer
     thisRoomChans <- liftM (map sendChan) $ roomClientsS ri
     let newRoomName = if (proto < 42) || kicked then nick newMaster else oldRoomName
@@ -216,12 +218,13 @@
                 , name = newRoomName
                 , isRestrictedJoins = False
                 , isRestrictedTeams = False
-                , isRegisteredOnly = False
-                , readyPlayers = if isReady newMaster then readyPlayers r else readyPlayers r + 1})
-        , ModifyClient2 newMasterId (\c -> c{isMaster = True, isReady = True})
+                , isRegisteredOnly = False}
+                )
+        , ModifyClient2 newMasterId (\c -> c{isMaster = True})
+        , ModifyClient2 oldMasterId (\c -> c{isMaster = False})
         , AnswerClients [sendChan newMaster] ["ROOM_CONTROL_ACCESS", "1"]
-        , AnswerClients thisRoomChans ["CLIENT_FLAGS", "-h", oldMaster]
-        , AnswerClients thisRoomChans ["CLIENT_FLAGS", "+hr", nick newMaster]
+        , AnswerClients thisRoomChans ["CLIENT_FLAGS", "-h", nick oldMaster]
+        , AnswerClients thisRoomChans ["CLIENT_FLAGS", "+h", nick newMaster]
         ]
 
     newRoom' <- io $ room'sM rnc id ri
@@ -381,7 +384,7 @@
         if p < 38 then
             processAction $ ByeClient $ loc "Nickname is already in use"
             else
-            processAction $ NoticeMessage NickAlreadyInUse
+            mapM_ processAction [NoticeMessage NickAlreadyInUse, ModifyClient $ \c -> c{nick = B.empty}]
         else
         do
         db <- gets (dbQueries . serverInfo)
@@ -615,6 +618,12 @@
     processAction $ Warning versionsStats
 
 
+processAction (Random chans items) = do
+    let i = if null items then ["heads", "tails"] else items
+    n <- io $ randomRIO (0, length i - 1)
+    processAction $ AnswerClients chans ["CHAT", "[random]", i !! n]
+
+
 #if defined(OFFICIAL_SERVER)
 processAction SaveReplay = do
     ri <- clientRoomA
--- a/gameServer/CoreTypes.hs	Thu Apr 04 14:37:19 2013 +0200
+++ b/gameServer/CoreTypes.hs	Tue Jun 04 22:28:12 2013 +0200
@@ -75,6 +75,7 @@
     | CheckRecord
     | CheckFailed B.ByteString
     | CheckSuccess [B.ByteString]
+    | Random [ClientChan] [B.ByteString]
 
 type ClientChan = Chan [B.ByteString]
 
@@ -108,8 +109,7 @@
         isKickedFromServer :: Bool,
         clientClan :: !(Maybe B.ByteString),
         checkInfo :: Maybe CheckInfo,
-        teamsInGame :: Word,
-        actionsPending :: [Action]
+        teamsInGame :: Word
     }
 
 instance Eq ClientInfo where
@@ -238,8 +238,8 @@
     ServerInfo
         True
         "<h2><p align=center><a href=\"http://www.hedgewars.org/\">http://www.hedgewars.org/</a></p></h2>"
-        "<font color=yellow><h3 align=center>Hedgewars 0.9.18 is out! Please update.</h3><p align=center><a href=http://hedgewars.org/download.html>Download page here</a></font>"
-        43 -- latestReleaseVersion
+        "<font color=yellow><h3 align=center>Hedgewars 0.9.19 is out! Please update.</h3><p align=center><a href=http://hedgewars.org/download.html>Download page here</a></font>"
+        45 -- latestReleaseVersion
         41 -- earliestCompatibleVersion
         46631
         ""
--- a/gameServer/HWProtoCore.hs	Thu Apr 04 14:37:19 2013 +0200
+++ b/gameServer/HWProtoCore.hs	Tue Jun 04 22:28:12 2013 +0200
@@ -4,7 +4,6 @@
 import Control.Monad.Reader
 import Data.Maybe
 import qualified Data.ByteString.Char8 as B
-import qualified Data.List as L
 --------------------------------------
 import CoreTypes
 import Actions
@@ -30,26 +29,28 @@
 handleCmd ["PONG"] = do
     cl <- thisClient
     if pingsQueue cl == 0 then
-        return $ actionsPending cl ++ [ModifyClient (\c -> c{actionsPending = []})]
+        return [ProtocolError "Protocol violation"]
         else
         return [ModifyClient (\c -> c{pingsQueue = pingsQueue c - 1})]
 
-handleCmd ("CMD" : parameters) =
-    let c = concatMap B.words parameters in
-        if not $ null c then
-            h $ (upperCase . head $ c) : tail c
-            else
-            return []
+handleCmd ["CMD", parameters] = do
+        let (cmd, plist) = B.break (== ' ') parameters
+        let param = B.dropWhile (== ' ') plist
+        h (upperCase cmd) param
     where
-        h ["DELEGATE", n] = handleCmd ["DELEGATE", n]
-        h ["STATS"] = handleCmd ["STATS"]
-        h ["PART", msg] = handleCmd ["PART", msg]
-        h ["QUIT", msg] = handleCmd ["QUIT", msg]
-        h ["GLOBAL", msg] = do
+        h "DELEGATE" n | not $ B.null n = handleCmd ["DELEGATE", n]
+        h "STATS" _ = handleCmd ["STATS"]
+        h "PART" m | not $ B.null m = handleCmd ["PART", m]
+                   | otherwise = handleCmd ["PART"]
+        h "QUIT" m | not $ B.null m = handleCmd ["QUIT", m]
+                   | otherwise = handleCmd ["QUIT"]
+        h "RND" p = handleCmd ("RND" : B.words p)
+        h "GLOBAL" p = do
+            cl <- thisClient
             rnc <- liftM snd ask
             let chans = map (sendChan . client rnc) $ allClients rnc
-            return [AnswerClients chans ["CHAT", "[global notice]", msg]]
-        h c = return [Warning . B.concat . L.intersperse " " $ "Unknown cmd" : c]
+            return [AnswerClients chans ["CHAT", "[global notice]", p] | isAdministrator cl]
+        h c p = return [Warning $ B.concat ["Unknown cmd: /", c, p]]
 
 handleCmd cmd = do
     (ci, irnc) <- ask
@@ -72,9 +73,9 @@
     let cl = rnc `client` fromJust maybeClientId
     let roomId = clientRoom rnc clientId
     let clRoom = room rnc roomId
-    let roomMasterSign = if isMaster cl then "@" else ""
+    let roomMasterSign = if isMaster cl then "+" else ""
     let adminSign = if isAdministrator cl then "@" else ""
-    let rInfo = if roomId /= lobbyId then B.concat [roomMasterSign, "room ", name clRoom] else adminSign `B.append` "lobby"
+    let rInfo = if roomId /= lobbyId then B.concat [adminSign, roomMasterSign, "room ", name clRoom] else adminSign `B.append` "lobby"
     let roomStatus = if isJust $ gameInfo clRoom then
             if teamsInGame cl > 0 then "(playing)" else "(spectating)"
             else
--- a/gameServer/HWProtoInRoomState.hs	Thu Apr 04 14:37:19 2013 +0200
+++ b/gameServer/HWProtoInRoomState.hs	Tue Jun 04 22:28:12 2013 +0200
@@ -59,7 +59,7 @@
                 else
                 liftM (head . (L.\\) (map B.singleton ['0'..]) . map teamcolor . teams) thisRoom
         let roomTeams = teams rm
-        let hhNum = let p = if not $ null roomTeams then hhnum $ head roomTeams else 4 in newTeamHHNum roomTeams p
+        let hhNum = let p = if not $ null roomTeams then minimum [hhnum $ head roomTeams, canAddNumber roomTeams] else 4 in newTeamHHNum roomTeams p
         let newTeam = clNick `seq` TeamInfo ci clNick tName teamColor grave fort voicepack flag dif hhNum (hhsList hhsInfo)
         return $
             if not . null . drop (maxTeams rm - 1) $ roomTeams then
@@ -79,10 +79,7 @@
                 AnswerClients clChan ["TEAM_ACCEPTED", tName],
                 AnswerClients othChans $ teamToNet $ newTeam,
                 AnswerClients roomChans ["TEAM_COLOR", tName, teamColor],
-                ModifyClient $ \c -> c{actionsPending = actionsPending cl
-                    ++ [AnswerClients clChan ["HH_NUM", tName, showB $ hhnum newTeam]]
-                    },
-                AnswerClients [sendChan cl] ["PING"]
+                AnswerClients roomChans ["HH_NUM", tName, showB $ hhnum newTeam]
                 ]
         where
         canAddNumber rt = (48::Int) - (sum $ map hhnum rt)
@@ -172,17 +169,15 @@
 handleCmd_inRoom ["TOGGLE_READY"] = do
     cl <- thisClient
     chans <- roomClientsChans
-    if isMaster cl then
-        return []
-        else
-        return [
-            ModifyRoom (\r -> r{readyPlayers = readyPlayers r + (if isReady cl then -1 else 1)}),
-            ModifyClient (\c -> c{isReady = not $ isReady cl}),
-            AnswerClients chans $ if clientProto cl < 38 then
-                    [if isReady cl then "NOT_READY" else "READY", nick cl]
-                    else
-                    ["CLIENT_FLAGS", if isReady cl then "-r" else "+r", nick cl]
-            ]
+
+    return [
+        ModifyRoom (\r -> r{readyPlayers = readyPlayers r + (if isReady cl then -1 else 1)}),
+        ModifyClient (\c -> c{isReady = not $ isReady cl}),
+        AnswerClients chans $ if clientProto cl < 38 then
+                [if isReady cl then "NOT_READY" else "READY", nick cl]
+                else
+                ["CLIENT_FLAGS", if isReady cl then "-r" else "+r", nick cl]
+        ]
 
 
 handleCmd_inRoom ["START_GAME"] = do
@@ -353,6 +348,10 @@
         else
         return []
 
+handleCmd_inRoom ("RND":rs) = do
+    n <- clientNick
+    s <- roomClientsChans
+    return [AnswerClients s ["CHAT", n, B.unwords $ "/rnd" : rs], Random s rs]
 
 handleCmd_inRoom ["LIST"] = return [] -- for old clients (<= 0.9.17)
 
--- a/gameServer/HWProtoLobbyState.hs	Thu Apr 04 14:37:19 2013 +0200
+++ b/gameServer/HWProtoLobbyState.hs	Tue Jun 04 22:28:12 2013 +0200
@@ -92,12 +92,9 @@
                 , AnswerClients [sendChan cl] $ ["CLIENT_FLAGS", "+h", ownerNick]
             ]
             ++ (if clientProto cl < 38 then map (readynessMessage cl) jRoomClients else [sendStateFlags cl jRoomClients])
-            ++ [AnswerClients [sendChan cl] ["PING"]
-                , ModifyClient $ \c -> c{actionsPending = actionsPending cl
-                    ++ answerFullConfig cl (mapParams jRoom) (params jRoom)
-                    ++ answerTeams cl jRoom
-                    ++ watchRound cl jRoom chans}
-                ]
+            ++ answerFullConfig cl (mapParams jRoom) (params jRoom)
+            ++ answerTeams cl jRoom
+            ++ watchRound cl jRoom chans
 
         where
         readynessMessage cl c = AnswerClients [sendChan cl] [if isReady c then "READY" else "NOT_READY", nick c]
@@ -147,6 +144,11 @@
         else
         liftM ((:) (AnswerClients [clChan] ["JOINING", roomName])) $ handleCmd_lobby ["JOIN_ROOM", roomName]
 
+
+handleCmd_lobby ("RND":rs) = do
+    c <- liftM sendChan thisClient
+    return [Random [c] rs]
+
     ---------------------------
     -- Administrator's stuff --
 
--- a/gameServer/NetRoutines.hs	Thu Apr 04 14:37:19 2013 +0200
+++ b/gameServer/NetRoutines.hs	Tue Jun 04 22:28:12 2013 +0200
@@ -47,7 +47,6 @@
                     Nothing
                     Nothing
                     0
-                    []
                     )
 
         writeChan chan $ Accept newClient
--- a/gameServer/OfficialServer/extdbinterface.hs	Thu Apr 04 14:37:19 2013 +0200
+++ b/gameServer/OfficialServer/extdbinterface.hs	Tue Jun 04 22:28:12 2013 +0200
@@ -14,7 +14,7 @@
 
 
 dbQueryAccount =
-    "SELECT users.pass, users_roles.rid FROM users LEFT JOIN users_roles ON users.uid = users_roles.uid WHERE users.name = ?"
+    "SELECT users.pass, users_roles.rid FROM users LEFT JOIN users_roles ON (users.uid = users_roles.uid AND users_roles.rid = 3) WHERE users.name = ?"
 
 dbQueryStats =
     "INSERT INTO gameserver_stats (players, rooms, last_update) VALUES (?, ?, UNIX_TIMESTAMP())"
@@ -29,7 +29,7 @@
                 execute statement [SqlByteString clNick]
                 passAndRole <- fetchRow statement
                 finish statement
-                let response = 
+                let response =
                         if isJust passAndRole then
                         (
                             clId,
--- a/gameServer/Utils.hs	Thu Apr 04 14:37:19 2013 +0200
+++ b/gameServer/Utils.hs	Tue Jun 04 22:28:12 2013 +0200
@@ -90,6 +90,8 @@
             , (42, "0.9.18-dev")
             , (43, "0.9.18")
             , (44, "0.9.19-dev")
+            , (45, "0.9.19")
+            , (46, "0.9.20-dev")
             ]
 
 askFromConsole :: B.ByteString -> IO B.ByteString
--- a/gameServer/hedgewars-server.cabal	Thu Apr 04 14:37:19 2013 +0200
+++ b/gameServer/hedgewars-server.cabal	Tue Jun 04 22:28:12 2013 +0200
@@ -21,6 +21,7 @@
     bytestring,
     bytestring-show,
     network >= 2.3,
+    random,
     time,
     mtl >= 2,
     dataenc,
--- a/hedgewars/ArgParsers.inc	Thu Apr 04 14:37:19 2013 +0200
+++ b/hedgewars/ArgParsers.inc	Tue Jun 04 22:28:12 2013 +0200
@@ -1,6 +1,6 @@
 (*
  * Hedgewars, a free turn based strategy game
- * Copyright (c) 2004-2012 Andrey Korotaev <unC0Rr@gmail.com>
+ * Copyright (c) 2004-2013 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
@@ -173,9 +173,9 @@
       mediaarray: array [0..9] of shortstring = ('--fullscreen-width', '--fullscreen-height', '--width', '--height', '--depth', '--volume','--nomusic','--nosound','--locale','--fullscreen');
       allarray: array [0..13] of shortstring = ('--fullscreen-width','--fullscreen-height', '--width', '--height', '--depth','--volume','--nomusic','--nosound','--locale','--fullscreen','--showfps','--altdmg','--frame-interval','--low-quality');
       reallyAll: array[0..30] of shortstring = (
-                '--prefix', '--user-prefix', '--locale', '--fullscreen-width', '--fullscreen-height', '--width', 
+                '--prefix', '--user-prefix', '--locale', '--fullscreen-width', '--fullscreen-height', '--width',
                 '--height', '--frame-interval', '--volume','--nomusic', '--nosound',
-                '--fullscreen', '--showfps', '--altdmg', '--low-quality', '--raw-quality', '--stereo', '--nick', 
+                '--fullscreen', '--showfps', '--altdmg', '--low-quality', '--raw-quality', '--stereo', '--nick',
   {deprecated}  '--depth', '--set-video', '--set-audio', '--set-other', '--set-multimedia', '--set-everything',
   {internal}    '--internal', '--port', '--recorder', '--landpreview',
   {misc}        '--stats-only', '--gci', '--help');
@@ -192,12 +192,12 @@
         {--prefix}               0 : PathPrefix        := getStringParameter (arg, paramIndex, parseParameter);
         {--user-prefix}          1 : UserPathPrefix    := getStringParameter (arg, paramIndex, parseParameter);
         {--locale}               2 : cLocaleFName      := getStringParameter (arg, paramIndex, parseParameter);
-        {--fullscreen-width}     3 : cFullscreenWidth  := getLongIntParameter(arg, paramIndex, parseParameter);
-        {--fullscreen-height}    4 : cFullscreenHeight := getLongIntParameter(arg, paramIndex, parseParameter);
-        {--width}                5 : cWindowedWidth    := getLongIntParameter(arg, paramIndex, parseParameter);
-        {--height}               6 : cWindowedHeight   := getLongIntParameter(arg, paramIndex, parseParameter);
+        {--fullscreen-width}     3 : cFullscreenWidth  := max(getLongIntParameter(arg, paramIndex, parseParameter), cMinScreenWidth);
+        {--fullscreen-height}    4 : cFullscreenHeight := max(getLongIntParameter(arg, paramIndex, parseParameter), cMinScreenHeight);
+        {--width}                5 : cWindowedWidth    := max(2 * (getLongIntParameter(arg, paramIndex, parseParameter) div 2), cMinScreenWidth);
+        {--height}               6 : cWindowedHeight   := max(2 * (getLongIntParameter(arg, paramIndex, parseParameter) div 2), cMinScreenHeight);
         {--frame-interval}       7 : cTimerInterval    := getLongIntParameter(arg, paramIndex, parseParameter);
-        {--volume}               8 : SetVolume          ( getLongIntParameter(arg, paramIndex, parseParameter) );
+        {--volume}               8 : SetVolume          ( max(getLongIntParameter(arg, paramIndex, parseParameter), 0) );
         {--nomusic}              9 : SetMusic           ( false );
         {--nosound}             10 : SetSound           ( false );
         {--fullscreen}          11 : cFullScreen       := true;
--- a/hedgewars/CMakeLists.txt	Thu Apr 04 14:37:19 2013 +0200
+++ b/hedgewars/CMakeLists.txt	Tue Jun 04 22:28:12 2013 +0200
@@ -175,7 +175,7 @@
 if(PNG_FOUND)
     list(REMOVE_AT PNG_LIBRARIES 1) #removing the zlib library path
     get_filename_component(PNG_LIBRARY_DIR ${PNG_LIBRARIES} PATH)
-    list(APPEND pascal_flags "-dPNG_SCREENSHOTS" "-Fl${PNG_LIBRARY_DIR}")
+    list(APPEND pascal_flags "-dPNG_SCREENSHOTS" "-Fl${PNG_LIBRARY_DIR}" "-k-L${PNG_LIBRARY_DIR}")
 endif()
 
 
--- a/hedgewars/GSHandlers.inc	Thu Apr 04 14:37:19 2013 +0200
+++ b/hedgewars/GSHandlers.inc	Tue Jun 04 22:28:12 2013 +0200
@@ -1,6 +1,6 @@
 (*
  * Hedgewars, a free turn based strategy game
- * Copyright (c) 2004-2012 Andrey Korotaev <unC0Rr@gmail.com>
+ * Copyright (c) 2004-2013 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
@@ -197,6 +197,7 @@
     tdY := Gear^.dY;
 
 
+
 // might need some testing/adjustments - just to avoid projectiles to fly forever (accelerated by wind/skips)
     if (hwRound(Gear^.X) < min(LAND_WIDTH div -2, -2048))
     or (hwRound(Gear^.X) > max(LAND_WIDTH * 3 div 2, 6144)) then
@@ -429,14 +430,13 @@
     CalcRotationDirAngle(Gear);
 
     // let's add some smoke depending on speed
-    s:= max(32,152 - hwRound(Distance(Gear^.dX,Gear^.dY)*120))+random(10);
+    s:= max(32,152 - round((abs(hwFloat2FLoat(Gear^.dX))+abs(hwFloat2Float(Gear^.dY)))*120))+random(10);
     if (GameTicks mod s) = 0 then
         begin
         // adjust angle to match the texture
         if Gear^.dX.isNegative then
-            i:= 130
-        else
-            i:= 50;
+             i:= 130
+        else i:= 50;
 
         smoke:= AddVisualGear(hwRound(Gear^.X)-round(cos((Gear^.DirAngle+i) * pi / 180)*20), hwRound(Gear^.Y)-round(sin((Gear^.DirAngle+i) * pi / 180)*20), vgtSmoke);
         if smoke <> nil then
@@ -504,7 +504,11 @@
     or (Gear^.Kind = gtBall) then
         CalcRotationDirAngle(Gear)
     else if (GameTicks and $1F) = 0 then
-        AddVisualGear(hwRound(Gear^.X), hwRound(Gear^.Y), vgtSmokeTrace)
+        begin
+        if hwRound(Gear^.Y) > cWaterLine then
+             AddVisualGear(hwRound(Gear^.X), hwRound(Gear^.Y), vgtBubble)
+        else AddVisualGear(hwRound(Gear^.X), hwRound(Gear^.Y), vgtSmokeTrace)
+        end
 end;
 
 ////////////////////////////////////////////////////////////////////////////////
@@ -521,24 +525,31 @@
         exit
         end;
     if (GameTicks and $3F) = 0 then
-        AddVisualGear(hwRound(Gear^.X), hwRound(Gear^.Y), vgtSmokeTrace);
+        begin
+        if hwRound(Gear^.Y) > cWaterLine then
+             AddVisualGear(hwRound(Gear^.X), hwRound(Gear^.Y), vgtBubble)
+        else AddVisualGear(hwRound(Gear^.X), hwRound(Gear^.Y), vgtSmokeTrace)
+        end
 end;
 
 ////////////////////////////////////////////////////////////////////////////////
 procedure doStepSnowball(Gear: PGear);
 var kick, i: LongInt;
     particle: PVisualGear;
+    gdX, gdY: hwFloat;
 begin
     AllInactive := false;
     if (GameFlags and gfMoreWind) = 0 then
         Gear^.dX := Gear^.dX + cWindSpeed;
+    gdX := Gear^.dX;
+    gdY := Gear^.dY;
     doStepFallingGear(Gear);
     CalcRotationDirAngle(Gear);
     if (Gear^.State and gstCollision) <> 0 then
         begin
-        kick:= hwRound((hwAbs(Gear^.dX)+hwAbs(Gear^.dY)) * _20);
-        Gear^.dY.isNegative:= (not Gear^.dY.isNegative);
-        Gear^.dX.isNegative:= (not Gear^.dX.isNegative);
+        kick:= hwRound((hwAbs(gdX)+hwAbs(gdY)) * _20);
+        Gear^.dX:= gdX;
+        Gear^.dY:= gdY;
         AmmoShove(Gear, 0, kick);
         for i:= 15 + kick div 10 downto 0 do
             begin
@@ -1418,7 +1429,9 @@
 ////////////////////////////////////////////////////////////////////////////////
 procedure doStepMine(Gear: PGear);
 var vg: PVisualGear;
+    dxdy: hwFloat;
 begin
+    if Gear^.Health = 0 then dxdy:= hwAbs(Gear^.dX)+hwAbs(Gear^.dY);
     if (Gear^.State and gstMoving) <> 0 then
         begin
         DeleteCI(Gear);
@@ -1436,14 +1449,8 @@
         doStepFallingGear(Gear);
     if (Gear^.Health = 0) then
         begin
-        if (not Gear^.dY.isNegative) and (Gear^.dY > _0_2) and (TestCollisionYwithGear(Gear, 1) <> 0) then
-            inc(Gear^.Damage, hwRound(Gear^.dY * _70))
-        else if (not Gear^.dX.isNegative) and (Gear^.dX > _0_2) and TestCollisionXwithGear(Gear, 1) then
-            inc(Gear^.Damage, hwRound(Gear^.dX * _70))
-        else if Gear^.dY.isNegative and (Gear^.dY < -_0_2) and (TestCollisionYwithGear(Gear, -1) <> 0) then
-            inc(Gear^.Damage, hwRound(Gear^.dY * -_70))
-        else if Gear^.dX.isNegative and (Gear^.dX < -_0_2) and TestCollisionXwithGear(Gear, -1) then
-            inc(Gear^.Damage, hwRound(Gear^.dX * -_70));
+        if (dxdy > _0_4) and (Gear^.State and gstCollision <> 0) then
+            inc(Gear^.Damage, hwRound(dxdy * _50));
 
         if ((GameTicks and $FF) = 0) and (Gear^.Damage > random(30)) then
             begin
@@ -1577,46 +1584,38 @@
 
 ///////////////////////////////////////////////////////////////////////////////
 
-(*
-TODO
-Increase damage as barrel smokes?
-Try tweaking friction some more
-*)
 procedure doStepRollingBarrel(Gear: PGear);
 var
     i: LongInt;
     particle: PVisualGear;
+    dxdy: hwFloat;
 begin
     if (Gear^.dY.QWordValue = 0) and (Gear^.dY.QWordValue = 0) and (TestCollisionYwithGear(Gear, 1) = 0) then
         SetLittle(Gear^.dY);
     Gear^.State := Gear^.State or gstAnimation;
+    if Gear^.Health < cBarrelHealth then Gear^.State:= Gear^.State and not gstFrozen;
 
     if ((Gear^.dX.QWordValue <> 0)
     or (Gear^.dY.QWordValue <> 0))  then
         begin
         DeleteCI(Gear);
         AllInactive := false;
-        if (not Gear^.dY.isNegative) and (Gear^.dY > _0_2) and (TestCollisionYwithGear(Gear, 1) <> 0) then
+        dxdy:= hwAbs(Gear^.dX)+hwAbs(Gear^.dY);
+        doStepFallingGear(Gear);
+        if (Gear^.State and gstCollision <> 0) and(dxdy > _0_4) then
             begin
-            Gear^.State := Gear^.State or gsttmpFlag;
-            inc(Gear^.Damage, hwRound(Gear^.dY * _70));
-            for i:= min(12, hwRound(Gear^.dY*_10)) downto 0 do
+            if (TestCollisionYwithGear(Gear, 1) <> 0) then
                 begin
-                particle := AddVisualGear(hwRound(Gear^.X) - 5 + Random(10), hwRound(Gear^.Y) + 12,vgtDust);
-                if particle <> nil then
-                    particle^.dX := particle^.dX + (Gear^.dX.QWordValue / 21474836480)
-                end
-            end
-        else if (not Gear^.dX.isNegative) and (Gear^.dX > _0_2) and TestCollisionXwithGear(Gear, 1) then
-                inc(Gear^.Damage, hwRound(Gear^.dX * _70))
-
-        else if Gear^.dY.isNegative and (Gear^.dY < -_0_2) and (TestCollisionYwithGear(Gear, -1) <> 0) then
-                inc(Gear^.Damage, hwRound(Gear^.dY * -_70))
-
-        else if Gear^.dX.isNegative and (Gear^.dX < -_0_2) and TestCollisionXwithGear(Gear, -1) then
-                inc(Gear^.Damage, hwRound(Gear^.dX * -_70));
-
-        doStepFallingGear(Gear);
+                Gear^.State := Gear^.State or gsttmpFlag;
+                for i:= min(12, hwRound(dxdy*_10)) downto 0 do
+                    begin
+                    particle := AddVisualGear(hwRound(Gear^.X) - 5 + Random(10), hwRound(Gear^.Y) + 12,vgtDust);
+                    if particle <> nil then
+                        particle^.dX := particle^.dX + (Gear^.dX.QWordValue / 21474836480)
+                    end
+                end;
+            inc(Gear^.Damage, hwRound(dxdy * _50))
+            end;
         CalcRotationDirAngle(Gear);
         //CheckGearDrowning(Gear)
         end
@@ -1655,23 +1654,19 @@
     dec(Gear^.Health, Gear^.Damage);
     Gear^.Damage := 0;
     if Gear^.Health <= 0 then
-        Gear^.doStep := @doStepCase;
-    // Hand off to doStepCase for the explosion
-
+        doStepCase(Gear);
 end;
 
 procedure doStepCase(Gear: PGear);
 var
     i, x, y: LongInt;
     k: TGearType;
-    exBoom: boolean;
     dX, dY: HWFloat;
     hog: PHedgehog;
     sparkles: PVisualGear;
     gi: PGear;
 begin
     k := Gear^.Kind;
-    exBoom := false;
 
     if (Gear^.Message and gmDestroy) > 0 then
         begin
@@ -1684,22 +1679,54 @@
                 Gear^.Message := Gear^.Message and (not (gmLJump or gmHJump));
         exit
         end;
+    if (k = gtExplosives) and (Gear^.Health < cBarrelHealth) then Gear^.State:= Gear^.State and not gstFrozen;
+
+    if ((k <> gtExplosives) and (Gear^.Damage > 0)) or ((k = gtExplosives) and (Gear^.Health<=0)) then
+        begin
+        x := hwRound(Gear^.X);
+        y := hwRound(Gear^.Y);
+        hog:= Gear^.Hedgehog;
+
+        DeleteGear(Gear);
+        // <-- delete gear!
+
+        if k = gtCase then
+            begin
+            doMakeExplosion(x, y, 25, hog, EXPLAutoSound);
+            for i:= 0 to 63 do
+                AddGear(x, y, gtFlame, 0, _0, _0, 0);
+            end
+        else if k = gtExplosives then
+                begin
+                doMakeExplosion(x, y, 75, hog, EXPLAutoSound);
+                for i:= 0 to 31 do
+                    begin
+                    dX := AngleCos(i * 64) * _0_5 * (getrandomf + _1);
+                    dY := AngleSin(i * 64) * _0_5 * (getrandomf + _1);
+                    AddGear(x, y, gtFlame, 0, dX, dY, 0);
+                    AddGear(x, y, gtFlame, gstTmpFlag, -dX, -dY, 0);
+                    end
+                end;
+            exit
+        end;
 
     if k = gtExplosives then
         begin
         //if V > _0_03 then Gear^.State:= Gear^.State or gstAnimation;
         if (hwAbs(Gear^.dX) > _0_15) or ((hwAbs(Gear^.dY) > _0_15) and (hwAbs(Gear^.dX) > _0_02)) then
+            begin
             Gear^.doStep := @doStepRollingBarrel;
-
-        if (Gear^.Health > 0) and ((Gear^.Health * 100 div cBarrelHealth) < random(90)) and ((GameTicks and $FF) = 0) then
+            exit;
+            end
+        else Gear^.dX:= _0;
+
+        if ((Gear^.Health * 100 div cBarrelHealth) < random(90)) and ((GameTicks and $FF) = 0) then
             if (cBarrelHealth div Gear^.Health) > 2 then
                 AddVisualGear(hwRound(Gear^.X) - 16 + Random(32), hwRound(Gear^.Y) - 2, vgtSmoke)
-        else
-            AddVisualGear(hwRound(Gear^.X) - 16 + Random(32), hwRound(Gear^.Y) - 2, vgtSmokeWhite);
+            else
+                AddVisualGear(hwRound(Gear^.X) - 16 + Random(32), hwRound(Gear^.Y) - 2, vgtSmokeWhite);
         dec(Gear^.Health, Gear^.Damage);
         Gear^.Damage := 0;
-        if Gear^.Health <= 0 then
-            exBoom := true;
         end
     else
         begin
@@ -1751,34 +1778,6 @@
             end
         end;
 
-    if (Gear^.Damage > 0) or exBoom then
-        begin
-        x := hwRound(Gear^.X);
-        y := hwRound(Gear^.Y);
-        hog:= Gear^.Hedgehog;
-
-        DeleteGear(Gear);
-        // <-- delete gear!
-
-        if k = gtCase then
-            begin
-            doMakeExplosion(x, y, 25, hog, EXPLAutoSound);
-            for i:= 0 to 63 do
-                AddGear(x, y, gtFlame, 0, _0, _0, 0);
-            end
-        else if k = gtExplosives then
-                begin
-                doMakeExplosion(x, y, 75, hog, EXPLAutoSound);
-                for i:= 0 to 31 do
-                    begin
-                    dX := AngleCos(i * 64) * _0_5 * (getrandomf + _1);
-                    dY := AngleSin(i * 64) * _0_5 * (getrandomf + _1);
-                    AddGear(x, y, gtFlame, 0, dX, dY, 0);
-                    AddGear(x, y, gtFlame, gstTmpFlag, -dX, -dY, 0);
-                    end
-                end;
-            exit
-        end;
 
     if (Gear^.dY.QWordValue <> 0)
     or (TestCollisionYwithGear(Gear, 1) = 0) then
@@ -2432,25 +2431,24 @@
 var
     dX, dY, gdX, gdY: hwFloat;
     i: LongInt;
-    dxn, dyn: boolean;
 begin
     AllInactive := false;
-    dxn := Gear^.dX.isNegative;
-    dyn := Gear^.dY.isNegative;
+    gdX := Gear^.dX;
+    gdY := Gear^.dY;
 
     doStepFallingGear(Gear);
     if (Gear^.State and gstCollision) <> 0 then
         begin
-        gdX := Gear^.dX;
-        gdY := Gear^.dY;
         doMakeExplosion(hwRound(Gear^.X), hwRound(Gear^.Y), 20, Gear^.Hedgehog, EXPLAutoSound);
-
-        gdX.isNegative := not dxn;
-        gdY.isNegative := not dyn;
+        gdX.isNegative := not gdX.isNegative;
+        gdY.isNegative := not gdY.isNegative;
+        gdX:= gdX*_0_2;
+        gdY:= gdY*_0_2;
+
         for i:= 0 to 4 do
             begin
-            dX := gdX + (GetRandomf - _0_5) * _0_03;
-            dY := gdY + (GetRandomf - _0_5) * _0_03;
+            dX := gdX + rndSign(GetRandomf) * _0_03;
+            dY := gdY + rndSign(GetRandomf) * _0_03;
             AddGear(hwRound(Gear^.X), hwRound(Gear^.Y), gtCluster, 0, dX, dY, 25);
             end;
 
@@ -2459,7 +2457,11 @@
         end;
 
     if (GameTicks and $3F) = 0 then
-        AddVisualGear(hwRound(Gear^.X), hwRound(Gear^.Y), vgtSmokeTrace)
+        begin
+        if hwRound(Gear^.Y) > cWaterLine then
+             AddVisualGear(hwRound(Gear^.X), hwRound(Gear^.Y), vgtBubble)
+        else AddVisualGear(hwRound(Gear^.X), hwRound(Gear^.Y), vgtSmokeTrace)
+        end
 end;
 
 ////////////////////////////////////////////////////////////////////////////////
@@ -2767,7 +2769,6 @@
 procedure doStepSeductionWork(Gear: PGear);
 var i: LongInt;
     hogs: PGearArrayS;
-    len: Integer;
 begin
     AllInactive := false;
     hogs := GearsNear(Gear^.X, Gear^.Y, gtHedgehog, Gear^.Radius);
@@ -2960,7 +2961,11 @@
     doStepFallingGear(Gear);
 
     if (GameTicks and $3F) = 0 then
-        AddVisualGear(hwRound(Gear^.X), hwRound(Gear^.Y), vgtSmokeTrace);
+        begin
+        if hwRound(Gear^.Y) > cWaterLine then
+             AddVisualGear(hwRound(Gear^.X), hwRound(Gear^.Y), vgtBubble)
+        else AddVisualGear(hwRound(Gear^.X), hwRound(Gear^.Y), vgtSmokeTrace)
+        end;
 
     if ((Gear^.State and gstCollision) <> 0) then
         begin
@@ -3210,10 +3215,11 @@
     move:= _0_02;
     fuel:= 5;
     end;*)
-
-    if Gear^.Health > 0 then
-        begin
-        if (HHGear^.Message and gmUp) <> 0 then
+    if HHGear^.Message and gmPrecise <> 0 then
+        HedgehogChAngle(HHGear)
+    else if Gear^.Health > 0 then
+        begin
+        if HHGear^.Message and gmUp <> 0 then
             begin
             if (not HHGear^.dY.isNegative) or (HHGear^.Y > -_256) then
                 begin
@@ -3280,10 +3286,12 @@
         Gear^.Tex := RenderStringTex(trmsg[sidFuel] + ': ' + inttostr(i) + '%', cWhiteColor, fntSmall)
         end;
 
-    if HHGear^.Message and (gmAttack or gmUp or gmPrecise or gmLeft or gmRight) <> 0 then
+    if (HHGear^.Message and (gmAttack or gmUp or gmLeft or gmRight) <> 0) and
+       (HHGear^.Message and gmPrecise = 0) then
         Gear^.State := Gear^.State and (not gsttmpFlag);
 
-    HHGear^.Message := HHGear^.Message and (not (gmUp or gmPrecise or gmLeft or gmRight));
+    if HHGear^.Message and gmPrecise = 0 then
+        HHGear^.Message := HHGear^.Message and (not (gmUp or gmLeft or gmRight));
     HHGear^.State := HHGear^.State or gstMoving;
 
     Gear^.X := HHGear^.X;
@@ -3300,7 +3308,7 @@
     if // (Gear^.Health = 0)
         (HHGear^.Damage <> 0)
         //or CheckGearDrowning(HHGear)
-        or (cWaterLine + 512 < hwRound(HHGear^.Y))
+        or (cWaterLine + cVisibleWater * 4 < hwRound(HHGear^.Y))
         or (TurnTimeLeft = 0)
         // allow brief ground touches - to be fair on this, might need another counter
         or (((GameTicks and $1FF) = 0) and (not HHGear^.dY.isNegative) and (TestCollisionYwithGear(HHGear, 1) <> 0))
@@ -3701,7 +3709,11 @@
             // wow! good candidate there, let's see if the distance and direction is okay!
             if hasdxy then
                 begin
-                s := r / Distance(iterator^.dX, iterator^.dY);
+                s := Distance(iterator^.dX, iterator^.dY);
+                // if the resulting distance is 0 skip this gear
+                if s.QWordValue = 0 then
+                    continue;
+                s := r / s;
                 ox:= iterator^.X + s * iterator^.dX;
                 oy:= iterator^.Y + s * iterator^.dY;
                 end
@@ -4650,7 +4662,6 @@
     resgear: PGear;
     hh: PHedgehog;
     i: LongInt;
-    len: Integer;
 begin
     if (TurnTimeLeft > 0) then
         dec(TurnTimeLeft);
@@ -4743,7 +4754,6 @@
     graves: PGearArrayS;
     hh: PHedgehog;
     i: LongInt;
-    len: Integer;
 begin
     AllInactive := false;
     graves := GearsNear(Gear^.X, Gear^.Y, gtGrave, Gear^.Radius);
@@ -5093,7 +5103,18 @@
     Gear^.Tex := RenderStringTex(trmsg[sidFuel] + ': ' + inttostr(t) +
               '%', cWhiteColor, fntSmall)
     end;
-    if GameTicks mod 10 = 0 then dec(Gear^.Health);
+    if Gear^.Message and (gmUp or gmDown) <> 0 then
+        begin
+        StopSoundChan(Gear^.SoundChannel);
+        Gear^.SoundChannel:= -1;
+        if GameTicks mod 40 = 0 then dec(Gear^.Health)
+        end
+    else 
+        begin
+        if Gear^.SoundChannel = -1 then
+            Gear^.SoundChannel := LoopSound(sndIceBeam);
+        if GameTicks mod 10 = 0 then dec(Gear^.Health)
+        end
 end;
 
 
@@ -5110,17 +5131,6 @@
     LastDamage:= nil;
     X:= Hedgehog^.Gear^.X;
     Y:= Hedgehog^.Gear^.Y;
-    //unfreeze all semifrozen hogs - make this generic hog cleanup
-(*
-    iter := GearsList;
-    while iter <> nil do
-        begin
-        if (iter^.Kind = gtHedgehog) and
-        (iter^.Hedgehog^.Effects[heFrozen] and $FF = 0) then
-        iter^.Hedgehog^.Effects[heFrozen]:= 0;
-        iter:= iter^.NextGear
-        end
-*)
   end;
 end;
 
@@ -5135,21 +5145,22 @@
 const iceRadius = 32;
 const iceHeight = 40;
 var
-    HHGear: PGear;
+    HHGear, iter: PGear;
     landRect: TSDL_Rect;
     ndX, ndY: hwFloat;
-    i, t, gX, gY: LongInt;
+    i, j, t, gX, gY: LongInt;
     hogs: PGearArrayS;
-    len: Integer;
+    vg: PVisualGear;
 begin
     HHGear := Gear^.Hedgehog^.Gear;
-    if (Gear^.Message and gmAttack <> 0) or (Gear^.Health = 0) or (HHGear = nil) or (HHGear^.Damage <> 0) then
-        begin
+    if (Gear^.Message and gmAttack <> 0) or (Gear^.Health = 0) or (HHGear = nil) or (HHGear^.Damage <> 0) or (HHGear^.dX.QWordValue > 4294967)  then
+        begin
+        StopSoundChan(Gear^.SoundChannel);
         DeleteGear(Gear);
         AfterAttack;
         exit
-        end
-    else if Gear^.Message and (gmUp or gmDown) = 0 then updateFuel(Gear);
+        end;
+    updateFuel(Gear);
 
     with Gear^ do
         begin
@@ -5173,7 +5184,7 @@
 
             if Target.X <> NoPointX then
                 begin
-                CheckCollisionWithLand(Gear);
+                CheckCollision(Gear);
                 if (State and gstCollision) <> 0 then
                     begin
                     if Timer = iceWaitCollision then
@@ -5205,6 +5216,49 @@
                     landRect.w := min(2*iceRadius, LAND_WIDTH - landRect.x - 1);
                     landRect.h := min(2*iceRadius, LAND_HEIGHT - landRect.y - 1);
                     UpdateLandTexture(landRect.x, landRect.w, landRect.y, landRect.h, true);
+                    
+                    // Freeze nearby mines/explosives/cases too
+                    iter := GearsList;
+                    while iter <> nil do
+                        begin
+                        if (iter^.State and gstFrozen = 0) and
+                           ((iter^.Kind = gtExplosives) or (iter^.Kind = gtCase) or (iter^.Kind = gtMine)) and 
+                           (abs(iter^.X.Round-target.x)+abs(iter^.Y.Round-target.y)+2<2*iceRadius) and (Distance(iter^.X-int2hwFloat(target.x),iter^.Y-int2hwFloat(target.y))<int2hwFloat(iceRadius*2)) then
+                            begin
+                            for t:= 0 to 5 do
+                                begin
+                                vg:= AddVisualGear(hwRound(iter^.X)+random(4)-8, hwRound(iter^.Y)+random(8), vgtDust, 1);
+                                if vg <> nil then
+                                    begin
+                                    i:= random(100) + 155;
+                                    vg^.Tint:= i shl 24 or i shl 16 or $FF shl 8 or Longword(random(200) + 55);
+                                    vg^.Angle:= random(360);
+                                    vg^.dx:= 0.001 * random(80);
+                                    vg^.dy:= 0.001 * random(80)
+                                    end
+                                end;
+                            PlaySound(sndHogFreeze);
+                            iter^.State:= iter^.State or gstFrozen;
+                            if iter^.Kind = gtMine then // dud mine block
+                                begin
+                                vg:= AddVisualGear(hwRound(iter^.X) - 4  + Random(8), hwRound(iter^.Y) - 4 - Random(4), vgtSmoke);
+                                if vg <> nil then
+                                    vg^.Scale:= 0.5;
+                                PlaySound(sndVaporize);
+                                iter^.Health := 0;
+                                iter^.Damage := 0;
+                                iter^.State := iter^.State and (not gstAttacking)
+                                end
+                            else if iter^.Kind = gtCase then
+                                begin
+                                DeleteCI(iter);
+                                AddGearCI(iter)
+                                end
+                            else // gtExplosives
+                                iter^.Health:= iter^.Health + cBarrelHealth
+                            end;
+                        iter:= iter^.NextGear
+                        end;
 
                     // FillRoundInLandWithIce(Target.X, Target.Y, iceRadius);
                     SetAllHHToActive(true);
@@ -5213,10 +5267,26 @@
 
                 if (Timer = iceCollideWithWater) and ((GameTicks - Power) > groundFreezingTime) then
                     begin
+                    PlaySound(sndHogFreeze);
                     DrawIceBreak(Target.X, cWaterLine - iceHeight, iceRadius, iceHeight);
                     SetAllHHToActive(true);
                     Timer := iceWaitCollision;
                     end;
+(*
+ Any ideas for something that would look good here?
+                if (Target.X <> NoPointX) and ((Timer = iceCollideWithGround) or (Timer = iceCollideWithWater)) and (GameTicks mod max((groundFreezingTime-((GameTicks - Power)*2)),2) = 0) then //and CheckLandValue(Target.X, Target.Y, lfIce) then
+                    begin
+                        vg:= AddVisualGear(Target.X+random(20)-10, Target.Y+random(40)-10, vgtDust, 1);
+                        if vg <> nil then
+                            begin
+                            i:= random(100) + 155;
+                            vg^.Tint:= IceColor or $FF;
+                            vg^.Angle:= random(360);
+                            vg^.dx:= 0.001 * random(80);
+                            vg^.dy:= 0.001 * random(80)
+                            end
+                    end;
+*)
 
 // freeze nearby hogs
                 hogs := GearsNear(int2hwFloat(Target.X), int2hwFloat(Target.Y), gtHedgehog, Gear^.Radius*2);
@@ -5229,7 +5299,10 @@
                                 if hogs.ar^[i]^.Hedgehog^.Effects[heFrozen] < 256 then
                                     hogs.ar^[i]^.Hedgehog^.Effects[heFrozen] := hogs.ar^[i]^.Hedgehog^.Effects[heFrozen] + 1
                                 else if hogs.ar^[i]^.Hedgehog^.Effects[heFrozen] = 256 then
-                                    hogs.ar^[i]^.Hedgehog^.Effects[heFrozen]:= 200000;//cHedgehogTurnTime + cReadyDelay
+                                    begin
+                                    hogs.ar^[i]^.Hedgehog^.Effects[heFrozen]:= 200000-1;//cHedgehogTurnTime + cReadyDelay
+                                    PlaySound(sndHogFreeze);
+                                    end;
                                 end;
                 inc(Pos)
                 end
@@ -5242,14 +5315,16 @@
                 X:= HHGear^.X;
                 Y:= HHGear^.Y
                 end;
-            {if (gX > max(LAND_WIDTH,4096)*2) or
+            if (gX > max(LAND_WIDTH,4096)*2) or
                     (gX < -max(LAND_WIDTH,4096)) or
                     (gY < -max(LAND_HEIGHT,4096)) or
                     (gY > max(LAND_HEIGHT,4096)+512) then
-            begin
-                X:= HHGear^.X;
-                Y:= HHGear^.Y
-            end}
+                begin
+                //X:= HHGear^.X;
+                //Y:= HHGear^.Y
+                Target.X:= gX;
+                Target.Y:= gY;
+                end
         end
     end;
 end;
--- a/hedgewars/PNGh.pas	Thu Apr 04 14:37:19 2013 +0200
+++ b/hedgewars/PNGh.pas	Tue Jun 04 22:28:12 2013 +0200
@@ -1,6 +1,6 @@
 (*
  * Hedgewars, a free turn based strategy game
- * Copyright (c) 2004-2012 Andrey Korotaev <unC0Rr@gmail.com>
+ * Copyright (c) 2004-2013 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
--- a/hedgewars/SDLh.pas	Thu Apr 04 14:37:19 2013 +0200
+++ b/hedgewars/SDLh.pas	Tue Jun 04 22:28:12 2013 +0200
@@ -1,6 +1,6 @@
 (*
  * Hedgewars, a free turn based strategy game
- * Copyright (c) 2004-2012 Andrey Korotaev <unC0Rr@gmail.com>
+ * Copyright (c) 2004-2013 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
@@ -35,12 +35,6 @@
 {$ENDIF}
 
 {$IFDEF UNIX}
-    {$IFNDEF DARWIN}
-        {necessary for statically linking physfs (divdi3 undefined on 32 bit)}
-        {$IFDEF CPU32}
-            {$linklib stdc++}
-        {$ENDIF}
-    {$ENDIF}
     {$IFDEF HAIKU}
         {$linklib root}
     {$ELSE}
@@ -962,12 +956,11 @@
 procedure SDL_StartTextInput; cdecl; external SDLLibName;
 
 function  SDL_PeepEvents(event: PSDL_Event; numevents: LongInt; action: TSDL_eventaction; minType, maxType: LongWord): LongInt; cdecl; external SDLLibName;
-function  SDL_CreateThread(fn: Pointer; name: PChar; data: Pointer): PSDL_Thread; cdecl; external SDLLibName;
 {$ELSE}
-function  SDL_CreateThread(fn: Pointer; data: Pointer): PSDL_Thread; cdecl; external SDLLibName;
 function  SDL_PeepEvents(event: PSDL_Event; numevents: LongInt; action: TSDL_eventaction; mask: LongWord): LongInt; cdecl; external SDLLibName;
 {$ENDIF}
 
+
 function  SDL_GetMouseState(x, y: PLongInt): Byte; cdecl; external SDLLibName;
 function  SDL_GetKeyName(key: LongWord): PChar; cdecl; external SDLLibName;
 function  SDL_GetScancodeName(key: LongWord): PChar; cdecl; external SDLLibName;
@@ -985,7 +978,13 @@
 procedure SDL_WM_SetCaption(title: PChar; icon: PChar); cdecl; external SDLLibName;
 function  SDL_WM_ToggleFullScreen(surface: PSDL_Surface): LongInt; cdecl; external SDLLibName;
 
+
+// remember to mark the threaded functions as 'cdecl; export;'
+// (or have fun debugging nil arguments)
+function  SDL_CreateThread(fn: Pointer; {$IFDEF SDL13}name: PChar;{$ENDIF} data: Pointer): PSDL_Thread; cdecl; external SDLLibName;
 procedure SDL_WaitThread(thread: PSDL_Thread; status: PLongInt); cdecl; external SDLLibName;
+procedure SDL_KillThread(thread: PSDL_Thread); cdecl; external SDLLibName;
+
 function  SDL_CreateMutex: PSDL_mutex; cdecl; external SDLLibName;
 procedure SDL_DestroyMutex(mutex: PSDL_mutex); cdecl; external SDLLibName;
 function  SDL_LockMutex(mutex: PSDL_mutex): LongInt; cdecl; external SDLLibName name 'SDL_mutexP';
--- a/hedgewars/VGSHandlers.inc	Thu Apr 04 14:37:19 2013 +0200
+++ b/hedgewars/VGSHandlers.inc	Tue Jun 04 22:28:12 2013 +0200
@@ -1,6 +1,6 @@
 (*
  * Hedgewars, a free turn based strategy game
- * Copyright (c) 2004-2012 Andrey Korotaev <unC0Rr@gmail.com>
+ * Copyright (c) 2004-2013 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
--- a/hedgewars/config.inc.in	Thu Apr 04 14:37:19 2013 +0200
+++ b/hedgewars/config.inc.in	Tue Jun 04 22:28:12 2013 +0200
@@ -1,6 +1,6 @@
 (*
  * Hedgewars, a free turn based strategy game
- * Copyright (c) 2004-2012 Andrey Korotaev <unC0Rr@gmail.com>
+ * Copyright (c) 2004-2013 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
--- a/hedgewars/hwLibrary.pas	Thu Apr 04 14:37:19 2013 +0200
+++ b/hedgewars/hwLibrary.pas	Tue Jun 04 22:28:12 2013 +0200
@@ -1,6 +1,6 @@
 (*
  * Hedgewars, a free turn based strategy game
- * Copyright (c) 2004-2012 Andrey Korotaev <unC0Rr@gmail.com>
+ * Copyright (c) 2004-2013 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
--- a/hedgewars/hwengine.pas	Thu Apr 04 14:37:19 2013 +0200
+++ b/hedgewars/hwengine.pas	Tue Jun 04 22:28:12 2013 +0200
@@ -1,6 +1,6 @@
 (*
  * Hedgewars, a free turn based strategy game
- * Copyright (c) 2004-2012 Andrey Korotaev <unC0Rr@gmail.com>
+ * Copyright (c) 2004-2013 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
@@ -32,7 +32,7 @@
 uses SDLh, uMisc, uConsole, uGame, uConsts, uLand, uAmmos, uVisualGears, uGears, uStore, uWorld, uInputHandler
      , uSound, uScript, uTeams, uStats, uIO, uLocale, uChat, uAI, uAIMisc, uAILandMarks, uLandTexture, uCollisions
      , SysUtils, uTypes, uVariables, uCommands, uUtils, uCaptions, uDebug, uCommandHandlers, uLandPainted
-     , uPhysFSLayer, uCursor
+     , uPhysFSLayer, uCursor, uRandom
      {$IFDEF USE_VIDEO_RECORDING}, uVideoRec {$ENDIF}
      {$IFDEF USE_TOUCH_INTERFACE}, uTouch {$ENDIF}
      {$IFDEF ANDROID}, GLUnit{$ENDIF}
@@ -94,6 +94,7 @@
                 DisableSomeWeapons;
             AddClouds;
             AddFlakes;
+            SetRandomSeed(cSeed, false);
             AssignHHCoords;
             AddMiscGears;
             StoreLoad(false);
@@ -107,7 +108,7 @@
             ScriptCall('onGameStart');
             GameState:= gsGame;
             end;
-        gsConfirm, gsGame:
+        gsConfirm, gsGame, gsChat:
             begin
             if not cOnlyStats then
 {$IFDEF WEBGL}
@@ -119,12 +120,6 @@
             DoGameTick(Lag);
             if not cOnlyStats then ProcessVisualGears(Lag);
             end;
-        gsChat:
-            begin
-            if not cOnlyStats then DrawWorld(Lag);
-            DoGameTick(Lag);
-            if not cOnlyStats then ProcessVisualGears(Lag);
-            end;
         gsExit:
             begin
             DoTimer:= true;
@@ -200,10 +195,10 @@
                     // sdl on iphone supports only ashii keyboards and the unicode field is deprecated in sdl 1.3
                         KeyPressChat(SDL_GetKeyFromScancode(event.key.keysym.sym), event.key.keysym.sym); //TODO correct for keymodifiers
                         end
-                    else
-                        ProcessKey(event.key);
+                    else 
+                        if GameState >= gsGame then ProcessKey(event.key);
                 SDL_KEYUP:
-                    if GameState <> gsChat then
+                    if (GameState <> gsChat) and (GameState >= gsGame) then
                         ProcessKey(event.key);
 
                 SDL_WINDOWEVENT:
@@ -245,22 +240,19 @@
                     if GameState = gsChat then
                         KeyPressChat(event.key.keysym.unicode, event.key.keysym.sym)
                     else
-                        ProcessKey(event.key);
+                        if GameState >= gsGame then ProcessKey(event.key);
                 SDL_KEYUP:
-                    if GameState <> gsChat then
+                    if (GameState <> gsChat) and (GameState >= gsGame) then
                         ProcessKey(event.key);
 
                 SDL_MOUSEBUTTONDOWN:
                     if GameState = gsConfirm then
-                    begin
-                        resetPosition();
-                        ParseCommand('quit', true);
-                    end
+                        ParseCommand('quit', true)
                     else
-                        ProcessMouse(event.button, true);
+                        if (GameState >= gsGame) then ProcessMouse(event.button, true);
 
                 SDL_MOUSEBUTTONUP:
-                    ProcessMouse(event.button, false);
+                    if (GameState >= gsGame) then ProcessMouse(event.button, false);
 
                 SDL_ACTIVEEVENT:
                     if (event.active.state and SDL_APPINPUTFOCUS) <> 0 then
@@ -390,7 +382,7 @@
                      ' (' + cHashString + ') with protocol #' + inttostr(cNetProtoVersion));
     AddFileLog('Prefix: "' + PathPrefix +'"');
     AddFileLog('UserPrefix: "' + UserPathPrefix +'"');
-    
+
     for i:= 0 to ParamCount do
         AddFileLog(inttostr(i) + ': ' + ParamStr(i));
 
--- a/hedgewars/options.inc	Thu Apr 04 14:37:19 2013 +0200
+++ b/hedgewars/options.inc	Tue Jun 04 22:28:12 2013 +0200
@@ -1,6 +1,6 @@
 (*
  * Hedgewars, a free turn based strategy game
- * Copyright (c) 2004-2012 Andrey Korotaev <unC0Rr@gmail.com>
+ * Copyright (c) 2004-2013 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
@@ -39,7 +39,6 @@
 
 {$IFDEF ANDROID}
     {$DEFINE MOBILE}
-    {$DEFINE USE_SDLTHREADS}
     {$DEFINE USE_CONTEXT_RESTORE}
     {$DEFINE Java_Prefix:= 'Java_org_hedgewars_hedgeroid_EngineProtocol_PascalExports_'}
 {$ENDIF}
--- a/hedgewars/uAI.pas	Thu Apr 04 14:37:19 2013 +0200
+++ b/hedgewars/uAI.pas	Tue Jun 04 22:28:12 2013 +0200
@@ -1,6 +1,6 @@
 (*
  * Hedgewars, a free turn based strategy game
- * Copyright (c) 2004-2012 Andrey Korotaev <unC0Rr@gmail.com>
+ * Copyright (c) 2004-2013 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
@@ -30,7 +30,7 @@
 
 implementation
 uses uConsts, SDLh, uAIMisc, uAIAmmoTests, uAIActions,
-    uAmmos, SysUtils{$IFNDEF USE_SDLTHREADS} {$IFDEF UNIX}, cthreads{$ENDIF} {$ENDIF}, uTypes,
+    uAmmos, SysUtils, uTypes,
     uVariables, uCommands, uUtils, uDebug, uAILandMarks;
 
 {$IFDEF AI_MAINTHREAD}
@@ -41,25 +41,21 @@
 var BestActions: TActions;
     CanUseAmmo: array [TAmmoType] of boolean;
     StopThinking: boolean;
-{$IFDEF USE_SDLTHREADS} 
-    ThinkThread: PSDL_Thread = nil;
-{$ELSE}
-    ThinkThread: TThreadID;
-{$ENDIF}
-    hasThread: LongInt;
-    StartTicks: LongInt;
+    StartTicks: Longword;
+    ThinkThread: PSDL_Thread;
+    ThreadLock: PSDL_Mutex;
 
 procedure FreeActionsList;
 begin
     AddFileLog('FreeActionsList called');
-    if hasThread <> 0 then
-    begin
-        AddFileLog('Waiting AI thread to finish');
+    if (ThinkThread <> nil) then
+        begin
         StopThinking:= true;
-        repeat
-            SDL_Delay(10)
-        until hasThread = 0
-    end;
+        SDL_WaitThread(ThinkThread, nil);
+        end;
+    SDL_LockMutex(ThreadLock);
+    ThinkThread:= nil;
+    SDL_UnlockMutex(ThreadLock);
 
     with CurrentHedgehog^ do
         if Gear <> nil then
@@ -71,7 +67,6 @@
 end;
 
 
-
 const cBranchStackSize = 12;
 type TStackEntry = record
                    WastedTicks: Longword;
@@ -128,22 +123,18 @@
         with Me^.Hedgehog^ do
             a:= CurAmmoType;
         aa:= a;
-{$IFDEF USE_SDLTHREADS}
-        SDL_delay(0);    //ThreadSwitch was only a hint
-{$ELSE}
-        ThreadSwitch();
-{$ENDIF}       
+        SDL_delay(0); // hint to let the context switch run
         repeat
-        if (CanUseAmmo[a]) 
-            and ((not rareChecks) or ((AmmoTests[a].flags and amtest_Rare) = 0)) 
-            and ((i = 0) or ((AmmoTests[a].flags and amtest_NoTarget) = 0)) 
+        if (CanUseAmmo[a])
+            and ((not rareChecks) or ((AmmoTests[a].flags and amtest_Rare) = 0))
+            and ((i = 0) or ((AmmoTests[a].flags and amtest_NoTarget) = 0))
             then
             begin
 {$HINTS OFF}
-            Score:= AmmoTests[a].proc(Me, Targets.ar[i].Point, BotLevel, ap);
+            Score:= AmmoTests[a].proc(Me, Targets.ar[i], BotLevel, ap);
 {$HINTS ON}
             if Actions.Score + Score > BestActions.Score then
-                if (BestActions.Score < 0) or (Actions.Score + Score > BestActions.Score + Byte(BotLevel) * 2048) then
+                if (BestActions.Score < 0) or (Actions.Score + Score > BestActions.Score + Byte(BotLevel - 1) * 2048) then
                     begin
                     BestActions:= Actions;
                     inc(BestActions.Score, Score);
@@ -155,10 +146,10 @@
                         AddAction(BestActions, aia_LookRight, 0, 200, 0, 0)
                     else if (ap.Angle < 0) then
                         AddAction(BestActions, aia_LookLeft, 0, 200, 0, 0);
-                    
+
                     if (Ammoz[a].Ammo.Propz and ammoprop_Timerable) <> 0 then
                         AddAction(BestActions, aia_Timer, ap.Time div 1000, 400, 0, 0);
-                        
+
                     if (Ammoz[a].Ammo.Propz and ammoprop_NoCrosshair) = 0 then
                         begin
                         dAngle:= LongInt(Me^.Angle) - Abs(ap.Angle);
@@ -173,23 +164,23 @@
                             AddAction(BestActions, aia_Down, aim_release, -dAngle, 0, 0)
                             end
                         end;
-                        
+
                     if (Ammoz[a].Ammo.Propz and ammoprop_NeedTarget) <> 0 then
                         begin
                         AddAction(BestActions, aia_Put, 0, 1, ap.AttackPutX, ap.AttackPutY)
                         end;
-                        
+
                     if (Ammoz[a].Ammo.Propz and ammoprop_OscAim) <> 0 then
                         begin
                         AddAction(BestActions, aia_attack, aim_push, 350 + random(200), 0, 0);
                         AddAction(BestActions, aia_attack, aim_release, 1, 0, 0);
-                         
+
                         if abs(ap.Angle) > 32 then
                            begin
                            AddAction(BestActions, aia_Down, aim_push, 100 + random(150), 0, 0);
                            AddAction(BestActions, aia_Down, aim_release, 32, 0, 0);
                            end;
-                        
+
                         AddAction(BestActions, aia_waitAngle, ap.Angle, 250, 0, 0);
                         AddAction(BestActions, aia_attack, aim_push, 1, 0, 0);
                         AddAction(BestActions, aia_attack, aim_release, 1, 0, 0);
@@ -248,21 +239,21 @@
 
 if (Me^.State and gstAttacked) = 0 then
     TestAmmos(Actions, Me, false);
-    
+
 BestRate:= RatePlace(Me);
 BaseRate:= Max(BestRate, 0);
 
-// switch to 'skip' if we can't move because of mouse cursor being shown
+// switch to 'skip' if we cannot move because of mouse cursor being shown
 if (Ammoz[Me^.Hedgehog^.CurAmmoType].Ammo.Propz and ammoprop_NeedTarget) <> 0 then
     AddAction(Actions, aia_Weapon, Longword(amSkip), 100 + random(200), 0, 0);
-    
-if ((CurrentHedgehog^.MultiShootAttacks = 0) or ((Ammoz[Me^.Hedgehog^.CurAmmoType].Ammo.Propz and ammoprop_NoMoveAfter) = 0)) 
+
+if ((CurrentHedgehog^.MultiShootAttacks = 0) or ((Ammoz[Me^.Hedgehog^.CurAmmoType].Ammo.Propz and ammoprop_NoMoveAfter) = 0))
     and (GameFlags and gfArtillery = 0) then
     begin
     tmp:= random(2) + 1;
     Push(0, Actions, Me^, tmp);
     Push(0, Actions, Me^, tmp xor 3);
-    
+
     while (Stack.Count > 0) and (not StopThinking) do
         begin
         Pop(ticks, Actions, Me^);
@@ -272,7 +263,7 @@
             AddAction(Actions, aia_WaitXL, hwRound(Me^.X), 0, 0, 0)
         else
             AddAction(Actions, aia_WaitXR, hwRound(Me^.X), 0, 0, 0);
-        
+
         steps:= 0;
 
         while (not StopThinking) do
@@ -285,8 +276,8 @@
             if ticks > maxticks then
                 break;
 
-            if (BotLevel < 5) 
-                and (GoInfo.JumpType = jmpHJump) 
+            if (BotLevel < 5)
+                and (GoInfo.JumpType = jmpHJump)
                 and (not checkMark(hwRound(Me^.X), hwRound(Me^.Y), markHJumped))
                 then // hjump support
                 begin
@@ -300,7 +291,7 @@
                             AddAction(MadeActions, aia_LookRight, 0, 200, 0, 0)
                         else
                             AddAction(MadeActions, aia_LookLeft, 0, 200, 0, 0);
-                            
+
                         AddAction(MadeActions, aia_HJump, 0, 305 + random(50), 0, 0);
                         AddAction(MadeActions, aia_HJump, 0, 350, 0, 0);
                         end;
@@ -308,8 +299,8 @@
                     Push(ticks, Stack.States[Pred(Stack.Count)].MadeActions, AltMe, Me^.Message)
                     end;
                 end;
-            if (BotLevel < 3) 
-                and (GoInfo.JumpType = jmpLJump) 
+            if (BotLevel < 3)
+                and (GoInfo.JumpType = jmpLJump)
                 and (not checkMark(hwRound(Me^.X), hwRound(Me^.Y), markLJumped))
                 then // ljump support
                 begin
@@ -328,7 +319,7 @@
 
                 // push current position so we proceed from it after checking jump+forward walk opportunities
                 if CanGo then Push(ticks, Actions, Me^, Me^.Message);
-                
+
                 // first check where we go after jump walking forward
                 if Push(ticks, Actions, AltMe, Me^.Message) then
                     with Stack.States[Pred(Stack.Count)] do
@@ -336,10 +327,10 @@
                 break
                 end;
 
-            // 'not CanGO' means we can't go straight, possible jumps are checked above
-            if (not CanGo) then
+            // 'not CanGO' means we cannot go straight, possible jumps are checked above
+            if not CanGo then
                 break;
-            
+
              inc(steps);
              Actions.actions[Pred(Actions.Count)].Param:= hwRound(Me^.X);
              Rate:= RatePlace(Me);
@@ -352,17 +343,17 @@
                 end
             else if Rate < BestRate then
                 break;
-                
+
             if ((Me^.State and gstAttacked) = 0) and ((steps mod 4) = 0) then
                 begin
                 if (steps > 4) and checkMark(hwRound(Me^.X), hwRound(Me^.Y), markWalkedHere) then
-                    break;                    
+                    break;
                 addMark(hwRound(Me^.X), hwRound(Me^.Y), markWalkedHere);
 
                 TestAmmos(Actions, Me, ticks shr 12 = oldticks shr 12);
-                
+
                 end;
-                
+
             if GoInfo.FallPix >= FallPixForBranching then
                 Push(ticks, Actions, Me^, Me^.Message xor 3); // aia_Left xor 3 = aia_Right
 
@@ -382,31 +373,26 @@
     end {if}
 end;
 
-function Think(Me: Pointer): ptrint;
+function Think(Me: PGear): LongInt; cdecl; export;
 var BackMe, WalkMe: TGear;
     switchCount: LongInt;
     currHedgehogIndex, itHedgehog, switchesNum, i: Longword;
     switchImmediatelyAvailable: boolean;
     Actions: TActions;
 begin
-InterlockedIncrement(hasThread);
-
-{$IFDEF AI_MAINTHREAD}
-StartTicks:= SDL_GetTicks();
-{$ELSE}
+dmgMod:= 0.01 * hwFloat2Float(cDamageModifier) * cDamagePercent;
 StartTicks:= GameTicks;
-{$ENDIF}
 
 currHedgehogIndex:= CurrentTeam^.CurrHedgehog;
 itHedgehog:= currHedgehogIndex;
 switchesNum:= 0;
 
 switchImmediatelyAvailable:= (CurAmmoGear <> nil) and (CurAmmoGear^.Kind = gtSwitcher);
-if PGear(Me)^.Hedgehog^.BotLevel <> 5 then
+if Me^.Hedgehog^.BotLevel <> 5 then
     switchCount:= HHHasAmmo(PGear(Me)^.Hedgehog^, amSwitch)
 else switchCount:= 0;
 
-if (PGear(Me)^.State and gstAttacking) = 0 then
+if ((Me^.State and gstAttacked) = 0) or isInMultiShoot then
     if Targets.Count > 0 then
         begin
         // iterate over current team hedgehogs
@@ -422,7 +408,7 @@
                     begin
                     // when AI has to use switcher, make it cost smth unless they have a lot of switches
                     if (switchCount < 10) then Actions.Score:= (-27+switchCount*3)*4000;
-                    AddAction(Actions, aia_Weapon, Longword(amSwitch), 300 + random(200), 0, 0);                    
+                    AddAction(Actions, aia_Weapon, Longword(amSwitch), 300 + random(200), 0, 0);
                     AddAction(Actions, aia_attack, aim_push, 300 + random(300), 0, 0);
                     AddAction(Actions, aia_attack, aim_release, 1, 0, 0);
                     end;
@@ -436,10 +422,9 @@
                 itHedgehog:= Succ(itHedgehog) mod CurrentTeam^.HedgehogsNumber;
             until (itHedgehog = currHedgehogIndex) or ((CurrentTeam^.Hedgehogs[itHedgehog].Gear <> nil) and (CurrentTeam^.Hedgehogs[itHedgehog].Effects[heFrozen]=0));
 
-
             inc(switchesNum);
         until (not (switchImmediatelyAvailable or (switchCount > 0)))
-            or StopThinking 
+            or StopThinking
             or (itHedgehog = currHedgehogIndex)
             or BestActions.isWalkingToABetterPlace;
 
@@ -460,10 +445,9 @@
         end else SDL_Delay(100)
 else
     begin
-    BackMe:= PGear(Me)^;
-    
-//{$IFNDEF AI_MAINTHREAD}
-    while (not StopThinking) and (BestActions.Count = 0) do
+    BackMe:= Me^;
+    i:= 12;
+    while (not StopThinking) and (BestActions.Count = 0) and (i > 0) do
         begin
 
 (*
@@ -478,17 +462,17 @@
         Actions.Pos:= 0;
         Actions.Score:= 0;
         Walk(@WalkMe, Actions);
-{$IFNDEF AI_MAINTHREAD}
-        if (not StopThinking) then
+        dec(i);
+        if not StopThinking then
             SDL_Delay(100)
-{$ENDIF}
         end
-//{$ENDIF}
     end;
 
-PGear(Me)^.State:= PGear(Me)^.State and (not gstHHThinking);
+Me^.State:= Me^.State and (not gstHHThinking);
+SDL_LockMutex(ThreadLock);
+ThinkThread:= nil;
+SDL_UnlockMutex(ThreadLock);
 Think:= 0;
-InterlockedDecrement(hasThread)
 end;
 
 procedure StartThink(Me: PGear);
@@ -517,22 +501,16 @@
     exit
     end;
 
-FillBonuses((Me^.State and gstAttacked) <> 0);
-AddFileLog('Enter Think Thread');
+FillBonuses(((Me^.State and gstAttacked) <> 0) and (not isInMultiShoot));
 
-{$IFDEF AI_MAINTHREAD}
-Think(Me);
-{$ELSE}
-{$IFDEF USE_SDLTHREADS}
-ThinkThread := SDL_CreateThread(@Think{$IFDEF SDL13}, nil{$ENDIF}, Me);
-{$ELSE}
-BeginThread(@Think, Me, ThinkThread);
-{$ENDIF}
-AddFileLog('Thread started');
-{$ENDIF}
+SDL_LockMutex(ThreadLock);
+ThinkThread:= SDL_CreateThread(@Think{$IFDEF SDL13}, 'think'{$ENDIF}, Me);
+SDL_UnlockMutex(ThreadLock);
 end;
 
-//var scoreShown: boolean = false;
+{$IFDEF DEBUGAI}
+var scoreShown: boolean = false;
+{$ENDIF}
 
 procedure ProcessBot;
 const cStopThinkTime = 40;
@@ -550,21 +528,25 @@
                     StopMessages(Gear^.Message);
                     TryDo((Gear^.Message and gmAllStoppable) = 0, 'Engine bug: AI may break demos playing', true);
                     end;
-                    
+
                 if Gear^.Message <> 0 then
                     exit;
-                    
-                //scoreShown:= false;   
+
+{$IFDEF DEBUGAI}
+                scoreShown:= false;
+{$ENDIF}
                 StartThink(Gear);
                 StartTicks:= GameTicks
-                
+
             end else
                 begin
-                {if not scoreShown then
+{$IFDEF DEBUGAI}
+                if not scoreShown then
                     begin
                     if BestActions.Score > 0 then ParseCommand('/say Expected score = ' + inttostr(BestActions.Score div 1024), true);
                     scoreShown:= true
-                    end;}
+                    end;
+{$ENDIF}
                 ProcessAction(BestActions, Gear)
                 end
         else if ((GameTicks - StartTicks) > cMaxAIThinkTime)
@@ -574,16 +556,15 @@
 
 procedure initModule;
 begin
-    hasThread:= 0;
     StartTicks:= 0;
-{$IFNDEF PAS2C}
-    ThinkThread:= ThinkThread;
-{$ENDIF}
+    ThinkThread:= nil;
+    ThreadLock:= SDL_CreateMutex();
 end;
 
 procedure freeModule;
 begin
     FreeActionsList();
+    SDL_DestroyMutex(ThreadLock);
 end;
 
 end.
--- a/hedgewars/uAIActions.pas	Thu Apr 04 14:37:19 2013 +0200
+++ b/hedgewars/uAIActions.pas	Tue Jun 04 22:28:12 2013 +0200
@@ -1,6 +1,6 @@
 (*
  * Hedgewars, a free turn based strategy game
- * Copyright (c) 2004-2012 Andrey Korotaev <unC0Rr@gmail.com>
+ * Copyright (c) 2004-2013 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
--- a/hedgewars/uAIAmmoTests.pas	Thu Apr 04 14:37:19 2013 +0200
+++ b/hedgewars/uAIAmmoTests.pas	Tue Jun 04 22:28:12 2013 +0200
@@ -1,6 +1,6 @@
 (*
  * Hedgewars, a free turn based strategy game
- * Copyright (c) 2004-2012 Andrey Korotaev <unC0Rr@gmail.com>
+ * Copyright (c) 2004-2013 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
@@ -20,7 +20,7 @@
 
 unit uAIAmmoTests;
 interface
-uses SDLh, uConsts, uFloat, uTypes;
+uses SDLh, uConsts, uFloat, uTypes, uAIMisc;
 const
     amtest_Rare     = $00000001; // check only several positions
     amtest_NoTarget = $00000002; // each pos, but no targetting
@@ -34,27 +34,27 @@
         AttackPutX, AttackPutY: LongInt;
         end;
 
-function TestBazooka(Me: PGear; Targ: TPoint; Level: LongInt; var ap: TAttackParams): LongInt;
-function TestSnowball(Me: PGear; Targ: TPoint; Level: LongInt; var ap: TAttackParams): LongInt;
-function TestGrenade(Me: PGear; Targ: TPoint; Level: LongInt; var ap: TAttackParams): LongInt;
-function TestMolotov(Me: PGear; Targ: TPoint; Level: LongInt; var ap: TAttackParams): LongInt;
-function TestClusterBomb(Me: PGear; Targ: TPoint; Level: LongInt; var ap: TAttackParams): LongInt;
-function TestWatermelon(Me: PGear; Targ: TPoint; Level: LongInt; var ap: TAttackParams): LongInt;
-function TestDrillRocket(Me: PGear; Targ: TPoint; Level: LongInt; var ap: TAttackParams): LongInt;
-function TestMortar(Me: PGear; Targ: TPoint; Level: LongInt; var ap: TAttackParams): LongInt;
-function TestShotgun(Me: PGear; Targ: TPoint; Level: LongInt; var ap: TAttackParams): LongInt;
-function TestDesertEagle(Me: PGear; Targ: TPoint; Level: LongInt; var ap: TAttackParams): LongInt;
-function TestSniperRifle(Me: PGear; Targ: TPoint; Level: LongInt; var ap: TAttackParams): LongInt;
-function TestBaseballBat(Me: PGear; Targ: TPoint; Level: LongInt; var ap: TAttackParams): LongInt;
-function TestFirePunch(Me: PGear; Targ: TPoint; Level: LongInt; var ap: TAttackParams): LongInt;
-function TestWhip(Me: PGear; Targ: TPoint; Level: LongInt; var ap: TAttackParams): LongInt;
-function TestKamikaze(Me: PGear; Targ: TPoint; Level: LongInt; var ap: TAttackParams): LongInt;
-function TestAirAttack(Me: PGear; Targ: TPoint; Level: LongInt; var ap: TAttackParams): LongInt;
-function TestTeleport(Me: PGear; Targ: TPoint; Level: LongInt; var ap: TAttackParams): LongInt;
-function TestHammer(Me: PGear; Targ: TPoint; Level: LongInt; var ap: TAttackParams): LongInt;
-function TestCake(Me: PGear; Targ: TPoint; Level: LongInt; var ap: TAttackParams): LongInt;
+function TestBazooka(Me: PGear; Targ: TTarget; Level: LongInt; var ap: TAttackParams): LongInt;
+function TestSnowball(Me: PGear; Targ: TTarget; Level: LongInt; var ap: TAttackParams): LongInt;
+function TestGrenade(Me: PGear; Targ: TTarget; Level: LongInt; var ap: TAttackParams): LongInt;
+function TestMolotov(Me: PGear; Targ: TTarget; Level: LongInt; var ap: TAttackParams): LongInt;
+function TestClusterBomb(Me: PGear; Targ: TTarget; Level: LongInt; var ap: TAttackParams): LongInt;
+function TestWatermelon(Me: PGear; Targ: TTarget; Level: LongInt; var ap: TAttackParams): LongInt;
+function TestDrillRocket(Me: PGear; Targ: TTarget; Level: LongInt; var ap: TAttackParams): LongInt;
+function TestMortar(Me: PGear; Targ: TTarget; Level: LongInt; var ap: TAttackParams): LongInt;
+function TestShotgun(Me: PGear; Targ: TTarget; Level: LongInt; var ap: TAttackParams): LongInt;
+function TestDesertEagle(Me: PGear; Targ: TTarget; Level: LongInt; var ap: TAttackParams): LongInt;
+function TestSniperRifle(Me: PGear; Targ: TTarget; Level: LongInt; var ap: TAttackParams): LongInt;
+function TestBaseballBat(Me: PGear; Targ: TTarget; Level: LongInt; var ap: TAttackParams): LongInt;
+function TestFirePunch(Me: PGear; Targ: TTarget; Level: LongInt; var ap: TAttackParams): LongInt;
+function TestWhip(Me: PGear; Targ: TTarget; Level: LongInt; var ap: TAttackParams): LongInt;
+function TestKamikaze(Me: PGear; Targ: TTarget; Level: LongInt; var ap: TAttackParams): LongInt;
+function TestAirAttack(Me: PGear; Targ: TTarget; Level: LongInt; var ap: TAttackParams): LongInt;
+function TestTeleport(Me: PGear; Targ: TTarget; Level: LongInt; var ap: TAttackParams): LongInt;
+function TestHammer(Me: PGear; Targ: TTarget; Level: LongInt; var ap: TAttackParams): LongInt;
+function TestCake(Me: PGear; Targ: TTarget; Level: LongInt; var ap: TAttackParams): LongInt;
 
-type TAmmoTestProc = function (Me: PGear; Targ: TPoint; Level: LongInt; var ap: TAttackParams): LongInt;
+type TAmmoTestProc = function (Me: PGear; Targ: TTarget; Level: LongInt; var ap: TAttackParams): LongInt;
     TAmmoTest = record
             proc: TAmmoTestProc;
             flags: Longword;
@@ -123,14 +123,14 @@
             );
 
 implementation
-uses uAIMisc, uVariables, uUtils, uGearsHandlers;
+uses uVariables, uUtils, uGearsHandlers;
 
 function Metric(x1, y1, x2, y2: LongInt): LongInt; inline;
 begin
 Metric:= abs(x1 - x2) + abs(y1 - y2)
 end;
 
-function TestBazooka(Me: PGear; Targ: TPoint; Level: LongInt; var ap: TAttackParams): LongInt;
+function TestBazooka(Me: PGear; Targ: TTarget; Level: LongInt; var ap: TAttackParams): LongInt;
 var Vx, Vy, r, mX, mY: real;
     rTime: LongInt;
     EX, EY: LongInt;
@@ -147,8 +147,8 @@
 valueResult:= BadTurn;
 repeat
     rTime:= rTime + 300 + Level * 50 + random(300);
-    Vx:= - windSpeed * rTime * 0.5 + (Targ.X + AIrndSign(2) - mX) / rTime;
-    Vy:= cGravityf * rTime * 0.5 - (Targ.Y + 1 - mY) / rTime;
+    Vx:= - windSpeed * rTime * 0.5 + (Targ.Point.X + AIrndSign(2) - mX) / rTime;
+    Vy:= cGravityf * rTime * 0.5 - (Targ.Point.Y + 1 - mY) / rTime;
     r:= sqr(Vx) + sqr(Vy);
     if not (r > 1) then
         begin
@@ -164,15 +164,15 @@
             dY:= dY + cGravityf;
             dec(t)
         until (((Me = CurrentHedgehog^.Gear) and TestColl(trunc(x), trunc(y), 5)) or
-               ((Me <> CurrentHedgehog^.Gear) and TestCollExcludingMe(Me, trunc(x), trunc(y), 5))) or (t <= 0);
+               ((Me <> CurrentHedgehog^.Gear) and TestCollExcludingMe(Me^.Hedgehog^.Gear, trunc(x), trunc(y), 5))) or (t <= 0);
 
         EX:= trunc(x);
         EY:= trunc(y);
         if Level = 1 then
             value:= RateExplosion(Me, EX, EY, 101, afTrackFall or afErasesLand)
         else value:= RateExplosion(Me, EX, EY, 101);
-        if value = 0 then
-            value:= 1024 - Metric(Targ.X, Targ.Y, EX, EY) div 64;
+        if (value = 0) and (Targ.Kind = gtHedgehog) and (Targ.Score > 0) then
+            value:= 1024 - Metric(Targ.Point.X, Targ.Point.Y, EX, EY) div 64;
         if valueResult <= value then
             begin
             ap.Angle:= DxDy2AttackAnglef(Vx, Vy) + AIrndSign(random((Level - 1) * 9));
@@ -184,12 +184,12 @@
             end;
         end
 //until (value > 204800) or (rTime > 4250); not so useful since adding score to the drowning
-until rTime > 4250;
+until rTime > 5050 - Level * 800;
 TestBazooka:= valueResult
 end;
 
 
-function TestDrillRocket(Me: PGear; Targ: TPoint; Level: LongInt; var ap: TAttackParams): LongInt;
+function TestDrillRocket(Me: PGear; Targ: TTarget; Level: LongInt; var ap: TAttackParams): LongInt;
 var Vx, Vy, r, mX, mY: real;
     rTime: LongInt;
     EX, EY: LongInt;
@@ -210,8 +210,8 @@
     valueResult:= BadTurn;
     repeat
         rTime:= rTime + 300 + Level * 50 + random(300);
-        Vx:= - windSpeed * rTime * 0.5 + (Targ.X + AIrndSign(2) - mX) / rTime;
-        Vy:= cGravityf * rTime * 0.5 - (Targ.Y - 35 - mY) / rTime;
+        Vx:= - windSpeed * rTime * 0.5 + (Targ.Point.X + AIrndSign(2) - mX) / rTime;
+        Vy:= cGravityf * rTime * 0.5 - (Targ.Point.Y - 35 - mY) / rTime;
         r:= sqr(Vx) + sqr(Vy);
         if not (r > 1) then
             begin
@@ -227,9 +227,9 @@
                 dY:= dY + cGravityf;
                 dec(t)
             until (((Me = CurrentHedgehog^.Gear) and TestColl(trunc(x), trunc(y), 5)) or
-                   ((Me <> CurrentHedgehog^.Gear) and TestCollExcludingMe(Me, trunc(x), trunc(y), 5))) or (y > cWaterLine);
+                   ((Me <> CurrentHedgehog^.Gear) and TestCollExcludingMe(Me^.Hedgehog^.Gear, trunc(x), trunc(y), 5))) or (y > cWaterLine);
 
-            if TestCollWithLand(trunc(x), trunc(y), 5) and (Abs(Targ.X - trunc(x)) + Abs(Targ.Y - trunc(y)) > 21) then
+            if TestCollExcludingObjects(trunc(x), trunc(y), 5) and (Abs(Targ.Point.X - trunc(x)) + Abs(Targ.Point.Y - trunc(y)) > 21) then
                 begin
                 timer := 500;
                 t2 := 0.5 / sqrt(sqr(dX) + sqr(dY));
@@ -239,16 +239,18 @@
                     x:= x + dX;
                     y:= y + dY;
                     dec(timer);
-                until (Abs(Targ.X - trunc(x)) + Abs(Targ.Y - trunc(y)) < 22)
+                until (Abs(Targ.Point.X - trunc(x)) + Abs(Targ.Point.Y - trunc(y)) < 22)
                     or (x < 0)
                     or (y < 0)
                     or (trunc(x) > LAND_WIDTH)
                     or (trunc(y) > LAND_HEIGHT)
-                    or (not TestCollWithLand(trunc(x), trunc(y), 5))
+                    or not TestCollExcludingObjects(trunc(x), trunc(y), 5)
                     or (timer = 0)
                 end;
             EX:= trunc(x);
             EY:= trunc(y);
+            // Try to prevent AI from thinking firing into water will cause a drowning
+            if (EY < cWaterLine-5) and (Timer > 0) and (Abs(Targ.Point.X - trunc(x)) + Abs(Targ.Point.Y - trunc(y)) > 21) then exit(BadTurn);
             if Level = 1 then
                 value:= RateExplosion(Me, EX, EY, 101, afTrackFall or afErasesLand)
             else value:= RateExplosion(Me, EX, EY, 101);
@@ -262,12 +264,12 @@
                 valueResult:= value-2500 // trying to make it slightly less attractive than a bazooka, to prevent waste.  AI could use awareness of weapon count
                 end;
             end
-    until rTime > 4250;
+    until rTime > 5050 - Level * 800;
     TestDrillRocket:= valueResult
 end;
 
 
-function TestSnowball(Me: PGear; Targ: TPoint; Level: LongInt; var ap: TAttackParams): LongInt;
+function TestSnowball(Me: PGear; Targ: TTarget; Level: LongInt; var ap: TAttackParams): LongInt;
 var Vx, Vy, r: real;
     rTime: LongInt;
     EX, EY: LongInt;
@@ -285,8 +287,8 @@
 valueResult:= BadTurn;
 repeat
     rTime:= rTime + 300 + Level * 50 + random(1000);
-    Vx:= - windSpeed * rTime * 0.5 + ((Targ.X + AIrndSign(2)) - meX) / rTime;
-    Vy:= cGravityf * rTime * 0.5 - (Targ.Y - meY) / rTime;
+    Vx:= - windSpeed * rTime * 0.5 + ((Targ.Point.X + AIrndSign(2)) - meX) / rTime;
+    Vy:= cGravityf * rTime * 0.5 - (Targ.Point.Y - meY) / rTime;
     r:= sqr(Vx) + sqr(Vy);
     if not (r > 1) then
         begin
@@ -302,14 +304,14 @@
             dY:= dY + cGravityf;
             dec(t)
         until (((Me = CurrentHedgehog^.Gear) and TestColl(trunc(x), trunc(y), 5)) or
-               ((Me <> CurrentHedgehog^.Gear) and TestCollExcludingMe(Me, trunc(x), trunc(y), 5))) or (t <= 0);
+               ((Me <> CurrentHedgehog^.Gear) and TestCollExcludingMe(Me^.Hedgehog^.Gear, trunc(x), trunc(y), 5))) or (t <= 0);
         EX:= trunc(x);
         EY:= trunc(y);
 
-        value:= RateShove(trunc(x), trunc(y), 5, 1, trunc((abs(dX)+abs(dY))*20), -dX, -dY, afTrackFall);
+        value:= RateShove(Me, trunc(x), trunc(y), 5, 1, trunc((abs(dX)+abs(dY))*20), -dX, -dY, afTrackFall);
         // LOL copypasta: this is score for digging with... snowball
         //if value = 0 then
-        //    value:= - Metric(Targ.X, Targ.Y, EX, EY) div 64;
+        //    value:= - Metric(Targ.Point.X, Targ.Point.Y, EX, EY) div 64;
 
         if valueResult <= value then
             begin
@@ -321,11 +323,11 @@
             valueResult:= value
             end;
      end
-until (rTime > 4250);
+until (rTime > 5050 - Level * 800);
 TestSnowball:= valueResult
 end;
 
-function TestMolotov(Me: PGear; Targ: TPoint; Level: LongInt; var ap: TAttackParams): LongInt;
+function TestMolotov(Me: PGear; Targ: TTarget; Level: LongInt; var ap: TAttackParams): LongInt;
 var Vx, Vy, r: real;
     Score, EX, EY, valueResult: LongInt;
     TestTime: Longword;
@@ -339,8 +341,8 @@
 ap.ExplR:= 0;
 repeat
     inc(TestTime, 300);
-    Vx:= (Targ.X - meX) / TestTime;
-    Vy:= cGravityf * (TestTime div 2) - Targ.Y - meY / TestTime;
+    Vx:= (Targ.Point.X - meX) / TestTime;
+    Vy:= cGravityf * (TestTime div 2) - Targ.Point.Y - meY / TestTime;
     r:= sqr(Vx) + sqr(Vy);
     if not (r > 1) then
         begin
@@ -354,7 +356,7 @@
             dY:= dY + cGravityf;
             dec(t)
         until (((Me = CurrentHedgehog^.Gear) and TestColl(trunc(x), trunc(y), 6)) or
-               ((Me <> CurrentHedgehog^.Gear) and TestCollExcludingMe(Me, trunc(x), trunc(y), 6))) or (t = 0);
+               ((Me <> CurrentHedgehog^.Gear) and TestCollExcludingMe(Me^.Hedgehog^.Gear, trunc(x), trunc(y), 6))) or (t = 0);
         EX:= trunc(x);
         EY:= trunc(y);
         if t < 50 then
@@ -372,11 +374,11 @@
             valueResult:= Score
             end;
         end
-until (TestTime > 4250);
+until (TestTime > 5050 - Level * 800);
 TestMolotov:= valueResult
 end;
 
-function TestGrenade(Me: PGear; Targ: TPoint; Level: LongInt; var ap: TAttackParams): LongInt;
+function TestGrenade(Me: PGear; Targ: TTarget; Level: LongInt; var ap: TAttackParams): LongInt;
 const tDelta = 24;
 var Vx, Vy, r: real;
     Score, EX, EY, valueResult: LongInt;
@@ -391,8 +393,8 @@
 meY:= hwFloat2Float(Me^.Y);
 repeat
     inc(TestTime, 1000);
-    Vx:= (Targ.X - meX) / (TestTime + tDelta);
-    Vy:= cGravityf * ((TestTime + tDelta) div 2) - (Targ.Y - meY) / (TestTime + tDelta);
+    Vx:= (Targ.Point.X - meX) / (TestTime + tDelta);
+    Vy:= cGravityf * ((TestTime + tDelta) div 2) - (Targ.Point.Y - meY) / (TestTime + tDelta);
     r:= sqr(Vx) + sqr(Vy);
     if not (r > 1) then
         begin
@@ -406,7 +408,7 @@
             dY:= dY + cGravityf;
             dec(t)
         until (((Me = CurrentHedgehog^.Gear) and TestColl(trunc(x), trunc(y), 5)) or
-               ((Me <> CurrentHedgehog^.Gear) and TestCollExcludingMe(Me, trunc(x), trunc(y), 5))) or (t = 0);
+               ((Me <> CurrentHedgehog^.Gear) and TestCollExcludingMe(Me^.Hedgehog^.Gear, trunc(x), trunc(y), 5))) or (t = 0);
     EX:= trunc(x);
     EY:= trunc(y);
     if t < 50 then
@@ -418,8 +420,8 @@
 
     if (valueResult < Score) and (Score > 0) then
         begin
-        ap.Angle:= DxDy2AttackAnglef(Vx, Vy) + AIrndSign(random(Level));
-        ap.Power:= trunc(sqrt(r) * cMaxPower) + AIrndSign(random(Level) * 15);
+        ap.Angle:= DxDy2AttackAnglef(Vx, Vy) + AIrndSign(random(Level * 3));
+        ap.Power:= trunc(sqrt(r) * cMaxPower) + AIrndSign(random(Level) * 20);
         ap.Time:= TestTime;
         ap.ExplR:= 100;
         ap.ExplX:= EX;
@@ -428,11 +430,11 @@
         end;
     end
 //until (Score > 204800) or (TestTime > 4000);
-until TestTime > 4000;
+until TestTime > 4500 - Level * 512;
 TestGrenade:= valueResult
 end;
 
-function TestClusterBomb(Me: PGear; Targ: TPoint; Level: LongInt; var ap: TAttackParams): LongInt;
+function TestClusterBomb(Me: PGear; Targ: TTarget; Level: LongInt; var ap: TAttackParams): LongInt;
 const tDelta = 24;
 var Vx, Vy, r: real;
     Score, EX, EY, valueResult: LongInt;
@@ -448,11 +450,11 @@
 repeat
     inc(TestTime, 900);
     // Try to overshoot slightly, seems to pay slightly better dividends in terms of hitting cluster
-    if meX<Targ.X then
-        Vx:= ((Targ.X+10) - meX) / (TestTime + tDelta)
+    if meX<Targ.Point.X then
+        Vx:= ((Targ.Point.X+10) - meX) / (TestTime + tDelta)
     else
-        Vx:= ((Targ.X-10) - meX) / (TestTime + tDelta);
-    Vy:= cGravityf * ((TestTime + tDelta) div 2) - ((Targ.Y-50) - meY) / (TestTime + tDelta);
+        Vx:= ((Targ.Point.X-10) - meX) / (TestTime + tDelta);
+    Vy:= cGravityf * ((TestTime + tDelta) div 2) - ((Targ.Point.Y-50) - meY) / (TestTime + tDelta);
     r:= sqr(Vx)+sqr(Vy);
     if not (r > 1) then
         begin
@@ -466,7 +468,7 @@
         dY:= dY + cGravityf;
         dec(t)
     until (((Me = CurrentHedgehog^.Gear) and TestColl(trunc(x), trunc(y), 5)) or
-           ((Me <> CurrentHedgehog^.Gear) and TestCollExcludingMe(Me, trunc(x), trunc(y), 5))) or (t = 0);
+           ((Me <> CurrentHedgehog^.Gear) and TestCollExcludingMe(Me^.Hedgehog^.Gear, trunc(x), trunc(y), 5))) or (t = 0);
     EX:= trunc(x);
     EY:= trunc(y);
     if t < 50 then
@@ -474,9 +476,9 @@
     else
         Score:= BadTurn;
 
-     if valueResult < Score then
+     if Score > 0 then
         begin
-        ap.Angle:= DxDy2AttackAnglef(Vx, Vy) + AIrndSign(random(Level));
+        ap.Angle:= DxDy2AttackAnglef(Vx, Vy) + AIrndSign(random(Level * 2));
         ap.Power:= trunc(sqrt(r) * cMaxPower) + AIrndSign(random(Level) * 15);
         ap.Time:= TestTime div 1000 * 1000;
         ap.ExplR:= 90;
@@ -489,7 +491,7 @@
 TestClusterBomb:= valueResult
 end;
 
-function TestWatermelon(Me: PGear; Targ: TPoint; Level: LongInt; var ap: TAttackParams): LongInt;
+function TestWatermelon(Me: PGear; Targ: TTarget; Level: LongInt; var ap: TAttackParams): LongInt;
 const tDelta = 24;
 var Vx, Vy, r: real;
     Score, EX, EY, valueResult: LongInt;
@@ -504,8 +506,8 @@
 meY:= hwFloat2Float(Me^.Y);
 repeat
     inc(TestTime, 900);
-    Vx:= (Targ.X - meX) / (TestTime + tDelta);
-    Vy:= cGravityf * ((TestTime + tDelta) div 2) - ((Targ.Y-50) - meY) / (TestTime + tDelta);
+    Vx:= (Targ.Point.X - meX) / (TestTime + tDelta);
+    Vy:= cGravityf * ((TestTime + tDelta) div 2) - ((Targ.Point.Y-50) - meY) / (TestTime + tDelta);
     r:= sqr(Vx)+sqr(Vy);
     if not (r > 1) then
         begin
@@ -519,7 +521,7 @@
             dY:= dY + cGravityf;
             dec(t)
        until (((Me = CurrentHedgehog^.Gear) and TestColl(trunc(x), trunc(y), 6)) or
-               ((Me <> CurrentHedgehog^.Gear) and TestCollExcludingMe(Me, trunc(x), trunc(y), 6))) or (t = 0);
+               ((Me <> CurrentHedgehog^.Gear) and TestCollExcludingMe(Me^.Hedgehog^.Gear, trunc(x), trunc(y), 6))) or (t = 0);
 
         EX:= trunc(x);
         EY:= trunc(y);
@@ -565,7 +567,7 @@
                 Solve:= 0
     end;
 
-function TestMortar(Me: PGear; Targ: TPoint; Level: LongInt; var ap: TAttackParams): LongInt;
+function TestMortar(Me: PGear; Targ: TTarget; Level: LongInt; var ap: TAttackParams): LongInt;
 //const tDelta = 24;
 var Vx, Vy: real;
     Score, EX, EY: LongInt;
@@ -581,13 +583,13 @@
     if (Level > 2) then
         exit(BadTurn);
 
-    TestTime:= Solve(Targ.X, Targ.Y, trunc(meX), trunc(meY));
+    TestTime:= Solve(Targ.Point.X, Targ.Point.Y, trunc(meX), trunc(meY));
 
     if TestTime = 0 then
         exit(BadTurn);
 
-    Vx:= (Targ.X - meX) / TestTime;
-    Vy:= cGravityf * (TestTime div 2) - (Targ.Y - meY) / TestTime;
+    Vx:= (Targ.Point.X - meX) / TestTime;
+    Vy:= cGravityf * (TestTime div 2) - (Targ.Point.Y - meY) / TestTime;
 
     x:= meX;
     y:= meY;
@@ -600,14 +602,14 @@
         EX:= trunc(x);
         EY:= trunc(y);
     until (((Me = CurrentHedgehog^.Gear) and TestColl(EX, EY, 4)) or
-           ((Me <> CurrentHedgehog^.Gear) and TestCollExcludingMe(Me, EX, EY, 4))) or (EY > cWaterLine);
+           ((Me <> CurrentHedgehog^.Gear) and TestCollExcludingMe(Me^.Hedgehog^.Gear, EX, EY, 4))) or (EY > cWaterLine);
 
     if (EY < cWaterLine) and (dY >= 0) then
         begin
         Score:= RateExplosion(Me, EX, EY, 91);
         if (Score = 0) then
-            if (dY > 0.15) then
-                Score:= - abs(Targ.Y - EY) div 32
+            if (dY > 0.15) and (Targ.Kind = gtHedgehog) and (Targ.Score > 0) then
+                Score:= - abs(Targ.Point.Y - EY) div 32
             else
                 Score:= BadTurn
         else if (Score < 0) then
@@ -616,7 +618,7 @@
     else
         Score:= BadTurn;
 
-    if BadTurn < Score then
+    if Score > 0 then
         begin
         ap.Angle:= DxDy2AttackAnglef(Vx, Vy) + AIrndSign(random(Level));
         ap.Power:= 1;
@@ -627,7 +629,7 @@
         end;
 end;
 
-function TestShotgun(Me: PGear; Targ: TPoint; Level: LongInt; var ap: TAttackParams): LongInt;
+function TestShotgun(Me: PGear; Targ: TTarget; Level: LongInt; var ap: TAttackParams): LongInt;
 const
     MIN_RANGE =  80;
     MAX_RANGE = 400;
@@ -641,12 +643,12 @@
 ap.Power:= 1;
 x:= hwFloat2Float(Me^.X);
 y:= hwFloat2Float(Me^.Y);
-range:= Metric(trunc(x), trunc(y), Targ.X, Targ.Y);
+range:= Metric(trunc(x), trunc(y), Targ.Point.X, Targ.Point.Y);
 if ( range < MIN_RANGE ) or ( range > MAX_RANGE ) then
     exit(BadTurn);
 
-Vx:= (Targ.X - x) * 1 / 1024;
-Vy:= (Targ.Y - y) * 1 / 1024;
+Vx:= (Targ.Point.X - x) * 1 / 1024;
+Vy:= (Targ.Point.Y - y) * 1 / 1024;
 ap.Angle:= DxDy2AttackAnglef(Vx, -Vy);
 repeat
     x:= x + vX;
@@ -654,20 +656,20 @@
     rx:= trunc(x);
     ry:= trunc(y);
     if ((Me = CurrentHedgehog^.Gear) and TestColl(rx, ry, 2)) or
-        ((Me <> CurrentHedgehog^.Gear) and TestCollExcludingMe(Me, rx, ry, 2)) then
+        ((Me <> CurrentHedgehog^.Gear) and TestCollExcludingMe(Me^.Hedgehog^.Gear, rx, ry, 2)) then
     begin
         x:= x + vX * 8;
         y:= y + vY * 8;
         valueResult:= RateShotgun(Me, vX, vY, rx, ry);
 
-        if valueResult = 0 then
-            valueResult:= 1024 - Metric(Targ.X, Targ.Y, rx, ry) div 64
+        if (valueResult = 0) and (Targ.Kind = gtHedgehog) and (Targ.Score > 0) then
+            valueResult:= 1024 - Metric(Targ.Point.X, Targ.Point.Y, rx, ry) div 64
         else
             dec(valueResult, Level * 4000);
         // 27/20 is reuse bonus
         exit(valueResult * 27 div 20)
     end
-until (Abs(Targ.X - trunc(x)) + Abs(Targ.Y - trunc(y)) < 4)
+until (Abs(Targ.Point.X - trunc(x)) + Abs(Targ.Point.Y - trunc(y)) < 4)
     or (x < 0)
     or (y < 0)
     or (trunc(x) > LAND_WIDTH)
@@ -676,27 +678,26 @@
 TestShotgun:= BadTurn
 end;
 
-function TestDesertEagle(Me: PGear; Targ: TPoint; Level: LongInt; var ap: TAttackParams): LongInt;
-var Vx, Vy, x, y, t, dmgMod: real;
+function TestDesertEagle(Me: PGear; Targ: TTarget; Level: LongInt; var ap: TAttackParams): LongInt;
+var Vx, Vy, x, y, t: real;
     d: Longword;
     fallDmg, valueResult: LongInt;
 begin
-if Level > 4 then exit(BadTurn);
-dmgMod:= 0.01 * hwFloat2Float(cDamageModifier) * cDamagePercent;
+if (Level > 4) or (Targ.Score < 0) or (Targ.Kind <> gtHedgehog) then exit(BadTurn);
 Level:= Level; // avoid compiler hint
-ap.ExplR:= 0;
+ap.ExplR:= 1;
 ap.Time:= 0;
 ap.Power:= 1;
 
 x:= hwFloat2Float(Me^.X);
 y:= hwFloat2Float(Me^.Y);
 
-if Abs(trunc(x) - Targ.X) + Abs(trunc(y) - Targ.Y) < 20 then
+if Abs(trunc(x) - Targ.Point.X) + Abs(trunc(y) - Targ.Point.Y) < 20 then
     exit(BadTurn);
 
-t:= 2 / sqrt(sqr(Targ.X - x)+sqr(Targ.Y-y));
-Vx:= (Targ.X - x) * t;
-Vy:= (Targ.Y - y) * t;
+t:= 2 / sqrt(sqr(Targ.Point.X - x)+sqr(Targ.Point.Y-y));
+Vx:= (Targ.Point.X - x) * t;
+Vy:= (Targ.Point.Y - y) * t;
 ap.Angle:= DxDy2AttackAnglef(Vx, -Vy);
 d:= 0;
 
@@ -706,47 +707,40 @@
     if ((trunc(x) and LAND_WIDTH_MASK) = 0)and((trunc(y) and LAND_HEIGHT_MASK) = 0)
     and (Land[trunc(y), trunc(x)] <> 0) then
         inc(d);
-until (Abs(Targ.X - trunc(x)) + Abs(Targ.Y - trunc(y)) < 5)
+until (Abs(Targ.Point.X - trunc(x)) + Abs(Targ.Point.Y - trunc(y)) < 5)
     or (x < 0)
     or (y < 0)
     or (trunc(x) > LAND_WIDTH)
     or (trunc(y) > LAND_HEIGHT)
     or (d > 48);
 
-if Abs(Targ.X - trunc(x)) + Abs(Targ.Y - trunc(y)) < 5 then
-    begin
-    fallDmg:= TraceShoveFall(Targ.X, Targ.Y, vX * 0.00125 * 20, vY * 0.00125 * 20);
-    if fallDmg < 0 then
-        valueResult:= 204800
-    else valueResult:= Max(0, (4 - d div 12) * trunc((7 + fallDmg) * dmgMod) * 1024)
-    end
-else
-    valueResult:= BadTurn;
+if Abs(Targ.Point.X - trunc(x)) + Abs(Targ.Point.Y - trunc(y)) < 5 then
+     valueResult:= RateShove(Me, Targ.Point.X, Targ.Point.Y, 1, 7, 20, vX*0.125, vY*0.125, afTrackFall)
+else valueResult:= BadTurn;
 TestDesertEagle:= valueResult
 end;
 
 
-function TestSniperRifle(Me: PGear; Targ: TPoint; Level: LongInt; var ap: TAttackParams): LongInt;
-var Vx, Vy, x, y, t, dmg, dmgMod: real;
+function TestSniperRifle(Me: PGear; Targ: TTarget; Level: LongInt; var ap: TAttackParams): LongInt;
+var Vx, Vy, x, y, t, dmg: real;
     d: Longword;
     fallDmg: LongInt;
 begin
-if Level > 3 then exit(BadTurn);
-dmgMod:= 0.01 * hwFloat2Float(cDamageModifier) * cDamagePercent;
+if (Level > 3) or (Targ.Score < 0) or (Targ.Kind <> gtHedgehog) then exit(BadTurn);
 Level:= Level; // avoid compiler hint
 ap.ExplR:= 0;
 ap.Time:= 0;
 ap.Power:= 1;
 x:= hwFloat2Float(Me^.X);
 y:= hwFloat2Float(Me^.Y);
-if Abs(trunc(x) - Targ.X) + Abs(trunc(y) - Targ.Y) < 40 then
+if Abs(trunc(x) - Targ.Point.X) + Abs(trunc(y) - Targ.Point.Y) < 40 then
     exit(BadTurn);
 
-dmg:= sqrt(sqr(Targ.X - x)+sqr(Targ.Y-y));
+dmg:= sqrt(sqr(Targ.Point.X - x)+sqr(Targ.Point.Y-y));
 t:= 1.5 / dmg;
 dmg:= dmg * 0.025; // div 40
-Vx:= (Targ.X - x) * t;
-Vy:= (Targ.Y - y) * t;
+Vx:= (Targ.Point.X - x) * t;
+Vy:= (Targ.Point.Y - y) * t;
 ap.Angle:= DxDy2AttackAnglef(Vx, -Vy);
 d:= 0;
 
@@ -756,27 +750,20 @@
     if ((trunc(x) and LAND_WIDTH_MASK) = 0)and((trunc(y) and LAND_HEIGHT_MASK) = 0)
     and (Land[trunc(y), trunc(x)] <> 0) then
         inc(d);
-until (Abs(Targ.X - trunc(x)) + Abs(Targ.Y - trunc(y)) < 4)
+until (Abs(Targ.Point.X - trunc(x)) + Abs(Targ.Point.Y - trunc(y)) < 4)
     or (x < 0)
     or (y < 0)
     or (trunc(x) > LAND_WIDTH)
     or (trunc(y) > LAND_HEIGHT)
     or (d > 22);
 
-if Abs(Targ.X - trunc(x)) + Abs(Targ.Y - trunc(y)) < 4 then
-    begin
-    fallDmg:= TraceShoveFall(Targ.X, Targ.Y, vX * 0.00166 * dmg, vY * 0.00166 * dmg);
-    if fallDmg < 0 then
-        TestSniperRifle:= BadTurn
-    else
-        TestSniperRifle:= Max(0, trunc((dmg + fallDmg) * dmgMod) * 1024)
-    end
-else
-    TestSniperRifle:= BadTurn
+if Abs(Targ.Point.X - trunc(x)) + Abs(Targ.Point.Y - trunc(y)) < 4 then
+     TestSniperRifle:= RateShove(Me, Targ.Point.X, Targ.Point.Y, 1, trunc(dmg), 20, vX*0.166, vY*0.166, afTrackFall)
+else TestSniperRifle:= BadTurn;
 end;
 
 
-function TestBaseballBat(Me: PGear; Targ: TPoint; Level: LongInt; var ap: TAttackParams): LongInt;
+function TestBaseballBat(Me: PGear; Targ: TTarget; Level: LongInt; var ap: TAttackParams): LongInt;
 var valueResult, a, v1, v2: LongInt;
     x, y, trackFall: LongInt;
     dx, dy: real;
@@ -800,10 +787,10 @@
         dx:= sin(a / cMaxAngle * pi) * 0.5;
         dy:= cos(a / cMaxAngle * pi) * 0.5;
 
-        v1:= RateShove(x - 10, y + 2
+        v1:= RateShove(Me, x - 10, y + 2
                 , 32, 30, 115
                 , -dx, -dy, trackFall);
-        v2:= RateShove(x + 10, y + 2
+        v2:= RateShove(Me, x + 10, y + 2
                 , 32, 30, 115
                 , dx, -dy, trackFall);
         if (v1 > valueResult) or (v2 > valueResult) then
@@ -828,7 +815,7 @@
     TestBaseballBat:= valueResult;
 end;
 
-function TestFirePunch(Me: PGear; Targ: TPoint; Level: LongInt; var ap: TAttackParams): LongInt;
+function TestFirePunch(Me: PGear; Targ: TTarget; Level: LongInt; var ap: TAttackParams): LongInt;
 var valueResult, v1, v2, i: LongInt;
     x, y, trackFall: LongInt;
 begin
@@ -846,11 +833,11 @@
     v1:= 0;
     for i:= 0 to 8 do
         begin
-        v1:= v1 + RateShove(x - 5, y - 10 * i
+        v1:= v1 + RateShove(Me, x - 5, y - 10 * i
                 , 19, 30, 40
                 , -0.45, -0.9, trackFall or afSetSkip);
         end;
-    v1:= v1 + RateShove(x - 5, y - 90
+    v1:= v1 + RateShove(Me, x - 5, y - 90
             , 19, 30, 40
             , -0.45, -0.9, trackFall);
 
@@ -859,11 +846,11 @@
     v2:= 0;
     for i:= 0 to 8 do
         begin
-        v2:= v2 + RateShove(x + 5, y - 10 * i
+        v2:= v2 + RateShove(Me, x + 5, y - 10 * i
                 , 19, 30, 40
                 , 0.45, -0.9, trackFall or afSetSkip);
         end;
-    v2:= v2 + RateShove(x + 5, y - 90
+    v2:= v2 + RateShove(Me, x + 5, y - 90
             , 19, 30, 40
             , 0.45, -0.9, trackFall);
 
@@ -886,7 +873,7 @@
 end;
 
 
-function TestWhip(Me: PGear; Targ: TPoint; Level: LongInt; var ap: TAttackParams): LongInt;
+function TestWhip(Me: PGear; Targ: TTarget; Level: LongInt; var ap: TAttackParams): LongInt;
 var valueResult, v1, v2: LongInt;
     x, y, trackFall: LongInt;
 begin
@@ -905,19 +892,19 @@
     {first RateShove checks farthermost of two whip's AmmoShove attacks
     to encourage distant attacks (damaged hog is excluded from view of second
     RateShove call)}
-    v1:= RateShove(x - 13, y
+    v1:= RateShove(Me, x - 13, y
             , 30, 30, 25
             , -1, -0.8, trackFall or afSetSkip);
     v1:= v1 +
-        RateShove(x - 2, y
+        RateShove(Me, x - 2, y
             , 30, 30, 25
             , -1, -0.8, trackFall);
     // now try opposite direction
-    v2:= RateShove(x + 13, y
+    v2:= RateShove(Me, x + 13, y
             , 30, 30, 25
             , 1, -0.8, trackFall or afSetSkip);
     v2:= v2 +
-        RateShove(x + 2, y
+        RateShove(Me, x + 2, y
             , 30, 30, 25
             , 1, -0.8, trackFall);
 
@@ -941,7 +928,7 @@
     TestWhip:= valueResult;
 end;
 
-function TestKamikaze(Me: PGear; Targ: TPoint; Level: LongInt; var ap: TAttackParams): LongInt;
+function TestKamikaze(Me: PGear; Targ: TTarget; Level: LongInt; var ap: TAttackParams): LongInt;
 const step = 8;
 var valueResult, i, v, tx: LongInt;
     trackFall: LongInt;
@@ -963,7 +950,7 @@
 
     x:= hwFloat2Float(Me^.X);
     y:= hwFloat2Float(Me^.Y);
-    d:= sqrt(sqr(Targ.X - x) + sqr(Targ.Y - y));
+    d:= sqrt(sqr(Targ.Point.X - x) + sqr(Targ.Point.Y - y));
     if d < 10 then
         begin
         dx:= 0;
@@ -973,8 +960,8 @@
     else
         begin
         t:= step / d;
-        dx:= (Targ.X - x) * t;
-        dy:= (Targ.Y - y) * t;
+        dx:= (Targ.Point.X - x) * t;
+        dy:= (Targ.Point.Y - y) * t;
 
         ap.Angle:= DxDy2AttackAnglef(dx, -dy)
         end;
@@ -984,7 +971,7 @@
     for i:= 0 to 512 div step - 2 do
         begin
         valueResult:= valueResult +
-            RateShove(trunc(x), trunc(y)
+            RateShove(Me, trunc(x), trunc(y)
                 , 30, 30, 25
                 , cx, -0.9, trackFall or afSetSkip);
 
@@ -996,14 +983,14 @@
         x:= hwFloat2Float(Me^.X);
         y:= hwFloat2Float(Me^.Y);
         tx:= trunc(x);
-        v:= RateShove(tx, trunc(y)
+        v:= RateShove(Me, tx, trunc(y)
                 , 30, 30, 25
                 , -cx, -0.9, trackFall);
         for i:= 1 to 512 div step - 2 do
             begin
             y:= y + dy;
             v:= v +
-                RateShove(tx, trunc(y)
+                RateShove(Me, tx, trunc(y)
                     , 30, 30, 25
                     , -cx, -0.9, trackFall or afSetSkip);
             end
@@ -1014,7 +1001,7 @@
         valueResult:= v
         end;
 
-    v:= RateShove(trunc(x), trunc(y)
+    v:= RateShove(Me, trunc(x), trunc(y)
             , 30, 30, 25
             , cx, -0.9, trackFall);
     valueResult:= valueResult + v - KillScore * friendlyfactor div 100 * 1024;
@@ -1025,7 +1012,7 @@
     TestKamikaze:= valueResult;
 end;
 
-function TestHammer(Me: PGear; Targ: TPoint; Level: LongInt; var ap: TAttackParams): LongInt;
+function TestHammer(Me: PGear; Targ: TTarget; Level: LongInt; var ap: TAttackParams): LongInt;
 var rate: LongInt;
 begin
 Level:= Level; // avoid compiler hint
@@ -1042,7 +1029,7 @@
 TestHammer:= rate;
 end;
 
-function TestAirAttack(Me: PGear; Targ: TPoint; Level: LongInt; var ap: TAttackParams): LongInt;
+function TestAirAttack(Me: PGear; Targ: TTarget; Level: LongInt; var ap: TAttackParams): LongInt;
 const cShift = 4;
 var bombsSpeed, X, Y, dY: real;
     b: array[0..9] of boolean;
@@ -1056,12 +1043,12 @@
     exit(BadTurn);
 
 ap.Angle:= 0;
-ap.AttackPutX:= Targ.X;
-ap.AttackPutY:= Targ.Y;
+ap.AttackPutX:= Targ.Point.X;
+ap.AttackPutY:= Targ.Point.Y;
 
 bombsSpeed:= hwFloat2Float(cBombsSpeed);
-X:= Targ.X - 135 - cShift; // hh center - cShift
-X:= X - bombsSpeed * sqrt(((Targ.Y + 128) * 2) / cGravityf);
+X:= Targ.Point.X - 135 - cShift; // hh center - cShift
+X:= X - bombsSpeed * sqrt(((Targ.Point.Y + 128) * 2) / cGravityf);
 Y:= -128;
 dY:= 0;
 
@@ -1093,7 +1080,7 @@
 
 for i:= 0 to 5 do inc(valueResult, dmg[i]);
 t:= valueResult;
-ap.AttackPutX:= Targ.X - 60;
+ap.AttackPutX:= Targ.Point.X - 60;
 
 for i:= 0 to 3 do
     begin
@@ -1102,7 +1089,7 @@
     if t > valueResult then
         begin
         valueResult:= t;
-        ap.AttackPutX:= Targ.X - 30 - cShift + i * 30
+        ap.AttackPutX:= Targ.Point.X - 30 - cShift + i * 30
         end
     end;
 
@@ -1112,7 +1099,7 @@
 end;
 
 
-function TestTeleport(Me: PGear; Targ: TPoint; Level: LongInt; var ap: TAttackParams): LongInt;
+function TestTeleport(Me: PGear; Targ: TTarget; Level: LongInt; var ap: TAttackParams): LongInt;
 var
     i, failNum: longword;
     maxTop: longword;
@@ -1125,15 +1112,15 @@
         begin
         if Me^.Health <= 100  then
             begin
-            maxTop := Targ.Y - cHHRadius * 2;
+            maxTop := Targ.Point.Y - cHHRadius * 2;
 
-            while (not TestColl(Targ.X, maxTop, cHHRadius)) and (maxTop > topY + cHHRadius * 2 + 1) do
+            while not TestColl(Targ.Point.X, maxTop, cHHRadius) and (maxTop > topY + cHHRadius * 2 + 1) do
                 dec(maxTop, cHHRadius*2);
-            if not TestColl(Targ.X, maxTop + cHHRadius, cHHRadius) then
+            if not TestColl(Targ.Point.X, maxTop + cHHRadius, cHHRadius) then
                 begin
-                ap.AttackPutX := Targ.X;
+                ap.AttackPutX := Targ.Point.X;
                 ap.AttackPutY := maxTop + cHHRadius;
-                TestTeleport := Targ.Y - maxTop;
+                TestTeleport := Targ.Point.Y - maxTop;
                 end;
             end;
         end
@@ -1176,7 +1163,7 @@
     end;
 end;
 
-function TestCake(Me: PGear; Targ: TPoint; Level: LongInt; var ap: TAttackParams): LongInt;
+function TestCake(Me: PGear; Targ: TTarget; Level: LongInt; var ap: TAttackParams): LongInt;
 var valueResult, v1, v2: LongInt;
     cake: TGear;
 begin
--- a/hedgewars/uAIMisc.pas	Thu Apr 04 14:37:19 2013 +0200
+++ b/hedgewars/uAIMisc.pas	Tue Jun 04 22:28:12 2013 +0200
@@ -1,6 +1,6 @@
 (*
  * Hedgewars, a free turn based strategy game
- * Copyright (c) 2004-2012 Andrey Korotaev <unC0Rr@gmail.com>
+ * Copyright (c) 2004-2013 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
@@ -30,14 +30,18 @@
 
       BadTurn = Low(LongInt) div 4;
 
-type TTarget = record
+type TTarget = record // starting to look more and more like a gear
     Point: TPoint;
-    Score: LongInt;
-    skip, matters: boolean;
+    Score, Radius: LongInt;
+    State: LongWord;
+    Density: real;
+    skip, matters, dead: boolean;
+    Kind: TGearType;
     end;
 TTargets = record
     Count: Longword;
-    ar: array[0..Pred(cMaxHHs)] of TTarget;
+    ar: array[0..Pred(256)] of TTarget;
+    reset: boolean;
     end;
 TJumpType = (jmpNone, jmpHJump, jmpLJump);
 TGoInfo = record
@@ -65,6 +69,7 @@
 procedure freeModule;
 
 procedure FillTargets;
+procedure ResetTargets; inline;
 procedure AddBonus(x, y: LongInt; r: Longword; s: LongInt); inline;
 procedure FillBonuses(isAfterAttack: boolean);
 procedure AwareOfExplosion(x, y, r: LongInt); inline;
@@ -73,12 +78,11 @@
 function  TestColl(x, y, r: LongInt): boolean; inline;
 function  TestCollExcludingObjects(x, y, r: LongInt): boolean; inline;
 function  TestCollExcludingMe(Me: PGear; x, y, r: LongInt): boolean; inline;
-function  TraceShoveFall(x, y, dX, dY: Real): LongInt;
-function TestCollWithLand(x, y, r: LongInt): boolean; inline;
 
 function  RateExplosion(Me: PGear; x, y, r: LongInt): LongInt; inline;
-function  RateExplosion(Me: PGear; x, y, r: LongInt; Flags: LongWord): LongInt;
-function  RateShove(x, y, r, power, kick: LongInt; gdX, gdY: real; Flags: LongWord): LongInt;
+function  RateExplosion(Me: PGear; x, y, r: LongInt; Flags: LongWord): LongInt; inline;
+function  RealRateExplosion(Me: PGear; x, y, r: LongInt; Flags: LongWord): LongInt;
+function  RateShove(Me: PGear; x, y, r, power, kick: LongInt; gdX, gdY: real; Flags: LongWord): LongInt;
 function  RateShotgun(Me: PGear; gdX, gdY: real; x, y: LongInt): LongInt;
 function  RateHammer(Me: PGear): LongInt;
 
@@ -94,52 +98,82 @@
 
 const KillScore = 200;
 var friendlyfactor: LongInt = 300;
+var dmgMod: real = 1.0;
 
 implementation
 uses uCollisions, uVariables, uUtils, uLandTexture, uGearsUtils;
 
-var 
+var
     KnownExplosion: record
         X, Y, Radius: LongInt
         end = (X: 0; Y: 0; Radius: 0);
 
+procedure ResetTargets; inline;
+var i: LongWord;
+begin
+if Targets.reset then
+    for i:= 0 to Targets.Count do
+        Targets.ar[i].dead:= false;
+Targets.reset:= false;
+end;
 procedure FillTargets;
 var i, t: Longword;
     f, e: LongInt;
+    Gear: PGear;
 begin
 Targets.Count:= 0;
+Targets.reset:= false;
 f:= 0;
 e:= 0;
-for t:= 0 to Pred(TeamsCount) do
-    with TeamsArray[t]^ do
-        if not hasGone then
+Gear:= GearsList;
+while Gear <> nil do
+    begin
+    if  (((Gear^.Kind = gtHedgehog) and
+            (Gear <> ThinkingHH) and
+            (Gear^.Health > Gear^.Damage) and
+            not(Gear^.Hedgehog^.Team^.hasgone)) or
+        ((Gear^.Kind = gtExplosives) and
+            (Gear^.Health > Gear^.Damage)) or
+        ((Gear^.Kind = gtMine) and
+            (Gear^.Health = 0) and
+             (Gear^.Damage < 35))
+             )  and 
+        (Targets.Count < 256) then
+        begin
+        with Targets.ar[Targets.Count] do
             begin
-            for i:= 0 to cMaxHHIndex do
-                if (Hedgehogs[i].Gear <> nil)
-                and (Hedgehogs[i].Gear <> ThinkingHH)
-                and (Hedgehogs[i].Gear^.Health > Hedgehogs[i].Gear^.Damage) 
-                    then
+            skip:= false;
+            dead:= false;
+            Kind:= Gear^.Kind;
+            Radius:= Gear^.Radius;
+            Density:= hwFloat2Float(Gear^.Density)/3;
+            State:= Gear^.State;
+            matters:= (Gear^.AIHints and aihDoesntMatter) = 0;
+
+            Point.X:= hwRound(Gear^.X);
+            Point.Y:= hwRound(Gear^.Y);
+            if (Gear^.Kind = gtHedgehog) then
+                begin
+                if (Gear^.Hedgehog^.Team^.Clan = CurrentTeam^.Clan) then
                     begin
-                    with Targets.ar[Targets.Count], Hedgehogs[i] do
-                        begin
-                        skip:= false;
-                        matters:= (Hedgehogs[i].Gear^.AIHints and aihDoesntMatter) = 0;
-                        
-                        Point.X:= hwRound(Gear^.X);
-                        Point.Y:= hwRound(Gear^.Y);
-                        if Clan <> CurrentTeam^.Clan then
-                            begin
-                            Score:= Gear^.Health - Gear^.Damage;
-                            inc(e)
-                            end else
-                            begin
-                            Score:= Gear^.Damage - Gear^.Health;
-                            inc(f)
-                            end
-                        end;
-                    inc(Targets.Count)
+                    Score:= Gear^.Damage - Gear^.Health;
+                    inc(f)
+                    end
+                else 
+                    begin
+                    Score:= Gear^.Health - Gear^.Damage;
+                    inc(e)
                     end;
+                end
+            else if Gear^.Kind = gtExplosives then
+                Score:= Gear^.Health - Gear^.Damage
+            else if Gear^.Kind = gtMine then 
+                Score:= max(0,35-Gear^.Damage);
             end;
+        inc(Targets.Count)
+        end;
+    Gear:= Gear^.NextGear
+    end;
 
 if e > f then friendlyfactor:= 300 + (e - f) * 30
 else friendlyfactor:= max(30, 300 - f * 80 div max(1,e))
@@ -185,24 +219,24 @@
             gtFlame:
                 if (Gear^.State and gsttmpFlag) <> 0 then
                     AddBonus(hwRound(Gear^.X), hwRound(Gear^.Y), 20, -50);
-// avoid mines unless they are very likely to be duds, or are duds. also avoid if they are about to blow 
+// avoid mines unless they are very likely to be duds, or are duds. also avoid if they are about to blow
             gtMine:
                 if ((Gear^.State and gstAttacking) = 0) and (((cMineDudPercent < 90) and (Gear^.Health <> 0))
                 or (isAfterAttack and (Gear^.Health = 0) and (Gear^.Damage > 30))) then
                     AddBonus(hwRound(Gear^.X), hwRound(Gear^.Y), 50, -50)
                 else if (Gear^.State and gstAttacking) <> 0 then
                     AddBonus(hwRound(Gear^.X), hwRound(Gear^.Y), 100, -50); // mine is on
-                    
+
             gtExplosives:
             if isAfterAttack then
                 AddBonus(hwRound(Gear^.X), hwRound(Gear^.Y), 75, -60 + Gear^.Health);
-                
+
             gtSMine:
                 AddBonus(hwRound(Gear^.X), hwRound(Gear^.Y), 50, -30);
-                
+
             gtDynamite:
                 AddBonus(hwRound(Gear^.X), hwRound(Gear^.Y), 150, -75);
-                
+
             gtHedgehog:
                 begin
                 if Gear^.Damage >= Gear^.Health then
@@ -260,6 +294,58 @@
     RatePlace:= rate;
 end;
 
+function CheckBounds(x, y, r: Longint): boolean; inline;
+begin
+    CheckBounds := (((x-r) and LAND_WIDTH_MASK) = 0) and
+        (((x+r) and LAND_WIDTH_MASK) = 0) and
+        (((y-r) and LAND_HEIGHT_MASK) = 0) and
+        (((y+r) and LAND_HEIGHT_MASK) = 0);
+end;
+
+
+function TestCollWithEverything(x, y, r: LongInt): boolean; inline;
+begin
+    if not CheckBounds(x, y, r) then
+        exit(false);
+
+    if (Land[y-r, x-r] <> 0) or
+       (Land[y+r, x-r] <> 0) or
+       (Land[y-r, x+r] <> 0) or
+       (Land[y+r, x+r] <> 0) then
+       exit(true);
+
+    TestCollWithEverything := false;
+end;
+
+function TestCollExcludingObjects(x, y, r: LongInt): boolean; inline;
+begin
+    if not CheckBounds(x, y, r) then
+        exit(false);
+
+    if (Land[y-r, x-r] > lfAllObjMask) or
+       (Land[y+r, x-r] > lfAllObjMask) or
+       (Land[y-r, x-r] > lfAllObjMask) or
+       (Land[y+r, x+r] > lfAllObjMask) then
+       exit(true);
+
+    TestCollExcludingObjects:= false;
+end;
+
+function TestColl(x, y, r: LongInt): boolean; inline;
+begin
+    if not CheckBounds(x, y, r) then
+        exit(false);
+
+    if (Land[y-r, x-r] and lfNotCurrentMask <> 0) or
+       (Land[y+r, x-r] and lfNotCurrentMask <> 0) or
+       (Land[y+r, x-r] and lfNotCurrentMask <> 0) or
+       (Land[y+r, x+r] and lfNotCurrentMask <> 0) then
+       exit(true);
+
+    TestColl:= false;
+end;
+
+
 // Wrapper to test various approaches.  If it works reasonably, will just replace.
 // Right now, converting to hwFloat is a tad inefficient since the x/y were hwFloat to begin with...
 function TestCollExcludingMe(Me: PGear; x, y, r: LongInt): boolean; inline;
@@ -270,155 +356,134 @@
         MeX:= hwRound(Me^.X);
         MeY:= hwRound(Me^.Y);
         // We are still inside the hog. Skip radius test
-        if ((((x-MeX)*(x-MeX)) + ((y-MeY)*(y-MeY))) < 256) and (Land[y, x] <= lfAllObjMask) and ((Land[y, x] and lfObjMask) < 2) then
+        if ((sqr(x-MeX) + sqr(y-MeY)) < 256) and (Land[y, x] and lfObjMask = 0) then
             exit(false);
     end;
-    TestCollExcludingMe:= TestColl(x, y, r)
-end;
-
-function TestCollExcludingObjects(x, y, r: LongInt): boolean; inline;
-var b: boolean;
-begin
-    b:= (((x-r) and LAND_WIDTH_MASK) = 0) and (((y-r) and LAND_HEIGHT_MASK) = 0) and (Land[y-r, x-r] > lfAllObjMask);
-    if b then
-        exit(true);
-    
-    b:= (((x-r) and LAND_WIDTH_MASK) = 0) and (((y+r) and LAND_HEIGHT_MASK) = 0) and (Land[y+r, x-r] > lfAllObjMask);
-    if b then
-        exit(true);
-    
-    b:= (((x+r) and LAND_WIDTH_MASK) = 0) and (((y-r) and LAND_HEIGHT_MASK) = 0) and (Land[y-r, x+r] > lfAllObjMask);
-    if b then
-        exit(true);
-    
-    b:= (((x+r) and LAND_WIDTH_MASK) = 0) and (((y+r) and LAND_HEIGHT_MASK) = 0) and (Land[y+r, x+r] > lfAllObjMask);
-    if b then
-        exit(true);
-    
-    TestCollExcludingObjects:= false;
+    TestCollExcludingMe:= TestCollWithEverything(x, y, r)
 end;
 
-function TestColl(x, y, r: LongInt): boolean; inline;
-var b: boolean;
-begin
-    b:= (((x-r) and LAND_WIDTH_MASK) = 0) and (((y-r) and LAND_HEIGHT_MASK) = 0) and (Land[y-r, x-r] and lfNotCurrentMask <> 0);
-    if b then
-        exit(true);
-    
-    b:= (((x-r) and LAND_WIDTH_MASK) = 0) and (((y+r) and LAND_HEIGHT_MASK) = 0) and (Land[y+r, x-r] and lfNotCurrentMask <> 0);
-    if b then
-        exit(true);
-    
-    b:= (((x+r) and LAND_WIDTH_MASK) = 0) and (((y-r) and LAND_HEIGHT_MASK) = 0) and (Land[y-r, x+r] and lfNotCurrentMask <> 0);
-    if b then
-        exit(true);
-    
-    b:= (((x+r) and LAND_WIDTH_MASK) = 0) and (((y+r) and LAND_HEIGHT_MASK) = 0) and (Land[y+r, x+r] and lfNotCurrentMask <> 0);
-    if b then
-        exit(true);
-    
-    TestColl:= false;
-end;
+
 
-function TestCollWithLand(x, y, r: LongInt): boolean; inline;
-var b: boolean;
-begin
-    b:= (((x-r) and LAND_WIDTH_MASK) = 0) and (((y-r) and LAND_HEIGHT_MASK) = 0) and (Land[y-r, x-r] > lfAllObjMask);
-    if b then
-        exit(true);
-        
-    b:= (((x-r) and LAND_WIDTH_MASK) = 0) and (((y+r) and LAND_HEIGHT_MASK) = 0) and (Land[y+r, x-r] > lfAllObjMask);
-    if b then
-        exit(true);
-        
-    b:= (((x+r) and LAND_WIDTH_MASK) = 0) and (((y-r) and LAND_HEIGHT_MASK) = 0) and (Land[y-r, x+r] > lfAllObjMask);
-    if b then
-        exit(true);
-        
-    b:= (((x+r) and LAND_WIDTH_MASK) = 0) and (((y+r) and LAND_HEIGHT_MASK) = 0) and (Land[y+r, x+r] > lfAllObjMask);
-    if b then
-        exit(true);
-
-    TestCollWithLand:= false;
-end;
-
-function TraceFall(eX, eY: LongInt; x, y, dX, dY: Real; r: LongWord): LongInt;
+function TraceFall(eX, eY: LongInt; var x, y: Real; dX, dY: Real; r: LongWord; Target: TTarget): LongInt;
 var skipLandCheck: boolean;
-    rCorner: real;
+    rCorner, dxdy, odX, odY: real;
     dmg: LongInt;
 begin
+    odX:= dX;
+    odY:= dY;
     skipLandCheck:= true;
-    if x - eX < 0 then dX:= -dX;
-    if y - eY < 0 then dY:= -dY;
     // ok. attempt approximate search for an unbroken trajectory into water.  if it continues far enough, assume out of map
     rCorner:= r * 0.75;
     while true do
-    begin
+        begin
         x:= x + dX;
         y:= y + dY;
         dY:= dY + cGravityf;
         skipLandCheck:= skipLandCheck and (r <> 0) and (abs(eX-x) + abs(eY-y) < r) and ((abs(eX-x) < rCorner) or (abs(eY-y) < rCorner));
-        if (not skipLandCheck) and TestCollWithLand(trunc(x), trunc(y), cHHRadius) then
-        begin
-            if 0.4 < dY then
-            begin
-                dmg := 1 + trunc((abs(dY) - 0.4) * 70);
-                if dmg >= 1 then
-                    exit(dmg);
+        if not skipLandCheck and TestCollExcludingObjects(trunc(x), trunc(y), Target.Radius) then
+            with Target do
+                begin
+                if (Kind = gtHedgehog) and (0.4 < dY) then
+                    begin
+                    dmg := 1 + trunc((dY - 0.4) * 70);
+                    exit(dmg)
+                    end
+                else 
+                    begin
+                    dxdy:= abs(dX)+abs(dY);
+                    if ((Kind = gtMine) and (dxdy > 0.35)) or 
+                       ((Kind = gtExplosives) and 
+                            (((State and gstTmpFlag <> 0) and (dxdy > 0.35)) or
+                             ((State and gstTmpFlag = 0) and 
+                                ((abs(odX) > 0.15) or ((abs(odY) > 0.15) and 
+                                (abs(odX) > 0.02))) and (dxdy > 0.35)))) then
+                        begin
+                        dmg := trunc(dxdy * 25);
+                        exit(dmg)
+                        end
+                    else if (Kind = gtExplosives) and not((abs(odX) > 0.15) or ((abs(odY) > 0.15) and (abs(odX) > 0.02))) and (dY > 0.2) then
+                        begin
+                        dmg := trunc(dy * 70);
+                        exit(dmg)
+                        end
+                    end;
+            exit(0)
             end;
-            exit(0)
-        end;
-        if (y > cWaterLine) or (x > 4096) or (x < 0) then
-            exit(-1);
-    end;
+        if (y > cWaterLine) or (x > rightX) or (x < leftX) then exit(-1)
+        end
 end;
 
-function TraceShoveFall(x, y, dX, dY: Real): LongInt;
+function TraceShoveFall(var x, y: Real; dX, dY: Real; Target: TTarget): LongInt;
 var dmg: LongInt;
+    dxdy, odX, odY: real;
 begin
+    odX:= dX;
+    odY:= dY;
 //v:= random($FFFFFFFF);
     while true do
-    begin
+        begin
         x:= x + dX;
         y:= y + dY;
         dY:= dY + cGravityf;
 
-{        if ((trunc(y) and LAND_HEIGHT_MASK) = 0) and ((trunc(x) and LAND_WIDTH_MASK) = 0) then 
+{        if ((trunc(y) and LAND_HEIGHT_MASK) = 0) and ((trunc(x) and LAND_WIDTH_MASK) = 0) then
             begin
             LandPixels[trunc(y), trunc(x)]:= v;
             UpdateLandTexture(trunc(X), 1, trunc(Y), 1, true);
             end;}
 
-
-        // consider adding dX/dY calc here for fall damage
-        if TestCollExcludingObjects(trunc(x), trunc(y), cHHRadius) then
-        begin
-            if 0.4 < dY then
-            begin
-                dmg := 1 + trunc((abs(dY) - 0.4) * 70);
-                if dmg >= 1 then
+        if TestCollExcludingObjects(trunc(x), trunc(y), Target.Radius) then
+            with Target do
+                begin
+                if (Kind = gtHedgehog) and (0.4 < dY) then
+                    begin
+                    dmg := trunc((dY - 0.4) * 70);
                     exit(dmg);
-            end;
+                    end
+                else 
+                    begin
+                    dxdy:= abs(dX)+abs(dY);
+                    if ((Kind = gtMine) and (dxdy > 0.4)) or 
+                       ((Kind = gtExplosives) and 
+                            (((State and gstTmpFlag <> 0) and (dxdy > 0.4)) or
+                             ((State and gstTmpFlag = 0) and 
+                                ((abs(odX) > 0.15) or ((abs(odY) > 0.15) and 
+                                (abs(odX) > 0.02))) and (dxdy > 0.35)))) then
+                        begin
+                        dmg := trunc(dxdy * 50);
+                        exit(dmg)
+                        end
+                    else if (Kind = gtExplosives) and not((abs(odX) > 0.15) or ((abs(odY) > 0.15) and (abs(odX) > 0.02))) and (dY > 0.2) then
+                        begin
+                        dmg := trunc(dy * 70);
+                        exit(dmg)
+                        end
+                    end;
             exit(0)
         end;
-        if (y > cWaterLine) or (x > 4096) or (x < 0) then
+        if (y > cWaterLine) or (x > rightX) or (x < leftX) then
             // returning -1 for drowning so it can be considered in the Rate routine
             exit(-1)
     end;
 end;
 
-function RateExplosion(Me: PGear; x, y, r: LongInt): LongInt;
+function RateExplosion(Me: PGear; x, y, r: LongInt): LongInt; inline;
 begin
-    RateExplosion:= RateExplosion(Me, x, y, r, 0);
+    RateExplosion:= RealRateExplosion(Me, x, y, r, 0);
+    ResetTargets;
+end;
+function RateExplosion(Me: PGear; x, y, r: LongInt; Flags: LongWord): LongInt; inline;
+begin
+    RateExplosion:= RealRateExplosion(Me, x, y, r, Flags);
+    ResetTargets;
 end;
 
-function RateExplosion(Me: PGear; x, y, r: LongInt; Flags: LongWord): LongInt;
-var i, fallDmg, dmg, dmgBase, rate, erasure: LongInt;
-    dX, dY, dmgMod: real;
+function RealRateExplosion(Me: PGear; x, y, r: LongInt; Flags: LongWord): LongInt;
+var i, fallDmg, dmg, dmgBase, rate, subrate, erasure: LongInt;
+    pX, pY, dX, dY: real;
     hadSkips: boolean;
 begin
 fallDmg:= 0;
-dmgMod:= 0.01 * hwFloat2Float(cDamageModifier) * cDamagePercent;
 rate:= 0;
 // add our virtual position
 with Targets.ar[Targets.Count] do
@@ -427,10 +492,12 @@
     Point.y:= hwRound(Me^.Y);
     skip:= false;
     matters:= true;
+    Kind:= gtHedgehog;
+    Density:= 1;
+    Radius:= cHHRadius;
     Score:= - ThinkingHH^.Health
     end;
 // rate explosion
-dmgBase:= r + cHHRadius div 2;
 
 if (Flags and afErasesLand <> 0) and (GameFlags and gfSolidLand = 0) then erasure:= r
 else erasure:= 0;
@@ -438,98 +505,169 @@
 hadSkips:= false;
 
 for i:= 0 to Targets.Count do
-    with Targets.ar[i] do
-      if not matters then hadSkips:= true
-        else
-        begin
-        dmg:= 0;
-        if abs(Point.x - x) + abs(Point.y - y) < dmgBase then
-            dmg:= trunc(dmgMod * min((dmgBase - trunc(sqrt(sqr(Point.x - x)+sqr(Point.y - y)))) div 2, r));
+    if not Targets.ar[i].dead then
+        with Targets.ar[i] do
+          if not matters then hadSkips:= true
+            else
+            begin
+            dmg:= 0;
+            dmgBase:= r + Radius div 2;
+            if abs(Point.x - x) + abs(Point.y - y) < dmgBase then
+                dmg:= trunc(dmgMod * min((dmgBase - trunc(sqrt(sqr(Point.x - x)+sqr(Point.y - y)))) div 2, r));
 
-        if dmg > 0 then
-            begin
-            if (Flags and afTrackFall <> 0) and (dmg < abs(Score)) then
+            if dmg > 0 then
                 begin
-                dX:= 0.005 * dmg + 0.01;
-                dY:= dX;
-                if (x and LAND_WIDTH_MASK = 0) and ((y+cHHRadius+2) and LAND_HEIGHT_MASK = 0) and 
-                   (Land[y+cHHRadius+2, x] and lfIndestructible <> 0) then
-                     fallDmg:= trunc(TraceFall(x, y, Point.x, Point.y, dX, dY, 0) * dmgMod)
-                else fallDmg:= trunc(TraceFall(x, y, Point.x, Point.y, dX, dY, erasure) * dmgMod)
-                end;
-            if fallDmg < 0 then // drowning. score healthier hogs higher, since their death is more likely to benefit the AI
-                if Score > 0 then
-                    inc(rate, (KillScore + Score div 10) * 1024)   // Add a bit of a bonus for bigger hog drownings
-                else
-                    dec(rate, (KillScore * friendlyfactor div 100 - Score div 10) * 1024) // and more of a punishment for drowning bigger friendly hogs
-            else if (dmg+fallDmg) >= abs(Score) then
-                if Score > 0 then
-                    inc(rate, KillScore * 1024 + (dmg + fallDmg)) // tiny bonus for dealing more damage than needed to kill
-                else
-                    dec(rate, KillScore * friendlyfactor div 100 * 1024)
-            else
-                if Score > 0 then
-                    inc(rate, (dmg + fallDmg) * 1024)
-                else dec(rate, (dmg + fallDmg) * friendlyfactor div 100 * 1024)
+                pX:= Point.x;
+                pY:= Point.y;
+                fallDmg:= 0;
+                if (Flags and afTrackFall <> 0) and (Score > 0) and (dmg < Score) then
+                    begin
+                    dX:= (0.005 * dmg + 0.01) / Density;
+                    dY:= dX;
+                    if (Kind = gtExplosives) and (State and gstTmpFlag = 0) and 
+                       (((abs(dY) > 0.15) and (abs(dX) < 0.02)) or
+                        ((abs(dY) < 0.15) and (abs(dX) < 0.15))) then
+                        dX:= 0;
+
+                    if pX - x < 0 then dX:= -dX;
+                    if pY - y < 0 then dY:= -dY;
+
+                    if (x and LAND_WIDTH_MASK = 0) and ((y+cHHRadius+2) and LAND_HEIGHT_MASK = 0) and
+                       (Land[y+cHHRadius+2, x] and lfIndestructible <> 0) then
+                         fallDmg:= trunc(TraceFall(x, y, pX, pY, dX, dY, 0, Targets.ar[i]) * dmgMod)
+                    else fallDmg:= trunc(TraceFall(x, y, pX, pY, dX, dY, erasure, Targets.ar[i]) * dmgMod)
+                    end;
+                if Kind = gtHedgehog then
+                    begin
+                    if fallDmg < 0 then // drowning. score healthier hogs higher, since their death is more likely to benefit the AI
+                        begin
+                        if Score > 0 then
+                            inc(rate, (KillScore + Score div 10) * 1024)   // Add a bit of a bonus for bigger hog drownings
+                        else
+                            dec(rate, (KillScore * friendlyfactor div 100 - Score div 10) * 1024) // and more of a punishment for drowning bigger friendly hogs
+                        end
+                    else if (dmg+fallDmg) >= abs(Score) then
+                        begin
+                        dead:= true;
+                        Targets.reset:= true;
+                        if dX < 0.035 then
+                            begin
+                            subrate:= RealRateExplosion(Me, round(pX), round(pY), 61, afErasesLand or (Flags and afTrackFall));
+                            if abs(subrate) > 2000 then inc(Rate,subrate)
+                            end;
+                        if Score > 0 then
+                             inc(rate, KillScore * 1024 + (dmg + fallDmg)) // tiny bonus for dealing more damage than needed to kill
+                        else dec(rate, KillScore * friendlyfactor div 100 * 1024)
+                        end
+                    else
+                        begin
+                        if Score > 0 then
+                             inc(rate, (dmg + fallDmg) * 1024)
+                        else dec(rate, (dmg + fallDmg) * friendlyfactor div 100 * 1024)
+                        end
+                    end
+                else if (fallDmg >= 0) and ((dmg+fallDmg) >= Score) then
+                    begin
+                    dead:= true;
+                    Targets.reset:= true;
+                    if Kind = gtExplosives then
+                         subrate:= RealRateExplosion(Me, round(pX), round(pY), 151, afErasesLand or (Flags and afTrackFall))
+                    else subrate:= RealRateExplosion(Me, round(pX), round(pY), 101, afErasesLand or (Flags and afTrackFall));
+                    if abs(subrate) > 2000 then inc(Rate,subrate);
+                    end
+                end
             end;
-        end;
 
 if hadSkips and (rate = 0) then
-    RateExplosion:= BadTurn
+    RealRateExplosion:= BadTurn
     else
-    RateExplosion:= rate;
+    RealRateExplosion:= rate;
 end;
 
-function RateShove(x, y, r, power, kick: LongInt; gdX, gdY: real; Flags: LongWord): LongInt;
-var i, fallDmg, dmg, rate: LongInt;
-    dX, dY, dmgMod: real;
+function RateShove(Me: PGear; x, y, r, power, kick: LongInt; gdX, gdY: real; Flags: LongWord): LongInt;
+var i, fallDmg, dmg, rate, subrate: LongInt;
+    dX, dY, pX, pY: real;
 begin
 fallDmg:= 0;
 dX:= gdX * 0.01 * kick;
 dY:= gdY * 0.01 * kick;
-dmgMod:= 0.01 * hwFloat2Float(cDamageModifier) * cDamagePercent;
 rate:= 0;
 for i:= 0 to Pred(Targets.Count) do
     with Targets.ar[i] do
-      if skip then 
-        if (Flags and afSetSkip = 0) then skip:= false else {still skip}
-      else if matters then
-        begin
-        dmg:= 0;
-        if abs(Point.x - x) + abs(Point.y - y) < r then
-            dmg:= r - trunc(sqrt(sqr(Point.x - x)+sqr(Point.y - y)));
-
-        if dmg > 0 then
+        if skip then
+            begin
+            if Flags and afSetSkip = 0 then skip:= false
+            end
+        else if matters then
             begin
-            if (Flags and afSetSkip <> 0) then skip:= true;
-            if (Flags and afTrackFall <> 0) and (Score > 0) then 
-                fallDmg:= trunc(TraceShoveFall(Point.x, Point.y - 2, dX, dY) * dmgMod);
-            if fallDmg < 0 then // drowning. score healthier hogs higher, since their death is more likely to benefit the AI
-                if Score > 0 then
-                    inc(rate, KillScore + Score div 10)   // Add a bit of a bonus for bigger hog drownings
-                else
-                    dec(rate, KillScore * friendlyfactor div 100 - Score div 10) // and more of a punishment for drowning bigger friendly hogs
-            else if power+fallDmg >= abs(Score) then
-                if Score > 0 then
-                    inc(rate, KillScore)
-                else
-                    dec(rate, KillScore * friendlyfactor div 100)
-            else
-                if Score > 0 then
-                    inc(rate, power+fallDmg)
-                else
-                    dec(rate, (power+fallDmg) * friendlyfactor div 100)
+            dmg:= 0;
+            if abs(Point.x - x) + abs(Point.y - y) < r then
+                dmg:= r - trunc(sqrt(sqr(Point.x - x)+sqr(Point.y - y)));
+
+            if dmg > 0 then
+                begin
+                pX:= Point.x;
+                pY:= Point.y-2;
+                fallDmg:= 0;
+                if (Flags and afSetSkip <> 0) then skip:= true;
+                if not(dead) and (Flags and afTrackFall <> 0) and (Score > 0) and (power < Score) then
+                    if (Kind = gtExplosives) and (State and gstTmpFlag = 0) and 
+                       (((abs(dY) > 0.15) and (abs(dX) < 0.02)) or
+                        ((abs(dY) < 0.15) and (abs(dX) < 0.15))) then
+                        fallDmg:= trunc(TraceShoveFall(pX, pY, 0, dY, Targets.ar[i]) * dmgMod)
+                    else
+                        fallDmg:= trunc(TraceShoveFall(pX, pY, dX, dY, Targets.ar[i]) * dmgMod);
+                if Kind = gtHedgehog then
+                    begin
+                    if fallDmg < 0 then // drowning. score healthier hogs higher, since their death is more likely to benefit the AI
+                        begin
+                        if Score > 0 then
+                            inc(rate, KillScore + Score div 10)   // Add a bit of a bonus for bigger hog drownings
+                        else
+                            dec(rate, KillScore * friendlyfactor div 100 - Score div 10) // and more of a punishment for drowning bigger friendly hogs
+                        end
+                    else if power+fallDmg >= abs(Score) then
+                        begin
+                        dead:= true;
+                        Targets.reset:= true;
+                        if dX < 0.035 then
+                            begin
+                            subrate:= RealRateExplosion(Me, round(pX), round(pY), 61, afErasesLand or afTrackFall);
+                            if abs(subrate) > 2000 then inc(Rate,subrate div 1024)
+                            end;
+                        if Score > 0 then
+                            inc(rate, KillScore)
+                        else
+                            dec(rate, KillScore * friendlyfactor div 100)
+                        end
+                    else
+                        begin
+                        if Score > 0 then
+                            inc(rate, power+fallDmg)
+                        else
+                            dec(rate, (power+fallDmg) * friendlyfactor div 100)
+                        end
+                    end
+                else if (fallDmg >= 0) and ((dmg+fallDmg) >= Score) then
+                    begin
+                    dead:= true;
+                    Targets.reset:= true;
+                    if Kind = gtExplosives then
+                         subrate:= RealRateExplosion(Me, round(pX), round(pY), 151, afErasesLand or (Flags and afTrackFall))
+                    else subrate:= RealRateExplosion(Me, round(pX), round(pY), 101, afErasesLand or (Flags and afTrackFall));
+                    if abs(subrate) > 2000 then inc(Rate,subrate div 1024);
+                    end
+                end
             end;
-        end;
-RateShove:= rate * 1024
+RateShove:= rate * 1024;
+ResetTargets
 end;
 
 function RateShotgun(Me: PGear; gdX, gdY: real; x, y: LongInt): LongInt;
-var i, dmg, fallDmg, baseDmg, rate, erasure: LongInt;
-    dX, dY, dmgMod: real;
+var i, dmg, fallDmg, baseDmg, rate, subrate, erasure: LongInt;
+    pX, pY, dX, dY: real;
     hadSkips: boolean;
 begin
-dmgMod:= 0.01 * hwFloat2Float(cDamageModifier) * cDamagePercent;
 rate:= 0;
 gdX:= gdX * 0.01;
 gdY:= gdX * 0.01;
@@ -540,6 +678,9 @@
     Point.y:= hwRound(Me^.Y);
     skip:= false;
     matters:= true;
+    Kind:= gtHedgehog;
+    Density:= 1;
+    Radius:= cHHRadius;
     Score:= - ThinkingHH^.Health
     end;
 // rate shot
@@ -551,48 +692,80 @@
 hadSkips:= false;
 
 for i:= 0 to Targets.Count do
-    with Targets.ar[i] do
-      if not matters then hadSkips:= true
-        else
-        begin
-        dmg:= 0;
-        if abs(Point.x - x) + abs(Point.y - y) < baseDmg then
-            begin
-            dmg:= min(baseDmg - trunc(sqrt(sqr(Point.x - x)+sqr(Point.y - y))), 25);
-            dmg:= trunc(dmg * dmgMod);
-            end;
-        if dmg > 0 then
+    if not Targets.ar[i].dead then
+        with Targets.ar[i] do
+          if not matters then hadSkips:= true
+            else
             begin
-            dX:= gdX * dmg;
-            dY:= gdY * dmg;
-            if dX < 0 then dX:= dX - 0.01
-            else dX:= dX + 0.01;
-            if (x and LAND_WIDTH_MASK = 0) and ((y+cHHRadius+2) and LAND_HEIGHT_MASK = 0) and 
-               (Land[y+cHHRadius+2, x] and lfIndestructible <> 0) then
-                 fallDmg:= trunc(TraceFall(x, y, Point.x, Point.y, dX, dY, 0) * dmgMod)
-            else fallDmg:= trunc(TraceFall(x, y, Point.x, Point.y, dX, dY, erasure) * dmgMod);
-            if fallDmg < 0 then // drowning. score healthier hogs higher, since their death is more likely to benefit the AI
-                if Score > 0 then
-                    inc(rate, KillScore + Score div 10)   // Add a bit of a bonus for bigger hog drownings
-                else
-                    dec(rate, KillScore * friendlyfactor div 100 - Score div 10) // and more of a punishment for drowning bigger friendly hogs
-            else if (dmg+fallDmg) >= abs(Score) then
-                if Score > 0 then
-                    inc(rate, KillScore)
-                else
-                    dec(rate, KillScore * friendlyfactor div 100)
-            else
-                if Score > 0 then
-                    inc(rate, dmg+fallDmg)
-            else
-                dec(rate, (dmg+fallDmg) * friendlyfactor div 100)
+            dmg:= 0;
+            if abs(Point.x - x) + abs(Point.y - y) < baseDmg then
+                begin
+                dmg:= min(baseDmg - trunc(sqrt(sqr(Point.x - x)+sqr(Point.y - y))), 25);
+                dmg:= trunc(dmg * dmgMod);
+                end;
+            if dmg > 0 then
+                begin
+                if not(dead) and (Score > 0) and (dmg < Score) then
+                    begin
+                    pX:= Point.x;
+                    pY:= Point.y;
+                    dX:= gdX * dmg / Density;
+                    dY:= gdY * dmg / Density;
+                    if dX < 0 then dX:= dX - 0.01
+                    else dX:= dX + 0.01;
+                    if (Kind = gtExplosives) and (State and gstTmpFlag = 0) and 
+                       (((abs(dY) > 0.15) and (abs(dX) < 0.02)) or
+                        ((abs(dY) < 0.15) and (abs(dX) < 0.15))) then 
+                       dX:= 0;
+                    if (x and LAND_WIDTH_MASK = 0) and ((y+cHHRadius+2) and LAND_HEIGHT_MASK = 0) and
+                       (Land[y+cHHRadius+2, x] and lfIndestructible <> 0) then
+                         fallDmg:= trunc(TraceFall(x, y, pX, pY, dX, dY, 0, Targets.ar[i]) * dmgMod)
+                    else fallDmg:= trunc(TraceFall(x, y, pX, pY, dX, dY, erasure, Targets.ar[i]) * dmgMod)
+                    end;
+                if Kind = gtHedgehog then
+                    begin
+                    if fallDmg < 0 then // drowning. score healthier hogs higher, since their death is more likely to benefit the AI
+                        begin
+                        if Score > 0 then
+                            inc(rate, KillScore + Score div 10)   // Add a bit of a bonus for bigger hog drownings
+                        else
+                            dec(rate, KillScore * friendlyfactor div 100 - Score div 10) // and more of a punishment for drowning bigger friendly hogs
+                        end
+                    else if (dmg+fallDmg) >= abs(Score) then
+                        begin
+                        dead:= true;
+                        Targets.reset:= true;
+                        if dX < 0.035 then
+                            begin
+                            subrate:= RealRateExplosion(Me, round(pX), round(pY), 61, afErasesLand or afTrackFall);
+                            if abs(subrate) > 2000 then inc(Rate,subrate div 1024)
+                            end;
+                        if Score > 0 then
+                            inc(rate, KillScore)
+                        else
+                            dec(rate, KillScore * friendlyfactor div 100)
+                        end
+                    else if Score > 0 then
+                         inc(rate, dmg+fallDmg)
+                    else dec(rate, (dmg+fallDmg) * friendlyfactor div 100)
+                    end
+                else if (fallDmg >= 0) and ((dmg+fallDmg) >= Score) then
+                    begin
+                    dead:= true;
+                    Targets.reset:= true;
+                    if Kind = gtExplosives then
+                         subrate:= RealRateExplosion(Me, round(pX), round(pY), 151, afErasesLand or afTrackFall)
+                    else subrate:= RealRateExplosion(Me, round(pX), round(pY), 101, afErasesLand or afTrackFall);
+                    if abs(subrate) > 2000 then inc(Rate,subrate div 1024);
+                    end
+                end
             end;
-        end;
 
 if hadSkips and (rate = 0) then
     RateShotgun:= BadTurn
     else
     RateShotgun:= rate * 1024;
+    ResetTargets;
 end;
 
 function RateHammer(Me: PGear): LongInt;
@@ -605,14 +778,13 @@
 
 for i:= 0 to Pred(Targets.Count) do
     with Targets.ar[i] do
-      if matters then
          // hammer hit radius is 8, shift is 10
-        if abs(Point.x - x) + abs(Point.y - y) < 18 then
+      if matters and (Kind = gtHedgehog) and (abs(Point.x - x) + abs(Point.y - y) < 18) then
             begin
             r:= trunc(sqrt(sqr(Point.x - x)+sqr(Point.y - y)));
 
             if r <= 18 then
-                if Score > 0 then 
+                if Score > 0 then
                     inc(rate, Score div 3)
                 else
                     inc(rate, Score div 3 * friendlyfactor div 100)
@@ -630,7 +802,7 @@
 bY:= hwRound(Gear^.Y);
 case JumpType of
     jmpNone: exit(false);
-    
+
     jmpHJump:
         if TestCollisionYwithGear(Gear, -1) = 0 then
         begin
@@ -640,7 +812,7 @@
         end
     else
         exit(false);
-        
+
     jmpLJump:
         begin
             if TestCollisionYwithGear(Gear, -1) <> 0 then
@@ -662,12 +834,12 @@
 end;
 
 repeat
-        {if ((hwRound(Gear^.Y) and LAND_HEIGHT_MASK) = 0) and ((hwRound(Gear^.X) and LAND_WIDTH_MASK) = 0) then 
+        {if ((hwRound(Gear^.Y) and LAND_HEIGHT_MASK) = 0) and ((hwRound(Gear^.X) and LAND_WIDTH_MASK) = 0) then
             begin
             LandPixels[hwRound(Gear^.Y), hwRound(Gear^.X)]:= Gear^.Hedgehog^.Team^.Clan^.Color;
             UpdateLandTexture(hwRound(Gear^.X), 1, hwRound(Gear^.Y), 1, true);
             end;}
-            
+
     if not (hwRound(Gear^.Y) + cHHRadius < cWaterLine) then
         exit(false);
     if (Gear^.State and gstMoving) <> 0 then
@@ -725,7 +897,7 @@
 GoInfo.JumpType:= jmpNone;
 tY:= hwRound(Gear^.Y);
 repeat
-        {if ((hwRound(Gear^.Y) and LAND_HEIGHT_MASK) = 0) and ((hwRound(Gear^.X) and LAND_WIDTH_MASK) = 0) then 
+        {if ((hwRound(Gear^.Y) and LAND_HEIGHT_MASK) = 0) and ((hwRound(Gear^.X) and LAND_WIDTH_MASK) = 0) then
             begin
             LandPixels[hwRound(Gear^.Y), hwRound(Gear^.X)]:= random($FFFFFFFF);//Gear^.Hedgehog^.Team^.Clan^.Color;
             UpdateLandTexture(hwRound(Gear^.X), 1, hwRound(Gear^.Y), 1, true);
@@ -739,8 +911,8 @@
             AddWalkBonus(pX, tY, 250, -40);
         exit(false)
         end;
-        
-    // hog is falling    
+
+    // hog is falling
     if (Gear^.State and gstMoving) <> 0 then
         begin
         inc(GoInfo.Ticks);
@@ -749,7 +921,7 @@
             begin
             GoInfo.FallPix:= 0;
             // try ljump instead of fall with damage
-            HHJump(AltGear, jmpLJump, GoInfo); 
+            HHJump(AltGear, jmpLJump, GoInfo);
             if AltGear^.Hedgehog^.BotLevel < 4 then
                 AddWalkBonus(pX, tY, 175, -20);
             exit(false)
--- a/hedgewars/uAmmos.pas	Thu Apr 04 14:37:19 2013 +0200
+++ b/hedgewars/uAmmos.pas	Tue Jun 04 22:28:12 2013 +0200
@@ -1,6 +1,6 @@
 (*
  * Hedgewars, a free turn based strategy game
- * Copyright (c) 2004-2012 Andrey Korotaev <unC0Rr@gmail.com>
+ * Copyright (c) 2004-2013 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
--- a/hedgewars/uCaptions.pas	Thu Apr 04 14:37:19 2013 +0200
+++ b/hedgewars/uCaptions.pas	Tue Jun 04 22:28:12 2013 +0200
@@ -1,6 +1,6 @@
 (*
  * Hedgewars, a free turn based strategy game
- * Copyright (c) 2004-2012 Andrey Korotaev <unC0Rr@gmail.com>
+ * Copyright (c) 2004-2013 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
--- a/hedgewars/uChat.pas	Thu Apr 04 14:37:19 2013 +0200
+++ b/hedgewars/uChat.pas	Tue Jun 04 22:28:12 2013 +0200
@@ -1,6 +1,6 @@
 (*
  * Hedgewars, a free turn based strategy game
- * Copyright (c) 2004-2012 Andrey Korotaev <unC0Rr@gmail.com>
+ * Copyright (c) 2004-2013 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
--- a/hedgewars/uCollisions.pas	Thu Apr 04 14:37:19 2013 +0200
+++ b/hedgewars/uCollisions.pas	Tue Jun 04 22:28:12 2013 +0200
@@ -1,6 +1,6 @@
 (*
  * Hedgewars, a free turn based strategy game
- * Copyright (c) 2004-2012 Andrey Korotaev <unC0Rr@gmail.com>
+ * Copyright (c) 2004-2013 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
@@ -83,7 +83,7 @@
     X:= hwRound(Gear^.X);
     Y:= hwRound(Gear^.Y);
     Radius:= Gear^.Radius;
-    ChangeRoundInLand(X, Y, Radius - 1, true, (Gear = CurrentHedgehog^.Gear) or (Gear^.Kind = gtCase));
+    ChangeRoundInLand(X, Y, Radius - 1, true, (Gear = CurrentHedgehog^.Gear) or ((Gear^.Kind = gtCase) and (Gear^.State and gstFrozen <> 0)));
     cGear:= Gear
     end;
 Gear^.CollisionIndex:= Count;
@@ -104,7 +104,7 @@
 if Gear^.CollisionIndex >= 0 then
     begin
     with cinfos[Gear^.CollisionIndex] do
-        ChangeRoundInLand(X, Y, Radius - 1, false, (Gear = CurrentHedgehog^.Gear) or (Gear^.Kind = gtCase));
+        ChangeRoundInLand(X, Y, Radius - 1, false, (Gear = CurrentHedgehog^.Gear) or ((Gear^.Kind = gtCase) and (Gear^.State and gstFrozen <> 0)));
     cinfos[Gear^.CollisionIndex]:= cinfos[Pred(Count)];
     cinfos[Gear^.CollisionIndex].cGear^.CollisionIndex:= Gear^.CollisionIndex;
     Gear^.CollisionIndex:= -1;
--- a/hedgewars/uCommandHandlers.pas	Thu Apr 04 14:37:19 2013 +0200
+++ b/hedgewars/uCommandHandlers.pas	Tue Jun 04 22:28:12 2013 +0200
@@ -1,6 +1,6 @@
 (*
  * Hedgewars, a free turn based strategy game
- * Copyright (c) 2004-2012 Andrey Korotaev <unC0Rr@gmail.com>
+ * Copyright (c) 2004-2013 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
@@ -574,7 +574,7 @@
 begin
 if isDeveloperMode then
     begin
-    SetRandomSeed(s);
+    SetRandomSeed(s, true);
     cSeed:= s;
     InitStepsFlags:= InitStepsFlags or cifRandomize
     end
--- a/hedgewars/uCommands.pas	Thu Apr 04 14:37:19 2013 +0200
+++ b/hedgewars/uCommands.pas	Tue Jun 04 22:28:12 2013 +0200
@@ -1,6 +1,6 @@
 (*
  * Hedgewars, a free turn based strategy game
- * Copyright (c) 2004-2012 Andrey Korotaev <unC0Rr@gmail.com>
+ * Copyright (c) 2004-2013 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
--- a/hedgewars/uConsole.pas	Thu Apr 04 14:37:19 2013 +0200
+++ b/hedgewars/uConsole.pas	Tue Jun 04 22:28:12 2013 +0200
@@ -1,6 +1,6 @@
 (*
  * Hedgewars, a free turn based strategy game
- * Copyright (c) 2004-2012 Andrey Korotaev <unC0Rr@gmail.com>
+ * Copyright (c) 2004-2013 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
--- a/hedgewars/uConsts.pas	Thu Apr 04 14:37:19 2013 +0200
+++ b/hedgewars/uConsts.pas	Tue Jun 04 22:28:12 2013 +0200
@@ -1,6 +1,6 @@
 (*
  * Hedgewars, a free turn based strategy game
- * Copyright (c) 2004-2012 Andrey Korotaev <unC0Rr@gmail.com>
+ * Copyright (c) 2004-2013 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
@@ -214,6 +214,8 @@
     gstLoser          = $00080000;
     gstHHGone         = $00100000;
     gstInvisible      = $00200000;
+    gstSubmersible    = $00400000;
+    gstFrozen         = $00800000;
 
     // gear messages
     gmLeft           = $00000001;
--- a/hedgewars/uDebug.pas	Thu Apr 04 14:37:19 2013 +0200
+++ b/hedgewars/uDebug.pas	Tue Jun 04 22:28:12 2013 +0200
@@ -1,6 +1,6 @@
 (*
  * Hedgewars, a free turn based strategy game
- * Copyright (c) 2004-2012 Andrey Korotaev <unC0Rr@gmail.com>
+ * Copyright (c) 2004-2013 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
--- a/hedgewars/uFloat.pas	Thu Apr 04 14:37:19 2013 +0200
+++ b/hedgewars/uFloat.pas	Tue Jun 04 22:28:12 2013 +0200
@@ -1,6 +1,6 @@
 (*
  * Hedgewars, a free turn based strategy game
- * Copyright (c) 2004-2012 Andrey Korotaev <unC0Rr@gmail.com>
+ * Copyright (c) 2004-2013 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
@@ -86,7 +86,8 @@
 function hwAbs(const t: hwFloat): hwFloat; inline; // Returns the value of t with positive sign.
 function hwSqr(const t: hwFloat): hwFloat; inline; // Returns the square value of parameter t.
 function hwPow(const t: hwFloat; p: LongWord): hwFloat; inline; // Returns the power of the value
-function hwSqrt(const t: hwFloat): hwFloat; inline; // Returns the the positive square root of parameter t.
+function hwSqrt1(const t: hwFloat): hwFloat; inline; // Returns the the positive square root of parameter t.
+function hwSqrt(const x: hwFloat): hwFloat; inline; // Returns the the positive square root of parameter t.
 function Distance(const dx, dy: hwFloat): hwFloat; // Returns the distance between two points in 2-dimensional space, of which the parameters are the horizontal and vertical distance.
 function DistanceI(const dx, dy: LongInt): hwFloat; // Same as above for integer parameters.
 function AngleSin(const Angle: Longword): hwFloat;
@@ -274,7 +275,7 @@
     end
 end;
 
-function isZero(const z: hwFloat): boolean; inline; 
+function isZero(const z: hwFloat): boolean; inline;
 begin
 isZero := z.QWordValue = 0;
 end;
@@ -287,7 +288,7 @@
     if z1.QWordValue = z2.QWordValue then
         b:= false
     else
-        b:= not((z1.QWordValue = z2.QWordValue) or ((z2.QWordValue < z1.QWordValue) <> z1.isNegative))
+        b:= (z2.QWordValue < z1.QWordValue) = z1.isNegative
 end;
 
 operator > (const z1, z2: hwFloat) b : boolean; inline;
@@ -418,24 +419,23 @@
 end;
 
 operator / (const z1: hwFloat; z2: hwFloat) z : hwFloat; inline;
-var t: hwFloat;
+var t: QWord;
 begin
 z.isNegative:= z1.isNegative xor z2.isNegative;
 z.Round:= z1.QWordValue div z2.QWordValue;
-t:= z1 - z2 * z.Round;
-if t.QWordValue = 0 then
-    z.Frac:= 0
-else
+t:= z1.QWordValue - z2.QWordValue * z.Round;
+z.Frac:= 0;
+
+if t <> 0 then
     begin
-    while ((t.QWordValue and $8000000000000000) = 0) and ((z2.QWordValue and $8000000000000000) = 0) do
+    while ((t and $FF00000000000000) = 0) and ((z2.QWordValue and $FF00000000000000) = 0) do
         begin
-        t.QWordValue:= t.QWordValue shl 1;
-        z2.QWordValue:= z2.QWordValue shl 1
+        t:= t shl 8;
+        z2.QWordValue:= z2.QWordValue shl 8
         end;
+
     if z2.Round > 0 then
-        z.Frac:= (t.QWordValue) div (z2.Round)
-    else
-        z.Frac:= 0
+        inc(z.QWordValue, t div z2.Round);
     end
 end;
 
@@ -491,14 +491,14 @@
     end
 end;
 
-function hwSqrt(const t: hwFloat): hwFloat;
+function hwSqrt1(const t: hwFloat): hwFloat;
 const pwr = 8; // even value, feel free to adjust
       rThreshold = 1 shl (pwr + 32);
       lThreshold = 1 shl (pwr div 2 + 32);
 var l, r: QWord;
     c: hwFloat;
 begin
-hwSqrt.isNegative:= false;
+hwSqrt1.isNegative:= false;
 
 if t.Round = 0 then
     begin
@@ -531,12 +531,47 @@
         l:= c.QWordValue
 until r - l <= 1;
 
-hwSqrt.QWordValue:= l
+hwSqrt1.QWordValue:= l
 end;
 
-function Distance(const dx, dy: hwFloat): hwFloat;
+function hwSqrt(const x: hwFloat): hwFloat;
+var r, t, s, q: QWord;
+    i: integer;
 begin
-Distance:= hwSqrt(hwSqr(dx) + hwSqr(dy))
+hwSqrt.isNegative:= false;
+
+t:= $4000000000000000;
+r:= 0;
+q:= x.QWordValue;
+
+for i:= 0 to 31 do
+    begin
+    s:= r + t;
+    r:= r shr 1;
+    if s <= q then
+        begin
+        dec(q, s);
+        inc(r, t);
+        end;
+    t:= t shr 2;
+    end;
+
+hwSqrt.QWordValue:= r shl 16
+end;
+
+
+
+function Distance(const dx, dy: hwFloat): hwFloat;
+var r: QWord;
+begin
+r:= dx.QWordValue or dy.QWordValue;
+
+if r < $10000 then
+    begin
+    Distance.QWordValue:= r;
+    Distance.isNegative:= false
+    end else
+    Distance:= hwSqrt(hwSqr(dx) + hwSqr(dy))
 end;
 
 function DistanceI(const dx, dy: LongInt): hwFloat;
--- a/hedgewars/uGame.pas	Thu Apr 04 14:37:19 2013 +0200
+++ b/hedgewars/uGame.pas	Tue Jun 04 22:28:12 2013 +0200
@@ -1,6 +1,6 @@
 (*
  * Hedgewars, a free turn based strategy game
- * Copyright (c) 2004-2012 Andrey Korotaev <unC0Rr@gmail.com>
+ * Copyright (c) 2004-2013 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
--- a/hedgewars/uGears.pas	Thu Apr 04 14:37:19 2013 +0200
+++ b/hedgewars/uGears.pas	Tue Jun 04 22:28:12 2013 +0200
@@ -1,6 +1,6 @@
 (*
  * Hedgewars, a free turn based strategy game
- * Copyright (c) 2004-2012 Andrey Korotaev <unC0Rr@gmail.com>
+ * Copyright (c) 2004-2013 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
@@ -768,7 +768,8 @@
     begin
     dec(i);
     Gear:= t^.ar[i];
-    if (Ammo^.Kind = gtFlame) and (Gear^.Kind = gtHedgehog) and (Gear^.Hedgehog^.Effects[heFrozen] > 255) then
+    if ((Ammo^.Kind = gtFlame) or (Ammo^.Kind = gtBlowTorch)) and 
+       (Gear^.Kind = gtHedgehog) and (Gear^.Hedgehog^.Effects[heFrozen] > 255) then
         Gear^.Hedgehog^.Effects[heFrozen]:= max(255,Gear^.Hedgehog^.Effects[heFrozen]-10000);
     tmpDmg:= ModifyDamage(Damage, Gear);
     if (Gear^.State and gstNoDamage) = 0 then
--- a/hedgewars/uGearsHandlers.pas	Thu Apr 04 14:37:19 2013 +0200
+++ b/hedgewars/uGearsHandlers.pas	Tue Jun 04 22:28:12 2013 +0200
@@ -1,6 +1,6 @@
 (*
  * Hedgewars, a free turn based strategy game
- * Copyright (c) 2004-2012 Andrey Korotaev <unC0Rr@gmail.com>
+ * Copyright (c) 2004-2013 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
--- a/hedgewars/uGearsHandlersRope.pas	Thu Apr 04 14:37:19 2013 +0200
+++ b/hedgewars/uGearsHandlersRope.pas	Tue Jun 04 22:28:12 2013 +0200
@@ -1,6 +1,6 @@
 (*
  * Hedgewars, a free turn based strategy game
- * Copyright (c) 2004-2012 Andrey Korotaev <unC0Rr@gmail.com>
+ * Copyright (c) 2004-2013 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
--- a/hedgewars/uGearsHedgehog.pas	Thu Apr 04 14:37:19 2013 +0200
+++ b/hedgewars/uGearsHedgehog.pas	Tue Jun 04 22:28:12 2013 +0200
@@ -1,6 +1,6 @@
 (*
  * Hedgewars, a free turn based strategy game
- * Copyright (c) 2004-2012 Andrey Korotaev <unC0Rr@gmail.com>
+ * Copyright (c) 2004-2013 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
@@ -257,8 +257,16 @@
             and ((Gear^.Message and gmLJump) <> 0)
             and ((Ammoz[CurAmmoType].Ammo.Propz and ammoprop_AltUse) <> 0) then
                 begin
-                newDx:= dX;
-                newDy:= dY;
+                if (CurAmmoGear^.AmmoType = amJetpack) and (Gear^.Message and gmPrecise <> 0) then
+                    begin
+                    newDx:= xx*cMaxPower/cPowerDivisor;
+                    newDy:= yy*cMaxPower/cPowerDivisor
+                    end
+                else
+                    begin
+                    newDx:= dX;
+                    newDy:= dY
+                    end;
                 altUse:= true
                 end
             else
@@ -385,11 +393,15 @@
                        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;
-            if altUse and (newGear <> nil) then
+            if altUse and (newGear <> nil) and 
+               ((CurAmmoGear = nil) or (CurAmmoGear^.AmmoType <> amJetpack) or (Gear^.Message and gmPrecise = 0)) then
                begin
                newGear^.dX:= newDx / newGear^.Density;
                newGear^.dY:= newDY / newGear^.Density
                end;
+            if (CurAmmoGear <> nil) and (CurAmmoGear^.AmmoType = amJetpack) and
+               (Gear^.Message and gmPrecise <> 0) and (hwRound(Y) > cWaterLine) then
+                newGear^.State:= newGear^.State or gstSubmersible;
 
             case CurAmmoType of
                      amGrenade, amMolotov,
@@ -513,7 +525,9 @@
                 begin
                 if TagTurnTimeLeft = 0 then
                     TagTurnTimeLeft:= TurnTimeLeft;
-                TurnTimeLeft:=(Ammoz[a].TimeAfterTurn * cGetAwayTime) div 100;
+                if (CurAmmoGear <> nil) and (CurAmmoGear^.State and gstSubmersible <> 0) and (hwRound(CurAmmoGear^.Y) > cWaterLine) then
+                     TurnTimeLeft:=(Ammoz[a].TimeAfterTurn * cGetAwayTime) div 25
+                else TurnTimeLeft:=(Ammoz[a].TimeAfterTurn * cGetAwayTime) div 100;
                 end;
             if ((Ammoz[a].Ammo.Propz and ammoprop_NoRoundEnd) = 0) and (HHGear <> nil) then
                 HHGear^.State:= HHGear^.State or gstAttacked;
@@ -546,6 +560,7 @@
     end
 else if Gear^.Timer = 1 then
     begin
+    Gear^.Hedgehog^.Effects[heFrozen]:= 0;
     Gear^.State:= Gear^.State or gstNoDamage;
     doMakeExplosion(hwRound(Gear^.X), hwRound(Gear^.Y), 30, CurrentHedgehog, EXPLAutoSound);
     AddGear(hwRound(Gear^.X), hwRound(Gear^.Y), gtGrave, 0, _0, _0, 0)^.Hedgehog:= Gear^.Hedgehog;
@@ -797,7 +812,7 @@
         da:= 2
     else da:= 1;
 
-if (((HHGear^.Message and gmPrecise) = 0) or ((GameTicks mod 5) = 1)) then
+if ((HHGear^.Message and gmPrecise = 0) or ((CurAmmoGear <> nil) and (CurAmmoGear^.AmmoType = amJetpack))) or (GameTicks mod 5 = 1) then
     if ((HHGear^.Message and gmUp) <> 0) and (HHGear^.Angle >= CurMinAngle + da) then
         dec(HHGear^.Angle, da)
     else
@@ -960,8 +975,11 @@
     begin
     Gear^.State:= Gear^.State and (not gstWinner);
     Gear^.State:= Gear^.State and (not gstMoving);
-    while (TestCollisionYWithGear(Gear,1) = 0) and (not CheckGearDrowning(Gear)) do
-        Gear^.Y:= Gear^.Y+_1;
+    while (TestCollisionYWithGear(Gear,1) = 0) and (not CheckGearDrowning(Gear)) and (Gear <> nil) do
+        Gear^.Y:= Gear^.Y + _1;
+
+    // could become nil in CheckGearDrowning if ai's hog fails to respawn in ai survival
+    if Gear = nil then exit;
     SetLittle(Gear^.dX);
     Gear^.dY:= _0
     end
@@ -981,7 +999,10 @@
         Gear^.dY:= _0;
         Gear^.Y:= Gear^.Y + _1
         end;
+
     CheckGearDrowning(Gear);
+    // could become nil if ai's hog fails to respawn in ai survival
+    if Gear = nil then exit;
     // hide target cursor if current hog is drowning
     if (Gear^.State and gstDrowning) <> 0 then
         if (CurrentHedgehog^.Gear = Gear) then
@@ -1063,7 +1084,7 @@
             HHGear^.Message:= HHGear^.Message or gmAttack;
     // check for case with ammo
     t:= CheckGearNear(HHGear, gtCase, 36, 36);
-    if t <> nil then
+    if (t <> nil) and (t^.State and gstFrozen = 0) then
         PickUp(HHGear, t)
     end;
 
--- a/hedgewars/uGearsList.pas	Thu Apr 04 14:37:19 2013 +0200
+++ b/hedgewars/uGearsList.pas	Tue Jun 04 22:28:12 2013 +0200
@@ -1,6 +1,6 @@
 (*
  * Hedgewars, a free turn based strategy game
- * Copyright (c) 2004-2012 Andrey Korotaev <unC0Rr@gmail.com>
+ * Copyright (c) 2004-2013 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
@@ -471,7 +471,8 @@
                 end;
      gtJetpack: begin
                 gear^.Health:= 2000;
-                gear^.Damage:= 100
+                gear^.Damage:= 100;
+                gear^.State:= gstSubmersible
                 end;
      gtMolotov: begin
                 gear^.Radius:= 6;
--- a/hedgewars/uGearsRender.pas	Thu Apr 04 14:37:19 2013 +0200
+++ b/hedgewars/uGearsRender.pas	Tue Jun 04 22:28:12 2013 +0200
@@ -1,6 +1,6 @@
 (*
  * Hedgewars, a free turn based strategy game
- * Copyright (c) 2004-2012 Andrey Korotaev <unC0Rr@gmail.com>
+ * Copyright (c) 2004-2013 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
@@ -365,13 +365,7 @@
                     lx:= lx + ax;
                     ly:= ly + ay;
                     tx:= round(lx);
-                    ty:= round(ly);
-                    if (abs(tx-hx) > 1000) or (abs(hy-ty) > 1000) then
-                        begin
-                        DrawLine(hx, hy, tx, ty, 1.0, $FF, $00, $00, $C0);
-                        hx:= tx;
-                        hy:= ty
-                        end
+                    ty:= round(ly)
                     end;
                 // reached edge of land. assume infinite beam. Extend it way out past camera
                 if ((ty and LAND_HEIGHT_MASK) <> 0) or ((tx and LAND_WIDTH_MASK) <> 0) then
@@ -381,7 +375,6 @@
                     end;
 
                 //if (abs(lx-tx)>8) or (abs(ly-ty)>8) then
-                if (tx <> hx) or (ty <> hy) then
                     begin
                     DrawLine(hx, hy, tx, ty, 1.0, $FF, $00, $00, $C0);
                     end;
@@ -999,6 +992,8 @@
     aAngle: real;
     startX, endX, startY, endY: LongInt;
 begin
+    if Gear^.State and gstFrozen <> 0 then Tint($A0, $A0, $FF, $FF);
+    //if Gear^.State and gstFrozen <> 0 then Tint(IceColor or $FF);
     if Gear^.Target.X <> NoPointX then
         if Gear^.AmmoType = amBee then
             DrawSpriteRotatedF(sprTargetBee, Gear^.Target.X + WorldDx, Gear^.Target.Y + WorldDy, 0, 0, (RealTicks shr 3) mod 360)
@@ -1058,11 +1053,13 @@
       gtPickHammer: DrawSprite(sprPHammer, x - 16, y - 50 + LongInt(((GameTicks shr 5) and 1) * 2), 0);
             gtRope: DrawRope(Gear);
 
-            gtMine: if (((Gear^.State and gstAttacking) = 0)or((Gear^.Timer and $3FF) < 420)) and (Gear^.Health <> 0) then
+            gtMine: begin
+                    if (((Gear^.State and gstAttacking) = 0)or((Gear^.Timer and $3FF) < 420)) and (Gear^.Health <> 0) then
                            DrawSpriteRotated(sprMineOff, x, y, 0, Gear^.DirAngle)
-                       else if Gear^.Health <> 0 then
-                           DrawSpriteRotated(sprMineOn, x, y, 0, Gear^.DirAngle)
-                       else DrawSpriteRotated(sprMineDead, x, y, 0, Gear^.DirAngle);
+                    else if Gear^.Health <> 0 then
+                       DrawSpriteRotated(sprMineOn, x, y, 0, Gear^.DirAngle)
+                    else DrawSpriteRotated(sprMineDead, x, y, 0, Gear^.DirAngle);
+                    end;
 
            gtSMine: if (((Gear^.State and gstAttacking) = 0)or((Gear^.Timer and $3FF) < 420)) and (Gear^.Health <> 0) then
                            DrawSpriteRotated(sprSMineOff, x, y, 0, Gear^.DirAngle)
@@ -1076,26 +1073,38 @@
                         begin
                         if ((Gear^.Pos and posCaseAmmo) <> 0) then
                             begin
-                            i:= (GameTicks shr 6) mod 64;
-                            if i > 18 then
-                                i:= 0;
-                            DrawSprite(sprCase, x - 24, y - 24, i);
+                            if Gear^.State and gstFrozen <> 0 then
+                                DrawSprite(sprCase, x - 24, y - 28, 0)
+                            else
+                                begin
+                                i:= (GameTicks shr 6) mod 64;
+                                if i > 18 then i:= 0;
+                                DrawSprite(sprCase, x - 24, y - 24, i)
+                                end
                             end
                         else if ((Gear^.Pos and posCaseHealth) <> 0) then
                             begin
-                            i:= ((GameTicks shr 6) + 38) mod 64;
-                            if i > 13 then
-                                i:= 0;
-                            DrawSprite(sprFAid, x - 24, y - 24, i);
+                            if Gear^.State and gstFrozen <> 0 then
+                                DrawSprite(sprFAid, x - 24, y - 28, 0)
+                            else
+                                begin
+                                i:= ((GameTicks shr 6) + 38) mod 64;
+                                if i > 13 then i:= 0;
+                                DrawSprite(sprFAid, x - 24, y - 24, i)
+                                end
                             end
                         else if ((Gear^.Pos and posCaseUtility) <> 0) then
                             begin
-                            i:= (GameTicks shr 6) mod 70;
-                            if i > 23 then
-                                i:= 0;
-                            i:= i mod 12;
-                            DrawSprite(sprUtility, x - 24, y - 24, i);
-                            end;
+                            if Gear^.State and gstFrozen <> 0 then
+                                DrawSprite(sprUtility, x - 24, y - 28, 0)
+                            else
+                                begin
+                                i:= (GameTicks shr 6) mod 70;
+                                if i > 23 then i:= 0;
+                                i:= i mod 12;
+                                DrawSprite(sprUtility, x - 24, y - 24, i)
+                                end
+                            end
                         end;
                     if Gear^.Timer < 1833 then
                         begin
@@ -1116,7 +1125,7 @@
                     else if Gear^.State and gsttmpFlag = 0 then
                         DrawSpriteRotatedF(sprExplosivesRoll, x, y + 4, 0, 0, Gear^.DirAngle)
                     else
-                        DrawSpriteRotatedF(sprExplosivesRoll, x, y + 4, 1, 0, Gear^.DirAngle);
+                        DrawSpriteRotatedF(sprExplosivesRoll, x, y + 4, 1, 0, Gear^.DirAngle)
                     end;
         gtDynamite: DrawSprite(sprDynamite, x - 16, y - 25, Gear^.Tag and 1, Gear^.Tag shr 1);
      gtClusterBomb: DrawSpriteRotated(sprClusterBomb, x, y, 0, Gear^.DirAngle);
@@ -1305,6 +1314,7 @@
          end;
       if Gear^.RenderTimer and (Gear^.Tex <> nil) then
           DrawTextureCentered(x + 8, y + 8, Gear^.Tex);
+    if Gear^.State and gstFrozen <> 0 then Tint($FF, $FF, $FF, $FF)
 end;
 
 end.
--- a/hedgewars/uGearsUtils.pas	Thu Apr 04 14:37:19 2013 +0200
+++ b/hedgewars/uGearsUtils.pas	Tue Jun 04 22:28:12 2013 +0200
@@ -1,6 +1,6 @@
 (*
  * Hedgewars, a free turn based strategy game
- * Copyright (c) 2004-2012 Andrey Korotaev <unC0Rr@gmail.com>
+ * Copyright (c) 2004-2013 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
@@ -31,13 +31,13 @@
 procedure HHHurt(Hedgehog: PHedgehog; Source: TDamageSource);
 procedure CheckHHDamage(Gear: PGear);
 procedure CalcRotationDirAngle(Gear: PGear);
-procedure ResurrectHedgehog(gear: PGear);
+procedure ResurrectHedgehog(var gear: PGear);
 
 procedure FindPlace(var Gear: PGear; withFall: boolean; Left, Right: LongInt); inline;
 procedure FindPlace(var Gear: PGear; withFall: boolean; Left, Right: LongInt; skipProximity: boolean);
 
 function  CheckGearNear(Gear: PGear; Kind: TGearType; rX, rY: LongInt): PGear;
-function  CheckGearDrowning(Gear: PGear): boolean;
+function  CheckGearDrowning(var Gear: PGear): boolean;
 procedure CheckCollision(Gear: PGear); inline;
 procedure CheckCollisionWithLand(Gear: PGear); inline;
 
@@ -263,6 +263,7 @@
 
 procedure HHHurt(Hedgehog: PHedgehog; Source: TDamageSource);
 begin
+if Hedgehog^.Effects[heFrozen] <> 0 then exit;
 if (Source = dsFall) or (Source = dsExplosion) then
     case random(3) of
         0: PlaySoundV(sndOoff1, Hedgehog^.Team^.voicepack);
@@ -289,32 +290,34 @@
     i: LongWord;
     particle: PVisualGear;
 begin
-    if _0_4 < Gear^.dY then
-        begin
-        dmg := ModifyDamage(1 + hwRound((hwAbs(Gear^.dY) - _0_4) * 70), Gear);
-        PlaySound(sndBump);
-        if dmg < 1 then
-            exit;
+if _0_4 < Gear^.dY then
+    begin
+    dmg := ModifyDamage(1 + hwRound((Gear^.dY - _0_4) * 70), Gear);
+    if Gear^.Hedgehog^.Effects[heFrozen] = 0 then
+         PlaySound(sndBump)
+    else PlaySound(sndFrozenHogImpact);
+    if dmg < 1 then
+        exit;
 
-        for i:= min(12, (3 + dmg div 10)) downto 0 do
-            begin
-            particle := AddVisualGear(hwRound(Gear^.X) - 5 + Random(10), hwRound(Gear^.Y) + 12, vgtDust);
-            if particle <> nil then
-                particle^.dX := particle^.dX + (Gear^.dX.QWordValue / 21474836480);
-            end;
+    for i:= min(12, (3 + dmg div 10)) downto 0 do
+        begin
+        particle := AddVisualGear(hwRound(Gear^.X) - 5 + Random(10), hwRound(Gear^.Y) + 12, vgtDust);
+        if particle <> nil then
+            particle^.dX := particle^.dX + (Gear^.dX.QWordValue / 21474836480);
+        end;
 
-        if (Gear^.Invulnerable) then
-            exit;
+    if (Gear^.Invulnerable) then
+        exit;
 
-        //if _0_6 < Gear^.dY then
-        //    PlaySound(sndOw4, Gear^.Hedgehog^.Team^.voicepack)
-        //else
-        //    PlaySound(sndOw1, Gear^.Hedgehog^.Team^.voicepack);
+    //if _0_6 < Gear^.dY then
+    //    PlaySound(sndOw4, Gear^.Hedgehog^.Team^.voicepack)
+    //else
+    //    PlaySound(sndOw1, Gear^.Hedgehog^.Team^.voicepack);
 
-        if Gear^.LastDamage <> nil then
-            ApplyDamage(Gear, Gear^.LastDamage, dmg, dsFall)
-        else
-            ApplyDamage(Gear, CurrentHedgehog, dmg, dsFall);
+    if Gear^.LastDamage <> nil then
+        ApplyDamage(Gear, Gear^.LastDamage, dmg, dsFall)
+    else
+        ApplyDamage(Gear, CurrentHedgehog, dmg, dsFall);
     end
 end;
 
@@ -337,8 +340,8 @@
         Gear^.DirAngle := Gear^.DirAngle - 360
 end;
 
-function CheckGearDrowning(Gear: PGear): boolean;
-var
+function CheckGearDrowning(var Gear: PGear): boolean;
+var 
     skipSpeed, skipAngle, skipDecay: hwFloat;
     i, maxDrops, X, Y: LongInt;
     vdX, vdY: real;
@@ -361,7 +364,7 @@
             else DeleteGear(Gear);
             exit
             end;
-        isSubmersible:= (Gear = CurrentHedgehog^.Gear) and (CurAmmoGear <> nil) and (CurAmmoGear^.AmmoType = amJetpack);
+        isSubmersible:= ((Gear = CurrentHedgehog^.Gear) and (CurAmmoGear <> nil) and (CurAmmoGear^.State and gstSubmersible <> 0)) or (Gear^.State and gstSubmersible <> 0);
         skipSpeed := _0_25;
         skipAngle := _1_9;
         skipDecay := _0_87;
@@ -369,7 +372,7 @@
         vdX:= hwFloat2Float(Gear^.dX);
         vdY:= hwFloat2Float(Gear^.dY);
         // this could perhaps be a tiny bit higher.
-        if  (hwSqr(Gear^.dX) + hwSqr(Gear^.dY) > skipSpeed)
+        if  (cWaterLine + 64 + Gear^.Radius > Y) and (hwSqr(Gear^.dX) + hwSqr(Gear^.dY) > skipSpeed) 
         and (hwAbs(Gear^.dX) > skipAngle * hwAbs(Gear^.dY)) then
             begin
             Gear^.dY.isNegative := true;
@@ -390,7 +393,11 @@
                     if Gear^.Kind = gtHedgehog then
                         begin
                         if Gear^.Hedgehog^.Effects[heResurrectable] <> 0 then
-                            ResurrectHedgehog(Gear)
+                            begin
+                            // Gear could become nil after this, just exit to skip splashes
+                            ResurrectHedgehog(Gear);
+                            exit
+                            end
                         else
                             begin
                             Gear^.doStep := @doStepDrowningGear;
@@ -401,10 +408,13 @@
                     else
                         Gear^.doStep := @doStepDrowningGear;
                         if Gear^.Kind = gtFlake then
-                            exit // skip splashes
-                end;
+                            exit // skip splashes 
+                end
+            else if (Y > cWaterLine + cVisibleWater*4) and 
+                    ((Gear <> CurrentHedgehog^.Gear) or (CurAmmoGear = nil) or (CurAmmoGear^.State and gstSubmersible = 0)) then
+                Gear^.doStep:= @doStepDrowningGear;
             if ((not isSubmersible) and (Y < cWaterLine + 64 + Gear^.Radius))
-            or (isSubmersible and (Y < cWaterLine + 2 + Gear^.Radius) and ((CurAmmoGear^.Pos = 0)
+            or (isSubmersible and (Y < cWaterLine + 2 + Gear^.Radius) and (Gear = CurAmmoGear) and ((CurAmmoGear^.Pos = 0)
             and (CurAmmoGear^.dY < _0_01))) then
                 if Gear^.Density * Gear^.dY > _1 then
                     PlaySound(sndSplash)
@@ -416,7 +426,7 @@
 
         if ((cReducedQuality and rqPlainSplash) = 0)
         and (((not isSubmersible) and (Y < cWaterLine + 64 + Gear^.Radius))
-        or (isSubmersible and (Y < cWaterLine + 2 + Gear^.Radius) and ((CurAmmoGear^.Pos = 0)
+        or (isSubmersible and (Y < cWaterLine + 2 + Gear^.Radius) and (Gear = CurAmmoGear) and ((CurAmmoGear^.Pos = 0)
         and (CurAmmoGear^.dY < _0_01)))) then
             begin
             splash:= AddVisualGear(X, cWaterLine, vgtSplash);
@@ -457,7 +467,7 @@
                         end
                 end
             end;
-        if isSubmersible and (CurAmmoGear^.Pos = 0) then
+        if isSubmersible and (Gear = CurAmmoGear) and (CurAmmoGear^.Pos = 0) then
             CurAmmoGear^.Pos := 1000
         end
     else
@@ -465,7 +475,7 @@
 end;
 
 
-procedure ResurrectHedgehog(gear: PGear);
+procedure ResurrectHedgehog(var gear: PGear);
 var tempTeam : PTeam;
     sparkles: PVisualGear;
     gX, gY: LongInt;
@@ -507,7 +517,7 @@
         RenderHealth(gear^.Hedgehog^);
         ScriptCall('onGearResurrect', gear^.uid);
         gear^.State := gstWait;
-    end;
+        end;
     RecountTeamHealth(tempTeam);
 end;
 
--- a/hedgewars/uIO.pas	Thu Apr 04 14:37:19 2013 +0200
+++ b/hedgewars/uIO.pas	Tue Jun 04 22:28:12 2013 +0200
@@ -1,6 +1,6 @@
 (*
  * Hedgewars, a free turn based strategy game
- * Copyright (c) 2004-2012 Andrey Korotaev <unC0Rr@gmail.com>
+ * Copyright (c) 2004-2013 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
--- a/hedgewars/uInputHandler.pas	Thu Apr 04 14:37:19 2013 +0200
+++ b/hedgewars/uInputHandler.pas	Tue Jun 04 22:28:12 2013 +0200
@@ -1,6 +1,6 @@
 (*
  * Hedgewars, a free turn based strategy game
- * Copyright (c) 2004-2012 Andrey Korotaev <unC0Rr@gmail.com>
+ * Copyright (c) 2004-2013 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
@@ -289,8 +289,8 @@
 DefaultBinds[KeyNameToCode(_S'y')]:= 'confirm';
 
 DefaultBinds[KeyNameToCode('mousem')]:= 'zoomreset';
-DefaultBinds[KeyNameToCode('wheelup')]:= 'zoomout';
-DefaultBinds[KeyNameToCode('wheeldown')]:= 'zoomin';
+DefaultBinds[KeyNameToCode('wheelup')]:= 'zoomin';
+DefaultBinds[KeyNameToCode('wheeldown')]:= 'zoomout';
 
 DefaultBinds[KeyNameToCode('f12')]:= 'fullscr';
 
--- a/hedgewars/uLand.pas	Thu Apr 04 14:37:19 2013 +0200
+++ b/hedgewars/uLand.pas	Tue Jun 04 22:28:12 2013 +0200
@@ -1,6 +1,6 @@
 (*
  * Hedgewars, a free turn based strategy game
- * Copyright (c) 2004-2012 Andrey Korotaev <unC0Rr@gmail.com>
+ * Copyright (c) 2004-2013 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
@@ -484,28 +484,11 @@
 
         p:= tmpsurf^.pixels;
         for y:= 0 to Pred(tmpsurf^.h) do
-        begin
+            begin
             for x:= 0 to Pred(tmpsurf^.w) do
-            begin
-                // this an if instead of masking colours to avoid confusing map creators
-                if ((AMask and p^[x]) = 0) then
-                    Land[cpY + y, cpX + x]:= 0
-                else if p^[x] = $FFFFFFFF then                  // white
-                    Land[cpY + y, cpX + x]:= lfObject
-                else if p^[x] = AMask then                      // black
-                    begin
-                    Land[cpY + y, cpX + x]:= lfBasic;
-                    disableLandBack:= false
-                    end
-                else if p^[x] = (AMask or RMask) then           // red
-                    Land[cpY + y, cpX + x]:= lfIndestructible
-                else if p^[x] = (AMask or BMask) then           // blue
-                    Land[cpY + y, cpX + x]:= lfObject or lfIce
-                else if p^[x] = (AMask or GMask) then           // green
-                    Land[cpY + y, cpX + x]:= lfObject or lfBouncy
+                SetLand(Land[cpY + y, cpX + x], p^[x]);
+            p:= @(p^[tmpsurf^.pitch div 4]);
             end;
-            p:= @(p^[tmpsurf^.pitch div 4]);
-        end;
 
     if SDL_MustLock(tmpsurf) then
         SDL_UnlockSurface(tmpsurf);
--- a/hedgewars/uLandGenMaze.pas	Thu Apr 04 14:37:19 2013 +0200
+++ b/hedgewars/uLandGenMaze.pas	Tue Jun 04 22:28:12 2013 +0200
@@ -1,3 +1,5 @@
+{$INCLUDE "options.inc"}
+
 unit uLandGenMaze;
 
 interface
--- a/hedgewars/uLandGraphics.pas	Thu Apr 04 14:37:19 2013 +0200
+++ b/hedgewars/uLandGraphics.pas	Tue Jun 04 22:28:12 2013 +0200
@@ -1,6 +1,6 @@
 (*
  * Hedgewars, a free turn based strategy game
- * Copyright (c) 2004-2012 Andrey Korotaev <unC0Rr@gmail.com>
+ * Copyright (c) 2004-2013 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
--- a/hedgewars/uLandObjects.pas	Thu Apr 04 14:37:19 2013 +0200
+++ b/hedgewars/uLandObjects.pas	Tue Jun 04 22:28:12 2013 +0200
@@ -1,6 +1,6 @@
 (*
  * Hedgewars, a free turn based strategy game
- * Copyright (c) 2004-2012 Andrey Korotaev <unC0Rr@gmail.com>
+ * Copyright (c) 2004-2013 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
@@ -27,7 +27,9 @@
 procedure LoadThemeConfig;
 procedure BlitImageAndGenerateCollisionInfo(cpX, cpY, Width: Longword; Image: PSDL_Surface); inline;
 procedure BlitImageAndGenerateCollisionInfo(cpX, cpY, Width: Longword; Image: PSDL_Surface; extraFlags: Word);
+procedure BlitImageUsingMask(cpX, cpY: Longword;  Image, Mask: PSDL_Surface);
 procedure AddOnLandObjects(Surface: PSDL_Surface);
+procedure SetLand(var LandWord: Word; Pixel: LongWord); inline;
 
 implementation
 uses uStore, uConsts, uConsole, uRandom, uSound, GLunit
@@ -42,7 +44,7 @@
 type TRectsArray = array[0..MaxRects] of TSDL_Rect;
      PRectArray = ^TRectsArray;
      TThemeObject = record
-                     Surf: PSDL_Surface;
+                     Surf, Mask: PSDL_Surface;
                      inland: TSDL_Rect;
                      outland: array[0..Pred(MAXOBJECTRECTS)] of TSDL_Rect;
                      rectcnt: Longword;
@@ -68,7 +70,25 @@
     ThemeObjects: TThemeObjects;
     SprayObjects: TSprayObjects;
 
-
+procedure SetLand(var LandWord: Word; Pixel: LongWord); inline;
+begin
+    // this an if instead of masking colours to avoid confusing map creators
+    if ((AMask and Pixel) = 0) then
+        LandWord:= 0
+    else if Pixel = $FFFFFFFF then                  // white
+        LandWord:= lfObject
+    else if Pixel = AMask then                      // black
+        begin
+        LandWord:= lfBasic;
+        disableLandBack:= false
+        end
+    else if Pixel = (AMask or RMask) then           // red
+        LandWord:= lfIndestructible
+    else if Pixel = (AMask or BMask) then           // blue
+        LandWord:= lfObject or lfIce
+    else if Pixel = (AMask or GMask) then           // green
+        LandWord:= lfObject or lfBouncy
+end;
 
 procedure BlitImageAndGenerateCollisionInfo(cpX, cpY, Width: Longword; Image: PSDL_Surface); inline;
 begin
@@ -121,6 +141,47 @@
 WriteLnToConsole(msgOK)
 end;
 
+procedure BlitImageUsingMask(cpX, cpY: Longword;  Image, Mask: PSDL_Surface);
+var p, mp: PLongwordArray;
+    x, y: Longword;
+    bpp: LongInt;
+begin
+WriteToConsole('Generating collision info... ');
+
+if SDL_MustLock(Image) then
+    SDLTry(SDL_LockSurface(Image) >= 0, true);
+
+bpp:= Image^.format^.BytesPerPixel;
+TryDo(bpp = 4, 'Land object should be 32bit', true);
+
+p:= Image^.pixels;
+mp:= Mask^.pixels;
+for y:= 0 to Pred(Image^.h) do
+    begin
+    for x:= 0 to Pred(Image^.w) do
+        begin
+        if (cReducedQuality and rqBlurryLand) = 0 then
+            begin
+            if (LandPixels[cpY + y, cpX + x] = 0)
+            or (((p^[x] and AMask) <> 0) and (((LandPixels[cpY + y, cpX + x] and AMask) shr AShift) < 255)) then
+                LandPixels[cpY + y, cpX + x]:= p^[x];
+            end
+        else
+            if LandPixels[(cpY + y) div 2, (cpX + x) div 2] = 0 then 
+                LandPixels[(cpY + y) div 2, (cpX + x) div 2]:= p^[x];
+
+        if (Land[cpY + y, cpX + x] <= lfAllObjMask) or (Land[cpY + y, cpX + x] and lfObject <> 0)  then
+            SetLand(Land[cpY + y, cpX + x], mp^[x]);
+        end;
+    p:= @(p^[Image^.pitch shr 2]);
+    mp:= @(mp^[Mask^.pitch shr 2])
+    end;
+
+if SDL_MustLock(Image) then
+    SDL_UnlockSurface(Image);
+WriteLnToConsole(msgOK)
+end;
+
 procedure AddRect(x1, y1, w1, h1: LongInt);
 begin
 with Rects^[RectCount] do
@@ -328,7 +389,9 @@
     if bRes then
         begin
         i:= getrandom(cnt);
-        BlitImageAndGenerateCollisionInfo(ar[i].x, ar[i].y, 0, Obj.Surf);
+        if Obj.Mask <> nil then
+             BlitImageUsingMask(ar[i].x, ar[i].y, Obj.Surf, Obj.Mask)
+        else BlitImageAndGenerateCollisionInfo(ar[i].x, ar[i].y, 0, Obj.Surf);
         AddRect(ar[i].x, ar[i].y, Width, Height);
         dec(Maxcnt)
         end
@@ -557,9 +620,10 @@
         with ThemeObjects.objs[Pred(ThemeObjects.Count)] do
             begin
             i:= Pos(',', s);
-            Surf:= LoadDataImage(ptCurrTheme, Trim(Copy(s, 1, Pred(i))), ifTransparent or ifIgnoreCaps);
+            Surf:= LoadDataImage(ptCurrTheme, Trim(Copy(s, 1, Pred(i))), ifTransparent or ifIgnoreCaps or ifCritical);
             Width:= Surf^.w;
             Height:= Surf^.h;
+            Mask:= LoadDataImage(ptCurrTheme, Trim(Copy(s, 1, Pred(i)))+'_mask', ifTransparent or ifIgnoreCaps);
             Delete(s, 1, i);
             i:= Pos(',', s);
             Maxcnt:= StrToInt(Trim(Copy(s, 1, Pred(i))));
--- a/hedgewars/uLandPainted.pas	Thu Apr 04 14:37:19 2013 +0200
+++ b/hedgewars/uLandPainted.pas	Tue Jun 04 22:28:12 2013 +0200
@@ -1,6 +1,6 @@
 (*
  * Hedgewars, a free turn based strategy game
- * Copyright (c) 2004-2012 Andrey Korotaev <unC0Rr@gmail.com>
+ * Copyright (c) 2004-2013 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
--- a/hedgewars/uLandTemplates.pas	Thu Apr 04 14:37:19 2013 +0200
+++ b/hedgewars/uLandTemplates.pas	Tue Jun 04 22:28:12 2013 +0200
@@ -1,6 +1,6 @@
 (*
  * Hedgewars, a free turn based strategy game
- * Copyright (c) 2004-2012 Andrey Korotaev <unC0Rr@gmail.com>
+ * Copyright (c) 2004-2013 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
@@ -1815,7 +1815,7 @@
         FillPointsCount: Succ(High(Template0FPoints)){$IFDEF PAS2C}-1{$ENDIF};
         BezierizeCount: 3;
         RandPassesCount: 8;
-        TemplateHeight: 1424; TemplateWidth: 2848;
+        TemplateHeight: 1424; TemplateWidth: 3072;
         canMirror: true; canFlip: false; isNegative: false; canInvert: false;
         hasGirders: true;
         MaxHedgeHogs: 18;
@@ -1826,7 +1826,7 @@
         FillPointsCount: Succ(High(Template1FPoints)){$IFDEF PAS2C}-1{$ENDIF};
         BezierizeCount: 3;
         RandPassesCount: 7;
-        TemplateHeight: 1424; TemplateWidth: 2848;
+        TemplateHeight: 1424; TemplateWidth: 3072;
         canMirror: true; canFlip: false; isNegative: false; canInvert: false;
         hasGirders: true;
         MaxHedgeHogs: 18;
@@ -1837,7 +1837,7 @@
         FillPointsCount: Succ(High(Template2FPoints)){$IFDEF PAS2C}-1{$ENDIF};
         BezierizeCount: 2;
         RandPassesCount: 6;
-        TemplateHeight: 1424; TemplateWidth: 2848;
+        TemplateHeight: 1424; TemplateWidth: 3072;
         canMirror: true; canFlip: false; isNegative: false; canInvert: false;
         hasGirders: true;
         MaxHedgeHogs: 18;
@@ -1848,7 +1848,7 @@
         FillPointsCount: Succ(High(Template3FPoints)){$IFDEF PAS2C}-1{$ENDIF};
         BezierizeCount: 3;
         RandPassesCount: 4;
-        TemplateHeight: 1424; TemplateWidth: 2848;
+        TemplateHeight: 1424; TemplateWidth: 3072;
         canMirror: true; canFlip: false; isNegative: false; canInvert: false;
         hasGirders: true;
         MaxHedgeHogs: 18;
@@ -1859,7 +1859,7 @@
         FillPointsCount: Succ(High(Template4FPoints)){$IFDEF PAS2C}-1{$ENDIF};
         BezierizeCount: 3;
         RandPassesCount: 4;
-        TemplateHeight: 1424; TemplateWidth: 2848;
+        TemplateHeight: 1424; TemplateWidth: 3072;
         canMirror: true; canFlip: false; isNegative: false; canInvert: false;
         hasGirders: true;
         MaxHedgeHogs: 18;
@@ -1870,7 +1870,7 @@
         FillPointsCount: Succ(High(Template5FPoints)){$IFDEF PAS2C}-1{$ENDIF};
         BezierizeCount: 2;
         RandPassesCount: 8;
-        TemplateHeight: 1424; TemplateWidth: 2848;
+        TemplateHeight: 1424; TemplateWidth: 3072;
         canMirror: true; canFlip: false; isNegative: false; canInvert: false;
         hasGirders: true;
         MaxHedgeHogs: 18;
@@ -1881,7 +1881,7 @@
         FillPointsCount: Succ(High(Template6FPoints)){$IFDEF PAS2C}-1{$ENDIF};
         BezierizeCount: 2;
         RandPassesCount: 5;
-        TemplateHeight: 1424; TemplateWidth: 2848;
+        TemplateHeight: 1424; TemplateWidth: 3072;
         canMirror: true; canFlip: false; isNegative: false; canInvert: false;
         hasGirders: true;
         MaxHedgeHogs: 18;
@@ -1892,7 +1892,7 @@
         FillPointsCount: Succ(High(Template7FPoints)){$IFDEF PAS2C}-1{$ENDIF};
         BezierizeCount: 4;
         RandPassesCount: 4;
-        TemplateHeight: 1424; TemplateWidth: 2848;
+        TemplateHeight: 1424; TemplateWidth: 3072;
         canMirror: true; canFlip: false; isNegative: false; canInvert: false;
         hasGirders: true;
         MaxHedgeHogs: 18;
@@ -1903,7 +1903,7 @@
         FillPointsCount: Succ(High(Template8FPoints)){$IFDEF PAS2C}-1{$ENDIF};
         BezierizeCount: 2;
         RandPassesCount: 7;
-        TemplateHeight: 1424; TemplateWidth: 2848;
+        TemplateHeight: 1424; TemplateWidth: 3072;
         canMirror: true; canFlip: false; isNegative: false; canInvert: false;
         hasGirders: true;
         MaxHedgeHogs: 18;
@@ -1914,7 +1914,7 @@
         FillPointsCount: Succ(High(Template9FPoints)){$IFDEF PAS2C}-1{$ENDIF};
         BezierizeCount: 1;
         RandPassesCount: 5;
-        TemplateHeight: 1424; TemplateWidth: 2848;
+        TemplateHeight: 1424; TemplateWidth: 3072;
         canMirror: true; canFlip: false; isNegative: false; canInvert: false;
         hasGirders: true;
         MaxHedgeHogs: 18;
@@ -1925,7 +1925,7 @@
         FillPointsCount: Succ(High(Template10FPoints)){$IFDEF PAS2C}-1{$ENDIF};
         BezierizeCount: 2;
         RandPassesCount: 6;
-        TemplateHeight: 1424; TemplateWidth: 2848;
+        TemplateHeight: 1424; TemplateWidth: 3072;
         canMirror: true; canFlip: false; isNegative: false; canInvert: false;
         hasGirders: true;
         MaxHedgeHogs: 18;
@@ -1936,7 +1936,7 @@
         FillPointsCount: Succ(High(Template11FPoints)){$IFDEF PAS2C}-1{$ENDIF};
         BezierizeCount: 1;
         RandPassesCount: 8;
-        TemplateHeight: 1424; TemplateWidth: 2848;
+        TemplateHeight: 1424; TemplateWidth: 3072;
         canMirror: true; canFlip: false; isNegative: false; canInvert: false;
         hasGirders: true;
         MaxHedgeHogs: 18;
@@ -1947,7 +1947,7 @@
         FillPointsCount: Succ(High(Template12FPoints)){$IFDEF PAS2C}-1{$ENDIF};
         BezierizeCount: 3;
         RandPassesCount: 8;
-        TemplateHeight: 1424; TemplateWidth: 2848;
+        TemplateHeight: 1424; TemplateWidth: 3072;
         canMirror: true; canFlip: false; isNegative: false; canInvert: false;
         hasGirders: true;
         MaxHedgeHogs: 18;
@@ -1958,7 +1958,7 @@
         FillPointsCount: Succ(High(Template13FPoints)){$IFDEF PAS2C}-1{$ENDIF};
         BezierizeCount: 3;
         RandPassesCount: 5;
-        TemplateHeight: 1424; TemplateWidth: 2848;
+        TemplateHeight: 1424; TemplateWidth: 3072;
         canMirror: true; canFlip: false; isNegative: false; canInvert: false;
         hasGirders: true;
         MaxHedgeHogs: 18;
@@ -1969,7 +1969,7 @@
         FillPointsCount: Succ(High(Template14FPoints)){$IFDEF PAS2C}-1{$ENDIF};
         BezierizeCount: 3;
         RandPassesCount: 7;
-        TemplateHeight: 1424; TemplateWidth: 2848;
+        TemplateHeight: 1424; TemplateWidth: 3072;
         canMirror: true; canFlip: false; isNegative: false; canInvert: false;
         hasGirders: true;
         MaxHedgeHogs: 18;
@@ -1980,7 +1980,7 @@
         FillPointsCount: Succ(High(Template15FPoints)){$IFDEF PAS2C}-1{$ENDIF};
         BezierizeCount: 2;
         RandPassesCount: 6;
-        TemplateHeight: 1424; TemplateWidth: 2848;
+        TemplateHeight: 1424; TemplateWidth: 3072;
         canMirror: true; canFlip: false; isNegative: false; canInvert: false;
         hasGirders: true;
         MaxHedgeHogs: 18;
@@ -1991,7 +1991,7 @@
         FillPointsCount: Succ(High(Template16FPoints)){$IFDEF PAS2C}-1{$ENDIF};
         BezierizeCount: 2;
         RandPassesCount: 6;
-        TemplateHeight: 1424; TemplateWidth: 2848;
+        TemplateHeight: 1424; TemplateWidth: 3072;
         canMirror: true; canFlip: false; isNegative: false; canInvert: false;
         hasGirders: true;
         MaxHedgeHogs: 18;
@@ -2002,7 +2002,7 @@
         FillPointsCount: Succ(High(Template17FPoints)){$IFDEF PAS2C}-1{$ENDIF};
         BezierizeCount: 3;
         RandPassesCount: 7;
-        TemplateHeight: 1424; TemplateWidth: 2848;
+        TemplateHeight: 1424; TemplateWidth: 3072;
         canMirror: true; canFlip: false; isNegative: false; canInvert: false;
         hasGirders: true;
         MaxHedgeHogs: 18;
@@ -2013,7 +2013,7 @@
         FillPointsCount: Succ(High(Template18FPoints)){$IFDEF PAS2C}-1{$ENDIF};
         BezierizeCount: 3;
         RandPassesCount: 8;
-        TemplateHeight: 1424; TemplateWidth: 3900;
+        TemplateHeight: 1424; TemplateWidth: 4096;
         canMirror: true; canFlip: false; isNegative: false; canInvert: false;
         hasGirders: true;
         MaxHedgeHogs: 36;
@@ -2024,7 +2024,7 @@
         FillPointsCount: Succ(High(Template19FPoints)){$IFDEF PAS2C}-1{$ENDIF};
         BezierizeCount: 3;
         RandPassesCount: 7;
-        TemplateHeight: 1424; TemplateWidth: 3900;
+        TemplateHeight: 1424; TemplateWidth: 4096;
         canMirror: true; canFlip: false; isNegative: false; canInvert: false;
         hasGirders: true;
         MaxHedgeHogs: 36;
@@ -2035,7 +2035,7 @@
         FillPointsCount: Succ(High(Template20FPoints)){$IFDEF PAS2C}-1{$ENDIF};
         BezierizeCount: 2;
         RandPassesCount: 6;
-        TemplateHeight: 1424; TemplateWidth: 3900;
+        TemplateHeight: 1424; TemplateWidth: 4096;
         canMirror: true; canFlip: false; isNegative: false; canInvert: false;
         hasGirders: true;
         MaxHedgeHogs: 36;
@@ -2046,7 +2046,7 @@
         FillPointsCount: Succ(High(Template21FPoints)){$IFDEF PAS2C}-1{$ENDIF};
         BezierizeCount: 3;
         RandPassesCount: 4;
-        TemplateHeight: 1424; TemplateWidth: 3900;
+        TemplateHeight: 1424; TemplateWidth: 4096;
         canMirror: true; canFlip: false; isNegative: false; canInvert: false;
         hasGirders: true;
         MaxHedgeHogs: 36;
@@ -2057,7 +2057,7 @@
         FillPointsCount: Succ(High(Template22FPoints)){$IFDEF PAS2C}-1{$ENDIF};
         BezierizeCount: 3;
         RandPassesCount: 4;
-        TemplateHeight: 1424; TemplateWidth: 3900;
+        TemplateHeight: 1424; TemplateWidth: 4096;
         canMirror: true; canFlip: false; isNegative: false; canInvert: false;
         hasGirders: true;
         MaxHedgeHogs: 36;
@@ -2068,7 +2068,7 @@
         FillPointsCount: Succ(High(Template23FPoints)){$IFDEF PAS2C}-1{$ENDIF};
         BezierizeCount: 2;
         RandPassesCount: 8;
-        TemplateHeight: 1424; TemplateWidth: 3900;
+        TemplateHeight: 1424; TemplateWidth: 4096;
         canMirror: true; canFlip: false; isNegative: false; canInvert: false;
         hasGirders: true;
         MaxHedgeHogs: 36;
@@ -2079,7 +2079,7 @@
         FillPointsCount: Succ(High(Template24FPoints)){$IFDEF PAS2C}-1{$ENDIF};
         BezierizeCount: 2;
         RandPassesCount: 5;
-        TemplateHeight: 1424; TemplateWidth: 3900;
+        TemplateHeight: 1424; TemplateWidth: 4096;
         canMirror: true; canFlip: false; isNegative: false; canInvert: false;
         hasGirders: true;
         MaxHedgeHogs: 36;
@@ -2090,7 +2090,7 @@
         FillPointsCount: Succ(High(Template25FPoints)){$IFDEF PAS2C}-1{$ENDIF};
         BezierizeCount: 4;
         RandPassesCount: 4;
-        TemplateHeight: 1424; TemplateWidth: 3900;
+        TemplateHeight: 1424; TemplateWidth: 4096;
         canMirror: true; canFlip: false; isNegative: false; canInvert: false;
         hasGirders: true;
         MaxHedgeHogs: 36;
@@ -2101,7 +2101,7 @@
         FillPointsCount: Succ(High(Template26FPoints)){$IFDEF PAS2C}-1{$ENDIF};
         BezierizeCount: 2;
         RandPassesCount: 7;
-        TemplateHeight: 1424; TemplateWidth: 3900;
+        TemplateHeight: 1424; TemplateWidth: 4096;
         canMirror: true; canFlip: false; isNegative: false; canInvert: false;
         hasGirders: true;
         MaxHedgeHogs: 36;
@@ -2112,7 +2112,7 @@
         FillPointsCount: Succ(High(Template27FPoints)){$IFDEF PAS2C}-1{$ENDIF};
         BezierizeCount: 1;
         RandPassesCount: 5;
-        TemplateHeight: 1424; TemplateWidth: 3900;
+        TemplateHeight: 1424; TemplateWidth: 4096;
         canMirror: true; canFlip: false; isNegative: false; canInvert: false;
         hasGirders: true;
         MaxHedgeHogs: 36;
@@ -2123,7 +2123,7 @@
         FillPointsCount: Succ(High(Template28FPoints)){$IFDEF PAS2C}-1{$ENDIF};
         BezierizeCount: 2;
         RandPassesCount: 6;
-        TemplateHeight: 1424; TemplateWidth: 3900;
+        TemplateHeight: 1424; TemplateWidth: 4096;
         canMirror: true; canFlip: false; isNegative: false; canInvert: false;
         hasGirders: true;
         MaxHedgeHogs: 36;
@@ -2134,7 +2134,7 @@
         FillPointsCount: Succ(High(Template29FPoints)){$IFDEF PAS2C}-1{$ENDIF};
         BezierizeCount: 1;
         RandPassesCount: 8;
-        TemplateHeight: 1424; TemplateWidth: 3900;
+        TemplateHeight: 1424; TemplateWidth: 4096;
         canMirror: true; canFlip: false; isNegative: false; canInvert: false;
         hasGirders: true;
         MaxHedgeHogs: 36;
@@ -2145,7 +2145,7 @@
         FillPointsCount: Succ(High(Template30FPoints)){$IFDEF PAS2C}-1{$ENDIF};
         BezierizeCount: 3;
         RandPassesCount: 8;
-        TemplateHeight: 1424; TemplateWidth: 3900;
+        TemplateHeight: 1424; TemplateWidth: 4096;
         canMirror: true; canFlip: false; isNegative: false; canInvert: false;
         hasGirders: true;
         MaxHedgeHogs: 36;
@@ -2156,7 +2156,7 @@
         FillPointsCount: Succ(High(Template31FPoints)){$IFDEF PAS2C}-1{$ENDIF};
         BezierizeCount: 3;
         RandPassesCount: 5;
-        TemplateHeight: 1424; TemplateWidth: 3900;
+        TemplateHeight: 1424; TemplateWidth: 4096;
         canMirror: true; canFlip: false; isNegative: false; canInvert: false;
         hasGirders: true;
         MaxHedgeHogs: 36;
@@ -2167,7 +2167,7 @@
         FillPointsCount: Succ(High(Template32FPoints)){$IFDEF PAS2C}-1{$ENDIF};
         BezierizeCount: 3;
         RandPassesCount: 7;
-        TemplateHeight: 1424; TemplateWidth: 3900;
+        TemplateHeight: 1424; TemplateWidth: 4096;
         canMirror: true; canFlip: false; isNegative: false; canInvert: false;
         hasGirders: true;
         MaxHedgeHogs: 36;
@@ -2178,7 +2178,7 @@
         FillPointsCount: Succ(High(Template33FPoints)){$IFDEF PAS2C}-1{$ENDIF};
         BezierizeCount: 2;
         RandPassesCount: 6;
-        TemplateHeight: 1424; TemplateWidth: 3900;
+        TemplateHeight: 1424; TemplateWidth: 4096;
         canMirror: true; canFlip: false; isNegative: false; canInvert: false;
         hasGirders: true;
         MaxHedgeHogs: 36;
@@ -2189,7 +2189,7 @@
         FillPointsCount: Succ(High(Template34FPoints)){$IFDEF PAS2C}-1{$ENDIF};
         BezierizeCount: 2;
         RandPassesCount: 6;
-        TemplateHeight: 1424; TemplateWidth: 3900;
+        TemplateHeight: 1424; TemplateWidth: 4096;
         canMirror: true; canFlip: false; isNegative: false; canInvert: false;
         hasGirders: true;
         MaxHedgeHogs: 36;
@@ -2200,7 +2200,7 @@
         FillPointsCount: Succ(High(Template35FPoints)){$IFDEF PAS2C}-1{$ENDIF};
         BezierizeCount: 3;
         RandPassesCount: 7;
-        TemplateHeight: 1424; TemplateWidth: 3900;
+        TemplateHeight: 1424; TemplateWidth: 4096;
         canMirror: true; canFlip: false; isNegative: false; canInvert: false;
         hasGirders: true;
         MaxHedgeHogs: 36;
--- a/hedgewars/uLandTexture.pas	Thu Apr 04 14:37:19 2013 +0200
+++ b/hedgewars/uLandTexture.pas	Tue Jun 04 22:28:12 2013 +0200
@@ -1,6 +1,6 @@
 (*
  * Hedgewars, a free turn based strategy game
- * Copyright (c) 2004-2012 Andrey Korotaev <unC0Rr@gmail.com>
+ * Copyright (c) 2004-2013 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
--- a/hedgewars/uLocale.pas	Thu Apr 04 14:37:19 2013 +0200
+++ b/hedgewars/uLocale.pas	Tue Jun 04 22:28:12 2013 +0200
@@ -1,6 +1,6 @@
 (*
  * Hedgewars, a free turn based strategy game
- * Copyright (c) 2004-2012 Andrey Korotaev <unC0Rr@gmail.com>
+ * Copyright (c) 2004-2013 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
--- a/hedgewars/uMisc.pas	Thu Apr 04 14:37:19 2013 +0200
+++ b/hedgewars/uMisc.pas	Tue Jun 04 22:28:12 2013 +0200
@@ -1,6 +1,6 @@
 (*
  * Hedgewars, a free turn based strategy game
- * Copyright (c) 2004-2012 Andrey Korotaev <unC0Rr@gmail.com>
+ * Copyright (c) 2004-2013 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
@@ -38,8 +38,7 @@
 
 implementation
 uses SysUtils, uVariables, uUtils
-     {$IFDEF PNG_SCREENSHOTS}, PNGh, png {$ENDIF}
-     {$IFNDEF USE_SDLTHREADS} {$IFDEF UNIX}, cthreads{$ENDIF} {$ENDIF};
+     {$IFDEF PNG_SCREENSHOTS}, PNGh, png {$ENDIF};
 
 type PScreenshot = ^TScreenshot;
      TScreenshot = record
@@ -64,7 +63,7 @@
 
 {$IFDEF PNG_SCREENSHOTS}
 // this funtion will be executed in separate thread
-function SaveScreenshot(screenshot: pointer): PtrInt;
+function SaveScreenshot(screenshot: pointer): LongInt; cdecl; export;
 var i: LongInt;
     png_ptr: ^png_struct;
     info_ptr: ^png_info;
@@ -119,7 +118,7 @@
 {$ELSE} // no PNG_SCREENSHOTS
 
 // this funtion will be executed in separate thread
-function SaveScreenshot(screenshot: pointer): PtrInt;
+function SaveScreenshot(screenshot: pointer): LongInt; cdecl; export;
 var f: file;
     // Windows Bitmap Header
     head: array[0..53] of Byte = (
@@ -263,11 +262,7 @@
 image^.size:= size;
 image^.buffer:= p;
 
-{$IFDEF USE_SDLTHREADS}
-SDL_CreateThread(@SaveScreenshot{$IFDEF SDL13}, nil{$ENDIF}, image);
-{$ELSE}
-BeginThread(@SaveScreenshot, image);
-{$ENDIF}
+SDL_CreateThread(@SaveScreenshot{$IFDEF SDL13}, 'snapshot'{$ENDIF}, image);
 MakeScreenshot:= true; // possibly it is not true but we will not wait for thread to terminate
 end;
 
--- a/hedgewars/uPhysFSLayer.pas	Thu Apr 04 14:37:19 2013 +0200
+++ b/hedgewars/uPhysFSLayer.pas	Tue Jun 04 22:28:12 2013 +0200
@@ -9,6 +9,8 @@
 {$IFNDEF WIN32}
     {$linklib physfs}
     {$linklib physlayer}
+
+    {statically linking physfs brings IOKit dependency on OSX}
     {$IFDEF DARWIN}
         {$linkframework IOKit}
     {$ENDIF}
@@ -34,6 +36,7 @@
 
 function  physfsReader(L: Plua_State; f: PFSFile; sz: Psize_t) : PChar; cdecl; external PhyslayerLibName;
 procedure physfsReaderSetBuffer(buf: pointer); cdecl; external PhyslayerLibName;
+procedure hedgewarsMountPackage(filename: PChar); cdecl; external PhyslayerLibName;
 
 {$IFNDEF PAS2C}
 //apparently pas2c doesn't render the functions below if it finds 'implementation' first
--- a/hedgewars/uRandom.pas	Thu Apr 04 14:37:19 2013 +0200
+++ b/hedgewars/uRandom.pas	Tue Jun 04 22:28:12 2013 +0200
@@ -1,6 +1,6 @@
 (*
  * Hedgewars, a free turn based strategy game
- * Copyright (c) 2004-2012 Andrey Korotaev <unC0Rr@gmail.com>
+ * Copyright (c) 2004-2013 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
@@ -30,8 +30,8 @@
 interface
 uses uFloat;
 
-procedure SetRandomSeed(Seed: shortstring); // Sets the seed that should be used for generating pseudo-random values.
-function  GetRandomf: hwFloat; // Returns a pseudo-random hwFloat.
+procedure SetRandomSeed(Seed: shortstring; dropAdditionalPart: boolean); // Sets the seed that should be used for generating pseudo-random values.
+function  GetRandomf: hwFloat; overload; // Returns a pseudo-random hwFloat.
 function  GetRandom(m: LongWord): LongWord; overload; inline; // Returns a positive pseudo-random integer smaller than m.
 procedure AddRandomness(r: LongWord); inline;
 function  rndSign(num: hwFloat): hwFloat; // Returns num with a random chance of having a inverted sign.
@@ -61,18 +61,24 @@
    str(GetNext, s);
 end;
 
-procedure SetRandomSeed(Seed: shortstring);
-var i: Longword;
+procedure SetRandomSeed(Seed: shortstring; dropAdditionalPart: boolean);
+var i, t, l: Longword;
 begin
 n:= 54;
 
 if Length(Seed) > 54 then
     Seed:= copy(Seed, 1, 54); // not 55 to ensure we have odd numbers in cirbuf
 
-for i:= 0 to Pred(Length(Seed)) do
-    cirbuf[i]:= byte(Seed[i + 1]);
+t:= 0;
+l:= Length(Seed);
 
-for i:= Length(Seed) to 54 do
+while (t < l) and ((not dropAdditionalPart) or (Seed[t + 1] <> '|')) do
+    begin
+    cirbuf[t]:= byte(Seed[t + 1]);
+    inc(t)
+    end;
+
+for i:= t to 54 do
     cirbuf[i]:= $A98765 + 68; // odd number
 
 for i:= 0 to 1023 do
--- a/hedgewars/uRender.pas	Thu Apr 04 14:37:19 2013 +0200
+++ b/hedgewars/uRender.pas	Tue Jun 04 22:28:12 2013 +0200
@@ -1,6 +1,6 @@
 (*
  * Hedgewars, a free turn based strategy game
- * Copyright (c) 2004-2012 Andrey Korotaev <unC0Rr@gmail.com>
+ * Copyright (c) 2004-2013 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
--- a/hedgewars/uRenderUtils.pas	Thu Apr 04 14:37:19 2013 +0200
+++ b/hedgewars/uRenderUtils.pas	Tue Jun 04 22:28:12 2013 +0200
@@ -1,6 +1,6 @@
 (*
  * Hedgewars, a free turn based strategy game
- * Copyright (c) 2004-2012 Andrey Korotaev <unC0Rr@gmail.com>
+ * Copyright (c) 2004-2013 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
--- a/hedgewars/uScript.pas	Thu Apr 04 14:37:19 2013 +0200
+++ b/hedgewars/uScript.pas	Tue Jun 04 22:28:12 2013 +0200
@@ -1,6 +1,6 @@
 (*
  * Hedgewars, a free turn based strategy game
- * Copyright (c) 2004-2012 Andrey Korotaev <unC0Rr@gmail.com>
+ * Copyright (c) 2004-2013 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
@@ -2039,7 +2039,8 @@
     // call the script file
     lua_pcall(luaState, 0, 0, 0);
     ScriptLoaded:= true
-    end
+    end;
+    hedgewarsMountPackage(Str2PChar(copy(s, 1, length(s)-4)+'.hwp'));
 end;
 
 procedure SetGlobals;
@@ -2261,6 +2262,7 @@
 ScriptSetInteger('gfMultiWeapon', gfMultiWeapon);
 ScriptSetInteger('gfSolidLand', gfSolidLand);
 ScriptSetInteger('gfBorder', gfBorder);
+ScriptSetInteger('gfBottomBorder', gfBottomBorder);
 ScriptSetInteger('gfDivideTeams', gfDivideTeams);
 ScriptSetInteger('gfLowGravity', gfLowGravity);
 ScriptSetInteger('gfLaserSight', gfLaserSight);
--- a/hedgewars/uSinTable.pas	Thu Apr 04 14:37:19 2013 +0200
+++ b/hedgewars/uSinTable.pas	Tue Jun 04 22:28:12 2013 +0200
@@ -1,6 +1,6 @@
 (*
  * Hedgewars, a free turn based strategy game
- * Copyright (c) 2004-2012 Andrey Korotaev <unC0Rr@gmail.com>
+ * Copyright (c) 2004-2013 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
--- a/hedgewars/uSound.pas	Thu Apr 04 14:37:19 2013 +0200
+++ b/hedgewars/uSound.pas	Tue Jun 04 22:28:12 2013 +0200
@@ -1,6 +1,6 @@
 (*
  * Hedgewars, a free turn based strategy game
- * Copyright (c) 2004-2012 Andrey Korotaev <unC0Rr@gmail.com>
+ * Copyright (c) 2004-2013 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
@@ -155,7 +155,7 @@
             (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:          'Justyouwait.ogg'; Path: ptVoices),// sndJustyouwait
             (FileName:             'Incoming.ogg'; Path: ptVoices),// sndIncoming
             (FileName:               'Missed.ogg'; Path: ptVoices),// sndMissed
             (FileName:               'Stupid.ogg'; Path: ptVoices),// sndStupid
@@ -248,7 +248,10 @@
             (FileName:                 'bump.ogg'; Path: ptSounds),// sndBump
             (FileName:            'hogchant3.ogg'; Path: ptSounds),// sndResurrector
             (FileName:                'plane.ogg'; Path: ptSounds),// sndPlane
-            (FileName:               'TARDIS.ogg'; Path: ptSounds) // sndTardis
+            (FileName:               'TARDIS.ogg'; Path: ptSounds),// sndTardis
+            (FileName:    'frozen_hog_impact.ogg'; Path: ptSounds),// sndFrozenHogImpact
+            (FileName:             'ice_beam.ogg'; Path: ptSounds),// sndIceBeam
+            (FileName:           'hog_freeze.ogg'; Path: ptSounds) // sndHogFreeze
             );
 
 
--- a/hedgewars/uStats.pas	Thu Apr 04 14:37:19 2013 +0200
+++ b/hedgewars/uStats.pas	Tue Jun 04 22:28:12 2013 +0200
@@ -1,6 +1,6 @@
 (*
  * Hedgewars, a free turn based strategy game
- * Copyright (c) 2004-2012 Andrey Korotaev <unC0Rr@gmail.com>
+ * Copyright (c) 2004-2013 Andrey Korotaev <unC0Rr@gmail.com>
  *</