merge
authormikade
Mon, 20 Jun 2011 20:43:11 +0200 (2011-06-20)
changeset 5270 df1588234b96
parent 5248 32465b4b4049 (current diff)
parent 5269 e32fc0fcaad0 (diff)
child 5271 48d18e329298
merge
--- a/.hgignore	Fri Jun 17 18:03:12 2011 +0200
+++ b/.hgignore	Mon Jun 20 20:43:11 2011 +0200
@@ -22,6 +22,7 @@
 glob:vittorio.*
 glob:project_files/HedgewarsMobile/Data/
 glob:project_files/HedgewarsMobile/build/
+glob:gameServer/dist/
 glob:misc/libtremor/Xcode/build/
 glob:misc/liblua/Xcode/build/
 glob:misc/libfreetype/Xcode/build/
--- a/QTfrontend/CMakeLists.txt	Fri Jun 17 18:03:12 2011 +0200
+++ b/QTfrontend/CMakeLists.txt	Mon Jun 20 20:43:11 2011 +0200
@@ -4,6 +4,7 @@
 set(QT_USE_QTCORE TRUE)
 set(QT_USE_QTGUI TRUE)
 set(QT_USE_QTNETWORK TRUE)
+set(QT_USE_QTWEBKIT TRUE)
 set(QT_USE_QTSVG FALSE)
 set(QT_USE_QTXML FALSE)
 set(QT_USE_QTOPENGL FALSE)
@@ -46,6 +47,7 @@
 configure_file(${CMAKE_CURRENT_SOURCE_DIR}/hwconsts.cpp.in ${CMAKE_CURRENT_BINARY_DIR}/hwconsts.cpp)
 
 set(hwfr_src
+    HWApplication.cpp
     game.cpp
     main.cpp
     hwform.cpp
@@ -66,6 +68,7 @@
     pagenetserver.cpp
     pagenetgame.cpp
     pageinfo.cpp
+    pagedata.cpp
     pagesingleplayer.cpp
     pagetraining.cpp
     pagecampaign.cpp
@@ -130,6 +133,7 @@
 endif(MINGW)
 
 set(hwfr_moc_hdrs
+    HWApplication.h
     game.h
     hats.h
     hwform.h
@@ -149,6 +153,7 @@
     pageoptions.h
     pagemain.h
     pageinfo.h
+    pagedata.h
     pagesingleplayer.h
     pagenettype.h
     pageconnecting.h
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/QTfrontend/HWApplication.cpp	Mon Jun 20 20:43:11 2011 +0200
@@ -0,0 +1,45 @@
+/*
+ * Hedgewars, a free turn based strategy game
+ * Copyright (c) 2005-2011 Andrey Korotaev <unC0Rr@gmail.com>
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; version 2 of the License
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA
+ */
+
+#include "HWApplication.h"
+#include <QFileOpenEvent>
+
+#include "hwform.h"
+
+HWApplication::HWApplication(int &argc,  char **argv):
+     QApplication(argc, argv)
+{
+
+}
+
+bool HWApplication::event(QEvent *event) {
+    QFileOpenEvent *openEvent;
+
+    switch (event->type()) {
+        case QEvent::FileOpen:
+            openEvent = (QFileOpenEvent *)event;
+            if (form) form->PlayDemoQuick(openEvent->file());
+            return true;
+            break;
+        default:
+            return QApplication::event(event);
+            break;
+    }
+}
+
+
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/QTfrontend/HWApplication.h	Mon Jun 20 20:43:11 2011 +0200
@@ -0,0 +1,41 @@
+/*
+ * Hedgewars, a free turn based strategy game
+ * Copyright (c) 2005-2011 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 HWAPP_H
+#define HWAPP_H
+
+#include <QApplication>
+#include <QString>
+#include <QEvent>
+
+class HWForm;
+
+class HWApplication : public QApplication
+{
+    Q_OBJECT
+public:
+    HWApplication(int &argc, char **argv);
+    ~HWApplication() {};
+
+    HWForm *form;
+protected:
+    bool event(QEvent *);
+};
+
+#endif
+
--- a/QTfrontend/SDLs.cpp	Fri Jun 17 18:03:12 2011 +0200
+++ b/QTfrontend/SDLs.cpp	Mon Jun 20 20:43:11 2011 +0200
@@ -21,8 +21,7 @@
 #include "SDL.h"
 #include "SDL_mixer.h"
 #include "hwconsts.h"
-
-#include <QApplication>
+#include "HWApplication.h"
 
 
 extern char sdlkeys[1024][2][128];
@@ -101,38 +100,38 @@
         for(int aid = 0; aid < SDL_JoystickNumAxes(joy) && i < 1021; aid++)
         {
             // Again store the part of the string not changing for multiple uses
-            QString axis = prefix + QApplication::translate("binds (keys)", "Axis") + QString(" %1 ").arg(aid + 1);
+            QString axis = prefix + HWApplication::translate("binds (keys)", "Axis") + QString(" %1 ").arg(aid + 1);
 
             // Entry for "Axis Up"
             sprintf(sdlkeys[i][0], "j%da%du", jid, aid);
-            sprintf(sdlkeys[i++][1], "%s", ((isxb && aid < 5) ? (prefix + QApplication::translate("binds (keys)", xbox360axes[aid * 2])) : axis + QApplication::translate("binds (keys)", "(Up)")).toStdString().c_str());
+            sprintf(sdlkeys[i++][1], "%s", ((isxb && aid < 5) ? (prefix + HWApplication::translate("binds (keys)", xbox360axes[aid * 2])) : axis + HWApplication::translate("binds (keys)", "(Up)")).toStdString().c_str());
 
             // Entry for "Axis Down"
             sprintf(sdlkeys[i][0], "j%da%dd", jid, aid);
-            sprintf(sdlkeys[i++][1], "%s", ((isxb && aid < 5) ? (prefix + QApplication::translate("binds (keys)", xbox360axes[aid * 2 + 1])) : axis + QApplication::translate("binds (keys)", "(Down)")).toStdString().c_str());
+            sprintf(sdlkeys[i++][1], "%s", ((isxb && aid < 5) ? (prefix + HWApplication::translate("binds (keys)", xbox360axes[aid * 2 + 1])) : axis + HWApplication::translate("binds (keys)", "(Down)")).toStdString().c_str());
         }
 
         // Register entries for all coolie hats of this joystick/gamepad
         for(int hid = 0; hid < SDL_JoystickNumHats(joy) && i < 1019; hid++)
         {
             // Again store the part of the string not changing for multiple uses
-            QString hat = prefix + (isxb ? (QApplication::translate("binds (keys)", xb360dpad) + QString(" ")) : QApplication::translate("binds (keys)", "Hat") + QString(" %1 ").arg(hid + 1));
+            QString hat = prefix + (isxb ? (HWApplication::translate("binds (keys)", xb360dpad) + QString(" ")) : HWApplication::translate("binds (keys)", "Hat") + QString(" %1 ").arg(hid + 1));
 
             // Entry for "Hat Up"
             sprintf(sdlkeys[i][0], "j%dh%du", jid, hid);
-            sprintf(sdlkeys[i++][1], "%s", (hat + QApplication::translate("binds (keys)", "(Up)")).toStdString().c_str());
+            sprintf(sdlkeys[i++][1], "%s", (hat + HWApplication::translate("binds (keys)", "(Up)")).toStdString().c_str());
 
             // Entry for "Hat Down"
             sprintf(sdlkeys[i][0], "j%dh%dd", jid, hid);
-            sprintf(sdlkeys[i++][1], "%s", (hat + QApplication::translate("binds (keys)", "(Down)")).toStdString().c_str());
+            sprintf(sdlkeys[i++][1], "%s", (hat + HWApplication::translate("binds (keys)", "(Down)")).toStdString().c_str());
 
             // Entry for "Hat Left"
             sprintf(sdlkeys[i][0], "j%dh%dl", jid, hid);
-            sprintf(sdlkeys[i++][1], "%s", (hat + QApplication::translate("binds (keys)", "(Left)")).toStdString().c_str());
+            sprintf(sdlkeys[i++][1], "%s", (hat + HWApplication::translate("binds (keys)", "(Left)")).toStdString().c_str());
 
             // Entry for "Hat Right"
             sprintf(sdlkeys[i][0], "j%dh%dr", jid, hid);
-            sprintf(sdlkeys[i++][1], "%s", (hat + QApplication::translate("binds (keys)", "(Right)")).toStdString().c_str());
+            sprintf(sdlkeys[i++][1], "%s", (hat + HWApplication::translate("binds (keys)", "(Right)")).toStdString().c_str());
         }
 
         // Register entries for all buttons of this joystick/gamepad
@@ -140,7 +139,7 @@
         {
             // Buttons
             sprintf(sdlkeys[i][0], "j%db%d", jid, bid);
-            sprintf(sdlkeys[i++][1], "%s", (prefix + ((isxb && bid < 10) ? (QApplication::translate("binds (keys)", xb360buttons[bid]) + QString(" ")) : QApplication::translate("binds (keys)", "Button") + QString(" %1").arg(bid + 1))).toStdString().c_str());
+            sprintf(sdlkeys[i++][1], "%s", (prefix + ((isxb && bid < 10) ? (HWApplication::translate("binds (keys)", xb360buttons[bid]) + QString(" ")) : HWApplication::translate("binds (keys)", "Button") + QString(" %1").arg(bid + 1))).toStdString().c_str());
         }
         // Close the game controller as we no longer need it
         SDL_JoystickClose(joy);
--- a/QTfrontend/chatwidget.cpp	Fri Jun 17 18:03:12 2011 +0200
+++ b/QTfrontend/chatwidget.cpp	Mon Jun 20 20:43:11 2011 +0200
@@ -21,7 +21,6 @@
 #include <QTextBrowser>
 #include <QLineEdit>
 #include <QAction>
-#include <QApplication>
 #include <QTextDocument>
 #include <QDir>
 #include <QSettings>
@@ -31,7 +30,6 @@
 #include <QCursor>
 #include <QScrollBar>
 #include <QItemSelectionModel>
-#include <QLabel>
 
 #include "hwconsts.h"
 #include "SDLs.h"
@@ -165,12 +163,7 @@
     connect(chatNicks, SIGNAL(currentRowChanged(int)),
         this, SLOT(chatNickSelected(int)));
 
-    mainLayout.addWidget(chatNicks, 1, 1, 2, 1);
-
-    lblCount = new QLabel(this);
-    mainLayout.addWidget(lblCount, 0, 1);
-    lblCount->setText("0");
-    lblCount->setSizePolicy(QSizePolicy::Maximum, QSizePolicy::Maximum);
+    mainLayout.addWidget(chatNicks, 0, 1, 3, 1);
 
     acInfo = new QAction(QAction::tr("Info"), chatNicks);
     acInfo->setIcon(QIcon(":/res/info.png"));
@@ -398,7 +391,7 @@
     updateNickItem(item);
     chatNicks->addItem(item);
 
-    lblCount->setText(QString::number(chatNicks->count()));
+    emit nickCountUpdate(chatNicks->count());
 
     if(notifyNick && notify && gameSettings->value("frontend/sound", true).toBool()) {
        Mix_PlayChannel(-1, sound[rand()%4], 0);
@@ -411,7 +404,7 @@
     QListIterator<QListWidgetItem *> it(items);
     while(it.hasNext()) chatNicks->takeItem(chatNicks->row(it.next()));
 
-    lblCount->setText(QString::number(chatNicks->count()));
+    emit nickCountUpdate(chatNicks->count());
 }
 
 void HWChatWidget::clear()
--- a/QTfrontend/chatwidget.h	Fri Jun 17 18:03:12 2011 +0200
+++ b/QTfrontend/chatwidget.h	Mon Jun 20 20:43:11 2011 +0200
@@ -34,7 +34,6 @@
 class QListWidget;
 class QSettings;
 class SDLInteraction;
-class QLabel;
 
 // this class is for custom nick sorting
 class ListWidgetNickItem : public QListWidgetItem
@@ -88,6 +87,7 @@
   void ban(const QString & str);
   void info(const QString & str);
   void follow(const QString &);
+  void nickCountUpdate(int cnt);
 
  private:
   QGridLayout mainLayout;
@@ -102,7 +102,6 @@
   QAction * acIgnore;
   QAction * acFriend;
   QSettings * gameSettings;
-  QLabel * lblCount;
   SDLInteraction * sdli;
   Mix_Chunk *sound[4];
   bool notify;
--- a/QTfrontend/drawmapwidget.cpp	Fri Jun 17 18:03:12 2011 +0200
+++ b/QTfrontend/drawmapwidget.cpp	Mon Jun 20 20:43:11 2011 +0200
@@ -18,6 +18,7 @@
 
 #include <QFile>
 #include <QMessageBox>
+#include <QEvent>
 
 #include "drawmapwidget.h"
 
--- a/QTfrontend/drawmapwidget.h	Fri Jun 17 18:03:12 2011 +0200
+++ b/QTfrontend/drawmapwidget.h	Mon Jun 20 20:43:11 2011 +0200
@@ -23,7 +23,6 @@
 #include <QHBoxLayout>
 #include <QPushButton>
 #include <QGraphicsView>
-#include <QApplication>
 
 #include "qaspectratiolayout.h"
 #include "drawmapscene.h"
--- a/QTfrontend/gameuiconfig.cpp	Fri Jun 17 18:03:12 2011 +0200
+++ b/QTfrontend/gameuiconfig.cpp	Mon Jun 20 20:43:11 2011 +0200
@@ -20,7 +20,6 @@
 #include <QCheckBox>
 #include <QLineEdit>
 #include <QDesktopWidget>
-#include <QApplication>
 #include <QInputDialog>
 #include <QCryptographicHash>
 
@@ -30,6 +29,7 @@
 #include "pagenetserver.h"
 #include "hwconsts.h"
 #include "fpsedit.h"
+#include "HWApplication.h"
 
 GameUIConfig::GameUIConfig(HWForm * FormWidgets, const QString & fileName)
     : QSettings(fileName, QSettings::IniFormat)
@@ -75,6 +75,8 @@
 
     Form->ui.pageOptions->editNetNick->setText(netNick);
     
+    Form->ui.pageOptions->editNetPassword->installEventFilter(this);
+    
     int passLength = value("net/passwordlength", 0).toInt();
     setNetPasswordLength(passLength);
 
@@ -97,7 +99,7 @@
 
     Form->ui.pageOptions->CBLanguage->setCurrentIndex(Form->ui.pageOptions->CBLanguage->findData(value("misc/locale", "").toString()));
 
-    depth = QApplication::desktop()->depth();
+    depth = HWApplication::desktop()->depth();
     if (depth < 16) depth = 16;
     else if (depth > 16) depth = 32;
 }
@@ -327,6 +329,24 @@
     return (netPasswordLength() == 0 || Form->ui.pageOptions->editNetPassword->text() != QString(netPasswordLength(), '\0'));
 }
 
+// When hedgewars launches, the password field is set with null characters. If the user tries to edit the field and there are such characters, then clear the field
+bool GameUIConfig::eventFilter(QObject *object, QEvent *event)
+{
+    if (event->type() == QEvent::FocusIn)
+    {
+        if ((QLineEdit *)object == Form->ui.pageOptions->editNetPassword)
+        {
+            if (!netPasswordIsValid())
+            {
+                Form->ui.pageOptions->editNetPassword->clear();
+            }
+        }
+    }
+    
+    // Don't filter anything
+    return false;
+}
+
 void GameUIConfig::setNetPasswordLength(int passwordLength)
 {
     if (passwordLength > 0)
--- a/QTfrontend/gameuiconfig.h	Fri Jun 17 18:03:12 2011 +0200
+++ b/QTfrontend/gameuiconfig.h	Mon Jun 20 20:43:11 2011 +0200
@@ -22,6 +22,7 @@
 #include <QSettings>
 #include <QStringList>
 #include <QRect>
+#include <QEvent>
 
 class HWForm;
 class QSettings;
@@ -69,9 +70,9 @@
 
 public slots:
     void SaveOptions();
-
 private:
     bool netPasswordIsValid();
+    bool eventFilter(QObject *object, QEvent *event);
     quint8 depth;
 };
 
--- a/QTfrontend/hwform.cpp	Fri Jun 17 18:03:12 2011 +0200
+++ b/QTfrontend/hwform.cpp	Mon Jun 20 20:43:11 2011 +0200
@@ -182,9 +182,7 @@
     connect(ui.pageOptions->BtnDeleteTeam, SIGNAL(clicked()), this, SLOT(DeleteTeam()));
     connect(ui.pageOptions->BtnSaveOptions, SIGNAL(clicked()), config, SLOT(SaveOptions()));
     connect(ui.pageOptions->BtnSaveOptions, SIGNAL(clicked()), this, SLOT(GoBack()));
-#ifndef __APPLE__
     connect(ui.pageOptions->BtnAssociateFiles, SIGNAL(clicked()), this, SLOT(AssociateFiles()));
-#endif
 
     connect(ui.pageOptions->WeaponEdit, SIGNAL(clicked()), this, SLOT(GoToSelectWeapon()));
     connect(ui.pageOptions->WeaponNew, SIGNAL(clicked()), this, SLOT(GoToSelectNewWeapon()));
@@ -460,8 +458,7 @@
 #ifdef USE_XFIRE
     updateXfire();
 #endif
-    if(id == ID_PAGE_DRAWMAP)
-    {
+    if (id == ID_PAGE_DRAWMAP) {
         DrawMapScene * scene;
         if(lastid == ID_PAGE_MULTIPLAYER)
             scene = ui.pageMultiplayer->gameCFG->pMapContainer->getDrawMapScene();
@@ -470,9 +467,9 @@
 
         ui.pageDrawMap->drawMapWidget->setScene(scene);
     }
-    if(lastid == ID_PAGE_DRAWMAP)
-    {
-        if(id == ID_PAGE_MULTIPLAYER)
+
+    if (lastid == ID_PAGE_DRAWMAP) {
+        if (id == ID_PAGE_MULTIPLAYER)
             ui.pageMultiplayer->gameCFG->pMapContainer->mapDrawingFinished();
         else
             ui.pageNetGame->pGameCFG->pMapContainer->mapDrawingFinished();
@@ -487,37 +484,35 @@
         ui.pageOptions->CBTeamName->setVisible(false);
         ui.pageOptions->LblNoEditTeam->setVisible(true);
 
-        if(id == ID_PAGE_MULTIPLAYER) {
-          curTeamSelWidget = ui.pageMultiplayer->teamsSelect;
+        if (id == ID_PAGE_MULTIPLAYER) {
+            curTeamSelWidget = ui.pageMultiplayer->teamsSelect;
         } else {
-          curTeamSelWidget = ui.pageNetGame->pNetTeamsWidget;
+            curTeamSelWidget = ui.pageNetGame->pNetTeamsWidget;
         }
 
         QList<HWTeam> teamsList;
-        for(QStringList::iterator it = tmNames.begin(); it != tmNames.end(); it++) {
-          HWTeam team(*it);
-          team.LoadFromFile();
-          teamsList.push_back(team);
+        for (QStringList::iterator it = tmNames.begin(); it != tmNames.end(); it++) {
+            HWTeam team(*it);
+            team.LoadFromFile();
+            teamsList.push_back(team);
         }
 
-        if(lastid == ID_PAGE_SETUP || lastid == ID_PAGE_DRAWMAP) { // _TEAM
-          if (editedTeam) {
-            curTeamSelWidget->addTeam(*editedTeam);
-          }
-        } else if(lastid != ID_PAGE_GAMESTATS
+        if (lastid == ID_PAGE_SETUP || lastid == ID_PAGE_DRAWMAP) { // _TEAM
+            if (editedTeam) {
+                curTeamSelWidget->addTeam(*editedTeam);
+            }
+        } else if (lastid != ID_PAGE_GAMESTATS
                 && lastid != ID_PAGE_INGAME
                 && lastid != ID_PAGE_SCHEME
                 && lastid != ID_PAGE_SELECTWEAPON) {
             curTeamSelWidget->resetPlayingTeams(teamsList);
         }
     } else
-    if (id == ID_PAGE_GAMESTATS)
-    {
-        ui.pageGameStats->renderStats();
-    }
+        if (id == ID_PAGE_GAMESTATS) {
+            ui.pageGameStats->renderStats();
+        }
 
-    if(id == ID_PAGE_MAIN)
-    {
+    if (id == ID_PAGE_MAIN) {
         ui.pageOptions->BtnNewTeam->setVisible(true);
         ui.pageOptions->BtnEditTeam->setVisible(true);
         ui.pageOptions->BtnDeleteTeam->setVisible(true);
@@ -526,16 +521,16 @@
     }
 
     // load and save ignore/friends lists
-    if(lastid == ID_PAGE_NETGAME) // leaving a room
+    if (lastid == ID_PAGE_NETGAME) // leaving a room
         ui.pageNetGame->pChatWidget->saveLists(ui.pageOptions->editNetNick->text());
     else if(lastid == ID_PAGE_ROOMSLIST) // leaving the lobby
         ui.pageRoomsList->chatWidget->saveLists(ui.pageOptions->editNetNick->text());
 
-    if(id == ID_PAGE_NETGAME) // joining a room
+    if (id == ID_PAGE_NETGAME) // joining a room
         ui.pageNetGame->pChatWidget->loadLists(ui.pageOptions->editNetNick->text());
 // joining the lobby 
-    else if(id == ID_PAGE_ROOMSLIST) {
-        if ( hwnet && game && game->gameState == gsStarted) { // abnormal exit - kick or room destruction - send kills.
+    else if (id == ID_PAGE_ROOMSLIST) {
+        if (hwnet && game && game->gameState == gsStarted) { // abnormal exit - kick or room destruction - send kills.
             game->netSuspend = true;
             game->KillAllTeams();
         }
@@ -713,12 +708,21 @@
                 tr("Error"),
                 tr("Please select record from the list above"),
                 tr("OK"));
-        return ;
+        return;
     }
     CreateGame(0, 0, 0);
     game->PlayDemo(curritem->data(Qt::UserRole).toString());
 }
 
+void HWForm::PlayDemoQuick(const QString & demofilename)
+{
+    if (game && game->gameState == gsStarted) return;
+    GoBack(); //needed to cleanly disconnect from netgame
+    GoToPage(ID_PAGE_MAIN);
+    CreateGame(0, 0, 0);
+    game->PlayDemo(demofilename);
+}
+
 void HWForm::NetConnectServer(const QString & host, quint16 port)
 {
     _NetConnect(host, port, ui.pageOptions->editNetNick->text().trimmed());
@@ -1253,8 +1257,10 @@
     registry_hkcr.setValue("Hedgewars.Demo/Shell/Open/Command/Default", "\"" + bindir->absolutePath().replace("/", "\\") + "\\hwengine.exe\" \"" + cfgdir->absolutePath().replace("/","\\") + "\" \"" + datadir->absolutePath().replace("/", "\\") + "\" \"%1\" --set-everything "+arguments);
     registry_hkcr.setValue("Hedgewars.Save/Shell/Open/Command/Default", "\"" + bindir->absolutePath().replace("/", "\\") + "\\hwengine.exe\" \"" + cfgdir->absolutePath().replace("/","\\") + "\" \"" + datadir->absolutePath().replace("/", "\\") + "\" \"%1\" --set-everything "+arguments);
 #elif defined __APPLE__
-    success = false;
-    // TODO; also enable button in pages.cpp and signal in hwform.cpp
+    // only useful when other apps have taken precedence over our file extensions and you want to reset it
+    system("defaults write com.apple.LaunchServices LSHandlers -array-add '<dict><key>LSHandlerContentTag</key><string>hwd</string><key>LSHandlerContentTagClass</key><string>public.filename-extension</string><key>LSHandlerRoleAll</key><string>org.hedgewars.desktop</string></dict>'");
+    system("defaults write com.apple.LaunchServices LSHandlers -array-add '<dict><key>LSHandlerContentTag</key><string>hws</string><key>LSHandlerContentTagClass</key><string>public.filename-extension</string><key>LSHandlerRoleAll</key><string>org.hedgewars.desktop</string></dict>'");
+    system("/System/Library/Frameworks/CoreServices.framework/Versions/A/Frameworks/LaunchServices.framework/Versions/A/Support/lsregister -kill -domain local -domain system -domain user");
 #else
     // this is a little silly due to all the system commands below anyway - just use mkdir -p ?  Does have the advantage of the alert I guess
     if (success) success = checkForDir(QDir::home().absolutePath() + "/.local");
--- a/QTfrontend/hwform.h	Fri Jun 17 18:03:12 2011 +0200
+++ b/QTfrontend/hwform.h	Mon Jun 20 20:43:11 2011 +0200
@@ -58,6 +58,7 @@
     GameUIConfig * config;
     QSettings * gameSettings; // Same file GameUIConfig points to but without the baggage.  Needs sync() calls if you want to get GameUIConfig changes though
     void updateXfire();
+    void PlayDemoQuick(const QString & demofilename);
 
 private slots:
     void GoToSaves();
@@ -161,7 +162,7 @@
     QSignalMapper * pageSwitchMapper;
 
 #ifdef __APPLE__
-        InstallController * panel;
+    InstallController * panel;
 #endif
 
     void OnPageShown(quint8 id, quint8 lastid=0);
--- a/QTfrontend/main.cpp	Fri Jun 17 18:03:12 2011 +0200
+++ b/QTfrontend/main.cpp	Mon Jun 20 20:43:11 2011 +0200
@@ -16,7 +16,8 @@
  * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA
  */
 
-#include <QApplication>
+#include "HWApplication.h"
+
 #include <QTranslator>
 #include <QLocale>
 #include <QMessageBox>
@@ -51,7 +52,7 @@
 }
 
 int main(int argc, char *argv[]) {
-    QApplication app(argc, argv);
+    HWApplication app(argc, argv);
     app.setAttribute(Qt::AA_DontShowIconsInMenus,false);
 
     QStringList arguments = app.arguments();
@@ -455,8 +456,8 @@
     CocoaInitializer initializer;
 #endif
 
-    HWForm *Form = new HWForm();
+    app.form = new HWForm();
 
-    Form->show();
+    app.form->show();
     return app.exec();
 }
--- a/QTfrontend/mapContainer.cpp	Fri Jun 17 18:03:12 2011 +0200
+++ b/QTfrontend/mapContainer.cpp	Mon Jun 20 20:43:11 2011 +0200
@@ -24,7 +24,6 @@
 #include <QLinearGradient>
 #include <QColor>
 #include <QTextStream>
-#include <QApplication>
 #include <QLabel>
 #include <QListWidget>
 #include <QVBoxLayout>
@@ -35,6 +34,7 @@
 #include "hwconsts.h"
 #include "mapContainer.h"
 #include "igbox.h"
+#include "HWApplication.h"
 
 HWMapContainer::HWMapContainer(QWidget * parent) :
     QWidget(parent),
@@ -46,10 +46,10 @@
     hhLimit = 18;
     templateFilter = 0;
 
-    mainLayout.setContentsMargins(QApplication::style()->pixelMetric(QStyle::PM_LayoutLeftMargin),
+    mainLayout.setContentsMargins(HWApplication::style()->pixelMetric(QStyle::PM_LayoutLeftMargin),
         1,
-        QApplication::style()->pixelMetric(QStyle::PM_LayoutRightMargin),
-        QApplication::style()->pixelMetric(QStyle::PM_LayoutBottomMargin));
+        HWApplication::style()->pixelMetric(QStyle::PM_LayoutRightMargin),
+        HWApplication::style()->pixelMetric(QStyle::PM_LayoutBottomMargin));
 
     QWidget* mapWidget = new QWidget(this);
     mainLayout.addWidget(mapWidget, 0, 0, Qt::AlignHCenter);
--- a/QTfrontend/namegen.cpp	Fri Jun 17 18:03:12 2011 +0200
+++ b/QTfrontend/namegen.cpp	Mon Jun 20 20:43:11 2011 +0200
@@ -19,7 +19,6 @@
 
 #include <QFile>
 #include <QTextStream>
-#include <QApplication>
 #include <QStringList>
 #include <QLineEdit>
 #include "namegen.h"
--- a/QTfrontend/pageeditteam.cpp	Fri Jun 17 18:03:12 2011 +0200
+++ b/QTfrontend/pageeditteam.cpp	Mon Jun 20 20:43:11 2011 +0200
@@ -24,13 +24,13 @@
 #include <QTabWidget>
 #include <QGroupBox>
 #include <QToolBox>
-#include <QApplication>
 
 #include "pageeditteam.h"
 #include "sdlkeys.h"
 #include "hwconsts.h"
 #include "SquareLabel.h"
 #include "hats.h"
+#include "HWApplication.h"
 
 PageEditTeam::PageEditTeam(QWidget* parent, SDLInteraction * sdli) :
   AbstractPage(parent)
@@ -315,24 +315,24 @@
                 pagelayout->addWidget(l, num++, 0, 1, 2);
             }
             curW = new QWidget(this);
-            BindsBox->addItem(curW, QApplication::translate("binds (categories)", cbinds[i].category));
+            BindsBox->addItem(curW, HWApplication::translate("binds (categories)", cbinds[i].category));
             pagelayout = new QGridLayout(curW);
             num = 0;
         }
         if(cbinds[i].description != NULL)
         {
             l = new QLabel(curW);
-            l->setText((num > 0 ? QString("\n") : QString("")) + QApplication::translate("binds (descriptions)", cbinds[i].description));
+            l->setText((num > 0 ? QString("\n") : QString("")) + HWApplication::translate("binds (descriptions)", cbinds[i].description));
             pagelayout->addWidget(l, num++, 0, 1, 2);
         }
 
         l = new QLabel(curW);
-        l->setText(QApplication::translate("binds", cbinds[i].name));
+        l->setText(HWApplication::translate("binds", cbinds[i].name));
         l->setAlignment(Qt::AlignRight);
         pagelayout->addWidget(l, num, 0);
         CBBind[i] = new QComboBox(curW);
         for(int j = 0; sdlkeys[j][1][0] != '\0'; j++)
-            CBBind[i]->addItem(QApplication::translate("binds (keys)", sdlkeys[j][1]).contains(": ") ? QApplication::translate("binds (keys)", sdlkeys[j][1]) : QApplication::translate("binds (keys)", "Keyboard") + QString(": ") + QApplication::translate("binds (keys)", sdlkeys[j][1]), sdlkeys[j][0]);
+            CBBind[i]->addItem(HWApplication::translate("binds (keys)", sdlkeys[j][1]).contains(": ") ? HWApplication::translate("binds (keys)", sdlkeys[j][1]) : HWApplication::translate("binds (keys)", "Keyboard") + QString(": ") + HWApplication::translate("binds (keys)", sdlkeys[j][1]), sdlkeys[j][0]);
         pagelayout->addWidget(CBBind[i++], num++, 1);
     }
 }
--- a/QTfrontend/pageoptions.cpp	Fri Jun 17 18:03:12 2011 +0200
+++ b/QTfrontend/pageoptions.cpp	Mon Jun 20 20:43:11 2011 +0200
@@ -239,16 +239,17 @@
             CBNameWithDate->setText(QCheckBox::tr("Append date and time to record file name"));
             MiscLayout->addWidget(CBNameWithDate, 4, 0, 1, 2);
 
-#ifdef SPARKLE_ENABLED
-            CBAutoUpdate = new QCheckBox(groupMisc);
-            CBAutoUpdate->setText(QCheckBox::tr("Check for updates at startup"));
-            MiscLayout->addWidget(CBAutoUpdate, 5, 0, 1, 2);
-#endif
-#ifndef __APPLE__
             BtnAssociateFiles = new QPushButton(groupMisc);
             BtnAssociateFiles->setText(QPushButton::tr("Associate file extensions"));
             BtnAssociateFiles->setEnabled(!custom_data && !custom_config);
             MiscLayout->addWidget(BtnAssociateFiles, 5, 0, 1, 2);
+
+#ifdef __APPLE__
+#ifdef SPARKLE_ENABLED
+            CBAutoUpdate = new QCheckBox(groupMisc);
+            CBAutoUpdate->setText(QCheckBox::tr("Check for updates at startup"));
+            MiscLayout->addWidget(CBAutoUpdate, 6, 0, 1, 3);
+#endif
 #endif
             gbTBLayout->addWidget(groupMisc, 2, 0);
         }
--- a/QTfrontend/pageroomslist.cpp	Fri Jun 17 18:03:12 2011 +0200
+++ b/QTfrontend/pageroomslist.cpp	Mon Jun 20 20:43:11 2011 +0200
@@ -42,7 +42,7 @@
     roomName->setMaxLength(60);
     newRoomLayout->addWidget(roomNameLabel);
     newRoomLayout->addWidget(roomName);
-    pageLayout->addLayout(newRoomLayout, 0, 0);
+    pageLayout->addLayout(newRoomLayout, 0, 0, 1, 2);
 
     roomsList = new QTableWidget(this);
     roomsList->setSelectionBehavior(QAbstractItemView::SelectRows);
@@ -51,7 +51,7 @@
     roomsList->setAlternatingRowColors(true);
     roomsList->setShowGrid(false);
     roomsList->setSelectionMode(QAbstractItemView::SingleSelection);
-    pageLayout->addWidget(roomsList, 1, 0, 3, 1);
+    pageLayout->addWidget(roomsList, 1, 0, 3, 2);
     pageLayout->setRowStretch(2, 100);
     
     QHBoxLayout * filterLayout = new QHBoxLayout();
@@ -97,19 +97,27 @@
     filterLayout->addWidget(searchLabel);
     filterLayout->addWidget(searchText);
 
-    pageLayout->addLayout(filterLayout, 4, 0);
+    pageLayout->addLayout(filterLayout, 4, 0, 1, 2);
 
     chatWidget = new HWChatWidget(this, gameSettings, sdli, false);
-    pageLayout->addWidget(chatWidget, 5, 0, 1, 2);
+    pageLayout->addWidget(chatWidget, 5, 0, 1, 3);
     pageLayout->setRowStretch(5, 350);
 
-    BtnCreate = addButton(tr("Create"), pageLayout, 0, 1);
-    BtnJoin = addButton(tr("Join"), pageLayout, 1, 1);
-    BtnRefresh = addButton(tr("Refresh"), pageLayout, 3, 1);
-    BtnClear = addButton(tr("Clear"), pageLayout, 4, 1);
+    BtnCreate = addButton(tr("Create"), pageLayout, 0, 2);
+    BtnJoin = addButton(tr("Join"), pageLayout, 1, 2);
+    BtnRefresh = addButton(tr("Refresh"), pageLayout, 3, 2);
+    BtnClear = addButton(tr("Clear"), pageLayout, 4, 2);
 
     BtnBack = addButton(":/res/Exit.png", pageLayout, 6, 0, true);
-    BtnAdmin = addButton(tr("Admin features"), pageLayout, 6, 1);
+
+    lblCount = new QLabel(this);
+    pageLayout->addWidget(lblCount, 6, 1, Qt::AlignHCenter);
+    lblCount->setText("?");
+    lblCount->setSizePolicy(QSizePolicy::Maximum, QSizePolicy::Maximum);
+
+    connect(chatWidget, SIGNAL(nickCountUpdate(const int)), this, SLOT(updateNickCounter(const int)));
+
+    BtnAdmin = addButton(tr("Admin features"), pageLayout, 6, 2);
 
     connect(BtnCreate, SIGNAL(clicked()), this, SLOT(onCreateClick()));
     connect(BtnJoin, SIGNAL(clicked()), this, SLOT(onJoinClick()));
@@ -380,3 +388,9 @@
         emit askForJoinRoom(room);
     }
 }
+
+void PageRoomsList::updateNickCounter(int cnt)
+{
+    lblCount->setText(tr("%1 players online").arg(cnt));
+}
+
--- a/QTfrontend/pageroomslist.h	Fri Jun 17 18:03:12 2011 +0200
+++ b/QTfrontend/pageroomslist.h	Mon Jun 20 20:43:11 2011 +0200
@@ -45,6 +45,7 @@
     QComboBox * CBRules;
     QComboBox * CBWeapons;
     HWChatWidget * chatWidget;
+    QLabel * lblCount;
 
 private:
     bool gameInLobby;
@@ -55,6 +56,7 @@
 public slots:
     void setRoomsList(const QStringList & list);
     void setAdmin(bool);
+    void updateNickCounter(int cnt);
 
 private slots:
     void onCreateClick();
--- a/QTfrontend/team.cpp	Fri Jun 17 18:03:12 2011 +0200
+++ b/QTfrontend/team.cpp	Mon Jun 20 20:43:11 2011 +0200
@@ -18,11 +18,11 @@
 
 #include <QFile>
 #include <QTextStream>
-#include <QApplication>
 #include <QStringList>
 #include <QLineEdit>
 #include <QCryptographicHash>
 #include <QSettings>
+
 #include "team.h"
 #include "hwform.h"
 #include "pageeditteam.h"
--- a/QTfrontend/ui_hwform.h	Fri Jun 17 18:03:12 2011 +0200
+++ b/QTfrontend/ui_hwform.h	Mon Jun 20 20:43:11 2011 +0200
@@ -29,6 +29,7 @@
 class PageNetChat;
 class PageNetGame;
 class PageInfo;
+class PageDataDownload;
 class PageGameStats;
 class PageSinglePlayer;
 class PageTraining;
@@ -62,6 +63,7 @@
     PageNetChat *pageNetChat;
     PageNetGame *pageNetGame;
     PageInfo *pageInfo;
+    PageDataDownload *pageDataDownload;
     PageGameStats *pageGameStats;
     PageSinglePlayer *pageSinglePlayer;
     PageTraining *pageTraining;
--- a/gameServer/Utils.hs	Fri Jun 17 18:03:12 2011 +0200
+++ b/gameServer/Utils.hs	Mon Jun 20 20:43:11 2011 +0200
@@ -75,7 +75,9 @@
             t : replaceTeam tm ts
 
 illegalName :: B.ByteString -> Bool
-illegalName s = B.null s || B.all isSpace s || isSpace (B.head s) || isSpace (B.last s)
+illegalName s = B.null s || B.all isSpace s || isSpace (B.head s) || isSpace (B.last s) || B.any isIllegalChar s
+    where
+        isIllegalChar c = c `List.elem` "$()*+?[]^{|}"
 
 protoNumber2ver :: Word16 -> B.ByteString
 protoNumber2ver v = Map.findWithDefault "Unknown" v vermap
--- a/hedgewars/uLandGraphics.pas	Fri Jun 17 18:03:12 2011 +0200
+++ b/hedgewars/uLandGraphics.pas	Mon Jun 20 20:43:11 2011 +0200
@@ -30,6 +30,7 @@
 function  addBgColor(OldColor, NewColor: LongWord): LongWord;
 function  SweepDirty: boolean;
 function  Despeckle(X, Y: LongInt): boolean;
+procedure Smooth(X, Y: LongInt);
 function  CheckLandValue(X, Y: LongInt; LandFlag: Word): boolean;
 function  DrawExplosion(X, Y, Radius: LongInt): Longword;
 procedure DrawHLinesExplosions(ar: PRangeArray; Radius: LongInt; y, dY: LongInt; Count: Byte);
@@ -751,9 +752,46 @@
 Despeckle:= false
 end;
 
+procedure Smooth(X, Y: LongInt);
+begin
+// a bit of AA for explosions
+if ((cReducedQuality and rqBlurryLand) = 0) and (Land[Y, X] = 0) and (Y > topY+1) and 
+   (Y < LAND_HEIGHT-2) and (X>leftX+1) and (X<rightX-1) then
+    begin
+    if ((((Land[y, x-1] and lfDamaged) <> 0) and (((Land[y+1,x] and lfDamaged) <> 0)) or ((Land[y-1,x] and lfDamaged) <> 0)) or
+       (((Land[y, x+1] and lfDamaged) <> 0) and (((Land[y-1,x] and lfDamaged) <> 0) or ((Land[y+1,x] and lfDamaged) <> 0)))) then
+        begin
+        if (LandPixels[y,x] = 0) then LandPixels[y,x]:= (cExplosionBorderColor and not AMask) or (128 shl AShift)
+        else
+            LandPixels[y,x]:=
+                            (((((LandPixels[y,x] and RMask shr RShift) div 2)+((cExplosionBorderColor and RMask) shr RShift) div 2) and $FF) shl RShift) or
+                            (((((LandPixels[y,x] and GMask shr GShift) div 2)+((cExplosionBorderColor and GMask) shr GShift) div 2) and $FF) shl GShift) or
+                            (((((LandPixels[y,x] and BMask shr BShift) div 2)+((cExplosionBorderColor and BMask) shr BShift) div 2) and $FF) shl BShift) or ($FF shl AShift);
+        Land[y,x]:= lfBasic
+        end
+    else if ((((Land[y, x-1] and lfDamaged) <> 0) and ((Land[y+1,x-1] and lfDamaged) <> 0) and ((Land[y+2,x] and lfDamaged) <> 0)) or
+            (((Land[y, x-1] and lfDamaged) <> 0) and ((Land[y-1,x-1] and lfDamaged) <> 0) and ((Land[y-2,x] and lfDamaged) <> 0)) or
+            (((Land[y, x+1] and lfDamaged) <> 0) and ((Land[y+1,x+1] and lfDamaged) <> 0) and ((Land[y+2,x] and lfDamaged) <> 0)) or
+            (((Land[y, x+1] and lfDamaged) <> 0) and ((Land[y-1,x+1] and lfDamaged) <> 0) and ((Land[y-2,x] and lfDamaged) <> 0)) or
+            (((Land[y+1, x] and lfDamaged) <> 0) and ((Land[y+1,x+1] and lfDamaged) <> 0) and ((Land[y,x+2] and lfDamaged) <> 0)) or
+            (((Land[y-1, x] and lfDamaged) <> 0) and ((Land[y-1,x+1] and lfDamaged) <> 0) and ((Land[y,x+2] and lfDamaged) <> 0)) or
+            (((Land[y+1, x] and lfDamaged) <> 0) and ((Land[y+1,x-1] and lfDamaged) <> 0) and ((Land[y,x-2] and lfDamaged) <> 0)) or
+            (((Land[y-1, x] and lfDamaged) <> 0) and ((Land[y-1,x-1] and lfDamaged) <> 0) and ((Land[y,x-2] and lfDamaged) <> 0))) then
+        begin
+        if (LandPixels[y,x] = 0) then LandPixels[y,x]:= (cExplosionBorderColor and not AMask) or (64 shl AShift)
+        else
+            LandPixels[y,x]:=
+                            (((((LandPixels[y,x] and RMask shr RShift) * 3 div 4)+((cExplosionBorderColor and RMask) shr RShift) div 4) and $FF) shl RShift) or
+                            (((((LandPixels[y,x] and GMask shr GShift) * 3 div 4)+((cExplosionBorderColor and GMask) shr GShift) div 4) and $FF) shl GShift) or
+                            (((((LandPixels[y,x] and BMask shr BShift) * 3 div 4)+((cExplosionBorderColor and BMask) shr BShift) div 4) and $FF) shl BShift) or ($FF shl AShift);
+        Land[y,x]:= lfBasic
+        end
+    end
+end;
+
 function SweepDirty: boolean;
 var x, y, xx, yy, ty, tx: LongInt;
-    bRes, updateBlock, resweep, recheck: boolean;
+    bRes, updateBlock, resweep, recheck, firstpass: boolean;
 begin
 bRes:= false;
 reCheck:= true;
@@ -769,6 +807,7 @@
                 begin
                 updateBlock:= false;
                 resweep:= true;
+                firstpass:= true;
                 ty:= y * 32;
                 tx:= x * 32;
                 while(resweep) do
@@ -776,6 +815,7 @@
                     resweep:= false;
                     for yy:= ty to ty + 31 do
                         for xx:= tx to tx + 31 do
+                            begin
                             if Despeckle(xx, yy) then
                                 begin
                                 bRes:= true;
@@ -802,6 +842,9 @@
                                     recheck:= true;
                                     end
                                 end;
+                            if firstpass then Smooth(xx,yy);
+                            end;
+                    firstpass:= false
                     end;
                 if updateBlock then UpdateLandTexture(tx, 32, ty, 32);
                 LandDirty[y, x]:= 0;
--- a/hedgewars/uVisualGears.pas	Fri Jun 17 18:03:12 2011 +0200
+++ b/hedgewars/uVisualGears.pas	Mon Jun 20 20:43:11 2011 +0200
@@ -403,21 +403,21 @@
 begin
 Gear:= VisualGearsList;
 case Layer of
-    // this level is very distant in the background when stereo
+    // this layer is very distant in the background when stereo
     0: while Gear <> nil do
         begin
         if Gear^.Tint <> $FFFFFFFF then Tint(Gear^.Tint);
         case Gear^.Kind of
             vgtFlake: if SuddenDeathDmg then
-                        if vobSDVelocity = 0 then
-                            DrawSprite(sprSDFlake, round(Gear^.X) + WorldDx, round(Gear^.Y) + WorldDy + SkyOffset, Gear^.Frame)
-                        else
-                            DrawRotatedF(sprSDFlake, round(Gear^.X) + WorldDx, round(Gear^.Y) + WorldDy + SkyOffset, Gear^.Frame, 1, Gear^.Angle)
+                          if vobSDVelocity = 0 then
+                              DrawSprite(sprSDFlake, round(Gear^.X) + WorldDx, round(Gear^.Y) + WorldDy + SkyOffset, Gear^.Frame)
+                          else
+                              DrawRotatedF(sprSDFlake, round(Gear^.X) + WorldDx, round(Gear^.Y) + WorldDy + SkyOffset, Gear^.Frame, 1, Gear^.Angle)
                       else
-                        if vobVelocity = 0 then
-                            DrawSprite(sprFlake, round(Gear^.X) + WorldDx, round(Gear^.Y) + WorldDy + SkyOffset, Gear^.Frame)
-                        else
-                            DrawRotatedF(sprFlake, round(Gear^.X) + WorldDx, round(Gear^.Y) + WorldDy + SkyOffset, Gear^.Frame, 1, Gear^.Angle);
+                          if vobVelocity = 0 then
+                              DrawSprite(sprFlake, round(Gear^.X) + WorldDx, round(Gear^.Y) + WorldDy + SkyOffset, Gear^.Frame)
+                          else
+                              DrawRotatedF(sprFlake, round(Gear^.X) + WorldDx, round(Gear^.Y) + WorldDy + SkyOffset, Gear^.Frame, 1, Gear^.Angle);
             vgtCloud: if SuddenDeathDmg then
                           DrawSprite(sprSDCloud, round(Gear^.X) + WorldDx, round(Gear^.Y) + WorldDy + SkyOffset, Gear^.Frame)
                       else
@@ -425,8 +425,8 @@
             end;
         if Gear^.Tint <> $FFFFFFFF then Tint($FF,$FF,$FF,$FF);
         Gear:= Gear^.NextGear
-        end;
-    // this level is on the land one when stereo
+       end;
+    // this layer is on the land level (which is close but behind the screen plane) when stereo
     1: while Gear <> nil do
         begin
         tinted:= false;
@@ -436,47 +436,47 @@
             vgtEvilTrace: if Gear^.State < 8 then DrawSprite(sprEvilTrace, round(Gear^.X) + WorldDx, round(Gear^.Y) + WorldDy, Gear^.State);
             vgtLineTrail: DrawLine(Gear^.X, Gear^.Y, Gear^.dX, Gear^.dY, 1.0, $FF, min(Gear^.Timer, $C0), min(Gear^.Timer, $80), min(Gear^.Timer, $FF));
         end;
-            if (cReducedQuality and rqAntiBoom) = 0 then
-                case Gear^.Kind of
-                    vgtSmoke: DrawSprite(sprSmoke, round(Gear^.X) + WorldDx - 11, round(Gear^.Y) + WorldDy - 11, 7 - Gear^.Frame);
-                    vgtSmokeWhite: DrawSprite(sprSmokeWhite, round(Gear^.X) + WorldDx - 11, round(Gear^.Y) + WorldDy - 11, 7 - Gear^.Frame);
-                    vgtDust: if Gear^.State = 1 then
-                                DrawSprite(sprSnowDust, round(Gear^.X) + WorldDx - 11, round(Gear^.Y) + WorldDy - 11, 7 - Gear^.Frame)
-                             else
-                                DrawSprite(sprDust, round(Gear^.X) + WorldDx - 11, round(Gear^.Y) + WorldDy - 11, 7 - Gear^.Frame);
-                    vgtFire: if (Gear^.State and gstTmpFlag) = 0 then
-                                 DrawSprite(sprFlame, round(Gear^.X) + WorldDx - 8, round(Gear^.Y) + WorldDy, (RealTicks shr 6 + Gear^.Frame) mod 8)
-                             else
-                                 DrawTextureF(SpritesData[sprFlame].Texture, Gear^.FrameTicks / 900, round(Gear^.X) + WorldDx, round(Gear^.Y) + WorldDy, (RealTicks shr 7 + Gear^.Frame) mod 8, 1, 16, 16);
-                    vgtSplash: if SuddenDeathDmg then
-                                   DrawSprite(sprSDSplash, round(Gear^.X) + WorldDx - 40, round(Gear^.Y) + WorldDy - 58, 19 - (Gear^.FrameTicks div 37))
-                               else
-                                   DrawSprite(sprSplash, round(Gear^.X) + WorldDx - 40, round(Gear^.Y) + WorldDy - 58, 19 - (Gear^.FrameTicks div 37));
-                    vgtDroplet: if SuddenDeathDmg then
-                                    DrawSprite(sprSDDroplet, round(Gear^.X) + WorldDx - 8, round(Gear^.Y) + WorldDy - 8, Gear^.Frame)
-                                else
-                                    DrawSprite(sprDroplet, round(Gear^.X) + WorldDx - 8, round(Gear^.Y) + WorldDy - 8, Gear^.Frame);
-                    vgtChunk: DrawRotatedF(sprChunk, round(Gear^.X) + WorldDx, round(Gear^.Y) + WorldDy, Gear^.Frame, 1, Gear^.Angle);
-                 end;
+        if (cReducedQuality and rqAntiBoom) = 0 then
+            case Gear^.Kind of
+                vgtSmoke: DrawSprite(sprSmoke, round(Gear^.X) + WorldDx - 11, round(Gear^.Y) + WorldDy - 11, 7 - Gear^.Frame);
+                vgtSmokeWhite: DrawSprite(sprSmokeWhite, round(Gear^.X) + WorldDx - 11, round(Gear^.Y) + WorldDy - 11, 7 - Gear^.Frame);
+                vgtDust: if Gear^.State = 1 then
+                             DrawSprite(sprSnowDust, round(Gear^.X) + WorldDx - 11, round(Gear^.Y) + WorldDy - 11, 7 - Gear^.Frame)
+                         else
+                             DrawSprite(sprDust, round(Gear^.X) + WorldDx - 11, round(Gear^.Y) + WorldDy - 11, 7 - Gear^.Frame);
+                vgtFire: if (Gear^.State and gstTmpFlag) = 0 then
+                             DrawSprite(sprFlame, round(Gear^.X) + WorldDx - 8, round(Gear^.Y) + WorldDy, (RealTicks shr 6 + Gear^.Frame) mod 8)
+                         else
+                             DrawTextureF(SpritesData[sprFlame].Texture, Gear^.FrameTicks / 900, round(Gear^.X) + WorldDx, round(Gear^.Y) + WorldDy, (RealTicks shr 7 + Gear^.Frame) mod 8, 1, 16, 16);
+                vgtSplash: if SuddenDeathDmg then
+                               DrawSprite(sprSDSplash, round(Gear^.X) + WorldDx - 40, round(Gear^.Y) + WorldDy - 58, 19 - (Gear^.FrameTicks div 37))
+                           else
+                               DrawSprite(sprSplash, round(Gear^.X) + WorldDx - 40, round(Gear^.Y) + WorldDy - 58, 19 - (Gear^.FrameTicks div 37));
+                vgtDroplet: if SuddenDeathDmg then
+                                DrawSprite(sprSDDroplet, round(Gear^.X) + WorldDx - 8, round(Gear^.Y) + WorldDy - 8, Gear^.Frame)
+                            else
+                                DrawSprite(sprDroplet, round(Gear^.X) + WorldDx - 8, round(Gear^.Y) + WorldDy - 8, Gear^.Frame);
+                vgtBubble: DrawSprite(sprBubbles, round(Gear^.X) + WorldDx - 8, round(Gear^.Y) + WorldDy - 8, Gear^.Frame);//(RealTicks div 64 + Gear^.Frame) mod 8);
+            end;
         if (Gear^.Tint <> $FFFFFFFF) or tinted then Tint($FF,$FF,$FF,$FF);
         Gear:= Gear^.NextGear
-        end;
-    // this level is on the screen plane when stereo (depth = 0)
+       end;
+    // this layer is on the screen plane (depth = 0) when stereo
     3: while Gear <> nil do
         begin
         tinted:= false;
         if Gear^.Tint <> $FFFFFFFF then Tint(Gear^.Tint);
         case Gear^.Kind of
             vgtSpeechBubble: begin
-                           if (Gear^.Tex <> nil) and (((Gear^.State = 0) and (Gear^.Hedgehog^.Team <> CurrentTeam)) or (Gear^.State = 1)) then
-                           begin
-                               tinted:= true;
-                               Tint($FF, $FF, $FF,  $66);
-                               DrawCentered(round(Gear^.X) + WorldDx, round(Gear^.Y) + WorldDy, Gear^.Tex)
-                           end
-                           else if (Gear^.Tex <> nil) and (((Gear^.State = 0) and (Gear^.Hedgehog^.Team = CurrentTeam)) or (Gear^.State = 2)) then
-                               DrawCentered(round(Gear^.X) + WorldDx, round(Gear^.Y) + WorldDy, Gear^.Tex);
-                       end;
+                             if (Gear^.Tex <> nil) and (((Gear^.State = 0) and (Gear^.Hedgehog^.Team <> CurrentTeam)) or (Gear^.State = 1)) then
+                                 begin
+                                 tinted:= true;
+                                 Tint($FF, $FF, $FF,  $66);
+                                 DrawCentered(round(Gear^.X) + WorldDx, round(Gear^.Y) + WorldDy, Gear^.Tex)
+                                 end
+                             else if (Gear^.Tex <> nil) and (((Gear^.State = 0) and (Gear^.Hedgehog^.Team = CurrentTeam)) or (Gear^.State = 2)) then
+                                 DrawCentered(round(Gear^.X) + WorldDx, round(Gear^.Y) + WorldDy, Gear^.Tex);
+                             end;
             vgtSmallDamageTag: DrawCentered(round(Gear^.X) + WorldDx, round(Gear^.Y) + WorldDy, Gear^.Tex);
             vgtHealthTag: if Gear^.Tex <> nil then DrawCentered(round(Gear^.X) + WorldDx, round(Gear^.Y) + WorldDy, Gear^.Tex);
             vgtHealth: begin
@@ -488,10 +488,14 @@
                        DrawSprite(sprHealth, round(Gear^.X) + WorldDx - 8, round(Gear^.Y) + WorldDy - 8, 0);
                        end;
         end;
+        if (cReducedQuality and rqAntiBoom) = 0 then
+            case Gear^.Kind of
+                vgtChunk: DrawRotatedF(sprChunk, round(Gear^.X) + WorldDx, round(Gear^.Y) + WorldDy, Gear^.Frame, 1, Gear^.Angle);
+            end;
         if (Gear^.Tint <> $FFFFFFFF) or tinted then Tint($FF,$FF,$FF,$FF);
         Gear:= Gear^.NextGear
        end;
-    // this level is outside the screen when stereo
+    // this layer is outside the screen when stereo
     2: while Gear <> nil do
         begin
         tinted:= false;
@@ -503,27 +507,26 @@
                              Tint($FF, $FF, $FF, round($FF * (1 - power(Gear^.Timer / 250, 4))));
                              DrawRotatedTextureF(SpritesData[sprBigExplosion].Texture, 0.85 * (-power(2, -10 * Int(Gear^.Timer)/250) + 1) + 0.4, 0, 0, round(Gear^.X) + WorldDx, round(Gear^.Y) + WorldDy, 0, 1, 385, 385, Gear^.Angle);
                              end;
-            end;
+        end;
         if (cReducedQuality and rqAntiBoom) = 0 then
             case Gear^.Kind of
                 vgtExplPart: DrawSprite(sprExplPart, round(Gear^.X) + WorldDx - 16, round(Gear^.Y) + WorldDy - 16, 7 - Gear^.Frame);
                 vgtExplPart2: DrawSprite(sprExplPart2, round(Gear^.X) + WorldDx - 16, round(Gear^.Y) + WorldDy - 16, 7 - Gear^.Frame);
-                vgtBubble: DrawSprite(sprBubbles, round(Gear^.X) + WorldDx - 8, round(Gear^.Y) + WorldDy - 8, Gear^.Frame);//(RealTicks div 64 + Gear^.Frame) mod 8);
                 vgtSteam: DrawSprite(sprSmokeWhite, round(Gear^.X) + WorldDx - 11, round(Gear^.Y) + WorldDy - 11, 7 - Gear^.Frame);
                 vgtAmmo: begin
-                        tinted:= true;
-                        Tint($FF, $FF, $FF, round(Gear^.alpha * $FF));
-                        DrawTextureF(ropeIconTex, Gear^.scale, round(Gear^.X) + WorldDx, round(Gear^.Y) + WorldDy, 0, 1, 32, 32);
-                        DrawTextureF(SpritesData[sprAMAmmos].Texture, Gear^.scale * 0.90, round(Gear^.X) + WorldDx, round(Gear^.Y) + WorldDy, Gear^.Frame - 1, 1, 32, 32);
-                        end;
+                         tinted:= true;
+                         Tint($FF, $FF, $FF, round(Gear^.alpha * $FF));
+                         DrawTextureF(ropeIconTex, Gear^.scale, round(Gear^.X) + WorldDx, round(Gear^.Y) + WorldDy, 0, 1, 32, 32);
+                         DrawTextureF(SpritesData[sprAMAmmos].Texture, Gear^.scale * 0.90, round(Gear^.X) + WorldDx, round(Gear^.Y) + WorldDy, Gear^.Frame - 1, 1, 32, 32);
+                         end;
                 vgtShell: begin
-                            if Gear^.FrameTicks < $FF then
-                                begin
-                                Tint($FF, $FF, $FF, Gear^.FrameTicks);
-                                tinted:= true
-                                end;
-                            DrawRotatedF(sprShell, round(Gear^.X) + WorldDx, round(Gear^.Y) + WorldDy, Gear^.Frame, 1, Gear^.Angle);
-                            end;
+                          if Gear^.FrameTicks < $FF then
+                              begin
+                              Tint($FF, $FF, $FF, Gear^.FrameTicks);
+                              tinted:= true
+                              end;
+                          DrawRotatedF(sprShell, round(Gear^.X) + WorldDx, round(Gear^.Y) + WorldDy, Gear^.Frame, 1, Gear^.Angle);
+                          end;
                 vgtFeather: begin
                             if Gear^.FrameTicks < 255 then
                                 begin
@@ -533,40 +536,40 @@
                             DrawRotatedF(sprFeather, round(Gear^.X) + WorldDx, round(Gear^.Y) + WorldDy, Gear^.Frame, 1, Gear^.Angle);
                           end;
                 vgtEgg: begin
-                            if Gear^.FrameTicks < $FF then
-                                begin
+                        if Gear^.FrameTicks < $FF then
+                            begin
                                 Tint($FF, $FF, $FF, Gear^.FrameTicks);
                                 tinted:= true
-                                end;
-                            DrawRotatedF(sprEgg, round(Gear^.X) + WorldDx, round(Gear^.Y) + WorldDy, Gear^.Frame, 1, Gear^.Angle);
                             end;
-               vgtBeeTrace: begin
-                            if Gear^.FrameTicks < $FF then
-                                Tint($FF, $FF, $FF, Gear^.FrameTicks div 2)
-                            else
-                                Tint($FF, $FF, $FF, $80);
-                            tinted:= true;
-                            DrawRotatedF(sprBeeTrace, round(Gear^.X) + WorldDx, round(Gear^.Y) + WorldDy, Gear^.Frame, 1, (RealTicks shr 4) mod cMaxAngle);
-                            end;
+                        DrawRotatedF(sprEgg, round(Gear^.X) + WorldDx, round(Gear^.Y) + WorldDy, Gear^.Frame, 1, Gear^.Angle);
+                        end;
+                vgtBeeTrace: begin
+                             if Gear^.FrameTicks < $FF then
+                                 Tint($FF, $FF, $FF, Gear^.FrameTicks div 2)
+                             else
+                                 Tint($FF, $FF, $FF, $80);
+                             tinted:= true;
+                             DrawRotatedF(sprBeeTrace, round(Gear^.X) + WorldDx, round(Gear^.Y) + WorldDy, Gear^.Frame, 1, (RealTicks shr 4) mod cMaxAngle);
+                             end;
                 vgtSmokeRing: begin
-                            tinted:= true;
-                            Tint($FF, $FF, $FF, round(Gear^.alpha * $FF));
-                            DrawRotatedTextureF(SpritesData[sprSmokeRing].Texture, Gear^.scale, 0, 0, round(Gear^.X) + WorldDx, round(Gear^.Y) + WorldDy, 0, 1, 200, 200, Gear^.Angle);
-                            end;
-                 vgtNote: DrawRotatedF(sprNote, round(Gear^.X) + WorldDx, round(Gear^.Y) + WorldDy, Gear^.Frame, 1, Gear^.Angle);
+                              tinted:= true;
+                              Tint($FF, $FF, $FF, round(Gear^.alpha * $FF));
+                              DrawRotatedTextureF(SpritesData[sprSmokeRing].Texture, Gear^.scale, 0, 0, round(Gear^.X) + WorldDx, round(Gear^.Y) + WorldDy, 0, 1, 200, 200, Gear^.Angle);
+                              end;
+                vgtNote: DrawRotatedF(sprNote, round(Gear^.X) + WorldDx, round(Gear^.Y) + WorldDy, Gear^.Frame, 1, Gear^.Angle);
                 vgtBulletHit: DrawRotatedF(sprBulletHit, round(Gear^.X) + WorldDx - 0, round(Gear^.Y) + WorldDy - 0, 7 - (Gear^.FrameTicks div 50), 1, Gear^.Angle);
             end;
         case Gear^.Kind of
-            vgtCircle:  if gear^.Angle = 1 then 
-                            begin
-                            tmp:= Gear^.State / 100;
-                            DrawTexture(round(Gear^.X-24*tmp) + WorldDx, round(Gear^.Y-24*tmp) + WorldDy, SpritesData[sprVampiric].Texture, tmp)
-                            end
-                        else DrawCircle(round(Gear^.X) + WorldDx, round(Gear^.Y) + WorldDy, Gear^.State, Gear^.Timer);
+            vgtCircle: if gear^.Angle = 1 then
+                           begin
+                           tmp:= Gear^.State / 100;
+                           DrawTexture(round(Gear^.X-24*tmp) + WorldDx, round(Gear^.Y-24*tmp) + WorldDy, SpritesData[sprVampiric].Texture, tmp)
+                           end
+                       else DrawCircle(round(Gear^.X) + WorldDx, round(Gear^.Y) + WorldDy, Gear^.State, Gear^.Timer);
         end;
         if (Gear^.Tint <> $FFFFFFFF) or tinted then Tint($FF,$FF,$FF,$FF);
         Gear:= Gear^.NextGear
-        end
+       end
     end;
 end;
 
Binary file misc/hedgewars.png has changed
--- a/project_files/hedgewars.pro	Fri Jun 17 18:03:12 2011 +0200
+++ b/project_files/hedgewars.pro	Mon Jun 20 20:43:11 2011 +0200
@@ -3,6 +3,7 @@
 DEPENDPATH += ../QTfrontend/
 INCLUDEPATH += ../QTfrontend/
 INCLUDEPATH += /usr/local/include/SDL
+INCLUDEPATH += /usr/include/SDL
 
 DESTDIR = .
 
@@ -11,6 +12,7 @@
 }
 
 QT += network
+QT += webkit
 
 HEADERS += ../QTfrontend/KB.h ../QTfrontend/SDLs.h \
 	../QTfrontend/SquareLabel.h ../QTfrontend/about.h \
@@ -24,13 +26,12 @@
 	../QTfrontend/igbox.h ../QTfrontend/input_ip.h \
 	../QTfrontend/itemNum.h ../QTfrontend/mapContainer.h \
 	../QTfrontend/misc.h ../QTfrontend/namegen.h \
-        ../QTfrontend/netregister.h ../QTfrontend/netserver.h \
+    ../QTfrontend/netregister.h ../QTfrontend/netserver.h \
 	../QTfrontend/netserverslist.h ../QTfrontend/netudpserver.h \
 	../QTfrontend/netudpwidget.h ../QTfrontend/newnetclient.h \
-	../QTfrontend/pages.h ../QTfrontend/playrecordpage.h \
-        ../QTfrontend/proto.h \
+    ../QTfrontend/proto.h \
 	../QTfrontend/sdlkeys.h ../QTfrontend/selectWeapon.h \
-	../QTfrontend/statsPage.h ../QTfrontend/tcpBase.h \
+	../QTfrontend/tcpBase.h \
 	../QTfrontend/team.h ../QTfrontend/teamselect.h \
 	../QTfrontend/teamselhelper.h ../QTfrontend/togglebutton.h \
 	../QTfrontend/ui_hwform.h ../QTfrontend/vertScrollArea.h \
@@ -38,7 +39,27 @@
 	../QTfrontend/achievements.h \
     ../QTfrontend/drawmapwidget.h \
     ../QTfrontend/drawmapscene.h \
-    ../QTfrontend/qaspectratiolayout.h
+    ../QTfrontend/qaspectratiolayout.h \
+    ../QTfrontend/pagetraining.h \
+    ../QTfrontend/pagesingleplayer.h \
+    ../QTfrontend/pageselectweapon.h \
+    ../QTfrontend/pagescheme.h \
+    ../QTfrontend/pageroomslist.h \
+    ../QTfrontend/pageoptions.h \
+    ../QTfrontend/pagenettype.h \
+    ../QTfrontend/pagenetserver.h \
+    ../QTfrontend/pagenetgame.h \
+    ../QTfrontend/pagenet.h \
+    ../QTfrontend/pagemultiplayer.h \
+    ../QTfrontend/pagemain.h \
+    ../QTfrontend/pageingame.h \
+    ../QTfrontend/pageinfo.h \
+    ../QTfrontend/pagedata.h \
+    ../QTfrontend/pageeditteam.h \
+    ../QTfrontend/pagedrawmap.h \
+    ../QTfrontend/pageconnecting.h \
+    ../QTfrontend/pagecampaign.h \
+    ../QTfrontend/pageadmin.h
 
 SOURCES += ../QTfrontend/SDLs.cpp ../QTfrontend/SquareLabel.cpp \
 	../QTfrontend/about.cpp ../QTfrontend/ammoSchemeModel.cpp \
@@ -54,9 +75,9 @@
 	../QTfrontend/namegen.cpp ../QTfrontend/netregister.cpp \
 	../QTfrontend/netserver.cpp ../QTfrontend/netserverslist.cpp \
 	../QTfrontend/netudpserver.cpp ../QTfrontend/netudpwidget.cpp \
-        ../QTfrontend/newnetclient.cpp \
-	../QTfrontend/playrecordpage.cpp ../QTfrontend/proto.cpp \
-	../QTfrontend/selectWeapon.cpp ../QTfrontend/statsPage.cpp \
+    ../QTfrontend/newnetclient.cpp \
+	../QTfrontend/proto.cpp \
+	../QTfrontend/selectWeapon.cpp \
 	../QTfrontend/tcpBase.cpp ../QTfrontend/team.cpp \
 	../QTfrontend/teamselect.cpp ../QTfrontend/teamselhelper.cpp \
 	../QTfrontend/togglebutton.cpp ../QTfrontend/ui_hwform.cpp \
@@ -80,6 +101,7 @@
     ../QTfrontend/pagemain.cpp \
     ../QTfrontend/pageingame.cpp \
     ../QTfrontend/pageinfo.cpp \
+    ../QTfrontend/pagedata.cpp \
     ../QTfrontend/pageeditteam.cpp \
     ../QTfrontend/pagedrawmap.cpp \
     ../QTfrontend/pageconnecting.cpp \
--- a/share/CMakeLists.txt	Fri Jun 17 18:03:12 2011 +0200
+++ b/share/CMakeLists.txt	Mon Jun 20 20:43:11 2011 +0200
@@ -20,6 +20,8 @@
 		DESTINATION ../)
 	install(PROGRAMS "${hedgewars_SOURCE_DIR}/share/Icon.icns"
 		DESTINATION ../Resources/)
+	install(PROGRAMS "${hedgewars_SOURCE_DIR}/share/hwico.icns"
+		DESTINATION ../Resources/)
 	install(PROGRAMS "${hedgewars_SOURCE_DIR}/share/dsa_pub.pem"
 		DESTINATION ../Resources/)
 ENDIF(APPLE)
--- a/share/Info.plist.in	Fri Jun 17 18:03:12 2011 +0200
+++ b/share/Info.plist.in	Mon Jun 20 20:43:11 2011 +0200
@@ -44,8 +44,112 @@
 		<string>ppc</string>
 	</array>
 	<key>LSMinimumSystemVersion</key>
-	<string>${minimum_macosx}</string>
+	<string>${minimum_macosx_version}</string>
 	<key>SUPublicDSAKeyFile</key>
 	<string>dsa_pub.pem</string>
+	<key>CFBundleLocalizations</key>
+	<array>
+		<string>ar</string>
+		<string>bg</string>
+		<string>cs</string>
+		<string>de</string>
+		<string>el</string>
+		<string>en</string>
+		<string>es</string>
+		<string>fi</string>
+		<string>fr</string>
+		<string>gl</string>
+		<string>hu</string>
+		<string>it</string>
+		<string>ja</string>
+		<string>ko</string>
+		<string>nl</string>
+		<string>pl</string>
+		<string>pt_BR</string>
+		<string>pt_PT</string>
+		<string>ru</string>
+		<string>sk</string>
+		<string>sv</string>
+		<string>tr</string>
+		<string>uk</string>
+		<string>zh_CN</string>
+		<string>zh_TW</string>
+	</array>
+	<key>UTExportedTypeDeclarations</key>
+	<array>
+		<dict>
+			<key>UTTypeIdentifier</key>
+			<string>org.hedgewars.desktop.hws</string>
+			<key>UTTypeReferenceURL</key>
+			<string>http://www.hedgewars.org/demos/</string>
+			<key>UTTypeDescription</key>
+			<string>Hedgewars Save Game</string>
+			<key>UTTypeIconFile</key>
+			<string>public.text.icns</string>
+			<key>UTTypeConformsTo</key>
+			<array>
+				<string>public.data</string>
+			</array>
+			<key>UTTypeTagSpecification</key>
+			<dict>
+				<key>public.filename-extension</key>
+				<array>
+					<string>hws</string>
+				</array>
+				<key>public.mime-type</key>
+				<string>application/x-hedgewars-save</string>
+			</dict>
+		</dict>
+		<dict>
+			<key>UTTypeIdentifier</key>
+			<string>org.hedgewars.desktop.hwd</string>
+			<key>UTTypeReferenceURL</key>
+			<string>http://www.hedgewars.org/demos/</string>
+			<key>UTTypeIconFile</key>
+			<string>public.text.icns</string>
+			<key>UTTypeDescription</key>
+			<string>Hedgewars Demo Game</string>
+			<key>UTTypeConformsTo</key>
+			<array>
+				<string>public.data</string>
+			</array>
+			<key>UTTypeTagSpecification</key>
+			<dict>
+				<key>public.filename-extension</key>
+				<array>
+					<string>hwd</string>
+				</array>
+				<key>public.mime-type</key>
+				<string>application/x-hedgewars-demo</string>
+			</dict>
+		</dict>
+	</array>
+	<key>CFBundleDocumentTypes</key>
+	<array>
+		<dict>
+			<key>CFBundleTypeIconFile</key>
+			<string>hwico.icns</string>
+			<key>CFBundleTypeName</key>
+			<string>Hedgewars Savefile</string>
+			<key>LSItemContentTypes</key>
+			<array>
+				<string>org.hedgewars.desktop.hws</string>
+			</array>
+			<key>CFBundleTypeRole</key>
+			<string>Editor</string>
+		</dict>
+		<dict>
+			<key>CFBundleTypeIconFile</key>
+			<string>hwico.icns</string>
+			<key>CFBundleTypeName</key>
+			<string>Hedgewars Demofile</string>
+			<key>LSItemContentTypes</key>
+			<array>
+				<string>org.hedgewars.desktop.hwd</string>
+			</array>
+			<key>CFBundleTypeRole</key>
+			<string>Viewer</string>
+		</dict>
+	</array>
 </dict>
 </plist>
--- a/share/hedgewars/Data/Locale/pl.txt	Fri Jun 17 18:03:12 2011 +0200
+++ b/share/hedgewars/Data/Locale/pl.txt	Mon Jun 20 20:43:11 2011 +0200
@@ -52,6 +52,10 @@
 00:49=Wskrzeszacz
 00:50=Wiertniczy nalot
 00:51=Kula błotna
+00:52=Nie wybrano broń
+00:53=TARDIS
+00:54=Struktura
+00:55=Land Spray
 
 01:00=Walczmy!
 01:01=Remis
@@ -142,7 +146,6 @@
 02:00=%1 się wykrwawił
 02:00=%1 zginął za słuszną sprawę
 02:00=%1 zostawił w domu kamizelkę kuloodporną
- 
 
 ; Hog (%1) drowned
 02:01=%1 robi za łódź podwodną!
@@ -207,6 +210,7 @@
 02:01=%1 chciał sobie pogadać z rybkami
 02:01=%1, uważaj na rekiny!
 02:01=%1 pływa po Warszawsku. Tyłkiem po piasku!
+
 ; Round starts
 02:02=Walczmy!
 02:02=Cel! Pal!
@@ -259,10 +263,13 @@
 02:02=Daj im popalić!
 02:02=Nie odczuwaj strachu!
 02:02=Bądź odważny i podbijaj!
+
 ; Round ends (win; unused atm)
 02:03=...
+
 ; Round ends (draw; unused atm)
 02:04=...
+
 ; New health crate
 02:05=Przybyła pomoc!
 02:05=Medyk!
@@ -294,6 +301,7 @@
 02:05=W Hedgewars opieka zdrowotna naprawdę wymiata!
 02:05=Na zdrowie!
 02:05=Szczepionka!
+
 ; New ammo crate
 02:06=Więcej broni!
 02:06=Posiłki!
@@ -325,6 +333,7 @@
 02:06=Wyślij SMS na numer 7400 do wygrania zawartość zasobnika!
 02:06=Czy to ptak...? Czy to samolot...?
 02:06=Spadające gwiazdy nie spełniają życzeń, ale zasobniki jak najbardziej
+
 ; New utility crate
 02:07=Czas na narzędzia!
 02:07=To może się przydać...
@@ -343,6 +352,7 @@
 02:07=Zasobniki prosto z Ameryki!
 02:07=Zapasy materiałów eksploatacyjnych!
 02:07=Dorwij przeciwnika szybciej z nowymi narzędziami
+
 ; Hog (%1) skips his turn
 02:08=%1 jest taki nudny...
 02:08=%1 próbuje się skupić
@@ -394,6 +404,7 @@
 02:08=%1 ma wszystko w nosie
 02:08=%1 nie chce połamać sobie igieł
 02:08=%1 ma stracha
+
 ; Hog (%1) hurts himself only
 02:09=%1 powinien potrenować celowanie!
 02:09=%1 najwidoczniej nienawidzi samego siebie..
@@ -445,6 +456,7 @@
 02:09=%1 ma już dość tego świata
 02:09=%1 dostał łapówkę
 02:09=%1 przywalił, jak łysy czupryną o kant kuli
+
 ; Hog shot an home run (using the bat and another hog)
 02:10=Home Run!
 02:10=To ptak? To samolot?
@@ -455,6 +467,16 @@
 02:10=Niezły rzut!
 02:10=Chyba padnie rekord Guinessa w rzucie jeżem!
 02:10=To było odlotowe!
+
+; Hog (%1) has to leave (team is gone)
+02:11=%1 musi iść do łóżka!
+02:11=%1 wydaje się zbyt zajęty, by grać
+02:11=Zostałeś zajęty zamrozić dla jeża, %1
+02:11=Źłe gry przestała, albo nie działa.
+02:11=%1 awaria z gracza
+02:11=Belka go, Szkot!
+02:11=%1 musi odejść
+
 ; Weapon Categories
 03:00=Granat z zapalnikiem
 03:01=Granat z zapalnikiem
@@ -507,6 +529,10 @@
 03:48=Ała! Moja głowa...
 03:49=Powrót z zaświatów
 03:50=Krecia brygada
+03:51=Znalezione na ziemi
+03:52=UNUSED
+03:53=Typ 40
+03:54=Zbudować coś
 
 ; Weapon Descriptions (use | as line breaks)
 04:00=Atakuj przeciwników zwykłym granatem.|Wybuchnie kiedy zapalnik skończy odliczanie.|1-5: Ustawia zapalnik|Atak: Przytrzymaj by rzucić z większą siłą
@@ -560,7 +586,6 @@
 04:48=Czyż walenie jeży po głowach nie|jest zabawne? Dobre uderzenie|z młotka zabierze 1/3 życia|przeciwnika i wkopie go w podłoże|Atak: Uderz
 04:49=Wskrześ swoich przyjaciół!|Jednakże uważaj byś nie pomógł swojemu wrogowi.|Atak: Przytrzymaj by powoli przywracać życie|Góra: Przyspiesz wskrzeszanie
 
-
 ; Game goal strings
 05:00=Ustawienia gry
 05:01=Obowiązują następujące zasady:
@@ -583,3 +608,4 @@
 05:18=Tura nie kończy się po wykonaniu ataku
 05:19=Uzbrojenie zostaje przywrócone przy kolejnej turze
 05:20=Każdy z jeży ma oddzielne uzbrojenie
+05:21=Zespół Tag: Zespoły w klanie na kolejnych kolejkach|Wspólna Godzina: Drużyny w akcji raz z kolei klanu
--- a/share/hedgewars/Data/Locale/ru.txt	Fri Jun 17 18:03:12 2011 +0200
+++ b/share/hedgewars/Data/Locale/ru.txt	Mon Jun 20 20:43:11 2011 +0200
@@ -12,7 +12,7 @@
 00:09=Пистолет Desert Eagle
 00:10=Динамит
 00:11=Бейсбольная бита
-00:12=Неистовый удар
+00:12=Восходящий удар Дракона
 00:13=сек
 00:14=Парашют
 00:15=Воздушная атака
@@ -52,6 +52,10 @@
 00:49=Воскреситель
 00:50=Сверлящий удар
 00:51=Комок грязи
+00:52=Оружие не выбрано
+00:53=Машина времени и пространства
+00:54=Структура
+00:55=Земляной распылитель
 
 01:00=Вперёд к победе!
 01:01=Ничья
@@ -434,6 +438,10 @@
 03:48=Время Молота!
 03:49=Делает то, о чем ты подумал
 03:50=Большой любитель кротов
+03:51=Найденный на земле
+03:52=Не используется
+03:53=Модель 40
+03:54=Построй что нибудь
 
 ; Weapon Descriptions (use | as line breaks)
 04:00=Атакуй своих врагов обычной гранатой.|Она взорвется сразу, как только таймер|достигнет нуля.|1-5: Установить таймер гранаты|Атака: Удерживай для более дальнего броска
@@ -448,7 +456,7 @@
 04:09=Не уверен, что хорошо прицелился?|Используй пистолет Desert Eagle|с возможностью сделать до четырех|выстрелов за ход.|Атака: Выстрелить (несколько раз)
 04:10=Грубая сила всегда была в цене.|Брось эту классическую взрывчатку|возле своих врагов и убегай.|Атака: Бросить динамит рядом с собой
 04:11=Избавься от вражеских ежей с помощью|подачи битой, отправив их за край карты|или в воду. Или как насчет того, чтобы отправить ударом|одну из мин на карте в подарок своим друзьям?|Атака: Нанести удар по всему, что стоит перед тобой
-04:12=Стань лицом к лицу со своим врагом,|чтобы обрушить на него всю мощь|смертоносной техники боевых исскуств.|Атака: Исполнить Неистовый Удар
+04:12=Стань лицом к лицу со своим врагом,|чтобы обрушить на него всю мощь|смертоносной техники боевых исскуств.|Атака: Исполнить Восходящий удар Дракона
 04:13=Не используется
 04:14=Боишься высоты? Тогда возьми парашут.|Он раскроется, как только ты начнешь слишком|долго падать, и тем самым убережет ежа|от падения с большой высоты.|Атака: Раскрыть парашут|Длинный прыжок: Сбросить гранаты или похожее вооружение
 04:15=Вызови самолет, чтобы атаковать своих врагов|с помощью воздушной бомбардировки.|Влево/Вправо: Определить направление атаки|Курсор: Выбрать бомбардируемую область
@@ -467,7 +475,7 @@
 04:28=Через короткий промежуток времени после|запуска этой ракеты она начнет сверлить|твердую поверхность и взорвется как только|сработает ее плавкий предохранитель или|она высвободится на открытое пространство.|Атака: Удерживай для выстрела с большей силой
 04:29=Это штука - детям не игрушка!|Шаромет стреляет огромным количеством|маленьких шариков, заполненных взрывчаткой.|Атака: Выстрелить с максимальной силой|Вверх/Вниз: Продолжать прицельную стрельбу
 04:30=Вызови самолет для осуществления мощного|удара напалмом. При надлежащем прицеливании,|такая атака может нанести опустошительный урон|большим участкам поверхности, включая ежей,|которым не повезло оказаться не в то время,|не в том месте.|И еще... не забудь учесть направление и силу ветра.|Влево/Вправо: Определить направление атаки|Курсор: Выбрать область для удара напалмом
-04:31=Радиоуправляемый самолет - идеальное оружие,|чтобы пополнить коллекцию старых самолетов|или атаковать далеко стоящих ежей. Направь его|прямо на своих врагов или сбрось сперва несколько|бомб.|Атака: Запустить самолет или сбросить бомбы|Длинный прыжок: Исполнить 'Полет валькирий'|Вверх/Вниз: Направлять самолет в процессе полета
+04:31=Радиоуправляемый самолет - идеальное оружие,|чтобы пополнить коллекцию старых самолетов|или атаковать далеко стоящих ежей. Направь его|прямо на своих врагов или сбрось сперва несколько|бомб.|Атака: Запустить самолет или сбросить бомбы|Длинный прыжок: Исполнить 'Полет валькирий'|Вверх/Вниз: Управлять самолетом в процессе полета
 04:32=Слабая гравитация более эффективна, чем диета!|Прыгай выше и на более дальние дистанции или|позволь своим врагам улететь еще дальше.|Атака: Включить слабую гравитацию
 04:33=Иногда тебе нужно просто немного повысить|силу своего оружия, чтобы нанести сопернику|больший урон.|Атака: Включить дополнительный урон
 04:34=Не сможете меня задеть!|Атака: Включить неуязвимость
@@ -508,5 +516,6 @@
 05:17=Ежи ИИ возрождаются в момент гибели
 05:18=Неограниченное количество атак
 05:19=Оружие восстановится в конце хода
-05:20=Оружие не разделено между ежами
+05:20=Ежи не имеют общего оружия
+05:21=Признак команды: Команды в клане ходят последовательно|Общее время: Команды в клане имеют общее время хода
 
Binary file share/hwico.icns has changed