Merge
authorMedo <smaxein@googlemail.com>
Wed, 02 May 2012 23:53:45 +0200
changeset 7006 6af78154dc62
parent 6852 9e724f4863a3 (current diff)
parent 7003 e118ee168577 (diff)
child 7009 23131a8b4c3a
Merge
QTfrontend/model/hats.cpp
QTfrontend/model/hats.h
QTfrontend/model/themesmodel.cpp
QTfrontend/model/themesmodel.h
QTfrontend/util/HWDataManager.cpp
QTfrontend/util/HWDataManager.h
foo
hedgewars/HHHandlers.inc
hedgewars/uKeys.pas
project_files/Android-build/SDL-android-project/src/org/hedgewars/hedgeroid/SDLActivity.java
project_files/HedgewarsMobile/Resources/backSound.wav
project_files/HedgewarsMobile/Resources/clickSound.wav
project_files/HedgewarsMobile/Resources/selSound.wav
share/hedgewars/Data/Maps/Sticks/map.cfg
share/hedgewars/Data/Maps/Sticks/preview@2x.png
share/hedgewars/Data/Music/Nature.ogg
--- a/CMakeLists.txt	Sun Apr 01 15:23:34 2012 +0200
+++ b/CMakeLists.txt	Wed May 02 23:53:45 2012 +0200
@@ -159,7 +159,7 @@
 
 if(Optz)
 #	set(pascal_compiler_flags_cmn "-O3" "-OpPENTIUM4" "-CfSSE3" "-Xs" "-Si" ${pascal_compiler_flags_cmn})
-	set(pascal_compiler_flags_cmn "-Os" "-Xs" "-Si" ${pascal_compiler_flags_cmn})
+	set(pascal_compiler_flags_cmn "-Os" "-Ooregvar" "-Xs" "-Si" ${pascal_compiler_flags_cmn})
 	set(haskell_compiler_flags_cmn "-w" "-fno-warn-unused-do-bind" ${haskell_compiler_flags_cmn})
 else(Optz)
 	set(pascal_compiler_flags_cmn "-O-" "-g" "-gl" "-gv" "-dDEBUGFILE" ${pascal_compiler_flags_cmn})
--- a/QTfrontend/CMakeLists.txt	Sun Apr 01 15:23:34 2012 +0200
+++ b/QTfrontend/CMakeLists.txt	Wed May 02 23:53:45 2012 +0200
@@ -119,6 +119,7 @@
     HWApplication.h
     hwform.h
     team.h
+    util/DataManager.h
     )
 
 set(hwfr_hdrs
--- a/QTfrontend/CocoaInitializer.h	Sun Apr 01 15:23:34 2012 +0200
+++ b/QTfrontend/CocoaInitializer.h	Wed May 02 23:53:45 2012 +0200
@@ -1,6 +1,6 @@
 /*
  * Hedgewars, a free turn based strategy game
- * Copyright (c) 2005-2012 Andrey Korotaev <unC0Rr@gmail.com>
+ * Copyright (c) 2004-2012 Andrey Korotaev <unC0Rr@gmail.com>
  *
  * This program is free software; you can redistribute it and/or modify
  * it under the terms of the GNU General Public License as published by
--- a/QTfrontend/CocoaInitializer.mm	Sun Apr 01 15:23:34 2012 +0200
+++ b/QTfrontend/CocoaInitializer.mm	Wed May 02 23:53:45 2012 +0200
@@ -1,6 +1,6 @@
 /*
  * Hedgewars, a free turn based strategy game
- * Copyright (c) 2005-2011 Andrey Korotaev <unC0Rr@gmail.com>
+ * Copyright (c) 2004-2012 Andrey Korotaev <unC0Rr@gmail.com>
  *
  * This program is free software; you can redistribute it and/or modify
  * it under the terms of the GNU General Public License as published by
--- a/QTfrontend/HWApplication.cpp	Sun Apr 01 15:23:34 2012 +0200
+++ b/QTfrontend/HWApplication.cpp	Wed May 02 23:53:45 2012 +0200
@@ -1,6 +1,6 @@
 /*
  * Hedgewars, a free turn based strategy game
- * Copyright (c) 2005-2012 Andrey Korotaev <unC0Rr@gmail.com>
+ * Copyright (c) 2004-2012 Andrey Korotaev <unC0Rr@gmail.com>
  *
  * This program is free software; you can redistribute it and/or modify
  * it under the terms of the GNU General Public License as published by
--- a/QTfrontend/HWApplication.h	Sun Apr 01 15:23:34 2012 +0200
+++ b/QTfrontend/HWApplication.h	Wed May 02 23:53:45 2012 +0200
@@ -1,6 +1,6 @@
 /*
  * Hedgewars, a free turn based strategy game
- * Copyright (c) 2005-2012 Andrey Korotaev <unC0Rr@gmail.com>
+ * Copyright (c) 2004-2012 Andrey Korotaev <unC0Rr@gmail.com>
  *
  * This program is free software; you can redistribute it and/or modify
  * it under the terms of the GNU General Public License as published by
--- a/QTfrontend/InstallController.cpp	Sun Apr 01 15:23:34 2012 +0200
+++ b/QTfrontend/InstallController.cpp	Wed May 02 23:53:45 2012 +0200
@@ -1,6 +1,6 @@
 /*
  * Hedgewars, a free turn based strategy game
- * Copyright (c) 2009-2012 Andrey Korotaev <unC0Rr@gmail.com>
+ * Copyright (c) 2004-2012 Andrey Korotaev <unC0Rr@gmail.com>
  *
  * This program is free software; you can redistribute it and/or modify
  * it under the terms of the GNU General Public License as published by
--- a/QTfrontend/InstallController.h	Sun Apr 01 15:23:34 2012 +0200
+++ b/QTfrontend/InstallController.h	Wed May 02 23:53:45 2012 +0200
@@ -1,6 +1,6 @@
 /*
  * Hedgewars, a free turn based strategy game
- * Copyright (c) 2009-2012 Andrey Korotaev <unC0Rr@gmail.com>
+ * Copyright (c) 2004-2012 Andrey Korotaev <unC0Rr@gmail.com>
  *
  * This program is free software; you can redistribute it and/or modify
  * it under the terms of the GNU General Public License as published by
--- a/QTfrontend/KB.h	Sun Apr 01 15:23:34 2012 +0200
+++ b/QTfrontend/KB.h	Wed May 02 23:53:45 2012 +0200
@@ -1,6 +1,6 @@
 /*
  * Hedgewars, a free turn based strategy game
- * Copyright (c) 2006-2012 Andrey Korotaev <unC0Rr@gmail.com>
+ * Copyright (c) 2004-2012 Andrey Korotaev <unC0Rr@gmail.com>
  *
  * This program is free software; you can redistribute it and/or modify
  * it under the terms of the GNU General Public License as published by
--- a/QTfrontend/M3Panel.h	Sun Apr 01 15:23:34 2012 +0200
+++ b/QTfrontend/M3Panel.h	Wed May 02 23:53:45 2012 +0200
@@ -1,6 +1,6 @@
 /*
  * Hedgewars, a free turn based strategy game
- * Copyright (c) 2009-2012 Andrey Korotaev <unC0Rr@gmail.com>
+ * Copyright (c) 2004-2012 Andrey Korotaev <unC0Rr@gmail.com>
  *
  * This program is free software; you can redistribute it and/or modify
  * it under the terms of the GNU General Public License as published by
--- a/QTfrontend/M3Panel.mm	Sun Apr 01 15:23:34 2012 +0200
+++ b/QTfrontend/M3Panel.mm	Wed May 02 23:53:45 2012 +0200
@@ -1,6 +1,6 @@
 /*
  * Hedgewars, a free turn based strategy game
- * Copyright (c) 2009-2011 Andrey Korotaev <unC0Rr@gmail.com>
+ * Copyright (c) 2004-2012 Andrey Korotaev <unC0Rr@gmail.com>
  *
  * This program is free software; you can redistribute it and/or modify
  * it under the terms of the GNU General Public License as published by
--- a/QTfrontend/SparkleAutoUpdater.mm	Sun Apr 01 15:23:34 2012 +0200
+++ b/QTfrontend/SparkleAutoUpdater.mm	Wed May 02 23:53:45 2012 +0200
@@ -1,6 +1,6 @@
 /*
  * Hedgewars, a free turn based strategy game
- * Copyright (c) 2005-2011 Andrey Korotaev <unC0Rr@gmail.com>
+ * Copyright (c) 2004-2012 Andrey Korotaev <unC0Rr@gmail.com>
  *
  * This program is free software; you can redistribute it and/or modify
  * it under the terms of the GNU General Public License as published by
--- a/QTfrontend/achievements.cpp	Sun Apr 01 15:23:34 2012 +0200
+++ b/QTfrontend/achievements.cpp	Wed May 02 23:53:45 2012 +0200
@@ -1,6 +1,6 @@
 /*
  * Hedgewars, a free turn based strategy game
- * Copyright (c) 2005-2012 Andrey Korotaev <unC0Rr@gmail.com>
+ * Copyright (c) 2004-2012 Andrey Korotaev <unC0Rr@gmail.com>
  *
  * This program is free software; you can redistribute it and/or modify
  * it under the terms of the GNU General Public License as published by
--- a/QTfrontend/achievements.h	Sun Apr 01 15:23:34 2012 +0200
+++ b/QTfrontend/achievements.h	Wed May 02 23:53:45 2012 +0200
@@ -1,6 +1,6 @@
 /*
  * Hedgewars, a free turn based strategy game
- * Copyright (c) 2005-2012 Andrey Korotaev <unC0Rr@gmail.com>
+ * Copyright (c) 2004-2012 Andrey Korotaev <unC0Rr@gmail.com>
  *
  * This program is free software; you can redistribute it and/or modify
  * it under the terms of the GNU General Public License as published by
--- a/QTfrontend/binds.cpp	Sun Apr 01 15:23:34 2012 +0200
+++ b/QTfrontend/binds.cpp	Wed May 02 23:53:45 2012 +0200
@@ -1,6 +1,6 @@
 /*
  * Hedgewars, a free turn based strategy game
- * Copyright (c) 2005-2012 Andrey Korotaev <unC0Rr@gmail.com>
+ * Copyright (c) 2004-2012 Andrey Korotaev <unC0Rr@gmail.com>
  *
  * This program is free software; you can redistribute it and/or modify
  * it under the terms of the GNU General Public License as published by
--- a/QTfrontend/binds.h	Sun Apr 01 15:23:34 2012 +0200
+++ b/QTfrontend/binds.h	Wed May 02 23:53:45 2012 +0200
@@ -1,6 +1,6 @@
 /*
  * Hedgewars, a free turn based strategy game
- * Copyright (c) 2005-2012 Andrey Korotaev <unC0Rr@gmail.com>
+ * Copyright (c) 2004-2012 Andrey Korotaev <unC0Rr@gmail.com>
  *
  * This program is free software; you can redistribute it and/or modify
  * it under the terms of the GNU General Public License as published by
--- a/QTfrontend/drawmapscene.cpp	Sun Apr 01 15:23:34 2012 +0200
+++ b/QTfrontend/drawmapscene.cpp	Wed May 02 23:53:45 2012 +0200
@@ -1,6 +1,6 @@
 /*
  * Hedgewars, a free turn based strategy game
- * Copyright (c) 2012 Andrey Korotaev <unC0Rr@gmail.com>
+ * Copyright (c) 2004-2012 Andrey Korotaev <unC0Rr@gmail.com>
  *
  * This program is free software; you can redistribute it and/or modify
  * it under the terms of the GNU General Public License as published by
@@ -31,19 +31,28 @@
 DrawMapScene::DrawMapScene(QObject *parent) :
     QGraphicsScene(parent),
     m_pen(Qt::yellow),
-    m_brush(Qt::yellow)
+    m_brush(Qt::yellow),
+    m_cursor(new QGraphicsEllipseItem(-0.5, -0.5, 1, 1))
 {
     setSceneRect(0, 0, 4096, 2048);
 
     QLinearGradient gradient(0, 0, 0, 2048);
     gradient.setColorAt(0, QColor(60, 60, 155));
     gradient.setColorAt(1, QColor(155, 155, 60));
-    setBackgroundBrush(QBrush(gradient));
+
+    m_eraser = QBrush(gradient);
+    setBackgroundBrush(m_eraser);
+    m_isErasing = false;
 
     m_pen.setWidth(76);
     m_pen.setJoinStyle(Qt::RoundJoin);
     m_pen.setCapStyle(Qt::RoundCap);
     m_currPath = 0;
+
+    m_isCursorShown = false;
+    m_cursor->setPen(QPen(Qt::green));
+    m_cursor->setZValue(1);
+    m_cursor->setScale(m_pen.width());
 }
 
 void DrawMapScene::mouseMoveEvent(QGraphicsSceneMouseEvent * mouseEvent)
@@ -62,12 +71,16 @@
         else
         {
             path.lineTo(mouseEvent->scenePos());
-            paths.first().second.append(mouseEvent->scenePos().toPoint());
+            paths.first().points.append(mouseEvent->scenePos().toPoint());
         }
         m_currPath->setPath(path);
 
         emit pathChanged();
     }
+
+    if(!m_isCursorShown)
+        showCursor();
+    m_cursor->setPos(mouseEvent->scenePos());
 }
 
 void DrawMapScene::mousePressEvent(QGraphicsSceneMouseEvent * mouseEvent)
@@ -79,7 +92,12 @@
     p += QPointF(0.01, 0.01);
     path.moveTo(p);
     path.lineTo(mouseEvent->scenePos());
-    paths.prepend(qMakePair(serializePenWidth(m_pen.width()), QList<QPoint>() << mouseEvent->scenePos().toPoint()));
+
+    PathParams params;
+    params.width = serializePenWidth(m_pen.width());
+    params.erasing = m_isErasing;
+    params.points = QList<QPoint>() << mouseEvent->scenePos().toPoint();
+    paths.prepend(params);
     m_currPath->setPath(path);
 
     emit pathChanged();
@@ -91,7 +109,7 @@
     {
         QPainterPath path = m_currPath->path();
         path.lineTo(mouseEvent->scenePos());
-        paths.first().second.append(mouseEvent->scenePos().toPoint());
+        paths.first().points.append(mouseEvent->scenePos().toPoint());
         m_currPath->setPath(path);
 
         simplifyLast();
@@ -107,15 +125,39 @@
     else if(wheelEvent->delta() < 0 && m_pen.width() >= 16)
         m_pen.setWidth(m_pen.width() - 10);
 
+    m_cursor->setScale(m_pen.width());
+
     if(m_currPath)
     {
         m_currPath->setPen(m_pen);
-        paths.first().first = serializePenWidth(m_pen.width());
+        paths.first().width = serializePenWidth(m_pen.width());
     }
 }
 
+void DrawMapScene::showCursor()
+{
+    qDebug() << "show cursor";
+    if(!m_isCursorShown)
+        addItem(m_cursor);
+
+    m_isCursorShown = true;
+}
+
+void DrawMapScene::hideCursor()
+{
+    qDebug() << "hide cursor";
+    if(m_isCursorShown)
+        removeItem(m_cursor);
+
+    m_isCursorShown = false;
+}
+
 void DrawMapScene::undo()
 {
+    // cursor is a part of items()
+    if(m_isCursorShown)
+        return;
+
     if(items().size())
     {
         removeItem(items().first());
@@ -135,6 +177,10 @@
 
 void DrawMapScene::clearMap()
 {
+    // cursor is a part of items()
+    if(m_isCursorShown)
+        return;
+
     // don't clear if already cleared
     if(!items().size())
         return;
@@ -155,6 +201,16 @@
     emit pathChanged();
 }
 
+
+void DrawMapScene::setErasing(bool erasing)
+{
+    m_isErasing = erasing;
+    if(erasing)
+        m_pen.setBrush(m_eraser);
+    else
+        m_pen.setBrush(m_brush);
+}
+
 QByteArray DrawMapScene::encode()
 {
     QByteArray b;
@@ -162,13 +218,14 @@
     for(int i = paths.size() - 1; i >= 0; --i)
     {
         int cnt = 0;
-        QPair<quint8, QList<QPoint> > points = paths.at(i);
-        foreach(QPoint point, points.second)
+        PathParams params = paths.at(i);
+        foreach(QPoint point, params.points)
         {
             qint16 px = qToBigEndian((qint16)point.x());
             qint16 py = qToBigEndian((qint16)point.y());
             quint8 flags = 0;
-            if(!cnt) flags = 0x80 + points.first;
+            if(!cnt) flags = 0x80 + params.width;
+            if(params.erasing) flags |= 0x40;
             b.append((const char *)&px, 2);
             b.append((const char *)&py, 2);
             b.append((const char *)&flags, 1);
@@ -183,12 +240,14 @@
 
 void DrawMapScene::decode(QByteArray data)
 {
+    bool erasing = m_isErasing;
+
     oldItems.clear();
     oldPaths.clear();
     clear();
     paths.clear();
 
-    QPair<quint8, QList<QPoint> > points;
+    PathParams params;
 
     while(data.size() >= 5)
     {
@@ -201,37 +260,43 @@
 
         if(flags & 0x80)
         {
-            if(points.second.size())
+            if(params.points.size())
             {
-                addPath(pointsToPath(points.second), m_pen);
+                addPath(pointsToPath(params.points), m_pen);
 
-                paths.prepend(points);
+                paths.prepend(params);
 
-                points.second.clear();
+                params.points.clear();
             }
 
-            quint8 penWidth = flags & 0x7f;
+            quint8 penWidth = flags & 0x3f;
             m_pen.setWidth(deserializePenWidth(penWidth));
-            points.first = penWidth;
+            if(flags & 0x40)
+                m_pen.setBrush(m_eraser);
+            else
+                m_pen.setBrush(m_brush);
+            params.width = penWidth;
         }
 
-        points.second.append(QPoint(px, py));
+        params.points.append(QPoint(px, py));
     }
 
-    if(points.second.size())
+    if(params.points.size())
     {
-        addPath(pointsToPath(points.second), m_pen);
-        paths.prepend(points);
+        addPath(pointsToPath(params.points), m_pen);
+        paths.prepend(params);
     }
 
     emit pathChanged();
+
+    setErasing(erasing);
 }
 
 void DrawMapScene::simplifyLast()
 {
     if(!paths.size()) return;
 
-    QList<QPoint> points = paths.at(0).second;
+    QList<QPoint> points = paths.at(0).points;
 
     QPoint prevPoint = points.first();
     int i = 1;
@@ -248,18 +313,27 @@
         }
     }
 
-    paths[0].second = points;
+    paths[0].points = points;
 
 
     // redraw path
     {
-        QGraphicsPathItem * pathItem = static_cast<QGraphicsPathItem *>(items()[0]);
-        pathItem->setPath(pointsToPath(paths[0].second));
+        QGraphicsPathItem * pathItem = static_cast<QGraphicsPathItem *>(items()[m_isCursorShown ? 1 : 0]);
+        pathItem->setPath(pointsToPath(paths[0].points));
     }
 
     emit pathChanged();
 }
 
+int DrawMapScene::pointsCount()
+{
+    int cnt = 0;
+    foreach(PathParams p, paths)
+        cnt += p.points.size();
+
+    return cnt;
+}
+
 QPainterPath DrawMapScene::pointsToPath(const QList<QPoint> points)
 {
     QPainterPath path;
--- a/QTfrontend/drawmapscene.h	Sun Apr 01 15:23:34 2012 +0200
+++ b/QTfrontend/drawmapscene.h	Wed May 02 23:53:45 2012 +0200
@@ -1,6 +1,6 @@
 /*
  * Hedgewars, a free turn based strategy game
- * Copyright (c) 2012 Andrey Korotaev <unC0Rr@gmail.com>
+ * Copyright (c) 2004-2012 Andrey Korotaev <unC0Rr@gmail.com>
  *
  * This program is free software; you can redistribute it and/or modify
  * it under the terms of the GNU General Public License as published by
@@ -21,10 +21,18 @@
 
 #include <QGraphicsScene>
 #include <QPainterPath>
+#include <QGraphicsEllipseItem>
 
 class QGraphicsPathItem;
 
-typedef QList<QPair<quint8, QList<QPoint> > > Paths;
+struct PathParams
+{
+    quint8 width;
+    bool erasing;
+    QList<QPoint> points;
+};
+
+typedef QList<PathParams> Paths;
 
 class DrawMapScene : public QGraphicsScene
 {
@@ -34,6 +42,7 @@
 
         QByteArray encode();
         void decode(QByteArray data);
+        int pointsCount();
 
     signals:
         void pathChanged();
@@ -42,14 +51,21 @@
         void undo();
         void clearMap();
         void simplifyLast();
+        void setErasing(bool erasing);
+        void showCursor();
+        void hideCursor();
 
     private:
         QPen m_pen;
+        QBrush m_eraser;
         QBrush m_brush;
         QGraphicsPathItem  * m_currPath;
         Paths paths;
         Paths oldPaths;
+        bool m_isErasing;
         QList<QGraphicsItem *> oldItems;
+        QGraphicsEllipseItem * m_cursor;
+        bool m_isCursorShown;
 
         virtual void mouseMoveEvent(QGraphicsSceneMouseEvent * mouseEvent);
         virtual void mousePressEvent(QGraphicsSceneMouseEvent * mouseEvent);
--- a/QTfrontend/game.cpp	Sun Apr 01 15:23:34 2012 +0200
+++ b/QTfrontend/game.cpp	Wed May 02 23:53:45 2012 +0200
@@ -1,6 +1,6 @@
 /*
  * Hedgewars, a free turn based strategy game
- * Copyright (c) 2005-2012 Andrey Korotaev <unC0Rr@gmail.com>
+ * Copyright (c) 2004-2012 Andrey Korotaev <unC0Rr@gmail.com>
  *
  * This program is free software; you can redistribute it and/or modify
  * it under the terms of the GNU General Public License as published by
@@ -115,10 +115,11 @@
 void HWGame::SendQuickConfig()
 {
     QByteArray teamscfg;
+    ThemeModel * themeModel = DataManager::instance().themeModel();
 
     HWProto::addStringToBuffer(teamscfg, "TL");
     HWProto::addStringToBuffer(teamscfg, QString("etheme %1")
-                               .arg((themesModel->rowCount() > 0) ? themesModel->index(rand() % themesModel->rowCount()).data().toString() : "steel"));
+                               .arg((themeModel->rowCount() > 0) ? themeModel->index(rand() % themeModel->rowCount()).data().toString() : "steel"));
     HWProto::addStringToBuffer(teamscfg, "eseed " + QUuid::createUuid().toString());
 
     HWTeam team1;
--- a/QTfrontend/game.h	Sun Apr 01 15:23:34 2012 +0200
+++ b/QTfrontend/game.h	Wed May 02 23:53:45 2012 +0200
@@ -1,6 +1,6 @@
 /*
  * Hedgewars, a free turn based strategy game
- * Copyright (c) 2005-2012 Andrey Korotaev <unC0Rr@gmail.com>
+ * Copyright (c) 2004-2012 Andrey Korotaev <unC0Rr@gmail.com>
  *
  * This program is free software; you can redistribute it and/or modify
  * it under the terms of the GNU General Public License as published by
--- a/QTfrontend/gameuiconfig.cpp	Sun Apr 01 15:23:34 2012 +0200
+++ b/QTfrontend/gameuiconfig.cpp	Wed May 02 23:53:45 2012 +0200
@@ -1,6 +1,6 @@
 /*
  * Hedgewars, a free turn based strategy game
- * Copyright (c) 2006-2012 Andrey Korotaev <unC0Rr@gmail.com>
+ * Copyright (c) 2004-2012 Andrey Korotaev <unC0Rr@gmail.com>
  *
  * This program is free software; you can redistribute it and/or modify
  * it under the terms of the GNU General Public License as published by
@@ -41,6 +41,11 @@
     //Form->resize(value("frontend/width", 640).toUInt(), value("frontend/height", 450).toUInt());
     resizeToConfigValues();
 
+    reloadValues();
+}
+
+void GameUIConfig::reloadValues(void)
+{
     Form->ui.pageOptions->WeaponTooltip->setChecked(value("misc/weaponTooltips", true).toBool());
 
     int t = Form->ui.pageOptions->CBResolution->findText(value("video/resolution").toString());
@@ -68,11 +73,18 @@
 
     QString netNick = value("net/nick", "").toString();
     Form->ui.pageOptions->editNetNick->setText(netNick);
+    bool savePwd = value("net/savepassword",true).toBool();
+    Form->ui.pageOptions->CBSavePassword->setChecked(savePwd);
 
     Form->ui.pageOptions->editNetPassword->installEventFilter(this);
 
     int passLength = value("net/passwordlength", 0).toInt();
     setNetPasswordLength(passLength);
+    if (savePwd == false) {
+        Form->ui.pageOptions->editNetPassword->setEnabled(savePwd);
+        Form->ui.pageOptions->editNetPassword->setText("");
+        setNetPasswordLength(0);        
+    }
 
     delete netHost;
     netHost = new QString(value("net/ip", "").toString());
@@ -149,11 +161,12 @@
     setValue("audio/volume", Form->ui.pageOptions->volumeBox->value());
 
     setValue("net/nick", netNick());
-    if (netPasswordIsValid())
+    if (netPasswordIsValid() && Form->ui.pageOptions->CBSavePassword->isChecked())
     {
         setValue("net/passwordhash", netPasswordHash());
         setValue("net/passwordlength", netPasswordLength());
     }
+    setValue("net/savepassword", Form->ui.pageOptions->CBSavePassword->isChecked());
     setValue("net/ip", *netHost);
     setValue("net/port", netPort);
     setValue("net/servername", Form->ui.pageNetServer->leServerDescr->text());
--- a/QTfrontend/gameuiconfig.h	Sun Apr 01 15:23:34 2012 +0200
+++ b/QTfrontend/gameuiconfig.h	Wed May 02 23:53:45 2012 +0200
@@ -1,6 +1,6 @@
 /*
  * Hedgewars, a free turn based strategy game
- * Copyright (c) 2006-2012 Andrey Korotaev <unC0Rr@gmail.com>
+ * Copyright (c) 2004-2012 Andrey Korotaev <unC0Rr@gmail.com>
  *
  * This program is free software; you can redistribute it and/or modify
  * it under the terms of the GNU General Public License as published by
@@ -64,6 +64,7 @@
         bool isAutoUpdateEnabled();
 #endif
 #endif
+        void reloadValues(void);
 
     signals:
         void frontendFullscreen(bool value);
--- a/QTfrontend/hwconsts.cpp.in	Sun Apr 01 15:23:34 2012 +0200
+++ b/QTfrontend/hwconsts.cpp.in	Wed May 02 23:53:45 2012 +0200
@@ -1,6 +1,6 @@
 /*
  * Hedgewars, a free turn based strategy game
- * Copyright (c) 2007-2011 Andrey Korotaev <unC0Rr@gmail.com>
+ * Copyright (c) 2004-2012 Andrey Korotaev <unC0Rr@gmail.com>
  *
  * This program is free software; you can redistribute it and/or modify
  * it under the terms of the GNU General Public License as published by
@@ -27,10 +27,6 @@
 QDir * cfgdir = new QDir();
 QDir * datadir = new QDir();
 
-ThemesModel * themesModel;
-QStringList * mapList;
-QStringList * scriptList;
-
 bool custom_config = false;
 bool custom_data = false;
 
--- a/QTfrontend/hwconsts.h	Sun Apr 01 15:23:34 2012 +0200
+++ b/QTfrontend/hwconsts.h	Wed May 02 23:53:45 2012 +0200
@@ -1,6 +1,6 @@
 /*
  * Hedgewars, a free turn based strategy game
- * Copyright (c) 2005-2012 Andrey Korotaev <unC0Rr@gmail.com>
+ * Copyright (c) 2004-2012 Andrey Korotaev <unC0Rr@gmail.com>
  *
  * This program is free software; you can redistribute it and/or modify
  * it under the terms of the GNU General Public License as published by
@@ -22,7 +22,6 @@
 #include <QStringList>
 #include <QPair>
 
-#include "themesmodel.h"
 
 extern QString * cProtoVer;
 extern QString * cVersionString;
@@ -41,10 +40,6 @@
 
 class QStringListModel;
 
-extern ThemesModel * themesModel;
-extern QStringList * mapList;
-extern QStringList * scriptList;
-
 extern QString * cDefaultAmmoStore;
 extern int cAmmoNumber;
 extern QList< QPair<QString, QString> > cDefaultAmmos;
--- a/QTfrontend/hwform.cpp	Sun Apr 01 15:23:34 2012 +0200
+++ b/QTfrontend/hwform.cpp	Wed May 02 23:53:45 2012 +0200
@@ -1,6 +1,6 @@
 /*
  * Hedgewars, a free turn based strategy game
- * Copyright (c) 2005-2012 Andrey Korotaev <unC0Rr@gmail.com>
+ * Copyright (c) 2004-2012 Andrey Korotaev <unC0Rr@gmail.com>
  *
  * This program is free software; you can redistribute it and/or modify
  * it under the terms of the GNU General Public License as published by
@@ -83,6 +83,7 @@
 #include "netudpserver.h"
 #include "chatwidget.h"
 #include "input_ip.h"
+#include "input_password.h"
 #include "ammoSchemeModel.h"
 #include "bgwidget.h"
 #include "xfire.h"
@@ -90,7 +91,7 @@
 #include "mouseoverfilter.h"
 #include "roomslistmodel.h"
 
-#include "HWDataManager.h"
+#include "DataManager.h"
 
 #ifdef __APPLE__
 #include "M3Panel.h"
@@ -119,7 +120,7 @@
 {
     // set music track
     SDLInteraction::instance().setMusicTrack(
-        HWDataManager::instance().findFileForRead("Music/main_theme.ogg")
+        DataManager::instance().findFileForRead("Music/main_theme.ogg")
     );
 
 #ifdef USE_XFIRE
@@ -154,8 +155,10 @@
     connect (hideFrontend, SIGNAL(activated()), this, SLOT(showMinimized()));
 #else
     // ctrl+q closes frontend for consistency
-    QShortcut *closeFrontend = new QShortcut(QKeySequence("Ctrl+Q"), this);
+    QShortcut * closeFrontend = new QShortcut(QKeySequence("Ctrl+Q"), this);
     connect (closeFrontend, SIGNAL(activated()), this, SLOT(close()));
+    QShortcut * updateData = new QShortcut(QKeySequence("F5"), this);
+    connect (updateData, SIGNAL(activated()), &DataManager::instance(), SLOT(reload()));
 #endif
 
     UpdateTeamsLists();
@@ -592,6 +595,11 @@
         ui.pageOptions->setTeamOptionsEnabled(true);
     }
 
+    if (id == ID_PAGE_SETUP)
+    {
+        config->reloadValues();
+    }
+
     // load and save ignore/friends lists
     if (lastid == ID_PAGE_NETGAME) // leaving a room
         ui.pageNetGame->pChatWidget->saveLists(ui.pageOptions->editNetNick->text());
@@ -638,7 +646,7 @@
         //New page animation
         animationNewSlide = new QPropertyAnimation(ui.Pages->widget(id), "pos");
         animationNewSlide->setDuration(duration);
-        animationNewSlide->setStartValue(QPoint(20000/coeff, 0));
+        animationNewSlide->setStartValue(QPoint(this->width()*1.5/coeff, 0));
         animationNewSlide->setEndValue(QPoint(0, 0));
         animationNewSlide->setEasingCurve(QEasingCurve::OutExpo);
 
@@ -656,7 +664,7 @@
         animationOldSlide = new QPropertyAnimation(ui.Pages->widget(lastid), "pos");
         animationOldSlide->setDuration(duration);
         animationOldSlide->setStartValue(QPoint(0, 0));
-        animationOldSlide->setEndValue(QPoint(-20000/coeff, 0));
+        animationOldSlide->setEndValue(QPoint(this->width()*1.5/coeff, 0));
         animationOldSlide->setEasingCurve(QEasingCurve::OutExpo);
 
 #ifdef false
@@ -935,25 +943,34 @@
 
 void HWForm::NetPassword(const QString & nick)
 {
-    bool ok = false;
     int passLength = config->value("net/passwordlength", 0).toInt();
     QString hash = config->value("net/passwordhash", "").toString();
 
     // If the password is blank, ask the user to enter one in
     if (passLength == 0)
     {
-        QString password = QInputDialog::getText(this, tr("Password"), tr("Your nickname %1 is\nregistered on Hedgewars.org\nPlease provide your password below\nor pick another nickname in game config:").arg(nick), QLineEdit::Password, passLength==0?NULL:QString(passLength,'\0'), &ok);
-
-        if (!ok)
+        HWPasswordDialog * hpd = new HWPasswordDialog(this, tr("Your nickname %1 is\nregistered on Hedgewars.org\nPlease provide your password below\nor pick another nickname in game config:").arg(nick));
+        hpd->cbSave->setChecked(config->value("net/savepassword", true).toBool());
+        if (hpd->exec() != QDialog::Accepted)
         {
             ForcedDisconnect(tr("No password supplied."));
+            delete hpd;
             return;
         }
 
+        QString password = hpd->lePassword->text();
         hash = QCryptographicHash::hash(password.toLatin1(), QCryptographicHash::Md5).toHex();
-        config->setValue("net/passwordhash", hash);
-        config->setValue("net/passwordlength", password.size());
-        config->setNetPasswordLength(password.size());
+
+        bool save = hpd->cbSave->isChecked();
+        config->setValue("net/savepassword", save);
+        if (save) // user wants to save password
+        {
+            config->setValue("net/passwordhash", hash);
+            config->setValue("net/passwordlength", password.size());
+            config->setNetPasswordLength(password.size());
+        }
+
+        delete hpd;
     }
 
     hwnet->SendPasswordHash(hash);
@@ -1180,6 +1197,7 @@
         netPort = hpd->sbPort->value();
         NetConnectServer(*netHost, netPort);
     }
+    delete hpd;
 }
 
 void HWForm::NetStartServer()
@@ -1524,7 +1542,7 @@
     HWTeam team(ui.pageCampaign->CBTeam->currentText());
     ui.pageCampaign->CBSelect->clear();
 
-    QStringList entries = HWDataManager::instance().entryList(
+    QStringList entries = DataManager::instance().entryList(
                               "Missions/Campaign",
                               QDir::Files,
                               QStringList("*#*.lua")
--- a/QTfrontend/hwform.h	Sun Apr 01 15:23:34 2012 +0200
+++ b/QTfrontend/hwform.h	Wed May 02 23:53:45 2012 +0200
@@ -1,6 +1,6 @@
 /*
  * Hedgewars, a free turn based strategy game
- * Copyright (c) 2005-2012 Andrey Korotaev <unC0Rr@gmail.com>
+ * Copyright (c) 2004-2012 Andrey Korotaev <unC0Rr@gmail.com>
  *
  * This program is free software; you can redistribute it and/or modify
  * it under the terms of the GNU General Public License as published by
--- a/QTfrontend/main.cpp	Sun Apr 01 15:23:34 2012 +0200
+++ b/QTfrontend/main.cpp	Wed May 02 23:53:45 2012 +0200
@@ -1,6 +1,6 @@
 /*
  * Hedgewars, a free turn based strategy game
- * Copyright (c) 2005-2012 Andrey Korotaev <unC0Rr@gmail.com>
+ * Copyright (c) 2004-2012 Andrey Korotaev <unC0Rr@gmail.com>
  *
  * This program is free software; you can redistribute it and/or modify
  * it under the terms of the GNU General Public License as published by
@@ -32,7 +32,7 @@
 #include "hwconsts.h"
 #include "newnetclient.h"
 
-#include "HWDataManager.h"
+#include "DataManager.h"
 
 #ifdef _WIN32
 #include <Shlobj.h>
@@ -209,67 +209,7 @@
         return 1;
     }
 
-    HWDataManager & dataMgr = HWDataManager::instance();
-
-    {
-        QStringList themes;
-
-        themes.append(dataMgr.entryList(
-                          "Themes",
-                          QDir::AllDirs | QDir::NoDotAndDotDot)
-                     );
-
-        QList<QPair<QIcon, QIcon> > icons;
-
-        themes.sort();
-        for(int i = themes.size() - 1; i >= 0; --i)
-        {
-            QString file = dataMgr.findFileForRead(
-                               QString("Themes/%1/icon.png").arg(themes.at(i))
-                           );
-
-            if(QFile::exists(file))
-            {
-                // load icon
-                QPair<QIcon, QIcon> ic;
-                ic.first = QIcon(file);
-
-                // load preview icon
-                ic.second = QIcon(
-                                dataMgr.findFileForRead(
-                                    QString("Themes/%1/icon@2x.png").arg(themes.at(i))
-                                )
-                            );
-
-                icons.prepend(ic);
-            }
-            else
-            {
-                themes.removeAt(i);
-            }
-        }
-
-        themesModel = new ThemesModel(themes);
-        Q_ASSERT(themes.size() == icons.size());
-        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);
-        }
-    }
-
-    mapList = new QStringList(dataMgr.entryList(
-                                  QString("Maps"),
-                                  QDir::Dirs | QDir::NoDotAndDotDot
-                              )
-                             );
-
-    scriptList = new QStringList(dataMgr.entryList(
-                                     QString("Scripts/Multiplayer"),
-                                     QDir::Files,
-                                     QStringList("*.lua")
-                                 )
-                                );
+    DataManager & dataMgr = DataManager::instance();
 
     QTranslator Translator;
     {
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/QTfrontend/model/GameStyleModel.cpp	Wed May 02 23:53:45 2012 +0200
@@ -0,0 +1,96 @@
+/*
+ * Hedgewars, a free turn based strategy game
+ * Copyright (c) 2004-2012 Andrey Korotaev <unC0Rr@gmail.com>
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; version 2 of the License
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA
+ */
+
+/**
+ * @file
+ * @brief GameStyleModel class implementation
+ */
+
+#include "GameStyleModel.h"
+
+
+void GameStyleModel::loadGameStyles()
+{
+    beginResetModel();
+
+
+    // empty list, so that we can (re)fill it
+    QStandardItemModel::clear();
+
+    QList<QStandardItem * > items;
+    items.append(new QStandardItem("Normal"));
+
+    // define a separator item
+    QStandardItem * separator = new QStandardItem("---");
+    separator->setData(QLatin1String("separator"), Qt::AccessibleDescriptionRole);
+    separator->setFlags(separator->flags() & ~( Qt::ItemIsEnabled | Qt::ItemIsSelectable ) );
+
+    items.append(separator);
+
+
+    QStringList scripts = DataManager::instance().entryList(
+                             QString("Scripts/Multiplayer"),
+                             QDir::Files,
+                             QStringList("*.lua")
+                         );
+
+    foreach(QString script, scripts)
+    {
+        script = script.remove(".lua", Qt::CaseInsensitive);
+
+        QFile scriptCfgFile(DataManager::instance().findFileForRead(
+                            QString("Scripts/Multiplayer/%2.cfg").arg(script)));
+
+        QString name = script;
+        name = name.replace("_", " ");
+
+        QString scheme = "locked";
+        QString weapons = "locked";
+
+        if (scriptCfgFile.exists() && scriptCfgFile.open(QFile::ReadOnly))
+        {
+            QTextStream input(&scriptCfgFile);
+            input >> scheme;
+            input >> weapons;
+            scriptCfgFile.close();
+
+            if (!scheme.isEmpty())
+                scheme.replace("_", " ");
+
+            if (!weapons.isEmpty())
+                weapons.replace("_", " ");
+        }
+
+        QStandardItem * item = new QStandardItem(name);
+
+        item->setData(script, ScriptRole);
+        item->setData(scheme, SchemeRole);
+        item->setData(weapons, WeaponsRole);
+
+        items.append(item);
+    }
+
+    QStandardItemModel::appendColumn(items);
+
+
+    endResetModel();
+}
+
+
+
+
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/QTfrontend/model/GameStyleModel.h	Wed May 02 23:53:45 2012 +0200
@@ -0,0 +1,48 @@
+/*
+ * Hedgewars, a free turn based strategy game
+ * Copyright (c) 2004-2012 Andrey Korotaev <unC0Rr@gmail.com>
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; version 2 of the License
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA
+ */
+
+/**
+ * @file
+ * @brief GameStyleModel class definition
+ */
+
+#ifndef HEDGEWARS_GAMESTYLEMODEL_H
+#define HEDGEWARS_GAMESTYLEMODEL_H
+
+#include <QStandardItemModel>
+#include <QStringList>
+#include <QMap>
+
+#include "DataManager.h"
+
+/**
+ * @brief A model listing available game styles
+ */
+class GameStyleModel : public QStandardItemModel
+{
+        Q_OBJECT
+
+    public:
+        enum DataRoles { ScriptRole = Qt::UserRole+1, SchemeRole, WeaponsRole };
+
+    public slots:
+        /// reloads the themes from the DataManager
+        void loadGameStyles();
+};
+
+#endif // HEDGEWARS_GAMESTYLEMODEL_H
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/QTfrontend/model/HatModel.cpp	Wed May 02 23:53:45 2012 +0200
@@ -0,0 +1,148 @@
+/*
+ * Hedgewars, a free turn based strategy game
+ * Copyright (c) 2004-2012 Andrey Korotaev <unC0Rr@gmail.com>
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; version 2 of the License
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA
+ */
+
+/**
+ * @file
+ * @brief HatModel class implementation
+ */
+
+#include "HatModel.h"
+
+#include <QDir>
+#include <QPixmap>
+#include <QPainter>
+#include "hwform.h" // player hash
+
+#include "DataManager.h"
+
+HatModel::HatModel(QObject* parent) :
+    QAbstractListModel(parent)
+{
+    hats = QVector<QPair<QString, QIcon> >();
+}
+
+void HatModel::loadHats()
+{
+    // this method resets the contents of this model (important to know for views).
+    beginResetModel();
+
+    // prepare hats Vector
+    hats.clear();
+
+    DataManager & dataMgr = DataManager::instance();
+
+    QPixmap hhpix = QPixmap(
+                        dataMgr.findFileForRead("Graphics/Hedgehog/Idle.png")
+                    ).copy(0, 0, 32, 32);
+
+    // my reserved hats
+    QStringList hatsList = dataMgr.entryList(
+                               "Graphics/Hats/Reserved",
+                               QDir::Files,
+                               QStringList(playerHash+"*.png")
+                           );
+
+    int nReserved = hatsList.size();
+
+    // regular hats
+    hatsList.append(dataMgr.entryList(
+                        "Graphics/Hats",
+                        QDir::Files,
+                        QStringList("*.png")
+                    )
+                   );
+
+
+    int nHats = hatsList.size();
+
+    for (int i = 0; i < nHats; i++)
+    {
+        bool isReserved = (i < nReserved);
+
+        QString str = hatsList.at(i);
+        str = str.remove(QRegExp("\\.png$"));
+        QPixmap pix(
+            dataMgr.findFileForRead(
+                "Graphics/Hats/" + QString(isReserved?"Reserved/":"") + str +
+                ".png"
+            )
+        );
+
+        // rename properly
+        if (isReserved)
+            str = "Reserved "+str.remove(0,32);
+
+        QPixmap tmppix(32, 37);
+        tmppix.fill(QColor(Qt::transparent));
+
+        QPainter painter(&tmppix);
+        painter.drawPixmap(QPoint(0, 5), hhpix);
+        painter.drawPixmap(QPoint(0, 0), pix.copy(0, 0, 32, 32));
+        if(pix.width() > 32)
+            painter.drawPixmap(QPoint(0, 0), pix.copy(32, 0, 32, 32));
+        painter.end();
+
+        if (str == "NoHat")
+            hats.prepend(qMakePair(str, QIcon(tmppix)));
+        else
+            hats.append(qMakePair(str, QIcon(tmppix)));
+    }
+
+
+    endResetModel();
+}
+
+QVariant HatModel::headerData(int section,
+                               Qt::Orientation orientation, int role) const
+{
+    Q_UNUSED(section);
+    Q_UNUSED(orientation);
+    Q_UNUSED(role);
+
+    return QVariant();
+}
+
+int HatModel::rowCount(const QModelIndex &parent) const
+{
+    if (parent.isValid())
+        return 0;
+    else
+        return hats.size();
+}
+
+/*int HatModel::columnCount(const QModelIndex & parent) const
+{
+    if (parent.isValid())
+        return 0;
+    else
+        return 2;
+}
+*/
+QVariant HatModel::data(const QModelIndex &index,
+                         int role) const
+{
+    if (!index.isValid() || index.row() < 0
+            || index.row() >= hats.size()
+            || (role != Qt::DisplayRole && role != Qt::DecorationRole))
+        return QVariant();
+
+    if (role == Qt::DisplayRole)
+        return hats.at(index.row()).first;
+    else // role == Qt::DecorationRole
+        return hats.at(index.row()).second;
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/QTfrontend/model/HatModel.h	Wed May 02 23:53:45 2012 +0200
@@ -0,0 +1,53 @@
+/*
+ * Hedgewars, a free turn based strategy game
+ * Copyright (c) 2004-2012 Andrey Korotaev <unC0Rr@gmail.com>
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; version 2 of the License
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA
+ */
+
+/**
+ * @file
+ * @brief HatModel class definition
+ */
+
+#ifndef HEDGEWARS_HATMODEL_H
+#define HEDGEWARS_HATMODEL_H
+
+#include <QAbstractListModel>
+#include <QStringList>
+#include <QVector>
+#include <QPair>
+#include <QIcon>
+
+class HatModel : public QAbstractListModel
+{
+        Q_OBJECT
+
+    public:
+        HatModel(QObject *parent = 0);
+
+        QVariant headerData(int section, Qt::Orientation orientation, int role) const;
+        int rowCount(const QModelIndex & parent) const;
+        //int columnCount(const QModelIndex & parent) const;
+
+    public slots:
+        /// Reloads hats using the DataManager.
+        void loadHats();
+
+        QVariant data(const QModelIndex &index, int role) const;
+    protected:
+        QVector<QPair<QString, QIcon> > hats;
+};
+
+#endif // HEDGEWARS_HATMODEL_H
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/QTfrontend/model/MapModel.cpp	Wed May 02 23:53:45 2012 +0200
@@ -0,0 +1,238 @@
+/*
+ * Hedgewars, a free turn based strategy game
+ * Copyright (c) 2004-2012 Andrey Korotaev <unC0Rr@gmail.com>
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; version 2 of the License
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA
+ */
+
+/**
+ * @file
+ * @brief MapModel class implementation
+ */
+
+#include "MapModel.h"
+
+
+void MapModel::loadMaps()
+{
+    // this method resets the contents of this model (important to know for views).
+    beginResetModel();
+
+    // we'll need the DataManager a few times, so let's get a reference to it
+    DataManager & datamgr = DataManager::instance();
+
+    // fetch list of available maps
+    QStringList maps =
+        datamgr.entryList("Maps", QDir::AllDirs | QDir::NoDotAndDotDot);
+
+    // empty list, so that we can (re)fill it
+    QStandardItemModel::clear();
+
+    QList<QStandardItem *> genMaps;
+    QList<QStandardItem *> missionMaps;
+    QList<QStandardItem *> staticMaps;
+
+    // add generated/handdrawn maps to list
+    // TODO: icons for these
+
+    genMaps.append(
+        infoToItem(QIcon(), QComboBox::tr("generated map..."), GeneratedMap, "+rnd+"));
+    genMaps.append(
+        infoToItem(QIcon(), QComboBox::tr("generated maze..."), GeneratedMaze, "+maze+"));
+    genMaps.append(
+        infoToItem(QIcon(), QComboBox::tr("hand drawn map..."), HandDrawnMap, "+drawn+"));
+
+    // only 2 map relate files are relevant:
+    // - the cfg file that contains the settings/info of the map
+    // - the lua file - if it exists it's a mission, otherwise it isn't
+    QFile mapLuaFile;
+    QFile mapCfgFile;
+
+    // add mission/static maps to lists
+    foreach (QString map, maps)
+    {
+        mapCfgFile.setFileName(
+            datamgr.findFileForRead(QString("Maps/%1/map.cfg").arg(map)));
+        mapLuaFile.setFileName(
+            datamgr.findFileForRead(QString("Maps/%1/map.lua").arg(map)));
+
+
+        if (mapCfgFile.open(QFile::ReadOnly))
+        {
+            QString caption;
+            QString theme;
+            quint32 limit = 0;
+            QString scheme;
+            QString weapons;
+            // if there is a lua file for this map, then it's a mission
+            bool isMission = mapLuaFile.exists();
+            MapType type = isMission?MissionMap:StaticMap;
+
+            // load map info from file
+            QTextStream input(&mapCfgFile);
+            input >> theme;
+            input >> limit;
+            if (isMission) { // scheme and weapons are only relevant for missions
+                input >> scheme;
+                input >> weapons;
+            }
+            mapCfgFile.close();
+
+            // let's use some semi-sane hedgehog limit, rather than none
+            if (limit == 0)
+                limit = 18;
+
+
+            // the default scheme/weaponset for missions.
+            // if empty we assume the map sets these internally -> locked
+            if (isMission)
+            {
+                if (scheme.isEmpty())
+                    scheme = "locked";
+                else
+                    scheme.replace("_", " ");
+
+                if (weapons.isEmpty())
+                    weapons = "locked";
+                else
+                    weapons.replace("_", " ");
+            }
+
+            // add a mission caption prefix to missions
+            if (isMission)
+            {
+                // TODO: icon
+                caption = QComboBox::tr("Mission") + ": " + map;
+            }
+            else
+                caption = map;
+
+            // we know everything there is about the map, let's get am item for it
+            QStandardItem * item = infoToItem(
+                QIcon(), caption, type, map, theme, limit, scheme, weapons);
+
+            // append item to the list
+            if (isMission)
+                missionMaps.append(item);
+            else
+                staticMaps.append(item);
+        
+        }
+
+    }
+
+
+    // define a separator item
+    QStandardItem separator("---");
+    separator.setData(QLatin1String("separator"), Qt::AccessibleDescriptionRole);
+    separator.setFlags(separator.flags() & ~( Qt::ItemIsEnabled | Qt::ItemIsSelectable ) );
+
+    // create list:
+    // generated+handdrawn maps, 2 saperators, missions, 1 separator, static maps
+    QList<QStandardItem * > items;
+    items.append(genMaps);
+    items.append(separator.clone());
+    items.append(separator.clone());
+    items.append(missionMaps);
+    items.append(separator.clone());
+    items.append(staticMaps);
+
+
+    // create row-index lookup table
+
+    m_mapIndexes.clear();
+
+    int count = items.size();
+
+    for (int i = 0; i < count; i++)
+    {
+        QStandardItem * si = items.at(i);
+        QVariant v = si->data(Qt::UserRole + 1);
+        if (v.canConvert<MapInfo>())
+            m_mapIndexes.insert(v.value<MapInfo>().name, i);
+    }
+
+
+    // store start-index and count of relevant types
+
+    m_typeLoc.insert(GeneratedMap, QPair<int,int>(0, 1));
+    m_typeLoc.insert(GeneratedMaze, QPair<int,int>(1, 1));
+    m_typeLoc.insert(HandDrawnMap, QPair<int,int>(2, 1));
+    // mission maps
+    int startIdx = genMaps.size() + 2; // start after genMaps and 2 separators
+    count = missionMaps.size();
+    m_typeLoc.insert(MissionMap, QPair<int,int>(startIdx, count));
+    // static maps
+    startIdx += count + 1; // start after missions and 2 separators
+    count = staticMaps.size();
+    m_typeLoc.insert(StaticMap, QPair<int,int>(startIdx, count));
+
+    // store list contents in the item model
+    QStandardItemModel::appendColumn(items);
+
+
+    endResetModel();
+}
+
+
+int MapModel::randomMap(MapType type) const
+{
+    // return a random index for this type or -1 if none available
+    QPair<int,int> loc = m_typeLoc.value(type, QPair<int,int>(-1,0));
+
+    int startIdx = loc.first;
+    int count = loc.second;
+
+    if (count < 1)
+        return -1;
+    else
+        return startIdx + (rand() % count);
+}
+
+
+QStandardItem * MapModel::infoToItem(
+    const QIcon & icon,
+    const QString caption,
+    MapType type,
+    QString name,
+    QString theme,
+    quint32 limit,
+    QString scheme,
+    QString weapons)
+const
+{
+    QStandardItem * item = new QStandardItem(icon, caption);
+    MapInfo mapInfo;
+    QVariant qvar(QVariant::UserType);
+
+    mapInfo.type = type;
+    mapInfo.name = name;
+    mapInfo.theme = theme;
+    mapInfo.limit = limit;
+    mapInfo.scheme = scheme;
+    mapInfo.weapons = weapons;
+
+
+    qvar.setValue(mapInfo);
+    item->setData(qvar, Qt::UserRole + 1);
+
+    return item;
+}
+
+
+int MapModel::indexOf(const QString & map) const
+{
+    return m_mapIndexes.value(map, -1);
+}
+
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/QTfrontend/model/MapModel.h	Wed May 02 23:53:45 2012 +0200
@@ -0,0 +1,120 @@
+/*
+ * Hedgewars, a free turn based strategy game
+ * Copyright (c) 2004-2012 Andrey Korotaev <unC0Rr@gmail.com>
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; version 2 of the License
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA
+ */
+
+/**
+ * @file
+ * @brief MapModel class definition
+ */
+
+#ifndef HEDGEWARS_MAPMODEL_H
+#define HEDGEWARS_MAPMODEL_H
+
+#include <QStandardItemModel>
+#include <QStringList>
+#include <QTextStream>
+#include <QHash>
+#include <QMap>
+#include <QIcon>
+#include <QComboBox>
+
+#include "DataManager.h"
+
+/**
+ * @brief A model that vertically lists available maps
+ *
+ * @author sheepluva
+ * @since 0.9.18
+ */
+class MapModel : public QStandardItemModel
+{
+        Q_OBJECT
+
+    public:
+        enum MapType {
+            Invalid,
+            GeneratedMap,
+            GeneratedMaze,
+            HandDrawnMap,
+            MissionMap,
+            StaticMap
+        };
+
+        /// a struct for holding the attributes of a map.
+        struct MapInfo
+        {
+            MapType type; ///< The map-type
+            QString name; ///< The internal name.
+            QString theme; ///< The theme to be used. (can be empty)
+            quint32 limit; ///< The maximum allowed number of hedgehogs.
+            QString scheme; ///< Default scheme name or "locked", for mission-maps.
+            QString weapons; ///< Default weaponset name or "locked", for missions-maps.
+        };
+
+        /**
+         * @brief Returns the row-index of the given map.
+         * @param map map of which to get the row-index of.
+         * @return row-index of map or -1 if not available.
+         */
+        int indexOf(const QString & map) const;
+
+        /**
+         * @brief Returns the row-index of a random map with a specified type.
+         * @param type desired type of map.
+         * @return row-index of a map with the desired type, -1 if none found.
+         */
+        int randomMap(MapType type) const;
+
+    public slots:
+        /// Reloads the maps using the DataManager.
+        void loadMaps();
+
+
+    private:
+        /// start-index and map count for each map-type.
+        QMap<MapType, QPair<int,int> > m_typeLoc;
+
+        /// map index lookup table
+        QHash<QString, int> m_mapIndexes;
+
+        /**
+         * @brief Creates a QStandardItem, that holds the map info and item appearance.
+         * The used role for the data is Qt::UserRole + 1.
+         * @param icon the icon to be displayed (can be an empty QIcon()).
+         * @param caption the text to be displayed.
+         * @param type the type of the map.
+         * @param name the internal name of the map.
+         * @param theme the theme of the map (or empty if none).
+         * @param limit the hedgehog limit of the map.
+         * @param scheme mission map: default scheme name or "locked".
+         * @param weapons mission map: default weaponset name or "locked".
+         * @return pointer to item representing the map info: at Qt::UserRole + 1.
+         */
+        QStandardItem * infoToItem(
+            const QIcon & icon,
+            const QString caption,
+            MapType type = Invalid,
+            QString name = "",
+            QString theme = "",
+            quint32 limit = 0,
+            QString scheme = "",
+            QString weapons = "") const;
+};
+
+Q_DECLARE_METATYPE(MapModel::MapInfo)
+
+#endif // HEDGEWARS_MAPMODEL_H
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/QTfrontend/model/ThemeModel.cpp	Wed May 02 23:53:45 2012 +0200
@@ -0,0 +1,97 @@
+/*
+ * Hedgewars, a free turn based strategy game
+ * Copyright (c) 2004-2012 Andrey Korotaev <unC0Rr@gmail.com>
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; version 2 of the License
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA
+ */
+
+/**
+ * @file
+ * @brief ThemeModel class implementation
+ */
+
+#include "ThemeModel.h"
+
+ThemeModel::ThemeModel(QObject *parent) :
+    QAbstractListModel(parent)
+{
+    m_data = QList<QMap<int, QVariant> >();
+}
+
+int ThemeModel::rowCount(const QModelIndex &parent) const
+{
+    if(parent.isValid())
+        return 0;
+    else
+        return m_data.size();
+}
+
+
+QVariant ThemeModel::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);
+}
+
+
+void ThemeModel::loadThemes()
+{
+    beginResetModel();
+
+
+    DataManager & datamgr = DataManager::instance();
+
+    QStringList themes =
+        datamgr.entryList("Themes", QDir::AllDirs | QDir::NoDotAndDotDot);
+
+    m_data.clear();
+
+#if QT_VERSION >= QT_VERSION_CHECK(4, 7, 0)
+    m_data.reserve(themes.size());
+#endif
+
+    foreach (QString theme, themes)
+    {
+        // themes without icon are supposed to be hidden
+        QString iconpath =
+            datamgr.findFileForRead(QString("Themes/%1/icon.png").arg(theme));
+
+        if (!QFile::exists(iconpath))
+            continue;
+
+        QMap<int, QVariant> dataset;
+
+        // set name
+        dataset.insert(Qt::DisplayRole, theme);
+
+        // load and set icon
+        QIcon icon(iconpath);
+        dataset.insert(Qt::DecorationRole, icon);
+
+        // load and set preview icon
+        QIcon preview(datamgr.findFileForRead(QString("Themes/%1/icon@2x.png").arg(theme)));
+        dataset.insert(Qt::UserRole, preview);
+
+        m_data.append(dataset);
+    }
+
+
+    endResetModel();
+}
+
+
+
+
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/QTfrontend/model/ThemeModel.h	Wed May 02 23:53:45 2012 +0200
@@ -0,0 +1,57 @@
+/*
+ * Hedgewars, a free turn based strategy game
+ * Copyright (c) 2004-2012 Andrey Korotaev <unC0Rr@gmail.com>
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; version 2 of the License
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA
+ */
+
+/**
+ * @file
+ * @brief ThemeModel class definition
+ */
+
+#ifndef HEDGEWARS_THEMEMODEL_H
+#define HEDGEWARS_THEMEMODEL_H
+
+#include <QAbstractListModel>
+#include <QStringList>
+#include <QMap>
+#include <QIcon>
+
+#include "DataManager.h"
+
+/**
+ * @brief A model listing available themes
+ */
+class ThemeModel : public QAbstractListModel
+{
+        Q_OBJECT
+
+    public:
+        explicit ThemeModel(QObject *parent = 0);
+
+        int rowCount(const QModelIndex &parent = QModelIndex()) const;
+        QVariant data(const QModelIndex &index, int role) const;
+
+
+    public slots:
+        /// reloads the themes from the DataManager
+        void loadThemes();
+
+
+    private:
+        QList<QMap<int, QVariant> > m_data;
+};
+
+#endif // HEDGEWARS_THEMEMODEL_H
--- a/QTfrontend/model/ammoSchemeModel.cpp	Sun Apr 01 15:23:34 2012 +0200
+++ b/QTfrontend/model/ammoSchemeModel.cpp	Wed May 02 23:53:45 2012 +0200
@@ -1,6 +1,6 @@
 /*
  * Hedgewars, a free turn based strategy game
- * Copyright (c) 2005-2012 Andrey Korotaev <unC0Rr@gmail.com>
+ * Copyright (c) 2004-2012 Andrey Korotaev <unC0Rr@gmail.com>
  *
  * This program is free software; you can redistribute it and/or modify
  * it under the terms of the GNU General Public License as published by
--- a/QTfrontend/model/ammoSchemeModel.h	Sun Apr 01 15:23:34 2012 +0200
+++ b/QTfrontend/model/ammoSchemeModel.h	Wed May 02 23:53:45 2012 +0200
@@ -1,6 +1,6 @@
 /*
  * Hedgewars, a free turn based strategy game
- * Copyright (c) 2005-2012 Andrey Korotaev <unC0Rr@gmail.com>
+ * Copyright (c) 2004-2012 Andrey Korotaev <unC0Rr@gmail.com>
  *
  * This program is free software; you can redistribute it and/or modify
  * it under the terms of the GNU General Public License as published by
--- a/QTfrontend/model/hats.cpp	Sun Apr 01 15:23:34 2012 +0200
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,129 +0,0 @@
-/*
- * Hedgewars, a free turn based strategy game
- * Copyright (c) 2008-2012 Andrey Korotaev <unC0Rr@gmail.com>
- *
- * This program is free software; you can redistribute it and/or modify
- * it under the terms of the GNU General Public License as published by
- * the Free Software Foundation; version 2 of the License
- *
- * This program is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
- * GNU General Public License for more details.
- *
- * You should have received a copy of the GNU General Public License
- * along with this program; if not, write to the Free Software
- * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA
- */
-
-#include <QDir>
-#include <QPixmap>
-#include <QPainter>
-#include "hwconsts.h"
-#include "hwform.h"
-#include "hats.h"
-
-#include "HWDataManager.h"
-
-HatsModel::HatsModel(QObject* parent) :
-    QAbstractListModel(parent)
-{
-    HWDataManager & dataMgr = HWDataManager::instance();
-
-    QPixmap hhpix = QPixmap(
-                        dataMgr.findFileForRead("Graphics/Hedgehog/Idle.png")
-                    ).copy(0, 0, 32, 32);
-
-    // my reserved hats
-    QStringList hatsList = dataMgr.entryList(
-                               "Graphics/Hats/Reserved",
-                               QDir::Files,
-                               QStringList(playerHash+"*.png")
-                           );
-
-    int nReserved = hatsList.size();
-
-    // regular hats
-    hatsList.append(dataMgr.entryList(
-                        "Graphics/Hats",
-                        QDir::Files,
-                        QStringList("*.png")
-                    )
-                   );
-
-
-    int nHats = hatsList.size();
-
-    for (int i = 0; i < nHats; i++)
-    {
-        bool isReserved = (i < nReserved);
-
-        QString str = hatsList.at(i);
-        str = str.remove(QRegExp("\\.png$"));
-        QPixmap pix(
-            dataMgr.findFileForRead(
-                "Graphics/Hats/" + QString(isReserved?"Reserved/":"") + str +
-                ".png"
-            )
-        );
-
-        // rename properly
-        if (isReserved)
-            str = "Reserved "+str.remove(0,32);
-
-        QPixmap tmppix(32, 37);
-        tmppix.fill(QColor(Qt::transparent));
-
-        QPainter painter(&tmppix);
-        painter.drawPixmap(QPoint(0, 5), hhpix);
-        painter.drawPixmap(QPoint(0, 0), pix.copy(0, 0, 32, 32));
-        if(pix.width() > 32)
-            painter.drawPixmap(QPoint(0, 0), pix.copy(32, 0, 32, 32));
-        painter.end();
-
-        if (str == "NoHat")
-            hats.prepend(qMakePair(str, QIcon(tmppix)));
-        else
-            hats.append(qMakePair(str, QIcon(tmppix)));
-    }
-}
-
-QVariant HatsModel::headerData(int section,
-                               Qt::Orientation orientation, int role) const
-{
-    Q_UNUSED(section);
-    Q_UNUSED(orientation);
-    Q_UNUSED(role);
-
-    return QVariant();
-}
-
-int HatsModel::rowCount(const QModelIndex &parent) const
-{
-    if (parent.isValid())
-        return 0;
-    else
-        return hats.size();
-}
-
-/*int HatsModel::columnCount(const QModelIndex & parent) const
-{
-    if (parent.isValid())
-        return 0;
-    else
-        return 2;
-}
-*/
-QVariant HatsModel::data(const QModelIndex &index,
-                         int role) const
-{
-    if (!index.isValid() || index.row() < 0
-            || index.row() >= hats.size()
-            || (role != Qt::DisplayRole && role != Qt::DecorationRole))
-        return QVariant();
-
-    if (role == Qt::DisplayRole)
-        return hats.at(index.row()).first;
-    else // role == Qt::DecorationRole
-        return hats.at(index.row()).second;
-}
--- a/QTfrontend/model/hats.h	Sun Apr 01 15:23:34 2012 +0200
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,44 +0,0 @@
-/*
- * Hedgewars, a free turn based strategy game
- * Copyright (c) 2008-2012 Andrey Korotaev <unC0Rr@gmail.com>
- *
- * This program is free software; you can redistribute it and/or modify
- * it under the terms of the GNU General Public License as published by
- * the Free Software Foundation; version 2 of the License
- *
- * This program is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
- * GNU General Public License for more details.
- *
- * You should have received a copy of the GNU General Public License
- * along with this program; if not, write to the Free Software
- * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA
- */
-
-#ifndef _HATS_INCLUDED
-#define _HATS_INCLUDED
-
-#include <QAbstractListModel>
-#include <QStringList>
-#include <QVector>
-#include <QPair>
-#include <QIcon>
-
-class HatsModel : public QAbstractListModel
-{
-        Q_OBJECT
-
-    public:
-        HatsModel(QObject *parent = 0);
-
-        QVariant headerData(int section, Qt::Orientation orientation, int role) const;
-        int rowCount(const QModelIndex & parent) const;
-        //int columnCount(const QModelIndex & parent) const;
-
-        QVariant data(const QModelIndex &index, int role) const;
-    protected:
-        QVector<QPair<QString, QIcon> > hats;
-};
-
-#endif // _HATS_INCLUDED
--- a/QTfrontend/model/netserverslist.cpp	Sun Apr 01 15:23:34 2012 +0200
+++ b/QTfrontend/model/netserverslist.cpp	Wed May 02 23:53:45 2012 +0200
@@ -1,6 +1,6 @@
 /*
  * Hedgewars, a free turn based strategy game
- * Copyright (c) 2007-2012 Andrey Korotaev <unC0Rr@gmail.com>
+ * Copyright (c) 2004-2012 Andrey Korotaev <unC0Rr@gmail.com>
  *
  * This program is free software; you can redistribute it and/or modify
  * it under the terms of the GNU General Public License as published by
--- a/QTfrontend/model/netserverslist.h	Sun Apr 01 15:23:34 2012 +0200
+++ b/QTfrontend/model/netserverslist.h	Wed May 02 23:53:45 2012 +0200
@@ -1,6 +1,6 @@
 /*
  * Hedgewars, a free turn based strategy game
- * Copyright (c) 2007-2012 Andrey Korotaev <unC0Rr@gmail.com>
+ * Copyright (c) 2004-2012 Andrey Korotaev <unC0Rr@gmail.com>
  *
  * This program is free software; you can redistribute it and/or modify
  * it under the terms of the GNU General Public License as published by
--- a/QTfrontend/model/roomslistmodel.cpp	Sun Apr 01 15:23:34 2012 +0200
+++ b/QTfrontend/model/roomslistmodel.cpp	Wed May 02 23:53:45 2012 +0200
@@ -1,11 +1,39 @@
+/*
+ * Hedgewars, a free turn based strategy game
+ * Copyright (c) 2004-2012 Andrey Korotaev <unC0Rr@gmail.com>
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; version 2 of the License
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA
+ */
+
+/**
+ * @file
+ * @brief RoomsListModel class implementation
+ */
+
 #include "roomslistmodel.h"
 
+#include <QBrush>
+#include <QColor>
+#include <QIcon>
+
 RoomsListModel::RoomsListModel(QObject *parent) :
-    QAbstractTableModel(parent)
+    QAbstractTableModel(parent),
+    c_nColumns(8)
 {
     m_headerData =
     QStringList()
-     << QString()
+     << tr("In progress")
      << tr("Room Name")
      << tr("C")
      << tr("T")
@@ -13,8 +41,11 @@
      << tr("Map")
      << tr("Rules")
      << tr("Weapons");
+
+    m_mapModel = DataManager::instance().mapModel();
 }
 
+
 QVariant RoomsListModel::headerData(int section, Qt::Orientation orientation, int role) const
 {
     if(orientation == Qt::Vertical || role != Qt::DisplayRole)
@@ -23,6 +54,7 @@
         return QVariant(m_headerData.at(section));
 }
 
+
 int RoomsListModel::rowCount(const QModelIndex & parent) const
 {
     if(parent.isValid())
@@ -31,49 +63,130 @@
         return m_data.size();
 }
 
+
 int RoomsListModel::columnCount(const QModelIndex & parent) const
 {
     if(parent.isValid())
         return 0;
     else
-        return 8;
+        return c_nColumns;
 }
 
+
 QVariant RoomsListModel::data(const QModelIndex &index, int role) const
 {
-    if (!index.isValid() || index.row() < 0
-            || index.row() >= m_data.size()
-            || index.column() >= 8
-            || (role != Qt::EditRole && role != Qt::DisplayRole)
-       )
+    int column = index.column();
+    int row = index.row();
+
+    // invalid index
+    if (!index.isValid())
+        return QVariant();
+
+    // invalid row
+    if ((row < 0) || (row >= m_data.size()))
+        return QVariant();
+
+    // invalid column
+    if ((column < 0) || (column >= c_nColumns))
         return QVariant();
 
-    return m_data.at(index.row()).at(index.column());
+    // not a role we have data for
+    if (role != Qt::DisplayRole)
+        // only custom-align counters
+        if ((role != Qt::TextAlignmentRole)
+            || ((column != PlayerCountColumn) && (column != TeamCountColumn)))
+                // only decorate name column
+                if ((role != Qt::DecorationRole) || (column != NameColumn))
+                    // only dye map column
+                    if ((role != Qt::ForegroundRole) || (column != MapColumn))
+                        return QVariant();
+
+    // decorate room name based on room state
+    if (role == Qt::DecorationRole)
+    {
+        const QIcon roomBusyIcon(":/res/iconDamage.png");
+        const QIcon roomWaitingIcon(":/res/iconTime.png");
+
+        if (m_data.at(row).at(0).isEmpty())
+            return QVariant(roomWaitingIcon);
+        else
+            return QVariant(roomBusyIcon);
+    }
+
+    QString content = m_data.at(row).at(column);
+
+    if (role == Qt::DisplayRole)
+    {
+        // supply in progress flag as bool
+        if (column == 0)
+            return QVariant(QString(!content.isEmpty()));
+
+        // display room names
+        if (column == 5)
+        {
+            // special names
+            if (content[0] == '+')
+            {
+                if (content == "+rnd+") return tr("Random Map");
+                if (content == "+maze+") return tr("Random Maze");
+                if (content == "+drawn+") return tr("Hand-drawn");
+            }
+
+            // prefix ? if map not available
+            if ((m_mapModel->indexOf(content) < 0))
+                return QString ("? %1").arg(content);
+        }
+
+        return content;
+    }
+
+    // dye map names red if map not available
+    if (role == Qt::ForegroundRole)
+    {
+        if ((m_mapModel->indexOf(content) < 0))
+            return QBrush(QColor("darkred"));
+        else
+            return QVariant();
+    }
+
+    if (role == Qt::TextAlignmentRole)
+    {
+        return (int)(Qt::AlignHCenter | Qt::AlignVCenter);
+    }
+
+    Q_ASSERT(false);
+    return QVariant();
 }
 
+
 void RoomsListModel::setRoomsList(const QStringList & rooms)
 {
-    if(m_data.size())
-    {
-        beginRemoveRows(QModelIndex(), 0, m_data.size() - 1);
-        m_data.clear();
-        endRemoveRows();
-    }
+    beginResetModel();
+
+    m_data.clear();
 
-    for(int i = 0; i < rooms.size(); i += 8)
+    int nRooms = rooms.size();
+
+    for (int i = 0; i < nRooms; i += c_nColumns)
     {
         QStringList l;
-        //l.reserve(8);  not really that useful an optimisation and causes problems w/ old Qt.  Harmless to leave it out.
-        for(int t = 0; t < 8; ++t)
+
+#if QT_VERSION >= QT_VERSION_CHECK(4, 7, 0)
+        l.reserve(c_nColumns);  // small optimisation not supported in old Qt
+#endif
+
+        for (int t = 0; t < c_nColumns; t++)
+        {
             l.append(rooms[i + t]);
+        }
 
         m_data.append(roomInfo2RoomRecord(l));
     }
 
-    beginInsertRows(QModelIndex(), 0, m_data.size() - 1);
-    endInsertRows();
+    endResetModel();
 }
 
+
 void RoomsListModel::addRoom(const QStringList & info)
 {
     beginInsertRows(QModelIndex(), 0, 0);
@@ -83,12 +196,33 @@
     endInsertRows();
 }
 
+
+int RoomsListModel::rowOfRoom(const QString & name)
+{
+    int size = m_data.size();
+
+    if (size < 1)
+        return -1;
+
+    int i = 0;
+
+    // search for record with matching room name
+    while(m_data[i].at(NameColumn) != name)
+    {
+        i++;
+        if(i >= size)
+            return -1;
+    }
+
+    return i;
+}
+
+
 void RoomsListModel::removeRoom(const QString & name)
 {
-    int i = 0;
-    while(i < m_data.size() && m_data[i].at(0) != name)
-        ++i;
-    if(i >= m_data.size())
+    int i = rowOfRoom(name);
+
+    if (i < 0)
         return;
 
     beginRemoveRows(QModelIndex(), i, i);
@@ -98,25 +232,32 @@
     endRemoveRows();
 }
 
+
 void RoomsListModel::updateRoom(const QString & name, const QStringList & info)
 {
-    int i = 0;
-    while(i < m_data.size() && m_data[i].at(0) != name)
-        ++i;
-    if(i >= m_data.size())
+    int i = rowOfRoom(name);
+
+    if (i < 0)
         return;
 
-
     m_data[i] = roomInfo2RoomRecord(info);
 
     emit dataChanged(index(i, 0), index(i, columnCount(QModelIndex()) - 1));
 }
 
+
 QStringList RoomsListModel::roomInfo2RoomRecord(const QStringList & info)
 {
     QStringList result;
 
     result = info;
 
+    // for matters of less memory usage and quicker access store
+    // the boolean string as either "t" or empty
+    if (info[StateColumn].toLower() == "true")
+        result[StateColumn] = "t";
+    else
+        result[StateColumn] = QString();
+
     return result;
 }
--- a/QTfrontend/model/roomslistmodel.h	Sun Apr 01 15:23:34 2012 +0200
+++ b/QTfrontend/model/roomslistmodel.h	Wed May 02 23:53:45 2012 +0200
@@ -1,13 +1,51 @@
-#ifndef ROOMSLISTMODEL_H
-#define ROOMSLISTMODEL_H
+/*
+ * Hedgewars, a free turn based strategy game
+ * Copyright (c) 2004-2012 Andrey Korotaev <unC0Rr@gmail.com>
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; version 2 of the License
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA
+ */
+
+/**
+ * @file
+ * @brief RoomsListModel class definition
+ */
+
+#ifndef HEDGEWARS_ROOMSLISTMODEL_H
+#define HEDGEWARS_ROOMSLISTMODEL_H
 
 #include <QAbstractTableModel>
 #include <QStringList>
 
+#include "DataManager.h"
+
 class RoomsListModel : public QAbstractTableModel
 {
     Q_OBJECT
 public:
+    // if you add a column here, also incr. c_nColumns in constructor
+    // also adjust header in constructor to changes
+    enum Column {
+        StateColumn,
+        NameColumn,
+        PlayerCountColumn,
+        TeamCountColumn,
+        OwnerColumn,
+        MapColumn,
+        SchemeColumn,
+        WeaponsColumn
+    };
+
     explicit RoomsListModel(QObject *parent = 0);
 
     QVariant headerData(int section, Qt::Orientation orientation, int role) const;
@@ -20,12 +58,15 @@
     void addRoom(const QStringList & info);
     void removeRoom(const QString & name);
     void updateRoom(const QString & name, const QStringList & info);
+    int rowOfRoom(const QString & name);
 
 private:
+    const int c_nColumns;
     QList<QStringList> m_data;
     QStringList m_headerData;
+    MapModel * m_mapModel;
 
     QStringList roomInfo2RoomRecord(const QStringList & info);
 };
 
-#endif // ROOMSLISTMODEL_H
+#endif // HEDGEWARS_ROOMSLISTMODEL_H
--- a/QTfrontend/model/themesmodel.cpp	Sun Apr 01 15:23:34 2012 +0200
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,49 +0,0 @@
-
-#include "themesmodel.h"
-
-ThemesModel::ThemesModel(QStringList themes, QObject *parent) :
-    QAbstractListModel(parent)
-{
-#if QT_VERSION >= QT_VERSION_CHECK(4, 7, 0)
-    m_data.reserve(themes.size());
-#endif
-
-    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;
-    }
-
-}
-
-
-
-
--- a/QTfrontend/model/themesmodel.h	Sun Apr 01 15:23:34 2012 +0200
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,28 +0,0 @@
-#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/net/hwmap.cpp	Sun Apr 01 15:23:34 2012 +0200
+++ b/QTfrontend/net/hwmap.cpp	Wed May 02 23:53:45 2012 +0200
@@ -1,7 +1,7 @@
 /*
  * Hedgewars, a free turn based strategy game
  * Copyright (c) 2006-2007 Ulyanov Igor <iulyanov@gmail.com>
- * Copyright (c) 2007-2012 Andrey Korotaev <unC0Rr@gmail.com>
+ * Copyright (c) 2004-2012 Andrey Korotaev <unC0Rr@gmail.com>
  *
  * This program is free software; you can redistribute it and/or modify
  * it under the terms of the GNU General Public License as published by
--- a/QTfrontend/net/hwmap.h	Sun Apr 01 15:23:34 2012 +0200
+++ b/QTfrontend/net/hwmap.h	Wed May 02 23:53:45 2012 +0200
@@ -1,7 +1,7 @@
 /*
  * Hedgewars, a free turn based strategy game
  * Copyright (c) 2006 Igor Ulyanov <iulyanov@gmail.com>
- * Copyright (c) 2006-2012 Andrey Korotaev <unC0Rr@gmail.com>
+ * Copyright (c) 2004-2012 Andrey Korotaev <unC0Rr@gmail.com>
  *
  * This program is free software; you can redistribute it and/or modify
  * it under the terms of the GNU General Public License as published by
--- a/QTfrontend/net/netregister.cpp	Sun Apr 01 15:23:34 2012 +0200
+++ b/QTfrontend/net/netregister.cpp	Wed May 02 23:53:45 2012 +0200
@@ -1,6 +1,6 @@
 /*
  * Hedgewars, a free turn based strategy game
- * Copyright (c) 2007-2012 Andrey Korotaev <unC0Rr@gmail.com>
+ * Copyright (c) 2004-2012 Andrey Korotaev <unC0Rr@gmail.com>
  *
  * This program is free software; you can redistribute it and/or modify
  * it under the terms of the GNU General Public License as published by
--- a/QTfrontend/net/netregister.h	Sun Apr 01 15:23:34 2012 +0200
+++ b/QTfrontend/net/netregister.h	Wed May 02 23:53:45 2012 +0200
@@ -1,6 +1,6 @@
 /*
  * Hedgewars, a free turn based strategy game
- * Copyright (c) 2007-2012 Andrey Korotaev <unC0Rr@gmail.com>
+ * Copyright (c) 2004-2012 Andrey Korotaev <unC0Rr@gmail.com>
  *
  * This program is free software; you can redistribute it and/or modify
  * it under the terms of the GNU General Public License as published by
--- a/QTfrontend/net/netserver.cpp	Sun Apr 01 15:23:34 2012 +0200
+++ b/QTfrontend/net/netserver.cpp	Wed May 02 23:53:45 2012 +0200
@@ -1,7 +1,7 @@
 /*
  * Hedgewars, a free turn based strategy game
  * Copyright (c) 2006-2008 Igor Ulyanov <iulyanov@gmail.com>
- * Copyright (c) 2008-2012 Andrey Korotaev <unC0Rr@gmail.com>
+ * Copyright (c) 2004-2012 Andrey Korotaev <unC0Rr@gmail.com>
  *
  * This program is free software; you can redistribute it and/or modify
  * it under the terms of the GNU General Public License as published by
--- a/QTfrontend/net/netserver.h	Sun Apr 01 15:23:34 2012 +0200
+++ b/QTfrontend/net/netserver.h	Wed May 02 23:53:45 2012 +0200
@@ -1,7 +1,7 @@
 /*
  * Hedgewars, a free turn based strategy game
  * Copyright (c) 2006-2008 Igor Ulyanov <iulyanov@gmail.com>
- * Copyright (c) 2008-2012 Andrey Korotaev <unC0Rr@gmail.com>
+ * Copyright (c) 2004-2012 Andrey Korotaev <unC0Rr@gmail.com>
  *
  * This program is free software; you can redistribute it and/or modify
  * it under the terms of the GNU General Public License as published by
--- a/QTfrontend/net/netudpserver.cpp	Sun Apr 01 15:23:34 2012 +0200
+++ b/QTfrontend/net/netudpserver.cpp	Wed May 02 23:53:45 2012 +0200
@@ -1,7 +1,7 @@
 /*
  * Hedgewars, a free turn based strategy game
  * Copyright (c) 2007-2008 Igor Ulyanov <iulyanov@gmail.com>
- * Copyright (c) 2008-2012 Andrey Korotaev <unC0Rr@gmail.com>
+ * Copyright (c) 2004-2012 Andrey Korotaev <unC0Rr@gmail.com>
  *
  * This program is free software; you can redistribute it and/or modify
  * it under the terms of the GNU General Public License as published by
--- a/QTfrontend/net/netudpserver.h	Sun Apr 01 15:23:34 2012 +0200
+++ b/QTfrontend/net/netudpserver.h	Wed May 02 23:53:45 2012 +0200
@@ -1,7 +1,7 @@
 /*
  * Hedgewars, a free turn based strategy game
  * Copyright (c) 2007-2008 Igor Ulyanov <iulyanov@gmail.com>
- * Copyright (c) 2008-2012 Andrey Korotaev <unC0Rr@gmail.com>
+ * Copyright (c) 2004-2012 Andrey Korotaev <unC0Rr@gmail.com>
  *
  * This program is free software; you can redistribute it and/or modify
  * it under the terms of the GNU General Public License as published by
--- a/QTfrontend/net/netudpwidget.cpp	Sun Apr 01 15:23:34 2012 +0200
+++ b/QTfrontend/net/netudpwidget.cpp	Wed May 02 23:53:45 2012 +0200
@@ -1,7 +1,7 @@
 /*
  * Hedgewars, a free turn based strategy game
  * Copyright (c) 2007 Igor Ulyanov <iulyanov@gmail.com>
- * Copyright (c) 2007-2012 Andrey Korotaev <unC0Rr@gmail.com>
+ * Copyright (c) 2004-2012 Andrey Korotaev <unC0Rr@gmail.com>
  *
  * This program is free software; you can redistribute it and/or modify
  * it under the terms of the GNU General Public License as published by
--- a/QTfrontend/net/netudpwidget.h	Sun Apr 01 15:23:34 2012 +0200
+++ b/QTfrontend/net/netudpwidget.h	Wed May 02 23:53:45 2012 +0200
@@ -1,7 +1,7 @@
 /*
  * Hedgewars, a free turn based strategy game
  * Copyright (c) 2007 Igor Ulyanov <iulyanov@gmail.com>
- * Copyright (c) 2007-2012 Andrey Korotaev <unC0Rr@gmail.com>
+ * Copyright (c) 2004-2012 Andrey Korotaev <unC0Rr@gmail.com>
  *
  * This program is free software; you can redistribute it and/or modify
  * it under the terms of the GNU General Public License as published by
--- a/QTfrontend/net/newnetclient.cpp	Sun Apr 01 15:23:34 2012 +0200
+++ b/QTfrontend/net/newnetclient.cpp	Wed May 02 23:53:45 2012 +0200
@@ -1,7 +1,7 @@
 /*
  * Hedgewars, a free turn based strategy game
  * Copyright (c) 2006-2008 Igor Ulyanov <iulyanov@gmail.com>
- * Copyright (c) 2008-2012 Andrey Korotaev <unC0Rr@gmail.com>
+ * Copyright (c) 2004-2012 Andrey Korotaev <unC0Rr@gmail.com>
  *
  * This program is free software; you can redistribute it and/or modify
  * it under the terms of the GNU General Public License as published by
--- a/QTfrontend/net/newnetclient.h	Sun Apr 01 15:23:34 2012 +0200
+++ b/QTfrontend/net/newnetclient.h	Wed May 02 23:53:45 2012 +0200
@@ -1,7 +1,7 @@
 /*
  * Hedgewars, a free turn based strategy game
  * Copyright (c) 2006-2008 Igor Ulyanov <iulyanov@gmail.com>
- * Copyright (c) 2008-2012 Andrey Korotaev <unC0Rr@gmail.com>
+ * Copyright (c) 2004-2012 Andrey Korotaev <unC0Rr@gmail.com>
  *
  * This program is free software; you can redistribute it and/or modify
  * it under the terms of the GNU General Public License as published by
--- a/QTfrontend/net/proto.cpp	Sun Apr 01 15:23:34 2012 +0200
+++ b/QTfrontend/net/proto.cpp	Wed May 02 23:53:45 2012 +0200
@@ -1,6 +1,6 @@
 /*
  * Hedgewars, a free turn based strategy game
- * Copyright (c) 2006-2012 Andrey Korotaev <unC0Rr@gmail.com>
+ * Copyright (c) 2004-2012 Andrey Korotaev <unC0Rr@gmail.com>
  *
  * This program is free software; you can redistribute it and/or modify
  * it under the terms of the GNU General Public License as published by
--- a/QTfrontend/net/proto.h	Sun Apr 01 15:23:34 2012 +0200
+++ b/QTfrontend/net/proto.h	Wed May 02 23:53:45 2012 +0200
@@ -1,6 +1,6 @@
 /*
  * Hedgewars, a free turn based strategy game
- * Copyright (c) 2006-2012 Andrey Korotaev <unC0Rr@gmail.com>
+ * Copyright (c) 2004-2012 Andrey Korotaev <unC0Rr@gmail.com>
  *
  * This program is free software; you can redistribute it and/or modify
  * it under the terms of the GNU General Public License as published by
--- a/QTfrontend/net/tcpBase.cpp	Sun Apr 01 15:23:34 2012 +0200
+++ b/QTfrontend/net/tcpBase.cpp	Wed May 02 23:53:45 2012 +0200
@@ -1,7 +1,7 @@
 /*
  * Hedgewars, a free turn based strategy game
  * Copyright (c) 2006-2007 Igor Ulyanov <iulyanov@gmail.com>
- * Copyright (c) 2007-2012 Andrey Korotaev <unC0Rr@gmail.com>
+ * Copyright (c) 2004-2012 Andrey Korotaev <unC0Rr@gmail.com>
  *
  * This program is free software; you can redistribute it and/or modify
  * it under the terms of the GNU General Public License as published by
--- a/QTfrontend/net/tcpBase.h	Sun Apr 01 15:23:34 2012 +0200
+++ b/QTfrontend/net/tcpBase.h	Wed May 02 23:53:45 2012 +0200
@@ -1,7 +1,7 @@
 /*
  * Hedgewars, a free turn based strategy game
  * Copyright (c) 2006-2007 Igor Ulyanov <iulyanov@gmail.com>
- * Copyright (c) 2007-2012 Andrey Korotaev <unC0Rr@gmail.com>
+ * Copyright (c) 2004-2012 Andrey Korotaev <unC0Rr@gmail.com>
  *
  * This program is free software; you can redistribute it and/or modify
  * it under the terms of the GNU General Public License as published by
--- a/QTfrontend/sdlkeys.h	Sun Apr 01 15:23:34 2012 +0200
+++ b/QTfrontend/sdlkeys.h	Wed May 02 23:53:45 2012 +0200
@@ -1,6 +1,6 @@
 /*
  * Hedgewars, a free turn based strategy game
- * Copyright (c) 2005-2012 Andrey Korotaev <unC0Rr@gmail.com>
+ * Copyright (c) 2004-2012 Andrey Korotaev <unC0Rr@gmail.com>
  *
  * This program is free software; you can redistribute it and/or modify
  * it under the terms of the GNU General Public License as published by
--- a/QTfrontend/team.cpp	Sun Apr 01 15:23:34 2012 +0200
+++ b/QTfrontend/team.cpp	Wed May 02 23:53:45 2012 +0200
@@ -1,6 +1,6 @@
 /*
  * Hedgewars, a free turn based strategy game
- * Copyright (c) 2005-2012 Andrey Korotaev <unC0Rr@gmail.com>
+ * Copyright (c) 2004-2012 Andrey Korotaev <unC0Rr@gmail.com>
  *
  * This program is free software; you can redistribute it and/or modify
  * it under the terms of the GNU General Public License as published by
@@ -25,7 +25,6 @@
 
 #include "team.h"
 #include "hwform.h"
-#include "hats.h"
 
 HWTeam::HWTeam(const QString & teamname) :
     QObject(0)
--- a/QTfrontend/team.h	Sun Apr 01 15:23:34 2012 +0200
+++ b/QTfrontend/team.h	Wed May 02 23:53:45 2012 +0200
@@ -1,6 +1,6 @@
 /*
  * Hedgewars, a free turn based strategy game
- * Copyright (c) 2005-2012 Andrey Korotaev <unC0Rr@gmail.com>
+ * Copyright (c) 2004-2012 Andrey Korotaev <unC0Rr@gmail.com>
  * Copyright (c) 2007 Igor Ulyanov <iulyanov@gmail.com>
  *
  * This program is free software; you can redistribute it and/or modify
--- a/QTfrontend/ui/dialog/input_ip.cpp	Sun Apr 01 15:23:34 2012 +0200
+++ b/QTfrontend/ui/dialog/input_ip.cpp	Wed May 02 23:53:45 2012 +0200
@@ -1,6 +1,6 @@
 /*
  * Hedgewars, a free turn based strategy game
- * Copyright (c) 2007-2012 Andrey Korotaev <unC0Rr@gmail.com>
+ * Copyright (c) 2004-2012 Andrey Korotaev <unC0Rr@gmail.com>
  *
  * This program is free software; you can redistribute it and/or modify
  * it under the terms of the GNU General Public License as published by
--- a/QTfrontend/ui/dialog/input_ip.h	Sun Apr 01 15:23:34 2012 +0200
+++ b/QTfrontend/ui/dialog/input_ip.h	Wed May 02 23:53:45 2012 +0200
@@ -1,6 +1,6 @@
 /*
  * Hedgewars, a free turn based strategy game
- * Copyright (c) 2007-2012 Andrey Korotaev <unC0Rr@gmail.com>
+ * Copyright (c) 2004-2012 Andrey Korotaev <unC0Rr@gmail.com>
  *
  * This program is free software; you can redistribute it and/or modify
  * it under the terms of the GNU General Public License as published by
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/QTfrontend/ui/dialog/input_password.cpp	Wed May 02 23:53:45 2012 +0200
@@ -0,0 +1,53 @@
+/*
+ * Hedgewars, a free turn based strategy game
+ * Copyright (c) 2004-2012 Andrey Korotaev <unC0Rr@gmail.com>
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; version 2 of the License
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA
+ */
+
+#include <QLineEdit>
+#include <QDialogButtonBox>
+#include <QPushButton>
+#include <QGridLayout>
+#include <QCheckBox>
+#include <QLabel>
+
+#include "input_password.h"
+
+HWPasswordDialog::HWPasswordDialog(QWidget* parent, const QString & label) : QDialog(parent)
+{
+    setWindowTitle(tr("Password"));
+
+    QGridLayout * layout = new QGridLayout(this);
+
+    QLabel * lbLabel = new QLabel(this);
+    lbLabel->setText(label);
+    layout->addWidget(lbLabel, 0, 0);
+
+    lePassword = new QLineEdit(this);
+    lePassword->setEchoMode(QLineEdit::Password);
+    layout->addWidget(lePassword, 1, 0);
+
+    cbSave = new QCheckBox(this);
+    cbSave->setText(QCheckBox::tr("Save password"));
+    layout->addWidget(cbSave, 2, 0);
+
+    QDialogButtonBox* dbbButtons = new QDialogButtonBox(this);
+    QPushButton * pbOK = dbbButtons->addButton(QDialogButtonBox::Ok);
+    QPushButton * pbCancel = dbbButtons->addButton(QDialogButtonBox::Cancel);
+    layout->addWidget(dbbButtons, 3, 0);
+
+    connect(pbOK, SIGNAL(clicked()), this, SLOT(accept()));
+    connect(pbCancel, SIGNAL(clicked()), this, SLOT(reject()));
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/QTfrontend/ui/dialog/input_password.h	Wed May 02 23:53:45 2012 +0200
@@ -0,0 +1,38 @@
+/*
+ * Hedgewars, a free turn based strategy game
+ * Copyright (c) 2004-2012 Andrey Korotaev <unC0Rr@gmail.com>
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; version 2 of the License
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA
+ */
+
+#ifndef INPUT_PASSWORD_H
+#define INPUT_PASSWORD_H
+
+#include <QDialog>
+
+class QLineEdit;
+class QCheckBox;
+
+class HWPasswordDialog : public QDialog
+{
+        Q_OBJECT
+    public:
+        HWPasswordDialog(QWidget* parent, const QString & label);
+
+        QLineEdit* lePassword;
+        QCheckBox* cbSave;
+};
+
+
+#endif // INPUT_PASSWORD_H
--- a/QTfrontend/ui/mouseoverfilter.cpp	Sun Apr 01 15:23:34 2012 +0200
+++ b/QTfrontend/ui/mouseoverfilter.cpp	Wed May 02 23:53:45 2012 +0200
@@ -11,7 +11,7 @@
 #include "ui_hwform.h"
 #include "hwform.h"
 #include "gameuiconfig.h"
-#include "HWDataManager.h"
+#include "DataManager.h"
 #include "SDLInteraction.h"
 
 MouseOverFilter::MouseOverFilter(QObject *parent) :
@@ -41,7 +41,7 @@
         QTabWidget * tab = dynamic_cast<QTabWidget*>(dist);
         if (HWForm::config->isFrontendSoundEnabled() && (button || textfield || checkbox || droplist || slider || tab))
         {
-            HWDataManager & dataMgr = HWDataManager::instance();
+            DataManager & dataMgr = DataManager::instance();
             SDLInteraction::instance().playSoundFile(dataMgr.findFileForRead("Sounds/steps.ogg"));
         }
 
--- a/QTfrontend/ui/page/AbstractPage.cpp	Sun Apr 01 15:23:34 2012 +0200
+++ b/QTfrontend/ui/page/AbstractPage.cpp	Wed May 02 23:53:45 2012 +0200
@@ -1,6 +1,6 @@
 /*
  * Hedgewars, a free turn based strategy game
- * Copyright (c) 2006-2012 Andrey Korotaev <unC0Rr@gmail.com>
+ * Copyright (c) 2004-2012 Andrey Korotaev <unC0Rr@gmail.com>
  *
  * This program is free software; you can redistribute it and/or modify
  * it under the terms of the GNU General Public License as published by
--- a/QTfrontend/ui/page/AbstractPage.h	Sun Apr 01 15:23:34 2012 +0200
+++ b/QTfrontend/ui/page/AbstractPage.h	Wed May 02 23:53:45 2012 +0200
@@ -1,6 +1,6 @@
 /*
  * Hedgewars, a free turn based strategy game
- * Copyright (c) 2006-2012 Andrey Korotaev <unC0Rr@gmail.com>
+ * Copyright (c) 2004-2012 Andrey Korotaev <unC0Rr@gmail.com>
  *
  * This program is free software; you can redistribute it and/or modify
  * it under the terms of the GNU General Public License as published by
--- a/QTfrontend/ui/page/pageadmin.cpp	Sun Apr 01 15:23:34 2012 +0200
+++ b/QTfrontend/ui/page/pageadmin.cpp	Wed May 02 23:53:45 2012 +0200
@@ -1,6 +1,6 @@
 /*
  * Hedgewars, a free turn based strategy game
- * Copyright (c) 2006-2012 Andrey Korotaev <unC0Rr@gmail.com>
+ * Copyright (c) 2004-2012 Andrey Korotaev <unC0Rr@gmail.com>
  *
  * This program is free software; you can redistribute it and/or modify
  * it under the terms of the GNU General Public License as published by
--- a/QTfrontend/ui/page/pageadmin.h	Sun Apr 01 15:23:34 2012 +0200
+++ b/QTfrontend/ui/page/pageadmin.h	Wed May 02 23:53:45 2012 +0200
@@ -1,6 +1,6 @@
 /*
  * Hedgewars, a free turn based strategy game
- * Copyright (c) 2006-2012 Andrey Korotaev <unC0Rr@gmail.com>
+ * Copyright (c) 2004-2012 Andrey Korotaev <unC0Rr@gmail.com>
  *
  * This program is free software; you can redistribute it and/or modify
  * it under the terms of the GNU General Public License as published by
--- a/QTfrontend/ui/page/pagecampaign.cpp	Sun Apr 01 15:23:34 2012 +0200
+++ b/QTfrontend/ui/page/pagecampaign.cpp	Wed May 02 23:53:45 2012 +0200
@@ -1,6 +1,6 @@
 /*
  * Hedgewars, a free turn based strategy game
- * Copyright (c) 2006-2012 Andrey Korotaev <unC0Rr@gmail.com>
+ * Copyright (c) 2004-2012 Andrey Korotaev <unC0Rr@gmail.com>
  *
  * This program is free software; you can redistribute it and/or modify
  * it under the terms of the GNU General Public License as published by
--- a/QTfrontend/ui/page/pagecampaign.h	Sun Apr 01 15:23:34 2012 +0200
+++ b/QTfrontend/ui/page/pagecampaign.h	Wed May 02 23:53:45 2012 +0200
@@ -1,6 +1,6 @@
 /*
  * Hedgewars, a free turn based strategy game
- * Copyright (c) 2006-2012 Andrey Korotaev <unC0Rr@gmail.com>
+ * Copyright (c) 2004-2012 Andrey Korotaev <unC0Rr@gmail.com>
  *
  * This program is free software; you can redistribute it and/or modify
  * it under the terms of the GNU General Public License as published by
--- a/QTfrontend/ui/page/pageconnecting.cpp	Sun Apr 01 15:23:34 2012 +0200
+++ b/QTfrontend/ui/page/pageconnecting.cpp	Wed May 02 23:53:45 2012 +0200
@@ -1,6 +1,6 @@
 /*
  * Hedgewars, a free turn based strategy game
- * Copyright (c) 2006-2012 Andrey Korotaev <unC0Rr@gmail.com>
+ * Copyright (c) 2004-2012 Andrey Korotaev <unC0Rr@gmail.com>
  *
  * This program is free software; you can redistribute it and/or modify
  * it under the terms of the GNU General Public License as published by
--- a/QTfrontend/ui/page/pageconnecting.h	Sun Apr 01 15:23:34 2012 +0200
+++ b/QTfrontend/ui/page/pageconnecting.h	Wed May 02 23:53:45 2012 +0200
@@ -1,6 +1,6 @@
 /*
  * Hedgewars, a free turn based strategy game
- * Copyright (c) 2006-2012 Andrey Korotaev <unC0Rr@gmail.com>
+ * Copyright (c) 2004-2012 Andrey Korotaev <unC0Rr@gmail.com>
  *
  * This program is free software; you can redistribute it and/or modify
  * it under the terms of the GNU General Public License as published by
--- a/QTfrontend/ui/page/pagedata.cpp	Sun Apr 01 15:23:34 2012 +0200
+++ b/QTfrontend/ui/page/pagedata.cpp	Wed May 02 23:53:45 2012 +0200
@@ -1,6 +1,6 @@
 /*
  * Hedgewars, a free turn based strategy game
- * Copyright (c) 2006-2012 Andrey Korotaev <unC0Rr@gmail.com>
+ * Copyright (c) 2004-2012 Andrey Korotaev <unC0Rr@gmail.com>
  *
  * This program is free software; you can redistribute it and/or modify
  * it under the terms of the GNU General Public License as published by
@@ -30,6 +30,7 @@
 #include "pagedata.h"
 #include "databrowser.h"
 #include "hwconsts.h"
+#include "DataManager.h"
 
 #include "quazip.h"
 #include "quazipfile.h"
@@ -52,6 +53,7 @@
 void PageDataDownload::connectSignals()
 {
     connect(web, SIGNAL(anchorClicked(QUrl)), this, SLOT(request(const QUrl&)));
+    connect(this, SIGNAL(goBack()), this, SLOT(onPageLeave()));
 }
 
 PageDataDownload::PageDataDownload(QWidget* parent) : AbstractPage(parent)
@@ -60,6 +62,8 @@
 
     web->setOpenLinks(false);
 //    fetchList();
+
+    m_contentDownloaded = false;
 }
 
 void PageDataDownload::request(const QUrl &url)
@@ -217,6 +221,8 @@
                 qWarning("read all but not EOF");
                 return false;
             }
+
+            m_contentDownloaded = true;
         }
 
         file.close();
@@ -232,3 +238,13 @@
 
     return true;
 }
+
+
+void PageDataDownload::onPageLeave()
+{
+    if (m_contentDownloaded)
+    {
+        m_contentDownloaded = false;
+        DataManager::instance().reload();
+    }
+}
--- a/QTfrontend/ui/page/pagedata.h	Sun Apr 01 15:23:34 2012 +0200
+++ b/QTfrontend/ui/page/pagedata.h	Wed May 02 23:53:45 2012 +0200
@@ -1,6 +1,6 @@
 /*
  * Hedgewars, a free turn based strategy game
- * Copyright (c) 2006-2012 Andrey Korotaev <unC0Rr@gmail.com>
+ * Copyright (c) 2004-2012 Andrey Korotaev <unC0Rr@gmail.com>
  *
  * This program is free software; you can redistribute it and/or modify
  * it under the terms of the GNU General Public License as published by
@@ -46,6 +46,8 @@
         QHash<QNetworkReply*, QProgressBar *> progressBars;
         QVBoxLayout *progressBarsLayout;
 
+        bool m_contentDownloaded; ///< true if something was downloaded since last page leave
+
         bool extractDataPack(QByteArray * buf);
 
     private slots:
@@ -54,6 +56,8 @@
         void pageDownloaded();
         void fileDownloaded();
         void downloadProgress(qint64, qint64);
+
+        void onPageLeave();
 };
 
 #endif
--- a/QTfrontend/ui/page/pagedrawmap.cpp	Sun Apr 01 15:23:34 2012 +0200
+++ b/QTfrontend/ui/page/pagedrawmap.cpp	Wed May 02 23:53:45 2012 +0200
@@ -1,6 +1,6 @@
 /*
  * Hedgewars, a free turn based strategy game
- * Copyright (c) 2006-2012 Andrey Korotaev <unC0Rr@gmail.com>
+ * Copyright (c) 2004-2012 Andrey Korotaev <unC0Rr@gmail.com>
  *
  * This program is free software; you can redistribute it and/or modify
  * it under the terms of the GNU General Public License as published by
@@ -19,6 +19,7 @@
 #include <QGridLayout>
 #include <QPushButton>
 #include <QFileDialog>
+#include <QCheckBox>
 
 #include "pagedrawmap.h"
 #include "drawmapwidget.h"
@@ -28,19 +29,22 @@
 {
     QGridLayout * pageLayout = new QGridLayout();
 
-    pbUndo = addButton(tr("Undo"), pageLayout, 0, 0);
-    pbClear = addButton(tr("Clear"), pageLayout, 1, 0);
-    pbLoad = addButton(tr("Load"), pageLayout, 2, 0);
-    pbSave = addButton(tr("Save"), pageLayout, 3, 0);
+    cbEraser = new QCheckBox(tr("Eraser"), this);
+    pageLayout->addWidget(cbEraser, 0, 0);
+    pbUndo = addButton(tr("Undo"), pageLayout, 1, 0);
+    pbClear = addButton(tr("Clear"), pageLayout, 2, 0);
+    pbLoad = addButton(tr("Load"), pageLayout, 3, 0);
+    pbSave = addButton(tr("Save"), pageLayout, 4, 0);
 
     drawMapWidget = new DrawMapWidget(this);
-    pageLayout->addWidget(drawMapWidget, 0, 1, 5, 1);
+    pageLayout->addWidget(drawMapWidget, 0, 1, 6, 1);
 
     return pageLayout;
 }
 
 void PageDrawMap::connectSignals()
 {
+    connect(cbEraser, SIGNAL(toggled(bool)), drawMapWidget, SLOT(setErasing(bool)));
     connect(pbUndo, SIGNAL(clicked()), drawMapWidget, SLOT(undo()));
     connect(pbClear, SIGNAL(clicked()), drawMapWidget, SLOT(clear()));
     connect(pbLoad, SIGNAL(clicked()), this, SLOT(load()));
--- a/QTfrontend/ui/page/pagedrawmap.h	Sun Apr 01 15:23:34 2012 +0200
+++ b/QTfrontend/ui/page/pagedrawmap.h	Wed May 02 23:53:45 2012 +0200
@@ -1,6 +1,6 @@
 /*
  * Hedgewars, a free turn based strategy game
- * Copyright (c) 2006-2012 Andrey Korotaev <unC0Rr@gmail.com>
+ * Copyright (c) 2004-2012 Andrey Korotaev <unC0Rr@gmail.com>
  *
  * This program is free software; you can redistribute it and/or modify
  * it under the terms of the GNU General Public License as published by
@@ -41,6 +41,7 @@
         QPushButton * pbClear;
         QPushButton * pbLoad;
         QPushButton * pbSave;
+        QCheckBox * cbEraser;
 
     private slots:
         void load();
--- a/QTfrontend/ui/page/pageeditteam.cpp	Sun Apr 01 15:23:34 2012 +0200
+++ b/QTfrontend/ui/page/pageeditteam.cpp	Wed May 02 23:53:45 2012 +0200
@@ -1,6 +1,6 @@
 /*
  * Hedgewars, a free turn based strategy game
- * Copyright (c) 2006-2012 Andrey Korotaev <unC0Rr@gmail.com>
+ * Copyright (c) 2004-2012 Andrey Korotaev <unC0Rr@gmail.com>
  *
  * This program is free software; you can redistribute it and/or modify
  * it under the terms of the GNU General Public License as published by
@@ -29,10 +29,9 @@
 
 #include "sdlkeys.h"
 #include "SquareLabel.h"
-#include "hats.h"
 #include "HWApplication.h"
 
-#include "HWDataManager.h"
+#include "DataManager.h"
 
 #include "pageeditteam.h"
 
@@ -61,11 +60,12 @@
     GBoxHedgehogs->setSizePolicy(QSizePolicy::Expanding, QSizePolicy::Fixed);
     QGridLayout * GBHLayout = new QGridLayout(GBoxHedgehogs);
 
-    HatsModel * hatsModel = new HatsModel(GBoxHedgehogs);
+    HatModel * hatModel = DataManager::instance().hatModel();
+
     for(int i = 0; i < HEDGEHOGS_PER_TEAM; i++)
     {
         HHHats[i] = new QComboBox(GBoxHedgehogs);
-        HHHats[i]->setModel(hatsModel);
+        HHHats[i]->setModel(hatModel);
         HHHats[i]->setIconSize(QSize(32, 37));
         //HHHats[i]->setSizeAdjustPolicy(QComboBox::AdjustToContents);
         //HHHats[i]->setModelColumn(1);
@@ -245,7 +245,7 @@
 
     m_playerHash = "0000000000000000000000000000000000000000";
 
-    HWDataManager & dataMgr = HWDataManager::instance();
+    DataManager & dataMgr = DataManager::instance();
 
     QStringList list;
 
@@ -333,14 +333,14 @@
 
 void PageEditTeam::CBFort_activated(const QString & fortname)
 {
-    HWDataManager & dataMgr = HWDataManager::instance();
+    DataManager & dataMgr = DataManager::instance();
     QPixmap pix(dataMgr.findFileForRead("Forts/" + fortname + "L.png"));
     FortPreview->setPixmap(pix);
 }
 
 void PageEditTeam::testSound()
 {
-    HWDataManager & dataMgr = HWDataManager::instance();
+    DataManager & dataMgr = DataManager::instance();
 
     QString voiceDir = QString("Sounds/voices/") + CBVoicepack->currentText();
 
--- a/QTfrontend/ui/page/pageeditteam.h	Sun Apr 01 15:23:34 2012 +0200
+++ b/QTfrontend/ui/page/pageeditteam.h	Wed May 02 23:53:45 2012 +0200
@@ -1,6 +1,6 @@
 /*
  * Hedgewars, a free turn based strategy game
- * Copyright (c) 2006-2012 Andrey Korotaev <unC0Rr@gmail.com>
+ * Copyright (c) 2004-2012 Andrey Korotaev <unC0Rr@gmail.com>
  *
  * This program is free software; you can redistribute it and/or modify
  * it under the terms of the GNU General Public License as published by
--- a/QTfrontend/ui/page/pagefeedback.cpp	Sun Apr 01 15:23:34 2012 +0200
+++ b/QTfrontend/ui/page/pagefeedback.cpp	Wed May 02 23:53:45 2012 +0200
@@ -1,6 +1,6 @@
 /*
  * Hedgewars, a free turn based strategy game
- * Copyright (c) 2006-2012 Andrey Korotaev <unC0Rr@gmail.com>
+ * Copyright (c) 2004-2012 Andrey Korotaev <unC0Rr@gmail.com>
  *
  * This program is free software; you can redistribute it and/or modify
  * it under the terms of the GNU General Public License as published by
--- a/QTfrontend/ui/page/pagefeedback.h	Sun Apr 01 15:23:34 2012 +0200
+++ b/QTfrontend/ui/page/pagefeedback.h	Wed May 02 23:53:45 2012 +0200
@@ -1,6 +1,6 @@
 /*
  * Hedgewars, a free turn based strategy game
- * Copyright (c) 2006-2012 Andrey Korotaev <unC0Rr@gmail.com>
+ * Copyright (c) 2004-2012 Andrey Korotaev <unC0Rr@gmail.com>
  *
  * This program is free software; you can redistribute it and/or modify
  * it under the terms of the GNU General Public License as published by
--- a/QTfrontend/ui/page/pagegamestats.cpp	Sun Apr 01 15:23:34 2012 +0200
+++ b/QTfrontend/ui/page/pagegamestats.cpp	Wed May 02 23:53:45 2012 +0200
@@ -1,6 +1,6 @@
 /*
  * Hedgewars, a free turn based strategy game
- * Copyright (c) 2010-2012 Andrey Korotaev <unC0Rr@gmail.com>
+ * Copyright (c) 2004-2012 Andrey Korotaev <unC0Rr@gmail.com>
  *
  * This program is free software; you can redistribute it and/or modify
  * it under the terms of the GNU General Public License as published by
--- a/QTfrontend/ui/page/pagegamestats.h	Sun Apr 01 15:23:34 2012 +0200
+++ b/QTfrontend/ui/page/pagegamestats.h	Wed May 02 23:53:45 2012 +0200
@@ -1,6 +1,6 @@
 /*
  * Hedgewars, a free turn based strategy game
- * Copyright (c) 2010-2012 Andrey Korotaev <unC0Rr@gmail.com>
+ * Copyright (c) 2004-2012 Andrey Korotaev <unC0Rr@gmail.com>
  *
  * This program is free software; you can redistribute it and/or modify
  * it under the terms of the GNU General Public License as published by
--- a/QTfrontend/ui/page/pageinfo.cpp	Sun Apr 01 15:23:34 2012 +0200
+++ b/QTfrontend/ui/page/pageinfo.cpp	Wed May 02 23:53:45 2012 +0200
@@ -1,6 +1,6 @@
 /*
  * Hedgewars, a free turn based strategy game
- * Copyright (c) 2006-2012 Andrey Korotaev <unC0Rr@gmail.com>
+ * Copyright (c) 2004-2012 Andrey Korotaev <unC0Rr@gmail.com>
  *
  * This program is free software; you can redistribute it and/or modify
  * it under the terms of the GNU General Public License as published by
--- a/QTfrontend/ui/page/pageinfo.h	Sun Apr 01 15:23:34 2012 +0200
+++ b/QTfrontend/ui/page/pageinfo.h	Wed May 02 23:53:45 2012 +0200
@@ -1,6 +1,6 @@
 /*
  * Hedgewars, a free turn based strategy game
- * Copyright (c) 2006-2012 Andrey Korotaev <unC0Rr@gmail.com>
+ * Copyright (c) 2004-2012 Andrey Korotaev <unC0Rr@gmail.com>
  *
  * This program is free software; you can redistribute it and/or modify
  * it under the terms of the GNU General Public License as published by
--- a/QTfrontend/ui/page/pageingame.cpp	Sun Apr 01 15:23:34 2012 +0200
+++ b/QTfrontend/ui/page/pageingame.cpp	Wed May 02 23:53:45 2012 +0200
@@ -1,6 +1,6 @@
 /*
  * Hedgewars, a free turn based strategy game
- * Copyright (c) 2006-2012 Andrey Korotaev <unC0Rr@gmail.com>
+ * Copyright (c) 2004-2012 Andrey Korotaev <unC0Rr@gmail.com>
  *
  * This program is free software; you can redistribute it and/or modify
  * it under the terms of the GNU General Public License as published by
--- a/QTfrontend/ui/page/pageingame.h	Sun Apr 01 15:23:34 2012 +0200
+++ b/QTfrontend/ui/page/pageingame.h	Wed May 02 23:53:45 2012 +0200
@@ -1,6 +1,6 @@
 /*
  * Hedgewars, a free turn based strategy game
- * Copyright (c) 2006-2012 Andrey Korotaev <unC0Rr@gmail.com>
+ * Copyright (c) 2004-2012 Andrey Korotaev <unC0Rr@gmail.com>
  *
  * This program is free software; you can redistribute it and/or modify
  * it under the terms of the GNU General Public License as published by
--- a/QTfrontend/ui/page/pagemain.cpp	Sun Apr 01 15:23:34 2012 +0200
+++ b/QTfrontend/ui/page/pagemain.cpp	Wed May 02 23:53:45 2012 +0200
@@ -1,6 +1,6 @@
 /*
  * Hedgewars, a free turn based strategy game
- * Copyright (c) 2006-2012 Andrey Korotaev <unC0Rr@gmail.com>
+ * Copyright (c) 2004-2012 Andrey Korotaev <unC0Rr@gmail.com>
  *
  * This program is free software; you can redistribute it and/or modify
  * it under the terms of the GNU General Public License as published by
--- a/QTfrontend/ui/page/pagemain.h	Sun Apr 01 15:23:34 2012 +0200
+++ b/QTfrontend/ui/page/pagemain.h	Wed May 02 23:53:45 2012 +0200
@@ -1,6 +1,6 @@
 /*
  * Hedgewars, a free turn based strategy game
- * Copyright (c) 2006-2012 Andrey Korotaev <unC0Rr@gmail.com>
+ * Copyright (c) 2004-2012 Andrey Korotaev <unC0Rr@gmail.com>
  *
  * This program is free software; you can redistribute it and/or modify
  * it under the terms of the GNU General Public License as published by
--- a/QTfrontend/ui/page/pagemultiplayer.cpp	Sun Apr 01 15:23:34 2012 +0200
+++ b/QTfrontend/ui/page/pagemultiplayer.cpp	Wed May 02 23:53:45 2012 +0200
@@ -1,6 +1,6 @@
 /*
  * Hedgewars, a free turn based strategy game
- * Copyright (c) 2006-2012 Andrey Korotaev <unC0Rr@gmail.com>
+ * Copyright (c) 2004-2012 Andrey Korotaev <unC0Rr@gmail.com>
  *
  * This program is free software; you can redistribute it and/or modify
  * it under the terms of the GNU General Public License as published by
--- a/QTfrontend/ui/page/pagemultiplayer.h	Sun Apr 01 15:23:34 2012 +0200
+++ b/QTfrontend/ui/page/pagemultiplayer.h	Wed May 02 23:53:45 2012 +0200
@@ -1,6 +1,6 @@
 /*
  * Hedgewars, a free turn based strategy game
- * Copyright (c) 2006-2012 Andrey Korotaev <unC0Rr@gmail.com>
+ * Copyright (c) 2004-2012 Andrey Korotaev <unC0Rr@gmail.com>
  *
  * This program is free software; you can redistribute it and/or modify
  * it under the terms of the GNU General Public License as published by
--- a/QTfrontend/ui/page/pagenet.cpp	Sun Apr 01 15:23:34 2012 +0200
+++ b/QTfrontend/ui/page/pagenet.cpp	Wed May 02 23:53:45 2012 +0200
@@ -1,6 +1,6 @@
 /*
  * Hedgewars, a free turn based strategy game
- * Copyright (c) 2006-2012 Andrey Korotaev <unC0Rr@gmail.com>
+ * Copyright (c) 2004-2012 Andrey Korotaev <unC0Rr@gmail.com>
  *
  * This program is free software; you can redistribute it and/or modify
  * it under the terms of the GNU General Public License as published by
--- a/QTfrontend/ui/page/pagenet.h	Sun Apr 01 15:23:34 2012 +0200
+++ b/QTfrontend/ui/page/pagenet.h	Wed May 02 23:53:45 2012 +0200
@@ -1,6 +1,6 @@
 /*
  * Hedgewars, a free turn based strategy game
- * Copyright (c) 2006-2012 Andrey Korotaev <unC0Rr@gmail.com>
+ * Copyright (c) 2004-2012 Andrey Korotaev <unC0Rr@gmail.com>
  *
  * This program is free software; you can redistribute it and/or modify
  * it under the terms of the GNU General Public License as published by
--- a/QTfrontend/ui/page/pagenetgame.cpp	Sun Apr 01 15:23:34 2012 +0200
+++ b/QTfrontend/ui/page/pagenetgame.cpp	Wed May 02 23:53:45 2012 +0200
@@ -1,6 +1,6 @@
 /*
  * Hedgewars, a free turn based strategy game
- * Copyright (c) 2006-2012 Andrey Korotaev <unC0Rr@gmail.com>
+ * Copyright (c) 2004-2012 Andrey Korotaev <unC0Rr@gmail.com>
  *
  * This program is free software; you can redistribute it and/or modify
  * it under the terms of the GNU General Public License as published by
@@ -40,6 +40,7 @@
     pChatWidget = new HWChatWidget(this, m_gameSettings, true);
     pChatWidget->setShowReady(true); // show status bulbs by default
     pChatWidget->setShowFollow(false); // don't show follow in nicks' context menus
+    pChatWidget->setIgnoreListKick(true); // kick ignored players automatically
     pageLayout->addWidget(pChatWidget, 2, 0, 1, 2);
     pageLayout->setRowStretch(1, 100);
     pageLayout->setRowStretch(2, 100);
--- a/QTfrontend/ui/page/pagenetgame.h	Sun Apr 01 15:23:34 2012 +0200
+++ b/QTfrontend/ui/page/pagenetgame.h	Wed May 02 23:53:45 2012 +0200
@@ -1,6 +1,6 @@
 /*
  * Hedgewars, a free turn based strategy game
- * Copyright (c) 2006-2012 Andrey Korotaev <unC0Rr@gmail.com>
+ * Copyright (c) 2004-2012 Andrey Korotaev <unC0Rr@gmail.com>
  *
  * This program is free software; you can redistribute it and/or modify
  * it under the terms of the GNU General Public License as published by
--- a/QTfrontend/ui/page/pagenetserver.cpp	Sun Apr 01 15:23:34 2012 +0200
+++ b/QTfrontend/ui/page/pagenetserver.cpp	Wed May 02 23:53:45 2012 +0200
@@ -1,6 +1,6 @@
 /*
  * Hedgewars, a free turn based strategy game
- * Copyright (c) 2006-2012 Andrey Korotaev <unC0Rr@gmail.com>
+ * Copyright (c) 2004-2012 Andrey Korotaev <unC0Rr@gmail.com>
  *
  * This program is free software; you can redistribute it and/or modify
  * it under the terms of the GNU General Public License as published by
--- a/QTfrontend/ui/page/pagenetserver.h	Sun Apr 01 15:23:34 2012 +0200
+++ b/QTfrontend/ui/page/pagenetserver.h	Wed May 02 23:53:45 2012 +0200
@@ -1,6 +1,6 @@
 /*
  * Hedgewars, a free turn based strategy game
- * Copyright (c) 2006-2012 Andrey Korotaev <unC0Rr@gmail.com>
+ * Copyright (c) 2004-2012 Andrey Korotaev <unC0Rr@gmail.com>
  *
  * This program is free software; you can redistribute it and/or modify
  * it under the terms of the GNU General Public License as published by
--- a/QTfrontend/ui/page/pagenettype.cpp	Sun Apr 01 15:23:34 2012 +0200
+++ b/QTfrontend/ui/page/pagenettype.cpp	Wed May 02 23:53:45 2012 +0200
@@ -1,6 +1,6 @@
 /*
  * Hedgewars, a free turn based strategy game
- * Copyright (c) 2006-2012 Andrey Korotaev <unC0Rr@gmail.com>
+ * Copyright (c) 2004-2012 Andrey Korotaev <unC0Rr@gmail.com>
  *
  * This program is free software; you can redistribute it and/or modify
  * it under the terms of the GNU General Public License as published by
--- a/QTfrontend/ui/page/pagenettype.h	Sun Apr 01 15:23:34 2012 +0200
+++ b/QTfrontend/ui/page/pagenettype.h	Wed May 02 23:53:45 2012 +0200
@@ -1,6 +1,6 @@
 /*
  * Hedgewars, a free turn based strategy game
- * Copyright (c) 2006-2012 Andrey Korotaev <unC0Rr@gmail.com>
+ * Copyright (c) 2004-2012 Andrey Korotaev <unC0Rr@gmail.com>
  *
  * This program is free software; you can redistribute it and/or modify
  * it under the terms of the GNU General Public License as published by
--- a/QTfrontend/ui/page/pageoptions.cpp	Sun Apr 01 15:23:34 2012 +0200
+++ b/QTfrontend/ui/page/pageoptions.cpp	Wed May 02 23:53:45 2012 +0200
@@ -1,6 +1,6 @@
 /*
  * Hedgewars, a free turn based strategy game
- * Copyright (c) 2006-2012 Andrey Korotaev <unC0Rr@gmail.com>
+ * Copyright (c) 2004-2012 Andrey Korotaev <unC0Rr@gmail.com>
  *
  * This program is free software; you can redistribute it and/or modify
  * it under the terms of the GNU General Public License as published by
@@ -187,28 +187,12 @@
         groupMisc->setTitle(QGroupBox::tr("Misc"));
         QGridLayout * MiscLayout = new QGridLayout(groupMisc);
 
-        labelNN = new QLabel(groupMisc);
-        labelNN->setText(QLabel::tr("Net nick"));
-        MiscLayout->addWidget(labelNN, 0, 0);
-
-        editNetNick = new QLineEdit(groupMisc);
-        editNetNick->setMaxLength(20);
-        editNetNick->setText(QLineEdit::tr("unnamed"));
-        connect(editNetNick, SIGNAL(editingFinished()), this, SLOT(trimNetNick()));
-        MiscLayout->addWidget(editNetNick, 0, 1);
-
-        labelNetPassword = new QLabel(groupMisc);
-        labelNetPassword->setText(QLabel::tr("Password"));
-        MiscLayout->addWidget(labelNetPassword, 1, 0);
-
-        editNetPassword = new QLineEdit(groupMisc);
-        editNetPassword->setEchoMode(QLineEdit::Password);
-        MiscLayout->addWidget(editNetPassword, 1, 1);
-
+        // Label for "Language"
         QLabel *labelLanguage = new QLabel(groupMisc);
         labelLanguage->setText(QLabel::tr("Locale") + " *");
-        MiscLayout->addWidget(labelLanguage, 2, 0);
+        MiscLayout->addWidget(labelLanguage, 0, 0);
 
+        // List of installed languages
         CBLanguage = new QComboBox(groupMisc);
         QDir tmpdir;
         tmpdir.cd(cfgdir->absolutePath());
@@ -233,26 +217,49 @@
             CBLanguage->addItem(QLocale::languageToString(loc.language()) + " (" + QLocale::countryToString(loc.country()) + ")", loc.name());
         }
 
-        MiscLayout->addWidget(CBLanguage, 2, 1);
+        MiscLayout->addWidget(CBLanguage, 0, 1);
+
+        // Label and field for net nick
+        labelNN = new QLabel(groupMisc);
+        labelNN->setText(QLabel::tr("Nickname"));
+        MiscLayout->addWidget(labelNN, 1, 0);
+
+        editNetNick = new QLineEdit(groupMisc);
+        editNetNick->setMaxLength(20);
+        editNetNick->setText(QLineEdit::tr("anonymous"));
+        MiscLayout->addWidget(editNetNick, 1, 1);
+
+        // Label and field for password
+        labelNetPassword = new QLabel(groupMisc);
+        labelNetPassword->setText(QLabel::tr("Password"));
+        MiscLayout->addWidget(labelNetPassword, 2, 0);
+
+        editNetPassword = new QLineEdit(groupMisc);
+        editNetPassword->setEchoMode(QLineEdit::Password);
+        MiscLayout->addWidget(editNetPassword, 2, 1);
+
+        CBSavePassword = new QCheckBox(groupMisc);
+        CBSavePassword->setText(QCheckBox::tr("Save password"));
+        MiscLayout->addWidget(CBSavePassword, 3, 0, 1, 2);
 
         CBAltDamage = new QCheckBox(groupMisc);
         CBAltDamage->setText(QCheckBox::tr("Alternative damage show"));
-        MiscLayout->addWidget(CBAltDamage, 3, 0, 1, 2);
+        MiscLayout->addWidget(CBAltDamage, 4, 0, 1, 2);
 
         CBNameWithDate = new QCheckBox(groupMisc);
         CBNameWithDate->setText(QCheckBox::tr("Append date and time to record file name"));
-        MiscLayout->addWidget(CBNameWithDate, 4, 0, 1, 2);
+        MiscLayout->addWidget(CBNameWithDate, 5, 0, 1, 2);
 
         BtnAssociateFiles = new QPushButton(groupMisc);
         BtnAssociateFiles->setText(QPushButton::tr("Associate file extensions"));
         BtnAssociateFiles->setEnabled(!custom_data && !custom_config);
-        MiscLayout->addWidget(BtnAssociateFiles, 5, 0, 1, 2);
+        MiscLayout->addWidget(BtnAssociateFiles, 6, 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);
+        MiscLayout->addWidget(CBAutoUpdate, 7, 0, 1, 3);
 #endif
 #endif
         gbTBLayout->addWidget(groupMisc, 2, 0);
@@ -338,7 +345,6 @@
         CBStereoMode->addItem(QComboBox::tr("Blue/Red grayscale"));
         CBStereoMode->addItem(QComboBox::tr("Red/Green grayscale"));
         CBStereoMode->addItem(QComboBox::tr("Green/Red grayscale"));
-        connect(CBStereoMode, SIGNAL(currentIndexChanged(int)), this, SLOT(forceFullscreen(int)));
 
         GBAstereolayout->addWidget(CBStereoMode);
         GBAlayout->addLayout(GBAstereolayout);
@@ -402,9 +408,12 @@
 
 void PageOptions::connectSignals()
 {
+    connect(SLQuality, SIGNAL(valueChanged(int)), this, SLOT(setQuality(int)));
     connect(CBResolution, SIGNAL(currentIndexChanged(int)), this, SLOT(setResolution(int)));
     connect(CBFullscreen, SIGNAL(stateChanged(int)), this, SLOT(setFullscreen(int)));
-    connect(SLQuality, SIGNAL(valueChanged(int)), this, SLOT(setQuality(int)));
+    connect(CBStereoMode, SIGNAL(currentIndexChanged(int)), this, SLOT(forceFullscreen(int)));
+    connect(editNetNick, SIGNAL(editingFinished()), this, SLOT(trimNetNick()));
+    connect(CBSavePassword, SIGNAL(stateChanged(int)), this, SLOT(savePwdChanged(int)));
 }
 
 PageOptions::PageOptions(QWidget* parent) : AbstractPage(parent)
@@ -466,6 +475,14 @@
     editNetNick->setText(editNetNick->text().trimmed());
 }
 
+void PageOptions::savePwdChanged(int state) {
+    if (state == 0) {
+        editNetPassword->setEnabled(false);
+        editNetPassword->setText("");
+    } else
+        editNetPassword->setEnabled(true);
+}
+
 void PageOptions::requestEditSelectedTeam()
 {
     emit editTeamRequested(CBTeamName->currentText());
--- a/QTfrontend/ui/page/pageoptions.h	Sun Apr 01 15:23:34 2012 +0200
+++ b/QTfrontend/ui/page/pageoptions.h	Wed May 02 23:53:45 2012 +0200
@@ -1,6 +1,6 @@
 /*
  * Hedgewars, a free turn based strategy game
- * Copyright (c) 2006-2012 Andrey Korotaev <unC0Rr@gmail.com>
+ * Copyright (c) 2004-2012 Andrey Korotaev <unC0Rr@gmail.com>
  *
  * This program is free software; you can redistribute it and/or modify
  * it under the terms of the GNU General Public License as published by
@@ -56,6 +56,7 @@
         QCheckBox *CBFullscreen;
         QCheckBox *CBFrontendFullscreen;
         QCheckBox *CBShowFPS;
+        QCheckBox *CBSavePassword;
         QCheckBox *CBAltDamage;
         QCheckBox *CBNameWithDate;
 #ifdef __APPLE__
@@ -100,6 +101,7 @@
         void trimNetNick();
         void requestEditSelectedTeam();
         void requestDeleteSelectedTeam();
+        void savePwdChanged(int state);
 };
 
 #endif
--- a/QTfrontend/ui/page/pageplayrecord.cpp	Sun Apr 01 15:23:34 2012 +0200
+++ b/QTfrontend/ui/page/pageplayrecord.cpp	Wed May 02 23:53:45 2012 +0200
@@ -1,6 +1,6 @@
 /*
  * Hedgewars, a free turn based strategy game
- * Copyright (c) 2006-2012 Andrey Korotaev <unC0Rr@gmail.com>
+ * Copyright (c) 2004-2012 Andrey Korotaev <unC0Rr@gmail.com>
  *
  * This program is free software; you can redistribute it and/or modify
  * it under the terms of the GNU General Public License as published by
@@ -16,6 +16,8 @@
  * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA
  */
 
+#include "pageplayrecord.h"
+
 #include <QFont>
 #include <QGridLayout>
 #include <QPushButton>
@@ -26,7 +28,8 @@
 #include <QInputDialog>
 
 #include "hwconsts.h"
-#include "pageplayrecord.h"
+
+#include "DataManager.h"
 
 QLayout * PagePlayDemo::bodyLayoutDefinition()
 {
@@ -61,6 +64,7 @@
 {
     connect(BtnRenameRecord, SIGNAL(clicked()), this, SLOT(renameRecord()));
     connect(BtnRemoveRecord, SIGNAL(clicked()), this, SLOT(removeRecord()));
+    connect(&DataManager::instance(), SIGNAL(updated()), this, SLOT(refresh()));
 }
 
 PagePlayDemo::PagePlayDemo(QWidget* parent) : AbstractPage(parent)
@@ -103,6 +107,14 @@
     }
 }
 
+
+void PagePlayDemo::refresh()
+{
+    if (this->isVisible());
+        FillFromDir(recType);
+}
+
+
 void PagePlayDemo::renameRecord()
 {
     QListWidgetItem * curritem = DemosList->currentItem();
--- a/QTfrontend/ui/page/pageplayrecord.h	Sun Apr 01 15:23:34 2012 +0200
+++ b/QTfrontend/ui/page/pageplayrecord.h	Wed May 02 23:53:45 2012 +0200
@@ -1,6 +1,6 @@
 /*
  * Hedgewars, a free turn based strategy game
- * Copyright (c) 2006-2012 Andrey Korotaev <unC0Rr@gmail.com>
+ * Copyright (c) 2004-2012 Andrey Korotaev <unC0Rr@gmail.com>
  *
  * This program is free software; you can redistribute it and/or modify
  * it under the terms of the GNU General Public License as published by
@@ -47,6 +47,9 @@
         QPushButton *BtnRemoveRecord;
         QListWidget *DemosList;
 
+    public slots:
+        void refresh();
+
     private:
         QLayout * bodyLayoutDefinition();
         void connectSignals();
--- a/QTfrontend/ui/page/pageroomslist.cpp	Sun Apr 01 15:23:34 2012 +0200
+++ b/QTfrontend/ui/page/pageroomslist.cpp	Wed May 02 23:53:45 2012 +0200
@@ -1,6 +1,6 @@
 /*
  * Hedgewars, a free turn based strategy game
- * Copyright (c) 2006-2012 Andrey Korotaev <unC0Rr@gmail.com>
+ * Copyright (c) 2004-2012 Andrey Korotaev <unC0Rr@gmail.com>
  *
  * This program is free software; you can redistribute it and/or modify
  * it under the terms of the GNU General Public License as published by
@@ -26,6 +26,10 @@
 #include <QHeaderView>
 #include <QTableView>
 
+#include <QSortFilterProxyModel>
+
+#include "roomslistmodel.h"
+
 #include "ammoSchemeModel.h"
 #include "pageroomslist.h"
 #include "hwconsts.h"
@@ -61,7 +65,7 @@
 
     filterLayout->addWidget(stateLabel);
     filterLayout->addWidget(CBState);
-    filterLayout->addSpacing(30);
+    filterLayout->addStretch(1);
 
     QLabel * ruleLabel = new QLabel(this);
     ruleLabel->setText(tr("Rules:"));
@@ -69,7 +73,7 @@
 
     filterLayout->addWidget(ruleLabel);
     filterLayout->addWidget(CBRules);
-    filterLayout->addSpacing(30);
+    filterLayout->addStretch(1);
 
     QLabel * weaponLabel = new QLabel(this);
     weaponLabel->setText(tr("Weapons:"));
@@ -77,14 +81,17 @@
 
     filterLayout->addWidget(weaponLabel);
     filterLayout->addWidget(CBWeapons);
-    filterLayout->addSpacing(30);
+    filterLayout->addStretch(1);
 
     QLabel * searchLabel = new QLabel(this);
     searchLabel->setText(tr("Search:"));
     searchText = new QLineEdit(this);
     searchText->setMaxLength(60);
+    searchText->setMinimumWidth(100);
+    searchText->setMaximumWidth(360);
     filterLayout->addWidget(searchLabel);
     filterLayout->addWidget(searchText);
+    filterLayout->setStretchFactor(searchText, 2);
 
     pageLayout->addLayout(filterLayout, 4, 0, 1, 2);
 
@@ -139,11 +146,21 @@
     connect(BtnRefresh, SIGNAL(clicked()), this, SLOT(onRefreshClick()));
     connect(BtnClear, SIGNAL(clicked()), this, SLOT(onClearClick()));
     connect(roomsList, SIGNAL(doubleClicked (const QModelIndex &)), this, SLOT(onJoinClick()));
-    connect(CBState, SIGNAL(currentIndexChanged (int)), this, SLOT(onRefreshClick()));
-    connect(CBRules, SIGNAL(currentIndexChanged (int)), this, SLOT(onRefreshClick()));
-    connect(CBWeapons, SIGNAL(currentIndexChanged (int)), this, SLOT(onRefreshClick()));
-    connect(searchText, SIGNAL(textChanged (const QString &)), this, SLOT(onRefreshClick()));
+    connect(CBState, SIGNAL(currentIndexChanged (int)), this, SLOT(onFilterChanged()));
+    connect(CBRules, SIGNAL(currentIndexChanged (int)), this, SLOT(onFilterChanged()));
+    connect(CBWeapons, SIGNAL(currentIndexChanged (int)), this, SLOT(onFilterChanged()));
+    connect(searchText, SIGNAL(textChanged (const QString &)), this, SLOT(onFilterChanged()));
     connect(this, SIGNAL(askJoinConfirmation (const QString &)), this, SLOT(onJoinConfirmation(const QString &)), Qt::QueuedConnection);
+
+    // save header state on change
+    connect(roomsList->horizontalHeader(), SIGNAL(sortIndicatorChanged(int, Qt::SortOrder)),
+            this, SLOT(saveHeaderState()));
+    connect(roomsList->horizontalHeader(), SIGNAL(sectionResized),
+            this, SLOT(saveHeaderState()));
+
+    // sorting
+    connect(roomsList->horizontalHeader(), SIGNAL(sortIndicatorChanged(int, Qt::SortOrder)),
+            this, SLOT(onSortIndicatorChanged(int, Qt::SortOrder)));
 }
 
 
@@ -152,6 +169,11 @@
 {
     m_gameSettings = gameSettings;
 
+    roomsModel = NULL;
+    stateFilteredModel = NULL;
+    schemeFilteredModel = NULL;
+    weaponsFilteredModel = NULL;
+
     initPage();
 
     // not the most elegant solution but it works
@@ -472,18 +494,118 @@
     chatWidget->setUser(nickname);
 }
 
-void PageRoomsList::setModel(QAbstractTableModel *model)
+void PageRoomsList::setModel(RoomsListModel * model)
 {
-    roomsList->setModel(model);
+    // filter chain:
+    // model -> stateFilteredModel -> schemeFilteredModel ->
+    // -> weaponsFilteredModel -> roomsModel (search filter+sorting)
+
+    if (roomsModel == NULL)
+    {
+        roomsModel = new QSortFilterProxyModel(this);
+        roomsModel->setDynamicSortFilter(true);
+        roomsModel->setSortCaseSensitivity(Qt::CaseInsensitive);
+        roomsModel->sort(RoomsListModel::StateColumn, Qt::AscendingOrder);
+
+        stateFilteredModel = new QSortFilterProxyModel(this);
+        schemeFilteredModel = new QSortFilterProxyModel(this);
+        weaponsFilteredModel = new QSortFilterProxyModel(this);
+
+        stateFilteredModel->setDynamicSortFilter(true);
+        schemeFilteredModel->setDynamicSortFilter(true);
+        weaponsFilteredModel->setDynamicSortFilter(true);
 
-    roomsList->hideColumn(0);
+        roomsModel->setFilterKeyColumn(-1); // search in all columns
+        stateFilteredModel->setFilterKeyColumn(RoomsListModel::StateColumn);
+        schemeFilteredModel->setFilterKeyColumn(RoomsListModel::SchemeColumn);
+        weaponsFilteredModel->setFilterKeyColumn(RoomsListModel::WeaponsColumn);
+
+        roomsModel->setFilterCaseSensitivity(Qt::CaseInsensitive);
+        schemeFilteredModel->setFilterCaseSensitivity(Qt::CaseInsensitive);
+        weaponsFilteredModel->setFilterCaseSensitivity(Qt::CaseInsensitive);
+
+        schemeFilteredModel->setSourceModel(stateFilteredModel);
+        weaponsFilteredModel->setSourceModel(schemeFilteredModel);
+        roomsModel->setSourceModel(weaponsFilteredModel);
+
+        // let the table view display the last model in the filter chain
+        roomsList->setModel(roomsModel);
+    }
+
+    stateFilteredModel->setSourceModel(model);
+
+    roomsList->hideColumn(RoomsListModel::StateColumn);
 
     QHeaderView * h = roomsList->horizontalHeader();
-    h->resizeSection(1, 200);
-    h->resizeSection(2, 50);
-    h->resizeSection(3, 50);
-    h->resizeSection(4, 100);
-    h->resizeSection(5, 100);
-    h->resizeSection(6, 100);
-    h->resizeSection(7, 100);
+
+    if (!restoreHeaderState())
+    {
+        h->resizeSection(RoomsListModel::PlayerCountColumn, 32);
+        h->resizeSection(RoomsListModel::TeamCountColumn, 32);
+        h->resizeSection(RoomsListModel::OwnerColumn, 100);
+        h->resizeSection(RoomsListModel::MapColumn, 100);
+        h->resizeSection(RoomsListModel::SchemeColumn, 100);
+        h->resizeSection(RoomsListModel::WeaponsColumn, 100);
+    }
+
+    h->setSortIndicatorShown(true);
+    h->setResizeMode(RoomsListModel::NameColumn, QHeaderView::Stretch);
+}
+
+
+void PageRoomsList::onSortIndicatorChanged(int logicalIndex, Qt::SortOrder order)
+{
+    if (roomsModel == NULL)
+        return;
+
+    // three state sorting: asc -> dsc -> default (by room state)
+    if ((order == Qt::AscendingOrder) && (logicalIndex == roomsModel->sortColumn()))
+        roomsList->horizontalHeader()->setSortIndicator(
+            RoomsListModel::StateColumn, Qt::AscendingOrder);
+    else
+        roomsModel->sort(logicalIndex, order);
 }
+
+
+void PageRoomsList::onFilterChanged()
+{
+    if (roomsModel == NULL)
+        return;
+
+    roomsModel->setFilterWildcard(QString("*%1*").arg(searchText->text()));
+
+    int stateIdx = CBState->currentIndex();
+    // any = 0, in lobby/false = 1, in progress/true = 2
+
+    if (stateIdx == 0)
+        stateFilteredModel->setFilterWildcard("*"); // "any"
+    else
+        stateFilteredModel->setFilterFixedString(QString(stateIdx == 2));
+
+    if (CBRules->currentIndex() == 0)
+        schemeFilteredModel->setFilterWildcard("*"); // "any"
+    else
+        schemeFilteredModel->setFilterWildcard(
+            QString("*%1*").arg(CBRules->currentText()));
+
+    if (CBWeapons->currentIndex() == 0)
+        weaponsFilteredModel->setFilterWildcard("*"); // "any"
+    else
+        weaponsFilteredModel->setFilterWildcard(
+            QString("*%1*").arg(CBWeapons->currentText()));
+}
+
+
+bool PageRoomsList::restoreHeaderState()
+{
+    if (!m_gameSettings->contains("frontend/roomslist_header"))
+        return false;
+    return roomsList->horizontalHeader()->restoreState(QByteArray::fromHex(
+        (m_gameSettings->value("frontend/roomslist_header").toByteArray())));
+}
+
+void PageRoomsList::saveHeaderState()
+{
+    m_gameSettings->setValue("frontend/roomslist_header",
+        roomsList->horizontalHeader()->saveState().toHex());
+}
--- a/QTfrontend/ui/page/pageroomslist.h	Sun Apr 01 15:23:34 2012 +0200
+++ b/QTfrontend/ui/page/pageroomslist.h	Wed May 02 23:53:45 2012 +0200
@@ -1,6 +1,6 @@
 /*
  * Hedgewars, a free turn based strategy game
- * Copyright (c) 2006-2012 Andrey Korotaev <unC0Rr@gmail.com>
+ * Copyright (c) 2004-2012 Andrey Korotaev <unC0Rr@gmail.com>
  *
  * This program is free software; you can redistribute it and/or modify
  * it under the terms of the GNU General Public License as published by
@@ -24,6 +24,8 @@
 class HWChatWidget;
 class AmmoSchemeModel;
 class QTableView;
+class RoomsListModel;
+class QSortFilterProxyModel;
 
 class PageRoomsList : public AbstractPage
 {
@@ -49,7 +51,7 @@
         HWChatWidget * chatWidget;
         QLabel * lblCount;
 
-        void setModel(QAbstractTableModel * model);
+        void setModel(RoomsListModel * model);
 
     public slots:
         void setAdmin(bool);
@@ -73,12 +75,20 @@
         void onRefreshClick();
         void onClearClick();
         void onJoinConfirmation(const QString &);
+        void onSortIndicatorChanged(int logicalIndex, Qt::SortOrder order);
+        void onFilterChanged();
+        void saveHeaderState();
 
     private:
         QSettings * m_gameSettings;
+        QSortFilterProxyModel * roomsModel;
+        QSortFilterProxyModel * stateFilteredModel;
+        QSortFilterProxyModel * schemeFilteredModel;
+        QSortFilterProxyModel * weaponsFilteredModel;
 
         AmmoSchemeModel * ammoSchemeModel;
 
+        bool restoreHeaderState();
 };
 
 #endif
--- a/QTfrontend/ui/page/pagescheme.cpp	Sun Apr 01 15:23:34 2012 +0200
+++ b/QTfrontend/ui/page/pagescheme.cpp	Wed May 02 23:53:45 2012 +0200
@@ -1,6 +1,6 @@
 /*
  * Hedgewars, a free turn based strategy game
- * Copyright (c) 2006-2012 Andrey Korotaev <unC0Rr@gmail.com>
+ * Copyright (c) 2004-2012 Andrey Korotaev <unC0Rr@gmail.com>
  *
  * This program is free software; you can redistribute it and/or modify
  * it under the terms of the GNU General Public License as published by
--- a/QTfrontend/ui/page/pagescheme.h	Sun Apr 01 15:23:34 2012 +0200
+++ b/QTfrontend/ui/page/pagescheme.h	Wed May 02 23:53:45 2012 +0200
@@ -1,6 +1,6 @@
 /*
  * Hedgewars, a free turn based strategy game
- * Copyright (c) 2006-2012 Andrey Korotaev <unC0Rr@gmail.com>
+ * Copyright (c) 2004-2012 Andrey Korotaev <unC0Rr@gmail.com>
  *
  * This program is free software; you can redistribute it and/or modify
  * it under the terms of the GNU General Public License as published by
--- a/QTfrontend/ui/page/pageselectweapon.cpp	Sun Apr 01 15:23:34 2012 +0200
+++ b/QTfrontend/ui/page/pageselectweapon.cpp	Wed May 02 23:53:45 2012 +0200
@@ -1,6 +1,6 @@
 /*
  * Hedgewars, a free turn based strategy game
- * Copyright (c) 2006-2012 Andrey Korotaev <unC0Rr@gmail.com>
+ * Copyright (c) 2004-2012 Andrey Korotaev <unC0Rr@gmail.com>
  *
  * This program is free software; you can redistribute it and/or modify
  * it under the terms of the GNU General Public License as published by
--- a/QTfrontend/ui/page/pageselectweapon.h	Sun Apr 01 15:23:34 2012 +0200
+++ b/QTfrontend/ui/page/pageselectweapon.h	Wed May 02 23:53:45 2012 +0200
@@ -1,6 +1,6 @@
 /*
  * Hedgewars, a free turn based strategy game
- * Copyright (c) 2006-2012 Andrey Korotaev <unC0Rr@gmail.com>
+ * Copyright (c) 2004-2012 Andrey Korotaev <unC0Rr@gmail.com>
  *
  * This program is free software; you can redistribute it and/or modify
  * it under the terms of the GNU General Public License as published by
--- a/QTfrontend/ui/page/pagesingleplayer.cpp	Sun Apr 01 15:23:34 2012 +0200
+++ b/QTfrontend/ui/page/pagesingleplayer.cpp	Wed May 02 23:53:45 2012 +0200
@@ -1,6 +1,6 @@
 /*
  * Hedgewars, a free turn based strategy game
- * Copyright (c) 2006-2012 Andrey Korotaev <unC0Rr@gmail.com>
+ * Copyright (c) 2004-2012 Andrey Korotaev <unC0Rr@gmail.com>
  *
  * This program is free software; you can redistribute it and/or modify
  * it under the terms of the GNU General Public License as published by
--- a/QTfrontend/ui/page/pagesingleplayer.h	Sun Apr 01 15:23:34 2012 +0200
+++ b/QTfrontend/ui/page/pagesingleplayer.h	Wed May 02 23:53:45 2012 +0200
@@ -1,6 +1,6 @@
 /*
  * Hedgewars, a free turn based strategy game
- * Copyright (c) 2006-2012 Andrey Korotaev <unC0Rr@gmail.com>
+ * Copyright (c) 2004-2012 Andrey Korotaev <unC0Rr@gmail.com>
  *
  * This program is free software; you can redistribute it and/or modify
  * it under the terms of the GNU General Public License as published by
--- a/QTfrontend/ui/page/pagetraining.cpp	Sun Apr 01 15:23:34 2012 +0200
+++ b/QTfrontend/ui/page/pagetraining.cpp	Wed May 02 23:53:45 2012 +0200
@@ -1,6 +1,6 @@
 /*
  * Hedgewars, a free turn based strategy game
- * Copyright (c) 2006-2012 Andrey Korotaev <unC0Rr@gmail.com>
+ * Copyright (c) 2004-2012 Andrey Korotaev <unC0Rr@gmail.com>
  *
  * This program is free software; you can redistribute it and/or modify
  * it under the terms of the GNU General Public License as published by
@@ -28,7 +28,7 @@
 #include <QSettings>
 
 #include "hwconsts.h"
-#include "HWDataManager.h"
+#include "DataManager.h"
 
 #include "pagetraining.h"
 
@@ -115,7 +115,7 @@
 {
     initPage();
 
-    HWDataManager & dataMgr = HWDataManager::instance();
+    DataManager & dataMgr = DataManager::instance();
 
     // get locale
     QSettings settings(cfgdir->absolutePath() + "/hedgewars.ini",
@@ -186,7 +186,7 @@
 
 void PageTraining::updateInfo()
 {
-    HWDataManager & dataMgr = HWDataManager::instance();
+    DataManager & dataMgr = DataManager::instance();
 
     if (lstMissions->currentItem())
     {
--- a/QTfrontend/ui/page/pagetraining.h	Sun Apr 01 15:23:34 2012 +0200
+++ b/QTfrontend/ui/page/pagetraining.h	Wed May 02 23:53:45 2012 +0200
@@ -1,6 +1,6 @@
 /*
  * Hedgewars, a free turn based strategy game
- * Copyright (c) 2006-2012 Andrey Korotaev <unC0Rr@gmail.com>
+ * Copyright (c) 2004-2012 Andrey Korotaev <unC0Rr@gmail.com>
  *
  * This program is free software; you can redistribute it and/or modify
  * it under the terms of the GNU General Public License as published by
--- a/QTfrontend/ui/widget/FreqSpinBox.cpp	Sun Apr 01 15:23:34 2012 +0200
+++ b/QTfrontend/ui/widget/FreqSpinBox.cpp	Wed May 02 23:53:45 2012 +0200
@@ -1,6 +1,6 @@
 /*
  * Hedgewars, a free turn based strategy game
- * Copyright (c) 2005-2012 Andrey Korotaev <unC0Rr@gmail.com>
+ * Copyright (c) 2004-2012 Andrey Korotaev <unC0Rr@gmail.com>
  *
  * This program is free software; you can redistribute it and/or modify
  * it under the terms of the GNU General Public License as published by
--- a/QTfrontend/ui/widget/FreqSpinBox.h	Sun Apr 01 15:23:34 2012 +0200
+++ b/QTfrontend/ui/widget/FreqSpinBox.h	Wed May 02 23:53:45 2012 +0200
@@ -1,6 +1,6 @@
 /*
  * Hedgewars, a free turn based strategy game
- * Copyright (c) 2005-2012 Andrey Korotaev <unC0Rr@gmail.com>
+ * Copyright (c) 2004-2012 Andrey Korotaev <unC0Rr@gmail.com>
  *
  * This program is free software; you can redistribute it and/or modify
  * it under the terms of the GNU General Public License as published by
--- a/QTfrontend/ui/widget/HistoryLineEdit.cpp	Sun Apr 01 15:23:34 2012 +0200
+++ b/QTfrontend/ui/widget/HistoryLineEdit.cpp	Wed May 02 23:53:45 2012 +0200
@@ -1,7 +1,7 @@
 /*
  * Hedgewars, a free turn based strategy game
  * Copyright (c) 2006-2007 Igor Ulyanov <iulyanov@gmail.com>
- * Copyright (c) 2007-2012 Andrey Korotaev <unC0Rr@gmail.com>
+ * Copyright (c) 2004-2012 Andrey Korotaev <unC0Rr@gmail.com>
  *
  * This program is free software; you can redistribute it and/or modify
  * it under the terms of the GNU General Public License as published by
--- a/QTfrontend/ui/widget/HistoryLineEdit.h	Sun Apr 01 15:23:34 2012 +0200
+++ b/QTfrontend/ui/widget/HistoryLineEdit.h	Wed May 02 23:53:45 2012 +0200
@@ -1,7 +1,7 @@
 /*
  * Hedgewars, a free turn based strategy game
  * Copyright (c) 2006-2007 Igor Ulyanov <iulyanov@gmail.com>
- * Copyright (c) 2007-2012 Andrey Korotaev <unC0Rr@gmail.com>
+ * Copyright (c) 2004-2012 Andrey Korotaev <unC0Rr@gmail.com>
  *
  * This program is free software; you can redistribute it and/or modify
  * it under the terms of the GNU General Public License as published by
--- a/QTfrontend/ui/widget/SmartLineEdit.cpp	Sun Apr 01 15:23:34 2012 +0200
+++ b/QTfrontend/ui/widget/SmartLineEdit.cpp	Wed May 02 23:53:45 2012 +0200
@@ -1,7 +1,7 @@
 /*
  * Hedgewars, a free turn based strategy game
  * Copyright (c) 2006-2007 Igor Ulyanov <iulyanov@gmail.com>
- * Copyright (c) 2007-2012 Andrey Korotaev <unC0Rr@gmail.com>
+ * Copyright (c) 2004-2012 Andrey Korotaev <unC0Rr@gmail.com>
  *
  * This program is free software; you can redistribute it and/or modify
  * it under the terms of the GNU General Public License as published by
--- a/QTfrontend/ui/widget/SmartLineEdit.h	Sun Apr 01 15:23:34 2012 +0200
+++ b/QTfrontend/ui/widget/SmartLineEdit.h	Wed May 02 23:53:45 2012 +0200
@@ -1,7 +1,7 @@
 /*
  * Hedgewars, a free turn based strategy game
  * Copyright (c) 2006-2007 Igor Ulyanov <iulyanov@gmail.com>
- * Copyright (c) 2007-2012 Andrey Korotaev <unC0Rr@gmail.com>
+ * Copyright (c) 2004-2012 Andrey Korotaev <unC0Rr@gmail.com>
  *
  * This program is free software; you can redistribute it and/or modify
  * it under the terms of the GNU General Public License as published by
--- a/QTfrontend/ui/widget/SquareLabel.cpp	Sun Apr 01 15:23:34 2012 +0200
+++ b/QTfrontend/ui/widget/SquareLabel.cpp	Wed May 02 23:53:45 2012 +0200
@@ -1,6 +1,6 @@
 /*
  * Hedgewars, a free turn based strategy game
- * Copyright (c) 2006-2012 Andrey Korotaev <unC0Rr@gmail.com>
+ * Copyright (c) 2004-2012 Andrey Korotaev <unC0Rr@gmail.com>
  *
  * This program is free software; you can redistribute it and/or modify
  * it under the terms of the GNU General Public License as published by
--- a/QTfrontend/ui/widget/SquareLabel.h	Sun Apr 01 15:23:34 2012 +0200
+++ b/QTfrontend/ui/widget/SquareLabel.h	Wed May 02 23:53:45 2012 +0200
@@ -1,6 +1,6 @@
 /*
  * Hedgewars, a free turn based strategy game
- * Copyright (c) 2006-2012 Andrey Korotaev <unC0Rr@gmail.com>
+ * Copyright (c) 2004-2012 Andrey Korotaev <unC0Rr@gmail.com>
  *
  * This program is free software; you can redistribute it and/or modify
  * it under the terms of the GNU General Public License as published by
--- a/QTfrontend/ui/widget/about.cpp	Sun Apr 01 15:23:34 2012 +0200
+++ b/QTfrontend/ui/widget/about.cpp	Wed May 02 23:53:45 2012 +0200
@@ -1,6 +1,6 @@
 /*
  * Hedgewars, a free turn based strategy game
- * Copyright (c) 2006-2012 Andrey Korotaev <unC0Rr@gmail.com>
+ * Copyright (c) 2004-2012 Andrey Korotaev <unC0Rr@gmail.com>
  *
  * This program is free software; you can redistribute it and/or modify
  * it under the terms of the GNU General Public License as published by
--- a/QTfrontend/ui/widget/about.h	Sun Apr 01 15:23:34 2012 +0200
+++ b/QTfrontend/ui/widget/about.h	Wed May 02 23:53:45 2012 +0200
@@ -1,6 +1,6 @@
 /*
  * Hedgewars, a free turn based strategy game
- * Copyright (c) 2006-2012 Andrey Korotaev <unC0Rr@gmail.com>
+ * Copyright (c) 2004-2012 Andrey Korotaev <unC0Rr@gmail.com>
  *
  * This program is free software; you can redistribute it and/or modify
  * it under the terms of the GNU General Public License as published by
--- a/QTfrontend/ui/widget/bgwidget.cpp	Sun Apr 01 15:23:34 2012 +0200
+++ b/QTfrontend/ui/widget/bgwidget.cpp	Wed May 02 23:53:45 2012 +0200
@@ -1,7 +1,7 @@
 /*
  * Hedgewars, a free turn based strategy game
  * Copyright (c) 2009 Kristian Lehmann <email@thexception.net>
- * Copyright (c) 2009-2012 Andrey Korotaev <unC0Rr@gmail.com>
+ * Copyright (c) 2004-2012 Andrey Korotaev <unC0Rr@gmail.com>
  *
  * This program is free software; you can redistribute it and/or modify
  * it under the terms of the GNU General Public License as published by
--- a/QTfrontend/ui/widget/bgwidget.h	Sun Apr 01 15:23:34 2012 +0200
+++ b/QTfrontend/ui/widget/bgwidget.h	Wed May 02 23:53:45 2012 +0200
@@ -1,7 +1,7 @@
 /*
  * Hedgewars, a free turn based strategy game
  * Copyright (c) 2009 Kristian Lehmann <email@thexception.net>
- * Copyright (c) 2009-2012 Andrey Korotaev <unC0Rr@gmail.com>
+ * Copyright (c) 2004-2012 Andrey Korotaev <unC0Rr@gmail.com>
  *
  * This program is free software; you can redistribute it and/or modify
  * it under the terms of the GNU General Public License as published by
--- a/QTfrontend/ui/widget/chatwidget.cpp	Sun Apr 01 15:23:34 2012 +0200
+++ b/QTfrontend/ui/widget/chatwidget.cpp	Wed May 02 23:53:45 2012 +0200
@@ -1,7 +1,7 @@
 /*
  * Hedgewars, a free turn based strategy game
  * Copyright (c) 2007 Igor Ulyanov <iulyanov@gmail.com>
- * Copyright (c) 2007-2012 Andrey Korotaev <unC0Rr@gmail.com>
+ * Copyright (c) 2004-2012 Andrey Korotaev <unC0Rr@gmail.com>
  *
  * This program is free software; you can redistribute it and/or modify
  * it under the terms of the GNU General Public License as published by
@@ -37,7 +37,7 @@
 #include <QMessageBox>
 
 
-#include "HWDataManager.h"
+#include "DataManager.h"
 #include "hwconsts.h"
 #include "gameuiconfig.h"
 
@@ -126,7 +126,7 @@
     if (orgStyleSheet.isEmpty())
     {
         // load external stylesheet if there is any
-        QFile extFile(HWDataManager::instance().findFileForRead("css/chat.css"));
+        QFile extFile(DataManager::instance().findFileForRead("css/chat.css"));
 
         QFile resFile(":/res/css/chat.css");
 
@@ -247,17 +247,22 @@
     this->notify = notify;
 
     m_isAdmin = false;
+    m_autoKickEnabled = false;
 
     if(gameSettings->value("frontend/sound", true).toBool())
     {
-        if (notify)
-            m_helloSound = HWDataManager::instance().findFileForRead(
-                               "Sounds/voices/Classic/Hello.ogg");
+        QStringList vpList =
+             QStringList() << "Classic" << "Default" << "Mobster" << "Russian";
 
-        m_hilightSound = HWDataManager::instance().findFileForRead(
+        foreach (QString vp, vpList)
+        {
+            m_helloSounds.append(DataManager::instance().findFileForRead(
+                               QString("Sounds/voices/%1/Hello.ogg").arg(vp)));
+        }
+
+        m_hilightSound = DataManager::instance().findFileForRead(
                              "Sounds/beep.ogg");
 
-        //m_hilightSound = m_helloSound;//"Sounds/beep.ogg";
     }
 
     mainLayout.setSpacing(1);
@@ -395,6 +400,11 @@
     }
 }
 
+void HWChatWidget::setIgnoreListKick(bool enabled)
+{
+    m_autoKickEnabled = enabled;
+}
+
 void HWChatWidget::loadList(QStringList & list, const QString & file)
 {
     list.clear();
@@ -632,6 +642,13 @@
 void HWChatWidget::nickAdded(const QString & nick, bool notifyNick)
 {
     bool isIgnored = ignoreList.contains(nick, Qt::CaseInsensitive);
+
+    if (isIgnored && m_isAdmin && m_autoKickEnabled)
+    {
+        emit kick(nick);
+        return;
+    }
+
     QListWidgetItem * item = new ListWidgetNickItem(nick, friendsList.contains(nick, Qt::CaseInsensitive), isIgnored);
     updateNickItem(item);
     chatNicks->addItem(item);
@@ -643,7 +660,8 @@
 
     if(notifyNick && notify && gameSettings->value("frontend/sound", true).toBool())
     {
-        SDLInteraction::instance().playSoundFile(m_helloSound);
+        SDLInteraction::instance().playSoundFile(
+                            m_helloSounds.at(rand() % m_helloSounds.size()));
     }
 }
 
@@ -968,7 +986,7 @@
 void HWChatWidget::saveStyleSheet()
 {
     QString dest =
-        HWDataManager::instance().findFileForWrite("css/chat.css");
+        DataManager::instance().findFileForWrite("css/chat.css");
 
     QFile file(dest);
     if (file.open(QIODevice::WriteOnly | QIODevice::Text))
--- a/QTfrontend/ui/widget/chatwidget.h	Sun Apr 01 15:23:34 2012 +0200
+++ b/QTfrontend/ui/widget/chatwidget.h	Wed May 02 23:53:45 2012 +0200
@@ -1,7 +1,7 @@
 /*
  * Hedgewars, a free turn based strategy game
  * Copyright (c) 2007 Igor Ulyanov <iulyanov@gmail.com>
- * Copyright (c) 2007-2012 Andrey Korotaev <unC0Rr@gmail.com>
+ * Copyright (c) 2004-2012 Andrey Korotaev <unC0Rr@gmail.com>
  *
  * This program is free software; you can redistribute it and/or modify
  * it under the terms of the GNU General Public License as published by
@@ -72,6 +72,7 @@
         HWChatWidget(QWidget* parent, QSettings * gameSettings, bool notify);
         void loadLists(const QString & nick);
         void saveLists(const QString & nick);
+        void setIgnoreListKick(bool enabled); ///< automatically kick people on ignore list (if possible)
         void setShowReady(bool s);
         void setShowFollow(bool enabled);
         QStringList ignoreList, friendsList;
@@ -136,13 +137,14 @@
         QAction * acIgnore;
         QAction * acFriend;
         QSettings * gameSettings;
-        QString m_helloSound;
+        QStringList m_helloSounds;
         QString m_hilightSound;
         QString m_userNick;
         QString m_clickedNick;
         QList<QRegExp> m_highlights; ///< regular expressions used for highlighting
         bool notify;
         bool showReady;
+        bool m_autoKickEnabled;
 
     private slots:
         void returnPressed();
--- a/QTfrontend/ui/widget/databrowser.cpp	Sun Apr 01 15:23:34 2012 +0200
+++ b/QTfrontend/ui/widget/databrowser.cpp	Wed May 02 23:53:45 2012 +0200
@@ -1,3 +1,26 @@
+/*
+ * Hedgewars, a free turn based strategy game
+ * Copyright (c) 2004-2012 Andrey Korotaev <unC0Rr@gmail.com>
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; version 2 of the License
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA
+ */
+
+/**
+ * @file
+ * @brief DataBrowser class implementation
+ */
+
 #include <QNetworkAccessManager>
 #include <QNetworkRequest>
 #include <QNetworkReply>
--- a/QTfrontend/ui/widget/databrowser.h	Sun Apr 01 15:23:34 2012 +0200
+++ b/QTfrontend/ui/widget/databrowser.h	Wed May 02 23:53:45 2012 +0200
@@ -1,5 +1,28 @@
-#ifndef DATABROWSER_H
-#define DATABROWSER_H
+/*
+ * Hedgewars, a free turn based strategy game
+ * Copyright (c) 2004-2012 Andrey Korotaev <unC0Rr@gmail.com>
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; version 2 of the License
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA
+ */
+
+/**
+ * @file
+ * @brief DataBrowser class definition
+ */
+
+#ifndef HEDGEWARS_DATABROWSER_H
+#define HEDGEWARS_DATABROWSER_H
 
 #include <QTextBrowser>
 #include <QSet>
@@ -30,4 +53,4 @@
         void resourceDownloaded();
 };
 
-#endif // DATABROWSER_H
+#endif // HEDGEWARS_DATABROWSER_H
--- a/QTfrontend/ui/widget/drawmapwidget.cpp	Sun Apr 01 15:23:34 2012 +0200
+++ b/QTfrontend/ui/widget/drawmapwidget.cpp	Wed May 02 23:53:45 2012 +0200
@@ -1,6 +1,6 @@
 /*
  * Hedgewars, a free turn based strategy game
- * Copyright (c) 2012 Andrey Korotaev <unC0Rr@gmail.com>
+ * Copyright (c) 2004-2012 Andrey Korotaev <unC0Rr@gmail.com>
  *
  * This program is free software; you can redistribute it and/or modify
  * it under the terms of the GNU General Public License as published by
@@ -19,6 +19,7 @@
 #include <QFile>
 #include <QMessageBox>
 #include <QEvent>
+#include <QDebug>
 
 #include "drawmapwidget.h"
 
@@ -51,8 +52,10 @@
 
 void DrawMapWidget::setScene(DrawMapScene * scene)
 {
+    m_scene = scene;
+
     ui->graphicsView->setScene(scene);
-    m_scene = scene;
+    connect(scene, SIGNAL(pathChanged()), this, SLOT(pathChanged()));
 }
 
 void DrawMapWidget::resizeEvent(QResizeEvent * event)
@@ -80,6 +83,11 @@
     if(m_scene) m_scene->clearMap();
 }
 
+void DrawMapWidget::setErasing(bool erasing)
+{
+    if(m_scene) m_scene->setErasing(erasing);
+}
+
 void DrawMapWidget::save(const QString & fileName)
 {
     if(m_scene)
@@ -105,3 +113,53 @@
             m_scene->decode(qUncompress(QByteArray::fromBase64(f.readAll())));
     }
 }
+
+void DrawMapWidget::pathChanged()
+{
+    ui->lblPoints->setNum(m_scene->pointsCount());
+}
+
+
+
+DrawMapView::DrawMapView(QWidget *parent) :
+    QGraphicsView(parent)
+{
+   setMouseTracking(true);
+
+    m_scene = 0;
+}
+
+
+DrawMapView::~DrawMapView()
+{
+
+}
+
+void DrawMapView::setScene(DrawMapScene *scene)
+{
+    m_scene = scene;
+
+    QGraphicsView::setScene(scene);
+}
+
+// Why don't I ever recieve this event?
+void DrawMapView::enterEvent(QEvent *event)
+{
+    if(m_scene)
+        m_scene->showCursor();
+
+    QGraphicsView::enterEvent(event);
+}
+
+void DrawMapView::leaveEvent(QEvent *event)
+{
+    if(m_scene)
+        m_scene->hideCursor();
+
+    QGraphicsView::leaveEvent(event);
+}
+
+bool DrawMapView::viewportEvent(QEvent *event)
+{
+    return QGraphicsView::viewportEvent(event);
+}
--- a/QTfrontend/ui/widget/drawmapwidget.h	Sun Apr 01 15:23:34 2012 +0200
+++ b/QTfrontend/ui/widget/drawmapwidget.h	Wed May 02 23:53:45 2012 +0200
@@ -1,6 +1,6 @@
 /*
  * Hedgewars, a free turn based strategy game
- * Copyright (c) 2012 Andrey Korotaev <unC0Rr@gmail.com>
+ * Copyright (c) 2004-2012 Andrey Korotaev <unC0Rr@gmail.com>
  *
  * This program is free software; you can redistribute it and/or modify
  * it under the terms of the GNU General Public License as published by
@@ -23,23 +23,50 @@
 #include <QHBoxLayout>
 #include <QPushButton>
 #include <QGraphicsView>
+#include <QLabel>
 
 #include "qaspectratiolayout.h"
 #include "drawmapscene.h"
 
+
+class DrawMapView : public QGraphicsView
+{
+    Q_OBJECT
+
+public:
+    explicit DrawMapView(QWidget *parent = 0);
+    ~DrawMapView();
+
+    void setScene(DrawMapScene *scene);
+
+protected:
+    void enterEvent(QEvent * event);
+    void leaveEvent(QEvent * event);
+    bool viewportEvent(QEvent * event);
+
+private:
+    DrawMapScene * m_scene;
+};
+
 namespace Ui
 {
     class Ui_DrawMapWidget
     {
         public:
-            QGraphicsView *graphicsView;
+            DrawMapView *graphicsView;
+            QLabel * lblPoints;
 
             void setupUi(QWidget *drawMapWidget)
             {
-                QAspectRatioLayout * arLayout = new QAspectRatioLayout(drawMapWidget);
+                QVBoxLayout * vbox = new QVBoxLayout(drawMapWidget);
+                vbox->setMargin(0);
+                lblPoints = new QLabel("0", drawMapWidget);
+                vbox->addWidget(lblPoints);
+                QAspectRatioLayout * arLayout = new QAspectRatioLayout();
                 arLayout->setMargin(0);
+                vbox->addLayout(arLayout);
 
-                graphicsView = new QGraphicsView(drawMapWidget);
+                graphicsView = new DrawMapView(drawMapWidget);
                 arLayout->addWidget(graphicsView);
 
                 retranslateUi(drawMapWidget);
@@ -70,6 +97,7 @@
     public slots:
         void undo();
         void clear();
+        void setErasing(bool erasing);
         void save(const QString & fileName);
         void load(const QString & fileName);
 
@@ -82,6 +110,9 @@
         Ui::DrawMapWidget *ui;
 
         DrawMapScene * m_scene;
+
+    private slots:
+        void pathChanged();
 };
 
 #endif // DRAWMAPWIDGET_H
--- a/QTfrontend/ui/widget/fpsedit.cpp	Sun Apr 01 15:23:34 2012 +0200
+++ b/QTfrontend/ui/widget/fpsedit.cpp	Wed May 02 23:53:45 2012 +0200
@@ -1,6 +1,6 @@
 /*
  * Hedgewars, a free turn based strategy game
- * Copyright (c) 2006-2012 Andrey Korotaev <unC0Rr@gmail.com>
+ * Copyright (c) 2004-2012 Andrey Korotaev <unC0Rr@gmail.com>
  *
  * This program is free software; you can redistribute it and/or modify
  * it under the terms of the GNU General Public License as published by
--- a/QTfrontend/ui/widget/fpsedit.h	Sun Apr 01 15:23:34 2012 +0200
+++ b/QTfrontend/ui/widget/fpsedit.h	Wed May 02 23:53:45 2012 +0200
@@ -1,6 +1,6 @@
 /*
  * Hedgewars, a free turn based strategy game
- * Copyright (c) 2006-2012 Andrey Korotaev <unC0Rr@gmail.com>
+ * Copyright (c) 2004-2012 Andrey Korotaev <unC0Rr@gmail.com>
  *
  * This program is free software; you can redistribute it and/or modify
  * it under the terms of the GNU General Public License as published by
--- a/QTfrontend/ui/widget/frameTeam.cpp	Sun Apr 01 15:23:34 2012 +0200
+++ b/QTfrontend/ui/widget/frameTeam.cpp	Wed May 02 23:53:45 2012 +0200
@@ -1,7 +1,7 @@
 /*
  * Hedgewars, a free turn based strategy game
  * Copyright (c) 2006-2007 Igor Ulyanov <iulyanov@gmail.com>
- * Copyright (c) 2007-2012 Andrey Korotaev <unC0Rr@gmail.com>
+ * Copyright (c) 2004-2012 Andrey Korotaev <unC0Rr@gmail.com>
  *
  * This program is free software; you can redistribute it and/or modify
  * it under the terms of the GNU General Public License as published by
@@ -56,15 +56,19 @@
 
 void FrameTeams::resetColors()
 {
-    currentColor=availableColors.end() - 1; // ensure next color is the first one
+    currentColor = availableColors.last(); // ensure next color is the first one
 }
 
 QColor FrameTeams::getNextColor() const
 {
-    QList<QColor>::ConstIterator nextColor=currentColor;
-    ++nextColor;
-    if (nextColor==availableColors.end()) nextColor=availableColors.begin();
-    return *nextColor;
+    int idx = availableColors.indexOf(currentColor);
+
+    idx++;
+
+    if (idx >= availableColors.size())
+        idx = 0;
+
+    return availableColors.at(idx);
 }
 
 void FrameTeams::addTeam(HWTeam team, bool willPlay)
--- a/QTfrontend/ui/widget/frameTeam.h	Sun Apr 01 15:23:34 2012 +0200
+++ b/QTfrontend/ui/widget/frameTeam.h	Wed May 02 23:53:45 2012 +0200
@@ -1,7 +1,7 @@
 /*
  * Hedgewars, a free turn based strategy game
  * Copyright (c) 2006-2007 Igor Ulyanov <iulyanov@gmail.com>
- * Copyright (c) 2007-2012 Andrey Korotaev <unC0Rr@gmail.com>
+ * Copyright (c) 2004-2012 Andrey Korotaev <unC0Rr@gmail.com>
  *
  * This program is free software; you can redistribute it and/or modify
  * it under the terms of the GNU General Public License as published by
@@ -55,7 +55,7 @@
         const int maxHedgehogsPerGame;
         int overallHedgehogs;
         QList<QColor> availableColors;
-        QList<QColor>::Iterator currentColor;
+        QColor currentColor;
 
         void emitTeamColorChanged(const HWTeam& team);
 
--- a/QTfrontend/ui/widget/gamecfgwidget.cpp	Sun Apr 01 15:23:34 2012 +0200
+++ b/QTfrontend/ui/widget/gamecfgwidget.cpp	Wed May 02 23:53:45 2012 +0200
@@ -1,6 +1,6 @@
 /*
  * Hedgewars, a free turn based strategy game
- * Copyright (c) 2006-2012 Andrey Korotaev <unC0Rr@gmail.com>
+ * Copyright (c) 2004-2012 Andrey Korotaev <unC0Rr@gmail.com>
  *
  * This program is free software; you can redistribute it and/or modify
  * it under the terms of the GNU General Public License as published by
@@ -28,7 +28,7 @@
 
 #include "gamecfgwidget.h"
 #include "igbox.h"
-#include "HWDataManager.h"
+#include "DataManager.h"
 #include "hwconsts.h"
 #include "ammoSchemeModel.h"
 #include "proto.h"
@@ -56,41 +56,8 @@
     Scripts = new QComboBox(GBoxOptions);
     GBoxOptionsLayout->addWidget(Scripts, 1, 1);
 
-    Scripts->addItem("Normal");
-    Scripts->insertSeparator(1);
-
-    for (int i = 0; i < scriptList->size(); ++i)
-    {
-        QString script = (*scriptList)[i].remove(".lua", Qt::CaseInsensitive);
-        QList<QVariant> scriptInfo;
-        scriptInfo.push_back(script);
-        QFile scriptCfgFile(HWDataManager::instance().findFileForRead(
-                                QString("Scripts/Multiplayer/%2.cfg").arg(script)));
-        if (scriptCfgFile.exists() && scriptCfgFile.open(QFile::ReadOnly))
-        {
-            QString scheme;
-            QString weapons;
-            QTextStream input(&scriptCfgFile);
-            input >> scheme;
-            input >> weapons;
-            if (scheme.isEmpty())
-                scheme = "locked";
-            scheme.replace("_", " ");
-            if (weapons.isEmpty())
-                weapons = "locked";
-            weapons.replace("_", " ");
-            scriptInfo.push_back(scheme);
-            scriptInfo.push_back(weapons);
-            scriptCfgFile.close();
-        }
-        else
-        {
-            scriptInfo.push_back("locked");
-            scriptInfo.push_back("locked");
-        }
-        Scripts->addItem(script.replace("_", " "), scriptInfo);
-    }
-
+    Scripts->setModel(DataManager::instance().gameStyleModel());
+    m_curScript = Scripts->currentText();
     connect(Scripts, SIGNAL(currentIndexChanged(int)), this, SLOT(scriptChanged(int)));
 
     QWidget *SchemeWidget = new QWidget(GBoxOptions);
@@ -146,6 +113,8 @@
     connect(pMapContainer, SIGNAL(newTemplateFilter(int)), this, SLOT(templateFilterChanged(int)));
     connect(pMapContainer, SIGNAL(drawMapRequested()), this, SIGNAL(goToDrawMap()));
     connect(pMapContainer, SIGNAL(drawnMapChanged(const QByteArray &)), this, SLOT(onDrawnMapChanged(const QByteArray &)));
+
+    connect(&DataManager::instance(), SIGNAL(updated()), this, SLOT(updateModelViews()));
 }
 
 void GameCFGWidget::jumpToSchemes()
@@ -244,7 +213,7 @@
 
     if (Scripts->currentIndex() > 0)
     {
-        bcfg << QString("escript Scripts/Multiplayer/%1.lua").arg(Scripts->itemData(Scripts->currentIndex()).toList()[0].toString()).toUtf8();
+        bcfg << QString("escript Scripts/Multiplayer/%1.lua").arg(Scripts->itemData(Scripts->currentIndex(), GameStyleModel::ScriptRole).toString()).toUtf8();
     }
 
     bcfg << QString("eseed " + pMapContainer->getCurrentSeed()).toUtf8();
@@ -525,10 +494,13 @@
 
 void GameCFGWidget::scriptChanged(int index)
 {
+    const QString & name = Scripts->itemText(index);
+    m_curScript = name;
+
     if(isEnabled() && index > 0)
     {
-        QString scheme = Scripts->itemData(Scripts->currentIndex()).toList()[1].toString();
-        QString weapons = Scripts->itemData(Scripts->currentIndex()).toList()[2].toString();
+        QString scheme = Scripts->itemData(index, GameStyleModel::SchemeRole).toString();
+        QString weapons = Scripts->itemData(index, GameStyleModel::WeaponsRole).toString();
 
         if (scheme == "locked")
         {
@@ -571,7 +543,7 @@
         WeaponsName->setEnabled(true);
         bindEntries->setEnabled(true);
     }
-    emit paramChanged("SCRIPT", QStringList(Scripts->itemText(index)));
+    emit paramChanged("SCRIPT", QStringList(name));
 }
 
 void GameCFGWidget::mapgenChanged(MapGenerator m)
@@ -593,3 +565,17 @@
 {
     emit paramChanged("DRAWNMAP", QStringList(qCompress(data, 9).toBase64()));
 }
+
+
+void GameCFGWidget::updateModelViews()
+{
+    // restore game-style selection
+    if (!m_curScript.isEmpty())
+    {
+        int idx = Scripts->findText(m_curScript);
+        if (idx >= 0)
+            Scripts->setCurrentIndex(idx);
+        else
+            Scripts->setCurrentIndex(0);
+    }
+}
--- a/QTfrontend/ui/widget/gamecfgwidget.h	Sun Apr 01 15:23:34 2012 +0200
+++ b/QTfrontend/ui/widget/gamecfgwidget.h	Wed May 02 23:53:45 2012 +0200
@@ -1,6 +1,6 @@
 /*
  * Hedgewars, a free turn based strategy game
- * Copyright (c) 2006-2012 Andrey Korotaev <unC0Rr@gmail.com>
+ * Copyright (c) 2004-2012 Andrey Korotaev <unC0Rr@gmail.com>
  *
  * This program is free software; you can redistribute it and/or modify
  * it under the terms of the GNU General Public License as published by
@@ -72,6 +72,7 @@
         void mapgenChanged(MapGenerator m);
         void maze_sizeChanged(int s);
         void onDrawnMapChanged(const QByteArray & data);
+        void updateModelViews();
 
     private:
         QGridLayout mainLayout;
@@ -79,6 +80,7 @@
         QString curNetAmmoName;
         QString curNetAmmo;
         QRegExp seedRegexp;
+        QString m_curScript;
 
         void setNetAmmo(const QString& name, const QString& ammo);
 
--- a/QTfrontend/ui/widget/hedgehogerWidget.cpp	Sun Apr 01 15:23:34 2012 +0200
+++ b/QTfrontend/ui/widget/hedgehogerWidget.cpp	Wed May 02 23:53:45 2012 +0200
@@ -1,7 +1,7 @@
 /*
  * Hedgewars, a free turn based strategy game
  * Copyright (c) 2006-2008 Ulyanov Igor <iulyanov@gmail.com>
- * Copyright (c) 2008-2012 Andrey Korotaev <unC0Rr@gmail.com>
+ * Copyright (c) 2004-2012 Andrey Korotaev <unC0Rr@gmail.com>
  *
  * This program is free software; you can redistribute it and/or modify
  * it under the terms of the GNU General Public License as published by
@@ -19,6 +19,8 @@
 
 #include "hedgehogerWidget.h"
 
+#include <QPainter>
+
 #include "frameTeam.h"
 
 CHedgehogerWidget::CHedgehogerWidget(const QImage& im, const QImage& img, QWidget * parent) :
@@ -32,6 +34,8 @@
       numItems = pOurFrameTeams->maxHedgehogsPerGame - pOurFrameTeams->overallHedgehogs;
     } else numItems = 4;
     pOurFrameTeams->overallHedgehogs += numItems;*/
+
+    this->setMinimumWidth(48);
 }
 
 void CHedgehogerWidget::incItems()
@@ -74,3 +78,34 @@
 {
     return numItems;
 }
+
+void CHedgehogerWidget::paintEvent(QPaintEvent* event)
+{
+    Q_UNUSED(event);
+
+    if (this->width() >= 11 * numItems + 26)
+        ItemNum::paintEvent(event);
+    else
+    {
+        int width = this->width() - 38;
+        QPainter painter(this);
+
+        for(int i=0; i<numItems; i++)
+        {
+            QRect target((i * width) / (numItems -1), i % 2, 25, 35);
+            if (enabled)
+            {
+                painter.drawImage(target, m_im);
+            }
+            else
+            {
+                painter.drawImage(target, m_img);
+            }
+        }
+    }
+
+    QPainter painter(this);
+    painter.setFont(QFont("MS Shell Dlg", 10, QFont::Bold));
+    painter.drawText(this->width() - 12, 23, QString::number(numItems));
+
+}
--- a/QTfrontend/ui/widget/hedgehogerWidget.h	Sun Apr 01 15:23:34 2012 +0200
+++ b/QTfrontend/ui/widget/hedgehogerWidget.h	Wed May 02 23:53:45 2012 +0200
@@ -1,7 +1,7 @@
 /*
  * Hedgewars, a free turn based strategy game
  * Copyright (c) 2006-2007 Ulyanov Igor <iulyanov@gmail.com>
- * Copyright (c) 2007-2012 Andrey Korotaev <unC0Rr@gmail.com>
+ * Copyright (c) 2004-2012 Andrey Korotaev <unC0Rr@gmail.com>
  *
  * This program is free software; you can redistribute it and/or modify
  * it under the terms of the GNU General Public License as published by
@@ -42,6 +42,8 @@
         virtual void incItems();
         virtual void decItems();
 
+        virtual void paintEvent(QPaintEvent* event);
+
     private:
         CHedgehogerWidget();
         FrameTeams* pOurFrameTeams;
--- a/QTfrontend/ui/widget/igbox.cpp	Sun Apr 01 15:23:34 2012 +0200
+++ b/QTfrontend/ui/widget/igbox.cpp	Wed May 02 23:53:45 2012 +0200
@@ -1,6 +1,6 @@
 /*
  * Hedgewars, a free turn based strategy game
- * Copyright (c) 2008-2012 Andrey Korotaev <unC0Rr@gmail.com>
+ * Copyright (c) 2004-2012 Andrey Korotaev <unC0Rr@gmail.com>
  *
  * This program is free software; you can redistribute it and/or modify
  * it under the terms of the GNU General Public License as published by
--- a/QTfrontend/ui/widget/igbox.h	Sun Apr 01 15:23:34 2012 +0200
+++ b/QTfrontend/ui/widget/igbox.h	Wed May 02 23:53:45 2012 +0200
@@ -1,6 +1,6 @@
 /*
  * Hedgewars, a free turn based strategy game
- * Copyright (c) 2008-2012 Andrey Korotaev <unC0Rr@gmail.com>
+ * Copyright (c) 2004-2012 Andrey Korotaev <unC0Rr@gmail.com>
  *
  * This program is free software; you can redistribute it and/or modify
  * it under the terms of the GNU General Public License as published by
--- a/QTfrontend/ui/widget/itemNum.h	Sun Apr 01 15:23:34 2012 +0200
+++ b/QTfrontend/ui/widget/itemNum.h	Wed May 02 23:53:45 2012 +0200
@@ -32,13 +32,12 @@
         unsigned char getItemsNum() const;
         void setItemsNum(const unsigned char num);
 
-    private:
+    protected:
         QImage m_im;
         QImage m_img;
         bool infinityState;
         bool enabled;
 
-    protected:
         ItemNum(const QImage& im, const QImage& img, QWidget * parent, unsigned char min=2, unsigned char max=8);
         virtual QSize sizeHint () const;
         virtual ~ItemNum()=0;
--- a/QTfrontend/ui/widget/mapContainer.cpp	Sun Apr 01 15:23:34 2012 +0200
+++ b/QTfrontend/ui/widget/mapContainer.cpp	Wed May 02 23:53:45 2012 +0200
@@ -68,104 +68,13 @@
 
     chooseMap = new QComboBox(mapWidget);
     chooseMap->setSizePolicy(QSizePolicy::Expanding, QSizePolicy::Fixed);
-    chooseMap->addItem(
-// FIXME - need real icons. Disabling until then
-//QIcon(":/res/mapRandom.png"),
-        QComboBox::tr("generated map..."));
-    chooseMap->addItem(
-// FIXME - need real icons. Disabling until then
-//QIcon(":/res/mapMaze.png"),
-        QComboBox::tr("generated maze..."));
-
-    chooseMap->addItem(QComboBox::tr("hand drawn map..."));
-    chooseMap->insertSeparator(chooseMap->count()); // separator between generators and missions
-
-    chooseMap->insertSeparator(chooseMap->count()); // separator between generators and missions
-
-    int missionindex = chooseMap->count();
-    numMissions = 0;
-    QFile mapLuaFile;
-    QFile mapCfgFile;
-    for (int i = 0; i < mapList->size(); ++i)
-    {
-        QString map = (*mapList)[i];
-        mapCfgFile.setFileName(
-            QString("%1/Data/Maps/%2/map.cfg")
-            .arg(cfgdir->absolutePath())
-            .arg(map));
-        if (mapCfgFile.exists())
-        {
-            mapLuaFile.setFileName(
-                QString("%1/Data/Maps/%2/map.lua")
-                .arg(cfgdir->absolutePath())
-                .arg(map));
-        }
-        else
-        {
-            mapCfgFile.setFileName(
-                QString("%1/Maps/%2/map.cfg")
-                .arg(datadir->absolutePath())
-                .arg(map));
-            mapLuaFile.setFileName(
-                QString("%1/Maps/%2/map.lua")
-                .arg(datadir->absolutePath())
-                .arg(map));
-        }
+    m_mapModel = DataManager::instance().mapModel();
+    chooseMap->setEditable(false);
+    chooseMap->setModel(m_mapModel);
 
-        if (mapCfgFile.open(QFile::ReadOnly))
-        {
-            QString theme;
-            quint32 limit = 0;
-            QString scheme;
-            QString weapons;
-            QList<QVariant> mapInfo;
-            bool isMission = mapLuaFile.exists();
-
-            QTextStream input(&mapCfgFile);
-            input >> theme;
-            input >> limit;
-            input >> scheme;
-            input >> weapons;
-            mapInfo.push_back(map);
-            mapInfo.push_back(theme);
-            if (limit)
-                mapInfo.push_back(limit);
-            else
-                mapInfo.push_back(18);
-
-
-            mapInfo.push_back(isMission);
+    // update model views after model changes (to e.g. re-adjust separators)
+    connect(&DataManager::instance(), SIGNAL(updated()), this, SLOT(updateModelViews()));
 
-            if (scheme.isEmpty())
-                scheme = "locked";
-            scheme.replace("_", " ");
-
-            if (weapons.isEmpty())
-                weapons = "locked";
-            weapons.replace("_", " ");
-
-            mapInfo.push_back(scheme);
-            mapInfo.push_back(weapons);
-
-            if(isMission)
-            {
-                chooseMap->insertItem(missionindex++,
-// FIXME - need real icons. Disabling until then
-//QIcon(":/res/mapMission.png"),
-                                      QComboBox::tr("Mission") + ": " + map, mapInfo);
-                numMissions++;
-            }
-            else
-                chooseMap->addItem(
-// FIXME - need real icons. Disabling until then
-//QIcon(":/res/mapCustom.png"),
-                    map, mapInfo);
-            mapCfgFile.close();
-        }
-    }
-    chooseMap->insertSeparator(missionindex); // separator between missions and maps
-
-    connect(chooseMap, SIGNAL(activated(int)), this, SLOT(mapChanged(int)));
     mapLayout->addWidget(chooseMap, 1, 1);
 
     QLabel * lblMap = new QLabel(tr("Map"), mapWidget);
@@ -208,14 +117,16 @@
 
     //gbThemes->setStyleSheet("padding: 0px"); // doesn't work - stylesheet is set with icon
     mapLayout->addWidget(gbThemes, 0, 2, 3, 1);
-
+    // disallow row to be collapsed (so it can't get ignored when Qt applies rowSpan of gbThemes)
+    mapLayout->setRowMinimumHeight(2, 13);
     QVBoxLayout * gbTLayout = new QVBoxLayout(gbThemes);
     gbTLayout->setContentsMargins(0, 0, 0 ,0);
     gbTLayout->setSpacing(0);
     lvThemes = new QListView(mapWidget);
     lvThemes->setMinimumHeight(30);
     lvThemes->setFixedWidth(140);
-    lvThemes->setModel(themesModel);
+    m_themeModel = DataManager::instance().themeModel();
+    lvThemes->setModel(m_themeModel);
     lvThemes->setIconSize(QSize(16, 16));
     lvThemes->setEditTriggers(QListView::NoEditTriggers);
 
@@ -264,6 +175,12 @@
 
     setRandomSeed();
     setRandomTheme();
+
+    chooseMap->setCurrentIndex(0);
+    mapChanged(0);
+    connect(chooseMap, SIGNAL(currentIndexChanged(int)), this, SLOT(mapChanged(int)));
+
+    updateModelViews();
 }
 
 void HWMapContainer::setImage(const QImage newImage)
@@ -294,9 +211,13 @@
 
 void HWMapContainer::mapChanged(int index)
 {
-    switch(index)
+    Q_ASSERT(chooseMap->itemData(index, Qt::UserRole + 1).canConvert<MapModel::MapInfo>());
+    m_mapInfo = chooseMap->itemData(index, Qt::UserRole + 1).value<MapModel::MapInfo>();
+    m_curMap = chooseMap->currentText();
+
+    switch(m_mapInfo.type)
     {
-        case MAPGEN_REGULAR:
+        case MapModel::GeneratedMap:
             mapgen = MAPGEN_REGULAR;
             updatePreview();
             gbThemes->show();
@@ -304,10 +225,8 @@
             cbTemplateFilter->show();
             maze_size_label->hide();
             cbMazeSize->hide();
-            emit mapChanged("+rnd+");
-            emit themeChanged(chooseMap->itemData(index).toList()[1].toString());
             break;
-        case MAPGEN_MAZE:
+        case MapModel::GeneratedMaze:
             mapgen = MAPGEN_MAZE;
             updatePreview();
             gbThemes->show();
@@ -315,10 +234,8 @@
             cbTemplateFilter->hide();
             maze_size_label->show();
             cbMazeSize->show();
-            emit mapChanged("+maze+");
-            emit themeChanged(chooseMap->itemData(index).toList()[1].toString());
             break;
-        case MAPGEN_DRAWN:
+        case MapModel::HandDrawnMap:
             mapgen = MAPGEN_DRAWN;
             updatePreview();
             gbThemes->show();
@@ -326,8 +243,6 @@
             cbTemplateFilter->hide();
             maze_size_label->hide();
             cbMazeSize->hide();
-            emit mapChanged("+drawn+");
-            emit themeChanged(chooseMap->itemData(index).toList()[1].toString());
             break;
         default:
             mapgen = MAPGEN_MAP;
@@ -337,9 +252,16 @@
             cbTemplateFilter->hide();
             maze_size_label->hide();
             cbMazeSize->hide();
-            emit mapChanged(chooseMap->itemData(index).toList()[0].toString());
+            m_theme = m_mapInfo.theme;
     }
 
+    // the map has no pre-defined theme, so let's use the selected one
+    if (m_mapInfo.theme.isEmpty())
+    {
+        m_theme = lvThemes->currentIndex().data().toString();
+        emit themeChanged(m_theme);
+    }
+    emit mapChanged(m_mapInfo.name);
     emit mapgenChanged(mapgen);
 }
 
@@ -385,20 +307,10 @@
 
 void HWMapContainer::themeSelected(const QModelIndex & current, const QModelIndex &)
 {
-    QString theme = current.data().toString();
-    QList<QVariant> mapInfo;
-    mapInfo.push_back(QString("+rnd+"));
-    mapInfo.push_back(theme);
-    mapInfo.push_back(18);
-    mapInfo.push_back(false);
-    chooseMap->setItemData(0, mapInfo);
-    mapInfo[0] = QString("+maze+");
-    chooseMap->setItemData(1, mapInfo);
-    mapInfo[0] = QString("+drawn+");
-    chooseMap->setItemData(2, mapInfo);
+    m_theme = current.data().toString();
 
     gbThemes->setIcon(qVariantValue<QIcon>(current.data(Qt::UserRole)));
-    emit themeChanged(theme);
+    emit themeChanged(m_theme);
 }
 
 QString HWMapContainer::getCurrentSeed() const
@@ -409,18 +321,17 @@
 QString HWMapContainer::getCurrentMap() const
 {
     if(chooseMap->currentIndex() < MAPGEN_MAP) return QString();
-    return chooseMap->itemData(chooseMap->currentIndex()).toList()[0].toString();
+    return(m_mapInfo.name);
 }
 
 QString HWMapContainer::getCurrentTheme() const
 {
-    return chooseMap->itemData(chooseMap->currentIndex()).toList()[1].toString();
+    return(m_theme);
 }
 
 bool HWMapContainer::getCurrentIsMission() const
 {
-    if(!chooseMap->currentIndex()) return false;
-    return chooseMap->itemData(chooseMap->currentIndex()).toList()[3].toBool();
+    return(m_mapInfo.type == MapModel::MissionMap);
 }
 
 int HWMapContainer::getCurrentHHLimit() const
@@ -430,12 +341,12 @@
 
 QString HWMapContainer::getCurrentScheme() const
 {
-    return chooseMap->itemData(chooseMap->currentIndex()).toList()[4].toString();
+    return(m_mapInfo.scheme);
 }
 
 QString HWMapContainer::getCurrentWeapons() const
 {
-    return chooseMap->itemData(chooseMap->currentIndex()).toList()[5].toString();
+    return(m_mapInfo.weapons);
 }
 
 quint32 HWMapContainer::getTemplateFilter() const
@@ -459,21 +370,15 @@
 void HWMapContainer::setSeed(const QString & seed)
 {
     intSetSeed(seed);
-    if (chooseMap->currentIndex() < MAPGEN_DRAWN)
+    if ((m_mapInfo.type == MapModel::GeneratedMap) || (m_mapInfo.type == MapModel::GeneratedMaze))
         updatePreview();
 }
 
 void HWMapContainer::intSetMap(const QString & map)
 {
-    int id = 0;
-    for(int i = 0; i < chooseMap->count(); i++)
-        if(!chooseMap->itemData(i).isNull() && chooseMap->itemData(i).toList()[0].toString() == map)
-        {
-            id = i;
-            break;
-        }
+    int id = m_mapModel->indexOf(map);
 
-    if(id > 0)
+    if(id >= 0)
     {
         if (pMap)
         {
@@ -493,7 +398,7 @@
 
 void HWMapContainer::setTheme(const QString & theme)
 {
-    QModelIndexList mdl = themesModel->match(themesModel->index(0), Qt::DisplayRole, theme);
+    QModelIndexList mdl = m_themeModel->match(m_themeModel->index(0), Qt::DisplayRole, theme);
 
     if(mdl.size())
         lvThemes->setCurrentIndex(mdl.at(0));
@@ -501,53 +406,41 @@
 
 void HWMapContainer::setRandomMap()
 {
+    int idx;
+
     setRandomSeed();
-    switch(chooseMap->currentIndex())
+    switch(m_mapInfo.type)
     {
-        case MAPGEN_REGULAR:
-        case MAPGEN_MAZE:
+        case MapModel::GeneratedMap:
+        case MapModel::GeneratedMaze:
             setRandomTheme();
             break;
-        case MAPGEN_DRAWN:
+        case MapModel::HandDrawnMap:
             emit drawMapRequested();
             break;
-        default:
-            if(chooseMap->currentIndex() <= numMissions + MAPGEN_MAP + 1)
-                setRandomMission();
-            else
-                setRandomStatic();
+        case MapModel::MissionMap:
+        case MapModel::StaticMap:
+            // get random map of same type
+            idx = m_mapModel->randomMap(m_mapInfo.type);
+            chooseMap->setCurrentIndex(idx);
             break;
+        case MapModel::Invalid:
+            Q_ASSERT(false);
     }
 }
 
-void HWMapContainer::setRandomStatic()
-{
-    int i = MAPGEN_MAP + 3 + numMissions + rand() % (chooseMap->count() - MAPGEN_MAP - 3 - numMissions);
-    chooseMap->setCurrentIndex(i);
-    mapChanged(i);
-}
-
-void HWMapContainer::setRandomMission()
-{
-    int i = MAPGEN_MAP + 2 + rand() % numMissions;
-    chooseMap->setCurrentIndex(i);
-    mapChanged(i);
-}
 
 void HWMapContainer::setRandomSeed()
 {
-    m_seed = QUuid::createUuid().toString();
-    seedEdit->setText(m_seed);
+    setSeed(QUuid::createUuid().toString());
     emit seedChanged(m_seed);
-    if (chooseMap->currentIndex() < MAPGEN_MAP)
-        updatePreview();
 }
 
 void HWMapContainer::setRandomTheme()
 {
-    if(!themesModel->rowCount()) return;
-    quint32 themeNum = rand() % themesModel->rowCount();
-    lvThemes->setCurrentIndex(themesModel->index(themeNum));
+    if(!m_themeModel->rowCount()) return;
+    quint32 themeNum = rand() % m_themeModel->rowCount();
+    lvThemes->setCurrentIndex(m_themeModel->index(themeNum));
 }
 
 void HWMapContainer::intSetTemplateFilter(int filter)
@@ -644,31 +537,31 @@
 
 void HWMapContainer::updatePreview()
 {
-    int curIndex = chooseMap->currentIndex();
-
-    switch(curIndex)
+    switch(m_mapInfo.type)
     {
-        case MAPGEN_REGULAR:
+        case MapModel::GeneratedMap:
             askForGeneratedPreview();
             break;
-        case MAPGEN_MAZE:
+        case MapModel::GeneratedMaze:
             askForGeneratedPreview();
             break;
-        case MAPGEN_DRAWN:
+        case MapModel::HandDrawnMap:
             askForGeneratedPreview();
             break;
         default:
             QPixmap mapImage;
-            QFile tmpfile;
-            tmpfile.setFileName(cfgdir->absolutePath() + "/Data/Maps/" + chooseMap->itemData(curIndex).toList()[0].toString() + "/preview.png");
-            if (!tmpfile.exists()) tmpfile.setFileName(datadir->absolutePath() + "/Maps/" + chooseMap->itemData(curIndex).toList()[0].toString() + "/preview.png");
-            if(!mapImage.load(QFileInfo(tmpfile).absoluteFilePath()))
+            bool success = mapImage.load(
+                DataManager::instance().findFileForRead(
+                    "Maps/" + m_mapInfo.name + "/preview.png")
+            );
+
+            if(!success)
             {
                 imageButt->setIcon(QIcon());
                 return;
             }
 
-            hhLimit = chooseMap->itemData(curIndex).toList()[2].toInt();
+            hhLimit = m_mapInfo.limit;
             addInfoToPreview(mapImage);
     }
 }
@@ -683,3 +576,29 @@
 
     updatePreview();
 }
+
+
+void HWMapContainer::updateModelViews()
+{
+    // restore theme selection
+    // do this before map selection restore, because map may overwrite theme
+    if (!m_theme.isEmpty())
+    {
+        QModelIndexList mdl = m_themeModel->match(m_themeModel->index(0), Qt::DisplayRole, m_theme);
+        if (mdl.size() > 0)
+            lvThemes->setCurrentIndex(mdl.at(0));
+        else
+            setRandomTheme();
+    }
+
+    // restore map selection
+    if (!m_curMap.isEmpty())
+    {
+        int idx = chooseMap->findText(m_curMap);
+        if (idx >= 0)
+            chooseMap->setCurrentIndex(idx);
+        else
+            chooseMap->setCurrentIndex(0);
+    }
+
+}
--- a/QTfrontend/ui/widget/mapContainer.h	Sun Apr 01 15:23:34 2012 +0200
+++ b/QTfrontend/ui/widget/mapContainer.h	Wed May 02 23:53:45 2012 +0200
@@ -1,7 +1,7 @@
 /*
  * Hedgewars, a free turn based strategy game
  * Copyright (c) 2006-2007 Igor Ulyanov <iulyanov@gmail.com>
- * Copyright (c) 2007-2012 Andrey Korotaev <unC0Rr@gmail.com>
+ * Copyright (c) 2004-2012 Andrey Korotaev <unC0Rr@gmail.com>
  *
  * This program is free software; you can redistribute it and/or modify
  * it under the terms of the GNU General Public License as published by
@@ -27,12 +27,15 @@
 #include <QByteArray>
 #include <QLineEdit>
 
+#include "DataManager.h"
+
 #include "hwmap.h"
 #include "drawmapscene.h"
 
 class QPushButton;
 class IconedGroupBox;
 class QListView;
+class SeparatorPainter;
 
 class MapFileErrorException
 {
@@ -69,6 +72,7 @@
         void setMazeSize(int size);
         void setDrawnMapData(const QByteArray & ar);
         void setAllMapParameters(const QString & map, MapGenerator m, int mazesize, const QString & seed, int tmpl);
+        void updateModelViews();
 
     signals:
         void seedChanged(const QString & seed);
@@ -87,8 +91,6 @@
         void setRandomSeed();
         void setRandomTheme();
         void setRandomMap();
-        void setRandomStatic();
-        void setRandomMission();
         void themeSelected(const QModelIndex & current, const QModelIndex &);
         void addInfoToPreview(QPixmap image);
         void seedEdited();
@@ -100,8 +102,10 @@
         QGridLayout mainLayout;
         QPushButton* imageButt;
         QComboBox* chooseMap;
+        MapModel * m_mapModel;
         IconedGroupBox* gbThemes;
         QListView* lvThemes;
+        ThemeModel * m_themeModel;
         HWMap* pMap;
         QString m_seed;
         QPushButton* seedSet;
@@ -114,7 +118,6 @@
         QLabel *maze_size_label;
         QComboBox *cbMazeSize;
         MapGenerator mapgen;
-        int numMissions;
         DrawMapScene drawMapScene;
 
         void intSetSeed(const QString & seed);
@@ -123,6 +126,10 @@
         void intSetTemplateFilter(int);
         void intSetMazeSize(int size);
         void updatePreview();
+
+        MapModel::MapInfo m_mapInfo;
+        QString m_theme;
+        QString m_curMap;
 };
 
 #endif // _HWMAP_CONTAINER_INCLUDED
--- a/QTfrontend/ui/widget/qpushbuttonwithsound.cpp	Sun Apr 01 15:23:34 2012 +0200
+++ b/QTfrontend/ui/widget/qpushbuttonwithsound.cpp	Wed May 02 23:53:45 2012 +0200
@@ -2,7 +2,7 @@
 #include <QDir>
 
 #include "qpushbuttonwithsound.h"
-#include "HWDataManager.h"
+#include "DataManager.h"
 #include "SDLInteraction.h"
 #include "hwform.h"
 #include "gameuiconfig.h"
@@ -19,7 +19,7 @@
     if ( !isSoundEnabled || !HWForm::config->isFrontendSoundEnabled())
         return;
 
-    HWDataManager & dataMgr = HWDataManager::instance();
+    DataManager & dataMgr = DataManager::instance();
 
     if (this->isEnabled())
         SDLInteraction::instance().playSoundFile(dataMgr.findFileForRead("Sounds/roperelease.ogg"));
--- a/QTfrontend/ui/widget/selectWeapon.cpp	Sun Apr 01 15:23:34 2012 +0200
+++ b/QTfrontend/ui/widget/selectWeapon.cpp	Wed May 02 23:53:45 2012 +0200
@@ -1,7 +1,7 @@
 /*
  * Hedgewars, a free turn based strategy game
  * Copyright (c) 2006-2008 Igor Ulyanov <iulyanov@gmail.com>
- * Copyright (c) 2008-2012 Andrey Korotaev <unC0Rr@gmail.com>
+ * Copyright (c) 2004-2012 Andrey Korotaev <unC0Rr@gmail.com>
  *
  * This program is free software; you can redistribute it and/or modify
  * it under the terms of the GNU General Public License as published by
--- a/QTfrontend/ui/widget/selectWeapon.h	Sun Apr 01 15:23:34 2012 +0200
+++ b/QTfrontend/ui/widget/selectWeapon.h	Wed May 02 23:53:45 2012 +0200
@@ -1,7 +1,7 @@
 /*
  * Hedgewars, a free turn based strategy game
  * Copyright (c) 2006-2008 Igor Ulyanov <iulyanov@gmail.com>
- * Copyright (c) 2008-2012 Andrey Korotaev <unC0Rr@gmail.com>
+ * Copyright (c) 2004-2012 Andrey Korotaev <unC0Rr@gmail.com>
  *
  * This program is free software; you can redistribute it and/or modify
  * it under the terms of the GNU General Public License as published by
--- a/QTfrontend/ui/widget/teamselect.cpp	Sun Apr 01 15:23:34 2012 +0200
+++ b/QTfrontend/ui/widget/teamselect.cpp	Wed May 02 23:53:45 2012 +0200
@@ -1,7 +1,7 @@
 /*
  * Hedgewars, a free turn based strategy game
  * Copyright (c) 2006-2007 Igor Ulyanov <iulyanov@gmail.com>
- * Copyright (c) 2007-2012 Andrey Korotaev <unC0Rr@gmail.com>
+ * Copyright (c) 2004-2012 Andrey Korotaev <unC0Rr@gmail.com>
  *
  * This program is free software; you can redistribute it and/or modify
  * it under the terms of the GNU General Public License as published by
--- a/QTfrontend/ui/widget/teamselect.h	Sun Apr 01 15:23:34 2012 +0200
+++ b/QTfrontend/ui/widget/teamselect.h	Wed May 02 23:53:45 2012 +0200
@@ -1,7 +1,7 @@
 /*
  * Hedgewars, a free turn based strategy game
  * Copyright (c) 2006-2007 Igor Ulyanov <iulyanov@gmail.com>
- * Copyright (c) 2007-2012 Andrey Korotaev <unC0Rr@gmail.com>
+ * Copyright (c) 2004-2012 Andrey Korotaev <unC0Rr@gmail.com>
  *
  * This program is free software; you can redistribute it and/or modify
  * it under the terms of the GNU General Public License as published by
--- a/QTfrontend/ui/widget/teamselhelper.cpp	Sun Apr 01 15:23:34 2012 +0200
+++ b/QTfrontend/ui/widget/teamselhelper.cpp	Wed May 02 23:53:45 2012 +0200
@@ -1,7 +1,7 @@
 /*
  * Hedgewars, a free turn based strategy game
  * Copyright (c) 2006-2007 Igor Ulyanov <iulyanov@gmail.com>
- * Copyright (c) 2007-2012 Andrey Korotaev <unC0Rr@gmail.com>
+ * Copyright (c) 2004-2012 Andrey Korotaev <unC0Rr@gmail.com>
  *
  * This program is free software; you can redistribute it and/or modify
  * it under the terms of the GNU General Public License as published by
@@ -32,10 +32,11 @@
     emit teamActivated(text());
 }
 
-TeamShowWidget::TeamShowWidget(HWTeam team, bool isPlaying, QWidget * parent) :
+TeamShowWidget::TeamShowWidget(HWTeam team, bool isPlaying, FrameTeams * parent) :
     QWidget(parent), mainLayout(this), m_team(team), m_isPlaying(isPlaying), phhoger(0),
     colorButt(0)
 {
+    m_parentFrameTeams = parent;
     QPalette newPalette = palette();
     newPalette.setColor(QPalette::Window, QColor(0x00, 0x00, 0x00));
     setPalette(newPalette);
@@ -129,43 +130,31 @@
 
 void TeamShowWidget::incrementTeamColor()
 {
-    FrameTeams* pOurFrameTeams=dynamic_cast<FrameTeams*>(parentWidget());
-    QColor color;
-    if(++pOurFrameTeams->currentColor==pOurFrameTeams->availableColors.end())
-        pOurFrameTeams->currentColor=pOurFrameTeams->availableColors.begin();
-    color=*pOurFrameTeams->currentColor;
-
-    changeTeamColor(color);
+    changeTeamColor(m_parentFrameTeams->getNextColor());
 }
 void TeamShowWidget::decrementTeamColor()
 {
-    FrameTeams* pOurFrameTeams=dynamic_cast<FrameTeams*>(parentWidget());
-    QColor color;
-    if(pOurFrameTeams->currentColor==pOurFrameTeams->availableColors.begin())
-        pOurFrameTeams->currentColor=pOurFrameTeams->availableColors.end()-1;
-    else --pOurFrameTeams->currentColor;
-    color=*pOurFrameTeams->currentColor;
+    const QList<QColor> & availColors = m_parentFrameTeams->availableColors;
+    int idx = availColors.indexOf(m_parentFrameTeams->currentColor);
+
+    idx--;
 
-    changeTeamColor(color);
+    if (idx < 0)
+        idx = availColors.size() - 1;
+
+    changeTeamColor(availColors.at(idx));
 }
 
 void TeamShowWidget::changeTeamColor(QColor color)
 {
-    FrameTeams* pOurFrameTeams=dynamic_cast<FrameTeams*>(parentWidget());
-    // set according color iterator
-    pOurFrameTeams->currentColor=std::find(pOurFrameTeams->availableColors.begin(),
-                                           pOurFrameTeams->availableColors.end(), color);
-    if(pOurFrameTeams->currentColor==pOurFrameTeams->availableColors.end())
-    {
-        // error condition
-        pOurFrameTeams->currentColor=pOurFrameTeams->availableColors.begin();
-    }
+    QColor & curColor = m_parentFrameTeams->currentColor;
+    curColor = color;
 
     colorButt->setStyleSheet(QString("QPushButton{"
                                      "background-color: %1;"
                                      "border-width: 1px;"
                                      "border-radius: 2px;"
-                                     "}").arg(pOurFrameTeams->currentColor->name()));
+                                     "}").arg(curColor.name()));
 
     m_team.setColor(color);
     emit teamColorChanged(m_team);
--- a/QTfrontend/ui/widget/teamselhelper.h	Sun Apr 01 15:23:34 2012 +0200
+++ b/QTfrontend/ui/widget/teamselhelper.h	Wed May 02 23:53:45 2012 +0200
@@ -1,7 +1,7 @@
 /*
  * Hedgewars, a free turn based strategy game
  * Copyright (c) 2006-2007 Igor Ulyanov <iulyanov@gmail.com>
- * Copyright (c) 2007-2012 Andrey Korotaev <unC0Rr@gmail.com>
+ * Copyright (c) 2004-2012 Andrey Korotaev <unC0Rr@gmail.com>
  *
  * This program is free software; you can redistribute it and/or modify
  * it under the terms of the GNU General Public License as published by
@@ -57,7 +57,7 @@
         void activateTeam();
 
     public:
-        TeamShowWidget(HWTeam team, bool isPlaying, QWidget * parent);
+        TeamShowWidget(HWTeam team, bool isPlaying, FrameTeams * parent);
         void setPlaying(bool isPlaying);
         void setHHNum(unsigned int num);
         void setInteractivity(bool interactive);
@@ -71,6 +71,7 @@
         CHedgehogerWidget* phhoger;
         QPushButton* colorButt;
         QPushButton* butt;
+        FrameTeams * m_parentFrameTeams;
 // QPushButton* bText;
 
     signals:
--- a/QTfrontend/ui/widget/togglebutton.cpp	Sun Apr 01 15:23:34 2012 +0200
+++ b/QTfrontend/ui/widget/togglebutton.cpp	Wed May 02 23:53:45 2012 +0200
@@ -1,7 +1,7 @@
 /*
  * Hedgewars, a free turn based strategy game
  * Copyright (c) 2009 Kristian Lehmann <email@thexception.net>
- * Copyright (c) 2009-2012 Andrey Korotaev <unC0Rr@gmail.com>
+ * Copyright (c) 2004-2012 Andrey Korotaev <unC0Rr@gmail.com>
  *
  * This program is free software; you can redistribute it and/or modify
  * it under the terms of the GNU General Public License as published by
--- a/QTfrontend/ui/widget/togglebutton.h	Sun Apr 01 15:23:34 2012 +0200
+++ b/QTfrontend/ui/widget/togglebutton.h	Wed May 02 23:53:45 2012 +0200
@@ -1,7 +1,7 @@
 /*
  * Hedgewars, a free turn based strategy game
  * Copyright (c) 2009 Kristian Lehmann <email@thexception.net>
- * Copyright (c) 2009-2012 Andrey Korotaev <unC0Rr@gmail.com>
+ * Copyright (c) 2004-2012 Andrey Korotaev <unC0Rr@gmail.com>
  *
  * This program is free software; you can redistribute it and/or modify
  * it under the terms of the GNU General Public License as published by
--- a/QTfrontend/ui/widget/vertScrollArea.cpp	Sun Apr 01 15:23:34 2012 +0200
+++ b/QTfrontend/ui/widget/vertScrollArea.cpp	Wed May 02 23:53:45 2012 +0200
@@ -1,7 +1,7 @@
 /*
  * Hedgewars, a free turn based strategy game
  * Copyright (c) 2006 Igor Ulyanov <iulyanov@gmail.com>
- * Copyright (c) 2006-2012 Andrey Korotaev <unC0Rr@gmail.com>
+ * Copyright (c) 2004-2012 Andrey Korotaev <unC0Rr@gmail.com>
  *
  * This program is free software; you can redistribute it and/or modify
  * it under the terms of the GNU General Public License as published by
--- a/QTfrontend/ui/widget/vertScrollArea.h	Sun Apr 01 15:23:34 2012 +0200
+++ b/QTfrontend/ui/widget/vertScrollArea.h	Wed May 02 23:53:45 2012 +0200
@@ -1,7 +1,7 @@
 /*
  * Hedgewars, a free turn based strategy game
  * Copyright (c) 2006 Igor Ulyanov <iulyanov@gmail.com>
- * Copyright (c) 2006-2012 Andrey Korotaev <unC0Rr@gmail.com>
+ * Copyright (c) 2004-2012 Andrey Korotaev <unC0Rr@gmail.com>
  *
  * This program is free software; you can redistribute it and/or modify
  * it under the terms of the GNU General Public License as published by
--- a/QTfrontend/ui/widget/weaponItem.cpp	Sun Apr 01 15:23:34 2012 +0200
+++ b/QTfrontend/ui/widget/weaponItem.cpp	Wed May 02 23:53:45 2012 +0200
@@ -1,7 +1,7 @@
 /*
  * Hedgewars, a free turn based strategy game
  * Copyright (c) 2006-2008 Igor Ulyanov <iulyanov@gmail.com>
- * Copyright (c) 2008-2012 Andrey Korotaev <unC0Rr@gmail.com>
+ * Copyright (c) 2004-2012 Andrey Korotaev <unC0Rr@gmail.com>
  *
  * This program is free software; you can redistribute it and/or modify
  * it under the terms of the GNU General Public License as published by
--- a/QTfrontend/ui/widget/weaponItem.h	Sun Apr 01 15:23:34 2012 +0200
+++ b/QTfrontend/ui/widget/weaponItem.h	Wed May 02 23:53:45 2012 +0200
@@ -1,7 +1,7 @@
 /*
  * Hedgewars, a free turn based strategy game
  * Copyright (c) 2006-2008 Igor Ulyanov <iulyanov@gmail.com>
- * Copyright (c) 2008-2012 Andrey Korotaev <unC0Rr@gmail.com>
+ * Copyright (c) 2004-2012 Andrey Korotaev <unC0Rr@gmail.com>
  *
  * This program is free software; you can redistribute it and/or modify
  * it under the terms of the GNU General Public License as published by
--- a/QTfrontend/ui_hwform.cpp	Sun Apr 01 15:23:34 2012 +0200
+++ b/QTfrontend/ui_hwform.cpp	Wed May 02 23:53:45 2012 +0200
@@ -1,6 +1,6 @@
 /*
  * Hedgewars, a free turn based strategy game
- * Copyright (c) 2006-2012 Andrey Korotaev <unC0Rr@gmail.com>
+ * Copyright (c) 2004-2012 Andrey Korotaev <unC0Rr@gmail.com>
  *
  * This program is free software; you can redistribute it and/or modify
  * it under the terms of the GNU General Public License as published by
--- a/QTfrontend/ui_hwform.h	Sun Apr 01 15:23:34 2012 +0200
+++ b/QTfrontend/ui_hwform.h	Wed May 02 23:53:45 2012 +0200
@@ -1,6 +1,6 @@
 /*
  * Hedgewars, a free turn based strategy game
- * Copyright (c) 2006-2012 Andrey Korotaev <unC0Rr@gmail.com>
+ * Copyright (c) 2004-2012 Andrey Korotaev <unC0Rr@gmail.com>
  *
  * This program is free software; you can redistribute it and/or modify
  * it under the terms of the GNU General Public License as published by
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/QTfrontend/util/DataManager.cpp	Wed May 02 23:53:45 2012 +0200
@@ -0,0 +1,164 @@
+/*
+ * Hedgewars, a free turn based strategy game
+ * Copyright (c) 2004-2012 Andrey Korotaev <unC0Rr@gmail.com>
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; version 2 of the License
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA
+ */
+
+/**
+ * @file
+ * @brief DataManager class implementation
+ */
+
+#include <QMap>
+#include <QStringList>
+
+#include <QFileInfo>
+
+#include "hwconsts.h"
+
+#include "DataManager.h"
+
+
+DataManager::DataManager()
+{
+    m_userData = new QDir(cfgdir->absolutePath());
+    if (!m_userData->cd("Data"))
+        m_userData = NULL;
+
+    m_defaultData = new QDir(datadir->absolutePath());
+
+    m_hatModel = NULL;
+    m_mapModel = NULL;
+    m_themeModel = NULL;
+}
+
+
+DataManager & DataManager::instance()
+{
+    static DataManager instance;
+    return instance;
+}
+
+
+QStringList DataManager::entryList(
+    const QString & subDirectory,
+    QDir::Filters filters,
+    const QStringList & nameFilters
+) const
+{
+    QStringList result;
+
+    if (m_userData != NULL)
+    {
+        QDir tmpDir(*m_userData);
+        if (tmpDir.cd(subDirectory))
+            result.append(tmpDir.entryList(nameFilters, filters));
+    }
+
+    QDir tmpDir(*m_defaultData);
+    if (tmpDir.cd(subDirectory))
+        result.append(tmpDir.entryList(nameFilters, filters));
+
+    result.removeDuplicates();
+
+    // sort case-insensitive
+    QMap<QString, QString> sortedFileNames;
+    foreach ( QString fn, result)
+    {
+        sortedFileNames.insert(fn.toLower(), fn);
+    }
+    result = sortedFileNames.values();
+
+    return result;
+}
+
+
+QString DataManager::findFileForRead(
+    const QString & relativeDataFilePath) const
+{
+    QString path;
+
+    if (m_userData != NULL)
+        path = m_userData->absolutePath()+"/"+relativeDataFilePath;
+
+    if ((!path.isEmpty()) && (!QFile::exists(path)))
+        path = m_defaultData->absolutePath()+"/"+relativeDataFilePath;
+
+    return path;
+}
+
+
+QString DataManager::findFileForWrite(
+    const QString & relativeDataFilePath) const
+{
+    if (m_userData != NULL)
+    {
+        QString path = m_userData->absolutePath()+"/"+relativeDataFilePath;
+
+        // create folders if needed
+        QDir tmp;
+        tmp.mkpath(QFileInfo(path).absolutePath());
+
+        return path;
+    }
+
+
+    return "";
+}
+
+GameStyleModel * DataManager::gameStyleModel()
+{
+    if (m_gameStyleModel == NULL) {
+        m_gameStyleModel = new GameStyleModel();
+        m_gameStyleModel->loadGameStyles();
+    }
+    return m_gameStyleModel;
+}
+
+HatModel * DataManager::hatModel()
+{
+    if (m_hatModel == NULL) {
+        m_hatModel = new HatModel();
+        m_hatModel->loadHats();
+    }
+    return m_hatModel;
+}
+
+MapModel * DataManager::mapModel()
+{
+    if (m_mapModel == NULL) {
+        m_mapModel = new MapModel();
+        m_mapModel->loadMaps();
+    }
+    return m_mapModel;
+}
+
+ThemeModel * DataManager::themeModel()
+{
+    if (m_themeModel == NULL) {
+        m_themeModel = new ThemeModel();
+        m_themeModel->loadThemes();
+    }
+    return m_themeModel;
+}
+
+void DataManager::reload()
+{
+    m_gameStyleModel->loadGameStyles();
+    m_hatModel->loadHats();
+    m_mapModel->loadMaps();
+    m_themeModel->loadThemes();
+    emit updated();
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/QTfrontend/util/DataManager.h	Wed May 02 23:53:45 2012 +0200
@@ -0,0 +1,168 @@
+/*
+ * Hedgewars, a free turn based strategy game
+ * Copyright (c) 2004-2012 Andrey Korotaev <unC0Rr@gmail.com>
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; version 2 of the License
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA
+ */
+
+/**
+ * @file
+ * @brief DataManager class definition
+ */
+
+#ifndef HEDGEWARS_DATAMANAGER_H
+#define HEDGEWARS_DATAMANAGER_H
+
+#include <QDir>
+#include <QFile>
+
+#include <QStringList>
+
+#include "GameStyleModel.h"
+#include "HatModel.h"
+#include "MapModel.h"
+#include "ThemeModel.h"
+
+class QDir;
+class QFile;
+class QStringList;
+class GameStyleModel;
+class HatModel;
+class MapModel;
+class ThemeModel;
+
+/**
+ * @brief Offers access to the data files of hedgewars.
+ *
+ * @see <a href="http://en.wikipedia.org/wiki/Singleton_pattern">singleton pattern</a>
+ *
+ * @author sheepluva
+ * @since 0.9.17
+ */
+class DataManager: public QObject
+{
+        Q_OBJECT
+
+    public:
+        /**
+         * @brief Returns reference to the <i>singleton</i> instance of this class.
+         *
+         * @see <a href="http://en.wikipedia.org/wiki/Singleton_pattern">singleton pattern</a>
+         *
+         * @return reference to the instance.
+         */
+        static DataManager & instance();
+
+        /**
+         * @brief Returns a sorted list of data directory entries.
+         *
+         * @param subDirectory sub-directory to search.
+         * @param filters filters for entry type.
+         * @param nameFilters filters by name patterns.
+         * @return a sorted list of matches in the subDirectory of data directory.
+         */
+        QStringList entryList(const QString & subDirectory,
+                              QDir::Filters filters = QDir::NoFilter,
+                              const QStringList & nameFilters = QStringList("*")
+                             ) const;
+
+        /**
+         * @brief Returns the path for the desires data file.
+         *
+         * Use this method if you want to read an existing data file.
+         *
+         * @param relativeDataFilePath relative path of the data file.
+         * @return real path to the file.
+         */
+        QString findFileForRead(const QString & relativeDataFilePath) const;
+
+
+        /**
+         * @brief Returns the path for the data file that is to be written.
+         *
+         * Use this method if you want to create or write into a data file.
+         *
+         * @param relativeDataFilePath relative path of data file write path.
+         * @return destination of path data file.
+         */
+        QString findFileForWrite(const QString & relativeDataFilePath) const;
+
+
+        /**
+         * @brief Returns pointer to a model of available game styles.
+         *
+         * The model is updated automatically on data reload.
+         *
+         * @return game style model pointer.
+         */
+        GameStyleModel * gameStyleModel();
+
+        /**
+         * @brief Returns pointer to a model of available hats.
+         *
+         * The model is updated automatically on data reload.
+         *
+         * @return hat model pointer.
+         */
+        HatModel * hatModel();
+
+        /**
+         * @brief Returns pointer to a model of available maps.
+         *
+         * The model is updated automatically on data reload.
+         *
+         * @return map model pointer.
+         */
+        MapModel * mapModel();
+
+        /**
+         * @brief Returns pointer to a model of available themes.
+         *
+         * The model is updated automatically on data reload.
+         *
+         * @return theme model pointer.
+         */
+        ThemeModel * themeModel();
+
+    public slots:
+        /// Reloads data from storage.
+        void reload();
+
+
+    signals:
+        /// This signal is emitted after the data has been updated.
+        void updated();
+
+
+    private:
+        /**
+         * @brief Class constructor of the <i>singleton</i>.
+         *
+         * Not to be used from outside the class,
+         * use the static {@link DataManager::instance()} instead.
+         *
+         * @see <a href="http://en.wikipedia.org/wiki/Singleton_pattern">singleton pattern</a>
+         */
+        DataManager();
+
+        QDir * m_defaultData; ///< directory of the installed data
+        QDir * m_userData;    ///< directory of custom data in the user's directory
+
+        GameStyleModel * m_gameStyleModel; ///< game style model instance
+        HatModel * m_hatModel; ///< hat model instance
+        MapModel * m_mapModel; ///< map model instance
+        ThemeModel * m_themeModel; ///< theme model instance
+};
+
+#endif // HEDGEWARS_DATAMANAGER_H
--- a/QTfrontend/util/HWDataManager.cpp	Sun Apr 01 15:23:34 2012 +0200
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,117 +0,0 @@
-/*
- * Hedgewars, a free turn based strategy game
- * Copyright (c) 2006-2007 Igor Ulyanov <iulyanov@gmail.com>
- * Copyright (c) 2007-2012 Andrey Korotaev <unC0Rr@gmail.com>
- *
- * This program is free software; you can redistribute it and/or modify
- * it under the terms of the GNU General Public License as published by
- * the Free Software Foundation; version 2 of the License
- *
- * This program is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
- * GNU General Public License for more details.
- *
- * You should have received a copy of the GNU General Public License
- * along with this program; if not, write to the Free Software
- * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA
- */
-
-/**
- * @file
- * @brief HWDataManager class implementation
- */
-
-#include <QMap>
-#include <QStringList>
-
-#include <QFileInfo>
-
-#include "hwconsts.h"
-
-#include "HWDataManager.h"
-
-
-HWDataManager::HWDataManager()
-{
-    userData = new QDir(cfgdir->absolutePath());
-    if (!userData->cd("Data"))
-        userData = NULL;
-
-    defaultData = new QDir(datadir->absolutePath());
-}
-
-
-HWDataManager & HWDataManager::instance()
-{
-    static HWDataManager instance;
-    return instance;
-}
-
-
-QStringList HWDataManager::entryList(
-    const QString & subDirectory,
-    QDir::Filters filters,
-    const QStringList & nameFilters
-) const
-{
-    QStringList result;
-
-    if (userData != NULL)
-    {
-        QDir tmpDir(*userData);
-        if (tmpDir.cd(subDirectory))
-            result.append(tmpDir.entryList(nameFilters, filters));
-    }
-
-    QDir tmpDir(*defaultData);
-    if (tmpDir.cd(subDirectory))
-        result.append(tmpDir.entryList(nameFilters, filters));
-
-    result.removeDuplicates();
-
-    // sort case-insensitive
-    QMap<QString, QString> sortedFileNames;
-    foreach ( QString fn, result)
-    {
-        sortedFileNames.insert(fn.toLower(), fn);
-    }
-    result = sortedFileNames.values();
-
-    return result;
-}
-
-
-QString HWDataManager::findFileForRead(
-    const QString & relativeDataFilePath) const
-{
-    QString path;
-
-    if (userData != NULL)
-        path = userData->absolutePath()+"/"+relativeDataFilePath;
-
-    if ((!path.isEmpty()) && (!QFile::exists(path)))
-        path = defaultData->absolutePath()+"/"+relativeDataFilePath;
-
-    return path;
-}
-
-
-QString HWDataManager::findFileForWrite(
-    const QString & relativeDataFilePath) const
-{
-    if (userData != NULL)
-    {
-        QString path = userData->absolutePath()+"/"+relativeDataFilePath;
-
-        // create folders if needed
-        QDir tmp;
-        tmp.mkpath(QFileInfo(path).absolutePath());
-
-        return path;
-    }
-
-
-    return "";
-}
-
--- a/QTfrontend/util/HWDataManager.h	Sun Apr 01 15:23:34 2012 +0200
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,107 +0,0 @@
-/*
- * Hedgewars, a free turn based strategy game
- * Copyright (c) 2006-2007 Igor Ulyanov <iulyanov@gmail.com>
- * Copyright (c) 2007-2012 Andrey Korotaev <unC0Rr@gmail.com>
- *
- * This program is free software; you can redistribute it and/or modify
- * it under the terms of the GNU General Public License as published by
- * the Free Software Foundation; version 2 of the License
- *
- * This program is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
- * GNU General Public License for more details.
- *
- * You should have received a copy of the GNU General Public License
- * along with this program; if not, write to the Free Software
- * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA
- */
-
-/**
- * @file
- * @brief HWDataManager class definition
- */
-
-#ifndef HEDGEWARS_HWDATAMANAGER_H
-#define HEDGEWARS_HWDATAMANAGER_H
-
-#include <QDir>
-#include <QFile>
-
-#include <QStringList>
-
-class QDir;
-class QFile;
-class QStringList;
-
-/**
- * @brief Offers access to the data files of hedgewars.
- *
- * @see <a href="http://en.wikipedia.org/wiki/Singleton_pattern">singleton pattern</a>
- *
- * @author sheepluva
- * @since 0.9.17
- */
-class HWDataManager
-{
-    public:
-        /**
-         * @brief Returns reference to the <i>singleton</i> instance of this class.
-         *
-         * @see <a href="http://en.wikipedia.org/wiki/Singleton_pattern">singleton pattern</a>
-         *
-         * @return reference to the instance.
-         */
-        static HWDataManager & instance();
-
-        /**
-         * @brief Returns a sorted list of data directory entries.
-         *
-         * @param subDirectory sub-directory to search.
-         * @param filters filters for entry type.
-         * @param nameFilters filters by name patterns.
-         * @return a sorted list of matches in the subDirectory of data directory.
-         */
-        QStringList entryList(const QString & subDirectory,
-                              QDir::Filters filters = QDir::NoFilter,
-                              const QStringList & nameFilters = QStringList("*")
-                             ) const;
-
-        /**
-         * @brief Returns the path for the desires data file.
-         *
-         * Use this method if you want to read an existing data file.
-         *
-         * @param relativeDataFilePath relative path of the data file.
-         * @return real path to the file.
-         */
-        QString findFileForRead(const QString & relativeDataFilePath) const;
-
-
-        /**
-         * @brief Returns the path for the data file that is to be written.
-         *
-         * Use this method if you want to create or write into a data file.
-         *
-         * @param relativeDataFilePath relative path of data file write path.
-         * @return destination of path data file.
-         */
-        QString findFileForWrite(const QString & relativeDataFilePath) const;
-
-
-    private:
-        /**
-         * @brief Class constructor of the <i>singleton</i>.
-         *
-         * Not to be used from outside the class,
-         * use the static {@link HWDataManager::instance()} instead.
-         *
-         * @see <a href="http://en.wikipedia.org/wiki/Singleton_pattern">singleton pattern</a>
-         */
-        HWDataManager();
-
-        QDir * defaultData; ///< directory of the installed data
-        QDir * userData;    ///< directory of custom data in the user's directory
-};
-
-#endif // HEDGEWARS_HWDATAMANAGER_H
--- a/QTfrontend/util/SDLInteraction.cpp	Sun Apr 01 15:23:34 2012 +0200
+++ b/QTfrontend/util/SDLInteraction.cpp	Wed May 02 23:53:45 2012 +0200
@@ -1,6 +1,6 @@
 /*
  * Hedgewars, a free turn based strategy game
- * Copyright (c) 2007-2012 Andrey Korotaev <unC0Rr@gmail.com>
+ * Copyright (c) 2004-2012 Andrey Korotaev <unC0Rr@gmail.com>
  *
  * This program is free software; you can redistribute it and/or modify
  * it under the terms of the GNU General Public License as published by
--- a/QTfrontend/util/SDLInteraction.h	Sun Apr 01 15:23:34 2012 +0200
+++ b/QTfrontend/util/SDLInteraction.h	Wed May 02 23:53:45 2012 +0200
@@ -1,6 +1,6 @@
 /*
  * Hedgewars, a free turn based strategy game
- * Copyright (c) 2007-2012 Andrey Korotaev <unC0Rr@gmail.com>
+ * Copyright (c) 2004-2012 Andrey Korotaev <unC0Rr@gmail.com>
  *
  * This program is free software; you can redistribute it and/or modify
  * it under the terms of the GNU General Public License as published by
@@ -43,7 +43,7 @@
          * @brief Class constructor of the <i>singleton</i>.
          *
          * Not to be used from outside the class,
-         * use the static {@link HWDataManager::instance()} instead.
+         * use the static {@link DataManager::instance()} instead.
          *
          * @see <a href="http://en.wikipedia.org/wiki/Singleton_pattern">singleton pattern</a>
          */
--- a/QTfrontend/util/namegen.cpp	Sun Apr 01 15:23:34 2012 +0200
+++ b/QTfrontend/util/namegen.cpp	Wed May 02 23:53:45 2012 +0200
@@ -1,7 +1,7 @@
 /*
  * Hedgewars, a free turn based strategy game
  * Copyright (c) 2009 Martin Minarik <ttsmj@pokec.sk>
- * Copyright (c) 2009-2012 Andrey Korotaev <unC0Rr@gmail.com>
+ * Copyright (c) 2004-2012 Andrey Korotaev <unC0Rr@gmail.com>
  *
  * This program is free software; you can redistribute it and/or modify
  * it under the terms of the GNU General Public License as published by
@@ -23,7 +23,7 @@
 #include <QLineEdit>
 
 #include "hwform.h"
-#include "HWDataManager.h"
+#include "DataManager.h"
 
 #include "namegen.h"
 
@@ -125,7 +125,7 @@
     QStringList list;
 
     // find .txt to load the names from
-    QFile * file = new QFile(HWDataManager::instance().findFileForRead(QString(
+    QFile * file = new QFile(DataManager::instance().findFileForRead(QString(
                                  "Names/%1.txt").arg(filename)));
 
     if (file->exists() && file->open(QIODevice::ReadOnly | QIODevice::Text))
@@ -154,7 +154,7 @@
     QStringList list;
 
     // find .cfg to load the dicts from
-    QFile * file = new QFile(HWDataManager::instance().findFileForRead(QString(
+    QFile * file = new QFile(DataManager::instance().findFileForRead(QString(
                                  "Names/%1.cfg").arg(hatname)));
 
     if (file->exists() && file->open(QIODevice::ReadOnly | QIODevice::Text))
@@ -184,7 +184,7 @@
 
     // find .ini to load the names from
     QFile * file = new QFile(
-        HWDataManager::instance().findFileForRead(QString("Names/types.ini")));
+        DataManager::instance().findFileForRead(QString("Names/types.ini")));
 
 
     if (file->exists() && file->open(QIODevice::ReadOnly | QIODevice::Text))
@@ -243,7 +243,7 @@
     QStringList Graves;
 
     //list all available Graves
-    Graves.append(HWDataManager::instance().entryList(
+    Graves.append(DataManager::instance().entryList(
                       "Graphics/Graves",
                       QDir::Files,
                       QStringList("*.png")
@@ -265,7 +265,7 @@
     QStringList Forts;
 
     //list all available Forts
-    Forts.append(HWDataManager::instance().entryList(
+    Forts.append(DataManager::instance().entryList(
                      "Forts",
                      QDir::Files,
                      QStringList("*L.png")
--- a/QTfrontend/util/namegen.h	Sun Apr 01 15:23:34 2012 +0200
+++ b/QTfrontend/util/namegen.h	Wed May 02 23:53:45 2012 +0200
@@ -1,7 +1,7 @@
 /*
  * Hedgewars, a free turn based strategy game
  * Copyright (c) 2009 Martin Minarik <ttsmj@pokec.sk>
- * Copyright (c) 2009-2012 Andrey Korotaev <unC0Rr@gmail.com>
+ * Copyright (c) 2004-2012 Andrey Korotaev <unC0Rr@gmail.com>
  *
  * This program is free software; you can redistribute it and/or modify
  * it under the terms of the GNU General Public License as published by
--- a/QTfrontend/xfire.cpp	Sun Apr 01 15:23:34 2012 +0200
+++ b/QTfrontend/xfire.cpp	Wed May 02 23:53:45 2012 +0200
@@ -1,6 +1,6 @@
 /*
  * Hedgewars, a free turn based strategy game
- * Copyright (c) 2010-2012 Andrey Korotaev <unC0Rr@gmail.com>
+ * Copyright (c) 2004-2012 Andrey Korotaev <unC0Rr@gmail.com>
  *
  * This program is free software; you can redistribute it and/or modify
  * it under the terms of the GNU General Public License as published by
--- a/QTfrontend/xfire.h	Sun Apr 01 15:23:34 2012 +0200
+++ b/QTfrontend/xfire.h	Wed May 02 23:53:45 2012 +0200
@@ -1,6 +1,6 @@
 /*
  * Hedgewars, a free turn based strategy game
- * Copyright (c) 2010-2012 Andrey Korotaev <unC0Rr@gmail.com>
+ * Copyright (c) 2004-2012 Andrey Korotaev <unC0Rr@gmail.com>
  *
  * This program is free software; you can redistribute it and/or modify
  * it under the terms of the GNU General Public License as published by
--- a/gameServer/CoreTypes.hs	Sun Apr 01 15:23:34 2012 +0200
+++ b/gameServer/CoreTypes.hs	Wed May 02 23:53:45 2012 +0200
@@ -192,6 +192,7 @@
 data Notice =
     NickAlreadyInUse
     | AdminLeft
+    | WrongPassword
     deriving Enum
 
 data ShutdownException =
--- a/gameServer/HWProtoInRoomState.hs	Sun Apr 01 15:23:34 2012 +0200
+++ b/gameServer/HWProtoInRoomState.hs	Wed May 02 23:53:45 2012 +0200
@@ -278,6 +278,8 @@
     where
         engineMsg cl = toEngineMsg $ B.concat ["b", nick cl, "(team): ", msg, "\x20\x20"]
 
+handleCmd_inRoom ["LIST"] = return [] -- for old clients (<= 0.9.17)
+
 handleCmd_inRoom (s:_) = return [ProtocolError $ "Incorrect command '" `B.append` s `B.append` "' (state: in room)"]
 
 handleCmd_inRoom [] = return [ProtocolError "Empty command (state: in room)"]
--- a/gameServer/HWProtoLobbyState.hs	Sun Apr 01 15:23:34 2012 +0200
+++ b/gameServer/HWProtoLobbyState.hs	Wed May 02 23:53:45 2012 +0200
@@ -76,7 +76,7 @@
             else if isRestrictedJoins jRoom then
             [Warning "Joining restricted"]
             else if roomPassword /= password jRoom then
-            [Warning "Wrong password"]
+            [NoticeMessage WrongPassword]
             else
             [
                 MoveToRoom jRI,
--- a/gameServer/Utils.hs	Sun Apr 01 15:23:34 2012 +0200
+++ b/gameServer/Utils.hs	Wed May 02 23:53:45 2012 +0200
@@ -123,9 +123,7 @@
     where
         f = map Char.toUpper . UTF8.toString
 
-roomInfo n r 
-    | isRestrictedJoins r = []
-    | otherwise = [
+roomInfo n r = [
         showB $ isJust $ gameInfo r,
         name r,
         showB $ playersIn r,
--- a/hedgewars/ArgParsers.inc	Sun Apr 01 15:23:34 2012 +0200
+++ b/hedgewars/ArgParsers.inc	Wed May 02 23:53:45 2012 +0200
@@ -50,10 +50,10 @@
     UserNick:= DecodeBase64(ParamStr(14));
     val(ParamStr(15), cReducedQuality);
     val(ParamStr(16), tmp);
-    cGrayScale:= false;
+    GrayScale:= false;
     if (tmp > 9) and (tmp < 16) then 
         begin
-        cGrayScale:= true;
+        GrayScale:= true;
         cStereoMode:= TStereoMode(max(0, min(ord(high(TStereoMode)), tmp-9)))
         end
     else if tmp <= 9 then 
--- a/hedgewars/CMakeLists.txt	Sun Apr 01 15:23:34 2012 +0200
+++ b/hedgewars/CMakeLists.txt	Wed May 02 23:53:45 2012 +0200
@@ -16,6 +16,7 @@
 set(engine_sources
     ${hwengine_project}
     SDLh.pas
+    PNGh.pas
     uAI.pas
     uAIActions.pas
     uAIAmmoTests.pas
@@ -34,7 +35,7 @@
     uGears.pas
     uGearsRender.pas
     uIO.pas
-    uKeys.pas
+    uInputHandler.pas
     uLand.pas
     uLandGenMaze.pas
     uLandGraphics.pas
@@ -63,7 +64,6 @@
     uWorld.pas
     GSHandlers.inc
     VGSHandlers.inc
-    HHHandlers.inc
     ArgParsers.inc
     options.inc
     adler32.pas
@@ -141,11 +141,24 @@
     message(FATAL_ERROR "No Pascal compiler found!")
 endif()
 
+
+#DEPENDECIES AND EXECUTABLES SECTION
+find_package(PNG)
+if(${PNG_FOUND})
+    message(STATUS "PNG screenshots enabled (library found at ${PNG_LIBRARY})")
+    set(pascal_compiler_flags_cmn "-dPNG_SCREENSHOTS" ${pascal_compiler_flags_cmn})
+    if(APPLE)  # need to explictly link with the static lib
+        string(REGEX REPLACE "(.*)libpng.*" "\\1" PNG_LIBDIR "${PNG_LIBRARY}")
+        set(pascal_compiler_flags_cmn "-k${PNG_LIBDIR}/libpng.a" ${pascal_compiler_flags_cmn})
+    endif()
+else()
+    message(STATUS "PNG library not found, switching to screenshots in BMP format")
+endif()
+
 set(pascal_compiler ${fpc_executable})
 set(pascal_compiler_flags ${noexecstack_flags} ${pascal_compiler_flags_cmn} ${hwengine_project})
 
 
-#DEPENDECIES AND EXECUTABLES SECTION
 IF(NOT APPLE)
     #here is the command for standard executables or for shared library
     add_custom_command(OUTPUT "${EXECUTABLE_OUTPUT_PATH}/${engine_output_name}${CMAKE_EXECUTABLE_SUFFIX}"
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/hedgewars/GL.h	Wed May 02 23:53:45 2012 +0200
@@ -0,0 +1,3 @@
+#pragma once
+
+#include <GL/gl.h>
--- a/hedgewars/GSHandlers.inc	Sun Apr 01 15:23:34 2012 +0200
+++ b/hedgewars/GSHandlers.inc	Wed May 02 23:53:45 2012 +0200
@@ -170,14 +170,14 @@
     Gear^.Y := Gear^.Y + cDrownSpeed;
     Gear^.X := Gear^.X + Gear^.dX * cDrownSpeed;
     // Create some bubbles (0.5% might be better but causes too few bubbles sometimes)
-    if ((not SuddenDeathDmg and (cWaterOpacity < $FF))
-    or (SuddenDeathDmg and (cSDWaterOpacity < $FF))) and ((GameTicks and $1F) = 0) then
+    if ((not SuddenDeathDmg and (WaterOpacity < $FF))
+    or (SuddenDeathDmg and (SDWaterOpacity < $FF))) and ((GameTicks and $1F) = 0) then
         if (Gear^.Kind = gtHedgehog) and (Random(4) = 0) then
             AddVisualGear(hwRound(Gear^.X) - Gear^.Radius, hwRound(Gear^.Y) - Gear^.Radius, vgtBubble)
     else if Random(12) = 0 then
              AddVisualGear(hwRound(Gear^.X) - Gear^.Radius, hwRound(Gear^.Y) - Gear^.Radius, vgtBubble);
-    if (not SuddenDeathDmg and (cWaterOpacity > $FE))
-    or (SuddenDeathDmg and (cSDWaterOpacity > $FE))
+    if (not SuddenDeathDmg and (WaterOpacity > $FE))
+    or (SuddenDeathDmg and (SDWaterOpacity > $FE))
     or (hwRound(Gear^.Y) > Gear^.Radius + cWaterLine + cVisibleWater) then
         DeleteGear(Gear);
     end;
@@ -345,8 +345,8 @@
                 doMakeExplosion(x, y, 20, Gear^.Hedgehog, EXPLAutoSound);
                 for i:= 0 to 4 do
                     begin
-                    dX := rndSign(GetRandom * _0_1) + Gear^.dX / 5;
-                    dY := (GetRandom - _3) * _0_08;
+                    dX := rndSign(GetRandomf * _0_1) + Gear^.dX / 5;
+                    dY := (GetRandomf - _3) * _0_08;
                     FollowGear := AddGear(x, y, gtCluster, 0, dX, dY, 25)
                     end
                 end;
@@ -357,8 +357,8 @@
                 doMakeExplosion(x, y, 75, Gear^.Hedgehog, EXPLAutoSound);
                 for i:= 0 to 5 do
                     begin
-                    dX := rndSign(GetRandom * _0_1) + Gear^.dX / 5;
-                    dY := (GetRandom - _1_5) * _0_3;
+                    dX := rndSign(GetRandomf * _0_1) + Gear^.dX / 5;
+                    dY := (GetRandomf - _1_5) * _0_3;
                     FollowGear:= AddGear(x, y, gtMelonPiece, 0, dX, dY, 75);
                     FollowGear^.DirAngle := i * 60
                     end
@@ -371,8 +371,8 @@
 
                 for i:= 0 to 127 do
                     begin
-                    dX := AngleCos(i * 16) * _0_5 * (GetRandom + _1);
-                    dY := AngleSin(i * 16) * _0_5 * (GetRandom + _1);
+                    dX := AngleCos(i * 16) * _0_5 * (GetRandomf + _1);
+                    dY := AngleSin(i * 16) * _0_5 * (GetRandomf + _1);
                     if i mod 2 = 0 then
                         begin
                         AddGear(x, y, gtFlame, gstTmpFlag, dX, dY, 0);
@@ -477,8 +477,8 @@
             end;
         for i:= 0 to 24 do
             begin
-            dX := AngleCos(i * 2) * ((_0_15*(i div 5))) * (GetRandom + _1);
-            dY := AngleSin(i * 8) * _0_5 * (GetRandom + _1);
+            dX := AngleCos(i * 2) * ((_0_15*(i div 5))) * (GetRandomf + _1);
+            dY := AngleSin(i * 8) * _0_5 * (GetRandomf + _1);
             AddGear(gX, gY, gtFlame, gstTmpFlag, dX, dY, 0);
             AddGear(gX, gY, gtFlame, gstTmpFlag, dX,-dY, 0);
             AddGear(gX, gY, gtFlame, gstTmpFlag,-dX, dY, 0);
@@ -690,7 +690,7 @@
                                 end
                             else Land[ly, lx]:= lf;
                         if gun then
-                            LandPixels[ry, rx]:= (cExplosionBorderColor and (not AMask)) or (p^[px] and AMask)
+                            LandPixels[ry, rx]:= (ExplosionBorderColor and (not AMask)) or (p^[px] and AMask)
                         else LandPixels[ry, rx]:= addBgColor(LandPixels[ry, rx], p^[px]);
                         end
                     else allpx:= false
@@ -1032,7 +1032,7 @@
         dec(Gear^.Health, Gear^.Damage);
         Gear^.Damage := 0
         end;
-    if ((Gear^.State and gstDrowning) <> 0) and (Gear^.Damage < Gear^.Health) and ((not SuddenDeathDmg and (cWaterOpacity < $FF)) or (SuddenDeathDmg and (cSDWaterOpacity < $FF))) then
+    if ((Gear^.State and gstDrowning) <> 0) and (Gear^.Damage < Gear^.Health) and ((not SuddenDeathDmg and (WaterOpacity < $FF)) or (SuddenDeathDmg and (SDWaterOpacity < $FF))) then
         begin
         for i:=(Gear^.Health - Gear^.Damage) * 4 downto 0 do
             begin
@@ -2130,8 +2130,8 @@
                 doMakeExplosion(x, y, 75, hog, EXPLAutoSound);
                 for i:= 0 to 31 do
                     begin
-                    dX := AngleCos(i * 64) * _0_5 * (getrandom + _1);
-                    dY := AngleSin(i * 64) * _0_5 * (getrandom + _1);
+                    dX := AngleCos(i * 64) * _0_5 * (getrandomf + _1);
+                    dY := AngleSin(i * 64) * _0_5 * (getrandomf + _1);
                     AddGear(x, y, gtFlame, 0, dX, dY, 0);
                     AddGear(x, y, gtFlame, gstTmpFlag, -dX, -dY, 0);
                     end
@@ -2715,7 +2715,7 @@
 procedure doStepSwitcherWork(Gear: PGear);
 var 
     HHGear: PGear;
-    Msg, State: Longword;
+    State: Longword;
 begin
     AllInactive := false;
 
@@ -2800,8 +2800,8 @@
         Gear^.dY.isNegative := not dyn;
         for i:= 0 to 4 do
             begin
-            dX := Gear^.dX + (GetRandom - _0_5) * _0_03;
-            dY := Gear^.dY + (GetRandom - _0_5) * _0_03;
+            dX := Gear^.dX + (GetRandomf - _0_5) * _0_03;
+            dY := Gear^.dY + (GetRandomf - _0_5) * _0_03;
             AddGear(hwRound(Gear^.X), hwRound(Gear^.Y), gtCluster, 0, dX, dY, 25);
             end;
 
@@ -2815,8 +2815,6 @@
 
 ////////////////////////////////////////////////////////////////////////////////
 procedure doStepKamikazeWork(Gear: PGear);
-
-const upd: Longword =   0;
 var 
     i: LongWord;
     HHGear: PGear;
@@ -3416,8 +3414,8 @@
     gY := hwRound(Gear^.Y) + GetLaunchY(amBallgun, HHGear^.Angle);
     if (Gear^.Timer mod 100) = 0 then
         begin
-        rx := rndSign(getRandom * _0_1);
-        ry := rndSign(getRandom * _0_1);
+        rx := rndSign(getRandomf * _0_1);
+        ry := rndSign(getRandomf * _0_1);
 
         AddGear(gx, gy, gtBall, 0, SignAs(AngleSin(HHGear^.Angle) * _0_8, HHGear^.dX) + rx, AngleCos(HHGear^.Angle) * ( - _0_8) + ry, 0);
 
@@ -3540,8 +3538,8 @@
             doMakeExplosion(hwRound(Gear^.X), hwRound(Gear^.Y), 25, Gear^.Hedgehog, EXPLAutoSound);
             for i:= 0 to 15 do
                 begin
-                dX := AngleCos(i * 64) * _0_5 * (GetRandom + _1);
-                dY := AngleSin(i * 64) * _0_5 * (GetRandom + _1);
+                dX := AngleCos(i * 64) * _0_5 * (GetRandomf + _1);
+                dY := AngleSin(i * 64) * _0_5 * (GetRandomf + _1);
                 AddGear(hwRound(Gear^.X), hwRound(Gear^.Y), gtFlame, 0, dX, dY, 0);
                 AddGear(hwRound(Gear^.X), hwRound(Gear^.Y), gtFlame, 0, dX, -dY, 0);
                 end;
@@ -3973,7 +3971,7 @@
                     begin
                     CurrentHedgehog^.Gear^.Message := CurrentHedgehog^.Gear^.Message and (not gmSwitch);
                 
-                    CurWeapon:= GetAmmoEntry(CurrentHedgehog^);
+                    CurWeapon:= GetCurAmmoEntry(CurrentHedgehog^);
                     if CurWeapon^.Pos <> 0 then
                         CurWeapon^.Pos := 0
                         
@@ -4344,7 +4342,7 @@
     if CurrentHedgehog <> nil then
         with CurrentHedgehog^ do
             begin
-            CurWeapon:= GetAmmoEntry(CurrentHedgehog^);
+            CurWeapon:= GetCurAmmoEntry(CurrentHedgehog^);
             if (CurAmmoType = amPortalGun) then
                 begin
                 if not destroyGear then
@@ -4444,7 +4442,7 @@
     if CurrentHedgehog <> nil then
         with CurrentHedgehog^ do
             begin
-            CurWeapon:= GetAmmoEntry(CurrentHedgehog^);
+            CurWeapon:= GetCurAmmoEntry(CurrentHedgehog^);
             // let's save the HH's dX's direction so we can decide where the "top" of the portal hole
             newPortal^.Elasticity.isNegative := CurrentHedgehog^.Gear^.dX.isNegative;
             // when doing a backjump the dx is the opposite of the facing direction
@@ -4756,8 +4754,8 @@
         dec(Gear^.Health);
         if (Gear^.Health mod 5) = 0 then
             begin
-            rx := rndSign(getRandom * _0_1);
-            ry := rndSign(getRandom * _0_1);
+            rx := rndSign(getRandomf * _0_1);
+            ry := rndSign(getRandomf * _0_1);
             speed := _0_5 * (_10 / Gear^.Tag);
     
             AddGear(gx, gy, gtFlame, gstTmpFlag,
@@ -4836,8 +4834,8 @@
         begin
         dec(Gear^.Health);
 
-        rx := rndSign(getRandom * _0_1);
-        ry := rndSign(getRandom * _0_1);
+        rx := rndSign(getRandomf * _0_1);
+        ry := rndSign(getRandomf * _0_1);
         speed := (_3 / Gear^.Tag);
 
         AddGear(gx, gy, gtFlake, gstTmpFlag, 
@@ -5148,8 +5146,8 @@
         gY := hwRound(Gear^.Y); 
         for i:= 0 to 10 do
         begin
-            dX := AngleCos(i * 2) * ((_0_1*(i div 5))) * (GetRandom + _1);
-            dY := AngleSin(i * 8) * _0_5 * (GetRandom + _1);
+            dX := AngleCos(i * 2) * ((_0_1*(i div 5))) * (GetRandomf + _1);
+            dY := AngleSin(i * 8) * _0_5 * (GetRandomf + _1);
             AddGear(gX, gY, gtFlame, 0, dX, dY, 0);
             AddGear(gX, gY, gtFlame, 0, dX, -dY, 0);
             AddGear(gX, gY, gtFlame, 0, -dX, dY, 0);
--- a/hedgewars/HHHandlers.inc	Sun Apr 01 15:23:34 2012 +0200
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,19 +0,0 @@
-(*
- * Hedgewars, a free turn based strategy game
- * Copyright (c) 2004-2012 Andrey Korotaev <unC0Rr@gmail.com>
- *
- * This program is free software; you can redistribute it and/or modify
- * it under the terms of the GNU General Public License as published by
- * the Free Software Foundation; version 2 of the License
- *
- * This program is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
- * GNU General Public License for more details.
- *
- * You should have received a copy of the GNU General Public License
- * along with this program; if not, write to the Free Software
- * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA
- *)
-
-////////////////////////////////////////////////////////////////////////////////
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/hedgewars/Math.h	Wed May 02 23:53:45 2012 +0200
@@ -0,0 +1,2 @@
+#pragma once
+
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/hedgewars/PNGh.pas	Wed May 02 23:53:45 2012 +0200
@@ -0,0 +1,90 @@
+(*
+ * Hedgewars, a free turn based strategy game
+ * Copyright (c) 2004-2012 Andrey Korotaev <unC0Rr@gmail.com>
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; version 2 of the License
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA
+ *)
+
+{$INCLUDE "options.inc"}
+
+unit PNGh;
+interface
+
+uses png;
+
+{$IFDEF FPC}
+    {$PACKRECORDS C}
+{$ELSE}
+    {$DEFINE cdecl attribute(cdecl)}
+{$ENDIF}
+
+const
+    // Constants for libpng, they are not defined in png unit.
+    // We actually don't need all of them.
+
+    // These describe the color_type field in png_info.
+    // color type masks
+    PNG_COLOR_MASK_PALETTE = 1;
+    PNG_COLOR_MASK_COLOR   = 2;
+    PNG_COLOR_MASK_ALPHA   = 4;
+
+    // color types.  Note that not all combinations are legal
+    PNG_COLOR_TYPE_GRAY       = 0;
+    PNG_COLOR_TYPE_PALETTE    = PNG_COLOR_MASK_COLOR or PNG_COLOR_MASK_PALETTE;
+    PNG_COLOR_TYPE_RGB        = PNG_COLOR_MASK_COLOR;
+    PNG_COLOR_TYPE_RGB_ALPHA  = PNG_COLOR_MASK_COLOR or PNG_COLOR_MASK_ALPHA;
+    PNG_COLOR_TYPE_GRAY_ALPHA = PNG_COLOR_MASK_ALPHA;
+
+    // aliases
+    PNG_COLOR_TYPE_RGBA = PNG_COLOR_TYPE_RGB_ALPHA;
+    PNG_COLOR_TYPE_GA   = PNG_COLOR_TYPE_GRAY_ALPHA;
+
+    // This is for compression type. PNG 1.0-1.2 only define the single type.
+    PNG_COMPRESSION_TYPE_BASE    = 0; // Deflate method 8, 32K window
+    PNG_COMPRESSION_TYPE_DEFAULT = PNG_COMPRESSION_TYPE_BASE;
+
+    // This is for filter type. PNG 1.0-1.2 only define the single type.
+    PNG_FILTER_TYPE_BASE        = 0;  // Single row per-byte filtering
+    PNG_INTRAPIXEL_DIFFERENCING = 64; // Used only in MNG datastreams
+    PNG_FILTER_TYPE_DEFAULT     = PNG_FILTER_TYPE_BASE;
+
+    // These are for the interlacing type.  These values should NOT be changed.
+    PNG_INTERLACE_NONE  = 0; // Non-interlaced image
+    PNG_INTERLACE_ADAM7 = 1; // Adam7 interlacing
+    PNG_INTERLACE_LAST  = 2; // Not a valid value
+
+type
+    // where is better place for this definition?
+    PFile = ^file;
+
+procedure png_init_pascal_io(png_ptr: png_structp; pf : PFile);
+
+implementation
+
+// We cannot get c-style FILE* pointer to pass it to libpng, so we implement our own writing functions
+procedure PngWriteData(png_ptr: png_structp; p: PByte; len: png_size_t); cdecl;
+begin
+    BlockWrite( PFile(png_get_io_ptr(png_ptr))^, p^, len);
+end;
+
+procedure PngFlushData(png_ptr: png_structp); cdecl;
+begin
+end;
+
+procedure png_init_pascal_io(png_ptr: png_structp; pf : PFile);
+begin
+    png_set_write_fn(png_ptr, pf, @PngWriteData, @PngFlushData);
+end;
+
+end.
--- a/hedgewars/PascalExports.pas	Sun Apr 01 15:23:34 2012 +0200
+++ b/hedgewars/PascalExports.pas	Wed May 02 23:53:45 2012 +0200
@@ -28,7 +28,7 @@
  *           http://en.wikipedia.org/wiki/X86_calling_conventions#cdecl
  *)
 interface
-uses uTypes, uConsts, uVariables, GLunit, uKeys, uSound, uAmmos, uUtils, uCommands;
+uses uTypes, uConsts, uVariables, GLunit, uInputHandler, uSound, uAmmos, uUtils, uCommands;
 
 {$INCLUDE "config.inc"}
 procedure HW_versionInfo(netProto: PLongInt; versionStr: PPChar); cdecl; export;
@@ -52,35 +52,12 @@
     versionStr^:= cVersionString;
 end;
 
-// emulate mouse/keyboard input
-procedure HW_click; cdecl; export;
-begin
-    leftClick:= true;
-end;
-
-procedure HW_ammoMenu; cdecl; export;
-begin
-    rightClick:= true;
-end;
-
 procedure HW_zoomSet(value: GLfloat); cdecl; export;
 begin
     cZoomVal:= value;
     ZoomValue:= value;
 end;
 
-procedure HW_zoomIn; cdecl; export;
-begin
-    if wheelDown = false then
-        wheelUp:= true;
-end;
-
-procedure HW_zoomOut; cdecl; export;
-begin
-    if wheelUp = false then
-        wheelDown:= true;
-end;
-
 procedure HW_zoomReset; cdecl; export;
 begin
     ZoomValue:= cZoomVal;
@@ -91,84 +68,12 @@
 
 function HW_zoomFactor: GLfloat; cdecl; export;
 begin
-    exit( ZoomValue / cDefaultZoomLevel );
+    HW_zoomFactor:= ZoomValue / cDefaultZoomLevel;
 end;
 
 function HW_zoomLevel: LongInt; cdecl; export;
 begin
-    exit( trunc((ZoomValue - cDefaultZoomLevel) / cZoomDelta) );
-end;
-
-procedure HW_walkingKeysUp; cdecl; export;
-begin
-    leftKey:= false;
-    rightKey:= false;
-    upKey:= false;
-    downKey:= false;
-    preciseKey:= false;
-end;
-
-procedure HW_otherKeysUp; cdecl; export;
-begin
-    spaceKey:= false;
-    enterKey:= false;
-    backspaceKey:= false;
-end;
-
-procedure HW_allKeysUp; cdecl; export;
-begin
-    // set all keys to released
-    uKeys.initModule;
-end;
-
-procedure HW_walkLeft; cdecl; export;
-begin
-    leftKey:= true;
-end;
-
-procedure HW_walkRight; cdecl; export;
-begin
-    rightKey:= true;
-end;
-
-procedure HW_preciseSet(status:boolean); cdecl; export;
-begin
-    preciseKey:= status;
-end;
-
-procedure HW_aimUp; cdecl; export;
-begin
-    upKey:= true;
-end;
-
-procedure HW_aimDown; cdecl; export;
-begin
-    downKey:= true;
-end;
-
-procedure HW_shoot; cdecl; export;
-begin
-    spaceKey:= true;
-end;
-
-procedure HW_jump; cdecl; export;
-begin
-    enterKey:= true;
-end;
-
-procedure HW_backjump; cdecl; export;
-begin
-    backspaceKey:= true;
-end;
-
-procedure HW_tab; cdecl; export;
-begin
-    tabKey:= true;
-end;
-
-procedure HW_chat; cdecl; export;
-begin
-    chatAction:= true;
+    HW_zoomLevel:= trunc((ZoomValue - cDefaultZoomLevel) / cZoomDelta);
 end;
 
 procedure HW_screenshot; cdecl; export;
@@ -176,20 +81,9 @@
     flagMakeCapture:= true;
 end;
 
-procedure HW_pause; cdecl; export;
-begin
-    if isPaused = false then
-        pauseAction:= true;
-end;
-
-procedure HW_pauseToggle; cdecl; export;
-begin
-    pauseAction:= true;
-end;
-
 function HW_isPaused: boolean; cdecl; export;
 begin
-    exit( isPaused );
+    HW_isPaused:= isPaused;
 end;
 
 // equivalent to esc+y; when closeFrontend = true the game exits after memory cleanup
@@ -201,11 +95,7 @@
 
 function HW_getSDLWindow: pointer; cdecl; export;
 begin
-{$IFDEF SDL13}
-    exit( SDLwindow );
-{$ELSE}
-    exit( nil );
-{$ENDIF}
+    HW_getSDLWindow:={$IFDEF SDL13}SDLwindow{$ELSE}nil{$ENDIF};
 end;
 
 // cursor handling
@@ -224,45 +114,41 @@
 // ammo menu related functions
 function HW_isAmmoMenuOpen: boolean; cdecl; export;
 begin
-    exit( bShowAmmoMenu );
+    HW_isAmmoMenuOpen:= bShowAmmoMenu;
 end;
 
 function HW_isAmmoMenuNotAllowed: boolean; cdecl; export;
 begin;
-    exit( (TurnTimeLeft = 0) or (not CurrentTeam^.ExtDriven and (((CurAmmoGear = nil)
-    or ((Ammoz[CurAmmoGear^.AmmoType].Ammo.Propz and ammoprop_AltAttack) = 0)) and hideAmmoMenu)) );
+    HW_isAmmoMenuNotAllowed:= ( (TurnTimeLeft = 0) or (not CurrentTeam^.ExtDriven and (((CurAmmoGear = nil) or
+                                ((Ammoz[CurAmmoGear^.AmmoType].Ammo.Propz and ammoprop_AltAttack) = 0)) and hideAmmoMenu)) );
 end;
 
 function HW_isWeaponRequiringClick: boolean; cdecl; export;
 begin
+    HW_isWeaponRequiringClick:= false;
     if (CurrentHedgehog <> nil) and (CurrentHedgehog^.Gear <> nil) and (CurrentHedgehog^.BotLevel = 0) then
-        exit( (CurrentHedgehog^.Gear^.State and gstHHChooseTarget) <> 0 )
-    else
-        exit(false);
+        HW_isWeaponRequiringClick:= (CurrentHedgehog^.Gear^.State and gstHHChooseTarget) <> 0;
 end;
 
 function HW_isWeaponTimerable: boolean; cdecl; export;
 begin
+    HW_isWeaponTimerable:= false;
     if (CurrentHedgehog <> nil) and (CurrentHedgehog^.Ammo <> nil) and (CurrentHedgehog^.BotLevel = 0) then
-        exit( (Ammoz[CurrentHedgehog^.CurAmmoType].Ammo.Propz and ammoprop_Timerable) <> 0)
-    else
-        exit(false);
+        HW_isWeaponTimerable:= (Ammoz[CurrentHedgehog^.CurAmmoType].Ammo.Propz and ammoprop_Timerable) <> 0;
 end;
 
 function HW_isWeaponSwitch: boolean cdecl; export;
 begin
+    HW_isWeaponSwitch:= false;
     if (CurAmmoGear <> nil) and (CurrentHedgehog^.BotLevel = 0) then
-        exit(CurAmmoGear^.AmmoType = amSwitch)
-    else
-        exit(false)
+        HW_isWeaponSwitch:= (CurAmmoGear^.AmmoType = amSwitch);
 end;
 
 function HW_isWeaponRope: boolean cdecl; export;
 begin
+    HW_isWeaponRope:= false;
     if (CurrentHedgehog <> nil) and (CurrentHedgehog^.Ammo <> nil) and (CurrentHedgehog^.BotLevel = 0) then
-        exit(CurrentHedgehog^.CurAmmoType = amRope)
-    else
-        exit(false);
+        HW_isWeaponRope:= (CurrentHedgehog^.CurAmmoType = amRope);
 end;
 
 procedure HW_setGrenadeTime(time: LongInt); cdecl; export;
@@ -272,14 +158,13 @@
 
 function HW_getGrenadeTime: LongInt; cdecl; export;
 var CurWeapon: PAmmo;
-    res: LongInt = 3;
 begin
+    HW_getGrenadeTime:= 3;
     if HW_isWeaponTimerable then
     begin
-        CurWeapon:= GetAmmoEntry(CurrentHedgehog^);
-        res:= CurWeapon^.Timer div 1000;
+        CurWeapon:= GetCurAmmoEntry(CurrentHedgehog^);
+        HW_getGrenadeTime:= CurWeapon^.Timer div 1000;
     end;
-    exit(res);
 end;
 
 procedure HW_setPianoSound(snd: LongInt); cdecl; export;
@@ -302,22 +187,22 @@
 
 function HW_getWeaponNameByIndex(whichone: LongInt): PChar; cdecl; export;
 begin
-    exit(str2pchar(trammo[Ammoz[TAmmoType(whichone+1)].NameId]));
+    HW_getWeaponNameByIndex:= (str2pchar(trammo[Ammoz[TAmmoType(whichone+1)].NameId]));
 end;
 
 function HW_getWeaponCaptionByIndex(whichone: LongInt): PChar; cdecl; export;
 begin
-    exit(str2pchar(trammoc[Ammoz[TAmmoType(whichone+1)].NameId]));
+    HW_getWeaponCaptionByIndex:= (str2pchar(trammoc[Ammoz[TAmmoType(whichone+1)].NameId]));
 end;
 
 function HW_getWeaponDescriptionByIndex(whichone: LongInt): PChar; cdecl; export;
 begin
-    exit(str2pchar(trammod[Ammoz[TAmmoType(whichone+1)].NameId]));
+    HW_getWeaponDescriptionByIndex:= (str2pchar(trammod[Ammoz[TAmmoType(whichone+1)].NameId]));
 end;
 
-function HW_getNumberOfWeapons:LongInt; cdecl; export;
+function HW_getNumberOfWeapons: LongInt; cdecl; export;
 begin
-    exit(ord(high(TAmmoType)));
+    HW_getNumberOfWeapons:= ord(high(TAmmoType));
 end;
 
 procedure HW_setWeapon(whichone: LongInt); cdecl; export;
@@ -329,26 +214,27 @@
 
 function HW_isWeaponAnEffect(whichone: LongInt): boolean; cdecl; export;
 begin
-    exit(Ammoz[TAmmoType(whichone+1)].Ammo.Propz and ammoprop_Effect <> 0)
+    HW_isWeaponAnEffect:= Ammoz[TAmmoType(whichone+1)].Ammo.Propz and ammoprop_Effect <> 0;
 end;
 
 function HW_getAmmoCounts(counts: PLongInt): LongInt; cdecl; export;
 var a : PHHAmmo;
-    slot, index: LongInt;
+    slot, index, res: LongInt;
 begin
+    HW_getAmmoCounts:= -1;
     // nil check
     if (CurrentHedgehog = nil) or (CurrentHedgehog^.Ammo = nil) or (CurrentTeam = nil) then
-        exit(-1);
+        exit;
     // hog controlled by opponent (net or ai)
     if (CurrentTeam^.ExtDriven) or (CurrentTeam^.Hedgehogs[0].BotLevel <> 0) then
-        exit(1);
+        exit;
 
     a:= CurrentHedgehog^.Ammo;
     for slot:= 0 to cMaxSlotIndex do
         for index:= 0 to cMaxSlotAmmoIndex do
             if a^[slot,index].Count <> 0 then // yes, ammomenu is hell
                 counts[ord(a^[slot,index].AmmoType)-1]:= a^[slot,index].Count;
-    exit(0);
+    HW_getAmmoCounts:= 0;
 end;
 
 procedure HW_getAmmoDelays (skipTurns: PByte); cdecl; export;
@@ -360,20 +246,19 @@
 
 function HW_getTurnsForCurrentTeam: LongInt; cdecl; export;
 begin
+    HW_getTurnsForCurrentTeam:= 0;
     if (CurrentTeam <> nil) and (CurrentTeam^.Clan <> nil) then
-        exit(CurrentTeam^.Clan^.TurnNumber)
-    else
-        exit(0);
+        HW_getTurnsForCurrentTeam:= CurrentTeam^.Clan^.TurnNumber;
 end;
 
 function HW_getMaxNumberOfHogs: LongInt; cdecl; export;
 begin
-    exit(cMaxHHIndex+1);
+    HW_getMaxNumberOfHogs:= cMaxHHIndex + 1;
 end;
 
 function HW_getMaxNumberOfTeams: LongInt; cdecl; export;
 begin
-    exit(cMaxTeams);
+    HW_getMaxNumberOfTeams:= cMaxTeams;
 end;
 
 procedure HW_memoryWarningCallback; cdecl; export;
--- a/hedgewars/SDLh.pas	Sun Apr 01 15:23:34 2012 +0200
+++ b/hedgewars/SDLh.pas	Wed May 02 23:53:45 2012 +0200
@@ -51,6 +51,9 @@
     {$PACKRECORDS C}
 {$ELSE}
     {$DEFINE cdecl attribute(cdecl)}
+    type PByte = ^Byte;
+    type PInteger = ^Integer;
+    type PLongInt = ^LongInt;
 {$ENDIF}
 
 {$IFDEF DARWIN}
@@ -111,6 +114,10 @@
 
     SDL_ALLEVENTS        = $FFFFFFFF;
     SDL_APPINPUTFOCUS    = $02;
+
+    SDL_BUTTON_LEFT      = 1;
+    SDL_BUTTON_MIDDLE    = 2;
+    SDL_BUTTON_RIGHT     = 3;
     SDL_BUTTON_WHEELUP   = 4;
     SDL_BUTTON_WHEELDOWN = 5;
 
@@ -291,7 +298,6 @@
     IMG_INIT_PNG = $00000002;
     IMG_INIT_TIF = $00000004;
 
-    {* SDL_EventMask type definition *}
 
 /////////////////////////////////////////////////////////////////
 ///////////////////////  TYPE DEFINITIONS ///////////////////////
@@ -368,7 +374,7 @@
 {$ENDIF}
         end;
 
-    SDL_eventaction = (SDL_ADDEVENT = 0, SDL_PEEPEVENT, SDL_GETEVENT);
+    TSDL_eventaction = (SDL_ADDEVENT, SDL_PEEPEVENT, SDL_GETEVENT);
 
     PSDL_Surface = ^TSDL_Surface;
     TSDL_Surface = record
@@ -439,7 +445,7 @@
 {$IFDEF SDL13}
     TSDL_KeySym = record
         scancode: LongInt;
-        sym: LongInt;
+        sym: LongWord;
         modifier: Word;
         unicode: LongWord;
         end;
@@ -543,9 +549,9 @@
     TSDL_KeyboardEvent = record
 {$IFDEF SDL13}
         type_: LongWord;
-        timestamp: LongWord;
+//        timestamp: LongWord;
         windowID: LongWord;
-        state, repeat_, padding2, padding3: Byte;
+        state, repeat_ {*,padding2, padding3*}: Byte;
 {$ELSE}
         type_, which, state: Byte;
 {$ENDIF}
@@ -570,7 +576,7 @@
         type_: LongWord;
         timestamp: LongWord;
         windowID: LongWord;
-        buttonm, state, padding1, padding2: Byte;
+        button, state, padding1, padding2: Byte;
         x, y: LongInt;
 {$ELSE}
         type_, which, button, state: Byte;
@@ -907,15 +913,18 @@
 function  SDL_SetHint(name, value: PChar): Boolean; cdecl; external SDLLibName;
 procedure SDL_StartTextInput; cdecl; external SDLLibName;
 
-function  SDL_PeepEvents(event: PSDL_Event; numevents: LongInt; action: SDL_eventaction; minType, maxType: LongWord): LongInt; cdecl; external SDLLibName;
+function  SDL_PeepEvents(event: PSDL_Event; numevents: LongInt; action: TSDL_eventaction; minType, maxType: LongWord): LongInt; cdecl; external SDLLibName;
 function  SDL_CreateThread(fn: Pointer; name: PChar; data: Pointer): PSDL_Thread; cdecl; external SDLLibName;
 {$ELSE}
 function  SDL_CreateThread(fn: Pointer; data: Pointer): PSDL_Thread; cdecl; external SDLLibName;
-function  SDL_PeepEvents(event: PSDL_Event; numevents: LongInt; action: SDL_eventaction; mask: LongWord): LongInt; cdecl; external SDLLibName;
+function  SDL_PeepEvents(event: PSDL_Event; numevents: LongInt; action: TSDL_eventaction; mask: LongWord): LongInt; cdecl; external SDLLibName;
 {$ENDIF}
 
 function  SDL_GetMouseState(x, y: PLongInt): Byte; cdecl; external SDLLibName;
 function  SDL_GetKeyName(key: LongWord): PChar; cdecl; external SDLLibName;
+function  SDL_GetScancodeName(key: LongWord): PChar; cdecl; external SDLLibName;
+function  SDL_GetKeyFromScancode(key: LongWord): LongInt; cdecl; external SDLLibName;
+
 
 procedure SDL_PumpEvents; cdecl; external SDLLibName;
 function  SDL_PollEvent(event: PSDL_Event): LongInt; cdecl; external SDLLibName;
@@ -966,7 +975,7 @@
 procedure SDL_FreeFormat(pixelformat: PSDL_PixelFormat); {$IFDEF SDL13}cdecl; external SDLLibName;{$ENDIF}
 function  SDL_VideoDriverName(namebuf: PChar; maxlen: LongInt): PChar; {$IFNDEF SDL13}cdecl; external SDLLibName;{$ENDIF}
 function  SDL_EnableUNICODE(enable: LongInt): LongInt; {$IFNDEF SDL13}cdecl; external SDLLibName;{$ENDIF}
-function  SDL_EnableKeyRepeat(delay_, interval: LongInt): LongInt; {$IFNDEF SDL13}cdecl; external SDLLibName;{$ENDIF}
+function  SDL_EnableKeyRepeat(timedelay, interval: LongInt): LongInt; {$IFNDEF SDL13}cdecl; external SDLLibName;{$ENDIF}
 
 (*  SDL_ttf  *)
 function  TTF_Init: LongInt; cdecl; external SDL_TTFLibName;
@@ -1045,11 +1054,10 @@
 function  SDLNet_Read32(buf: Pointer): LongWord;
 
 implementation
+{$IFDEF SDL13}
 uses strings, uVariables;
 
-{$IFDEF SDL13}
-// this needs to be reimplemented because in SDL_compat.c the window is the one created in the SDL_SetVideoMode
-// compatible function, but we use SDL_CreateWindow, so the window would be NULL
+// compatible functions
 procedure SDL_WarpMouse(x, y: Word);
 begin
     SDL_WarpMouseInWindow(SDLwindow, x, y);
@@ -1062,37 +1070,40 @@
     if (name <> nil) and (namebuf <> nil) then
         begin
         strlcopy(namebuf, name, maxlen);
-        exit(namebuf)
+        SDL_VideoDriverName:= namebuf
         end;
-    exit(name);
+    SDL_VideoDriverName:= name;
 end;
 
 function SDL_EnableUNICODE(enable: LongInt): LongInt;
 begin
     SDL_StartTextInput();
-    exit(0);
+    SDL_EnableUNICODE:= 0;
 end;
 
-function SDL_EnableKeyRepeat(delay_, interval: LongInt): LongInt;
+function SDL_EnableKeyRepeat(timedelay, interval: LongInt): LongInt;
 begin
-    exit(0);
+    timedelay:= timedelay;  // avoid hint
+    interval:= interval;    // avoid hint
+    SDL_EnableKeyRepeat:= 0;
 end;
 {$ELSE}
-function SDL_AllocFormat(format: LongWord): PSDL_PixelFormat;
 const conversionFormat: TSDL_PixelFormat = (
         palette: nil; BitsPerPixel: 32; BytesPerPixel: 4;
         Rloss: 0; Gloss: 0; Bloss: 0; Aloss: 0;
         Rshift: RShift; Gshift: GShift; Bshift: BShift; Ashift: AShift;
         RMask: RMask; GMask: GMask; BMask: BMask; AMask: AMask;
         colorkey: 0; alpha: 255);
+
+function SDL_AllocFormat(format: LongWord): PSDL_PixelFormat;
 begin
     format:= format;
-    exit(@conversionFormat);
+    SDL_AllocFormat:= @conversionFormat;
 end;
 
 procedure SDL_FreeFormat(pixelformat: PSDL_PixelFormat);
 begin
-    pixelformat:= pixelformat;
+    pixelformat:= pixelformat;  // avoid hint
 end;
 {$ENDIF}
 
@@ -1109,7 +1120,7 @@
 {$IFNDEF SDL_MIXER_NEWER}
 function  Mix_Init(flags: LongInt): LongInt;
 begin
-    exit(flags);
+    Mix_Init:= flags;
 end;
 
 procedure Mix_Quit;
@@ -1120,7 +1131,7 @@
 {$IFNDEF SDL_IMAGE_NEWER}
 function  IMG_Init(flags: LongInt): LongInt;
 begin
-    exit(flags);
+    IMG_Init:= flags;
 end;
 
 procedure IMG_Quit;
--- a/hedgewars/VGSHandlers.inc	Sun Apr 01 15:23:34 2012 +0200
+++ b/hedgewars/VGSHandlers.inc	Wed May 02 23:53:45 2012 +0200
@@ -728,16 +728,26 @@
 begin
 inc(Gear^.Timer, Steps);
     
-    while Gear^.Timer >= 10 do
-        begin
-        dec(Gear^.Timer, 10);
-        if WindBarWidth < Gear^.Tag then
-            inc(WindBarWidth)
-        else if WindBarWidth > Gear^.Tag then
-            dec(WindBarWidth);
-        end;
+while Gear^.Timer >= 10 do
+    begin
+    dec(Gear^.Timer, 10);
+    if WindBarWidth < Gear^.Tag then
+        inc(WindBarWidth)
+    else if WindBarWidth > Gear^.Tag then
+        dec(WindBarWidth);
+    end;
+if cWindspeedf > Gear^.dAngle then
+    begin
+    cWindspeedf := cWindspeedf - Gear^.Angle*Steps;
+    if cWindspeedf < Gear^.dAngle then cWindspeedf:= Gear^.dAngle;
+    end
+else if cWindspeedf < Gear^.dAngle then
+    begin
+    cWindspeedf := cWindspeedf + Gear^.Angle*Steps;
+    if cWindspeedf > Gear^.dAngle then cWindspeedf:= Gear^.dAngle;
+    end;
         
-if WindBarWidth = Gear^.Tag then 
+if (WindBarWidth = Gear^.Tag) and (cWindspeedf = Gear^.dAngle)  then 
     DeleteVisualGear(Gear)
 end;
 ////////////////////////////////////////////////////////////////////////////////
--- a/hedgewars/adler32.pas	Sun Apr 01 15:23:34 2012 +0200
+++ b/hedgewars/adler32.pas	Wed May 02 23:53:45 2012 +0200
@@ -63,9 +63,10 @@
 (*
 As per the license above, noting that this implementation of adler32 was stripped of everything we didn't need.
 That means no btypes, file loading, and the assembly version disabled.
+Also, the structure was removed to simplify C conversion
 *)
 
-procedure Adler32Update ( var adler     :longint; Msg     :pointer; Len     :longint );
+function Adler32Update ( var adler     :longint; Msg     :pointer; Len     :longint ) : longint;
 
 implementation
 
@@ -123,21 +124,17 @@
 end;
 *)
 
-procedure Adler32Update(var adler: longint; Msg: pointer; Len :longint);
+function Adler32Update(var adler: longint; Msg: pointer; Len :longint) : longint;
     {-update Adler32 with Msg data}
     const
         BASE = 65521; {max. prime < 65536 }
         NMAX = 3854; {max. n with 255n(n+1)/2 + (n+1)(BASE-1) < 2^31}
-    type
-        LH = packed record
-            L, H: word;
-            end;
     var
         s1, s2: longint;
         i, n: integer;
     begin
-        s1 := LH(adler).L;
-        s2 := LH(adler).H;
+        s1 := adler and $FFFF;
+        s2 := adler shr 16;
         while Len>0 do
             begin
             if Len<NMAX then
@@ -155,8 +152,7 @@
             s2 := s2 mod BASE;
             dec(len, n);
             end;
-        LH(adler).L := word(s1);
-        LH(adler).H := word(s2);
+        Adler32Update:= (s2 shl 16) or s1;
     end;
 
 end.
--- a/hedgewars/hwengine.pas	Sun Apr 01 15:23:34 2012 +0200
+++ b/hedgewars/hwengine.pas	Wed May 02 23:53:45 2012 +0200
@@ -1,20 +1,20 @@
 (*
-* Hedgewars, a free turn based strategy game
-* Copyright (c) 2004-2012 Andrey Korotaev <unC0Rr@gmail.com>
-*
-* This program is free software; you can redistribute it and/or modify
-* it under the terms of the GNU General Public License as published by
-* the Free Software Foundation; version 2 of the License
-*
-* This program is distributed in the hope that it will be useful,
-* but WITHOUT ANY WARRANTY; without even the implied warranty of
-* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
-* GNU General Public License for more details.
-*
-* You should have received a copy of the GNU General Public License
-* along with this program; if not, write to the Free Software
-* Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA
-*)
+ * Hedgewars, a free turn based strategy game
+ * Copyright (c) 2004-2012 Andrey Korotaev <unC0Rr@gmail.com>
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; version 2 of the License
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA
+ *)
 
 {$INCLUDE "options.inc"}
 
@@ -29,7 +29,7 @@
 program hwengine;
 {$ENDIF}
 
-uses SDLh, uMisc, uConsole, uGame, uConsts, uLand, uAmmos, uVisualGears, uGears, uStore, uWorld, uKeys, uSound,
+uses SDLh, uMisc, uConsole, uGame, uConsts, uLand, uAmmos, uVisualGears, uGears, uStore, uWorld, uInputHandler, uSound,
      uScript, uTeams, uStats, uIO, uLocale, uChat, uAI, uAIMisc, uRandom, uLandTexture, uCollisions,
      sysutils, uTypes, uVariables, uCommands, uUtils, uCaptions, uDebug, uCommandHandlers, uLandPainted
      {$IFDEF SDL13}, uTouch{$ENDIF}{$IFDEF ANDROID}, GLUnit{$ENDIF};
@@ -68,7 +68,7 @@
             AddFlakes;
             AssignHHCoords;
             AddMiscGears;
-            StoreLoad;
+            StoreLoad(false);
             InitWorld;
             ResetKbd;
             SoundLoad;
@@ -86,7 +86,7 @@
         gsConfirm, gsGame:
             begin
             DrawWorld(Lag); // never place between ProcessKbd and DoGameTick - bugs due to /put cmd and isCursorVisible
-            ProcessKbd;
+//            ProcessKbd;
             DoGameTick(Lag);
             ProcessVisualGears(Lag);
             end;
@@ -132,7 +132,7 @@
 begin
     WriteLnToConsole('Freeing resources...');
     FreeActionsList();
-    StoreRelease();
+    StoreRelease(false);
     ControllerClose();
     CloseIPC();
     TTF_Quit();
@@ -168,7 +168,12 @@
                 SDL_KEYDOWN:
                 if GameState = gsChat then
                     // sdl on iphone supports only ashii keyboards and the unicode field is deprecated in sdl 1.3
-                    KeyPressChat(event.key.keysym.sym);
+                    KeyPressChat(SDL_GetKeyFromScancode(event.key.keysym.sym))//TODO correct for keymodifiers
+                else
+                    ProcessKey(event.key);
+                SDL_KEYUP:
+                if GameState <> gsChat then
+                    ProcessKey(event.key);
                     
                 SDL_WINDOWEVENT:
                     if event.window.event = SDL_WINDOWEVENT_SHOWN then
@@ -207,15 +212,17 @@
 {$ELSE}
                 SDL_KEYDOWN:
                     if GameState = gsChat then
-                        KeyPressChat(event.key.keysym.unicode);
+                        KeyPressChat(event.key.keysym.unicode)
+                    else
+                        ProcessKey(event.key);
+                SDL_KEYUP:
+                if GameState <> gsChat then
+                    ProcessKey(event.key);
                     
                 SDL_MOUSEBUTTONDOWN:
-                    if event.button.button = SDL_BUTTON_WHEELDOWN then
-                        wheelDown:= true;
-                
+                    ProcessMouse(event.button, true); 
                 SDL_MOUSEBUTTONUP:
-                    if event.button.button = SDL_BUTTON_WHEELUP then
-                        wheelUp:= true;
+                    ProcessMouse(event.button, false); 
                     
                 SDL_ACTIVEEVENT:
                     if (event.active.state and SDL_APPINPUTFOCUS) <> 0 then
@@ -250,31 +257,31 @@
         end; //end case event.type_ of
     end; //end while SDL_PollEvent(@event) <> 0 do
 
-        if (cScreenResizeDelay <> 0) and (cScreenResizeDelay < RealTicks)
-        and ((cNewScreenWidth <> cScreenWidth) or (cNewScreenHeight <> cScreenHeight)) then
-            begin
-            cScreenResizeDelay:= 0;
-            cScreenWidth:= cNewScreenWidth;
-            cScreenHeight:= cNewScreenHeight;
+    if (cScreenResizeDelay <> 0) and (cScreenResizeDelay < RealTicks) and
+       ((cNewScreenWidth <> cScreenWidth) or (cNewScreenHeight <> cScreenHeight)) then
+    begin
+        cScreenResizeDelay:= 0;
+        cScreenWidth:= cNewScreenWidth;
+        cScreenHeight:= cNewScreenHeight;
 
-            ParseCommand('fullscr '+intToStr(LongInt(cFullScreen)), true);
-            WriteLnToConsole('window resize: ' + IntToStr(cScreenWidth) + ' x ' + IntToStr(cScreenHeight));
-            ScriptOnScreenResize();
-            InitCameraBorders();
-            InitTouchInterface();
-            end;
+        ParseCommand('fullscr '+intToStr(LongInt(cFullScreen)), true);
+        WriteLnToConsole('window resize: ' + IntToStr(cScreenWidth) + ' x ' + IntToStr(cScreenHeight));
+        ScriptOnScreenResize();
+        InitCameraBorders();
+        InitTouchInterface();
+    end;
 
-        if isTerminated = false then
-            begin
-            CurrTime:= SDL_GetTicks;
-            if PrevTime + longword(cTimerInterval) <= CurrTime then
-                begin
-                DoTimer(CurrTime - PrevTime);
-                PrevTime:= CurrTime
-                end
-            else SDL_Delay(1);
-            IPCCheckSock();
-            end;
+    if isTerminated = false then
+    begin
+        CurrTime:= SDL_GetTicks;
+        if PrevTime + longword(cTimerInterval) <= CurrTime then
+        begin
+            DoTimer(CurrTime - PrevTime);
+            PrevTime:= CurrTime
+        end
+        else SDL_Delay(1);
+        IPCCheckSock();
+        end;
     end;
 end;
 
@@ -442,7 +449,7 @@
         //uFloat does not need initialization
         //uGame does not need initialization
         uGears.initModule;
-        uKeys.initModule;
+        uInputHandler.initModule;
         //uLandGraphics does not need initialization
         //uLandObjects does not need initialization
         //uLandTemplates does not need initialization
@@ -478,7 +485,7 @@
         uLandTexture.freeModule;
         //uLandObjects does not need to be freed
         //uLandGraphics does not need to be freed
-        uKeys.freeModule;           //stub
+        uInputHandler.freeModule;           //stub
         uGears.freeModule;
         //uGame does not need to be freed
         //uFloat does not need to be freed
--- a/hedgewars/options.inc	Sun Apr 01 15:23:34 2012 +0200
+++ b/hedgewars/options.inc	Wed May 02 23:53:45 2012 +0200
@@ -1,6 +1,6 @@
 (*
  * Hedgewars, a free turn based strategy game
- * Copyright (c) 2004, 2012 Andrey Korotaev <unC0Rr@gmail.com>
+ * Copyright (c) 2004-2012 Andrey Korotaev <unC0Rr@gmail.com>
  *
  * This program is free software; you can redistribute it and/or modify
  * it under the terms of the GNU General Public License as published by
@@ -17,12 +17,12 @@
  *)
 
 {$IFDEF FPC}
-    {$J+}
+    {$WRITEABLECONST OFF} 
+    {$MODE OBJFPC}
 {$ELSE}
     {$ERROR Only Free Pascal supported!}
 {$ENDIF}
 
-{$MODE OBJFPC}
 {$MACRO ON}
 
 {$DEFINE GLunit:=GL}
@@ -63,4 +63,8 @@
     //{$DEFINE COUNTTICKS}
 {$ENDIF}
 
+{$IFNDEF MOBILE}
+    {$DEFINE USE_AM_NUMCOLUMN}
+{$ENDIF}
+
 //also available LUA_DISABLED
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/hedgewars/pas2c.h	Wed May 02 23:53:45 2012 +0200
@@ -0,0 +1,93 @@
+#pragma once
+
+#include <stdint.h>
+#include <stdbool.h>
+
+typedef union string255_
+    {
+        struct {
+            char s[256];
+        };
+        struct {
+            char len;
+            char str[255];
+        };
+    } string255;
+typedef struct string192_
+    {
+        char s[193];
+    } string192;
+typedef struct string31_
+    {
+        char s[32];
+    } string31;
+typedef struct string15_
+    {
+        char s[16];
+    } string15;
+
+typedef uint8_t Byte;
+typedef int8_t ShortInt;
+typedef uint16_t Word;
+typedef int16_t SmallInt;
+typedef uint32_t LongWord;
+typedef int32_t LongInt;
+typedef uint64_t QWord;
+typedef int64_t Int64;
+
+typedef LongInt Integer;
+typedef float extended;
+typedef float real;
+
+typedef bool boolean;
+
+typedef void * pointer;
+typedef Byte * PByte;
+typedef char * PChar;
+typedef LongInt * PLongInt;
+typedef Integer * PInteger;
+
+#ifdef __GNUG__
+#define NULL __null
+#else   /* G++ */
+/* shield NULL definition for non-gnu parsers */
+#ifndef __cplusplus
+#define NULL ((void *)0)
+#else
+#define NULL 0
+#endif  /* __cplusplus */
+#endif  /* G++ */
+
+#define new(a) __new((void **)&a, sizeof(*(a)))
+void __new(void ** p, int size);
+
+#define dispose(a) __dispose(a, sizeof(*(a)))
+void __dispose(pointer p, int size);
+
+#define FillChar(a, b, c) __FillChar(&(a), b, c)
+
+void __FillChar(pointer p, int size, char fill);
+string255 _strconcat(string255 a, string255 b);
+string255 _strappend(string255 s, char c);
+string255 _strprepend(char c, string255 s);
+bool _strcompare(string255 a, string255 b);
+char * _pchar(string255 s);
+
+int Length(string255 a);
+string255 copy(string255 a, int s, int l);
+string255 delete(string255 a, int s, int l);
+
+#define STRINIT(a) {.len = sizeof(a) - 1, .str = a}
+
+typedef int file;
+extern int FileMode;
+extern int IOResult;
+
+#define assign(a, b) assign_(&(a), b)
+void assign_(int * f, string255 fileName);
+void reset(int f, int size);
+#define BlockRead(a, b, c, d) BlockRead_(a, &(b), c, &(d))
+void BlockRead_(int f, void * p, int size, int * sizeRead);
+void close(int f);
+
+bool odd(int i);
--- a/hedgewars/pas2cSystem.pas	Sun Apr 01 15:23:34 2012 +0200
+++ b/hedgewars/pas2cSystem.pas	Wed May 02 23:53:45 2012 +0200
@@ -11,19 +11,19 @@
     SmallInt = integer;
     ShortInt = integer;
     QWord = integer;
-    GLInt = integer;
-    GLUInt = integer;
+    GLint = integer;
+    GLuint = integer;
     gl_unsigned_byte = integer;
+    Int = integer;
 
     pointer = pointer;
-    PChar = pointer;
 
     float = float;
     single = float;
     double = float;
     real = float;
     extended = float;
-    GLFloat = float;
+    GLfloat = float;
     gl_float = float;
 
     boolean = boolean;
@@ -35,6 +35,8 @@
     widechar = string;
 
     char = char;
+    PChar = ^char;
+    PPChar = ^Pchar;
     
     PByte = ^Byte;
     PLongInt = ^LongInt;
@@ -44,30 +46,43 @@
     Handle = integer;
     stderr = Handle;
 
+    png_structp = pointer;
+    png_size_t = integer;
+
 var 
     false, true: boolean;
+    
     write, writeLn, read, readLn: procedure;
+    
     StrLen, ord, Succ, Pred : function : integer;
     inc, dec, Low, High, Lo, Hi : function : integer;
     odd, even : function : boolean;
 
     Now : function : integer;
-    Length : function : integer;
-    SetLength, val : procedure;
 
     new, dispose, FillChar, Move : procedure;
 
     trunc, round : function : integer;
     Abs, Sqr : function : integer;
 
-    StrPas, FormatDateTime, copy, delete, str : function : shortstring;
+    StrPas, FormatDateTime, copy, delete, str, pos, trim, LowerCase : function : shortstring;
+    Length, StrToInt : function : integer;
+    SetLength, val : procedure;
+    _pchar : function : PChar;
 
-    assign, rewrite, reset, flush : procedure;
-    IOResult : function : integer;
-    exit, break, halt : procedure;
-    TextFile : Handle;
+    assign, rewrite, reset, flush, BlockWrite, BlockRead, close : procedure;
+    IOResult : integer;
+    exit, break, halt, continue : procedure;
+    TextFile, file : Handle;
+    FileMode : integer;
+    FileExists, DirectoryExists, eof : function : boolean;
+    ExtractFileName : function : string;
+    exitcode : integer;
+    
+    ParamCount : function : integer;
+    ParamStr : function : string;
 
-    Sqrt, ArcTan2, pi, cos, sin : function : float;
+    sqrt, arctan2, pi, cos, sin, power : function : float;
 
     TypeInfo, GetEnumName : function : shortstring;
 
@@ -86,6 +101,45 @@
     glcolor4ub, gl_texture_wrap_s, gltexparameteri,
     gl_texture_wrap_t, gl_texture_min_filter,
     gl_linear, gl_texture_mag_filter, glgentextures,
-    gldeletetextures : procedure;
+    gldeletetextures, glreadpixels, glclearcolor,
+    gl_line_strip, gldeleterenderbuffersext,
+    gldeleteframebuffersext, glext_loadextension,
+    gl_max_texture_size, glgetintegerv, gl_renderer,
+    glgetstring, gl_vendor, gl_version, glgenframebuffersext,
+    glbindframebufferext, glgenrenderbuffersext,
+    glbindrenderbufferext, glrenderbufferstorageext,
+    glframebufferrenderbufferext, glframebuffertexture2dext,
+    gl_framebuffer_ext, gl_depth_component, 
+    gl_depth_attachment_ext, gl_renderbuffer_ext, gl_rgba8,
+    gl_color_attachment0_ext, gl_modelview, gl_blend,
+    gl_src_alpha, gl_one_minus_src_alpha,  
+    gl_perspective_correction_hint, gl_fastest,
+    gl_dither, gl_vertex_array, gl_texture_coord_array,
+    glviewport, glloadidentity, glmatrixmode, glhint,
+    glblendfunc, glenableclientstate, gl_color_buffer_bit,
+    glclear, gldisableclientstate, gl_color_array,
+    glcolorpointer, gl_depth_buffer_bit, gl_quads,
+    glbegin, glend, gltexcoord2f, glvertex2d,
+    gl_true, gl_false, glcolormask, gl_projection,
+    gl_texture_priority, glenum, gl_clamp_to_edge,
+    gl_extensions, gl_bgra : procedure;
 
     TThreadId : function : integer;
+    BeginThread, ThreadSwitch : procedure;
+    InterlockedIncrement, InterlockedDecrement : procedure;
+    
+    random : function : integer;
+    randomize : procedure;
+    
+    Assigned : function : boolean;
+    
+    _strconcat, _strappend, _strprepend : function : string;
+    _strcompare, _strncompare : function : boolean;
+
+    png_structp, png_set_write_fn, png_get_io_ptr,
+    png_get_libpng_ver, png_create_write_struct,
+    png_create_info_struct, png_destroy_write_struct,
+    png_write_row, png_set_ihdr, png_write_info,
+    png_write_end : procedure;
+
+    EnumToStr : function : string;
--- a/hedgewars/uAI.pas	Sun Apr 01 15:23:34 2012 +0200
+++ b/hedgewars/uAI.pas	Wed May 02 23:53:45 2012 +0200
@@ -291,7 +291,8 @@
 
 function Think(Me: Pointer): ptrint;
 var BackMe, WalkMe: TGear;
-    StartTicks, currHedgehogIndex, itHedgehog, switchesNum, i, switchCount: Longword;
+    switchCount: LongInt;
+    StartTicks, currHedgehogIndex, itHedgehog, switchesNum, i: Longword;
     switchImmediatelyAvailable: boolean;
     Actions: TActions;
 begin
@@ -319,7 +320,7 @@
                 if not switchImmediatelyAvailable  then
                     begin
                     // when AI has to use switcher, make it cost smth unless they have a lot of switches
-                    if (SwitchCount < 10) then Actions.Score:= (-27+SwitchCount*3)*4000;
+                    if (switchCount < 10) then Actions.Score:= (-27+switchCount*3)*4000;
                     AddAction(Actions, aia_Weapon, Longword(amSwitch), 300 + random(200), 0, 0);                    
                     AddAction(Actions, aia_attack, aim_push, 300 + random(300), 0, 0);
                     AddAction(Actions, aia_attack, aim_release, 1, 0, 0);
@@ -408,8 +409,7 @@
 end;
 
 procedure ProcessBot;
-const StartTicks: Longword = 0;
-      cStopThinkTime = 40;
+const cStopThinkTime = 40;
 begin
 with CurrentHedgehog^ do
     if (Gear <> nil)
@@ -439,6 +439,7 @@
 procedure initModule;
 begin
     hasThread:= 0;
+    StartTicks:= 0;
     ThinkThread:= ThinkThread;
 end;
 
--- a/hedgewars/uAIActions.pas	Sun Apr 01 15:23:34 2012 +0200
+++ b/hedgewars/uAIActions.pas	Wed May 02 23:53:45 2012 +0200
@@ -126,8 +126,6 @@
 end;
 
 procedure CheckHang(Me: PGear);
-const PrevX: LongInt = 0;
-      timedelta: Longword = 0;
 begin
 if hwRound(Me^.X) <> PrevX then
     begin
--- a/hedgewars/uAIAmmoTests.pas	Sun Apr 01 15:23:34 2012 +0200
+++ b/hedgewars/uAIAmmoTests.pas	Wed May 02 23:53:45 2012 +0200
@@ -166,7 +166,7 @@
             value:= - Metric(Targ.X, Targ.Y, EX, EY) div 64;
         if valueResult <= value then
             begin
-            ap.Angle:= DxDy2AttackAngle(Vx, Vy) + AIrndSign(random((Level - 1) * 9));
+            ap.Angle:= DxDy2AttackAnglef(Vx, Vy) + AIrndSign(random((Level - 1) * 9));
             ap.Power:= trunc(sqrt(r) * cMaxPower) - random((Level - 1) * 17 + 1);
             ap.ExplR:= 100;
             ap.ExplX:= EX;
@@ -223,7 +223,7 @@
 
         if valueResult <= value then
             begin
-            ap.Angle:= DxDy2AttackAngle(Vx, Vy) + AIrndSign(random((Level - 1) * 9));
+            ap.Angle:= DxDy2AttackAnglef(Vx, Vy) + AIrndSign(random((Level - 1) * 9));
             ap.Power:= trunc(sqrt(r) * cMaxPower) - random((Level - 1) * 17 + 1);
             ap.ExplR:= 0;
             ap.ExplX:= EX;
@@ -273,7 +273,7 @@
                   
         if valueResult < Score then
             begin
-            ap.Angle:= DxDy2AttackAngle(Vx, Vy) + AIrndSign(random(Level));
+            ap.Angle:= DxDy2AttackAnglef(Vx, Vy) + AIrndSign(random(Level));
             ap.Power:= trunc(sqrt(r) * cMaxPower) + AIrndSign(random(Level) * 15);
             ap.Time:= TestTime;
             ap.ExplR:= 100;
@@ -327,7 +327,7 @@
 
     if valueResult < Score then
         begin
-        ap.Angle:= DxDy2AttackAngle(Vx, Vy) + AIrndSign(random(Level));
+        ap.Angle:= DxDy2AttackAnglef(Vx, Vy) + AIrndSign(random(Level));
         ap.Power:= trunc(sqrt(r) * cMaxPower) + AIrndSign(random(Level) * 15);
         ap.Time:= TestTime;
         ap.ExplR:= 100;
@@ -384,7 +384,7 @@
 
      if valueResult < Score then
         begin
-        ap.Angle:= DxDy2AttackAngle(Vx, Vy) + AIrndSign(random(Level));
+        ap.Angle:= DxDy2AttackAnglef(Vx, Vy) + AIrndSign(random(Level));
         ap.Power:= trunc(sqrt(r) * cMaxPower * 0.9) + AIrndSign(random(Level) * 15);
         ap.Time:= TestTime;
         ap.ExplR:= 90;
@@ -436,7 +436,7 @@
         
     if valueResult < Score then
         begin
-        ap.Angle:= DxDy2AttackAngle(Vx, Vy) + AIrndSign(random(Level));
+        ap.Angle:= DxDy2AttackAnglef(Vx, Vy) + AIrndSign(random(Level));
         ap.Power:= trunc(sqrt(r) * cMaxPower * 0.9) + AIrndSign(random(Level) * 15);
         ap.Time:= TestTime;
         ap.ExplR:= 300;
@@ -474,22 +474,22 @@
 function TestMortar(Me: PGear; Targ: TPoint; Level: LongInt; var ap: TAttackParams): LongInt;
 //const tDelta = 24;
 var Vx, Vy: real;
-    Score, EX, EY, valueResult: LongInt;
+    Score, EX, EY: LongInt;
     TestTime: Longword;
     x, y, dY, meX, meY: real;
 begin
-valueResult:= BadTurn;
+TestMortar:= BadTurn;
 ap.ExplR:= 0;
 meX:= hwFloat2Float(Me^.X);
 meY:= hwFloat2Float(Me^.Y);
 
 if (Level > 2) then
-    exit(BadTurn);
+    exit;
 
 TestTime:= Solve(Targ.X, Targ.Y, trunc(meX), trunc(meY));
 
 if TestTime = 0 then
-    exit(BadTurn);
+    exit;
 
     Vx:= (Targ.X - meX) / TestTime;
     Vy:= cGravityf * (TestTime div 2) - (Targ.Y - meY) / TestTime;
@@ -520,17 +520,15 @@
     else
         Score:= BadTurn;
 
-    if valueResult < Score then
+    if BadTurn < Score then
         begin
-        ap.Angle:= DxDy2AttackAngle(Vx, Vy) + AIrndSign(random(Level));
+        ap.Angle:= DxDy2AttackAnglef(Vx, Vy) + AIrndSign(random(Level));
         ap.Power:= 1;
         ap.ExplR:= 100;
         ap.ExplX:= EX;
         ap.ExplY:= EY;
-        valueResult:= Score
+        TestMortar:= Score
         end;
-
-TestMortar:= valueResult;
 end;
 
 function TestShotgun(Me: PGear; Targ: TPoint; Level: LongInt; var ap: TAttackParams): LongInt;
@@ -541,6 +539,7 @@
     rx, ry, valueResult: LongInt;
     range: integer;
 begin
+TestShotgun:= BadTurn;
 ap.ExplR:= 0;
 ap.Time:= 0;
 ap.Power:= 1;
@@ -548,26 +547,28 @@
 y:= hwFloat2Float(Me^.Y);
 range:= Metric(trunc(x), trunc(y), Targ.X, Targ.Y);
 if ( range < MIN_RANGE ) or ( range > MAX_RANGE ) then
-    exit(BadTurn);
+    exit;
 Vx:= (Targ.X - x) * 1 / 1024;
 Vy:= (Targ.Y - y) * 1 / 1024;
-ap.Angle:= DxDy2AttackAngle(Vx, -Vy);
+ap.Angle:= DxDy2AttackAnglef(Vx, -Vy);
 repeat
     x:= x + vX;
     y:= y + vY;
     rx:= trunc(x);
     ry:= trunc(y);
     if TestCollExcludingMe(Me, rx, ry, 2) then
-        begin
+    begin
         x:= x + vX * 8;
         y:= y + vY * 8;
         valueResult:= RateShotgun(Me, vX, vY, rx, ry);
      
-    if valueResult = 0 then 
-        valueResult:= - Metric(Targ.X, Targ.Y, rx, ry) div 64
-    else 
-        dec(valueResult, Level * 4000);
-    exit(valueResult * 27 div 20) // 27/20 is reuse bonus
+        if valueResult = 0 then 
+            valueResult:= - Metric(Targ.X, Targ.Y, rx, ry) div 64
+        else 
+            dec(valueResult, Level * 4000);
+        // 27/20 is reuse bonus
+        TestShotgun:= valueResult * 27 div 20;
+        exit 
     end
 until (Abs(Targ.X - trunc(x)) + Abs(Targ.Y - trunc(y)) < 4)
     or (x < 0)
@@ -591,11 +592,14 @@
 x:= hwFloat2Float(Me^.X);
 y:= hwFloat2Float(Me^.Y);
 if Abs(trunc(x) - Targ.X) + Abs(trunc(y) - Targ.Y) < 40 then
-   exit(BadTurn);
+begin
+    TestDesertEagle:= BadTurn;
+    exit;
+end;
 t:= 0.5 / sqrt(sqr(Targ.X - x)+sqr(Targ.Y-y));
 Vx:= (Targ.X - x) * t;
 Vy:= (Targ.Y - y) * t;
-ap.Angle:= DxDy2AttackAngle(Vx, -Vy);
+ap.Angle:= DxDy2AttackAnglef(Vx, -Vy);
 d:= 0;
 
 repeat
@@ -628,11 +632,12 @@
     x, y: real;
 begin
 Level:= Level; // avoid compiler hint
+TestBaseballBat:= BadTurn;
 ap.ExplR:= 0;
 x:= hwFloat2Float(Me^.X);
 y:= hwFloat2Float(Me^.Y);
 if (Level > 2) or (Abs(trunc(x) - Targ.X) + Abs(trunc(y) - Targ.Y) > 25) then
-    exit(BadTurn);
+    exit;
 
 ap.Time:= 0;
 ap.Power:= 1;
@@ -641,7 +646,7 @@
 else
     ap.Angle:= - cMaxAngle div 4;
 
-valueResult:= RateShove(Me, trunc(x) + 10 * hwSign(Targ.X - x), trunc(y), 15, 30, 115, hwSign(Me^.dX)*0.353, -0.353, 1);
+valueResult:= RateShove(Me, trunc(x) + LongWord(10*hwSignf(Targ.X - x)), trunc(y), 15, 30, 115, hwSign(Me^.dX)*0.353, -0.353, 1);
 if valueResult <= 0 then
     valueResult:= BadTurn
 else
@@ -650,7 +655,7 @@
 end;
 
 function TestFirePunch(Me: PGear; Targ: TPoint; Level: LongInt; var ap: TAttackParams): LongInt;
-var i, val1, val2, t: LongInt;
+var val1: LongInt;
     x, y: real;
 begin
 Level:= Level; // avoid compiler hint
@@ -665,12 +670,13 @@
     begin
 // TODO - find out WTH this works.
     if TestColl(trunc(x), trunc(y) - 16, 6) and 
-       (RateShove(Me, trunc(x) + 10 * hwSign(Me^.dX), 
+       (RateShove(Me, trunc(x) + LongWord(10 * hwSign(Me^.dX)), 
                       trunc(y) - 40, 30, 30, 40, hwSign(Me^.dX)*0.45, -0.9,  1) = 0) then
         val1:= Succ(BadTurn)
     else
         val1:= BadTurn;
-    exit(val1)
+    TestFirePunch:= val1;
+    exit;
     end;
 (*
 For some silly reason, having this enabled w/ the AI 
@@ -714,17 +720,18 @@
 or (Abs(trunc(y) - 50 - Targ.Y) > 50) then
     begin
     if TestColl(trunc(x), trunc(y) - 16, 6)
-    and (RateShove(Me, trunc(x) + 10 * hwSign(Me^.dX), trunc(y) - 40, 30, 30, 40, hwSign(Me^.dX), -0.8,  1) = 0) then
+    and (RateShove(Me, trunc(x) + LongWord(10 * hwSign(Me^.dX)), trunc(y) - 40, 30, 30, 40, hwSign(Me^.dX), -0.8,  1) = 0) then
         valueResult:= Succ(BadTurn)
     else
         valueResult:= BadTurn;
-    exit(valueResult)
+    TestWhip:= valueResult;
+    exit;
     end;
 
 valueResult:= 0;
 for i:= 0 to 4 do
-    valueResult:= valueResult + RateShove(Me, trunc(x) + 10 * hwSign(Targ.X - x),
-                                    trunc(y) - 20 * i - 5, 10, 30, 40, hwSign(Me^.dX), -0.8, 1);
+    valueResult:= valueResult + RateShove(Me, trunc(x) + LongWord(10 * hwSignf(Targ.X - x)),
+                                    trunc(y) - LongWord(20 * i) - 5, 10, 30, 40, hwSign(Me^.dX), -0.8, 1);
 if valueResult <= 0 then
     valueResult:= BadTurn
 else
@@ -762,7 +769,10 @@
 ap.ExplR:= 0;
 ap.Time:= 0;
 if (Level > 3) then
-    exit(BadTurn);
+begin
+    TestAirAttack:= BadTurn;
+    exit;
+end;
 
 ap.AttackPutX:= Targ.X;
 ap.AttackPutY:= Targ.Y;
@@ -790,10 +800,10 @@
         if b[i] then
             begin
             fexit:= false;
-            if TestColl(trunc(X) + i * 30, trunc(Y), 4) then
+            if TestColl(trunc(X) + LongWord(i * 30), trunc(Y), 4) then
                 begin
                 b[i]:= false;
-                dmg[i]:= RateExplosion(Me, trunc(X) + i * 30, trunc(Y), 58)
+                dmg[i]:= RateExplosion(Me, trunc(X) + LongWord(i * 30), trunc(Y), 58)
                 // 58 (instead of 60) for better prediction (hh moves after explosion of one of the rockets)
                 end
             end;
@@ -826,8 +836,9 @@
     maxTop: longword;
 begin
     TestTeleport := BadTurn;
+    exit;
     Level:= Level; // avoid compiler hint
-    FillBonuses(true, [gtCase]);
+    //FillBonuses(true, [gtCase]);
     if bonuses.Count = 0 then
         begin
         if Me^.Health <= 100  then
--- a/hedgewars/uAIMisc.pas	Sun Apr 01 15:23:34 2012 +0200
+++ b/hedgewars/uAIMisc.pas	Wed May 02 23:53:45 2012 +0200
@@ -1,6 +1,6 @@
 (*
  * Hedgewars, a free turn based strategy game
- * Copyright (c) 2005-2012 Andrey Korotaev <unC0Rr@gmail.com>
+ * Copyright (c) 2004-2012 Andrey Korotaev <unC0Rr@gmail.com>
  *
  * This program is free software; you can redistribute it and/or modify
  * it under the terms of the GNU General Public License as published by
@@ -48,18 +48,22 @@
 procedure freeModule;
 
 procedure FillTargets;
-procedure FillBonuses(isAfterAttack: boolean; filter: TGearsType = []);
+procedure FillBonuses(isAfterAttack: boolean);
 procedure AwareOfExplosion(x, y, r: LongInt); inline;
-function RatePlace(Gear: PGear): LongInt;
-function TestCollExcludingMe(Me: PGear; x, y, r: LongInt): boolean; inline;
-function TestColl(x, y, r: LongInt): boolean; inline;
-function TraceShoveFall(Me: PGear; x, y, dX, dY: Real): LongInt;
-function RateExplosion(Me: PGear; x, y, r: LongInt; Flags: LongWord = 0): LongInt;
-function RateShove(Me: PGear; x, y, r, power, kick: LongInt; gdX, gdY: real; Flags: LongWord): LongInt;
-function RateShotgun(Me: PGear; gdX, gdY: real; x, y: LongInt): LongInt;
-function RateHammer(Me: PGear): LongInt;
-function HHGo(Gear, AltGear: PGear; var GoInfo: TGoInfo): boolean;
-function AIrndSign(num: LongInt): LongInt;
+
+function  RatePlace(Gear: PGear): LongInt;
+function  TestColl(x, y, r: LongInt): boolean; inline;
+function  TestCollExcludingMe(Me: PGear; x, y, r: LongInt): boolean; inline;
+function  TraceShoveFall(Me: PGear; x, y, dX, dY: Real): LongInt;
+
+function  RateExplosion(Me: PGear; x, y, r: LongInt): LongInt; inline;
+function  RateExplosion(Me: PGear; x, y, r: LongInt; Flags: LongWord): LongInt;
+function  RateShove(Me: PGear; x, y, r, power, kick: LongInt; gdX, gdY: real; Flags: LongWord): LongInt;
+function  RateShotgun(Me: PGear; gdX, gdY: real; x, y: LongInt): LongInt;
+function  RateHammer(Me: PGear): LongInt;
+
+function  HHGo(Gear, AltGear: PGear; var GoInfo: TGoInfo): boolean;
+function  AIrndSign(num: LongInt): LongInt;
 
 var ThinkingHH: PGear;
     Targets: TTargets;
@@ -126,7 +130,7 @@
 TryDo(bonuses.Count <= MAXBONUS, 'Bonuses overflow', true)
 end;
 
-procedure FillBonuses(isAfterAttack: boolean; filter: TGearsType);
+procedure FillBonuses(isAfterAttack: boolean);
 var Gear: PGear;
     MyClan: PClan;
 begin
@@ -135,7 +139,6 @@
 Gear:= GearsList;
 while Gear <> nil do
     begin
-    if (filter = []) or (Gear^.Kind in filter) then
         case Gear^.Kind of
             gtCase:
             AddBonus(hwRound(Gear^.X), hwRound(Gear^.Y), 33, 25);
@@ -179,11 +182,11 @@
         AddBonus(X, Y, Radius + 10, -Radius);
 end;
 
-procedure AwareOfExplosion(x, y, r: LongInt);
+procedure AwareOfExplosion(x, y, r: LongInt); inline;
 begin
-KnownExplosion.X:= x;
-KnownExplosion.Y:= y;
-KnownExplosion.Radius:= r
+    KnownExplosion.X:= x;
+    KnownExplosion.Y:= y;
+    KnownExplosion.Radius:= r
 end;
 
 function RatePlace(Gear: PGear): LongInt;
@@ -210,54 +213,67 @@
 
 // Wrapper to test various approaches.  If it works reasonably, will just replace.
 // Right now, converting to hwFloat is a tad inefficient since the x/y were hwFloat to begin with...
-function TestCollExcludingMe(Me: PGear; x, y, r: LongInt): boolean;
+function TestCollExcludingMe(Me: PGear; x, y, r: LongInt): boolean; inline;
 var MeX, MeY: LongInt;
 begin
+    TestCollExcludingMe:= false;
     if ((x and LAND_WIDTH_MASK) = 0) and ((y and LAND_HEIGHT_MASK) = 0) then
-        begin
+    begin
         MeX:= hwRound(Me^.X);
         MeY:= hwRound(Me^.Y);
         // We are still inside the hog. Skip radius test
         if ((((x-MeX)*(x-MeX)) + ((y-MeY)*(y-MeY))) < 256) and ((Land[y, x] and $FF00) = 0) then
-            exit(false);
-        end;
-    exit(TestColl(x, y, r))
+            exit;
+    end;
+    TestCollExcludingMe:= TestColl(x, y, r)
 end;
 
-function TestColl(x, y, r: LongInt): boolean;
+function TestColl(x, y, r: LongInt): boolean; inline;
 var b: boolean;
 begin
-b:= (((x-r) and LAND_WIDTH_MASK) = 0)and(((y-r) and LAND_HEIGHT_MASK) = 0) and (Land[y-r, x-r] <> 0);
-if b then
-    exit(true);
+    TestColl:= true;
+
+    b:= (((x-r) and LAND_WIDTH_MASK) = 0) and (((y-r) and LAND_HEIGHT_MASK) = 0) and (Land[y-r, x-r] <> 0);
+    if b then
+        exit;
+    
+    b:= (((x-r) and LAND_WIDTH_MASK) = 0) and (((y+r) and LAND_HEIGHT_MASK) = 0) and (Land[y+r, x-r] <> 0);
+    if b then
+        exit;
     
-b:=(((x-r) and LAND_WIDTH_MASK) = 0)and(((y+r) and LAND_HEIGHT_MASK) = 0) and (Land[y+r, x-r] <> 0);
-if b then
-    exit(true);
+    b:= (((x+r) and LAND_WIDTH_MASK) = 0) and (((y-r) and LAND_HEIGHT_MASK) = 0) and (Land[y-r, x+r] <> 0);
+    if b then
+        exit;
     
-b:=(((x+r) and LAND_WIDTH_MASK) = 0)and(((y-r) and LAND_HEIGHT_MASK) = 0) and (Land[y-r, x+r] <> 0);
-if b then
-    exit(true);
+    b:= (((x+r) and LAND_WIDTH_MASK) = 0) and (((y+r) and LAND_HEIGHT_MASK) = 0) and (Land[y+r, x+r] <> 0);
+    if b then
+        exit;
     
-TestColl:=(((x+r) and LAND_WIDTH_MASK) = 0)and(((y+r) and LAND_HEIGHT_MASK) = 0) and (Land[y+r, x+r] <> 0)
+    TestColl:= false;
 end;
 
 function TestCollWithLand(x, y, r: LongInt): boolean; inline;
 var b: boolean;
 begin
-b:= (((x-r) and LAND_WIDTH_MASK) = 0)and(((y-r) and LAND_HEIGHT_MASK) = 0) and (Land[y-r, x-r] > 255);
-if b then
-    exit(true);
+    TestCollWithLand:= true;
     
-b:=(((x-r) and LAND_WIDTH_MASK) = 0)and(((y+r) and LAND_HEIGHT_MASK) = 0) and (Land[y+r, x-r] > 255);
-if b then
-    exit(true);
-    
-b:=(((x+r) and LAND_WIDTH_MASK) = 0)and(((y-r) and LAND_HEIGHT_MASK) = 0) and (Land[y-r, x+r] > 255);
-if b then
-    exit(true);
-    
-TestCollWithLand:=(((x+r) and LAND_WIDTH_MASK) = 0) and (((y+r) and LAND_HEIGHT_MASK) = 0) and (Land[y+r, x+r] > 255)
+    b:= (((x-r) and LAND_WIDTH_MASK) = 0) and (((y-r) and LAND_HEIGHT_MASK) = 0) and (Land[y-r, x-r] > 255);
+    if b then
+        exit;
+        
+    b:= (((x-r) and LAND_WIDTH_MASK) = 0) and (((y+r) and LAND_HEIGHT_MASK) = 0) and (Land[y+r, x-r] > 255);
+    if b then
+        exit;
+        
+    b:= (((x+r) and LAND_WIDTH_MASK) = 0) and (((y-r) and LAND_HEIGHT_MASK) = 0) and (Land[y-r, x+r] > 255);
+    if b then
+        exit;
+        
+    b:= (((x+r) and LAND_WIDTH_MASK) = 0) and (((y+r) and LAND_HEIGHT_MASK) = 0) and (Land[y+r, x+r] > 255);
+    if b then
+        exit;
+
+    TestCollWithLand:= false;
 end;
 
 function TraceFall(eX, eY: LongInt; x, y, dX, dY: Real; r: LongWord): LongInt;
@@ -271,48 +287,73 @@
     // ok. attempt approximate search for an unbroken trajectory into water.  if it continues far enough, assume out of map
     rCorner:= r * 0.75;
     while true do
-        begin
+    begin
         x:= x + dX;
         y:= y + dY;
         dY:= dY + cGravityf;
         skipLandCheck:= skipLandCheck and (r <> 0) and (abs(eX-x) + abs(eY-y) < r) and ((abs(eX-x) < rCorner) or (abs(eY-y) < rCorner));
         if not skipLandCheck and TestCollWithLand(trunc(x), trunc(y), cHHRadius) then
-            begin
+        begin
             if 0.4 < dY then
-                begin
+            begin
                 dmg := 1 + trunc((abs(dY) - 0.4) * 70);
-                if dmg >= 1 then exit(dmg)
+                if dmg >= 1 then
+                begin
+                    TraceFall:= dmg;
+                    exit
                 end;
-            exit(0)
             end;
-        if (y > cWaterLine) or (x > 4096) or (x < 0) then exit(-1); // returning -1 for drowning so it can be considered in the Rate routine
+            TraceFall:= 0;
+            exit
         end;
+        if (y > cWaterLine) or (x > 4096) or (x < 0) then
+        begin
+            // returning -1 for drowning so it can be considered in the Rate routine
+            TraceFall:= -1;
+            exit;
+        end;
+    end;
 end;
 
 function TraceShoveFall(Me: PGear; x, y, dX, dY: Real): LongInt;
 var dmg: LongInt;
 begin
     while true do
-        begin
+    begin
         x:= x + dX;
         y:= y + dY;
         dY:= dY + cGravityf;
         // consider adding dX/dY calc here for fall damage
         if TestCollExcludingMe(Me, trunc(x), trunc(y), cHHRadius) then
-            begin
+        begin
             if 0.4 < dY then
-                begin
+            begin
                 dmg := 1 + trunc((abs(dY) - 0.4) * 70);
-                if dmg >= 1 then exit(dmg)
+                if dmg >= 1 then
+                begin
+                    TraceShoveFall:= dmg;
+                    exit
                 end;
-            exit(0)
             end;
-        if (y > cWaterLine) or (x > 4096) or (x < 0) then exit(-1); // returning -1 for drowning so it can be considered in the Rate routine
+            TraceShoveFall:= 0;
+            exit
         end;
+        if (y > cWaterLine) or (x > 4096) or (x < 0) then
+        begin
+            // returning -1 for drowning so it can be considered in the Rate routine
+            TraceShoveFall:= -1;
+            exit;
+        end;
+    end;
 end;
 
 // Flags are not defined yet but 1 for checking drowning and 2 for assuming land erasure.
-function RateExplosion(Me: PGear; x, y, r: LongInt; Flags: LongWord = 0): LongInt;
+function RateExplosion(Me: PGear; x, y, r: LongInt): LongInt;
+begin
+    RateExplosion:= RateExplosion(Me, x, y, r, 0);
+end;
+
+function RateExplosion(Me: PGear; x, y, r: LongInt; Flags: LongWord): LongInt;
 var i, fallDmg, dmg, dmgBase, rate, erasure: LongInt;
     dX, dY, dmgMod: real;
 begin
@@ -487,95 +528,95 @@
 
 function HHJump(Gear: PGear; JumpType: TJumpType; var GoInfo: TGoInfo): boolean;
 var bX, bY: LongInt;
-    bRes: boolean;
 begin
-bRes:= false;
+HHJump:= false;
 GoInfo.Ticks:= 0;
 GoInfo.JumpType:= jmpNone;
 bX:= hwRound(Gear^.X);
 bY:= hwRound(Gear^.Y);
 case JumpType of
-    jmpNone:
-    exit(bRes);
+    jmpNone: exit;
     
     jmpHJump:
-    if TestCollisionYwithGear(Gear, -1) = 0 then
+        if TestCollisionYwithGear(Gear, -1) = 0 then
         begin
-        Gear^.dY:= -_0_2;
-        SetLittle(Gear^.dX);
-        Gear^.State:= Gear^.State or gstMoving or gstHHJumping;
+            Gear^.dY:= -_0_2;
+            SetLittle(Gear^.dX);
+            Gear^.State:= Gear^.State or gstMoving or gstHHJumping;
         end
     else
-        exit(bRes);
+        exit;
         
     jmpLJump:
-    begin
-    if TestCollisionYwithGear(Gear, -1) <> 0 then
-          if not TestCollisionXwithXYShift(Gear, _0, -2, hwSign(Gear^.dX)) then
-            Gear^.Y:= Gear^.Y - int2hwFloat(2)
-        else
-            if not TestCollisionXwithXYShift(Gear, _0, -1, hwSign(Gear^.dX)) then
-                Gear^.Y:= Gear^.Y - _1;
-        if not (TestCollisionXwithGear(Gear, hwSign(Gear^.dX))
-        or (TestCollisionYwithGear(Gear, -1) <> 0)) then
+        begin
+            if TestCollisionYwithGear(Gear, -1) <> 0 then
+                if not TestCollisionXwithXYShift(Gear, _0, -2, hwSign(Gear^.dX)) then
+                    Gear^.Y:= Gear^.Y - int2hwFloat(2)
+                else
+                    if not TestCollisionXwithXYShift(Gear, _0, -1, hwSign(Gear^.dX)) then
+                        Gear^.Y:= Gear^.Y - _1;
+            if not (TestCollisionXwithGear(Gear, hwSign(Gear^.dX)) or
+               (TestCollisionYwithGear(Gear, -1) <> 0)) then
             begin
-            Gear^.dY:= -_0_15;
-            Gear^.dX:= SignAs(_0_15, Gear^.dX);
-            Gear^.State:= Gear^.State or gstMoving or gstHHJumping
+                Gear^.dY:= -_0_15;
+                Gear^.dX:= SignAs(_0_15, Gear^.dX);
+                Gear^.State:= Gear^.State or gstMoving or gstHHJumping
             end
         else
-            exit(bRes)
-    end
-    end;
+            exit
+        end
+end;
 
 repeat
     if not (hwRound(Gear^.Y) + cHHRadius < cWaterLine) then
-        exit(bRes);
+        exit;
     if (Gear^.State and gstMoving) <> 0 then
-        begin
+    begin
         if (GoInfo.Ticks = 350) then
             if (not (hwAbs(Gear^.dX) > cLittle)) and (Gear^.dY < -_0_02) then
-                begin
+            begin
                 Gear^.dY:= -_0_25;
                 Gear^.dX:= SignAs(_0_02, Gear^.dX)
-                end;
-    if TestCollisionXwithGear(Gear, hwSign(Gear^.dX)) then SetLittle(Gear^.dX);
-        Gear^.X:= Gear^.X + Gear^.dX;
-    inc(GoInfo.Ticks);
-    Gear^.dY:= Gear^.dY + cGravity;
-    if Gear^.dY > _0_4 then
-        exit(bRes);
-    if (Gear^.dY.isNegative)and (TestCollisionYwithGear(Gear, -1) <> 0) then
-        Gear^.dY:= _0;
-    Gear^.Y:= Gear^.Y + Gear^.dY;
-    if (not Gear^.dY.isNegative)and (TestCollisionYwithGear(Gear, 1) <> 0) then
+            end;
+        if TestCollisionXwithGear(Gear, hwSign(Gear^.dX)) then SetLittle(Gear^.dX);
+            Gear^.X:= Gear^.X + Gear^.dX;
+        inc(GoInfo.Ticks);
+        Gear^.dY:= Gear^.dY + cGravity;
+        if Gear^.dY > _0_4 then
+            exit;
+        if (Gear^.dY.isNegative) and (TestCollisionYwithGear(Gear, -1) <> 0) then
+            Gear^.dY:= _0;
+        Gear^.Y:= Gear^.Y + Gear^.dY;
+        if (not Gear^.dY.isNegative) and (TestCollisionYwithGear(Gear, 1) <> 0) then
         begin
-        Gear^.State:= Gear^.State and not (gstMoving or gstHHJumping);
-        Gear^.dY:= _0;
-        case JumpType of
-            jmpHJump:
-            if bY - hwRound(Gear^.Y) > 5 then
-                begin
-                bRes:= true;
-                GoInfo.JumpType:= jmpHJump;
-                inc(GoInfo.Ticks, 300 + 300) // 300 before jump, 300 after
-                end;
-            jmpLJump: if abs(bX - hwRound(Gear^.X)) > 30 then
-                begin
-                bRes:= true;
-                GoInfo.JumpType:= jmpLJump;
-                inc(GoInfo.Ticks, 300 + 300) // 300 before jump, 300 after
-                end
-                end;
-            exit(bRes)
+            Gear^.State:= Gear^.State and not (gstMoving or gstHHJumping);
+            Gear^.dY:= _0;
+            case JumpType of
+                jmpHJump:
+                    if bY - hwRound(Gear^.Y) > 5 then
+                    begin
+                        HHJump:= true;
+                        GoInfo.JumpType:= jmpHJump;
+                        inc(GoInfo.Ticks, 300 + 300) // 300 before jump, 300 after
+                    end;
+                jmpLJump:
+                    if abs(bX - hwRound(Gear^.X)) > 30 then
+                    begin
+                        HHJump:= true;
+                        GoInfo.JumpType:= jmpLJump;
+                        inc(GoInfo.Ticks, 300 + 300) // 300 before jump, 300 after
+                    end
             end;
+            exit
         end;
+    end;
 until false
 end;
 
 function HHGo(Gear, AltGear: PGear; var GoInfo: TGoInfo): boolean;
 var pX, pY: LongInt;
 begin
+HHGo:= false;
 AltGear^:= Gear^;
 
 GoInfo.Ticks:= 0;
@@ -585,7 +626,7 @@
 pX:= hwRound(Gear^.X);
 pY:= hwRound(Gear^.Y);
 if pY + cHHRadius >= cWaterLine then
-    exit(false);
+    exit;
 if (Gear^.State and gstMoving) <> 0 then
     begin
     inc(GoInfo.Ticks);
@@ -594,7 +635,7 @@
         begin
         Goinfo.FallPix:= 0;
         HHJump(AltGear, jmpLJump, GoInfo); // try ljump instead of fall with damage
-        exit(false)
+        exit
         end;
     Gear^.Y:= Gear^.Y + Gear^.dY;
     if hwRound(Gear^.Y) > pY then
@@ -605,7 +646,8 @@
         Gear^.State:= Gear^.State and not (gstMoving or gstHHJumping);
         Gear^.dY:= _0;
         HHJump(AltGear, jmpLJump, GoInfo); // try ljump instead of fall
-        exit(true)
+        HHGo:= true;
+        exit
         end;
     continue
     end;
@@ -613,9 +655,9 @@
         Gear^.dX:= -cLittle
     else
         if (Gear^.Message and gmRight )<>0 then
-             Gear^.dX:=  cLittle
+            Gear^.dX:=  cLittle
         else
-                exit(false);
+            exit;
     if TestCollisionXwithGear(Gear, hwSign(Gear^.dX)) then
         begin
         if not (TestCollisionXwithXYShift(Gear, _0, -6, hwSign(Gear^.dX))
@@ -643,17 +685,18 @@
         end;
 
     if not TestCollisionXwithGear(Gear, hwSign(Gear^.dX)) then
-        begin
+    begin
         Gear^.X:= Gear^.X + int2hwFloat(hwSign(Gear^.dX));
         inc(GoInfo.Ticks, cHHStepTicks)
-        end;
-        
+    end;
+
+    // too scared to reformat this part
     if TestCollisionYwithGear(Gear, 1) = 0 then
         begin
         Gear^.Y:= Gear^.Y + _1;
         
     if TestCollisionYwithGear(Gear, 1) = 0 then
-          begin
+        begin
         Gear^.Y:= Gear^.Y + _1;
         
     if TestCollisionYwithGear(Gear, 1) = 0 then
@@ -685,10 +728,12 @@
     end
     end;
 if (pX <> hwRound(Gear^.X)) and ((Gear^.State and gstMoving) = 0) then
-    exit(true);
+begin
+    HHGo:= true;
+    exit;
+end;
 until (pX = hwRound(Gear^.X)) and (pY = hwRound(Gear^.Y)) and ((Gear^.State and gstMoving) = 0);
 HHJump(AltGear, jmpHJump, GoInfo);
-HHGo:= false;
 end;
 
 function AIrndSign(num: LongInt): LongInt;
--- a/hedgewars/uAmmos.pas	Sun Apr 01 15:23:34 2012 +0200
+++ b/hedgewars/uAmmos.pas	Wed May 02 23:53:45 2012 +0200
@@ -26,13 +26,13 @@
 procedure freeModule;
 
 procedure AddAmmoStore;
-procedure SetAmmoLoadout(s: shortstring);
-procedure SetAmmoProbability(s: shortstring);
-procedure SetAmmoDelay(s: shortstring);
-procedure SetAmmoReinforcement(s: shortstring);
+procedure SetAmmoLoadout(var s: shortstring);
+procedure SetAmmoProbability(var s: shortstring);
+procedure SetAmmoDelay(var s: shortstring);
+procedure SetAmmoReinforcement(var s: shortstring);
 procedure AssignStores;
 procedure AddAmmo(var Hedgehog: THedgehog; ammo: TAmmoType);
-procedure AddAmmo(var Hedgehog: THedgehog; ammo: TAmmoType; cnt: LongWord);
+procedure SetAmmo(var Hedgehog: THedgehog; ammo: TAmmoType; cnt: LongWord);
 function  HHHasAmmo(var Hedgehog: THedgehog; Ammo: TAmmoType): LongWord;
 procedure PackAmmo(Ammo: PHHAmmo; Slot: LongInt);
 procedure OnUsedAmmo(var Hedgehog: THedgehog);
@@ -43,7 +43,7 @@
 procedure DisableSomeWeapons;
 procedure ResetWeapons;
 function  GetAmmoByNum(num: Longword): PHHAmmo;
-function  GetAmmoEntry(var Hedgehog: THedgehog): PAmmo;
+function  GetCurAmmoEntry(var Hedgehog: THedgehog): PAmmo;
 function  GetAmmoEntry(var Hedgehog: THedgehog; am: TAmmoType): PAmmo;
 
 var StoreCnt: Longword;
@@ -145,13 +145,13 @@
 
 function GetAmmoByNum(num: Longword): PHHAmmo;
 begin
-TryDo(num < StoreCnt, 'Invalid store number', true);
-exit(StoresList[num])
+    TryDo(num < StoreCnt, 'Invalid store number', true);
+    GetAmmoByNum:= StoresList[num]
 end;
 
-function GetAmmoEntry(var Hedgehog: THedgehog): PAmmo;
+function GetCurAmmoEntry(var Hedgehog: THedgehog): PAmmo;
 begin
-GetAmmoEntry:= GetAmmoEntry(Hedgehog, Hedgehog.CurAmmoType)
+    GetCurAmmoEntry:= GetAmmoEntry(Hedgehog, Hedgehog.CurAmmoType)
 end;
 
 function GetAmmoEntry(var Hedgehog: THedgehog; am: TAmmoType): PAmmo;
@@ -200,11 +200,11 @@
 if (cnt <> AMMO_INFINITE) then
     begin
     inc(cnt, Ammoz[ammo].NumberInCase);
-    AddAmmo(Hedgehog, ammo, cnt)
+    SetAmmo(Hedgehog, ammo, cnt)
     end
 end;
 
-procedure AddAmmo(var Hedgehog: THedgehog; ammo: TAmmoType; cnt: LongWord);
+procedure SetAmmo(var Hedgehog: THedgehog; ammo: TAmmoType; cnt: LongWord);
 var ammos: TAmmoCounts;
     slot, ami: LongInt;
     hhammo: PHHAmmo;
@@ -224,7 +224,7 @@
 if ammos[ammo] > AMMO_INFINITE then ammos[ammo]:= AMMO_INFINITE;
 
 FillAmmoStore(hhammo, ammos);
-CurWeapon:= GetAmmoEntry(Hedgehog);
+CurWeapon:= GetCurAmmoEntry(Hedgehog);
 with Hedgehog, CurWeapon^ do
     if (Count = 0) or (AmmoType = amNothing) then
         begin
@@ -258,7 +258,7 @@
 procedure OnUsedAmmo(var Hedgehog: THedgehog);
 var CurWeapon: PAmmo;
 begin
-CurWeapon:= GetAmmoEntry(Hedgehog);
+CurWeapon:= GetCurAmmoEntry(Hedgehog);
 with Hedgehog do
     begin
 
@@ -280,18 +280,21 @@
 function  HHHasAmmo(var Hedgehog: THedgehog; Ammo: TAmmoType): LongWord;
 var slot, ami: LongInt;
 begin
-Slot:= Ammoz[Ammo].Slot;
-ami:= 0;
-while (ami <= cMaxSlotAmmoIndex) do
-        begin
+    HHHasAmmo:= 0;
+    Slot:= Ammoz[Ammo].Slot;
+    ami:= 0;
+    while (ami <= cMaxSlotAmmoIndex) do
+    begin
         with Hedgehog.Ammo^[Slot, ami] do
             if (AmmoType = Ammo) then
                 if Hedgehog.Team^.Clan^.TurnNumber > Ammoz[AmmoType].SkipTurns then
-                    exit(Count)
-                else exit(0);
-      inc(ami)
-      end;
-HHHasAmmo:= 0
+                begin
+                    HHHasAmmo:= Count;
+                    exit;
+                end
+                else exit;
+        inc(ami)
+    end;
 end;
 
 procedure ApplyAngleBounds(var Hedgehog: THedgehog; AmmoType: TAmmoType);
@@ -352,14 +355,14 @@
     begin
     Timer:= 10;
 
-    CurWeapon:= GetAmmoEntry(Hedgehog);
+    CurWeapon:= GetCurAmmoEntry(Hedgehog);
 
     if (CurWeapon^.Count = 0) then
         SwitchToFirstLegalAmmo(Hedgehog)
     else if CurWeapon^.AmmoType = amNothing then
         Hedgehog.CurAmmoType:= amNothing;
 
-    CurWeapon:= GetAmmoEntry(Hedgehog);
+    CurWeapon:= GetCurAmmoEntry(Hedgehog);
 
     ApplyAngleBounds(Hedgehog, CurWeapon^.AmmoType);
 
@@ -421,22 +424,22 @@
         Ammoz[t].Probability:= 0
 end;
 
-procedure SetAmmoLoadout(s: shortstring);
+procedure SetAmmoLoadout(var s: shortstring);
 begin
     ammoLoadout:= s;
 end;
 
-procedure SetAmmoProbability(s: shortstring);
+procedure SetAmmoProbability(var s: shortstring);
 begin
     ammoProbability:= s;
 end;
 
-procedure SetAmmoDelay(s: shortstring);
+procedure SetAmmoDelay(var s: shortstring);
 begin
     ammoDelay:= s;
 end;
 
-procedure SetAmmoReinforcement(s: shortstring);
+procedure SetAmmoReinforcement(var s: shortstring);
 begin
     ammoReinforcement:= s;
 end;
@@ -470,11 +473,11 @@
 procedure initModule;
 var i: Longword;
 begin
-    RegisterVariable('ammloadt', vtCommand, @SetAmmoLoadout, false);
-    RegisterVariable('ammdelay', vtCommand, @SetAmmoDelay, false);
-    RegisterVariable('ammprob',  vtCommand, @SetAmmoProbability, false);
-    RegisterVariable('ammreinf', vtCommand, @SetAmmoReinforcement, false);
-    RegisterVariable('ammstore', vtCommand, @chAddAmmoStore , false);
+    RegisterVariable('ammloadt', @SetAmmoLoadout, false);
+    RegisterVariable('ammdelay', @SetAmmoDelay, false);
+    RegisterVariable('ammprob',  @SetAmmoProbability, false);
+    RegisterVariable('ammreinf', @SetAmmoReinforcement, false);
+    RegisterVariable('ammstore', @chAddAmmoStore , false);
 
     StoreCnt:= 0;
     ammoLoadout:= '';
--- a/hedgewars/uCaptions.pas	Sun Apr 01 15:23:34 2012 +0200
+++ b/hedgewars/uCaptions.pas	Wed May 02 23:53:45 2012 +0200
@@ -90,7 +90,7 @@
         with Captions[grp] do
             if Tex <> nil then
                 begin
-                DrawCentered(0, offset, Tex);
+                DrawTextureCentered(0, offset, Tex);
                 inc(offset, Tex^.h + 2);
                 if EndTime <= RealTicks then
                     begin
--- a/hedgewars/uChat.pas	Sun Apr 01 15:23:34 2012 +0200
+++ b/hedgewars/uChat.pas	Wed May 02 23:53:45 2012 +0200
@@ -31,7 +31,7 @@
 procedure KeyPressChat(Key: Longword);
 
 implementation
-uses SDLh, uKeys, uTypes, uVariables, uCommands, uUtils, uTextures, uRender, uIO;
+uses SDLh, uInputHandler, uTypes, uVariables, uCommands, uUtils, uTextures, uRender, uIO;
 
 const MaxStrIndex = 27;
 
@@ -52,7 +52,8 @@
     ChatReady: boolean;
     showAll: boolean;
 
-const colors: array[#1..#6] of TSDL_Color = (
+const colors: array[#0..#6] of TSDL_Color = (
+    (r:$FF; g:$FF; b:$FF; unused:$FF), // unused, feel free to take it for anything
     (r:$FF; g:$FF; b:$FF; unused:$FF), // chat message [White]
     (r:$FF; g:$00; b:$FF; unused:$FF), // action message [Purple]
     (r:$90; g:$FF; b:$90; unused:$FF), // join/leave message [Lime]
@@ -272,7 +273,7 @@
 end;
 
 procedure KeyPressChat(Key: Longword);
-const firstByteMark: array[1..4] of byte = (0, $C0, $E0, $F0);
+const firstByteMark: array[0..3] of byte = (0, $C0, $E0, $F0);
 var i, btw: integer;
     utf8: shortstring;
 begin
@@ -322,7 +323,7 @@
         Key:= Key shr 6
         end;
 
-    utf8:= char(Key or firstByteMark[btw]) + utf8;
+    utf8:= char(Key or firstByteMark[Pred(btw)]) + utf8;
 
     if byte(InputStr.s[0]) + btw > 240 then
         exit;
@@ -361,7 +362,7 @@
 procedure chHistory(var s: shortstring);
 begin
     s:= s; // avoid compiler hint
-    uChat.showAll:= not uChat.showAll
+    showAll:= not showAll
 end;
 
 procedure chChat(var s: shortstring);
@@ -387,11 +388,11 @@
 procedure initModule;
 var i: ShortInt;
 begin
-    RegisterVariable('chatmsg', vtCommand, @chChatMessage, true);
-    RegisterVariable('say', vtCommand, @chSay, true);
-    RegisterVariable('team', vtCommand, @chTeamSay, true);
-    RegisterVariable('history', vtCommand, @chHistory, true );
-    RegisterVariable('chat', vtCommand, @chChat, true );
+    RegisterVariable('chatmsg', @chChatMessage, true);
+    RegisterVariable('say', @chSay, true);
+    RegisterVariable('team', @chTeamSay, true);
+    RegisterVariable('history', @chHistory, true );
+    RegisterVariable('chat', @chChat, true );
 
     lastStr:= 0;
     visibleCount:= 0;
--- a/hedgewars/uCollisions.pas	Sun Apr 01 15:23:34 2012 +0200
+++ b/hedgewars/uCollisions.pas	Wed May 02 23:53:45 2012 +0200
@@ -47,8 +47,10 @@
 function  TestCollisionX(Gear: PGear; Dir: LongInt): boolean;
 function  TestCollisionY(Gear: PGear; Dir: LongInt): boolean;
 
-function  TestCollisionXwithXYShift(Gear: PGear; ShiftX: hwFloat; ShiftY: LongInt; Dir: LongInt; withGear: boolean = true): boolean;
-function  TestCollisionYwithXYShift(Gear: PGear; ShiftX, ShiftY: LongInt; Dir: LongInt; withGear: boolean = true): boolean;
+function  TestCollisionXwithXYShift(Gear: PGear; ShiftX: hwFloat; ShiftY: LongInt; Dir: LongInt): boolean; inline;
+function  TestCollisionXwithXYShift(Gear: PGear; ShiftX: hwFloat; ShiftY: LongInt; Dir: LongInt; withGear: boolean): boolean;
+function  TestCollisionYwithXYShift(Gear: PGear; ShiftX, ShiftY: LongInt; Dir: LongInt): boolean; inline;
+function  TestCollisionYwithXYShift(Gear: PGear; ShiftX, ShiftY: LongInt; Dir: LongInt; withGear: boolean): boolean;
 
 function  TestRectancleForObstacle(x1, y1, x2, y2: LongInt; landOnly: boolean): boolean;
 
@@ -57,7 +59,7 @@
 function  CalcSlopeTangent(Gear: PGear; collisionX, collisionY: LongInt; var outDeltaX, outDeltaY: LongInt; TestWord: LongWord): Boolean;
 
 implementation
-uses uConsts, uLandGraphics, uVariables, uDebug, uGears, uGearsList;
+uses uConsts, uLandGraphics, uVariables, uDebug, uGearsList;
 
 type TCollisionEntry = record
     X, Y, Radius: LongInt;
@@ -153,6 +155,8 @@
     x:= x - Gear^.Radius
 else
     x:= x + Gear^.Radius;
+
+TestCollisionXwithGear:= true;
 if (x and LAND_WIDTH_MASK) = 0 then
     begin
     y:= hwRound(Gear^.Y) - Gear^.Radius + 1;
@@ -160,7 +164,7 @@
     repeat
         if (y and LAND_HEIGHT_MASK) = 0 then
             if Land[y, x] > TestWord then
-                exit(true);
+                exit;
         inc(y)
     until (y > i);
     end;
@@ -196,7 +200,10 @@
     repeat
         if (x and LAND_WIDTH_MASK) = 0 then
             if Land[y, x] > TestWord then
-                exit(Land[y, x]);
+            begin
+                TestCollisionYwithGear:= Land[y, x];
+                exit;
+            end;
      inc(x)
     until (x > i);
     end;
@@ -213,6 +220,8 @@
     x:= x - Gear^.Radius
 else
     x:= x + Gear^.Radius;
+
+TestCollisionXKick:= true;
 if (x and LAND_WIDTH_MASK) = 0 then
     begin
     y:= hwRound(Gear^.Y) - Gear^.Radius + 1;
@@ -220,7 +229,7 @@
     repeat
         if (y and LAND_HEIGHT_MASK) = 0 then
             if Land[y, x] > 255 then
-                exit(true)
+                exit
             else if Land[y, x] <> 0 then
                 flag:= true;
     inc(y)
@@ -255,7 +264,8 @@
                         Active:= true
                         end;
                     DeleteCI(cGear);
-                    exit(false)
+                    TestCollisionXKick:= false;
+                    exit;
                     end
     end
 end;
@@ -270,6 +280,8 @@
     y:= y - Gear^.Radius
 else
     y:= y + Gear^.Radius;
+
+TestCollisionYKick:= true;
 if (y and LAND_HEIGHT_MASK) = 0 then
     begin
     x:= hwRound(Gear^.X) - Gear^.Radius + 1;
@@ -278,7 +290,7 @@
     if (x and LAND_WIDTH_MASK) = 0 then
         if Land[y, x] > 0 then
             if Land[y, x] > 255 then
-                exit(true)
+                exit
             else if Land[y, x] <> 0 then
                 flag:= true;
     inc(x)
@@ -289,10 +301,8 @@
 if flag then
     begin
     if hwAbs(Gear^.dY) < cHHKick then
-        exit(true);
-    if (Gear^.State and gstHHJumping <> 0)
-    and (not Gear^.dY.isNegative)
-    and (Gear^.dY < _0_4) then
+        exit;
+    if (Gear^.State and gstHHJumping <> 0) and (not Gear^.dY.isNegative) and (Gear^.dY < _0_4) then
         exit;
 
     mx:= hwRound(Gear^.X);
@@ -313,12 +323,18 @@
                         Active:= true
                         end;
                     DeleteCI(cGear);
-                    exit(false)
+                    TestCollisionYKick:= false;
+                    exit
                     end
     end
 end;
 
-function TestCollisionXwithXYShift(Gear: PGear; ShiftX: hwFloat; ShiftY: LongInt; Dir: LongInt; withGear: boolean = true): boolean;
+function TestCollisionXwithXYShift(Gear: PGear; ShiftX: hwFloat; ShiftY: LongInt; Dir: LongInt): boolean; inline;
+begin
+    TestCollisionXwithXYShift:= TestCollisionXwithXYShift(Gear, ShiftX, ShiftY, Dir, true);
+end;
+
+function TestCollisionXwithXYShift(Gear: PGear; ShiftX: hwFloat; ShiftY: LongInt; Dir: LongInt; withGear: boolean): boolean;
 begin
 Gear^.X:= Gear^.X + ShiftX;
 Gear^.Y:= Gear^.Y + int2hwFloat(ShiftY);
@@ -328,6 +344,7 @@
 Gear^.X:= Gear^.X - ShiftX;
 Gear^.Y:= Gear^.Y - int2hwFloat(ShiftY)
 end;
+
 function TestCollisionX(Gear: PGear; Dir: LongInt): boolean;
 var x, y, i: LongInt;
 begin
@@ -336,6 +353,8 @@
     x:= x - Gear^.Radius
 else
     x:= x + Gear^.Radius;
+
+TestCollisionX:= true;
 if (x and LAND_WIDTH_MASK) = 0 then
     begin
     y:= hwRound(Gear^.Y) - Gear^.Radius + 1;
@@ -343,7 +362,7 @@
     repeat
         if (y and LAND_HEIGHT_MASK) = 0 then
             if Land[y, x] > 255 then
-                exit(true);
+                exit;
     inc(y)
     until (y > i);
     end;
@@ -358,6 +377,8 @@
     y:= y - Gear^.Radius
 else
     y:= y + Gear^.Radius;
+
+TestCollisionY:= true;
 if (y and LAND_HEIGHT_MASK) = 0 then
     begin
     x:= hwRound(Gear^.X) - Gear^.Radius + 1;
@@ -365,14 +386,19 @@
     repeat
         if (x and LAND_WIDTH_MASK) = 0 then
             if Land[y, x] > 255 then
-                exit(true);
+                exit;
     inc(x)
     until (x > i);
     end;
 TestCollisionY:= false
 end;
 
-function TestCollisionYwithXYShift(Gear: PGear; ShiftX, ShiftY: LongInt; Dir: LongInt; withGear: boolean = true): boolean;
+function TestCollisionYwithXYShift(Gear: PGear; ShiftX, ShiftY: LongInt; Dir: LongInt): boolean; inline;
+begin
+    TestCollisionYwithXYShift:= TestCollisionYwithXYShift(Gear, ShiftX, ShiftY, Dir, true);
+end;
+
+function TestCollisionYwithXYShift(Gear: PGear; ShiftX, ShiftY: LongInt; Dir: LongInt; withGear: boolean): boolean;
 begin
 Gear^.X:= Gear^.X + int2hwFloat(ShiftX);
 Gear^.Y:= Gear^.Y + int2hwFloat(ShiftY);
@@ -390,33 +416,34 @@
 var x, y: LongInt;
     TestWord: LongWord;
 begin
+TestRectancleForObstacle:= true;
+
 if landOnly then
     TestWord:= 255
 else
     TestWord:= 0;
 
 if x1 > x2 then
-    begin
+begin
     x  := x1;
     x1 := x2;
     x2 := x;
-  end;
+end;
 
 if y1 > y2 then
-    begin
+begin
     y  := y1;
     y1 := y2;
     y2 := y;
-  end;
+end;
 
 if (hasBorder and ((y1 < 0) or (x1 < 0) or (x2 > LAND_WIDTH))) then
-    exit(true);
+    exit;
 
 for y := y1 to y2 do
     for x := x1 to x2 do
-        if ((y and LAND_HEIGHT_MASK) = 0) and ((x and LAND_WIDTH_MASK) = 0)
-        and (Land[y, x] > TestWord) then
-            exit(true);
+        if ((y and LAND_HEIGHT_MASK) = 0) and ((x and LAND_WIDTH_MASK) = 0) and (Land[y, x] > TestWord) then
+            exit;
 
 TestRectancleForObstacle:= false
 end;
@@ -430,6 +457,8 @@
     isColl: Boolean;
 
 begin
+    CalcSlopeTangent:= false;
+
     dx:= Gear^.dX;
     dy:= Gear^.dY;
 
@@ -554,11 +583,11 @@
     ldy:= rdy - ldy;
 
     if ((ldx = 0) and (ldy = 0)) then
-        EXIT(false);
+        exit;
 
 outDeltaX:= ldx;
 outDeltaY:= ldy;
-exit(true);
+CalcSlopeTangent:= true;
 end;
 
 function CalcSlopeBelowGear(Gear: PGear): hwFloat;
--- a/hedgewars/uCommandHandlers.pas	Sun Apr 01 15:23:34 2012 +0200
+++ b/hedgewars/uCommandHandlers.pas	Wed May 02 23:53:45 2012 +0200
@@ -41,7 +41,6 @@
 end;
 
 procedure chQuit(var s: shortstring);
-const prevGState: TGameState = gsConfirm;
 begin
     s:= s; // avoid compiler hint
     if (GameState = gsGame) or (GameState = gsChat) then
@@ -659,90 +658,191 @@
     ZoomValue:= cDefaultZoomLevel;
 end;
 
+procedure chMapGen(var s: shortstring);
+begin
+val(s, cMapGen)
+end;
+
+procedure chTemplateFilter(var s: shortstring);
+begin
+val(s, cTemplateFilter)
+end;
+
+procedure chInactDelay(var s: shortstring);
+begin
+val(s, cInactDelay)
+end;
+
+procedure chReadyDelay(var s: shortstring);
+begin
+val(s, cReadyDelay)
+end;
+
+procedure chCaseFactor(var s: shortstring);
+begin
+val(s, cCaseFactor)
+end;
+
+procedure chHealthCaseProb(var s: shortstring);
+begin
+val(s, cHealthCaseProb)
+end;
+
+procedure chHealthCaseAmount(var s: shortstring);
+begin
+val(s, cHealthCaseAmount)
+end;
+
+procedure chSuddenDTurns(var s: shortstring);
+begin
+val(s, cSuddenDTurns)
+end;
+
+procedure chWaterRise(var s: shortstring);
+begin
+val(s, cWaterRise)
+end;
+
+procedure chHealthDecrease(var s: shortstring);
+begin
+val(s, cHealthDecrease)
+end;
+
+procedure chDamagePercent(var s: shortstring);
+begin
+val(s, cDamagePercent)
+end;
+
+procedure chRopePercent(var s: shortstring);
+begin
+val(s, cRopePercent)
+end;
+
+procedure chGetAwayTime(var s: shortstring);
+begin
+val(s, cGetAwayTime)
+end;
+
+procedure chMineDudPercent(var s: shortstring);
+begin
+val(s, cMineDudPercent)
+end;
+
+procedure chLandMines(var s: shortstring);
+begin
+val(s, cLandMines)
+end;
+
+procedure chExplosives(var s: shortstring);
+begin
+val(s, cExplosives)
+end;
+
+procedure chGameFlags(var s: shortstring);
+begin
+val(s, GameFlags)
+end;
+
+procedure chHedgehogTurnTime(var s: shortstring);
+begin
+val(s, cHedgehogTurnTime)
+end;
+
+procedure chMinesTime(var s: shortstring);
+begin
+val(s, cMinesTime)
+end;
+
+procedure chFastUntilLag(var s: shortstring);
+var i: LongInt;
+begin
+val(s, i);
+fastUntilLag:= i <> 0
+end;
 
 procedure initModule;
 begin
 //////// Begin top sorted by freq analysis not including chatmsg
-    RegisterVariable('+right'  , vtCommand, @chRight_p      , false);
-    RegisterVariable('-right'  , vtCommand, @chRight_m      , false);
-    RegisterVariable('+up'     , vtCommand, @chUp_p         , false);
-    RegisterVariable('-up'     , vtCommand, @chUp_m         , false);
-    RegisterVariable('+left'   , vtCommand, @chLeft_p       , false);
-    RegisterVariable('-left'   , vtCommand, @chLeft_m       , false);
-    RegisterVariable('+attack' , vtCommand, @chAttack_p     , false);
-    RegisterVariable('+down'   , vtCommand, @chDown_p       , false);
-    RegisterVariable('-down'   , vtCommand, @chDown_m       , false);
-    RegisterVariable('hjump'   , vtCommand, @chHJump        , false);
-    RegisterVariable('ljump'   , vtCommand, @chLJump        , false);
-    RegisterVariable('nextturn', vtCommand, @chNextTurn     , false);
-    RegisterVariable('-attack' , vtCommand, @chAttack_m     , false);
-    RegisterVariable('slot'    , vtCommand, @chSlot         , false);
-    RegisterVariable('setweap' , vtCommand, @chSetWeapon    , false);
+    RegisterVariable('+right'  , @chRight_p      , false);
+    RegisterVariable('-right'  , @chRight_m      , false);
+    RegisterVariable('+up'     , @chUp_p         , false);
+    RegisterVariable('-up'     , @chUp_m         , false);
+    RegisterVariable('+left'   , @chLeft_p       , false);
+    RegisterVariable('-left'   , @chLeft_m       , false);
+    RegisterVariable('+attack' , @chAttack_p     , false);
+    RegisterVariable('+down'   , @chDown_p       , false);
+    RegisterVariable('-down'   , @chDown_m       , false);
+    RegisterVariable('hjump'   , @chHJump        , false);
+    RegisterVariable('ljump'   , @chLJump        , false);
+    RegisterVariable('nextturn', @chNextTurn     , false);
+    RegisterVariable('-attack' , @chAttack_m     , false);
+    RegisterVariable('slot'    , @chSlot         , false);
+    RegisterVariable('setweap' , @chSetWeapon    , false);
 //////// End top by freq analysis
-    RegisterVariable('gencmd'  , vtCommand, @chGenCmd       , false);
-    RegisterVariable('flag'    , vtCommand, @chFlag         , false);
-    RegisterVariable('script'  , vtCommand, @chScript       , false);
-    RegisterVariable('proto'   , vtCommand, @chCheckProto   , true );
-    RegisterVariable('spectate', vtBoolean, @fastUntilLag   , false);
-    RegisterVariable('capture' , vtCommand, @chCapture      , true );
-    RegisterVariable('rotmask' , vtCommand, @chRotateMask   , true );
-    RegisterVariable('rdriven' , vtCommand, @chTeamLocal    , false);
-    RegisterVariable('map'     , vtCommand, @chSetMap       , false);
-    RegisterVariable('theme'   , vtCommand, @chSetTheme     , false);
-    RegisterVariable('seed'    , vtCommand, @chSetSeed      , false);
-    RegisterVariable('template_filter', vtLongInt, @cTemplateFilter, false);
-    RegisterVariable('mapgen'  , vtLongInt, @cMapGen        , false);
-    RegisterVariable('maze_size',vtLongInt, @cTemplateFilter, false);
-    RegisterVariable('delay'   , vtLongInt, @cInactDelay    , false);
-    RegisterVariable('ready'   , vtLongInt, @cReadyDelay    , false);
-    RegisterVariable('casefreq', vtLongInt, @cCaseFactor    , false);
-    RegisterVariable('healthprob', vtLongInt, @cHealthCaseProb, false);
-    RegisterVariable('hcaseamount', vtLongInt, @cHealthCaseAmount, false);
-    RegisterVariable('sd_turns', vtLongInt, @cSuddenDTurns  , false);
-    RegisterVariable('waterrise', vtLongInt, @cWaterRise    , false);
-    RegisterVariable('healthdec', vtLongInt, @cHealthDecrease, false);
-    RegisterVariable('damagepct',vtLongInt, @cDamagePercent , false);
-    RegisterVariable('ropepct' , vtLongInt, @cRopePercent   , false);
-    RegisterVariable('getawaytime' , vtLongInt, @cGetAwayTime , false);
-    RegisterVariable('minedudpct',vtLongInt,@cMineDudPercent, false);
-    RegisterVariable('minesnum', vtLongInt, @cLandMines     , false);
-    RegisterVariable('explosives',vtLongInt,@cExplosives    , false);
-    RegisterVariable('gmflags' , vtLongInt, @GameFlags      , false);
-    RegisterVariable('turntime', vtLongInt, @cHedgehogTurnTime, false);
-    RegisterVariable('minestime',vtLongInt, @cMinesTime     , false);
-    RegisterVariable('fort'    , vtCommand, @chFort         , false);
-    RegisterVariable('grave'   , vtCommand, @chGrave        , false);
-    RegisterVariable('hat'     , vtCommand, @chSetHat       , false);
-    RegisterVariable('quit'    , vtCommand, @chQuit         , true );
-    RegisterVariable('forcequit', vtCommand, @chForceQuit   , true );
-    RegisterVariable('confirm' , vtCommand, @chConfirm      , true );
-    RegisterVariable('halt',     vtCommand, @chHalt         , true );
-    RegisterVariable('+speedup', vtCommand, @chSpeedup_p    , true );
-    RegisterVariable('-speedup', vtCommand, @chSpeedup_m    , true );
-    RegisterVariable('zoomin'  , vtCommand, @chZoomIn       , true );
-    RegisterVariable('zoomout' , vtCommand, @chZoomOut      , true );
-    RegisterVariable('zoomreset',vtCommand, @chZoomReset    , true );
-    RegisterVariable('ammomenu', vtCommand, @chAmmoMenu     , true);
-    RegisterVariable('+precise', vtCommand, @chPrecise_p    , false);
-    RegisterVariable('-precise', vtCommand, @chPrecise_m    , false);
-    RegisterVariable('switch'  , vtCommand, @chSwitch       , false);
-    RegisterVariable('timer'   , vtCommand, @chTimer        , false);
-    RegisterVariable('taunt'   , vtCommand, @chTaunt        , false);
-    RegisterVariable('put'     , vtCommand, @chPut          , false);
-    RegisterVariable('+volup'  , vtCommand, @chVol_p        , true );
-    RegisterVariable('-volup'  , vtCommand, @chVol_m        , true );
-    RegisterVariable('+voldown', vtCommand, @chVol_m        , true );
-    RegisterVariable('-voldown', vtCommand, @chVol_p        , true );
-    RegisterVariable('findhh'  , vtCommand, @chFindhh       , true );
-    RegisterVariable('pause'   , vtCommand, @chPause        , true );
-    RegisterVariable('+cur_u'  , vtCommand, @chCurU_p       , true );
-    RegisterVariable('-cur_u'  , vtCommand, @chCurU_m       , true );
-    RegisterVariable('+cur_d'  , vtCommand, @chCurD_p       , true );
-    RegisterVariable('-cur_d'  , vtCommand, @chCurD_m       , true );
-    RegisterVariable('+cur_l'  , vtCommand, @chCurL_p       , true );
-    RegisterVariable('-cur_l'  , vtCommand, @chCurL_m       , true );
-    RegisterVariable('+cur_r'  , vtCommand, @chCurR_p       , true );
-    RegisterVariable('-cur_r'  , vtCommand, @chCurR_m       , true );
+    RegisterVariable('gencmd'  , @chGenCmd       , false);
+    RegisterVariable('flag'    , @chFlag         , false);
+    RegisterVariable('script'  , @chScript       , false);
+    RegisterVariable('proto'   , @chCheckProto   , true );
+    RegisterVariable('spectate', @chFastUntilLag   , false);
+    RegisterVariable('capture' , @chCapture      , true );
+    RegisterVariable('rotmask' , @chRotateMask   , true );
+    RegisterVariable('rdriven' , @chTeamLocal    , false);
+    RegisterVariable('map'     , @chSetMap       , false);
+    RegisterVariable('theme'   , @chSetTheme     , false);
+    RegisterVariable('seed'    , @chSetSeed      , false);
+    RegisterVariable('template_filter', @chTemplateFilter, false);
+    RegisterVariable('mapgen'  , @chMapGen        , false);
+    RegisterVariable('maze_size',@chTemplateFilter, false);
+    RegisterVariable('delay'   , @chInactDelay    , false);
+    RegisterVariable('ready'   , @chReadyDelay    , false);
+    RegisterVariable('casefreq', @chCaseFactor    , false);
+    RegisterVariable('healthprob', @chHealthCaseProb, false);
+    RegisterVariable('hcaseamount', @chHealthCaseAmount, false);
+    RegisterVariable('sd_turns', @chSuddenDTurns  , false);
+    RegisterVariable('waterrise', @chWaterRise    , false);
+    RegisterVariable('healthdec', @chHealthDecrease, false);
+    RegisterVariable('damagepct',@chDamagePercent , false);
+    RegisterVariable('ropepct' , @chRopePercent   , false);
+    RegisterVariable('getawaytime' , @chGetAwayTime , false);
+    RegisterVariable('minedudpct',@chMineDudPercent, false);
+    RegisterVariable('minesnum', @chLandMines     , false);
+    RegisterVariable('explosives',@chExplosives    , false);
+    RegisterVariable('gmflags' , @chGameFlags      , false);
+    RegisterVariable('turntime', @chHedgehogTurnTime, false);
+    RegisterVariable('minestime',@chMinesTime     , false);
+    RegisterVariable('fort'    , @chFort         , false);
+    RegisterVariable('grave'   , @chGrave        , false);
+    RegisterVariable('hat'     , @chSetHat       , false);
+    RegisterVariable('quit'    , @chQuit         , true );
+    RegisterVariable('forcequit', @chForceQuit   , true );
+    RegisterVariable('confirm' , @chConfirm      , true );
+    RegisterVariable('halt',     @chHalt         , true );
+    RegisterVariable('+speedup', @chSpeedup_p    , true );
+    RegisterVariable('-speedup', @chSpeedup_m    , true );
+    RegisterVariable('zoomin'  , @chZoomIn       , true );
+    RegisterVariable('zoomout' , @chZoomOut      , true );
+    RegisterVariable('zoomreset',@chZoomReset    , true );
+    RegisterVariable('ammomenu', @chAmmoMenu     , true);
+    RegisterVariable('+precise', @chPrecise_p    , false);
+    RegisterVariable('-precise', @chPrecise_m    , false);
+    RegisterVariable('switch'  , @chSwitch       , false);
+    RegisterVariable('timer'   , @chTimer        , false);
+    RegisterVariable('taunt'   , @chTaunt        , false);
+    RegisterVariable('put'     , @chPut          , false);
+    RegisterVariable('+volup'  , @chVol_p        , true );
+    RegisterVariable('-volup'  , @chVol_m        , true );
+    RegisterVariable('+voldown', @chVol_m        , true );
+    RegisterVariable('-voldown', @chVol_p        , true );
+    RegisterVariable('findhh'  , @chFindhh       , true );
+    RegisterVariable('pause'   , @chPause        , true );
+    RegisterVariable('+cur_u'  , @chCurU_p       , true );
+    RegisterVariable('-cur_u'  , @chCurU_m       , true );
+    RegisterVariable('+cur_d'  , @chCurD_p       , true );
+    RegisterVariable('-cur_d'  , @chCurD_m       , true );
+    RegisterVariable('+cur_l'  , @chCurL_p       , true );
+    RegisterVariable('-cur_l'  , @chCurL_m       , true );
+    RegisterVariable('+cur_r'  , @chCurR_p       , true );
+    RegisterVariable('-cur_r'  , @chCurR_m       , true );
 end;
 
 procedure freeModule;
--- a/hedgewars/uCommands.pas	Sun Apr 01 15:23:34 2012 +0200
+++ b/hedgewars/uCommands.pas	Wed May 02 23:53:45 2012 +0200
@@ -23,31 +23,30 @@
 interface
 
 var isDeveloperMode: boolean;
-type TVariableType = (vtCommand, vtLongInt, vtBoolean);
-    TCommandHandler = procedure (var params: shortstring);
+type TCommandHandler = procedure (var params: shortstring);
 
 procedure initModule;
 procedure freeModule;
-procedure RegisterVariable(Name: shortstring; VType: TVariableType; p: pointer; Trusted: boolean);
+procedure RegisterVariable(Name: shortstring; p: TCommandHandler; Trusted: boolean);
 procedure ParseCommand(CmdStr: shortstring; TrustedSource: boolean);
+procedure ParseTeamCommand(s: shortstring);
 procedure StopMessages(Message: Longword);
 
 implementation
-uses Types, uConsts, uVariables, uConsole, uUtils, uDebug;
+uses uConsts, uVariables, uConsole, uUtils, uDebug;
 
 type  PVariable = ^TVariable;
     TVariable = record
         Next: PVariable;
         Name: string[15];
-        VType: TVariableType;
-        Handler: pointer;
+        Handler: TCommandHandler;
         Trusted: boolean;
         end;
 
 var
     Variables: PVariable;
 
-procedure RegisterVariable(Name: shortstring; VType: TVariableType; p: pointer; Trusted: boolean);
+procedure RegisterVariable(Name: shortstring; p: TCommandHandler; Trusted: boolean);
 var
     value: PVariable;
 begin
@@ -55,7 +54,6 @@
 TryDo(value <> nil, 'RegisterVariable: value = nil', true);
 FillChar(value^, sizeof(TVariable), 0);
 value^.Name:= Name;
-value^.VType:= VType;
 value^.Handler:= p;
 value^.Trusted:= Trusted;
 
@@ -70,8 +68,7 @@
 
 
 procedure ParseCommand(CmdStr: shortstring; TrustedSource: boolean);
-var ii: LongInt;
-    s: shortstring;
+var s: shortstring;
     t: PVariable;
     c: char;
 begin
@@ -80,54 +77,40 @@
     exit;
 c:= CmdStr[1];
 if (c = '/') or (c = '$') then
-    Delete(CmdStr, 1, 1)
-else
-    c:= '/';
+    Delete(CmdStr, 1, 1);
 s:= '';
 SplitBySpace(CmdStr, s);
-AddFileLog('[Cmd] ' + c + CmdStr + ' (' + inttostr(length(s)) + ')');
+AddFileLog('[Cmd] ' + CmdStr + ' (' + inttostr(length(s)) + ')');
 t:= Variables;
 while t <> nil do
     begin
     if t^.Name = CmdStr then
         begin
         if TrustedSource or t^.Trusted then
-            case t^.VType of
-                vtCommand: if c='/' then
-                    begin
-                    TCommandHandler(t^.Handler)(s);
-                    end;
-                vtLongInt: if c='$' then
-                    if s[0]=#0 then
-                        begin
-                        str(PLongInt(t^.Handler)^, s);
-                        WriteLnToConsole('$' + CmdStr + ' is "' + s + '"');
-                        end
-                    else
-                        val(s, PLongInt(t^.Handler)^);
-                vtBoolean: if c='$' then
-                    if s[0]=#0 then
-                        begin
-                        str(ord(boolean(t^.Handler^)), s);
-                        WriteLnToConsole('$' + CmdStr + ' is "' + s + '"');
-                        end
-                    else
-                        begin
-                        val(s, ii);
-                        boolean(t^.Handler^):= not (ii = 0)
-                        end;
-                end;
-            exit
-            end
-        else
-            t:= t^.Next
-        end;
+            t^.Handler(s);
+        exit
+        end
+    else
+        t:= t^.Next
+    end;
 case c of
     '$': WriteLnToConsole(errmsgUnknownVariable + ': "$' + CmdStr + '"')
     else
         WriteLnToConsole(errmsgUnknownCommand  + ': "/' + CmdStr + '"') end
 end;
 
+procedure ParseTeamCommand(s: shortstring);
+var Trusted: boolean;
+begin
+Trusted:= (CurrentTeam <> nil)
+          and (not CurrentTeam^.ExtDriven)
+          and (CurrentHedgehog^.BotLevel = 0);
+ParseCommand(s, Trusted);
+if (CurrentTeam <> nil) and (not CurrentTeam^.ExtDriven) and (ReadyTimeLeft > 1) then
+    ParseCommand('gencmd R', true)
+end;
+
+
 
 procedure StopMessages(Message: Longword);
 begin
--- a/hedgewars/uConsole.pas	Sun Apr 01 15:23:34 2012 +0200
+++ b/hedgewars/uConsole.pas	Wed May 02 23:53:45 2012 +0200
@@ -31,8 +31,8 @@
 implementation
 uses Types, uVariables, uUtils {$IFDEF ANDROID}, log in 'log.pas'{$ENDIF};
 
-const cLineWidth: LongInt = 0;
-    cLinesCount = 8;
+const cLinesCount = 8;
+var   cLineWidth: LongInt;
 
 type
     TTextLine = record
@@ -97,7 +97,7 @@
     if Length(s) = High(s) then
         Dec(s[0]);
     s[Ord(Length(s))+1] := #0;
-    exit(@s[1]);
+    ShortStringAsPChar:= @s[1];
 end;
 
 function GetLastConsoleLine: shortstring;
--- a/hedgewars/uConsts.pas	Sun Apr 01 15:23:34 2012 +0200
+++ b/hedgewars/uConsts.pas	Wed May 02 23:53:45 2012 +0200
@@ -51,7 +51,6 @@
     cWhiteColor           : Longword = $FFFFFFFF;
     cYellowColor          : Longword = $FFFFFF00;
     cNearBlackColor       : Longword = $FF000010;
-    cExplosionBorderColor : LongWord = $FF808080;
 
 {$WARNINGS OFF}
     cAirPlaneSpeed: hwFloat = (isNegative: false; QWordValue:   3006477107); // 1.4
@@ -103,18 +102,18 @@
     MAXNAMELEN = 192;
     MAXROPEPOINTS = 3840;
 
+    {$IFNDEF PAS2C}
     // some opengl headers do not have these macros
     GL_BGR              = $80E0;
     GL_BGRA             = $80E1;
     GL_CLAMP_TO_EDGE    = $812F;
     GL_TEXTURE_PRIORITY = $8066;
+    {$ENDIF}
 
     cSendCursorPosTime  : LongWord = 50;
     cVisibleWater       : LongInt = 128;
     cCursorEdgesDist    : LongInt = 100;
     cTeamHealthWidth    : LongInt = 128;
-    cWaterOpacity       : byte = $80;
-    cSDWaterOpacity     : byte = $80;
 
     cifRandomize = $00000001;
     cifTheme     = $00000002;
@@ -122,16 +121,10 @@
     cifAllInited = cifRandomize or cifTheme or cifMap;
 
     cTransparentColor: Longword = $00000000;
-    cGrayScale: Boolean = false;
 
     RGB_LUMINANCE_RED    = 0.212671;
     RGB_LUMINANCE_GREEN  = 0.715160;
     RGB_LUMINANCE_BLUE   = 0.072169;
-(*
-    RGB_LUMINANCE_RED    = 0.3333333333;
-    RGB_LUMINANCE_GREEN  = 0.3333333333;
-    RGB_LUMINANCE_BLUE   = 0.3333333333;
-*)
 
     cMaxTeams        = 8;
     cMaxHHIndex      = 7;
@@ -155,6 +148,12 @@
 
     cKeyMaxIndex = 1023;
 
+    cHHFileName = 'Hedgehog';
+    cCHFileName = 'Crosshair';
+    cThemeCFGFilename = 'theme.cfg';
+
+    cFontBorder = 2;
+
     // do not change this value
     cDefaultZoomLevel = 2.0;
 
@@ -259,6 +258,7 @@
     ammoprop_Utility      = $00001000;
     ammoprop_Effect       = $00002000;
     ammoprop_SetBounce    = $00004000;
+    ammoprop_NeedUpDown   = $00008000;//Used by TouchInterface to show or hide up/down widgets 
     ammoprop_NoRoundEnd   = $10000000;
 
     AMMO_INFINITE = 100;
@@ -312,6 +312,10 @@
     FADE_ANIM_TIME = 500;
     MOVE_ANIM_TIME = 500;
 {$ENDIF}
+
+    cTagsMasks : array[0..15] of byte = (7, 0, 0, 0, 15, 6, 4, 5, 0, 0, 0, 0, 0, 14, 12, 13);
+    cTagsMasksNoHealth: array[0..15] of byte = (3, 2, 11, 1, 0, 0, 0, 0, 0, 10, 0, 9, 0, 0, 0, 0);
+       
 implementation
 
 end.
--- a/hedgewars/uFloat.pas	Sun Apr 01 15:23:34 2012 +0200
+++ b/hedgewars/uFloat.pas	Wed May 02 23:53:45 2012 +0200
@@ -90,7 +90,7 @@
 function AngleCos(const Angle: Longword): hwFloat;
 function SignAs(const num, signum: hwFloat): hwFloat; inline; // Returns an hwFloat with the value of parameter num and the sign of signum.
 function hwSign(r: hwFloat): LongInt; inline; // Returns an integer with value 1 and sign of parameter r.
-function hwSign(r: real): LongInt; inline; // Returns an integer with value 1 and sign of parameter r.
+function hwSignf(r: real): LongInt; inline; // Returns an integer with value 1 and sign of parameter r.
 function isZero(const z: hwFloat): boolean; inline;
 {$IFDEF FPC}
 {$J-}
@@ -424,12 +424,12 @@
     hwSign:= 1
 end;
 
-function hwSign(r: real): LongInt;
+function hwSignf(r: real): LongInt;
 begin
 if r < 0 then
-    hwSign:= -1
+    hwSignf:= -1
 else
-    hwSign:= 1
+    hwSignf:= 1
 end;
 
 
--- a/hedgewars/uGame.pas	Sun Apr 01 15:23:34 2012 +0200
+++ b/hedgewars/uGame.pas	Wed May 02 23:53:45 2012 +0200
@@ -26,7 +26,7 @@
 ////////////////////
     implementation
 ////////////////////
-uses uKeys, uTeams, uIO, uAI, uGears, uSound, uMobile, uVisualGears, uTypes, uVariables{$IFDEF SDL13}, uTouch{$ENDIF};
+uses uInputHandler, uTeams, uIO, uAI, uGears, uSound, uMobile, uVisualGears, uTypes, uVariables{$IFDEF SDL13}, uTouch{$ENDIF};
 
 procedure DoGameTick(Lag: LongInt);
 var i: LongInt;
--- a/hedgewars/uGears.pas	Sun Apr 01 15:23:34 2012 +0200
+++ b/hedgewars/uGears.pas	Wed May 02 23:53:45 2012 +0200
@@ -69,6 +69,14 @@
 procedure ShotgunShot(Gear: PGear); forward;
 procedure doStepCase(Gear: PGear); forward;
 
+
+var delay: LongWord;
+    delay2: LongWord;
+    step: (stDelay, stChDmg, stSweep, stTurnReact,
+    stAfterDelay, stChWin, stWater, stChWin2, stHealth,
+    stSpawn, stNTurn);
+    upd: Longword;
+
 // For better maintainability the step handlers of gears are stored in
 // separate files.
 // Note: step handlers of gears that are hedgehogs are in a different file
@@ -172,11 +180,6 @@
 end;
 
 procedure ProcessGears;
-const delay: LongWord = 0;
-    delay2: LongWord = 0;
-    step: (stDelay, stChDmg, stSweep, stTurnReact,
-    stAfterDelay, stChWin, stWater, stChWin2, stHealth,
-    stSpawn, stNTurn) = stDelay;
 var Gear, t: PGear;
     i, AliveCount: LongInt;
     s: shortstring;
@@ -996,6 +999,7 @@
 var t, aTot: LongInt;
     i: TAmmoType;
 begin
+Hedgehog:= Hedgehog; // avoid hint
 
 aTot:= 0;
 for i:= Low(TAmmoType) to High(TAmmoType) do
@@ -1237,22 +1241,23 @@
 
 procedure initModule;
 const handlers: array[TGearType] of TGearStepProcedure = (
+            @doStepFlame,
+            @doStepHedgehog,
+            @doStepMine,
+            @doStepCase,
+            @doStepCase,
             @doStepBomb,
-            @doStepHedgehog,
             @doStepShell,
             @doStepGrave,
             @doStepBee,
             @doStepShotgunShot,
             @doStepPickHammer,
             @doStepRope,
-            @doStepMine,
-            @doStepCase,
             @doStepDEagleShot,
             @doStepDynamite,
             @doStepBomb,
             @doStepCluster,
             @doStepShover,
-            @doStepFlame,
             @doStepFirePunch,
             @doStepActionTimer,
             @doStepActionTimer,
@@ -1280,7 +1285,6 @@
             @doStepSniperRifleShot,
             @doStepJetpack,
             @doStepMolotov,
-            @doStepCase,
             @doStepBirdy,
             @doStepEggWork,
             @doStepPortalShot,
@@ -1302,8 +1306,8 @@
 begin
     doStepHandlers:= handlers;
 
-    RegisterVariable('skip', vtCommand, @chSkip, false);
-    RegisterVariable('hogsay', vtCommand, @chHogSay, true );
+    RegisterVariable('skip', @chSkip, false);
+    RegisterVariable('hogsay', @chHogSay, true );
 
     CurAmmoGear:= nil;
     GearsList:= nil;
@@ -1315,6 +1319,12 @@
 
     AllInactive:= false;
     PrvInactive:= false;
+
+    //typed const
+    delay:= 0;
+    delay2:= 0;
+    step:= stDelay;
+    upd:= 0;
 end;
 
 procedure freeModule;
--- a/hedgewars/uGearsHedgehog.pas	Sun Apr 01 15:23:34 2012 +0200
+++ b/hedgewars/uGearsHedgehog.pas	Wed May 02 23:53:45 2012 +0200
@@ -30,7 +30,7 @@
 procedure PickUp(HH, Gear: PGear);
 
 implementation
-uses uConsts, uVariables, uFloat, uAmmos, uSound, uCaptions, uMisc, 
+uses uConsts, uVariables, uFloat, uAmmos, uSound, uCaptions, 
     uCommands, uLocale, uUtils, uVisualGears, uStats, uIO, uScript,
     uGearsList, uGears, uCollisions, uRandom, uStore, uTeams, 
     uGearsUtils;
@@ -131,7 +131,7 @@
     color: LongWord;
 begin
 Gear^.Message:= Gear^.Message and (not gmTimer);
-CurWeapon:= GetAmmoEntry(Gear^.Hedgehog^);
+CurWeapon:= GetCurAmmoEntry(Gear^.Hedgehog^);
 with Gear^.Hedgehog^ do
     if ((Gear^.Message and gmPrecise) <> 0) and ((CurWeapon^.Propz and ammoprop_SetBounce) <> 0) then
         begin
@@ -178,7 +178,7 @@
 begin
 newGear:= nil;
 bShowFinger:= false;
-CurWeapon:= GetAmmoEntry(Gear^.Hedgehog^);
+CurWeapon:= GetCurAmmoEntry(Gear^.Hedgehog^);
 with Gear^,
     Gear^.Hedgehog^ do
         begin
@@ -634,13 +634,11 @@
      end
 end;
 
-const StepTicks: LongWord = 0;
-
 procedure HedgehogStep(Gear: PGear);
 var PrevdX: LongInt;
     CurWeapon: PAmmo;
 begin
-CurWeapon:= GetAmmoEntry(Gear^.Hedgehog^);
+CurWeapon:= GetCurAmmoEntry(Gear^.Hedgehog^);
 if ((Gear^.State and (gstAttacking or gstMoving)) = 0) then
     begin
     if isCursorVisible then
--- a/hedgewars/uGearsList.pas	Sun Apr 01 15:23:34 2012 +0200
+++ b/hedgewars/uGearsList.pas	Wed May 02 23:53:45 2012 +0200
@@ -72,7 +72,6 @@
 end;
     
 function AddGear(X, Y: LongInt; Kind: TGearType; State: Longword; dX, dY: hwFloat; Timer: LongWord): PGear;
-const Counter: Longword = 0;
 var gear: PGear;
 begin
 inc(Counter);
@@ -285,8 +284,8 @@
                 gear^.Density:= _1;
                 if (gear^.dY.QWordValue = 0) and (gear^.dX.QWordValue = 0) then
                     begin
-                    gear^.dY:= (getrandom - _0_8) * _0_03;
-                    gear^.dX:= (getrandom - _0_5) * _0_4
+                    gear^.dY:= (getrandomf - _0_8) * _0_03;
+                    gear^.dX:= (getrandomf - _0_5) * _0_4
                     end
                 end;
    gtFirePunch: begin
@@ -502,7 +501,7 @@
             begin
             t:= max(Gear^.Damage, Gear^.Health);
             Gear^.Damage:= t;
-            if ((not SuddenDeathDmg and (cWaterOpacity < $FF)) or (SuddenDeathDmg and (cWaterOpacity < $FF)))
+            if ((not SuddenDeathDmg and (WaterOpacity < $FF)) or (SuddenDeathDmg and (WaterOpacity < $FF)))
             and (hwRound(Gear^.Y) < cWaterLine + 256) then
                 spawnHealthTagForHH(Gear, t);
             end;
--- a/hedgewars/uGearsRender.pas	Sun Apr 01 15:23:34 2012 +0200
+++ b/hedgewars/uGearsRender.pas	Wed May 02 23:53:45 2012 +0200
@@ -176,10 +176,10 @@
 
 
 if RopePoints.Count > 0 then
-    DrawRotated(sprRopeHook, hwRound(RopePoints.ar[0].X) + WorldDx, hwRound(RopePoints.ar[0].Y) + WorldDy, 1, RopePoints.HookAngle)
+    DrawSpriteRotated(sprRopeHook, hwRound(RopePoints.ar[0].X) + WorldDx, hwRound(RopePoints.ar[0].Y) + WorldDy, 1, RopePoints.HookAngle)
 else
     if Gear^.Elasticity.QWordValue > 0 then
-        DrawRotated(sprRopeHook, hwRound(Gear^.X) + WorldDx, hwRound(Gear^.Y) + WorldDy, 0, DxDy2Angle(Gear^.dY, Gear^.dX));
+        DrawSpriteRotated(sprRopeHook, hwRound(Gear^.X) + WorldDx, hwRound(Gear^.Y) + WorldDy, 0, DxDy2Angle(Gear^.dY, Gear^.dX));
 end;
 
 
@@ -224,7 +224,7 @@
         end
     else if (Gear^.State and gstHHGone) <> 0 then
         begin
-        DrawRotatedF(sprTeleport, sx, sy, Gear^.Pos, sign, 0);
+        DrawSpriteRotatedF(sprTeleport, sx, sy, Gear^.Pos, sign, 0);
         exit
         end;
 
@@ -235,7 +235,7 @@
     if HH^.Effects[hePoisoned] then
         begin
         Tint($00, $FF, $40, $40);
-        DrawRotatedTextureF(SpritesData[sprSmokeWhite].texture, 2, 0, 0, sx, sy, 0, 1, 22, 22, (RealTicks shr 36) mod 360);
+        DrawTextureRotatedF(SpritesData[sprSmokeWhite].texture, 2, 0, 0, sx, sy, 0, 1, 22, 22, (RealTicks shr 36) mod 360);
         Tint($FF, $FF, $FF, $FF)
         end;
 
@@ -335,7 +335,7 @@
             CrosshairY := Round(hwRound(Gear^.Y) + dy * 80 + GetLaunchY(HH^.CurAmmoType, Gear^.Angle));
  
             
-            DrawRotatedTex(HH^.Team^.CrosshairTex,
+            DrawTextureRotated(HH^.Team^.CrosshairTex,
                     12, 12, CrosshairX + WorldDx, CrosshairY + WorldDy, 0,
                     sign * (Gear^.Angle * 180.0) / cMaxAngle);
             end;
@@ -347,20 +347,20 @@
             case CurAmmoGear^.Kind of
                 gtShotgunShot: begin
                         if (CurAmmoGear^.State and gstAnimation <> 0) then
-                            DrawRotated(sprShotgun, hx, hy, sign, aangle)
+                            DrawSpriteRotated(sprShotgun, hx, hy, sign, aangle)
                         else
-                            DrawRotated(sprHandShotgun, hx, hy, sign, aangle);
+                            DrawSpriteRotated(sprHandShotgun, hx, hy, sign, aangle);
                     end;
-                gtDEagleShot: DrawRotated(sprDEagle, hx, hy, sign, aangle);
+                gtDEagleShot: DrawSpriteRotated(sprDEagle, hx, hy, sign, aangle);
                 gtSniperRifleShot: begin
                         if (CurAmmoGear^.State and gstAnimation <> 0) then
-                            DrawRotatedF(sprSniperRifle, hx, hy, 1, sign, aangle)
+                            DrawSpriteRotatedF(sprSniperRifle, hx, hy, 1, sign, aangle)
                         else
-                            DrawRotatedF(sprSniperRifle, hx, hy, 0, sign, aangle)
+                            DrawSpriteRotatedF(sprSniperRifle, hx, hy, 0, sign, aangle)
                     end;
-                gtBallgun: DrawRotated(sprHandBallgun, hx, hy, sign, aangle);
+                gtBallgun: DrawSpriteRotated(sprHandBallgun, hx, hy, sign, aangle);
                 gtRCPlane: begin
-                    DrawRotated(sprHandPlane, hx, hy, sign, 0);
+                    DrawSpriteRotated(sprHandPlane, hx, hy, sign, 0);
                     defaultPos:= false
                     end;
                 gtRope: begin
@@ -386,12 +386,12 @@
                     with HH^ do
                         if (HatTex <> nil) then
                             begin
-                            DrawRotatedTextureF(HatTex, 1.0, -1.0, -6.0, ox, oy, 0, i, 32, 32,
+                            DrawTextureRotatedF(HatTex, 1.0, -1.0, -6.0, ox, oy, 0, i, 32, 32,
                                 i*DxDy2Angle(CurAmmoGear^.dY, CurAmmoGear^.dX) + hAngle);
                             if HatTex^.w > 64 then
                                 begin
                                 Tint(HH^.Team^.Clan^.Color shl 8 or $FF);
-                                DrawRotatedTextureF(HatTex, 1.0, -1.0, -6.0, ox, oy, 32, i, 32, 32,
+                                DrawTextureRotatedF(HatTex, 1.0, -1.0, -6.0, ox, oy, 32, i, 32, 32,
                                     i*DxDy2Angle(CurAmmoGear^.dY, CurAmmoGear^.dX) + hAngle);
                                 Tint($FF, $FF, $FF, $FF)
                                 end
@@ -402,7 +402,7 @@
                     end;
                 gtBlowTorch:
                     begin
-                    DrawRotated(sprBlowTorch, hx, hy, sign, aangle);
+                    DrawSpriteRotated(sprBlowTorch, hx, hy, sign, aangle);
                     DrawHedgehog(sx, sy,
                             sign,
                             3,
@@ -435,7 +435,7 @@
                             end;
                     defaultPos:= false
                     end;
-                gtShover: DrawRotated(sprHandBaseball, hx, hy, sign, aangle + 180);
+                gtShover: DrawSpriteRotated(sprHandBaseball, hx, hy, sign, aangle + 180);
                 gtFirePunch:
                     begin
                     DrawHedgehog(sx, sy,
@@ -453,7 +453,7 @@
                 gtTeleport: defaultPos:= false;
                 gtWhip:
                     begin
-                    DrawRotatedF(sprWhip,
+                    DrawSpriteRotatedF(sprWhip,
                             sx,
                             sy,
                             1,
@@ -463,7 +463,7 @@
                     end;
                 gtHammer:
                     begin
-                    DrawRotatedF(sprHammer,
+                    DrawSpriteRotatedF(sprHammer,
                             sx,
                             sy,
                             1,
@@ -473,7 +473,7 @@
                     end;
                 gtResurrector:
                     begin
-                    DrawRotated(sprHandResurrector, sx, sy, 0, 0);
+                    DrawSpriteRotated(sprHandResurrector, sx, sy, 0, 0);
                     defaultPos:= false
                     end;
                 gtKamikaze:
@@ -485,7 +485,7 @@
                                 6,
                                 0)
                     else
-                        DrawRotatedF(sprKamikaze,
+                        DrawSpriteRotatedF(sprKamikaze,
                                 ox, oy,
                                 CurAmmoGear^.Pos - 1,
                                 sign,
@@ -502,7 +502,7 @@
                                 0)
                     else
                         begin
-                        DrawRotatedF(sprDress,
+                        DrawSpriteRotatedF(sprDress,
                                 ox, oy,
                                 CurAmmoGear^.Pos,
                                 sign,
@@ -513,14 +513,14 @@
                     end;
                 gtFlamethrower:
                     begin
-                    DrawRotatedF(sprHandFlamethrower, hx, hy, (RealTicks div 125) mod 4, sign, aangle);
+                    DrawSpriteRotatedF(sprHandFlamethrower, hx, hy, (RealTicks div 125) mod 4, sign, aangle);
                     if CurAmmoGear^.Tex <> nil then
-                        DrawCentered(sx, sy - 40, CurAmmoGear^.Tex)
+                        DrawTextureCentered(sx, sy - 40, CurAmmoGear^.Tex)
                     end;
                 gtLandGun:
-                    begin DrawRotated(sprHandBallgun, hx, hy, sign, aangle);
+                    begin DrawSpriteRotated(sprHandBallgun, hx, hy, sign, aangle);
                     if CurAmmoGear^.Tex <> nil then
-                        DrawCentered(sx, sy - 40, CurAmmoGear^.Tex)
+                        DrawTextureCentered(sx, sy - 40, CurAmmoGear^.Tex)
                     end;
             end;
 
@@ -568,7 +568,7 @@
                 end
             else
                 begin
-                DrawRotatedF(Wavez[TWave(Gear^.Tag)].Sprite,
+                DrawSpriteRotatedF(Wavez[TWave(Gear^.Tag)].Sprite,
                         sx,
                         sy,
                         Gear^.Pos,
@@ -592,51 +592,51 @@
                 dec(HH^.Timer)
                 end;
             amt:= CurrentHedgehog^.CurAmmoType;
-            CurWeapon:= GetAmmoEntry(HH^);
+            CurWeapon:= GetCurAmmoEntry(HH^);
             case amt of
-                amBazooka: DrawRotated(sprHandBazooka, hx, hy, sign, aangle);
-                amSnowball: DrawRotated(sprHandSnowball, hx, hy, sign, aangle);
-                amMortar: DrawRotated(sprHandMortar, hx, hy, sign, aangle);
-                amMolotov: DrawRotated(sprHandMolotov, hx, hy, sign, aangle);
-                amBallgun: DrawRotated(sprHandBallgun, hx, hy, sign, aangle);
-                amDrill: DrawRotated(sprHandDrill, hx, hy, sign, aangle);
-                amRope: DrawRotated(sprHandRope, hx, hy, sign, aangle);
-                amShotgun: DrawRotated(sprHandShotgun, hx, hy, sign, aangle);
-                amDEagle: DrawRotated(sprHandDEagle, hx, hy, sign, aangle);
-                amSineGun: DrawRotatedF(sprHandSinegun, hx, hy, 73 + (sign * LongInt(RealTicks div 73)) mod 8, sign, aangle);
+                amBazooka: DrawSpriteRotated(sprHandBazooka, hx, hy, sign, aangle);
+                amSnowball: DrawSpriteRotated(sprHandSnowball, hx, hy, sign, aangle);
+                amMortar: DrawSpriteRotated(sprHandMortar, hx, hy, sign, aangle);
+                amMolotov: DrawSpriteRotated(sprHandMolotov, hx, hy, sign, aangle);
+                amBallgun: DrawSpriteRotated(sprHandBallgun, hx, hy, sign, aangle);
+                amDrill: DrawSpriteRotated(sprHandDrill, hx, hy, sign, aangle);
+                amRope: DrawSpriteRotated(sprHandRope, hx, hy, sign, aangle);
+                amShotgun: DrawSpriteRotated(sprHandShotgun, hx, hy, sign, aangle);
+                amDEagle: DrawSpriteRotated(sprHandDEagle, hx, hy, sign, aangle);
+                amSineGun: DrawSpriteRotatedF(sprHandSinegun, hx, hy, 73 + (sign * LongInt(RealTicks div 73)) mod 8, sign, aangle);
                 
                 amPortalGun:
                     if (CurWeapon^.Timer and 2) <> 0 then // Add a new Hedgehog value instead of abusing timer?
-                        DrawRotatedF(sprPortalGun, hx, hy, 0, sign, aangle)
+                        DrawSpriteRotatedF(sprPortalGun, hx, hy, 0, sign, aangle)
                     else
-                        DrawRotatedF(sprPortalGun, hx, hy, 1+CurWeapon^.Pos, sign, aangle);
+                        DrawSpriteRotatedF(sprPortalGun, hx, hy, 1+CurWeapon^.Pos, sign, aangle);
                         
-                amSniperRifle: DrawRotatedF(sprSniperRifle, hx, hy, 0, sign, aangle);
-                amBlowTorch: DrawRotated(sprHandBlowTorch, hx, hy, sign, aangle);
-                amCake: DrawRotated(sprHandCake, hx, hy, sign, aangle);
-                amGrenade: DrawRotated(sprHandGrenade, hx, hy, sign, aangle);
-                amWatermelon: DrawRotated(sprHandMelon, hx, hy, sign, aangle);
-                amSkip: DrawRotated(sprHandSkip, hx, hy, sign, aangle);
-                amClusterBomb: DrawRotated(sprHandCluster, hx, hy, sign, aangle);
-                amDynamite: DrawRotated(sprHandDynamite, hx, hy, sign, aangle);
-                amHellishBomb: DrawRotated(sprHandHellish, hx, hy, sign, aangle);
-                amGasBomb: DrawRotated(sprHandCheese, hx, hy, sign, aangle);
-                amMine: DrawRotated(sprHandMine, hx, hy, sign, aangle);
-                amSMine: DrawRotated(sprHandSMine, hx, hy, sign, aangle);
+                amSniperRifle: DrawSpriteRotatedF(sprSniperRifle, hx, hy, 0, sign, aangle);
+                amBlowTorch: DrawSpriteRotated(sprHandBlowTorch, hx, hy, sign, aangle);
+                amCake: DrawSpriteRotated(sprHandCake, hx, hy, sign, aangle);
+                amGrenade: DrawSpriteRotated(sprHandGrenade, hx, hy, sign, aangle);
+                amWatermelon: DrawSpriteRotated(sprHandMelon, hx, hy, sign, aangle);
+                amSkip: DrawSpriteRotated(sprHandSkip, hx, hy, sign, aangle);
+                amClusterBomb: DrawSpriteRotated(sprHandCluster, hx, hy, sign, aangle);
+                amDynamite: DrawSpriteRotated(sprHandDynamite, hx, hy, sign, aangle);
+                amHellishBomb: DrawSpriteRotated(sprHandHellish, hx, hy, sign, aangle);
+                amGasBomb: DrawSpriteRotated(sprHandCheese, hx, hy, sign, aangle);
+                amMine: DrawSpriteRotated(sprHandMine, hx, hy, sign, aangle);
+                amSMine: DrawSpriteRotated(sprHandSMine, hx, hy, sign, aangle);
                 amSeduction: begin
-                             DrawRotated(sprHandSeduction, hx, hy, sign, aangle);
+                             DrawSpriteRotated(sprHandSeduction, hx, hy, sign, aangle);
                              DrawCircle(ox, oy, 248, 4, $FF, $00, $00, $AA); 
                              //Tint($FF, $0, $0, $AA);
                              //DrawTexture(ox - 240, oy - 240, SpritesData[sprVampiric].Texture, 10);
                              //Tint($FF, $FF, $FF, $FF);
                              end;
-                amVampiric: DrawRotatedF(sprHandVamp, hx, hy, (RealTicks div 125) mod 4, sign, aangle);
+                amVampiric: DrawSpriteRotatedF(sprHandVamp, hx, hy, (RealTicks div 125) mod 4, sign, aangle);
                 amRCPlane: begin
-                    DrawRotated(sprHandPlane, hx, hy, sign, 0);
+                    DrawSpriteRotated(sprHandPlane, hx, hy, sign, 0);
                     defaultPos:= false
                     end;
                 amGirder: begin
-                    DrawRotated(sprHandConstruction, hx, hy, sign, aangle);
+                    DrawSpriteRotated(sprHandConstruction, hx, hy, sign, aangle);
                     DrawSpriteClipped(sprGirder,
                                     ox-256,
                                     oy-256,
@@ -645,34 +645,34 @@
                                     cWaterLine+WorldDy,
                                     LongInt(leftX)+WorldDx)
                     end;
-                amBee: DrawRotatedF(sprHandBee, hx, hy, (RealTicks div 125) mod 4, sign, aangle);
-                amFlamethrower: DrawRotatedF(sprHandFlamethrower, hx, hy, (RealTicks div 125) mod 4, sign, aangle);
-                amLandGun: DrawRotated(sprHandBallgun, hx, hy, sign, aangle);
+                amBee: DrawSpriteRotatedF(sprHandBee, hx, hy, (RealTicks div 125) mod 4, sign, aangle);
+                amFlamethrower: DrawSpriteRotatedF(sprHandFlamethrower, hx, hy, (RealTicks div 125) mod 4, sign, aangle);
+                amLandGun: DrawSpriteRotated(sprHandBallgun, hx, hy, sign, aangle);
                 amResurrector: DrawCircle(ox, oy, 98, 4, $F5, $DB, $35, $AA); // I'd rather not like to hardcode 100 here
             end;
 
             case amt of
                 amAirAttack,
                 amMineStrike,
-                amDrillStrike: DrawRotated(sprHandAirAttack, sx, oy, sign, 0);
+                amDrillStrike: DrawSpriteRotated(sprHandAirAttack, sx, oy, sign, 0);
                 amPickHammer: DrawHedgehog(sx, sy,
                             sign,
                             1,
                             2,
                             0);
-                amTeleport: DrawRotatedF(sprTeleport, sx, sy, 0, sign, 0);
+                amTeleport: DrawSpriteRotatedF(sprTeleport, sx, sy, 0, sign, 0);
                 amKamikaze: DrawHedgehog(sx, sy,
                             sign,
                             1,
                             5,
                             0);
-                amWhip: DrawRotatedF(sprWhip,
+                amWhip: DrawSpriteRotatedF(sprWhip,
                             sx,
                             sy,
                             0,
                             sign,
                             0);
-                amHammer: DrawRotatedF(sprHammer,
+                amHammer: DrawSpriteRotatedF(sprHammer,
                             sx,
                             sy,
                             0,
@@ -700,7 +700,7 @@
             end;
 
             case amt of
-                amBaseballBat: DrawRotated(sprHandBaseball,
+                amBaseballBat: DrawSpriteRotated(sprHandBaseball,
                         sx - 4 * sign,
                         sy + 9, sign, aangle);
             end;
@@ -736,7 +736,7 @@
         begin
         if defaultPos then
             begin
-            DrawRotatedF(sprHHIdle,
+            DrawSpriteRotatedF(sprHHIdle,
                 sx,
                 sy,
                 (RealTicks div 128 + Gear^.Pos) mod 19,
@@ -828,7 +828,7 @@
                                 DrawSprite(sprJetpack, sx-36, sy-28, 3)
                             end;
                         if CurAmmoGear^.Tex <> nil then
-                            DrawCentered(sx, sy - 40, CurAmmoGear^.Tex);
+                            DrawTextureCentered(sx, sy - 40, CurAmmoGear^.Tex);
                         DrawAltWeapon(Gear, sx, sy)
                         end;
                 end;
@@ -847,17 +847,17 @@
             if ((cTagsMask and htHealth) <> 0) then
                 begin
                 dec(t, HealthTagTex^.h + 2);
-                DrawCentered(ox, t, HealthTagTex)
+                DrawTextureCentered(ox, t, HealthTagTex)
                 end;
             if (cTagsMask and htName) <> 0 then
                 begin
                 dec(t, NameTagTex^.h + 2);
-                DrawCentered(ox, t, NameTagTex)
+                DrawTextureCentered(ox, t, NameTagTex)
                 end;
             if (cTagsMask and htTeamName) <> 0 then
                 begin
                 dec(t, Team^.NameTagTex^.h + 2);
-                DrawCentered(ox, t, Team^.NameTagTex)
+                DrawTextureCentered(ox, t, Team^.NameTagTex)
                 end;
             if (cTagsMask and htTransparent) <> 0 then
                 Tint($FF, $FF, $FF, $FF)
@@ -865,7 +865,7 @@
         if (Gear^.State and gstHHDriven) <> 0 then // Current hedgehog
             begin
             if (CurAmmoGear <> nil) and (CurAmmoGear^.Kind = gtResurrector) then
-                DrawCentered(ox, sy - cHHRadius - 7 - HealthTagTex^.h, HealthTagTex);
+                DrawTextureCentered(ox, sy - cHHRadius - 7 - HealthTagTex^.h, HealthTagTex);
 
             if bShowFinger and ((Gear^.State and gstHHDriven) <> 0) then
                 DrawSprite(sprFinger, ox - 16, oy - 64,
@@ -880,7 +880,7 @@
     if HH^.Effects[hePoisoned] then
         begin
         Tint($00, $FF, $40, $80);
-        DrawRotatedTextureF(SpritesData[sprSmokeWhite].texture, 1.5, 0, 0, sx, sy, 0, 1, 22, 22, 360 - (RealTicks shr 37) mod 360);
+        DrawTextureRotatedF(SpritesData[sprSmokeWhite].texture, 1.5, 0, 0, sx, sy, 0, 1, 22, 22, 360 - (RealTicks shr 37) mod 360);
         end;
     if HH^.Effects[heResurrected] then
         begin
@@ -913,43 +913,43 @@
 begin
     if Gear^.Target.X <> NoPointX then
         if Gear^.AmmoType = amBee then
-            DrawRotatedF(sprTargetBee, Gear^.Target.X + WorldDx, Gear^.Target.Y + WorldDy, 0, 0, (RealTicks shr 3) mod 360)
+            DrawSpriteRotatedF(sprTargetBee, Gear^.Target.X + WorldDx, Gear^.Target.Y + WorldDy, 0, 0, (RealTicks shr 3) mod 360)
         else
-            DrawRotatedF(sprTargetP, Gear^.Target.X + WorldDx, Gear^.Target.Y + WorldDy, 0, 0, (RealTicks shr 3) mod 360);
+            DrawSpriteRotatedF(sprTargetP, Gear^.Target.X + WorldDx, Gear^.Target.Y + WorldDy, 0, 0, (RealTicks shr 3) mod 360);
 
     case Gear^.Kind of
-          gtGrenade: DrawRotated(sprBomb, x, y, 0, Gear^.DirAngle);
-      gtSnowball: DrawRotated(sprSnowball, x, y, 0, Gear^.DirAngle);
-       gtGasBomb: DrawRotated(sprCheese, x, y, 0, Gear^.DirAngle);
+          gtGrenade: DrawSpriteRotated(sprBomb, x, y, 0, Gear^.DirAngle);
+      gtSnowball: DrawSpriteRotated(sprSnowball, x, y, 0, Gear^.DirAngle);
+       gtGasBomb: DrawSpriteRotated(sprCheese, x, y, 0, Gear^.DirAngle);
                   
        gtMolotov: if (Gear^.State and gstDrowning) = 0 then
-                       DrawRotatedF(sprMolotov, x, y, (RealTicks div 125) mod 8, hwSign(Gear^.dX), Gear^.DirAngle * hwSign(Gear^.dX))
+                       DrawSpriteRotatedF(sprMolotov, x, y, (RealTicks div 125) mod 8, hwSign(Gear^.dX), Gear^.DirAngle * hwSign(Gear^.dX))
                   else DrawSprite(sprMolotov, x, y, 8);
 
        gtRCPlane: begin
                   aangle:= Gear^.Angle * 360 / 4096;
                   if Gear^.Tag < 0 then aangle:= 360-aangle;
                   Tint(Gear^.Hedgehog^.Team^.Clan^.Color shl 8 or $FF);
-                  DrawRotatedF(sprPlane, x, y, 0, Gear^.Tag, aangle - 90);
+                  DrawSpriteRotatedF(sprPlane, x, y, 0, Gear^.Tag, aangle - 90);
                   Tint($FF, $FF, $FF, $FF);
-                  DrawRotatedF(sprPlane, x, y, 1, Gear^.Tag, aangle - 90)
+                  DrawSpriteRotatedF(sprPlane, x, y, 1, Gear^.Tag, aangle - 90)
                   end;
-       gtBall: DrawRotatedf(sprBalls, x, y, Gear^.Tag,0, Gear^.DirAngle);
+       gtBall: DrawSpriteRotatedF(sprBalls, x, y, Gear^.Tag,0, Gear^.DirAngle);
 
        gtPortal: if ((Gear^.Tag and 1) = 0) // still moving?
                  or (Gear^.IntersectGear = nil) or (Gear^.IntersectGear^.IntersectGear <> Gear) // not linked&backlinked?
                  or ((Gear^.IntersectGear^.Tag and 1) = 0) then // linked portal still moving?
-                      DrawRotatedf(sprPortal, x, y, Gear^.Tag, hwSign(Gear^.dX), Gear^.DirAngle)
-                 else DrawRotatedf(sprPortal, x, y, 4 + Gear^.Tag div 2, hwSign(Gear^.dX), Gear^.DirAngle);
+                      DrawSpriteRotatedF(sprPortal, x, y, Gear^.Tag, hwSign(Gear^.dX), Gear^.DirAngle)
+                 else DrawSpriteRotatedF(sprPortal, x, y, 4 + Gear^.Tag div 2, hwSign(Gear^.dX), Gear^.DirAngle);
 
            gtDrill: if (Gear^.State and gsttmpFlag) <> 0 then
-                        DrawRotated(sprAirDrill, x, y, 0, DxDy2Angle(Gear^.dY, Gear^.dX))
+                        DrawSpriteRotated(sprAirDrill, x, y, 0, DxDy2Angle(Gear^.dY, Gear^.dX))
                     else
-                        DrawRotated(sprDrill, x, y, 0, DxDy2Angle(Gear^.dY, Gear^.dX));
+                        DrawSpriteRotated(sprDrill, x, y, 0, DxDy2Angle(Gear^.dY, Gear^.dX));
 
         gtHedgehog: DrawHH(Gear, x, y);
 
-           gtShell: DrawRotated(sprBazookaShell, x, y, 0, DxDy2Angle(Gear^.dY, Gear^.dX));
+           gtShell: DrawSpriteRotated(sprBazookaShell, x, y, 0, DxDy2Angle(Gear^.dY, Gear^.dX));
 
            gtGrave: begin
                     DrawTextureF(Gear^.Hedgehog^.Team^.GraveTex, 1, x, y, (GameTicks shr 7+Gear^.uid) and 7, 1, 32, 32);
@@ -962,21 +962,21 @@
                         Tint($FF, $FF, $FF, $FF)
                         end
                     end;
-             gtBee: DrawRotatedF(sprBee, x, y, (GameTicks shr 5) mod 2, 0, DxDy2Angle(Gear^.dY, Gear^.dX));
+             gtBee: DrawSpriteRotatedF(sprBee, x, y, (GameTicks shr 5) mod 2, 0, DxDy2Angle(Gear^.dY, Gear^.dX));
       gtPickHammer: DrawSprite(sprPHammer, x - 16, y - 50 + LongInt(((GameTicks shr 5) and 1) * 2), 0);
             gtRope: DrawRope(Gear);
             
             gtMine: if (((Gear^.State and gstAttacking) = 0)or((Gear^.Timer and $3FF) < 420)) and (Gear^.Health <> 0) then
-                           DrawRotated(sprMineOff, x, y, 0, Gear^.DirAngle)
+                           DrawSpriteRotated(sprMineOff, x, y, 0, Gear^.DirAngle)
                        else if Gear^.Health <> 0 then
-                           DrawRotated(sprMineOn, x, y, 0, Gear^.DirAngle)
-                       else DrawRotated(sprMineDead, x, y, 0, Gear^.DirAngle);
+                           DrawSpriteRotated(sprMineOn, x, y, 0, Gear^.DirAngle)
+                       else DrawSpriteRotated(sprMineDead, x, y, 0, Gear^.DirAngle);
                        
            gtSMine: if (((Gear^.State and gstAttacking) = 0)or((Gear^.Timer and $3FF) < 420)) and (Gear^.Health <> 0) then
-                           DrawRotated(sprSMineOff, x, y, 0, Gear^.DirAngle)
+                           DrawSpriteRotated(sprSMineOff, x, y, 0, Gear^.DirAngle)
                        else if Gear^.Health <> 0 then
-                           DrawRotated(sprSMineOn, x, y, 0, Gear^.DirAngle)
-                       else DrawRotated(sprMineDead, x, y, 0, Gear^.DirAngle);
+                           DrawSpriteRotated(sprSMineOn, x, y, 0, Gear^.DirAngle)
+                       else DrawSpriteRotated(sprMineDead, x, y, 0, Gear^.DirAngle);
                        
             gtCase: if ((Gear^.Pos and posCaseAmmo) <> 0) then
                         begin
@@ -1011,12 +1011,12 @@
                         DrawSprite(sprExplosives, x - 24, y - 24, i)
                         end
                     else if Gear^.State and gsttmpFlag = 0 then
-                        DrawRotatedF(sprExplosivesRoll, x, y + 4, 0, 0, Gear^.DirAngle)
+                        DrawSpriteRotatedF(sprExplosivesRoll, x, y + 4, 0, 0, Gear^.DirAngle)
                     else
-                        DrawRotatedF(sprExplosivesRoll, x, y + 4, 1, 0, Gear^.DirAngle);
+                        DrawSpriteRotatedF(sprExplosivesRoll, x, y + 4, 1, 0, Gear^.DirAngle);
                     end;
-        gtDynamite: DrawSprite2(sprDynamite, x - 16, y - 25, Gear^.Tag and 1, Gear^.Tag shr 1);
-     gtClusterBomb: DrawRotated(sprClusterBomb, x, y, 0, Gear^.DirAngle);
+        gtDynamite: DrawSprite(sprDynamite, x - 16, y - 25, Gear^.Tag and 1, Gear^.Tag shr 1);
+     gtClusterBomb: DrawSpriteRotated(sprClusterBomb, x, y, 0, Gear^.DirAngle);
          gtCluster: DrawSprite(sprClusterParticle, x - 8, y - 8, 0);
            gtFlame: if Gear^.Tag and 1 = 0 then
                          DrawTextureF(SpritesData[sprFlame].Texture, 2 / (Gear^.Tag mod 3 + 2), x, y, (GameTicks shr 7 + LongWord(Gear^.Tag)) mod 8, 1, 16, 16)
@@ -1027,16 +1027,16 @@
                     end;
        gtAirAttack: begin
                     Tint(Gear^.Hedgehog^.Team^.Clan^.Color shl 8 or $FF);
-                    DrawRotatedF(sprAirplane, x, y, 0, Gear^.Tag, 0);
+                    DrawSpriteRotatedF(sprAirplane, x, y, 0, Gear^.Tag, 0);
                     Tint($FF, $FF, $FF, $FF);
-                    DrawRotatedF(sprAirplane, x, y, 1, Gear^.Tag, 0);
+                    DrawSpriteRotatedF(sprAirplane, x, y, 1, Gear^.Tag, 0);
                     end;
-         gtAirBomb: DrawRotated(sprAirBomb, x, y, 0, DxDy2Angle(Gear^.dY, Gear^.dX));
+         gtAirBomb: DrawSpriteRotated(sprAirBomb, x, y, 0, DxDy2Angle(Gear^.dY, Gear^.dX));
         gtTeleport: begin
                     HHGear:= Gear^.Hedgehog^.Gear;
                     if not Gear^.Hedgehog^.Unplaced then
-                        DrawRotatedF(sprTeleport, x + 1, y - 3, Gear^.Pos, hwSign(Gear^.dX), 0);
-                    DrawRotatedF(sprTeleport, hwRound(HHGear^.X) + 1 + WorldDx, hwRound(HHGear^.Y) - 3 + WorldDy, 11 - Gear^.Pos, hwSign(HHGear^.dX), 0);
+                        DrawSpriteRotatedF(sprTeleport, x + 1, y - 3, Gear^.Pos, hwSign(Gear^.dX), 0);
+                    DrawSpriteRotatedF(sprTeleport, hwRound(HHGear^.X) + 1 + WorldDx, hwRound(HHGear^.Y) - 3 + WorldDy, 11 - Gear^.Pos, hwSign(HHGear^.dX), 0);
                     end;
         gtSwitcher: DrawSprite(sprSwitch, x - 16, y - 56, (GameTicks shr 6) mod 12);
           gtTarget: begin
@@ -1044,17 +1044,17 @@
                     DrawSprite(sprTarget, x - 16, y - 16, 0);
                     Tint($FF, $FF, $FF, $FF);
                     end;
-          gtMortar: DrawRotated(sprMortar, x, y, 0, DxDy2Angle(Gear^.dY, Gear^.dX));
+          gtMortar: DrawSpriteRotated(sprMortar, x, y, 0, DxDy2Angle(Gear^.dY, Gear^.dX));
           gtCake: if Gear^.Pos = 6 then
-                     DrawRotatedf(sprCakeWalk, x, y, (GameTicks div 40) mod 6, hwSign(Gear^.dX), Gear^.DirAngle * hwSign(Gear^.dX) + 90)
+                     DrawSpriteRotatedF(sprCakeWalk, x, y, (GameTicks div 40) mod 6, hwSign(Gear^.dX), Gear^.DirAngle * hwSign(Gear^.dX) + 90)
                   else
-                     DrawRotatedf(sprCakeDown, x, y, 5 - Gear^.Pos, hwSign(Gear^.dX), Gear^.DirAngle * hwSign(Gear^.dX) + 90);
+                     DrawSpriteRotatedF(sprCakeDown, x, y, 5 - Gear^.Pos, hwSign(Gear^.dX), Gear^.DirAngle * hwSign(Gear^.dX) + 90);
        gtSeduction: if Gear^.Pos >= 14 then
            DrawSprite(sprSeduction, x - 16, y - 16, 0);
            
-      gtWatermelon: DrawRotatedf(sprWatermelon, x, y, 0, 0, Gear^.DirAngle);
-      gtMelonPiece: DrawRotatedf(sprWatermelon, x, y, 1, 0, Gear^.DirAngle);
-     gtHellishBomb: DrawRotated(sprHellishBomb, x, y, 0, Gear^.DirAngle);
+      gtWatermelon: DrawSpriteRotatedF(sprWatermelon, x, y, 0, 0, Gear^.DirAngle);
+      gtMelonPiece: DrawSpriteRotatedF(sprWatermelon, x, y, 1, 0, Gear^.DirAngle);
+     gtHellishBomb: DrawSpriteRotated(sprHellishBomb, x, y, 0, Gear^.DirAngle);
            gtBirdy: begin
                     if Gear^.State and gstAnimation = gstAnimation then
                         begin
@@ -1089,7 +1089,7 @@
                             DrawTextureF(SpritesData[sprBirdy].Texture, 1, x, y, ((Gear^.Pos shr 6) or (RealTicks shr 8)) mod 2, Gear^.Tag, 75, 75);
                         end;
                     end;
-             gtEgg: DrawRotatedTextureF(SpritesData[sprEgg].Texture, 1, 0, 0, x, y, 0, 1, 16, 16, Gear^.DirAngle);
+             gtEgg: DrawTextureRotatedF(SpritesData[sprEgg].Texture, 1, 0, 0, x, y, 0, 1, 16, 16, Gear^.DirAngle);
            gtPiano: begin
                     if (Gear^.State and gstDrowning) = 0 then
                         begin
@@ -1107,25 +1107,25 @@
                         Tint($C0, $C0, $00, (5000 - Gear^.Timer) div 8)
                     else
                         Tint($C0, $C0, $00, $C0);
-                    DrawRotatedTextureF(SpritesData[sprSmokeWhite].texture, 3, 0, 0, x, y, 0, 1, 22, 22, (RealTicks shr 36 + Gear^.UID * 100) mod 360);
+                    DrawTextureRotatedF(SpritesData[sprSmokeWhite].texture, 3, 0, 0, x, y, 0, 1, 22, 22, (RealTicks shr 36 + Gear^.UID * 100) mod 360);
                     Tint($FF, $FF, $FF, $FF)
                     end;
      gtResurrector: begin
-                    DrawRotated(sprCross, x, y, 0, 0);
+                    DrawSpriteRotated(sprCross, x, y, 0, 0);
                     Tint($f5, $db, $35, max($00, round($C0 * abs(1 - (GameTicks mod 6000) / 3000))));
                     DrawTexture(x - 108, y - 108, SpritesData[sprVampiric].Texture, 4.5);
                     Tint($FF, $FF, $FF, $FF);
                     end;
-      gtNapalmBomb: DrawRotated(sprNapalmBomb, x, y, 0, DxDy2Angle(Gear^.dY, Gear^.dX));
+      gtNapalmBomb: DrawSpriteRotated(sprNapalmBomb, x, y, 0, DxDy2Angle(Gear^.dY, Gear^.dX));
            gtFlake: if Gear^.State and (gstDrowning or gstTmpFlag) <> 0  then
                         begin
-                        Tint((cExplosionBorderColor shr RShift) and $FF, 
-                             (cExplosionBorderColor shr GShift) and $FF, 
-                             (cExplosionBorderColor shr BShift) and $FF, 
+                        Tint((ExplosionBorderColor shr RShift) and $FF, 
+                             (ExplosionBorderColor shr GShift) and $FF, 
+                             (ExplosionBorderColor shr BShift) and $FF, 
                              $FF);
                         // Needs a nicer white texture to tint
-                        DrawRotatedTextureF(SpritesData[sprSnowDust].Texture, 1, 0, 0, x, y, 0, 1, 8, 8, Gear^.DirAngle);
-                        //DrawRotated(sprSnowDust, x, y, 0, Gear^.DirAngle);
+                        DrawTextureRotatedF(SpritesData[sprSnowDust].Texture, 1, 0, 0, x, y, 0, 1, 8, 8, Gear^.DirAngle);
+                        //DrawSpriteRotated(sprSnowDust, x, y, 0, Gear^.DirAngle);
                         //DrawTexture(x, y, SpritesData[sprVampiric].Texture, 0.1);
                         Tint($FF, $FF, $FF, $FF);
                         end
@@ -1140,9 +1140,9 @@
                         if vobVelocity = 0 then
                             DrawSprite(sprFlake, x, y, Gear^.Timer)
                         else
-                            DrawRotatedF(sprFlake, x, y, Gear^.Timer, 1, Gear^.DirAngle);
+                            DrawSpriteRotatedF(sprFlake, x, y, Gear^.Timer, 1, Gear^.DirAngle);
 //DrawSprite(sprFlake, x-SpritesData[sprFlake].Width div 2, y-SpritesData[sprFlake].Height div 2, Gear^.Timer)
-//DrawRotatedF(sprFlake, x-SpritesData[sprFlake].Width div 2, y-SpritesData[sprFlake].Height div 2, Gear^.Timer, 1, Gear^.DirAngle);
+//DrawSpriteRotatedF(sprFlake, x-SpritesData[sprFlake].Width div 2, y-SpritesData[sprFlake].Height div 2, Gear^.Timer, 1, Gear^.DirAngle);
                         if Gear^.FlightTime > 0 then
                             Tint($FF, $FF, $FF, $FF);
                         end;
@@ -1171,7 +1171,7 @@
 
          end;
       if Gear^.RenderTimer and (Gear^.Tex <> nil) then
-          DrawCentered(x + 8, y + 8, Gear^.Tex);
+          DrawTextureCentered(x + 8, y + 8, Gear^.Tex);
 end;
 
 end.
--- a/hedgewars/uGearsUtils.pas	Sun Apr 01 15:23:34 2012 +0200
+++ b/hedgewars/uGearsUtils.pas	Wed May 02 23:53:45 2012 +0200
@@ -22,7 +22,9 @@
 interface
 uses uTypes, math;
 
-procedure doMakeExplosion(X, Y, Radius: LongInt; AttackingHog: PHedgehog; Mask: Longword; const Tint: LongWord = $FFFFFFFF); 
+procedure doMakeExplosion(X, Y, Radius: LongInt; AttackingHog: PHedgehog; Mask: Longword); inline;
+procedure doMakeExplosion(X, Y, Radius: LongInt; AttackingHog: PHedgehog; Mask: Longword; const Tint: LongWord); 
+
 function  ModifyDamage(dmg: Longword; Gear: PGear): Longword;
 procedure ApplyDamage(Gear: PGear; AttackerHog: PHedgehog; Damage: Longword; Source: TDamageSource);
 procedure spawnHealthTagForHH(HHGear: PGear; dmg: Longword);
@@ -30,9 +32,11 @@
 procedure CheckHHDamage(Gear: PGear);
 procedure CalcRotationDirAngle(Gear: PGear);
 procedure ResurrectHedgehog(gear: PGear);
-procedure FindPlace(var Gear: PGear; withFall: boolean; Left, Right: LongInt; skipProximity: boolean = false);
+
+procedure FindPlace(var Gear: PGear; withFall: boolean; Left, Right: LongInt); inline;
+procedure FindPlace(var Gear: PGear; withFall: boolean; Left, Right: LongInt; skipProximity: boolean);
+
 function  CheckGearNear(Gear: PGear; Kind: TGearType; rX, rY: LongInt): PGear;
-function  CheckGearsNear(mX, mY: LongInt; Kind: TGearsType; rX, rY: LongInt): PGear;
 function  CheckGearDrowning(Gear: PGear): boolean;
 
 var doStepHandlers: array[TGearType] of TGearStepProcedure;
@@ -44,6 +48,11 @@
     uLocale, uTextures, uRenderUtils, uRandom, SDLh, uDebug, uGears,
     uGearsList;
 
+procedure doMakeExplosion(X, Y, Radius: LongInt; AttackingHog: PHedgehog; Mask: Longword); inline;
+begin
+    doMakeExplosion(X, Y, Radius, AttackingHog, Mask, $FFFFFFFF);
+end;
+
 procedure doMakeExplosion(X, Y, Radius: LongInt; AttackingHog: PHedgehog; Mask: Longword; const Tint: LongWord);
 var Gear: PGear;
     dmg, dmgBase: LongInt;
@@ -464,15 +473,41 @@
 var i: LongInt;
     count: LongInt = 0;
 begin
-if (y and LAND_HEIGHT_MASK) = 0 then
-    for i:= max(x - r, 0) to min(x + r, LAND_WIDTH - 4) do
-        if Land[y, i] <> 0 then
+    if (y and LAND_HEIGHT_MASK) = 0 then
+        for i:= max(x - r, 0) to min(x + r, LAND_WIDTH - 4) do
+            if Land[y, i] <> 0 then
             begin
-            inc(count);
-            if count = c then
-                exit(count)
+                inc(count);
+                if count = c then
+                begin
+                    CountNonZeroz:= count;
+                    exit
+                end;
             end;
-CountNonZeroz:= count;
+    CountNonZeroz:= count;
+end;
+
+
+function NoGearsToAvoid(mX, mY: LongInt; rX, rY: LongInt): boolean;
+var t: PGear;
+begin
+NoGearsToAvoid:= false;
+t:= GearsList;
+rX:= sqr(rX);
+rY:= sqr(rY);
+while t <> nil do
+    begin
+    if t^.Kind <= gtExplosives then
+        if not (hwSqr(int2hwFloat(mX) - t^.X) / rX + hwSqr(int2hwFloat(mY) - t^.Y) / rY > _1) then
+            exit;
+    t:= t^.NextGear
+    end;
+NoGearsToAvoid:= true
+end;
+
+procedure FindPlace(var Gear: PGear; withFall: boolean; Left, Right: LongInt); inline;
+begin
+    FindPlace(Gear, withFall, Left, Right, false);
 end;
 
 procedure FindPlace(var Gear: PGear; withFall: boolean; Left, Right: LongInt; skipProximity: boolean);
@@ -511,14 +546,14 @@
                 if (y - sy > Gear^.Radius * 2)
                     and (((Gear^.Kind = gtExplosives)
                     and (y < cWaterLine)
-                    and (reallySkip or (CheckGearsNear(x, y - Gear^.Radius, [gtFlame, gtHedgehog, gtMine, gtCase, gtExplosives], 60, 60) = nil))
+                    and (reallySkip or NoGearsToAvoid(x, y - Gear^.Radius, 60, 60))
                     and (CountNonZeroz(x, y+1, Gear^.Radius - 1, Gear^.Radius+1) > Gear^.Radius))
                 or
                     ((Gear^.Kind <> gtExplosives)
                     and (y < cWaterLine)
-                    and (reallySkip or (CheckGearsNear(x, y - Gear^.Radius, [gtFlame, gtHedgehog, gtMine, gtCase, gtExplosives], 110, 110) = nil)))) then
-                 
-                          begin
+                    and (reallySkip or NoGearsToAvoid(x, y - Gear^.Radius, 110, 110))
+                    )) then
+                    begin
                     ar[cnt].X:= x;
                     if withFall then
                         ar[cnt].Y:= sy + Gear^.Radius
@@ -575,27 +610,14 @@
     begin
     if (t <> Gear) and (t^.Kind = Kind) then
         if not((hwSqr(Gear^.X - t^.X) / rX + hwSqr(Gear^.Y - t^.Y) / rY) > _1) then
-        exit(t);
+        begin
+            CheckGearNear:= t;
+            exit;
+        end;
     t:= t^.NextGear
     end;
 
 CheckGearNear:= nil
 end;
 
-
-function CheckGearsNear(mX, mY: LongInt; Kind: TGearsType; rX, rY: LongInt): PGear;
-var t: PGear;
-begin
-t:= GearsList;
-rX:= sqr(rX);
-rY:= sqr(rY);
-while t <> nil do
-    begin
-    if t^.Kind in Kind then
-        if not (hwSqr(int2hwFloat(mX) - t^.X) / rX + hwSqr(int2hwFloat(mY) - t^.Y) / rY > _1) then
-            exit(t);
-    t:= t^.NextGear
-    end;
-CheckGearsNear:= nil
-end;
 end.
--- a/hedgewars/uIO.pas	Sun Apr 01 15:23:34 2012 +0200
+++ b/hedgewars/uIO.pas	Wed May 02 23:53:45 2012 +0200
@@ -26,6 +26,7 @@
 procedure freeModule;
 
 procedure SendIPC(s: shortstring);
+procedure SendIPCc(c: char);
 procedure SendIPCXY(cmd: char; X, Y: SmallInt);
 procedure SendIPCRaw(p: pointer; len: Longword);
 procedure SendIPCAndWaitReply(s: shortstring);
@@ -104,7 +105,7 @@
     WriteLnToConsole(msgOK);
     WriteToConsole('Establishing IPC connection to tcp 127.0.0.1:' + IntToStr(ipcPort) + ' ');
     {$HINTS OFF}
-    SDLTry(SDLNet_ResolveHost(ipaddr, '127.0.0.1', ipcPort) = 0, true);
+    SDLTry(SDLNet_ResolveHost(ipaddr, PChar('127.0.0.1'), ipcPort) = 0, true);
     {$HINTS ON}
     IPCSock:= SDLNet_TCP_Open(ipaddr);
     SDLTry(IPCSock <> nil, true);
@@ -123,7 +124,7 @@
 begin
 case s[1] of
      '!': begin AddFileLog('Ping? Pong!'); isPonged:= true; end;
-     '?': SendIPC('!');
+     '?': SendIPCc('!');
      'e': ParseCommand(copy(s, 2, Length(s) - 1), true);
      'E': OutError(copy(s, 2, Length(s) - 1), true);
      'W': OutError(copy(s, 2, Length(s) - 1), false);
@@ -142,27 +143,26 @@
 end;
 
 procedure IPCCheckSock;
-const ss: shortstring = '';
 var i: LongInt;
     s: shortstring;
 begin
-if IPCSock = nil then
-    exit;
+    if IPCSock = nil then
+        exit;
 
-fds^.numsockets:= 0;
-SDLNet_AddSocket(fds, IPCSock);
+    fds^.numsockets:= 0;
+    SDLNet_AddSocket(fds, IPCSock);
 
-while SDLNet_CheckSockets(fds, 0) > 0 do
+    while SDLNet_CheckSockets(fds, 0) > 0 do
     begin
-    i:= SDLNet_TCP_Recv(IPCSock, @s[1], 255 - Length(ss));
-    if i > 0 then
+        i:= SDLNet_TCP_Recv(IPCSock, @s[1], 255 - Length(SocketString));
+        if i > 0 then
         begin
-        s[0]:= char(i);
-        ss:= ss + s;
-        while (Length(ss) > 1) and (Length(ss) > byte(ss[1])) do
+            s[0]:= char(i);
+            SocketString:= SocketString + s;
+            while (Length(SocketString) > 1) and (Length(SocketString) > byte(SocketString[1])) do
             begin
-            ParseIPCCommand(copy(ss, 2, byte(ss[1])));
-            Delete(ss, 1, Succ(byte(ss[1])))
+                ParseIPCCommand(copy(SocketString, 2, byte(SocketString[1])));
+                Delete(SocketString, 1, Succ(byte(SocketString[1])))
             end
         end
     else
@@ -206,7 +206,7 @@
 end;
 
 procedure SendStat(sit: TStatInfoType; s: shortstring);
-const stc: array [TStatInfoType] of char = 'rDkKHTPsSB';
+const stc: array [TStatInfoType] of char = ('r', 'D', 'k', 'K', 'H', 'T', 'P', 's', 'S', 'B');
 var buf: shortstring;
 begin
 buf:= 'i' + stc[sit] + s;
@@ -229,6 +229,14 @@
     end
 end;
 
+procedure SendIPCc(c: char);
+var s: shortstring;
+begin
+    s[0]:= #1;
+    s[1]:= c;
+    SendIPC(s);
+end;
+
 procedure SendIPCRaw(p: pointer; len: Longword);
 begin
 if IPCSock <> nil then
@@ -259,7 +267,7 @@
 procedure SendIPCAndWaitReply(s: shortstring);
 begin
 SendIPC(s);
-SendIPC('?');
+SendIPCc('?');
 IPCWaitPongEvent
 end;
 
@@ -267,7 +275,7 @@
 begin
 inc(SendEmptyPacketTicks, Lag);
 if (SendEmptyPacketTicks >= cSendEmptyPacketTime) then
-    SendIPC('+')
+    SendIPCc('+')
 end;
 
 procedure NetGetNextCmd;
@@ -347,9 +355,11 @@
         't': ParseCommand('taunt ' + headcmd^.str[2], true);
         'h': ParseCommand('hogsay ' + copy(headcmd^.str, 2, Pred(headcmd^.len)), true);
         '1'..'5': ParseCommand('timer ' + headcmd^.cmd, true);
-        #128..char(128 + cMaxSlotIndex): ParseCommand('slot ' + char(byte(headcmd^.cmd) - 79), true)
         else
-            OutError('Unexpected protocol command: ' + headcmd^.cmd, True)
+            if (headcmd^.cmd >= #128) and (headcmd^.cmd <= char(128 + cMaxSlotIndex)) then
+                ParseCommand('slot ' + char(byte(headcmd^.cmd) - 79), true)
+                else
+                OutError('Unexpected protocol command: ' + headcmd^.cmd, True)
         end;
     RemoveCmd
     end;
@@ -418,14 +428,15 @@
 
 procedure initModule;
 begin
-    RegisterVariable('fatal', vtCommand, @chFatalError, true );
+    RegisterVariable('fatal', @chFatalError, true );
 
     IPCSock:= nil;
 
     headcmd:= nil;
     lastcmd:= nil;
-    isPonged:= false;   // was const
-
+    isPonged:= false;
+    SocketString:= '';
+    
     hiTicks:= 0;
     SendEmptyPacketTicks:= 0;
 end;
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/hedgewars/uInputHandler.pas	Wed May 02 23:53:45 2012 +0200
@@ -0,0 +1,459 @@
+(*
+ * Hedgewars, a free turn based strategy game
+ * Copyright (c) 2004-2012 Andrey Korotaev <unC0Rr@gmail.com>
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; version 2 of the License
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA
+ *)
+
+{$INCLUDE "options.inc"}
+
+unit uInputHandler;
+interface
+uses SDLh, uTypes;
+
+procedure initModule;
+procedure freeModule;
+
+function  KeyNameToCode(name: shortstring): word;
+procedure ProcessKbd;
+procedure ProcessMouse(event: TSDL_MouseButtonEvent; ButtonDown: boolean);
+procedure ProcessKey(event: TSDL_KeyboardEvent); inline;
+procedure ProcessKey(code: LongInt; KeyDown: boolean);
+
+procedure ResetKbd;
+procedure FreezeEnterKey;
+procedure InitKbdKeyTable;
+
+procedure SetBinds(var binds: TBinds);
+procedure SetDefaultBinds;
+
+procedure ControllerInit;
+procedure ControllerClose;
+procedure ControllerAxisEvent(joy, axis: Byte; value: Integer);
+procedure ControllerHatEvent(joy, hat, value: Byte);
+procedure ControllerButtonEvent(joy, button: Byte; pressed: Boolean);
+
+implementation
+uses uConsole, uCommands, uMisc, uVariables, uConsts, uUtils, uDebug;
+
+var tkbd, tkbdn: TKeyboardState;
+    quitKeyCode: Byte;
+    KeyNames: array [0..cKeyMaxIndex] of string[15];
+    CurrentBinds: TBinds;
+
+function KeyNameToCode(name: shortstring): word;
+var code: Word;
+begin
+    name:= LowerCase(name);
+    code:= cKeyMaxIndex;
+    while (code > 0) and (KeyNames[code] <> name) do dec(code);
+    KeyNameToCode:= code;
+end;
+
+procedure ProcessKbd;
+//var  i, j, k: LongInt;
+begin
+
+// move cursor/camera
+// TODO: Scale on screen dimensions and/or axis value (game controller)?
+//TODO what is this for?
+movecursor(5 * CursorMovementX, 5 * CursorMovementY);
+
+
+(* 
+TODO reimplement
+$IFNDEF MOBILE
+// Controller(s)
+k:= j; // should we test k for hitting the limit? sounds rather unlikely to ever reach it
+for j:= 0 to Pred(ControllerNumControllers) do
+    begin
+    for i:= 0 to Pred(ControllerNumAxes[j]) do
+        begin
+        if ControllerAxes[j][i] > 20000 then
+            tkbdn[k + 0]:= 1
+        else
+            tkbdn[k + 0]:= 0;
+        if ControllerAxes[j][i] < -20000 then
+            tkbdn[k + 1]:= 1
+        else
+            tkbdn[k + 1]:= 0;
+        inc(k, 2);
+        end;
+    for i:= 0 to Pred(ControllerNumHats[j]) do
+        begin
+        tkbdn[k + 0]:= ControllerHats[j][i] and SDL_HAT_UP;
+        tkbdn[k + 1]:= ControllerHats[j][i] and SDL_HAT_RIGHT;
+        tkbdn[k + 2]:= ControllerHats[j][i] and SDL_HAT_DOWN;
+        tkbdn[k + 3]:= ControllerHats[j][i] and SDL_HAT_LEFT;
+        inc(k, 4);
+        end;
+    for i:= 0 to Pred(ControllerNumButtons[j]) do
+        begin
+        tkbdn[k]:= ControllerButtons[j][i];
+        inc(k, 1);
+        end;
+    end;
+$ENDIF *)
+
+end;
+
+
+procedure ProcessKey(code: LongInt; KeyDown: boolean);
+var
+    Trusted: boolean;
+    s      : string;
+begin
+hideAmmoMenu:= false;
+Trusted:= (CurrentTeam <> nil)
+          and (not CurrentTeam^.ExtDriven)
+          and (CurrentHedgehog^.BotLevel = 0);
+
+tkbdn[code]:= ord(KeyDown);
+
+// ctrl/cmd + q to close engine and frontend
+if(KeyDown and (code = quitKeyCode)) then
+    begin
+{$IFDEF DARWIN}
+    if ((tkbdn[KeyNameToCode('left_meta')] = 1) or (tkbdn[KeyNameToCode('right_meta')] = 1)) then
+{$ELSE}
+    if ((tkbdn[KeyNameToCode('left_ctrl')] = 1) or (tkbdn[KeyNameToCode('right_ctrl')] = 1)) then
+{$ENDIF}
+        ParseCommand('halt', true);    
+    end;
+
+if CurrentBinds[code][0] <> #0 then
+    begin
+    if (code > 3) and (tkbdn[code] <> 0) and not ((CurrentBinds[code] = 'put') or (CurrentBinds[code] = 'ammomenu') or (CurrentBinds[code] = '+cur_u') or (CurrentBinds[code] = '+cur_d') or (CurrentBinds[code] = '+cur_l') or (CurrentBinds[code] = '+cur_r')) then hideAmmoMenu:= true;
+    if (tkbd[code] = 0) and (tkbdn[code] <> 0) then
+        begin
+        ParseCommand(CurrentBinds[code], Trusted);
+        if (CurrentTeam <> nil) and (not CurrentTeam^.ExtDriven) and (ReadyTimeLeft > 1) then
+            ParseCommand('gencmd R', true)
+        end
+    else if (CurrentBinds[code][1] = '+') and (tkbdn[code] = 0) and (tkbd[code] <> 0) then
+        begin
+        s:= CurrentBinds[code];
+        s[1]:= '-';
+        ParseCommand(s, Trusted);
+        if (CurrentTeam <> nil) and (not CurrentTeam^.ExtDriven) and (ReadyTimeLeft > 1) then
+            ParseCommand('gencmd R', true)
+        end;
+    tkbd[code]:= tkbdn[code]
+    end
+
+end;
+
+procedure ProcessKey(event: TSDL_KeyboardEvent); inline;
+begin
+    ProcessKey(event.keysym.sym, event.type_ = SDL_KEYDOWN);
+end;
+
+procedure ProcessMouse(event: TSDL_MouseButtonEvent; ButtonDown: boolean);
+begin
+case event.button of
+    SDL_BUTTON_LEFT:
+        ProcessKey(KeyNameToCode('mousel'), ButtonDown);
+    SDL_BUTTON_MIDDLE:
+        ProcessKey(KeyNameToCode('mousem'), ButtonDown);
+    SDL_BUTTON_RIGHT:
+        ProcessKey(KeyNameToCode('mouser'), ButtonDown);
+    SDL_BUTTON_WHEELDOWN:
+        ProcessKey(KeyNameToCode('wheeldown'), ButtonDown);
+    SDL_BUTTON_WHEELUP:
+        ProcessKey(KeyNameToCode('wheelup'), ButtonDown);
+    end;
+end;
+
+procedure ResetKbd;
+var j, k, t: LongInt;
+    i: LongInt;
+    pkbd: PByteArray;
+begin
+
+k:= SDL_GetMouseState(nil, nil);
+pkbd:=SDL_GetKeyState(@j);
+
+//TryDo(j < cKeyMaxIndex, 'SDL keys number is more than expected (' + IntToStr(j) + ')', true);
+
+for i:= 1 to pred(j) do
+    tkbdn[i]:= pkbd^[i];
+
+{$IFNDEF MOBILE}
+// Controller(s)
+k:= j; // should we test k for hitting the limit? sounds rather unlikely to ever reach it
+for j:= 0 to Pred(ControllerNumControllers) do
+    begin
+    for i:= 0 to Pred(ControllerNumAxes[j]) do
+        begin
+        if ControllerAxes[j][i] > 20000 then
+            tkbdn[k + 0]:= 1
+        else
+            tkbdn[k + 0]:= 0;
+        if ControllerAxes[j][i] < -20000 then
+            tkbdn[k + 1]:= 1
+        else
+            tkbdn[k + 1]:= 0;
+        inc(k, 2);
+        end;
+    for i:= 0 to Pred(ControllerNumHats[j]) do
+        begin
+        tkbdn[k + 0]:= ControllerHats[j][i] and SDL_HAT_UP;
+        tkbdn[k + 1]:= ControllerHats[j][i] and SDL_HAT_RIGHT;
+        tkbdn[k + 2]:= ControllerHats[j][i] and SDL_HAT_DOWN;
+        tkbdn[k + 3]:= ControllerHats[j][i] and SDL_HAT_LEFT;
+        inc(k, 4);
+        end;
+    for i:= 0 to Pred(ControllerNumButtons[j]) do
+        begin
+        tkbdn[k]:= ControllerButtons[j][i];
+        inc(k, 1);
+        end;
+    end;
+{$ENDIF}
+
+// what is this final loop for?
+for t:= 0 to cKeyMaxIndex do
+    tkbd[t]:= tkbdn[t]
+end;
+
+procedure InitKbdKeyTable;
+var i, j, k, t: LongInt;
+    s: string[15];
+begin
+//TODO in sdl13 this overrides some values (A and B) change indices to some other values at the back perhaps?
+KeyNames[1]:= 'mousel';
+KeyNames[2]:= 'mousem';
+KeyNames[3]:= 'mouser';
+KeyNames[4]:= 'wheelup';
+KeyNames[5]:= 'wheeldown';
+
+for i:= 6 to cKeyMaxIndex do
+    begin
+{$IFDEF SDL13}
+    s:= shortstring(SDL_GetScancodeName(i));
+{$ELSE}
+    s:= shortstring(sdl_getkeyname(i));
+{$ENDIF}
+    WriteToConsole(IntToStr(i) + ': ' + s + ' ' + IntToStr(cKeyMaxIndex));
+    if s = 'unknown key' then KeyNames[i]:= ''
+    else 
+        begin
+        for t:= 1 to Length(s) do
+            if s[t] = ' ' then
+                s[t]:= '_';
+        KeyNames[i]:= LowerCase(s)
+        end;
+    end;
+
+quitKeyCode:= KeyNameToCode('q');
+
+// get the size of keyboard array
+SDL_GetKeyState(@k);
+
+// Controller(s)
+for j:= 0 to Pred(ControllerNumControllers) do
+    begin
+    for i:= 0 to Pred(ControllerNumAxes[j]) do
+        begin
+        keynames[k + 0]:= 'j' + IntToStr(j) + 'a' + IntToStr(i) + 'u';
+        keynames[k + 1]:= 'j' + IntToStr(j) + 'a' + IntToStr(i) + 'd';
+        inc(k, 2);
+        end;
+    for i:= 0 to Pred(ControllerNumHats[j]) do
+        begin
+        keynames[k + 0]:= 'j' + IntToStr(j) + 'h' + IntToStr(i) + 'u';
+        keynames[k + 1]:= 'j' + IntToStr(j) + 'h' + IntToStr(i) + 'r';
+        keynames[k + 2]:= 'j' + IntToStr(j) + 'h' + IntToStr(i) + 'd';
+        keynames[k + 3]:= 'j' + IntToStr(j) + 'h' + IntToStr(i) + 'l';
+        inc(k, 4);
+        end;
+    for i:= 0 to Pred(ControllerNumButtons[j]) do
+        begin
+        keynames[k]:= 'j' + IntToStr(j) + 'b' + IntToStr(i);
+        inc(k, 1);
+        end;
+    end;
+
+DefaultBinds[KeyNameToCode('escape')]:= 'quit';
+DefaultBinds[KeyNameToCode('grave')]:= 'history';
+DefaultBinds[KeyNameToCode('delete')]:= 'rotmask';
+
+//numpad
+//DefaultBinds[265]:= '+volup';
+//DefaultBinds[256]:= '+voldown';
+
+DefaultBinds[KeyNameToCode('0')]:= '+volup';
+DefaultBinds[KeyNameToCode('9')]:= '+voldown';
+DefaultBinds[KeyNameToCode('c')]:= 'capture';
+DefaultBinds[KeyNameToCode('h')]:= 'findhh';
+DefaultBinds[KeyNameToCode('p')]:= 'pause';
+DefaultBinds[KeyNameToCode('s')]:= '+speedup';
+DefaultBinds[KeyNameToCode('t')]:= 'chat';
+DefaultBinds[KeyNameToCode('y')]:= 'confirm';
+
+DefaultBinds[KeyNameToCode('mousem')]:= 'zoomreset';
+DefaultBinds[KeyNameToCode('wheelup')]:= 'zoomout';
+DefaultBinds[KeyNameToCode('wheeldown')]:= 'zoomin';
+
+DefaultBinds[KeyNameToCode('f12')]:= 'fullscr';
+
+
+DefaultBinds[KeyNameToCode('mousel')]:= '/put';
+DefaultBinds[KeyNameToCode('mouser')]:= 'ammomenu';
+DefaultBinds[KeyNameToCode('backspace')]:= 'hjump';
+DefaultBinds[KeyNameToCode('tab')]:= 'switch';
+DefaultBinds[KeyNameToCode('return')]:= 'ljump';
+DefaultBinds[KeyNameToCode('space')]:= '+attack';
+DefaultBinds[KeyNameToCode('up')]:= '+up';
+DefaultBinds[KeyNameToCode('down')]:= '+down';
+DefaultBinds[KeyNameToCode('left')]:= '+left';
+DefaultBinds[KeyNameToCode('right')]:= '+right';
+DefaultBinds[KeyNameToCode('left_shift')]:= '+precise';
+
+for i:= 1 to 10 do DefaultBinds[KeyNameToCode('f'+IntToStr(i))]:= 'slot '+IntToStr(i);
+for i:= 1 to 5  do DefaultBinds[KeyNameToCode(IntToStr(i))]:= 'timer '+IntToStr(i);
+
+SetDefaultBinds();
+end;
+
+procedure SetBinds(var binds: TBinds);
+begin
+{$IFDEF MOBILE}
+    binds:= binds; // avoid hint
+    CurrentBinds:= DefaultBinds;
+{$ELSE}
+    CurrentBinds:= binds;
+{$ENDIF}
+end;
+
+procedure SetDefaultBinds;
+begin
+    CurrentBinds:= DefaultBinds;
+end;
+
+procedure FreezeEnterKey;
+begin
+    tkbd[3]:= 1;
+    tkbd[13]:= 1;
+    tkbd[27]:= 1;
+    tkbd[271]:= 1;
+end;
+
+var Controller: array [0..5] of PSDL_Joystick;
+
+procedure ControllerInit;
+var i, j: Integer;
+begin
+ControllerEnabled:= 0;
+{$IFDEF MOBILE}
+exit; // joystick subsystem disabled on iPhone
+{$ENDIF}
+
+SDL_InitSubSystem(SDL_INIT_JOYSTICK);
+ControllerNumControllers:= SDL_NumJoysticks();
+
+if ControllerNumControllers > 6 then
+    ControllerNumControllers:= 6;
+
+WriteLnToConsole('Number of game controllers: ' + IntToStr(ControllerNumControllers));
+
+if ControllerNumControllers > 0 then
+    begin
+    for j:= 0 to pred(ControllerNumControllers) do
+        begin
+        WriteLnToConsole('Using game controller: ' + SDL_JoystickName(j));
+        Controller[j]:= SDL_JoystickOpen(j);
+        if Controller[j] = nil then
+            WriteLnToConsole('* Failed to open game controller!')
+        else
+            begin
+            ControllerNumAxes[j]:= SDL_JoystickNumAxes(Controller[j]);
+            //ControllerNumBalls[j]:= SDL_JoystickNumBalls(Controller[j]);
+            ControllerNumHats[j]:= SDL_JoystickNumHats(Controller[j]);
+            ControllerNumButtons[j]:= SDL_JoystickNumButtons(Controller[j]);
+            WriteLnToConsole('* Number of axes: ' + IntToStr(ControllerNumAxes[j]));
+            //WriteLnToConsole('* Number of balls: ' + IntToStr(ControllerNumBalls[j]));
+            WriteLnToConsole('* Number of hats: ' + IntToStr(ControllerNumHats[j]));
+            WriteLnToConsole('* Number of buttons: ' + IntToStr(ControllerNumButtons[j]));
+            ControllerEnabled:= 1;
+
+            if ControllerNumAxes[j] > 20 then
+                ControllerNumAxes[j]:= 20;
+            //if ControllerNumBalls[j] > 20 then ControllerNumBalls[j]:= 20;
+            
+            if ControllerNumHats[j] > 20 then
+                ControllerNumHats[j]:= 20;
+                
+            if ControllerNumButtons[j] > 20 then
+                ControllerNumButtons[j]:= 20;
+
+            // reset all buttons/axes
+            for i:= 0 to pred(ControllerNumAxes[j]) do
+                ControllerAxes[j][i]:= 0;
+            (*for i:= 0 to pred(ControllerNumBalls[j]) do
+                begin
+                ControllerBalls[j][i][0]:= 0;
+                ControllerBalls[j][i][1]:= 0;
+                end;*)
+            for i:= 0 to pred(ControllerNumHats[j]) do
+                ControllerHats[j][i]:= SDL_HAT_CENTERED;
+            for i:= 0 to pred(ControllerNumButtons[j]) do
+                ControllerButtons[j][i]:= 0;
+            end;
+        end;
+    // enable event generation/controller updating
+    SDL_JoystickEventState(1);
+    end
+else
+    WriteLnToConsole('Not using any game controller');
+end;
+
+procedure ControllerClose;
+var j: Integer;
+begin
+    if ControllerEnabled > 0 then
+        for j:= 0 to pred(ControllerNumControllers) do
+            SDL_JoystickClose(Controller[j]);
+end;
+
+procedure ControllerAxisEvent(joy, axis: Byte; value: Integer);
+begin
+    ControllerAxes[joy][axis]:= value;
+end;
+
+procedure ControllerHatEvent(joy, hat, value: Byte);
+begin
+    ControllerHats[joy][hat]:= value;
+end;
+
+procedure ControllerButtonEvent(joy, button: Byte; pressed: Boolean);
+begin
+    if pressed then
+        ControllerButtons[joy][button]:= 1
+    else
+        ControllerButtons[joy][button]:= 0;
+end;
+
+procedure initModule;
+begin
+    wheelUp:= false;
+    wheelDown:= false;
+end;
+
+procedure freeModule;
+begin
+
+end;
+
+end.
--- a/hedgewars/uKeys.pas	Sun Apr 01 15:23:34 2012 +0200
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,539 +0,0 @@
-(*
- * Hedgewars, a free turn based strategy game
- * Copyright (c) 2004-2012 Andrey Korotaev <unC0Rr@gmail.com>
- *
- * This program is free software; you can redistribute it and/or modify
- * it under the terms of the GNU General Public License as published by
- * the Free Software Foundation; version 2 of the License
- *
- * This program is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
- * GNU General Public License for more details.
- *
- * You should have received a copy of the GNU General Public License
- * along with this program; if not, write to the Free Software
- * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA
- *)
-
-{$INCLUDE "options.inc"}
-
-unit uKeys;
-interface
-uses SDLh, uTypes;
-
-procedure initModule;
-procedure freeModule;
-
-function  KeyNameToCode(name: shortstring): word;
-procedure ProcessKbd;
-procedure ResetKbd;
-procedure FreezeEnterKey;
-procedure InitKbdKeyTable;
-
-procedure SetBinds(var binds: TBinds);
-procedure SetDefaultBinds;
-
-procedure ControllerInit;
-procedure ControllerClose;
-procedure ControllerAxisEvent(joy, axis: Byte; value: Integer);
-procedure ControllerHatEvent(joy, hat, value: Byte);
-procedure ControllerButtonEvent(joy, button: Byte; pressed: Boolean);
-
-{$IFDEF MOBILE}
-procedure setiPhoneBinds;
-{$ENDIF}
-
-implementation
-uses uConsole, uCommands, uMisc, uVariables, uConsts, uUtils, uDebug;
-
-var tkbd, tkbdn: TKeyboardState;
-    KeyNames: array [0..cKeyMaxIndex] of string[15];
-
-function KeyNameToCode(name: shortstring): word;
-var code: Word;
-begin
-    code:= cKeyMaxIndex;
-    while (code > 0) and (KeyNames[code] <> name) do dec(code);
-    KeyNameToCode:= code;
-end;
-
-
-procedure ProcessKbd;
-var  i, j, k: LongInt;
-     s: shortstring;
-     Trusted: boolean;
-{$IFNDEF MOBILE}pkbd: PByteArray;{$ENDIF}
-begin
-hideAmmoMenu:= false;
-Trusted:= (CurrentTeam <> nil)
-          and (not CurrentTeam^.ExtDriven)
-          and (CurrentHedgehog^.BotLevel = 0);
-
-// move cursor/camera
-// TODO: Scale on screen dimensions and/or axis value (game controller)?
-movecursor(5 * CursorMovementX, 5 * CursorMovementY);
-
-k:= SDL_GetMouseState(nil, nil);
-
-{$IFDEF MOBILE}
-SDL_GetKeyState(@j);
-{$ELSE}
-pkbd:= SDL_GetKeyState(@j);
-for i:= 6 to pred(j) do // first 6 will be overwritten
-    tkbdn[i]:= pkbd^[i];
-{$ENDIF}
-
-// mouse buttons
-{$IFDEF DARWIN}
-tkbdn[1]:= ((k and 1) and not (tkbdn[306] or tkbdn[305]));
-tkbdn[3]:= ((k and 1) and (tkbdn[306] or tkbdn[305])) or (k and 4);
-{$ELSE}
-tkbdn[1]:= (k and 1);
-tkbdn[3]:= ((k shr 2) and 1);
-{$ENDIF}
-tkbdn[2]:= ((k shr 1) and 1);
-
-// mouse wheels
-tkbdn[4]:= ord(wheelDown);
-tkbdn[5]:= ord(wheelUp);
-wheelUp:= false;
-wheelDown:= false;
-
-{$IFDEF MOBILE}
-setiPhoneBinds();
-{$ELSE}
-// Controller(s)
-k:= j; // should we test k for hitting the limit? sounds rather unlikely to ever reach it
-for j:= 0 to Pred(ControllerNumControllers) do
-    begin
-    for i:= 0 to Pred(ControllerNumAxes[j]) do
-        begin
-        if ControllerAxes[j][i] > 20000 then
-            tkbdn[k + 0]:= 1
-        else
-            tkbdn[k + 0]:= 0;
-        if ControllerAxes[j][i] < -20000 then
-            tkbdn[k + 1]:= 1
-        else
-            tkbdn[k + 1]:= 0;
-        inc(k, 2);
-        end;
-    for i:= 0 to Pred(ControllerNumHats[j]) do
-        begin
-        tkbdn[k + 0]:= ControllerHats[j][i] and SDL_HAT_UP;
-        tkbdn[k + 1]:= ControllerHats[j][i] and SDL_HAT_RIGHT;
-        tkbdn[k + 2]:= ControllerHats[j][i] and SDL_HAT_DOWN;
-        tkbdn[k + 3]:= ControllerHats[j][i] and SDL_HAT_LEFT;
-        inc(k, 4);
-        end;
-    for i:= 0 to Pred(ControllerNumButtons[j]) do
-        begin
-        tkbdn[k]:= ControllerButtons[j][i];
-        inc(k, 1);
-        end;
-    end;
-{$ENDIF}
-
-// ctrl/cmd + q to close engine and frontend
-{$IFDEF DARWIN}
-    if ((tkbdn[KeyNameToCode('left_meta')] = 1) or (tkbdn[KeyNameToCode('right_meta')] = 1)) then
-        {$ELSE}
-    if ((tkbdn[KeyNameToCode('left_ctrl')] = 1) or (tkbdn[KeyNameToCode('right_ctrl')] = 1)) then
-        {$ENDIF}
-    begin
-        if tkbdn[KeyNameToCode('q')] = 1 then ParseCommand ('halt', true)
-    end;
-
-// now process strokes
-for i:= 0 to cKeyMaxIndex do
-if CurrentBinds[i][0] <> #0 then
-    begin
-    if (i > 3) and (tkbdn[i] <> 0) and not ((CurrentBinds[i] = 'put') or (CurrentBinds[i] = 'ammomenu') or (CurrentBinds[i] = '+cur_u') or (CurrentBinds[i] = '+cur_d') or (CurrentBinds[i] = '+cur_l') or (CurrentBinds[i] = '+cur_r')) then hideAmmoMenu:= true;
-    if (tkbd[i] = 0) and (tkbdn[i] <> 0) then
-        begin
-        ParseCommand(CurrentBinds[i], Trusted);
-        if (CurrentTeam <> nil) and (not CurrentTeam^.ExtDriven) and (ReadyTimeLeft > 1) then
-            ParseCommand('gencmd R', true)
-        end
-    else if (CurrentBinds[i][1] = '+') and (tkbdn[i] = 0) and (tkbd[i] <> 0) then
-        begin
-        s:= CurrentBinds[i];
-        s[1]:= '-';
-        ParseCommand(s, Trusted);
-        if (CurrentTeam <> nil) and (not CurrentTeam^.ExtDriven) and (ReadyTimeLeft > 1) then
-            ParseCommand('gencmd R', true)
-        end;
-    tkbd[i]:= tkbdn[i]
-    end
-end;
-
-procedure ResetKbd;
-var j, k, t: LongInt;
-{$IFNDEF MOBILE}
-    i: LongInt;
-    pkbd: PByteArray;
-{$ENDIF}
-begin
-
-k:= SDL_GetMouseState(nil, nil);
-{$IFNDEF MOBILE}pkbd:={$ENDIF}SDL_GetKeyState(@j);
-
-TryDo(j < cKeyMaxIndex, 'SDL keys number is more than expected (' + IntToStr(j) + ')', true);
-
-{$IFNDEF MOBILE}
-for i:= 1 to pred(j) do
-    tkbdn[i]:= pkbd^[i];
-{$ENDIF}
-
-// mouse buttons
-{$IFDEF DARWIN}
-tkbdn[1]:= ((k and 1) and not (tkbdn[306] or tkbdn[305]));
-tkbdn[3]:= ((k and 1) and (tkbdn[306] or tkbdn[305])) or (k and 4);
-{$ELSE}
-tkbdn[1]:= (k and 1);
-tkbdn[3]:= ((k shr 2) and 1);
-{$ENDIF}
-tkbdn[2]:= ((k shr 1) and 1);
-
-// mouse wheels
-tkbdn[4]:= ord(wheelDown);
-tkbdn[5]:= ord(wheelUp);
-wheelUp:= false;
-wheelDown:= false;
-
-{$IFDEF MOBILE}
-setiPhoneBinds();
-{$ELSE}
-// Controller(s)
-k:= j; // should we test k for hitting the limit? sounds rather unlikely to ever reach it
-for j:= 0 to Pred(ControllerNumControllers) do
-    begin
-    for i:= 0 to Pred(ControllerNumAxes[j]) do
-        begin
-        if ControllerAxes[j][i] > 20000 then
-            tkbdn[k + 0]:= 1
-        else
-            tkbdn[k + 0]:= 0;
-        if ControllerAxes[j][i] < -20000 then
-            tkbdn[k + 1]:= 1
-        else
-            tkbdn[k + 1]:= 0;
-        inc(k, 2);
-        end;
-    for i:= 0 to Pred(ControllerNumHats[j]) do
-        begin
-        tkbdn[k + 0]:= ControllerHats[j][i] and SDL_HAT_UP;
-        tkbdn[k + 1]:= ControllerHats[j][i] and SDL_HAT_RIGHT;
-        tkbdn[k + 2]:= ControllerHats[j][i] and SDL_HAT_DOWN;
-        tkbdn[k + 3]:= ControllerHats[j][i] and SDL_HAT_LEFT;
-        inc(k, 4);
-        end;
-    for i:= 0 to Pred(ControllerNumButtons[j]) do
-        begin
-        tkbdn[k]:= ControllerButtons[j][i];
-        inc(k, 1);
-        end;
-    end;
-{$ENDIF}
-
-// what is this final loop for?
-for t:= 0 to cKeyMaxIndex do
-    tkbd[t]:= tkbdn[t]
-end;
-
-procedure InitKbdKeyTable;
-var i, j, k, t: LongInt;
-    s: string[15];
-begin
-KeyNames[1]:= 'mousel';
-KeyNames[2]:= 'mousem';
-KeyNames[3]:= 'mouser';
-KeyNames[4]:= 'wheelup';
-KeyNames[5]:= 'wheeldown';
-
-for i:= 6 to cKeyMaxIndex do
-    begin
-    s:= shortstring(sdl_getkeyname(i));
-    //writeln(stdout,IntToStr(i) + ': ' + s);
-    if s = 'unknown key' then KeyNames[i]:= ''
-    else 
-        begin
-        for t:= 1 to Length(s) do
-            if s[t] = ' ' then
-                s[t]:= '_';
-        KeyNames[i]:= s
-        end;
-    end;
-
-//for i:= 0 to cKeyMaxIndex do writeln(stdout,IntToStr(i) + ': ' + KeyNames[i]);
-
-// get the size of keyboard array
-SDL_GetKeyState(@k);
-
-// Controller(s)
-for j:= 0 to Pred(ControllerNumControllers) do
-    begin
-    for i:= 0 to Pred(ControllerNumAxes[j]) do
-        begin
-        keynames[k + 0]:= 'j' + IntToStr(j) + 'a' + IntToStr(i) + 'u';
-        keynames[k + 1]:= 'j' + IntToStr(j) + 'a' + IntToStr(i) + 'd';
-        inc(k, 2);
-        end;
-    for i:= 0 to Pred(ControllerNumHats[j]) do
-        begin
-        keynames[k + 0]:= 'j' + IntToStr(j) + 'h' + IntToStr(i) + 'u';
-        keynames[k + 1]:= 'j' + IntToStr(j) + 'h' + IntToStr(i) + 'r';
-        keynames[k + 2]:= 'j' + IntToStr(j) + 'h' + IntToStr(i) + 'd';
-        keynames[k + 3]:= 'j' + IntToStr(j) + 'h' + IntToStr(i) + 'l';
-        inc(k, 4);
-        end;
-    for i:= 0 to Pred(ControllerNumButtons[j]) do
-        begin
-        keynames[k]:= 'j' + IntToStr(j) + 'b' + IntToStr(i);
-        inc(k, 1);
-        end;
-    end;
-
-DefaultBinds[ 27]:= 'quit';
-DefaultBinds[ 96]:= 'history';
-DefaultBinds[127]:= 'rotmask';
-
-//numpad
-//DefaultBinds[265]:= '+volup';
-//DefaultBinds[256]:= '+voldown';
-
-DefaultBinds[KeyNameToCode('0')]:= '+volup';
-DefaultBinds[KeyNameToCode('9')]:= '+voldown';
-DefaultBinds[KeyNameToCode('c')]:= 'capture';
-DefaultBinds[KeyNameToCode('h')]:= 'findhh';
-DefaultBinds[KeyNameToCode('p')]:= 'pause';
-DefaultBinds[KeyNameToCode('s')]:= '+speedup';
-DefaultBinds[KeyNameToCode('t')]:= 'chat';
-DefaultBinds[KeyNameToCode('y')]:= 'confirm';
-
-DefaultBinds[KeyNameToCode('mousem')]:= 'zoomreset';
-DefaultBinds[KeyNameToCode('wheelup')]:= 'zoomout';
-DefaultBinds[KeyNameToCode('wheeldown')]:= 'zoomin';
-
-DefaultBinds[KeyNameToCode('f12')]:= 'fullscr';
-
-
-DefaultBinds[ 1]:= '/put';
-DefaultBinds[ 3]:= 'ammomenu';
-DefaultBinds[ 8]:= 'hjump';
-DefaultBinds[ 9]:= 'switch';
-DefaultBinds[13]:= 'ljump';
-DefaultBinds[32]:= '+attack';
-{$IFDEF MOBILE}
-DefaultBinds[23]:= '+up';
-DefaultBinds[24]:= '+down';
-DefaultBinds[25]:= '+left';
-DefaultBinds[26]:= '+right';
-DefaultBinds[27]:= '+precise';
-DefaultBinds[44]:= 'chat';
-DefaultBinds[55]:= 'pause';
-{$ELSE}
-DefaultBinds[KeyNameToCode('up')]:= '+up';
-DefaultBinds[KeyNameToCode('down')]:= '+down';
-DefaultBinds[KeyNameToCode('left')]:= '+left';
-DefaultBinds[KeyNameToCode('right')]:= '+right';
-DefaultBinds[KeyNameToCode('left_shift')]:= '+precise';
-{$ENDIF}
-
-for i:= 1 to 10 do DefaultBinds[KeyNameToCode('f'+IntToStr(i))]:= 'slot '+IntToStr(i);
-for i:= 1 to 5  do DefaultBinds[KeyNameToCode(IntToStr(i))]:= 'timer '+IntToStr(i);
-
-SetDefaultBinds();
-end;
-
-procedure SetBinds(var binds: TBinds);
-begin
-{$IFDEF MOBILE}
-    binds:= binds; // avoid hint
-    CurrentBinds:= DefaultBinds;
-{$ELSE}
-    CurrentBinds:= binds;
-{$ENDIF}
-end;
-
-procedure SetDefaultBinds;
-begin
-    CurrentBinds:= DefaultBinds;
-end;
-
-{$IFDEF MOBILE}
-procedure setiPhoneBinds;
-begin
-    tkbdn[ 1]:= ord(leftClick);
-    tkbdn[ 2]:= ord(middleClick);
-    tkbdn[ 3]:= ord(rightClick);
-
-    tkbdn[23]:= ord(upKey);
-    tkbdn[24]:= ord(downKey);
-    tkbdn[25]:= ord(leftKey);
-    tkbdn[26]:= ord(rightKey);
-    tkbdn[27]:= ord(preciseKey);
-
-    tkbdn[ 8]:= ord(backspaceKey);
-    tkbdn[ 9]:= ord(tabKey);
-    tkbdn[13]:= ord(enterKey);
-    tkbdn[32]:= ord(spaceKey);
-
-    tkbdn[44]:= ord(chatAction);
-    tkbdn[55]:= ord(pauseAction);
-
-    // set to false the keys that only need one stoke
-    leftClick:= false;
-    middleClick:= false;
-    rightClick:= false;
-
-    tabKey:= false;
-    enterKey:= false;
-    backspaceKey:= false;
-
-    chatAction:= false;
-    pauseAction:= false;
-end;
-{$ENDIF}
-
-procedure FreezeEnterKey;
-begin
-    tkbd[3]:= 1;
-    tkbd[13]:= 1;
-    tkbd[27]:= 1;
-    tkbd[271]:= 1;
-end;
-
-var Controller: array [0..5] of PSDL_Joystick;
-
-procedure ControllerInit;
-var i, j: Integer;
-begin
-ControllerEnabled:= 0;
-{$IFDEF MOBILE}
-exit; // joystick subsystem disabled on iPhone
-{$ENDIF}
-
-SDL_InitSubSystem(SDL_INIT_JOYSTICK);
-ControllerNumControllers:= SDL_NumJoysticks();
-
-if ControllerNumControllers > 6 then
-    ControllerNumControllers:= 6;
-
-WriteLnToConsole('Number of game controllers: ' + IntToStr(ControllerNumControllers));
-
-if ControllerNumControllers > 0 then
-    begin
-    for j:= 0 to pred(ControllerNumControllers) do
-        begin
-        WriteLnToConsole('Using game controller: ' + SDL_JoystickName(j));
-        Controller[j]:= SDL_JoystickOpen(j);
-        if Controller[j] = nil then
-            WriteLnToConsole('* Failed to open game controller!')
-        else
-            begin
-            ControllerNumAxes[j]:= SDL_JoystickNumAxes(Controller[j]);
-            //ControllerNumBalls[j]:= SDL_JoystickNumBalls(Controller[j]);
-            ControllerNumHats[j]:= SDL_JoystickNumHats(Controller[j]);
-            ControllerNumButtons[j]:= SDL_JoystickNumButtons(Controller[j]);
-            WriteLnToConsole('* Number of axes: ' + IntToStr(ControllerNumAxes[j]));
-            //WriteLnToConsole('* Number of balls: ' + IntToStr(ControllerNumBalls[j]));
-            WriteLnToConsole('* Number of hats: ' + IntToStr(ControllerNumHats[j]));
-            WriteLnToConsole('* Number of buttons: ' + IntToStr(ControllerNumButtons[j]));
-            ControllerEnabled:= 1;
-
-            if ControllerNumAxes[j] > 20 then
-                ControllerNumAxes[j]:= 20;
-            //if ControllerNumBalls[j] > 20 then ControllerNumBalls[j]:= 20;
-            
-            if ControllerNumHats[j] > 20 then
-                ControllerNumHats[j]:= 20;
-                
-            if ControllerNumButtons[j] > 20 then
-                ControllerNumButtons[j]:= 20;
-
-            // reset all buttons/axes
-            for i:= 0 to pred(ControllerNumAxes[j]) do
-                ControllerAxes[j][i]:= 0;
-            (*for i:= 0 to pred(ControllerNumBalls[j]) do
-                begin
-                ControllerBalls[j][i][0]:= 0;
-                ControllerBalls[j][i][1]:= 0;
-                end;*)
-            for i:= 0 to pred(ControllerNumHats[j]) do
-                ControllerHats[j][i]:= SDL_HAT_CENTERED;
-            for i:= 0 to pred(ControllerNumButtons[j]) do
-                ControllerButtons[j][i]:= 0;
-            end;
-        end;
-    // enable event generation/controller updating
-    SDL_JoystickEventState(1);
-    end
-else
-    WriteLnToConsole('Not using any game controller');
-end;
-
-procedure ControllerClose;
-var j: Integer;
-begin
-    if ControllerEnabled > 0 then
-        for j:= 0 to pred(ControllerNumControllers) do
-            SDL_JoystickClose(Controller[j]);
-end;
-
-procedure ControllerAxisEvent(joy, axis: Byte; value: Integer);
-begin
-    ControllerAxes[joy][axis]:= value;
-end;
-
-procedure ControllerHatEvent(joy, hat, value: Byte);
-begin
-    ControllerHats[joy][hat]:= value;
-end;
-
-procedure ControllerButtonEvent(joy, button: Byte; pressed: Boolean);
-begin
-    if pressed then
-        ControllerButtons[joy][button]:= 1
-    else
-        ControllerButtons[joy][button]:= 0;
-end;
-
-procedure initModule;
-begin
-    wheelUp:= false;
-    wheelDown:= false;
-{$IFDEF HWLIBRARY}
-    // this function is called by HW_allKeysUp so be careful
-
-    // mouse emulation
-    leftClick:= false;
-    middleClick:= false;
-    rightClick:= false;
-
-    // arrow key emulation
-    upKey:= false;
-    downKey:= false;
-    rightKey:= false;
-    leftKey:= false;
-    preciseKey:= false;
-
-    // action key emulation
-    backspaceKey:= false;
-    spaceKey:= false;
-    enterKey:= false;
-    tabKey:= false;
-
-    // other key emulation
-    chatAction:= false;
-    pauseAction:= false;
-{$ENDIF}
-end;
-
-procedure freeModule;
-begin
-
-end;
-
-end.
--- a/hedgewars/uLand.pas	Sun Apr 01 15:23:34 2012 +0200
+++ b/hedgewars/uLand.pas	Wed May 02 23:53:45 2012 +0200
@@ -57,7 +57,7 @@
     // freed in freeModule() below
     LandBackSurface:= LoadImage(UserPathz[ptCurrTheme] + '/LandBackTex', ifIgnoreCaps or ifTransparent);
     if LandBackSurface = nil then LandBackSurface:= LoadImage(Pathz[ptCurrTheme] + '/LandBackTex', ifIgnoreCaps or ifTransparent);
-    if (LandBackSurface <> nil) and cGrayScale then Surface2GrayScale(LandBackSurface);
+    if (LandBackSurface <> nil) and GrayScale then Surface2GrayScale(LandBackSurface);
 
     tmpsurf:= LoadImage(UserPathz[ptCurrTheme] + '/Border', ifIgnoreCaps or ifTransparent);
     if tmpsurf = nil then tmpsurf:= LoadImage(Pathz[ptCurrTheme] + '/Border', ifCritical or ifIgnoreCaps or ifTransparent);
@@ -458,7 +458,7 @@
         LandBackSurface:= LoadImage(UserPathz[ptCurrTheme] + '/LandBackTex', ifIgnoreCaps or ifTransparent);
         if LandBackSurface = nil then
             LandBackSurface:= LoadImage(Pathz[ptCurrTheme] + '/LandBackTex', ifIgnoreCaps or ifTransparent);
-        if (LandBackSurface <> nil) and cGrayScale then
+        if (LandBackSurface <> nil) and GrayScale then
             Surface2GrayScale(LandBackSurface)
         end;
 end;
@@ -647,7 +647,7 @@
 
 FreeLandObjects;
 
-if cGrayScale then
+if GrayScale then
     begin
     if (cReducedQuality and rqBlurryLand) = 0 then
         for x:= leftX to rightX do
@@ -728,7 +728,7 @@
 begin
     adler:= 1;
     for i:= 0 to LAND_HEIGHT-1 do
-        Adler32Update(adler, @Land[i,0], LAND_WIDTH);
+        adler:= Adler32Update(adler, @Land[i,0], LAND_WIDTH);
     s:= 'M' + IntToStr(adler) + cScriptName;
 
     chLandCheck(s);
@@ -737,8 +737,8 @@
 
 procedure initModule;
 begin
-    RegisterVariable('landcheck', vtCommand, @chLandCheck, false);
-    RegisterVariable('sendlanddigest', vtCommand, @chSendLandDigest, false);
+    RegisterVariable('landcheck', @chLandCheck, false);
+    RegisterVariable('sendlanddigest', @chSendLandDigest, false);
 
     LandBackSurface:= nil;
     digest:= '';
--- a/hedgewars/uLandGraphics.pas	Sun Apr 01 15:23:34 2012 +0200
+++ b/hedgewars/uLandGraphics.pas	Wed May 02 23:53:45 2012 +0200
@@ -328,9 +328,9 @@
         if ((Land[t, i] and lfBasic) <> 0) or ((Land[t, i] and lfObject) <> 0) then
             begin
             if (cReducedQuality and rqBlurryLand) = 0 then
-                LandPixels[t, i]:= cExplosionBorderColor
+                LandPixels[t, i]:= ExplosionBorderColor
             else
-                LandPixels[t div 2, i div 2]:= cExplosionBorderColor;
+                LandPixels[t div 2, i div 2]:= ExplosionBorderColor;
 
             Land[t, i]:= Land[t, i] or lfDamaged;
             //Despeckle(i, t);
@@ -343,9 +343,9 @@
         if ((Land[t, i] and lfBasic) <> 0) or ((Land[t, i] and lfObject) <> 0) then
             begin
             if (cReducedQuality and rqBlurryLand) = 0 then
-                LandPixels[t, i]:= cExplosionBorderColor
+                LandPixels[t, i]:= ExplosionBorderColor
             else
-                LandPixels[t div 2, i div 2]:= cExplosionBorderColor;
+                LandPixels[t div 2, i div 2]:= ExplosionBorderColor;
             Land[t, i]:= Land[t, i] or lfDamaged;
             //Despeckle(i, t);
             LandDirty[t div 32, i div 32]:= 1;
@@ -357,9 +357,9 @@
         if ((Land[t, i] and lfBasic) <> 0) or ((Land[t, i] and lfObject) <> 0) then
             begin
             if (cReducedQuality and rqBlurryLand) = 0 then
-                LandPixels[t, i]:= cExplosionBorderColor
+                LandPixels[t, i]:= ExplosionBorderColor
             else
-               LandPixels[t div 2, i div 2]:= cExplosionBorderColor;
+               LandPixels[t div 2, i div 2]:= ExplosionBorderColor;
 
             Land[t, i]:= Land[t, i] or lfDamaged;
             //Despeckle(i, t);
@@ -372,9 +372,9 @@
         if ((Land[t, i] and lfBasic) <> 0) or ((Land[t, i] and lfObject) <> 0) then
             begin
             if (cReducedQuality and rqBlurryLand) = 0 then
-                LandPixels[t, i]:= cExplosionBorderColor
+                LandPixels[t, i]:= ExplosionBorderColor
             else
-                LandPixels[t div 2, i div 2]:= cExplosionBorderColor;
+                LandPixels[t div 2, i div 2]:= ExplosionBorderColor;
 
             Land[t, i]:= Land[t, i] or lfDamaged;
             //Despeckle(i, y - dy);
@@ -503,9 +503,9 @@
             if ((Land[ty, tx] and lfBasic) <> 0) or ((Land[ty, tx] and lfObject) <> 0) then
                 begin
                  if (cReducedQuality and rqBlurryLand) = 0 then
-                    LandPixels[ty, tx]:= cExplosionBorderColor
+                    LandPixels[ty, tx]:= ExplosionBorderColor
                 else
-                    LandPixels[ty div 2, tx div 2]:= cExplosionBorderColor;
+                    LandPixels[ty div 2, tx div 2]:= ExplosionBorderColor;
 
                 Land[ty, tx]:= Land[ty, tx] or lfDamaged;
                 LandDirty[ty div 32, tx div 32]:= 1;
@@ -555,9 +555,9 @@
             LandDirty[ty div 32, tx div 32]:= 1
             end;
         if (cReducedQuality and rqBlurryLand) = 0 then
-            LandPixels[ty, tx]:= cExplosionBorderColor
+            LandPixels[ty, tx]:= ExplosionBorderColor
         else
-            LandPixels[ty div 2, tx div 2]:= cExplosionBorderColor
+            LandPixels[ty div 2, tx div 2]:= ExplosionBorderColor
         end
     end;
     nx:= nx - dY;
@@ -581,9 +581,9 @@
             if despeckle then
                 LandDirty[ty div 32, tx div 32]:= 1;
             if (cReducedQuality and rqBlurryLand) = 0 then
-                LandPixels[ty, tx]:= cExplosionBorderColor
+                LandPixels[ty, tx]:= ExplosionBorderColor
             else
-                LandPixels[ty div 2, tx div 2]:= cExplosionBorderColor
+                LandPixels[ty div 2, tx div 2]:= ExplosionBorderColor
             end
         end;
     X:= nx;
@@ -624,9 +624,9 @@
         if despeckle then
             LandDirty[ty div 32, tx div 32]:= 1;
         if (cReducedQuality and rqBlurryLand) = 0 then
-            LandPixels[ty, tx]:= cExplosionBorderColor
+            LandPixels[ty, tx]:= ExplosionBorderColor
         else
-            LandPixels[ty div 2, tx div 2]:= cExplosionBorderColor
+            LandPixels[ty div 2, tx div 2]:= ExplosionBorderColor
         end
         end;
     nx:= nx - dY;
@@ -650,9 +650,9 @@
         if despeckle then
             LandDirty[ty div 32, tx div 32]:= 1;
         if (cReducedQuality and rqBlurryLand) = 0 then
-            LandPixels[ty, tx]:= cExplosionBorderColor
+            LandPixels[ty, tx]:= ExplosionBorderColor
         else
-            LandPixels[ty div 2, tx div 2]:= cExplosionBorderColor
+            LandPixels[ty div 2, tx div 2]:= ExplosionBorderColor
         end
     end;
     nx:= nx - dY;
@@ -672,6 +672,7 @@
     p: PByteArray;
     Image: PSDL_Surface;
 begin
+TryPlaceOnLand:= false;
 numFramesFirstCol:= SpritesData[Obj].imageHeight div SpritesData[Obj].Height;
 
 TryDo(SpritesData[Obj].Surface <> nil, 'Assert SpritesData[Obj].Surface failed', true);
@@ -693,12 +694,12 @@
         begin
         for x:= 0 to Pred(w) do
             if (PLongword(@(p^[x * 4]))^) <> 0 then
-                if ((cpY + y) <= Longint(topY)) or ((cpY + y) >= LAND_HEIGHT)
-                or ((cpX + x) <= Longint(leftX)) or ((cpX + x) >= Longint(rightX)) or (Land[cpY + y, cpX + x] <> 0) then
+                if ((cpY + y) <= Longint(topY)) or ((cpY + y) >= LAND_HEIGHT) or
+                   ((cpX + x) <= Longint(leftX)) or ((cpX + x) >= Longint(rightX)) or (Land[cpY + y, cpX + x] <> 0) then
                     begin
-                    if SDL_MustLock(Image) then
-                        SDL_UnlockSurface(Image);
-                    exit(false)
+                        if SDL_MustLock(Image) then
+                            SDL_UnlockSurface(Image);
+                        exit;
                     end;
         p:= @(p^[Image^.pitch]);
         end;
@@ -758,58 +759,61 @@
 var nx, ny, i, j, c, xx, yy: LongInt;
     pixelsweep: boolean;
 begin
-if (cReducedQuality and rqBlurryLand) = 0 then
+    Despeckle:= true;
+
+    if (cReducedQuality and rqBlurryLand) = 0 then
     begin
-    xx:= X;
-    yy:= Y;
+        xx:= X;
+        yy:= Y;
     end
-else
+    else
     begin
-    xx:= X div 2;
-    yy:= Y div 2;
+        xx:= X div 2;
+        yy:= Y div 2;
     end;
-pixelsweep:= ((Land[Y, X] and $FF00) = 0) and (LandPixels[yy, xx] <> 0);
-if (((Land[Y, X] and lfDamaged) <> 0) and ((Land[Y, X] and lfIndestructible) = 0)) or pixelsweep then
+
+    pixelsweep:= ((Land[Y, X] and $FF00) = 0) and (LandPixels[yy, xx] <> 0);
+    if (((Land[Y, X] and lfDamaged) <> 0) and ((Land[Y, X] and lfIndestructible) = 0)) or pixelsweep then
     begin
-    c:= 0;
-    for i:= -1 to 1 do
-        for j:= -1 to 1 do
-            if (i <> 0) or (j <> 0) then
+        c:= 0;
+        for i:= -1 to 1 do
+            for j:= -1 to 1 do
+                if (i <> 0) or (j <> 0) then
                 begin
-                ny:= Y + i;
-                nx:= X + j;
-                if ((ny and LAND_HEIGHT_MASK) = 0) and ((nx and LAND_WIDTH_MASK) = 0) then
+                    ny:= Y + i;
+                    nx:= X + j;
+                    if ((ny and LAND_HEIGHT_MASK) = 0) and ((nx and LAND_WIDTH_MASK) = 0) then
                     begin
-                    if pixelsweep then
+                        if pixelsweep then
                         begin
-                        if ((cReducedQuality and rqBlurryLand) <> 0) then
+                            if ((cReducedQuality and rqBlurryLand) <> 0) then
                             begin
-                            nx:= nx div 2;
-                            ny:= ny div 2
+                                nx:= nx div 2;
+                                ny:= ny div 2
                             end;
-                        if LandPixels[ny, nx] <> 0 then
-                            inc(c);
+                            if LandPixels[ny, nx] <> 0 then
+                                inc(c);
                         end
                     else if Land[ny, nx] > 255 then
                         inc(c);
                     end
                 end;
 
-    if c < 4 then // 0-3 neighbours
+        if c < 4 then // 0-3 neighbours
         begin
-        if ((Land[Y, X] and lfBasic) <> 0) and (not disableLandBack) then
-            LandPixels[yy, xx]:= LandBackPixel(X, Y)
-        else
-            LandPixels[yy, xx]:= 0;
+            if ((Land[Y, X] and lfBasic) <> 0) and (not disableLandBack) then
+                LandPixels[yy, xx]:= LandBackPixel(X, Y)
+            else
+                LandPixels[yy, xx]:= 0;
 
-        if not pixelsweep then
+            if not pixelsweep then
             begin
-            Land[Y, X]:= 0;
-            exit(true)
+                Land[Y, X]:= 0;
+                exit
             end
         end;
     end;
-Despeckle:= false
+    Despeckle:= false
 end;
 
 procedure Smooth(X, Y: LongInt);
@@ -824,12 +828,12 @@
         if (cReducedQuality and rqBlurryLand) = 0 then
             begin
             if ((LandPixels[y,x] and AMask) shr AShift) < 10 then
-                LandPixels[y,x]:= (cExplosionBorderColor and (not AMask)) or (128 shl AShift)
+                LandPixels[y,x]:= (ExplosionBorderColor 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)
+                                (((((LandPixels[y,x] and RMask shr RShift) div 2)+((ExplosionBorderColor and RMask) shr RShift) div 2) and $FF) shl RShift) or
+                                (((((LandPixels[y,x] and GMask shr GShift) div 2)+((ExplosionBorderColor and GMask) shr GShift) div 2) and $FF) shl GShift) or
+                                (((((LandPixels[y,x] and BMask shr BShift) div 2)+((ExplosionBorderColor and BMask) shr BShift) div 2) and $FF) shl BShift) or ($FF shl AShift)
             end;
         if (Land[y, x-1] = lfObject) then
             Land[y,x]:= lfObject
@@ -850,12 +854,12 @@
         if (cReducedQuality and rqBlurryLand) = 0 then
             begin
             if ((LandPixels[y,x] and AMask) shr AShift) < 10 then
-                LandPixels[y,x]:= (cExplosionBorderColor and (not AMask)) or (64 shl AShift)
+                LandPixels[y,x]:= (ExplosionBorderColor 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)
+                                (((((LandPixels[y,x] and RMask shr RShift) * 3 div 4)+((ExplosionBorderColor and RMask) shr RShift) div 4) and $FF) shl RShift) or
+                                (((((LandPixels[y,x] and GMask shr GShift) * 3 div 4)+((ExplosionBorderColor and GMask) shr GShift) div 4) and $FF) shl GShift) or
+                                (((((LandPixels[y,x] and BMask shr BShift) * 3 div 4)+((ExplosionBorderColor and BMask) shr BShift) div 4) and $FF) shl BShift) or ($FF shl AShift)
             end;
         if (Land[y, x-1] = lfObject) then
             Land[y, x]:= lfObject
@@ -876,9 +880,9 @@
     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
         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)
+                        (((((LandPixels[y,x] and RMask shr RShift) div 2)+((ExplosionBorderColor and RMask) shr RShift) div 2) and $FF) shl RShift) or
+                        (((((LandPixels[y,x] and GMask shr GShift) div 2)+((ExplosionBorderColor and GMask) shr GShift) div 2) and $FF) shl GShift) or
+                        (((((LandPixels[y,x] and BMask shr BShift) div 2)+((ExplosionBorderColor and BMask) shr BShift) div 2) and $FF) shl BShift) or ($FF shl AShift)
         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))
@@ -890,9 +894,9 @@
     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
         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)
+                        (((((LandPixels[y,x] and RMask shr RShift) * 3 div 4)+((ExplosionBorderColor and RMask) shr RShift) div 4) and $FF) shl RShift) or
+                        (((((LandPixels[y,x] and GMask shr GShift) * 3 div 4)+((ExplosionBorderColor and GMask) shr GShift) div 4) and $FF) shl GShift) or
+                        (((((LandPixels[y,x] and BMask shr BShift) * 3 div 4)+((ExplosionBorderColor and BMask) shr BShift) div 4) and $FF) shl BShift) or ($FF shl AShift)
         end
     end
 end;
--- a/hedgewars/uLandObjects.pas	Sun Apr 01 15:23:34 2012 +0200
+++ b/hedgewars/uLandObjects.pas	Wed May 02 23:53:45 2012 +0200
@@ -25,7 +25,8 @@
 procedure AddObjects();
 procedure FreeLandObjects();
 procedure LoadThemeConfig;
-procedure BlitImageAndGenerateCollisionInfo(cpX, cpY, Width: Longword; Image: PSDL_Surface; extraFlags: Word = 0);
+procedure BlitImageAndGenerateCollisionInfo(cpX, cpY, Width: Longword; Image: PSDL_Surface); inline;
+procedure BlitImageAndGenerateCollisionInfo(cpX, cpY, Width: Longword; Image: PSDL_Surface; extraFlags: Word);
 procedure AddOnLandObjects(Surface: PSDL_Surface);
 
 implementation
@@ -65,8 +66,12 @@
     ThemeObjects: TThemeObjects;
     SprayObjects: TSprayObjects;
 
-
-procedure BlitImageAndGenerateCollisionInfo(cpX, cpY, Width: Longword; Image: PSDL_Surface; extraFlags: Word = 0);
+procedure BlitImageAndGenerateCollisionInfo(cpX, cpY, Width: Longword; Image: PSDL_Surface); inline;
+begin
+    BlitImageAndGenerateCollisionInfo(cpX, cpY, Width, Image, 0);
+end;
+    
+procedure BlitImageAndGenerateCollisionInfo(cpX, cpY, Width: Longword; Image: PSDL_Surface; extraFlags: Word);
 var p: PLongwordArray;
     x, y: Longword;
     bpp: LongInt;
@@ -296,11 +301,12 @@
     cnt, i: Longword;
     bRes: boolean;
 begin
+TryPut:= false;
 cnt:= 0;
 with Obj do
     begin
     if Maxcnt = 0 then
-        exit(false);
+        exit;
     x:= 0;
     repeat
         y:= topY+32; // leave room for a hedgie to teleport in
@@ -341,11 +347,12 @@
     r: TSDL_Rect;
     bRes: boolean;
 begin
+TryPut:= false;
 cnt:= 0;
 with Obj do
     begin
     if Maxcnt = 0 then
-        exit(false);
+        exit;
     x:= 0;
     r.x:= 0;
     r.y:= 0;
@@ -406,7 +413,7 @@
 
 AddProgress;
 // Set default water greyscale values
-if cGrayScale then
+if GrayScale then
     begin
     for i:= 0 to 3 do
         begin
@@ -461,7 +468,7 @@
         SkyColor.g:= StrToInt(Trim(Copy(s, 1, Pred(i))));
         Delete(s, 1, i);
         SkyColor.b:= StrToInt(Trim(s));
-        if cGrayScale
+        if GrayScale
             then
             begin
             t:= round(SkyColor.r * RGB_LUMINANCE_RED + SkyColor.g * RGB_LUMINANCE_GREEN + SkyColor.b * RGB_LUMINANCE_BLUE);
@@ -485,7 +492,7 @@
         c2.g:= StrToInt(Trim(Copy(s, 1, Pred(i))));
         Delete(s, 1, i);
         c2.b:= StrToInt(Trim(s));
-        if cGrayScale then
+        if GrayScale then
             begin
             t:= round(SkyColor.r * RGB_LUMINANCE_RED + SkyColor.g * RGB_LUMINANCE_GREEN + SkyColor.b * RGB_LUMINANCE_BLUE);
             if t > 255 then
@@ -494,7 +501,7 @@
             c2.g:= t;
             c2.b:= t
             end;
-        cExplosionBorderColor:= c2.value or AMask;
+        ExplosionBorderColor:= c2.value or AMask;
         end
     else if key = 'water-top' then
         begin
@@ -506,7 +513,7 @@
         Delete(s, 1, i);
         WaterColorArray[0].b:= StrToInt(Trim(s));
         WaterColorArray[0].a := 255;
-        if cGrayScale then
+        if GrayScale then
             begin
             t:= round(WaterColorArray[0].r * RGB_LUMINANCE_RED + WaterColorArray[0].g * RGB_LUMINANCE_GREEN + WaterColorArray[0].b * RGB_LUMINANCE_BLUE);
             if t > 255 then
@@ -527,7 +534,7 @@
         Delete(s, 1, i);
         WaterColorArray[2].b:= StrToInt(Trim(s));
         WaterColorArray[2].a := 255;
-        if cGrayScale then
+        if GrayScale then
             begin
             t:= round(WaterColorArray[2].r * RGB_LUMINANCE_RED + WaterColorArray[2].g * RGB_LUMINANCE_GREEN + WaterColorArray[2].b * RGB_LUMINANCE_BLUE);
             if t > 255 then
@@ -540,8 +547,8 @@
         end
     else if key = 'water-opacity' then
         begin
-        cWaterOpacity:= StrToInt(Trim(s));
-        cSDWaterOpacity:= cWaterOpacity
+        WaterOpacity:= StrToInt(Trim(s));
+        SDWaterOpacity:= WaterOpacity
         end
     else if key = 'music' then
         MusicFN:= Trim(s)
@@ -658,7 +665,7 @@
         Delete(s, 1, i);
         SDWaterColorArray[0].b:= StrToInt(Trim(s));
         SDWaterColorArray[0].a := 255;
-        if cGrayScale then
+        if GrayScale then
             begin
             t:= round(SDWaterColorArray[0].r * RGB_LUMINANCE_RED + SDWaterColorArray[0].g * RGB_LUMINANCE_GREEN + SDWaterColorArray[0].b * RGB_LUMINANCE_BLUE);
             if t > 255 then
@@ -679,7 +686,7 @@
         Delete(s, 1, i);
         SDWaterColorArray[2].b:= StrToInt(Trim(s));
         SDWaterColorArray[2].a := 255;
-        if cGrayScale then
+        if GrayScale then
             begin
             t:= round(SDWaterColorArray[2].r * RGB_LUMINANCE_RED + SDWaterColorArray[2].g * RGB_LUMINANCE_GREEN + SDWaterColorArray[2].b * RGB_LUMINANCE_BLUE);
             if t > 255 then
@@ -691,7 +698,7 @@
         SDWaterColorArray[3]:= SDWaterColorArray[2];
         end
     else if key = 'sd-water-opacity' then
-        cSDWaterOpacity:= StrToInt(Trim(s))
+        SDWaterOpacity:= StrToInt(Trim(s))
     else if key = 'sd-clouds' then
         cSDCloudsNumber:= Word(StrToInt(Trim(s))) * cScreenSpace div LAND_WIDTH
     else if key = 'sd-flakes' then
@@ -724,7 +731,7 @@
             RQSkyColor.g:= StrToInt(Trim(Copy(s, 1, Pred(i))));
             Delete(s, 1, i);
             RQSkyColor.b:= StrToInt(Trim(s));
-            if cGrayScale then
+            if GrayScale then
                 begin
                 t:= round(RQSkyColor.r * RGB_LUMINANCE_RED + RQSkyColor.g * RGB_LUMINANCE_GREEN + RQSkyColor.b * RGB_LUMINANCE_BLUE);
                 if t > 255 then
--- a/hedgewars/uLandOutline.pas	Sun Apr 01 15:23:34 2012 +0200
+++ b/hedgewars/uLandOutline.pas	Wed May 02 23:53:45 2012 +0200
@@ -220,47 +220,49 @@
 function CheckIntersect(V1, V2, V3, V4: TPoint): boolean;
 var c1, c2, dm: LongInt;
 begin
+    CheckIntersect:= false;
     dm:= (V4.y - V3.y) * (V2.x - V1.x) - (V4.x - V3.x) * (V2.y - V1.y);
     c1:= (V4.x - V3.x) * (V1.y - V3.y) - (V4.y - V3.y) * (V1.x - V3.x);
     if dm = 0 then
-            exit(false);
+        exit;
 
+    CheckIntersect:= true;
     c2:= (V2.x - V3.x) * (V1.y - V3.y) - (V2.y - V3.y) * (V1.x - V3.x);
     if dm > 0 then
-        begin
+    begin
         if (c1 < 0) or (c1 > dm) then
-            exit(false);
-        if (c2 < 0) or (c2 > dm) then
-            exit(false)
-        end 
+            CheckIntersect:= false
+        else if (c2 < 0) or (c2 > dm) then
+            CheckIntersect:= false;
+    end 
     else
-        begin
+    begin
         if (c1 > 0) or (c1 < dm) then
-            exit(false);
-        if (c2 > 0) or (c2 < dm) then
-            exit(false)
-        end;
+            CheckIntersect:= false
+        else if (c2 > 0) or (c2 < dm) then
+            CheckIntersect:= false;
+    end;
 
     //AddFileLog('1  (' + inttostr(V1.x) + ',' + inttostr(V1.y) + ')x(' + inttostr(V2.x) + ',' + inttostr(V2.y) + ')');
     //AddFileLog('2  (' + inttostr(V3.x) + ',' + inttostr(V3.y) + ')x(' + inttostr(V4.x) + ',' + inttostr(V4.y) + ')');
-    CheckIntersect:= true
 end;
 
 
 function CheckSelfIntersect(var pa: TPixAr; ind: Longword): boolean;
 var i: Longword;
 begin
+    CheckSelfIntersect:= false;
     if (ind <= 0) or (ind >= Pred(pa.Count)) then
-                exit(false);
+        exit;
+
+    CheckSelfIntersect:= true;
     for i:= 1 to pa.Count - 3 do
         if (i <= ind - 1) or (i >= ind + 2) then
         begin
-        if (i <> ind - 1) and
-            CheckIntersect(pa.ar[ind], pa.ar[ind - 1], pa.ar[i], pa.ar[i - 1]) then
-                exit(true);
-        if (i <> ind + 2) and
-            CheckIntersect(pa.ar[ind], pa.ar[ind + 1], pa.ar[i], pa.ar[i - 1]) then
-                exit(true);
+            if (i <> ind - 1) and CheckIntersect(pa.ar[ind], pa.ar[ind - 1], pa.ar[i], pa.ar[i - 1]) then
+                exit;
+            if (i <> ind + 2) and CheckIntersect(pa.ar[ind], pa.ar[ind + 1], pa.ar[i], pa.ar[i - 1]) then
+                exit;
         end;
     CheckSelfIntersect:= false
 end;
--- a/hedgewars/uLandPainted.pas	Sun Apr 01 15:23:34 2012 +0200
+++ b/hedgewars/uLandPainted.pas	Wed May 02 23:53:45 2012 +0200
@@ -43,7 +43,7 @@
 
 var pointsListHead, pointsListLast: PPointEntry;
 
-procedure DrawLineOnLand(X1, Y1, X2, Y2, radius: LongInt);
+procedure DrawLineOnLand(X1, Y1, X2, Y2, radius: LongInt; color: Longword);
 var  eX, eY, dX, dY: LongInt;
     i, sX, sY, x, y, d: LongInt;
     b: boolean;
@@ -110,7 +110,7 @@
                 begin
                 inc(len);
                 if (len mod 4) = 0 then
-                    FillRoundInLand(X, Y, radius, lfBasic)
+                    FillRoundInLand(X, Y, radius, color)
                 end
         end
 end;
@@ -148,6 +148,7 @@
 var pe: PPointEntry;
     prevPoint: PointRec;
     radius: LongInt;
+    color: Longword;
 begin
     // shutup compiler
     prevPoint.X:= 0;
@@ -161,14 +162,18 @@
         begin
         if (pe^.point.flags and $80 <> 0) then
             begin
-            radius:= (pe^.point.flags and $7F) * 5 + 3;
-            AddFileLog('[DRAW] Move to: ('+inttostr(pe^.point.X)+','+inttostr(pe^.point.Y)+')');
-            FillRoundInLand(pe^.point.X, pe^.point.Y, radius, lfBasic)
+            if (pe^.point.flags and $40 <> 0) then
+                color:= 0
+                else
+                color:= lfBasic;
+            radius:= (pe^.point.flags and $3F) * 5 + 3;
+            AddFileLog('[DRAW] Move to: ('+inttostr(pe^.point.X)+','+inttostr(pe^.point.Y)+'), radius = '+inttostr(radius));
+            FillRoundInLand(pe^.point.X, pe^.point.Y, radius, color)
             end
             else
             begin
-            AddFileLog('[DRAW] Line to: ('+inttostr(pe^.point.X)+','+inttostr(pe^.point.Y)+')');
-            DrawLineOnLand(prevPoint.X, prevPoint.Y, pe^.point.X, pe^.point.Y, radius);
+            AddFileLog('[DRAW] Line to: ('+inttostr(pe^.point.X)+','+inttostr(pe^.point.Y)+'), radius = '+inttostr(radius));
+            DrawLineOnLand(prevPoint.X, prevPoint.Y, pe^.point.X, pe^.point.Y, radius, color);
             end;
 
         prevPoint:= pe^.point;
@@ -181,7 +186,7 @@
     pointsListHead:= nil;
     pointsListLast:= nil;
 
-    RegisterVariable('draw', vtCommand, @chDraw, false);
+    RegisterVariable('draw', @chDraw, false);
 end;
 
 procedure freeModule;
--- a/hedgewars/uLandTemplates.pas	Sun Apr 01 15:23:34 2012 +0200
+++ b/hedgewars/uLandTemplates.pas	Wed May 02 23:53:45 2012 +0200
@@ -1573,7 +1573,7 @@
       );
 
 ////////////////////////////////////////////////////////////////////////
-const EdgeTemplates: array[0..42] of TEdgeTemplate =
+var EdgeTemplates: array[0..42] of TEdgeTemplate =
       (
        (BasePoints: @Template0Points;
         BasePointsCount: Succ(High(Template0Points));
--- a/hedgewars/uMisc.pas	Sun Apr 01 15:23:34 2012 +0200
+++ b/hedgewars/uMisc.pas	Wed May 02 23:53:45 2012 +0200
@@ -1,20 +1,20 @@
 (*
-* Hedgewars, a free turn based strategy game
-* Copyright (c) 2004-2012 Andrey Korotaev <unC0Rr@gmail.com>
-*
-* This program is free software; you can redistribute it and/or modify
-* it under the terms of the GNU General Public License as published by
-* the Free Software Foundation; version 2 of the License
-*
-* This program is distributed in the hope that it will be useful,
-* but WITHOUT ANY WARRANTY; without even the implied warranty of
-* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
-* GNU General Public License for more details.
-*
-* You should have received a copy of the GNU General Public License
-* along with this program; if not, write to the Free Software
-* Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA
-*)
+ * Hedgewars, a free turn based strategy game
+ * Copyright (c) 2004-2012 Andrey Korotaev <unC0Rr@gmail.com>
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; version 2 of the License
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA
+ *)
 
 {$INCLUDE "options.inc"}
 
@@ -23,20 +23,31 @@
 
 uses SDLh, uConsts, GLunit, uTypes;
 
+procedure initModule;
+procedure freeModule;
+
 procedure movecursor(dx, dy: LongInt);
 function  doSurfaceConversion(tmpsurf: PSDL_Surface): PSDL_Surface;
 function  MakeScreenshot(filename: shortstring): boolean;
 function  GetTeamStatString(p: PTeam): shortstring;
 {$IFDEF SDL13}
-function SDL_RectMake(x, y, width, height: LongInt): TSDL_Rect;
+function  SDL_RectMake(x, y, width, height: LongInt): TSDL_Rect; inline;
 {$ELSE}
-function SDL_RectMake(x, y: SmallInt; width, height: Word): TSDL_Rect;
+function  SDL_RectMake(x, y: SmallInt; width, height: Word): TSDL_Rect; inline;
 {$ENDIF}
-procedure initModule;
-procedure freeModule;
 
 implementation
-uses typinfo, sysutils, uVariables, uUtils;
+uses typinfo, sysutils, uVariables, uUtils
+     {$IFDEF PNG_SCREENSHOTS}, PNGh, png {$ENDIF}
+     {$IFNDEF USE_SDLTHREADS} {$IFDEF UNIX}, cthreads{$ENDIF} {$ENDIF};
+
+type PScreenshot = ^TScreenshot;
+     TScreenshot = record
+         buffer: PByte;
+         filename: shortstring;
+         width, height: LongInt;
+         size: QWord;
+         end;
 
 procedure movecursor(dx, dy: LongInt);
 var x, y: LongInt;
@@ -49,12 +60,65 @@
 SDL_WarpMouse(x, y);
 end;
 
-// captures and saves the screen. returns true on success.
-function MakeScreenshot(filename: shortstring): Boolean;
-var success: boolean;
-    p: Pointer;
-    size: QWord;
+{$IFDEF PNG_SCREENSHOTS}
+// this funtion will be executed in separate thread
+function SaveScreenshot(screenshot: pointer): PtrInt;
+var i: LongInt;
+    png_ptr: ^png_struct;
+    info_ptr: ^png_info;
     f: file;
+    image: PScreenshot;
+begin
+image:= PScreenshot(screenshot);
+
+png_ptr := png_create_write_struct(png_get_libpng_ver(nil), nil, nil, nil);
+if png_ptr = nil then
+begin
+    // AddFileLog('Error: Could not create png write struct.');
+    SaveScreenshot:= 0;
+    exit;
+end;
+
+info_ptr := png_create_info_struct(png_ptr);
+if info_ptr = nil then
+begin
+    png_destroy_write_struct(@png_ptr, nil);
+    // AddFileLog('Error: Could not create png info struct.');
+    SaveScreenshot:= 0;
+    exit;
+end;
+
+{$IOCHECKS OFF}
+Assign(f, image^.filename);
+Rewrite(f, 1);
+if IOResult = 0 then
+    begin
+    png_init_pascal_io(png_ptr,@f);
+    png_set_IHDR(png_ptr, info_ptr, image^.width, image^.height,
+                 8, // bit depth
+                 PNG_COLOR_TYPE_RGBA, PNG_INTERLACE_NONE,
+                 PNG_COMPRESSION_TYPE_DEFAULT, PNG_FILTER_TYPE_DEFAULT);
+    png_write_info(png_ptr, info_ptr);
+    // glReadPixels and libpng number rows in different order
+    for i:= image^.height-1 downto 0 do
+        png_write_row(png_ptr, image^.buffer + i*4*image^.width);
+    png_write_end(png_ptr, info_ptr);
+    Close(f);
+    end;
+{$IOCHECKS ON}
+
+// free everything
+png_destroy_write_struct(@png_ptr, @info_ptr);
+FreeMem(image^.buffer, image^.size);
+Dispose(image);
+SaveScreenshot:= 0;
+end;
+
+{$ELSE} // no PNG_SCREENSHOTS
+
+// this funtion will be executed in separate thread
+function SaveScreenshot(screenshot: pointer): PtrInt;
+var f: file;
     // Windows Bitmap Header
     head: array[0..53] of Byte = (
     $42, $4D,       // identifier ("BM")
@@ -73,93 +137,128 @@
     0, 0, 0, 0,     // number of colors (all)
     0, 0, 0, 0      // number of important colors
     );
+    image: PScreenshot;
+    size: QWord;
+begin
+image:= PScreenshot(screenshot);
+
+size:= image^.Width*image^.Height*4;
+
+head[$02]:= (size + 54) and $ff;
+head[$03]:= ((size + 54) shr 8) and $ff;
+head[$04]:= ((size + 54) shr 16) and $ff;
+head[$05]:= ((size + 54) shr 24) and $ff;
+head[$12]:= image^.Width and $ff;
+head[$13]:= (image^.Width shr 8) and $ff;
+head[$14]:= (image^.Width shr 16) and $ff;
+head[$15]:= (image^.Width shr 24) and $ff;
+head[$16]:= image^.Height and $ff;
+head[$17]:= (image^.Height shr 8) and $ff;
+head[$18]:= (image^.Height shr 16) and $ff;
+head[$19]:= (image^.Height shr 24) and $ff;
+head[$22]:= size and $ff;
+head[$23]:= (size shr 8) and $ff;
+head[$24]:= (size shr 16) and $ff;
+head[$25]:= (size shr 24) and $ff;
+
+{$IOCHECKS OFF}
+Assign(f, image^.filename);
+Rewrite(f, 1);
+if IOResult = 0 then
+    begin
+    BlockWrite(f, head, sizeof(head));
+    BlockWrite(f, image^.buffer^, size);
+    Close(f);
+    end
+else
+    begin
+    //AddFileLog('Error: Could not write to ' + filename);
+    end;
+{$IOCHECKS ON}
+
+// free everything
+FreeMem(image^.buffer, image^.size);
+Dispose(image);
+SaveScreenshot:= 0;
+end;
+
+{$ENDIF} // no PNG_SCREENSHOTS
+
+// captures and saves the screen. returns true on success.
+function MakeScreenshot(filename: shortstring): Boolean;
+var p: Pointer;
+    size: QWord;
+    image: PScreenshot;
+    format: GLenum;
+    ext: string[4];
 begin
 // flash
 ScreenFade:= sfFromWhite;
 ScreenFadeValue:= sfMax;
 ScreenFadeSpeed:= 5;
 
+{$IFDEF PNG_SCREENSHOTS}
+format:= GL_RGBA;
+ext:= '.png';
+{$ELSE}
+format:= GL_BGRA;
+ext:= '.bmp';
+{$ENDIF}
+
 size:= toPowerOf2(cScreenWidth) * toPowerOf2(cScreenHeight) * 4;
-p:= GetMem(size);
+p:= GetMem(size); // will be freed in SaveScreenshot()
 
 // memory could not be allocated
 if p = nil then
 begin
     AddFileLog('Error: Could not allocate memory for screenshot.');
-    exit(false);
+    MakeScreenshot:= false;
+    exit;
 end;
 
-// update header information and file name
-filename:= UserPathPrefix + '/Screenshots/' + filename + '.bmp';
-
-head[$02]:= (size + 54) and $ff;
-head[$03]:= ((size + 54) shr 8) and $ff;
-head[$04]:= ((size + 54) shr 16) and $ff;
-head[$05]:= ((size + 54) shr 24) and $ff;
-head[$12]:= cScreenWidth and $ff;
-head[$13]:= (cScreenWidth shr 8) and $ff;
-head[$14]:= (cScreenWidth shr 16) and $ff;
-head[$15]:= (cScreenWidth shr 24) and $ff;
-head[$16]:= cScreenHeight and $ff;
-head[$17]:= (cScreenHeight shr 8) and $ff;
-head[$18]:= (cScreenHeight shr 16) and $ff;
-head[$19]:= (cScreenHeight shr 24) and $ff;
-head[$22]:= size and $ff;
-head[$23]:= (size shr 8) and $ff;
-head[$24]:= (size shr 16) and $ff;
-head[$25]:= (size shr 24) and $ff;
+// read pixel from the front buffer
+glReadPixels(0, 0, cScreenWidth, cScreenHeight, format, GL_UNSIGNED_BYTE, p);
 
-// read pixel from the front buffer
-glReadPixels(0, 0, cScreenWidth, cScreenHeight, GL_BGRA, GL_UNSIGNED_BYTE, p);
+// allocate and fill structure that will be passed to new thread
+New(image); // will be disposed in SaveScreenshot()
+image^.filename:= UserPathPrefix + '/Screenshots/' + filename + ext;
+image^.width:= cScreenWidth;
+image^.height:= cScreenHeight;
+image^.size:= size;
+image^.buffer:= p;
 
-{$IOCHECKS OFF}
-Assign(f, filename);
-Rewrite(f, 1);
-if IOResult = 0 then
-    begin
-    BlockWrite(f, head, sizeof(head));
-    BlockWrite(f, p^, size);
-    Close(f);
-    success:= true;
-    end
-else
-    begin
-    AddFileLog('Error: Could not write to ' + filename);
-    success:= false;
-    end;
-{$IOCHECKS ON}
-
-FreeMem(p, size);
-MakeScreenshot:= success;
+{$IFDEF USE_SDLTHREADS}
+SDL_CreateThread(@SaveScreenshot{$IFDEF SDL13}, nil{$ENDIF}, image);
+{$ELSE}
+BeginThread(@SaveScreenshot, image);
+{$ENDIF}
+MakeScreenshot:= true; // possibly it is not true but we will not wait for thread to terminate
 end;
 
 // http://www.idevgames.com/forums/thread-5602-post-21860.html#pid21860
 function doSurfaceConversion(tmpsurf: PSDL_Surface): PSDL_Surface;
 var convertedSurf: PSDL_Surface;
 begin
+    doSurfaceConversion:= tmpsurf;
     if ((tmpsurf^.format^.bitsperpixel = 32) and (tmpsurf^.format^.rshift > tmpsurf^.format^.bshift)) or
        (tmpsurf^.format^.bitsperpixel = 24) then
         begin
         convertedSurf:= SDL_ConvertSurface(tmpsurf, conversionFormat, SDL_SWSURFACE);
         SDL_FreeSurface(tmpsurf);
-        exit(convertedSurf);
+        doSurfaceConversion:= convertedSurf;
         end;
-
-    exit(tmpsurf);
 end;
 
 {$IFDEF SDL13}
-function SDL_RectMake(x, y, width, height: LongInt): TSDL_Rect;
+function SDL_RectMake(x, y, width, height: LongInt): TSDL_Rect; inline;
 {$ELSE}
-function SDL_RectMake(x, y: SmallInt; width, height: Word): TSDL_Rect;
+function SDL_RectMake(x, y: SmallInt; width, height: Word): TSDL_Rect; inline;
 {$ENDIF}
-var rect: TSDL_Rect;
 begin
-    rect.x:= x;
-    rect.y:= y;
-    rect.w:= width;
-    rect.h:= height;
-    exit(rect);
+    SDL_RectMake.x:= x;
+    SDL_RectMake.y:= y;
+    SDL_RectMake.w:= width;
+    SDL_RectMake.h:= height;
 end;
 
 function GetTeamStatString(p: PTeam): shortstring;
@@ -170,7 +269,7 @@
 end;
 
 procedure initModule;
-const SDL_PIXELFORMAT_ABGR8888 = ((1 shl 31) or (6 shl 24) or (7 shl 20) or (6 shl 16) or (32 shl 8) or 4);
+const SDL_PIXELFORMAT_ABGR8888 = (1 shl 31) or (6 shl 24) or (7 shl 20) or (6 shl 16) or (32 shl 8) or 4;
 begin
     conversionFormat:= SDL_AllocFormat(SDL_PIXELFORMAT_ABGR8888);
 end;
--- a/hedgewars/uMobile.pas	Sun Apr 01 15:23:34 2012 +0200
+++ b/hedgewars/uMobile.pas	Wed May 02 23:53:45 2012 +0200
@@ -44,18 +44,15 @@
 // this function is just to determine whether we are running on a limited screen device
 function isPhone: Boolean; inline;
 begin
+    isPhone:= false;
 {$IFDEF IPHONEOS}
-    exit(isApplePhone());
+    isPhone:= isApplePhone();
 {$ENDIF}
 {$IFDEF ANDROID}
     //nasty nasty hack. TODO: implement callback to java to have a unified way of determining if it is a tablet
     if (cScreenWidth < 1000) and (cScreenHeight < 500) then
-    begin
-        exit(true);
-    end
-    else exit(false);
+        isPhone:= true;
 {$ENDIF}
-    exit(false);
 end;
 
 // this function should make the device vibrate in some way
--- a/hedgewars/uRandom.pas	Sun Apr 01 15:23:34 2012 +0200
+++ b/hedgewars/uRandom.pas	Wed May 02 23:53:45 2012 +0200
@@ -35,7 +35,7 @@
 procedure freeModule;
 
 procedure SetRandomSeed(Seed: shortstring); // Sets the seed that should be used for generating pseudo-random values.
-function  GetRandom: hwFloat; overload; // Returns a pseudo-random hwFloat.
+function  GetRandomf: hwFloat; overload; // Returns a pseudo-random hwFloat.
 function  GetRandom(m: LongWord): LongWord; overload; // Returns a positive pseudo-random integer smaller than m.
 function  rndSign(num: hwFloat): hwFloat; // Returns num with a random chance of having a inverted sign.
 
@@ -73,11 +73,11 @@
     GetNext
 end;
 
-function GetRandom: hwFloat;
+function GetRandomf: hwFloat;
 begin
 GetNext;
-GetRandom.isNegative:= false;
-GetRandom.QWordValue:= GetNext
+GetRandomf.isNegative:= false;
+GetRandomf.QWordValue:= GetNext
 end;
 
 function GetRandom(m: LongWord): LongWord;
--- a/hedgewars/uRender.pas	Sun Apr 01 15:23:34 2012 +0200
+++ b/hedgewars/uRender.pas	Wed May 02 23:53:45 2012 +0200
@@ -24,27 +24,32 @@
 
 uses SDLh, uTypes, GLunit, uConsts;
 
-procedure DrawSpriteFromRect(Sprite: TSprite; r: TSDL_Rect; X, Y, Height, Position: LongInt);
-procedure DrawFromRect(X, Y, W, H: LongInt; r: PSDL_Rect; SourceTexture: PTexture);
-procedure DrawFromRect(X, Y: LongInt; r: PSDL_Rect; SourceTexture: PTexture);
-procedure DrawSprite (Sprite: TSprite; X, Y, Frame: LongInt);
-procedure DrawSprite2(Sprite: TSprite; X, Y, FrameX, FrameY: LongInt);
-procedure DrawSpriteClipped(Sprite: TSprite; X, Y, TopY, RightX, BottomY, LeftX: LongInt);
-procedure DrawTexture(X, Y: LongInt; Texture: PTexture; Scale: GLfloat = 1.0);
-procedure DrawTextureF(Texture: PTexture; Scale: GLfloat; X, Y, Frame, Dir, w, h: LongInt);
-procedure DrawRotatedTextureF(Texture: PTexture; Scale, OffsetX, OffsetY: GLfloat; X, Y, Frame, Dir, w, h: LongInt; Angle: real);
-procedure DrawRotated(Sprite: TSprite; X, Y, Dir: LongInt; Angle: real);
-procedure DrawRotatedF(Sprite: TSprite; X, Y, Frame, Dir: LongInt; Angle: real);
-procedure DrawRotatedTex(Tex: PTexture; hw, hh, X, Y, Dir: LongInt; Angle: real);
-procedure DrawCentered(X, Top: LongInt; Source: PTexture);
-procedure DrawLine(X0, Y0, X1, Y1, Width: Single; r, g, b, a: Byte);
-procedure DrawFillRect(r: TSDL_Rect);
-procedure DrawCircle(X, Y, Radius, Width: LongInt; r, g, b, a: Byte);
-procedure DrawCircle(X, Y, Radius, Width: LongInt);
-procedure DrawHedgehog(X, Y: LongInt; Dir: LongInt; Pos, Step: LongWord; Angle: real);
-procedure DrawScreenWidget(widget: POnScreenWidget);
-procedure Tint(r, g, b, a: Byte); inline;
-procedure Tint(c: Longword); inline;
+procedure DrawSprite            (Sprite: TSprite; X, Y, Frame: LongInt);
+procedure DrawSprite            (Sprite: TSprite; X, Y, FrameX, FrameY: LongInt);
+procedure DrawSpriteFromRect    (Sprite: TSprite; r: TSDL_Rect; X, Y, Height, Position: LongInt);
+procedure DrawSpriteClipped     (Sprite: TSprite; X, Y, TopY, RightX, BottomY, LeftX: LongInt);
+procedure DrawSpriteRotated     (Sprite: TSprite; X, Y, Dir: LongInt; Angle: real);
+procedure DrawSpriteRotatedF    (Sprite: TSprite; X, Y, Frame, Dir: LongInt; Angle: real);
+
+procedure DrawTexture           (X, Y: LongInt; Texture: PTexture); inline;
+procedure DrawTexture           (X, Y: LongInt; Texture: PTexture; Scale: GLfloat);
+procedure DrawTextureFromRect   (X, Y: LongInt; r: PSDL_Rect; SourceTexture: PTexture);
+procedure DrawTextureFromRect   (X, Y, W, H: LongInt; r: PSDL_Rect; SourceTexture: PTexture);
+procedure DrawTextureCentered   (X, Top: LongInt; Source: PTexture);
+procedure DrawTextureF          (Texture: PTexture; Scale: GLfloat; X, Y, Frame, Dir, w, h: LongInt);
+procedure DrawTextureRotated    (Texture: PTexture; hw, hh, X, Y, Dir: LongInt; Angle: real);
+procedure DrawTextureRotatedF   (Texture: PTexture; Scale, OffsetX, OffsetY: GLfloat; X, Y, Frame, Dir, w, h: LongInt; Angle: real);
+
+procedure DrawCircle            (X, Y, Radius, Width: LongInt);
+procedure DrawCircle            (X, Y, Radius, Width: LongInt; r, g, b, a: Byte);
+
+procedure DrawLine              (X0, Y0, X1, Y1, Width: Single; r, g, b, a: Byte);
+procedure DrawFillRect          (r: TSDL_Rect);
+procedure DrawHedgehog          (X, Y: LongInt; Dir: LongInt; Pos, Step: LongWord; Angle: real);
+procedure DrawScreenWidget      (widget: POnScreenWidget);
+
+procedure Tint                  (r, g, b, a: Byte); inline;
+procedure Tint                  (c: Longword); inline;
 
 
 implementation
@@ -54,15 +59,15 @@
 begin
 r.y:= r.y + Height * Position;
 r.h:= Height;
-DrawFromRect(X, Y, @r, SpritesData[Sprite].Texture)
+DrawTextureFromRect(X, Y, @r, SpritesData[Sprite].Texture)
 end;
 
-procedure DrawFromRect(X, Y: LongInt; r: PSDL_Rect; SourceTexture: PTexture);
+procedure DrawTextureFromRect(X, Y: LongInt; r: PSDL_Rect; SourceTexture: PTexture);
 begin
-DrawFromRect(X, Y, r^.w, r^.h, r, SourceTexture)
+DrawTextureFromRect(X, Y, r^.w, r^.h, r, SourceTexture)
 end;
 
-procedure DrawFromRect(X, Y, W, H: LongInt; r: PSDL_Rect; SourceTexture: PTexture);
+procedure DrawTextureFromRect(X, Y, W, H: LongInt; r: PSDL_Rect; SourceTexture: PTexture);
 var rr: TSDL_Rect;
     _l, _r, _t, _b: real;
     VertexBuffer, TextureBuffer: array [0..3] of TVertex2f;
@@ -106,12 +111,15 @@
 TextureBuffer[3].X:= _l;
 TextureBuffer[3].Y:= _b;
 
-
 glVertexPointer(2, GL_FLOAT, 0, @VertexBuffer[0]);
 glTexCoordPointer(2, GL_FLOAT, 0, @TextureBuffer[0]);
 glDrawArrays(GL_TRIANGLE_FAN, 0, Length(VertexBuffer));
 end;
 
+procedure DrawTexture(X, Y: LongInt; Texture: PTexture); inline;
+begin
+    DrawTexture(X, Y, Texture, 1.0);
+end;
 
 procedure DrawTexture(X, Y: LongInt; Texture: PTexture; Scale: GLfloat);
 begin
@@ -131,10 +139,10 @@
 
 procedure DrawTextureF(Texture: PTexture; Scale: GLfloat; X, Y, Frame, Dir, w, h: LongInt);
 begin
-    DrawRotatedTextureF(Texture, Scale, 0, 0, X, Y, Frame, Dir, w, h, 0)
+    DrawTextureRotatedF(Texture, Scale, 0, 0, X, Y, Frame, Dir, w, h, 0)
 end;
 
-procedure DrawRotatedTextureF(Texture: PTexture; Scale, OffsetX, OffsetY: GLfloat; X, Y, Frame, Dir, w, h: LongInt; Angle: real);
+procedure DrawTextureRotatedF(Texture: PTexture; Scale, OffsetX, OffsetY: GLfloat; X, Y, Frame, Dir, w, h: LongInt; Angle: real);
 var ft, fb, fl, fr: GLfloat;
     hw, nx, ny: LongInt;
     VertexBuffer, TextureBuffer: array [0..3] of TVertex2f;
@@ -194,15 +202,15 @@
 glPopMatrix
 end;
 
-procedure DrawRotated(Sprite: TSprite; X, Y, Dir: LongInt; Angle: real);
+procedure DrawSpriteRotated(Sprite: TSprite; X, Y, Dir: LongInt; Angle: real);
 begin
-    DrawRotatedTex(SpritesData[Sprite].Texture,
+    DrawTextureRotated(SpritesData[Sprite].Texture,
         SpritesData[Sprite].Width,
         SpritesData[Sprite].Height,
         X, Y, Dir, Angle)
 end;
 
-procedure DrawRotatedF(Sprite: TSprite; X, Y, Frame, Dir: LongInt; Angle: real);
+procedure DrawSpriteRotatedF(Sprite: TSprite; X, Y, Frame, Dir: LongInt; Angle: real);
 begin
 glPushMatrix;
 glTranslatef(X, Y, 0);
@@ -219,7 +227,7 @@
 glPopMatrix
 end;
 
-procedure DrawRotatedTex(Tex: PTexture; hw, hh, X, Y, Dir: LongInt; Angle: real);
+procedure DrawTextureRotated(Texture: PTexture; hw, hh, X, Y, Dir: LongInt; Angle: real);
 var VertexBuffer: array [0..3] of TVertex2f;
 begin
 // do not draw anything outside the visible screen space (first check fixes some sprite drawing, e.g. hedgehogs)
@@ -240,7 +248,7 @@
     glRotatef(Angle, 0, 0,  1);
 
 
-glBindTexture(GL_TEXTURE_2D, Tex^.id);
+glBindTexture(GL_TEXTURE_2D, Texture^.id);
 
 VertexBuffer[0].X:= -hw;
 VertexBuffer[0].Y:= -hh;
@@ -252,21 +260,31 @@
 VertexBuffer[3].Y:= hh;
 
 glVertexPointer(2, GL_FLOAT, 0, @VertexBuffer[0]);
-glTexCoordPointer(2, GL_FLOAT, 0, @Tex^.tb);
+glTexCoordPointer(2, GL_FLOAT, 0, @Texture^.tb);
 glDrawArrays(GL_TRIANGLE_FAN, 0, Length(VertexBuffer));
 
 glPopMatrix
 end;
 
-procedure DrawSprite (Sprite: TSprite; X, Y, Frame: LongInt);
+procedure DrawSprite(Sprite: TSprite; X, Y, Frame: LongInt);
 var row, col, numFramesFirstCol: LongInt;
 begin
-if SpritesData[Sprite].imageHeight = 0 then
-    exit;
-numFramesFirstCol:= SpritesData[Sprite].imageHeight div SpritesData[Sprite].Height;
-row:= Frame mod numFramesFirstCol;
-col:= Frame div numFramesFirstCol;
-DrawSprite2 (Sprite, X, Y, col, row);
+    if SpritesData[Sprite].imageHeight = 0 then
+        exit;
+    numFramesFirstCol:= SpritesData[Sprite].imageHeight div SpritesData[Sprite].Height;
+    row:= Frame mod numFramesFirstCol;
+    col:= Frame div numFramesFirstCol;
+    DrawSprite(Sprite, X, Y, col, row);
+end;
+
+procedure DrawSprite(Sprite: TSprite; X, Y, FrameX, FrameY: LongInt);
+var r: TSDL_Rect;
+begin
+    r.x:= FrameX * SpritesData[Sprite].Width;
+    r.w:= SpritesData[Sprite].Width;
+    r.y:= FrameY * SpritesData[Sprite].Height;
+    r.h:= SpritesData[Sprite].Height;
+    DrawTextureFromRect(X, Y, @r, SpritesData[Sprite].Texture)
 end;
 
 procedure DrawSpriteClipped(Sprite: TSprite; X, Y, TopY, RightX, BottomY, LeftX: LongInt);
@@ -290,20 +308,10 @@
 dec(r.h, r.y);
 dec(r.w, r.x);
 
-DrawFromRect(X + r.x, Y + r.y, @r, SpritesData[Sprite].Texture)
+DrawTextureFromRect(X + r.x, Y + r.y, @r, SpritesData[Sprite].Texture)
 end;
 
-procedure DrawSprite2(Sprite: TSprite; X, Y, FrameX, FrameY: LongInt);
-var r: TSDL_Rect;
-begin
-    r.x:= FrameX * SpritesData[Sprite].Width;
-    r.w:= SpritesData[Sprite].Width;
-    r.y:= FrameY * SpritesData[Sprite].Height;
-    r.h:= SpritesData[Sprite].Height;
-    DrawFromRect(X, Y, @r, SpritesData[Sprite].Texture)
-end;
-
-procedure DrawCentered(X, Top: LongInt; Source: PTexture);
+procedure DrawTextureCentered(X, Top: LongInt; Source: PTexture);
 var scale: GLfloat;
 begin
     if (Source^.w + 20) > cScreenWidth then
@@ -449,9 +457,9 @@
 end;
 
 procedure DrawScreenWidget(widget: POnScreenWidget);
+{$IFDEF USE_TOUCH_INTERFACE}
 var alpha: byte = $FF;
 begin
-{$IFDEF USE_TOUCH_INTERFACE}
 with widget^ do
     begin
     if (fadeAnimStart <> 0) then
@@ -489,37 +497,37 @@
         Tint($FF, $FF, $FF, $FF);
         end;
     end;
+{$ELSE}
+begin
+widget:= widget; // avoid hint
 {$ENDIF}
 end;
 
 procedure Tint(r, g, b, a: Byte); inline;
-const 
-    lastTint: Longword = 0;
-var 
-    nc, tw: Longword;
+var nc, tw: Longword;
 begin
-nc:= (a shl 24) or (b shl 16) or (g shl 8) or r;
+    nc:= (a shl 24) or (b shl 16) or (g shl 8) or r;
 
-if nc = lastTint then
-    exit;
+    if nc = lastTint then
+        exit;
 
-if cGrayScale then
-    begin
-    tw:= round(r * RGB_LUMINANCE_RED + g * RGB_LUMINANCE_GREEN + b * RGB_LUMINANCE_BLUE);
-    if tw > 255 then
-        tw:= 255;
-    r:= tw;
-    g:= tw;
-    b:= tw
-    end;
+    if GrayScale then
+        begin
+        tw:= round(r * RGB_LUMINANCE_RED + g * RGB_LUMINANCE_GREEN + b * RGB_LUMINANCE_BLUE);
+        if tw > 255 then
+            tw:= 255;
+        r:= tw;
+        g:= tw;
+        b:= tw
+        end;
 
-glColor4ub(r, g, b, a);
-lastTint:= nc;
+    glColor4ub(r, g, b, a);
+    lastTint:= nc;
 end;
 
 procedure Tint(c: Longword); inline;
 begin
-Tint(((c shr 24) and $FF), ((c shr 16) and $FF), (c shr 8) and $FF, (c and $FF))
+    Tint(((c shr 24) and $FF), ((c shr 16) and $FF), (c shr 8) and $FF, (c and $FF))
 end;
 
 end.
--- a/hedgewars/uRenderUtils.pas	Sun Apr 01 15:23:34 2012 +0200
+++ b/hedgewars/uRenderUtils.pas	Wed May 02 23:53:45 2012 +0200
@@ -24,14 +24,19 @@
 uses SDLh, uTypes;
 
 procedure flipSurface(Surface: PSDL_Surface; Vertical: Boolean);
+
 procedure copyRotatedSurface(src, dest: PSDL_Surface); // this is necessary since width/height are read only in SDL
-procedure copyToXY(src, dest: PSDL_Surface; destX, destY: LongInt);
+procedure copyToXY(src, dest: PSDL_Surface; destX, destY: LongInt); inline;
 procedure copyToXY(src, dest: PSDL_Surface; srcX, srcY, srcW, srcH, destX, destY: LongInt);
-procedure DrawSprite2Surf(sprite: TSprite; dest: PSDL_Surface; x,y: LongInt; frame: LongInt = 0);
+
+procedure DrawSprite2Surf(sprite: TSprite; dest: PSDL_Surface; x,y: LongInt); inline;
+procedure DrawSprite2Surf(sprite: TSprite; dest: PSDL_Surface; x,y: LongInt; frame: LongInt);
 procedure DrawLine2Surf(dest: PSDL_Surface; x0,y0,x1,y1:LongInt; r,g,b: byte);
-function  RenderStringTex(s: ansistring; Color: Longword; font: THWFont; maxLength: LongWord = 0): PTexture;
+procedure DrawRoundRect(rect: PSDL_Rect; BorderColor, FillColor: Longword; Surface: PSDL_Surface; Clear: boolean);
+
+function  RenderStringTex(s: ansistring; Color: Longword; font: THWFont): PTexture;
+function  RenderStringTex(s: ansistring; Color: Longword; font: THWFont; maxLength: LongWord): PTexture;
 function  RenderSpeechBubbleTex(s: ansistring; SpeechType: Longword; font: THWFont): PTexture;
-procedure DrawRoundRect(rect: PSDL_Rect; BorderColor, FillColor: Longword; Surface: PSDL_Surface; Clear: boolean);
 
 implementation
 uses uUtils, uVariables, uConsts, uTextures, sysutils, uDebug;
@@ -65,8 +70,13 @@
     r.h:= rect^.h - 4;
     SDL_FillRect(Surface, @r, FillColor)
 end;
+(*
+function WriteInRoundRect(Surface: PSDL_Surface; X, Y: LongInt; Color: LongWord; Font: THWFont; s: ansistring): TSDL_Rect;
+begin
+    WriteInRoundRect:= WriteInRoundRect(Surface, X, Y, Color, Font, s, 0);
+end;*)
 
-function WriteInRoundRect(Surface: PSDL_Surface; X, Y: LongInt; Color: LongWord; Font: THWFont; s: ansistring; maxLength: LongWord = 0): TSDL_Rect;
+function WriteInRoundRect(Surface: PSDL_Surface; X, Y: LongInt; Color: LongWord; Font: THWFont; s: ansistring; maxLength: LongWord): TSDL_Rect;
 var w, h: LongInt;
     tmpsurf: PSDL_Surface;
     clr: TSDL_Color;
@@ -76,8 +86,8 @@
     if (maxLength <> 0) and (w > maxLength) then w := maxLength;
     finalRect.x:= X;
     finalRect.y:= Y;
-    finalRect.w:= w + FontBorder * 2 + 4;
-    finalRect.h:= h + FontBorder * 2;
+    finalRect.w:= w + cFontBorder * 2 + 4;
+    finalRect.h:= h + cFontBorder * 2;
     textRect.x:= X;
     textRect.y:= Y;
     textRect.w:= w;
@@ -87,15 +97,15 @@
     clr.g:= (Color shr 8) and $FF;
     clr.b:= Color and $FF;
     tmpsurf:= TTF_RenderUTF8_Blended(Fontz[Font].Handle, Str2PChar(s), clr);
-    finalRect.x:= X + FontBorder + 2;
-    finalRect.y:= Y + FontBorder;
+    finalRect.x:= X + cFontBorder + 2;
+    finalRect.y:= Y + cFontBorder;
     SDLTry(tmpsurf <> nil, true);
     SDL_UpperBlit(tmpsurf, @textRect, Surface, @finalRect);
     SDL_FreeSurface(tmpsurf);
     finalRect.x:= X;
     finalRect.y:= Y;
-    finalRect.w:= w + FontBorder * 2 + 4;
-    finalRect.h:= h + FontBorder * 2;
+    finalRect.w:= w + cFontBorder * 2 + 4;
+    finalRect.h:= h + cFontBorder * 2;
     WriteInRoundRect:= finalRect;
 end;
 
@@ -128,9 +138,9 @@
             end;
 end;
 
-procedure copyToXY(src, dest: PSDL_Surface; destX, destY: LongInt);
+procedure copyToXY(src, dest: PSDL_Surface; destX, destY: LongInt); inline;
 begin
-    copyToXY(src, dest, 0,0,src^.w, src^.h, destX, destY);
+    copyToXY(src, dest, 0, 0, src^.w, src^.h, destX, destY);
 end;
 
 procedure copyToXY(src, dest: PSDL_Surface; srcX, srcY, srcW, srcH, destX, destY: LongInt);
@@ -161,6 +171,11 @@
         end;
 end;
 
+procedure DrawSprite2Surf(sprite: TSprite; dest: PSDL_Surface; x,y: LongInt); inline;
+begin
+    DrawSprite2Surf(sprite, dest, x, y, 0);
+end;
+
 procedure DrawSprite2Surf(sprite: TSprite; dest: PSDL_Surface; x,y,frame: LongInt);
 var numFramesFirstCol, row, col: LongInt;
 begin
@@ -178,12 +193,11 @@
 
 procedure DrawLine2Surf(dest: PSDL_Surface; x0, y0,x1,y1: LongInt; r,g,b: byte);
 var
-    max: LongInt;
     dx,dy,err,e2,sx,sy: LongInt;
     yMax: LongInt;
     destPixels: PLongwordArray;
 begin
-    max:= (dest^.pitch div 4) * dest^.h;
+    //max:= (dest^.pitch div 4) * dest^.h;
     yMax:= dest^.pitch div 4;
     destPixels:= dest^.pixels;
 
@@ -234,7 +248,12 @@
             end;
 end;
 
-function  RenderStringTex(s: ansistring; Color: Longword; font: THWFont; maxLength: LongWord = 0): PTexture;
+function RenderStringTex(s: ansistring; Color: Longword; font: THWFont): PTexture;
+begin
+    RenderStringTex:= RenderStringTex(s, Color, font, 0);
+end;
+
+function RenderStringTex(s: ansistring; Color: Longword; font: THWFont; maxLength: LongWord): PTexture;
 var w, h: LongInt;
     finalSurface: PSDL_Surface;
 begin
@@ -244,7 +263,7 @@
     TTF_SizeUTF8(Fontz[font].Handle, Str2PChar(s), @w, @h);
     if (maxLength <> 0) and (w > maxLength) then w := maxLength;
 
-    finalSurface:= SDL_CreateRGBSurface(SDL_SWSURFACE, w + FontBorder * 2 + 4, h + FontBorder * 2,
+    finalSurface:= SDL_CreateRGBSurface(SDL_SWSURFACE, w + cFontBorder * 2 + 4, h + cFontBorder * 2,
             32, RMask, GMask, BMask, AMask);
 
     TryDo(finalSurface <> nil, 'RenderString: fail to create surface', true);
--- a/hedgewars/uScript.pas	Sun Apr 01 15:23:34 2012 +0200
+++ b/hedgewars/uScript.pas	Wed May 02 23:53:45 2012 +0200
@@ -1023,7 +1023,7 @@
             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))
+                SetAmmo(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
@@ -1713,7 +1713,7 @@
     exit;
 
 // push game variables so they may be modified by the script
-ScriptSetInteger('BorderColor', cExplosionBorderColor);
+ScriptSetInteger('BorderColor', ExplosionBorderColor);
 ScriptSetInteger('GameFlags', GameFlags);
 ScriptSetString('Seed', cSeed);
 ScriptSetInteger('TemplateFilter', cTemplateFilter);
--- a/hedgewars/uSound.pas	Sun Apr 01 15:23:34 2012 +0200
+++ b/hedgewars/uSound.pas	Wed May 02 23:53:45 2012 +0200
@@ -36,6 +36,7 @@
 uses SDLh, uConsts, uTypes, sysutils;
 
 var MusicFN: shortstring; // music file name
+    previousVolume: LongInt; // cached volume value
 
 procedure initModule;
 procedure freeModule;
@@ -90,6 +91,9 @@
 // Returns a pointer to the voicepack with the given name.
 function  AskForVoicepack(name: shortstring): Pointer;
 
+// Drastically lower the volume when we lose focus (and restore the previous value)
+procedure DampenAudio;
+procedure UndampenAudio;
 
 implementation
 uses uVariables, uConsole, uUtils, uCommands, uDebug;
@@ -464,8 +468,9 @@
 
 function ChangeVolume(voldelta: LongInt): LongInt;
 begin
+    ChangeVolume:= 0;
     if not isSoundEnabled then
-        exit(0);
+        exit;
 
     inc(Volume, voldelta);
     if Volume < 0 then
@@ -477,6 +482,17 @@
     ChangeVolume:= Volume * 100 div MIX_MAX_VOLUME
 end;
 
+procedure DampenAudio;
+begin
+    previousVolume:= Volume;
+    ChangeVolume(-Volume * 7 div 9);
+end;
+
+procedure UndampenAudio;
+begin
+ChangeVolume(previousVolume - Volume);
+end;
+
 procedure PauseMusic;
 begin
     if (MusicFN = '') or (not isMusicEnabled) then
@@ -528,7 +544,7 @@
 
 procedure initModule;
 begin
-    RegisterVariable('voicepack', vtCommand, @chVoicepack, false);
+    RegisterVariable('voicepack', @chVoicepack, false);
     MusicFN:='';
 end;
 
--- a/hedgewars/uStore.pas	Sun Apr 01 15:23:34 2012 +0200
+++ b/hedgewars/uStore.pas	Wed May 02 23:53:45 2012 +0200
@@ -26,8 +26,8 @@
 procedure initModule;
 procedure freeModule;
 
-procedure StoreLoad(reload: boolean = false);
-procedure StoreRelease(reload: boolean = false);
+procedure StoreLoad(reload: boolean);
+procedure StoreRelease(reload: boolean);
 procedure RenderHealth(var Hedgehog: THedgehog);
 procedure AddProgress;
 procedure FinishProgress;
@@ -57,10 +57,10 @@
 begin
 w:= 0; h:= 0; // avoid compiler hints
 TTF_SizeUTF8(Fontz[Font].Handle, Str2PChar(s), @w, @h);
-finalRect.x:= X + FontBorder + 2;
-finalRect.y:= Y + FontBorder;
-finalRect.w:= w + FontBorder * 2 + 4;
-finalRect.h:= h + FontBorder * 2;
+finalRect.x:= X + cFontBorder + 2;
+finalRect.y:= Y + cFontBorder;
+finalRect.w:= w + cFontBorder * 2 + 4;
+finalRect.h:= h + cFontBorder * 2;
 clr.r:= Color shr 16;
 clr.g:= (Color shr 8) and $FF;
 clr.b:= Color and $FF;
@@ -71,8 +71,8 @@
 SDL_FreeSurface(tmpsurf);
 finalRect.x:= X;
 finalRect.y:= Y;
-finalRect.w:= w + FontBorder * 2 + 4;
-finalRect.h:= h + FontBorder * 2;
+finalRect.w:= w + cFontBorder * 2 + 4;
+finalRect.h:= h + cFontBorder * 2;
 WriteInRect:= finalRect
 end;
 
@@ -524,28 +524,30 @@
 Hedgehog.HealthTagTex:= RenderStringTex(s, Hedgehog.Team^.Clan^.Color, fnt16)
 end;
 
-function  LoadImage(const filename: shortstring; imageFlags: LongInt): PSDL_Surface;
+function LoadImage(const filename: shortstring; imageFlags: LongInt): PSDL_Surface;
 var tmpsurf: PSDL_Surface;
     s: shortstring;
 begin
-WriteToConsole(msgLoading + filename + '.png [flags: ' + inttostr(imageFlags) + '] ');
+    LoadImage:= nil;
+    WriteToConsole(msgLoading + filename + '.png [flags: ' + inttostr(imageFlags) + '] ');
 
-s:= filename + '.png';
-tmpsurf:= IMG_Load(Str2PChar(s));
+    s:= filename + '.png';
+    tmpsurf:= IMG_Load(Str2PChar(s));
 
     if tmpsurf = nil then
-        begin
+    begin
         OutError(msgFailed, (imageFlags and ifCritical) <> 0);
-        exit(nil)
-        end;
+        exit;
+    end;
 
     if ((imageFlags and ifIgnoreCaps) = 0) and ((tmpsurf^.w > MaxTextureSize) or (tmpsurf^.h > MaxTextureSize)) then
-        begin
+    begin
         SDL_FreeSurface(tmpsurf);
         OutError(msgFailedSize, (imageFlags and ifCritical) <> 0);
         // dummy surface to replace non-critical textures that failed to load due to their size
-        exit(SDL_CreateRGBSurface(SDL_SWSURFACE, 2, 2, 32, RMask, GMask, BMask, AMask));
-        end;
+        LoadImage:= SDL_CreateRGBSurface(SDL_SWSURFACE, 2, 2, 32, RMask, GMask, BMask, AMask);
+        exit;
+    end;
 
     tmpsurf:= doSurfaceConversion(tmpsurf);
 
@@ -623,7 +625,9 @@
 
 {$IFDEF SDL13}
     // this function creates an opengles1.1 context by default on mobile devices
-    // use SDL_GL_SetAttribute to change this behaviour
+    // unless you un-comment this two attributes
+    //SDL_GL_SetAttribute(SDL_GL_CONTEXT_MAJOR_VERSION, 2);
+    //SDL_GL_SetAttribute(SDL_GL_CONTEXT_MINOR_VERSION, 0);
     if SDLGLcontext = nil then
         SDLGLcontext:= SDL_GL_CreateContext(SDLwindow);
     SDLTry(SDLGLcontext <> nil, true);
@@ -665,7 +669,9 @@
     AddFileLog('OpenGL-- Renderer: ' + shortstring(pchar(glGetString(GL_RENDERER))));
     AddFileLog('  |----- Vendor: ' + shortstring(pchar(glGetString(GL_VENDOR))));
     AddFileLog('  |----- Version: ' + shortstring(pchar(glGetString(GL_VERSION))));
-    AddFileLog('  \----- Texture Size: ' + inttostr(MaxTextureSize));
+    AddFileLog('  |----- Texture Size: ' + inttostr(MaxTextureSize));
+    AddFileLog('  \----- Extensions: ' + shortstring(pchar(glGetString(GL_EXTENSIONS))));
+    //TODO: don't have the Extensions line trimmed but slipt it into multiple lines
 
 {$IFNDEF S3D_DISABLED}
     if (cStereoMode = smHorizontal) or (cStereoMode = smVertical) or (cStereoMode = smAFR) then
@@ -783,7 +789,7 @@
     r.w:= squaresize;
     r.h:= squaresize;
 
-    DrawFromRect( -squaresize div 2, (cScreenHeight - squaresize) shr 1, @r, ProgrTex);
+    DrawTextureFromRect( -squaresize div 2, (cScreenHeight - squaresize) shr 1, @r, ProgrTex);
 
 {$IFDEF SDL13}
     SDL_GL_SwapWindow(SDLwindow);
@@ -823,8 +829,8 @@
 
 w:= 0;
 h:= 0;
-wa:= FontBorder * 2 + 4;
-ha:= FontBorder * 2;
+wa:= cFontBorder * 2 + 4;
+ha:= cFontBorder * 2;
 
 i:= 0; j:= 0; // avoid compiler hints
 
@@ -882,9 +888,9 @@
 DrawRoundRect(@r, cWhiteColor, cNearBlackColor, tmpsurf, true);
 
 // render caption
-r:= WriteInRect(tmpsurf, 36 + FontBorder + 2, ha, $ffffffff, font, caption);
+r:= WriteInRect(tmpsurf, 36 + cFontBorder + 2, ha, $ffffffff, font, caption);
 // render sub caption
-r:= WriteInRect(tmpsurf, 36 + FontBorder + 2, r.y + r.h, $ffc7c7c7, font, subcaption);
+r:= WriteInRect(tmpsurf, 36 + cFontBorder + 2, r.y + r.h, $ffc7c7c7, font, subcaption);
 
 // render all description lines
 tmpdesc:= description;
@@ -895,21 +901,21 @@
     r2:= r;
     if tmpline <> '' then
         begin
-        r:= WriteInRect(tmpsurf, FontBorder + 2, r.y + r.h, $ff707070, font, tmpline);
+        r:= WriteInRect(tmpsurf, cFontBorder + 2, r.y + r.h, $ff707070, font, tmpline);
 
         // render highlighted caption (if there is a ':')
         tmpline2:= '';
         SplitByChar(tmpline, tmpline2, ':');
         if tmpline2 <> '' then
-            WriteInRect(tmpsurf, FontBorder + 2, r2.y + r2.h, $ffc7c7c7, font, tmpline + ':');
+            WriteInRect(tmpsurf, cFontBorder + 2, r2.y + r2.h, $ffc7c7c7, font, tmpline + ':');
         end
     end;
 
 if extra <> '' then
-    r:= WriteInRect(tmpsurf, FontBorder + 2, r.y + r.h, extracolor, font, extra);
+    r:= WriteInRect(tmpsurf, cFontBorder + 2, r.y + r.h, extracolor, font, extra);
 
-r.x:= FontBorder + 6;
-r.y:= FontBorder + 4;
+r.x:= cFontBorder + 6;
+r.y:= cFontBorder + 4;
 r.w:= 32;
 r.h:= 32;
 SDL_FillRect(tmpsurf, @r, $ffffffff);
@@ -1113,7 +1119,7 @@
 var ai: TAmmoType;
     i: LongInt;
 begin
-    RegisterVariable('fullscr', vtCommand, @chFullScr, true);
+    RegisterVariable('fullscr', @chFullScr, true);
 
     SDLPrimSurface:= nil;
 
--- a/hedgewars/uTeams.pas	Sun Apr 01 15:23:34 2012 +0200
+++ b/hedgewars/uTeams.pas	Wed May 02 23:53:45 2012 +0200
@@ -20,7 +20,7 @@
 
 unit uTeams;
 interface
-uses uConsts, uKeys, uGears, uRandom, uFloat, uStats, uVisualGears, uCollisions, GLunit, uSound, uTypes, uWorld;
+uses uConsts, uInputHandler, uGears, uRandom, uFloat, uStats, uVisualGears, uCollisions, GLunit, uSound, uTypes{$IFDEF USE_TOUCH_INTERFACE}, uWorld{$ENDIF};
 
 procedure initModule;
 procedure freeModule;
@@ -37,15 +37,16 @@
 
 implementation
 uses uLocale, uAmmos, uChat, uMobile, uVariables, uUtils, uIO, uCaptions, uCommands, uDebug, uScript,
-    uGearsUtils, uGearsList;
+    uGearsUtils, uGearsList{$IFDEF SDL13}, uTouch{$ENDIF};
 
-const MaxTeamHealth: LongInt = 0;
+var MaxTeamHealth: LongInt;
 
 function CheckForWin: boolean;
 var AliveClan: PClan;
     s: shortstring;
     t, AliveCount, i, j: LongInt;
 begin
+CheckForWin:= false;
 AliveCount:= 0;
 for t:= 0 to Pred(ClansCount) do
     if ClansArray[t]^.ClanHealth > 0 then
@@ -54,9 +55,8 @@
         AliveClan:= ClansArray[t]
         end;
 
-if (AliveCount > 1)
-or ((AliveCount = 1) and ((GameFlags and gfOneClanMode) <> 0)) then
-    exit(false);
+if (AliveCount > 1) or ((AliveCount = 1) and ((GameFlags and gfOneClanMode) <> 0)) then
+    exit;
 CheckForWin:= true;
 
 TurnTimeLeft:= 0;
@@ -205,6 +205,8 @@
 procedure AfterSwitchHedgehog;
 var i, t: LongInt;
     CurWeapon: PAmmo;
+    w: real;
+    vg: PVisualGear;
 
 begin
 if PlacingHogs then
@@ -226,7 +228,7 @@
 
 inc(CurrentTeam^.Clan^.TurnNumber);
 
-CurWeapon:= GetAmmoEntry(CurrentHedgehog^);
+CurWeapon:= GetCurAmmoEntry(CurrentHedgehog^);
 if CurWeapon^.Count = 0 then
     CurrentHedgehog^.CurAmmoType:= amNothing;
 
@@ -248,13 +250,10 @@
 
 if (GameFlags and gfDisableWind) = 0 then
     begin
-    cWindSpeed:= rndSign(GetRandom * 2 * cMaxWindSpeed);
-    // cWindSpeedf:= cWindSpeed.QWordValue / _1.QWordValue throws 'Internal error 200502052' on Darwin
-    // see http://mantis.freepascal.org/view.php?id=17714
-    cWindSpeedf:= SignAs(cWindSpeed,cWindSpeed).QWordValue / SignAs(_1,_1).QWordValue;
-    if cWindSpeed.isNegative then
-        CWindSpeedf := -cWindSpeedf;
-    AddVisualGear(0, 0, vgtSmoothWindBar);
+    cWindSpeed:= rndSign(GetRandomf * 2 * cMaxWindSpeed);
+    w:= hwFloat2Float(cWindSpeed);
+    vg:= AddVisualGear(0, 0, vgtSmoothWindBar);
+    if vg <> nil then vg^.dAngle:= w;
     AddFileLog('Wind = '+FloatToStr(cWindSpeed));
     end;
 
@@ -289,7 +288,7 @@
         AddVoice(sndIllGetYou, CurrentTeam^.voicepack)
     else
         AddVoice(sndYesSir, CurrentTeam^.voicepack);
-    if PlacingHogs or (cHedgehogTurnTime < 1000000) then
+    if cHedgehogTurnTime < 1000000 then
         ReadyTimeLeft:= cReadyDelay;
     AddCaption(Format(shortstring(trmsg[sidReady]), CurrentTeam^.TeamName), cWhiteColor, capgrpGameState)
     end
@@ -301,6 +300,9 @@
     end;
 
 uMobile.NewTurnBeginning();
+{$IFDEF SDL13}
+uTouch.NewTurnBeginning();
+{$ENDIF}
 ScriptCall('onNewTurn');
 end;
 
@@ -605,12 +607,12 @@
 
 procedure initModule;
 begin
-RegisterVariable('addhh', vtCommand, @chAddHH, false);
-RegisterVariable('addteam', vtCommand, @chAddTeam, false);
-RegisterVariable('hhcoords', vtCommand, @chSetHHCoords, false);
-RegisterVariable('bind', vtCommand, @chBind, true );
-RegisterVariable('teamgone', vtCommand, @chTeamGone, true );
-RegisterVariable('finish', vtCommand, @chFinish, true ); // all teams gone
+RegisterVariable('addhh', @chAddHH, false);
+RegisterVariable('addteam', @chAddTeam, false);
+RegisterVariable('hhcoords', @chSetHHCoords, false);
+RegisterVariable('bind', @chBind, true );
+RegisterVariable('teamgone', @chTeamGone, true );
+RegisterVariable('finish', @chFinish, true ); // all teams gone
 
 CurrentTeam:= nil;
 PreviousTeam:= nil;
@@ -622,6 +624,7 @@
 LocalAmmo:= -1;
 GameOver:= false;
 NextClan:= true;
+MaxTeamHealth:= 0;
 end;
 
 procedure freeModule;
--- a/hedgewars/uTextures.pas	Sun Apr 01 15:23:34 2012 +0200
+++ b/hedgewars/uTextures.pas	Wed May 02 23:53:45 2012 +0200
@@ -156,7 +156,7 @@
 
 fromP4:= Surf^.pixels;
 
-if cGrayScale then
+if GrayScale then
     Surface2GrayScale(Surf);
 
 if (not SupportNPOTT) and (not (isPowerOf2(Surf^.w) and isPowerOf2(Surf^.h))) then
--- a/hedgewars/uTouch.pas	Sun Apr 01 15:23:34 2012 +0200
+++ b/hedgewars/uTouch.pas	Wed May 02 23:53:45 2012 +0200
@@ -22,12 +22,14 @@
 
 interface
 
-uses sysutils, uConsole, uVariables, SDLh, uFloat, uConsts, uCommands, uIO, GLUnit, uTypes;
+uses sysutils, uConsole, uVariables, SDLh, uFloat, uConsts, uCommands, uIO, GLUnit, uTypes, uCaptions, uAmmos, uWorld;
 
 
 procedure initModule;
 
 procedure ProcessTouch;
+procedure NewTurnBeginning;
+
 procedure onTouchDown(x,y: Longword; pointerId: TSDL_FingerId);
 procedure onTouchMotion(x,y: Longword; dx,dy: LongInt; pointerId: TSDL_FingerId);
 procedure onTouchUp(x,y: Longword; pointerId: TSDL_FingerId);
@@ -59,7 +61,6 @@
 
 const
     clickTime = 200;
-    longClickTime = 400;
     nilFingerId = High(TSDL_FingerId);
 
 var
@@ -81,6 +82,7 @@
     targetAngle: LongInt;
 
     buttonsDown: Longword;
+    targetting, targetted: boolean; //true when targetting an airstrike or the like
 
 procedure onTouchDown(x,y: Longword; pointerId: TSDL_FingerId);
 var 
@@ -101,35 +103,37 @@
 
 if isOnWidget(fireButton, finger^) then
     begin
-    spaceKey:= true;
+    ParseTeamCommand('+attack');
     moveCursor:= false;
     finger^.pressedWidget:= @fireButton;
     exit;
     end;
 if isOnWidget(arrowLeft, finger^) then
     begin
-    leftKey:= true;
+    ParseTeamCommand('+left');
     moveCursor:= false;
     finger^.pressedWidget:= @arrowLeft;
     exit;
     end;
 if isOnWidget(arrowRight, finger^) then
     begin
-    rightKey:= true;
+    ParseTeamCommand('+right');
     moveCursor:= false;
     finger^.pressedWidget:= @arrowRight;
     exit;
     end;
 if isOnWidget(arrowUp, finger^) then
     begin
-    upKey:= true;
+    ParseTeamCommand('+up');
+    aimingUp:= true;
     moveCursor:= false;
     finger^.pressedWidget:= @arrowUp;
     exit;
     end;
 if isOnWidget(arrowDown, finger^) then
     begin
-    downKey:= true;
+    ParseTeamCommand('+down');
+    aimingDown:= true;
     moveCursor:= false;
     finger^.pressedWidget:= @arrowDown;
     exit;
@@ -145,19 +149,30 @@
 
 if isOnWidget(utilityWidget, finger^) then
     begin
-    //ParseCommand('/timer ' + inttostr((CurrentHedgeHog^.CurWeapon^.Timer div 1000 + 1) mod 5));
+    finger^.pressedWidget:= @utilityWidget;
+    moveCursor:= false;
+    if(CurrentHedgehog <> nil) then
+        begin
+        if Ammoz[CurrentHedgehog^.CurAmmoType].Ammo.Propz and ammoprop_Timerable <> 0 then
+            ParseTeamCommand('/timer ' + inttostr((GetCurAmmoEntry(CurrentHedgeHog^)^.Timer div 1000) mod 5 + 1));
+        end;
+    exit;
     end; 
 dec(buttonsDown);//no buttonsDown, undo the inc() above
 if buttonsDown = 0 then
     begin
     moveCursor:= true;
-    if pointerCount = 2 then
-        begin
-        moveCursor:= false;
-        pinchSize := calculateDelta(finger^, getSecondFinger(finger^)^);
-        baseZoomValue := ZoomValue
+    case pointerCount of
+        1:
+            targetting:= not(targetted) and (CurrentHedgehog <> nil) and (Ammoz[CurrentHedgehog^.CurAmmoType].Ammo.Propz and ammoprop_NeedTarget <> 0);
+        2:
+            begin
+            moveCursor:= false;
+            pinchSize := calculateDelta(finger^, getSecondFinger(finger^)^);
+            baseZoomValue := ZoomValue
+            end;
+        end;
     end;
-end;
 {$ENDIF}
 end;
 
@@ -214,10 +229,12 @@
 finger:= updateFinger(x,y,0,0,pointerId);
 //Check for onTouchClick event
 if not(fingerHasMoved(finger^)) then
+    begin
     if (RealTicks - finger^.timeSinceDown) < clickTime then
         onTouchClick(finger^)
     else
-        onTouchLongClick(finger^);
+            onTouchLongClick(finger^);
+    end;
 
 if aimingCrosshair then
     begin
@@ -233,20 +250,34 @@
     dec(buttonsDown);
     
     if widget = @arrowLeft then
-        leftKey:= false;
+        ParseTeamCommand('-left');
     
     if widget = @arrowRight then
-        rightKey:= false;
+        ParseTeamCommand('-right');
 
     if widget = @arrowUp then
-        upKey:= false;
+        ParseTeamCommand('-up');
 
     if widget = @arrowDown then
-        downKey:= false;
+        ParseTeamCommand('-down');
 
     if widget = @fireButton then
-        spaceKey:= false;
+        ParseTeamCommand('-attack');
+    
+    if widget = @utilityWidget then
+        if (CurrentHedgehog <> nil)then
+            if(Ammoz[CurrentHedgehog^.CurAmmoType].Ammo.Propz and ammoprop_NeedTarget <> 0)then
+                begin
+                ParseTeamCommand('put');
+                targetted:= true;
+                end
+            else if CurAmmoGear^.AmmoType = amSwitch then
+                ParseTeamCommand('switch')
+            else WriteLnToConsole(inttostr(ord(Ammoz[CurrentHedgehog^.CurAmmoType].NameId)) + ' ' + inttostr(ord(sidSwitch)));
     end;
+        
+if targetting then
+    AddCaption('Press the target button to mark the target', cWhiteColor, capgrpAmmoInfo);
  
 deleteFinger(pointerId);
 {$ENDIF}
@@ -262,11 +293,10 @@
 {$IFDEF USE_TOUCH_INTERFACE}
 if isOnWidget(jumpWidget, finger) then
     begin
-    ParseCommand('ljump', (CurrentTeam <> nil) and not(CurrentTeam^.ExtDriven) and (CurrentHedgehog^.BotLevel=0));
-    if (CurrentTeam <> nil) and (not CurrentTeam^.ExtDriven) and (ReadyTimeLeft > 1) then
-        ParseCommand('gencmd R', true);
+    ParseTeamCommand('ljump');
     exit;
     end;
+
 {$ENDIF}
 end;
 
@@ -305,9 +335,7 @@
 
 if isOnWidget(jumpWidget, finger) then
     begin
-    ParseCommand('hjump', (CurrentTeam <> nil) and not(CurrentTeam^.ExtDriven) and (CurrentHedgehog^.BotLevel=0));
-    if (CurrentTeam <> nil) and (not CurrentTeam^.ExtDriven) and (ReadyTimeLeft > 1) then
-        ParseCommand('gencmd R', true);
+    ParseTeamCommand('hjump');    
     exit;
     end;
 {$ENDIF}
@@ -386,21 +414,35 @@
 
 end;
 
+procedure NewTurnBeginning;
+begin
+targetted:= false;
+targetting:= false;
+SetUtilityWidgetState;
+end;
+
+
 procedure ProcessTouch;
 var
     deltaAngle: LongInt;
 begin
-invertCursor := not(bShowAmmoMenu);
+invertCursor := not(bShowAmmoMenu or targetting); 
 if aimingCrosshair then
     if CurrentHedgehog^.Gear <> nil then
         begin
         deltaAngle:= CurrentHedgehog^.Gear^.Angle - targetAngle;
         if (deltaAngle > -5) and (deltaAngle < 5) then 
             begin
-                upKey:= false;
-                aimingUp:= false;
-                downKey:= false;
-                aimingDown:= false;
+                if(aimingUp)then
+                    begin
+                    aimingUp:= false;
+                    ParseTeamCommand('-up');
+                    end;
+                if(aimingDown)then
+                    begin
+                    aimingDown:= false;
+                    ParseTeamCommand('-down');
+                    end
             end
         else
             begin
@@ -408,21 +450,27 @@
                 begin
                 if aimingUp then
                     begin
-                    upKey:= false;
                     aimingUp:= false;
+                    ParseTeamCommand('-up');
                     end;
-                downKey:= true;
-                aimingDown:= true;
+                if(aimingDown)then
+                    begin
+                    aimingDown:= true;
+                    ParseTeamCommand('-down');
+                    end
                 end
             else
                 begin
                 if aimingDown then
                     begin
-                    downKey:= false;
+                    ParseTeamCommand('-down');
                     aimingDown:= false;
                     end;
-                upKey:= true;
-                aimingUp:= true;
+                if aimingUp then
+                    begin
+                    aimingUp:= true;
+                    ParseTeamCommand('+up');
+                    end;
                 end; 
             end;
         end
@@ -430,12 +478,12 @@
         begin
         if aimingUp then
             begin
-            upKey:= false;
+            ParseTeamCommand('-up');
             aimingUp:= false;
             end;
         if aimingDown then
             begin
-            upKey:= false;
+            ParseTeamCommand('-down');
             aimingDown:= false;
             end;
         end;
@@ -534,7 +582,7 @@
 //Method to calculate the distance this finger has moved since the downEvent
 function fingerHasMoved(finger: TTouch_Data): boolean;
 begin
-    fingerHasMoved := trunc(sqrt(sqr(finger.X-finger.historicalX) + sqr(finger.y-finger.historicalY))) > 330;
+    fingerHasMoved := trunc(sqrt(sqr(finger.X-finger.historicalX) + sqr(finger.y-finger.historicalY))) > 30;
 end;
 
 function calculateDelta(finger1, finger2: TTouch_Data): LongInt; inline;
--- a/hedgewars/uTypes.pas	Sun Apr 01 15:23:34 2012 +0200
+++ b/hedgewars/uTypes.pas	Wed May 02 23:53:45 2012 +0200
@@ -59,7 +59,7 @@
             sprQuestion, sprPowerBar, sprWindBar, sprWindL, sprWindR,
 {$IFDEF USE_TOUCH_INTERFACE}
             sprFireButton, sprArrowUp, sprArrowDown, sprArrowLeft, sprArrowRight,
-            sprJumpWidget, sprAMWidget, sprPauseButton, sprTimerButton,
+            sprJumpWidget, sprAMWidget, sprPauseButton, sprTimerButton, sprTargetButton,
 {$ENDIF}
             sprFlake, sprHandRope, sprHandBazooka, sprHandShotgun,
             sprHandDEagle, sprHandAirAttack, sprHandBaseball, sprPHammer,
@@ -90,15 +90,16 @@
             );
 
     // Gears that interact with other Gears and/or Land
-    TGearType = (gtGrenade, gtHedgehog, gtShell, gtGrave, gtBee, // 4
-            gtShotgunShot, gtPickHammer, gtRope, gtMine, gtCase, // 9
-            gtDEagleShot, gtDynamite, gtClusterBomb, gtCluster, gtShover, // 14
-            gtFlame, gtFirePunch, gtATStartGame, // 17
-            gtATFinishGame, gtParachute, gtAirAttack, gtAirBomb, gtBlowTorch, // 22
-            gtGirder, gtTeleport, gtSwitcher, gtTarget, gtMortar, // 27
-            gtWhip, gtKamikaze, gtCake, gtSeduction, gtWatermelon, gtMelonPiece, // 33
-            gtHellishBomb, gtWaterUp, gtDrill, gtBallGun, gtBall, gtRCPlane, // 39
-            gtSniperRifleShot, gtJetpack, gtMolotov, gtExplosives, gtBirdy, // 44
+    TGearType = ({-->}gtFlame, gtHedgehog, gtMine, gtCase, gtExplosives, // <-- these are gears which should be avoided when searching a spawn place
+            gtGrenade, gtShell, gtGrave, gtBee, // 8
+            gtShotgunShot, gtPickHammer, gtRope,  // 11
+            gtDEagleShot, gtDynamite, gtClusterBomb, gtCluster, gtShover, // 16
+            gtFirePunch, gtATStartGame, // 18
+            gtATFinishGame, gtParachute, gtAirAttack, gtAirBomb, gtBlowTorch, // 23
+            gtGirder, gtTeleport, gtSwitcher, gtTarget, gtMortar, // 28
+            gtWhip, gtKamikaze, gtCake, gtSeduction, gtWatermelon, gtMelonPiece, // 34
+            gtHellishBomb, gtWaterUp, gtDrill, gtBallGun, gtBall, gtRCPlane, // 40
+            gtSniperRifleShot, gtJetpack, gtMolotov, gtBirdy, // 44
             gtEgg, gtPortal, gtPiano, gtGasBomb, gtSineGunShot, gtFlamethrower, // 50
             gtSMine, gtPoisonCloud, gtHammer, gtHammerHit, gtResurrector, // 55
             gtNapalmBomb, gtSnowball, gtFlake, gtStructure, gtLandGun, gtTardis); // 61
@@ -112,8 +113,6 @@
             vgtBigExplosion, vgtChunk, vgtNote, vgtLineTrail, vgtBulletHit, vgtCircle,
             vgtSmoothWindBar, vgtStraightShot);
 
-    TGearsType = set of TGearType;
-
     // Damage can be caused by different sources
     TDamageSource = (dsUnknown, dsFall, dsBullet, dsExplosion, dsShove, dsPoison);
 
@@ -175,7 +174,7 @@
             Handle: PTTF_Font;
             Height: LongInt;
             style: LongInt;
-            Name: string[21];
+            Name: string[31];
             end;
 
     PAmmo = ^TAmmo;
--- a/hedgewars/uUtils.pas	Sun Apr 01 15:23:34 2012 +0200
+++ b/hedgewars/uUtils.pas	Wed May 02 23:53:45 2012 +0200
@@ -26,12 +26,14 @@
 procedure SplitBySpace(var a, b: shortstring);
 procedure SplitByChar(var a, b: ansistring; c: char);
 
+{$IFNDEF PAS2C}
 function  EnumToStr(const en : TGearType) : shortstring; overload;
 function  EnumToStr(const en : TVisualGearType) : shortstring; overload;
 function  EnumToStr(const en : TSound) : shortstring; overload;
 function  EnumToStr(const en : TAmmoType) : shortstring; overload;
 function  EnumToStr(const en : THogEffect) : shortstring; overload;
 function  EnumToStr(const en : TCapGroup) : shortstring; overload;
+{$ENDIF}
 
 function  Min(a, b: LongInt): LongInt; inline;
 function  Max(a, b: LongInt): LongInt; inline;
@@ -42,7 +44,7 @@
 function  DxDy2Angle(const _dY, _dX: hwFloat): GLfloat;
 function  DxDy2Angle32(const _dY, _dX: hwFloat): LongInt;
 function  DxDy2AttackAngle(const _dY, _dX: hwFloat): LongInt;
-function  DxDy2AttackAngle(const _dY, _dX: extended): LongInt;
+function  DxDy2AttackAnglef(const _dY, _dX: extended): LongInt;
 
 procedure SetLittle(var r: hwFloat);
 
@@ -102,6 +104,7 @@
     end else b:= '';
 end;
 
+{$IFNDEF PAS2C}
 function EnumToStr(const en : TGearType) : shortstring; overload;
 begin
 EnumToStr:= GetEnumName(TypeInfo(TGearType), ord(en))
@@ -130,7 +133,7 @@
 begin
 EnumToStr := GetEnumName(TypeInfo(TCapGroup), ord(en))
 end;
-
+{$ENDIF}
 
 function Min(a, b: LongInt): LongInt;
 begin
@@ -198,9 +201,9 @@
 DxDy2AttackAngle:= trunc(arctan2(dY, dX) * MaxAngleDivPI)
 end;
 
-function DxDy2AttackAngle(const _dY, _dX: extended): LongInt; inline;
+function DxDy2AttackAnglef(const _dY, _dX: extended): LongInt; inline;
 begin
-DxDy2AttackAngle:= trunc(arctan2(_dY, _dX) * (cMaxAngle/pi))
+DxDy2AttackAnglef:= trunc(arctan2(_dY, _dX) * (cMaxAngle/pi))
 end;
 
 
@@ -256,8 +259,8 @@
 end;
 
 
+var CharArray: array[byte] of Char;
 function Str2PChar(const s: shortstring): PChar;
-const CharArray: array[byte] of Char = '';
 begin
 CharArray:= s;
 CharArray[Length(s)]:= #0;
@@ -293,12 +296,13 @@
     u: WideChar;
     tmpstr: array[0..256] of WideChar;
 begin
+CheckCJKFont:= font;
 
 {$IFNDEF MOBILE}
 // remove chinese fonts for now
 if (font >= CJKfnt16) or (length(s) = 0) then
 {$ENDIF}
-    exit(font);
+    exit;
 
 l:= Utf8ToUnicode(@tmpstr, Str2PChar(s), length(s))-1;
 i:= 0;
@@ -317,10 +321,13 @@
        ((#$AC00  <= u) and (u <= #$D7AF))  or // Hangul Syllables
        ((#$F900  <= u) and (u <= #$FAFF))  or // CJK Compatibility Ideographs
        ((#$FE30  <= u) and (u <= #$FE4F)))    // CJK Compatibility Forms
-       then exit(THWFont( ord(font) + ((ord(High(THWFont))+1) div 2) ));
+       then 
+        begin
+            CheckCJKFont:=  THWFont( ord(font) + ((ord(High(THWFont))+1) div 2) );
+            exit;
+        end;
     inc(i)
     end;
-exit(font);
 (* two more to check. pascal WideChar is only 16 bit though
        ((#$20000 <= u) and (u >= #$2A6DF)) or // CJK Unified Ideographs Extension B
        ((#$2F800 <= u) and (u >= #$2FA1F)))   // CJK Compatibility Ideographs Supplement *)
--- a/hedgewars/uVariables.pas	Sun Apr 01 15:23:34 2012 +0200
+++ b/hedgewars/uVariables.pas	Wed May 02 23:53:45 2012 +0200
@@ -110,10 +110,26 @@
 
     GameTicks   : LongWord;
 
+    // originally typed consts
+    CharArray: array[byte] of Char;
+    LastTint: Longword;
+    SocketString: shortstring;
+    VGCounter: Longword;
+    PrevX: LongInt;
+    timedelta: Longword;
+    StartTicks: Longword;
+    Counter: Longword;
+    StepTicks: LongWord;
+    ExplosionBorderColor: LongWord;
+    WaterOpacity: byte;
+    SDWaterOpacity: byte;
+    prevGState: TGameState;
+    GrayScale: Boolean;
+
     // originally from uConsts
     Pathz: array[TPathType] of shortstring;
     UserPathz: array[TPathType] of shortstring;
-    CountTexz: array[1..Pred(AMMO_INFINITE)] of PTexture;
+    CountTexz: array[0..Pred(AMMO_INFINITE)] of PTexture;
     LAND_WIDTH       : Word;
     LAND_HEIGHT      : Word;
     LAND_WIDTH_MASK  : LongWord;
@@ -194,6 +210,17 @@
 
     LuaGoals        : shortstring;
 
+    VoiceList : array[0..7] of TVoice =  (
+                    ( snd: sndNone; voicepack: nil),
+                    ( snd: sndNone; voicepack: nil),
+                    ( snd: sndNone; voicepack: nil),
+                    ( snd: sndNone; voicepack: nil),
+                    ( snd: sndNone; voicepack: nil),
+                    ( snd: sndNone; voicepack: nil),
+                    ( snd: sndNone; voicepack: nil),
+                    ( snd: sndNone; voicepack: nil));
+    LastVoice : TVoice = ( snd: sndNone; voicepack: nil );
+
 /////////////////////////////////////
 //Buttons
 {$IFDEF USE_TOUCH_INTERFACE}
@@ -203,14 +230,11 @@
     firebutton, jumpWidget, AMWidget          : TOnScreenWidget;
     pauseButton, utilityWidget                : TOnScreenWidget;
 {$ENDIF}
+    AMAnimType      : LongInt;
 
-    AMAnimType      : LongInt;
+
 const
-    cHHFileName = 'Hedgehog';
-    cCHFileName = 'Crosshair';
-    cThemeCFGFilename = 'theme.cfg';
-
-    FontBorder = 2;
+    // these consts are here because they would cause circular dependencies in uConsts/uTypes
     cPathz: array[TPathType] of shortstring = (
         '',                              // ptNone
         '',                              // ptData
@@ -236,20 +260,6 @@
         'Graphics/Buttons'                // ptButton
     );
 
-    cTagsMasks : array[0..15] of byte = (7, 0, 0, 0, 15, 6, 4, 5, 0, 0, 0, 0, 0, 14, 12, 13);
-    cTagsMasksNoHealth: array[0..15] of byte = (3, 2, 11, 1, 0, 0, 0, 0, 0, 10, 0, 9, 0, 0, 0, 0);
-
-    VoiceList : array[0..7] of TVoice =  (
-                    ( snd: sndNone; voicepack: nil),
-                    ( snd: sndNone; voicepack: nil),
-                    ( snd: sndNone; voicepack: nil),
-                    ( snd: sndNone; voicepack: nil),
-                    ( snd: sndNone; voicepack: nil),
-                    ( snd: sndNone; voicepack: nil),
-                    ( snd: sndNone; voicepack: nil),
-                    ( snd: sndNone; voicepack: nil));
-    LastVoice : TVoice = ( snd: sndNone; voicepack: nil );
-
     Fontz: array[THWFont] of THHFont = (
             (Handle: nil;
             Height: 12;
@@ -279,8 +289,9 @@
             {$ENDIF}
             );
 
+var
     SpritesData: array[TSprite] of record
-            FileName: string[16];
+            FileName: string[15];
             Path, AltPath: TPathType;
             Texture: PTexture;
             Surface: PSDL_Surface;
@@ -406,6 +417,8 @@
             Width: 120; Height: 100; imageWidth: 0; imageHeight: 0; saveSurf: false; priority: tpHigh; getDimensions: false; getImageDimensions: true), // sprPauseButton
             (FileName: 'pause'; Path: ptButtons; AltPath: ptNone; Texture: nil; Surface: nil;//TODO correct image
             Width: 120; Height: 128; imageWidth: 0; imageHeight: 0; saveSurf: false; priority: tpHigh; getDimensions: false; getImageDimensions: true), // sprTimerButton
+            (FileName: 'forwardjump'; Path: ptButtons; AltPath: ptNone; Texture: nil; Surface: nil;//TODO correct image
+            Width: 120; Height: 128; imageWidth: 0; imageHeight: 0; saveSurf: false; priority: tpHigh; getDimensions: false; getImageDimensions: true), // sprTargetButton
 {$ENDIF}
             (FileName:      'Flake'; Path:ptCurrTheme; AltPath: ptNone; Texture: nil; Surface: nil;
             Width:  64; Height: 64; imageWidth: 0; imageHeight: 0; saveSurf: false; priority: tpHighest; getDimensions: false; getImageDimensions: true),// sprFlake
@@ -620,7 +633,7 @@
                 imageWidth: 0; imageHeight: 0; saveSurf: false; priority:
                 tpMedium; getDimensions: false; getImageDimensions: true),
             //sprHandResurrector
-            (FileName: 'Cross'; Path: ptGraphics; altPath: ptNone;
+            (FileName: 'Cross'; Path: ptGraphics; AltPath: ptNone;
                 Texture: nil; Surface: nil; Width: 108; Height: 138;
                 imageWidth: 0; imageHeight: 0; saveSurf: false; priority:
                 tpMedium; getDimensions: false; getImageDimensions: true),
@@ -662,12 +675,12 @@
             Width: 3; Height: 17; imageWidth: 3; imageHeight: 17; saveSurf: false; priority: tpLow; getDimensions: false; getImageDimensions: false) // sprSlider
             );
 
-
+const
     Wavez: array [TWave] of record
             Sprite: TSprite;
             FramesCount: Longword;
             Interval: Longword;
-            cmd: string[20];
+            cmd: string[31];
             Voice: TSound;
             VoiceDelay: LongWord;
             end = (
@@ -681,7 +694,7 @@
             );
 
     Soundz: array[TSound] of record
-            FileName: string[25];
+            FileName: string[31];
             Path    : TPathType;
             end = (
             (FileName:                         ''; Path: ptNone  ),// sndNone
@@ -799,7 +812,7 @@
             (FileName:                'plane.ogg'; Path: ptSounds),// sndPlane
             (FileName:               'TARDIS.ogg'; Path: ptSounds) // sndTardis
             );
-
+var
     Ammoz: array [TAmmoType] of record
             NameId: TAmmoStrId;
             NameTex: PTexture;
@@ -842,7 +855,11 @@
             NameTex: nil;
             Probability: 0;
             NumberInCase: 1;
-            Ammo: (Propz: ammoprop_Timerable or ammoprop_Power or ammoprop_AltUse or ammoprop_SetBounce;
+            Ammo: (Propz: ammoprop_Timerable or 
+                          ammoprop_Power or 
+                          ammoprop_AltUse or 
+                          ammoprop_SetBounce or
+                          ammoprop_NeedUpDown;
                 Count: AMMO_INFINITE;
                 NumPerTurn: 0;
                 Timer: 3000;
@@ -866,7 +883,11 @@
             NameTex: nil;
             Probability: 100;
             NumberInCase: 3;
-            Ammo: (Propz: ammoprop_Timerable or ammoprop_Power or ammoprop_AltUse or ammoprop_SetBounce;
+            Ammo: (Propz: ammoprop_Timerable or 
+                          ammoprop_Power or 
+                          ammoprop_AltUse or 
+                          ammoprop_SetBounce or
+                          ammoprop_NeedUpDown;
                 Count: 5;
                 NumPerTurn: 0;
                 Timer: 3000;
@@ -890,7 +911,9 @@
             NameTex: nil;
             Probability: 0;
             NumberInCase: 1;
-            Ammo: (Propz: ammoprop_Power or ammoprop_AltUse;
+            Ammo: (Propz: ammoprop_Power or 
+                          ammoprop_AltUse or
+                          ammoprop_NeedUpDown;
                 Count: AMMO_INFINITE;
                 NumPerTurn: 0;
                 Timer: 0;
@@ -914,7 +937,10 @@
             NameTex: nil;
             Probability: 100;
             NumberInCase: 1;
-            Ammo: (Propz: ammoprop_Power or ammoprop_NeedTarget or ammoprop_DontHold;
+            Ammo: (Propz: ammoprop_Power or 
+                          ammoprop_NeedTarget or 
+                          ammoprop_DontHold or
+                          ammoprop_NeedUpDown;
                 Count: 2;
                 NumPerTurn: 0;
                 Timer: 0;
@@ -938,7 +964,8 @@
             NameTex: nil;
             Probability: 0;
             NumberInCase: 1;
-            Ammo: (Propz: ammoprop_ForwMsgs;
+            Ammo: (Propz: ammoprop_ForwMsgs or
+                          ammoprop_NeedUpDown;
                 Count: AMMO_INFINITE;
                 NumPerTurn: 1;
                 Timer: 0;
@@ -962,7 +989,10 @@
             NameTex: nil;
             Probability: 0;
             NumberInCase: 1;
-            Ammo: (Propz: ammoprop_ForwMsgs or ammoprop_AttackInMove or ammoprop_NoCrosshair or ammoprop_DontHold;
+            Ammo: (Propz: ammoprop_ForwMsgs or 
+                          ammoprop_AttackInMove or 
+                          ammoprop_NoCrosshair or 
+                          ammoprop_DontHold;
                 Count: 2;
                 NumPerTurn: 0;
                 Timer: 0;
@@ -986,7 +1016,8 @@
             NameTex: nil;
             Probability: 0;
             NumberInCase: 1;
-            Ammo: (Propz: ammoprop_NoCrosshair or ammoprop_DontHold;
+            Ammo: (Propz: ammoprop_NoCrosshair or 
+                          ammoprop_DontHold;
                 Count: AMMO_INFINITE;
                 NumPerTurn: 0;
                 Timer: 0;
@@ -1014,7 +1045,8 @@
                           ammoprop_ForwMsgs or
                           ammoprop_AttackInMove or
                           ammoprop_Utility or
-                          ammoprop_AltAttack;
+                          ammoprop_AltAttack or
+                          ammoprop_NeedUpDown;
                     Count: 5;
                     NumPerTurn: 0;
                     Timer: 0;
@@ -1038,7 +1070,11 @@
             NameTex: nil;
             Probability: 100;
             NumberInCase: 1;
-            Ammo: (Propz: ammoprop_NoCrosshair or ammoprop_AttackInMove or ammoprop_DontHold or ammoprop_AltUse or ammoprop_SetBounce;
+            Ammo: (Propz: ammoprop_NoCrosshair or 
+                          ammoprop_AttackInMove or 
+                          ammoprop_DontHold or 
+                          ammoprop_AltUse or 
+                          ammoprop_SetBounce;
                 Count: 2;
                 NumPerTurn: 0;
                 Timer: 0;
@@ -1062,7 +1098,7 @@
             NameTex: nil;
             Probability: 20;
             NumberInCase: 2;
-            Ammo: (Propz: 0;
+            Ammo: (Propz: ammoprop_NeedUpDown;
                 Count: 3;
                 NumPerTurn: 3;
                 Timer: 0;
@@ -1086,7 +1122,10 @@
             NameTex: nil;
             Probability: 100;
             NumberInCase: 1;
-            Ammo: (Propz: ammoprop_NoCrosshair or ammoprop_AttackInMove or ammoprop_DontHold or ammoprop_AltUse;
+            Ammo: (Propz: ammoprop_NoCrosshair or 
+                          ammoprop_AttackInMove or 
+                          ammoprop_DontHold or 
+                          ammoprop_AltUse;
                 Count: 1;
                 NumPerTurn: 0;
                 Timer: 0;
@@ -1110,7 +1149,9 @@
             NameTex: nil;
             Probability: 0;
             NumberInCase: 1;
-            Ammo: (Propz: ammoprop_NoCrosshair or ammoprop_ForwMsgs or ammoprop_AttackInMove;
+            Ammo: (Propz: ammoprop_NoCrosshair or 
+                          ammoprop_ForwMsgs or 
+                          ammoprop_AttackInMove;
                 Count: AMMO_INFINITE;
                 NumPerTurn: 0;
                 Timer: 0;
@@ -1120,7 +1161,7 @@
                 Bounciness: 1000);
             Slot: 3;
             TimeAfterTurn: 3000;
-            MinAngle: 0;
+            minAngle: 0;
             maxAngle: 0;
             isDamaging: true;
             SkipTurns: 0;
@@ -1144,7 +1185,7 @@
                 Bounciness: 1000);
             Slot: 3;
             TimeAfterTurn: 3000;
-            MinAngle: 0;
+            minAngle: 0;
             maxAngle: 0;
             isDamaging: true;
             SkipTurns: 0;
@@ -1158,7 +1199,8 @@
             NameTex: nil;
             Probability: 100;
             NumberInCase: 1;
-            Ammo: (Propz: ammoprop_DontHold;
+            Ammo: (Propz: ammoprop_DontHold or
+                          ammoprop_NeedUpDown;
                 Count: 1;
                 NumPerTurn: 0;
                 Timer: 0;
@@ -1188,7 +1230,8 @@
                           ammoprop_NoCrosshair or
                           ammoprop_DontHold or
                           ammoprop_Utility or
-                          ammoprop_AltAttack;
+                          ammoprop_AltAttack or
+                          ammoprop_NeedUpDown;
                 Count: 2;
                 NumPerTurn: 0;
                 Timer: 0;
@@ -1213,10 +1256,10 @@
             Probability: 100;
             NumberInCase: 1;
             Ammo: (Propz: ammoprop_NoCrosshair or
-                            ammoprop_NeedTarget or
-                            ammoprop_AttackingPut or
-                            ammoprop_DontHold or
-                            ammoprop_NotBorder;
+                          ammoprop_NeedTarget or
+                          ammoprop_AttackingPut or
+                          ammoprop_DontHold or
+                          ammoprop_NotBorder;
                 Count: 1;
                 NumPerTurn: 0;
                 Timer: 0;
@@ -1241,10 +1284,10 @@
             Probability: 200;
             NumberInCase: 1;
             Ammo: (Propz: ammoprop_NoCrosshair or
-                            ammoprop_NeedTarget or
-                            ammoprop_AttackingPut or
-                            ammoprop_DontHold or
-                            ammoprop_NotBorder;
+                          ammoprop_NeedTarget or
+                          ammoprop_AttackingPut or
+                          ammoprop_DontHold or
+                          ammoprop_NotBorder;
                 Count: 1;
                 NumPerTurn: 0;
                 Timer: 0;
@@ -1268,7 +1311,8 @@
             NameTex: nil;
             Probability: 100;
             NumberInCase: 2;
-            Ammo: (Propz: ammoprop_ForwMsgs;
+            Ammo: (Propz: ammoprop_ForwMsgs or
+                          ammoprop_NeedUpDown;
                 Count: 1;
                 NumPerTurn: 0;
                 Timer: 0;
@@ -1401,7 +1445,10 @@
             NameTex: nil;
             Probability: 100;
             NumberInCase: 1;
-            Ammo: (Propz: ammoprop_ForwMsgs or ammoprop_DontHold or ammoprop_AttackInMove;
+            Ammo: (Propz: ammoprop_ForwMsgs or 
+                          ammoprop_DontHold or 
+                          ammoprop_NeedUpDown or
+                          ammoprop_AttackInMove;
                 Count: 1;
                 NumPerTurn: 0;
                 Timer: 0;
@@ -1425,7 +1472,9 @@
             NameTex: nil;
             Probability: 100;
             NumberInCase: 1;
-            Ammo: (Propz: ammoprop_ForwMsgs or ammoprop_NoCrosshair or ammoprop_DontHold;
+            Ammo: (Propz: ammoprop_ForwMsgs or 
+                          ammoprop_NoCrosshair or 
+                          ammoprop_DontHold;
                 Count: 1;
                 NumPerTurn: 0;
                 Timer: 0;
@@ -1449,7 +1498,9 @@
             NameTex: nil;
             Probability: 100;
             NumberInCase: 1;
-            Ammo: (Propz: ammoprop_ForwMsgs or ammoprop_DontHold or ammoprop_NoCrosshair;
+            Ammo: (Propz: ammoprop_ForwMsgs or 
+                          ammoprop_DontHold or
+                          ammoprop_NoCrosshair;
                 Count: 1;
                 NumPerTurn: 0;
                 Timer: 0;
@@ -1473,7 +1524,10 @@
             NameTex: nil;
             Probability: 400;
             NumberInCase: 1;
-            Ammo: (Propz: ammoprop_Timerable or ammoprop_Power or ammoprop_AltUse;
+            Ammo: (Propz: ammoprop_Timerable or 
+                          ammoprop_Power or 
+                          ammoprop_NeedUpDown or
+                          ammoprop_AltUse;
                 Count: 0;
                 NumPerTurn: 0;
                 Timer: 3000;
@@ -1497,7 +1551,9 @@
             NameTex: nil;
             Probability: 400;
             NumberInCase: 1;
-            Ammo: (Propz:  ammoprop_Power or ammoprop_AltUse;
+            Ammo: (Propz: ammoprop_Power or 
+                          ammoprop_NeedUpDown or
+                          ammoprop_AltUse;
                 Count: 0;
                 NumPerTurn: 0;
                 Timer: 5000;
@@ -1522,10 +1578,10 @@
             Probability: 100;
             NumberInCase: 1;
             Ammo: (Propz: ammoprop_NoCrosshair or
-                            ammoprop_NeedTarget or
-                            ammoprop_AttackingPut or
-                            ammoprop_DontHold or
-                            ammoprop_NotBorder;
+                          ammoprop_NeedTarget or
+                          ammoprop_AttackingPut or
+                          ammoprop_DontHold or
+                          ammoprop_NotBorder;
                 Count: 1;
                 NumPerTurn: 0;
                 Timer: 0;
@@ -1549,7 +1605,9 @@
             NameTex: nil;
             Probability: 300;
             NumberInCase: 1;
-            Ammo: (Propz: ammoprop_Power or ammoprop_AltUse;
+            Ammo: (Propz: ammoprop_Power or 
+                          ammoprop_NeedUpDown or
+                          ammoprop_AltUse;
                 Count: AMMO_INFINITE;
                 NumPerTurn: 0;
                 Timer: 0;
@@ -1573,7 +1631,9 @@
             NameTex: nil;
             Probability: 400;
             NumberInCase: 1;
-            Ammo: (Propz:  ammoprop_ForwMsgs or ammoprop_DontHold;
+            Ammo: (Propz: ammoprop_ForwMsgs or 
+                          ammoprop_NeedUpDown or
+                          ammoprop_DontHold;
                 Count: AMMO_INFINITE;
                 NumPerTurn: 0;
                 Timer: 5001;
@@ -1597,9 +1657,10 @@
             NameTex: nil;
             Probability: 200;
             NumberInCase: 1;
-            Ammo: (Propz: ammoprop_ForwMsgs{ or
-                            ammoprop_DontHold or
-                            ammoprop_AltAttack};
+            Ammo: (Propz: ammoprop_ForwMsgs or
+                          ammoprop_NeedUpDown{ or
+                          ammoprop_DontHold or
+                          ammoprop_AltAttack};
                 Count: 1;
                 NumPerTurn: 0;
                 Timer: 0;
@@ -1744,6 +1805,7 @@
                           ammoprop_DontHold or
                           ammoprop_AltUse or
                           ammoprop_Utility or
+                          ammoprop_NeedUpDown or
                           ammoprop_Effect;
                     Count: 1;
                     NumPerTurn: 0;
@@ -1797,7 +1859,7 @@
             NameTex: nil;
             Probability: 20;
             NumberInCase: 2;
-            Ammo: (Propz: 0;
+            Ammo: (Propz: ammoprop_NeedUpDown;
                 Count: 2;
                 NumPerTurn: 1;
                 Timer: 0;
@@ -1827,6 +1889,7 @@
                           ammoprop_NoCrosshair or
                           ammoprop_DontHold or
                           ammoprop_Utility or
+                          ammoprop_NeedUpDown or
                           ammoprop_AltAttack;
                 Count: 1;
                 NumPerTurn: 0;
@@ -1851,7 +1914,9 @@
             NameTex: nil;
             Probability: 0;
             NumberInCase: 1;
-            Ammo: (Propz: ammoprop_Power or ammoprop_AltUse;
+            Ammo: (Propz: ammoprop_Power or 
+                          ammoprop_NeedUpDown or
+                          ammoprop_AltUse;
                 Count: AMMO_INFINITE;
                 NumPerTurn: 0;
                 Timer: 3000;
@@ -1877,6 +1942,7 @@
             NumberInCase: 1;
             Ammo: (Propz: ammoprop_ForwMsgs or
                           ammoprop_NoCrosshair or
+                          ammoprop_NeedUpDown or
                           ammoprop_DontHold;
                 Count: 1;
                 NumPerTurn: 0;
@@ -1904,6 +1970,7 @@
             Ammo: (Propz: ammoprop_NoRoundEnd or
                           ammoprop_AttackInMove or
                           ammoprop_DontHold or
+                          ammoprop_NeedUpDown or
                           ammoprop_Utility;
                 Count: 1;
                 NumPerTurn: 3;
@@ -1956,7 +2023,11 @@
             NameTex: nil;
             Probability: 0;
             NumberInCase: 1;
-            Ammo: (Propz: ammoprop_Timerable or ammoprop_Power or ammoprop_AltUse or ammoprop_SetBounce;
+            Ammo: (Propz: ammoprop_Timerable or 
+                          ammoprop_Power or 
+                          ammoprop_AltUse or 
+                          ammoprop_NeedUpDown or
+                          ammoprop_SetBounce;
                 Count: AMMO_INFINITE;
                 NumPerTurn: 0;
                 Timer: 3000;
@@ -1980,7 +2051,8 @@
             NameTex: nil;
             Probability: 20;
             NumberInCase: 2;
-            Ammo: (Propz: ammoprop_AttackInMove;
+            Ammo: (Propz: ammoprop_AttackInMove or
+                          ammoprop_NeedUpDown;
                 Count: 1;
                 NumPerTurn: 0;
                 Timer: 0;
@@ -2004,7 +2076,9 @@
             NameTex: nil;
             Probability: 20;
             NumberInCase: 1;
-            Ammo: (Propz:  ammoprop_ForwMsgs or ammoprop_DontHold;
+            Ammo: (Propz: ammoprop_ForwMsgs or 
+                          ammoprop_NeedUpDown or
+                          ammoprop_DontHold;
                 Count: 1;
                 NumPerTurn: 0;
                 Timer: 5001;
@@ -2028,7 +2102,8 @@
             NameTex: nil;
             Probability: 100;
             NumberInCase: 1;
-            Ammo: (Propz: ammoprop_Power; //FIXME: enable multishoot at altuse, until then removed ammoprop_AltUse
+            Ammo: (Propz: ammoprop_Power or
+                          ammoprop_NeedUpDown; //FIXME: enable multishoot at altuse, until then removed ammoprop_AltUse
                 Count: 1;
                 NumPerTurn: 1;
                 Timer: 0;
@@ -2062,7 +2137,7 @@
                 Bounciness: 1000);
             Slot: 3;
             TimeAfterTurn: 3000;
-            MinAngle: 0;
+            minAngle: 0;
             maxAngle: 0;
             isDamaging: true;
             SkipTurns: 0;
@@ -2212,6 +2287,7 @@
             Probability: 20;
             NumberInCase: 1;
             Ammo: (Propz: ammoprop_NoRoundEnd or
+                          ammoprop_NeedTarget or
                           ammoprop_Utility;
                 Count: 1;
                 NumPerTurn: 0;
@@ -2232,23 +2308,25 @@
             ejectY: -3)
         );
 
+const
     GearKindAmmoTypeMap : array [TGearType] of TAmmoType = (    
-(*        gtGrenade *)   amGrenade
+(*          gtFlame *)   amNothing
 (*       gtHedgehog *) , amNothing
+(*           gtMine *) , amNothing
+(*           gtCase *) , amNothing
+(*     gtExplosives *) , amNothing
+(*        gtGrenade *) , amGrenade
 (*          gtShell *) , amBazooka
 (*          gtGrave *) , amNothing
 (*            gtBee *) , amBee
 (*    gtShotgunShot *) , amShotgun
 (*     gtPickHammer *) , amPickHammer
 (*           gtRope *) , amRope
-(*           gtMine *) , amNothing
-(*           gtCase *) , amNothing
 (*     gtDEagleShot *) , amDEagle
 (*       gtDynamite *) , amDynamite
 (*    gtClusterBomb *) , amClusterBomb
 (*        gtCluster *) , amClusterBomb
 (*         gtShover *) , amBaseballBat  // Shover is only used for baseball bat right now
-(*          gtFlame *) , amNothing
 (*      gtFirePunch *) , amFirePunch
 (*    gtATStartGame *) , amNothing
 (*   gtATFinishGame *) , amNothing
@@ -2276,7 +2354,6 @@
 (*gtSniperRifleShot *) , amSniperRifle
 (*        gtJetpack *) , amJetpack
 (*        gtMolotov *) , amMolotov
-(*     gtExplosives *) , amNothing
 (*          gtBirdy *) , amBirdy
 (*            gtEgg *) , amBirdy
 (*         gtPortal *) , amPortalGun
@@ -2378,7 +2455,6 @@
     vobSDFrameTicks, vobSDFramesCount, vobSDCount: Longword;
     vobSDVelocity, vobSDFallSpeed: LongInt;
 
-
     hideAmmoMenu: boolean;
     wheelUp: boolean;
     wheelDown: boolean;
@@ -2394,29 +2470,7 @@
     ControllerHats: array[0..5] of array[0..19] of Byte;
     ControllerButtons: array[0..5] of array[0..19] of Byte;
 
-    DefaultBinds, CurrentBinds: TBinds;
-
-    coeff: LongInt;
-
-{$IFDEF HWLIBRARY}
-    leftClick: boolean;
-    middleClick: boolean;
-    rightClick: boolean;
-
-    upKey: boolean;
-    downKey: boolean;
-    rightKey: boolean;
-    leftKey: boolean;
-    preciseKey: boolean;
-
-    backspaceKey: boolean;
-    spaceKey: boolean;
-    enterKey: boolean;
-    tabKey: boolean;
-
-    chatAction: boolean;
-    pauseAction: boolean;
-{$ENDIF}
+    DefaultBinds : TBinds;
 
 var trammo:  array[TAmmoStrId] of ansistring;   // name of the weapon
     trammoc: array[TAmmoStrId] of ansistring;   // caption of the weapon
@@ -2563,12 +2617,28 @@
     else
         cMaxCaptions:= 4;
 
+    vobFrameTicks:= 99999;
+    vobFramesCount:= 4;
+    vobCount:= 0;
+    vobVelocity:= 10;
+    vobFallSpeed:= 100;
+
     vobSDFrameTicks:= 99999;
     vobSDFramesCount:= 4;
     vobSDCount:= 30 * cScreenSpace div LAND_WIDTH;
     vobSDVelocity:= 15;
     vobSDFallSpeed:= 250;
 
+    PrevX:= 0;
+    timedelta:= 0;
+    Counter:= 0;
+    StepTicks:= 0;
+    ExplosionBorderColor:= $FF808080;
+    WaterOpacity:= $80;
+    SDWaterOpacity:= $80;
+    prevGState:= gsConfirm;
+    GrayScale:= false;
+
     LuaGoals:= '';
 end;
 
--- a/hedgewars/uVisualGears.pas	Sun Apr 01 15:23:34 2012 +0200
+++ b/hedgewars/uVisualGears.pas	Wed May 02 23:53:45 2012 +0200
@@ -34,20 +34,26 @@
 procedure initModule;
 procedure freeModule;
 
-function  AddVisualGear(X, Y: LongInt; Kind: TVisualGearType; State: LongWord = 0; Critical: Boolean = false): PVisualGear;
+function  AddVisualGear(X, Y: LongInt; Kind: TVisualGearType): PVisualGear; inline;
+function  AddVisualGear(X, Y: LongInt; Kind: TVisualGearType; State: LongWord): PVisualGear; inline;
+function  AddVisualGear(X, Y: LongInt; Kind: TVisualGearType; State: LongWord; Critical: Boolean): PVisualGear;
+
 procedure ProcessVisualGears(Steps: Longword);
-procedure KickFlakes(Radius, X, Y: LongInt);
 procedure DrawVisualGears(Layer: LongWord);
 procedure DeleteVisualGear(Gear: PVisualGear);
 function  VisualGearByUID(uid : Longword) : PVisualGear;
+
 procedure AddClouds;
-procedure ChangeToSDClouds;
 procedure AddFlakes;
-procedure ChangeToSDFlakes;
 procedure AddDamageTag(X, Y, Damage, Color: LongWord);
 
+procedure ChangeToSDClouds;
+procedure ChangeToSDFlakes;
+
+procedure KickFlakes(Radius, X, Y: LongInt);
+
 implementation
-uses uSound, uMobile, uVariables, uTextures, uRender, Math, uRenderUtils, uStore;
+uses uSound, uMobile, uVariables, uTextures, uRender, Math, uRenderUtils, uStore, uUtils;
 
 const cExplFrameTicks = 110;
 
@@ -112,8 +118,17 @@
             @doStepStraightShot
         );
 
-function  AddVisualGear(X, Y: LongInt; Kind: TVisualGearType; State: LongWord = 0; Critical: Boolean = false): PVisualGear;
-const VGCounter: Longword = 0;
+function AddVisualGear(X, Y: LongInt; Kind: TVisualGearType): PVisualGear; inline;
+begin
+    AddVisualGear:= AddVisualGear(X, Y, Kind, 0, false);
+end;
+
+function  AddVisualGear(X, Y: LongInt; Kind: TVisualGearType; State: LongWord): PVisualGear; inline;
+begin
+    AddVisualGear:= AddVisualGear(X, Y, Kind, State, false);
+end;
+
+function AddVisualGear(X, Y: LongInt; Kind: TVisualGearType; State: LongWord; Critical: Boolean): PVisualGear;
 var gear: PVisualGear;
     t: Longword;
     sp: real;
@@ -365,7 +380,11 @@
                 Frame:= 7;
                 Angle:= 0;
                 end;
-vgtSmoothWindBar: Tag:= hwRound(cWindSpeed * 72 / cMaxWindSpeed);
+vgtSmoothWindBar: 
+                begin
+                Angle:= hwFloat2Float(cMaxWindSpeed)*2 / 1440; // seems rate below is supposed to change wind bar at 1px per 10ms. Max time, 1440ms. This tries to match the rate of change
+                Tag:= hwRound(cWindSpeed * 72 / cMaxWindSpeed);
+                end;
  vgtStraightShot:
                 begin
                 Angle:= 0;
@@ -566,12 +585,12 @@
                                  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)
+                                     DrawSpriteRotatedF(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)
+                                     DrawSpriteRotatedF(sprFlake, round(Gear^.X) + WorldDx, round(Gear^.Y) + WorldDy + SkyOffset, Gear^.Frame, 1, Gear^.Angle)
                              end
                          else
                              begin
@@ -579,12 +598,12 @@
                                  if vobSDVelocity = 0 then
                                      DrawTextureF(SpritesData[sprSDFlake].Texture, Gear^.Scale, round(Gear^.X) + WorldDx, round(Gear^.Y) + WorldDy + SkyOffset, Gear^.Frame, 1, SpritesData[sprFlake].Width, SpritesData[sprFlake].Height)
                                  else
-                                     DrawRotatedTextureF(SpritesData[sprSDFlake].Texture, Gear^.Scale, 0, 0, round(Gear^.X) + WorldDx, round(Gear^.Y) + WorldDy + SkyOffset, Gear^.Frame, 1, SpritesData[sprFlake].Width, SpritesData[sprFlake].Height, Gear^.Angle)
+                                     DrawTextureRotatedF(SpritesData[sprSDFlake].Texture, Gear^.Scale, 0, 0, round(Gear^.X) + WorldDx, round(Gear^.Y) + WorldDy + SkyOffset, Gear^.Frame, 1, SpritesData[sprFlake].Width, SpritesData[sprFlake].Height, Gear^.Angle)
                              else
                                  if vobVelocity = 0 then
                                      DrawTextureF(SpritesData[sprFlake].Texture, Gear^.Scale, round(Gear^.X) + WorldDx, round(Gear^.Y) + WorldDy + SkyOffset, Gear^.Frame, 1, SpritesData[sprFlake].Width, SpritesData[sprFlake].Height)
                                  else
-                                     DrawRotatedTextureF(SpritesData[sprFlake].Texture, Gear^.Scale, 0, 0, round(Gear^.X) + WorldDx, round(Gear^.Y) + WorldDy + SkyOffset, Gear^.Frame, 1, SpritesData[sprFlake].Width, SpritesData[sprFlake].Height, Gear^.Angle)
+                                     DrawTextureRotatedF(SpritesData[sprFlake].Texture, Gear^.Scale, 0, 0, round(Gear^.X) + WorldDx, round(Gear^.Y) + WorldDy + SkyOffset, Gear^.Frame, 1, SpritesData[sprFlake].Width, SpritesData[sprFlake].Height, Gear^.Angle)
                              end;
                end;
            if Gear^.Tint <> $FFFFFFFF then
@@ -605,12 +624,12 @@
                              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)
+                                 DrawSpriteRotatedF(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);
+                                 DrawSpriteRotatedF(sprFlake, round(Gear^.X) + WorldDx, round(Gear^.Y) + WorldDy + SkyOffset, Gear^.Frame, 1, Gear^.Angle);
               vgtSmokeTrace: if Gear^.State < 8 then
                   DrawSprite(sprSmokeTrace, round(Gear^.X) + WorldDx, round(Gear^.Y) + WorldDy, Gear^.State);
               vgtEvilTrace: if Gear^.State < 8 then
@@ -661,27 +680,27 @@
                              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)
+                                 DrawSpriteRotatedF(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);*)
+                                 DrawSpriteRotatedF(sprFlake, round(Gear^.X) + WorldDx, round(Gear^.Y) + WorldDy + SkyOffset, Gear^.Frame, 1, Gear^.Angle);*)
                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)
+                                    DrawTextureCentered(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);
+                                    DrawTextureCentered(round(Gear^.X) + WorldDx, round(Gear^.Y) + WorldDy, Gear^.Tex);
                                 end;
-               vgtSmallDamageTag: DrawCentered(round(Gear^.X) + WorldDx, round(Gear^.Y) + WorldDy, Gear^.Tex);
+               vgtSmallDamageTag: DrawTextureCentered(round(Gear^.X) + WorldDx, round(Gear^.Y) + WorldDy, Gear^.Tex);
                vgtHealthTag: if Gear^.Tex <> nil then 
                                begin
                                if Gear^.Frame = 0 then 
-                                   DrawCentered(round(Gear^.X) + WorldDx, round(Gear^.Y) + WorldDy, Gear^.Tex)
+                                   DrawTextureCentered(round(Gear^.X) + WorldDx, round(Gear^.Y) + WorldDy, Gear^.Tex)
                                else
                                    begin
                                    SetScale(cDefaultZoomLevel);
@@ -697,12 +716,12 @@
                                     i:= -1
                                 else
                                     i:= 1;
-                                DrawRotatedTextureF(SpritesData[TSprite(Gear^.State)].Texture, Gear^.Scale, 0, 0, round(Gear^.X) + WorldDx, round(Gear^.Y) + WorldDy, Gear^.Frame, i, SpritesData[TSprite(Gear^.State)].Width, SpritesData[TSprite(Gear^.State)].Height, Gear^.Angle);
+                                DrawTextureRotatedF(SpritesData[TSprite(Gear^.State)].Texture, Gear^.Scale, 0, 0, round(Gear^.X) + WorldDx, round(Gear^.Y) + WorldDy, Gear^.Frame, i, SpritesData[TSprite(Gear^.State)].Width, SpritesData[TSprite(Gear^.State)].Height, Gear^.Angle);
                                 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);
+                   vgtChunk: DrawSpriteRotatedF(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);
@@ -722,7 +741,7 @@
                vgtBigExplosion: begin
                                 tinted:= true;
                                 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);
+                                DrawTextureRotatedF(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;
            if (cReducedQuality and rqAntiBoom) = 0 then
@@ -742,7 +761,7 @@
                                  Tint($FF, $FF, $FF, Gear^.FrameTicks);
                                  tinted:= true
                                  end;
-                             DrawRotatedF(sprShell, round(Gear^.X) + WorldDx, round(Gear^.Y) + WorldDy, Gear^.Frame, 1, Gear^.Angle);
+                             DrawSpriteRotatedF(sprShell, round(Gear^.X) + WorldDx, round(Gear^.Y) + WorldDy, Gear^.Frame, 1, Gear^.Angle);
                              end;
                    vgtFeather: begin
                                if Gear^.FrameTicks < 255 then
@@ -750,36 +769,36 @@
                                    Tint($FF, $FF, $FF, Gear^.FrameTicks);
                                    tinted:= true
                                    end;
-                               DrawRotatedF(sprFeather, round(Gear^.X) + WorldDx, round(Gear^.Y) + WorldDy, Gear^.Frame, 1, Gear^.Angle);
+                               DrawSpriteRotatedF(sprFeather, round(Gear^.X) + WorldDx, round(Gear^.Y) + WorldDy, Gear^.Frame, 1, Gear^.Angle);
                              end;
-                   vgtEgg: DrawRotatedF(sprEgg, round(Gear^.X) + WorldDx, round(Gear^.Y) + WorldDy, Gear^.Frame, 1, Gear^.Angle);
+                   vgtEgg: DrawSpriteRotatedF(sprEgg, round(Gear^.X) + WorldDx, round(Gear^.Y) + WorldDy, Gear^.Frame, 1, Gear^.Angle);
                    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);
+                                DrawSpriteRotatedF(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);
+                                 DrawTextureRotatedF(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);
+                   vgtNote: DrawSpriteRotatedF(sprNote, round(Gear^.X) + WorldDx, round(Gear^.Y) + WorldDy, Gear^.Frame, 1, Gear^.Angle);
+                   vgtBulletHit: DrawSpriteRotatedF(sprBulletHit, round(Gear^.X) + WorldDx - 0, round(Gear^.Y) + WorldDy - 0, 7 - (Gear^.FrameTicks div 50), 1, Gear^.Angle);
                end;
            case Gear^.Kind of
                vgtFlake: if SuddenDeathDmg then
                              if vobSDVelocity = 0 then
                                  DrawTextureF(SpritesData[sprSDFlake].Texture, Gear^.Scale, round(Gear^.X) + WorldDx, round(Gear^.Y) + WorldDy + SkyOffset, Gear^.Frame, 1, SpritesData[sprFlake].Width, SpritesData[sprFlake].Height)
                              else
-                                 DrawRotatedTextureF(SpritesData[sprSDFlake].Texture, Gear^.Scale, 0, 0, round(Gear^.X) + WorldDx, round(Gear^.Y) + WorldDy + SkyOffset, Gear^.Frame, 1, SpritesData[sprFlake].Width, SpritesData[sprFlake].Height, Gear^.Angle)
+                                 DrawTextureRotatedF(SpritesData[sprSDFlake].Texture, Gear^.Scale, 0, 0, round(Gear^.X) + WorldDx, round(Gear^.Y) + WorldDy + SkyOffset, Gear^.Frame, 1, SpritesData[sprFlake].Width, SpritesData[sprFlake].Height, Gear^.Angle)
                          else
                              if vobVelocity = 0 then
                                  DrawTextureF(SpritesData[sprFlake].Texture, Gear^.Scale, round(Gear^.X) + WorldDx, round(Gear^.Y) + WorldDy + SkyOffset, Gear^.Frame, 1, SpritesData[sprFlake].Width, SpritesData[sprFlake].Height)
                              else
-                                 DrawRotatedTextureF(SpritesData[sprFlake].Texture, Gear^.Scale, 0, 0, round(Gear^.X) + WorldDx, round(Gear^.Y) + WorldDy + SkyOffset, Gear^.Frame, 1, SpritesData[sprFlake].Width, SpritesData[sprFlake].Height, Gear^.Angle);
+                                 DrawTextureRotatedF(SpritesData[sprFlake].Texture, Gear^.Scale, 0, 0, round(Gear^.X) + WorldDx, round(Gear^.Y) + WorldDy + SkyOffset, Gear^.Frame, 1, SpritesData[sprFlake].Width, SpritesData[sprFlake].Height, Gear^.Angle);
                vgtCircle: if gear^.Angle = 1 then
                               begin
                               tmp:= Gear^.State / 100;
@@ -809,12 +828,12 @@
                             if vobSDVelocity = 0 then
                                 DrawTextureF(SpritesData[sprSDFlake].Texture, Gear^.Scale, round(Gear^.X) + WorldDx, round(Gear^.Y) + WorldDy + SkyOffset, Gear^.Frame, 1, SpritesData[sprFlake].Width, SpritesData[sprFlake].Height)
                             else
-                                DrawRotatedTextureF(SpritesData[sprSDFlake].Texture, Gear^.Scale, 0, 0, round(Gear^.X) + WorldDx, round(Gear^.Y) + WorldDy + SkyOffset, Gear^.Frame, 1, SpritesData[sprFlake].Width, SpritesData[sprFlake].Height, Gear^.Angle)
+                                DrawTextureRotatedF(SpritesData[sprSDFlake].Texture, Gear^.Scale, 0, 0, round(Gear^.X) + WorldDx, round(Gear^.Y) + WorldDy + SkyOffset, Gear^.Frame, 1, SpritesData[sprFlake].Width, SpritesData[sprFlake].Height, Gear^.Angle)
                         else
                             if vobVelocity = 0 then
                                 DrawTextureF(SpritesData[sprFlake].Texture, Gear^.Scale, round(Gear^.X) + WorldDx, round(Gear^.Y) + WorldDy + SkyOffset, Gear^.Frame, 1, SpritesData[sprFlake].Width, SpritesData[sprFlake].Height)
                             else
-                                DrawRotatedTextureF(SpritesData[sprFlake].Texture, Gear^.Scale, 0, 0, round(Gear^.X) + WorldDx, round(Gear^.Y) + WorldDy + SkyOffset, Gear^.Frame, 1, SpritesData[sprFlake].Width, SpritesData[sprFlake].Height, Gear^.Angle);
+                                DrawTextureRotatedF(SpritesData[sprFlake].Texture, Gear^.Scale, 0, 0, round(Gear^.X) + WorldDx, round(Gear^.Y) + WorldDy + SkyOffset, Gear^.Frame, 1, SpritesData[sprFlake].Width, SpritesData[sprFlake].Height, Gear^.Angle);
             end;
             if (Gear^.Tint <> $FFFFFFFF) then
                 Tint($FF,$FF,$FF,$FF);
@@ -837,12 +856,12 @@
                             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)
+                                DrawSpriteRotatedF(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);
+                                DrawSpriteRotatedF(sprFlake, round(Gear^.X) + WorldDx, round(Gear^.Y) + WorldDy + SkyOffset, Gear^.Frame, 1, Gear^.Angle);
                 end;
             if (Gear^.Tint <> $FFFFFFFF) then
                 Tint($FF,$FF,$FF,$FF);
@@ -861,12 +880,12 @@
                             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)
+                                DrawSpriteRotatedF(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);
+                                DrawSpriteRotatedF(sprFlake, round(Gear^.X) + WorldDx, round(Gear^.Y) + WorldDy + SkyOffset, Gear^.Frame, 1, Gear^.Angle);
                 end;
             if (Gear^.Tint <> $FFFFFFFF) then
                 Tint($FF,$FF,$FF,$FF);
@@ -976,6 +995,7 @@
 procedure initModule;
 var i: LongWord;
 begin
+VGCounter:= 0;
 for i:= 0 to 6 do
     VisualGearLayers[i]:= nil;
 end;
@@ -983,6 +1003,7 @@
 procedure freeModule;
 var i: LongWord;
 begin
+VGCounter:= 0;
 for i:= 0 to 6 do
     while VisualGearLayers[i] <> nil do DeleteVisualGear(VisualGearLayers[i]);
 end;
--- a/hedgewars/uWorld.pas	Sun Apr 01 15:23:34 2012 +0200
+++ b/hedgewars/uWorld.pas	Wed May 02 23:53:45 2012 +0200
@@ -36,6 +36,7 @@
 procedure ShakeCamera(amount: LongInt);
 procedure InitCameraBorders;
 procedure InitTouchInterface;
+procedure SetUtilityWidgetState(ammoType: TAmmoType);
 procedure animateWidget(widget: POnScreenWidget; fade, showWidget: boolean);
 procedure MoveCamera;
 procedure onFocusStateChanged;
@@ -381,6 +382,7 @@
     STurns: LongInt;
     amSurface: PSDL_Surface;
     AMRect: TSDL_Rect;
+    tmpsurf: PSDL_Surface;
 begin
     SlotsNum:= 0;
     for i:= 0 to cMaxSlotIndex do
@@ -389,11 +391,18 @@
 {$IFDEF USE_LANDSCAPE_AMMOMENU}
     SlotsNumX:= SlotsNum;
     SlotsNumY:= cMaxSlotAmmoIndex + 2;
+    {$IFDEF USE_AM_NUMCOLUMN}
+    inc(SlotsNumY);
+    {$ENDIF}
 {$ELSE}
     SlotsNumX:= cMaxSlotAmmoIndex + 1;
     SlotsNumY:= SlotsNum + 1;
+    {$IFDEF USE_AM_NUMCOLUMN}
+    inc(SlotsNumX);
+    {$ENDIF}
 {$ENDIF}
 
+
     AmmoRect.w:= (BORDERSIZE*2) + (SlotsNumX * AMSlotSize) + (SlotsNumX-1);
     AmmoRect.h:= (BORDERSIZE*2) + (SlotsNumY * AMSlotSize) + (SlotsNumY-1);
     amSurface := SDL_CreateRGBSurface(SDL_SWSURFACE, AmmoRect.w, AmmoRect.h, 32, RMask, GMask, BMask, AMask);
@@ -415,6 +424,21 @@
 {$ELSE}
             x:= AMRect.x;
 {$ENDIF}
+{$IFDEF USE_AM_NUMCOLUMN}
+            tmpsurf:= TTF_RenderUTF8_Blended(Fontz[fnt16].Handle, Str2PChar('F' + IntToStr(i+1)), cWhiteColorChannels);
+            copyToXY(tmpsurf, amSurface,
+                     x + AMSlotPadding + (AMSlotSize shr 1) - (tmpsurf^.w shr 1),
+                     y + AMSlotPadding + (AMSlotSize shr 1) - (tmpsurf^.h shr 1));
+
+            SDL_FreeSurface(tmpsurf);
+    {$IFDEF USE_LANDSCAPE_AMMOMENU}
+            y:= AMRect.y + AMSlotSize + 1;
+    {$ELSE}
+            x:= AMRect.x + AMSlotSize + 1;
+    {$ENDIF}
+{$ENDIF}
+
+
             for t:=0 to cMaxSlotAmmoIndex do
                 begin
                 if (Ammo^[i, t].Count > 0)  and (Ammo^[i, t].AmmoType <> amNothing) then
@@ -432,8 +456,8 @@
                         end
                     else //draw colored version
                         begin
-                            DrawSprite2Surf(sprAMAmmos, amSurface, x + AMSlotPadding, 
-       						       y + AMSlotPadding, AMFrame);
+                        DrawSprite2Surf(sprAMAmmos, amSurface, x + AMSlotPadding, 
+                                                               y + AMSlotPadding, AMFrame);
                         end;
 {$IFDEF USE_LANDSCAPE_AMMOMENU}
 	    inc(y, AMSlotSize + 1); //the plus one is for the border
@@ -480,23 +504,22 @@
 begin
 if (TurnTimeLeft = 0) or (not CurrentTeam^.ExtDriven and (((CurAmmoGear = nil)
 or ((Ammoz[CurAmmoGear^.AmmoType].Ammo.Propz and ammoprop_AltAttack) = 0)) and hideAmmoMenu)) then
-bShowAmmoMenu:= false;
-
+    bShowAmmoMenu:= false;
 
 // give the assigned ammo to hedgehog
 Ammo:= nil;
 if (CurrentTeam <> nil) and (CurrentHedgehog <> nil)
 and (not CurrentTeam^.ExtDriven) and (CurrentHedgehog^.BotLevel = 0) then
-Ammo:= CurrentHedgehog^.Ammo
+    Ammo:= CurrentHedgehog^.Ammo
 else if (LocalAmmo <> -1) then
-Ammo:= GetAmmoByNum(LocalAmmo);
+    Ammo:= GetAmmoByNum(LocalAmmo);
 Pos:= -1;
 if Ammo = nil then
-begin
-bShowAmmoMenu:= false;
-AMState:= AMHidden;
-exit
-end;
+    begin
+    bShowAmmoMenu:= false;
+    AMState:= AMHidden;
+    exit
+    end;
 
 //Init the menu 
 if(AmmoMenuInvalidated) then 
@@ -596,13 +619,21 @@
 
 Pos:= -1;
 Slot:= -1;
+{$IFDEF USE_LANDSCAPE_AMMOMENU}
+    {$IFDEF USE_AM_NUMCOLUMN}
+c:= 0;
+    {$ELSE}
 c:= -1;
-{$IFDEF USE_LANDSCAPE_AMMOMENU}
+    {$ENDIF}
     for i:= 0 to cMaxSlotIndex do
         if ((i = 0) and (Ammo^[i, 1].Count > 0)) or ((i <> 0) and (Ammo^[i, 0].Count > 0)) then
             begin
             inc(c);
+    {$IFDEF USE_AM_NUMCOLUMN}
+            g:= 1;
+    {$ELSE}
             g:= 0;
+    {$ENDIF}
             for t:=0 to cMaxSlotAmmoIndex do
                 if (Ammo^[i, t].Count > 0) and (Ammo^[i, t].AmmoType <> amNothing) then
                     begin
@@ -623,11 +654,20 @@
                    end;
             end;
 {$ELSE}
+    {$IFDEF USE_AM_NUMCOLUMN}
+c:= -1;
+    {$ELSE}
+c:= 0;
+    {$ENDIF}
     for i:= 0 to cMaxSlotIndex do
         if ((i = 0) and (Ammo^[i, 1].Count > 0)) or ((i <> 0) and (Ammo^[i, 0].Count > 0)) then
             begin
             inc(c);
+    {$IFDEF USE_AM_NUMCOLUMN}
+            g:= 1;
+    {$ELSE}
             g:= 0;
+    {$ENDIF}
             for t:=0 to cMaxSlotAmmoIndex do
                 if (Ammo^[i, t].Count > 0) and (Ammo^[i, t].AmmoType <> amNothing) then
                     begin
@@ -674,7 +714,7 @@
                 bSelected:= false;
                 FreeWeaponTooltip;
 {$IFDEF USE_TOUCH_INTERFACE}//show the aiming buttons + animation
-                if (Ammo^[Slot, Pos].Propz and ammoprop_NoCrosshair) = 0 then
+                if (Ammo^[Slot, Pos].Propz and ammoprop_NeedUpDown) <> 0 then
                     begin
                     if not(arrowUp.show) then
                         begin
@@ -688,16 +728,8 @@
                         animateWidget(@arrowUp, true, false);
                         animateWidget(@arrowDown, true, false);
                         end;
-                if (Ammo^[Slot, Pos].Propz and ammoprop_Timerable) <> 0 then
-                    begin
-                    if not utilityWidget.show then
-                        animateWidget(@utilityWidget, true, true); 
-                    end
-                else
-                    if utilityWidget.show then
-                        animateWidget(@utilityWidget, true, false); 
+                SetUtilityWidgetState(Ammo^[Slot, Pos].AmmoType);
 {$ENDIF}
-
                 exit
                 end;
             end
@@ -714,7 +746,7 @@
 {$ENDIF}
 
     bSelected:= false;
-{$IFNDEF USE_LANDSCAPE_AMMOMENU}
+{$IFNDEF USE_TOUCH_INTERFACE}
    if (AMShiftX = 0) and (AMShiftY = 0) then
         DrawSprite(sprArrow, CursorPoint.X, cScreenHeight - CursorPoint.Y, (RealTicks shr 6) mod 8);
 {$ENDIF}
@@ -1154,9 +1186,9 @@
 DrawVisualGears(6);
 
 if SuddenDeathDmg then
-    DrawWater(cSDWaterOpacity, 0)
+    DrawWater(SDWaterOpacity, 0)
 else
-    DrawWater(cWaterOpacity, 0);
+    DrawWater(WaterOpacity, 0);
 
     // Waves
 ChangeDepth(RM, cStereo_Water_near);
@@ -1164,19 +1196,19 @@
 
 if (cReducedQuality and rq2DWater) = 0 then
     begin
-    //DrawWater(cWaterOpacity, - offsetY div 40);
+    //DrawWater(WaterOpacity, - offsetY div 40);
     ChangeDepth(RM, cStereo_Water_near);
     DrawWaves(-1, 50 + WorldDx div 6, - cWaveHeight - offsetY div 40, 8);
     if SuddenDeathDmg then
-        DrawWater(cSDWaterOpacity, - offsetY div 20)
+        DrawWater(SDWaterOpacity, - offsetY div 20)
     else
-        DrawWater(cWaterOpacity, - offsetY div 20);
+        DrawWater(WaterOpacity, - offsetY div 20);
     ChangeDepth(RM, cStereo_Water_near);
     DrawWaves( 1, 75 - WorldDx div 4, - cWaveHeight - offsetY div 20, 2);
         if SuddenDeathDmg then
-            DrawWater(cSDWaterOpacity, - offsetY div 10)
+            DrawWater(SDWaterOpacity, - offsetY div 10)
         else
-            DrawWater(cWaterOpacity, - offsetY div 10);
+            DrawWater(WaterOpacity, - offsetY div 10);
         ChangeDepth(RM, cStereo_Water_near);
         DrawWaves( -1, 25 + WorldDx div 3, - cWaveHeight - offsetY div 10, 0);
         end
@@ -1200,9 +1232,9 @@
     with PHedgehog(CurrentHedgehog)^ do
         begin
         if CurAmmoType = amBee then
-            DrawRotatedF(sprTargetBee, TargetPoint.X + WorldDx, TargetPoint.Y + WorldDy, 0, 0, (RealTicks shr 3) mod 360)
+            DrawSpriteRotatedF(sprTargetBee, TargetPoint.X + WorldDx, TargetPoint.Y + WorldDy, 0, 0, (RealTicks shr 3) mod 360)
         else
-            DrawRotatedF(sprTargetP, TargetPoint.X + WorldDx, TargetPoint.Y + WorldDy, 0, 0, (RealTicks shr 3) mod 360)
+            DrawSpriteRotatedF(sprTargetP, TargetPoint.X + WorldDx, TargetPoint.Y + WorldDy, 0, 0, (RealTicks shr 3) mod 360)
         end
     end;
 {$WARNINGS ON}
@@ -1286,13 +1318,13 @@
         r.y:= 0;
         r.w:= 2 + TeamHealthBarWidth;
         r.h:= HealthTex^.h;
-        DrawFromRect(14, cScreenHeight + DrawHealthY + smallScreenOffset, @r, HealthTex);
+        DrawTextureFromRect(14, cScreenHeight + DrawHealthY + smallScreenOffset, @r, HealthTex);
 
         // draw health bars right border
         inc(r.x, cTeamHealthWidth + 2);
         if TeamHealth = 0 then inc(r.x);
         r.w:= 3;
-        DrawFromRect(TeamHealthBarWidth + 16, cScreenHeight + DrawHealthY + smallScreenOffset, @r, HealthTex);
+        DrawTextureFromRect(TeamHealthBarWidth + 16, cScreenHeight + DrawHealthY + smallScreenOffset, @r, HealthTex);
 
         if not highlight and not hasGone and (TeamHealth > 1) then
             for i:= 0 to cMaxHHIndex do
@@ -1321,15 +1353,15 @@
             r.y:= 2;
             r.w:= NameTagTex^.w - 4;
             r.h:= NameTagTex^.h - 4;
-            DrawFromRect(-NameTagTex^.w - 14, cScreenHeight + DrawHealthY + smallScreenOffset + 2, @r, NameTagTex);
+            DrawTextureFromRect(-NameTagTex^.w - 14, cScreenHeight + DrawHealthY + smallScreenOffset + 2, @r, NameTagTex);
             // draw flag
             r.w:= 22;
             r.h:= 15;
-            DrawFromRect(-12, cScreenHeight + DrawHealthY + smallScreenOffset + 2, @r, FlagTex);
+            DrawTextureFromRect(-12, cScreenHeight + DrawHealthY + smallScreenOffset + 2, @r, FlagTex);
             // draw health bar
             r.w:= TeamHealthBarWidth + 1;
             r.h:= HealthTex^.h - 4;
-            DrawFromRect(16, cScreenHeight + DrawHealthY + smallScreenOffset + 2, @r, HealthTex);
+            DrawTextureFromRect(16, cScreenHeight + DrawHealthY + smallScreenOffset + 2, @r, HealthTex);
             end;
         end;
 if smallScreenOffset <> 0 then
@@ -1404,9 +1436,9 @@
 
 // various captions
 if fastUntilLag then
-    DrawCentered(0, (cScreenHeight shr 1), SyncTexture);
+    DrawTextureCentered(0, (cScreenHeight shr 1), SyncTexture);
 if isPaused then
-    DrawCentered(0, (cScreenHeight shr 1), PauseTexture);
+    DrawTextureCentered(0, (cScreenHeight shr 1), PauseTexture);
 if not isFirstFrame and (missionTimer <> 0) or isPaused or fastUntilLag or (GameState = gsConfirm) then
     begin
     if (ReadyTimeLeft = 0) and (missionTimer > 0) then
@@ -1414,7 +1446,7 @@
     if missionTimer < 0 then
         missionTimer:= 0; // avoid subtracting below 0
     if missionTex <> nil then
-        DrawCentered(0, Min((cScreenHeight shr 1) + 100, cScreenHeight - 48 - missionTex^.h), missionTex);
+        DrawTextureCentered(0, Min((cScreenHeight shr 1) + 100, cScreenHeight - 48 - missionTex^.h), missionTex);
     end;
 
 // fps
@@ -1491,7 +1523,7 @@
    end;
 
 if GameState = gsConfirm then
-    DrawCentered(0, (cScreenHeight shr 1), ConfirmTexture);
+    DrawTextureCentered(0, (cScreenHeight shr 1), ConfirmTexture);
 
 if ScreenFade <> sfNone then
     begin
@@ -1546,7 +1578,7 @@
                 begin
             if (CurAmmoType = amNapalm) or (CurAmmoType = amMineStrike) then
                 DrawLine(-3000, topY-300, 7000, topY-300, 3.0, (Team^.Clan^.Color shr 16), (Team^.Clan^.Color shr 8) and $FF, Team^.Clan^.Color and $FF, $FF);
-            i:= GetAmmoEntry(CurrentHedgehog^)^.Pos;
+            i:= GetCurAmmoEntry(CurrentHedgehog^)^.Pos;
             with Ammoz[CurAmmoType] do
                 if PosCount > 1 then
                     DrawSprite(PosSprite, CursorPoint.X - (SpritesData[PosSprite].Width shr 1), cScreenHeight - CursorPoint.Y - (SpritesData[PosSprite].Height shr 1),i);
@@ -1712,6 +1744,38 @@
 begin
 if (not cHasFocus) and (GameState <> gsConfirm) then
     ParseCommand('quit', true);
+
+if not cHasFocus then DampenAudio()
+else UndampenAudio();
+end;
+
+procedure SetUtilityWidgetState(ammoType: TAmmoType);
+begin
+{$IFDEF TOUCH_INTERFACE}
+if(ammoType = amNothing)then
+    ammoType:= CurrentHedgehog^.CurAmmoType;
+
+if(CurrentHedgehog <> nil)then
+    if (Ammoz[ammoType].Ammo.Propz and ammoprop_Timerable) <> 0 then
+        begin
+        utilityWidget.sprite:= sprTimerButton;
+        animateWidget(@utilityWidget, true, true);
+        end 
+    else if (Ammoz[ammoType].Ammo.Propz and ammoprop_NeedTarget) <> 0 then
+        begin
+        utilityWidget.sprite:= sprTargetButton;
+        animateWidget(@utilityWidget, true, true);
+        end
+    else if ammoType = amSwitch then
+        begin
+        utilityWidget.sprite:= sprTargetButton;
+        animateWidget(@utilityWidget, true, true);
+        end
+    else if utilityWidget.show then
+        animateWidget(@utilityWidget, true, false);
+{$ELSE}
+ammoType:= ammoType; // avoid hint
+{$ENDIF}
 end;
 
 procedure animateWidget(widget: POnScreenWidget; fade, showWidget: boolean);
--- a/misc/hats_js_anim.xhtml	Sun Apr 01 15:23:34 2012 +0200
+++ b/misc/hats_js_anim.xhtml	Wed May 02 23:53:45 2012 +0200
@@ -47,6 +47,7 @@
 /*var masks = ['2001suit2', '2001suit', '4gsuif', 'AkuAku', 'android', 'angel', 'anzac', 'apple', 'ash', 'Balrog', 'banana', 'Bandit', 'bat', 'beaver', 'beefeater', 'Blanka', 'BlankaToothless', 'BlueCap', 'BlueHair', 'bobby2v', 'bobby', 'Bob', 'BrainSlugMouth', 'BrainSlug', 'britishpithhelmet', 'britmedic', 'britsapper', 'Bub', 'Bunny', 'bushhider', 'charlesdegaulle', 'charmander', 'chef', 'chikorita', 'Chunli', 'clown-copper', 'clown-crossed', 'clown', 'Coonskin3', 'Cororon', 'Cowboy', 'crown', 'cyborg', 'darthvader', 'Deer', 'desertgrenadier01', 'desertgrenadier02', 'desertgrenadier04', 'desertgrenadier05', 'desertgrenadierofficer', 'desertmedic', 'desertsapper1', 'desertsapper2', 'diglett', 'Disguise', 'Dragon', 'dwarf', 'eastertop', 'Elvis', 'Eva_00b', 'Eva_00y', 'Falcon', 'frenchwwigasmask', 'frenchwwihelmet', 'Gasmask', 'Geordi', 'germanwiimedichelmet', 'germanwwihelmetmustache', 'germanwwiipithhelmetdes', 'germanwwitankhelmet', 'Glasses', 'GreenCap', 'GreenHair', 'grenadier1', 'GreyHair', 'Guile', 'hedgehogk', 'HogInTheHat', 'hogpharoah', 'Honda', 'IndianChief', 'infernalhorns', 'InfernalHorns', 'Jason', 'jigglypuff', 'judo', 'junior', 'Ken', 'KirbyMask', 'kiss_criss', 'kiss_frehley', 'kiss_simmons', 'kiss_stanley', 'knight', 'Kululun', 'Ladle', 'lambda', 'Laminaria', 'laurel', 'lemon', 'link', 'lugia', 'Luigi', 'Mario', 'MegaHogX', 'metalband', 'mexicansunbrero', 'mickey_ears', 'Moose', 'mp3', 'mudkip', 'Mummy', 'naruto', 'NinjaFull', 'NinjaStraight', 'NinjaTriangle', 'OldMan', 'OrangeHair', 'orange', 'Pantsu', 'Pig', 'pikachu', 'PinkHair', 'pinksunhat', 'pirate_jack_bandana', 'pirate_jack', 'plainpith', 'Plunger', 'policecap', 'porkey', 'PrincessDaisy', 'PrincessPeach', 'Pumpkin_Hat', 'PurpleHair', 'quotecap', 'Rain', 'Rambo', 'rasta', 'RedCap', 'RedHair', 'RobinHood', 'royalguard', 'RSR', 'Ryu', 'Samurai', 'Samus', 'Santa', 'SauceBoatSilver', 'ShaggyYeti', 'sheep', 'ShortHair_Black', 'ShortHair_Brown', 'ShortHair_Grey', 'ShortHair_Red', 'ShortHair_Yellow', 'Skull', 'Sleepwalker', 'slowpoke', 'Sniper', 'Sonic', 'sovietcomrade2', 'sovietcomrade', 'SparkleSuperFun', 'SparkssHelmet', 'spartan', 'spcartman', 'spidey', 'spkenny', 'spkyle', 'spstan', 'squirtle', 'sth_AmyClassic', 'sth_Amy', 'sth_Eggman', 'sth_Knux', 'sth_Metal', 'sth_Shadow', 'sth_Sonic', 'sth_Super', 'sth_Tails', 'stormcloud', 'stormtrooper', 'StrawHatEyes', 'StrawHatFacial', 'StrawHat', 'Sunglasses', 'SunWukong', 'Teacup', 'Teapot', 'terminatorc', 'Terminator_Glasses', 'thug', 'Toad', 'tophats', 'touhou_chen', 'touhou_marisa', 'touhou_patchouli', 'touhou_remelia', 'touhou_suwako', 'touhou_yukari', 'trenchgrenadier1', 'trenchgrenadier2', 'trenchgrenadier3', 'ushanka', 'vampirichog', 'Vega', 'venom', 'Viking', 'voltorb', 'Wario', 'WhySoSerious', 'WizardHat', 'YellowCap', 'YellowHair', 'Zombi'];*/
 var masks = [];
 var themes = {
+"Cave":1,
 "Golf":1,
 "Stage":1,
 "Island":0,
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/project_files/Android-build/SDL-android-project/jni/SDL/src/video/android/SDL_androidkeyboard.c	Wed May 02 23:53:45 2012 +0200
@@ -0,0 +1,185 @@
+/*
+  Simple DirectMedia Layer
+  Copyright (C) 1997-2012 Sam Lantinga <slouken@libsdl.org>
+
+  This software is provided 'as-is', without any express or implied
+  warranty.  In no event will the authors be held liable for any damages
+  arising from the use of this software.
+
+  Permission is granted to anyone to use this software for any purpose,
+  including commercial applications, and to alter it and redistribute it
+  freely, subject to the following restrictions:
+
+  1. The origin of this software must not be misrepresented; you must not
+     claim that you wrote the original software. If you use this software
+     in a product, an acknowledgment in the product documentation would be
+     appreciated but is not required.
+  2. Altered source versions must be plainly marked as such, and must not be
+     misrepresented as being the original software.
+  3. This notice may not be removed or altered from any source distribution.
+*/
+#include "SDL_config.h"
+
+#if SDL_VIDEO_DRIVER_ANDROID
+
+#include <android/log.h>
+
+#include "../../events/SDL_events_c.h"
+
+#include "SDL_androidkeyboard.h"
+#include "SDL_keycode.h"
+
+
+void Android_InitKeyboard()
+{
+    SDL_Keycode keymap[SDL_NUM_SCANCODES];
+
+    /* Add default scancode to key mapping */
+    SDL_GetDefaultKeymap(keymap);
+    SDL_SetKeymap(0, keymap, SDL_NUM_SCANCODES);
+}
+
+static SDL_Scancode Android_Keycodes[] = {
+    SDL_SCANCODE_UNKNOWN, /* AKEYCODE_UNKNOWN */
+    SDL_SCANCODE_UNKNOWN, /* AKEYCODE_SOFT_LEFT */
+    SDL_SCANCODE_UNKNOWN, /* AKEYCODE_SOFT_RIGHT */
+    SDL_SCANCODE_AC_HOME, /* AKEYCODE_HOME */
+    SDL_SCANCODE_AC_BACK, /* AKEYCODE_BACK */
+    SDL_SCANCODE_UNKNOWN, /* AKEYCODE_CALL */
+    SDL_SCANCODE_UNKNOWN, /* AKEYCODE_ENDCALL */
+    SDL_SCANCODE_0, /* AKEYCODE_0 */
+    SDL_SCANCODE_1, /* AKEYCODE_1 */
+    SDL_SCANCODE_2, /* AKEYCODE_2 */
+    SDL_SCANCODE_3, /* AKEYCODE_3 */
+    SDL_SCANCODE_4, /* AKEYCODE_4 */
+    SDL_SCANCODE_5, /* AKEYCODE_5 */
+    SDL_SCANCODE_6, /* AKEYCODE_6 */
+    SDL_SCANCODE_7, /* AKEYCODE_7 */
+    SDL_SCANCODE_8, /* AKEYCODE_8 */
+    SDL_SCANCODE_9, /* AKEYCODE_9 */
+    SDL_SCANCODE_UNKNOWN, /* AKEYCODE_STAR */
+    SDL_SCANCODE_UNKNOWN, /* AKEYCODE_POUND */
+    SDL_SCANCODE_UP, /* AKEYCODE_DPAD_UP */
+    SDL_SCANCODE_DOWN, /* AKEYCODE_DPAD_DOWN */
+    SDL_SCANCODE_LEFT, /* AKEYCODE_DPAD_LEFT */
+    SDL_SCANCODE_RIGHT, /* AKEYCODE_DPAD_RIGHT */
+    SDL_SCANCODE_SELECT, /* AKEYCODE_DPAD_CENTER */
+    SDL_SCANCODE_VOLUMEUP, /* AKEYCODE_VOLUME_UP */
+    SDL_SCANCODE_VOLUMEDOWN, /* AKEYCODE_VOLUME_DOWN */
+    SDL_SCANCODE_POWER, /* AKEYCODE_POWER */
+    SDL_SCANCODE_UNKNOWN, /* AKEYCODE_CAMERA */
+    SDL_SCANCODE_CLEAR, /* AKEYCODE_CLEAR */
+    SDL_SCANCODE_A, /* AKEYCODE_A */
+    SDL_SCANCODE_B, /* AKEYCODE_B */
+    SDL_SCANCODE_C, /* AKEYCODE_C */
+    SDL_SCANCODE_D, /* AKEYCODE_D */
+    SDL_SCANCODE_E, /* AKEYCODE_E */
+    SDL_SCANCODE_F, /* AKEYCODE_F */
+    SDL_SCANCODE_G, /* AKEYCODE_G */
+    SDL_SCANCODE_H, /* AKEYCODE_H */
+    SDL_SCANCODE_I, /* AKEYCODE_I */
+    SDL_SCANCODE_J, /* AKEYCODE_J */
+    SDL_SCANCODE_K, /* AKEYCODE_K */
+    SDL_SCANCODE_L, /* AKEYCODE_L */
+    SDL_SCANCODE_M, /* AKEYCODE_M */
+    SDL_SCANCODE_N, /* AKEYCODE_N */
+    SDL_SCANCODE_O, /* AKEYCODE_O */
+    SDL_SCANCODE_P, /* AKEYCODE_P */
+    SDL_SCANCODE_Q, /* AKEYCODE_Q */
+    SDL_SCANCODE_R, /* AKEYCODE_R */
+    SDL_SCANCODE_S, /* AKEYCODE_S */
+    SDL_SCANCODE_T, /* AKEYCODE_T */
+    SDL_SCANCODE_U, /* AKEYCODE_U */
+    SDL_SCANCODE_V, /* AKEYCODE_V */
+    SDL_SCANCODE_W, /* AKEYCODE_W */
+    SDL_SCANCODE_X, /* AKEYCODE_X */
+    SDL_SCANCODE_Y, /* AKEYCODE_Y */
+    SDL_SCANCODE_Z, /* AKEYCODE_Z */
+    SDL_SCANCODE_COMMA, /* AKEYCODE_COMMA */
+    SDL_SCANCODE_PERIOD, /* AKEYCODE_PERIOD */
+    SDL_SCANCODE_LALT, /* AKEYCODE_ALT_LEFT */
+    SDL_SCANCODE_RALT, /* AKEYCODE_ALT_RIGHT */
+    SDL_SCANCODE_LSHIFT, /* AKEYCODE_SHIFT_LEFT */
+    SDL_SCANCODE_RSHIFT, /* AKEYCODE_SHIFT_RIGHT */
+    SDL_SCANCODE_TAB, /* AKEYCODE_TAB */
+    SDL_SCANCODE_SPACE, /* AKEYCODE_SPACE */
+    SDL_SCANCODE_UNKNOWN, /* AKEYCODE_SYM */
+    SDL_SCANCODE_UNKNOWN, /* AKEYCODE_EXPLORER */
+    SDL_SCANCODE_UNKNOWN, /* AKEYCODE_ENVELOPE */
+    SDL_SCANCODE_RETURN, /* AKEYCODE_ENTER */
+    SDL_SCANCODE_BACKSPACE, /* AKEYCODE_DEL */
+    SDL_SCANCODE_GRAVE, /* AKEYCODE_GRAVE */
+    SDL_SCANCODE_MINUS, /* AKEYCODE_MINUS */
+    SDL_SCANCODE_EQUALS, /* AKEYCODE_EQUALS */
+    SDL_SCANCODE_LEFTBRACKET, /* AKEYCODE_LEFT_BRACKET */
+    SDL_SCANCODE_RIGHTBRACKET, /* AKEYCODE_RIGHT_BRACKET */
+    SDL_SCANCODE_BACKSLASH, /* AKEYCODE_BACKSLASH */
+    SDL_SCANCODE_SEMICOLON, /* AKEYCODE_SEMICOLON */
+    SDL_SCANCODE_APOSTROPHE, /* AKEYCODE_APOSTROPHE */
+    SDL_SCANCODE_UNKNOWN, /* AKEYCODE_SLASH */
+    SDL_SCANCODE_UNKNOWN, /* AKEYCODE_AT */
+    SDL_SCANCODE_UNKNOWN, /* AKEYCODE_NUM */
+    SDL_SCANCODE_UNKNOWN, /* AKEYCODE_HEADSETHOOK */
+    SDL_SCANCODE_UNKNOWN, /* AKEYCODE_FOCUS */
+    SDL_SCANCODE_UNKNOWN, /* AKEYCODE_PLUS */
+    SDL_SCANCODE_MENU, /* AKEYCODE_MENU */
+    SDL_SCANCODE_UNKNOWN, /* AKEYCODE_NOTIFICATION */
+    SDL_SCANCODE_AC_SEARCH, /* AKEYCODE_SEARCH */
+    SDL_SCANCODE_AUDIOPLAY, /* AKEYCODE_MEDIA_PLAY_PAUSE */
+    SDL_SCANCODE_AUDIOSTOP, /* AKEYCODE_MEDIA_STOP */
+    SDL_SCANCODE_AUDIONEXT, /* AKEYCODE_MEDIA_NEXT */
+    SDL_SCANCODE_AUDIOPREV, /* AKEYCODE_MEDIA_PREVIOUS */
+    SDL_SCANCODE_UNKNOWN, /* AKEYCODE_MEDIA_REWIND */
+    SDL_SCANCODE_UNKNOWN, /* AKEYCODE_MEDIA_FAST_FORWARD */
+    SDL_SCANCODE_MUTE, /* AKEYCODE_MUTE */
+    SDL_SCANCODE_PAGEUP, /* AKEYCODE_PAGE_UP */
+    SDL_SCANCODE_PAGEDOWN, /* AKEYCODE_PAGE_DOWN */
+    SDL_SCANCODE_UNKNOWN, /* AKEYCODE_PICTSYMBOLS */
+    SDL_SCANCODE_UNKNOWN, /* AKEYCODE_SWITCH_CHARSET */
+    SDL_SCANCODE_UNKNOWN, /* AKEYCODE_BUTTON_A */
+    SDL_SCANCODE_UNKNOWN, /* AKEYCODE_BUTTON_B */
+    SDL_SCANCODE_UNKNOWN, /* AKEYCODE_BUTTON_C */
+    SDL_SCANCODE_UNKNOWN, /* AKEYCODE_BUTTON_X */
+    SDL_SCANCODE_UNKNOWN, /* AKEYCODE_BUTTON_Y */
+    SDL_SCANCODE_UNKNOWN, /* AKEYCODE_BUTTON_Z */
+    SDL_SCANCODE_UNKNOWN, /* AKEYCODE_BUTTON_L1 */
+    SDL_SCANCODE_UNKNOWN, /* AKEYCODE_BUTTON_R1 */
+    SDL_SCANCODE_UNKNOWN, /* AKEYCODE_BUTTON_L2 */
+    SDL_SCANCODE_UNKNOWN, /* AKEYCODE_BUTTON_R2 */
+    SDL_SCANCODE_UNKNOWN, /* AKEYCODE_BUTTON_THUMBL */
+    SDL_SCANCODE_UNKNOWN, /* AKEYCODE_BUTTON_THUMBR */
+    SDL_SCANCODE_UNKNOWN, /* AKEYCODE_BUTTON_START */
+    SDL_SCANCODE_UNKNOWN, /* AKEYCODE_BUTTON_SELECT */
+    SDL_SCANCODE_UNKNOWN, /* AKEYCODE_BUTTON_MODE */
+};
+
+static SDL_Scancode
+TranslateKeycode(int keycode)
+{
+    SDL_Scancode scancode = SDL_SCANCODE_UNKNOWN;
+
+    if (keycode < SDL_arraysize(Android_Keycodes)) {
+        scancode = Android_Keycodes[keycode];
+    }
+    if (scancode == SDL_SCANCODE_UNKNOWN) {
+        __android_log_print(ANDROID_LOG_INFO, "SDL", "Unknown keycode %d", keycode);
+    }
+    __android_log_print(ANDROID_LOG_INFO, "SDLXELI", "keycode %d scancode %d", keycode, scancode);
+    return scancode;
+}
+
+int
+Android_OnKeyDown(int keycode)
+{
+    return SDL_SendKeyboardKey(SDL_PRESSED, TranslateKeycode(keycode));
+}
+
+int
+Android_OnKeyUp(int keycode)
+{
+    return SDL_SendKeyboardKey(SDL_RELEASED, TranslateKeycode(keycode));
+}
+
+#endif /* SDL_VIDEO_DRIVER_ANDROID */
+
+/* vi: set ts=4 sw=4 expandtab: */
--- a/project_files/Android-build/SDL-android-project/src/org/hedgewars/hedgeroid/SDLActivity.java	Sun Apr 01 15:23:34 2012 +0200
+++ b/project_files/Android-build/SDL-android-project/src/org/hedgewars/hedgeroid/SDLActivity.java	Wed May 02 23:53:45 2012 +0200
@@ -100,11 +100,6 @@
 		super.onResume();
 	}
 
-	public void onBackPressed(){
-		super.onBackPressed();
-		PascalExports.HWterminate(true);
-	}
-
 	protected void onDestroy() {
 		super.onDestroy();
 		Log.v("SDL", "onDestroy()");
@@ -441,7 +436,7 @@
 		} catch (InterruptedException e) {
 			e.printStackTrace();
 		}
-		//Log.v("SDL", "SDL thread terminated");
+		Log.v("SDL", "SDL thread terminated");
 		//Log.v("SDL", "SDL thread terminated");
 	}
 }
@@ -481,14 +476,14 @@
 		Log.v("SDL", "surfaceCreated()");
 		holder.setType(SurfaceHolder.SURFACE_TYPE_GPU);
 		SDLActivity.createEGLSurface();
-//		enableSensor(Sensor.TYPE_ACCELEROMETER, true);
+		//		enableSensor(Sensor.TYPE_ACCELEROMETER, true);
 	}
 
 	// Called when we lose the surface
 	public void surfaceDestroyed(SurfaceHolder holder) {
 		Log.v("SDL", "surfaceDestroyed()");
 		SDLActivity.nativePause();
-//		enableSensor(Sensor.TYPE_ACCELEROMETER, false);
+		//		enableSensor(Sensor.TYPE_ACCELEROMETER, false);
 	}
 
 	// Called when the surface is resized
@@ -554,7 +549,15 @@
 
 	// Key events
 	public boolean onKey(View  v, int keyCode, KeyEvent event) {
-		if(keyCode == KeyEvent.KEYCODE_BACK) return false;
+		switch(keyCode){
+		case KeyEvent.KEYCODE_BACK:
+		        PascalExports.HWterminate(true);
+                        return true;
+		case KeyEvent.KEYCODE_VOLUME_DOWN:
+		case KeyEvent.KEYCODE_VOLUME_UP:
+		case KeyEvent.KEYCODE_VOLUME_MUTE:
+			return false;
+		}
 		if (event.getAction() == KeyEvent.ACTION_DOWN) {
 			//Log.v("SDL", "key down: " + keyCode);
 			SDLActivity.onNativeKeyDown(keyCode);
--- a/project_files/HedgewarsMobile/Classes/AboutViewController.m	Sun Apr 01 15:23:34 2012 +0200
+++ b/project_files/HedgewarsMobile/Classes/AboutViewController.m	Wed May 02 23:53:45 2012 +0200
@@ -52,12 +52,12 @@
 }
 
 -(IBAction) buttonPressed:(id) sender {
-    [AudioManagerController playBackSound];
+    [[AudioManagerController mainManager] playBackSound];
     [[self parentViewController] dismissModalViewControllerAnimated:YES];
 }
 
 -(IBAction) segmentedControlChanged:(id) sender {
-    [AudioManagerController playClickSound];
+    [[AudioManagerController mainManager] playClickSound];
     [self.tableView setContentOffset:CGPointMake(0, 0) animated:NO];
     [self.tableView reloadData];
 }
--- a/project_files/HedgewarsMobile/Classes/AudioManagerController.h	Sun Apr 01 15:23:34 2012 +0200
+++ b/project_files/HedgewarsMobile/Classes/AudioManagerController.h	Wed May 02 23:53:45 2012 +0200
@@ -18,23 +18,41 @@
 
 
 #import <Foundation/Foundation.h>
+#import <AudioToolbox/AudioToolbox.h>
 
 
+@class AVAudioPlayer;
+
 @interface AudioManagerController : NSObject {
+    @private
+    AVAudioPlayer *backgroundMusic;
+    SystemSoundID clickSound;
+    SystemSoundID backSound;
+    SystemSoundID selSound;
 
+    NSOperationQueue *audioFaderQueue;
 }
 
-+(void) playBackgroundMusic;
-+(void) pauseBackgroundMusic;
-+(void) stopBackgroundMusic;
+@property (nonatomic,retain) AVAudioPlayer *backgroundMusic;
+@property (assign) SystemSoundID clickSound;
+@property (assign) SystemSoundID backSound;
+@property (assign) SystemSoundID selSound;
+
+@property (nonatomic,retain) NSOperationQueue *audioFaderQueue;
+
++(id) mainManager;
 
-+(void) fadeInBackgroundMusic;
-+(void) fadeOutBackgroundMusic;
+-(void) playBackgroundMusic;
+-(void) pauseBackgroundMusic;
+-(void) stopBackgroundMusic;
 
-+(void) playClickSound;
-+(void) playBackSound;
-+(void) playSelectSound;
+-(void) fadeInBackgroundMusic;
+-(void) fadeOutBackgroundMusic;
 
-+(void) releaseCache;
+-(void) playClickSound;
+-(void) playBackSound;
+-(void) playSelectSound;
+-(SystemSoundID) loadSound:(NSString *)snd;
+-(void) unloadSounds;
 
 @end
--- a/project_files/HedgewarsMobile/Classes/AudioManagerController.m	Sun Apr 01 15:23:34 2012 +0200
+++ b/project_files/HedgewarsMobile/Classes/AudioManagerController.m	Wed May 02 23:53:45 2012 +0200
@@ -19,88 +19,115 @@
 
 #import "AudioManagerController.h"
 #import "AVFoundation/AVAudioPlayer.h"
-#import <AudioToolbox/AudioToolbox.h>
 #import "MXAudioPlayerFadeOperation.h"
 
 
-static AVAudioPlayer *backgroundMusic = nil;
-static SystemSoundID clickSound = -1;
-static SystemSoundID backSound = -1;
-static SystemSoundID selSound = -1;
+#define DEFAULT_VOLUME    0.45f
+#define FADEOUT_DURATION  3.0f
+#define FADEIN_DURATION   2.0f
 
-static NSOperationQueue *audioFaderQueue = nil;
-static MXAudioPlayerFadeOperation *fadeIn = nil;
-static MXAudioPlayerFadeOperation *fadeOut = nil;
+static AudioManagerController *mainInstance;
 
 @implementation AudioManagerController
+@synthesize backgroundMusic, clickSound, backSound, selSound, audioFaderQueue;
+
++(id) mainManager {
+    if (mainInstance == nil)
+        mainInstance = [[self alloc] init];
+    return mainInstance;
+}
+
+-(id) init {
+    if ((self = [super init])) {
+        self.backgroundMusic = nil;
+        self.clickSound = -1;
+        self.backSound = -1;
+        self.selSound = -1;
+
+        self.audioFaderQueue = nil;
+    }
+    return self;
+}
+
+-(void) dealloc {
+    [self unloadSounds];
+    releaseAndNil(backgroundMusic);
+    releaseAndNil(audioFaderQueue);
+    mainInstance = nil;
+    [super dealloc];
+}
+
+-(void) didReceiveMemoryWarning {
+    if (self.backgroundMusic.playing == NO)
+        self.backgroundMusic = nil;
+    if ([self.audioFaderQueue operationCount] == 0)
+        self.audioFaderQueue = nil;
+
+    [self unloadSounds];
+    MSG_MEMCLEAN();
+}
 
 #pragma mark -
 #pragma mark background music control
-+(void) loadBackgroundMusic {
-    NSString *musicString = [[NSBundle mainBundle] pathForResource:@"hwclassic" ofType:@"mp3"];
-    backgroundMusic = [[AVAudioPlayer alloc] initWithContentsOfURL:[NSURL fileURLWithPath:musicString] error:nil];
-
-    backgroundMusic.delegate = nil;
-    backgroundMusic.volume = 0;
-    backgroundMusic.numberOfLoops = -1;
-    [backgroundMusic prepareToPlay];
-}
-
-+(void) playBackgroundMusic {
+-(void) playBackgroundMusic {
     if ([[[NSUserDefaults standardUserDefaults] objectForKey:@"music"] boolValue] == NO)
         return;
 
-    if (backgroundMusic == nil)
-        [AudioManagerController loadBackgroundMusic];
-
-    backgroundMusic.volume = 0.45f;
-    [backgroundMusic play];
+    if (self.backgroundMusic == nil) {
+        NSString *musicString = [[NSBundle mainBundle] pathForResource:@"hwclassic" ofType:@"mp3"];
+        self.backgroundMusic = [[AVAudioPlayer alloc] initWithContentsOfURL:[NSURL fileURLWithPath:musicString] error:nil];
+        self.backgroundMusic.delegate = nil;
+        self.backgroundMusic.numberOfLoops = -1;
+    }
+    
+    self.backgroundMusic.volume = DEFAULT_VOLUME;
+    [self.backgroundMusic play];
 }
 
-+(void) pauseBackgroundMusic {
-    [backgroundMusic pause];
+-(void) pauseBackgroundMusic {
+    [self.backgroundMusic pause];
 }
 
-+(void) stopBackgroundMusic {
-    [backgroundMusic stop];
+-(void) stopBackgroundMusic {
+    [self.backgroundMusic stop];
 }
 
-+(void) fadeOutBackgroundMusic {
+-(void) fadeOutBackgroundMusic {
     if ([[[NSUserDefaults standardUserDefaults] objectForKey:@"music"] boolValue] == NO)
         return;
 
-    if (audioFaderQueue == nil)
-        audioFaderQueue = [[NSOperationQueue alloc] init];
-    if (backgroundMusic == nil)
-        [AudioManagerController loadBackgroundMusic];
-    if (fadeOut == nil)
-        fadeOut = [[MXAudioPlayerFadeOperation alloc] initFadeWithAudioPlayer:backgroundMusic toVolume:0.0 overDuration:3.0];
-
-    [audioFaderQueue addOperation:fadeOut];
+    if (self.audioFaderQueue == nil)
+        self.audioFaderQueue = [[NSOperationQueue alloc] init];
+    
+    MXAudioPlayerFadeOperation *fadeOut = [[MXAudioPlayerFadeOperation alloc] initFadeWithAudioPlayer:self.backgroundMusic
+                                                                                             toVolume:0.0
+                                                                                         overDuration:FADEOUT_DURATION];
+    [self.audioFaderQueue addOperation:fadeOut];
+    [fadeOut release];
 }
 
-+(void) fadeInBackgroundMusic {
+-(void) fadeInBackgroundMusic {
     if ([[[NSUserDefaults standardUserDefaults] objectForKey:@"music"] boolValue] == NO)
         return;
 
-    if (audioFaderQueue == nil)
-        audioFaderQueue = [[NSOperationQueue alloc] init];
-    if (backgroundMusic == nil)
-        [AudioManagerController loadBackgroundMusic];
-    if (fadeIn == nil)
-        fadeIn = [[MXAudioPlayerFadeOperation alloc] initFadeWithAudioPlayer:backgroundMusic toVolume:0.45 overDuration:2.0];
+    if (self.audioFaderQueue == nil)
+        self.audioFaderQueue = [[NSOperationQueue alloc] init];
 
+    [self playBackgroundMusic];
+    MXAudioPlayerFadeOperation *fadeIn = [[MXAudioPlayerFadeOperation alloc] initFadeWithAudioPlayer:self.backgroundMusic
+                                                                                            toVolume:DEFAULT_VOLUME
+                                                                                        overDuration:FADEIN_DURATION];
     [audioFaderQueue addOperation:fadeIn];
+    [fadeIn release];
 }
 
 #pragma mark -
 #pragma mark sound effects control
-+(SystemSoundID) loadSound:(NSString *)snd {
-    // get the filename of the sound file:
-    NSString *path = [NSString stringWithFormat:@"%@/%@",[[NSBundle mainBundle] resourcePath],snd];
+-(SystemSoundID) loadSound:(NSString *)snd {
+    SystemSoundID soundID;
 
-    // declare a system sound id and get a URL for the sound file
-    SystemSoundID soundID;
+    // get the filename of the sound file in a NSURL format
+    NSString *path = [[NSBundle mainBundle] pathForResource:snd ofType:@"caf"];
     NSURL *filePath = [NSURL fileURLWithPath:path isDirectory:NO];
 
     // use audio sevices to create and play the sound
@@ -108,48 +135,40 @@
     return soundID;
 }
 
-+(void) playClickSound {
-    if ([[[NSUserDefaults standardUserDefaults] objectForKey:@"sound"] boolValue] == NO)
-        return;
-    
-    if (clickSound == -1)
-        clickSound = [AudioManagerController loadSound:@"clickSound.wav"];
-    
-    AudioServicesPlaySystemSound(clickSound);
+-(void) unloadSounds {
+    AudioServicesDisposeSystemSoundID(clickSound), clickSound = -1;
+    AudioServicesDisposeSystemSoundID(backSound), backSound = -1;
+    AudioServicesDisposeSystemSoundID(selSound), selSound = -1;
 }
 
-+(void) playBackSound {
+-(void) playClickSound {
     if ([[[NSUserDefaults standardUserDefaults] objectForKey:@"sound"] boolValue] == NO)
         return;
     
-    if (backSound == -1)
-        backSound = [AudioManagerController loadSound:@"backSound.wav"];
+    if (self.clickSound == -1)
+        self.clickSound = [self loadSound:@"clickSound"];
     
-    AudioServicesPlaySystemSound(backSound);
+    AudioServicesPlaySystemSound(self.clickSound);
 }
 
-+(void) playSelectSound {
+-(void) playBackSound {
     if ([[[NSUserDefaults standardUserDefaults] objectForKey:@"sound"] boolValue] == NO)
         return;
     
-    if (selSound == -1)
-        selSound = [AudioManagerController loadSound:@"selSound.wav"];
+    if (self.backSound == -1)
+        self.backSound = [self loadSound:@"backSound"];
     
-    AudioServicesPlaySystemSound(selSound);
+    AudioServicesPlaySystemSound(self.backSound);
 }
 
-#pragma mark -
-#pragma mark memory management
-+(void) releaseCache {
-    [backgroundMusic stop];
-    [backgroundMusic release], backgroundMusic = nil;
-    [fadeOut release], fadeOut = nil;
-    [fadeIn release], fadeIn = nil;
-    [audioFaderQueue release], audioFaderQueue = nil;
-    AudioServicesDisposeSystemSoundID(clickSound), clickSound = -1;
-    AudioServicesDisposeSystemSoundID(backSound), backSound = -1;
-    AudioServicesDisposeSystemSoundID(selSound), selSound = -1;
-    MSG_MEMCLEAN();
+-(void) playSelectSound {
+    if ([[[NSUserDefaults standardUserDefaults] objectForKey:@"sound"] boolValue] == NO)
+        return;
+    
+    if (self.selSound == -1)
+        self.selSound = [self loadSound:@"selSound"];
+    
+    AudioServicesPlaySystemSound(self.selSound);
 }
 
 @end
--- a/project_files/HedgewarsMobile/Classes/CGPointUtils.h	Sun Apr 01 15:23:34 2012 +0200
+++ b/project_files/HedgewarsMobile/Classes/CGPointUtils.h	Wed May 02 23:53:45 2012 +0200
@@ -17,7 +17,7 @@
  */
 
 
-#import <CoreGraphics/CoreGraphics.h>
+#include <CoreGraphics/CoreGraphics.h>
 
 
 #define degreesToRadians(x) ( M_PI * x / 180.0)
--- a/project_files/HedgewarsMobile/Classes/CreationChamber.h	Sun Apr 01 15:23:34 2012 +0200
+++ b/project_files/HedgewarsMobile/Classes/CreationChamber.h	Wed May 02 23:53:45 2012 +0200
@@ -24,6 +24,7 @@
 
 }
 
++(void) createFirstLaunch;
 +(void) createSettings;
 
 +(void) createTeamNamed:(NSString *)nameWithoutExt;
--- a/project_files/HedgewarsMobile/Classes/CreationChamber.m	Sun Apr 01 15:23:34 2012 +0200
+++ b/project_files/HedgewarsMobile/Classes/CreationChamber.m	Wed May 02 23:53:45 2012 +0200
@@ -22,6 +22,56 @@
 
 @implementation CreationChamber
 
+#pragma mark Checking status
++(void) createFirstLaunch {
+    DLog(@"Creating necessary files");
+    NSInteger index;
+
+    // SAVES - just delete and overwrite
+    if ([[NSFileManager defaultManager] fileExistsAtPath:SAVES_DIRECTORY()])
+        [[NSFileManager defaultManager] removeItemAtPath:SAVES_DIRECTORY() error:NULL];
+    [[NSFileManager defaultManager] createDirectoryAtPath:SAVES_DIRECTORY()
+                              withIntermediateDirectories:NO
+                                               attributes:nil
+                                                    error:NULL];
+
+    // SCREENSHOTS - just create it the first time
+    if ([[NSFileManager defaultManager] fileExistsAtPath:SCREENSHOTS_DIRECTORY()] == NO)
+        [[NSFileManager defaultManager] createDirectoryAtPath:SCREENSHOTS_DIRECTORY()
+                                  withIntermediateDirectories:NO
+                                                   attributes:nil
+                                                        error:NULL];
+
+    // SETTINGS - nsuserdefaults ftw
+    [self createSettings];
+
+    // TEAMS - update exisiting teams with new format
+    NSArray *teamNames = [[NSArray alloc] initWithObjects:@"Edit Me!",@"Ninjas",@"Pirates",@"Robots",nil];
+    index = 0;
+    for (NSString *name in teamNames)
+        [self createTeamNamed:name ofType:index++ controlledByAI:[name isEqualToString:@"Robots"]];
+    [teamNames release];
+
+    // SCHEMES - always overwrite and delete custom ones
+    if ([[NSFileManager defaultManager] fileExistsAtPath:SCHEMES_DIRECTORY()] == YES)
+        [[NSFileManager defaultManager] removeItemAtPath:SCHEMES_DIRECTORY() error:NULL];
+    NSArray *schemeNames = [[NSArray alloc] initWithObjects:@"Default",@"Pro Mode",@"Shoppa",@"Clean Slate",
+                            @"Minefield",@"Barrel Mayhem",@"Tunnel Hogs",@"Fort Mode",@"Timeless",
+                            @"Thinking with Portals",@"King Mode",nil];
+    index = 0;
+    for (NSString *name in schemeNames)
+        [self createSchemeNamed:name ofType:index++];
+    [schemeNames release];
+
+    // WEAPONS - always overwrite as merge is not needed (missing weaps are 0ed automatically)
+    NSArray *weaponNames = [[NSArray alloc] initWithObjects:@"Default",@"Crazy",@"Pro Mode",@"Shoppa",@"Clean Slate",
+                            @"Minefield",@"Thinking with Portals",nil];
+    index = 0;
+    for (NSString *name in weaponNames)
+        [self createWeaponNamed:name ofType:index++];
+    [weaponNames release];
+}
+
 #pragma mark Settings
 +(void) createSettings {
     NSUserDefaults *settings = [NSUserDefaults standardUserDefaults];
@@ -41,11 +91,11 @@
 
 #pragma mark Teams
 +(void) createTeamNamed:(NSString *)nameWithoutExt {
-    [CreationChamber createTeamNamed:nameWithoutExt ofType:0 controlledByAI:NO];
+    [self createTeamNamed:nameWithoutExt ofType:0 controlledByAI:NO];
 }
 
 +(void) createTeamNamed:(NSString *)nameWithoutExt ofType:(NSInteger) type {
-    [CreationChamber createTeamNamed:nameWithoutExt ofType:type controlledByAI:NO];
+    [self createTeamNamed:nameWithoutExt ofType:type controlledByAI:NO];
 }
 
 +(void) createTeamNamed:(NSString *)nameWithoutExt ofType:(NSInteger) type controlledByAI:(BOOL) shouldAITakeOver {
@@ -133,7 +183,7 @@
 
 #pragma mark Weapons
 +(void) createWeaponNamed:(NSString *)nameWithoutExt {
-    [CreationChamber createWeaponNamed:nameWithoutExt ofType:0];
+    [self createWeaponNamed:nameWithoutExt ofType:0];
 }
 
 +(void) createWeaponNamed:(NSString *)nameWithoutExt ofType:(NSInteger) type {
@@ -208,7 +258,7 @@
 
 #pragma mark Schemes
 +(void) createSchemeNamed:(NSString *)nameWithoutExt {
-    [CreationChamber createSchemeNamed:nameWithoutExt ofType:0];
+    [self createSchemeNamed:nameWithoutExt ofType:0];
 }
 
 +(void) createSchemeNamed:(NSString *)nameWithoutExt ofType:(NSInteger) type {
@@ -230,7 +280,7 @@
 
     NSArray *mods = [[NSArray alloc] initWithContentsOfFile:GAMEMODS_FILE()];
     NSMutableArray *gamemodArray= [[NSMutableArray alloc] initWithCapacity:[mods count]];
-    for (int i = 0; i < [mods count]; i++)
+    for (NSUInteger i = 0; i < [mods count]; i++)
         [gamemodArray addObject:[NSNumber numberWithBool:NO]];
     [mods release];
 
--- a/project_files/HedgewarsMobile/Classes/DefinesAndMacros.h	Sun Apr 01 15:23:34 2012 +0200
+++ b/project_files/HedgewarsMobile/Classes/DefinesAndMacros.h	Wed May 02 23:53:45 2012 +0200
@@ -38,8 +38,8 @@
 #define ZAssert(condition, ...) do { if (!(condition)) { ALog(__VA_ARGS__); }} while(0)
 #define rotationManager(x) (IS_IPAD() ? YES : (x == UIInterfaceOrientationLandscapeRight) || (x == UIInterfaceOrientationLandscapeLeft))
 
-#define START_TIMER NSTimeInterval start = [NSDate timeIntervalSinceReferenceDate];
-#define END_TIMER(msg) 	NSTimeInterval stop = [NSDate timeIntervalSinceReferenceDate]; CMLog([NSString stringWithFormat:@"%@ Time = %f", msg, stop-start]);
+#define START_TIMER()   NSTimeInterval start = [NSDate timeIntervalSinceReferenceDate];
+#define END_TIMER(msg) 	NSTimeInterval stop = [NSDate timeIntervalSinceReferenceDate]; DLog([NSString stringWithFormat:@"%@ Time = %f", msg, stop-start]);
 
 
 #define DOCUMENTS_FOLDER()      [NSSearchPathForDirectoriesInDomains(NSDocumentDirectory, NSUserDomainMask, YES) objectAtIndex:0]
--- a/project_files/HedgewarsMobile/Classes/EditableCellView.h	Sun Apr 01 15:23:34 2012 +0200
+++ b/project_files/HedgewarsMobile/Classes/EditableCellView.h	Wed May 02 23:53:45 2012 +0200
@@ -30,8 +30,8 @@
     id<EditableCellViewDelegate> delegate;
     UITextField *textField;
     UILabel *titleLabel;
-    NSInteger minimumCharacters;
-    NSInteger maximumCharacters;
+    NSUInteger minimumCharacters;
+    NSUInteger maximumCharacters;
     BOOL respectEditing;
 
 @private
@@ -41,8 +41,8 @@
 @property (nonatomic,assign) id<EditableCellViewDelegate> delegate;
 @property (nonatomic,retain,readonly) UITextField *textField;
 @property (nonatomic,retain,readonly) UILabel *titleLabel;
-@property (nonatomic,assign) NSInteger minimumCharacters;
-@property (nonatomic,assign) NSInteger maximumCharacters;
+@property (nonatomic,assign) NSUInteger minimumCharacters;
+@property (nonatomic,assign) NSUInteger maximumCharacters;
 @property (nonatomic,assign) BOOL respectEditing;
 @property (nonatomic,retain) NSString *oldValue;
 
--- a/project_files/HedgewarsMobile/Classes/EngineProtocolNetwork.h	Sun Apr 01 15:23:34 2012 +0200
+++ b/project_files/HedgewarsMobile/Classes/EngineProtocolNetwork.h	Wed May 02 23:53:45 2012 +0200
@@ -18,21 +18,30 @@
 
 
 #import <Foundation/Foundation.h>
+#import "SDL_net.h"
+
+
+@protocol EngineProtocolDelegate <NSObject>
+
+-(void) gameEndedWithStatistics:(NSArray *)stats;
+
+@end
 
 
 @interface EngineProtocolNetwork : NSObject {
-    NSMutableArray *statsArray;
+    id<EngineProtocolDelegate> delegate;
     NSOutputStream *stream;
     TCPsocket csd;
     NSInteger enginePort;
 }
 
-@property (nonatomic,assign) NSMutableArray *statsArray;
+@property (nonatomic,assign) id<EngineProtocolDelegate> delegate;
 @property (nonatomic,retain) NSOutputStream *stream;
 @property (assign) TCPsocket csd;
 @property (assign) NSInteger enginePort;
 
 -(id)   init;
+-(id)   initWithPort:(NSInteger) port;
 -(void) spawnThread:(NSString *)onSaveFile withOptions:(NSDictionary *)dictionary;
 -(void) engineProtocol:(id) object;
 
--- a/project_files/HedgewarsMobile/Classes/EngineProtocolNetwork.m	Sun Apr 01 15:23:34 2012 +0200
+++ b/project_files/HedgewarsMobile/Classes/EngineProtocolNetwork.m	Wed May 02 23:53:45 2012 +0200
@@ -23,20 +23,24 @@
 #define BUFFER_SIZE 255     // like in original frontend
 
 @implementation EngineProtocolNetwork
-@synthesize statsArray, stream, csd, enginePort;
+@synthesize delegate, stream, csd, enginePort;
 
--(id) init {
-    if (self = [super init]) {
-        self.statsArray = nil;
+-(id) initWithPort:(NSInteger) port {
+    if ((self = [super init])) {
+        self.delegate = nil;
         self.csd = NULL;
         self.stream = nil;
-        self.enginePort = [HWUtils randomPort];
+        self.enginePort = port;
     }
     return self;
 }
 
+-(id) init {
+    return [self initWithPort:[HWUtils randomPort]];
+}
+
 -(void) dealloc {
-    releaseAndNil(statsArray);
+    self.delegate = nil;
     releaseAndNil(stream);
     [super dealloc];
 }
@@ -114,7 +118,7 @@
     // if we're loading an older version of ammos fill the engine message with 0s
     int diff = HW_getNumberOfWeapons() - [[ammoData objectForKey:@"ammostore_initialqt"] length];
     NSString *update = @"";
-    while ([update length] < diff)
+    while ((int)[update length] < diff)
         update = [update stringByAppendingString:@"0"];
 
     NSString *ammloadt = [[NSString alloc] initWithFormat:@"eammloadt %@%@", [ammoData objectForKey:@"ammostore_initialqt"], update];
@@ -166,7 +170,7 @@
     result = [[basicArray objectAtIndex:0] intValue];
     NSArray *basic = [[NSArray alloc] initWithContentsOfFile:BASICFLAGS_FILE()];
 
-    for (int i = 1; i < [basicArray count]; i++) {
+    for (NSUInteger i = 1; i < [basicArray count]; i++) {
         NSDictionary *dict = [basic objectAtIndex:i];
         NSString *command = [dict objectForKey:@"command"];
         NSInteger value = [[basicArray objectAtIndex:i] intValue];
@@ -212,6 +216,7 @@
 -(void) engineProtocol:(id) object {
     NSAutoreleasePool *pool = [[NSAutoreleasePool alloc] init];
     NSDictionary *gameConfig = (NSDictionary *)object;
+    NSMutableArray *statsArray = nil;
     TCPsocket sd;
     IPaddress ip;
     int eProto;
@@ -326,10 +331,10 @@
                 }
                 break;
             case 'i':
-                if (self.statsArray == nil) {
-                    self.statsArray = [[NSMutableArray alloc] initWithCapacity:10 - 2];
+                if (statsArray == nil) {
+                    statsArray = [[NSMutableArray alloc] initWithCapacity:10 - 2];
                     NSMutableArray *ranking = [[NSMutableArray alloc] initWithCapacity:4];
-                    [self.statsArray insertObject:ranking atIndex:0];
+                    [statsArray insertObject:ranking atIndex:0];
                     [ranking release];
                 }
                 NSString *tempStr = [NSString stringWithUTF8String:&buffer[2]];
@@ -338,16 +343,16 @@
                 int index = [arg length] + 3;
                 switch (buffer[1]) {
                     case 'r':           // winning team
-                        [self.statsArray insertObject:[NSString stringWithUTF8String:&buffer[2]] atIndex:1];
+                        [statsArray insertObject:[NSString stringWithUTF8String:&buffer[2]] atIndex:1];
                         break;
                     case 'D':           // best shot
-                        [self.statsArray addObject:[NSString stringWithFormat:@"The best shot award won by %s (with %@ points)", &buffer[index], arg]];
+                        [statsArray addObject:[NSString stringWithFormat:@"The best shot award won by %s (with %@ points)", &buffer[index], arg]];
                         break;
                     case 'k':           // best hedgehog
-                        [self.statsArray addObject:[NSString stringWithFormat:@"The best killer is %s with %@ kill(s) in a turn", &buffer[index], arg]];
+                        [statsArray addObject:[NSString stringWithFormat:@"The best killer is %s with %@ kill(s) in a turn", &buffer[index], arg]];
                         break;
                     case 'K':           // number of hogs killed
-                        [self.statsArray addObject:[NSString stringWithFormat:@"%@ hedgehog(s) were killed during this round", arg]];
+                        [statsArray addObject:[NSString stringWithFormat:@"%@ hedgehog(s) were killed during this round", arg]];
                         break;
                     case 'H':           // team health/graph
                         break;
@@ -355,16 +360,16 @@
                         // still WIP in statsPage.cpp
                         break;
                     case 'P':           // teams ranking
-                        [[self.statsArray objectAtIndex:0] addObject:tempStr];
+                        [[statsArray objectAtIndex:0] addObject:tempStr];
                         break;
                     case 's':           // self damage
-                        [self.statsArray addObject:[NSString stringWithFormat:@"%s thought it's good to shoot his own hedgehogs with %@ points", &buffer[index], arg]];
+                        [statsArray addObject:[NSString stringWithFormat:@"%s thought it's good to shoot his own hedgehogs with %@ points", &buffer[index], arg]];
                         break;
                     case 'S':           // friendly fire
-                        [self.statsArray addObject:[NSString stringWithFormat:@"%s killed %@ of his own hedgehogs", &buffer[index], arg]];
+                        [statsArray addObject:[NSString stringWithFormat:@"%s killed %@ of his own hedgehogs", &buffer[index], arg]];
                         break;
                     case 'B':           // turn skipped
-                        [self.statsArray addObject:[NSString stringWithFormat:@"%s was scared and skipped turn %@ times", &buffer[index], arg]];
+                        [statsArray addObject:[NSString stringWithFormat:@"%s was scared and skipped turn %@ times", &buffer[index], arg]];
                         break;
                     default:
                         DLog(@"Unhandled stat message, see statsPage.cpp");
@@ -373,6 +378,9 @@
                 break;
             case 'q':
                 // game ended and match finished, statsArray is full of delicious statistics
+                if (self.delegate != nil && [self.delegate respondsToSelector:@selector(gameEndedWithStatistics:)])
+                    [self.delegate gameEndedWithStatistics:statsArray];
+                [statsArray release];
                 [HWUtils setGameStatus:gsEnded];
                 // closing connection here would trigger a "IPC connection lost" error, so we have to wait until recv fails
                 break;
--- a/project_files/HedgewarsMobile/Classes/FortsViewController.m	Sun Apr 01 15:23:34 2012 +0200
+++ b/project_files/HedgewarsMobile/Classes/FortsViewController.m	Wed May 02 23:53:45 2012 +0200
@@ -39,7 +39,7 @@
     NSArray *directoryContents = [[NSFileManager defaultManager] contentsOfDirectoryAtPath:FORTS_DIRECTORY() error:NULL];
     NSMutableArray *filteredContents = [[NSMutableArray alloc] initWithCapacity:([directoryContents count] / IMGNUM_PER_FORT)];
     // we need to remove the double entries and the L.png suffix
-    for (int i = 0; i < [directoryContents count]; i++) {
+    for (NSUInteger i = 0; i < [directoryContents count]; i++) {
         if (i % IMGNUM_PER_FORT == IMGNUM_PER_FORT-1) {
             NSString *currentName = [directoryContents objectAtIndex:i];
             NSString *correctName = [currentName substringToIndex:([currentName length] - 5)];
--- a/project_files/HedgewarsMobile/Classes/GameConfigViewController.m	Sun Apr 01 15:23:34 2012 +0200
+++ b/project_files/HedgewarsMobile/Classes/GameConfigViewController.m	Wed May 02 23:53:45 2012 +0200
@@ -47,12 +47,12 @@
                 [alert show];
                 [alert release];
             } else {
-                [AudioManagerController playBackSound];
+                [[AudioManagerController mainManager] playBackSound];
                 [[self parentViewController] dismissModalViewControllerAnimated:YES];
             }
             break;
         case 1:
-            [AudioManagerController playClickSound];
+            [[AudioManagerController mainManager] playClickSound];
             if ([self isEverythingSet] == NO)
                 return;
             theButton.enabled = NO;
@@ -66,7 +66,7 @@
             
             break;
         case 2:
-            [AudioManagerController playClickSound];
+            [[AudioManagerController mainManager] playClickSound];
             if (self.helpPage == nil)
                 self.helpPage = [[HelpPageLobbyViewController alloc] initWithNibName:@"HelpPageLobbyViewController-iPad" bundle:nil];
             self.helpPage.view.alpha = 0;
@@ -85,7 +85,7 @@
 
     UISegmentedControl *theSegment = (UISegmentedControl *)sender;
 
-    [AudioManagerController playSelectSound];
+    [[AudioManagerController mainManager] playSelectSound];
     switch (theSegment.selectedSegmentIndex) {
         case 0:
             // this message is compulsory otherwise the table won't be loaded at all
@@ -159,7 +159,7 @@
     }
 
     // play if there aren't too many teams
-    if ([self.teamConfigViewController.listOfSelectedTeams count] > HW_getMaxNumberOfTeams()) {
+    if ((int)[self.teamConfigViewController.listOfSelectedTeams count] > HW_getMaxNumberOfTeams()) {
         UIAlertView *alert = [[UIAlertView alloc] initWithTitle:NSLocalizedString(@"Too many teams",@"")
                                                         message:NSLocalizedString(@"You exceeded the maximum number of tems allowed in a game",@"")
                                                        delegate:nil
--- a/project_files/HedgewarsMobile/Classes/GameInterfaceBridge.h	Sun Apr 01 15:23:34 2012 +0200
+++ b/project_files/HedgewarsMobile/Classes/GameInterfaceBridge.h	Wed May 02 23:53:45 2012 +0200
@@ -18,19 +18,18 @@
 
 
 #import <Foundation/Foundation.h>
+#import "EngineProtocolNetwork.h"
 
 
-@class EngineProtocolNetwork;
-
-@interface GameInterfaceBridge : NSObject {
+@interface GameInterfaceBridge : NSObject <EngineProtocolDelegate> {
     UIView *blackView;
     NSString *savePath;
-    EngineProtocolNetwork *proto;
+    NSInteger port;
 }
 
 @property (nonatomic,retain) UIView *blackView;
 @property (nonatomic,retain) NSString *savePath;
-@property (nonatomic,retain) EngineProtocolNetwork *proto;
+@property (assign) NSInteger port;
 
 +(void) startLocalGame:(NSDictionary *)withOptions;
 +(void) startSaveGame:(NSString *)atPath;
--- a/project_files/HedgewarsMobile/Classes/GameInterfaceBridge.m	Sun Apr 01 15:23:34 2012 +0200
+++ b/project_files/HedgewarsMobile/Classes/GameInterfaceBridge.m	Wed May 02 23:53:45 2012 +0200
@@ -25,19 +25,20 @@
 static UIViewController *callingController;
 
 @implementation GameInterfaceBridge
-@synthesize blackView, savePath, proto;
+@synthesize blackView, savePath, port;
 
 #pragma mark -
 #pragma mark Instance methods for engine interaction
 // prepares the controllers for hosting a game
 -(void) earlyEngineLaunch:(NSDictionary *)optionsOrNil {
     [self retain];
-    [AudioManagerController fadeOutBackgroundMusic];
+    [[AudioManagerController mainManager] fadeOutBackgroundMusic];
 
     EngineProtocolNetwork *engineProtocol = [[EngineProtocolNetwork alloc] init];
-    self.proto = engineProtocol;
+    self.port = engineProtocol.enginePort;
+    engineProtocol.delegate = self;
+    [engineProtocol spawnThread:self.savePath withOptions:optionsOrNil];
     [engineProtocol release];
-    [self.proto spawnThread:self.savePath withOptions:optionsOrNil];
 
     // add a black view hiding the background
     UIWindow *thisWindow = [[HedgewarsAppDelegate sharedAppDelegate] uiwindow];
@@ -53,9 +54,10 @@
     [thisWindow addSubview:self.blackView];
     [self.blackView release];
 
-    // keep track of uncompleted games
+    // keep the point of return for games that completed loading
     NSUserDefaults *userDefaults = [NSUserDefaults standardUserDefaults];
     [userDefaults setObject:self.savePath forKey:@"savedGamePath"];
+    [userDefaults setObject:[NSNumber numberWithBool:NO] forKey:@"saveIsValid"];
     [userDefaults synchronize];
 
     // let's launch the engine using this -perfomSelector so that the runloop can deal with queued messages first
@@ -81,26 +83,12 @@
     [UIView commitAnimations];
     [self.blackView performSelector:@selector(removeFromSuperview) withObject:nil afterDelay:1];
 
-    // engine thread *should* be done by now
-    NSArray *stats = [[NSArray alloc] initWithArray:self.proto.statsArray copyItems:YES];
-    if ([HWUtils gameStatus] == gsEnded && stats != nil) {
-        StatsPageViewController *statsPage = [[StatsPageViewController alloc] init];
-        statsPage.statsArray = stats;
-        statsPage.modalTransitionStyle = UIModalTransitionStyleCoverVertical;
-        if ([statsPage respondsToSelector:@selector(setModalPresentationStyle:)])
-            statsPage.modalPresentationStyle = UIModalPresentationPageSheet;
-
-        [callingController presentModalViewController:statsPage animated:YES];
-        [statsPage release];
-    }
-    [stats release];
-
     // can remove the savefile if the replay has ended
     if ([HWUtils gameType] == gtSave)
         [[NSFileManager defaultManager] removeItemAtPath:self.savePath error:nil];
 
     // restart music and we're done
-    [AudioManagerController fadeInBackgroundMusic];
+    [[AudioManagerController mainManager] fadeInBackgroundMusic];
     [HWUtils setGameStatus:gsNone];
     [HWUtils setGameType:gtNone];
     [self release];
@@ -110,9 +98,8 @@
 -(void) engineLaunch {
     const char *gameArgs[11];
     CGFloat width, height;
-    NSInteger enginePort = self.proto.enginePort;
     CGFloat screenScale = [[UIScreen mainScreen] safeScale];
-    NSString *ipcString = [[NSString alloc] initWithFormat:@"%d",enginePort];
+    NSString *ipcString = [[NSString alloc] initWithFormat:@"%d",self.port];
     NSString *localeString = [[NSString alloc] initWithFormat:@"%@.txt",[[NSLocale preferredLanguages] objectAtIndex:0]];
     NSUserDefaults *settings = [NSUserDefaults standardUserDefaults];
 
@@ -174,11 +161,23 @@
 -(void) dealloc {
     releaseAndNil(blackView);
     releaseAndNil(savePath);
-    releaseAndNil(proto);
     [super dealloc];
 }
 
 #pragma mark -
+#pragma mark EngineProtocolDelegate methods
+-(void) gameEndedWithStatistics:(NSArray *)stats {
+    if (stats != nil) {
+        StatsPageViewController *statsPage = [[StatsPageViewController alloc] init];
+        statsPage.statsArray = stats;
+        statsPage.modalTransitionStyle = UIModalTransitionStyleCoverVertical;
+
+        [callingController presentModalViewController:statsPage animated:YES];
+        [statsPage release];
+    }
+}
+
+#pragma mark -
 #pragma mark Class methods for setting up the engine from outsite
 +(void) registerCallingController:(UIViewController *)controller {
     callingController = controller;
--- a/project_files/HedgewarsMobile/Classes/GeneralSettingsViewController.m	Sun Apr 01 15:23:34 2012 +0200
+++ b/project_files/HedgewarsMobile/Classes/GeneralSettingsViewController.m	Wed May 02 23:53:45 2012 +0200
@@ -43,7 +43,7 @@
     NSUserDefaults *userDefaults = [NSUserDefaults standardUserDefaults];
     [userDefaults synchronize];
     if ([[userDefaults objectForKey:@"music"] boolValue] == NO)
-        [AudioManagerController stopBackgroundMusic];
+        [[AudioManagerController mainManager] stopBackgroundMusic];
 
     [super viewWillDisappear:animated];
 }
@@ -63,7 +63,7 @@
             [theOtherSwitch setOn:NO animated:YES];
 
             // since switching sound on won't turn music on anyways, we can always turn off music
-            [AudioManagerController pauseBackgroundMusic];
+            [[AudioManagerController mainManager]pauseBackgroundMusic];
             [settings setObject:[NSNumber numberWithBool:NO] forKey:@"music"];
             break;
         case 20:    //musicSwitch
@@ -76,9 +76,9 @@
                 [settings setObject:[NSNumber numberWithBool:theSwitch.on] forKey:@"music"];
 
             if (theSwitch.on)
-                [AudioManagerController playBackgroundMusic];
+                [[AudioManagerController mainManager] playBackgroundMusic];
             else
-                [AudioManagerController pauseBackgroundMusic];
+                [[AudioManagerController mainManager] pauseBackgroundMusic];
             break;
         case 30:    //alternateSwitch
             [settings setObject:[NSNumber numberWithBool:theSwitch.on] forKey:@"alternate"];
--- a/project_files/HedgewarsMobile/Classes/HedgewarsAppDelegate.m	Sun Apr 01 15:23:34 2012 +0200
+++ b/project_files/HedgewarsMobile/Classes/HedgewarsAppDelegate.m	Wed May 02 23:53:45 2012 +0200
@@ -36,7 +36,7 @@
 #pragma mark -
 #pragma mark AppDelegate methods
 -(id) init {
-    if (self = [super init]){
+    if ((self = [super init])) {
         mainViewController = nil;
         uiwindow = nil;
     }
@@ -68,7 +68,7 @@
     [HWUtils releaseCache];
     // don't stop music if it is playing
     if ([HWUtils isGameLaunched]) {
-        [AudioManagerController releaseCache];
+        [[AudioManagerController mainManager] didReceiveMemoryWarning];
         HW_memoryWarningCallback();
     }
     MSG_MEMCLEAN();
--- a/project_files/HedgewarsMobile/Classes/MGSplitViewController/MGSplitCornersView.m	Sun Apr 01 15:23:34 2012 +0200
+++ b/project_files/HedgewarsMobile/Classes/MGSplitViewController/MGSplitCornersView.m	Wed May 02 23:53:45 2012 +0200
@@ -7,7 +7,7 @@
 //
 
 #import "MGSplitCornersView.h"
-
+#import "CGPointUtils.h"
 
 @implementation MGSplitCornersView
 
@@ -40,24 +40,6 @@
 
 
 #pragma mark -
-#pragma mark Geometry helpers
-
-
-double deg2Rad(double degrees)
-{
-	// Converts degrees to radians.
-	return degrees * (M_PI / 180.0);
-}
-
-
-double rad2Deg(double radians)
-{
-	// Converts radians to degrees.
-	return radians * (180 / M_PI);
-}
-
-
-#pragma mark -
 #pragma mark Drawing
 
 
@@ -78,7 +60,7 @@
 			case MGCornersPositionLeadingVertical: // top of screen for a left/right split
 				[path moveToPoint:pt];
 				pt.y += cornerRadius;
-				[path appendPath:[UIBezierPath bezierPathWithArcCenter:pt radius:cornerRadius startAngle:deg2Rad(90) endAngle:0 clockwise:YES]];
+				[path appendPath:[UIBezierPath bezierPathWithArcCenter:pt radius:cornerRadius startAngle:degreesToRadians(90) endAngle:0 clockwise:YES]];
 				pt.x += cornerRadius;
 				pt.y -= cornerRadius;
 				[path addLineToPoint:pt];
@@ -91,7 +73,7 @@
 				pt.y = maxY;
 				[path addLineToPoint:pt];
 				pt.x += cornerRadius;
-				[path appendPath:[UIBezierPath bezierPathWithArcCenter:pt radius:cornerRadius startAngle:deg2Rad(180) endAngle:deg2Rad(90) clockwise:YES]];
+				[path appendPath:[UIBezierPath bezierPathWithArcCenter:pt radius:cornerRadius startAngle:degreesToRadians(180) endAngle:degreesToRadians(90) clockwise:YES]];
 				pt.y -= cornerRadius;
 				[path addLineToPoint:pt];
 				pt.x -= cornerRadius;
@@ -104,7 +86,7 @@
 				pt.y = maxY;
 				[path moveToPoint:pt];
 				pt.y -= cornerRadius;
-				[path appendPath:[UIBezierPath bezierPathWithArcCenter:pt radius:cornerRadius startAngle:deg2Rad(270) endAngle:deg2Rad(360) clockwise:NO]];
+				[path appendPath:[UIBezierPath bezierPathWithArcCenter:pt radius:cornerRadius startAngle:degreesToRadians(270) endAngle:degreesToRadians(360) clockwise:NO]];
 				pt.x += cornerRadius;
 				pt.y += cornerRadius;
 				[path addLineToPoint:pt];
@@ -118,7 +100,7 @@
 				pt.y -= cornerRadius;
 				[path addLineToPoint:pt];
 				pt.x += cornerRadius;
-				[path appendPath:[UIBezierPath bezierPathWithArcCenter:pt radius:cornerRadius startAngle:deg2Rad(180) endAngle:deg2Rad(270) clockwise:NO]];
+				[path appendPath:[UIBezierPath bezierPathWithArcCenter:pt radius:cornerRadius startAngle:degreesToRadians(180) endAngle:degreesToRadians(270) clockwise:NO]];
 				pt.y += cornerRadius;
 				[path addLineToPoint:pt];
 				pt.x -= cornerRadius;
@@ -134,7 +116,7 @@
 				pt.y -= cornerRadius;
 				[path addLineToPoint:pt];
 				pt.x += cornerRadius;
-				[path appendPath:[UIBezierPath bezierPathWithArcCenter:pt radius:cornerRadius startAngle:deg2Rad(180) endAngle:deg2Rad(270) clockwise:NO]];
+				[path appendPath:[UIBezierPath bezierPathWithArcCenter:pt radius:cornerRadius startAngle:degreesToRadians(180) endAngle:degreesToRadians(270) clockwise:NO]];
 				pt.y += cornerRadius;
 				[path addLineToPoint:pt];
 				pt.x -= cornerRadius;
@@ -147,7 +129,7 @@
 				pt.y = maxY;
 				[path addLineToPoint:pt];
 				pt.x += cornerRadius;
-				[path appendPath:[UIBezierPath bezierPathWithArcCenter:pt radius:cornerRadius startAngle:deg2Rad(180) endAngle:deg2Rad(90) clockwise:YES]];
+				[path appendPath:[UIBezierPath bezierPathWithArcCenter:pt radius:cornerRadius startAngle:degreesToRadians(180) endAngle:degreesToRadians(90) clockwise:YES]];
 				pt.y -= cornerRadius;
 				[path addLineToPoint:pt];
 				pt.x -= cornerRadius;
@@ -160,7 +142,7 @@
 				pt.y = cornerRadius;
 				[path moveToPoint:pt];
 				pt.y -= cornerRadius;
-				[path appendPath:[UIBezierPath bezierPathWithArcCenter:pt radius:cornerRadius startAngle:deg2Rad(270) endAngle:deg2Rad(360) clockwise:NO]];
+				[path appendPath:[UIBezierPath bezierPathWithArcCenter:pt radius:cornerRadius startAngle:degreesToRadians(270) endAngle:degreesToRadians(360) clockwise:NO]];
 				pt.x += cornerRadius;
 				pt.y += cornerRadius;
 				[path addLineToPoint:pt];
@@ -171,7 +153,7 @@
 				pt.y = maxY - cornerRadius;
 				[path moveToPoint:pt];
 				pt.y += cornerRadius;
-				[path appendPath:[UIBezierPath bezierPathWithArcCenter:pt radius:cornerRadius startAngle:deg2Rad(90) endAngle:0 clockwise:YES]];
+				[path appendPath:[UIBezierPath bezierPathWithArcCenter:pt radius:cornerRadius startAngle:degreesToRadians(90) endAngle:0 clockwise:YES]];
 				pt.x += cornerRadius;
 				pt.y -= cornerRadius;
 				[path addLineToPoint:pt];
--- a/project_files/HedgewarsMobile/Classes/MGSplitViewController/MGSplitViewController.m	Sun Apr 01 15:23:34 2012 +0200
+++ b/project_files/HedgewarsMobile/Classes/MGSplitViewController/MGSplitViewController.m	Wed May 02 23:53:45 2012 +0200
@@ -702,7 +702,7 @@
 }
 
 
-- (IBAction)showMasterPopover:(id)sender
+- (IBAction)showMasterPopover:(id) sender
 {
 	if (_hiddenPopoverController && !(_hiddenPopoverController.popoverVisible)) {
 		// Inform delegate.
--- a/project_files/HedgewarsMobile/Classes/MNEValueTrackingSlider.m	Sun Apr 01 15:23:34 2012 +0200
+++ b/project_files/HedgewarsMobile/Classes/MNEValueTrackingSlider.m	Wed May 02 23:53:45 2012 +0200
@@ -93,7 +93,7 @@
 
 @synthesize thumbRect, textValue;
 
-#pragma Private methods
+#pragma mark Private methods
 
 -(void) _constructSlider {
     valuePopupView = [[SliderValuePopupView alloc] initWithFrame:CGRectZero];
--- a/project_files/HedgewarsMobile/Classes/MXAudioPlayerFadeOperation.m	Sun Apr 01 15:23:34 2012 +0200
+++ b/project_files/HedgewarsMobile/Classes/MXAudioPlayerFadeOperation.m	Wed May 02 23:53:45 2012 +0200
@@ -48,7 +48,7 @@
 #pragma mark -
 #pragma mark NSOperation
 -(id) initFadeWithAudioPlayer:(AVAudioPlayer*)player toVolume:(float)volume overDuration:(NSTimeInterval)duration withDelay:(NSTimeInterval)timeDelay {
-  if (self = [super init]) {
+  if ((self = [super init])) {
     self.audioPlayer = player;
     [player prepareToPlay];
     _fadeDuration = duration;
--- a/project_files/HedgewarsMobile/Classes/MainMenuViewController.m	Sun Apr 01 15:23:34 2012 +0200
+++ b/project_files/HedgewarsMobile/Classes/MainMenuViewController.m	Wed May 02 23:53:45 2012 +0200
@@ -37,56 +37,6 @@
     return rotationManager(interfaceOrientation);
 }
 
-// check if some configuration files are already set; if they are present it means that the current copy must be updated
--(void) createNecessaryFiles {
-    DLog(@"Creating necessary files");
-    NSInteger index;
-    
-    // SAVES - just delete and overwrite
-    if ([[NSFileManager defaultManager] fileExistsAtPath:SAVES_DIRECTORY()])
-        [[NSFileManager defaultManager] removeItemAtPath:SAVES_DIRECTORY() error:NULL];
-    [[NSFileManager defaultManager] createDirectoryAtPath:SAVES_DIRECTORY()
-                              withIntermediateDirectories:NO
-                                               attributes:nil
-                                                    error:NULL];
-
-    // SCREENSHOTS - just create it the first time
-    if ([[NSFileManager defaultManager] fileExistsAtPath:SCREENSHOTS_DIRECTORY()] == NO)
-        [[NSFileManager defaultManager] createDirectoryAtPath:SCREENSHOTS_DIRECTORY()
-                                  withIntermediateDirectories:NO
-                                                   attributes:nil
-                                                        error:NULL];
-
-    // SETTINGS - nsuserdefaults ftw
-    [CreationChamber createSettings];
-
-    // TEAMS - update exisiting teams with new format
-    NSArray *teamNames = [[NSArray alloc] initWithObjects:@"Edit Me!",@"Ninjas",@"Pirates",@"Robots",nil];
-    index = 0;
-    for (NSString *name in teamNames)
-        [CreationChamber createTeamNamed:name ofType:index++ controlledByAI:[name isEqualToString:@"Robots"]];
-    [teamNames release];
-
-    // SCHEMES - always overwrite and delete custom ones
-    if ([[NSFileManager defaultManager] fileExistsAtPath:SCHEMES_DIRECTORY()] == YES)
-        [[NSFileManager defaultManager] removeItemAtPath:SCHEMES_DIRECTORY() error:NULL];
-    NSArray *schemeNames = [[NSArray alloc] initWithObjects:@"Default",@"Pro Mode",@"Shoppa",@"Clean Slate",
-                            @"Minefield",@"Barrel Mayhem",@"Tunnel Hogs",@"Fort Mode",@"Timeless",
-                            @"Thinking with Portals",@"King Mode",nil];
-    index = 0;
-    for (NSString *name in schemeNames)
-        [CreationChamber createSchemeNamed:name ofType:index++];
-    [schemeNames release];
-
-    // WEAPONS - always overwrite as merge is not needed (missing weaps are 0ed automatically)
-    NSArray *weaponNames = [[NSArray alloc] initWithObjects:@"Default",@"Crazy",@"Pro Mode",@"Shoppa",@"Clean Slate",
-                            @"Minefield",@"Thinking with Portals",nil];
-    index = 0;
-    for (NSString *name in weaponNames)
-        [CreationChamber createWeaponNamed:name ofType:index++];
-    [weaponNames release];
-}
-
 #pragma mark -
 -(void) viewDidLoad {
     self.view.frame = [[UIScreen mainScreen] safeBounds];
@@ -104,14 +54,14 @@
         [userDefaults setObject:@"" forKey:@"savedGamePath"];
         // update the tracking version with the new one
         [userDefaults setObject:version forKey:@"HedgeVersion"];
+        [userDefaults synchronize];
 
-        [userDefaults synchronize];
-        [self createNecessaryFiles];
+        [CreationChamber createFirstLaunch];
     }
 
     // prompt for restoring any previous game
     NSString *saveString = [userDefaults objectForKey:@"savedGamePath"];
-    if (saveString != nil && [saveString isEqualToString:@""] == NO) {
+    if (saveString != nil && [saveString isEqualToString:@""] == NO && [[userDefaults objectForKey:@"saveIsValid"] boolValue]) {
         if (self.restoreViewController == nil) {
             NSString *xibName = [@"RestoreViewController-" stringByAppendingString:(IS_IPAD() ? @"iPad" : @"iPhone")];
             RestoreViewController *restored = [[RestoreViewController alloc] initWithNibName:xibName bundle:nil];
@@ -132,7 +82,7 @@
 }
 
 -(void) viewWillAppear:(BOOL)animated {
-    [AudioManagerController playBackgroundMusic];
+    [[AudioManagerController mainManager] playBackgroundMusic];
     [super viewWillAppear:animated];
 }
 
@@ -143,7 +93,7 @@
     NSString *xib = nil;
     NSString *debugStr = nil;
 
-    [AudioManagerController playClickSound];
+    [[AudioManagerController mainManager] playClickSound];
     switch (button.tag) {
         case 0:
             if (nil == self.gameConfigViewController) {
--- a/project_files/HedgewarsMobile/Classes/MapConfigViewController.m	Sun Apr 01 15:23:34 2012 +0200
+++ b/project_files/HedgewarsMobile/Classes/MapConfigViewController.m	Wed May 02 23:53:45 2012 +0200
@@ -35,7 +35,7 @@
 }
 
 -(IBAction) mapButtonPressed:(id) sender {
-    [AudioManagerController playClickSound];
+    [[AudioManagerController mainManager] playClickSound];
     [self updatePreview];
 }
 
@@ -114,7 +114,7 @@
 
 -(UITableViewCell *)tableView:(UITableView *)aTableView cellForRowAtIndexPath:(NSIndexPath *)indexPath {
     static NSString *CellIdentifier = @"Cell";
-    NSInteger row = [indexPath row];
+    NSUInteger row = [indexPath row];
 
     UITableViewCell *cell = [aTableView dequeueReusableCellWithIdentifier:CellIdentifier];
     if (cell == nil)
@@ -290,7 +290,7 @@
         [self updatePreview];
         oldValue = num;
     }
-    [AudioManagerController playClickSound];
+    [[AudioManagerController mainManager] playClickSound];
 }
 
 // perform actions based on the activated section, then call updatePreview to visually update the selection
@@ -299,7 +299,7 @@
     NSString *mapgen, *staticmap, *mission;
     NSInteger newPage = self.segmentedControl.selectedSegmentIndex;
 
-    [AudioManagerController playSelectSound];
+    [[AudioManagerController mainManager] playSelectSound];
     switch (newPage) {
         case 0: // Random
             mapgen = @"e$mapgen 0";
--- a/project_files/HedgewarsMobile/Classes/MapPreviewButtonView.h	Sun Apr 01 15:23:34 2012 +0200
+++ b/project_files/HedgewarsMobile/Classes/MapPreviewButtonView.h	Wed May 02 23:53:45 2012 +0200
@@ -18,6 +18,7 @@
 
 
 #import <UIKit/UIKit.h>
+#import "SDL_net.h"
 
 
 @protocol MapPreviewViewDelegate <NSObject>
--- a/project_files/HedgewarsMobile/Classes/MapPreviewButtonView.m	Sun Apr 01 15:23:34 2012 +0200
+++ b/project_files/HedgewarsMobile/Classes/MapPreviewButtonView.m	Wed May 02 23:53:45 2012 +0200
@@ -60,10 +60,10 @@
     return SDLNet_TCP_Send(csd, [string UTF8String], length);
 }
 
--(const uint8_t *)engineProtocol {
+-(void) engineProtocol:(uint8_t *)unpackedMap {
     IPaddress ip;
     BOOL serverQuit = NO;
-    static uint8_t map[128*32];
+    uint8_t packedMap[128*32];
     int port = [HWUtils randomPort];
 
     if (SDLNet_Init() < 0) {
@@ -103,50 +103,45 @@
             [self sendToEngine:[dictForEngine objectForKey:@"mazeSizeCommand"]];
             [self sendToEngine:@"!"];
 
-            memset(map, 0, 128*32);
-            SDLNet_TCP_Recv(csd, map, 128*32);
+            memset(packedMap, 0, 128*32);
+            SDLNet_TCP_Recv(csd, packedMap, 128*32);
             SDLNet_TCP_Recv(csd, &maxHogs, sizeof(uint8_t));
 
             SDLNet_TCP_Close(csd);
             serverQuit = YES;
         }
     }
-
     [HWUtils freePort:port];
     SDLNet_TCP_Close(sd);
     SDLNet_Quit();
-    return map;
+
+    // spread the packed bits in an array of bytes (one pixel per element, 0= transparent 1= color)
+    int k = 0;
+    memset(unpackedMap, 255, 128*32*8);     // 255 is white
+    for (int i = 0; i < 32*128; i++) {
+        for (int j = 7; j >= 0; j--) {
+            if (((packedMap[i] >> j) & 0x01) != 0)
+                unpackedMap[k] = 170;       // level of gray [0-255]
+            k++;
+        }
+    }
+    return;
 }
 
 -(void) drawingThread {
     NSAutoreleasePool *pool = [[NSAutoreleasePool alloc] init];
-    const uint8_t *map = [self engineProtocol];
-    uint8_t mapExp[128*32*8];
+    uint8_t unpackedMap[128*32*8];
+    [self engineProtocol:unpackedMap];
 
-    // draw the buffer (1 pixel per component, 0= transparent 1= color)
-    int k = 0;
-    for (int i = 0; i < 32*128; i++) {
-        unsigned char byte = map[i];
-        for (int j = 0; j < 8; j++) {
-            // select the color based on the leftmost bit
-            if ((byte & 0x80) != 0)
-                mapExp[k] = 100;
-            else
-                mapExp[k] = 255;
-            // shift to next bit
-            byte <<= 1;
-            k++;
-        }
-    }
+    // http://developer.apple.com/mac/library/qa/qa2001/qa1037.html
     CGColorSpaceRef colorspace = CGColorSpaceCreateDeviceGray();
-    CGContextRef bitmapImage = CGBitmapContextCreate(mapExp, 256, 128, 8, 256, colorspace, kCGImageAlphaNone);
+    CGContextRef bitmapImage = CGBitmapContextCreate(unpackedMap, 256, 128, 8, 256, colorspace, kCGImageAlphaNone);
     CGColorSpaceRelease(colorspace);
 
     CGImageRef previewCGImage = CGBitmapContextCreateImage(bitmapImage);
     CGContextRelease(bitmapImage);
     UIImage *previewImage = [[UIImage alloc] initWithCGImage:previewCGImage];
     CGImageRelease(previewCGImage);
-    previewCGImage = nil;
 
     // all these are performed on the main thread to prevent a leak
     [self performSelectorOnMainThread:@selector(setImageRounded:)
@@ -164,18 +159,6 @@
                         waitUntilDone:NO];
     
     [pool release];
-
-    /*
-    // http://developer.apple.com/mac/library/qa/qa2001/qa1037.html
-    UIGraphicsBeginImageContext(CGSizeMake(256,128));
-    CGContextRef context = UIGraphicsGetCurrentContext();
-    UIGraphicsPushContext(context);
-    CGContextSetRGBFillColor(context, 0.5, 0.5, 0.7, 1.0);
-    CGContextFillRect(context,CGRectMake(xc,yc,1,1));
-    UIGraphicsPopContext();
-    UIImage *previewImage = UIGraphicsGetImageFromCurrentImageContext();
-    UIGraphicsEndImageContext();
-    */
 }
 
 -(void) updatePreviewWithSeed:(NSString *)seed {
--- a/project_files/HedgewarsMobile/Classes/MissionTrainingViewController.m	Sun Apr 01 15:23:34 2012 +0200
+++ b/project_files/HedgewarsMobile/Classes/MissionTrainingViewController.m	Wed May 02 23:53:45 2012 +0200
@@ -64,7 +64,7 @@
     UIButton *button = (UIButton *)sender;
 
     if (button.tag == 0) {
-        [AudioManagerController playBackSound];
+        [[AudioManagerController mainManager] playBackSound];
         [[self parentViewController] dismissModalViewControllerAnimated:YES];
     } else {
         [GameInterfaceBridge registerCallingController:self];
@@ -89,7 +89,7 @@
         NSMutableArray *filteredArray = [[NSMutableArray alloc] initWithCapacity:[descArray count]/3];
         [descComplete release];
         // sanity check to avoid having missions and descriptions conflicts
-        for (int i = 0; i < [self.listOfMissions count]; i++) {
+        for (NSUInteger i = 0; i < [self.listOfMissions count]; i++) {
             NSString *desc = [[self.listOfMissions objectAtIndex:i] stringByDeletingPathExtension];
             for (NSString *str in descArray)
                 if ([str hasPrefix:desc] && [str hasSuffix:@"\""]) {
--- a/project_files/HedgewarsMobile/Classes/ObjcExports.h	Sun Apr 01 15:23:34 2012 +0200
+++ b/project_files/HedgewarsMobile/Classes/ObjcExports.h	Wed May 02 23:53:45 2012 +0200
@@ -20,7 +20,8 @@
 void clearView(void);
 BOOL isApplePhone(void);
 
-void startSpinningProgress(void);
-void stopSpinningProgress(void);
+void startLoadingIndicator(void);
+void stopLoadingIndicator(void);
+
 void saveBeganSynching(void);
 void saveFinishedSynching(void);
--- a/project_files/HedgewarsMobile/Classes/ObjcExports.m	Sun Apr 01 15:23:34 2012 +0200
+++ b/project_files/HedgewarsMobile/Classes/ObjcExports.m	Wed May 02 23:53:45 2012 +0200
@@ -25,11 +25,11 @@
 
 #pragma mark -
 #pragma mark functions called by pascal code
-BOOL inline isApplePhone() {
+BOOL inline isApplePhone(void) {
     return (IS_IPAD() == NO);
 }
 
-void startLoadingIndicator() {
+void startLoadingIndicator(void) {
     // this is the first ojbc function called by engine, so we have to initialize some variables here
     overlay_instance = [[OverlayViewController alloc] initWithNibName:@"OverlayViewController" bundle:nil];
     // in order to get rotation events we have to insert the view inside the first view of the second window
@@ -57,16 +57,19 @@
     [overlay_instance.loadingIndicator release];
 }
 
-void stopLoadingIndicator() {
+void stopLoadingIndicator(void) {
     HW_zoomSet(1.7);
     if ([HWUtils gameType] != gtSave) {
         [overlay_instance.loadingIndicator stopAnimating];
         [overlay_instance.loadingIndicator removeFromSuperview];
         [HWUtils setGameStatus:gsInGame];
     }
+    // mark the savefile as valid, eg it's been loaded correctly
+    [[NSUserDefaults standardUserDefaults] setObject:[NSNumber numberWithBool:YES] forKey:@"saveIsValid"];
+    [[NSUserDefaults standardUserDefaults] synchronize];
 }
 
-void saveFinishedSynching() {
+void saveFinishedSynching(void) {
     [UIView beginAnimations:@"fading from save synch" context:NULL];
     [UIView setAnimationDuration:1];
     overlay_instance.view.backgroundColor = [UIColor clearColor];
@@ -81,7 +84,7 @@
     [HWUtils setGameStatus:gsInGame];
 }
 
-void clearView() {
+void clearView(void) {
     [overlay_instance clearOverlay];
 }
 
--- a/project_files/HedgewarsMobile/Classes/OverlayViewController.m	Sun Apr 01 15:23:34 2012 +0200
+++ b/project_files/HedgewarsMobile/Classes/OverlayViewController.m	Wed May 02 23:53:45 2012 +0200
@@ -227,13 +227,13 @@
             HW_backjump();
             break;
         case 10:
-            [AudioManagerController playClickSound];
+            [[AudioManagerController mainManager] playClickSound];
             HW_pause();
             [self clearOverlay];
             [self showPopover];
             break;
         case 11:
-            [AudioManagerController playClickSound];
+            [[AudioManagerController mainManager] playClickSound];
             [self clearOverlay];
             HW_ammoMenu();
             break;
--- a/project_files/HedgewarsMobile/Classes/RestoreViewController.m	Sun Apr 01 15:23:34 2012 +0200
+++ b/project_files/HedgewarsMobile/Classes/RestoreViewController.m	Wed May 02 23:53:45 2012 +0200
@@ -31,11 +31,11 @@
     NSUserDefaults *defaults = [NSUserDefaults standardUserDefaults];
 
     if (theButton.tag != 0) {
-        [AudioManagerController playClickSound];
+        [[AudioManagerController mainManager] playClickSound];
         [GameInterfaceBridge registerCallingController:self.parentViewController];
         [GameInterfaceBridge startSaveGame:[[NSUserDefaults standardUserDefaults] objectForKey:@"savedGamePath"]];
     } else {
-        [AudioManagerController playBackSound];
+        [[AudioManagerController mainManager] playBackSound];
         [defaults setObject:@"" forKey:@"savedGamePath"];
         [defaults synchronize];
     }
--- a/project_files/HedgewarsMobile/Classes/SavedGamesViewController.m	Sun Apr 01 15:23:34 2012 +0200
+++ b/project_files/HedgewarsMobile/Classes/SavedGamesViewController.m	Wed May 02 23:53:45 2012 +0200
@@ -66,7 +66,7 @@
     UIButton *button = (UIButton *)sender;
 
     if (button.tag == 0) {
-        [AudioManagerController playBackSound];
+        [[AudioManagerController mainManager] playBackSound];
         [self.tableView setEditing:NO animated:YES];
         [[self parentViewController] dismissModalViewControllerAnimated:YES];
     } else {
--- a/project_files/HedgewarsMobile/Classes/SchemeWeaponConfigViewController.m	Sun Apr 01 15:23:34 2012 +0200
+++ b/project_files/HedgewarsMobile/Classes/SchemeWeaponConfigViewController.m	Wed May 02 23:53:45 2012 +0200
@@ -98,11 +98,12 @@
 -(void) viewDidLoad {
     self.sectionsHidden = NO;
 
-    NSInteger verticalOffset = IS_IPAD() ? 45 : 0;
+    NSInteger topOffset = IS_IPAD() ? 45 : 0;
+    NSInteger bottomOffset = IS_IPAD() ? 3 : 0;
     UITableView *aTableView = [[UITableView alloc] initWithFrame:CGRectMake(0,
-                                                                            verticalOffset,
+                                                                            topOffset,
                                                                             self.view.frame.size.width,
-                                                                            self.view.frame.size.height - verticalOffset)
+                                                                            self.view.frame.size.height - topOffset - bottomOffset)
                                                            style:UITableViewStyleGrouped];
     aTableView.delegate = self;
     aTableView.dataSource = self;
@@ -271,9 +272,9 @@
             if ([[settings objectForKey:@"sync_ws"] boolValue]) {
                 for (NSString *str in self.listOfWeapons) {
                     if ([str isEqualToString:self.selectedScheme]) {
-                        int index = [self.listOfSchemes indexOfObject:str];
+                        int row = [self.listOfSchemes indexOfObject:str];
                         self.selectedWeapon = str;
-                        self.lastIndexPath_we = [NSIndexPath indexPathForRow:index inSection:1];
+                        self.lastIndexPath_we = [NSIndexPath indexPathForRow:row inSection:1];
                         break;
                     }
                 }
--- a/project_files/HedgewarsMobile/Classes/ServerProtocolNetwork.h	Sun Apr 01 15:23:34 2012 +0200
+++ b/project_files/HedgewarsMobile/Classes/ServerProtocolNetwork.h	Wed May 02 23:53:45 2012 +0200
@@ -18,7 +18,7 @@
 
 
 #import <Foundation/Foundation.h>
-//#import "EngineProtocolNetwork.h"
+#import "SDL_net.h"
 
 
 @interface ServerProtocolNetwork : NSObject {
--- a/project_files/HedgewarsMobile/Classes/ServerProtocolNetwork.m	Sun Apr 01 15:23:34 2012 +0200
+++ b/project_files/HedgewarsMobile/Classes/ServerProtocolNetwork.m	Wed May 02 23:53:45 2012 +0200
@@ -30,7 +30,7 @@
 #pragma mark -
 #pragma mark init and class methods
 -(id) init:(NSInteger) onPort withAddress:(NSString *)address {
-    if (self = [super init]) {
+    if ((self = [super init])) {
         self.serverPort = onPort;
         self.serverAddress = address;
     }
--- a/project_files/HedgewarsMobile/Classes/SettingsBaseViewController.m	Sun Apr 01 15:23:34 2012 +0200
+++ b/project_files/HedgewarsMobile/Classes/SettingsBaseViewController.m	Wed May 02 23:53:45 2012 +0200
@@ -132,7 +132,7 @@
 }
 
 -(void) dismissSplitView {
-    [AudioManagerController playBackSound];
+    [[AudioManagerController mainManager] playBackSound];
     [[[HedgewarsAppDelegate sharedAppDelegate] mainViewController] dismissModalViewControllerAnimated:YES];
 }
 
@@ -240,7 +240,7 @@
         nextController.navigationItem.hidesBackButton = YES;
         [nextController viewWillAppear:NO];
         [targetController.navigationController pushViewController:nextController animated:NO];
-        [AudioManagerController playClickSound];
+        [[AudioManagerController mainManager] playClickSound];
     }
 }
 
--- a/project_files/HedgewarsMobile/Classes/SquareButtonView.h	Sun Apr 01 15:23:34 2012 +0200
+++ b/project_files/HedgewarsMobile/Classes/SquareButtonView.h	Wed May 02 23:53:45 2012 +0200
@@ -21,15 +21,16 @@
 
 
 @interface SquareButtonView : UIButton {
-    NSInteger colorIndex;
+    NSMutableDictionary *ownerDictionary;
+    NSUInteger colorIndex;
     NSUInteger selectedColor;
     NSArray *colorArray;
-    NSMutableDictionary *ownerDictionary;
 }
 
+@property (nonatomic,retain) NSMutableDictionary *ownerDictionary;
 @property (nonatomic,retain) NSArray *colorArray;
-@property (nonatomic) NSUInteger selectedColor;
-@property (nonatomic,retain) NSMutableDictionary *ownerDictionary;
+@property (nonatomic,assign) NSUInteger selectedColor;
+@property (nonatomic,assign) NSUInteger colorIndex;
 
 -(void) nextColor;
 -(void) selectColor:(NSUInteger) color;
--- a/project_files/HedgewarsMobile/Classes/SquareButtonView.m	Sun Apr 01 15:23:34 2012 +0200
+++ b/project_files/HedgewarsMobile/Classes/SquareButtonView.m	Wed May 02 23:53:45 2012 +0200
@@ -22,12 +22,12 @@
 
 
 @implementation SquareButtonView
-@synthesize colorArray, selectedColor, ownerDictionary;
+@synthesize ownerDictionary, colorIndex, selectedColor, colorArray;
 
 -(id) initWithFrame:(CGRect)frame {
     if ((self = [super initWithFrame:frame])) {
-        colorIndex = -1;
-        selectedColor = 0;
+        self.colorIndex = 0;
+        self.selectedColor = 0;
 
         self.colorArray = [HWUtils teamColors];
 
@@ -47,24 +47,21 @@
 }
 
 -(void) nextColor {
-    colorIndex++;
+    self.colorIndex++;
 
-    if (colorIndex >= [colorArray count])
-        colorIndex = 0;
+    if (self.colorIndex >= [self.colorArray count])
+        self.colorIndex = 0;
 
-    NSUInteger color = [[self.colorArray objectAtIndex:colorIndex] unsignedIntValue];
-    self.backgroundColor = [UIColor colorWithRed:((color & 0x00FF0000) >> 16)/255.0f
-                                           green:((color & 0x0000FF00) >> 8)/255.0f
-                                            blue: (color & 0x000000FF)/255.0f
-                                           alpha:1.0f];
-
-    [ownerDictionary setObject:[NSNumber numberWithInt:color] forKey:@"color"];
+    NSNumber *colorNumber = [self.colorArray objectAtIndex:colorIndex];
+    [self.ownerDictionary setObject:colorNumber forKey:@"color"];
+    NSUInteger color = [colorNumber unsignedIntValue];
+    [self selectColor:color];
 }
 
 -(void) selectColor:(NSUInteger) color {
-    if (color != selectedColor) {
-        selectedColor = color;
-        colorIndex = [self.colorArray indexOfObject:[NSNumber numberWithUnsignedInt:color]];
+    if (color != self.selectedColor) {
+        self.selectedColor = color;
+        self.colorIndex = [self.colorArray indexOfObject:[NSNumber numberWithUnsignedInt:color]];
 
         self.backgroundColor = [UIColor colorWithRed:((color & 0x00FF0000) >> 16)/255.0f
                                                green:((color & 0x0000FF00) >> 8)/255.0f
--- a/project_files/HedgewarsMobile/Classes/StatsPageViewController.h	Sun Apr 01 15:23:34 2012 +0200
+++ b/project_files/HedgewarsMobile/Classes/StatsPageViewController.h	Wed May 02 23:53:45 2012 +0200
@@ -26,4 +26,4 @@
 
 @property (nonatomic,retain) NSArray *statsArray;
 
-@end
\ No newline at end of file
+@end
--- a/project_files/HedgewarsMobile/Classes/StatsPageViewController.m	Sun Apr 01 15:23:34 2012 +0200
+++ b/project_files/HedgewarsMobile/Classes/StatsPageViewController.m	Wed May 02 23:53:45 2012 +0200
@@ -161,7 +161,7 @@
 #pragma mark -
 #pragma mark button delegate
 -(void) dismissView {
-    [AudioManagerController playClickSound];
+    [[AudioManagerController mainManager] playClickSound];
     [self dismissModalViewControllerAnimated:YES];
 }
 
--- a/project_files/HedgewarsMobile/Classes/TeamConfigViewController.m	Sun Apr 01 15:23:34 2012 +0200
+++ b/project_files/HedgewarsMobile/Classes/TeamConfigViewController.m	Wed May 02 23:53:45 2012 +0200
@@ -68,7 +68,7 @@
         self.cachedContentsOfDir = contentsOfDir;
         NSArray *colors = [HWUtils teamColors];
         NSMutableArray *array = [[NSMutableArray alloc] initWithCapacity:[contentsOfDir count]];
-        for (int i = 0; i < [contentsOfDir count]; i++) {
+        for (NSUInteger i = 0; i < [contentsOfDir count]; i++) {
             NSMutableDictionary *dict = [[NSMutableDictionary alloc] initWithObjectsAndKeys:
                                          [contentsOfDir objectAtIndex:i],@"team",
                                          [NSNumber numberWithInt:4],@"number",
@@ -224,8 +224,8 @@
 #pragma mark -
 #pragma mark Table view delegate
 -(void) tableView:(UITableView *)aTableView didSelectRowAtIndexPath:(NSIndexPath *)indexPath {
-    NSInteger row = [indexPath row];
-    NSInteger section = [indexPath section];
+    NSUInteger row = [indexPath row];
+    NSUInteger section = [indexPath section];
 
     if (section == 1 && [self.listOfAllTeams count] > row) {
         [self.listOfSelectedTeams addObject:[self.listOfAllTeams objectAtIndex:row]];
@@ -254,7 +254,7 @@
 }
 
 -(void) holdAction:(NSString *)content onTable:(UITableView *)aTableView {
-    NSInteger row;
+    NSUInteger row;
     for (row = 0; row < [self.listOfSelectedTeams count]; row++) {
         NSDictionary *dict = [self.listOfSelectedTeams objectAtIndex:row];
         if ([content isEqualToString:[[dict objectForKey:@"team"] stringByDeletingPathExtension]])
--- a/project_files/HedgewarsMobile/Hedgewars.xcodeproj/project.pbxproj	Sun Apr 01 15:23:34 2012 +0200
+++ b/project_files/HedgewarsMobile/Hedgewars.xcodeproj/project.pbxproj	Wed May 02 23:53:45 2012 +0200
@@ -69,8 +69,8 @@
 		611E0EE711FB20610077A41E /* ammoButton.png in Resources */ = {isa = PBXBuildFile; fileRef = 611E0EE511FB20610077A41E /* ammoButton.png */; };
 		611E0EE811FB20610077A41E /* cornerButton.png in Resources */ = {isa = PBXBuildFile; fileRef = 611E0EE611FB20610077A41E /* cornerButton.png */; };
 		611E12FF117BBBDA0044B62F /* Entitlements-Development.plist in Resources */ = {isa = PBXBuildFile; fileRef = 611E12FE117BBBDA0044B62F /* Entitlements-Development.plist */; };
-		611EE974122A9C4100DF6938 /* clickSound.wav in Resources */ = {isa = PBXBuildFile; fileRef = 611EE973122A9C4100DF6938 /* clickSound.wav */; };
-		611EE9DA122AA10A00DF6938 /* selSound.wav in Resources */ = {isa = PBXBuildFile; fileRef = 611EE9D8122AA10A00DF6938 /* selSound.wav */; };
+		611EE974122A9C4100DF6938 /* clickSound.caf in Resources */ = {isa = PBXBuildFile; fileRef = 611EE973122A9C4100DF6938 /* clickSound.caf */; };
+		611EE9DA122AA10A00DF6938 /* selSound.caf in Resources */ = {isa = PBXBuildFile; fileRef = 611EE9D8122AA10A00DF6938 /* selSound.caf */; };
 		611EEAEE122B2A4D00DF6938 /* HelpPageInGameViewController.m in Sources */ = {isa = PBXBuildFile; fileRef = 611EEAEC122B2A4D00DF6938 /* HelpPageInGameViewController.m */; };
 		611EEAEF122B2A4D00DF6938 /* HelpPageLobbyViewController-iPad.xib in Resources */ = {isa = PBXBuildFile; fileRef = 611EEAED122B2A4D00DF6938 /* HelpPageLobbyViewController-iPad.xib */; };
 		611EEBC1122B34A800DF6938 /* helpingame.png in Resources */ = {isa = PBXBuildFile; fileRef = 611EEBC0122B34A800DF6938 /* helpingame.png */; };
@@ -190,7 +190,7 @@
 		6179883C114AA34C00BA94A9 /* uVisualGears.pas in Sources */ = {isa = PBXBuildFile; fileRef = 6179880E114AA34C00BA94A9 /* uVisualGears.pas */; };
 		6179883D114AA34C00BA94A9 /* uWorld.pas in Sources */ = {isa = PBXBuildFile; fileRef = 6179880F114AA34C00BA94A9 /* uWorld.pas */; };
 		61798935114AB25F00BA94A9 /* AudioToolbox.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = 61798934114AB25F00BA94A9 /* AudioToolbox.framework */; };
-		61808A5D128C930A005D0E2F /* backSound.wav in Resources */ = {isa = PBXBuildFile; fileRef = 611EE9D7122AA10A00DF6938 /* backSound.wav */; };
+		61808A5D128C930A005D0E2F /* backSound.caf in Resources */ = {isa = PBXBuildFile; fileRef = 611EE9D7122AA10A00DF6938 /* backSound.caf */; };
 		61842B24122B619D0096E335 /* HelpPageInGameViewController-iPad.xib in Resources */ = {isa = PBXBuildFile; fileRef = 61842B23122B619D0096E335 /* HelpPageInGameViewController-iPad.xib */; };
 		61842B3E122B65BD0096E335 /* helpabove.png in Resources */ = {isa = PBXBuildFile; fileRef = 61842B3D122B65BD0096E335 /* helpabove.png */; };
 		61842B40122B66280096E335 /* helpleft.png in Resources */ = {isa = PBXBuildFile; fileRef = 61842B3F122B66280096E335 /* helpleft.png */; };
@@ -416,9 +416,9 @@
 		611E0EE511FB20610077A41E /* ammoButton.png */ = {isa = PBXFileReference; lastKnownFileType = image.png; name = ammoButton.png; path = Resources/Overlay/ammoButton.png; sourceTree = "<group>"; };
 		611E0EE611FB20610077A41E /* cornerButton.png */ = {isa = PBXFileReference; lastKnownFileType = image.png; name = cornerButton.png; path = Resources/Overlay/cornerButton.png; sourceTree = "<group>"; };
 		611E12FE117BBBDA0044B62F /* Entitlements-Development.plist */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = text.plist.xml; path = "Entitlements-Development.plist"; sourceTree = "<group>"; };
-		611EE973122A9C4100DF6938 /* clickSound.wav */ = {isa = PBXFileReference; lastKnownFileType = audio.wav; name = clickSound.wav; path = Resources/clickSound.wav; sourceTree = "<group>"; };
-		611EE9D7122AA10A00DF6938 /* backSound.wav */ = {isa = PBXFileReference; lastKnownFileType = audio.wav; name = backSound.wav; path = Resources/backSound.wav; sourceTree = "<group>"; };
-		611EE9D8122AA10A00DF6938 /* selSound.wav */ = {isa = PBXFileReference; lastKnownFileType = audio.wav; name = selSound.wav; path = Resources/selSound.wav; sourceTree = "<group>"; };
+		611EE973122A9C4100DF6938 /* clickSound.caf */ = {isa = PBXFileReference; lastKnownFileType = file; name = clickSound.caf; path = Resources/clickSound.caf; sourceTree = "<group>"; };
+		611EE9D7122AA10A00DF6938 /* backSound.caf */ = {isa = PBXFileReference; lastKnownFileType = file; name = backSound.caf; path = Resources/backSound.caf; sourceTree = "<group>"; };
+		611EE9D8122AA10A00DF6938 /* selSound.caf */ = {isa = PBXFileReference; lastKnownFileType = file; name = selSound.caf; path = Resources/selSound.caf; sourceTree = "<group>"; };
 		611EEAEB122B2A4D00DF6938 /* HelpPageInGameViewController.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = HelpPageInGameViewController.h; sourceTree = "<group>"; };
 		611EEAEC122B2A4D00DF6938 /* HelpPageInGameViewController.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = HelpPageInGameViewController.m; sourceTree = "<group>"; };
 		611EEAED122B2A4D00DF6938 /* HelpPageLobbyViewController-iPad.xib */ = {isa = PBXFileReference; lastKnownFileType = file.xib; path = "HelpPageLobbyViewController-iPad.xib"; sourceTree = "<group>"; };
@@ -891,9 +891,9 @@
 			isa = PBXGroup;
 			children = (
 				612CABC71391D3CC005E9596 /* hwclassic.mp3 */,
-				611EE973122A9C4100DF6938 /* clickSound.wav */,
-				611EE9D7122AA10A00DF6938 /* backSound.wav */,
-				611EE9D8122AA10A00DF6938 /* selSound.wav */,
+				611EE973122A9C4100DF6938 /* clickSound.caf */,
+				611EE9D7122AA10A00DF6938 /* backSound.caf */,
+				611EE9D8122AA10A00DF6938 /* selSound.caf */,
 			);
 			name = Sounds;
 			sourceTree = "<group>";
@@ -1516,8 +1516,8 @@
 				615AD96212073B4D00F2FF04 /* startGameButton.png in Resources */,
 				615AD9E9120764CA00F2FF04 /* backButton.png in Resources */,
 				615AD9EB1207654E00F2FF04 /* helpButton.png in Resources */,
-				611EE974122A9C4100DF6938 /* clickSound.wav in Resources */,
-				611EE9DA122AA10A00DF6938 /* selSound.wav in Resources */,
+				611EE974122A9C4100DF6938 /* clickSound.caf in Resources */,
+				611EE9DA122AA10A00DF6938 /* selSound.caf in Resources */,
 				611EEAEF122B2A4D00DF6938 /* HelpPageLobbyViewController-iPad.xib in Resources */,
 				611EEBC1122B34A800DF6938 /* helpingame.png in Resources */,
 				611EEBC4122B355700DF6938 /* helpbottom.png in Resources */,
@@ -1538,7 +1538,7 @@
 				61E2F7451283752C00E12521 /* tw.png in Resources */,
 				61DF0EDC1284DF2300F3F10B /* HelpPageLobbyViewController-iPhone.xib in Resources */,
 				61DF0F211284F72A00F3F10B /* HelpPageInGameViewController-iPhone.xib in Resources */,
-				61808A5D128C930A005D0E2F /* backSound.wav in Resources */,
+				61808A5D128C930A005D0E2F /* backSound.caf in Resources */,
 				61D3D2A51290E03A003CE7C3 /* irc.png in Resources */,
 				6172FED91298CF9800D73365 /* background~iphone.png in Resources */,
 				6172FEEF1298D25D00D73365 /* mediumBackground~ipad.png in Resources */,
@@ -1875,6 +1875,7 @@
 		61022D7C12305A2800B08935 /* Distro AppStore */ = {
 			isa = XCBuildConfiguration;
 			buildSettings = {
+				ALWAYS_SEARCH_USER_PATHS = NO;
 				APPLY_RULES_IN_COPY_FILES = YES;
 				ARCHS = "$(ARCHS_STANDARD_32_BIT)";
 				CODE_SIGN_IDENTITY = "iPhone Distribution";
@@ -1887,13 +1888,34 @@
 				FPC_UNITS_PATH = "-Fu\"$(PROJECT_DIR)\"";
 				GCC_C_LANGUAGE_STANDARD = c99;
 				GCC_DEBUGGING_SYMBOLS = default;
+				GCC_DYNAMIC_NO_PIC = NO;
 				GCC_FAST_MATH = YES;
 				GCC_OPTIMIZATION_LEVEL = s;
 				GCC_PREPROCESSOR_DEFINITIONS = "";
 				GCC_STRICT_ALIASING = YES;
 				GCC_THUMB_SUPPORT = NO;
 				GCC_VERSION = com.apple.compilers.llvm.clang.1_0;
+				GCC_WARN_64_TO_32_BIT_CONVERSION = YES;
+				GCC_WARN_ABOUT_MISSING_FIELD_INITIALIZERS = YES;
+				GCC_WARN_ABOUT_MISSING_NEWLINE = YES;
+				GCC_WARN_ABOUT_MISSING_PROTOTYPES = NO;
 				GCC_WARN_ABOUT_RETURN_TYPE = YES;
+				GCC_WARN_CHECK_SWITCH_STATEMENTS = YES;
+				GCC_WARN_FOUR_CHARACTER_CONSTANTS = YES;
+				GCC_WARN_INITIALIZER_NOT_FULLY_BRACKETED = YES;
+				GCC_WARN_MISSING_PARENTHESES = YES;
+				GCC_WARN_NON_VIRTUAL_DESTRUCTOR = YES;
+				GCC_WARN_PEDANTIC = YES;
+				GCC_WARN_SHADOW = YES;
+				GCC_WARN_SIGN_COMPARE = YES;
+				GCC_WARN_STRICT_SELECTOR_MATCH = YES;
+				GCC_WARN_UNDECLARED_SELECTOR = YES;
+				GCC_WARN_UNINITIALIZED_AUTOS = NO;
+				GCC_WARN_UNKNOWN_PRAGMAS = YES;
+				GCC_WARN_UNUSED_FUNCTION = YES;
+				GCC_WARN_UNUSED_LABEL = YES;
+				GCC_WARN_UNUSED_PARAMETER = NO;
+				GCC_WARN_UNUSED_VALUE = YES;
 				GCC_WARN_UNUSED_VARIABLE = YES;
 				HEADER_SEARCH_PATHS = (
 					"\"$(SRCROOT)/../../../Library/SDL/src/video\"/**",
@@ -1916,6 +1938,12 @@
 				TARGETED_DEVICE_FAMILY = "1,2";
 				VALIDATE_PRODUCT = YES;
 				VALID_ARCHS = "armv7 armv6";
+				WARNING_CFLAGS = (
+					"-Wall",
+					"-Wbad-function-cast",
+					"-Wmissing-declarations",
+					"-Wnested-externs",
+				);
 			};
 			name = "Distro AppStore";
 		};
@@ -1956,6 +1984,7 @@
 		6137064B117B1CB3004EE44A /* Distro Adhoc */ = {
 			isa = XCBuildConfiguration;
 			buildSettings = {
+				ALWAYS_SEARCH_USER_PATHS = NO;
 				APPLY_RULES_IN_COPY_FILES = YES;
 				ARCHS = "$(ARCHS_STANDARD_32_BIT)";
 				CODE_SIGN_ENTITLEMENTS = "Entitlements-Distribution.plist";
@@ -1969,13 +1998,34 @@
 				FPC_UNITS_PATH = "-Fu\"$(PROJECT_DIR)\"";
 				GCC_C_LANGUAGE_STANDARD = c99;
 				GCC_DEBUGGING_SYMBOLS = full;
+				GCC_DYNAMIC_NO_PIC = YES;
 				GCC_FAST_MATH = YES;
 				GCC_OPTIMIZATION_LEVEL = 0;
 				GCC_PREPROCESSOR_DEFINITIONS = DEBUG;
 				GCC_STRICT_ALIASING = YES;
 				GCC_THUMB_SUPPORT = NO;
 				GCC_VERSION = com.apple.compilers.llvm.clang.1_0;
+				GCC_WARN_64_TO_32_BIT_CONVERSION = YES;
+				GCC_WARN_ABOUT_MISSING_FIELD_INITIALIZERS = YES;
+				GCC_WARN_ABOUT_MISSING_NEWLINE = YES;
+				GCC_WARN_ABOUT_MISSING_PROTOTYPES = NO;
 				GCC_WARN_ABOUT_RETURN_TYPE = YES;
+				GCC_WARN_CHECK_SWITCH_STATEMENTS = YES;
+				GCC_WARN_FOUR_CHARACTER_CONSTANTS = YES;
+				GCC_WARN_INITIALIZER_NOT_FULLY_BRACKETED = YES;
+				GCC_WARN_MISSING_PARENTHESES = YES;
+				GCC_WARN_NON_VIRTUAL_DESTRUCTOR = YES;
+				GCC_WARN_PEDANTIC = YES;
+				GCC_WARN_SHADOW = YES;
+				GCC_WARN_SIGN_COMPARE = YES;
+				GCC_WARN_STRICT_SELECTOR_MATCH = YES;
+				GCC_WARN_UNDECLARED_SELECTOR = YES;
+				GCC_WARN_UNINITIALIZED_AUTOS = NO;
+				GCC_WARN_UNKNOWN_PRAGMAS = YES;
+				GCC_WARN_UNUSED_FUNCTION = YES;
+				GCC_WARN_UNUSED_LABEL = YES;
+				GCC_WARN_UNUSED_PARAMETER = NO;
+				GCC_WARN_UNUSED_VALUE = YES;
 				GCC_WARN_UNUSED_VARIABLE = YES;
 				HEADER_SEARCH_PATHS = (
 					"\"$(SRCROOT)/../../../Library/SDL/src/video\"/**",
@@ -1996,6 +2046,12 @@
 				TARGETED_DEVICE_FAMILY = "1,2";
 				VALIDATE_PRODUCT = YES;
 				VALID_ARCHS = "armv7 armv6";
+				WARNING_CFLAGS = (
+					"-Wall",
+					"-Wbad-function-cast",
+					"-Wmissing-declarations",
+					"-Wnested-externs",
+				);
 			};
 			name = "Distro Adhoc";
 		};
@@ -2080,6 +2136,7 @@
 		C01FCF4F08A954540054247B /* Debug */ = {
 			isa = XCBuildConfiguration;
 			buildSettings = {
+				ALWAYS_SEARCH_USER_PATHS = NO;
 				APPLY_RULES_IN_COPY_FILES = YES;
 				ARCHS = "$(ARCHS_STANDARD_32_BIT)";
 				CODE_SIGN_IDENTITY = "iPhone Developer";
@@ -2093,13 +2150,34 @@
 				FPC_UNITS_PATH = "-Fu\"$(PROJECT_DIR)\"";
 				GCC_C_LANGUAGE_STANDARD = c99;
 				GCC_DEBUGGING_SYMBOLS = full;
+				GCC_DYNAMIC_NO_PIC = NO;
 				GCC_FAST_MATH = YES;
 				GCC_OPTIMIZATION_LEVEL = 0;
 				GCC_PREPROCESSOR_DEFINITIONS = DEBUG;
 				GCC_STRICT_ALIASING = YES;
 				GCC_THUMB_SUPPORT = NO;
 				GCC_VERSION = com.apple.compilers.llvm.clang.1_0;
+				GCC_WARN_64_TO_32_BIT_CONVERSION = YES;
+				GCC_WARN_ABOUT_MISSING_FIELD_INITIALIZERS = YES;
+				GCC_WARN_ABOUT_MISSING_NEWLINE = YES;
+				GCC_WARN_ABOUT_MISSING_PROTOTYPES = NO;
 				GCC_WARN_ABOUT_RETURN_TYPE = YES;
+				GCC_WARN_CHECK_SWITCH_STATEMENTS = YES;
+				GCC_WARN_FOUR_CHARACTER_CONSTANTS = YES;
+				GCC_WARN_INITIALIZER_NOT_FULLY_BRACKETED = YES;
+				GCC_WARN_MISSING_PARENTHESES = YES;
+				GCC_WARN_NON_VIRTUAL_DESTRUCTOR = YES;
+				GCC_WARN_PEDANTIC = YES;
+				GCC_WARN_SHADOW = YES;
+				GCC_WARN_SIGN_COMPARE = YES;
+				GCC_WARN_STRICT_SELECTOR_MATCH = YES;
+				GCC_WARN_UNDECLARED_SELECTOR = YES;
+				GCC_WARN_UNINITIALIZED_AUTOS = NO;
+				GCC_WARN_UNKNOWN_PRAGMAS = YES;
+				GCC_WARN_UNUSED_FUNCTION = YES;
+				GCC_WARN_UNUSED_LABEL = YES;
+				GCC_WARN_UNUSED_PARAMETER = NO;
+				GCC_WARN_UNUSED_VALUE = YES;
 				GCC_WARN_UNUSED_VARIABLE = YES;
 				HEADER_SEARCH_PATHS = (
 					"\"$(SRCROOT)/../../../Library/SDL/src/video\"/**",
@@ -2120,12 +2198,19 @@
 				TARGETED_DEVICE_FAMILY = "1,2";
 				VALIDATE_PRODUCT = NO;
 				VALID_ARCHS = "armv7 armv6";
+				WARNING_CFLAGS = (
+					"-Wall",
+					"-Wbad-function-cast",
+					"-Wmissing-declarations",
+					"-Wnested-externs",
+				);
 			};
 			name = Debug;
 		};
 		C01FCF5008A954540054247B /* Release */ = {
 			isa = XCBuildConfiguration;
 			buildSettings = {
+				ALWAYS_SEARCH_USER_PATHS = NO;
 				APPLY_RULES_IN_COPY_FILES = YES;
 				ARCHS = "$(ARCHS_STANDARD_32_BIT)";
 				CODE_SIGN_ENTITLEMENTS = "Entitlements-Development.plist";
@@ -2139,13 +2224,34 @@
 				FPC_UNITS_PATH = "-Fu\"$(PROJECT_DIR)\"";
 				GCC_C_LANGUAGE_STANDARD = c99;
 				GCC_DEBUGGING_SYMBOLS = default;
+				GCC_DYNAMIC_NO_PIC = YES;
 				GCC_FAST_MATH = YES;
 				GCC_OPTIMIZATION_LEVEL = s;
 				GCC_PREPROCESSOR_DEFINITIONS = DEBUG;
 				GCC_STRICT_ALIASING = YES;
 				GCC_THUMB_SUPPORT = NO;
 				GCC_VERSION = com.apple.compilers.llvm.clang.1_0;
+				GCC_WARN_64_TO_32_BIT_CONVERSION = YES;
+				GCC_WARN_ABOUT_MISSING_FIELD_INITIALIZERS = YES;
+				GCC_WARN_ABOUT_MISSING_NEWLINE = YES;
+				GCC_WARN_ABOUT_MISSING_PROTOTYPES = NO;
 				GCC_WARN_ABOUT_RETURN_TYPE = YES;
+				GCC_WARN_CHECK_SWITCH_STATEMENTS = YES;
+				GCC_WARN_FOUR_CHARACTER_CONSTANTS = YES;
+				GCC_WARN_INITIALIZER_NOT_FULLY_BRACKETED = YES;
+				GCC_WARN_MISSING_PARENTHESES = YES;
+				GCC_WARN_NON_VIRTUAL_DESTRUCTOR = YES;
+				GCC_WARN_PEDANTIC = YES;
+				GCC_WARN_SHADOW = YES;
+				GCC_WARN_SIGN_COMPARE = YES;
+				GCC_WARN_STRICT_SELECTOR_MATCH = YES;
+				GCC_WARN_UNDECLARED_SELECTOR = YES;
+				GCC_WARN_UNINITIALIZED_AUTOS = NO;
+				GCC_WARN_UNKNOWN_PRAGMAS = YES;
+				GCC_WARN_UNUSED_FUNCTION = YES;
+				GCC_WARN_UNUSED_LABEL = YES;
+				GCC_WARN_UNUSED_PARAMETER = NO;
+				GCC_WARN_UNUSED_VALUE = YES;
 				GCC_WARN_UNUSED_VARIABLE = YES;
 				HEADER_SEARCH_PATHS = (
 					"\"$(SRCROOT)/../../../Library/SDL/src/video\"/**",
@@ -2167,6 +2273,12 @@
 				TARGETED_DEVICE_FAMILY = "1,2";
 				VALIDATE_PRODUCT = NO;
 				VALID_ARCHS = "armv7 armv6";
+				WARNING_CFLAGS = (
+					"-Wall",
+					"-Wbad-function-cast",
+					"-Wmissing-declarations",
+					"-Wnested-externs",
+				);
 			};
 			name = Release;
 		};
--- a/project_files/HedgewarsMobile/Hedgewars_Prefix.pch	Sun Apr 01 15:23:34 2012 +0200
+++ b/project_files/HedgewarsMobile/Hedgewars_Prefix.pch	Wed May 02 23:53:45 2012 +0200
@@ -31,6 +31,5 @@
 #import "CreationChamber.h"
 #import "HWUtils.h"
 #import "hwconsts.h"
-#import "SDL_net.h"
 #endif
 
Binary file project_files/HedgewarsMobile/Resources/backSound.caf has changed
Binary file project_files/HedgewarsMobile/Resources/backSound.wav has changed
Binary file project_files/HedgewarsMobile/Resources/clickSound.caf has changed
Binary file project_files/HedgewarsMobile/Resources/clickSound.wav has changed
Binary file project_files/HedgewarsMobile/Resources/selSound.caf has changed
Binary file project_files/HedgewarsMobile/Resources/selSound.wav has changed
--- a/project_files/hedgewars.pro	Sun Apr 01 15:23:34 2012 +0200
+++ b/project_files/hedgewars.pro	Wed May 02 23:53:45 2012 +0200
@@ -22,7 +22,8 @@
 QT += network
 QT += webkit
 
-HEADERS += ../QTfrontend/model/themesmodel.h \
+HEADERS += ../QTfrontend/model/ThemeModel.h \
+    ../QTfrontend/model/MapModel.h \
     ../QTfrontend/model/ammoSchemeModel.h \
     ../QTfrontend/model/netserverslist.h \
     ../QTfrontend/model/hats.h \
@@ -72,7 +73,7 @@
     ../QTfrontend/ui/widget/mapContainer.h \
     ../QTfrontend/ui/widget/HistoryLineEdit.h \
     ../QTfrontend/ui/widget/SmartLineEdit.h \
-    ../QTfrontend/util/HWDataManager.h \
+    ../QTfrontend/util/DataManager.h \
     ../QTfrontend/net/netregister.h \
     ../QTfrontend/net/netserver.h \
     ../QTfrontend/net/netudpwidget.h \
@@ -100,10 +101,12 @@
     ../QTfrontend/ui/qpushbuttonwithsound.h \
     ../QTfrontend/ui/widget/qpushbuttonwithsound.h \
     ../QTfrontend/ui/page/pagefeedback.h \
-    ../QTfrontend/model/roomslistmodel.h
+    ../QTfrontend/model/roomslistmodel.h \
+    ../QTfrontend/ui/dialog/input_password.h
 
 SOURCES += ../QTfrontend/model/ammoSchemeModel.cpp \
-    ../QTfrontend/model/themesmodel.cpp \
+    ../QTfrontend/model/MapModel.cpp \
+    ../QTfrontend/model/ThemeModel.cpp \
     ../QTfrontend/model/hats.cpp \
     ../QTfrontend/model/netserverslist.cpp \
     ../QTfrontend/ui/qaspectratiolayout.cpp \
@@ -152,7 +155,7 @@
     ../QTfrontend/ui/widget/mapContainer.cpp \
     ../QTfrontend/ui/widget/HistoryLineEdit.cpp \
     ../QTfrontend/ui/widget/SmartLineEdit.cpp \
-    ../QTfrontend/util/HWDataManager.cpp \
+    ../QTfrontend/util/DataManager.cpp \
     ../QTfrontend/net/tcpBase.cpp \
     ../QTfrontend/net/netregister.cpp \
     ../QTfrontend/net/proto.cpp \
@@ -178,7 +181,8 @@
     ../QTfrontend/ui/mouseoverfilter.cpp \
     ../QTfrontend/ui/widget/qpushbuttonwithsound.cpp \
     ../QTfrontend/ui/page/pagefeedback.cpp \
-    ../QTfrontend/model/roomslistmodel.cpp
+    ../QTfrontend/model/roomslistmodel.cpp \
+    ../QTfrontend/ui/dialog/input_password.cpp
 
 win32 {
     SOURCES += ../QTfrontend/xfire.cpp
--- a/share/hedgewars/Data/Locale/cs.txt	Sun Apr 01 15:23:34 2012 +0200
+++ b/share/hedgewars/Data/Locale/cs.txt	Wed May 02 23:53:45 2012 +0200
@@ -52,6 +52,10 @@
 00:49=Oživovač
 00:50=Vrtákový útok
 00:51=Hrouda bláta
+00:52=Není vybrána žádná zbraň
+00:53=TimeBox
+00:54=Struktura
+00:55=Pozemek s rozprašovačem
 
 01:00=Do boje!
 01:01=Kolo nerozhodně
@@ -68,6 +72,12 @@
 01:12=Poslední kolo před Náhlou smrtí!
 01:13=%1 kol do Náhlé smrti!
 01:14=Připrav se, %1!
+01:15=Nepatrný
+01:16=Nízký
+01:17=Normální
+01:18=Vysoký
+01:19=Extrémní
+01:20=%1 odskočit
 
 ; Event messages
 ; Hog (%1) died
@@ -175,7 +185,7 @@
 02:01=%1 má v ranách slanou vodu
 02:01=%1 šel po prkně
 02:01=%1 si dává koupel
-02:01=%1 je moc moc moc mokrý
+02:01=%1 je moc moc moc mokrý
 02:01=%1 si namočil bodliny
 02:01=%1 našel truhlu Mrtvého muže
 
@@ -434,6 +444,11 @@
 03:48=Čas na kladivo!
 03:49=Dělá to, co myslíš
 03:50=Krtkův fanda
+03:51=Nalezeno na zemi
+03:52=NEPOUŽITO
+03:53=Typ 40
+03:54=Vytvořit něco
+03:55=Užitečnost
 
 ; Weapon Descriptions (use | as line breaks)
 04:00=Zaútoč na nepřítele pomocí obyčejného granátu.|Exploduje jakmile časovač dojde k nule.|1-5: Nastavuje časovač|Útok: Drž pro hození větší silou
@@ -487,6 +502,12 @@
 04:47=Zdvojnásob zábavu pomocí dvou ostnatých, zákeřných, lepkavých|min. Vytvoř řetězovou reakci nebo se braň (nebo oboje!)|Útok: Drž pro hození větší silou (dvakrát)
 04:48=Proč by se měli týrat jen krtci? Mlácení ježků může|být stejná zábava! Jedna dobrá rána tímhle kladivem|uštědří poškození za jednu třetinu ježkova zdraví a|zarazí ho pod zem.|Útok: Aktivace
 04:49=Vzkřis své přátele! Ale měj se na pozoru, protože|tohle vzkřísí i tvé protivníky.|Útok: Drž stisknuto pro pomalé oživování|Nahoru: Zrychlí oživování
+04:50=Je někdo skrývá v podzemí?|Vykopat s vrtačkou stávky!|Časovač určuje, jak daleko to bude kopat.
+04:51=Získat ve volném záběru vrhá kouli bláta.|Žihadla bit, a srazí prasata zpět.
+04:52=NEPOUŽITO
+04:53=Vydejte se na dobrodružství v čase a prostoru,|přičemž vaši kamarádi bojovat dál sám.|Být připraven vrátit kdykoliv,|nebo náhlé smrti nebo pokud jsou všichni poraženi.|Prohlášení. Nefunguje v náhlé smrti,|Pokud jste sami, nebo jste-li král.
+04:54=NEÚPLNÝ                  
+04:55=Sprej proud lepkavými vločkami.|Stavět mosty, pohřbít nepřátele, utěsnění tunely.|Buďte opatrní, nechcete dostat každý z vás!
 
 ; Game goal strings
 05:00=Herní módy
@@ -510,3 +531,4 @@
 05:18=Neomezeně útoků
 05:19=Zbraně jsou obnoveny na konci tahu
 05:20=Zbraně nejsou sdíleny mezi ježky
+05:21=Tag týmu: Týmy v klanu se postupně střídají|Sdílené čas: Týmy v rámci podílu klan zase čas
--- a/share/hedgewars/Data/Locale/de.txt	Sun Apr 01 15:23:34 2012 +0200
+++ b/share/hedgewars/Data/Locale/de.txt	Wed May 02 23:53:45 2012 +0200
@@ -103,6 +103,47 @@
 02:00=%1 war einmal.
 02:00=%1 hat wohl versagt.
 02:00=Mach's gut, %1!
+02:00=%1 hinterlässt eine Frau und Kind
+02:00=%1 ins Leben gerufen hat seine letzte Panzerfaust
+02:00=%1 hat seine letzte Granate geworfen
+02:00=%1 hat seine letzte Kuchen gebacken
+02:00=%1 hat auf seiner letzten Seil schwangen
+02:00=%1 genannt hat seinen letzten Luftangriff
+02:00=%1 gepumpt hat seine letzte Schrotflinte
+02:00=%1 geworfen hat seine letzte Melone
+02:00=%1 gezogen hat seinen letzten deagle
+02:00=%1 nahm einen Schuss zu viel
+02:00=%1 könnte wirklich eine gesundheitliche Kiste verwendet haben
+02:00=%1 gegangen ist, um ein besseres Spiel zu spielen
+02:00=%1 hat ragequit Leben
+02:00=%1 scheitert
+02:00=Schlecht schlecht %1...
+02:00=%1 lieber Warmux
+02:00=%1 wurde blockiert Schüsse mit seinem Gesicht
+02:00=%1 ist ein Held unter mir ... err ... Schweine
+02:00=%1 findet seinen Platz in der Walhalla
+02:00=%1 hat das Gebäude verlassen
+02:00=%1 geht den Weg der Dinosaurier
+02:00=%1 Igel bringt, einen Schritt näher zum Aussterben
+02:00=%1 bringt eine Träne zu mir ins Auge
+02:00=%1 ist ein Ex-Schwein
+02:00=%1 wird die Radieschen
+02:00=%1 hat aufgehört zu sein
+02:00=Verabschieden Sie sich von %1
+02:00=Keine Hoffnung mehr für %1
+02:00=%1 steht vor der letzte Vorhang
+02:00=Rauchen, wenn du hast, %1
+02:00=%1 erleidet einen spontanen massiven Vorhandensein Ausfall
+02:00=%1 weitergegeben hat
+02:00=%1 ist mausetot
+02:00=%1 nicht mehr
+02:00=%1 abgelaufen
+02:00=Beraubt des Lebens, %1 ruht in Frieden
+02:00=%1 tritt der Chor unsichtbar
+02:00=Abschied %1, wussten wir kaum ye!
+02:00=%1 hatte eine geringe Toleranz für erschossen
+02:00=%1 hätte verwenden können ein zusätzliches Leben
+02:00=Gibt es einen Arzt im Haus?
 
 ; Hog (%1) drowned
 02:01=%1 geht auf Tauchstation!
@@ -127,6 +168,51 @@
 02:01=%1 erliegt dem Sog der Tiefe!
 02:01=%1 geht der Sache auf den Grund!
 02:01=%1 wäre fast verdurstet!
+02:01=%1 checkt das tiefe Ende
+02:01=%1 geht gluck gluck gluck
+02:01=%1 geht Spritzer
+02:01=%1 vergaß seine Armbinden
+02:01=%1 wirklich genommen haben sollte Schwimmunterricht
+02:01=%1 verließ seinem Surfbrett zu Hause
+02:01=%1 wird gewaschen, bis
+02:01=%1 ist ein Schwein matschig
+02:01=%1 vergessen, sein Leben zu bringen Jacke
+02:01=%1 geht Splish Spritzer
+02:01=%1 wird mit den Fischen schlafen
+02:01=%1 denkt das Wasser saugen Physik in diesem Spiel
+02:01=%1 sieht durstig
+02:01=Das Meer behauptet %1
+02:01=%1 wird auf dem Meer verschollen
+02:01=%1 sollten mitgebracht haben seine Tauchausrüstung
+02:01=%1 bekommt eine Bestattung auf See
+02:01=%1 hat, dass die sinkenden Gefühl
+02:01=%1 übt seine Rückenschwimmen
+02:01=%1 geht auf der Suche nach der Titanic
+02:01=%1 ist nicht Jesus
+02:01=%1 wird Findet Nemo
+02:01=%1 ein Leck
+02:01=Du mußt fragen, wie viele Schweine sind da unten
+02:01=%1 macht das Meer etwas höher
+02:01=%1 nicht in der Marine zu gewinnen
+02:01=%1 tut sein Identitätswechsel von einem toten Fisch
+02:01=Zumindest ging nicht in die Toilette, %1
+02:01=Sonic nicht schwimmen konnte und kann weder %1
+02:01=%1 will spielen Ecco the Dolphin
+02:01=%1, Aquaria ist gegangen, um zu besuchen
+02:01=%1 hat festgestellt, die verlorene Stadt Atlantis
+02:01=%1 Ziele für die Hauptrolle in Bioshock 3
+02:01=Ihre doggy Paddel könnte ein wenig Arbeit, %1
+02:01=%1 sollten mitgebracht haben einen Jet-Ski
+02:01=%1 mag es nicht, Wassersport
+02:01=%1 wird forever blowing bubbles
+02:01=%1 ist kurz von einem Floß
+02:01=%1 denkt Salzwasser ist gut für die Haut
+02:01=%1 bekommt Salzwasser in seine Wunden
+02:01=%1 hat ging die Planke
+02:01=%1 verfügt über eine Badewanne
+02:01=%1 ist nass nass nass
+02:01=%1 bekommt seine Federkiele nass
+02:01=Es ist Davy Jones 'locker für %1
 
 ; Round starts
 02:02=Auf in die Schlacht!
@@ -135,6 +221,55 @@
 02:02=Los geht's!
 02:02=Alles angetreten!
 02:02=Los, los, los!
+02:02=Lassen Sie uns dies Partei beginnen
+02:02=Letzte Schwein steht gewinnt
+02:02=Gehen wir!
+02:02=Lasst uns rocken!
+02:02=Lassen Sie uns jam!
+02:02=Es ist Anfang ...
+02:02=Dies ist der Beginn von etwas Großem
+02:02=Willkommen bei Hedgewars
+02:02=Willkommen auf der Front
+02:02=Crush deine Feinde!
+02:02=Mai die beste Schwein Sieg
+02:02=Sieg oder Tod
+02:02=Dem Sieger geht die Beute
+02:02=Verlieren ist keine Option
+02:02=Cry Havoc! Lassen Sie verlieren die Schweine des Krieges!
+02:02=Hedgewars, die Ihnen von Hedgewars.org
+02:02=GL HF
+02:02=Nur sich glücklich schätzen du bist nicht gegen Tiyuri
+02:02=Nur sich glücklich schätzen du bist nicht gegen unC0Rr
+02:02=Nur sich glücklich schätzen du bist nicht gegen Nemo
+02:02=Nur sich glücklich schätzen du bist nicht gegen Smaxx
+02:02=Nur sich glücklich schätzen du bist nicht gegen Jessor
+02:02=Gib alles!
+02:02=Die Verlierer machen die Reinigung auf!
+02:02=Lassen Sie den Kampf des Jahrtausends beginnen
+02:02=Lassen Sie den Kampf des Jahrhunderts beginnen
+02:02=Lassen Sie den Kampf des Jahrzehnts beginnen
+02:02=Lassen Sie den Kampf des Jahres beginnen
+02:02=Lassen Sie den Kampf des Monats beginnen
+02:02=Lassen Sie den Kampf in der Woche beginnen
+02:02=Lassen Sie den Kampf des Tages beginnen
+02:02=Lassen Sie den Kampf der Stunde beginnen
+02:02=Tun Sie Ihr Bestes!
+02:02=Zerstöre den Feind!
+02:02=Viel Glück
+02:02=Viel Spaß
+02:02=Kämpfe den guten Kampf
+02:02=Kampf schmutzig
+02:02=Kampf mit Ehre
+02:02=Gib nicht auf
+02:02=Never surrender
+02:02=Rock und Socke!
+02:02=Lassen Sie den fragfest beginnen!
+02:02=Ich hoffe du bist bereit für einen Kampf!
+02:02=Gehen gehen!
+02:02=Igel Voraus!
+02:02=Bringt es ihnen!
+02:02=Habt keine Angst!
+02:02=Seien Sie mutig und erobern
 
 ; Round ends (win; unused atm)
 02:03=...
@@ -148,6 +283,16 @@
 02:05=Das kommt gelegen!
 02:05=Jemand denkt an euch!
 02:05=Mit Liebe verpackt?
+02:05=Frisches Pflaster!
+02:05=So werden Sie sich besser fühlen
+02:05=Ein Hallo-Trank! Whoops falsche Spiel
+02:05=Ein wählen mir oben!
+02:05=Zugreifen
+02:05=Ein gesunder Snack
+02:05=Ein Mittel, um Schmerzen
+02:05=Richtige Dosierung: so viele wie du finden kannst!
+02:05=Schnelle Lieferung
+02:05=Vorräte!
 
 ; New ammo crate
 02:06=Nachschub!
@@ -155,6 +300,22 @@
 02:06=Was wohl darin ist?
 02:06=Bringt das die Wende?
 02:06=Tod aus der Luft!
+02:06=Ein Geschenk!
+02:06=Spezielle Lieferung!
+02:06=Es war ein Alptraum bekommen dies durch den Zoll
+02:06=Destruktive Spielzeug aus dem Himmel
+02:06=Warnung! Inhalt Flüchtige
+02:06=Wählen es oder blasen sie auf, ist Qual der Wahl
+02:06=Extras!
+02:06=Mmm Munition
+02:06=Eine Schachtel zerstörerische Kraft
+02:06=Luftpost!
+02:06=Was auch immer ist in diesem Feld ist es nicht Pizza
+02:06=Bekommen!
+02:06=Waffe fallen zu lassen eingehende
+02:06=Lassen Sie sich nicht, dass der Feind schnappen!
+02:06=Shiny neues Spielzeug!
+02:06=Eine geheimnisvolle Kiste!
 
 ; New utility crate
 02:07=Nützliches?
@@ -162,6 +323,12 @@
 02:07=Was wohl darin ist?
 02:07=Lieferung frei Haus!
 02:07=Mehr als nur eine Kiste!
+02:07=Weitere Hilfsmittel!
+02:07=Extras für Sie!
+02:07=Dies sollte gut sein!
+02:07=Verwenden Sie diese mit Bedacht
+02:07=Ooo diese Box ist schwer
+02:07=Möglicherweise müssen Sie diese
 
 ; Hog (%1) skips his turn
 02:08=%1 ist so ein Langeweiler ...
@@ -172,12 +339,68 @@
 02:08=%1 ist ein Drückeberger.
 02:08=%1 überdenkt die Situation.
 02:08=%1 kann sich nicht entscheiden.
+02:08=%1 muss ein wenig mehr Motivation
+02:08=%1 ist ein Pazifist
+02:08=%1 hat eine Verschnaufpause
+02:08=%1 hat einen Rest
+02:08=%1 Schüttelfrost aus
+02:08=%1 hat kein Vertrauen in seine eigenen Fähigkeiten
+02:08=%1 beschließt, nichts zu tun
+02:08=%1 lässt den Feind zu vernichten selbst
+02:08=%1 wäre bei Partys schrecklich
+02:08=%1 versteckt sich
+02:08=%1 hat sich entschlossen, diese Chance geben
+02:08=%1 entscheidet das Beste, was er tun kann, ist nichts ...
+02:08=%1 ist ein großes Weichei
+02:08=Bock bock bock, %1 ist ein Huhn
+02:08=%1 schaut ein wenig gelb
+02:08=%1 ist ein Feigling!
+02:08=%1 wird für den plötzlichen Tod wartet
+02:08=%1 ist wartet auf Sudden Death
+02:08=%1 ist nicht die Bekämpfung von Typ
+02:08=%1 überdenkt seinen Sinn im Leben
+02:08=%1 war nie viel von einem guten Schuss ohnehin
+02:08=%1 wollte nicht, dass die Armee in erster Linie verbinden
+02:08=Aufhören, unsere Zeit, %1
+02:08=Ich bin in dir enttäuscht, %1
+02:08=Los, können Sie es besser machen %1
+02:08=%1 wird gebrochen
+02:08=%1 hat anscheinend Besseres zu tun
+02:08=%1 ist zu Tode erschrocken
+02:08=%1 ist eingeschlafen
 
 ; Hog (%1) hurts himself only
 02:09=%1 sollte besser Zielen üben!
 02:09=%1 scheint sich zu hassen.
 02:09=%1 steht auf der falschen Seite!
 02:09=%1 lebt gefährlich!
+02:09=%1 hat keinen Instinkt der Selbsterhaltung
+02:09=%1 durcheinander
+02:09=%1 vermasselt
+02:09=Das war ein schlechter Schuss, %1
+02:09=%1 ist ein wenig zu sorglos mit gefährlichen Waffen
+02:09=%1 sollte eine Änderung der Laufbahn betrachten
+02:09=Schlechteste. Schuss. Je!
+02:09=Kein kein kein %1, Sie schießen auf den Feind!
+02:09=%1 sollte nur werden, den Feind zu vernichten
+02:09=%1 bewegt sich einen Schritt näher an Selbstmord
+02:09=%1, Hilfsmittel der Feind
+02:09=Das war dumm %1
+02:09=%1 Leben mit dem Mantra des "keine Schmerzen, keine gewinnen"
+02:09=%1 ist verwirrt
+02:09=%1 verletzen sich in seiner Verwirrung
+02:09=%1 hat ein Talent für sich zu blamieren
+02:09=%1 ist ein Trottel!
+02:09=%1 ist ungeschickt
+02:09=%1 zeigt der Feind, wozu er fähig ist
+02:09=%1 kann nicht erwartet werden, perfekt zu sein werden die ganze Zeit
+02:09=Mach dir keine Sorgen %1, pobody die nerfect
+02:09=%1 völlig mit Absicht getan
+02:09=Ich werde niemandem sagen, wenn Sie nicht tun, %1
+02:09=Wie peinlich!
+02:09=Ich bin sicher, niemand sah, dass %1
+02:09=%1, Bedürfnisse, seine Field Manual überprüfen
+02:09=%1 Waffe eindeutig versagt
 
 ; Hog (%1) shot an home run (using the bat and another hog)
 02:10=Home Run!
@@ -305,7 +528,6 @@
 04:52=NICHT IN VERWENDUNG
 04:53=Unternimm eine Reise durch Zeit und Raum,|während du deine Kameraden alleine am Schlachtfeld zurücklässt.|Sei darauf vorbereitet jederzeit wieder zurückzukommen,|oder auf Sudden Death wenn sie alle besiegt wurden.|Disclaimer: Nicht funktionstüchtig wenn in Sudden Death,|wenn du alleine bist - oder der König.
 04:54=IN ARBEIT
-
 04:55=Versprühe einen Strahl klebriger Flocken.|Baue Brücken, begrabe Gegner, versiegle Tunnel.|Pass auf, dass du selbst nichts abbekommst!
 
 ; Game goal strings
--- a/share/hedgewars/Data/Locale/ja.txt	Sun Apr 01 15:23:34 2012 +0200
+++ b/share/hedgewars/Data/Locale/ja.txt	Wed May 02 23:53:45 2012 +0200
@@ -72,41 +72,481 @@
 01:12=サドンデスまで最後の番!
 01:13=サドンデスまで%1番残り!
 01:14=準備して、%1!
+01:15=わずかな
+01:16=低い
+01:17=通常の
+01:18=高い
+01:19=極端な
+01:20=%1のバウンス
 
 ; Event messages
 ; Hog (%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は実際に健康上のクレートを使用することもできました
+02:00=%1は優れたゲームをプレイしてしまった
+02:00=%1は寿命を有する
+02:00=%1が失敗した
+02:00=貧しい貧しい%1...
+02:00=%1のwarmuxを好む
+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=家の中で医者はありますか?
+
 ; Hog (%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=あなたがダウンしてありますどのように多くの豚不思議ちゃ
+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でBioshock3の先導的な役割を目指して
+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: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=ただ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=私はあなたの闘争のために準備が整いましたね!
+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=電源!
+
 ; New ammo crate
 02:06=もっと火力だ!
 02:06=なかになにかな
 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=神秘的なボックス!
+
 ; 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が眠っている
+
 ; Hog (%1) hurts himself only - see en.txt for examples
 02:09=もちろん、%1 がわざとしたねw
 ; The real saying has けってん = shortcoming, whereas てっけん = clenched fist
 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=どのように恥ずかしい!
+02:09=私は誰もその%1を見たことが確信している
+02:09=%1は彼の分野のマニュアルを確認する必要があります
+02:09=%1の武器は明らかに故障
+
 ; Hog shot an home run (using the bat and another hog)
 02:10=ホームラン!
 02:10=鳥、飛行機…いや、%1だ!
+02:10=が出ていることを!
+
 ; Hog (%1) has to leave (team is gone)
 02:11=%1 は出かけなければ…
 02:11=%1 はちょっと用がある
+02:11=ビーム彼のアップ、スコッティ!
+02:11=%1ベッドに移動しています!
+02:11=%1行かなければならない
+
+; Weapon Categories
+03:00=時限グレネード
+03:01=時限グレネード
+03:02=弾道兵器
+03:03=誘導兵器
+03:04=銃(複数枚)
+03:05=掘削ツール
+03:06=アクション
+03:07=トランスポートユーティリティ
+03:08=近接爆弾
+03:09=銃(複数枚)
+03:10=BOOM!
+03:11=ボンク!
+03:12=武術
+03:13=UNUSED
+03:14=トランスポートユーティリティ
+03:15=空中攻撃
+03:16=空中攻撃
+03:17=掘削ツール
+03:18=ユーティリティ
+03:19=トランスポートユーティリティ
+03:20=アクション
+03:21=弾道兵器
+03:22=私インディアナ呼ぶ!
+03:23=本当に)マーシャルアーツ
+03:24=ケーキは嘘ではありません!
+03:25=衣装キット
+03:26=ジューシーなグレネード
+03:27=燃えるようなグレネード
+03:28=弾道兵器
+03:29=弾道兵器
+03:30=空中攻撃
+03:31=リモコン爆弾
+03:32=一時的効果
+03:33=一時的効果
+03:34=一時的効果
+03:35=一時的効果
+03:36=一時的効果
+03:37=一時的効果
+03:38=銃(複数枚)
+03:39=トランスポートユーティリティ
+03:40=グレネードを焼却
+03:41=の大ファン
+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=UNUSED
+03:53=タイプ40
+03:54=何かを構築
+03:55=ユーティリティ
+
+; Weapon Descriptions (use | as line breaks)
+04:00=シンプルな手榴弾を使って敵を攻撃。そのタイマーがゼロに達するとそれが爆発する。1-5:セットグレネードのタイマー攻撃:より多くの電力をスローするようにホールド
+04:01=クラスター爆弾を使用して敵を攻撃。そのタイマーがゼロに達すると、それは小さな爆弾に分割されます。1-5:セットグレネードのタイマー攻撃:より多くの電力をスローするようにホールド
+04:02=風に影響されるかもしれない弾道発射体を使用して敵を攻撃。攻撃:より多くの電力を使って撮影するホールド
+04:03=選択したターゲットにロックされ爆発的な蜂を起動します。その精度を向上させるためにフルパワーを使って撮影しないでください。カーソル:ピックターゲット攻撃:より多くの電力を使って撮影するホールド
+04:04=2ショットでショットガンを使って敵を攻撃する。その広がりあなたのおかげで、あなたの対戦相手に危害を直接ヒットする必要はありません。攻撃:シュート(複数回)
+04:05=地下に移動!地面に穴を開けると他の領域に到達するを使用しています。攻撃の開始または停止掘り
+04:06=退屈?攻撃する方法はありません?あなたの弾薬を保存しますか?問題ありません!ちょうどあなたのターン、臆病者をスキップして!攻撃:戦闘せずにターンをスキップ
+04:07=ロープでタイムアウトショットを使用して、巨大な距離を埋める。他の豚またはドロップ手榴弾およびそれらの他の武器にスライドするように勢いを使用しています。攻撃:ドロップ手榴弾または類似の武器:ロープロングジャンプシュートまたは解放
+04:08=狭い通路の右またはそれらの足の下鉱山をドロップすることで、離れてあなたの敵を保つ。あなた自身でそれをトリガする前に撤退してください!攻撃:あなたの足の隣に地雷を削除します。
+04:09=あなたの照準が分からない?4打差までを使用して攻撃するためにデザートイーグルを使用しています。攻撃:シュート(複数回)
+04:10=ブルートフォースは常にオプションです。あなたの敵と後退の隣にあるこの古典的な爆発物をドロップします。攻撃:あなたの足の隣にあるドロップダイナマイト
+04:11=マップの国境を越えてまたは水の中にそれらをバッティングして敵の豚を取り除く。またはどのようにお友達にいくつかの鉱山をノックでしょうか?攻撃:あなたの前にバットすべてを
+04:12=このほとんど致命的な武道技術の力を解き放つに近いと個人的な取得します。攻撃:素晴らしいを実行します。
+04:13=UNUSED
+04:14=高所恐怖症?優れたパラシュートをつかむ。それはあなたが遠すぎたら落ちる展開と秋のダメージを受けてから豚を保存します。攻撃:ドロップ手榴弾または類似の武器:パラシュートロングジャンプを伸ばし
+04:15=爆撃の実行を使用して敵を攻撃する飛行機の中で呼び出します。左右:選択してターゲット領域:攻撃方向のカーソルを決定
+04:16=ターゲットエリアにいくつかの鉱山をドロップするには飛行機の中で呼び出します。左右:選択してターゲット領域:攻撃方向のカーソルを決定
+04:17=避難が必要ですか?あなたがカバー付与固体地面にトンネルを掘るためにブロートーチを使用しています。攻撃の開始または停止掘り
+04:18=追加の保護が必要な場合、または地面を通過したいですか?好きなように、いくつかの桁に置きます。有効な位置に配置桁:左右:カーソルを配置する選択桁
+04:19=それはあなたが数秒以内に危険な状況から豚を保存することができますように、右瞬間テレポーテーションで使用するほぼすべての武器をより強力にすることができます。カーソル:選択してターゲット領域
+04:20=別の豚と、現在のターンを再生することができます。攻撃:スイッチング豚を有効にする
+04:21=インパクト時に複数の爆弾を解放します手榴弾のような弾丸を撃つ。攻撃:フルパワーで撃つ
+04:22=だけでなく、インディジョーンズのために!鞭は多くの状況で有用な武器である。あなたが崖から誰かを突き出すしたい場合は特に。攻撃:あなたの前にストライクのすべて
+04:23=あなたが失うものは何もない場合、これはかなり便利かもしれません。彼の方法上のすべてを傷つけると終了時に爆発し、特定の方向に彼を起動することで、豚を生け贄に捧げる。攻撃:壊滅的な、致命的な攻撃を開始
+04:24=誕生日おめでとう!このケーキを起動し、それが右の敵の隣に歩いて、彼らが爆発的パーティを持たせてみましょう。ケーキは、ほぼすべての地形を通過することができますが、彼は以前、この方法を爆発させるかもしれません。攻撃:ケーキを起動するか、停止させると爆発する
+04:25=(そして、いくつかのギャップや穴)が豚に向かってジャンプすることがあなたの敵を取得するには、この変装キットを使用しています。攻撃:キットを使用して、別の豚を誘惑しよう
+04:26=あなたの敵で、このジューシーなスイカをスローします。タイマーの期限が切れると、それはいくつかの爆発的な断片に分割されます。1-5:セットスイカのタイマー攻撃:より多くの電力を使って撮影するホールド
+04:27=この悪魔のよう爆発を使用して、あなたの対戦相手に業火の雨してみましょう。近すぎる小さな火災が長く続くかもしれないと爆発に得ることはありません。攻撃:より多くの電力を使って撮影するホールド
+04:28=このロケットを打ち上げた後の短い時間、それは固体地面を掘削を開始し、そのヒューズがトリガされると爆発するか、再び再浮上します。攻撃:より多くの電力を使って撮影するホールド
+04:29=これは小さな子供のためのものではありません!ボール銃は爆薬を充填した小さな色のボールのトンを発生させます。攻撃:アップダウン、フルパワーでシュートを目指して進みます
+04:30=強力なナパームストライキを起動するには飛行機の中で呼び出します。適切にこの攻撃を目指してそこに座って不運な豚を含む風景の巨大な部分を根絶することができます。左右:選択してターゲット領域:攻撃方向のカーソルを決定
+04:31=RCプレーンは箱を収集したり、遠く離れた豚を攻撃するのに理想的な武器です。どちらの敵にそれを操縦するか、最初のいくつかの爆弾をドロップします。攻撃:ワルキューレが戦闘に乗りましょう左右:平面ステアジャンプ平面またはドロップロング爆弾を起動します。
+04:32=低重力はどんなダイエットよりも効果的です!高く、長い距離を飛び越えたり、敵がさらに飛ぶしましょう。攻撃:アクティブ
+04:33=時には、いくつかのより多くのダメージを与えるためにその少し余分なブーストをちょうど必要があります。攻撃:アクティブ
+04:34=私に触れることができない!攻撃:アクティブ
+04:35=時には時間が早すぎる実行している。あなたの攻撃を完了するために、いくつかの余分な秒をつかむ。攻撃:アクティブ
+04:36=さて、時にはあなたが目指すのはあまりにも悪いです。現代の技術を使用していくつかの支援を得る。攻撃:アクティブ
+04:37=日光を恐れてはいけません。それはちょうど1ターン持続しますが、あなたが他の豚に何のダメージを吸収することができるようになります。攻撃:アクティブ
+04:38=スナイパーライフルは、あなたの全体の兵器庫の中で最も壊滅的な武器になります、しかし、それは接近戦で非常に効果的です。ダメージは、そのターゲットまでの距離とともに増加を与えた。攻撃:シュート(回)
+04:39=空飛ぶ円盤を使用してマップの他の部分に飛ぶ。これは、マスターユーティリティのハード戦場のほぼ任意の位置に行くことができるようになりました。攻撃:最大アクティブ左右:ドロップ手榴弾または類似の武器:一方向にロングジャンプ力を適用します。
+04:40=(すぐになる)、燃焼液で満たされたこのボトルを使用して、火災のいくつかの地を設定します。攻撃:より多くの電力を使って撮影するホールド
+04:41=証拠の性質も、空飛ぶ円盤を上回るかもしれません。バーディは、豚を持ち歩くとあなたの敵に卵をドロップすることができます!バーディーを使用すると、あなたのターンの時間に食べるように、迅速である!攻撃:およびドロップ卵アップ左右:一方向にフラップ
+04:42=この携帯ポータル装置は、瞬時に、あなたの敵、または地形上の2点間のあなたの武器あなたを輸送することが可能です。賢明にそれを使用して、キャンペーンがあります...大成功!攻撃:サイクルポータルの色:ポータルスイッチを撃つ
+04:43=あなたの音楽デビュー爆発を成功させる!天からピアノをドロップしますが、注意してください...誰かがそれを再生する必要があり、それはあなたの人生を要するかもしれない!カーソル:選択してターゲット領域F1-F9キーを押して:ピアノを弾く
+04:44=これはただのチーズではなく、生物兵器だ!タイマーがゼロに達すると、それは間違いなく臭いをタッチする誰もが不幸に毒されたら、それは被害の膨大な量が発生することはありません!1-5:セットグレネードのタイマー攻撃:より多くの電力をスローするようにホールド
+04:45=すべてのそれらの物理学のクラスは最終的に報われている、あなたの敵に壊滅的な正弦波を起動します。気を付けろ、この武器は非常にキックをパックします。(この武器は不完全です)攻撃力:シュート
+04:46=液体炎を非常に暑いとあなたの敵をカバーしています。ほのぼの!アタックを上下にアクティブにします。左右を目指して進みます:唾の電源を変更します。
+04:47=2先端のとがった、卑劣な、粘着地雷の楽しみを倍増。連鎖反応を設定するか(あるいは両方!)攻撃を守る:より多くの電力(倍)で撮影するホールド
+04:48=なぜモルすべての虐待を取得する必要があります?豚をは、単に楽しみとしてすることができます!このハンマーから良い打撃は豚の健康状態の3分の1をオフに剃るし、それらを地下に突入します。攻撃:アクティブ
+04:49=あなたの友人を復活させる!しかし、これはまたあなたの敵を復活させること注意してください。攻撃:ゆっくりと復活させるために押された攻撃に注意してください。復活を加速
+04:50=誰かが地下に隠れている?ドリルのストライキでそれらを掘る!タイマーは、それを掘る方法をはるかに制御します。
+04:51=泥のボールを投げつけることによって自由なショットで取得します。刺されは、ビット、豚をバックノックする。
+04:52=UNUSED
+04:53=あなたの仲間が単独で戦うために残しながら、時間と空間を介して冒険に出る。いつでも返すように準備する、または突然死の場合、または、それらはすべて敗北しています。免責事項。あなたは一人である場合は、突然死で機能するか、キングである場合ではありません。
+04:54=INCOMPLETE
+04:55=スティッキーフレークのストリームをスプレー。トンネルを封鎖、敵を埋める、ブリッジを構築します。あなたが上の任意のを取得しないように注意してください!
+
+; Game goal strings
+05:00=ゲームモード
+05:01=次の規則が適用されます
+05:02=砦:あなたの要塞を守り、敵を打ち負かす!
+05:03=低重力:足元に気をつけて
+05:04=不死身:豚は不死身(ほぼ)です。
+05:05=吸血鬼:豚は、ダメージのために癒される
+05:06=カルマ:豚は、ダメージのために破損します。
+05:07=キングを保護する:あなたの王が死んではいけない|場所キング:あなたの王のために保護された出発点をピック
+05:08=場所のハリネズミ:ゲームが起動する前に、豚を置きます
+05:09=砲兵:豚の位置を変更するには、歩くことができない
+05:10=不滅の地形:ほとんどの武器は地形を破壊することはありません
+05:11=共有弾薬:同じ色のすべてのチームが彼らの弾薬を共有する
+05:12=鉱山タイマー:鉱山は、%1秒後()を爆発します。
+05:13=鉱山タイマ:鉱山は即座に爆発します。
+05:14=鉱山タイマ:鉱山は0の後に爆発します。 0- 5秒
+05:15=ダメージ修正:すべての武器は、%1%のダメージを行います
+05:16=すべての豚の健康状態はターン終了時にリセットされます。
+05:17=死の豚のリスポーン
+05:18=無限の攻撃
+05:19=武器はターン終了時にリセットされます。
+05:20=武器は豚の間で共有されていません
+05:21=タグチーム:一族のチームは、連続ターンを取る|共有時間:一族の株のターン時間内にチーム
Binary file share/hedgewars/Data/Maps/Islands/map.png has changed
--- a/share/hedgewars/Data/Maps/Trash/map.cfg	Sun Apr 01 15:23:34 2012 +0200
+++ b/share/hedgewars/Data/Maps/Trash/map.cfg	Wed May 02 23:53:45 2012 +0200
@@ -1,1 +1,1 @@
-Nature
\ No newline at end of file
+Compost
Binary file share/hedgewars/Data/Music/Golf.ogg has changed
Binary file share/hedgewars/Data/Music/Nature.ogg has changed
--- a/tools/PascalBasics.hs	Sun Apr 01 15:23:34 2012 +0200
+++ b/tools/PascalBasics.hs	Wed May 02 23:53:45 2012 +0200
@@ -8,7 +8,7 @@
 import Text.Parsec.Language
 import Data.Char
 
-builtin = ["succ", "pred", "low", "high", "ord"]
+builtin = ["succ", "pred", "low", "high", "ord", "inc", "dec", "exit"]
     
 pascalLanguageDef
     = emptyDef
--- a/tools/PascalParser.hs	Sun Apr 01 15:23:34 2012 +0200
+++ b/tools/PascalParser.hs	Wed May 02 23:53:45 2012 +0200
@@ -14,7 +14,7 @@
 import PascalBasics
 import PascalUnitSyntaxTree
     
-knownTypes = ["shortstring", "char", "byte"]
+knownTypes = ["shortstring", "ansistring", "char", "byte"]
 
 pascalUnit = do
     comments
@@ -113,12 +113,13 @@
         comments
         e <- initExpression
         comments
-        return $ VarDeclaration False ([i], fromMaybe (DeriveType e) t) (Just e)
+        return $ VarDeclaration (isNothing t) ([i], fromMaybe (DeriveType e) t) (Just e)
         
 typeDecl = choice [
     char '^' >> typeDecl >>= return . PointerTo
     , try (string "shortstring") >> return (String 255)
     , try (string "string") >> optionMaybe (brackets pas $ integer pas) >>= return . String . fromMaybe 255
+    , try (string "ansistring") >> optionMaybe (brackets pas $ integer pas) >>= return . String . fromMaybe 255
     , arrayDecl
     , recordDecl
     , setDecl
@@ -407,6 +408,7 @@
         , withBlock
         , forCycle
         , (try $ reference >>= \r -> string ":=" >> return r) >>= \r -> expression >>= return . Assignment r
+        , builtInFunction expression >>= \(n, e) -> return $ BuiltInFunctionCall e (SimpleReference (Identifier n BTUnknown))
         , procCall
         , char ';' >> comments >> return NOP
         ]
@@ -581,8 +583,8 @@
            , Infix (try $ string "or" >> return (InitBinOp "or")) AssocLeft
            , Infix (try $ string "xor" >> return (InitBinOp "xor")) AssocLeft
           ]
-        , [  Infix (try $ string "shl" >> return (InitBinOp "and")) AssocNone
-           , Infix (try $ string "shr" >> return (InitBinOp "or")) AssocNone
+        , [  Infix (try $ string "shl" >> return (InitBinOp "shl")) AssocNone
+           , Infix (try $ string "shr" >> return (InitBinOp "shr")) AssocNone
           ]
         , [Prefix (try (string "not") >> return (InitPrefixOp "not"))]
         ]
@@ -596,7 +598,7 @@
 builtInFunction e = do
     name <- choice $ map (\s -> try $ caseInsensitiveString s >>= \i -> notFollowedBy alphaNum >> return i) builtin
     spaces
-    exprs <- parens pas $ commaSep1 pas $ e
+    exprs <- option [] $ parens pas $ option [] $ commaSep1 pas $ e
     spaces
     return (name, exprs)
 
--- a/tools/PascalPreprocessor.hs	Sun Apr 01 15:23:34 2012 +0200
+++ b/tools/PascalPreprocessor.hs	Wed May 02 23:53:45 2012 +0200
@@ -15,7 +15,7 @@
         , (try $ string "//") >> manyTill anyChar (try newline) >> return "\n"
         ]
 
-initDefines = Map.fromList [("FPC", "")]
+initDefines = Map.fromList [("FPC", ""), ("PAS2C", "")]
         
 preprocess :: String -> IO String
 preprocess fn = do
@@ -74,7 +74,7 @@
         char '"'
         spaces
         char '}'
-        f <- liftIO (readFile fn)
+        f <- liftIO (readFile fn `catch` error ("File not found: " ++ fn))
         c <- getInput
         setInput $ f ++ c
         return ""
--- a/tools/PascalUnitSyntaxTree.hs	Sun Apr 01 15:23:34 2012 +0200
+++ b/tools/PascalUnitSyntaxTree.hs	Wed May 02 23:53:45 2012 +0200
@@ -32,10 +32,10 @@
     | FunctionType TypeDecl [TypeVarDeclaration]
     | DeriveType InitExpression 
     | VoidType
-    | UnknownType
     deriving Show
 data Range = Range Identifier
            | RangeFromTo InitExpression InitExpression
+           | RangeInfinite
     deriving Show
 data Initialize = Initialize String
     deriving Show
@@ -52,6 +52,7 @@
         | Phrases [Phrase]
         | SwitchCase Expression [([InitExpression], Phrase)] (Maybe [Phrase])
         | Assignment Reference Expression
+        | BuiltInFunctionCall [Expression] Reference
         | NOP
     deriving Show
 data Expression = Expression String
@@ -103,8 +104,9 @@
     | BTBool
     | BTFloat
     | BTRecord [(String, BaseType)]
-    | BTArray BaseType BaseType
+    | BTArray Range BaseType BaseType
     | BTFunction BaseType
+    | BTFunctionReturn String BaseType
     | BTPointerTo BaseType
     | BTUnresolved String
     | BTSet BaseType
--- a/tools/pas2c.hs	Sun Apr 01 15:23:34 2012 +0200
+++ b/tools/pas2c.hs	Wed May 02 23:53:45 2012 +0200
@@ -1,3 +1,4 @@
+{-# LANGUAGE ScopedTypeVariables #-}
 module Pas2C where
 
 import Text.PrettyPrint.HughesPJ
@@ -13,6 +14,7 @@
 import System.IO.Error
 import qualified Data.Map as Map
 import Data.List (find)
+import Numeric
 
 import PascalParser
 import PascalUnitSyntaxTree
@@ -29,10 +31,47 @@
         currentScope :: [Record],
         lastIdentifier :: String,
         lastType :: BaseType,
+        stringConsts :: [(String, String)],
+        uniqCounter :: Int,
         namespaces :: Map.Map String [Record]
     }
     
-emptyState = RenderState [] "" BTUnknown
+emptyState = RenderState [] "" BTUnknown [] 0
+
+getUniq :: State RenderState Int
+getUniq = do
+    i <- gets uniqCounter
+    modify(\s -> s{uniqCounter = uniqCounter s + 1})
+    return i
+    
+addStringConst :: String -> State RenderState Doc
+addStringConst str = do
+    strs <- gets stringConsts
+    let a = find ((==) str . snd) strs
+    if isJust a then
+        do
+        modify (\s -> s{lastType = BTString})
+        return . text . fst . fromJust $ a
+    else
+        do
+        i <- getUniq
+        let sn = "__str" ++ show i
+        modify (\s -> s{lastType = BTString, stringConsts = (sn, str) : strs})
+        return $ text sn
+    
+escapeStr :: String -> String
+escapeStr = foldr escapeChar []
+
+escapeChar :: Char -> ShowS
+escapeChar '"' s = "\\\"" ++ s
+escapeChar a s = a : s
+
+strInit :: String -> Doc
+strInit a = text "STRINIT" <> parens (doubleQuotes (text $ escapeStr a))
+
+renderStringConsts :: State RenderState Doc
+renderStringConsts = liftM (vcat . map (\(a, b) -> text "const string255" <+> (text a) <+> text "=" <+> strInit b <> semi)) 
+    $ gets stringConsts
     
 docToLower :: Doc -> Doc
 docToLower = text . map toLower . render
@@ -76,6 +115,8 @@
 renderCFiles units = do
     let u = Map.toList units
     let nss = Map.map (toNamespace nss) units
+    hPutStrLn stderr $ "Units: " ++ (show . Map.keys . Map.filter (not . null) $ nss)
+    --writeFile "pas2c.log" $ unlines . map (\t -> show (fst t) ++ "\n" ++ (unlines . map ((:) '\t' . show) . snd $ t)) . Map.toList $ nss
     mapM_ (toCFiles nss) u
     where
     toNamespace :: Map.Map String [Record] -> PascalUnit -> [Record]
@@ -86,10 +127,16 @@
         currentScope $ execState (interface2C interface) (emptyState nss)
 
 
-withState' :: (a -> a) -> State a b -> State a b
-withState' f s = do
+withState' :: (RenderState -> RenderState) -> State RenderState a -> State RenderState a
+withState' f sf = do
     st <- liftM f get
-    return $ evalState s st
+    let (a, s) = runState sf st
+    modify(\st -> st{
+        lastType = lastType s
+        , uniqCounter = uniqCounter s
+        , stringConsts = stringConsts s
+        })
+    return a
 
 withLastIdNamespace :: State RenderState Doc -> State RenderState Doc
 withLastIdNamespace f = do
@@ -97,11 +144,12 @@
     nss <- gets namespaces
     withState' (\st -> st{currentScope = fromMaybe [] $ Map.lookup li (namespaces st)}) f
 
-withRecordNamespace :: [(String, BaseType)] -> State RenderState Doc -> State RenderState Doc
-withRecordNamespace recs = withState' f
+withRecordNamespace :: String -> [(String, BaseType)] -> State RenderState Doc -> State RenderState Doc
+withRecordNamespace _ [] = error "withRecordNamespace: empty record"
+withRecordNamespace prefix recs = withState' f
     where
         f st = st{currentScope = records ++ currentScope st}
-        records = map (\(a, b) -> (map toLower a, (a, b))) recs
+        records = map (\(a, b) -> (map toLower a, (prefix ++ a, b))) recs
 
 toCFiles :: Map.Map String [Record] -> (String, PascalUnit) -> IO ()
 toCFiles _ (_, System _) = return ()
@@ -110,14 +158,14 @@
     toCFiles' p
     where
     toCFiles' (fn, p@(Program {})) = writeFile (fn ++ ".c") $ (render2C initialState . pascal2C) p
-    toCFiles' (fn, (Unit _ interface implementation _ _)) = do
-        let (a, s) = runState (interface2C interface) initialState
-        writeFile (fn ++ ".h") $ "#pragma once\n" ++ (render a)
-        writeFile (fn ++ ".c") $ (render2C s . implementation2C) implementation
+    toCFiles' (fn, (Unit unitId interface implementation _ _)) = do
+        let (a, s) = runState (id2C IOInsert (setBaseType BTUnit unitId) >> interface2C interface) initialState
+        writeFile (fn ++ ".h") $ "#pragma once\n\n#include \"pas2c.h\"\n\n" ++ (render (a $+$ text ""))
+        writeFile (fn ++ ".c") $ "#include \"" ++ fn ++ ".h\"\n" ++ (render2C s . implementation2C) implementation
     initialState = emptyState ns
 
     render2C :: RenderState -> State RenderState Doc -> String
-    render2C a = render . flip evalState a
+    render2C a = render . ($+$ empty) . flip evalState a
 
 usesFiles :: PascalUnit -> [String]
 usesFiles (Program _ (Implementation uses _) _) = "pas2cSystem" : uses2List uses
@@ -131,21 +179,29 @@
     
 pascal2C (Program _ implementation mainFunction) = do
     impl <- implementation2C implementation
-    main <- tvar2C True 
+    [main] <- tvar2C True 
         (FunctionDeclaration (Identifier "main" BTInt) (SimpleType $ Identifier "int" BTInt) [] (Just (TypesAndVars [], mainFunction)))
     return $ impl $+$ main
 
     
     
 interface2C :: Interface -> State RenderState Doc
-interface2C (Interface uses tvars) = liftM2 ($+$) (uses2C uses) (typesAndVars2C True tvars)
-
+interface2C (Interface uses tvars) = do
+    u <- uses2C uses
+    tv <- typesAndVars2C True tvars
+    r <- renderStringConsts
+    return (u $+$ r $+$ tv)
+    
 implementation2C :: Implementation -> State RenderState Doc
-implementation2C (Implementation uses tvars) = liftM2 ($+$) (uses2C uses) (typesAndVars2C True tvars)
+implementation2C (Implementation uses tvars) = do
+    u <- uses2C uses
+    tv <- typesAndVars2C True tvars
+    r <- renderStringConsts
+    return (u $+$ r $+$ tv)
 
 
 typesAndVars2C :: Bool -> TypesAndVars -> State RenderState Doc
-typesAndVars2C b (TypesAndVars ts) = liftM vcat $ mapM (tvar2C b) ts
+typesAndVars2C b (TypesAndVars ts) = liftM (vcat . map (<> semi) . concat) $ mapM (tvar2C b) ts
 
 setBaseType :: BaseType -> Identifier -> Identifier
 setBaseType bt (Identifier i _) = Identifier i bt
@@ -158,7 +214,7 @@
     where
     injectNamespace (Identifier i _) = do
         getNS <- gets (flip Map.lookup . namespaces)
-        let f = flip (foldl (\a b -> b:a)) (fromMaybe [] (getNS i))
+        let f = flip (foldl (flip (:))) (fromMaybe [] (getNS i))
         modify (\s -> s{currentScope = f $ currentScope s})
 
 uses2List :: Uses -> [String]
@@ -167,6 +223,12 @@
 
 id2C :: InsertOption -> Identifier -> State RenderState Doc
 id2C IOInsert (Identifier i t) = do
+    ns <- gets currentScope
+{--    case t of 
+        BTUnknown -> do
+            ns <- gets currentScope
+            error $ "id2C IOInsert: type BTUnknown for " ++ show i ++ "\nnamespace: " ++ show (take 100 ns)
+        _ -> do --}
     modify (\s -> s{currentScope = (n, (i, t)) : currentScope s, lastIdentifier = n})
     return $ text i
     where
@@ -175,16 +237,15 @@
     let i' = map toLower i
     v <- gets $ find (\(a, _) -> a == i') . currentScope
     ns <- gets currentScope
+    lt <- gets lastType
     if isNothing v then 
-        error $ "Not defined: '" ++ i' ++ "'\n" -- ++ show ns
+        error $ "Not defined: '" ++ i' ++ "'\n" ++ show lt ++ "\n" ++ show (take 100 ns)
         else 
         let vv = snd $ fromJust v in modify (\s -> s{lastType = snd vv, lastIdentifier = fst vv}) >> (return . text . fst $ vv)
 id2C IODeferred (Identifier i t) = do
     let i' = map toLower i
     v <- gets $ find (\(a, _) -> a == i') . currentScope
     if (isNothing v) then
-        do
-        modify (\s -> s{currentScope = (i', (i, t)) : currentScope s})
         return $ text i
         else
         return . text . fst . snd . fromJust $ v
@@ -197,7 +258,8 @@
         BTUnknown -> do
             ns <- gets currentScope
             error $ "id2CTyped: type BTUnknown for " ++ show i ++ "\ntype: " ++ show t ++ "\nnamespace: " ++ show (take 100 ns)
-        _ -> id2C IOInsert (Identifier i tb)
+        _ -> return ()
+    id2C IOInsert (Identifier i tb)
 
 
 resolveType :: TypeDecl -> State RenderState BaseType
@@ -221,8 +283,10 @@
     where
         f :: TypeVarDeclaration -> State RenderState [(String, BaseType)]
         f (VarDeclaration _ (ids, td) _) = mapM (\(Identifier i _) -> liftM ((,) i) $ resolveType td) ids
-resolveType (ArrayDecl (Just _) t) = liftM (BTArray BTInt) $ resolveType t
-resolveType (ArrayDecl Nothing t) = liftM (BTArray BTInt) $ resolveType t
+resolveType (ArrayDecl (Just i) t) = do
+    t' <- resolveType t
+    return $ BTArray i BTInt t' 
+resolveType (ArrayDecl Nothing t) = liftM (BTArray RangeInfinite BTInt) $ resolveType t
 resolveType (FunctionType t _) = liftM BTFunction $ resolveType t
 resolveType (DeriveType (InitHexNumber _)) = return BTInt
 resolveType (DeriveType (InitNumber _)) = return BTInt
@@ -236,127 +300,249 @@
 resolveType (String _) = return BTString
 resolveType VoidType = return BTVoid
 resolveType (Sequence ids) = return $ BTEnum $ map (\(Identifier i _) -> map toLower i) ids
-resolveType (RangeType _) = return $ BTUnknown
+resolveType (RangeType _) = return $ BTVoid
 resolveType (Set t) = liftM BTSet $ resolveType t
---resolveType UnknownType = return BTUnknown    
-resolveType a = error $ "resolveType: " ++ show a
-    
+   
+
+resolve :: String -> BaseType -> State RenderState BaseType
+resolve s (BTUnresolved t) = do
+    v <- gets $ find (\(a, _) -> a == t) . currentScope
+    if isJust v then
+        resolve s . snd . snd . fromJust $ v
+        else
+        error $ "Unknown type " ++ show t ++ "\n" ++ s
+resolve _ t = return t
 
-fromPointer :: BaseType -> State RenderState BaseType    
-fromPointer (BTPointerTo t) = f t
-    where
-        f (BTUnresolved s) = do
-            v <- gets $ find (\(a, _) -> a == s) . currentScope
-            if isJust v then
-                f . snd . snd . fromJust $ v
-                else
-                error $ "Unknown type " ++ show t
-        f t = return t
-fromPointer t = error $ "Dereferencing from non-pointer type " ++ show t
+fromPointer :: String -> BaseType -> State RenderState BaseType
+fromPointer s (BTPointerTo t) = resolve s t
+fromPointer s (BTFunctionReturn _ (BTPointerTo t)) = resolve s t
+fromPointer s t = do
+    ns <- gets currentScope
+    error $ "Dereferencing from non-pointer type " ++ show t ++ "\n" ++ s ++ "\n\n" ++ show (take 100 ns)
+
+    
+functionParams2C params = liftM (hcat . punctuate comma . concat) $ mapM (tvar2C False) params
 
-
-tvar2C :: Bool -> TypeVarDeclaration -> State RenderState Doc
-tvar2C _ (FunctionDeclaration name returnType params Nothing) = do
+fun2C :: Bool -> String -> TypeVarDeclaration -> State RenderState [Doc]
+fun2C _ _ (FunctionDeclaration name returnType params Nothing) = do
     t <- type2C returnType 
-    p <- withState' id $ liftM hcat $ mapM (tvar2C False) params
-    n <- id2C IOInsert name
-    return $ t <+> n <> parens p <> text ";"
+    t'<- gets lastType
+    p <- withState' id $ functionParams2C params
+    n <- id2C IOInsert $ setBaseType (BTFunction t') name
+    return [t empty <+> n <> parens p]
     
-tvar2C True (FunctionDeclaration (Identifier i _) returnType params (Just (tvars, phrase))) = do
+fun2C True rv (FunctionDeclaration name returnType params (Just (tvars, phrase))) = do
+    let res = docToLower $ text rv <> text "_result"
     t <- type2C returnType
     t'<- gets lastType
-    n <- id2C IOInsert (Identifier i (BTFunction t'))
-    (p, ph) <- withState' (\st -> st{currentScope = (lastIdentifier st, (lastIdentifier st ++ "_result", t')) : currentScope st}) $ do
-        p <- liftM hcat $ mapM (tvar2C False) params
+    n <- id2C IOInsert $ setBaseType (BTFunction t') name
+    (p, ph) <- withState' (\st -> st{currentScope = (map toLower rv, (render res, BTFunctionReturn (render n) t')) : currentScope st}) $ do
+        p <- functionParams2C params
         ph <- liftM2 ($+$) (typesAndVars2C False tvars) (phrase2C' phrase)
         return (p, ph)
-    let res = docToLower $ n <> text "_result"
     let phrasesBlock = case returnType of
             VoidType -> ph
-            _ -> t <+> res <> semi $+$ ph $+$ text "return" <+> res <> semi
-    return $ 
-        t <+> n <> parens p
+            _ -> t empty <+> res <> semi $+$ ph $+$ text "return" <+> res <> semi
+    return [ 
+        t empty <+> n <> parens p
         $+$
         text "{" 
         $+$ 
         nest 4 phrasesBlock
         $+$
-        text "}"
+        text "}"]
     where
     phrase2C' (Phrases p) = liftM vcat $ mapM phrase2C p
     phrase2C' p = phrase2C p
     
-tvar2C False (FunctionDeclaration (Identifier name _) _ _ _) = error $ "nested functions not allowed: " ++ name
+fun2C False _ (FunctionDeclaration (Identifier name _) _ _ _) = error $ "nested functions not allowed: " ++ name
+fun2C _ tv _ = error $ "fun2C: I don't render " ++ show tv
 
+tvar2C :: Bool -> TypeVarDeclaration -> State RenderState [Doc]
+tvar2C b f@(FunctionDeclaration (Identifier name _) _ _ _) =
+    fun2C b name f
 tvar2C _ td@(TypeDeclaration i' t) = do
     i <- id2CTyped t i'
-    tp <- type2C t
-    return $ text "type" <+> i <+> tp <> semi
+    tp <- case t of
+        FunctionType {} -> type2C (PointerTo t)
+        _ -> type2C t
+    return [text "typedef" <+> tp i]
     
 tvar2C _ (VarDeclaration isConst (ids, t) mInitExpr) = do
-    t' <- type2C t
-    i <- mapM (id2CTyped t) ids
+    t' <- liftM (((if isConst then text "const" else empty) <+>) . ) $ type2C t
     ie <- initExpr mInitExpr
-    return $ if isConst then text "const" else empty
-        <+> t'
-        <+> (hsep . punctuate (char ',') $ i)
-        <+> ie
-        <> text ";"
+    lt <- gets lastType
+    case (isConst, lt, ids, mInitExpr) of
+         (True, BTInt, [i], Just _) -> do
+             i' <- id2CTyped t i
+             return [text "enum" <> braces (i' <+> ie)]
+         (True, BTFloat, [i], Just e) -> do
+             i' <- id2CTyped t i
+             ie <- initExpr2C e
+             return [text "#define" <+> i' <+> parens ie <> text "\n"]
+         _ -> liftM (map(\i -> t' i <+> ie)) $ mapM (id2CTyped t) ids
     where
     initExpr Nothing = return $ empty
     initExpr (Just e) = liftM (text "=" <+>) (initExpr2C e)
     
-tvar2C f (OperatorDeclaration op i ret params body) = 
-    tvar2C f (FunctionDeclaration i ret params body)
+tvar2C f (OperatorDeclaration op (Identifier i _) ret params body) = do
+    r <- op2CTyped op (extractTypes params)
+    fun2C f i (FunctionDeclaration r ret params body)
 
     
+op2CTyped :: String -> [TypeDecl] -> State RenderState Identifier
+op2CTyped op t = do
+    t' <- liftM (render . hcat . punctuate (char '_') . map (\t -> t empty)) $ mapM type2C t
+    bt <- gets lastType
+    return $ case bt of
+         BTRecord {} -> Identifier (t' ++ "_op_" ++ opStr) bt
+         _ -> Identifier t' bt
+    where 
+    opStr = case op of
+                    "+" -> "add"
+                    "-" -> "sub"
+                    "*" -> "mul"
+                    "/" -> "div"
+                    "=" -> "eq"
+                    "<" -> "lt"
+                    ">" -> "gt"
+                    _ -> error $ "op2CTyped: unknown op '" ++ op ++ "'"
+    
+extractTypes :: [TypeVarDeclaration] -> [TypeDecl]
+extractTypes = concatMap f
+    where
+        f (VarDeclaration _ (ids, t) _) = replicate (length ids) t
+        f a = error $ "extractTypes: can't extract from " ++ show a
+
 initExpr2C :: InitExpression -> State RenderState Doc
+initExpr2C InitNull = return $ text "NULL"
+initExpr2C (InitAddress expr) = liftM ((<>) (text "&")) (initExpr2C expr)
+initExpr2C (InitPrefixOp op expr) = liftM (text (op2C op) <>) (initExpr2C expr)
 initExpr2C (InitBinOp op expr1 expr2) = do
     e1 <- initExpr2C expr1
     e2 <- initExpr2C expr2
-    o <- op2C op
-    return $ parens $ e1 <+> o <+> e2
+    return $ parens $ e1 <+> text (op2C op) <+> e2
 initExpr2C (InitNumber s) = return $ text s
 initExpr2C (InitFloat s) = return $ text s
 initExpr2C (InitHexNumber s) = return $ text "0x" <> (text . map toLower $ s)
-initExpr2C (InitString s) = return $ doubleQuotes $ text s 
+initExpr2C (InitString [a]) = return . quotes $ text [a]
+initExpr2C (InitString s) = return $ strInit s
+initExpr2C (InitChar a) = return $ quotes $ text "\\x" <> text (showHex (read a) "")
 initExpr2C (InitReference i) = id2C IOLookup i
-initExpr2C _ = return $ text "<<expression>>"
+initExpr2C (InitRecord fields) = do
+    (fs :: [Doc]) <- mapM (\(Identifier a _, b) -> liftM (text "." <> text a <+> equals <+>) $ initExpr2C b) fields
+    return $ lbrace $+$ (nest 4 . vcat . punctuate comma $ fs) $+$ rbrace
+initExpr2C (InitArray [value]) = initExpr2C value
+initExpr2C (InitArray values) = liftM (braces . vcat . punctuate comma) $ mapM initExpr2C values
+initExpr2C r@(InitRange (Range i@(Identifier i' _))) = do
+    id2C IOLookup i
+    t <- gets lastType
+    case t of
+         BTEnum s -> return . int $ length s
+         BTInt -> case i' of
+                       "byte" -> return $ int 256
+                       _ -> error $ "InitRange identifier: " ++ i'
+         _ -> error $ "InitRange: " ++ show r
+initExpr2C (InitRange (RangeFromTo (InitNumber "0") r)) = initExpr2C $ BuiltInFunction "succ" [r]
+initExpr2C (InitRange (RangeFromTo (InitChar "0") (InitChar r))) = initExpr2C $ BuiltInFunction "succ" [InitNumber r]
+initExpr2C (InitRange a) = error $ show a --return $ text "<<range>>"
+initExpr2C (InitSet []) = return $ text "0"
+initExpr2C (InitSet a) = return $ text "<<set>>"
+initExpr2C (BuiltInFunction "low" [InitReference e]) = return $ 
+    case e of
+         (Identifier "LongInt" _) -> int (-2^31)
+         (Identifier "SmallInt" _) -> int (-2^15)
+         _ -> error $ "BuiltInFunction 'low': " ++ show e
+initExpr2C (BuiltInFunction "high" [e]) = do
+    initExpr2C e
+    t <- gets lastType
+    case t of
+         (BTArray i _ _) -> initExpr2C $ BuiltInFunction "pred" [InitRange i]
+         a -> error $ "BuiltInFunction 'high': " ++ show a
+initExpr2C (BuiltInFunction "succ" [BuiltInFunction "pred" [e]]) = initExpr2C e
+initExpr2C (BuiltInFunction "pred" [BuiltInFunction "succ" [e]]) = initExpr2C e
+initExpr2C (BuiltInFunction "succ" [e]) = liftM (<> text " + 1") $ initExpr2C e
+initExpr2C (BuiltInFunction "pred" [e]) = liftM (<> text " - 1") $ initExpr2C e
+initExpr2C b@(BuiltInFunction _ _) = error $ show b    
+initExpr2C a = error $ "initExpr2C: don't know how to render " ++ show a
 
 
-type2C :: TypeDecl -> State RenderState Doc
-type2C (SimpleType i) = id2C IOLookup i
+range2C :: InitExpression -> State RenderState [Doc]
+range2C (InitString [a]) = return [quotes $ text [a]]
+range2C (InitRange (Range i)) = liftM (flip (:) []) $ id2C IOLookup i
+range2C (InitRange (RangeFromTo (InitString [a]) (InitString [b]))) = return $ map (\i -> quotes $ text [i]) [a..b]
+range2C a = liftM (flip (:) []) $ initExpr2C a
+
+baseType2C :: String -> BaseType -> Doc
+baseType2C _ BTFloat = text "float"
+baseType2C _ BTBool = text "bool"
+baseType2C _ BTString = text "string255"
+baseType2C s a = error $ "baseType2C: " ++ show a ++ "\n" ++ s
+
+type2C :: TypeDecl -> State RenderState (Doc -> Doc)
+type2C (SimpleType i) = liftM (\i a -> i <+> a) $ id2C IOLookup i
 type2C t = do
     r <- type2C' t
     rt <- resolveType t
     modify (\st -> st{lastType = rt})
     return r
     where
-    type2C' VoidType = return $ text "void"
-    type2C' (String l) = return $ text $ "string" ++ show l
-    type2C' (PointerTo (SimpleType i)) = liftM (<> text "*") $ id2C IODeferred i
-    type2C' (PointerTo t) = liftM (<> text "*") $ type2C t
+    type2C' VoidType = return (text "void" <+>)
+    type2C' (String l) = return (text "string255" <+>)--return (text ("string" ++ show l) <+>)
+    type2C' (PointerTo (SimpleType i)) = liftM (\i a -> text "struct __" <> i <+> text "*" <+> a) $ id2C IODeferred i
+    type2C' (PointerTo t) = liftM (\t a -> t (parens $ text "*" <> a)) $ type2C t
     type2C' (RecordType tvs union) = do
-        t <- mapM (tvar2C False) tvs
-        return $ text "{" $+$ (nest 4 . vcat $ t) $+$ text "}"
-    type2C' (RangeType r) = return $ text "<<range type>>"
+        t <- withState' id $ mapM (tvar2C False) tvs
+        u <- unions
+        return $ \i -> text "struct __" <> i <+> lbrace $+$ nest 4 ((vcat . map (<> semi) . concat $ t) $$ u) $+$ rbrace <+> i
+        where
+            unions = case union of
+                     Nothing -> return empty
+                     Just a -> do
+                         structs <- mapM struct2C a
+                         return $ text "union" $+$ braces (nest 4 $ vcat structs) <> semi
+            struct2C tvs = do
+                t <- withState' id $ mapM (tvar2C False) tvs
+                return $ text "struct" $+$ braces (nest 4 (vcat . map (<> semi) . concat $ t)) <> semi
+    type2C' (RangeType r) = return (text "int" <+>)
     type2C' (Sequence ids) = do
-        mapM_ (id2C IOInsert) ids
-        return $ text "<<sequence type>>"
-    type2C' (ArrayDecl r t) = return $ text "<<array type>>"
-    type2C' (Set t) = return $ text "<<set>>"
-    type2C' (FunctionType returnType params) = return $ text "<<function>>"
-    type2C' (DeriveType _) = return $ text "<<type derived from constant literal>>"
+        is <- mapM (id2C IOInsert . setBaseType bt) ids
+        return (text "enum" <+> (braces . vcat . punctuate comma . map (\(a, b) -> a <+> equals <+> text "0x" <> text (showHex b "")) $ zip is [1..]) <+>)
+        where
+            bt = BTEnum $ map (\(Identifier i _) -> map toLower i) ids
+    type2C' (ArrayDecl Nothing t) = type2C (PointerTo t)
+    type2C' (ArrayDecl (Just r) t) = do
+        t' <- type2C t
+        r' <- initExpr2C (InitRange r)
+        return $ \i -> t' i <> brackets r'
+    type2C' (Set t) = return (text "<<set>>" <+>)
+    type2C' (FunctionType returnType params) = do
+        t <- type2C returnType
+        p <- withState' id $ functionParams2C params
+        return (\i -> t empty <+> i <> parens p)
+    type2C' (DeriveType (InitBinOp _ _ i)) = type2C' (DeriveType i)
+    type2C' (DeriveType (InitPrefixOp _ i)) = type2C' (DeriveType i)
+    type2C' (DeriveType (InitNumber _)) = return (text "int" <+>)
+    type2C' (DeriveType (InitHexNumber _)) = return (text "int" <+>)
+    type2C' (DeriveType (InitFloat _)) = return (text "float" <+>)
+    type2C' (DeriveType (BuiltInFunction {})) = return (text "int" <+>)
+    type2C' (DeriveType (InitString {})) = return (text "string255" <+>)
+    type2C' (DeriveType r@(InitReference {})) = do
+        initExpr2C r
+        t <- gets lastType
+        return (baseType2C (show r) t <+>)
+    type2C' (DeriveType a) = error $ "Can't derive type from " ++ show a
 
 phrase2C :: Phrase -> State RenderState Doc
 phrase2C (Phrases p) = do
     ps <- mapM phrase2C p
     return $ text "{" $+$ (nest 4 . vcat $ ps) $+$ text "}"
 phrase2C (ProcCall f@(FunCall {}) []) = liftM (<> semi) $ ref2C f
-phrase2C (ProcCall ref params) = do
+phrase2C (ProcCall ref []) = liftM (<> semi) $ ref2CF ref
+phrase2C (ProcCall ref params) = error $ "ProcCall"{-do
     r <- ref2C ref
     ps <- mapM expr2C params
-    return $ r <> parens (hsep . punctuate (char ',') $ ps) <> semi
+    return $ r <> parens (hsep . punctuate (char ',') $ ps) <> semi -}
 phrase2C (IfThenElse (expr) phrase1 mphrase2) = do
     e <- expr2C expr
     p1 <- (phrase2C . wrapPhrase) phrase1
@@ -367,10 +553,12 @@
     elsePart | isNothing mphrase2 = return $ empty
              | otherwise = liftM (text "else" $$) $ (phrase2C . wrapPhrase) (fromJust mphrase2)
 phrase2C (Assignment ref expr) = do
-    r <- ref2C ref 
-    e <- expr2C expr
-    return $
-        r <> text " = " <> e <> semi
+    r <- ref2C ref
+    t <- gets lastType
+    e <- case (t, expr) of
+         (BTFunction _, (Reference r')) -> ref2C r'
+         _ -> expr2C expr
+    return $ r <+> text "=" <+> e <> semi
 phrase2C (WhileCycle expr phrase) = do
     e <- expr2C expr
     p <- phrase2C $ wrapPhrase phrase
@@ -378,19 +566,29 @@
 phrase2C (SwitchCase expr cases mphrase) = do
     e <- expr2C expr
     cs <- mapM case2C cases
+    d <- dflt
     return $ 
-        text "switch" <> parens e <> text "of" $+$ (nest 4 . vcat) cs
+        text "switch" <> parens e $+$ braces (nest 4 . vcat $ cs ++ d)
     where
     case2C :: ([InitExpression], Phrase) -> State RenderState Doc
     case2C (e, p) = do
-        ie <- mapM initExpr2C e
+        ies <- mapM range2C e
         ph <- phrase2C p
         return $ 
-            text "case" <+> parens (hsep . punctuate (char ',') $ ie) <> char ':' <> nest 4 (ph $+$ text "break;")
-phrase2C (WithBlock ref p) = do
+             vcat (map (\i -> text "case" <+> i <> colon) . concat $ ies) <> nest 4 (ph $+$ text "break;")
+    dflt | isNothing mphrase = return []
+         | otherwise = do
+             ph <- mapM phrase2C $ fromJust mphrase
+             return [text "default:" <+> nest 4 (vcat ph)]
+                                         
+phrase2C wb@(WithBlock ref p) = do
     r <- ref2C ref 
-    ph <- phrase2C $ wrapPhrase p
-    return $ text "namespace" <> parens r $$ ph
+    t <- gets lastType
+    case t of
+        (BTRecord rs) -> withRecordNamespace (render r ++ ".") rs $ phrase2C $ wrapPhrase p
+        a -> do
+            ns <- gets currentScope
+            error $ "'with' block referencing non-record type " ++ show a ++ "\n" ++ show wb ++ "\nnamespace: " ++ show (take 100 ns)
 phrase2C (ForCycle i' e1' e2' p) = do
     i <- id2C IOLookup i'
     e1 <- expr2C e1'
@@ -403,52 +601,117 @@
 phrase2C (RepeatCycle e' p') = do
     e <- expr2C e'
     p <- phrase2C (Phrases p')
-    return $ text "do" <+> p <+> text "while" <> parens (text "!" <> parens e)
+    return $ text "do" <+> p <+> text "while" <> parens (text "!" <> parens e) <> semi
 phrase2C NOP = return $ text ";"
 
+phrase2C (BuiltInFunctionCall [] (SimpleReference (Identifier "exit" BTUnknown))) = return $ text "return" <> semi
+phrase2C (BuiltInFunctionCall [e] (SimpleReference (Identifier "exit" BTUnknown))) = liftM (\e -> text "return" <> e <> semi) $ expr2C e
+phrase2C (BuiltInFunctionCall [e] (SimpleReference (Identifier "dec" BTUnknown))) = liftM (\e -> text "--" <> e <> semi) $ expr2C e
+phrase2C (BuiltInFunctionCall [e1, e2] (SimpleReference (Identifier "dec" BTUnknown))) = liftM2 (\a b -> a <> text " -= " <> b <> semi) (expr2C e1) (expr2C e2)
+phrase2C (BuiltInFunctionCall [e] (SimpleReference (Identifier "inc" BTUnknown))) = liftM (\e -> text "++" <> e <> semi) $ expr2C e
+phrase2C (BuiltInFunctionCall [e1, e2] (SimpleReference (Identifier "inc" BTUnknown))) = liftM2 (\a b -> a <+> text "+=" <+> b <> semi) (expr2C e1) (expr2C e2)
+phrase2C a = error $ "phrase2C: " ++ show a
 
 wrapPhrase p@(Phrases _) = p
 wrapPhrase p = Phrases [p]
 
-
 expr2C :: Expression -> State RenderState Doc
 expr2C (Expression s) = return $ text s
 expr2C (BinOp op expr1 expr2) = do
     e1 <- expr2C expr1
+    t1 <- gets lastType
     e2 <- expr2C expr2
-    o <- op2C op
-    return $ parens $ e1 <+> o <+> e2
+    t2 <- gets lastType
+    case (op2C op, t1, t2) of
+        ("+", BTString, BTString) -> expr2C $ BuiltInFunCall [expr1, expr2] (SimpleReference $ Identifier "_strconcat" (BTFunction BTString))
+        ("+", BTString, BTChar) -> expr2C $ BuiltInFunCall [expr1, expr2] (SimpleReference $ Identifier "_strappend" (BTFunction BTString))
+        ("+", BTChar, BTString) -> expr2C $ BuiltInFunCall [expr1, expr2] (SimpleReference $ Identifier "_strprepend" (BTFunction BTString))
+        ("==", BTString, _) -> expr2C $ BuiltInFunCall [expr1, expr2] (SimpleReference $ Identifier "_strcompare" (BTFunction BTBool))
+        ("!=", BTString, _) -> expr2C $ BuiltInFunCall [expr1, expr2] (SimpleReference $ Identifier "_strncompare" (BTFunction BTBool))
+        ("&", BTBool, _) -> return $ parens e1 <+> text "&&" <+> parens e2
+        ("|", BTBool, _) -> return $ parens e1 <+> text "||" <+> parens e2
+        (o, _, _) | o `elem` boolOps -> do
+                        modify(\s -> s{lastType = BTBool})
+                        return $ parens e1 <+> text o <+> parens e2
+                  | otherwise -> return $ parens e1 <+> text o <+> parens e2
+    where
+        boolOps = ["==", "!=", "<", ">", "<=", ">="]
 expr2C (NumberLiteral s) = return $ text s
 expr2C (FloatLiteral s) = return $ text s
 expr2C (HexNumber s) = return $ text "0x" <> (text . map toLower $ s)
-expr2C (StringLiteral s) = return $ doubleQuotes $ text s 
-expr2C (Reference ref) = ref2C ref
-expr2C (PrefixOp op expr) = liftM2 (<+>) (op2C op) (expr2C expr)
+expr2C (StringLiteral [a]) = do
+    modify(\s -> s{lastType = BTChar})
+    return . quotes $ text [a]
+expr2C (StringLiteral s) = addStringConst s
+expr2C (Reference ref) = ref2CF ref
+expr2C (PrefixOp op expr) = liftM (text (op2C op) <>) (expr2C expr)
 expr2C Null = return $ text "NULL"
+expr2C (CharCode a) = do
+    modify(\s -> s{lastType = BTChar})
+    return $ quotes $ text "\\x" <> text (showHex (read a) "")
+expr2C (HexCharCode a) = return $ quotes $ text "\\x" <> text (map toLower a)
+expr2C (SetExpression ids) = mapM (id2C IOLookup) ids >>= return . parens . hcat . punctuate (text " | ")
+
+expr2C (BuiltInFunCall [e] (SimpleReference (Identifier "ord" _))) = liftM parens $ expr2C e
+expr2C (BuiltInFunCall [e] (SimpleReference (Identifier "succ" _))) = liftM (<> text " + 1") $ expr2C e
+expr2C (BuiltInFunCall [e] (SimpleReference (Identifier "pred" _))) = liftM (<> text " - 1") $ expr2C e
 expr2C (BuiltInFunCall params ref) = do
     r <- ref2C ref 
+    t <- gets lastType
     ps <- mapM expr2C params
+    case t of
+        BTFunction t' -> do
+            modify (\s -> s{lastType = t'})
+        _ -> error $ "BuiltInFunCall lastType: " ++ show t
     return $ 
         r <> parens (hsep . punctuate (char ',') $ ps)
-expr2C _ = return $ text "<<expression>>"
+expr2C a = error $ "Don't know how to render " ++ show a
 
+ref2CF :: Reference -> State RenderState Doc
+ref2CF (SimpleReference name) = do
+    i <- id2C IOLookup name
+    t <- gets lastType
+    case t of
+         BTFunction _ -> return $ i <> parens empty
+         _ -> return $ i
+ref2CF r = ref2C r
 
 ref2C :: Reference -> State RenderState Doc
-ref2C ae@(ArrayElement exprs ref) = do
-    es <- mapM expr2C exprs
+-- rewrite into proper form
+ref2C (RecordField ref1 (ArrayElement exprs ref2)) = ref2C $ ArrayElement exprs (RecordField ref1 ref2)
+ref2C (RecordField ref1 (Dereference ref2)) = ref2C $ Dereference (RecordField ref1 ref2)
+ref2C (RecordField ref1 (RecordField ref2 ref3)) = ref2C $ RecordField (RecordField ref1 ref2) ref3
+ref2C (RecordField ref1 (FunCall params ref2)) = ref2C $ FunCall params (RecordField ref1 ref2)
+ref2C (ArrayElement (a:b:xs) ref) = ref2C $ ArrayElement (b:xs) (ArrayElement [a] ref)
+-- conversion routines
+ref2C ae@(ArrayElement [expr] ref) = do
+    e <- expr2C expr
     r <- ref2C ref 
     t <- gets lastType
     ns <- gets currentScope
     case t of
-         (BTArray _ (BTArray _ t')) -> modify (\st -> st{lastType = t'})
-         (BTArray _ t') -> modify (\st -> st{lastType = t'})
+         (BTArray _ _ t') -> modify (\st -> st{lastType = t'})
+         (BTFunctionReturn _ (BTArray _ _ t')) -> modify (\st -> st{lastType = t'})
+         (BTFunctionReturn _ (BTString)) -> modify (\st -> st{lastType = BTChar})
          (BTString) -> modify (\st -> st{lastType = BTChar})
+         (BTPointerTo t) -> do
+                t'' <- fromPointer (show t) =<< gets lastType
+                case t'' of
+                     BTChar -> modify (\st -> st{lastType = BTChar})
+                     a -> error $ "Getting element of " ++ show a ++ "\nReference: " ++ show ae ++ "\n" ++ show (take 100 ns)
          a -> error $ "Getting element of " ++ show a ++ "\nReference: " ++ show ae ++ "\n" ++ show (take 100 ns)
-    return $ r <> (brackets . hcat) (punctuate comma es)
+    case t of
+         BTString ->  return $ r <> text ".s" <> brackets e
+         _ -> return $ r <> brackets e
 ref2C (SimpleReference name) = id2C IOLookup name
-ref2C (RecordField (Dereference ref1) ref2) = do
+ref2C rf@(RecordField (Dereference ref1) ref2) = do
     r1 <- ref2C ref1 
-    r2 <- ref2C ref2
+    t <- fromPointer (show ref1) =<< gets lastType
+    ns <- gets currentScope
+    r2 <- case t of
+        BTRecord rs -> withRecordNamespace "" rs $ ref2C ref2
+        BTUnit -> withLastIdNamespace $ ref2C ref2
+        a -> error $ "dereferencing from " ++ show a ++ "\n" ++ show rf ++ "\n" ++ show (take 100 ns)
     return $ 
         r1 <> text "->" <> r2
 ref2C rf@(RecordField ref1 ref2) = do
@@ -456,48 +719,56 @@
     t <- gets lastType
     ns <- gets currentScope
     r2 <- case t of
-        BTRecord rs -> withRecordNamespace rs $ ref2C ref2
-        BTUnit -> withLastIdNamespace $ ref2C ref2
+        BTFunctionReturn s (BTRecord rs) -> withRecordNamespace "" rs $ ref2C ref2       
+        BTRecord rs -> withRecordNamespace "" rs $ ref2C ref2
+        BTUnit -> withLastIdNamespace $ ref2C ref2        
         a -> error $ "dereferencing from " ++ show a ++ "\n" ++ show rf ++ "\n" ++ show (take 100 ns)
     return $ 
         r1 <> text "." <> r2
-ref2C (Dereference ref) = do
+ref2C d@(Dereference ref) = do
     r <- ref2C ref
-    t <- fromPointer =<< gets lastType
+    t <- fromPointer (show d) =<< gets lastType
     modify (\st -> st{lastType = t})
-    return $ (parens $ text "*") <> r
-ref2C (FunCall params ref) = do
-    ps <- liftM (parens . hsep . punctuate (char ',')) $ mapM expr2C params
+    return $ (parens $ text "*" <> r)
+ref2C f@(FunCall params ref) = do
     r <- ref2C ref
     t <- gets lastType
     case t of
-        BTFunction t -> do
-            modify (\s -> s{lastType = t})
+        BTFunction t' -> do
+            ps <- liftM (parens . hsep . punctuate (char ',')) $ mapM expr2C params
+            modify (\s -> s{lastType = t'})
             return $ r <> ps
-        _ -> return $ parens r <> ps
+        BTFunctionReturn r t' -> do
+            ps <- liftM (parens . hsep . punctuate (char ',')) $ mapM expr2C params
+            modify (\s -> s{lastType = t'})
+            return $ text r <> ps
+        _ -> case (ref, params) of
+                  (SimpleReference i, [p]) -> ref2C $ TypeCast i p
+                  _ -> error $ "ref2C FunCall erroneous type cast detected: " ++ show f ++ "\nType detected: " ++ show t
         
 ref2C (Address ref) = do
     r <- ref2C ref
     return $ text "&" <> parens r
-ref2C (TypeCast t' expr) = do
-    t <- id2C IOLookup t'
-    e <- expr2C expr
-    return $ parens t <> e
+ref2C (TypeCast t'@(Identifier i _) expr) = do
+    case map toLower i of
+        "pchar" -> ref2C $ FunCall [expr] (SimpleReference (Identifier "_pchar" $ BTPointerTo BTChar))
+        a -> do
+            e <- expr2C expr
+            t <- id2C IOLookup t'    
+            return $ parens t <> e
 ref2C (RefExpression expr) = expr2C expr
 
 
-op2C :: String -> State RenderState Doc
-op2C "or" = return $ text "|"
-op2C "and" = return $ text "&"
-op2C "not" = return $ text "!"
-op2C "xor" = return $ text "^"
-op2C "div" = return $ text "/"
-op2C "mod" = return $ text "%"
-op2C "shl" = return $ text "<<"
-op2C "shr" = return $ text ">>"
-op2C "<>" = return $ text "!="
-op2C "=" = return $ text "=="
-op2C a = return $ text a
+op2C :: String -> String
+op2C "or" = "|"
+op2C "and" = "&"
+op2C "not" = "!"
+op2C "xor" = "^"
+op2C "div" = "/"
+op2C "mod" = "%"
+op2C "shl" = "<<"
+op2C "shr" = ">>"
+op2C "<>" = "!="
+op2C "=" = "=="
+op2C a = a
 
-maybeVoid "" = "void"
-maybeVoid a = a