merge
authorunc0rr
Thu, 23 Jun 2011 21:19:43 +0400
changeset 5294 67278f1cba2c
parent 5247 bf6d4bc531d2 (current diff)
parent 5292 f9f75c5bc395 (diff)
child 5296 0bb518ad2da8
merge
hedgewars/uVariables.pas
hedgewars/uWorld.pas
share/hedgewars/Data/Graphics/Chunk.png
share/hedgewars/Data/Themes/Art/Clouds.png
share/hedgewars/Data/Themes/Art/Flake.png
share/hedgewars/Data/Themes/Blox/Flake.png
share/hedgewars/Data/Themes/Blox/Sky.png
share/hedgewars/Data/Themes/Blox/icon.png
share/hedgewars/Data/Themes/Blox/icon@2x.png
share/hedgewars/Data/Themes/Blox/plant1.png
share/hedgewars/Data/Themes/Blox/plant2.png
share/hedgewars/Data/Themes/Blox/plant3.png
share/hedgewars/Data/Themes/Blox/plant4.png
share/hedgewars/Data/Themes/Cake/Clouds.png
share/hedgewars/Data/Themes/Cake/icon.png
share/hedgewars/Data/Themes/Cake/icon@2x.png
share/hedgewars/Data/Themes/Cake/plant4.png
share/hedgewars/Data/Themes/Cheese/Flake.png
share/hedgewars/Data/Themes/CrazyMission/Flake.png
share/hedgewars/Data/Themes/CrazyMission/horizont.png
share/hedgewars/Data/Themes/Deepspace/Clouds.png
share/hedgewars/Data/Themes/Deepspace/horizont.png
share/hedgewars/Data/Themes/EarthRise/Clouds.png
share/hedgewars/Data/Themes/EarthRise/horizontL.png
share/hedgewars/Data/Themes/Planes/Flake.png
share/hedgewars/Data/Themes/themes.cfg
--- a/.hgignore	Tue Jun 21 16:43:05 2011 +0400
+++ b/.hgignore	Thu Jun 23 21:19:43 2011 +0400
@@ -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	Tue Jun 21 16:43:05 2011 +0400
+++ b/QTfrontend/CMakeLists.txt	Thu Jun 23 21:19:43 2011 +0400
@@ -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
@@ -111,6 +114,7 @@
     qaspectratiolayout.cpp
     drawmapwidget.cpp
     drawmapscene.cpp
+    themesmodel.cpp
     )
 
 #xfire integration
@@ -130,6 +134,7 @@
 endif(MINGW)
 
 set(hwfr_moc_hdrs
+    HWApplication.h
     game.h
     hats.h
     hwform.h
@@ -149,6 +154,7 @@
     pageoptions.h
     pagemain.h
     pageinfo.h
+    pagedata.h
     pagesingleplayer.h
     pagenettype.h
     pageconnecting.h
@@ -190,6 +196,7 @@
     qaspectratiolayout.h
     drawmapwidget.h
     drawmapscene.h
+    themesmodel.h
     )
 
 set(hwfr_hdrs
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/QTfrontend/HWApplication.cpp	Thu Jun 23 21:19:43 2011 +0400
@@ -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	Thu Jun 23 21:19:43 2011 +0400
@@ -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	Tue Jun 21 16:43:05 2011 +0400
+++ b/QTfrontend/SDLs.cpp	Thu Jun 23 21:19:43 2011 +0400
@@ -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	Tue Jun 21 16:43:05 2011 +0400
+++ b/QTfrontend/chatwidget.cpp	Thu Jun 23 21:19:43 2011 +0400
@@ -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	Tue Jun 21 16:43:05 2011 +0400
+++ b/QTfrontend/chatwidget.h	Thu Jun 23 21:19:43 2011 +0400
@@ -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	Tue Jun 21 16:43:05 2011 +0400
+++ b/QTfrontend/drawmapwidget.cpp	Thu Jun 23 21:19:43 2011 +0400
@@ -18,6 +18,7 @@
 
 #include <QFile>
 #include <QMessageBox>
+#include <QEvent>
 
 #include "drawmapwidget.h"
 
--- a/QTfrontend/drawmapwidget.h	Tue Jun 21 16:43:05 2011 +0400
+++ b/QTfrontend/drawmapwidget.h	Thu Jun 23 21:19:43 2011 +0400
@@ -23,7 +23,6 @@
 #include <QHBoxLayout>
 #include <QPushButton>
 #include <QGraphicsView>
-#include <QApplication>
 
 #include "qaspectratiolayout.h"
 #include "drawmapscene.h"
--- a/QTfrontend/game.cpp	Tue Jun 21 16:43:05 2011 +0400
+++ b/QTfrontend/game.cpp	Thu Jun 23 21:19:43 2011 +0400
@@ -20,6 +20,7 @@
 #include <QByteArray>
 #include <QUuid>
 #include <QColor>
+#include <QStringListModel>
 
 #include "game.h"
 #include "hwconsts.h"
@@ -110,7 +111,7 @@
 
     HWProto::addStringToBuffer(teamscfg, "TL");
     HWProto::addStringToBuffer(teamscfg, QString("etheme %1")
-            .arg((Themes->size() > 0) ? Themes->at(rand() % Themes->size()) : "steel"));
+            .arg((themesModel->rowCount() > 0) ? themesModel->index(rand() % themesModel->rowCount()).data().toString() : "steel"));
     HWProto::addStringToBuffer(teamscfg, "eseed " + QUuid::createUuid().toString());
 
     HWNamegen namegen;
--- a/QTfrontend/gameuiconfig.cpp	Tue Jun 21 16:43:05 2011 +0400
+++ b/QTfrontend/gameuiconfig.cpp	Thu Jun 23 21:19:43 2011 +0400
@@ -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	Tue Jun 21 16:43:05 2011 +0400
+++ b/QTfrontend/gameuiconfig.h	Thu Jun 23 21:19:43 2011 +0400
@@ -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/hwconsts.cpp.in	Tue Jun 21 16:43:05 2011 +0400
+++ b/QTfrontend/hwconsts.cpp.in	Thu Jun 23 21:19:43 2011 +0400
@@ -27,7 +27,7 @@
 QDir * cfgdir = new QDir();
 QDir * datadir = new QDir();
 
-QStringList * Themes;
+ThemesModel * themesModel;
 QStringList * mapList;
 QStringList * scriptList;
 
--- a/QTfrontend/hwconsts.h	Tue Jun 21 16:43:05 2011 +0400
+++ b/QTfrontend/hwconsts.h	Thu Jun 23 21:19:43 2011 +0400
@@ -22,6 +22,8 @@
 #include <QStringList>
 #include <QPair>
 
+#include "themesmodel.h"
+
 extern QString * cProtoVer;
 extern QString * cVersionString;
 extern QString * cDataDir;
@@ -37,7 +39,9 @@
 extern int cMaxTeams;
 extern int cMinServerVersion;
 
-extern QStringList * Themes;
+class QStringListModel;
+
+extern ThemesModel * themesModel;
 extern QStringList * mapList;
 extern QStringList * scriptList;
 
--- a/QTfrontend/hwform.cpp	Tue Jun 21 16:43:05 2011 +0400
+++ b/QTfrontend/hwform.cpp	Thu Jun 23 21:19:43 2011 +0400
@@ -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	Tue Jun 21 16:43:05 2011 +0400
+++ b/QTfrontend/hwform.h	Thu Jun 23 21:19:43 2011 +0400
@@ -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	Tue Jun 21 16:43:05 2011 +0400
+++ b/QTfrontend/main.cpp	Thu Jun 23 21:19:43 2011 +0400
@@ -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>
@@ -24,6 +25,7 @@
 #include <QRegExp>
 #include <QMap>
 #include <QSettings>
+#include <QStringListModel>
 
 #include "hwform.h"
 #include "hwconsts.h"
@@ -51,7 +53,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();
@@ -383,24 +385,52 @@
         return 1;
     }
 
-    Themes = new QStringList();
-    QFile userthemesfile(cfgdir->absolutePath() + "/Data/Themes/themes.cfg");
-    if (userthemesfile.open(QIODevice::ReadOnly)) {
-        QTextStream stream(&userthemesfile);
-        while (!stream.atEnd()) Themes->append(stream.readLine());
-        userthemesfile.close();
-    }
-    QFile themesfile(datadir->absolutePath() + "/Themes/themes.cfg");
-    QString str;
-    if (themesfile.open(QIODevice::ReadOnly)) {
-        QTextStream stream(&themesfile);
-        while (!stream.atEnd()) {
-            str = stream.readLine();
-            if (!Themes->contains(str)) Themes->append(str);
+    {
+        QDir dir;
+        dir.setPath(cfgdir->absolutePath() + "/Data/Themes");
+
+        QStringList themes;
+        themes.append(dir.entryList(QDir::AllDirs | QDir::NoDotAndDotDot));
+
+        dir.setPath(datadir->absolutePath() + "/Themes");
+        themes.append(dir.entryList(QDir::AllDirs | QDir::NoDotAndDotDot));
+
+        QList<QPair<QIcon, QIcon> > icons;
+
+        for(int i = themes.size() - 1; i >= 0; --i)
+        {
+            QFile tmpfile;
+            tmpfile.setFileName(QString("%1/Data/Themes/%2/icon.png").arg(cfgdir->absolutePath()).arg(themes.at(i)));
+            if (!tmpfile.exists())
+            {
+                tmpfile.setFileName(QString("%1/Themes/%2/icon.png").arg(datadir->absolutePath()).arg(themes.at(i)));
+                if(tmpfile.exists())
+                { // load icon
+                    QPair<QIcon, QIcon> ic;
+                    ic.first = QIcon(QFileInfo(tmpfile).absoluteFilePath());
+
+                    QFile previewIconFile;
+                    previewIconFile.setFileName(QString("%1/Data/Themes/%2/icon@2x.png").arg(cfgdir->absolutePath()).arg(themes.at(i)));
+                    if (previewIconFile.exists()) ic.second = QIcon(QFileInfo(previewIconFile).absoluteFilePath());
+                    else ic.second = QIcon(QString("%1/Themes/%2/icon@2x.png").arg(datadir->absolutePath()).arg(themes.at(i)));
+
+                    icons.prepend(ic);
+                }
+                else
+                {
+                    themes.removeAt(i);
+                }
+            }
         }
-        themesfile.close();
-    } else {
-        QMessageBox::critical(0, "Error", "Cannot access themes.cfg", "OK");
+
+        themesModel = new ThemesModel(themes);
+        for(int i = 0; i < icons.size(); ++i)
+        {
+            themesModel->setData(themesModel->index(i), icons[i].first, Qt::DecorationRole);
+            themesModel->setData(themesModel->index(i), icons[i].second, Qt::UserRole);
+
+            qDebug() << "icon test" << themesModel->index(i).data(Qt::UserRole).toString();
+        }
     }
 
     QDir tmpdir;
@@ -431,8 +461,8 @@
     QTranslator Translator;
     {
         QSettings settings(cfgdir->absolutePath() + "/hedgewars.ini", QSettings::IniFormat);
-        QString cc = settings.value("misc/locale", "").toString();
-        if(!cc.compare(""))
+        QString cc = settings.value("misc/locale", QString()).toString();
+        if(cc.isEmpty())
             cc = QLocale::system().name();
         QFile tmpfile;
         tmpfile.setFileName(cfgdir->absolutePath() + "Data/Locale/hedgewars_" + cc);
@@ -455,8 +485,8 @@
     CocoaInitializer initializer;
 #endif
 
-    HWForm *Form = new HWForm();
+    app.form = new HWForm();
 
-    Form->show();
+    app.form->show();
     return app.exec();
 }
--- a/QTfrontend/mapContainer.cpp	Tue Jun 21 16:43:05 2011 +0400
+++ b/QTfrontend/mapContainer.cpp	Thu Jun 23 21:19:43 2011 +0400
@@ -24,17 +24,18 @@
 #include <QLinearGradient>
 #include <QColor>
 #include <QTextStream>
-#include <QApplication>
 #include <QLabel>
-#include <QListWidget>
+#include <QListView>
 #include <QVBoxLayout>
 #include <QIcon>
 #include <QLineEdit>
 #include <QMessageBox>
+#include <QStringListModel>
 
 #include "hwconsts.h"
 #include "mapContainer.h"
 #include "igbox.h"
+#include "HWApplication.h"
 
 HWMapContainer::HWMapContainer(QWidget * parent) :
     QWidget(parent),
@@ -46,10 +47,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);
@@ -200,24 +201,18 @@
     QVBoxLayout * gbTLayout = new QVBoxLayout(gbThemes);
     gbTLayout->setContentsMargins(0, 0, 0 ,0);
     gbTLayout->setSpacing(0);
-    lwThemes = new QListWidget(mapWidget);
-    lwThemes->setMinimumHeight(30);
-    lwThemes->setFixedWidth(140);
-    QFile tmpfile;
-    for (int i = 0; i < Themes->size(); ++i) {
-        QListWidgetItem * lwi = new QListWidgetItem();
-        lwi->setText(Themes->at(i));
-        tmpfile.setFileName(QString("%1/Data/Themes/%2/icon.png").arg(cfgdir->absolutePath()).arg(Themes->at(i)));
-        if (tmpfile.exists()) lwi->setIcon(QIcon(QFileInfo(tmpfile).absoluteFilePath()));
-        else lwi->setIcon(QIcon(QString("%1/Themes/%2/icon.png").arg(datadir->absolutePath()).arg(Themes->at(i))));
-        //lwi->setTextAlignment(Qt::AlignHCenter);
-        lwThemes->addItem(lwi);
-    }
-    connect(lwThemes, SIGNAL(currentRowChanged(int)), this, SLOT(themeSelected(int)));
+    lvThemes = new QListView(mapWidget);
+    lvThemes->setMinimumHeight(30);
+    lvThemes->setFixedWidth(140);
+    lvThemes->setModel(themesModel);
+    lvThemes->setIconSize(QSize(16, 16));
+    lvThemes->setEditTriggers(QListView::NoEditTriggers);
+
+    connect(lvThemes->selectionModel(), SIGNAL(currentRowChanged( const QModelIndex &, const QModelIndex &)), this, SLOT(themeSelected( const QModelIndex &, const QModelIndex &)));
 
     // override default style to tighten up theme scroller
-    lwThemes->setStyleSheet(QString(
-        "QListWidget{"
+    lvThemes->setStyleSheet(QString(
+        "QListView{"
             "border: solid;"
             "border-width: 0px;"
             "border-radius: 0px;"
@@ -229,8 +224,8 @@
         )
     );
 
-    gbTLayout->addWidget(lwThemes);
-    lwThemes->setSizePolicy(QSizePolicy::Maximum, QSizePolicy::Minimum);
+    gbTLayout->addWidget(lvThemes);
+    lvThemes->setSizePolicy(QSizePolicy::Maximum, QSizePolicy::Minimum);
 
     mapLayout->setSizeConstraint(QLayout::SetFixedSize);
 
@@ -376,9 +371,9 @@
             );
 }
 
-void HWMapContainer::themeSelected(int currentRow)
+void HWMapContainer::themeSelected(const QModelIndex & current, const QModelIndex &)
 {
-    QString theme = Themes->at(currentRow);
+    QString theme = current.data().toString();
     QList<QVariant> mapInfo;
     mapInfo.push_back(QString("+rnd+"));
     mapInfo.push_back(theme);
@@ -389,10 +384,8 @@
     chooseMap->setItemData(1, mapInfo);
     mapInfo[0] = QString("+drawn+");
     chooseMap->setItemData(2, mapInfo);
-    QFile tmpfile;
-    tmpfile.setFileName(QString("%1/Data/Themes/%2/icon@2x.png").arg(cfgdir->absolutePath()).arg(theme));
-    if (tmpfile.exists()) gbThemes->setIcon(QIcon(QFileInfo(tmpfile).absoluteFilePath()));
-    else gbThemes->setIcon(QIcon(QString("%1/Themes/%2/icon@2x.png").arg(datadir->absolutePath()).arg(theme)));
+
+    gbThemes->setIcon(qVariantValue<QIcon>(current.data(Qt::UserRole)));
     emit themeChanged(theme);
 }
 
@@ -487,9 +480,10 @@
 
 void HWMapContainer::setTheme(const QString & theme)
 {
-    QList<QListWidgetItem *> items = lwThemes->findItems(theme, Qt::MatchExactly);
-    if(items.size())
-        lwThemes->setCurrentItem(items.at(0));
+    QModelIndexList mdl = themesModel->match(themesModel->index(0), Qt::DisplayRole, theme);
+
+    if(mdl.size())
+        lvThemes->setCurrentIndex(mdl.at(0));
 }
 
 void HWMapContainer::setRandomMap()
@@ -539,9 +533,9 @@
 
 void HWMapContainer::setRandomTheme()
 {
-    if(!Themes->size()) return;
-    quint32 themeNum = rand() % Themes->size();
-    lwThemes->setCurrentRow(themeNum);
+    if(!themesModel->rowCount()) return;
+    quint32 themeNum = rand() % themesModel->rowCount();
+    lvThemes->setCurrentIndex(themesModel->index(themeNum));
 }
 
 void HWMapContainer::intSetTemplateFilter(int filter)
--- a/QTfrontend/mapContainer.h	Tue Jun 21 16:43:05 2011 +0400
+++ b/QTfrontend/mapContainer.h	Thu Jun 23 21:19:43 2011 +0400
@@ -32,7 +32,7 @@
 
 class QPushButton;
 class IconedGroupBox;
-class QListWidget;
+class QListView;
 
 class MapFileErrorException
 {
@@ -89,7 +89,7 @@
   void setRandomMap();
   void setRandomStatic();
   void setRandomMission();
-  void themeSelected(int currentRow);
+  void themeSelected(const QModelIndex & current, const QModelIndex &);
   void addInfoToPreview(QPixmap image);
   void seedEdited();
 
@@ -101,7 +101,7 @@
   QPushButton* imageButt;
   QComboBox* chooseMap;
   IconedGroupBox* gbThemes;
-  QListWidget* lwThemes;
+  QListView* lvThemes;
   HWMap* pMap;
   QString m_seed;
   QPushButton* seedSet;
--- a/QTfrontend/namegen.cpp	Tue Jun 21 16:43:05 2011 +0400
+++ b/QTfrontend/namegen.cpp	Thu Jun 23 21:19:43 2011 +0400
@@ -19,7 +19,6 @@
 
 #include <QFile>
 #include <QTextStream>
-#include <QApplication>
 #include <QStringList>
 #include <QLineEdit>
 #include "namegen.h"
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/QTfrontend/pagedata.cpp	Thu Jun 23 21:19:43 2011 +0400
@@ -0,0 +1,36 @@
+/*
+ * Hedgewars, a free turn based strategy game
+ * Copyright (c) 2006-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 <QGridLayout>
+#include <QPushButton>
+
+#include "pagedata.h"
+
+PageDataDownload::PageDataDownload(QWidget* parent) : AbstractPage(parent)
+{
+    QGridLayout * pageLayout = new QGridLayout(this);
+    pageLayout->setColumnStretch(0, 1);
+    pageLayout->setColumnStretch(1, 1);
+    pageLayout->setColumnStretch(2, 1);
+
+    BtnBack = addButton(":/res/Exit.png", pageLayout, 1, 0, true);
+
+    web = new QWebView(this);
+    web->load(QUrl("http://m8y.org/hw/"));
+    pageLayout->addWidget(web, 0, 0, 1, 3);
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/QTfrontend/pagedata.h	Thu Jun 23 21:19:43 2011 +0400
@@ -0,0 +1,35 @@
+/*
+ * Hedgewars, a free turn based strategy game
+ * Copyright (c) 2006-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 PAGE_DATA_H
+#define PAGE_DATA_H
+#include <QWebView>
+#include "AbstractPage.h"
+
+class PageDataDownload : public AbstractPage
+{
+    Q_OBJECT
+
+public:
+    PageDataDownload(QWidget* parent = 0);
+
+    QPushButton *BtnBack;
+    QWebView *web;
+};
+
+#endif
--- a/QTfrontend/pageeditteam.cpp	Tue Jun 21 16:43:05 2011 +0400
+++ b/QTfrontend/pageeditteam.cpp	Thu Jun 23 21:19:43 2011 +0400
@@ -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	Tue Jun 21 16:43:05 2011 +0400
+++ b/QTfrontend/pageoptions.cpp	Thu Jun 23 21:19:43 2011 +0400
@@ -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	Tue Jun 21 16:43:05 2011 +0400
+++ b/QTfrontend/pageroomslist.cpp	Thu Jun 23 21:19:43 2011 +0400
@@ -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	Tue Jun 21 16:43:05 2011 +0400
+++ b/QTfrontend/pageroomslist.h	Thu Jun 23 21:19:43 2011 +0400
@@ -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	Tue Jun 21 16:43:05 2011 +0400
+++ b/QTfrontend/team.cpp	Thu Jun 23 21:19:43 2011 +0400
@@ -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"
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/QTfrontend/themesmodel.cpp	Thu Jun 23 21:19:43 2011 +0400
@@ -0,0 +1,47 @@
+
+#include "themesmodel.h"
+
+ThemesModel::ThemesModel(QStringList themes, QObject *parent) :
+    QAbstractListModel(parent)
+{
+    m_data.reserve(themes.size());
+
+    foreach(QString theme, themes)
+    {
+        m_data.append(QHash<int, QVariant>());
+        m_data.last().insert(Qt::DisplayRole, theme);
+    }
+}
+
+int ThemesModel::rowCount(const QModelIndex &parent) const
+{
+    if(parent.isValid())
+        return 0;
+    else
+        return m_data.size();
+}
+
+QVariant ThemesModel::data(const QModelIndex &index, int role) const
+{
+    if(index.column() > 0 || index.row() >= m_data.size())
+        return QVariant();
+    else
+        return m_data.at(index.row()).value(role);
+}
+
+bool ThemesModel::setData(const QModelIndex &index, const QVariant &value, int role)
+{
+    if(index.column() > 0 || index.row() >= m_data.size())
+        return false;
+    else
+    {
+        m_data[index.row()].insert(role, value);
+
+        return true;
+    }
+
+}
+
+
+
+
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/QTfrontend/themesmodel.h	Thu Jun 23 21:19:43 2011 +0400
@@ -0,0 +1,28 @@
+#ifndef THEMESMODEL_H
+#define THEMESMODEL_H
+
+#include <QAbstractListModel>
+#include <QStringList>
+#include <QHash>
+
+class ThemesModel : public QAbstractListModel
+{
+    Q_OBJECT
+public:
+    explicit ThemesModel(QStringList themes, QObject *parent = 0);
+
+    int rowCount(const QModelIndex &parent = QModelIndex()) const;
+    QVariant data(const QModelIndex &index, int role) const;
+    bool setData(const QModelIndex &index, const QVariant &value,
+                 int role = Qt::EditRole);
+
+signals:
+
+public slots:
+
+private:
+
+    QList<QHash<int, QVariant> > m_data;
+};
+
+#endif // THEMESMODEL_H
--- a/QTfrontend/ui_hwform.h	Tue Jun 21 16:43:05 2011 +0400
+++ b/QTfrontend/ui_hwform.h	Thu Jun 23 21:19:43 2011 +0400
@@ -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	Tue Jun 21 16:43:05 2011 +0400
+++ b/gameServer/Utils.hs	Thu Jun 23 21:19:43 2011 +0400
@@ -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/GSHandlers.inc	Tue Jun 21 16:43:05 2011 +0400
+++ b/hedgewars/GSHandlers.inc	Thu Jun 23 21:19:43 2011 +0400
@@ -4813,89 +4813,52 @@
     x, y: LongInt;
     hog: PHedgehog;
 begin
-    if (Gear^.Hedgehog <> nil) and (Gear^.Tag = TotalRounds) then
+    if CurAmmoGear = Gear then
         begin
-            hog:= Gear^.Hedgehog;
-            hog^.Gear:= hog^.GearHidden;
-            hog^.Gear^.X:= Gear^.X;
-            hog^.Gear^.Y:= Gear^.Y - Int2hwFloat(Gear^.Radius);
-            hog^.Gear^.Active:= false;
-            hog^.Gear^.State:= hog^.Gear^.State And not gstHHdriven;
-            InsertGearToList(hog^.Gear);
-            hog^.GearHidden:= nil;
-            Gear^.Hedgehog:= nil;
+        if (CurrentHedgehog = nil) or (CurrentHedgehog^.Gear = nil) then 
+            begin
+            DeleteGear(Gear);
+            exit
+            end;
+        if Gear = CurAmmoGear then CurAmmoGear := nil;
+        Gear^.Hedgehog:= CurrentHedgehog;
+        RemoveGearFromList(CurrentHedgehog^.Gear);
+        CurrentHedgehog^.Gear^.Z := cHHZ;
+        CurrentHedgehog^.Gear^.Active := false;
+        CurrentHedgehog^.Gear^.State:= CurrentHedgehog^.Gear^.State and not gstHHDriven;
+        CurrentHedgehog^.GearHidden:= CurrentHedgehog^.Gear;
+        CurrentHedgehog^.Gear:= nil;
+        Gear^.Tag:= TotalRounds + Gear^.Tag;
+        AddGearCI(Gear);
         end;
 
     dec(Gear^.Health, Gear^.Damage);
     Gear^.Damage := 0;
-
-    if Gear^.Health <= 0 then
-    begin
-        if Gear^.Hedgehog <> nil then
+        
+    if (Gear^.Tag = TotalRounds) or (Gear^.Health <= 0) then
         begin
-            hog:= Gear^.Hedgehog;
-            hog^.Gear:= hog^.GearHidden;
-            hog^.Gear^.X:= Gear^.X;
-            hog^.Gear^.Y:= Gear^.Y;
-            InsertGearToList(hog^.Gear);
-            hog^.GearHidden:= nil;
+        if Gear^.Hedgehog <> nil then
+            begin
+            Gear^.Hedgehog^.Gear:= Gear^.Hedgehog^.GearHidden;
+            Gear^.Hedgehog^.GearHidden:= nil;
+            Gear^.Hedgehog^.Gear^.X:= Gear^.X;
+            Gear^.Hedgehog^.Gear^.Y:= Gear^.Y - int2hwFloat(Gear^.Radius + cHHRadius);
+            InsertGearToList(Gear^.Hedgehog^.Gear);
             Gear^.Hedgehog:= nil;
+            SetAllHHToActive;
+            end;
         end;
-
+        
+    if Gear^.Health <= 0 then
+        begin
         x := hwRound(Gear^.X);
         y := hwRound(Gear^.Y);
 
+        DeleteCI(Gear);
         DeleteGear(Gear);
 
         doMakeExplosion(x, y, 50, CurrentHedgehog, EXPLAutoSound);
-    end;
-end;
-
-procedure doStepPlaceStructure(Gear: PGear);
-var 
-    hog: PHedgehog;
-    HHGear: PGear;
-    x, y, tx, ty: hwFloat;
-begin
-    AllInactive := false;
-
-    HHGear := Gear^.Hedgehog^.Gear;
-    tx := int2hwFloat(TargetPoint.X);
-    ty := int2hwFloat(TargetPoint.Y);
-    x := HHGear^.X;
-    y := HHGear^.Y;
-
-    HHGear := Gear^.Hedgehog^.Gear;
-    if (Distance(tx - x, ty - y) > _256) or
-       not TryPlaceOnLand(TargetPoint.X - SpritesData[sprHHTelepMask].Width div 2,
-       TargetPoint.Y - SpritesData[sprHHTelepMask].Height div 2,
-       sprHHTelepMask, 0, false, false) then
-        begin
-        HHGear^.Message := HHGear^.Message and not gmAttack;
-        HHGear^.State := HHGear^.State and not gstAttacking;
-        HHGear^.State := HHGear^.State or gstHHChooseTarget;
-        DeleteGear(Gear);
-        isCursorVisible := true;
-        PlaySound(sndDenied)
-        end
-    else
-        begin
-        DeleteCI(HHGear);
-        SetAllHHToActive;
-        PlaySound(sndPlaced);
-        CurAmmoGear:= nil;
-        AfterAttack;
-        Gear^.X := tx;
-        Gear^.Y := ty;
-        Gear^.Tag := TotalRounds + Gear^.Tag;
-        hog:= CurrentHedgehog;
-        hog^.GearHidden:= hog^.Gear;
-        RemoveGearFromList(hog^.Gear);
-        hog^.Gear:= nil;
-        Gear^.Hedgehog := hog;
-        Gear^.doStep := @doStepStructure;
         end;
-    TargetPoint.X := NoPointX;
 end;
 
 procedure doStepTardis(Gear: PGear);
--- a/hedgewars/HHHandlers.inc	Tue Jun 21 16:43:05 2011 +0400
+++ b/hedgewars/HHHandlers.inc	Thu Jun 23 21:19:43 2011 +0400
@@ -316,7 +316,7 @@
                     end;
                    amDrillStrike: AddGear(CurWeapon^.Pos, 0, gtAirAttack, 3, _0, _0, CurWeapon^.Timer);
                    //amMelonStrike: AddGear(CurWeapon^.Pos, 0, gtAirAttack, 4, _0, _0, 0);
-                     amStructure: CurAmmoGear:= AddGear(hwRound(X), hwRound(Y), gtStructure, 0, _0, _0, 0);
+                     amStructure: CurAmmoGear:= AddGear(hwRound(lx) + hwSign(dX) * 7, hwRound(ly), gtStructure, gstWait, SignAs(_0_02, dX), _0, 3000);
                         amTardis: CurAmmoGear:= AddGear(hwRound(X), hwRound(Y), gtTardis, 0, _0, _0, 5000);
                   end;
 
@@ -380,7 +380,7 @@
         else
             begin
             OnUsedAmmo(CurrentHedgehog^);
-            if ((Ammoz[a].Ammo.Propz and ammoprop_NoRoundEnd) = 0) and ((GameFlags and gfInfAttack) = 0) then
+            if ((Ammoz[a].Ammo.Propz and ammoprop_NoRoundEnd) = 0) and (((GameFlags and gfInfAttack) = 0) or PlacingHogs) then
                 begin
                 if TagTurnTimeLeft = 0 then TagTurnTimeLeft:= TurnTimeLeft;
                 TurnTimeLeft:=(Ammoz[a].TimeAfterTurn * cGetAwayTime) div 100;
--- a/hedgewars/options.inc	Tue Jun 21 16:43:05 2011 +0400
+++ b/hedgewars/options.inc	Thu Jun 23 21:19:43 2011 +0400
@@ -34,11 +34,8 @@
   {$DEFINE GLunit:=gles11}
 {$ENDIF}
 
-{$IFNDEF DARWIN}
-  {$DEFINE DEBUGFILE}
-  {  $DEFINE DUMP}
-  {  $DEFINE TRACEAIACTIONS}
-  {  $DEFINE COUNTTICKS}
-{$ENDIF}
+{$DEFINE DEBUGFILE}
+//{$DEFINE TRACEAIACTIONS}
+//{$DEFINE COUNTTICKS}
 
 //also available LUA_DISABLED
--- a/hedgewars/uAmmos.pas	Tue Jun 21 16:43:05 2011 +0400
+++ b/hedgewars/uAmmos.pas	Thu Jun 23 21:19:43 2011 +0400
@@ -32,6 +32,7 @@
 procedure SetAmmoReinforcement(s: shortstring);
 procedure AssignStores;
 procedure AddAmmo(var Hedgehog: THedgehog; ammo: TAmmoType);
+procedure AddAmmo(var Hedgehog: THedgehog; ammo: TAmmoType; cnt: LongWord);
 function  HHHasAmmo(var Hedgehog: THedgehog; Ammo: TAmmoType): boolean;
 procedure PackAmmo(Ammo: PHHAmmo; Slot: LongInt);
 procedure OnUsedAmmo(var Hedgehog: THedgehog);
@@ -43,6 +44,7 @@
 procedure ResetWeapons;
 function  GetAmmoByNum(num: Longword): PHHAmmo;
 function  GetAmmoEntry(var Hedgehog: THedgehog): PAmmo;
+function  GetAmmoEntry(var Hedgehog: THedgehog; am: TAmmoType): PAmmo;
 
 var StoreCnt: Longword;
 
@@ -139,13 +141,18 @@
 end;
 
 function GetAmmoEntry(var Hedgehog: THedgehog): PAmmo;
+begin
+GetAmmoEntry:= GetAmmoEntry(Hedgehog, Hedgehog.CurAmmoType)
+end;
+
+function GetAmmoEntry(var Hedgehog: THedgehog; am: TAmmoType): PAmmo;
 var ammoidx, slot: LongWord;
 begin
 with Hedgehog do
     begin
-    slot:= Ammoz[CurAmmoType].Slot;
+    slot:= Ammoz[am].Slot;
     ammoidx:= 0;
-    while (ammoidx < cMaxSlotAmmoIndex) and (Ammo^[slot, ammoidx].AmmoType <> CurAmmoType) do inc(ammoidx);
+    while (ammoidx < cMaxSlotAmmoIndex) and (Ammo^[slot, ammoidx].AmmoType <> am) do inc(ammoidx);
     GetAmmoEntry:= @Ammo^[slot, ammoidx];
     end
 end;
@@ -170,6 +177,17 @@
 end;
 
 procedure AddAmmo(var Hedgehog: THedgehog; ammo: TAmmoType);
+var cnt: LongWord;
+begin
+cnt:= GetAmmoEntry(Hedgehog, ammo)^.Count;
+if cnt <> AMMO_INFINITE then
+    begin
+    inc(cnt, Ammoz[ammo].NumberInCase);
+    AddAmmo(Hedgehog, ammo, cnt)
+    end
+end;
+
+procedure AddAmmo(var Hedgehog: THedgehog; ammo: TAmmoType; cnt: LongWord);
 var ammos: TAmmoCounts;
     slot, ami: LongInt;
     hhammo: PHHAmmo;
@@ -184,11 +202,8 @@
         if hhammo^[slot, ami].Count > 0 then
            ammos[hhammo^[slot, ami].AmmoType]:= hhammo^[slot, ami].Count;
 
-if ammos[ammo] <> AMMO_INFINITE then
-   begin
-   inc(ammos[ammo], Ammoz[ammo].NumberInCase);
-   if ammos[ammo] > AMMO_INFINITE then ammos[ammo]:= AMMO_INFINITE
-   end;
+ammos[ammo]:= cnt;
+if ammos[ammo] > AMMO_INFINITE then ammos[ammo]:= AMMO_INFINITE;
 
 FillAmmoStore(hhammo, ammos)
 end;
--- a/hedgewars/uCollisions.pas	Tue Jun 21 16:43:05 2011 +0400
+++ b/hedgewars/uCollisions.pas	Thu Jun 23 21:19:43 2011 +0400
@@ -22,7 +22,7 @@
 interface
 uses uFloat, uTypes;
 
-const cMaxGearArrayInd = 255;
+const cMaxGearArrayInd = 1023;
 
 type PGearArray = ^TGearArray;
     TGearArray = record
--- a/hedgewars/uGears.pas	Tue Jun 21 16:43:05 2011 +0400
+++ b/hedgewars/uGears.pas	Thu Jun 23 21:19:43 2011 +0400
@@ -147,7 +147,7 @@
             @doStepNapalmBomb,
             @doStepSnowball,
             @doStepSnowflake,
-            @doStepPlaceStructure,
+            @doStepStructure,
             @doStepLandGun,
             @doStepTardis);
 
@@ -1292,7 +1292,7 @@
     if (GameFlags and gfSolidLand) = 0 then
         begin
         cnt:= DrawExplosion(X, Y, Radius) div 1608; // approx 2 16x16 circles to erase per chunk
-        if cnt > 0 then
+        if (cnt > 0) and (SpritesData[sprChunk].Texture <> nil) then
             for i:= 0 to cnt do
                 AddVisualGear(X, Y, vgtChunk)
         end;
--- a/hedgewars/uLand.pas	Tue Jun 21 16:43:05 2011 +0400
+++ b/hedgewars/uLand.pas	Thu Jun 23 21:19:43 2011 +0400
@@ -1062,35 +1062,40 @@
 
     LandSurface2LandPixels(tmpsurf);
     SDL_FreeSurface(tmpsurf);
-    if (cReducedQuality and rqBlurryLand) = 0 then
-        for x:= leftX+2 to rightX-2 do
-            for y:= topY+2 to LAND_HEIGHT-3 do
-                if (Land[y, x] = 0) and 
-                   (((Land[y, x-1] = lfBasic) and ((Land[y+1,x] = lfBasic)) or (Land[y-1,x] = lfBasic)) or
-                   ((Land[y, x+1] = lfBasic) and ((Land[y-1,x] = lfBasic) or (Land[y+1,x] = lfBasic)))) then
-                begin
+    for x:= leftX+2 to rightX-2 do
+        for y:= topY+2 to LAND_HEIGHT-3 do
+            if (Land[y, x] = 0) and 
+               (((Land[y, x-1] = lfBasic) and ((Land[y+1,x] = lfBasic)) or (Land[y-1,x] = lfBasic)) or
+               ((Land[y, x+1] = lfBasic) and ((Land[y-1,x] = lfBasic) or (Land[y+1,x] = lfBasic)))) then
+            begin
+                if (cReducedQuality and rqBlurryLand) = 0 then
+                    begin
                     if Land[y, x-1] = lfBasic then LandPixels[y, x]:= LandPixels[y, x-1]
                     else if Land[y, x+1] = lfBasic then LandPixels[y, x]:= LandPixels[y, x+1];
-                    LandPixels[y,x]:= (LandPixels[y,x] and not AMask) or (128 shl AShift);
-                    Land[y,x]:= lfObject
-                end
-                else if (Land[y, x] = 0) and
-                        (((Land[y, x-1] = lfBasic) and (Land[y+1,x-1] = lfBasic) and (Land[y+2,x] = lfBasic)) or
-                        ((Land[y, x-1] = lfBasic) and (Land[y-1,x-1] = lfBasic) and (Land[y-2,x] = lfBasic)) or
-                        ((Land[y, x+1] = lfBasic) and (Land[y+1,x+1] = lfBasic) and (Land[y+2,x] = lfBasic)) or
-                        ((Land[y, x+1] = lfBasic) and (Land[y-1,x+1] = lfBasic) and (Land[y-2,x] = lfBasic)) or
-                        ((Land[y+1, x] = lfBasic) and (Land[y+1,x+1] = lfBasic) and (Land[y,x+2] = lfBasic)) or
-                        ((Land[y-1, x] = lfBasic) and (Land[y-1,x+1] = lfBasic) and (Land[y,x+2] = lfBasic)) or
-                        ((Land[y+1, x] = lfBasic) and (Land[y+1,x-1] = lfBasic) and (Land[y,x-2] = lfBasic)) or
-                        ((Land[y-1, x] = lfBasic) and (Land[y-1,x-1] = lfBasic) and (Land[y,x-2] = lfBasic))) then
-                begin
+                    LandPixels[y,x]:= (LandPixels[y,x] and not AMask) or (128 shl AShift)
+                    end;
+                Land[y,x]:= lfObject
+            end
+            else if (Land[y, x] = 0) and
+                    (((Land[y, x-1] = lfBasic) and (Land[y+1,x-1] = lfBasic) and (Land[y+2,x] = lfBasic)) or
+                    ((Land[y, x-1] = lfBasic) and (Land[y-1,x-1] = lfBasic) and (Land[y-2,x] = lfBasic)) or
+                    ((Land[y, x+1] = lfBasic) and (Land[y+1,x+1] = lfBasic) and (Land[y+2,x] = lfBasic)) or
+                    ((Land[y, x+1] = lfBasic) and (Land[y-1,x+1] = lfBasic) and (Land[y-2,x] = lfBasic)) or
+                    ((Land[y+1, x] = lfBasic) and (Land[y+1,x+1] = lfBasic) and (Land[y,x+2] = lfBasic)) or
+                    ((Land[y-1, x] = lfBasic) and (Land[y-1,x+1] = lfBasic) and (Land[y,x+2] = lfBasic)) or
+                    ((Land[y+1, x] = lfBasic) and (Land[y+1,x-1] = lfBasic) and (Land[y,x-2] = lfBasic)) or
+                    ((Land[y-1, x] = lfBasic) and (Land[y-1,x-1] = lfBasic) and (Land[y,x-2] = lfBasic))) then
+            begin
+                if (cReducedQuality and rqBlurryLand) = 0 then
+                    begin
                     if Land[y, x-1] = lfBasic then LandPixels[y, x]:= LandPixels[y, x-1]
                     else if Land[y, x+1] = lfBasic then LandPixels[y, x]:= LandPixels[y, x+1]
                     else if Land[y+1, x] = lfBasic then LandPixels[y, x]:= LandPixels[y+1, x]
                     else if Land[y-1, x] = lfBasic then LandPixels[y, x]:= LandPixels[y-1, x];
-                    LandPixels[y,x]:= (LandPixels[y,x] and not AMask) or (64 shl AShift);
-                    Land[y,x]:= lfObject
-                end;
+                    LandPixels[y,x]:= (LandPixels[y,x] and not AMask) or (64 shl AShift)
+                    end;
+                Land[y,x]:= lfObject
+            end;
     AddProgress();
 end;
 
--- a/hedgewars/uLandGraphics.pas	Tue Jun 21 16:43:05 2011 +0400
+++ b/hedgewars/uLandGraphics.pas	Thu Jun 23 21:19:43 2011 +0400
@@ -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,52 @@
 Despeckle:= false
 end;
 
+procedure Smooth(X, Y: LongInt);
+begin
+// a bit of AA for explosions
+if (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 (cReducedQuality and rqBlurryLand) = 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)
+            end;
+        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 (cReducedQuality and rqBlurryLand) = 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)
+            end;
+        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 +813,7 @@
                 begin
                 updateBlock:= false;
                 resweep:= true;
+                firstpass:= true;
                 ty:= y * 32;
                 tx:= x * 32;
                 while(resweep) do
@@ -776,6 +821,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 +848,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/uScript.pas	Tue Jun 21 16:43:05 2011 +0400
+++ b/hedgewars/uScript.pas	Thu Jun 23 21:19:43 2011 +0400
@@ -657,6 +657,30 @@
     lc_gethogname:= 1
 end;
 
+function lc_sethogname(L : Plua_State) : LongInt; Cdecl;
+var gear : PGear;
+  hogName: ShortString;
+begin
+    if lua_gettop(L) <> 2 then
+        begin
+        LuaError('Lua: Wrong number of parameters passed to SetHogName!');
+        lua_pushnil(L)
+        end
+    else
+        begin
+        gear:= GearByUID(lua_tointeger(L, 1));
+        if (gear <> nil) and (gear^.Kind = gtHedgehog) and (gear^.Hedgehog <> nil) then
+
+	    hogName:= lua_tostring(L, 2);
+            gear^.Hedgehog^.Name:= hogName;
+
+	    FreeTexture(gear^.Hedgehog^.NameTagTex);
+            gear^.Hedgehog^.NameTagTex:= RenderStringTex(gear^.Hedgehog^.Name, gear^.Hedgehog^.Team^.Clan^.Color, fnt16);
+
+        end;
+    lc_sethogname:= 0;
+end;
+
 function lc_gettimer(L : Plua_State) : LongInt; Cdecl;
 var gear : PGear;
 begin
@@ -827,19 +851,42 @@
     lc_switchhog:= 0
 end;
 
+{function lc_addammo(L : Plua_State) : LongInt; Cdecl;
+var gear : PGear;
+begin
+
+    if lua_gettop(L) = 3 then
+    begin
+	gear:= GearByUID(lua_tointeger(L, 1));
+        if (gear <> nil) and (gear^.Hedgehog <> nil) then
+            AddAmmoAmount(gear^.Hedgehog^, TAmmoType(lua_tointeger(L, 2)), lua_tointeger(L,3) );
+    end else
+    
+    if lua_gettop(L) = 2 then
+    begin
+	gear:= GearByUID(lua_tointeger(L, 1));
+        if (gear <> nil) and (gear^.Hedgehog <> nil) then
+            AddAmmo(gear^.Hedgehog^, TAmmoType(lua_tointeger(L, 2)));
+    end else
+    begin
+    	LuaError('Lua: Wrong number of parameters passed to AddAmmo!');
+    end;
+
+    lc_addammo:= 0;
+
+end;}
+
 function lc_addammo(L : Plua_State) : LongInt; Cdecl;
 var gear : PGear;
 begin
-    if lua_gettop(L) <> 2 then
-        begin
-        LuaError('Lua: Wrong number of parameters passed to AddAmmo!');
-        end
-    else
+    if (lua_gettop(L) = 3) or (lua_gettop(L) = 2) then
         begin
         gear:= GearByUID(lua_tointeger(L, 1));
         if (gear <> nil) and (gear^.Hedgehog <> nil) then
-            AddAmmo(gear^.Hedgehog^, TAmmoType(lua_tointeger(L, 2)));
-        end;
+            if lua_gettop(L) = 2 then AddAmmo(gear^.Hedgehog^, TAmmoType(lua_tointeger(L, 2)))
+            else AddAmmo(gear^.Hedgehog^, TAmmoType(lua_tointeger(L, 2)), lua_tointeger(L, 3))
+        end
+    else LuaError('Lua: Wrong number of parameters passed to AddAmmo!');
     lc_addammo:= 0
 end;
 
@@ -856,6 +903,12 @@
         if gear <> nil then
             begin
             gear^.Health:= lua_tointeger(L, 2);
+
+	    if (gear^.Kind = gtHedgehog) and (gear^.Hedgehog <> nil) then
+            begin  
+		RenderHealth(gear^.Hedgehog^);
+            end;
+
             SetAllToActive;
             end
         end;
@@ -1712,6 +1765,7 @@
 lua_register(luaState, 'SetClanColor', @lc_setclancolor);
 lua_register(luaState, 'GetHogTeamName', @lc_gethogteamname);
 lua_register(luaState, 'GetHogName', @lc_gethogname);
+lua_register(luaState, 'SetHogName', @lc_sethogname);
 lua_register(luaState, 'GetHogLevel', @lc_gethoglevel);
 lua_register(luaState, 'SetHogLevel', @lc_sethoglevel);
 lua_register(luaState, 'GetX', @lc_getx);
--- a/hedgewars/uStore.pas	Tue Jun 21 16:43:05 2011 +0400
+++ b/hedgewars/uStore.pas	Thu Jun 23 21:19:43 2011 +0400
@@ -283,10 +283,12 @@
         if (((cReducedQuality and (rqNoBackground or rqLowRes)) = 0) or   // why rqLowRes?
                 (not (ii in [sprSky, sprSkyL, sprSkyR, sprHorizont, sprHorizontL, sprHorizontR]))) and
            (((cReducedQuality and rqPlainSplash) = 0) or ((not (ii in [sprSplash, sprDroplet, sprSDSplash, sprSDDroplet])))) and
-           (((cReducedQuality and rqKillFlakes) = 0) or (Theme = 'Snow') or (Theme = 'Christmas') or ((not (ii in [sprFlake, sprSDFlake])))) then
+           (((cReducedQuality and rqKillFlakes) = 0) or (Theme = 'Snow') or (Theme = 'Christmas') or ((not (ii in [sprFlake, sprSDFlake])))) and
+           ((cCloudsNumber > 0) or (ii <> sprCloud)) and
+           ((vobCount > 0) or (ii <> sprFlake)) then
         begin
             if AltPath = ptNone then
-                if ii in [sprHorizontL, sprHorizontR, sprSkyL, sprSkyR] then // FIXME: hack
+                if ii in [sprHorizont, sprHorizontL, sprHorizontR, sprSky, sprSkyL, sprSkyR, sprChunk] then // FIXME: hack
                     begin
                     tmpsurf:= LoadImage(UserPathz[Path] + '/' + FileName, ifAlpha or ifTransparent);
                     if tmpsurf = nil then tmpsurf:= LoadImage(Pathz[Path] + '/' + FileName, ifAlpha or ifTransparent)
@@ -306,7 +308,7 @@
             if tmpsurf <> nil then
             begin
                 if getImageDimensions then
-                begin
+		begin
                     imageWidth:= tmpsurf^.w;
                     imageHeight:= tmpsurf^.h
                 end;
--- a/hedgewars/uVariables.pas	Tue Jun 21 16:43:05 2011 +0400
+++ b/hedgewars/uVariables.pas	Thu Jun 23 21:19:43 2011 +0400
@@ -547,7 +547,7 @@
             Width:  64; Height: 64; imageWidth: 0; imageHeight: 0; saveSurf: false; priority: tpMedium; getDimensions: false; getImageDimensions: true),// sprHandCheese
             (FileName:  'amFlamethrower'; Path: ptHedgehog; AltPath: ptNone; Texture: nil; Surface: nil;
             Width:  128; Height: 128; imageWidth: 0; imageHeight: 0; saveSurf: false; priority: tpMedium; getDimensions: false; getImageDimensions: true),// sprHandFlamethrower
-            (FileName:  'Chunk'; Path: ptCurrTheme; AltPath: ptGraphics; Texture: nil; Surface: nil;
+            (FileName:  'Chunk'; Path: ptCurrTheme; AltPath: ptNone; Texture: nil; Surface: nil;
             Width:  32; Height: 32; imageWidth: 0; imageHeight: 0; saveSurf: false; priority: tpMedium; getDimensions: false; getImageDimensions: true),// sprChunk
             (FileName:  'Note'; Path: ptGraphics; AltPath: ptNone; Texture: nil; Surface: nil;
             Width:  32; Height: 32; imageWidth: 0; imageHeight: 0; saveSurf: false; priority: tpMedium; getDimensions: false; getImageDimensions: true),// sprNote
@@ -2037,7 +2037,7 @@
             ejectX: 0; 
             ejectY: 0),
 
-// Tardis (just a copy of teleport til nemo arives)
+// Tardis
             (NameId: sidTardis;
             NameTex: nil;
             Probability: 200;
@@ -2063,15 +2063,13 @@
             ejectX: 0;
             ejectY: 0),
 
-// Structure
+// Structure      
             (NameId: sidStructure;
             NameTex: nil;
             Probability: 0;
             NumberInCase: 1;
             Ammo: (Propz: ammoprop_ForwMsgs or
                           ammoprop_NoCrosshair or
-                          ammoprop_NeedTarget or
-                          ammoprop_AttackingPut or
                           ammoprop_Utility or
                           ammoprop_DontHold;
                 Count: 1;
@@ -2086,10 +2084,11 @@
             maxAngle: 0;
             isDamaging: false;
             SkipTurns: 0;
-            PosCount: 2;
-            PosSprite: sprAmTeleport;
+            PosCount: 1;
+            PosSprite: sprWater;
             ejectX: 0;
             ejectY: 0),
+            
 // Land Gun
             (NameId: sidLandGun;
             NameTex: nil;
--- a/hedgewars/uVisualGears.pas	Tue Jun 21 16:43:05 2011 +0400
+++ b/hedgewars/uVisualGears.pas	Thu Jun 23 21:19:43 2011 +0400
@@ -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;
 
--- a/hedgewars/uWorld.pas	Tue Jun 21 16:43:05 2011 +0400
+++ b/hedgewars/uWorld.pas	Thu Jun 23 21:19:43 2011 +0400
@@ -528,8 +528,8 @@
 var i, w, h, lw, lh, rw, rh, sw: LongInt;
 begin
     sw:= round(cScreenWidth / cScaleFactor);
-    if (SpritesData[sprL].Texture = nil) or (SpritesData[sprR].Texture = nil) then
-    begin
+    if ((SpritesData[sprL].Texture = nil) or (SpritesData[sprR].Texture = nil)) and (SpritesData[spr].Texture <> nil) then
+        begin
         w:= SpritesData[spr].Width * SpritesData[spr].Texture^.Scale;
         h:= SpritesData[spr].Height * SpritesData[spr].Texture^.Scale;
         i:= Shift mod w;
@@ -539,9 +539,9 @@
             DrawTexture(i, WorldDy + LAND_HEIGHT + OffsetY - h, SpritesData[spr].Texture, SpritesData[spr].Texture^.Scale);
             inc(i, w)
         until i > sw
-    end
-    else
-    begin
+        end
+    else if SpritesData[spr].Texture <> nil then
+        begin
         w:= SpritesData[spr].Width * SpritesData[spr].Texture^.Scale;
         h:= SpritesData[spr].Height * SpritesData[spr].Texture^.Scale;
         lw:= SpritesData[sprL].Width * SpritesData[spr].Texture^.Scale;
@@ -553,18 +553,18 @@
 
         i:= Shift - lw;
         while i >= -sw - lw do
-        begin
+            begin
             DrawTexture(i, WorldDy + LAND_HEIGHT + OffsetY - lh, SpritesData[sprL].Texture, SpritesData[sprL].Texture^.Scale);
             dec(i, lw);
-        end;
+            end;
 
         i:= Shift + w;
         while i <= sw do
-        begin
+            begin
             DrawTexture(i, WorldDy + LAND_HEIGHT + OffsetY - rh, SpritesData[sprR].Texture, SpritesData[sprR].Texture^.Scale);
             inc(i, rw)
+            end
         end
-    end
 end;
 
 
Binary file misc/hedgewars.png has changed
--- a/project_files/HedgewarsMobile/Classes/MapConfigViewController.m	Tue Jun 21 16:43:05 2011 +0400
+++ b/project_files/HedgewarsMobile/Classes/MapConfigViewController.m	Thu Jun 23 21:19:43 2011 +0400
@@ -380,14 +380,14 @@
 -(void) loadDataSourceArray {
     NSString *model = getModelType();
 
-    // themes.cfg contains all the user-selectable themes
-    NSString *string = [[NSString alloc] initWithContentsOfFile:[THEMES_DIRECTORY() stringByAppendingString:@"/themes.cfg"]
-                                                       encoding:NSUTF8StringEncoding
-                                                          error:NULL];
-    NSMutableArray *themeArray = [[NSMutableArray alloc] initWithArray:[string componentsSeparatedByString:@"\n"]];
-    [string release];
-    // remove a trailing "" element
-    [themeArray removeLastObject];
+    // only folders containing icon.png are a valid theme
+    NSArray *themeArrayFull = [[NSFileManager defaultManager] contentsOfDirectoryAtPath:THEMES_DIRECTORY() error:NULL];
+    NSMutableArray *themeArray = [[NSMutableArray alloc] init];
+    for (NSString *themeName in themeArrayFull) {
+        NSString *checkPath = [[NSString alloc] initWithFormat:@"%@/%@/icon.png",THEMES_DIRECTORY(),themeName];
+        if ([[NSFileManager defaultManager] fileExistsAtPath:checkPath])
+            [themeArray addObject:themeName];
+    }
 
     // remove images that are too big for certain devices without loading the whole image
     NSArray *mapArrayFull = [[NSFileManager defaultManager] contentsOfDirectoryAtPath:MAPS_DIRECTORY() error:NULL];
--- a/project_files/HedgewarsMobile/Hedgewars.xcodeproj/project.pbxproj	Tue Jun 21 16:43:05 2011 +0400
+++ b/project_files/HedgewarsMobile/Hedgewars.xcodeproj/project.pbxproj	Thu Jun 23 21:19:43 2011 +0400
@@ -1370,7 +1370,7 @@
 			);
 			runOnlyForDeploymentPostprocessing = 0;
 			shellPath = /bin/sh;
-			shellScript = "#copy new stuff over old stuff\nrm -rf ${PROJECT_DIR}/Data\n\n#create config.inc\necho \"Updating config file...\"\nPROTO=`cat ${PROJECT_DIR}/../../CMakeLists.txt | grep HEDGEWARS_PROTO_VER | cut -d ' ' -f 3`\nMAJN=`cat ${PROJECT_DIR}/../../CMakeLists.txt | grep CPACK_PACKAGE_VERSION_MAJOR | xargs | cut -d ' ' -f 3`\nMINN=`cat ${PROJECT_DIR}/../../CMakeLists.txt | grep CPACK_PACKAGE_VERSION_MINOR | xargs | cut -d ' ' -f 3`\nPATN=`cat ${PROJECT_DIR}/../../CMakeLists.txt | grep CPACK_PACKAGE_VERSION_PATCH | xargs | cut -d ' ' -f 3 | cut -d '$' -f 1`\nREVN=-`/usr/local/bin/hg id -n ${PROJECT_DIR}/../../`\necho \"const cNetProtoVersion = $PROTO; const cVersionString = '${MAJN}.${MINN}.${PATN}${REVN}'; const cLuaLibrary = '';\" > ${PROJECT_DIR}/../../hedgewars/config.inc\n\necho \"Copying Data...\"\ncp -R ${PROJECT_DIR}/../../share/hedgewars/Data ${PROJECT_DIR}/Data\n\n#copy some files from QTfrontend/res\necho \"Fetching additional graphics from QTfrontend/res...\"\nmkdir ${PROJECT_DIR}/Data/Graphics/Btn\ncp    ${PROJECT_DIR}/../../QTfrontend/res/btn*.png        ${PROJECT_DIR}/Data/Graphics/Btn/\ncp    ${PROJECT_DIR}/../../QTfrontend/res/icon*.png       ${PROJECT_DIR}/Data/Graphics/Btn/\ncp    ${PROJECT_DIR}/../../QTfrontend/res/StatsMedal*.png ${PROJECT_DIR}/Data/Graphics/Btn/\ncp    ${PROJECT_DIR}/../../QTfrontend/res/StatsR.png      ${PROJECT_DIR}/Data/Graphics/Btn/StatsStar.png\ncp    ${PROJECT_DIR}/../../QTfrontend/res/ammopic.png     ${PROJECT_DIR}/Data/Graphics/Btn/iconAmmo.png\ncp -R ${PROJECT_DIR}/../../QTfrontend/res/botlevels       ${PROJECT_DIR}/Data/Graphics/Hedgehog/botlevels/\n\necho \"Removing text and dummy files...\"\n#delete all CMakeLists.txt and image source files\nfind ${PROJECT_DIR}/Data -name CMakeLists.txt -delete\nfind ${PROJECT_DIR}/Data -name *.svg -delete\nfind ${PROJECT_DIR}/Data -name *.svgz -delete\nfind ${PROJECT_DIR}/Data -name *.sifz -delete\nfind ${PROJECT_DIR}/Data -name *.xcf -delete\nfind ${PROJECT_DIR}/Data -name *.orig -delete\n\n#delete desktop frontend translation\nrm -rf ${PROJECT_DIR}/Data/Locale/hedgewars_*\n\n#delete dummy maps and hats, misc stuff\nrm -rf ${PROJECT_DIR}/Data/Maps/{test*,Ruler}\nrm -rf ${PROJECT_DIR}/Data/Graphics/Hats/{TeamCap,TeamHeadband,TeamHair}\nrm -rf ${PROJECT_DIR}/Data/misc/\n\n#delete forbidden maps\nrm -rf ${PROJECT_DIR}/Data/Maps/{Cheese,FlightJoust}\n\n#delete useless fonts\nrm -rf ${PROJECT_DIR}/Data/Fonts/{wqy-zenhei.ttc,DroidSansFallback.ttf}\n\n#delete all names, reserved hats\nrm -rf ${PROJECT_DIR}/Data/Names/\nrm -rf ${PROJECT_DIR}/Data/Graphics/Hats/Reserved/\n\necho \"Handling audio files...\"\n#delete the Classic voice\nrm -rf ${PROJECT_DIR}/Data/Sounds/voices/Classic\n#delete the main theme file\nrm -rf ${PROJECT_DIR}/Data/Music/main_theme.ogg\n#copy mono audio\ncp -R ${PROJECT_DIR}/Audio/* ${PROJECT_DIR}/Data/\n#remove unused voices\nfor i in {Amazing,Brilliant,Bugger,Bungee,Cutitout,Drat,Excellent,Fire,FlawlessPossibility,Gonnagetyou,Grenade,Hmm,Justyouwait,Leavemealone,Ohdear,Ouch,Perfect,Revenge,Runaway,Solong,Thisoneismine,VictoryPossibility,Watchthis,Whatthe,Whoopsee}; do find Data/Sounds/voices/ -name $i.ogg -delete; done\n\necho \"Tweaking Data contents...\"\n#move Lua maps in Missions\nmkdir ${PROJECT_DIR}/Data/Missions/Maps/\nmv ${PROJECT_DIR}/Data/Maps/{Basketball,Knockball,TrophyRace,CTF_Blizzard,Control} ${PROJECT_DIR}/Data/Missions/Maps/\n#workaround for missing map in CTF_Blizzard\nln -s ../../../Maps/Blizzard/map.png ${PROJECT_DIR}/Data/Missions/Maps/CTF_Blizzard/map.png\n\n#reduce the number of flakes for City\nawk '{if ($1 == 1500) $1=40; print $0}' < ${PROJECT_DIR}/Data/Themes/City/theme.cfg > /tmp/tempfile\nmv /tmp/tempfile ${PROJECT_DIR}/Data/Themes/City/theme.cfg\n\n#remove Isalnd from the list of Themes\nawk '{if ($1 != \"Island\") print $0}' < ${PROJECT_DIR}/Data/Themes/themes.cfg > /tmp/tempfile && mv /tmp/tempfile ${PROJECT_DIR}/Data/Themes/themes.cfg\n\n#remove Beach and Digital themes as well as Islqnd (from Maps and Themes folders)\nrm -rf ${PROJECT_DIR}/Data/Themes/{Beach,Digital}\nrm -rf ${PROJECT_DIR}/Data/Themes/Island\nawk '{if ($1 == \"Island\") print \"Nature\"}' < ${PROJECT_DIR}/Data/Maps/Cave/map.cfg > /tmp/tempfile && mv /tmp/tempfile ${PROJECT_DIR}/Data/Maps/Cave/map.cfg\nawk '{if ($1 == \"Island\") print \"Nature\"}' < ${PROJECT_DIR}/Data/Maps/Lonely_Island/map.cfg > /tmp/tempfile && mv /tmp/tempfile ${PROJECT_DIR}/Data/Maps/Lonely_Island/map.cfg\nawk '{if ($1 == \"Island\") print \"Nature\"}' < ${PROJECT_DIR}/Data/Maps/PirateFlag/map.cfg > /tmp/tempfile && mv /tmp/tempfile ${PROJECT_DIR}/Data/Maps/PirateFlag/map.cfg\n\necho \"Done\"";
+			shellScript = "#copy new stuff over old stuff\nrm -rf ${PROJECT_DIR}/Data\n\n#create config.inc\necho \"Updating config file...\"\nPROTO=`cat ${PROJECT_DIR}/../../CMakeLists.txt | grep HEDGEWARS_PROTO_VER | cut -d ' ' -f 3`\nMAJN=`cat ${PROJECT_DIR}/../../CMakeLists.txt | grep CPACK_PACKAGE_VERSION_MAJOR | xargs | cut -d ' ' -f 3`\nMINN=`cat ${PROJECT_DIR}/../../CMakeLists.txt | grep CPACK_PACKAGE_VERSION_MINOR | xargs | cut -d ' ' -f 3`\nPATN=`cat ${PROJECT_DIR}/../../CMakeLists.txt | grep CPACK_PACKAGE_VERSION_PATCH | xargs | cut -d ' ' -f 3 | cut -d '$' -f 1`\nREVN=-`/usr/local/bin/hg id -n ${PROJECT_DIR}/../../`\necho \"const cNetProtoVersion = $PROTO; const cVersionString = '${MAJN}.${MINN}.${PATN}${REVN}'; const cLuaLibrary = '';\" > ${PROJECT_DIR}/../../hedgewars/config.inc\n\necho \"Copying Data...\"\ncp -R ${PROJECT_DIR}/../../share/hedgewars/Data ${PROJECT_DIR}/Data\n\n#copy some files from QTfrontend/res\necho \"Fetching additional graphics from QTfrontend/res...\"\nmkdir ${PROJECT_DIR}/Data/Graphics/Btn\ncp    ${PROJECT_DIR}/../../QTfrontend/res/btn*.png        ${PROJECT_DIR}/Data/Graphics/Btn/\ncp    ${PROJECT_DIR}/../../QTfrontend/res/icon*.png       ${PROJECT_DIR}/Data/Graphics/Btn/\ncp    ${PROJECT_DIR}/../../QTfrontend/res/StatsMedal*.png ${PROJECT_DIR}/Data/Graphics/Btn/\ncp    ${PROJECT_DIR}/../../QTfrontend/res/StatsR.png      ${PROJECT_DIR}/Data/Graphics/Btn/StatsStar.png\ncp    ${PROJECT_DIR}/../../QTfrontend/res/ammopic.png     ${PROJECT_DIR}/Data/Graphics/Btn/iconAmmo.png\ncp -R ${PROJECT_DIR}/../../QTfrontend/res/botlevels       ${PROJECT_DIR}/Data/Graphics/Hedgehog/botlevels/\n\necho \"Removing text and dummy files...\"\n#delete all CMakeLists.txt and image source files\nfind ${PROJECT_DIR}/Data -name CMakeLists.txt -delete\nfind ${PROJECT_DIR}/Data -name *.svg -delete\nfind ${PROJECT_DIR}/Data -name *.svgz -delete\nfind ${PROJECT_DIR}/Data -name *.sifz -delete\nfind ${PROJECT_DIR}/Data -name *.xcf -delete\nfind ${PROJECT_DIR}/Data -name *.orig -delete\n\n#delete desktop frontend translation\nrm -rf ${PROJECT_DIR}/Data/Locale/hedgewars_*\n\n#delete dummy maps and hats, misc stuff\nrm -rf ${PROJECT_DIR}/Data/Maps/{test*,Ruler}\nrm -rf ${PROJECT_DIR}/Data/Graphics/Hats/{TeamCap,TeamHeadband,TeamHair}\nrm -rf ${PROJECT_DIR}/Data/misc/\n\n#delete forbidden maps\nrm -rf ${PROJECT_DIR}/Data/Maps/{Cheese,FlightJoust}\n\n#delete useless fonts\nrm -rf ${PROJECT_DIR}/Data/Fonts/{wqy-zenhei.ttc,DroidSansFallback.ttf}\n\n#delete all names, reserved hats\nrm -rf ${PROJECT_DIR}/Data/Names/\nrm -rf ${PROJECT_DIR}/Data/Graphics/Hats/Reserved/\n\necho \"Handling audio files...\"\n#delete the Classic voice\nrm -rf ${PROJECT_DIR}/Data/Sounds/voices/Classic\n#delete the main theme file\nrm -rf ${PROJECT_DIR}/Data/Music/main_theme.ogg\n#copy mono audio\ncp -R ${PROJECT_DIR}/Audio/* ${PROJECT_DIR}/Data/\n#remove unused voices\nfor i in {Amazing,Brilliant,Bugger,Bungee,Cutitout,Drat,Excellent,Fire,FlawlessPossibility,Gonnagetyou,Grenade,Hmm,Justyouwait,Leavemealone,Ohdear,Ouch,Perfect,Revenge,Runaway,Solong,Thisoneismine,VictoryPossibility,Watchthis,Whatthe,Whoopsee}; do find Data/Sounds/voices/ -name $i.ogg -delete; done\n\necho \"Tweaking Data contents...\"\n#move Lua maps in Missions\nmkdir ${PROJECT_DIR}/Data/Missions/Maps/\nmv ${PROJECT_DIR}/Data/Maps/{Basketball,Knockball,TrophyRace,CTF_Blizzard,Control} ${PROJECT_DIR}/Data/Missions/Maps/\n#workaround for missing map in CTF_Blizzard\nln -s ../../../Maps/Blizzard/map.png ${PROJECT_DIR}/Data/Missions/Maps/CTF_Blizzard/map.png\n\n#reduce the number of flakes for City\nawk '{if ($1 == 1500) $1=40; print $0}' < ${PROJECT_DIR}/Data/Themes/City/theme.cfg > /tmp/tempfile\nmv /tmp/tempfile ${PROJECT_DIR}/Data/Themes/City/theme.cfg\n\n#remove WIP themes (check they are not used in Maps)\nrm -rf ${PROJECT_DIR}/Data/Themes/{Beach,Digital}\n\necho \"Done\"";
 			showEnvVarsInLog = 0;
 		};
 		9283011B0F10CB2D00CC5A3C /* Build libfpc.a */ = {
--- a/project_files/hedgewars.pro	Tue Jun 21 16:43:05 2011 +0400
+++ b/project_files/hedgewars.pro	Thu Jun 23 21:19:43 2011 +0400
@@ -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,32 @@
 	../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 \
+    ../QTfrontend/pageplayrecord.h \
+    ../QTfrontend/pagegamestats.h \
+    ../QTfrontend/HWApplication.h \
+    ../QTfrontend/AbstractPage.h \
+    ../QTfrontend/themesmodel.h
 
 SOURCES += ../QTfrontend/SDLs.cpp ../QTfrontend/SquareLabel.cpp \
 	../QTfrontend/about.cpp ../QTfrontend/ammoSchemeModel.cpp \
@@ -54,9 +80,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,11 +106,16 @@
     ../QTfrontend/pagemain.cpp \
     ../QTfrontend/pageingame.cpp \
     ../QTfrontend/pageinfo.cpp \
+    ../QTfrontend/pagedata.cpp \
     ../QTfrontend/pageeditteam.cpp \
     ../QTfrontend/pagedrawmap.cpp \
     ../QTfrontend/pageconnecting.cpp \
     ../QTfrontend/pagecampaign.cpp \
-    ../QTfrontend/pageadmin.cpp
+    ../QTfrontend/pageadmin.cpp \
+    ../QTfrontend/pagegamestats.cpp \
+    ../QTfrontend/pageplayrecord.cpp \
+    ../QTfrontend/HWApplication.cpp \
+    ../QTfrontend/themesmodel.cpp
 
 win32 {
 	SOURCES += ../QTfrontend/xfire.cpp
--- a/share/CMakeLists.txt	Tue Jun 21 16:43:05 2011 +0400
+++ b/share/CMakeLists.txt	Thu Jun 23 21:19:43 2011 +0400
@@ -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	Tue Jun 21 16:43:05 2011 +0400
+++ b/share/Info.plist.in	Thu Jun 23 21:19:43 2011 +0400
@@ -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>
Binary file share/hedgewars/Data/Graphics/Chunk.png has changed
--- a/share/hedgewars/Data/Locale/pl.txt	Tue Jun 21 16:43:05 2011 +0400
+++ b/share/hedgewars/Data/Locale/pl.txt	Thu Jun 23 21:19:43 2011 +0400
@@ -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	Tue Jun 21 16:43:05 2011 +0400
+++ b/share/hedgewars/Data/Locale/ru.txt	Thu Jun 23 21:19:43 2011 +0400
@@ -12,7 +12,7 @@
 00:09=Пистолет Desert Eagle
 00:10=Динамит
 00:11=Бейсбольная бита
-00:12=Shoryuken
+00:12=Восходящий удар Дракона
 00:13=сек
 00:14=Парашют
 00:15=Воздушная атака
@@ -42,6 +42,20 @@
 00:39=Летающая тарелка
 00:40=Коктейль Молотова
 00:41=Птичка
+00:42=Портативный телепорт
+00:43=Фортепьяновый удар
+00:44=Старый Лимбургер
+00:45=Синус-пушка (в разработке)
+00:46=Огнемет
+00:47=Мина-липучка
+00:48=Молот
+00:49=Воскреситель
+00:50=Сверлящий удар
+00:51=Комок грязи
+00:52=Оружие не выбрано
+00:53=Машина времени и пространства
+00:54=Структура
+00:55=Земляной распылитель
 
 01:00=Вперёд к победе!
 01:01=Ничья
@@ -49,152 +63,327 @@
 01:03=Громкость %1%
 01:04=Пауза
 01:05=Точно выйти (Y-Да/Esc-Нет)?
-01:06=Скоро погибель!
+01:06=Скоро потоп!
 01:07=Ещё %1
 01:08=Топливо
 01:09=Синхронизация...
+01:10=Использование этого предмета не завершит твой ход!
+01:11=Это оружие или предмет еще недоступно!
+01:12=Последний раунд до потопа!
+01:13=%1 раундов до потопа!
+01:14=Приготовься, %1!
 
 ; Event messages
 ; Hog (%1) died
-02:00=%1 не думал, что так случится!
-02:00=%1 машет на прощание рукой!
+02:00=%1 накрылся медным тазом!
+02:00=%1 увидел свет в конце тонеля!
+02:00=%1 никогда не знал, что его ждет!
+02:00=%1 помахал на прощание лапкой!
 02:00=%1 ушёл в лучший мир!
+02:00=%1 встретился со своим Создателем!
+02:00=%1 больше не может держаться!
+02:00=%1 исполнил свой долг!
+02:00=%1 принес последнюю жертву!
+02:00=%1 покидает мирскую суету!
+02:00=%1 стал удобрением!
+02:00=%1 отстрелялся!
+02:00=%1 приказал долго жить!
+02:00=%1, мы будем вспоминать о тебе с любовью!
+02:00=%1 покинул этот мир из-за аневризмы!
+02:00=%1 оставил жену и ребенка
 02:00=%1 уже не воспользуется базукой
 02:00=%1 уже не бросит гранату
 02:00=%1 уже не испечёт торт
 02:00=%1 уже не повисит на верёвке
-02:00=%1 отстрелялся
-02:00=%1 ушёл поиграть в лучшую игру
+02:00=%1 уже не вызовет воздушную атаку
+02:00=%1 уже не выстрелит из дробовика
+02:00=%1 уже не достанет свой арбуз
+02:00=%1 уже не достанет свой Desert Eagle
+02:00=%1 заплатил сполна
+02:00=%1 мог бы воспользоваться аптечкой
+02:00=%1 ушел играть в игру получше
+02:00=%1 прожил трудную жизнь
 02:00=%1 вышел из строя
 02:00=Бедный, бедный %1...
-02:00=%1 предпочитает Warmux
-02:00=%1 идёт по пути динозавров
+02:00=%1 предпочитает Wormux
+02:00=%1 принял удар на себя
+02:00=%1 герой среди лю...гм...ежей
+02:00=%1 занял свое место в Валгале
+02:00=%1 оставил дом
+02:00=%1 пошел по стопам динозавров
 02:00=%1 ведёт ежей по пути вымирания
 02:00=%1 выдавил слезу из моих глаз
+02:00=%1 бывший ёж
+02:00=%1 откинул копыта
 02:00=%1 перестал существовать
 02:00=Скажите "Прощай, %1!"
 02:00=Надежды больше нет, %1
-02:00=Срок истёк, %1
-02:00=%1 терпел обиды
+02:00=Это было твое последнее представление, %1
+02:00=Закури перед смертью, %1, т.к твоему здоровью это уже не повредит
+02:00=%1 испытал Внезапный Массовый Отказ в Системе Жизнеобеспечения (C)
+02:00=%1 преставился
+02:00=%1 стопроцентный труп
+02:00=%1 ... его больше нет
+02:00=%1 закончился
+02:00=Лишенный жизни, %1, покойся с миром
+02:00=%1 присоединился к хору невидимых
+02:00=Прощай %1, мы едва тебя знали!
+02:00=%1 имел плохую сопротивляемость к тому, чтобы быть застреленным
 02:00=%1 хотел бы иметь ещё одну жизнь
 02:00=В доме есть доктор?
+
 ; Hog (%1) drowned
 02:01=%1 играет подводную лодку!
 02:01=%1 подражает Титанику!
 02:01=%1 плавает как топор!
 02:01=%1 плавает как кирпич!
 02:01=%1 проверяет глубину
-02:01=%1 вызывает всплеск
-02:01=%1 забыл надувной круг
+02:01=%1 издал бульк, бульк, бульк
+02:01=От %1 пошли брызги
+02:01=%1 забыл свои надувные нарукавнички
 02:01=%1 пропустил уроки плавания
+02:01=%1 забыл дома доску для серфинга
+02:01=%1 помылся
+02:01=%1 - это один мокрый ёж
 02:01=%1 забыл надеть спасательный жилет
+02:01=%1 плескается в воде
 02:01=%1 спит среди рыб
-02:01=%1 томится жаждой
+02:01=%1 думал, что физика воды в этой игре полный отстой
+02:01=%1 испытывает жажду
+02:01=Море заказало %1
 02:01=%1 потерян в море
 02:01=%1 забыл надеть акваланг
 02:01=%1 похоронен в море
-02:01=%1 пробует плавать на спине
+02:01=У %1 было дурное предчуствие
+02:01=%1 учится плавать на спине
 02:01=%1 поплыл искать Титаник
-02:01=%1 ищет Немо
+02:01=%1 не Иисус
+02:01=%1 в поисках Немо
+02:01=%1 дал течь
+02:01=Ты будешь удивлен, узнав, сколько здесь внизу ежей, %1
 02:01=%1 немного повысил уровень океана
 02:01=%1 не записался в моряки
+02:01=%1 перевоплотился в мертвую рыбу
+02:01=По крайней мере, тебя не смыло в унитаз, %1
+02:01=Соник тоже никогда не умел плавать и не умеет сейчас, %1
+02:01=%1 хочет поиграть в Ecco the Dolphin
+02:01=%1 пошел посмотреть аквариум
 02:01=%1 нашёл потерянный город Атлантиды
+02:01=%1 стремится к главной роли в игре Bioshock 3
+02:01=Твое плаванье по-сабачьи принесло мало пользы, %1
+02:01=%1 забыл взять гидроцикл
 02:01=%1 не любит водный спорт
-02:01=%1 заливает раны солёной водой
+02:01=%1 всегда пускает пузыри
+02:01=%1 нуждается в плоту
+02:01=%1 думает, что соленая вода полезна для кожи
+02:01=%1 обрабатывает раны соленой водой
+02:01=%1 прошел по доске
 02:01=%1 принимает ванну
+02:01=%1 промок
 02:01=%1 промочил иголки
+02:01=Это сундучок Дэйви Джонса для %1
+
 ; Round starts
-02:02=Вперёд к победе!
-02:02=Вооружены и готовы!
-02:02=Сделаем это!
-02:02=Начнём вечеринку!
+02:02=Сразимся!
+02:02=Вооружены и готовы к бою!
+02:02=Приготовься пошуметь!
+02:02=Начнем!
+02:02=Начнем эту партию
+02:02=Останется только один
 02:02=Поехали!
+02:02=Поколбасимся!
+02:02=Налетай!
 02:02=Это начало...
 02:02=Это начало чего-то большого
-02:02=Добро пожаловать на войну ежей
-02:02=Добро пожаловать на фронт
-02:02=Разбей врага!
+02:02=Добро пожаловать в Hedgewars
+02:02=Добро пожаловать на передовую
+02:02=Сокруши своих врагов!
+02:02=Пусть победит сильнейший
 02:02=Победа или смерть
+02:02=Победитель получает все
 02:02=Поражение - не вариант
+02:02=Порви всех! Спусти с цепей ежей войны!
 02:02=Hedgewars от команды Hedgewars.org
 02:02=Удачи, веселись
-02:02=Побеждённые убирают за всех!
+02:02=Можешь считать себя счастливчиком, что ты играешь не против Tiyuri
+02:02=Можешь считать себя счастливчиком, что ты играешь против unC0Rr
+02:02=Можешь считать себя счастливчиком, что ты играешь против Nemo
+02:02=Можешь считать себя счастливчиком, что ты играешь не против Smaxx
+02:02=Можешь считать себя счастливчиком, что ты играешь не против Jessor
+02:02=Сделай все что сможешь и даже больше!
+02:02=Проигравшие убирают за всех!
+02:02=Начни битву тысячелетия
+02:02=Начни битву века
+02:02=Начни битву этого квартала года
+02:02=Начни битву года
+02:02=Начни битву месяца
+02:02=Начни битву недели
+02:02=Нажни битву дня
+02:02=Начни битву часа
+02:02=Покажи все, на что ты способен!
+02:02=Уничтожь врагов!
 02:02=Удачи
-02:02=Не сдавайся!
+02:02=Веселись
+02:02=Отдайся всецело битве
+02:02=Сражайся грязно, не брезгуй любыми методами
+02:02=Сражайся с честью
+02:02=Не сдавайся
+02:02=Никогда не сдавайся
+02:02=Врежь им и наваляй!
+02:02=Открой счет убитым ежам. Начни Frag-фестиваль!
+02:02=Я надеюсь, что ты готов к потасовке!
+02:02=Давай, давай, поехали!
+02:02=Ежиное наступление!
+02:02=Наваляй им!
+02:02=Не бойся!
+02:02=Будь храбрым и победи
+
 ; Round ends (win; unused atm)
 02:03=...
+
 ; Round ends (draw; unused atm)
 02:04=...
+
 ; New health crate
 02:05=Помощь пришла!
 02:05=Аптечка!
 02:05=Первая помощь с небес!
+02:05=Медпакет для тебя
 02:05=Здоровье... в форме ящика!
-02:05=Доктор звонит
-02:05=Для улучшения самочувствия
-02:05=Подбери это
+02:05=Доктора вызывали?
+02:05=Новые бинты!
+02:05=Это улучшит твое самочуствие
+02:05=Супер-микстура! Еще не все потеряно
+02:05=Подбери меня
+02:05=Подбери ее
+02:05=Оздоровительная закуска
 02:05=Средство от боли
-02:05=Дозировка: сколько найдёшь!
+02:05=Способ применения и дозы: столько, сколько сможешь найти!
+02:05=Срочная доставка
+02:05=Доставка!
+
 ; New ammo crate
 02:06=Ещё оружие!
 02:06=Подкрепление!
-02:06=Интересно, что там?
+02:06=Опечатано и погружено!
+02:06=Интересно, что там за оружие?
+02:06=Доставка!
+02:06=Что бы там могло быть внутри?
+02:06=Рождество в Hedgewars приходит раньше
 02:06=Подарок!
 02:06=Особая посылка!
 02:06=Было сложно провести это через таможню
 02:06=Опасные игрушки с небес
-02:06=Подбери или взорви
-02:06=Мммм... оружие
+02:06=Предупреждение! Содержимое изменчиво
+02:06=Подбери это или взорви, выбор за тобой
+02:06=Клёвые штучки!
+02:06=Мммм... боеприпасы
+02:06=Ящик разрушительной силы
 02:06=Воздушная почта!
 02:06=Что бы там ни было, это не пицца
 02:06=Подбери!
-02:06=Не отдавай врагу!
-02:06=Новые игрушки!
+02:06=Прибыло подкрепление
+02:06=Не отдавай это врагу!
+02:06=Игрушки - новые, блестящие, совсем как настоящие!
 02:06=Магический ящик!
+
 ; New utility crate
-02:07=Это может быть полезно...
+02:07=Время мастерить!
+02:07=Это может пригодиться...
+02:07=Полезная вещь!
+02:07=Используй этот ящик
+02:07=Ищи его внизу
+02:07=Еще полезные вещи!
+02:07=Инструменты для тебя!
+02:07=Это должно быть что-то хорошее!
 02:07=Используй с умом
-02:07=Тебе это понадобится
-02:07=Используй этот ящик
 02:07=О! Это тяжёлый ящик
+02:07=Тебе это может понадобиться
+
 ; Hog (%1) skips his turn
 02:08=%1 такой скучный...
+02:08=%1 ни о чем не беспокоится
 02:08=%1 ленивый ёж
 02:08=%1 беспечен
 02:08=%1 сдался
+02:08=Задремаешь - проиграешь, %1
 02:08=%1 позорно пропускает
-02:08=%1 нуждается в мотивации
+02:08=%1 самый настоящий лентяй
+02:08=%1 нуждается в немного большей мотивации
 02:08=%1 пацифист
+02:08=%1 взял передышку
 02:08=%1 отдыхает
-02:08=%1 расслабляется
-02:08=%1 позволяет врагу делать что угодно
+02:08=%1 прохлаждается
+02:08=%1 не верит в собственные силы
+02:08=%1 решил вообще ничего не делать
+02:08=%1 позволяет врагу уничтожить себя
+02:08=%1 был бы самым скучным на вечеринках
 02:08=%1 прячется
 02:08=%1 решил пропустить эту возможность
 02:08=%1 решил, что лучше сделать... ничего
-02:08=%1 большой копуша
+02:08=%1 слабак
+02:08=Цыпа цыпа цыпа, цыпленок %1
+02:08=%1 выглядит желторотым юнцом
 02:08=%1 трус!
-02:08=%1 ожидает потоп
+02:08=%1 ждет потопа
+02:08=%1 не боец
 02:08=%1 пересматривает свой смысл жизни
-02:08=%1 всё равно не умеет стрелять
+02:08=%1 в любом случае, никогда не умел хорошо стрелять
+02:08=%1 не хотел присоединяться к армии в первых рядах
+02:08=Хватит впустую тратить время, %1
 02:08=Я разочарован тобой, %1
+02:08=Давай, ты можешь добиться большего, чем этот %1
+02:08=Намерения %1 провалились
+02:08=%1 очевидно знает более интересные дела
+02:08=%1 оцепенел от страха
+02:08=%1 уснул
+
 ; Hog (%1) hurts himself only
 02:09=%1 должен практиковаться в прицеливании!
 02:09=%1 ненавидит себя
+02:09=%1 перешел на сторону врага!
+02:09=%1 уподобился эмо
 02:09=%1 не той стороной взялся за оружие
+02:09=%1 немного садистский
+02:09=%1 мазохист
 02:09=%1 не имеет инстинкта самосохранения
 02:09=%1 напортачил
+02:09=%1 перенервничал
 02:09=Это был плохой выстрел, %1
-02:09=%1 неосторожен с оружием
+02:09=%1 немного неосторожен с опасным оружием
+02:09=%1 должен пересмотреть свой карьерный путь
 02:09=Худший. Выстрел. Из всех!
 02:09=Нет, нет, нет %1, стреляй по ВРАГУ!
-02:09=%1 на шаг ближе к самоубийству
+02:09=%1 должен был всего лишь уничтожить врага
+02:09=%1 стал на шаг ближе к самоубийству
 02:09=%1 помогает врагу
+02:09=Это было глупо, %1
+02:09=%1 живет молитвами "через мучения к наслаждению"
+02:09=%1 совсем запутался
+02:09=%1 поранил себя в суматохе
+02:09=%1 горазд ставить себя в глупое положение
+02:09=%1 недотёпа!
+02:09=%1 неуклюжий
 02:09=%1 показывает врагу, на что он способен
-02:09=%1, конечно, сделал это специально
+02:09=Нельзя от %1 всегда ожидать совершенства
+02:09=Не волнуйся %1, сикто не новершенен
+02:09=%1 вообщем-то сделал это намерено
 02:09=Я никому не скажу, если ты не скажешь, %1
+02:09=Какой стыд!
+02:09=Я уверен, никто этого не видел %1
+02:09=%1 должен пересмотреть свой боевой устав
+02:09=Очевидно, что оружие %1 работало со сбоями
+
 ; Hog shot an home run (using the bat and another hog)
-02:10=Птица, самолёт, ...
-02:10=Он вылетел!
+02:10=Хоум-ран!
+02:10=Птица, самолет, ...
+02:10=Тот отсутствует!
+
+; Hog (%1) has to leave (team is gone)
+02:11=%1 должен идти спать!
+02:11=%1 кажется слишком занят, чтобы играть
+02:11=Излучи его, Скотти!
+02:11=%1 должен идти
 
 ; Weapon Categories
 03:00=Граната с таймером
@@ -239,50 +428,72 @@
 03:39=Инструмент для перемещения
 03:40=Испепеляющая граната
 03:41=Большой поклонник Squawks
+03:42=Здесь я веду записи...
+; the misspelled "Beethoven" is intentional (-> to beat)
+03:43=Исполнение смертельной сонаты Бетховена
+03:44=Годен до: 1923
+03:45=Достижения науки
+03:46=Горячо, горячо, горячо!
+03:47=Прикрепи их где-нибудь с пользой!
+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: Установить таймер гранаты|Attack: Удерживай для более дальнего броска
-04:01=Атакуй своих врагов касетной бомбой.|Она расколется на несколько меньших бомб,|когда таймер достигнет нуля.|1-5: Установить таймер бомбы|Attack: Удерживай для более дальнего броска
-04:02=Атакуй своих врагов баллистическим снарядом,|на который может повлиять направление ветра.|Attack: Удерживай для выстрела с большей силой
-04:03=Запусти взрывчатую пчелу, которая соединится|с выбранной целью. Не бросай ее слишком сильно,|чтобы повысить точность.|Cursor: Захватить цель|Attack: Удерживай для более дальнего броска
-04:04=Атакуй своих врагов с помощью дробовика|с двумя выстрелами. Благодаря его большому|радиусу поражения тебе не нужно заботиться о|точности попадания, чтобы нанести урон сопернику.|Attack: Выстрелить (несколько раз)
-04:05=Двигайся вглубь земли! Используй отбойный|молоток, чтобы пробурить отверстие в земле и|добраться до других участков.|Attack: Запустить или остановить бурение
-04:06=Заскучал?|Нет возможности атаковать?|Бережешь боеприпасы?|Нет проблем! Пропусти ход, трус!|Attack: Пропустить ход без сражения
-04:07=Преодолевай большие расстояния за короткое|время с помощью веревки. Используй инерцию тела,|чтобы переместиться к другим ежам или сбросить|на них гранаты и другое вооружение.|Attack: Выстрелить или освободить веревку|Long Jump: Сбросить гранаты или похожее вооружение
-04:08=Держи своих врагов на расстоянии,|бросая мины в узкие проходы или|прямо им под ноги. Убедись, что отступил,|пока мина не сработала рядом с тобой!|Attack: Бросить мину рядом с собой
-04:09=Не уверен, что хорошо прицелился?|Используй пистолет Desert Eagle|с возможностью сделать до четырех|выстрелов за ход.|Attack: Выстрелить (несколько раз)
-04:10=Грубая сила всегда была в цене.|Брось эту классическую взрывчатку|возле своих врагов и убегай.|Attack: Бросить динамит рядом с собой
-04:11=Избавься от вражеских ежей с помощью|подачи битой, отправив их за край карты|или в воду. Или как насчет того, чтобы отправить ударом|одну из мин на карте в подарок своим друзьям?|Attack: Нанести удар по всему, что стоит перед тобой
-04:12=Стань лицом к лицу со своим врагом,|чтобы обрушить на него всю мощь|смертоносной техники боевых исскуств.|Attack: Исполнить Неистовый Удар
+04:00=Атакуй своих врагов обычной гранатой.|Она взорвется сразу, как только таймер|достигнет нуля.|1-5: Установить таймер гранаты|Атака: Удерживай для более дальнего броска
+04:01=Атакуй своих врагов касетной бомбой.|Она расколется на несколько меньших бомб,|когда таймер достигнет нуля.|1-5: Установить таймер бомбы|Атака: Удерживай для более дальнего броска
+04:02=Атакуй своих врагов баллистическим снарядом,|на который может повлиять направление ветра.|Атака: Удерживай для выстрела с большей силой
+04:03=Запусти взрывчатую пчелу, которая соединится|с выбранной целью. Не бросай ее слишком сильно,|чтобы повысить точность.|Курсор: Захватить цель|Атака: Удерживай для более дальнего броска
+04:04=Атакуй своих врагов с помощью дробовика|с двумя выстрелами. Благодаря его большому|радиусу поражения тебе не нужно заботиться о|точности попадания, чтобы нанести урон сопернику.|Атака: Выстрелить (несколько раз)
+04:05=Двигайся вглубь земли! Используй отбойный|молоток, чтобы пробурить отверстие в земле и|добраться до других участков.|Атака: Запустить или остановить бурение
+04:06=Заскучал?|Нет возможности атаковать?|Бережешь боеприпасы?|Нет проблем! Пропусти ход, трус!|Атака: Пропустить ход без сражения
+04:07=Преодолевай большие расстояния за короткое|время с помощью веревки. Используй инерцию тела,|чтобы переместиться к другим ежам или сбросить|на них гранаты и другое вооружение.|Атака: Выстрелить или освободить веревку|Длинный прыжок: Сбросить гранаты или похожее вооружение
+04:08=Держи своих врагов на расстоянии,|бросая мины в узкие проходы или|прямо им под ноги. Убедись, что отступил,|пока мина не сработала рядом с тобой!|Атака: Бросить мину рядом с собой
+04:09=Не уверен, что хорошо прицелился?|Используй пистолет Desert Eagle|с возможностью сделать до четырех|выстрелов за ход.|Атака: Выстрелить (несколько раз)
+04:10=Грубая сила всегда была в цене.|Брось эту классическую взрывчатку|возле своих врагов и убегай.|Атака: Бросить динамит рядом с собой
+04:11=Избавься от вражеских ежей с помощью|подачи битой, отправив их за край карты|или в воду. Или как насчет того, чтобы отправить ударом|одну из мин на карте в подарок своим друзьям?|Атака: Нанести удар по всему, что стоит перед тобой
+04:12=Стань лицом к лицу со своим врагом,|чтобы обрушить на него всю мощь|смертоносной техники боевых исскуств.|Атака: Исполнить Восходящий удар Дракона
 04:13=Не используется
-04:14=Боишься высоты? Тогда возьми парашут.|Он раскроется, как только ты начнешь слишком|долго падать, и тем самым убережет ежа|от падения с большой высоты.|Attack: Раскрыть парашут|Long Jump: Сбросить гранаты или похожее вооружение
-04:15=Вызови самолет, чтобы атаковать своих врагов|с помощью воздушной бомбардировки.|Left/Right: Определить направление атаки|Cursor: Выбрать бомбардируемую область
-04:16=Вызови самолет, чтобы сбросить несколько мин|в заданной области.|Left/Right: Определить направление атаки|Cursor: Выбрать минируемую область
-04:17=Нуждаешься в убежище? Используй паяльную|лампу, чтобы пробурить тунель в твердом грунте,|обеспечив себя крышей над головой.|Attack: Запустить или остановить бурение
-04:18=Нуждаешься в дополнительной защите|или хочешь преодолеть непреодолимую преграду?|Размести несколько поперечных балок там,|где тебе будет удобно.|Left/Right: Выбрать балку для размещения|Cursor: Разместить поперечную балку в нужной позиции
-04:19=Использование телепортации в нужный момент|времени может оказаться более полезным,|чем все имеющееся оружие, поскольку она|позволяет тебе вытаскивать ежей из опасных|ситуаций за считанные секунды.|Cursor: Выбрать место телепортации
-04:20=Позволь себе сыграть текущий ход другим ежом.|Attack: Активировать переключение ежей|Tab: Переключить ежа
-04:21=Выстрели снарядом с разделяющейся боеголовкой,|которая в результате столкновения с препятствием|расколется на несколько бомб.|Attack: Выстрелить с максимальной силой
-04:22=Эта штука не только для Индианы Джонс!|Кнут - полезное оружие во многих ситуациях.|Особенно, когда ты хочешь кого-нибудь сбросить|с крутого склона.|Attack: Нанести удар по всему, что стоит перед тобой
-04:23=Когда тебе нечего терять, эта возможность|может быть очень кстати. Пожертвуй своим ежом,|запустив его в заданном направлении. Он нанесет|урон всему на своем пути и в конце взорвется.|Attack: Запустить разрушительную и смертельную атаку
-04:24=С Днем Рождения! Запусти этот торт, дай ему|добежать до твоих врагов и организуй взрывную вечеринку.|Торт способен преодолеть практически всю территорию,|но может взорваться и раньше на этом пути.|Attack: Запустить торт или остановить его и взорвать
-04:25=Используй этот набор косметики, чтобы привлечь|к себе вражеского ежа, который пылая страстью|бросится к твоему ежу (а также в какой-нибудь|обрыв или яму).|Attack: Использовать косметику и попытаться соблазнить|другого ежа
-04:26=Брось этот сочный арбуз по своим врагам.|Когда таймер достигнет нуля он разделится|на несколько взрывоопасных арбузных корок.|1-5: Установить арбузный таймер|Attack: Удерживай для более дальнего броска
-04:27=Пролей дождь адского огня на своих|оппонентов, используя эту дьявольскую|взрывчатку. Держись подальше от взрыва,|поскольку мелкий огонь после него|будет гореть еще некоторое время.|Attack: Удерживай для более дальнего броска
-04:28=Через короткий промежуток времени после|запуска этой ракеты она начнет сверлить|твердую поверхность и взорвется как только|сработает ее плавкий предохранитель или|она высвободится на открытое пространство.|Attack: Удерживай для выстрела с большей силой
-04:29=Это штука - детям не игрушка!|Шаромет стреляет огромным количеством|маленьких шариков, заполненных взрывчаткой.|Attack: Выстрелить с максимальной силой|Up/Down: Продолжать прицельную стрельбу
-04:30=Вызови самолет для осуществления мощного|удара напалмом. При надлежащем прицеливании,|такая атака может нанести опустошительный урон|большим участкам поверхности, включая ежей,|которым не повезло оказаться не в то время,|не в том месте.|И еще... не забудь учесть направление и силу ветра.|Left/Right: Определить направление атаки|Cursor: Выбрать область для удара напалмом
-04:31=Радиоуправляемый самолет - идеальное оружие,|чтобы пополнить коллекцию старых самолетов|или атаковать далеко стоящих ежей. Направь его|прямо на своих врагов или сбрось сперва несколько|бомб.|Attack: Запусти самолет или сбрось бомбы|Long Jump: Исполнить 'Полет валькирий'|Up/Down: Направлять самолет в процессе полета
-04:32=Слабая гравитация более эффективна, чем диета!|Прыгай выше и на более дальние дистанции или|позволь своим врагам улететь еще дальше.|Attack: Включить слабую гравитацию
-04:33=Иногда тебе нужно просто немного повысить|силу своего оружия, чтобы нанести сопернику|больший урон.|Attack: Включить дополнительный урон
-04:34=Не сможете ко мне прикоснуться!|Attack: Включить неуязвимость
-04:35=Иногда кажется, что время летит слишком быстро.|Воспользуйся этими дополнительными секундами,|чтобы завершить свою атаку.|Attack: Включить дополнительное время
-04:36=Действительно, иногда ты выглядишь|просто мазилой. Воспользуйся поддержкой|современных технологий.|Attack: Включить лазерный прицел
-04:37=Не бойся дневного света. Его вред для тебя|продлится всего один ход, но позволит тебе|поглотить весь урон, который ты нанесешь|другим ежам.|Attack: Включить вампиризм
-04:38=Снайперская винтовка может быть самым|разрушительным оружием во всем твоем|арсенале, однако она очень неэффективна|на близких дистанциях. Наносимый урон|увеличивается пропорционально расстоянию|до цели.|Attack: Выстрелить (дважды)
-04:39=Летай в другие части карты на летающей тарелке.|Это сложное в освоении устройство позволит тебе|переместиться практически в любую точку на поле|битвы.|Attack: Запустить тарелку|Up/Left/Right: Приложить тягу для движения в одном|направлении (многократное нажатие)|Long Jump: Сбросить гранаты или похожее вооружение
-04:40=Вызови пожар на каком-нибудь участке|поверхности с помощью это бутылки,|заполненной горючей жидкостью.|Attack: Удерживай для более дальнего броска
-04:41=Очевидно, что живая природа может превзойти|летающую тарелку. Птичка может носить повсюду|твоего ежа и сбрасывать яйца на твоих врагов!|Attack: Запустить птичку и бросать яйца|Up/Left/Right: Хлопать крыльями для движения в одном|направлении
+04:14=Боишься высоты? Тогда возьми парашут.|Он раскроется, как только ты начнешь слишком|долго падать, и тем самым убережет ежа|от падения с большой высоты.|Атака: Раскрыть парашут|Длинный прыжок: Сбросить гранаты или похожее вооружение
+04:15=Вызови самолет, чтобы атаковать своих врагов|с помощью воздушной бомбардировки.|Влево/Вправо: Определить направление атаки|Курсор: Выбрать бомбардируемую область
+04:16=Вызови самолет, чтобы сбросить несколько мин|в заданной области.|Влево/Вправо: Определить направление атаки|Курсор: Выбрать минируемую область
+04:17=Нуждаешься в убежище? Используй паяльную|лампу, чтобы пробурить тунель в твердом грунте,|обеспечив себя крышей над головой.|Атака: Запустить или остановить бурение
+04:18=Нуждаешься в дополнительной защите|или хочешь преодолеть непреодолимую преграду?|Размести несколько поперечных балок там,|где тебе будет удобно.|Left/Right: Выбрать балку для размещения|Курсор: Разместить поперечную балку в нужной позиции
+04:19=Использование телепортации в нужный момент|времени может оказаться более полезным,|чем все имеющееся оружие, поскольку она|позволяет тебе вытаскивать ежей из опасных|ситуаций за считанные секунды.|Курсор: Выбрать место телепортации
+04:20=Позволь себе сыграть текущий ход другим ежом.|Атака: Активировать переключение ежей|Tab: Переключить ежа
+04:21=Выстрели снарядом с разделяющейся боеголовкой,|которая в результате столкновения с препятствием|расколется на несколько бомб.|Атака: Выстрелить с максимальной силой
+04:22=Эта штука не только для Индианы Джонс!|Кнут - полезное оружие во многих ситуациях.|Особенно, когда ты хочешь кого-нибудь сбросить|с крутого склона.|Атака: Нанести удар по всему, что стоит перед тобой
+04:23=Когда тебе нечего терять, эта возможность|может быть очень кстати. Пожертвуй своим ежом,|запустив его в заданном направлении. Он нанесет|урон всему на своем пути и в конце взорвется.|Атака: Запустить разрушительную и смертельную атаку
+04:24=С Днем Рождения! Запусти этот торт, дай ему|добежать до твоих врагов и организуй взрывную вечеринку.|Торт способен преодолеть практически всю территорию,|но может взорваться и раньше на этом пути.|Атака: Запустить торт или остановить его и взорвать
+04:25=Используй этот набор косметики, чтобы привлечь|к себе вражеского ежа, который пылая страстью|бросится к твоему ежу (а также в какой-нибудь|обрыв или яму).|Атака: Использовать косметику и попытаться соблазнить|другого ежа
+04:26=Брось этот сочный арбуз по своим врагам.|Когда таймер достигнет нуля он разделится|на несколько взрывоопасных арбузных корок.|1-5: Установить арбузный таймер|Атака: Удерживай для более дальнего броска
+04:27=Пролей дождь адского огня на своих|оппонентов, используя эту дьявольскую|взрывчатку. Держись подальше от взрыва,|поскольку мелкий огонь после него|будет гореть еще некоторое время.|Атака: Удерживай для более дальнего броска
+04:28=Через короткий промежуток времени после|запуска этой ракеты она начнет сверлить|твердую поверхность и взорвется как только|сработает ее плавкий предохранитель или|она высвободится на открытое пространство.|Атака: Удерживай для выстрела с большей силой
+04:29=Это штука - детям не игрушка!|Шаромет стреляет огромным количеством|маленьких шариков, заполненных взрывчаткой.|Атака: Выстрелить с максимальной силой|Вверх/Вниз: Продолжать прицельную стрельбу
+04:30=Вызови самолет для осуществления мощного|удара напалмом. При надлежащем прицеливании,|такая атака может нанести опустошительный урон|большим участкам поверхности, включая ежей,|которым не повезло оказаться не в то время,|не в том месте.|И еще... не забудь учесть направление и силу ветра.|Влево/Вправо: Определить направление атаки|Курсор: Выбрать область для удара напалмом
+04:31=Радиоуправляемый самолет - идеальное оружие,|чтобы пополнить коллекцию старых самолетов|или атаковать далеко стоящих ежей. Направь его|прямо на своих врагов или сбрось сперва несколько|бомб.|Атака: Запустить самолет или сбросить бомбы|Длинный прыжок: Исполнить 'Полет валькирий'|Вверх/Вниз: Управлять самолетом в процессе полета
+04:32=Слабая гравитация более эффективна, чем диета!|Прыгай выше и на более дальние дистанции или|позволь своим врагам улететь еще дальше.|Атака: Включить слабую гравитацию
+04:33=Иногда тебе нужно просто немного повысить|силу своего оружия, чтобы нанести сопернику|больший урон.|Атака: Включить дополнительный урон
+04:34=Не сможете меня задеть!|Атака: Включить неуязвимость
+04:35=Иногда кажется, что время летит слишком быстро.|Воспользуйся этими дополнительными секундами,|чтобы завершить свою атаку.|Атака: Включить дополнительное время
+04:36=Действительно, иногда ты выглядишь|просто мазилой. Воспользуйся поддержкой|современных технологий.|Атака: Включить лазерный прицел
+04:37=Не бойся дневного света. Его вред для тебя|продлится всего один ход, но позволит тебе|поглотить весь урон, который ты нанесешь|другим ежам.|Атака: Включить вампиризм
+04:38=Снайперская винтовка может быть самым|разрушительным оружием во всем твоем|арсенале, однако она очень неэффективна|на близких дистанциях. Наносимый урон|увеличивается пропорционально расстоянию|до цели.|Атака: Выстрелить (дважды)
+04:39=Летай в другие части карты на летающей тарелке.|Это сложное в освоении устройство позволит тебе|переместиться практически в любую точку на поле|битвы.|Атака: Запустить тарелку|Вверх/Влево/Вправо: Приложить тягу для движения|в одном направлении (многократное нажатие)|Длинный прыжок: Сбросить гранаты или похожее|вооружение
+04:40=Вызови пожар на каком-нибудь участке|поверхности с помощью этой бутылки,|заполненной горючей жидкостью.|Атака: Удерживай для более дальнего броска
+04:41=Очевидно, что живая природа может превзойти|летающую тарелку. Птичка может повсюду носить|твоего ежа и сбрасывать яйца на твоих врагов!|Атака: Запустить птичку и бросать яйца|Вверх/Влево/Вправо: Хлопать крыльями для движения в одном|направлении
+04:42=Этот портативный телепорт способен мгновенно|переместить тебя, твоих врагов, или твое вооружение|между двумя точками на местности. Используй его с умом|и твоей кампании будет сопутствовать...|ОГРОМНЫЙ УСПЕХ!|Атака: Выстрелить точкой телепорта|Переключение: Прокрутить цвета точек телепорта
+04:43=Обеспечь своему музыкальному дебюту взрывной успех!|Сбрось фортепьяно с небес, но знай... кто-то должен|играть на нем, и это может стоить тебе жизни!|Курсор: Выбрать область удара|F1-F9: Играть на фортепьяно
+04:44=Это не обычный сыр, это война с применением|биологического оружия! Сыр не причинит большого|урона сразу, как только таймер достигнет нуля.|Но он будет постоянно отравлять любого,|кто имел неудачу вдохнуть зловоние!|1-5: Установить таймер гранаты|Атака: Удерживай для более дальнего броска
+04:45=Все те уроки физики, что были, наконец окупились|запуском разрушительной Синус-волны|по твоим врагам.|Будь осторожен, это оружие наносит серийный удар.|(Разработка этого оружия еще не завершена)|Атака: Выстрелить
+04:46=Накрой своих врагов испепеляющим жидким|пламенем. С самыми теплыми чувствами!|Атака: Активировать|Вверх/Вниз: Продолжать прицельный полив|Влево/Вправо: Изменить силу (дальность) полива
+04:47=Удвой веселье с двумя шипованными, коварными,|липучими минами. Устрой цепную реакцию или|защити себя (или то и другое!)|Атака: Удерживай для более дальнего броска|(дважды)
+04:48=Почему кротам достаются все оскорбления?|Вакингующий ёж может быть столь забавным!|Хороший удар этого молота сбреет треть|здоровья ежа и погрузит его в землю.|Атака: Ударить молотом
+04:49=Воскреси своих друзей!|Но будь осторожен, т.к. оно также воскресит|твоих врагов.|Атака: Удерживай атаку нажатой для медленного|воскрешения|Вверх: Ускорить воскрешение
 
 ; Game goal strings
 05:00=Режимы игры
@@ -301,3 +512,10 @@
 05:13=Таймер мины: мины детонируют мгновенно
 05:14=Таймер мины: мины детонируют после 0 - 3 секунд
 05:15=Изменение уровня урона: всё оружие наносит %1% урона
+05:16=Здоровье всех ежей восстановится в конце хода
+05:17=Ежи ИИ возрождаются в момент гибели
+05:18=Неограниченное количество атак
+05:19=Оружие восстановится в конце хода
+05:20=Ежи не имеют общего оружия
+05:21=Признак команды: Команды в клане ходят последовательно|Общее время: Команды в клане имеют общее время хода
+
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/share/hedgewars/Data/Missions/Training/User_Mission_-_That_Sinking_Feeling.lua	Thu Jun 23 21:19:43 2011 +0400
@@ -0,0 +1,244 @@
+
+
+loadfile(GetDataPath() .. "Scripts/Locale.lua")()
+
+local player
+local hh = {}
+local hhCount = 8
+local GameOver = false
+local introStage = 0
+local genCounter = 0
+local waterCounter = 0
+local waterPix = 0
+
+-- allow skipping of the intro via hitting precise key
+function onPrecise()
+	if introStage < 100 then
+		introStage = 110
+		genCounter = 0
+		FollowGear(CurrentHedgehog)
+		AddCaption(loc("Good luck out there!"))
+		ShowMission(loc("That Sinking Feeling"), loc("User Challenge"), loc("Save as many hapless hogs as possible!"), 4, 0)
+	end
+end
+
+function onGameInit()
+
+	Seed = 0
+	GameFlags = gfInfAttack + gfInvulnerable
+	TurnTime = 90000
+	CaseFreq = 0
+	MinesNum = 0
+	MinesTime  = 3000
+	Explosives = 0
+	Delay = 10
+	Map = "Islands"
+	Theme = "City"
+
+	AddTeam(loc("Nameless Heroes"), 14483456, "Simple", "Island", "Default")
+	player = AddHog(loc("The Nameless One"), 0, 1, "NoHat")
+
+	AddTeam(loc("Hapless Hogs"), 	1175851, "Simple", "Island", "Default")
+	hh[0] = AddHog(loc("Sinky"), 1, 100, "lemon")
+	hh[1] = AddHog(loc("Drowner"), 1, 100, "orange")
+	hh[2] = AddHog(loc("Heavy"), 1, 100, "Teapot")
+	hh[3] = AddHog(loc("Clumsy"), 1, 100, "SauceBoatSilver")
+	hh[4] = AddHog(loc("Silly"), 1, 100, "Ladle")
+	hh[5] = AddHog(loc("Careless"), 1, 100, "StrawHatEyes")
+	hh[6] = AddHog(loc("Sponge"), 1, 100, "Chunli")
+	hh[7] = AddHog(loc("Deadweight"), 1, 100, "Teacup")
+
+	SetGearPosition(player, 3992, 733)
+	SetGearPosition(hh[0], 938, 1369)
+	SetGearPosition(hh[1], 1301, 1439)
+	SetGearPosition(hh[2], 2093, 447)
+	SetGearPosition(hh[3], 2971, 926)
+	SetGearPosition(hh[4], 719, 545)
+	SetGearPosition(hh[5], 1630, 821)
+	SetGearPosition(hh[6], 2191, 810)
+	SetGearPosition(hh[7], 3799, 945)
+
+end
+
+
+function onGameStart()
+
+	ShowMission(loc("That Sinking Feeling"), loc("User Challenge"), loc("Save as many hapless hogs as possible!"), 4, 1)
+
+	HogTurnLeft(hh[0], false)
+	HogTurnLeft(hh[1], true)
+
+	SpawnUtilityCrate(148,265,amLowGravity)
+	SpawnUtilityCrate(2124,1516,amJetpack)
+
+end
+
+
+function onNewTurn()
+	TurnTimeLeft = -1
+end
+
+function onGameTick()
+
+	-- intro sequence
+	if introStage < 100 then
+
+		AddCaption(loc("Press [Precise] to skip intro"))
+
+		genCounter = genCounter + 1
+
+		if introStage == 0 then
+
+			FollowGear(hh[0])
+
+			if genCounter == 2000 then
+				HogSay(hh[0], loc("This rain is really something..."), SAY_SAY,2)
+			elseif genCounter == 5000 then
+				introStage = 1
+				genCounter = 0
+			end
+
+		elseif introStage == 1 then
+
+			FollowGear(hh[1])
+
+			if genCounter == 2000 then
+				HogSay(hh[1], loc("Heh, it's not that bad."), SAY_SAY,2)
+			elseif genCounter == 5000 then
+				introStage = 2
+				genCounter = 0
+			end
+
+		elseif introStage == 2 then
+
+			FollowGear(hh[0])
+
+			if genCounter == 2000 then
+				HogSay(hh[0], loc("You'd almost swear the water was rising!"), SAY_SHOUT,2)
+			elseif genCounter == 6000 then
+				introStage = 3
+				genCounter = 0
+			end
+
+		elseif introStage == 3 then
+
+			FollowGear(hh[1])
+
+			if genCounter == 2000 then
+				HogSay(hh[1], loc("Haha, now THAT would be something!"), SAY_SAY,2)
+			elseif genCounter == 6000 then
+				introStage = 4
+				genCounter = 0
+			end
+
+		elseif introStage == 4 then
+
+			FollowGear(hh[0])
+
+			if genCounter == 2000 then
+				HogSay(hh[0], loc("Hahahaha!"), SAY_SHOUT,2)
+				HogSay(hh[1], loc("Hahahaha!"), SAY_SHOUT,2)
+			elseif genCounter == 3000 then
+				introStage = 5
+				genCounter = 0
+			end
+
+		elseif introStage == 5 then
+
+			FollowGear(hh[1])
+
+			if genCounter == 2000 then
+				HogSay(hh[0], loc("..."), SAY_THINK,2)
+				HogSay(hh[1], loc("..."), SAY_THINK,2)
+			elseif genCounter == 5000 then
+				introStage = 6
+				genCounter = 0
+			end
+
+		elseif introStage == 6 then
+
+			FollowGear(hh[0])
+
+			if genCounter == 2000 then
+				HogSay(hh[0], loc("It's a good thing SUDDEN DEATH is 99 turns away..."), SAY_THINK,2)
+			elseif genCounter == 6000 then
+				introStage = 7
+				genCounter = 0
+			end
+
+
+		elseif introStage == 7 then
+
+			if genCounter == 2000 then
+				introStage = 110
+				FollowGear(CurrentHedgehog)
+				ShowMission(loc("That Sinking Feeling"), loc("User Challenge"), loc("Save as many hapless hogs as possible!"), 4, 0)
+			end
+
+		end
+
+	end
+
+	-- start the water rising when the intro is finished
+	if introStage == 110 then
+
+		waterCounter = waterCounter + 1
+		if (waterCounter == 100) and (waterPix < 1615) then
+			waterCounter = 0
+			SetTag(AddGear(0, 0, gtWaterUp, 0, 0, 0, 0), 1)
+			waterPix = waterPix +1
+			--AddCaption(waterPix)
+
+			if (waterPix >= 1615) and (GameOver == false) then
+				GameOver = true
+				SetHealth(player, 0)
+				TurnTimeLeft = 1
+				ShowMission(loc("That Sinking Feeling"), loc("MISSION SUCCESS"), loc("You saved") .. " " .. hhCount .. " " .. loc("Hapless Hogs") .."!", 0, 0)
+			end
+
+		end
+
+	end
+
+	if TurnTimeLeft == 1 then
+		SetHealth(player, 0)
+	end
+
+end
+
+
+function onAmmoStoreInit()
+
+	SetAmmo(amBazooka, 9, 0, 0, 0)
+
+	SetAmmo(amRope, 9, 0, 0, 0)
+	SetAmmo(amParachute, 9, 0, 0, 0)
+	SetAmmo(amJetpack, 2, 0, 0, 2)
+
+	SetAmmo(amGirder, 9, 0, 0, 0)
+	SetAmmo(amBaseballBat, 9, 0, 0, 0)
+
+	SetAmmo(amTeleport, 1, 0, 0, 1)
+	SetAmmo(amPortalGun, 3, 0, 0, 1)
+
+	SetAmmo(amLowGravity, 0, 0, 0, 1)
+
+end
+
+function onGearDelete(gear)
+
+	if GetGearType(gear) == gtHedgehog then
+		if GetHogTeamName(gear) == "Hapless Hogs" then
+			hhCount = hhCount - 1
+			AddCaption(hhCount .. loc(" Hapless Hogs left!"))
+		end
+	end
+
+	if ((gear == player) or (hhCount == 0)) and (GameOver == false) then
+		SetHealth(player, 0)
+		TurnTimeLeft = 1
+		ShowMission(loc("That Sinking Feeling"), loc("MISSION FAILED"), loc("Oh no! Just try again!"), -amSkip, 0)
+		GameOver = true
+	end
+
+end
--- a/share/hedgewars/Data/Scripts/Multiplayer/Capture_the_Flag.lua	Tue Jun 21 16:43:05 2011 +0400
+++ b/share/hedgewars/Data/Scripts/Multiplayer/Capture_the_Flag.lua	Thu Jun 23 21:19:43 2011 +0400
@@ -1,7 +1,7 @@
---------------------------------
--- CAPTURE_THE_FLAG_CUSTOM 0.3
+---------------------------------------
+-- CAPTURE_THE_FLAG GAMEPLAY MODE 0.4
 -- by mikade
---------------------------------
+---------------------------------------
 
 -- Version History
 ---------
@@ -50,6 +50,17 @@
 -- added a check to make sure the player doesn't kamikaze straight down and make the flag's starting point underwater
 -- added a check to make sure the player drops the flag if he has it and he uses kamikaze
 
+--------
+-- 0.4
+--------
+
+-- remove user-branding and version numbers
+-- removed some stuff that wasn't needed
+-- fix piano strike exploit
+-- changed delay to allow for better portals
+-- changed starting feedback a little
+-- increased the radius around the circle indicating the flag thief so that it doesn't obscure his health
+
 -----------------
 --SCRIPT BEGINS
 -----------------
@@ -188,10 +199,6 @@
 		end
 		AddCaption(loc("Flag captured!"))
 
-	--below line doesnt usually get called
-	--else 
-		-- now gets called if you go over your own flag, presumably		
-		--AddCaption("Hmm... that wasn't supposed to happen...")
 	end
 	
 end
@@ -227,7 +234,7 @@
 			fGear[i] = AddVisualGear(fSpawnX[i],fSpawnY[i],vgtCircle,0,true)
 			fGearX[i] = fSpawnX[i]
 			fGearY[i] = fSpawnY[i]			
-			--fGear[i] = SpawnAmmoCrate(fSpawnX[i],fSpawnY[i],amSkip)
+
 			fNeedsRespawn[i] = false
 			fIsMissing[i] = false -- new, this should solve problems of a respawned flag being "returned" when a player tries to score
 			AddCaption(loc("Flag respawned!"))
@@ -255,12 +262,10 @@
 			fIsMissing[wtf] = true
 			fNeedsRespawn[wtf] = true
 			HandleRespawns()
-			--AddCaption("hah??")
 		else	--normally	
 			fGearX[wtf]  =  fThiefX[wtf]
 			fGearY[wtf]  =  fThiefY[wtf]	
 			fGear[wtf] = AddVisualGear(fGearX[wtf],fGearY[wtf],vgtCircle,0,true)		
-			--fGear[wtf] = AddVisualGear(fThiefX[wtf],fThiefY[wtf],vgtCircle,0,true)
 		end
 
 		AddVisualGear(fThiefX[wtf], fThiefY[wtf], vgtBigExplosion, 0, false)
@@ -290,8 +295,8 @@
 				SetVisualGearValues(fGear[i], fSpawnX[i],fSpawnY[i], 20, 200, 0, 0, 100, fGearRad, 2, fCol[i])
 			end
 		elseif (fIsMissing[i] == true) and (fNeedsRespawn[i] == false) then
-			if fThief[i] ~= nil then -- draw circle round flag carrier
-				SetVisualGearValues(fCirc[i], fThiefX[i], fThiefY[i], 20, 200, 0, 0, 100, 33, 3, fCol[i])
+			if fThief[i] ~= nil then -- draw circle round flag carrier			-- 33
+				SetVisualGearValues(fCirc[i], fThiefX[i], fThiefY[i], 20, 200, 0, 0, 100, 50, 3, fCol[i])
 				--AddCaption("circle marking carrier")
 			elseif fThief[i] == nil then -- draw cirle round dropped flag
 				--g1X,g1Y,g4,g5,g6,g7,g8,g9,g10,g11 =  GetVisualGearValues(fGear[i])				
@@ -419,8 +424,6 @@
 		--SetVisualGearValues(zxc, 1000,1000, 20, 100, 0,    10,                     1,         100,        5,      GetClanColor(0))		
 		
 		SetVisualGearValues(fSpawnC[i], fSpawnX[i],fSpawnY[i], 20, 100, 0, 10, 0, 75, 5, fCol[i])
-		--SetVisualGearValues(fCirc[i], fSpawnX[i],fSpawnY[i], 20, 20, 0, 10, 0, 33, 3, fCol[i])
-
 				
 	end
 
@@ -432,12 +435,9 @@
 
 function onGameInit()
 
-	-- Things we don't modify here will use their default values.
-	
 	GameFlags = band(bor(GameFlags, gfDivideTeams), bnot(gfKing + gfForts))
-	SuddenDeathTurns = 99 -- suddendeath is off, effectively
-	--TurnTime = 30000 -- (was 30) The time the player has to move each round (in ms)
-	--Delay = 10 -- The delay between each round
+	SuddenDeathTurns = 999 -- suddendeath is off, effectively
+	Delay = 10 
 
 end
 
@@ -445,7 +445,7 @@
 function onGameStart()
 
 	--ShowMission(loc(caption), loc(subcaption), loc(goal), 0, 0)
-	ShowMission(loc("CAPTURE THE FLAG"), loc("by mikade"), loc("CUSTOM BUILD 0.2"), 0, 0)
+	ShowMission(loc("CAPTURE THE FLAG"), loc("Flags, and their home base will be placed where each team ends their first turn."), "", 0, 0)
 
 	RebuildTeamInfo()
 	
@@ -484,7 +484,7 @@
 		HandleRespawns()
 	--new method of placing starting flags	
 	elseif gameTurns == 1 then
-		ShowMission(loc("CAPTURE THE FLAG"), loc("Flags will be placed where each team ends their turn."), "", 0, 0)
+		ShowMission(loc("CAPTURE THE FLAG"), loc("Flags, and their home base will be placed where each team ends their first turn."), "", 0, 0)
 	elseif gameTurns == 2 then
 		fPlaced[0] = true
 		ShowMission(loc("CAPTURE THE FLAG"), loc("RULES OF THE GAME [Press ESC to view]"), loc(" - Return the enemy flag to your base to score | - First team to 3 captures wins | - You may only score when your flag is in your base | - Hogs will drop the flag if killed, or drowned | - Dropped flags may be returned or recaptured | - Hogs respawn when killed"), 0, 0)
@@ -562,16 +562,21 @@
 
 end
 
-function onGearDamage(gear, damage)
---
-end
-
 function onGearAdd(gear)
 
 	if GetGearType(gear) == gtHedgehog then
 		hhs[numhhs] = gear
 		numhhs = numhhs + 1
 		SetEffect(gear, heResurrectable, true)
+	
+	elseif GetGearType(gear) == gtPiano then
+
+		for i = 0, 1 do
+			if CurrentHedgehog == fThief[i] then
+				FlagThiefDead(gear)			
+			end
+		end
+
 	end
 
 end
@@ -579,7 +584,6 @@
 function onGearDelete(gear)
 
 	if GetGearType(gear) == gtHedgehog then
-	--AddCaption("gear deleted!")
 		for i = 0, (numhhs-1) do
 			if gear == hhs[i] then
 				
@@ -588,8 +592,7 @@
 						FlagThiefDead(gear)
 					end
 				end				
-				hhs[i] = nil
-				--AddCaption("for real")	
+				hhs[i] = nil	
 			end		
 		end
 	end
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/share/hedgewars/Data/Scripts/Multiplayer/Space_Invasion.cfg	Thu Jun 23 21:19:43 2011 +0400
@@ -0,0 +1,2 @@
+Default
+Default
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/share/hedgewars/Data/Scripts/Multiplayer/Space_Invasion.lua	Thu Jun 23 21:19:43 2011 +0400
@@ -0,0 +1,1886 @@
+
+loadfile(GetDataPath() .. "Scripts/Locale.lua")()
+loadfile(GetDataPath() .. "Scripts/Tracker.lua")()
+
+---------------------------------------------------
+---------------------------------------------------
+---------------------------------------------------
+--- Space Invasion Code Follows (0.7)
+---------------------------------------------------
+---------------------------------------------------
+-- VERSION HISTORY
+----------------
+-- version 0.1
+----------------
+-- conversion of tumbler into space invasion
+-- a million and one changes
+-- bells and whistles
+
+----------------
+-- version 0.2
+----------------
+-- code slowly getting cleaner, it still looks like a spaghetti monster tho
+-- lots of console tracking :/
+-- all visual gears are now compulsary (will probably revert this)
+-- implemented fMod to try combat desyncs and bring this in line with dev
+
+----------------
+-- version 0.3
+----------------
+-- values of scoring changed to 3:10, and now based on vCircScore
+-- time gained from killing a red circ increased from 3 to 4
+-- circles now spawn at a distance of at least 800 or until sanity limit
+-- roundsLimit now based off MinesTime (kinda, its an experiment)
+
+-----------------
+--0.4
+-----------------
+-- commented out a lot of WriteLnToConsoles (dont need them at this point)
+-- added some different WriteLnToConsoles
+-- changed some of the collision detect for explosives in checkvarious()
+
+-----------------
+--0.5
+-----------------
+-- added implementation for a projectile shield
+-- added a "bonus" orange invader that partially recharges player shield
+-- added a tough "blueboss" blue invader
+-- expanded user feedback
+-- circles now have health and are capable of being merely "damaged"
+-- redid a lot of the collision code and added CircleDamaged
+-- added more sounds to events
+-- added more visual gears
+
+-----------------
+--0.6
+-----------------
+-- removed a few WriteLns
+-- added randomized grunts on circ damage
+-- added (mostly) graceful fading out of circles :D:
+-- changed odds for circles
+-- changed user feedback
+-- fixed the location of the explosion where player bashes into circ
+
+-----------------
+--0.7
+-----------------
+-- added PlaySound(sndSuddenDeath) when ammo gets depleted
+-- added an extra "Ammo Depleted" note if user presses fire while empty
+-- specified how much shield power is gained on shield powerup collection
+-- changed odds for circles AGAIN, ammo is now sliiightly more common
+-- switched most of the explosions/smoke effects back to non-critical vgears (with a few exceptions)
+-- tumbletime is now based off turntime and is variable
+-- delete explosives in DeleteFarFlungBarrel rather than explode them on map boundaries to save on performance
+-- utilized the improved AddCaption to tint / prevent overrides
+-- temporarily disabled bugged sort that displays teams according to their score
+-- reluctantly changed the colour of the bonus circ to purple 
+-- standarized point notation
+-- added some missing locs
+-- commented out remaining WriteLnToConsoles for the meanwhile with the prefix "nw"
+
+-- ACHIEIVEMENTS added
+-- (during one turn) aka repeatable
+-- Ammo Manic (Destroy 3 green circles for + 5 points)
+-- Drone Hunter (Destroy 5 red circles for + 10 points)
+-- Shield Seeker (Destroy 3 purple circles for +10 points)
+-- Boss Slayer (Destroy 2 blue circles for +25 points)
+
+-- Shield Master (disolve 5 shells for +10 points)
+-- Shield Miser (don't use your shield at all +20 points)
+
+-- Depleted Kamikaze! (kamikaze into a blue/red circ when you are out of ammo) 5pts
+-- Timed Kamikaze! (kamikaze into a blue/red circ when you only have 5s left) 10pts
+-- Kamikaze Expert (combination of the above two) 15pts
+
+-- Multi-shot (destroy more than 1 invader with a single bullet) 5pts
+-- X-Hit Combo (destroy another invader in less than 3 seconds) chainLength*2 points
+
+-- Accuracy Bonus (80% accuracy at the end of your turn with more than 5 shots fired) 15pts
+
+--(during the length of the game) aka non-repeatable
+-- 10/25/50 kills (+25/+50/+100 points)
+
+--------------------------
+--notes for later
+--------------------------
+-- maybe add a check for a tie, NAH
+-- more achievements? (3 kamikazes in a row, long distance shooter, supreme shield expert/miser etc?)
+
+--[[CAPTION CATEGORIES
+-----------------
+capgrpGameState
+-----------------
+
+-----------------
+capgrpAmmostate
+-----------------
+AddCaption( chainLength .. loc("-chain! +") .. chainLength*2 .. loc(" points!"),0xffba00ff,capgrpAmmostate)
+AddCaption(loc("Multi-shot! +5 points!"),0xffba00ff,capgrpAmmostate) 
+
+-----------------
+capgrpAmmoinfo
+-----------------
+AddCaption(loc("Shield Miser! +20 points!"),0xffba00ff,capgrpAmmoinfo)
+AddCaption(loc("Shield Master! +10 points!"),0xffba00ff,capgrpAmmoinfo)
+
+-----------------
+capgrpVolume
+-----------------
+AddCaption(loc("Boom! +25 points!"),0xffba00ff,capgrpVolume)
+AddCaption(loc("BOOM! +50 points!"),0xffba00ff,capgrpVolume)
+AddCaption(loc("BOOM! BOOM! BOOM! +100 points!"),0xffba00ff,capgrpVolume)
+AddCaption(loc("Accuracy Bonus! +15 points!"),0xffba00ff,capgrpVolume)
+
+-----------------
+capgrpMessage 
+-----------------
+AddCaption(loc("Ammo Depleted!"),0xff0000ff,capgrpMessage)
+AddCaption(loc("Ammo: ") .. primShotsLeft)
+AddCaption("Shield Depleted",0xff0000ff,capgrpMessage)
+AddCaption( loc("Shield ON:") .. " " .. shieldHealth - 80 .. " " .. loc("Power Remaining") )
+AddCaption(loc("Shield OFF:") .. " " .. shieldHealth - 80 .. " " .. loc("Power Remaining") )
+
+AddCaption(loc("Time Extended!") .. "+" .. 4 .. loc("s"), 0xff0000ff,capgrpMessage )
+AddCaption("+" .. 3 .. " " .. loc("Ammo"), 0x00ff00ff,capgrpMessage)
+AddCaption(loc("Shield boosted! +30 power"), 0xff00ffff,capgrpMessage)
+AddCaption(loc("Shield is fully recharged!"), 0xffae00ff,capgrpMessage)
+AddCaption(loc("Boss defeated! +50 points!"), 0x0050ffff,capgrpMessage)
+
+AddCaption(loc("GOTCHA!"))
+AddCaption(loc("Kamikaze Expert! +15 points!"),0xffba00ff,capgrpMessage)
+AddCaption(loc("Depleted Kamikaze! +5 points!"),0xffba00ff,capgrpMessage)
+AddCaption(loc("Timed Kamikaze! +10 points!"),0xffba00ff,capgrpMessage)
+
+-----------------
+capgrpMessage2 
+-----------------
+AddCaption(loc("Drone Hunter! +10 points!"),0xffba00ff,capgrpMessage2)
+AddCaption(loc("Ammo Maniac! +5 points!"),0xffba00ff,capgrpMessage2)
+AddCaption(loc("Shield Seeker! +10 points!"),0xffba00ff,capgrpMessage2)
+AddCaption(loc("Boss Slayer! +25 points!"),0xffba00ff,capgrpMessage2)
+]]
+
+----------------------------------
+-- so I herd u liek wariables
+----------------------------------
+
+--local fMod = 1	-- for use in .15 single player only, otherwise desync
+local fMod = 1000000 -- use this for dev and .16+ games
+
+-- some console stuff
+local shellID = 0
+local explosivesID = 0
+local luaGameTicks = 0
+
+-- gaudyRacer
+local roundLimit = 3	-- no longer set here (see version history)
+local roundNumber = 0
+local firstClan = 10
+local gameOver = false
+local gameBegun = false
+
+local bestClan = 10
+local bestScore = 0
+local sdScore = {}
+local sdName = {}
+local sdKills = {}
+
+--------------------------
+-- hog and team tracking variales
+--------------------------
+
+local numhhs = 0
+local hhs = {}
+
+local numTeams
+local teamNameArr = {}
+local teamClan = {}
+local teamSize = {}
+local teamIndex = {}
+
+local teamComment = {}
+local teamScore = {}
+local teamCircsKilled = {}
+
+-- stats variables
+--local teamRed = {}
+--local teamBlue = {}
+--local teamOrange = {}
+--local teamGreen = {}
+local RK = 0
+local GK = 0
+local BK = 0
+local OK = 0
+local SK = 0
+local shieldMiser = true
+local chainCounter = 0
+local chainLength = 0 
+local shotsFired = 0
+local shotsHit = 0
+
+---------------------
+-- tumbler goods
+---------------------
+
+local moveTimer = 0
+local leftOn = false
+local rightOn = false
+local upOn = false
+local downOn = false
+
+local primShotsMax = 5
+local primShotsLeft = 0
+
+local TimeLeftCounter = 0
+local TimeLeft = 0
+local stopMovement = false
+local tumbleStarted = false
+
+local beam = false
+local pShield
+local shieldHealth
+
+local Timer100 = 0
+
+
+-----------------------------------------------
+-- CIRCLY GOODIES
+-----------------------------------------------
+
+local CirclesAreGo = false
+local playerIsFine = true
+local targetHit = false
+
+local FadeAlpha = 0 -- used to fade the circles out gracefully when player dies
+local pTimer = 0 -- tracking projectiles following player
+
+local circAdjustTimer = 0		-- handle adjustment of circs direction
+local m2Count = 0		-- handle speed of circs
+
+local vCirc = {}
+local vCCount = 0
+
+local vCircActive = {}
+local vCircHealth = {}
+local vType = {}
+local vCounter = {}		-- how often this circ gets to "fire" etc
+local vCounterLim = {} -- when vCounter == vCounterLim circle performs its special
+local vCircScore = {} -- how many points killing this invader gives
+
+local vCircRadMax = {}
+local vCircRadMin = {}
+local vCircRadDir = {}
+local vCircRadCounter = {}
+
+local vCircDX = {}
+local vCircDY = {}
+
+local vCircX = {}
+local vCircY = {}
+local vCircMinA = {}
+local vCircMaxA = {}
+local vCircType = {}
+local vCircPulse = {}
+local vCircFuckAll = {}
+local vCircRadius = {}
+local vCircWidth = {}
+local vCircCol = {}
+
+-------------------------------------------
+-- some lazy copypasta/modified methods
+-------------------------------------------
+
+function RebuildTeamInfo()
+
+	-- make a list of individual team names
+	for i = 0, (TeamsCount-1) do
+		teamNameArr[i] = " " -- = i
+		teamSize[i] = 0
+		teamIndex[i] = 0
+		teamScore[i] = 0
+		teamCircsKilled[i] = 0
+	end
+	numTeams = 0
+
+	for i = 0, (numhhs-1) do
+
+		z = 0
+		unfinished = true
+		while(unfinished == true) do
+
+			newTeam = true
+			tempHogTeamName = GetHogTeamName(hhs[i]) -- this is the new name
+
+			if tempHogTeamName == teamNameArr[z] then
+				newTeam = false
+				unfinished = false
+			end
+
+			z = z + 1
+
+			if z == (TeamsCount-1) then
+				unfinished = false
+				if newTeam == true then
+					teamNameArr[numTeams] = tempHogTeamName
+					numTeams = numTeams + 1
+				end
+			end
+
+		end
+
+	end
+
+	-- find out how many hogs per team, and the index of the first hog in hhs
+	for i = 0, (TeamsCount-1) do
+
+		for z = 0, (numhhs-1) do
+			if GetHogTeamName(hhs[z]) == teamNameArr[i] then
+				teamClan[i] = GetHogClan(hhs[z])
+				if teamSize[i] == 0 then
+					teamIndex[i] = z -- should give starting index
+				end
+				teamSize[i] = teamSize[i] + 1
+				--add a pointer so this hog appears at i in hhs
+			end
+		end
+
+	end
+
+end
+
+-- control
+function AwardPoints(p)
+
+	for i = 0,(TeamsCount-1) do
+		if teamClan[i] == GetHogClan(CurrentHedgehog) then
+			teamScore[i] = teamScore[i] + p
+		end
+	end
+
+end
+
+function AwardKills(t)
+
+	for i = 0,(TeamsCount-1) do
+		if teamClan[i] == GetHogClan(CurrentHedgehog) then
+			teamCircsKilled[i] = teamCircsKilled[i] + 1
+
+			if teamCircsKilled[i] == 10 then
+				AddCaption(loc("Boom! +25 points!"),0xffba00ff,capgrpVolume)
+				AwardPoints(25)
+			elseif teamCircsKilled[i] == 25 then
+				AddCaption(loc("BOOM! +50 points!"),0xffba00ff,capgrpVolume)
+				AwardPoints(50)
+			elseif teamCircsKilled[i] == 50 then
+				AddCaption(loc("BOOM! BOOM! BOOM! +100 points!"),0xffba00ff,capgrpVolume)
+				AwardPoints(100)
+			end
+
+			--[[
+			if t == "R" then
+				redCircsKilled[i] = redCircsKilled[i] + 1
+			end
+			--etc
+			--etc
+			]]
+		end
+	end
+
+end
+
+-----------------
+
+function bubbleSort(table)
+
+	for i = 1, #table do
+        for j = 2, #table do
+            if table[j] < table[j-1] then
+
+				temp = table[j-1]
+				t2 = sdName[j-1]
+				t3 = sdKills[j-1]
+
+				table[j-1] = table[j]
+                sdName[j-1] = sdName[j]
+				sdKills[j-1] = sdKills[j]
+
+				table[j] = temp
+				sdName[j] = t2
+				sdKills[j] = t3
+
+            end
+        end
+    end
+
+    return
+
+end
+
+-----------------
+
+function CommentOnScore()
+
+	for i = 0,(TeamsCount-1) do
+		sdScore[i] = teamScore[i]
+		sdKills[i] = teamCircsKilled[i]
+		sdName[i] = teamNameArr[i]
+	end
+
+	--bubbleSort(sdScore)
+
+	for i = 0,(TeamsCount-1) do
+		if sdName[i] ~= " " then
+			teamComment[i] = sdName[i] .. " |" ..
+			loc("SCORE: ") .. sdScore[i] .. loc (" points|") ..
+			loc("KILLS: ") .. sdKills[i] .. loc (" invaders destroyed|") ..
+			" " .. "|"
+		elseif sdName[i] == " " then
+			teamComment[i] = "|"
+		end
+	end
+
+	entireC = ""
+	for i = (TeamsCount-1),0,-1 do
+		entireC = entireC .. teamComment[i]
+	end
+
+	ShowMission(loc("SPACE INVASION"), loc("STATUS UPDATE"), loc("Rounds Complete: ") .. roundNumber .. "/" .. roundLimit .. "|" .. " " .. "|" .. loc("Team Scores: ") .. "|" ..entireC, 4, 1)
+
+end
+
+-- gaudy racer
+function CheckForNewRound()
+
+	if GetHogClan(CurrentHedgehog) == firstClan then
+
+		roundNumber = roundNumber + 1
+
+		CommentOnScore()
+
+		-- end game if its at round limit
+		if roundNumber == roundLimit then
+
+			for i = 0, (TeamsCount-1) do
+				if teamScore[i] > bestScore then
+					bestScore = teamScore[i]
+					bestClan = teamClan[i]
+				end
+			end
+
+			for i = 0, (numhhs-1) do
+				if GetHogClan(hhs[i]) ~= bestClan then
+					SetEffect(hhs[i], heResurrectable, false)
+					SetHealth(hhs[i],0)
+				end
+			end
+			gameOver = true
+			TurnTimeLeft = 0	--1
+			TimeLeft = 0
+		end
+
+	end
+
+end
+
+
+----------------------------------------
+-- some tumbler/space invaders methods
+----------------------------------------
+
+function isATrackedGear(gear)
+	if 	(GetGearType(gear) == gtExplosives) or
+		(GetGearType(gear) == gtShell) or
+		(GetGearType(gear) == gtFlame) or-- new -- gtBall
+		(GetGearType(gear) == gtBall)
+	then
+		return(true)
+	else
+		return(false)
+	end
+end
+
+function setNewGearValues(gear)
+
+	if GetGearType(gear) == gtShell then
+		lfs = 50	-- roughly 5 seconds
+		shellID = shellID + 1
+		setGearValue(gear,"ID",shellID)
+		--nw WriteLnToConsole("Just assigned ID " .. getGearValue(gear,"ID") .. " to this shell")
+	elseif GetGearType(gear) == gtBall then
+		lfs = 70	-- 7s
+	elseif GetGearType(gear) == gtExplosives then
+		lfs = 15	-- 1.5s
+		explosivesID = explosivesID + 1
+		setGearValue(gear,"ID",explosivesID)
+		--nw WriteLnToConsole("Just assigned ID " .. getGearValue(gear,"ID") .. " to this explosives")
+	elseif GetGearType(gear) == gtFlame then
+		lfs = 5	-- 0.5s
+	else
+		lfs = 100
+	end
+
+	setGearValue(gear,"lifespan",lfs)
+	--WriteLnToConsole("I also set its lifespan to " .. lfs)
+
+
+end
+
+function HandleLifeSpan(gear)
+
+	decreaseGearValue(gear,"lifespan")
+
+	--WriteLnToConsole("Just decreased the lifespan of a gear to " .. getGearValue(gear,"lifespan"))
+	--WriteLnToConsole("The above event occured game Time: " .. GameTime .. "; luaTicks: " .. luaGameTicks)
+
+
+	if getGearValue(gear,"lifespan") == 0 then
+
+		if GetGearType(gear) == gtShell then
+			AddVisualGear(GetX(gear), GetY(gear), vgtExplosion, 0, false)
+			WriteLnToConsole("about to delete a shell due to lifespan == 0")
+		--elseif GetGearType(gear) == gtBall then
+		--	AddVisualGear(GetX(gear), GetY(gear), vgtSmoke, 0, true)
+		elseif GetGearType(gear) == gtExplosives then
+			AddVisualGear(GetX(gear), GetY(gear), vgtBigExplosion, 0, false)
+			--nw WriteLnToConsole("about to delete a explosive due to lifespan == 0")
+		elseif GetGearType(gear) == gtFlame then
+			AddVisualGear(GetX(gear), GetY(gear), vgtSmoke, 0, false)
+			--WriteLnToConsole("about to delete flame due to lifespan == 0")
+		end
+
+		DeleteGear(gear)
+
+	end
+
+end
+
+-- this prevents ugly barrel clipping sounds when a barrel flies off map limits
+function DeleteFarFlungBarrel(gear)
+
+	if GetGearType(gear) == gtExplosives then
+		if 	(GetX(gear) < -1900) or
+			(GetX(gear) > 6200) or
+			(GetY(gear) < -3400)
+		then
+			AddVisualGear(GetX(gear), GetY(gear), vgtBigExplosion, 0, false)			
+			DeleteGear(gear)			
+			--SetHealth(gear, 0)
+			--WriteLnToConsole("I'm setting barrel ID " .. getGearValue(gear,"ID") .. " to 0 health because it's been flung too close to the map edges. at Game Time: " .. GameTime .. "; luaTicks: " .. luaGameTicks)
+		end
+
+	end
+
+end
+
+-----------------------
+--EVENT HANDLERS
+-- action keys
+-----------------------
+
+-- o rite dis wan iz liek synched n stuff hope full lee
+function onPrecise()
+
+	--WriteLnToConsole("onPrecise event handler at Game Time: " .. GameTime .. "; luaTicks: " .. luaGameTicks)
+
+	-- Fire Barrel
+	if (primShotsLeft > 0) and (CurrentHedgehog ~= nil) and (stopMovement == false) and (tumbleStarted == true) then
+
+		shotsFired = shotsFired +1		
+		
+		morte = AddGear(GetX(CurrentHedgehog), GetY(CurrentHedgehog), gtExplosives, 0, 0, 0, 1)
+
+		primShotsLeft = primShotsLeft - 1
+
+		if primShotsLeft == 0 then
+			PlaySound(sndSuddenDeath)
+			AddCaption(loc("Ammo Depleted!"),0xff0000ff,capgrpMessage)
+		else
+			AddCaption(loc("Ammo: ") .. primShotsLeft)
+		end
+
+		CopyPV(CurrentHedgehog, morte) -- new addition
+		x,y = GetGearVelocity(morte)
+		--WriteLnToConsole("I'm going to shoot a barrel so I just got the velocity of currenthedgehog. It is dx: " .. x .. "; dy: " .. y)
+		--WriteLnToConsole("The above event occured game Time: " .. GameTime .. "; luaTicks: " .. luaGameTicks)
+
+
+
+		x = x*2
+		y = y*2
+		SetGearVelocity(morte, x, y)
+
+		--WriteLnToConsole("I just SET the velocity of a barrel I created. It is now dx: " .. x .. "; dy: " .. y)
+		--WriteLnToConsole("The above event occured game Time: " .. GameTime .. "; luaTicks: " .. luaGameTicks)
+
+
+
+	elseif (primShotsLeft == 0) and (CurrentHedgehog ~= nil) and (stopMovement == false) and (tumbleStarted == true) then
+		AddCaption(loc("Ammo Depleted!"),0xff0000ff,capgrpMessage)
+	end
+
+
+end
+
+function onLJump()
+
+	if (CurrentHedgehog ~= nil) and (stopMovement == false) and (tumbleStarted == true) then
+		shieldMiser = false
+		if shieldHealth == 80 then
+			AddCaption("Shield Depleted",0xff0000ff,capgrpMessage)
+			PlaySound(sndMineTick)
+			PlaySound(sndSwitchHog)
+		elseif (beam == false) and (shieldHealth > 80) then
+			beam = true
+			SetVisualGearValues(pShield, GetX(CurrentHedgehog), GetY(CurrentHedgehog), 40, 255, 1, 10, 0, 300, 1, 0xa800ffff)
+			AddCaption( loc("Shield ON:") .. " " .. shieldHealth - 80 .. " " .. loc("Power Remaining") )
+			PlaySound(sndWarp)
+		else
+			beam = false
+			SetVisualGearValues(pShield, GetX(CurrentHedgehog), GetY(CurrentHedgehog), 0, 0, 1, 10, 0, 0, 0, 0xa800ffff)
+			AddCaption(loc("Shield OFF:") .. " " .. shieldHealth - 80 .. " " .. loc("Power Remaining") )
+		end
+	end
+end
+
+-----------------
+-- movement keys
+-----------------
+
+function onLeft()
+	leftOn = true
+end
+
+function onRight()
+	rightOn = true
+end
+
+function onUp()
+	upOn = true
+end
+
+function onDown()
+	downOn = true
+end
+
+function onDownUp()
+	downOn = false
+end
+
+function onUpUp()
+	upOn = false
+end
+
+function onLeftUp()
+	leftOn = false
+end
+
+function onRightUp()
+	rightOn = false
+end
+
+--------------------------
+-- other event handlers
+--------------------------
+
+function onGameInit()
+	GameFlags = 0 + gfRandomOrder
+	Theme = "EarthRise"
+	CaseFreq = 0
+	HealthCaseProb = 0
+	MinesNum = 0
+	Explosives = 0
+end
+
+function onGameStart()
+
+	if (MinesTime == -1000) or (MinesTime == 0) then
+		roundLimit = 3
+	else
+		roundLimit = (MinesTime / 1000)
+	end
+
+	ShowMission	(
+				loc("SPACE INVASION"),
+				loc("a Hedgewars mini-game"),
+
+				loc("Destroy invaders to score points.") .. "|" ..
+				" " .. "|" ..
+
+				loc("Round Limit:") .. " " .. roundLimit .. "|" ..
+				loc("Turn Time:") .. " " .. (TurnTime/1000) .. loc("s") .. "|" ..
+				" " .. "|" ..
+
+				loc("Movement: [Up], [Down], [Left], [Right]") .. "|" ..
+				loc("Fire:") .. " " .. loc("[Left Shift]") .. "|" ..
+				loc("Toggle Shield:") .. " " .. loc("[Enter]") .. "|" ..
+
+				--" " .. "|" ..
+				--loc("Invaders List: ") .. "|" ..
+				--loc("Blue Jabberwock: (50 points)") .. "|" ..
+				--loc("Red Warbler: (10 points)") .. "|" ..
+				--loc("Orange Gob: (5 points)") .. "|" ..
+				--loc("Green Wrangler: (3 points)") .. "|" ..
+
+
+				"", 4, 4000
+				)
+
+	CreateMeSomeCircles()
+	RebuildTeamInfo() -- control
+
+end
+
+
+function onNewTurn()
+
+	primShotsLeft = primShotsMax
+	stopMovement = false
+	tumbleStarted = false
+	beam = false
+	shieldHealth = 30 + 80 -- 50 = 5 secs, roughly
+
+	RK = 0
+	GK = 0
+	BK = 0
+	OK = 0
+	SK = 0
+	shieldMiser = true
+	shotsFired = 0
+	shotsHit = 0
+	chainLength = 0
+	chainCounter = 0
+
+	-------------------------
+	-- gaudy racer
+	-------------------------
+	CheckForNewRound()
+
+	-- Handle Starting Stage of Game
+	if (gameOver == false) and (gameBegun == false) then
+		gameBegun = true
+		roundNumber = 0 -- 0
+		firstClan = GetHogClan(CurrentHedgehog)
+	end
+
+	if gameOver == true then
+		gameBegun = false
+		stopMovement = true
+		tumbleStarted = false
+		SetMyCircles(false)
+	end
+	---------------
+	---------------
+	--AddCaption("num g: " .. numGears() )
+
+	--WriteLnToConsole("onNewTurn, I just set a bunch of variables to their necessary states. This was done at:")
+	--WriteLnToConsole("The above occured at Game Time: " .. GameTime .. "; luaTicks: " .. luaGameTicks)
+
+end
+
+function ThingsToBeRunOnGears(gear)
+
+	HandleLifeSpan(gear)
+	DeleteFarFlungBarrel(gear)
+
+	if CirclesAreGo == true then
+		CheckVarious(gear)
+		ProjectileTrack(gear)
+	end
+
+end
+
+
+function onGameTick()
+
+	
+	--WriteLnToConsole("Start of GameTick")	
+	luaGameTicks = luaGameTicks + 1 -- GameTime
+
+	HandleCircles()
+
+	Timer100 = Timer100 + 1
+	if Timer100 >= 100 then
+		Timer100 = 0
+
+		if beam == true then
+			shieldHealth = shieldHealth - 1
+			if shieldHealth <= 80 then
+				shieldHealth = 80
+				beam = false
+				AddCaption(loc("Shield Depleted"),0xff0000ff,capgrpMessage)
+				PlaySound(sndMineTick)
+				PlaySound(sndSwitchHog)
+			end
+		end
+
+
+		--nw WriteLnToConsole("Starting ThingsToBeRunOnGears()")
+
+		runOnGears(ThingsToBeRunOnGears)
+
+		--nw WriteLnToConsole("Finished ThingsToBeRunOnGears()")
+
+		--runOnGears(HandleLifeSpan)
+		--runOnGears(DeleteFarFlungBarrel)
+
+		if CirclesAreGo == true then
+			CheckDistances()
+			--runOnGears(CheckVarious)	-- used to be in handletracking for some bizarre reason
+			--runOnGears(ProjectileTrack)
+		end
+
+		-- white smoke trail as player falls from the sky
+		if (TimeLeft <= 0) and (stopMovement == true) and (CurrentHedgehog ~= nil) then
+			j,k = GetGearVelocity(CurrentHedgehog)
+			if (j ~= 0) and (k ~= 0) then
+				AddVisualGear(GetX(CurrentHedgehog), GetY(CurrentHedgehog), vgtSmoke, 0, true)
+			end
+		end
+
+		--nw WriteLnToConsole("Finished 100Timer")
+
+	end
+
+
+	-- start the player tumbling with a boom once their turn has actually begun
+	if (tumbleStarted == false) and (gameOver == false) then
+		if (TurnTimeLeft > 0) and (TurnTimeLeft ~= TurnTime) then
+			--AddCaption(loc("Good to go!"))
+			tumbleStarted = true
+			TimeLeft = (TurnTime/1000)	--45
+			FadeAlpha = 0
+			AddGear(GetX(CurrentHedgehog), GetY(CurrentHedgehog), gtGrenade, 0, 0, 0, 1)
+			SetMyCircles(true)
+		end
+	end
+
+	--WriteLnToConsole("Finished initial check")
+
+	if (CurrentHedgehog ~= nil) and (tumbleStarted == true) then
+
+		--AddCaption(GetX(CurrentHedgehog) .. ";" .. GetY(CurrentHedgehog) )
+
+		-- Calculate and display turn time
+		TimeLeftCounter = TimeLeftCounter + 1
+		if TimeLeftCounter == 1000 then
+			TimeLeftCounter = 0
+			TimeLeft = TimeLeft - 1
+
+			if TimeLeft >= 0 then
+				--AddCaption(loc("Time Left: ") .. TimeLeft)
+			end
+
+		end
+
+		--WriteLnToConsole("Finished timeleft calculations")
+
+		-------------------------------
+		-- Player has run out of luck (out of time or hit by gtShell)
+		-------------------------------
+		-- checks in FloatyThings
+		if PlayerIsFine() == false then
+			TimeLeft = 0
+		end
+		
+		--WriteLnToConsole("successfully checked playerIsFine")
+		
+		if (TimeLeft == 0) then
+			if (stopMovement == false) then	--time to stop the player
+				stopMovement = true
+				beam = false
+				upOn = false
+				down = false
+				leftOn = false
+				rightOn = false
+				SetMyCircles(false)
+				--nw WriteLnToConsole("Player is out of luck")
+
+				if shieldMiser == true then
+					AddCaption(loc("Shield Miser! +20 points!"),0xffba00ff,capgrpAmmoinfo)
+					AwardPoints(20)
+				end
+
+				if ((shotsHit / shotsFired * 100) >= 80) and (shotsFired > 4) then
+					AddCaption(loc("Accuracy Bonus! +15 points!"),0xffba00ff,capgrpVolume)
+					AwardPoints(15)
+				end
+
+			end
+		else -- remove this if you want tumbler to fall slowly on death
+		-------------------------------
+		-- Player is still in luck
+		-------------------------------
+			
+
+			--WriteLnToConsole("about to do chainCounter checks")
+			if chainCounter > 0 then
+				chainCounter = chainCounter -1 
+				if chainCounter == 0 then
+					chainLength = 0
+				end
+			end
+				
+			-- handle movement based on IO
+			moveTimer = moveTimer + 1
+			if moveTimer == 100 then -- 100
+				--nw WriteLnToConsole("Start of Player MoveTimer")
+				moveTimer = 0
+
+				---------------
+				-- new trail code
+				---------------
+				-- the trail lets you know you have 5s left to pilot, akin to birdy feathers
+				if (TimeLeft <= 5) and (TimeLeft > 0) then							--vgtSmoke
+					tempE = AddVisualGear(GetX(CurrentHedgehog), GetY(CurrentHedgehog), vgtSmoke, 0, true)
+					g1, g2, g3, g4, g5, g6, g7, g8, g9, g10 = GetVisualGearValues(tempE)
+					SetVisualGearValues(tempE, g1, g2, g3, g4, g5, g6, g7, g8, g9, GetClanColor(GetHogClan(CurrentHedgehog)) )
+				end
+				--------------
+				--------------
+
+				dx, dy = GetGearVelocity(CurrentHedgehog)
+
+				--WriteLnToConsole("I just got the velocity of currenthedgehog. It is dx: " .. dx .. "; dy: " .. dy)
+				--WriteLnToConsole("The above event occured game Time: " .. GameTime .. "; luaTicks: " .. luaGameTicks)
+
+
+				dxlimit = 0.4*fMod
+				dylimit = 0.4*fMod
+
+				if dx > dxlimit then
+					dx = dxlimit
+				end
+				if dy > dylimit then
+					dy = dylimit
+				end
+				if dx < -dxlimit then
+					dx = -dxlimit
+				end
+				if dy < -dylimit then
+					dy = -dylimit
+				end
+
+
+				if leftOn == true then
+					dx = dx - 0.1*fMod
+				end
+				if rightOn == true then
+					dx = dx + 0.1*fMod
+				end
+
+				if upOn == true then
+					dy = dy - 0.1*fMod
+				end
+				if downOn == true then
+					dy = dy + 0.1*fMod
+				end
+
+				SetGearVelocity(CurrentHedgehog, dx, dy)
+
+				--WriteLnToConsole("I just SET the velocity of currenthedgehog. It is now dx: " .. dx .. "; dy: " .. dy)
+				--WriteLnToConsole("The above event occured game Time: " .. GameTime .. "; luaTicks: " .. luaGameTicks)
+				--nw WriteLnToConsole("End of Player MoveTimer")
+
+			end
+
+		end -- new end I put here to check if he's still alive or not
+
+	end
+
+	--WriteLnToConsole("End of GameTick")
+
+end
+
+function onGearResurrect(gear)
+
+	-- did I fall into the water? well, that was a stupid thing to do
+	if gear == CurrentHedgehog then
+		TimeLeft = 0
+		--WriteLnToConsole("Current hedgehog just drowned himself")
+		--WriteLnToConsole("The above event occured game Time: " .. GameTime .. "; luaTicks: " .. luaGameTicks)
+
+	end
+
+end
+
+function onGearAdd(gear)
+
+	if isATrackedGear(gear) then
+		trackGear(gear)
+		setNewGearValues(gear)
+	end
+
+	--if GetGearType(gear) == gtBall then
+	--	SetTimer(gear, 5000)
+	--end
+
+	if GetGearType(gear) == gtHedgehog then
+		SetEffect(gear, heResurrectable, true)
+
+		-----------
+		-- control
+		hhs[numhhs] = gear
+		numhhs = numhhs + 1
+		-----------
+	end
+
+end
+
+function onGearDelete(gear)
+
+	if GetGearType(gear) == gtShell then
+		--nw WriteLnToConsole("on GearDelete call. Shell ID: " .. getGearValue(gear,"ID"))
+		--WriteLnToConsole("The above event occured game Time: " .. GameTime .. "; luaTicks: " .. luaGameTicks)
+
+		--if CurrentHedgehog ~= nil then
+		--	WriteLnToConsole("As it happens, player is at: " .. GetX(CurrentHedgehog) .. "; " .. GetY(CurrentHedgehog))
+		--end
+	elseif GetGearType(gear) == gtExplosives then
+		--nw WriteLnToConsole("on GearDelete call. Explosives ID: " .. getGearValue(gear,"ID"))
+		--WriteLnToConsole("The above event occured game Time: " .. GameTime .. "; luaTicks: " .. luaGameTicks)
+
+		--if CurrentHedgehog ~= nil then
+		--	WriteLnToConsole("As it happens, player is at: " .. GetX(CurrentHedgehog) .. "; " .. GetY(CurrentHedgehog))
+		--end
+	elseif GetGearType(gear) == gtFlame then
+		--WriteLnToConsole("on GearDelete flame")
+	end
+
+
+
+
+
+	if isATrackedGear(gear) then
+		trackDeletion(gear)
+	end
+
+	if CurrentHedgehog ~= nil then
+		FollowGear(CurrentHedgehog)
+	end
+
+end
+
+
+
+------------------------------------------------------------
+------------------------------------------------------------
+------------------------------------------------------------
+------------------------------------------------------------
+-- FLOATY THINGS
+-- "I'll make this into a generic library and code properly
+-- when I have more time and feel less lazy"
+------------------------------------------------------------
+------------------------------------------------------------
+------------------------------------------------------------
+------------------------------------------------------------
+
+
+
+
+function PlayerIsFine()
+	return (playerIsFine)
+end
+
+function GetDistFromGearToGear(gear, gear2)
+
+	g1X, g1Y = GetGearPosition(gear)
+	g2X, g2Y = GetGearPosition(gear2)
+	q = g1X - g2X
+	w = g1Y - g2Y
+
+
+	--[[
+	WriteLnToConsole("I just got the position of two gears and calculated the distance betwen them")
+	if gear == CurrentHedgehog then
+		WriteLnToConsole("Gear 1 is CurrentHedgehog.")
+	end
+	if gear2 == CurrentHedgehog then
+		WriteLnToConsole("Gear 2 is CurrentHedgehog.")
+	end
+	WriteLnToConsole("G1X: " .. g1X .. "; G1Y: " .. g1Y)
+	WriteLnToConsole("G2X: " .. g2X .. "; G2Y: " .. g2Y)
+	WriteLnToConsole("Their distance is " .. (q*q) + (w*w) )
+	WriteLnToConsole("The above events occured game Time: " .. GameTime .. "; luaTicks: " .. luaGameTicks)
+]]
+
+
+	return ( (q*q) + (w*w) )
+
+end
+
+function GetDistFromGearToXY(gear, g2X, g2Y)
+
+	g1X, g1Y = GetGearPosition(gear)
+	q = g1X - g2X
+	w = g1Y - g2Y
+
+
+	--[[WriteLnToConsole("I just got the position of a gear and calculated the distance betwen it and another xy")
+	if gear == CurrentHedgehog then
+		WriteLnToConsole("Gear 1 is CurrentHedgehog.")
+	end
+
+	WriteLnToConsole("G1X: " .. g1X .. "; G1Y: " .. g1Y)
+	WriteLnToConsole("Other X: " .. g2X .. "; Other Y: " .. g2Y)
+	WriteLnToConsole("Their distance is " .. (q*q) + (w*w) )
+	WriteLnToConsole("The above events occured game Time: " .. GameTime .. "; luaTicks: " .. luaGameTicks)
+]]
+
+
+	return ( (q*q) + (w*w) )
+
+
+end
+
+function CreateMeSomeCircles()
+
+	for i = 0, 7 do
+		vCCount = vCCount +1
+		vCirc[i] = AddVisualGear(0,0,vgtCircle,0,true)
+
+		vCircDX[i] = 0
+		vCircDY[i] = 0
+
+		vType[i] = "generic"
+		vCounter[i] = 0
+		vCounterLim[i] = 3000
+		vCircScore[i] = 0
+		vCircHealth[i] = 1
+
+		vCircMinA[i] = 80	--80 --20
+		vCircMaxA[i] = 255
+		vCircType[i] = 1	--1
+		vCircPulse[i] = 10
+		vCircFuckAll[i] = 0
+		vCircRadius[i] = 0
+		vCircWidth[i] = 3 --5
+
+		vCircRadMax[i] = 0
+		vCircRadMin[i] = 0
+		vCircRadDir[i] = -1
+		vCircRadCounter[i] = 0
+
+		vCircX[i], vCircY[i] = 0,0
+
+		vCircCol[i] = 0xff00ffff
+
+		SetVisualGearValues(vCirc[i], vCircX[i], vCircY[i], vCircMinA[i], vCircMaxA[i], vCircType[i], vCircPulse[i], vCircFuckAll[i], vCircRadius[i], vCircWidth[i], vCircCol[i])
+	end
+
+	pShield = AddVisualGear(0,0,vgtCircle,0,true)
+	--SetVisualGearValues(pShield, GetX(CurrentHedgehog), GetY(CurrentHedgehog), 80, 200, 1, 10, 0, 200, 5, 0xff00ffff)
+
+
+end
+
+function IGotMeASafeXYValue(i)
+
+	acceptibleDistance = 800
+
+	-- put this in here to thwart attempts at repositioning and test sanity limit
+	--vCircX[i] = GetX(CurrentHedgehog)+250
+	--vCircY[i] = GetY(CurrentHedgehog)+250
+
+	vCircX[i] = GetRandom(5000)
+	vCircY[i] = GetRandom(2000)
+	dist = GetDistFromGearToXY(CurrentHedgehog, vCircX[i], vCircY[i])
+	if dist > acceptibleDistance*acceptibleDistance then
+		return(true)
+	else
+		return(false)
+	end
+
+end
+
+function CircleDamaged(i)
+
+	res = ""
+	vCircHealth[i] = vCircHealth[i] -1
+
+	if vCircHealth[i] <= 0 then
+	-- circle is dead, do death effects/consequences
+
+		vCircActive[i] = false
+
+		if (vType[i] == "drone") then
+			PlaySound(sndHellishImpact4)
+			TimeLeft = TimeLeft + 4
+			AddCaption(loc("Time Extended!") .. "+" .. 4 .. loc("s"), 0xff0000ff,capgrpMessage )
+
+			morte = AddGear(vCircX[i], vCircY[i], gtExplosives, 0, 0, 0, 1)
+			SetHealth(morte, 0)
+
+			RK = RK + 1
+			if RK == 5 then
+				RK = 0
+				AddCaption(loc("Drone Hunter! +10 points!"),0xffba00ff,capgrpMessage2)
+				AwardPoints(10)
+			end
+
+		elseif (vType[i] == "ammo") then
+			AddVisualGear(vCircX[i], vCircY[i], vgtExplosion, 0, false)
+			PlaySound(sndExplosion)
+			PlaySound(sndShotgunReload)
+			primShotsLeft = primShotsLeft + 3
+			AddCaption("+" .. 3 .. " " .. loc("Ammo"), 0x00ff00ff,capgrpMessage)
+
+			GK = GK + 1
+			if GK == 3 then
+				GK = 0
+				AddCaption(loc("Ammo Maniac! +5 points!"),0xffba00ff,capgrpMessage2)
+				AwardPoints(5)
+			end
+
+		elseif (vType[i] == "bonus") then
+
+			AddVisualGear(vCircX[i], vCircY[i], vgtExplosion, 0, false)
+			PlaySound(sndExplosion)
+
+			AddVisualGear(vCircX[i], vCircY[i], vgtFire, 0, false)
+			AddVisualGear(vCircX[i], vCircY[i], vgtFire, 0, false)
+			AddVisualGear(vCircX[i], vCircY[i], vgtFire, 0, false)
+			AddVisualGear(vCircX[i], vCircY[i], vgtFire, 0, false)
+			AddVisualGear(vCircX[i], vCircY[i], vgtFire, 0, false)
+			AddVisualGear(vCircX[i], vCircY[i], vgtSmoke, 0, false)
+
+			PlaySound(sndVaporize)
+			--sndWarp sndMineTick --sndSwitchHog --sndSuddenDeath
+
+			shieldHealth = shieldHealth + 30
+			AddCaption(loc("Shield boosted! +30 power"), 0xa800ffff,capgrpMessage)
+			if shieldHealth >= 250 then
+				shieldHealth = 250
+				AddCaption(loc("Shield is fully recharged!"),0xa800ffff,capgrpMessage)
+			end
+
+			OK = OK + 1
+			if OK == 3 then
+				OK = 0
+				AddCaption(loc("Shield Seeker! + 10 points!"),0xffba00ff,capgrpMessage2)
+				AwardPoints(10)
+			end
+
+		elseif (vType[i] == "blueboss") then
+			PlaySound(sndHellishImpact3)
+			AddCaption(loc("Boss defeated! +50 points!"), 0x0050ffff,capgrpMessage)
+
+			morte = AddGear(vCircX[i], vCircY[i], gtExplosives, 0, 0, 0, 1)
+			SetHealth(morte, 0)
+
+			BK = BK + 1
+			if BK == 2 then
+				BK = 0
+				AddCaption(loc("Boss Slayer! +25 points!"),0xffba00ff,capgrpMessage2)
+				AwardPoints(25)
+			end
+
+		end
+
+		AwardPoints(vCircScore[i])
+		AwardKills()
+		SetUpCircle(i)
+		res = "fatal"
+
+		chainCounter = 3000
+		chainLength = chainLength + 1
+		if chainLength > 1 then
+			AddCaption( chainLength .. loc("-Hit Combo! +") .. chainLength*2 .. loc(" points!"),0xffba00ff,capgrpAmmostate)
+			AwardPoints(chainLength*2)
+		end
+
+	else
+	-- circle is merely damaged
+	-- do damage effects/sounds
+		AddVisualGear(vCircX[i], vCircY[i], vgtSteam, 0, false)
+		r = GetRandom(4)
+		if r == 0 then
+			PlaySound(sndHellishImpact1)
+		elseif r == 1 then
+			PlaySound(sndHellishImpact2)
+		elseif r == 2 then
+			PlaySound(sndHellishImpact3)
+		elseif r == 3 then
+			PlaySound(sndHellishImpact4)
+		end
+		res = "non-fatal"
+
+	end
+
+	return(res)
+
+end
+
+function SetUpCircle(i)
+
+
+	r = GetRandom(10)
+	--r = 8
+	-- 80% of spawning either red/green
+	if r <= 7 then
+
+		--r = GetRandom(5)
+		r = GetRandom(2)
+		--r = 1
+		if r == 0 then
+		--if r <= 2 then
+			vCircCol[i] = 0xff0000ff -- red
+			vType[i] = "drone"
+			vCircRadMin[i] = 50	*5
+			vCircRadMax[i] = 90	*5
+			vCounterLim[i] = 3000
+			vCircScore[i] = 10
+			vCircHealth[i] = 1
+		--else
+		elseif r == 1 then
+			vCircCol[i] = 0x00ff00ff -- green
+			vType[i] = "ammo"
+			vCircRadMin[i] = 25	*7
+			vCircRadMax[i] = 30	*7
+			vCircScore[i] = 3
+			vCircHealth[i] = 1
+		end
+
+	-- 20% chance of spawning boss or bonus
+	else
+		r = GetRandom(5)
+		--r = GetRandom(2)
+		--r = 0
+		if r <= 1 then
+		--if r == 0 then
+			vCircCol[i] = 0x0050ffff -- sexy blue
+			vType[i] = "blueboss"
+			vCircRadMin[i] = 100*5
+			vCircRadMax[i] = 180*5
+			vCircWidth[i] = 1
+			vCounterLim[i] = 2000
+			vCircScore[i] = 50
+			vCircHealth[i] = 3
+		else
+		--elseif r == 1 then
+			--vCircCol[i] = 0xffae00ff -- orange
+			vCircCol[i] = 0xa800ffff -- purp
+			vType[i] = "bonus"
+			vCircRadMin[i] = 20 *7
+			vCircRadMax[i] = 40 *7
+			vCircScore[i] = 5
+			vCircHealth[i] = 1
+		end
+
+	end
+
+	-- regenerate circle xy if too close to player or until sanity limit kicks in
+	reN = 0
+	--zzz = 0
+	while (reN < 10) do
+		if IGotMeASafeXYValue(i) == false then
+			reN = reN + 1
+			--zzz = zzz + 1
+		else
+			reN = 15
+		end
+	end
+	--AddCaption("Took me this many retries: " .. zzz) -- number of times it took to work
+
+	vCircRadius[i] = vCircRadMax[i] - GetRandom(vCircRadMin[i])
+
+	g1, g2, g3, g4, g5, g6, g7, g8, g9, g10 = GetVisualGearValues(vCirc[i])
+	SetVisualGearValues(vCirc[i], vCircX[i], vCircY[i], g3, g4, g5, g6, g7, vCircRadius[i], vCircWidth[i], vCircCol[i]-0x000000ff)
+	-- - -0x000000ff
+	vCircActive[i] = true -- new
+
+	--nw WriteLnToConsole("CIRC " .. i .. ": X: " .. vCircX[i] .. "; Y: " .. vCircY[i])
+	--nw WriteLnToConsole("CIRC " .. i .. ": dX: " .. vCircDX[i] .. "; dY: " .. vCircDY[i])
+	--nw WriteLnToConsole("CIRC " .. i .. ": RAD:" .. vCircRadius[i])
+
+end
+
+function SetMyCircles(s)
+
+	CirclesAreGo = s
+	playerIsFine = s
+
+	if s == true then
+		--nw WriteLnToConsole("About to set up all circles, old values are here:")
+		for i = 0,(vCCount-1) do
+			--nw WriteLnToConsole("CIRC " .. i .. ": X: " .. vCircX[i] .. "; Y: " .. vCircY[i])
+			--nw WriteLnToConsole("CIRC " .. i .. ": dX: " .. vCircDX[i] .. "; dY: " .. vCircDY[i])
+			--nw WriteLnToConsole("CIRC " .. i .. ": RAD:" .. vCircRadius[i])
+		end
+		--nw WriteLnToConsole("Old values given, new values to follow...")
+	end
+
+	for i = 0,(vCCount-1) do
+
+		if s == false then
+			--vCircCol[i] = 0xffffffff
+			vCircActive[i] = false
+		elseif s == true then
+			SetUpCircle(i)
+		end
+
+	end
+
+end
+
+function WellHeAintGonnaJumpNoMore(x,y)
+
+	AddVisualGear(x, y, vgtBigExplosion, 0, false)
+	playerIsFine = false
+	AddCaption(loc("GOTCHA!"))
+	PlaySound(sndExplosion)
+	PlaySound(sndHellish)
+
+	targetHit = true
+
+end
+
+--- collision detection for weapons fire
+function CheckVarious(gear)
+
+	--if (GetGearType(gear) == gtExplosives) then
+		--nw WriteLnToConsole("Start of CheckVarious(): Exp ID: " .. getGearValue(gear,"ID"))
+	--elseif (GetGearType(gear) == gtShell) then
+		--nw WriteLnToConsole("Start of CheckVarious(): Shell ID: " .. getGearValue(gear,"ID"))
+	--end
+
+
+
+
+	targetHit = false
+
+	-- if circle is hit by player fire
+	if (GetGearType(gear) == gtExplosives) then
+		circsHit = 0
+
+		for i = 0,(vCCount-1) do
+
+			--nw WriteLnToConsole("Is it neccessary to check for collision with circ " .. i)
+
+			--if (vCircActive[i] == true) and ( (vType[i] == "drone") ) then
+
+				--nw WriteLnToConsole("YES. about to calc distance between gtExplosives and circ " .. i)
+
+				dist = GetDistFromGearToXY(gear, vCircX[i], vCircY[i])
+
+				-- calculate my real radius if I am an aura
+				if vCircType[i] == 0 then
+					NR = vCircRadius[i]
+				else
+					NR = (48/100*vCircRadius[i])/2
+				end
+
+				if dist <= NR*NR then
+
+						--nw WriteLnToConsole("Collision confirmed. The gtExplosives is within the circ radius!")
+
+					--SetGearPosition(gear, vCircX[i], vCircY[i])
+						--WriteLnToConsole("set the gtExplosives to be in the center of circ")
+					AddVisualGear(GetX(gear), GetY(gear), vgtBigExplosion, 0, false)
+
+					targetHit = true
+					--DeleteGear(gear)
+					--SetHealth(gear,0)
+						--WriteLnToConsole("set " .. "Exp ID: " .. getGearValue(gear,"ID") .. " health to 0")
+						--WriteLnToConsole("targetHit set to true, explosive is at distance " .. dist .. "(within range " .. NR*NR.. ") of circ" )
+
+					CircleDamaged(i)
+
+					circsHit = circsHit + 1
+					if circsHit > 1 then
+						AddCaption(loc("Multi-shot! +5 points!"),0xffba00ff,capgrpAmmostate) 
+					end
+
+					shotsHit = shotsHit + 1
+
+				end
+
+			--end
+
+		end
+
+	-- if player is hit by circle bazooka
+	elseif (GetGearType(gear) == gtShell) or (GetGearType(gear) == gtBall) then
+
+		dist = GetDistFromGearToGear(gear, CurrentHedgehog)
+
+		if beam == true then
+
+			if dist < 3000 then
+				tempE = AddVisualGear(GetX(gear), GetY(gear), vgtSmoke, 0, true)
+				g1, g2, g3, g4, g5, g6, g7, g8, g9, g10 = GetVisualGearValues(tempE)
+				SetVisualGearValues(tempE, g1, g2, g3, g4, g5, g6, g7, g8, g9, 0xff00ffff )
+				PlaySound(sndVaporize)
+				DeleteGear(gear)
+
+				SK = SK + 1
+				if SK == 5 then
+					SK = 0
+					AddCaption(loc("Shield Master! +10 points!"),0xffba00ff,capgrpAmmoinfo)
+					AwardPoints(10)
+				end
+			end
+
+		elseif dist < 1600 then
+			WellHeAintGonnaJumpNoMore(GetX(gear), GetY(gear))
+		end
+
+		--[[if targetHit == true then
+			WriteLnToConsole("about to delete shell due to targetHit being set to true earlier")
+			DeleteGear(gear)
+			WriteLnToConsole("there, I deleted it")
+		end]]
+
+
+	end
+
+	if targetHit == true then
+			--nw WriteLnToConsole("about to delete something due to targetHit being set to true earlier")
+			DeleteGear(gear)
+			--nw WriteLnToConsole("there, I deleted it")
+	end
+
+	--nw WriteLnToConsole("End of CheckVarious()")
+
+end
+
+-- collision detection for player entering a circle
+function CheckDistances()
+
+	--nw WriteLnToConsole("Start of CheckDistances()")
+
+	for i = 0,(vCCount-1) do
+
+
+		--nw WriteLnToConsole("Attempting to calculate dist of circ " .. i)
+
+		g1X, g1Y = GetGearPosition(CurrentHedgehog)
+		g2X, g2Y = vCircX[i], vCircY[i]
+
+		g1X = g1X - g2X
+		g1Y = g1Y - g2Y
+		dist = (g1X*g1X) + (g1Y*g1Y)
+
+		--nw WriteLnToConsole("Calcs done. Dist to CurrentHedgehog is " .. dist)
+
+		-- calculate my real radius if I am an aura
+		if vCircType[i] == 0 then
+			NR = vCircRadius[i]
+		else
+			NR = (48/100*vCircRadius[i])/2
+		end
+
+		if dist <= NR*NR then
+
+			if 	(vCircActive[i] == true) and
+				((vType[i] == "ammo") or (vType[i] == "bonus") )
+			then
+
+				CircleDamaged(i)
+
+			elseif (vCircActive[i] == true) and
+					( (vType[i] == "drone") or (vType[i] == "blueboss") )
+			then
+
+				ss = CircleDamaged(i)
+				WellHeAintGonnaJumpNoMore(GetX(CurrentHedgehog),GetY(CurrentHedgehog))
+
+				if ss == "fatal" then
+					if (primShotsLeft == 0) and (TimeLeft <= 9) then
+						AddCaption(loc("Kamikaze Expert! +15 points!"),0xffba00ff,capgrpMessage)
+						AwardPoints(15)
+					elseif (primShotsLeft == 0) then
+						AddCaption(loc("Depleted Kamikaze! +5 points!"),0xffba00ff,capgrpMessage)
+						AwardPoints(5)
+					elseif TimeLeft <= 9 then
+						AddCaption(loc("Timed Kamikaze! +10 points!"),0xffba00ff,capgrpMessage)
+						AwardPoints(10)
+					end
+				end
+
+			end
+
+
+		end
+
+	end
+
+	--nw WriteLnToConsole("End of CheckDistances()")
+
+end
+
+function HandleCircles()
+
+
+	--[[if CirclesAreGo == true then
+
+		--CheckDistances()
+		--runOnGears(CheckVarious)	-- used to be in handletracking for some bizarre reason
+
+		--pTimer = pTimer + 1
+		--if pTimer == 100 then
+		--	pTimer = 0
+		--	runOnGears(ProjectileTrack)
+		--end
+
+	end]]
+
+	for i = 0,(vCCount-1) do
+
+		vCounter[i] = vCounter[i] + 1
+		if vCounter[i] >= vCounterLim[i] then
+
+			vCounter[i] = 0
+
+			if 	((vType[i] == "drone") or (vType[i] == "blueboss") ) and
+				(vCircActive[i] == true) then
+				AddGear(vCircX[i], vCircY[i], gtShell, 0, 0, 0, 1)
+
+				--WriteLnToConsole("Circle " .. i .. " just fired/added a gtShell")
+				--WriteLnToConsole("The above event occured game Time: " .. GameTime .. "; luaTicks: " .. luaGameTicks)
+
+			--elseif (vType[i] == "bluebottle") and (vCircActive[i] == true) then
+			--	AddGear(vCircX[i], vCircY[i]-vCircRadius[i], gtBall, 0, 0, 0, 1)
+			--	AddGear(vCircX[i], vCircY[i]+vCircRadius[i], gtBall, 0, 0, 0, 1)
+			--	AddGear(vCircX[i]-vCircRadius[i], vCircY[i], gtBall, 0, 0, 0, 1)
+			--	AddGear(vCircX[i]+vCircRadius[i], vCircY[i], gtBall, 0, 0, 0, 1)
+			end
+
+		end
+
+		if (vCircActive[i] == true) then
+
+			vCircRadCounter[i] = vCircRadCounter[i] + 1
+			if vCircRadCounter[i] == 100 then
+
+				vCircRadCounter[i] = 0
+
+				-- make my radius increase/decrease faster if I am an aura
+				if vCircType[i] == 0 then
+					M = 1
+				else
+					M = 10
+				end
+
+				vCircRadius[i] = vCircRadius[i] + vCircRadDir[i]
+				if vCircRadius[i] > vCircRadMax[i] then
+					vCircRadDir[i] = -M
+				elseif vCircRadius[i] < vCircRadMin[i] then
+					vCircRadDir[i] = M
+				end
+
+
+				-- random effect test
+				-- maybe use this to tell the difference between circs
+				-- you can kill by shooting or not
+				--vgtSmoke vgtSmokeWhite
+				--vgtSteam -- nice long trail
+				--vgtDust -- short trail on earthrise
+				--vgtSmokeTrace
+				if vType[i] == "ammo" then
+
+					tempE = AddVisualGear(vCircX[i], vCircY[i], vgtSmoke, 0, true)
+					g1, g2, g3, g4, g5, g6, g7, g8, g9, g10 = GetVisualGearValues(tempE)	--0xff00ffff	--0x00ff00ff
+					SetVisualGearValues(tempE, vCircX[i], vCircY[i], g3, g4, g5, g6, g7, g8, g9, vCircCol[i] )
+
+					--AddVisualGear(vCircX[i], vCircY[i], vgtDust, 0, true)
+
+				elseif vType[i] == "bonus" then
+
+					tempE = AddVisualGear(vCircX[i], vCircY[i], vgtDust, 0, true)
+					g1, g2, g3, g4, g5, g6, g7, g8, g9, g10 = GetVisualGearValues(tempE)	--0xff00ffff	--0x00ff00ff --vCircCol[i]
+					SetVisualGearValues(tempE, vCircX[i], vCircY[i], g3, g4, g5, g6, g7, 1, g9, 0xff00ffff )
+
+
+				elseif vType[i] == "blueboss" then
+
+					k = 25
+					g = vgtSteam
+					trailColour = 0xae00ffff
+
+					-- 0xffae00ff -- orange
+					-- 0xae00ffff -- purp
+
+					tempE = AddVisualGear(vCircX[i], vCircY[i], g, 0, true)
+					g1, g2, g3, g4, g5, g6, g7, g8, g9, g10 = GetVisualGearValues(tempE)	--0xff00ffff	--0x00ff00ff
+					SetVisualGearValues(tempE, vCircX[i], vCircY[i]+k, g3, g4, g5, g6, g7, g8, g9, trailColour-75 )
+
+					tempE = AddVisualGear(vCircX[i], vCircY[i], g, 0, true)
+					g1, g2, g3, g4, g5, g6, g7, g8, g9, g10 = GetVisualGearValues(tempE)	--0xff00ffff	--0x00ff00ff
+					SetVisualGearValues(tempE, vCircX[i]+k, vCircY[i]-k, g3, g4, g5, g6, g7, g8, g9, trailColour-75 )
+
+					tempE = AddVisualGear(vCircX[i], vCircY[i], g, 0, true)
+					g1, g2, g3, g4, g5, g6, g7, g8, g9, g10 = GetVisualGearValues(tempE)	--0xff00ffff	--0x00ff00ff
+					SetVisualGearValues(tempE, vCircX[i]-k, vCircY[i]-k, g3, g4, g5, g6, g7, g8, g9, trailColour-75 )
+
+
+				end
+
+
+			end
+
+		end
+
+
+	end
+
+	-- alter the circles velocities
+	circAdjustTimer = circAdjustTimer + 1
+	if circAdjustTimer == 2000 then
+
+		circAdjustTimer = 0
+
+		for i = 0,(vCCount-1) do
+
+			-- bounce the circles off the edges if they go too far
+			-- or make them move in random directions
+
+			if vCircX[i] > 5500 then
+				vCircDX[i] = -5	--5 circmovchange
+			elseif vCircX[i] < -1500 then
+				vCircDX[i] = 5	--5 circmovchange
+			else
+
+				z = GetRandom(2)
+				if z == 1 then
+					z = 1
+				else
+					z = -1
+				end
+				vCircDX[i] = vCircDX[i] + GetRandom(3)*z	--3 circmovchange
+			end
+
+			if vCircY[i] > 1500 then
+				vCircDY[i] = -5	--5 circmovchange
+			elseif vCircY[i] < -2900 then
+				vCircDY[i] = 5	--5 circmovchange
+			else
+				z = GetRandom(2)
+				if z == 1 then
+					z = 1
+				else
+					z = -1
+				end
+				vCircDY[i] = vCircDY[i] + GetRandom(3)*z	--3 circmovchange
+			end
+
+		end
+
+	end
+
+	-- move the circles according to their current velocities
+	m2Count = m2Count + 1
+	if m2Count == 25 then	--25 circmovchange
+
+		m2Count = 0
+		for i = 0,(vCCount-1) do
+			vCircX[i] = vCircX[i] + vCircDX[i]
+			vCircY[i] = vCircY[i] + vCircDY[i]
+		end
+
+		if (TimeLeft == 0) and (tumbleStarted == true) then
+
+			FadeAlpha = FadeAlpha + 1
+			if FadeAlpha >= 255 then
+				FadeAlpha = 255
+			end
+
+			--new			
+			--if FadeAlpha == 1 then
+			--	AddCaption("GOT IT")				
+			--	for i = 0,(vCCount-1) do
+			--		g1, g2, g3, g4, g5, g6, g7, g8, g9, g10 = GetVisualGearValues(vCirc[i])
+			--		vCircCol[i] = g10	
+			--	end
+			--end
+
+		end
+
+	end
+
+	for i = 0,(vCCount-1) do
+		g1, g2, g3, g4, g5, g6, g7, g8, g9, g10 = GetVisualGearValues(vCirc[i])		-- vCircCol[i] g10
+		SetVisualGearValues(vCirc[i], vCircX[i], vCircY[i], g3, g4, g5, g6, g7, vCircRadius[i], g9, g10)
+	end
+
+	if 	(TimeLeft == 0) or
+		((tumbleStarted == false)) then
+		for i = 0,(vCCount-1) do
+			g1, g2, g3, g4, g5, g6, g7, g8, g9, g10 = GetVisualGearValues(vCirc[i])		-- vCircCol[i] g10
+			SetVisualGearValues(vCirc[i], vCircX[i], vCircY[i], g3, g4, g5, g6, g7, vCircRadius[i], g9, (vCircCol[i]-FadeAlpha))
+		end
+	end
+
+
+	if (CurrentHedgehog ~= nil) and (beam == true) then
+		g1, g2, g3, g4, g5, g6, g7, g8, g9, g10 = GetVisualGearValues(pShield)
+		--SetVisualGearValues(pShield, GetX(CurrentHedgehog), GetY(CurrentHedgehog), g3, g4, g5, g6, g7, 200, g9, g10 )
+		SetVisualGearValues(pShield, GetX(CurrentHedgehog), GetY(CurrentHedgehog), g3, g4, g5, g6, g7, 200, g9, 0xa800ffff-0x000000ff - -shieldHealth )
+	else
+		SetVisualGearValues(pShield, GetX(CurrentHedgehog), GetY(CurrentHedgehog), g3, g4, g5, g6, g7, 0, g9, g10 )
+	end
+
+end
+
+function ProjectileTrack(gear)
+
+	if (GetGearType(gear) == gtShell) then
+
+		--nw WriteLnToConsole("ProjectileTrack() for Shell ID: " .. getGearValue(gear,"ID"))
+
+		-- newnew
+		if (GetGearType(gear) == gtShell) then
+			turningSpeed = 0.1*fMod
+		--elseif (GetGearType(gear) == gtBall) then
+		--	turningSpeed = 0.2*fMod
+		end
+
+		dx, dy = GetGearVelocity(gear)
+
+		--WriteLnToConsole("I'm trying to track currenthedge with shell ID: " .. getGearValue(gear,"ID"))
+		--WriteLnToConsole("I just got the velocity of the shell. It is dx: " .. dx .. "; dy: " .. dy)
+		--WriteLnToConsole("CurrentHedgehog is at X: " .. GetX(CurrentHedgehog) .. "; Y: " .. GetY(CurrentHedgehog) )
+
+		if GetX(gear) > GetX(CurrentHedgehog) then
+			dx = dx - turningSpeed--0.1
+		else
+			dx = dx + turningSpeed--0.1
+		end
+
+		if GetY(gear) > GetY(CurrentHedgehog) then
+			dy = dy - turningSpeed--0.1
+		else
+			dy = dy + turningSpeed--0.1
+		end
+
+
+		if (GetGearType(gear) == gtShell) then
+			dxlimit = 0.4*fMod
+			dylimit = 0.4*fMod
+		--elseif (GetGearType(gear) == gtBall) then
+		--	dxlimit = 0.5	--  0.5 is about the same
+		--	dylimit = 0.5 -- 0.6 is faster than player
+		end
+
+		if dx > dxlimit then
+			dx = dxlimit
+		end
+		if dy > dylimit then
+			dy = dylimit
+		end
+		if dx < -dxlimit then
+			dx = -dxlimit
+		end
+		if dy < -dylimit then
+			dy = -dylimit
+		end
+
+		SetGearVelocity(gear, dx, dy)
+
+		--WriteLnToConsole("I just SET the velocity of shell towards currenthegdge. It is now dx: " .. dx .. "; dy: " .. dy)
+		--WriteLnToConsole("The above events occured game Time: " .. GameTime .. "; luaTicks: " .. luaGameTicks)
+		--nw WriteLnToConsole("ProjectileTrack() finished successfully")
+
+	end
+
+end
+
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/share/hedgewars/Data/Scripts/Multiplayer/The_Specialists.lua	Thu Jun 23 21:19:43 2011 +0400
@@ -0,0 +1,256 @@
+----------------------------------
+-- THE SPECIALISTS MODE 0.2
+-- by mikade
+----------------------------------
+
+-- version history
+-----------------
+-- version 0.1
+-----------------
+-- concept test
+
+----------------
+-- version 0.2
+----------------
+-- added gfRandomOrder to gameflags
+-- removed some deprecated variables/methods
+-- fixed lack of portal reset
+
+--------------------
+--TO DO
+--------------------
+
+-- add proper gameflag checking, maybe
+-- set crate drops etc.
+-- assuming place hog mode + gfinfattack doesn't get the fix: somehow end turn after teleport
+
+loadfile(GetDataPath() .. "Scripts/Locale.lua")()
+
+local numhhs = 0 
+local hhs = {} 
+
+local currName 
+local lastName
+
+function CreateTeam()
+
+	currTeam = ""
+	lastTeam = ""
+	z = 0
+
+	for i = 0, (numhhs-1) do
+
+		currTeam = GetHogTeamName(hhs[i])
+
+		if currTeam == lastTeam then
+			z = z + 1
+		else
+			z = 1		
+		end
+
+		if z == 1 then
+
+			SetHogName(hhs[i],"Soldier")
+			SetHogHat(hhs[i], "Vega")
+			SetHealth(hhs[i],200)
+
+		elseif z == 2 then
+
+			SetHogHat(hhs[i], "Glasses")
+			SetHogName(hhs[i],"Engineer")
+
+		elseif z == 3 then
+
+			SetHogName(hhs[i],"Ninja")			
+			SetHogHat(hhs[i], "NinjaFull")
+			SetHealth(hhs[i],80)
+
+		elseif z == 4 then
+
+			SetHogName(hhs[i],"Demo")			
+			SetHogHat(hhs[i], "Skull")
+			SetHealth(hhs[i],200)
+
+		elseif z == 5 then
+
+			SetHogName(hhs[i],"Sniper")			
+			SetHogHat(hhs[i], "Sniper")
+			SetHealth(hhs[i],120)
+
+		elseif z == 6 then
+
+			SetHogName(hhs[i],"Saint")			
+			SetHogHat(hhs[i], "angel")
+			SetHealth(hhs[i],300)
+
+		elseif z == 7 then
+
+			SetHogName(hhs[i],"Pyro")			
+			SetHogHat(hhs[i], "Gasmask")
+			SetHealth(hhs[i],150)
+		
+		elseif z == 8 then
+		
+			SetHogName(hhs[i],"Loon")			
+			SetHogHat(hhs[i], "clown")
+			SetHealth(hhs[i],100)
+
+		end
+
+		lastTeam = GetHogTeamName(hhs[i])
+
+	end	
+
+end
+
+function ResetAllAmmo()
+
+	AddAmmo(CurrentHedgehog, amBazooka, 0)
+	AddAmmo(CurrentHedgehog, amGrenade, 0)
+	AddAmmo(CurrentHedgehog, amShotgun, 0)
+	
+	AddAmmo(CurrentHedgehog, amGirder, 0)
+	AddAmmo(CurrentHedgehog, amBlowTorch, 0)
+	AddAmmo(CurrentHedgehog, amPickHammer, 0)
+	AddAmmo(CurrentHedgehog, amSwitch, 0)
+
+	AddAmmo(CurrentHedgehog, amRope, 0)
+	AddAmmo(CurrentHedgehog, amParachute, 0)
+	AddAmmo(CurrentHedgehog, amFirePunch, 0)
+
+	AddAmmo(CurrentHedgehog, amDynamite, 0)
+	AddAmmo(CurrentHedgehog, amDrill, 0)
+	AddAmmo(CurrentHedgehog, amMine, 0)
+
+	AddAmmo(CurrentHedgehog, amSniperRifle, 0)
+	AddAmmo(CurrentHedgehog, amDEagle, 0)
+	AddAmmo(CurrentHedgehog, amPortalGun, 0)
+
+	AddAmmo(CurrentHedgehog, amSeduction, 0)
+	AddAmmo(CurrentHedgehog, amResurrector, 0)
+	AddAmmo(CurrentHedgehog, amInvulnerable, 0)
+	
+	AddAmmo(CurrentHedgehog, amFlamethrower, 0)
+	AddAmmo(CurrentHedgehog, amMolotov, 0)
+	AddAmmo(CurrentHedgehog, amNapalm, 0)
+	
+	AddAmmo(CurrentHedgehog, amBaseballBat, 0)
+	AddAmmo(CurrentHedgehog, amGasBomb, 0)
+	AddAmmo(CurrentHedgehog, amKamikaze, 0)
+
+end
+
+function AssignAmmo()
+
+	ResetAllAmmo()	
+	n = GetHogName(CurrentHedgehog)
+
+	AddAmmo(CurrentHedgehog, amSkip,100)
+
+	if n == "Soldier" then 
+		AddAmmo(CurrentHedgehog, amBazooka,1)
+		AddAmmo(CurrentHedgehog, amGrenade,1)
+		AddAmmo(CurrentHedgehog, amShotgun,1)
+	elseif n == "Engineer" then
+		AddAmmo(CurrentHedgehog, amGirder, 2)
+		AddAmmo(CurrentHedgehog, amBlowTorch, 1)
+		AddAmmo(CurrentHedgehog, amPickHammer, 1)	
+		AddAmmo(CurrentHedgehog, amSwitch, 2)	
+	elseif n == "Ninja" then
+		AddAmmo(CurrentHedgehog, amRope, 100)
+		AddAmmo(CurrentHedgehog, amParachute, 100)
+		AddAmmo(CurrentHedgehog, amFirePunch, 1)
+	elseif n == "Demo" then
+		AddAmmo(CurrentHedgehog, amDynamite, 1)
+		AddAmmo(CurrentHedgehog, amMine, 1)
+		AddAmmo(CurrentHedgehog, amDrill, 1)
+	elseif n == "Sniper" then
+		AddAmmo(CurrentHedgehog, amSniperRifle, 1)
+		AddAmmo(CurrentHedgehog, amDEagle, 1)
+		AddAmmo(CurrentHedgehog, amPortalGun, 2)
+	elseif n == "Saint" then
+		AddAmmo(CurrentHedgehog, amSeduction, 100)
+		AddAmmo(CurrentHedgehog, amResurrector, 1)
+		AddAmmo(CurrentHedgehog, amInvulnerable, 1)
+	elseif n == "Pyro" then
+		AddAmmo(CurrentHedgehog, amFlamethrower, 1)
+		AddAmmo(CurrentHedgehog, amMolotov, 1)
+		AddAmmo(CurrentHedgehog, amNapalm, 1)
+	elseif n == "Loon" then
+		AddAmmo(CurrentHedgehog, amBaseballBat, 1)
+		AddAmmo(CurrentHedgehog, amGasBomb, 1)
+		AddAmmo(CurrentHedgehog, amKamikaze, 1)
+	end
+
+end
+
+function onGameInit()
+	GameFlags = gfRandomOrder + gfResetWeps + gfInfAttack + gfPlaceHog
+	Delay = 10
+end
+
+function onGameStart()
+   	
+	CreateTeam()
+
+	ShowMission	(
+				loc("THE SPECIALISTS"),
+				loc("a Hedgewars mini-game"),
+
+				loc("Eliminate the enemy specialists.") .. "|" ..
+				" " .. "|" ..
+
+				loc("Game Modifiers: ") .. "|" ..
+				loc("Per-Hog Ammo") .. "|" ..				
+				loc("Weapons Reset") .. "|" ..				
+				loc("Unlimited Attacks") .. "|" ..
+
+				"", 4, 4000
+				)
+
+end
+
+
+function onNewTurn()
+	currName = GetHogName(CurrentHedgehog)
+	lastName = GetHogName(CurrentHedgehog)
+	AssignAmmo()
+	AddAmmo(CurrentHedgehog, amSwitch, 1)
+end
+
+function onGameTick()
+
+	if (CurrentHedgehog ~= nil) then
+
+		currName = GetHogName(CurrentHedgehog)
+		
+		if currName ~= lastName then
+			AddCaption(loc("Switched to ") .. currName .. "!")
+			AssignAmmo()		
+		end
+
+		lastName = currName
+
+	end
+
+end
+
+function onGearAdd(gear)
+    
+	if GetGearType(gear) == gtHedgehog then
+		hhs[numhhs] = gear
+		numhhs = numhhs + 1
+	end
+
+end
+
+function onGearDelete(gear)
+--
+end
+
+function onAmmoStoreInit()
+
+end
+
+
+
Binary file share/hedgewars/Data/Themes/Art/Clouds.png has changed
Binary file share/hedgewars/Data/Themes/Art/Flake.png has changed
Binary file share/hedgewars/Data/Themes/Bamboo/SkyL.png has changed
Binary file share/hedgewars/Data/Themes/Bamboo/SkyR.png has changed
Binary file share/hedgewars/Data/Themes/Blox/Flake.png has changed
Binary file share/hedgewars/Data/Themes/Blox/Sky.png has changed
Binary file share/hedgewars/Data/Themes/Blox/icon.png has changed
Binary file share/hedgewars/Data/Themes/Blox/icon@2x.png has changed
Binary file share/hedgewars/Data/Themes/Blox/plant1.png has changed
Binary file share/hedgewars/Data/Themes/Blox/plant2.png has changed
Binary file share/hedgewars/Data/Themes/Blox/plant3.png has changed
Binary file share/hedgewars/Data/Themes/Blox/plant4.png has changed
Binary file share/hedgewars/Data/Themes/Blox/tmp.png has changed
--- a/share/hedgewars/Data/Themes/CMakeLists.txt	Tue Jun 21 16:43:05 2011 +0400
+++ b/share/hedgewars/Data/Themes/CMakeLists.txt	Thu Jun 23 21:19:43 2011 +0400
@@ -30,5 +30,3 @@
 	)
 	add_subdirectory(${dir})
 endforeach(dir)
-
-install(FILES themes.cfg DESTINATION ${SHAREPATH}Data/Themes)
Binary file share/hedgewars/Data/Themes/Cake/Clouds.png has changed
Binary file share/hedgewars/Data/Themes/Cake/icon.png has changed
Binary file share/hedgewars/Data/Themes/Cake/icon@2x.png has changed
Binary file share/hedgewars/Data/Themes/Cake/plant4.png has changed
--- a/share/hedgewars/Data/Themes/Cake/theme.cfg	Tue Jun 21 16:43:05 2011 +0400
+++ b/share/hedgewars/Data/Themes/Cake/theme.cfg	Thu Jun 23 21:19:43 2011 +0400
@@ -8,5 +8,4 @@
 object = plant1, 3, 83, 215, 92, 35, 1, 0, 0, 250, 190
 object = plant2, 3, 118, 115, 41, 20, 1, 0, 0, 159, 110
 object = plant3, 3, 0, 115, 70, 40, 1, 8, 0, 60, 100
-object = plant4, 3, 20, 200, 25, 5, 1, 0, 0, 70, 150
 flakes = 20, 100, 0, 30, 250
Binary file share/hedgewars/Data/Themes/Cheese/Flake.png has changed
Binary file share/hedgewars/Data/Themes/CrazyMission/Flake.png has changed
Binary file share/hedgewars/Data/Themes/CrazyMission/horizont.png has changed
Binary file share/hedgewars/Data/Themes/Deepspace/Clouds.png has changed
Binary file share/hedgewars/Data/Themes/Deepspace/horizont.png has changed
Binary file share/hedgewars/Data/Themes/EarthRise/Clouds.png has changed
Binary file share/hedgewars/Data/Themes/EarthRise/horizontL.png has changed
Binary file share/hedgewars/Data/Themes/EarthRise/horizontR.png has changed
Binary file share/hedgewars/Data/Themes/Halloween/SkyL.png has changed
Binary file share/hedgewars/Data/Themes/Halloween/SkyR.png has changed
Binary file share/hedgewars/Data/Themes/Jungle/SkyL.png has changed
Binary file share/hedgewars/Data/Themes/Jungle/SkyR.png has changed
Binary file share/hedgewars/Data/Themes/Planes/Flake.png has changed
--- a/share/hedgewars/Data/Themes/themes.cfg	Tue Jun 21 16:43:05 2011 +0400
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,22 +0,0 @@
-Art
-Bamboo
-Bath
-Brick
-Castle
-Cheese
-Christmas
-City
-Compost
-Desert
-EarthRise
-Freeway
-Halloween
-Hell
-Island
-Jungle
-Nature
-Olympics
-Sheep
-Snow
-Stage
-Underwater
Binary file share/hwico.icns has changed